Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

release: 0.9.0 #297

Merged
merged 7 commits into from
Jan 8, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion .release-please-manifest.json
Original file line number Diff line number Diff line change
@@ -1,3 +1,3 @@
{
".": "0.8.1"
".": "0.9.0"
}
21 changes: 21 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -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)
Expand Down
4 changes: 4 additions & 0 deletions examples/.keep
Original file line number Diff line number Diff line change
@@ -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.
19 changes: 11 additions & 8 deletions pyproject.toml
Original file line number Diff line number Diff line change
@@ -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"
Expand All @@ -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"
Expand Down Expand Up @@ -53,7 +54,6 @@ dev-dependencies = [
"pytest",
"pytest-asyncio",
"ruff",
"isort",
"time-machine",
"nox",
"dirty-equals>=0.6.0",
Expand All @@ -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"
Expand Down Expand Up @@ -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
Expand All @@ -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"]
Expand Down
1 change: 0 additions & 1 deletion requirements-dev.lock
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
3 changes: 1 addition & 2 deletions src/anthropic/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -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,
Expand Down
54 changes: 30 additions & 24 deletions src/anthropic/_base_client.py
Original file line number Diff line number Diff line change
Expand Up @@ -48,7 +48,6 @@
Body,
Omit,
Query,
ModelT,
Headers,
Timeout,
NotGiven,
Expand All @@ -58,9 +57,9 @@
PostParser,
ProxiesTypes,
RequestFiles,
HttpxSendArgs,
AsyncTransport,
RequestOptions,
UnknownResponse,
ModelBuilderProtocol,
BinaryResponseContent,
)
Expand Down Expand Up @@ -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.

Expand All @@ -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()
Expand All @@ -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:
Expand All @@ -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
Expand All @@ -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
Expand All @@ -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
Expand All @@ -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,
Expand All @@ -275,20 +274,20 @@ 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:
self._model = model
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
Expand Down Expand Up @@ -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:
Expand Down Expand Up @@ -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:
Expand Down Expand Up @@ -965,7 +968,7 @@ def _retry_request(

def _request_api_list(
self,
model: Type[ModelT],
model: Type[object],
page: Type[SyncPageT],
options: FinalRequestOptions,
) -> SyncPageT:
Expand Down Expand Up @@ -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 = {},
Expand Down Expand Up @@ -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:
Expand Down Expand Up @@ -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
Expand Down Expand Up @@ -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)

Expand Down
15 changes: 10 additions & 5 deletions src/anthropic/_client.py
Original file line number Diff line number Diff line change
Expand Up @@ -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,
Expand Down
Loading