Skip to content

Commit dda57a5

Browse files
committed
Adds fallback search for 'python<TAG>.exe' style shebangs.
Fixes #91
1 parent 0c2dd81 commit dda57a5

File tree

5 files changed

+41
-19
lines changed

5 files changed

+41
-19
lines changed

src/manage/pathutils.py

Lines changed: 11 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -124,22 +124,18 @@ def match(self, pattern, full_match=False):
124124
if "*" not in p:
125125
return m.casefold() == p
126126

127-
allow_skip = False
127+
must_start_with = not p.startswith("*")
128128
for bit in p.split("*"):
129-
if bit:
130-
if allow_skip:
131-
allow_skip = False
132-
try:
133-
i = m.index(bit)
134-
except ValueError:
135-
return False
136-
m = m[i + len(bit):]
137-
elif m.startswith(bit):
138-
m = m[len(bit):]
139-
else:
140-
return False
141-
else:
142-
allow_skip = True
129+
if not bit:
130+
continue
131+
try:
132+
i = m.index(bit)
133+
except ValueError:
134+
return False
135+
if must_start_with and i != 0:
136+
return False
137+
m = m[i + len(bit):]
138+
must_start_with = False
143139
return True
144140

145141

src/manage/scriptutils.py

Lines changed: 8 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -24,7 +24,7 @@ def _find_shebang_command(cmd, full_cmd):
2424
for i in cmd.get_installs():
2525
if is_default and i.get("default"):
2626
return i
27-
for a in i["alias"]:
27+
for a in i.get("alias", ()):
2828
if sh_cmd.match(a["name"]):
2929
LOGGER.debug("Matched alias %s in %s", a["name"], i["id"])
3030
return {**i, "executable": i["prefix"] / a["target"]}
@@ -34,8 +34,13 @@ def _find_shebang_command(cmd, full_cmd):
3434
if sh_cmd.match(i["executable"]):
3535
LOGGER.debug("Matched executable %s in %s", i["executable"], i["id"])
3636
return i
37-
else:
38-
raise LookupError
37+
38+
# Fallback search for 'python<TAG>.exe' shebangs
39+
if sh_cmd.match("python*.exe"):
40+
tag = sh_cmd.name[6:-4]
41+
return cmd.get_install_to_run(f"PythonCore/{tag}")
42+
43+
raise LookupError
3944

4045

4146
def _find_on_path(cmd, full_cmd):

tests/conftest.py

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -143,6 +143,11 @@ def __init__(self, installs=[]):
143143
def get_installs(self):
144144
return self.installs
145145

146+
def get_install_to_run(self, tag):
147+
company, _, tag = (tag.replace("/", "\\")).rpartition("\\")
148+
return [i for i in self.installs
149+
if i["tag"] == tag and (not company or i["company"] == company)][0]
150+
146151

147152
@pytest.fixture
148153
def fake_config():

tests/test_pathutils.py

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
import pytest
2+
3+
from manage.pathutils import Path, PurePath
4+
5+
def test_path_match():
6+
p = Path("python3.12.exe")
7+
assert p.match("*.exe")
8+
assert p.match("python*")
9+
assert p.match("python*.exe")
10+
assert p.match("p*3.*.exe")

tests/test_scriptutils.py

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,7 @@
1717

1818
def _fake_install(v, **kwargs):
1919
return {
20-
"company": "Test",
20+
"company": kwargs.get("company", "Test"),
2121
"id": f"test-{v}",
2222
"tag": str(v),
2323
"version": str(v),
@@ -29,6 +29,8 @@ def _fake_install(v, **kwargs):
2929
INSTALLS = [
3030
_fake_install("1.0", alias=[{"name": "test1.0.exe", "target": "./test-binary-1.0.exe"}]),
3131
_fake_install("1.1", alias=[{"name": "test1.1.exe", "target": "./test-binary-1.1.exe"}]),
32+
_fake_install("1.3.1", company="PythonCore"),
33+
_fake_install("1.3.2", company="PythonOther"),
3234
_fake_install("2.0", alias=[{"name": "test2.0.exe", "target": "./test-binary-2.0.exe"}]),
3335
]
3436

@@ -46,6 +48,10 @@ def _fake_install(v, **kwargs):
4648
("#! /usr/bin/env test1.0\n", "1.0"),
4749
("#! /usr/bin/env test2.0\n", "2.0"),
4850
("#! /usr/bin/env -S test2.0\n", "2.0"),
51+
# Legacy handling specifically for "python<TAG>"
52+
("#! /usr/bin/python1.3.1", "1.3.1"),
53+
("#! /usr/bin/env python1.3.1", "1.3.1"),
54+
("#! /usr/bin/python1.3.2", None),
4955
])
5056
def test_read_shebang(fake_config, tmp_path, script, expect):
5157
fake_config.installs.extend(INSTALLS)

0 commit comments

Comments
 (0)