[Python-checkins] cpython: asyncio, Tulip issue 130: Add more checks on subprocess_exec/subprocess_shell

victor.stinner python-checkins at python.org
Tue Feb 11 11:46:07 CET 2014


http://hg.python.org/cpython/rev/f729e9ee5dfc
changeset:   89146:f729e9ee5dfc
user:        Victor Stinner <victor.stinner at gmail.com>
date:        Tue Feb 11 11:44:56 2014 +0100
summary:
  asyncio, Tulip issue 130: Add more checks on subprocess_exec/subprocess_shell
parameters

files:
  Lib/asyncio/base_events.py                |  12 +-
  Lib/asyncio/subprocess.py                 |   5 +-
  Lib/test/test_asyncio/test_base_events.py |  54 ++++++++++-
  3 files changed, 64 insertions(+), 7 deletions(-)


diff --git a/Lib/asyncio/base_events.py b/Lib/asyncio/base_events.py
--- a/Lib/asyncio/base_events.py
+++ b/Lib/asyncio/base_events.py
@@ -558,7 +558,7 @@
                          stdout=subprocess.PIPE, stderr=subprocess.PIPE,
                          universal_newlines=False, shell=True, bufsize=0,
                          **kwargs):
-        if not isinstance(cmd, str):
+        if not isinstance(cmd, (bytes, str)):
             raise ValueError("cmd must be a string")
         if universal_newlines:
             raise ValueError("universal_newlines must be False")
@@ -572,7 +572,7 @@
         return transport, protocol
 
     @tasks.coroutine
-    def subprocess_exec(self, protocol_factory, *args, stdin=subprocess.PIPE,
+    def subprocess_exec(self, protocol_factory, program, *args, stdin=subprocess.PIPE,
                         stdout=subprocess.PIPE, stderr=subprocess.PIPE,
                         universal_newlines=False, shell=False, bufsize=0,
                         **kwargs):
@@ -582,9 +582,15 @@
             raise ValueError("shell must be False")
         if bufsize != 0:
             raise ValueError("bufsize must be 0")
+        popen_args = (program,) + args
+        for arg in popen_args:
+            if not isinstance(arg, (str, bytes)):
+                raise TypeError("program arguments must be "
+                                "a bytes or text string, not %s"
+                                % type(arg).__name__)
         protocol = protocol_factory()
         transport = yield from self._make_subprocess_transport(
-            protocol, args, False, stdin, stdout, stderr, bufsize, **kwargs)
+            protocol, popen_args, False, stdin, stdout, stderr, bufsize, **kwargs)
         return transport, protocol
 
     def _add_callback(self, handle):
diff --git a/Lib/asyncio/subprocess.py b/Lib/asyncio/subprocess.py
--- a/Lib/asyncio/subprocess.py
+++ b/Lib/asyncio/subprocess.py
@@ -180,7 +180,7 @@
     return Process(transport, protocol, loop)
 
 @tasks.coroutine
-def create_subprocess_exec(*args, stdin=None, stdout=None, stderr=None,
+def create_subprocess_exec(program, *args, stdin=None, stdout=None, stderr=None,
                            loop=None, limit=streams._DEFAULT_LIMIT, **kwds):
     if loop is None:
         loop = events.get_event_loop()
@@ -188,7 +188,8 @@
                                                         loop=loop)
     transport, protocol = yield from loop.subprocess_exec(
                                             protocol_factory,
-                                            *args, stdin=stdin, stdout=stdout,
+                                            program, *args,
+                                            stdin=stdin, stdout=stdout,
                                             stderr=stderr, **kwds)
     yield from protocol.waiter
     return Process(transport, protocol, loop)
diff --git a/Lib/test/test_asyncio/test_base_events.py b/Lib/test/test_asyncio/test_base_events.py
--- a/Lib/test/test_asyncio/test_base_events.py
+++ b/Lib/test/test_asyncio/test_base_events.py
@@ -3,6 +3,7 @@
 import errno
 import logging
 import socket
+import sys
 import time
 import unittest
 import unittest.mock
@@ -234,8 +235,57 @@
         self.assertEqual([handle], list(self.loop._ready))
 
     def test_run_until_complete_type_error(self):
-        self.assertRaises(
-            TypeError, self.loop.run_until_complete, 'blah')
+        self.assertRaises(TypeError,
+            self.loop.run_until_complete, 'blah')
+
+    def test_subprocess_exec_invalid_args(self):
+        args = [sys.executable, '-c', 'pass']
+
+        # missing program parameter (empty args)
+        self.assertRaises(TypeError,
+            self.loop.run_until_complete, self.loop.subprocess_exec,
+            asyncio.SubprocessProtocol)
+
+        # exepected multiple arguments, not a list
+        self.assertRaises(TypeError,
+            self.loop.run_until_complete, self.loop.subprocess_exec,
+            asyncio.SubprocessProtocol, args)
+
+        # program arguments must be strings, not int
+        self.assertRaises(TypeError,
+            self.loop.run_until_complete, self.loop.subprocess_exec,
+            asyncio.SubprocessProtocol, sys.executable, 123)
+
+        # universal_newlines, shell, bufsize must not be set
+        self.assertRaises(TypeError,
+        self.loop.run_until_complete, self.loop.subprocess_exec,
+            asyncio.SubprocessProtocol, *args, universal_newlines=True)
+        self.assertRaises(TypeError,
+            self.loop.run_until_complete, self.loop.subprocess_exec,
+            asyncio.SubprocessProtocol, *args, shell=True)
+        self.assertRaises(TypeError,
+            self.loop.run_until_complete, self.loop.subprocess_exec,
+            asyncio.SubprocessProtocol, *args, bufsize=4096)
+
+    def test_subprocess_shell_invalid_args(self):
+        # exepected a string, not an int or a list
+        self.assertRaises(TypeError,
+            self.loop.run_until_complete, self.loop.subprocess_shell,
+            asyncio.SubprocessProtocol, 123)
+        self.assertRaises(TypeError,
+            self.loop.run_until_complete, self.loop.subprocess_shell,
+            asyncio.SubprocessProtocol, [sys.executable, '-c', 'pass'])
+
+        # universal_newlines, shell, bufsize must not be set
+        self.assertRaises(TypeError,
+            self.loop.run_until_complete, self.loop.subprocess_shell,
+            asyncio.SubprocessProtocol, 'exit 0', universal_newlines=True)
+        self.assertRaises(TypeError,
+            self.loop.run_until_complete, self.loop.subprocess_shell,
+            asyncio.SubprocessProtocol, 'exit 0', shell=True)
+        self.assertRaises(TypeError,
+            self.loop.run_until_complete, self.loop.subprocess_shell,
+            asyncio.SubprocessProtocol, 'exit 0', bufsize=4096)
 
 
 class MyProto(asyncio.Protocol):

-- 
Repository URL: http://hg.python.org/cpython


More information about the Python-checkins mailing list