Mercurial > hg
changeset 49810:a9faacdc5943
typing: add type hints to mercurial/win32.py
These are the low level functions that are imported by the mercurial.windows
module, which is in turn imported by mercurial.utils as the platform module.
Pretty straightforward, but pytype inferred very little of it, likely because of
the heavy ctypes usage. It also seems to trigger a pytype bug in procutil, now
that it has an idea of the underlying function type, so disable that warning to
maintain a working test.
author | Matt Harbison <matt_harbison@yahoo.com> |
---|---|
date | Thu, 15 Dec 2022 18:02:55 -0500 |
parents | 7a80a614c9e5 |
children | 0a91aba258e0 |
files | mercurial/posix.py mercurial/utils/procutil.py mercurial/win32.py |
diffstat | 3 files changed, 37 insertions(+), 24 deletions(-) [+] |
line wrap: on
line diff
--- a/mercurial/posix.py Thu Dec 15 15:46:25 2022 -0500 +++ b/mercurial/posix.py Thu Dec 15 18:02:55 2022 -0500 @@ -625,7 +625,7 @@ return pycompat.rapply(pycompat.fsencode, list(grp.getgrnam(name).gr_mem)) -def spawndetached(args): +def spawndetached(args) -> int: return os.spawnvp(os.P_NOWAIT | getattr(os, 'P_DETACH', 0), args[0], args)
--- a/mercurial/utils/procutil.py Thu Dec 15 15:46:25 2022 -0500 +++ b/mercurial/utils/procutil.py Thu Dec 15 18:02:55 2022 -0500 @@ -585,7 +585,7 @@ return _gethgcmd() -def rundetached(args, condfn): +def rundetached(args, condfn) -> int: """Execute the argument list in a detached process. condfn is a callable which is called repeatedly and should return @@ -621,6 +621,12 @@ if prevhandler is not None: signal.signal(signal.SIGCHLD, prevhandler) + # pytype seems to get confused by not having a return in the finally + # block, and thinks the return value should be Optional[int] here. It + # appears to be https://github.com/google/pytype/issues/938, without + # the `with` clause. + pass # pytype: disable=bad-return-type + @contextlib.contextmanager def uninterruptible(warn):
--- a/mercurial/win32.py Thu Dec 15 15:46:25 2022 -0500 +++ b/mercurial/win32.py Thu Dec 15 18:02:55 2022 -0500 @@ -14,6 +14,13 @@ import random import subprocess +from typing import ( + List, + NoReturn, + Optional, + Tuple, +) + from . import ( encoding, pycompat, @@ -356,7 +363,7 @@ _kernel32.PeekNamedPipe.restype = _BOOL -def _raiseoserror(name): +def _raiseoserror(name: bytes) -> NoReturn: # Force the code to a signed int to avoid an 'int too large' error. # See https://bugs.python.org/issue28474 code = _kernel32.GetLastError() @@ -368,7 +375,7 @@ ) -def _getfileinfo(name): +def _getfileinfo(name: bytes) -> _BY_HANDLE_FILE_INFORMATION: fh = _kernel32.CreateFileA( name, 0, @@ -389,7 +396,7 @@ _kernel32.CloseHandle(fh) -def checkcertificatechain(cert, build=True): +def checkcertificatechain(cert: bytes, build: bool = True) -> bool: """Tests the given certificate to see if there is a complete chain to a trusted root certificate. As a side effect, missing certificates are downloaded and installed unless ``build=False``. True is returned if a @@ -439,7 +446,7 @@ _crypt32.CertFreeCertificateContext(certctx) -def oslink(src, dst): +def oslink(src: bytes, dst: bytes) -> None: try: if not _kernel32.CreateHardLinkA(dst, src, None): _raiseoserror(src) @@ -447,12 +454,12 @@ _raiseoserror(src) -def nlinks(name): +def nlinks(name: bytes) -> int: '''return number of hardlinks for the given file''' return _getfileinfo(name).nNumberOfLinks -def samefile(path1, path2): +def samefile(path1: bytes, path2: bytes) -> bool: '''Returns whether path1 and path2 refer to the same file or directory.''' res1 = _getfileinfo(path1) res2 = _getfileinfo(path2) @@ -463,14 +470,14 @@ ) -def samedevice(path1, path2): +def samedevice(path1: bytes, path2: bytes) -> bool: '''Returns whether path1 and path2 are on the same device.''' res1 = _getfileinfo(path1) res2 = _getfileinfo(path2) return res1.dwVolumeSerialNumber == res2.dwVolumeSerialNumber -def peekpipe(pipe): +def peekpipe(pipe) -> int: handle = msvcrt.get_osfhandle(pipe.fileno()) # pytype: disable=module-attr avail = _DWORD() @@ -485,14 +492,14 @@ return avail.value -def lasterrorwaspipeerror(err): +def lasterrorwaspipeerror(err) -> bool: if err.errno != errno.EINVAL: return False err = _kernel32.GetLastError() return err == _ERROR_BROKEN_PIPE or err == _ERROR_NO_DATA -def testpid(pid): +def testpid(pid: int) -> bool: """return True if pid is still running or unable to determine, False otherwise""" h = _kernel32.OpenProcess(_PROCESS_QUERY_INFORMATION, False, pid) @@ -506,7 +513,7 @@ return _kernel32.GetLastError() != _ERROR_INVALID_PARAMETER -def executablepath(): +def executablepath() -> bytes: '''return full path of hg.exe''' size = 600 buf = ctypes.create_string_buffer(size + 1) @@ -520,7 +527,7 @@ return buf.value -def getvolumename(path): +def getvolumename(path: bytes) -> Optional[bytes]: """Get the mount point of the filesystem from a directory or file (best-effort) @@ -541,7 +548,7 @@ return buf.value -def getfstype(path): +def getfstype(path: bytes) -> Optional[bytes]: """Get the filesystem type name from a directory or file (best-effort) Returns None if we are unsure. Raises OSError on ENOENT, EPERM, etc. @@ -572,7 +579,7 @@ return name.value -def getuser(): +def getuser() -> bytes: '''return name of current user''' size = _DWORD(300) buf = ctypes.create_string_buffer(size.value + 1) @@ -581,10 +588,10 @@ return buf.value -_signalhandler = [] +_signalhandler: List[_SIGNAL_HANDLER] = [] -def setsignalhandler(): +def setsignalhandler() -> None: """Register a termination handler for console events including CTRL+C. python signal handlers do not work well with socket operations. @@ -601,7 +608,7 @@ raise ctypes.WinError() # pytype: disable=module-attr -def hidewindow(): +def hidewindow() -> None: def callback(hwnd, pid): wpid = _DWORD() _user32.GetWindowThreadProcessId(hwnd, ctypes.byref(wpid)) @@ -614,7 +621,7 @@ _user32.EnumWindows(_WNDENUMPROC(callback), pid) -def termsize(): +def termsize() -> Tuple[int, int]: # cmd.exe does not handle CR like a unix console, the CR is # counted in the line length. On 80 columns consoles, if 80 # characters are written, the following CR won't apply on the @@ -635,7 +642,7 @@ return width, height -def enablevtmode(): +def enablevtmode() -> bool: """Enable virtual terminal mode for the associated console. Return True if enabled, else False.""" @@ -661,7 +668,7 @@ return True -def spawndetached(args): +def spawndetached(args: List[bytes]) -> int: # No standard library function really spawns a fully detached # process under win32 because they allocate pipes or other objects # to handle standard streams communications. Passing these objects @@ -703,7 +710,7 @@ return pi.dwProcessId -def unlink(f): +def unlink(f: bytes) -> None: '''try to implement POSIX' unlink semantics on Windows''' if os.path.isdir(f): @@ -758,7 +765,7 @@ pass -def makedir(path, notindexed): +def makedir(path: bytes, notindexed: bool) -> None: os.mkdir(path) if notindexed: _kernel32.SetFileAttributesA(path, _FILE_ATTRIBUTE_NOT_CONTENT_INDEXED)