-
Notifications
You must be signed in to change notification settings - Fork 69
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
Add more common interfaces #175
Conversation
This still leaves classes in control of what interfaces they implement, unlike the virtual duck-typed subclassing of ABCs, as described in #135 It gets us most of the way there, though. If we want to do it, it's now pretty easy with a small change to the definition of -------------------------------------------------------------------------------------------------
modified: src/zope/interface/declarations.py
-------------------------------------------------------------------------------------------------
@@ -275,6 +275,27 @@ def _implements_name(ob):
return (getattr(ob, '__module__', '?') or '?') + \
'.' + (getattr(ob, '__name__', '?') or '?')
+def _abc_interfaces():
+ try:
+ from zope.interface.common import ABCInterface, ABCInterfaceClass
+ except ImportError:
+ return [] # Circular imports at _wire() time.
+ from zope.interface.common import collections, numbers, io # Ensure defined
+
+ seen = set()
+ to_examine = list(ABCInterface.dependents)
+ while to_examine:
+ iface = to_examine.pop()
+ if iface in seen:
+ continue
+ seen.add(iface)
+ to_examine.extend(iface.dependents)
+ return [x for x in seen if isinstance(x, ABCInterfaceClass)]
+
+def _abc_interfaces_of(cls):
+ ifaces = _abc_interfaces()
+
+ return [iface for iface in ifaces if issubclass(cls, iface.getABC())]
@_use_c_impl
def implementedBy(cls):
@@ -338,7 +359,8 @@ def implementedBy(cls):
raise TypeError("ImplementedBy called for non-factory", cls)
bases = ()
- spec = Implements.named(spec_name, *[implementedBy(c) for c in bases])
+ spec = Implements.named(spec_name,
+ *([implementedBy(c) for c in bases] + _abc_interfaces_of(cls)))
spec.inherit = cls
try: With that change, classes that "subclass" ABCs automatically also provide those interfaces: >>> from zope.interface.common import collections
>>> class Sized(object):
...: def __len__(self): return 0
...:
>>> from zope.interface import providedBy
>>> list(providedBy(Sized()))
[<ABCInterfaceClass zope.interface.common.collections.IHashable>,
<ABCInterfaceClass zope.interface.common.collections.ISized>] That's a rough approximation, of course. The biggest issue is later registrations and cache invalidations. E.g., this doesn't do what you'd expect: >>> class VirtualSized(object):
... pass
...
>>> list(providedBy(VirtualSized()))
[<ABCInterfaceClass zope.interface.common.collections.IHashable>]
>>> from collections.abc import Sized
>>> Sized.register(VirtualSized)
<class '__main__.VirtualSized'>
>>> isinstance(VirtualSized(), Sized)
True
>>> list(providedBy(VirtualSized()))
[<ABCInterfaceClass zope.interface.common.collections.IHashable>] I feel like that's solvable, though. Is that something we want to proceed with? I'm not sure I personally have a defined use-case for it right now, but OTOH, I think I remember writing things like |
Overall this looks fine. I must admit, I can not judge every detail. |
Register implemented standard library types on import. Derive the interface methods and documentation from the ABC automatically. I hope to use this for numbers too. Part of #138
…on about ABCs and builtins. bytearray turns out to violate that.
…g and sequence interfaces.
Thanks for the feedback! |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
LGTM, but maybe wait for @mgedmin review or some other experienced dev!
This is rather a big diff and I'm not feeling up to reviewing it right now. (Lack of review from little old me should not be a blocker to merging!) |
No worries! Thank you. I will go ahead and merge as I'd like to make a release soon. Since it's completely opt-in I don't think it can do any harm. |
Derived automatically from Python stdlib ABCs.
When done, this will fix #138.
So far, its just the collection classes. Remaining items:
ByteString
numbers
ABCsIText
and whatever else is missing fromdolmen.builtins