[ZODB-Dev] How do you "wake up" sleepy persistent objects?

Patrick K. O'Brien pobrien@orbtech.com
Thu, 11 Oct 2001 17:53:07 -0500


Here is my situation. I'm working on a sample app that uses ZODB, but not
Zope. The interface to the application is, at this point, simply the Python
shell. Specifically, the Python shell that I created in wxPython/Scintilla,
called PyCrust (http://sourceforge.net/projects/pycrust/). PyCrust provides
call tips for methods and an auto-completion popup list whenever you type an
object name followed by a dot. I noticed that ghosted objects did not
display all of their attributes in the autocompletion list the first time
you typed a dot, but they would the second time (because we just woke them
up). Since I wanted to see the proper autocompletion list the first time
around, I changed the method that generates the popup list to the following:

def getAllAttributeNames(object):
    """Return list of all attributes, including inherited, for an object.

    Recursively walk through a class and all base classes.
    """
    attributes = []
    # Wake up sleepy objects - a hack for ZODB objects in "ghost" state.
    wakeupcall = dir(object)
    del wakeupcall
    # Get attributes available through the normal convention.
    attributes += dir(object)
    # For a class instance, get the attributes for the class.
    if hasattr(object, '__class__'):
        # Break a circular reference. This happens with extension classes.
        if object.__class__ is object:
            pass
        else:
            attributes += getAllAttributeNames(object.__class__)
    # Also get attributes from any and all parent classes.
    if hasattr(object, '__bases__'):
        for base in object.__bases__:
            attributes += getAllAttributeNames(base)
    return attributes

This does what I want. Do you consider this case of waking up ghosts to be
acceptable? Or do you have a suggestion for a better way to handle this
situation?

Thanks for all the help.

P.S. Yes, this method can return a list with duplicated attribute names, but
its caller dedups the list. See below.

def getAttributeNames(object, includeMagic=1, includeSingle=1,
includeDouble=1):
    """Return list of unique attributes, including inherited, for an
object."""
    attributes = []
    dict = {}
    if includeMagic:
        try: attributes += object._getAttributeNames()
        except: pass
    # Get all attribute names, removing duplicates from the attribute list.
    for item in getAllAttributeNames(object):
        dict[item] = None
    attributes += dict.keys()
    attributes.sort()
    if not includeSingle:
        attributes = filter(lambda item: item[0]!='_' or item[1]=='_',
attributes)
    if not includeDouble:
        attributes = filter(lambda item: item[:2]!='__', attributes)
    return attributes

---
Patrick K. O'Brien
Orbtech (http://www.orbtech.com)
"I am, therefore I think."

-----Original Message-----
From: zodb-dev-admin@zope.org [mailto:zodb-dev-admin@zope.org]On Behalf Of
Jim Fulton
Sent: Thursday, October 11, 2001 5:38 PM
To: Chris McDonough
Cc: pobrien@orbtech.com; ZODB
Subject: Re: [ZODB-Dev] How do you "wake up" sleepy persistent objects?

Let me try to summarize.

First, you usually don't need to wake up ghosts. Why would
anyone want to wake up a ghost? I can see doing it
during debugging, but not otherwise.

In general, messing with an objects __dict__ is impolite. :)
You really shouldn't count on getting anything from a __dict__.
The only time to mess with a __dict__ is when you actually want
to defeat the normal persistence machinery. We recently used this
hack^H^H^H^Htechnique in a DTML optimization.

In Python 2.2, __dict__ will be a far less important than
it is now in standard Python. It will be much more bad form to
access a __dict__ than it is in Python now.

I imagine that dir does some attribute access that causes
persistent objects to be activated.

I don't realloy consider the fact that you can't count on __dict__
to be a gitcha in ZODB.  It is a little unfortunate that dir doesn't
always do the right thing.

Jim