@@ -153,48 +153,72 @@ def dataset(self, *args, **kwargs):
153153 kwargs ['connection' ] = self
154154 return Dataset (* args , ** kwargs )
155155
156- def begin_transaction (self , dataset_id , serializable = False ):
157- """Begin a transaction.
156+ #
157+ # Protobuf RPCs for DatastoreService
158+ #
159+ def lookup (self , dataset_id , key_pbs ):
160+ """Lookup keys from a dataset in the Cloud Datastore.
158161
159- :type dataset_id: string
160- :param dataset_id: The dataset over which to execute the transaction.
161- """
162+ This method deals only with protobufs
163+ (:class:`gcloud.datastore.datastore_v1_pb2.Key`
164+ and
165+ :class:`gcloud.datastore.datastore_v1_pb2.Entity`)
166+ and is used under the hood for methods like
167+ :func:`gcloud.datastore.dataset.Dataset.get_entity`:
162168
163- if self .transaction ():
164- raise ValueError ('Cannot start a transaction with another already '
165- 'in progress.' )
169+ >>> from gcloud import datastore
170+ >>> from gcloud.datastore.key import Key
171+ >>> connection = datastore.get_connection(email, key_path)
172+ >>> dataset = connection.dataset('dataset-id')
173+ >>> key = Key(dataset=dataset).kind('MyKind').id(1234)
166174
167- request = datastore_pb . BeginTransactionRequest ()
175+ Using the :class:`gcloud.datastore.dataset.Dataset` helper:
168176
169- if serializable :
170- request .isolation_level = (
171- datastore_pb .BeginTransactionRequest .SERIALIZABLE )
172- else :
173- request .isolation_level = (
174- datastore_pb .BeginTransactionRequest .SNAPSHOT )
177+ >>> dataset.get_entity(key)
178+ <Entity object>
175179
176- response = self ._rpc (dataset_id , 'beginTransaction' , request ,
177- datastore_pb .BeginTransactionResponse )
180+ Using the ``connection`` class directly:
178181
179- return response .transaction
182+ >>> connection.lookup('dataset-id', key.to_protobuf())
183+ <Entity protobuf>
180184
181- def rollback_transaction ( self , dataset_id ):
182- """Rollback the connection's existing transaction .
185+ :type dataset_id: string
186+ :param dataset_id: The dataset to look up the keys .
183187
184- Raises a ``ValueError``
185- if the connection isn't currently in a transaction.
188+ :type key_pbs: list of :class:`gcloud.datastore.datastore_v1_pb2.Key`
189+ (or a single Key)
190+ :param key_pbs: The key (or keys) to retrieve from the datastore.
186191
187- :type dataset_id: string
188- :param dataset_id: The dataset to which the transaction belongs.
192+ :rtype: list of :class:`gcloud.datastore.datastore_v1_pb2.Entity`
193+ (or a single Entity)
194+ :returns: The entities corresponding to the keys provided.
195+ If a single key was provided and no results matched,
196+ this will return None.
197+ If multiple keys were provided and no results matched,
198+ this will return an empty list.
189199 """
190- if not self .transaction () or not self .transaction ().id ():
191- raise ValueError ('No transaction to rollback.' )
200+ lookup_request = datastore_pb .LookupRequest ()
192201
193- request = datastore_pb .RollbackRequest ()
194- request .transaction = self .transaction ().id ()
195- # Nothing to do with this response, so just execute the method.
196- self ._rpc (dataset_id , 'rollback' , request ,
197- datastore_pb .RollbackResponse )
202+ single_key = isinstance (key_pbs , datastore_pb .Key )
203+
204+ if single_key :
205+ key_pbs = [key_pbs ]
206+
207+ for key_pb in key_pbs :
208+ lookup_request .key .add ().CopyFrom (key_pb )
209+
210+ lookup_response = self ._rpc (dataset_id , 'lookup' , lookup_request ,
211+ datastore_pb .LookupResponse )
212+
213+ results = [result .entity for result in lookup_response .found ]
214+
215+ if single_key :
216+ if results :
217+ return results [0 ]
218+ else :
219+ return None
220+
221+ return results
198222
199223 def run_query (self , dataset_id , query_pb , namespace = None ):
200224 """Run a query on the Cloud Datastore.
@@ -250,69 +274,30 @@ def run_query(self, dataset_id, query_pb, namespace=None):
250274 response .batch .skipped_results ,
251275 )
252276
253- def lookup (self , dataset_id , key_pbs ):
254- """Lookup keys from a dataset in the Cloud Datastore.
255-
256- This method deals only with protobufs
257- (:class:`gcloud.datastore.datastore_v1_pb2.Key`
258- and
259- :class:`gcloud.datastore.datastore_v1_pb2.Entity`)
260- and is used under the hood for methods like
261- :func:`gcloud.datastore.dataset.Dataset.get_entity`:
262-
263- >>> from gcloud import datastore
264- >>> from gcloud.datastore.key import Key
265- >>> connection = datastore.get_connection(email, key_path)
266- >>> dataset = connection.dataset('dataset-id')
267- >>> key = Key(dataset=dataset).kind('MyKind').id(1234)
268-
269- Using the :class:`gcloud.datastore.dataset.Dataset` helper:
270-
271- >>> dataset.get_entity(key)
272- <Entity object>
273-
274- Using the ``connection`` class directly:
275-
276- >>> connection.lookup('dataset-id', key.to_protobuf())
277- <Entity protobuf>
277+ def begin_transaction (self , dataset_id , serializable = False ):
278+ """Begin a transaction.
278279
279280 :type dataset_id: string
280- :param dataset_id: The dataset to look up the keys.
281-
282- :type key_pbs: list of :class:`gcloud.datastore.datastore_v1_pb2.Key`
283- (or a single Key)
284- :param key_pbs: The key (or keys) to retrieve from the datastore.
285-
286- :rtype: list of :class:`gcloud.datastore.datastore_v1_pb2.Entity`
287- (or a single Entity)
288- :returns: The entities corresponding to the keys provided.
289- If a single key was provided and no results matched,
290- this will return None.
291- If multiple keys were provided and no results matched,
292- this will return an empty list.
281+ :param dataset_id: The dataset over which to execute the transaction.
293282 """
294- lookup_request = datastore_pb .LookupRequest ()
295-
296- single_key = isinstance (key_pbs , datastore_pb .Key )
297-
298- if single_key :
299- key_pbs = [key_pbs ]
300283
301- for key_pb in key_pbs :
302- lookup_request .key .add ().CopyFrom (key_pb )
284+ if self .transaction ():
285+ raise ValueError ('Cannot start a transaction with another already '
286+ 'in progress.' )
303287
304- lookup_response = self ._rpc (dataset_id , 'lookup' , lookup_request ,
305- datastore_pb .LookupResponse )
288+ request = datastore_pb .BeginTransactionRequest ()
306289
307- results = [result .entity for result in lookup_response .found ]
290+ if serializable :
291+ request .isolation_level = (
292+ datastore_pb .BeginTransactionRequest .SERIALIZABLE )
293+ else :
294+ request .isolation_level = (
295+ datastore_pb .BeginTransactionRequest .SNAPSHOT )
308296
309- if single_key :
310- if results :
311- return results [0 ]
312- else :
313- return None
297+ response = self ._rpc (dataset_id , 'beginTransaction' , request ,
298+ datastore_pb .BeginTransactionResponse )
314299
315- return results
300+ return response . transaction
316301
317302 def commit (self , dataset_id , mutation_pb ):
318303 """Commit dataset mutations in context of current transation (if any).
@@ -339,6 +324,27 @@ def commit(self, dataset_id, mutation_pb):
339324 datastore_pb .CommitResponse )
340325 return response .mutation_result
341326
327+ def rollback_transaction (self , dataset_id ):
328+ """Rollback the connection's existing transaction.
329+
330+ Raises a ``ValueError``
331+ if the connection isn't currently in a transaction.
332+
333+ :type dataset_id: string
334+ :param dataset_id: The dataset to which the transaction belongs.
335+ """
336+ if not self .transaction () or not self .transaction ().id ():
337+ raise ValueError ('No transaction to rollback.' )
338+
339+ request = datastore_pb .RollbackRequest ()
340+ request .transaction = self .transaction ().id ()
341+ # Nothing to do with this response, so just execute the method.
342+ self ._rpc (dataset_id , 'rollback' , request ,
343+ datastore_pb .RollbackResponse )
344+
345+ #
346+ # Entity-related helper methods.
347+ #
342348 def save_entity (self , dataset_id , key_pb , properties ):
343349 """Save an entity to the Cloud Datastore with the provided properties.
344350
0 commit comments