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