[Zope3-dev] Backward-incompatible bug fix to zope.proxy

Roger Ineichen dev at projekt01.ch
Sun Apr 2 19:17:21 EDT 2006


Jim Fulton schrieb:
> A while ago, Gary and I found what appeared to be a bug in
> zope.proxy.ProxyBase's handling of non-data descriptors (descriptors
> that define __get__, but not __set__ and __delete__) defined in
> proxy classes.  Normally, when a class has non-data descriptors,
> instance data overrides the descriptor.  ProxyBase let non-data
> descriptors override instance data.  For a proxy, instance data almost
> always comes from the proxied object.  This behavior of ProxyBase
> caused subtle bugs.
> 
> I've decided to fix this bug because it was causing my pain on my
> jim-adapter branch.  I decided to fix this bug on the branch.  The fix
> has a somewhat unexpected side effect. It turns out that some proxy
> applications depended on the old behavior.
> 
> Consider location proxies:
> 
>   class LocationProxy(ProxyBase):
>       ...
> 
>       def __reduce__(self, proto=None):
>           raise TypeError("Not picklable")
> 
>       ...
> 
> Here the proxy is trying to prevent pickling by providing a __reduce__
> that raises an exception.  Now methods are non-data descriptors.  With
> the fix, the __reduce__ of the proxied object is used.  We need to
> convert __reduce__ to a data descriptor.  I've added a function to
> the branch that can be used as a decorator to do this:
> 
> 
>   class LocationProxy(ProxyBase):
>       ...
> 
>       @zope.proxy.non_overridable
>       def __reduce__(self, proto=None):
>           raise TypeError("Not picklable")
> 
>       ...
> 
> 
> I also had to change the the descriptors defined in zope.app.decorator
> to be data descriptors.
> 
> The fix is obviously not backward compatible.  I don't know if this
> would effect anything outside of Zope.  If this affects anyone, please
> let me know.  If necessary, I can probably provide a ProxyBase2 with
> the fix and leave ProxyBase alone, but I'd rather not.
> 
> Is anyone using zope.proxy to define custom proxy types?
> 
> Jim
> 

Hi Jim,

We just use a IContainer location proxy adapter.
But since this adapter isn't persistent I don't think this
is a problem.

def proxify(container, item):
     if IContainer.providedBy(item):
         proxy = ContainerLocationProxy(item)
     else:
         proxy = LocationProxy(item)
     proxy.__name__ = item.__name__
     proxy.__parent__ = container
     return proxy

class ContainerLocationProxy(LocationProxy):
     """Proxy the location of a container an its items."""

     # zope.app.conatiner.interfaces.IReadContainer
     def __getitem__(self, key):
         return proxify(self, getProxiedObject(self).__getitem__(key))

     ...

Regards
Roger Ineichen
_____________________________
Projekt01 GmbH
www.projekt01.ch
Boesch 65
6331 Hünenberg
phone     +41 (0)41 781 01 78
mobile    +41 (0)79 340 52 32
fax       +41 (0)41 781 00 78
email roger.ineichen at projekt01.ch
_____________________________
END OF MESSAGE


More information about the Zope3-dev mailing list