[Twisted-Python] Problems with PB and Jelly...

Jasper Phillips jasper at peak.org
Sun Mar 23 06:59:15 EST 2003

Hash: SHA1

On Sat, 22 Mar 2003, Brian Warner wrote:

> > I have a Perspective <-> Referenceable server/client setup, and am trying
> > to pass objects between them.  Following the online docs I've set all the
> > relavent classes to inherit from pb.Copyable + pb.RemoteCopy, and passed
> > them all to pb.setUnjellyableForClass.
> I'll take responsibility for that one (I wrote those docs :). If the classes
> behave the same way on both ends, then it can make sense to inherit from both
> Copyable and RemoteCopy. If objects are supposed to behave differently
> depending upon whether they are the "home" or the "away" form, then you'll
> want two classes, where the "home" form is pb.Copyable and the receiving
> "away" form is pb.RemoteCopy.

The way you wrote it in the docs made sense to me!  As my objects are treated
the same on either side, I chose to use multiple inheritence to avoid
tripling the number of classes I needed.

> Often this depends upon whether the object really has a home: if it is just
> a container for some chunk of state, and doesn't hold any references to
> other objects, then it doesn't really have a home and you can use the
> dual-inheritance trick to cut down on some typing.

Hmmmm.  You're implying that the state can't hold references to other
objects?  That might explain an exception I'm getting, which I'll describe
below.  If this is true, is there some easy way around this, or do I need
a custom setCopyableState()?

> > I'm also unsure what to make of the last bullet under "Things To Watch Out
> > For" on the above webpage.  It seems unsure whether using __init__ to
> > initialize transferable objects is ok...  Must I truly go and hack all
> > my objects to not use __init__, and instead use setCopyableState()?
> To be precise, the received objects are created with a hack that creates an
> object of a dummy class, then transforms it into the correct class, then runs
> setCopyableState to populate the attributes. By doing this, it avoids running
> the new class' __init__ method altogether. When the object is created by you
> (by using the class name as a callable), it will run __init__. When it is
> created in response to a received serialized instance, it will not run
> __init__ but will run setCopyableState instead. This lets you set up objects
> differently in the two different situations.

I've since gone and investigated more close what's going on.  I've used this
hack before, and it was exactly what I was hoping to see.

However, I'm sometimes getting an exception when the actual dictionary
copying is done, as something other than a dict is being copied into
__dict__.  At this point the "jelType" is "dereference"...

Suddenly, I wonder if this is because I'm using a circular reference?
I have a "map" which contains "cells", which contain "links" having
a reference to "map"...

Damn, it looks like this might be the cuplrit.  "reference" jelyTypes are
recursively descended into before they are stored, and if a dereference is
found before it's stored... some sort of _Dereference object is created?
An attempt is then made to copy this into __dict__, and boom.

I can think of two ways to avoid this problem: 2 passes, or creating
instances and storing a ref to them before recursing to determine their their
state.  Perhaps this _Dereference is intended to be replaced with a real
reference in some sort of 2nd pass?

I'll have to look into this more closely latter.  At first glance it appears
to be something best fixed in twisted itself rather than a local
setCopyableState()... at least to this twisted newbie. ;-)

> > The "module not allowed" exception is misleading, and stems from what
> > appears to be an obsolete branch "else" branch of
> > jelly._Unjellier.unjelly(), judging by the fact that it uses the temp
> > variable jelType for something different than the "if" branch.
> I think you might be right. We have a review of PB scheduled for the PyCon
> sprint next tuesday.. I've added that code to the list of stuff to be
> examined. We'll try to clear out all the dead code on that day.

I've since looked at this code more closely as well.  The "else" branch in
question is most definitely _not_ dead code, but it is confusing.  ;-)

jelly._Unjellier.unjelly() is used in two manners, which you can see fairly
easily by printing out the local variable "jelType".  Sometimes this is a
"type" name that gets munged into a _unjelly_"type" method call (ie the final
"if" branch), and other times "jelType" is a class's local import name, which
is parsed into recursive unjelly commands (the "else" branch).

Then again, that's what I think is going on.  Hard to say, since I'm still
getting exceptions out of it I don't quite grasp. ;-(

- -Jasper

Version: GnuPG v1.0.6 (GNU/Linux)
Comment: For info see http://www.gnupg.org


More information about the Twisted-Python mailing list