Hello, I've stumbled upon a wrinkly edge case (bug?) in zope.component. What I was trying to do is register an AbsoluteURL adapter for lovely.remotetask.processor.ProcessorRequest objects, and since they don't implement a specific interface, I thought I'd use the class itself as the required component. But registering the adapter for "* lovely.remotetask.processor.ProcessorRequest" fails with a strange TypeError (see below). The reason is that the class inherits from zope.publisher.base.BaseRequests which uses __slots__. The minimal reproduction recipe to see the error is this: class Slotted(object): __slots__ = ('__provides__') zope.component.provideAdapter( lambda x: True, (Slotted,), zope.interface.Interface) Which will raise File "/home/wosc/.python-eggs/zope.component-3.7.1-py2.6.egg/zope/component/registry.py", line 419, in _getAdapterRequired elif not ISpecification.providedBy(r): TypeError: 'member_descriptor' object is not callable Why is this? Can this be made to work? How would I go about investigating that? Thanks, Wolfgang
Wolfgang Schnerring wrote:
The minimal reproduction recipe to see the error is this:
class Slotted(object): __slots__ = ('__provides__')
zope.component.provideAdapter( lambda x: True, (Slotted,), zope.interface.Interface)
Which will raise File "/home/wosc/.python-eggs/zope.component-3.7.1-py2.6.egg/zope/component/registry.py", line 419, in _getAdapterRequired elif not ISpecification.providedBy(r): TypeError: 'member_descriptor' object is not callable
Why is this? Can this be made to work? How would I go about investigating that?
It looks to me like a possible bug in zope.interface. Try deleting _zope_interface_coptimizations.so to hopefully expand that traceback. Shane
* Shane Hathaway <shane@hathawaymix.org> [2009-12-03 11:44]:
Wolfgang Schnerring wrote:
The minimal reproduction recipe to see the error is this:
class Slotted(object): __slots__ = ('__provides__')
zope.component.provideAdapter( lambda x: True, (Slotted,), zope.interface.Interface)
Which will raise File "/home/wosc/.python-eggs/zope.component-3.7.1-py2.6.egg/zope/component/registry.py", line 419, in _getAdapterRequired elif not ISpecification.providedBy(r): TypeError: 'member_descriptor' object is not callable
It looks to me like a possible bug in zope.interface. Try deleting _zope_interface_coptimizations.so to hopefully expand that traceback.
Thanks for the hint! This enabled me to step through all of it with pdb, which turns up zope/interface/declarations.py:1249 def getObjectSpecification(ob): provides = getattr(ob, '__provides__', None) if provides is not None: return provides [...] So it seems that __provides__ is part of the zope.interface mechanics, and if unset that attribute should not exist -- but when using __slots__ it always exists, namely as a 'member_descriptor' object. I'll try and see whether I can come up with a way for zope.interface to do the Right Thing(tm) in this situation. Wolfgang
* Wolfgang Schnerring <ws@gocept.com> [2009-12-07 08:53]:
The minimal reproduction recipe to see the error is this:
class Slotted(object): __slots__ = ('__provides__')
zope.component.provideAdapter( lambda x: True, (Slotted,), zope.interface.Interface) I'll try and see whether I can come up with a way for zope.interface to do the Right Thing(tm) in this situation.
I forgot to mention this here: the edge case has been fixed and released in zope.interface-3.5.3 Wolfgang
participants (2)
-
Shane Hathaway -
Wolfgang Schnerring