diff --git a/.release-please-manifest.json b/.release-please-manifest.json index a36746b8..caf5ca3f 100644 --- a/.release-please-manifest.json +++ b/.release-please-manifest.json @@ -1,3 +1,3 @@ { - ".": "0.25.0" + ".": "0.26.0" } \ No newline at end of file diff --git a/.stats.yml b/.stats.yml index 7a16060c..06232146 100644 --- a/.stats.yml +++ b/.stats.yml @@ -1,4 +1,4 @@ -configured_endpoints: 18 -openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/hyperspell%2Fhyperspell-55497442c9c2cf4077d1e8661fdf82ebe905dbb140ec65421ffa78da6d06a015.yml -openapi_spec_hash: aa9abda3ed926041c12f664e4225c5ed -config_hash: bd953556a1d60f48307815fdaf9ba88b +configured_endpoints: 20 +openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/hyperspell%2Fhyperspell-cd8c28747615d8967e4e20e6fd5b9488a3022fece37f1c4c133c9b8d9c4415f3.yml +openapi_spec_hash: 2aa6c5d6faa2cbd4038108b5ebc103b3 +config_hash: e29127278ff246754ce4801403db0cd9 diff --git a/CHANGELOG.md b/CHANGELOG.md index ec94995a..ea68271c 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,22 @@ # Changelog +## 0.26.0 (2025-10-14) + +Full Changelog: [v0.25.0...v0.26.0](https://github.com/hyperspell/python-sdk/compare/v0.25.0...v0.26.0) + +### Features + +* **api:** api update ([9f27d7f](https://github.com/hyperspell/python-sdk/commit/9f27d7f462d15b54cf1aa62e962da1d34a03e616)) +* **api:** api update ([476c23d](https://github.com/hyperspell/python-sdk/commit/476c23d01aae74bc13013d71e32430264d45bab1)) +* **api:** update via SDK Studio ([634025a](https://github.com/hyperspell/python-sdk/commit/634025ac77ffe7b2691e53800ee0915dae55e486)) +* **api:** update via SDK Studio ([1f502f0](https://github.com/hyperspell/python-sdk/commit/1f502f0278a7c35e76cbdd8b18b0bb3ab8f69287)) +* **api:** update via SDK Studio ([df1dc5d](https://github.com/hyperspell/python-sdk/commit/df1dc5d547313a241604e554cf515d904ad196a6)) + + +### Chores + +* **internal:** detect missing future annotations with ruff ([210e641](https://github.com/hyperspell/python-sdk/commit/210e641ade71c871f0f80f1c0a0cc043169be302)) + ## 0.25.0 (2025-09-29) Full Changelog: [v0.22.1...v0.25.0](https://github.com/hyperspell/python-sdk/compare/v0.22.1...v0.25.0) diff --git a/api.md b/api.md index 568a25d8..a0af7c08 100644 --- a/api.md +++ b/api.md @@ -9,12 +9,18 @@ from hyperspell.types import QueryResult Types: ```python -from hyperspell.types import IntegrationRevokeResponse +from hyperspell.types import ( + IntegrationListResponse, + IntegrationConnectResponse, + IntegrationRevokeResponse, +) ``` Methods: -- client.integrations.revoke(provider) -> IntegrationRevokeResponse +- client.integrations.list() -> IntegrationListResponse +- client.integrations.connect(integration_id, \*\*params) -> IntegrationConnectResponse +- client.integrations.revoke(integration_id) -> IntegrationRevokeResponse ## GoogleCalendar diff --git a/pyproject.toml b/pyproject.toml index 0cdb5090..1889a095 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -1,6 +1,6 @@ [project] name = "hyperspell" -version = "0.25.0" +version = "0.26.0" description = "The official Python library for the hyperspell API" dynamic = ["readme"] license = "MIT" @@ -224,6 +224,8 @@ select = [ "B", # remove unused imports "F401", + # check for missing future annotations + "FA102", # bare except statements "E722", # unused arguments @@ -246,6 +248,8 @@ unfixable = [ "T203", ] +extend-safe-fixes = ["FA102"] + [tool.ruff.lint.flake8-tidy-imports.banned-api] "functools.lru_cache".msg = "This function does not retain type information for the wrapped function's arguments; The `lru_cache` function from `_utils` should be used instead" diff --git a/src/hyperspell/_version.py b/src/hyperspell/_version.py index 1b27d30f..d4a6d30b 100644 --- a/src/hyperspell/_version.py +++ b/src/hyperspell/_version.py @@ -1,4 +1,4 @@ # File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. __title__ = "hyperspell" -__version__ = "0.25.0" # x-release-please-version +__version__ = "0.26.0" # x-release-please-version diff --git a/src/hyperspell/resources/integrations/integrations.py b/src/hyperspell/resources/integrations/integrations.py index 937c8d3c..178d7b9a 100644 --- a/src/hyperspell/resources/integrations/integrations.py +++ b/src/hyperspell/resources/integrations/integrations.py @@ -2,6 +2,8 @@ from __future__ import annotations +from typing import Optional + import httpx from .slack import ( @@ -12,7 +14,9 @@ SlackResourceWithStreamingResponse, AsyncSlackResourceWithStreamingResponse, ) -from ..._types import Body, Query, Headers, NotGiven, not_given +from ...types import integration_connect_params +from ..._types import Body, Omit, Query, Headers, NotGiven, omit, not_given +from ..._utils import maybe_transform, async_maybe_transform from ..._compat import cached_property from ..._resource import SyncAPIResource, AsyncAPIResource from ..._response import ( @@ -38,7 +42,9 @@ GoogleCalendarResourceWithStreamingResponse, AsyncGoogleCalendarResourceWithStreamingResponse, ) +from ...types.integration_list_response import IntegrationListResponse from ...types.integration_revoke_response import IntegrationRevokeResponse +from ...types.integration_connect_response import IntegrationConnectResponse __all__ = ["IntegrationsResource", "AsyncIntegrationsResource"] @@ -75,9 +81,68 @@ def with_streaming_response(self) -> IntegrationsResourceWithStreamingResponse: """ return IntegrationsResourceWithStreamingResponse(self) + def list( + self, + *, + # 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, + ) -> IntegrationListResponse: + """List all integrations for the user.""" + return self._get( + "/integrations/list", + options=make_request_options( + extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout + ), + cast_to=IntegrationListResponse, + ) + + def connect( + self, + integration_id: str, + *, + redirect_url: Optional[str] | Omit = omit, + # 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, + ) -> IntegrationConnectResponse: + """ + Redirects to the connect URL to link an integration. + + 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 + """ + if not integration_id: + raise ValueError(f"Expected a non-empty value for `integration_id` but received {integration_id!r}") + return self._get( + f"/integrations/{integration_id}/connect", + options=make_request_options( + extra_headers=extra_headers, + extra_query=extra_query, + extra_body=extra_body, + timeout=timeout, + query=maybe_transform( + {"redirect_url": redirect_url}, integration_connect_params.IntegrationConnectParams + ), + ), + cast_to=IntegrationConnectResponse, + ) + def revoke( self, - provider: str, + integration_id: 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. @@ -99,10 +164,10 @@ def revoke( timeout: Override the client-level default timeout for this request, in seconds """ - if not provider: - raise ValueError(f"Expected a non-empty value for `provider` but received {provider!r}") + if not integration_id: + raise ValueError(f"Expected a non-empty value for `integration_id` but received {integration_id!r}") return self._get( - f"/integrations/{provider}/revoke", + f"/integrations/{integration_id}/revoke", options=make_request_options( extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout ), @@ -142,9 +207,68 @@ def with_streaming_response(self) -> AsyncIntegrationsResourceWithStreamingRespo """ return AsyncIntegrationsResourceWithStreamingResponse(self) + async def list( + self, + *, + # 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, + ) -> IntegrationListResponse: + """List all integrations for the user.""" + return await self._get( + "/integrations/list", + options=make_request_options( + extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout + ), + cast_to=IntegrationListResponse, + ) + + async def connect( + self, + integration_id: str, + *, + redirect_url: Optional[str] | Omit = omit, + # 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, + ) -> IntegrationConnectResponse: + """ + Redirects to the connect URL to link an integration. + + 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 + """ + if not integration_id: + raise ValueError(f"Expected a non-empty value for `integration_id` but received {integration_id!r}") + return await self._get( + f"/integrations/{integration_id}/connect", + options=make_request_options( + extra_headers=extra_headers, + extra_query=extra_query, + extra_body=extra_body, + timeout=timeout, + query=await async_maybe_transform( + {"redirect_url": redirect_url}, integration_connect_params.IntegrationConnectParams + ), + ), + cast_to=IntegrationConnectResponse, + ) + async def revoke( self, - provider: str, + integration_id: 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. @@ -166,10 +290,10 @@ async def revoke( timeout: Override the client-level default timeout for this request, in seconds """ - if not provider: - raise ValueError(f"Expected a non-empty value for `provider` but received {provider!r}") + if not integration_id: + raise ValueError(f"Expected a non-empty value for `integration_id` but received {integration_id!r}") return await self._get( - f"/integrations/{provider}/revoke", + f"/integrations/{integration_id}/revoke", options=make_request_options( extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout ), @@ -181,6 +305,12 @@ class IntegrationsResourceWithRawResponse: def __init__(self, integrations: IntegrationsResource) -> None: self._integrations = integrations + self.list = to_raw_response_wrapper( + integrations.list, + ) + self.connect = to_raw_response_wrapper( + integrations.connect, + ) self.revoke = to_raw_response_wrapper( integrations.revoke, ) @@ -202,6 +332,12 @@ class AsyncIntegrationsResourceWithRawResponse: def __init__(self, integrations: AsyncIntegrationsResource) -> None: self._integrations = integrations + self.list = async_to_raw_response_wrapper( + integrations.list, + ) + self.connect = async_to_raw_response_wrapper( + integrations.connect, + ) self.revoke = async_to_raw_response_wrapper( integrations.revoke, ) @@ -223,6 +359,12 @@ class IntegrationsResourceWithStreamingResponse: def __init__(self, integrations: IntegrationsResource) -> None: self._integrations = integrations + self.list = to_streamed_response_wrapper( + integrations.list, + ) + self.connect = to_streamed_response_wrapper( + integrations.connect, + ) self.revoke = to_streamed_response_wrapper( integrations.revoke, ) @@ -244,6 +386,12 @@ class AsyncIntegrationsResourceWithStreamingResponse: def __init__(self, integrations: AsyncIntegrationsResource) -> None: self._integrations = integrations + self.list = async_to_streamed_response_wrapper( + integrations.list, + ) + self.connect = async_to_streamed_response_wrapper( + integrations.connect, + ) self.revoke = async_to_streamed_response_wrapper( integrations.revoke, ) diff --git a/src/hyperspell/types/__init__.py b/src/hyperspell/types/__init__.py index 0ed74dd4..5f3077cf 100644 --- a/src/hyperspell/types/__init__.py +++ b/src/hyperspell/types/__init__.py @@ -17,8 +17,11 @@ from .memory_delete_response import MemoryDeleteResponse as MemoryDeleteResponse from .memory_status_response import MemoryStatusResponse as MemoryStatusResponse from .auth_delete_user_response import AuthDeleteUserResponse as AuthDeleteUserResponse +from .integration_list_response import IntegrationListResponse as IntegrationListResponse +from .integration_connect_params import IntegrationConnectParams as IntegrationConnectParams from .evaluate_score_query_params import EvaluateScoreQueryParams as EvaluateScoreQueryParams from .integration_revoke_response import IntegrationRevokeResponse as IntegrationRevokeResponse +from .integration_connect_response import IntegrationConnectResponse as IntegrationConnectResponse from .evaluate_score_query_response import EvaluateScoreQueryResponse as EvaluateScoreQueryResponse from .evaluate_score_highlight_params import EvaluateScoreHighlightParams as EvaluateScoreHighlightParams from .evaluate_score_highlight_response import EvaluateScoreHighlightResponse as EvaluateScoreHighlightResponse diff --git a/src/hyperspell/types/auth_me_response.py b/src/hyperspell/types/auth_me_response.py index d4ca2c54..7eb70095 100644 --- a/src/hyperspell/types/auth_me_response.py +++ b/src/hyperspell/types/auth_me_response.py @@ -6,7 +6,7 @@ from .._models import BaseModel -__all__ = ["AuthMeResponse", "App"] +__all__ = ["AuthMeResponse", "App", "Connection"] class App(BaseModel): @@ -23,6 +23,64 @@ class App(BaseModel): """The app's redirect URL""" +class Connection(BaseModel): + id: str + """The connection's id""" + + label: Optional[str] = None + """The connection's label""" + + provider: Literal[ + "collections", + "vault", + "web_crawler", + "notion", + "slack", + "google_calendar", + "reddit", + "box", + "google_drive", + "airtable", + "algolia", + "amplitude", + "asana", + "ashby", + "bamboohr", + "basecamp", + "bubbles", + "calendly", + "confluence", + "clickup", + "datadog", + "deel", + "discord", + "dropbox", + "exa", + "facebook", + "front", + "github", + "gitlab", + "google_docs", + "google_mail", + "google_sheet", + "hubspot", + "jira", + "linear", + "microsoft_teams", + "mixpanel", + "monday", + "outlook", + "perplexity", + "rippling", + "salesforce", + "segment", + "todoist", + "twitter", + "zoom", + ] + """The connection's provider""" + + class AuthMeResponse(BaseModel): id: str """The user's id""" @@ -82,6 +140,9 @@ class AuthMeResponse(BaseModel): ] """All integrations available for the app""" + connections: List[Connection] + """Established connections for the user""" + installed_integrations: List[ Literal[ "collections", diff --git a/src/hyperspell/types/integration_connect_params.py b/src/hyperspell/types/integration_connect_params.py new file mode 100644 index 00000000..02eedc83 --- /dev/null +++ b/src/hyperspell/types/integration_connect_params.py @@ -0,0 +1,12 @@ +# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. + +from __future__ import annotations + +from typing import Optional +from typing_extensions import TypedDict + +__all__ = ["IntegrationConnectParams"] + + +class IntegrationConnectParams(TypedDict, total=False): + redirect_url: Optional[str] diff --git a/src/hyperspell/types/integration_connect_response.py b/src/hyperspell/types/integration_connect_response.py new file mode 100644 index 00000000..b403c918 --- /dev/null +++ b/src/hyperspell/types/integration_connect_response.py @@ -0,0 +1,13 @@ +# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. + +from datetime import datetime + +from .._models import BaseModel + +__all__ = ["IntegrationConnectResponse"] + + +class IntegrationConnectResponse(BaseModel): + expires_at: datetime + + url: str diff --git a/src/hyperspell/types/integration_list_response.py b/src/hyperspell/types/integration_list_response.py new file mode 100644 index 00000000..36c8fed7 --- /dev/null +++ b/src/hyperspell/types/integration_list_response.py @@ -0,0 +1,70 @@ +# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. + +from typing import List +from typing_extensions import Literal + +from .._models import BaseModel + +__all__ = ["IntegrationListResponse", "Integration"] + + +class Integration(BaseModel): + id: str + """The integration's id""" + + allow_multiple_connections: bool + """Whether the integration allows multiple connections""" + + provider: Literal[ + "collections", + "vault", + "web_crawler", + "notion", + "slack", + "google_calendar", + "reddit", + "box", + "google_drive", + "airtable", + "algolia", + "amplitude", + "asana", + "ashby", + "bamboohr", + "basecamp", + "bubbles", + "calendly", + "confluence", + "clickup", + "datadog", + "deel", + "discord", + "dropbox", + "exa", + "facebook", + "front", + "github", + "gitlab", + "google_docs", + "google_mail", + "google_sheet", + "hubspot", + "jira", + "linear", + "microsoft_teams", + "mixpanel", + "monday", + "outlook", + "perplexity", + "rippling", + "salesforce", + "segment", + "todoist", + "twitter", + "zoom", + ] + """The integration's provider""" + + +class IntegrationListResponse(BaseModel): + integrations: List[Integration] diff --git a/tests/api_resources/test_integrations.py b/tests/api_resources/test_integrations.py index 25babdd3..3b2934d7 100644 --- a/tests/api_resources/test_integrations.py +++ b/tests/api_resources/test_integrations.py @@ -9,7 +9,11 @@ from hyperspell import Hyperspell, AsyncHyperspell from tests.utils import assert_matches_type -from hyperspell.types import IntegrationRevokeResponse +from hyperspell.types import ( + IntegrationListResponse, + IntegrationRevokeResponse, + IntegrationConnectResponse, +) base_url = os.environ.get("TEST_API_BASE_URL", "http://127.0.0.1:4010") @@ -17,17 +21,88 @@ class TestIntegrations: parametrize = pytest.mark.parametrize("client", [False, True], indirect=True, ids=["loose", "strict"]) + @parametrize + def test_method_list(self, client: Hyperspell) -> None: + integration = client.integrations.list() + assert_matches_type(IntegrationListResponse, integration, path=["response"]) + + @parametrize + def test_raw_response_list(self, client: Hyperspell) -> None: + response = client.integrations.with_raw_response.list() + + assert response.is_closed is True + assert response.http_request.headers.get("X-Stainless-Lang") == "python" + integration = response.parse() + assert_matches_type(IntegrationListResponse, integration, path=["response"]) + + @parametrize + def test_streaming_response_list(self, client: Hyperspell) -> None: + with client.integrations.with_streaming_response.list() as response: + assert not response.is_closed + assert response.http_request.headers.get("X-Stainless-Lang") == "python" + + integration = response.parse() + assert_matches_type(IntegrationListResponse, integration, path=["response"]) + + assert cast(Any, response.is_closed) is True + + @parametrize + def test_method_connect(self, client: Hyperspell) -> None: + integration = client.integrations.connect( + integration_id="integration_id", + ) + assert_matches_type(IntegrationConnectResponse, integration, path=["response"]) + + @parametrize + def test_method_connect_with_all_params(self, client: Hyperspell) -> None: + integration = client.integrations.connect( + integration_id="integration_id", + redirect_url="redirect_url", + ) + assert_matches_type(IntegrationConnectResponse, integration, path=["response"]) + + @parametrize + def test_raw_response_connect(self, client: Hyperspell) -> None: + response = client.integrations.with_raw_response.connect( + integration_id="integration_id", + ) + + assert response.is_closed is True + assert response.http_request.headers.get("X-Stainless-Lang") == "python" + integration = response.parse() + assert_matches_type(IntegrationConnectResponse, integration, path=["response"]) + + @parametrize + def test_streaming_response_connect(self, client: Hyperspell) -> None: + with client.integrations.with_streaming_response.connect( + integration_id="integration_id", + ) as response: + assert not response.is_closed + assert response.http_request.headers.get("X-Stainless-Lang") == "python" + + integration = response.parse() + assert_matches_type(IntegrationConnectResponse, integration, path=["response"]) + + assert cast(Any, response.is_closed) is True + + @parametrize + def test_path_params_connect(self, client: Hyperspell) -> None: + with pytest.raises(ValueError, match=r"Expected a non-empty value for `integration_id` but received ''"): + client.integrations.with_raw_response.connect( + integration_id="", + ) + @parametrize def test_method_revoke(self, client: Hyperspell) -> None: integration = client.integrations.revoke( - "provider", + "integration_id", ) assert_matches_type(IntegrationRevokeResponse, integration, path=["response"]) @parametrize def test_raw_response_revoke(self, client: Hyperspell) -> None: response = client.integrations.with_raw_response.revoke( - "provider", + "integration_id", ) assert response.is_closed is True @@ -38,7 +113,7 @@ def test_raw_response_revoke(self, client: Hyperspell) -> None: @parametrize def test_streaming_response_revoke(self, client: Hyperspell) -> None: with client.integrations.with_streaming_response.revoke( - "provider", + "integration_id", ) as response: assert not response.is_closed assert response.http_request.headers.get("X-Stainless-Lang") == "python" @@ -50,7 +125,7 @@ def test_streaming_response_revoke(self, client: Hyperspell) -> None: @parametrize def test_path_params_revoke(self, client: Hyperspell) -> None: - with pytest.raises(ValueError, match=r"Expected a non-empty value for `provider` but received ''"): + with pytest.raises(ValueError, match=r"Expected a non-empty value for `integration_id` but received ''"): client.integrations.with_raw_response.revoke( "", ) @@ -61,17 +136,88 @@ class TestAsyncIntegrations: "async_client", [False, True, {"http_client": "aiohttp"}], indirect=True, ids=["loose", "strict", "aiohttp"] ) + @parametrize + async def test_method_list(self, async_client: AsyncHyperspell) -> None: + integration = await async_client.integrations.list() + assert_matches_type(IntegrationListResponse, integration, path=["response"]) + + @parametrize + async def test_raw_response_list(self, async_client: AsyncHyperspell) -> None: + response = await async_client.integrations.with_raw_response.list() + + assert response.is_closed is True + assert response.http_request.headers.get("X-Stainless-Lang") == "python" + integration = await response.parse() + assert_matches_type(IntegrationListResponse, integration, path=["response"]) + + @parametrize + async def test_streaming_response_list(self, async_client: AsyncHyperspell) -> None: + async with async_client.integrations.with_streaming_response.list() as response: + assert not response.is_closed + assert response.http_request.headers.get("X-Stainless-Lang") == "python" + + integration = await response.parse() + assert_matches_type(IntegrationListResponse, integration, path=["response"]) + + assert cast(Any, response.is_closed) is True + + @parametrize + async def test_method_connect(self, async_client: AsyncHyperspell) -> None: + integration = await async_client.integrations.connect( + integration_id="integration_id", + ) + assert_matches_type(IntegrationConnectResponse, integration, path=["response"]) + + @parametrize + async def test_method_connect_with_all_params(self, async_client: AsyncHyperspell) -> None: + integration = await async_client.integrations.connect( + integration_id="integration_id", + redirect_url="redirect_url", + ) + assert_matches_type(IntegrationConnectResponse, integration, path=["response"]) + + @parametrize + async def test_raw_response_connect(self, async_client: AsyncHyperspell) -> None: + response = await async_client.integrations.with_raw_response.connect( + integration_id="integration_id", + ) + + assert response.is_closed is True + assert response.http_request.headers.get("X-Stainless-Lang") == "python" + integration = await response.parse() + assert_matches_type(IntegrationConnectResponse, integration, path=["response"]) + + @parametrize + async def test_streaming_response_connect(self, async_client: AsyncHyperspell) -> None: + async with async_client.integrations.with_streaming_response.connect( + integration_id="integration_id", + ) as response: + assert not response.is_closed + assert response.http_request.headers.get("X-Stainless-Lang") == "python" + + integration = await response.parse() + assert_matches_type(IntegrationConnectResponse, integration, path=["response"]) + + assert cast(Any, response.is_closed) is True + + @parametrize + async def test_path_params_connect(self, async_client: AsyncHyperspell) -> None: + with pytest.raises(ValueError, match=r"Expected a non-empty value for `integration_id` but received ''"): + await async_client.integrations.with_raw_response.connect( + integration_id="", + ) + @parametrize async def test_method_revoke(self, async_client: AsyncHyperspell) -> None: integration = await async_client.integrations.revoke( - "provider", + "integration_id", ) assert_matches_type(IntegrationRevokeResponse, integration, path=["response"]) @parametrize async def test_raw_response_revoke(self, async_client: AsyncHyperspell) -> None: response = await async_client.integrations.with_raw_response.revoke( - "provider", + "integration_id", ) assert response.is_closed is True @@ -82,7 +228,7 @@ async def test_raw_response_revoke(self, async_client: AsyncHyperspell) -> None: @parametrize async def test_streaming_response_revoke(self, async_client: AsyncHyperspell) -> None: async with async_client.integrations.with_streaming_response.revoke( - "provider", + "integration_id", ) as response: assert not response.is_closed assert response.http_request.headers.get("X-Stainless-Lang") == "python" @@ -94,7 +240,7 @@ async def test_streaming_response_revoke(self, async_client: AsyncHyperspell) -> @parametrize async def test_path_params_revoke(self, async_client: AsyncHyperspell) -> None: - with pytest.raises(ValueError, match=r"Expected a non-empty value for `provider` but received ''"): + with pytest.raises(ValueError, match=r"Expected a non-empty value for `integration_id` but received ''"): await async_client.integrations.with_raw_response.revoke( "", )