Web   ·   Wiki   ·   Activities   ·   Blog   ·   Lists   ·   Chat   ·   Meeting   ·   Bugs   ·   Git   ·   Translate   ·   Archive   ·   People   ·   Donate
summaryrefslogtreecommitdiffstats
path: root/util/persistence.py.args
diff options
context:
space:
mode:
Diffstat (limited to 'util/persistence.py.args')
-rw-r--r--util/persistence.py.args81
1 files changed, 81 insertions, 0 deletions
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