|
2 | 2 | from http.client import HTTPSConnection |
3 | 3 | from io import StringIO |
4 | 4 | from json import loads |
5 | | -from urllib.parse import urlencode |
| 5 | +from urllib.parse import quote_plus, urlencode |
6 | 6 | from xml.etree.ElementTree import Element, fromstring |
7 | 7 |
|
8 | 8 | import requests |
|
15 | 15 | MultiDistance, |
16 | 16 | MultiRadius, |
17 | 17 | Radius, |
| 18 | + ZipCode, |
18 | 19 | ) |
19 | 20 | from pyzipcodeapi.enums import CountryEnum, DistanceUnitEnum, FormatEnum, GeoUnitEnum |
20 | 21 | from pyzipcodeapi.options import OPTIONS |
21 | 22 |
|
| 23 | +ResultType = DictReader | bytes | type | Element | Error | list[type] |
| 24 | + |
22 | 25 | BASE_URL = "https://www.zipcodeapi.com/rest/{api_key}/{option}.{format}/" |
23 | 26 | FORMAT = ["json", "xml", "csv"] |
24 | 27 |
|
@@ -149,9 +152,7 @@ def _post(self, option: str, path: str, data: dict): |
149 | 152 | headers=headers, |
150 | 153 | ) |
151 | 154 |
|
152 | | - def _parse_response( |
153 | | - self, data_class: type | None = None |
154 | | - ) -> DictReader | bytes | type | Element | Error | list[type]: |
| 155 | + def _parse_response(self, data_class: type | None = None) -> ResultType: |
155 | 156 | response = self.con.getresponse() |
156 | 157 | success = response.status == 200 |
157 | 158 | data = response.read() |
@@ -250,3 +251,19 @@ def multi_info( |
250 | 251 | """multi-info.<format>/<zip_code>/<units>""" |
251 | 252 | self._get("multi-info", f"{','.join(zip_codes)}/{units}") |
252 | 253 | return self._parse_response() |
| 254 | + |
| 255 | + def city_zip_codes( |
| 256 | + self, city: str, state: str |
| 257 | + ) -> ZipCode | DictReader | Element: |
| 258 | + """ |
| 259 | + US: city-zips.<format>/<city>/<state> |
| 260 | + CA: city-postal-codes.<format>/<city>/<province> |
| 261 | + """ |
| 262 | + option = "city-postal-codes" if self.country == CountryEnum.CA else "city-zips" |
| 263 | + self._get(option, f"{quote_plus(city)}/{quote_plus(state)}") |
| 264 | + return self._parse_response(data_class=ZipCode) |
| 265 | + |
| 266 | + def state_zip_codes(self, state: str) -> ZipCode | DictReader | Element: |
| 267 | + """state-zips.<format>/<state>""" |
| 268 | + self._get("state-zips", f"{quote_plus(state)}") |
| 269 | + return self._parse_response(data_class=ZipCode) |
0 commit comments