|
3 | 3 | import json |
4 | 4 | import os |
5 | 5 | import time |
6 | | -from importlib.metadata import PackageNotFoundError |
| 6 | +from importlib.metadata import PackageNotFoundError, distribution |
7 | 7 | from importlib.metadata import version as pkg_version |
8 | 8 |
|
9 | 9 | import httpx |
|
13 | 13 | PYPI_URL = "https://pypi.org/pypi/transformerlab-cli/json" |
14 | 14 | CACHE_FILE = os.path.join(CONFIG_DIR, ".version_cache.json") |
15 | 15 | CACHE_TTL_SECONDS = 4 * 60 * 60 # 4 hours |
| 16 | +PACKAGE_NAME = "transformerlab-cli" |
16 | 17 |
|
17 | 18 |
|
18 | 19 | def get_installed_version() -> str: |
19 | 20 | """Return the installed CLI version from package metadata, or 'unknown'.""" |
20 | 21 | try: |
21 | | - return pkg_version("transformerlab-cli") |
| 22 | + return pkg_version(PACKAGE_NAME) |
22 | 23 | except PackageNotFoundError: |
23 | 24 | return "unknown" |
24 | 25 |
|
25 | 26 |
|
| 27 | +def get_install_source() -> dict | None: |
| 28 | + """Return PEP 610 direct_url.json contents for non-PyPI installs, else None. |
| 29 | +
|
| 30 | + PyPI installs have no direct_url.json. Local paths, editable installs, and |
| 31 | + VCS (git) installs do — so its presence means `uv tool upgrade` will resolve |
| 32 | + against that source rather than PyPI. |
| 33 | + """ |
| 34 | + try: |
| 35 | + dist = distribution(PACKAGE_NAME) |
| 36 | + raw = dist.read_text("direct_url.json") |
| 37 | + if raw is None: |
| 38 | + return None |
| 39 | + return json.loads(raw) |
| 40 | + except Exception: |
| 41 | + return None |
| 42 | + |
| 43 | + |
| 44 | +def describe_install_source(direct_url: dict) -> str: |
| 45 | + """Human-readable description of a direct_url.json entry.""" |
| 46 | + url = direct_url.get("url", "") or "" |
| 47 | + dir_info = direct_url.get("dir_info") or {} |
| 48 | + vcs_info = direct_url.get("vcs_info") or {} |
| 49 | + |
| 50 | + if vcs_info: |
| 51 | + vcs = vcs_info.get("vcs", "vcs") |
| 52 | + commit = (vcs_info.get("commit_id") or "")[:7] |
| 53 | + suffix = f" @ {commit}" if commit else "" |
| 54 | + return f"{vcs}: {url}{suffix}" |
| 55 | + if url.startswith("file://"): |
| 56 | + path = url[len("file://") :] |
| 57 | + kind = "editable directory" if dir_info.get("editable") else "local directory" |
| 58 | + return f"{kind}: {path}" |
| 59 | + return url or "unknown source" |
| 60 | + |
| 61 | + |
26 | 62 | def _parse_version(v: str) -> tuple[int, ...]: |
27 | 63 | """Parse a PEP 440 version string into a tuple of ints for comparison. |
28 | 64 |
|
|
0 commit comments