Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Release 5.0.0 #191

Merged
merged 10 commits into from
Jan 29, 2025
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 7 additions & 1 deletion HISTORY.rst
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,13 @@
History
-------

5.0.0
5.0.1 (2025-01-28)
++++++++++++++++++

* Allow ``ip_address`` in the ``Traits`` record to be ``None`` again. The
primary use case for this is from the ``minfraud`` package.

5.0.0 (2025-01-28)
++++++++++++++++++

* BREAKING: The ``raw`` attribute on the model classes has been replaced
Expand Down
3 changes: 1 addition & 2 deletions docs/conf.py
Original file line number Diff line number Diff line change
@@ -1,5 +1,4 @@
#!/usr/bin/env python3
# -*- coding: utf-8 -*-
#
# geoip2 documentation build configuration file, created by
# sphinx-quickstart on Tue Apr 9 13:34:57 2013.
Expand All @@ -12,8 +11,8 @@
# All configuration values have a default; values that are commented out
# serve to show the default.

import sys
import os
import sys

# If extensions (or modules to document with autodoc) are in another directory,
# add these directories to sys.path here. If the directory is relative to the
Expand Down
14 changes: 6 additions & 8 deletions examples/benchmark.py
Original file line number Diff line number Diff line change
@@ -1,15 +1,15 @@
#!/usr/bin/python
# -*- coding: utf-8 -*-

from __future__ import print_function

import argparse
import geoip2.database
import contextlib
import random
import socket
import struct
import timeit

import geoip2.database

parser = argparse.ArgumentParser(description="Benchmark maxminddb.")
parser.add_argument("--count", default=250000, type=int, help="number of lookups")
parser.add_argument("--mode", default=0, type=int, help="reader mode to use")
Expand All @@ -20,12 +20,10 @@
reader = geoip2.database.Reader(args.file, mode=args.mode)


def lookup_ip_address():
def lookup_ip_address() -> None:
ip = socket.inet_ntoa(struct.pack("!L", random.getrandbits(32)))
try:
record = reader.city(str(ip))
except geoip2.errors.AddressNotFoundError:
pass
with contextlib.suppress(geoip2.errors.AddressNotFoundError):
reader.city(str(ip))


elapsed = timeit.timeit(
Expand Down
2 changes: 1 addition & 1 deletion geoip2/__init__.py
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
# pylint:disable=C0111

__title__ = "geoip2"
__version__ = "4.8.1"
__version__ = "5.0.1"
__author__ = "Gregory Oschwald"
__license__ = "Apache License, Version 2.0"
__copyright__ = "Copyright (c) 2013-2025 MaxMind, Inc."
13 changes: 6 additions & 7 deletions geoip2/_internal.py
Original file line number Diff line number Diff line change
@@ -1,22 +1,21 @@
"""This package contains internal utilities"""
"""This package contains internal utilities."""

# pylint: disable=too-few-public-methods
from abc import ABCMeta
from typing import Any


class Model(metaclass=ABCMeta):
"""Shared methods for MaxMind model classes"""
"""Shared methods for MaxMind model classes."""

def __eq__(self, other: Any) -> bool:
def __eq__(self, other: object) -> bool:
return isinstance(other, self.__class__) and self.to_dict() == other.to_dict()

def __ne__(self, other):
def __ne__(self, other) -> bool:
return not self.__eq__(other)

# pylint: disable=too-many-branches
def to_dict(self):
"""Returns a dict of the object suitable for serialization"""
def to_dict(self) -> dict:
"""Returns a dict of the object suitable for serialization."""
result = {}
for key, value in self.__dict__.items():
if key.startswith("_"):
Expand Down
54 changes: 33 additions & 21 deletions geoip2/database.py
Original file line number Diff line number Diff line change
Expand Up @@ -7,41 +7,41 @@

import inspect
import os
from typing import Any, AnyStr, cast, IO, Optional, Sequence, Type, Union
from collections.abc import Sequence
from typing import IO, Any, AnyStr, Optional, Union, cast

import maxminddb

from maxminddb import (
MODE_AUTO,
MODE_MMAP,
MODE_MMAP_EXT,
MODE_FD,
MODE_FILE,
MODE_MEMORY,
MODE_FD,
MODE_MMAP,
MODE_MMAP_EXT,
)

import geoip2
import geoip2.models
import geoip2.errors
from geoip2.types import IPAddress
import geoip2.models
from geoip2.models import (
ASN,
ISP,
AnonymousIP,
City,
ConnectionType,
Country,
Domain,
Enterprise,
ISP,
)
from geoip2.types import IPAddress

__all__ = [
"MODE_AUTO",
"MODE_MMAP",
"MODE_MMAP_EXT",
"MODE_FD",
"MODE_FILE",
"MODE_MEMORY",
"MODE_FD",
"MODE_MMAP",
"MODE_MMAP_EXT",
"Reader",
]

Expand Down Expand Up @@ -135,9 +135,9 @@ def country(self, ip_address: IPAddress) -> Country:
:returns: :py:class:`geoip2.models.Country` object

"""

return cast(
Country, self._model_for(geoip2.models.Country, "Country", ip_address)
Country,
self._model_for(geoip2.models.Country, "Country", ip_address),
)

def city(self, ip_address: IPAddress) -> City:
Expand All @@ -161,7 +161,9 @@ def anonymous_ip(self, ip_address: IPAddress) -> AnonymousIP:
return cast(
AnonymousIP,
self._flat_model_for(
geoip2.models.AnonymousIP, "GeoIP2-Anonymous-IP", ip_address
geoip2.models.AnonymousIP,
"GeoIP2-Anonymous-IP",
ip_address,
),
)

Expand All @@ -174,7 +176,8 @@ def asn(self, ip_address: IPAddress) -> ASN:

"""
return cast(
ASN, self._flat_model_for(geoip2.models.ASN, "GeoLite2-ASN", ip_address)
ASN,
self._flat_model_for(geoip2.models.ASN, "GeoLite2-ASN", ip_address),
)

def connection_type(self, ip_address: IPAddress) -> ConnectionType:
Expand All @@ -188,7 +191,9 @@ def connection_type(self, ip_address: IPAddress) -> ConnectionType:
return cast(
ConnectionType,
self._flat_model_for(
geoip2.models.ConnectionType, "GeoIP2-Connection-Type", ip_address
geoip2.models.ConnectionType,
"GeoIP2-Connection-Type",
ip_address,
),
)

Expand Down Expand Up @@ -227,7 +232,8 @@ def isp(self, ip_address: IPAddress) -> ISP:

"""
return cast(
ISP, self._flat_model_for(geoip2.models.ISP, "GeoIP2-ISP", ip_address)
ISP,
self._flat_model_for(geoip2.models.ISP, "GeoIP2-ISP", ip_address),
)

def _get(self, database_type: str, ip_address: IPAddress) -> Any:
Expand All @@ -247,19 +253,26 @@ def _get(self, database_type: str, ip_address: IPAddress) -> Any:

def _model_for(
self,
model_class: Union[Type[Country], Type[Enterprise], Type[City]],
model_class: Union[type[Country], type[Enterprise], type[City]],
types: str,
ip_address: IPAddress,
) -> Union[Country, Enterprise, City]:
(record, prefix_len) = self._get(types, ip_address)
return model_class(
self._locales, ip_address=ip_address, prefix_len=prefix_len, **record
self._locales,
ip_address=ip_address,
prefix_len=prefix_len,
**record,
)

def _flat_model_for(
self,
model_class: Union[
Type[Domain], Type[ISP], Type[ConnectionType], Type[ASN], Type[AnonymousIP]
type[Domain],
type[ISP],
type[ConnectionType],
type[ASN],
type[AnonymousIP],
],
types: str,
ip_address: IPAddress,
Expand All @@ -278,5 +291,4 @@ def metadata(

def close(self) -> None:
"""Closes the GeoIP2 database."""

self._db_reader.close()
3 changes: 1 addition & 2 deletions geoip2/errors.py
Original file line number Diff line number Diff line change
Expand Up @@ -53,8 +53,7 @@ def __init__(

@property
def network(self) -> Optional[Union[ipaddress.IPv4Network, ipaddress.IPv6Network]]:
"""The network for the error"""

"""The network for the error."""
if self.ip_address is None or self._prefix_len is None:
return None
return ipaddress.ip_network(f"{self.ip_address}/{self._prefix_len}", False)
Expand Down
Loading
Loading