From 6dbde7271c2da7bf93dbb73357f1818da69f1251 Mon Sep 17 00:00:00 2001 From: Aarni Koskela Date: Tue, 27 Aug 2024 10:25:52 +0300 Subject: [PATCH 01/11] Do not manipulate `sys.path` in tests --- tests/database_test.py | 3 --- tests/models_test.py | 3 --- tests/webservice_test.py | 3 --- 3 files changed, 9 deletions(-) diff --git a/tests/database_test.py b/tests/database_test.py index 73279dc..7e8b365 100644 --- a/tests/database_test.py +++ b/tests/database_test.py @@ -4,12 +4,9 @@ from __future__ import unicode_literals import ipaddress -import sys import unittest from unittest.mock import patch, MagicMock -sys.path.append("..") - import geoip2.database import geoip2.errors import maxminddb diff --git a/tests/models_test.py b/tests/models_test.py index 9f4fa72..47a6d41 100644 --- a/tests/models_test.py +++ b/tests/models_test.py @@ -3,12 +3,9 @@ from __future__ import unicode_literals -import sys from typing import Dict import unittest -sys.path.append("..") - import geoip2.models diff --git a/tests/webservice_test.py b/tests/webservice_test.py index 813738f..7318d7d 100644 --- a/tests/webservice_test.py +++ b/tests/webservice_test.py @@ -4,8 +4,6 @@ import asyncio import copy import ipaddress -import json -import sys from typing import cast, Dict import unittest from pytest_httpserver import HeaderValueMatcher @@ -14,7 +12,6 @@ from collections import defaultdict -sys.path.append("..") import geoip2 from geoip2.errors import ( AddressNotFoundError, From c20a22fb696f2feac1b0f2c6ff0cdc2b47d3701e Mon Sep 17 00:00:00 2001 From: Aarni Koskela Date: Tue, 27 Aug 2024 11:19:06 +0300 Subject: [PATCH 02/11] Remove antiquated codings/futures --- tests/database_test.py | 2 -- tests/models_test.py | 2 -- tests/webservice_test.py | 1 - 3 files changed, 5 deletions(-) diff --git a/tests/database_test.py b/tests/database_test.py index 7e8b365..921bfbc 100644 --- a/tests/database_test.py +++ b/tests/database_test.py @@ -1,7 +1,5 @@ #!/usr/bin/env python -# -*- coding: utf-8 -*- -from __future__ import unicode_literals import ipaddress import unittest diff --git a/tests/models_test.py b/tests/models_test.py index 47a6d41..9d61279 100644 --- a/tests/models_test.py +++ b/tests/models_test.py @@ -1,7 +1,5 @@ #!/usr/bin/env python -# -*- coding: utf-8 -*- -from __future__ import unicode_literals from typing import Dict import unittest diff --git a/tests/webservice_test.py b/tests/webservice_test.py index 7318d7d..3c97bb9 100644 --- a/tests/webservice_test.py +++ b/tests/webservice_test.py @@ -1,5 +1,4 @@ #!/usr/bin/env python -# -*- coding: utf-8 -*- import asyncio import copy From fabcc1d27f7e6c0f379abb69d4bacfaaa6c89524 Mon Sep 17 00:00:00 2001 From: Aarni Koskela Date: Tue, 27 Aug 2024 11:20:53 +0300 Subject: [PATCH 03/11] Run codemod-unittest-to-pytest-asserts --- tests/database_test.py | 146 +++++++------- tests/models_test.py | 405 ++++++++++++++++----------------------- tests/webservice_test.py | 106 +++++----- 3 files changed, 277 insertions(+), 380 deletions(-) diff --git a/tests/database_test.py b/tests/database_test.py index 921bfbc..8cca30f 100644 --- a/tests/database_test.py +++ b/tests/database_test.py @@ -23,7 +23,7 @@ def test_language_list(self) -> None: ) record = reader.country("81.2.69.160") - self.assertEqual(record.country.name, "Великобритания") + assert record.country.name == "Великобритания" reader.close() def test_unknown_address(self) -> None: @@ -41,7 +41,7 @@ def test_unknown_address_network(self) -> None: reader.city("10.10.10.10") self.fail("Expected AddressNotFoundError") except geoip2.errors.AddressNotFoundError as e: - self.assertEqual(e.network, ipaddress.ip_network("10.0.0.0/8")) + assert e.network == ipaddress.ip_network("10.0.0.0/8") except Exception as e: self.fail(f"Expected AddressNotFoundError, got {type(e)}: {str(e)}") finally: @@ -71,14 +71,14 @@ def test_anonymous_ip(self) -> None: ip_address = "1.2.0.1" record = reader.anonymous_ip(ip_address) - self.assertEqual(record.is_anonymous, True) - self.assertEqual(record.is_anonymous_vpn, True) - self.assertEqual(record.is_hosting_provider, False) - self.assertEqual(record.is_public_proxy, False) - self.assertEqual(record.is_residential_proxy, False) - self.assertEqual(record.is_tor_exit_node, False) - self.assertEqual(record.ip_address, ip_address) - self.assertEqual(record.network, ipaddress.ip_network("1.2.0.0/16")) + assert record.is_anonymous is True + assert record.is_anonymous_vpn is True + assert record.is_hosting_provider is False + assert record.is_public_proxy is False + assert record.is_residential_proxy is False + assert record.is_tor_exit_node is False + assert record.ip_address == ip_address + assert record.network == ipaddress.ip_network("1.2.0.0/16") reader.close() def test_anonymous_ip_all_set(self) -> None: @@ -88,14 +88,14 @@ def test_anonymous_ip_all_set(self) -> None: ip_address = "81.2.69.1" record = reader.anonymous_ip(ip_address) - self.assertEqual(record.is_anonymous, True) - self.assertEqual(record.is_anonymous_vpn, True) - self.assertEqual(record.is_hosting_provider, True) - self.assertEqual(record.is_public_proxy, True) - self.assertEqual(record.is_residential_proxy, True) - self.assertEqual(record.is_tor_exit_node, True) - self.assertEqual(record.ip_address, ip_address) - self.assertEqual(record.network, ipaddress.ip_network("81.2.69.0/24")) + assert record.is_anonymous is True + assert record.is_anonymous_vpn is True + assert record.is_hosting_provider is True + assert record.is_public_proxy is True + assert record.is_residential_proxy is True + assert record.is_tor_exit_node is True + assert record.ip_address == ip_address + assert record.network == ipaddress.ip_network("81.2.69.0/24") reader.close() def test_asn(self) -> None: @@ -104,12 +104,12 @@ def test_asn(self) -> None: ip_address = "1.128.0.0" record = reader.asn(ip_address) - self.assertEqual(record, eval(repr(record)), "ASN repr can be eval'd") + assert record == eval(repr(record)), "ASN repr can be eval'd" - self.assertEqual(record.autonomous_system_number, 1221) - self.assertEqual(record.autonomous_system_organization, "Telstra Pty Ltd") - self.assertEqual(record.ip_address, ip_address) - self.assertEqual(record.network, ipaddress.ip_network("1.128.0.0/11")) + assert record.autonomous_system_number == 1221 + assert record.autonomous_system_organization == "Telstra Pty Ltd" + assert record.ip_address == ip_address + assert record.network == ipaddress.ip_network("1.128.0.0/11") self.assertRegex( str(record), @@ -123,18 +123,16 @@ def test_city(self) -> None: reader = geoip2.database.Reader("tests/data/test-data/GeoIP2-City-Test.mmdb") record = reader.city("81.2.69.160") - self.assertEqual( - record.country.name, "United Kingdom", "The default locale is en" - ) - self.assertEqual(record.country.is_in_european_union, False) - self.assertEqual( - record.location.accuracy_radius, 100, "The accuracy_radius is populated" - ) - self.assertEqual(record.registered_country.is_in_european_union, False) - self.assertFalse(record.traits.is_anycast) + assert record.country.name == "United Kingdom", "The default locale is en" + assert record.country.is_in_european_union is False + assert ( + record.location.accuracy_radius == 100 + ), "The accuracy_radius is populated" + assert record.registered_country.is_in_european_union is False + assert not record.traits.is_anycast record = reader.city("214.1.1.0") - self.assertTrue(record.traits.is_anycast) + assert record.traits.is_anycast reader.close() @@ -146,13 +144,11 @@ def test_connection_type(self) -> None: record = reader.connection_type(ip_address) - self.assertEqual( - record, eval(repr(record)), "ConnectionType repr can be eval'd" - ) + assert record == eval(repr(record)), "ConnectionType repr can be eval'd" - self.assertEqual(record.connection_type, "Cellular") - self.assertEqual(record.ip_address, ip_address) - self.assertEqual(record.network, ipaddress.ip_network("1.0.1.0/24")) + assert record.connection_type == "Cellular" + assert record.ip_address == ip_address + assert record.network == ipaddress.ip_network("1.0.1.0/24") self.assertRegex( str(record), @@ -165,16 +161,14 @@ def test_connection_type(self) -> None: def test_country(self) -> None: reader = geoip2.database.Reader("tests/data/test-data/GeoIP2-Country-Test.mmdb") record = reader.country("81.2.69.160") - self.assertEqual( - record.traits.ip_address, "81.2.69.160", "IP address is added to model" - ) - self.assertEqual(record.traits.network, ipaddress.ip_network("81.2.69.160/27")) - self.assertEqual(record.country.is_in_european_union, False) - self.assertEqual(record.registered_country.is_in_european_union, False) - self.assertFalse(record.traits.is_anycast) + assert record.traits.ip_address == "81.2.69.160", "IP address is added to model" + assert record.traits.network == ipaddress.ip_network("81.2.69.160/27") + assert record.country.is_in_european_union is False + assert record.registered_country.is_in_european_union is False + assert not record.traits.is_anycast record = reader.country("214.1.1.0") - self.assertTrue(record.traits.is_anycast) + assert record.traits.is_anycast reader.close() @@ -184,11 +178,11 @@ def test_domain(self) -> None: ip_address = "1.2.0.0" record = reader.domain(ip_address) - self.assertEqual(record, eval(repr(record)), "Domain repr can be eval'd") + assert record == eval(repr(record)), "Domain repr can be eval'd" - self.assertEqual(record.domain, "maxmind.com") - self.assertEqual(record.ip_address, ip_address) - self.assertEqual(record.network, ipaddress.ip_network("1.2.0.0/16")) + assert record.domain == "maxmind.com" + assert record.ip_address == ip_address + assert record.network == ipaddress.ip_network("1.2.0.0/16") self.assertRegex( str(record), @@ -204,26 +198,24 @@ def test_enterprise(self) -> None: ) as reader: ip_address = "74.209.24.0" record = reader.enterprise(ip_address) - self.assertEqual(record.city.confidence, 11) - self.assertEqual(record.country.confidence, 99) - self.assertEqual(record.country.geoname_id, 6252001) - self.assertEqual(record.country.is_in_european_union, False) - self.assertEqual(record.location.accuracy_radius, 27) - self.assertEqual(record.registered_country.is_in_european_union, False) - self.assertEqual(record.traits.connection_type, "Cable/DSL") - self.assertTrue(record.traits.is_legitimate_proxy) - self.assertEqual(record.traits.ip_address, ip_address) - self.assertEqual( - record.traits.network, ipaddress.ip_network("74.209.16.0/20") - ) - self.assertFalse(record.traits.is_anycast) + assert record.city.confidence == 11 + assert record.country.confidence == 99 + assert record.country.geoname_id == 6252001 + assert record.country.is_in_european_union is False + assert record.location.accuracy_radius == 27 + assert record.registered_country.is_in_european_union is False + assert record.traits.connection_type == "Cable/DSL" + assert record.traits.is_legitimate_proxy + assert record.traits.ip_address == ip_address + assert record.traits.network == ipaddress.ip_network("74.209.16.0/20") + assert not record.traits.is_anycast record = reader.enterprise("149.101.100.0") - self.assertEqual(record.traits.mobile_country_code, "310") - self.assertEqual(record.traits.mobile_network_code, "004") + assert record.traits.mobile_country_code == "310" + assert record.traits.mobile_network_code == "004" record = reader.enterprise("214.1.1.0") - self.assertTrue(record.traits.is_anycast) + assert record.traits.is_anycast def test_isp(self) -> None: with geoip2.database.Reader( @@ -231,14 +223,14 @@ def test_isp(self) -> None: ) as reader: ip_address = "1.128.0.0" record = reader.isp(ip_address) - self.assertEqual(record, eval(repr(record)), "ISP repr can be eval'd") + assert record == eval(repr(record)), "ISP repr can be eval'd" - self.assertEqual(record.autonomous_system_number, 1221) - self.assertEqual(record.autonomous_system_organization, "Telstra Pty Ltd") - self.assertEqual(record.isp, "Telstra Internet") - self.assertEqual(record.organization, "Telstra Internet") - self.assertEqual(record.ip_address, ip_address) - self.assertEqual(record.network, ipaddress.ip_network("1.128.0.0/11")) + assert record.autonomous_system_number == 1221 + assert record.autonomous_system_organization == "Telstra Pty Ltd" + assert record.isp == "Telstra Internet" + assert record.organization == "Telstra Internet" + assert record.ip_address == ip_address + assert record.network == ipaddress.ip_network("1.128.0.0/11") self.assertRegex( str(record), @@ -248,15 +240,15 @@ def test_isp(self) -> None: record = reader.isp("149.101.100.0") - self.assertEqual(record.mobile_country_code, "310") - self.assertEqual(record.mobile_network_code, "004") + assert record.mobile_country_code == "310" + assert record.mobile_network_code == "004" def test_context_manager(self) -> None: with geoip2.database.Reader( "tests/data/test-data/GeoIP2-Country-Test.mmdb" ) as reader: record = reader.country("81.2.69.160") - self.assertEqual(record.traits.ip_address, "81.2.69.160") + assert record.traits.ip_address == "81.2.69.160" @patch("maxminddb.open_database") def test_modes(self, mock_open) -> None: diff --git a/tests/models_test.py b/tests/models_test.py index 9d61279..1846d27 100644 --- a/tests/models_test.py +++ b/tests/models_test.py @@ -1,6 +1,4 @@ -#!/usr/bin/env python - - +import pytest from typing import Dict import unittest @@ -89,81 +87,53 @@ def test_insights_full(self) -> None: } model = geoip2.models.Insights(raw) - self.assertEqual( - type(model), geoip2.models.Insights, "geoip2.models.Insights object" - ) - self.assertEqual( - type(model.city), geoip2.records.City, "geoip2.records.City object" - ) - self.assertEqual( - type(model.continent), - geoip2.records.Continent, - "geoip2.records.Continent object", - ) - self.assertEqual( - type(model.country), geoip2.records.Country, "geoip2.records.Country object" - ) - self.assertEqual( - type(model.registered_country), - geoip2.records.Country, - "geoip2.records.Country object", - ) - self.assertEqual( - type(model.represented_country), - geoip2.records.RepresentedCountry, - "geoip2.records.RepresentedCountry object", - ) - self.assertEqual( - type(model.location), - geoip2.records.Location, - "geoip2.records.Location object", - ) - self.assertEqual( - type(model.subdivisions[0]), - geoip2.records.Subdivision, - "geoip2.records.Subdivision object", - ) - self.assertEqual( - type(model.traits), geoip2.records.Traits, "geoip2.records.Traits object" - ) - self.assertEqual(model.raw, raw, "raw method returns raw input") - self.assertEqual( - model.subdivisions[0].iso_code, "MN", "div 1 has correct iso_code" - ) - self.assertEqual( - model.subdivisions[0].confidence, 88, "div 1 has correct confidence" - ) - self.assertEqual( - model.subdivisions[0].geoname_id, 574635, "div 1 has correct geoname_id" - ) - self.assertEqual( - model.subdivisions[0].names, {"en": "Minnesota"}, "div 1 names are correct" - ) - self.assertEqual( - model.subdivisions[1].name, "Hennepin", "div 2 has correct name" - ) - self.assertEqual( - model.subdivisions.most_specific.iso_code, - "HP", - "subdivisions.most_specific returns HP", - ) - self.assertEqual( - model.represented_country.name, - "United Kingdom", - "represented_country name is correct", - ) - self.assertEqual( - model.represented_country.type, - "military", - "represented_country type is correct", - ) - self.assertEqual(model.location.average_income, 24626, "correct average_income") - self.assertEqual(model.location.latitude, 44.98, "correct latitude") - self.assertEqual(model.location.longitude, 93.2636, "correct longitude") - self.assertEqual(model.location.metro_code, 765, "correct metro_code") - self.assertEqual( - model.location.population_density, 1341, "correct population_density" - ) + assert type(model) == geoip2.models.Insights, "geoip2.models.Insights object" + assert type(model.city) == geoip2.records.City, "geoip2.records.City object" + assert ( + type(model.continent) == geoip2.records.Continent + ), "geoip2.records.Continent object" + assert ( + type(model.country) == geoip2.records.Country + ), "geoip2.records.Country object" + assert ( + type(model.registered_country) == geoip2.records.Country + ), "geoip2.records.Country object" + assert ( + type(model.represented_country) == geoip2.records.RepresentedCountry + ), "geoip2.records.RepresentedCountry object" + assert ( + type(model.location) == geoip2.records.Location + ), "geoip2.records.Location object" + assert ( + type(model.subdivisions[0]) == geoip2.records.Subdivision + ), "geoip2.records.Subdivision object" + assert ( + type(model.traits) == geoip2.records.Traits + ), "geoip2.records.Traits object" + assert model.raw == raw, "raw method returns raw input" + assert model.subdivisions[0].iso_code == "MN", "div 1 has correct iso_code" + assert model.subdivisions[0].confidence == 88, "div 1 has correct confidence" + assert ( + model.subdivisions[0].geoname_id == 574635 + ), "div 1 has correct geoname_id" + assert model.subdivisions[0].names == { + "en": "Minnesota" + }, "div 1 names are correct" + assert model.subdivisions[1].name == "Hennepin", "div 2 has correct name" + assert ( + model.subdivisions.most_specific.iso_code == "HP" + ), "subdivisions.most_specific returns HP" + assert ( + model.represented_country.name == "United Kingdom" + ), "represented_country name is correct" + assert ( + model.represented_country.type == "military" + ), "represented_country type is correct" + assert model.location.average_income == 24626, "correct average_income" + assert model.location.latitude == 44.98, "correct latitude" + assert model.location.longitude == 93.2636, "correct longitude" + assert model.location.metro_code == 765, "correct metro_code" + assert model.location.population_density == 1341, "correct population_density" self.assertRegex( str(model), @@ -171,7 +141,7 @@ def test_insights_full(self) -> None: "Insights str representation looks reasonable", ) - self.assertEqual(model, eval(repr(model)), "Insights repr can be eval'd") + assert model == eval(repr(model)), "Insights repr can be eval'd" self.assertRegex( str(model.location), @@ -179,64 +149,49 @@ def test_insights_full(self) -> None: "Location str representation is reasonable", ) - self.assertEqual( - model.location, eval(repr(model.location)), "Location repr can be eval'd" - ) + assert model.location == eval( + repr(model.location) + ), "Location repr can be eval'd" - self.assertIs(model.country.is_in_european_union, False) - self.assertIs(model.registered_country.is_in_european_union, False) - self.assertIs(model.represented_country.is_in_european_union, True) + assert model.country.is_in_european_union is False + assert model.registered_country.is_in_european_union is False + assert model.represented_country.is_in_european_union is True - self.assertIs(model.traits.is_anonymous, True) - self.assertIs(model.traits.is_anonymous_proxy, True) - self.assertIs(model.traits.is_anonymous_vpn, True) - self.assertIs(model.traits.is_anycast, True) - self.assertIs(model.traits.is_hosting_provider, True) - self.assertIs(model.traits.is_public_proxy, True) - self.assertIs(model.traits.is_residential_proxy, True) - self.assertIs(model.traits.is_satellite_provider, True) - self.assertIs(model.traits.is_tor_exit_node, True) - self.assertEqual(model.traits.user_count, 2) - self.assertEqual(model.traits.static_ip_score, 1.3) + assert model.traits.is_anonymous is True + assert model.traits.is_anonymous_proxy is True + assert model.traits.is_anonymous_vpn is True + assert model.traits.is_anycast is True + assert model.traits.is_hosting_provider is True + assert model.traits.is_public_proxy is True + assert model.traits.is_residential_proxy is True + assert model.traits.is_satellite_provider is True + assert model.traits.is_tor_exit_node is True + assert model.traits.user_count == 2 + assert model.traits.static_ip_score == 1.3 def test_insights_min(self) -> None: model = geoip2.models.Insights({"traits": {"ip_address": "5.6.7.8"}}) - self.assertEqual( - type(model), geoip2.models.Insights, "geoip2.models.Insights object" - ) - self.assertEqual( - type(model.city), geoip2.records.City, "geoip2.records.City object" - ) - self.assertEqual( - type(model.continent), - geoip2.records.Continent, - "geoip2.records.Continent object", - ) - self.assertEqual( - type(model.country), geoip2.records.Country, "geoip2.records.Country object" - ) - self.assertEqual( - type(model.registered_country), - geoip2.records.Country, - "geoip2.records.Country object", - ) - self.assertEqual( - type(model.location), - geoip2.records.Location, - "geoip2.records.Location object", - ) - self.assertEqual( - type(model.traits), geoip2.records.Traits, "geoip2.records.Traits object" - ) - self.assertEqual( - type(model.subdivisions.most_specific), - geoip2.records.Subdivision, - "geoip2.records.Subdivision object returned even" - "when none are available.", - ) - self.assertEqual( - model.subdivisions.most_specific.names, {}, "Empty names hash returned" - ) + assert type(model) == geoip2.models.Insights, "geoip2.models.Insights object" + assert type(model.city) == geoip2.records.City, "geoip2.records.City object" + assert ( + type(model.continent) == geoip2.records.Continent + ), "geoip2.records.Continent object" + assert ( + type(model.country) == geoip2.records.Country + ), "geoip2.records.Country object" + assert ( + type(model.registered_country) == geoip2.records.Country + ), "geoip2.records.Country object" + assert ( + type(model.location) == geoip2.records.Location + ), "geoip2.records.Location object" + assert ( + type(model.traits) == geoip2.records.Traits + ), "geoip2.records.Traits object" + assert ( + type(model.subdivisions.most_specific) == geoip2.records.Subdivision + ), "geoip2.records.Subdivision object returned evenwhen none are available." + assert model.subdivisions.most_specific.names == {}, "Empty names hash returned" def test_city_full(self) -> None: raw = { @@ -261,86 +216,64 @@ def test_city_full(self) -> None: }, } model = geoip2.models.City(raw) - self.assertEqual(type(model), geoip2.models.City, "geoip2.models.City object") - self.assertEqual( - type(model.city), geoip2.records.City, "geoip2.records.City object" - ) - self.assertEqual( - type(model.continent), - geoip2.records.Continent, - "geoip2.records.Continent object", - ) - self.assertEqual( - type(model.country), geoip2.records.Country, "geoip2.records.Country object" - ) - self.assertEqual( - type(model.registered_country), - geoip2.records.Country, - "geoip2.records.Country object", - ) - self.assertEqual( - type(model.location), - geoip2.records.Location, - "geoip2.records.Location object", - ) - self.assertEqual( - type(model.traits), geoip2.records.Traits, "geoip2.records.Traits object" - ) - self.assertEqual(model.raw, raw, "raw method returns raw input") - self.assertEqual(model.continent.geoname_id, 42, "continent geoname_id is 42") - self.assertEqual(model.continent.code, "NA", "continent code is NA") - self.assertEqual( - model.continent.names, {"en": "North America"}, "continent names is correct" - ) - self.assertEqual( - model.continent.name, "North America", "continent name is correct" - ) - self.assertEqual(model.country.geoname_id, 1, "country geoname_id is 1") - self.assertEqual(model.country.iso_code, "US", "country iso_code is US") - self.assertEqual( - model.country.names, - {"en": "United States of America"}, - "country names is correct", - ) - self.assertEqual( - model.country.name, "United States of America", "country name is correct" - ) - self.assertEqual(model.country.confidence, None, "country confidence is None") - self.assertEqual( - model.registered_country.iso_code, "CA", "registered_country iso_code is CA" - ) - self.assertEqual( - model.registered_country.names, - {"en": "Canada"}, - "registered_country names is correct", - ) - self.assertEqual( - model.registered_country.name, - "Canada", - "registered_country name is correct", - ) - self.assertEqual( - model.traits.is_anonymous_proxy, - False, - "traits is_anonymous_proxy returns False by default", - ) - self.assertEqual( - model.traits.is_anycast, - False, - "traits is_anycast returns False by default", - ) - self.assertEqual( - model.traits.is_satellite_provider, - True, - "traits is_setellite_provider is True", - ) - self.assertEqual(model.raw, raw, "raw method produces raw output") + assert type(model) == geoip2.models.City, "geoip2.models.City object" + assert type(model.city) == geoip2.records.City, "geoip2.records.City object" + assert ( + type(model.continent) == geoip2.records.Continent + ), "geoip2.records.Continent object" + assert ( + type(model.country) == geoip2.records.Country + ), "geoip2.records.Country object" + assert ( + type(model.registered_country) == geoip2.records.Country + ), "geoip2.records.Country object" + assert ( + type(model.location) == geoip2.records.Location + ), "geoip2.records.Location object" + assert ( + type(model.traits) == geoip2.records.Traits + ), "geoip2.records.Traits object" + assert model.raw == raw, "raw method returns raw input" + assert model.continent.geoname_id == 42, "continent geoname_id is 42" + assert model.continent.code == "NA", "continent code is NA" + assert model.continent.names == { + "en": "North America" + }, "continent names is correct" + assert model.continent.name == "North America", "continent name is correct" + assert model.country.geoname_id == 1, "country geoname_id is 1" + assert model.country.iso_code == "US", "country iso_code is US" + assert model.country.names == { + "en": "United States of America" + }, "country names is correct" + assert ( + model.country.name == "United States of America" + ), "country name is correct" + assert model.country.confidence is None, "country confidence is None" + assert ( + model.registered_country.iso_code == "CA" + ), "registered_country iso_code is CA" + assert model.registered_country.names == { + "en": "Canada" + }, "registered_country names is correct" + assert ( + model.registered_country.name == "Canada" + ), "registered_country name is correct" + assert ( + model.traits.is_anonymous_proxy is False + ), "traits is_anonymous_proxy returns False by default" + assert ( + model.traits.is_anycast is False + ), "traits is_anycast returns False by default" + assert ( + model.traits.is_satellite_provider is True + ), "traits is_setellite_provider is True" + assert model.raw == raw, "raw method produces raw output" self.assertRegex( str(model), r"^geoip2.models.City\(\{.*geoname_id.*\}, \[.*en.*\]\)" ) - self.assertFalse(model == True, "__eq__ does not blow up on weird input") + assert not (model == True), "__eq__ does not blow up on weird input" def test_unknown_keys(self) -> None: model = geoip2.models.City( @@ -380,11 +313,11 @@ def test_unknown_keys(self) -> None: "unk_base": {"blah": 1}, } ) - with self.assertRaises(AttributeError): + with pytest.raises(AttributeError): model.unk_base # type: ignore - with self.assertRaises(AttributeError): + with pytest.raises(AttributeError): model.traits.invalid # type: ignore - self.assertEqual(model.traits.ip_address, "1.2.3.4", "correct ip") + assert model.traits.ip_address == "1.2.3.4", "correct ip" class TestNames(unittest.TestCase): @@ -418,49 +351,39 @@ class TestNames(unittest.TestCase): def test_names(self) -> None: model = geoip2.models.Country(self.raw, locales=["sq", "ar"]) - self.assertEqual( - model.continent.names, - self.raw["continent"]["names"], - "Correct names dict for continent", - ) - self.assertEqual( - model.country.names, - self.raw["country"]["names"], - "Correct names dict for country", - ) + assert ( + model.continent.names == self.raw["continent"]["names"] + ), "Correct names dict for continent" + assert ( + model.country.names == self.raw["country"]["names"] + ), "Correct names dict for country" def test_three_locales(self) -> None: model = geoip2.models.Country(self.raw, locales=["fr", "zh-CN", "en"]) - self.assertEqual( - model.continent.name, - "北美洲", - "continent name is in Chinese (no French available)", - ) - self.assertEqual(model.country.name, "États-Unis", "country name is in French") + assert ( + model.continent.name == "北美洲" + ), "continent name is in Chinese (no French available)" + assert model.country.name == "États-Unis", "country name is in French" def test_two_locales(self) -> None: model = geoip2.models.Country(self.raw, locales=["ak", "fr"]) - self.assertEqual( - model.continent.name, - None, - "continent name is undef (no Akan or French " "available)", - ) - self.assertEqual(model.country.name, "États-Unis", "country name is in French") + assert ( + model.continent.name is None + ), "continent name is undef (no Akan or French available)" + assert model.country.name == "États-Unis", "country name is in French" def test_unknown_locale(self) -> None: model = geoip2.models.Country(self.raw, locales=["aa"]) - self.assertEqual( - model.continent.name, None, "continent name is undef (no Afar available)" - ) - self.assertEqual( - model.country.name, None, "country name is in None (no Afar available)" - ) + assert ( + model.continent.name is None + ), "continent name is undef (no Afar available)" + assert model.country.name is None, "country name is in None (no Afar available)" def test_german(self) -> None: model = geoip2.models.Country(self.raw, locales=["de"]) - self.assertEqual( - model.continent.name, "Nordamerika", "Correct german name for continent" - ) + assert ( + model.continent.name == "Nordamerika" + ), "Correct german name for continent" if __name__ == "__main__": diff --git a/tests/webservice_test.py b/tests/webservice_test.py index 3c97bb9..00c8a93 100644 --- a/tests/webservice_test.py +++ b/tests/webservice_test.py @@ -72,42 +72,30 @@ def test_country_ok(self): content_type=self._content_type("country"), ) country = self.run_client(self.client.country("1.2.3.4")) - self.assertEqual( - type(country), geoip2.models.Country, "return value of client.country" - ) - self.assertEqual(country.continent.geoname_id, 42, "continent geoname_id is 42") - self.assertEqual(country.continent.code, "NA", "continent code is NA") - self.assertEqual( - country.continent.name, "North America", "continent name is North America" - ) - self.assertEqual(country.country.geoname_id, 1, "country geoname_id is 1") - self.assertIs( - country.country.is_in_european_union, - False, - "country is_in_european_union is False", - ) - self.assertEqual(country.country.iso_code, "US", "country iso_code is US") - self.assertEqual( - country.country.names, {"en": "United States of America"}, "country names" - ) - self.assertEqual( - country.country.name, - "United States of America", - "country name is United States of America", - ) - self.assertEqual( - country.maxmind.queries_remaining, 11, "queries_remaining is 11" - ) - self.assertIs( - country.registered_country.is_in_european_union, - True, - "registered_country is_in_european_union is True", - ) - self.assertEqual( - country.traits.network, ipaddress.ip_network("1.2.3.0/24"), "network" - ) - self.assertTrue(country.traits.is_anycast) - self.assertEqual(country.raw, self.country, "raw response is correct") + assert type(country) == geoip2.models.Country, "return value of client.country" + assert country.continent.geoname_id == 42, "continent geoname_id is 42" + assert country.continent.code == "NA", "continent code is NA" + assert ( + country.continent.name == "North America" + ), "continent name is North America" + assert country.country.geoname_id == 1, "country geoname_id is 1" + assert ( + country.country.is_in_european_union is False + ), "country is_in_european_union is False" + assert country.country.iso_code == "US", "country iso_code is US" + assert country.country.names == { + "en": "United States of America" + }, "country names" + assert ( + country.country.name == "United States of America" + ), "country name is United States of America" + assert country.maxmind.queries_remaining == 11, "queries_remaining is 11" + assert ( + country.registered_country.is_in_european_union is True + ), "registered_country is_in_european_union is True" + assert country.traits.network == ipaddress.ip_network("1.2.3.0/24"), "network" + assert country.traits.is_anycast + assert country.raw == self.country, "raw response is correct" def test_me(self): self.httpserver.expect_request( @@ -118,15 +106,13 @@ def test_me(self): content_type=self._content_type("country"), ) implicit_me = self.run_client(self.client.country()) - self.assertEqual( - type(implicit_me), geoip2.models.Country, "country() returns Country object" - ) + assert ( + type(implicit_me) == geoip2.models.Country + ), "country() returns Country object" explicit_me = self.run_client(self.client.country()) - self.assertEqual( - type(explicit_me), - geoip2.models.Country, - "country('me') returns Country object", - ) + assert ( + type(explicit_me) == geoip2.models.Country + ), "country('me') returns Country object" def test_200_error(self): self.httpserver.expect_request( @@ -312,11 +298,9 @@ def test_city_ok(self): content_type=self._content_type("city"), ) city = self.run_client(self.client.city("1.2.3.4")) - self.assertEqual(type(city), geoip2.models.City, "return value of client.city") - self.assertEqual( - city.traits.network, ipaddress.ip_network("1.2.3.0/24"), "network" - ) - self.assertTrue(city.traits.is_anycast) + assert type(city) == geoip2.models.City, "return value of client.city" + assert city.traits.network == ipaddress.ip_network("1.2.3.0/24"), "network" + assert city.traits.is_anycast def test_insights_ok(self): self.httpserver.expect_request( @@ -327,28 +311,26 @@ def test_insights_ok(self): content_type=self._content_type("insights"), ) insights = self.run_client(self.client.insights("1.2.3.4")) - self.assertEqual( - type(insights), geoip2.models.Insights, "return value of client.insights" - ) - self.assertEqual( - insights.traits.network, ipaddress.ip_network("1.2.3.0/24"), "network" - ) - self.assertTrue(insights.traits.is_anycast) - self.assertEqual(insights.traits.static_ip_score, 1.3, "static_ip_score is 1.3") - self.assertEqual(insights.traits.user_count, 2, "user_count is 2") + assert ( + type(insights) == geoip2.models.Insights + ), "return value of client.insights" + assert insights.traits.network == ipaddress.ip_network("1.2.3.0/24"), "network" + assert insights.traits.is_anycast + assert insights.traits.static_ip_score == 1.3, "static_ip_score is 1.3" + assert insights.traits.user_count == 2, "user_count is 2" def test_named_constructor_args(self): id = 47 key = "1234567890ab" client = self.client_class(account_id=id, license_key=key) - self.assertEqual(client._account_id, str(id)) - self.assertEqual(client._license_key, key) + assert client._account_id == str(id) + assert client._license_key == key def test_missing_constructor_args(self): - with self.assertRaises(TypeError): + with pytest.raises(TypeError): self.client_class(license_key="1234567890ab") - with self.assertRaises(TypeError): + with pytest.raises(TypeError): self.client_class("47") From fc4049e218246e541998c7ef0e84d771f0a4f7b0 Mon Sep 17 00:00:00 2001 From: Aarni Koskela Date: Tue, 27 Aug 2024 11:29:11 +0300 Subject: [PATCH 04/11] Rewrite remaining unittest assertions --- tests/database_test.py | 64 ++++++++++++++++------------------------ tests/models_test.py | 29 +++++++----------- tests/webservice_test.py | 31 +++++++++---------- 3 files changed, 50 insertions(+), 74 deletions(-) diff --git a/tests/database_test.py b/tests/database_test.py index 8cca30f..a47841c 100644 --- a/tests/database_test.py +++ b/tests/database_test.py @@ -2,9 +2,12 @@ import ipaddress +import re import unittest from unittest.mock import patch, MagicMock +import pytest + import geoip2.database import geoip2.errors import maxminddb @@ -28,38 +31,34 @@ def test_language_list(self) -> None: def test_unknown_address(self) -> None: reader = geoip2.database.Reader("tests/data/test-data/GeoIP2-City-Test.mmdb") - with self.assertRaisesRegex( + with pytest.raises( geoip2.errors.AddressNotFoundError, - "The address 10.10.10.10 is not in the " "database.", + match="The address 10.10.10.10 is not in the database.", ): reader.city("10.10.10.10") reader.close() def test_unknown_address_network(self) -> None: reader = geoip2.database.Reader("tests/data/test-data/GeoIP2-City-Test.mmdb") - try: + with pytest.raises(geoip2.errors.AddressNotFoundError) as ei: reader.city("10.10.10.10") - self.fail("Expected AddressNotFoundError") - except geoip2.errors.AddressNotFoundError as e: - assert e.network == ipaddress.ip_network("10.0.0.0/8") - except Exception as e: - self.fail(f"Expected AddressNotFoundError, got {type(e)}: {str(e)}") - finally: - reader.close() + assert ei.value.network == ipaddress.ip_network("10.0.0.0/8") + reader.close() def test_wrong_database(self) -> None: reader = geoip2.database.Reader("tests/data/test-data/GeoIP2-City-Test.mmdb") - with self.assertRaisesRegex( + with pytest.raises( TypeError, - "The country method cannot be used with " "the GeoIP2-City database", + match="The country method cannot be used with the GeoIP2-City database", ): reader.country("1.1.1.1") reader.close() def test_invalid_address(self) -> None: reader = geoip2.database.Reader("tests/data/test-data/GeoIP2-City-Test.mmdb") - with self.assertRaisesRegex( - ValueError, "u?'invalid' does not appear to be an " "IPv4 or IPv6 address" + with pytest.raises( + ValueError, + match="u?'invalid' does not appear to be an " "IPv4 or IPv6 address", ): reader.city("invalid") reader.close() @@ -111,11 +110,9 @@ def test_asn(self) -> None: assert record.ip_address == ip_address assert record.network == ipaddress.ip_network("1.128.0.0/11") - self.assertRegex( - str(record), - r"geoip2.models.ASN\(.*1\.128\.0\.0.*\)", - "str representation is correct", - ) + assert re.search( + r"geoip2.models.ASN\(.*1\.128\.0\.0.*\)", str(record) + ), "str representation is correct" reader.close() @@ -149,13 +146,9 @@ def test_connection_type(self) -> None: assert record.connection_type == "Cellular" assert record.ip_address == ip_address assert record.network == ipaddress.ip_network("1.0.1.0/24") - - self.assertRegex( - str(record), - r"ConnectionType\(\{.*Cellular.*\}\)", - "ConnectionType str representation is reasonable", - ) - + assert re.search( + r"ConnectionType\(\{.*Cellular.*\}\)", str(record) + ), "ConnectionType str representation is reasonable" reader.close() def test_country(self) -> None: @@ -183,12 +176,9 @@ def test_domain(self) -> None: assert record.domain == "maxmind.com" assert record.ip_address == ip_address assert record.network == ipaddress.ip_network("1.2.0.0/16") - - self.assertRegex( - str(record), - r"Domain\(\{.*maxmind.com.*\}\)", - "Domain str representation is reasonable", - ) + assert re.search( + r"Domain\(\{.*maxmind.com.*\}\)", str(record) + ), "Domain str representation is reasonable" reader.close() @@ -231,13 +221,9 @@ def test_isp(self) -> None: assert record.organization == "Telstra Internet" assert record.ip_address == ip_address assert record.network == ipaddress.ip_network("1.128.0.0/11") - - self.assertRegex( - str(record), - r"ISP\(\{.*Telstra.*\}\)", - "ISP str representation is reasonable", - ) - + assert re.search( + r"ISP\(\{.*Telstra.*\}\)", str(record) + ), "ISP str representation is reasonable" record = reader.isp("149.101.100.0") assert record.mobile_country_code == "310" diff --git a/tests/models_test.py b/tests/models_test.py index 1846d27..9836c4a 100644 --- a/tests/models_test.py +++ b/tests/models_test.py @@ -1,3 +1,5 @@ +import re + import pytest from typing import Dict import unittest @@ -134,20 +136,13 @@ def test_insights_full(self) -> None: assert model.location.longitude == 93.2636, "correct longitude" assert model.location.metro_code == 765, "correct metro_code" assert model.location.population_density == 1341, "correct population_density" - - self.assertRegex( - str(model), - r"^geoip2.models.Insights\(\{.*geoname_id.*\}, \[.*en.*\]\)", - "Insights str representation looks reasonable", - ) - + assert re.search( + r"^geoip2.models.Insights\(\{.*geoname_id.*\}, \[.*en.*\]\)", str(model) + ), "Insights str representation looks reasonable" assert model == eval(repr(model)), "Insights repr can be eval'd" - - self.assertRegex( - str(model.location), - r"^geoip2.records.Location\(.*longitude=.*\)", - "Location str representation is reasonable", - ) + assert re.search( + r"^geoip2.records.Location\(.*longitude=.*\)", str(model.location) + ), "Location str representation is reasonable" assert model.location == eval( repr(model.location) @@ -268,11 +263,9 @@ def test_city_full(self) -> None: model.traits.is_satellite_provider is True ), "traits is_setellite_provider is True" assert model.raw == raw, "raw method produces raw output" - - self.assertRegex( - str(model), r"^geoip2.models.City\(\{.*geoname_id.*\}, \[.*en.*\]\)" - ) - + assert re.search( + r"^geoip2.models.City\(\{.*geoname_id.*\}, \[.*en.*\]\)", str(model) + ), "City str representation looks reasonable" assert not (model == True), "__eq__ does not blow up on weird input" def test_unknown_keys(self) -> None: diff --git a/tests/webservice_test.py b/tests/webservice_test.py index 00c8a93..1e80bca 100644 --- a/tests/webservice_test.py +++ b/tests/webservice_test.py @@ -123,14 +123,12 @@ def test_200_error(self): content_type=self._content_type("country"), ) - with self.assertRaisesRegex( - GeoIP2Error, "could not decode the response as JSON" - ): + with pytest.raises(GeoIP2Error, match="could not decode the response as JSON"): self.run_client(self.client.country("1.1.1.1")) def test_bad_ip_address(self): - with self.assertRaisesRegex( - ValueError, "'1.2.3' does not appear to be an IPv4 " "or IPv6 address" + with pytest.raises( + ValueError, match="'1.2.3' does not appear to be an IPv4 or IPv6 address" ): self.run_client(self.client.country("1.2.3")) @@ -142,9 +140,7 @@ def test_no_body_error(self): status=400, content_type=self._content_type("country"), ) - with self.assertRaisesRegex( - HTTPError, "Received a 400 error for .* with no body" - ): + with pytest.raises(HTTPError, match="Received a 400 error for .* with no body"): self.run_client(self.client.country("1.2.3.7")) def test_weird_body_error(self): @@ -157,9 +153,10 @@ def test_weird_body_error(self): content_type=self._content_type("country"), ) - with self.assertRaisesRegex( + with pytest.raises( HTTPError, - "Response contains JSON but it does not " "specify code or error keys", + match="Response contains JSON but it does not " + "specify code or error keys", ): self.run_client(self.client.country("1.2.3.8")) @@ -172,8 +169,8 @@ def test_bad_body_error(self): status=400, content_type=self._content_type("country"), ) - with self.assertRaisesRegex( - HTTPError, "it did not include the expected JSON body" + with pytest.raises( + HTTPError, match="it did not include the expected JSON body" ): self.run_client(self.client.country("1.2.3.9")) @@ -185,7 +182,7 @@ def test_500_error(self): status=500, content_type=self._content_type("country"), ) - with self.assertRaisesRegex(HTTPError, r"Received a server error \(500\) for"): + with pytest.raises(HTTPError, match=r"Received a server error \(500\) for"): self.run_client(self.client.country("1.2.3.10")) def test_300_error(self): @@ -197,8 +194,8 @@ def test_300_error(self): status=300, content_type=self._content_type("country"), ) - with self.assertRaisesRegex( - HTTPError, r"Received a very surprising HTTP status \(300\) for" + with pytest.raises( + HTTPError, match=r"Received a very surprising HTTP status \(300\) for" ): self.run_client(self.client.country("1.2.3.11")) @@ -245,7 +242,7 @@ def _test_error(self, status, error_code, error_class): status=status, content_type=self._content_type("country"), ) - with self.assertRaisesRegex(error_class, msg): + with pytest.raises(error_class, match=msg): self.run_client(self.client.country("1.2.3.18")) def test_unknown_error(self): @@ -259,7 +256,7 @@ def test_unknown_error(self): status=400, content_type=self._content_type("country"), ) - with self.assertRaisesRegex(InvalidRequestError, msg): + with pytest.raises(InvalidRequestError, match=msg): self.run_client(self.client.country(ip)) def test_request(self): From ec9c837daadf8318f2d7c79c1662ff09373cbce1 Mon Sep 17 00:00:00 2001 From: Aarni Koskela Date: Tue, 27 Aug 2024 11:30:48 +0300 Subject: [PATCH 05/11] Don't imply tests can be run directly without pytest --- tests/database_test.py | 3 --- tests/models_test.py | 4 ---- tests/webservice_test.py | 6 ------ 3 files changed, 13 deletions(-) diff --git a/tests/database_test.py b/tests/database_test.py index a47841c..fc05c9a 100644 --- a/tests/database_test.py +++ b/tests/database_test.py @@ -1,6 +1,3 @@ -#!/usr/bin/env python - - import ipaddress import re import unittest diff --git a/tests/models_test.py b/tests/models_test.py index 9836c4a..6bc2c3d 100644 --- a/tests/models_test.py +++ b/tests/models_test.py @@ -377,7 +377,3 @@ def test_german(self) -> None: assert ( model.continent.name == "Nordamerika" ), "Correct german name for continent" - - -if __name__ == "__main__": - unittest.main() diff --git a/tests/webservice_test.py b/tests/webservice_test.py index 1e80bca..da6c53c 100644 --- a/tests/webservice_test.py +++ b/tests/webservice_test.py @@ -1,5 +1,3 @@ -#!/usr/bin/env python - import asyncio import copy import ipaddress @@ -357,7 +355,3 @@ def run_client(self, v): del TestBaseClient - - -if __name__ == "__main__": - unittest.main() From aad2e708f0b0770856449a0e58792fe95136f0ca Mon Sep 17 00:00:00 2001 From: Aarni Koskela Date: Wed, 28 Aug 2024 12:56:05 +0300 Subject: [PATCH 06/11] Don't derive from unittest.TestCase when not necessary --- tests/database_test.py | 3 +-- tests/models_test.py | 5 ++--- 2 files changed, 3 insertions(+), 5 deletions(-) diff --git a/tests/database_test.py b/tests/database_test.py index fc05c9a..c045828 100644 --- a/tests/database_test.py +++ b/tests/database_test.py @@ -1,6 +1,5 @@ import ipaddress import re -import unittest from unittest.mock import patch, MagicMock import pytest @@ -15,7 +14,7 @@ maxminddb.extension = None # type: ignore -class TestReader(unittest.TestCase): +class TestReader: def test_language_list(self) -> None: reader = geoip2.database.Reader( "tests/data/test-data/GeoIP2-Country-Test.mmdb", diff --git a/tests/models_test.py b/tests/models_test.py index 6bc2c3d..38a32af 100644 --- a/tests/models_test.py +++ b/tests/models_test.py @@ -2,12 +2,11 @@ import pytest from typing import Dict -import unittest import geoip2.models -class TestModels(unittest.TestCase): +class TestModels: def test_insights_full(self) -> None: raw = { "city": { @@ -313,7 +312,7 @@ def test_unknown_keys(self) -> None: assert model.traits.ip_address == "1.2.3.4", "correct ip" -class TestNames(unittest.TestCase): +class TestNames: raw: Dict = { "continent": { "code": "NA", From d32a3262a1f7b5c419e2c0e14867aabdd9072ebb Mon Sep 17 00:00:00 2001 From: Aarni Koskela Date: Wed, 28 Aug 2024 13:00:31 +0300 Subject: [PATCH 07/11] Use isinstance for type checking Via `ast-grep run --pattern 'type($A) == $B' --rewrite 'isinstance($A, $B)' -iU tests` --- tests/models_test.py | 88 +++++++++++++++++++++------------------- tests/webservice_test.py | 18 ++++---- 2 files changed, 56 insertions(+), 50 deletions(-) diff --git a/tests/models_test.py b/tests/models_test.py index 38a32af..c22237a 100644 --- a/tests/models_test.py +++ b/tests/models_test.py @@ -88,28 +88,30 @@ def test_insights_full(self) -> None: } model = geoip2.models.Insights(raw) - assert type(model) == geoip2.models.Insights, "geoip2.models.Insights object" - assert type(model.city) == geoip2.records.City, "geoip2.records.City object" - assert ( - type(model.continent) == geoip2.records.Continent + assert isinstance( + model, geoip2.models.Insights + ), "geoip2.models.Insights object" + assert isinstance(model.city, geoip2.records.City), "geoip2.records.City object" + assert isinstance( + model.continent, geoip2.records.Continent ), "geoip2.records.Continent object" - assert ( - type(model.country) == geoip2.records.Country + assert isinstance( + model.country, geoip2.records.Country ), "geoip2.records.Country object" - assert ( - type(model.registered_country) == geoip2.records.Country + assert isinstance( + model.registered_country, geoip2.records.Country ), "geoip2.records.Country object" - assert ( - type(model.represented_country) == geoip2.records.RepresentedCountry + assert isinstance( + model.represented_country, geoip2.records.RepresentedCountry ), "geoip2.records.RepresentedCountry object" - assert ( - type(model.location) == geoip2.records.Location + assert isinstance( + model.location, geoip2.records.Location ), "geoip2.records.Location object" - assert ( - type(model.subdivisions[0]) == geoip2.records.Subdivision + assert isinstance( + model.subdivisions[0], geoip2.records.Subdivision ), "geoip2.records.Subdivision object" - assert ( - type(model.traits) == geoip2.records.Traits + assert isinstance( + model.traits, geoip2.records.Traits ), "geoip2.records.Traits object" assert model.raw == raw, "raw method returns raw input" assert model.subdivisions[0].iso_code == "MN", "div 1 has correct iso_code" @@ -165,25 +167,27 @@ def test_insights_full(self) -> None: def test_insights_min(self) -> None: model = geoip2.models.Insights({"traits": {"ip_address": "5.6.7.8"}}) - assert type(model) == geoip2.models.Insights, "geoip2.models.Insights object" - assert type(model.city) == geoip2.records.City, "geoip2.records.City object" - assert ( - type(model.continent) == geoip2.records.Continent + assert isinstance( + model, geoip2.models.Insights + ), "geoip2.models.Insights object" + assert isinstance(model.city, geoip2.records.City), "geoip2.records.City object" + assert isinstance( + model.continent, geoip2.records.Continent ), "geoip2.records.Continent object" - assert ( - type(model.country) == geoip2.records.Country + assert isinstance( + model.country, geoip2.records.Country ), "geoip2.records.Country object" - assert ( - type(model.registered_country) == geoip2.records.Country + assert isinstance( + model.registered_country, geoip2.records.Country ), "geoip2.records.Country object" - assert ( - type(model.location) == geoip2.records.Location + assert isinstance( + model.location, geoip2.records.Location ), "geoip2.records.Location object" - assert ( - type(model.traits) == geoip2.records.Traits + assert isinstance( + model.traits, geoip2.records.Traits ), "geoip2.records.Traits object" - assert ( - type(model.subdivisions.most_specific) == geoip2.records.Subdivision + assert isinstance( + model.subdivisions.most_specific, geoip2.records.Subdivision ), "geoip2.records.Subdivision object returned evenwhen none are available." assert model.subdivisions.most_specific.names == {}, "Empty names hash returned" @@ -210,22 +214,22 @@ def test_city_full(self) -> None: }, } model = geoip2.models.City(raw) - assert type(model) == geoip2.models.City, "geoip2.models.City object" - assert type(model.city) == geoip2.records.City, "geoip2.records.City object" - assert ( - type(model.continent) == geoip2.records.Continent + assert isinstance(model, geoip2.models.City), "geoip2.models.City object" + assert isinstance(model.city, geoip2.records.City), "geoip2.records.City object" + assert isinstance( + model.continent, geoip2.records.Continent ), "geoip2.records.Continent object" - assert ( - type(model.country) == geoip2.records.Country + assert isinstance( + model.country, geoip2.records.Country ), "geoip2.records.Country object" - assert ( - type(model.registered_country) == geoip2.records.Country + assert isinstance( + model.registered_country, geoip2.records.Country ), "geoip2.records.Country object" - assert ( - type(model.location) == geoip2.records.Location + assert isinstance( + model.location, geoip2.records.Location ), "geoip2.records.Location object" - assert ( - type(model.traits) == geoip2.records.Traits + assert isinstance( + model.traits, geoip2.records.Traits ), "geoip2.records.Traits object" assert model.raw == raw, "raw method returns raw input" assert model.continent.geoname_id == 42, "continent geoname_id is 42" diff --git a/tests/webservice_test.py b/tests/webservice_test.py index da6c53c..d97c53f 100644 --- a/tests/webservice_test.py +++ b/tests/webservice_test.py @@ -70,7 +70,9 @@ def test_country_ok(self): content_type=self._content_type("country"), ) country = self.run_client(self.client.country("1.2.3.4")) - assert type(country) == geoip2.models.Country, "return value of client.country" + assert isinstance( + country, geoip2.models.Country + ), "return value of client.country" assert country.continent.geoname_id == 42, "continent geoname_id is 42" assert country.continent.code == "NA", "continent code is NA" assert ( @@ -104,12 +106,12 @@ def test_me(self): content_type=self._content_type("country"), ) implicit_me = self.run_client(self.client.country()) - assert ( - type(implicit_me) == geoip2.models.Country + assert isinstance( + implicit_me, geoip2.models.Country ), "country() returns Country object" explicit_me = self.run_client(self.client.country()) - assert ( - type(explicit_me) == geoip2.models.Country + assert isinstance( + explicit_me, geoip2.models.Country ), "country('me') returns Country object" def test_200_error(self): @@ -293,7 +295,7 @@ def test_city_ok(self): content_type=self._content_type("city"), ) city = self.run_client(self.client.city("1.2.3.4")) - assert type(city) == geoip2.models.City, "return value of client.city" + assert isinstance(city, geoip2.models.City), "return value of client.city" assert city.traits.network == ipaddress.ip_network("1.2.3.0/24"), "network" assert city.traits.is_anycast @@ -306,8 +308,8 @@ def test_insights_ok(self): content_type=self._content_type("insights"), ) insights = self.run_client(self.client.insights("1.2.3.4")) - assert ( - type(insights) == geoip2.models.Insights + assert isinstance( + insights, geoip2.models.Insights ), "return value of client.insights" assert insights.traits.network == ipaddress.ip_network("1.2.3.0/24"), "network" assert insights.traits.is_anycast From 40b53acd4576472111eb6e8de572998df02781ae Mon Sep 17 00:00:00 2001 From: Aarni Koskela Date: Wed, 28 Aug 2024 13:04:14 +0300 Subject: [PATCH 08/11] Address `ruff` lint issues --- tests/database_test.py | 2 +- tests/models_test.py | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/tests/database_test.py b/tests/database_test.py index c045828..dfbb449 100644 --- a/tests/database_test.py +++ b/tests/database_test.py @@ -240,5 +240,5 @@ def test_modes(self, mock_open) -> None: with geoip2.database.Reader( path, mode=geoip2.database.MODE_MMAP_EXT, - ) as reader: + ): mock_open.assert_called_once_with(path, geoip2.database.MODE_MMAP_EXT) diff --git a/tests/models_test.py b/tests/models_test.py index c22237a..3cd805b 100644 --- a/tests/models_test.py +++ b/tests/models_test.py @@ -269,7 +269,7 @@ def test_city_full(self) -> None: assert re.search( r"^geoip2.models.City\(\{.*geoname_id.*\}, \[.*en.*\]\)", str(model) ), "City str representation looks reasonable" - assert not (model == True), "__eq__ does not blow up on weird input" + assert not (model == 8), "__eq__ does not blow up on weird input" def test_unknown_keys(self) -> None: model = geoip2.models.City( From 8d8cd424782897584c021249201411c3d996c083 Mon Sep 17 00:00:00 2001 From: Aarni Koskela Date: Thu, 29 Aug 2024 08:37:47 +0300 Subject: [PATCH 09/11] Add pytest-cov, pin pytest --- pyproject.toml | 2 ++ setup.cfg | 6 ++---- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/pyproject.toml b/pyproject.toml index 5befe70..8ab4217 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -36,6 +36,8 @@ classifiers = [ [project.optional-dependencies] test = [ + "pytest~=8.3", + "pytest-cov~=5.0", "pytest-httpserver>=1.0.10", ] diff --git a/setup.cfg b/setup.cfg index fb01367..a0000af 100644 --- a/setup.cfg +++ b/setup.cfg @@ -20,10 +20,8 @@ python = 3.12: py312,black,lint,flake8,mypy [testenv:{py38,py39,py310,py311,py312}-test] -deps = - pytest-httpserver - pytest -commands = pytest tests +commands = pytest tests {posargs:--cov --cov-report=term-missing} +extras = test [testenv:py312-black] deps = black From e407bd66f861fc2e7e4d651a0c7b2e29605dc049 Mon Sep 17 00:00:00 2001 From: Aarni Koskela Date: Thu, 29 Aug 2024 08:44:04 +0300 Subject: [PATCH 10/11] Test database metadata --- tests/database_test.py | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/tests/database_test.py b/tests/database_test.py index dfbb449..bfdb798 100644 --- a/tests/database_test.py +++ b/tests/database_test.py @@ -232,6 +232,13 @@ def test_context_manager(self) -> None: record = reader.country("81.2.69.160") assert record.traits.ip_address == "81.2.69.160" + def test_metadata(self) -> None: + with geoip2.database.Reader( + "tests/data/test-data/GeoIP2-Country-Test.mmdb" + ) as reader: + meta = reader.metadata() + assert meta.database_type == "GeoIP2-Country" + @patch("maxminddb.open_database") def test_modes(self, mock_open) -> None: mock_open.return_value = MagicMock() From 5dbae3f873ca169fb02e70826c56e12bcdc8b8cf Mon Sep 17 00:00:00 2001 From: Aarni Koskela Date: Thu, 29 Aug 2024 08:44:39 +0300 Subject: [PATCH 11/11] Test client context manager/closing --- tests/webservice_test.py | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/tests/webservice_test.py b/tests/webservice_test.py index d97c53f..898d494 100644 --- a/tests/webservice_test.py +++ b/tests/webservice_test.py @@ -1,6 +1,7 @@ import asyncio import copy import ipaddress +from contextlib import ExitStack, AsyncExitStack from typing import cast, Dict import unittest from pytest_httpserver import HeaderValueMatcher @@ -333,9 +334,14 @@ def test_missing_constructor_args(self): class TestClient(TestBaseClient): def setUp(self): + self.stack = ExitStack() self.client_class = Client self.client = Client(42, "abcdef123456") self.client._base_uri = self.httpserver.url_for("/geoip/v2.1") + self.stack.enter_context(self.client) + + def tearDown(self): + self.stack.close() def run_client(self, v): return v @@ -343,12 +349,15 @@ def run_client(self, v): class TestAsyncClient(TestBaseClient): def setUp(self): + self.stack = AsyncExitStack() self._loop = asyncio.new_event_loop() self.client_class = AsyncClient self.client = AsyncClient(42, "abcdef123456") self.client._base_uri = self.httpserver.url_for("/geoip/v2.1") + self._loop.run_until_complete(self.stack.enter_async_context(self.client)) def tearDown(self): + self._loop.run_until_complete(self.stack.aclose()) self._loop.run_until_complete(self.client.close()) self._loop.close()