pycompat: fix bytestr(bytes) in Python 3.11
In Python 3.10, the `bytes` type itself does not have a `__bytes__`
attribute, but it does in 3.11. Yet `bytes(bytes)` does not give
the wished output, so we have to add an exceptional case.
The added case in the doctest reproduces the problem with Python 3.11.
Impact: error treatment in expressions such as `repo[b'invalid']` gets
broken.
--- a/mercurial/pycompat.py Thu Jan 04 14:45:31 2024 -0500
+++ b/mercurial/pycompat.py Wed Jan 03 18:33:39 2024 +0100
@@ -203,6 +203,13 @@
>>> bytestr(bytesable())
'bytes'
+ ...unless the argument is the bytes *type* itself: it gets a
+ __bytes__() method in Python 3.11, which cannot be used as in an instance
+ of bytes:
+
+ >>> bytestr(bytes)
+ "<class 'bytes'>"
+
There's no implicit conversion from non-ascii str as its encoding is
unknown:
@@ -252,10 +259,9 @@
def __new__(cls: Type[_Tbytestr], s: object = b'') -> _Tbytestr:
if isinstance(s, bytestr):
return s
- if not isinstance(
- s, (bytes, bytearray)
- ) and not builtins.hasattr( # hasattr-py3-only
- s, u'__bytes__'
+ if not isinstance(s, (bytes, bytearray)) and (
+ isinstance(s, type)
+ or not builtins.hasattr(s, u'__bytes__') # hasattr-py3-only
):
s = str(s).encode('ascii')
return bytes.__new__(cls, s)