Coverage for apps/borrower_portal/ports.py: 40%
16 statements
« prev ^ index » next coverage.py v7.17.0, created at 2026-11-04 14:06 +0000
« prev ^ index » next coverage.py v7.17.0, created at 2026-11-04 14:06 +0000
1"""Address lookup seam for the borrower portal (add-borrower-portal-api design.md D13).
3Same port-and-fake pattern as the other external seams: a ``Protocol`` the API depends on and a
4built-in sample provider used until a real one (e.g. Google Places, as Arive uses) is wired.
5"""
7from __future__ import annotations
9from typing import Protocol
12class AddressLookup(Protocol):
13 def search(self, query: str) -> list[dict]:
14 """Up to ten ``{label, address_line, city, state_code, county, postal_code}`` matches."""
17_SAMPLE_ADDRESSES = [
18 ("100 Main Street", "Boca Raton", "FL", "Palm Beach", "33432"),
19 ("2450 Ocean Drive", "Miami Beach", "FL", "Miami-Dade", "33139"),
20 ("17 Harbor View Lane", "San Diego", "CA", "San Diego", "92101"),
21 ("880 Market Street", "San Francisco", "CA", "San Francisco", "94102"),
22 ("5 Lakeshore Drive", "Chicago", "IL", "Cook", "60611"),
23 ("321 Congress Avenue", "Austin", "TX", "Travis", "78701"),
24 ("44 Peachtree Street", "Atlanta", "GA", "Fulton", "30303"),
25 ("901 Pine Street", "Seattle", "WA", "King", "98101"),
26]
29class SampleAddressLookup:
30 """Development provider: matches the query against a fixed list of addresses."""
32 def search(self, query: str) -> list[dict]:
33 q = query.lower()
34 results = []
35 for line, city, state, county, postal in _SAMPLE_ADDRESSES:
36 label = f"{line}, {city}, {state} {postal}"
37 if q in label.lower():
38 results.append(
39 {
40 "label": label,
41 "address_line": line,
42 "city": city,
43 "state_code": state,
44 "county": county,
45 "postal_code": postal,
46 }
47 )
48 return results[:10]
51def get_address_lookup() -> AddressLookup:
52 return SampleAddressLookup()