Title: csv: quote embedded CR/LF under QUOTE_MINIMAL by jinmay · Pull Request #8315 · RustPython/RustPython · GitHub
Open Graph Title: csv: quote embedded CR/LF under QUOTE_MINIMAL by jinmay · Pull Request #8315 · RustPython/RustPython
X Title: csv: quote embedded CR/LF under QUOTE_MINIMAL by jinmay · Pull Request #8315 · RustPython/RustPython
Description: Closes #8317 (re-created; #8302 was closed by accident) This PR follows our AI policy Summary Under QUOTE_MINIMAL, a field containing \r or \n must be quoted regardless of the lineterminator — CPython quotes them unconditionally. RustPython serialized QUOTE_MINIMAL rows with csv_core, which decides quoting from the bytes it registered for the terminator, so with a terminator other than CR/LF (e.g. '!' or '\0') embedded \r/\n were left unquoted. QUOTE_MINIMAL now uses a hand-written path (like QUOTE_NONE / QUOTE_STRINGS) that decides quoting via the existing field_needs_quotes, which always treats \r/\n as needing quotes. QUOTE_ALL and QUOTE_NONNUMERIC still use csv_core. This also fixes an empty row (writerow([])) emitting "" instead of only the terminator. import csv, io sio = io.StringIO() csv.writer(sio, lineterminator="!").writerow(["\r", "\n"]) # before: '\r,\n!' # after: '"\r","\n"!' (matches CPython) Multi-character lineterminator (the !@# case in test_write_lineterminator) is still unsupported and left for a follow-up, so that test stays marked. Test plan Unmarks test_write_iterable and test_write_empty_fields (both @unittest.expectedFailure before). cargo run --release -- -m test test_csv: 128 run, 7 skipped, SUCCESS. extra_tests/snippets/stdlib_csv.py: passes (added writer cases for custom terminators and empty fields). cargo fmt --check / cargo clippy: clean (no new warnings). Compared against CPython 3.14.6 on the same machine; the QUOTE_MINIMAL writer outputs match. Assisted-by: Claude Code:claude-opus-4-8 Summary by CodeRabbit Bug Fixes Fixed CSV writing with minimal quoting so fields are quoted only when required by delimiters, quotes, line breaks, or line terminators. Correctly handles empty fields and single empty values when producing CSV output. Ensured custom line terminators are serialized correctly. Tests Added coverage for minimal-quoting behavior, line terminators, and empty fields.
Open Graph Description: Closes #8317 (re-created; #8302 was closed by accident) This PR follows our AI policy Summary Under QUOTE_MINIMAL, a field containing \r or \n must be quoted regardless of the lineterminator — CP...
X Description: Closes #8317 (re-created; #8302 was closed by accident) This PR follows our AI policy Summary Under QUOTE_MINIMAL, a field containing \r or \n must be quoted regardless of the lineterminator — CP...
Opengraph URL: https://github.com/RustPython/RustPython/pull/8315
X: @github
Domain: github.com
| route-pattern | /:user_id/:repository/pull/:id/files(.:format) |
| route-controller | pull_requests |
| route-action | files |
| fetch-nonce | v2:18326083-abb4-ea0a-0155-6adcb7f05e89 |
| current-catalog-service-hash | ae870bc5e265a340912cde392f23dad3671a0a881730ffdadd82f2f57d81641b |
| request-id | D892:3609E5:7EF2A9:AF7C36:6A604463 |
| html-safe-nonce | 14357adbddd7f970aa275c12853786d5f9671cb4b14e437141f7b60ef27c2301 |
| visitor-payload | eyJyZWZlcnJlciI6IiIsInJlcXVlc3RfaWQiOiJEODkyOjM2MDlFNTo3RUYyQTk6QUY3QzM2OjZBNjA0NDYzIiwidmlzaXRvcl9pZCI6IjMzNTEzOTM4Nzk3MzA1OTY4MyIsInJlZ2lvbl9lZGdlIjoiaWFkIiwicmVnaW9uX3JlbmRlciI6ImlhZCJ9 |
| visitor-hmac | 3474d1ed2945561409655706d2c720c3a4f594c709f49c281bdd97d324a91592 |
| hovercard-subject-tag | pull_request:4082290341 |
| github-keyboard-shortcuts | repository,pull-request-list,pull-request-conversation,pull-request-files-changed,copilot |
| google-site-verification | Apib7-x98H0j5cPqHWwSMm6dNU4GmODRoqxLiDzdx9I |
| octolytics-url | https://collector.github.com/github/collect |
| analytics-location | / |
| fb:app_id | 1401488693436528 |
| apple-itunes-app | app-id=1477376905, app-argument=https://github.com/RustPython/RustPython/pull/8315/files |
| twitter:image | https://avatars.githubusercontent.com/u/13075035?s=400&v=4 |
| twitter:card | summary_large_image |
| og:image | https://avatars.githubusercontent.com/u/13075035?s=400&v=4 |
| og:image:alt | Closes #8317 (re-created; #8302 was closed by accident) This PR follows our AI policy Summary Under QUOTE_MINIMAL, a field containing \r or \n must be quoted regardless of the lineterminator — CP... |
| og:site_name | GitHub |
| og:type | object |
| hostname | github.com |
| expected-hostname | github.com |
| None | 60da8c2a42fa2bbf5f7567474990ec467836a84444262a58e200fa91b7f3d2d0 |
| turbo-cache-control | no-preview |
| diff-view | unified |
| go-import | github.com/RustPython/RustPython git https://github.com/RustPython/RustPython.git |
| octolytics-dimension-user_id | 39710557 |
| octolytics-dimension-user_login | RustPython |
| octolytics-dimension-repository_id | 135201145 |
| octolytics-dimension-repository_nwo | RustPython/RustPython |
| octolytics-dimension-repository_public | true |
| octolytics-dimension-repository_is_fork | false |
| octolytics-dimension-repository_network_root_id | 135201145 |
| octolytics-dimension-repository_network_root_nwo | RustPython/RustPython |
| turbo-body-classes | logged-out env-production page-responsive full-width |
| disable-turbo | true |
| browser-stats-url | https://api.github.com/_private/browser/stats |
| browser-errors-url | https://api.github.com/_private/browser/errors |
| release | 9824515e740d83d5eb82168a089b806ab0fe04a1 |
| ui-target | full |
| theme-color | #1e2327 |
| color-scheme | light dark |
Links:
Viewport: width=device-width