Skip to content

Commit 36118d8

Browse files
committed
Add tests to improve coverage
1 parent bd20de5 commit 36118d8

File tree

2 files changed

+113
-24
lines changed

2 files changed

+113
-24
lines changed

src/manage/aliasutils.py

Lines changed: 34 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -149,7 +149,7 @@ def create_alias(cmd, install, alias, target, *, script_code=None, _link=os.link
149149
if script_code:
150150
do_update = True
151151
try:
152-
do_update = p_script.read_text(encoding="utf-8") == script_code
152+
do_update = p_script.read_text(encoding="utf-8") != script_code
153153
except FileNotFoundError:
154154
pass
155155
except (OSError, UnicodeDecodeError):
@@ -198,6 +198,24 @@ def _parse_entrypoint_line(line):
198198
return None, None, None
199199

200200

201+
def _readlines(path):
202+
try:
203+
f = open(path, "r", encoding="utf-8", errors="strict")
204+
except OSError:
205+
LOGGER.debug("Failed to read %s", path, exc_info=True)
206+
return
207+
208+
with f:
209+
try:
210+
while True:
211+
yield next(f)
212+
except StopIteration:
213+
return
214+
except UnicodeDecodeError:
215+
LOGGER.debug("Failed to decode contents of %s", path, exc_info=True)
216+
return
217+
218+
201219
def _scan_one(root):
202220
# Scan d for dist-info directories with entry_points.txt
203221
dist_info = [d for d in root.glob("*.dist-info") if d.is_dir()]
@@ -207,28 +225,21 @@ def _scan_one(root):
207225

208226
# Filter down to [console_scripts] and [gui_scripts]
209227
for ep in entrypoints:
210-
try:
211-
f = open(ep, "r", encoding="utf-8", errors="strict")
212-
except OSError:
213-
LOGGER.debug("Failed to read %s", ep, exc_info=True)
214-
continue
215-
216-
with f:
217-
alias = None
218-
for line in f:
219-
if line.strip() == "[console_scripts]":
220-
alias = dict(windowed=0)
221-
elif line.strip() == "[gui_scripts]":
222-
alias = dict(windowed=1)
223-
elif line.lstrip().startswith("["):
224-
alias = None
225-
elif alias is not None:
226-
name, mod, func = _parse_entrypoint_line(line)
227-
if name and mod and func:
228-
yield (
229-
{**alias, "name": name},
230-
SCRIPT_CODE.format(mod=mod, func=func),
231-
)
228+
alias = None
229+
for line in _readlines(ep):
230+
if line.strip() == "[console_scripts]":
231+
alias = dict(windowed=0)
232+
elif line.strip() == "[gui_scripts]":
233+
alias = dict(windowed=1)
234+
elif line.lstrip().startswith("["):
235+
alias = None
236+
elif alias is not None:
237+
name, mod, func = _parse_entrypoint_line(line)
238+
if name and mod and func:
239+
yield (
240+
{**alias, "name": name},
241+
SCRIPT_CODE.format(mod=mod, func=func),
242+
)
232243

233244

234245
def _scan(prefix, dirs):

tests/test_alias.py

Lines changed: 79 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -48,18 +48,23 @@ def __enter__(self):
4848
def __exit__(self, *exc_info):
4949
pass
5050

51-
def check(self, cmd, tag, name, expect, windowed=0):
51+
def check(self, cmd, tag, name, expect, windowed=0, script_code=None):
5252
AU.create_alias(
5353
cmd,
5454
{"tag": tag},
5555
{"name": name, "windowed": windowed},
5656
self._expect_target,
57+
script_code=script_code,
5758
)
5859
print(*cmd.global_dir.glob("*"), sep="\n")
5960
assert (cmd.global_dir / f"{name}.exe").is_file()
6061
assert (cmd.global_dir / f"{name}.exe.__target__").is_file()
6162
assert (cmd.global_dir / f"{name}.exe").read_text() == expect
6263
assert (cmd.global_dir / f"{name}.exe.__target__").read_text() == self._expect_target
64+
if script_code:
65+
assert (cmd.global_dir / f"{name}.exe.__script__.py").is_file()
66+
assert (cmd.global_dir / f"{name}.exe.__script__.py").read_text() == script_code
67+
assert name.casefold() in cmd.scratch["aliasutils.create_alias.alias_written"]
6368

6469
def check_32(self, cmd, tag, name):
6570
self.check(cmd, tag, name, self._expect["-32"])
@@ -79,6 +84,10 @@ def check_arm64(self, cmd, tag, name):
7984
def check_warm64(self, cmd, tag, name):
8085
self.check(cmd, tag, name, self._expect["w-arm64"], windowed=1)
8186

87+
def check_script(self, cmd, tag, name, windowed=0):
88+
self.check(cmd, tag, name, self._expect["w-32" if windowed else "-32"],
89+
windowed=windowed, script_code=secrets.token_hex(128))
90+
8291

8392
def test_write_alias_tag_with_platform(alias_checker):
8493
alias_checker.check_32(alias_checker.Cmd(), "1.0-32", "testA")
@@ -103,6 +112,12 @@ def test_write_alias_fallback_platform(alias_checker):
103112
alias_checker.check_w64(alias_checker.Cmd("-spam"), "1.0", "testB")
104113

105114

115+
def test_write_script_alias(alias_checker):
116+
alias_checker.check_script(alias_checker.Cmd(), "1.0-32", "testA", windowed=0)
117+
alias_checker.check_script(alias_checker.Cmd(), "1.0-32", "testB", windowed=1)
118+
alias_checker.check_script(alias_checker.Cmd(), "1.0-32", "testA", windowed=0)
119+
120+
106121
def test_write_alias_launcher_missing(fake_config, assert_log, tmp_path):
107122
fake_config.launcher_exe = tmp_path / "non-existent.exe"
108123
fake_config.default_platform = '-32'
@@ -232,6 +247,38 @@ def test_parse_entrypoint_line():
232247
assert expect == AU._parse_entrypoint_line(line)
233248

234249

250+
def test_scan_create_entrypoints(fake_config, tmp_path):
251+
root = tmp_path / "test_install"
252+
site = root / "site-packages"
253+
A = site / "A.dist-info"
254+
A.mkdir(parents=True, exist_ok=True)
255+
(A / "entry_points.txt").write_text("""[console_scripts]
256+
a = a:main
257+
258+
[gui_scripts]
259+
aw = a:main
260+
""")
261+
262+
install = dict(prefix=root, id="test", alias=[dict(target="target.exe")])
263+
264+
created = []
265+
AU.scan_and_create_entrypoints(
266+
fake_config,
267+
install,
268+
dict(dirs=["site-packages"]),
269+
_create_alias=lambda *a, **kw: created.append((a, kw)),
270+
)
271+
assert 2 == len(created)
272+
for name, windowed, c in zip("a aw".split(), [0, 1], created):
273+
expect = dict(zip("cmd install alias target".split(), c[0])) | c[1]
274+
assert expect["cmd"] is fake_config
275+
assert expect["install"] is install
276+
assert expect["alias"]["name"] == name
277+
assert expect["alias"]["windowed"] == windowed
278+
assert expect["target"].match("target.exe")
279+
assert "from a import main" in expect["script_code"]
280+
281+
235282
def test_scan_entrypoints(tmp_path):
236283
site = tmp_path / "site"
237284
A = site / "a.dist-info"
@@ -243,8 +290,18 @@ def test_scan_entrypoints(tmp_path):
243290
a_cmd = a:main
244291
a2_cmd = a:main2 [spam]
245292
293+
[other] # shouldn't be included
294+
a3_cmd = a:main3
295+
246296
[gui_scripts]
247297
aw_cmd = a:main
298+
""")
299+
(B / "entry_points.txt").write_bytes(b"""# Invalid file
300+
301+
\x80\x81\x82\x83\x84\x85\x86\x87\x88\x89
302+
303+
[console_scripts]
304+
b_cmd = b:main
248305
""")
249306
actual = list(AU._scan_one(site))
250307
assert [a[0]["name"] for a in actual] == [
@@ -255,3 +312,24 @@ def test_scan_entrypoints(tmp_path):
255312
"(main())", "(main2())", "(main())"
256313
]
257314

315+
316+
def test_cleanup_aliases(fake_config):
317+
root = fake_config.global_dir
318+
root.mkdir(parents=True, exist_ok=True)
319+
(root / "alias1.exe").write_bytes(b"")
320+
(root / "alias1.exe.__target__").write_bytes(b"")
321+
(root / "alias1.exe.__script__.py").write_bytes(b"")
322+
(root / "alias2.exe").write_bytes(b"")
323+
(root / "alias2.exe.__target__").write_bytes(b"")
324+
(root / "alias2.exe.__script__.py").write_bytes(b"")
325+
(root / "alias3.exe").write_bytes(b"")
326+
(root / "alias3.exe.__target__").write_bytes(b"")
327+
fake_config.scratch["aliasutils.create_alias.alias_written"] = set([
328+
"alias1".casefold(),
329+
"alias3".casefold(),
330+
])
331+
AU.cleanup_alias(fake_config)
332+
assert set(f.name for f in root.glob("*")) == set([
333+
"alias1.exe", "alias1.exe.__target__", "alias1.exe.__script__.py",
334+
"alias3.exe", "alias3.exe.__target__",
335+
])

0 commit comments

Comments
 (0)