Skip to content
Merged
Show file tree
Hide file tree
Changes from 1 commit
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
Next Next commit
gh-100247: Fix py.exe launcher not using entire shebang command for f…
…inding custom commands.
  • Loading branch information
zooba committed Jan 11, 2023
commit a5609e6756caf383049b58086da11c3c25c43aea
57 changes: 40 additions & 17 deletions Lib/test/test_launcher.py
Original file line number Diff line number Diff line change
Expand Up @@ -67,12 +67,17 @@
)


TEST_PY_COMMANDS = "\n".join([
TEST_PY_DEFAULTS = "\n".join([
"[defaults]",
*[f"{k[3:].lower()}={v}" for k, v in TEST_PY_ENV.items()]
*[f"{k[3:].lower()}={v}" for k, v in TEST_PY_ENV.items()],
])


TEST_PY_COMMANDS = "\n".join([
"[commands]",
"test-command=TEST_EXE.exe",
])

def create_registry_data(root, data):
def _create_registry_data(root, key, value):
if isinstance(value, dict):
Expand Down Expand Up @@ -429,21 +434,21 @@ def test_search_major_2(self):
self.assertTrue(data["env.tag"].startswith("2."), data["env.tag"])

def test_py_default(self):
with self.py_ini(TEST_PY_COMMANDS):
with self.py_ini(TEST_PY_DEFAULTS):
data = self.run_py(["-arg"])
self.assertEqual("PythonTestSuite", data["SearchInfo.company"])
self.assertEqual("3.100", data["SearchInfo.tag"])
self.assertEqual("X.Y.exe -arg", data["stdout"].strip())

def test_py2_default(self):
with self.py_ini(TEST_PY_COMMANDS):
with self.py_ini(TEST_PY_DEFAULTS):
data = self.run_py(["-2", "-arg"])
self.assertEqual("PythonTestSuite", data["SearchInfo.company"])
self.assertEqual("3.100-32", data["SearchInfo.tag"])
self.assertEqual("X.Y-32.exe -arg", data["stdout"].strip())

def test_py3_default(self):
with self.py_ini(TEST_PY_COMMANDS):
with self.py_ini(TEST_PY_DEFAULTS):
data = self.run_py(["-3", "-arg"])
self.assertEqual("PythonTestSuite", data["SearchInfo.company"])
self.assertEqual("3.100-arm64", data["SearchInfo.tag"])
Expand All @@ -468,7 +473,7 @@ def test_py3_default_env(self):
self.assertEqual("X.Y-arm64.exe -X fake_arg_for_test -arg", data["stdout"].strip())

def test_py_default_short_argv0(self):
with self.py_ini(TEST_PY_COMMANDS):
with self.py_ini(TEST_PY_DEFAULTS):
for argv0 in ['"py.exe"', 'py.exe', '"py"', 'py']:
with self.subTest(argv0):
data = self.run_py(["--version"], argv=f'{argv0} --version')
Expand Down Expand Up @@ -518,63 +523,63 @@ def test_virtualenv_with_env(self):
self.assertNotEqual(data2["SearchInfo.lowPriorityTag"], "True")

def test_py_shebang(self):
with self.py_ini(TEST_PY_COMMANDS):
with self.py_ini(TEST_PY_DEFAULTS):
with self.script("#! /usr/bin/python -prearg") as script:
data = self.run_py([script, "-postarg"])
self.assertEqual("PythonTestSuite", data["SearchInfo.company"])
self.assertEqual("3.100", data["SearchInfo.tag"])
self.assertEqual(f"X.Y.exe -prearg {script} -postarg", data["stdout"].strip())

def test_python_shebang(self):
with self.py_ini(TEST_PY_COMMANDS):
with self.py_ini(TEST_PY_DEFAULTS):
with self.script("#! python -prearg") as script:
data = self.run_py([script, "-postarg"])
self.assertEqual("PythonTestSuite", data["SearchInfo.company"])
self.assertEqual("3.100", data["SearchInfo.tag"])
self.assertEqual(f"X.Y.exe -prearg {script} -postarg", data["stdout"].strip())

def test_py2_shebang(self):
with self.py_ini(TEST_PY_COMMANDS):
with self.py_ini(TEST_PY_DEFAULTS):
with self.script("#! /usr/bin/python2 -prearg") as script:
data = self.run_py([script, "-postarg"])
self.assertEqual("PythonTestSuite", data["SearchInfo.company"])
self.assertEqual("3.100-32", data["SearchInfo.tag"])
self.assertEqual(f"X.Y-32.exe -prearg {script} -postarg", data["stdout"].strip())

def test_py3_shebang(self):
with self.py_ini(TEST_PY_COMMANDS):
with self.py_ini(TEST_PY_DEFAULTS):
with self.script("#! /usr/bin/python3 -prearg") as script:
data = self.run_py([script, "-postarg"])
self.assertEqual("PythonTestSuite", data["SearchInfo.company"])
self.assertEqual("3.100-arm64", data["SearchInfo.tag"])
self.assertEqual(f"X.Y-arm64.exe -X fake_arg_for_test -prearg {script} -postarg", data["stdout"].strip())

def test_py_shebang_nl(self):
with self.py_ini(TEST_PY_COMMANDS):
with self.py_ini(TEST_PY_DEFAULTS):
with self.script("#! /usr/bin/python -prearg\n") as script:
data = self.run_py([script, "-postarg"])
self.assertEqual("PythonTestSuite", data["SearchInfo.company"])
self.assertEqual("3.100", data["SearchInfo.tag"])
self.assertEqual(f"X.Y.exe -prearg {script} -postarg", data["stdout"].strip())

def test_py2_shebang_nl(self):
with self.py_ini(TEST_PY_COMMANDS):
with self.py_ini(TEST_PY_DEFAULTS):
with self.script("#! /usr/bin/python2 -prearg\n") as script:
data = self.run_py([script, "-postarg"])
self.assertEqual("PythonTestSuite", data["SearchInfo.company"])
self.assertEqual("3.100-32", data["SearchInfo.tag"])
self.assertEqual(f"X.Y-32.exe -prearg {script} -postarg", data["stdout"].strip())

def test_py3_shebang_nl(self):
with self.py_ini(TEST_PY_COMMANDS):
with self.py_ini(TEST_PY_DEFAULTS):
with self.script("#! /usr/bin/python3 -prearg\n") as script:
data = self.run_py([script, "-postarg"])
self.assertEqual("PythonTestSuite", data["SearchInfo.company"])
self.assertEqual("3.100-arm64", data["SearchInfo.tag"])
self.assertEqual(f"X.Y-arm64.exe -X fake_arg_for_test -prearg {script} -postarg", data["stdout"].strip())

def test_py_shebang_short_argv0(self):
with self.py_ini(TEST_PY_COMMANDS):
with self.py_ini(TEST_PY_DEFAULTS):
with self.script("#! /usr/bin/python -prearg") as script:
# Override argv to only pass "py.exe" as the command
data = self.run_py([script, "-postarg"], argv=f'"py.exe" "{script}" -postarg')
Expand All @@ -591,7 +596,7 @@ def test_py_handle_64_in_ini(self):

def test_search_path(self):
stem = Path(sys.executable).stem
with self.py_ini(TEST_PY_COMMANDS):
with self.py_ini(TEST_PY_DEFAULTS):
with self.script(f"#! /usr/bin/env {stem} -prearg") as script:
data = self.run_py(
[script, "-postarg"],
Expand All @@ -602,7 +607,7 @@ def test_search_path(self):
def test_search_path_exe(self):
# Leave the .exe on the name to ensure we don't add it a second time
name = Path(sys.executable).name
with self.py_ini(TEST_PY_COMMANDS):
with self.py_ini(TEST_PY_DEFAULTS):
with self.script(f"#! /usr/bin/env {name} -prearg") as script:
data = self.run_py(
[script, "-postarg"],
Expand All @@ -612,7 +617,7 @@ def test_search_path_exe(self):

def test_recursive_search_path(self):
stem = self.get_py_exe().stem
with self.py_ini(TEST_PY_COMMANDS):
with self.py_ini(TEST_PY_DEFAULTS):
with self.script(f"#! /usr/bin/env {stem}") as script:
data = self.run_py(
[script],
Expand Down Expand Up @@ -673,3 +678,21 @@ def test_literal_shebang_quoted_escape(self):
f'"{script.parent}\\some\\ random app" -witharg {script}',
data["stdout"].strip(),
)

def test_literal_shebang_command(self):
with self.py_ini(TEST_PY_COMMANDS):
with self.script('#! test-command arg1') as script:
data = self.run_py([script])
self.assertEqual(
f"TEST_EXE.exe arg1 {script}",
data["stdout"].strip(),
)

def test_literal_shebang_invalid_template(self):
with self.script('#! /usr/bin/not-python arg1') as script:
data = self.run_py([script])
expect = Path.cwd() / "/usr/bin/not-python"
self.assertEqual(
f"{expect} arg1 {script}",
data["stdout"].strip(),
)
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
Restores support for the :file:`py.exe` launcher finding shebang commands in
its configuration file using the full command name.
Loading