summaryrefslogtreecommitdiffstats
path: root/Lib
diff options
context:
space:
mode:
authorAlex Waygood <Alex.Waygood@Gmail.com>2023-05-12 06:01:31 (GMT)
committerGitHub <noreply@github.com>2023-05-12 06:01:31 (GMT)
commitf0f5bb32043e1223d8c413e763cd93061d4f9fac (patch)
tree217a4dbfc9e85a7e2722b6791062f6a96bdadaab /Lib
parenta0a98ddb31591357bead4694b21717cb4034924f (diff)
downloadcpython-f0f5bb32043e1223d8c413e763cd93061d4f9fac.zip
cpython-f0f5bb32043e1223d8c413e763cd93061d4f9fac.tar.gz
cpython-f0f5bb32043e1223d8c413e763cd93061d4f9fac.tar.bz2
gh-91896: Improve visibility of `ByteString` deprecation warnings (#104294)
Diffstat (limited to 'Lib')
-rw-r--r--Lib/collections/abc.py9
-rw-r--r--Lib/test/libregrtest/refleak.py16
-rw-r--r--Lib/test/test_collections.py10
-rw-r--r--Lib/test/test_typing.py30
-rw-r--r--Lib/typing.py32
5 files changed, 85 insertions, 12 deletions
diff --git a/Lib/collections/abc.py b/Lib/collections/abc.py
index 86ca8b8..60b1eb6 100644
--- a/Lib/collections/abc.py
+++ b/Lib/collections/abc.py
@@ -1,3 +1,12 @@
from _collections_abc import *
from _collections_abc import __all__
from _collections_abc import _CallableGenericAlias
+
+_deprecated_ByteString = globals().pop("ByteString")
+
+def __getattr__(attr):
+ if attr == "ByteString":
+ import warnings
+ warnings._deprecated("collections.abc.ByteString", remove=(3, 14))
+ return _deprecated_ByteString
+ raise AttributeError(f"module 'collections.abc' has no attribute {attr!r}")
diff --git a/Lib/test/libregrtest/refleak.py b/Lib/test/libregrtest/refleak.py
index 2de8c6c..776a9e9 100644
--- a/Lib/test/libregrtest/refleak.py
+++ b/Lib/test/libregrtest/refleak.py
@@ -48,11 +48,13 @@ def dash_R(ns, test_name, test_func):
else:
zdc = zipimport._zip_directory_cache.copy()
abcs = {}
- for abc in [getattr(collections.abc, a) for a in collections.abc.__all__]:
- if not isabstract(abc):
- continue
- for obj in abc.__subclasses__() + [abc]:
- abcs[obj] = _get_dump(obj)[0]
+ # catch and ignore collections.abc.ByteString deprecation
+ with warnings.catch_warnings(action='ignore', category=DeprecationWarning):
+ for abc in [getattr(collections.abc, a) for a in collections.abc.__all__]:
+ if not isabstract(abc):
+ continue
+ for obj in abc.__subclasses__() + [abc]:
+ 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
@@ -173,7 +175,9 @@ def dash_R_cleanup(fs, ps, pic, zdc, abcs):
zipimport._zip_directory_cache.update(zdc)
# Clear ABC registries, restoring previously saved ABC registries.
- abs_classes = [getattr(collections.abc, a) for a in collections.abc.__all__]
+ # ignore deprecation warning for collections.abc.ByteString
+ with warnings.catch_warnings(action='ignore', category=DeprecationWarning):
+ abs_classes = [getattr(collections.abc, a) for a in collections.abc.__all__]
abs_classes = filter(isabstract, abs_classes)
for abc in abs_classes:
for obj in abc.__subclasses__() + [abc]:
diff --git a/Lib/test/test_collections.py b/Lib/test/test_collections.py
index bb8b352..f0736b8 100644
--- a/Lib/test/test_collections.py
+++ b/Lib/test/test_collections.py
@@ -11,6 +11,7 @@ from itertools import product, chain, combinations
import string
import sys
from test import support
+from test.support.import_helper import import_fresh_module
import types
import unittest
@@ -25,7 +26,7 @@ from collections.abc import Sized, Container, Callable, Collection
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):
@@ -1939,6 +1940,8 @@ class TestCollectionABCs(ABCTestCase):
nativeseq, seqseq, (letter, start, stop))
def test_ByteString(self):
+ with self.assertWarns(DeprecationWarning):
+ from collections.abc import ByteString
for sample in [bytes, bytearray]:
with self.assertWarns(DeprecationWarning):
self.assertIsInstance(sample(), ByteString)
@@ -1960,6 +1963,11 @@ class TestCollectionABCs(ABCTestCase):
# No metaclass conflict
class Z(ByteString, Awaitable): pass
+ def test_ByteString_attribute_access(self):
+ collections_abc = import_fresh_module("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)
diff --git a/Lib/test/test_typing.py b/Lib/test/test_typing.py
index f162e58..3422dc1 100644
--- a/Lib/test/test_typing.py
+++ b/Lib/test/test_typing.py
@@ -8,6 +8,7 @@ import pickle
import re
import sys
import warnings
+from test.support.import_helper import import_fresh_module
from unittest import TestCase, main, skipUnless, skip
from unittest.mock import patch
from copy import copy, deepcopy
@@ -3908,7 +3909,14 @@ class GenericTests(BaseTestCase):
self.assertEqual(MyChain[int]().__orig_class__, MyChain[int])
def test_all_repr_eq_any(self):
- objs = (getattr(typing, el) for el in typing.__all__)
+ typing = import_fresh_module("typing")
+ with warnings.catch_warnings(record=True) as wlog:
+ warnings.filterwarnings('always', '', DeprecationWarning)
+ objs = [getattr(typing, el) for el in typing.__all__]
+ self.assertEqual(
+ [str(w.message) for w in wlog],
+ ["'typing.ByteString' is deprecated and slated for removal in Python 3.14"]
+ )
for obj in objs:
self.assertNotEqual(repr(obj), '')
self.assertEqual(obj, obj)
@@ -5996,8 +6004,16 @@ class CollectionsAbcTests(BaseTestCase):
self.assertNotIsInstance((), typing.MutableSequence)
def test_bytestring(self):
- self.assertIsInstance(b'', typing.ByteString)
- self.assertIsInstance(bytearray(b''), typing.ByteString)
+ with self.assertWarns(DeprecationWarning):
+ from typing import ByteString
+ with self.assertWarns(DeprecationWarning):
+ self.assertIsInstance(b'', ByteString)
+ with self.assertWarns(DeprecationWarning):
+ self.assertIsInstance(bytearray(b''), ByteString)
+ with self.assertWarns(DeprecationWarning):
+ class Foo(ByteString): ...
+ with self.assertWarns(DeprecationWarning):
+ class Bar(ByteString, typing.Awaitable): ...
def test_list(self):
self.assertIsSubclass(list, typing.List)
@@ -8293,6 +8309,10 @@ SpecialAttrsT = typing.TypeVar('SpecialAttrsT', int, float, complex)
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',
@@ -8301,7 +8321,7 @@ class SpecialAttrsTests(BaseTestCase):
typing.AsyncIterable: 'AsyncIterable',
typing.AsyncIterator: 'AsyncIterator',
typing.Awaitable: 'Awaitable',
- typing.ByteString: 'ByteString',
+ typing_ByteString: 'ByteString',
typing.Callable: 'Callable',
typing.ChainMap: 'ChainMap',
typing.Collection: 'Collection',
@@ -8626,6 +8646,8 @@ class AllTests(BaseTestCase):
getattr(v, '__module__', None) == typing.__name__
)
}
+ # Deprecated; added dynamically via module __getattr__
+ computed_all.add("ByteString")
self.assertSetEqual(computed_all, actual_all)
diff --git a/Lib/typing.py b/Lib/typing.py
index 62c7dd3..bf7bd24 100644
--- a/Lib/typing.py
+++ b/Lib/typing.py
@@ -1599,6 +1599,22 @@ class _SpecialGenericAlias(_NotIterable, _BaseGenericAlias, _root=True):
def __ror__(self, left):
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'
@@ -2756,7 +2772,6 @@ Mapping = _alias(collections.abc.Mapping, 2)
MutableMapping = _alias(collections.abc.MutableMapping, 2)
Sequence = _alias(collections.abc.Sequence, 1)
MutableSequence = _alias(collections.abc.MutableSequence, 1)
-ByteString = _alias(collections.abc.ByteString, 0) # Not generic
# Tuple accepts variable number of parameters.
Tuple = _TupleType(tuple, -1, inst=False, name='Tuple')
Tuple.__doc__ = \
@@ -3556,3 +3571,18 @@ def override(method: F, /) -> F:
# read-only property, TypeError if it's a builtin class.
pass
return method
+
+
+def __getattr__(attr):
+ if attr == "ByteString":
+ import warnings
+ warnings._deprecated("typing.ByteString", remove=(3, 14))
+ with warnings.catch_warnings(
+ action="ignore", category=DeprecationWarning
+ ):
+ # Not generic
+ ByteString = globals()["ByteString"] = _DeprecatedGenericAlias(
+ collections.abc.ByteString, 0, removal_version=(3, 14)
+ )
+ return ByteString
+ raise AttributeError(f"module 'typing' has no attribute {attr!r}")