TextIOWrapper can translate received line endings or leave them visible to the parser.
Make this comfortable
Python TextIOWrapper: choose whether input line endings are normalized
Operation contract
Two independent wrappers decode the same owned UTF-8 bytes. The universal-newline reader converts CRLF and LF to LF. The second reader keeps the original endings, so a byte-sensitive parser can distinguish them. Both wrappers close their owned buffers.
Failure boundary
Neither mode changes the original bytes in the source buffer. For signed or hashed wire data, authenticate bytes before text translation. A real file reader should also declare encoding, error policy, and a byte limit; the in-memory fixture omits those outer constraints.
Working program
import io
wire_bytes = b"R-47\r\nR-73\n"
with io.TextIOWrapper(io.BytesIO(wire_bytes), encoding="utf-8", newline=None) as normalized:
print("normalized", repr(normalized.read()))
with io.TextIOWrapper(io.BytesIO(wire_bytes), encoding="utf-8", newline="") as preserved:
print("preserved", repr(preserved.read()))Output
normalized 'R-47\nR-73\n'
preserved 'R-47\r\nR-73\n'Costs and limits
Decoding scans the input and allocates a text representation. The two independent wrappers in this fixture each hold a short source; do not duplicate large buffers merely to compare modes in production.
Common Mistakes
- Universal-newline mode changes the text returned by read.
- Text normalization must not precede verification of exact signed bytes.
- Closing a TextIOWrapper also closes its underlying buffer unless ownership is transferred deliberately.
Connected lessons
python
textio-newline-contract
