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

verifyObject doesn't correctly work on classes with classProvides #15

Open
tseaver opened this issue Jan 12, 2015 · 1 comment
Open
Labels

Comments

@tseaver
Copy link
Member

tseaver commented Jan 12, 2015

In https://bugs.launchpad.net/zope.interface/+bug/675424, Christian Zagrodnik reported:

When for instance declaring a factory classProvides is handy at times:

>>> import zope.interface
>>> import zope.interface.verify
>>>
>>> class IFoo(zope.interface.Interface):
...     def __call__(arg):
...         pass
...
>>> class FooOkay(object):
...     zope.interface.classProvides(IFoo)
...     def __init__(self, arg):
...         pass
...
>>> zope.interface.verify.verifyObject(IFoo, FooOkay)
True

That's was working.

The next case should raise an error, but doesn't. IFoo requires an arg to be passed which the following class doesn't implement:

>>> class FooVerifiedByNotLikeSpec(object):
...     zope.interface.classProvides(IFoo)
...
>>> zope.interface.verify.verifyObject(IFoo, FooVerifiedByNotLikeSpec)
True

The next case should actually pass but doesn't.

>>> class FooBroken(object):
...     zope.interface.classProvides(IFoo)
...     def __init__(self, arg):
...         pass
...     def __call__(self):
...         pass
...
>>> zope.interface.verify.verifyObject(IFoo, FooBroken)
Traceback (most recent call last):
File "<console>", line 1, in <module>
File "/Users/zagy/development/eggs/zope.interface-3.6.1-py2.7-macosx-10.6-x86_64.egg/zope/interface/verify.py", line 102, in verifyObject
    return _verify(iface, candidate, tentative, vtype='o')
File "/Users/zagy/development/eggs/zope.interface-3.6.1-py2.7-macosx-10.6-x86_64.egg/zope/interface/verify.py", line 94, in _verify
    raise BrokenMethodImplementation(name, mess)
BrokenMethodImplementation: The implementation of __call__ violates its contract
        because implementation doesn't allow enough arguments.

Apparently verifyObject doesn't take any special care for classes which proivde an interface.

@tseaver tseaver added the bug label Jan 12, 2015
@mjpieters
Copy link
Member

mjpieters commented Feb 28, 2018

This is not a trivial problem. What's happening is that verification doesn't take special method lookup into account. How should interfaces handle special methods, like __add__ and __contains__? These methods can never be directly provided, really, (except for modules, which as of Python 3.7 can directly provide __dir__ and __getattr__ functions).

And for classes without a more specific metaclass than type, it could be argued that they could only ever "directly provide" __call__(*args, **kwargs), never something more specific. That the type.__call__() method used for ClassObj() invokes __new__ and, optionally, __new__, is an implementation detail that verifyObject can't be expected to handle.

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

No branches or pull requests

2 participants