asyncio, Tulip issue 130: Add more checks on subprocess_exec/subprocess_shell
parameters
This commit is contained in:
parent
a125497ea3
commit
4e8d2f25e2
|
@ -558,7 +558,7 @@ class BaseEventLoop(events.AbstractEventLoop):
|
||||||
stdout=subprocess.PIPE, stderr=subprocess.PIPE,
|
stdout=subprocess.PIPE, stderr=subprocess.PIPE,
|
||||||
universal_newlines=False, shell=True, bufsize=0,
|
universal_newlines=False, shell=True, bufsize=0,
|
||||||
**kwargs):
|
**kwargs):
|
||||||
if not isinstance(cmd, str):
|
if not isinstance(cmd, (bytes, str)):
|
||||||
raise ValueError("cmd must be a string")
|
raise ValueError("cmd must be a string")
|
||||||
if universal_newlines:
|
if universal_newlines:
|
||||||
raise ValueError("universal_newlines must be False")
|
raise ValueError("universal_newlines must be False")
|
||||||
|
@ -572,7 +572,7 @@ class BaseEventLoop(events.AbstractEventLoop):
|
||||||
return transport, protocol
|
return transport, protocol
|
||||||
|
|
||||||
@tasks.coroutine
|
@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,
|
stdout=subprocess.PIPE, stderr=subprocess.PIPE,
|
||||||
universal_newlines=False, shell=False, bufsize=0,
|
universal_newlines=False, shell=False, bufsize=0,
|
||||||
**kwargs):
|
**kwargs):
|
||||||
|
@ -582,9 +582,15 @@ class BaseEventLoop(events.AbstractEventLoop):
|
||||||
raise ValueError("shell must be False")
|
raise ValueError("shell must be False")
|
||||||
if bufsize != 0:
|
if bufsize != 0:
|
||||||
raise ValueError("bufsize must be 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()
|
protocol = protocol_factory()
|
||||||
transport = yield from self._make_subprocess_transport(
|
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
|
return transport, protocol
|
||||||
|
|
||||||
def _add_callback(self, handle):
|
def _add_callback(self, handle):
|
||||||
|
|
|
@ -180,7 +180,7 @@ def create_subprocess_shell(cmd, stdin=None, stdout=None, stderr=None,
|
||||||
return Process(transport, protocol, loop)
|
return Process(transport, protocol, loop)
|
||||||
|
|
||||||
@tasks.coroutine
|
@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):
|
loop=None, limit=streams._DEFAULT_LIMIT, **kwds):
|
||||||
if loop is None:
|
if loop is None:
|
||||||
loop = events.get_event_loop()
|
loop = events.get_event_loop()
|
||||||
|
@ -188,7 +188,8 @@ def create_subprocess_exec(*args, stdin=None, stdout=None, stderr=None,
|
||||||
loop=loop)
|
loop=loop)
|
||||||
transport, protocol = yield from loop.subprocess_exec(
|
transport, protocol = yield from loop.subprocess_exec(
|
||||||
protocol_factory,
|
protocol_factory,
|
||||||
*args, stdin=stdin, stdout=stdout,
|
program, *args,
|
||||||
|
stdin=stdin, stdout=stdout,
|
||||||
stderr=stderr, **kwds)
|
stderr=stderr, **kwds)
|
||||||
yield from protocol.waiter
|
yield from protocol.waiter
|
||||||
return Process(transport, protocol, loop)
|
return Process(transport, protocol, loop)
|
||||||
|
|
|
@ -3,6 +3,7 @@
|
||||||
import errno
|
import errno
|
||||||
import logging
|
import logging
|
||||||
import socket
|
import socket
|
||||||
|
import sys
|
||||||
import time
|
import time
|
||||||
import unittest
|
import unittest
|
||||||
import unittest.mock
|
import unittest.mock
|
||||||
|
@ -234,8 +235,57 @@ class BaseEventLoopTests(unittest.TestCase):
|
||||||
self.assertEqual([handle], list(self.loop._ready))
|
self.assertEqual([handle], list(self.loop._ready))
|
||||||
|
|
||||||
def test_run_until_complete_type_error(self):
|
def test_run_until_complete_type_error(self):
|
||||||
self.assertRaises(
|
self.assertRaises(TypeError,
|
||||||
TypeError, self.loop.run_until_complete, 'blah')
|
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):
|
class MyProto(asyncio.Protocol):
|
||||||
|
|
Loading…
Reference in New Issue