typing: add type hints to global variables in mercurial/pycompat.py
authorMatt Harbison <matt_harbison@yahoo.com>
Wed, 14 Dec 2022 01:32:03 -0500
changeset 49801 9cd327509cd4
parent 49800 c43b283a19c3
child 49802 f3f33980f19b
typing: add type hints to global variables in mercurial/pycompat.py The way `osaltsep` and `sysexecutable` were defined, pytype determined them to be `Union[bytes, str]`. This was a problem because that cascaded to all of the callers, and also because it couldn't be annotated as bytes on the initial assignment. Therefore, we use a ternary operator. The documentation says that `sys.executable` can either be None or an empty string if the value couldn't be determined. We opt for an empty string here because there are places that blindly pass it to `os.path.xxx()` functions, which crash if given None. Other places test `if pycompat.sysexecutable`, so empty string works for both.
mercurial/pycompat.py
--- a/mercurial/pycompat.py	Tue Dec 13 16:48:47 2022 -0500
+++ b/mercurial/pycompat.py	Wed Dec 14 01:32:03 2022 -0500
@@ -28,6 +28,10 @@
 import tempfile
 import xmlrpc.client as xmlrpclib
 
+from typing import (
+    List,
+    Optional,
+)
 
 ispy3 = sys.version_info[0] >= 3
 ispypy = '__pypy__' in sys.builtin_module_names
@@ -94,21 +98,17 @@
 
 fsencode = os.fsencode
 fsdecode = os.fsdecode
-oscurdir = os.curdir.encode('ascii')
-oslinesep = os.linesep.encode('ascii')
-osname = os.name.encode('ascii')
-ospathsep = os.pathsep.encode('ascii')
-ospardir = os.pardir.encode('ascii')
-ossep = os.sep.encode('ascii')
-osaltsep = os.altsep
-if osaltsep:
-    osaltsep = osaltsep.encode('ascii')
-osdevnull = os.devnull.encode('ascii')
+oscurdir: bytes = os.curdir.encode('ascii')
+oslinesep: bytes = os.linesep.encode('ascii')
+osname: bytes = os.name.encode('ascii')
+ospathsep: bytes = os.pathsep.encode('ascii')
+ospardir: bytes = os.pardir.encode('ascii')
+ossep: bytes = os.sep.encode('ascii')
+osaltsep: Optional[bytes] = os.altsep.encode('ascii') if os.altsep else None
+osdevnull: bytes = os.devnull.encode('ascii')
 
-sysplatform = sys.platform.encode('ascii')
-sysexecutable = sys.executable
-if sysexecutable:
-    sysexecutable = os.fsencode(sysexecutable)
+sysplatform: bytes = sys.platform.encode('ascii')
+sysexecutable: bytes = os.fsencode(sys.executable) if sys.executable else b''
 
 
 def maplist(*args):
@@ -143,6 +143,7 @@
     # (this is how Python 2 worked). To get that, we encode with the mbcs
     # encoding, which will pass CP_ACP to the underlying Windows API to
     # produce bytes.
+    sysargv: List[bytes] = []
     if os.name == r'nt':
         sysargv = [a.encode("mbcs", "ignore") for a in sys.argv]
     else:
@@ -377,12 +378,12 @@
 
 json_loads = json.loads
 
-isjython = sysplatform.startswith(b'java')
+isjython: bool = sysplatform.startswith(b'java')
 
-isdarwin = sysplatform.startswith(b'darwin')
-islinux = sysplatform.startswith(b'linux')
-isposix = osname == b'posix'
-iswindows = osname == b'nt'
+isdarwin: bool = sysplatform.startswith(b'darwin')
+islinux: bool = sysplatform.startswith(b'linux')
+isposix: bool = osname == b'posix'
+iswindows: bool = osname == b'nt'
 
 
 def getoptb(args, shortlist, namelist):