From 800e3caabcd9c85b0b2ae9299217ea31d0309545 Mon Sep 17 00:00:00 2001 From: Antoine van Gelder Date: Sun, 28 Oct 2007 09:45:28 +0000 Subject: Initial import --- (limited to 'util/persistence.py.args') diff --git a/util/persistence.py.args b/util/persistence.py.args new file mode 100644 index 0000000..1aa235f --- /dev/null +++ b/util/persistence.py.args @@ -0,0 +1,81 @@ +# This program is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 2 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program; if not, write to the Free Software +# Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA +# + + +import sys + +from util.decorators import DecoratorWithArgs + + +class Persistent(type): + '''Metaclass providing object persistence''' + def __init__(cls, name, bases, dct): + super(Persistent, cls).__init__(name, bases, dct) + + setattr(cls, '__dirty__', False) + setattr(cls, '__properties__', filter(_is_persistent, dct.iteritems())) + + from util.journalpickler import dumps, loads + setattr(cls, 'dumps', dumps) + setattr(cls, 'loads', loads) + + +@DecoratorWithArgs +def PersistentProperty(function, default = None): + '''Decorator to set persistent properties''' + keys = 'fset', 'fdel' + func_locals = {'doc':function.__doc__} + + def fgetter(obj, name, getter, default_value): + attr_name = '_' + obj.__class__.__name__ + '__' + name + if not hasattr(obj, attr_name): + setattr(obj, attr_name, default_value(obj)) + return getter(obj) + + def fsetter(obj, name, setter, value): + setattr(obj, '__dirty__', True) + return setter(obj, value) + + def introspect(frame, event, arg): + if event == 'return': + locals = frame.f_locals + func_locals.update(dict((k,locals.get(k)) for k in keys)) + if locals.has_key('fset'): + func_locals['fset'] = \ + lambda obj, value : fsetter(obj, function.__name__, locals['fset'], value) + if default != None: + get_function = \ + lambda obj : fgetter(obj, function.__name__, locals['fget'], lambda x : default) + else: + get_function = \ + lambda obj : fgetter(obj, function.__name__, locals['fget'], lambda x : None) + get_function.decorator = PersistentProperty # tag the getter so we can id + # the decorator. Yeah, it's ugly. + func_locals['fget'] = get_function + sys.settrace(None) + return introspect + + sys.settrace(introspect) + function() + return property(**func_locals) + + +# a wee bit ugly +def _is_persistent(item): + '''check if property is decorated with PersistentProperty decorator''' + prop = item[1] + return type(prop) is property and \ + hasattr(prop.fget, 'decorator') and \ + prop.fget.decorator is PersistentProperty -- cgit v0.9.1