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.
--- 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):