diff --git a/Lib/collections/__init__.py b/Lib/collections/__init__.py index 8aeee359cd6..f0b41fd9d10 100644 --- a/Lib/collections/__init__.py +++ b/Lib/collections/__init__.py @@ -17,16 +17,7 @@ list, set, and tuple. __all__ = ['deque', 'defaultdict', 'namedtuple', 'UserDict', 'UserList', 'UserString', 'Counter', 'OrderedDict', 'ChainMap'] -# For backwards compatibility, continue to make the collections ABCs -# through Python 3.6 available through the collections module. -# Note, no new collections ABCs were added in Python 3.7 import _collections_abc -from _collections_abc import (AsyncGenerator, AsyncIterable, AsyncIterator, - Awaitable, ByteString, Callable, Collection, Container, Coroutine, - Generator, Hashable, ItemsView, Iterable, Iterator, KeysView, Mapping, - MappingView, MutableMapping, MutableSequence, MutableSet, Reversible, - Sequence, Set, Sized, ValuesView) - from operator import itemgetter as _itemgetter, eq as _eq from keyword import iskeyword as _iskeyword import sys as _sys @@ -40,7 +31,7 @@ try: except ImportError: pass else: - MutableSequence.register(deque) + _collections_abc.MutableSequence.register(deque) try: from _collections import defaultdict @@ -48,22 +39,37 @@ except ImportError: pass +def __getattr__(name): + # For backwards compatibility, continue to make the collections ABCs + # through Python 3.6 available through the collections module. + # Note, no new collections ABCs were added in Python 3.7 + if name in _collections_abc.__all__: + obj = getattr(_collections_abc, name) + import warnings + warnings.warn("Using or importing the ABCs from 'collections' instead " + "of from 'collections.abc' is deprecated, " + "and in 3.8 it will stop working", + DeprecationWarning, stacklevel=2) + globals()[name] = obj + return obj + raise AttributeError(f'module {__name__!r} has no attribute {name!r}') + ################################################################################ ### OrderedDict ################################################################################ -class _OrderedDictKeysView(KeysView): +class _OrderedDictKeysView(_collections_abc.KeysView): def __reversed__(self): yield from reversed(self._mapping) -class _OrderedDictItemsView(ItemsView): +class _OrderedDictItemsView(_collections_abc.ItemsView): def __reversed__(self): for key in reversed(self._mapping): yield (key, self._mapping[key]) -class _OrderedDictValuesView(ValuesView): +class _OrderedDictValuesView(_collections_abc.ValuesView): def __reversed__(self): for key in reversed(self._mapping): @@ -215,7 +221,7 @@ class OrderedDict(dict): size += sizeof(self.__root) * n # proxy objects return size - update = __update = MutableMapping.update + update = __update = _collections_abc.MutableMapping.update def keys(self): "D.keys() -> a set-like object providing a view on D's keys" @@ -229,7 +235,7 @@ class OrderedDict(dict): "D.values() -> an object providing a view on D's values" return _OrderedDictValuesView(self) - __ne__ = MutableMapping.__ne__ + __ne__ = _collections_abc.MutableMapping.__ne__ __marker = object() @@ -636,7 +642,7 @@ class Counter(dict): raise TypeError('expected at most 1 arguments, got %d' % len(args)) iterable = args[0] if args else None if iterable is not None: - if isinstance(iterable, Mapping): + if isinstance(iterable, _collections_abc.Mapping): if self: self_get = self.get for elem, count in iterable.items(): @@ -673,7 +679,7 @@ class Counter(dict): iterable = args[0] if args else None if iterable is not None: self_get = self.get - if isinstance(iterable, Mapping): + if isinstance(iterable, _collections_abc.Mapping): for elem, count in iterable.items(): self[elem] = self_get(elem, 0) - count else: @@ -875,7 +881,7 @@ class Counter(dict): ### ChainMap ######################################################################## -class ChainMap(MutableMapping): +class ChainMap(_collections_abc.MutableMapping): ''' A ChainMap groups multiple dicts (or other mappings) together to create a single, updateable view. @@ -983,7 +989,7 @@ class ChainMap(MutableMapping): ### UserDict ################################################################################ -class UserDict(MutableMapping): +class UserDict(_collections_abc.MutableMapping): # Start by filling-out the abstract methods def __init__(*args, **kwargs): @@ -1050,7 +1056,7 @@ class UserDict(MutableMapping): ### UserList ################################################################################ -class UserList(MutableSequence): +class UserList(_collections_abc.MutableSequence): """A more or less complete user-defined wrapper around list objects.""" def __init__(self, initlist=None): self.data = [] @@ -1123,7 +1129,7 @@ class UserList(MutableSequence): ### UserString ################################################################################ -class UserString(Sequence): +class UserString(_collections_abc.Sequence): def __init__(self, seq): if isinstance(seq, str): self.data = seq diff --git a/Modules/_decimal/_decimal.c b/Modules/_decimal/_decimal.c index fddb39ef652..5bce780cb7f 100644 --- a/Modules/_decimal/_decimal.c +++ b/Modules/_decimal/_decimal.c @@ -5521,6 +5521,7 @@ PyInit__decimal(void) PyObject *numbers = NULL; PyObject *Number = NULL; PyObject *collections = NULL; + PyObject *collections_abc = NULL; PyObject *MutableMapping = NULL; PyObject *obj = NULL; DecCondMap *cm; @@ -5595,7 +5596,8 @@ PyInit__decimal(void) Py_CLEAR(obj); /* MutableMapping */ - ASSIGN_PTR(MutableMapping, PyObject_GetAttrString(collections, + ASSIGN_PTR(collections_abc, PyImport_ImportModule("collections.abc")); + ASSIGN_PTR(MutableMapping, PyObject_GetAttrString(collections_abc, "MutableMapping")); /* Create SignalDict type */ ASSIGN_PTR(PyDecSignalDict_Type, @@ -5606,6 +5608,7 @@ PyInit__decimal(void) /* Done with collections, MutableMapping */ Py_CLEAR(collections); + Py_CLEAR(collections_abc); Py_CLEAR(MutableMapping); @@ -5765,6 +5768,7 @@ error: Py_CLEAR(Number); /* GCOV_NOT_REACHED */ Py_CLEAR(Rational); /* GCOV_NOT_REACHED */ Py_CLEAR(collections); /* GCOV_NOT_REACHED */ + Py_CLEAR(collections_abc); /* GCOV_NOT_REACHED */ Py_CLEAR(MutableMapping); /* GCOV_NOT_REACHED */ Py_CLEAR(SignalTuple); /* GCOV_NOT_REACHED */ Py_CLEAR(DecimalTuple); /* GCOV_NOT_REACHED */