# HG changeset patch # User Matt Harbison # Date 1721422186 14400 # Node ID ed28085827ec37e7c233c0c0e44646f26e3db67e # Parent e618a1756b08d5d2642c26e194be7d72ee301f75 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. diff -r e618a1756b08 -r ed28085827ec mercurial/util.py --- 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):