Coverage for /home/martinb/.local/share/virtualenvs/camcops/lib/python3.6/site-packages/zope/interface/interface.py : 56%

Hot-keys on this page
r m x p toggle line displays
j k next/prev highlighted chunk
0 (zero) top of page
1 (one) first highlighted chunk
1##############################################################################
2#
3# Copyright (c) 2001, 2002 Zope Foundation and Contributors.
4# All Rights Reserved.
5#
6# This software is subject to the provisions of the Zope Public License,
7# Version 2.1 (ZPL). A copy of the ZPL should accompany this distribution.
8# THIS SOFTWARE IS PROVIDED "AS IS" AND ANY AND ALL EXPRESS OR IMPLIED
9# WARRANTIES ARE DISCLAIMED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
10# WARRANTIES OF TITLE, MERCHANTABILITY, AGAINST INFRINGEMENT, AND FITNESS
11# FOR A PARTICULAR PURPOSE.
12#
13##############################################################################
14"""Interface object implementation
15"""
16# pylint:disable=protected-access
17import sys
18from types import MethodType
19from types import FunctionType
20import weakref
22from zope.interface._compat import _use_c_impl
23from zope.interface._compat import PYTHON2 as PY2
24from zope.interface.exceptions import Invalid
25from zope.interface.ro import ro as calculate_ro
26from zope.interface import ro
28__all__ = [
29 # Most of the public API from this module is directly exported
30 # from zope.interface. The only remaining public API intended to
31 # be imported from here should be those few things documented as
32 # such.
33 'InterfaceClass',
34 'Specification',
35 'adapter_hooks',
36]
38CO_VARARGS = 4
39CO_VARKEYWORDS = 8
40# Put in the attrs dict of an interface by ``taggedValue`` and ``invariants``
41TAGGED_DATA = '__interface_tagged_values__'
42# Put in the attrs dict of an interface by ``interfacemethod``
43INTERFACE_METHODS = '__interface_methods__'
45_decorator_non_return = object()
46_marker = object()
50def invariant(call):
51 f_locals = sys._getframe(1).f_locals
52 tags = f_locals.setdefault(TAGGED_DATA, {})
53 invariants = tags.setdefault('invariants', [])
54 invariants.append(call)
55 return _decorator_non_return
58def taggedValue(key, value):
59 """Attaches a tagged value to an interface at definition time."""
60 f_locals = sys._getframe(1).f_locals
61 tagged_values = f_locals.setdefault(TAGGED_DATA, {})
62 tagged_values[key] = value
63 return _decorator_non_return
66class Element(object):
67 """
68 Default implementation of `zope.interface.interfaces.IElement`.
69 """
71 # We can't say this yet because we don't have enough
72 # infrastructure in place.
73 #
74 #implements(IElement)
76 def __init__(self, __name__, __doc__=''): # pylint:disable=redefined-builtin
77 if not __doc__ and __name__.find(' ') >= 0:
78 __doc__ = __name__
79 __name__ = None
81 self.__name__ = __name__
82 self.__doc__ = __doc__
83 # Tagged values are rare, especially on methods or attributes.
84 # Deferring the allocation can save substantial memory.
85 self.__tagged_values = None
87 def getName(self):
88 """ Returns the name of the object. """
89 return self.__name__
91 def getDoc(self):
92 """ Returns the documentation for the object. """
93 return self.__doc__
95 ###
96 # Tagged values.
97 #
98 # Direct tagged values are set only in this instance. Others
99 # may be inherited (for those subclasses that have that concept).
100 ###
102 def getTaggedValue(self, tag):
103 """ Returns the value associated with 'tag'. """
104 if not self.__tagged_values:
105 raise KeyError(tag)
106 return self.__tagged_values[tag]
108 def queryTaggedValue(self, tag, default=None):
109 """ Returns the value associated with 'tag'. """
110 return self.__tagged_values.get(tag, default) if self.__tagged_values else default
112 def getTaggedValueTags(self):
113 """ Returns a collection of all tags. """
114 return self.__tagged_values.keys() if self.__tagged_values else ()
116 def setTaggedValue(self, tag, value):
117 """ Associates 'value' with 'key'. """
118 if self.__tagged_values is None:
119 self.__tagged_values = {}
120 self.__tagged_values[tag] = value
122 queryDirectTaggedValue = queryTaggedValue
123 getDirectTaggedValue = getTaggedValue
124 getDirectTaggedValueTags = getTaggedValueTags
127SpecificationBasePy = object # filled by _use_c_impl.
130@_use_c_impl
131class SpecificationBase(object):
132 # This object is the base of the inheritance hierarchy for ClassProvides:
133 #
134 # ClassProvides < ClassProvidesBase, Declaration
135 # Declaration < Specification < SpecificationBase
136 # ClassProvidesBase < SpecificationBase
137 #
138 # In order to have compatible instance layouts, we need to declare
139 # the storage used by Specification and Declaration here (and
140 # those classes must have ``__slots__ = ()``); fortunately this is
141 # not a waste of space because those are the only two inheritance
142 # trees. These all translate into tp_members in C.
143 __slots__ = (
144 # Things used here.
145 '_implied',
146 # Things used in Specification.
147 '_dependents',
148 '_bases',
149 '_v_attrs',
150 '__iro__',
151 '__sro__',
152 '__weakref__',
153 )
155 def providedBy(self, ob):
156 """Is the interface implemented by an object
157 """
158 spec = providedBy(ob)
159 return self in spec._implied
161 def implementedBy(self, cls):
162 """Test whether the specification is implemented by a class or factory.
164 Raise TypeError if argument is neither a class nor a callable.
165 """
166 spec = implementedBy(cls)
167 return self in spec._implied
169 def isOrExtends(self, interface):
170 """Is the interface the same as or extend the given interface
171 """
172 return interface in self._implied # pylint:disable=no-member
174 __call__ = isOrExtends
177class NameAndModuleComparisonMixin(object):
178 # Internal use. Implement the basic sorting operators (but not (in)equality
179 # or hashing). Subclasses must provide ``__name__`` and ``__module__``
180 # attributes. Subclasses will be mutually comparable; but because equality
181 # and hashing semantics are missing from this class, take care in how
182 # you define those two attributes: If you stick with the default equality
183 # and hashing (identity based) you should make sure that all possible ``__name__``
184 # and ``__module__`` pairs are unique ACROSS ALL SUBCLASSES. (Actually, pretty
185 # much the same thing goes if you define equality and hashing to be based on
186 # those two attributes: they must still be consistent ACROSS ALL SUBCLASSES.)
188 # pylint:disable=assigning-non-slot
189 __slots__ = ()
191 def _compare(self, other):
192 """
193 Compare *self* to *other* based on ``__name__`` and ``__module__``.
195 Return 0 if they are equal, return 1 if *self* is
196 greater than *other*, and return -1 if *self* is less than
197 *other*.
199 If *other* does not have ``__name__`` or ``__module__``, then
200 return ``NotImplemented``.
202 .. caution::
203 This allows comparison to things well outside the type hierarchy,
204 perhaps not symmetrically.
206 For example, ``class Foo(object)`` and ``class Foo(Interface)``
207 in the same file would compare equal, depending on the order of
208 operands. Writing code like this by hand would be unusual, but it could
209 happen with dynamic creation of types and interfaces.
211 None is treated as a pseudo interface that implies the loosest
212 contact possible, no contract. For that reason, all interfaces
213 sort before None.
214 """
215 if other is self:
216 return 0
218 if other is None:
219 return -1
221 n1 = (self.__name__, self.__module__)
222 try:
223 n2 = (other.__name__, other.__module__)
224 except AttributeError:
225 return NotImplemented
227 # This spelling works under Python3, which doesn't have cmp().
228 return (n1 > n2) - (n1 < n2)
230 def __lt__(self, other):
231 c = self._compare(other)
232 if c is NotImplemented:
233 return c
234 return c < 0
236 def __le__(self, other):
237 c = self._compare(other)
238 if c is NotImplemented:
239 return c
240 return c <= 0
242 def __gt__(self, other):
243 c = self._compare(other)
244 if c is NotImplemented:
245 return c
246 return c > 0
248 def __ge__(self, other):
249 c = self._compare(other)
250 if c is NotImplemented:
251 return c
252 return c >= 0
255@_use_c_impl
256class InterfaceBase(NameAndModuleComparisonMixin, SpecificationBasePy):
257 """Base class that wants to be replaced with a C base :)
258 """
260 __slots__ = (
261 '__name__',
262 '__ibmodule__',
263 '_v_cached_hash',
264 )
266 def __init__(self, name=None, module=None):
267 self.__name__ = name
268 self.__ibmodule__ = module
270 def _call_conform(self, conform):
271 raise NotImplementedError
273 @property
274 def __module_property__(self):
275 # This is for _InterfaceMetaClass
276 return self.__ibmodule__
278 def __call__(self, obj, alternate=_marker):
279 """Adapt an object to the interface
280 """
281 try:
282 conform = obj.__conform__
283 except AttributeError:
284 conform = None
286 if conform is not None:
287 adapter = self._call_conform(conform)
288 if adapter is not None:
289 return adapter
291 adapter = self.__adapt__(obj)
293 if adapter is not None:
294 return adapter
295 if alternate is not _marker:
296 return alternate
297 raise TypeError("Could not adapt", obj, self)
299 def __adapt__(self, obj):
300 """Adapt an object to the receiver
301 """
302 if self.providedBy(obj):
303 return obj
305 for hook in adapter_hooks:
306 adapter = hook(self, obj)
307 if adapter is not None:
308 return adapter
310 return None
312 def __hash__(self):
313 # pylint:disable=assigning-non-slot,attribute-defined-outside-init
314 try:
315 return self._v_cached_hash
316 except AttributeError:
317 self._v_cached_hash = hash((self.__name__, self.__module__))
318 return self._v_cached_hash
320 def __eq__(self, other):
321 c = self._compare(other)
322 if c is NotImplemented:
323 return c
324 return c == 0
326 def __ne__(self, other):
327 if other is self:
328 return False
330 c = self._compare(other)
331 if c is NotImplemented:
332 return c
333 return c != 0
335adapter_hooks = _use_c_impl([], 'adapter_hooks')
338class Specification(SpecificationBase):
339 """Specifications
341 An interface specification is used to track interface declarations
342 and component registrations.
344 This class is a base class for both interfaces themselves and for
345 interface specifications (declarations).
347 Specifications are mutable. If you reassign their bases, their
348 relations with other specifications are adjusted accordingly.
349 """
350 __slots__ = ()
352 # The root of all Specifications. This will be assigned `Interface`,
353 # once it is defined.
354 _ROOT = None
356 # Copy some base class methods for speed
357 isOrExtends = SpecificationBase.isOrExtends
358 providedBy = SpecificationBase.providedBy
360 def __init__(self, bases=()):
361 # There are many leaf interfaces with no dependents,
362 # and a few with very many. It's a heavily left-skewed
363 # distribution. In a survey of Plone and Zope related packages
364 # that loaded 2245 InterfaceClass objects and 2235 ClassProvides
365 # instances, there were a total of 7000 Specification objects created.
366 # 4700 had 0 dependents, 1400 had 1, 382 had 2 and so on. Only one
367 # for <type> had 1664. So there's savings to be had deferring
368 # the creation of dependents.
369 self._dependents = None # type: weakref.WeakKeyDictionary
370 self._bases = ()
371 self._implied = {}
372 self._v_attrs = None
373 self.__iro__ = ()
374 self.__sro__ = ()
376 self.__bases__ = tuple(bases)
378 @property
379 def dependents(self):
380 if self._dependents is None:
381 self._dependents = weakref.WeakKeyDictionary()
382 return self._dependents
384 def subscribe(self, dependent):
385 self._dependents[dependent] = self.dependents.get(dependent, 0) + 1
387 def unsubscribe(self, dependent):
388 try:
389 n = self._dependents[dependent]
390 except TypeError:
391 raise KeyError(dependent)
392 n -= 1
393 if not n:
394 del self.dependents[dependent]
395 else:
396 assert n > 0
397 self.dependents[dependent] = n
399 def __setBases(self, bases):
400 # Remove ourselves as a dependent of our old bases
401 for b in self.__bases__:
402 b.unsubscribe(self)
404 # Register ourselves as a dependent of our new bases
405 self._bases = bases
406 for b in bases:
407 b.subscribe(self)
409 self.changed(self)
411 __bases__ = property(
412 lambda self: self._bases,
413 __setBases,
414 )
416 # This method exists for tests to override the way we call
417 # ro.calculate_ro(), usually by adding extra kwargs. We don't
418 # want to have a mutable dictionary as a class member that we pass
419 # ourself because mutability is bad, and passing **kw is slower than
420 # calling the bound function.
421 _do_calculate_ro = calculate_ro
423 def _calculate_sro(self):
424 """
425 Calculate and return the resolution order for this object, using its ``__bases__``.
427 Ensures that ``Interface`` is always the last (lowest priority) element.
428 """
429 # We'd like to make Interface the lowest priority as a
430 # property of the resolution order algorithm. That almost
431 # works out naturally, but it fails when class inheritance has
432 # some bases that DO implement an interface, and some that DO
433 # NOT. In such a mixed scenario, you wind up with a set of
434 # bases to consider that look like this: [[..., Interface],
435 # [..., object], ...]. Depending on the order of inheritance,
436 # Interface can wind up before or after object, and that can
437 # happen at any point in the tree, meaning Interface can wind
438 # up somewhere in the middle of the order. Since Interface is
439 # treated as something that everything winds up implementing
440 # anyway (a catch-all for things like adapters), having it high up
441 # the order is bad. It's also bad to have it at the end, just before
442 # some concrete class: concrete classes should be HIGHER priority than
443 # interfaces (because there's only one class, but many implementations).
444 #
445 # One technically nice way to fix this would be to have
446 # ``implementedBy(object).__bases__ = (Interface,)``
447 #
448 # But: (1) That fails for old-style classes and (2) that causes
449 # everything to appear to *explicitly* implement Interface, when up
450 # to this point it's been an implicit virtual sort of relationship.
451 #
452 # So we force the issue by mutating the resolution order.
454 # Note that we let C3 use pre-computed __sro__ for our bases.
455 # This requires that by the time this method is invoked, our bases
456 # have settled their SROs. Thus, ``changed()`` must first
457 # update itself before telling its descendents of changes.
458 sro = self._do_calculate_ro(base_mros={
459 b: b.__sro__
460 for b in self.__bases__
461 })
462 root = self._ROOT
463 if root is not None and sro and sro[-1] is not root:
464 # In one dataset of 1823 Interface objects, 1117 ClassProvides objects,
465 # sro[-1] was root 4496 times, and only not root 118 times. So it's
466 # probably worth checking.
468 # Once we don't have to deal with old-style classes,
469 # we can add a check and only do this if base_count > 1,
470 # if we tweak the bootstrapping for ``<implementedBy object>``
471 sro = [
472 x
473 for x in sro
474 if x is not root
475 ]
476 sro.append(root)
478 return sro
480 def changed(self, originally_changed):
481 """
482 We, or something we depend on, have changed.
484 By the time this is called, the things we depend on,
485 such as our bases, should themselves be stable.
486 """
487 self._v_attrs = None
489 implied = self._implied
490 implied.clear()
492 ancestors = self._calculate_sro()
493 self.__sro__ = tuple(ancestors)
494 self.__iro__ = tuple([ancestor for ancestor in ancestors
495 if isinstance(ancestor, InterfaceClass)
496 ])
498 for ancestor in ancestors:
499 # We directly imply our ancestors:
500 implied[ancestor] = ()
502 # Now, advise our dependents of change
503 # (being careful not to create the WeakKeyDictionary if not needed):
504 for dependent in tuple(self._dependents.keys() if self._dependents else ()):
505 dependent.changed(originally_changed)
507 # Just in case something called get() at some point
508 # during that process and we have a cycle of some sort
509 # make sure we didn't cache incomplete results.
510 self._v_attrs = None
512 def interfaces(self):
513 """Return an iterator for the interfaces in the specification.
514 """
515 seen = {}
516 for base in self.__bases__:
517 for interface in base.interfaces():
518 if interface not in seen:
519 seen[interface] = 1
520 yield interface
522 def extends(self, interface, strict=True):
523 """Does the specification extend the given interface?
525 Test whether an interface in the specification extends the
526 given interface
527 """
528 return ((interface in self._implied)
529 and
530 ((not strict) or (self != interface))
531 )
533 def weakref(self, callback=None):
534 return weakref.ref(self, callback)
536 def get(self, name, default=None):
537 """Query for an attribute description
538 """
539 attrs = self._v_attrs
540 if attrs is None:
541 attrs = self._v_attrs = {}
542 attr = attrs.get(name)
543 if attr is None:
544 for iface in self.__iro__:
545 attr = iface.direct(name)
546 if attr is not None:
547 attrs[name] = attr
548 break
550 return default if attr is None else attr
553class _InterfaceMetaClass(type):
554 # Handling ``__module__`` on ``InterfaceClass`` is tricky. We need
555 # to be able to read it on a type and get the expected string. We
556 # also need to be able to set it on an instance and get the value
557 # we set. So far so good. But what gets tricky is that we'd like
558 # to store the value in the C structure (``InterfaceBase.__ibmodule__``) for
559 # direct access during equality, sorting, and hashing. "No
560 # problem, you think, I'll just use a property" (well, the C
561 # equivalents, ``PyMemberDef`` or ``PyGetSetDef``).
562 #
563 # Except there is a problem. When a subclass is created, the
564 # metaclass (``type``) always automatically puts the expected
565 # string in the class's dictionary under ``__module__``, thus
566 # overriding the property inherited from the superclass. Writing
567 # ``Subclass.__module__`` still works, but
568 # ``Subclass().__module__`` fails.
569 #
570 # There are multiple ways to work around this:
571 #
572 # (1) Define ``InterfaceBase.__getattribute__`` to watch for
573 # ``__module__`` and return the C storage.
574 #
575 # This works, but slows down *all* attribute access (except,
576 # ironically, to ``__module__``) by about 25% (40ns becomes 50ns)
577 # (when implemented in C). Since that includes methods like
578 # ``providedBy``, that's probably not acceptable.
579 #
580 # All the other methods involve modifying subclasses. This can be
581 # done either on the fly in some cases, as instances are
582 # constructed, or by using a metaclass. These next few can be done on the fly.
583 #
584 # (2) Make ``__module__`` a descriptor in each subclass dictionary.
585 # It can't be a straight up ``@property`` descriptor, though, because accessing
586 # it on the class returns a ``property`` object, not the desired string.
587 #
588 # (3) Implement a data descriptor (``__get__`` and ``__set__``)
589 # that is both a subclass of string, and also does the redirect of
590 # ``__module__`` to ``__ibmodule__`` and does the correct thing
591 # with the ``instance`` argument to ``__get__`` is None (returns
592 # the class's value.) (Why must it be a subclass of string? Because
593 # when it' s in the class's dict, it's defined on an *instance* of the
594 # metaclass; descriptors in an instance's dict aren't honored --- their
595 # ``__get__`` is never invoked --- so it must also *be* the value we want
596 # returned.)
597 #
598 # This works, preserves the ability to read and write
599 # ``__module__``, and eliminates any penalty accessing other
600 # attributes. But it slows down accessing ``__module__`` of
601 # instances by 200% (40ns to 124ns), requires editing class dicts on the fly
602 # (in InterfaceClass.__init__), thus slightly slowing down all interface creation,
603 # and is ugly.
604 #
605 # (4) As in the last step, but make it a non-data descriptor (no ``__set__``).
606 #
607 # If you then *also* store a copy of ``__ibmodule__`` in
608 # ``__module__`` in the instance's dict, reading works for both
609 # class and instance and is full speed for instances. But the cost
610 # is storage space, and you can't write to it anymore, not without
611 # things getting out of sync.
612 #
613 # (Actually, ``__module__`` was never meant to be writable. Doing
614 # so would break BTrees and normal dictionaries, as well as the
615 # repr, maybe more.)
616 #
617 # That leaves us with a metaclass. (Recall that a class is an
618 # instance of its metaclass, so properties/descriptors defined in
619 # the metaclass are used when accessing attributes on the
620 # instance/class. We'll use that to define ``__module__``.) Here
621 # we can have our cake and eat it too: no extra storage, and
622 # C-speed access to the underlying storage. The only substantial
623 # cost is that metaclasses tend to make people's heads hurt. (But
624 # still less than the descriptor-is-string, hopefully.)
626 __slots__ = ()
628 def __new__(cls, name, bases, attrs):
629 # Figure out what module defined the interface.
630 # This is copied from ``InterfaceClass.__init__``;
631 # reviewers aren't sure how AttributeError or KeyError
632 # could be raised.
633 __module__ = sys._getframe(1).f_globals['__name__']
634 # Get the C optimized __module__ accessor and give it
635 # to the new class.
636 moduledescr = InterfaceBase.__dict__['__module__']
637 if isinstance(moduledescr, str):
638 # We're working with the Python implementation,
639 # not the C version
640 moduledescr = InterfaceBase.__dict__['__module_property__']
641 attrs['__module__'] = moduledescr
642 kind = type.__new__(cls, name, bases, attrs)
643 kind.__module = __module__
644 return kind
646 @property
647 def __module__(cls):
648 return cls.__module
650 def __repr__(cls):
651 return "<class '%s.%s'>" % (
652 cls.__module,
653 cls.__name__,
654 )
657_InterfaceClassBase = _InterfaceMetaClass(
658 'InterfaceClass',
659 # From least specific to most specific.
660 (InterfaceBase, Specification, Element),
661 {'__slots__': ()}
662)
665def interfacemethod(func):
666 """
667 Convert a method specification to an actual method of the interface.
669 This is a decorator that functions like `staticmethod` et al.
671 The primary use of this decorator is to allow interface definitions to
672 define the ``__adapt__`` method, but other interface methods can be
673 overridden this way too.
675 .. seealso:: `zope.interface.interfaces.IInterfaceDeclaration.interfacemethod`
676 """
677 f_locals = sys._getframe(1).f_locals
678 methods = f_locals.setdefault(INTERFACE_METHODS, {})
679 methods[func.__name__] = func
680 return _decorator_non_return
683class InterfaceClass(_InterfaceClassBase):
684 """
685 Prototype (scarecrow) Interfaces Implementation.
687 Note that it is not possible to change the ``__name__`` or ``__module__``
688 after an instance of this object has been constructed.
689 """
691 # We can't say this yet because we don't have enough
692 # infrastructure in place.
693 #
694 #implements(IInterface)
696 def __new__(cls, name=None, bases=(), attrs=None, __doc__=None, # pylint:disable=redefined-builtin
697 __module__=None):
698 assert isinstance(bases, tuple)
699 attrs = attrs or {}
700 needs_custom_class = attrs.pop(INTERFACE_METHODS, None)
701 if needs_custom_class:
702 needs_custom_class.update(
703 {'__classcell__': attrs.pop('__classcell__')}
704 if '__classcell__' in attrs
705 else {}
706 )
707 if '__adapt__' in needs_custom_class:
708 # We need to tell the C code to call this.
709 needs_custom_class['_CALL_CUSTOM_ADAPT'] = 1
711 if issubclass(cls, _InterfaceClassWithCustomMethods):
712 cls_bases = (cls,)
713 elif cls is InterfaceClass:
714 cls_bases = (_InterfaceClassWithCustomMethods,)
715 else:
716 cls_bases = (cls, _InterfaceClassWithCustomMethods)
718 cls = type(cls)( # pylint:disable=self-cls-assignment
719 name + "<WithCustomMethods>",
720 cls_bases,
721 needs_custom_class
722 )
723 elif PY2 and bases and len(bases) > 1:
724 bases_with_custom_methods = tuple(
725 type(b)
726 for b in bases
727 if issubclass(type(b), _InterfaceClassWithCustomMethods)
728 )
730 # If we have a subclass of InterfaceClass in *bases*,
731 # Python 3 is smart enough to pass that as *cls*, but Python
732 # 2 just passes whatever the first base in *bases* is. This means that if
733 # we have multiple inheritance, and one of our bases has already defined
734 # a custom method like ``__adapt__``, we do the right thing automatically
735 # and extend it on Python 3, but not necessarily on Python 2. To fix this, we need
736 # to run the MRO algorithm and get the most derived base manually.
737 # Note that this only works for consistent resolution orders
738 if bases_with_custom_methods:
739 cls = type( # pylint:disable=self-cls-assignment
740 name + "<WithCustomMethods>",
741 bases_with_custom_methods,
742 {}
743 ).__mro__[1] # Not the class we created, the most derived.
745 return _InterfaceClassBase.__new__(cls)
747 def __init__(self, name, bases=(), attrs=None, __doc__=None, # pylint:disable=redefined-builtin
748 __module__=None):
749 # We don't call our metaclass parent directly
750 # pylint:disable=non-parent-init-called
751 # pylint:disable=super-init-not-called
752 if not all(isinstance(base, InterfaceClass) for base in bases):
753 raise TypeError('Expected base interfaces')
755 if attrs is None:
756 attrs = {}
758 if __module__ is None:
759 __module__ = attrs.get('__module__')
760 if isinstance(__module__, str):
761 del attrs['__module__']
762 else:
763 try:
764 # Figure out what module defined the interface.
765 # This is how cPython figures out the module of
766 # a class, but of course it does it in C. :-/
767 __module__ = sys._getframe(1).f_globals['__name__']
768 except (AttributeError, KeyError): # pragma: no cover
769 pass
771 InterfaceBase.__init__(self, name, __module__)
772 # These asserts assisted debugging the metaclass
773 # assert '__module__' not in self.__dict__
774 # assert self.__ibmodule__ is self.__module__ is __module__
776 d = attrs.get('__doc__')
777 if d is not None:
778 if not isinstance(d, Attribute):
779 if __doc__ is None:
780 __doc__ = d
781 del attrs['__doc__']
783 if __doc__ is None:
784 __doc__ = ''
786 Element.__init__(self, name, __doc__)
788 tagged_data = attrs.pop(TAGGED_DATA, None)
789 if tagged_data is not None:
790 for key, val in tagged_data.items():
791 self.setTaggedValue(key, val)
793 Specification.__init__(self, bases)
794 self.__attrs = self.__compute_attrs(attrs)
796 self.__identifier__ = "%s.%s" % (__module__, name)
798 def __compute_attrs(self, attrs):
799 # Make sure that all recorded attributes (and methods) are of type
800 # `Attribute` and `Method`
801 def update_value(aname, aval):
802 if isinstance(aval, Attribute):
803 aval.interface = self
804 if not aval.__name__:
805 aval.__name__ = aname
806 elif isinstance(aval, FunctionType):
807 aval = fromFunction(aval, self, name=aname)
808 else:
809 raise InvalidInterface("Concrete attribute, " + aname)
810 return aval
812 return {
813 aname: update_value(aname, aval)
814 for aname, aval in attrs.items()
815 if aname not in (
816 # __locals__: Python 3 sometimes adds this.
817 '__locals__',
818 # __qualname__: PEP 3155 (Python 3.3+)
819 '__qualname__',
820 # __annotations__: PEP 3107 (Python 3.0+)
821 '__annotations__',
822 )
823 and aval is not _decorator_non_return
824 }
826 def interfaces(self):
827 """Return an iterator for the interfaces in the specification.
828 """
829 yield self
831 def getBases(self):
832 return self.__bases__
834 def isEqualOrExtendedBy(self, other):
835 """Same interface or extends?"""
836 return self == other or other.extends(self)
838 def names(self, all=False): # pylint:disable=redefined-builtin
839 """Return the attribute names defined by the interface."""
840 if not all:
841 return self.__attrs.keys()
843 r = self.__attrs.copy()
845 for base in self.__bases__:
846 r.update(dict.fromkeys(base.names(all)))
848 return r.keys()
850 def __iter__(self):
851 return iter(self.names(all=True))
853 def namesAndDescriptions(self, all=False): # pylint:disable=redefined-builtin
854 """Return attribute names and descriptions defined by interface."""
855 if not all:
856 return self.__attrs.items()
858 r = {}
859 for base in self.__bases__[::-1]:
860 r.update(dict(base.namesAndDescriptions(all)))
862 r.update(self.__attrs)
864 return r.items()
866 def getDescriptionFor(self, name):
867 """Return the attribute description for the given name."""
868 r = self.get(name)
869 if r is not None:
870 return r
872 raise KeyError(name)
874 __getitem__ = getDescriptionFor
876 def __contains__(self, name):
877 return self.get(name) is not None
879 def direct(self, name):
880 return self.__attrs.get(name)
882 def queryDescriptionFor(self, name, default=None):
883 return self.get(name, default)
885 def validateInvariants(self, obj, errors=None):
886 """validate object to defined invariants."""
888 for iface in self.__iro__:
889 for invariant in iface.queryDirectTaggedValue('invariants', ()):
890 try:
891 invariant(obj)
892 except Invalid as error:
893 if errors is not None:
894 errors.append(error)
895 else:
896 raise
898 if errors:
899 raise Invalid(errors)
901 def queryTaggedValue(self, tag, default=None):
902 """
903 Queries for the value associated with *tag*, returning it from the nearest
904 interface in the ``__iro__``.
906 If not found, returns *default*.
907 """
908 for iface in self.__iro__:
909 value = iface.queryDirectTaggedValue(tag, _marker)
910 if value is not _marker:
911 return value
912 return default
914 def getTaggedValue(self, tag):
915 """ Returns the value associated with 'tag'. """
916 value = self.queryTaggedValue(tag, default=_marker)
917 if value is _marker:
918 raise KeyError(tag)
919 return value
921 def getTaggedValueTags(self):
922 """ Returns a list of all tags. """
923 keys = set()
924 for base in self.__iro__:
925 keys.update(base.getDirectTaggedValueTags())
926 return keys
928 def __repr__(self):
929 try:
930 return self._v_repr
931 except AttributeError:
932 name = str(self)
933 r = "<%s %s>" % (self.__class__.__name__, name)
934 self._v_repr = r # pylint:disable=attribute-defined-outside-init
935 return r
937 def __str__(self):
938 name = self.__name__
939 m = self.__ibmodule__
940 if m:
941 name = '%s.%s' % (m, name)
942 return name
944 def _call_conform(self, conform):
945 try:
946 return conform(self)
947 except TypeError: # pragma: no cover
948 # We got a TypeError. It might be an error raised by
949 # the __conform__ implementation, or *we* may have
950 # made the TypeError by calling an unbound method
951 # (object is a class). In the later case, we behave
952 # as though there is no __conform__ method. We can
953 # detect this case by checking whether there is more
954 # than one traceback object in the traceback chain:
955 if sys.exc_info()[2].tb_next is not None:
956 # There is more than one entry in the chain, so
957 # reraise the error:
958 raise
959 # This clever trick is from Phillip Eby
961 return None # pragma: no cover
963 def __reduce__(self):
964 return self.__name__
966Interface = InterfaceClass("Interface", __module__='zope.interface')
967# Interface is the only member of its own SRO.
968Interface._calculate_sro = lambda: (Interface,)
969Interface.changed(Interface)
970assert Interface.__sro__ == (Interface,)
971Specification._ROOT = Interface
972ro._ROOT = Interface
974class _InterfaceClassWithCustomMethods(InterfaceClass):
975 """
976 Marker class for interfaces with custom methods that override InterfaceClass methods.
977 """
980class Attribute(Element):
981 """Attribute descriptions
982 """
984 # We can't say this yet because we don't have enough
985 # infrastructure in place.
986 #
987 # implements(IAttribute)
989 interface = None
991 def _get_str_info(self):
992 """Return extra data to put at the end of __str__."""
993 return ""
995 def __str__(self):
996 of = ''
997 if self.interface is not None:
998 of = self.interface.__module__ + '.' + self.interface.__name__ + '.'
999 # self.__name__ may be None during construction (e.g., debugging)
1000 return of + (self.__name__ or '<unknown>') + self._get_str_info()
1002 def __repr__(self):
1003 return "<%s.%s object at 0x%x %s>" % (
1004 type(self).__module__,
1005 type(self).__name__,
1006 id(self),
1007 self
1008 )
1011class Method(Attribute):
1012 """Method interfaces
1014 The idea here is that you have objects that describe methods.
1015 This provides an opportunity for rich meta-data.
1016 """
1018 # We can't say this yet because we don't have enough
1019 # infrastructure in place.
1020 #
1021 # implements(IMethod)
1023 positional = required = ()
1024 _optional = varargs = kwargs = None
1025 def _get_optional(self):
1026 if self._optional is None:
1027 return {}
1028 return self._optional
1029 def _set_optional(self, opt):
1030 self._optional = opt
1031 def _del_optional(self):
1032 self._optional = None
1033 optional = property(_get_optional, _set_optional, _del_optional)
1035 def __call__(self, *args, **kw):
1036 raise BrokenImplementation(self.interface, self.__name__)
1038 def getSignatureInfo(self):
1039 return {'positional': self.positional,
1040 'required': self.required,
1041 'optional': self.optional,
1042 'varargs': self.varargs,
1043 'kwargs': self.kwargs,
1044 }
1046 def getSignatureString(self):
1047 sig = []
1048 for v in self.positional:
1049 sig.append(v)
1050 if v in self.optional.keys():
1051 sig[-1] += "=" + repr(self.optional[v])
1052 if self.varargs:
1053 sig.append("*" + self.varargs)
1054 if self.kwargs:
1055 sig.append("**" + self.kwargs)
1057 return "(%s)" % ", ".join(sig)
1059 _get_str_info = getSignatureString
1062def fromFunction(func, interface=None, imlevel=0, name=None):
1063 name = name or func.__name__
1064 method = Method(name, func.__doc__)
1065 defaults = getattr(func, '__defaults__', None) or ()
1066 code = func.__code__
1067 # Number of positional arguments
1068 na = code.co_argcount - imlevel
1069 names = code.co_varnames[imlevel:]
1070 opt = {}
1071 # Number of required arguments
1072 defaults_count = len(defaults)
1073 if not defaults_count:
1074 # PyPy3 uses ``__defaults_count__`` for builtin methods
1075 # like ``dict.pop``. Surprisingly, these don't have recorded
1076 # ``__defaults__``
1077 defaults_count = getattr(func, '__defaults_count__', 0)
1079 nr = na - defaults_count
1080 if nr < 0:
1081 defaults = defaults[-nr:]
1082 nr = 0
1084 # Determine the optional arguments.
1085 opt.update(dict(zip(names[nr:], defaults)))
1087 method.positional = names[:na]
1088 method.required = names[:nr]
1089 method.optional = opt
1091 argno = na
1093 # Determine the function's variable argument's name (i.e. *args)
1094 if code.co_flags & CO_VARARGS:
1095 method.varargs = names[argno]
1096 argno = argno + 1
1097 else:
1098 method.varargs = None
1100 # Determine the function's keyword argument's name (i.e. **kw)
1101 if code.co_flags & CO_VARKEYWORDS:
1102 method.kwargs = names[argno]
1103 else:
1104 method.kwargs = None
1106 method.interface = interface
1108 for key, value in func.__dict__.items():
1109 method.setTaggedValue(key, value)
1111 return method
1114def fromMethod(meth, interface=None, name=None):
1115 if isinstance(meth, MethodType):
1116 func = meth.__func__
1117 else:
1118 func = meth
1119 return fromFunction(func, interface, imlevel=1, name=name)
1122# Now we can create the interesting interfaces and wire them up:
1123def _wire():
1124 from zope.interface.declarations import classImplements
1125 # From lest specific to most specific.
1126 from zope.interface.interfaces import IElement
1127 classImplements(Element, IElement)
1129 from zope.interface.interfaces import IAttribute
1130 classImplements(Attribute, IAttribute)
1132 from zope.interface.interfaces import IMethod
1133 classImplements(Method, IMethod)
1135 from zope.interface.interfaces import ISpecification
1136 classImplements(Specification, ISpecification)
1138 from zope.interface.interfaces import IInterface
1139 classImplements(InterfaceClass, IInterface)
1142# We import this here to deal with module dependencies.
1143# pylint:disable=wrong-import-position
1144from zope.interface.declarations import implementedBy
1145from zope.interface.declarations import providedBy
1146from zope.interface.exceptions import InvalidInterface
1147from zope.interface.exceptions import BrokenImplementation
1149# This ensures that ``Interface`` winds up in the flattened()
1150# list of the immutable declaration. It correctly overrides changed()
1151# as a no-op, so we bypass that.
1152from zope.interface.declarations import _empty
1153Specification.changed(_empty, _empty)