From 77732be801c18013cfbc86e27fcc50194ca22c8e Mon Sep 17 00:00:00 2001 From: Serhiy Storchaka Date: Wed, 4 Oct 2017 20:25:40 +0300 Subject: [PATCH] bpo-30404: The -u option now makes the stdout and stderr streams totally unbuffered. (#1667) --- Doc/using/cmdline.rst | 8 ++++---- Lib/test/test_cmd_line.py | 7 +++---- .../2017-10-03-23-46-39.bpo-30404._9Yi5u.rst | 2 ++ Python/pylifecycle.c | 12 ++++++++---- 4 files changed, 17 insertions(+), 12 deletions(-) create mode 100644 Misc/NEWS.d/next/Core and Builtins/2017-10-03-23-46-39.bpo-30404._9Yi5u.rst diff --git a/Doc/using/cmdline.rst b/Doc/using/cmdline.rst index 9c1c269d1df..7b60a9b71fe 100644 --- a/Doc/using/cmdline.rst +++ b/Doc/using/cmdline.rst @@ -303,13 +303,13 @@ Miscellaneous options .. cmdoption:: -u - Force the binary layer of the stdout and stderr streams (which is - available as their ``buffer`` attribute) to be unbuffered. The text I/O - layer will still be line-buffered if writing to the console, or - block-buffered if redirected to a non-interactive file. + Force the stdout and stderr streams to be unbuffered. See also :envvar:`PYTHONUNBUFFERED`. + .. versionchanged:: 3.7 + The text layer of the stdout and stderr streams now is unbuffered. + .. cmdoption:: -v diff --git a/Lib/test/test_cmd_line.py b/Lib/test/test_cmd_line.py index 3e204279173..28ddb2ba1bf 100644 --- a/Lib/test/test_cmd_line.py +++ b/Lib/test/test_cmd_line.py @@ -221,13 +221,12 @@ class CmdLineTest(unittest.TestCase): rc, out, err = assert_python_ok('-u', '-c', code) data = err if stream == 'stderr' else out self.assertEqual(data, b'x', "binary %s not unbuffered" % stream) - # Text is line-buffered - code = ("import os, sys; sys.%s.write('x\\n'); os._exit(0)" + # Text is unbuffered + code = ("import os, sys; sys.%s.write('x'); os._exit(0)" % stream) rc, out, err = assert_python_ok('-u', '-c', code) data = err if stream == 'stderr' else out - self.assertEqual(data.strip(), b'x', - "text %s not line-buffered" % stream) + self.assertEqual(data, b'x', "text %s not unbuffered" % stream) def test_unbuffered_input(self): # sys.stdin still works with '-u' diff --git a/Misc/NEWS.d/next/Core and Builtins/2017-10-03-23-46-39.bpo-30404._9Yi5u.rst b/Misc/NEWS.d/next/Core and Builtins/2017-10-03-23-46-39.bpo-30404._9Yi5u.rst new file mode 100644 index 00000000000..6c2802077f0 --- /dev/null +++ b/Misc/NEWS.d/next/Core and Builtins/2017-10-03-23-46-39.bpo-30404._9Yi5u.rst @@ -0,0 +1,2 @@ +The -u option now makes the stdout and stderr streams unbuffered rather than +line-buffered. diff --git a/Python/pylifecycle.c b/Python/pylifecycle.c index 4b0383b4292..5b13bc45822 100644 --- a/Python/pylifecycle.c +++ b/Python/pylifecycle.c @@ -1498,7 +1498,7 @@ create_stdio(PyObject* io, PyObject *buf = NULL, *stream = NULL, *text = NULL, *raw = NULL, *res; const char* mode; const char* newline; - PyObject *line_buffering; + PyObject *line_buffering, *write_through; int buffering, isatty; _Py_IDENTIFIER(open); _Py_IDENTIFIER(isatty); @@ -1555,7 +1555,11 @@ create_stdio(PyObject* io, Py_DECREF(res); if (isatty == -1) goto error; - if (isatty || Py_UnbufferedStdioFlag) + if (Py_UnbufferedStdioFlag) + write_through = Py_True; + else + write_through = Py_False; + if (isatty && !Py_UnbufferedStdioFlag) line_buffering = Py_True; else line_buffering = Py_False; @@ -1574,9 +1578,9 @@ create_stdio(PyObject* io, newline = "\n"; #endif - stream = _PyObject_CallMethodId(io, &PyId_TextIOWrapper, "OsssO", + stream = _PyObject_CallMethodId(io, &PyId_TextIOWrapper, "OsssOO", buf, encoding, errors, - newline, line_buffering); + newline, line_buffering, write_through); Py_CLEAR(buf); if (stream == NULL) goto error;