Re: [ZODB-Dev] Persistent object has empty __dict__ for a little while

2010-01-06 Thread Tres Seaver
-BEGIN PGP SIGNED MESSAGE-
Hash: SHA1

Martin Aspeli wrote:
 Hi,
 
 This one is pretty high no the list of weirdest things to have happened 
 to me in a while. Basically, I have a persistent object that has an 
 empty __dict__() on the first request, until it suddenly decides to have 
 data again.
 
 I'm on ZODB 3.9.3, using Zope 2.12 and Plone 4. I have a persistent 
 object, /plone/portal_registry:
 
class Registry(registry.Registry, SimpleItem):
pass
 
 The base class is:
 
class Registry(Persistent):
def __init__(self):
self._records = Records(self)
 
 Records is:
 
  class Records(Persistent):
 
__parent__ = None
 
def __init__(self, parent):
self.__parent__ = parent
self.data = OOBTree()
 
def __getitem__(self, name):
return self.data.__getitem__(name)
 
 The BTree contains string keys and Record objects as values. Record is:
 
  class Record(Persistent):
  __name__ = u
  __parent__ = None
 
  field = None
 
 __parent__ is set to records.__parent__, which is going to be the 
 Registry object.
 
 field is set to a special persistent field class inheriting from 
 zope.schema's fields, but mixing in persistence. In this case, I have a 
 list field:
 
class PersistentField(persistent.Persistent):
Base class for persistent field definitions.

 
class PersistentCollectionField(PersistentField,
   zope.schema._field.AbstractCollection):
 
class List(PersistentCollectionField, zope.schema.List):
pass
 
 I then have some code like this:
 
  def cloneField(self, field):
  clone = field.__class__.__new__(field.__class__)
  clone.__dict__.update(field.__dict__)
  for name, attr in field.__dict__.items():
  if IField.providedBy(attr):
  clone.__dict__[name] = self.cloneField(attr)
  return clone
 
 This is used like so:
 
  registry = getUtility(IRegistry) # persistent/local
  clone = self.cloneField(registry.records[recordName].field)
 
 This seems to work always *except* on the first request immediately 
 after starting up Zope. In this case, field.__dict__ is {}. If I poke at 
 it long enough in pdb, it suddenly springs into life and contains values 
 again.
 
 Can anyone enlighten me as to:
 
   - why this may happen
   - how I can ensure it stops happening :-)

You have a ghost, likely:  try getting it to unghostify by accessing an
attribute, or calling '_p_activate' (accessing '__dict__' doesn't
provoke the auto-activation).


Tres.
- --
===
Tres Seaver  +1 540-429-0999  tsea...@palladion.com
Palladion Software   Excellence by Designhttp://palladion.com
-BEGIN PGP SIGNATURE-
Version: GnuPG v1.4.9 (GNU/Linux)
Comment: Using GnuPG with Mozilla - http://enigmail.mozdev.org

iEYEARECAAYFAktE7UUACgkQ+gerLs4ltQ68YwCeOywUw4a/c7UXap6uxyIzMCx7
9VcAoII4X56V7LConhNSYCWvFMWMooBD
=XvFD
-END PGP SIGNATURE-

___
For more information about ZODB, see the ZODB Wiki:
http://www.zope.org/Wikis/ZODB/

ZODB-Dev mailing list  -  ZODB-Dev@zope.org
https://mail.zope.org/mailman/listinfo/zodb-dev


Re: [ZODB-Dev] Persistent object has empty __dict__ for a little while

2010-01-06 Thread Jim Fulton
On Wed, Jan 6, 2010 at 10:40 AM, Martin Aspeli optilude+li...@gmail.com wrote:
 Hi,

 This one is pretty high no the list of weirdest things to have happened
 to me in a while. Basically, I have a persistent object that has an
 empty __dict__() on the first request, until it suddenly decides to have
 data again.

 I'm on ZODB 3.9.3, using Zope 2.12 and Plone 4. I have a persistent
 object, /plone/portal_registry:

   class Registry(registry.Registry, SimpleItem):
       pass

 The base class is:

   class Registry(Persistent):
       def __init__(self):
           self._records = Records(self)

 Records is:

     class Records(Persistent):

       __parent__ = None

       def __init__(self, parent):
           self.__parent__ = parent
           self.data = OOBTree()

       def __getitem__(self, name):
           return self.data.__getitem__(name)

 The BTree contains string keys and Record objects as values. Record is:

     class Record(Persistent):
         __name__ = u
         __parent__ = None

         field = None

 __parent__ is set to records.__parent__, which is going to be the
 Registry object.

 field is set to a special persistent field class inheriting from
 zope.schema's fields, but mixing in persistence. In this case, I have a
 list field:

   class PersistentField(persistent.Persistent):
       Base class for persistent field definitions.
       

   class PersistentCollectionField(PersistentField,
              zope.schema._field.AbstractCollection):

   class List(PersistentCollectionField, zope.schema.List):
       pass

 I then have some code like this:

     def cloneField(self, field):
         clone = field.__class__.__new__(field.__class__)
         clone.__dict__.update(field.__dict__)
         for name, attr in field.__dict__.items():
             if IField.providedBy(attr):
                 clone.__dict__[name] = self.cloneField(attr)
         return clone

 This is used like so:

     registry = getUtility(IRegistry) # persistent/local
     clone = self.cloneField(registry.records[recordName].field)

 This seems to work always *except* on the first request immediately
 after starting up Zope. In this case, field.__dict__ is {}. If I poke at
 it long enough in pdb, it suddenly springs into life and contains values
 again.

 Can anyone enlighten me as to:

  - why this may happen
  - how I can ensure it stops happening :-)

__dict__ is a special variable. Accessing it doesn't cause an object
to be activated.

Rather than doing:

   clone.__dict__.update(field.__dict__)

I would do:

   clone.__setstate__(field.__getstate__)

Alternatively, you can assure that field is acticated first, using
_p_activate or by accessing an
attribute.

Jim

-- 
Jim Fulton
___
For more information about ZODB, see the ZODB Wiki:
http://www.zope.org/Wikis/ZODB/

ZODB-Dev mailing list  -  ZODB-Dev@zope.org
https://mail.zope.org/mailman/listinfo/zodb-dev