no longer accept None in result maker functions

This commit is contained in:
Sarah Hoffmann
2025-09-03 21:42:12 +02:00
parent 341c09ee95
commit 8339c2b928
10 changed files with 17 additions and 57 deletions

View File

@@ -19,7 +19,7 @@ from .logging import log
from . import types as ntyp from . import types as ntyp
from . import results as nres from . import results as nres
RowFunc = Callable[[Optional[SaRow], Type[nres.BaseResultT]], Optional[nres.BaseResultT]] RowFunc = Callable[[SaRow, Type[nres.BaseResultT]], nres.BaseResultT]
GEOMETRY_TYPE_MAP = { GEOMETRY_TYPE_MAP = {
'POINT': 'ST_Point', 'POINT': 'ST_Point',
@@ -74,7 +74,6 @@ class LookupCollector:
for row in await conn.execute(sql): for row in await conn.execute(sql):
result = row_func(row, nres.SearchResult) result = row_func(row, nres.SearchResult)
assert result is not None
if hasattr(row, 'bbox'): if hasattr(row, 'bbox'):
result.bbox = ntyp.Bbox.from_wkb(row.bbox) result.bbox = ntyp.Bbox.from_wkb(row.bbox)
@@ -116,7 +115,6 @@ class DetailedCollector:
for row in await conn.execute(sql): for row in await conn.execute(sql):
self.result = row_func(row, nres.DetailedResult) self.result = row_func(row, nres.DetailedResult)
assert self.result is not None
# add missing details # add missing details
if 'type' in self.result.geometry: if 'type' in self.result.geometry:
self.result.geometry['type'] = \ self.result.geometry['type'] = \

View File

@@ -310,15 +310,11 @@ def _filter_geometries(row: SaRow) -> Dict[str, str]:
if k.startswith('geometry_')} if k.startswith('geometry_')}
def create_from_placex_row(row: Optional[SaRow], def create_from_placex_row(row: SaRow, class_type: Type[BaseResultT]) -> BaseResultT:
class_type: Type[BaseResultT]) -> Optional[BaseResultT]:
""" Construct a new result and add the data from the result row """ Construct a new result and add the data from the result row
from the placex table. 'class_type' defines the type of result from the placex table. 'class_type' defines the type of result
to return. Returns None if the row is None. to return. Returns None if the row is None.
""" """
if row is None:
return None
return class_type(source_table=SourceTable.PLACEX, return class_type(source_table=SourceTable.PLACEX,
place_id=row.place_id, place_id=row.place_id,
osm_object=(row.osm_type, row.osm_id), osm_object=(row.osm_type, row.osm_id),
@@ -340,8 +336,7 @@ def create_from_placex_row(row: Optional[SaRow],
geometry=_filter_geometries(row)) geometry=_filter_geometries(row))
def create_from_osmline_row(row: Optional[SaRow], def create_from_osmline_row(row: SaRow, class_type: Type[BaseResultT]) -> BaseResultT:
class_type: Type[BaseResultT]) -> Optional[BaseResultT]:
""" Construct a new result and add the data from the result row """ Construct a new result and add the data from the result row
from the address interpolation table osmline. 'class_type' defines from the address interpolation table osmline. 'class_type' defines
the type of result to return. Returns None if the row is None. the type of result to return. Returns None if the row is None.
@@ -349,9 +344,6 @@ def create_from_osmline_row(row: Optional[SaRow],
If the row contains a housenumber, then the housenumber is filled out. If the row contains a housenumber, then the housenumber is filled out.
Otherwise the result contains the interpolation information in extratags. Otherwise the result contains the interpolation information in extratags.
""" """
if row is None:
return None
hnr = getattr(row, 'housenumber', None) hnr = getattr(row, 'housenumber', None)
res = class_type(source_table=SourceTable.OSMLINE, res = class_type(source_table=SourceTable.OSMLINE,
@@ -375,10 +367,10 @@ def create_from_osmline_row(row: Optional[SaRow],
return res return res
def create_from_tiger_row(row: Optional[SaRow], def create_from_tiger_row(row: SaRow,
class_type: Type[BaseResultT], class_type: Type[BaseResultT],
osm_type: Optional[str] = None, osm_type: Optional[str] = None,
osm_id: Optional[int] = None) -> Optional[BaseResultT]: osm_id: Optional[int] = None) -> BaseResultT:
""" Construct a new result and add the data from the result row """ Construct a new result and add the data from the result row
from the Tiger data interpolation table. 'class_type' defines from the Tiger data interpolation table. 'class_type' defines
the type of result to return. Returns None if the row is None. the type of result to return. Returns None if the row is None.
@@ -386,9 +378,6 @@ def create_from_tiger_row(row: Optional[SaRow],
If the row contains a housenumber, then the housenumber is filled out. If the row contains a housenumber, then the housenumber is filled out.
Otherwise the result contains the interpolation information in extratags. Otherwise the result contains the interpolation information in extratags.
""" """
if row is None:
return None
hnr = getattr(row, 'housenumber', None) hnr = getattr(row, 'housenumber', None)
res = class_type(source_table=SourceTable.TIGER, res = class_type(source_table=SourceTable.TIGER,
@@ -411,15 +400,11 @@ def create_from_tiger_row(row: Optional[SaRow],
return res return res
def create_from_postcode_row(row: Optional[SaRow], def create_from_postcode_row(row: SaRow, class_type: Type[BaseResultT]) -> BaseResultT:
class_type: Type[BaseResultT]) -> Optional[BaseResultT]:
""" Construct a new result and add the data from the result row """ Construct a new result and add the data from the result row
from the postcode table. 'class_type' defines from the postcode table. 'class_type' defines
the type of result to return. Returns None if the row is None. the type of result to return. Returns None if the row is None.
""" """
if row is None:
return None
return class_type(source_table=SourceTable.POSTCODE, return class_type(source_table=SourceTable.POSTCODE,
place_id=row.place_id, place_id=row.place_id,
parent_place_id=row.parent_place_id, parent_place_id=row.parent_place_id,
@@ -432,15 +417,11 @@ def create_from_postcode_row(row: Optional[SaRow],
geometry=_filter_geometries(row)) geometry=_filter_geometries(row))
def create_from_country_row(row: Optional[SaRow], def create_from_country_row(row: SaRow, class_type: Type[BaseResultT]) -> BaseResultT:
class_type: Type[BaseResultT]) -> Optional[BaseResultT]:
""" Construct a new result and add the data from the result row """ Construct a new result and add the data from the result row
from the fallback country tables. 'class_type' defines from the fallback country tables. 'class_type' defines
the type of result to return. Returns None if the row is None. the type of result to return. Returns None if the row is None.
""" """
if row is None:
return None
return class_type(source_table=SourceTable.COUNTRY, return class_type(source_table=SourceTable.COUNTRY,
category=('place', 'country'), category=('place', 'country'),
centroid=Point.from_wkb(row.centroid), centroid=Point.from_wkb(row.centroid),

View File

@@ -21,7 +21,7 @@ from .logging import log
from .types import AnyPoint, DataLayer, ReverseDetails, GeometryFormat, Bbox from .types import AnyPoint, DataLayer, ReverseDetails, GeometryFormat, Bbox
RowFunc = Callable[[Optional[SaRow], Type[nres.ReverseResult]], Optional[nres.ReverseResult]] RowFunc = Callable[[SaRow, Type[nres.ReverseResult]], nres.ReverseResult]
WKT_PARAM: SaBind = sa.bindparam('wkt', type_=Geometry) WKT_PARAM: SaBind = sa.bindparam('wkt', type_=Geometry)
MAX_RANK_PARAM: SaBind = sa.bindparam('max_rank') MAX_RANK_PARAM: SaBind = sa.bindparam('max_rank')
@@ -596,12 +596,13 @@ class ReverseGeocoder:
if row is None and self.layer_enabled(DataLayer.ADDRESS): if row is None and self.layer_enabled(DataLayer.ADDRESS):
row, row_func = await self.lookup_country(ccodes) row, row_func = await self.lookup_country(ccodes)
if row is None:
return None
result = row_func(row, nres.ReverseResult) result = row_func(row, nres.ReverseResult)
if result is not None: result.distance = getattr(row, 'distance', 0)
assert row is not None if hasattr(row, 'bbox'):
result.distance = getattr(row, 'distance', 0) result.bbox = Bbox.from_wkb(row.bbox)
if hasattr(row, 'bbox'): await nres.add_result_details(self.conn, [result], self.params)
result.bbox = Bbox.from_wkb(row.bbox)
await nres.add_result_details(self.conn, [result], self.params)
return result return result

View File

@@ -78,7 +78,6 @@ async def _get_placex_housenumbers(conn: SearchConnection,
for row in await conn.execute(sql): for row in await conn.execute(sql):
result = nres.create_from_placex_row(row, nres.SearchResult) result = nres.create_from_placex_row(row, nres.SearchResult)
assert result
result.bbox = Bbox.from_wkb(row.bbox) result.bbox = Bbox.from_wkb(row.bbox)
yield result yield result
@@ -102,9 +101,7 @@ async def _get_osmline(conn: SearchConnection, place_ids: List[int],
sql = base.add_geometry_columns(sa.select(sub), sub.c.centroid, details) sql = base.add_geometry_columns(sa.select(sub), sub.c.centroid, details)
for row in await conn.execute(sql): for row in await conn.execute(sql):
result = nres.create_from_osmline_row(row, nres.SearchResult) yield nres.create_from_osmline_row(row, nres.SearchResult)
assert result
yield result
async def _get_tiger(conn: SearchConnection, place_ids: List[int], async def _get_tiger(conn: SearchConnection, place_ids: List[int],
@@ -126,9 +123,7 @@ async def _get_tiger(conn: SearchConnection, place_ids: List[int],
sql = base.add_geometry_columns(sa.select(sub), sub.c.centroid, details) sql = base.add_geometry_columns(sa.select(sub), sub.c.centroid, details)
for row in await conn.execute(sql): for row in await conn.execute(sql):
result = nres.create_from_tiger_row(row, nres.SearchResult) yield nres.create_from_tiger_row(row, nres.SearchResult)
assert result
yield result
class AddressSearch(base.AbstractSearch): class AddressSearch(base.AbstractSearch):
@@ -325,7 +320,6 @@ class AddressSearch(base.AbstractSearch):
results = nres.SearchResults() results = nres.SearchResults()
for row in await conn.execute(sql, bind_params): for row in await conn.execute(sql, bind_params):
result = nres.create_from_placex_row(row, nres.SearchResult) result = nres.create_from_placex_row(row, nres.SearchResult)
assert result
result.bbox = Bbox.from_wkb(row.bbox) result.bbox = Bbox.from_wkb(row.bbox)
result.accuracy = row.accuracy result.accuracy = row.accuracy
if row.rank_address < 30: if row.rank_address < 30:

View File

@@ -56,7 +56,6 @@ class CountrySearch(base.AbstractSearch):
results = nres.SearchResults() results = nres.SearchResults()
for row in await conn.execute(sql, bind_params): for row in await conn.execute(sql, bind_params):
result = nres.create_from_placex_row(row, nres.SearchResult) result = nres.create_from_placex_row(row, nres.SearchResult)
assert result
result.accuracy = self.penalty + self.countries.get_penalty(row.country_code, 5.0) result.accuracy = self.penalty + self.countries.get_penalty(row.country_code, 5.0)
result.bbox = Bbox.from_wkb(row.bbox) result.bbox = Bbox.from_wkb(row.bbox)
results.append(result) results.append(result)
@@ -111,7 +110,6 @@ class CountrySearch(base.AbstractSearch):
results = nres.SearchResults() results = nres.SearchResults()
for row in await conn.execute(sql, bind_params): for row in await conn.execute(sql, bind_params):
result = nres.create_from_country_row(row, nres.SearchResult) result = nres.create_from_country_row(row, nres.SearchResult)
assert result
result.bbox = Bbox.from_wkb(row.bbox) result.bbox = Bbox.from_wkb(row.bbox)
result.accuracy = self.penalty + self.countries.get_penalty(row.country_code, 5.0) result.accuracy = self.penalty + self.countries.get_penalty(row.country_code, 5.0)
results.append(result) results.append(result)

View File

@@ -130,7 +130,6 @@ class NearSearch(base.AbstractSearch):
'countries': details.countries} 'countries': details.countries}
for row in await conn.execute(sql, bind_params): for row in await conn.execute(sql, bind_params):
result = nres.create_from_placex_row(row, nres.SearchResult) result = nres.create_from_placex_row(row, nres.SearchResult)
assert result
result.accuracy = self.penalty + penalty result.accuracy = self.penalty + penalty
result.bbox = Bbox.from_wkb(row.bbox) result.bbox = Bbox.from_wkb(row.bbox)
results.append(result) results.append(result)

View File

@@ -202,7 +202,6 @@ class PlaceSearch(base.AbstractSearch):
results = nres.SearchResults() results = nres.SearchResults()
for row in await conn.execute(sql, bind_params): for row in await conn.execute(sql, bind_params):
result = nres.create_from_placex_row(row, nres.SearchResult) result = nres.create_from_placex_row(row, nres.SearchResult)
assert result
result.bbox = Bbox.from_wkb(row.bbox) result.bbox = Bbox.from_wkb(row.bbox)
result.accuracy = row.accuracy result.accuracy = row.accuracy
results.append(result) results.append(result)

View File

@@ -106,7 +106,6 @@ class PoiSearch(base.AbstractSearch):
results = nres.SearchResults() results = nres.SearchResults()
for row in rows: for row in rows:
result = nres.create_from_placex_row(row, nres.SearchResult) result = nres.create_from_placex_row(row, nres.SearchResult)
assert result
result.accuracy = self.penalty + self.qualifiers.get_penalty((row.class_, row.type)) result.accuracy = self.penalty + self.qualifiers.get_penalty((row.class_, row.type))
result.bbox = Bbox.from_wkb(row.bbox) result.bbox = Bbox.from_wkb(row.bbox)
results.append(result) results.append(result)

View File

@@ -121,7 +121,6 @@ class PostcodeSearch(base.AbstractSearch):
else: else:
result = nres.create_from_postcode_row(row, nres.SearchResult) result = nres.create_from_postcode_row(row, nres.SearchResult)
assert result
if result.place_id not in details.excluded: if result.place_id not in details.excluded:
result.accuracy = row.accuracy result.accuracy = row.accuracy
results.append(result) results.append(result)

View File

@@ -48,14 +48,6 @@ def test_detailed_result_custom_importance():
assert res.calculated_importance() == 0.4563 assert res.calculated_importance() == 0.4563
@pytest.mark.parametrize('func', (nresults.create_from_placex_row,
nresults.create_from_osmline_row,
nresults.create_from_tiger_row,
nresults.create_from_postcode_row))
def test_create_row_none(func):
assert func(None, DetailedResult) is None
@pytest.mark.parametrize('func', (nresults.create_from_osmline_row, @pytest.mark.parametrize('func', (nresults.create_from_osmline_row,
nresults.create_from_tiger_row)) nresults.create_from_tiger_row))
def test_create_row_with_housenumber(func): def test_create_row_with_housenumber(func):