pathlib: extract a function `resolve_pkg_root_and_module_name`

Will be reused.
This commit is contained in:
Bruno Oliveira 2024-02-27 20:03:08 +02:00
parent dcf01fd39a
commit 7524e60d8f
1 changed files with 36 additions and 10 deletions

View File

@ -541,16 +541,10 @@ def import_path(
insert_missing_modules(sys.modules, module_name)
return mod
pkg_path = resolve_package_path(path)
if pkg_path is not None:
pkg_root = pkg_path.parent
names = list(path.with_suffix("").relative_to(pkg_root).parts)
if names[-1] == "__init__":
names.pop()
module_name = ".".join(names)
else:
pkg_root = path.parent
module_name = path.stem
try:
pkg_root, module_name = resolve_pkg_root_and_module_name(path)
except CouldNotResolvePathError:
pkg_root, module_name = path.parent, path.stem
# Change sys.path permanently: restoring it at the end of this function would cause surprising
# problems because of delayed imports: for example, a conftest.py file imported by this function
@ -689,6 +683,38 @@ def resolve_package_path(path: Path) -> Optional[Path]:
return result
def resolve_pkg_root_and_module_name(path: Path) -> Tuple[Path, str]:
"""
Return the path to the directory of the root package that contains the
given Python file, and its module name:
src/
app/
__init__.py
core/
__init__.py
models.py
Passing the full path to `models.py` will yield Path("src") and "app.core.models".
Raises CouldNotResolvePathError if the given path does not belong to a package (missing any __init__.py files).
"""
pkg_path = resolve_package_path(path)
if pkg_path is not None:
pkg_root = pkg_path.parent
names = list(path.with_suffix("").relative_to(pkg_root).parts)
if names[-1] == "__init__":
names.pop()
module_name = ".".join(names)
return pkg_root, module_name
raise CouldNotResolvePathError(f"Could not resolve for {path}")
class CouldNotResolvePathError(Exception):
"""Custom exception raised by resolve_pkg_root_and_module_name."""
def scandir(
path: Union[str, "os.PathLike[str]"],
sort_key: Callable[["os.DirEntry[str]"], object] = lambda entry: entry.name,