diff --git a/.release-please-manifest.json b/.release-please-manifest.json index cd6d5c95..d589672a 100644 --- a/.release-please-manifest.json +++ b/.release-please-manifest.json @@ -1,3 +1,3 @@ { - ".": "0.1.0-beta.28" + ".": "0.1.0-beta.29" } \ No newline at end of file diff --git a/.stats.yml b/.stats.yml index a87492aa..f1d55cd4 100644 --- a/.stats.yml +++ b/.stats.yml @@ -1,4 +1,4 @@ -configured_endpoints: 110 -openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/stigg/stigg-7dccccd9c809d3fcc5f0ba477228a67b5f1fc5352b282081131f9fa0d90577d4.yml -openapi_spec_hash: 43d3823a6e045c2fd0b832877f2d8739 -config_hash: 0eca08dde117ac62155a012abb0ecac7 +configured_endpoints: 111 +openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/stigg/stigg-adaad2912e291814c93ac60d21f83f15a49cfd8d8ee8dc07b5f4b4a961d74904.yml +openapi_spec_hash: 1bbed365dc0b25763e34f2869ab08593 +config_hash: 2e65c1178cfd5d688faf5c9b1a48a732 diff --git a/CHANGELOG.md b/CHANGELOG.md index 92cc61d5..2bad7aea 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,13 @@ # Changelog +## 0.1.0-beta.29 (2026-06-23) + +Full Changelog: [v0.1.0-beta.28...v0.1.0-beta.29](https://github.com/stiggio/stigg-python/compare/v0.1.0-beta.28...v0.1.0-beta.29) + +### Features + +* **api:** add update method to data export destinations ([d7166a7](https://github.com/stiggio/stigg-python/commit/d7166a7efc21c7bb19b10a55dcb6695b0d81c481)) + ## 0.1.0-beta.28 (2026-06-23) Full Changelog: [v0.1.0-beta.27...v0.1.0-beta.28](https://github.com/stiggio/stigg-python/compare/v0.1.0-beta.27...v0.1.0-beta.28) diff --git a/api.md b/api.md index bae81d85..c4fe5043 100644 --- a/api.md +++ b/api.md @@ -186,12 +186,17 @@ Methods: Types: ```python -from stigg.types.v1.events.data_export import DestinationCreateResponse, DestinationDeleteResponse +from stigg.types.v1.events.data_export import ( + DestinationCreateResponse, + DestinationUpdateResponse, + DestinationDeleteResponse, +) ``` Methods: - client.v1.events.data_export.destinations.create(\*\*params) -> DestinationCreateResponse +- client.v1.events.data_export.destinations.update(destination_id, \*\*params) -> DestinationUpdateResponse - client.v1.events.data_export.destinations.delete(destination_id) -> DestinationDeleteResponse ### Beta diff --git a/pyproject.toml b/pyproject.toml index e6030b3c..27db2f4c 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -1,6 +1,6 @@ [project] name = "stigg" -version = "0.1.0-beta.28" +version = "0.1.0-beta.29" description = "The official Python library for the stigg API" dynamic = ["readme"] license = "Apache-2.0" diff --git a/src/stigg/_version.py b/src/stigg/_version.py index d1b9c504..ede35a86 100644 --- a/src/stigg/_version.py +++ b/src/stigg/_version.py @@ -1,4 +1,4 @@ # File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. __title__ = "stigg" -__version__ = "0.1.0-beta.28" # x-release-please-version +__version__ = "0.1.0-beta.29" # x-release-please-version diff --git a/src/stigg/resources/v1/events/data_export/destinations.py b/src/stigg/resources/v1/events/data_export/destinations.py index 82ba1733..8bac145e 100644 --- a/src/stigg/resources/v1/events/data_export/destinations.py +++ b/src/stigg/resources/v1/events/data_export/destinations.py @@ -15,9 +15,10 @@ async_to_streamed_response_wrapper, ) from ....._base_client import make_request_options -from .....types.v1.events.data_export import destination_create_params +from .....types.v1.events.data_export import destination_create_params, destination_update_params from .....types.v1.events.data_export.destination_create_response import DestinationCreateResponse from .....types.v1.events.data_export.destination_delete_response import DestinationDeleteResponse +from .....types.v1.events.data_export.destination_update_response import DestinationUpdateResponse __all__ = ["DestinationsResource", "AsyncDestinationsResource"] @@ -100,6 +101,64 @@ def create( cast_to=DestinationCreateResponse, ) + def update( + self, + destination_id: str, + *, + enabled_models: SequenceNotStr[str], + integration_id: str, + x_account_id: str | Omit = omit, + x_environment_id: 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, + ) -> DestinationUpdateResponse: + """Update a destination's entity selection. + + Pushes the new enabled_models to the + provider first, then persists the selection. Applies on the next scheduled + transfer. + + Args: + integration_id: Target integration row hosting the destination + + 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 destination_id: + raise ValueError(f"Expected a non-empty value for `destination_id` but received {destination_id!r}") + extra_headers = { + **strip_not_given( + { + "X-ACCOUNT-ID": x_account_id, + "X-ENVIRONMENT-ID": x_environment_id, + } + ), + **(extra_headers or {}), + } + return self._patch( + path_template("/api/v1/data-export/destinations/{destination_id}", destination_id=destination_id), + body=maybe_transform( + { + "enabled_models": enabled_models, + "integration_id": integration_id, + }, + destination_update_params.DestinationUpdateParams, + ), + options=make_request_options( + extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout + ), + cast_to=DestinationUpdateResponse, + ) + def delete( self, destination_id: str, @@ -224,6 +283,64 @@ async def create( cast_to=DestinationCreateResponse, ) + async def update( + self, + destination_id: str, + *, + enabled_models: SequenceNotStr[str], + integration_id: str, + x_account_id: str | Omit = omit, + x_environment_id: 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, + ) -> DestinationUpdateResponse: + """Update a destination's entity selection. + + Pushes the new enabled_models to the + provider first, then persists the selection. Applies on the next scheduled + transfer. + + Args: + integration_id: Target integration row hosting the destination + + 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 destination_id: + raise ValueError(f"Expected a non-empty value for `destination_id` but received {destination_id!r}") + extra_headers = { + **strip_not_given( + { + "X-ACCOUNT-ID": x_account_id, + "X-ENVIRONMENT-ID": x_environment_id, + } + ), + **(extra_headers or {}), + } + return await self._patch( + path_template("/api/v1/data-export/destinations/{destination_id}", destination_id=destination_id), + body=await async_maybe_transform( + { + "enabled_models": enabled_models, + "integration_id": integration_id, + }, + destination_update_params.DestinationUpdateParams, + ), + options=make_request_options( + extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout + ), + cast_to=DestinationUpdateResponse, + ) + async def delete( self, destination_id: str, @@ -277,6 +394,9 @@ def __init__(self, destinations: DestinationsResource) -> None: self.create = to_raw_response_wrapper( destinations.create, ) + self.update = to_raw_response_wrapper( + destinations.update, + ) self.delete = to_raw_response_wrapper( destinations.delete, ) @@ -289,6 +409,9 @@ def __init__(self, destinations: AsyncDestinationsResource) -> None: self.create = async_to_raw_response_wrapper( destinations.create, ) + self.update = async_to_raw_response_wrapper( + destinations.update, + ) self.delete = async_to_raw_response_wrapper( destinations.delete, ) @@ -301,6 +424,9 @@ def __init__(self, destinations: DestinationsResource) -> None: self.create = to_streamed_response_wrapper( destinations.create, ) + self.update = to_streamed_response_wrapper( + destinations.update, + ) self.delete = to_streamed_response_wrapper( destinations.delete, ) @@ -313,6 +439,9 @@ def __init__(self, destinations: AsyncDestinationsResource) -> None: self.create = async_to_streamed_response_wrapper( destinations.create, ) + self.update = async_to_streamed_response_wrapper( + destinations.update, + ) self.delete = async_to_streamed_response_wrapper( destinations.delete, ) diff --git a/src/stigg/types/v1/events/data_export/__init__.py b/src/stigg/types/v1/events/data_export/__init__.py index 4c9b171e..0fceedc8 100644 --- a/src/stigg/types/v1/events/data_export/__init__.py +++ b/src/stigg/types/v1/events/data_export/__init__.py @@ -3,5 +3,7 @@ from __future__ import annotations from .destination_create_params import DestinationCreateParams as DestinationCreateParams +from .destination_update_params import DestinationUpdateParams as DestinationUpdateParams from .destination_create_response import DestinationCreateResponse as DestinationCreateResponse from .destination_delete_response import DestinationDeleteResponse as DestinationDeleteResponse +from .destination_update_response import DestinationUpdateResponse as DestinationUpdateResponse diff --git a/src/stigg/types/v1/events/data_export/destination_update_params.py b/src/stigg/types/v1/events/data_export/destination_update_params.py new file mode 100644 index 00000000..927159f9 --- /dev/null +++ b/src/stigg/types/v1/events/data_export/destination_update_params.py @@ -0,0 +1,21 @@ +# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. + +from __future__ import annotations + +from typing_extensions import Required, Annotated, TypedDict + +from ....._types import SequenceNotStr +from ....._utils import PropertyInfo + +__all__ = ["DestinationUpdateParams"] + + +class DestinationUpdateParams(TypedDict, total=False): + enabled_models: Required[Annotated[SequenceNotStr[str], PropertyInfo(alias="enabledModels")]] + + integration_id: Required[Annotated[str, PropertyInfo(alias="integrationId")]] + """Target integration row hosting the destination""" + + x_account_id: Annotated[str, PropertyInfo(alias="X-ACCOUNT-ID")] + + x_environment_id: Annotated[str, PropertyInfo(alias="X-ENVIRONMENT-ID")] diff --git a/src/stigg/types/v1/events/data_export/destination_update_response.py b/src/stigg/types/v1/events/data_export/destination_update_response.py new file mode 100644 index 00000000..f43ce08d --- /dev/null +++ b/src/stigg/types/v1/events/data_export/destination_update_response.py @@ -0,0 +1,66 @@ +# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. + +from typing import List, Optional + +from pydantic import Field as FieldInfo + +from ....._models import BaseModel + +__all__ = ["DestinationUpdateResponse", "Data", "DataDestination", "DataDestinationLastSyncStatus"] + + +class DataDestinationLastSyncStatus(BaseModel): + """Latest sync snapshot for the destination, refreshed by the provider webhook""" + + finished_at: str = FieldInfo(alias="finishedAt") + """ISO8601 timestamp of when the latest sync finished""" + + status: str + """Sync status (PENDING, RUNNING, INCOMPLETE, FAILED, SUCCEEDED, CANCELLED)""" + + transfer_id: str = FieldInfo(alias="transferId") + """Provider transfer ID of the latest sync""" + + blamed_party: Optional[str] = FieldInfo(alias="blamedParty", default=None) + """Party responsible for a failed sync, as reported by the data-export provider""" + + failure_message: Optional[str] = FieldInfo(alias="failureMessage", default=None) + """Customer-friendly failure message, when the latest sync failed""" + + rows_transferred: Optional[float] = FieldInfo(alias="rowsTransferred", default=None) + """Number of rows transferred in the latest sync""" + + +class DataDestination(BaseModel): + """A single destination entry under the DATA_EXPORT integration.""" + + connected_at: str = FieldInfo(alias="connectedAt") + """ISO8601 timestamp of when the destination was connected""" + + destination_id: str = FieldInfo(alias="destinationId") + """Provider destination ID""" + + type: str + """Destination type (snowflake, bigquery, ...)""" + + connection_status: Optional[str] = FieldInfo(alias="connectionStatus", default=None) + """Connection status of the destination (connected, failed)""" + + enabled_models: Optional[List[str]] = FieldInfo(alias="enabledModels", default=None) + + last_sync_status: Optional[DataDestinationLastSyncStatus] = FieldInfo(alias="lastSyncStatus", default=None) + """Latest sync snapshot for the destination, refreshed by the provider webhook""" + + +class Data(BaseModel): + """Current destinations under the DATA_EXPORT integration.""" + + destinations: List[DataDestination] + """Current destinations under the DATA_EXPORT integration""" + + +class DestinationUpdateResponse(BaseModel): + """Response object""" + + data: Data + """Current destinations under the DATA_EXPORT integration.""" diff --git a/tests/api_resources/v1/events/data_export/test_destinations.py b/tests/api_resources/v1/events/data_export/test_destinations.py index 408b16d7..cfb1474c 100644 --- a/tests/api_resources/v1/events/data_export/test_destinations.py +++ b/tests/api_resources/v1/events/data_export/test_destinations.py @@ -12,6 +12,7 @@ from stigg.types.v1.events.data_export import ( DestinationCreateResponse, DestinationDeleteResponse, + DestinationUpdateResponse, ) base_url = os.environ.get("TEST_API_BASE_URL", "http://127.0.0.1:4010") @@ -69,6 +70,68 @@ def test_streaming_response_create(self, client: Stigg) -> None: assert cast(Any, response.is_closed) is True + @pytest.mark.skip(reason="Mock server tests are disabled") + @parametrize + def test_method_update(self, client: Stigg) -> None: + destination = client.v1.events.data_export.destinations.update( + destination_id="x", + enabled_models=["x"], + integration_id="x", + ) + assert_matches_type(DestinationUpdateResponse, destination, path=["response"]) + + @pytest.mark.skip(reason="Mock server tests are disabled") + @parametrize + def test_method_update_with_all_params(self, client: Stigg) -> None: + destination = client.v1.events.data_export.destinations.update( + destination_id="x", + enabled_models=["x"], + integration_id="x", + x_account_id="X-ACCOUNT-ID", + x_environment_id="X-ENVIRONMENT-ID", + ) + assert_matches_type(DestinationUpdateResponse, destination, path=["response"]) + + @pytest.mark.skip(reason="Mock server tests are disabled") + @parametrize + def test_raw_response_update(self, client: Stigg) -> None: + response = client.v1.events.data_export.destinations.with_raw_response.update( + destination_id="x", + enabled_models=["x"], + integration_id="x", + ) + + assert response.is_closed is True + assert response.http_request.headers.get("X-Stainless-Lang") == "python" + destination = response.parse() + assert_matches_type(DestinationUpdateResponse, destination, path=["response"]) + + @pytest.mark.skip(reason="Mock server tests are disabled") + @parametrize + def test_streaming_response_update(self, client: Stigg) -> None: + with client.v1.events.data_export.destinations.with_streaming_response.update( + destination_id="x", + enabled_models=["x"], + integration_id="x", + ) as response: + assert not response.is_closed + assert response.http_request.headers.get("X-Stainless-Lang") == "python" + + destination = response.parse() + assert_matches_type(DestinationUpdateResponse, destination, path=["response"]) + + assert cast(Any, response.is_closed) is True + + @pytest.mark.skip(reason="Mock server tests are disabled") + @parametrize + def test_path_params_update(self, client: Stigg) -> None: + with pytest.raises(ValueError, match=r"Expected a non-empty value for `destination_id` but received ''"): + client.v1.events.data_export.destinations.with_raw_response.update( + destination_id="", + enabled_models=["x"], + integration_id="x", + ) + @pytest.mark.skip(reason="Mock server tests are disabled") @parametrize def test_method_delete(self, client: Stigg) -> None: @@ -176,6 +239,68 @@ async def test_streaming_response_create(self, async_client: AsyncStigg) -> None assert cast(Any, response.is_closed) is True + @pytest.mark.skip(reason="Mock server tests are disabled") + @parametrize + async def test_method_update(self, async_client: AsyncStigg) -> None: + destination = await async_client.v1.events.data_export.destinations.update( + destination_id="x", + enabled_models=["x"], + integration_id="x", + ) + assert_matches_type(DestinationUpdateResponse, destination, path=["response"]) + + @pytest.mark.skip(reason="Mock server tests are disabled") + @parametrize + async def test_method_update_with_all_params(self, async_client: AsyncStigg) -> None: + destination = await async_client.v1.events.data_export.destinations.update( + destination_id="x", + enabled_models=["x"], + integration_id="x", + x_account_id="X-ACCOUNT-ID", + x_environment_id="X-ENVIRONMENT-ID", + ) + assert_matches_type(DestinationUpdateResponse, destination, path=["response"]) + + @pytest.mark.skip(reason="Mock server tests are disabled") + @parametrize + async def test_raw_response_update(self, async_client: AsyncStigg) -> None: + response = await async_client.v1.events.data_export.destinations.with_raw_response.update( + destination_id="x", + enabled_models=["x"], + integration_id="x", + ) + + assert response.is_closed is True + assert response.http_request.headers.get("X-Stainless-Lang") == "python" + destination = await response.parse() + assert_matches_type(DestinationUpdateResponse, destination, path=["response"]) + + @pytest.mark.skip(reason="Mock server tests are disabled") + @parametrize + async def test_streaming_response_update(self, async_client: AsyncStigg) -> None: + async with async_client.v1.events.data_export.destinations.with_streaming_response.update( + destination_id="x", + enabled_models=["x"], + integration_id="x", + ) as response: + assert not response.is_closed + assert response.http_request.headers.get("X-Stainless-Lang") == "python" + + destination = await response.parse() + assert_matches_type(DestinationUpdateResponse, destination, path=["response"]) + + assert cast(Any, response.is_closed) is True + + @pytest.mark.skip(reason="Mock server tests are disabled") + @parametrize + async def test_path_params_update(self, async_client: AsyncStigg) -> None: + with pytest.raises(ValueError, match=r"Expected a non-empty value for `destination_id` but received ''"): + await async_client.v1.events.data_export.destinations.with_raw_response.update( + destination_id="", + enabled_models=["x"], + integration_id="x", + ) + @pytest.mark.skip(reason="Mock server tests are disabled") @parametrize async def test_method_delete(self, async_client: AsyncStigg) -> None: