resolve_pkg_root_and_module_name() considers sys.meta_path when importing namespace packages. Regression test for #12112.
(
self,
tmp_path: Path,
monkeypatch: MonkeyPatch,
pytester: Pytester,
)
| 1594 | ) |
| 1595 | |
| 1596 | def test_detect_meta_path( |
| 1597 | self, |
| 1598 | tmp_path: Path, |
| 1599 | monkeypatch: MonkeyPatch, |
| 1600 | pytester: Pytester, |
| 1601 | ) -> None: |
| 1602 | """ |
| 1603 | resolve_pkg_root_and_module_name() considers sys.meta_path when importing namespace packages. |
| 1604 | |
| 1605 | Regression test for #12112. |
| 1606 | """ |
| 1607 | |
| 1608 | class CustomImporter(importlib.abc.MetaPathFinder): |
| 1609 | """ |
| 1610 | Imports the module name "com" as a namespace package. |
| 1611 | |
| 1612 | This ensures our namespace detection considers sys.meta_path, which is important |
| 1613 | to support all possible ways a module can be imported (for example editable installs). |
| 1614 | """ |
| 1615 | |
| 1616 | def find_spec( |
| 1617 | self, name: str, path: Any = None, target: Any = None |
| 1618 | ) -> importlib.machinery.ModuleSpec | None: |
| 1619 | if name == "com": |
| 1620 | spec = importlib.machinery.ModuleSpec("com", loader=None) |
| 1621 | spec.submodule_search_locations = [str(com_root_2), str(com_root_1)] |
| 1622 | return spec |
| 1623 | return None |
| 1624 | |
| 1625 | # Setup directories without configuring sys.path. |
| 1626 | models_py, _algorithms_py = self.setup_directories( |
| 1627 | tmp_path, monkeypatch=None, pytester=pytester |
| 1628 | ) |
| 1629 | com_root_1 = tmp_path / "src/dist1/com" |
| 1630 | com_root_2 = tmp_path / "src/dist2/com" |
| 1631 | |
| 1632 | # Because the namespace package is not setup correctly, we cannot resolve it as a namespace package. |
| 1633 | pkg_root, module_name = resolve_pkg_root_and_module_name( |
| 1634 | models_py, consider_namespace_packages=True |
| 1635 | ) |
| 1636 | assert (pkg_root, module_name) == ( |
| 1637 | tmp_path / "src/dist1/com/company", |
| 1638 | "app.core.models", |
| 1639 | ) |
| 1640 | |
| 1641 | # Insert our custom importer, which will recognize the "com" directory as a namespace package. |
| 1642 | new_meta_path = [CustomImporter(), *sys.meta_path] |
| 1643 | monkeypatch.setattr(sys, "meta_path", new_meta_path) |
| 1644 | |
| 1645 | # Now we should be able to resolve the path as namespace package. |
| 1646 | pkg_root, module_name = resolve_pkg_root_and_module_name( |
| 1647 | models_py, consider_namespace_packages=True |
| 1648 | ) |
| 1649 | assert (pkg_root, module_name) == ( |
| 1650 | tmp_path / "src/dist1", |
| 1651 | "com.company.app.core.models", |
| 1652 | ) |
| 1653 |
nothing calls this directly
no test coverage detected