aboutsummaryrefslogtreecommitdiffstats
path: root/contrib/python/zope.interface/py3/zope/interface/declarations.py
diff options
context:
space:
mode:
authorrobot-piglet <robot-piglet@yandex-team.com>2024-08-28 17:49:28 +0300
committerrobot-piglet <robot-piglet@yandex-team.com>2024-08-28 17:58:46 +0300
commit05f1a7bca5400633bcb52b58affe23880df1fd0e (patch)
tree87744c3c5cb786fddbe15004779b941988a0b7d7 /contrib/python/zope.interface/py3/zope/interface/declarations.py
parentdc1a94ab8d6985d2dcf888fa1881e7b80f7042b1 (diff)
downloadydb-05f1a7bca5400633bcb52b58affe23880df1fd0e.tar.gz
Intermediate changes
Diffstat (limited to 'contrib/python/zope.interface/py3/zope/interface/declarations.py')
-rw-r--r--contrib/python/zope.interface/py3/zope/interface/declarations.py282
1 files changed, 155 insertions, 127 deletions
diff --git a/contrib/python/zope.interface/py3/zope/interface/declarations.py b/contrib/python/zope.interface/py3/zope/interface/declarations.py
index 87e625203c..a9b983da81 100644
--- a/contrib/python/zope.interface/py3/zope/interface/declarations.py
+++ b/contrib/python/zope.interface/py3/zope/interface/declarations.py
@@ -34,6 +34,7 @@ from types import ModuleType
from zope.interface._compat import _use_c_impl
from zope.interface.interface import Interface
+from zope.interface.interface import InterfaceBase
from zope.interface.interface import InterfaceClass
from zope.interface.interface import NameAndModuleComparisonMixin
from zope.interface.interface import Specification
@@ -61,6 +62,7 @@ def _next_super_class(ob):
next_class = complete_mro[complete_mro.index(class_that_invoked_super) + 1]
return next_class
+
class named:
def __init__(self, name):
@@ -103,7 +105,7 @@ class Declaration(Specification):
if not [
j
for j in other.interfaces()
- if i.extends(j, 0) # non-strict extends
+ if i.extends(j, 0) # non-strict extends
]
])
@@ -114,10 +116,10 @@ class Declaration(Specification):
.. versionchanged:: 5.4.0
Now tries to preserve a consistent resolution order. Interfaces
- being added to this object are added to the front of the resulting resolution
- order if they already extend an interface in this object. Previously,
- they were always added to the end of the order, which easily resulted in
- invalid orders.
+ being added to this object are added to the front of the resulting
+ resolution order if they already extend an interface in this
+ object. Previously, they were always added to the end of the order,
+ which easily resulted in invalid orders.
"""
before = []
result = list(self.interfaces())
@@ -171,9 +173,11 @@ class Declaration(Specification):
# classes.)
this_name = iface.__name__
duplicate_transform = _implements_name
- elif (isinstance(iface, Implements)
- and not iface.declared
- and iface.inherit in interfaces):
+ elif (
+ isinstance(iface, Implements) and
+ not iface.declared and
+ iface.inherit in interfaces
+ ):
# If nothing is declared, there's no need to even print this;
# it would just show as ``classImplements(Class)``, and the
# ``Class`` has typically already.
@@ -216,13 +220,15 @@ class _ImmutableDeclaration(Declaration):
@__bases__.setter
def __bases__(self, new_bases):
# We expect the superclass constructor to set ``self.__bases__ = ()``.
- # Rather than attempt to special case that in the constructor and allow
- # setting __bases__ only at that time, it's easier to just allow setting
- # the empty tuple at any time. That makes ``x.__bases__ = x.__bases__`` a nice
- # no-op too. (Skipping the superclass constructor altogether is a recipe
- # for maintenance headaches.)
+ # Rather than attempt to special case that in the constructor and
+ # allow setting __bases__ only at that time, it's easier to just allow
+ # setting the empty tuple at any time. That makes ``x.__bases__ =
+ # x.__bases__`` a nice no-op too. (Skipping the superclass constructor
+ # altogether is a recipe for maintenance headaches.)
if new_bases != ():
- raise TypeError("Cannot set non-empty bases on shared empty Declaration.")
+ raise TypeError(
+ "Cannot set non-empty bases on shared empty Declaration."
+ )
# As the immutable empty declaration, we cannot be changed.
# This means there's no logical reason for us to have dependents
@@ -246,20 +252,20 @@ class _ImmutableDeclaration(Declaration):
def weakref(self, callback=None):
# We're a singleton, we never go away. So there's no need to return
- # distinct weakref objects here; their callbacks will never
- # be called. Instead, we only need to return a callable that
- # returns ourself. The easiest one is to return _ImmutableDeclaration
- # itself; testing on Python 3.8 shows that's faster than a function that
- # returns _empty. (Remember, one goal is to avoid allocating any
- # object, and that includes a method.)
+ # distinct weakref objects here; their callbacks will never be called.
+ # Instead, we only need to return a callable that returns ourself. The
+ # easiest one is to return _ImmutableDeclaration itself; testing on
+ # Python 3.8 shows that's faster than a function that returns _empty.
+ # (Remember, one goal is to avoid allocating any object, and that
+ # includes a method.)
return _ImmutableDeclaration
@property
def _v_attrs(self):
# _v_attrs is not a public, documented property, but some client code
# uses it anyway as a convenient place to cache things. To keep the
- # empty declaration truly immutable, we must ignore that. That includes
- # ignoring assignments as well.
+ # empty declaration truly immutable, we must ignore that. That
+ # includes ignoring assignments as well.
return {}
@_v_attrs.setter
@@ -275,26 +281,28 @@ class _ImmutableDeclaration(Declaration):
class Implements(NameAndModuleComparisonMixin,
Declaration):
- # Inherit from NameAndModuleComparisonMixin to be
- # mutually comparable with InterfaceClass objects.
- # (The two must be mutually comparable to be able to work in e.g., BTrees.)
- # Instances of this class generally don't have a __module__ other than
- # `zope.interface.declarations`, whereas they *do* have a __name__ that is the
- # fully qualified name of the object they are representing.
+ # Inherit from NameAndModuleComparisonMixin to be mutually comparable with
+ # InterfaceClass objects. (The two must be mutually comparable to be able
+ # to work in e.g., BTrees.) Instances of this class generally don't have a
+ # __module__ other than `zope.interface.declarations`, whereas they *do*
+ # have a __name__ that is the fully qualified name of the object they are
+ # representing.
# Note, though, that equality and hashing are still identity based. This
- # accounts for things like nested objects that have the same name (typically
- # only in tests) and is consistent with pickling. As far as comparisons to InterfaceClass
- # goes, we'll never have equal name and module to those, so we're still consistent there.
- # Instances of this class are essentially intended to be unique and are
- # heavily cached (note how our __reduce__ handles this) so having identity
- # based hash and eq should also work.
-
- # We want equality and hashing to be based on identity. However, we can't actually
- # implement __eq__/__ne__ to do this because sometimes we get wrapped in a proxy.
- # We need to let the proxy types implement these methods so they can handle unwrapping
- # and then rely on: (1) the interpreter automatically changing `implements == proxy` into
- # `proxy == implements` (which will call proxy.__eq__ to do the unwrapping) and then
+ # accounts for things like nested objects that have the same name
+ # (typically only in tests) and is consistent with pickling. As far as
+ # comparisons to InterfaceClass goes, we'll never have equal name and
+ # module to those, so we're still consistent there. Instances of this
+ # class are essentially intended to be unique and are heavily cached (note
+ # how our __reduce__ handles this) so having identity based hash and eq
+ # should also work.
+
+ # We want equality and hashing to be based on identity. However, we can't
+ # actually implement __eq__/__ne__ to do this because sometimes we get
+ # wrapped in a proxy. We need to let the proxy types implement these
+ # methods so they can handle unwrapping and then rely on: (1) the
+ # interpreter automatically changing `implements == proxy` into `proxy ==
+ # implements` (which will call proxy.__eq__ to do the unwrapping) and then
# (2) the default equality and hashing semantics being identity based.
# class whose specification should be used as additional base
@@ -313,11 +321,11 @@ class Implements(NameAndModuleComparisonMixin,
@classmethod
def named(cls, name, *bases):
- # Implementation method: Produce an Implements interface with
- # a fully fleshed out __name__ before calling the constructor, which
- # sets bases to the given interfaces and which may pass this object to
- # other objects (e.g., to adjust dependents). If they're sorting or comparing
- # by name, this needs to be set.
+ # Implementation method: Produce an Implements interface with a fully
+ # fleshed out __name__ before calling the constructor, which sets
+ # bases to the given interfaces and which may pass this object to
+ # other objects (e.g., to adjust dependents). If they're sorting or
+ # comparing by name, this needs to be set.
inst = cls.__new__(cls)
inst.__name__ = name
inst.__init__(*bases)
@@ -332,13 +340,16 @@ class Implements(NameAndModuleComparisonMixin,
def __repr__(self):
if self.inherit:
- name = getattr(self.inherit, '__name__', None) or _implements_name(self.inherit)
+ name = (
+ getattr(self.inherit, '__name__', None) or
+ _implements_name(self.inherit)
+ )
else:
name = self.__name__
declared_names = self._argument_names_for_repr(self.declared)
if declared_names:
declared_names = ', ' + declared_names
- return 'classImplements({}{})'.format(name, declared_names)
+ return f'classImplements({name}{declared_names})'
def __reduce__(self):
return implementedBy, (self.inherit, )
@@ -353,6 +364,12 @@ def _implements_name(ob):
# equality and hashing is still based on identity.
# It might be nice to use __qualname__ on Python 3, but that would produce
# different values between Py2 and Py3.
+
+ # Special-case 'InterfaceBase': its '__module__' member descriptor
+ # behaves differently across Python 3.x versions.
+ if ob is InterfaceBase:
+ return 'zope.interface.interface.InterfaceBase'
+
return (getattr(ob, '__module__', '?') or '?') + \
'.' + (getattr(ob, '__name__', '?') or '?')
@@ -370,7 +387,7 @@ def _implementedBy_super(sup):
# that excludes the classes being skipped over but
# includes everything else.
implemented_by_self = implementedBy(sup.__self_class__)
- cache = implemented_by_self._super_cache # pylint:disable=protected-access
+ cache = implemented_by_self._super_cache # pylint:disable=protected-access
if cache is None:
cache = implemented_by_self._super_cache = weakref.WeakKeyDictionary()
@@ -405,7 +422,9 @@ def _implementedBy_super(sup):
@_use_c_impl
-def implementedBy(cls): # pylint:disable=too-many-return-statements,too-many-branches
+def implementedBy(
+ cls
+): # pylint:disable=too-many-return-statements,too-many-branches
"""Return the interfaces implemented for a class' instances
The value returned is an `~zope.interface.interfaces.IDeclaration`.
@@ -459,10 +478,10 @@ def implementedBy(cls): # pylint:disable=too-many-return-statements,too-many-bra
spec_name = _implements_name(cls)
if spec is not None:
# old-style __implemented__ = foo declaration
- spec = (spec, ) # tuplefy, as it might be just an int
+ spec = (spec, ) # tuplefy, as it might be just an int
spec = Implements.named(spec_name, *_normalizeargs(spec))
- spec.inherit = None # old-style implies no inherit
- del cls.__implemented__ # get rid of the old-style declaration
+ spec.inherit = None # old-style implies no inherit
+ del cls.__implemented__ # get rid of the old-style declaration
else:
try:
bases = cls.__bases__
@@ -482,9 +501,8 @@ def implementedBy(cls): # pylint:disable=too-many-return-statements,too-many-bra
if isinstance(cls, type) and '__provides__' not in cls.__dict__:
# Make sure we get a __provides__ descriptor
cls.__provides__ = ClassProvides(
- cls,
- getattr(cls, '__class__', type(cls)),
- )
+ cls, getattr(cls, '__class__', type(cls)),
+ )
except TypeError:
if not isinstance(cls, type):
@@ -502,9 +520,10 @@ def classImplementsOnly(cls, *interfaces):
specifications (`~zope.interface.interfaces.IDeclaration` objects).
The interfaces given (including the interfaces in the specifications)
- replace any previous declarations, *including* inherited definitions. If you
- wish to preserve inherited declarations, you can pass ``implementedBy(cls)``
- in *interfaces*. This can be used to alter the interface resolution order.
+ replace any previous declarations, *including* inherited definitions. If
+ you wish to preserve inherited declarations, you can pass
+ ``implementedBy(cls)`` in *interfaces*. This can be used to alter the
+ interface resolution order.
"""
spec = implementedBy(cls)
# Clear out everything inherited. It's important to
@@ -521,8 +540,8 @@ def classImplements(cls, *interfaces):
"""
Declare additional interfaces implemented for instances of a class
- The arguments after the class are one or more interfaces or
- interface specifications (`~zope.interface.interfaces.IDeclaration` objects).
+ The arguments after the class are one or more interfaces or interface
+ specifications (`~zope.interface.interfaces.IDeclaration` objects).
The interfaces given (including the interfaces in the specifications)
are added to any interfaces previously declared. An effort is made to
@@ -534,13 +553,14 @@ def classImplements(cls, *interfaces):
based on inheritance, in order to try to maintain a consistent
resolution order. Previously, all interfaces were added to the end.
.. versionchanged:: 5.1.0
- If *cls* is already declared to implement an interface (or derived interface)
- in *interfaces* through inheritance, the interface is ignored. Previously, it
- would redundantly be made direct base of *cls*, which often produced inconsistent
- interface resolution orders. Now, the order will be consistent, but may change.
- Also, if the ``__bases__`` of the *cls* are later changed, the *cls* will no
- longer be considered to implement such an interface (changing the ``__bases__`` of *cls*
- has never been supported).
+ If *cls* is already declared to implement an interface (or derived
+ interface) in *interfaces* through inheritance, the interface is
+ ignored. Previously, it would redundantly be made direct base of *cls*,
+ which often produced inconsistent interface resolution orders. Now, the
+ order will be consistent, but may change. Also, if the ``__bases__``
+ of the *cls* are later changed, the *cls* will no longer be considered
+ to implement such an interface (changing the ``__bases__`` of *cls* has
+ never been supported).
"""
spec = implementedBy(cls)
interfaces = tuple(_normalizeargs(interfaces))
@@ -578,9 +598,9 @@ def classImplementsFirst(cls, iface):
def _classImplements_ordered(spec, before=(), after=()):
# Elide everything already inherited.
# Except, if it is the root, and we don't already declare anything else
- # that would imply it, allow the root through. (TODO: When we disallow non-strict
- # IRO, this part of the check can be removed because it's not possible to re-declare
- # like that.)
+ # that would imply it, allow the root through. (TODO: When we disallow
+ # non-strict IRO, this part of the check can be removed because it's not
+ # possible to re-declare like that.)
before = [
x
for x in before
@@ -595,8 +615,8 @@ def _classImplements_ordered(spec, before=(), after=()):
# eliminate duplicates
new_declared = []
seen = set()
- for l in before, spec.declared, after:
- for b in l:
+ for lst in before, spec.declared, after:
+ for b in lst:
if b not in seen:
new_declared.append(b)
seen.add(b)
@@ -604,7 +624,7 @@ def _classImplements_ordered(spec, before=(), after=()):
spec.declared = tuple(new_declared)
# compute the bases
- bases = new_declared # guaranteed no dupes
+ bases = new_declared # guaranteed no dupes
if spec.inherit is not None:
for c in spec.inherit.__bases__:
@@ -629,19 +649,18 @@ class implementer:
This function is called as a class decorator.
- The arguments are one or more interfaces or interface
- specifications (`~zope.interface.interfaces.IDeclaration`
- objects).
+ The arguments are one or more interfaces or interface specifications
+ (`~zope.interface.interfaces.IDeclaration` objects).
- The interfaces given (including the interfaces in the
- specifications) are added to any interfaces previously declared,
- unless the interface is already implemented.
+ The interfaces given (including the interfaces in the specifications) are
+ added to any interfaces previously declared, unless the interface is
+ already implemented.
Previous declarations include declarations for base classes unless
implementsOnly was used.
- This function is provided for convenience. It provides a more
- convenient way to call `classImplements`. For example::
+ This function is provided for convenience. It provides a more convenient
+ way to call `classImplements`. For example::
@implementer(I1)
class C(object):
@@ -675,6 +694,7 @@ class implementer:
raise TypeError("Can't declare implements", ob)
return ob
+
class implementer_only:
"""Declare the only interfaces implemented by instances of a class
@@ -728,22 +748,23 @@ class Provides(Declaration): # Really named ProvidesClass
def __init__(self, cls, *interfaces):
self.__args = (cls, ) + interfaces
self._cls = cls
- Declaration.__init__(self, *self._add_interfaces_to_cls(interfaces, cls))
+ Declaration.__init__(
+ self, *self._add_interfaces_to_cls(interfaces, cls)
+ )
# Added to by ``moduleProvides``, et al
_v_module_names = ()
def __repr__(self):
- # The typical way to create instances of this
- # object is via calling ``directlyProvides(...)`` or ``alsoProvides()``,
- # but that's not the only way. Proxies, for example,
- # directly use the ``Provides(...)`` function (which is the
- # more generic method, and what we pickle as). We're after the most
- # readable, useful repr in the common case, so we use the most
- # common name.
+ # The typical way to create instances of this object is via calling
+ # ``directlyProvides(...)`` or ``alsoProvides()``, but that's not the
+ # only way. Proxies, for example, directly use the ``Provides(...)``
+ # function (which is the more generic method, and what we pickle as).
+ # We're after the most readable, useful repr in the common case, so we
+ # use the most common name.
#
- # We also cooperate with ``moduleProvides`` to attempt to do the
- # right thing for that API. See it for details.
+ # We also cooperate with ``moduleProvides`` to attempt to do the right
+ # thing for that API. See it for details.
function_name = 'directlyProvides'
if self._cls is ModuleType and self._v_module_names:
# See notes in ``moduleProvides``/``directlyProvides``
@@ -758,7 +779,7 @@ class Provides(Declaration): # Really named ProvidesClass
if len(mod_names) == 1:
mod_names = "sys.modules[%r]" % mod_names[0]
ordered_names = (
- '{}, '.format(mod_names)
+ f'{mod_names}, '
) + ordered_names
return "{}({})".format(
function_name,
@@ -783,13 +804,16 @@ class Provides(Declaration): # Really named ProvidesClass
raise AttributeError('__provides__')
+
ProvidesClass = Provides
+
# Registry of instance declarations
# This is a memory optimization to allow objects to share specifications.
InstanceDeclarations = weakref.WeakValueDictionary()
-def Provides(*interfaces): # pylint:disable=function-redefined
+
+def Provides(*interfaces): # pylint:disable=function-redefined
"""Declaration for an instance of *cls*.
The correct signature is ``cls, *interfaces``.
@@ -806,10 +830,11 @@ def Provides(*interfaces): # pylint:disable=function-redefined
return spec
+
Provides.__safe_for_unpickling__ = True
-def directlyProvides(object, *interfaces): # pylint:disable=redefined-builtin
+def directlyProvides(object, *interfaces): # pylint:disable=redefined-builtin
"""Declare interfaces declared directly for an object
The arguments after the object are one or more interfaces or interface
@@ -842,8 +867,7 @@ def directlyProvides(object, *interfaces): # pylint:disable=redefined-builtin
provides._v_module_names += (object.__name__,)
-
-def alsoProvides(object, *interfaces): # pylint:disable=redefined-builtin
+def alsoProvides(object, *interfaces): # pylint:disable=redefined-builtin
"""Declare interfaces declared directly for an object
The arguments after the object are one or more interfaces or interface
@@ -855,7 +879,7 @@ def alsoProvides(object, *interfaces): # pylint:disable=redefined-builtin
directlyProvides(object, directlyProvidedBy(object), *interfaces)
-def noLongerProvides(object, interface): # pylint:disable=redefined-builtin
+def noLongerProvides(object, interface): # pylint:disable=redefined-builtin
""" Removes a directly provided interface from an object.
"""
directlyProvides(object, directlyProvidedBy(object) - interface)
@@ -903,22 +927,24 @@ class ClassProvides(Declaration, ClassProvidesBase):
self._cls = cls
self._implements = implementedBy(cls)
self.__args = (cls, metacls, ) + interfaces
- Declaration.__init__(self, *self._add_interfaces_to_cls(interfaces, metacls))
+ Declaration.__init__(
+ self, *self._add_interfaces_to_cls(interfaces, metacls)
+ )
def __repr__(self):
- # There are two common ways to get instances of this object:
- # The most interesting way is calling ``@provider(..)`` as a decorator
- # of a class; this is the same as calling ``directlyProvides(cls, ...)``.
+ # There are two common ways to get instances of this object: The most
+ # interesting way is calling ``@provider(..)`` as a decorator of a
+ # class; this is the same as calling ``directlyProvides(cls, ...)``.
#
- # The other way is by default: anything that invokes ``implementedBy(x)``
- # will wind up putting an instance in ``type(x).__provides__``; this includes
- # the ``@implementer(...)`` decorator. Those instances won't have any
- # interfaces.
+ # The other way is by default: anything that invokes
+ # ``implementedBy(x)`` will wind up putting an instance in
+ # ``type(x).__provides__``; this includes the ``@implementer(...)``
+ # decorator. Those instances won't have any interfaces.
#
# Thus, as our repr, we go with the ``directlyProvides()`` syntax.
interfaces = (self._cls, ) + self.__args[2:]
ordered_names = self._argument_names_for_repr(interfaces)
- return "directlyProvides({})".format(ordered_names)
+ return f"directlyProvides({ordered_names})"
def __reduce__(self):
return self.__class__, self.__args
@@ -927,18 +953,18 @@ class ClassProvides(Declaration, ClassProvidesBase):
__get__ = ClassProvidesBase.__get__
-def directlyProvidedBy(object): # pylint:disable=redefined-builtin
+def directlyProvidedBy(object): # pylint:disable=redefined-builtin
"""Return the interfaces directly provided by the given object
The value returned is an `~zope.interface.interfaces.IDeclaration`.
"""
provides = getattr(object, "__provides__", None)
if (
- provides is None # no spec
+ provides is None # no spec
# We might have gotten the implements spec, as an
# optimization. If so, it's like having only one base, that we
# lop off to exclude class-supplied declarations:
- or isinstance(provides, Implements)
+ or isinstance(provides, Implements) # noqa W503
):
return _empty
@@ -1008,8 +1034,8 @@ def moduleProvides(*interfaces):
directlyProvides(sys.modules[__name__], I1)
"""
- frame = sys._getframe(1) # pylint:disable=protected-access
- locals = frame.f_locals # pylint:disable=redefined-builtin
+ frame = sys._getframe(1) # pylint:disable=protected-access
+ locals = frame.f_locals # pylint:disable=redefined-builtin
# Try to make sure we were called from a module body
if (locals is not frame.f_globals) or ('__name__' not in locals):
@@ -1020,18 +1046,18 @@ def moduleProvides(*interfaces):
raise TypeError(
"moduleProvides can only be used once in a module definition.")
- # Note: This is cached based on the key ``(ModuleType, *interfaces)``;
- # One consequence is that any module that provides the same interfaces
- # gets the same ``__repr__``, meaning that you can't tell what module
- # such a declaration came from. Adding the module name to ``_v_module_names``
- # attempts to correct for this; it works in some common situations, but fails
- # (1) after pickling (the data is lost) and (2) if declarations are
- # actually shared and (3) if the alternate spelling of ``directlyProvides()``
- # is used. Problem (3) is fixed by cooperating with ``directlyProvides``
- # to maintain this information, and problem (2) is worked around by
- # printing all the names, but (1) is unsolvable without introducing
- # new classes or changing the stored data...but it doesn't actually matter,
- # because ``ModuleType`` can't be pickled!
+ # Note: This is cached based on the key ``(ModuleType, *interfaces)``; One
+ # consequence is that any module that provides the same interfaces gets
+ # the same ``__repr__``, meaning that you can't tell what module such a
+ # declaration came from. Adding the module name to ``_v_module_names``
+ # attempts to correct for this; it works in some common situations, but
+ # fails (1) after pickling (the data is lost) and (2) if declarations are
+ # actually shared and (3) if the alternate spelling of
+ # ``directlyProvides()`` is used. Problem (3) is fixed by cooperating
+ # with ``directlyProvides`` to maintain this information, and problem (2)
+ # is worked around by printing all the names, but (1) is unsolvable
+ # without introducing new classes or changing the stored data...but it
+ # doesn't actually matter, because ``ModuleType`` can't be pickled!
p = locals["__provides__"] = Provides(ModuleType,
*_normalizeargs(interfaces))
p._v_module_names += (locals['__name__'],)
@@ -1050,7 +1076,8 @@ def ObjectSpecification(direct, cls):
These combine information for the object and for it's classes.
"""
- return Provides(cls, direct) # pragma: no cover fossil
+ return Provides(cls, direct) # pragma: no cover fossil
+
@_use_c_impl
def getObjectSpecification(ob):
@@ -1086,7 +1113,7 @@ def providedBy(ob):
# Try to get __providedBy__
try:
- if isinstance(ob, super): # Some objects raise errors on isinstance()
+ if isinstance(ob, super): # Some objects raise errors on isinstance()
return implementedBy(ob)
r = ob.__providedBy__
@@ -1136,8 +1163,8 @@ def providedBy(ob):
class ObjectSpecificationDescriptor:
"""Implement the ``__providedBy__`` attribute
- The ``__providedBy__`` attribute computes the interfaces provided by
- an object. If an object has an ``__provides__`` attribute, that is returned.
+ The ``__providedBy__`` attribute computes the interfaces provided by an
+ object. If an object has an ``__provides__`` attribute, that is returned.
Otherwise, `implementedBy` the *cls* is returned.
.. versionchanged:: 5.4.0
@@ -1184,6 +1211,7 @@ def _normalizeargs(sequence, output=None):
return output
+
_empty = _ImmutableDeclaration()
objectSpecificationDescriptor = ObjectSpecificationDescriptor()