Mercurial > hg
changeset 51721:ed28085827ec
typing: explicitly type some `mercurial.util` eol code to avoid @overload
Unlike the previous commit, this makes a material difference in the generated
stub file- the `pycompat.identity()` aliases generated an @overload like this:
@overload
def fromnativeeol(a: _T0) -> _T0: ...
... which might fail to detect a bad argument, like str. This drops the
@overload for the 3 related methods, so there's a single definition for each.
The `typelib.BinaryIO_Proxy` is used for subclassing (the same as was done in
8147abc05794), so that it is a `BinaryIO` type during type checking, but still
inherits `object` at runtime. That way, we don't need to implement unused
abstract methods.
author | Matt Harbison <matt_harbison@yahoo.com> |
---|---|
date | Fri, 19 Jul 2024 16:49:46 -0400 |
parents | e618a1756b08 |
children | 43adbe03079b |
files | mercurial/util.py |
diffstat | 1 files changed, 25 insertions(+), 6 deletions(-) [+] |
line wrap: on
line diff
--- a/mercurial/util.py Fri Jul 19 16:38:53 2024 -0400 +++ b/mercurial/util.py Fri Jul 19 16:49:46 2024 -0400 @@ -32,10 +32,13 @@ import sys import time import traceback +import typing import warnings from typing import ( Any, + BinaryIO, + Callable, Iterable, Iterator, List, @@ -55,6 +58,7 @@ i18n, policy, pycompat, + typelib, urllibcompat, ) from .utils import ( @@ -2907,20 +2911,20 @@ ) -class transformingwriter: +class transformingwriter(typelib.BinaryIO_Proxy): """Writable file wrapper to transform data by function""" - def __init__(self, fp, encode): + def __init__(self, fp: BinaryIO, encode: Callable[[bytes], bytes]) -> None: self._fp = fp self._encode = encode - def close(self): + def close(self) -> None: self._fp.close() - def flush(self): + def flush(self) -> None: self._fp.flush() - def write(self, data): + def write(self, data: bytes) -> int: return self._fp.write(self._encode(data)) @@ -2938,7 +2942,7 @@ return _eolre.sub(b'\r\n', s) -def _crlfwriter(fp): +def _crlfwriter(fp: typelib.BinaryIO_Proxy) -> typelib.BinaryIO_Proxy: return transformingwriter(fp, tocrlf) @@ -2951,6 +2955,21 @@ fromnativeeol = pycompat.identity nativeeolwriter = pycompat.identity +if typing.TYPE_CHECKING: + # Replace the various overloads that come along with aliasing other methods + # with the narrow definition that we care about in the type checking phase + # only. This ensures that both Windows and POSIX see only the definition + # that is actually available. + + def tonativeeol(s: bytes) -> bytes: + raise NotImplementedError + + def fromnativeeol(s: bytes) -> bytes: + raise NotImplementedError + + def nativeeolwriter(fp: typelib.BinaryIO_Proxy) -> typelib.BinaryIO_Proxy: + raise NotImplementedError + # TODO delete since workaround variant for Python 2 no longer needed. def iterfile(fp):