Skip to content
Merged
Show file tree
Hide file tree
Changes from 2 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
23 changes: 9 additions & 14 deletions src/manage/pathutils.py
Original file line number Diff line number Diff line change
Expand Up @@ -124,23 +124,18 @@
if "*" not in p:
return m.casefold() == p

allow_skip = False
must_start_with = True
for bit in p.split("*"):
if bit:
if allow_skip:
allow_skip = False
try:
i = m.index(bit)
except ValueError:
return False
m = m[i + len(bit):]
elif m.startswith(bit):
m = m[len(bit):]
else:
try:
i = m.index(bit)
except ValueError:
return False
else:
allow_skip = True
return True
if must_start_with and i != 0:
return False

Check warning on line 135 in src/manage/pathutils.py

View check run for this annotation

Codecov / codecov/patch

src/manage/pathutils.py#L135

Added line #L135 was not covered by tests
m = m[i + len(bit):]
must_start_with = False
return not m or p.endswith("*")


class Path(PurePath):
Expand Down
11 changes: 8 additions & 3 deletions src/manage/scriptutils.py
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,7 @@ def _find_shebang_command(cmd, full_cmd):
for i in cmd.get_installs():
if is_default and i.get("default"):
return i
for a in i["alias"]:
for a in i.get("alias", ()):
if sh_cmd.match(a["name"]):
LOGGER.debug("Matched alias %s in %s", a["name"], i["id"])
return {**i, "executable": i["prefix"] / a["target"]}
Expand All @@ -34,8 +34,13 @@ def _find_shebang_command(cmd, full_cmd):
if sh_cmd.match(i["executable"]):
LOGGER.debug("Matched executable %s in %s", i["executable"], i["id"])
return i
else:
raise LookupError

# Fallback search for 'python<TAG>.exe' shebangs
if sh_cmd.match("python*.exe"):
tag = sh_cmd.name[6:-4]
return cmd.get_install_to_run(f"PythonCore/{tag}")

raise LookupError


def _find_on_path(cmd, full_cmd):
Expand Down
5 changes: 5 additions & 0 deletions tests/conftest.py
Original file line number Diff line number Diff line change
Expand Up @@ -143,6 +143,11 @@ def __init__(self, installs=[]):
def get_installs(self):
return self.installs

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


@pytest.fixture
def fake_config():
Expand Down
16 changes: 16 additions & 0 deletions tests/test_pathutils.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
import pytest

from manage.pathutils import Path, PurePath

def test_path_match():
p = Path("python3.12.exe")
assert p.match("*.exe")
assert p.match("python*")
assert p.match("python*.exe")
assert p.match("*hon3.*")
assert p.match("p*3.*.exe")

assert not p.match("*.com")
assert not p.match("example*")
assert not p.match("example*.com")
assert not p.match("*ple*")
8 changes: 7 additions & 1 deletion tests/test_scriptutils.py
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@

def _fake_install(v, **kwargs):
return {
"company": "Test",
"company": kwargs.get("company", "Test"),
"id": f"test-{v}",
"tag": str(v),
"version": str(v),
Expand All @@ -29,6 +29,8 @@ def _fake_install(v, **kwargs):
INSTALLS = [
_fake_install("1.0", alias=[{"name": "test1.0.exe", "target": "./test-binary-1.0.exe"}]),
_fake_install("1.1", alias=[{"name": "test1.1.exe", "target": "./test-binary-1.1.exe"}]),
_fake_install("1.3.1", company="PythonCore"),
_fake_install("1.3.2", company="PythonOther"),
_fake_install("2.0", alias=[{"name": "test2.0.exe", "target": "./test-binary-2.0.exe"}]),
]

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