diff --git a/Lib/test/test_subprocess.py b/Lib/test/test_subprocess.py --- a/Lib/test/test_subprocess.py +++ b/Lib/test/test_subprocess.py @@ -191,9 +191,52 @@ p.wait() self.assertEqual(p.stderr, None) + def test_cwd(self): + tmpdir = tempfile.gettempdir() + # We cannot use os.path.realpath to canonicalize the path, + # since it doesn't expand Tru64 {memb} strings. See bug 1063571. + cwd = os.getcwd() + os.chdir(tmpdir) + tmpdir = os.getcwd() + os.chdir(cwd) + p = subprocess.Popen([sys.executable, "-c", + 'import sys,os;' + 'sys.stdout.write(os.getcwd())'], + stdout=subprocess.PIPE, + cwd=tmpdir) + self.addCleanup(p.stdout.close) + normcase = os.path.normcase + self.assertEqual(normcase(p.stdout.read().decode("utf-8")), + normcase(tmpdir)) + @unittest.skipIf(sys.base_prefix != sys.prefix, 'Test is not venv-compatible') - def test_executable_with_cwd(self): + def test_cwd_wrong(self): + # Check that Popen looks for args[0] relative to cwd (failing case). + python_path = os.path.realpath(sys.executable) + python_dir, python_base = os.path.split(python_path) + wrong_cwd = os.path.join(python_dir, 'Doc') + self.assertRaises(FileNotFoundError, subprocess.Popen, + [python_base], cwd=wrong_cwd) + + @unittest.skipIf(sys.base_prefix != sys.prefix, + 'Test is not venv-compatible') + def test_cwd_with_relative_arg(self): + # Check that Popen looks for args[0] relative to cwd (succeeding case). + python_path = os.path.realpath(sys.executable) + python_dir, python_base = os.path.split(python_path) + wrong_cwd = os.path.join(python_dir, 'Doc') + relative_python = os.path.join(os.pardir, python_base) + p = subprocess.Popen([relative_python, "-c", + "import sys; sys.exit(47)"], cwd=wrong_cwd) + p.wait() + self.assertEqual(p.returncode, 47) + + @unittest.skipIf(sys.base_prefix != sys.prefix, + 'Test is not venv-compatible') + def test_cwd_with_absolute_executable(self): + # Check that an absolute path for executable works with cwd (and that + # executable takes precedence over args[0]). python_dir = os.path.dirname(os.path.realpath(sys.executable)) p = subprocess.Popen(["somethingyoudonthave", "-c", "import sys; sys.exit(47)"], @@ -203,6 +246,21 @@ @unittest.skipIf(sys.base_prefix != sys.prefix, 'Test is not venv-compatible') + def test_cwd_with_relative_executable(self): + # Check that Popen looks for executable relative to cwd (and that + # executable takes precedence over args[0]). + python_path = os.path.realpath(sys.executable) + python_dir, python_base = os.path.split(python_path) + wrong_cwd = os.path.join(python_dir, 'Doc') + relative_python = os.path.join(os.pardir, python_base) + p = subprocess.Popen(["somethingyoudonthave", "-c", + "import sys; sys.exit(47)"], + executable=relative_python, cwd=wrong_cwd) + p.wait() + self.assertEqual(p.returncode, 47) + + @unittest.skipIf(sys.base_prefix != sys.prefix, + 'Test is not venv-compatible') @unittest.skipIf(sysconfig.is_python_build(), "need an installed Python. See #7774") def test_executable_without_cwd(self): @@ -369,24 +427,6 @@ p.wait() self.assertEqual(p.stdin, None) - def test_cwd(self): - tmpdir = tempfile.gettempdir() - # We cannot use os.path.realpath to canonicalize the path, - # since it doesn't expand Tru64 {memb} strings. See bug 1063571. - cwd = os.getcwd() - os.chdir(tmpdir) - tmpdir = os.getcwd() - os.chdir(cwd) - p = subprocess.Popen([sys.executable, "-c", - 'import sys,os;' - 'sys.stdout.write(os.getcwd())'], - stdout=subprocess.PIPE, - cwd=tmpdir) - self.addCleanup(p.stdout.close) - normcase = os.path.normcase - self.assertEqual(normcase(p.stdout.read().decode("utf-8")), - normcase(tmpdir)) - def test_env(self): newenv = os.environ.copy() newenv["FRUIT"] = "orange"