Improved modules
================
+collections.abc
+---------------
+
+* :class:`collections.abc.ByteString` has been removed from
+ ``collections.abc.__all__``. :class:`!collections.abc.ByteString` has been
+ deprecated since Python 3.12, and is scheduled for removal in Python 3.17.
+
+* The following statements now cause ``DeprecationWarning``\ s to be emitted at
+ runtime:
+
+ * ``from collections.abc import ByteString``
+ * ``import collections.abc; collections.abc.ByteString``.
+
+ ``DeprecationWarning``\ s were already emitted if
+ :class:`collections.abc.ByteString` was subclassed or used as the second
+ argument to :func:`isinstance` or :func:`issubclass`, but warnings were not
+ previously emitted if it was merely imported or accessed from the
+ :mod:`!collections.abc` module.
+
dbm
---
as it was incorrectly infered in runtime before.
(Contributed by Nikita Sobolev in :gh:`137191`.)
+* :class:`typing.ByteString` has been removed from ``typing.__all__``.
+ :class:`!typing.ByteString` has been deprecated since Python 3.9, and is
+ scheduled for removal in Python 3.17.
+
+* The following statements now cause ``DeprecationWarning``\ s to be emitted at
+ runtime:
+
+ * ``from typing import ByteString``
+ * ``import typing; typing.ByteString``.
+
+ ``DeprecationWarning``\ s were already emitted if :class:`typing.ByteString`
+ was subclassed or used as the second argument to :func:`isinstance` or
+ :func:`issubclass`, but warnings were not previously emitted if it was merely
+ imported or accessed from the :mod:`!typing` module.
+
unicodedata
-----------
"Mapping", "MutableMapping",
"MappingView", "KeysView", "ItemsView", "ValuesView",
"Sequence", "MutableSequence",
- "ByteString", "Buffer",
+ "Buffer",
]
# This module has been renamed from collections.abc to _collections_abc to
MutableSequence.register(list)
MutableSequence.register(bytearray)
+
+_deprecated_ByteString = globals().pop("ByteString")
+
+def __getattr__(attr):
+ if attr == "ByteString":
+ import warnings
+ warnings._deprecated("collections.abc.ByteString", remove=(3, 17))
+ globals()["ByteString"] = _deprecated_ByteString
+ return _deprecated_ByteString
+ raise AttributeError(f"module 'collections.abc' has no attribute {attr!r}")
for obj in abc.__subclasses__() + [abc]:
abcs[obj] = _get_dump(obj)[0]
+ # `ByteString` is not included in `collections.abc.__all__`
+ with warnings.catch_warnings(action='ignore', category=DeprecationWarning):
+ ByteString = collections.abc.ByteString
+ # Mypy doesn't even think `ByteString` is a class, hence the `type: ignore`
+ for obj in ByteString.__subclasses__() + [ByteString]: # type: ignore[attr-defined]
+ abcs[obj] = _get_dump(obj)[0]
+
# bpo-31217: Integer pool to get a single integer object for the same
# value. The pool is used to prevent false alarm when checking for memory
# block leaks. Fill the pool with values in -1000..1000 which are the most
# Clear ABC registries, restoring previously saved ABC registries.
abs_classes = [getattr(collections.abc, a) for a in collections.abc.__all__]
+ with warnings.catch_warnings(action='ignore', category=DeprecationWarning):
+ abs_classes.append(collections.abc.ByteString)
abs_classes = filter(isabstract, abs_classes)
for abc in abs_classes:
for obj in abc.__subclasses__() + [abc]:
import string
import sys
from test import support
+from test.support.import_helper import import_fresh_module
import types
import unittest
from collections.abc import Set, MutableSet
from collections.abc import Mapping, MutableMapping, KeysView, ItemsView, ValuesView
from collections.abc import Sequence, MutableSequence
-from collections.abc import ByteString, Buffer
+from collections.abc import Buffer
class TestUserObjects(unittest.TestCase):
nativeseq, seqseq, (letter, start, stop))
def test_ByteString(self):
+ previous_sys_modules = sys.modules.copy()
+ self.addCleanup(sys.modules.update, previous_sys_modules)
+
+ for module in "collections", "_collections_abc", "collections.abc":
+ sys.modules.pop(module, None)
+
+ with self.assertWarns(DeprecationWarning):
+ from collections.abc import ByteString
for sample in [bytes, bytearray]:
with self.assertWarns(DeprecationWarning):
self.assertIsInstance(sample(), ByteString)
# No metaclass conflict
class Z(ByteString, Awaitable): pass
+ def test_ByteString_attribute_access(self):
+ collections_abc = import_fresh_module(
+ "collections.abc",
+ fresh=("collections", "_collections_abc")
+ )
+ with self.assertWarns(DeprecationWarning):
+ collections_abc.ByteString
+
def test_Buffer(self):
for sample in [bytes, bytearray, memoryview]:
self.assertIsInstance(sample(b"x"), Buffer)
import pickle
import re
import sys
+import warnings
from unittest import TestCase, main, skip
from unittest.mock import patch
from copy import copy, deepcopy
self.assertNotIsInstance((), typing.MutableSequence)
def test_bytestring(self):
+ previous_typing_module = sys.modules.pop("typing", None)
+ self.addCleanup(sys.modules.__setitem__, "typing", previous_typing_module)
+
+ with self.assertWarns(DeprecationWarning):
+ from typing import ByteString
+ with self.assertWarns(DeprecationWarning):
+ self.assertIsInstance(b'', ByteString)
with self.assertWarns(DeprecationWarning):
- self.assertIsInstance(b'', typing.ByteString)
+ self.assertIsInstance(bytearray(b''), ByteString)
with self.assertWarns(DeprecationWarning):
- self.assertIsInstance(bytearray(b''), typing.ByteString)
+ self.assertIsSubclass(bytes, ByteString)
with self.assertWarns(DeprecationWarning):
- class Foo(typing.ByteString): ...
+ self.assertIsSubclass(bytearray, ByteString)
with self.assertWarns(DeprecationWarning):
- class Bar(typing.ByteString, typing.Awaitable): ...
+ class Foo(ByteString): ...
+ with self.assertWarns(DeprecationWarning):
+ class Bar(ByteString, typing.Awaitable): ...
def test_list(self):
self.assertIsSubclass(list, typing.List)
class SpecialAttrsTests(BaseTestCase):
def test_special_attrs(self):
+ with warnings.catch_warnings(
+ action='ignore', category=DeprecationWarning
+ ):
+ typing_ByteString = typing.ByteString
cls_to_check = {
# ABC classes
typing.AbstractSet: 'AbstractSet',
typing.AsyncIterable: 'AsyncIterable',
typing.AsyncIterator: 'AsyncIterator',
typing.Awaitable: 'Awaitable',
- typing.ByteString: 'ByteString',
+ typing_ByteString: 'ByteString',
typing.Callable: 'Callable',
typing.ChainMap: 'ChainMap',
typing.Collection: 'Collection',
# there's a few types and metaclasses that aren't exported
not k.endswith(('Meta', '_contra', '_co')) and
not k.upper() == k and
- # but export all things that have __module__ == 'typing'
+ k not in {"ByteString"} and
+ # but export all other things that have __module__ == 'typing'
getattr(v, '__module__', None) == typing.__name__
)
}
# ABCs (from collections.abc).
'AbstractSet', # collections.abc.Set.
- 'ByteString',
'Container',
'ContextManager',
'Hashable',
return Union[left, self]
-class _DeprecatedGenericAlias(_SpecialGenericAlias, _root=True):
- def __init__(
- self, origin, nparams, *, removal_version, inst=True, name=None
- ):
- super().__init__(origin, nparams, inst=inst, name=name)
- self._removal_version = removal_version
-
- def __instancecheck__(self, inst):
- import warnings
- warnings._deprecated(
- f"{self.__module__}.{self._name}", remove=self._removal_version
- )
- return super().__instancecheck__(inst)
-
-
class _CallableGenericAlias(_NotIterable, _GenericAlias, _root=True):
def __repr__(self):
assert self._name == 'Callable'
MutableMapping = _alias(collections.abc.MutableMapping, 2)
Sequence = _alias(collections.abc.Sequence, 1)
MutableSequence = _alias(collections.abc.MutableSequence, 1)
-ByteString = _DeprecatedGenericAlias(
- collections.abc.ByteString, 0, removal_version=(3, 17) # Not generic.
-)
# Tuple accepts variable number of parameters.
Tuple = _TupleType(tuple, -1, inst=False, name='Tuple')
Tuple.__doc__ = \
)
warnings.warn(depr_message, category=DeprecationWarning, stacklevel=2)
obj = _collect_type_parameters
+ elif attr == "ByteString":
+ import warnings
+
+ warnings._deprecated(
+ "typing.ByteString",
+ message=(
+ "{name!r} and 'collections.abc.ByteString' are deprecated "
+ "and slated for removal in Python {remove}"
+ ),
+ remove=(3, 17)
+ )
+
+ class _DeprecatedGenericAlias(_SpecialGenericAlias, _root=True):
+ def __init__(
+ self, origin, nparams, *, removal_version, inst=True, name=None
+ ):
+ super().__init__(origin, nparams, inst=inst, name=name)
+ self._removal_version = removal_version
+
+ def __instancecheck__(self, inst):
+ import warnings
+ warnings._deprecated(
+ f"{self.__module__}.{self._name}", remove=self._removal_version
+ )
+ return super().__instancecheck__(inst)
+
+ def __subclasscheck__(self, cls):
+ import warnings
+ warnings._deprecated(
+ f"{self.__module__}.{self._name}", remove=self._removal_version
+ )
+ return super().__subclasscheck__(cls)
+
+ with warnings.catch_warnings(
+ action="ignore", category=DeprecationWarning
+ ):
+ # Not generic
+ ByteString = globals()["ByteString"] = _DeprecatedGenericAlias(
+ collections.abc.ByteString, 0, removal_version=(3, 17)
+ )
+
+ return ByteString
else:
raise AttributeError(f"module {__name__!r} has no attribute {attr!r}")
globals()[attr] = obj
--- /dev/null
+:class:`collections.abc.ByteString` has been removed from
+``collections.abc.__all__``, and :class:`typing.ByteString` has been removed
+from ``typing.__all__``. The former has been deprecated since Python 3.12,
+and the latter has been deprecated since Python 3.9. Both classes are
+scheduled for removal in Python 3.17.
+
+Additionally, the following statements now cause ``DeprecationWarning``\ s to
+be emitted at runtime: ``from collections.abc import ByteString``, ``from
+typing import ByteString``, ``import collections.abc;
+collections.abc.ByteString`` and ``import typing; typing.ByteString``. Both
+classes already caused ``DeprecationWarning``\ s to be emitted if they were
+subclassed or used as the second argument to ``isinstance()`` or
+``issubclass()``, but they did not previously lead to
+``DeprecationWarning``\ s if they were merely imported or accessed from their
+respective modules.