comparison mercurial/util.py @ 51304:f15cb5111a1e

pytype: move some type comment to proper annotation We support direct type annotations now, while pytype is starting to complains about them.
author Pierre-Yves David <pierre-yves.david@octobus.net>
date Tue, 19 Dec 2023 21:29:34 +0100
parents 9d3721552b6c
children 7d3b92e8df13
comparison
equal deleted inserted replaced
51303:81224afd938d 51304:f15cb5111a1e
145 umask = platform.umask 145 umask = platform.umask
146 unlink = platform.unlink 146 unlink = platform.unlink
147 username = platform.username 147 username = platform.username
148 148
149 149
150 def setumask(val): 150 def setumask(val: int) -> None:
151 # type: (int) -> None
152 '''updates the umask. used by chg server''' 151 '''updates the umask. used by chg server'''
153 if pycompat.iswindows: 152 if pycompat.iswindows:
154 return 153 return
155 os.umask(val) 154 os.umask(val)
156 global umask 155 global umask
1848 if pycompat.ispypy: 1847 if pycompat.ispypy:
1849 # PyPy runs slower with gc disabled 1848 # PyPy runs slower with gc disabled
1850 nogc = lambda x: x 1849 nogc = lambda x: x
1851 1850
1852 1851
1853 def pathto(root, n1, n2): 1852 def pathto(root: bytes, n1: bytes, n2: bytes) -> bytes:
1854 # type: (bytes, bytes, bytes) -> bytes
1855 """return the relative path from one place to another. 1853 """return the relative path from one place to another.
1856 root should use os.sep to separate directories 1854 root should use os.sep to separate directories
1857 n1 should use os.sep to separate directories 1855 n1 should use os.sep to separate directories
1858 n2 should use "/" to separate directories 1856 n2 should use "/" to separate directories
1859 returns an os.sep-separated path. 1857 returns an os.sep-separated path.
2060 b'lpt9', 2058 b'lpt9',
2061 } 2059 }
2062 _winreservedchars = b':*?"<>|' 2060 _winreservedchars = b':*?"<>|'
2063 2061
2064 2062
2065 def checkwinfilename(path): 2063 def checkwinfilename(path: bytes) -> Optional[bytes]:
2066 # type: (bytes) -> Optional[bytes]
2067 r"""Check that the base-relative path is a valid filename on Windows. 2064 r"""Check that the base-relative path is a valid filename on Windows.
2068 Returns None if the path is ok, or a UI string describing the problem. 2065 Returns None if the path is ok, or a UI string describing the problem.
2069 2066
2070 >>> checkwinfilename(b"just/a/normal/path") 2067 >>> checkwinfilename(b"just/a/normal/path")
2071 >>> checkwinfilename(b"foo/bar/con.xml") 2068 >>> checkwinfilename(b"foo/bar/con.xml")
2155 ld = os.open(pathname, flags) 2152 ld = os.open(pathname, flags)
2156 os.write(ld, info) 2153 os.write(ld, info)
2157 os.close(ld) 2154 os.close(ld)
2158 2155
2159 2156
2160 def readlock(pathname): 2157 def readlock(pathname: bytes) -> bytes:
2161 # type: (bytes) -> bytes
2162 try: 2158 try:
2163 return readlink(pathname) 2159 return readlink(pathname)
2164 except OSError as why: 2160 except OSError as why:
2165 if why.errno not in (errno.EINVAL, errno.ENOSYS): 2161 if why.errno not in (errno.EINVAL, errno.ENOSYS):
2166 raise 2162 raise
2179 2175
2180 2176
2181 # File system features 2177 # File system features
2182 2178
2183 2179
2184 def fscasesensitive(path): 2180 def fscasesensitive(path: bytes) -> bool:
2185 # type: (bytes) -> bool
2186 """ 2181 """
2187 Return true if the given path is on a case-sensitive filesystem 2182 Return true if the given path is on a case-sensitive filesystem
2188 2183
2189 Requires a path (like /foo/.hg) ending with a foldable final 2184 Requires a path (like /foo/.hg) ending with a foldable final
2190 directory component. 2185 directory component.
2284 re = _re() 2279 re = _re()
2285 2280
2286 _fspathcache = {} 2281 _fspathcache = {}
2287 2282
2288 2283
2289 def fspath(name, root): 2284 def fspath(name: bytes, root: bytes) -> bytes:
2290 # type: (bytes, bytes) -> bytes
2291 """Get name in the case stored in the filesystem 2285 """Get name in the case stored in the filesystem
2292 2286
2293 The name should be relative to root, and be normcase-ed for efficiency. 2287 The name should be relative to root, and be normcase-ed for efficiency.
2294 2288
2295 Note that this function is unnecessary, and should not be 2289 Note that this function is unnecessary, and should not be
2329 dir = os.path.join(dir, part) 2323 dir = os.path.join(dir, part)
2330 2324
2331 return b''.join(result) 2325 return b''.join(result)
2332 2326
2333 2327
2334 def checknlink(testfile): 2328 def checknlink(testfile: bytes) -> bool:
2335 # type: (bytes) -> bool
2336 '''check whether hardlink count reporting works properly''' 2329 '''check whether hardlink count reporting works properly'''
2337 2330
2338 # testfile may be open, so we need a separate file for checking to 2331 # testfile may be open, so we need a separate file for checking to
2339 # work around issue2543 (or testfile may get lost on Samba shares) 2332 # work around issue2543 (or testfile may get lost on Samba shares)
2340 f1, f2, fp = None, None, None 2333 f1, f2, fp = None, None, None
2363 os.unlink(f) 2356 os.unlink(f)
2364 except OSError: 2357 except OSError:
2365 pass 2358 pass
2366 2359
2367 2360
2368 def endswithsep(path): 2361 def endswithsep(path: bytes) -> bool:
2369 # type: (bytes) -> bool
2370 '''Check path ends with os.sep or os.altsep.''' 2362 '''Check path ends with os.sep or os.altsep.'''
2371 return bool( # help pytype 2363 return bool( # help pytype
2372 path.endswith(pycompat.ossep) 2364 path.endswith(pycompat.ossep)
2373 or pycompat.osaltsep 2365 or pycompat.osaltsep
2374 and path.endswith(pycompat.osaltsep) 2366 and path.endswith(pycompat.osaltsep)
2375 ) 2367 )
2376 2368
2377 2369
2378 def splitpath(path): 2370 def splitpath(path: bytes) -> List[bytes]:
2379 # type: (bytes) -> List[bytes]
2380 """Split path by os.sep. 2371 """Split path by os.sep.
2381 Note that this function does not use os.altsep because this is 2372 Note that this function does not use os.altsep because this is
2382 an alternative of simple "xxx.split(os.sep)". 2373 an alternative of simple "xxx.split(os.sep)".
2383 It is recommended to use os.path.normpath() before using this 2374 It is recommended to use os.path.normpath() before using this
2384 function if need.""" 2375 function if need."""
2607 except OSError as e: 2598 except OSError as e:
2608 if e.errno != errno.ENOENT and e.errno != errno.ENOTEMPTY: 2599 if e.errno != errno.ENOENT and e.errno != errno.ENOTEMPTY:
2609 raise 2600 raise
2610 2601
2611 2602
2612 def unlinkpath(f, ignoremissing=False, rmdir=True): 2603 def unlinkpath(
2613 # type: (bytes, bool, bool) -> None 2604 f: bytes, ignoremissing: bool = False, rmdir: bool = True
2605 ) -> None:
2614 """unlink and remove the directory if it is empty""" 2606 """unlink and remove the directory if it is empty"""
2615 if ignoremissing: 2607 if ignoremissing:
2616 tryunlink(f) 2608 tryunlink(f)
2617 else: 2609 else:
2618 unlink(f) 2610 unlink(f)
2622 removedirs(os.path.dirname(f)) 2614 removedirs(os.path.dirname(f))
2623 except OSError: 2615 except OSError:
2624 pass 2616 pass
2625 2617
2626 2618
2627 def tryunlink(f): 2619 def tryunlink(f: bytes) -> None:
2628 # type: (bytes) -> None
2629 """Attempt to remove a file, ignoring FileNotFoundError.""" 2620 """Attempt to remove a file, ignoring FileNotFoundError."""
2630 try: 2621 try:
2631 unlink(f) 2622 unlink(f)
2632 except FileNotFoundError: 2623 except FileNotFoundError:
2633 pass 2624 pass
2634 2625
2635 2626
2636 def makedirs(name, mode=None, notindexed=False): 2627 def makedirs(
2637 # type: (bytes, Optional[int], bool) -> None 2628 name: bytes, mode: Optional[int] = None, notindexed: bool = False
2629 ) -> None:
2638 """recursive directory creation with parent mode inheritance 2630 """recursive directory creation with parent mode inheritance
2639 2631
2640 Newly created directories are marked as "not to be indexed by 2632 Newly created directories are marked as "not to be indexed by
2641 the content indexing service", if ``notindexed`` is specified 2633 the content indexing service", if ``notindexed`` is specified
2642 for "write" mode access. 2634 for "write" mode access.
2661 raise 2653 raise
2662 if mode is not None: 2654 if mode is not None:
2663 os.chmod(name, mode) 2655 os.chmod(name, mode)
2664 2656
2665 2657
2666 def readfile(path): 2658 def readfile(path: bytes) -> bytes:
2667 # type: (bytes) -> bytes
2668 with open(path, b'rb') as fp: 2659 with open(path, b'rb') as fp:
2669 return fp.read() 2660 return fp.read()
2670 2661
2671 2662
2672 def writefile(path, text): 2663 def writefile(path: bytes, text: bytes) -> None:
2673 # type: (bytes, bytes) -> None
2674 with open(path, b'wb') as fp: 2664 with open(path, b'wb') as fp:
2675 fp.write(text) 2665 fp.write(text)
2676 2666
2677 2667
2678 def appendfile(path, text): 2668 def appendfile(path: bytes, text: bytes) -> None:
2679 # type: (bytes, bytes) -> None
2680 with open(path, b'ab') as fp: 2669 with open(path, b'ab') as fp:
2681 fp.write(text) 2670 fp.write(text)
2682 2671
2683 2672
2684 class chunkbuffer: 2673 class chunkbuffer:
2835 return unittable[-1][2] % count 2824 return unittable[-1][2] % count
2836 2825
2837 return go 2826 return go
2838 2827
2839 2828
2840 def processlinerange(fromline, toline): 2829 def processlinerange(fromline: int, toline: int) -> Tuple[int, int]:
2841 # type: (int, int) -> Tuple[int, int]
2842 """Check that linerange <fromline>:<toline> makes sense and return a 2830 """Check that linerange <fromline>:<toline> makes sense and return a
2843 0-based range. 2831 0-based range.
2844 2832
2845 >>> processlinerange(10, 20) 2833 >>> processlinerange(10, 20)
2846 (9, 20) 2834 (9, 20)
2895 # are removed or a LF. We do not care about old Macintosh files, so a 2883 # are removed or a LF. We do not care about old Macintosh files, so a
2896 # stray CR is an error. 2884 # stray CR is an error.
2897 _eolre = remod.compile(br'\r*\n') 2885 _eolre = remod.compile(br'\r*\n')
2898 2886
2899 2887
2900 def tolf(s): 2888 def tolf(s: bytes) -> bytes:
2901 # type: (bytes) -> bytes
2902 return _eolre.sub(b'\n', s) 2889 return _eolre.sub(b'\n', s)
2903 2890
2904 2891
2905 def tocrlf(s): 2892 def tocrlf(s: bytes) -> bytes:
2906 # type: (bytes) -> bytes
2907 return _eolre.sub(b'\r\n', s) 2893 return _eolre.sub(b'\r\n', s)
2908 2894
2909 2895
2910 def _crlfwriter(fp): 2896 def _crlfwriter(fp):
2911 return transformingwriter(fp, tocrlf) 2897 return transformingwriter(fp, tocrlf)
2924 # TODO delete since workaround variant for Python 2 no longer needed. 2910 # TODO delete since workaround variant for Python 2 no longer needed.
2925 def iterfile(fp): 2911 def iterfile(fp):
2926 return fp 2912 return fp
2927 2913
2928 2914
2929 def iterlines(iterator): 2915 def iterlines(iterator: Iterable[bytes]) -> Iterator[bytes]:
2930 # type: (Iterable[bytes]) -> Iterator[bytes]
2931 for chunk in iterator: 2916 for chunk in iterator:
2932 for line in chunk.splitlines(): 2917 for line in chunk.splitlines():
2933 yield line 2918 yield line
2934 2919
2935 2920
2936 def expandpath(path): 2921 def expandpath(path: bytes) -> bytes:
2937 # type: (bytes) -> bytes
2938 return os.path.expanduser(os.path.expandvars(path)) 2922 return os.path.expanduser(os.path.expandvars(path))
2939 2923
2940 2924
2941 def interpolate(prefix, mapping, s, fn=None, escape_prefix=False): 2925 def interpolate(prefix, mapping, s, fn=None, escape_prefix=False):
2942 """Return the result of interpolating items in the mapping into string s. 2926 """Return the result of interpolating items in the mapping into string s.
3060 (b'gb', 2 ** 30), 3044 (b'gb', 2 ** 30),
3061 (b'b', 1), 3045 (b'b', 1),
3062 ) 3046 )
3063 3047
3064 3048
3065 def sizetoint(s): 3049 def sizetoint(s: bytes) -> int:
3066 # type: (bytes) -> int
3067 """Convert a space specifier to a byte count. 3050 """Convert a space specifier to a byte count.
3068 3051
3069 >>> sizetoint(b'30') 3052 >>> sizetoint(b'30')
3070 30 3053 30
3071 >>> sizetoint(b'2.2kb') 3054 >>> sizetoint(b'2.2kb')
3283 locale.setlocale(locale.LC_CTYPE, oldloc) 3266 locale.setlocale(locale.LC_CTYPE, oldloc)
3284 else: 3267 else:
3285 yield 3268 yield
3286 3269
3287 3270
3288 def _estimatememory(): 3271 def _estimatememory() -> Optional[int]:
3289 # type: () -> Optional[int]
3290 """Provide an estimate for the available system memory in Bytes. 3272 """Provide an estimate for the available system memory in Bytes.
3291 3273
3292 If no estimate can be provided on the platform, returns None. 3274 If no estimate can be provided on the platform, returns None.
3293 """ 3275 """
3294 if pycompat.sysplatform.startswith(b'win'): 3276 if pycompat.sysplatform.startswith(b'win'):