From 6a6e2fe084e9db07c885800747d58479e4216854 Mon Sep 17 00:00:00 2001 From: Serhiy Storchaka Date: Wed, 12 Dec 2018 09:59:46 +0200 Subject: [PATCH 1/3] bpo-8765: Deprecate writing unicode to binary streams in Py3k mode. --- Lib/test/test_fileio.py | 8 ++++++-- .../Library/2018-12-12-09-59-41.bpo-8765.IFupT2.rst | 2 ++ Modules/_io/bufferedio.c | 11 +++++++++++ Modules/_io/fileio.c | 13 ++++++++++++- 4 files changed, 31 insertions(+), 3 deletions(-) create mode 100644 Misc/NEWS.d/next/Library/2018-12-12-09-59-41.bpo-8765.IFupT2.rst diff --git a/Lib/test/test_fileio.py b/Lib/test/test_fileio.py index 2825a87024da17..4b5dd829080262 100644 --- a/Lib/test/test_fileio.py +++ b/Lib/test/test_fileio.py @@ -12,7 +12,7 @@ from UserList import UserList from test.test_support import TESTFN, check_warnings, run_unittest, make_bad_fd -from test.test_support import py3k_bytes as bytes, cpython_only +from test.test_support import py3k_bytes as bytes, cpython_only, check_py3k_warnings from test.script_helper import run_python from _io import FileIO as _FileIO @@ -101,6 +101,10 @@ def test_none_args(self): self.assertEqual(self.f.readline(None), b"hi\n") self.assertEqual(self.f.readlines(None), [b"bye\n", b"abc"]) + def testWriteUnicode(self): + with check_py3k_warnings(): + self.f.write('') + def testRepr(self): self.assertEqual(repr(self.f), "<_io.FileIO name=%r mode='%s'>" % (self.f.name, self.f.mode)) @@ -210,7 +214,7 @@ def testErrnoOnClose(self, f): @ClosedFDRaises def testErrnoOnClosedWrite(self, f): - f.write('a') + f.write(b'a') @ClosedFDRaises def testErrnoOnClosedSeek(self, f): diff --git a/Misc/NEWS.d/next/Library/2018-12-12-09-59-41.bpo-8765.IFupT2.rst b/Misc/NEWS.d/next/Library/2018-12-12-09-59-41.bpo-8765.IFupT2.rst new file mode 100644 index 00000000000000..24a8efc2a94f70 --- /dev/null +++ b/Misc/NEWS.d/next/Library/2018-12-12-09-59-41.bpo-8765.IFupT2.rst @@ -0,0 +1,2 @@ +The write() method of buffered and unbuffered binary streams in the io +module emits now a DeprecationWarning in Py3k mode for unicode argument. diff --git a/Modules/_io/bufferedio.c b/Modules/_io/bufferedio.c index 5bef7463e7cb26..7170c6bc38b13b 100644 --- a/Modules/_io/bufferedio.c +++ b/Modules/_io/bufferedio.c @@ -1807,8 +1807,19 @@ bufferedwriter_write(buffered *self, PyObject *args) Py_buffer buf; Py_ssize_t written, avail, remaining; Py_off_t offset; + PyObject *arg; CHECK_INITIALIZED(self) + + if (!PyArg_ParseTuple(args, "O:write", &arg)) { + return NULL; + } + if (PyUnicode_Check(arg) && + PyErr_WarnPy3k("write() argument must be string or buffer, " + "not 'unicode'", 1) < 0) + { + return NULL; + } if (!PyArg_ParseTuple(args, "s*:write", &buf)) { return NULL; } diff --git a/Modules/_io/fileio.c b/Modules/_io/fileio.c index 2b40ada195a1f5..acb675fb183b88 100644 --- a/Modules/_io/fileio.c +++ b/Modules/_io/fileio.c @@ -710,14 +710,25 @@ fileio_write(fileio *self, PyObject *args) { Py_buffer pbuf; Py_ssize_t n, len; + PyObject *arg; if (self->fd < 0) return err_closed(); if (!self->writable) return err_mode("writing"); - if (!PyArg_ParseTuple(args, "s*", &pbuf)) + if (!PyArg_ParseTuple(args, "O:write", &arg)) { return NULL; + } + if (PyUnicode_Check(arg) && + PyErr_WarnPy3k("write() argument must be string or buffer, " + "not 'unicode'", 1) < 0) + { + return NULL; + } + if (!PyArg_ParseTuple(args, "s*:write", &pbuf)) { + return NULL; + } if (_PyVerify_fd(self->fd)) { Py_BEGIN_ALLOW_THREADS From 722f679895dc2237878cf52400f587e6c4b60db3 Mon Sep 17 00:00:00 2001 From: Serhiy Storchaka Date: Sun, 13 Jan 2019 21:01:22 +0200 Subject: [PATCH 2/3] Call PyArg_ParseTuple() only once. --- Modules/_io/bufferedio.c | 10 +++------- Modules/_io/fileio.c | 9 +++------ 2 files changed, 6 insertions(+), 13 deletions(-) diff --git a/Modules/_io/bufferedio.c b/Modules/_io/bufferedio.c index 7170c6bc38b13b..b8c98a4d0d0439 100644 --- a/Modules/_io/bufferedio.c +++ b/Modules/_io/bufferedio.c @@ -1807,20 +1807,16 @@ bufferedwriter_write(buffered *self, PyObject *args) Py_buffer buf; Py_ssize_t written, avail, remaining; Py_off_t offset; - PyObject *arg; CHECK_INITIALIZED(self) - - if (!PyArg_ParseTuple(args, "O:write", &arg)) { + if (!PyArg_ParseTuple(args, "s*:write", &buf)) { return NULL; } - if (PyUnicode_Check(arg) && + if (PyUnicode_Check(PyTuple_GET_ITEM(args, 0)) && PyErr_WarnPy3k("write() argument must be string or buffer, " "not 'unicode'", 1) < 0) { - return NULL; - } - if (!PyArg_ParseTuple(args, "s*:write", &buf)) { + PyBuffer_Release(&buf); return NULL; } diff --git a/Modules/_io/fileio.c b/Modules/_io/fileio.c index acb675fb183b88..ed5b918e76a7f8 100644 --- a/Modules/_io/fileio.c +++ b/Modules/_io/fileio.c @@ -710,23 +710,20 @@ fileio_write(fileio *self, PyObject *args) { Py_buffer pbuf; Py_ssize_t n, len; - PyObject *arg; if (self->fd < 0) return err_closed(); if (!self->writable) return err_mode("writing"); - if (!PyArg_ParseTuple(args, "O:write", &arg)) { + if (!PyArg_ParseTuple(args, "s*:write", &pbuf)) { return NULL; } - if (PyUnicode_Check(arg) && + if (PyUnicode_Check(PyTuple_GET_ITEM(args, 0)) && PyErr_WarnPy3k("write() argument must be string or buffer, " "not 'unicode'", 1) < 0) { - return NULL; - } - if (!PyArg_ParseTuple(args, "s*:write", &pbuf)) { + PyBuffer_Release(&pbuf); return NULL; } From 8d47d47df042036dcbfcab31fe43ab84eb0d5f3d Mon Sep 17 00:00:00 2001 From: Serhiy Storchaka Date: Tue, 15 Jan 2019 10:51:22 +0200 Subject: [PATCH 3/3] Update Lib/test/test_fileio.py --- Lib/test/test_fileio.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Lib/test/test_fileio.py b/Lib/test/test_fileio.py index 4b5dd829080262..57c9f14f47eacf 100644 --- a/Lib/test/test_fileio.py +++ b/Lib/test/test_fileio.py @@ -103,7 +103,7 @@ def test_none_args(self): def testWriteUnicode(self): with check_py3k_warnings(): - self.f.write('') + self.f.write(u'') def testRepr(self): self.assertEqual(repr(self.f), "<_io.FileIO name=%r mode='%s'>"