Skip to content

Commit

Permalink
Geocodeio: fix GeocoderQueryError for empty result
Browse files Browse the repository at this point in the history
  • Loading branch information
KostyaEsmukov committed Apr 4, 2021
1 parent 9f18e98 commit fe0d493
Show file tree
Hide file tree
Showing 3 changed files with 37 additions and 5 deletions.
21 changes: 17 additions & 4 deletions geopy/geocoders/base.py
Original file line number Diff line number Diff line change
Expand Up @@ -208,6 +208,8 @@ class options:
504: GeocoderTimedOut
}

NONE_RESULT = object() # special return value for `_geocoder_exception_handler`


class Geocoder:
"""
Expand Down Expand Up @@ -335,6 +337,9 @@ def _geocoder_exception_handler(self, error):
Override if custom exceptions processing is needed.
For example, raising an appropriate GeocoderQuotaExceeded on non-200
response with a textual message in the body about the exceeded quota.
Return `NONE_RESULT` to have the geocoding call return `None` (meaning
empty result).
"""
pass

Expand Down Expand Up @@ -371,14 +376,18 @@ async def fut():
res = await res
return res
except Exception as error:
self._adapter_error_handler(error)
res = self._adapter_error_handler(error)
if res is NONE_RESULT:
return None
raise

return fut()
else:
return callback(result)
except Exception as error:
self._adapter_error_handler(error)
res = self._adapter_error_handler(error)
if res is NONE_RESULT:
return None
raise

def _adapter_error_handler(self, error):
Expand All @@ -390,7 +399,9 @@ def _adapter_error_handler(self, error):
error.text,
exc_info=False,
)
self._geocoder_exception_handler(error)
res = self._geocoder_exception_handler(error)
if res is NONE_RESULT:
return NONE_RESULT
exc_cls = ERROR_CODE_MAP.get(error.status_code, GeocoderServiceError)
if issubclass(exc_cls, GeocoderRateLimited):
raise exc_cls(
Expand All @@ -399,7 +410,9 @@ def _adapter_error_handler(self, error):
else:
raise exc_cls(str(error)) from error
else:
self._geocoder_exception_handler(error)
res = self._geocoder_exception_handler(error)
if res is NONE_RESULT:
return NONE_RESULT

# def geocode(self, query, *, exactly_one=True, timeout=DEFAULT_SENTINEL):
# raise NotImplementedError()
Expand Down
7 changes: 6 additions & 1 deletion geopy/geocoders/geocodio.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@

from geopy.adapters import AdapterHTTPError
from geopy.exc import GeocoderQueryError, GeocoderQuotaExceeded
from geopy.geocoders.base import DEFAULT_SENTINEL, Geocoder
from geopy.geocoders.base import DEFAULT_SENTINEL, NONE_RESULT, Geocoder
from geopy.location import Location
from geopy.util import logger

Expand Down Expand Up @@ -212,6 +212,11 @@ def _geocoder_exception_handler(self, error):
return
if error.status_code == 422:
error_message = self._get_error_message(error)
if (
'could not geocode address' in error_message.lower()
and 'postal code or city required' in error_message.lower()
):
return NONE_RESULT
raise GeocoderQueryError(error_message) from error
if error.status_code == 403:
error_message = self._get_error_message(error)
Expand Down
14 changes: 14 additions & 0 deletions test/geocoders/geocodio.py
Original file line number Diff line number Diff line change
Expand Up @@ -56,6 +56,20 @@ async def test_reverse(self):
)
assert "new york" in location.address.lower()

async def test_geocode_no_result(self):
await self.geocode_run(
{"query": "dksajdkjashdkjashdjasghd"},
{},
expect_failure=True,
)

async def test_geocode_structured_no_result(self):
await self.geocode_run(
{"query": {"city": "dkasdjksahdksajhd", "street": "sdahaskjdhask"}},
{},
expect_failure=True,
)

async def test_reverse_no_result(self):
await self.reverse_run(
# North Atlantic Ocean
Expand Down

0 comments on commit fe0d493

Please sign in to comment.