Skip to content

Commit 6875fab

Browse files
feat: prepare aws package (#1615)
1 parent fd82d6b commit 6875fab

File tree

9 files changed

+1672
-46
lines changed

9 files changed

+1672
-46
lines changed

pyproject.toml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -41,6 +41,7 @@ classifiers = [
4141
[project.optional-dependencies]
4242
aiohttp = ["aiohttp", "httpx_aiohttp>=0.1.9"]
4343
vertex = ["google-auth[requests] >=2, <3"]
44+
aws = ["boto3 >= 1.28.57", "botocore >= 1.31.57"]
4445
bedrock = ["boto3 >= 1.28.57", "botocore >= 1.31.57"]
4546
mcp = ["mcp>=1.0; python_version >= '3.10'"]
4647

src/anthropic/__init__.py

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -98,6 +98,7 @@
9898
if not _t.TYPE_CHECKING:
9999
from ._utils._resources_proxy import resources as resources
100100

101+
from .lib.aws import AnthropicAWS as AnthropicAWS, AsyncAnthropicAWS as AsyncAnthropicAWS
101102
from .lib.tools import beta_tool, beta_async_tool
102103
from .lib.vertex import *
103104
from .lib.bedrock import *

src/anthropic/lib/aws/__init__.py

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
from ._client import AnthropicAWS as AnthropicAWS, AsyncAnthropicAWS as AsyncAnthropicAWS

src/anthropic/lib/aws/_auth.py

Lines changed: 72 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,72 @@
1+
from __future__ import annotations
2+
3+
from typing import TYPE_CHECKING
4+
5+
import httpx
6+
7+
from ..._utils import lru_cache
8+
9+
if TYPE_CHECKING:
10+
import boto3
11+
12+
13+
@lru_cache(maxsize=512)
14+
def _get_session(
15+
*,
16+
aws_access_key: str | None,
17+
aws_secret_key: str | None,
18+
aws_session_token: str | None,
19+
region: str | None,
20+
profile: str | None,
21+
) -> boto3.Session:
22+
import boto3
23+
24+
return boto3.Session(
25+
profile_name=profile,
26+
region_name=region,
27+
aws_access_key_id=aws_access_key,
28+
aws_secret_access_key=aws_secret_key,
29+
aws_session_token=aws_session_token,
30+
)
31+
32+
33+
def get_auth_headers(
34+
*,
35+
method: str,
36+
url: str,
37+
headers: httpx.Headers,
38+
aws_access_key: str | None,
39+
aws_secret_key: str | None,
40+
aws_session_token: str | None,
41+
region: str | None,
42+
profile: str | None,
43+
data: str | None,
44+
service_name: str,
45+
) -> dict[str, str]:
46+
from botocore.auth import SigV4Auth
47+
from botocore.awsrequest import AWSRequest
48+
49+
session = _get_session(
50+
profile=profile,
51+
region=region,
52+
aws_access_key=aws_access_key,
53+
aws_secret_key=aws_secret_key,
54+
aws_session_token=aws_session_token,
55+
)
56+
57+
# The connection header may be stripped by a proxy somewhere, so the receiver
58+
# of this message may not see this header, so we remove it from the set of headers
59+
# that are signed.
60+
new_headers = {k: v for k, v in dict(headers).items() if k.lower() != "connection"}
61+
62+
request = AWSRequest(method=method.upper(), url=url, headers=new_headers, data=data)
63+
credentials = session.get_credentials()
64+
if not credentials:
65+
raise RuntimeError("Could not resolve AWS credentials from session")
66+
67+
signer = SigV4Auth(credentials, service_name, session.region_name)
68+
signer.add_auth(request)
69+
70+
prepped = request.prepare()
71+
72+
return {key: value for key, value in dict(prepped.headers).items() if value is not None}

0 commit comments

Comments
 (0)