Skip to content

csv.writer: QUOTE_NONNUMERIC does not quote numeric-looking strings #8413

Description

@jinmay

Feature

Follow-up from #8302 / #8322.

With QUOTE_NONNUMERIC, csv.writer decides quoting from the serialized bytes instead of the original Python object, so numeric-looking strings such as "123" are written unquoted. Reading the output back with QUOTE_NONNUMERIC then silently turns them into floats.

import csv, io
sio = io.StringIO()
csv.writer(sio, quoting=csv.QUOTE_NONNUMERIC).writerow(["123", 123, "a"])
print(repr(sio.getvalue()))
# CPython:    '"123",123,"a"\r\n'
# RustPython: '123,123,"a"\r\n'

CPython decides before stringification, on the original object: quoted = !PyNumber_Check(field) (Modules/_csv.c, csv_writerow). Since str "123" and int 123 stringify to identical bytes, this cannot be expressed through csv_core::Writer, which still handles QUOTE_ALL/QUOTE_NONNUMERIC — the other four quoting modes were already moved to hand-written paths in #8260 / #8304 / #8315, one function per mode, duplicating the same row-serialization skeleton.

Rather than adding a fourth and fifth copy, I'd like to fix this by unifying the writer into a single serialization loop with one per-field quote-decision function covering all six modes. That makes the csv_core::Writer path dead code, so the stateful writer, its buffer machinery, and the single-byte terminator sentinel workaround from #8328 can be removed. Scope is writer-only: the reader keeps using csv-core, and non-ASCII dialect characters remain a separate follow-up (#8310 territory).

QUOTE_ALL is unaffected by the bug (it always quotes). test_write_quoting (Lib/test/test_csv.py) does not catch this because it has no numeric-looking string case.

Python Documentation or reference to CPython source code

https://docs.python.org/3/library/csv.html#csv.QUOTE_NONNUMERIC

Drafted with AI assistance (Claude Code), reviewed by me.

Metadata

Metadata

Assignees

Labels

No labels
No labels

Type

No type

Projects

No projects

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions