summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorVictor Stinner <victor.stinner@gmail.com>2014-02-11 10:44:56 (GMT)
committerVictor Stinner <victor.stinner@gmail.com>2014-02-11 10:44:56 (GMT)
commit20e0743a5603479c56f32209b77a8bfac87baf53 (patch)
tree1f230143345bdd0f7f1c7ab8f8e6d55d6c3ace56
parent9af4a246f9b87d859a6f72e2a10b40614ad07030 (diff)
downloadcpython-20e0743a5603479c56f32209b77a8bfac87baf53.zip
cpython-20e0743a5603479c56f32209b77a8bfac87baf53.tar.gz
cpython-20e0743a5603479c56f32209b77a8bfac87baf53.tar.bz2
asyncio, Tulip issue 130: Add more checks on subprocess_exec/subprocess_shell
parameters
-rw-r--r--Lib/asyncio/base_events.py12
-rw-r--r--Lib/asyncio/subprocess.py5
-rw-r--r--Lib/test/test_asyncio/test_base_events.py54
3 files changed, 64 insertions, 7 deletions
diff --git a/Lib/asyncio/base_events.py b/Lib/asyncio/base_events.py
index 4b7b161..5765f47 100644
--- a/Lib/asyncio/base_events.py
+++ b/Lib/asyncio/base_events.py
@@ -558,7 +558,7 @@ class BaseEventLoop(events.AbstractEventLoop):
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 @@ class BaseEventLoop(events.AbstractEventLoop):
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 @@ class BaseEventLoop(events.AbstractEventLoop):
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
index 848d64f..8d1a407 100644
--- a/Lib/asyncio/subprocess.py
+++ b/Lib/asyncio/subprocess.py
@@ -180,7 +180,7 @@ def create_subprocess_shell(cmd, stdin=None, stdout=None, stderr=None,
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 @@ def create_subprocess_exec(*args, stdin=None, stdout=None, stderr=None,
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
index c6950ab..94e2d59 100644
--- 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 @@ class BaseEventLoopTests(unittest.TestCase):
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):