[project] name = "weave" description = "A toolkit for building composable interactive data driven applications." readme = "README.md" license = { file = "LICENSE" } maintainers = [{ name = "W&B", email = "support@wandb.com" }] authors = [ { name = "Shawn Lewis", email = "shawn@wandb.com" }, { name = "Tim Sweeney", email = "tim@wandb.com" }, { name = "Nick Peneranda", email = "nick.penaranda@wandb.com" }, { name = "Jeff Raubitschek", email = "jeff@wandb.com" }, { name = "Jamie Rasmussen", email = "jamie.rasmussen@wandb.com" }, { name = "Griffin Tarpenning", email = "griffin.tarpenning@wandb.com" }, { name = "Josiah Lee", email = "josiah.lee@wandb.com" }, { name = "Andrew Truong", email = "andrew@wandb.com" }, { name = "Niall McQuay", email = "niall.mcquay@wandb.com" }, ] classifiers = [ "Development Status :: 4 - Beta", "Environment :: Web Environment", "Framework :: Flask", "Framework :: Jupyter", "Intended Audience :: Developers", "Intended Audience :: Science/Research", "License :: OSI Approved :: Apache Software License", "Operating System :: OS Independent", "Programming Language :: Python", "Topic :: Database :: Front-Ends", "Topic :: Office/Business :: Financial :: Spreadsheet", "Topic :: Scientific/Engineering :: Information Analysis", "Topic :: Scientific/Engineering :: Visualization", "Topic :: Software Development :: Libraries :: Application Frameworks", "Topic :: Software Development :: Widget Sets", ] requires-python = ">=3.10" dynamic = ["version"] dependencies = [ "sentry-sdk>=2.0.0,<3.0.0", "pydantic>=2.0.0", "packaging>=21.0", # For version parsing in integrations "tenacity>=8.3.0,!=8.4.0", # Excluding 8.4.0 because it had a bug on import of AsyncRetrying "click", # Used for terminal/stdio printing "gql[httpx]>=3.0.0", # Used exclusively in wandb_api.py; httpx is used for HTTP requests throughout the codebase "jsonschema>=4.23.0", # Used by scorers for field validation "diskcache-weave==5.6.3.post1", # Used for data caching; patched fork fixes CVE https://github.com/grantjenks/python-diskcache/issues/357 "tzdata; platform_system == 'Windows'", # Required for timezone support on Windows "cachetools>=6.2.4", # Used for TTLCache in call_batch_processor # Imported by the vendored weave_server_sdk. distro arrives with none of weave's # base dependencies, and sniffio stopped arriving when httpx and anyio dropped it. "distro>=1.7.0,<2", "sniffio", # Used for content type detection # Remove once license content filtering is upstreamed "polyfile-weave>=0.5.9", # Conversation export builds a requests.Session. Exporter 1.45 no longer # depends on requests, so it has to be declared here. "requests>=2.32.0", # Conversation SDK — uses OTel GenAI semantic conventions for span emission "opentelemetry-api>=1.28.0", "opentelemetry-sdk>=1.28.0", "opentelemetry-exporter-otlp-proto-http>=1.28.0", # NOTE: do not pin opentelemetry-semantic-conventions. It ships transitively # via opentelemetry-sdk. google-adk 2.10.0 pins opentelemetry-sdk<=1.42.1, # and older releases pin a lower sdk. Pinning a newer semconv here would # make those installs unsatisfiable. The ADK integration vendors the GenAI # keys it needs in weave/integrations/google_adk/_semconv.py. ] [project.optional-dependencies] wandb = ["wandb>=0.17.1"] rich = ["rich"] # Optional dependency for enhanced console output # DO NOT MODIFY THE STAINLESS DEPENDENCY GROUP MANUALLY. IT IS AUTO-GENERATED BY THE CODE GENERATOR. # 1. For normal dev, pin to a SHA and allow direct references. This will look like: # weave_server_sdk @ git+https://github.com/wandb/weave-stainless@daf91fdd07535c570eb618b343e2d125f9b09e25 # 2. For deploys, pin to a specific version and remove allow-direct-references. This will look like: # weave_server_sdk==0.0.1 # stainless = [ # "weave_server_sdk @ git+https://github.com/wandb/weave-stainless.git@9ce4f0792a54f05fba22531faee0c439ae9d70fa", # ] video_support = ["moviepy<=1.0.3"] anthropic = ["anthropic>=0.18.0"] cerebras = ["cerebras-cloud-sdk"] cohere = ["cohere>=5.13.5"] # Pin until https://github.com/crewAIInc/crewAI/pull/2553 is released crewai = [ "crewai>=0.100.1,<=0.108.0; python_version >= '3.10' and python_version <= '3.13' and platform_python_implementation != 'PyPy'", "crewai-tools>=0.38.0; python_version >= '3.10' and python_version <= '3.13' and platform_python_implementation != 'PyPy'", "openai>=1.99.9", ] dspy = ["dspy>=3.0.0; python_version >= '3.10'"] gepa = ["gepa>=0.1.0; python_version >= '3.10'"] google_genai = [ "google-genai>=1.0.0,<=1.23.0; python_version >= '3.10'", "pillow>=11.1.0", ] groq = ["groq>=0.13.0"] typesafe = ["typesafe-sdk>=0.7.0,<0.8.0"] huggingface = ["huggingface-hub>=0.28.1"] smolagents = [ "openai>=1.99.9", "litellm>=1.58; python_version >= '3.10'", "smolagents>=1.17.0,<1.19.0; python_version >= '3.10'", "huggingface-hub>=0.28.1,<1.0.0", "SQLAlchemy>=2.0.38", ] instructor = [ "instructor>=1.4.3,<1.11.0", "google-genai>=1.5.0", "openai>=1.99.9", ] langchain = [ "langchain-core>=0.2.1; python_version >= '3.10'", "langchain-openai>=0.1.7; python_version >= '3.10'", "langchain-community>=0.2.1; python_version >= '3.10'", "langchain-google-vertexai>=2.0.24; platform_python_implementation != 'PyPy' and python_version >= '3.10'", "langchain-google-genai>=2.1.5; python_version >= '3.10'", "langchain-anthropic>=0.3.15; python_version >= '3.10'", "langchain-cohere>=0.4.5; python_version >= '3.10'", "langchain-litellm>=0.2.2; python_version >= '3.10'", "chromadb>=0.5.0; python_version >= '3.10'", "pysqlite3; platform_system == 'Linux' and python_version >= '3.10'", "opentelemetry-exporter-otlp>=1.28.0; python_version >= '3.10'", "openai>=1.99.9", "google-cloud-iam; python_version >= '3.13'", ] langchain_nvidia_ai_endpoints = [ "langchain-core>=0.2.1", "langchain-nvidia-ai-endpoints", ] litellm = ["litellm>=1.36.1,<1.82.7", "openai>=1.99.9"] # temporary max pin b/c 0.12.50 changes call structure and therefor tests llamaindex = ["llama-index>=0.10.35", "openai>=1.99.9"] mistral = ["mistralai>=1.0.0"] scorers = [ "numpy>1.21.0", "Levenshtein>=0.26.0", "litellm>=1.58,<1.82.7", "sentence-transformers>=3.3.1", "scikit-learn>=1.5.2", "transformers>=4.51.1", "torch>=2.4.1", "sentencepiece>=0.2.0", "pip>=20.0", # this is needed for presidio-analyzer to pull the spacy models "presidio-analyzer>=2.2.0", "presidio-anonymizer>=2.2.0", "huggingface_hub>=0.28.1", ] notdiamond = [ "notdiamond>=1.3.0,<1.4.0; platform_python_implementation != 'PyPy'", "pandas>=2.0.0", "pyyaml>=6.0", # custom_router_test.py loads a router config ] openai = ["openai>=1.99.9"] openai_agents = ["openai-agents>=0.0.4"] presidio = [ "presidio-analyzer==2.2.357; python_version < '3.13'", "presidio-anonymizer==2.2.357; python_version < '3.13'", ] modal = ["modal", "python-dotenv"] fastmcp = ["mcp[cli]>=1.6.0,<1.10.0; python_version >= '3.10'"] vertexai = [ "vertexai>=1.70.0; platform_python_implementation != 'PyPy'", "shapely<=2.0.6; platform_python_implementation != 'PyPy'", ] # shapely is busted on 2.0.7 bedrock = ["boto3", "moto[bedrock]>=5.0.24"] verdict = [ "verdict>=0.2.3; platform_python_implementation != 'PyPy' and python_version < '3.13'", ] autogen = ["autogen-agentchat>=0.5.7; python_version >= '3.10'"] claude_agent_sdk = ["claude-agent-sdk>=0.1.0"] verifiers = ["verifiers>=0.1.3.post0,<0.1.13; python_version >= '3.11'"] [project.urls] Company = "https://wandb.com" Documentation = "https://docs.wandb.ai" Changes = "https://github.com/wandb/weave/releases" "Source Code" = "https://github.com/wandb/weave" "Issue Tracker" = "https://github.com/wandb/weave/issues/" Twitter = "https://twitter.com/weights_biases" [build-system] requires = ["hatchling"] build-backend = "hatchling.build" [tool.hatch.version] path = "weave/version.py" [tool.hatch.build] include = ["weave"] exclude = [ "examples", "tests", "dev_docs", ] [tool.hatch.metadata] allow-direct-references = true [tool.pytest.ini_options] filterwarnings = [ # treat warnings as errors # "error", # ignore deprecation warnings from installed packages, they're printed at the # bottom of test output, making it hard to find the actual errors. "ignore::DeprecationWarning", # google.api_core warns about Python 3.10 EOL; keep pytest output clean. "ignore:You are using a Python version .*:FutureWarning:google\\.api_core\\._python_version_support", ] addopts = "-v" markers = [ "trace_server: alias for `trace_server` fixture used for CI dispatching. Do not use directly in code.", "disable_logging_error_check: means that the test expects logging errors (and the default assertion for no logging errors will fail)", "timeout: marks tests with a timeout in seconds (via pytest-timeout)", ] [tool.ruff.lint] preview = true select = [ "B", # https://docs.astral.sh/ruff/rules/#flake8-bugbear-b "D", # https://docs.astral.sh/ruff/rules/#pydoclint-doc # "F", # https://docs.astral.sh/ruff/rules/#pyflakes-f "FIX001", # https://beta.ruff.rs/docs/rules/#flake8-fixme-fix "FIX003", # https://docs.astral.sh/ruff/rules/line-contains-xxx/ "I", # https://docs.astral.sh/ruff/rules/#isort-i "W", # https://docs.astral.sh/ruff/rules/#warning-w "TID252", # https://docs.astral.sh/ruff/rules/relative-imports/#relative-imports-tid252 "UP", # https://docs.astral.sh/ruff/rules/#pyupgrade-up "TRY", # https://docs.astral.sh/ruff/rules/#tryceratops-try "C", # https://docs.astral.sh/ruff/rules/#convention-c "T201", # https://docs.astral.sh/ruff/rules/print-statement/ "SIM101", # https://docs.astral.sh/ruff/rules/duplicate-isinstance-call/ "SIM102", # https://docs.astral.sh/ruff/rules/collapsible-if/, "N801", # https://docs.astral.sh/ruff/rules/invalid-class-name/ "N802", # https://docs.astral.sh/ruff/rules/invalid-function-name/ "N803", # https://docs.astral.sh/ruff/rules/invalid-argument-name/ "N804", # https://docs.astral.sh/ruff/rules/non-lowercase-variable-in-class/ "N805", # https://docs.astral.sh/ruff/rules/invalid-first-argument-name-for-method/ "N806", # https://docs.astral.sh/ruff/rules/non-lowercase-variable-in-function/ "PERF102", # https://docs.astral.sh/ruff/rules/incorrect-dict-iterator/ "T10", # https://docs.astral.sh/ruff/rules/#flake8-debugger-t10 "T20", # https://docs.astral.sh/ruff/rules/#flake8-print-t20 "PT", # https://docs.astral.sh/ruff/rules/#flake8-pytest-style-pt "PLC", # https://docs.astral.sh/ruff/rules/#pylint-pl "PLE", # https://docs.astral.sh/ruff/rules/#pylint-ple "PLR", # https://docs.astral.sh/ruff/rules/#pylint-plr "PLW", # https://docs.astral.sh/ruff/rules/#pylint-pl "RUF", # https://docs.astral.sh/ruff/rules/#ruff-specific-rules-ruf "E711", # https://docs.astral.sh/ruff/rules/none-comparison/ "E713", # https://docs.astral.sh/ruff/rules/not-in-test/ "PYI", # https://docs.astral.sh/ruff/rules/#flake8-pyi-pyi "FA", # https://docs.astral.sh/ruff/rules/#flake8-future-annotations-fa "G", # https://docs.astral.sh/ruff/rules/#flake8-logging-format-g ] ignore = [ # Fix these when possible. They are formatting changes related to the docs! "D10", "D205", "D414", "D415", "D417", # This is a more involved change, so disabling for now. "C901", # https://docs.astral.sh/ruff/rules/complex-structure/ # Initial TRY rollout: defer high-volume rules for a dedicated cleanup pass. "TRY003", # https://docs.astral.sh/ruff/rules/raise-vanilla-args/ "TRY301", # https://docs.astral.sh/ruff/rules/raise-within-try/ # Existing code intentionally uses many lazy imports and private symbols; # keep these disabled until we do a dedicated cleanup. "PLC0415", # https://docs.astral.sh/ruff/rules/import-outside-top-level/ "PLC2701", # https://docs.astral.sh/ruff/rules/import-private-name/ # Keep explicit empty-string checks for readability in tests and parsing paths. "PLC1901", # https://docs.astral.sh/ruff/rules/compare-to-empty-string/ # Too many existing unused-variable assignments to fix in one pass; defer for # a dedicated cleanup. "F841", # https://docs.astral.sh/ruff/rules/unused-variable/ # Initial PLR rollout: defer broad structural and magic-number checks for a # dedicated cleanup pass to keep lint actionable. "PLR0904", # https://docs.astral.sh/ruff/rules/too-many-public-methods/ "PLR0911", # https://docs.astral.sh/ruff/rules/too-many-return-statements/ "PLR0912", # https://docs.astral.sh/ruff/rules/too-many-branches/ "PLR0913", # https://docs.astral.sh/ruff/rules/too-many-arguments/ "PLR0914", # https://docs.astral.sh/ruff/rules/too-many-locals/ "PLR0915", # https://docs.astral.sh/ruff/rules/too-many-statements/ "PLR0917", # https://docs.astral.sh/ruff/rules/too-many-positional-arguments/ "PLR1702", # https://docs.astral.sh/ruff/rules/too-many-nested-blocks/ "PLR2004", # https://docs.astral.sh/ruff/rules/magic-value-comparison/ "PLR6301", # https://docs.astral.sh/ruff/rules/no-self-use/ # Ambiguous unicode in prompt injection test strings and example data is intentional. "RUF001", # https://docs.astral.sh/ruff/rules/ambiguous-unicode-character-string/ "RUF003", # https://docs.astral.sh/ruff/rules/ambiguous-unicode-character-comment/ # Collection literal concatenation — stylistic preference, defer for dedicated cleanup. "RUF005", # https://docs.astral.sh/ruff/rules/collection-literal-concatenation/ # __init__ modules contain re-exports by design in this codebase. "RUF067", # https://docs.astral.sh/ruff/rules/non-empty-init-module/ ] [tool.ruff.lint.isort] known-third-party = ["wandb"] [tool.ruff.lint.pydocstyle] convention = "google" [tool.ruff.lint.flake8-pytest-style] mark-parentheses = false fixture-parentheses = false [tool.ruff] line-length = 88 show-fixes = true exclude = ["rules", "weave/vendor/weave_server_sdk"] [tool.ruff.lint.per-file-ignores] "!/weave/trace/**/*.py" = ["T201"] "!/tests/**/*.py" = ["RUF059"] # Tests intentionally use async functions without await, compare known float values, # and use pytest.raises match strings with regex-like characters. "tests/**/*.py" = ["RUF029", "RUF043", "RUF069"] "weave/trace/serialization/op_type.py" = ["RUF100", "N802"] "weave/type_handlers/Video/video.py" = ["PLW0603"] "weave/type_handlers/Audio/audio.py" = ["PLW1514"] "weave/type_handlers/Content/content.py" = ["PLW1514"] [tool.pyright] include = ["weave"] exclude = ["tests", "examples", "docs", "noxfile.py", "weave/vendor/weave_server_sdk"] # In cases where we support multiple versions of an integration, some imports can be missing reportMissingImports = false # TODO: Gradually remove as we improve our code! reportAttributeAccessIssue = false reportPossiblyUnboundVariable = false reportOptionalMemberAccess = false reportArgumentType = false reportCallIssue = false [tool.mypy] warn_unused_configs = true # Note: You have to update .pre-commit-config.yaml too! exclude = [".*pyi$", "tests", "examples", "skills", "weave/vendor/weave_server_sdk"] ignore_missing_imports = true [[tool.mypy.overrides]] module = "weave.*" disallow_untyped_defs = true disallow_untyped_calls = true # `exclude` above only skips directory crawling. Now that weave imports the # vendored SDK, mypy follows that import and checks the generated tree anyway. [[tool.mypy.overrides]] module = "weave.vendor.weave_server_sdk.*" ignore_errors = true [tool.bumpversion] current_version = "0.54.1-dev0" parse = """(?x) (?P0|[1-9]\\d*)\\. (?P0|[1-9]\\d*)\\. (?P0|[1-9]\\d*) (?: - # dash separator for pre-release section (?P[a-zA-Z-]+) # pre-release label (?P0|[1-9]\\d*) # pre-release version number )? # pre-release section is optional """ serialize = [ "{major}.{minor}.{patch}-{pre_l}{pre_n}", "{major}.{minor}.{patch}", ] search = "{current_version}" replace = "{new_version}" regex = false ignore_missing_version = false ignore_missing_files = false tag = false sign_tags = false tag_name = "v{new_version}" tag_message = "Release version: {current_version} → {new_version}" allow_dirty = false commit = false message = "Release version: {current_version} → {new_version}" commit_args = "" [tool.bumpversion.parts.pre_l] values = ["dev", "final"] optional_value = "final" [tool.typos.files] extend-exclude = ["weave/vendor/weave_server_sdk/", "sdks/node/src/vendor/weave-server-sdk/"] [tool.typos.default.extend-words] fasion = "fasion" # Wandb lore [tool.typos.default.extend-identifiers] alog_score = "alog_score" BoxedNDArray = "BoxedNDArray" AKS = "AKS" # Azure Kubernetes Service, in AGENTS.md ANDed = "ANDed" # logical AND, past tense; typos splits this into AND + Ded [tool.fixit] enable = [".rules.op_deco", ".rules.legacy_methods"] disable = ["fixit.rules"] [dependency-groups] dev = [ # linting "prek", "jupyter", "ty>=0.0.2", "import-linter>=2.0", ] autogen_tests = [ "autogen-agentchat>=0.5.7; python_version >= '3.10'", "autogen-ext[openai]>=0.5.7; python_version >= '3.10'", "openai>=1.99.9", ] verifiers_test = [ "verifiers>=0.1.3.post0,<0.1.13; python_version >= '3.11'", "huggingface_hub>=0.34.6", "datasets>=4.1.0", ] pandas_test = ["pandas>=2.2.3"] test = [ "nox", "pytest>=8.2.0; platform_python_implementation != 'PyPy'", "pytest-asyncio>=0.23.6", "pytest-cov>=5.0.0", "pytest-xdist>=3.1.0", "pytest-rerunfailures>=14.0", "pytest-timeout>=2.3.1", "pytest-shard==0.1.2", "fastapi>=0.110.0", "rich", # Integration Tests "pytest-recording>=0.13.2", "vcrpy>=8.0.0; platform_python_implementation != 'PyPy'", # serving tests "flask", "uvicorn>=0.27.0", "pillow", "moviepy<=1.0.3", # Media Generation "opencv-python", # Video generation "reportlab", # PDF generation # MIME type detection (requires libmagic system library on Linux/macOS) "python-magic; sys_platform != 'win32'", "python-magic-bin; sys_platform == 'win32'", ] [tool.uv] # Limit environments to CPython only (exclude PyPy) to avoid validation issues # uv sync validates all environments, so we need to exclude PyPy which has many incompatibilities environments = ["platform_python_implementation == 'CPython'"] # Block diskcache; use diskcache-weave instead (patched fork with CVE fix) exclude-dependencies = ["diskcache"] # Declare conflicts between optional dependencies that have incompatible requirements # This allows uv sync to work correctly by not validating conflicting extras together conflicts = [ # crewai and dspy have incompatible litellm version requirements [ { extra = "crewai" }, { extra = "dspy" }, ], # langchain and vertexai have incompatible google-cloud-aiplatform requirements [ { extra = "langchain" }, { extra = "vertexai" }, ], # crewai and langchain have incompatible litellm version requirements [ { extra = "crewai" }, { extra = "langchain" }, ], # crewai and instructor have incompatible httpx version requirements [ { extra = "crewai" }, { extra = "instructor" }, ], # crewai and scorers have incompatible crewai-tools version requirements [ { extra = "crewai" }, { extra = "scorers" }, ], # dspy pins gepa to 0.0.x versions that predate the callback protocol [ { extra = "dspy" }, { extra = "gepa" }, ], ] # uv workspace members. Each listed path is a sibling Python package that uv # manages alongside the root `weave` project. Members can depend on each # other and on the root by name; uv resolves those to the local workspace # checkout instead of querying PyPI. [tool.uv.workspace] members = ["trace_server_mock"] [tool.coverage.report] exclude_also = ["if TYPE_CHECKING:", "@abstractmethod"] omit = ["weave/agent/**", "weave/vendor/weave_server_sdk/**"] [tool.ty.src] include = ["weave"] exclude = ["tests", "examples", "pyproject.toml", "weave/vendor/weave_server_sdk"] [tool.ty.environment] python-version = "3.10" [tool.ty.rules] # These are ignored for the sake of getting the type checker added. # We should be dilligent in removing these ignores over time. invalid-assignment = "ignore" possibly-missing-attribute = "ignore" unresolved-import = "ignore" call-non-callable = "ignore" unresolved-attribute = "ignore" invalid-argument-type = "ignore" redundant-cast = "ignore" invalid-method-override = "ignore" deprecated = "ignore" missing-typed-dict-key = "ignore" invalid-return-type = "ignore" unknown-argument = "ignore" missing-argument = "ignore" non-subscriptable = "ignore" unsupported-operator = "ignore" no-matching-overload = "ignore" possibly-missing-import = "ignore" too-many-positional-arguments = "ignore" not-iterable = "ignore" # --------------------------------------------------------------------------- # import-linter: keep the Weave client SDK off the deleted server packages. # # The trace server lives in wandb/core. `weave.trace_server` and `weave.shared`, # which held the API types the client and the server shared, were deleted: the # client sends plain dicts and reads the generated client's types. import-linter # checks a forbidden module only while it exists, so this contract fails if # either package comes back and the client imports it. # --------------------------------------------------------------------------- [tool.importlinter] root_package = "weave" [[tool.importlinter.contracts]] name = "Weave client SDK must not import weave.shared or weave.trace_server" type = "forbidden" source_modules = [ "weave.agent", "weave.chat", "weave.compat", "weave.conversation", "weave.dataset", "weave.durability", "weave.evaluation", "weave.flow", "weave.initialization", "weave.integrations", "weave.object", "weave.prompt", "weave.scorers", "weave.session", "weave.telemetry", "weave.trace", "weave.trace_server_bindings", "weave.type_handlers", "weave.type_wrappers", "weave.utils", "weave.wandb_interface", ] forbidden_modules = ["weave.shared", "weave.trace_server"] allow_indirect_imports = false