aboutsummaryrefslogtreecommitdiffstats
path: root/contrib/python/zope.interface/py3/zope/interface/common/__init__.py
diff options
context:
space:
mode:
authorshmel1k <shmel1k@ydb.tech>2023-11-26 18:16:14 +0300
committershmel1k <shmel1k@ydb.tech>2023-11-26 18:43:30 +0300
commitb8cf9e88f4c5c64d9406af533d8948deb050d695 (patch)
tree218eb61fb3c3b96ec08b4d8cdfef383104a87d63 /contrib/python/zope.interface/py3/zope/interface/common/__init__.py
parent523f645a83a0ec97a0332dbc3863bb354c92a328 (diff)
downloadydb-b8cf9e88f4c5c64d9406af533d8948deb050d695.tar.gz
add kikimr_configure
Diffstat (limited to 'contrib/python/zope.interface/py3/zope/interface/common/__init__.py')
-rw-r--r--contrib/python/zope.interface/py3/zope/interface/common/__init__.py272
1 files changed, 272 insertions, 0 deletions
diff --git a/contrib/python/zope.interface/py3/zope/interface/common/__init__.py b/contrib/python/zope.interface/py3/zope/interface/common/__init__.py
new file mode 100644
index 0000000000..56f4566a24
--- /dev/null
+++ b/contrib/python/zope.interface/py3/zope/interface/common/__init__.py
@@ -0,0 +1,272 @@
+##############################################################################
+# Copyright (c) 2020 Zope Foundation and Contributors.
+# All Rights Reserved.
+#
+# This software is subject to the provisions of the Zope Public License,
+# Version 2.1 (ZPL). A copy of the ZPL should accompany this distribution.
+# THIS SOFTWARE IS PROVIDED "AS IS" AND ANY AND ALL EXPRESS OR IMPLIED
+# WARRANTIES ARE DISCLAIMED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+# WARRANTIES OF TITLE, MERCHANTABILITY, AGAINST INFRINGEMENT, AND FITNESS
+# FOR A PARTICULAR PURPOSE.
+##############################################################################
+
+import itertools
+from types import FunctionType
+
+from zope.interface import classImplements
+from zope.interface import Interface
+from zope.interface.interface import fromFunction
+from zope.interface.interface import InterfaceClass
+from zope.interface.interface import _decorator_non_return
+
+__all__ = [
+ # Nothing public here.
+]
+
+
+# pylint:disable=inherit-non-class,
+# pylint:disable=no-self-argument,no-method-argument
+# pylint:disable=unexpected-special-method-signature
+
+class optional:
+ # Apply this decorator to a method definition to make it
+ # optional (remove it from the list of required names), overriding
+ # the definition inherited from the ABC.
+ def __init__(self, method):
+ self.__doc__ = method.__doc__
+
+
+class ABCInterfaceClass(InterfaceClass):
+ """
+ An interface that is automatically derived from a
+ :class:`abc.ABCMeta` type.
+
+ Internal use only.
+
+ The body of the interface definition *must* define
+ a property ``abc`` that is the ABC to base the interface on.
+
+ If ``abc`` is *not* in the interface definition, a regular
+ interface will be defined instead (but ``extra_classes`` is still
+ respected).
+
+ Use the ``@optional`` decorator on method definitions if
+ the ABC defines methods that are not actually required in all cases
+ because the Python language has multiple ways to implement a protocol.
+ For example, the ``iter()`` protocol can be implemented with
+ ``__iter__`` or the pair ``__len__`` and ``__getitem__``.
+
+ When created, any existing classes that are registered to conform
+ to the ABC are declared to implement this interface. This is *not*
+ automatically updated as the ABC registry changes. If the body of the
+ interface definition defines ``extra_classes``, it should be a
+ tuple giving additional classes to declare implement the interface.
+
+ Note that this is not fully symmetric. For example, it is usually
+ the case that a subclass relationship carries the interface
+ declarations over::
+
+ >>> from zope.interface import Interface
+ >>> class I1(Interface):
+ ... pass
+ ...
+ >>> from zope.interface import implementer
+ >>> @implementer(I1)
+ ... class Root(object):
+ ... pass
+ ...
+ >>> class Child(Root):
+ ... pass
+ ...
+ >>> child = Child()
+ >>> isinstance(child, Root)
+ True
+ >>> from zope.interface import providedBy
+ >>> list(providedBy(child))
+ [<InterfaceClass __main__.I1>]
+
+ However, that's not the case with ABCs and ABC interfaces. Just
+ because ``isinstance(A(), AnABC)`` and ``isinstance(B(), AnABC)``
+ are both true, that doesn't mean there's any class hierarchy
+ relationship between ``A`` and ``B``, or between either of them
+ and ``AnABC``. Thus, if ``AnABC`` implemented ``IAnABC``, it would
+ not follow that either ``A`` or ``B`` implements ``IAnABC`` (nor
+ their instances provide it)::
+
+ >>> class SizedClass(object):
+ ... def __len__(self): return 1
+ ...
+ >>> from collections.abc import Sized
+ >>> isinstance(SizedClass(), Sized)
+ True
+ >>> from zope.interface import classImplements
+ >>> classImplements(Sized, I1)
+ None
+ >>> list(providedBy(SizedClass()))
+ []
+
+ Thus, to avoid conflicting assumptions, ABCs should not be
+ declared to implement their parallel ABC interface. Only concrete
+ classes specifically registered with the ABC should be declared to
+ do so.
+
+ .. versionadded:: 5.0.0
+ """
+
+ # If we could figure out invalidation, and used some special
+ # Specification/Declaration instances, and override the method ``providedBy`` here,
+ # perhaps we could more closely integrate with ABC virtual inheritance?
+
+ def __init__(self, name, bases, attrs):
+ # go ahead and give us a name to ease debugging.
+ self.__name__ = name
+ extra_classes = attrs.pop('extra_classes', ())
+ ignored_classes = attrs.pop('ignored_classes', ())
+
+ if 'abc' not in attrs:
+ # Something like ``IList(ISequence)``: We're extending
+ # abc interfaces but not an ABC interface ourself.
+ InterfaceClass.__init__(self, name, bases, attrs)
+ ABCInterfaceClass.__register_classes(self, extra_classes, ignored_classes)
+ self.__class__ = InterfaceClass
+ return
+
+ based_on = attrs.pop('abc')
+ self.__abc = based_on
+ self.__extra_classes = tuple(extra_classes)
+ self.__ignored_classes = tuple(ignored_classes)
+
+ assert name[1:] == based_on.__name__, (name, based_on)
+ methods = {
+ # Passing the name is important in case of aliases,
+ # e.g., ``__ror__ = __or__``.
+ k: self.__method_from_function(v, k)
+ for k, v in vars(based_on).items()
+ if isinstance(v, FunctionType) and not self.__is_private_name(k)
+ and not self.__is_reverse_protocol_name(k)
+ }
+
+ methods['__doc__'] = self.__create_class_doc(attrs)
+ # Anything specified in the body takes precedence.
+ methods.update(attrs)
+ InterfaceClass.__init__(self, name, bases, methods)
+ self.__register_classes()
+
+ @staticmethod
+ def __optional_methods_to_docs(attrs):
+ optionals = {k: v for k, v in attrs.items() if isinstance(v, optional)}
+ for k in optionals:
+ attrs[k] = _decorator_non_return
+
+ if not optionals:
+ return ''
+
+ docs = "\n\nThe following methods are optional:\n - " + "\n-".join(
+ "{}\n{}".format(k, v.__doc__) for k, v in optionals.items()
+ )
+ return docs
+
+ def __create_class_doc(self, attrs):
+ based_on = self.__abc
+ def ref(c):
+ mod = c.__module__
+ name = c.__name__
+ if mod == str.__module__:
+ return "`%s`" % name
+ if mod == '_io':
+ mod = 'io'
+ return "`{}.{}`".format(mod, name)
+ implementations_doc = "\n - ".join(
+ ref(c)
+ for c in sorted(self.getRegisteredConformers(), key=ref)
+ )
+ if implementations_doc:
+ implementations_doc = "\n\nKnown implementations are:\n\n - " + implementations_doc
+
+ based_on_doc = (based_on.__doc__ or '')
+ based_on_doc = based_on_doc.splitlines()
+ based_on_doc = based_on_doc[0] if based_on_doc else ''
+
+ doc = """Interface for the ABC `{}.{}`.\n\n{}{}{}""".format(
+ based_on.__module__, based_on.__name__,
+ attrs.get('__doc__', based_on_doc),
+ self.__optional_methods_to_docs(attrs),
+ implementations_doc
+ )
+ return doc
+
+
+ @staticmethod
+ def __is_private_name(name):
+ if name.startswith('__') and name.endswith('__'):
+ return False
+ return name.startswith('_')
+
+ @staticmethod
+ def __is_reverse_protocol_name(name):
+ # The reverse names, like __rand__,
+ # aren't really part of the protocol. The interpreter has
+ # very complex behaviour around invoking those. PyPy
+ # doesn't always even expose them as attributes.
+ return name.startswith('__r') and name.endswith('__')
+
+ def __method_from_function(self, function, name):
+ method = fromFunction(function, self, name=name)
+ # Eliminate the leading *self*, which is implied in
+ # an interface, but explicit in an ABC.
+ method.positional = method.positional[1:]
+ return method
+
+ def __register_classes(self, conformers=None, ignored_classes=None):
+ # Make the concrete classes already present in our ABC's registry
+ # declare that they implement this interface.
+ conformers = conformers if conformers is not None else self.getRegisteredConformers()
+ ignored = ignored_classes if ignored_classes is not None else self.__ignored_classes
+ for cls in conformers:
+ if cls in ignored:
+ continue
+ classImplements(cls, self)
+
+ def getABC(self):
+ """
+ Return the ABC this interface represents.
+ """
+ return self.__abc
+
+ def getRegisteredConformers(self):
+ """
+ Return an iterable of the classes that are known to conform to
+ the ABC this interface parallels.
+ """
+ based_on = self.__abc
+
+ # The registry only contains things that aren't already
+ # known to be subclasses of the ABC. But the ABC is in charge
+ # of checking that, so its quite possible that registrations
+ # are in fact ignored, winding up just in the _abc_cache.
+ try:
+ registered = list(based_on._abc_registry) + list(based_on._abc_cache)
+ except AttributeError:
+ # Rewritten in C in CPython 3.7.
+ # These expose the underlying weakref.
+ from abc import _get_dump
+ data = _get_dump(based_on)
+ registry = data[0]
+ cache = data[1]
+ registered = [x() for x in itertools.chain(registry, cache)]
+ registered = [x for x in registered if x is not None]
+
+ return set(itertools.chain(registered, self.__extra_classes))
+
+
+def _create_ABCInterface():
+ # It's a two-step process to create the root ABCInterface, because
+ # without specifying a corresponding ABC, using the normal constructor
+ # gets us a plain InterfaceClass object, and there is no ABC to associate with the
+ # root.
+ abc_name_bases_attrs = ('ABCInterface', (Interface,), {})
+ instance = ABCInterfaceClass.__new__(ABCInterfaceClass, *abc_name_bases_attrs)
+ InterfaceClass.__init__(instance, *abc_name_bases_attrs)
+ return instance
+
+ABCInterface = _create_ABCInterface()