Skip to content

Commit 25501bb

Browse files
committed
Merge branch 'master' of https://github.com/kmonsoor/python-patterns into kmonsoor-master
2 parents 1b898a5 + 3615512 commit 25501bb

File tree

1 file changed

+57
-51
lines changed

1 file changed

+57
-51
lines changed

memento.py

Lines changed: 57 additions & 51 deletions
Original file line numberDiff line numberDiff line change
@@ -3,110 +3,114 @@
33

44
"""http://code.activestate.com/recipes/413838-memento-closure/"""
55

6-
import copy
6+
from copy import copy, deepcopy
77

88

9-
def Memento(obj, deep=False):
10-
state = (copy.copy, copy.deepcopy)[bool(deep)](obj.__dict__)
9+
def memento(obj, deep=False):
10+
state = copy(obj.__dict__) if deep else deepcopy(obj.__dict__)
1111

12-
def Restore():
12+
def restore():
1313
obj.__dict__.clear()
1414
obj.__dict__.update(state)
15-
return Restore
1615

16+
return restore
1717

18-
class Transaction:
1918

20-
"""A transaction guard. This is really just
21-
syntactic suggar arount a memento closure.
22-
"""
19+
class Transaction:
20+
"""A transaction guard.
21+
This is, in fact, just syntactic sugar around a memento closure.
22+
"""
2323
deep = False
24+
states = []
2425

2526
def __init__(self, *targets):
2627
self.targets = targets
27-
self.Commit()
28+
self.commit()
2829

29-
def Commit(self):
30-
self.states = [Memento(target, self.deep) for target in self.targets]
30+
def commit(self):
31+
self.states = [memento(target, self.deep) for target in self.targets]
3132

32-
def Rollback(self):
33-
for st in self.states:
34-
st()
33+
def rollback(self):
34+
for a_state in self.states:
35+
a_state()
3536

3637

37-
class transactional(object):
38-
38+
class Transactional(object):
3939
"""Adds transactional semantics to methods. Methods decorated with
40-
@transactional will rollback to entry state upon exceptions.
40+
@Transactional will rollback to entry-state upon exceptions.
4141
"""
4242

4343
def __init__(self, method):
4444
self.method = method
4545

4646
def __get__(self, obj, T):
4747
def transaction(*args, **kwargs):
48-
state = Memento(obj)
48+
state = memento(obj)
4949
try:
5050
return self.method(obj, *args, **kwargs)
51-
except:
51+
except Exception as e:
5252
state()
53-
raise
53+
raise e
54+
5455
return transaction
5556

5657

5758
class NumObj(object):
58-
5959
def __init__(self, value):
6060
self.value = value
6161

6262
def __repr__(self):
6363
return '<%s: %r>' % (self.__class__.__name__, self.value)
6464

65-
def Increment(self):
65+
def increment(self):
6666
self.value += 1
6767

68-
@transactional
69-
def DoStuff(self):
68+
@Transactional
69+
def do_stuff(self):
7070
self.value = '1111' # <- invalid value
71-
self.Increment() # <- will fail and rollback
71+
self.increment() # <- will fail and rollback
7272

7373

7474
if __name__ == '__main__':
75-
n = NumObj(-1)
76-
print(n)
77-
t = Transaction(n)
75+
num_obj = NumObj(-1)
76+
print(num_obj)
77+
78+
a_transaction = Transaction(num_obj)
7879
try:
7980
for i in range(3):
80-
n.Increment()
81-
print(n)
82-
t.Commit()
83-
print('-- commited')
81+
num_obj.increment()
82+
print(num_obj)
83+
a_transaction.commit()
84+
print('-- committed')
85+
8486
for i in range(3):
85-
n.Increment()
86-
print(n)
87-
n.value += 'x' # will fail
88-
print(n)
89-
except:
90-
t.Rollback()
87+
num_obj.increment()
88+
print(num_obj)
89+
num_obj.value += 'x' # will fail
90+
print(num_obj)
91+
except Exception as e:
92+
a_transaction.rollback()
9193
print('-- rolled back')
92-
print(n)
94+
print(num_obj)
95+
9396
print('-- now doing stuff ...')
9497
try:
95-
n.DoStuff()
96-
except:
98+
num_obj.do_stuff()
99+
except Exception as e:
97100
print('-> doing stuff failed!')
98101
import sys
99102
import traceback
103+
100104
traceback.print_exc(file=sys.stdout)
101-
pass
102-
print(n)
105+
print(num_obj)
106+
103107

104108
### OUTPUT ###
105109
# <NumObj: -1>
106110
# <NumObj: 0>
107111
# <NumObj: 1>
108112
# <NumObj: 2>
109-
# -- commited
113+
# -- committed
110114
# <NumObj: 3>
111115
# <NumObj: 4>
112116
# <NumObj: 5>
@@ -115,13 +119,15 @@ def DoStuff(self):
115119
# -- now doing stuff ...
116120
# -> doing stuff failed!
117121
# Traceback (most recent call last):
118-
# File "memento.py", line 91, in <module>
119-
# n.DoStuff()
120-
# File "memento.py", line 47, in transaction
122+
# File "memento.py", line 97, in <module>
123+
# num_obj.do_stuff()
124+
# File "memento.py", line 52, in transaction
125+
# raise e
126+
# File "memento.py", line 49, in transaction
121127
# return self.method(obj, *args, **kwargs)
122-
# File "memento.py", line 67, in DoStuff
123-
# self.Increment() # <- will fail and rollback
124-
# File "memento.py", line 62, in Increment
128+
# File "memento.py", line 70, in do_stuff
129+
# self.increment() # <- will fail and rollback
130+
# File "memento.py", line 65, in increment
125131
# self.value += 1
126132
# TypeError: Can't convert 'int' object to str implicitly
127133
# <NumObj: 2>

0 commit comments

Comments
 (0)