mirror of
https://github.com/MadsLorentzen/ai-job-search.git
synced 2026-11-11 17:37:59 +00:00
fix(verify_pdf): exclude currency amounts from ASCII date checks (#724)
* fix(verify-pdf): distinguish currency amounts from date ranges * docs: reference PR 724 in unreleased fix --------- Co-authored-by: Mads Lorentzen <madslorentzen17@gmail.com> Co-authored-by: Claude Fable 5.1 <noreply@anthropic.com>
This commit is contained in:
2 files changed
+28
-2
No files matched your search
@@ -121,6 +121,16 @@ class FindNonAsciiDateRangesTests(unittest.TestCase):
|
|||||||
with self.subTest(text=text):
|
with self.subTest(text=text):
|
||||||
self.assertEqual(find_non_ascii_date_ranges(text), [])
|
self.assertEqual(find_non_ascii_date_ranges(text), [])
|
||||||
|
|
||||||
|
def test_attached_currency_symbols_make_numeric_ranges_quantities(self):
|
||||||
|
# The real PDF CLI previously reported these budget amounts as dates.
|
||||||
|
# Currency symbols identify amounts even when both values resemble years.
|
||||||
|
for symbol in ("€", "£", "$", "¥"):
|
||||||
|
for text in (f"Budget {symbol}2000–{symbol}5000 per month",
|
||||||
|
f"Budget 1500{symbol}–2000{symbol} per month",
|
||||||
|
f"Budget {symbol}2000–{symbol}2024 per month"):
|
||||||
|
with self.subTest(text=text):
|
||||||
|
self.assertEqual(find_non_ascii_date_ranges(text), [])
|
||||||
|
|
||||||
def test_numerically_formatted_date_ranges_are_still_caught(self):
|
def test_numerically_formatted_date_ranges_are_still_caught(self):
|
||||||
# A composite token (slashed, dotted, hyphenated) is not a bare number,
|
# A composite token (slashed, dotted, hyphenated) is not a bare number,
|
||||||
# so the quantity rule does not apply and the year rule still fires.
|
# so the quantity rule does not apply and the year rule still fires.
|
||||||
|
|||||||
+18
-2
@@ -155,6 +155,18 @@ def _bare_number(token):
|
|||||||
return core
|
return core
|
||||||
|
|
||||||
|
|
||||||
|
def _currency_amount(token):
|
||||||
|
"""A numeric amount with an attached Unicode currency symbol, or None."""
|
||||||
|
core = token.strip(_OUTER_PUNCTUATION)
|
||||||
|
if core and unicodedata.category(core[0]) == "Sc":
|
||||||
|
core = core[1:]
|
||||||
|
elif core and unicodedata.category(core[-1]) == "Sc":
|
||||||
|
core = core[:-1]
|
||||||
|
else:
|
||||||
|
return None
|
||||||
|
return core if _BARE_NUMBER.fullmatch(core) else None
|
||||||
|
|
||||||
|
|
||||||
_TWO_DIGIT_YEAR = re.compile(r"\d{2}")
|
_TWO_DIGIT_YEAR = re.compile(r"\d{2}")
|
||||||
|
|
||||||
|
|
||||||
@@ -165,13 +177,17 @@ def _quantity_range(line, dash_index):
|
|||||||
(`2016-17`, `2019-20`): the short form is how academic years and seasons
|
(`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
|
are written, and it was caught before the quantity rule existed. Anything
|
||||||
else with bare numbers on both sides is a quantity (`1500-2000`,
|
else with bare numbers on both sides is a quantity (`1500-2000`,
|
||||||
`2000-5000`) and is left alone.
|
`2000-5000`) and is left alone. An attached currency symbol makes a
|
||||||
|
numeric pair an amount range, even when both amounts resemble years.
|
||||||
"""
|
"""
|
||||||
before = _TOKEN_BEFORE.search(line[:dash_index])
|
before = _TOKEN_BEFORE.search(line[:dash_index])
|
||||||
after = _TOKEN_AFTER.search(line[dash_index + 1 :])
|
after = _TOKEN_AFTER.search(line[dash_index + 1 :])
|
||||||
if not before or not after:
|
if not before or not after:
|
||||||
return False
|
return False
|
||||||
left, right = _bare_number(before.group(1)), _bare_number(after.group(1))
|
left_money, right_money = _currency_amount(before.group(1)), _currency_amount(after.group(1))
|
||||||
|
left, right = left_money or _bare_number(before.group(1)), right_money or _bare_number(after.group(1))
|
||||||
|
if left_money is not None or right_money is not None:
|
||||||
|
return left is not None and right is not None
|
||||||
if left is None or right is None:
|
if left is None or right is None:
|
||||||
return False
|
return False
|
||||||
if _BARE_YEAR.fullmatch(left) and (_BARE_YEAR.fullmatch(right) or _TWO_DIGIT_YEAR.fullmatch(right)):
|
if _BARE_YEAR.fullmatch(left) and (_BARE_YEAR.fullmatch(right) or _TWO_DIGIT_YEAR.fullmatch(right)):
|
||||||
|
|||||||
Reference in new issue
Block a user