diff --git a/mypy.ini b/mypy.ini index b57646b0..b4f97067 100644 --- a/mypy.ini +++ b/mypy.ini @@ -45,3 +45,6 @@ disable_error_code = func-returns-value module = "black.files.*" ignore_errors = true ignore_missing_imports = true + +[mypy-anthropic.lib.vertex._auth] +disallow_untyped_calls = false diff --git a/requirements-dev.lock b/requirements-dev.lock index c21713ef..1081f33c 100644 --- a/requirements-dev.lock +++ b/requirements-dev.lock @@ -16,24 +16,22 @@ anyio==4.4.0 # via httpx argcomplete==3.1.2 # via nox -attrs==23.1.0 - # via pytest -boto3==1.28.58 +boto3==1.35.49 # via anthropic -boto3-stubs==1.28.41 -botocore==1.31.58 +boto3-stubs==1.35.49 +botocore==1.35.49 # via anthropic # via boto3 # via s3transfer -botocore-stubs==1.34.94 +botocore-stubs==1.35.49 # via boto3-stubs -cachetools==5.3.3 +cachetools==5.5.0 # via google-auth certifi==2023.7.22 # via httpcore # via httpx # via requests -charset-normalizer==3.3.2 +charset-normalizer==3.4.0 # via requests colorlog==6.7.0 # via nox @@ -42,14 +40,15 @@ distlib==0.3.7 # via virtualenv distro==1.8.0 # via anthropic -exceptiongroup==1.1.3 +exceptiongroup==1.2.2 # via anyio + # via pytest filelock==3.12.4 # via huggingface-hub # via virtualenv -fsspec==2024.3.1 +fsspec==2024.10.0 # via huggingface-hub -google-auth==2.26.2 +google-auth==2.35.0 # via anthropic h11==0.14.0 # via httpcore @@ -58,7 +57,7 @@ httpcore==1.0.2 httpx==0.25.2 # via anthropic # via respx -huggingface-hub==0.16.4 +huggingface-hub==0.26.1 # via tokenizers idna==3.4 # via anyio @@ -67,7 +66,7 @@ idna==3.4 importlib-metadata==7.0.0 iniconfig==2.0.0 # via pytest -jiter==0.4.0 +jiter==0.6.1 # via anthropic jmespath==1.0.1 # via boto3 @@ -88,40 +87,38 @@ packaging==23.2 # via pytest platformdirs==3.11.0 # via virtualenv -pluggy==1.3.0 - # via pytest -py==1.11.0 +pluggy==1.5.0 # via pytest -pyasn1==0.6.0 +pyasn1==0.6.1 # via pyasn1-modules # via rsa -pyasn1-modules==0.4.0 +pyasn1-modules==0.4.1 # via google-auth -pydantic==2.7.1 +pydantic==2.9.2 # via anthropic -pydantic-core==2.18.2 +pydantic-core==2.23.4 # via pydantic pygments==2.18.0 # via rich pyright==1.1.380 -pytest==7.1.1 +pytest==8.3.3 # via pytest-asyncio -pytest-asyncio==0.21.1 +pytest-asyncio==0.24.0 python-dateutil==2.8.2 # via botocore # via time-machine pytz==2023.3.post1 # via dirty-equals -pyyaml==6.0.1 +pyyaml==6.0.2 # via huggingface-hub -requests==2.31.0 +requests==2.32.3 # via huggingface-hub respx==0.20.2 rich==13.7.1 rsa==4.9 # via google-auth ruff==0.6.9 -s3transfer==0.7.0 +s3transfer==0.10.3 # via boto3 setuptools==68.2.2 # via nodeenv @@ -132,18 +129,18 @@ sniffio==1.3.0 # via anyio # via httpx time-machine==2.9.0 -tokenizers==0.14.0 +tokenizers==0.20.1 # via anthropic -tomli==2.0.1 +tomli==2.0.2 # via mypy # via pytest -tqdm==4.66.4 +tqdm==4.66.5 # via huggingface-hub -types-awscrt==0.20.9 +types-awscrt==0.23.0 # via botocore-stubs -types-s3transfer==0.10.1 +types-s3transfer==0.10.3 # via boto3-stubs -typing-extensions==4.8.0 +typing-extensions==4.12.2 # via anthropic # via anyio # via boto3-stubs @@ -151,7 +148,7 @@ typing-extensions==4.8.0 # via mypy # via pydantic # via pydantic-core -urllib3==1.26.18 +urllib3==1.26.20 # via botocore # via requests virtualenv==20.24.5 diff --git a/requirements.lock b/requirements.lock index 80a8d9d4..d0ca469a 100644 --- a/requirements.lock +++ b/requirements.lock @@ -14,29 +14,29 @@ annotated-types==0.6.0 anyio==4.4.0 # via anthropic # via httpx -boto3==1.34.103 +boto3==1.35.49 # via anthropic -botocore==1.34.103 +botocore==1.35.49 # via anthropic # via boto3 # via s3transfer -cachetools==5.3.3 +cachetools==5.5.0 # via google-auth certifi==2023.7.22 # via httpcore # via httpx # via requests -charset-normalizer==3.3.2 +charset-normalizer==3.4.0 # via requests distro==1.8.0 # via anthropic -exceptiongroup==1.1.3 +exceptiongroup==1.2.2 # via anyio -filelock==3.14.0 +filelock==3.16.1 # via huggingface-hub -fsspec==2024.3.1 +fsspec==2024.10.0 # via huggingface-hub -google-auth==2.29.0 +google-auth==2.35.0 # via anthropic h11==0.14.0 # via httpcore @@ -44,37 +44,37 @@ httpcore==1.0.2 # via httpx httpx==0.25.2 # via anthropic -huggingface-hub==0.16.4 +huggingface-hub==0.26.1 # via tokenizers idna==3.4 # via anyio # via httpx # via requests -jiter==0.4.0 +jiter==0.6.1 # via anthropic jmespath==1.0.1 # via boto3 # via botocore -packaging==24.0 +packaging==24.1 # via huggingface-hub -pyasn1==0.6.0 +pyasn1==0.6.1 # via pyasn1-modules # via rsa -pyasn1-modules==0.4.0 +pyasn1-modules==0.4.1 # via google-auth -pydantic==2.7.1 +pydantic==2.9.2 # via anthropic -pydantic-core==2.18.2 +pydantic-core==2.23.4 # via pydantic python-dateutil==2.9.0.post0 # via botocore -pyyaml==6.0.1 +pyyaml==6.0.2 # via huggingface-hub -requests==2.31.0 +requests==2.32.3 # via huggingface-hub rsa==4.9 # via google-auth -s3transfer==0.10.1 +s3transfer==0.10.3 # via boto3 six==1.16.0 # via python-dateutil @@ -82,16 +82,16 @@ sniffio==1.3.0 # via anthropic # via anyio # via httpx -tokenizers==0.14.0 +tokenizers==0.20.1 # via anthropic -tqdm==4.66.4 +tqdm==4.66.5 # via huggingface-hub -typing-extensions==4.8.0 +typing-extensions==4.12.2 # via anthropic # via anyio # via huggingface-hub # via pydantic # via pydantic-core -urllib3==1.26.18 +urllib3==1.26.20 # via botocore # via requests diff --git a/src/anthropic/_compat.py b/src/anthropic/_compat.py index 162a6fbe..d89920d9 100644 --- a/src/anthropic/_compat.py +++ b/src/anthropic/_compat.py @@ -133,7 +133,7 @@ def model_json(model: pydantic.BaseModel, *, indent: int | None = None) -> str: def model_dump( model: pydantic.BaseModel, *, - exclude: IncEx = None, + exclude: IncEx | None = None, exclude_unset: bool = False, exclude_defaults: bool = False, warnings: bool = True, diff --git a/src/anthropic/_models.py b/src/anthropic/_models.py index d386eaa3..42551b76 100644 --- a/src/anthropic/_models.py +++ b/src/anthropic/_models.py @@ -176,7 +176,7 @@ def __str__(self) -> str: # Based on https://github.com/samuelcolvin/pydantic/issues/1168#issuecomment-817742836. @classmethod @override - def construct( + def construct( # pyright: ignore[reportIncompatibleMethodOverride] cls: Type[ModelT], _fields_set: set[str] | None = None, **values: object, @@ -248,8 +248,8 @@ def model_dump( self, *, mode: Literal["json", "python"] | str = "python", - include: IncEx = None, - exclude: IncEx = None, + include: IncEx | None = None, + exclude: IncEx | None = None, by_alias: bool = False, exclude_unset: bool = False, exclude_defaults: bool = False, @@ -303,8 +303,8 @@ def model_dump_json( self, *, indent: int | None = None, - include: IncEx = None, - exclude: IncEx = None, + include: IncEx | None = None, + exclude: IncEx | None = None, by_alias: bool = False, exclude_unset: bool = False, exclude_defaults: bool = False, diff --git a/src/anthropic/_types.py b/src/anthropic/_types.py index ab7f9c21..fd6f305a 100644 --- a/src/anthropic/_types.py +++ b/src/anthropic/_types.py @@ -16,7 +16,7 @@ Optional, Sequence, ) -from typing_extensions import Literal, Protocol, TypeAlias, TypedDict, override, runtime_checkable +from typing_extensions import Set, Literal, Protocol, TypeAlias, TypedDict, override, runtime_checkable import httpx import pydantic @@ -195,7 +195,9 @@ def get(self, __key: str) -> str | None: ... # Note: copied from Pydantic # https://github.com/pydantic/pydantic/blob/32ea570bf96e84234d2992e1ddf40ab8a565925a/pydantic/main.py#L49 -IncEx: TypeAlias = "set[int] | set[str] | dict[int, Any] | dict[str, Any] | None" +IncEx: TypeAlias = Union[ + Set[int], Set[str], Mapping[int, Union["IncEx", Literal[True]]], Mapping[str, Union["IncEx", Literal[True]]] +] PostParser = Callable[[Any], Any] diff --git a/src/anthropic/lib/bedrock/_auth.py b/src/anthropic/lib/bedrock/_auth.py index 99bd35ed..0a8b2109 100644 --- a/src/anthropic/lib/bedrock/_auth.py +++ b/src/anthropic/lib/bedrock/_auth.py @@ -61,6 +61,8 @@ def get_auth_headers( request = AWSRequest(method=method.upper(), url=url, headers=headers, data=data) credentials = session.get_credentials() + if not credentials: + raise RuntimeError("could not resolve credentials from session") signer = SigV4Auth(credentials, "bedrock", session.region_name) signer.add_auth(request) diff --git a/tests/conftest.py b/tests/conftest.py index be676870..09c53153 100644 --- a/tests/conftest.py +++ b/tests/conftest.py @@ -1,11 +1,11 @@ from __future__ import annotations import os -import asyncio import logging from typing import TYPE_CHECKING, Iterator, AsyncIterator import pytest +from pytest_asyncio import is_async_test from anthropic import Anthropic, AsyncAnthropic @@ -17,11 +17,13 @@ logging.getLogger("anthropic").setLevel(logging.DEBUG) -@pytest.fixture(scope="session") -def event_loop() -> Iterator[asyncio.AbstractEventLoop]: - loop = asyncio.new_event_loop() - yield loop - loop.close() +# automatically add `pytest.mark.asyncio()` to all of our async tests +# so we don't have to add that boilerplate everywhere +def pytest_collection_modifyitems(items: list[pytest.Function]) -> None: + pytest_asyncio_tests = (item for item in items if is_async_test(item)) + session_scope_marker = pytest.mark.asyncio(loop_scope="session") + for async_test in pytest_asyncio_tests: + async_test.add_marker(session_scope_marker, append=False) base_url = os.environ.get("TEST_API_BASE_URL", "http://127.0.0.1:4010")