55
66"""
77import inspect
8+ from typing import Any , cast , List , Optional , Type , Union
89
910import maxminddb
1011
1112# pylint: disable=unused-import
12- from maxminddb import (
13+ from maxminddb import ( # type: ignore
1314 MODE_AUTO ,
1415 MODE_MMAP ,
1516 MODE_MMAP_EXT ,
2122import geoip2
2223import geoip2 .models
2324import geoip2 .errors
25+ from geoip2 .types import IPAddress
26+ from geoip2 .models import (
27+ ASN ,
28+ AnonymousIP ,
29+ City ,
30+ ConnectionType ,
31+ Country ,
32+ Domain ,
33+ Enterprise ,
34+ ISP ,
35+ )
2436
2537
26- class Reader ( object ) :
38+ class Reader :
2739 """GeoIP2 database Reader object.
2840
2941 Instances of this class provide a reader for the GeoIP2 database format.
@@ -47,7 +59,9 @@ class Reader(object):
4759
4860"""
4961
50- def __init__ (self , fileish , locales = None , mode = MODE_AUTO ):
62+ def __init__ (
63+ self , fileish : str , locales : Optional [List [str ]] = None , mode : int = MODE_AUTO
64+ ) -> None :
5165 """Create GeoIP2 Reader.
5266
5367 :param fileish: The string path to the GeoIP2 database, or an existing
@@ -94,13 +108,13 @@ def __init__(self, fileish, locales=None, mode=MODE_AUTO):
94108 self ._db_type = self ._db_reader .metadata ().database_type
95109 self ._locales = locales
96110
97- def __enter__ (self ):
111+ def __enter__ (self ) -> "Reader" :
98112 return self
99113
100- def __exit__ (self , exc_type , exc_value , traceback ) :
114+ def __exit__ (self , exc_type : None , exc_value : None , traceback : None ) -> None :
101115 self .close ()
102116
103- def country (self , ip_address ) :
117+ def country (self , ip_address : IPAddress ) -> Country :
104118 """Get the Country object for the IP address.
105119
106120 :param ip_address: IPv4 or IPv6 address as a string.
@@ -109,83 +123,101 @@ def country(self, ip_address):
109123
110124 """
111125
112- return self ._model_for (geoip2 .models .Country , "Country" , ip_address )
126+ return cast (
127+ Country , self ._model_for (geoip2 .models .Country , "Country" , ip_address )
128+ )
113129
114- def city (self , ip_address ) :
130+ def city (self , ip_address : IPAddress ) -> City :
115131 """Get the City object for the IP address.
116132
117133 :param ip_address: IPv4 or IPv6 address as a string.
118134
119135 :returns: :py:class:`geoip2.models.City` object
120136
121137 """
122- return self ._model_for (geoip2 .models .City , "City" , ip_address )
138+ return cast ( City , self ._model_for (geoip2 .models .City , "City" , ip_address ) )
123139
124- def anonymous_ip (self , ip_address ) :
140+ def anonymous_ip (self , ip_address : IPAddress ) -> AnonymousIP :
125141 """Get the AnonymousIP object for the IP address.
126142
127143 :param ip_address: IPv4 or IPv6 address as a string.
128144
129145 :returns: :py:class:`geoip2.models.AnonymousIP` object
130146
131147 """
132- return self ._flat_model_for (
133- geoip2 .models .AnonymousIP , "GeoIP2-Anonymous-IP" , ip_address
148+ return cast (
149+ AnonymousIP ,
150+ self ._flat_model_for (
151+ geoip2 .models .AnonymousIP , "GeoIP2-Anonymous-IP" , ip_address
152+ ),
134153 )
135154
136- def asn (self , ip_address ) :
155+ def asn (self , ip_address : IPAddress ) -> ASN :
137156 """Get the ASN object for the IP address.
138157
139158 :param ip_address: IPv4 or IPv6 address as a string.
140159
141160 :returns: :py:class:`geoip2.models.ASN` object
142161
143162 """
144- return self ._flat_model_for (geoip2 .models .ASN , "GeoLite2-ASN" , ip_address )
163+ return cast (
164+ ASN , self ._flat_model_for (geoip2 .models .ASN , "GeoLite2-ASN" , ip_address )
165+ )
145166
146- def connection_type (self , ip_address ) :
167+ def connection_type (self , ip_address : IPAddress ) -> ConnectionType :
147168 """Get the ConnectionType object for the IP address.
148169
149170 :param ip_address: IPv4 or IPv6 address as a string.
150171
151172 :returns: :py:class:`geoip2.models.ConnectionType` object
152173
153174 """
154- return self ._flat_model_for (
155- geoip2 .models .ConnectionType , "GeoIP2-Connection-Type" , ip_address
175+ return cast (
176+ ConnectionType ,
177+ self ._flat_model_for (
178+ geoip2 .models .ConnectionType , "GeoIP2-Connection-Type" , ip_address
179+ ),
156180 )
157181
158- def domain (self , ip_address ) :
182+ def domain (self , ip_address : IPAddress ) -> Domain :
159183 """Get the Domain object for the IP address.
160184
161185 :param ip_address: IPv4 or IPv6 address as a string.
162186
163187 :returns: :py:class:`geoip2.models.Domain` object
164188
165189 """
166- return self ._flat_model_for (geoip2 .models .Domain , "GeoIP2-Domain" , ip_address )
190+ return cast (
191+ Domain ,
192+ self ._flat_model_for (geoip2 .models .Domain , "GeoIP2-Domain" , ip_address ),
193+ )
167194
168- def enterprise (self , ip_address ) :
195+ def enterprise (self , ip_address : IPAddress ) -> Enterprise :
169196 """Get the Enterprise object for the IP address.
170197
171198 :param ip_address: IPv4 or IPv6 address as a string.
172199
173200 :returns: :py:class:`geoip2.models.Enterprise` object
174201
175202 """
176- return self ._model_for (geoip2 .models .Enterprise , "Enterprise" , ip_address )
203+ return cast (
204+ Enterprise ,
205+ self ._model_for (geoip2 .models .Enterprise , "Enterprise" , ip_address ),
206+ )
177207
178- def isp (self , ip_address ) :
208+ def isp (self , ip_address : IPAddress ) -> ISP :
179209 """Get the ISP object for the IP address.
180210
181211 :param ip_address: IPv4 or IPv6 address as a string.
182212
183213 :returns: :py:class:`geoip2.models.ISP` object
184214
185215 """
186- return self ._flat_model_for (geoip2 .models .ISP , "GeoIP2-ISP" , ip_address )
216+ return cast (
217+ ISP , self ._flat_model_for (geoip2 .models .ISP , "GeoIP2-ISP" , ip_address )
218+ )
187219
188- def _get (self , database_type , ip_address ) :
220+ def _get (self , database_type : str , ip_address : IPAddress ) -> Any :
189221 if database_type not in self ._db_type :
190222 caller = inspect .stack ()[2 ][3 ]
191223 raise TypeError (
@@ -197,29 +229,41 @@ def _get(self, database_type, ip_address):
197229 raise geoip2 .errors .AddressNotFoundError (
198230 "The address %s is not in the database." % ip_address
199231 )
200- return (record , prefix_len )
201-
202- def _model_for (self , model_class , types , ip_address ):
232+ return record , prefix_len
233+
234+ def _model_for (
235+ self ,
236+ model_class : Union [Type [Country ], Type [Enterprise ], Type [City ]],
237+ types : str ,
238+ ip_address : IPAddress ,
239+ ) -> Union [Country , Enterprise , City ]:
203240 (record , prefix_len ) = self ._get (types , ip_address )
204241 traits = record .setdefault ("traits" , {})
205242 traits ["ip_address" ] = ip_address
206243 traits ["prefix_len" ] = prefix_len
207244 return model_class (record , locales = self ._locales )
208245
209- def _flat_model_for (self , model_class , types , ip_address ):
246+ def _flat_model_for (
247+ self ,
248+ model_class : Union [
249+ Type [Domain ], Type [ISP ], Type [ConnectionType ], Type [ASN ], Type [AnonymousIP ]
250+ ],
251+ types : str ,
252+ ip_address : IPAddress ,
253+ ) -> Union [ConnectionType , ISP , AnonymousIP , Domain , ASN ]:
210254 (record , prefix_len ) = self ._get (types , ip_address )
211255 record ["ip_address" ] = ip_address
212256 record ["prefix_len" ] = prefix_len
213257 return model_class (record )
214258
215- def metadata (self ):
259+ def metadata (self ) -> maxminddb . reader . Metadata :
216260 """The metadata for the open database.
217261
218262 :returns: :py:class:`maxminddb.reader.Metadata` object
219263 """
220264 return self ._db_reader .metadata ()
221265
222- def close (self ):
266+ def close (self ) -> None :
223267 """Closes the GeoIP2 database."""
224268
225269 self ._db_reader .close ()
0 commit comments