Improve check for __init__ files

This commit is contained in:
Bruno Oliveira 2024-03-31 09:35:48 -03:00
parent fedeb6b010
commit 7a25556ae5
2 changed files with 23 additions and 9 deletions

View File

@ -773,6 +773,11 @@ def resolve_pkg_root_and_module_name(
pkg_root = pkg_path.parent
if consider_namespace_packages:
for candidate in (pkg_root, *pkg_root.parents):
# If any of the parent paths has an __init__.py, it means it is not a namespace package:
# https://packaging.python.org/en/latest/guides/packaging-namespace-packages
if (candidate / "__init__.py").is_file():
break
if _is_namespace_package(candidate):
# Point the pkg_root to the root of the namespace package.
pkg_root = candidate.parent
@ -788,12 +793,6 @@ def resolve_pkg_root_and_module_name(
def _is_namespace_package(module_path: Path) -> bool:
# If the path has an __init__.py file, it means it is not
# a namespace package:
# https://packaging.python.org/en/latest/guides/packaging-namespace-packages
if (module_path / "__init__.py").is_file():
return False
module_name = module_path.name
# Empty module names break find_spec.

View File

@ -1226,11 +1226,26 @@ class TestNamespacePackages:
models_py, algorithms_py = self.setup_directories(
tmp_path, monkeypatch, pytester
)
# Namespace packages must not have an __init__.py at any of its
# directories; if it does, we then fall back to importing just the
# part of the package containing the __init__.py files.
# Namespace packages must not have an __init__.py at its top-level
# directory; if it does, it is no longer a namespace package and we fall back
# to importing just the part of the package containing the __init__.py files.
(tmp_path / "src/dist1/com/__init__.py").touch()
# Ensure Python no longer considers dist1/com a namespace package.
r = pytester.runpython_c(
dedent(
f"""
import sys
sys.path.append(r{str(tmp_path / "src/dist1")!r})
sys.path.append(r{str(tmp_path / "src/dist2")!r})
import com.company.app.core.models
import com.company.calc.algo.algorithms
"""
)
)
assert r.ret == 1
r.stderr.fnmatch_lines("*No module named 'com.company.calc*")
pkg_root, module_name = resolve_pkg_root_and_module_name(
models_py, consider_namespace_packages=True
)