From 09b7695f12f2b44d2df6898407d7e68dd9493ed4 Mon Sep 17 00:00:00 2001 From: Shantanu <12621235+hauntsaninja@users.noreply.github.com> Date: Thu, 4 May 2023 09:39:33 -0700 Subject: [PATCH] gh-91896: Deprecate collections.abc.ByteString (#102096) Co-authored-by: Alex Waygood Co-authored-by: Hugo van Kemenade --- Doc/library/collections.abc.rst | 6 ++++++ Doc/library/typing.rst | 3 +-- Doc/whatsnew/3.12.rst | 5 +++++ Lib/_collections_abc.py | 21 ++++++++++++++++++- Lib/test/test_collections.py | 19 +++++++++++++---- ...3-03-08-02-45-46.gh-issue-91896.kgON_a.rst | 1 + 6 files changed, 48 insertions(+), 7 deletions(-) create mode 100644 Misc/NEWS.d/next/Library/2023-03-08-02-45-46.gh-issue-91896.kgON_a.rst diff --git a/Doc/library/collections.abc.rst b/Doc/library/collections.abc.rst index 669b7345499..43a3286ba83 100644 --- a/Doc/library/collections.abc.rst +++ b/Doc/library/collections.abc.rst @@ -273,6 +273,12 @@ Collections Abstract Base Classes -- Detailed Descriptions The index() method added support for *stop* and *start* arguments. + .. deprecated-removed:: 3.12 3.14 + The :class:`ByteString` ABC has been deprecated. + For use in typing, prefer a union, like ``bytes | bytearray``, or + :class:`collections.abc.Buffer`. + For use as an ABC, prefer :class:`Sequence` or :class:`collections.abc.Buffer`. + .. class:: Set MutableSet diff --git a/Doc/library/typing.rst b/Doc/library/typing.rst index c22fc0b28a5..162041fc7a8 100644 --- a/Doc/library/typing.rst +++ b/Doc/library/typing.rst @@ -2139,8 +2139,7 @@ Corresponding to collections in :mod:`collections.abc` annotate arguments of any of the types mentioned above. .. deprecated:: 3.9 - :class:`collections.abc.ByteString` now supports subscripting (``[]``). - See :pep:`585` and :ref:`types-genericalias`. + Prefer :class:`collections.abc.Buffer`, or a union like ``bytes | bytearray | memoryview``. .. class:: Collection(Sized, Iterable[T_co], Container[T_co]) diff --git a/Doc/whatsnew/3.12.rst b/Doc/whatsnew/3.12.rst index 3fe3310a26e..4a988bf4b99 100644 --- a/Doc/whatsnew/3.12.rst +++ b/Doc/whatsnew/3.12.rst @@ -792,6 +792,11 @@ Pending Removal in Python 3.14 (Contributed by Jason R. Coombs and Hugo van Kemenade in :gh:`93963`.) +* Deprecated :class:`collections.abc.ByteString`. + Prefer :class:`Sequence` or :class:`collections.abc.Buffer`. + For use in typing, prefer a union, like ``bytes | bytearray``, or :class:`collections.abc.Buffer`. + (Contributed by Shantanu Jain in :gh:`91896`.) + * Creating immutable types (:data:`Py_TPFLAGS_IMMUTABLETYPE`) with mutable bases using the C API. diff --git a/Lib/_collections_abc.py b/Lib/_collections_abc.py index 2117190cf8b..601107d2d86 100644 --- a/Lib/_collections_abc.py +++ b/Lib/_collections_abc.py @@ -1071,8 +1071,27 @@ Sequence.register(str) Sequence.register(range) Sequence.register(memoryview) +class _DeprecateByteStringMeta(ABCMeta): + def __new__(cls, name, bases, namespace, **kwargs): + if name != "ByteString": + import warnings -class ByteString(Sequence): + warnings._deprecated( + "collections.abc.ByteString", + remove=(3, 14), + ) + return super().__new__(cls, name, bases, namespace, **kwargs) + + def __instancecheck__(cls, instance): + import warnings + + warnings._deprecated( + "collections.abc.ByteString", + remove=(3, 14), + ) + return super().__instancecheck__(instance) + +class ByteString(Sequence, metaclass=_DeprecateByteStringMeta): """This unifies bytes and bytearray. XXX Should add all their methods. diff --git a/Lib/test/test_collections.py b/Lib/test/test_collections.py index 8fc28a6bf98..bb8b352518e 100644 --- a/Lib/test/test_collections.py +++ b/Lib/test/test_collections.py @@ -1940,14 +1940,25 @@ class TestCollectionABCs(ABCTestCase): def test_ByteString(self): for sample in [bytes, bytearray]: - self.assertIsInstance(sample(), ByteString) + with self.assertWarns(DeprecationWarning): + self.assertIsInstance(sample(), ByteString) self.assertTrue(issubclass(sample, ByteString)) for sample in [str, list, tuple]: - self.assertNotIsInstance(sample(), ByteString) + with self.assertWarns(DeprecationWarning): + self.assertNotIsInstance(sample(), ByteString) self.assertFalse(issubclass(sample, ByteString)) - self.assertNotIsInstance(memoryview(b""), ByteString) + with self.assertWarns(DeprecationWarning): + self.assertNotIsInstance(memoryview(b""), ByteString) self.assertFalse(issubclass(memoryview, ByteString)) - self.validate_abstract_methods(ByteString, '__getitem__', '__len__') + with self.assertWarns(DeprecationWarning): + self.validate_abstract_methods(ByteString, '__getitem__', '__len__') + + with self.assertWarns(DeprecationWarning): + class X(ByteString): pass + + with self.assertWarns(DeprecationWarning): + # No metaclass conflict + class Z(ByteString, Awaitable): pass def test_Buffer(self): for sample in [bytes, bytearray, memoryview]: diff --git a/Misc/NEWS.d/next/Library/2023-03-08-02-45-46.gh-issue-91896.kgON_a.rst b/Misc/NEWS.d/next/Library/2023-03-08-02-45-46.gh-issue-91896.kgON_a.rst new file mode 100644 index 00000000000..b5282d3d612 --- /dev/null +++ b/Misc/NEWS.d/next/Library/2023-03-08-02-45-46.gh-issue-91896.kgON_a.rst @@ -0,0 +1 @@ +Deprecate :class:`collections.abc.ByteString`