Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

list(ProxyFactory(schema)) does not work on Python 3 #141

Closed
mgedmin opened this issue Jul 9, 2019 · 1 comment · Fixed by zopefoundation/zope.security#69
Closed

list(ProxyFactory(schema)) does not work on Python 3 #141

mgedmin opened this issue Jul 9, 2019 · 1 comment · Fixed by zopefoundation/zope.security#69

Comments

@mgedmin
Copy link
Member

mgedmin commented Jul 9, 2019

This code works on Python 2.7:

>>> from zope.interface import Interface
>>> from zope.security.proxy import ProxyFactory
>>> class IFoo(Interface):
...     def x(): 'an method'
...
>>> list(IFoo)
['x']
>>> list(ProxyFactory(IFoo))
['x']

It breaks on Python 3:

>>> list(IFoo)
['x']
>>> list(ProxyFactory(IFoo))
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
zope.security.interfaces.ForbiddenAttribute: ('__len__', <InterfaceClass __main__.IFoo>)

AFAICT the reason is that Python's list(an_object) tries to compute len(an_object) as an optimization (to preallocate all the list entries in one go). Python 2 ignores exceptions raised by an_object.__class__.__len__(an_object) when they're an AttributeError subclass and merely skips the optimization. Python 3 does not suppress the exception but instead fails the entire operation.

It's a bit more subtle than that, e.g. if a class doesn't have a __len__, then list() on instances of that class succeeds, but if the class has a __len__ that does raise AttributeError, then list() on instances of that class fails (on Python 3).

I'm not sure if this is a problem in zope.interface or in zope.security. The simplest solution would be to allow __len__ on Interface objects.

@jamadden
Copy link
Member

jamadden commented Jul 9, 2019

I suspect the fix belongs in zope.security. There have been other zope.interface-on-Python3 fixes necessary there, specifically around iteration and length hints (and also for BTrees) (e.g., zopefoundation/zope.security@6f8de03)

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging a pull request may close this issue.

2 participants