From 9cadb1b6e0d10aaeb8f9e69e51f672a53de6b164 Mon Sep 17 00:00:00 2001 From: Antoine Pitrou Date: Mon, 15 Sep 2008 23:02:56 +0000 Subject: [PATCH] Issue #3782: os.write() must not accept unicode strings --- Lib/pty.py | 2 +- Lib/test/test_asyncore.py | 10 +++++----- Lib/test/test_os.py | 24 +++++++++++++++++++++++- Lib/test/test_pty.py | 4 ++-- Lib/test/test_subprocess.py | 26 ++++++++++++++------------ Lib/test/test_tempfile.py | 2 +- Lib/test/tf_inherit_check.py | 2 +- Misc/NEWS | 2 ++ Modules/posixmodule.c | 2 +- 9 files changed, 50 insertions(+), 24 deletions(-) diff --git a/Lib/pty.py b/Lib/pty.py index 487382725e..810ebd8228 100644 --- a/Lib/pty.py +++ b/Lib/pty.py @@ -129,7 +129,7 @@ def fork(): def _writen(fd, data): """Write all the data to a descriptor.""" - while data != '': + while data: n = os.write(fd, data) data = data[n:] diff --git a/Lib/test/test_asyncore.py b/Lib/test/test_asyncore.py index 12ef247a0e..940b45e336 100644 --- a/Lib/test/test_asyncore.py +++ b/Lib/test/test_asyncore.py @@ -381,8 +381,8 @@ class DispatcherWithSendTests_UsePoll(DispatcherWithSendTests): if hasattr(asyncore, 'file_wrapper'): class FileWrapperTest(unittest.TestCase): def setUp(self): - self.d = "It's not dead, it's sleeping!" - open(TESTFN, 'w').write(self.d) + self.d = b"It's not dead, it's sleeping!" + open(TESTFN, 'wb').write(self.d) def tearDown(self): unlink(TESTFN) @@ -400,8 +400,8 @@ if hasattr(asyncore, 'file_wrapper'): self.assertRaises(OSError, w.read, 1) def test_send(self): - d1 = "Come again?" - d2 = "I want to buy some cheese." + d1 = b"Come again?" + d2 = b"I want to buy some cheese." fd = os.open(TESTFN, os.O_WRONLY | os.O_APPEND) w = asyncore.file_wrapper(fd) os.close(fd) @@ -409,7 +409,7 @@ if hasattr(asyncore, 'file_wrapper'): w.write(d1) w.send(d2) w.close() - self.assertEqual(open(TESTFN).read(), self.d + d1 + d2) + self.assertEqual(open(TESTFN, 'rb').read(), self.d + d1 + d2) def test_main(): diff --git a/Lib/test/test_os.py b/Lib/test/test_os.py index 50b583162e..f58aaf7911 100644 --- a/Lib/test/test_os.py +++ b/Lib/test/test_os.py @@ -41,7 +41,7 @@ class FileTests(unittest.TestCase): os.close(second) # close a fd that is open, and one that isn't os.closerange(first, first + 2) - self.assertRaises(OSError, os.write, first, "a") + self.assertRaises(OSError, os.write, first, b"a") def test_rename(self): path = support.TESTFN @@ -50,6 +50,28 @@ class FileTests(unittest.TestCase): new = sys.getrefcount(path) self.assertEqual(old, new) + def test_read(self): + with open(support.TESTFN, "w+b") as fobj: + fobj.write(b"spam") + fobj.flush() + fd = fobj.fileno() + os.lseek(fd, 0, 0) + s = os.read(fd, 4) + self.assertEqual(type(s), bytes) + self.assertEqual(s, b"spam") + + def test_write(self): + # os.write() accepts bytes- and buffer-like objects but not strings + fd = os.open(support.TESTFN, os.O_CREAT | os.O_WRONLY) + self.assertRaises(TypeError, os.write, fd, "beans") + os.write(fd, b"bacon\n") + os.write(fd, bytearray(b"eggs\n")) + os.write(fd, memoryview(b"spam\n")) + os.close(fd) + with open(support.TESTFN, "rb") as fobj: + self.assertEqual(fobj.read(), b"bacon\neggs\nspam\n") + + class TemporaryFileTests(unittest.TestCase): def setUp(self): self.files = [] diff --git a/Lib/test/test_pty.py b/Lib/test/test_pty.py index f62fc99fba..ec52f9ffbc 100644 --- a/Lib/test/test_pty.py +++ b/Lib/test/test_pty.py @@ -7,8 +7,8 @@ import signal from test.support import verbose, TestSkipped, run_unittest import unittest -TEST_STRING_1 = "I wish to buy a fish license.\n" -TEST_STRING_2 = "For my pet fish, Eric.\n" +TEST_STRING_1 = b"I wish to buy a fish license.\n" +TEST_STRING_2 = b"For my pet fish, Eric.\n" if verbose: def debug(msg): diff --git a/Lib/test/test_subprocess.py b/Lib/test/test_subprocess.py index fe916c2a85..f4f1cd5a86 100644 --- a/Lib/test/test_subprocess.py +++ b/Lib/test/test_subprocess.py @@ -128,7 +128,7 @@ class ProcessTestCase(unittest.TestCase): # stdin is set to open file descriptor tf = tempfile.TemporaryFile() d = tf.fileno() - os.write(d, "pear") + os.write(d, b"pear") os.lseek(d, 0, 0) p = subprocess.Popen([sys.executable, "-c", 'import sys; sys.exit(sys.stdin.read() == "pear")'], @@ -237,7 +237,7 @@ class ProcessTestCase(unittest.TestCase): def test_stdout_filedes_of_stdout(self): # stdout is set to 1 (#1531862). - cmd = r"import sys, os; sys.exit(os.write(sys.stdout.fileno(), '.\n'))" + cmd = r"import sys, os; sys.exit(os.write(sys.stdout.fileno(), b'.\n'))" rc = subprocess.call([sys.executable, "-c", cmd], stdout=1) self.assertEquals(rc, 2) @@ -548,11 +548,12 @@ class ProcessTestCase(unittest.TestCase): def test_args_string(self): # args is a string - f, fname = self.mkstemp() - os.write(f, "#!/bin/sh\n") - os.write(f, "exec '%s' -c 'import sys; sys.exit(47)'\n" % - sys.executable) - os.close(f) + fd, fname = self.mkstemp() + # reopen in text mode + with open(fd, "w") as fobj: + fobj.write("#!/bin/sh\n") + fobj.write("exec '%s' -c 'import sys; sys.exit(47)'\n" % + sys.executable) os.chmod(fname, 0o700) p = subprocess.Popen(fname) p.wait() @@ -590,11 +591,12 @@ class ProcessTestCase(unittest.TestCase): def test_call_string(self): # call() function with string argument on UNIX - f, fname = self.mkstemp() - os.write(f, "#!/bin/sh\n") - os.write(f, "exec '%s' -c 'import sys; sys.exit(47)'\n" % - sys.executable) - os.close(f) + fd, fname = self.mkstemp() + # reopen in text mode + with open(fd, "w") as fobj: + fobj.write("#!/bin/sh\n") + fobj.write("exec '%s' -c 'import sys; sys.exit(47)'\n" % + sys.executable) os.chmod(fname, 0o700) rc = subprocess.call(fname) os.remove(fname) diff --git a/Lib/test/test_tempfile.py b/Lib/test/test_tempfile.py index 5a81455213..0e5cb0f2d1 100644 --- a/Lib/test/test_tempfile.py +++ b/Lib/test/test_tempfile.py @@ -252,7 +252,7 @@ class test__mkstemp_inner(TC): # _mkstemp_inner can create files in a user-selected directory dir = tempfile.mkdtemp() try: - self.do_create(dir=dir).write("blat") + self.do_create(dir=dir).write(b"blat") finally: os.rmdir(dir) diff --git a/Lib/test/tf_inherit_check.py b/Lib/test/tf_inherit_check.py index 0fd108914e..92ebd95e52 100644 --- a/Lib/test/tf_inherit_check.py +++ b/Lib/test/tf_inherit_check.py @@ -10,7 +10,7 @@ try: fd = int(sys.argv[2]) try: - os.write(fd, "blat") + os.write(fd, b"blat") except os.error: # Success -- could not write to fd. sys.exit(0) diff --git a/Misc/NEWS b/Misc/NEWS index c2734c8b94..0024e82f08 100644 --- a/Misc/NEWS +++ b/Misc/NEWS @@ -140,6 +140,8 @@ Library Extension Modules ----------------- +- Issue #3782: os.write() must not accept unicode strings. + - Issue #2975: When compiling several extension modules with Visual Studio 2008 from the same python interpreter, some environment variables would grow without limit. diff --git a/Modules/posixmodule.c b/Modules/posixmodule.c index 8931ea295f..f6a4d956a9 100644 --- a/Modules/posixmodule.c +++ b/Modules/posixmodule.c @@ -4896,7 +4896,7 @@ posix_write(PyObject *self, PyObject *args) int fd; Py_ssize_t size; - if (!PyArg_ParseTuple(args, "is*:write", &fd, &pbuf)) + if (!PyArg_ParseTuple(args, "iy*:write", &fd, &pbuf)) return NULL; Py_BEGIN_ALLOW_THREADS size = write(fd, pbuf.buf, (size_t)pbuf.len); -- 2.40.0