Mercurial > hg
comparison mercurial/pycompat.py @ 51310:f0e7d51bb454 stable
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.
author | Georges Racinet <georges.racinet@octobus.net> |
---|---|
date | Wed, 03 Jan 2024 18:33:39 +0100 |
parents | 9bffc6c4e4c5 |
children | 7e6aae033d8d |
comparison
equal
deleted
inserted
replaced
51309:9b44b25dece1 | 51310:f0e7d51bb454 |
---|---|
201 ... def __bytes__(self): | 201 ... def __bytes__(self): |
202 ... return b'bytes' | 202 ... return b'bytes' |
203 >>> bytestr(bytesable()) | 203 >>> bytestr(bytesable()) |
204 'bytes' | 204 'bytes' |
205 | 205 |
206 ...unless the argument is the bytes *type* itself: it gets a | |
207 __bytes__() method in Python 3.11, which cannot be used as in an instance | |
208 of bytes: | |
209 | |
210 >>> bytestr(bytes) | |
211 "<class 'bytes'>" | |
212 | |
206 There's no implicit conversion from non-ascii str as its encoding is | 213 There's no implicit conversion from non-ascii str as its encoding is |
207 unknown: | 214 unknown: |
208 | 215 |
209 >>> bytestr(chr(0x80)) # doctest: +ELLIPSIS | 216 >>> bytestr(chr(0x80)) # doctest: +ELLIPSIS |
210 Traceback (most recent call last): | 217 Traceback (most recent call last): |
250 pass | 257 pass |
251 | 258 |
252 def __new__(cls: Type[_Tbytestr], s: object = b'') -> _Tbytestr: | 259 def __new__(cls: Type[_Tbytestr], s: object = b'') -> _Tbytestr: |
253 if isinstance(s, bytestr): | 260 if isinstance(s, bytestr): |
254 return s | 261 return s |
255 if not isinstance( | 262 if not isinstance(s, (bytes, bytearray)) and ( |
256 s, (bytes, bytearray) | 263 isinstance(s, type) |
257 ) and not builtins.hasattr( # hasattr-py3-only | 264 or not builtins.hasattr(s, u'__bytes__') # hasattr-py3-only |
258 s, u'__bytes__' | |
259 ): | 265 ): |
260 s = str(s).encode('ascii') | 266 s = str(s).encode('ascii') |
261 return bytes.__new__(cls, s) | 267 return bytes.__new__(cls, s) |
262 | 268 |
263 # The base class uses `int` return in py3, but the point of this class is to | 269 # The base class uses `int` return in py3, but the point of this class is to |