[Zope-dev] ZPatterns bug: infinite recursion with External Attribute Provider

Steve Alexander steve@cat-box.net
Sun, 17 Sep 2000 21:18:17 +0100


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