fuzzyworld-tools / commit
Issues: accept a run record on the line after its label; never show that line as text
server/issues.py | 8 ++++++-- tests/test_issues.py | 15 +++++++++++++++ 2 files changed, 21 insertions(+), 2 deletions(-) diff --git a/server/issues.py b/server/issues.py index 97ee4be..baa97be 100644 --- a/server/issues.py +++ b/server/issues.py @@ -86,7 +86,7 @@ Error = comments.CommentError REPO_RE = re.compile(r"^[A-Za-z0-9][A-Za-z0-9._-]*$") BUGS_RE = re.compile(r"^bugs-k7q4\+([A-Za-z0-9][A-Za-z0-9._-]*)@fuzzyworld\.net$", re.I) ADDRESS_RE = re.compile(r"[^\s@<>]+@[^\s@<>]+") -RECORD_RE = re.compile(r"^Run record: (\{.*\})\s*$", re.M) +RECORD_RE = re.compile(r"^Run record:[ \t]*\n?[ \t]*(\{.*\})\s*$", re.M) # the JSON may sit on the next line: some mail clients break the line after the label RECORD_MAX = 64 * 1024 RECORD_DEPTH = 32 RECORD_KEYS = ("simVersion", "seed", "startLevel", "startCharge", "options", "actions") # every key of the real records; the rest is dropped @@ -603,9 +603,13 @@ def report_text(content, flowed=False, delsp=False): if flowed: lines = unflow(lines, delsp) cut = find_cut(lines) - kept, in_device = [], False + kept, in_device, after_label = [], False, False for line in lines[:cut]: s = line.lstrip() + if after_label and s.startswith("{"): # the record sat on the line after a bare "Run record:" label + after_label = False + continue + after_label = s.startswith("Run record:") and not s[len("Run record:"):].strip() if s.startswith("Device:"): in_device = True continue diff --git a/tests/test_issues.py b/tests/test_issues.py index fc730b1..ea8434e 100644 --- a/tests/test_issues.py +++ b/tests/test_issues.py @@ -322,6 +322,21 @@ class Records(Base): raw = rd(os.path.join(self.state, "repos", "explodorama", "1", "record.json")) self.assertEqual(raw, json.dumps(self.fixture(), separators=(",", ":"))) # re-serialized, compact + def test_find_record_accepts_the_json_on_the_next_line(self): + # seen in the first real IMAP mail: the mail client broke the line after "Run record: " + for text in ("x\nRun record: \n" + record() + " \n\n", "x\r\nRun record:\r\n" + record() + "\r\n"): + rec, why = issues.find_record(text) + self.assertEqual(rec["seed"], 7, why) + # but not across a blank line, and not when the next line is prose + self.assertEqual(issues.find_record("Run record:\n\n" + record() + "\n"), (None, "")) + self.assertEqual(issues.find_record("Run record:\nit crashed {sorry}\n"), (None, "")) + + def test_record_json_on_the_next_line_is_not_shown_as_text(self): + text = issues.report_text("Hi\n\nSeed 1\nRun record: \n" + record() + " \n\nbye\n") + self.assertNotIn("simVersion", text) + self.assertIn("Seed 1", text) + self.assertIn("bye", text) + def test_find_record_skips_the_too_long_footer(self): text = "x\nRun record: " + record() + "\n\n---\nRun record: too long for an email link. Paste it.\n" rec, why = issues.find_record(text)