diff options
-rw-r--r-- | Lib/io.py | 20 | ||||
-rw-r--r-- | Lib/test/output/test_cProfile | 28 | ||||
-rw-r--r-- | Lib/test/output/test_profile | 28 | ||||
-rw-r--r-- | Lib/test/test_io.py | 17 |
4 files changed, 57 insertions, 36 deletions
@@ -151,8 +151,10 @@ def open(file, mode="r", buffering=None, encoding=None, errors=None, closefd) if buffering is None: buffering = -1 - if buffering < 0 and raw.isatty(): - buffering = 1 + line_buffering = False + if buffering == 1 or buffering < 0 and raw.isatty(): + buffering = -1 + line_buffering = True if buffering < 0: buffering = DEFAULT_BUFFER_SIZE try: @@ -182,7 +184,7 @@ def open(file, mode="r", buffering=None, encoding=None, errors=None, buffer.name = file buffer.mode = mode return buffer - text = TextIOWrapper(buffer, encoding, errors, newline) + text = TextIOWrapper(buffer, encoding, errors, newline, line_buffering) text.name = file text.mode = mode return text @@ -1133,7 +1135,8 @@ class TextIOWrapper(TextIOBase): _CHUNK_SIZE = 128 - def __init__(self, buffer, encoding=None, errors=None, newline=None): + def __init__(self, buffer, encoding=None, errors=None, newline=None, + line_buffering=False): if newline not in (None, "", "\n", "\r", "\r\n"): raise ValueError("illegal newline value: %r" % (newline,)) if encoding is None: @@ -1160,6 +1163,7 @@ class TextIOWrapper(TextIOBase): raise ValueError("invalid errors: %r" % errors) self.buffer = buffer + self._line_buffering = line_buffering self._encoding = encoding self._errors = errors self._readuniversal = not newline @@ -1180,6 +1184,10 @@ class TextIOWrapper(TextIOBase): def errors(self): return self._errors + @property + def line_buffering(self): + return self._line_buffering + # A word about _snapshot. This attribute is either None, or a # tuple (decoder_state, readahead, pending) where decoder_state is # the second (integer) item of the decoder state, readahead is the @@ -1218,13 +1226,13 @@ class TextIOWrapper(TextIOBase): raise TypeError("can't write %s to text stream" % s.__class__.__name__) length = len(s) - haslf = "\n" in s + haslf = (self._writetranslate or self._line_buffering) and "\n" in s if haslf and self._writetranslate and self._writenl != "\n": s = s.replace("\n", self._writenl) # XXX What if we were just reading? b = s.encode(self._encoding, self._errors) self.buffer.write(b) - if haslf and self.isatty(): + if self._line_buffering and (haslf or "\r" in s): self.flush() self._snapshot = None if self._decoder: diff --git a/Lib/test/output/test_cProfile b/Lib/test/output/test_cProfile index 2b799ec..0037924 100644 --- a/Lib/test/output/test_cProfile +++ b/Lib/test/output/test_cProfile @@ -5,10 +5,10 @@ test_cProfile ncalls tottime percall cumtime percall filename:lineno(function) 1 0.000 0.000 1.000 1.000 <string>:1(<module>) - 2 0.000 0.000 0.000 0.000 io.py:1193(flush) - 1 0.000 0.000 0.000 0.000 io.py:257(flush) - 1 0.000 0.000 0.000 0.000 io.py:644(closed) - 1 0.000 0.000 0.000 0.000 io.py:862(flush) + 2 0.000 0.000 0.000 0.000 io.py:1201(flush) + 1 0.000 0.000 0.000 0.000 io.py:259(flush) + 1 0.000 0.000 0.000 0.000 io.py:646(closed) + 1 0.000 0.000 0.000 0.000 io.py:864(flush) 8 0.064 0.008 0.080 0.010 test_cProfile.py:103(subhelper) 28 0.028 0.001 0.028 0.001 test_cProfile.py:115(__getattr__) 1 0.270 0.270 1.000 1.000 test_cProfile.py:30(testfunc) @@ -30,11 +30,11 @@ test_cProfile Function called... ncalls tottime cumtime <string>:1(<module>) -> 1 0.270 1.000 test_cProfile.py:30(testfunc) -io.py:1193(flush) -> 1 0.000 0.000 io.py:257(flush) - 1 0.000 0.000 io.py:862(flush) -io.py:257(flush) -> -io.py:644(closed) -> -io.py:862(flush) -> 1 0.000 0.000 io.py:644(closed) +io.py:1201(flush) -> 1 0.000 0.000 io.py:259(flush) + 1 0.000 0.000 io.py:864(flush) +io.py:259(flush) -> +io.py:646(closed) -> +io.py:864(flush) -> 1 0.000 0.000 io.py:646(closed) test_cProfile.py:103(subhelper) -> 16 0.016 0.016 test_cProfile.py:115(__getattr__) test_cProfile.py:115(__getattr__) -> test_cProfile.py:30(testfunc) -> 1 0.014 0.130 test_cProfile.py:40(factorial) @@ -53,7 +53,7 @@ test_cProfile.py:89(helper2_indirect) -> 2 0.006 0.040 test_cProfile.py:93(helper2) -> 8 0.064 0.080 test_cProfile.py:103(subhelper) 8 0.000 0.008 {hasattr} {exec} -> 1 0.000 1.000 <string>:1(<module>) - 2 0.000 0.000 io.py:1193(flush) + 2 0.000 0.000 io.py:1201(flush) {hasattr} -> 12 0.012 0.012 test_cProfile.py:115(__getattr__) {method 'append' of 'list' objects} -> {method 'disable' of '_lsprof.Profiler' objects} -> @@ -65,10 +65,10 @@ test_cProfile.py:93(helper2) -> 8 0.064 0.080 Function was called by... ncalls tottime cumtime <string>:1(<module>) <- 1 0.000 1.000 {exec} -io.py:1193(flush) <- 2 0.000 0.000 {exec} -io.py:257(flush) <- 1 0.000 0.000 io.py:1193(flush) -io.py:644(closed) <- 1 0.000 0.000 io.py:862(flush) -io.py:862(flush) <- 1 0.000 0.000 io.py:1193(flush) +io.py:1201(flush) <- 2 0.000 0.000 {exec} +io.py:259(flush) <- 1 0.000 0.000 io.py:1201(flush) +io.py:646(closed) <- 1 0.000 0.000 io.py:864(flush) +io.py:864(flush) <- 1 0.000 0.000 io.py:1201(flush) test_cProfile.py:103(subhelper) <- 8 0.064 0.080 test_cProfile.py:93(helper2) test_cProfile.py:115(__getattr__) <- 16 0.016 0.016 test_cProfile.py:103(subhelper) 12 0.012 0.012 {hasattr} diff --git a/Lib/test/output/test_profile b/Lib/test/output/test_profile index ca09f8c..5ecdbae 100644 --- a/Lib/test/output/test_profile +++ b/Lib/test/output/test_profile @@ -10,10 +10,10 @@ test_profile 12 0.000 0.000 0.012 0.001 :0(hasattr) 1 0.000 0.000 0.000 0.000 :0(setprofile) 1 0.000 0.000 1.000 1.000 <string>:1(<module>) - 2 0.000 0.000 0.000 0.000 io.py:1193(flush) - 1 0.000 0.000 0.000 0.000 io.py:257(flush) - 1 0.000 0.000 0.000 0.000 io.py:644(closed) - 1 0.000 0.000 0.000 0.000 io.py:862(flush) + 2 0.000 0.000 0.000 0.000 io.py:1201(flush) + 1 0.000 0.000 0.000 0.000 io.py:259(flush) + 1 0.000 0.000 0.000 0.000 io.py:646(closed) + 1 0.000 0.000 0.000 0.000 io.py:864(flush) 0 0.000 0.000 profile:0(profiler) 1 0.000 0.000 1.000 1.000 profile:0(testfunc()) 8 0.064 0.008 0.080 0.010 test_profile.py:103(subhelper) @@ -33,15 +33,15 @@ Function called... :0(append) -> :0(exc_info) -> :0(exec) -> <string>:1(<module>)(1) 1.000 - io.py:1193(flush)(2) 0.000 + io.py:1201(flush)(2) 0.000 :0(hasattr) -> test_profile.py:115(__getattr__)(12) 0.028 :0(setprofile) -> <string>:1(<module>) -> test_profile.py:30(testfunc)(1) 1.000 -io.py:1193(flush) -> io.py:257(flush)(1) 0.000 - io.py:862(flush)(1) 0.000 -io.py:257(flush) -> -io.py:644(closed) -> -io.py:862(flush) -> io.py:644(closed)(1) 0.000 +io.py:1201(flush) -> io.py:259(flush)(1) 0.000 + io.py:864(flush)(1) 0.000 +io.py:259(flush) -> +io.py:646(closed) -> +io.py:864(flush) -> io.py:646(closed)(1) 0.000 profile:0(profiler) -> profile:0(testfunc())(1) 1.000 profile:0(testfunc()) -> :0(exec)(1) 1.000 :0(setprofile)(1) 0.000 @@ -74,10 +74,10 @@ Function was called by... test_profile.py:93(helper2)(8) 0.400 :0(setprofile) <- profile:0(testfunc())(1) 1.000 <string>:1(<module>) <- :0(exec)(1) 1.000 -io.py:1193(flush) <- :0(exec)(2) 1.000 -io.py:257(flush) <- io.py:1193(flush)(1) 0.000 -io.py:644(closed) <- io.py:862(flush)(1) 0.000 -io.py:862(flush) <- io.py:1193(flush)(1) 0.000 +io.py:1201(flush) <- :0(exec)(2) 1.000 +io.py:259(flush) <- io.py:1201(flush)(1) 0.000 +io.py:646(closed) <- io.py:864(flush)(1) 0.000 +io.py:864(flush) <- io.py:1201(flush)(1) 0.000 profile:0(profiler) <- profile:0(testfunc()) <- profile:0(profiler)(1) 0.000 test_profile.py:103(subhelper) <- test_profile.py:93(helper2)(8) 0.400 diff --git a/Lib/test/test_io.py b/Lib/test/test_io.py index f5b4a94..87e871b 100644 --- a/Lib/test/test_io.py +++ b/Lib/test/test_io.py @@ -496,6 +496,17 @@ class TextIOWrapperTest(unittest.TestCase): def tearDown(self): test_support.unlink(test_support.TESTFN) + def testLineBuffering(self): + r = io.BytesIO() + b = io.BufferedWriter(r, 1000) + t = io.TextIOWrapper(b, newline="\n", line_buffering=True) + t.write("X") + self.assertEquals(r.getvalue(), b"") # No flush happened + t.write("Y\nZ") + self.assertEquals(r.getvalue(), b"XY\nZ") # All got flushed + t.write("A\rB") + self.assertEquals(r.getvalue(), b"XY\nZA\rB") + def testEncodingErrorsReading(self): # (1) default b = io.BytesIO(b"abc\n\xff\n") @@ -525,13 +536,15 @@ class TextIOWrapperTest(unittest.TestCase): self.assertRaises(UnicodeError, t.write, "\xff") # (3) ignore b = io.BytesIO() - t = io.TextIOWrapper(b, encoding="ascii", errors="ignore", newline="\n") + t = io.TextIOWrapper(b, encoding="ascii", errors="ignore", + newline="\n") t.write("abc\xffdef\n") t.flush() self.assertEquals(b.getvalue(), b"abcdef\n") # (4) replace b = io.BytesIO() - t = io.TextIOWrapper(b, encoding="ascii", errors="replace", newline="\n") + t = io.TextIOWrapper(b, encoding="ascii", errors="replace", + newline="\n") t.write("abc\xffdef\n") t.flush() self.assertEquals(b.getvalue(), b"abc?def\n") |