Skip to content

Commit d00b503

Browse files
mel1-Gaschey-forpeoplealex-dzeda
authored
BFD-4655: Update BFD synthetic data with Clear test users (#3083)
Co-authored-by: aschey-forpeople <162160982+aschey-forpeople@users.noreply.github.com> Co-authored-by: Austin Schey <austin.schey@forpeople.us> Co-authored-by: Alex Dzeda <alex@e14s.com>
1 parent e2eb8dd commit d00b503

11 files changed

Lines changed: 212 additions & 211 deletions

File tree

apps/bfd-model-idr/synthetic-data/SYNTHETIC_BENE_HSTRY.csv

Lines changed: 14 additions & 14 deletions
Large diffs are not rendered by default.

apps/bfd-pipeline-idr/loader.py

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -95,7 +95,7 @@ def __init__(
9595
self.insert_timer = Timer("insert", model, partition)
9696
self.commit_timer = Timer("commit", model, partition)
9797
self.load_type = load_type
98-
self.enable_load_progress = load_mode == LoadMode.IDR or force_load_progress()
98+
self.enable_load_progress = should_track_load_progress(load_mode)
9999

100100
def load(
101101
self,
@@ -352,3 +352,8 @@ def _convert_date(date_field: date | datetime) -> datetime:
352352
if type(date_field) is datetime:
353353
return date_field.replace(tzinfo=UTC)
354354
return datetime.combine(date_field, datetime.min.time()).replace(tzinfo=UTC)
355+
356+
357+
def should_track_load_progress(load_mode: LoadMode) -> bool:
358+
# Whether to read/write load progress, which is diabled for synthetic and testing loads.
359+
return load_mode == LoadMode.IDR or force_load_progress()

apps/bfd-pipeline-idr/matching/parser.py

Lines changed: 31 additions & 69 deletions
Original file line numberDiff line numberDiff line change
@@ -139,19 +139,19 @@ def repl_interstate(match: re.Match[str]) -> str:
139139
(r"\bBZN\b", "BOX"),
140140
(r"\bB0X\b", "BOX"),
141141
(r"\bRUTA RURAL\b", "RR"),
142-
(r"\bIH(\d+[A-Z]?)\b", r"INTERSTATE \1"),
143-
(r"\bI\s?(\d+[A-Z]?)(?:\s+(?:HIGHWAY|HWY))?\b", repl_interstate),
144-
(r"\bUS(?:\s+HIGHWAY)?\s+(\d+[A-Z]?)(?:\s+(?:HIGHWAY|HWY))?\b", r"US HIGHWAY \1"),
142+
(r"\bIH(\d{1,4}[A-Z]?)\b", r"INTERSTATE \1"),
143+
(r"\bI\s?(\d{1,4}[A-Z]?)(?:\s+(?:HIGHWAY|HWY))?\b", repl_interstate),
144+
(r"\bUS(?:\s+HIGHWAY)?\s+(\d{1,4}[A-Z]?)(?:\s+(?:HIGHWAY|HWY))?\b", r"US HIGHWAY \1"),
145145
(r"\bBYP ROAD\b", "BYPASS ROAD"),
146146
(r"\bKY\s+(\d{1,4})(?:\s+(?:HIGHWAY|HWY))?\b", r"KY HIGHWAY \1"),
147147
(r"\bCNTY\b", "COUNTY"),
148-
(r"\bCR\s+(\d+[A-Z]?)(?:\s+(?:ROAD|RD))?\b", r"COUNTY ROAD \1"),
148+
(r"\bCR\s+(\d{1,4}[A-Z]?)(?:\s+(?:ROAD|RD))?\b", r"COUNTY ROAD \1"),
149149
(r"\bHWY\b", "HIGHWAY"),
150150
(r"\bRD\b", "ROAD"),
151151
(r"\bRT\b", "ROUTE"),
152152
(r"\bRTE\b", "ROUTE"),
153153
(r"\bSR\s+([A-Z]+)(?:\s+(?:ROUTE|RT|RTE|ROAD|RD))?\b", r"STATE ROUTE \1"),
154-
(r"\bSR\s+(\d+[A-Z]?)(?:\s+(?:ROAD|RD|ROUTE|RT|RTE))?\b", r"STATE ROAD \1"),
154+
(r"\bSR\s+(\d{1,4}[A-Z]?)(?:\s+(?:ROAD|RD|ROUTE|RT|RTE))?\b", r"STATE ROAD \1"),
155155
(r"\bSR\b", "STATE ROAD"),
156156
(r"\bTSR\b", "TOWNSHIP ROAD"),
157157
]
@@ -169,8 +169,9 @@ def normalize_text(text: str) -> str:
169169
# Mask floating point periods to preserve them (e.g. 39.2)
170170
text = re.sub(r"(\d)\.(\d)", r"\1_DOT_\2", text)
171171

172-
# Remove specific punctuation: *, ., (, ), ", :, ;, ', &, @
173-
text = re.sub(r'[*.,()":;\'&@]', "", text)
172+
# Remove unnecessary punctuation
173+
# Preserve commas since they reduce ambiguity in address components
174+
text = re.sub(r'[*.()":;\'&@]', "", text)
174175

175176
# Restore floating point periods
176177
text = text.replace("_DOT_", ".")
@@ -306,16 +307,9 @@ def normalize_address(address_str: str) -> str:
306307
else:
307308
formatted_lines.append(line)
308309

309-
normalized_lines: list[str] = []
310-
country_line = ""
311-
for line in formatted_lines:
312-
if line.strip().upper() in COUNTRIES:
313-
country_line = line
314-
else:
315-
normalized_lines.append(line)
316-
317-
if country_line:
318-
normalized_lines.append(country_line)
310+
normalized_lines = [
311+
line for line in formatted_lines if line.strip() and line.strip().upper() not in COUNTRIES
312+
]
319313

320314
res = "\n".join(normalized_lines)
321315

@@ -565,7 +559,7 @@ def get_val_simple(obj: object) -> str:
565559
if "SubaddressIdentifier" in tokens:
566560
street_parts.append(tokens["SubaddressIdentifier"])
567561

568-
# City, State, ZIP — Moved up for boundary standalone passes
562+
# City, State, ZIP — Only move to last_line_parts if they appear together
569563
if "StateName" in tokens:
570564
state_val_dict = _format_state(tokens["StateName"])
571565
if "PlaceName" in tokens:
@@ -595,50 +589,6 @@ def get_val_simple(obj: object) -> str:
595589
final_lines.append(_apply_pr_exceptions(" ".join(line1_parts)))
596590
if line2_parts:
597591
final_lines.append(_apply_pr_exceptions(" ".join(line2_parts)))
598-
if last_line_parts:
599-
# Construct City State Zip carefully
600-
city = last_line_parts[0] if len(last_line_parts) > 0 else ""
601-
state = last_line_parts[1] if len(last_line_parts) > 1 else ""
602-
zip_code_val = last_line_parts[2] if len(last_line_parts) > 2 else ""
603-
604-
last_line = ""
605-
if city:
606-
last_line += city
607-
608-
# Handle Canada spacing
609-
if state:
610-
state_parts = state.split()
611-
if (
612-
state_parts[0]
613-
in (
614-
"AB",
615-
"BC",
616-
"MB",
617-
"NB",
618-
"NL",
619-
"NT",
620-
"NS",
621-
"NU",
622-
"ON",
623-
"PE",
624-
"QC",
625-
"SK",
626-
"YT",
627-
)
628-
and len(state_parts) > 1
629-
):
630-
# usaddress merged part of Zip into StateName
631-
# e.g., 'ON K1A'
632-
state = state_parts[0]
633-
zip_code_val = " ".join(state_parts[1:]) + (
634-
" " + zip_code_val if zip_code_val else ""
635-
)
636-
637-
last_line += (" " if last_line else "") + state
638-
639-
if zip_code_val:
640-
last_line += (" " if last_line else "") + zip_code_val
641-
final_lines.append(last_line)
642592

643593
return "\n".join(final_lines)
644594

@@ -684,9 +634,26 @@ def _format_from_raw(raw_parsed: list[tuple[str, str]]) -> str:
684634
if can_swap and not any(v.isdigit() for v, _label in raw_parsed[:-1]):
685635
raw_parsed = [raw_parsed[-1], *raw_parsed[:-1]]
686636

637+
# Identify and fix lines that are just City State Zip incorrectly tagged
638+
if len(raw_parsed) >= 2:
639+
v_state, l_state = raw_parsed[-2]
640+
_, l_zip = raw_parsed[-1]
641+
is_state_abbr = v_state.upper() in STATES.values()
642+
is_state_name = v_state.upper() in STATES
643+
if l_zip == "ZipCode" and (is_state_abbr or is_state_name) and l_state != "StateName":
644+
raw_parsed[-2] = (v_state, "StateName")
645+
for i in range(len(raw_parsed) - 2):
646+
if raw_parsed[i][1] in ("StreetName", "PlaceName", "StreetNamePostType"):
647+
raw_parsed[i] = (raw_parsed[i][0], "PlaceName")
648+
687649
has_street_name = any(label == "StreetName" for _val, label in raw_parsed)
688650
reconstructed: list[str] = []
651+
geo_labels = ("PlaceName", "StateName", "ZipCode", "CountryName")
652+
has_other = any(p_label not in geo_labels for _, p_label in raw_parsed)
653+
689654
for p_val, p_label in raw_parsed:
655+
if p_label in geo_labels and not has_other:
656+
continue
690657
# apply directional checks
691658
res_val = p_val
692659
if "Directional" in p_label:
@@ -698,6 +665,7 @@ def _format_from_raw(raw_parsed: list[tuple[str, str]]) -> str:
698665
# apply state checks
699666
elif p_label == "StateName":
700667
res_val = _format_state(p_val)
668+
701669
# apply secondary unit
702670
elif p_label == "OccupancyType":
703671
res_val = _format_secondary_unit(p_val)
@@ -722,11 +690,6 @@ def _apply_pr_exceptions(text: str) -> str:
722690
if not lines:
723691
return text
724692

725-
last_line_val = ""
726-
# If the last line contains a State and Zip code, isolate it from reordering
727-
if re.search(r"\b[A-Z]{2}\b\s+\d{5}", lines[-1].upper()):
728-
last_line_val = lines.pop(-1)
729-
730693
urb_lines: list[str] = []
731694
condo_lines: list[str] = []
732695
street_lines_list: list[str] = []
@@ -767,8 +730,7 @@ def _apply_pr_exceptions(text: str) -> str:
767730
break
768731

769732
lines = urb_lines + condo_lines + street_lines_list + other_lines + postal_lines
770-
if last_line_val:
771-
lines.append(last_line_val)
733+
772734
text = "\n".join(lines)
773735

774736
# Standardize Spanish boxes on the combined text (e.g., APARTADO -> PO BOX)

0 commit comments

Comments
 (0)