Yesterday, I released "dm.zdoc" and today I find problems. The analysis revealed: The class "webdav.EtagSupport.EtagSupport" has initially no attributes "__provides__" and "__providedBy__". For still unknown reasons, it suddenly gets these attributes. "__provides__" is a "zope.interface.declarations.ClassProvides". Therefore, I expect that Zope 3 or "five" is responsible for these additions. "EtagSupport" is in the mro of "ManagableIndex". But nevertheless, "ManagableIndex.__provides__" results in an "AttributeError". Here is a transscript reproducing the problem:
import App.FindHomes from webdav.EtagSupport import EtagSupport EtagSupport.__provides__ Traceback (most recent call last): File "<stdin>", line 1, in ? AttributeError: class EtagSupport has no attribute '__provides__' from Products.ManagableIndex.ManagableIndex import ManagableIndex /usr/local/lib/python24.zip/whrandom.py:38: DeprecationWarning: the whrandom module is deprecated; please use the random module DeprecationWarning) EtagSupport.__provides__ <zope.interface.declarations.ClassProvides object at 0x40b5566c> ManagableIndex.__provides__ Traceback (most recent call last): File "<stdin>", line 1, in ? AttributeError: __provides__ from inspect import getmro EtagSupport in getmro(ManagableIndex) True
Any ideas? -- Dieter
Dieter Maurer wrote at 2008-1-7 17:55 +0100:
Yesterday, I released "dm.zdoc" and today I find problems.
The analysis revealed:
The class "webdav.EtagSupport.EtagSupport" has initially no attributes "__provides__" and "__providedBy__".
For still unknown reasons, it suddenly gets these attributes. "__provides__" is a "zope.interface.declarations.ClassProvides". Therefore, I expect that Zope 3 or "five" is responsible for these additions.
"EtagSupport" is in the mro of "ManagableIndex". But nevertheless, "ManagableIndex.__provides__" results in an "AttributeError".
Here is a transscript reproducing the problem:
import App.FindHomes from webdav.EtagSupport import EtagSupport EtagSupport.__provides__ Traceback (most recent call last): File "<stdin>", line 1, in ? AttributeError: class EtagSupport has no attribute '__provides__' from Products.ManagableIndex.ManagableIndex import ManagableIndex /usr/local/lib/python24.zip/whrandom.py:38: DeprecationWarning: the whrandom module is deprecated; please use the random module DeprecationWarning) EtagSupport.__provides__ <zope.interface.declarations.ClassProvides object at 0x40b5566c> ManagableIndex.__provides__ Traceback (most recent call last): File "<stdin>", line 1, in ? AttributeError: __provides__ from inspect import getmro EtagSupport in getmro(ManagableIndex) True
Any ideas?
I think I understand the behavior -- and I think it is a "zope.interface" bug. Under some circumstances "zope.interface" adds a "__provides__" descriptor to a class. The descriptor is implemented in "zope/interface/_zope_interface_coptimizations.c" and called "CPB_descr_get". While "__implements__" is inherited by derived classes, the inherited "__provides__" refuses to work for a derived class and raises "AttributeError: __provides__" instead, the AttriuteError, I observe.... I will try to make my failure independent of "ManagableIndex" and then file a bug report. -- Dieter
On Jan 7, 2008, at 2:35 PM, Dieter Maurer wrote:
Dieter Maurer wrote at 2008-1-7 17:55 +0100:
Yesterday, I released "dm.zdoc" and today I find problems.
The analysis revealed:
The class "webdav.EtagSupport.EtagSupport" has initially no attributes "__provides__" and "__providedBy__".
For still unknown reasons, it suddenly gets these attributes. "__provides__" is a "zope.interface.declarations.ClassProvides". Therefore, I expect that Zope 3 or "five" is responsible for these additions.
"EtagSupport" is in the mro of "ManagableIndex". But nevertheless, "ManagableIndex.__provides__" results in an "AttributeError".
Here is a transscript reproducing the problem:
import App.FindHomes from webdav.EtagSupport import EtagSupport EtagSupport.__provides__ Traceback (most recent call last): File "<stdin>", line 1, in ? AttributeError: class EtagSupport has no attribute '__provides__' from Products.ManagableIndex.ManagableIndex import ManagableIndex /usr/local/lib/python24.zip/whrandom.py:38: DeprecationWarning: the whrandom module is deprecated; please use the random module DeprecationWarning) EtagSupport.__provides__ <zope.interface.declarations.ClassProvides object at 0x40b5566c> ManagableIndex.__provides__ Traceback (most recent call last): File "<stdin>", line 1, in ? AttributeError: __provides__ from inspect import getmro EtagSupport in getmro(ManagableIndex) True
Any ideas?
I think I understand the behavior -- and I think it is a "zope.interface" bug.
No, it is intended behavior.
Under some circumstances "zope.interface" adds a "__provides__" descriptor to a class. The descriptor is implemented in "zope/interface/_zope_interface_coptimizations.c" and called "CPB_descr_get".
While "__implements__" is inherited by derived classes, the inherited "__provides__" refuses to work for a derived class and raises "AttributeError: __provides__" instead, the AttriuteError, I observe....
That is intentional.
I will try to make my failure independent of "ManagableIndex" and then file a bug report.
I'm unclear why this caused a problem for you. You never said, afaict, what actually broke for you. What expectation did you have that is unsatisfied? My main gripe with the way this works is that classes get mutated. If I ever redo this someday, I'd use a data structure external to the classes. Modifying the classes was a mistake. Jim -- Jim Fulton Zope Corporation
Hello Jim, Jim Fulton wrote at 2008-1-7 15:15 -0500:
....
I think I understand the behavior -- and I think it is a "zope.interface" bug.
No, it is intended behavior.
Why?
...
Under some circumstances "zope.interface" adds a "__provides__" descriptor to a class. The descriptor is implemented in "zope/interface/_zope_interface_coptimizations.c" and called "CPB_descr_get".
While "__implements__" is inherited by derived classes, the inherited "__provides__" refuses to work for a derived class and raises "AttributeError: __provides__" instead, the AttriuteError, I observe....
That is intentional.
If "__implements__" is inherited, why is "__provides__" not inherited?
I will try to make my failure independent of "ManagableIndex" and then file a bug report.
I'm unclear why this caused a problem for you. You never said, afaict, what actually broke for you. What expectation did you have that is unsatisfied?
"inspect" does no longer work reliably. "inspect.getmembers" and "inspect.classify_class_attrs" require that for each "name" in "dir(cls)" "getattr(cls, name)" does not raise an exception. This fails for classes magically stuffed with a "__provides__" descriptor. As a consequence, "pydoc" (which sits on top of inspect) fails -- and therefore "dm.zdoc".
My main gripe with the way this works is that classes get mutated. If I ever redo this someday, I'd use a data structure external to the classes. Modifying the classes was a mistake.
Yes. That, too, would have avoided the bug. -- Dieter
On Jan 7, 2008, at 3:54 PM, Dieter Maurer wrote:
...
Under some circumstances "zope.interface" adds a "__provides__" descriptor to a class. The descriptor is implemented in "zope/interface/_zope_interface_coptimizations.c" and called "CPB_descr_get".
While "__implements__" is inherited by derived classes, the inherited "__provides__" refuses to work for a derived class and raises "AttributeError: __provides__" instead, the AttriuteError, I observe....
That is intentional.
If "__implements__" is inherited, why is "__provides__" not inherited?
__provides__ (in this context) is a class attribute. I don't support (and don't want to support) inheritance between class objects.
I will try to make my failure independent of "ManagableIndex" and then file a bug report.
I'm unclear why this caused a problem for you. You never said, afaict, what actually broke for you. What expectation did you have that is unsatisfied?
"inspect" does no longer work reliably.
I expected as much. inspect is broken.
"inspect.getmembers" and "inspect.classify_class_attrs" require that for each "name" in "dir(cls)" "getattr(cls, name)" does not raise an exception.
This fails for classes magically stuffed with a "__provides__" descriptor.
It also fails for any descriptor that sometimes raises attribute errors. Someone should report this as an inspect bug. This would be so easy to fix.
As a consequence, "pydoc" (which sits on top of inspect) fails -- and therefore "dm.zdoc".
That's what you get for building on a broken foundation. I suggest monkey-fixing inspect.getmembers. This is a small function that should be easy to replace with a non-broken version.
My main gripe with the way this works is that classes get mutated. If I ever redo this someday, I'd use a data structure external to the classes. Modifying the classes was a mistake.
Yes. That, too, would have avoided the bug.
Yes, it would have avoided the inspect bug. IMO, it would also have been cleaner. If someone wants to volunteer to change it, I'll try to provide some oversight. Unfortunately, it's not a small task, which is why I'm not volunteering to do it. Jim -- Jim Fulton Zope Corporation
Jim Fulton wrote at 2008-1-7 16:04 -0500:
...
If "__implements__" is inherited, why is "__provides__" not inherited?
__provides__ (in this context) is a class attribute. I don't support (and don't want to support) inheritance between class objects.
Where can I read about the "__provides__" semantics? Where is it documented? Python does support class attribute inheritance as can be seen by this small transscript:
class C(object): x=1 # class attribute "x" ... class CD(C): pass ... CD.x # class attribute "x" inherited by "CD" 1
Why do you think that "zope.interface" should not support class attribute inheritance.
....
This fails for classes magically stuffed with a "__provides__" descriptor.
It also fails for any descriptor that sometimes raises attribute errors. Someone should report this as an inspect bug. This would be so easy to fix.
True -- but if they are not far more ready to admit a bug, there is little chance that this gets fixed.
.... I suggest monkey-fixing inspect.getmembers. This is a small function that should be easy to replace with a non-broken version.
This is already done. "dm.reuse" allows in many cases to fix functions without code duplication. Nevertheless, I am convinced to face a bug both in "zope.interface" as well as in "inspect".
....
My main gripe with the way this works is that classes get mutated. If I ever redo this someday, I'd use a data structure external to the classes. Modifying the classes was a mistake.
Yes. That, too, would have avoided the bug.
Yes, it would have avoided the inspect bug. IMO, it would also have been cleaner. If someone wants to volunteer to change it, I'll try to provide some oversight. Unfortunately, it's not a small task, which is why I'm not volunteering to do it.
You probably have already a notion about the semantics of "__provides__". If someone else should change anything with it, he will need a precise understanding what "__provides__" means, which properties is has and which not. Moreover, backward compatibility needs to be taken into account. When "__provides__" stops to be an ill behaving class attribute, then this obviously is a change in behavior. -- Dieter
Jim Fulton wrote at 2008-1-7 16:04 -0500:
...
"inspect.getmembers" and "inspect.classify_class_attrs" require that for each "name" in "dir(cls)" "getattr(cls, name)" does not raise an exception.
This fails for classes magically stuffed with a "__provides__" descriptor.
It also fails for any descriptor that sometimes raises attribute errors. Someone should report this as an inspect bug.
I filed a bug report for "zope.interface" and for "inspect" ("http://bugs.python.org/issue1785") -- Dieter
On Jan 10, 2008, at 12:44 PM, Dieter Maurer wrote:
Jim Fulton wrote at 2008-1-7 16:04 -0500:
...
"inspect.getmembers" and "inspect.classify_class_attrs" require that for each "name" in "dir(cls)" "getattr(cls, name)" does not raise an exception.
This fails for classes magically stuffed with a "__provides__" descriptor.
It also fails for any descriptor that sometimes raises attribute errors. Someone should report this as an inspect bug.
I filed a bug report for "zope.interface" and for "inspect" ("http://bugs.python.org/issue1785")
Much thanks! Jim -- Jim Fulton Zope Corporation
participants (2)
-
Dieter Maurer -
Jim Fulton