From 5df78577187ab33565e3cc2b72fcd0a51c9531db Mon Sep 17 00:00:00 2001 From: "stainless-app[bot]" <142633134+stainless-app[bot]@users.noreply.github.com> Date: Thu, 27 Feb 2025 21:56:12 +0000 Subject: [PATCH 01/18] docs: update URLs from stainlessapi.com to stainless.com (#608) More details at https://www.stainless.com/changelog/stainless-com --- README.md | 2 +- SECURITY.md | 4 ++-- tests/api_resources/connect/test_sessions.py | 4 ++-- 3 files changed, 5 insertions(+), 5 deletions(-) diff --git a/README.md b/README.md index 9b82e4ec..b1b54166 100644 --- a/README.md +++ b/README.md @@ -6,7 +6,7 @@ The Finch Python library provides convenient access to the Finch REST API from a application. The library includes type definitions for all request params and response fields, and offers both synchronous and asynchronous clients powered by [httpx](https://github.com/encode/httpx). -It is generated with [Stainless](https://www.stainlessapi.com/). +It is generated with [Stainless](https://www.stainless.com/). ## Documentation diff --git a/SECURITY.md b/SECURITY.md index 6cef554f..b6499508 100644 --- a/SECURITY.md +++ b/SECURITY.md @@ -2,9 +2,9 @@ ## Reporting Security Issues -This SDK is generated by [Stainless Software Inc](http://stainlessapi.com). Stainless takes security seriously, and encourages you to report any security vulnerability promptly so that appropriate action can be taken. +This SDK is generated by [Stainless Software Inc](http://stainless.com). Stainless takes security seriously, and encourages you to report any security vulnerability promptly so that appropriate action can be taken. -To report a security issue, please contact the Stainless team at security@stainlessapi.com. +To report a security issue, please contact the Stainless team at security@stainless.com. ## Responsible Disclosure diff --git a/tests/api_resources/connect/test_sessions.py b/tests/api_resources/connect/test_sessions.py index c9965727..cc53a9b7 100644 --- a/tests/api_resources/connect/test_sessions.py +++ b/tests/api_resources/connect/test_sessions.py @@ -35,7 +35,7 @@ def test_method_new_with_all_params(self, client: Finch) -> None: customer_id="x", customer_name="x", products=["company"], - customer_email="dev@stainlessapi.com", + customer_email="dev@stainless.com", integration={ "auth_method": "assisted", "provider": "provider", @@ -135,7 +135,7 @@ async def test_method_new_with_all_params(self, async_client: AsyncFinch) -> Non customer_id="x", customer_name="x", products=["company"], - customer_email="dev@stainlessapi.com", + customer_email="dev@stainless.com", integration={ "auth_method": "assisted", "provider": "provider", From 2bae32b4504f2e17d53238d2ef7c6267c9d19636 Mon Sep 17 00:00:00 2001 From: "stainless-app[bot]" <142633134+stainless-app[bot]@users.noreply.github.com> Date: Thu, 27 Feb 2025 22:47:52 +0000 Subject: [PATCH 02/18] chore(docs): update client docstring (#610) --- src/finch/_client.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/finch/_client.py b/src/finch/_client.py index 46a7fa61..b976d0fe 100644 --- a/src/finch/_client.py +++ b/src/finch/_client.py @@ -435,7 +435,7 @@ def __init__( # part of our public interface in the future. _strict_response_validation: bool = False, ) -> None: - """Construct a new async Finch client instance. + """Construct a new async AsyncFinch client instance. This automatically infers the following arguments from their corresponding environment variables if they are not provided: - `client_id` from `FINCH_CLIENT_ID` From f397f2097d2d349d16a46c2fbf79432c6d48290c Mon Sep 17 00:00:00 2001 From: "stainless-app[bot]" <142633134+stainless-app[bot]@users.noreply.github.com> Date: Mon, 3 Mar 2025 20:35:14 +0000 Subject: [PATCH 03/18] chore(internal): codegen related update (#611) --- src/finch/_base_client.py | 97 +---------------- src/finch/_client.py | 64 +----------- tests/test_client.py | 215 -------------------------------------- 3 files changed, 3 insertions(+), 373 deletions(-) diff --git a/src/finch/_base_client.py b/src/finch/_base_client.py index 992b035c..d552f2cb 100644 --- a/src/finch/_base_client.py +++ b/src/finch/_base_client.py @@ -9,7 +9,6 @@ import inspect import logging import platform -import warnings import email.utils from types import TracebackType from random import random @@ -36,7 +35,7 @@ import httpx import distro import pydantic -from httpx import URL, Limits +from httpx import URL from pydantic import PrivateAttr from . import _exceptions @@ -51,13 +50,10 @@ Timeout, NotGiven, ResponseT, - Transport, AnyMapping, PostParser, - ProxiesTypes, RequestFiles, HttpxSendArgs, - AsyncTransport, RequestOptions, HttpxRequestFiles, ModelBuilderProtocol, @@ -338,9 +334,6 @@ class BaseClient(Generic[_HttpxClientT, _DefaultStreamT]): _base_url: URL max_retries: int timeout: Union[float, Timeout, None] - _limits: httpx.Limits - _proxies: ProxiesTypes | None - _transport: Transport | AsyncTransport | None _strict_response_validation: bool _idempotency_header: str | None _default_stream_cls: type[_DefaultStreamT] | None = None @@ -353,9 +346,6 @@ def __init__( _strict_response_validation: bool, max_retries: int = DEFAULT_MAX_RETRIES, timeout: float | Timeout | None = DEFAULT_TIMEOUT, - limits: httpx.Limits, - transport: Transport | AsyncTransport | None, - proxies: ProxiesTypes | None, custom_headers: Mapping[str, str] | None = None, custom_query: Mapping[str, object] | None = None, ) -> None: @@ -363,9 +353,6 @@ def __init__( self._base_url = self._enforce_trailing_slash(URL(base_url)) self.max_retries = max_retries self.timeout = timeout - self._limits = limits - self._proxies = proxies - self._transport = transport self._custom_headers = custom_headers or {} self._custom_query = custom_query or {} self._strict_response_validation = _strict_response_validation @@ -801,46 +788,11 @@ def __init__( base_url: str | URL, max_retries: int = DEFAULT_MAX_RETRIES, timeout: float | Timeout | None | NotGiven = NOT_GIVEN, - transport: Transport | None = None, - proxies: ProxiesTypes | None = None, - limits: Limits | None = None, http_client: httpx.Client | None = None, custom_headers: Mapping[str, str] | None = None, custom_query: Mapping[str, object] | None = None, _strict_response_validation: bool, ) -> None: - kwargs: dict[str, Any] = {} - if limits is not None: - warnings.warn( - "The `connection_pool_limits` argument is deprecated. The `http_client` argument should be passed instead", - category=DeprecationWarning, - stacklevel=3, - ) - if http_client is not None: - raise ValueError("The `http_client` argument is mutually exclusive with `connection_pool_limits`") - else: - limits = DEFAULT_CONNECTION_LIMITS - - if transport is not None: - kwargs["transport"] = transport - warnings.warn( - "The `transport` argument is deprecated. The `http_client` argument should be passed instead", - category=DeprecationWarning, - stacklevel=3, - ) - if http_client is not None: - raise ValueError("The `http_client` argument is mutually exclusive with `transport`") - - if proxies is not None: - kwargs["proxies"] = proxies - warnings.warn( - "The `proxies` argument is deprecated. The `http_client` argument should be passed instead", - category=DeprecationWarning, - stacklevel=3, - ) - if http_client is not None: - raise ValueError("The `http_client` argument is mutually exclusive with `proxies`") - if not is_given(timeout): # if the user passed in a custom http client with a non-default # timeout set then we use that timeout. @@ -861,12 +813,9 @@ def __init__( super().__init__( version=version, - limits=limits, # cast to a valid type because mypy doesn't understand our type narrowing timeout=cast(Timeout, timeout), - proxies=proxies, base_url=base_url, - transport=transport, max_retries=max_retries, custom_query=custom_query, custom_headers=custom_headers, @@ -876,9 +825,6 @@ def __init__( base_url=base_url, # cast to a valid type because mypy doesn't understand our type narrowing timeout=cast(Timeout, timeout), - limits=limits, - follow_redirects=True, - **kwargs, # type: ignore ) def is_closed(self) -> bool: @@ -1387,45 +1333,10 @@ def __init__( _strict_response_validation: bool, max_retries: int = DEFAULT_MAX_RETRIES, timeout: float | Timeout | None | NotGiven = NOT_GIVEN, - transport: AsyncTransport | None = None, - proxies: ProxiesTypes | None = None, - limits: Limits | None = None, http_client: httpx.AsyncClient | None = None, custom_headers: Mapping[str, str] | None = None, custom_query: Mapping[str, object] | None = None, ) -> None: - kwargs: dict[str, Any] = {} - if limits is not None: - warnings.warn( - "The `connection_pool_limits` argument is deprecated. The `http_client` argument should be passed instead", - category=DeprecationWarning, - stacklevel=3, - ) - if http_client is not None: - raise ValueError("The `http_client` argument is mutually exclusive with `connection_pool_limits`") - else: - limits = DEFAULT_CONNECTION_LIMITS - - if transport is not None: - kwargs["transport"] = transport - warnings.warn( - "The `transport` argument is deprecated. The `http_client` argument should be passed instead", - category=DeprecationWarning, - stacklevel=3, - ) - if http_client is not None: - raise ValueError("The `http_client` argument is mutually exclusive with `transport`") - - if proxies is not None: - kwargs["proxies"] = proxies - warnings.warn( - "The `proxies` argument is deprecated. The `http_client` argument should be passed instead", - category=DeprecationWarning, - stacklevel=3, - ) - if http_client is not None: - raise ValueError("The `http_client` argument is mutually exclusive with `proxies`") - if not is_given(timeout): # if the user passed in a custom http client with a non-default # timeout set then we use that timeout. @@ -1447,11 +1358,8 @@ def __init__( super().__init__( version=version, base_url=base_url, - limits=limits, # cast to a valid type because mypy doesn't understand our type narrowing timeout=cast(Timeout, timeout), - proxies=proxies, - transport=transport, max_retries=max_retries, custom_query=custom_query, custom_headers=custom_headers, @@ -1461,9 +1369,6 @@ def __init__( base_url=base_url, # cast to a valid type because mypy doesn't understand our type narrowing timeout=cast(Timeout, timeout), - limits=limits, - follow_redirects=True, - **kwargs, # type: ignore ) def is_closed(self) -> bool: diff --git a/src/finch/_client.py b/src/finch/_client.py index b976d0fe..e98dadf2 100644 --- a/src/finch/_client.py +++ b/src/finch/_client.py @@ -19,7 +19,6 @@ NotGiven, Transport, ProxiesTypes, - AsyncTransport, RequestOptions, ) from ._utils import ( @@ -32,11 +31,8 @@ from ._exceptions import APIStatusError from ._base_client import ( DEFAULT_MAX_RETRIES, - DEFAULT_CONNECTION_LIMITS, SyncAPIClient, AsyncAPIClient, - SyncHttpxClientWrapper, - AsyncHttpxClientWrapper, ) from .resources.hris import hris from .resources.jobs import jobs @@ -83,12 +79,6 @@ def __init__( # We provide a `DefaultHttpxClient` class that you can pass to retain the default values we use for `limits`, `timeout` & `follow_redirects`. # See the [httpx documentation](https://www.python-httpx.org/api/#client) for more details. http_client: httpx.Client | None = None, - # See httpx documentation for [custom transports](https://www.python-httpx.org/advanced/#custom-transports) - transport: Transport | None = None, - # See httpx documentation for [proxies](https://www.python-httpx.org/advanced/#http-proxying) - proxies: ProxiesTypes | None = None, - # See httpx documentation for [limits](https://www.python-httpx.org/advanced/#pool-limit-configuration) - connection_pool_limits: httpx.Limits | None = None, # Enable or disable schema validation for data returned by the API. # When enabled an error APIResponseValidationError is raised # if the API responds with invalid data for the expected schema. @@ -131,9 +121,6 @@ def __init__( max_retries=max_retries, timeout=timeout, http_client=http_client, - transport=transport, - proxies=proxies, - limits=connection_pool_limits, custom_headers=default_headers, custom_query=default_query, _strict_response_validation=_strict_response_validation, @@ -219,7 +206,6 @@ def copy( base_url: str | httpx.URL | None = None, timeout: float | Timeout | None | NotGiven = NOT_GIVEN, http_client: httpx.Client | None = None, - connection_pool_limits: httpx.Limits | None = None, max_retries: int | NotGiven = NOT_GIVEN, default_headers: Mapping[str, str] | None = None, set_default_headers: Mapping[str, str] | None = None, @@ -248,24 +234,7 @@ def copy( elif set_default_query is not None: params = set_default_query - if connection_pool_limits is not None: - if http_client is not None: - raise ValueError("The 'http_client' argument is mutually exclusive with 'connection_pool_limits'") - - if not isinstance(self._client, SyncHttpxClientWrapper): - raise ValueError( - "A custom HTTP client has been set and is mutually exclusive with the 'connection_pool_limits' argument" - ) - - http_client = None - else: - if self._limits is not DEFAULT_CONNECTION_LIMITS: - connection_pool_limits = self._limits - else: - connection_pool_limits = None - - http_client = http_client or self._client - + http_client = http_client or self._client return self.__class__( access_token=access_token or self.access_token, client_id=client_id or self.client_id, @@ -274,7 +243,6 @@ def copy( base_url=base_url or self.base_url, timeout=self.timeout if isinstance(timeout, NotGiven) else timeout, http_client=http_client, - connection_pool_limits=connection_pool_limits, max_retries=max_retries if is_given(max_retries) else self.max_retries, default_headers=headers, default_query=params, @@ -419,12 +387,6 @@ def __init__( # We provide a `DefaultAsyncHttpxClient` class that you can pass to retain the default values we use for `limits`, `timeout` & `follow_redirects`. # See the [httpx documentation](https://www.python-httpx.org/api/#asyncclient) for more details. http_client: httpx.AsyncClient | None = None, - # See httpx documentation for [custom transports](https://www.python-httpx.org/advanced/#custom-transports) - transport: AsyncTransport | None = None, - # See httpx documentation for [proxies](https://www.python-httpx.org/advanced/#http-proxying) - proxies: ProxiesTypes | None = None, - # See httpx documentation for [limits](https://www.python-httpx.org/advanced/#pool-limit-configuration) - connection_pool_limits: httpx.Limits | None = None, # Enable or disable schema validation for data returned by the API. # When enabled an error APIResponseValidationError is raised # if the API responds with invalid data for the expected schema. @@ -467,9 +429,6 @@ def __init__( max_retries=max_retries, timeout=timeout, http_client=http_client, - transport=transport, - proxies=proxies, - limits=connection_pool_limits, custom_headers=default_headers, custom_query=default_query, _strict_response_validation=_strict_response_validation, @@ -555,7 +514,6 @@ def copy( base_url: str | httpx.URL | None = None, timeout: float | Timeout | None | NotGiven = NOT_GIVEN, http_client: httpx.AsyncClient | None = None, - connection_pool_limits: httpx.Limits | None = None, max_retries: int | NotGiven = NOT_GIVEN, default_headers: Mapping[str, str] | None = None, set_default_headers: Mapping[str, str] | None = None, @@ -584,24 +542,7 @@ def copy( elif set_default_query is not None: params = set_default_query - if connection_pool_limits is not None: - if http_client is not None: - raise ValueError("The 'http_client' argument is mutually exclusive with 'connection_pool_limits'") - - if not isinstance(self._client, AsyncHttpxClientWrapper): - raise ValueError( - "A custom HTTP client has been set and is mutually exclusive with the 'connection_pool_limits' argument" - ) - - http_client = None - else: - if self._limits is not DEFAULT_CONNECTION_LIMITS: - connection_pool_limits = self._limits - else: - connection_pool_limits = None - - http_client = http_client or self._client - + http_client = http_client or self._client return self.__class__( access_token=access_token or self.access_token, client_id=client_id or self.client_id, @@ -610,7 +551,6 @@ def copy( base_url=base_url or self.base_url, timeout=self.timeout if isinstance(timeout, NotGiven) else timeout, http_client=http_client, - connection_pool_limits=connection_pool_limits, max_retries=max_retries if is_given(max_retries) else self.max_retries, default_headers=headers, default_query=params, diff --git a/tests/test_client.py b/tests/test_client.py index 52d6f178..a52f63d4 100644 --- a/tests/test_client.py +++ b/tests/test_client.py @@ -18,7 +18,6 @@ import httpx import pytest -import packaging.version as version from respx import MockRouter from pydantic import ValidationError @@ -645,113 +644,6 @@ def test_absolute_request_url(self, client: Finch) -> None: ) assert request.url == "https://myapi.com/foo" - @pytest.mark.skipif( - version.parse(httpx.__version__) >= version.parse("0.28.0"), - reason="Test is only relevant for httpx versions < 0.28.0", - ) - def test_transport_option_is_deprecated(self) -> None: - with pytest.warns( - DeprecationWarning, - match="The `transport` argument is deprecated. The `http_client` argument should be passed instead", - ): - transport = httpx.MockTransport( - lambda: None, # type: ignore - ) - - client = Finch( - base_url=base_url, access_token=access_token, _strict_response_validation=True, transport=transport - ) - - assert client._client._transport is transport - - def test_transport_option_mutually_exclusive_with_http_client(self) -> None: - with httpx.Client() as http_client: - with pytest.raises(ValueError, match="The `http_client` argument is mutually exclusive with `transport`"): - with pytest.warns(DeprecationWarning): - Finch( - base_url=base_url, - access_token=access_token, - _strict_response_validation=True, - transport=httpx.MockTransport( - lambda: None, # type: ignore - ), - http_client=http_client, - ) - - @pytest.mark.skipif( - version.parse(httpx.__version__) >= version.parse("0.28.0"), - reason="Test is only relevant for httpx versions < 0.28.0", - ) - def test_connection_pool_limits_option_is_deprecated(self) -> None: - with pytest.warns( - DeprecationWarning, - match="The `connection_pool_limits` argument is deprecated. The `http_client` argument should be passed instead", - ): - connection_pool_limits = httpx.Limits( - max_connections=101, max_keepalive_connections=76, keepalive_expiry=23 - ) - - client = Finch( - base_url=base_url, - access_token=access_token, - _strict_response_validation=True, - connection_pool_limits=connection_pool_limits, - ) - - assert isinstance(client._client._transport, httpx.HTTPTransport) - assert client._client._transport._pool._max_connections == 101 - assert client._client._transport._pool._max_keepalive_connections == 76 - assert client._client._transport._pool._keepalive_expiry == 23 - - def test_connection_pool_limits_option_mutually_exclusive_with_http_client(self) -> None: - with httpx.Client() as http_client: - with pytest.raises( - ValueError, match="The `http_client` argument is mutually exclusive with `connection_pool_limits`" - ): - with pytest.warns(DeprecationWarning): - Finch( - base_url=base_url, - access_token=access_token, - _strict_response_validation=True, - connection_pool_limits=httpx.Limits( - max_connections=101, max_keepalive_connections=76, keepalive_expiry=23 - ), - http_client=http_client, - ) - - @pytest.mark.skipif( - version.parse(httpx.__version__) >= version.parse("0.28.0"), - reason="Test is only relevant for httpx versions < 0.28.0", - ) - def test_proxies_option_is_deprecated(self) -> None: - with pytest.warns( - DeprecationWarning, - match="The `proxies` argument is deprecated. The `http_client` argument should be passed instead", - ): - proxies = "https://www.example.com/proxy" - - client = Finch( - base_url=base_url, access_token=access_token, _strict_response_validation=True, proxies=proxies - ) - - mounts = list(client._client._mounts.keys()) - assert len(mounts) == 1 - - pattern = mounts[0].pattern - assert pattern == "all://" - - def test_proxies_option_mutually_exclusive_with_http_client(self) -> None: - with httpx.Client() as http_client: - with pytest.raises(ValueError, match="The `http_client` argument is mutually exclusive with `proxies`"): - with pytest.warns(DeprecationWarning): - Finch( - base_url=base_url, - access_token=access_token, - _strict_response_validation=True, - proxies="https://www.example.com/proxy", - http_client=http_client, - ) - def test_copied_client_does_not_close_http(self) -> None: client = Finch(base_url=base_url, access_token=access_token, _strict_response_validation=True) assert not client.is_closed() @@ -1541,113 +1433,6 @@ def test_absolute_request_url(self, client: AsyncFinch) -> None: ) assert request.url == "https://myapi.com/foo" - @pytest.mark.skipif( - version.parse(httpx.__version__) >= version.parse("0.28.0"), - reason="Test is only relevant for httpx versions < 0.28.0", - ) - def test_transport_option_is_deprecated(self) -> None: - with pytest.warns( - DeprecationWarning, - match="The `transport` argument is deprecated. The `http_client` argument should be passed instead", - ): - transport = httpx.MockTransport( - lambda: None, # type: ignore - ) - - client = AsyncFinch( - base_url=base_url, access_token=access_token, _strict_response_validation=True, transport=transport - ) - - assert client._client._transport is transport - - async def test_transport_option_mutually_exclusive_with_http_client(self) -> None: - async with httpx.AsyncClient() as http_client: - with pytest.raises(ValueError, match="The `http_client` argument is mutually exclusive with `transport`"): - with pytest.warns(DeprecationWarning): - AsyncFinch( - base_url=base_url, - access_token=access_token, - _strict_response_validation=True, - transport=httpx.MockTransport( - lambda: None, # type: ignore - ), - http_client=http_client, - ) - - @pytest.mark.skipif( - version.parse(httpx.__version__) >= version.parse("0.28.0"), - reason="Test is only relevant for httpx versions < 0.28.0", - ) - def test_connection_pool_limits_option_is_deprecated(self) -> None: - with pytest.warns( - DeprecationWarning, - match="The `connection_pool_limits` argument is deprecated. The `http_client` argument should be passed instead", - ): - connection_pool_limits = httpx.Limits( - max_connections=101, max_keepalive_connections=76, keepalive_expiry=23 - ) - - client = AsyncFinch( - base_url=base_url, - access_token=access_token, - _strict_response_validation=True, - connection_pool_limits=connection_pool_limits, - ) - - assert isinstance(client._client._transport, httpx.AsyncHTTPTransport) - assert client._client._transport._pool._max_connections == 101 - assert client._client._transport._pool._max_keepalive_connections == 76 - assert client._client._transport._pool._keepalive_expiry == 23 - - async def test_connection_pool_limits_option_mutually_exclusive_with_http_client(self) -> None: - async with httpx.AsyncClient() as http_client: - with pytest.raises( - ValueError, match="The `http_client` argument is mutually exclusive with `connection_pool_limits`" - ): - with pytest.warns(DeprecationWarning): - AsyncFinch( - base_url=base_url, - access_token=access_token, - _strict_response_validation=True, - connection_pool_limits=httpx.Limits( - max_connections=101, max_keepalive_connections=76, keepalive_expiry=23 - ), - http_client=http_client, - ) - - @pytest.mark.skipif( - version.parse(httpx.__version__) >= version.parse("0.28.0"), - reason="Test is only relevant for httpx versions < 0.28.0", - ) - def test_proxies_option_is_deprecated(self) -> None: - with pytest.warns( - DeprecationWarning, - match="The `proxies` argument is deprecated. The `http_client` argument should be passed instead", - ): - proxies = "https://www.example.com/proxy" - - client = AsyncFinch( - base_url=base_url, access_token=access_token, _strict_response_validation=True, proxies=proxies - ) - - mounts = list(client._client._mounts.keys()) - assert len(mounts) == 1 - - pattern = mounts[0].pattern - assert pattern == "all://" - - async def test_proxies_option_mutually_exclusive_with_http_client(self) -> None: - async with httpx.AsyncClient() as http_client: - with pytest.raises(ValueError, match="The `http_client` argument is mutually exclusive with `proxies`"): - with pytest.warns(DeprecationWarning): - AsyncFinch( - base_url=base_url, - access_token=access_token, - _strict_response_validation=True, - proxies="https://www.example.com/proxy", - http_client=http_client, - ) - async def test_copied_client_does_not_close_http(self) -> None: client = AsyncFinch(base_url=base_url, access_token=access_token, _strict_response_validation=True) assert not client.is_closed() From ac900617af1bc37b728cbbc69ba22c5061ffddb7 Mon Sep 17 00:00:00 2001 From: "stainless-app[bot]" <142633134+stainless-app[bot]@users.noreply.github.com> Date: Fri, 14 Mar 2025 17:43:15 +0000 Subject: [PATCH 04/18] feat(api): manual updates (#612) --- release-please-config.json | 10 +--------- 1 file changed, 1 insertion(+), 9 deletions(-) diff --git a/release-please-config.json b/release-please-config.json index d416b017..b55afaba 100644 --- a/release-please-config.json +++ b/release-please-config.json @@ -60,16 +60,8 @@ } ], "reviewers": [ - "araujodavid", - "NandoSangenetto", - "delainerogers", - "ericpsimon", "jordanbrauer", - "vitorfreitas", - "miguel-finch", - "edkim-finch", - "bteodosioFinch", - "ashar-finch" + "minupalaniappan" ], "release-type": "python", "extra-files": [ From e42e1fd10f2bf00f41a9f53d103614d6603d1f56 Mon Sep 17 00:00:00 2001 From: "stainless-app[bot]" <142633134+stainless-app[bot]@users.noreply.github.com> Date: Wed, 5 Mar 2025 18:07:04 +0000 Subject: [PATCH 05/18] codegen metadata --- .stats.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.stats.yml b/.stats.yml index 06d70961..7cc1a4d2 100644 --- a/.stats.yml +++ b/.stats.yml @@ -1,2 +1,2 @@ configured_endpoints: 41 -openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/finch%2Ffinch-7a816d4a5f0039230590a6662f3513d5756344ca662761ecbc49016593f65836.yml +openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/finch%2Ffinch-a8fb4796584347205fabadf0148a039a0259b7363ffa476579032acd2987311a.yml From 805a34676a56c5e302dacc2105630ed05c06d69b Mon Sep 17 00:00:00 2001 From: "stainless-app[bot]" <142633134+stainless-app[bot]@users.noreply.github.com> Date: Thu, 6 Mar 2025 02:00:47 +0000 Subject: [PATCH 06/18] codegen metadata --- .stats.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.stats.yml b/.stats.yml index 7cc1a4d2..27e0c64c 100644 --- a/.stats.yml +++ b/.stats.yml @@ -1,2 +1,2 @@ configured_endpoints: 41 -openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/finch%2Ffinch-a8fb4796584347205fabadf0148a039a0259b7363ffa476579032acd2987311a.yml +openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/finch%2Ffinch-777eedfd80c3e04a8739959418783d1c976180f4f09d7a883f7de5c2b6cda5a6.yml From 6dd5f30dfb8eb5b82500fd18e9472813b84bfdfc Mon Sep 17 00:00:00 2001 From: "stainless-app[bot]" <142633134+stainless-app[bot]@users.noreply.github.com> Date: Thu, 6 Mar 2025 14:46:40 +0000 Subject: [PATCH 07/18] chore(internal): codegen related update (#614) --- api.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/api.md b/api.md index cf19f855..45ab0c57 100644 --- a/api.md +++ b/api.md @@ -133,12 +133,12 @@ from finch.types.hris import ( BenefitFrequency, BenefitType, BenefitsSupport, - BenfitContribution, CompanyBenefit, CreateCompanyBenefitsResponse, SupportPerBenefitType, SupportedBenefit, UpdateCompanyBenefitResponse, + BenfitContribution, ) ``` From 1ffccafbb26c672fdea41495b91774babb9cdb06 Mon Sep 17 00:00:00 2001 From: "stainless-app[bot]" <142633134+stainless-app[bot]@users.noreply.github.com> Date: Mon, 10 Mar 2025 17:00:17 +0000 Subject: [PATCH 08/18] chore(internal): codegen related update (#615) --- src/finch/types/webhook_event.py | 24 ++++++++++++++---------- 1 file changed, 14 insertions(+), 10 deletions(-) diff --git a/src/finch/types/webhook_event.py b/src/finch/types/webhook_event.py index 17bb1d4f..d0dc5702 100644 --- a/src/finch/types/webhook_event.py +++ b/src/finch/types/webhook_event.py @@ -1,8 +1,9 @@ # File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. from typing import Union -from typing_extensions import TypeAlias +from typing_extensions import Annotated, TypeAlias +from .._utils import PropertyInfo from .company_event import CompanyEvent from .payment_event import PaymentEvent from .directory_event import DirectoryEvent @@ -14,13 +15,16 @@ __all__ = ["WebhookEvent"] -WebhookEvent: TypeAlias = Union[ - AccountUpdateEvent, - JobCompletionEvent, - CompanyEvent, - DirectoryEvent, - EmploymentEvent, - IndividualEvent, - PaymentEvent, - PayStatementEvent, +WebhookEvent: TypeAlias = Annotated[ + Union[ + AccountUpdateEvent, + JobCompletionEvent, + CompanyEvent, + DirectoryEvent, + EmploymentEvent, + IndividualEvent, + PaymentEvent, + PayStatementEvent, + ], + PropertyInfo(discriminator="event_type"), ] From 3f0a07eb43ee54586a1bb2d1d843fb94dba70026 Mon Sep 17 00:00:00 2001 From: "stainless-app[bot]" <142633134+stainless-app[bot]@users.noreply.github.com> Date: Tue, 11 Mar 2025 01:06:00 +0000 Subject: [PATCH 09/18] test: add DEFER_PYDANTIC_BUILD=false flag to tests (#616) --- scripts/test | 2 ++ 1 file changed, 2 insertions(+) diff --git a/scripts/test b/scripts/test index 4fa5698b..2b878456 100755 --- a/scripts/test +++ b/scripts/test @@ -52,6 +52,8 @@ else echo fi +export DEFER_PYDANTIC_BUILD=false + echo "==> Running tests" rye run pytest "$@" From 9c2b530e4a89d19276ba031558bc9f077069aa92 Mon Sep 17 00:00:00 2001 From: "stainless-app[bot]" <142633134+stainless-app[bot]@users.noreply.github.com> Date: Tue, 11 Mar 2025 16:50:35 +0000 Subject: [PATCH 10/18] chore(internal): codegen related update (#617) --- .stats.yml | 2 +- api.md | 4 +-- src/finch/resources/jobs/automated.py | 22 ++++++------ src/finch/types/jobs/__init__.py | 1 + .../types/jobs/automated_list_response.py | 34 +++++++++++++++++++ tests/api_resources/jobs/test_automated.py | 23 +++++++------ 6 files changed, 61 insertions(+), 25 deletions(-) create mode 100644 src/finch/types/jobs/automated_list_response.py diff --git a/.stats.yml b/.stats.yml index 27e0c64c..424dc58b 100644 --- a/.stats.yml +++ b/.stats.yml @@ -1,2 +1,2 @@ configured_endpoints: 41 -openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/finch%2Ffinch-777eedfd80c3e04a8739959418783d1c976180f4f09d7a883f7de5c2b6cda5a6.yml +openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/finch%2Ffinch-f1779210fbedfc6099076412405288b489f727cbb0b3a85e7b7c12fabb37ef47.yml diff --git a/api.md b/api.md index 45ab0c57..15b5ef12 100644 --- a/api.md +++ b/api.md @@ -238,14 +238,14 @@ Methods: Types: ```python -from finch.types.jobs import AutomatedAsyncJob, AutomatedCreateResponse +from finch.types.jobs import AutomatedAsyncJob, AutomatedCreateResponse, AutomatedListResponse ``` Methods: - client.jobs.automated.create(\*\*params) -> AutomatedCreateResponse - client.jobs.automated.retrieve(job_id) -> AutomatedAsyncJob -- client.jobs.automated.list(\*\*params) -> SyncPage[AutomatedAsyncJob] +- client.jobs.automated.list(\*\*params) -> AutomatedListResponse ## Manual diff --git a/src/finch/resources/jobs/automated.py b/src/finch/resources/jobs/automated.py index ce3e70ca..3fa895ce 100644 --- a/src/finch/resources/jobs/automated.py +++ b/src/finch/resources/jobs/automated.py @@ -16,10 +16,10 @@ from ..._compat import cached_property from ..._resource import SyncAPIResource, AsyncAPIResource from ..._response import to_streamed_response_wrapper, async_to_streamed_response_wrapper -from ...pagination import SyncPage, AsyncPage from ...types.jobs import automated_list_params, automated_create_params -from ..._base_client import AsyncPaginator, make_request_options +from ..._base_client import make_request_options from ...types.jobs.automated_async_job import AutomatedAsyncJob +from ...types.jobs.automated_list_response import AutomatedListResponse from ...types.jobs.automated_create_response import AutomatedCreateResponse __all__ = ["Automated", "AsyncAutomated"] @@ -200,7 +200,7 @@ def list( extra_query: Query | None = None, extra_body: Body | None = None, timeout: float | httpx.Timeout | None | NotGiven = NOT_GIVEN, - ) -> SyncPage[AutomatedAsyncJob]: + ) -> AutomatedListResponse: """Get all automated jobs. Automated jobs are completed by a machine. By default, @@ -220,9 +220,8 @@ def list( timeout: Override the client-level default timeout for this request, in seconds """ - return self._get_api_list( + return self._get( "/jobs/automated", - page=SyncPage[AutomatedAsyncJob], options=make_request_options( extra_headers=extra_headers, extra_query=extra_query, @@ -236,7 +235,7 @@ def list( automated_list_params.AutomatedListParams, ), ), - model=AutomatedAsyncJob, + cast_to=AutomatedListResponse, ) @@ -404,7 +403,7 @@ async def retrieve( cast_to=AutomatedAsyncJob, ) - def list( + async def list( self, *, limit: int | NotGiven = NOT_GIVEN, @@ -415,7 +414,7 @@ def list( extra_query: Query | None = None, extra_body: Body | None = None, timeout: float | httpx.Timeout | None | NotGiven = NOT_GIVEN, - ) -> AsyncPaginator[AutomatedAsyncJob, AsyncPage[AutomatedAsyncJob]]: + ) -> AutomatedListResponse: """Get all automated jobs. Automated jobs are completed by a machine. By default, @@ -435,15 +434,14 @@ def list( timeout: Override the client-level default timeout for this request, in seconds """ - return self._get_api_list( + return await self._get( "/jobs/automated", - page=AsyncPage[AutomatedAsyncJob], options=make_request_options( extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout, - query=maybe_transform( + query=await async_maybe_transform( { "limit": limit, "offset": offset, @@ -451,7 +449,7 @@ def list( automated_list_params.AutomatedListParams, ), ), - model=AutomatedAsyncJob, + cast_to=AutomatedListResponse, ) diff --git a/src/finch/types/jobs/__init__.py b/src/finch/types/jobs/__init__.py index b5eaa10b..ee2d3e8e 100644 --- a/src/finch/types/jobs/__init__.py +++ b/src/finch/types/jobs/__init__.py @@ -6,4 +6,5 @@ from .automated_async_job import AutomatedAsyncJob as AutomatedAsyncJob from .automated_list_params import AutomatedListParams as AutomatedListParams from .automated_create_params import AutomatedCreateParams as AutomatedCreateParams +from .automated_list_response import AutomatedListResponse as AutomatedListResponse from .automated_create_response import AutomatedCreateResponse as AutomatedCreateResponse diff --git a/src/finch/types/jobs/automated_list_response.py b/src/finch/types/jobs/automated_list_response.py new file mode 100644 index 00000000..d934dea6 --- /dev/null +++ b/src/finch/types/jobs/automated_list_response.py @@ -0,0 +1,34 @@ +# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. + +from typing import List, Optional + +from ..._models import BaseModel +from .automated_async_job import AutomatedAsyncJob + +__all__ = ["AutomatedListResponse", "Meta", "MetaQuotas", "MetaQuotasDataSyncAll"] + + +class MetaQuotasDataSyncAll(BaseModel): + allowed_refreshes: Optional[int] = None + + remaining_refreshes: Optional[int] = None + + +class MetaQuotas(BaseModel): + data_sync_all: Optional[MetaQuotasDataSyncAll] = None + + +class Meta(BaseModel): + quotas: Optional[MetaQuotas] = None + """Information about remaining quotas for this connection. + + Only applicable for customers opted in to use Finch's Data Sync Refresh endpoint + (`POST /jobs/automated`). Please contact a Finch representative for more + details. + """ + + +class AutomatedListResponse(BaseModel): + data: List[AutomatedAsyncJob] + + meta: Meta diff --git a/tests/api_resources/jobs/test_automated.py b/tests/api_resources/jobs/test_automated.py index db83b0e5..c0dc5e49 100644 --- a/tests/api_resources/jobs/test_automated.py +++ b/tests/api_resources/jobs/test_automated.py @@ -9,8 +9,11 @@ from finch import Finch, AsyncFinch from tests.utils import assert_matches_type -from finch.pagination import SyncPage, AsyncPage -from finch.types.jobs import AutomatedAsyncJob, AutomatedCreateResponse +from finch.types.jobs import ( + AutomatedAsyncJob, + AutomatedListResponse, + AutomatedCreateResponse, +) base_url = os.environ.get("TEST_API_BASE_URL", "http://127.0.0.1:4010") @@ -124,7 +127,7 @@ def test_path_params_retrieve(self, client: Finch) -> None: @parametrize def test_method_list(self, client: Finch) -> None: automated = client.jobs.automated.list() - assert_matches_type(SyncPage[AutomatedAsyncJob], automated, path=["response"]) + assert_matches_type(AutomatedListResponse, automated, path=["response"]) @parametrize def test_method_list_with_all_params(self, client: Finch) -> None: @@ -132,7 +135,7 @@ def test_method_list_with_all_params(self, client: Finch) -> None: limit=0, offset=0, ) - assert_matches_type(SyncPage[AutomatedAsyncJob], automated, path=["response"]) + assert_matches_type(AutomatedListResponse, automated, path=["response"]) @parametrize def test_raw_response_list(self, client: Finch) -> None: @@ -141,7 +144,7 @@ def test_raw_response_list(self, client: Finch) -> None: assert response.is_closed is True assert response.http_request.headers.get("X-Stainless-Lang") == "python" automated = response.parse() - assert_matches_type(SyncPage[AutomatedAsyncJob], automated, path=["response"]) + assert_matches_type(AutomatedListResponse, automated, path=["response"]) @parametrize def test_streaming_response_list(self, client: Finch) -> None: @@ -150,7 +153,7 @@ def test_streaming_response_list(self, client: Finch) -> None: assert response.http_request.headers.get("X-Stainless-Lang") == "python" automated = response.parse() - assert_matches_type(SyncPage[AutomatedAsyncJob], automated, path=["response"]) + assert_matches_type(AutomatedListResponse, automated, path=["response"]) assert cast(Any, response.is_closed) is True @@ -264,7 +267,7 @@ async def test_path_params_retrieve(self, async_client: AsyncFinch) -> None: @parametrize async def test_method_list(self, async_client: AsyncFinch) -> None: automated = await async_client.jobs.automated.list() - assert_matches_type(AsyncPage[AutomatedAsyncJob], automated, path=["response"]) + assert_matches_type(AutomatedListResponse, automated, path=["response"]) @parametrize async def test_method_list_with_all_params(self, async_client: AsyncFinch) -> None: @@ -272,7 +275,7 @@ async def test_method_list_with_all_params(self, async_client: AsyncFinch) -> No limit=0, offset=0, ) - assert_matches_type(AsyncPage[AutomatedAsyncJob], automated, path=["response"]) + assert_matches_type(AutomatedListResponse, automated, path=["response"]) @parametrize async def test_raw_response_list(self, async_client: AsyncFinch) -> None: @@ -281,7 +284,7 @@ async def test_raw_response_list(self, async_client: AsyncFinch) -> None: assert response.is_closed is True assert response.http_request.headers.get("X-Stainless-Lang") == "python" automated = response.parse() - assert_matches_type(AsyncPage[AutomatedAsyncJob], automated, path=["response"]) + assert_matches_type(AutomatedListResponse, automated, path=["response"]) @parametrize async def test_streaming_response_list(self, async_client: AsyncFinch) -> None: @@ -290,6 +293,6 @@ async def test_streaming_response_list(self, async_client: AsyncFinch) -> None: assert response.http_request.headers.get("X-Stainless-Lang") == "python" automated = await response.parse() - assert_matches_type(AsyncPage[AutomatedAsyncJob], automated, path=["response"]) + assert_matches_type(AutomatedListResponse, automated, path=["response"]) assert cast(Any, response.is_closed) is True From a18d4b59192e8efdd5ce03d6e3e88fcc0135f9ec Mon Sep 17 00:00:00 2001 From: "stainless-app[bot]" <142633134+stainless-app[bot]@users.noreply.github.com> Date: Thu, 13 Mar 2025 16:45:42 +0000 Subject: [PATCH 11/18] chore(internal): remove extra empty newlines (#618) --- pyproject.toml | 2 -- 1 file changed, 2 deletions(-) diff --git a/pyproject.toml b/pyproject.toml index 897b2659..27f6e0e3 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -38,7 +38,6 @@ Homepage = "https://github.com/Finch-API/finch-api-python" Repository = "https://github.com/Finch-API/finch-api-python" - [tool.rye] managed = true # version pins are in requirements-dev.lock @@ -152,7 +151,6 @@ reportImplicitOverride = true reportImportCycles = false reportPrivateUsage = false - [tool.ruff] line-length = 120 output-format = "grouped" From c62de3cf8821a5bfb814547c68939e78411d0681 Mon Sep 17 00:00:00 2001 From: "stainless-app[bot]" <142633134+stainless-app[bot]@users.noreply.github.com> Date: Fri, 14 Mar 2025 15:17:21 +0000 Subject: [PATCH 12/18] chore(internal): bump rye to 0.44.0 (#619) --- .devcontainer/Dockerfile | 2 +- .github/workflows/ci.yml | 4 ++-- .github/workflows/publish-pypi.yml | 2 +- 3 files changed, 4 insertions(+), 4 deletions(-) diff --git a/.devcontainer/Dockerfile b/.devcontainer/Dockerfile index 55d20255..ff261bad 100644 --- a/.devcontainer/Dockerfile +++ b/.devcontainer/Dockerfile @@ -3,7 +3,7 @@ FROM mcr.microsoft.com/vscode/devcontainers/python:0-${VARIANT} USER vscode -RUN curl -sSf https://rye.astral.sh/get | RYE_VERSION="0.35.0" RYE_INSTALL_OPTION="--yes" bash +RUN curl -sSf https://rye.astral.sh/get | RYE_VERSION="0.44.0" RYE_INSTALL_OPTION="--yes" bash ENV PATH=/home/vscode/.rye/shims:$PATH RUN echo "[[ -d .venv ]] && source .venv/bin/activate || export PATH=\$PATH" >> /home/vscode/.bashrc diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index c8a8a4f7..3b286e5a 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -21,7 +21,7 @@ jobs: curl -sSf https://rye.astral.sh/get | bash echo "$HOME/.rye/shims" >> $GITHUB_PATH env: - RYE_VERSION: '0.35.0' + RYE_VERSION: '0.44.0' RYE_INSTALL_OPTION: '--yes' - name: Install dependencies @@ -42,7 +42,7 @@ jobs: curl -sSf https://rye.astral.sh/get | bash echo "$HOME/.rye/shims" >> $GITHUB_PATH env: - RYE_VERSION: '0.35.0' + RYE_VERSION: '0.44.0' RYE_INSTALL_OPTION: '--yes' - name: Bootstrap diff --git a/.github/workflows/publish-pypi.yml b/.github/workflows/publish-pypi.yml index ddd68577..e35862a0 100644 --- a/.github/workflows/publish-pypi.yml +++ b/.github/workflows/publish-pypi.yml @@ -21,7 +21,7 @@ jobs: curl -sSf https://rye.astral.sh/get | bash echo "$HOME/.rye/shims" >> $GITHUB_PATH env: - RYE_VERSION: '0.35.0' + RYE_VERSION: '0.44.0' RYE_INSTALL_OPTION: '--yes' - name: Publish to PyPI From 735fb42343c68e6e484a0ac962c0946fc4643659 Mon Sep 17 00:00:00 2001 From: "stainless-app[bot]" <142633134+stainless-app[bot]@users.noreply.github.com> Date: Fri, 14 Mar 2025 18:00:27 +0000 Subject: [PATCH 13/18] chore(internal): codegen related update (#620) --- requirements-dev.lock | 1 + requirements.lock | 1 + 2 files changed, 2 insertions(+) diff --git a/requirements-dev.lock b/requirements-dev.lock index fe794e91..b2e2daa3 100644 --- a/requirements-dev.lock +++ b/requirements-dev.lock @@ -7,6 +7,7 @@ # all-features: true # with-sources: false # generate-hashes: false +# universal: false -e file:. annotated-types==0.6.0 diff --git a/requirements.lock b/requirements.lock index 7d43b8d3..d9942c73 100644 --- a/requirements.lock +++ b/requirements.lock @@ -7,6 +7,7 @@ # all-features: true # with-sources: false # generate-hashes: false +# universal: false -e file:. annotated-types==0.6.0 From 971eac8aef3ad9a5b87b70567726cb0c524b9251 Mon Sep 17 00:00:00 2001 From: "stainless-app[bot]" <142633134+stainless-app[bot]@users.noreply.github.com> Date: Fri, 14 Mar 2025 22:10:25 +0000 Subject: [PATCH 14/18] fix(types): handle more discriminated union shapes (#621) --- src/finch/_models.py | 7 +++++-- tests/test_models.py | 32 ++++++++++++++++++++++++++++++++ 2 files changed, 37 insertions(+), 2 deletions(-) diff --git a/src/finch/_models.py b/src/finch/_models.py index c4401ff8..b51a1bf5 100644 --- a/src/finch/_models.py +++ b/src/finch/_models.py @@ -65,7 +65,7 @@ from ._constants import RAW_RESPONSE_HEADER if TYPE_CHECKING: - from pydantic_core.core_schema import ModelField, LiteralSchema, ModelFieldsSchema + from pydantic_core.core_schema import ModelField, ModelSchema, LiteralSchema, ModelFieldsSchema __all__ = ["BaseModel", "GenericModel"] @@ -646,15 +646,18 @@ def _build_discriminated_union_meta(*, union: type, meta_annotations: tuple[Any, def _extract_field_schema_pv2(model: type[BaseModel], field_name: str) -> ModelField | None: schema = model.__pydantic_core_schema__ + if schema["type"] == "definitions": + schema = schema["schema"] + if schema["type"] != "model": return None + schema = cast("ModelSchema", schema) fields_schema = schema["schema"] if fields_schema["type"] != "model-fields": return None fields_schema = cast("ModelFieldsSchema", fields_schema) - field = fields_schema["fields"].get(field_name) if not field: return None diff --git a/tests/test_models.py b/tests/test_models.py index 2def6ec5..ee0f1618 100644 --- a/tests/test_models.py +++ b/tests/test_models.py @@ -854,3 +854,35 @@ class Model(BaseModel): m = construct_type(value={"cls": "foo"}, type_=Model) assert isinstance(m, Model) assert isinstance(m.cls, str) + + +def test_discriminated_union_case() -> None: + class A(BaseModel): + type: Literal["a"] + + data: bool + + class B(BaseModel): + type: Literal["b"] + + data: List[Union[A, object]] + + class ModelA(BaseModel): + type: Literal["modelA"] + + data: int + + class ModelB(BaseModel): + type: Literal["modelB"] + + required: str + + data: Union[A, B] + + # when constructing ModelA | ModelB, value data doesn't match ModelB exactly - missing `required` + m = construct_type( + value={"type": "modelB", "data": {"type": "a", "data": True}}, + type_=cast(Any, Annotated[Union[ModelA, ModelB], PropertyInfo(discriminator="type")]), + ) + + assert isinstance(m, ModelB) From bffb8540f25ba56cfeb452d0c92dbadb291d88e9 Mon Sep 17 00:00:00 2001 From: "stainless-app[bot]" <142633134+stainless-app[bot]@users.noreply.github.com> Date: Mon, 17 Mar 2025 13:03:42 +0000 Subject: [PATCH 15/18] fix(ci): ensure pip is always available (#622) --- bin/publish-pypi | 1 + 1 file changed, 1 insertion(+) diff --git a/bin/publish-pypi b/bin/publish-pypi index 05bfccbb..ebebf916 100644 --- a/bin/publish-pypi +++ b/bin/publish-pypi @@ -5,5 +5,6 @@ mkdir -p dist rye build --clean # Patching importlib-metadata version until upstream library version is updated # https://github.com/pypa/twine/issues/977#issuecomment-2189800841 +"$HOME/.rye/self/bin/python3" -m ensurepip "$HOME/.rye/self/bin/python3" -m pip install 'importlib-metadata==7.2.1' rye publish --yes --token=$PYPI_TOKEN From 419c35ad3f89c7da406c33a67069f0e8a7937aa4 Mon Sep 17 00:00:00 2001 From: "stainless-app[bot]" <142633134+stainless-app[bot]@users.noreply.github.com> Date: Mon, 17 Mar 2025 15:51:15 +0000 Subject: [PATCH 16/18] fix(ci): remove publishing patch (#623) --- bin/publish-pypi | 4 ---- pyproject.toml | 2 +- 2 files changed, 1 insertion(+), 5 deletions(-) diff --git a/bin/publish-pypi b/bin/publish-pypi index ebebf916..826054e9 100644 --- a/bin/publish-pypi +++ b/bin/publish-pypi @@ -3,8 +3,4 @@ set -eux mkdir -p dist rye build --clean -# Patching importlib-metadata version until upstream library version is updated -# https://github.com/pypa/twine/issues/977#issuecomment-2189800841 -"$HOME/.rye/self/bin/python3" -m ensurepip -"$HOME/.rye/self/bin/python3" -m pip install 'importlib-metadata==7.2.1' rye publish --yes --token=$PYPI_TOKEN diff --git a/pyproject.toml b/pyproject.toml index 27f6e0e3..215f163d 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -86,7 +86,7 @@ typecheck = { chain = [ "typecheck:mypy" = "mypy ." [build-system] -requires = ["hatchling", "hatch-fancy-pypi-readme"] +requires = ["hatchling==1.26.3", "hatch-fancy-pypi-readme"] build-backend = "hatchling.build" [tool.hatch.build] From 6179f1558884a9f1663f65496d7b15957b710ae8 Mon Sep 17 00:00:00 2001 From: "stainless-app[bot]" <142633134+stainless-app[bot]@users.noreply.github.com> Date: Tue, 25 Mar 2025 16:25:06 +0000 Subject: [PATCH 17/18] feat(api): api update (#624) --- .stats.yml | 2 +- src/finch/resources/hris/documents.py | 16 ++++++++-------- tests/api_resources/sandbox/test_company.py | 16 ++++++++-------- 3 files changed, 17 insertions(+), 17 deletions(-) diff --git a/.stats.yml b/.stats.yml index 424dc58b..fc279b3c 100644 --- a/.stats.yml +++ b/.stats.yml @@ -1,2 +1,2 @@ configured_endpoints: 41 -openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/finch%2Ffinch-f1779210fbedfc6099076412405288b489f727cbb0b3a85e7b7c12fabb37ef47.yml +openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/finch%2Ffinch-69819ddc6d03624ee8d880317fca03afab50a0a843218f1d9f14616e8a003dad.yml diff --git a/src/finch/resources/hris/documents.py b/src/finch/resources/hris/documents.py index 4413f816..6c60b2f8 100644 --- a/src/finch/resources/hris/documents.py +++ b/src/finch/resources/hris/documents.py @@ -60,8 +60,8 @@ def list( ) -> DocumentListResponse: """**Beta:** This endpoint is in beta and may change. - - Retrieve a list of company-wide documents. + Retrieve a list of + company-wide documents. Args: individual_ids: Comma-delimited list of stable Finch uuids for each individual. If empty, @@ -115,8 +115,8 @@ def retreive( ) -> DocumentRetreiveResponse: """**Beta:** This endpoint is in beta and may change. - - Retrieve details of a specific document by its ID. + Retrieve details of a + specific document by its ID. Args: extra_headers: Send extra headers @@ -179,8 +179,8 @@ async def list( ) -> DocumentListResponse: """**Beta:** This endpoint is in beta and may change. - - Retrieve a list of company-wide documents. + Retrieve a list of + company-wide documents. Args: individual_ids: Comma-delimited list of stable Finch uuids for each individual. If empty, @@ -234,8 +234,8 @@ async def retreive( ) -> DocumentRetreiveResponse: """**Beta:** This endpoint is in beta and may change. - - Retrieve details of a specific document by its ID. + Retrieve details of a + specific document by its ID. Args: extra_headers: Send extra headers diff --git a/tests/api_resources/sandbox/test_company.py b/tests/api_resources/sandbox/test_company.py index 3c89e1c6..aa0e957f 100644 --- a/tests/api_resources/sandbox/test_company.py +++ b/tests/api_resources/sandbox/test_company.py @@ -26,7 +26,7 @@ def test_method_update(self, client: Finch) -> None: entity={}, legal_name="legal_name", locations=[{}], - primary_email="primary_email", + primary_email="dev@stainless.com", primary_phone_number="primary_phone_number", ) assert_matches_type(CompanyUpdateResponse, company, path=["response"]) @@ -67,7 +67,7 @@ def test_method_update_with_all_params(self, client: Finch) -> None: "state": "state", } ], - primary_email="primary_email", + primary_email="dev@stainless.com", primary_phone_number="primary_phone_number", ) assert_matches_type(CompanyUpdateResponse, company, path=["response"]) @@ -81,7 +81,7 @@ def test_raw_response_update(self, client: Finch) -> None: entity={}, legal_name="legal_name", locations=[{}], - primary_email="primary_email", + primary_email="dev@stainless.com", primary_phone_number="primary_phone_number", ) @@ -99,7 +99,7 @@ def test_streaming_response_update(self, client: Finch) -> None: entity={}, legal_name="legal_name", locations=[{}], - primary_email="primary_email", + primary_email="dev@stainless.com", primary_phone_number="primary_phone_number", ) as response: assert not response.is_closed @@ -123,7 +123,7 @@ async def test_method_update(self, async_client: AsyncFinch) -> None: entity={}, legal_name="legal_name", locations=[{}], - primary_email="primary_email", + primary_email="dev@stainless.com", primary_phone_number="primary_phone_number", ) assert_matches_type(CompanyUpdateResponse, company, path=["response"]) @@ -164,7 +164,7 @@ async def test_method_update_with_all_params(self, async_client: AsyncFinch) -> "state": "state", } ], - primary_email="primary_email", + primary_email="dev@stainless.com", primary_phone_number="primary_phone_number", ) assert_matches_type(CompanyUpdateResponse, company, path=["response"]) @@ -178,7 +178,7 @@ async def test_raw_response_update(self, async_client: AsyncFinch) -> None: entity={}, legal_name="legal_name", locations=[{}], - primary_email="primary_email", + primary_email="dev@stainless.com", primary_phone_number="primary_phone_number", ) @@ -196,7 +196,7 @@ async def test_streaming_response_update(self, async_client: AsyncFinch) -> None entity={}, legal_name="legal_name", locations=[{}], - primary_email="primary_email", + primary_email="dev@stainless.com", primary_phone_number="primary_phone_number", ) as response: assert not response.is_closed From 29e8011114022672c67193edee4ca7a523e6a7b3 Mon Sep 17 00:00:00 2001 From: "stainless-app[bot]" <142633134+stainless-app[bot]@users.noreply.github.com> Date: Tue, 25 Mar 2025 16:25:33 +0000 Subject: [PATCH 18/18] release: 1.17.0 --- .release-please-manifest.json | 2 +- CHANGELOG.md | 33 +++++++++++++++++++++++++++++++++ pyproject.toml | 2 +- src/finch/_version.py | 2 +- 4 files changed, 36 insertions(+), 3 deletions(-) diff --git a/.release-please-manifest.json b/.release-please-manifest.json index bc845f32..6a197bef 100644 --- a/.release-please-manifest.json +++ b/.release-please-manifest.json @@ -1,3 +1,3 @@ { - ".": "1.16.0" + ".": "1.17.0" } \ No newline at end of file diff --git a/CHANGELOG.md b/CHANGELOG.md index 1fc40806..5cc38458 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,38 @@ # Changelog +## 1.17.0 (2025-03-25) + +Full Changelog: [v1.16.0...v1.17.0](https://github.com/Finch-API/finch-api-python/compare/v1.16.0...v1.17.0) + +### Features + +* **api:** api update ([#624](https://github.com/Finch-API/finch-api-python/issues/624)) ([6179f15](https://github.com/Finch-API/finch-api-python/commit/6179f1558884a9f1663f65496d7b15957b710ae8)) +* **api:** manual updates ([#612](https://github.com/Finch-API/finch-api-python/issues/612)) ([ac90061](https://github.com/Finch-API/finch-api-python/commit/ac900617af1bc37b728cbbc69ba22c5061ffddb7)) + + +### Bug Fixes + +* **ci:** ensure pip is always available ([#622](https://github.com/Finch-API/finch-api-python/issues/622)) ([bffb854](https://github.com/Finch-API/finch-api-python/commit/bffb8540f25ba56cfeb452d0c92dbadb291d88e9)) +* **ci:** remove publishing patch ([#623](https://github.com/Finch-API/finch-api-python/issues/623)) ([419c35a](https://github.com/Finch-API/finch-api-python/commit/419c35ad3f89c7da406c33a67069f0e8a7937aa4)) +* **types:** handle more discriminated union shapes ([#621](https://github.com/Finch-API/finch-api-python/issues/621)) ([971eac8](https://github.com/Finch-API/finch-api-python/commit/971eac8aef3ad9a5b87b70567726cb0c524b9251)) + + +### Chores + +* **docs:** update client docstring ([#610](https://github.com/Finch-API/finch-api-python/issues/610)) ([2bae32b](https://github.com/Finch-API/finch-api-python/commit/2bae32b4504f2e17d53238d2ef7c6267c9d19636)) +* **internal:** bump rye to 0.44.0 ([#619](https://github.com/Finch-API/finch-api-python/issues/619)) ([c62de3c](https://github.com/Finch-API/finch-api-python/commit/c62de3cf8821a5bfb814547c68939e78411d0681)) +* **internal:** codegen related update ([#611](https://github.com/Finch-API/finch-api-python/issues/611)) ([f397f20](https://github.com/Finch-API/finch-api-python/commit/f397f2097d2d349d16a46c2fbf79432c6d48290c)) +* **internal:** codegen related update ([#614](https://github.com/Finch-API/finch-api-python/issues/614)) ([6dd5f30](https://github.com/Finch-API/finch-api-python/commit/6dd5f30dfb8eb5b82500fd18e9472813b84bfdfc)) +* **internal:** codegen related update ([#615](https://github.com/Finch-API/finch-api-python/issues/615)) ([1ffccaf](https://github.com/Finch-API/finch-api-python/commit/1ffccafbb26c672fdea41495b91774babb9cdb06)) +* **internal:** codegen related update ([#617](https://github.com/Finch-API/finch-api-python/issues/617)) ([9c2b530](https://github.com/Finch-API/finch-api-python/commit/9c2b530e4a89d19276ba031558bc9f077069aa92)) +* **internal:** codegen related update ([#620](https://github.com/Finch-API/finch-api-python/issues/620)) ([735fb42](https://github.com/Finch-API/finch-api-python/commit/735fb42343c68e6e484a0ac962c0946fc4643659)) +* **internal:** remove extra empty newlines ([#618](https://github.com/Finch-API/finch-api-python/issues/618)) ([a18d4b5](https://github.com/Finch-API/finch-api-python/commit/a18d4b59192e8efdd5ce03d6e3e88fcc0135f9ec)) + + +### Documentation + +* update URLs from stainlessapi.com to stainless.com ([#608](https://github.com/Finch-API/finch-api-python/issues/608)) ([5df7857](https://github.com/Finch-API/finch-api-python/commit/5df78577187ab33565e3cc2b72fcd0a51c9531db)) + ## 1.16.0 (2025-02-27) Full Changelog: [v1.15.0...v1.16.0](https://github.com/Finch-API/finch-api-python/compare/v1.15.0...v1.16.0) diff --git a/pyproject.toml b/pyproject.toml index 215f163d..2a035143 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -1,6 +1,6 @@ [project] name = "finch-api" -version = "1.16.0" +version = "1.17.0" description = "The official Python library for the Finch API" dynamic = ["readme"] license = "Apache-2.0" diff --git a/src/finch/_version.py b/src/finch/_version.py index 49d3934d..8d7d3f5a 100644 --- a/src/finch/_version.py +++ b/src/finch/_version.py @@ -1,4 +1,4 @@ # File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. __title__ = "finch" -__version__ = "1.16.0" # x-release-please-version +__version__ = "1.17.0" # x-release-please-version