Skip to content

Commit

Permalink
Fix warning when failed import is parent package
Browse files Browse the repository at this point in the history
  • Loading branch information
jakelishman committed Jan 9, 2024
1 parent 41c3081 commit 3703276
Show file tree
Hide file tree
Showing 2 changed files with 23 additions and 3 deletions.
8 changes: 5 additions & 3 deletions qiskit/utils/lazy_tester.py
Original file line number Diff line number Diff line change
Expand Up @@ -292,9 +292,11 @@ def _is_available(self):
try:
imported = importlib.import_module(module)
except ModuleNotFoundError as exc:
if exc.name == module:
# If the module that wasn't found is the one we were explicitly searching for,
# then it's just not installed.
failed_parts = exc.name.split(".")
target_parts = module.split(".")
if failed_parts == target_parts[: len(failed_parts)]:
# If the module that wasn't found is the one we were explicitly searching for
# (or one of its parents), then it's just not installed.
return False
# Otherwise, we _did_ find the module, it just didn't import, which is a problem.
failed_modules[module] = exc
Expand Down
18 changes: 18 additions & 0 deletions test/python/utils/test_lazy_loaders.py
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@
import importlib.abc
import importlib.util
import sys
import warnings
from unittest import mock

import ddt
Expand Down Expand Up @@ -98,6 +99,23 @@ def test_evaluates_correctly_false(self, test_generator):
if test_generator():
self.fail("did not evaluate false")

def test_submodule_import_detects_false_correctly(self):
"""Test that a lazy import of a submodule where the parent is not available still generates
a silent failure."""

# The idea here is that the base package is what will fail the import, and the corresponding
# `ImportError.name` won't be the same as the full path we were trying to import. We want
# to make sure that the "was it found and failed to import?" handling is correct in this
# case.
def checker():
return LazyImportTester("_qiskit_module_does_not_exist_.submodule")

# Just in case something else is allowing the warnings, but they should be forbidden by
# default.
with warnings.catch_warnings(record=True) as log:
self.assertFalse(checker())
self.assertEqual(log, [])

@ddt.data(available_importer, available_process, unavailable_importer, unavailable_process)
def test_check_occurs_once(self, test_generator):
"""Check that the test of availability is only performed once."""
Expand Down

0 comments on commit 3703276

Please sign in to comment.