relenv 0.21.2__py3-none-any.whl → 0.22.1__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- relenv/__init__.py +14 -2
- relenv/__main__.py +12 -6
- relenv/_resources/xz/config.h +148 -0
- relenv/_resources/xz/readme.md +4 -0
- relenv/build/__init__.py +28 -30
- relenv/build/common/__init__.py +50 -0
- relenv/build/common/_sysconfigdata_template.py +72 -0
- relenv/build/common/builder.py +907 -0
- relenv/build/common/builders.py +163 -0
- relenv/build/common/download.py +324 -0
- relenv/build/common/install.py +609 -0
- relenv/build/common/ui.py +432 -0
- relenv/build/darwin.py +128 -14
- relenv/build/linux.py +292 -74
- relenv/build/windows.py +123 -169
- relenv/buildenv.py +48 -17
- relenv/check.py +10 -5
- relenv/common.py +492 -165
- relenv/create.py +147 -7
- relenv/fetch.py +16 -4
- relenv/manifest.py +15 -7
- relenv/python-versions.json +350 -0
- relenv/pyversions.py +817 -30
- relenv/relocate.py +101 -55
- relenv/runtime.py +457 -282
- relenv/toolchain.py +9 -3
- {relenv-0.21.2.dist-info → relenv-0.22.1.dist-info}/METADATA +1 -1
- relenv-0.22.1.dist-info/RECORD +48 -0
- tests/__init__.py +2 -0
- tests/_pytest_typing.py +45 -0
- tests/conftest.py +42 -36
- tests/test_build.py +426 -9
- tests/test_common.py +373 -48
- tests/test_create.py +149 -6
- tests/test_downloads.py +19 -15
- tests/test_fips_photon.py +6 -3
- tests/test_module_imports.py +44 -0
- tests/test_pyversions_runtime.py +177 -0
- tests/test_relocate.py +45 -39
- tests/test_relocate_module.py +257 -0
- tests/test_runtime.py +1968 -6
- tests/test_verify_build.py +477 -34
- relenv/build/common.py +0 -1707
- relenv-0.21.2.dist-info/RECORD +0 -35
- {relenv-0.21.2.dist-info → relenv-0.22.1.dist-info}/WHEEL +0 -0
- {relenv-0.21.2.dist-info → relenv-0.22.1.dist-info}/entry_points.txt +0 -0
- {relenv-0.21.2.dist-info → relenv-0.22.1.dist-info}/licenses/LICENSE.md +0 -0
- {relenv-0.21.2.dist-info → relenv-0.22.1.dist-info}/licenses/NOTICE +0 -0
- {relenv-0.21.2.dist-info → relenv-0.22.1.dist-info}/top_level.txt +0 -0
relenv/runtime.py
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
# Copyright 2022-2025 Broadcom.
|
|
2
|
-
# SPDX-License-Identifier: Apache-2
|
|
2
|
+
# SPDX-License-Identifier: Apache-2.0
|
|
3
3
|
"""
|
|
4
4
|
This code is run when initializing the python interperter in a Relenv environment.
|
|
5
5
|
|
|
@@ -10,19 +10,61 @@ This code is run when initializing the python interperter in a Relenv environmen
|
|
|
10
10
|
gcc. This ensures when using pip any c dependencies are compiled against the
|
|
11
11
|
proper glibc version.
|
|
12
12
|
"""
|
|
13
|
+
from __future__ import annotations
|
|
14
|
+
|
|
13
15
|
import contextlib
|
|
14
|
-
import ctypes
|
|
16
|
+
import ctypes as _ctypes
|
|
15
17
|
import functools
|
|
16
|
-
import importlib
|
|
17
|
-
import json
|
|
18
|
+
import importlib as _importlib
|
|
19
|
+
import json as _json
|
|
18
20
|
import os
|
|
19
21
|
import pathlib
|
|
20
|
-
import shutil
|
|
21
|
-
import site
|
|
22
|
-
import subprocess
|
|
23
|
-
import sys
|
|
22
|
+
import shutil as _shutil
|
|
23
|
+
import site as _site
|
|
24
|
+
import subprocess as _subprocess
|
|
25
|
+
import sys as _sys
|
|
24
26
|
import textwrap
|
|
25
|
-
import warnings
|
|
27
|
+
import warnings as _warnings
|
|
28
|
+
from importlib.machinery import ModuleSpec
|
|
29
|
+
from types import ModuleType
|
|
30
|
+
from typing import (
|
|
31
|
+
Any,
|
|
32
|
+
Callable,
|
|
33
|
+
Dict,
|
|
34
|
+
Iterable,
|
|
35
|
+
Iterator,
|
|
36
|
+
Optional,
|
|
37
|
+
Sequence,
|
|
38
|
+
Union,
|
|
39
|
+
cast,
|
|
40
|
+
)
|
|
41
|
+
|
|
42
|
+
# The tests monkeypatch these module-level imports (e.g., json.loads) inside
|
|
43
|
+
# relenv.runtime itself; keeping them as Any both preserves test isolation—no
|
|
44
|
+
# need to patch the global stdlib modules—and avoids mypy attr-defined noise
|
|
45
|
+
# while still exercising the real runtime wiring.
|
|
46
|
+
json = cast(Any, _json)
|
|
47
|
+
importlib = cast(Any, _importlib)
|
|
48
|
+
site = cast(Any, _site)
|
|
49
|
+
subprocess = cast(Any, _subprocess)
|
|
50
|
+
sys = cast(Any, _sys)
|
|
51
|
+
ctypes = cast(Any, _ctypes)
|
|
52
|
+
shutil = cast(Any, _shutil)
|
|
53
|
+
warnings = cast(Any, _warnings)
|
|
54
|
+
|
|
55
|
+
__all__ = [
|
|
56
|
+
"sys",
|
|
57
|
+
"shutil",
|
|
58
|
+
"subprocess",
|
|
59
|
+
"json",
|
|
60
|
+
"importlib",
|
|
61
|
+
"site",
|
|
62
|
+
"ctypes",
|
|
63
|
+
"warnings",
|
|
64
|
+
]
|
|
65
|
+
|
|
66
|
+
PathType = Union[str, os.PathLike[str]]
|
|
67
|
+
ConfigVars = Dict[str, str]
|
|
26
68
|
|
|
27
69
|
# relenv.pth has a __file__ which is set to the path to site.py of the python
|
|
28
70
|
# interpreter being used. We're using that to determine the proper
|
|
@@ -32,7 +74,7 @@ import warnings
|
|
|
32
74
|
# imports happen before our path munghing in site in wrapsitecustomize.
|
|
33
75
|
|
|
34
76
|
|
|
35
|
-
def path_import(name, path):
|
|
77
|
+
def path_import(name: str, path: PathType) -> ModuleType:
|
|
36
78
|
"""
|
|
37
79
|
Import module from a path.
|
|
38
80
|
|
|
@@ -42,46 +84,50 @@ def path_import(name, path):
|
|
|
42
84
|
import importlib.util
|
|
43
85
|
|
|
44
86
|
spec = importlib.util.spec_from_file_location(name, path)
|
|
87
|
+
if spec is None or spec.loader is None:
|
|
88
|
+
raise ImportError(f"Unable to load module {name} from {path}")
|
|
45
89
|
module = importlib.util.module_from_spec(spec)
|
|
46
90
|
spec.loader.exec_module(module)
|
|
47
91
|
sys.modules[name] = module
|
|
48
92
|
return module
|
|
49
93
|
|
|
50
94
|
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
95
|
+
_COMMON: Optional[ModuleType] = None
|
|
96
|
+
_RELOCATE: Optional[ModuleType] = None
|
|
97
|
+
_BUILDENV: Optional[ModuleType] = None
|
|
98
|
+
|
|
99
|
+
|
|
100
|
+
def common() -> ModuleType:
|
|
101
|
+
"""Return the cached ``relenv.common`` module."""
|
|
102
|
+
global _COMMON
|
|
103
|
+
if _COMMON is None:
|
|
104
|
+
_COMMON = path_import(
|
|
57
105
|
"relenv.common", str(pathlib.Path(__file__).parent / "common.py")
|
|
58
106
|
)
|
|
59
|
-
return
|
|
107
|
+
return _COMMON
|
|
60
108
|
|
|
61
109
|
|
|
62
|
-
def relocate():
|
|
63
|
-
"""
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
relocate.relocate = path_import(
|
|
110
|
+
def relocate() -> ModuleType:
|
|
111
|
+
"""Return the cached ``relenv.relocate`` module."""
|
|
112
|
+
global _RELOCATE
|
|
113
|
+
if _RELOCATE is None:
|
|
114
|
+
_RELOCATE = path_import(
|
|
68
115
|
"relenv.relocate", str(pathlib.Path(__file__).parent / "relocate.py")
|
|
69
116
|
)
|
|
70
|
-
return
|
|
117
|
+
return _RELOCATE
|
|
71
118
|
|
|
72
119
|
|
|
73
|
-
def buildenv():
|
|
74
|
-
"""
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
buildenv.buildenv = path_import(
|
|
120
|
+
def buildenv() -> ModuleType:
|
|
121
|
+
"""Return the cached ``relenv.buildenv`` module."""
|
|
122
|
+
global _BUILDENV
|
|
123
|
+
if _BUILDENV is None:
|
|
124
|
+
_BUILDENV = path_import(
|
|
79
125
|
"relenv.buildenv", str(pathlib.Path(__file__).parent / "buildenv.py")
|
|
80
126
|
)
|
|
81
|
-
return
|
|
127
|
+
return _BUILDENV
|
|
82
128
|
|
|
83
129
|
|
|
84
|
-
def get_major_version():
|
|
130
|
+
def get_major_version() -> str:
|
|
85
131
|
"""
|
|
86
132
|
Current python major version.
|
|
87
133
|
"""
|
|
@@ -89,7 +135,7 @@ def get_major_version():
|
|
|
89
135
|
|
|
90
136
|
|
|
91
137
|
@contextlib.contextmanager
|
|
92
|
-
def pushd(new_dir):
|
|
138
|
+
def pushd(new_dir: PathType) -> Iterator[None]:
|
|
93
139
|
"""
|
|
94
140
|
Changedir context.
|
|
95
141
|
"""
|
|
@@ -101,7 +147,7 @@ def pushd(new_dir):
|
|
|
101
147
|
os.chdir(old_dir)
|
|
102
148
|
|
|
103
149
|
|
|
104
|
-
def debug(string):
|
|
150
|
+
def debug(string: str) -> None:
|
|
105
151
|
"""
|
|
106
152
|
Prints the provided message if RELENV_DEBUG is truthy in the environment.
|
|
107
153
|
|
|
@@ -113,7 +159,7 @@ def debug(string):
|
|
|
113
159
|
sys.stdout.flush()
|
|
114
160
|
|
|
115
161
|
|
|
116
|
-
def relenv_root():
|
|
162
|
+
def relenv_root() -> pathlib.Path:
|
|
117
163
|
"""
|
|
118
164
|
Return the relenv module root.
|
|
119
165
|
"""
|
|
@@ -126,7 +172,9 @@ def relenv_root():
|
|
|
126
172
|
return MODULE_DIR.parent.parent.parent.parent
|
|
127
173
|
|
|
128
174
|
|
|
129
|
-
def _build_shebang(
|
|
175
|
+
def _build_shebang(
|
|
176
|
+
func: Callable[..., bytes], *args: Any, **kwargs: Any
|
|
177
|
+
) -> Callable[..., bytes]:
|
|
130
178
|
"""
|
|
131
179
|
Build a shebang to point to the proper location.
|
|
132
180
|
|
|
@@ -135,34 +183,37 @@ def _build_shebang(func, *args, **kwargs):
|
|
|
135
183
|
"""
|
|
136
184
|
|
|
137
185
|
@functools.wraps(func)
|
|
138
|
-
def wrapped(self, *args, **kwargs):
|
|
186
|
+
def wrapped(self: Any, *args: Any, **kwargs: Any) -> bytes:
|
|
139
187
|
scripts = pathlib.Path(self.target_dir)
|
|
140
188
|
if TARGET.TARGET:
|
|
141
|
-
scripts = pathlib.Path(
|
|
189
|
+
scripts = pathlib.Path(_ensure_target_path()).absolute() / "bin"
|
|
142
190
|
try:
|
|
143
191
|
interpreter = common().relative_interpreter(
|
|
144
192
|
sys.RELENV, scripts, pathlib.Path(sys.executable).resolve()
|
|
145
193
|
)
|
|
146
194
|
except ValueError:
|
|
147
195
|
debug(f"Relenv Value Error - _build_shebang {self.target_dir}")
|
|
148
|
-
|
|
196
|
+
original_result: bytes = func(self, *args, **kwargs)
|
|
197
|
+
return original_result
|
|
149
198
|
debug(f"Relenv - _build_shebang {scripts} {interpreter}")
|
|
150
199
|
if sys.platform == "win32":
|
|
151
200
|
return (
|
|
152
201
|
str(pathlib.Path("#!<launcher_dir>") / interpreter).encode() + b"\r\n"
|
|
153
202
|
)
|
|
154
|
-
|
|
203
|
+
rel_path = str(pathlib.PurePosixPath("/") / interpreter)
|
|
204
|
+
formatted = cast(str, common().format_shebang(rel_path))
|
|
205
|
+
return formatted.encode()
|
|
155
206
|
|
|
156
207
|
return wrapped
|
|
157
208
|
|
|
158
209
|
|
|
159
|
-
def get_config_var_wrapper(func):
|
|
210
|
+
def get_config_var_wrapper(func: Callable[[str], Any]) -> Callable[[str], Any]:
|
|
160
211
|
"""
|
|
161
212
|
Return a wrapper to resolve paths relative to the relenv root.
|
|
162
213
|
"""
|
|
163
214
|
|
|
164
215
|
@functools.wraps(func)
|
|
165
|
-
def wrapped(name):
|
|
216
|
+
def wrapped(name: str) -> Any:
|
|
166
217
|
if name == "BINDIR":
|
|
167
218
|
orig = func(name)
|
|
168
219
|
if os.environ.get("RELENV_PIP_DIR"):
|
|
@@ -179,13 +230,13 @@ def get_config_var_wrapper(func):
|
|
|
179
230
|
return wrapped
|
|
180
231
|
|
|
181
232
|
|
|
182
|
-
|
|
233
|
+
CONFIG_VARS_DEFAULTS: ConfigVars = {
|
|
183
234
|
"AR": "ar",
|
|
184
235
|
"CC": "gcc",
|
|
185
236
|
"CFLAGS": "-Wno-unused-result -Wsign-compare -DNDEBUG -g -fwrapv -O3 -Wall",
|
|
186
237
|
"CPPFLAGS": "-I. -I./Include",
|
|
187
238
|
"CXX": "g++",
|
|
188
|
-
"LIBDEST": "/usr/local/lib/python3.
|
|
239
|
+
"LIBDEST": "/usr/local/lib/python3.10",
|
|
189
240
|
"SCRIPTDIR": "/usr/local/lib",
|
|
190
241
|
"BLDSHARED": "gcc -shared",
|
|
191
242
|
"LDFLAGS": "",
|
|
@@ -193,10 +244,10 @@ _CONFIG_VARS_DEFAULTS = {
|
|
|
193
244
|
"LDSHARED": "gcc -shared",
|
|
194
245
|
}
|
|
195
246
|
|
|
196
|
-
_SYSTEM_CONFIG_VARS = None
|
|
247
|
+
_SYSTEM_CONFIG_VARS: Optional[ConfigVars] = None
|
|
197
248
|
|
|
198
249
|
|
|
199
|
-
def system_sysconfig():
|
|
250
|
+
def system_sysconfig() -> ConfigVars:
|
|
200
251
|
"""
|
|
201
252
|
Read the system python's sysconfig values.
|
|
202
253
|
|
|
@@ -204,7 +255,7 @@ def system_sysconfig():
|
|
|
204
255
|
to avoid the overhead of shelling out.
|
|
205
256
|
"""
|
|
206
257
|
global _SYSTEM_CONFIG_VARS
|
|
207
|
-
if _SYSTEM_CONFIG_VARS:
|
|
258
|
+
if _SYSTEM_CONFIG_VARS is not None:
|
|
208
259
|
return _SYSTEM_CONFIG_VARS
|
|
209
260
|
pyexec = pathlib.Path("/usr/bin/python3")
|
|
210
261
|
if pyexec.exists():
|
|
@@ -220,25 +271,27 @@ def system_sysconfig():
|
|
|
220
271
|
_SYSTEM_CONFIG_VARS = json.loads(p.stdout.strip())
|
|
221
272
|
except json.JSONDecodeError:
|
|
222
273
|
debug(f"Failed to load JSON from: {p.stdout.strip()}")
|
|
223
|
-
_SYSTEM_CONFIG_VARS =
|
|
274
|
+
_SYSTEM_CONFIG_VARS = CONFIG_VARS_DEFAULTS
|
|
224
275
|
else:
|
|
225
276
|
debug("System python not found")
|
|
226
|
-
_SYSTEM_CONFIG_VARS =
|
|
277
|
+
_SYSTEM_CONFIG_VARS = CONFIG_VARS_DEFAULTS
|
|
227
278
|
return _SYSTEM_CONFIG_VARS
|
|
228
279
|
|
|
229
280
|
|
|
230
|
-
def get_config_vars_wrapper(
|
|
281
|
+
def get_config_vars_wrapper(
|
|
282
|
+
func: Callable[..., ConfigVars], mod: ModuleType
|
|
283
|
+
) -> Callable[..., ConfigVars]:
|
|
231
284
|
"""
|
|
232
285
|
Return a wrapper to resolve paths relative to the relenv root.
|
|
233
286
|
"""
|
|
234
287
|
|
|
235
288
|
@functools.wraps(func)
|
|
236
|
-
def wrapped(*args):
|
|
289
|
+
def wrapped(*args: Any) -> ConfigVars:
|
|
237
290
|
if sys.platform == "win32" or "RELENV_BUILDENV" in os.environ:
|
|
238
291
|
return func(*args)
|
|
239
292
|
|
|
240
|
-
|
|
241
|
-
|
|
293
|
+
config_vars = func()
|
|
294
|
+
system_config_vars = system_sysconfig()
|
|
242
295
|
for name in [
|
|
243
296
|
"AR",
|
|
244
297
|
"CC",
|
|
@@ -252,20 +305,26 @@ def get_config_vars_wrapper(func, mod):
|
|
|
252
305
|
"LDCXXSHARED",
|
|
253
306
|
"LDSHARED",
|
|
254
307
|
]:
|
|
255
|
-
|
|
256
|
-
mod
|
|
308
|
+
config_vars[name] = system_config_vars[name]
|
|
309
|
+
setattr(mod, "_CONFIG_VARS", config_vars)
|
|
257
310
|
return func(*args)
|
|
258
311
|
|
|
259
312
|
return wrapped
|
|
260
313
|
|
|
261
314
|
|
|
262
|
-
def get_paths_wrapper(
|
|
315
|
+
def get_paths_wrapper(
|
|
316
|
+
func: Callable[..., Dict[str, str]], default_scheme: str
|
|
317
|
+
) -> Callable[..., Dict[str, str]]:
|
|
263
318
|
"""
|
|
264
319
|
Return a wrapper to resolve paths relative to the relenv root.
|
|
265
320
|
"""
|
|
266
321
|
|
|
267
322
|
@functools.wraps(func)
|
|
268
|
-
def wrapped(
|
|
323
|
+
def wrapped(
|
|
324
|
+
scheme: Optional[str] = default_scheme,
|
|
325
|
+
vars: Optional[Dict[str, str]] = None,
|
|
326
|
+
expand: bool = True,
|
|
327
|
+
) -> Dict[str, str]:
|
|
269
328
|
paths = func(scheme=scheme, vars=vars, expand=expand)
|
|
270
329
|
if "RELENV_PIP_DIR" in os.environ:
|
|
271
330
|
paths["scripts"] = str(relenv_root())
|
|
@@ -275,7 +334,7 @@ def get_paths_wrapper(func, default_scheme):
|
|
|
275
334
|
return wrapped
|
|
276
335
|
|
|
277
336
|
|
|
278
|
-
def finalize_options_wrapper(func):
|
|
337
|
+
def finalize_options_wrapper(func: Callable[..., Any]) -> Callable[..., Any]:
|
|
279
338
|
"""
|
|
280
339
|
Wrapper around build_ext.finalize_options.
|
|
281
340
|
|
|
@@ -283,15 +342,15 @@ def finalize_options_wrapper(func):
|
|
|
283
342
|
"""
|
|
284
343
|
|
|
285
344
|
@functools.wraps(func)
|
|
286
|
-
def wrapper(self, *args, **kwargs):
|
|
345
|
+
def wrapper(self: Any, *args: Any, **kwargs: Any) -> None:
|
|
287
346
|
func(self, *args, **kwargs)
|
|
288
347
|
if "RELENV_BUILDENV" in os.environ:
|
|
289
|
-
self.include_dirs.append(
|
|
348
|
+
self.include_dirs.append(str(relenv_root() / "include"))
|
|
290
349
|
|
|
291
350
|
return wrapper
|
|
292
351
|
|
|
293
352
|
|
|
294
|
-
def install_wheel_wrapper(func):
|
|
353
|
+
def install_wheel_wrapper(func: Callable[..., Any]) -> Callable[..., Any]:
|
|
295
354
|
"""
|
|
296
355
|
Wrap pip's wheel install function.
|
|
297
356
|
|
|
@@ -300,15 +359,15 @@ def install_wheel_wrapper(func):
|
|
|
300
359
|
|
|
301
360
|
@functools.wraps(func)
|
|
302
361
|
def wrapper(
|
|
303
|
-
name,
|
|
304
|
-
wheel_path,
|
|
305
|
-
scheme,
|
|
306
|
-
req_description,
|
|
307
|
-
pycompile,
|
|
308
|
-
warn_script_location,
|
|
309
|
-
direct_url,
|
|
310
|
-
requested,
|
|
311
|
-
):
|
|
362
|
+
name: str,
|
|
363
|
+
wheel_path: PathType,
|
|
364
|
+
scheme: Any,
|
|
365
|
+
req_description: str,
|
|
366
|
+
pycompile: Any,
|
|
367
|
+
warn_script_location: Any,
|
|
368
|
+
direct_url: Any,
|
|
369
|
+
requested: Any,
|
|
370
|
+
) -> Any:
|
|
312
371
|
from zipfile import ZipFile
|
|
313
372
|
|
|
314
373
|
from pip._internal.utils.wheel import parse_wheel
|
|
@@ -348,7 +407,7 @@ def install_wheel_wrapper(func):
|
|
|
348
407
|
return wrapper
|
|
349
408
|
|
|
350
409
|
|
|
351
|
-
def install_legacy_wrapper(func):
|
|
410
|
+
def install_legacy_wrapper(func: Callable[..., Any]) -> Callable[..., Any]:
|
|
352
411
|
"""
|
|
353
412
|
Wrap pip's legacy install function.
|
|
354
413
|
|
|
@@ -359,21 +418,21 @@ def install_legacy_wrapper(func):
|
|
|
359
418
|
|
|
360
419
|
@functools.wraps(func)
|
|
361
420
|
def wrapper(
|
|
362
|
-
install_options,
|
|
363
|
-
global_options,
|
|
364
|
-
root,
|
|
365
|
-
home,
|
|
366
|
-
prefix,
|
|
367
|
-
use_user_site,
|
|
368
|
-
pycompile,
|
|
369
|
-
scheme,
|
|
370
|
-
setup_py_path,
|
|
371
|
-
isolated,
|
|
372
|
-
req_name,
|
|
373
|
-
build_env,
|
|
374
|
-
unpacked_source_directory,
|
|
375
|
-
req_description,
|
|
376
|
-
):
|
|
421
|
+
install_options: Any,
|
|
422
|
+
global_options: Any,
|
|
423
|
+
root: Any,
|
|
424
|
+
home: Any,
|
|
425
|
+
prefix: Any,
|
|
426
|
+
use_user_site: Any,
|
|
427
|
+
pycompile: Any,
|
|
428
|
+
scheme: Any,
|
|
429
|
+
setup_py_path: Any,
|
|
430
|
+
isolated: Any,
|
|
431
|
+
req_name: Any,
|
|
432
|
+
build_env: Any,
|
|
433
|
+
unpacked_source_directory: Any,
|
|
434
|
+
req_description: Any,
|
|
435
|
+
) -> Any:
|
|
377
436
|
|
|
378
437
|
pkginfo = pathlib.Path(setup_py_path).parent / "PKG-INFO"
|
|
379
438
|
with open(pkginfo) as fp:
|
|
@@ -447,13 +506,19 @@ class Wrapper:
|
|
|
447
506
|
Wrap methods of an imported module.
|
|
448
507
|
"""
|
|
449
508
|
|
|
450
|
-
def __init__(
|
|
509
|
+
def __init__(
|
|
510
|
+
self,
|
|
511
|
+
module: str,
|
|
512
|
+
wrapper: Callable[[str], ModuleType],
|
|
513
|
+
matcher: str = "equals",
|
|
514
|
+
_loading: bool = False,
|
|
515
|
+
) -> None:
|
|
451
516
|
self.module = module
|
|
452
517
|
self.wrapper = wrapper
|
|
453
518
|
self.matcher = matcher
|
|
454
519
|
self.loading = _loading
|
|
455
520
|
|
|
456
|
-
def matches(self, module):
|
|
521
|
+
def matches(self: "Wrapper", module: str) -> bool:
|
|
457
522
|
"""
|
|
458
523
|
Check if wrapper metches module being imported.
|
|
459
524
|
"""
|
|
@@ -461,7 +526,7 @@ class Wrapper:
|
|
|
461
526
|
return module.startswith(self.module)
|
|
462
527
|
return self.module == module
|
|
463
528
|
|
|
464
|
-
def __call__(self, module_name):
|
|
529
|
+
def __call__(self: "Wrapper", module_name: str) -> ModuleType:
|
|
465
530
|
"""
|
|
466
531
|
Preform the wrapper operation.
|
|
467
532
|
"""
|
|
@@ -473,15 +538,24 @@ class RelenvImporter:
|
|
|
473
538
|
Handle runtime wrapping of module methods.
|
|
474
539
|
"""
|
|
475
540
|
|
|
476
|
-
def __init__(
|
|
541
|
+
def __init__(
|
|
542
|
+
self,
|
|
543
|
+
wrappers: Optional[Iterable[Wrapper]] = None,
|
|
544
|
+
_loads: Optional[Dict[str, ModuleType]] = None,
|
|
545
|
+
) -> None:
|
|
477
546
|
if wrappers is None:
|
|
478
547
|
wrappers = []
|
|
479
|
-
self.wrappers = set(wrappers)
|
|
548
|
+
self.wrappers: set[Wrapper] = set(wrappers)
|
|
480
549
|
if _loads is None:
|
|
481
550
|
_loads = {}
|
|
482
|
-
self._loads = _loads
|
|
483
|
-
|
|
484
|
-
def find_spec(
|
|
551
|
+
self._loads: Dict[str, ModuleType] = _loads
|
|
552
|
+
|
|
553
|
+
def find_spec(
|
|
554
|
+
self: "RelenvImporter",
|
|
555
|
+
module_name: str,
|
|
556
|
+
package_path: Optional[Sequence[str]] = None,
|
|
557
|
+
target: Any = None,
|
|
558
|
+
) -> Optional[ModuleSpec]:
|
|
485
559
|
"""
|
|
486
560
|
Find modules being imported.
|
|
487
561
|
"""
|
|
@@ -489,9 +563,15 @@ class RelenvImporter:
|
|
|
489
563
|
if wrapper.matches(module_name) and not wrapper.loading:
|
|
490
564
|
debug(f"RelenvImporter - match {module_name} {package_path} {target}")
|
|
491
565
|
wrapper.loading = True
|
|
492
|
-
|
|
566
|
+
spec = importlib.util.spec_from_loader(module_name, self)
|
|
567
|
+
return cast(Optional[ModuleSpec], spec)
|
|
568
|
+
return None
|
|
493
569
|
|
|
494
|
-
def find_module(
|
|
570
|
+
def find_module(
|
|
571
|
+
self: "RelenvImporter",
|
|
572
|
+
module_name: str,
|
|
573
|
+
package_path: Optional[Sequence[str]] = None,
|
|
574
|
+
) -> Optional["RelenvImporter"]:
|
|
495
575
|
"""
|
|
496
576
|
Find modules being imported.
|
|
497
577
|
"""
|
|
@@ -500,38 +580,43 @@ class RelenvImporter:
|
|
|
500
580
|
debug(f"RelenvImporter - match {module_name}")
|
|
501
581
|
wrapper.loading = True
|
|
502
582
|
return self
|
|
583
|
+
return None
|
|
503
584
|
|
|
504
|
-
def load_module(self, name):
|
|
585
|
+
def load_module(self: "RelenvImporter", name: str) -> ModuleType:
|
|
505
586
|
"""
|
|
506
587
|
Load an imported module.
|
|
507
588
|
"""
|
|
589
|
+
mod: Optional[ModuleType] = None
|
|
508
590
|
for wrapper in self.wrappers:
|
|
509
591
|
if wrapper.matches(name):
|
|
510
592
|
debug(f"RelenvImporter - load_module {name}")
|
|
511
593
|
mod = wrapper(name)
|
|
512
594
|
wrapper.loading = False
|
|
513
595
|
break
|
|
596
|
+
if mod is None:
|
|
597
|
+
mod = importlib.import_module(name)
|
|
514
598
|
sys.modules[name] = mod
|
|
515
599
|
return mod
|
|
516
600
|
|
|
517
|
-
def create_module(self, spec):
|
|
601
|
+
def create_module(self: "RelenvImporter", spec: ModuleSpec) -> Optional[ModuleType]:
|
|
518
602
|
"""
|
|
519
603
|
Create the module via a spec.
|
|
520
604
|
"""
|
|
521
605
|
return self.load_module(spec.name)
|
|
522
606
|
|
|
523
|
-
def exec_module(self, module):
|
|
607
|
+
def exec_module(self: "RelenvImporter", module: ModuleType) -> None:
|
|
524
608
|
"""
|
|
525
609
|
Exec module noop.
|
|
526
610
|
"""
|
|
527
611
|
return None
|
|
528
612
|
|
|
529
613
|
|
|
530
|
-
def wrap_sysconfig(name):
|
|
614
|
+
def wrap_sysconfig(name: str) -> ModuleType:
|
|
531
615
|
"""
|
|
532
616
|
Sysconfig wrapper.
|
|
533
617
|
"""
|
|
534
|
-
|
|
618
|
+
module: ModuleType = importlib.import_module("sysconfig")
|
|
619
|
+
mod = cast(Any, module)
|
|
535
620
|
mod.get_config_var = get_config_var_wrapper(mod.get_config_var)
|
|
536
621
|
mod.get_config_vars = get_config_vars_wrapper(mod.get_config_vars, mod)
|
|
537
622
|
mod._PIP_USE_SYSCONFIG = True
|
|
@@ -542,48 +627,52 @@ def wrap_sysconfig(name):
|
|
|
542
627
|
# Python < 3.10
|
|
543
628
|
scheme = mod._get_default_scheme()
|
|
544
629
|
mod.get_paths = get_paths_wrapper(mod.get_paths, scheme)
|
|
545
|
-
return
|
|
630
|
+
return module
|
|
546
631
|
|
|
547
632
|
|
|
548
|
-
def wrap_pip_distlib_scripts(name):
|
|
633
|
+
def wrap_pip_distlib_scripts(name: str) -> ModuleType:
|
|
549
634
|
"""
|
|
550
635
|
pip.distlib.scripts wrapper.
|
|
551
636
|
"""
|
|
552
|
-
|
|
637
|
+
module: ModuleType = importlib.import_module(name)
|
|
638
|
+
mod = cast(Any, module)
|
|
553
639
|
mod.ScriptMaker._build_shebang = _build_shebang(mod.ScriptMaker._build_shebang)
|
|
554
|
-
return
|
|
640
|
+
return module
|
|
555
641
|
|
|
556
642
|
|
|
557
|
-
def wrap_distutils_command(name):
|
|
643
|
+
def wrap_distutils_command(name: str) -> ModuleType:
|
|
558
644
|
"""
|
|
559
645
|
distutils.command wrapper.
|
|
560
646
|
"""
|
|
561
|
-
|
|
647
|
+
module: ModuleType = importlib.import_module(name)
|
|
648
|
+
mod = cast(Any, module)
|
|
562
649
|
mod.build_ext.finalize_options = finalize_options_wrapper(
|
|
563
650
|
mod.build_ext.finalize_options
|
|
564
651
|
)
|
|
565
|
-
return
|
|
652
|
+
return module
|
|
566
653
|
|
|
567
654
|
|
|
568
|
-
def wrap_pip_install_wheel(name):
|
|
655
|
+
def wrap_pip_install_wheel(name: str) -> ModuleType:
|
|
569
656
|
"""
|
|
570
657
|
pip._internal.operations.install.wheel wrapper.
|
|
571
658
|
"""
|
|
572
|
-
|
|
659
|
+
module: ModuleType = importlib.import_module(name)
|
|
660
|
+
mod = cast(Any, module)
|
|
573
661
|
mod.install_wheel = install_wheel_wrapper(mod.install_wheel)
|
|
574
|
-
return
|
|
662
|
+
return module
|
|
575
663
|
|
|
576
664
|
|
|
577
|
-
def wrap_pip_install_legacy(name):
|
|
665
|
+
def wrap_pip_install_legacy(name: str) -> ModuleType:
|
|
578
666
|
"""
|
|
579
667
|
pip._internal.operations.install.legacy wrapper.
|
|
580
668
|
"""
|
|
581
|
-
|
|
669
|
+
module: ModuleType = importlib.import_module(name)
|
|
670
|
+
mod = cast(Any, module)
|
|
582
671
|
mod.install = install_legacy_wrapper(mod.install)
|
|
583
|
-
return
|
|
672
|
+
return module
|
|
584
673
|
|
|
585
674
|
|
|
586
|
-
def set_env_if_not_set(name, value):
|
|
675
|
+
def set_env_if_not_set(name: str, value: str) -> None:
|
|
587
676
|
"""
|
|
588
677
|
Set an environment variable if not already set.
|
|
589
678
|
|
|
@@ -600,21 +689,21 @@ def set_env_if_not_set(name, value):
|
|
|
600
689
|
os.environ[name] = value
|
|
601
690
|
|
|
602
691
|
|
|
603
|
-
def wrap_pip_build_wheel(name):
|
|
692
|
+
def wrap_pip_build_wheel(name: str) -> ModuleType:
|
|
604
693
|
"""
|
|
605
694
|
pip._internal.operations.build wrapper.
|
|
606
695
|
"""
|
|
607
|
-
|
|
696
|
+
module: ModuleType = importlib.import_module(name)
|
|
697
|
+
mod = cast(Any, module)
|
|
608
698
|
|
|
609
|
-
def wrap(func):
|
|
699
|
+
def wrap(func: Callable[..., Any]) -> Callable[..., Any]:
|
|
610
700
|
@functools.wraps(func)
|
|
611
|
-
def wrapper(*args, **kwargs):
|
|
701
|
+
def wrapper(*args: Any, **kwargs: Any) -> Any:
|
|
612
702
|
if sys.platform != "linux":
|
|
613
703
|
return func(*args, **kwargs)
|
|
614
|
-
|
|
615
|
-
toolchain = base_dir / common().get_triplet()
|
|
704
|
+
toolchain = common().get_toolchain()
|
|
616
705
|
cargo_home = str(common().DATA_DIR / "cargo")
|
|
617
|
-
if not toolchain.exists():
|
|
706
|
+
if toolchain is None or not toolchain.exists():
|
|
618
707
|
debug("Unable to set CARGO_HOME no toolchain exists")
|
|
619
708
|
else:
|
|
620
709
|
relenvroot = str(sys.RELENV)
|
|
@@ -631,7 +720,7 @@ def wrap_pip_build_wheel(name):
|
|
|
631
720
|
return wrapper
|
|
632
721
|
|
|
633
722
|
mod.build_wheel_pep517 = wrap(mod.build_wheel_pep517)
|
|
634
|
-
return
|
|
723
|
+
return module
|
|
635
724
|
|
|
636
725
|
|
|
637
726
|
class TARGET:
|
|
@@ -639,21 +728,31 @@ class TARGET:
|
|
|
639
728
|
Container for global pip target state.
|
|
640
729
|
"""
|
|
641
730
|
|
|
642
|
-
TARGET = False
|
|
643
|
-
|
|
644
|
-
IGNORE = False
|
|
645
|
-
INSTALL = False
|
|
731
|
+
TARGET: bool = False
|
|
732
|
+
PATH: Optional[str] = None
|
|
733
|
+
IGNORE: bool = False
|
|
734
|
+
INSTALL: bool = False
|
|
735
|
+
|
|
736
|
+
|
|
737
|
+
def _ensure_target_path() -> str:
|
|
738
|
+
"""
|
|
739
|
+
Return the stored target path, raising if it is unavailable.
|
|
740
|
+
"""
|
|
741
|
+
if TARGET.PATH is None:
|
|
742
|
+
raise RuntimeError("TARGET path requested but not initialized")
|
|
743
|
+
return TARGET.PATH
|
|
646
744
|
|
|
647
745
|
|
|
648
|
-
def wrap_cmd_install(name):
|
|
746
|
+
def wrap_cmd_install(name: str) -> ModuleType:
|
|
649
747
|
"""
|
|
650
748
|
Wrap pip install command to store target argument state.
|
|
651
749
|
"""
|
|
652
|
-
|
|
750
|
+
module: ModuleType = importlib.import_module(name)
|
|
751
|
+
mod = cast(Any, module)
|
|
653
752
|
|
|
654
|
-
def
|
|
753
|
+
def wrap_run(func: Callable[..., Any]) -> Callable[..., Any]:
|
|
655
754
|
@functools.wraps(func)
|
|
656
|
-
def wrapper(self, options, args):
|
|
755
|
+
def wrapper(self: Any, options: Any, args: Sequence[str]) -> Any:
|
|
657
756
|
if not options.use_user_site:
|
|
658
757
|
if options.target_dir:
|
|
659
758
|
TARGET.TARGET = True
|
|
@@ -663,11 +762,13 @@ def wrap_cmd_install(name):
|
|
|
663
762
|
|
|
664
763
|
return wrapper
|
|
665
764
|
|
|
666
|
-
mod.InstallCommand.run =
|
|
765
|
+
mod.InstallCommand.run = wrap_run(mod.InstallCommand.run)
|
|
667
766
|
|
|
668
|
-
def
|
|
767
|
+
def wrap_handle_target(func: Callable[..., Any]) -> Callable[..., Any]:
|
|
669
768
|
@functools.wraps(func)
|
|
670
|
-
def wrapper(
|
|
769
|
+
def wrapper(
|
|
770
|
+
self: Any, target_dir: str, target_temp_dir: str, upgrade: bool
|
|
771
|
+
) -> int:
|
|
671
772
|
from pip._internal.cli.status_codes import SUCCESS
|
|
672
773
|
|
|
673
774
|
return SUCCESS
|
|
@@ -675,30 +776,37 @@ def wrap_cmd_install(name):
|
|
|
675
776
|
return wrapper
|
|
676
777
|
|
|
677
778
|
if hasattr(mod.InstallCommand, "_handle_target_dir"):
|
|
678
|
-
mod.InstallCommand._handle_target_dir =
|
|
779
|
+
mod.InstallCommand._handle_target_dir = wrap_handle_target(
|
|
679
780
|
mod.InstallCommand._handle_target_dir
|
|
680
781
|
)
|
|
681
|
-
return
|
|
782
|
+
return module
|
|
682
783
|
|
|
683
784
|
|
|
684
|
-
def wrap_locations(name):
|
|
785
|
+
def wrap_locations(name: str) -> ModuleType:
|
|
685
786
|
"""
|
|
686
787
|
Wrap pip locations to fix locations when installing with target.
|
|
687
788
|
"""
|
|
688
|
-
|
|
789
|
+
module: ModuleType = importlib.import_module(name)
|
|
790
|
+
mod = cast(Any, module)
|
|
689
791
|
|
|
690
|
-
def
|
|
792
|
+
def make_scheme_wrapper(func: Callable[..., Any]) -> Callable[..., Any]:
|
|
691
793
|
@functools.wraps(func)
|
|
692
794
|
def wrapper(
|
|
693
|
-
dist_name
|
|
694
|
-
|
|
795
|
+
dist_name: str,
|
|
796
|
+
user: bool = False,
|
|
797
|
+
home: Optional[PathType] = None,
|
|
798
|
+
root: Optional[PathType] = None,
|
|
799
|
+
isolated: bool = False,
|
|
800
|
+
prefix: Optional[PathType] = None,
|
|
801
|
+
) -> Any:
|
|
695
802
|
scheme = func(dist_name, user, home, root, isolated, prefix)
|
|
696
803
|
if TARGET.TARGET and TARGET.INSTALL:
|
|
697
804
|
from pip._internal.models.scheme import Scheme
|
|
698
805
|
|
|
806
|
+
target_path = _ensure_target_path()
|
|
699
807
|
scheme = Scheme(
|
|
700
|
-
platlib=
|
|
701
|
-
purelib=
|
|
808
|
+
platlib=target_path,
|
|
809
|
+
purelib=target_path,
|
|
702
810
|
headers=scheme.headers,
|
|
703
811
|
scripts=scheme.scripts,
|
|
704
812
|
data=scheme.data,
|
|
@@ -709,142 +817,179 @@ def wrap_locations(name):
|
|
|
709
817
|
|
|
710
818
|
# get_scheme is not available on pip-19.2.3
|
|
711
819
|
# try:
|
|
712
|
-
mod.get_scheme =
|
|
820
|
+
mod.get_scheme = make_scheme_wrapper(mod.get_scheme)
|
|
713
821
|
# except AttributeError:
|
|
714
822
|
# debug(f"Module {mod} does not have attribute get_scheme")
|
|
715
823
|
|
|
716
|
-
return
|
|
824
|
+
return module
|
|
717
825
|
|
|
718
826
|
|
|
719
|
-
def wrap_req_command(name):
|
|
827
|
+
def wrap_req_command(name: str) -> ModuleType:
|
|
720
828
|
"""
|
|
721
829
|
Honor ignore installed option from pip cli.
|
|
722
830
|
"""
|
|
723
|
-
|
|
831
|
+
module: ModuleType = importlib.import_module(name)
|
|
832
|
+
mod = cast(Any, module)
|
|
724
833
|
|
|
725
|
-
def
|
|
834
|
+
def make_package_finder_wrapper(func: Callable[..., Any]) -> Callable[..., Any]:
|
|
726
835
|
@functools.wraps(func)
|
|
727
836
|
def wrapper(
|
|
728
|
-
self,
|
|
729
|
-
options,
|
|
730
|
-
session,
|
|
731
|
-
target_python=None,
|
|
732
|
-
ignore_requires_python=None,
|
|
733
|
-
):
|
|
837
|
+
self: Any,
|
|
838
|
+
options: Any,
|
|
839
|
+
session: Any,
|
|
840
|
+
target_python: Any = None,
|
|
841
|
+
ignore_requires_python: Any = None,
|
|
842
|
+
) -> Any:
|
|
734
843
|
if TARGET.TARGET:
|
|
735
844
|
options.ignore_installed = TARGET.IGNORE
|
|
736
845
|
return func(self, options, session, target_python, ignore_requires_python)
|
|
737
846
|
|
|
738
847
|
return wrapper
|
|
739
848
|
|
|
740
|
-
mod.RequirementCommand._build_package_finder =
|
|
849
|
+
mod.RequirementCommand._build_package_finder = make_package_finder_wrapper(
|
|
741
850
|
mod.RequirementCommand._build_package_finder
|
|
742
851
|
)
|
|
743
|
-
return
|
|
852
|
+
return module
|
|
744
853
|
|
|
745
854
|
|
|
746
|
-
def wrap_req_install(name):
|
|
855
|
+
def wrap_req_install(name: str) -> ModuleType:
|
|
747
856
|
"""
|
|
748
857
|
Honor ignore installed option from pip cli.
|
|
749
858
|
"""
|
|
750
|
-
|
|
751
|
-
|
|
752
|
-
def wrap(func):
|
|
753
|
-
if mod.InstallRequirement.install.__code__.co_argcount == 7:
|
|
754
|
-
|
|
755
|
-
@functools.wraps(func)
|
|
756
|
-
def wrapper(
|
|
757
|
-
self,
|
|
758
|
-
root=None,
|
|
759
|
-
home=None,
|
|
760
|
-
prefix=None,
|
|
761
|
-
warn_script_location=True,
|
|
762
|
-
use_user_site=False,
|
|
763
|
-
pycompile=True,
|
|
764
|
-
):
|
|
765
|
-
try:
|
|
766
|
-
if TARGET.TARGET:
|
|
767
|
-
TARGET.INSTALL = True
|
|
768
|
-
home = TARGET.PATH
|
|
769
|
-
return func(
|
|
770
|
-
self,
|
|
771
|
-
root,
|
|
772
|
-
home,
|
|
773
|
-
prefix,
|
|
774
|
-
warn_script_location,
|
|
775
|
-
use_user_site,
|
|
776
|
-
pycompile,
|
|
777
|
-
)
|
|
778
|
-
finally:
|
|
779
|
-
TARGET.INSTALL = False
|
|
780
|
-
|
|
781
|
-
elif mod.InstallRequirement.install.__code__.co_argcount == 8:
|
|
782
|
-
|
|
783
|
-
@functools.wraps(func)
|
|
784
|
-
def wrapper(
|
|
785
|
-
self,
|
|
786
|
-
global_options=None,
|
|
787
|
-
root=None,
|
|
788
|
-
home=None,
|
|
789
|
-
prefix=None,
|
|
790
|
-
warn_script_location=True,
|
|
791
|
-
use_user_site=False,
|
|
792
|
-
pycompile=True,
|
|
793
|
-
):
|
|
794
|
-
try:
|
|
795
|
-
if TARGET.TARGET:
|
|
796
|
-
TARGET.INSTALL = True
|
|
797
|
-
home = TARGET.PATH
|
|
798
|
-
return func(
|
|
799
|
-
self,
|
|
800
|
-
global_options,
|
|
801
|
-
root,
|
|
802
|
-
home,
|
|
803
|
-
prefix,
|
|
804
|
-
warn_script_location,
|
|
805
|
-
use_user_site,
|
|
806
|
-
pycompile,
|
|
807
|
-
)
|
|
808
|
-
finally:
|
|
809
|
-
TARGET.INSTALL = False
|
|
859
|
+
module: ModuleType = importlib.import_module(name)
|
|
860
|
+
mod = cast(Any, module)
|
|
810
861
|
|
|
811
|
-
|
|
812
|
-
|
|
813
|
-
|
|
814
|
-
@functools.wraps(func)
|
|
815
|
-
def wrapper(
|
|
816
|
-
self,
|
|
817
|
-
install_options,
|
|
818
|
-
global_options=None,
|
|
819
|
-
root=None,
|
|
820
|
-
home=None,
|
|
821
|
-
prefix=None,
|
|
822
|
-
warn_script_location=True,
|
|
823
|
-
use_user_site=False,
|
|
824
|
-
pycompile=True,
|
|
825
|
-
):
|
|
826
|
-
try:
|
|
827
|
-
if TARGET.TARGET:
|
|
828
|
-
TARGET.INSTALL = True
|
|
829
|
-
home = TARGET.PATH
|
|
830
|
-
return func(
|
|
831
|
-
self,
|
|
832
|
-
install_options,
|
|
833
|
-
global_options,
|
|
834
|
-
root,
|
|
835
|
-
home,
|
|
836
|
-
prefix,
|
|
837
|
-
warn_script_location,
|
|
838
|
-
use_user_site,
|
|
839
|
-
pycompile,
|
|
840
|
-
)
|
|
841
|
-
finally:
|
|
842
|
-
TARGET.INSTALL = False
|
|
862
|
+
original = mod.InstallRequirement.install
|
|
863
|
+
argcount = original.__code__.co_argcount
|
|
843
864
|
|
|
844
|
-
|
|
865
|
+
if argcount == 7:
|
|
866
|
+
|
|
867
|
+
@functools.wraps(original)
|
|
868
|
+
def install_wrapper_pep517(
|
|
869
|
+
self: Any,
|
|
870
|
+
root: Optional[PathType] = None,
|
|
871
|
+
home: Optional[PathType] = None,
|
|
872
|
+
prefix: Optional[PathType] = None,
|
|
873
|
+
warn_script_location: bool = True,
|
|
874
|
+
use_user_site: bool = False,
|
|
875
|
+
pycompile: bool = True,
|
|
876
|
+
) -> Any:
|
|
877
|
+
try:
|
|
878
|
+
if TARGET.TARGET:
|
|
879
|
+
TARGET.INSTALL = True
|
|
880
|
+
home = _ensure_target_path()
|
|
881
|
+
return original(
|
|
882
|
+
self,
|
|
883
|
+
root,
|
|
884
|
+
home,
|
|
885
|
+
prefix,
|
|
886
|
+
warn_script_location,
|
|
887
|
+
use_user_site,
|
|
888
|
+
pycompile,
|
|
889
|
+
)
|
|
890
|
+
finally:
|
|
891
|
+
TARGET.INSTALL = False
|
|
892
|
+
|
|
893
|
+
mod.InstallRequirement.install = install_wrapper_pep517
|
|
894
|
+
|
|
895
|
+
elif argcount == 8:
|
|
896
|
+
|
|
897
|
+
@functools.wraps(original)
|
|
898
|
+
def install_wrapper_pep517_opts(
|
|
899
|
+
self: Any,
|
|
900
|
+
global_options: Any = None,
|
|
901
|
+
root: Optional[PathType] = None,
|
|
902
|
+
home: Optional[PathType] = None,
|
|
903
|
+
prefix: Optional[PathType] = None,
|
|
904
|
+
warn_script_location: bool = True,
|
|
905
|
+
use_user_site: bool = False,
|
|
906
|
+
pycompile: bool = True,
|
|
907
|
+
) -> Any:
|
|
908
|
+
try:
|
|
909
|
+
if TARGET.TARGET:
|
|
910
|
+
TARGET.INSTALL = True
|
|
911
|
+
home = _ensure_target_path()
|
|
912
|
+
return original(
|
|
913
|
+
self,
|
|
914
|
+
global_options,
|
|
915
|
+
root,
|
|
916
|
+
home,
|
|
917
|
+
prefix,
|
|
918
|
+
warn_script_location,
|
|
919
|
+
use_user_site,
|
|
920
|
+
pycompile,
|
|
921
|
+
)
|
|
922
|
+
finally:
|
|
923
|
+
TARGET.INSTALL = False
|
|
924
|
+
|
|
925
|
+
mod.InstallRequirement.install = install_wrapper_pep517_opts
|
|
926
|
+
|
|
927
|
+
elif argcount == 9:
|
|
928
|
+
|
|
929
|
+
@functools.wraps(original)
|
|
930
|
+
def install_wrapper_legacy(
|
|
931
|
+
self: Any,
|
|
932
|
+
install_options: Any,
|
|
933
|
+
global_options: Any = None,
|
|
934
|
+
root: Optional[PathType] = None,
|
|
935
|
+
home: Optional[PathType] = None,
|
|
936
|
+
prefix: Optional[PathType] = None,
|
|
937
|
+
warn_script_location: bool = True,
|
|
938
|
+
use_user_site: bool = False,
|
|
939
|
+
pycompile: bool = True,
|
|
940
|
+
) -> Any:
|
|
941
|
+
try:
|
|
942
|
+
if TARGET.TARGET:
|
|
943
|
+
TARGET.INSTALL = True
|
|
944
|
+
home = _ensure_target_path()
|
|
945
|
+
return original(
|
|
946
|
+
self,
|
|
947
|
+
install_options,
|
|
948
|
+
global_options,
|
|
949
|
+
root,
|
|
950
|
+
home,
|
|
951
|
+
prefix,
|
|
952
|
+
warn_script_location,
|
|
953
|
+
use_user_site,
|
|
954
|
+
pycompile,
|
|
955
|
+
)
|
|
956
|
+
finally:
|
|
957
|
+
TARGET.INSTALL = False
|
|
958
|
+
|
|
959
|
+
mod.InstallRequirement.install = install_wrapper_legacy
|
|
960
|
+
|
|
961
|
+
else:
|
|
962
|
+
|
|
963
|
+
@functools.wraps(original)
|
|
964
|
+
def install_wrapper_generic(
|
|
965
|
+
self: Any,
|
|
966
|
+
global_options: Any = None,
|
|
967
|
+
root: Optional[PathType] = None,
|
|
968
|
+
home: Optional[PathType] = None,
|
|
969
|
+
prefix: Optional[PathType] = None,
|
|
970
|
+
warn_script_location: bool = True,
|
|
971
|
+
use_user_site: bool = False,
|
|
972
|
+
pycompile: bool = True,
|
|
973
|
+
) -> Any:
|
|
974
|
+
try:
|
|
975
|
+
if TARGET.TARGET:
|
|
976
|
+
TARGET.INSTALL = True
|
|
977
|
+
home = _ensure_target_path()
|
|
978
|
+
return original(
|
|
979
|
+
self,
|
|
980
|
+
global_options,
|
|
981
|
+
root,
|
|
982
|
+
home,
|
|
983
|
+
prefix,
|
|
984
|
+
warn_script_location,
|
|
985
|
+
use_user_site,
|
|
986
|
+
pycompile,
|
|
987
|
+
)
|
|
988
|
+
finally:
|
|
989
|
+
TARGET.INSTALL = False
|
|
845
990
|
|
|
846
|
-
|
|
847
|
-
return
|
|
991
|
+
mod.InstallRequirement.install = install_wrapper_generic
|
|
992
|
+
return module
|
|
848
993
|
|
|
849
994
|
|
|
850
995
|
importer = RelenvImporter(
|
|
@@ -863,7 +1008,7 @@ importer = RelenvImporter(
|
|
|
863
1008
|
)
|
|
864
1009
|
|
|
865
1010
|
|
|
866
|
-
def install_cargo_config():
|
|
1011
|
+
def install_cargo_config() -> None:
|
|
867
1012
|
"""
|
|
868
1013
|
Setup cargo config.
|
|
869
1014
|
"""
|
|
@@ -887,27 +1032,46 @@ def install_cargo_config():
|
|
|
887
1032
|
return
|
|
888
1033
|
|
|
889
1034
|
# cargo_home = dirs.data / "cargo"
|
|
890
|
-
|
|
891
|
-
cargo_home.mkdir()
|
|
1035
|
+
cargo_home.mkdir(parents=True, exist_ok=True)
|
|
892
1036
|
cargo_config = cargo_home / "config.toml"
|
|
893
|
-
if
|
|
894
|
-
|
|
895
|
-
|
|
896
|
-
|
|
897
|
-
|
|
898
|
-
|
|
899
|
-
|
|
900
|
-
|
|
901
|
-
|
|
902
|
-
|
|
903
|
-
|
|
904
|
-
|
|
1037
|
+
if triplet == "x86_64-linux-gnu":
|
|
1038
|
+
cargo_triplet = "x86_64-unknown-linux-gnu"
|
|
1039
|
+
else:
|
|
1040
|
+
cargo_triplet = "aarch64-unknown-linux-gnu"
|
|
1041
|
+
gcc = toolchain / "bin" / f"{triplet}-gcc"
|
|
1042
|
+
|
|
1043
|
+
def existing_linker() -> str | None:
|
|
1044
|
+
if not cargo_config.exists():
|
|
1045
|
+
return None
|
|
1046
|
+
try:
|
|
1047
|
+
contents = cargo_config.read_text()
|
|
1048
|
+
except OSError:
|
|
1049
|
+
return None
|
|
1050
|
+
marker = f"[target.{cargo_triplet}]"
|
|
1051
|
+
if marker not in contents:
|
|
1052
|
+
return None
|
|
1053
|
+
for line in contents.splitlines():
|
|
1054
|
+
stripped = line.strip()
|
|
1055
|
+
if stripped.startswith("linker"):
|
|
1056
|
+
value_part: str
|
|
1057
|
+
_, _, value_part = stripped.partition("=")
|
|
1058
|
+
value_str: str = value_part.strip().strip('"')
|
|
1059
|
+
if value_str:
|
|
1060
|
+
return value_str
|
|
1061
|
+
return None
|
|
1062
|
+
|
|
1063
|
+
if existing_linker() != str(gcc):
|
|
1064
|
+
cargo_config.write_text(
|
|
1065
|
+
textwrap.dedent(
|
|
1066
|
+
"""\
|
|
1067
|
+
[target.{triplet}]
|
|
1068
|
+
linker = "{linker}"
|
|
905
1069
|
"""
|
|
906
|
-
|
|
907
|
-
|
|
1070
|
+
).format(triplet=cargo_triplet, linker=gcc)
|
|
1071
|
+
)
|
|
908
1072
|
|
|
909
1073
|
|
|
910
|
-
def setup_openssl():
|
|
1074
|
+
def setup_openssl() -> None:
|
|
911
1075
|
"""
|
|
912
1076
|
Configure openssl certificate locations.
|
|
913
1077
|
"""
|
|
@@ -947,7 +1111,7 @@ def setup_openssl():
|
|
|
947
1111
|
debug(msg)
|
|
948
1112
|
else:
|
|
949
1113
|
try:
|
|
950
|
-
_, directory = proc.stdout.split(":")
|
|
1114
|
+
_, directory = proc.stdout.split(":", 1)
|
|
951
1115
|
except ValueError:
|
|
952
1116
|
debug("Unable to parse modules dir")
|
|
953
1117
|
return
|
|
@@ -981,7 +1145,7 @@ def setup_openssl():
|
|
|
981
1145
|
debug(msg)
|
|
982
1146
|
else:
|
|
983
1147
|
try:
|
|
984
|
-
_, directory = proc.stdout.split(":")
|
|
1148
|
+
_, directory = proc.stdout.split(":", 1)
|
|
985
1149
|
except ValueError:
|
|
986
1150
|
debug("Unable to parse openssldir")
|
|
987
1151
|
return
|
|
@@ -993,7 +1157,7 @@ def setup_openssl():
|
|
|
993
1157
|
os.environ["SSL_CERT_FILE"] = str(cert_file)
|
|
994
1158
|
|
|
995
1159
|
|
|
996
|
-
def set_openssl_modules_dir(path):
|
|
1160
|
+
def set_openssl_modules_dir(path: str) -> None:
|
|
997
1161
|
"""
|
|
998
1162
|
Set the default search location for openssl modules.
|
|
999
1163
|
"""
|
|
@@ -1011,7 +1175,7 @@ def set_openssl_modules_dir(path):
|
|
|
1011
1175
|
OSSL_PROVIDER_set_default_search_path(None, path.encode())
|
|
1012
1176
|
|
|
1013
1177
|
|
|
1014
|
-
def load_openssl_provider(name):
|
|
1178
|
+
def load_openssl_provider(name: str) -> int:
|
|
1015
1179
|
"""
|
|
1016
1180
|
Load an openssl module.
|
|
1017
1181
|
"""
|
|
@@ -1024,10 +1188,11 @@ def load_openssl_provider(name):
|
|
|
1024
1188
|
OSSL_PROVIDER_load = libcrypto.OSSL_PROVIDER_load
|
|
1025
1189
|
OSSL_PROVIDER_load.argtypes = (POSSL_LIB_CTX, ctypes.c_char_p)
|
|
1026
1190
|
OSSL_PROVIDER_load.restype = ctypes.c_int
|
|
1027
|
-
|
|
1191
|
+
result = OSSL_PROVIDER_load(None, name.encode())
|
|
1192
|
+
return int(result)
|
|
1028
1193
|
|
|
1029
1194
|
|
|
1030
|
-
def setup_crossroot():
|
|
1195
|
+
def setup_crossroot() -> None:
|
|
1031
1196
|
"""
|
|
1032
1197
|
Setup cross root if needed.
|
|
1033
1198
|
"""
|
|
@@ -1045,7 +1210,7 @@ def setup_crossroot():
|
|
|
1045
1210
|
] + [_ for _ in sys.path if "site-packages" not in _]
|
|
1046
1211
|
|
|
1047
1212
|
|
|
1048
|
-
def wrapsitecustomize(func):
|
|
1213
|
+
def wrapsitecustomize(func: Callable[[], Any]) -> Callable[[], None]:
|
|
1049
1214
|
"""
|
|
1050
1215
|
Wrap site.execsitecustomize.
|
|
1051
1216
|
|
|
@@ -1054,12 +1219,14 @@ def wrapsitecustomize(func):
|
|
|
1054
1219
|
"""
|
|
1055
1220
|
|
|
1056
1221
|
@functools.wraps(func)
|
|
1057
|
-
def wrapper():
|
|
1222
|
+
def wrapper() -> None:
|
|
1058
1223
|
func()
|
|
1059
1224
|
|
|
1060
|
-
|
|
1225
|
+
sitecustomize_module = None
|
|
1061
1226
|
try:
|
|
1062
|
-
import sitecustomize
|
|
1227
|
+
import sitecustomize as _sitecustomize
|
|
1228
|
+
|
|
1229
|
+
sitecustomize_module = _sitecustomize
|
|
1063
1230
|
except ImportError as exc:
|
|
1064
1231
|
if exc.name != "sitecustomize":
|
|
1065
1232
|
raise
|
|
@@ -1068,7 +1235,10 @@ def wrapsitecustomize(func):
|
|
|
1068
1235
|
# relenv environment. This can't be done when pip is using build_env to
|
|
1069
1236
|
# install packages. This code seems potentially brittle and there may
|
|
1070
1237
|
# be reasonable arguments against doing it at all.
|
|
1071
|
-
if
|
|
1238
|
+
if (
|
|
1239
|
+
sitecustomize_module is None
|
|
1240
|
+
or "pip-build-env" not in sitecustomize_module.__file__
|
|
1241
|
+
):
|
|
1072
1242
|
_orig = sys.path[:]
|
|
1073
1243
|
# Replace sys.path
|
|
1074
1244
|
sys.path[:] = common().sanitize_sys_path(sys.path)
|
|
@@ -1083,7 +1253,7 @@ def wrapsitecustomize(func):
|
|
|
1083
1253
|
return wrapper
|
|
1084
1254
|
|
|
1085
1255
|
|
|
1086
|
-
def bootstrap():
|
|
1256
|
+
def bootstrap() -> None:
|
|
1087
1257
|
"""
|
|
1088
1258
|
Bootstrap the relenv environment.
|
|
1089
1259
|
"""
|
|
@@ -1100,3 +1270,8 @@ def bootstrap():
|
|
|
1100
1270
|
setup_crossroot()
|
|
1101
1271
|
install_cargo_config()
|
|
1102
1272
|
sys.meta_path = [importer] + sys.meta_path
|
|
1273
|
+
|
|
1274
|
+
# For Python 3.13+, sysconfig became a package so the importer doesn't
|
|
1275
|
+
# intercept it. Manually wrap it here.
|
|
1276
|
+
if sys.version_info >= (3, 13):
|
|
1277
|
+
wrap_sysconfig("sysconfig")
|