Skip to content

Commit a09ed5b

Browse files
committed
Some pylint-inspired clean-up. Also added pylint test to Travis.
1 parent 1624fb8 commit a09ed5b

File tree

10 files changed

+90
-69
lines changed

10 files changed

+90
-69
lines changed

.travis.yml

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,11 +5,14 @@ python:
55
- 3.2
66
- 3.3
77
- pypy
8-
script: nosetests
98
install:
109
- pip install -r requirements.txt
1110
- pip install git+https://github.com/maxmind/HTTPretty.git
11+
- pip install pylint
1212
- if [[ $TRAVIS_PYTHON_VERSION == '2.6' ]]; then pip install unittest2; fi
13+
script:
14+
- nosetests
15+
- pylint geoip2
1316
notifications:
1417
email:
1518
recipients:

geoip2/__init__.py

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,8 @@
1+
"""
2+
=================
3+
GeoIP2 Python API
4+
=================
5+
"""
16
__title__ = 'geoip2'
27
__version__ = '0.1'
38
__author__ = 'Gregory Oschwald'

geoip2/errors.py

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,7 @@ class GeoIP2Error(RuntimeError):
1414
"""
1515

1616

17-
class GeoIP2HTTPError(GeoIP2Error):
17+
class HTTPError(GeoIP2Error):
1818
"""There was an error when making your HTTP request.
1919
2020
This class represents an HTTP transport error. It extends
@@ -25,22 +25,22 @@ class GeoIP2HTTPError(GeoIP2Error):
2525
2626
"""
2727
def __init__(self, message, http_status=None, uri=None):
28-
super(GeoIP2HTTPError, self).__init__(message)
28+
super(HTTPError, self).__init__(message)
2929
self.http_status = http_status
3030
self.uri = uri
3131

3232

33-
class GeoIP2WebServiceError(GeoIP2HTTPError):
33+
class WebServiceError(HTTPError):
3434
"""The GeoIP2 web service returned an error.
3535
3636
This class represents an error returned by MaxMind's GeoIP2 Precision
37-
web service. It extends :py:exc:`GeoIP2HTTPError`.
37+
web service. It extends :py:exc:`HTTPError`.
3838
3939
:ivar code: The code returned by the MaxMind web service
4040
:ivar http_status: The HTTP status code returned
4141
:ivar uri: The URI queried
4242
4343
"""
4444
def __init__(self, message, code=None, http_status=None, uri=None):
45-
super(GeoIP2WebServiceError, self).__init__(message, http_status, uri)
45+
super(WebServiceError, self).__init__(message, http_status, uri)
4646
self.code = code

geoip2/models.py

Lines changed: 5 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@
1010
http://dev.maxmind.com/geoip/geoip2/web-services for more details.
1111
1212
"""
13+
#pylint:disable=R0903
1314
import geoip2.records
1415

1516

@@ -50,10 +51,10 @@ def __init__(self, raw_response, languages=None):
5051
geoip2.records.Country(languages,
5152
**raw_response.get('registered_country',
5253
{}))
53-
self.represented_country = \
54-
geoip2.records.RepresentedCountry(languages,
55-
**raw_response.get('represented_country',
56-
{}))
54+
self.represented_country \
55+
= geoip2.records.RepresentedCountry(languages,
56+
**raw_response.get(
57+
'represented_country', {}))
5758

5859
self.traits = geoip2.records.Traits(**raw_response.get('traits', {}))
5960
self.raw = raw_response

geoip2/records.py

Lines changed: 29 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -4,21 +4,22 @@
44
=======
55
66
"""
7-
7+
#pylint:disable=R0903
88
from abc import ABCMeta
9-
import collections
109

1110

1211
class Record(object):
1312
"""All records are subclasses of ``Record``"""
1413
__metaclass__ = ABCMeta
1514

15+
_valid_attributes = None
16+
1617
def __init__(self, **kwargs):
1718
valid_args = dict((k, kwargs.get(k)) for k in self._valid_attributes)
1819
self.__dict__.update(valid_args)
1920

2021
def __setattr__(self, name, value):
21-
raise NotImplementedError(name + ' is read-only.')
22+
raise AttributeError("can't set attribute")
2223

2324

2425
class PlaceRecord(Record):
@@ -35,6 +36,8 @@ def __init__(self, languages=None, **kwargs):
3536

3637
@property
3738
def name(self):
39+
"""Dict with language codes as keys and localized name as value"""
40+
#pylint:disable=E1101
3841
return next((self.names.get(x) for x in self._languages if x in
3942
self.names), None)
4043

@@ -100,9 +103,9 @@ class Country(PlaceRecord):
100103
end point.
101104
:ivar geoname_id: The GeoName ID for the country. This attribute is
102105
returned by all end points.
103-
:ivar iso_code: The two-character ISO 3166-1
104-
(http://en.wikipedia.org/wiki/ISO_3166-1) alpha code for the country.
105-
This attribute is returned by all end points.
106+
:ivar iso_code: The two-character `ISO 3166-1
107+
<http://en.wikipedia.org/wiki/ISO_3166-1>`_ alpha code for the
108+
country. This attribute is returned by all end points.
106109
:ivar name: The name of the country based on the languages list
107110
passed to the constructor. This attribute is returned by all end points.
108111
:ivar names: A dictionary where the keys are language codes and the values
@@ -115,8 +118,8 @@ class Country(PlaceRecord):
115118
class RepresentedCountry(Country):
116119
"""Contains data for the represented country associated with an IP address
117120
118-
This class contains the country-level data associated with an IP address for
119-
the IP's represented country. The represented country is the country
121+
This class contains the country-level data associated with an IP address
122+
for the IP's represented country. The represented country is the country
120123
represented by something like a military base or embassy.
121124
122125
This record is returned by all the end points.
@@ -128,8 +131,8 @@ class RepresentedCountry(Country):
128131
end point.
129132
:ivar geoname_id: The GeoName ID for the country. This attribute is
130133
returned by all end points.
131-
:ivar iso_code: The two-character ISO 3166-1
132-
(http://en.wikipedia.org/wiki/ISO_3166-1) alpha code for the country.
134+
:ivar iso_code: The two-character `ISO 3166-1
135+
<http://en.wikipedia.org/wiki/ISO_3166-1>`_ alpha code for the country.
133136
This attribute is returned by all end points.
134137
:ivar name: The name of the country based on the languages list
135138
passed to the constructor. This attribute is returned by all end points.
@@ -141,7 +144,8 @@ class RepresentedCountry(Country):
141144
endpoints.
142145
143146
"""
144-
_valid_attributes = set(['confidence', 'geoname_id', 'iso_code', 'names', 'type'])
147+
_valid_attributes = set(['confidence', 'geoname_id', 'iso_code',
148+
'names', 'type'])
145149

146150

147151
class Location(Record):
@@ -164,13 +168,13 @@ class Location(Record):
164168
except the Country end point.
165169
:ivar metro_code: The metro code of the location if the
166170
location is in the US. MaxMind returns the same metro codes as the
167-
Google AdWords API
168-
(https://developers.google.com/adwords/api/docs/appendix/cities-DMAregions).
171+
`Google AdWords API
172+
<https://developers.google.com/adwords/api/docs/appendix/cities-DMAregions>`_.
169173
This attribute is returned by all end points except the Country end
170174
point.
171175
:ivar time_zone: The time zone associated with location, as
172-
specified by the IANA Time Zone Database
173-
(http://www.iana.org/time-zones), e.g., "America/New_York". This
176+
specified by the `IANA Time Zone Database
177+
<http://www.iana.org/time-zones>`_, e.g., "America/New_York". This
174178
attribute is returned by all end points except the Country end point.
175179
176180
"""
@@ -215,9 +219,9 @@ class Subdivision(PlaceRecord):
215219
:ivar geoname_id: This is a GeoName ID for the subdivision. This
216220
attribute is returned by all end points except Country.
217221
:ivar iso_code: This is a string up to three characters long
218-
contain the subdivision portion of the ISO 3166-2 code
219-
(http://en.wikipedia.org/wiki/ISO_3166-2). This attribute is returned
220-
by all end points except Country.
222+
contain the subdivision portion of the `ISO 3166-2 code
223+
<http://en.wikipedia.org/wiki/ISO_3166-2>`_. This attribute is
224+
returned by all end points except Country.
221225
:ivar name: The name of the subdivision based on the languages list
222226
passed to the constructor. This attribute is returned by all end points.
223227
:ivar names: A dictionary where the keys are language codes and the
@@ -241,6 +245,7 @@ class Subdivisions(tuple):
241245
end point.
242246
243247
"""
248+
#pylint:disable=R0924,W0212,W0142
244249
def __new__(cls, languages, *subdivisions):
245250
subdivisions = [Subdivision(languages, **x) for x in subdivisions]
246251
obj = super(cls, Subdivisions).__new__(cls, subdivisions)
@@ -271,14 +276,14 @@ class Traits(Record):
271276
272277
This class has the following attributes:
273278
274-
:ivar autonomous_system_number: The autonomous system
275-
number (http://en.wikipedia.org/wiki/Autonomous_system_(Internet))
279+
:ivar autonomous_system_number: The `autonomous system
280+
number <http://en.wikipedia.org/wiki/Autonomous_system_(Internet)>`_
276281
associated with the IP address. This attribute is only available from
277282
the City/ISP/Org and Omni end points.
278283
:ivar autonomous_system_organization: The organization
279-
associated with the registered autonomous system number
280-
(http://en.wikipedia.org/wiki/Autonomous_system_(Internet)) for the IP
281-
address. This attribute is only available from the City/ISP/Org and
284+
associated with the registered `autonomous system number
285+
<http://en.wikipedia.org/wiki/Autonomous_system_(Internet)>`_ for the
286+
IP address. This attribute is only available from the City/ISP/Org and
282287
Omni end points.
283288
:ivar domain: The second level domain associated with the
284289
IP address. This will be something like "example.com" or
@@ -331,7 +336,7 @@ class Traits(Record):
331336
'organization',
332337
'user_type'])
333338

334-
def __init__(self, languages=None, **kwargs):
339+
def __init__(self, **kwargs):
335340
for k in ['is_anonymous_proxy', 'is_satellite_provider']:
336341
kwargs[k] = bool(kwargs.get(k, False))
337342
super(Traits, self).__init__(**kwargs)

geoip2/webservices.py

Lines changed: 27 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -60,14 +60,14 @@
6060
web service docs.
6161
6262
If the web service returns an explicit error document, this is thrown as a
63-
GeoIP2WebServiceError exception. If some other sort of error occurs, this is
64-
thrown as a GeoIP2HTTPError. The difference is that the webservice error
63+
WebServiceError exception. If some other sort of error occurs, this is
64+
thrown as a HTTPError. The difference is that the webservice error
6565
includes an error message and error code delivered by the web service. The
6666
latter is thrown when some sort of unanticipated error occurs, such as the
6767
web service returning a 500 or an invalid error document.
6868
6969
If the web service returns any status code besides 200, 4xx, or 5xx, this also
70-
becomes a GeoIP2HTTPError.
70+
becomes a HTTPError.
7171
7272
Finally, if the web service returns a 200 but the body is invalid, the client
7373
throws a GeoIP2Error object.
@@ -98,7 +98,7 @@
9898
import geoip2.models
9999
import requests
100100
from requests.utils import default_user_agent
101-
from .errors import GeoIP2Error, GeoIP2HTTPError, GeoIP2WebServiceError
101+
from .errors import GeoIP2Error, HTTPError, WebServiceError
102102

103103

104104
class Client(object):
@@ -206,66 +206,66 @@ def _response_for(self, path, model_class, ip_address):
206206
uri = '/'.join([self._base_uri, path, ip_address])
207207
response = requests.get(uri, auth=(self.user_id, self.license_key),
208208
headers={'Accept': 'application/json',
209-
'User-Agent': self._user_agent() })
210-
if (response.status_code == 200):
209+
'User-Agent': self._user_agent()})
210+
if (response.status_code == 200): #pylint:disable=E1103
211211
body = self._handle_success(response, uri)
212212
return model_class(body, languages=self.languages)
213213
else:
214214
self._handle_error(response, uri)
215215

216216
def _user_agent(self):
217217
return 'GeoIP2 Python Client v%s (%s)' % (geoip2.__version__,
218-
default_user_agent())
218+
default_user_agent())
219219

220220
def _handle_success(self, response, uri):
221221
try:
222222
return response.json()
223-
except ValueError as e:
223+
except ValueError as ex:
224224
raise GeoIP2Error('Received a 200 response for %(uri)s'
225225
' but could not decode the response as '
226226
'JSON: ' % locals() +
227-
', '.join(e.args), 200, uri)
227+
', '.join(ex.args), 200, uri)
228228

229229
def _handle_error(self, response, uri):
230230
status = response.status_code
231231

232232
if status >= 400 and status < 499:
233233
self._handle_4xx_status(response, status, uri)
234234
elif status >= 500 and status < 599:
235-
self._handle_5xx_status(response, status, uri)
235+
self._handle_5xx_status(status, uri)
236236
else:
237-
self._handle_non_200_status(response, status, uri)
237+
self._handle_non_200_status(status, uri)
238238

239239
def _handle_4xx_status(self, response, status, uri):
240240
if response.content:
241241
try:
242242
body = response.json()
243-
except ValueError as e:
244-
raise GeoIP2HTTPError(
243+
except ValueError as ex:
244+
raise HTTPError(
245245
'Received a %(status)i error for %(uri)s but it did'
246246
' not include the expected JSON body: ' % locals() +
247-
', '.join(e.args), status, uri)
247+
', '.join(ex.args), status, uri)
248248
else:
249249
if 'code' in body and 'error' in body:
250-
raise GeoIP2WebServiceError(body.get('error'),
251-
body.get('code'),
252-
status, uri)
250+
raise WebServiceError(body.get('error'),
251+
body.get('code'),
252+
status, uri)
253253
else:
254-
raise GeoIP2HTTPError(
254+
raise HTTPError(
255255
'Response contains JSON but it does not specify '
256256
'code or error keys', status, uri)
257257
else:
258-
raise GeoIP2HTTPError('Received a %(status)i error for %(uri)s '
259-
'with no body.' % locals(), status, uri)
258+
raise HTTPError('Received a %(status)i error for %(uri)s '
259+
'with no body.' % locals(), status, uri)
260260

261-
def _handle_5xx_status(self, response, status, uri):
262-
raise GeoIP2HTTPError('Received a server error (%(status)i) for '
263-
'%(uri)s' % locals(), status, uri)
261+
def _handle_5xx_status(self, status, uri):
262+
raise HTTPError('Received a server error (%(status)i) for '
263+
'%(uri)s' % locals(), status, uri)
264264

265-
def _handle_non_200_status(self, response, status, uri):
266-
raise GeoIP2HTTPError('Received a very surprising HTTP status '
267-
'(%(status)i) for %(uri)s' % locals(), status,
268-
uri)
265+
def _handle_non_200_status(self, status, uri):
266+
raise HTTPError('Received a very surprising HTTP status '
267+
'(%(status)i) for %(uri)s' % locals(), status,
268+
uri)
269269
"""
270270
271271
:copyright: (c) 2013 by MaxMind, Inc.

pylintrc

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
[MESSAGES CONTROL]
2+
disable=R0201,W0105
3+
4+
[BASIC]
5+
6+
no-docstring-rgx=_.*

setup.py

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,7 @@
3030
package_dir={'geoip2': 'geoip2'},
3131
include_package_data=True,
3232
install_requires=['requests'],
33+
test_suite="tests",
3334
license=open('LICENSE').read(),
3435
classifiers=(
3536
'Development Status :: 3 - Alpha',

tests/__init__.py

Whitespace-only changes.

0 commit comments

Comments
 (0)