From 644758193eed6d218d1a38262e33b07c491b136c Mon Sep 17 00:00:00 2001 From: "stainless-app[bot]" <142633134+stainless-app[bot]@users.noreply.github.com> Date: Thu, 9 Apr 2026 18:46:46 +0000 Subject: [PATCH 1/6] codegen metadata --- .stats.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.stats.yml b/.stats.yml index e00ff937e..95061352d 100644 --- a/.stats.yml +++ b/.stats.yml @@ -1,4 +1,4 @@ configured_endpoints: 72 -openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/anthropic%2Fanthropic-d87d3ef6f636c667a0256be82cebef0699d17403d409c26ec15813683cfc3263.yml +openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/anthropic%2Fanthropic-dfe504526eed07979685a729ac9afd45e59cc2879291714b9f4674f2ef1247c7.yml openapi_spec_hash: d849fdf2c4dd6631a60c4340e9bc1322 -config_hash: 062be10c6bf39b6719b3a5ea2bf758b3 +config_hash: 831f90480c5b2b863b726e89eabaa90c From b7e157d85f50b2900ddf896e8e80882dd7311bfd Mon Sep 17 00:00:00 2001 From: Mike Cluck Date: Thu, 9 Apr 2026 15:46:05 -0400 Subject: [PATCH 2/6] feat: vertex eu region (#1658) --- src/anthropic/lib/vertex/_client.py | 2 ++ tests/lib/test_vertex.py | 5 +++++ 2 files changed, 7 insertions(+) diff --git a/src/anthropic/lib/vertex/_client.py b/src/anthropic/lib/vertex/_client.py index 70f04eeb4..8918b759c 100644 --- a/src/anthropic/lib/vertex/_client.py +++ b/src/anthropic/lib/vertex/_client.py @@ -121,6 +121,8 @@ def __init__( base_url = "https://aiplatform.googleapis.com/v1" elif region == "us": base_url = "https://aiplatform.us.rep.googleapis.com/v1" + elif region == "eu": + base_url = "https://aiplatform.eu.rep.googleapis.com/v1" else: base_url = f"https://{region}-aiplatform.googleapis.com/v1" diff --git a/tests/lib/test_vertex.py b/tests/lib/test_vertex.py index 36196b194..c2d9b3d4b 100644 --- a/tests/lib/test_vertex.py +++ b/tests/lib/test_vertex.py @@ -129,6 +129,11 @@ def test_us_region_base_url(self) -> None: client = AnthropicVertex(region="us", project_id="test-project", access_token="fake-token") assert str(client.base_url).rstrip("/") == "https://aiplatform.us.rep.googleapis.com/v1" + def test_eu_region_base_url(self) -> None: + """Test that us region uses the correct base URL.""" + client = AnthropicVertex(region="eu", project_id="test-project", access_token="fake-token") + assert str(client.base_url).rstrip("/") == "https://aiplatform.eu.rep.googleapis.com/v1" + @pytest.mark.parametrize("region", ["us-central1", "europe-west1", "asia-southeast1"]) def test_regional_base_url(self, region: str) -> None: """Test that regional endpoints use the correct base URL format.""" From 837b25bb6262186a5bae92aa70eb73c3cf8c90af Mon Sep 17 00:00:00 2001 From: "stainless-app[bot]" <142633134+stainless-app[bot]@users.noreply.github.com> Date: Fri, 10 Apr 2026 14:57:47 +0000 Subject: [PATCH 3/6] fix: ensure file data are only sent as 1 parameter --- src/anthropic/_utils/_utils.py | 5 +++-- tests/test_extract_files.py | 9 +++++++++ 2 files changed, 12 insertions(+), 2 deletions(-) diff --git a/src/anthropic/_utils/_utils.py b/src/anthropic/_utils/_utils.py index eec7f4a1f..63b8cd602 100644 --- a/src/anthropic/_utils/_utils.py +++ b/src/anthropic/_utils/_utils.py @@ -86,8 +86,9 @@ def _extract_items( index += 1 if is_dict(obj): try: - # We are at the last entry in the path so we must remove the field - if (len(path)) == index: + # Remove the field if there are no more dict keys in the path, + # only "" traversal markers or end. + if all(p == "" for p in path[index:]): item = obj.pop(key) else: item = obj[key] diff --git a/tests/test_extract_files.py b/tests/test_extract_files.py index 02c0614f4..07e2430eb 100644 --- a/tests/test_extract_files.py +++ b/tests/test_extract_files.py @@ -35,6 +35,15 @@ def test_multiple_files() -> None: assert query == {"documents": [{}, {}]} +def test_top_level_file_array() -> None: + query = {"files": [b"file one", b"file two"], "title": "hello"} + assert extract_files(query, paths=[["files", ""]]) == [ + ("files[]", b"file one"), + ("files[]", b"file two"), + ] + assert query == {"title": "hello"} + + @pytest.mark.parametrize( "query,paths,expected", [ From 48089fdb788500d00718b9d4ae24cd34e5e91beb Mon Sep 17 00:00:00 2001 From: "stainless-app[bot]" <142633134+stainless-app[bot]@users.noreply.github.com> Date: Fri, 10 Apr 2026 20:49:57 +0000 Subject: [PATCH 4/6] docs: improve examples From 0f3c28b973026d135f91f38c4ad82ae2b1131522 Mon Sep 17 00:00:00 2001 From: "stainless-app[bot]" <142633134+stainless-app[bot]@users.noreply.github.com> Date: Fri, 10 Apr 2026 22:22:54 +0000 Subject: [PATCH 5/6] docs: update examples --- tests/api_resources/beta/test_messages.py | 32 +++++++++++------------ tests/api_resources/test_completions.py | 32 +++++++++++------------ tests/api_resources/test_messages.py | 32 +++++++++++------------ 3 files changed, 48 insertions(+), 48 deletions(-) diff --git a/tests/api_resources/beta/test_messages.py b/tests/api_resources/beta/test_messages.py index 65bde9427..b391c1f64 100644 --- a/tests/api_resources/beta/test_messages.py +++ b/tests/api_resources/beta/test_messages.py @@ -392,11 +392,11 @@ def test_method_count_tokens(self, client: Anthropic) -> None: message = client.beta.messages.count_tokens( messages=[ { - "content": "string", + "content": "Hello, world", "role": "user", } ], - model="claude-mythos-preview", + model="claude-opus-4-6", ) assert_matches_type(BetaMessageTokensCount, message, path=["response"]) @@ -405,11 +405,11 @@ def test_method_count_tokens_with_all_params(self, client: Anthropic) -> None: message = client.beta.messages.count_tokens( messages=[ { - "content": "string", + "content": "Hello, world", "role": "user", } ], - model="claude-mythos-preview", + model="claude-opus-4-6", cache_control={ "type": "ephemeral", "ttl": "5m", @@ -516,11 +516,11 @@ def test_raw_response_count_tokens(self, client: Anthropic) -> None: response = client.beta.messages.with_raw_response.count_tokens( messages=[ { - "content": "string", + "content": "Hello, world", "role": "user", } ], - model="claude-mythos-preview", + model="claude-opus-4-6", ) assert response.is_closed is True @@ -533,11 +533,11 @@ def test_streaming_response_count_tokens(self, client: Anthropic) -> None: with client.beta.messages.with_streaming_response.count_tokens( messages=[ { - "content": "string", + "content": "Hello, world", "role": "user", } ], - model="claude-mythos-preview", + model="claude-opus-4-6", ) as response: assert not response.is_closed assert response.http_request.headers.get("X-Stainless-Lang") == "python" @@ -941,11 +941,11 @@ async def test_method_count_tokens(self, async_client: AsyncAnthropic) -> None: message = await async_client.beta.messages.count_tokens( messages=[ { - "content": "string", + "content": "Hello, world", "role": "user", } ], - model="claude-mythos-preview", + model="claude-opus-4-6", ) assert_matches_type(BetaMessageTokensCount, message, path=["response"]) @@ -954,11 +954,11 @@ async def test_method_count_tokens_with_all_params(self, async_client: AsyncAnth message = await async_client.beta.messages.count_tokens( messages=[ { - "content": "string", + "content": "Hello, world", "role": "user", } ], - model="claude-mythos-preview", + model="claude-opus-4-6", cache_control={ "type": "ephemeral", "ttl": "5m", @@ -1065,11 +1065,11 @@ async def test_raw_response_count_tokens(self, async_client: AsyncAnthropic) -> response = await async_client.beta.messages.with_raw_response.count_tokens( messages=[ { - "content": "string", + "content": "Hello, world", "role": "user", } ], - model="claude-mythos-preview", + model="claude-opus-4-6", ) assert response.is_closed is True @@ -1082,11 +1082,11 @@ async def test_streaming_response_count_tokens(self, async_client: AsyncAnthropi async with async_client.beta.messages.with_streaming_response.count_tokens( messages=[ { - "content": "string", + "content": "Hello, world", "role": "user", } ], - model="claude-mythos-preview", + model="claude-opus-4-6", ) as response: assert not response.is_closed assert response.http_request.headers.get("X-Stainless-Lang") == "python" diff --git a/tests/api_resources/test_completions.py b/tests/api_resources/test_completions.py index bf1797c5f..6d4a7f2be 100644 --- a/tests/api_resources/test_completions.py +++ b/tests/api_resources/test_completions.py @@ -21,7 +21,7 @@ class TestCompletions: def test_method_create_overload_1(self, client: Anthropic) -> None: completion = client.completions.create( max_tokens_to_sample=256, - model="claude-mythos-preview", + model="claude-2.1", prompt="\n\nHuman: Hello, world!\n\nAssistant:", ) assert_matches_type(Completion, completion, path=["response"]) @@ -30,7 +30,7 @@ def test_method_create_overload_1(self, client: Anthropic) -> None: def test_method_create_with_all_params_overload_1(self, client: Anthropic) -> None: completion = client.completions.create( max_tokens_to_sample=256, - model="claude-mythos-preview", + model="claude-2.1", prompt="\n\nHuman: Hello, world!\n\nAssistant:", metadata={"user_id": "13803d75-b4b5-4c3e-b2a2-6f21399b021b"}, stop_sequences=["string"], @@ -46,7 +46,7 @@ def test_method_create_with_all_params_overload_1(self, client: Anthropic) -> No def test_raw_response_create_overload_1(self, client: Anthropic) -> None: response = client.completions.with_raw_response.create( max_tokens_to_sample=256, - model="claude-mythos-preview", + model="claude-2.1", prompt="\n\nHuman: Hello, world!\n\nAssistant:", ) @@ -59,7 +59,7 @@ def test_raw_response_create_overload_1(self, client: Anthropic) -> None: def test_streaming_response_create_overload_1(self, client: Anthropic) -> None: with client.completions.with_streaming_response.create( max_tokens_to_sample=256, - model="claude-mythos-preview", + model="claude-2.1", prompt="\n\nHuman: Hello, world!\n\nAssistant:", ) as response: assert not response.is_closed @@ -74,7 +74,7 @@ def test_streaming_response_create_overload_1(self, client: Anthropic) -> None: def test_method_create_overload_2(self, client: Anthropic) -> None: completion_stream = client.completions.create( max_tokens_to_sample=256, - model="claude-mythos-preview", + model="claude-2.1", prompt="\n\nHuman: Hello, world!\n\nAssistant:", stream=True, ) @@ -84,7 +84,7 @@ def test_method_create_overload_2(self, client: Anthropic) -> None: def test_method_create_with_all_params_overload_2(self, client: Anthropic) -> None: completion_stream = client.completions.create( max_tokens_to_sample=256, - model="claude-mythos-preview", + model="claude-2.1", prompt="\n\nHuman: Hello, world!\n\nAssistant:", stream=True, metadata={"user_id": "13803d75-b4b5-4c3e-b2a2-6f21399b021b"}, @@ -100,7 +100,7 @@ def test_method_create_with_all_params_overload_2(self, client: Anthropic) -> No def test_raw_response_create_overload_2(self, client: Anthropic) -> None: response = client.completions.with_raw_response.create( max_tokens_to_sample=256, - model="claude-mythos-preview", + model="claude-2.1", prompt="\n\nHuman: Hello, world!\n\nAssistant:", stream=True, ) @@ -113,7 +113,7 @@ def test_raw_response_create_overload_2(self, client: Anthropic) -> None: def test_streaming_response_create_overload_2(self, client: Anthropic) -> None: with client.completions.with_streaming_response.create( max_tokens_to_sample=256, - model="claude-mythos-preview", + model="claude-2.1", prompt="\n\nHuman: Hello, world!\n\nAssistant:", stream=True, ) as response: @@ -135,7 +135,7 @@ class TestAsyncCompletions: async def test_method_create_overload_1(self, async_client: AsyncAnthropic) -> None: completion = await async_client.completions.create( max_tokens_to_sample=256, - model="claude-mythos-preview", + model="claude-2.1", prompt="\n\nHuman: Hello, world!\n\nAssistant:", ) assert_matches_type(Completion, completion, path=["response"]) @@ -144,7 +144,7 @@ async def test_method_create_overload_1(self, async_client: AsyncAnthropic) -> N async def test_method_create_with_all_params_overload_1(self, async_client: AsyncAnthropic) -> None: completion = await async_client.completions.create( max_tokens_to_sample=256, - model="claude-mythos-preview", + model="claude-2.1", prompt="\n\nHuman: Hello, world!\n\nAssistant:", metadata={"user_id": "13803d75-b4b5-4c3e-b2a2-6f21399b021b"}, stop_sequences=["string"], @@ -160,7 +160,7 @@ async def test_method_create_with_all_params_overload_1(self, async_client: Asyn async def test_raw_response_create_overload_1(self, async_client: AsyncAnthropic) -> None: response = await async_client.completions.with_raw_response.create( max_tokens_to_sample=256, - model="claude-mythos-preview", + model="claude-2.1", prompt="\n\nHuman: Hello, world!\n\nAssistant:", ) @@ -173,7 +173,7 @@ async def test_raw_response_create_overload_1(self, async_client: AsyncAnthropic async def test_streaming_response_create_overload_1(self, async_client: AsyncAnthropic) -> None: async with async_client.completions.with_streaming_response.create( max_tokens_to_sample=256, - model="claude-mythos-preview", + model="claude-2.1", prompt="\n\nHuman: Hello, world!\n\nAssistant:", ) as response: assert not response.is_closed @@ -188,7 +188,7 @@ async def test_streaming_response_create_overload_1(self, async_client: AsyncAnt async def test_method_create_overload_2(self, async_client: AsyncAnthropic) -> None: completion_stream = await async_client.completions.create( max_tokens_to_sample=256, - model="claude-mythos-preview", + model="claude-2.1", prompt="\n\nHuman: Hello, world!\n\nAssistant:", stream=True, ) @@ -198,7 +198,7 @@ async def test_method_create_overload_2(self, async_client: AsyncAnthropic) -> N async def test_method_create_with_all_params_overload_2(self, async_client: AsyncAnthropic) -> None: completion_stream = await async_client.completions.create( max_tokens_to_sample=256, - model="claude-mythos-preview", + model="claude-2.1", prompt="\n\nHuman: Hello, world!\n\nAssistant:", stream=True, metadata={"user_id": "13803d75-b4b5-4c3e-b2a2-6f21399b021b"}, @@ -214,7 +214,7 @@ async def test_method_create_with_all_params_overload_2(self, async_client: Asyn async def test_raw_response_create_overload_2(self, async_client: AsyncAnthropic) -> None: response = await async_client.completions.with_raw_response.create( max_tokens_to_sample=256, - model="claude-mythos-preview", + model="claude-2.1", prompt="\n\nHuman: Hello, world!\n\nAssistant:", stream=True, ) @@ -227,7 +227,7 @@ async def test_raw_response_create_overload_2(self, async_client: AsyncAnthropic async def test_streaming_response_create_overload_2(self, async_client: AsyncAnthropic) -> None: async with async_client.completions.with_streaming_response.create( max_tokens_to_sample=256, - model="claude-mythos-preview", + model="claude-2.1", prompt="\n\nHuman: Hello, world!\n\nAssistant:", stream=True, ) as response: diff --git a/tests/api_resources/test_messages.py b/tests/api_resources/test_messages.py index f4e600b64..63963ed67 100644 --- a/tests/api_resources/test_messages.py +++ b/tests/api_resources/test_messages.py @@ -314,11 +314,11 @@ def test_method_count_tokens(self, client: Anthropic) -> None: message = client.messages.count_tokens( messages=[ { - "content": "string", + "content": "Hello, world", "role": "user", } ], - model="claude-mythos-preview", + model="claude-opus-4-6", ) assert_matches_type(MessageTokensCount, message, path=["response"]) @@ -327,11 +327,11 @@ def test_method_count_tokens_with_all_params(self, client: Anthropic) -> None: message = client.messages.count_tokens( messages=[ { - "content": "string", + "content": "Hello, world", "role": "user", } ], - model="claude-mythos-preview", + model="claude-opus-4-6", cache_control={ "type": "ephemeral", "ttl": "5m", @@ -403,11 +403,11 @@ def test_raw_response_count_tokens(self, client: Anthropic) -> None: response = client.messages.with_raw_response.count_tokens( messages=[ { - "content": "string", + "content": "Hello, world", "role": "user", } ], - model="claude-mythos-preview", + model="claude-opus-4-6", ) assert response.is_closed is True @@ -420,11 +420,11 @@ def test_streaming_response_count_tokens(self, client: Anthropic) -> None: with client.messages.with_streaming_response.count_tokens( messages=[ { - "content": "string", + "content": "Hello, world", "role": "user", } ], - model="claude-mythos-preview", + model="claude-opus-4-6", ) as response: assert not response.is_closed assert response.http_request.headers.get("X-Stainless-Lang") == "python" @@ -733,11 +733,11 @@ async def test_method_count_tokens(self, async_client: AsyncAnthropic) -> None: message = await async_client.messages.count_tokens( messages=[ { - "content": "string", + "content": "Hello, world", "role": "user", } ], - model="claude-mythos-preview", + model="claude-opus-4-6", ) assert_matches_type(MessageTokensCount, message, path=["response"]) @@ -746,11 +746,11 @@ async def test_method_count_tokens_with_all_params(self, async_client: AsyncAnth message = await async_client.messages.count_tokens( messages=[ { - "content": "string", + "content": "Hello, world", "role": "user", } ], - model="claude-mythos-preview", + model="claude-opus-4-6", cache_control={ "type": "ephemeral", "ttl": "5m", @@ -822,11 +822,11 @@ async def test_raw_response_count_tokens(self, async_client: AsyncAnthropic) -> response = await async_client.messages.with_raw_response.count_tokens( messages=[ { - "content": "string", + "content": "Hello, world", "role": "user", } ], - model="claude-mythos-preview", + model="claude-opus-4-6", ) assert response.is_closed is True @@ -839,11 +839,11 @@ async def test_streaming_response_count_tokens(self, async_client: AsyncAnthropi async with async_client.messages.with_streaming_response.count_tokens( messages=[ { - "content": "string", + "content": "Hello, world", "role": "user", } ], - model="claude-mythos-preview", + model="claude-opus-4-6", ) as response: assert not response.is_closed assert response.http_request.headers.get("X-Stainless-Lang") == "python" From 027716d7f05edf24705a533c251efa9db326d0d8 Mon Sep 17 00:00:00 2001 From: "stainless-app[bot]" <142633134+stainless-app[bot]@users.noreply.github.com> Date: Fri, 10 Apr 2026 22:23:26 +0000 Subject: [PATCH 6/6] release: 0.94.0 --- .release-please-manifest.json | 2 +- CHANGELOG.md | 19 +++++++++++++++++++ pyproject.toml | 2 +- src/anthropic/_version.py | 2 +- 4 files changed, 22 insertions(+), 3 deletions(-) diff --git a/.release-please-manifest.json b/.release-please-manifest.json index c486f6de6..91393ed88 100644 --- a/.release-please-manifest.json +++ b/.release-please-manifest.json @@ -1,3 +1,3 @@ { - ".": "0.93.0" + ".": "0.94.0" } \ No newline at end of file diff --git a/CHANGELOG.md b/CHANGELOG.md index 6116d6d38..aa329d2ee 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,24 @@ # Changelog +## 0.94.0 (2026-04-10) + +Full Changelog: [v0.93.0...v0.94.0](https://github.com/anthropics/anthropic-sdk-python/compare/v0.93.0...v0.94.0) + +### Features + +* vertex eu region ([#1658](https://github.com/anthropics/anthropic-sdk-python/issues/1658)) ([b7e157d](https://github.com/anthropics/anthropic-sdk-python/commit/b7e157d85f50b2900ddf896e8e80882dd7311bfd)) + + +### Bug Fixes + +* ensure file data are only sent as 1 parameter ([837b25b](https://github.com/anthropics/anthropic-sdk-python/commit/837b25bb6262186a5bae92aa70eb73c3cf8c90af)) + + +### Documentation + +* improve examples ([48089fd](https://github.com/anthropics/anthropic-sdk-python/commit/48089fdb788500d00718b9d4ae24cd34e5e91beb)) +* update examples ([0f3c28b](https://github.com/anthropics/anthropic-sdk-python/commit/0f3c28b973026d135f91f38c4ad82ae2b1131522)) + ## 0.93.0 (2026-04-09) Full Changelog: [v0.92.0...v0.93.0](https://github.com/anthropics/anthropic-sdk-python/compare/v0.92.0...v0.93.0) diff --git a/pyproject.toml b/pyproject.toml index 0160d27fd..883a3317d 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -1,6 +1,6 @@ [project] name = "anthropic" -version = "0.93.0" +version = "0.94.0" description = "The official Python library for the anthropic API" dynamic = ["readme"] license = "MIT" diff --git a/src/anthropic/_version.py b/src/anthropic/_version.py index dfbdffd16..9c558dc5b 100644 --- a/src/anthropic/_version.py +++ b/src/anthropic/_version.py @@ -1,4 +1,4 @@ # File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. __title__ = "anthropic" -__version__ = "0.93.0" # x-release-please-version +__version__ = "0.94.0" # x-release-please-version