# 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 def is_persistent(item): prop = item[1] return type(prop) is property and \ hasattr(prop.fget, 'decorator') and \ prop.fget.decorator is PersistentProperty class Persistent(type): def __init__(cls, name, bases, dct): # is_dirty setattr(cls, '__dirty__', False) # properties setattr(cls, '__properties__', filter(is_persistent, dct.iteritems())) super(Persistent, cls).__init__(name, bases, dct) def PersistentProperty(function): function.decorator = PersistentProperty keys = 'fset', 'fdel' func_locals = {'doc':function.__doc__} def fgetter(obj, name, getter, fdef): attr_name = '_' + obj.__class__.__name__ + '__' + name if not hasattr(obj, attr_name): setattr(obj, attr_name, fdef(obj)) return getter(obj) def fsetter(obj, name, setter, value): setattr(obj, '__dirty__', True) return setter(obj, value) def probe_function(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 locals.has_key('fdef'): f = lambda obj : fgetter(obj, function.__name__, locals['fget'], locals['fdef']) else: f = lambda obj : fgetter(obj, function.__name__, locals['fget'], lambda x : None) f.decorator = PersistentProperty # tag the getter func_locals['fget'] = f sys.settrace(None) return probe_function sys.settrace(probe_function) function() return property(**func_locals)