# HG changeset patch # User Matt Harbison # Date 1721434188 14400 # Node ID 43adbe03079b9a3bd9beb36b995c1e8e3513b240 # Parent ed28085827ec37e7c233c0c0e44646f26e3db67e typing: add type hints to the `charencode` module Since this module is dynamically imported from either `mercurial.pure` or `mercurial.cext`, these hints aren't detected in `mercurial.encoding`, and need to be imported directly there during the type-checking phase. This keeps the runtime selection via the policy config in place, but allows pytype to see these as functions with proper signatures instead of just `Any`. We don't attempt to import the `mercurial.cext` version yet because there's no types stubs for that module, but this will get the ball rolling. I thought this would spill over into other modules from there, but the only two *.pyi files that changed were for `encoding` and `charencode`. Applying this to other dynamically selected modules will clean some things up in other files, so this is a start. I had originally redefined the functions in the type-checking block (like some of the `os.path` aliasing in `mercurial.util`), but this is better because we won't have another duplication of the definitions that may get out of date. diff -r ed28085827ec -r 43adbe03079b mercurial/encoding.py --- a/mercurial/encoding.py Fri Jul 19 16:49:46 2024 -0400 +++ b/mercurial/encoding.py Fri Jul 19 20:09:48 2024 -0400 @@ -40,6 +40,16 @@ unichr = chr +if typing.TYPE_CHECKING: + # TODO: make a stub file for .cext.charencode, and import here + from .pure.charencode import ( + asciilower, + asciiupper, + isasciistr, + jsonescapeu8fast as _jsonescapeu8fast, + ) + + # These unicode characters are ignored by HFS+ (Apple Technote 1150, # "Unicode Subtleties"), so we need to ignore them in some places for # sanity. @@ -524,7 +534,7 @@ other = 0 -def jsonescape(s: Any, paranoid: Any = False) -> Any: +def jsonescape(s: bytes, paranoid: bool = False) -> bytes: """returns a string suitable for JSON JSON is problematic for us because it doesn't support non-Unicode diff -r ed28085827ec -r 43adbe03079b mercurial/pure/charencode.py --- a/mercurial/pure/charencode.py Fri Jul 19 16:49:46 2024 -0400 +++ b/mercurial/pure/charencode.py Fri Jul 19 20:09:48 2024 -0400 @@ -11,7 +11,7 @@ from .. import pycompat -def isasciistr(s): +def isasciistr(s: bytes) -> bool: try: s.decode('ascii') return True @@ -19,7 +19,7 @@ return False -def asciilower(s): +def asciilower(s: bytes) -> bytes: """convert a string to lowercase if ASCII Raises UnicodeDecodeError if non-ASCII characters are found.""" @@ -27,7 +27,7 @@ return s.lower() -def asciiupper(s): +def asciiupper(s: bytes) -> bytes: """convert a string to uppercase if ASCII Raises UnicodeDecodeError if non-ASCII characters are found.""" @@ -52,7 +52,7 @@ _jsonmap.extend(pycompat.bytechr(x) for x in range(128, 256)) -def jsonescapeu8fast(u8chars, paranoid): +def jsonescapeu8fast(u8chars: bytes, paranoid: bool) -> bytes: """Convert a UTF-8 byte string to JSON-escaped form (fast path) Raises ValueError if non-ASCII characters have to be escaped. @@ -70,7 +70,7 @@ _utf8strict = r'surrogatepass' -def jsonescapeu8fallback(u8chars, paranoid): +def jsonescapeu8fallback(u8chars: bytes, paranoid: bool) -> bytes: """Convert a UTF-8 byte string to JSON-escaped form (slow path) Escapes all non-ASCII characters no matter if paranoid is False.