From 05da5530605f937d0f2b4924020929739a380ec9 Mon Sep 17 00:00:00 2001 From: "Gregory P. Smith" Date: Thu, 24 Aug 2017 14:58:25 -0700 Subject: [PATCH 1/2] [3.6] bpo-22536: Set the filename in FileNotFoundError. (GH-3194) Have the subprocess module set the filename in the FileNotFoundError exception raised on POSIX systems when the executable or cwd are missing. (cherry picked from commit 8621bb5d93239316f97281826461b85072ff6db7) --- Lib/subprocess.py | 12 ++++++------ Lib/test/test_subprocess.py | 10 ++++++++++ .../next/Library/2017-08-23.bpo-22536._narf_.rst | 2 ++ 3 files changed, 18 insertions(+), 6 deletions(-) create mode 100644 Misc/NEWS.d/next/Library/2017-08-23.bpo-22536._narf_.rst diff --git a/Lib/subprocess.py b/Lib/subprocess.py index e0a93c55dc0f18..d0132342462b1e 100644 --- a/Lib/subprocess.py +++ b/Lib/subprocess.py @@ -1328,15 +1328,15 @@ def _execute_child(self, args, executable, preexec_fn, close_fds, child_exec_never_called = (err_msg == "noexec") if child_exec_never_called: err_msg = "" + # The error must be from chdir(cwd). + err_filename = cwd + else: + err_filename = orig_executable if errno_num != 0: err_msg = os.strerror(errno_num) if errno_num == errno.ENOENT: - 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) + err_msg += ': ' + repr(err_filename) + raise child_exception_type(errno_num, err_msg, err_filename) raise child_exception_type(err_msg) diff --git a/Lib/test/test_subprocess.py b/Lib/test/test_subprocess.py index ccdd3232700470..1a8147b222b310 100644 --- a/Lib/test/test_subprocess.py +++ b/Lib/test/test_subprocess.py @@ -1375,6 +1375,16 @@ def test_failed_child_execute_fd_leak(self): fds_after_exception = os.listdir(fd_directory) self.assertEqual(fds_before_popen, fds_after_exception) + def test_file_not_found_includes_filename(self): + with self.assertRaises(FileNotFoundError) as c: + subprocess.call(['/opt/nonexistent_binary', 'with', 'some', 'args']) + self.assertEqual(c.exception.filename, '/opt/nonexistent_binary') + + def test_file_not_found_with_bad_cwd(self): + with self.assertRaises(FileNotFoundError) as c: + subprocess.Popen(['exit', '0'], cwd='/some/nonexistent/directory') + self.assertEqual(c.exception.filename, '/some/nonexistent/directory') + class RunFuncTestCase(BaseTestCase): def run_python(self, code, **kwargs): diff --git a/Misc/NEWS.d/next/Library/2017-08-23.bpo-22536._narf_.rst b/Misc/NEWS.d/next/Library/2017-08-23.bpo-22536._narf_.rst new file mode 100644 index 00000000000000..bd238f95b8a9a9 --- /dev/null +++ b/Misc/NEWS.d/next/Library/2017-08-23.bpo-22536._narf_.rst @@ -0,0 +1,2 @@ +The subprocess module now sets the filename when FileNotFoundError +is raised on POSIX systems due to the executable or cwd not being found. From 92929c488f028bdff76b44409af88fef64651ebf Mon Sep 17 00:00:00 2001 From: "Gregory P. Smith" Date: Mon, 4 Sep 2017 13:49:46 -0700 Subject: [PATCH 2/2] bpo-22536 [3.6] (GH-3202) skip non-windows tests. --- Lib/test/test_subprocess.py | 2 ++ 1 file changed, 2 insertions(+) diff --git a/Lib/test/test_subprocess.py b/Lib/test/test_subprocess.py index 1a8147b222b310..83abe9d67f7a20 100644 --- a/Lib/test/test_subprocess.py +++ b/Lib/test/test_subprocess.py @@ -1375,11 +1375,13 @@ def test_failed_child_execute_fd_leak(self): fds_after_exception = os.listdir(fd_directory) self.assertEqual(fds_before_popen, fds_after_exception) + @unittest.skipIf(mswindows, "behavior currently not supported on Windows") def test_file_not_found_includes_filename(self): with self.assertRaises(FileNotFoundError) as c: subprocess.call(['/opt/nonexistent_binary', 'with', 'some', 'args']) self.assertEqual(c.exception.filename, '/opt/nonexistent_binary') + @unittest.skipIf(mswindows, "behavior currently not supported on Windows") def test_file_not_found_with_bad_cwd(self): with self.assertRaises(FileNotFoundError) as c: subprocess.Popen(['exit', '0'], cwd='/some/nonexistent/directory')