Skip to content

Commit 09ae444

Browse files
authored
Merge pull request #196 from maxmind/greg/eng-1824
Add dev deps and minor doc improvements
2 parents 960b6cb + 620e6f2 commit 09ae444

File tree

15 files changed

+442
-86
lines changed

15 files changed

+442
-86
lines changed

.github/workflows/test-libmaxminddb.yml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,7 @@ jobs:
1616
# We don't test on Windows currently due to issues
1717
# build libmaxminddb there.
1818
platform: [macos-latest, ubuntu-latest]
19-
python-version: [3.8, 3.9, "3.10", 3.11, 3.12, 3.13]
19+
python-version: [3.9, "3.10", 3.11, 3.12, 3.13]
2020

2121
name: Python ${{ matrix.python-version }} on ${{ matrix.platform }}
2222
runs-on: ${{ matrix.platform }}

.github/workflows/test.yml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,7 @@ jobs:
1414
strategy:
1515
matrix:
1616
platform: [macos-latest, ubuntu-24.04-arm, ubuntu-latest, windows-latest]
17-
python-version: [3.8, 3.9, "3.10", 3.11, 3.12, 3.13]
17+
python-version: [3.9, "3.10", 3.11, 3.12, 3.13]
1818

1919
name: Python ${{ matrix.python-version }} on ${{ matrix.platform }}
2020
runs-on: ${{ matrix.platform }}

HISTORY.rst

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,9 +3,11 @@
33
History
44
-------
55

6-
2.6.4
6+
2.7.0
77
++++++++++++++++++
88

9+
* IMPORTANT: Python 3.9 or greater is required. If you are using an older
10+
version, please use an earlier release.
911
* The vendored ``libmaxminddb`` has been updated to 1.12.2.
1012
* The C extension now checks that the database metadata lookup was
1113
successful.

README.rst

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -97,7 +97,7 @@ invalid IP address or an IPv6 address in an IPv4 database.
9797
Requirements
9898
------------
9999

100-
This code requires Python 3.8+. Older versions are not supported. The C
100+
This code requires Python 3.9+. Older versions are not supported. The C
101101
extension requires CPython.
102102

103103
Versioning

docs/index.rst

Lines changed: 11 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -8,20 +8,28 @@
88

99
.. include:: ../README.rst
1010

11-
=======
12-
Modules
13-
=======
11+
======
12+
Module
13+
======
1414

1515
.. automodule:: maxminddb
1616
:members:
1717
:undoc-members:
1818
:show-inheritance:
1919

20+
======
21+
Errors
22+
======
23+
2024
.. automodule:: maxminddb.errors
2125
:members:
2226
:undoc-members:
2327
:show-inheritance:
2428

29+
===============
30+
Database Reader
31+
===============
32+
2533
.. automodule:: maxminddb.reader
2634
:members:
2735
:undoc-members:

maxminddb/__init__.py

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,5 @@
1+
"""Module for reading MaxMind DB files."""
2+
13
# pylint:disable=C0111
24
import os
35
from typing import IO, AnyStr, Union, cast

maxminddb/decoder.py

Lines changed: 17 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -1,13 +1,7 @@
1-
"""
2-
maxminddb.decoder
3-
~~~~~~~~~~~~~~~~~
4-
5-
This package contains code for decoding the MaxMind DB data section.
6-
7-
"""
1+
"""Decoder for the MaxMind DB data section."""
82

93
import struct
10-
from typing import Dict, List, Tuple, Union, cast
4+
from typing import Union, cast
115

126
try:
137
# pylint: disable=unused-import
@@ -43,35 +37,35 @@ def __init__(
4337
self._buffer = database_buffer
4438
self._pointer_base = pointer_base
4539

46-
def _decode_array(self, size: int, offset: int) -> Tuple[List[Record], int]:
40+
def _decode_array(self, size: int, offset: int) -> tuple[list[Record], int]:
4741
array = []
4842
for _ in range(size):
4943
(value, offset) = self.decode(offset)
5044
array.append(value)
5145
return array, offset
5246

53-
def _decode_boolean(self, size: int, offset: int) -> Tuple[bool, int]:
47+
def _decode_boolean(self, size: int, offset: int) -> tuple[bool, int]:
5448
return size != 0, offset
5549

56-
def _decode_bytes(self, size: int, offset: int) -> Tuple[bytes, int]:
50+
def _decode_bytes(self, size: int, offset: int) -> tuple[bytes, int]:
5751
new_offset = offset + size
5852
return self._buffer[offset:new_offset], new_offset
5953

60-
def _decode_double(self, size: int, offset: int) -> Tuple[float, int]:
54+
def _decode_double(self, size: int, offset: int) -> tuple[float, int]:
6155
self._verify_size(size, 8)
6256
new_offset = offset + size
6357
packed_bytes = self._buffer[offset:new_offset]
6458
(value,) = struct.unpack(b"!d", packed_bytes)
6559
return value, new_offset
6660

67-
def _decode_float(self, size: int, offset: int) -> Tuple[float, int]:
61+
def _decode_float(self, size: int, offset: int) -> tuple[float, int]:
6862
self._verify_size(size, 4)
6963
new_offset = offset + size
7064
packed_bytes = self._buffer[offset:new_offset]
7165
(value,) = struct.unpack(b"!f", packed_bytes)
7266
return value, new_offset
7367

74-
def _decode_int32(self, size: int, offset: int) -> Tuple[int, int]:
68+
def _decode_int32(self, size: int, offset: int) -> tuple[int, int]:
7569
if size == 0:
7670
return 0, offset
7771
new_offset = offset + size
@@ -82,15 +76,15 @@ def _decode_int32(self, size: int, offset: int) -> Tuple[int, int]:
8276
(value,) = struct.unpack(b"!i", packed_bytes)
8377
return value, new_offset
8478

85-
def _decode_map(self, size: int, offset: int) -> Tuple[Dict[str, Record], int]:
86-
container: Dict[str, Record] = {}
79+
def _decode_map(self, size: int, offset: int) -> tuple[dict[str, Record], int]:
80+
container: dict[str, Record] = {}
8781
for _ in range(size):
8882
(key, offset) = self.decode(offset)
8983
(value, offset) = self.decode(offset)
90-
container[cast(str, key)] = value
84+
container[cast("str", key)] = value
9185
return container, offset
9286

93-
def _decode_pointer(self, size: int, offset: int) -> Tuple[Record, int]:
87+
def _decode_pointer(self, size: int, offset: int) -> tuple[Record, int]:
9488
pointer_size = (size >> 3) + 1
9589

9690
buf = self._buffer[offset : offset + pointer_size]
@@ -113,12 +107,12 @@ def _decode_pointer(self, size: int, offset: int) -> Tuple[Record, int]:
113107
(value, _) = self.decode(pointer)
114108
return value, new_offset
115109

116-
def _decode_uint(self, size: int, offset: int) -> Tuple[int, int]:
110+
def _decode_uint(self, size: int, offset: int) -> tuple[int, int]:
117111
new_offset = offset + size
118112
uint_bytes = self._buffer[offset:new_offset]
119113
return int.from_bytes(uint_bytes, "big"), new_offset
120114

121-
def _decode_utf8_string(self, size: int, offset: int) -> Tuple[str, int]:
115+
def _decode_utf8_string(self, size: int, offset: int) -> tuple[str, int]:
122116
new_offset = offset + size
123117
return self._buffer[offset:new_offset].decode("utf-8"), new_offset
124118

@@ -138,7 +132,7 @@ def _decode_utf8_string(self, size: int, offset: int) -> Tuple[str, int]:
138132
15: _decode_float,
139133
}
140134

141-
def decode(self, offset: int) -> Tuple[Record, int]:
135+
def decode(self, offset: int) -> tuple[Record, int]:
142136
"""Decode a section of the data section starting at offset.
143137
144138
Arguments:
@@ -162,7 +156,7 @@ def decode(self, offset: int) -> Tuple[Record, int]:
162156
(size, new_offset) = self._size_from_ctrl_byte(ctrl_byte, new_offset, type_num)
163157
return decoder(self, size, new_offset)
164158

165-
def _read_extended(self, offset: int) -> Tuple[int, int]:
159+
def _read_extended(self, offset: int) -> tuple[int, int]:
166160
next_byte = self._buffer[offset]
167161
type_num = next_byte + 7
168162
if type_num < 7:
@@ -185,7 +179,7 @@ def _size_from_ctrl_byte(
185179
ctrl_byte: int,
186180
offset: int,
187181
type_num: int,
188-
) -> Tuple[int, int]:
182+
) -> tuple[int, int]:
189183
size = ctrl_byte & 0x1F
190184
if type_num == 1 or size < 29:
191185
return size, offset

maxminddb/errors.py

Lines changed: 2 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,5 @@
1-
"""
2-
maxminddb.errors
3-
~~~~~~~~~~~~~~~~
4-
5-
This module contains custom errors for the MaxMind DB reader
6-
"""
1+
"""Typed errors thrown by this library."""
72

83

94
class InvalidDatabaseError(RuntimeError):
10-
"""This error is thrown when unexpected data is found in the database."""
5+
"""An error thrown when unexpected data is found in the database."""

maxminddb/extension.pyi

Lines changed: 4 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -1,17 +1,11 @@
1-
"""
2-
maxminddb.extension
3-
~~~~~~~~~~~~~~~~
4-
5-
This module contains the C extension database reader and related classes.
6-
7-
"""
1+
"""C extension database reader and related classes."""
82

93
# pylint: disable=E0601,E0602
104
from ipaddress import IPv4Address, IPv6Address
115
from os import PathLike
12-
from typing import IO, Any, AnyStr, Optional, Tuple, Union
6+
from typing import IO, Any, AnyStr, Optional, Union
137

14-
from maxminddb import MODE_AUTO
8+
from maxminddb.const import MODE_AUTO
159
from maxminddb.types import Record
1610

1711
class Reader:
@@ -50,7 +44,7 @@ class Reader:
5044
def get_with_prefix_len(
5145
self,
5246
ip_address: Union[str, IPv6Address, IPv4Address],
53-
) -> Tuple[Optional[Record], int]:
47+
) -> tuple[Optional[Record], int]:
5448
"""Return a tuple with the record and the associated prefix length
5549
5650
Arguments:

maxminddb/reader.py

Lines changed: 8 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,4 @@
1-
"""
2-
maxminddb.reader
3-
~~~~~~~~~~~~~~~~
4-
5-
This module contains the pure Python database reader and related classes.
6-
7-
"""
1+
"""Pure-Python reader for the MaxMind DB file format."""
82

93
try:
104
import mmap
@@ -14,9 +8,10 @@
148

159
import ipaddress
1610
import struct
11+
from collections.abc import Iterator
1712
from ipaddress import IPv4Address, IPv6Address
1813
from os import PathLike
19-
from typing import IO, Any, AnyStr, Dict, Iterator, List, Optional, Tuple, Union
14+
from typing import IO, Any, AnyStr, Optional, Union
2015

2116
from maxminddb.const import MODE_AUTO, MODE_FD, MODE_FILE, MODE_MEMORY, MODE_MMAP
2217
from maxminddb.decoder import Decoder
@@ -28,8 +23,7 @@
2823

2924

3025
class Reader:
31-
"""
32-
A pure Python implementation of a reader for the MaxMind DB format. IP
26+
"""A pure Python implementation of a reader for the MaxMind DB format. IP
3327
addresses can be looked up using the ``get`` method.
3428
"""
3529

@@ -148,7 +142,7 @@ def get(self, ip_address: Union[str, IPv6Address, IPv4Address]) -> Optional[Reco
148142
def get_with_prefix_len(
149143
self,
150144
ip_address: Union[str, IPv6Address, IPv4Address],
151-
) -> Tuple[Optional[Record], int]:
145+
) -> tuple[Optional[Record], int]:
152146
"""Return a tuple with the record and the associated prefix length.
153147
154148
Arguments:
@@ -202,7 +196,7 @@ def _generate_children(self, node, depth, ip_acc) -> Iterator:
202196
right = self._read_node(node, 1)
203197
yield from self._generate_children(right, depth, ip_acc | 1)
204198

205-
def _find_address_in_tree(self, packed: bytearray) -> Tuple[int, int]:
199+
def _find_address_in_tree(self, packed: bytearray) -> tuple[int, int]:
206200
bit_count = len(packed) * 8
207201
node = self._start_node(bit_count)
208202
node_count = self._metadata.node_count
@@ -303,7 +297,7 @@ class Metadata:
303297
A string identifying the database type, e.g., "GeoIP2-City".
304298
"""
305299

306-
description: Dict[str, str]
300+
description: dict[str, str]
307301
"""
308302
A map from locales to text descriptions of the database.
309303
"""
@@ -315,7 +309,7 @@ class Metadata:
315309
both IPv4 and IPv6 lookups.
316310
"""
317311

318-
languages: List[str]
312+
languages: list[str]
319313
"""
320314
A list of locale codes supported by the databse.
321315
"""

0 commit comments

Comments
 (0)