############################################################################## # # Copyright (c) 2004 Zope Corporation and Contributors. # All Rights Reserved. # # This software is subject to the provisions of the Zope Public License, # Version 2.1 (ZPL). A copy of the ZPL should accompany this distribution. # THIS SOFTWARE IS PROVIDED "AS IS" AND ANY AND ALL EXPRESS OR IMPLIED # WARRANTIES ARE DISCLAIMED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED # WARRANTIES OF TITLE, MERCHANTABILITY, AGAINST INFRINGEMENT, AND FITNESS # FOR A PARTICULAR PURPOSE. # ############################################################################## """ZCLass Persistent Meta Class IMPORTANT -- This module is private to ZClasses and experimetal. It is highly subject to change and likely to move $Id: _pmc.py 40218 2005-11-18 14:39:19Z andreasjung $ """ import ExtensionClass import ZODB.persistentclass # See the comments in ZODB.persistentclass class ZClassPersistentMetaClass(ExtensionClass.ExtensionClass): # 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 # database, because __getnewargs__ returns an extra argument # for _p_changed. # The above is *not* true for old (< 2.8) ZClass code. # Old ZClass records have all of their data in their # arguments. This is rather fortunate. It means that # we don't need to call __setstate__. We *do*, however, need # to call pmc_init_of. cdict = dict([(k, v) for (k, v) in cdict.items() if not k.startswith('_p_')]) cdict['_p_class_dict'] = {'_p_changed': _p_changed} result = super(ZClassPersistentMetaClass, self ).__new__(self, name, bases, cdict) ExtensionClass.pmc_init_of(result) return result # copy_reg.py:_slotnames() tries to use this attribute as a cache. # Dont allow this attribute to be written as it may cause us # to register with the data_manager. __slotnames__ = property(None) def __setattr__(self, name, v): super(ZClassPersistentMetaClass, self).__setattr__(name, v) if not ((name.startswith('_p_') or name.startswith('_v'))): self._p_maybeupdate(name) def __delattr__(self, name): super(ZClassPersistentMetaClass, self).__delattr__(name) if not ((name.startswith('_p_') or name.startswith('_v'))): self._p_maybeupdate(name) def __setstate__(self, state): try: self.__bases__, cdict = state except TypeError: # Maybe an old ZClass with state == None if state is None: cdict = None if cdict is not None: cdict = dict([(k, v) for (k, v) in cdict.items() if not k.startswith('_p_')]) _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 ZODB.persistentclass.special_class_descrs) and (k != '_p_class_dict') )] for k in to_remove: delattr(self, k) try: del cdict['__slotnames__'] except KeyError: pass for k, v in cdict.items(): setattr(self, k, v) self._p_class_dict = _p_class_dict ExtensionClass.pmc_init_of(self) self._p_changed = False __setstate__ = ZODB.persistentclass._p_MethodDescr(__setstate__)