Skip to content

Commit c66f9f8

Browse files
bpo-25988: Emit a warning when use or import ABCs from 'collections'. (#5460)
1 parent a29ddf4 commit c66f9f8

File tree

2 files changed

+32
-22
lines changed

2 files changed

+32
-22
lines changed

Lib/collections/__init__.py

Lines changed: 27 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -17,16 +17,7 @@
1717
__all__ = ['deque', 'defaultdict', 'namedtuple', 'UserDict', 'UserList',
1818
'UserString', 'Counter', 'OrderedDict', 'ChainMap']
1919

20-
# For backwards compatibility, continue to make the collections ABCs
21-
# through Python 3.6 available through the collections module.
22-
# Note, no new collections ABCs were added in Python 3.7
2320
import _collections_abc
24-
from _collections_abc import (AsyncGenerator, AsyncIterable, AsyncIterator,
25-
Awaitable, ByteString, Callable, Collection, Container, Coroutine,
26-
Generator, Hashable, ItemsView, Iterable, Iterator, KeysView, Mapping,
27-
MappingView, MutableMapping, MutableSequence, MutableSet, Reversible,
28-
Sequence, Set, Sized, ValuesView)
29-
3021
from operator import itemgetter as _itemgetter, eq as _eq
3122
from keyword import iskeyword as _iskeyword
3223
import sys as _sys
@@ -40,30 +31,45 @@
4031
except ImportError:
4132
pass
4233
else:
43-
MutableSequence.register(deque)
34+
_collections_abc.MutableSequence.register(deque)
4435

4536
try:
4637
from _collections import defaultdict
4738
except ImportError:
4839
pass
4940

5041

42+
def __getattr__(name):
43+
# For backwards compatibility, continue to make the collections ABCs
44+
# through Python 3.6 available through the collections module.
45+
# Note, no new collections ABCs were added in Python 3.7
46+
if name in _collections_abc.__all__:
47+
obj = getattr(_collections_abc, name)
48+
import warnings
49+
warnings.warn("Using or importing the ABCs from 'collections' instead "
50+
"of from 'collections.abc' is deprecated, "
51+
"and in 3.8 it will stop working",
52+
DeprecationWarning, stacklevel=2)
53+
globals()[name] = obj
54+
return obj
55+
raise AttributeError(f'module {__name__!r} has no attribute {name!r}')
56+
5157
################################################################################
5258
### OrderedDict
5359
################################################################################
5460

55-
class _OrderedDictKeysView(KeysView):
61+
class _OrderedDictKeysView(_collections_abc.KeysView):
5662

5763
def __reversed__(self):
5864
yield from reversed(self._mapping)
5965

60-
class _OrderedDictItemsView(ItemsView):
66+
class _OrderedDictItemsView(_collections_abc.ItemsView):
6167

6268
def __reversed__(self):
6369
for key in reversed(self._mapping):
6470
yield (key, self._mapping[key])
6571

66-
class _OrderedDictValuesView(ValuesView):
72+
class _OrderedDictValuesView(_collections_abc.ValuesView):
6773

6874
def __reversed__(self):
6975
for key in reversed(self._mapping):
@@ -215,7 +221,7 @@ def __sizeof__(self):
215221
size += sizeof(self.__root) * n # proxy objects
216222
return size
217223

218-
update = __update = MutableMapping.update
224+
update = __update = _collections_abc.MutableMapping.update
219225

220226
def keys(self):
221227
"D.keys() -> a set-like object providing a view on D's keys"
@@ -229,7 +235,7 @@ def values(self):
229235
"D.values() -> an object providing a view on D's values"
230236
return _OrderedDictValuesView(self)
231237

232-
__ne__ = MutableMapping.__ne__
238+
__ne__ = _collections_abc.MutableMapping.__ne__
233239

234240
__marker = object()
235241

@@ -636,7 +642,7 @@ def update(*args, **kwds):
636642
raise TypeError('expected at most 1 arguments, got %d' % len(args))
637643
iterable = args[0] if args else None
638644
if iterable is not None:
639-
if isinstance(iterable, Mapping):
645+
if isinstance(iterable, _collections_abc.Mapping):
640646
if self:
641647
self_get = self.get
642648
for elem, count in iterable.items():
@@ -673,7 +679,7 @@ def subtract(*args, **kwds):
673679
iterable = args[0] if args else None
674680
if iterable is not None:
675681
self_get = self.get
676-
if isinstance(iterable, Mapping):
682+
if isinstance(iterable, _collections_abc.Mapping):
677683
for elem, count in iterable.items():
678684
self[elem] = self_get(elem, 0) - count
679685
else:
@@ -875,7 +881,7 @@ def __iand__(self, other):
875881
### ChainMap
876882
########################################################################
877883

878-
class ChainMap(MutableMapping):
884+
class ChainMap(_collections_abc.MutableMapping):
879885
''' A ChainMap groups multiple dicts (or other mappings) together
880886
to create a single, updateable view.
881887
@@ -983,7 +989,7 @@ def clear(self):
983989
### UserDict
984990
################################################################################
985991

986-
class UserDict(MutableMapping):
992+
class UserDict(_collections_abc.MutableMapping):
987993

988994
# Start by filling-out the abstract methods
989995
def __init__(*args, **kwargs):
@@ -1050,7 +1056,7 @@ def fromkeys(cls, iterable, value=None):
10501056
### UserList
10511057
################################################################################
10521058

1053-
class UserList(MutableSequence):
1059+
class UserList(_collections_abc.MutableSequence):
10541060
"""A more or less complete user-defined wrapper around list objects."""
10551061
def __init__(self, initlist=None):
10561062
self.data = []
@@ -1123,7 +1129,7 @@ def extend(self, other):
11231129
### UserString
11241130
################################################################################
11251131

1126-
class UserString(Sequence):
1132+
class UserString(_collections_abc.Sequence):
11271133
def __init__(self, seq):
11281134
if isinstance(seq, str):
11291135
self.data = seq

Modules/_decimal/_decimal.c

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5521,6 +5521,7 @@ PyInit__decimal(void)
55215521
PyObject *numbers = NULL;
55225522
PyObject *Number = NULL;
55235523
PyObject *collections = NULL;
5524+
PyObject *collections_abc = NULL;
55245525
PyObject *MutableMapping = NULL;
55255526
PyObject *obj = NULL;
55265527
DecCondMap *cm;
@@ -5595,7 +5596,8 @@ PyInit__decimal(void)
55955596
Py_CLEAR(obj);
55965597

55975598
/* MutableMapping */
5598-
ASSIGN_PTR(MutableMapping, PyObject_GetAttrString(collections,
5599+
ASSIGN_PTR(collections_abc, PyImport_ImportModule("collections.abc"));
5600+
ASSIGN_PTR(MutableMapping, PyObject_GetAttrString(collections_abc,
55995601
"MutableMapping"));
56005602
/* Create SignalDict type */
56015603
ASSIGN_PTR(PyDecSignalDict_Type,
@@ -5606,6 +5608,7 @@ PyInit__decimal(void)
56065608

56075609
/* Done with collections, MutableMapping */
56085610
Py_CLEAR(collections);
5611+
Py_CLEAR(collections_abc);
56095612
Py_CLEAR(MutableMapping);
56105613

56115614

@@ -5765,6 +5768,7 @@ PyInit__decimal(void)
57655768
Py_CLEAR(Number); /* GCOV_NOT_REACHED */
57665769
Py_CLEAR(Rational); /* GCOV_NOT_REACHED */
57675770
Py_CLEAR(collections); /* GCOV_NOT_REACHED */
5771+
Py_CLEAR(collections_abc); /* GCOV_NOT_REACHED */
57685772
Py_CLEAR(MutableMapping); /* GCOV_NOT_REACHED */
57695773
Py_CLEAR(SignalTuple); /* GCOV_NOT_REACHED */
57705774
Py_CLEAR(DecimalTuple); /* GCOV_NOT_REACHED */

0 commit comments

Comments
 (0)