Add regression test for #12112
This commit is contained in:
parent
f75dd87eb7
commit
68a4d9830a
|
@ -1,5 +1,7 @@
|
||||||
# mypy: allow-untyped-defs
|
# mypy: allow-untyped-defs
|
||||||
import errno
|
import errno
|
||||||
|
import importlib.abc
|
||||||
|
import importlib.machinery
|
||||||
import os.path
|
import os.path
|
||||||
from pathlib import Path
|
from pathlib import Path
|
||||||
import pickle
|
import pickle
|
||||||
|
@ -10,6 +12,7 @@ from types import ModuleType
|
||||||
from typing import Any
|
from typing import Any
|
||||||
from typing import Generator
|
from typing import Generator
|
||||||
from typing import Iterator
|
from typing import Iterator
|
||||||
|
from typing import Optional
|
||||||
from typing import Tuple
|
from typing import Tuple
|
||||||
import unittest.mock
|
import unittest.mock
|
||||||
|
|
||||||
|
@ -1120,7 +1123,7 @@ class TestNamespacePackages:
|
||||||
"""Test import_path support when importing from properly namespace packages."""
|
"""Test import_path support when importing from properly namespace packages."""
|
||||||
|
|
||||||
def setup_directories(
|
def setup_directories(
|
||||||
self, tmp_path: Path, monkeypatch: MonkeyPatch, pytester: Pytester
|
self, tmp_path: Path, monkeypatch: Optional[MonkeyPatch], pytester: Pytester
|
||||||
) -> Tuple[Path, Path]:
|
) -> Tuple[Path, Path]:
|
||||||
# Set up a namespace package "com.company", containing
|
# Set up a namespace package "com.company", containing
|
||||||
# two subpackages, "app" and "calc".
|
# two subpackages, "app" and "calc".
|
||||||
|
@ -1149,9 +1152,9 @@ class TestNamespacePackages:
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
assert r.ret == 0
|
assert r.ret == 0
|
||||||
|
if monkeypatch is not None:
|
||||||
monkeypatch.syspath_prepend(tmp_path / "src/dist1")
|
monkeypatch.syspath_prepend(tmp_path / "src/dist1")
|
||||||
monkeypatch.syspath_prepend(tmp_path / "src/dist2")
|
monkeypatch.syspath_prepend(tmp_path / "src/dist2")
|
||||||
return models_py, algorithms_py
|
return models_py, algorithms_py
|
||||||
|
|
||||||
@pytest.mark.parametrize("import_mode", ["prepend", "append", "importlib"])
|
@pytest.mark.parametrize("import_mode", ["prepend", "append", "importlib"])
|
||||||
|
@ -1235,3 +1238,61 @@ class TestNamespacePackages:
|
||||||
tmp_path / "src/dist1/com/company",
|
tmp_path / "src/dist1/com/company",
|
||||||
"app.core.models",
|
"app.core.models",
|
||||||
)
|
)
|
||||||
|
|
||||||
|
def test_detect_meta_path(
|
||||||
|
self,
|
||||||
|
tmp_path: Path,
|
||||||
|
monkeypatch: MonkeyPatch,
|
||||||
|
pytester: Pytester,
|
||||||
|
) -> None:
|
||||||
|
"""
|
||||||
|
resolve_pkg_root_and_module_name() considers sys.meta_path when importing namespace packages.
|
||||||
|
|
||||||
|
Regression test for #12112.
|
||||||
|
"""
|
||||||
|
|
||||||
|
class CustomImporter(importlib.abc.MetaPathFinder):
|
||||||
|
"""
|
||||||
|
Imports the module name "com" as a namespace package.
|
||||||
|
|
||||||
|
This ensures our namespace detection considers sys.meta_path, which is important
|
||||||
|
to support all possible ways a module can be imported (for example editable installs).
|
||||||
|
"""
|
||||||
|
|
||||||
|
def find_spec(
|
||||||
|
self, name: str, path: Any = None, target: Any = None
|
||||||
|
) -> Optional[importlib.machinery.ModuleSpec]:
|
||||||
|
if name == "com":
|
||||||
|
spec = importlib.machinery.ModuleSpec("com", loader=None)
|
||||||
|
spec.submodule_search_locations = [str(com_root_2), str(com_root_1)]
|
||||||
|
return spec
|
||||||
|
return None
|
||||||
|
|
||||||
|
# Setup directories without configuring sys.path.
|
||||||
|
models_py, algorithms_py = self.setup_directories(
|
||||||
|
tmp_path, monkeypatch=None, pytester=pytester
|
||||||
|
)
|
||||||
|
com_root_1 = tmp_path / "src/dist1/com"
|
||||||
|
com_root_2 = tmp_path / "src/dist2/com"
|
||||||
|
|
||||||
|
# Because the namespace package is not setup correctly, we cannot resolve it as a namespace package.
|
||||||
|
pkg_root, module_name = resolve_pkg_root_and_module_name(
|
||||||
|
models_py, consider_namespace_packages=True
|
||||||
|
)
|
||||||
|
assert (pkg_root, module_name) == (
|
||||||
|
tmp_path / "src/dist1/com/company",
|
||||||
|
"app.core.models",
|
||||||
|
)
|
||||||
|
|
||||||
|
# Insert our custom importer, which will recognize the "com" directory as a namespace package.
|
||||||
|
new_meta_path = [CustomImporter(), *sys.meta_path]
|
||||||
|
monkeypatch.setattr(sys, "meta_path", new_meta_path)
|
||||||
|
|
||||||
|
# Now we should be able to resolve the path as namespace package.
|
||||||
|
pkg_root, module_name = resolve_pkg_root_and_module_name(
|
||||||
|
models_py, consider_namespace_packages=True
|
||||||
|
)
|
||||||
|
assert (pkg_root, module_name) == (
|
||||||
|
tmp_path / "src/dist1",
|
||||||
|
"com.company.app.core.models",
|
||||||
|
)
|
||||||
|
|
Loading…
Reference in New Issue