diff --git a/.release-please-manifest.json b/.release-please-manifest.json index 2b28d6ec..6d78745c 100644 --- a/.release-please-manifest.json +++ b/.release-please-manifest.json @@ -1,3 +1,3 @@ { - ".": "0.8.1" + ".": "0.9.0" } \ No newline at end of file diff --git a/CHANGELOG.md b/CHANGELOG.md index 0b36bdd8..c260616f 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,26 @@ # Changelog +## 0.9.0 (2024-01-08) + +Full Changelog: [v0.8.1...v0.9.0](https://github.com/anthropics/anthropic-sdk-python/compare/v0.8.1...v0.9.0) + +### Features + +* add `None` default value to nullable response properties ([#299](https://github.com/anthropics/anthropic-sdk-python/issues/299)) ([da423db](https://github.com/anthropics/anthropic-sdk-python/commit/da423db5c14b213c52fe0986981c4f01aff0d2c3)) + + +### Bug Fixes + +* **client:** correctly use custom http client auth ([#296](https://github.com/anthropics/anthropic-sdk-python/issues/296)) ([6289d6e](https://github.com/anthropics/anthropic-sdk-python/commit/6289d6e205f872c02114f05333d5426055f2416f)) + + +### Chores + +* add .keep files for examples and custom code directories ([#302](https://github.com/anthropics/anthropic-sdk-python/issues/302)) ([73a07ea](https://github.com/anthropics/anthropic-sdk-python/commit/73a07ea7a5254d205b68e25c46c1f2267604ac9b)) +* **internal:** loosen type var restrictions ([#301](https://github.com/anthropics/anthropic-sdk-python/issues/301)) ([5e5e1e7](https://github.com/anthropics/anthropic-sdk-python/commit/5e5e1e716a8732af66e2234307521b4620b07361)) +* **internal:** replace isort with ruff ([#298](https://github.com/anthropics/anthropic-sdk-python/issues/298)) ([7c60904](https://github.com/anthropics/anthropic-sdk-python/commit/7c60904f5da10c4ef6ab8af4e8631bc938b35131)) +* use property declarations for resource members ([#300](https://github.com/anthropics/anthropic-sdk-python/issues/300)) ([8671297](https://github.com/anthropics/anthropic-sdk-python/commit/8671297b87105635accefd574c44dbffd8a4f9e9)) + ## 0.8.1 (2023-12-22) Full Changelog: [v0.8.0...v0.8.1](https://github.com/anthropics/anthropic-sdk-python/compare/v0.8.0...v0.8.1) diff --git a/examples/.keep b/examples/.keep new file mode 100644 index 00000000..d8c73e93 --- /dev/null +++ b/examples/.keep @@ -0,0 +1,4 @@ +File generated from our OpenAPI spec by Stainless. + +This directory can be used to store example files demonstrating usage of this SDK. +It is ignored by Stainless code generation and its content (other than this keep file) won't be touched. \ No newline at end of file diff --git a/pyproject.toml b/pyproject.toml index 265ac8e4..8a119ed8 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -1,6 +1,6 @@ [project] name = "anthropic" -version = "0.8.1" +version = "0.9.0" description = "The official Python library for the anthropic API" readme = "README.md" license = "MIT" @@ -14,6 +14,7 @@ dependencies = [ "anyio>=3.5.0, <5", "distro>=1.7.0, <2", "sniffio", + "cached-property; python_version < '3.8'", "tokenizers >= 0.13.0" ] requires-python = ">= 3.7" @@ -53,7 +54,6 @@ dev-dependencies = [ "pytest", "pytest-asyncio", "ruff", - "isort", "time-machine", "nox", "dirty-equals>=0.6.0", @@ -66,7 +66,6 @@ format = { chain = [ "format:ruff", "format:docs", "fix:ruff", - "format:isort", ]} "format:black" = "black ." "format:docs" = "python bin/ruffen-docs.py README.md api.md" @@ -127,16 +126,13 @@ reportImplicitOverride = true reportImportCycles = false reportPrivateUsage = false -[tool.isort] -profile = "black" -length_sort = true -extra_standard_library = ["typing_extensions"] - [tool.ruff] line-length = 120 output-format = "grouped" target-version = "py37" select = [ + # isort + "I", # bugbear rules "B", # remove unused imports @@ -163,6 +159,13 @@ ignore-init-module-imports = true [tool.ruff.format] docstring-code-format = true +[tool.ruff.lint.isort] +length-sort = true +length-sort-straight = true +combine-as-imports = true +extra-standard-library = ["typing_extensions"] +known-first-party = ["anthropic", "tests"] + [tool.ruff.per-file-ignores] "bin/**.py" = ["T201", "T203"] "tests/**.py" = ["T201", "T203"] diff --git a/requirements-dev.lock b/requirements-dev.lock index 59453708..8ff81764 100644 --- a/requirements-dev.lock +++ b/requirements-dev.lock @@ -27,7 +27,6 @@ huggingface-hub==0.16.4 idna==3.4 importlib-metadata==7.0.0 iniconfig==2.0.0 -isort==5.10.1 mypy==1.7.1 mypy-extensions==1.0.0 nodeenv==1.8.0 diff --git a/src/anthropic/__init__.py b/src/anthropic/__init__.py index 6ea55b0b..c1e6bd4c 100644 --- a/src/anthropic/__init__.py +++ b/src/anthropic/__init__.py @@ -15,8 +15,7 @@ RequestOptions, ) from ._version import __title__, __version__ -from ._constants import AI_PROMPT as AI_PROMPT -from ._constants import HUMAN_PROMPT as HUMAN_PROMPT +from ._constants import AI_PROMPT as AI_PROMPT, HUMAN_PROMPT as HUMAN_PROMPT from ._exceptions import ( APIError, ConflictError, diff --git a/src/anthropic/_base_client.py b/src/anthropic/_base_client.py index 481171a4..97c6bef9 100644 --- a/src/anthropic/_base_client.py +++ b/src/anthropic/_base_client.py @@ -48,7 +48,6 @@ Body, Omit, Query, - ModelT, Headers, Timeout, NotGiven, @@ -58,9 +57,9 @@ PostParser, ProxiesTypes, RequestFiles, + HttpxSendArgs, AsyncTransport, RequestOptions, - UnknownResponse, ModelBuilderProtocol, BinaryResponseContent, ) @@ -141,7 +140,7 @@ def __init__( self.params = params -class BasePage(GenericModel, Generic[ModelT]): +class BasePage(GenericModel, Generic[_T]): """ Defines the core interface for pagination. @@ -154,7 +153,7 @@ class BasePage(GenericModel, Generic[ModelT]): """ _options: FinalRequestOptions = PrivateAttr() - _model: Type[ModelT] = PrivateAttr() + _model: Type[_T] = PrivateAttr() def has_next_page(self) -> bool: items = self._get_page_items() @@ -165,7 +164,7 @@ def has_next_page(self) -> bool: def next_page_info(self) -> Optional[PageInfo]: ... - def _get_page_items(self) -> Iterable[ModelT]: # type: ignore[empty-body] + def _get_page_items(self) -> Iterable[_T]: # type: ignore[empty-body] ... def _params_from_url(self, url: URL) -> httpx.QueryParams: @@ -190,13 +189,13 @@ def _info_to_options(self, info: PageInfo) -> FinalRequestOptions: raise ValueError("Unexpected PageInfo state") -class BaseSyncPage(BasePage[ModelT], Generic[ModelT]): +class BaseSyncPage(BasePage[_T], Generic[_T]): _client: SyncAPIClient = pydantic.PrivateAttr() def _set_private_attributes( self, client: SyncAPIClient, - model: Type[ModelT], + model: Type[_T], options: FinalRequestOptions, ) -> None: self._model = model @@ -211,7 +210,7 @@ def _set_private_attributes( # methods should continue to work as expected as there is an alternative method # to cast a model to a dictionary, model.dict(), which is used internally # by pydantic. - def __iter__(self) -> Iterator[ModelT]: # type: ignore + def __iter__(self) -> Iterator[_T]: # type: ignore for page in self.iter_pages(): for item in page._get_page_items(): yield item @@ -236,13 +235,13 @@ def get_next_page(self: SyncPageT) -> SyncPageT: return self._client._request_api_list(self._model, page=self.__class__, options=options) -class AsyncPaginator(Generic[ModelT, AsyncPageT]): +class AsyncPaginator(Generic[_T, AsyncPageT]): def __init__( self, client: AsyncAPIClient, options: FinalRequestOptions, page_cls: Type[AsyncPageT], - model: Type[ModelT], + model: Type[_T], ) -> None: self._model = model self._client = client @@ -265,7 +264,7 @@ def _parser(resp: AsyncPageT) -> AsyncPageT: return await self._client.request(self._page_cls, self._options) - async def __aiter__(self) -> AsyncIterator[ModelT]: + async def __aiter__(self) -> AsyncIterator[_T]: # https://github.com/microsoft/pyright/issues/3464 page = cast( AsyncPageT, @@ -275,12 +274,12 @@ async def __aiter__(self) -> AsyncIterator[ModelT]: yield item -class BaseAsyncPage(BasePage[ModelT], Generic[ModelT]): +class BaseAsyncPage(BasePage[_T], Generic[_T]): _client: AsyncAPIClient = pydantic.PrivateAttr() def _set_private_attributes( self, - model: Type[ModelT], + model: Type[_T], client: AsyncAPIClient, options: FinalRequestOptions, ) -> None: @@ -288,7 +287,7 @@ def _set_private_attributes( self._client = client self._options = options - async def __aiter__(self) -> AsyncIterator[ModelT]: + async def __aiter__(self) -> AsyncIterator[_T]: async for page in self.iter_pages(): for item in page._get_page_items(): yield item @@ -527,7 +526,7 @@ def _process_response_data( if data is None: return cast(ResponseT, None) - if cast_to is UnknownResponse: + if cast_to is object: return cast(ResponseT, data) try: @@ -873,11 +872,15 @@ def _request( request = self._build_request(options) self._prepare_request(request) + kwargs: HttpxSendArgs = {} + if self.custom_auth is not None: + kwargs["auth"] = self.custom_auth + try: response = self._client.send( request, - auth=self.custom_auth, stream=stream or self._should_stream_response_body(request=request), + **kwargs, ) except httpx.TimeoutException as err: if retries > 0: @@ -965,7 +968,7 @@ def _retry_request( def _request_api_list( self, - model: Type[ModelT], + model: Type[object], page: Type[SyncPageT], options: FinalRequestOptions, ) -> SyncPageT: @@ -1127,7 +1130,7 @@ def get_api_list( self, path: str, *, - model: Type[ModelT], + model: Type[object], page: Type[SyncPageT], body: Body | None = None, options: RequestOptions = {}, @@ -1335,11 +1338,15 @@ async def _request( request = self._build_request(options) await self._prepare_request(request) + kwargs: HttpxSendArgs = {} + if self.custom_auth is not None: + kwargs["auth"] = self.custom_auth + try: response = await self._client.send( request, - auth=self.custom_auth, stream=stream or self._should_stream_response_body(request=request), + **kwargs, ) except httpx.TimeoutException as err: if retries > 0: @@ -1425,10 +1432,10 @@ async def _retry_request( def _request_api_list( self, - model: Type[ModelT], + model: Type[_T], page: Type[AsyncPageT], options: FinalRequestOptions, - ) -> AsyncPaginator[ModelT, AsyncPageT]: + ) -> AsyncPaginator[_T, AsyncPageT]: return AsyncPaginator(client=self, options=options, page_cls=page, model=model) @overload @@ -1575,13 +1582,12 @@ def get_api_list( self, path: str, *, - # TODO: support paginating `str` - model: Type[ModelT], + model: Type[_T], page: Type[AsyncPageT], body: Body | None = None, options: RequestOptions = {}, method: str = "get", - ) -> AsyncPaginator[ModelT, AsyncPageT]: + ) -> AsyncPaginator[_T, AsyncPageT]: opts = FinalRequestOptions.construct(method=method, url=path, json_data=body, **options) return self._request_api_list(model, page, opts) diff --git a/src/anthropic/_client.py b/src/anthropic/_client.py index 2785e7c6..fea68224 100644 --- a/src/anthropic/_client.py +++ b/src/anthropic/_client.py @@ -21,13 +21,18 @@ AsyncTransport, RequestOptions, ) -from ._utils import is_given, get_async_library +from ._utils import ( + is_given, + get_async_library, +) from ._version import __version__ -from ._streaming import Stream as Stream -from ._streaming import AsyncStream as AsyncStream +from ._streaming import Stream as Stream, AsyncStream as AsyncStream from ._exceptions import APIStatusError -from ._tokenizers import TokenizerType # type: ignore[import] -from ._tokenizers import sync_get_tokenizer, async_get_tokenizer +from ._tokenizers import ( + TokenizerType, # type: ignore[import] + sync_get_tokenizer, + async_get_tokenizer, +) from ._base_client import ( DEFAULT_LIMITS, DEFAULT_MAX_RETRIES, diff --git a/src/anthropic/_compat.py b/src/anthropic/_compat.py index 34323c9b..3cda3990 100644 --- a/src/anthropic/_compat.py +++ b/src/anthropic/_compat.py @@ -43,21 +43,23 @@ def is_typeddict(type_: type[Any]) -> bool: # noqa: ARG001 else: if PYDANTIC_V2: - from pydantic.v1.typing import get_args as get_args - from pydantic.v1.typing import is_union as is_union - from pydantic.v1.typing import get_origin as get_origin - from pydantic.v1.typing import is_typeddict as is_typeddict - from pydantic.v1.typing import is_literal_type as is_literal_type - from pydantic.v1.datetime_parse import parse_date as parse_date - from pydantic.v1.datetime_parse import parse_datetime as parse_datetime + from pydantic.v1.typing import ( + get_args as get_args, + is_union as is_union, + get_origin as get_origin, + is_typeddict as is_typeddict, + is_literal_type as is_literal_type, + ) + from pydantic.v1.datetime_parse import parse_date as parse_date, parse_datetime as parse_datetime else: - from pydantic.typing import get_args as get_args - from pydantic.typing import is_union as is_union - from pydantic.typing import get_origin as get_origin - from pydantic.typing import is_typeddict as is_typeddict - from pydantic.typing import is_literal_type as is_literal_type - from pydantic.datetime_parse import parse_date as parse_date - from pydantic.datetime_parse import parse_datetime as parse_datetime + from pydantic.typing import ( + get_args as get_args, + is_union as is_union, + get_origin as get_origin, + is_typeddict as is_typeddict, + is_literal_type as is_literal_type, + ) + from pydantic.datetime_parse import parse_date as parse_date, parse_datetime as parse_datetime # refactored config @@ -171,3 +173,13 @@ class GenericModel(pydantic.BaseModel): class GenericModel(pydantic.generics.GenericModel, pydantic.BaseModel): ... + + +# cached properties +if TYPE_CHECKING: + cached_property = property +else: + try: + from functools import cached_property as cached_property + except ImportError: + from cached_property import cached_property as cached_property diff --git a/src/anthropic/_models.py b/src/anthropic/_models.py index 330a2064..48d5624f 100644 --- a/src/anthropic/_models.py +++ b/src/anthropic/_models.py @@ -30,17 +30,11 @@ AnyMapping, HttpxRequestFiles, ) -from ._utils import ( - is_list, - is_given, - is_mapping, - parse_date, - parse_datetime, - strip_not_given, -) -from ._compat import PYDANTIC_V2, ConfigDict -from ._compat import GenericModel as BaseGenericModel +from ._utils import is_list, is_given, is_mapping, parse_date, parse_datetime, strip_not_given from ._compat import ( + PYDANTIC_V2, + ConfigDict, + GenericModel as BaseGenericModel, get_args, is_union, parse_obj, diff --git a/src/anthropic/_response.py b/src/anthropic/_response.py index 3fc3f293..bfe3895b 100644 --- a/src/anthropic/_response.py +++ b/src/anthropic/_response.py @@ -9,7 +9,7 @@ import httpx -from ._types import NoneType, UnknownResponse, BinaryResponseContent +from ._types import NoneType, BinaryResponseContent from ._utils import is_given, extract_type_var_from_base from ._models import BaseModel, is_basemodel from ._constants import RAW_RESPONSE_HEADER @@ -162,7 +162,7 @@ def _parse(self) -> R: # `ResponseT` TypeVar, however if that TypeVar is ever updated in the future, then # this function would become unsafe but a type checker would not report an error. if ( - cast_to is not UnknownResponse + cast_to is not object and not origin is list and not origin is dict and not origin is Union diff --git a/src/anthropic/_types.py b/src/anthropic/_types.py index 8372db4f..35cc62e1 100644 --- a/src/anthropic/_types.py +++ b/src/anthropic/_types.py @@ -19,15 +19,9 @@ Sequence, AsyncIterator, ) -from typing_extensions import ( - Literal, - Protocol, - TypeAlias, - TypedDict, - override, - runtime_checkable, -) +from typing_extensions import Literal, Protocol, TypeAlias, TypedDict, override, runtime_checkable +import httpx import pydantic from httpx import URL, Proxy, Timeout, Response, BaseTransport, AsyncBaseTransport @@ -264,11 +258,6 @@ class RequestOptions(TypedDict, total=False): idempotency_key: str -# Sentinel class used when the response type is an object with an unknown schema -class UnknownResponse: - ... - - # Sentinel class used until PEP 0661 is accepted class NotGiven: """ @@ -345,7 +334,17 @@ def get(self, __key: str) -> str | None: ResponseT = TypeVar( "ResponseT", - bound="Union[str, None, BaseModel, List[Any], Dict[str, Any], Response, UnknownResponse, ModelBuilderProtocol, BinaryResponseContent]", + bound=Union[ + object, + str, + None, + "BaseModel", + List[Any], + Dict[str, Any], + Response, + ModelBuilderProtocol, + BinaryResponseContent, + ], ) StrBytesIntFloat = Union[str, bytes, int, float] @@ -369,3 +368,7 @@ class InheritsGeneric(Protocol): class _GenericAlias(Protocol): __origin__: type[object] + + +class HttpxSendArgs(TypedDict, total=False): + auth: httpx.Auth diff --git a/src/anthropic/_utils/__init__.py b/src/anthropic/_utils/__init__.py index a43201d3..2dcfc122 100644 --- a/src/anthropic/_utils/__init__.py +++ b/src/anthropic/_utils/__init__.py @@ -1,40 +1,45 @@ from ._proxy import LazyProxy as LazyProxy -from ._utils import flatten as flatten -from ._utils import is_dict as is_dict -from ._utils import is_list as is_list -from ._utils import is_given as is_given -from ._utils import is_tuple as is_tuple -from ._utils import is_mapping as is_mapping -from ._utils import is_tuple_t as is_tuple_t -from ._utils import parse_date as parse_date -from ._utils import is_sequence as is_sequence -from ._utils import coerce_float as coerce_float -from ._utils import is_mapping_t as is_mapping_t -from ._utils import removeprefix as removeprefix -from ._utils import removesuffix as removesuffix -from ._utils import extract_files as extract_files -from ._utils import is_sequence_t as is_sequence_t -from ._utils import required_args as required_args -from ._utils import coerce_boolean as coerce_boolean -from ._utils import coerce_integer as coerce_integer -from ._utils import file_from_path as file_from_path -from ._utils import parse_datetime as parse_datetime -from ._utils import strip_not_given as strip_not_given -from ._utils import deepcopy_minimal as deepcopy_minimal -from ._utils import get_async_library as get_async_library -from ._utils import maybe_coerce_float as maybe_coerce_float -from ._utils import get_required_header as get_required_header -from ._utils import maybe_coerce_boolean as maybe_coerce_boolean -from ._utils import maybe_coerce_integer as maybe_coerce_integer -from ._typing import is_list_type as is_list_type -from ._typing import is_union_type as is_union_type -from ._typing import extract_type_arg as extract_type_arg -from ._typing import is_required_type as is_required_type -from ._typing import is_annotated_type as is_annotated_type -from ._typing import strip_annotated_type as strip_annotated_type -from ._typing import extract_type_var_from_base as extract_type_var_from_base -from ._streams import consume_sync_iterator as consume_sync_iterator -from ._streams import consume_async_iterator as consume_async_iterator -from ._transform import PropertyInfo as PropertyInfo -from ._transform import transform as transform -from ._transform import maybe_transform as maybe_transform +from ._utils import ( + flatten as flatten, + is_dict as is_dict, + is_list as is_list, + is_given as is_given, + is_tuple as is_tuple, + is_mapping as is_mapping, + is_tuple_t as is_tuple_t, + parse_date as parse_date, + is_sequence as is_sequence, + coerce_float as coerce_float, + is_mapping_t as is_mapping_t, + removeprefix as removeprefix, + removesuffix as removesuffix, + extract_files as extract_files, + is_sequence_t as is_sequence_t, + required_args as required_args, + coerce_boolean as coerce_boolean, + coerce_integer as coerce_integer, + file_from_path as file_from_path, + parse_datetime as parse_datetime, + strip_not_given as strip_not_given, + deepcopy_minimal as deepcopy_minimal, + get_async_library as get_async_library, + maybe_coerce_float as maybe_coerce_float, + get_required_header as get_required_header, + maybe_coerce_boolean as maybe_coerce_boolean, + maybe_coerce_integer as maybe_coerce_integer, +) +from ._typing import ( + is_list_type as is_list_type, + is_union_type as is_union_type, + extract_type_arg as extract_type_arg, + is_required_type as is_required_type, + is_annotated_type as is_annotated_type, + strip_annotated_type as strip_annotated_type, + extract_type_var_from_base as extract_type_var_from_base, +) +from ._streams import consume_sync_iterator as consume_sync_iterator, consume_async_iterator as consume_async_iterator +from ._transform import ( + PropertyInfo as PropertyInfo, + transform as transform, + maybe_transform as maybe_transform, +) diff --git a/src/anthropic/_utils/_transform.py b/src/anthropic/_utils/_transform.py index 342b5241..3a1c1496 100644 --- a/src/anthropic/_utils/_transform.py +++ b/src/anthropic/_utils/_transform.py @@ -6,7 +6,10 @@ import pydantic -from ._utils import is_list, is_mapping +from ._utils import ( + is_list, + is_mapping, +) from ._typing import ( is_list_type, is_union_type, diff --git a/src/anthropic/_utils/_utils.py b/src/anthropic/_utils/_utils.py index cc624b0c..1c5c21a8 100644 --- a/src/anthropic/_utils/_utils.py +++ b/src/anthropic/_utils/_utils.py @@ -21,8 +21,7 @@ import sniffio from .._types import Headers, NotGiven, FileTypes, NotGivenOr, HeadersLike -from .._compat import parse_date as parse_date -from .._compat import parse_datetime as parse_datetime +from .._compat import parse_date as parse_date, parse_datetime as parse_datetime _T = TypeVar("_T") _TupleT = TypeVar("_TupleT", bound=Tuple[object, ...]) diff --git a/src/anthropic/_version.py b/src/anthropic/_version.py index 9703c64f..17bb7b81 100644 --- a/src/anthropic/_version.py +++ b/src/anthropic/_version.py @@ -1,4 +1,4 @@ # File generated from our OpenAPI spec by Stainless. __title__ = "anthropic" -__version__ = "0.8.1" # x-release-please-version +__version__ = "0.9.0" # x-release-please-version diff --git a/src/anthropic/lib/.keep b/src/anthropic/lib/.keep new file mode 100644 index 00000000..5e2c99fd --- /dev/null +++ b/src/anthropic/lib/.keep @@ -0,0 +1,4 @@ +File generated from our OpenAPI spec by Stainless. + +This directory can be used to store custom files to expand the SDK. +It is ignored by Stainless code generation and its content (other than this keep file) won't be touched. \ No newline at end of file diff --git a/src/anthropic/lib/streaming/__init__.py b/src/anthropic/lib/streaming/__init__.py index 642cc33a..71c5efd6 100644 --- a/src/anthropic/lib/streaming/__init__.py +++ b/src/anthropic/lib/streaming/__init__.py @@ -1,6 +1,8 @@ -from ._messages import MessageStream as MessageStream -from ._messages import MessageStreamT as MessageStreamT -from ._messages import AsyncMessageStream as AsyncMessageStream -from ._messages import AsyncMessageStreamT as AsyncMessageStreamT -from ._messages import MessageStreamManager as MessageStreamManager -from ._messages import AsyncMessageStreamManager as AsyncMessageStreamManager +from ._messages import ( + MessageStream as MessageStream, + MessageStreamT as MessageStreamT, + AsyncMessageStream as AsyncMessageStream, + AsyncMessageStreamT as AsyncMessageStreamT, + MessageStreamManager as MessageStreamManager, + AsyncMessageStreamManager as AsyncMessageStreamManager, +) diff --git a/src/anthropic/resources/__init__.py b/src/anthropic/resources/__init__.py index c47cc0e9..d39ac2ed 100644 --- a/src/anthropic/resources/__init__.py +++ b/src/anthropic/resources/__init__.py @@ -1,12 +1,7 @@ # File generated from our OpenAPI spec by Stainless. from .beta import Beta, AsyncBeta, BetaWithRawResponse, AsyncBetaWithRawResponse -from .completions import ( - Completions, - AsyncCompletions, - CompletionsWithRawResponse, - AsyncCompletionsWithRawResponse, -) +from .completions import Completions, AsyncCompletions, CompletionsWithRawResponse, AsyncCompletionsWithRawResponse __all__ = [ "Completions", diff --git a/src/anthropic/resources/beta/__init__.py b/src/anthropic/resources/beta/__init__.py index aae168a4..ef10de5d 100644 --- a/src/anthropic/resources/beta/__init__.py +++ b/src/anthropic/resources/beta/__init__.py @@ -1,12 +1,7 @@ # File generated from our OpenAPI spec by Stainless. from .beta import Beta, AsyncBeta, BetaWithRawResponse, AsyncBetaWithRawResponse -from .messages import ( - Messages, - AsyncMessages, - MessagesWithRawResponse, - AsyncMessagesWithRawResponse, -) +from .messages import Messages, AsyncMessages, MessagesWithRawResponse, AsyncMessagesWithRawResponse __all__ = [ "Messages", diff --git a/src/anthropic/resources/beta/beta.py b/src/anthropic/resources/beta/beta.py index 5d472172..ab63ff8b 100644 --- a/src/anthropic/resources/beta/beta.py +++ b/src/anthropic/resources/beta/beta.py @@ -2,40 +2,31 @@ from __future__ import annotations -from typing import TYPE_CHECKING - -from .messages import ( - Messages, - AsyncMessages, - MessagesWithRawResponse, - AsyncMessagesWithRawResponse, -) +from .messages import Messages, AsyncMessages, MessagesWithRawResponse, AsyncMessagesWithRawResponse +from ..._compat import cached_property from ..._resource import SyncAPIResource, AsyncAPIResource -if TYPE_CHECKING: - from ..._client import Anthropic, AsyncAnthropic - __all__ = ["Beta", "AsyncBeta"] class Beta(SyncAPIResource): - messages: Messages - with_raw_response: BetaWithRawResponse + @cached_property + def messages(self) -> Messages: + return Messages(self._client) - def __init__(self, client: Anthropic) -> None: - super().__init__(client) - self.messages = Messages(client) - self.with_raw_response = BetaWithRawResponse(self) + @cached_property + def with_raw_response(self) -> BetaWithRawResponse: + return BetaWithRawResponse(self) class AsyncBeta(AsyncAPIResource): - messages: AsyncMessages - with_raw_response: AsyncBetaWithRawResponse + @cached_property + def messages(self) -> AsyncMessages: + return AsyncMessages(self._client) - def __init__(self, client: AsyncAnthropic) -> None: - super().__init__(client) - self.messages = AsyncMessages(client) - self.with_raw_response = AsyncBetaWithRawResponse(self) + @cached_property + def with_raw_response(self) -> AsyncBetaWithRawResponse: + return AsyncBetaWithRawResponse(self) class BetaWithRawResponse: diff --git a/src/anthropic/resources/beta/messages.py b/src/anthropic/resources/beta/messages.py index 5a516622..d6408f44 100644 --- a/src/anthropic/resources/beta/messages.py +++ b/src/anthropic/resources/beta/messages.py @@ -2,7 +2,7 @@ from __future__ import annotations -from typing import TYPE_CHECKING, List, overload +from typing import List, overload from functools import partial from typing_extensions import Literal @@ -10,16 +10,14 @@ from ..._types import NOT_GIVEN, Body, Query, Headers, NotGiven from ..._utils import required_args, maybe_transform +from ..._compat import cached_property from ..._resource import SyncAPIResource, AsyncAPIResource from ..._response import to_raw_response_wrapper, async_to_raw_response_wrapper from ..._streaming import Stream, AsyncStream -from ...types.beta import ( - Message, - MessageParam, - MessageStreamEvent, - message_create_params, +from ...types.beta import Message, MessageParam, MessageStreamEvent, message_create_params +from ..._base_client import ( + make_request_options, ) -from ..._base_client import make_request_options from ...lib.streaming import ( MessageStream, MessageStreamT, @@ -29,18 +27,13 @@ AsyncMessageStreamManager, ) -if TYPE_CHECKING: - from ..._client import Anthropic, AsyncAnthropic - __all__ = ["Messages", "AsyncMessages"] class Messages(SyncAPIResource): - with_raw_response: MessagesWithRawResponse - - def __init__(self, client: Anthropic) -> None: - super().__init__(client) - self.with_raw_response = MessagesWithRawResponse(self) + @cached_property + def with_raw_response(self) -> MessagesWithRawResponse: + return MessagesWithRawResponse(self) @overload def create( @@ -663,11 +656,9 @@ def stream( class AsyncMessages(AsyncAPIResource): - with_raw_response: AsyncMessagesWithRawResponse - - def __init__(self, client: AsyncAnthropic) -> None: - super().__init__(client) - self.with_raw_response = AsyncMessagesWithRawResponse(self) + @cached_property + def with_raw_response(self) -> AsyncMessagesWithRawResponse: + return AsyncMessagesWithRawResponse(self) @overload async def create( diff --git a/src/anthropic/resources/completions.py b/src/anthropic/resources/completions.py index 17916130..d14052c6 100644 --- a/src/anthropic/resources/completions.py +++ b/src/anthropic/resources/completions.py @@ -2,7 +2,7 @@ from __future__ import annotations -from typing import TYPE_CHECKING, List, Union, overload +from typing import List, Union, overload from typing_extensions import Literal import httpx @@ -10,23 +10,21 @@ from ..types import Completion, completion_create_params from .._types import NOT_GIVEN, Body, Query, Headers, NotGiven from .._utils import required_args, maybe_transform +from .._compat import cached_property from .._resource import SyncAPIResource, AsyncAPIResource from .._response import to_raw_response_wrapper, async_to_raw_response_wrapper from .._streaming import Stream, AsyncStream -from .._base_client import make_request_options - -if TYPE_CHECKING: - from .._client import Anthropic, AsyncAnthropic +from .._base_client import ( + make_request_options, +) __all__ = ["Completions", "AsyncCompletions"] class Completions(SyncAPIResource): - with_raw_response: CompletionsWithRawResponse - - def __init__(self, client: Anthropic) -> None: - super().__init__(client) - self.with_raw_response = CompletionsWithRawResponse(self) + @cached_property + def with_raw_response(self) -> CompletionsWithRawResponse: + return CompletionsWithRawResponse(self) @overload def create( @@ -359,11 +357,9 @@ def create( class AsyncCompletions(AsyncAPIResource): - with_raw_response: AsyncCompletionsWithRawResponse - - def __init__(self, client: AsyncAnthropic) -> None: - super().__init__(client) - self.with_raw_response = AsyncCompletionsWithRawResponse(self) + @cached_property + def with_raw_response(self) -> AsyncCompletionsWithRawResponse: + return AsyncCompletionsWithRawResponse(self) @overload async def create( diff --git a/src/anthropic/types/beta/message.py b/src/anthropic/types/beta/message.py index af82cb5a..0b3bd3bd 100644 --- a/src/anthropic/types/beta/message.py +++ b/src/anthropic/types/beta/message.py @@ -63,7 +63,7 @@ class Message(BaseModel): This will always be `"assistant"`. """ - stop_reason: Optional[Literal["end_turn", "max_tokens", "stop_sequence"]] + stop_reason: Optional[Literal["end_turn", "max_tokens", "stop_sequence"]] = None """The reason that we stopped. This may be one the following values: @@ -79,7 +79,7 @@ class Message(BaseModel): null in the `message_start` event and non-null otherwise. """ - stop_sequence: Optional[str] + stop_sequence: Optional[str] = None """Which custom stop sequence was generated. This value will be non-null if one of your custom stop sequences was generated. diff --git a/src/anthropic/types/beta/message_delta_event.py b/src/anthropic/types/beta/message_delta_event.py index 54b441ab..fc291cf4 100644 --- a/src/anthropic/types/beta/message_delta_event.py +++ b/src/anthropic/types/beta/message_delta_event.py @@ -9,9 +9,9 @@ class Delta(BaseModel): - stop_reason: Optional[Literal["end_turn", "max_tokens", "stop_sequence"]] + stop_reason: Optional[Literal["end_turn", "max_tokens", "stop_sequence"]] = None - stop_sequence: Optional[str] + stop_sequence: Optional[str] = None class MessageDeltaEvent(BaseModel): diff --git a/tests/test_client.py b/tests/test_client.py index 2fe4afe6..53bc3cc5 100644 --- a/tests/test_client.py +++ b/tests/test_client.py @@ -21,11 +21,7 @@ from anthropic._client import Anthropic, AsyncAnthropic from anthropic._models import BaseModel, FinalRequestOptions from anthropic._streaming import Stream, AsyncStream -from anthropic._exceptions import ( - APIStatusError, - APITimeoutError, - APIResponseValidationError, -) +from anthropic._exceptions import APIStatusError, APITimeoutError, APIResponseValidationError from anthropic._base_client import ( DEFAULT_TIMEOUT, HTTPX_DEFAULT_TIMEOUT, diff --git a/tests/utils.py b/tests/utils.py index 3a5830b4..4c9df902 100644 --- a/tests/utils.py +++ b/tests/utils.py @@ -8,7 +8,12 @@ from typing_extensions import Literal, get_args, get_origin, assert_type from anthropic._types import NoneType -from anthropic._utils import is_dict, is_list, is_list_type, is_union_type +from anthropic._utils import ( + is_dict, + is_list, + is_list_type, + is_union_type, +) from anthropic._compat import PYDANTIC_V2, field_outer_type, get_model_fields from anthropic._models import BaseModel