Log message for revision 29939: Import what we can from ZODB.persistentclass to avoid duplication.
Changed: U Zope/trunk/lib/python/ZClasses/_pmc.py -=- Modified: Zope/trunk/lib/python/ZClasses/_pmc.py =================================================================== --- Zope/trunk/lib/python/ZClasses/_pmc.py 2005-04-10 13:15:31 UTC (rev 29938) +++ Zope/trunk/lib/python/ZClasses/_pmc.py 2005-04-10 13:42:00 UTC (rev 29939) @@ -18,136 +18,24 @@ $Id$ """ - - -# Notes: -# -# Persistent classes are non-ghostable. This has some interesting -# ramifications: -# -# - When an object is invalidated, it must reload it's state -# -# - When an object is loaded from the database, it's state must be -# loaded. Unfortunately, there isn't a clear signal when an object is -# loaded from the database. This should probably be fixed. -# -# In the mean time, we need to infer. This should be viewed as a -# short term hack. -# -# Here's the strategy we'll use: -# -# - We'll have a need to be loaded flag that we'll set in -# __new__, through an extra argument. -# -# - When setting _p_oid and _p_jar, if both are set and we need to be -# loaded, then we'll load out state. -# -# - We'll use _p_changed is None to indicate that we're in this state. -# - import ExtensionClass +import ZODB.persistentclass -class _p_DataDescr(object): - # Descr used as base for _p_ data. Data are stored in - # _p_class_dict. +# See the comments in ZODB.persistentclass - def __init__(self, name): - self.__name__ = name - - def __get__(self, inst, cls): - if inst is None: - return self - - if '__global_persistent_class_not_stored_in_DB__' in inst.__dict__: - raise AttributeError, self.__name__ - return inst._p_class_dict.get(self.__name__) - - def __set__(self, inst, v): - inst._p_class_dict[self.__name__] = v - - def __delete__(self, inst): - raise AttributeError, self.__name__ - -class _p_oid_or_jar_Descr(_p_DataDescr): - # Special descr for _p_oid and _p_jar that loads - # state when set if both are set and and _p_changed is None - # - # See notes above - - def __set__(self, inst, v): - get = inst._p_class_dict.get - if v == get(self.__name__): - return - - inst._p_class_dict[self.__name__] = v - - jar = get('_p_jar') - if (jar is not None - and get('_p_oid') is not None - and get('_p_changed') is None - ): - jar.setstate(inst) - -class _p_ChangedDescr(object): - # descriptor to handle special weird emantics of _p_changed - - def __get__(self, inst, cls): - if inst is None: - return self - return inst._p_class_dict['_p_changed'] - - def __set__(self, inst, v): - if v is None: - return - inst._p_class_dict['_p_changed'] = bool(v) - - def __delete__(self, inst): - inst._p_invalidate() - -class _p_MethodDescr(object): - """Provide unassignable class attributes - """ - - def __init__(self, func): - self.func = func - - def __get__(self, inst, cls): - if inst is None: - return cls - return self.func.__get__(inst, cls) - - def __set__(self, inst, v): - raise AttributeError, self.__name__ - - def __delete__(self, inst): - raise AttributeError, self.__name__ - - -special_class_descrs = '__dict__', '__weakref__' - - -def _p_maybeupdate(self, name): - get = self._p_class_dict.get - data_manager = get('_p_jar') - - if ( - (data_manager is not None) - and - (get('_p_oid') is not None) - and - (get('_p_changed') == False) - ): - - self._p_changed = True - data_manager.register(self) - class ZClassPersistentMetaClass(ExtensionClass.ExtensionClass): - _p_jar = _p_oid_or_jar_Descr('_p_jar') - _p_oid = _p_oid_or_jar_Descr('_p_oid') - _p_changed = _p_ChangedDescr() - _p_serial = _p_DataDescr('_p_serial') + # For weird reasons having to do with restrictions on built-in + # types, we can't subclass + # ZODB.persistentclass.PersistentMetaClass, so we do the next best + # thing: + for name in ('_p_jar', '_p_oid', '_p_changed', '_p_serial', + '__getnewargs__', '_p_maybeupdate', '_p_deactivate', + '_p_invalidate', '__getstate__', '_p_activate', ): + locals()[name] = ZODB.persistentclass.PersistentMetaClass.__dict__[ + name] + def __new__(self, name, bases, cdict, _p_changed=False): # _p_changed will be None if we are being loaded from the @@ -168,46 +56,15 @@ ExtensionClass.pmc_init_of(result) return result - def __getnewargs__(self): - return self.__name__, self.__bases__, {}, None - - __getnewargs__ = _p_MethodDescr(__getnewargs__) - def __setattr__(self, name, v): if not ((name.startswith('_p_') or name.startswith('_v'))): - _p_maybeupdate(self, name) + self._p_maybeupdate(name) super(ZClassPersistentMetaClass, self).__setattr__(name, v) def __delattr__(self, name): if not ((name.startswith('_p_') or name.startswith('_v'))): - _p_maybeupdate(self, name) + self._p_maybeupdate(name) super(ZClassPersistentMetaClass, self).__delattr__(name) - - def _p_deactivate(self): - # persistent classes can't be ghosts - pass - - _p_deactivate = _p_MethodDescr(_p_deactivate) - - def _p_invalidate(self): - # reset state - self._p_class_dict['_p_changed'] = None - self._p_jar.setstate(self) - - _p_invalidate = _p_MethodDescr(_p_invalidate) - - - def __getstate__(self): - return (self.__bases__, - dict([(k, v) for (k, v) in self.__dict__.items() - if not (k.startswith('_p_') - or k.startswith('_v_') - or k in special_class_descrs - ) - ]), - ) - - __getstate__ = _p_MethodDescr(__getstate__) def __setstate__(self, state): try: @@ -224,13 +81,14 @@ _p_class_dict = self._p_class_dict self._p_class_dict = {} - to_remove = [k for k in self.__dict__ - if ((k not in cdict) - and - (k not in special_class_descrs) - and - (k != '_p_class_dict') - )] + to_remove = [ + k for k in self.__dict__ + if ((k not in cdict) + and + (k not in ZODB.persistentclass.special_class_descrs) + and + (k != '_p_class_dict') + )] for k in to_remove: delattr(self, k) @@ -244,9 +102,4 @@ self._p_changed = False - __setstate__ = _p_MethodDescr(__setstate__) - - def _p_activate(self): - self._p_jar.setstate(self) - - _p_activate = _p_MethodDescr(_p_activate) + __setstate__ = ZODB.persistentclass._p_MethodDescr(__setstate__) _______________________________________________ Zope-Checkins maillist - Zope-Checkins@zope.org http://mail.zope.org/mailman/listinfo/zope-checkins