zope.interface
zope.interface copied to clipboard
verifyObject doesn't verify keyword arguments
Given the following:
class IFoo(zope.interface.Interface):
def bar(lorem="ipsum", alice=42):
""" ... """
@zope.interface.implementer(IFoo)
class Foo():
def bar(self, x=666, y=99):
return x + y
I would have expected verification to fail but it doesn't:
>>> zope.interface.verify.verifyObject(IFoo, Foo())
True
How can I force verifyObject
to verify the function signature exactly? So that it it is exactly the same (same positional and keyword arguments with same names in same order and also the same *args
and **kwargs
).
Jaakko Luttinen wrote at 2019-6-14 08:06 -0700:
Given the following:
class IFoo(zope.interface.Interface): def bar(lorem="ipsum", alice=42): """ ... """ @zope.interface.implementer(IFoo) class Foo(): def bar(self, x=666, y=99): return x + y
I would have expected verification to fail but it doesn't:
>>> zope.interface.verify.verifyObject(IFoo, Foo()) True
How can I force
verifyObject
to verify the function signature exactly? So that it it is exactly the same (same positional and keyword arguments with same names in same order and also the same*args
and**kwargs
).
A paramter definition of the form param=value can mean two things:
- param is a positional parameter with default value value
- param is a keyword argument
For case 1, the parameter name has no importance (as positional parameters are identified via position, not via name).
zope.interface
cannot separate those two cases --
Python has only learned recently (Python 3+) to distinguish
between those cases and zope.interface
predates this.
Because zope.interface
cannot distinguish the cases, it is permissive
(i.e. does not check the names).
You will need your own verification in order to get the names checked.
To help with its definition, you could make use of dm.reuse.rebindFunction
(you find dm.reuse
on PyPI): it allows you to reuse a
function definition (_verify
, verifyClass
and verifyObject
, all
from zope.interface.verify
, in this case) and change some of its
"globals" (in your case _incompat
and _verify
).
In your version of _incompat
you would check in addition the parameter
names.
For a clean solution, zope.interface
would need to learn how
to differentiate between a positional argument with default value
and a true keyword argument and check the names for the latter.
See #63 for some details. Maybe at least some parts of the issue can be fixed via a PR.
See #63 for some details. Maybe at least some parts of the issue can be fixed via a PR.
Will zope.interface
drop Python 2 support soon?
After there is only Python 3, zope.interface
should (of course) support Python 3's new keyword only arguments (and for them check that they do not change names).
I am against checking the names of positional arguments - whether with or without toggle: a positional argument is defined by its position not by its name. If I want an argument defined by name, I use a keyword only argument (provided I can do this because I support only Python 3).
From 2020-01-01 on there is no need to support Python 2.7 any more. (People needing Python 2 support can still use older package versions.)