Skip to content

Commit d3e7eb9

Browse files
authored
Merge pull request #83 from ipinfo/error-handling
handling error body
2 parents 45b3378 + ed31024 commit d3e7eb9

File tree

6 files changed

+38
-12
lines changed

6 files changed

+38
-12
lines changed

ipinfo/error.py

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
import json
2+
3+
4+
class APIError(Exception):
5+
def __init__(self, error_code, error_json):
6+
self.error_code = error_code
7+
self.error_json = error_json
8+
9+
def __str__(self):
10+
return f"APIError: {self.error_code}\n{json.dumps(self.error_json, indent=2)}"

ipinfo/handler.py

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@
1010

1111
import requests
1212

13+
from .error import APIError
1314
from .cache.default import DefaultCache
1415
from .details import Details
1516
from .exceptions import RequestQuotaExceededError, TimeoutExceededError
@@ -140,7 +141,10 @@ def getDetails(self, ip_address=None, timeout=None):
140141
response = requests.get(url, headers=headers, **req_opts)
141142
if response.status_code == 429:
142143
raise RequestQuotaExceededError()
143-
response.raise_for_status()
144+
if response.status_code >= 400:
145+
error_response = response.json()
146+
error_code = response.status_code
147+
raise APIError(error_code, error_response)
144148
details = response.json()
145149

146150
# format & cache

ipinfo/handler_async.py

Lines changed: 7 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@
1111

1212
import aiohttp
1313

14+
from .error import APIError
1415
from .cache.default import DefaultCache
1516
from .details import Details
1617
from .exceptions import RequestQuotaExceededError, TimeoutExceededError
@@ -98,10 +99,10 @@ def __init__(self, access_token=None, **kwargs):
9899
if "ttl" not in cache_options:
99100
cache_options["ttl"] = CACHE_TTL
100101
self.cache = DefaultCache(**cache_options)
101-
102+
102103
# setup custom headers
103104
self.headers = kwargs.get("headers", None)
104-
105+
105106
async def init(self):
106107
"""
107108
Initializes internal aiohttp connection pool.
@@ -163,7 +164,10 @@ async def getDetails(self, ip_address=None, timeout=None):
163164
async with self.httpsess.get(url, headers=headers, **req_opts) as resp:
164165
if resp.status == 429:
165166
raise RequestQuotaExceededError()
166-
resp.raise_for_status()
167+
if resp.status >= 400:
168+
error_response = await resp.json()
169+
error_code = resp.status
170+
raise APIError(error_code, error_response)
167171
details = await resp.json()
168172

169173
# format & cache

ipinfo/handler_utils.py

Lines changed: 6 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -51,14 +51,14 @@
5151
def get_headers(access_token, custom_headers):
5252
"""Build headers for request to IPinfo API."""
5353
headers = {
54-
"user-agent": "IPinfoClient/Python{version}/{sdk_version}".format(
55-
version=sys.version_info[0], sdk_version=SDK_VERSION
54+
"user-agent": "IPinfoClient/Python{version}/{sdk_version}".format(
55+
version=sys.version_info[0], sdk_version=SDK_VERSION
5656
),
5757
"accept": "application/json",
5858
}
5959

6060
if custom_headers:
61-
headers = {** headers, ** custom_headers}
61+
headers = {**headers, **custom_headers}
6262

6363
if access_token:
6464
headers["authorization"] = "Bearer {}".format(access_token)
@@ -79,7 +79,9 @@ def format_details(
7979
"""
8080
details["country_name"] = countries.get(details.get("country"))
8181
details["isEU"] = details.get("country") in eu_countries
82-
details["country_flag_url"] = COUNTRY_FLAGS_URL + details.get("country") + ".svg"
82+
details["country_flag_url"] = (
83+
COUNTRY_FLAGS_URL + details.get("country") + ".svg"
84+
)
8385
details["country_flag"] = copy.deepcopy(
8486
countries_flags.get(details.get("country"))
8587
)

tests/handler_async_test.py

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -48,7 +48,10 @@ async def test_get_details():
4848
assert country_flag["emoji"] == "🇺🇸"
4949
assert country_flag["unicode"] == "U+1F1FA U+1F1F8"
5050
country_flag_url = details.country_flag_url
51-
assert country_flag_url == "https://cdn.ipinfo.io/static/images/countries-flags/US.svg"
51+
assert (
52+
country_flag_url
53+
== "https://cdn.ipinfo.io/static/images/countries-flags/US.svg"
54+
)
5255
country_currency = details.country_currency
5356
assert country_currency["code"] == "USD"
5457
assert country_currency["symbol"] == "$"
@@ -162,4 +165,4 @@ async def test_bogon_details():
162165
token = os.environ.get("IPINFO_TOKEN", "")
163166
handler = AsyncHandler(token)
164167
details = await handler.getDetails("127.0.0.1")
165-
assert details.all == {'bogon': True, 'ip': '127.0.0.1'}
168+
assert details.all == {"bogon": True, "ip": "127.0.0.1"}

tests/handler_test.py

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -45,7 +45,10 @@ def test_get_details():
4545
assert country_flag["emoji"] == "🇺🇸"
4646
assert country_flag["unicode"] == "U+1F1FA U+1F1F8"
4747
country_flag_url = details.country_flag_url
48-
assert country_flag_url == "https://cdn.ipinfo.io/static/images/countries-flags/US.svg"
48+
assert (
49+
country_flag_url
50+
== "https://cdn.ipinfo.io/static/images/countries-flags/US.svg"
51+
)
4952
country_currency = details.country_currency
5053
assert country_currency["code"] == "USD"
5154
assert country_currency["symbol"] == "$"
@@ -165,4 +168,4 @@ def test_bogon_details():
165168
handler = Handler(token)
166169
details = handler.getDetails("127.0.0.1")
167170
assert isinstance(details, Details)
168-
assert details.all == {'bogon': True, 'ip': '127.0.0.1'}
171+
assert details.all == {"bogon": True, "ip": "127.0.0.1"}

0 commit comments

Comments
 (0)