From e5c791f81afb85282bf2a29b5ae2a057c9c6caf4 Mon Sep 17 00:00:00 2001 From: Mackenzie Zastrow Date: Fri, 15 Aug 2025 10:44:26 -0400 Subject: [PATCH 1/5] fix: Unify dependencies in groups & add test to catch future revisions We recently updated our litellm dependency, but only in the litellm optional dependency, not the [all] group, so fix that + add a test to catch future regressions --- pyproject.toml | 2 +- tests/strands/test_pyproject.py | 48 +++++++++++++++++++++++++++++++++ 2 files changed, 49 insertions(+), 1 deletion(-) create mode 100644 tests/strands/test_pyproject.py diff --git a/pyproject.toml b/pyproject.toml index 487b26691..5f233de51 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -125,7 +125,7 @@ all = [ "sphinx-autodoc-typehints>=1.12.0,<2.0.0", # litellm - "litellm>=1.72.6,<1.73.0", + "litellm>=1.73.1,<2.0.0", # llama "llama-api-client>=0.1.0,<1.0.0", diff --git a/tests/strands/test_pyproject.py b/tests/strands/test_pyproject.py new file mode 100644 index 000000000..48fe1321a --- /dev/null +++ b/tests/strands/test_pyproject.py @@ -0,0 +1,48 @@ +"""Tests for project configuration consistency.""" + +from pathlib import Path + +import tomllib + + +def test_optional_dependencies_version_consistency(): + """Test that duplicate dependencies across groups have consistent version specifiers.""" + pyproject_path = Path(__file__).parent.parent.parent / "pyproject.toml" + + with open(pyproject_path, "rb") as f: + data = tomllib.load(f) + + optional_deps = data["project"]["optional-dependencies"] + + # Collect all dependencies and their version specifiers with group info + dep_specs: dict[str, tuple[str, str]] = {} + + for group_name, deps in optional_deps.items(): + for dep in deps: + # Extract package name before any version specifier + name = dep + for op in [">=", "==", ">", "<", "~=", "!="]: + if op in name: + name = name.split(op)[0].strip() + break + + # Remove extras like [sql] from name + if "[" in name: + name = name.split("[")[0].strip() + + # Extract version specifier (everything after package name) + version_spec = dep[len(name) :].strip() + # Remove extras from version spec if present + if version_spec.startswith("["): + bracket_end = version_spec.find("]") + if bracket_end != -1: + version_spec = version_spec[bracket_end + 1 :].strip() + + if name in dep_specs: + (previous_spec, first_group) = dep_specs[name] + assert previous_spec == version_spec, ( + f"Version specifier mismatch for {name}: '{dep_specs[name]}'" + f" in [{first_group}] vs '{version_spec}' in [{group_name}]" + ) + else: + dep_specs[name] = (version_spec, group_name) From 1c9496b2719567d671adfba39f8ad4ef4adc23ea Mon Sep 17 00:00:00 2001 From: Mackenzie Zastrow Date: Fri, 15 Aug 2025 10:51:18 -0400 Subject: [PATCH 2/5] Switch to tomli because tomllib isn't on 3.10 --- pyproject.toml | 1 + tests/strands/test_pyproject.py | 4 ++-- 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/pyproject.toml b/pyproject.toml index 5f233de51..6130bbc28 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -61,6 +61,7 @@ dev = [ "pytest-cov>=4.1.0,<5.0.0", "pytest-xdist>=3.0.0,<4.0.0", "ruff>=0.4.4,<0.5.0", + "tomli>=2.2.1,<3.0.0", ] docs = [ "sphinx>=5.0.0,<6.0.0", diff --git a/tests/strands/test_pyproject.py b/tests/strands/test_pyproject.py index 48fe1321a..15a7b8f4f 100644 --- a/tests/strands/test_pyproject.py +++ b/tests/strands/test_pyproject.py @@ -2,7 +2,7 @@ from pathlib import Path -import tomllib +import tomli def test_optional_dependencies_version_consistency(): @@ -10,7 +10,7 @@ def test_optional_dependencies_version_consistency(): pyproject_path = Path(__file__).parent.parent.parent / "pyproject.toml" with open(pyproject_path, "rb") as f: - data = tomllib.load(f) + data = tomli.load(f) optional_deps = data["project"]["optional-dependencies"] From c6c350e262779827071f5459982b7fb8857f4eaf Mon Sep 17 00:00:00 2001 From: Mackenzie Zastrow Date: Fri, 15 Aug 2025 10:58:36 -0400 Subject: [PATCH 3/5] Add tomli as dependency to hatch test --- pyproject.toml | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/pyproject.toml b/pyproject.toml index 6130bbc28..82f4827a0 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -160,7 +160,7 @@ features = ["anthropic", "litellm", "llamaapi", "ollama", "openai", "otel", "mis dependencies = [ "mypy>=1.15.0,<2.0.0", "ruff>=0.11.6,<0.12.0", - "strands-agents @ {root:uri}" + "strands-agents @ {root:uri}", ] [tool.hatch.envs.hatch-static-analysis.scripts] @@ -186,6 +186,7 @@ extra-dependencies = [ "pytest-asyncio>=0.26.0,<0.27.0", "pytest-cov>=4.1.0,<5.0.0", "pytest-xdist>=3.0.0,<4.0.0", + "tomli>=2.2.1,<3.0.0", ] extra-args = [ "-n", From 77aab313962e9b1f784d7f89b86486749caf3b57 Mon Sep 17 00:00:00 2001 From: Mackenzie Zastrow Date: Mon, 18 Aug 2025 14:57:23 -0400 Subject: [PATCH 4/5] fix: Unify dependencies by referencing other groups We recently updated our litellm dependency, but only in the litellm optional dependency, not the [all] group - instead of specifying dependencies twice, have all reference the other optional dependency groups of strands. --- pyproject.toml | 47 +------------------------------- tests/strands/test_pyproject.py | 48 --------------------------------- 2 files changed, 1 insertion(+), 94 deletions(-) delete mode 100644 tests/strands/test_pyproject.py diff --git a/pyproject.toml b/pyproject.toml index 82f4827a0..7ac51d2df 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -61,7 +61,6 @@ dev = [ "pytest-cov>=4.1.0,<5.0.0", "pytest-xdist>=3.0.0,<4.0.0", "ruff>=0.4.4,<0.5.0", - "tomli>=2.2.1,<3.0.0", ] docs = [ "sphinx>=5.0.0,<6.0.0", @@ -105,50 +104,7 @@ a2a = [ "starlette>=0.46.2,<1.0.0", ] all = [ - # anthropic - "anthropic>=0.21.0,<1.0.0", - - # dev - "commitizen>=4.4.0,<5.0.0", - "hatch>=1.0.0,<2.0.0", - "moto>=5.1.0,<6.0.0", - "mypy>=1.15.0,<2.0.0", - "pre-commit>=3.2.0,<4.2.0", - "pytest>=8.0.0,<9.0.0", - "pytest-asyncio>=0.26.0,<0.27.0", - "pytest-cov>=4.1.0,<5.0.0", - "pytest-xdist>=3.0.0,<4.0.0", - "ruff>=0.4.4,<0.5.0", - - # docs - "sphinx>=5.0.0,<6.0.0", - "sphinx-rtd-theme>=1.0.0,<2.0.0", - "sphinx-autodoc-typehints>=1.12.0,<2.0.0", - - # litellm - "litellm>=1.73.1,<2.0.0", - - # llama - "llama-api-client>=0.1.0,<1.0.0", - - # mistral - "mistralai>=1.8.2", - - # ollama - "ollama>=0.4.8,<1.0.0", - - # openai - "openai>=1.68.0,<2.0.0", - - # otel - "opentelemetry-exporter-otlp-proto-http>=1.30.0,<2.0.0", - - # a2a - "a2a-sdk[sql]>=0.3.0,<0.4.0", - "uvicorn>=0.34.2,<1.0.0", - "httpx>=0.28.1,<1.0.0", - "fastapi>=0.115.12,<1.0.0", - "starlette>=0.46.2,<1.0.0", + "strands-agents[a2a,anthropic,dev,docs,litellm,llamaapi,mistral,ollama,openai,otel]", ] [tool.hatch.version] @@ -186,7 +142,6 @@ extra-dependencies = [ "pytest-asyncio>=0.26.0,<0.27.0", "pytest-cov>=4.1.0,<5.0.0", "pytest-xdist>=3.0.0,<4.0.0", - "tomli>=2.2.1,<3.0.0", ] extra-args = [ "-n", diff --git a/tests/strands/test_pyproject.py b/tests/strands/test_pyproject.py deleted file mode 100644 index 15a7b8f4f..000000000 --- a/tests/strands/test_pyproject.py +++ /dev/null @@ -1,48 +0,0 @@ -"""Tests for project configuration consistency.""" - -from pathlib import Path - -import tomli - - -def test_optional_dependencies_version_consistency(): - """Test that duplicate dependencies across groups have consistent version specifiers.""" - pyproject_path = Path(__file__).parent.parent.parent / "pyproject.toml" - - with open(pyproject_path, "rb") as f: - data = tomli.load(f) - - optional_deps = data["project"]["optional-dependencies"] - - # Collect all dependencies and their version specifiers with group info - dep_specs: dict[str, tuple[str, str]] = {} - - for group_name, deps in optional_deps.items(): - for dep in deps: - # Extract package name before any version specifier - name = dep - for op in [">=", "==", ">", "<", "~=", "!="]: - if op in name: - name = name.split(op)[0].strip() - break - - # Remove extras like [sql] from name - if "[" in name: - name = name.split("[")[0].strip() - - # Extract version specifier (everything after package name) - version_spec = dep[len(name) :].strip() - # Remove extras from version spec if present - if version_spec.startswith("["): - bracket_end = version_spec.find("]") - if bracket_end != -1: - version_spec = version_spec[bracket_end + 1 :].strip() - - if name in dep_specs: - (previous_spec, first_group) = dep_specs[name] - assert previous_spec == version_spec, ( - f"Version specifier mismatch for {name}: '{dep_specs[name]}'" - f" in [{first_group}] vs '{version_spec}' in [{group_name}]" - ) - else: - dep_specs[name] = (version_spec, group_name) From 2c655ffc98d103a4b9a23be1ce0265f33632316c Mon Sep 17 00:00:00 2001 From: Mackenzie Zastrow Date: Mon, 18 Aug 2025 15:06:05 -0400 Subject: [PATCH 5/5] Clamp version of openai to avoid breaking change bug in litellm See BerriAI/litellm/issues/13711 for more info --- pyproject.toml | 2 ++ 1 file changed, 2 insertions(+) diff --git a/pyproject.toml b/pyproject.toml index 7ac51d2df..f312e82c2 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -69,6 +69,8 @@ docs = [ ] litellm = [ "litellm>=1.73.1,<2.0.0", + # https://github.com/BerriAI/litellm/issues/13711 + "openai<1.100.0", ] llamaapi = [ "llama-api-client>=0.1.0,<1.0.0",