8000 gh-91896: Improve visibility of `ByteString` deprecation warnings · python/cpython@424486a · GitHub
[go: up one dir, main page]

Skip to content

Commit 424486a

Browse files
committed
gh-91896: Improve visibility of ByteString deprecation warnings
1 parent 1f56795 commit 424486a

File tree

4 files changed

+75
-6
lines changed

4 files changed

+75
-6
lines changed

Lib/collections/abc.py

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,12 @@
11
from _collections_abc import *
22
from _collections_abc import __all__
33
from _collections_abc import _CallableGenericAlias
4+
5+
_deprecated_ByteString = globals().pop("ByteString")
6+
7+
def __getattr__(attr):
8+
if attr == "ByteString":
9+
import warnings
10+
warnings._deprecated("collections.abc.ByteString", remove=(3, 14))
11+
return _deprecated_ByteString
12+
raise AttributeError(f"module 'collections.abc' has no attribute {attr!r}")

Lib/test/test_collections.py

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@
1111
import string
1212
import sys
1313
from test import support
14+
from test.support.import_helper import import_fresh_module
1415
import types
1516
import unittest
1617

@@ -25,7 +26,7 @@
2526
from collections.abc import Set, MutableSet
2627
from collections.abc import Mapping, MutableMapping, KeysView, ItemsView, ValuesView
2728
from collections.abc import Sequence, MutableSequence
28-
from collections.abc import ByteString, Buffer
29+
from collections.abc import Buffer
2930

3031

3132
class TestUserObjects(unittest.TestCase):
@@ -1939,6 +1940,8 @@ def assert_index_same(seq1, seq2, index_args):
19391940
nativeseq, seqseq, (letter, start, stop))
19401941

19411942
def test_ByteString(self):
1943+
with self.assertWarns(DeprecationWarning):
1944+
from collections.abc import ByteString
19421945
for sample in [bytes, bytearray]:
19431946
with self.assertWarns(DeprecationWarning):
19441947
self.assertIsInstance(sample(), ByteString)
@@ -1960,6 +1963,11 @@ class X(ByteString): pass
19601963
# No metaclass conflict
19611964
class Z(ByteString, Awaitable): pass
19621965

1966+
def test_ByteString_attribute_access(self):
1967+
collections_abc = import_fresh_module("collections.abc")
1968+
with self.assertWarns(DeprecationWarning):
1969+
collections_abc.ByteString
1970+
19631971
def test_Buffer(self):
19641972
for sample in [bytes, bytearray, memoryview]:
19651973
self.assertIsInstance(sample(b"x"), Buffer)

Lib/test/test_typing.py

Lines changed: 26 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@
88
import re
99
import sys
1010
import warnings
11+
from test.support.import_helper import import_fresh_module
1112
from unittest import TestCase, main, skipUnless, skip
1213
from unittest.mock import patch
1314
from copy import copy, deepcopy
@@ -3908,7 +3909,14 @@ class MyChain(typing.ChainMap[str, T]): ...
39083909
self.assertEqual(MyChain[int]().__orig_class__, MyChain[int])
39093910

39103911
def test_all_repr_eq_any(self):
3911-
objs = (getattr(typing, el) for el in typing.__all__)
3912+
typing = import_fresh_module("typing")
3913+
with warnings.catch_warnings(record=True) as wlog:
3914+
warnings.filterwarnings('always', '', DeprecationWarning)
3915+
objs = [getattr(typing, el) for el in typing.__all__]
3916+
self.assertEqual(
3917+
[str(w.message) for w in wlog],
3918+
["'typing.ByteString' is deprecated and slated for removal in Python 3.14"]
3919+
)
39123920
for obj in objs:
39133921
self.assertNotEqual(repr(obj), '')
39143922
self.assertEqual(obj, obj)
@@ -5996,8 +6004,16 @@ def test_mutablesequence(self):
59966004
self.assertNotIsInstance((), typing.MutableSequence)
59976005

59986006
def test_bytestring(self):
5999-
self.assertIsInstance(b'', typing.ByteString)
6000-
self.assertIsInstance(bytearray(b''), typing.ByteString)
6007+
with self.assertWarns(DeprecationWarning):
6008+
from typing import ByteString
6009+
with self.assertWarns(DeprecationWarning):
6010+
self.assertIsInstance(b'', ByteString)
6011+
with self.assertWarns(DeprecationWarning):
6012+
self.assertIsInstance(bytearray(b''), ByteString)
6013+
with self.assertWarns(DeprecationWarning):
6014+
class Foo(ByteString):
6015+
def __len__(self): return 42
6016+
def __getitem__(self, n): return 42
60016017

60026018
def test_list(self):
60036019
self.assertIsSubclass(list, typing.List)
@@ -8293,6 +8309,10 @@ def test_no_isinstance(self):
82938309
class SpecialAttrsTests(BaseTestCase):
82948310

82958311
def test_special_attrs(self):
8312+
with warnings.catch_warnings(
8313+
action='ignore', category=DeprecationWarning
8314+
):
8315+
typing_ByteString = typing.ByteString
82968316
cls_to_check = {
82978317
# ABC classes
82988318
typing.AbstractSet: 'AbstractSet',
@@ -8301,7 +8321,7 @@ def test_special_attrs(self):
83018321
typing.AsyncIterable: 'AsyncIterable',
83028322
typing.AsyncIterator: 'AsyncIterator',
83038323
typing.Awaitable: 'Awaitable',
8304-
typing.ByteString: 'ByteString',
8324+
typing_ByteString: 'ByteString',
83058325
typing.Callable: 'Callable',
83068326
typing.ChainMap: 'ChainMap',
83078327
typing.Collection: 'Collection',
@@ -8626,6 +8646,8 @@ def test_all_exported_names(self):
86268646
getattr(v, '__module__', None) == typing.__name__
86278647
)
86288648
}
8649+
# Deprecated; added dynamically via module __getattr__
8650+
computed_all.add("ByteString")
86298651
self.assertSetEqual(computed_all, actual_all)
86308652

86318653

Lib/typing.py

Lines changed: 31 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1604,6 +1604,22 @@ def __or__(self, right):
16041604
def __ror__(self, left):
16051605
return Union[left, self]
16061606

1607+
1608+
class _DeprecatedGenericAlias(_SpecialGenericAlias, _root=True):
1609+
def __init__(
1610+
self, origin, nparams, *, removal_version, inst=True, name=None
1611+
):
1612+
super().__init__(origin, nparams, inst=inst, name=name)
1613+
self._removal_version = removal_version
1614+
1615+
def __instancecheck__(self, inst):
1616+
import warnings
1617+
warnings._deprecated(
1618+
f"{self.__module__}.{self._name}", remove=self._removal_version
1619+
)
1620+
return super().__instancecheck__(inst)
1621+
1622+
16071623
class _CallableGenericAlias(_NotIterable, _GenericAlias, _root=True):
16081624
def __repr__(self):
16091625
assert self._name == 'Callable'
@@ -2763,7 +2779,6 @@ class Other(Leaf): # Error reported by type checker
27632779
MutableMapping = _alias(collections.abc.MutableMapping, 2)
27642780
Sequence = _alias(collections.abc.Sequence, 1)
27652781
MutableSequence = _alias(collections.abc.MutableSequence, 1)
2766-
ByteString = _alias(collections.abc.ByteString, 0) # Not generic
27672782
# Tuple accepts variable number of parameters.
27682783
Tuple = _TupleType(tuple, -1, inst=False, name='Tuple')
27692784
Tuple.__doc__ = \
@@ -3563,3 +3578,18 @@ def method(self) -> None:
35633578
# read-only property, TypeError if it's a builtin class.
35643579
pass
35653580
return method
3581+
3582+
3583+
def __getattr__(attr):
3584+
if attr == "ByteString":
3585+
import warnings
3586+
warnings._deprecated("typing.ByteString", remove=(3, 14))
3587+
with warnings.catch_warnings(
3588+
action="ignore", category=DeprecationWarning
3589+
):
3590+
# Not generic
3591+
ByteString = globals()["ByteString"] = _DeprecatedGenericAlias(
3592+
collections.abc.ByteString, 0, removal_version=(3, 14)
3593+
)
3594+
return ByteString
3595+
raise AttributeError(f"module 'typing' has no attribute {attr!r}")

0 commit comments

Comments
 (0)
0