Skip to content

Commit 01cac90

Browse files
authored
Merge pull request #88 from wbolster/single-reader-type-checking
Improve type checking: return ‘Reader’ from open_database()
2 parents ee8485a + 7b28aa6 commit 01cac90

File tree

3 files changed

+59
-34
lines changed

3 files changed

+59
-34
lines changed

.pylintrc

+1
Original file line numberDiff line numberDiff line change
@@ -4,3 +4,4 @@ disable=C0330
44
[BASIC]
55

66
no-docstring-rgx=_.*
7+
extension-pkg-allow-list=maxminddb.extension

maxminddb/__init__.py

+55-31
Original file line numberDiff line numberDiff line change
@@ -1,29 +1,42 @@
11
# pylint:disable=C0111
22
import os
3-
from typing import AnyStr, IO, Union
3+
from typing import IO, AnyStr, Union, cast
44

5-
import maxminddb.reader
6-
7-
try:
8-
import maxminddb.extension
9-
except ImportError:
10-
maxminddb.extension = None # type: ignore
11-
12-
from maxminddb.const import (
5+
from .const import (
136
MODE_AUTO,
14-
MODE_MMAP,
15-
MODE_MMAP_EXT,
7+
MODE_FD,
168
MODE_FILE,
179
MODE_MEMORY,
18-
MODE_FD,
10+
MODE_MMAP,
11+
MODE_MMAP_EXT,
1912
)
20-
from maxminddb.decoder import InvalidDatabaseError
21-
from maxminddb.reader import Reader as PyReader
13+
from .decoder import InvalidDatabaseError
14+
from .reader import Reader
15+
16+
try:
17+
# pylint: disable=import-self
18+
from . import extension as _extension
19+
except ImportError:
20+
_extension = None # type: ignore[assignment]
21+
22+
23+
__all__ = [
24+
"InvalidDatabaseError",
25+
"MODE_AUTO",
26+
"MODE_FD",
27+
"MODE_FILE",
28+
"MODE_MEMORY",
29+
"MODE_MMAP",
30+
"MODE_MMAP_EXT",
31+
"Reader",
32+
"open_database",
33+
]
2234

2335

2436
def open_database(
25-
database: Union[AnyStr, int, os.PathLike, IO], mode: int = MODE_AUTO
26-
) -> Union[PyReader, "maxminddb.extension.Reader"]:
37+
database: Union[AnyStr, int, os.PathLike, IO],
38+
mode: int = MODE_AUTO,
39+
) -> Reader:
2740
"""Open a MaxMind DB database
2841
2942
Arguments:
@@ -39,21 +52,32 @@ def open_database(
3952
* MODE_AUTO - tries MODE_MMAP_EXT, MODE_MMAP, MODE_FILE in that
4053
order. Default mode.
4154
"""
42-
has_extension = maxminddb.extension and hasattr(maxminddb.extension, "Reader")
43-
if (mode == MODE_AUTO and has_extension) or mode == MODE_MMAP_EXT:
44-
if not has_extension:
45-
raise ValueError(
46-
"MODE_MMAP_EXT requires the maxminddb.extension module to be available"
47-
)
48-
return maxminddb.extension.Reader(database)
49-
if mode in (MODE_AUTO, MODE_MMAP, MODE_FILE, MODE_MEMORY, MODE_FD):
50-
return PyReader(database, mode)
51-
raise ValueError(f"Unsupported open mode: {mode}")
52-
53-
54-
def Reader(database): # pylint: disable=invalid-name
55-
"""This exists for backwards compatibility. Use open_database instead"""
56-
return open_database(database)
55+
if mode not in (
56+
MODE_AUTO,
57+
MODE_FD,
58+
MODE_FILE,
59+
MODE_MEMORY,
60+
MODE_MMAP,
61+
MODE_MMAP_EXT,
62+
):
63+
raise ValueError(f"Unsupported open mode: {mode}")
64+
65+
has_extension = _extension and hasattr(_extension, "Reader")
66+
use_extension = has_extension if mode == MODE_AUTO else mode == MODE_MMAP_EXT
67+
68+
if not use_extension:
69+
return Reader(database, mode)
70+
71+
if not has_extension:
72+
raise ValueError(
73+
"MODE_MMAP_EXT requires the maxminddb.extension module to be available"
74+
)
75+
76+
# The C type exposes the same API as the Python Reader, so for type
77+
# checking purposes, pretend it is one. (Ideally this would be a subclass
78+
# of, or share a common parent class with, the Python Reader
79+
# implementation.)
80+
return cast(Reader, _extension.Reader(database, mode))
5781

5882

5983
__title__ = "maxminddb"

tests/reader_test.py

+3-3
Original file line numberDiff line numberDiff line change
@@ -250,16 +250,16 @@ def test_opening_path(self):
250250
self.assertEqual(reader.metadata().database_type, "MaxMind DB Decoder Test")
251251

252252
def test_no_extension_exception(self):
253-
real_extension = maxminddb.extension
254-
maxminddb.extension = None
253+
real_extension = maxminddb._extension
254+
maxminddb._extension = None
255255
with self.assertRaisesRegex(
256256
ValueError,
257257
"MODE_MMAP_EXT requires the maxminddb.extension module to be available",
258258
):
259259
open_database(
260260
"tests/data/test-data/MaxMind-DB-test-decoder.mmdb", MODE_MMAP_EXT
261261
)
262-
maxminddb.extension = real_extension
262+
maxminddb._extension = real_extension
263263

264264
def test_broken_database(self):
265265
reader = open_database(

0 commit comments

Comments
 (0)