diff --git a/CHANGELOG.md b/CHANGELOG.md new file mode 100644 index 0000000..56a6f65 --- /dev/null +++ b/CHANGELOG.md @@ -0,0 +1,13 @@ +# IPInfo Changelog + +## 2.0.0 + +#### Breaking Changes + +- Fix [Issue #8](https://github.com/ipinfo/python/issues/8). + Deleted the `ip_address` key in the details object which was of type [`IPv4Address`](https://docs.python.org/3/library/ipaddress.html). + + This allows serializing the details object (into JSON or something else) without errors by default. + + Users who expected that object type can simply pull the `ip` key instead and turn it into an [`IPv4Address`](https://docs.python.org/3/library/ipaddress.html) + object on their own. diff --git a/README.md b/README.md index b05457a..15860e9 100644 --- a/README.md +++ b/README.md @@ -77,21 +77,6 @@ US United States ``` -### IP Address - -`details.ip_address` will return the an `ipaddress` object from the [Python Standard Library](https://docs.python.org/3/library/ipaddress.html). `details.ip` will still return a string. - -```python ->>> details.ip -104.175.221.247 ->>> type(details.ip) - ->>> details.ip_address -104.175.221.247 ->>> type(details.ip_address) - -``` - #### Longitude and Latitude `details.latitude` and `details.longitude` will return latitude and longitude, respectively, as strings. `details.loc` will still return a composite string of both values. @@ -125,7 +110,6 @@ United States 'country_name': 'United States', 'hostname': 'cpe-104-175-221-247.socal.res.rr.com', 'ip': '104.175.221.247', -'ip_address': IPv4Address('104.175.221.247'), 'loc': '34.0293,-118.3570', 'latitude': '34.0293', 'longitude': '-118.3570', diff --git a/ipinfo/handler.py b/ipinfo/handler.py index a4cc3fa..07ccceb 100644 --- a/ipinfo/handler.py +++ b/ipinfo/handler.py @@ -2,7 +2,6 @@ Main API client handler for fetching data from the IPinfo service. """ -import ipaddress import json import os import sys @@ -30,7 +29,6 @@ def __init__(self, access_token=None, **kwargs): """Initialize the Handler object with country name list and the cache initialized.""" self.access_token = access_token self.countries = self._read_country_names(kwargs.get("countries_file")) - self.request_options = kwargs.get("request_options", {}) if "timeout" not in self.request_options: self.request_options["timeout"] = self.REQUEST_TIMEOUT_DEFAULT @@ -47,7 +45,6 @@ def getDetails(self, ip_address=None): """Get details for specified IP address as a Details object.""" raw_details = self._requestDetails(ip_address) raw_details["country_name"] = self.countries.get(raw_details.get("country")) - raw_details["ip_address"] = ipaddress.ip_address(raw_details.get("ip")) raw_details["latitude"], raw_details["longitude"] = self._read_coords( raw_details.get("loc") ) @@ -73,7 +70,7 @@ def _requestDetails(self, ip_address=None): def _get_headers(self): """Built headers for request to IPinfo API.""" headers = { - "user-agent": "IPinfoClient/Python{version}/1.0".format( + "user-agent": "IPinfoClient/Python{version}/2.0.0".format( version=sys.version_info[0] ), "accept": "application/json", diff --git a/requirements.txt b/requirements.txt index 874fc8f..9078712 100644 --- a/requirements.txt +++ b/requirements.txt @@ -2,7 +2,7 @@ # This file is autogenerated by pip-compile # To update, run: # -# pip-compile --no-index --output-file=requirements.txt requirements.in +# pip-compile --no-index # appdirs==1.4.3 # via black atomicwrites==1.3.0 # via pytest @@ -13,13 +13,15 @@ certifi==2019.3.9 # via requests chardet==3.0.4 # via requests click==7.0 # via black, pip-tools idna==2.8 # via requests -more-itertools==6.0.0 # via pytest +importlib-metadata==0.18 # via pluggy +more-itertools==7.0.0 # via pytest pip-tools==3.7.0 -pluggy==0.9.0 # via pytest +pluggy==0.12.0 # via pytest py==1.8.0 # via pytest pytest==4.5.0 -requests==2.21.0 +requests==2.22.0 six==1.12.0 # via pip-tools, pytest toml==0.10.0 # via black -urllib3==1.24.1 # via requests +urllib3==1.25.3 # via requests wcwidth==0.1.7 # via pytest +zipp==0.5.1 # via importlib-metadata diff --git a/setup.py b/setup.py index 804bddb..217aaea 100644 --- a/setup.py +++ b/setup.py @@ -10,12 +10,12 @@ setup( name="ipinfo", - version="1.1.2", + version="2.0.0", description="Official Python library for IPInfo", long_description=long_description, url="https://github.com/ipinfo/python", - author="James Timmins", - author_email="jameshtimmins@gmail.com", + author="IPinfo", + author_email="support@ipinfo.io", license="Apache License 2.0", packages=["ipinfo", "ipinfo.cache"], install_requires=["requests", "cachetools", "six"], diff --git a/tests/default_cache_test.py b/tests/default_cache_test.py index 7827839..e4d1e7f 100644 --- a/tests/default_cache_test.py +++ b/tests/default_cache_test.py @@ -9,13 +9,13 @@ def _get_new_cache(): def test_contains(): cache = _get_new_cache() - cache['foo'] = 'bar' + cache["foo"] = "bar" - assert 'foo' in cache + assert "foo" in cache def test_get(): cache = _get_new_cache() - cache['foo'] = 'bar' + cache["foo"] = "bar" - assert cache['foo'] == 'bar' + assert cache["foo"] == "bar" diff --git a/tests/details_test.py b/tests/details_test.py index dd53c49..d53252e 100644 --- a/tests/details_test.py +++ b/tests/details_test.py @@ -4,25 +4,25 @@ def test_init(): - data = {'foo': 'bar'} + data = {"foo": "bar"} details = Details(data) assert details.details == data def test_getattr_success(): - data = {'foo': 'bar'} + data = {"foo": "bar"} details = Details(data) - assert details.foo == data['foo'] + assert details.foo == data["foo"] def test_getattr_fail(): - data = {'foo': 'bar'} + data = {"foo": "bar"} details = Details(data) with pytest.raises(Exception): details.blah def test_all(): - data = {'foo': 'bar', 'ham': 'eggs'} + data = {"foo": "bar", "ham": "eggs"} details = Details(data) assert details.all == data diff --git a/tests/handler_test.py b/tests/handler_test.py index 9368e5b..6a9769b 100644 --- a/tests/handler_test.py +++ b/tests/handler_test.py @@ -1,4 +1,4 @@ -import ipaddress +import json from ipinfo.cache.default import DefaultCache from ipinfo.details import Details @@ -6,39 +6,69 @@ def test_init(): - token = 'mytesttoken' + token = "mytesttoken" handler = Handler(token) assert handler.access_token == token assert isinstance(handler.cache, DefaultCache) - assert 'US' in handler.countries + assert "US" in handler.countries def test_headers(): - token = 'mytesttoken' + token = "mytesttoken" handler = Handler(token) headers = handler._get_headers() - assert 'user-agent' in headers - assert 'accept' in headers - assert 'authorization' in headers + assert "user-agent" in headers + assert "accept" in headers + assert "authorization" in headers def test_get_details(): + handler = Handler() + fake_details = {"country": "US", "ip": "127.0.0.1", "loc": "12.34,56.78"} + + handler._requestDetails = lambda x: fake_details + + details = handler.getDetails(fake_details["ip"]) + assert isinstance(details, Details) + assert details.country == fake_details["country"] + assert details.country_name == "United States" + assert details.ip == fake_details["ip"] + assert details.loc == fake_details["loc"] + assert details.longitude == "56.78" + assert details.latitude == "12.34" + + +def test_json_serialization(): handler = Handler() fake_details = { - 'country': 'US', - 'ip': '127.0.0.1', - 'loc': '12.34,56.78' + "asn": { + "asn": "AS20001", + "domain": "twcable.com", + "name": "Time Warner Cable Internet LLC", + "route": "104.172.0.0/14", + "type": "isp", + }, + "city": "Los Angeles", + "company": { + "domain": "twcable.com", + "name": "Time Warner Cable Internet LLC", + "type": "isp", + }, + "country": "US", + "country_name": "United States", + "hostname": "cpe-104-175-221-247.socal.res.rr.com", + "ip": "104.175.221.247", + "loc": "34.0293,-118.3570", + "latitude": "34.0293", + "longitude": "-118.3570", + "phone": "323", + "postal": "90016", + "region": "California", } handler._requestDetails = lambda x: fake_details - details = handler.getDetails(fake_details['ip']) + details = handler.getDetails(fake_details["ip"]) assert isinstance(details, Details) - assert details.country == fake_details['country'] - assert details.country_name == 'United States' - assert details.ip == fake_details['ip'] - assert isinstance(details.ip_address, ipaddress.IPv4Address) - assert details.loc == fake_details['loc'] - assert details.longitude == '56.78' - assert details.latitude == '12.34' + assert json.dumps(details.all) diff --git a/tests/init_test.py b/tests/init_test.py index fb20b9b..9a4f020 100644 --- a/tests/init_test.py +++ b/tests/init_test.py @@ -4,4 +4,4 @@ def test_get_handler(): handler = ipinfo.getHandler() - assert(isinstance(handler, Handler)) + assert isinstance(handler, Handler)