Mercurial > public > mercurial-scm > hg-stable
comparison mercurial/pycompat.py @ 49898:55d45d0de4e7
typing: add type hints to pycompat.bytestr
The problem with leaving pytype to its own devices here was that for functions
that returned a bytestr, pytype inferred `Union[bytes, int]`. It now accepts
that it can be treated as plain bytes.
I wasn't able to figure out the arg type for `__getitem__`- `SupportsIndex`
(which PyCharm indicated is how the superclass function is typed) got flagged:
File "/mnt/c/Users/Matt/hg/mercurial/pycompat.py", line 236, in __getitem__:
unsupported operand type(s) for item retrieval: bytestr and SupportsIndex [unsupported-operands]
Function __getitem__ on bytestr expects int
But some caller got flagged when I marked it as `int`.
There's some minor spillover problems elsewhere- pytype doesn't seem to
recognize that `bytes.startswith()` can optionally take a 3rd and 4th arg, so
those few places have the warning disabled. It also flags where the tar API is
being abused, but that would be a tricky refactor (and would require typing
extensions until py3.7 is dropped), so disable those too.
author | Matt Harbison <matt_harbison@yahoo.com> |
---|---|
date | Wed, 14 Dec 2022 01:51:33 -0500 |
parents | f3f33980f19b |
children | c5a06cc37401 |
comparison
equal
deleted
inserted
replaced
49897:f3f33980f19b | 49898:55d45d0de4e7 |
---|---|
27 import sys | 27 import sys |
28 import tempfile | 28 import tempfile |
29 import xmlrpc.client as xmlrpclib | 29 import xmlrpc.client as xmlrpclib |
30 | 30 |
31 from typing import ( | 31 from typing import ( |
32 Iterable, | |
33 Iterator, | |
32 List, | 34 List, |
33 Optional, | 35 Optional, |
36 Type, | |
37 TypeVar, | |
34 ) | 38 ) |
35 | 39 |
36 ispy3 = sys.version_info[0] >= 3 | 40 ispy3 = sys.version_info[0] >= 3 |
37 ispypy = '__pypy__' in sys.builtin_module_names | 41 ispypy = '__pypy__' in sys.builtin_module_names |
38 TYPE_CHECKING = False | 42 TYPE_CHECKING = False |
39 | 43 |
40 if not globals(): # hide this from non-pytype users | 44 if not globals(): # hide this from non-pytype users |
41 import typing | 45 import typing |
42 | 46 |
43 TYPE_CHECKING = typing.TYPE_CHECKING | 47 TYPE_CHECKING = typing.TYPE_CHECKING |
48 | |
49 _Tbytestr = TypeVar('_Tbytestr', bound='bytestr') | |
44 | 50 |
45 | 51 |
46 def future_set_exception_info(f, exc_info): | 52 def future_set_exception_info(f, exc_info): |
47 f.set_exception(exc_info[0]) | 53 f.set_exception(exc_info[0]) |
48 | 54 |
210 # since the appropriate bytes format is done internally. | 216 # since the appropriate bytes format is done internally. |
211 # | 217 # |
212 # https://github.com/google/pytype/issues/500 | 218 # https://github.com/google/pytype/issues/500 |
213 if TYPE_CHECKING: | 219 if TYPE_CHECKING: |
214 | 220 |
215 def __init__(self, s=b''): | 221 def __init__(self, s: object = b'') -> None: |
216 pass | 222 pass |
217 | 223 |
218 def __new__(cls, s=b''): | 224 def __new__(cls: Type[_Tbytestr], s: object = b'') -> _Tbytestr: |
219 if isinstance(s, bytestr): | 225 if isinstance(s, bytestr): |
220 return s | 226 return s |
221 if not isinstance( | 227 if not isinstance( |
222 s, (bytes, bytearray) | 228 s, (bytes, bytearray) |
223 ) and not builtins.hasattr( # hasattr-py3-only | 229 ) and not builtins.hasattr( # hasattr-py3-only |
224 s, u'__bytes__' | 230 s, u'__bytes__' |
225 ): | 231 ): |
226 s = str(s).encode('ascii') | 232 s = str(s).encode('ascii') |
227 return bytes.__new__(cls, s) | 233 return bytes.__new__(cls, s) |
228 | 234 |
229 def __getitem__(self, key): | 235 def __getitem__(self, key) -> bytes: |
230 s = bytes.__getitem__(self, key) | 236 s = bytes.__getitem__(self, key) |
231 if not isinstance(s, bytes): | 237 if not isinstance(s, bytes): |
232 s = bytechr(s) | 238 s = bytechr(s) |
233 return s | 239 return s |
234 | 240 |
235 def __iter__(self): | 241 def __iter__(self) -> Iterator[bytes]: |
236 return iterbytestr(bytes.__iter__(self)) | 242 return iterbytestr(bytes.__iter__(self)) |
237 | 243 |
238 def __repr__(self): | 244 def __repr__(self) -> str: |
239 return bytes.__repr__(self)[1:] # drop b'' | 245 return bytes.__repr__(self)[1:] # drop b'' |
240 | 246 |
241 | 247 |
242 def iterbytestr(s): | 248 def iterbytestr(s: Iterable[int]) -> Iterator[bytes]: |
243 """Iterate bytes as if it were a str object of Python 2""" | 249 """Iterate bytes as if it were a str object of Python 2""" |
244 return map(bytechr, s) | 250 return map(bytechr, s) |
245 | 251 |
246 | 252 |
247 def maybebytestr(s): | 253 def maybebytestr(s): |