Skip to content

Commit 2305048

Browse files
authored
Merge pull request #96 from maxmind/greg/residential-proxy
Add is_residential_proxy
2 parents fe8e488 + d7b3dec commit 2305048

File tree

9 files changed

+52
-3
lines changed

9 files changed

+52
-3
lines changed

HISTORY.rst

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,12 @@
33
History
44
-------
55

6+
4.1.0
7+
++++++++++++++++++
8+
9+
* Added the ``is_residential_proxy`` attribute to ``geoip2.model.AnonymousIP``
10+
and ``geoip2.record.Traits``.
11+
612
4.0.2 (2020-07-28)
713
++++++++++++++++++
814

README.rst

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -229,6 +229,8 @@ Anonymous IP Database
229229
False
230230
>>> response.is_public_proxy
231231
False
232+
>>> response.is_residential_proxy
233+
False
232234
>>> response.is_tor_exit_node
233235
True
234236
>>> response.ip_address

geoip2/models.py

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -396,6 +396,13 @@ class AnonymousIP(SimpleModel):
396396
397397
:type: bool
398398
399+
.. attribute:: is_residential_proxy
400+
401+
This is true if the IP address is on a suspected anonymizing network
402+
and belongs to a residential ISP.
403+
404+
:type: bool
405+
399406
.. attribute:: is_tor_exit_node
400407
401408
This is true if the IP address is a Tor exit node.
@@ -421,6 +428,7 @@ class AnonymousIP(SimpleModel):
421428
is_anonymous_vpn: bool
422429
is_hosting_provider: bool
423430
is_public_proxy: bool
431+
is_residential_proxy: bool
424432
is_tor_exit_node: bool
425433

426434
def __init__(self, raw: Dict[str, bool]) -> None:
@@ -429,6 +437,7 @@ def __init__(self, raw: Dict[str, bool]) -> None:
429437
self.is_anonymous_vpn = raw.get("is_anonymous_vpn", False)
430438
self.is_hosting_provider = raw.get("is_hosting_provider", False)
431439
self.is_public_proxy = raw.get("is_public_proxy", False)
440+
self.is_residential_proxy = raw.get("is_residential_proxy", False)
432441
self.is_tor_exit_node = raw.get("is_tor_exit_node", False)
433442

434443

geoip2/records.py

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -693,6 +693,15 @@ class Traits(Record):
693693
694694
:type: bool
695695
696+
.. attribute:: is_residential_proxy
697+
698+
This is true if the IP address is on a suspected anonymizing network
699+
and belongs to a residential ISP. This attribute is only available from
700+
GeoIP2 Precision Insights.
701+
702+
:type: bool
703+
704+
696705
.. attribute:: is_satellite_provider
697706
698707
This is true if the IP address is from a satellite provider that
@@ -798,6 +807,7 @@ class Traits(Record):
798807
is_hosting_provider: bool
799808
is_legitimate_proxy: bool
800809
is_public_proxy: bool
810+
is_residential_proxy: bool
801811
is_satellite_provider: bool
802812
is_tor_exit_node: bool
803813
isp: Optional[str]
@@ -821,6 +831,7 @@ def __init__(
821831
is_hosting_provider: bool = False,
822832
is_legitimate_proxy: bool = False,
823833
is_public_proxy: bool = False,
834+
is_residential_proxy: bool = False,
824835
is_satellite_provider: bool = False,
825836
is_tor_exit_node: bool = False,
826837
isp: Optional[str] = None,
@@ -843,6 +854,7 @@ def __init__(
843854
self.is_hosting_provider = is_hosting_provider
844855
self.is_legitimate_proxy = is_legitimate_proxy
845856
self.is_public_proxy = is_public_proxy
857+
self.is_residential_proxy = is_residential_proxy
846858
self.is_satellite_provider = is_satellite_provider
847859
self.is_tor_exit_node = is_tor_exit_node
848860
self.isp = isp

setup.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -26,7 +26,7 @@
2626
include_package_data=True,
2727
python_requires=">=3.6",
2828
install_requires=requirements,
29-
tests_require=["mocket>=3.8.6"],
29+
tests_require=["mocket>=3.8.9"],
3030
test_suite="tests",
3131
license=geoip2.__license__,
3232
classifiers=[

tests/data

Submodule data updated 44 files

tests/database_test.py

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -66,11 +66,29 @@ def test_anonymous_ip(self) -> None:
6666
self.assertEqual(record.is_anonymous_vpn, True)
6767
self.assertEqual(record.is_hosting_provider, False)
6868
self.assertEqual(record.is_public_proxy, False)
69+
self.assertEqual(record.is_residential_proxy, False)
6970
self.assertEqual(record.is_tor_exit_node, False)
7071
self.assertEqual(record.ip_address, ip_address)
7172
self.assertEqual(record.network, ipaddress.ip_network("1.2.0.0/16"))
7273
reader.close()
7374

75+
def test_anonymous_ip_all_set(self) -> None:
76+
reader = geoip2.database.Reader(
77+
"tests/data/test-data/GeoIP2-Anonymous-IP-Test.mmdb"
78+
)
79+
ip_address = "81.2.69.1"
80+
81+
record = reader.anonymous_ip(ip_address)
82+
self.assertEqual(record.is_anonymous, True)
83+
self.assertEqual(record.is_anonymous_vpn, True)
84+
self.assertEqual(record.is_hosting_provider, True)
85+
self.assertEqual(record.is_public_proxy, True)
86+
self.assertEqual(record.is_residential_proxy, True)
87+
self.assertEqual(record.is_tor_exit_node, True)
88+
self.assertEqual(record.ip_address, ip_address)
89+
self.assertEqual(record.network, ipaddress.ip_network("81.2.69.0/24"))
90+
reader.close()
91+
7492
def test_asn(self) -> None:
7593
reader = geoip2.database.Reader("tests/data/test-data/GeoLite2-ASN-Test.mmdb")
7694

tests/models_test.py

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -79,6 +79,7 @@ def test_insights_full(self) -> None:
7979
"is_anonymous_vpn": True,
8080
"is_hosting_provider": True,
8181
"is_public_proxy": True,
82+
"is_residential_proxy": True,
8283
"is_satellite_provider": True,
8384
"is_tor_exit_node": True,
8485
"isp": "Comcast",
@@ -194,6 +195,7 @@ def test_insights_full(self) -> None:
194195
self.assertIs(model.traits.is_anonymous_vpn, True)
195196
self.assertIs(model.traits.is_hosting_provider, True)
196197
self.assertIs(model.traits.is_public_proxy, True)
198+
self.assertIs(model.traits.is_residential_proxy, True)
197199
self.assertIs(model.traits.is_satellite_provider, True)
198200
self.assertIs(model.traits.is_tor_exit_node, True)
199201
self.assertEqual(model.traits.user_count, 2)

tests/webservice_test.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,7 @@
1414
# httpretty currently doesn't work, but mocket with the compat interface
1515
# does.
1616
from mocket import Mocket # type: ignore
17-
from mocket.plugins.httpretty import HTTPretty as httpretty, httprettified # type: ignore
17+
from mocket.plugins.httpretty import httpretty, httprettified # type: ignore
1818
import geoip2
1919
from geoip2.errors import (
2020
AddressNotFoundError,

0 commit comments

Comments
 (0)