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