diff --git a/CHANGELOG.md b/CHANGELOG.md index 0b15e11f..803a916f 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -301,6 +301,13 @@ per-file diff commands. (detail unavailable, synthesised from search)`, documented in the CLI README, and covered by automated tests. +- **`verify_pdf.py --ascii-dates` catches the `2016–17` form again** (#698) - the quantity rule from + #533 treated `17` as a bare non-year number, so `MSc Physics, 2016–17`, `Sep 2016–17` and + `2019–20 season` passed `/apply` Step 5d although the guide says a year on either side of the + dash is enough, and all three were caught before #533. A year followed by a two-digit year is + now a date pair; `1500–2000` and `2000–5000` stay quantities. Two new `test_verify_pdf.py` + cases; the date-pair one fails on master. + ### Security - **CI no longer leaves the job token in `.git/config` or expands a PR-controlled name into a diff --git a/tests/test_verify_pdf.py b/tests/test_verify_pdf.py index 3085cffc..6df55b86 100644 --- a/tests/test_verify_pdf.py +++ b/tests/test_verify_pdf.py @@ -134,6 +134,17 @@ class FindNonAsciiDateRangesTests(unittest.TestCase): with self.subTest(text=text): self.assertEqual(len(find_non_ascii_date_ranges(text)), 1) + def test_year_and_two_digit_year_is_a_date_range(self): + # The academic-year and season form, caught before the quantity rule + # (#533) and suppressed by it because `17` is a bare non-year number. + for text in ("MSc Physics, 2016\u201317", "Sep 2016\u201317", "2019\u201320 season", "2016 \u2013 17"): + with self.subTest(text=text): + self.assertEqual(len(find_non_ascii_date_ranges(text)), 1) + + def test_two_digit_number_before_a_year_is_still_a_quantity(self): + # Only year-first is the date form; `17-2016` is not a date anyone writes. + self.assertEqual(find_non_ascii_date_ranges("items 17\u20132016"), []) + def test_two_years_joined_by_a_dash_are_still_a_date_range(self): for text in ("2016\u20132024", "1990\u20132010 programme", "Roles 2000\u20132024"): with self.subTest(text=text): diff --git a/tools/verify_pdf.py b/tools/verify_pdf.py index 83782625..9b757f5f 100644 --- a/tools/verify_pdf.py +++ b/tools/verify_pdf.py @@ -132,8 +132,18 @@ def _bare_number(token): return core +_TWO_DIGIT_YEAR = re.compile(r"\d{2}") + + def _quantity_range(line, dash_index): - """True when both sides of the dash are bare numbers and not both years.""" + """True when both sides of the dash are bare numbers and not a date pair. + + A date pair is two years (`2016-2024`) or a year and a two-digit year + (`2016-17`, `2019-20`): the short form is how academic years and seasons + are written, and it was caught before the quantity rule existed. Anything + else with bare numbers on both sides is a quantity (`1500-2000`, + `2000-5000`) and is left alone. + """ before = _TOKEN_BEFORE.search(line[:dash_index]) after = _TOKEN_AFTER.search(line[dash_index + 1 :]) if not before or not after: @@ -141,7 +151,9 @@ def _quantity_range(line, dash_index): left, right = _bare_number(before.group(1)), _bare_number(after.group(1)) if left is None or right is None: return False - return not (_BARE_YEAR.fullmatch(left) and _BARE_YEAR.fullmatch(right)) + if _BARE_YEAR.fullmatch(left) and (_BARE_YEAR.fullmatch(right) or _TWO_DIGIT_YEAR.fullmatch(right)): + return False + return True def find_non_ascii_date_ranges(text):