From 6e94884a9a9051c17d7c38686fcc182f48d5d805 Mon Sep 17 00:00:00 2001 From: Stainless Bot <107565488+stainless-bot@users.noreply.github.com> Date: Thu, 22 Feb 2024 15:26:49 -0500 Subject: [PATCH 1/8] chore(internal): update deps (#296) --- .github/workflows/ci.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 2c7d3722..57ebf837 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -14,7 +14,7 @@ jobs: if: github.repository == 'Finch-API/finch-api-python' steps: - - uses: actions/checkout@v3 + - uses: actions/checkout@v4 - name: Install Rye run: | From 8d42399f838fc6274053977c4b648db181199bdf Mon Sep 17 00:00:00 2001 From: Stainless Bot <107565488+stainless-bot@users.noreply.github.com> Date: Fri, 23 Feb 2024 11:34:01 -0500 Subject: [PATCH 2/8] feat(api): make redirect_uri optional (#298) --- src/finch/_client.py | 4 ++-- src/finch/resources/access_tokens.py | 4 ++-- src/finch/types/access_token_create_params.py | 4 ++-- tests/api_resources/test_access_tokens.py | 10 ++-------- 4 files changed, 8 insertions(+), 14 deletions(-) diff --git a/src/finch/_client.py b/src/finch/_client.py index f49ef73e..5b7be7f9 100644 --- a/src/finch/_client.py +++ b/src/finch/_client.py @@ -305,7 +305,7 @@ def get_access_token( self, code: str, *, - redirect_uri: str, + redirect_uri: str | None = None, ) -> str: """Returns an access token for the Finch API given an authorization code. @@ -657,7 +657,7 @@ async def get_access_token( self, code: str, *, - redirect_uri: str, + redirect_uri: str | None = None, ) -> str: """Returns an access token for the Finch API given an authorization code. diff --git a/src/finch/resources/access_tokens.py b/src/finch/resources/access_tokens.py index 6c1f7f82..8ab710c1 100644 --- a/src/finch/resources/access_tokens.py +++ b/src/finch/resources/access_tokens.py @@ -31,9 +31,9 @@ def create( self, *, code: str, - redirect_uri: str, client_id: str | NotGiven = NOT_GIVEN, client_secret: str | NotGiven = NOT_GIVEN, + redirect_uri: str | NotGiven = NOT_GIVEN, # Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs. # The extra values given here take precedence over values defined on the client or passed to this method. extra_headers: Headers | None = None, @@ -98,9 +98,9 @@ async def create( self, *, code: str, - redirect_uri: str, client_id: str | NotGiven = NOT_GIVEN, client_secret: str | NotGiven = NOT_GIVEN, + redirect_uri: str | NotGiven = NOT_GIVEN, # Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs. # The extra values given here take precedence over values defined on the client or passed to this method. extra_headers: Headers | None = None, diff --git a/src/finch/types/access_token_create_params.py b/src/finch/types/access_token_create_params.py index 57412ee2..5935703f 100644 --- a/src/finch/types/access_token_create_params.py +++ b/src/finch/types/access_token_create_params.py @@ -10,8 +10,8 @@ class AccessTokenCreateParams(TypedDict, total=False): code: Required[str] - redirect_uri: Required[str] - client_id: str client_secret: str + + redirect_uri: str diff --git a/tests/api_resources/test_access_tokens.py b/tests/api_resources/test_access_tokens.py index 3abe3e65..e909b979 100644 --- a/tests/api_resources/test_access_tokens.py +++ b/tests/api_resources/test_access_tokens.py @@ -21,7 +21,6 @@ class TestAccessTokens: def test_method_create(self, client: Finch) -> None: access_token = client.access_tokens.create( code="", - redirect_uri="https://example.com", ) assert_matches_type(CreateAccessTokenResponse, access_token, path=["response"]) @@ -29,9 +28,9 @@ def test_method_create(self, client: Finch) -> None: def test_method_create_with_all_params(self, client: Finch) -> None: access_token = client.access_tokens.create( code="", - redirect_uri="https://example.com", client_id="", client_secret="", + redirect_uri="https://example.com", ) assert_matches_type(CreateAccessTokenResponse, access_token, path=["response"]) @@ -39,7 +38,6 @@ def test_method_create_with_all_params(self, client: Finch) -> None: def test_raw_response_create(self, client: Finch) -> None: response = client.access_tokens.with_raw_response.create( code="", - redirect_uri="https://example.com", ) assert response.is_closed is True @@ -51,7 +49,6 @@ def test_raw_response_create(self, client: Finch) -> None: def test_streaming_response_create(self, client: Finch) -> None: with client.access_tokens.with_streaming_response.create( code="", - redirect_uri="https://example.com", ) as response: assert not response.is_closed assert response.http_request.headers.get("X-Stainless-Lang") == "python" @@ -69,7 +66,6 @@ class TestAsyncAccessTokens: async def test_method_create(self, async_client: AsyncFinch) -> None: access_token = await async_client.access_tokens.create( code="", - redirect_uri="https://example.com", ) assert_matches_type(CreateAccessTokenResponse, access_token, path=["response"]) @@ -77,9 +73,9 @@ async def test_method_create(self, async_client: AsyncFinch) -> None: async def test_method_create_with_all_params(self, async_client: AsyncFinch) -> None: access_token = await async_client.access_tokens.create( code="", - redirect_uri="https://example.com", client_id="", client_secret="", + redirect_uri="https://example.com", ) assert_matches_type(CreateAccessTokenResponse, access_token, path=["response"]) @@ -87,7 +83,6 @@ async def test_method_create_with_all_params(self, async_client: AsyncFinch) -> async def test_raw_response_create(self, async_client: AsyncFinch) -> None: response = await async_client.access_tokens.with_raw_response.create( code="", - redirect_uri="https://example.com", ) assert response.is_closed is True @@ -99,7 +94,6 @@ async def test_raw_response_create(self, async_client: AsyncFinch) -> None: async def test_streaming_response_create(self, async_client: AsyncFinch) -> None: async with async_client.access_tokens.with_streaming_response.create( code="", - redirect_uri="https://example.com", ) as response: assert not response.is_closed assert response.http_request.headers.get("X-Stainless-Lang") == "python" From 75e91f636e11472f298ed8796f318b97a15338cc Mon Sep 17 00:00:00 2001 From: Stainless Bot <107565488+stainless-bot@users.noreply.github.com> Date: Mon, 26 Feb 2024 12:12:25 +0100 Subject: [PATCH 3/8] chore(internal): bump pyright (#299) --- requirements-dev.lock | 2 +- src/finch/_models.py | 2 +- src/finch/_utils/_proxy.py | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/requirements-dev.lock b/requirements-dev.lock index c4603027..b00261be 100644 --- a/requirements-dev.lock +++ b/requirements-dev.lock @@ -63,7 +63,7 @@ pydantic==2.4.2 # via finch-api pydantic-core==2.10.1 # via pydantic -pyright==1.1.332 +pyright==1.1.351 pytest==7.1.1 # via pytest-asyncio pytest-asyncio==0.21.1 diff --git a/src/finch/_models.py b/src/finch/_models.py index 48d5624f..81089149 100644 --- a/src/finch/_models.py +++ b/src/finch/_models.py @@ -283,7 +283,7 @@ def construct_type(*, value: object, type_: type) -> object: if is_union(origin): try: - return validate_type(type_=type_, value=value) + return validate_type(type_=cast("type[object]", type_), value=value) except Exception: pass diff --git a/src/finch/_utils/_proxy.py b/src/finch/_utils/_proxy.py index 6f05efcd..b9c12dc3 100644 --- a/src/finch/_utils/_proxy.py +++ b/src/finch/_utils/_proxy.py @@ -45,7 +45,7 @@ def __dir__(self) -> Iterable[str]: @property # type: ignore @override - def __class__(self) -> type: + def __class__(self) -> type: # pyright: ignore proxied = self.__get_proxied__() if issubclass(type(proxied), LazyProxy): return type(proxied) From 3af8e4ca2391a818c4bfafa9d7e0efbf7a7b0d67 Mon Sep 17 00:00:00 2001 From: Stainless Bot <107565488+stainless-bot@users.noreply.github.com> Date: Tue, 27 Feb 2024 15:01:59 +0100 Subject: [PATCH 4/8] chore(client): use anyio.sleep instead of asyncio.sleep (#300) --- src/finch/_resource.py | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/src/finch/_resource.py b/src/finch/_resource.py index f832efb9..99f728b6 100644 --- a/src/finch/_resource.py +++ b/src/finch/_resource.py @@ -3,9 +3,10 @@ from __future__ import annotations import time -import asyncio from typing import TYPE_CHECKING +import anyio + if TYPE_CHECKING: from ._client import Finch, AsyncFinch @@ -39,4 +40,4 @@ def __init__(self, client: AsyncFinch) -> None: self._get_api_list = client.get_api_list async def _sleep(self, seconds: float) -> None: - await asyncio.sleep(seconds) + await anyio.sleep(seconds) From b2552a162373430d773de362982538a0b268dd1f Mon Sep 17 00:00:00 2001 From: Stainless Bot <107565488+stainless-bot@users.noreply.github.com> Date: Thu, 29 Feb 2024 13:32:29 +0100 Subject: [PATCH 5/8] chore(internal): minor core client restructuring (#301) --- src/finch/_base_client.py | 5 ++++- src/finch/_streaming.py | 34 ++++++++++++++++++++++++++++------ 2 files changed, 32 insertions(+), 7 deletions(-) diff --git a/src/finch/_base_client.py b/src/finch/_base_client.py index 73bd2411..dda280f6 100644 --- a/src/finch/_base_client.py +++ b/src/finch/_base_client.py @@ -79,7 +79,7 @@ RAW_RESPONSE_HEADER, OVERRIDE_CAST_TO_HEADER, ) -from ._streaming import Stream, AsyncStream +from ._streaming import Stream, SSEDecoder, AsyncStream, SSEBytesDecoder from ._exceptions import ( APIStatusError, APITimeoutError, @@ -431,6 +431,9 @@ def _prepare_url(self, url: str) -> URL: return merge_url + def _make_sse_decoder(self) -> SSEDecoder | SSEBytesDecoder: + return SSEDecoder() + def _build_request( self, options: FinalRequestOptions, diff --git a/src/finch/_streaming.py b/src/finch/_streaming.py index 4dfad86a..1cd37536 100644 --- a/src/finch/_streaming.py +++ b/src/finch/_streaming.py @@ -5,7 +5,7 @@ import inspect from types import TracebackType from typing import TYPE_CHECKING, Any, Generic, TypeVar, Iterator, AsyncIterator, cast -from typing_extensions import Self, TypeGuard, override, get_origin +from typing_extensions import Self, Protocol, TypeGuard, override, get_origin, runtime_checkable import httpx @@ -23,6 +23,8 @@ class Stream(Generic[_T]): response: httpx.Response + _decoder: SSEDecoder | SSEBytesDecoder + def __init__( self, *, @@ -33,7 +35,7 @@ def __init__( self.response = response self._cast_to = cast_to self._client = client - self._decoder = SSEDecoder() + self._decoder = client._make_sse_decoder() self._iterator = self.__stream__() def __next__(self) -> _T: @@ -44,7 +46,10 @@ def __iter__(self) -> Iterator[_T]: yield item def _iter_events(self) -> Iterator[ServerSentEvent]: - yield from self._decoder.iter(self.response.iter_lines()) + if isinstance(self._decoder, SSEBytesDecoder): + yield from self._decoder.iter_bytes(self.response.iter_bytes()) + else: + yield from self._decoder.iter(self.response.iter_lines()) def __stream__(self) -> Iterator[_T]: cast_to = cast(Any, self._cast_to) @@ -84,6 +89,8 @@ class AsyncStream(Generic[_T]): response: httpx.Response + _decoder: SSEDecoder | SSEBytesDecoder + def __init__( self, *, @@ -94,7 +101,7 @@ def __init__( self.response = response self._cast_to = cast_to self._client = client - self._decoder = SSEDecoder() + self._decoder = client._make_sse_decoder() self._iterator = self.__stream__() async def __anext__(self) -> _T: @@ -105,8 +112,12 @@ async def __aiter__(self) -> AsyncIterator[_T]: yield item async def _iter_events(self) -> AsyncIterator[ServerSentEvent]: - async for sse in self._decoder.aiter(self.response.aiter_lines()): - yield sse + if isinstance(self._decoder, SSEBytesDecoder): + async for sse in self._decoder.aiter_bytes(self.response.aiter_bytes()): + yield sse + else: + async for sse in self._decoder.aiter(self.response.aiter_lines()): + yield sse async def __stream__(self) -> AsyncIterator[_T]: cast_to = cast(Any, self._cast_to) @@ -259,6 +270,17 @@ def decode(self, line: str) -> ServerSentEvent | None: return None +@runtime_checkable +class SSEBytesDecoder(Protocol): + def iter_bytes(self, iterator: Iterator[bytes]) -> Iterator[ServerSentEvent]: + """Given an iterator that yields raw binary data, iterate over it & yield every event encountered""" + ... + + def aiter_bytes(self, iterator: AsyncIterator[bytes]) -> AsyncIterator[ServerSentEvent]: + """Given an async iterator that yields raw binary data, iterate over it & yield every event encountered""" + ... + + def is_stream_class_type(typ: type) -> TypeGuard[type[Stream[object]] | type[AsyncStream[object]]]: """TypeGuard for determining whether or not the given type is a subclass of `Stream` / `AsyncStream`""" origin = get_origin(typ) or typ From 46c5cba7021ca9af3dc0a741c72b3530c4be74f4 Mon Sep 17 00:00:00 2001 From: Stainless Bot <107565488+stainless-bot@users.noreply.github.com> Date: Thu, 29 Feb 2024 17:40:07 +0100 Subject: [PATCH 6/8] docs(contributing): improve wording (#302) --- CONTRIBUTING.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index a99519ea..5cdf4a22 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -82,7 +82,7 @@ pip install ./path-to-wheel-file.whl ## Running tests -Most tests will require you to [setup a mock server](https://github.com/stoplightio/prism) against the OpenAPI spec to run the tests. +Most tests require you to [set up a mock server](https://github.com/stoplightio/prism) against the OpenAPI spec to run the tests. ```bash # you will need npm installed @@ -117,7 +117,7 @@ the changes aren't made through the automated pipeline, you may want to make rel ### Publish with a GitHub workflow -You can release to package managers by using [the `Publish PyPI` GitHub action](https://www.github.com/Finch-API/finch-api-python/actions/workflows/publish-pypi.yml). This will require a setup organization or repository secret to be set up. +You can release to package managers by using [the `Publish PyPI` GitHub action](https://www.github.com/Finch-API/finch-api-python/actions/workflows/publish-pypi.yml). This requires a setup organization or repository secret to be set up. ### Publish manually From f4b2c3c217c226db6af3a8dd11892ae2a95efac6 Mon Sep 17 00:00:00 2001 From: Stainless Bot <107565488+stainless-bot@users.noreply.github.com> Date: Fri, 1 Mar 2024 14:56:51 +0100 Subject: [PATCH 7/8] chore(docs): mention install from git repo (#303) --- CONTRIBUTING.md | 2 +- README.md | 1 + 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index 5cdf4a22..265c3ac7 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -59,7 +59,7 @@ If you’d like to use the repository from source, you can either install from g To install via git: ```bash -pip install git+ssh://git@github.com:Finch-API/finch-api-python.git +pip install git+ssh://git@github.com/Finch-API/finch-api-python.git ``` Alternatively, you can build from source and install the wheel file: diff --git a/README.md b/README.md index ef8230aa..20b3a152 100644 --- a/README.md +++ b/README.md @@ -13,6 +13,7 @@ The REST API documentation can be found [in the Finch Documentation Center](http ## Installation ```sh +# install from PyPI pip install finch-api ``` From de1862d0f1b1ca315a059430352cb75e8cbbd1c6 Mon Sep 17 00:00:00 2001 From: "stainless-app[bot]" <142633134+stainless-app[bot]@users.noreply.github.com> Date: Fri, 1 Mar 2024 13:57:17 +0000 Subject: [PATCH 8/8] release: 0.16.0 --- .release-please-manifest.json | 2 +- CHANGELOG.md | 22 ++++++++++++++++++++++ pyproject.toml | 2 +- src/finch/_version.py | 2 +- 4 files changed, 25 insertions(+), 3 deletions(-) diff --git a/.release-please-manifest.json b/.release-please-manifest.json index 8f3e0a49..b4e9013b 100644 --- a/.release-please-manifest.json +++ b/.release-please-manifest.json @@ -1,3 +1,3 @@ { - ".": "0.15.0" + ".": "0.16.0" } \ No newline at end of file diff --git a/CHANGELOG.md b/CHANGELOG.md index 1b1d127c..4f425764 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,27 @@ # Changelog +## 0.16.0 (2024-03-01) + +Full Changelog: [v0.15.0...v0.16.0](https://github.com/Finch-API/finch-api-python/compare/v0.15.0...v0.16.0) + +### Features + +* **api:** make redirect_uri optional ([#298](https://github.com/Finch-API/finch-api-python/issues/298)) ([8d42399](https://github.com/Finch-API/finch-api-python/commit/8d42399f838fc6274053977c4b648db181199bdf)) + + +### Chores + +* **client:** use anyio.sleep instead of asyncio.sleep ([#300](https://github.com/Finch-API/finch-api-python/issues/300)) ([3af8e4c](https://github.com/Finch-API/finch-api-python/commit/3af8e4ca2391a818c4bfafa9d7e0efbf7a7b0d67)) +* **docs:** mention install from git repo ([#303](https://github.com/Finch-API/finch-api-python/issues/303)) ([f4b2c3c](https://github.com/Finch-API/finch-api-python/commit/f4b2c3c217c226db6af3a8dd11892ae2a95efac6)) +* **internal:** bump pyright ([#299](https://github.com/Finch-API/finch-api-python/issues/299)) ([75e91f6](https://github.com/Finch-API/finch-api-python/commit/75e91f636e11472f298ed8796f318b97a15338cc)) +* **internal:** minor core client restructuring ([#301](https://github.com/Finch-API/finch-api-python/issues/301)) ([b2552a1](https://github.com/Finch-API/finch-api-python/commit/b2552a162373430d773de362982538a0b268dd1f)) +* **internal:** update deps ([#296](https://github.com/Finch-API/finch-api-python/issues/296)) ([6e94884](https://github.com/Finch-API/finch-api-python/commit/6e94884a9a9051c17d7c38686fcc182f48d5d805)) + + +### Documentation + +* **contributing:** improve wording ([#302](https://github.com/Finch-API/finch-api-python/issues/302)) ([46c5cba](https://github.com/Finch-API/finch-api-python/commit/46c5cba7021ca9af3dc0a741c72b3530c4be74f4)) + ## 0.15.0 (2024-02-20) Full Changelog: [v0.14.2...v0.15.0](https://github.com/Finch-API/finch-api-python/compare/v0.14.2...v0.15.0) diff --git a/pyproject.toml b/pyproject.toml index 881ca222..adc8b3c0 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -1,6 +1,6 @@ [project] name = "finch-api" -version = "0.15.0" +version = "0.16.0" description = "The official Python library for the Finch API" readme = "README.md" license = "Apache-2.0" diff --git a/src/finch/_version.py b/src/finch/_version.py index 82f3daa9..0056b453 100644 --- a/src/finch/_version.py +++ b/src/finch/_version.py @@ -1,4 +1,4 @@ # File generated from our OpenAPI spec by Stainless. __title__ = "finch" -__version__ = "0.15.0" # x-release-please-version +__version__ = "0.16.0" # x-release-please-version