Skip to content

csv: apply dialect quoting and lineterminator in writer#8254

Merged
youknowone merged 2 commits into
RustPython:mainfrom
jinmay:csv-writer-dialect-quoting
Jul 16, 2026
Merged

csv: apply dialect quoting and lineterminator in writer#8254
youknowone merged 2 commits into
RustPython:mainfrom
jinmay:csv-writer-dialect-quoting

Conversation

@jinmay

@jinmay jinmay commented Jul 11, 2026

Copy link
Copy Markdown
Contributor

Summary

csv.writer ignored the quoting and lineterminator defined by a dialect (passed by name like dialect='unix' or as a dialect object), so writing with a built-in dialect diverged from CPython. Only explicit keyword arguments took effect. to_writer now resolves both from the dialect (via get_quoting() / get_lineterminator(), mirroring the existing get_delimiter()), while an explicit keyword argument still overrides it.

While fixing this I also found the QuoteStyle::Minimal → csv_core mapping was Always (quoting every field under QUOTE_MINIMAL); it is now Necessary. This was dormant because the quote style was only applied for an explicit quoting= argument, so it had to be fixed before applying the dialect's quoting.

import csv, io
sio = io.StringIO()
csv.writer(sio, dialect='unix').writerow([1, 'abc def', 'abc'])
# before: '1,abc def,abc\r\n'
# after:  '"1","abc def","abc"\n'   (matches CPython)

Test plan

  • Unmarks TestDialectUnix.test_simple_writer and Test_Csv.test_write_quoting (both @unittest.expectedFailure before). cargo run --release -- -m test test_csv: 128 run, 7 skipped, SUCCESS.
  • extra_tests/snippets/stdlib_csv.py: passes.
  • cargo fmt --check / cargo clippy: clean (no new warnings).
  • Compared against real CPython 3.14.6 on the same machine; the outputs for the dialect='unix' and QUOTE_MINIMAL cases match.

Assisted-by: Claude Code:claude-opus-4-8

Summary by CodeRabbit

  • Bug Fixes
    • Corrected minimal CSV quoting so values are quoted only when necessary.
    • Improved CSV formatting to consistently respect the selected dialect’s line terminator and quoting settings.
    • Ensured explicitly configured formatting options take precedence over dialect defaults.

@coderabbitai

coderabbitai Bot commented Jul 11, 2026

Copy link
Copy Markdown
Contributor

Review Change Stack

No actionable comments were generated in the recent review. 🎉

ℹ️ Recent review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yml

Review profile: CHILL

Plan: Pro

Run ID: 4c4557cb-d393-463b-b07c-aebc36c431b6

📥 Commits

Reviewing files that changed from the base of the PR and between 7145002 and 13ef019.

⛔ Files ignored due to path filters (1)
  • Lib/test/test_csv.py is excluded by !Lib/**
📒 Files selected for processing (1)
  • crates/stdlib/src/csv.rs
🚧 Files skipped from review as they are similar to previous changes (1)
  • crates/stdlib/src/csv.rs

📝 Walkthrough

Walkthrough

CSV writer configuration now respects dialect-provided quoting and line terminators, while explicit FormatOptions values override dialect defaults. Minimal quoting maps to csv_core::QuoteStyle::Necessary.

Changes

CSV formatting behavior

Layer / File(s) Summary
Quote mapping and option resolution
crates/stdlib/src/csv.rs
Minimal quoting uses the necessary quote style, and helper methods resolve dialect or default values with explicit overrides.
Writer configuration
crates/stdlib/src/csv.rs
to_writer applies resolved line terminator and quoting settings.

Estimated code review effort: 2 (Simple) | ~10 minutes

Possibly related PRs

Suggested reviewers: shaharnaveh, youknowone, moreal

🚥 Pre-merge checks | ✅ 5
✅ Passed checks (5 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title clearly summarizes the main change: applying dialect quoting and line terminator behavior in csv.writer.
Linked Issues check ✅ Passed The code changes match issue #8253 by honoring dialect quoting and lineterminator settings and preserving explicit overrides.
Out of Scope Changes check ✅ Passed No unrelated changes are evident in the reviewed summary; the edits stay focused on csv writer dialect behavior.
Docstring Coverage ✅ Passed No functions found in the changed files to evaluate docstring coverage. Skipping docstring coverage check.
✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands.

@github-actions

github-actions Bot commented Jul 11, 2026

Copy link
Copy Markdown
Contributor

📦 Library Dependencies

The following Lib/ modules were modified. Here are their dependencies:

[x] lib: cpython/Lib/csv.py
[x] test: cpython/Lib/test/test_csv.py (TODO: 23)

dependencies:

  • csv

dependent tests: (4 tests)

  • csv: test_csv test_genericalias
    • importlib.metadata: test_importlib test_zoneinfo

Legend:

  • [+] path exists in CPython
  • [x] up-to-date, [ ] outdated

@jinmay
jinmay marked this pull request as ready for review July 11, 2026 15:29
@youknowone youknowone added the z-ca-2026 Tag to track Contribution Academy 2026 label Jul 12, 2026
@doma17

doma17 commented Jul 12, 2026

Copy link
Copy Markdown
Contributor

Hello!

With this PR, RustPython writes \r,\n!, while CPython writes "\r","\n"!.

  csv.writer(sio, lineterminator="!").writerow(["\r", "\n"])

It looks like embedded CR/LF may no longer be quoted when the line terminator is not CR or LF.

@youknowone

Copy link
Copy Markdown
Member

@doma17 Thank you so much!
@jinmay could you check it please?

jinmay added 2 commits July 14, 2026 07:42
QuoteStyle::Minimal was mapped to csv_core's Always, which quoted every
field even under QUOTE_MINIMAL. Map it to Necessary so only fields that
require quoting are quoted.

Unmarks Test_Csv.test_write_quoting.

Assisted-by: Claude Code:claude-opus-4-8
csv.writer ignored the quoting and lineterminator from a dialect (whether
passed by name or object), always using the defaults. Resolve both from the
dialect via get_quoting()/get_lineterminator(), mirroring get_delimiter(), so
an explicit keyword argument still overrides the dialect.

Unmarks TestDialectUnix.test_simple_writer.

Assisted-by: Claude Code:claude-opus-4-8
@jinmay
jinmay force-pushed the csv-writer-dialect-quoting branch from 7145002 to 13ef019 Compare July 13, 2026 22:42
@jinmay

jinmay commented Jul 16, 2026

Copy link
Copy Markdown
Contributor Author

@doma17 thanks.

From what I found, the cause seems to be in csv-core: for QUOTE_MINIMAL it decides quoting by the terminator, so with a custom lineterminator it doesn't quote \r/\n. CPython always quotes them.

To fix it, I think we'd move QUOTE_MINIMAL to our native write path (like QUOTE_NONE) and unmark test_write_lineterminator. But that's a different test than this PR targeted, so the scope gets bigger than the original issue.

Fix it here, or as a follow-up?

@youknowone youknowone left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@jinmay @doma17 Thank you so much! If it is separated issue, could you open an issue about that? I prefer to have separated issue when it is not a blocker of other task

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

z-ca-2026 Tag to track Contribution Academy 2026

Projects

None yet

Development

Successfully merging this pull request may close these issues.

csv.writer ignores a dialect's quoting and lineterminator

3 participants