@@ -32,9 +32,8 @@ class Transaction(Batch):
3232
3333 >>> datastore.set_defaults()
3434
35- >>> with Transaction() as xact:
36- ... datastore.put(entity1)
37- ... datastore.put(entity2)
35+ >>> with Transaction():
36+ ... datastore.put([entity1, entity2])
3837
3938 Because it derives from :class:`Batch`, :class`Transaction` also provides
4039 :meth:`put` and :meth:`delete` methods::
@@ -46,7 +45,7 @@ class Transaction(Batch):
4645 By default, the transaction is rolled back if the transaction block
4746 exits with an error::
4847
49- >>> with Transaction() as txn :
48+ >>> with Transaction():
5049 ... do_some_work()
5150 ... raise SomeException() # rolls back
5251
@@ -71,16 +70,34 @@ class Transaction(Batch):
7170 ... entity = Entity(key=Key('Thing'))
7271 ... datastore.put([entity])
7372 ... assert entity.key.is_partial # There is no ID on this key.
73+ ...
7474 >>> assert not entity.key.is_partial # There *is* an ID.
7575
76+ After completion, you can determine if a commit succeeded or failed.
77+ For example, trying to delete a key that doesn't exist::
78+
79+ >>> with Transaction() as xact:
80+ ... xact.delete(key)
81+ ...
82+ >>> xact.succeeded
83+ False
84+
85+ or successfully storing two entities:
86+
87+ >>> with Transaction() as xact:
88+ ... datastore.put([entity1, entity2])
89+ ...
90+ >>> xact.succeeded
91+ True
92+
7693 If you don't want to use the context manager you can initialize a
7794 transaction manually::
7895
7996 >>> transaction = Transaction()
8097 >>> transaction.begin()
8198
8299 >>> entity = Entity(key=Key('Thing'))
83- >>> transaction.put([ entity] )
100+ >>> transaction.put(entity)
84101
85102 >>> if error:
86103 ... transaction.rollback()
@@ -97,9 +114,17 @@ class Transaction(Batch):
97114 are not set.
98115 """
99116
117+ _IN_PROGRESS = 1
118+ """Enum value for _IN_PROGRESS status of transaction."""
119+
120+ _FINISHED = 2
121+ """Enum value for _FINISHED status of transaction."""
122+
100123 def __init__ (self , dataset_id = None , connection = None ):
101124 super (Transaction , self ).__init__ (dataset_id , connection )
102125 self ._id = None
126+ self ._status = None
127+ self ._commit_success = False
103128
104129 @property
105130 def id (self ):
@@ -123,13 +148,32 @@ def current():
123148 if isinstance (top , Transaction ):
124149 return top
125150
151+ @property
152+ def succeeded (self ):
153+ """Determines if transaction has succeeded or failed.
154+
155+ :rtype: boolean
156+ :returns: Boolean indicating successful commit.
157+ :raises: :class:`ValueError` if the transaction is still in progress.
158+ """
159+ if self ._status != self ._FINISHED :
160+ raise ValueError ('Transaction not yet finished. '
161+ 'Success not known.' )
162+
163+ return self ._commit_success
164+
126165 def begin (self ):
127166 """Begins a transaction.
128167
129168 This method is called automatically when entering a with
130169 statement, however it can be called explicitly if you don't want
131170 to use a context manager.
171+
172+ :raises: :class:`ValueError` if the transaction has already begun.
132173 """
174+ if self ._status is not None :
175+ raise ValueError ('Transaction already started previously.' )
176+ self ._status = self ._IN_PROGRESS
133177 self ._id = self .connection .begin_transaction (self ._dataset_id )
134178
135179 def rollback (self ):
@@ -140,8 +184,12 @@ def rollback(self):
140184 - Sets the current connection's transaction reference to None.
141185 - Sets the current transaction's ID to None.
142186 """
143- self .connection .rollback (self ._dataset_id , self ._id )
144- self ._id = None
187+ try :
188+ self .connection .rollback (self ._dataset_id , self ._id )
189+ finally :
190+ self ._status = self ._FINISHED
191+ # Clear our own ID in case this gets accidentally reused.
192+ self ._id = None
145193
146194 def commit (self ):
147195 """Commits the transaction.
@@ -154,7 +202,10 @@ def commit(self):
154202
155203 - Sets the current transaction's ID to None.
156204 """
157- super (Transaction , self ).commit ()
158-
159- # Clear our own ID in case this gets accidentally reused.
160- self ._id = None
205+ try :
206+ super (Transaction , self ).commit ()
207+ finally :
208+ self ._commit_success = True
209+ self ._status = self ._FINISHED
210+ # Clear our own ID in case this gets accidentally reused.
211+ self ._id = None
0 commit comments