|
4 | 4 | import os |
5 | 5 | import sys |
6 | 6 | import zipfile |
| 7 | +from functools import cached_property |
| 8 | +from importlib.abc import SourceLoader |
| 9 | +from importlib.util import spec_from_file_location |
7 | 10 |
|
8 | 11 | ABS_HERE = os.path.abspath(os.path.dirname(__file__)) |
9 | | -NEW_IMPORT_SYSTEM = sys.version_info[0] >= 3 # noqa: PLR2004 |
10 | 12 |
|
11 | 13 |
|
12 | 14 | class VersionPlatformSelect: |
13 | 15 | def __init__(self) -> None: |
14 | | - self.archive = ABS_HERE |
15 | | - self._zip_file = zipfile.ZipFile(ABS_HERE, "r") |
| 16 | + zipapp = ABS_HERE |
| 17 | + self.archive = zipapp |
| 18 | + self._zip_file = zipfile.ZipFile(zipapp) |
16 | 19 | self.modules = self._load("modules.json") |
17 | 20 | self.distributions = self._load("distributions.json") |
18 | 21 | self.__cache = {} |
19 | 22 |
|
20 | 23 | def _load(self, of_file): |
21 | 24 | version = ".".join(str(i) for i in sys.version_info[0:2]) |
22 | | - per_version = json.loads(self.get_data(of_file).decode("utf-8")) |
| 25 | + per_version = json.loads(self.get_data(of_file).decode()) |
23 | 26 | all_platforms = per_version[version] if version in per_version else per_version["3.9"] |
24 | 27 | content = all_platforms.get("==any", {}) # start will all platforms |
25 | 28 | not_us = f"!={sys.platform}" |
@@ -65,25 +68,62 @@ def find_distributions(self, context): |
65 | 68 | def __repr__(self) -> str: |
66 | 69 | return f"{self.__class__.__name__}(path={ABS_HERE})" |
67 | 70 |
|
68 | | - def _register_distutils_finder(self): |
| 71 | + def _register_distutils_finder(self): # noqa: C901 |
69 | 72 | if "distlib" not in self.modules: |
70 | 73 | return |
71 | 74 |
|
| 75 | + class Resource: |
| 76 | + def __init__(self, path: str, name: str, loader: SourceLoader) -> None: |
| 77 | + self.path = os.path.join(path, name) |
| 78 | + self.name = name |
| 79 | + self.loader = loader |
| 80 | + |
| 81 | + @property |
| 82 | + def bytes(self) -> bytes: |
| 83 | + return self.loader.get_data(self.name) |
| 84 | + |
| 85 | + @property |
| 86 | + def is_container(self) -> bool: |
| 87 | + return len(self.resources) > 1 |
| 88 | + |
| 89 | + @cached_property |
| 90 | + def resources(self) -> list[str]: |
| 91 | + return [ |
| 92 | + i.filename |
| 93 | + for i in ( |
| 94 | + (j for j in zip_file.filelist if j.filename.startswith(f"{self.name}/")) |
| 95 | + if self.name |
| 96 | + else zip_file.filelist |
| 97 | + ) |
| 98 | + ] |
| 99 | + |
72 | 100 | class DistlibFinder: |
73 | 101 | def __init__(self, path, loader) -> None: |
74 | 102 | self.path = path |
75 | 103 | self.loader = loader |
76 | 104 |
|
77 | 105 | def find(self, name): |
78 | | - class Resource: |
79 | | - def __init__(self, content) -> None: |
80 | | - self.bytes = content |
81 | | - |
82 | | - full_path = os.path.join(self.path, name) |
83 | | - return Resource(self.loader.get_data(full_path)) |
| 106 | + return Resource(self.path, name, self.loader) |
| 107 | + |
| 108 | + def iterator(self, resource_name): |
| 109 | + resource = self.find(resource_name) |
| 110 | + if resource is not None: |
| 111 | + todo = [resource] |
| 112 | + while todo: |
| 113 | + resource = todo.pop(0) |
| 114 | + yield resource |
| 115 | + if resource.is_container: |
| 116 | + resource_name = resource.name |
| 117 | + for name in resource.resources: |
| 118 | + child = self.find(f"{resource_name}/{name}" if resource_name else name) |
| 119 | + if child.is_container: |
| 120 | + todo.append(child) |
| 121 | + else: |
| 122 | + yield child |
84 | 123 |
|
85 | 124 | from distlib.resources import register_finder # noqa: PLC0415 |
86 | 125 |
|
| 126 | + zip_file = self._zip_file |
87 | 127 | register_finder(self, lambda module: DistlibFinder(os.path.dirname(module.__file__), self)) |
88 | 128 |
|
89 | 129 |
|
@@ -113,41 +153,15 @@ def locate_file(self, path): |
113 | 153 | return _VER_DISTRIBUTION_CLASS |
114 | 154 |
|
115 | 155 |
|
116 | | -if NEW_IMPORT_SYSTEM: |
117 | | - from importlib.abc import SourceLoader |
118 | | - from importlib.util import spec_from_file_location |
119 | | - |
120 | | - class VersionedFindLoad(VersionPlatformSelect, SourceLoader): |
121 | | - def find_spec(self, fullname, path, target=None): # noqa: ARG002 |
122 | | - zip_path = self.find_mod(fullname) |
123 | | - if zip_path is not None: |
124 | | - return spec_from_file_location(name=fullname, loader=self) |
125 | | - return None |
126 | | - |
127 | | - def module_repr(self, module): |
128 | | - raise NotImplementedError |
129 | | - |
130 | | -else: |
131 | | - from imp import new_module |
132 | | - |
133 | | - class VersionedFindLoad(VersionPlatformSelect): |
134 | | - def find_module(self, fullname, path=None): # noqa: ARG002 |
135 | | - return self if self.find_mod(fullname) else None |
136 | | - |
137 | | - def load_module(self, fullname): |
138 | | - filename = self.get_filename(fullname) |
139 | | - code = self.get_data(filename) |
140 | | - mod = sys.modules.setdefault(fullname, new_module(fullname)) |
141 | | - mod.__file__ = filename |
142 | | - mod.__loader__ = self |
143 | | - is_package = filename.endswith("__init__.py") |
144 | | - if is_package: |
145 | | - mod.__path__ = [os.path.dirname(filename)] |
146 | | - mod.__package__ = fullname |
147 | | - else: |
148 | | - mod.__package__ = fullname.rpartition(".")[0] |
149 | | - exec(code, mod.__dict__) # noqa: S102 |
150 | | - return mod |
| 156 | +class VersionedFindLoad(VersionPlatformSelect, SourceLoader): |
| 157 | + def find_spec(self, fullname, path, target=None): # noqa: ARG002 |
| 158 | + zip_path = self.find_mod(fullname) |
| 159 | + if zip_path is not None: |
| 160 | + return spec_from_file_location(name=fullname, loader=self) |
| 161 | + return None |
| 162 | + |
| 163 | + def module_repr(self, module): |
| 164 | + raise NotImplementedError |
151 | 165 |
|
152 | 166 |
|
153 | 167 | def run(): |
|
0 commit comments