2525import pytz
2626import six
2727
28+ from gcloud .datastore import datastore_v1_pb2 as datastore_pb
2829from gcloud .datastore .entity import Entity
2930from gcloud .datastore .key import Key
3031
@@ -65,19 +66,15 @@ def key_from_protobuf(pb):
6566 :rtype: :class:`gcloud.datastore.key.Key`
6667 :returns: a new `Key` instance
6768 """
68- path = []
69+ path_args = []
6970 for element in pb .path_element :
70- element_dict = {'kind' : element .kind }
71-
71+ path_args .append (element .kind )
7272 if element .HasField ('id' ):
73- element_dict ['id' ] = element .id
74-
73+ path_args .append (element .id )
7574 # This is safe: we expect proto objects returned will only have
7675 # one of `name` or `id` set.
7776 if element .HasField ('name' ):
78- element_dict ['name' ] = element .name
79-
80- path .append (element_dict )
77+ path_args .append (element .name )
8178
8279 dataset_id = None
8380 if pb .partition_id .HasField ('dataset_id' ):
@@ -86,7 +83,7 @@ def key_from_protobuf(pb):
8683 if pb .partition_id .HasField ('namespace' ):
8784 namespace = pb .partition_id .namespace
8885
89- return Key (path , namespace , dataset_id )
86+ return Key (* path_args , namespace = namespace , dataset_id = dataset_id )
9087
9188
9289def _pb_attr_value (val ):
@@ -263,3 +260,44 @@ def _set_protobuf_value(value_pb, val):
263260 _set_protobuf_value (i_pb , item )
264261 else : # scalar, just assign
265262 setattr (value_pb , attr , val )
263+
264+
265+ def _prepare_key_for_request (key_pb ):
266+ """Add protobuf keys to a request object.
267+
268+ :type key_pb: :class:`gcloud.datastore.datastore_v1_pb2.Key`
269+ :param key_pb: A key to be added to a request.
270+
271+ :rtype: :class:`gcloud.datastore.datastore_v1_pb2.Key`
272+ :returns: A key which will be added to a request. It will be the
273+ original if nothing needs to be changed.
274+ """
275+ if key_pb .partition_id .HasField ('dataset_id' ):
276+ # We remove the dataset_id from the protobuf. This is because
277+ # the backend fails a request if the key contains un-prefixed
278+ # dataset ID. The backend fails because requests to
279+ # /datastore/.../datasets/foo/...
280+ # and
281+ # /datastore/.../datasets/s~foo/...
282+ # both go to the datastore given by 's~foo'. So if the key
283+ # protobuf in the request body has dataset_id='foo', the
284+ # backend will reject since 'foo' != 's~foo'.
285+ new_key_pb = datastore_pb .Key ()
286+ new_key_pb .CopyFrom (key_pb )
287+ new_key_pb .partition_id .ClearField ('dataset_id' )
288+ key_pb = new_key_pb
289+ return key_pb
290+
291+
292+ def _add_keys_to_request (request_field_pb , key_pbs ):
293+ """Add protobuf keys to a request object.
294+
295+ :type request_field_pb: `RepeatedCompositeFieldContainer`
296+ :param request_field_pb: A repeated proto field that contains keys.
297+
298+ :type key_pbs: list of :class:`gcloud.datastore.datastore_v1_pb2.Key`
299+ :param key_pbs: The keys to add to a request.
300+ """
301+ for key_pb in key_pbs :
302+ key_pb = _prepare_key_for_request (key_pb )
303+ request_field_pb .add ().CopyFrom (key_pb )
0 commit comments