mirror of
https://github.com/BerriAI/litellm.git
synced 2026-11-12 08:42:18 +00:00
feat(packaging): build litellm-proxy gateway wheels (#49605)
* feat(packaging): ship litellm-proxy wheels with the proxy extra Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> * fix(packaging): keep litellm-proxy out of the proxy extra until PyPI has it The current release pipeline publishes litellm with whatever pyproject.toml lists, so pinning an unpublished package would break pip install litellm[proxy]. Images and CI still install the locally built gateway wheel Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> --------- Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
parent
6282300598
commit
79710a6ff1
12 changed files with 139 additions and 28 deletions
2
.github/workflows/image-scan.yml
vendored
2
.github/workflows/image-scan.yml
vendored
|
|
@ -53,7 +53,7 @@ jobs:
|
|||
if: >-
|
||||
github.event_name != 'pull_request' ||
|
||||
github.event.pull_request.head.repo.full_name == github.repository
|
||||
timeout-minutes: 30
|
||||
timeout-minutes: 60
|
||||
permissions:
|
||||
contents: read
|
||||
steps:
|
||||
|
|
|
|||
2
.github/workflows/test-linting.yml
vendored
2
.github/workflows/test-linting.yml
vendored
|
|
@ -21,7 +21,7 @@ jobs:
|
|||
pull-requests: read
|
||||
actions: read
|
||||
runs-on: ubuntu-latest
|
||||
timeout-minutes: 20
|
||||
timeout-minutes: 30
|
||||
services:
|
||||
redis:
|
||||
image: redis@sha256:e2debfb7956fa12c7ddc79d7e645c8cf26b30c99a6e9161ea9bf4171e1668a5f
|
||||
|
|
|
|||
18
.github/workflows/test-unit.yml
vendored
18
.github/workflows/test-unit.yml
vendored
|
|
@ -45,7 +45,7 @@ jobs:
|
|||
id: rust-bridge-key
|
||||
if: steps.changes.outputs.decision != 'skip'
|
||||
env:
|
||||
RUST_BRIDGE_CACHE_KEY: ${{ runner.os }}-rust-bridge-editable-${{ hashFiles('litellm-rust/Cargo.lock', 'litellm-rust/Cargo.toml', 'litellm-rust/crates/**', 'model_prices_and_context_window.json', 'pyproject.toml') }}
|
||||
RUST_BRIDGE_CACHE_KEY: ${{ runner.os }}-rust-bridge-editable-${{ hashFiles('litellm-rust/Cargo.lock', 'litellm-rust/Cargo.toml', 'litellm-rust/crates/**', 'model_prices_and_context_window.json', 'pyproject.toml', 'packaging/litellm-proxy/pyproject.toml') }}
|
||||
run: echo "key=$RUST_BRIDGE_CACHE_KEY" >> "$GITHUB_OUTPUT"
|
||||
|
||||
- name: Set up Python
|
||||
|
|
@ -98,6 +98,18 @@ jobs:
|
|||
mkdir -p rust-bridge-dist/litellm/rust_bridge
|
||||
cp litellm/rust_bridge/_native.abi3.so rust-bridge-dist/litellm/rust_bridge/_native.abi3.so
|
||||
|
||||
- name: Build the gateway wheel once for test shards
|
||||
if: steps.changes.outputs.decision != 'skip' && steps.rust-bridge-cache.outputs.cache-hit != 'true'
|
||||
timeout-minutes: 15
|
||||
working-directory: packaging/litellm-proxy
|
||||
env:
|
||||
RUSTC_WRAPPER: sccache
|
||||
SCCACHE_GHA_ENABLED: "true"
|
||||
SCCACHE_GHA_VERSION: litellm-ci-v1
|
||||
SCCACHE_GHA_RW_MODE: ${{ github.event_name == 'push' && github.ref == 'refs/heads/main' && 'READ_WRITE' || 'READ_ONLY' }}
|
||||
CARGO_INCREMENTAL: "0"
|
||||
run: uv run --no-project --with maturin==1.15.0 maturin build --profile dev --strip --out ../../rust-bridge-dist
|
||||
|
||||
- name: Upload Rust bridge artifact
|
||||
if: steps.changes.outputs.decision != 'skip'
|
||||
timeout-minutes: 10
|
||||
|
|
@ -1024,7 +1036,7 @@ jobs:
|
|||
if [ -z "$RUST_BRIDGE_ARTIFACT" ]; then
|
||||
.github/scripts/uv_sync_with_retries.sh --frozen --group ci --group proxy-dev --extra google --extra proxy --extra semantic-router --extra saml --extra extra_proxy --extra proxy-runtime --extra utils
|
||||
else
|
||||
.github/scripts/uv_sync_with_retries.sh --frozen --group ci --group proxy-dev --extra google --extra proxy --extra semantic-router --extra saml --extra extra_proxy --extra proxy-runtime --extra utils --no-install-project
|
||||
.github/scripts/uv_sync_with_retries.sh --frozen --group ci --group proxy-dev --extra google --extra proxy --extra semantic-router --extra saml --extra extra_proxy --extra proxy-runtime --extra utils --no-install-project --no-install-package litellm-proxy
|
||||
uv pip install --no-deps --python .venv/bin/python rust-bridge-dist/*.whl
|
||||
cp rust-bridge-dist/litellm/rust_bridge/_native.abi3.so litellm/rust_bridge/_native.abi3.so
|
||||
uv run --no-sync python -c "import importlib.metadata; import litellm.rust_bridge._native; print(importlib.metadata.version('litellm'))"
|
||||
|
|
@ -1486,7 +1498,7 @@ jobs:
|
|||
if [ -z "$RUST_BRIDGE_ARTIFACT" ]; then
|
||||
.github/scripts/uv_sync_with_retries.sh --frozen --group ci --group proxy-dev --extra google --extra proxy --extra semantic-router --extra saml --extra extra_proxy --extra proxy-runtime --extra utils
|
||||
else
|
||||
.github/scripts/uv_sync_with_retries.sh --frozen --group ci --group proxy-dev --extra google --extra proxy --extra semantic-router --extra saml --extra extra_proxy --extra proxy-runtime --extra utils --no-install-project
|
||||
.github/scripts/uv_sync_with_retries.sh --frozen --group ci --group proxy-dev --extra google --extra proxy --extra semantic-router --extra saml --extra extra_proxy --extra proxy-runtime --extra utils --no-install-project --no-install-package litellm-proxy
|
||||
uv pip install --no-deps --python .venv/bin/python rust-bridge-dist/*.whl
|
||||
cp rust-bridge-dist/litellm/rust_bridge/_native.abi3.so litellm/rust_bridge/_native.abi3.so
|
||||
fi
|
||||
|
|
|
|||
|
|
@ -76,6 +76,7 @@ ENV UV_PROJECT_ENVIRONMENT=/app/.venv \
|
|||
COPY pyproject.toml uv.lock ./
|
||||
COPY enterprise/pyproject.toml enterprise/
|
||||
COPY litellm-proxy-extras/pyproject.toml litellm-proxy-extras/
|
||||
COPY packaging/litellm-proxy/pyproject.toml packaging/litellm-proxy/
|
||||
|
||||
# Install third-party dependencies (cached unless pyproject.toml/uv.lock change)
|
||||
RUN uv sync --frozen --no-install-project --no-install-workspace --no-default-groups --no-editable \
|
||||
|
|
@ -101,7 +102,8 @@ COPY --from=ui-builder /ui/out/. litellm/proxy/_experimental/out/
|
|||
RUN sed -i 's/\r$//' docker/build_admin_ui.sh && chmod +x docker/build_admin_ui.sh && ./docker/build_admin_ui.sh
|
||||
|
||||
# Install project and workspace packages (fast - deps already cached)
|
||||
RUN uv sync --frozen --no-default-groups --no-editable \
|
||||
RUN uv build --package litellm-proxy --wheel --out-dir /wheels
|
||||
RUN uv sync --frozen --no-install-package litellm-proxy --no-default-groups --no-editable \
|
||||
--extra proxy \
|
||||
--extra proxy-runtime \
|
||||
--group admin-mcp \
|
||||
|
|
@ -111,6 +113,8 @@ RUN uv sync --frozen --no-default-groups --no-editable \
|
|||
--extra bedrock-realtime \
|
||||
--python python3.13
|
||||
|
||||
RUN uv pip install --python /app/.venv/bin/python --no-deps /wheels/litellm_proxy-*.whl
|
||||
|
||||
RUN HOME=/opt/prisma XDG_CACHE_HOME=/opt/prisma/.cache PRISMA_BINARY_CACHE_DIR=/opt/prisma/binaries \
|
||||
npm_config_cache=/root/.npm \
|
||||
prisma generate --schema=./schema.prisma
|
||||
|
|
|
|||
|
|
@ -74,6 +74,7 @@ ENV UV_PROJECT_ENVIRONMENT=/app/.venv \
|
|||
COPY pyproject.toml uv.lock ./
|
||||
COPY enterprise/pyproject.toml enterprise/
|
||||
COPY litellm-proxy-extras/pyproject.toml litellm-proxy-extras/
|
||||
COPY packaging/litellm-proxy/pyproject.toml packaging/litellm-proxy/
|
||||
|
||||
# Install third-party dependencies (cached unless pyproject.toml/uv.lock change)
|
||||
RUN uv sync --frozen --no-install-project --no-install-workspace --no-default-groups --no-editable \
|
||||
|
|
@ -99,7 +100,8 @@ COPY --from=ui-builder /ui/out/. litellm/proxy/_experimental/out/
|
|||
RUN sed -i 's/\r$//' docker/build_admin_ui.sh && chmod +x docker/build_admin_ui.sh && ./docker/build_admin_ui.sh
|
||||
|
||||
# Install project and workspace packages (fast - deps already cached)
|
||||
RUN uv sync --frozen --no-default-groups --no-editable \
|
||||
RUN uv build --package litellm-proxy --wheel --out-dir /wheels
|
||||
RUN uv sync --frozen --no-install-package litellm-proxy --no-default-groups --no-editable \
|
||||
--extra proxy \
|
||||
--extra proxy-runtime \
|
||||
--group admin-mcp \
|
||||
|
|
@ -109,6 +111,8 @@ RUN uv sync --frozen --no-default-groups --no-editable \
|
|||
--extra bedrock-realtime \
|
||||
--python python3.13
|
||||
|
||||
RUN uv pip install --python /app/.venv/bin/python --no-deps /wheels/litellm_proxy-*.whl
|
||||
|
||||
RUN HOME=/opt/prisma XDG_CACHE_HOME=/opt/prisma/.cache PRISMA_BINARY_CACHE_DIR=/opt/prisma/binaries \
|
||||
npm_config_cache=/root/.npm \
|
||||
prisma generate --schema=./schema.prisma
|
||||
|
|
|
|||
|
|
@ -41,10 +41,14 @@ COPY pyproject.toml README.md rust-toolchain.toml ./
|
|||
COPY .cargo ./.cargo
|
||||
COPY litellm-rust ./litellm-rust
|
||||
COPY model_prices_and_context_window.json ./
|
||||
COPY packaging/litellm-proxy/pyproject.toml packaging/litellm-proxy/
|
||||
|
||||
RUN --mount=type=cache,target=/root/.cache/uv \
|
||||
mkdir -p litellm/rust_bridge /wheels && \
|
||||
touch litellm/__init__.py litellm/rust_bridge/__init__.py && \
|
||||
uvx --python python3.13 --from maturin==1.15.0 --with puccinialin==0.1.14 \
|
||||
python -c "import maturin; maturin.build_wheel('/wheels')" && \
|
||||
cd packaging/litellm-proxy && \
|
||||
uvx --python python3.13 --from maturin==1.15.0 --with puccinialin==0.1.14 \
|
||||
python -c "import maturin; maturin.build_wheel('/wheels')"
|
||||
|
||||
|
|
@ -85,6 +89,7 @@ RUN --mount=type=cache,target=/root/.cache/uv \
|
|||
--mount=type=bind,source=uv.lock,target=uv.lock \
|
||||
--mount=type=bind,source=enterprise/pyproject.toml,target=enterprise/pyproject.toml \
|
||||
--mount=type=bind,source=litellm-proxy-extras/pyproject.toml,target=litellm-proxy-extras/pyproject.toml \
|
||||
--mount=type=bind,source=packaging/litellm-proxy/pyproject.toml,target=packaging/litellm-proxy/pyproject.toml \
|
||||
uv sync --frozen --no-install-project --no-install-workspace --no-default-groups --no-editable \
|
||||
--extra proxy \
|
||||
--extra proxy-runtime \
|
||||
|
|
@ -98,7 +103,7 @@ RUN --mount=type=cache,target=/root/.cache/uv \
|
|||
COPY . .
|
||||
|
||||
RUN --mount=type=cache,target=/root/.cache/uv \
|
||||
uv sync --frozen --no-install-project --no-default-groups --no-editable \
|
||||
uv sync --frozen --no-install-project --no-install-package litellm-proxy --no-default-groups --no-editable \
|
||||
--extra proxy \
|
||||
--extra proxy-runtime \
|
||||
--group admin-mcp \
|
||||
|
|
@ -108,7 +113,7 @@ RUN --mount=type=cache,target=/root/.cache/uv \
|
|||
--python python3.13
|
||||
|
||||
RUN --mount=type=bind,from=rust-native,source=/wheels,target=/wheels \
|
||||
uv pip install --python /app/.venv/bin/python --no-deps /wheels/litellm-*.whl
|
||||
uv pip install --python /app/.venv/bin/python --no-deps /wheels/litellm-*.whl /wheels/litellm_proxy-*.whl
|
||||
|
||||
# PYTHONPATH=/app makes the source tree shadow the installed package, so the
|
||||
# compiled Rust extension must live next to the source or it is never imported.
|
||||
|
|
|
|||
22
packaging/litellm-proxy/pyproject.toml
Normal file
22
packaging/litellm-proxy/pyproject.toml
Normal file
|
|
@ -0,0 +1,22 @@
|
|||
[project]
|
||||
name = "litellm-proxy"
|
||||
version = "1.109.0"
|
||||
description = "Opt-in Rust HTTP forwarding server for the LiteLLM Python proxy"
|
||||
requires-python = ">=3.10, <3.16"
|
||||
license = "MIT"
|
||||
|
||||
[build-system]
|
||||
requires = ["maturin==1.15.0"]
|
||||
build-backend = "maturin"
|
||||
|
||||
[tool.maturin]
|
||||
manifest-path = "../../litellm-rust/crates/gateway/Cargo.toml"
|
||||
bindings = "bin"
|
||||
targets = [{ name = "litellm-gateway", kind = "bin" }]
|
||||
profile = "release"
|
||||
editable-profile = "dev"
|
||||
include = [
|
||||
{ path = "rust-toolchain.toml", format = "sdist" },
|
||||
{ path = ".cargo/config.toml", format = "sdist" },
|
||||
{ path = "model_prices_and_context_window.json", format = "sdist" },
|
||||
]
|
||||
|
|
@ -359,6 +359,7 @@ exclude = [
|
|||
]
|
||||
|
||||
[tool.uv]
|
||||
concurrent-builds = 1
|
||||
cache-keys = [
|
||||
{ file = "pyproject.toml" },
|
||||
{ file = "rust-toolchain.toml" },
|
||||
|
|
@ -395,11 +396,12 @@ brotli = "2026-10-22T14:01:00Z"
|
|||
pypdf = "2026-10-28T17:01:00Z"
|
||||
|
||||
[tool.uv.sources]
|
||||
litellm-proxy = { workspace = true }
|
||||
litellm-proxy-extras = { workspace = true }
|
||||
litellm-enterprise = { workspace = true }
|
||||
|
||||
[tool.uv.workspace]
|
||||
members = ["enterprise", "litellm-proxy-extras"]
|
||||
members = ["enterprise", "litellm-proxy-extras", "packaging/litellm-proxy"]
|
||||
|
||||
[tool.commitizen]
|
||||
version = "1.109.0"
|
||||
|
|
|
|||
|
|
@ -1,4 +1,4 @@
|
|||
"""Build the independent core distribution from shared repository sources."""
|
||||
"""Build standalone core or gateway distributions from shared repository sources."""
|
||||
|
||||
import argparse
|
||||
import shutil
|
||||
|
|
@ -19,8 +19,16 @@ SOURCES: Final = (
|
|||
"LICENSE",
|
||||
)
|
||||
|
||||
IN_TREE_RUST_PATH: Final = "../../litellm-rust/"
|
||||
|
||||
def stage_core_distribution(source: Path, destination: Path) -> None:
|
||||
|
||||
class BuildOptions(argparse.Namespace):
|
||||
package: str
|
||||
out_dir: Path
|
||||
sdist_only: bool
|
||||
|
||||
|
||||
def stage_core_distribution(source: Path, destination: Path, *, package: str = "litellm-core") -> None:
|
||||
version: Final = subprocess.run(
|
||||
["uv", "version", "--short"], cwd=source, check=True, capture_output=True, text=True
|
||||
).stdout.strip()
|
||||
|
|
@ -53,8 +61,7 @@ def stage_core_distribution(source: Path, destination: Path) -> None:
|
|||
)(directory, names)
|
||||
|
||||
destination.mkdir(parents=True, exist_ok=True)
|
||||
for name in SOURCES:
|
||||
path: Final = source / name
|
||||
for name, path in ((name, source / name) for name in SOURCES if package == "litellm-core" or name != "litellm"):
|
||||
if path.is_dir():
|
||||
shutil.copytree(
|
||||
path,
|
||||
|
|
@ -63,15 +70,19 @@ def stage_core_distribution(source: Path, destination: Path) -> None:
|
|||
)
|
||||
else:
|
||||
shutil.copy2(path, destination / name)
|
||||
shutil.copy2(source / "packaging/litellm-core/pyproject.toml", destination / "pyproject.toml")
|
||||
template: Final = (source / "packaging" / package / "pyproject.toml").read_text()
|
||||
if package == "litellm-proxy" and IN_TREE_RUST_PATH not in template:
|
||||
raise SystemExit(f"packaging/{package}/pyproject.toml no longer points at {IN_TREE_RUST_PATH}")
|
||||
metadata: Final = template.replace(IN_TREE_RUST_PATH, "litellm-rust/")
|
||||
(destination / "pyproject.toml").write_text(metadata)
|
||||
subprocess.run(["uv", "version", version, "--frozen"], cwd=destination, check=True)
|
||||
|
||||
|
||||
def build_core_distribution(output: Path, *, sdist_only: bool = False) -> None:
|
||||
def build_core_distribution(output: Path, *, sdist_only: bool = False, package: str = "litellm-core") -> None:
|
||||
output_path: Final = output.resolve()
|
||||
with tempfile.TemporaryDirectory(prefix="litellm-core-") as temporary:
|
||||
stage: Final = Path(temporary)
|
||||
stage_core_distribution(ROOT, stage)
|
||||
stage_core_distribution(ROOT, stage, package=package)
|
||||
subprocess.run(
|
||||
["uv", "build", "--python", sys.executable, "--out-dir", str(output_path)]
|
||||
+ (["--sdist"] if sdist_only else []),
|
||||
|
|
@ -82,12 +93,13 @@ def build_core_distribution(output: Path, *, sdist_only: bool = False) -> None:
|
|||
|
||||
def main() -> None:
|
||||
parser: Final = argparse.ArgumentParser(description=__doc__)
|
||||
parser.add_argument("--package", choices=("litellm-core", "litellm-proxy"), default="litellm-core")
|
||||
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)
|
||||
args: Final = parser.parse_args(namespace=BuildOptions())
|
||||
build_core_distribution(Path(args.out_dir), sdist_only=args.sdist_only, package=args.package)
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
|
|
|
|||
|
|
@ -20,12 +20,21 @@ else:
|
|||
ROOT: Final = Path(__file__).resolve().parents[2]
|
||||
|
||||
|
||||
@pytest.mark.parametrize(
|
||||
("package_cli_args", "package"),
|
||||
[
|
||||
(("--package", "litellm-proxy"), "litellm-proxy"),
|
||||
((), "litellm-core"),
|
||||
],
|
||||
)
|
||||
@pytest.mark.parametrize("sdist_only", [False, True])
|
||||
def test_build_command_selects_requested_distributions(tmp_path: Path, sdist_only: bool) -> None:
|
||||
def test_build_command_selects_requested_distributions(
|
||||
tmp_path: Path, sdist_only: bool, package_cli_args: tuple[str, ...], package: str
|
||||
) -> None:
|
||||
from scripts.build_core_distribution import main
|
||||
|
||||
output: Final = tmp_path / "dist"
|
||||
arguments: Final = ["build_core_distribution.py", "--out-dir", str(output)] + (
|
||||
arguments: Final = ["build_core_distribution.py", *package_cli_args, "--out-dir", str(output)] + (
|
||||
["--sdist-only"] if sdist_only else []
|
||||
)
|
||||
with (
|
||||
|
|
@ -42,6 +51,7 @@ def test_build_command_selects_requested_distributions(tmp_path: Path, sdist_onl
|
|||
assert command[command.index("--out-dir") + 1] == str(output)
|
||||
assert run.call_args.kwargs["check"] is True
|
||||
assert run.call_args.kwargs["cwd"] == stage.call_args.args[1]
|
||||
assert stage.call_args.kwargs["package"] == package
|
||||
assert not stage.call_args.args[1].exists()
|
||||
|
||||
|
||||
|
|
@ -53,7 +63,10 @@ def source_repository(tmp_path: Path) -> Path:
|
|||
return source
|
||||
|
||||
|
||||
def test_staging_stamps_release_version_without_modifying_sources(tmp_path: Path, source_repository: Path) -> None:
|
||||
@pytest.mark.parametrize("package", ["litellm-core", "litellm-proxy"])
|
||||
def test_staging_stamps_release_version_without_modifying_sources(
|
||||
tmp_path: Path, source_repository: Path, package: str
|
||||
) -> None:
|
||||
from scripts.build_core_distribution import SOURCES, stage_core_distribution
|
||||
|
||||
source: Final = source_repository
|
||||
|
|
@ -61,16 +74,44 @@ def test_staging_stamps_release_version_without_modifying_sources(tmp_path: Path
|
|||
path: Final = source / name
|
||||
path.write_text(f"shared {name}")
|
||||
(source / "pyproject.toml").write_text('[project]\nname = "litellm"\nversion = "9.8.7rc1"\n')
|
||||
manifest: Final = source / "packaging/litellm-core/pyproject.toml"
|
||||
manifest: Final = source / "packaging" / package / "pyproject.toml"
|
||||
manifest.parent.mkdir(parents=True)
|
||||
manifest.write_bytes((ROOT / "packaging/litellm-core/pyproject.toml").read_bytes())
|
||||
manifest.write_bytes((ROOT / "packaging" / package / "pyproject.toml").read_bytes())
|
||||
original: Final = manifest.read_bytes()
|
||||
stage: Final = tmp_path / "stage"
|
||||
stage_core_distribution(source, stage)
|
||||
assert tomllib.loads((stage / "pyproject.toml").read_text())["project"]["version"] == "9.8.7rc1"
|
||||
stage_core_distribution(source, stage, package=package)
|
||||
staged_project: Final = tomllib.loads((stage / "pyproject.toml").read_text())
|
||||
assert staged_project["project"]["name"] == package
|
||||
assert staged_project["project"]["version"] == "9.8.7rc1"
|
||||
if package == "litellm-proxy":
|
||||
assert staged_project["tool"]["maturin"]["targets"] == [{"name": "litellm-gateway", "kind": "bin"}]
|
||||
assert not (stage / "litellm").exists()
|
||||
assert all(
|
||||
(stage / name).exists()
|
||||
for name in ("litellm-rust", ".cargo", "rust-toolchain.toml", "model_prices_and_context_window.json")
|
||||
)
|
||||
assert manifest.read_bytes() == original
|
||||
assert (source / "pyproject.toml").read_text() == '[project]\nname = "litellm"\nversion = "9.8.7rc1"\n'
|
||||
assert all((stage / name).read_bytes() == (source / name).read_bytes() for name in SOURCES)
|
||||
expected: Final = tuple(name for name in SOURCES if package == "litellm-core" or name != "litellm")
|
||||
assert all((stage / name).read_bytes() == (source / name).read_bytes() for name in expected)
|
||||
|
||||
|
||||
def test_gateway_staging_refuses_manifest_without_in_tree_rust_path(tmp_path: Path, source_repository: Path) -> None:
|
||||
from scripts.build_core_distribution import SOURCES, stage_core_distribution
|
||||
|
||||
source: Final = source_repository
|
||||
for name in SOURCES:
|
||||
(source / name).write_text(f"shared {name}")
|
||||
(source / "pyproject.toml").write_text('[project]\nname = "litellm"\nversion = "9.8.7"\n')
|
||||
manifest: Final = source / "packaging" / "litellm-proxy" / "pyproject.toml"
|
||||
manifest.parent.mkdir(parents=True)
|
||||
manifest.write_text(
|
||||
(ROOT / "packaging" / "litellm-proxy" / "pyproject.toml")
|
||||
.read_text()
|
||||
.replace("../../litellm-rust/", "../../rust/")
|
||||
)
|
||||
with pytest.raises(SystemExit, match="no longer points at"):
|
||||
stage_core_distribution(source, tmp_path / "stage", package="litellm-proxy")
|
||||
|
||||
|
||||
@pytest.fixture(scope="module")
|
||||
|
|
@ -99,7 +140,9 @@ def test_core_wheel_metadata_and_resources(distributions: tuple[Path, Path]) ->
|
|||
assert metadata["Version"] == tomllib.loads((ROOT / "pyproject.toml").read_text())["project"]["version"]
|
||||
assert not metadata.get_all("Provides-Extra")
|
||||
assert not any(n.endswith(".dist-info/entry_points.txt") for n in names)
|
||||
requirements: Final = tomllib.loads((ROOT / "packaging/litellm-core/pyproject.toml").read_text())["project"]["dependencies"]
|
||||
requirements: Final = tomllib.loads((ROOT / "packaging/litellm-core/pyproject.toml").read_text())["project"][
|
||||
"dependencies"
|
||||
]
|
||||
for python_version in ("3.10", "3.11", "3.12", "3.13", "3.14"):
|
||||
environment: Final = {"python_version": python_version, "python_full_version": python_version + ".0"}
|
||||
assert {
|
||||
|
|
|
|||
|
|
@ -89,6 +89,7 @@ importlib-metadata: >=6.8.0 # Apache 2.0 License
|
|||
tokenizers: >=0.20.2 # Apache 2.0 License
|
||||
jinja2: >=3.1.4 # BSD 3-Clause License
|
||||
litellm-proxy-extras: >=0.1.1 # MIT License
|
||||
litellm-proxy: >=1.109.0 # MIT, verified in repository LICENSE for litellm-rust and packaging/litellm-proxy
|
||||
litellm-enterprise: >=0.1.1 # LiteLLM Enterprise License
|
||||
a2a-sdk: >=0.3.22 # Apache 2.0 license
|
||||
anyio: >=4.5.0 # Unknown license
|
||||
|
|
|
|||
6
uv.lock
generated
6
uv.lock
generated
|
|
@ -22,6 +22,7 @@ pypdf = "2026-10-28T17:01:00Z"
|
|||
members = [
|
||||
"litellm",
|
||||
"litellm-enterprise",
|
||||
"litellm-proxy",
|
||||
"litellm-proxy-extras",
|
||||
]
|
||||
constraints = [
|
||||
|
|
@ -5526,6 +5527,11 @@ name = "litellm-enterprise"
|
|||
version = "0.1.81"
|
||||
source = { editable = "enterprise" }
|
||||
|
||||
[[package]]
|
||||
name = "litellm-proxy"
|
||||
version = "1.109.0"
|
||||
source = { editable = "packaging/litellm-proxy" }
|
||||
|
||||
[[package]]
|
||||
name = "litellm-proxy-extras"
|
||||
version = "0.4.112"
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue