relenv 0.22.2__tar.gz → 0.22.3__tar.gz
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-0.22.2/relenv.egg-info → relenv-0.22.3}/PKG-INFO +1 -1
- relenv-0.22.3/relenv/_resources/xz/crc32_table.c +22 -0
- relenv-0.22.3/relenv/_resources/xz/crc64_table.c +33 -0
- relenv-0.22.3/relenv/_resources/xz/readme.md +13 -0
- {relenv-0.22.2 → relenv-0.22.3}/relenv/build/windows.py +8 -0
- {relenv-0.22.2 → relenv-0.22.3}/relenv/common.py +1 -1
- {relenv-0.22.2 → relenv-0.22.3}/relenv/python-versions.json +43 -0
- {relenv-0.22.2 → relenv-0.22.3}/relenv/relocate.py +85 -3
- {relenv-0.22.2 → relenv-0.22.3}/relenv/runtime.py +28 -19
- {relenv-0.22.2 → relenv-0.22.3/relenv.egg-info}/PKG-INFO +1 -1
- {relenv-0.22.2 → relenv-0.22.3}/relenv.egg-info/SOURCES.txt +3 -0
- {relenv-0.22.2 → relenv-0.22.3}/tests/test_build.py +2 -6
- relenv-0.22.3/tests/test_relocate_tools.py +152 -0
- {relenv-0.22.2 → relenv-0.22.3}/tests/test_runtime.py +72 -0
- {relenv-0.22.2 → relenv-0.22.3}/tests/test_verify_build.py +3 -0
- relenv-0.22.2/relenv/_resources/xz/readme.md +0 -4
- {relenv-0.22.2 → relenv-0.22.3}/LICENSE.md +0 -0
- {relenv-0.22.2 → relenv-0.22.3}/MANIFEST.in +0 -0
- {relenv-0.22.2 → relenv-0.22.3}/NOTICE +0 -0
- {relenv-0.22.2 → relenv-0.22.3}/README.md +0 -0
- {relenv-0.22.2 → relenv-0.22.3}/pyproject.toml +0 -0
- {relenv-0.22.2 → relenv-0.22.3}/relenv/__init__.py +0 -0
- {relenv-0.22.2 → relenv-0.22.3}/relenv/__main__.py +0 -0
- {relenv-0.22.2 → relenv-0.22.3}/relenv/_resources/xz/config.h +0 -0
- {relenv-0.22.2 → relenv-0.22.3}/relenv/_scripts/install_vc_build.ps1 +0 -0
- {relenv-0.22.2 → relenv-0.22.3}/relenv/build/__init__.py +0 -0
- {relenv-0.22.2 → relenv-0.22.3}/relenv/build/common/__init__.py +0 -0
- {relenv-0.22.2 → relenv-0.22.3}/relenv/build/common/_sysconfigdata_template.py +0 -0
- {relenv-0.22.2 → relenv-0.22.3}/relenv/build/common/builder.py +0 -0
- {relenv-0.22.2 → relenv-0.22.3}/relenv/build/common/builders.py +0 -0
- {relenv-0.22.2 → relenv-0.22.3}/relenv/build/common/download.py +0 -0
- {relenv-0.22.2 → relenv-0.22.3}/relenv/build/common/install.py +0 -0
- {relenv-0.22.2 → relenv-0.22.3}/relenv/build/common/ui.py +0 -0
- {relenv-0.22.2 → relenv-0.22.3}/relenv/build/darwin.py +0 -0
- {relenv-0.22.2 → relenv-0.22.3}/relenv/build/linux.py +0 -0
- {relenv-0.22.2 → relenv-0.22.3}/relenv/buildenv.py +0 -0
- {relenv-0.22.2 → relenv-0.22.3}/relenv/check.py +0 -0
- {relenv-0.22.2 → relenv-0.22.3}/relenv/create.py +0 -0
- {relenv-0.22.2 → relenv-0.22.3}/relenv/fetch.py +0 -0
- {relenv-0.22.2 → relenv-0.22.3}/relenv/manifest.py +0 -0
- {relenv-0.22.2 → relenv-0.22.3}/relenv/pyversions.py +0 -0
- {relenv-0.22.2 → relenv-0.22.3}/relenv/toolchain.py +0 -0
- {relenv-0.22.2 → relenv-0.22.3}/relenv.egg-info/dependency_links.txt +0 -0
- {relenv-0.22.2 → relenv-0.22.3}/relenv.egg-info/entry_points.txt +0 -0
- {relenv-0.22.2 → relenv-0.22.3}/relenv.egg-info/requires.txt +0 -0
- {relenv-0.22.2 → relenv-0.22.3}/relenv.egg-info/top_level.txt +0 -0
- {relenv-0.22.2 → relenv-0.22.3}/setup.cfg +0 -0
- {relenv-0.22.2 → relenv-0.22.3}/setup.py +0 -0
- {relenv-0.22.2 → relenv-0.22.3}/tests/__init__.py +0 -0
- {relenv-0.22.2 → relenv-0.22.3}/tests/_pytest_typing.py +0 -0
- {relenv-0.22.2 → relenv-0.22.3}/tests/conftest.py +0 -0
- {relenv-0.22.2 → relenv-0.22.3}/tests/test_common.py +0 -0
- {relenv-0.22.2 → relenv-0.22.3}/tests/test_create.py +0 -0
- {relenv-0.22.2 → relenv-0.22.3}/tests/test_downloads.py +0 -0
- {relenv-0.22.2 → relenv-0.22.3}/tests/test_fips_photon.py +0 -0
- {relenv-0.22.2 → relenv-0.22.3}/tests/test_module_imports.py +0 -0
- {relenv-0.22.2 → relenv-0.22.3}/tests/test_pyversions_runtime.py +0 -0
- {relenv-0.22.2 → relenv-0.22.3}/tests/test_relocate.py +0 -0
- {relenv-0.22.2 → relenv-0.22.3}/tests/test_relocate_module.py +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: relenv
|
|
3
|
-
Version: 0.22.
|
|
3
|
+
Version: 0.22.3
|
|
4
4
|
Project-URL: Source Code, https://github.com/saltstack/relative-environment-for-python
|
|
5
5
|
Project-URL: Documentation, https://relenv.readthedocs.io/en/latest/
|
|
6
6
|
Project-URL: Changelog, https://relenv.readthedocs.io/en/latest/changelog.html
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
///////////////////////////////////////////////////////////////////////////////
|
|
2
|
+
//
|
|
3
|
+
/// \file crc32_table.c
|
|
4
|
+
/// \brief Precalculated CRC32 table with correct endianness
|
|
5
|
+
//
|
|
6
|
+
// Author: Lasse Collin
|
|
7
|
+
//
|
|
8
|
+
// This file has been put into the public domain.
|
|
9
|
+
// You can do whatever you want with this file.
|
|
10
|
+
//
|
|
11
|
+
///////////////////////////////////////////////////////////////////////////////
|
|
12
|
+
|
|
13
|
+
#include "common.h"
|
|
14
|
+
|
|
15
|
+
// Having the declaration here silences clang -Wmissing-variable-declarations.
|
|
16
|
+
extern const uint32_t lzma_crc32_table[8][256];
|
|
17
|
+
|
|
18
|
+
#ifdef WORDS_BIGENDIAN
|
|
19
|
+
# include "crc32_table_be.h"
|
|
20
|
+
#else
|
|
21
|
+
# include "crc32_table_le.h"
|
|
22
|
+
#endif
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
///////////////////////////////////////////////////////////////////////////////
|
|
2
|
+
//
|
|
3
|
+
/// \file crc64_table.c
|
|
4
|
+
/// \brief Precalculated CRC64 table with correct endianness
|
|
5
|
+
//
|
|
6
|
+
// Author: Lasse Collin
|
|
7
|
+
//
|
|
8
|
+
// This file has been put into the public domain.
|
|
9
|
+
// You can do whatever you want with this file.
|
|
10
|
+
//
|
|
11
|
+
///////////////////////////////////////////////////////////////////////////////
|
|
12
|
+
|
|
13
|
+
#include "common.h"
|
|
14
|
+
|
|
15
|
+
|
|
16
|
+
// FIXME: Compared to crc64_fast.c this has to check for __x86_64__ too
|
|
17
|
+
// so that in 32-bit builds crc64_x86.S won't break due to a missing table.
|
|
18
|
+
#if (defined(__x86_64__) && defined(__SSSE3__) \
|
|
19
|
+
&& defined(__SSE4_1__) && defined(__PCLMUL__)) \
|
|
20
|
+
|| (defined(__e2k__) && __iset__ >= 6)
|
|
21
|
+
// No table needed. Use a typedef to avoid an empty translation unit.
|
|
22
|
+
typedef void lzma_crc64_dummy;
|
|
23
|
+
|
|
24
|
+
#else
|
|
25
|
+
// Having the declaration here silences clang -Wmissing-variable-declarations.
|
|
26
|
+
extern const uint64_t lzma_crc64_table[4][256];
|
|
27
|
+
|
|
28
|
+
# if defined(WORDS_BIGENDIAN)
|
|
29
|
+
# include "crc64_table_be.h"
|
|
30
|
+
# else
|
|
31
|
+
# include "crc64_table_le.h"
|
|
32
|
+
# endif
|
|
33
|
+
#endif
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
The config.h file was removed from XZ-Utils starting with version 5.5.0.
|
|
2
|
+
XZ-Utils switched to CMake and removed Visual Studio project files and
|
|
3
|
+
pre-generated headers/sources.
|
|
4
|
+
|
|
5
|
+
We include the following files from XZ 5.4.7 to maintain compatibility with
|
|
6
|
+
Python's MSBuild-based build system on Windows (PCbuild/liblzma.vcxproj):
|
|
7
|
+
|
|
8
|
+
- config.h (src/common/config.h)
|
|
9
|
+
- crc32_table.c (src/liblzma/check/crc32_table.c)
|
|
10
|
+
- crc64_table.c (src/liblzma/check/crc64_table.c)
|
|
11
|
+
|
|
12
|
+
These files are copied into the extracted XZ source directory during the
|
|
13
|
+
Windows build process if they are missing.
|
|
@@ -197,6 +197,14 @@ def update_xz(dirs: Dirs, env: EnvMapping) -> None:
|
|
|
197
197
|
config_file_source = dirs.root / "_resources" / "xz" / "config.h"
|
|
198
198
|
if not config_file.exists():
|
|
199
199
|
shutil.copy(str(config_file_source), str(config_file))
|
|
200
|
+
|
|
201
|
+
# Also copy crc32_table.c and crc64_table.c which are missing in newer XZ tarballs
|
|
202
|
+
check_dir = target_dir / "src" / "liblzma" / "check"
|
|
203
|
+
for filename in ["crc32_table.c", "crc64_table.c"]:
|
|
204
|
+
target_file = check_dir / filename
|
|
205
|
+
source_file = dirs.root / "_resources" / "xz" / filename
|
|
206
|
+
if not target_file.exists():
|
|
207
|
+
shutil.copy(str(source_file), str(target_file))
|
|
200
208
|
# Update externals.spdx.json with the correct version, url, and hash
|
|
201
209
|
# This became a thing in 3.12
|
|
202
210
|
if env["RELENV_PY_MAJOR_VERSION"] in ["3.12", "3.13", "3.14"]:
|
|
@@ -203,6 +203,14 @@
|
|
|
203
203
|
"linux",
|
|
204
204
|
"darwin"
|
|
205
205
|
]
|
|
206
|
+
},
|
|
207
|
+
"3.6.1": {
|
|
208
|
+
"url": "https://github.com/openssl/openssl/releases/download/openssl-{version}/openssl-{version}.tar.gz",
|
|
209
|
+
"sha256": "b1bfedcd5b289ff22aee87c9d600f515767ebf45f77168cb6d64f231f518a82e",
|
|
210
|
+
"platforms": [
|
|
211
|
+
"linux",
|
|
212
|
+
"darwin"
|
|
213
|
+
]
|
|
206
214
|
}
|
|
207
215
|
},
|
|
208
216
|
"sqlite": {
|
|
@@ -225,6 +233,16 @@
|
|
|
225
233
|
"darwin",
|
|
226
234
|
"win32"
|
|
227
235
|
]
|
|
236
|
+
},
|
|
237
|
+
"3.51.2.0": {
|
|
238
|
+
"url": "https://sqlite.org/2026/sqlite-autoconf-{version}.tar.gz",
|
|
239
|
+
"sha256": "fbd89f866b1403bb66a143065440089dd76100f2238314d92274a082d4f2b7bb",
|
|
240
|
+
"sqliteversion": "3510200",
|
|
241
|
+
"platforms": [
|
|
242
|
+
"linux",
|
|
243
|
+
"darwin",
|
|
244
|
+
"win32"
|
|
245
|
+
]
|
|
228
246
|
}
|
|
229
247
|
},
|
|
230
248
|
"xz": {
|
|
@@ -235,6 +253,15 @@
|
|
|
235
253
|
"linux",
|
|
236
254
|
"darwin"
|
|
237
255
|
]
|
|
256
|
+
},
|
|
257
|
+
"5.8.2": {
|
|
258
|
+
"url": "http://tukaani.org/xz/xz-{version}.tar.gz",
|
|
259
|
+
"sha256": "ce09c50a5962786b83e5da389c90dd2c15ecd0980a258dd01f70f9e7ce58a8f1",
|
|
260
|
+
"platforms": [
|
|
261
|
+
"linux",
|
|
262
|
+
"darwin",
|
|
263
|
+
"win32"
|
|
264
|
+
]
|
|
238
265
|
}
|
|
239
266
|
},
|
|
240
267
|
"libffi": {
|
|
@@ -262,6 +289,13 @@
|
|
|
262
289
|
"platforms": [
|
|
263
290
|
"linux"
|
|
264
291
|
]
|
|
292
|
+
},
|
|
293
|
+
"6.6": {
|
|
294
|
+
"url": "https://mirrors.ocf.berkeley.edu/gnu/ncurses/ncurses-{version}.tar.gz",
|
|
295
|
+
"sha256": "355b4cbbed880b0381a04c46617b7656e362585d52e9cf84a67e2009b749ff11",
|
|
296
|
+
"platforms": [
|
|
297
|
+
"linux"
|
|
298
|
+
]
|
|
265
299
|
}
|
|
266
300
|
},
|
|
267
301
|
"readline": {
|
|
@@ -344,6 +378,15 @@
|
|
|
344
378
|
"darwin",
|
|
345
379
|
"win32"
|
|
346
380
|
]
|
|
381
|
+
},
|
|
382
|
+
"2.7.4": {
|
|
383
|
+
"url": "https://github.com/libexpat/libexpat/releases/download/R_2_7_4/expat-{version}.tar.xz",
|
|
384
|
+
"sha256": "9e9cabb457c1e09de91db2706d8365645792638eb3be1f94dbb2149301086ac0",
|
|
385
|
+
"platforms": [
|
|
386
|
+
"linux",
|
|
387
|
+
"darwin",
|
|
388
|
+
"win32"
|
|
389
|
+
]
|
|
347
390
|
}
|
|
348
391
|
}
|
|
349
392
|
}
|
|
@@ -11,6 +11,7 @@ import os as _os
|
|
|
11
11
|
import pathlib
|
|
12
12
|
import shutil as _shutil
|
|
13
13
|
import subprocess as _subprocess
|
|
14
|
+
import sys as _sys
|
|
14
15
|
from typing import Optional
|
|
15
16
|
|
|
16
17
|
log = logging.getLogger(__name__)
|
|
@@ -18,6 +19,7 @@ log = logging.getLogger(__name__)
|
|
|
18
19
|
os = _os
|
|
19
20
|
shutil = _shutil
|
|
20
21
|
subprocess = _subprocess
|
|
22
|
+
sys = _sys
|
|
21
23
|
|
|
22
24
|
__all__ = [
|
|
23
25
|
"is_macho",
|
|
@@ -70,6 +72,83 @@ LC_ID_DYLIB = "LC_ID_DYLIB"
|
|
|
70
72
|
LC_LOAD_DYLIB = "LC_LOAD_DYLIB"
|
|
71
73
|
LC_RPATH = "LC_RPATH"
|
|
72
74
|
|
|
75
|
+
# Cache for readelf binary path
|
|
76
|
+
_READELF_BINARY: Optional[str] = None
|
|
77
|
+
|
|
78
|
+
# Cache for patchelf binary path
|
|
79
|
+
_PATCHELF_BINARY: Optional[str] = None
|
|
80
|
+
|
|
81
|
+
|
|
82
|
+
def _get_readelf_binary() -> str:
|
|
83
|
+
"""
|
|
84
|
+
Get the path to readelf binary, preferring toolchain version.
|
|
85
|
+
|
|
86
|
+
Returns the cached value if already computed. On Linux, prefers the
|
|
87
|
+
toolchain's readelf over the system version. Falls back to "readelf"
|
|
88
|
+
from PATH if toolchain is unavailable.
|
|
89
|
+
|
|
90
|
+
:return: Path to readelf binary
|
|
91
|
+
:rtype: str
|
|
92
|
+
"""
|
|
93
|
+
global _READELF_BINARY
|
|
94
|
+
if _READELF_BINARY is not None:
|
|
95
|
+
return _READELF_BINARY
|
|
96
|
+
|
|
97
|
+
# Only Linux has the toolchain with readelf
|
|
98
|
+
if sys.platform == "linux":
|
|
99
|
+
try:
|
|
100
|
+
from relenv.common import get_toolchain, get_triplet
|
|
101
|
+
|
|
102
|
+
toolchain = get_toolchain()
|
|
103
|
+
if toolchain:
|
|
104
|
+
triplet = get_triplet()
|
|
105
|
+
toolchain_readelf = toolchain / "bin" / f"{triplet}-readelf"
|
|
106
|
+
if toolchain_readelf.exists():
|
|
107
|
+
_READELF_BINARY = str(toolchain_readelf)
|
|
108
|
+
return _READELF_BINARY
|
|
109
|
+
except Exception:
|
|
110
|
+
# Fall through to system readelf
|
|
111
|
+
pass
|
|
112
|
+
|
|
113
|
+
# Fall back to system readelf
|
|
114
|
+
_READELF_BINARY = "readelf"
|
|
115
|
+
return _READELF_BINARY
|
|
116
|
+
|
|
117
|
+
|
|
118
|
+
def _get_patchelf_binary() -> str:
|
|
119
|
+
"""
|
|
120
|
+
Get the path to patchelf binary, preferring toolchain version.
|
|
121
|
+
|
|
122
|
+
Returns the cached value if already computed. On Linux, prefers the
|
|
123
|
+
toolchain's patchelf over the system version. Falls back to "patchelf"
|
|
124
|
+
from PATH if toolchain is unavailable.
|
|
125
|
+
|
|
126
|
+
:return: Path to patchelf binary
|
|
127
|
+
:rtype: str
|
|
128
|
+
"""
|
|
129
|
+
global _PATCHELF_BINARY
|
|
130
|
+
if _PATCHELF_BINARY is not None:
|
|
131
|
+
return _PATCHELF_BINARY
|
|
132
|
+
|
|
133
|
+
# Only Linux has the toolchain with patchelf
|
|
134
|
+
if sys.platform == "linux":
|
|
135
|
+
try:
|
|
136
|
+
from relenv.common import get_toolchain
|
|
137
|
+
|
|
138
|
+
toolchain = get_toolchain()
|
|
139
|
+
if toolchain:
|
|
140
|
+
toolchain_patchelf = toolchain / "bin" / "patchelf"
|
|
141
|
+
if toolchain_patchelf.exists():
|
|
142
|
+
_PATCHELF_BINARY = str(toolchain_patchelf)
|
|
143
|
+
return _PATCHELF_BINARY
|
|
144
|
+
except Exception:
|
|
145
|
+
# Fall through to system patchelf
|
|
146
|
+
pass
|
|
147
|
+
|
|
148
|
+
# Fall back to system patchelf
|
|
149
|
+
_PATCHELF_BINARY = "patchelf"
|
|
150
|
+
return _PATCHELF_BINARY
|
|
151
|
+
|
|
73
152
|
|
|
74
153
|
def is_macho(path: str | os.PathLike[str]) -> bool:
|
|
75
154
|
"""
|
|
@@ -192,8 +271,9 @@ def parse_rpath(path: str | os.PathLike[str]) -> list[str]:
|
|
|
192
271
|
:return: The RPATH's found.
|
|
193
272
|
:rtype: list
|
|
194
273
|
"""
|
|
274
|
+
readelf = _get_readelf_binary()
|
|
195
275
|
proc = subprocess.run(
|
|
196
|
-
[
|
|
276
|
+
[readelf, "-d", path], stdout=subprocess.PIPE, stderr=subprocess.PIPE
|
|
197
277
|
)
|
|
198
278
|
return parse_readelf_d(proc.stdout.decode())
|
|
199
279
|
|
|
@@ -280,8 +360,9 @@ def remove_rpath(path: str | os.PathLike[str]) -> bool:
|
|
|
280
360
|
return True
|
|
281
361
|
|
|
282
362
|
log.info("Remove RPATH from %s (was: %s)", path, old_rpath)
|
|
363
|
+
patchelf = _get_patchelf_binary()
|
|
283
364
|
proc = subprocess.run(
|
|
284
|
-
[
|
|
365
|
+
[patchelf, "--remove-rpath", path],
|
|
285
366
|
stderr=subprocess.PIPE,
|
|
286
367
|
stdout=subprocess.PIPE,
|
|
287
368
|
)
|
|
@@ -319,8 +400,9 @@ def patch_rpath(
|
|
|
319
400
|
if new_rpath not in old_rpath:
|
|
320
401
|
patched_rpath = ":".join([new_rpath] + old_rpath)
|
|
321
402
|
log.info("Set RPATH=%s %s", patched_rpath, path)
|
|
403
|
+
patchelf = _get_patchelf_binary()
|
|
322
404
|
proc = subprocess.run(
|
|
323
|
-
[
|
|
405
|
+
[patchelf, "--force-rpath", "--set-rpath", patched_rpath, path],
|
|
324
406
|
stderr=subprocess.PIPE,
|
|
325
407
|
stdout=subprocess.PIPE,
|
|
326
408
|
)
|
|
@@ -384,25 +384,30 @@ def install_wheel_wrapper(func: Callable[..., Any]) -> Callable[..., Any]:
|
|
|
384
384
|
direct_url,
|
|
385
385
|
requested,
|
|
386
386
|
)
|
|
387
|
-
|
|
388
|
-
|
|
389
|
-
|
|
390
|
-
|
|
391
|
-
|
|
392
|
-
|
|
393
|
-
|
|
394
|
-
|
|
395
|
-
|
|
396
|
-
|
|
397
|
-
|
|
398
|
-
|
|
399
|
-
|
|
400
|
-
if otool_bin:
|
|
401
|
-
relocate().handle_macho(str(plat / file), str(rootdir), True)
|
|
402
|
-
else:
|
|
403
|
-
debug(
|
|
404
|
-
"The otool command is not available, please run `xcode-select --install`"
|
|
387
|
+
if "RELENV_BUILDENV" in os.environ:
|
|
388
|
+
plat = pathlib.Path(scheme.platlib)
|
|
389
|
+
rootdir = relenv_root()
|
|
390
|
+
with open(plat / info_dir / "RECORD") as fp:
|
|
391
|
+
for line in fp.readlines():
|
|
392
|
+
file = plat / line.split(",", 1)[0]
|
|
393
|
+
if not file.exists():
|
|
394
|
+
debug(f"Relenv - File not found {file}")
|
|
395
|
+
continue
|
|
396
|
+
if relocate().is_elf(file):
|
|
397
|
+
debug(f"Relenv - Found elf {file}")
|
|
398
|
+
relocate().handle_elf(
|
|
399
|
+
plat / file, rootdir / "lib", True, rootdir
|
|
405
400
|
)
|
|
401
|
+
elif relocate().is_macho(file):
|
|
402
|
+
otool_bin = shutil.which("otool")
|
|
403
|
+
if otool_bin:
|
|
404
|
+
relocate().handle_macho(
|
|
405
|
+
str(plat / file), str(rootdir), True
|
|
406
|
+
)
|
|
407
|
+
else:
|
|
408
|
+
debug(
|
|
409
|
+
"The otool command is not available, please run `xcode-select --install`"
|
|
410
|
+
)
|
|
406
411
|
|
|
407
412
|
return wrapper
|
|
408
413
|
|
|
@@ -1022,7 +1027,11 @@ def install_cargo_config() -> None:
|
|
|
1022
1027
|
cargo_home = dirs.data / "cargo"
|
|
1023
1028
|
triplet = common().get_triplet()
|
|
1024
1029
|
|
|
1025
|
-
|
|
1030
|
+
try:
|
|
1031
|
+
toolchain = common().get_toolchain()
|
|
1032
|
+
except PermissionError:
|
|
1033
|
+
pass
|
|
1034
|
+
|
|
1026
1035
|
if not toolchain:
|
|
1027
1036
|
debug("Unable to set CARGO_HOME ppbt package not installed")
|
|
1028
1037
|
return
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: relenv
|
|
3
|
-
Version: 0.22.
|
|
3
|
+
Version: 0.22.3
|
|
4
4
|
Project-URL: Source Code, https://github.com/saltstack/relative-environment-for-python
|
|
5
5
|
Project-URL: Documentation, https://relenv.readthedocs.io/en/latest/
|
|
6
6
|
Project-URL: Changelog, https://relenv.readthedocs.io/en/latest/changelog.html
|
|
@@ -25,6 +25,8 @@ relenv.egg-info/entry_points.txt
|
|
|
25
25
|
relenv.egg-info/requires.txt
|
|
26
26
|
relenv.egg-info/top_level.txt
|
|
27
27
|
relenv/_resources/xz/config.h
|
|
28
|
+
relenv/_resources/xz/crc32_table.c
|
|
29
|
+
relenv/_resources/xz/crc64_table.c
|
|
28
30
|
relenv/_resources/xz/readme.md
|
|
29
31
|
relenv/_scripts/install_vc_build.ps1
|
|
30
32
|
relenv/build/__init__.py
|
|
@@ -50,5 +52,6 @@ tests/test_module_imports.py
|
|
|
50
52
|
tests/test_pyversions_runtime.py
|
|
51
53
|
tests/test_relocate.py
|
|
52
54
|
tests/test_relocate_module.py
|
|
55
|
+
tests/test_relocate_tools.py
|
|
53
56
|
tests/test_runtime.py
|
|
54
57
|
tests/test_verify_build.py
|
|
@@ -154,8 +154,8 @@ def test_get_dependency_version_sqlite_all_platforms() -> None:
|
|
|
154
154
|
def test_get_dependency_version_xz_all_platforms() -> None:
|
|
155
155
|
"""Test getting XZ version for various platforms."""
|
|
156
156
|
# XZ 5.5.0+ removed MSBuild support, so Windows uses a fallback version
|
|
157
|
-
#
|
|
158
|
-
for platform in ["linux", "darwin"]:
|
|
157
|
+
# BUT we now have XZ 5.8.2 in python-versions.json for win32 too
|
|
158
|
+
for platform in ["linux", "darwin", "win32"]:
|
|
159
159
|
result = get_dependency_version("xz", platform)
|
|
160
160
|
assert result is not None, f"XZ should be available for {platform}"
|
|
161
161
|
assert isinstance(result, dict)
|
|
@@ -166,10 +166,6 @@ def test_get_dependency_version_xz_all_platforms() -> None:
|
|
|
166
166
|
assert "xz" in result["url"].lower()
|
|
167
167
|
assert isinstance(result["sha256"], str)
|
|
168
168
|
|
|
169
|
-
# Windows should return None (uses hardcoded fallback in windows.py)
|
|
170
|
-
result = get_dependency_version("xz", "win32")
|
|
171
|
-
assert result is None, "XZ should not be in JSON for win32 (uses fallback)"
|
|
172
|
-
|
|
173
169
|
|
|
174
170
|
def test_get_dependency_version_nonexistent() -> None:
|
|
175
171
|
"""Test that nonexistent dependency returns None."""
|
|
@@ -0,0 +1,152 @@
|
|
|
1
|
+
# Copyright 2022-2026 Broadcom.
|
|
2
|
+
# SPDX-License-Identifier: Apache-2.0
|
|
3
|
+
|
|
4
|
+
import pathlib
|
|
5
|
+
from typing import Iterator
|
|
6
|
+
from unittest.mock import patch
|
|
7
|
+
|
|
8
|
+
import pytest
|
|
9
|
+
|
|
10
|
+
from relenv import relocate
|
|
11
|
+
|
|
12
|
+
|
|
13
|
+
@pytest.fixture(autouse=True) # type: ignore[misc]
|
|
14
|
+
def reset_globals() -> Iterator[None]:
|
|
15
|
+
"""Reset global caches in relocate module before and after each test."""
|
|
16
|
+
relocate._READELF_BINARY = None
|
|
17
|
+
relocate._PATCHELF_BINARY = None
|
|
18
|
+
yield
|
|
19
|
+
relocate._READELF_BINARY = None
|
|
20
|
+
relocate._PATCHELF_BINARY = None
|
|
21
|
+
|
|
22
|
+
|
|
23
|
+
def test_get_readelf_binary_toolchain_exists(tmp_path: pathlib.Path) -> None:
|
|
24
|
+
"""Test that toolchain readelf is used when available."""
|
|
25
|
+
toolchain_root = tmp_path / "toolchain"
|
|
26
|
+
toolchain_root.mkdir()
|
|
27
|
+
triplet = "x86_64-linux-gnu"
|
|
28
|
+
|
|
29
|
+
# Create the fake toolchain binary
|
|
30
|
+
bin_dir = toolchain_root / "bin"
|
|
31
|
+
bin_dir.mkdir(parents=True)
|
|
32
|
+
toolchain_readelf = bin_dir / f"{triplet}-readelf"
|
|
33
|
+
toolchain_readelf.touch()
|
|
34
|
+
|
|
35
|
+
with patch("relenv.relocate.sys.platform", "linux"):
|
|
36
|
+
# We need to mock relenv.common.get_toolchain and get_triplet
|
|
37
|
+
# Since they are imported inside the function, we can patch the module if it's already imported
|
|
38
|
+
# or use patch.dict(sys.modules)
|
|
39
|
+
|
|
40
|
+
# Ensure relenv.common is imported so we can patch it
|
|
41
|
+
import relenv.common # noqa: F401
|
|
42
|
+
|
|
43
|
+
with patch("relenv.common.get_toolchain", return_value=toolchain_root):
|
|
44
|
+
with patch("relenv.common.get_triplet", return_value=triplet):
|
|
45
|
+
readelf = relocate._get_readelf_binary()
|
|
46
|
+
|
|
47
|
+
assert readelf == str(toolchain_readelf)
|
|
48
|
+
assert relocate._READELF_BINARY == str(toolchain_readelf)
|
|
49
|
+
|
|
50
|
+
|
|
51
|
+
def test_get_readelf_binary_toolchain_missing(tmp_path: pathlib.Path) -> None:
|
|
52
|
+
"""Test that system readelf is used when toolchain binary is missing."""
|
|
53
|
+
toolchain_root = tmp_path / "toolchain"
|
|
54
|
+
toolchain_root.mkdir()
|
|
55
|
+
triplet = "x86_64-linux-gnu"
|
|
56
|
+
|
|
57
|
+
# Do NOT create the binary
|
|
58
|
+
|
|
59
|
+
with patch("relenv.relocate.sys.platform", "linux"):
|
|
60
|
+
# Ensure relenv.common is imported so we can patch it
|
|
61
|
+
import relenv.common # noqa: F401
|
|
62
|
+
|
|
63
|
+
with patch("relenv.common.get_toolchain", return_value=toolchain_root):
|
|
64
|
+
with patch("relenv.common.get_triplet", return_value=triplet):
|
|
65
|
+
readelf = relocate._get_readelf_binary()
|
|
66
|
+
|
|
67
|
+
assert readelf == "readelf"
|
|
68
|
+
assert relocate._READELF_BINARY == "readelf"
|
|
69
|
+
|
|
70
|
+
|
|
71
|
+
def test_get_readelf_binary_no_toolchain() -> None:
|
|
72
|
+
"""Test that system readelf is used when get_toolchain returns None."""
|
|
73
|
+
with patch("relenv.relocate.sys.platform", "linux"):
|
|
74
|
+
# Ensure relenv.common is imported so we can patch it
|
|
75
|
+
import relenv.common # noqa: F401
|
|
76
|
+
|
|
77
|
+
with patch("relenv.common.get_toolchain", return_value=None):
|
|
78
|
+
readelf = relocate._get_readelf_binary()
|
|
79
|
+
|
|
80
|
+
assert readelf == "readelf"
|
|
81
|
+
assert relocate._READELF_BINARY == "readelf"
|
|
82
|
+
|
|
83
|
+
|
|
84
|
+
def test_get_readelf_binary_not_linux() -> None:
|
|
85
|
+
"""Test that system readelf is used on non-Linux platforms."""
|
|
86
|
+
with patch("relenv.relocate.sys.platform", "darwin"):
|
|
87
|
+
readelf = relocate._get_readelf_binary()
|
|
88
|
+
|
|
89
|
+
assert readelf == "readelf"
|
|
90
|
+
assert relocate._READELF_BINARY == "readelf"
|
|
91
|
+
|
|
92
|
+
|
|
93
|
+
def test_get_patchelf_binary_toolchain_exists(tmp_path: pathlib.Path) -> None:
|
|
94
|
+
"""Test that toolchain patchelf is used when available."""
|
|
95
|
+
toolchain_root = tmp_path / "toolchain"
|
|
96
|
+
toolchain_root.mkdir()
|
|
97
|
+
|
|
98
|
+
# Create the fake toolchain binary
|
|
99
|
+
bin_dir = toolchain_root / "bin"
|
|
100
|
+
bin_dir.mkdir(parents=True)
|
|
101
|
+
toolchain_patchelf = bin_dir / "patchelf"
|
|
102
|
+
toolchain_patchelf.touch()
|
|
103
|
+
|
|
104
|
+
with patch("relenv.relocate.sys.platform", "linux"):
|
|
105
|
+
# Ensure relenv.common is imported so we can patch it
|
|
106
|
+
import relenv.common # noqa: F401
|
|
107
|
+
|
|
108
|
+
with patch("relenv.common.get_toolchain", return_value=toolchain_root):
|
|
109
|
+
patchelf = relocate._get_patchelf_binary()
|
|
110
|
+
|
|
111
|
+
assert patchelf == str(toolchain_patchelf)
|
|
112
|
+
assert relocate._PATCHELF_BINARY == str(toolchain_patchelf)
|
|
113
|
+
|
|
114
|
+
|
|
115
|
+
def test_get_patchelf_binary_toolchain_missing(tmp_path: pathlib.Path) -> None:
|
|
116
|
+
"""Test that system patchelf is used when toolchain binary is missing."""
|
|
117
|
+
toolchain_root = tmp_path / "toolchain"
|
|
118
|
+
toolchain_root.mkdir()
|
|
119
|
+
|
|
120
|
+
# Do NOT create the binary
|
|
121
|
+
|
|
122
|
+
with patch("relenv.relocate.sys.platform", "linux"):
|
|
123
|
+
# Ensure relenv.common is imported so we can patch it
|
|
124
|
+
import relenv.common # noqa: F401
|
|
125
|
+
|
|
126
|
+
with patch("relenv.common.get_toolchain", return_value=toolchain_root):
|
|
127
|
+
patchelf = relocate._get_patchelf_binary()
|
|
128
|
+
|
|
129
|
+
assert patchelf == "patchelf"
|
|
130
|
+
assert relocate._PATCHELF_BINARY == "patchelf"
|
|
131
|
+
|
|
132
|
+
|
|
133
|
+
def test_get_patchelf_binary_no_toolchain() -> None:
|
|
134
|
+
"""Test that system patchelf is used when get_toolchain returns None."""
|
|
135
|
+
with patch("relenv.relocate.sys.platform", "linux"):
|
|
136
|
+
# Ensure relenv.common is imported so we can patch it
|
|
137
|
+
import relenv.common # noqa: F401
|
|
138
|
+
|
|
139
|
+
with patch("relenv.common.get_toolchain", return_value=None):
|
|
140
|
+
patchelf = relocate._get_patchelf_binary()
|
|
141
|
+
|
|
142
|
+
assert patchelf == "patchelf"
|
|
143
|
+
assert relocate._PATCHELF_BINARY == "patchelf"
|
|
144
|
+
|
|
145
|
+
|
|
146
|
+
def test_get_patchelf_binary_not_linux() -> None:
|
|
147
|
+
"""Test that system patchelf is used on non-Linux platforms."""
|
|
148
|
+
with patch("relenv.relocate.sys.platform", "darwin"):
|
|
149
|
+
patchelf = relocate._get_patchelf_binary()
|
|
150
|
+
|
|
151
|
+
assert patchelf == "patchelf"
|
|
152
|
+
assert relocate._PATCHELF_BINARY == "patchelf"
|
|
@@ -374,6 +374,7 @@ def test_finalize_options_wrapper_appends_include(
|
|
|
374
374
|
def test_install_wheel_wrapper_processes_record(
|
|
375
375
|
tmp_path: pathlib.Path, monkeypatch: pytest.MonkeyPatch
|
|
376
376
|
) -> None:
|
|
377
|
+
monkeypatch.setenv("RELENV_BUILDENV", "1")
|
|
377
378
|
plat_dir = tmp_path / "plat"
|
|
378
379
|
info_dir = plat_dir / "demo.dist-info"
|
|
379
380
|
info_dir.mkdir(parents=True)
|
|
@@ -440,6 +441,7 @@ def test_install_wheel_wrapper_processes_record(
|
|
|
440
441
|
def test_install_wheel_wrapper_missing_file(
|
|
441
442
|
tmp_path: pathlib.Path, monkeypatch: pytest.MonkeyPatch
|
|
442
443
|
) -> None:
|
|
444
|
+
monkeypatch.setenv("RELENV_BUILDENV", "1")
|
|
443
445
|
plat_dir = tmp_path / "plat"
|
|
444
446
|
info_dir = plat_dir / "demo.dist-info"
|
|
445
447
|
info_dir.mkdir(parents=True)
|
|
@@ -477,6 +479,7 @@ def test_install_wheel_wrapper_missing_file(
|
|
|
477
479
|
def test_install_wheel_wrapper_macho_with_otool(
|
|
478
480
|
tmp_path: pathlib.Path, monkeypatch: pytest.MonkeyPatch
|
|
479
481
|
) -> None:
|
|
482
|
+
monkeypatch.setenv("RELENV_BUILDENV", "1")
|
|
480
483
|
plat_dir = tmp_path / "plat"
|
|
481
484
|
info_dir = plat_dir / "demo.dist-info"
|
|
482
485
|
info_dir.mkdir(parents=True)
|
|
@@ -520,6 +523,7 @@ def test_install_wheel_wrapper_macho_with_otool(
|
|
|
520
523
|
def test_install_wheel_wrapper_macho_without_otool(
|
|
521
524
|
tmp_path: pathlib.Path, monkeypatch: pytest.MonkeyPatch
|
|
522
525
|
) -> None:
|
|
526
|
+
monkeypatch.setenv("RELENV_BUILDENV", "1")
|
|
523
527
|
plat_dir = tmp_path / "plat"
|
|
524
528
|
info_dir = plat_dir / "demo.dist-info"
|
|
525
529
|
info_dir.mkdir(parents=True)
|
|
@@ -565,6 +569,74 @@ def test_install_wheel_wrapper_macho_without_otool(
|
|
|
565
569
|
assert any("otool command is not available" in msg for msg in messages)
|
|
566
570
|
|
|
567
571
|
|
|
572
|
+
def test_install_wheel_wrapper_skips_without_buildenv(
|
|
573
|
+
tmp_path: pathlib.Path, monkeypatch: pytest.MonkeyPatch
|
|
574
|
+
) -> None:
|
|
575
|
+
monkeypatch.delenv("RELENV_BUILDENV", raising=False)
|
|
576
|
+
plat_dir = tmp_path / "plat"
|
|
577
|
+
info_dir = plat_dir / "demo.dist-info"
|
|
578
|
+
info_dir.mkdir(parents=True)
|
|
579
|
+
record = info_dir / "RECORD"
|
|
580
|
+
record.write_text("libdemo.so,,\n")
|
|
581
|
+
binary = plat_dir / "libdemo.so"
|
|
582
|
+
binary.touch()
|
|
583
|
+
|
|
584
|
+
# If relocation runs, this mock will raise an error or capture calls
|
|
585
|
+
handled: list[tuple[pathlib.Path, pathlib.Path]] = []
|
|
586
|
+
monkeypatch.setattr(
|
|
587
|
+
relenv.runtime,
|
|
588
|
+
"relocate",
|
|
589
|
+
lambda: SimpleNamespace(
|
|
590
|
+
is_elf=lambda path: path.name.endswith(".so"),
|
|
591
|
+
is_macho=lambda path: False,
|
|
592
|
+
handle_elf=lambda file, lib_dir, fix, root: handled.append((file, lib_dir)),
|
|
593
|
+
handle_macho=lambda *args, **kwargs: None,
|
|
594
|
+
),
|
|
595
|
+
)
|
|
596
|
+
|
|
597
|
+
wheel_utils = ModuleType("pip._internal.utils.wheel")
|
|
598
|
+
wheel_utils.parse_wheel = lambda _zf, _name: ("demo.dist-info", {})
|
|
599
|
+
monkeypatch.setitem(sys.modules, wheel_utils.__name__, wheel_utils)
|
|
600
|
+
|
|
601
|
+
class DummyZip:
|
|
602
|
+
def __init__(self, path: pathlib.Path) -> None:
|
|
603
|
+
self.path = path
|
|
604
|
+
|
|
605
|
+
def __enter__(self) -> DummyZip:
|
|
606
|
+
return self
|
|
607
|
+
|
|
608
|
+
def __exit__(self, *exc: object) -> bool:
|
|
609
|
+
return False
|
|
610
|
+
|
|
611
|
+
monkeypatch.setattr("zipfile.ZipFile", DummyZip)
|
|
612
|
+
|
|
613
|
+
install_module = ModuleType("pip._internal.operations.install.wheel")
|
|
614
|
+
|
|
615
|
+
def original_install(*_args: object, **_kwargs: object) -> str:
|
|
616
|
+
return "original"
|
|
617
|
+
|
|
618
|
+
install_module.install_wheel = original_install # type: ignore[attr-defined]
|
|
619
|
+
monkeypatch.setitem(sys.modules, install_module.__name__, install_module)
|
|
620
|
+
|
|
621
|
+
wrapped_module = relenv.runtime.wrap_pip_install_wheel(install_module.__name__)
|
|
622
|
+
|
|
623
|
+
scheme = SimpleNamespace(
|
|
624
|
+
platlib=str(plat_dir),
|
|
625
|
+
)
|
|
626
|
+
wrapped_module.install_wheel(
|
|
627
|
+
"demo",
|
|
628
|
+
tmp_path / "wheel.whl",
|
|
629
|
+
scheme,
|
|
630
|
+
"desc",
|
|
631
|
+
None,
|
|
632
|
+
None,
|
|
633
|
+
None,
|
|
634
|
+
None,
|
|
635
|
+
)
|
|
636
|
+
|
|
637
|
+
assert not handled
|
|
638
|
+
|
|
639
|
+
|
|
568
640
|
def test_install_legacy_wrapper_prefix(
|
|
569
641
|
monkeypatch: pytest.MonkeyPatch, tmp_path: pathlib.Path
|
|
570
642
|
) -> None:
|
|
@@ -519,6 +519,9 @@ def test_pip_install_pyzmq(
|
|
|
519
519
|
env["RELENV_BUILDENV"] = "yes"
|
|
520
520
|
env["USE_STATIC_REQUIREMENTS"] = "1"
|
|
521
521
|
|
|
522
|
+
if pyzmq_version == "26.2.0":
|
|
523
|
+
env["CMAKE_ARGS"] = "-DCMAKE_POLICY_VERSION_MINIMUM=3.5"
|
|
524
|
+
|
|
522
525
|
if sys.platform == "linux":
|
|
523
526
|
fake_bsd_root = tmp_path / "fake_libbsd"
|
|
524
527
|
(fake_bsd_root / "bsd").mkdir(parents=True, exist_ok=True)
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|