parse_line breaks on quoted fields

Done

/home/devdi/devswarm/evals/tasks/csv_quoted_fields/repo · 2026-11-09 16:10:02 UTC · took 47.4s

  1. Plan (done)
  2. Code (done)
  3. Test (done)
  4. Review (done)
  5. Finish (done)
Cost
$0.0059
Tests
Passed
Iterations
1
Re-plans
0
LLM calls
11
Prompt read from cache
74%

Usage by agent

Cost per agent
planner: $0.0010 planner planner, Cost: $0.0010 $0.0010 coder: $0.0021 coder coder, Cost: $0.0021 $0.0021 tester: $0.0019 tester tester, Cost: $0.0019 $0.0019 reviewer: $0.0009 reviewer reviewer, Cost: $0.0009 $0.0009
Tokens per agent
  • Cache read
  • Cache write
  • Input
  • Output
planner: 8,224 planner planner, Cache read: 5,799 planner, Cache write: 790 planner, Output: 1,627 8,224 coder: 22.0K coder coder, Cache read: 14.9K coder, Cache write: 4,299 coder, Output: 2,784 22.0K tester: 20.0K tester tester, Cache read: 13.1K tester, Cache write: 4,571 tester, Output: 2,354 20.0K reviewer: 5,543 reviewer reviewer, Cache read: 1,727 reviewer, Cache write: 2,648 reviewer, Output: 1,164 5,543
View as table
AgentCostCache readCache writeInputOutput
planner$0.00105,79979081,627
coder$0.002114,9154,299102,784
tester$0.001913,0584,57182,354
reviewer$0.00091,7272,64841,164

Timeline

  1. planner iteration 1 Finished 3 calls · 8,224 tokens · $0.0010 · 11.0s

    Loading…

  2. coder iteration 1 Finished 4 calls · 22.0K tokens · $0.0021 · 14.0s

    Loading…

  3. tester iteration 1 Finished 3 calls · 20.0K tokens · $0.0019 · 14.2s

    Loading…

  4. verify iteration 1 Passed 0.5s
    .........                                                                [100%]
    9 passed in 0.03s
    
  5. reviewer iteration 1 Finished 1 calls · 5,543 tokens · $0.0009 · 6.9s

    Loading…

Final diff

diff --git a/csvline.py b/csvline.py
index c00ae65..d639ee8 100644
--- a/csvline.py
+++ b/csvline.py
@@ -1,2 +1,33 @@
 def parse_line(line: str) -> list[str]:
-    return line.split(",")
+    fields: list[str] = []
+    buf: list[str] = []
+    in_quotes = False
+    at_field_start = True
+    i = 0
+    n = len(line)
+    while i < n:
+        ch = line[i]
+        if in_quotes:
+            if ch == '"':
+                if i + 1 < n and line[i + 1] == '"':
+                    # doubled quote inside a quoted field: literal quote
+                    buf.append('"')
+                    i += 2
+                    continue
+                in_quotes = False
+            else:
+                buf.append(ch)
+        elif ch == ",":
+            fields.append("".join(buf))
+            buf = []
+            at_field_start = True
+            i += 1
+            continue
+        elif ch == '"' and at_field_start:
+            in_quotes = True
+        else:
+            buf.append(ch)
+        at_field_start = False
+        i += 1
+    fields.append("".join(buf))
+    return fields
diff --git a/test_csvline.py b/test_csvline.py
index 3dff251..63aa895 100644
--- a/test_csvline.py
+++ b/test_csvline.py
@@ -3,3 +3,40 @@ from csvline import parse_line
 
 def test_simple():
     assert parse_line("a,b,c") == ["a", "b", "c"]
+
+
+def test_quoted_comma():
+    assert parse_line('a,"b,c",d') == ["a", "b,c", "d"]
+
+
+def test_doubled_quote_is_literal():
+    assert parse_line('"say ""hi""",x') == ['say "hi"', "x"]
+
+
+def test_empty_fields_kept():
+    assert parse_line("a,,b") == ["a", "", "b"]
+    assert parse_line("a,b,") == ["a", "b", ""]
+    assert parse_line(",") == ["", ""]
+    assert parse_line("") == [""]
+
+
+def test_empty_quoted_field():
+    assert parse_line('"",x') == ["", "x"]
+    assert parse_line('""""') == ['"']
+
+
+def test_quoted_field_at_end():
+    assert parse_line('x,"y"') == ["x", "y"]
+
+
+def test_unterminated_quote_takes_rest_of_line():
+    assert parse_line('"abc,d') == ["abc,d"]
+
+
+def test_doubled_quote_at_field_end():
+    assert parse_line('"a""",b') == ['a"', "b"]
+    assert parse_line('"""",x') == ['"', "x"]
+
+
+def test_mid_field_quote_is_literal():
+    assert parse_line('ab"c,d') == ['ab"c', "d"]