"""
Optional build-metadata loader for animedex.
Loads :mod:`animedex.config.build_info` if it has been generated by
``tools/generate_build_info.py`` (or by ``make build_info``) and
exposes a single dictionary, :data:`BUILD_INFO`, that the CLI banner
and the self-diagnostic both consume.
When ``build_info.py`` is missing (the file is git-ignored, so this is
the normal case in a fresh checkout) :data:`BUILD_INFO` still exists
but ``available`` is ``False``. Every consumer should branch on
``BUILD_INFO["available"]`` rather than catching ``ImportError`` itself.
The fields, mirrored from the generator:
* ``commit`` - full HEAD SHA, ``"unknown"`` if git was unavailable.
* ``commit_short`` - 7-character HEAD SHA, ``"unknown"`` otherwise.
* ``describe`` - ``git describe --tags --always --dirty`` output.
* ``tag`` - tag at HEAD when HEAD is exactly on a tag; ``None`` otherwise.
* ``dirty`` - bool; ``True`` if the working tree had uncommitted changes.
* ``build_time`` - UTC ISO-8601 timestamp.
* ``build_host`` - hostname captured at generation time.
* ``available`` - ``True`` if the values came from the generated file,
``False`` if they are placeholders.
"""
from __future__ import annotations
from typing import Any, Dict, Optional
def _load() -> Dict[str, Any]:
"""Attempt to import ``animedex.config.build_info`` and produce the
canonical :data:`BUILD_INFO` shape.
:return: A dictionary describing the build, with ``available=True``
on success or ``available=False`` when the generated module
is missing or malformed.
:rtype: Dict[str, Any]
"""
try:
from animedex.config import build_info as _bi # type: ignore[import-not-found]
except Exception:
return {
"available": False,
"commit": "unknown",
"commit_short": "unknown",
"describe": "unknown",
"tag": None,
"dirty": False,
"build_time": "unknown",
"build_host": "unknown",
}
def _attr(name: str, default: Any) -> Any:
return getattr(_bi, name, default)
return {
"available": True,
"commit": _attr("__COMMIT__", "unknown"),
"commit_short": _attr("__COMMIT_SHORT__", "unknown"),
"describe": _attr("__GIT_DESCRIBE__", "unknown"),
"tag": _attr("__TAG__", None),
"dirty": bool(_attr("__DIRTY__", False)),
"build_time": _attr("__BUILD_TIME__", "unknown"),
"build_host": _attr("__BUILD_HOST__", "unknown"),
}
#: Canonical build-metadata mapping. Always populated; check
#: ``BUILD_INFO["available"]`` to distinguish a real build from a
#: placeholder.
BUILD_INFO: Dict[str, Any] = _load()
[docs]
def get_build_info() -> Dict[str, Any]:
"""Return a copy of :data:`BUILD_INFO` so callers cannot mutate it.
:return: A shallow copy of the canonical build-info dict.
:rtype: Dict[str, Any]
"""
return dict(BUILD_INFO)
# ``Optional`` is exported for callers that wish to use type hints on
# ``tag`` (which can legitimately be ``None``).
__all__ = ["BUILD_INFO", "format_short", "format_block", "get_build_info", "Optional"]