From c0ab02bbf9cd6b607f4866e514bf79a3d143d020 Mon Sep 17 00:00:00 2001 From: Mathieu Scheltienne Date: Mon, 26 Jan 2026 11:42:08 +0100 Subject: [PATCH 1/2] Support namespace package in sys_info --- src/template/utils/config.py | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/template/utils/config.py b/src/template/utils/config.py index a4ea5cc..cd6985f 100644 --- a/src/template/utils/config.py +++ b/src/template/utils/config.py @@ -47,7 +47,8 @@ def sys_info( ljust = 26 out = partial(print, end="", file=fid) - package = __package__.split(".")[0] if package is None else package + package = __package__ if package is None else package + package = package.replace("-", "_") if "-" in package else package # OS information - requires python 3.8 or above out("Platform:".ljust(ljust) + platform.platform() + "\n") From 45cc197e42e723ddba6d19acd5063a2913e84bab Mon Sep 17 00:00:00 2001 From: Mathieu Scheltienne Date: Mon, 26 Jan 2026 11:57:12 +0100 Subject: [PATCH 2/2] fix --- src/template/utils/config.py | 27 ++++++++++++++++++++++++--- 1 file changed, 24 insertions(+), 3 deletions(-) diff --git a/src/template/utils/config.py b/src/template/utils/config.py index cd6985f..e38ca33 100644 --- a/src/template/utils/config.py +++ b/src/template/utils/config.py @@ -4,7 +4,7 @@ import sys import tomllib from functools import lru_cache, partial -from importlib.metadata import metadata, requires, version +from importlib.metadata import PackageNotFoundError, metadata, requires, version from importlib.util import find_spec from pathlib import Path from typing import TYPE_CHECKING @@ -47,8 +47,10 @@ def sys_info( ljust = 26 out = partial(print, end="", file=fid) - package = __package__ if package is None else package - package = package.replace("-", "_") if "-" in package else package + if package is None: + package = _find_distribution_name(__package__) + if "-" in package: + package = package.replace("-", "_") # OS information - requires python 3.8 or above out("Platform:".ljust(ljust) + platform.platform() + "\n") @@ -180,6 +182,25 @@ def _list_dependencies_info( out(f"Not installed: {', '.join(not_found)}\n") +def _find_distribution_name(module_package: str) -> str: + """Find the distribution name from a module's ``__package__``. + + Tries progressively shorter prefixes until finding one with valid metadata. + Handles both regular packages (e.g., ``template.utils`` -> ``template``) and + namespace packages (e.g., ``sphinxcontrib.pydantic.utils`` -> + ``sphinxcontrib.pydantic``). + """ + parts = module_package.split(".") + for i in range(len(parts), 0, -1): + candidate = ".".join(parts[:i]) + try: + version(candidate) + return candidate + except PackageNotFoundError: + continue + return module_package + + @lru_cache(maxsize=1) def _get_gpu_info() -> tuple[str | None, str | None]: """Get the GPU information."""