Coverage for src/couchers/postal/address_validation.py: 100%
15 statements
« prev ^ index » next coverage.py v7.11.0, created at 2025-12-20 11:53 +0000
« prev ^ index » next coverage.py v7.11.0, created at 2025-12-20 11:53 +0000
1from dataclasses import dataclass
4@dataclass
5class ValidatedAddress:
6 address_line_1: str
7 address_line_2: str | None
8 city: str
9 state: str | None
10 postal_code: str | None
11 country: str # ISO 3166-1 alpha-2
12 was_corrected: bool
13 is_deliverable: bool
16class AddressValidationError(Exception):
17 """Raised when address cannot be validated or is undeliverable."""
19 pass
22def validate_address(
23 address_line_1: str,
24 address_line_2: str | None,
25 city: str,
26 state: str | None,
27 postal_code: str | None,
28 country: str,
29) -> ValidatedAddress:
30 """
31 Validates and normalizes a postal address.
33 In production, this would call an external service like:
34 - Google Address Validation API
35 - Smarty (formerly SmartyStreets)
36 - Melissa
38 Args:
39 address_line_1: Street address (required)
40 address_line_2: Apartment/suite/unit (optional)
41 city: City or locality (required)
42 state: State/province/region (optional, varies by country)
43 postal_code: Postal/ZIP code (optional, some countries don't have them)
44 country: ISO 3166-1 alpha-2 country code (required)
46 Returns:
47 ValidatedAddress with normalized fields and deliverability status.
49 Raises:
50 AddressValidationError: If address is completely invalid/undeliverable
51 """
52 # STUB IMPLEMENTATION
53 # For now, just normalize and return as-is
54 return ValidatedAddress(
55 address_line_1=address_line_1.strip(),
56 address_line_2=address_line_2.strip() if address_line_2 else None,
57 city=city.strip(),
58 state=state.strip() if state else None,
59 postal_code=postal_code.strip() if postal_code else None,
60 country=country.strip().upper(),
61 was_corrected=False, # Stub always returns false
62 is_deliverable=True, # Stub always returns true
63 )