Skip to content

Commit 5fbdd1b

Browse files
committed
feat: add school districts support
- Add SchoolDistrict model - Add school_districts to GeocodioFields - Add unit and integration tests for school districts
1 parent 859a6d8 commit 5fbdd1b

File tree

4 files changed

+92
-3
lines changed

4 files changed

+92
-3
lines changed

src/geocodio/client.py

Lines changed: 25 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,7 @@
1313
from .models import (
1414
GeocodingResponse, GeocodingResult, AddressComponents,
1515
Location, GeocodioFields, Timezone, CongressionalDistrict,
16-
CensusData, ACSSurveyData
16+
CensusData, ACSSurveyData, StateLegislativeDistrict, SchoolDistrict
1717
)
1818
from .exceptions import InvalidRequestError, AuthenticationError, GeocodioServerError
1919

@@ -182,6 +182,27 @@ def _parse_fields(self, fields_data: dict | None) -> GeocodioFields | None:
182182
for cd in fields_data["congressional_districts"]
183183
]
184184

185+
state_legislative_districts = None
186+
if "stateleg" in fields_data:
187+
state_legislative_districts = [
188+
StateLegislativeDistrict.from_api(district)
189+
for district in fields_data["stateleg"]
190+
]
191+
192+
state_legislative_districts_next = None
193+
if "stateleg-next" in fields_data:
194+
state_legislative_districts_next = [
195+
StateLegislativeDistrict.from_api(district)
196+
for district in fields_data["stateleg-next"]
197+
]
198+
199+
school_districts = None
200+
if "school" in fields_data:
201+
school_districts = [
202+
SchoolDistrict.from_api(district)
203+
for district in fields_data["school"]
204+
]
205+
185206
census2010 = (
186207
CensusData.from_api(fields_data["census2010"])
187208
if "census2010" in fields_data else None
@@ -200,6 +221,9 @@ def _parse_fields(self, fields_data: dict | None) -> GeocodioFields | None:
200221
return GeocodioFields(
201222
timezone=timezone,
202223
congressional_districts=congressional_districts,
224+
state_legislative_districts=state_legislative_districts,
225+
state_legislative_districts_next=state_legislative_districts_next,
226+
school_districts=school_districts,
203227
census2010=census2010,
204228
census2020=census2020,
205229
acs=acs,

src/geocodio/models.py

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -121,6 +121,18 @@ class ACSSurveyData(_HasExtras, ApiModelMixin):
121121
extras: Dict[str, Any] = field(default_factory=dict, repr=False)
122122

123123

124+
@dataclass(slots=True, frozen=True)
125+
class SchoolDistrict(_HasExtras, ApiModelMixin):
126+
"""
127+
School district information.
128+
"""
129+
name: str
130+
district_number: Optional[str] = None
131+
lea_id: Optional[str] = None # Local Education Agency ID
132+
nces_id: Optional[str] = None # National Center for Education Statistics ID
133+
extras: Dict[str, Any] = field(default_factory=dict, repr=False)
134+
135+
124136
@dataclass(slots=True, frozen=True)
125137
class GeocodioFields:
126138
"""
@@ -131,6 +143,7 @@ class GeocodioFields:
131143
congressional_districts: Optional[List[CongressionalDistrict]] = None
132144
state_legislative_districts: Optional[List[StateLegislativeDistrict]] = None
133145
state_legislative_districts_next: Optional[List[StateLegislativeDistrict]] = None
146+
school_districts: Optional[List[SchoolDistrict]] = None
134147
census2010: Optional[CensusData] = None
135148
census2020: Optional[CensusData] = None
136149
acs: Optional[ACSSurveyData] = None

tests/e2e/test_api.py

Lines changed: 33 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -221,4 +221,36 @@ def test_integration_with_state_legislative_districts(client):
221221
if district.ocd_id:
222222
assert isinstance(district.ocd_id, str)
223223
if district.proportion:
224-
assert isinstance(district.proportion, float)
224+
assert isinstance(district.proportion, float)
225+
226+
227+
def test_integration_with_school_districts(client):
228+
"""Test real API call with school district fields."""
229+
# Test address
230+
address = "1600 Pennsylvania Ave NW, Washington, DC"
231+
232+
# Request additional fields
233+
response = client.geocode(
234+
address,
235+
fields=["school"]
236+
)
237+
238+
# Verify response structure
239+
assert response is not None
240+
assert len(response.results) > 0
241+
result = response.results[0]
242+
243+
# Verify fields data
244+
fields = result.fields
245+
assert fields is not None
246+
247+
# Check school districts
248+
if fields.school_districts:
249+
district = fields.school_districts[0]
250+
assert district.name is not None
251+
if district.district_number:
252+
assert isinstance(district.district_number, str)
253+
if district.lea_id:
254+
assert isinstance(district.lea_id, str)
255+
if district.nces_id:
256+
assert isinstance(district.nces_id, str)

tests/test_models.py

Lines changed: 21 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
import pytest
22
from geocodio.models import (
33
AddressComponents, Timezone, CongressionalDistrict,
4-
GeocodioFields, GeocodingResult, GeocodingResponse, Location, StateLegislativeDistrict
4+
GeocodioFields, GeocodingResult, GeocodingResponse, Location, StateLegislativeDistrict, SchoolDistrict
55
)
66

77

@@ -110,4 +110,24 @@ def test_state_legislative_district_extras():
110110
assert district.ocd_id == "ocd-division/country:us/state:va/sldl:8"
111111
assert district.proportion == 1.0
112112
assert district.get_extra("extra_field") == "extra value"
113+
assert district.get_extra("nonexistent", "default") == "default"
114+
115+
116+
def test_school_district_extras():
117+
# Test that extra fields are stored in extras
118+
data = {
119+
"name": "Arlington Public Schools",
120+
"district_number": "001",
121+
"lea_id": "5100000",
122+
"nces_id": "5100000",
123+
"extra_field": "extra value"
124+
}
125+
126+
district = SchoolDistrict.from_api(data)
127+
128+
assert district.name == "Arlington Public Schools"
129+
assert district.district_number == "001"
130+
assert district.lea_id == "5100000"
131+
assert district.nces_id == "5100000"
132+
assert district.get_extra("extra_field") == "extra value"
113133
assert district.get_extra("nonexistent", "default") == "default"

0 commit comments

Comments
 (0)