Repository navigation
collections.abc.ByteString is not equivalent to typing.ByteString #102092
Description
Activity
- addedtype-bugAn unexpected behavior, bug, or errorAn unexpected behavior, bug, or errordocsDocumentation in the Doc dirDocumentation in the Doc dir
on Feb 20, 2023 Thanks for the research here! Before we make changes in CPython it might make sense to wait for PEP 688 to be accepted (hopefully soon?), since that will affect what we should point users to.
I'm not sure I see the issue, though. At runtime
typing.ByteStringreally is an alias forcollections.abc.ByteString:ByteString = _alias(collections.abc.ByteString, 0) # Not generic.And
memoryviewis not a subclass of either type at runtime:In [51]: issubclass(memoryview, collections.abc.ByteString) Out[51]: False In [52]: issubclass(memoryview, typing.ByteString) Out[52]: FalseSo while I am in favor of deprecating both ByteString objects, I don't see why we need to decouple them.
... I don't see why we need to decouple them.
I was hoping we could get away with treating
typing.ByteStringasbytes | bytearray | memoryview. This seemed like too breaking of a change for acollections.abc.ByteString, since the whole point of ABCs is to make your own subtypes of them and there are indications thatcollections.abc.ByteStringwas genuinely meant to be likebytes | bytearray.I realise I was also kind of hoping we could just... pretend that
collections.abc.ByteStringdoesn't exist, since I'd like to avoid users thinking there's an interface there.Anyway, the claim is that
typing.ByteStringhas clearly defined, reasonably well documented semantics here:This type represents the types bytes, bytearray, and memoryview of byte sequences.
And while PEP 688 provides a path for something with better semantics (since users of
typing.ByteStringwould probably want all buffers), maybe the existing semantics are still useful, and we can "fix" this outright bug in the implementation oftyping.ByteString.
So possible "fixes" are:
- Make
typing.ByteStringequivalent tobytes | bytearray | memoryview. As I type this, I'm realising this has the downside it would break any user who was subclassingtyping.ByteString
(python/typeshed#9783 doesn't surface issues and I couldn't find any
typing.ByteStringsubclasses on grep.app, and I found acollections.abc.ByteStringone)- Register
memoryviewwithcollections.abc.ByteString. While desirable for use viatyping.ByteString, there are indications thatcollections.abc.ByteStringwas genuinely meant to be justbytes | bytearrayand e.g. havestartswithand things like that. In which case this could break user expectations. E.g., the docstring says:
This unifies bytes and bytearray. XXX Should add all their methods.
edit: it is also tested that memoryview is not a
collections.abc.ByteString- Don't "fix", and just aggressively pursue the deprecations.
- Make
I guess 2 might be more viable than I initially gave it credit for. This table is pretty clear that the interface for
collections.abc.ByteStringis__getitem__+__len__. More authoritative than the "XXX" docstring, at least :-)We can still go with option 3 and just deprecate instead of touching these, if we feel it's too messy.
Reacted by Raymond HettingerSo your claim is essentially that there is a discrepancy between the implementation and the documentation for
typing.ByteString, and we should fix that discrepancy by adjusting the implementation. I'm not sure why you don't want to change the documentation instead, though.memoryviewis not a ByteString at runtime or according to typeshed, so it seems less disruptive to adjust the documentation.My preference is to deprecate both variants of
ByteString. As I see it, there are three possible use cases forByteString, and it doesn't work well for any of them:- A shorthand for "any buffer type". ByteString doesn't actually mean this; PEP 688 will provide a solid solution for this use case.
- A shorthand for "bytes | bytearray", or possibly "bytes | bytearray | memoryview" depending on which part of the docs we believe. Users who want this should just write "bytes | bytearray": it's barely any longer and does not suffer from the ambiguity of
ByteString. - An ABC representing the common interface of
bytesandbytearray, as suggested by the "XXX" comment in the docstring. But sincecollections.abc.ByteStringdoesn't define any of this interface, it's not actually useful for this purpose. And as @rhettinger explained when I tried to add the shared bytes/bytearray methods, backward compatibility means we can essentially never add methods to an ABC.
ByteStringis purely a source of confusion and I don't think it is useful. Let's deprecate it and remove it in 3.14.Okay, great. #102096 adds deprecation warnings to collections.abc.ByteString
+1 on the deprecation and eventual removal. Since the situation is so muddled, and
ByteStringseems mostly unused, it's better to start from the beginning.- added a commit that references this issue
on May 8, 2023 - added a commit that references this issue
on May 28, 2023 I think we're done here -- the docs for both
collections.abc.ByteStringandtyping.ByteStringhave pretty clear "don't use this!" notices next to them now, and there's no claim of direct equivalency anymore.Feel free to reopen if there's something more to be done!
Reacted by ShantanuReacted by Sebastian Rittau
There are two related, but different strands of conversation here:
collections.abc.ByteStringis useless and confusing: Deprecate and schedule removal of collections.abc.ByteString and typing.ByteString #91896bytescan be used as a shorthand fortyping.ByteStringand includesmemoryviewandbytearrayhttps://peps.python.org/pep-0688/However, there is an additional issue!
collections.abc.ByteStringis not an accurate replacement fortyping.ByteString!collections.abc.ByteStringonly registersbytesandbytearray, whereastyping.ByteStringis documented as also representing a memoryview. This is an issue regardless of the above two related conversations.For this issue we could:
typing.ByteStringout from under the "Corresponding to collections in collections.abc" section to the "Other concrete types" sectioncollections.abc.ByteStringfrom typing.rsttyping.ByteStringas being deprecated, but change the reason. ByteString is not a generic type andcollections.abc.ByteStringis not a semantic replacement for it as above, so the current reason is wrong on two countstyping.ByteStringin typeshed as a simple Union, and not the Sequence[int] thing it is right now.typing.ByteStringas a Union in typing.py instead of the generic alias it is now(?)Here's how this relates to the other two strands of conversation:
typing.ByteStringandcollections.abc.ByteString. I'm fine with going slow on the removal oftyping.ByteString, since once it's a union in typeshed it's not causing much harm. But ideally we can removecollections.abc.ByteStringin 3.14, since its isinstance behaviour is not what you want.cc @JelleZijlstra