Skip to content

Commit 126630f

Browse files
authored
Merge pull request #154 from robotpy/legacy-py
Add CI for some legacy python versions
2 parents ee0298e + ade5a58 commit 126630f

7 files changed

Lines changed: 109 additions & 58 deletions

File tree

.github/workflows/ci.yml

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -64,6 +64,9 @@ jobs:
6464
strategy:
6565
matrix:
6666
container:
67+
- ghcr.io/robotpy/crossenv-ci-images:py308-arm64-24.04-qemu
68+
- ghcr.io/robotpy/crossenv-ci-images:py309-arm64-24.04-qemu
69+
- ghcr.io/robotpy/crossenv-ci-images:py310-arm64-24.04-qemu
6770
- ghcr.io/robotpy/crossenv-ci-images:py311-arm64-24.04-qemu
6871
- ghcr.io/robotpy/crossenv-ci-images:py312-arm64-24.04-qemu
6972
- ghcr.io/robotpy/crossenv-ci-images:py313-arm64-24.04-qemu

crossenv/__init__.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -538,6 +538,7 @@ def ensure_directories(self, env_dir):
538538
utils.remove_path(os.path.join(env_dir, sub))
539539

540540
context = super().ensure_directories(env_dir)
541+
context.sys_executable = sys.executable
541542
context.lib_path = os.path.join(env_dir, "lib")
542543
context.exposed_libs = os.path.join(context.lib_path, "exposed.txt")
543544
utils.mkdir_if_needed(context.lib_path)
@@ -893,7 +894,6 @@ def make_cross_python(self, context):
893894
"subprocess-patch.py",
894895
"distutils-sysconfig-patch.py",
895896
"pip-_vendor-distlib-scripts-patch.py",
896-
"pkg_resources-patch.py",
897897
"packaging-tags-patch.py",
898898
]
899899

crossenv/scripts/cross-expose.py.tmpl

Lines changed: 102 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1,16 +1,89 @@
11
#!{{context.build_env_exe}}
22

33
import sys
4-
import os
54
import importlib
65
import argparse
76
import logging
8-
import pkg_resources
7+
import pathlib
8+
import re
9+
import subprocess
10+
import tempfile
11+
12+
13+
try:
14+
import importlib.metadata
15+
16+
def _get_package(name):
17+
try:
18+
dist = importlib.metadata.distribution(name)
19+
return dist.version
20+
except importlib.metadata.PackageNotFoundError:
21+
return None
22+
23+
except ImportError:
24+
import pkg_resources
25+
26+
def _get_package(name):
27+
try:
28+
dist = pkg_resources.get_distribution(name)
29+
return dist.version
30+
except pkg_resources.DistributionNotFound:
31+
return None
32+
933

1034
logger = logging.getLogger()
1135
EXPOSED_LIBS = {{repr(context.exposed_libs)}}
1236

1337

38+
def install_fake_wheel(name, version):
39+
# https://packaging.python.org/en/latest/specifications/name-normalization/#name-normalization
40+
name = re.sub(r"[-_.]+", "-", name).lower()
41+
wheel_dist = name.replace("-", "_")
42+
43+
with tempfile.TemporaryDirectory() as tname:
44+
tpath = pathlib.Path(tname)
45+
dist_info = tpath / f"{wheel_dist}-{version}.dist-info"
46+
dist_info.mkdir(parents=True, exist_ok=True)
47+
48+
with open(dist_info / "METADATA", "w") as fp:
49+
fp.write(
50+
"Metadata-Version: 2.1\n" f"Name: {name}\n" f"Version: {version}\n"
51+
)
52+
53+
with open(dist_info / "WHEEL", "w") as fp:
54+
fp.write(
55+
"Wheel-Version: 1.0\n"
56+
"Generator: crossenv\n"
57+
"Root-Is-Purelib: true\n"
58+
"Tag: py3-none-any\n"
59+
)
60+
61+
subprocess.check_call(
62+
[
63+
{{repr(context.sys_executable)}},
64+
"-m",
65+
"wheel",
66+
"pack",
67+
tname,
68+
"--dest-dir",
69+
tname,
70+
]
71+
)
72+
73+
whl = list(tpath.glob("*.whl"))[0]
74+
75+
subprocess.check_call(
76+
[
77+
{{repr(context.cross_env_exe)}},
78+
"-m",
79+
"pip",
80+
"--disable-pip-version-check",
81+
"install",
82+
str(whl),
83+
]
84+
)
85+
86+
1487
def get_exposed():
1588
exposed = set()
1689
try:
@@ -34,22 +107,43 @@ def list_exposed():
34107
def expose_packages(names, unexpose=False):
35108
exposed = get_exposed()
36109
names = set(names)
110+
added = set()
111+
removed = []
37112

38113
if not unexpose:
39114
for name in names:
40-
try:
41-
pkg_resources.require(name)
42-
except pkg_resources.DistributionNotFound:
43-
logger.warning("%r was not found in build-python. Skipping.", name)
44-
else:
115+
if name in exposed:
116+
continue
117+
version = _get_package(name)
118+
if version is not None:
45119
exposed.add(name)
120+
added.add((name, version))
121+
else:
122+
logger.warning("%r was not found in build-python. Skipping.", name)
46123

47124
else:
48125
for name in names:
49126
if name not in exposed:
50127
logger.warning("%r was not exposed. Skipping.", name)
51128
else:
52129
exposed.remove(name)
130+
removed.append(name)
131+
132+
for name, version in added:
133+
install_fake_wheel(name, version)
134+
135+
if removed:
136+
subprocess.check_call(
137+
[
138+
{{repr(context.cross_env_exe)}},
139+
"-m",
140+
"pip",
141+
"--disable-pip-version-check",
142+
"uninstall",
143+
"-y",
144+
]
145+
+ removed
146+
)
53147

54148
with open(EXPOSED_LIBS, "w") as fp:
55149
for item in sorted(exposed):
@@ -129,7 +223,7 @@ def main():
129223
expose_packages(args.MODULE, args.unexpose)
130224
except Exception as e:
131225
exit_code = 1
132-
logger.error("Cannot %s %s: %s", action, mod, e)
226+
logger.error("Cannot %s %s: %s", action, args.MODULE, e)
133227
logger.error("Traceback:", exc_info=True)
134228

135229
sys.exit(exit_code)

crossenv/scripts/pkg_resources-patch.py.tmpl

Lines changed: 0 additions & 46 deletions
This file was deleted.

crossenv/scripts/site.py.tmpl

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -122,9 +122,7 @@ class CrossenvFinder(importlib.abc.MetaPathFinder):
122122
"distutils.sysconfig": "{{context.lib_path}}/distutils-sysconfig-patch.py",
123123
"distutils.sysconfig_pypy": "{{context.lib_path}}/distutils-sysconfig-patch.py",
124124
"platform": "{{context.lib_path}}/platform-patch.py",
125-
"pkg_resources": "{{context.lib_path}}/pkg_resources-patch.py",
126125
"pip._vendor.distlib.scripts": "{{context.lib_path}}/pip-_vendor-distlib-scripts-patch.py",
127-
"pip._vendor.pkg_resources": "{{context.lib_path}}/pkg_resources-patch.py",
128126
"pip._vendor.packaging.tags": "{{context.lib_path}}/packaging-tags-patch.py",
129127
"packaging.tags": "{{context.lib_path}}/packaging-tags-patch.py",
130128
}

pyproject.toml

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,9 @@ classifiers = [
2222
"License :: OSI Approved :: MIT License",
2323
"Programming Language :: Python :: 3",
2424
]
25+
dependencies = [
26+
"wheel"
27+
]
2528

2629
[project.urls]
2730
Homepage = "https://github.com/benfogle/crossenv"

tests/test_environment.py

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -248,7 +248,6 @@ def test_run_sysconfig_module(crossenv):
248248
assert destdirs_cmdline == out
249249

250250

251-
@pytest.mark.xfail(reason="cross-expose needs to patch importlib.metadata")
252251
def test_cross_expose(crossenv):
253252
out = crossenv.check_output(["pip", "freeze"])
254253
assert b"colorama" not in out

0 commit comments

Comments
 (0)