mirror of
https://github.com/BerriAI/litellm.git
synced 2026-08-28 05:25:59 +00:00
prisma resolves its prisma-client-py generator through a plain /bin/sh PATH lookup, never through the interpreter that ran prisma generate, so the gate's generate step landed the client in whatever venv the caller had on PATH: the owned env never received one, every gate run regenerated, the caller's venv was mutated instead, and any invocation without a venv on PATH (the rewritten publisher workflow) failed outright The generate now runs with the target interpreter's bin directory pinned to the front of the child PATH. The prisma schema joins the environment fingerprint so clientless counts recorded before this commit can never be compared against clientful ones, a cold provision announces itself on stderr instead of sitting silent for two minutes, and the CI gate step reuses the job's prisma binary cache
93 lines
3.2 KiB
Python
93 lines
3.2 KiB
Python
#!/usr/bin/env python3
|
|
"""Run ``prisma generate`` only when its inputs changed since the last run.
|
|
|
|
The generated client is a pure function of ``litellm/proxy/schema.prisma`` and
|
|
the installed prisma package version, so a stamp of those two written next to
|
|
the venv is enough to prove the client is current. The stamp lives under
|
|
``sys.prefix`` so recreating the venv discards it, and a missing generated
|
|
client (a fresh or reinstalled prisma package) forces a regenerate even when
|
|
the stamp matches. The prisma package itself is never imported here: once
|
|
generated it re-exports the whole client on import, which costs more than the
|
|
generate this script exists to skip.
|
|
|
|
prisma resolves its generator command (``prisma-client-py``) through a plain
|
|
PATH lookup, never through the interpreter that invoked ``prisma generate``,
|
|
so the generate runs with this interpreter's own bin directory pinned to the
|
|
front of PATH; without that pin the client lands in whichever venv the caller
|
|
happened to have on PATH (or the generate fails outright when none is).
|
|
"""
|
|
|
|
import hashlib
|
|
import importlib.metadata
|
|
import importlib.util
|
|
import os
|
|
import subprocess
|
|
import sys
|
|
from collections.abc import Callable, Mapping
|
|
from pathlib import Path
|
|
|
|
REPO_ROOT = Path(__file__).resolve().parent.parent
|
|
SCHEMA = REPO_ROOT / "litellm" / "proxy" / "schema.prisma"
|
|
STAMP = Path(sys.prefix) / "litellm-prisma-schema.stamp"
|
|
|
|
|
|
def stamp_value(schema_bytes: bytes, prisma_version: str) -> str:
|
|
return f"{hashlib.sha256(schema_bytes).hexdigest()}:{prisma_version}"
|
|
|
|
|
|
def should_skip(stamp: Path, expected: str, client_generated: bool) -> bool:
|
|
if not client_generated:
|
|
return False
|
|
try:
|
|
return stamp.read_text() == expected
|
|
except OSError:
|
|
return False
|
|
|
|
|
|
def client_is_generated() -> bool:
|
|
spec = importlib.util.find_spec("prisma")
|
|
if spec is None or not spec.submodule_search_locations:
|
|
return False
|
|
return any(
|
|
(Path(location) / "client.py").exists()
|
|
for location in spec.submodule_search_locations
|
|
)
|
|
|
|
|
|
def env_with_own_bin_first(base_env: Mapping[str, str]) -> dict[str, str]:
|
|
bin_dir = str(Path(sys.executable).parent)
|
|
inherited = base_env.get("PATH")
|
|
path = os.pathsep.join((bin_dir, inherited)) if inherited else bin_dir
|
|
return {**base_env, "PATH": path}
|
|
|
|
|
|
def _run_command(cmd: list[str], cwd: Path, env: dict[str, str]) -> int:
|
|
return subprocess.run(cmd, cwd=cwd, env=env).returncode
|
|
|
|
|
|
def run_generate(run: Callable[[list[str], Path, dict[str, str]], int] = _run_command) -> int:
|
|
return run(
|
|
[sys.executable, "-m", "prisma", "generate", "--schema", str(SCHEMA)],
|
|
REPO_ROOT,
|
|
env_with_own_bin_first(os.environ),
|
|
)
|
|
|
|
|
|
def main() -> int:
|
|
version = importlib.metadata.version("prisma")
|
|
expected = stamp_value(SCHEMA.read_bytes(), version)
|
|
if should_skip(STAMP, expected, client_is_generated()):
|
|
print(
|
|
f"Prisma client already generated for {SCHEMA.relative_to(REPO_ROOT)} "
|
|
f"(prisma {version}); skipping prisma generate"
|
|
)
|
|
return 0
|
|
returncode = run_generate()
|
|
if returncode != 0:
|
|
return returncode
|
|
STAMP.write_text(expected)
|
|
return 0
|
|
|
|
|
|
if __name__ == "__main__":
|
|
raise SystemExit(main())
|