Refactor is_importable and improve docs
This commit is contained in:
parent
04cbe4f640
commit
b6c0190f15
|
@ -788,7 +788,8 @@ def resolve_pkg_root_and_module_name(
|
|||
if consider_namespace_packages:
|
||||
start = pkg_root if pkg_root is not None else path.parent
|
||||
for candidate in (start, *start.parents):
|
||||
if is_importable(candidate, path):
|
||||
module_name = compute_module_name(candidate, path)
|
||||
if is_importable(module_name, path):
|
||||
# Point the pkg_root to the root of the namespace package.
|
||||
pkg_root = candidate
|
||||
break
|
||||
|
@ -800,17 +801,25 @@ def resolve_pkg_root_and_module_name(
|
|||
raise CouldNotResolvePathError(f"Could not resolve for {path}")
|
||||
|
||||
|
||||
def is_importable(root: Path, module_path: Path) -> bool:
|
||||
def is_importable(module_name: str, module_path: Path) -> bool:
|
||||
"""
|
||||
Return if the given module path could be imported normally by Python, akin to the user
|
||||
entering the REPL and importing the corresponding module name directly.
|
||||
entering the REPL and importing the corresponding module name directly, and corresponds
|
||||
to the module_path specified.
|
||||
|
||||
:param module_name:
|
||||
Full module name that we want to check if is importable.
|
||||
For example, "app.models".
|
||||
|
||||
:param module_path:
|
||||
Full path to the python module/package we want to check if is importable.
|
||||
For example, "/projects/src/app/models.py".
|
||||
"""
|
||||
module_name = compute_module_name(root, module_path)
|
||||
try:
|
||||
# Note this is different from what we do in ``import_path``, where we also search sys.meta_path.
|
||||
# Searching sys.meta_path will eventually find a spec which can load the file even if the interpreter would
|
||||
# not find this module normally in the REPL, which is exactly what we want to be able to do in
|
||||
# ``import_path``, but not here.
|
||||
# Note this is different from what we do in ``_import_module_using_spec``, where we explicitly search through
|
||||
# sys.meta_path to be able to pass the path of the module that we want to import (``meta_importer.find_spec``).
|
||||
# Using importlib.util.find_spec() is different, it gives the same results as trying to import
|
||||
# the module normally in the REPL.
|
||||
spec = importlib.util.find_spec(module_name)
|
||||
except (ImportError, ValueError, ImportWarning):
|
||||
return False
|
||||
|
|
|
@ -1377,11 +1377,11 @@ def test_is_importable_bad_arguments(pytester: Pytester) -> None:
|
|||
pytester.syspathinsert()
|
||||
path = pytester.path / "bar.x"
|
||||
path.mkdir()
|
||||
assert is_importable(path.parent, path) is False
|
||||
assert is_importable("bar.x", path) is False
|
||||
|
||||
path = pytester.path / ".bar.x"
|
||||
path.mkdir()
|
||||
assert is_importable(path.parent, path) is False
|
||||
assert is_importable(".bar.x", path) is False
|
||||
|
||||
|
||||
def test_compute_module_name(tmp_path: Path) -> None:
|
||||
|
|
Loading…
Reference in New Issue