From d69573f3c088e6cc02794213276038cee7ae59ce Mon Sep 17 00:00:00 2001 From: Stainless Bot Date: Sat, 6 Jan 2024 01:00:11 +0000 Subject: [PATCH] feat(api): add method to create access token --- .stats.yml | 2 +- api.md | 13 ++ src/finch/_client.py | 26 ++++ src/finch/resources/__init__.py | 10 ++ src/finch/resources/access_tokens.py | 129 ++++++++++++++++++ src/finch/types/__init__.py | 2 + src/finch/types/access_token_create_params.py | 17 +++ .../types/create_access_token_response.py | 9 ++ tests/api_resources/test_access_tokens.py | 71 ++++++++++ 9 files changed, 278 insertions(+), 1 deletion(-) create mode 100644 src/finch/resources/access_tokens.py create mode 100644 src/finch/types/access_token_create_params.py create mode 100644 src/finch/types/create_access_token_response.py create mode 100644 tests/api_resources/test_access_tokens.py diff --git a/.stats.yml b/.stats.yml index c125dfb2..e16f1ad2 100644 --- a/.stats.yml +++ b/.stats.yml @@ -1 +1 @@ -configured_endpoints: 23 +configured_endpoints: 24 diff --git a/api.md b/api.md index 6207a701..b920447c 100644 --- a/api.md +++ b/api.md @@ -10,6 +10,19 @@ Methods: - client.get_access_token(\*args) -> str - client.get_auth_url(\*args) -> str +- client.with_access_token(\*args) -> Self + +# AccessTokens + +Types: + +```python +from finch.types import CreateAccessTokenResponse +``` + +Methods: + +- client.access_tokens.create(\*\*params) -> CreateAccessTokenResponse # HRIS diff --git a/src/finch/_client.py b/src/finch/_client.py index f11a51ed..d6e88d57 100644 --- a/src/finch/_client.py +++ b/src/finch/_client.py @@ -51,6 +51,7 @@ class Finch(SyncAPIClient): + access_tokens: resources.AccessTokens hris: resources.HRIS providers: resources.Providers account: resources.Account @@ -135,6 +136,7 @@ def __init__( _strict_response_validation=_strict_response_validation, ) + self.access_tokens = resources.AccessTokens(self) self.hris = resources.HRIS(self) self.providers = resources.Providers(self) self.account = resources.Account(self) @@ -311,6 +313,16 @@ def get_auth_url( ) ) + def with_access_token( + self, + access_token: str, + ) -> Self: + """ + Returns a copy of the current Finch client with the given access token for + authentication. + """ + return self.with_options(access_token=access_token) + @override def _make_status_error( self, @@ -346,6 +358,7 @@ def _make_status_error( class AsyncFinch(AsyncAPIClient): + access_tokens: resources.AsyncAccessTokens hris: resources.AsyncHRIS providers: resources.AsyncProviders account: resources.AsyncAccount @@ -430,6 +443,7 @@ def __init__( _strict_response_validation=_strict_response_validation, ) + self.access_tokens = resources.AsyncAccessTokens(self) self.hris = resources.AsyncHRIS(self) self.providers = resources.AsyncProviders(self) self.account = resources.AsyncAccount(self) @@ -606,6 +620,16 @@ def get_auth_url( ) ) + def with_access_token( + self, + access_token: str, + ) -> Self: + """ + Returns a copy of the current Finch client with the given access token for + authentication. + """ + return self.with_options(access_token=access_token) + @override def _make_status_error( self, @@ -642,6 +666,7 @@ def _make_status_error( class FinchWithRawResponse: def __init__(self, client: Finch) -> None: + self.access_tokens = resources.AccessTokensWithRawResponse(client.access_tokens) self.hris = resources.HRISWithRawResponse(client.hris) self.providers = resources.ProvidersWithRawResponse(client.providers) self.account = resources.AccountWithRawResponse(client.account) @@ -651,6 +676,7 @@ def __init__(self, client: Finch) -> None: class AsyncFinchWithRawResponse: def __init__(self, client: AsyncFinch) -> None: + self.access_tokens = resources.AsyncAccessTokensWithRawResponse(client.access_tokens) self.hris = resources.AsyncHRISWithRawResponse(client.hris) self.providers = resources.AsyncProvidersWithRawResponse(client.providers) self.account = resources.AsyncAccountWithRawResponse(client.account) diff --git a/src/finch/resources/__init__.py b/src/finch/resources/__init__.py index 32d0cf28..152e5776 100644 --- a/src/finch/resources/__init__.py +++ b/src/finch/resources/__init__.py @@ -5,6 +5,12 @@ from .account import Account, AsyncAccount, AccountWithRawResponse, AsyncAccountWithRawResponse from .webhooks import Webhooks, AsyncWebhooks from .providers import Providers, AsyncProviders, ProvidersWithRawResponse, AsyncProvidersWithRawResponse +from .access_tokens import ( + AccessTokens, + AsyncAccessTokens, + AccessTokensWithRawResponse, + AsyncAccessTokensWithRawResponse, +) from .request_forwarding import ( RequestForwarding, AsyncRequestForwarding, @@ -13,6 +19,10 @@ ) __all__ = [ + "AccessTokens", + "AsyncAccessTokens", + "AccessTokensWithRawResponse", + "AsyncAccessTokensWithRawResponse", "HRIS", "AsyncHRIS", "HRISWithRawResponse", diff --git a/src/finch/resources/access_tokens.py b/src/finch/resources/access_tokens.py new file mode 100644 index 00000000..161da255 --- /dev/null +++ b/src/finch/resources/access_tokens.py @@ -0,0 +1,129 @@ +# File generated from our OpenAPI spec by Stainless. + +from __future__ import annotations + +import httpx + +from ..types import CreateAccessTokenResponse, access_token_create_params +from .._types import NOT_GIVEN, Body, Query, Headers, NotGiven +from .._utils import maybe_transform +from .._compat import cached_property +from .._resource import SyncAPIResource, AsyncAPIResource +from .._response import to_raw_response_wrapper, async_to_raw_response_wrapper +from .._base_client import ( + make_request_options, +) + +__all__ = ["AccessTokens", "AsyncAccessTokens"] + + +class AccessTokens(SyncAPIResource): + @cached_property + def with_raw_response(self) -> AccessTokensWithRawResponse: + return AccessTokensWithRawResponse(self) + + def create( + self, + *, + client_id: str, + client_secret: str, + code: str, + redirect_uri: str, + # Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs. + # The extra values given here take precedence over values defined on the client or passed to this method. + extra_headers: Headers | None = None, + extra_query: Query | None = None, + extra_body: Body | None = None, + timeout: float | httpx.Timeout | None | NotGiven = NOT_GIVEN, + ) -> CreateAccessTokenResponse: + """ + Exchange the authorization code for an access token + + Args: + extra_headers: Send extra headers + + extra_query: Add additional query parameters to the request + + extra_body: Add additional JSON properties to the request + + timeout: Override the client-level default timeout for this request, in seconds + """ + return self._post( + "/auth/token", + body=maybe_transform( + { + "client_id": client_id, + "client_secret": client_secret, + "code": code, + "redirect_uri": redirect_uri, + }, + access_token_create_params.AccessTokenCreateParams, + ), + options=make_request_options( + extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout + ), + cast_to=CreateAccessTokenResponse, + ) + + +class AsyncAccessTokens(AsyncAPIResource): + @cached_property + def with_raw_response(self) -> AsyncAccessTokensWithRawResponse: + return AsyncAccessTokensWithRawResponse(self) + + async def create( + self, + *, + client_id: str, + client_secret: str, + code: str, + redirect_uri: str, + # Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs. + # The extra values given here take precedence over values defined on the client or passed to this method. + extra_headers: Headers | None = None, + extra_query: Query | None = None, + extra_body: Body | None = None, + timeout: float | httpx.Timeout | None | NotGiven = NOT_GIVEN, + ) -> CreateAccessTokenResponse: + """ + Exchange the authorization code for an access token + + Args: + extra_headers: Send extra headers + + extra_query: Add additional query parameters to the request + + extra_body: Add additional JSON properties to the request + + timeout: Override the client-level default timeout for this request, in seconds + """ + return await self._post( + "/auth/token", + body=maybe_transform( + { + "client_id": client_id, + "client_secret": client_secret, + "code": code, + "redirect_uri": redirect_uri, + }, + access_token_create_params.AccessTokenCreateParams, + ), + options=make_request_options( + extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout + ), + cast_to=CreateAccessTokenResponse, + ) + + +class AccessTokensWithRawResponse: + def __init__(self, access_tokens: AccessTokens) -> None: + self.create = to_raw_response_wrapper( + access_tokens.create, + ) + + +class AsyncAccessTokensWithRawResponse: + def __init__(self, access_tokens: AsyncAccessTokens) -> None: + self.create = async_to_raw_response_wrapper( + access_tokens.create, + ) diff --git a/src/finch/types/__init__.py b/src/finch/types/__init__.py index ece2573d..e8b6a6dd 100644 --- a/src/finch/types/__init__.py +++ b/src/finch/types/__init__.py @@ -13,5 +13,7 @@ from .provider import Provider as Provider from .introspection import Introspection as Introspection from .disconnect_response import DisconnectResponse as DisconnectResponse +from .access_token_create_params import AccessTokenCreateParams as AccessTokenCreateParams +from .create_access_token_response import CreateAccessTokenResponse as CreateAccessTokenResponse from .request_forwarding_forward_params import RequestForwardingForwardParams as RequestForwardingForwardParams from .request_forwarding_forward_response import RequestForwardingForwardResponse as RequestForwardingForwardResponse diff --git a/src/finch/types/access_token_create_params.py b/src/finch/types/access_token_create_params.py new file mode 100644 index 00000000..2fc25749 --- /dev/null +++ b/src/finch/types/access_token_create_params.py @@ -0,0 +1,17 @@ +# File generated from our OpenAPI spec by Stainless. + +from __future__ import annotations + +from typing_extensions import Required, TypedDict + +__all__ = ["AccessTokenCreateParams"] + + +class AccessTokenCreateParams(TypedDict, total=False): + client_id: Required[str] + + client_secret: Required[str] + + code: Required[str] + + redirect_uri: Required[str] diff --git a/src/finch/types/create_access_token_response.py b/src/finch/types/create_access_token_response.py new file mode 100644 index 00000000..5b017fc2 --- /dev/null +++ b/src/finch/types/create_access_token_response.py @@ -0,0 +1,9 @@ +# File generated from our OpenAPI spec by Stainless. + +from .._models import BaseModel + +__all__ = ["CreateAccessTokenResponse"] + + +class CreateAccessTokenResponse(BaseModel): + access_token: str diff --git a/tests/api_resources/test_access_tokens.py b/tests/api_resources/test_access_tokens.py new file mode 100644 index 00000000..4a89d515 --- /dev/null +++ b/tests/api_resources/test_access_tokens.py @@ -0,0 +1,71 @@ +# File generated from our OpenAPI spec by Stainless. + +from __future__ import annotations + +import os + +import pytest + +from finch import Finch, AsyncFinch +from finch.types import CreateAccessTokenResponse +from tests.utils import assert_matches_type +from finch._client import Finch, AsyncFinch + +base_url = os.environ.get("TEST_API_BASE_URL", "http://127.0.0.1:4010") +access_token = "My Access Token" + + +class TestAccessTokens: + strict_client = Finch(base_url=base_url, access_token=access_token, _strict_response_validation=True) + loose_client = Finch(base_url=base_url, access_token=access_token, _strict_response_validation=False) + parametrize = pytest.mark.parametrize("client", [strict_client, loose_client], ids=["strict", "loose"]) + + @parametrize + def test_method_create(self, client: Finch) -> None: + access_token = client.access_tokens.create( + client_id="", + client_secret="", + code="", + redirect_uri="https://example.com", + ) + assert_matches_type(CreateAccessTokenResponse, access_token, path=["response"]) + + @parametrize + def test_raw_response_create(self, client: Finch) -> None: + response = client.access_tokens.with_raw_response.create( + client_id="", + client_secret="", + code="", + redirect_uri="https://example.com", + ) + assert response.http_request.headers.get("X-Stainless-Lang") == "python" + access_token = response.parse() + assert_matches_type(CreateAccessTokenResponse, access_token, path=["response"]) + + +class TestAsyncAccessTokens: + strict_client = AsyncFinch(base_url=base_url, access_token=access_token, _strict_response_validation=True) + loose_client = AsyncFinch(base_url=base_url, access_token=access_token, _strict_response_validation=False) + parametrize = pytest.mark.parametrize("client", [strict_client, loose_client], ids=["strict", "loose"]) + + @parametrize + async def test_method_create(self, client: AsyncFinch) -> None: + access_token = await client.access_tokens.create( + client_id="", + client_secret="", + code="", + redirect_uri="https://example.com", + ) + assert_matches_type(CreateAccessTokenResponse, access_token, path=["response"]) + + @parametrize + async def test_raw_response_create(self, client: AsyncFinch) -> None: + response = await client.access_tokens.with_raw_response.create( + client_id="", + client_secret="", + code="", + redirect_uri="https://example.com", + ) + assert response.http_request.headers.get("X-Stainless-Lang") == "python" + access_token = response.parse() + assert_matches_type(CreateAccessTokenResponse, access_token, path=["response"])