summaryrefslogtreecommitdiffstats
path: root/Lib
diff options
context:
space:
mode:
authorMartin v. Löwis <martin@v.loewis.de>2005-08-24 07:38:12 (GMT)
committerMartin v. Löwis <martin@v.loewis.de>2005-08-24 07:38:12 (GMT)
commit56066d2e554b6b92375d3e276f2f02663526c087 (patch)
tree877e93e7f59a7f09a713c029d8b2227f61b8521d /Lib
parent6d2b346140ed0f3bc4c67fc33bf69a60c496e6a4 (diff)
downloadcpython-56066d2e554b6b92375d3e276f2f02663526c087.zip
cpython-56066d2e554b6b92375d3e276f2f02663526c087.tar.gz
cpython-56066d2e554b6b92375d3e276f2f02663526c087.tar.bz2
Return complete lines from codec stream readers
even if there is an exception in later lines, resulting in correct line numbers for decoding errors in source code. Fixes #1178484. Will backport to 2.4.
Diffstat (limited to 'Lib')
-rw-r--r--Lib/codecs.py20
1 files changed, 17 insertions, 3 deletions
diff --git a/Lib/codecs.py b/Lib/codecs.py
index 0ffa382..a964f99 100644
--- a/Lib/codecs.py
+++ b/Lib/codecs.py
@@ -236,7 +236,7 @@ class StreamReader(Codec):
def decode(self, input, errors='strict'):
raise NotImplementedError
- def read(self, size=-1, chars=-1):
+ def read(self, size=-1, chars=-1, firstline=False):
""" Decodes data from the stream self.stream and returns the
resulting object.
@@ -253,6 +253,11 @@ class StreamReader(Codec):
is intended to prevent having to decode huge files in one
step.
+ If firstline is true, and a UnicodeDecodeError happens
+ after the first line terminator in the input only the first line
+ will be returned, the rest of the input will be kept until the
+ next call to read().
+
The method should use a greedy read strategy meaning that
it should read as much data as is allowed within the
definition of the encoding and the given size, e.g. if
@@ -275,7 +280,16 @@ class StreamReader(Codec):
newdata = self.stream.read(size)
# decode bytes (those remaining from the last call included)
data = self.bytebuffer + newdata
- newchars, decodedbytes = self.decode(data, self.errors)
+ try:
+ newchars, decodedbytes = self.decode(data, self.errors)
+ except UnicodeDecodeError, exc:
+ if firstline:
+ newchars, decodedbytes = self.decode(data[:exc.start], self.errors)
+ lines = newchars.splitlines(True)
+ if len(lines)<=1:
+ raise
+ else:
+ raise
# keep undecoded bytes until the next call
self.bytebuffer = data[decodedbytes:]
# put new characters in the character buffer
@@ -306,7 +320,7 @@ class StreamReader(Codec):
line = ""
# If size is given, we call read() only once
while True:
- data = self.read(readsize)
+ data = self.read(readsize, firstline=True)
if data:
# If we're at a "\r" read one extra character (which might
# be a "\n") to get a proper line ending. If the stream is