From 6322114c6e752686d4d3f502df94339037a44698 Mon Sep 17 00:00:00 2001 From: Stainless Bot <107565488+stainless-bot@users.noreply.github.com> Date: Fri, 3 Nov 2023 05:24:56 +0000 Subject: [PATCH 01/11] feat(client): allow binary returns (#164) --- src/finch/_base_client.py | 93 +++++++++++++++++++++++ src/finch/_response.py | 5 +- src/finch/_types.py | 151 +++++++++++++++++++++++++++++++++++++- tests/test_client.py | 31 +++++++- 4 files changed, 273 insertions(+), 7 deletions(-) diff --git a/src/finch/_base_client.py b/src/finch/_base_client.py index 5ed9f54d..5354c488 100644 --- a/src/finch/_base_client.py +++ b/src/finch/_base_client.py @@ -1,5 +1,6 @@ from __future__ import annotations +import os import json import time import uuid @@ -60,6 +61,7 @@ RequestOptions, UnknownResponse, ModelBuilderProtocol, + BinaryResponseContent, ) from ._utils import is_dict, is_given, is_mapping from ._compat import model_copy, model_dump @@ -1672,3 +1674,94 @@ def _merge_mappings( """ merged = {**obj1, **obj2} return {key: value for key, value in merged.items() if not isinstance(value, Omit)} + + +class HttpxBinaryResponseContent(BinaryResponseContent): + response: httpx.Response + + def __init__(self, response: httpx.Response) -> None: + self.response = response + + @property + @override + def content(self) -> bytes: + return self.response.content + + @property + @override + def text(self) -> str: + return self.response.text + + @property + @override + def encoding(self) -> Optional[str]: + return self.response.encoding + + @property + @override + def charset_encoding(self) -> Optional[str]: + return self.response.charset_encoding + + @override + def json(self, **kwargs: Any) -> Any: + return self.response.json(**kwargs) + + @override + def read(self) -> bytes: + return self.response.read() + + @override + def iter_bytes(self, chunk_size: Optional[int] = None) -> Iterator[bytes]: + return self.response.iter_bytes(chunk_size) + + @override + def iter_text(self, chunk_size: Optional[int] = None) -> Iterator[str]: + return self.response.iter_text(chunk_size) + + @override + def iter_lines(self) -> Iterator[str]: + return self.response.iter_lines() + + @override + def iter_raw(self, chunk_size: Optional[int] = None) -> Iterator[bytes]: + return self.response.iter_raw(chunk_size) + + @override + def stream_to_file(self, file: str | os.PathLike[str]) -> None: + with open(file, mode="wb") as f: + for data in self.response.iter_bytes(): + f.write(data) + + @override + def close(self) -> None: + return self.response.close() + + @override + async def aread(self) -> bytes: + return await self.response.aread() + + @override + async def aiter_bytes(self, chunk_size: Optional[int] = None) -> AsyncIterator[bytes]: + return self.response.aiter_bytes(chunk_size) + + @override + async def aiter_text(self, chunk_size: Optional[int] = None) -> AsyncIterator[str]: + return self.response.aiter_text(chunk_size) + + @override + async def aiter_lines(self) -> AsyncIterator[str]: + return self.response.aiter_lines() + + @override + async def aiter_raw(self, chunk_size: Optional[int] = None) -> AsyncIterator[bytes]: + return self.response.aiter_raw(chunk_size) + + @override + async def astream_to_file(self, file: str | os.PathLike[str]) -> None: + with open(file, mode="wb") as f: + async for data in self.response.aiter_bytes(): + f.write(data) + + @override + async def aclose(self) -> None: + return await self.response.aclose() diff --git a/src/finch/_response.py b/src/finch/_response.py index 7939edaa..11eb3199 100644 --- a/src/finch/_response.py +++ b/src/finch/_response.py @@ -9,7 +9,7 @@ import httpx import pydantic -from ._types import NoneType, UnknownResponse +from ._types import NoneType, UnknownResponse, BinaryResponseContent from ._utils import is_given from ._models import BaseModel from ._constants import RAW_RESPONSE_HEADER @@ -135,6 +135,9 @@ def _parse(self) -> R: origin = get_origin(cast_to) or cast_to + if inspect.isclass(origin) and issubclass(origin, BinaryResponseContent): + return cast(R, cast_to(response)) # type: ignore + if origin == APIResponse: raise RuntimeError("Unexpected state - cast_to is `APIResponse`") diff --git a/src/finch/_types.py b/src/finch/_types.py index ef5e84c5..2f024cbe 100644 --- a/src/finch/_types.py +++ b/src/finch/_types.py @@ -1,6 +1,7 @@ from __future__ import annotations from os import PathLike +from abc import ABC, abstractmethod from typing import ( IO, TYPE_CHECKING, @@ -13,8 +14,10 @@ Mapping, TypeVar, Callable, + Iterator, Optional, Sequence, + AsyncIterator, ) from typing_extensions import ( Literal, @@ -25,7 +28,6 @@ runtime_checkable, ) -import httpx import pydantic from httpx import URL, Proxy, Timeout, Response, BaseTransport, AsyncBaseTransport @@ -40,6 +42,151 @@ ModelT = TypeVar("ModelT", bound=pydantic.BaseModel) _T = TypeVar("_T") + +class BinaryResponseContent(ABC): + def __init__( + self, + response: Any, + ) -> None: + ... + + @property + @abstractmethod + def content(self) -> bytes: + pass + + @property + @abstractmethod + def text(self) -> str: + pass + + @property + @abstractmethod + def encoding(self) -> Optional[str]: + """ + Return an encoding to use for decoding the byte content into text. + The priority for determining this is given by... + + * `.encoding = <>` has been set explicitly. + * The encoding as specified by the charset parameter in the Content-Type header. + * The encoding as determined by `default_encoding`, which may either be + a string like "utf-8" indicating the encoding to use, or may be a callable + which enables charset autodetection. + """ + pass + + @property + @abstractmethod + def charset_encoding(self) -> Optional[str]: + """ + Return the encoding, as specified by the Content-Type header. + """ + pass + + @abstractmethod + def json(self, **kwargs: Any) -> Any: + pass + + @abstractmethod + def read(self) -> bytes: + """ + Read and return the response content. + """ + pass + + @abstractmethod + def iter_bytes(self, chunk_size: Optional[int] = None) -> Iterator[bytes]: + """ + A byte-iterator over the decoded response content. + This allows us to handle gzip, deflate, and brotli encoded responses. + """ + pass + + @abstractmethod + def iter_text(self, chunk_size: Optional[int] = None) -> Iterator[str]: + """ + A str-iterator over the decoded response content + that handles both gzip, deflate, etc but also detects the content's + string encoding. + """ + pass + + @abstractmethod + def iter_lines(self) -> Iterator[str]: + pass + + @abstractmethod + def iter_raw(self, chunk_size: Optional[int] = None) -> Iterator[bytes]: + """ + A byte-iterator over the raw response content. + """ + pass + + @abstractmethod + def stream_to_file(self, file: str | PathLike[str]) -> None: + """ + Stream the output to the given file. + """ + pass + + @abstractmethod + def close(self) -> None: + """ + Close the response and release the connection. + Automatically called if the response body is read to completion. + """ + pass + + @abstractmethod + async def aread(self) -> bytes: + """ + Read and return the response content. + """ + pass + + @abstractmethod + async def aiter_bytes(self, chunk_size: Optional[int] = None) -> AsyncIterator[bytes]: + """ + A byte-iterator over the decoded response content. + This allows us to handle gzip, deflate, and brotli encoded responses. + """ + pass + + @abstractmethod + async def aiter_text(self, chunk_size: Optional[int] = None) -> AsyncIterator[str]: + """ + A str-iterator over the decoded response content + that handles both gzip, deflate, etc but also detects the content's + string encoding. + """ + pass + + @abstractmethod + async def aiter_lines(self) -> AsyncIterator[str]: + pass + + @abstractmethod + async def aiter_raw(self, chunk_size: Optional[int] = None) -> AsyncIterator[bytes]: + """ + A byte-iterator over the raw response content. + """ + pass + + async def astream_to_file(self, file: str | PathLike[str]) -> None: + """ + Stream the output to the given file. + """ + pass + + @abstractmethod + async def aclose(self) -> None: + """ + Close the response and release the connection. + Automatically called if the response body is read to completion. + """ + pass + + # Approximates httpx internal ProxiesTypes and RequestFiles types # while adding support for `PathLike` instances ProxiesDict = Dict["str | URL", Union[None, str, URL, Proxy]] @@ -181,7 +328,7 @@ def get(self, __key: str) -> str | None: ResponseT = TypeVar( "ResponseT", - bound="Union[str, None, BaseModel, List[Any], Dict[str, Any], httpx.Response, UnknownResponse, ModelBuilderProtocol]", + bound="Union[str, None, BaseModel, List[Any], Dict[str, Any], Response, UnknownResponse, ModelBuilderProtocol, BinaryResponseContent]", ) StrBytesIntFloat = Union[str, bytes, int, float] diff --git a/tests/test_client.py b/tests/test_client.py index c7766520..d2644f51 100644 --- a/tests/test_client.py +++ b/tests/test_client.py @@ -41,12 +41,23 @@ class TestFinch: @pytest.mark.respx(base_url=base_url) def test_raw_response(self, respx_mock: MockRouter) -> None: - respx_mock.post("/foo").mock(return_value=httpx.Response(200, json={"foo": "bar"})) + respx_mock.post("/foo").mock(return_value=httpx.Response(200, json='{"foo": "bar"}')) response = self.client.post("/foo", cast_to=httpx.Response) assert response.status_code == 200 assert isinstance(response, httpx.Response) - assert response.json() == {"foo": "bar"} + assert response.json() == '{"foo": "bar"}' + + @pytest.mark.respx(base_url=base_url) + def test_raw_response_for_binary(self, respx_mock: MockRouter) -> None: + respx_mock.post("/foo").mock( + return_value=httpx.Response(200, headers={"Content-Type": "application/binary"}, content='{"foo": "bar"}') + ) + + response = self.client.post("/foo", cast_to=httpx.Response) + assert response.status_code == 200 + assert isinstance(response, httpx.Response) + assert response.json() == '{"foo": "bar"}' def test_copy(self) -> None: copied = self.client.copy() @@ -672,12 +683,24 @@ class TestAsyncFinch: @pytest.mark.respx(base_url=base_url) @pytest.mark.asyncio async def test_raw_response(self, respx_mock: MockRouter) -> None: - respx_mock.post("/foo").mock(return_value=httpx.Response(200, json={"foo": "bar"})) + respx_mock.post("/foo").mock(return_value=httpx.Response(200, json='{"foo": "bar"}')) + + response = await self.client.post("/foo", cast_to=httpx.Response) + assert response.status_code == 200 + assert isinstance(response, httpx.Response) + assert response.json() == '{"foo": "bar"}' + + @pytest.mark.respx(base_url=base_url) + @pytest.mark.asyncio + async def test_raw_response_for_binary(self, respx_mock: MockRouter) -> None: + respx_mock.post("/foo").mock( + return_value=httpx.Response(200, headers={"Content-Type": "application/binary"}, content='{"foo": "bar"}') + ) response = await self.client.post("/foo", cast_to=httpx.Response) assert response.status_code == 200 assert isinstance(response, httpx.Response) - assert response.json() == {"foo": "bar"} + assert response.json() == '{"foo": "bar"}' def test_copy(self) -> None: copied = self.client.copy() From f3e7e763c9e1809b6d84e78720465a96daa11ec2 Mon Sep 17 00:00:00 2001 From: Stainless Bot <107565488+stainless-bot@users.noreply.github.com> Date: Fri, 3 Nov 2023 10:47:26 +0000 Subject: [PATCH 02/11] feat(client): support passing BaseModels to request params at runtime (#166) --- src/finch/_utils/_transform.py | 7 +++++- tests/test_transform.py | 46 +++++++++++++++++++++++++++++++++- 2 files changed, 51 insertions(+), 2 deletions(-) diff --git a/src/finch/_utils/_transform.py b/src/finch/_utils/_transform.py index d524b329..db40bff2 100644 --- a/src/finch/_utils/_transform.py +++ b/src/finch/_utils/_transform.py @@ -4,6 +4,8 @@ from datetime import date, datetime from typing_extensions import Literal, get_args, override, get_type_hints +import pydantic + from ._utils import ( is_list, is_mapping, @@ -14,7 +16,7 @@ is_annotated_type, strip_annotated_type, ) -from .._compat import is_typeddict +from .._compat import model_dump, is_typeddict _T = TypeVar("_T") @@ -165,6 +167,9 @@ def _transform_recursive( data = _transform_recursive(data, annotation=annotation, inner_type=subtype) return data + if isinstance(data, pydantic.BaseModel): + return model_dump(data, exclude_unset=True, exclude_defaults=True) + return _transform_value(data, annotation) diff --git a/tests/test_transform.py b/tests/test_transform.py index 5becb2f8..83a905bb 100644 --- a/tests/test_transform.py +++ b/tests/test_transform.py @@ -1,10 +1,13 @@ from __future__ import annotations -from typing import List, Union, Optional +from typing import Any, List, Union, Optional from datetime import date, datetime from typing_extensions import Required, Annotated, TypedDict +import pytest + from finch._utils import PropertyInfo, transform, parse_datetime +from finch._models import BaseModel class Foo1(TypedDict): @@ -186,3 +189,44 @@ class DateDictWithRequiredAlias(TypedDict, total=False): def test_datetime_with_alias() -> None: assert transform({"required_prop": None}, DateDictWithRequiredAlias) == {"prop": None} # type: ignore[comparison-overlap] assert transform({"required_prop": date.fromisoformat("2023-02-23")}, DateDictWithRequiredAlias) == {"prop": "2023-02-23"} # type: ignore[comparison-overlap] + + +class MyModel(BaseModel): + foo: str + + +def test_pydantic_model_to_dictionary() -> None: + assert transform(MyModel(foo="hi!"), Any) == {"foo": "hi!"} + assert transform(MyModel.construct(foo="hi!"), Any) == {"foo": "hi!"} + + +def test_pydantic_empty_model() -> None: + assert transform(MyModel.construct(), Any) == {} + + +def test_pydantic_unknown_field() -> None: + assert transform(MyModel.construct(my_untyped_field=True), Any) == {"my_untyped_field": True} + + +def test_pydantic_mismatched_types() -> None: + model = MyModel.construct(foo=True) + with pytest.warns(UserWarning): + params = transform(model, Any) + assert params == {"foo": True} + + +def test_pydantic_mismatched_object_type() -> None: + model = MyModel.construct(foo=MyModel.construct(hello="world")) + with pytest.warns(UserWarning): + params = transform(model, Any) + assert params == {"foo": {"hello": "world"}} + + +class ModelNestedObjects(BaseModel): + nested: MyModel + + +def test_pydantic_nested_objects() -> None: + model = ModelNestedObjects.construct(nested={"foo": "stainless"}) + assert isinstance(model.nested, MyModel) + assert transform(model, Any) == {"nested": {"foo": "stainless"}} From c607d545379a03d0926aef998e246fd33009d716 Mon Sep 17 00:00:00 2001 From: Stainless Bot <107565488+stainless-bot@users.noreply.github.com> Date: Fri, 3 Nov 2023 16:49:05 +0000 Subject: [PATCH 03/11] fix(binaries): don't synchronously block in astream_to_file (#167) --- src/finch/_base_client.py | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/src/finch/_base_client.py b/src/finch/_base_client.py index 5354c488..22f90050 100644 --- a/src/finch/_base_client.py +++ b/src/finch/_base_client.py @@ -1758,9 +1758,10 @@ async def aiter_raw(self, chunk_size: Optional[int] = None) -> AsyncIterator[byt @override async def astream_to_file(self, file: str | os.PathLike[str]) -> None: - with open(file, mode="wb") as f: + path = anyio.Path(file) + async with await path.open(mode="wb") as f: async for data in self.response.aiter_bytes(): - f.write(data) + await f.write(data) @override async def aclose(self) -> None: From 69faf737601c196eb3fa53fa2575c9c3a53a0d28 Mon Sep 17 00:00:00 2001 From: Stainless Bot <107565488+stainless-bot@users.noreply.github.com> Date: Fri, 3 Nov 2023 22:16:31 +0000 Subject: [PATCH 04/11] chore(internal): remove unused int/float conversion (#168) --- src/finch/_models.py | 15 ++++++--------- src/finch/pagination.py | 6 ++++-- tests/test_models.py | 29 ++++++++++++++++++++--------- 3 files changed, 30 insertions(+), 20 deletions(-) diff --git a/src/finch/_models.py b/src/finch/_models.py index 40245ac9..00d787ca 100644 --- a/src/finch/_models.py +++ b/src/finch/_models.py @@ -313,16 +313,13 @@ def construct_type(*, value: object, type_: type) -> object: return [construct_type(value=entry, type_=inner_type) for entry in value] if origin == float: - try: - return float(cast(Any, value)) - except Exception: - return value + if isinstance(value, int): + coerced = float(value) + if coerced != value: + return value + return coerced - if origin == int: - try: - return int(cast(Any, value)) - except Exception: - return value + return value if type_ == datetime: try: diff --git a/src/finch/pagination.py b/src/finch/pagination.py index 8162b275..3cb9ed96 100644 --- a/src/finch/pagination.py +++ b/src/finch/pagination.py @@ -41,9 +41,10 @@ def next_page_info(self) -> None: @classmethod def build(cls: Type[_BaseModelT], *, response: Response, data: object) -> _BaseModelT: # noqa: ARG003 return cls.construct( + None, **{ **(cast(Mapping[str, Any], data) if is_mapping(data) else {"items": data}), - } + }, ) @@ -65,9 +66,10 @@ def next_page_info(self) -> None: @classmethod def build(cls: Type[_BaseModelT], *, response: Response, data: object) -> _BaseModelT: # noqa: ARG003 return cls.construct( + None, **{ **(cast(Mapping[str, Any], data) if is_mapping(data) else {"items": data}), - } + }, ) diff --git a/tests/test_models.py b/tests/test_models.py index e9d5cac4..ecdf47a1 100644 --- a/tests/test_models.py +++ b/tests/test_models.py @@ -439,21 +439,32 @@ class Model(BaseModel): assert model_json(model) == expected_json -def test_coerces_int() -> None: +def test_does_not_coerce_int() -> None: class Model(BaseModel): bar: int assert Model.construct(bar=1).bar == 1 - assert Model.construct(bar=10.9).bar == 10 - assert Model.construct(bar="19").bar == 19 - assert Model.construct(bar=False).bar == 0 + assert Model.construct(bar=10.9).bar == 10.9 + assert Model.construct(bar="19").bar == "19" # type: ignore[comparison-overlap] + assert Model.construct(bar=False).bar is False - # TODO: support this - # assert Model.construct(bar="True").bar == 1 - # mismatched types are left as-is - m = Model.construct(bar={"foo": "bar"}) - assert m.bar == {"foo": "bar"} # type: ignore[comparison-overlap] +def test_int_to_float_safe_conversion() -> None: + class Model(BaseModel): + float_field: float + + m = Model.construct(float_field=10) + assert m.float_field == 10.0 + assert isinstance(m.float_field, float) + + m = Model.construct(float_field=10.12) + assert m.float_field == 10.12 + assert isinstance(m.float_field, float) + + # number too big + m = Model.construct(float_field=2**53 + 1) + assert m.float_field == 2**53 + 1 + assert isinstance(m.float_field, int) def test_deprecated_alias() -> None: From 37fe0007d4c1643a14aae4e580ebebf537963399 Mon Sep 17 00:00:00 2001 From: Stainless Bot <107565488+stainless-bot@users.noreply.github.com> Date: Sun, 5 Nov 2023 14:16:41 +0000 Subject: [PATCH 05/11] docs(readme): improve example snippets (#169) --- README.md | 30 +++++++++++------------------- 1 file changed, 11 insertions(+), 19 deletions(-) diff --git a/README.md b/README.md index 43877d82..4b53b968 100644 --- a/README.md +++ b/README.md @@ -27,11 +27,8 @@ client = Finch( access_token="My Access Token", ) -page = client.hris.directory.list( - candidate_id="", -) -directory = page.individuals[0] -print(directory.first_name) +page = client.hris.directory.list() +print(page.page) ``` ## Async usage @@ -39,6 +36,7 @@ print(directory.first_name) Simply import `AsyncFinch` instead of `Finch` and use `await` with each API call: ```python +import asyncio from finch import AsyncFinch client = AsyncFinch( @@ -46,11 +44,9 @@ client = AsyncFinch( ) -async def main(): - page = await client.hris.directory.list( - candidate_id="", - ) - print(page.individuals[0].first_name) +async def main() -> None: + page = await client.hris.directory.list() + print(page.page) asyncio.run(main()) @@ -138,10 +134,8 @@ from finch import Finch client = Finch() -client.hris.directory.list( - path_params=[], - params={}, -) +page = client.hris.directory.list() +print(page.page) ``` ## Webhook Verification @@ -183,7 +177,7 @@ from finch import Finch client = Finch() try: - client.hris.directory.list() + client.hris.company.retrieve() except finch.APIConnectionError as e: print("The server could not be reached") print(e.__cause__) # an underlying Exception, likely raised within httpx. @@ -304,13 +298,11 @@ The "raw" Response object can be accessed by prefixing `.with_raw_response.` to from finch import Finch client = Finch() -page = client.hris.directory.with_raw_response.list() -response = page.individuals[0] - +response = client.hris.directory.with_raw_response.list() print(response.headers.get('X-My-Header')) directory = response.parse() # get the object that `hris.directory.list()` would have returned -print(directory.first_name) +print(directory.id) ``` These methods return an [`APIResponse`](https://github.com/Finch-API/finch-api-python/src/finch/_response.py) object. From fc12d835d80d6d7f076aa81ecfb5fcc318c80261 Mon Sep 17 00:00:00 2001 From: Stainless Bot <107565488+stainless-bot@users.noreply.github.com> Date: Mon, 6 Nov 2023 03:20:08 +0000 Subject: [PATCH 06/11] fix: prevent TypeError in Python 3.8 (ABC is not subscriptable) (#170) --- src/finch/_types.py | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/src/finch/_types.py b/src/finch/_types.py index 2f024cbe..1fd2729a 100644 --- a/src/finch/_types.py +++ b/src/finch/_types.py @@ -191,7 +191,10 @@ async def aclose(self) -> None: # while adding support for `PathLike` instances ProxiesDict = Dict["str | URL", Union[None, str, URL, Proxy]] ProxiesTypes = Union[str, Proxy, ProxiesDict] -FileContent = Union[IO[bytes], bytes, PathLike[str]] +if TYPE_CHECKING: + FileContent = Union[IO[bytes], bytes, PathLike[str]] +else: + FileContent = Union[IO[bytes], bytes, PathLike] # PathLike is not subscriptable in Python 3.8. FileTypes = Union[ # file (or bytes) FileContent, From a3dcd4b1add4499894bfc4f63dfe3f46b9a3a2e9 Mon Sep 17 00:00:00 2001 From: Stainless Bot <107565488+stainless-bot@users.noreply.github.com> Date: Mon, 6 Nov 2023 21:22:24 +0000 Subject: [PATCH 07/11] feat(client): support passing httpx.Timeout to method timeout argument (#171) --- src/finch/_base_client.py | 2 +- src/finch/resources/account.py | 10 +++++---- src/finch/resources/hris/benefits/benefits.py | 22 ++++++++++--------- .../resources/hris/benefits/individuals.py | 18 ++++++++------- src/finch/resources/hris/company.py | 6 +++-- src/finch/resources/hris/directory.py | 10 +++++---- src/finch/resources/hris/employments.py | 6 +++-- src/finch/resources/hris/individuals.py | 6 +++-- src/finch/resources/hris/pay_statements.py | 6 +++-- src/finch/resources/hris/payments.py | 6 +++-- src/finch/resources/providers.py | 6 +++-- src/finch/resources/request_forwarding.py | 6 +++-- 12 files changed, 63 insertions(+), 41 deletions(-) diff --git a/src/finch/_base_client.py b/src/finch/_base_client.py index 22f90050..e37759cd 100644 --- a/src/finch/_base_client.py +++ b/src/finch/_base_client.py @@ -1537,7 +1537,7 @@ def make_request_options( extra_query: Query | None = None, extra_body: Body | None = None, idempotency_key: str | None = None, - timeout: float | None | NotGiven = NOT_GIVEN, + timeout: float | httpx.Timeout | None | NotGiven = NOT_GIVEN, post_parser: PostParser | NotGiven = NOT_GIVEN, ) -> RequestOptions: """Create a dict of type RequestOptions without keys of NotGiven values.""" diff --git a/src/finch/resources/account.py b/src/finch/resources/account.py index 18fe7744..5d90dfdc 100644 --- a/src/finch/resources/account.py +++ b/src/finch/resources/account.py @@ -4,6 +4,8 @@ from typing import TYPE_CHECKING +import httpx + from ..types import Introspection, DisconnectResponse from .._types import NOT_GIVEN, Body, Query, Headers, NotGiven from .._resource import SyncAPIResource, AsyncAPIResource @@ -31,7 +33,7 @@ def disconnect( extra_headers: Headers | None = None, extra_query: Query | None = None, extra_body: Body | None = None, - timeout: float | None | NotGiven = NOT_GIVEN, + timeout: float | httpx.Timeout | None | NotGiven = NOT_GIVEN, ) -> DisconnectResponse: """ Disconnect an employer from your application and invalidate all `access_token`s @@ -54,7 +56,7 @@ def introspect( extra_headers: Headers | None = None, extra_query: Query | None = None, extra_body: Body | None = None, - timeout: float | None | NotGiven = NOT_GIVEN, + timeout: float | httpx.Timeout | None | NotGiven = NOT_GIVEN, ) -> Introspection: """Read account information associated with an `access_token`""" return self._get( @@ -81,7 +83,7 @@ async def disconnect( extra_headers: Headers | None = None, extra_query: Query | None = None, extra_body: Body | None = None, - timeout: float | None | NotGiven = NOT_GIVEN, + timeout: float | httpx.Timeout | None | NotGiven = NOT_GIVEN, ) -> DisconnectResponse: """ Disconnect an employer from your application and invalidate all `access_token`s @@ -104,7 +106,7 @@ async def introspect( extra_headers: Headers | None = None, extra_query: Query | None = None, extra_body: Body | None = None, - timeout: float | None | NotGiven = NOT_GIVEN, + timeout: float | httpx.Timeout | None | NotGiven = NOT_GIVEN, ) -> Introspection: """Read account information associated with an `access_token`""" return await self._get( diff --git a/src/finch/resources/hris/benefits/benefits.py b/src/finch/resources/hris/benefits/benefits.py index c48dd78d..f90a5100 100644 --- a/src/finch/resources/hris/benefits/benefits.py +++ b/src/finch/resources/hris/benefits/benefits.py @@ -4,6 +4,8 @@ from typing import TYPE_CHECKING, Optional +import httpx + from ...._types import NOT_GIVEN, Body, Query, Headers, NotGiven from ...._utils import maybe_transform from .individuals import ( @@ -53,7 +55,7 @@ def create( extra_headers: Headers | None = None, extra_query: Query | None = None, extra_body: Body | None = None, - timeout: float | None | NotGiven = NOT_GIVEN, + timeout: float | httpx.Timeout | None | NotGiven = NOT_GIVEN, ) -> CreateCompanyBenefitsResponse: """ **Availability: Automated and Assisted Benefits providers** @@ -97,7 +99,7 @@ def retrieve( extra_headers: Headers | None = None, extra_query: Query | None = None, extra_body: Body | None = None, - timeout: float | None | NotGiven = NOT_GIVEN, + timeout: float | httpx.Timeout | None | NotGiven = NOT_GIVEN, ) -> CompanyBenefit: """ **Availability: Automated Benefits providers only** @@ -131,7 +133,7 @@ def update( extra_headers: Headers | None = None, extra_query: Query | None = None, extra_body: Body | None = None, - timeout: float | None | NotGiven = NOT_GIVEN, + timeout: float | httpx.Timeout | None | NotGiven = NOT_GIVEN, ) -> UpdateCompanyBenefitResponse: """ **Availability: Automated and Assisted Benefits providers** @@ -166,7 +168,7 @@ def list( extra_headers: Headers | None = None, extra_query: Query | None = None, extra_body: Body | None = None, - timeout: float | None | NotGiven = NOT_GIVEN, + timeout: float | httpx.Timeout | None | NotGiven = NOT_GIVEN, ) -> SyncSinglePage[CompanyBenefit]: """ **Availability: Automated Benefits providers only** @@ -190,7 +192,7 @@ def list_supported_benefits( extra_headers: Headers | None = None, extra_query: Query | None = None, extra_body: Body | None = None, - timeout: float | None | NotGiven = NOT_GIVEN, + timeout: float | httpx.Timeout | None | NotGiven = NOT_GIVEN, ) -> SyncSinglePage[SupportedBenefit]: """ **Availability: Automated and Assisted Benefits providers** @@ -228,7 +230,7 @@ async def create( extra_headers: Headers | None = None, extra_query: Query | None = None, extra_body: Body | None = None, - timeout: float | None | NotGiven = NOT_GIVEN, + timeout: float | httpx.Timeout | None | NotGiven = NOT_GIVEN, ) -> CreateCompanyBenefitsResponse: """ **Availability: Automated and Assisted Benefits providers** @@ -272,7 +274,7 @@ async def retrieve( extra_headers: Headers | None = None, extra_query: Query | None = None, extra_body: Body | None = None, - timeout: float | None | NotGiven = NOT_GIVEN, + timeout: float | httpx.Timeout | None | NotGiven = NOT_GIVEN, ) -> CompanyBenefit: """ **Availability: Automated Benefits providers only** @@ -306,7 +308,7 @@ async def update( extra_headers: Headers | None = None, extra_query: Query | None = None, extra_body: Body | None = None, - timeout: float | None | NotGiven = NOT_GIVEN, + timeout: float | httpx.Timeout | None | NotGiven = NOT_GIVEN, ) -> UpdateCompanyBenefitResponse: """ **Availability: Automated and Assisted Benefits providers** @@ -341,7 +343,7 @@ def list( extra_headers: Headers | None = None, extra_query: Query | None = None, extra_body: Body | None = None, - timeout: float | None | NotGiven = NOT_GIVEN, + timeout: float | httpx.Timeout | None | NotGiven = NOT_GIVEN, ) -> AsyncPaginator[CompanyBenefit, AsyncSinglePage[CompanyBenefit]]: """ **Availability: Automated Benefits providers only** @@ -365,7 +367,7 @@ def list_supported_benefits( extra_headers: Headers | None = None, extra_query: Query | None = None, extra_body: Body | None = None, - timeout: float | None | NotGiven = NOT_GIVEN, + timeout: float | httpx.Timeout | None | NotGiven = NOT_GIVEN, ) -> AsyncPaginator[SupportedBenefit, AsyncSinglePage[SupportedBenefit]]: """ **Availability: Automated and Assisted Benefits providers** diff --git a/src/finch/resources/hris/benefits/individuals.py b/src/finch/resources/hris/benefits/individuals.py index 8219ab1d..fb4b3450 100644 --- a/src/finch/resources/hris/benefits/individuals.py +++ b/src/finch/resources/hris/benefits/individuals.py @@ -4,6 +4,8 @@ from typing import TYPE_CHECKING, List +import httpx + from ...._types import NOT_GIVEN, Body, Query, Headers, NotGiven from ...._utils import maybe_transform from ...._resource import SyncAPIResource, AsyncAPIResource @@ -43,7 +45,7 @@ def enroll_many( extra_headers: Headers | None = None, extra_query: Query | None = None, extra_body: Body | None = None, - timeout: float | None | NotGiven = NOT_GIVEN, + timeout: float | httpx.Timeout | None | NotGiven = NOT_GIVEN, ) -> SyncSinglePage[EnrolledIndividual]: """ **Availability: Automated and Assisted Benefits providers** @@ -88,7 +90,7 @@ def enrolled_ids( extra_headers: Headers | None = None, extra_query: Query | None = None, extra_body: Body | None = None, - timeout: float | None | NotGiven = NOT_GIVEN, + timeout: float | httpx.Timeout | None | NotGiven = NOT_GIVEN, ) -> IndividualEnrolledIDsResponse: """ **Availability: Automated Benefits providers only** @@ -122,7 +124,7 @@ def retrieve_many_benefits( extra_headers: Headers | None = None, extra_query: Query | None = None, extra_body: Body | None = None, - timeout: float | None | NotGiven = NOT_GIVEN, + timeout: float | httpx.Timeout | None | NotGiven = NOT_GIVEN, ) -> SyncSinglePage[IndividualBenefit]: """ **Availability: Automated Benefits providers only** @@ -167,7 +169,7 @@ def unenroll_many( extra_headers: Headers | None = None, extra_query: Query | None = None, extra_body: Body | None = None, - timeout: float | None | NotGiven = NOT_GIVEN, + timeout: float | httpx.Timeout | None | NotGiven = NOT_GIVEN, ) -> SyncSinglePage[UnenrolledIndividual]: """ **Availability: Automated and Assisted Benefits providers** @@ -216,7 +218,7 @@ def enroll_many( extra_headers: Headers | None = None, extra_query: Query | None = None, extra_body: Body | None = None, - timeout: float | None | NotGiven = NOT_GIVEN, + timeout: float | httpx.Timeout | None | NotGiven = NOT_GIVEN, ) -> AsyncPaginator[EnrolledIndividual, AsyncSinglePage[EnrolledIndividual]]: """ **Availability: Automated and Assisted Benefits providers** @@ -261,7 +263,7 @@ async def enrolled_ids( extra_headers: Headers | None = None, extra_query: Query | None = None, extra_body: Body | None = None, - timeout: float | None | NotGiven = NOT_GIVEN, + timeout: float | httpx.Timeout | None | NotGiven = NOT_GIVEN, ) -> IndividualEnrolledIDsResponse: """ **Availability: Automated Benefits providers only** @@ -295,7 +297,7 @@ def retrieve_many_benefits( extra_headers: Headers | None = None, extra_query: Query | None = None, extra_body: Body | None = None, - timeout: float | None | NotGiven = NOT_GIVEN, + timeout: float | httpx.Timeout | None | NotGiven = NOT_GIVEN, ) -> AsyncPaginator[IndividualBenefit, AsyncSinglePage[IndividualBenefit]]: """ **Availability: Automated Benefits providers only** @@ -340,7 +342,7 @@ def unenroll_many( extra_headers: Headers | None = None, extra_query: Query | None = None, extra_body: Body | None = None, - timeout: float | None | NotGiven = NOT_GIVEN, + timeout: float | httpx.Timeout | None | NotGiven = NOT_GIVEN, ) -> AsyncPaginator[UnenrolledIndividual, AsyncSinglePage[UnenrolledIndividual]]: """ **Availability: Automated and Assisted Benefits providers** diff --git a/src/finch/resources/hris/company.py b/src/finch/resources/hris/company.py index 651c153d..af6d6441 100644 --- a/src/finch/resources/hris/company.py +++ b/src/finch/resources/hris/company.py @@ -4,6 +4,8 @@ from typing import TYPE_CHECKING +import httpx + from ..._types import NOT_GIVEN, Body, Query, Headers, NotGiven from ..._resource import SyncAPIResource, AsyncAPIResource from ..._response import to_raw_response_wrapper, async_to_raw_response_wrapper @@ -31,7 +33,7 @@ def retrieve( extra_headers: Headers | None = None, extra_query: Query | None = None, extra_body: Body | None = None, - timeout: float | None | NotGiven = NOT_GIVEN, + timeout: float | httpx.Timeout | None | NotGiven = NOT_GIVEN, ) -> Company: """Read basic company data""" return self._get( @@ -58,7 +60,7 @@ async def retrieve( extra_headers: Headers | None = None, extra_query: Query | None = None, extra_body: Body | None = None, - timeout: float | None | NotGiven = NOT_GIVEN, + timeout: float | httpx.Timeout | None | NotGiven = NOT_GIVEN, ) -> Company: """Read basic company data""" return await self._get( diff --git a/src/finch/resources/hris/directory.py b/src/finch/resources/hris/directory.py index 69c39ac5..ff3950aa 100644 --- a/src/finch/resources/hris/directory.py +++ b/src/finch/resources/hris/directory.py @@ -5,6 +5,8 @@ import typing_extensions from typing import TYPE_CHECKING +import httpx + from ..._types import NOT_GIVEN, Body, Query, Headers, NotGiven from ..._utils import maybe_transform from ..._resource import SyncAPIResource, AsyncAPIResource @@ -36,7 +38,7 @@ def list( extra_headers: Headers | None = None, extra_query: Query | None = None, extra_body: Body | None = None, - timeout: float | None | NotGiven = NOT_GIVEN, + timeout: float | httpx.Timeout | None | NotGiven = NOT_GIVEN, ) -> SyncIndividualsPage[IndividualInDirectory]: """ Read company directory and organization structure @@ -84,7 +86,7 @@ def list_individuals( extra_headers: Headers | None = None, extra_query: Query | None = None, extra_body: Body | None = None, - timeout: float | None | NotGiven = NOT_GIVEN, + timeout: float | httpx.Timeout | None | NotGiven = NOT_GIVEN, ) -> SyncIndividualsPage[IndividualInDirectory]: """ Read company directory and organization structure @@ -129,7 +131,7 @@ def list( extra_headers: Headers | None = None, extra_query: Query | None = None, extra_body: Body | None = None, - timeout: float | None | NotGiven = NOT_GIVEN, + timeout: float | httpx.Timeout | None | NotGiven = NOT_GIVEN, ) -> AsyncPaginator[IndividualInDirectory, AsyncIndividualsPage[IndividualInDirectory]]: """ Read company directory and organization structure @@ -177,7 +179,7 @@ def list_individuals( extra_headers: Headers | None = None, extra_query: Query | None = None, extra_body: Body | None = None, - timeout: float | None | NotGiven = NOT_GIVEN, + timeout: float | httpx.Timeout | None | NotGiven = NOT_GIVEN, ) -> AsyncPaginator[IndividualInDirectory, AsyncIndividualsPage[IndividualInDirectory]]: """ Read company directory and organization structure diff --git a/src/finch/resources/hris/employments.py b/src/finch/resources/hris/employments.py index d41a531e..0b16202e 100644 --- a/src/finch/resources/hris/employments.py +++ b/src/finch/resources/hris/employments.py @@ -4,6 +4,8 @@ from typing import TYPE_CHECKING, List +import httpx + from ..._types import NOT_GIVEN, Body, Query, Headers, NotGiven from ..._utils import maybe_transform from ..._resource import SyncAPIResource, AsyncAPIResource @@ -34,7 +36,7 @@ def retrieve_many( extra_headers: Headers | None = None, extra_query: Query | None = None, extra_body: Body | None = None, - timeout: float | None | NotGiven = NOT_GIVEN, + timeout: float | httpx.Timeout | None | NotGiven = NOT_GIVEN, ) -> SyncResponsesPage[EmploymentDataResponse]: """ Read individual employment and income data @@ -82,7 +84,7 @@ def retrieve_many( extra_headers: Headers | None = None, extra_query: Query | None = None, extra_body: Body | None = None, - timeout: float | None | NotGiven = NOT_GIVEN, + timeout: float | httpx.Timeout | None | NotGiven = NOT_GIVEN, ) -> AsyncPaginator[EmploymentDataResponse, AsyncResponsesPage[EmploymentDataResponse]]: """ Read individual employment and income data diff --git a/src/finch/resources/hris/individuals.py b/src/finch/resources/hris/individuals.py index 34622c26..892eb820 100644 --- a/src/finch/resources/hris/individuals.py +++ b/src/finch/resources/hris/individuals.py @@ -4,6 +4,8 @@ from typing import TYPE_CHECKING, List, Optional +import httpx + from ..._types import NOT_GIVEN, Body, Query, Headers, NotGiven from ..._utils import maybe_transform from ..._resource import SyncAPIResource, AsyncAPIResource @@ -35,7 +37,7 @@ def retrieve_many( extra_headers: Headers | None = None, extra_query: Query | None = None, extra_body: Body | None = None, - timeout: float | None | NotGiven = NOT_GIVEN, + timeout: float | httpx.Timeout | None | NotGiven = NOT_GIVEN, ) -> SyncResponsesPage[IndividualResponse]: """ Read individual data, excluding income and employment data @@ -84,7 +86,7 @@ def retrieve_many( extra_headers: Headers | None = None, extra_query: Query | None = None, extra_body: Body | None = None, - timeout: float | None | NotGiven = NOT_GIVEN, + timeout: float | httpx.Timeout | None | NotGiven = NOT_GIVEN, ) -> AsyncPaginator[IndividualResponse, AsyncResponsesPage[IndividualResponse]]: """ Read individual data, excluding income and employment data diff --git a/src/finch/resources/hris/pay_statements.py b/src/finch/resources/hris/pay_statements.py index 242cb846..4c444e9b 100644 --- a/src/finch/resources/hris/pay_statements.py +++ b/src/finch/resources/hris/pay_statements.py @@ -4,6 +4,8 @@ from typing import TYPE_CHECKING, List +import httpx + from ..._types import NOT_GIVEN, Body, Query, Headers, NotGiven from ..._utils import maybe_transform from ..._resource import SyncAPIResource, AsyncAPIResource @@ -34,7 +36,7 @@ def retrieve_many( extra_headers: Headers | None = None, extra_query: Query | None = None, extra_body: Body | None = None, - timeout: float | None | NotGiven = NOT_GIVEN, + timeout: float | httpx.Timeout | None | NotGiven = NOT_GIVEN, ) -> SyncResponsesPage[PayStatementResponse]: """ Read detailed pay statements for each individual. @@ -83,7 +85,7 @@ def retrieve_many( extra_headers: Headers | None = None, extra_query: Query | None = None, extra_body: Body | None = None, - timeout: float | None | NotGiven = NOT_GIVEN, + timeout: float | httpx.Timeout | None | NotGiven = NOT_GIVEN, ) -> AsyncPaginator[PayStatementResponse, AsyncResponsesPage[PayStatementResponse]]: """ Read detailed pay statements for each individual. diff --git a/src/finch/resources/hris/payments.py b/src/finch/resources/hris/payments.py index 8a6a0e17..17364d80 100644 --- a/src/finch/resources/hris/payments.py +++ b/src/finch/resources/hris/payments.py @@ -5,6 +5,8 @@ from typing import TYPE_CHECKING, Union from datetime import date +import httpx + from ..._types import NOT_GIVEN, Body, Query, Headers, NotGiven from ..._utils import maybe_transform from ..._resource import SyncAPIResource, AsyncAPIResource @@ -36,7 +38,7 @@ def list( extra_headers: Headers | None = None, extra_query: Query | None = None, extra_body: Body | None = None, - timeout: float | None | NotGiven = NOT_GIVEN, + timeout: float | httpx.Timeout | None | NotGiven = NOT_GIVEN, ) -> SyncSinglePage[Payment]: """ Read payroll and contractor related payments by the company. @@ -93,7 +95,7 @@ def list( extra_headers: Headers | None = None, extra_query: Query | None = None, extra_body: Body | None = None, - timeout: float | None | NotGiven = NOT_GIVEN, + timeout: float | httpx.Timeout | None | NotGiven = NOT_GIVEN, ) -> AsyncPaginator[Payment, AsyncSinglePage[Payment]]: """ Read payroll and contractor related payments by the company. diff --git a/src/finch/resources/providers.py b/src/finch/resources/providers.py index 1dbea42b..aa6eedc5 100644 --- a/src/finch/resources/providers.py +++ b/src/finch/resources/providers.py @@ -4,6 +4,8 @@ from typing import TYPE_CHECKING +import httpx + from ..types import Provider from .._types import NOT_GIVEN, Body, Query, Headers, NotGiven from .._resource import SyncAPIResource, AsyncAPIResource @@ -32,7 +34,7 @@ def list( extra_headers: Headers | None = None, extra_query: Query | None = None, extra_body: Body | None = None, - timeout: float | None | NotGiven = NOT_GIVEN, + timeout: float | httpx.Timeout | None | NotGiven = NOT_GIVEN, ) -> SyncSinglePage[Provider]: """Return details on all available payroll and HR systems.""" return self._get_api_list( @@ -60,7 +62,7 @@ def list( extra_headers: Headers | None = None, extra_query: Query | None = None, extra_body: Body | None = None, - timeout: float | None | NotGiven = NOT_GIVEN, + timeout: float | httpx.Timeout | None | NotGiven = NOT_GIVEN, ) -> AsyncPaginator[Provider, AsyncSinglePage[Provider]]: """Return details on all available payroll and HR systems.""" return self._get_api_list( diff --git a/src/finch/resources/request_forwarding.py b/src/finch/resources/request_forwarding.py index 073654ed..21d6e44b 100644 --- a/src/finch/resources/request_forwarding.py +++ b/src/finch/resources/request_forwarding.py @@ -4,6 +4,8 @@ from typing import TYPE_CHECKING, Optional +import httpx + from ..types import RequestForwardingForwardResponse, request_forwarding_forward_params from .._types import NOT_GIVEN, Body, Query, Headers, NotGiven from .._utils import maybe_transform @@ -37,7 +39,7 @@ def forward( extra_headers: Headers | None = None, extra_query: Query | None = None, extra_body: Body | None = None, - timeout: float | None | NotGiven = NOT_GIVEN, + timeout: float | httpx.Timeout | None | NotGiven = NOT_GIVEN, ) -> RequestForwardingForwardResponse: """ The Forward API allows you to make direct requests to an employment system. @@ -107,7 +109,7 @@ async def forward( extra_headers: Headers | None = None, extra_query: Query | None = None, extra_body: Body | None = None, - timeout: float | None | NotGiven = NOT_GIVEN, + timeout: float | httpx.Timeout | None | NotGiven = NOT_GIVEN, ) -> RequestForwardingForwardResponse: """ The Forward API allows you to make direct requests to an employment system. From 19702d1b40f8e3fbfdf35d1da0645a14c422cdb7 Mon Sep 17 00:00:00 2001 From: Stainless Bot <107565488+stainless-bot@users.noreply.github.com> Date: Tue, 7 Nov 2023 16:52:32 +0000 Subject: [PATCH 08/11] chore(docs): fix some typos (#172) --- src/finch/_client.py | 4 ++-- src/finch/_utils/_transform.py | 6 +++--- tests/api_resources/test_webhooks.py | 4 ++-- tests/test_extract_files.py | 2 +- 4 files changed, 8 insertions(+), 8 deletions(-) diff --git a/src/finch/_client.py b/src/finch/_client.py index 7c0f9b38..7da9096f 100644 --- a/src/finch/_client.py +++ b/src/finch/_client.py @@ -297,7 +297,7 @@ def get_auth_url( ) -> str: """ Returns the authorization url which can be visited in order to obtain an - authorization code from Finch. The autorization code can then be exchanged for + authorization code from Finch. The authorization code can then be exchanged for an access token for the Finch api by calling get_access_token(). """ if self.client_id is None: @@ -602,7 +602,7 @@ def get_auth_url( ) -> str: """ Returns the authorization url which can be visited in order to obtain an - authorization code from Finch. The autorization code can then be exchanged for + authorization code from Finch. The authorization code can then be exchanged for an access token for the Finch api by calling get_access_token(). """ if self.client_id is None: diff --git a/src/finch/_utils/_transform.py b/src/finch/_utils/_transform.py index db40bff2..dc497ea3 100644 --- a/src/finch/_utils/_transform.py +++ b/src/finch/_utils/_transform.py @@ -95,7 +95,7 @@ class Params(TypedDict, total=False): return cast(_T, transformed) -def _get_annoted_type(type_: type) -> type | None: +def _get_annotated_type(type_: type) -> type | None: """If the given type is an `Annotated` type then it is returned, if not `None` is returned. This also unwraps the type when applicable, e.g. `Required[Annotated[T, ...]]` @@ -115,7 +115,7 @@ def _maybe_transform_key(key: str, type_: type) -> str: Note: this function only looks at `Annotated` types that contain `PropertInfo` metadata. """ - annotated_type = _get_annoted_type(type_) + annotated_type = _get_annotated_type(type_) if annotated_type is None: # no `Annotated` definition for this type, no transformation needed return key @@ -174,7 +174,7 @@ def _transform_recursive( def _transform_value(data: object, type_: type) -> object: - annotated_type = _get_annoted_type(type_) + annotated_type = _get_annotated_type(type_) if annotated_type is None: return data diff --git a/tests/api_resources/test_webhooks.py b/tests/api_resources/test_webhooks.py index ca6219fb..250d3a22 100644 --- a/tests/api_resources/test_webhooks.py +++ b/tests/api_resources/test_webhooks.py @@ -83,7 +83,7 @@ def test_verify_signature(self) -> None: is None ) - # different signaature version + # different signature version with pytest.raises(ValueError, match=invalid_signature_message): verify( payload=payload, @@ -183,7 +183,7 @@ def test_verify_signature(self) -> None: is None ) - # different signaature version + # different signature version with pytest.raises(ValueError, match=invalid_signature_message): verify( payload=payload, diff --git a/tests/test_extract_files.py b/tests/test_extract_files.py index 43cc2bee..912c0a1b 100644 --- a/tests/test_extract_files.py +++ b/tests/test_extract_files.py @@ -54,7 +54,7 @@ def test_multiple_files() -> None: [], ], ], - ids=["dict expecting array", "arraye expecting dict", "unknown keys"], + ids=["dict expecting array", "array expecting dict", "unknown keys"], ) def test_ignores_incorrect_paths( query: dict[str, object], From 9a8407df5c7e44c3466c2fb860fcbd0d162a9d40 Mon Sep 17 00:00:00 2001 From: Stainless Bot <107565488+stainless-bot@users.noreply.github.com> Date: Tue, 7 Nov 2023 17:34:45 +0000 Subject: [PATCH 09/11] chore(docs): fix github links (#173) --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index 4b53b968..a404df51 100644 --- a/README.md +++ b/README.md @@ -305,7 +305,7 @@ directory = response.parse() # get the object that `hris.directory.list()` woul print(directory.id) ``` -These methods return an [`APIResponse`](https://github.com/Finch-API/finch-api-python/src/finch/_response.py) object. +These methods return an [`APIResponse`](https://github.com/Finch-API/finch-api-python/tree/main/src/finch/_response.py) object. ### Configuring the HTTP client From 5334b9cb09e65c07495a4b8ae3910547e0121539 Mon Sep 17 00:00:00 2001 From: Stainless Bot <107565488+stainless-bot@users.noreply.github.com> Date: Wed, 8 Nov 2023 18:23:16 +0000 Subject: [PATCH 10/11] chore(internal): improve github devcontainer setup (#174) --- .devcontainer/Dockerfile | 28 +++++----------------------- .devcontainer/devcontainer.json | 21 ++++++++++++++++++++- 2 files changed, 25 insertions(+), 24 deletions(-) diff --git a/.devcontainer/Dockerfile b/.devcontainer/Dockerfile index 73f1b9f2..6eb00725 100644 --- a/.devcontainer/Dockerfile +++ b/.devcontainer/Dockerfile @@ -1,27 +1,9 @@ -# syntax=docker/dockerfile:1 -FROM debian:bookworm-slim +ARG VARIANT="3.9" +FROM mcr.microsoft.com/vscode/devcontainers/python:0-${VARIANT} -RUN apt-get update && apt-get install -y \ - libxkbcommon0 \ - ca-certificates \ - make \ - curl \ - git \ - unzip \ - libc++1 \ - vim \ - termcap \ - && apt-get clean autoclean +USER vscode RUN curl -sSf https://rye-up.com/get | RYE_VERSION="0.15.2" RYE_INSTALL_OPTION="--yes" bash -ENV PATH=/root/.rye/shims:$PATH +ENV PATH=/home/vscode/.rye/shims:$PATH -WORKDIR /workspace - -COPY README.md .python-version pyproject.toml requirements.lock requirements-dev.lock /workspace/ - -RUN rye sync --all-features - -COPY . /workspace - -CMD ["rye", "shell"] +RUN echo "[[ -d .venv ]] && source .venv/bin/activate" >> /home/vscode/.bashrc diff --git a/.devcontainer/devcontainer.json b/.devcontainer/devcontainer.json index d55fc4d6..b9da964d 100644 --- a/.devcontainer/devcontainer.json +++ b/.devcontainer/devcontainer.json @@ -3,7 +3,26 @@ { "name": "Debian", "build": { - "dockerfile": "Dockerfile" + "dockerfile": "Dockerfile", + "context": ".." + }, + + "postStartCommand": "rye sync --all-features", + + "customizations": { + "vscode": { + "extensions": [ + "ms-python.python" + ], + "settings": { + "terminal.integrated.shell.linux": "/bin/bash", + "python.pythonPath": ".venv/bin/python", + "python.typeChecking": "basic", + "terminal.integrated.env.linux": { + "PATH": "/home/vscode/.rye/shims:${env:PATH}" + } + } + } } // Features to add to the dev container. More info: https://containers.dev/features. From 8974a7a0d962fe649877421cf0b1dea44c634146 Mon Sep 17 00:00:00 2001 From: Stainless Bot <107565488+stainless-bot@users.noreply.github.com> Date: Wed, 8 Nov 2023 18:23:32 +0000 Subject: [PATCH 11/11] release: 0.6.0 --- .release-please-manifest.json | 2 +- CHANGELOG.md | 29 +++++++++++++++++++++++++++++ pyproject.toml | 2 +- src/finch/_version.py | 2 +- 4 files changed, 32 insertions(+), 3 deletions(-) diff --git a/.release-please-manifest.json b/.release-please-manifest.json index 2aca35ae..4208b5cb 100644 --- a/.release-please-manifest.json +++ b/.release-please-manifest.json @@ -1,3 +1,3 @@ { - ".": "0.5.0" + ".": "0.6.0" } \ No newline at end of file diff --git a/CHANGELOG.md b/CHANGELOG.md index 8c2e6666..f3d0fc5d 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,34 @@ # Changelog +## 0.6.0 (2023-11-08) + +Full Changelog: [v0.5.0...v0.6.0](https://github.com/Finch-API/finch-api-python/compare/v0.5.0...v0.6.0) + +### Features + +* **client:** allow binary returns ([#164](https://github.com/Finch-API/finch-api-python/issues/164)) ([6322114](https://github.com/Finch-API/finch-api-python/commit/6322114c6e752686d4d3f502df94339037a44698)) +* **client:** support passing BaseModels to request params at runtime ([#166](https://github.com/Finch-API/finch-api-python/issues/166)) ([f3e7e76](https://github.com/Finch-API/finch-api-python/commit/f3e7e763c9e1809b6d84e78720465a96daa11ec2)) +* **client:** support passing httpx.Timeout to method timeout argument ([#171](https://github.com/Finch-API/finch-api-python/issues/171)) ([a3dcd4b](https://github.com/Finch-API/finch-api-python/commit/a3dcd4b1add4499894bfc4f63dfe3f46b9a3a2e9)) + + +### Bug Fixes + +* **binaries:** don't synchronously block in astream_to_file ([#167](https://github.com/Finch-API/finch-api-python/issues/167)) ([c607d54](https://github.com/Finch-API/finch-api-python/commit/c607d545379a03d0926aef998e246fd33009d716)) +* prevent TypeError in Python 3.8 (ABC is not subscriptable) ([#170](https://github.com/Finch-API/finch-api-python/issues/170)) ([fc12d83](https://github.com/Finch-API/finch-api-python/commit/fc12d835d80d6d7f076aa81ecfb5fcc318c80261)) + + +### Chores + +* **docs:** fix github links ([#173](https://github.com/Finch-API/finch-api-python/issues/173)) ([9a8407d](https://github.com/Finch-API/finch-api-python/commit/9a8407df5c7e44c3466c2fb860fcbd0d162a9d40)) +* **docs:** fix some typos ([#172](https://github.com/Finch-API/finch-api-python/issues/172)) ([19702d1](https://github.com/Finch-API/finch-api-python/commit/19702d1b40f8e3fbfdf35d1da0645a14c422cdb7)) +* **internal:** improve github devcontainer setup ([#174](https://github.com/Finch-API/finch-api-python/issues/174)) ([5334b9c](https://github.com/Finch-API/finch-api-python/commit/5334b9cb09e65c07495a4b8ae3910547e0121539)) +* **internal:** remove unused int/float conversion ([#168](https://github.com/Finch-API/finch-api-python/issues/168)) ([69faf73](https://github.com/Finch-API/finch-api-python/commit/69faf737601c196eb3fa53fa2575c9c3a53a0d28)) + + +### Documentation + +* **readme:** improve example snippets ([#169](https://github.com/Finch-API/finch-api-python/issues/169)) ([37fe000](https://github.com/Finch-API/finch-api-python/commit/37fe0007d4c1643a14aae4e580ebebf537963399)) + ## 0.5.0 (2023-10-31) Full Changelog: [v0.4.0...v0.5.0](https://github.com/Finch-API/finch-api-python/compare/v0.4.0...v0.5.0) diff --git a/pyproject.toml b/pyproject.toml index 8a7938d0..9622e610 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -1,6 +1,6 @@ [project] name = "finch-api" -version = "0.5.0" +version = "0.6.0" description = "Client 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 a8bbc1fc..991bac2b 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.5.0" # x-release-please-version +__version__ = "0.6.0" # x-release-please-version