relenv 0.21.1__py3-none-any.whl → 0.21.2__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/build/common.py +98 -0
- relenv/build/linux.py +4 -4
- relenv/build/windows.py +301 -40
- relenv/common.py +16 -4
- relenv/runtime.py +33 -4
- {relenv-0.21.1.dist-info → relenv-0.21.2.dist-info}/METADATA +1 -1
- {relenv-0.21.1.dist-info → relenv-0.21.2.dist-info}/RECORD +13 -13
- tests/test_verify_build.py +23 -0
- {relenv-0.21.1.dist-info → relenv-0.21.2.dist-info}/WHEEL +0 -0
- {relenv-0.21.1.dist-info → relenv-0.21.2.dist-info}/entry_points.txt +0 -0
- {relenv-0.21.1.dist-info → relenv-0.21.2.dist-info}/licenses/LICENSE.md +0 -0
- {relenv-0.21.1.dist-info → relenv-0.21.2.dist-info}/licenses/NOTICE +0 -0
- {relenv-0.21.1.dist-info → relenv-0.21.2.dist-info}/top_level.txt +0 -0
relenv/build/common.py
CHANGED
|
@@ -38,6 +38,7 @@ from relenv.common import (
|
|
|
38
38
|
runcmd,
|
|
39
39
|
work_dirs,
|
|
40
40
|
fetch_url,
|
|
41
|
+
Version,
|
|
41
42
|
)
|
|
42
43
|
import relenv.relocate
|
|
43
44
|
|
|
@@ -358,6 +359,99 @@ def build_sqlite(env, dirs, logfp):
|
|
|
358
359
|
runcmd(["make", "install"], env=env, stderr=logfp, stdout=logfp)
|
|
359
360
|
|
|
360
361
|
|
|
362
|
+
def update_ensurepip(directory):
|
|
363
|
+
"""
|
|
364
|
+
Update bundled dependencies for ensurepip (pip & setuptools).
|
|
365
|
+
"""
|
|
366
|
+
# ensurepip bundle location
|
|
367
|
+
bundle_dir = directory / "ensurepip" / "_bundled"
|
|
368
|
+
|
|
369
|
+
# Make sure the destination directory exists
|
|
370
|
+
bundle_dir.mkdir(parents=True, exist_ok=True)
|
|
371
|
+
|
|
372
|
+
# Detect existing whl. Later versions of python don't include setuptools. We
|
|
373
|
+
# only want to update whl files that python expects to be there
|
|
374
|
+
pip_version = "25.2"
|
|
375
|
+
setuptools_version = "80.9.0"
|
|
376
|
+
update_pip = False
|
|
377
|
+
update_setuptools = False
|
|
378
|
+
for file in bundle_dir.glob("*.whl"):
|
|
379
|
+
|
|
380
|
+
log.debug("Checking whl: %s", str(file))
|
|
381
|
+
if file.name.startswith("pip-"):
|
|
382
|
+
found_version = file.name.split("-")[1]
|
|
383
|
+
log.debug("Found version %s", found_version)
|
|
384
|
+
if Version(found_version) >= Version(pip_version):
|
|
385
|
+
log.debug("Found correct pip version or newer: %s", found_version)
|
|
386
|
+
else:
|
|
387
|
+
file.unlink()
|
|
388
|
+
update_pip = True
|
|
389
|
+
if file.name.startswith("setuptools-"):
|
|
390
|
+
found_version = file.name.split("-")[1]
|
|
391
|
+
log.debug("Found version %s", found_version)
|
|
392
|
+
if Version(found_version) >= Version(setuptools_version):
|
|
393
|
+
log.debug(
|
|
394
|
+
"Found correct setuptools version or newer: %s", found_version
|
|
395
|
+
)
|
|
396
|
+
else:
|
|
397
|
+
file.unlink()
|
|
398
|
+
update_setuptools = True
|
|
399
|
+
|
|
400
|
+
# Download whl files and update __init__.py
|
|
401
|
+
init_file = directory / "ensurepip" / "__init__.py"
|
|
402
|
+
if update_pip:
|
|
403
|
+
whl = f"pip-{pip_version}-py3-none-any.whl"
|
|
404
|
+
whl_path = "b7/3f/945ef7ab14dc4f9d7f40288d2df998d1837ee0888ec3659c813487572faa"
|
|
405
|
+
url = f"https://files.pythonhosted.org/packages/{whl_path}/{whl}"
|
|
406
|
+
download_url(url=url, dest=bundle_dir)
|
|
407
|
+
assert (bundle_dir / whl).exists()
|
|
408
|
+
|
|
409
|
+
# Update __init__.py
|
|
410
|
+
old = "^_PIP_VERSION.*"
|
|
411
|
+
new = f'_PIP_VERSION = "{pip_version}"'
|
|
412
|
+
patch_file(path=init_file, old=old, new=new)
|
|
413
|
+
|
|
414
|
+
# setuptools
|
|
415
|
+
if update_setuptools:
|
|
416
|
+
whl = f"setuptools-{setuptools_version}-py3-none-any.whl"
|
|
417
|
+
whl_path = "a3/dc/17031897dae0efacfea57dfd3a82fdd2a2aeb58e0ff71b77b87e44edc772"
|
|
418
|
+
url = f"https://files.pythonhosted.org/packages/{whl_path}/{whl}"
|
|
419
|
+
download_url(url=url, dest=bundle_dir)
|
|
420
|
+
assert (bundle_dir / whl).exists()
|
|
421
|
+
|
|
422
|
+
# setuptools
|
|
423
|
+
old = "^_SETUPTOOLS_VERSION.*"
|
|
424
|
+
new = f'_SETUPTOOLS_VERSION = "{setuptools_version}"'
|
|
425
|
+
patch_file(path=init_file, old=old, new=new)
|
|
426
|
+
|
|
427
|
+
log.debug("ensurepip __init__.py contents:")
|
|
428
|
+
log.debug(init_file.read_text())
|
|
429
|
+
|
|
430
|
+
|
|
431
|
+
def patch_file(path, old, new):
|
|
432
|
+
"""
|
|
433
|
+
Search a file line by line for a string to replace.
|
|
434
|
+
|
|
435
|
+
:param path: Location of the file to search
|
|
436
|
+
:type path: str
|
|
437
|
+
:param old: The value that will be replaced
|
|
438
|
+
:type path: str
|
|
439
|
+
:param new: The value that will replace the 'old' value.
|
|
440
|
+
:type path: str
|
|
441
|
+
"""
|
|
442
|
+
log.debug("Patching file: %s", path)
|
|
443
|
+
import re
|
|
444
|
+
|
|
445
|
+
with open(path, "r") as fp:
|
|
446
|
+
content = fp.read()
|
|
447
|
+
new_content = ""
|
|
448
|
+
for line in content.splitlines():
|
|
449
|
+
line = re.sub(old, new, line)
|
|
450
|
+
new_content += line + "\n"
|
|
451
|
+
with open(path, "w") as fp:
|
|
452
|
+
fp.write(new_content)
|
|
453
|
+
|
|
454
|
+
|
|
361
455
|
def tarball_version(href):
|
|
362
456
|
if href.endswith("tar.gz"):
|
|
363
457
|
try:
|
|
@@ -1457,6 +1551,9 @@ def finalize(env, dirs, logfp):
|
|
|
1457
1551
|
|
|
1458
1552
|
pymodules = libdir / find_pythonlib(libdir)
|
|
1459
1553
|
|
|
1554
|
+
# update ensurepip
|
|
1555
|
+
update_ensurepip(pymodules)
|
|
1556
|
+
|
|
1460
1557
|
cwd = os.getcwd()
|
|
1461
1558
|
modname = find_sysconfigdata(pymodules)
|
|
1462
1559
|
path = sys.path
|
|
@@ -1474,6 +1571,7 @@ def finalize(env, dirs, logfp):
|
|
|
1474
1571
|
bindir = pathlib.Path(dirs.prefix) / "bin"
|
|
1475
1572
|
sitepackages = pymodules / "site-packages"
|
|
1476
1573
|
install_runtime(sitepackages)
|
|
1574
|
+
|
|
1477
1575
|
# Install pip
|
|
1478
1576
|
python = dirs.prefix / "bin" / "python3"
|
|
1479
1577
|
if env["RELENV_HOST_ARCH"] != env["RELENV_BUILD_ARCH"]:
|
relenv/build/linux.py
CHANGED
|
@@ -379,11 +379,11 @@ def build_python(env, dirs, logfp):
|
|
|
379
379
|
)
|
|
380
380
|
|
|
381
381
|
if pathlib.Path("setup.py").exists():
|
|
382
|
-
with tempfile.NamedTemporaryFile(mode="w", suffix="_patch") as
|
|
383
|
-
|
|
384
|
-
|
|
382
|
+
with tempfile.NamedTemporaryFile(mode="w", suffix="_patch") as p_file:
|
|
383
|
+
p_file.write(PATCH)
|
|
384
|
+
p_file.flush()
|
|
385
385
|
runcmd(
|
|
386
|
-
["patch", "-p0", "-i",
|
|
386
|
+
["patch", "-p0", "-i", p_file.name],
|
|
387
387
|
env=env,
|
|
388
388
|
stderr=logfp,
|
|
389
389
|
stdout=logfp,
|
relenv/build/windows.py
CHANGED
|
@@ -4,14 +4,26 @@
|
|
|
4
4
|
The windows build process.
|
|
5
5
|
"""
|
|
6
6
|
import glob
|
|
7
|
-
import
|
|
8
|
-
import
|
|
7
|
+
import json
|
|
8
|
+
import logging
|
|
9
9
|
import os
|
|
10
10
|
import pathlib
|
|
11
|
+
import shutil
|
|
12
|
+
import sys
|
|
11
13
|
import tarfile
|
|
12
|
-
|
|
13
|
-
from .common import
|
|
14
|
-
|
|
14
|
+
|
|
15
|
+
from .common import (
|
|
16
|
+
builds,
|
|
17
|
+
create_archive,
|
|
18
|
+
download_url,
|
|
19
|
+
extract_archive,
|
|
20
|
+
install_runtime,
|
|
21
|
+
MODULE_DIR,
|
|
22
|
+
patch_file,
|
|
23
|
+
runcmd,
|
|
24
|
+
update_ensurepip,
|
|
25
|
+
)
|
|
26
|
+
from ..common import arches, WIN32, Version
|
|
15
27
|
|
|
16
28
|
log = logging.getLogger(__name__)
|
|
17
29
|
|
|
@@ -36,44 +48,269 @@ def populate_env(env, dirs):
|
|
|
36
48
|
env["MSBUILDDISABLENODEREUSE"] = "1"
|
|
37
49
|
|
|
38
50
|
|
|
39
|
-
def
|
|
51
|
+
def update_props(source, old, new):
|
|
40
52
|
"""
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
:param path: Location of the file to search
|
|
44
|
-
:type path: str
|
|
45
|
-
:param old: The value that will be replaced
|
|
46
|
-
:type path: str
|
|
47
|
-
:param new: The value that will replace the 'old' value.
|
|
48
|
-
:type path: str
|
|
49
|
-
"""
|
|
50
|
-
import re
|
|
51
|
-
|
|
52
|
-
with open(path, "r") as fp:
|
|
53
|
-
content = fp.read()
|
|
54
|
-
new_content = ""
|
|
55
|
-
for line in content.splitlines():
|
|
56
|
-
re.sub(old, new, line)
|
|
57
|
-
new_content += line + os.linesep
|
|
58
|
-
with open(path, "w") as fp:
|
|
59
|
-
fp.write(new_content)
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
def override_dependency(source, old, new):
|
|
63
|
-
"""
|
|
64
|
-
Overwrite a dependency string for Windoes PCBuild.
|
|
53
|
+
Overwrite a dependency string for Windows PCBuild.
|
|
65
54
|
|
|
66
55
|
:param source: Python's source directory
|
|
67
|
-
:type
|
|
56
|
+
:type source: str
|
|
68
57
|
:param old: Regular expression to search for
|
|
69
|
-
:type
|
|
58
|
+
:type old: str
|
|
70
59
|
:param new: Replacement text
|
|
71
|
-
:type
|
|
60
|
+
:type new: str
|
|
72
61
|
"""
|
|
73
62
|
patch_file(source / "PCbuild" / "python.props", old, new)
|
|
74
63
|
patch_file(source / "PCbuild" / "get_externals.bat", old, new)
|
|
75
64
|
|
|
76
65
|
|
|
66
|
+
def get_externals_source(externals_dir, url):
|
|
67
|
+
"""
|
|
68
|
+
Download external source code dependency.
|
|
69
|
+
|
|
70
|
+
Download source code and extract to the "externals" directory in the root of
|
|
71
|
+
the python source. Only works with a tarball
|
|
72
|
+
"""
|
|
73
|
+
zips_dir = externals_dir / "zips"
|
|
74
|
+
zips_dir.mkdir(parents=True, exist_ok=True)
|
|
75
|
+
local_file = download_url(url=url, dest=str(zips_dir))
|
|
76
|
+
extract_archive(archive=str(local_file), to_dir=str(externals_dir))
|
|
77
|
+
try:
|
|
78
|
+
os.remove(local_file)
|
|
79
|
+
except OSError:
|
|
80
|
+
log.exception("Failed to remove temporary file")
|
|
81
|
+
|
|
82
|
+
|
|
83
|
+
def get_externals_bin(source_root, url):
|
|
84
|
+
"""
|
|
85
|
+
Download external binary dependency.
|
|
86
|
+
|
|
87
|
+
Download binaries to the "externals" directory in the root of the python
|
|
88
|
+
source.
|
|
89
|
+
"""
|
|
90
|
+
pass
|
|
91
|
+
|
|
92
|
+
|
|
93
|
+
def update_sqlite(dirs, env):
|
|
94
|
+
"""
|
|
95
|
+
Update the SQLITE library.
|
|
96
|
+
"""
|
|
97
|
+
version = "3.50.4.0"
|
|
98
|
+
url = "https://sqlite.org/2025/sqlite-autoconf-3500400.tar.gz"
|
|
99
|
+
sha256 = "a3db587a1b92ee5ddac2f66b3edb41b26f9c867275782d46c3a088977d6a5b18"
|
|
100
|
+
ref_loc = f"cpe:2.3:a:sqlite:sqlite:{version}:*:*:*:*:*:*:*"
|
|
101
|
+
target_dir = dirs.source / "externals" / f"sqlite-{version}"
|
|
102
|
+
target_dir.parent.mkdir(parents=True, exist_ok=True)
|
|
103
|
+
if not target_dir.exists():
|
|
104
|
+
update_props(dirs.source, r"sqlite-\d+.\d+.\d+.\d+", f"sqlite-{version}")
|
|
105
|
+
get_externals_source(externals_dir=dirs.source / "externals", url=url)
|
|
106
|
+
# # we need to fix the name of the extracted directory
|
|
107
|
+
extracted_dir = dirs.source / "externals" / "sqlite-autoconf-3500400"
|
|
108
|
+
shutil.move(str(extracted_dir), str(target_dir))
|
|
109
|
+
# Update externals.spdx.json with the correct version, url, and hash
|
|
110
|
+
# This became a thing in 3.12
|
|
111
|
+
if env["RELENV_PY_MAJOR_VERSION"] in ["3.12"]:
|
|
112
|
+
spdx_json = dirs.source / "Misc" / "externals.spdx.json"
|
|
113
|
+
with open(str(spdx_json), "r") as f:
|
|
114
|
+
data = json.load(f)
|
|
115
|
+
for pkg in data["packages"]:
|
|
116
|
+
if pkg["name"] == "sqlite":
|
|
117
|
+
pkg["versionInfo"] = version
|
|
118
|
+
pkg["downloadLocation"] = url
|
|
119
|
+
pkg["checksums"][0]["checksumValue"] = sha256
|
|
120
|
+
pkg["externalRefs"][0]["referenceLocator"] = ref_loc
|
|
121
|
+
with open(str(spdx_json), "w") as f:
|
|
122
|
+
json.dump(data, f, indent=2)
|
|
123
|
+
|
|
124
|
+
|
|
125
|
+
def update_xz(dirs, env):
|
|
126
|
+
"""
|
|
127
|
+
Update the XZ library.
|
|
128
|
+
"""
|
|
129
|
+
version = "5.6.2"
|
|
130
|
+
url = f"https://github.com/tukaani-project/xz/releases/download/v{version}/xz-{version}.tar.xz"
|
|
131
|
+
sha256 = "8bfd20c0e1d86f0402f2497cfa71c6ab62d4cd35fd704276e3140bfb71414519"
|
|
132
|
+
ref_loc = f"cpe:2.3:a:tukaani:xz:{version}:*:*:*:*:*:*:*"
|
|
133
|
+
target_dir = dirs.source / "externals" / f"xz-{version}"
|
|
134
|
+
target_dir.parent.mkdir(parents=True, exist_ok=True)
|
|
135
|
+
if not target_dir.exists():
|
|
136
|
+
update_props(dirs.source, r"xz-\d+.\d+.\d+", f"xz-{version}")
|
|
137
|
+
get_externals_source(externals_dir=dirs.source / "externals", url=url)
|
|
138
|
+
# Starting with version v5.5.0, XZ-Utils removed the ability to compile
|
|
139
|
+
# with MSBuild. We are bringing the config.h from the last version that
|
|
140
|
+
# had it, 5.4.7
|
|
141
|
+
config_file = target_dir / "src" / "common" / "config.h"
|
|
142
|
+
config_file_source = dirs.root / "_resources" / "xz" / "config.h"
|
|
143
|
+
if not config_file.exists():
|
|
144
|
+
shutil.copy(str(config_file_source), str(config_file))
|
|
145
|
+
# Update externals.spdx.json with the correct version, url, and hash
|
|
146
|
+
# This became a thing in 3.12
|
|
147
|
+
if env["RELENV_PY_MAJOR_VERSION"] in ["3.12", "3.13", "3.14"]:
|
|
148
|
+
spdx_json = dirs.source / "Misc" / "externals.spdx.json"
|
|
149
|
+
with open(str(spdx_json), "r") as f:
|
|
150
|
+
data = json.load(f)
|
|
151
|
+
for pkg in data["packages"]:
|
|
152
|
+
if pkg["name"] == "xz":
|
|
153
|
+
pkg["versionInfo"] = version
|
|
154
|
+
pkg["downloadLocation"] = url
|
|
155
|
+
pkg["checksums"][0]["checksumValue"] = sha256
|
|
156
|
+
pkg["externalRefs"][0]["referenceLocator"] = ref_loc
|
|
157
|
+
with open(str(spdx_json), "w") as f:
|
|
158
|
+
json.dump(data, f, indent=2)
|
|
159
|
+
|
|
160
|
+
|
|
161
|
+
def update_expat(dirs, env):
|
|
162
|
+
"""
|
|
163
|
+
Update the EXPAT library.
|
|
164
|
+
"""
|
|
165
|
+
# Patch <src>/Modules/expat/refresh.sh. When the SBOM is created, refresh.sh
|
|
166
|
+
# is scanned for the expat version, even though it doesn't run on Windows.
|
|
167
|
+
version = "2.7.3"
|
|
168
|
+
hash = "821ac9710d2c073eaf13e1b1895a9c9aa66c1157a99635c639fbff65cdbdd732"
|
|
169
|
+
url = f'https://github.com/libexpat/libexpat/releases/download/R_{version.replace(".", "_")}/expat-{version}.tar.xz'
|
|
170
|
+
bash_refresh = dirs.source / "Modules" / "expat" / "refresh.sh"
|
|
171
|
+
old = r'expected_libexpat_tag="R_\d+_\d+_\d"'
|
|
172
|
+
new = f'expected_libexpat_tag="R_{version.replace(".", "_")}"'
|
|
173
|
+
patch_file(bash_refresh, old=old, new=new)
|
|
174
|
+
old = r'expected_libexpat_version="\d+.\d+.\d"'
|
|
175
|
+
new = f'expected_libexpat_version="{version}"'
|
|
176
|
+
patch_file(bash_refresh, old=old, new=new)
|
|
177
|
+
old = 'expected_libexpat_sha256=".*"'
|
|
178
|
+
new = f'expected_libexpat_sha256="{hash}"'
|
|
179
|
+
patch_file(bash_refresh, old=old, new=new)
|
|
180
|
+
get_externals_source(externals_dir=dirs.source / "Modules" / "expat", url=url)
|
|
181
|
+
# Copy *.h and *.c to expat directory
|
|
182
|
+
expat_lib_dir = dirs.source / "Modules" / "expat" / f"expat-{version}" / "lib"
|
|
183
|
+
expat_dir = dirs.source / "Modules" / "expat"
|
|
184
|
+
for file in glob.glob(str(expat_lib_dir / "*.h")):
|
|
185
|
+
if expat_dir / os.path.basename(file):
|
|
186
|
+
(expat_dir / os.path.basename(file)).unlink()
|
|
187
|
+
shutil.move(file, str(expat_dir))
|
|
188
|
+
for file in glob.glob(str(expat_lib_dir / "*.c")):
|
|
189
|
+
if expat_dir / os.path.basename(file):
|
|
190
|
+
(expat_dir / os.path.basename(file)).unlink()
|
|
191
|
+
shutil.move(file, str(expat_dir))
|
|
192
|
+
# Update sbom.spdx.json with the correct hashes. This became a thing in 3.12
|
|
193
|
+
# python Tools/build/generate_sbom.py doesn't work because it requires a git
|
|
194
|
+
# repository, so we have to do it manually.
|
|
195
|
+
if env["RELENV_PY_MAJOR_VERSION"] in ["3.12", "3.13", "3.14"]:
|
|
196
|
+
checksums = {
|
|
197
|
+
"Modules/expat/expat.h": [
|
|
198
|
+
{
|
|
199
|
+
"algorithm": "SHA1",
|
|
200
|
+
"checksumValue": "a4395dd0589a97aab0904f7a5f5dc5781a086aa2",
|
|
201
|
+
},
|
|
202
|
+
{
|
|
203
|
+
"algorithm": "SHA256",
|
|
204
|
+
"checksumValue": "610b844bbfa3ec955772cc825db4d4db470827d57adcb214ad372d0eaf00e591",
|
|
205
|
+
},
|
|
206
|
+
],
|
|
207
|
+
"Modules/expat/expat_external.h": [
|
|
208
|
+
{
|
|
209
|
+
"algorithm": "SHA1",
|
|
210
|
+
"checksumValue": "8fdf2e79a7ab46a3c76c74ed7e5fe641cbef308d",
|
|
211
|
+
},
|
|
212
|
+
{
|
|
213
|
+
"algorithm": "SHA256",
|
|
214
|
+
"checksumValue": "ffb960af48b80935f3856a16e87023524b104f7fc1e58104f01db88ba7bfbcc9",
|
|
215
|
+
},
|
|
216
|
+
],
|
|
217
|
+
"Modules/expat/internal.h": [
|
|
218
|
+
{
|
|
219
|
+
"algorithm": "SHA1",
|
|
220
|
+
"checksumValue": "7dce7d98943c5db33ae05e54801dcafb4547b9dd",
|
|
221
|
+
},
|
|
222
|
+
{
|
|
223
|
+
"algorithm": "SHA256",
|
|
224
|
+
"checksumValue": "6bfe307d52e7e4c71dbc30d3bd902a4905cdd83bbe4226a7e8dfa8e4c462a157",
|
|
225
|
+
},
|
|
226
|
+
],
|
|
227
|
+
"Modules/expat/refresh.sh": [
|
|
228
|
+
{
|
|
229
|
+
"algorithm": "SHA1",
|
|
230
|
+
"checksumValue": "71812ca27328697a8dcae1949cd638717538321a",
|
|
231
|
+
},
|
|
232
|
+
{
|
|
233
|
+
"algorithm": "SHA256",
|
|
234
|
+
"checksumValue": "64fd1368de41e4ebc14593c65f5a676558aed44bd7d71c43ae05d06f9086d3b0",
|
|
235
|
+
},
|
|
236
|
+
],
|
|
237
|
+
"Modules/expat/xmlparse.c": [
|
|
238
|
+
{
|
|
239
|
+
"algorithm": "SHA1",
|
|
240
|
+
"checksumValue": "4c81a1f04fc653877c63c834145c18f93cd95f3e",
|
|
241
|
+
},
|
|
242
|
+
{
|
|
243
|
+
"algorithm": "SHA256",
|
|
244
|
+
"checksumValue": "04a379615f476d55f95ca1853107e20627b48ca4afe8d0fd5981ac77188bf0a6",
|
|
245
|
+
},
|
|
246
|
+
],
|
|
247
|
+
"Modules/expat/xmlrole.h": [
|
|
248
|
+
{
|
|
249
|
+
"algorithm": "SHA1",
|
|
250
|
+
"checksumValue": "ac2964cca107f62dd133bfd4736a9a17defbc401",
|
|
251
|
+
},
|
|
252
|
+
{
|
|
253
|
+
"algorithm": "SHA256",
|
|
254
|
+
"checksumValue": "92e41f373b67f6e0dcd7735faef3c3f1e2c17fe59e007e6b74beef6a2e70fa88",
|
|
255
|
+
},
|
|
256
|
+
],
|
|
257
|
+
"Modules/expat/xmltok.c": [
|
|
258
|
+
{
|
|
259
|
+
"algorithm": "SHA1",
|
|
260
|
+
"checksumValue": "1e2d35d90a1c269217f83d3bdf3c71cc22cb4c3f",
|
|
261
|
+
},
|
|
262
|
+
{
|
|
263
|
+
"algorithm": "SHA256",
|
|
264
|
+
"checksumValue": "98d0fc735041956cc2e7bbbe2fb8f03130859410e0aee5e8015f406a37c02a3c",
|
|
265
|
+
},
|
|
266
|
+
],
|
|
267
|
+
"Modules/expat/xmltok.h": [
|
|
268
|
+
{
|
|
269
|
+
"algorithm": "SHA1",
|
|
270
|
+
"checksumValue": "d126831eaa5158cff187a8c93f4bc1c8118f3b17",
|
|
271
|
+
},
|
|
272
|
+
{
|
|
273
|
+
"algorithm": "SHA256",
|
|
274
|
+
"checksumValue": "91bf003a725a675761ea8d92cebc299a76fd28c3a950572f41bc7ce5327ee7b5",
|
|
275
|
+
},
|
|
276
|
+
],
|
|
277
|
+
}
|
|
278
|
+
spdx_json = dirs.source / "Misc" / "sbom.spdx.json"
|
|
279
|
+
with open(str(spdx_json), "r") as f:
|
|
280
|
+
data = json.load(f)
|
|
281
|
+
for file in data["files"]:
|
|
282
|
+
if file["fileName"] in checksums.keys():
|
|
283
|
+
print(file["fileName"])
|
|
284
|
+
file["checksums"] = checksums[file["fileName"]]
|
|
285
|
+
with open(str(spdx_json), "w") as f:
|
|
286
|
+
json.dump(data, f, indent=2)
|
|
287
|
+
|
|
288
|
+
|
|
289
|
+
def update_expat_check(env):
|
|
290
|
+
"""
|
|
291
|
+
Check if the given python version should get an updated libexpat.
|
|
292
|
+
|
|
293
|
+
Patch libexpat on these versions and below:
|
|
294
|
+
- 3.9.23
|
|
295
|
+
- 3.10.18
|
|
296
|
+
- 3.11.13
|
|
297
|
+
- 3.12.11
|
|
298
|
+
- 3.13.7
|
|
299
|
+
"""
|
|
300
|
+
relenv_version = Version(env["RELENV_PY_VERSION"])
|
|
301
|
+
if relenv_version.minor == 9 and relenv_version.micro <= 23:
|
|
302
|
+
return True
|
|
303
|
+
elif relenv_version.minor == 10 and relenv_version.micro <= 18:
|
|
304
|
+
return True
|
|
305
|
+
elif relenv_version.minor == 11 and relenv_version.micro <= 13:
|
|
306
|
+
return True
|
|
307
|
+
elif relenv_version.minor == 12 and relenv_version.micro <= 11:
|
|
308
|
+
return True
|
|
309
|
+
elif relenv_version.minor == 13 and relenv_version.micro <= 7:
|
|
310
|
+
return True
|
|
311
|
+
return False
|
|
312
|
+
|
|
313
|
+
|
|
77
314
|
def build_python(env, dirs, logfp):
|
|
78
315
|
"""
|
|
79
316
|
Run the commands to build Python.
|
|
@@ -86,12 +323,32 @@ def build_python(env, dirs, logfp):
|
|
|
86
323
|
:type logfp: file
|
|
87
324
|
"""
|
|
88
325
|
# Override default versions
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
326
|
+
|
|
327
|
+
# Create externals directory
|
|
328
|
+
externals_dir = dirs.source / "externals"
|
|
329
|
+
externals_dir.mkdir(parents=True, exist_ok=True)
|
|
330
|
+
|
|
331
|
+
# SQLITE
|
|
332
|
+
# TODO: Python 3.12 started creating an SBOM. We're doing something wrong
|
|
333
|
+
# TODO: updating sqlite so SBOM creation is failing. Gating here until we
|
|
334
|
+
# TODO: fix this. Here's the original gate:
|
|
335
|
+
# if env["RELENV_PY_MAJOR_VERSION"] in ["3.10", "3.11", "3.12"]:
|
|
336
|
+
if env["RELENV_PY_MAJOR_VERSION"] in ["3.10", "3.11"]:
|
|
337
|
+
update_sqlite(dirs=dirs, env=env)
|
|
338
|
+
|
|
339
|
+
# XZ-Utils
|
|
340
|
+
# TODO: Python 3.12 started creating an SBOM. We're doing something wrong
|
|
341
|
+
# TODO: updating XZ so SBOM creation is failing. Gating here until we fix
|
|
342
|
+
# TODO: this. Here's the original gate:
|
|
343
|
+
# if env["RELENV_PY_MAJOR_VERSION"] in ["3.10", "3.11", "3.12", "3.13", "3.14"]:
|
|
344
|
+
if env["RELENV_PY_MAJOR_VERSION"] in ["3.10", "3.11"]:
|
|
345
|
+
update_xz(dirs=dirs, env=env)
|
|
346
|
+
|
|
347
|
+
# TODO: This was my attempt to fix the expat error during build... it failed
|
|
348
|
+
# TODO: so we're just skipping for now.
|
|
349
|
+
if env["RELENV_PY_MAJOR_VERSION"] in ["3.10", "3.11"]:
|
|
350
|
+
if update_expat_check(env=env):
|
|
351
|
+
update_expat(dirs=dirs, env=env)
|
|
95
352
|
|
|
96
353
|
arch_to_plat = {
|
|
97
354
|
"amd64": "x64",
|
|
@@ -106,6 +363,7 @@ def build_python(env, dirs, logfp):
|
|
|
106
363
|
plat,
|
|
107
364
|
"--no-tkinter",
|
|
108
365
|
]
|
|
366
|
+
|
|
109
367
|
log.info("Start PCbuild")
|
|
110
368
|
runcmd(cmd, env=env, stderr=logfp, stdout=logfp)
|
|
111
369
|
log.info("PCbuild finished")
|
|
@@ -202,9 +460,11 @@ def finalize(env, dirs, logfp):
|
|
|
202
460
|
"""
|
|
203
461
|
# Lay down site customize
|
|
204
462
|
sitepackages = dirs.prefix / "Lib" / "site-packages"
|
|
205
|
-
|
|
206
463
|
install_runtime(sitepackages)
|
|
207
464
|
|
|
465
|
+
# update ensurepip
|
|
466
|
+
update_ensurepip(dirs.prefix / "Lib")
|
|
467
|
+
|
|
208
468
|
# Install pip
|
|
209
469
|
python = dirs.prefix / "Scripts" / "python.exe"
|
|
210
470
|
runcmd([str(python), "-m", "ensurepip"], env=env, stderr=logfp, stdout=logfp)
|
|
@@ -243,6 +503,7 @@ def finalize(env, dirs, logfp):
|
|
|
243
503
|
"*.pyd",
|
|
244
504
|
"*.dll",
|
|
245
505
|
"*.lib",
|
|
506
|
+
"*.whl",
|
|
246
507
|
"/Include/*",
|
|
247
508
|
"/Lib/site-packages/*",
|
|
248
509
|
]
|
relenv/common.py
CHANGED
|
@@ -18,7 +18,7 @@ import threading
|
|
|
18
18
|
import time
|
|
19
19
|
|
|
20
20
|
# relenv package version
|
|
21
|
-
__version__ = "0.21.
|
|
21
|
+
__version__ = "0.21.2"
|
|
22
22
|
|
|
23
23
|
MODULE_DIR = pathlib.Path(__file__).resolve().parent
|
|
24
24
|
|
|
@@ -336,12 +336,19 @@ def extract_archive(to_dir, archive):
|
|
|
336
336
|
:type archive: str
|
|
337
337
|
"""
|
|
338
338
|
if archive.endswith("tgz"):
|
|
339
|
+
log.debug("Found tgz archive")
|
|
340
|
+
read_type = "r:gz"
|
|
341
|
+
elif archive.endswith("tar.gz"):
|
|
342
|
+
log.debug("Found tar.gz archive")
|
|
339
343
|
read_type = "r:gz"
|
|
340
344
|
elif archive.endswith("xz"):
|
|
345
|
+
log.debug("Found xz archive")
|
|
341
346
|
read_type = "r:xz"
|
|
342
347
|
elif archive.endswith("bz2"):
|
|
348
|
+
log.debug("Found bz2 archive")
|
|
343
349
|
read_type = "r:bz2"
|
|
344
350
|
else:
|
|
351
|
+
log.warning("Found unknown archive type: %s", archive)
|
|
345
352
|
read_type = "r"
|
|
346
353
|
with tarfile.open(archive, read_type) as t:
|
|
347
354
|
t.extractall(to_dir)
|
|
@@ -411,6 +418,7 @@ def fetch_url(url, fp, backoff=3, timeout=30):
|
|
|
411
418
|
n += 1
|
|
412
419
|
try:
|
|
413
420
|
fin = urllib.request.urlopen(url, timeout=timeout)
|
|
421
|
+
break
|
|
414
422
|
except (
|
|
415
423
|
urllib.error.HTTPError,
|
|
416
424
|
urllib.error.URLError,
|
|
@@ -420,6 +428,8 @@ def fetch_url(url, fp, backoff=3, timeout=30):
|
|
|
420
428
|
raise RelenvException(f"Error fetching url {url} {exc}")
|
|
421
429
|
log.debug("Unable to connect %s", url)
|
|
422
430
|
time.sleep(n * 10)
|
|
431
|
+
else:
|
|
432
|
+
raise RelenvException(f"Error fetching url: {url}")
|
|
423
433
|
log.info("url opened %s", url)
|
|
424
434
|
try:
|
|
425
435
|
total = 0
|
|
@@ -434,7 +444,6 @@ def fetch_url(url, fp, backoff=3, timeout=30):
|
|
|
434
444
|
block = fin.read(10240)
|
|
435
445
|
finally:
|
|
436
446
|
fin.close()
|
|
437
|
-
# fp.close()
|
|
438
447
|
log.info("Download complete %s", url)
|
|
439
448
|
|
|
440
449
|
|
|
@@ -514,18 +523,21 @@ def download_url(url, dest, verbose=True, backoff=3, timeout=60):
|
|
|
514
523
|
"""
|
|
515
524
|
local = get_download_location(url, dest)
|
|
516
525
|
if verbose:
|
|
517
|
-
|
|
526
|
+
log.debug(f"Downloading {url} -> {local}")
|
|
518
527
|
fout = open(local, "wb")
|
|
519
528
|
try:
|
|
520
529
|
fetch_url(url, fout, backoff, timeout)
|
|
521
530
|
except Exception as exc:
|
|
522
531
|
if verbose:
|
|
523
|
-
|
|
532
|
+
log.error("Unable to download: %s\n%s", url, exc)
|
|
524
533
|
try:
|
|
525
534
|
os.unlink(local)
|
|
526
535
|
except OSError:
|
|
527
536
|
pass
|
|
528
537
|
raise
|
|
538
|
+
finally:
|
|
539
|
+
fout.close()
|
|
540
|
+
log.debug(f"Finished downloading {url} -> {local}")
|
|
529
541
|
return local
|
|
530
542
|
|
|
531
543
|
|
relenv/runtime.py
CHANGED
|
@@ -750,12 +750,39 @@ def wrap_req_install(name):
|
|
|
750
750
|
mod = importlib.import_module(name)
|
|
751
751
|
|
|
752
752
|
def wrap(func):
|
|
753
|
-
if mod.InstallRequirement.install.__code__.co_argcount ==
|
|
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:
|
|
754
782
|
|
|
755
783
|
@functools.wraps(func)
|
|
756
784
|
def wrapper(
|
|
757
785
|
self,
|
|
758
|
-
install_options,
|
|
759
786
|
global_options=None,
|
|
760
787
|
root=None,
|
|
761
788
|
home=None,
|
|
@@ -770,7 +797,6 @@ def wrap_req_install(name):
|
|
|
770
797
|
home = TARGET.PATH
|
|
771
798
|
return func(
|
|
772
799
|
self,
|
|
773
|
-
install_options,
|
|
774
800
|
global_options,
|
|
775
801
|
root,
|
|
776
802
|
home,
|
|
@@ -783,10 +809,12 @@ def wrap_req_install(name):
|
|
|
783
809
|
TARGET.INSTALL = False
|
|
784
810
|
|
|
785
811
|
else:
|
|
812
|
+
# Oldest version of this method sigature with 9 arguments.
|
|
786
813
|
|
|
787
814
|
@functools.wraps(func)
|
|
788
815
|
def wrapper(
|
|
789
816
|
self,
|
|
817
|
+
install_options,
|
|
790
818
|
global_options=None,
|
|
791
819
|
root=None,
|
|
792
820
|
home=None,
|
|
@@ -801,6 +829,7 @@ def wrap_req_install(name):
|
|
|
801
829
|
home = TARGET.PATH
|
|
802
830
|
return func(
|
|
803
831
|
self,
|
|
832
|
+
install_options,
|
|
804
833
|
global_options,
|
|
805
834
|
root,
|
|
806
835
|
home,
|
|
@@ -845,8 +874,8 @@ def install_cargo_config():
|
|
|
845
874
|
# load the ssl module. Causing out setup_openssl method to fail to load
|
|
846
875
|
# fips module.
|
|
847
876
|
dirs = common().work_dirs()
|
|
848
|
-
triplet = common().get_triplet()
|
|
849
877
|
cargo_home = dirs.data / "cargo"
|
|
878
|
+
triplet = common().get_triplet()
|
|
850
879
|
|
|
851
880
|
toolchain = common().get_toolchain()
|
|
852
881
|
if not toolchain:
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: relenv
|
|
3
|
-
Version: 0.21.
|
|
3
|
+
Version: 0.21.2
|
|
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
|
|
@@ -2,22 +2,22 @@ relenv/__init__.py,sha256=NyZyghiBF5up_Uq6iJhmBr5HUKzfDtP-yZlU1OS6lQM,101
|
|
|
2
2
|
relenv/__main__.py,sha256=73VLBFMCXA8ccJiHYJ2KmctJRira-I_MnDKFIdv9JVI,1344
|
|
3
3
|
relenv/buildenv.py,sha256=TVpvA6qZ5zNca1YvEJwxpUps7gHtuETPxGIiA2zFAqI,3197
|
|
4
4
|
relenv/check.py,sha256=AIGxq_2ZBVVIBO8QiJZHknGILyjmxLgN00TTHlFjNsY,951
|
|
5
|
-
relenv/common.py,sha256=
|
|
5
|
+
relenv/common.py,sha256=cvj7D4u491AD8lGvkM3YHhuZuc-QvJ6TQzCIpiv84i0,23582
|
|
6
6
|
relenv/create.py,sha256=Uwoz7c07V0gZBRUM_gPPyENBdKlQqy32ABYiAM5A6XQ,3830
|
|
7
7
|
relenv/fetch.py,sha256=KsAJKXgsR3eSB32cd0zlWSU4UIjRJOwhXzoDVmTQo6k,2299
|
|
8
8
|
relenv/manifest.py,sha256=jm3hySI4tWnvfGspf9Q416mugZJc-rlwvLIoaxxlFQc,840
|
|
9
9
|
relenv/pyversions.py,sha256=636SwGSYzrK3yjWBW0iNR7TRws0Xm6puxLvlF1deX3o,10108
|
|
10
10
|
relenv/relocate.py,sha256=P5l4s5H4bR8cYm1PEtwp9yJyVfZ5km44jLe0LvL8CL0,11797
|
|
11
|
-
relenv/runtime.py,sha256=
|
|
11
|
+
relenv/runtime.py,sha256=iZgZt1q_ti8QxlEycdlkJibWHJ4Rz6m8x3UvRuWQdKY,33075
|
|
12
12
|
relenv/toolchain.py,sha256=EpwfR8Xno2hpGFZ1r0dkCdIp6vARfcGD8X6cntjy3Bs,782
|
|
13
13
|
relenv/_scripts/install_vc_build.ps1,sha256=ir1bcz7rNOuFw4E5_AqBidiKS0SpPViXW7zaanRPCoM,7629
|
|
14
14
|
relenv/build/__init__.py,sha256=2JrIYRvDtXsKBnhCEdWPyKLJkx59UPA9eYDSHbI7spw,6212
|
|
15
|
-
relenv/build/common.py,sha256=
|
|
15
|
+
relenv/build/common.py,sha256=5TJ-Tym51H8PaRYoiNxg39JAICoRMZJ9_AhcamFfDeM,52304
|
|
16
16
|
relenv/build/darwin.py,sha256=Z9OWPvIbkmSDmkngYPmapDqN3t8YtSFV3innWOtD8kw,3475
|
|
17
|
-
relenv/build/linux.py,sha256=
|
|
18
|
-
relenv/build/windows.py,sha256=
|
|
19
|
-
relenv-0.21.
|
|
20
|
-
relenv-0.21.
|
|
17
|
+
relenv/build/linux.py,sha256=X5POmdci-aFw2-rIUmkX13JLW_Cc035u6FU6UAOTLsQ,19505
|
|
18
|
+
relenv/build/windows.py,sha256=SmP0AdWtZM1JO695ojF28b4a8UGoJZydf5kPbLw1B3U,18009
|
|
19
|
+
relenv-0.21.2.dist-info/licenses/LICENSE.md,sha256=T0SRk3vJM1YcAJjDz9vsX9gsCRatAVSBS7LeU0tklRM,9919
|
|
20
|
+
relenv-0.21.2.dist-info/licenses/NOTICE,sha256=Ns0AybPHBsgJKJJfjE6YnGgWEQQ9F7lQ6QNlYLlQT3E,548
|
|
21
21
|
tests/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
22
22
|
tests/conftest.py,sha256=-_l6m7K-_IvPHtfyhN29chqk8wQKdB0DvdSCRXBh6TQ,2179
|
|
23
23
|
tests/test_build.py,sha256=i1gRIQzbkl-TDyXfJZzb3LFMSFWJkbOXFMv7laQpzoo,1331
|
|
@@ -27,9 +27,9 @@ tests/test_downloads.py,sha256=zdULspcHcepOVkEQKOMr0pw02t9GRiBCcIP72So0EYc,3302
|
|
|
27
27
|
tests/test_fips_photon.py,sha256=fx5EKzRgJ5HbVLZ49M1YN_x2FYSxHahzPwwMaTcVQsA,1325
|
|
28
28
|
tests/test_relocate.py,sha256=_3Eb22qhzWvMnLIgPCqO-t_WZ-hklSMfy8GBTrdjCf0,8854
|
|
29
29
|
tests/test_runtime.py,sha256=n_gTiQqAgO_Vqk6Xf_2Hi3gIkBn_lhDqoovOiQ5fxG8,626
|
|
30
|
-
tests/test_verify_build.py,sha256=
|
|
31
|
-
relenv-0.21.
|
|
32
|
-
relenv-0.21.
|
|
33
|
-
relenv-0.21.
|
|
34
|
-
relenv-0.21.
|
|
35
|
-
relenv-0.21.
|
|
30
|
+
tests/test_verify_build.py,sha256=Zj_2zbyR3hiZdPHk5WAtJ1T0JPFcdfY1gTp0pvcHVCc,52975
|
|
31
|
+
relenv-0.21.2.dist-info/METADATA,sha256=ecYtYrgVC7her99VC-GUAGYUnVtig9KtSmjjcs3gd3g,1360
|
|
32
|
+
relenv-0.21.2.dist-info/WHEEL,sha256=_zCd3N1l69ArxyTb8rzEoP9TpbYXkqRFSNOD5OuxnTs,91
|
|
33
|
+
relenv-0.21.2.dist-info/entry_points.txt,sha256=dO66nWPPWl8ALWWnZFlHKAo6mfPFuQid7purYWL2ddc,48
|
|
34
|
+
relenv-0.21.2.dist-info/top_level.txt,sha256=P4Ro6JLZE53ZdsQ76o2OzBcpb0MaVJmbfr0HAn9WF8M,13
|
|
35
|
+
relenv-0.21.2.dist-info/RECORD,,
|
tests/test_verify_build.py
CHANGED
|
@@ -1859,3 +1859,26 @@ def test_import_ssl_module(pyexec):
|
|
|
1859
1859
|
assert proc.returncode == 0
|
|
1860
1860
|
assert proc.stdout.decode() == ""
|
|
1861
1861
|
assert proc.stderr.decode() == ""
|
|
1862
|
+
|
|
1863
|
+
|
|
1864
|
+
@pytest.mark.skip_unless_on_linux
|
|
1865
|
+
@pytest.mark.parametrize("pip_version", ["25.2", "25.3"])
|
|
1866
|
+
def test_install_setuptools_25_2_to_25_3(pipexec, build, minor_version, pip_version):
|
|
1867
|
+
"""
|
|
1868
|
+
Validate we handle the changes to pip._internal.req.InstallRequirement.install signature.
|
|
1869
|
+
"""
|
|
1870
|
+
subprocess.run(
|
|
1871
|
+
[str(pipexec), "install", "--upgrade", f"pip=={pip_version}"],
|
|
1872
|
+
check=True,
|
|
1873
|
+
)
|
|
1874
|
+
subprocess.run(
|
|
1875
|
+
[
|
|
1876
|
+
str(pipexec),
|
|
1877
|
+
"install",
|
|
1878
|
+
"--upgrade",
|
|
1879
|
+
"--no-binary=:all:",
|
|
1880
|
+
"--no-cache-dir",
|
|
1881
|
+
"setuptools",
|
|
1882
|
+
],
|
|
1883
|
+
check=True,
|
|
1884
|
+
)
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|