collections.py 7.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284
  1. ##############################################################################
  2. # Copyright (c) 2020 Zope Foundation and Contributors.
  3. # All Rights Reserved.
  4. #
  5. # This software is subject to the provisions of the Zope Public License,
  6. # Version 2.1 (ZPL). A copy of the ZPL should accompany this distribution.
  7. # THIS SOFTWARE IS PROVIDED "AS IS" AND ANY AND ALL EXPRESS OR IMPLIED
  8. # WARRANTIES ARE DISCLAIMED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
  9. # WARRANTIES OF TITLE, MERCHANTABILITY, AGAINST INFRINGEMENT, AND FITNESS
  10. # FOR A PARTICULAR PURPOSE.
  11. ##############################################################################
  12. """
  13. Interface definitions paralleling the abstract base classes defined in
  14. :mod:`collections.abc`.
  15. After this module is imported, the standard library types will declare
  16. that they implement the appropriate interface. While most standard
  17. library types will properly implement that interface (that
  18. is, ``verifyObject(ISequence, list()))`` will pass, for example), a few might not:
  19. - `memoryview` doesn't feature all the defined methods of
  20. ``ISequence`` such as ``count``; it is still declared to provide
  21. ``ISequence`` though.
  22. - `collections.deque.pop` doesn't accept the ``index`` argument of
  23. `collections.abc.MutableSequence.pop`
  24. - `range.index` does not accept the ``start`` and ``stop`` arguments.
  25. .. versionadded:: 5.0.0
  26. """
  27. from __future__ import absolute_import
  28. import sys
  29. from abc import ABCMeta
  30. # The collections imports are here, and not in
  31. # zope.interface._compat to avoid importing collections
  32. # unless requested. It's a big import.
  33. try:
  34. from collections import abc
  35. except ImportError:
  36. import collections as abc
  37. from collections import OrderedDict
  38. try:
  39. # On Python 3, all of these extend the appropriate collection ABC,
  40. # but on Python 2, UserDict does not (though it is registered as a
  41. # MutableMapping). (Importantly, UserDict on Python 2 is *not*
  42. # registered, because it's not iterable.) Extending the ABC is not
  43. # taken into account for interface declarations, though, so we
  44. # need to be explicit about it.
  45. from collections import UserList
  46. from collections import UserDict
  47. from collections import UserString
  48. except ImportError:
  49. # Python 2
  50. from UserList import UserList
  51. from UserDict import IterableUserDict as UserDict
  52. from UserString import UserString
  53. from zope.interface._compat import PYTHON2 as PY2
  54. from zope.interface._compat import PYTHON3 as PY3
  55. from zope.interface.common import ABCInterface
  56. from zope.interface.common import optional
  57. # pylint:disable=inherit-non-class,
  58. # pylint:disable=no-self-argument,no-method-argument
  59. # pylint:disable=unexpected-special-method-signature
  60. # pylint:disable=no-value-for-parameter
  61. PY35 = sys.version_info[:2] >= (3, 5)
  62. PY36 = sys.version_info[:2] >= (3, 6)
  63. def _new_in_ver(name, ver,
  64. bases_if_missing=(ABCMeta,),
  65. register_if_missing=()):
  66. if ver:
  67. return getattr(abc, name)
  68. # TODO: It's a shame to have to repeat the bases when
  69. # the ABC is missing. Can we DRY that?
  70. missing = ABCMeta(name, bases_if_missing, {
  71. '__doc__': "The ABC %s is not defined in this version of Python." % (
  72. name
  73. ),
  74. })
  75. for c in register_if_missing:
  76. missing.register(c)
  77. return missing
  78. __all__ = [
  79. 'IAsyncGenerator',
  80. 'IAsyncIterable',
  81. 'IAsyncIterator',
  82. 'IAwaitable',
  83. 'ICollection',
  84. 'IContainer',
  85. 'ICoroutine',
  86. 'IGenerator',
  87. 'IHashable',
  88. 'IItemsView',
  89. 'IIterable',
  90. 'IIterator',
  91. 'IKeysView',
  92. 'IMapping',
  93. 'IMappingView',
  94. 'IMutableMapping',
  95. 'IMutableSequence',
  96. 'IMutableSet',
  97. 'IReversible',
  98. 'ISequence',
  99. 'ISet',
  100. 'ISized',
  101. 'IValuesView',
  102. ]
  103. class IContainer(ABCInterface):
  104. abc = abc.Container
  105. @optional
  106. def __contains__(other):
  107. """
  108. Optional method. If not provided, the interpreter will use
  109. ``__iter__`` or the old ``__getitem__`` protocol
  110. to implement ``in``.
  111. """
  112. class IHashable(ABCInterface):
  113. abc = abc.Hashable
  114. class IIterable(ABCInterface):
  115. abc = abc.Iterable
  116. @optional
  117. def __iter__():
  118. """
  119. Optional method. If not provided, the interpreter will
  120. implement `iter` using the old ``__getitem__`` protocol.
  121. """
  122. class IIterator(IIterable):
  123. abc = abc.Iterator
  124. class IReversible(IIterable):
  125. abc = _new_in_ver('Reversible', PY36, (IIterable.getABC(),))
  126. @optional
  127. def __reversed__():
  128. """
  129. Optional method. If this isn't present, the interpreter
  130. will use ``__len__`` and ``__getitem__`` to implement the
  131. `reversed` builtin.
  132. """
  133. class IGenerator(IIterator):
  134. # New in 3.5
  135. abc = _new_in_ver('Generator', PY35, (IIterator.getABC(),))
  136. class ISized(ABCInterface):
  137. abc = abc.Sized
  138. # ICallable is not defined because there's no standard signature.
  139. class ICollection(ISized,
  140. IIterable,
  141. IContainer):
  142. abc = _new_in_ver('Collection', PY36,
  143. (ISized.getABC(), IIterable.getABC(), IContainer.getABC()))
  144. class ISequence(IReversible,
  145. ICollection):
  146. abc = abc.Sequence
  147. extra_classes = (UserString,)
  148. # On Python 2, basestring is registered as an ISequence, and
  149. # its subclass str is an IByteString. If we also register str as
  150. # an ISequence, that tends to lead to inconsistent resolution order.
  151. ignored_classes = (basestring,) if str is bytes else () # pylint:disable=undefined-variable
  152. @optional
  153. def __reversed__():
  154. """
  155. Optional method. If this isn't present, the interpreter
  156. will use ``__len__`` and ``__getitem__`` to implement the
  157. `reversed` builtin.
  158. """
  159. @optional
  160. def __iter__():
  161. """
  162. Optional method. If not provided, the interpreter will
  163. implement `iter` using the old ``__getitem__`` protocol.
  164. """
  165. class IMutableSequence(ISequence):
  166. abc = abc.MutableSequence
  167. extra_classes = (UserList,)
  168. class IByteString(ISequence):
  169. """
  170. This unifies `bytes` and `bytearray`.
  171. """
  172. abc = _new_in_ver('ByteString', PY3,
  173. (ISequence.getABC(),),
  174. (bytes, bytearray))
  175. class ISet(ICollection):
  176. abc = abc.Set
  177. class IMutableSet(ISet):
  178. abc = abc.MutableSet
  179. class IMapping(ICollection):
  180. abc = abc.Mapping
  181. extra_classes = (dict,)
  182. # OrderedDict is a subclass of dict. On CPython 2,
  183. # it winds up registered as a IMutableMapping, which
  184. # produces an inconsistent IRO if we also try to register it
  185. # here.
  186. ignored_classes = (OrderedDict,)
  187. if PY2:
  188. @optional
  189. def __eq__(other):
  190. """
  191. The interpreter will supply one.
  192. """
  193. __ne__ = __eq__
  194. class IMutableMapping(IMapping):
  195. abc = abc.MutableMapping
  196. extra_classes = (dict, UserDict,)
  197. ignored_classes = (OrderedDict,)
  198. class IMappingView(ISized):
  199. abc = abc.MappingView
  200. class IItemsView(IMappingView, ISet):
  201. abc = abc.ItemsView
  202. class IKeysView(IMappingView, ISet):
  203. abc = abc.KeysView
  204. class IValuesView(IMappingView, ICollection):
  205. abc = abc.ValuesView
  206. @optional
  207. def __contains__(other):
  208. """
  209. Optional method. If not provided, the interpreter will use
  210. ``__iter__`` or the old ``__len__`` and ``__getitem__`` protocol
  211. to implement ``in``.
  212. """
  213. class IAwaitable(ABCInterface):
  214. abc = _new_in_ver('Awaitable', PY35)
  215. class ICoroutine(IAwaitable):
  216. abc = _new_in_ver('Coroutine', PY35)
  217. class IAsyncIterable(ABCInterface):
  218. abc = _new_in_ver('AsyncIterable', PY35)
  219. class IAsyncIterator(IAsyncIterable):
  220. abc = _new_in_ver('AsyncIterator', PY35)
  221. class IAsyncGenerator(IAsyncIterator):
  222. abc = _new_in_ver('AsyncGenerator', PY36)