From 2b71a05e4ce28acd36353c9d18c3a7405b0fbc8a Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 24 Aug 2026 02:47:06 +0000 Subject: [PATCH 1/2] build(deps): bump anthropic from 0.125.0 to 1.0.0 Bumps [anthropic](https://github.com/anthropics/anthropic-sdk-python) from 0.125.0 to 1.0.0. - [Release notes](https://github.com/anthropics/anthropic-sdk-python/releases) - [Changelog](https://github.com/anthropics/anthropic-sdk-python/blob/main/CHANGELOG.md) - [Commits](https://github.com/anthropics/anthropic-sdk-python/compare/v0.125.0...v1.0.0) --- updated-dependencies: - dependency-name: anthropic dependency-version: 1.0.0 dependency-type: direct:production update-type: version-update:semver-major ... Signed-off-by: dependabot[bot] --- pyproject.toml | 2 +- requirements-lock.txt | 6 +++--- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/pyproject.toml b/pyproject.toml index 0e0b2c54..0b47d8ab 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -34,7 +34,7 @@ dependencies = [ "aiofiles", "aiohttp", "alembic", - "anthropic==0.125.0", + "anthropic==1.0.0", # 5.0.0 split Confluence into separate Cloud (REST v2) and Server (REST v1) # classes with different method signatures. The major ceiling keeps the next # such split from reaching production through a routine bump. diff --git a/requirements-lock.txt b/requirements-lock.txt index 9eb824a1..1d90bcdf 100644 --- a/requirements-lock.txt +++ b/requirements-lock.txt @@ -151,9 +151,9 @@ annotated-types==0.8.0 \ --hash=sha256:13b2beaad985e05e2d6407ee4c4f35590b11f8d693a258a561055cac8f64cab7 \ --hash=sha256:f072f4d804ea359e4eaf198b1af7a8b0943881a87f31bb764f8bf219bb9419e0 # via pydantic -anthropic==0.125.0 \ - --hash=sha256:3486013602eca76d8b12540764e53654f02cf4951110bca86cf06e67428a9f21 \ - --hash=sha256:e0cdd336580cb7411c1cdab69f80973e9bf4bff7f8e08141811d46307d45c682 +anthropic==1.0.0 \ + --hash=sha256:32dd52e9e1d774393b27182f451398ba4262287a4d0eab30887f89f1481b3ae4 \ + --hash=sha256:42be3c97604af7252c5898413aee076ace6c46e9bca0d0d90ceb77c7d3719027 # via dispatch (pyproject.toml) anyio==4.14.2 \ --hash=sha256:9f505dda5ac9f0c8309b5e8bd445a8c2bf7246f3ce950121e45ea15bc41d1494 \ From 7aa5dea12d10ee03eaa9a39806ec4a3511281cf8 Mon Sep 17 00:00:00 2001 From: Jamyn Shanley <696574+Jamyn@users.noreply.github.com> Date: Mon, 24 Aug 2026 14:07:07 +0000 Subject: [PATCH 2/2] build(deps): move the anthropic fixtures to httpx2 for SDK 1.0 anthropic 1.x builds on httpx2 and rejects an httpx client from its constructor, so the plugin fixtures failed to build a client at all. Dependabot's lockfile edit rewrote the anthropic pin in place without re-resolving, leaving `httpx # via anthropic` and a `distro` entry the SDK no longer requires; regenerated inside the pinned base image. --- requirements-lock.txt | 9 +++------ tests/plugins/dispatch_anthropic/conftest.py | 4 ++-- .../dispatch_anthropic/fake_anthropic.py | 20 +++++++++++-------- .../test_anthropic_sdk_surface.py | 12 +++++++++++ tests/plugins/dispatch_openai/fake_openai.py | 2 +- 5 files changed, 30 insertions(+), 17 deletions(-) diff --git a/requirements-lock.txt b/requirements-lock.txt index 1d90bcdf..97ee897a 100644 --- a/requirements-lock.txt +++ b/requirements-lock.txt @@ -787,10 +787,6 @@ deprecated==1.3.1 \ # via # atlassian-python-api # limits -distro==1.9.0 \ - --hash=sha256:2fa77c6fd8940f116ee1d6b94a2f90b13b5ea8d019b98bc8bafdcabcdd9bdbed \ - --hash=sha256:7bffd925d65168f85027d8da9af6bddab658135b840670a223589bc0c8ef02b2 - # via anthropic dkimpy==1.1.8 \ --hash=sha256:b5f60fb47bbf5d8d762f134bcea0c388eba6b498342a682a21f1686545094b77 # via emails @@ -1093,12 +1089,13 @@ httpx==0.28.1 \ --hash=sha256:d909fcccc110f8c7faf814ca82a9a4d816bc5a6dbfea25d6591d6985b8ba59ad # via # dispatch (pyproject.toml) - # anthropic # weasel httpx2==2.12.0 \ --hash=sha256:7631fe9887a8a2275f4a2540e053aa670fcc50742864a9ae7c66e609fdcf12cf \ --hash=sha256:cc8b6eecb8661c146b8f89a60e97456ee086e91a784ed31ac450c3a9e613dd36 - # via openai + # via + # anthropic + # openai idna==3.19 \ --hash=sha256:5e0811a4383b21dc5838069f801c4fb62113b7447663d2530d2bd6e77b49bf15 \ --hash=sha256:815e7be7a7806d54abb586dc943addc79e8b2ee16915059658cbeff4b1b43bf4 diff --git a/tests/plugins/dispatch_anthropic/conftest.py b/tests/plugins/dispatch_anthropic/conftest.py index 8be9109b..e5d09843 100644 --- a/tests/plugins/dispatch_anthropic/conftest.py +++ b/tests/plugins/dispatch_anthropic/conftest.py @@ -6,7 +6,7 @@ importer gets a second copy. """ -import httpx +import httpx2 import pytest from anthropic import Anthropic @@ -22,7 +22,7 @@ def client_factory(**kwargs): # max_retries=0 only so a failure test issues one request rather than # three with backoff; it does not change what is sent. return Anthropic( - http_client=httpx.Client(transport=httpx.MockTransport(api)), + http_client=httpx2.Client(transport=httpx2.MockTransport(api)), max_retries=0, **kwargs, ) diff --git a/tests/plugins/dispatch_anthropic/fake_anthropic.py b/tests/plugins/dispatch_anthropic/fake_anthropic.py index 7b5866f8..57f59a15 100644 --- a/tests/plugins/dispatch_anthropic/fake_anthropic.py +++ b/tests/plugins/dispatch_anthropic/fake_anthropic.py @@ -1,6 +1,6 @@ """An in-memory Anthropic API, for driving the real plugin against (issue #79). -The fake is installed at the httpx transport, below the anthropic SDK, so the +The fake is installed at the httpx2 transport, below the anthropic SDK, so the plugin's own client construction and the SDK's own request building, structured output schema generation and response parsing all run for real against it. Replacing ``client.messages`` with a mock instead would assert only that the @@ -8,6 +8,10 @@ repeat, is precisely a case where every mocked assertion passed while no real request could ever be built. +httpx2, not httpx: anthropic 1.x builds its requests on httpx2 and rejects an +httpx client from its constructor outright, so a fake mounted on httpx would not +even construct. + Only the plugin's ``Anthropic`` name is patched, and only to hand the real client a transport. Everything the plugin passes to that constructor -- the API key above all -- still travels the real code path and lands in a request this @@ -16,7 +20,7 @@ import json -import httpx +import httpx2 from anthropic import Anthropic # noqa: F401 (re-exported for the fixtures) # Obviously fake, and never a real-looking credential. @@ -68,7 +72,7 @@ def respond_with_text(self, content: str): def respond_with_blocks(self, blocks: list[dict], stop_reason: str = "end_turn"): """An arbitrary content-block list -- several text blocks, a thinking block, a tool_use block, or none at all.""" - self._handler = lambda request: httpx.Response( + self._handler = lambda request: httpx2.Response( 200, json=self._message(request, blocks, stop_reason=stop_reason) ) @@ -81,7 +85,7 @@ def respond_with_refusal(self, category: str = "cyber"): """The model declined. Anthropic sends stop_reason ``refusal`` plus a ``stop_details`` object naming the policy category; ``content`` is empty, and ``messages.parse`` reports ``parsed_output`` as None.""" - self._handler = lambda request: httpx.Response( + self._handler = lambda request: httpx2.Response( 200, json=self._message( request, @@ -109,7 +113,7 @@ def respond_with_status( body quotes the submitted API key back inside it -- see ``respond_with_key_echo``, which is the shape that matters. """ - self._handler = lambda request: httpx.Response( + self._handler = lambda request: httpx2.Response( status, json={"type": "error", "error": {"type": error_type, "message": message}}, headers={"request-id": "req_test_0001"}, @@ -128,7 +132,7 @@ def respond_with_undocumented_refusal_category(self, category: str): def respond_with_non_envelope(self, status: int = 502): """A body that is not Anthropic's error envelope at all -- what a proxy or gateway in front of the API returns. `APIStatusError.type` is None.""" - self._handler = lambda request: httpx.Response( + self._handler = lambda request: httpx2.Response( status, text="502 Bad Gateway" ) @@ -138,7 +142,7 @@ def respond_with_connection_error(self): `APIStatusError`, so it has no status, type or request id.""" def raise_connect_error(request): - raise httpx.ConnectError("connection refused", request=request) + raise httpx2.ConnectError("connection refused", request=request) self._handler = raise_connect_error @@ -180,7 +184,7 @@ def _message(self, request, blocks, stop_reason="end_turn", stop_details=None): "usage": {"input_tokens": 1, "output_tokens": 1}, } - def __call__(self, request: httpx.Request) -> httpx.Response: + def __call__(self, request: httpx2.Request) -> httpx2.Response: self.requests.append( { "url": str(request.url), diff --git a/tests/plugins/dispatch_anthropic/test_anthropic_sdk_surface.py b/tests/plugins/dispatch_anthropic/test_anthropic_sdk_surface.py index 84fddb7c..e7401e14 100644 --- a/tests/plugins/dispatch_anthropic/test_anthropic_sdk_surface.py +++ b/tests/plugins/dispatch_anthropic/test_anthropic_sdk_surface.py @@ -57,3 +57,15 @@ def test_the_error_hierarchy_the_plugin_catches_is_the_root_one(): for cls in (APIStatusError, APIConnectionError, AuthenticationError, RateLimitError): assert issubclass(cls, AnthropicError), cls.__name__ + + +def test_the_sdk_builds_on_httpx2(): + """The fixtures mount their fake at the SDK's transport, so they have to + hand it a client of the right kind -- and anthropic 1.x rejects an ``httpx`` + client from the constructor outright. Pinning the HTTP layer here reports a + future swap as the dependency change it is, rather than as a TypeError in + every fixture that builds a client.""" + import httpx2 + from anthropic import DefaultHttpxClient + + assert issubclass(DefaultHttpxClient, httpx2.Client) diff --git a/tests/plugins/dispatch_openai/fake_openai.py b/tests/plugins/dispatch_openai/fake_openai.py index 6a8e0d82..4ab45dc1 100644 --- a/tests/plugins/dispatch_openai/fake_openai.py +++ b/tests/plugins/dispatch_openai/fake_openai.py @@ -10,7 +10,7 @@ httpx2, not httpx: openai 3.x builds its requests on httpx2 and only accepts an httpx client through a legacy escape hatch the SDK documents as temporary. A fake mounted on that hatch would exercise a stack production no longer uses. -The anthropic fake stays on httpx, which is what that SDK still ships against. +The anthropic fake is on httpx2 too, since anthropic 1.x. Only the plugin's ``OpenAI`` name is patched, and only to hand the real client a transport. Everything the plugin passes to that constructor -- the API key above