Mercurial > public > mercurial-scm > hg
comparison mercurial/utils/resourceutil.py @ 51665:32a1c9226dd9
typing: add type hints to `mercurial/utils/resourceutil.py`
The `except` path requires byte args (because of the byte based manipulation in
`_package_path()`), while the `else` case tolerates `AnyStr`. Pytype was unable
to figure this out, and we should make sure the interface is the same for all
environments.
author | Matt Harbison <matt_harbison@yahoo.com> |
---|---|
date | Wed, 10 Jul 2024 15:49:16 -0400 |
parents | d718eddf01d9 |
children | 493034cc3265 |
comparison
equal
deleted
inserted
replaced
51663:8e3f6b5bf720 | 51665:32a1c9226dd9 |
---|---|
9 | 9 |
10 | 10 |
11 import _imp | 11 import _imp |
12 import os | 12 import os |
13 import sys | 13 import sys |
14 import typing | |
14 | 15 |
15 from .. import pycompat | 16 from .. import pycompat |
17 | |
18 | |
19 if typing.TYPE_CHECKING: | |
20 from typing import ( | |
21 BinaryIO, | |
22 Iterator, | |
23 ) | |
16 | 24 |
17 | 25 |
18 def mainfrozen(): | 26 def mainfrozen(): |
19 """return True if we are a frozen executable. | 27 """return True if we are a frozen executable. |
20 | 28 |
37 # The installers store the files outside of library.zip, like | 45 # The installers store the files outside of library.zip, like |
38 # C:\Program Files\Mercurial\defaultrc\*.rc. This strips the | 46 # C:\Program Files\Mercurial\defaultrc\*.rc. This strips the |
39 # leading "mercurial." off of the package name, so that these | 47 # leading "mercurial." off of the package name, so that these |
40 # pseudo resources are found in their directory next to the | 48 # pseudo resources are found in their directory next to the |
41 # executable. | 49 # executable. |
42 def _package_path(package): | 50 def _package_path(package: bytes) -> bytes: |
43 dirs = package.split(b".") | 51 dirs = package.split(b".") |
44 assert dirs[0] == b"mercurial" | 52 assert dirs[0] == b"mercurial" |
45 return os.path.join(_rootpath, *dirs[1:]) | 53 return os.path.join(_rootpath, *dirs[1:]) |
46 | 54 |
47 | 55 |
48 else: | 56 else: |
49 datapath = os.path.dirname(os.path.dirname(pycompat.fsencode(__file__))) | 57 datapath = os.path.dirname(os.path.dirname(pycompat.fsencode(__file__))) |
50 _rootpath = os.path.dirname(datapath) | 58 _rootpath = os.path.dirname(datapath) |
51 | 59 |
52 def _package_path(package): | 60 def _package_path(package: bytes) -> bytes: |
53 return os.path.join(_rootpath, *package.split(b".")) | 61 return os.path.join(_rootpath, *package.split(b".")) |
54 | 62 |
55 | 63 |
56 try: | 64 try: |
57 # importlib.resources exists from Python 3.7; see fallback in except clause | 65 # importlib.resources exists from Python 3.7; see fallback in except clause |
70 | 78 |
71 except (ImportError, AttributeError): | 79 except (ImportError, AttributeError): |
72 # importlib.resources was not found (almost definitely because we're on a | 80 # importlib.resources was not found (almost definitely because we're on a |
73 # Python version before 3.7) | 81 # Python version before 3.7) |
74 | 82 |
75 def open_resource(package, name): | 83 def open_resource(package: bytes, name: bytes) -> "BinaryIO": |
76 path = os.path.join(_package_path(package), name) | 84 path = os.path.join(_package_path(package), name) |
77 return open(path, "rb") | 85 return open(path, "rb") |
78 | 86 |
79 def is_resource(package, name): | 87 def is_resource(package: bytes, name: bytes) -> bool: |
80 path = os.path.join(_package_path(package), name) | 88 path = os.path.join(_package_path(package), name) |
81 | 89 |
82 try: | 90 try: |
83 return os.path.isfile(pycompat.fsdecode(path)) | 91 return os.path.isfile(pycompat.fsdecode(path)) |
84 except (IOError, OSError): | 92 except (IOError, OSError): |
85 return False | 93 return False |
86 | 94 |
87 def contents(package): | 95 def contents(package: bytes) -> "Iterator[bytes]": |
88 path = pycompat.fsdecode(_package_path(package)) | 96 path = pycompat.fsdecode(_package_path(package)) |
89 | 97 |
90 for p in os.listdir(path): | 98 for p in os.listdir(path): |
91 yield pycompat.fsencode(p) | 99 yield pycompat.fsencode(p) |
92 | 100 |
93 | 101 |
94 else: | 102 else: |
95 from .. import encoding | 103 from .. import encoding |
96 | 104 |
97 def open_resource(package, name): | 105 def open_resource(package: bytes, name: bytes) -> "BinaryIO": |
98 if hasattr(resources, 'files'): | 106 if hasattr(resources, 'files'): |
99 return ( | 107 return ( |
100 resources.files( # pytype: disable=module-attr | 108 resources.files( # pytype: disable=module-attr |
101 pycompat.sysstr(package) | 109 pycompat.sysstr(package) |
102 ) | 110 ) |
106 else: | 114 else: |
107 return resources.open_binary( # pytype: disable=module-attr | 115 return resources.open_binary( # pytype: disable=module-attr |
108 pycompat.sysstr(package), pycompat.sysstr(name) | 116 pycompat.sysstr(package), pycompat.sysstr(name) |
109 ) | 117 ) |
110 | 118 |
111 def is_resource(package, name): | 119 def is_resource(package: bytes, name: bytes) -> bool: |
112 return resources.is_resource( # pytype: disable=module-attr | 120 return resources.is_resource( # pytype: disable=module-attr |
113 pycompat.sysstr(package), encoding.strfromlocal(name) | 121 pycompat.sysstr(package), encoding.strfromlocal(name) |
114 ) | 122 ) |
115 | 123 |
116 def contents(package): | 124 def contents(package: bytes) -> "Iterator[bytes]": |
117 # pytype: disable=module-attr | 125 # pytype: disable=module-attr |
118 for r in resources.contents(pycompat.sysstr(package)): | 126 for r in resources.contents(pycompat.sysstr(package)): |
119 # pytype: enable=module-attr | 127 # pytype: enable=module-attr |
120 yield encoding.strtolocal(r) | 128 yield encoding.strtolocal(r) |