bpo-42388: Fix subprocess.check_output input=None when text=True (GH-23467)
When the modern text= spelling of the universal_newlines= parameter was added
for Python 3.7, check_output's special case around input=None was overlooked.
So it behaved differently with universal_newlines=True vs text=True. This
reconciles the behavior to be consistent and adds a test to guarantee it.
Also clarifies the existing check_output documentation.
Co-authored-by: Alexey Izbyshev <izbyshev@ispras.ru>
(cherry picked from commit 64abf37344
)
Co-authored-by: Gregory P. Smith <greg@krypto.org>
This commit is contained in:
parent
efd64c8ea0
commit
d5aadb2854
|
@ -1127,8 +1127,9 @@ calls these functions.
|
||||||
The arguments shown above are merely some common ones.
|
The arguments shown above are merely some common ones.
|
||||||
The full function signature is largely the same as that of :func:`run` -
|
The full function signature is largely the same as that of :func:`run` -
|
||||||
most arguments are passed directly through to that interface.
|
most arguments are passed directly through to that interface.
|
||||||
However, explicitly passing ``input=None`` to inherit the parent's
|
One API deviation from :func:`run` behavior exists: passing ``input=None``
|
||||||
standard input file handle is not supported.
|
will behave the same as ``input=b''`` (or ``input=''``, depending on other
|
||||||
|
arguments) rather than using the parent's standard input file handle.
|
||||||
|
|
||||||
By default, this function will return the data as encoded bytes. The actual
|
By default, this function will return the data as encoded bytes. The actual
|
||||||
encoding of the output data may depend on the command being invoked, so the
|
encoding of the output data may depend on the command being invoked, so the
|
||||||
|
|
|
@ -406,7 +406,11 @@ def check_output(*popenargs, timeout=None, **kwargs):
|
||||||
if 'input' in kwargs and kwargs['input'] is None:
|
if 'input' in kwargs and kwargs['input'] is None:
|
||||||
# Explicitly passing input=None was previously equivalent to passing an
|
# Explicitly passing input=None was previously equivalent to passing an
|
||||||
# empty string. That is maintained here for backwards compatibility.
|
# empty string. That is maintained here for backwards compatibility.
|
||||||
kwargs['input'] = '' if kwargs.get('universal_newlines', False) else b''
|
if kwargs.get('universal_newlines') or kwargs.get('text'):
|
||||||
|
empty = ''
|
||||||
|
else:
|
||||||
|
empty = b''
|
||||||
|
kwargs['input'] = empty
|
||||||
|
|
||||||
return run(*popenargs, stdout=PIPE, timeout=timeout, check=True,
|
return run(*popenargs, stdout=PIPE, timeout=timeout, check=True,
|
||||||
**kwargs).stdout
|
**kwargs).stdout
|
||||||
|
|
|
@ -195,6 +195,28 @@ class ProcessTestCase(BaseTestCase):
|
||||||
input=b'pear')
|
input=b'pear')
|
||||||
self.assertIn(b'PEAR', output)
|
self.assertIn(b'PEAR', output)
|
||||||
|
|
||||||
|
def test_check_output_input_none(self):
|
||||||
|
"""input=None has a legacy meaning of input='' on check_output."""
|
||||||
|
output = subprocess.check_output(
|
||||||
|
[sys.executable, "-c",
|
||||||
|
"import sys; print('XX' if sys.stdin.read() else '')"],
|
||||||
|
input=None)
|
||||||
|
self.assertNotIn(b'XX', output)
|
||||||
|
|
||||||
|
def test_check_output_input_none_text(self):
|
||||||
|
output = subprocess.check_output(
|
||||||
|
[sys.executable, "-c",
|
||||||
|
"import sys; print('XX' if sys.stdin.read() else '')"],
|
||||||
|
input=None, text=True)
|
||||||
|
self.assertNotIn('XX', output)
|
||||||
|
|
||||||
|
def test_check_output_input_none_universal_newlines(self):
|
||||||
|
output = subprocess.check_output(
|
||||||
|
[sys.executable, "-c",
|
||||||
|
"import sys; print('XX' if sys.stdin.read() else '')"],
|
||||||
|
input=None, universal_newlines=True)
|
||||||
|
self.assertNotIn('XX', output)
|
||||||
|
|
||||||
def test_check_output_stdout_arg(self):
|
def test_check_output_stdout_arg(self):
|
||||||
# check_output() refuses to accept 'stdout' argument
|
# check_output() refuses to accept 'stdout' argument
|
||||||
with self.assertRaises(ValueError) as c:
|
with self.assertRaises(ValueError) as c:
|
||||||
|
|
|
@ -0,0 +1,2 @@
|
||||||
|
Fix subprocess.check_output(..., input=None) behavior when text=True to be
|
||||||
|
consistent with that of the documentation and universal_newlines=True.
|
Loading…
Reference in New Issue