ZPatterns bug: infinite recursion with External Attribute Provider
ZPatterns-0-4-2a2 When I use an External Attribute Provider, I get an infinite recursion problem, and Zope hangs. This is because DataManager (in DataManagers.py) uses normal getattr() and object.__skinSlot__ methods to get and set the special attribute __skinSlot__ on DataSkins. Thus, the system tries to store the __skinSlot__ attribute in the DataSkin instance by storing the __skinSlot__ attribute in the DataSkin instance by storing the __skinSlot__ attribute in the DataSkin instance by... I can fix this, by patching DataManager to use client.__dict__ instead: def _readableSlotFor(self,client): #slot = getattr(client,'__skinSlot__',_marker) slot = client.__dict__.get('__skinSlot__',_marker) if slot is _marker: return {} client._setSlot(slot); return slot def _writeableSlotFor(self,client): #slot = getattr(client,'__skinSlot__',_marker) slot = client.__dict__.get('__skinSlot__',_marker) if slot is _marker: #slot = client.__skinSlot__ = PersistentMapping() slot = client.__dict__['__skinSlot__'] = PersistentMapping() client._setSlot(slot); return slot This works, in as far as I can do things like add sub-objects to a ZClass that derives from DataSkin and ObjectManager without infinite regress. However, I still get an attribute error. This is because the External Attribute Provider only offers to set and delete its attributes. I'm confused as to why this should be -- surely the External Attribute Provider should offer to get the same attributes as it is offering to set and delete? Or, do I have to use an extra provider in the form of some SkinScript or a Generic Attribute Provider to do the getting? I tried altering namesForRegistration, so that the External Attribute Provider would offer to getattr for "*", then refreshed the customizer I'd put the EAP into. def namesForRegistration(self,container): """XXX""" return { 'provides':('attributes',), 'setattr': self.Attributes, 'delattr': self.Attributes, 'getattr': self.Attributes } I can now add sub-objects to my ZClass instances, and I can traverse to those sub-objects by typing them into the URL field of my browser. However, I can't get a list of the sub-objects by calling objectIds. I'm trying to make sense of External Attribute Provider so that I can write a BTreeAttributeProvider for DataSkinAddons, as discussed on the zope-dev list at the end of August, subject "BTreeFolder /w Customizer support". Any pointers appreciated. -- Steve Alexander Software Engineer Cat-Box limited http://www.cat-box.net
At 09:18 PM 9/17/00 +0100, Steve Alexander wrote:
ZPatterns-0-4-2a2
When I use an External Attribute Provider, I get an infinite recursion problem, and Zope hangs.
Argh. This is what happens when I create a new feature on the spur of the moment and toss it in just before a release. :(
This is because DataManager (in DataManagers.py) uses normal getattr() and object.__skinSlot__ methods to get and set the special attribute __skinSlot__ on DataSkins.
Yes, that clearly should be fixed.
This works, in as far as I can do things like add sub-objects to a ZClass that derives from DataSkin and ObjectManager without infinite regress. However, I still get an attribute error. This is because the External Attribute Provider only offers to set and delete its attributes. I'm confused as to why this should be -- surely the External Attribute Provider should offer to get the same attributes as it is offering to set and delete?
Yes, it should, and that's my own stupid implementation error. I forgot to include code for that. :( I'll do another update release this week to fix this and the other problem you reported (w/link to parent providers). You might want to report the list vs. string behavior on that one to the Collector, since that does indeed sound like a Zope bug to me. IMHO, multi-select properties ought to be tuples anyway, but they certainly should never be a string.
At 09:18 PM 9/17/00 +0100, Steve Alexander wrote:
I can fix this, by patching DataManager to use client.__dict__ instead:
def _readableSlotFor(self,client): #slot = getattr(client,'__skinSlot__',_marker) slot = client.__dict__.get('__skinSlot__',_marker)
if slot is _marker: return {}
client._setSlot(slot); return slot
def _writeableSlotFor(self,client): #slot = getattr(client,'__skinSlot__',_marker) slot = client.__dict__.get('__skinSlot__',_marker)
if slot is _marker: #slot = client.__skinSlot__ = PersistentMapping() slot = client.__dict__['__skinSlot__'] = PersistentMapping()
You also need "client._p_changed = 1" here, or the slot will not be saved.
This works, in as far as I can do things like add sub-objects to a ZClass that derives from DataSkin and ObjectManager without infinite regress. However, I still get an attribute error. This is because the External Attribute Provider only offers to set and delete its attributes. I'm confused as to why this should be -- surely the External Attribute Provider should offer to get the same attributes as it is offering to set and delete?
That was me forgetting to update the namesForRegistration method in the subclass. :(
I can now add sub-objects to my ZClass instances, and I can traverse to those sub-objects by typing them into the URL field of my browser. However, I can't get a list of the sub-objects by calling objectIds.
Hm. I don't know what could cause that, if the other bugs are fixed. I'm in the process of getting all the patches checked in right now to do a release today (I hope).
participants (2)
-
Phillip J. Eby -
Steve Alexander