diff --git a/README.md b/README.md index 656bc5b8..6b330f26 100644 --- a/README.md +++ b/README.md @@ -8,7 +8,7 @@ and offers both synchronous and asynchronous clients powered by [httpx](https:// ## Documentation -The API documentation can be found at [https://developer.tryfinch.com/](https://developer.tryfinch.com/). +The API documentation can be found [in the Finch Documentation Center](https://developer.tryfinch.com/). ## Installation @@ -27,7 +27,7 @@ client = Finch( access_token="my access token", ) -page = client.hris.directory.list_individuals( +page = client.hris.directory.list( candidate_id="", ) directory = page.individuals[0] @@ -47,7 +47,7 @@ client = AsyncFinch( async def main(): - page = await client.hris.directory.list_individuals( + page = await client.hris.directory.list( candidate_id="", ) print(page.individuals[0].first_name) @@ -77,7 +77,7 @@ client = Finch() all_directories = [] # Automatically fetches more pages as needed. -for directory in client.hris.directory.list_individuals(): +for directory in client.hris.directory.list(): # Do something with directory here all_directories.append(directory) print(all_directories) @@ -95,7 +95,7 @@ client = AsyncFinch() async def main() -> None: all_directories = [] # Iterate through items across all pages, issuing requests as needed. - async for directory in client.hris.directory.list_individuals(): + async for directory in client.hris.directory.list(): all_directories.append(directory) print(all_directories) @@ -106,7 +106,7 @@ asyncio.run(main()) Alternatively, you can use the `.has_next_page()`, `.next_page_info()`, or `.get_next_page()` methods for more granular control working with pages: ```python -first_page = await client.hris.directory.list_individuals() +first_page = await client.hris.directory.list() if first_page.has_next_page(): print(f"will fetch next page using these details: {first_page.next_page_info()}") next_page = await first_page.get_next_page() @@ -118,7 +118,7 @@ if first_page.has_next_page(): Or just work directly with the returned data: ```python -first_page = await client.hris.directory.list_individuals() +first_page = await client.hris.directory.list() print( f"the current start offset for this page: {first_page.paging.offset}" @@ -138,7 +138,7 @@ from finch import Finch client = Finch() -client.hris.directory.list_individuals( +client.hris.directory.list( path_params=[], params={}, ) @@ -183,7 +183,7 @@ from finch import Finch client = Finch() try: - client.hris.directory.list_individuals() + client.hris.directory.list() except finch.APIConnectionError as e: print("The server could not be reached") print(e.__cause__) # an underlying Exception, likely raised within httpx. @@ -226,7 +226,7 @@ client = Finch( ) # Or, configure per-request: -client.with_options(max_retries=5).hris.directory.list_individuals() +client.with_options(max_retries=5).hris.directory.list() ``` ### Timeouts @@ -249,7 +249,7 @@ client = Finch( ) # Override per-request: -client.with_options(timeout=5 * 1000).hris.directory.list_individuals() +client.with_options(timeout=5 * 1000).hris.directory.list() ``` On timeout, an `APITimeoutError` is thrown. @@ -313,7 +313,7 @@ By default the library closes underlying HTTP connections whenever the client is ## Versioning -This package generally attempts to follow [SemVer](https://semver.org/spec/v2.0.0.html) conventions, though certain backwards-incompatible changes may be released as minor versions: +This package generally follows [SemVer](https://semver.org/spec/v2.0.0.html) conventions, though certain backwards-incompatible changes may be released as minor versions: 1. Changes that only affect static types, without breaking runtime behavior. 2. Changes to library internals which are technically public but not intended or documented for external use. _(Please open a GitHub issue to let us know if you are relying on such internals)_. diff --git a/api.md b/api.md index f2ebbce6..df158a2e 100644 --- a/api.md +++ b/api.md @@ -35,7 +35,7 @@ from finch.types.hris import IndividualInDirectory Methods: -- client.hris.directory.list_individuals(\*\*params) -> SyncIndividualsPage[IndividualInDirectory] +- client.hris.directory.list(\*\*params) -> SyncIndividualsPage[IndividualInDirectory] ## Individuals @@ -95,6 +95,7 @@ Types: ```python from finch.types.hris import ( + BenefitContribution, BenefitFrequency, BenefitType, BenfitContribution, diff --git a/src/finch/resources/hris/directory.py b/src/finch/resources/hris/directory.py index 0076a97c..a13a1c3a 100644 --- a/src/finch/resources/hris/directory.py +++ b/src/finch/resources/hris/directory.py @@ -2,18 +2,20 @@ from __future__ import annotations +import typing_extensions + from ..._types import NOT_GIVEN, Body, Query, Headers, NotGiven from ..._utils import maybe_transform from ..._resource import SyncAPIResource, AsyncAPIResource from ...pagination import SyncIndividualsPage, AsyncIndividualsPage -from ...types.hris import IndividualInDirectory, directory_list_individuals_params +from ...types.hris import IndividualInDirectory, directory_list_params from ..._base_client import AsyncPaginator, make_request_options __all__ = ["Directory", "AsyncDirectory"] class Directory(SyncAPIResource): - def list_individuals( + def list( self, *, limit: int | NotGiven = NOT_GIVEN, @@ -54,15 +56,53 @@ def list_individuals( "limit": limit, "offset": offset, }, - directory_list_individuals_params.DirectoryListIndividualsParams, + directory_list_params.DirectoryListParams, ), ), model=IndividualInDirectory, ) + @typing_extensions.deprecated("use `list` instead") + def list_individuals( + self, + *, + limit: int | NotGiven = NOT_GIVEN, + offset: int | NotGiven = NOT_GIVEN, + # Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs. + # The extra values given here take precedence over values defined on the client or passed to this method. + extra_headers: Headers | None = None, + extra_query: Query | None = None, + extra_body: Body | None = None, + timeout: float | None | NotGiven = NOT_GIVEN, + ) -> SyncIndividualsPage[IndividualInDirectory]: + """ + Read company directory and organization structure + + Args: + limit: Number of employees to return (defaults to all) + + offset: Index to start from (defaults to 0) + + 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.list( + limit=limit, + offset=offset, + extra_headers=extra_headers, + extra_query=extra_query, + extra_body=extra_body, + timeout=timeout, + ) + class AsyncDirectory(AsyncAPIResource): - def list_individuals( + def list( self, *, limit: int | NotGiven = NOT_GIVEN, @@ -103,8 +143,46 @@ def list_individuals( "limit": limit, "offset": offset, }, - directory_list_individuals_params.DirectoryListIndividualsParams, + directory_list_params.DirectoryListParams, ), ), model=IndividualInDirectory, ) + + @typing_extensions.deprecated("use `list` instead") + def list_individuals( + self, + *, + limit: int | NotGiven = NOT_GIVEN, + offset: int | NotGiven = NOT_GIVEN, + # Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs. + # The extra values given here take precedence over values defined on the client or passed to this method. + extra_headers: Headers | None = None, + extra_query: Query | None = None, + extra_body: Body | None = None, + timeout: float | None | NotGiven = NOT_GIVEN, + ) -> AsyncPaginator[IndividualInDirectory, AsyncIndividualsPage[IndividualInDirectory]]: + """ + Read company directory and organization structure + + Args: + limit: Number of employees to return (defaults to all) + + offset: Index to start from (defaults to 0) + + 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.list( + limit=limit, + offset=offset, + extra_headers=extra_headers, + extra_query=extra_query, + extra_body=extra_body, + timeout=timeout, + ) diff --git a/src/finch/types/hris/__init__.py b/src/finch/types/hris/__init__.py index 844182fe..95dcb512 100644 --- a/src/finch/types/hris/__init__.py +++ b/src/finch/types/hris/__init__.py @@ -14,8 +14,10 @@ from .benfit_contribution import BenfitContribution as BenfitContribution from .individual_response import IndividualResponse as IndividualResponse from .payment_list_params import PaymentListParams as PaymentListParams +from .benefit_contribution import BenefitContribution as BenefitContribution from .benefit_create_params import BenefitCreateParams as BenefitCreateParams from .benefit_update_params import BenefitUpdateParams as BenefitUpdateParams +from .directory_list_params import DirectoryListParams as DirectoryListParams from .pay_statement_response import PayStatementResponse as PayStatementResponse from .individual_in_directory import IndividualInDirectory as IndividualInDirectory from .employment_data_response import EmploymentDataResponse as EmploymentDataResponse diff --git a/src/finch/types/hris/benefit_contribution.py b/src/finch/types/hris/benefit_contribution.py new file mode 100644 index 00000000..48ecc288 --- /dev/null +++ b/src/finch/types/hris/benefit_contribution.py @@ -0,0 +1,16 @@ +# File generated from our OpenAPI spec by Stainless. + +from typing import Optional +from typing_extensions import Literal + +from ..._models import BaseModel + +__all__ = ["BenefitContribution"] + + +class BenefitContribution(BaseModel): + amount: Optional[int] = None + """Contribution amount in cents (if `fixed`) or basis points (if `percent`).""" + + type: Optional[Literal["fixed", "percent"]] = None + """Contribution type.""" diff --git a/src/finch/types/hris/benefits/individual_benefit.py b/src/finch/types/hris/benefits/individual_benefit.py index d1b077f4..1016cf1c 100644 --- a/src/finch/types/hris/benefits/individual_benefit.py +++ b/src/finch/types/hris/benefits/individual_benefit.py @@ -4,7 +4,7 @@ from typing_extensions import Literal from ...._models import BaseModel -from ..benfit_contribution import BenfitContribution +from ..benefit_contribution import BenefitContribution __all__ = ["IndividualBenefit", "Body"] @@ -21,9 +21,9 @@ class Body(BaseModel): for this individual. """ - company_contribution: Optional[BenfitContribution] = None + company_contribution: Optional[BenefitContribution] = None - employee_deduction: Optional[BenfitContribution] = None + employee_deduction: Optional[BenefitContribution] = None hsa_contribution_limit: Optional[Literal["individual", "family"]] = None """Type for HSA contribution limit if the benefit is a HSA.""" diff --git a/src/finch/types/hris/benfit_contribution.py b/src/finch/types/hris/benfit_contribution.py index 4f30c065..522d5602 100644 --- a/src/finch/types/hris/benfit_contribution.py +++ b/src/finch/types/hris/benfit_contribution.py @@ -1,16 +1,7 @@ # File generated from our OpenAPI spec by Stainless. -from typing import Optional -from typing_extensions import Literal -from ..._models import BaseModel +from .benefit_contribution import BenefitContribution -__all__ = ["BenfitContribution"] - - -class BenfitContribution(BaseModel): - amount: Optional[int] = None - """Contribution amount in cents (if `fixed`) or basis points (if `percent`).""" - - type: Optional[Literal["fixed", "percent"]] = None - """Contribution type.""" +BenfitContribution = BenefitContribution +"""use `BenefitContribution` instead""" diff --git a/src/finch/types/hris/company_benefit.py b/src/finch/types/hris/company_benefit.py index c2d24202..224f9437 100644 --- a/src/finch/types/hris/company_benefit.py +++ b/src/finch/types/hris/company_benefit.py @@ -5,7 +5,7 @@ from ..._models import BaseModel from .benefit_type import BenefitType from .benefit_frequency import BenefitFrequency -from .benfit_contribution import BenfitContribution +from .benefit_contribution import BenefitContribution __all__ = ["CompanyBenefit"] @@ -13,11 +13,11 @@ class CompanyBenefit(BaseModel): benefit_id: str - company_contribution: Optional[BenfitContribution] + company_contribution: Optional[BenefitContribution] description: Optional[str] - employee_deduction: Optional[BenfitContribution] + employee_deduction: Optional[BenefitContribution] frequency: Optional[BenefitFrequency] diff --git a/src/finch/types/hris/directory_list_params.py b/src/finch/types/hris/directory_list_params.py new file mode 100644 index 00000000..83741e8b --- /dev/null +++ b/src/finch/types/hris/directory_list_params.py @@ -0,0 +1,15 @@ +# File generated from our OpenAPI spec by Stainless. + +from __future__ import annotations + +from typing_extensions import TypedDict + +__all__ = ["DirectoryListParams"] + + +class DirectoryListParams(TypedDict, total=False): + limit: int + """Number of employees to return (defaults to all)""" + + offset: int + """Index to start from (defaults to 0)""" diff --git a/tests/api_resources/hris/test_directory.py b/tests/api_resources/hris/test_directory.py index d2ff1cd4..3bafc55f 100644 --- a/tests/api_resources/hris/test_directory.py +++ b/tests/api_resources/hris/test_directory.py @@ -21,18 +21,33 @@ class TestDirectory: parametrize = pytest.mark.parametrize("client", [strict_client, loose_client], ids=["strict", "loose"]) @parametrize - def test_method_list_individuals(self, client: Finch) -> None: - directory = client.hris.directory.list_individuals() + def test_method_list(self, client: Finch) -> None: + directory = client.hris.directory.list() assert_matches_type(SyncIndividualsPage[IndividualInDirectory], directory, path=["response"]) @parametrize - def test_method_list_individuals_with_all_params(self, client: Finch) -> None: - directory = client.hris.directory.list_individuals( + def test_method_list_with_all_params(self, client: Finch) -> None: + directory = client.hris.directory.list( limit=0, offset=0, ) assert_matches_type(SyncIndividualsPage[IndividualInDirectory], directory, path=["response"]) + @parametrize + def test_method_list_individuals(self, client: Finch) -> None: + with pytest.warns(DeprecationWarning): + directory = client.hris.directory.list_individuals() # pyright: ignore[reportDeprecated] + assert_matches_type(SyncIndividualsPage[IndividualInDirectory], directory, path=["response"]) + + @parametrize + def test_method_list_individuals_with_all_params(self, client: Finch) -> None: + with pytest.warns(DeprecationWarning): + directory = client.hris.directory.list_individuals( # pyright: ignore[reportDeprecated] + limit=0, + offset=0, + ) + assert_matches_type(SyncIndividualsPage[IndividualInDirectory], directory, path=["response"]) + class TestAsyncDirectory: strict_client = AsyncFinch(base_url=base_url, access_token=access_token, _strict_response_validation=True) @@ -40,14 +55,29 @@ class TestAsyncDirectory: parametrize = pytest.mark.parametrize("client", [strict_client, loose_client], ids=["strict", "loose"]) @parametrize - async def test_method_list_individuals(self, client: AsyncFinch) -> None: - directory = await client.hris.directory.list_individuals() + async def test_method_list(self, client: AsyncFinch) -> None: + directory = await client.hris.directory.list() assert_matches_type(AsyncIndividualsPage[IndividualInDirectory], directory, path=["response"]) @parametrize - async def test_method_list_individuals_with_all_params(self, client: AsyncFinch) -> None: - directory = await client.hris.directory.list_individuals( + async def test_method_list_with_all_params(self, client: AsyncFinch) -> None: + directory = await client.hris.directory.list( limit=0, offset=0, ) assert_matches_type(AsyncIndividualsPage[IndividualInDirectory], directory, path=["response"]) + + @parametrize + async def test_method_list_individuals(self, client: AsyncFinch) -> None: + with pytest.warns(DeprecationWarning): + directory = await client.hris.directory.list_individuals() # pyright: ignore[reportDeprecated] + assert_matches_type(AsyncIndividualsPage[IndividualInDirectory], directory, path=["response"]) + + @parametrize + async def test_method_list_individuals_with_all_params(self, client: AsyncFinch) -> None: + with pytest.warns(DeprecationWarning): + directory = await client.hris.directory.list_individuals( # pyright: ignore[reportDeprecated] + limit=0, + offset=0, + ) + assert_matches_type(AsyncIndividualsPage[IndividualInDirectory], directory, path=["response"]) diff --git a/tests/test_client.py b/tests/test_client.py index d2f1cee4..a8d86ce4 100644 --- a/tests/test_client.py +++ b/tests/test_client.py @@ -56,7 +56,7 @@ def test_copy(self) -> None: assert self.client.access_token == access_token def test_copy_default_options(self) -> None: - # options that have a default are overriden correctly + # options that have a default are overridden correctly copied = self.client.copy(max_retries=7) assert copied.max_retries == 7 assert self.client.max_retries == 2 @@ -685,7 +685,7 @@ def test_copy(self) -> None: assert self.client.access_token == access_token def test_copy_default_options(self) -> None: - # options that have a default are overriden correctly + # options that have a default are overridden correctly copied = self.client.copy(max_retries=7) assert copied.max_retries == 7 assert self.client.max_retries == 2