You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
{{ message }}
Repository navigation
codecs.StreamReader doesn't pass final=1 to the UTF-8 codec #56717
although it seems to me that both lines should be the same. The first line is correct, I think, since the <F4> at the end is a maximal subpart of an ill-formed subsequence, according to the definition in the Unicode standard.
IIUC this happens because StreamReader calls codecs.utf_8_decode without passing final=1 [0], so when the decoder finds the trailing F4 it doesn't decode it yet because it waits from the other 3 bytes (F4 is the start byte of a 4-bytes UTF-8 sequence):
>>> b =b'A\xf5BC\xf4'
>>> chars, decnum = codecs.utf_8_decode(b, 'replace', 0) # final=0
>>> chars, decnum
('A�BC', 4) # F4 not decoded yet
>>> b = b[decnum:]
>>> b
b'\xf4' # F4 still here
>>> chars, decnum = codecs.utf_8_decode(b, 'replace', 0)
>>> chars, decnum
('', 0) # additional calls keep waiting for the other 3 bytes
>>> chars, decnum = codecs.utf_8_decode(b, 'replace', 1) # final=1
>>> chars, decnum
('�', 1) # when final=1 is passed F4 is decoded, but it never happens
While passing 1 makes the attached script work as expected, it breaks several other test in test_codecs (apparently not all the decoders accept the 'final' argument).
Also passing 1 should be done only for the last call: read can be called several times with a specific size, and it shouldn't use final=1 until the last call to avoid errors mid-stream.
The final parameter is an extension to the decoder API signature,
so it's not surprising that not all codecs implement it.
The ones that do should use it for all calls, since that way
the actual consumed number of bytes is correctly reported
back to the StreamReader instance.
Note: The parameter name "final" is a bit misleading. What happens
is that the number of bytes consumed by the decoder were previously
always reported as len(buffer), since the C API for decoders did
not provide a way to report back the number of bytes consumed.
This was changed when stateful decoders were added to the C API,
since these do allow reporting back the consumed bytes. A more
appropriate name for the parameter would have been
"report_bytes_consumed".
final=0: I'm passing in a few bytes, but there are more to come, so if the last byte(s) doesn't make sense on its own (e.g. it's a start byte but the continuation bytes are missing), wait for the others before raising an error;
final=1: these are the last bytes, so if the last byte(s) doesn't make sense raise an error (or ignore/replace) because there won't be other bytes that might turn that in a well-formed byte sequence.
Activity
spatz123 commentedon Jul 6, 2011
The attached script produces the output
'A\ufffdBC\ufffd'
'A\ufffdBC'
although it seems to me that both lines should be the same. The first line is correct, I think, since the <F4> at the end is a maximal subpart of an ill-formed subsequence, according to the definition in the Unicode standard.
vstinner commentedon Jul 6, 2011
I confirm, there is a bug in codecs.StreamReader.
vstinner commentedon Jul 6, 2011
You should use the io module, it doesn't have the bug :)
ezio-melotti commentedon Sep 4, 2011
IIUC this happens because StreamReader calls codecs.utf_8_decode without passing final=1 [0], so when the decoder finds the trailing F4 it doesn't decode it yet because it waits from the other 3 bytes (F4 is the start byte of a 4-bytes UTF-8 sequence):
While passing 1 makes the attached script work as expected, it breaks several other test in test_codecs (apparently not all the decoders accept the 'final' argument).
Also passing 1 should be done only for the last call: read can be called several times with a specific size, and it shouldn't use final=1 until the last call to avoid errors mid-stream.
[0]: see Lib/codecs.py:482
malemburg commentedon Sep 21, 2011
The final parameter is an extension to the decoder API signature,
so it's not surprising that not all codecs implement it.
The ones that do should use it for all calls, since that way
the actual consumed number of bytes is correctly reported
back to the StreamReader instance.
Note: The parameter name "final" is a bit misleading. What happens
is that the number of bytes consumed by the decoder were previously
always reported as len(buffer), since the C API for decoders did
not provide a way to report back the number of bytes consumed.
This was changed when stateful decoders were added to the C API,
since these do allow reporting back the consumed bytes. A more
appropriate name for the parameter would have been
"report_bytes_consumed".
ezio-melotti commentedon Sep 21, 2011
AFAIU final means:
[-]Codecs Anomaly[/-][+]codecs.StreamReader doesn't pass final=1 to the UTF-8 codec[/+]pythongh-107862: Reference the existing issues for two of the codec e…
pythongh-107862: Reference the existing issues for two of the codec e…