diff options
author | Benjamin Peterson <benjamin@python.org> | 2012-10-10 18:10:44 (GMT) |
---|---|---|
committer | Benjamin Peterson <benjamin@python.org> | 2012-10-10 18:10:44 (GMT) |
commit | b36a05094d16bfb86c1b113bcab769ca6dbeee7a (patch) | |
tree | b137758b30fa94c2b3f4a5388b69128d159bdaf9 /Lib | |
parent | 00f86f2202ca7dc78604b387ae61e269b90f0079 (diff) | |
parent | db8570349e3a3d02e3fe4300232c3b1ecd9c8259 (diff) | |
download | cpython-b36a05094d16bfb86c1b113bcab769ca6dbeee7a.zip cpython-b36a05094d16bfb86c1b113bcab769ca6dbeee7a.tar.gz cpython-b36a05094d16bfb86c1b113bcab769ca6dbeee7a.tar.bz2 |
merge heads
Diffstat (limited to 'Lib')
-rw-r--r-- | Lib/subprocess.py | 10 | ||||
-rw-r--r-- | Lib/test/test_subprocess.py | 60 |
2 files changed, 57 insertions, 13 deletions
diff --git a/Lib/subprocess.py b/Lib/subprocess.py index 775db50..57cc1a4 100644 --- a/Lib/subprocess.py +++ b/Lib/subprocess.py @@ -1327,6 +1327,7 @@ class Popen(object): if executable is None: executable = args[0] + orig_executable = executable # For transferring possible exec failure from child to parent. # Data format: "exception name:hex errno:description" @@ -1409,10 +1410,17 @@ class Popen(object): err_msg = err_msg.decode(errors="surrogatepass") if issubclass(child_exception_type, OSError) and hex_errno: errno_num = int(hex_errno, 16) + child_exec_never_called = (err_msg == "noexec") + if child_exec_never_called: + err_msg = "" if errno_num != 0: err_msg = os.strerror(errno_num) if errno_num == errno.ENOENT: - err_msg += ': ' + repr(args[0]) + if child_exec_never_called: + # The error must be from chdir(cwd). + err_msg += ': ' + repr(cwd) + else: + err_msg += ': ' + repr(orig_executable) raise child_exception_type(errno_num, err_msg) raise child_exception_type(err_msg) diff --git a/Lib/test/test_subprocess.py b/Lib/test/test_subprocess.py index 07e2b4b..b260c81 100644 --- a/Lib/test/test_subprocess.py +++ b/Lib/test/test_subprocess.py @@ -200,13 +200,16 @@ class ProcessTestCase(BaseTestCase): p.wait() self.assertEqual(47, p.returncode) - # TODO: make this test work on Linux. - # This may be failing on Linux because of issue #7774. - @unittest.skipIf(sys.platform not in ('win32', 'darwin'), - "possible bug using executable argument on Linux") def test_executable(self): # Check that the executable argument works. - self._assert_python(["doesnotexist", "-c"], executable=sys.executable) + # + # On Unix (non-Mac and non-Windows), Python looks at args[0] to + # determine where its standard library is, so we need the directory + # of args[0] to be valid for the Popen() call to Python to succeed. + # See also issue #16170 and issue #7774. + doesnotexist = os.path.join(os.path.dirname(sys.executable), + "doesnotexist") + self._assert_python([doesnotexist, "-c"], executable=sys.executable) def test_executable_takes_precedence(self): # Check that the executable argument takes precedence over args[0]. @@ -1035,24 +1038,30 @@ class _SuppressCoreFiles(object): @unittest.skipIf(mswindows, "POSIX specific tests") class POSIXProcessTestCase(BaseTestCase): - def test_exceptions(self): - nonexistent_dir = "/_this/pa.th/does/not/exist" + def setUp(self): + super().setUp() + self._nonexistent_dir = "/_this/pa.th/does/not/exist" + + def _get_chdir_exception(self): try: - os.chdir(nonexistent_dir) + os.chdir(self._nonexistent_dir) except OSError as e: # This avoids hard coding the errno value or the OS perror() # string and instead capture the exception that we want to see # below for comparison. desired_exception = e - desired_exception.strerror += ': ' + repr(sys.executable) + desired_exception.strerror += ': ' + repr(self._nonexistent_dir) else: self.fail("chdir to nonexistant directory %s succeeded." % - nonexistent_dir) + self._nonexistent_dir) + return desired_exception - # Error in the child re-raised in the parent. + def test_exception_cwd(self): + """Test error in the child raised in the parent for a bad cwd.""" + desired_exception = self._get_chdir_exception() try: p = subprocess.Popen([sys.executable, "-c", ""], - cwd=nonexistent_dir) + cwd=self._nonexistent_dir) except OSError as e: # Test that the child process chdir failure actually makes # it up to the parent process as the correct exception. @@ -1061,6 +1070,33 @@ class POSIXProcessTestCase(BaseTestCase): else: self.fail("Expected OSError: %s" % desired_exception) + def test_exception_bad_executable(self): + """Test error in the child raised in the parent for a bad executable.""" + desired_exception = self._get_chdir_exception() + try: + p = subprocess.Popen([sys.executable, "-c", ""], + executable=self._nonexistent_dir) + except OSError as e: + # Test that the child process exec failure actually makes + # it up to the parent process as the correct exception. + self.assertEqual(desired_exception.errno, e.errno) + self.assertEqual(desired_exception.strerror, e.strerror) + else: + self.fail("Expected OSError: %s" % desired_exception) + + def test_exception_bad_args_0(self): + """Test error in the child raised in the parent for a bad args[0].""" + desired_exception = self._get_chdir_exception() + try: + p = subprocess.Popen([self._nonexistent_dir, "-c", ""]) + except OSError as e: + # Test that the child process exec failure actually makes + # it up to the parent process as the correct exception. + self.assertEqual(desired_exception.errno, e.errno) + self.assertEqual(desired_exception.strerror, e.strerror) + else: + self.fail("Expected OSError: %s" % desired_exception) + def test_restore_signals(self): # Code coverage for both values of restore_signals to make sure it # at least does not blow up. |