示例#1
0
 def test_named_constructor_args(self):
     id = '47'
     key = '1234567890ab'
     for client in (Client(account_id=id, license_key=key),
                    Client(user_id=id, license_key=key)):
         self.assertEqual(client._account_id, id)
         self.assertEqual(client._license_key, key)
示例#2
0
def geolocate(url):
    """
    Finds data about url in geolocation database and transfers it mongodb

    :param url: url to lacate
    :return: geolocation_id
    """
    from geoip2.database import Reader
    from geoip2.webservice import Client
    from geoip2.errors import GeoIP2Error, HTTPError

    geolocation_data = dict()

    try:
        ip = url_to_ip(url)

        response = None

        if config.GEOIP2_WEB_SERVICE_USER_ID and config.GEOIP2_WEB_SERVICE_LICENSE_KEY \
                and config.GEOIP2_WEB_SERVICE_TYPE:
            client = Client(config.GEOIP2_WEB_SERVICE_USER_ID,
                            config.GEOIP2_WEB_SERVICE_LICENSE_KEY)

            if config.GEOIP2_WEB_SERVICE_TYPE == 'country':
                response = client.country(ip).country
            elif config.GEOIP2_WEB_SERVICE_TYPE == 'city':
                response = client.city(ip).city
            elif config.GEOIP2_WEB_SERVICE_TYPE == 'insights':
                response = client.insights(ip).insights
        elif config.GEOIP2_DATABASE_PATH and config.GEOIP2_DATABASE_TYPE:
            reader = Reader(config.GEOIP2_DATABASE_PATH)

            if config.GEOIP2_DATABASE_TYPE == 'country':
                response = reader.country(ip).country
            if config.GEOIP2_DATABASE_TYPE == 'city':
                response = reader.city(ip).city
        else:
            reader = Reader(
                '/opt/project/worker/utils/geoloc_databases/GeoLite2-City.mmdb'
            )
            response = reader.city(ip)

        for name in dir(response):
            value = getattr(response, name)
            if not name.startswith('_') and not type(value) == dict:
                geolocation_data[name] = value.__dict__

    except (GeoIP2Error, HTTPError) as error:
        geolocation_data = {'_error': str(error)}

    finally:
        duplicate = db.geolocation.find_one(geolocation_data)

        if duplicate:
            return duplicate['_id']

        geolocation_id = db.geolocation.insert_one(geolocation_data)

        return str(geolocation_id.inserted_id)
示例#3
0
 def setUp(self):
     self.client = Client(42, 'abcdef123456')
示例#4
0
class TestClient(unittest.TestCase):

    def setUp(self):
        self.client = Client(42, 'abcdef123456')

    base_uri = 'https://geoip.maxmind.com/geoip/v2.1/'
    country = {
        'continent': {'code': 'NA',
                      'geoname_id': 42,
                      'names': {'en': 'North America'}},
        'country': {
            'geoname_id': 1,
            'iso_code': 'US',
            'names': {'en': 'United States of America'}
        },
        'maxmind': {'queries_remaining': 11},
        'traits': {'ip_address': '1.2.3.4'},
    }

    def _content_type(self, endpoint):
        return ('application/vnd.maxmind.com-' + endpoint +
                '+json; charset=UTF-8; version=1.0')

    @requests_mock.mock()
    def test_country_ok(self, mock):
        mock.get(self.base_uri + 'country/1.2.3.4',
                 json=self.country,
                 status_code=200,
                 headers={'Content-Type': self._content_type('country')})
        country = 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.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.assertEqual(country.raw, self.country, 'raw response is correct')

    @requests_mock.mock()
    def test_me(self, mock):
        mock.get(self.base_uri + 'country/me',
                 json=self.country,
                 status_code=200,
                 headers={'Content-Type': self._content_type('country')})
        implicit_me = self.client.country()
        self.assertEqual(
            type(implicit_me), geoip2.models.Country,
            'country() returns Country object')
        explicit_me = self.client.country()
        self.assertEqual(
            type(explicit_me), geoip2.models.Country,
            'country(\'me\') returns Country object')

    @requests_mock.mock()
    def test_200_error(self, mock):
        mock.get(self.base_uri + 'country/1.1.1.1',
                 status_code=200,
                 headers={'Content-Type': self._content_type('country')})
        with self.assertRaisesRegex(GeoIP2Error,
                                    'could not decode the response as JSON'):
            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"):
            self.client.country('1.2.3')

    @requests_mock.mock()
    def test_no_body_error(self, mock):
        mock.get(self.base_uri + 'country/' + '1.2.3.7',
                 text='',
                 status_code=400,
                 headers={'Content-Type': self._content_type('country')})
        with self.assertRaisesRegex(
                HTTPError, 'Received a 400 error for .* with no body'):
            self.client.country('1.2.3.7')

    @requests_mock.mock()
    def test_weird_body_error(self, mock):
        mock.get(self.base_uri + 'country/' + '1.2.3.8',
                 text='{"wierd": 42}',
                 status_code=400,
                 headers={'Content-Type': self._content_type('country')})
        with self.assertRaisesRegex(HTTPError,
                                    'Response contains JSON but it does not '
                                    'specify code or error keys'):
            self.client.country('1.2.3.8')

    @requests_mock.mock()
    def test_bad_body_error(self, mock):
        mock.get(self.base_uri + 'country/' + '1.2.3.9',
                 text='bad body',
                 status_code=400,
                 headers={'Content-Type': self._content_type('country')})
        with self.assertRaisesRegex(
                HTTPError, 'it did not include the expected JSON body'):
            self.client.country('1.2.3.9')

    @requests_mock.mock()
    def test_500_error(self, mock):
        mock.get(self.base_uri + 'country/' + '1.2.3.10', status_code=500)
        with self.assertRaisesRegex(HTTPError,
                                    'Received a server error \(500\) for'):
            self.client.country('1.2.3.10')

    @requests_mock.mock()
    def test_300_error(self, mock):
        mock.get(self.base_uri + 'country/' + '1.2.3.11',
                 status_code=300,
                 headers={'Content-Type': self._content_type('country')})
        with self.assertRaisesRegex(HTTPError,
                                    'Received a very surprising HTTP status '
                                    '\(300\) for'):

            self.client.country('1.2.3.11')

    @requests_mock.mock()
    def test_ip_address_required(self, mock):
        self._test_error(mock, 400, 'IP_ADDRESS_REQUIRED', InvalidRequestError)

    @requests_mock.mock()
    def test_ip_address_not_found(self, mock):
        self._test_error(mock, 404, 'IP_ADDRESS_NOT_FOUND',
                         AddressNotFoundError)

    @requests_mock.mock()
    def test_ip_address_reserved(self, mock):
        self._test_error(mock, 400, 'IP_ADDRESS_RESERVED',
                         AddressNotFoundError)

    @requests_mock.mock()
    def test_permission_required(self, mock):
        self._test_error(mock, 403, 'PERMISSION_REQUIRED',
                         PermissionRequiredError)

    @requests_mock.mock()
    def test_auth_invalid(self, mock):
        self._test_error(mock, 400, 'AUTHORIZATION_INVALID',
                         AuthenticationError)

    @requests_mock.mock()
    def test_license_key_required(self, mock):
        self._test_error(mock, 401, 'LICENSE_KEY_REQUIRED',
                         AuthenticationError)

    @requests_mock.mock()
    def test_user_id_required(self, mock):
        self._test_error(mock, 401, 'USER_ID_REQUIRED', AuthenticationError)

    @requests_mock.mock()
    def test_user_id_unkown(self, mock):
        self._test_error(mock, 401, 'USER_ID_UNKNOWN', AuthenticationError)

    @requests_mock.mock()
    def test_out_of_queries_error(self, mock):
        self._test_error(mock, 402, 'OUT_OF_QUERIES', OutOfQueriesError)

    def _test_error(self, mock, status, error_code, error_class):
        msg = 'Some error message'
        body = {'error': msg, 'code': error_code}
        mock.get(self.base_uri + 'country/1.2.3.18',
                 json=body,
                 status_code=status,
                 headers={'Content-Type': self._content_type('country')})
        with self.assertRaisesRegex(error_class, msg):
            self.client.country('1.2.3.18')

    @requests_mock.mock()
    def test_unknown_error(self, mock):
        msg = 'Unknown error type'
        ip = '1.2.3.19'
        body = {'error': msg, 'code': 'UNKNOWN_TYPE'}
        mock.get(self.base_uri + 'country/' + ip,
                 json=body,
                 status_code=400,
                 headers={'Content-Type': self._content_type('country')})
        with self.assertRaisesRegex(InvalidRequestError, msg):
            self.client.country(ip)

    @requests_mock.mock()
    def test_request(self, mock):
        mock.get(self.base_uri + 'country/' + '1.2.3.4',
                 json=self.country,
                 status_code=200,
                 headers={'Content-Type': self._content_type('country')})
        self.client.country('1.2.3.4')
        request = mock.request_history[-1]

        self.assertEqual(request.path, '/geoip/v2.1/country/1.2.3.4',
                         'correct URI is used')
        self.assertEqual(request.headers['Accept'], 'application/json',
                         'correct Accept header')
        self.assertRegex(request.headers['User-Agent'],
                         '^GeoIP2 Python Client v', 'Correct User-Agent')
        self.assertEqual(request.headers['Authorization'],
                         'Basic NDI6YWJjZGVmMTIzNDU2', 'correct auth')

    @requests_mock.mock()
    def test_city_ok(self, mock):
        mock.get(self.base_uri + 'city/' + '1.2.3.4',
                 json=self.country,
                 status_code=200,
                 headers={'Content-Type': self._content_type('city')})
        city = self.client.city('1.2.3.4')
        self.assertEqual(
            type(city), geoip2.models.City, 'return value of client.city')

    @requests_mock.mock()
    def test_insights_ok(self, mock):
        mock.get(self.base_uri + 'insights/1.2.3.4',
                 json=self.country,
                 status_code=200,
                 headers={'Content-Type': self._content_type('country')})
        insights = self.client.insights('1.2.3.4')
        self.assertEqual(
            type(insights), geoip2.models.Insights,
            'return value of client.insights')
示例#5
0
    def test_missing_constructor_args(self):
        with self.assertRaises(TypeError):
            Client(license_key="1234567890ab")

        with self.assertRaises(TypeError):
            Client("47")
示例#6
0
 def setUp(self):
     self.client = Client(42, "abcdef123456")
示例#7
0
class TestClient(unittest.TestCase):
    def setUp(self):
        self.client = Client(42, "abcdef123456")

    base_uri = "https://geoip.maxmind.com/geoip/v2.1/"
    country = {
        "continent": {
            "code": "NA",
            "geoname_id": 42,
            "names": {
                "en": "North America"
            }
        },
        "country": {
            "geoname_id": 1,
            "iso_code": "US",
            "names": {
                "en": "United States of America"
            },
        },
        "maxmind": {
            "queries_remaining": 11
        },
        "registered_country": {
            "geoname_id": 2,
            "is_in_european_union": True,
            "iso_code": "DE",
            "names": {
                "en": "Germany"
            },
        },
        "traits": {
            "ip_address": "1.2.3.4",
            "network": "1.2.3.0/24"
        },
    }

    # this is not a comprehensive representation of the
    # JSON from the server
    insights = copy.deepcopy(country)
    insights["traits"]["user_count"] = 2
    insights["traits"]["static_ip_score"] = 1.3

    def _content_type(self, endpoint):
        return ("application/vnd.maxmind.com-" + endpoint +
                "+json; charset=UTF-8; version=1.0")

    @requests_mock.mock()
    def test_country_ok(self, mock):
        mock.get(
            self.base_uri + "country/1.2.3.4",
            json=self.country,
            status_code=200,
            headers={"Content-Type": self._content_type("country")},
        )
        country = 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,
                         compat_ip_network("1.2.3.0/24"), "network")
        self.assertEqual(country.raw, self.country, "raw response is correct")

    @requests_mock.mock()
    def test_me(self, mock):
        mock.get(
            self.base_uri + "country/me",
            json=self.country,
            status_code=200,
            headers={"Content-Type": self._content_type("country")},
        )
        implicit_me = self.client.country()
        self.assertEqual(type(implicit_me), geoip2.models.Country,
                         "country() returns Country object")
        explicit_me = self.client.country()
        self.assertEqual(
            type(explicit_me),
            geoip2.models.Country,
            "country('me') returns Country object",
        )

    @requests_mock.mock()
    def test_200_error(self, mock):
        mock.get(
            self.base_uri + "country/1.1.1.1",
            status_code=200,
            headers={"Content-Type": self._content_type("country")},
        )
        with self.assertRaisesRegex(GeoIP2Error,
                                    "could not decode the response as JSON"):
            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"):
            self.client.country("1.2.3")

    @requests_mock.mock()
    def test_no_body_error(self, mock):
        mock.get(
            self.base_uri + "country/" + "1.2.3.7",
            text="",
            status_code=400,
            headers={"Content-Type": self._content_type("country")},
        )
        with self.assertRaisesRegex(
                HTTPError, "Received a 400 error for .* with no body"):
            self.client.country("1.2.3.7")

    @requests_mock.mock()
    def test_weird_body_error(self, mock):
        mock.get(
            self.base_uri + "country/" + "1.2.3.8",
            text='{"wierd": 42}',
            status_code=400,
            headers={"Content-Type": self._content_type("country")},
        )
        with self.assertRaisesRegex(
                HTTPError,
                "Response contains JSON but it does not "
                "specify code or error keys",
        ):
            self.client.country("1.2.3.8")

    @requests_mock.mock()
    def test_bad_body_error(self, mock):
        mock.get(
            self.base_uri + "country/" + "1.2.3.9",
            text="bad body",
            status_code=400,
            headers={"Content-Type": self._content_type("country")},
        )
        with self.assertRaisesRegex(
                HTTPError, "it did not include the expected JSON body"):
            self.client.country("1.2.3.9")

    @requests_mock.mock()
    def test_500_error(self, mock):
        mock.get(self.base_uri + "country/" + "1.2.3.10", status_code=500)
        with self.assertRaisesRegex(HTTPError,
                                    r"Received a server error \(500\) for"):
            self.client.country("1.2.3.10")

    @requests_mock.mock()
    def test_300_error(self, mock):
        mock.get(
            self.base_uri + "country/" + "1.2.3.11",
            status_code=300,
            headers={"Content-Type": self._content_type("country")},
        )
        with self.assertRaisesRegex(
                HTTPError,
                r"Received a very surprising HTTP status \(300\) for"):

            self.client.country("1.2.3.11")

    @requests_mock.mock()
    def test_ip_address_required(self, mock):
        self._test_error(mock, 400, "IP_ADDRESS_REQUIRED", InvalidRequestError)

    @requests_mock.mock()
    def test_ip_address_not_found(self, mock):
        self._test_error(mock, 404, "IP_ADDRESS_NOT_FOUND",
                         AddressNotFoundError)

    @requests_mock.mock()
    def test_ip_address_reserved(self, mock):
        self._test_error(mock, 400, "IP_ADDRESS_RESERVED",
                         AddressNotFoundError)

    @requests_mock.mock()
    def test_permission_required(self, mock):
        self._test_error(mock, 403, "PERMISSION_REQUIRED",
                         PermissionRequiredError)

    @requests_mock.mock()
    def test_auth_invalid(self, mock):
        self._test_error(mock, 400, "AUTHORIZATION_INVALID",
                         AuthenticationError)

    @requests_mock.mock()
    def test_license_key_required(self, mock):
        self._test_error(mock, 401, "LICENSE_KEY_REQUIRED",
                         AuthenticationError)

    @requests_mock.mock()
    def test_account_id_required(self, mock):
        self._test_error(mock, 401, "ACCOUNT_ID_REQUIRED", AuthenticationError)

    @requests_mock.mock()
    def test_user_id_required(self, mock):
        self._test_error(mock, 401, "USER_ID_REQUIRED", AuthenticationError)

    @requests_mock.mock()
    def test_account_id_unkown(self, mock):
        self._test_error(mock, 401, "ACCOUNT_ID_UNKNOWN", AuthenticationError)

    @requests_mock.mock()
    def test_user_id_unkown(self, mock):
        self._test_error(mock, 401, "USER_ID_UNKNOWN", AuthenticationError)

    @requests_mock.mock()
    def test_out_of_queries_error(self, mock):
        self._test_error(mock, 402, "OUT_OF_QUERIES", OutOfQueriesError)

    def _test_error(self, mock, status, error_code, error_class):
        msg = "Some error message"
        body = {"error": msg, "code": error_code}
        mock.get(
            self.base_uri + "country/1.2.3.18",
            json=body,
            status_code=status,
            headers={"Content-Type": self._content_type("country")},
        )
        with self.assertRaisesRegex(error_class, msg):
            self.client.country("1.2.3.18")

    @requests_mock.mock()
    def test_unknown_error(self, mock):
        msg = "Unknown error type"
        ip = "1.2.3.19"
        body = {"error": msg, "code": "UNKNOWN_TYPE"}
        mock.get(
            self.base_uri + "country/" + ip,
            json=body,
            status_code=400,
            headers={"Content-Type": self._content_type("country")},
        )
        with self.assertRaisesRegex(InvalidRequestError, msg):
            self.client.country(ip)

    @requests_mock.mock()
    def test_request(self, mock):
        mock.get(
            self.base_uri + "country/" + "1.2.3.4",
            json=self.country,
            status_code=200,
            headers={"Content-Type": self._content_type("country")},
        )
        self.client.country("1.2.3.4")
        request = mock.request_history[-1]

        self.assertEqual(request.path, "/geoip/v2.1/country/1.2.3.4",
                         "correct URI is used")
        self.assertEqual(request.headers["Accept"], "application/json",
                         "correct Accept header")
        self.assertRegex(
            request.headers["User-Agent"],
            "^GeoIP2 Python Client v",
            "Correct User-Agent",
        )
        self.assertEqual(
            request.headers["Authorization"],
            "Basic NDI6YWJjZGVmMTIzNDU2",
            "correct auth",
        )

    @requests_mock.mock()
    def test_city_ok(self, mock):
        mock.get(
            self.base_uri + "city/" + "1.2.3.4",
            json=self.country,
            status_code=200,
            headers={"Content-Type": self._content_type("city")},
        )
        city = self.client.city("1.2.3.4")
        self.assertEqual(type(city), geoip2.models.City,
                         "return value of client.city")
        self.assertEqual(city.traits.network, compat_ip_network("1.2.3.0/24"),
                         "network")

    @requests_mock.mock()
    def test_insights_ok(self, mock):
        mock.get(
            self.base_uri + "insights/1.2.3.4",
            json=self.insights,
            status_code=200,
            headers={"Content-Type": self._content_type("country")},
        )
        insights = self.client.insights("1.2.3.4")
        self.assertEqual(type(insights), geoip2.models.Insights,
                         "return value of client.insights")
        self.assertEqual(insights.traits.network,
                         compat_ip_network("1.2.3.0/24"), "network")
        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")

    def test_named_constructor_args(self):
        id = "47"
        key = "1234567890ab"
        for client in (
                Client(account_id=id, license_key=key),
                Client(user_id=id, license_key=key),
        ):
            self.assertEqual(client._account_id, id)
            self.assertEqual(client._license_key, key)

    def test_missing_constructor_args(self):
        with self.assertRaises(TypeError):
            Client(license_key="1234567890ab")

        with self.assertRaises(TypeError):
            Client("47")
class TestClient(unittest.TestCase):
    def setUp(self):
        self.client = Client(
            42,
            'abcdef123456',
        )

    base_uri = 'https://geoip.maxmind.com/geoip/v2.1/'
    country = {
        'continent': {
            'code': 'NA',
            'geoname_id': 42,
            'names': {
                'en': 'North America'
            }
        },
        'country': {
            'geoname_id': 1,
            'iso_code': 'US',
            'names': {
                'en': 'United States of America'
            }
        },
        'maxmind': {
            'queries_remaining': 11
        },
        'traits': {
            'ip_address': '1.2.3.4'
        },
    }

    def _content_type(self, endpoint):
        return ('application/vnd.maxmind.com-' + endpoint +
                '+json; charset=UTF-8; version=1.0')

    def test_country_ok(self):
        httpretty.register_uri(httpretty.GET,
                               self.base_uri + 'country/1.2.3.4',
                               body=json.dumps(self.country),
                               status=200,
                               content_type=self._content_type('country'))
        country = 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.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.assertEqual(country.raw, self.country, 'raw response is correct')

    def test_me(self):
        httpretty.register_uri(httpretty.GET,
                               self.base_uri + 'country/me',
                               body=json.dumps(self.country),
                               status=200,
                               content_type=self._content_type('country'))
        implicit_me = self.client.country()
        self.assertEqual(type(implicit_me), geoip2.models.Country,
                         'country() returns Country object')
        explicit_me = self.client.country()
        self.assertEqual(type(explicit_me), geoip2.models.Country,
                         'country(\'me\') returns Country object')

    def test_200_error(self):
        httpretty.register_uri(httpretty.GET,
                               self.base_uri + 'country/1.1.1.1',
                               status=200,
                               content_type=self._content_type('country'))
        with self.assertRaisesRegex(GeoIP2Error,
                                    'could not decode the response as JSON'):
            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"):
            self.client.country('1.2.3')

    def test_no_body_error(self):
        httpretty.register_uri(httpretty.GET,
                               self.base_uri + 'country/' + '1.2.3.7',
                               body='',
                               status=400,
                               content_type=self._content_type('country'))
        with self.assertRaisesRegex(
                HTTPError, 'Received a 400 error for .* with no body'):
            self.client.country('1.2.3.7')

    def test_weird_body_error(self):
        httpretty.register_uri(httpretty.GET,
                               self.base_uri + 'country/' + '1.2.3.8',
                               body='{"wierd": 42}',
                               status=400,
                               content_type=self._content_type('country'))
        with self.assertRaisesRegex(
                HTTPError, 'Response contains JSON but it does not '
                'specify code or error keys'):
            self.client.country('1.2.3.8')

    def test_bad_body_error(self):
        httpretty.register_uri(httpretty.GET,
                               self.base_uri + 'country/' + '1.2.3.9',
                               body='bad body',
                               status=400,
                               content_type=self._content_type('country'))
        with self.assertRaisesRegex(
                HTTPError, 'it did not include the expected JSON body'):
            self.client.country('1.2.3.9')

    def test_500_error(self):
        httpretty.register_uri(httpretty.GET,
                               self.base_uri + 'country/' + '1.2.3.10',
                               status=500)
        with self.assertRaisesRegex(HTTPError,
                                    'Received a server error \(500\) for'):
            self.client.country('1.2.3.10')

    def test_300_error(self):
        httpretty.register_uri(httpretty.GET,
                               self.base_uri + 'country/' + '1.2.3.11',
                               status=300,
                               content_type=self._content_type('country'))
        with self.assertRaisesRegex(
                HTTPError, 'Received a very surprising HTTP status '
                '\(300\) for'):

            self.client.country('1.2.3.11')

    def test_address_not_found_error(self):
        body = {'error': 'Not in DB', 'code': 'IP_ADDRESS_NOT_FOUND'}
        httpretty.register_uri(httpretty.GET,
                               self.base_uri + 'country/' + '1.2.3.13',
                               body=json.dumps(body),
                               status=404,
                               content_type=self._content_type('country'))
        with self.assertRaisesRegex(AddressNotFoundError, 'Not in DB'):
            self.client.country('1.2.3.13')

    def test_private_address_error(self):
        body = {'error': 'Private', 'code': 'IP_ADDRESS_RESERVED'}
        httpretty.register_uri(httpretty.GET,
                               self.base_uri + 'country/' + '1.2.3.14',
                               body=json.dumps(body),
                               status=401,
                               content_type=self._content_type('country'))
        with self.assertRaisesRegex(AddressNotFoundError, 'Private'):
            self.client.country('1.2.3.14')

    def test_auth_invalid(self):
        body = {'error': 'Invalid auth', 'code': 'AUTHORIZATION_INVALID'}
        httpretty.register_uri(httpretty.GET,
                               self.base_uri + 'country/' + '1.2.3.15',
                               body=json.dumps(body),
                               status=400,
                               content_type=self._content_type('country'))
        with self.assertRaisesRegex(AuthenticationError, 'Invalid auth'):
            self.client.country('1.2.3.15')

    def test_license_required(self):
        body = {'error': 'License required', 'code': 'LICENSE_KEY_REQUIRED'}
        httpretty.register_uri(httpretty.GET,
                               self.base_uri + 'country/' + '1.2.3.16',
                               body=json.dumps(body),
                               status=401,
                               content_type=self._content_type('country'))
        with self.assertRaisesRegex(AuthenticationError, 'License required'):
            self.client.country('1.2.3.16')

    def test_user_id_required(self):
        body = {'error': 'User ID required', 'code': 'USER_ID_REQUIRED'}
        httpretty.register_uri(httpretty.GET,
                               self.base_uri + 'country/' + '1.2.3.17',
                               body=json.dumps(body),
                               status=401,
                               content_type=self._content_type('country'))
        with self.assertRaisesRegex(AuthenticationError, 'User ID required'):
            self.client.country('1.2.3.17')

    def test_out_of_queries_error(self):
        body = {'error': 'Out of Queries', 'code': 'OUT_OF_QUERIES'}
        httpretty.register_uri(httpretty.GET,
                               self.base_uri + 'country/' + '1.2.3.18',
                               body=json.dumps(body),
                               status=402,
                               content_type=self._content_type('country'))
        with self.assertRaisesRegex(
                OutOfQueriesError,
                'Out of Queries',
        ):
            self.client.country('1.2.3.18')

    def test_request(self):
        httpretty.register_uri(httpretty.GET,
                               self.base_uri + 'country/' + '1.2.3.4',
                               body=json.dumps(self.country),
                               status=200,
                               content_type=self._content_type('country'))
        country = self.client.country('1.2.3.4')
        request = httpretty.core.httpretty.latest_requests[-1]

        self.assertEqual(request.path, '/geoip/v2.1/country/1.2.3.4',
                         'correct URI is used')
        self.assertEqual(request.headers['Accept'], 'application/json',
                         'correct Accept header')
        self.assertRegex(request.headers['User-Agent'],
                         '^GeoIP2 Python Client v', 'Correct User-Agent')
        self.assertEqual(request.headers['Authorization'],
                         'Basic NDI6YWJjZGVmMTIzNDU2', 'correct auth')

    def test_city_ok(self):
        httpretty.register_uri(httpretty.GET,
                               self.base_uri + 'city/' + '1.2.3.4',
                               body=json.dumps(self.country),
                               status=200,
                               content_type=self._content_type('city'))
        city = self.client.city('1.2.3.4')
        self.assertEqual(type(city), geoip2.models.City,
                         'return value of client.city')

    def test_insights_ok(self):
        httpretty.register_uri(httpretty.GET,
                               self.base_uri + 'insights/1.2.3.4',
                               body=json.dumps(self.country),
                               status=200,
                               content_type=self._content_type('country'))
        insights = self.client.insights('1.2.3.4')
        self.assertEqual(type(insights), geoip2.models.Insights,
                         'return value of client.insights')

    def test_insights_ok(self):
        httpretty.register_uri(httpretty.GET,
                               self.base_uri + 'insights/1.2.3.4',
                               body=json.dumps(self.country),
                               status=200,
                               content_type=self._content_type('country'))
        insights = self.client.insights('1.2.3.4')
        self.assertEqual(type(insights), geoip2.models.Insights,
                         'return value of client.insights')
class TestClient(unittest.TestCase):

    def setUp(self):
        self.client = Client(42, 'abcdef123456',)

    base_uri = 'https://geoip.maxmind.com/geoip/v2.1/'
    country = {
        'continent': {
            'code': 'NA',
            'geoname_id': 42,
            'names': {'en': 'North America'}
        },
        'country': {
            'geoname_id': 1,
            'iso_code': 'US',
            'names': {'en': 'United States of America'}
        },
        'maxmind': {'queries_remaining': 11},
        'traits': {'ip_address': '1.2.3.4'},
    }

    def _content_type(self, endpoint):
        return ('application/vnd.maxmind.com-' +
                endpoint + '+json; charset=UTF-8; version=1.0')

    def test_country_ok(self):
        httpretty.register_uri(httpretty.GET,
                               self.base_uri + 'country/1.2.3.4',
                               body=json.dumps(self.country),
                               status=200,
                               content_type=self._content_type('country'))
        country = 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.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.assertEqual(country.raw, self.country, 'raw response is correct')

    def test_me(self):
        httpretty.register_uri(httpretty.GET,
                               self.base_uri + 'country/me',
                               body=json.dumps(self.country),
                               status=200,
                               content_type=self._content_type('country'))
        implicit_me = self.client.country()
        self.assertEqual(type(implicit_me), geoip2.models.Country,
                         'country() returns Country object')
        explicit_me = self.client.country()
        self.assertEqual(type(explicit_me), geoip2.models.Country,
                         'country(\'me\') returns Country object')

    def test_200_error(self):
        httpretty.register_uri(httpretty.GET,
                               self.base_uri + 'country/1.1.1.1',
                               status=200,
                               content_type=self._content_type('country'))
        with self.assertRaisesRegex(GeoIP2Error,
                                    'could not decode the response as JSON'):
            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"):
            self.client.country('1.2.3')

    def test_no_body_error(self):
        httpretty.register_uri(httpretty.GET,
                               self.base_uri + 'country/' + '1.2.3.7',
                               body='',
                               status=400,
                               content_type=self._content_type('country'))
        with self.assertRaisesRegex(HTTPError,
                                    'Received a 400 error for .* with no body'):
            self.client.country('1.2.3.7')

    def test_weird_body_error(self):
        httpretty.register_uri(httpretty.GET,
                               self.base_uri + 'country/' + '1.2.3.8',
                               body='{"wierd": 42}',
                               status=400,
                               content_type=self._content_type('country'))
        with self.assertRaisesRegex(HTTPError,
                                    'Response contains JSON but it does not '
                                    'specify code or error keys'):
            self.client.country('1.2.3.8')

    def test_bad_body_error(self):
        httpretty.register_uri(httpretty.GET,
                               self.base_uri + 'country/' + '1.2.3.9',
                               body='bad body',
                               status=400,
                               content_type=self._content_type('country'))
        with self.assertRaisesRegex(HTTPError,
                                    'it did not include the expected JSON body'
                                    ):
            self.client.country('1.2.3.9')

    def test_500_error(self):
        httpretty.register_uri(httpretty.GET,
                               self.base_uri + 'country/' + '1.2.3.10',
                               status=500)
        with self.assertRaisesRegex(HTTPError,
                                    'Received a server error \(500\) for'):
            self.client.country('1.2.3.10')

    def test_300_error(self):
        httpretty.register_uri(httpretty.GET,
                               self.base_uri + 'country/' + '1.2.3.11',
                               status=300,
                               content_type=self._content_type('country'))
        with self.assertRaisesRegex(HTTPError,
                                    'Received a very surprising HTTP status '
                                    '\(300\) for'):

            self.client.country('1.2.3.11')

    def test_address_not_found_error(self):
        body = {'error': 'Not in DB', 'code': 'IP_ADDRESS_NOT_FOUND'}
        httpretty.register_uri(httpretty.GET,
                               self.base_uri + 'country/' + '1.2.3.13',
                               body=json.dumps(body),
                               status=404,
                               content_type=self._content_type('country'))
        with self.assertRaisesRegex(AddressNotFoundError,
                                    'Not in DB'):
            self.client.country('1.2.3.13')

    def test_private_address_error(self):
        body = {'error': 'Private', 'code': 'IP_ADDRESS_RESERVED'}
        httpretty.register_uri(httpretty.GET,
                               self.base_uri + 'country/' + '1.2.3.14',
                               body=json.dumps(body),
                               status=401,
                               content_type=self._content_type('country'))
        with self.assertRaisesRegex(AddressNotFoundError, 'Private'):
            self.client.country('1.2.3.14')

    def test_auth_invalid(self):
        body = {'error': 'Invalid auth', 'code': 'AUTHORIZATION_INVALID'}
        httpretty.register_uri(httpretty.GET,
                               self.base_uri + 'country/' + '1.2.3.15',
                               body=json.dumps(body),
                               status=400,
                               content_type=self._content_type('country'))
        with self.assertRaisesRegex(AuthenticationError, 'Invalid auth'):
            self.client.country('1.2.3.15')

    def test_license_required(self):
        body = {'error': 'License required', 'code': 'LICENSE_KEY_REQUIRED'}
        httpretty.register_uri(httpretty.GET,
                               self.base_uri + 'country/' + '1.2.3.16',
                               body=json.dumps(body),
                               status=401,
                               content_type=self._content_type('country'))
        with self.assertRaisesRegex(AuthenticationError, 'License required'):
            self.client.country('1.2.3.16')

    def test_user_id_required(self):
        body = {'error': 'User ID required', 'code': 'USER_ID_REQUIRED'}
        httpretty.register_uri(httpretty.GET,
                               self.base_uri + 'country/' + '1.2.3.17',
                               body=json.dumps(body),
                               status=401,
                               content_type=self._content_type('country'))
        with self.assertRaisesRegex(AuthenticationError, 'User ID required'):
            self.client.country('1.2.3.17')

    def test_out_of_queries_error(self):
        body = {'error': 'Out of Queries', 'code': 'OUT_OF_QUERIES'}
        httpretty.register_uri(httpretty.GET,
                               self.base_uri + 'country/' + '1.2.3.18',
                               body=json.dumps(body),
                               status=402,
                               content_type=self._content_type('country'))
        with self.assertRaisesRegex(OutOfQueriesError, 'Out of Queries',):
            self.client.country('1.2.3.18')

    def test_request(self):
        httpretty.register_uri(httpretty.GET,
                               self.base_uri + 'country/' + '1.2.3.4',
                               body=json.dumps(self.country),
                               status=200,
                               content_type=self._content_type('country'))
        country = self.client.country('1.2.3.4')
        request = httpretty.core.httpretty.latest_requests[-1]

        self.assertEqual(request.path,
                         '/geoip/v2.1/country/1.2.3.4',
                         'correct URI is used')
        self.assertEqual(request.headers['Accept'],
                         'application/json',
                         'correct Accept header')
        self.assertRegex(request.headers['User-Agent'],
                         '^GeoIP2 Python Client v',
                         'Correct User-Agent')
        self.assertEqual(request.headers['Authorization'],
                         'Basic NDI6YWJjZGVmMTIzNDU2', 'correct auth')

    def test_city_ok(self):
        httpretty.register_uri(httpretty.GET,
                               self.base_uri + 'city/' + '1.2.3.4',
                               body=json.dumps(self.country),
                               status=200,
                               content_type=self._content_type('city'))
        city = self.client.city('1.2.3.4')
        self.assertEqual(type(city), geoip2.models.City,
                         'return value of client.city')

    def test_city_isp_org_ok(self):
        httpretty.register_uri(httpretty.GET,
                               self.base_uri + 'city/1.2.3.4',
                               body=json.dumps(self.country),
                               status=200,
                               content_type=self._content_type('country'))
        city_isp_org = self.client.city_isp_org('1.2.3.4')
        self.assertEqual(type(city_isp_org), geoip2.models.City,
                         'return value of client.city_isp_org')

    def test_insights_ok(self):
        httpretty.register_uri(httpretty.GET,
                               self.base_uri + 'insights/1.2.3.4',
                               body=json.dumps(self.country),
                               status=200,
                               content_type=self._content_type('country'))
        omni = self.client.insights('1.2.3.4')
        self.assertEqual(type(omni), geoip2.models.Insights,
                         'return value of client.omni')

    def test_insights_ok(self):
        httpretty.register_uri(httpretty.GET,
                               self.base_uri + 'insights/1.2.3.4',
                               body=json.dumps(self.country),
                               status=200,
                               content_type=self._content_type('country'))
        insights = self.client.insights('1.2.3.4')
        self.assertEqual(type(insights), geoip2.models.Insights,
                         'return value of client.insights')