File size: 3,930 Bytes
32387a0
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
"""Round-trip tests for the inline bracket format.

These tests rely only on the in-process modules (no downloads). The
larger end-to-end round-trip across the real BEA M2 corpus lives in
``test_m2_roundtrip.py`` and is skipped when the data is not present.
"""

from __future__ import annotations

import pytest

from gec.m2 import Edit
from gec.parse import parse_inline, recover_correction
from gec.render import render_inline


# ---------- render ----------


def test_render_simple_substitution():
    src = "I goes to school".split()
    edits = [Edit(1, 2, "go", "R:VERB:SVA")]
    assert render_inline(src, edits) == "I {goes=>go} to school"


def test_render_insertion():
    src = "I to school".split()
    edits = [Edit(1, 1, "go", "M:VERB")]
    assert render_inline(src, edits) == "I {=>go} to school"


def test_render_deletion():
    src = "I really go to school".split()
    edits = [Edit(1, 2, "", "U:ADV")]
    assert render_inline(src, edits) == "I {really=>} go to school"


def test_render_multitoken_replacement():
    src = "She have did it".split()
    edits = [Edit(1, 3, "did", "R:VERB:TENSE")]
    assert render_inline(src, edits) == "She {have did=>did} it"


def test_render_multiple_edits_in_order():
    src = "I goes to schol".split()
    edits = [Edit(1, 2, "go"), Edit(3, 4, "school")]
    assert render_inline(src, edits) == "I {goes=>go} to {schol=>school}"


def test_render_unordered_edits_are_sorted():
    src = "I goes to schol".split()
    edits = [Edit(3, 4, "school"), Edit(1, 2, "go")]
    assert render_inline(src, edits) == "I {goes=>go} to {schol=>school}"


def test_render_no_edits():
    src = "I go to school".split()
    assert render_inline(src, []) == "I go to school"


# ---------- parse ----------


def test_parse_substitution():
    text = "I {goes=>go} to school"
    corrected, edits, ok = parse_inline(text)
    assert ok
    assert corrected == "I go to school"
    assert len(edits) == 1
    assert edits[0].src == ["goes"] and edits[0].tgt == ["go"]


def test_parse_insertion():
    text = "I {=>really} go to school"
    corrected, edits, ok = parse_inline(text)
    assert ok
    assert corrected == "I really go to school"
    assert edits[0].src == [] and edits[0].tgt == ["really"]


def test_parse_deletion():
    text = "I {really=>} go to school"
    corrected, edits, ok = parse_inline(text)
    assert ok
    assert corrected == "I go to school"
    assert edits[0].src == ["really"] and edits[0].tgt == []


def test_parse_multitoken():
    text = "She {have did=>did} it"
    corrected, edits, ok = parse_inline(text)
    assert ok
    assert corrected == "She did it"
    assert edits[0].src == ["have", "did"]
    assert edits[0].tgt == ["did"]


def test_parse_malformed_returns_not_ok():
    text = "I {goes=>go to school"
    corrected, edits, ok = parse_inline(text)
    assert not ok
    # Permissive: we still try to recover something usable.
    assert "I" in corrected


def test_parse_no_edits_passthrough():
    corrected, edits, ok = parse_inline("I go to school")
    assert ok
    assert corrected == "I go to school"
    assert edits == []


# ---------- round-trip ----------


@pytest.mark.parametrize(
    "src, edits, expected_target",
    [
        ("I goes to school".split(), [Edit(1, 2, "go")], "I go to school"),
        ("I to school".split(), [Edit(1, 1, "go")], "I go to school"),
        ("I really go".split(), [Edit(1, 2, "")], "I go"),
        ("She have did it".split(), [Edit(1, 3, "did")], "She did it"),
        (
            "I goes to schol".split(),
            [Edit(1, 2, "go"), Edit(3, 4, "school")],
            "I go to school",
        ),
        ("I go to school".split(), [], "I go to school"),
    ],
)
def test_render_then_parse_recovers_target(src, edits, expected_target):
    rendered = render_inline(src, edits)
    recovered = recover_correction(rendered)
    assert recovered == expected_target