Mercurial > public > mercurial-scm > hg-stable
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'): |