-----BEGIN PGP SIGNED MESSAGE----- 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. [snip]
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 -----BEGIN PGP SIGNATURE----- Version: GnuPG v1.0.6 (GNU/Linux) Comment: For info see http://www.gnupg.org iD8DBQE+faGY8EpjZ7/X9bIRAq3bAKDOyRV9oB98xDlTlUdx9rgEz1eItgCgx4Yu 7S3uLjnNpZ1JLDNEmMhWT9Y= =+Ilk -----END PGP SIGNATURE-----