]> git.ipfire.org Git - thirdparty/Python/cpython.git/commitdiff
gh-95285: py.exe launcher fails with short argv0 (GH-95295)
authorSteve Dower <steve.dower@python.org>
Tue, 26 Jul 2022 20:24:44 +0000 (21:24 +0100)
committerGitHub <noreply@github.com>
Tue, 26 Jul 2022 20:24:44 +0000 (21:24 +0100)
Lib/test/test_launcher.py
Misc/NEWS.d/next/Windows/2022-07-26-20-33-12.gh-issue-95285.w6fa22.rst [new file with mode: 0644]
PC/launcher2.c

index 50a2e8c03d6473f655a7a362b12baa321bb70031..b4009a99a705afd652c4a2741a6c7ee4b2b43e57 100644 (file)
@@ -149,7 +149,7 @@ class RunPyMixin:
     @classmethod
     def find_py(cls):
         py_exe = None
-        if sysconfig.is_python_build(True):
+        if sysconfig.is_python_build():
             py_exe = Path(sys.executable).parent / PY_EXE
         else:
             for p in os.getenv("PATH").split(";"):
@@ -187,7 +187,7 @@ class RunPyMixin:
             )
         return py_exe
 
-    def run_py(self, args, env=None, allow_fail=False, expect_returncode=0):
+    def run_py(self, args, env=None, allow_fail=False, expect_returncode=0, argv=None):
         if not self.py_exe:
             self.py_exe = self.find_py()
 
@@ -198,9 +198,12 @@ class RunPyMixin:
             "PYLAUNCHER_DEBUG": "1",
             "PYLAUNCHER_DRYRUN": "1",
         }
+        if not argv:
+            argv = [self.py_exe, *args]
         with subprocess.Popen(
-            [self.py_exe, *args],
+            argv,
             env=env,
+            executable=self.py_exe,
             stdin=subprocess.PIPE,
             stdout=subprocess.PIPE,
             stderr=subprocess.PIPE,
@@ -539,6 +542,15 @@ class TestLauncher(unittest.TestCase, RunPyMixin):
         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.script("#! /usr/bin/env 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')
+        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_install(self):
         data = self.run_py(["-V:3.10"], env={"PYLAUNCHER_ALWAYS_INSTALL": "1"}, expect_returncode=111)
         cmd = data["stdout"].strip()
diff --git a/Misc/NEWS.d/next/Windows/2022-07-26-20-33-12.gh-issue-95285.w6fa22.rst b/Misc/NEWS.d/next/Windows/2022-07-26-20-33-12.gh-issue-95285.w6fa22.rst
new file mode 100644 (file)
index 0000000..76b38e7
--- /dev/null
@@ -0,0 +1,2 @@
+Fix :ref:`launcher` handling of command lines where it is only passed a
+short executable name.
index c8ed1b0f7c8a6d1f2f10b7928a924729a961b796..31b5617771e9b973b26b0eed13ffb5e7b0b2c035 100644 (file)
@@ -580,6 +580,9 @@ parseCommandLine(SearchInfo *search)
             break;
         }
     }
+    if (tail == search->originalCmdLine && tail[0] == L'"') {
+        ++tail;
+    }
     // Without special cases, we can now fill in the search struct
     int tailLen = (int)(end ? (end - tail) : wcsnlen_s(tail, MAXLEN));
     search->executableLength = -1;