Files
litellm/pyproject.toml
T
stuxf a6c30b30bf build: migrate packaging, CI, and Docker from Poetry to uv (#25007)
* build: migrate packaging metadata to uv

* ci: move automation and local tooling to uv

* docker: migrate image builds and runtime setup to uv

* docs: update install and deployment guidance for uv

* chore: align auxiliary scripts and tests with uv

* test: harden test_litellm isolation

* fix: keep release and health check images self-contained

* build: pin uv tooling and health check deps

* test: isolate bedrock image request formatting from suite state

* test: cover sandbox executor requirements flow

* ci: fix circleci no-op command steps

* ci: fix circleci publish workflow parsing

* fix: stabilize remaining uv migration CI checks

* ci: increase matrix test timeout headroom

* fix: restore published docker and license coverage

* fix: restore proxy runtime build parity

* fix: restore proxy extras parity and venv migrations

* ci: persist uv path across circleci steps

* fix: keep psycopg binary in default test env

* docker: preserve prisma cache across stages

* test: run local proxy checks through uv python

* build: restore runtime deps moved into ci

* build: refresh uv lock after upstream merge

* fix: restore module import in test_check_migration after merge

The conflict resolution imported only the function but the test body
references check_migration as a module throughout.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>

* fix: revert dependency promotions, remove nodejs-wheel-binaries, fix Docker layer caching

- Move google-generativeai, Pillow, tenacity back to ci group (they are
  lazily imported and bloat the base SDK install needlessly)
- Remove nodejs-wheel-binaries from extra_proxy and proxy-dev (redundant
  in Docker where system Node.js is already installed via apk)
- Remove all nodejs-wheel node replacement and venv npm patching blocks
  from Dockerfiles since the wheel is no longer installed
- Add --no-default-groups to CodSpeed benchmark workflow so the benchmark
  environment matches the old minimal pip install footprint
- Apply standard uv two-phase Docker pattern: copy metadata first, install
  deps (cached layer), then copy source and install project
- Replace CircleCI enterprise no-op with proper uv sync command

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>

* chore: regenerate uv.lock after removing nodejs-wheel-binaries

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>

* fix(ci): use cache/restore instead of cache to prevent cache poisoning

The old workflow used actions/cache/restore (read-only). The uv migration
changed it to actions/cache (read-write), which zizmor flags as a cache
poisoning risk. Restore the safer read-only variant.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>

* fix(ci): disable setup-uv built-in cache to silence cache-poisoning alert

The setup-uv action enables caching by default, which zizmor flags as a
cache poisoning risk. Disable it since we already use a read-only
cache/restore step.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>

* fix(ci): disable setup-uv cache in publish workflow

Silences zizmor cache-poisoning alert. Publishing workflow runs
infrequently on protected branches so caching adds no real benefit.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>

* fix(test): remove duplicate verbose_logger mock in test_check_migration

The logger was patched twice — first via mocker.patch() then via
mocker.patch.object(autospec=True). The second call fails because
autospec cannot inspect an already-mocked attribute. Remove the
redundant first patch.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>

* fix(ci): free disk space before Docker build in test-server-root-path

The Dockerfile.non_root build ran out of disk on the CI runner. Remove
Android SDK, .NET, Boost, and GHC toolchains (~12GB) to free space.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>

---------

Co-authored-by: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-09 11:46:23 -07:00

270 lines
8.2 KiB
TOML

[project]
name = "litellm"
version = "1.83.5"
description = "Library to easily interface with LLM API providers"
readme = "README.md"
requires-python = ">=3.9"
license = "MIT"
license-files = ["LICENSE"]
authors = [
{ name = "BerriAI" },
]
dependencies = [
"fastuuid==0.14.0",
"httpx==0.28.1",
"openai==2.24.0",
"python-dotenv==1.0.1",
"tiktoken==0.12.0",
"importlib-metadata==8.5.0",
"tokenizers==0.22.2",
"click==8.1.8",
"jinja2==3.1.6",
"aiohttp==3.13.3",
"pydantic==2.12.5",
"jsonschema==4.23.0",
]
[project.urls]
Homepage = "https://litellm.ai"
Repository = "https://github.com/BerriAI/litellm"
Documentation = "https://docs.litellm.ai"
# Dependencies pinned from the published `litellm[proxy]==1.83.0` resolution.
# Docker and CI should prefer `uv.lock` rather than maintaining parallel installers.
[project.optional-dependencies]
proxy = [
"gunicorn==23.0.0",
"uvicorn==0.33.0",
"uvloop==0.21.0; sys_platform != 'win32'",
"fastapi==0.124.4",
"backoff==2.2.1",
"pyyaml==6.0.3",
"rq==2.7.0",
"orjson==3.10.15",
"apscheduler==3.11.2",
"fastapi-sso==0.16.0",
"PyJWT==2.11.0; python_version >= '3.9'",
"python-multipart==0.0.20",
# Docker uses 46.0.5; pyproject uses 43.0.3 for Python 3.9.0/3.9.1 compat.
"cryptography==43.0.3",
"pynacl==1.6.2",
"websockets==15.0.1",
"boto3==1.42.59",
"azure-identity==1.25.2; python_version >= '3.9'",
"azure-storage-blob==12.28.0",
"mcp==1.26.0; python_version >= '3.10'",
"litellm-proxy-extras==0.4.65",
"litellm-enterprise==0.1.37",
"rich==13.9.4",
"polars==1.38.1; python_version >= '3.10'",
"soundfile==0.12.1",
"pyroscope-io==0.8.16; sys_platform != 'win32'",
]
extra_proxy = [
"prisma==0.11.0",
"azure-identity==1.25.2; python_version >= '3.9'",
"azure-keyvault-secrets==4.10.0",
# Not in PyPI proxy extra.
"google-cloud-kms==2.24.2",
"google-cloud-iam==2.19.1",
# Not in PyPI proxy extra.
"resend==2.23.0",
"redisvl==0.4.1; python_version >= '3.9' and python_version < '3.14'",
"a2a-sdk==0.3.24; python_version >= '3.10'",
]
utils = [
# Not in Docker or PyPI proxy extra.
"numpydoc==1.8.0",
]
caching = ["diskcache==5.6.3"]
semantic-router = [
"semantic-router==0.1.12; python_version >= '3.9' and python_version < '3.14'",
"aurelio-sdk==0.0.19; python_version >= '3.9' and python_version < '3.14'",
]
mlflow = ["mlflow==3.9.0; python_version >= '3.10'"]
grpc = [
# Newest non-yanked release older than the 30-day cutoff.
"grpcio==1.78.0",
]
google = ["google-cloud-aiplatform==1.133.0"]
proxy-runtime = [
# Historically bundled in the proxy Docker images via requirements.txt.
# Keep these in a dedicated extra so uv-based images preserve the same
# feature surface without forcing the base SDK install to grow.
"google-cloud-aiplatform==1.133.0",
"google-genai==1.37.0",
"anthropic[vertex]==0.84.0",
"grpcio==1.78.0",
"prometheus-client==0.20.0",
"langfuse==2.59.7",
"opentelemetry-api==1.28.0",
"opentelemetry-sdk==1.28.0",
"opentelemetry-exporter-otlp==1.28.0",
"ddtrace==2.19.0",
"sentry-sdk==2.21.0",
"mangum==0.17.0",
"azure-ai-contentsafety==1.0.0",
"azure-storage-file-datalake==12.20.0",
"pypdf==6.7.5; python_version < '3.14'",
"llm-sandbox==0.3.31; python_version >= '3.10'",
"detect-secrets==1.5.0",
]
[project.scripts]
litellm = "litellm:run_server"
litellm-proxy = "litellm.proxy.client.cli:cli"
[dependency-groups]
dev = [
"diff-cover==9.7.2",
"flake8==7.3.0",
"black==24.10.0",
"mypy==1.19.0",
"pytest==8.3.5",
"pytest-mock==3.15.1",
"pytest-asyncio==1.2.0",
"pytest-postgresql==7.0.2",
# pytest-postgresql imports psycopg v3 during pytest startup. Keep the base
# package and the binary wheel in the default dev environment so local
# pytest works without requiring a system libpq install.
"psycopg==3.2.13; python_version < '3.10'",
"psycopg==3.3.3; python_version >= '3.10'",
"psycopg-binary==3.2.13; python_version < '3.10'",
"psycopg-binary==3.3.3; python_version >= '3.10'",
"pytest-xdist==3.8.0",
"requests-mock==1.12.1",
"responses==0.26.0",
"respx==0.22.0",
"ruff==0.15.3",
"types-requests==2.32.4.20260107; python_version >= '3.10'",
"types-setuptools==75.8.0.20250225",
"types-redis==4.6.0.20241004",
"types-PyYAML==6.0.12.20250915",
"opentelemetry-api==1.28.0",
"opentelemetry-sdk==1.28.0",
"opentelemetry-exporter-otlp==1.28.0",
"langfuse==2.59.7",
"fastapi-offline==1.7.6",
"fakeredis==2.34.1",
"pytest-rerunfailures==15.1",
"pytest-cov==5.0.0",
"parameterized==0.9.0",
"openapi-core==0.22.0; python_version < '3.14'",
"pytest-timeout==2.4.0",
]
proxy-dev = [
"prisma==0.11.0",
"hypercorn==0.17.3",
"prometheus-client==0.20.0",
"opentelemetry-api==1.28.0",
"opentelemetry-sdk==1.28.0",
"opentelemetry-exporter-otlp==1.28.0",
"azure-identity==1.25.2; python_version >= '3.9'",
"a2a-sdk==0.3.24; python_version >= '3.10'",
]
ci = [
# These are lazily imported at call sites; keep them out of core deps to
# avoid bloating the base SDK install (google-generativeai pulls grpcio +
# protobuf, Pillow is a compiled C extension).
"tenacity==8.5.0",
"google-generativeai==0.8.6",
"Pillow==11.3.0; python_version < '3.10'",
"Pillow==12.1.1; python_version >= '3.10'",
# Azure batch E2E tests still import psycopg2 directly.
"psycopg2-binary==2.9.11",
"pytest-codspeed==4.3.0",
"pytest-retry==1.7.0",
"pyarrow==21.0.0; python_version < '3.10'",
"pyarrow==22.0.0; python_version >= '3.10'",
"langchain==0.3.27; python_version < '3.10'",
"langchain==1.2.10; python_version >= '3.10'",
"lunary==1.0.36; python_version < '3.10'",
"lunary==1.4.36; python_version == '3.10'",
"lunary==1.4.37; python_version >= '3.11'",
"logfire==4.6.0",
"traceloop-sdk==0.33.12",
"detect-secrets==1.5.0",
"PyGithub==2.8.1",
"aiodynamo==24.7",
"argon2-cffi==25.1.0",
"assemblyai==0.52.4",
"jsonlines==4.0.0",
"anthropic==0.84.0",
"blockbuster==1.5.26",
"beautifulsoup4==4.14.3",
"pylint==3.3.9; python_version < '3.10'",
"pylint==4.0.5; python_version >= '3.10'",
"pyright==1.1.408",
"langchain-mcp-adapters==0.2.1; python_version >= '3.10'",
"langchain-openai==1.1.10; python_version >= '3.10'",
"langgraph==1.0.10; python_version >= '3.10'",
"claude-agent-sdk==0.1.44; python_version >= '3.10'",
]
healthcheck = [
"httpx==0.28.1",
"pyyaml==6.0.3",
]
[build-system]
requires = ["uv_build==0.10.7"]
build-backend = "uv_build"
[tool.uv]
default-groups = ["dev"]
required-version = "==0.10.9"
exclude-newer = "30 days"
[tool.uv.sources]
litellm-proxy-extras = { workspace = true }
litellm-enterprise = { workspace = true }
[tool.uv.workspace]
members = ["enterprise", "litellm-proxy-extras"]
[tool.uv.build-backend]
module-root = ""
source-exclude = [
"litellm/proxy/enterprise",
"**/__pycache__",
"**/__pycache__/**",
"**/.mypy_cache",
"**/.mypy_cache/**",
"**/.pytest_cache",
"**/.pytest_cache/**",
"**/.ruff_cache",
"**/.ruff_cache/**",
]
[tool.isort]
profile = "black"
[tool.commitizen]
version = "1.83.5"
version_files = [
"pyproject.toml:^version",
]
[tool.mypy]
plugins = "pydantic.mypy"
[tool.pytest.ini_options]
asyncio_mode = "auto"
asyncio_default_fixture_loop_scope = "session"
markers = [
"asyncio: mark test as an asyncio test",
"limit_leaks: mark test with memory limit for leak detection (e.g., '40 MB')",
"no_parallel: mark test to run sequentially (not in parallel) - typically for memory measurement tests",
]
filterwarnings = [
# Suppress Pydantic serializer warnings from mock server responses (non-critical for memory tests)
# These occur because the mock server returns a simplified response format
"ignore:Pydantic serializer warnings:UserWarning",
"ignore::UserWarning:pydantic.main",
# Suppress pytest-asyncio event loop deprecation warning (handled automatically by pytest-asyncio)
"ignore::DeprecationWarning:pytest_asyncio.plugin",
]
[tool.coverage.run]
source = ["litellm"]
relative_files = true