litellm/scripts/build_core_distribution.py
joshua-berri f48d837cd2
feat(sdk): build core from an independent packaging manifest (#44340)
* feat(sdk): build core from an independent packaging manifest

* test(sdk): compare rebuilt core payload without generated SBOM identity

* fix(sdk): retain native build configuration in the core sdist

* test(sdk): collect coverage from the core build entry point

* fix(ci): isolate core packaging coverage configuration

* fix(test): identify installed core metadata on Python 3.10

* fix(packaging): preserve Git ignore rules in core staging

* fix(packaging): support source-only core builds

* fix(packaging): reject overlapping SDK distributions

* fix(packaging): align core requirements with current main

---------

Co-authored-by: Joshua Valluru <326636767+joshua-berri@users.noreply.github.com>
2026-10-08 18:40:14 -07:00

86 lines
2.8 KiB
Python

"""Build the independent core distribution from shared repository sources."""
import argparse
import shutil
import subprocess
import sys
import tempfile
from pathlib import Path
from typing import Final
ROOT: Final = Path(__file__).resolve().parents[1]
SOURCES: Final = ("litellm", "litellm-rust", ".cargo", "rust-toolchain.toml", "README.md", "LICENSE")
def stage_core_distribution(source: Path, destination: Path) -> None:
version: Final = subprocess.run(
["uv", "version", "--short"], cwd=source, check=True, capture_output=True, text=True
).stdout.strip()
ignored: Final = frozenset(
source / name
for name in subprocess.run(
[
"git",
"ls-files",
"--ignored",
"--cached",
"--others",
"--exclude-standard",
"--directory",
"-z",
"--",
*SOURCES,
],
cwd=source,
check=True,
capture_output=True,
text=True,
).stdout.split("\0")
if name
)
def ignored_sources(directory: str, names: list[str]) -> set[str]:
return {name for name in names if Path(directory) / name in ignored} | shutil.ignore_patterns(
"__pycache__", ".pytest_cache", ".ruff_cache", "target", ".git", "*.so", "*.pyd"
)(directory, names)
destination.mkdir(parents=True, exist_ok=True)
for name in SOURCES:
path: Final = source / name
if path.is_dir():
shutil.copytree(
path,
destination / name,
ignore=ignored_sources,
)
else:
shutil.copy2(path, destination / name)
shutil.copy2(source / "packaging/litellm-core/pyproject.toml", destination / "pyproject.toml")
subprocess.run(["uv", "version", version, "--frozen"], cwd=destination, check=True)
def build_core_distribution(output: Path, *, sdist_only: bool = False) -> None:
output_path: Final = output.resolve()
with tempfile.TemporaryDirectory(prefix="litellm-core-") as temporary:
stage: Final = Path(temporary)
stage_core_distribution(ROOT, stage)
subprocess.run(
["uv", "build", "--python", sys.executable, "--out-dir", str(output_path)]
+ (["--sdist"] if sdist_only else []),
cwd=stage,
check=True,
)
def main() -> None:
parser: Final = argparse.ArgumentParser(description=__doc__)
parser.add_argument("--out-dir", type=Path, default=ROOT / "dist/core")
parser.add_argument(
"--sdist-only", action="store_true", help="Build only the source archive, without compiling a wheel"
)
args: Final = parser.parse_args()
build_core_distribution(Path(args.out_dir), sdist_only=args.sdist_only)
if __name__ == "__main__":
main()