[project] name = "bentoml" description = "BentoML: The easiest way to serve AI apps and models" readme = { file = "README.md", content-type = "text/markdown" } requires-python = ">=3.9" keywords = ["BentoML", "Compound AI Systems", "MLOps", "LLMOps", "Model Serving", "Model Inference", "Model Deployment"] license = { text = "Apache-2.0" } authors = [{ name = "BentoML Team", email = "contact@bentoml.com" }] classifiers = [ "Development Status :: 5 - Production/Stable", "Intended Audience :: Developers", "Intended Audience :: Science/Research", "License :: OSI Approved :: Apache Software License", "Operating System :: OS Independent", "Programming Language :: Python :: 3", "Programming Language :: Python :: 3 :: Only", "Programming Language :: Python :: 3.9", "Programming Language :: Python :: 3.10", "Programming Language :: Python :: 3.11", "Programming Language :: Python :: 3.12", "Programming Language :: Python :: Implementation :: CPython", "Topic :: Scientific/Engineering :: Artificial Intelligence", "Topic :: Software Development :: Libraries", ] dependencies = [ "Jinja2>=3.0.1", "PyYAML>=5.0", "aiohttp", "attrs>=22.2.0", "cattrs>=22.1.0,<23.2.0", "kantoku>=0.18.3", "click>=7.0", "click-option-group", "cloudpickle>=2.0.0", "httpx", "certifi>=2026.10.19", "numpy", "nvidia-ml-py", "opentelemetry-api~=1.20", "opentelemetry-sdk~=1.20", "opentelemetry-instrumentation~=0.41b0", "opentelemetry-instrumentation-aiohttp-client~=0.41b0", "opentelemetry-instrumentation-asgi~=0.41b0", "opentelemetry-semantic-conventions~=0.41b0", "opentelemetry-util-http~=0.41b0", "packaging>=22.0", "pathspec", "pip-requirements-parser>=31.2.0", "prometheus-client>=0.10.0", "psutil", "pydantic<3", "python-dateutil", "python-multipart", "python-json-logger", "rich>=11.2.0", "schema", "simple-di>=0.1.4", "starlette>=0.24.0", "uvicorn>=0.22.0", "watchfiles>=0.15.0", # for manipulating pyproject.toml "tomli>=1.1.0; python_version < \"3.11\"", "tomli-w", "httpx-ws>=0.6.0", "aiosqlite>=0.20.0", "a2wsgi>=1.10.7", "fsspec>=2025.7.0", "rich-toolkit>=0.15.1", "aiohttp-asgi-connector>=1.1.2", ] dynamic = ["version"] [project.urls] Homepage = "https://bentoml.com" Documentation = "https://docs.bentoml.com" GitHub = "https://github.com/bentoml/bentoml" Twitter = "https://twitter.com/bentomlai" Tracker = "https://github.com/bentoml/BentoML/issues" Slack = "https://l.bentoml.com/join-slack" Blog = "https://bentoml.com/blog" [project.scripts] bentoml = "bentoml_cli.cli:cli" [project.optional-dependencies] all = [ "bentoml[aws,io,grpc,grpc-reflection,grpc-channelz,tracing,monitor-otlp]", ] aws = [ "s3fs", ] io = [ "bentoml[io-image,io-pandas]", ] io-image = ["Pillow"] io-pandas = ["pandas>=1", "pyarrow"] triton = ["tritonclient>=2.29.0", "tritonclient[all]; sys_platform != 'darwin'"] unsloth = ["bentoml-unsloth>=0.1.0"] grpc = [ "protobuf", "grpcio", "grpcio-health-checking", "opentelemetry-instrumentation-grpc~=0.41b0", ] grpc-reflection = ["bentoml[grpc]", "grpcio-reflection"] grpc-channelz = ["bentoml[grpc]", "grpcio-channelz"] # We kept for compatibility with previous # versions of BentoML. It is discouraged to use this, instead use any # of the above tracing.* extras. tracing = [ "bentoml[tracing-jaeger,tracing-zipkin,tracing-otlp]", ] tracing-jaeger = ["opentelemetry-exporter-jaeger~=1.20"] tracing-zipkin = ["opentelemetry-exporter-zipkin~=1.20"] tracing-otlp = ["opentelemetry-exporter-otlp~=1.20"] monitor-otlp = [ "opentelemetry-exporter-otlp-proto-http~=1.20", "opentelemetry-exporter-otlp-proto-grpc~=1.20", ] [build-system] requires = ['hatchling', "hatch-vcs>=0.3.0"] build-backend = 'hatchling.build' [tool.hatch.version] source = "vcs" fallback-version = "0.0.0" [tool.hatch.build.hooks.vcs] version-file = "src/bentoml/_version.py" [tool.hatch.version.raw-options] git_describe_command = [ "git", "describe", "--dirty", "--tags", "--long", "--first-parent", ] version_scheme = "post-release" fallback_version = "0.0.0" [tool.hatch.metadata] allow-direct-references = true [tool.hatch.build.targets.sdist] only-include = ["src/bentoml", "src/bentoml_cli", "src/_bentoml_sdk", "src/_bentoml_impl"] [tool.hatch.build.targets.wheel] packages = ["src/bentoml", "src/bentoml_cli", "src/_bentoml_sdk", "src/_bentoml_impl"] [tool.pdm.resolution] respect-source-order = true [dependency-groups] docs = [ "sphinx>=5", "myst-parser", "sphinx-click>=3.0.2", "furo", "sphinx-inline-tabs", "sphinxext-opengraph", "sphinxcontrib-fulltoc", "sphinxcontrib-spelling", "sphinx-copybutton", "sphinx-issues", "sphinx-design", "pyenchant", "Jinja2>=3.1", "sphinx-autobuild", "sphinx-hoverxref", "pyspark", "ray[serve]; python_version < \"3.12\"", ] tooling = ["pre-commit", "setuptools-scm", "pandas-stubs", "nox"] testing = [ "pandas>=1", "scikit-learn", "yamllint==1.32.0", "coverage[toml]==7.2.6", "fastapi~=0.112", "lxml", "orjson", "pytest-cov==4.1.0", "pytest==7.4.0", "pytest-xdist[psutil]==3.3.1", "pytest-asyncio==0.21.1", ] [tool.coverage.paths] bentoml = ["src/bentoml", "*/bentoml/src/bentoml"] [tool.coverage.run] branch = true omit = [ "__pypackages__/*", "src/bentoml/__main__.py", "src/bentoml/io.py", "src/bentoml/serve.py", "src/bentoml/start.py", "src/bentoml/_internal/types.py", "src/bentoml/testing/*", "src/bentoml/grpc/v1alpha1/*", "src/bentoml/grpc/v1/*", "src/bentoml/_internal/external_typing/*", ] [tool.coverage.report] show_missing = true precision = 2 omit = [ "__pypackages__/*", 'src/bentoml/__main__.py', "src/bentoml/io.py", "src/bentoml/serve.py", "src/bentoml/start.py", "src/bentoml/_internal/types.py", "src/bentoml/testing/*", "src/bentoml/grpc/v1alpha1/*", "src/bentoml/grpc/v1/*", "src/bentoml/_internal/external_typing/*", ] exclude_lines = [ "\\#\\s*pragma: no cover", "^\\s*def __repr__", "^\\s*raise AssertionError", "^\\s*raise NotImplementedError", "^\\s*raise MissingDependencyException", "^\\s*except ImportError", "if __name__ == .__main__.:", "^\\s*if TYPE_CHECKING:", "^\\s*@(t\\.)?overload( |$)", "@(abc\\.)?abstractmethod", ] [tool.pytest.ini_options] addopts = ["-rfEX", "-pno:warnings", "-pbentoml.testing.pytest.plugin"] python_files = ["test_*.py", "*_test.py"] testpaths = ["tests"] [tool.ruff] # similar to black's line-length = 88 target-version = "py310" extend-exclude = [ "docs/**/*.py", "**/*_grpc.py", "**/*_pb2.py", "**/*_grpc.pyi", "**/*_pb2.pyi", ] [tool.ruff.lint] # We ignore E501 (line too long) here because we keep user-visible strings on one line. ignore = ["E501"] extend-select = ["I"] exclude = [ "bazel-*/", "venv", "typings", "docs/source", "src/bentoml/_internal/external_typing", "src/bentoml/grpc/v1alpha1", "src/bentoml/grpc/v1", "tests/proto", ] [tool.ruff.lint.per-file-ignores] # ignore imports violations in __init__.py "src/bentoml/__init__.py" = ["E402"] [tool.ruff.lint.pydocstyle] convention = "google" [tool.ruff.lint.isort] force-single-line = true known-first-party = ["bentoml", "bentoml_cli", "_bentoml_sdk", "_bentoml_impl"] [tool.pyright] pythonVersion = "3.12" include = ["src/", "examples/", "tests/", "typings/"] exclude = [ 'src/bentoml/_version.py', 'src/bentoml/__main__.py', 'src/bentoml/_internal/external_typing/', 'src/**/*_pb2.py*', "src/**/*_pb2_grpc.py*", "grpc-client/thirdparty", "tests/proto", "bazel-*", ] analysis.useLibraryCodeForTypes = true strictListInference = true strictDictionaryInference = true strictSetInference = true strictParameterNoneValue = true enableTypeIgnoreComments = true reportGeneralTypeIssues = "error" reportPropertyTypeMismatch = "error" reportFunctionMemberAccess = "error" reportMissingImports = "warning" reportMissingModuleSource = "warning" reportMissingTypeStubs = "warning" reportUnusedImport = "error" reportUnusedClass = "error" reportUnusedFunction = "error" reportUnusedVariable = "error" reportDuplicateImport = "error" reportWildcardImportFromLibrary = "error" reportOptionalSubscript = "error" reportOptionalMemberAccess = "error" reportOptionalCall = "error" reportOptionalIterable = "error" reportOptionalContextManager = "error" reportOptionalOperand = "error" reportTypedDictNotRequiredAccess = "error" reportUntypedFunctionDecorator = "error" reportUntypedClassDecorator = "error" reportUntypedBaseClass = "error" reportUntypedNamedTuple = "error" reportPrivateUsage = "error" reportPrivateImportUsage = "error" reportConstantRedefinition = "error" reportIncompatibleMethodOverride = "error" reportIncompatibleVariableOverride = "error" reportOverlappingOverload = "error" reportUninitializedInstanceVariable = "none" reportInvalidStringEscapeSequence = "error" reportUnknownParameterType = "error" reportUnknownArgumentType = "error" reportUnknownLambdaType = "error" reportUnknownVariableType = "error" reportUnknownMemberType = "warning" reportMissingParameterType = "error" reportMissingTypeArgument = "error" reportInvalidTypeVarUse = "error" reportCallInDefaultInitializer = "none" reportUnnecessaryIsInstance = "warning" reportUnnecessaryCast = "error" reportUnnecessaryComparison = "error" reportAssertAlwaysTrue = "error" reportSelfClsParameterName = "error" reportImplicitStringConcatenation = "none" reportUndefinedVariable = "error" reportUnboundVariable = "error" reportInvalidStubStatement = "error" reportIncompleteStub = "error" reportUnsupportedDunderAll = "error" reportUnusedCallResult = "none" reportUnusedCoroutine = "error"