diff options
author | Brian Curtin <brian.curtin@gmail.com> | 2010-12-03 02:46:02 (GMT) |
---|---|---|
committer | Brian Curtin <brian.curtin@gmail.com> | 2010-12-03 02:46:02 (GMT) |
commit | 79cdb661f5a6cf8bba07aa50f4451f6c409bb067 (patch) | |
tree | 951cc547f5023ab2965b790fe01617e19952d3cf /Lib | |
parent | 2d93e6ee637f3ec62114919835a32ed009b99a0b (diff) | |
download | cpython-79cdb661f5a6cf8bba07aa50f4451f6c409bb067.zip cpython-79cdb661f5a6cf8bba07aa50f4451f6c409bb067.tar.gz cpython-79cdb661f5a6cf8bba07aa50f4451f6c409bb067.tar.bz2 |
Fix #10554. Added context manager support to Popen objects.
Added a few common Popen uses to the tests like we've done for a few other
instances of adding context managers. Eventually the entire test suite
could be converted to use the context manager format.
Diffstat (limited to 'Lib')
-rw-r--r-- | Lib/subprocess.py | 10 | ||||
-rw-r--r-- | Lib/test/test_subprocess.py | 44 |
2 files changed, 53 insertions, 1 deletions
diff --git a/Lib/subprocess.py b/Lib/subprocess.py index 192185d..bdbcc6b 100644 --- a/Lib/subprocess.py +++ b/Lib/subprocess.py @@ -697,6 +697,16 @@ class Popen(object): data = data.replace(b"\r\n", b"\n").replace(b"\r", b"\n") return data.decode(encoding) + def __enter__(self): + return self + + def __exit__(self, type, value, traceback): + if self.stdout: + self.stdout.close() + if self.stderr: + self.stderr.close() + if self.stdin: + self.stdin.close() def __del__(self, _maxsize=sys.maxsize, _active=_active): if not self._child_created: diff --git a/Lib/test/test_subprocess.py b/Lib/test/test_subprocess.py index d1812e5..ec1e186 100644 --- a/Lib/test/test_subprocess.py +++ b/Lib/test/test_subprocess.py @@ -1183,6 +1183,47 @@ class CommandsWithSpaces (BaseTestCase): # call() function with sequence argument with spaces on Windows self.with_spaces([sys.executable, self.fname, "ab cd"]) + +class ContextManagerTests(ProcessTestCase): + + def test_pipe(self): + with subprocess.Popen([sys.executable, "-c", + "import sys;" + "sys.stdout.write('stdout');" + "sys.stderr.write('stderr');"], + stdout=subprocess.PIPE, + stderr=subprocess.PIPE) as proc: + self.assertEqual(proc.stdout.read(), b"stdout") + self.assertStderrEqual(proc.stderr.read(), b"stderr") + + self.assertTrue(proc.stdout.closed) + self.assertTrue(proc.stderr.closed) + + def test_returncode(self): + with subprocess.Popen([sys.executable, "-c", + "import sys; sys.exit(100)"]) as proc: + proc.wait() + self.assertEqual(proc.returncode, 100) + + def test_communicate_stdin(self): + with subprocess.Popen([sys.executable, "-c", + "import sys;" + "sys.exit(sys.stdin.read() == 'context')"], + stdin=subprocess.PIPE) as proc: + proc.communicate(b"context") + self.assertEqual(proc.returncode, 1) + + def test_invalid_args(self): + with self.assertRaises(EnvironmentError) as c: + with subprocess.Popen(['nonexisting_i_hope'], + stdout=subprocess.PIPE, + stderr=subprocess.PIPE) as proc: + pass + + if c.exception.errno != errno.ENOENT: # ignore "no such file" + raise c.exception + + def test_main(): unit_tests = (ProcessTestCase, POSIXProcessTestCase, @@ -1191,7 +1232,8 @@ def test_main(): CommandTests, ProcessTestCaseNoPoll, HelperFunctionTests, - CommandsWithSpaces) + CommandsWithSpaces, + ContextManagerTests) support.run_unittest(*unit_tests) support.reap_children() |