diff --git a/src/manage/scriptutils.py b/src/manage/scriptutils.py index d4b9715..07e4a11 100644 --- a/src/manage/scriptutils.py +++ b/src/manage/scriptutils.py @@ -19,11 +19,16 @@ def _find_shebang_command(cmd, full_cmd): if not sh_cmd.match("*.exe"): sh_cmd = sh_cmd.with_name(sh_cmd.name + ".exe") - is_default = sh_cmd.match("python.exe") or sh_cmd.match("py.exe") + is_wdefault = sh_cmd.match("pythonw.exe") or sh_cmd.match("pyw.exe") + is_default = is_wdefault or sh_cmd.match("python.exe") or sh_cmd.match("py.exe") for i in cmd.get_installs(): if is_default and i.get("default"): - return i + if is_wdefault: + target = [t for t in i.get("run-for", []) if t.get("windowed")] + if target: + return {**i, "executable": i["prefix"] / target[0]["target"]} + return {**i, "executable": i["prefix"] / i["executable"]} for a in i.get("alias", ()): if sh_cmd.match(a["name"]): LOGGER.debug("Matched alias %s in %s", a["name"], i["id"]) @@ -35,7 +40,10 @@ def _find_shebang_command(cmd, full_cmd): LOGGER.debug("Matched executable %s in %s", i["executable"], i["id"]) return i - # Fallback search for 'python.exe' shebangs + # Fallback search for 'python[w].exe' shebangs + if sh_cmd.match("pythonw*.exe"): + tag = sh_cmd.name[7:-4] + return cmd.get_install_to_run(f"PythonCore/{tag}", windowed=True) if sh_cmd.match("python*.exe"): tag = sh_cmd.name[6:-4] return cmd.get_install_to_run(f"PythonCore/{tag}") diff --git a/tests/conftest.py b/tests/conftest.py index 41957ca..6faf08e 100644 --- a/tests/conftest.py +++ b/tests/conftest.py @@ -159,7 +159,14 @@ def __init__(self, global_dir, installs=[]): def get_installs(self, *, include_unmanaged=True, set_default=True): return self.installs - def get_install_to_run(self, tag): + def get_install_to_run(self, tag, *, windowed=False): + if windowed: + i = self.get_install_to_run(tag) + target = [t for t in i.get("run-for", []) if t.get("windowed")] + if target: + return {**i, "executable": i["prefix"] / target[0]["target"]} + return i + company, _, tag = tag.replace("/", "\\").rpartition("\\") return [i for i in self.installs if i["tag"] == tag and (not company or i["company"] == company)][0] diff --git a/tests/test_scriptutils.py b/tests/test_scriptutils.py index 05d3309..0ee8804 100644 --- a/tests/test_scriptutils.py +++ b/tests/test_scriptutils.py @@ -8,6 +8,7 @@ from manage.scriptutils import ( find_install_from_script, + _find_shebang_command, _read_script, NewEncoding, _maybe_quote, @@ -69,6 +70,25 @@ def test_read_shebang(fake_config, tmp_path, script, expect): assert not expect +def test_default_py_shebang(fake_config, tmp_path): + inst = _fake_install("1.0", company="PythonCore", prefix=PurePath("C:\\TestRoot"), default=True) + inst["run-for"] = [ + dict(name="python.exe", target=".\\python.exe"), + dict(name="pythonw.exe", target=".\\pythonw.exe", windowed=1), + ] + fake_config.installs[:] = [inst] + + # Finds the install's default executable + assert _find_shebang_command(fake_config, "python")["executable"].match("test-binary-1.0.exe") + assert _find_shebang_command(fake_config, "py")["executable"].match("test-binary-1.0.exe") + assert _find_shebang_command(fake_config, "python1.0")["executable"].match("test-binary-1.0.exe") + # Finds the install's run-for executable with windowed=1 + assert _find_shebang_command(fake_config, "pythonw")["executable"].match("pythonw.exe") + assert _find_shebang_command(fake_config, "pyw")["executable"].match("pythonw.exe") + assert _find_shebang_command(fake_config, "pythonw1.0")["executable"].match("pythonw.exe") + + + @pytest.mark.parametrize("script, expect", [ ("# not a coding comment", None), ("# coding: utf-8-sig", None),