Skip to content

Commit 5f05a23

Browse files
committed
Get rid of some magic
This provides a fairly significant performance boost. It also makes the code more idiomatic and easier for static analyzers to understand.
1 parent 00560e6 commit 5f05a23

File tree

1 file changed

+132
-76
lines changed

1 file changed

+132
-76
lines changed

geoip2/records.py

Lines changed: 132 additions & 76 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@
44
=======
55
66
"""
7+
# pylint:disable=too-many-arguments,too-many-instance-attributes,too-many-locals
78

89
import ipaddress
910

@@ -19,15 +20,6 @@ class Record(SimpleEquality):
1920

2021
__metaclass__ = ABCMeta
2122

22-
_valid_attributes = set()
23-
24-
def __init__(self, **kwargs):
25-
for k in self._valid_attributes:
26-
self.__dict__[k] = kwargs.get(k)
27-
28-
def __setattr__(self, name, value):
29-
raise AttributeError("can't set attribute")
30-
3123
def __repr__(self):
3224
args = ', '.join('%s=%r' % x for x in self.__dict__.items())
3325
return '{module}.{class_name}({data})'.format(
@@ -41,13 +33,13 @@ class PlaceRecord(Record):
4133

4234
__metaclass__ = ABCMeta
4335

44-
def __init__(self, locales=None, **kwargs):
36+
def __init__(self, locales=None, names=None):
4537
if locales is None:
4638
locales = ['en']
47-
if kwargs.get('names') is None:
48-
kwargs['names'] = {}
49-
object.__setattr__(self, '_locales', locales)
50-
super(PlaceRecord, self).__init__(**kwargs)
39+
self._locales = locales
40+
if names is None:
41+
names = {}
42+
self.names = names
5143

5244
@property
5345
def name(self):
@@ -95,8 +87,15 @@ class City(PlaceRecord):
9587
:type: dict
9688
9789
"""
98-
99-
_valid_attributes = set(['confidence', 'geoname_id', 'names'])
90+
def __init__(self,
91+
locales=None,
92+
confidence=None,
93+
geoname_id=None,
94+
names=None,
95+
**_):
96+
self.confidence = confidence
97+
self.geoname_id = geoname_id
98+
super(City, self).__init__(locales, names)
10099

101100

102101
class Continent(PlaceRecord):
@@ -136,8 +135,15 @@ class Continent(PlaceRecord):
136135
:type: dict
137136
138137
"""
139-
140-
_valid_attributes = set(['code', 'geoname_id', 'names'])
138+
def __init__(self,
139+
locales=None,
140+
code=None,
141+
geoname_id=None,
142+
names=None,
143+
**_):
144+
self.code = code
145+
self.geoname_id = geoname_id
146+
super(Continent, self).__init__(locales, names)
141147

142148

143149
class Country(PlaceRecord):
@@ -191,15 +197,19 @@ class Country(PlaceRecord):
191197
:type: dict
192198
193199
"""
194-
195-
_valid_attributes = set([
196-
'confidence', 'geoname_id', 'is_in_european_union', 'iso_code', 'names'
197-
])
198-
199-
def __init__(self, locales=None, **kwargs):
200-
if 'is_in_european_union' not in kwargs:
201-
kwargs['is_in_european_union'] = False
202-
super(Country, self).__init__(locales, **kwargs)
200+
def __init__(self,
201+
locales=None,
202+
confidence=None,
203+
geoname_id=None,
204+
is_in_european_union=False,
205+
iso_code=None,
206+
names=None,
207+
**_):
208+
self.confidence = confidence
209+
self.geoname_id = geoname_id
210+
self.is_in_european_union = is_in_european_union
211+
self.iso_code = iso_code
212+
super(Country, self).__init__(locales, names)
203213

204214

205215
class RepresentedCountry(Country):
@@ -263,11 +273,21 @@ class RepresentedCountry(Country):
263273
:type: unicode
264274
265275
"""
266-
267-
_valid_attributes = set([
268-
'confidence', 'geoname_id', 'is_in_european_union', 'iso_code',
269-
'names', 'type'
270-
])
276+
def __init__(
277+
self,
278+
locales=None,
279+
confidence=None,
280+
geoname_id=None,
281+
is_in_european_union=False,
282+
iso_code=None,
283+
names=None,
284+
# pylint:disable=redefined-builtin
285+
type=None,
286+
**_):
287+
self.type = type
288+
super(RepresentedCountry,
289+
self).__init__(locales, confidence, geoname_id,
290+
is_in_european_union, iso_code, names)
271291

272292

273293
class Location(Record):
@@ -336,12 +356,27 @@ class Location(Record):
336356
:type: unicode
337357
338358
"""
339-
340-
_valid_attributes = set([
341-
'average_income', 'accuracy_radius', 'latitude', 'longitude',
342-
'metro_code', 'population_density', 'postal_code', 'postal_confidence',
343-
'time_zone'
344-
])
359+
def __init__(
360+
self,
361+
average_income=None,
362+
accuracy_radius=None,
363+
latitude=None,
364+
longitude=None,
365+
metro_code=None,
366+
population_density=None,
367+
postal_code=None,
368+
postal_confidence=None,
369+
time_zone=None,
370+
):
371+
self.average_income = average_income
372+
self.accuracy_radius = accuracy_radius
373+
self.latitude = latitude
374+
self.longitude = longitude
375+
self.metro_code = metro_code
376+
self.population_density = population_density
377+
self.postal_code = postal_code
378+
self.postal_confidence = postal_confidence
379+
self.time_zone = time_zone
345380

346381

347382
class MaxMind(Record):
@@ -357,8 +392,11 @@ class MaxMind(Record):
357392
:type: int
358393
359394
"""
360-
361-
_valid_attributes = set(['queries_remaining'])
395+
def __init__(
396+
self,
397+
queries_remaining=None,
398+
):
399+
self.queries_remaining = queries_remaining
362400

363401

364402
class Postal(Record):
@@ -388,8 +426,9 @@ class Postal(Record):
388426
:type: int
389427
390428
"""
391-
392-
_valid_attributes = set(['code', 'confidence'])
429+
def __init__(self, code=None, confidence=None):
430+
self.code = code
431+
self.confidence = confidence
393432

394433

395434
class Subdivision(PlaceRecord):
@@ -439,8 +478,17 @@ class Subdivision(PlaceRecord):
439478
:type: dict
440479
441480
"""
442-
443-
_valid_attributes = set(['confidence', 'geoname_id', 'iso_code', 'names'])
481+
def __init__(self,
482+
locales=None,
483+
confidence=None,
484+
geoname_id=None,
485+
iso_code=None,
486+
names=None,
487+
**_):
488+
self.confidence = confidence
489+
self.geoname_id = geoname_id
490+
self.iso_code = iso_code
491+
super(Subdivision, self).__init__(locales, names)
444492

445493

446494
class Subdivisions(tuple):
@@ -667,35 +715,43 @@ class Traits(Record):
667715
:type: unicode
668716
669717
"""
670-
671-
_valid_attributes = set([
672-
'autonomous_system_number', 'autonomous_system_organization',
673-
'connection_type', 'domain', 'is_anonymous', 'is_anonymous_proxy',
674-
'is_anonymous_vpn', 'is_hosting_provider', 'is_legitimate_proxy',
675-
'is_public_proxy', 'is_satellite_provider', 'is_tor_exit_node',
676-
'is_satellite_provider', 'isp', 'ip_address', 'network',
677-
'organization', 'user_type'
678-
])
679-
680-
def __init__(self, **kwargs):
681-
for k in [
682-
'is_anonymous',
683-
'is_anonymous_proxy',
684-
'is_anonymous_vpn',
685-
'is_hosting_provider',
686-
'is_legitimate_proxy',
687-
'is_public_proxy',
688-
'is_satellite_provider',
689-
'is_tor_exit_node',
690-
]:
691-
kwargs[k] = bool(kwargs.get(k, False))
692-
693-
try:
694-
network = kwargs['network']
695-
if not isinstance(network,
696-
(ipaddress.IPv4Network, ipaddress.IPv6Network)):
697-
kwargs['network'] = compat_ip_network(network)
698-
except KeyError:
699-
pass
700-
701-
super(Traits, self).__init__(**kwargs)
718+
def __init__(self,
719+
autonomous_system_number=None,
720+
autonomous_system_organization=None,
721+
connection_type=None,
722+
domain=None,
723+
is_anonymous=False,
724+
is_anonymous_proxy=False,
725+
is_anonymous_vpn=False,
726+
is_hosting_provider=False,
727+
is_legitimate_proxy=False,
728+
is_public_proxy=False,
729+
is_satellite_provider=False,
730+
is_tor_exit_node=False,
731+
isp=None,
732+
ip_address=None,
733+
network=None,
734+
organization=None,
735+
user_type=None,
736+
**_):
737+
738+
if network is not None and not isinstance(
739+
network, (ipaddress.IPv4Network, ipaddress.IPv6Network)):
740+
network = compat_ip_network(network)
741+
self.autonomous_system_number = autonomous_system_number
742+
self.autonomous_system_organization = autonomous_system_organization
743+
self.connection_type = connection_type
744+
self.domain = domain
745+
self.is_anonymous = is_anonymous
746+
self.is_anonymous_proxy = is_anonymous_proxy
747+
self.is_anonymous_vpn = is_anonymous_vpn
748+
self.is_hosting_provider = is_hosting_provider
749+
self.is_legitimate_proxy = is_legitimate_proxy
750+
self.is_public_proxy = is_public_proxy
751+
self.is_satellite_provider = is_satellite_provider
752+
self.is_tor_exit_node = is_tor_exit_node
753+
self.isp = isp
754+
self.ip_address = ip_address
755+
self.network = network
756+
self.organization = organization
757+
self.user_type = user_type

0 commit comments

Comments
 (0)