(original) (raw)

diff -r bffa0b8a16e8 Lib/test/test_cmd_line.py --- a/Lib/test/test_cmd_line.py Sun Jul 27 04:07:18 2014 -0400 +++ b/Lib/test/test_cmd_line.py Mon Jul 28 23:44:01 2014 +0200 @@ -3,7 +3,10 @@ # See test_cmd_line_script.py for testing of script execution import test.test_support +import os +import subprocess import sys +import tempfile import unittest from test.script_helper import ( assert_python_ok, assert_python_failure, spawn_python, kill_python, @@ -134,6 +137,48 @@ class CmdLineTest(unittest.TestCase): self.assertEqual(err.splitlines().count(b'Unknown option: -a'), 1) self.assertEqual(b'', out) + def check_input(self, code, expected): + with tempfile.NamedTemporaryFile("wb+") as stdin: + sep = os.linesep + stdin.write(sep.join(('abc', 'def'))) + stdin.flush() + stdin.seek(0) + proc = subprocess.Popen((sys.executable, "-c", code), + stdin=stdin, + stdout=subprocess.PIPE) + stdout, stderr = proc.communicate() + self.assertEqual(stdout.rstrip(), expected) + + def test_stdin_readline(self): + # Issue #11272: check that sys.stdin.readline() replaces '\r\n' by '\n' + # on Windows (sys.stdin is opened in binary mode) + self.check_input( + "import sys; print(repr(sys.stdin.readline()))", + "'abc\\n'") + + def test_builtin_input(self): + # Issue #11272: check that input() strips newlines ('\n' or '\r\n') + self.check_input( + "print(repr(raw_input()))", + "'abc'") + + def test_output_newline(self): + # Issue 13119 Newline for print() should be \r\n on Windows. + code = """if 1: + import sys + print 1 + print 2 + print >>sys.stderr, 3 + print >>sys.stderr, 4""" + rc, out, err = assert_python_ok('-c', code) + + if sys.platform == 'win32': + self.assertEqual('1\r\n2\r\n', out) + self.assertEqual('3\r\n4', err) + else: + self.assertEqual('1\n2\n', out) + self.assertEqual('3\n4', err) + def test_main(): test.test_support.run_unittest(CmdLineTest) diff -r bffa0b8a16e8 Lib/test/test_os.py --- a/Lib/test/test_os.py Sun Jul 27 04:07:18 2014 -0400 +++ b/Lib/test/test_os.py Mon Jul 28 23:44:01 2014 +0200 @@ -64,6 +64,25 @@ class FileTests(unittest.TestCase): new = sys.getrefcount(path) self.assertEqual(old, new) + def write_windows_console(self, *args): + retcode = subprocess.call(args, + # use a new console to not flood the test output + creationflags=subprocess.CREATE_NEW_CONSOLE, + # use a shell to hide the console window (SW_HIDE) + shell=True) + self.assertEqual(retcode, 0) + + @unittest.skipUnless(sys.platform == 'win32', + 'test specific to the Windows console') + def test_write_windows_console(self): + # Issue #11395: the Windows console returns an error (12: not enough + # space error) on writing into stdout if stdout mode is binary and the + # length is greater than 66,000 bytes (or less, depending on heap + # usage). + code = "print('x' * 100000)" + self.write_windows_console(sys.executable, "-c", code) + self.write_windows_console(sys.executable, "-u", "-c", code) + class TemporaryFileTests(unittest.TestCase): def setUp(self): diff -r bffa0b8a16e8 Misc/NEWS --- a/Misc/NEWS Sun Jul 27 04:07:18 2014 -0400 +++ b/Misc/NEWS Mon Jul 28 23:44:01 2014 +0200 @@ -10,6 +10,17 @@ What's New in Python 2.7.9? Core and Builtins ----------------- +- Issue #11272: On Windows, raw_input() now also strips '\r' (and not only + '\n'), not only '\n', and sys.stdin uses universal newline (replace '\r\n' by + '\n'). + +- Issue #11395: On Windows, io.FileIO().write() and os.write() clamp the data + length to 32,767 bytes if the file is a TTY, print() and file.write() write + chunks of 32,767 bytes if the file is a TTY. The Windows console returns an + error (12: not enough space error) on writing into stdout if stdout mode is + binary and the length is greater than 66,000 bytes (or less, depending on + heap usage). + Library ------- diff -r bffa0b8a16e8 Modules/_io/fileio.c --- a/Modules/_io/fileio.c Sun Jul 27 04:07:18 2014 -0400 +++ b/Modules/_io/fileio.c Mon Jul 28 23:44:01 2014 +0200 @@ -677,6 +677,12 @@ fileio_write(fileio *self, PyObject *arg #if defined(MS_WIN64) || defined(MS_WINDOWS) if (len > INT_MAX) len = INT_MAX; + /* Issue #11395: the Windows console returns an error (12: not + enough space error) on writing into stdout if stdout mode is + binary and the length is greater than 66,000 bytes (or less, + depending on heap usage). */ + if (len > 32767 && isatty(self->fd)) + len = 32767; n = write(self->fd, pbuf.buf, (int)len); #else n = write(self->fd, pbuf.buf, len); diff -r bffa0b8a16e8 Modules/posixmodule.c --- a/Modules/posixmodule.c Sun Jul 27 04:07:18 2014 -0400 +++ b/Modules/posixmodule.c Mon Jul 28 23:44:01 2014 +0200 @@ -6777,6 +6777,12 @@ posix_write(PyObject *self, PyObject *ar #if defined(MS_WIN64) || defined(MS_WINDOWS) if (len > INT_MAX) len = INT_MAX; + /* Issue #11395: the Windows console returns an error (12: not + enough space error) on writing into stdout if stdout mode is + binary and the length is greater than 66,000 bytes (or less, + depending on heap usage). */ + if (len > 32767 && isatty(fd)) + len = 32767; size = write(fd, pbuf.buf, (int)len); #else size = write(fd, pbuf.buf, len); diff -r bffa0b8a16e8 Objects/fileobject.c --- a/Objects/fileobject.c Sun Jul 27 04:07:18 2014 -0400 +++ b/Objects/fileobject.c Mon Jul 28 23:44:01 2014 +0200 @@ -1847,6 +1847,16 @@ file_write(PyFileObject *f, PyObject *ar } } f->f_softspace = 0; + +#ifdef MS_WINDOWS + /* Issue #11395: the Windows console returns an error (12: not + enough space error) on writing into stdout if stdout mode is + binary and the length is greater than 66,000 bytes (or less, + depending on heap usage). */ + if (n > 32767 && isatty(fileno(f->f_fp))) + n = 32767; +#endif + FILE_BEGIN_ALLOW_THREADS(f) errno = 0; n2 = fwrite(s, 1, n, f->f_fp); diff -r bffa0b8a16e8 Objects/stringobject.c --- a/Objects/stringobject.c Sun Jul 27 04:07:18 2014 -0400 +++ b/Objects/stringobject.c Mon Jul 28 23:44:01 2014 +0200 @@ -852,7 +852,7 @@ PyString_AsStringAndSize(register PyObje static int string_print(PyStringObject *op, FILE *fp, int flags) { - Py_ssize_t i, str_len; + Py_ssize_t i, str_len, sizemax; char c; int quote; @@ -870,13 +870,28 @@ string_print(PyStringObject *op, FILE *f if (flags & Py_PRINT_RAW) { char *data = op->ob_sval; Py_ssize_t size = Py_SIZE(op); + + /* Very long strings cannot be written atomically. + * But don't write exactly INT_MAX bytes at a time + * to avoid memory aligment issues. + */ + sizemax = INT_MAX & ~0x3FFF; +#if defined(MS_WINDOWS) + /* Issue #11395: the Windows console returns an error (12: not + enough space error) on writing into stdout if stdout mode is + binary and the length is greater than 66,000 bytes (or less, + depending on heap usage). */ + if (isatty(fileno(fp))) + sizemax = 32767; +#endif + Py_BEGIN_ALLOW_THREADS - while (size > INT_MAX) { + while (size > sizemax) { /* Very long strings cannot be written atomically. * But don't write exactly INT_MAX bytes at a time * to avoid memory aligment issues. */ - const int chunk_size = INT_MAX & ~0x3FFF; + int chunk_size = sizemax; fwrite(data, 1, chunk_size, fp); data += chunk_size; size -= chunk_size; diff -r bffa0b8a16e8 Parser/tokenizer.c --- a/Parser/tokenizer.c Sun Jul 27 04:07:18 2014 -0400 +++ b/Parser/tokenizer.c Mon Jul 28 23:44:01 2014 +0200 @@ -864,6 +864,13 @@ tok_nextc(register struct tok_state *tok } if (tok->prompt != NULL) { char *newtok = PyOS_Readline(stdin, stdout, tok->prompt); + if (newtok != NULL) { + char *translated = translate_newlines(newtok, 0, tok); + PyMem_FREE(newtok); + if (translated == NULL) + return EOF; + newtok = translated; + } if (tok->nextprompt != NULL) tok->prompt = tok->nextprompt; if (newtok == NULL) diff -r bffa0b8a16e8 Python/bltinmodule.c --- a/Python/bltinmodule.c Sun Jul 27 04:07:18 2014 -0400 +++ b/Python/bltinmodule.c Mon Jul 28 23:44:01 2014 +0200 @@ -2022,6 +2022,7 @@ builtin_raw_input(PyObject *self, PyObje PyObject *v = NULL; PyObject *fin = PySys_GetObject("stdin"); PyObject *fout = PySys_GetObject("stdout"); + size_t len; if (!PyArg_UnpackTuple(args, "[raw_]input", 0, 1, &v)) return NULL; @@ -2065,19 +2066,22 @@ builtin_raw_input(PyObject *self, PyObje PyErr_SetNone(PyExc_KeyboardInterrupt); return NULL; } - if (*s == '\0') { + len = strlen(s); + if (len == 0) { PyErr_SetNone(PyExc_EOFError); result = NULL; } - else { /* strip trailing '\n' */ - size_t len = strlen(s); + else { if (len > PY_SSIZE_T_MAX) { PyErr_SetString(PyExc_OverflowError, "[raw_]input: input too long"); result = NULL; } else { - result = PyString_FromStringAndSize(s, len-1); + len--; /* strip trailing '\n' */ + if (len != 0 && s[len-1] == '\r') + len--; /* strip trailing '\r' */ + result = PyString_FromStringAndSize(s, len); } } PyMem_FREE(s);