11import re
2+ from typing import Union
23
34from ideal_ukpostcode .exceptions import InvalidArea , InvalidDistrict , InvalidSector , InvalidUnit
45
56
6- def validate_areacode (area ):
7- # Validate a uk postcode area
8- # input = The postcode area is either one or two characters long and is alphabetical.
9- # return = A boolean result with whether the postcode area is valid or not
10-
11- result = bool (re .match ("[A-Z]{1,2}$" , area ))
7+ def validate_areacode (area : Union [str , None ]) -> bool :
8+ """
9+ Validate a UK postcode area.
10+
11+ The postcode area is either one or two characters long and is alphabetical.
12+
13+ Args:
14+ area: The postcode area to validate
15+
16+ Returns:
17+ True if the postcode area is valid, False otherwise
18+ """
19+ if not area or not isinstance (area , str ):
20+ return False
21+ result = bool (re .match (r"^[A-Z]{1,2}$" , area ))
1222 return result
1323
1424
15- def validate_districtcode (district ):
16- # Validate a uk postcode district
17- # input = The postcode district is one digit, two digits or a digit followed by a letter.
18- # return = A boolean result with whether the postcode area is valid or not
19-
20- result = bool (re .match ("[0-9][A-Z0-9]?|ASCN|STHL|TDCU|BBND|[BFS]IQQ|PCRN|TKCA" , district ))
25+ def validate_districtcode (district : Union [str , None ]) -> bool :
26+ """
27+ Validate a UK postcode district.
28+
29+ The postcode district is one digit, two digits or a digit followed by a letter.
30+
31+ Args:
32+ district: The postcode district to validate
33+
34+ Returns:
35+ True if the postcode district is valid, False otherwise
36+ """
37+ if not district or not isinstance (district , str ):
38+ return False
39+ result = bool (re .match (r"^([0-9][A-Z0-9]?|ASCN|STHL|TDCU|BBND|[BFS]IQQ|PCRN|TKCA)$" , district ))
2140 return result
2241
2342
24- def validate_sectorcode (sector ):
25- # Validate a uk postcode sector
26- # input = The postcode sector is made up of a single digit
27- # return = A boolean result with whether the postcode sector is valid or not
28-
29- result = bool (re .match (r"\d$" , sector ))
43+ def validate_sectorcode (sector : Union [str , int , None ]) -> bool :
44+ """
45+ Validate a UK postcode sector.
46+
47+ The postcode sector is made up of a single digit.
48+
49+ Args:
50+ sector: The postcode sector to validate
51+
52+ Returns:
53+ True if the postcode sector is valid, False otherwise
54+ """
55+ if sector is None :
56+ return False
57+ result = bool (re .match (r"^\d$" , str (sector )))
3058 return result
3159
3260
33- def validate_unitcode (unit ):
34- # Validate a uk postcode unit
35- # input = The postcode unit is two characters
36- # return = A boolean result with whether the postcode sector is valid or not
37-
38- result = bool (re .match ("[A-Z]{2}$" , unit ))
61+ def validate_unitcode (unit : Union [str , None ]) -> bool :
62+ """
63+ Validate a UK postcode unit.
64+
65+ The postcode unit is two characters.
66+
67+ Args:
68+ unit: The postcode unit to validate
69+
70+ Returns:
71+ True if the postcode unit is valid, False otherwise
72+ """
73+ if not unit or not isinstance (unit , str ):
74+ return False
75+ result = bool (re .match (r"^[A-Z]{2}$" , unit ))
3976 return result
4077
4178
42- def format (area , district , sector , unit ):
43-
79+ def format (area : Union [str , None ], district : Union [str , None ],
80+ sector : Union [str , int , None ], unit : Union [str , None ]) -> str :
81+ """
82+ Format UK postcode components into a standard postcode string.
83+
84+ Args:
85+ area: The postcode area (1-2 alphabetical characters)
86+ district: The postcode district
87+ sector: The postcode sector (single digit)
88+ unit: The postcode unit (2 alphabetical characters)
89+
90+ Returns:
91+ Formatted postcode string (e.g., "EC1A 1BB")
92+
93+ Raises:
94+ InvalidArea: If the area code is invalid
95+ InvalidDistrict: If the district code is invalid
96+ InvalidSector: If the sector code is invalid
97+ InvalidUnit: If the unit code is invalid
98+ """
4499 if not validate_areacode (str (area )):
45100 raise InvalidArea
46101 if not validate_districtcode (str (district )):
@@ -50,7 +105,7 @@ def format(area, district, sector, unit):
50105 if not validate_unitcode (str (unit )):
51106 raise InvalidUnit
52107
53- outward_code = area + district
54- inward_code = str (sector ) + unit
108+ outward_code = str ( area ) + str ( district )
109+ inward_code = str (sector ) + str ( unit )
55110
56111 return outward_code + " " + inward_code
0 commit comments