|
4 | 4 | import sys |
5 | 5 | import tomllib |
6 | 6 | from functools import lru_cache, partial |
7 | | -from importlib.metadata import metadata, requires, version |
| 7 | +from importlib.metadata import PackageNotFoundError, metadata, requires, version |
8 | 8 | from importlib.util import find_spec |
9 | 9 | from pathlib import Path |
10 | 10 | from typing import TYPE_CHECKING |
@@ -47,7 +47,10 @@ def sys_info( |
47 | 47 |
|
48 | 48 | ljust = 26 |
49 | 49 | out = partial(print, end="", file=fid) |
50 | | - package = __package__.split(".")[0] if package is None else package |
| 50 | + if package is None: |
| 51 | + package = _find_distribution_name(__package__) |
| 52 | + if "-" in package: |
| 53 | + package = package.replace("-", "_") |
51 | 54 |
|
52 | 55 | # OS information - requires python 3.8 or above |
53 | 56 | out("Platform:".ljust(ljust) + platform.platform() + "\n") |
@@ -179,6 +182,25 @@ def _list_dependencies_info( |
179 | 182 | out(f"Not installed: {', '.join(not_found)}\n") |
180 | 183 |
|
181 | 184 |
|
| 185 | +def _find_distribution_name(module_package: str) -> str: |
| 186 | + """Find the distribution name from a module's ``__package__``. |
| 187 | +
|
| 188 | + Tries progressively shorter prefixes until finding one with valid metadata. |
| 189 | + Handles both regular packages (e.g., ``template.utils`` -> ``template``) and |
| 190 | + namespace packages (e.g., ``sphinxcontrib.pydantic.utils`` -> |
| 191 | + ``sphinxcontrib.pydantic``). |
| 192 | + """ |
| 193 | + parts = module_package.split(".") |
| 194 | + for i in range(len(parts), 0, -1): |
| 195 | + candidate = ".".join(parts[:i]) |
| 196 | + try: |
| 197 | + version(candidate) |
| 198 | + return candidate |
| 199 | + except PackageNotFoundError: |
| 200 | + continue |
| 201 | + return module_package |
| 202 | + |
| 203 | + |
182 | 204 | @lru_cache(maxsize=1) |
183 | 205 | def _get_gpu_info() -> tuple[str | None, str | None]: |
184 | 206 | """Get the GPU information.""" |
|
0 commit comments