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.
Feature
Follow-up from #8302 / #8322.
With
QUOTE_NONNUMERIC,csv.writerdecides 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 withQUOTE_NONNUMERICthen silently turns them into floats.CPython decides before stringification, on the original object:
quoted = !PyNumber_Check(field)(Modules/_csv.c,csv_writerow). Sincestr "123"andint 123stringify to identical bytes, this cannot be expressed throughcsv_core::Writer, which still handlesQUOTE_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::Writerpath 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 usingcsv-core, and non-ASCII dialect characters remain a separate follow-up (#8310 territory).QUOTE_ALLis 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.