Created
February 13, 2014 04:45
-
-
Save atsuya046/8969861 to your computer and use it in GitHub Desktop.
GoF design pattern - Memento
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
# -*- coding: utf-8 -*- | |
"""http://code.activestate.com/recipes/413838-memento-closure/""" | |
import copy | |
def Memento(obj, deep=False): | |
state = (copy.copy, copy.deepcopy)[bool(deep)](obj.__dict__) | |
def Restore(): | |
obj.__dict__.clear() | |
obj.__dict__.update(state) | |
return Restore | |
class Transaction: | |
"""A transaction guard. This is really just | |
syntactic suggar arount a memento closure. | |
""" | |
deep = False | |
def __init__(self, *targets): | |
self.targets = targets | |
self.Commit() | |
def Commit(self): | |
self.states = [Memento(target, self.deep) for target in self.targets] | |
def Rollback(self): | |
for st in self.states: | |
st() | |
class transactional(object): | |
"""Adds transactional semantics to methods. Methods decorated with | |
transactional will rollback to entry state upon exceptions. | |
""" | |
def __init__(self, method): | |
self.method = method | |
def __get__(self, obj, T): | |
def transaction(*args, **kwargs): | |
state = Memento(obj) | |
try: | |
return self.method(obj, *args, **kwargs) | |
except: | |
state() | |
raise | |
return transaction | |
class NumObj(object): | |
def __init__(self, value): | |
self.value = value | |
def __repr__(self): | |
return '<%s: %r>' % (self.__class__.__name__, self.value) | |
def Increment(self): | |
self.value += 1 | |
@transactional | |
def DoStuff(self): | |
self.value = '1111' | |
self.Increment() | |
if __name__ == '__main__': | |
n = NumObj(-1) | |
print(n) | |
t = Transaction(n) | |
try: | |
for i in range(3): | |
n.Increment() | |
print(n) | |
t.Commit() | |
print('-- commited') | |
for i in range(3): | |
n.Increment() | |
print(n) | |
n.value += 'x' # will fail | |
print(n) | |
except: | |
t.Rollback() | |
print('-- rolled back') | |
print(n) | |
print('--now doing stuff ...') | |
try: | |
n.DoStuff() | |
except: | |
print('-> doing stuff failed!') | |
import sys, traceback | |
traceback.print_exc(file=sys.stdout) | |
pass | |
print(n) |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment