Skip to content

Commit 9607370

Browse files
committed
Add MCC/MNC support
1 parent 5f44f43 commit 9607370

File tree

4 files changed

+83
-18
lines changed

4 files changed

+83
-18
lines changed

HISTORY.rst

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,19 @@
1+
12
.. :changelog:
23
34
History
45
-------
56

7+
4.5.0
8+
++++++++++++++++++
9+
10+
* Support for mobile country code (MCC) and mobile network codes (MNC) was
11+
added for the GeoIP2 ISP and Enterprise databases as well as the GeoIP2
12+
City and Insights web services. ``mobile_country_code`` and
13+
``mobile_network_code`` attributes were added to ``geoip2.model.ISP``
14+
for the GeoIP2 ISP database and ``geoip2.record.Traits`` for the
15+
Enterprise database and the GeoIP2 City and Insights web services.
16+
617
4.4.0 (2021-09-24)
718
++++++++++++++++++
819

geoip2/models.py

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -577,6 +577,23 @@ class ISP(ASN):
577577
578578
:type: unicode
579579
580+
.. attribute: mobile_country_code
581+
582+
The `mobile country code (MCC)
583+
<https://en.wikipedia.org/wiki/Mobile_country_code>`_ associated with the
584+
IP address and ISP.
585+
586+
:type: str
587+
588+
.. attribute: mobile_network_code
589+
590+
The `mobile network code (MCC)
591+
<https://en.wikipedia.org/wiki/Mobile_country_code>`_ associated with the
592+
IP address and ISP.
593+
594+
:type: str
595+
596+
580597
.. attribute:: organization
581598
582599
The name of the organization associated with the IP address.
@@ -599,10 +616,14 @@ class ISP(ASN):
599616
"""
600617

601618
isp: Optional[str]
619+
mobile_country_code: Optional[str]
620+
mobile_network_code: Optional[str]
602621
organization: Optional[str]
603622

604623
# pylint:disable=too-many-arguments
605624
def __init__(self, raw: Dict[str, Union[str, int]]) -> None:
606625
super().__init__(raw)
607626
self.isp = cast(Optional[str], raw.get("isp"))
627+
self.mobile_country_code = cast(Optional[str], raw.get("mobile_country_code"))
628+
self.mobile_network_code = cast(Optional[str], raw.get("mobile_network_code"))
608629
self.organization = cast(Optional[str], raw.get("organization"))

geoip2/records.py

Lines changed: 25 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -713,7 +713,7 @@ class Traits(Record):
713713
714714
.. attribute:: is_tor_exit_node
715715
716-
This is true if the IP address is a Tor exit node. This attribute is
716+
This is true if the IP address is a Tor exit node. This attribute is
717717
only available from GeoIP2 Precision Insights.
718718
719719
:type: bool
@@ -726,6 +726,24 @@ class Traits(Record):
726726
727727
:type: unicode
728728
729+
.. attribute: mobile_country_code
730+
731+
The `mobile country code (MCC)
732+
<https://en.wikipedia.org/wiki/Mobile_country_code>`_ associated with the
733+
IP address and ISP. This attribute is available from the City and
734+
Insights web services and the GeoIP2 Enterprise database.
735+
736+
:type: str
737+
738+
.. attribute: mobile_network_code
739+
740+
The `mobile network code (MCC)
741+
<https://en.wikipedia.org/wiki/Mobile_country_code>`_ associated with the
742+
IP address and ISP. This attribute is available from the City and
743+
Insights web services and the GeoIP2 Enterprise database.
744+
745+
:type: str
746+
729747
.. attribute:: network
730748
731749
The network associated with the record. In particular, this is the
@@ -808,6 +826,8 @@ class Traits(Record):
808826
is_tor_exit_node: bool
809827
isp: Optional[str]
810828
ip_address: Optional[str]
829+
mobile_country_code: Optional[str]
830+
mobile_network_code: Optional[str]
811831
organization: Optional[str]
812832
static_ip_score: Optional[float]
813833
user_count: Optional[int]
@@ -838,6 +858,8 @@ def __init__(
838858
static_ip_score: Optional[float] = None,
839859
user_count: Optional[int] = None,
840860
user_type: Optional[str] = None,
861+
mobile_country_code: Optional[str] = None,
862+
mobile_network_code: Optional[str] = None,
841863
**_,
842864
) -> None:
843865
self.autonomous_system_number = autonomous_system_number
@@ -854,6 +876,8 @@ def __init__(
854876
self.is_satellite_provider = is_satellite_provider
855877
self.is_tor_exit_node = is_tor_exit_node
856878
self.isp = isp
879+
self.mobile_country_code = mobile_country_code
880+
self.mobile_network_code = mobile_network_code
857881
self.organization = organization
858882
self.static_ip_score = static_ip_score
859883
self.user_type = user_type

tests/database_test.py

Lines changed: 26 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -199,27 +199,36 @@ def test_enterprise(self) -> None:
199199
record.traits.network, ipaddress.ip_network("74.209.16.0/20")
200200
)
201201

202-
def test_isp(self) -> None:
203-
reader = geoip2.database.Reader("tests/data/test-data/GeoIP2-ISP-Test.mmdb")
202+
record = reader.enterprise("149.101.100.0")
204203

205-
ip_address = "1.128.0.0"
206-
record = reader.isp(ip_address)
207-
self.assertEqual(record, eval(repr(record)), "ISP repr can be eval'd")
204+
self.assertEqual(record.traits.mobile_country_code, "310")
205+
self.assertEqual(record.traits.mobile_network_code, "004")
208206

209-
self.assertEqual(record.autonomous_system_number, 1221)
210-
self.assertEqual(record.autonomous_system_organization, "Telstra Pty Ltd")
211-
self.assertEqual(record.isp, "Telstra Internet")
212-
self.assertEqual(record.organization, "Telstra Internet")
213-
self.assertEqual(record.ip_address, ip_address)
214-
self.assertEqual(record.network, ipaddress.ip_network("1.128.0.0/11"))
207+
def test_isp(self) -> None:
208+
with geoip2.database.Reader(
209+
"tests/data/test-data/GeoIP2-ISP-Test.mmdb"
210+
) as reader:
211+
ip_address = "1.128.0.0"
212+
record = reader.isp(ip_address)
213+
self.assertEqual(record, eval(repr(record)), "ISP repr can be eval'd")
214+
215+
self.assertEqual(record.autonomous_system_number, 1221)
216+
self.assertEqual(record.autonomous_system_organization, "Telstra Pty Ltd")
217+
self.assertEqual(record.isp, "Telstra Internet")
218+
self.assertEqual(record.organization, "Telstra Internet")
219+
self.assertEqual(record.ip_address, ip_address)
220+
self.assertEqual(record.network, ipaddress.ip_network("1.128.0.0/11"))
221+
222+
self.assertRegex(
223+
str(record),
224+
r"ISP\(\{.*Telstra.*\}\)",
225+
"ISP str representation is reasonable",
226+
)
215227

216-
self.assertRegex(
217-
str(record),
218-
r"ISP\(\{.*Telstra.*\}\)",
219-
"ISP str representation is reasonable",
220-
)
228+
record = reader.isp("149.101.100.0")
221229

222-
reader.close()
230+
self.assertEqual(record.mobile_country_code, "310")
231+
self.assertEqual(record.mobile_network_code, "004")
223232

224233
def test_context_manager(self) -> None:
225234
with geoip2.database.Reader(

0 commit comments

Comments
 (0)