Show More
@@ -625,7 +625,7 b' def groupmembers(name):' | |||||
625 | return pycompat.rapply(pycompat.fsencode, list(grp.getgrnam(name).gr_mem)) |
|
625 | return pycompat.rapply(pycompat.fsencode, list(grp.getgrnam(name).gr_mem)) | |
626 |
|
626 | |||
627 |
|
627 | |||
628 | def spawndetached(args): |
|
628 | def spawndetached(args) -> int: | |
629 | return os.spawnvp(os.P_NOWAIT | getattr(os, 'P_DETACH', 0), args[0], args) |
|
629 | return os.spawnvp(os.P_NOWAIT | getattr(os, 'P_DETACH', 0), args[0], args) | |
630 |
|
630 | |||
631 |
|
631 |
@@ -585,7 +585,7 b' def hgcmd():' | |||||
585 | return _gethgcmd() |
|
585 | return _gethgcmd() | |
586 |
|
586 | |||
587 |
|
587 | |||
588 | def rundetached(args, condfn): |
|
588 | def rundetached(args, condfn) -> int: | |
589 | """Execute the argument list in a detached process. |
|
589 | """Execute the argument list in a detached process. | |
590 |
|
590 | |||
591 | condfn is a callable which is called repeatedly and should return |
|
591 | condfn is a callable which is called repeatedly and should return | |
@@ -621,6 +621,12 b' def rundetached(args, condfn):' | |||||
621 | if prevhandler is not None: |
|
621 | if prevhandler is not None: | |
622 | signal.signal(signal.SIGCHLD, prevhandler) |
|
622 | signal.signal(signal.SIGCHLD, prevhandler) | |
623 |
|
623 | |||
|
624 | # pytype seems to get confused by not having a return in the finally | |||
|
625 | # block, and thinks the return value should be Optional[int] here. It | |||
|
626 | # appears to be https://github.com/google/pytype/issues/938, without | |||
|
627 | # the `with` clause. | |||
|
628 | pass # pytype: disable=bad-return-type | |||
|
629 | ||||
624 |
|
630 | |||
625 | @contextlib.contextmanager |
|
631 | @contextlib.contextmanager | |
626 | def uninterruptible(warn): |
|
632 | def uninterruptible(warn): |
@@ -14,6 +14,13 b' import os' | |||||
14 | import random |
|
14 | import random | |
15 | import subprocess |
|
15 | import subprocess | |
16 |
|
16 | |||
|
17 | from typing import ( | |||
|
18 | List, | |||
|
19 | NoReturn, | |||
|
20 | Optional, | |||
|
21 | Tuple, | |||
|
22 | ) | |||
|
23 | ||||
17 | from . import ( |
|
24 | from . import ( | |
18 | encoding, |
|
25 | encoding, | |
19 | pycompat, |
|
26 | pycompat, | |
@@ -356,7 +363,7 b' except AttributeError:' | |||||
356 | _kernel32.PeekNamedPipe.restype = _BOOL |
|
363 | _kernel32.PeekNamedPipe.restype = _BOOL | |
357 |
|
364 | |||
358 |
|
365 | |||
359 | def _raiseoserror(name): |
|
366 | def _raiseoserror(name: bytes) -> NoReturn: | |
360 | # Force the code to a signed int to avoid an 'int too large' error. |
|
367 | # Force the code to a signed int to avoid an 'int too large' error. | |
361 | # See https://bugs.python.org/issue28474 |
|
368 | # See https://bugs.python.org/issue28474 | |
362 | code = _kernel32.GetLastError() |
|
369 | code = _kernel32.GetLastError() | |
@@ -368,7 +375,7 b' def _raiseoserror(name):' | |||||
368 | ) |
|
375 | ) | |
369 |
|
376 | |||
370 |
|
377 | |||
371 | def _getfileinfo(name): |
|
378 | def _getfileinfo(name: bytes) -> _BY_HANDLE_FILE_INFORMATION: | |
372 | fh = _kernel32.CreateFileA( |
|
379 | fh = _kernel32.CreateFileA( | |
373 | name, |
|
380 | name, | |
374 | 0, |
|
381 | 0, | |
@@ -389,7 +396,7 b' def _getfileinfo(name):' | |||||
389 | _kernel32.CloseHandle(fh) |
|
396 | _kernel32.CloseHandle(fh) | |
390 |
|
397 | |||
391 |
|
398 | |||
392 | def checkcertificatechain(cert, build=True): |
|
399 | def checkcertificatechain(cert: bytes, build: bool = True) -> bool: | |
393 | """Tests the given certificate to see if there is a complete chain to a |
|
400 | """Tests the given certificate to see if there is a complete chain to a | |
394 | trusted root certificate. As a side effect, missing certificates are |
|
401 | trusted root certificate. As a side effect, missing certificates are | |
395 | downloaded and installed unless ``build=False``. True is returned if a |
|
402 | downloaded and installed unless ``build=False``. True is returned if a | |
@@ -439,7 +446,7 b' def checkcertificatechain(cert, build=Tr' | |||||
439 | _crypt32.CertFreeCertificateContext(certctx) |
|
446 | _crypt32.CertFreeCertificateContext(certctx) | |
440 |
|
447 | |||
441 |
|
448 | |||
442 | def oslink(src, dst): |
|
449 | def oslink(src: bytes, dst: bytes) -> None: | |
443 | try: |
|
450 | try: | |
444 | if not _kernel32.CreateHardLinkA(dst, src, None): |
|
451 | if not _kernel32.CreateHardLinkA(dst, src, None): | |
445 | _raiseoserror(src) |
|
452 | _raiseoserror(src) | |
@@ -447,12 +454,12 b' def oslink(src, dst):' | |||||
447 | _raiseoserror(src) |
|
454 | _raiseoserror(src) | |
448 |
|
455 | |||
449 |
|
456 | |||
450 | def nlinks(name): |
|
457 | def nlinks(name: bytes) -> int: | |
451 | '''return number of hardlinks for the given file''' |
|
458 | '''return number of hardlinks for the given file''' | |
452 | return _getfileinfo(name).nNumberOfLinks |
|
459 | return _getfileinfo(name).nNumberOfLinks | |
453 |
|
460 | |||
454 |
|
461 | |||
455 | def samefile(path1, path2): |
|
462 | def samefile(path1: bytes, path2: bytes) -> bool: | |
456 | '''Returns whether path1 and path2 refer to the same file or directory.''' |
|
463 | '''Returns whether path1 and path2 refer to the same file or directory.''' | |
457 | res1 = _getfileinfo(path1) |
|
464 | res1 = _getfileinfo(path1) | |
458 | res2 = _getfileinfo(path2) |
|
465 | res2 = _getfileinfo(path2) | |
@@ -463,14 +470,14 b' def samefile(path1, path2):' | |||||
463 | ) |
|
470 | ) | |
464 |
|
471 | |||
465 |
|
472 | |||
466 | def samedevice(path1, path2): |
|
473 | def samedevice(path1: bytes, path2: bytes) -> bool: | |
467 | '''Returns whether path1 and path2 are on the same device.''' |
|
474 | '''Returns whether path1 and path2 are on the same device.''' | |
468 | res1 = _getfileinfo(path1) |
|
475 | res1 = _getfileinfo(path1) | |
469 | res2 = _getfileinfo(path2) |
|
476 | res2 = _getfileinfo(path2) | |
470 | return res1.dwVolumeSerialNumber == res2.dwVolumeSerialNumber |
|
477 | return res1.dwVolumeSerialNumber == res2.dwVolumeSerialNumber | |
471 |
|
478 | |||
472 |
|
479 | |||
473 | def peekpipe(pipe): |
|
480 | def peekpipe(pipe) -> int: | |
474 | handle = msvcrt.get_osfhandle(pipe.fileno()) # pytype: disable=module-attr |
|
481 | handle = msvcrt.get_osfhandle(pipe.fileno()) # pytype: disable=module-attr | |
475 | avail = _DWORD() |
|
482 | avail = _DWORD() | |
476 |
|
483 | |||
@@ -485,14 +492,14 b' def peekpipe(pipe):' | |||||
485 | return avail.value |
|
492 | return avail.value | |
486 |
|
493 | |||
487 |
|
494 | |||
488 | def lasterrorwaspipeerror(err): |
|
495 | def lasterrorwaspipeerror(err) -> bool: | |
489 | if err.errno != errno.EINVAL: |
|
496 | if err.errno != errno.EINVAL: | |
490 | return False |
|
497 | return False | |
491 | err = _kernel32.GetLastError() |
|
498 | err = _kernel32.GetLastError() | |
492 | return err == _ERROR_BROKEN_PIPE or err == _ERROR_NO_DATA |
|
499 | return err == _ERROR_BROKEN_PIPE or err == _ERROR_NO_DATA | |
493 |
|
500 | |||
494 |
|
501 | |||
495 | def testpid(pid): |
|
502 | def testpid(pid: int) -> bool: | |
496 | """return True if pid is still running or unable to |
|
503 | """return True if pid is still running or unable to | |
497 | determine, False otherwise""" |
|
504 | determine, False otherwise""" | |
498 | h = _kernel32.OpenProcess(_PROCESS_QUERY_INFORMATION, False, pid) |
|
505 | h = _kernel32.OpenProcess(_PROCESS_QUERY_INFORMATION, False, pid) | |
@@ -506,7 +513,7 b' def testpid(pid):' | |||||
506 | return _kernel32.GetLastError() != _ERROR_INVALID_PARAMETER |
|
513 | return _kernel32.GetLastError() != _ERROR_INVALID_PARAMETER | |
507 |
|
514 | |||
508 |
|
515 | |||
509 | def executablepath(): |
|
516 | def executablepath() -> bytes: | |
510 | '''return full path of hg.exe''' |
|
517 | '''return full path of hg.exe''' | |
511 | size = 600 |
|
518 | size = 600 | |
512 | buf = ctypes.create_string_buffer(size + 1) |
|
519 | buf = ctypes.create_string_buffer(size + 1) | |
@@ -520,7 +527,7 b' def executablepath():' | |||||
520 | return buf.value |
|
527 | return buf.value | |
521 |
|
528 | |||
522 |
|
529 | |||
523 | def getvolumename(path): |
|
530 | def getvolumename(path: bytes) -> Optional[bytes]: | |
524 | """Get the mount point of the filesystem from a directory or file |
|
531 | """Get the mount point of the filesystem from a directory or file | |
525 | (best-effort) |
|
532 | (best-effort) | |
526 |
|
533 | |||
@@ -541,7 +548,7 b' def getvolumename(path):' | |||||
541 | return buf.value |
|
548 | return buf.value | |
542 |
|
549 | |||
543 |
|
550 | |||
544 | def getfstype(path): |
|
551 | def getfstype(path: bytes) -> Optional[bytes]: | |
545 | """Get the filesystem type name from a directory or file (best-effort) |
|
552 | """Get the filesystem type name from a directory or file (best-effort) | |
546 |
|
553 | |||
547 | Returns None if we are unsure. Raises OSError on ENOENT, EPERM, etc. |
|
554 | Returns None if we are unsure. Raises OSError on ENOENT, EPERM, etc. | |
@@ -572,7 +579,7 b' def getfstype(path):' | |||||
572 | return name.value |
|
579 | return name.value | |
573 |
|
580 | |||
574 |
|
581 | |||
575 | def getuser(): |
|
582 | def getuser() -> bytes: | |
576 | '''return name of current user''' |
|
583 | '''return name of current user''' | |
577 | size = _DWORD(300) |
|
584 | size = _DWORD(300) | |
578 | buf = ctypes.create_string_buffer(size.value + 1) |
|
585 | buf = ctypes.create_string_buffer(size.value + 1) | |
@@ -581,10 +588,10 b' def getuser():' | |||||
581 | return buf.value |
|
588 | return buf.value | |
582 |
|
589 | |||
583 |
|
590 | |||
584 | _signalhandler = [] |
|
591 | _signalhandler: List[_SIGNAL_HANDLER] = [] | |
585 |
|
592 | |||
586 |
|
593 | |||
587 | def setsignalhandler(): |
|
594 | def setsignalhandler() -> None: | |
588 | """Register a termination handler for console events including |
|
595 | """Register a termination handler for console events including | |
589 | CTRL+C. python signal handlers do not work well with socket |
|
596 | CTRL+C. python signal handlers do not work well with socket | |
590 | operations. |
|
597 | operations. | |
@@ -601,7 +608,7 b' def setsignalhandler():' | |||||
601 | raise ctypes.WinError() # pytype: disable=module-attr |
|
608 | raise ctypes.WinError() # pytype: disable=module-attr | |
602 |
|
609 | |||
603 |
|
610 | |||
604 | def hidewindow(): |
|
611 | def hidewindow() -> None: | |
605 | def callback(hwnd, pid): |
|
612 | def callback(hwnd, pid): | |
606 | wpid = _DWORD() |
|
613 | wpid = _DWORD() | |
607 | _user32.GetWindowThreadProcessId(hwnd, ctypes.byref(wpid)) |
|
614 | _user32.GetWindowThreadProcessId(hwnd, ctypes.byref(wpid)) | |
@@ -614,7 +621,7 b' def hidewindow():' | |||||
614 | _user32.EnumWindows(_WNDENUMPROC(callback), pid) |
|
621 | _user32.EnumWindows(_WNDENUMPROC(callback), pid) | |
615 |
|
622 | |||
616 |
|
623 | |||
617 | def termsize(): |
|
624 | def termsize() -> Tuple[int, int]: | |
618 | # cmd.exe does not handle CR like a unix console, the CR is |
|
625 | # cmd.exe does not handle CR like a unix console, the CR is | |
619 | # counted in the line length. On 80 columns consoles, if 80 |
|
626 | # counted in the line length. On 80 columns consoles, if 80 | |
620 | # characters are written, the following CR won't apply on the |
|
627 | # characters are written, the following CR won't apply on the | |
@@ -635,7 +642,7 b' def termsize():' | |||||
635 | return width, height |
|
642 | return width, height | |
636 |
|
643 | |||
637 |
|
644 | |||
638 | def enablevtmode(): |
|
645 | def enablevtmode() -> bool: | |
639 | """Enable virtual terminal mode for the associated console. Return True if |
|
646 | """Enable virtual terminal mode for the associated console. Return True if | |
640 | enabled, else False.""" |
|
647 | enabled, else False.""" | |
641 |
|
648 | |||
@@ -661,7 +668,7 b' def enablevtmode():' | |||||
661 | return True |
|
668 | return True | |
662 |
|
669 | |||
663 |
|
670 | |||
664 | def spawndetached(args): |
|
671 | def spawndetached(args: List[bytes]) -> int: | |
665 | # No standard library function really spawns a fully detached |
|
672 | # No standard library function really spawns a fully detached | |
666 | # process under win32 because they allocate pipes or other objects |
|
673 | # process under win32 because they allocate pipes or other objects | |
667 | # to handle standard streams communications. Passing these objects |
|
674 | # to handle standard streams communications. Passing these objects | |
@@ -703,7 +710,7 b' def spawndetached(args):' | |||||
703 | return pi.dwProcessId |
|
710 | return pi.dwProcessId | |
704 |
|
711 | |||
705 |
|
712 | |||
706 | def unlink(f): |
|
713 | def unlink(f: bytes) -> None: | |
707 | '''try to implement POSIX' unlink semantics on Windows''' |
|
714 | '''try to implement POSIX' unlink semantics on Windows''' | |
708 |
|
715 | |||
709 | if os.path.isdir(f): |
|
716 | if os.path.isdir(f): | |
@@ -758,7 +765,7 b' def unlink(f):' | |||||
758 | pass |
|
765 | pass | |
759 |
|
766 | |||
760 |
|
767 | |||
761 | def makedir(path, notindexed): |
|
768 | def makedir(path: bytes, notindexed: bool) -> None: | |
762 | os.mkdir(path) |
|
769 | os.mkdir(path) | |
763 | if notindexed: |
|
770 | if notindexed: | |
764 | _kernel32.SetFileAttributesA(path, _FILE_ATTRIBUTE_NOT_CONTENT_INDEXED) |
|
771 | _kernel32.SetFileAttributesA(path, _FILE_ATTRIBUTE_NOT_CONTENT_INDEXED) |
General Comments 0
You need to be logged in to leave comments.
Login now