|
1 | 1 | import csv |
2 | 2 | import io |
| 3 | +import sys |
3 | 4 |
|
4 | 5 | from testutils import assert_raises |
5 | 6 |
|
@@ -262,6 +263,42 @@ def test_multichar_lineterminator(): |
262 | 263 | test_multichar_lineterminator() |
263 | 264 |
|
264 | 265 |
|
| 266 | +def test_reject_non_ascii_lineterminator(): |
| 267 | + # CPython accepts non-ASCII line terminators; RustPython rejects them |
| 268 | + # because the writer quotes and escapes byte by byte. Supporting them |
| 269 | + # requires code-point-wise handling as part of full Unicode dialect support. |
| 270 | + with assert_raises(csv.Error): |
| 271 | + csv.writer(io.StringIO(), lineterminator="é") |
| 272 | + |
| 273 | + with assert_raises(csv.Error): |
| 274 | + csv.writer(io.StringIO(), lineterminator="\x85") |
| 275 | + |
| 276 | + with assert_raises(csv.Error): |
| 277 | + csv.writer(io.StringIO(), lineterminator="\ud800") |
| 278 | + |
| 279 | + with assert_raises(csv.Error): |
| 280 | + csv.writer( |
| 281 | + io.StringIO(), lineterminator="é", quoting=csv.QUOTE_NONE, escapechar="\\" |
| 282 | + ) |
| 283 | + |
| 284 | + with assert_raises(csv.Error): |
| 285 | + csv.register_dialect("non_ascii_lt", lineterminator="é") |
| 286 | + |
| 287 | + class NonAsciiDialect(csv.excel): |
| 288 | + lineterminator = "é" |
| 289 | + |
| 290 | + with assert_raises(csv.Error): |
| 291 | + NonAsciiDialect() |
| 292 | + |
| 293 | + buf = io.StringIO() |
| 294 | + csv.writer(buf, lineterminator="!@#").writerow(["a", "b"]) |
| 295 | + assert buf.getvalue() == "a,b!@#" |
| 296 | + |
| 297 | + |
| 298 | +if sys.implementation.name == "rustpython": |
| 299 | + test_reject_non_ascii_lineterminator() |
| 300 | + |
| 301 | + |
265 | 302 | def test_empty_lineterminator(): |
266 | 303 | class EmptyLineTerminator(csv.excel): |
267 | 304 | lineterminator = "" |
|
0 commit comments