Skip to content

Commit 1e45f5a

Browse files
committed
Add integration test for entrypoint creation
1 parent 682d0f8 commit 1e45f5a

File tree

7 files changed

+173
-11
lines changed

7 files changed

+173
-11
lines changed

.github/workflows/build.yml

Lines changed: 2 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -172,19 +172,10 @@ jobs:
172172
PYTHON_MANAGER_CONFIG: .\test-config.json
173173
PYMANAGER_DEBUG: true
174174

175-
- name: 'Validate entrypoint script'
175+
- name: 'Validate entrypoint scripts'
176176
run: |
177177
$env:PYTHON_MANAGER_CONFIG = (gi $env:PYTHON_MANAGER_CONFIG).FullName
178-
cd .\test_installs\_bin
179-
del pip* -Verbose
180-
pymanager install --refresh
181-
dir pip*
182-
Get-Item .\pip.exe
183-
Get-Item .\pip.exe.__target__
184-
Get-Content .\pip.exe.__target__
185-
Get-Item .\pip.exe.__script__.py
186-
Get-Content .\pip.exe.__script__.py
187-
.\pip.exe --version
178+
pymanager exec tests\run-eptest.py
188179
env:
189180
PYTHON_MANAGER_INCLUDE_UNMANAGED: false
190181
PYTHON_MANAGER_CONFIG: .\test-config.json

ci/release.yml

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -313,6 +313,16 @@ stages:
313313
PYTHON_MANAGER_CONFIG: .\test-config.json
314314
PYMANAGER_DEBUG: true
315315
316+
- powershell: |
317+
$env:PYTHON_MANAGER_CONFIG = (gi $env:PYTHON_MANAGER_CONFIG).FullName
318+
pymanager exec tests\run-eptest.py
319+
displayName: 'Validate entrypoint scripts'
320+
timeoutInMinutes: 5
321+
env:
322+
PYTHON_MANAGER_INCLUDE_UNMANAGED: false
323+
PYTHON_MANAGER_CONFIG: .\test-config.json
324+
PYMANAGER_DEBUG: true
325+
316326
- powershell: |
317327
pymanager list --online 3 3-32 3-64 3-arm64
318328
pymanager install --download .\bundle 3 3-32 3-64 3-arm64

src/manage/commands.py

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -425,6 +425,8 @@ def __init__(self, args, root=None):
425425
LOGGER.warn("Failed to read configuration file from %s", self.config_file)
426426
raise
427427

428+
self.config = config
429+
428430
# Top-level arguments get updated manually from the config
429431
# (per-command config gets loaded automatically below)
430432

src/manage/list_command.py

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -222,6 +222,11 @@ def list_formats(cmd, installs):
222222
LOGGER.print(f"{k:<{max_key_width}} {doc}", always=True)
223223

224224

225+
def list_config(cmd, installs):
226+
"List the current config"
227+
LOGGER.print(json.dumps(cmd.config, default=str), always=True)
228+
229+
225230
def format_legacy(cmd, installs, paths=False):
226231
"List runtimes using the old format"
227232
seen_default = False
@@ -262,6 +267,7 @@ def format_legacy_paths(cmd, installs):
262267
"legacy": format_legacy,
263268
"legacy-paths": format_legacy_paths,
264269
"formats": list_formats,
270+
"config": list_config,
265271
}
266272

267273

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
[console_scripts]
2+
eptest=eptestpackage:main
3+
eptest-refresh=eptestpackage:do_refresh
4+
5+
[gui_scripts]
6+
eptestw=eptestpackage:mainw
Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
def main():
2+
print("eptestpackage:main")
3+
4+
def mainw():
5+
print("eptestpackage:mainw")
6+
7+
def do_refresh():
8+
import subprocess
9+
with subprocess.Popen(
10+
["pymanager", "install", "-q", "--refresh"],
11+
stdout=subprocess.PIPE,
12+
stderr=subprocess.STDOUT,
13+
encoding="ascii",
14+
errors="replace",
15+
) as p:
16+
out, _ = p.communicate(None)
17+
print(out)
18+
19+
print("eptestpackage:do_refresh")

tests/run-eptest.py

Lines changed: 128 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,128 @@
1+
# This is an integration test, rather than a unit test.
2+
# It should be run in a Python runtime that has been installed.
3+
# The 'pymanager.exe' under test should be first on PATH
4+
5+
import json
6+
import shutil
7+
import subprocess
8+
import sys
9+
10+
from pathlib import Path
11+
12+
EXIT_SETUP_FAILED = 1
13+
EXIT_ALIAS_NOT_CREATED = 2
14+
EXIT_ALIAS_INVALID = 3
15+
16+
CLEANUP = []
17+
18+
def run(*args, **kwargs):
19+
print("##[command]", *args)
20+
with subprocess.Popen(
21+
args,
22+
stdout=kwargs.pop("stdout", subprocess.PIPE),
23+
stderr=kwargs.pop("stderr", subprocess.STDOUT),
24+
encoding=kwargs.pop("encoding", "ascii"),
25+
errors=kwargs.pop("errors", "replace"),
26+
**kwargs,
27+
) as p:
28+
out, err = p.communicate(None)
29+
if p.returncode:
30+
raise subprocess.CalledProcessError(p.returncode, args, out, err)
31+
return out, err
32+
33+
def main():
34+
out, _ = run("pymanager", "list", "-f=json", "-q")
35+
for install in json.loads(out)["versions"]:
36+
if not install.get("unmanaged"):
37+
break
38+
else:
39+
print("[ERROR] No suitable (managed) runtime found.")
40+
sys.exit(EXIT_SETUP_FAILED)
41+
42+
print("Using", install["display-name"], "from", install["prefix"], "for test")
43+
44+
prefix = install["prefix"]
45+
exe = install["executable"]
46+
47+
site = Path(prefix) / "Lib/site-packages"
48+
if not site.is_dir():
49+
print("[ERROR] Selected runtime has no site-packages folder.")
50+
sys.exit(EXIT_SETUP_FAILED)
51+
52+
eptest_src = Path(__file__).parent / "eptestpackage"
53+
if not eptest_src.is_dir():
54+
print("[ERROR] eptestpackage is missing from test script location.")
55+
sys.exit(EXIT_SETUP_FAILED)
56+
57+
dist_info = site / "eptestpackage-1.0.dist-info"
58+
dist_info.mkdir(parents=True, exist_ok=True)
59+
CLEANUP.append(lambda: shutil.rmtree(dist_info))
60+
for f in (eptest_src / "eptestpackage.dist-info").glob("*"):
61+
(dist_info / f.name).write_bytes(f.read_bytes())
62+
(site / "eptestpackage.py").write_bytes((eptest_src / "eptestpackage.py").read_bytes())
63+
CLEANUP.append((site / "eptestpackage.py").unlink)
64+
65+
print("Listing 'installed' packages (should include eptestpackage)")
66+
print(*site.glob("*"), sep="\n")
67+
print()
68+
69+
out, _ = run(exe, "-c", "import eptestpackage; eptestpackage.main()")
70+
if out.strip() != "eptestpackage:main":
71+
print(out)
72+
print("[ERROR] Failed to import eptestpackage")
73+
sys.exit(EXIT_SETUP_FAILED)
74+
print("Confirmed eptestpackage is importable")
75+
76+
out, _ = run("pymanager", "list", "-f=config", "-q")
77+
try:
78+
config = json.loads(out)
79+
except json.JSONDecodeError:
80+
print("py list -f=config output:")
81+
print(out)
82+
raise
83+
bin_dir = Path(config["global_dir"])
84+
print(bin_dir)
85+
86+
refresh_log, _ = run("pymanager", "install", "--refresh", "-vv")
87+
CLEANUP.append(lambda: run("pymanager", "install", "--refresh"))
88+
89+
print("Listing global aliases (should include eptest, eptestw, eptest-refresh)")
90+
print(*bin_dir.glob("eptest*"), sep="\n")
91+
92+
for n in ["eptest.exe", "eptestw.exe", "eptest-refresh.exe"]:
93+
if not (bin_dir / n).is_file():
94+
print("--refresh log follows")
95+
print(refresh_log)
96+
print("[ERROR] Did not create", n)
97+
sys.exit(EXIT_ALIAS_NOT_CREATED)
98+
99+
out, _ = run(bin_dir / "eptest.exe")
100+
if out.strip() != "eptestpackage:main":
101+
print(out)
102+
print("[ERROR] eptest.exe alias failed")
103+
sys.exit(EXIT_ALIAS_INVALID)
104+
105+
out, _ = run(bin_dir / "eptestw.exe")
106+
if out.strip() != "eptestpackage:mainw":
107+
print(out)
108+
print("[ERROR] eptestw.exe alias failed")
109+
sys.exit(EXIT_ALIAS_INVALID)
110+
111+
out, _ = run(bin_dir / "eptest-refresh.exe")
112+
if not out.strip().endswith("eptestpackage:do_refresh"):
113+
print(out)
114+
print("[ERROR] eptest-refresh.exe alias failed")
115+
sys.exit(EXIT_ALIAS_INVALID)
116+
117+
118+
try:
119+
main()
120+
finally:
121+
print("Beginning cleanup")
122+
while CLEANUP:
123+
try:
124+
CLEANUP.pop()()
125+
except subprocess.CalledProcessError as ex:
126+
print("Subprocess failed during cleanup:")
127+
print(ex.args, ex.returncode)
128+
print(ex.output)

0 commit comments

Comments
 (0)