comparison mercurial/util.py @ 51924:1d95a87813ad

typing: add type annotations to the `mercurial.util.filestat` class It's referenced in the `vfs` classes, so get this out of the way to help there. The `TypeVar` definition and its usage was copied from the existing `util.pyi` file.
author Matt Harbison <matt_harbison@yahoo.com>
date Fri, 20 Sep 2024 00:04:09 -0400
parents 8f3cbea2547c
children f833ad92ee44
comparison
equal deleted inserted replaced
51923:e59e1d8d29d2 51924:1d95a87813ad
43 Iterable, 43 Iterable,
44 Iterator, 44 Iterator,
45 List, 45 List,
46 Optional, 46 Optional,
47 Tuple, 47 Tuple,
48 Type,
49 TypeVar,
48 ) 50 )
49 51
50 from .node import hex 52 from .node import hex
51 from .thirdparty import attr 53 from .thirdparty import attr
52 54
155 statisexec = platform.statisexec 157 statisexec = platform.statisexec
156 statislink = platform.statislink 158 statislink = platform.statislink
157 umask = platform.umask 159 umask = platform.umask
158 unlink = platform.unlink 160 unlink = platform.unlink
159 username = platform.username 161 username = platform.username
162
163
164 if typing.TYPE_CHECKING:
165 _Tfilestat = TypeVar('_Tfilestat', bound='filestat')
160 166
161 167
162 def setumask(val: int) -> None: 168 def setumask(val: int) -> None:
163 '''updates the umask. used by chg server''' 169 '''updates the umask. used by chg server'''
164 if pycompat.iswindows: 170 if pycompat.iswindows:
2489 'stat' attribute is result of 'os.stat()' if specified 'path' 2495 'stat' attribute is result of 'os.stat()' if specified 'path'
2490 exists. Otherwise, it is None. This can avoid preparative 2496 exists. Otherwise, it is None. This can avoid preparative
2491 'exists()' examination on client side of this class. 2497 'exists()' examination on client side of this class.
2492 """ 2498 """
2493 2499
2494 def __init__(self, stat): 2500 def __init__(self, stat: Optional[os.stat_result]) -> None:
2495 self.stat = stat 2501 self.stat = stat
2496 2502
2497 @classmethod 2503 @classmethod
2498 def frompath(cls, path): 2504 def frompath(cls: Type[_Tfilestat], path: bytes) -> _Tfilestat:
2499 try: 2505 try:
2500 stat = os.stat(path) 2506 stat = os.stat(path)
2501 except FileNotFoundError: 2507 except FileNotFoundError:
2502 stat = None 2508 stat = None
2503 return cls(stat) 2509 return cls(stat)
2504 2510
2505 @classmethod 2511 @classmethod
2506 def fromfp(cls, fp): 2512 def fromfp(cls: Type[_Tfilestat], fp: BinaryIO) -> _Tfilestat:
2507 stat = os.fstat(fp.fileno()) 2513 stat = os.fstat(fp.fileno())
2508 return cls(stat) 2514 return cls(stat)
2509 2515
2510 __hash__ = object.__hash__ 2516 __hash__ = object.__hash__
2511 2517
2512 def __eq__(self, old): 2518 def __eq__(self, old) -> bool:
2513 try: 2519 try:
2514 # if ambiguity between stat of new and old file is 2520 # if ambiguity between stat of new and old file is
2515 # avoided, comparison of size, ctime and mtime is enough 2521 # avoided, comparison of size, ctime and mtime is enough
2516 # to exactly detect change of a file regardless of platform 2522 # to exactly detect change of a file regardless of platform
2517 return ( 2523 return (
2524 try: 2530 try:
2525 return self.stat is None and old.stat is None 2531 return self.stat is None and old.stat is None
2526 except AttributeError: 2532 except AttributeError:
2527 return False 2533 return False
2528 2534
2529 def isambig(self, old): 2535 def isambig(self, old: _Tfilestat) -> bool:
2530 """Examine whether new (= self) stat is ambiguous against old one 2536 """Examine whether new (= self) stat is ambiguous against old one
2531 2537
2532 "S[N]" below means stat of a file at N-th change: 2538 "S[N]" below means stat of a file at N-th change:
2533 2539
2534 - S[n-1].ctime < S[n].ctime: can detect change of a file 2540 - S[n-1].ctime < S[n].ctime: can detect change of a file
2559 try: 2565 try:
2560 return self.stat[stat.ST_CTIME] == old.stat[stat.ST_CTIME] 2566 return self.stat[stat.ST_CTIME] == old.stat[stat.ST_CTIME]
2561 except AttributeError: 2567 except AttributeError:
2562 return False 2568 return False
2563 2569
2564 def avoidambig(self, path, old): 2570 def avoidambig(self, path: bytes, old: _Tfilestat) -> bool:
2565 """Change file stat of specified path to avoid ambiguity 2571 """Change file stat of specified path to avoid ambiguity
2566 2572
2567 'old' should be previous filestat of 'path'. 2573 'old' should be previous filestat of 'path'.
2568 2574
2569 This skips avoiding ambiguity, if a process doesn't have 2575 This skips avoiding ambiguity, if a process doesn't have
2579 # utime() on the file created by another user causes EPERM, 2585 # utime() on the file created by another user causes EPERM,
2580 # if a process doesn't have appropriate privileges 2586 # if a process doesn't have appropriate privileges
2581 return False 2587 return False
2582 return True 2588 return True
2583 2589
2584 def __ne__(self, other): 2590 def __ne__(self, other) -> bool:
2585 return not self == other 2591 return not self == other
2586 2592
2587 2593
2588 class atomictempfile: 2594 class atomictempfile:
2589 """writable file object that atomically updates a file 2595 """writable file object that atomically updates a file