Skip to content

Commit

Permalink
Handle missing extension correctly
Browse files Browse the repository at this point in the history
If the extension module cannot be imported, the fallback path
would trigger ‘NameError: name 'maxminddb' is not defined’.

While at it:

- Use an underscored name for the optional extension import to hide it
  a bit from view (e.g. autocomplete in interactive Python shells)

- Use relative imports not unnecessarily repeat the module name
  everywhere
  • Loading branch information
wbolster committed Sep 23, 2021
1 parent e8a521b commit 7b28aa6
Show file tree
Hide file tree
Showing 2 changed files with 15 additions and 13 deletions.
22 changes: 12 additions & 10 deletions maxminddb/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,21 +2,23 @@
import os
from typing import IO, AnyStr, Union, cast

try:
import maxminddb.extension
except ImportError:
maxminddb.extension = None # type: ignore

from maxminddb.const import (
from .const import (
MODE_AUTO,
MODE_FD,
MODE_FILE,
MODE_MEMORY,
MODE_MMAP,
MODE_MMAP_EXT,
)
from maxminddb.decoder import InvalidDatabaseError
from maxminddb.reader import Reader
from .decoder import InvalidDatabaseError
from .reader import Reader

try:
# pylint: disable=import-self
from . import extension as _extension
except ImportError:
_extension = None # type: ignore[assignment]


__all__ = [
"InvalidDatabaseError",
Expand Down Expand Up @@ -60,7 +62,7 @@ def open_database(
):
raise ValueError(f"Unsupported open mode: {mode}")

has_extension = maxminddb.extension and hasattr(maxminddb.extension, "Reader")
has_extension = _extension and hasattr(_extension, "Reader")
use_extension = has_extension if mode == MODE_AUTO else mode == MODE_MMAP_EXT

if not use_extension:
Expand All @@ -75,7 +77,7 @@ def open_database(
# checking purposes, pretend it is one. (Ideally this would be a subclass
# of, or share a common parent class with, the Python Reader
# implementation.)
return cast(Reader, maxminddb.extension.Reader(database, mode))
return cast(Reader, _extension.Reader(database, mode))


__title__ = "maxminddb"
Expand Down
6 changes: 3 additions & 3 deletions tests/reader_test.py
Original file line number Diff line number Diff line change
Expand Up @@ -250,16 +250,16 @@ def test_opening_path(self):
self.assertEqual(reader.metadata().database_type, "MaxMind DB Decoder Test")

def test_no_extension_exception(self):
real_extension = maxminddb.extension
maxminddb.extension = None
real_extension = maxminddb._extension
maxminddb._extension = None
with self.assertRaisesRegex(
ValueError,
"MODE_MMAP_EXT requires the maxminddb.extension module to be available",
):
open_database(
"tests/data/test-data/MaxMind-DB-test-decoder.mmdb", MODE_MMAP_EXT
)
maxminddb.extension = real_extension
maxminddb._extension = real_extension

def test_broken_database(self):
reader = open_database(
Expand Down

0 comments on commit 7b28aa6

Please sign in to comment.