Ctrl K
ComunidadGuías…

scripts/lint_backend_python_floor.py

Rama main · réplica de lectura del repositorio original.

Archivo original ↗Preguntar a KiBot
#!/usr/bin/env python3
# SPDX-License-Identifier: AGPL-3.0-only
# Copyright 2026-present the Unsloth AI Inc. team. All rights reserved. See /studio/LICENSE.AGPL-3.0

"""Fails on stdlib APIs newer than the oldest CI interpreter (via vermin); syntax checks miss these."""

from __future__ import annotations

import json
import re
import shutil
import subprocess
import sys
from pathlib import Path

REPO = Path(__file__).resolve().parents[1]
WORKFLOW = REPO / ".github" / "workflows" / "studio-backend-ci.yml"

# Both trees the CI matrix legs execute: studio-backend-ci also runs `pytest unsloth_cli/tests`.
ROOTS = (
    REPO / "studio" / "backend",
    REPO / "unsloth_cli",
)

# Scan everything under studio/backend, tests included: the CI legs execute all of it.
EXCLUDE_PARTS = ("vendor", "node_modules", "__pycache__", ".venv")


# An above-floor symbol reached deliberately is suppressed AT THE SITE, with `# novermin` and a comment saying why, not by dropping its file from the scan. The one live case is locale.getencoding() in the data-designer plugin's state_store, inside a try/except AttributeError with a pre-3.11 fallback.


# Floor is declared in the workflow; the matrix and pyproject (>= 3.9) cannot supply the real floor.
FLOOR_KEY = "PYTHON_FLOOR"


def declared_floor() -> tuple[int, int]:
    """The floor the workflow declares, as (major, minor)."""
    text = WORKFLOW.read_text(encoding = "utf-8")
    found = re.search(rf"^\s*{FLOOR_KEY}:\s*['\"]?(\d+)\.(\d+)['\"]?\s*$", text, re.M)
    if not found:
        raise SystemExit(
            f"{WORKFLOW.name} declares no {FLOOR_KEY}, so this lint has no target. It is "
            f"declared there rather than here so that the number lives with the CI that "
            f"used to test it."
        )
    return int(found.group(1)), int(found.group(2))


def targets() -> list[str]:
    """Every .py the matrix legs ship or execute, found rather than listed."""
    found = []
    for root in ROOTS:
        if not root.is_dir():
            raise SystemExit(f"{root} is gone; the scan would silently stop covering it")
        found.extend(
            str(path)
            for path in sorted(root.rglob("*.py"))
            if not any(part in EXCLUDE_PARTS for part in path.relative_to(root).parts)
        )
    if not found:
        raise SystemExit(f"no python files found under {ROOTS}; the scan would pass on nothing")
    return found


def main() -> int:
    floor = declared_floor()
    target = f"{floor[0]}.{floor[1]}"
    # The console script: vermin has no __main__, so `python -m vermin` always fails.
    vermin = shutil.which("vermin")
    if vermin is None:
        raise SystemExit(
            "vermin is not installed, so the backend floor is unchecked. Install it in "
            "the job that runs this, rather than letting the check quietly pass."
        )
    files = targets()
    print(f"[floor] {len(files)} files must run on Python {target}, " f"the declared floor")
    command = [
        vermin,
        "--no-tips",
        "--violations",
        f"-t={target}",
        *files,
    ]
    result = subprocess.run(command, capture_output = True, text = True)
    sys.stdout.write(result.stdout)
    sys.stderr.write(result.stderr)
    if result.returncode == 0:
        print(f"[floor] OK: nothing needs more than {target}")
        return 0
    print(
        f"::error title=Backend needs a newer Python than the matrix floor::"
        f"something under studio/backend or unsloth_cli requires more than Python {target}, "
        f"which is the "
        f"floor studio-backend-ci declares. Nothing runs that interpreter any more, so "
        f"this check is the only thing standing between an above-floor symbol and a user "
        f"on that version. Either guard the usage behind a sys.version_info check, or "
        f"raise {FLOOR_KEY} in the workflow and say why."
    )
    return 1


if __name__ == "__main__":
    raise SystemExit(main())