Commit 17596665 authored by Guido van Rossum's avatar Guido van Rossum

New I/O code from Tony Lownds implement newline feature correctly,

and implements .newlines attribute in a 2.x-compatible fashion.
parent 384283f1
This diff is collapsed.
"""Unit tests for io.py.""" """Unit tests for io.py."""
import os
import sys import sys
import time import time
import array import array
...@@ -481,30 +482,61 @@ class TextIOWrapperTest(unittest.TestCase): ...@@ -481,30 +482,61 @@ class TextIOWrapperTest(unittest.TestCase):
def tearDown(self): def tearDown(self):
test_support.unlink(test_support.TESTFN) test_support.unlink(test_support.TESTFN)
def testNewlinesInput(self):
testdata = b"AAA\nBBB\nCCC\rDDD\rEEE\r\nFFF\r\nGGG"
normalized = testdata.replace(b"\r\n", b"\n").replace(b"\r", b"\n")
for newline, expected in [
(None, normalized.decode("ASCII").splitlines(True)),
("", testdata.decode("ASCII").splitlines(True)),
("\n", ["AAA\n", "BBB\n", "CCC\rDDD\rEEE\r\n", "FFF\r\n", "GGG"]),
("\r\n", ["AAA\nBBB\nCCC\rDDD\rEEE\r\n", "FFF\r\n", "GGG"]),
("\r", ["AAA\nBBB\nCCC\r", "DDD\r", "EEE\r", "\nFFF\r", "\nGGG"]),
]:
buf = io.BytesIO(testdata)
txt = io.TextIOWrapper(buf, encoding="ASCII", newline=newline)
self.assertEquals(txt.readlines(), expected)
txt.seek(0)
self.assertEquals(txt.read(), "".join(expected))
def testNewlinesOutput(self):
testdict = {
"": b"AAA\nBBB\nCCC\nX\rY\r\nZ",
"\n": b"AAA\nBBB\nCCC\nX\rY\r\nZ",
"\r": b"AAA\rBBB\rCCC\rX\rY\r\rZ",
"\r\n": b"AAA\r\nBBB\r\nCCC\r\nX\rY\r\r\nZ",
}
tests = [(None, testdict[os.linesep])] + sorted(testdict.items())
for newline, expected in tests:
buf = io.BytesIO()
txt = io.TextIOWrapper(buf, encoding="ASCII", newline=newline)
txt.write("AAA\nB")
txt.write("BB\nCCC\n")
txt.write("X\rY\r\nZ")
txt.flush()
self.assertEquals(buf.getvalue(), expected)
def testNewlines(self): def testNewlines(self):
input_lines = [ "unix\n", "windows\r\n", "os9\r", "last\n", "nonl" ] input_lines = [ "unix\n", "windows\r\n", "os9\r", "last\n", "nonl" ]
tests = [ tests = [
[ None, [ 'unix\n', 'windows\n', 'os9\n', 'last\n', 'nonl' ] ], [ None, [ 'unix\n', 'windows\n', 'os9\n', 'last\n', 'nonl' ] ],
[ '\n', input_lines ], [ '', input_lines ],
[ '\r\n', input_lines ], [ '\n', [ "unix\n", "windows\r\n", "os9\rlast\n", "nonl" ] ],
[ '\r\n', [ "unix\nwindows\r\n", "os9\rlast\nnonl" ] ],
[ '\r', [ "unix\nwindows\r", "\nos9\r", "last\nnonl" ] ],
] ]
encodings = ('utf-8', 'latin-1') encodings = ('utf-8', 'latin-1')
# Try a range of pad sizes to test the case where \r is the last # Try a range of buffer sizes to test the case where \r is the last
# character in TextIOWrapper._pending_line. # character in TextIOWrapper._pending_line.
for encoding in encodings: for encoding in encodings:
# XXX: str.encode() should return bytes
data = bytes(''.join(input_lines).encode(encoding))
for do_reads in (False, True): for do_reads in (False, True):
for padlen in chain(range(10), range(50, 60)): for bufsize in range(1, 10):
pad = '.' * padlen for newline, exp_lines in tests:
data_lines = [ pad + line for line in input_lines ] bufio = io.BufferedReader(io.BytesIO(data), bufsize)
# XXX: str.encode() should return bytes
data = bytes(''.join(data_lines).encode(encoding))
for newline, exp_line_ends in tests:
exp_lines = [ pad + line for line in exp_line_ends ]
bufio = io.BufferedReader(io.BytesIO(data))
textio = io.TextIOWrapper(bufio, newline=newline, textio = io.TextIOWrapper(bufio, newline=newline,
encoding=encoding) encoding=encoding)
if do_reads: if do_reads:
...@@ -522,6 +554,47 @@ class TextIOWrapperTest(unittest.TestCase): ...@@ -522,6 +554,47 @@ class TextIOWrapperTest(unittest.TestCase):
self.assertEquals(got_line, exp_line) self.assertEquals(got_line, exp_line)
self.assertEquals(len(got_lines), len(exp_lines)) self.assertEquals(len(got_lines), len(exp_lines))
def testNewlinesInput(self):
testdata = b"AAA\nBBB\nCCC\rDDD\rEEE\r\nFFF\r\nGGG"
normalized = testdata.replace(b"\r\n", b"\n").replace(b"\r", b"\n")
for newline, expected in [
(None, normalized.decode("ASCII").splitlines(True)),
("", testdata.decode("ASCII").splitlines(True)),
("\n", ["AAA\n", "BBB\n", "CCC\rDDD\rEEE\r\n", "FFF\r\n", "GGG"]),
("\r\n", ["AAA\nBBB\nCCC\rDDD\rEEE\r\n", "FFF\r\n", "GGG"]),
("\r", ["AAA\nBBB\nCCC\r", "DDD\r", "EEE\r", "\nFFF\r", "\nGGG"]),
]:
buf = io.BytesIO(testdata)
txt = io.TextIOWrapper(buf, encoding="ASCII", newline=newline)
self.assertEquals(txt.readlines(), expected)
txt.seek(0)
self.assertEquals(txt.read(), "".join(expected))
def testNewlinesOutput(self):
import os
orig_linesep = os.linesep
data = "AAA\nBBB\rCCC\n"
data_lf = b"AAA\nBBB\rCCC\n"
data_cr = b"AAA\rBBB\rCCC\r"
data_crlf = b"AAA\r\nBBB\rCCC\r\n"
for os.linesep, newline, expected in [
("\n", None, data_lf),
("\r\n", None, data_crlf),
("\n", "", data_lf),
("\r\n", "", data_lf),
("\n", "\n", data_lf),
("\r\n", "\n", data_lf),
("\n", "\r", data_cr),
("\r\n", "\r", data_cr),
("\n", "\r\n", data_crlf),
("\r\n", "\r\n", data_crlf),
]:
buf = io.BytesIO()
txt = io.TextIOWrapper(buf, encoding="ASCII", newline=newline)
txt.write(data)
txt.close()
self.assertEquals(buf.getvalue(), expected)
# Systematic tests of the text I/O API # Systematic tests of the text I/O API
def testBasicIO(self): def testBasicIO(self):
......
...@@ -12,9 +12,8 @@ FATX = 'x' * (2**14) ...@@ -12,9 +12,8 @@ FATX = 'x' * (2**14)
DATA_TEMPLATE = [ DATA_TEMPLATE = [
"line1=1", "line1=1",
"line2='this is a very long line designed to go past the magic " + "line2='this is a very long line designed to go past any default " +
"hundred character limit that is inside fileobject.c and which " + "buffer limits that exist in io.py but we also want to test " +
"is meant to speed up the common case, but we also want to test " +
"the uncommon case, naturally.'", "the uncommon case, naturally.'",
"def line3():pass", "def line3():pass",
"line4 = '%s'" % FATX, "line4 = '%s'" % FATX,
...@@ -32,7 +31,7 @@ DATA_SPLIT = [x + "\n" for x in DATA_TEMPLATE] ...@@ -32,7 +31,7 @@ DATA_SPLIT = [x + "\n" for x in DATA_TEMPLATE]
class TestGenericUnivNewlines(unittest.TestCase): class TestGenericUnivNewlines(unittest.TestCase):
# use a class variable DATA to define the data to write to the file # use a class variable DATA to define the data to write to the file
# and a class variable NEWLINE to set the expected newlines value # and a class variable NEWLINE to set the expected newlines value
READMODE = 'U' READMODE = 'r'
WRITEMODE = 'wb' WRITEMODE = 'wb'
def setUp(self): def setUp(self):
...@@ -79,12 +78,6 @@ class TestGenericUnivNewlines(unittest.TestCase): ...@@ -79,12 +78,6 @@ class TestGenericUnivNewlines(unittest.TestCase):
self.assertEqual(data, DATA_SPLIT[1:]) self.assertEqual(data, DATA_SPLIT[1:])
class TestNativeNewlines(TestGenericUnivNewlines):
NEWLINE = None
DATA = DATA_LF
READMODE = 'r'
WRITEMODE = 'w'
class TestCRNewlines(TestGenericUnivNewlines): class TestCRNewlines(TestGenericUnivNewlines):
NEWLINE = '\r' NEWLINE = '\r'
DATA = DATA_CR DATA = DATA_CR
...@@ -104,7 +97,6 @@ class TestMixedNewlines(TestGenericUnivNewlines): ...@@ -104,7 +97,6 @@ class TestMixedNewlines(TestGenericUnivNewlines):
def test_main(): def test_main():
test_support.run_unittest( test_support.run_unittest(
TestNativeNewlines,
TestCRNewlines, TestCRNewlines,
TestLFNewlines, TestLFNewlines,
TestCRLFNewlines, TestCRLFNewlines,
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment