Skip to content

topmark.utils.version

topmark / utils / version

Version utilities for TopMark.

ComputedVersion dataclass

ComputedVersion(
    *, version_text, version_format, error=None
)

Computed package version text and format metadata.

Attributes:

Name Type Description
version_text str

The effective version string.

version_format str

The format of version_text, such as "pep440" or "semver".

error Exception | None

Conversion error when SemVer conversion was requested but failed.

convert_pep440_to_semver

convert_pep440_to_semver(pep440_version)

Convert a PEP 440 version string to a SemVer-compatible string.

Maps

rcN -> -rc.N aN -> -alpha.N bN -> -beta.N devN -> -dev.N (after any pre-release) +local kept as-is

Parameters:

Name Type Description Default
pep440_version str

The version in PEP 440 format

required

Returns:

Type Description
str

The version in SemVer format.

Raises:

Type Description
ValueError

on post releases.

Source code in src/topmark/utils/version.py
def convert_pep440_to_semver(pep440_version: str) -> str:
    """Convert a PEP 440 version string to a SemVer-compatible string.

    Maps:
      rcN  -> -rc.N
      aN   -> -alpha.N
      bN   -> -beta.N
      devN -> -dev.N (after any pre-release)
      +local kept as-is

    Args:
        pep440_version: The version in PEP 440 format

    Returns:
        The version in SemVer format.

    Raises:
        ValueError: on post releases.
    """
    m: re.Match[str] | None = _PEP440_RE.match(pep440_version)
    if not m:
        raise ValueError(f"Not a recognized PEP 440 version: {pep440_version!r}")
    if m.group("post") is not None:
        raise ValueError(f"Post-releases are not valid SemVer: {pep440_version!r}")
    major: str | None = None
    minor: str | None = None
    patch: str | None = None
    major, minor, patch = m.group("major"), m.group("minor"), m.group("patch")
    base: str = f"{major}.{minor}.{patch}"
    pre: str = ""
    if m.group("pre_label"):
        lbl: str = {"a": "alpha", "b": "beta", "rc": "rc"}[m.group("pre_label")]
        pre = f"-{lbl}.{m.group('pre_num')}"
    dev: str = f"{'.' if pre else '-'}dev.{m.group('dev')}" if m.group("dev") else ""
    local: str = f"+{m.group('local')}" if m.group("local") else ""
    return f"{base}{pre}{dev}{local}"

compute_version_text

compute_version_text(*, semver)

Compute the version string for TopMark.

Parameters:

Name Type Description Default
semver bool

If True, attempt to convert the package's PEP 440 version to SemVer.

required

Returns:

Type Description
ComputedVersion

Tuple (version_text, version_format, error).

ComputedVersion

If SemVer conversion is requested and fails, TopMark falls back to the original

ComputedVersion

PEP 440 version string and returns: - version_text: the PEP 440 version - version_format: "pep440" - error: the conversion exception

ComputedVersion

If SemVer conversion succeeds (or semver=False), error is None.

Source code in src/topmark/utils/version.py
def compute_version_text(
    *,
    semver: bool,
) -> ComputedVersion:
    """Compute the version string for TopMark.

    Args:
        semver: If True, attempt to convert the package's PEP 440 version to SemVer.

    Returns:
        Tuple (`version_text`, `version_format`, `error`).

        If SemVer conversion is requested and fails, TopMark falls back to the original
        PEP 440 version string and returns:
            - version_text: the PEP 440 version
            - version_format: "pep440"
            - error: the conversion exception

        If SemVer conversion succeeds (or semver=False), `error` is None.
    """
    version_text: str = TOPMARK_VERSION
    version_format: str = "pep440"
    error: Exception | None = None

    if semver:
        try:
            version_text = convert_pep440_to_semver(version_text)
            version_format = "semver"
        except ValueError as err:
            # Fall back to PEP440 and report the error
            error = err
    return ComputedVersion(
        version_text=version_text,
        version_format=version_format,
        error=error,
    )

check_python_version

check_python_version()

Check if the current Python version meets the minimum requirement.

Source code in src/topmark/utils/version.py
def check_python_version() -> None:
    """Check if the current Python version meets the minimum requirement."""
    if sys.version_info < (MIN_VERSION_MAJOR, MIN_VERSION_MINOR):
        print(  # noqa: T201
            f"Error: {TOPMARK} v{TOPMARK_VERSION} requires "
            f"Python {MIN_VERSION_MAJOR}.{MIN_VERSION_MINOR} or higher.\n"
            f"Current version: {sys.version.split()[0]}",
            file=sys.stderr,
        )
        sys.exit(1)