[Zope3-checkins] CVS: Zope3/src/zodb/code - class_.py:1.5
Jeremy Hylton
jeremy@zope.com
Mon, 30 Dec 2002 19:18:45 -0500
Update of /cvs-repository/Zope3/src/zodb/code
In directory cvs.zope.org:/tmp/cvs-serv23294
Modified Files:
class_.py
Log Message:
First attempt at repairing pickling for persistent classes.
=== Zope3/src/zodb/code/class_.py 1.4 => 1.5 ===
--- Zope3/src/zodb/code/class_.py:1.4 Mon Dec 30 18:05:02 2002
+++ Zope3/src/zodb/code/class_.py Mon Dec 30 19:18:44 2002
@@ -182,8 +182,8 @@
self.__setstate__ = func.__setstate__
def __repr__(self):
- return "<descriptor %s.%s>" % (self.__objclass__.__name__,
- self.__name__)
+ return "<persistent descriptor %s.%s>" % (self.__objclass__.__name__,
+ self.__name__)
def __get__(self, object, klass=None):
if object is None:
@@ -219,7 +219,11 @@
_pc_init = False
- def __new__(meta, name, bases, dict):
+ # A class is normally created in the UPTODATE state, but when a
+ # new ghost is created for it the serialization machinery passes
+ # GHOST instead of UPTODATE. See __getnewargs__().
+
+ def __new__(meta, name, bases, dict, state=UPTODATE):
cls = super(PersistentClassMetaClass, meta).__new__(
meta, name, bases, dict)
# helper functions
@@ -234,7 +238,7 @@
extend_attr("_p_oid", None)
extend_attr("_p_jar", None)
extend_attr("_p_atime", time.time() % 86400)
- extend_attr("_p_state", UPTODATE)
+ extend_attr("_p_state", state)
extend_meth("_p_activate", meta._p_activate)
extend_meth("_p_deactivate", meta._p_activate)
extend_meth("__getstate__", meta.__getstate__)
@@ -248,11 +252,6 @@
cls._pc_init = True
return cls
- def fixup(cls, mod):
- for k, v in cls.__dict__.items():
- if isinstance(v, function):
- setattr(cls, k, PersistentFunction(v, mod))
-
def __getattribute__(cls, name):
# XXX I'm not sure I understand this code any more.
super_meth = super(PersistentClassMetaClass, cls).__getattribute__
@@ -292,33 +291,54 @@
return "<persistent class %s.%s>" % (cls.__module__,
cls.__name__)
+ # XXX This stuff only handles methods, not data members, but it's
+ # a start.
+
+ # The state of a persistent class is its persistent functions.
+ # They need to be extracted from the methods when the class is pickled
+ # and put back into descriptors when they are unpickled.
+
+ # How to recognize other class attributes that need to be pickled?
+
def __getstate__(cls):
dict = {}
- for k, v in cls.__dict__.items():
- if hasattr(v, '_p_oid'):
- dict[k] = v
+ for k in cls.__dict__.keys():
+ v = getattr(cls, k)
+ if isinstance(v, PersistentMethod):
+ dict[k] = v.im_func
return dict
def __setstate__(cls, dict):
for k, v in dict.items():
- setattr(cls, k, v)
+ setattr(cls, k, PersistentDescriptor(cls, v))
def _p_deactivate(cls):
# do nothing but mark the state change for now
cls._p_state = GHOST
def _p_activate(cls):
- if cls._p_state is None:
+ if cls._p_state == GHOST:
dm = cls._p_jar
if dm is not None:
- # reactivate
- cls._p_state = UPTODATE
+ cls._p_state = CHANGED
+ try:
+ dm.setstate(cls)
+ finally:
+ # XXX Should really put in special inconsistent state
+ cls._p_state = UPTODATE
# Methods below here are not wrapped to be class-only attributes.
# They are available as methods of classes using this metaclass.
def __getnewargs__(cls):
- return cls.__name__, cls.__bases__, {}
+ # XXX This should really be _p_getnewargs() or something like that.
+
+ # If the class is later loaded and unghostified, the arguments
+ # passed to __new__() won't have an __module__. It seems that
+ # the module gets set to zodb.code.class_ in that case, which
+ # is wrong.
+ return (cls.__name__, cls.__bases__,
+ {"__module__": cls.__module__}, GHOST)
def _p_newstate(cls, acls):
# Update a class's __dict__ in place. Must use setattr and