diff --git a/.stats.yml b/.stats.yml index c60c6d5cbc3..41b5b15dd67 100644 --- a/.stats.yml +++ b/.stats.yml @@ -1,4 +1,4 @@ -configured_endpoints: 2317 -openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/cloudflare/cloudflare-6c72aaee26a255cefb59365441066a292ee06cff650529eb8b95d9ffb73ec13a.yml -openapi_spec_hash: 393731844a065cd2de4b422825007b70 -config_hash: fb00b1d45d83236f53f8ef08adb2db5c +configured_endpoints: 2329 +openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/cloudflare/cloudflare-884b4b7d2d826afd303115f717021363d35e76d0819f4822e9faf6c577ea66ca.yml +openapi_spec_hash: 4fc7ac1b97d37c76f38db408ab2ed0cd +config_hash: 1fe0cc702fafe448e633d379a5633326 diff --git a/src/cloudflare/resources/abuse_reports/mitigations.py b/src/cloudflare/resources/abuse_reports/mitigations.py index 7286fe6009b..ba7dfc2d728 100644 --- a/src/cloudflare/resources/abuse_reports/mitigations.py +++ b/src/cloudflare/resources/abuse_reports/mitigations.py @@ -69,13 +69,25 @@ def list( | Omit = omit, status: Literal["pending", "active", "in_review", "cancelled", "removed"] | Omit = omit, type: Literal[ + "account_suspend", + "copyright_interstitial", + "geo_block", "legal_block", + "malware_interstitial", "misleading_interstitial", - "phishing_interstitial", "network_block", + "phishing_interstitial", + "playfairite_enforce", + "r2_takedown_account", + "r2_takedown_bucket", + "r2_takedown_object", "rate_limit_cache", - "account_suspend", "redirect_video_stream", + "registrar_freeze", + "registrar_parking", + "stream_block_account", + "user_suspend", + "workers_takedown_by_zone_id", ] | Omit = omit, # Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs. @@ -238,13 +250,25 @@ def list( | Omit = omit, status: Literal["pending", "active", "in_review", "cancelled", "removed"] | Omit = omit, type: Literal[ + "account_suspend", + "copyright_interstitial", + "geo_block", "legal_block", + "malware_interstitial", "misleading_interstitial", - "phishing_interstitial", "network_block", + "phishing_interstitial", + "playfairite_enforce", + "r2_takedown_account", + "r2_takedown_bucket", + "r2_takedown_object", "rate_limit_cache", - "account_suspend", "redirect_video_stream", + "registrar_freeze", + "registrar_parking", + "stream_block_account", + "user_suspend", + "workers_takedown_by_zone_id", ] | Omit = omit, # Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs. diff --git a/src/cloudflare/resources/ai_gateway/ai_gateway.py b/src/cloudflare/resources/ai_gateway/ai_gateway.py index fac8e0b1718..a2b415a26b5 100644 --- a/src/cloudflare/resources/ai_gateway/ai_gateway.py +++ b/src/cloudflare/resources/ai_gateway/ai_gateway.py @@ -255,6 +255,7 @@ def update( retry_backoff: Optional[Literal["constant", "linear", "exponential"]] | Omit = omit, retry_delay: Optional[int] | Omit = omit, retry_max_attempts: Optional[int] | Omit = omit, + spend_limits: Optional[ai_gateway_update_params.SpendLimits] | Omit = omit, store_id: Optional[str] | Omit = omit, stripe: Optional[ai_gateway_update_params.Stripe] | Omit = omit, workers_ai_billing_mode: Literal["postpaid"] | Omit = omit, @@ -314,6 +315,7 @@ def update( "retry_backoff": retry_backoff, "retry_delay": retry_delay, "retry_max_attempts": retry_max_attempts, + "spend_limits": spend_limits, "store_id": store_id, "stripe": stripe, "workers_ai_billing_mode": workers_ai_billing_mode, @@ -627,6 +629,7 @@ async def update( retry_backoff: Optional[Literal["constant", "linear", "exponential"]] | Omit = omit, retry_delay: Optional[int] | Omit = omit, retry_max_attempts: Optional[int] | Omit = omit, + spend_limits: Optional[ai_gateway_update_params.SpendLimits] | Omit = omit, store_id: Optional[str] | Omit = omit, stripe: Optional[ai_gateway_update_params.Stripe] | Omit = omit, workers_ai_billing_mode: Literal["postpaid"] | Omit = omit, @@ -686,6 +689,7 @@ async def update( "retry_backoff": retry_backoff, "retry_delay": retry_delay, "retry_max_attempts": retry_max_attempts, + "spend_limits": spend_limits, "store_id": store_id, "stripe": stripe, "workers_ai_billing_mode": workers_ai_billing_mode, diff --git a/src/cloudflare/resources/dns/__init__.py b/src/cloudflare/resources/dns/__init__.py index 58768dba906..7d175c52cab 100644 --- a/src/cloudflare/resources/dns/__init__.py +++ b/src/cloudflare/resources/dns/__init__.py @@ -8,6 +8,14 @@ DNSResourceWithStreamingResponse, AsyncDNSResourceWithStreamingResponse, ) +from .usage import ( + UsageResource, + AsyncUsageResource, + UsageResourceWithRawResponse, + AsyncUsageResourceWithRawResponse, + UsageResourceWithStreamingResponse, + AsyncUsageResourceWithStreamingResponse, +) from .dnssec import ( DNSSECResource, AsyncDNSSECResource, @@ -62,6 +70,12 @@ "AsyncRecordsResourceWithRawResponse", "RecordsResourceWithStreamingResponse", "AsyncRecordsResourceWithStreamingResponse", + "UsageResource", + "AsyncUsageResource", + "UsageResourceWithRawResponse", + "AsyncUsageResourceWithRawResponse", + "UsageResourceWithStreamingResponse", + "AsyncUsageResourceWithStreamingResponse", "SettingsResource", "AsyncSettingsResource", "SettingsResourceWithRawResponse", diff --git a/src/cloudflare/resources/dns/api.md b/src/cloudflare/resources/dns/api.md index 73fb955aeed..8695bc1b784 100644 --- a/src/cloudflare/resources/dns/api.md +++ b/src/cloudflare/resources/dns/api.md @@ -72,6 +72,32 @@ Methods: - client.dns.records.scan_review(\*, zone_id, \*\*params) -> Optional[RecordScanReviewResponse] - client.dns.records.scan_trigger(\*, zone_id) -> RecordScanTriggerResponse +## Usage + +### Zone + +Types: + +```python +from cloudflare.types.dns.usage import ZoneGetResponse +``` + +Methods: + +- client.dns.usage.zone.get(\*, zone_id) -> Optional[ZoneGetResponse] + +### Account + +Types: + +```python +from cloudflare.types.dns.usage import AccountGetResponse +``` + +Methods: + +- client.dns.usage.account.get(\*, account_id) -> Optional[AccountGetResponse] + ## Settings ### Zone diff --git a/src/cloudflare/resources/dns/dns.py b/src/cloudflare/resources/dns/dns.py index a4c4157a412..badc953563b 100644 --- a/src/cloudflare/resources/dns/dns.py +++ b/src/cloudflare/resources/dns/dns.py @@ -20,6 +20,14 @@ ) from ..._compat import cached_property from ..._resource import SyncAPIResource, AsyncAPIResource +from .usage.usage import ( + UsageResource, + AsyncUsageResource, + UsageResourceWithRawResponse, + AsyncUsageResourceWithRawResponse, + UsageResourceWithStreamingResponse, + AsyncUsageResourceWithStreamingResponse, +) from .settings.settings import ( SettingsResource, AsyncSettingsResource, @@ -57,6 +65,10 @@ def dnssec(self) -> DNSSECResource: def records(self) -> RecordsResource: return RecordsResource(self._client) + @cached_property + def usage(self) -> UsageResource: + return UsageResource(self._client) + @cached_property def settings(self) -> SettingsResource: return SettingsResource(self._client) @@ -98,6 +110,10 @@ def dnssec(self) -> AsyncDNSSECResource: def records(self) -> AsyncRecordsResource: return AsyncRecordsResource(self._client) + @cached_property + def usage(self) -> AsyncUsageResource: + return AsyncUsageResource(self._client) + @cached_property def settings(self) -> AsyncSettingsResource: return AsyncSettingsResource(self._client) @@ -142,6 +158,10 @@ def dnssec(self) -> DNSSECResourceWithRawResponse: def records(self) -> RecordsResourceWithRawResponse: return RecordsResourceWithRawResponse(self._dns.records) + @cached_property + def usage(self) -> UsageResourceWithRawResponse: + return UsageResourceWithRawResponse(self._dns.usage) + @cached_property def settings(self) -> SettingsResourceWithRawResponse: return SettingsResourceWithRawResponse(self._dns.settings) @@ -167,6 +187,10 @@ def dnssec(self) -> AsyncDNSSECResourceWithRawResponse: def records(self) -> AsyncRecordsResourceWithRawResponse: return AsyncRecordsResourceWithRawResponse(self._dns.records) + @cached_property + def usage(self) -> AsyncUsageResourceWithRawResponse: + return AsyncUsageResourceWithRawResponse(self._dns.usage) + @cached_property def settings(self) -> AsyncSettingsResourceWithRawResponse: return AsyncSettingsResourceWithRawResponse(self._dns.settings) @@ -192,6 +216,10 @@ def dnssec(self) -> DNSSECResourceWithStreamingResponse: def records(self) -> RecordsResourceWithStreamingResponse: return RecordsResourceWithStreamingResponse(self._dns.records) + @cached_property + def usage(self) -> UsageResourceWithStreamingResponse: + return UsageResourceWithStreamingResponse(self._dns.usage) + @cached_property def settings(self) -> SettingsResourceWithStreamingResponse: return SettingsResourceWithStreamingResponse(self._dns.settings) @@ -217,6 +245,10 @@ def dnssec(self) -> AsyncDNSSECResourceWithStreamingResponse: def records(self) -> AsyncRecordsResourceWithStreamingResponse: return AsyncRecordsResourceWithStreamingResponse(self._dns.records) + @cached_property + def usage(self) -> AsyncUsageResourceWithStreamingResponse: + return AsyncUsageResourceWithStreamingResponse(self._dns.usage) + @cached_property def settings(self) -> AsyncSettingsResourceWithStreamingResponse: return AsyncSettingsResourceWithStreamingResponse(self._dns.settings) diff --git a/src/cloudflare/resources/dns/usage/__init__.py b/src/cloudflare/resources/dns/usage/__init__.py new file mode 100644 index 00000000000..84f2ba47257 --- /dev/null +++ b/src/cloudflare/resources/dns/usage/__init__.py @@ -0,0 +1,47 @@ +# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. + +from .zone import ( + ZoneResource, + AsyncZoneResource, + ZoneResourceWithRawResponse, + AsyncZoneResourceWithRawResponse, + ZoneResourceWithStreamingResponse, + AsyncZoneResourceWithStreamingResponse, +) +from .usage import ( + UsageResource, + AsyncUsageResource, + UsageResourceWithRawResponse, + AsyncUsageResourceWithRawResponse, + UsageResourceWithStreamingResponse, + AsyncUsageResourceWithStreamingResponse, +) +from .account import ( + AccountResource, + AsyncAccountResource, + AccountResourceWithRawResponse, + AsyncAccountResourceWithRawResponse, + AccountResourceWithStreamingResponse, + AsyncAccountResourceWithStreamingResponse, +) + +__all__ = [ + "ZoneResource", + "AsyncZoneResource", + "ZoneResourceWithRawResponse", + "AsyncZoneResourceWithRawResponse", + "ZoneResourceWithStreamingResponse", + "AsyncZoneResourceWithStreamingResponse", + "AccountResource", + "AsyncAccountResource", + "AccountResourceWithRawResponse", + "AsyncAccountResourceWithRawResponse", + "AccountResourceWithStreamingResponse", + "AsyncAccountResourceWithStreamingResponse", + "UsageResource", + "AsyncUsageResource", + "UsageResourceWithRawResponse", + "AsyncUsageResourceWithRawResponse", + "UsageResourceWithStreamingResponse", + "AsyncUsageResourceWithStreamingResponse", +] diff --git a/src/cloudflare/resources/dns/usage/account.py b/src/cloudflare/resources/dns/usage/account.py new file mode 100644 index 00000000000..b53b9e4109d --- /dev/null +++ b/src/cloudflare/resources/dns/usage/account.py @@ -0,0 +1,183 @@ +# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. + +from __future__ import annotations + +from typing import Type, Optional, cast + +import httpx + +from ...._types import Body, Query, Headers, NotGiven, not_given +from ...._utils import path_template +from ...._compat import cached_property +from ...._resource import SyncAPIResource, AsyncAPIResource +from ...._response import ( + to_raw_response_wrapper, + to_streamed_response_wrapper, + async_to_raw_response_wrapper, + async_to_streamed_response_wrapper, +) +from ...._wrappers import ResultWrapper +from ...._base_client import make_request_options +from ....types.dns.usage.account_get_response import AccountGetResponse + +__all__ = ["AccountResource", "AsyncAccountResource"] + + +class AccountResource(SyncAPIResource): + @cached_property + def with_raw_response(self) -> AccountResourceWithRawResponse: + """ + This property can be used as a prefix for any HTTP method call to return + the raw response object instead of the parsed content. + + For more information, see https://www.github.com/cloudflare/cloudflare-python#accessing-raw-response-data-eg-headers + """ + return AccountResourceWithRawResponse(self) + + @cached_property + def with_streaming_response(self) -> AccountResourceWithStreamingResponse: + """ + An alternative to `.with_raw_response` that doesn't eagerly read the response body. + + For more information, see https://www.github.com/cloudflare/cloudflare-python#with_streaming_response + """ + return AccountResourceWithStreamingResponse(self) + + def get( + self, + *, + account_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. + extra_headers: Headers | None = None, + extra_query: Query | None = None, + extra_body: Body | None = None, + timeout: float | httpx.Timeout | None | NotGiven = not_given, + ) -> Optional[AccountGetResponse]: + """Get the current DNS record usage and quota for an account. + + May include internal + DNS usage and quota. + + Args: + account_id: Identifier. + + 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 account_id: + raise ValueError(f"Expected a non-empty value for `account_id` but received {account_id!r}") + return self._get( + path_template("/accounts/{account_id}/dns_records/usage", account_id=account_id), + options=make_request_options( + extra_headers=extra_headers, + extra_query=extra_query, + extra_body=extra_body, + timeout=timeout, + post_parser=ResultWrapper[Optional[AccountGetResponse]]._unwrapper, + ), + cast_to=cast(Type[Optional[AccountGetResponse]], ResultWrapper[AccountGetResponse]), + ) + + +class AsyncAccountResource(AsyncAPIResource): + @cached_property + def with_raw_response(self) -> AsyncAccountResourceWithRawResponse: + """ + This property can be used as a prefix for any HTTP method call to return + the raw response object instead of the parsed content. + + For more information, see https://www.github.com/cloudflare/cloudflare-python#accessing-raw-response-data-eg-headers + """ + return AsyncAccountResourceWithRawResponse(self) + + @cached_property + def with_streaming_response(self) -> AsyncAccountResourceWithStreamingResponse: + """ + An alternative to `.with_raw_response` that doesn't eagerly read the response body. + + For more information, see https://www.github.com/cloudflare/cloudflare-python#with_streaming_response + """ + return AsyncAccountResourceWithStreamingResponse(self) + + async def get( + self, + *, + account_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. + extra_headers: Headers | None = None, + extra_query: Query | None = None, + extra_body: Body | None = None, + timeout: float | httpx.Timeout | None | NotGiven = not_given, + ) -> Optional[AccountGetResponse]: + """Get the current DNS record usage and quota for an account. + + May include internal + DNS usage and quota. + + Args: + account_id: Identifier. + + 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 account_id: + raise ValueError(f"Expected a non-empty value for `account_id` but received {account_id!r}") + return await self._get( + path_template("/accounts/{account_id}/dns_records/usage", account_id=account_id), + options=make_request_options( + extra_headers=extra_headers, + extra_query=extra_query, + extra_body=extra_body, + timeout=timeout, + post_parser=ResultWrapper[Optional[AccountGetResponse]]._unwrapper, + ), + cast_to=cast(Type[Optional[AccountGetResponse]], ResultWrapper[AccountGetResponse]), + ) + + +class AccountResourceWithRawResponse: + def __init__(self, account: AccountResource) -> None: + self._account = account + + self.get = to_raw_response_wrapper( + account.get, + ) + + +class AsyncAccountResourceWithRawResponse: + def __init__(self, account: AsyncAccountResource) -> None: + self._account = account + + self.get = async_to_raw_response_wrapper( + account.get, + ) + + +class AccountResourceWithStreamingResponse: + def __init__(self, account: AccountResource) -> None: + self._account = account + + self.get = to_streamed_response_wrapper( + account.get, + ) + + +class AsyncAccountResourceWithStreamingResponse: + def __init__(self, account: AsyncAccountResource) -> None: + self._account = account + + self.get = async_to_streamed_response_wrapper( + account.get, + ) diff --git a/src/cloudflare/resources/dns/usage/usage.py b/src/cloudflare/resources/dns/usage/usage.py new file mode 100644 index 00000000000..43dd5daf595 --- /dev/null +++ b/src/cloudflare/resources/dns/usage/usage.py @@ -0,0 +1,134 @@ +# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. + +from __future__ import annotations + +from .zone import ( + ZoneResource, + AsyncZoneResource, + ZoneResourceWithRawResponse, + AsyncZoneResourceWithRawResponse, + ZoneResourceWithStreamingResponse, + AsyncZoneResourceWithStreamingResponse, +) +from .account import ( + AccountResource, + AsyncAccountResource, + AccountResourceWithRawResponse, + AsyncAccountResourceWithRawResponse, + AccountResourceWithStreamingResponse, + AsyncAccountResourceWithStreamingResponse, +) +from ...._compat import cached_property +from ...._resource import SyncAPIResource, AsyncAPIResource + +__all__ = ["UsageResource", "AsyncUsageResource"] + + +class UsageResource(SyncAPIResource): + @cached_property + def zone(self) -> ZoneResource: + return ZoneResource(self._client) + + @cached_property + def account(self) -> AccountResource: + return AccountResource(self._client) + + @cached_property + def with_raw_response(self) -> UsageResourceWithRawResponse: + """ + This property can be used as a prefix for any HTTP method call to return + the raw response object instead of the parsed content. + + For more information, see https://www.github.com/cloudflare/cloudflare-python#accessing-raw-response-data-eg-headers + """ + return UsageResourceWithRawResponse(self) + + @cached_property + def with_streaming_response(self) -> UsageResourceWithStreamingResponse: + """ + An alternative to `.with_raw_response` that doesn't eagerly read the response body. + + For more information, see https://www.github.com/cloudflare/cloudflare-python#with_streaming_response + """ + return UsageResourceWithStreamingResponse(self) + + +class AsyncUsageResource(AsyncAPIResource): + @cached_property + def zone(self) -> AsyncZoneResource: + return AsyncZoneResource(self._client) + + @cached_property + def account(self) -> AsyncAccountResource: + return AsyncAccountResource(self._client) + + @cached_property + def with_raw_response(self) -> AsyncUsageResourceWithRawResponse: + """ + This property can be used as a prefix for any HTTP method call to return + the raw response object instead of the parsed content. + + For more information, see https://www.github.com/cloudflare/cloudflare-python#accessing-raw-response-data-eg-headers + """ + return AsyncUsageResourceWithRawResponse(self) + + @cached_property + def with_streaming_response(self) -> AsyncUsageResourceWithStreamingResponse: + """ + An alternative to `.with_raw_response` that doesn't eagerly read the response body. + + For more information, see https://www.github.com/cloudflare/cloudflare-python#with_streaming_response + """ + return AsyncUsageResourceWithStreamingResponse(self) + + +class UsageResourceWithRawResponse: + def __init__(self, usage: UsageResource) -> None: + self._usage = usage + + @cached_property + def zone(self) -> ZoneResourceWithRawResponse: + return ZoneResourceWithRawResponse(self._usage.zone) + + @cached_property + def account(self) -> AccountResourceWithRawResponse: + return AccountResourceWithRawResponse(self._usage.account) + + +class AsyncUsageResourceWithRawResponse: + def __init__(self, usage: AsyncUsageResource) -> None: + self._usage = usage + + @cached_property + def zone(self) -> AsyncZoneResourceWithRawResponse: + return AsyncZoneResourceWithRawResponse(self._usage.zone) + + @cached_property + def account(self) -> AsyncAccountResourceWithRawResponse: + return AsyncAccountResourceWithRawResponse(self._usage.account) + + +class UsageResourceWithStreamingResponse: + def __init__(self, usage: UsageResource) -> None: + self._usage = usage + + @cached_property + def zone(self) -> ZoneResourceWithStreamingResponse: + return ZoneResourceWithStreamingResponse(self._usage.zone) + + @cached_property + def account(self) -> AccountResourceWithStreamingResponse: + return AccountResourceWithStreamingResponse(self._usage.account) + + +class AsyncUsageResourceWithStreamingResponse: + def __init__(self, usage: AsyncUsageResource) -> None: + self._usage = usage + + @cached_property + def zone(self) -> AsyncZoneResourceWithStreamingResponse: + return AsyncZoneResourceWithStreamingResponse(self._usage.zone) + + @cached_property + def account(self) -> AsyncAccountResourceWithStreamingResponse: + return AsyncAccountResourceWithStreamingResponse(self._usage.account) diff --git a/src/cloudflare/resources/dns/usage/zone.py b/src/cloudflare/resources/dns/usage/zone.py new file mode 100644 index 00000000000..1fd9151910f --- /dev/null +++ b/src/cloudflare/resources/dns/usage/zone.py @@ -0,0 +1,181 @@ +# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. + +from __future__ import annotations + +from typing import Type, Optional, cast + +import httpx + +from ...._types import Body, Query, Headers, NotGiven, not_given +from ...._utils import path_template +from ...._compat import cached_property +from ...._resource import SyncAPIResource, AsyncAPIResource +from ...._response import ( + to_raw_response_wrapper, + to_streamed_response_wrapper, + async_to_raw_response_wrapper, + async_to_streamed_response_wrapper, +) +from ...._wrappers import ResultWrapper +from ...._base_client import make_request_options +from ....types.dns.usage.zone_get_response import ZoneGetResponse + +__all__ = ["ZoneResource", "AsyncZoneResource"] + + +class ZoneResource(SyncAPIResource): + @cached_property + def with_raw_response(self) -> ZoneResourceWithRawResponse: + """ + This property can be used as a prefix for any HTTP method call to return + the raw response object instead of the parsed content. + + For more information, see https://www.github.com/cloudflare/cloudflare-python#accessing-raw-response-data-eg-headers + """ + return ZoneResourceWithRawResponse(self) + + @cached_property + def with_streaming_response(self) -> ZoneResourceWithStreamingResponse: + """ + An alternative to `.with_raw_response` that doesn't eagerly read the response body. + + For more information, see https://www.github.com/cloudflare/cloudflare-python#with_streaming_response + """ + return ZoneResourceWithStreamingResponse(self) + + def get( + self, + *, + zone_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. + extra_headers: Headers | None = None, + extra_query: Query | None = None, + extra_body: Body | None = None, + timeout: float | httpx.Timeout | None | NotGiven = not_given, + ) -> Optional[ZoneGetResponse]: + """ + Get the current DNS record usage for a zone, including the number of records and + the quota limit. + + Args: + zone_id: Identifier. + + 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 zone_id: + raise ValueError(f"Expected a non-empty value for `zone_id` but received {zone_id!r}") + return self._get( + path_template("/zones/{zone_id}/dns_records/usage", zone_id=zone_id), + options=make_request_options( + extra_headers=extra_headers, + extra_query=extra_query, + extra_body=extra_body, + timeout=timeout, + post_parser=ResultWrapper[Optional[ZoneGetResponse]]._unwrapper, + ), + cast_to=cast(Type[Optional[ZoneGetResponse]], ResultWrapper[ZoneGetResponse]), + ) + + +class AsyncZoneResource(AsyncAPIResource): + @cached_property + def with_raw_response(self) -> AsyncZoneResourceWithRawResponse: + """ + This property can be used as a prefix for any HTTP method call to return + the raw response object instead of the parsed content. + + For more information, see https://www.github.com/cloudflare/cloudflare-python#accessing-raw-response-data-eg-headers + """ + return AsyncZoneResourceWithRawResponse(self) + + @cached_property + def with_streaming_response(self) -> AsyncZoneResourceWithStreamingResponse: + """ + An alternative to `.with_raw_response` that doesn't eagerly read the response body. + + For more information, see https://www.github.com/cloudflare/cloudflare-python#with_streaming_response + """ + return AsyncZoneResourceWithStreamingResponse(self) + + async def get( + self, + *, + zone_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. + extra_headers: Headers | None = None, + extra_query: Query | None = None, + extra_body: Body | None = None, + timeout: float | httpx.Timeout | None | NotGiven = not_given, + ) -> Optional[ZoneGetResponse]: + """ + Get the current DNS record usage for a zone, including the number of records and + the quota limit. + + Args: + zone_id: Identifier. + + 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 zone_id: + raise ValueError(f"Expected a non-empty value for `zone_id` but received {zone_id!r}") + return await self._get( + path_template("/zones/{zone_id}/dns_records/usage", zone_id=zone_id), + options=make_request_options( + extra_headers=extra_headers, + extra_query=extra_query, + extra_body=extra_body, + timeout=timeout, + post_parser=ResultWrapper[Optional[ZoneGetResponse]]._unwrapper, + ), + cast_to=cast(Type[Optional[ZoneGetResponse]], ResultWrapper[ZoneGetResponse]), + ) + + +class ZoneResourceWithRawResponse: + def __init__(self, zone: ZoneResource) -> None: + self._zone = zone + + self.get = to_raw_response_wrapper( + zone.get, + ) + + +class AsyncZoneResourceWithRawResponse: + def __init__(self, zone: AsyncZoneResource) -> None: + self._zone = zone + + self.get = async_to_raw_response_wrapper( + zone.get, + ) + + +class ZoneResourceWithStreamingResponse: + def __init__(self, zone: ZoneResource) -> None: + self._zone = zone + + self.get = to_streamed_response_wrapper( + zone.get, + ) + + +class AsyncZoneResourceWithStreamingResponse: + def __init__(self, zone: AsyncZoneResource) -> None: + self._zone = zone + + self.get = async_to_streamed_response_wrapper( + zone.get, + ) diff --git a/src/cloudflare/resources/logpush/datasets/fields.py b/src/cloudflare/resources/logpush/datasets/fields.py index b833e0cd1fc..905b3f0fcb0 100644 --- a/src/cloudflare/resources/logpush/datasets/fields.py +++ b/src/cloudflare/resources/logpush/datasets/fields.py @@ -74,6 +74,7 @@ def get( "sinkhole_http_logs", "spectrum_events", "ssh_logs", + "turnstile_events", "warp_config_changes", "warp_toggle_changes", "workers_trace_events", @@ -194,6 +195,7 @@ async def get( "sinkhole_http_logs", "spectrum_events", "ssh_logs", + "turnstile_events", "warp_config_changes", "warp_toggle_changes", "workers_trace_events", diff --git a/src/cloudflare/resources/logpush/datasets/jobs.py b/src/cloudflare/resources/logpush/datasets/jobs.py index ece4498669f..d229ba4c636 100644 --- a/src/cloudflare/resources/logpush/datasets/jobs.py +++ b/src/cloudflare/resources/logpush/datasets/jobs.py @@ -75,6 +75,7 @@ def get( "sinkhole_http_logs", "spectrum_events", "ssh_logs", + "turnstile_events", "warp_config_changes", "warp_toggle_changes", "workers_trace_events", @@ -190,6 +191,7 @@ def get( "sinkhole_http_logs", "spectrum_events", "ssh_logs", + "turnstile_events", "warp_config_changes", "warp_toggle_changes", "workers_trace_events", diff --git a/src/cloudflare/resources/logpush/jobs.py b/src/cloudflare/resources/logpush/jobs.py index 67ed788882f..8c62a706d68 100644 --- a/src/cloudflare/resources/logpush/jobs.py +++ b/src/cloudflare/resources/logpush/jobs.py @@ -84,6 +84,7 @@ def create( "sinkhole_http_logs", "spectrum_events", "ssh_logs", + "turnstile_events", "warp_config_changes", "warp_toggle_changes", "workers_trace_events", @@ -590,6 +591,7 @@ async def create( "sinkhole_http_logs", "spectrum_events", "ssh_logs", + "turnstile_events", "warp_config_changes", "warp_toggle_changes", "workers_trace_events", diff --git a/src/cloudflare/resources/realtime_kit/sessions.py b/src/cloudflare/resources/realtime_kit/sessions.py index 5c575c80543..749342eb2ed 100644 --- a/src/cloudflare/resources/realtime_kit/sessions.py +++ b/src/cloudflare/resources/realtime_kit/sessions.py @@ -131,16 +131,14 @@ def get_participant_data_from_peer_id( timeout: float | httpx.Timeout | None | NotGiven = not_given, ) -> SessionGetParticipantDataFromPeerIDResponse: """ - Returns details of the given peer ID along with call statistics for the given - session ID. + Returns participant details for the given peer ID along with call statistics. Args: account_id: The account identifier tag. app_id: The app identifier tag. - filters: Comma separated list of filters to apply. Note that there must be no spaces - between the filters. + filters: Filter to apply to the peer report. include_peer_events: if true, response includes all the peer events of participant. @@ -718,16 +716,14 @@ async def get_participant_data_from_peer_id( timeout: float | httpx.Timeout | None | NotGiven = not_given, ) -> SessionGetParticipantDataFromPeerIDResponse: """ - Returns details of the given peer ID along with call statistics for the given - session ID. + Returns participant details for the given peer ID along with call statistics. Args: account_id: The account identifier tag. app_id: The app identifier tag. - filters: Comma separated list of filters to apply. Note that there must be no spaces - between the filters. + filters: Filter to apply to the peer report. include_peer_events: if true, response includes all the peer events of participant. diff --git a/src/cloudflare/resources/resource_sharing/api.md b/src/cloudflare/resources/resource_sharing/api.md index 7fec9dc27db..00b2d014706 100644 --- a/src/cloudflare/resources/resource_sharing/api.md +++ b/src/cloudflare/resources/resource_sharing/api.md @@ -45,10 +45,19 @@ Methods: Types: ```python -from cloudflare.types.resource_sharing import ResourceCreateResponse, ResourceListResponse +from cloudflare.types.resource_sharing import ( + ResourceCreateResponse, + ResourceUpdateResponse, + ResourceListResponse, + ResourceDeleteResponse, + ResourceGetResponse, +) ``` Methods: - client.resource_sharing.resources.create(share_id, \*, account_id, \*\*params) -> Optional[ResourceCreateResponse] +- client.resource_sharing.resources.update(share_resource_id, \*, account_id, share_id, \*\*params) -> Optional[ResourceUpdateResponse] - client.resource_sharing.resources.list(share_id, \*, account_id, \*\*params) -> SyncV4PagePaginationArray[ResourceListResponse] +- client.resource_sharing.resources.delete(share_resource_id, \*, account_id, share_id) -> Optional[ResourceDeleteResponse] +- client.resource_sharing.resources.get(share_resource_id, \*, account_id, share_id) -> Optional[ResourceGetResponse] diff --git a/src/cloudflare/resources/resource_sharing/resources.py b/src/cloudflare/resources/resource_sharing/resources.py index 84a136aabe7..1016063f44c 100644 --- a/src/cloudflare/resources/resource_sharing/resources.py +++ b/src/cloudflare/resources/resource_sharing/resources.py @@ -20,9 +20,12 @@ from ..._wrappers import ResultWrapper from ...pagination import SyncV4PagePaginationArray, AsyncV4PagePaginationArray from ..._base_client import AsyncPaginator, make_request_options -from ...types.resource_sharing import resource_list_params, resource_create_params +from ...types.resource_sharing import resource_list_params, resource_create_params, resource_update_params +from ...types.resource_sharing.resource_get_response import ResourceGetResponse from ...types.resource_sharing.resource_list_response import ResourceListResponse from ...types.resource_sharing.resource_create_response import ResourceCreateResponse +from ...types.resource_sharing.resource_delete_response import ResourceDeleteResponse +from ...types.resource_sharing.resource_update_response import ResourceUpdateResponse __all__ = ["ResourcesResource", "AsyncResourcesResource"] @@ -121,6 +124,65 @@ def create( cast_to=cast(Type[Optional[ResourceCreateResponse]], ResultWrapper[ResourceCreateResponse]), ) + def update( + self, + share_resource_id: str, + *, + account_id: str, + share_id: str, + meta: object, + # 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, + ) -> Optional[ResourceUpdateResponse]: + """ + Update is not immediate, an updated share resource object with a new status will + be returned. + + Args: + account_id: Account identifier. + + share_id: Share identifier tag. + + share_resource_id: Share Resource identifier. + + meta: Resource Metadata. + + 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 account_id: + raise ValueError(f"Expected a non-empty value for `account_id` but received {account_id!r}") + if not share_id: + raise ValueError(f"Expected a non-empty value for `share_id` but received {share_id!r}") + if not share_resource_id: + raise ValueError(f"Expected a non-empty value for `share_resource_id` but received {share_resource_id!r}") + return self._put( + path_template( + "/accounts/{account_id}/shares/{share_id}/resources/{share_resource_id}", + account_id=account_id, + share_id=share_id, + share_resource_id=share_resource_id, + ), + body=maybe_transform({"meta": meta}, resource_update_params.ResourceUpdateParams), + options=make_request_options( + extra_headers=extra_headers, + extra_query=extra_query, + extra_body=extra_body, + timeout=timeout, + post_parser=ResultWrapper[Optional[ResourceUpdateResponse]]._unwrapper, + ), + cast_to=cast(Type[Optional[ResourceUpdateResponse]], ResultWrapper[ResourceUpdateResponse]), + ) + def list( self, share_id: str, @@ -199,6 +261,115 @@ def list( model=ResourceListResponse, ) + def delete( + self, + share_resource_id: str, + *, + account_id: str, + share_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. + extra_headers: Headers | None = None, + extra_query: Query | None = None, + extra_body: Body | None = None, + timeout: float | httpx.Timeout | None | NotGiven = not_given, + ) -> Optional[ResourceDeleteResponse]: + """ + Deletion is not immediate, an updated share resource object with a new status + will be returned. + + Args: + account_id: Account identifier. + + share_id: Share identifier tag. + + share_resource_id: Share Resource identifier. + + 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 account_id: + raise ValueError(f"Expected a non-empty value for `account_id` but received {account_id!r}") + if not share_id: + raise ValueError(f"Expected a non-empty value for `share_id` but received {share_id!r}") + if not share_resource_id: + raise ValueError(f"Expected a non-empty value for `share_resource_id` but received {share_resource_id!r}") + return self._delete( + path_template( + "/accounts/{account_id}/shares/{share_id}/resources/{share_resource_id}", + account_id=account_id, + share_id=share_id, + share_resource_id=share_resource_id, + ), + options=make_request_options( + extra_headers=extra_headers, + extra_query=extra_query, + extra_body=extra_body, + timeout=timeout, + post_parser=ResultWrapper[Optional[ResourceDeleteResponse]]._unwrapper, + ), + cast_to=cast(Type[Optional[ResourceDeleteResponse]], ResultWrapper[ResourceDeleteResponse]), + ) + + def get( + self, + share_resource_id: str, + *, + account_id: str, + share_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. + extra_headers: Headers | None = None, + extra_query: Query | None = None, + extra_body: Body | None = None, + timeout: float | httpx.Timeout | None | NotGiven = not_given, + ) -> Optional[ResourceGetResponse]: + """ + Get share resource by ID. + + Args: + account_id: Account identifier. + + share_id: Share identifier tag. + + share_resource_id: Share Resource identifier. + + 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 account_id: + raise ValueError(f"Expected a non-empty value for `account_id` but received {account_id!r}") + if not share_id: + raise ValueError(f"Expected a non-empty value for `share_id` but received {share_id!r}") + if not share_resource_id: + raise ValueError(f"Expected a non-empty value for `share_resource_id` but received {share_resource_id!r}") + return self._get( + path_template( + "/accounts/{account_id}/shares/{share_id}/resources/{share_resource_id}", + account_id=account_id, + share_id=share_id, + share_resource_id=share_resource_id, + ), + options=make_request_options( + extra_headers=extra_headers, + extra_query=extra_query, + extra_body=extra_body, + timeout=timeout, + post_parser=ResultWrapper[Optional[ResourceGetResponse]]._unwrapper, + ), + cast_to=cast(Type[Optional[ResourceGetResponse]], ResultWrapper[ResourceGetResponse]), + ) + class AsyncResourcesResource(AsyncAPIResource): @cached_property @@ -294,6 +465,65 @@ async def create( cast_to=cast(Type[Optional[ResourceCreateResponse]], ResultWrapper[ResourceCreateResponse]), ) + async def update( + self, + share_resource_id: str, + *, + account_id: str, + share_id: str, + meta: object, + # 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, + ) -> Optional[ResourceUpdateResponse]: + """ + Update is not immediate, an updated share resource object with a new status will + be returned. + + Args: + account_id: Account identifier. + + share_id: Share identifier tag. + + share_resource_id: Share Resource identifier. + + meta: Resource Metadata. + + 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 account_id: + raise ValueError(f"Expected a non-empty value for `account_id` but received {account_id!r}") + if not share_id: + raise ValueError(f"Expected a non-empty value for `share_id` but received {share_id!r}") + if not share_resource_id: + raise ValueError(f"Expected a non-empty value for `share_resource_id` but received {share_resource_id!r}") + return await self._put( + path_template( + "/accounts/{account_id}/shares/{share_id}/resources/{share_resource_id}", + account_id=account_id, + share_id=share_id, + share_resource_id=share_resource_id, + ), + body=await async_maybe_transform({"meta": meta}, resource_update_params.ResourceUpdateParams), + options=make_request_options( + extra_headers=extra_headers, + extra_query=extra_query, + extra_body=extra_body, + timeout=timeout, + post_parser=ResultWrapper[Optional[ResourceUpdateResponse]]._unwrapper, + ), + cast_to=cast(Type[Optional[ResourceUpdateResponse]], ResultWrapper[ResourceUpdateResponse]), + ) + def list( self, share_id: str, @@ -372,6 +602,115 @@ def list( model=ResourceListResponse, ) + async def delete( + self, + share_resource_id: str, + *, + account_id: str, + share_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. + extra_headers: Headers | None = None, + extra_query: Query | None = None, + extra_body: Body | None = None, + timeout: float | httpx.Timeout | None | NotGiven = not_given, + ) -> Optional[ResourceDeleteResponse]: + """ + Deletion is not immediate, an updated share resource object with a new status + will be returned. + + Args: + account_id: Account identifier. + + share_id: Share identifier tag. + + share_resource_id: Share Resource identifier. + + 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 account_id: + raise ValueError(f"Expected a non-empty value for `account_id` but received {account_id!r}") + if not share_id: + raise ValueError(f"Expected a non-empty value for `share_id` but received {share_id!r}") + if not share_resource_id: + raise ValueError(f"Expected a non-empty value for `share_resource_id` but received {share_resource_id!r}") + return await self._delete( + path_template( + "/accounts/{account_id}/shares/{share_id}/resources/{share_resource_id}", + account_id=account_id, + share_id=share_id, + share_resource_id=share_resource_id, + ), + options=make_request_options( + extra_headers=extra_headers, + extra_query=extra_query, + extra_body=extra_body, + timeout=timeout, + post_parser=ResultWrapper[Optional[ResourceDeleteResponse]]._unwrapper, + ), + cast_to=cast(Type[Optional[ResourceDeleteResponse]], ResultWrapper[ResourceDeleteResponse]), + ) + + async def get( + self, + share_resource_id: str, + *, + account_id: str, + share_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. + extra_headers: Headers | None = None, + extra_query: Query | None = None, + extra_body: Body | None = None, + timeout: float | httpx.Timeout | None | NotGiven = not_given, + ) -> Optional[ResourceGetResponse]: + """ + Get share resource by ID. + + Args: + account_id: Account identifier. + + share_id: Share identifier tag. + + share_resource_id: Share Resource identifier. + + 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 account_id: + raise ValueError(f"Expected a non-empty value for `account_id` but received {account_id!r}") + if not share_id: + raise ValueError(f"Expected a non-empty value for `share_id` but received {share_id!r}") + if not share_resource_id: + raise ValueError(f"Expected a non-empty value for `share_resource_id` but received {share_resource_id!r}") + return await self._get( + path_template( + "/accounts/{account_id}/shares/{share_id}/resources/{share_resource_id}", + account_id=account_id, + share_id=share_id, + share_resource_id=share_resource_id, + ), + options=make_request_options( + extra_headers=extra_headers, + extra_query=extra_query, + extra_body=extra_body, + timeout=timeout, + post_parser=ResultWrapper[Optional[ResourceGetResponse]]._unwrapper, + ), + cast_to=cast(Type[Optional[ResourceGetResponse]], ResultWrapper[ResourceGetResponse]), + ) + class ResourcesResourceWithRawResponse: def __init__(self, resources: ResourcesResource) -> None: @@ -380,9 +719,18 @@ def __init__(self, resources: ResourcesResource) -> None: self.create = to_raw_response_wrapper( resources.create, ) + self.update = to_raw_response_wrapper( + resources.update, + ) self.list = to_raw_response_wrapper( resources.list, ) + self.delete = to_raw_response_wrapper( + resources.delete, + ) + self.get = to_raw_response_wrapper( + resources.get, + ) class AsyncResourcesResourceWithRawResponse: @@ -392,9 +740,18 @@ def __init__(self, resources: AsyncResourcesResource) -> None: self.create = async_to_raw_response_wrapper( resources.create, ) + self.update = async_to_raw_response_wrapper( + resources.update, + ) self.list = async_to_raw_response_wrapper( resources.list, ) + self.delete = async_to_raw_response_wrapper( + resources.delete, + ) + self.get = async_to_raw_response_wrapper( + resources.get, + ) class ResourcesResourceWithStreamingResponse: @@ -404,9 +761,18 @@ def __init__(self, resources: ResourcesResource) -> None: self.create = to_streamed_response_wrapper( resources.create, ) + self.update = to_streamed_response_wrapper( + resources.update, + ) self.list = to_streamed_response_wrapper( resources.list, ) + self.delete = to_streamed_response_wrapper( + resources.delete, + ) + self.get = to_streamed_response_wrapper( + resources.get, + ) class AsyncResourcesResourceWithStreamingResponse: @@ -416,6 +782,15 @@ def __init__(self, resources: AsyncResourcesResource) -> None: self.create = async_to_streamed_response_wrapper( resources.create, ) + self.update = async_to_streamed_response_wrapper( + resources.update, + ) self.list = async_to_streamed_response_wrapper( resources.list, ) + self.delete = async_to_streamed_response_wrapper( + resources.delete, + ) + self.get = async_to_streamed_response_wrapper( + resources.get, + ) diff --git a/src/cloudflare/resources/workflows/api.md b/src/cloudflare/resources/workflows/api.md index a90bde50ec2..9b6d98404ce 100644 --- a/src/cloudflare/resources/workflows/api.md +++ b/src/cloudflare/resources/workflows/api.md @@ -28,6 +28,7 @@ from cloudflare.types.workflows import ( InstanceListResponse, InstanceBulkResponse, InstanceGetResponse, + InstanceStepResponse, ) ``` @@ -37,6 +38,7 @@ Methods: - client.workflows.instances.list(workflow_name, \*, account_id, \*\*params) -> SyncV4PagePaginationArray[InstanceListResponse] - client.workflows.instances.bulk(workflow_name, \*, account_id, \*\*params) -> SyncSinglePage[InstanceBulkResponse] - client.workflows.instances.get(instance_id, \*, account_id, workflow_name, \*\*params) -> InstanceGetResponse +- client.workflows.instances.step(instance_id, \*, account_id, workflow_name, \*\*params) -> InstanceStepResponse ### Status @@ -61,10 +63,11 @@ Methods: Types: ```python -from cloudflare.types.workflows import VersionListResponse, VersionGetResponse +from cloudflare.types.workflows import VersionListResponse, VersionGetResponse, VersionGraphResponse ``` Methods: - client.workflows.versions.list(workflow_name, \*, account_id, \*\*params) -> SyncV4PagePaginationArray[VersionListResponse] - client.workflows.versions.get(version_id, \*, account_id, workflow_name) -> VersionGetResponse +- client.workflows.versions.graph(version_id, \*, account_id, workflow_name) -> VersionGraphResponse diff --git a/src/cloudflare/resources/workflows/instances/instances.py b/src/cloudflare/resources/workflows/instances/instances.py index c0a88c923a9..fe90af5e81b 100644 --- a/src/cloudflare/resources/workflows/instances/instances.py +++ b/src/cloudflare/resources/workflows/instances/instances.py @@ -37,10 +37,17 @@ from ...._wrappers import ResultWrapper from ....pagination import SyncSinglePage, AsyncSinglePage, SyncV4PagePaginationArray, AsyncV4PagePaginationArray from ...._base_client import AsyncPaginator, make_request_options -from ....types.workflows import instance_get_params, instance_bulk_params, instance_list_params, instance_create_params +from ....types.workflows import ( + instance_get_params, + instance_bulk_params, + instance_list_params, + instance_step_params, + instance_create_params, +) from ....types.workflows.instance_get_response import InstanceGetResponse from ....types.workflows.instance_bulk_response import InstanceBulkResponse from ....types.workflows.instance_list_response import InstanceListResponse +from ....types.workflows.instance_step_response import InstanceStepResponse from ....types.workflows.instance_create_response import InstanceCreateResponse __all__ = ["InstancesResource", "AsyncInstancesResource"] @@ -318,6 +325,80 @@ def get( cast_to=cast(Type[InstanceGetResponse], ResultWrapper[InstanceGetResponse]), ) + def step( + self, + instance_id: str, + *, + account_id: str, + workflow_name: str, + name: str, + type: Literal["step", "waitForEvent"], + attempt: int | 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, + ) -> InstanceStepResponse: + """ + Retrieves the full, untruncated output for a specific step on a workflow + instance. Returns a flat status-shaped JSON body with step `status` ('running' | + 'waiting' | 'complete' | 'errored'), `error` (nullable), and `output` (the step + value, or null while running/waiting/errored). When the step returned a + ReadableStream from step.do, the response is served as + 'application/octet-stream' with the raw bytes as the body instead of JSON. A + `status='running'` response with non-null `error` indicates the step is + currently retrying after a prior attempt failed. + + Args: + name: Exact step name from the instance logs response, including the generated counter + suffix. + + type: Step type to disambiguate step.do and waitForEvent entries that share the same + name. + + attempt: Specific attempt number to retrieve output or error for. + + 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 account_id: + raise ValueError(f"Expected a non-empty value for `account_id` but received {account_id!r}") + if not workflow_name: + raise ValueError(f"Expected a non-empty value for `workflow_name` but received {workflow_name!r}") + if not instance_id: + raise ValueError(f"Expected a non-empty value for `instance_id` but received {instance_id!r}") + return self._get( + path_template( + "/accounts/{account_id}/workflows/{workflow_name}/instances/{instance_id}/step", + account_id=account_id, + workflow_name=workflow_name, + instance_id=instance_id, + ), + options=make_request_options( + extra_headers=extra_headers, + extra_query=extra_query, + extra_body=extra_body, + timeout=timeout, + query=maybe_transform( + { + "name": name, + "type": type, + "attempt": attempt, + }, + instance_step_params.InstanceStepParams, + ), + post_parser=ResultWrapper[InstanceStepResponse]._unwrapper, + ), + cast_to=cast(Type[InstanceStepResponse], ResultWrapper[InstanceStepResponse]), + ) + class AsyncInstancesResource(AsyncAPIResource): @cached_property @@ -591,6 +672,80 @@ async def get( cast_to=cast(Type[InstanceGetResponse], ResultWrapper[InstanceGetResponse]), ) + async def step( + self, + instance_id: str, + *, + account_id: str, + workflow_name: str, + name: str, + type: Literal["step", "waitForEvent"], + attempt: int | 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, + ) -> InstanceStepResponse: + """ + Retrieves the full, untruncated output for a specific step on a workflow + instance. Returns a flat status-shaped JSON body with step `status` ('running' | + 'waiting' | 'complete' | 'errored'), `error` (nullable), and `output` (the step + value, or null while running/waiting/errored). When the step returned a + ReadableStream from step.do, the response is served as + 'application/octet-stream' with the raw bytes as the body instead of JSON. A + `status='running'` response with non-null `error` indicates the step is + currently retrying after a prior attempt failed. + + Args: + name: Exact step name from the instance logs response, including the generated counter + suffix. + + type: Step type to disambiguate step.do and waitForEvent entries that share the same + name. + + attempt: Specific attempt number to retrieve output or error for. + + 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 account_id: + raise ValueError(f"Expected a non-empty value for `account_id` but received {account_id!r}") + if not workflow_name: + raise ValueError(f"Expected a non-empty value for `workflow_name` but received {workflow_name!r}") + if not instance_id: + raise ValueError(f"Expected a non-empty value for `instance_id` but received {instance_id!r}") + return await self._get( + path_template( + "/accounts/{account_id}/workflows/{workflow_name}/instances/{instance_id}/step", + account_id=account_id, + workflow_name=workflow_name, + instance_id=instance_id, + ), + options=make_request_options( + extra_headers=extra_headers, + extra_query=extra_query, + extra_body=extra_body, + timeout=timeout, + query=await async_maybe_transform( + { + "name": name, + "type": type, + "attempt": attempt, + }, + instance_step_params.InstanceStepParams, + ), + post_parser=ResultWrapper[InstanceStepResponse]._unwrapper, + ), + cast_to=cast(Type[InstanceStepResponse], ResultWrapper[InstanceStepResponse]), + ) + class InstancesResourceWithRawResponse: def __init__(self, instances: InstancesResource) -> None: @@ -608,6 +763,9 @@ def __init__(self, instances: InstancesResource) -> None: self.get = to_raw_response_wrapper( instances.get, ) + self.step = to_raw_response_wrapper( + instances.step, + ) @cached_property def status(self) -> StatusResourceWithRawResponse: @@ -634,6 +792,9 @@ def __init__(self, instances: AsyncInstancesResource) -> None: self.get = async_to_raw_response_wrapper( instances.get, ) + self.step = async_to_raw_response_wrapper( + instances.step, + ) @cached_property def status(self) -> AsyncStatusResourceWithRawResponse: @@ -660,6 +821,9 @@ def __init__(self, instances: InstancesResource) -> None: self.get = to_streamed_response_wrapper( instances.get, ) + self.step = to_streamed_response_wrapper( + instances.step, + ) @cached_property def status(self) -> StatusResourceWithStreamingResponse: @@ -686,6 +850,9 @@ def __init__(self, instances: AsyncInstancesResource) -> None: self.get = async_to_streamed_response_wrapper( instances.get, ) + self.step = async_to_streamed_response_wrapper( + instances.step, + ) @cached_property def status(self) -> AsyncStatusResourceWithStreamingResponse: diff --git a/src/cloudflare/resources/workflows/versions.py b/src/cloudflare/resources/workflows/versions.py index b702774c237..51002d88919 100644 --- a/src/cloudflare/resources/workflows/versions.py +++ b/src/cloudflare/resources/workflows/versions.py @@ -22,6 +22,7 @@ from ...types.workflows import version_list_params from ...types.workflows.version_get_response import VersionGetResponse from ...types.workflows.version_list_response import VersionListResponse +from ...types.workflows.version_graph_response import VersionGraphResponse __all__ = ["VersionsResource", "AsyncVersionsResource"] @@ -147,6 +148,54 @@ def get( cast_to=cast(Type[VersionGetResponse], ResultWrapper[VersionGetResponse]), ) + def graph( + self, + version_id: str, + *, + account_id: str, + workflow_name: 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, + ) -> VersionGraphResponse: + """ + Retrieves the graph visualization of a workflow version. + + 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 account_id: + raise ValueError(f"Expected a non-empty value for `account_id` but received {account_id!r}") + if not workflow_name: + raise ValueError(f"Expected a non-empty value for `workflow_name` but received {workflow_name!r}") + if not version_id: + raise ValueError(f"Expected a non-empty value for `version_id` but received {version_id!r}") + return self._get( + path_template( + "/accounts/{account_id}/workflows/{workflow_name}/versions/{version_id}/graph", + account_id=account_id, + workflow_name=workflow_name, + version_id=version_id, + ), + options=make_request_options( + extra_headers=extra_headers, + extra_query=extra_query, + extra_body=extra_body, + timeout=timeout, + post_parser=ResultWrapper[VersionGraphResponse]._unwrapper, + ), + cast_to=cast(Type[VersionGraphResponse], ResultWrapper[VersionGraphResponse]), + ) + class AsyncVersionsResource(AsyncAPIResource): @cached_property @@ -269,6 +318,54 @@ async def get( cast_to=cast(Type[VersionGetResponse], ResultWrapper[VersionGetResponse]), ) + async def graph( + self, + version_id: str, + *, + account_id: str, + workflow_name: 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, + ) -> VersionGraphResponse: + """ + Retrieves the graph visualization of a workflow version. + + 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 account_id: + raise ValueError(f"Expected a non-empty value for `account_id` but received {account_id!r}") + if not workflow_name: + raise ValueError(f"Expected a non-empty value for `workflow_name` but received {workflow_name!r}") + if not version_id: + raise ValueError(f"Expected a non-empty value for `version_id` but received {version_id!r}") + return await self._get( + path_template( + "/accounts/{account_id}/workflows/{workflow_name}/versions/{version_id}/graph", + account_id=account_id, + workflow_name=workflow_name, + version_id=version_id, + ), + options=make_request_options( + extra_headers=extra_headers, + extra_query=extra_query, + extra_body=extra_body, + timeout=timeout, + post_parser=ResultWrapper[VersionGraphResponse]._unwrapper, + ), + cast_to=cast(Type[VersionGraphResponse], ResultWrapper[VersionGraphResponse]), + ) + class VersionsResourceWithRawResponse: def __init__(self, versions: VersionsResource) -> None: @@ -280,6 +377,9 @@ def __init__(self, versions: VersionsResource) -> None: self.get = to_raw_response_wrapper( versions.get, ) + self.graph = to_raw_response_wrapper( + versions.graph, + ) class AsyncVersionsResourceWithRawResponse: @@ -292,6 +392,9 @@ def __init__(self, versions: AsyncVersionsResource) -> None: self.get = async_to_raw_response_wrapper( versions.get, ) + self.graph = async_to_raw_response_wrapper( + versions.graph, + ) class VersionsResourceWithStreamingResponse: @@ -304,6 +407,9 @@ def __init__(self, versions: VersionsResource) -> None: self.get = to_streamed_response_wrapper( versions.get, ) + self.graph = to_streamed_response_wrapper( + versions.graph, + ) class AsyncVersionsResourceWithStreamingResponse: @@ -316,3 +422,6 @@ def __init__(self, versions: AsyncVersionsResource) -> None: self.get = async_to_streamed_response_wrapper( versions.get, ) + self.graph = async_to_streamed_response_wrapper( + versions.graph, + ) diff --git a/src/cloudflare/resources/workflows/workflows.py b/src/cloudflare/resources/workflows/workflows.py index 803e81f301d..e8a57121959 100644 --- a/src/cloudflare/resources/workflows/workflows.py +++ b/src/cloudflare/resources/workflows/workflows.py @@ -2,7 +2,7 @@ from __future__ import annotations -from typing import Type, cast +from typing import Type, Iterable, cast import httpx @@ -80,6 +80,7 @@ def update( class_name: str, script_name: str, limits: workflow_update_params.Limits | Omit = omit, + schedules: Iterable[workflow_update_params.Schedule] | 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, @@ -112,6 +113,7 @@ def update( "class_name": class_name, "script_name": script_name, "limits": limits, + "schedules": schedules, }, workflow_update_params.WorkflowUpdateParams, ), @@ -298,6 +300,7 @@ async def update( class_name: str, script_name: str, limits: workflow_update_params.Limits | Omit = omit, + schedules: Iterable[workflow_update_params.Schedule] | 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, @@ -330,6 +333,7 @@ async def update( "class_name": class_name, "script_name": script_name, "limits": limits, + "schedules": schedules, }, workflow_update_params.WorkflowUpdateParams, ), diff --git a/src/cloudflare/resources/zero_trust/access/__init__.py b/src/cloudflare/resources/zero_trust/access/__init__.py index ac8d0a9fa77..f8e1684a27b 100644 --- a/src/cloudflare/resources/zero_trust/access/__init__.py +++ b/src/cloudflare/resources/zero_trust/access/__init__.py @@ -128,6 +128,14 @@ SAMLCertificatesResourceWithStreamingResponse, AsyncSAMLCertificatesResourceWithStreamingResponse, ) +from .idp_federation_grants import ( + IdPFederationGrantsResource, + AsyncIdPFederationGrantsResource, + IdPFederationGrantsResourceWithRawResponse, + AsyncIdPFederationGrantsResourceWithRawResponse, + IdPFederationGrantsResourceWithStreamingResponse, + AsyncIdPFederationGrantsResourceWithStreamingResponse, +) __all__ = [ "AIControlsResource", @@ -142,6 +150,12 @@ "AsyncGatewayCAResourceWithRawResponse", "GatewayCAResourceWithStreamingResponse", "AsyncGatewayCAResourceWithStreamingResponse", + "IdPFederationGrantsResource", + "AsyncIdPFederationGrantsResource", + "IdPFederationGrantsResourceWithRawResponse", + "AsyncIdPFederationGrantsResourceWithRawResponse", + "IdPFederationGrantsResourceWithStreamingResponse", + "AsyncIdPFederationGrantsResourceWithStreamingResponse", "SAMLCertificatesResource", "AsyncSAMLCertificatesResource", "SAMLCertificatesResourceWithRawResponse", diff --git a/src/cloudflare/resources/zero_trust/access/access.py b/src/cloudflare/resources/zero_trust/access/access.py index f9f363b3313..9efd000a88a 100644 --- a/src/cloudflare/resources/zero_trust/access/access.py +++ b/src/cloudflare/resources/zero_trust/access/access.py @@ -92,6 +92,14 @@ SAMLCertificatesResourceWithStreamingResponse, AsyncSAMLCertificatesResourceWithStreamingResponse, ) +from .idp_federation_grants import ( + IdPFederationGrantsResource, + AsyncIdPFederationGrantsResource, + IdPFederationGrantsResourceWithRawResponse, + AsyncIdPFederationGrantsResourceWithRawResponse, + IdPFederationGrantsResourceWithStreamingResponse, + AsyncIdPFederationGrantsResourceWithStreamingResponse, +) from .ai_controls.ai_controls import ( AIControlsResource, AsyncAIControlsResource, @@ -137,6 +145,10 @@ def ai_controls(self) -> AIControlsResource: def gateway_ca(self) -> GatewayCAResource: return GatewayCAResource(self._client) + @cached_property + def idp_federation_grants(self) -> IdPFederationGrantsResource: + return IdPFederationGrantsResource(self._client) + @cached_property def saml_certificates(self) -> SAMLCertificatesResource: return SAMLCertificatesResource(self._client) @@ -218,6 +230,10 @@ def ai_controls(self) -> AsyncAIControlsResource: def gateway_ca(self) -> AsyncGatewayCAResource: return AsyncGatewayCAResource(self._client) + @cached_property + def idp_federation_grants(self) -> AsyncIdPFederationGrantsResource: + return AsyncIdPFederationGrantsResource(self._client) + @cached_property def saml_certificates(self) -> AsyncSAMLCertificatesResource: return AsyncSAMLCertificatesResource(self._client) @@ -302,6 +318,10 @@ def ai_controls(self) -> AIControlsResourceWithRawResponse: def gateway_ca(self) -> GatewayCAResourceWithRawResponse: return GatewayCAResourceWithRawResponse(self._access.gateway_ca) + @cached_property + def idp_federation_grants(self) -> IdPFederationGrantsResourceWithRawResponse: + return IdPFederationGrantsResourceWithRawResponse(self._access.idp_federation_grants) + @cached_property def saml_certificates(self) -> SAMLCertificatesResourceWithRawResponse: return SAMLCertificatesResourceWithRawResponse(self._access.saml_certificates) @@ -367,6 +387,10 @@ def ai_controls(self) -> AsyncAIControlsResourceWithRawResponse: def gateway_ca(self) -> AsyncGatewayCAResourceWithRawResponse: return AsyncGatewayCAResourceWithRawResponse(self._access.gateway_ca) + @cached_property + def idp_federation_grants(self) -> AsyncIdPFederationGrantsResourceWithRawResponse: + return AsyncIdPFederationGrantsResourceWithRawResponse(self._access.idp_federation_grants) + @cached_property def saml_certificates(self) -> AsyncSAMLCertificatesResourceWithRawResponse: return AsyncSAMLCertificatesResourceWithRawResponse(self._access.saml_certificates) @@ -432,6 +456,10 @@ def ai_controls(self) -> AIControlsResourceWithStreamingResponse: def gateway_ca(self) -> GatewayCAResourceWithStreamingResponse: return GatewayCAResourceWithStreamingResponse(self._access.gateway_ca) + @cached_property + def idp_federation_grants(self) -> IdPFederationGrantsResourceWithStreamingResponse: + return IdPFederationGrantsResourceWithStreamingResponse(self._access.idp_federation_grants) + @cached_property def saml_certificates(self) -> SAMLCertificatesResourceWithStreamingResponse: return SAMLCertificatesResourceWithStreamingResponse(self._access.saml_certificates) @@ -497,6 +525,10 @@ def ai_controls(self) -> AsyncAIControlsResourceWithStreamingResponse: def gateway_ca(self) -> AsyncGatewayCAResourceWithStreamingResponse: return AsyncGatewayCAResourceWithStreamingResponse(self._access.gateway_ca) + @cached_property + def idp_federation_grants(self) -> AsyncIdPFederationGrantsResourceWithStreamingResponse: + return AsyncIdPFederationGrantsResourceWithStreamingResponse(self._access.idp_federation_grants) + @cached_property def saml_certificates(self) -> AsyncSAMLCertificatesResourceWithStreamingResponse: return AsyncSAMLCertificatesResourceWithStreamingResponse(self._access.saml_certificates) diff --git a/src/cloudflare/resources/zero_trust/access/ai_controls/mcp/servers.py b/src/cloudflare/resources/zero_trust/access/ai_controls/mcp/servers.py index b855f84cbdc..3c874c8e772 100644 --- a/src/cloudflare/resources/zero_trust/access/ai_controls/mcp/servers.py +++ b/src/cloudflare/resources/zero_trust/access/ai_controls/mcp/servers.py @@ -61,6 +61,7 @@ def create( name: str, auth_credentials: str | Omit = omit, description: Optional[str] | Omit = omit, + is_shared_oauth_callback_enabled: bool | Omit = omit, updated_prompts: Iterable[server_create_params.UpdatedPrompt] | Omit = omit, updated_tools: Iterable[server_create_params.UpdatedTool] | Omit = omit, # Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs. @@ -76,6 +77,12 @@ def create( Args: id: server id + is_shared_oauth_callback_enabled: When true, the gateway worker uses the shared Cloudflare-owned OAuth callback + endpoint as the redirect_uri for upstream on-behalf OAuth, instead of the + customer portal hostname. New public server creates default to true; existing + servers default to false from migration until explicitly updated. Effective + behavior is gated by the gateway worker's per-env rollout mode KV key. + extra_headers: Send extra headers extra_query: Add additional query parameters to the request @@ -96,6 +103,7 @@ def create( "name": name, "auth_credentials": auth_credentials, "description": description, + "is_shared_oauth_callback_enabled": is_shared_oauth_callback_enabled, "updated_prompts": updated_prompts, "updated_tools": updated_tools, }, @@ -118,6 +126,7 @@ def update( account_id: str, auth_credentials: str | Omit = omit, description: Optional[str] | Omit = omit, + is_shared_oauth_callback_enabled: bool | Omit = omit, name: str | Omit = omit, updated_prompts: Iterable[server_update_params.UpdatedPrompt] | Omit = omit, updated_tools: Iterable[server_update_params.UpdatedTool] | Omit = omit, @@ -134,6 +143,12 @@ def update( Args: id: server id + is_shared_oauth_callback_enabled: When true, the gateway worker uses the shared Cloudflare-owned OAuth callback + endpoint as the redirect_uri for upstream on-behalf OAuth, instead of the + customer portal hostname. New public server creates default to true; existing + servers default to false from migration until explicitly updated. Effective + behavior is gated by the gateway worker's per-env rollout mode KV key. + extra_headers: Send extra headers extra_query: Add additional query parameters to the request @@ -152,6 +167,7 @@ def update( { "auth_credentials": auth_credentials, "description": description, + "is_shared_oauth_callback_enabled": is_shared_oauth_callback_enabled, "name": name, "updated_prompts": updated_prompts, "updated_tools": updated_tools, @@ -378,6 +394,7 @@ async def create( name: str, auth_credentials: str | Omit = omit, description: Optional[str] | Omit = omit, + is_shared_oauth_callback_enabled: bool | Omit = omit, updated_prompts: Iterable[server_create_params.UpdatedPrompt] | Omit = omit, updated_tools: Iterable[server_create_params.UpdatedTool] | Omit = omit, # Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs. @@ -393,6 +410,12 @@ async def create( Args: id: server id + is_shared_oauth_callback_enabled: When true, the gateway worker uses the shared Cloudflare-owned OAuth callback + endpoint as the redirect_uri for upstream on-behalf OAuth, instead of the + customer portal hostname. New public server creates default to true; existing + servers default to false from migration until explicitly updated. Effective + behavior is gated by the gateway worker's per-env rollout mode KV key. + extra_headers: Send extra headers extra_query: Add additional query parameters to the request @@ -413,6 +436,7 @@ async def create( "name": name, "auth_credentials": auth_credentials, "description": description, + "is_shared_oauth_callback_enabled": is_shared_oauth_callback_enabled, "updated_prompts": updated_prompts, "updated_tools": updated_tools, }, @@ -435,6 +459,7 @@ async def update( account_id: str, auth_credentials: str | Omit = omit, description: Optional[str] | Omit = omit, + is_shared_oauth_callback_enabled: bool | Omit = omit, name: str | Omit = omit, updated_prompts: Iterable[server_update_params.UpdatedPrompt] | Omit = omit, updated_tools: Iterable[server_update_params.UpdatedTool] | Omit = omit, @@ -451,6 +476,12 @@ async def update( Args: id: server id + is_shared_oauth_callback_enabled: When true, the gateway worker uses the shared Cloudflare-owned OAuth callback + endpoint as the redirect_uri for upstream on-behalf OAuth, instead of the + customer portal hostname. New public server creates default to true; existing + servers default to false from migration until explicitly updated. Effective + behavior is gated by the gateway worker's per-env rollout mode KV key. + extra_headers: Send extra headers extra_query: Add additional query parameters to the request @@ -469,6 +500,7 @@ async def update( { "auth_credentials": auth_credentials, "description": description, + "is_shared_oauth_callback_enabled": is_shared_oauth_callback_enabled, "name": name, "updated_prompts": updated_prompts, "updated_tools": updated_tools, diff --git a/src/cloudflare/resources/zero_trust/access/idp_federation_grants.py b/src/cloudflare/resources/zero_trust/access/idp_federation_grants.py new file mode 100644 index 00000000000..89da448503a --- /dev/null +++ b/src/cloudflare/resources/zero_trust/access/idp_federation_grants.py @@ -0,0 +1,520 @@ +# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. + +from __future__ import annotations + +from typing import Type, Optional, cast + +import httpx + +from ...._types import Body, Query, Headers, NotGiven, not_given +from ...._utils import path_template, maybe_transform, async_maybe_transform +from ...._compat import cached_property +from ...._resource import SyncAPIResource, AsyncAPIResource +from ...._response import ( + to_raw_response_wrapper, + to_streamed_response_wrapper, + async_to_raw_response_wrapper, + async_to_streamed_response_wrapper, +) +from ...._wrappers import ResultWrapper +from ...._base_client import make_request_options +from ....types.zero_trust.access import idp_federation_grant_create_params +from ....types.zero_trust.access.idp_federation_grant import IdPFederationGrant +from ....types.zero_trust.access.idp_federation_grant_list_response import IdPFederationGrantListResponse +from ....types.zero_trust.access.idp_federation_grant_delete_response import IdPFederationGrantDeleteResponse + +__all__ = ["IdPFederationGrantsResource", "AsyncIdPFederationGrantsResource"] + + +class IdPFederationGrantsResource(SyncAPIResource): + @cached_property + def with_raw_response(self) -> IdPFederationGrantsResourceWithRawResponse: + """ + This property can be used as a prefix for any HTTP method call to return + the raw response object instead of the parsed content. + + For more information, see https://www.github.com/cloudflare/cloudflare-python#accessing-raw-response-data-eg-headers + """ + return IdPFederationGrantsResourceWithRawResponse(self) + + @cached_property + def with_streaming_response(self) -> IdPFederationGrantsResourceWithStreamingResponse: + """ + An alternative to `.with_raw_response` that doesn't eagerly read the response body. + + For more information, see https://www.github.com/cloudflare/cloudflare-python#with_streaming_response + """ + return IdPFederationGrantsResourceWithStreamingResponse(self) + + def create( + self, + *, + account_id: str, + idp_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. + extra_headers: Headers | None = None, + extra_query: Query | None = None, + extra_body: Body | None = None, + timeout: float | httpx.Timeout | None | NotGiven = not_given, + ) -> Optional[IdPFederationGrant]: + """ + Creates an IdP federation grant for the specified identity provider, making it + available for federation to other accounts in the same Cloudflare organization. + + The account must belong to a Cloudflare organization. One-time pin and + Cloudflare-managed identity providers cannot be federated. An identity provider + may only have one active grant at a time. + + Args: + account_id: Identifier. + + idp_id: UID of the identity provider to federate. Must be an existing identity provider + in this account. One-time pin and Cloudflare-managed identity providers cannot + be federated. + + 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 account_id: + raise ValueError(f"Expected a non-empty value for `account_id` but received {account_id!r}") + return self._post( + path_template("/accounts/{account_id}/access/idp_federation_grants", account_id=account_id), + body=maybe_transform({"idp_id": idp_id}, idp_federation_grant_create_params.IdPFederationGrantCreateParams), + options=make_request_options( + extra_headers=extra_headers, + extra_query=extra_query, + extra_body=extra_body, + timeout=timeout, + post_parser=ResultWrapper[Optional[IdPFederationGrant]]._unwrapper, + ), + cast_to=cast(Type[Optional[IdPFederationGrant]], ResultWrapper[IdPFederationGrant]), + ) + + def list( + self, + *, + account_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. + extra_headers: Headers | None = None, + extra_query: Query | None = None, + extra_body: Body | None = None, + timeout: float | httpx.Timeout | None | NotGiven = not_given, + ) -> Optional[IdPFederationGrantListResponse]: + """ + Lists the IdP federation grants owned by the account. + + Args: + account_id: Identifier. + + 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 account_id: + raise ValueError(f"Expected a non-empty value for `account_id` but received {account_id!r}") + return self._get( + path_template("/accounts/{account_id}/access/idp_federation_grants", account_id=account_id), + options=make_request_options( + extra_headers=extra_headers, + extra_query=extra_query, + extra_body=extra_body, + timeout=timeout, + post_parser=ResultWrapper[Optional[IdPFederationGrantListResponse]]._unwrapper, + ), + cast_to=cast(Type[Optional[IdPFederationGrantListResponse]], ResultWrapper[IdPFederationGrantListResponse]), + ) + + def delete( + self, + grant_id: str, + *, + account_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. + extra_headers: Headers | None = None, + extra_query: Query | None = None, + extra_body: Body | None = None, + timeout: float | httpx.Timeout | None | NotGiven = not_given, + ) -> Optional[IdPFederationGrantDeleteResponse]: + """Deletes an IdP federation grant. + + The identity provider remains in the account, + but it is no longer available for federation to other accounts. + + Args: + account_id: Identifier. + + grant_id: Identifier. + + 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 account_id: + raise ValueError(f"Expected a non-empty value for `account_id` but received {account_id!r}") + if not grant_id: + raise ValueError(f"Expected a non-empty value for `grant_id` but received {grant_id!r}") + return self._delete( + path_template( + "/accounts/{account_id}/access/idp_federation_grants/{grant_id}", + account_id=account_id, + grant_id=grant_id, + ), + options=make_request_options( + extra_headers=extra_headers, + extra_query=extra_query, + extra_body=extra_body, + timeout=timeout, + post_parser=ResultWrapper[Optional[IdPFederationGrantDeleteResponse]]._unwrapper, + ), + cast_to=cast( + Type[Optional[IdPFederationGrantDeleteResponse]], ResultWrapper[IdPFederationGrantDeleteResponse] + ), + ) + + def get( + self, + grant_id: str, + *, + account_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. + extra_headers: Headers | None = None, + extra_query: Query | None = None, + extra_body: Body | None = None, + timeout: float | httpx.Timeout | None | NotGiven = not_given, + ) -> Optional[IdPFederationGrant]: + """ + Retrieves a single IdP federation grant by its UID. + + Args: + account_id: Identifier. + + grant_id: Identifier. + + 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 account_id: + raise ValueError(f"Expected a non-empty value for `account_id` but received {account_id!r}") + if not grant_id: + raise ValueError(f"Expected a non-empty value for `grant_id` but received {grant_id!r}") + return self._get( + path_template( + "/accounts/{account_id}/access/idp_federation_grants/{grant_id}", + account_id=account_id, + grant_id=grant_id, + ), + options=make_request_options( + extra_headers=extra_headers, + extra_query=extra_query, + extra_body=extra_body, + timeout=timeout, + post_parser=ResultWrapper[Optional[IdPFederationGrant]]._unwrapper, + ), + cast_to=cast(Type[Optional[IdPFederationGrant]], ResultWrapper[IdPFederationGrant]), + ) + + +class AsyncIdPFederationGrantsResource(AsyncAPIResource): + @cached_property + def with_raw_response(self) -> AsyncIdPFederationGrantsResourceWithRawResponse: + """ + This property can be used as a prefix for any HTTP method call to return + the raw response object instead of the parsed content. + + For more information, see https://www.github.com/cloudflare/cloudflare-python#accessing-raw-response-data-eg-headers + """ + return AsyncIdPFederationGrantsResourceWithRawResponse(self) + + @cached_property + def with_streaming_response(self) -> AsyncIdPFederationGrantsResourceWithStreamingResponse: + """ + An alternative to `.with_raw_response` that doesn't eagerly read the response body. + + For more information, see https://www.github.com/cloudflare/cloudflare-python#with_streaming_response + """ + return AsyncIdPFederationGrantsResourceWithStreamingResponse(self) + + async def create( + self, + *, + account_id: str, + idp_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. + extra_headers: Headers | None = None, + extra_query: Query | None = None, + extra_body: Body | None = None, + timeout: float | httpx.Timeout | None | NotGiven = not_given, + ) -> Optional[IdPFederationGrant]: + """ + Creates an IdP federation grant for the specified identity provider, making it + available for federation to other accounts in the same Cloudflare organization. + + The account must belong to a Cloudflare organization. One-time pin and + Cloudflare-managed identity providers cannot be federated. An identity provider + may only have one active grant at a time. + + Args: + account_id: Identifier. + + idp_id: UID of the identity provider to federate. Must be an existing identity provider + in this account. One-time pin and Cloudflare-managed identity providers cannot + be federated. + + 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 account_id: + raise ValueError(f"Expected a non-empty value for `account_id` but received {account_id!r}") + return await self._post( + path_template("/accounts/{account_id}/access/idp_federation_grants", account_id=account_id), + body=await async_maybe_transform( + {"idp_id": idp_id}, idp_federation_grant_create_params.IdPFederationGrantCreateParams + ), + options=make_request_options( + extra_headers=extra_headers, + extra_query=extra_query, + extra_body=extra_body, + timeout=timeout, + post_parser=ResultWrapper[Optional[IdPFederationGrant]]._unwrapper, + ), + cast_to=cast(Type[Optional[IdPFederationGrant]], ResultWrapper[IdPFederationGrant]), + ) + + async def list( + self, + *, + account_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. + extra_headers: Headers | None = None, + extra_query: Query | None = None, + extra_body: Body | None = None, + timeout: float | httpx.Timeout | None | NotGiven = not_given, + ) -> Optional[IdPFederationGrantListResponse]: + """ + Lists the IdP federation grants owned by the account. + + Args: + account_id: Identifier. + + 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 account_id: + raise ValueError(f"Expected a non-empty value for `account_id` but received {account_id!r}") + return await self._get( + path_template("/accounts/{account_id}/access/idp_federation_grants", account_id=account_id), + options=make_request_options( + extra_headers=extra_headers, + extra_query=extra_query, + extra_body=extra_body, + timeout=timeout, + post_parser=ResultWrapper[Optional[IdPFederationGrantListResponse]]._unwrapper, + ), + cast_to=cast(Type[Optional[IdPFederationGrantListResponse]], ResultWrapper[IdPFederationGrantListResponse]), + ) + + async def delete( + self, + grant_id: str, + *, + account_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. + extra_headers: Headers | None = None, + extra_query: Query | None = None, + extra_body: Body | None = None, + timeout: float | httpx.Timeout | None | NotGiven = not_given, + ) -> Optional[IdPFederationGrantDeleteResponse]: + """Deletes an IdP federation grant. + + The identity provider remains in the account, + but it is no longer available for federation to other accounts. + + Args: + account_id: Identifier. + + grant_id: Identifier. + + 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 account_id: + raise ValueError(f"Expected a non-empty value for `account_id` but received {account_id!r}") + if not grant_id: + raise ValueError(f"Expected a non-empty value for `grant_id` but received {grant_id!r}") + return await self._delete( + path_template( + "/accounts/{account_id}/access/idp_federation_grants/{grant_id}", + account_id=account_id, + grant_id=grant_id, + ), + options=make_request_options( + extra_headers=extra_headers, + extra_query=extra_query, + extra_body=extra_body, + timeout=timeout, + post_parser=ResultWrapper[Optional[IdPFederationGrantDeleteResponse]]._unwrapper, + ), + cast_to=cast( + Type[Optional[IdPFederationGrantDeleteResponse]], ResultWrapper[IdPFederationGrantDeleteResponse] + ), + ) + + async def get( + self, + grant_id: str, + *, + account_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. + extra_headers: Headers | None = None, + extra_query: Query | None = None, + extra_body: Body | None = None, + timeout: float | httpx.Timeout | None | NotGiven = not_given, + ) -> Optional[IdPFederationGrant]: + """ + Retrieves a single IdP federation grant by its UID. + + Args: + account_id: Identifier. + + grant_id: Identifier. + + 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 account_id: + raise ValueError(f"Expected a non-empty value for `account_id` but received {account_id!r}") + if not grant_id: + raise ValueError(f"Expected a non-empty value for `grant_id` but received {grant_id!r}") + return await self._get( + path_template( + "/accounts/{account_id}/access/idp_federation_grants/{grant_id}", + account_id=account_id, + grant_id=grant_id, + ), + options=make_request_options( + extra_headers=extra_headers, + extra_query=extra_query, + extra_body=extra_body, + timeout=timeout, + post_parser=ResultWrapper[Optional[IdPFederationGrant]]._unwrapper, + ), + cast_to=cast(Type[Optional[IdPFederationGrant]], ResultWrapper[IdPFederationGrant]), + ) + + +class IdPFederationGrantsResourceWithRawResponse: + def __init__(self, idp_federation_grants: IdPFederationGrantsResource) -> None: + self._idp_federation_grants = idp_federation_grants + + self.create = to_raw_response_wrapper( + idp_federation_grants.create, + ) + self.list = to_raw_response_wrapper( + idp_federation_grants.list, + ) + self.delete = to_raw_response_wrapper( + idp_federation_grants.delete, + ) + self.get = to_raw_response_wrapper( + idp_federation_grants.get, + ) + + +class AsyncIdPFederationGrantsResourceWithRawResponse: + def __init__(self, idp_federation_grants: AsyncIdPFederationGrantsResource) -> None: + self._idp_federation_grants = idp_federation_grants + + self.create = async_to_raw_response_wrapper( + idp_federation_grants.create, + ) + self.list = async_to_raw_response_wrapper( + idp_federation_grants.list, + ) + self.delete = async_to_raw_response_wrapper( + idp_federation_grants.delete, + ) + self.get = async_to_raw_response_wrapper( + idp_federation_grants.get, + ) + + +class IdPFederationGrantsResourceWithStreamingResponse: + def __init__(self, idp_federation_grants: IdPFederationGrantsResource) -> None: + self._idp_federation_grants = idp_federation_grants + + self.create = to_streamed_response_wrapper( + idp_federation_grants.create, + ) + self.list = to_streamed_response_wrapper( + idp_federation_grants.list, + ) + self.delete = to_streamed_response_wrapper( + idp_federation_grants.delete, + ) + self.get = to_streamed_response_wrapper( + idp_federation_grants.get, + ) + + +class AsyncIdPFederationGrantsResourceWithStreamingResponse: + def __init__(self, idp_federation_grants: AsyncIdPFederationGrantsResource) -> None: + self._idp_federation_grants = idp_federation_grants + + self.create = async_to_streamed_response_wrapper( + idp_federation_grants.create, + ) + self.list = async_to_streamed_response_wrapper( + idp_federation_grants.list, + ) + self.delete = async_to_streamed_response_wrapper( + idp_federation_grants.delete, + ) + self.get = async_to_streamed_response_wrapper( + idp_federation_grants.get, + ) diff --git a/src/cloudflare/resources/zero_trust/api.md b/src/cloudflare/resources/zero_trust/api.md index fae9fa9e7dc..14f6d3f5e57 100644 --- a/src/cloudflare/resources/zero_trust/api.md +++ b/src/cloudflare/resources/zero_trust/api.md @@ -498,6 +498,25 @@ Methods: - client.zero_trust.access.gateway_ca.list(\*, account_id) -> SyncSinglePage[GatewayCAListResponse] - client.zero_trust.access.gateway_ca.delete(certificate_id, \*, account_id) -> Optional[GatewayCADeleteResponse] +### IdPFederationGrants + +Types: + +```python +from cloudflare.types.zero_trust.access import ( + IdPFederationGrant, + IdPFederationGrantListResponse, + IdPFederationGrantDeleteResponse, +) +``` + +Methods: + +- client.zero_trust.access.idp_federation_grants.create(\*, account_id, \*\*params) -> Optional[IdPFederationGrant] +- client.zero_trust.access.idp_federation_grants.list(\*, account_id) -> Optional[IdPFederationGrantListResponse] +- client.zero_trust.access.idp_federation_grants.delete(grant_id, \*, account_id) -> Optional[IdPFederationGrantDeleteResponse] +- client.zero_trust.access.idp_federation_grants.get(grant_id, \*, account_id) -> Optional[IdPFederationGrant] + ### SAMLCertificates Types: @@ -1173,6 +1192,20 @@ Methods: - client.zero_trust.dex.rules.delete(rule_id, \*, account_id) -> Optional[RuleDeleteResponse] - client.zero_trust.dex.rules.get(rule_id, \*, account_id) -> Optional[RuleGetResponse] +### Devices + +#### ISPs + +Types: + +```python +from cloudflare.types.zero_trust.dex.devices import ISPs +``` + +Methods: + +- client.zero_trust.dex.devices.isps.list(device_id, \*, account_id, \*\*params) -> SyncV4PagePagination[Optional[ISPs]] + ## Tunnels Types: diff --git a/src/cloudflare/resources/zero_trust/dex/__init__.py b/src/cloudflare/resources/zero_trust/dex/__init__.py index b4e5b64def8..076ef18e863 100644 --- a/src/cloudflare/resources/zero_trust/dex/__init__.py +++ b/src/cloudflare/resources/zero_trust/dex/__init__.py @@ -32,6 +32,14 @@ TestsResourceWithStreamingResponse, AsyncTestsResourceWithStreamingResponse, ) +from .devices import ( + DevicesResource, + AsyncDevicesResource, + DevicesResourceWithRawResponse, + AsyncDevicesResourceWithRawResponse, + DevicesResourceWithStreamingResponse, + AsyncDevicesResourceWithStreamingResponse, +) from .commands import ( CommandsResource, AsyncCommandsResource, @@ -136,6 +144,12 @@ "AsyncRulesResourceWithRawResponse", "RulesResourceWithStreamingResponse", "AsyncRulesResourceWithStreamingResponse", + "DevicesResource", + "AsyncDevicesResource", + "DevicesResourceWithRawResponse", + "AsyncDevicesResourceWithRawResponse", + "DevicesResourceWithStreamingResponse", + "AsyncDevicesResourceWithStreamingResponse", "DEXResource", "AsyncDEXResource", "DEXResourceWithRawResponse", diff --git a/src/cloudflare/resources/zero_trust/dex/devices/__init__.py b/src/cloudflare/resources/zero_trust/dex/devices/__init__.py new file mode 100644 index 00000000000..c38aac84a8b --- /dev/null +++ b/src/cloudflare/resources/zero_trust/dex/devices/__init__.py @@ -0,0 +1,33 @@ +# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. + +from .isps import ( + ISPsResource, + AsyncISPsResource, + ISPsResourceWithRawResponse, + AsyncISPsResourceWithRawResponse, + ISPsResourceWithStreamingResponse, + AsyncISPsResourceWithStreamingResponse, +) +from .devices import ( + DevicesResource, + AsyncDevicesResource, + DevicesResourceWithRawResponse, + AsyncDevicesResourceWithRawResponse, + DevicesResourceWithStreamingResponse, + AsyncDevicesResourceWithStreamingResponse, +) + +__all__ = [ + "ISPsResource", + "AsyncISPsResource", + "ISPsResourceWithRawResponse", + "AsyncISPsResourceWithRawResponse", + "ISPsResourceWithStreamingResponse", + "AsyncISPsResourceWithStreamingResponse", + "DevicesResource", + "AsyncDevicesResource", + "DevicesResourceWithRawResponse", + "AsyncDevicesResourceWithRawResponse", + "DevicesResourceWithStreamingResponse", + "AsyncDevicesResourceWithStreamingResponse", +] diff --git a/src/cloudflare/resources/zero_trust/dex/devices/devices.py b/src/cloudflare/resources/zero_trust/dex/devices/devices.py new file mode 100644 index 00000000000..6af9a2a3313 --- /dev/null +++ b/src/cloudflare/resources/zero_trust/dex/devices/devices.py @@ -0,0 +1,102 @@ +# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. + +from __future__ import annotations + +from .isps import ( + ISPsResource, + AsyncISPsResource, + ISPsResourceWithRawResponse, + AsyncISPsResourceWithRawResponse, + ISPsResourceWithStreamingResponse, + AsyncISPsResourceWithStreamingResponse, +) +from ....._compat import cached_property +from ....._resource import SyncAPIResource, AsyncAPIResource + +__all__ = ["DevicesResource", "AsyncDevicesResource"] + + +class DevicesResource(SyncAPIResource): + @cached_property + def isps(self) -> ISPsResource: + return ISPsResource(self._client) + + @cached_property + def with_raw_response(self) -> DevicesResourceWithRawResponse: + """ + This property can be used as a prefix for any HTTP method call to return + the raw response object instead of the parsed content. + + For more information, see https://www.github.com/cloudflare/cloudflare-python#accessing-raw-response-data-eg-headers + """ + return DevicesResourceWithRawResponse(self) + + @cached_property + def with_streaming_response(self) -> DevicesResourceWithStreamingResponse: + """ + An alternative to `.with_raw_response` that doesn't eagerly read the response body. + + For more information, see https://www.github.com/cloudflare/cloudflare-python#with_streaming_response + """ + return DevicesResourceWithStreamingResponse(self) + + +class AsyncDevicesResource(AsyncAPIResource): + @cached_property + def isps(self) -> AsyncISPsResource: + return AsyncISPsResource(self._client) + + @cached_property + def with_raw_response(self) -> AsyncDevicesResourceWithRawResponse: + """ + This property can be used as a prefix for any HTTP method call to return + the raw response object instead of the parsed content. + + For more information, see https://www.github.com/cloudflare/cloudflare-python#accessing-raw-response-data-eg-headers + """ + return AsyncDevicesResourceWithRawResponse(self) + + @cached_property + def with_streaming_response(self) -> AsyncDevicesResourceWithStreamingResponse: + """ + An alternative to `.with_raw_response` that doesn't eagerly read the response body. + + For more information, see https://www.github.com/cloudflare/cloudflare-python#with_streaming_response + """ + return AsyncDevicesResourceWithStreamingResponse(self) + + +class DevicesResourceWithRawResponse: + def __init__(self, devices: DevicesResource) -> None: + self._devices = devices + + @cached_property + def isps(self) -> ISPsResourceWithRawResponse: + return ISPsResourceWithRawResponse(self._devices.isps) + + +class AsyncDevicesResourceWithRawResponse: + def __init__(self, devices: AsyncDevicesResource) -> None: + self._devices = devices + + @cached_property + def isps(self) -> AsyncISPsResourceWithRawResponse: + return AsyncISPsResourceWithRawResponse(self._devices.isps) + + +class DevicesResourceWithStreamingResponse: + def __init__(self, devices: DevicesResource) -> None: + self._devices = devices + + @cached_property + def isps(self) -> ISPsResourceWithStreamingResponse: + return ISPsResourceWithStreamingResponse(self._devices.isps) + + +class AsyncDevicesResourceWithStreamingResponse: + def __init__(self, devices: AsyncDevicesResource) -> None: + self._devices = devices + + @cached_property + def isps(self) -> AsyncISPsResourceWithStreamingResponse: + return AsyncISPsResourceWithStreamingResponse(self._devices.isps) diff --git a/src/cloudflare/resources/zero_trust/dex/devices/isps.py b/src/cloudflare/resources/zero_trust/dex/devices/isps.py new file mode 100644 index 00000000000..4e3675de167 --- /dev/null +++ b/src/cloudflare/resources/zero_trust/dex/devices/isps.py @@ -0,0 +1,258 @@ +# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. + +from __future__ import annotations + +from typing import Union, Optional +from datetime import datetime +from typing_extensions import Literal + +import httpx + +from ....._types import Body, Omit, Query, Headers, NotGiven, omit, not_given +from ....._utils import path_template, maybe_transform +from ....._compat import cached_property +from ....._resource import SyncAPIResource, AsyncAPIResource +from ....._response import ( + to_raw_response_wrapper, + to_streamed_response_wrapper, + async_to_raw_response_wrapper, + async_to_streamed_response_wrapper, +) +from .....pagination import SyncV4PagePagination, AsyncV4PagePagination +from ....._base_client import AsyncPaginator, make_request_options +from .....types.zero_trust.dex.devices import isp_list_params +from .....types.zero_trust.dex.devices.isps import ISPs + +__all__ = ["ISPsResource", "AsyncISPsResource"] + + +class ISPsResource(SyncAPIResource): + @cached_property + def with_raw_response(self) -> ISPsResourceWithRawResponse: + """ + This property can be used as a prefix for any HTTP method call to return + the raw response object instead of the parsed content. + + For more information, see https://www.github.com/cloudflare/cloudflare-python#accessing-raw-response-data-eg-headers + """ + return ISPsResourceWithRawResponse(self) + + @cached_property + def with_streaming_response(self) -> ISPsResourceWithStreamingResponse: + """ + An alternative to `.with_raw_response` that doesn't eagerly read the response body. + + For more information, see https://www.github.com/cloudflare/cloudflare-python#with_streaming_response + """ + return ISPsResourceWithStreamingResponse(self) + + def list( + self, + device_id: str, + *, + account_id: str, + per_page: int, + cursor: str | Omit = omit, + from_: Union[str, datetime] | Omit = omit, + page: int | Omit = omit, + sort_by: Literal["time_start"] | Omit = omit, + sort_order: Literal["ASC", "DESC"] | Omit = omit, + to: Union[str, datetime] | 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, + ) -> SyncV4PagePagination[Optional[ISPs]]: + """ + List ISP information observed for a specific device during traceroute tests. + + Args: + device_id: API Resource UUID tag. + + per_page: Number of items per page + + cursor: Cursor for cursor-based pagination. Mutually exclusive with page. + + from_: Start time for the query in ISO 8601 format + + page: Page number of paginated results. Mutually exclusive with cursor. + + sort_by: The field to sort results by + + sort_order: The order to sort results + + to: End time for the query in ISO 8601 format + + 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 account_id: + raise ValueError(f"Expected a non-empty value for `account_id` but received {account_id!r}") + if not device_id: + raise ValueError(f"Expected a non-empty value for `device_id` but received {device_id!r}") + return self._get_api_list( + path_template( + "/accounts/{account_id}/dex/devices/{device_id}/isps", account_id=account_id, device_id=device_id + ), + page=SyncV4PagePagination[Optional[ISPs]], + options=make_request_options( + extra_headers=extra_headers, + extra_query=extra_query, + extra_body=extra_body, + timeout=timeout, + query=maybe_transform( + { + "per_page": per_page, + "cursor": cursor, + "from_": from_, + "page": page, + "sort_by": sort_by, + "sort_order": sort_order, + "to": to, + }, + isp_list_params.ISPListParams, + ), + ), + model=ISPs, + ) + + +class AsyncISPsResource(AsyncAPIResource): + @cached_property + def with_raw_response(self) -> AsyncISPsResourceWithRawResponse: + """ + This property can be used as a prefix for any HTTP method call to return + the raw response object instead of the parsed content. + + For more information, see https://www.github.com/cloudflare/cloudflare-python#accessing-raw-response-data-eg-headers + """ + return AsyncISPsResourceWithRawResponse(self) + + @cached_property + def with_streaming_response(self) -> AsyncISPsResourceWithStreamingResponse: + """ + An alternative to `.with_raw_response` that doesn't eagerly read the response body. + + For more information, see https://www.github.com/cloudflare/cloudflare-python#with_streaming_response + """ + return AsyncISPsResourceWithStreamingResponse(self) + + def list( + self, + device_id: str, + *, + account_id: str, + per_page: int, + cursor: str | Omit = omit, + from_: Union[str, datetime] | Omit = omit, + page: int | Omit = omit, + sort_by: Literal["time_start"] | Omit = omit, + sort_order: Literal["ASC", "DESC"] | Omit = omit, + to: Union[str, datetime] | 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, + ) -> AsyncPaginator[Optional[ISPs], AsyncV4PagePagination[Optional[ISPs]]]: + """ + List ISP information observed for a specific device during traceroute tests. + + Args: + device_id: API Resource UUID tag. + + per_page: Number of items per page + + cursor: Cursor for cursor-based pagination. Mutually exclusive with page. + + from_: Start time for the query in ISO 8601 format + + page: Page number of paginated results. Mutually exclusive with cursor. + + sort_by: The field to sort results by + + sort_order: The order to sort results + + to: End time for the query in ISO 8601 format + + 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 account_id: + raise ValueError(f"Expected a non-empty value for `account_id` but received {account_id!r}") + if not device_id: + raise ValueError(f"Expected a non-empty value for `device_id` but received {device_id!r}") + return self._get_api_list( + path_template( + "/accounts/{account_id}/dex/devices/{device_id}/isps", account_id=account_id, device_id=device_id + ), + page=AsyncV4PagePagination[Optional[ISPs]], + options=make_request_options( + extra_headers=extra_headers, + extra_query=extra_query, + extra_body=extra_body, + timeout=timeout, + query=maybe_transform( + { + "per_page": per_page, + "cursor": cursor, + "from_": from_, + "page": page, + "sort_by": sort_by, + "sort_order": sort_order, + "to": to, + }, + isp_list_params.ISPListParams, + ), + ), + model=ISPs, + ) + + +class ISPsResourceWithRawResponse: + def __init__(self, isps: ISPsResource) -> None: + self._isps = isps + + self.list = to_raw_response_wrapper( + isps.list, + ) + + +class AsyncISPsResourceWithRawResponse: + def __init__(self, isps: AsyncISPsResource) -> None: + self._isps = isps + + self.list = async_to_raw_response_wrapper( + isps.list, + ) + + +class ISPsResourceWithStreamingResponse: + def __init__(self, isps: ISPsResource) -> None: + self._isps = isps + + self.list = to_streamed_response_wrapper( + isps.list, + ) + + +class AsyncISPsResourceWithStreamingResponse: + def __init__(self, isps: AsyncISPsResource) -> None: + self._isps = isps + + self.list = async_to_streamed_response_wrapper( + isps.list, + ) diff --git a/src/cloudflare/resources/zero_trust/dex/dex.py b/src/cloudflare/resources/zero_trust/dex/dex.py index 82bd1271b6f..7239e291764 100644 --- a/src/cloudflare/resources/zero_trust/dex/dex.py +++ b/src/cloudflare/resources/zero_trust/dex/dex.py @@ -28,6 +28,14 @@ AsyncTestsResourceWithStreamingResponse, ) from ...._resource import SyncAPIResource, AsyncAPIResource +from .devices.devices import ( + DevicesResource, + AsyncDevicesResource, + DevicesResourceWithRawResponse, + AsyncDevicesResourceWithRawResponse, + DevicesResourceWithStreamingResponse, + AsyncDevicesResourceWithStreamingResponse, +) from .traceroute_tests import ( TracerouteTestsResource, AsyncTracerouteTestsResource, @@ -117,6 +125,10 @@ def traceroute_tests(self) -> TracerouteTestsResource: def rules(self) -> RulesResource: return RulesResource(self._client) + @cached_property + def devices(self) -> DevicesResource: + return DevicesResource(self._client) + @cached_property def with_raw_response(self) -> DEXResourceWithRawResponse: """ @@ -174,6 +186,10 @@ def traceroute_tests(self) -> AsyncTracerouteTestsResource: def rules(self) -> AsyncRulesResource: return AsyncRulesResource(self._client) + @cached_property + def devices(self) -> AsyncDevicesResource: + return AsyncDevicesResource(self._client) + @cached_property def with_raw_response(self) -> AsyncDEXResourceWithRawResponse: """ @@ -234,6 +250,10 @@ def traceroute_tests(self) -> TracerouteTestsResourceWithRawResponse: def rules(self) -> RulesResourceWithRawResponse: return RulesResourceWithRawResponse(self._dex.rules) + @cached_property + def devices(self) -> DevicesResourceWithRawResponse: + return DevicesResourceWithRawResponse(self._dex.devices) + class AsyncDEXResourceWithRawResponse: def __init__(self, dex: AsyncDEXResource) -> None: @@ -275,6 +295,10 @@ def traceroute_tests(self) -> AsyncTracerouteTestsResourceWithRawResponse: def rules(self) -> AsyncRulesResourceWithRawResponse: return AsyncRulesResourceWithRawResponse(self._dex.rules) + @cached_property + def devices(self) -> AsyncDevicesResourceWithRawResponse: + return AsyncDevicesResourceWithRawResponse(self._dex.devices) + class DEXResourceWithStreamingResponse: def __init__(self, dex: DEXResource) -> None: @@ -316,6 +340,10 @@ def traceroute_tests(self) -> TracerouteTestsResourceWithStreamingResponse: def rules(self) -> RulesResourceWithStreamingResponse: return RulesResourceWithStreamingResponse(self._dex.rules) + @cached_property + def devices(self) -> DevicesResourceWithStreamingResponse: + return DevicesResourceWithStreamingResponse(self._dex.devices) + class AsyncDEXResourceWithStreamingResponse: def __init__(self, dex: AsyncDEXResource) -> None: @@ -356,3 +384,7 @@ def traceroute_tests(self) -> AsyncTracerouteTestsResourceWithStreamingResponse: @cached_property def rules(self) -> AsyncRulesResourceWithStreamingResponse: return AsyncRulesResourceWithStreamingResponse(self._dex.rules) + + @cached_property + def devices(self) -> AsyncDevicesResourceWithStreamingResponse: + return AsyncDevicesResourceWithStreamingResponse(self._dex.devices) diff --git a/src/cloudflare/types/abuse_reports/mitigation_list_params.py b/src/cloudflare/types/abuse_reports/mitigation_list_params.py index 4093a07c4fb..6e0e1472123 100644 --- a/src/cloudflare/types/abuse_reports/mitigation_list_params.py +++ b/src/cloudflare/types/abuse_reports/mitigation_list_params.py @@ -41,13 +41,25 @@ class MitigationListParams(TypedDict, total=False): """Filter by the status of the mitigation.""" type: Literal[ + "account_suspend", + "copyright_interstitial", + "geo_block", "legal_block", + "malware_interstitial", "misleading_interstitial", - "phishing_interstitial", "network_block", + "phishing_interstitial", + "playfairite_enforce", + "r2_takedown_account", + "r2_takedown_bucket", + "r2_takedown_object", "rate_limit_cache", - "account_suspend", "redirect_video_stream", + "registrar_freeze", + "registrar_parking", + "stream_block_account", + "user_suspend", + "workers_takedown_by_zone_id", ] """Filter by the type of mitigation. diff --git a/src/cloudflare/types/abuse_reports/mitigation_list_response.py b/src/cloudflare/types/abuse_reports/mitigation_list_response.py index 3e0f9fd8075..6f2f5983a70 100644 --- a/src/cloudflare/types/abuse_reports/mitigation_list_response.py +++ b/src/cloudflare/types/abuse_reports/mitigation_list_response.py @@ -21,20 +21,33 @@ class Mitigation(BaseModel): entity_id: str entity_type: Literal["url_pattern", "account", "zone"] + """The type of entity targeted by a mitigation.""" status: Literal["pending", "active", "in_review", "cancelled", "removed"] """The status of a mitigation""" type: Literal[ + "account_suspend", + "copyright_interstitial", + "geo_block", "legal_block", + "malware_interstitial", "misleading_interstitial", - "phishing_interstitial", "network_block", + "phishing_interstitial", + "playfairite_enforce", + "r2_takedown_account", + "r2_takedown_bucket", + "r2_takedown_object", "rate_limit_cache", - "account_suspend", "redirect_video_stream", + "registrar_freeze", + "registrar_parking", + "stream_block_account", + "user_suspend", + "workers_takedown_by_zone_id", ] - """The type of mitigation""" + """The type of mitigation applied to a reported entity.""" class MitigationListResponse(BaseModel): diff --git a/src/cloudflare/types/abuse_reports/mitigation_review_response.py b/src/cloudflare/types/abuse_reports/mitigation_review_response.py index 6e83c1f4ad3..7d5cf2e61ae 100644 --- a/src/cloudflare/types/abuse_reports/mitigation_review_response.py +++ b/src/cloudflare/types/abuse_reports/mitigation_review_response.py @@ -20,17 +20,30 @@ class MitigationReviewResponse(BaseModel): entity_id: str entity_type: Literal["url_pattern", "account", "zone"] + """The type of entity targeted by a mitigation.""" status: Literal["pending", "active", "in_review", "cancelled", "removed"] """The status of a mitigation""" type: Literal[ + "account_suspend", + "copyright_interstitial", + "geo_block", "legal_block", + "malware_interstitial", "misleading_interstitial", - "phishing_interstitial", "network_block", + "phishing_interstitial", + "playfairite_enforce", + "r2_takedown_account", + "r2_takedown_bucket", + "r2_takedown_object", "rate_limit_cache", - "account_suspend", "redirect_video_stream", + "registrar_freeze", + "registrar_parking", + "stream_block_account", + "user_suspend", + "workers_takedown_by_zone_id", ] - """The type of mitigation""" + """The type of mitigation applied to a reported entity.""" diff --git a/src/cloudflare/types/ai_gateway/ai_gateway_create_response.py b/src/cloudflare/types/ai_gateway/ai_gateway_create_response.py index 753c5704050..4d5c36e42ec 100644 --- a/src/cloudflare/types/ai_gateway/ai_gateway_create_response.py +++ b/src/cloudflare/types/ai_gateway/ai_gateway_create_response.py @@ -18,6 +18,13 @@ "GuardrailsPrompt", "GuardrailsResponse", "Otel", + "SpendLimits", + "SpendLimitsRule", + "SpendLimitsRuleMetadata", + "SpendLimitsRuleMetadataMode", + "SpendLimitsRuleMetadataUnionMember1", + "SpendLimitsRuleModel", + "SpendLimitsRuleProvider", "Stripe", "StripeUsageEvent", ] @@ -128,6 +135,57 @@ class Otel(BaseModel): content_type: Optional[Literal["json", "protobuf"]] = None +class SpendLimitsRuleMetadataMode(BaseModel): + mode: Literal["partition"] + + +class SpendLimitsRuleMetadataUnionMember1(BaseModel): + mode: Literal["filter"] + + values: List[str] + + +SpendLimitsRuleMetadata: TypeAlias = Union[SpendLimitsRuleMetadataMode, SpendLimitsRuleMetadataUnionMember1] + + +class SpendLimitsRuleModel(BaseModel): + mode: Literal["filter"] + + values: List[str] + + +class SpendLimitsRuleProvider(BaseModel): + mode: Literal["filter"] + + values: List[str] + + +class SpendLimitsRule(BaseModel): + limit: float + + limit_type: Literal["cost"] = FieldInfo(alias="limitType") + + window: int + + id: Optional[str] = None + + enabled: Optional[bool] = None + + metadata: Optional[Dict[str, SpendLimitsRuleMetadata]] = None + + model: Optional[SpendLimitsRuleModel] = None + + provider: Optional[SpendLimitsRuleProvider] = None + + technique: Optional[Literal["fixed", "sliding"]] = None + + +class SpendLimits(BaseModel): + enabled: Optional[bool] = None + + rules: Optional[List[SpendLimitsRule]] = None + + class StripeUsageEvent(BaseModel): payload: str @@ -185,6 +243,8 @@ class AIGatewayCreateResponse(BaseModel): retry_max_attempts: Optional[int] = None """Maximum number of retry attempts for failed requests (1-5)""" + spend_limits: Optional[SpendLimits] = None + store_id: Optional[str] = None stripe: Optional[Stripe] = None diff --git a/src/cloudflare/types/ai_gateway/ai_gateway_delete_response.py b/src/cloudflare/types/ai_gateway/ai_gateway_delete_response.py index bf676c3ea83..3fa277ec5af 100644 --- a/src/cloudflare/types/ai_gateway/ai_gateway_delete_response.py +++ b/src/cloudflare/types/ai_gateway/ai_gateway_delete_response.py @@ -18,6 +18,13 @@ "GuardrailsPrompt", "GuardrailsResponse", "Otel", + "SpendLimits", + "SpendLimitsRule", + "SpendLimitsRuleMetadata", + "SpendLimitsRuleMetadataMode", + "SpendLimitsRuleMetadataUnionMember1", + "SpendLimitsRuleModel", + "SpendLimitsRuleProvider", "Stripe", "StripeUsageEvent", ] @@ -128,6 +135,57 @@ class Otel(BaseModel): content_type: Optional[Literal["json", "protobuf"]] = None +class SpendLimitsRuleMetadataMode(BaseModel): + mode: Literal["partition"] + + +class SpendLimitsRuleMetadataUnionMember1(BaseModel): + mode: Literal["filter"] + + values: List[str] + + +SpendLimitsRuleMetadata: TypeAlias = Union[SpendLimitsRuleMetadataMode, SpendLimitsRuleMetadataUnionMember1] + + +class SpendLimitsRuleModel(BaseModel): + mode: Literal["filter"] + + values: List[str] + + +class SpendLimitsRuleProvider(BaseModel): + mode: Literal["filter"] + + values: List[str] + + +class SpendLimitsRule(BaseModel): + limit: float + + limit_type: Literal["cost"] = FieldInfo(alias="limitType") + + window: int + + id: Optional[str] = None + + enabled: Optional[bool] = None + + metadata: Optional[Dict[str, SpendLimitsRuleMetadata]] = None + + model: Optional[SpendLimitsRuleModel] = None + + provider: Optional[SpendLimitsRuleProvider] = None + + technique: Optional[Literal["fixed", "sliding"]] = None + + +class SpendLimits(BaseModel): + enabled: Optional[bool] = None + + rules: Optional[List[SpendLimitsRule]] = None + + class StripeUsageEvent(BaseModel): payload: str @@ -185,6 +243,8 @@ class AIGatewayDeleteResponse(BaseModel): retry_max_attempts: Optional[int] = None """Maximum number of retry attempts for failed requests (1-5)""" + spend_limits: Optional[SpendLimits] = None + store_id: Optional[str] = None stripe: Optional[Stripe] = None diff --git a/src/cloudflare/types/ai_gateway/ai_gateway_get_response.py b/src/cloudflare/types/ai_gateway/ai_gateway_get_response.py index 642f2530597..8baedb39786 100644 --- a/src/cloudflare/types/ai_gateway/ai_gateway_get_response.py +++ b/src/cloudflare/types/ai_gateway/ai_gateway_get_response.py @@ -18,6 +18,13 @@ "GuardrailsPrompt", "GuardrailsResponse", "Otel", + "SpendLimits", + "SpendLimitsRule", + "SpendLimitsRuleMetadata", + "SpendLimitsRuleMetadataMode", + "SpendLimitsRuleMetadataUnionMember1", + "SpendLimitsRuleModel", + "SpendLimitsRuleProvider", "Stripe", "StripeUsageEvent", ] @@ -128,6 +135,57 @@ class Otel(BaseModel): content_type: Optional[Literal["json", "protobuf"]] = None +class SpendLimitsRuleMetadataMode(BaseModel): + mode: Literal["partition"] + + +class SpendLimitsRuleMetadataUnionMember1(BaseModel): + mode: Literal["filter"] + + values: List[str] + + +SpendLimitsRuleMetadata: TypeAlias = Union[SpendLimitsRuleMetadataMode, SpendLimitsRuleMetadataUnionMember1] + + +class SpendLimitsRuleModel(BaseModel): + mode: Literal["filter"] + + values: List[str] + + +class SpendLimitsRuleProvider(BaseModel): + mode: Literal["filter"] + + values: List[str] + + +class SpendLimitsRule(BaseModel): + limit: float + + limit_type: Literal["cost"] = FieldInfo(alias="limitType") + + window: int + + id: Optional[str] = None + + enabled: Optional[bool] = None + + metadata: Optional[Dict[str, SpendLimitsRuleMetadata]] = None + + model: Optional[SpendLimitsRuleModel] = None + + provider: Optional[SpendLimitsRuleProvider] = None + + technique: Optional[Literal["fixed", "sliding"]] = None + + +class SpendLimits(BaseModel): + enabled: Optional[bool] = None + + rules: Optional[List[SpendLimitsRule]] = None + + class StripeUsageEvent(BaseModel): payload: str @@ -185,6 +243,8 @@ class AIGatewayGetResponse(BaseModel): retry_max_attempts: Optional[int] = None """Maximum number of retry attempts for failed requests (1-5)""" + spend_limits: Optional[SpendLimits] = None + store_id: Optional[str] = None stripe: Optional[Stripe] = None diff --git a/src/cloudflare/types/ai_gateway/ai_gateway_list_response.py b/src/cloudflare/types/ai_gateway/ai_gateway_list_response.py index 06720a66689..90b0d287777 100644 --- a/src/cloudflare/types/ai_gateway/ai_gateway_list_response.py +++ b/src/cloudflare/types/ai_gateway/ai_gateway_list_response.py @@ -18,6 +18,13 @@ "GuardrailsPrompt", "GuardrailsResponse", "Otel", + "SpendLimits", + "SpendLimitsRule", + "SpendLimitsRuleMetadata", + "SpendLimitsRuleMetadataMode", + "SpendLimitsRuleMetadataUnionMember1", + "SpendLimitsRuleModel", + "SpendLimitsRuleProvider", "Stripe", "StripeUsageEvent", ] @@ -128,6 +135,57 @@ class Otel(BaseModel): content_type: Optional[Literal["json", "protobuf"]] = None +class SpendLimitsRuleMetadataMode(BaseModel): + mode: Literal["partition"] + + +class SpendLimitsRuleMetadataUnionMember1(BaseModel): + mode: Literal["filter"] + + values: List[str] + + +SpendLimitsRuleMetadata: TypeAlias = Union[SpendLimitsRuleMetadataMode, SpendLimitsRuleMetadataUnionMember1] + + +class SpendLimitsRuleModel(BaseModel): + mode: Literal["filter"] + + values: List[str] + + +class SpendLimitsRuleProvider(BaseModel): + mode: Literal["filter"] + + values: List[str] + + +class SpendLimitsRule(BaseModel): + limit: float + + limit_type: Literal["cost"] = FieldInfo(alias="limitType") + + window: int + + id: Optional[str] = None + + enabled: Optional[bool] = None + + metadata: Optional[Dict[str, SpendLimitsRuleMetadata]] = None + + model: Optional[SpendLimitsRuleModel] = None + + provider: Optional[SpendLimitsRuleProvider] = None + + technique: Optional[Literal["fixed", "sliding"]] = None + + +class SpendLimits(BaseModel): + enabled: Optional[bool] = None + + rules: Optional[List[SpendLimitsRule]] = None + + class StripeUsageEvent(BaseModel): payload: str @@ -185,6 +243,8 @@ class AIGatewayListResponse(BaseModel): retry_max_attempts: Optional[int] = None """Maximum number of retry attempts for failed requests (1-5)""" + spend_limits: Optional[SpendLimits] = None + store_id: Optional[str] = None stripe: Optional[Stripe] = None diff --git a/src/cloudflare/types/ai_gateway/ai_gateway_update_params.py b/src/cloudflare/types/ai_gateway/ai_gateway_update_params.py index 798b0082c6d..de45bb4501c 100644 --- a/src/cloudflare/types/ai_gateway/ai_gateway_update_params.py +++ b/src/cloudflare/types/ai_gateway/ai_gateway_update_params.py @@ -18,6 +18,13 @@ "GuardrailsPrompt", "GuardrailsResponse", "Otel", + "SpendLimits", + "SpendLimitsRule", + "SpendLimitsRuleMetadata", + "SpendLimitsRuleMetadataMode", + "SpendLimitsRuleMetadataUnionMember1", + "SpendLimitsRuleModel", + "SpendLimitsRuleProvider", "Stripe", "StripeUsageEvent", ] @@ -63,6 +70,8 @@ class AIGatewayUpdateParams(TypedDict, total=False): retry_max_attempts: Optional[int] """Maximum number of retry attempts for failed requests (1-5)""" + spend_limits: Optional[SpendLimits] + store_id: Optional[str] stripe: Optional[Stripe] @@ -181,6 +190,57 @@ class Otel(TypedDict, total=False): content_type: Literal["json", "protobuf"] +class SpendLimitsRuleMetadataMode(TypedDict, total=False): + mode: Required[Literal["partition"]] + + +class SpendLimitsRuleMetadataUnionMember1(TypedDict, total=False): + mode: Required[Literal["filter"]] + + values: Required[SequenceNotStr[str]] + + +SpendLimitsRuleMetadata: TypeAlias = Union[SpendLimitsRuleMetadataMode, SpendLimitsRuleMetadataUnionMember1] + + +class SpendLimitsRuleModel(TypedDict, total=False): + mode: Required[Literal["filter"]] + + values: Required[SequenceNotStr[str]] + + +class SpendLimitsRuleProvider(TypedDict, total=False): + mode: Required[Literal["filter"]] + + values: Required[SequenceNotStr[str]] + + +class SpendLimitsRule(TypedDict, total=False): + limit: Required[float] + + limit_type: Required[Annotated[Literal["cost"], PropertyInfo(alias="limitType")]] + + window: Required[int] + + id: str + + enabled: bool + + metadata: Dict[str, SpendLimitsRuleMetadata] + + model: SpendLimitsRuleModel + + provider: SpendLimitsRuleProvider + + technique: Literal["fixed", "sliding"] + + +class SpendLimits(TypedDict, total=False): + enabled: bool + + rules: Iterable[SpendLimitsRule] + + class StripeUsageEvent(TypedDict, total=False): payload: Required[str] diff --git a/src/cloudflare/types/ai_gateway/ai_gateway_update_response.py b/src/cloudflare/types/ai_gateway/ai_gateway_update_response.py index 8d5d502e961..febe03efdb8 100644 --- a/src/cloudflare/types/ai_gateway/ai_gateway_update_response.py +++ b/src/cloudflare/types/ai_gateway/ai_gateway_update_response.py @@ -18,6 +18,13 @@ "GuardrailsPrompt", "GuardrailsResponse", "Otel", + "SpendLimits", + "SpendLimitsRule", + "SpendLimitsRuleMetadata", + "SpendLimitsRuleMetadataMode", + "SpendLimitsRuleMetadataUnionMember1", + "SpendLimitsRuleModel", + "SpendLimitsRuleProvider", "Stripe", "StripeUsageEvent", ] @@ -128,6 +135,57 @@ class Otel(BaseModel): content_type: Optional[Literal["json", "protobuf"]] = None +class SpendLimitsRuleMetadataMode(BaseModel): + mode: Literal["partition"] + + +class SpendLimitsRuleMetadataUnionMember1(BaseModel): + mode: Literal["filter"] + + values: List[str] + + +SpendLimitsRuleMetadata: TypeAlias = Union[SpendLimitsRuleMetadataMode, SpendLimitsRuleMetadataUnionMember1] + + +class SpendLimitsRuleModel(BaseModel): + mode: Literal["filter"] + + values: List[str] + + +class SpendLimitsRuleProvider(BaseModel): + mode: Literal["filter"] + + values: List[str] + + +class SpendLimitsRule(BaseModel): + limit: float + + limit_type: Literal["cost"] = FieldInfo(alias="limitType") + + window: int + + id: Optional[str] = None + + enabled: Optional[bool] = None + + metadata: Optional[Dict[str, SpendLimitsRuleMetadata]] = None + + model: Optional[SpendLimitsRuleModel] = None + + provider: Optional[SpendLimitsRuleProvider] = None + + technique: Optional[Literal["fixed", "sliding"]] = None + + +class SpendLimits(BaseModel): + enabled: Optional[bool] = None + + rules: Optional[List[SpendLimitsRule]] = None + + class StripeUsageEvent(BaseModel): payload: str @@ -185,6 +243,8 @@ class AIGatewayUpdateResponse(BaseModel): retry_max_attempts: Optional[int] = None """Maximum number of retry attempts for failed requests (1-5)""" + spend_limits: Optional[SpendLimits] = None + store_id: Optional[str] = None stripe: Optional[Stripe] = None diff --git a/src/cloudflare/types/dns/usage/__init__.py b/src/cloudflare/types/dns/usage/__init__.py index f8ee8b14b1c..4e413a5b08f 100644 --- a/src/cloudflare/types/dns/usage/__init__.py +++ b/src/cloudflare/types/dns/usage/__init__.py @@ -1,3 +1,6 @@ # File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. from __future__ import annotations + +from .zone_get_response import ZoneGetResponse as ZoneGetResponse +from .account_get_response import AccountGetResponse as AccountGetResponse diff --git a/src/cloudflare/types/dns/usage/account_get_response.py b/src/cloudflare/types/dns/usage/account_get_response.py new file mode 100644 index 00000000000..86a020719ac --- /dev/null +++ b/src/cloudflare/types/dns/usage/account_get_response.py @@ -0,0 +1,30 @@ +# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. + +from typing import Optional + +from ...._models import BaseModel + +__all__ = ["AccountGetResponse"] + + +class AccountGetResponse(BaseModel): + record_quota: Optional[int] = None + """Maximum number of DNS records allowed across all public zones in the account. + + Null if using zone-level quota. + """ + + record_usage: int + """Current number of DNS records across all public zones in the account.""" + + internal_record_quota: Optional[int] = None + """Maximum number of DNS records allowed across all internal zones in the account. + + Only present if internal DNS is enabled. + """ + + internal_record_usage: Optional[int] = None + """Current number of DNS records across all internal zones in the account. + + Only present if internal DNS is enabled. + """ diff --git a/src/cloudflare/types/dns/usage/zone_get_response.py b/src/cloudflare/types/dns/usage/zone_get_response.py new file mode 100644 index 00000000000..3c939e08972 --- /dev/null +++ b/src/cloudflare/types/dns/usage/zone_get_response.py @@ -0,0 +1,18 @@ +# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. + +from typing import Optional + +from ...._models import BaseModel + +__all__ = ["ZoneGetResponse"] + + +class ZoneGetResponse(BaseModel): + record_quota: Optional[int] = None + """Maximum number of DNS records allowed for the zone. + + Null if using account-level quota. + """ + + record_usage: int + """Current number of DNS records in the zone.""" diff --git a/src/cloudflare/types/intel/sinkhole.py b/src/cloudflare/types/intel/sinkhole.py index 9895bde4bc0..8e404467050 100644 --- a/src/cloudflare/types/intel/sinkhole.py +++ b/src/cloudflare/types/intel/sinkhole.py @@ -9,7 +9,7 @@ class Sinkhole(BaseModel): - id: Optional[int] = None + id: Optional[str] = None """The unique identifier for the sinkhole.""" account_tag: Optional[str] = None diff --git a/src/cloudflare/types/logpush/job_create_params.py b/src/cloudflare/types/logpush/job_create_params.py index ca59411a9df..61d6089a4d6 100644 --- a/src/cloudflare/types/logpush/job_create_params.py +++ b/src/cloudflare/types/logpush/job_create_params.py @@ -54,6 +54,7 @@ class JobCreateParams(TypedDict, total=False): "sinkhole_http_logs", "spectrum_events", "ssh_logs", + "turnstile_events", "warp_config_changes", "warp_toggle_changes", "workers_trace_events", diff --git a/src/cloudflare/types/logpush/logpush_job.py b/src/cloudflare/types/logpush/logpush_job.py index e20ceeab1cb..fbe866558cc 100644 --- a/src/cloudflare/types/logpush/logpush_job.py +++ b/src/cloudflare/types/logpush/logpush_job.py @@ -44,6 +44,7 @@ class LogpushJob(BaseModel): "sinkhole_http_logs", "spectrum_events", "ssh_logs", + "turnstile_events", "warp_config_changes", "warp_toggle_changes", "workers_trace_events", diff --git a/src/cloudflare/types/realtime_kit/session_get_participant_data_from_peer_id_params.py b/src/cloudflare/types/realtime_kit/session_get_participant_data_from_peer_id_params.py index 95288d3835c..d36ef09e63c 100644 --- a/src/cloudflare/types/realtime_kit/session_get_participant_data_from_peer_id_params.py +++ b/src/cloudflare/types/realtime_kit/session_get_participant_data_from_peer_id_params.py @@ -15,10 +15,7 @@ class SessionGetParticipantDataFromPeerIDParams(TypedDict, total=False): """The app identifier tag.""" filters: Literal["device_info", "ip_information", "precall_network_information", "events", "quality_stats"] - """Comma separated list of filters to apply. - - Note that there must be no spaces between the filters. - """ + """Filter to apply to the peer report.""" include_peer_events: bool """if true, response includes all the peer events of participant.""" diff --git a/src/cloudflare/types/realtime_kit/session_get_participant_data_from_peer_id_response.py b/src/cloudflare/types/realtime_kit/session_get_participant_data_from_peer_id_response.py index 1ac3743888b..763cd63ba8b 100644 --- a/src/cloudflare/types/realtime_kit/session_get_participant_data_from_peer_id_response.py +++ b/src/cloudflare/types/realtime_kit/session_get_participant_data_from_peer_id_response.py @@ -6,10 +6,10 @@ from ..._models import BaseModel -__all__ = ["SessionGetParticipantDataFromPeerIDResponse", "Data", "DataPeerReport"] +__all__ = ["SessionGetParticipantDataFromPeerIDResponse", "Data", "DataParticipant", "DataParticipantPeerReport"] -class DataPeerReport(BaseModel): +class DataParticipantPeerReport(BaseModel): """Peer call statistics report.""" metadata: Optional[Dict[str, object]] = None @@ -29,9 +29,9 @@ def __getattr__(self, attr: str) -> object: ... __pydantic_extra__: Dict[str, object] -class Data(BaseModel): +class DataParticipant(BaseModel): id: Optional[str] = None - """Participant ID. This maps to the corresponding peerId.""" + """ID of the participant.""" created_at: Optional[str] = None """timestamp when this participant was created.""" @@ -53,10 +53,10 @@ class Data(BaseModel): peer_events: Optional[List[Dict[str, object]]] = None - peer_report: Optional[DataPeerReport] = None + peer_report: Optional[DataParticipantPeerReport] = None """Peer call statistics report.""" - preset_name: Optional[str] = None + role: Optional[str] = None """Name of the preset associated with the participant.""" session_id: Optional[str] = None @@ -68,6 +68,10 @@ class Data(BaseModel): """User id for this participant.""" +class Data(BaseModel): + participant: Optional[DataParticipant] = None + + class SessionGetParticipantDataFromPeerIDResponse(BaseModel): data: Optional[Data] = None diff --git a/src/cloudflare/types/resource_sharing/__init__.py b/src/cloudflare/types/resource_sharing/__init__.py index c38cd309a1e..7655008fc78 100644 --- a/src/cloudflare/types/resource_sharing/__init__.py +++ b/src/cloudflare/types/resource_sharing/__init__.py @@ -5,12 +5,16 @@ from .recipient_get_params import RecipientGetParams as RecipientGetParams from .resource_list_params import ResourceListParams as ResourceListParams from .recipient_list_params import RecipientListParams as RecipientListParams +from .resource_get_response import ResourceGetResponse as ResourceGetResponse from .recipient_get_response import RecipientGetResponse as RecipientGetResponse from .resource_create_params import ResourceCreateParams as ResourceCreateParams from .resource_list_response import ResourceListResponse as ResourceListResponse +from .resource_update_params import ResourceUpdateParams as ResourceUpdateParams from .recipient_create_params import RecipientCreateParams as RecipientCreateParams from .recipient_list_response import RecipientListResponse as RecipientListResponse from .resource_create_response import ResourceCreateResponse as ResourceCreateResponse +from .resource_delete_response import ResourceDeleteResponse as ResourceDeleteResponse +from .resource_update_response import ResourceUpdateResponse as ResourceUpdateResponse from .recipient_create_response import RecipientCreateResponse as RecipientCreateResponse from .recipient_delete_response import RecipientDeleteResponse as RecipientDeleteResponse from .resource_sharing_get_params import ResourceSharingGetParams as ResourceSharingGetParams diff --git a/src/cloudflare/types/resource_sharing/resource_delete_response.py b/src/cloudflare/types/resource_sharing/resource_delete_response.py new file mode 100644 index 00000000000..deff33152bc --- /dev/null +++ b/src/cloudflare/types/resource_sharing/resource_delete_response.py @@ -0,0 +1,44 @@ +# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. + +from datetime import datetime +from typing_extensions import Literal + +from ..._models import BaseModel + +__all__ = ["ResourceDeleteResponse"] + + +class ResourceDeleteResponse(BaseModel): + id: str + """Share Resource identifier.""" + + created: datetime + """When the share was created.""" + + meta: object + """Resource Metadata.""" + + modified: datetime + """When the share was modified.""" + + resource_account_id: str + """Account identifier.""" + + resource_id: str + """Share Resource identifier.""" + + resource_type: Literal[ + "custom-ruleset", + "gateway-policy", + "gateway-destination-ip", + "gateway-block-page-settings", + "gateway-extended-email-matching", + "idp-federation-grant", + ] + """Resource Type.""" + + resource_version: int + """Resource Version.""" + + status: Literal["active", "deleting", "deleted"] + """Resource Status.""" diff --git a/src/cloudflare/types/resource_sharing/resource_get_response.py b/src/cloudflare/types/resource_sharing/resource_get_response.py new file mode 100644 index 00000000000..a357bb5074f --- /dev/null +++ b/src/cloudflare/types/resource_sharing/resource_get_response.py @@ -0,0 +1,44 @@ +# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. + +from datetime import datetime +from typing_extensions import Literal + +from ..._models import BaseModel + +__all__ = ["ResourceGetResponse"] + + +class ResourceGetResponse(BaseModel): + id: str + """Share Resource identifier.""" + + created: datetime + """When the share was created.""" + + meta: object + """Resource Metadata.""" + + modified: datetime + """When the share was modified.""" + + resource_account_id: str + """Account identifier.""" + + resource_id: str + """Share Resource identifier.""" + + resource_type: Literal[ + "custom-ruleset", + "gateway-policy", + "gateway-destination-ip", + "gateway-block-page-settings", + "gateway-extended-email-matching", + "idp-federation-grant", + ] + """Resource Type.""" + + resource_version: int + """Resource Version.""" + + status: Literal["active", "deleting", "deleted"] + """Resource Status.""" diff --git a/src/cloudflare/types/resource_sharing/resource_update_params.py b/src/cloudflare/types/resource_sharing/resource_update_params.py new file mode 100644 index 00000000000..d69bbdc0eb0 --- /dev/null +++ b/src/cloudflare/types/resource_sharing/resource_update_params.py @@ -0,0 +1,18 @@ +# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. + +from __future__ import annotations + +from typing_extensions import Required, TypedDict + +__all__ = ["ResourceUpdateParams"] + + +class ResourceUpdateParams(TypedDict, total=False): + account_id: Required[str] + """Account identifier.""" + + share_id: Required[str] + """Share identifier tag.""" + + meta: Required[object] + """Resource Metadata.""" diff --git a/src/cloudflare/types/resource_sharing/resource_update_response.py b/src/cloudflare/types/resource_sharing/resource_update_response.py new file mode 100644 index 00000000000..f207220bf2d --- /dev/null +++ b/src/cloudflare/types/resource_sharing/resource_update_response.py @@ -0,0 +1,44 @@ +# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. + +from datetime import datetime +from typing_extensions import Literal + +from ..._models import BaseModel + +__all__ = ["ResourceUpdateResponse"] + + +class ResourceUpdateResponse(BaseModel): + id: str + """Share Resource identifier.""" + + created: datetime + """When the share was created.""" + + meta: object + """Resource Metadata.""" + + modified: datetime + """When the share was modified.""" + + resource_account_id: str + """Account identifier.""" + + resource_id: str + """Share Resource identifier.""" + + resource_type: Literal[ + "custom-ruleset", + "gateway-policy", + "gateway-destination-ip", + "gateway-block-page-settings", + "gateway-extended-email-matching", + "idp-federation-grant", + ] + """Resource Type.""" + + resource_version: int + """Resource Version.""" + + status: Literal["active", "deleting", "deleted"] + """Resource Status.""" diff --git a/src/cloudflare/types/workflows/__init__.py b/src/cloudflare/types/workflows/__init__.py index 385d8fff853..7bcec65237c 100644 --- a/src/cloudflare/types/workflows/__init__.py +++ b/src/cloudflare/types/workflows/__init__.py @@ -6,6 +6,7 @@ from .version_list_params import VersionListParams as VersionListParams from .instance_bulk_params import InstanceBulkParams as InstanceBulkParams from .instance_list_params import InstanceListParams as InstanceListParams +from .instance_step_params import InstanceStepParams as InstanceStepParams from .version_get_response import VersionGetResponse as VersionGetResponse from .workflow_list_params import WorkflowListParams as WorkflowListParams from .instance_get_response import InstanceGetResponse as InstanceGetResponse @@ -14,6 +15,8 @@ from .instance_bulk_response import InstanceBulkResponse as InstanceBulkResponse from .instance_create_params import InstanceCreateParams as InstanceCreateParams from .instance_list_response import InstanceListResponse as InstanceListResponse +from .instance_step_response import InstanceStepResponse as InstanceStepResponse +from .version_graph_response import VersionGraphResponse as VersionGraphResponse from .workflow_list_response import WorkflowListResponse as WorkflowListResponse from .workflow_update_params import WorkflowUpdateParams as WorkflowUpdateParams from .instance_create_response import InstanceCreateResponse as InstanceCreateResponse diff --git a/src/cloudflare/types/workflows/instance_bulk_response.py b/src/cloudflare/types/workflows/instance_bulk_response.py index d941e320187..18348034307 100644 --- a/src/cloudflare/types/workflows/instance_bulk_response.py +++ b/src/cloudflare/types/workflows/instance_bulk_response.py @@ -1,5 +1,6 @@ # File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. +from typing import Optional from typing_extensions import Literal from ..._models import BaseModel @@ -17,3 +18,5 @@ class InstanceBulkResponse(BaseModel): version_id: str workflow_id: str + + trigger_source: Optional[Literal["unknown", "api", "binding", "event", "cron"]] = None diff --git a/src/cloudflare/types/workflows/instance_create_response.py b/src/cloudflare/types/workflows/instance_create_response.py index 76df532ca4c..12496c29da1 100644 --- a/src/cloudflare/types/workflows/instance_create_response.py +++ b/src/cloudflare/types/workflows/instance_create_response.py @@ -1,5 +1,6 @@ # File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. +from typing import Optional from typing_extensions import Literal from ..._models import BaseModel @@ -17,3 +18,5 @@ class InstanceCreateResponse(BaseModel): version_id: str workflow_id: str + + trigger_source: Optional[Literal["unknown", "api", "binding", "event", "cron"]] = None diff --git a/src/cloudflare/types/workflows/instance_get_response.py b/src/cloudflare/types/workflows/instance_get_response.py index 90f743706f3..f9e0ddad80f 100644 --- a/src/cloudflare/types/workflows/instance_get_response.py +++ b/src/cloudflare/types/workflows/instance_get_response.py @@ -26,6 +26,7 @@ "StepUnionMember3", "StepUnionMember3Error", "Trigger", + "Schedule", ] @@ -162,6 +163,12 @@ class Trigger(BaseModel): source: Literal["unknown", "api", "binding", "event", "cron"] +class Schedule(BaseModel): + cron: str + + scheduled_time: float = FieldInfo(alias="scheduledTime") + + class InstanceGetResponse(BaseModel): end: Optional[datetime] = None @@ -190,3 +197,5 @@ class InstanceGetResponse(BaseModel): trigger: Trigger version_id: str = FieldInfo(alias="versionId") + + schedule: Optional[Schedule] = None diff --git a/src/cloudflare/types/workflows/instance_list_response.py b/src/cloudflare/types/workflows/instance_list_response.py index 7a266896551..ea6f15bb284 100644 --- a/src/cloudflare/types/workflows/instance_list_response.py +++ b/src/cloudflare/types/workflows/instance_list_response.py @@ -27,3 +27,5 @@ class InstanceListResponse(BaseModel): version_id: str workflow_id: str + + trigger_source: Optional[Literal["unknown", "api", "binding", "event", "cron"]] = None diff --git a/src/cloudflare/types/workflows/instance_step_params.py b/src/cloudflare/types/workflows/instance_step_params.py new file mode 100644 index 00000000000..e1eafb3acf5 --- /dev/null +++ b/src/cloudflare/types/workflows/instance_step_params.py @@ -0,0 +1,28 @@ +# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. + +from __future__ import annotations + +from typing_extensions import Literal, Required, TypedDict + +__all__ = ["InstanceStepParams"] + + +class InstanceStepParams(TypedDict, total=False): + account_id: Required[str] + + workflow_name: Required[str] + + name: Required[str] + """ + Exact step name from the instance logs response, including the generated counter + suffix. + """ + + type: Required[Literal["step", "waitForEvent"]] + """ + Step type to disambiguate step.do and waitForEvent entries that share the same + name. + """ + + attempt: int + """Specific attempt number to retrieve output or error for.""" diff --git a/src/cloudflare/types/workflows/instance_step_response.py b/src/cloudflare/types/workflows/instance_step_response.py new file mode 100644 index 00000000000..d91e7202d14 --- /dev/null +++ b/src/cloudflare/types/workflows/instance_step_response.py @@ -0,0 +1,33 @@ +# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. + +from typing import Optional +from typing_extensions import Literal + +from ..._models import BaseModel + +__all__ = ["InstanceStepResponse", "Error"] + + +class Error(BaseModel): + """Error details when status='errored'; null otherwise.""" + + message: str + + name: str + + +class InstanceStepResponse(BaseModel): + error: Optional[Error] = None + """Error details when status='errored'; null otherwise.""" + + status: Literal[ + "queued", "running", "paused", "errored", "terminated", "complete", "waitingForPause", "waiting", "rollingBack" + ] + + output: Optional[object] = None + """Full step output or waitForEvent payload without truncation. + + Sensitive outputs are returned as '[REDACTED]'. Populated when + status='complete'. May be a ReadableStream when the step returned one from + step.do; stream outputs are served as application/octet-stream rather than JSON. + """ diff --git a/src/cloudflare/types/workflows/version_graph_response.py b/src/cloudflare/types/workflows/version_graph_response.py new file mode 100644 index 00000000000..71070ac4789 --- /dev/null +++ b/src/cloudflare/types/workflows/version_graph_response.py @@ -0,0 +1,377 @@ +# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. + +from typing import Dict, List, Union, Optional +from datetime import datetime +from typing_extensions import Literal, TypeAlias + +from ..._models import BaseModel + +__all__ = [ + "VersionGraphResponse", + "Graph", + "GraphWorkflow", + "GraphWorkflowFunctions", + "GraphWorkflowNode", + "GraphWorkflowNodeUnionMember0", + "GraphWorkflowNodeUnionMember1", + "GraphWorkflowNodeUnionMember1Config", + "GraphWorkflowNodeUnionMember1ConfigRetries", + "GraphWorkflowNodeUnionMember2", + "GraphWorkflowNodeUnionMember2Options", + "GraphWorkflowNodeUnionMember2Payload", + "GraphWorkflowNodeUnionMember2PayloadType", + "GraphWorkflowNodeUnionMember2PayloadUnionMember1", + "GraphWorkflowNodeUnionMember3", + "GraphWorkflowNodeUnionMember4", + "GraphWorkflowNodeUnionMember5", + "GraphWorkflowNodeUnionMember6", + "GraphWorkflowNodeUnionMember6CatchBlock", + "GraphWorkflowNodeUnionMember6FinallyBlock", + "GraphWorkflowNodeUnionMember6TryBlock", + "GraphWorkflowNodeUnionMember7", + "GraphWorkflowNodeUnionMember8", + "GraphWorkflowNodeUnionMember8Branch", + "GraphWorkflowNodeUnionMember9", + "GraphWorkflowNodeUnionMember9Branch", + "GraphWorkflowNodeUnionMember10", + "GraphWorkflowNodeUnionMember10Functions", + "GraphWorkflowNodeUnionMember10Payload", + "GraphWorkflowNodeUnionMember10PayloadType", + "GraphWorkflowNodeUnionMember10PayloadUnionMember1", + "GraphWorkflowNodeUnionMember11", + "GraphWorkflowNodeUnionMember12", + "GraphWorkflowNodeUnionMember13", + "GraphWorkflowPayload", + "GraphWorkflowPayloadType", + "GraphWorkflowPayloadUnionMember1", +] + + +class GraphWorkflowFunctions(BaseModel): + name: str + + nodes: List[object] + """Child nodes (recursive).""" + + type: Literal["function_def"] + + +class GraphWorkflowNodeUnionMember0(BaseModel): + duration: Union[float, str] + """Duration as milliseconds (number) or human-readable string.""" + + name: str + + type: Literal["step_sleep"] + + resolves: Optional[float] = None + + starts: Optional[float] = None + + +class GraphWorkflowNodeUnionMember1ConfigRetries(BaseModel): + """Retry policy for a step.""" + + backoff: Literal["constant", "linear", "exponential"] + """Backoff strategy for step retries.""" + + delay: Union[float, str] + """Duration as milliseconds (number) or human-readable string.""" + + limit: float + + +class GraphWorkflowNodeUnionMember1Config(BaseModel): + """Configuration for a step (retries and timeout).""" + + retries: GraphWorkflowNodeUnionMember1ConfigRetries + """Retry policy for a step.""" + + timeout: Union[float, str] + """Duration as milliseconds (number) or human-readable string.""" + + +class GraphWorkflowNodeUnionMember1(BaseModel): + config: GraphWorkflowNodeUnionMember1Config + """Configuration for a step (retries and timeout).""" + + name: str + + nodes: List[object] + """Child nodes (recursive).""" + + type: Literal["step_do"] + + resolves: Optional[float] = None + + starts: Optional[float] = None + + +class GraphWorkflowNodeUnionMember2Options(BaseModel): + """Options for a waitForEvent step.""" + + event_type: str + + timeout: Union[float, str] + """Duration as milliseconds (number) or human-readable string.""" + + +class GraphWorkflowNodeUnionMember2PayloadType(BaseModel): + type: Literal["unknown"] + + +class GraphWorkflowNodeUnionMember2PayloadUnionMember1(BaseModel): + fields: Dict[str, object] + """Nested JsonShape fields (recursive structure).""" + + type: Literal["object"] + + +GraphWorkflowNodeUnionMember2Payload: TypeAlias = Union[ + GraphWorkflowNodeUnionMember2PayloadType, GraphWorkflowNodeUnionMember2PayloadUnionMember1 +] + + +class GraphWorkflowNodeUnionMember2(BaseModel): + name: str + + options: Optional[GraphWorkflowNodeUnionMember2Options] = None + """Options for a waitForEvent step.""" + + type: Literal["step_wait_for_event"] + + payload: Optional[GraphWorkflowNodeUnionMember2Payload] = None + """Shape descriptor for JSON payloads.""" + + resolves: Optional[float] = None + + starts: Optional[float] = None + + +class GraphWorkflowNodeUnionMember3(BaseModel): + name: str + + timestamp: str + + type: Literal["step_sleep_until"] + + resolves: Optional[float] = None + + starts: Optional[float] = None + + +class GraphWorkflowNodeUnionMember4(BaseModel): + nodes: List[object] + """Child nodes (recursive).""" + + type: Literal["loop"] + + +class GraphWorkflowNodeUnionMember5(BaseModel): + kind: Literal["all", "any", "all_settled", "race"] + """Parallel execution strategy.""" + + nodes: List[object] + """Child nodes (recursive).""" + + type: Literal["parallel"] + + +class GraphWorkflowNodeUnionMember6CatchBlock(BaseModel): + nodes: List[object] + """Child nodes (recursive).""" + + type: Literal["block"] + + +class GraphWorkflowNodeUnionMember6FinallyBlock(BaseModel): + nodes: List[object] + """Child nodes (recursive).""" + + type: Literal["block"] + + +class GraphWorkflowNodeUnionMember6TryBlock(BaseModel): + nodes: List[object] + """Child nodes (recursive).""" + + type: Literal["block"] + + +class GraphWorkflowNodeUnionMember6(BaseModel): + catch_block: Optional[GraphWorkflowNodeUnionMember6CatchBlock] = None + + finally_block: Optional[GraphWorkflowNodeUnionMember6FinallyBlock] = None + + try_block: Optional[GraphWorkflowNodeUnionMember6TryBlock] = None + + type: Literal["try"] + + +class GraphWorkflowNodeUnionMember7(BaseModel): + nodes: List[object] + """Child nodes (recursive).""" + + type: Literal["block"] + + +class GraphWorkflowNodeUnionMember8Branch(BaseModel): + condition: Optional[str] = None + + nodes: List[object] + """Child nodes (recursive).""" + + +class GraphWorkflowNodeUnionMember8(BaseModel): + branches: List[GraphWorkflowNodeUnionMember8Branch] + + type: Literal["if"] + + +class GraphWorkflowNodeUnionMember9Branch(BaseModel): + condition: Optional[str] = None + + nodes: List[object] + """Child nodes (recursive).""" + + +class GraphWorkflowNodeUnionMember9(BaseModel): + branches: List[GraphWorkflowNodeUnionMember9Branch] + + discriminant: str + + type: Literal["switch"] + + +class GraphWorkflowNodeUnionMember10Functions(BaseModel): + name: str + + nodes: List[object] + """Child nodes (recursive).""" + + type: Literal["function_def"] + + +class GraphWorkflowNodeUnionMember10PayloadType(BaseModel): + type: Literal["unknown"] + + +class GraphWorkflowNodeUnionMember10PayloadUnionMember1(BaseModel): + fields: Dict[str, object] + """Nested JsonShape fields (recursive structure).""" + + type: Literal["object"] + + +GraphWorkflowNodeUnionMember10Payload: TypeAlias = Union[ + GraphWorkflowNodeUnionMember10PayloadType, GraphWorkflowNodeUnionMember10PayloadUnionMember1 +] + + +class GraphWorkflowNodeUnionMember10(BaseModel): + class_name: str + + functions: Dict[str, GraphWorkflowNodeUnionMember10Functions] + + nodes: List[object] + """Child nodes (recursive).""" + + type: Literal["start"] + + payload: Optional[GraphWorkflowNodeUnionMember10Payload] = None + """Shape descriptor for JSON payloads.""" + + +class GraphWorkflowNodeUnionMember11(BaseModel): + name: str + + type: Literal["function_call"] + + resolves: Optional[float] = None + + starts: Optional[float] = None + + +class GraphWorkflowNodeUnionMember12(BaseModel): + name: str + + nodes: List[object] + """Child nodes (recursive).""" + + type: Literal["function_def"] + + +class GraphWorkflowNodeUnionMember13(BaseModel): + kind: Literal["break", "return"] + """Break or return from a loop.""" + + type: Literal["break"] + + +GraphWorkflowNode: TypeAlias = Union[ + GraphWorkflowNodeUnionMember0, + GraphWorkflowNodeUnionMember1, + GraphWorkflowNodeUnionMember2, + GraphWorkflowNodeUnionMember3, + GraphWorkflowNodeUnionMember4, + GraphWorkflowNodeUnionMember5, + GraphWorkflowNodeUnionMember6, + GraphWorkflowNodeUnionMember7, + GraphWorkflowNodeUnionMember8, + GraphWorkflowNodeUnionMember9, + GraphWorkflowNodeUnionMember10, + GraphWorkflowNodeUnionMember11, + GraphWorkflowNodeUnionMember12, + GraphWorkflowNodeUnionMember13, +] + + +class GraphWorkflowPayloadType(BaseModel): + type: Literal["unknown"] + + +class GraphWorkflowPayloadUnionMember1(BaseModel): + fields: Dict[str, object] + """Nested JsonShape fields (recursive structure).""" + + type: Literal["object"] + + +GraphWorkflowPayload: TypeAlias = Union[GraphWorkflowPayloadType, GraphWorkflowPayloadUnionMember1] + + +class GraphWorkflow(BaseModel): + """A parsed workflow entrypoint with its step graph.""" + + class_name: str + + functions: Dict[str, GraphWorkflowFunctions] + + nodes: List[GraphWorkflowNode] + + payload: Optional[GraphWorkflowPayload] = None + """Shape descriptor for JSON payloads.""" + + +class Graph(BaseModel): + """Versioned workflow graph payload.""" + + version: float + + workflow: GraphWorkflow + """A parsed workflow entrypoint with its step graph.""" + + +class VersionGraphResponse(BaseModel): + id: str + + class_name: str + + created_on: datetime + + graph: Optional[Graph] = None + """Versioned workflow graph payload.""" + + modified_on: datetime + + workflow_id: str diff --git a/src/cloudflare/types/workflows/workflow_get_response.py b/src/cloudflare/types/workflows/workflow_get_response.py index 7698baaaa17..0553291d9f0 100644 --- a/src/cloudflare/types/workflows/workflow_get_response.py +++ b/src/cloudflare/types/workflows/workflow_get_response.py @@ -1,13 +1,13 @@ # File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. -from typing import Optional +from typing import List, Optional from datetime import datetime from pydantic import Field as FieldInfo from ..._models import BaseModel -__all__ = ["WorkflowGetResponse", "Instances"] +__all__ = ["WorkflowGetResponse", "Instances", "Schedule"] class Instances(BaseModel): @@ -30,6 +30,12 @@ class Instances(BaseModel): waiting_for_pause: Optional[float] = FieldInfo(alias="waitingForPause", default=None) +class Schedule(BaseModel): + cron: str + + next_instance: str + + class WorkflowGetResponse(BaseModel): id: str @@ -46,3 +52,5 @@ class WorkflowGetResponse(BaseModel): script_name: str triggered_on: Optional[datetime] = None + + schedules: Optional[List[Schedule]] = None diff --git a/src/cloudflare/types/workflows/workflow_list_response.py b/src/cloudflare/types/workflows/workflow_list_response.py index bde9d7dd38c..a05251d55ce 100644 --- a/src/cloudflare/types/workflows/workflow_list_response.py +++ b/src/cloudflare/types/workflows/workflow_list_response.py @@ -1,13 +1,13 @@ # File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. -from typing import Optional +from typing import List, Optional from datetime import datetime from pydantic import Field as FieldInfo from ..._models import BaseModel -__all__ = ["WorkflowListResponse", "Instances"] +__all__ = ["WorkflowListResponse", "Instances", "Schedule"] class Instances(BaseModel): @@ -30,6 +30,12 @@ class Instances(BaseModel): waiting_for_pause: Optional[float] = FieldInfo(alias="waitingForPause", default=None) +class Schedule(BaseModel): + cron: str + + next_instance: str + + class WorkflowListResponse(BaseModel): id: str @@ -46,3 +52,5 @@ class WorkflowListResponse(BaseModel): script_name: str triggered_on: Optional[datetime] = None + + schedules: Optional[List[Schedule]] = None diff --git a/src/cloudflare/types/workflows/workflow_update_params.py b/src/cloudflare/types/workflows/workflow_update_params.py index 2ff781a484d..045b90afdf6 100644 --- a/src/cloudflare/types/workflows/workflow_update_params.py +++ b/src/cloudflare/types/workflows/workflow_update_params.py @@ -2,9 +2,10 @@ from __future__ import annotations +from typing import Iterable from typing_extensions import Required, TypedDict -__all__ = ["WorkflowUpdateParams", "Limits"] +__all__ = ["WorkflowUpdateParams", "Limits", "Schedule"] class WorkflowUpdateParams(TypedDict, total=False): @@ -16,6 +17,12 @@ class WorkflowUpdateParams(TypedDict, total=False): limits: Limits + schedules: Iterable[Schedule] + class Limits(TypedDict, total=False): steps: int + + +class Schedule(TypedDict, total=False): + cron: Required[str] diff --git a/src/cloudflare/types/zero_trust/access/__init__.py b/src/cloudflare/types/zero_trust/access/__init__.py index cb7d98a5425..f1db601942e 100644 --- a/src/cloudflare/types/zero_trust/access/__init__.py +++ b/src/cloudflare/types/zero_trust/access/__init__.py @@ -47,6 +47,7 @@ from .tag_delete_response import TagDeleteResponse as TagDeleteResponse from .approval_group_param import ApprovalGroupParam as ApprovalGroupParam from .associated_hostnames import AssociatedHostnames as AssociatedHostnames +from .idp_federation_grant import IdPFederationGrant as IdPFederationGrant from .policy_create_params import PolicyCreateParams as PolicyCreateParams from .policy_list_response import PolicyListResponse as PolicyListResponse from .policy_update_params import PolicyUpdateParams as PolicyUpdateParams @@ -94,6 +95,9 @@ from .saml_certificate_list_response import SAMLCertificateListResponse as SAMLCertificateListResponse from .saml_certificate_rotate_response import SAMLCertificateRotateResponse as SAMLCertificateRotateResponse from .scim_config_authentication_oauth2 import SCIMConfigAuthenticationOauth2 as SCIMConfigAuthenticationOauth2 +from .idp_federation_grant_create_params import IdPFederationGrantCreateParams as IdPFederationGrantCreateParams +from .idp_federation_grant_list_response import IdPFederationGrantListResponse as IdPFederationGrantListResponse +from .idp_federation_grant_delete_response import IdPFederationGrantDeleteResponse as IdPFederationGrantDeleteResponse from .scim_config_authentication_http_basic import ( SCIMConfigAuthenticationHTTPBasic as SCIMConfigAuthenticationHTTPBasic, ) diff --git a/src/cloudflare/types/zero_trust/access/ai_controls/mcp/portal_create_response.py b/src/cloudflare/types/zero_trust/access/ai_controls/mcp/portal_create_response.py index 7dc526be769..61c6e6f7223 100644 --- a/src/cloudflare/types/zero_trust/access/ai_controls/mcp/portal_create_response.py +++ b/src/cloudflare/types/zero_trust/access/ai_controls/mcp/portal_create_response.py @@ -84,9 +84,9 @@ class Server(BaseModel): """ When true, the gateway worker uses the shared Cloudflare-owned OAuth callback endpoint as the redirect_uri for upstream on-behalf OAuth, instead of the - customer portal hostname. Operators manage this internal rollout flag through - admin endpoints. Effective behavior is gated by the gateway worker's per-env - rollout mode KV key. + customer portal hostname. New public server creates default to true; existing + servers default to false from migration until explicitly updated. Effective + behavior is gated by the gateway worker's per-env rollout mode KV key. """ last_successful_sync: Optional[datetime] = None diff --git a/src/cloudflare/types/zero_trust/access/ai_controls/mcp/portal_list_response.py b/src/cloudflare/types/zero_trust/access/ai_controls/mcp/portal_list_response.py index 05017bfb676..3008b57f175 100644 --- a/src/cloudflare/types/zero_trust/access/ai_controls/mcp/portal_list_response.py +++ b/src/cloudflare/types/zero_trust/access/ai_controls/mcp/portal_list_response.py @@ -84,9 +84,9 @@ class Server(BaseModel): """ When true, the gateway worker uses the shared Cloudflare-owned OAuth callback endpoint as the redirect_uri for upstream on-behalf OAuth, instead of the - customer portal hostname. Operators manage this internal rollout flag through - admin endpoints. Effective behavior is gated by the gateway worker's per-env - rollout mode KV key. + customer portal hostname. New public server creates default to true; existing + servers default to false from migration until explicitly updated. Effective + behavior is gated by the gateway worker's per-env rollout mode KV key. """ last_successful_sync: Optional[datetime] = None diff --git a/src/cloudflare/types/zero_trust/access/ai_controls/mcp/portal_read_response.py b/src/cloudflare/types/zero_trust/access/ai_controls/mcp/portal_read_response.py index 1b65b772635..07ed7ca9071 100644 --- a/src/cloudflare/types/zero_trust/access/ai_controls/mcp/portal_read_response.py +++ b/src/cloudflare/types/zero_trust/access/ai_controls/mcp/portal_read_response.py @@ -84,9 +84,9 @@ class Server(BaseModel): """ When true, the gateway worker uses the shared Cloudflare-owned OAuth callback endpoint as the redirect_uri for upstream on-behalf OAuth, instead of the - customer portal hostname. Operators manage this internal rollout flag through - admin endpoints. Effective behavior is gated by the gateway worker's per-env - rollout mode KV key. + customer portal hostname. New public server creates default to true; existing + servers default to false from migration until explicitly updated. Effective + behavior is gated by the gateway worker's per-env rollout mode KV key. """ last_successful_sync: Optional[datetime] = None diff --git a/src/cloudflare/types/zero_trust/access/ai_controls/mcp/portal_update_response.py b/src/cloudflare/types/zero_trust/access/ai_controls/mcp/portal_update_response.py index 42790e98208..a29b140f119 100644 --- a/src/cloudflare/types/zero_trust/access/ai_controls/mcp/portal_update_response.py +++ b/src/cloudflare/types/zero_trust/access/ai_controls/mcp/portal_update_response.py @@ -84,9 +84,9 @@ class Server(BaseModel): """ When true, the gateway worker uses the shared Cloudflare-owned OAuth callback endpoint as the redirect_uri for upstream on-behalf OAuth, instead of the - customer portal hostname. Operators manage this internal rollout flag through - admin endpoints. Effective behavior is gated by the gateway worker's per-env - rollout mode KV key. + customer portal hostname. New public server creates default to true; existing + servers default to false from migration until explicitly updated. Effective + behavior is gated by the gateway worker's per-env rollout mode KV key. """ last_successful_sync: Optional[datetime] = None diff --git a/src/cloudflare/types/zero_trust/access/ai_controls/mcp/server_create_params.py b/src/cloudflare/types/zero_trust/access/ai_controls/mcp/server_create_params.py index 57c26163547..598d4762a3f 100644 --- a/src/cloudflare/types/zero_trust/access/ai_controls/mcp/server_create_params.py +++ b/src/cloudflare/types/zero_trust/access/ai_controls/mcp/server_create_params.py @@ -24,6 +24,15 @@ class ServerCreateParams(TypedDict, total=False): description: Optional[str] + is_shared_oauth_callback_enabled: bool + """ + When true, the gateway worker uses the shared Cloudflare-owned OAuth callback + endpoint as the redirect_uri for upstream on-behalf OAuth, instead of the + customer portal hostname. New public server creates default to true; existing + servers default to false from migration until explicitly updated. Effective + behavior is gated by the gateway worker's per-env rollout mode KV key. + """ + updated_prompts: Iterable[UpdatedPrompt] updated_tools: Iterable[UpdatedTool] diff --git a/src/cloudflare/types/zero_trust/access/ai_controls/mcp/server_create_response.py b/src/cloudflare/types/zero_trust/access/ai_controls/mcp/server_create_response.py index df613df40b6..815b4463833 100644 --- a/src/cloudflare/types/zero_trust/access/ai_controls/mcp/server_create_response.py +++ b/src/cloudflare/types/zero_trust/access/ai_controls/mcp/server_create_response.py @@ -74,9 +74,9 @@ class ServerCreateResponse(BaseModel): """ When true, the gateway worker uses the shared Cloudflare-owned OAuth callback endpoint as the redirect_uri for upstream on-behalf OAuth, instead of the - customer portal hostname. Operators manage this internal rollout flag through - admin endpoints. Effective behavior is gated by the gateway worker's per-env - rollout mode KV key. + customer portal hostname. New public server creates default to true; existing + servers default to false from migration until explicitly updated. Effective + behavior is gated by the gateway worker's per-env rollout mode KV key. """ last_successful_sync: Optional[datetime] = None diff --git a/src/cloudflare/types/zero_trust/access/ai_controls/mcp/server_delete_response.py b/src/cloudflare/types/zero_trust/access/ai_controls/mcp/server_delete_response.py index e26d32a3331..458ed1089ac 100644 --- a/src/cloudflare/types/zero_trust/access/ai_controls/mcp/server_delete_response.py +++ b/src/cloudflare/types/zero_trust/access/ai_controls/mcp/server_delete_response.py @@ -74,9 +74,9 @@ class ServerDeleteResponse(BaseModel): """ When true, the gateway worker uses the shared Cloudflare-owned OAuth callback endpoint as the redirect_uri for upstream on-behalf OAuth, instead of the - customer portal hostname. Operators manage this internal rollout flag through - admin endpoints. Effective behavior is gated by the gateway worker's per-env - rollout mode KV key. + customer portal hostname. New public server creates default to true; existing + servers default to false from migration until explicitly updated. Effective + behavior is gated by the gateway worker's per-env rollout mode KV key. """ last_successful_sync: Optional[datetime] = None diff --git a/src/cloudflare/types/zero_trust/access/ai_controls/mcp/server_list_response.py b/src/cloudflare/types/zero_trust/access/ai_controls/mcp/server_list_response.py index fe5dffa46b6..7e12dd45fb8 100644 --- a/src/cloudflare/types/zero_trust/access/ai_controls/mcp/server_list_response.py +++ b/src/cloudflare/types/zero_trust/access/ai_controls/mcp/server_list_response.py @@ -74,9 +74,9 @@ class ServerListResponse(BaseModel): """ When true, the gateway worker uses the shared Cloudflare-owned OAuth callback endpoint as the redirect_uri for upstream on-behalf OAuth, instead of the - customer portal hostname. Operators manage this internal rollout flag through - admin endpoints. Effective behavior is gated by the gateway worker's per-env - rollout mode KV key. + customer portal hostname. New public server creates default to true; existing + servers default to false from migration until explicitly updated. Effective + behavior is gated by the gateway worker's per-env rollout mode KV key. """ last_successful_sync: Optional[datetime] = None diff --git a/src/cloudflare/types/zero_trust/access/ai_controls/mcp/server_read_response.py b/src/cloudflare/types/zero_trust/access/ai_controls/mcp/server_read_response.py index af85d6b8528..259bcd23a18 100644 --- a/src/cloudflare/types/zero_trust/access/ai_controls/mcp/server_read_response.py +++ b/src/cloudflare/types/zero_trust/access/ai_controls/mcp/server_read_response.py @@ -74,9 +74,9 @@ class ServerReadResponse(BaseModel): """ When true, the gateway worker uses the shared Cloudflare-owned OAuth callback endpoint as the redirect_uri for upstream on-behalf OAuth, instead of the - customer portal hostname. Operators manage this internal rollout flag through - admin endpoints. Effective behavior is gated by the gateway worker's per-env - rollout mode KV key. + customer portal hostname. New public server creates default to true; existing + servers default to false from migration until explicitly updated. Effective + behavior is gated by the gateway worker's per-env rollout mode KV key. """ last_successful_sync: Optional[datetime] = None diff --git a/src/cloudflare/types/zero_trust/access/ai_controls/mcp/server_update_params.py b/src/cloudflare/types/zero_trust/access/ai_controls/mcp/server_update_params.py index 38cf578f571..394c9e5a3f4 100644 --- a/src/cloudflare/types/zero_trust/access/ai_controls/mcp/server_update_params.py +++ b/src/cloudflare/types/zero_trust/access/ai_controls/mcp/server_update_params.py @@ -15,6 +15,15 @@ class ServerUpdateParams(TypedDict, total=False): description: Optional[str] + is_shared_oauth_callback_enabled: bool + """ + When true, the gateway worker uses the shared Cloudflare-owned OAuth callback + endpoint as the redirect_uri for upstream on-behalf OAuth, instead of the + customer portal hostname. New public server creates default to true; existing + servers default to false from migration until explicitly updated. Effective + behavior is gated by the gateway worker's per-env rollout mode KV key. + """ + name: str updated_prompts: Iterable[UpdatedPrompt] diff --git a/src/cloudflare/types/zero_trust/access/ai_controls/mcp/server_update_response.py b/src/cloudflare/types/zero_trust/access/ai_controls/mcp/server_update_response.py index 19cf816346a..af37f6b9644 100644 --- a/src/cloudflare/types/zero_trust/access/ai_controls/mcp/server_update_response.py +++ b/src/cloudflare/types/zero_trust/access/ai_controls/mcp/server_update_response.py @@ -74,9 +74,9 @@ class ServerUpdateResponse(BaseModel): """ When true, the gateway worker uses the shared Cloudflare-owned OAuth callback endpoint as the redirect_uri for upstream on-behalf OAuth, instead of the - customer portal hostname. Operators manage this internal rollout flag through - admin endpoints. Effective behavior is gated by the gateway worker's per-env - rollout mode KV key. + customer portal hostname. New public server creates default to true; existing + servers default to false from migration until explicitly updated. Effective + behavior is gated by the gateway worker's per-env rollout mode KV key. """ last_successful_sync: Optional[datetime] = None diff --git a/src/cloudflare/types/zero_trust/access/idp_federation_grant.py b/src/cloudflare/types/zero_trust/access/idp_federation_grant.py new file mode 100644 index 00000000000..c9bd2c2bda6 --- /dev/null +++ b/src/cloudflare/types/zero_trust/access/idp_federation_grant.py @@ -0,0 +1,18 @@ +# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. + +from datetime import datetime + +from ...._models import BaseModel + +__all__ = ["IdPFederationGrant"] + + +class IdPFederationGrant(BaseModel): + id: str + """UID of the IdP federation grant.""" + + created_at: datetime + """When the grant was created.""" + + idp_id: str + """UID of the identity provider being federated.""" diff --git a/src/cloudflare/types/zero_trust/access/idp_federation_grant_create_params.py b/src/cloudflare/types/zero_trust/access/idp_federation_grant_create_params.py new file mode 100644 index 00000000000..8c305cc572b --- /dev/null +++ b/src/cloudflare/types/zero_trust/access/idp_federation_grant_create_params.py @@ -0,0 +1,19 @@ +# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. + +from __future__ import annotations + +from typing_extensions import Required, TypedDict + +__all__ = ["IdPFederationGrantCreateParams"] + + +class IdPFederationGrantCreateParams(TypedDict, total=False): + account_id: Required[str] + """Identifier.""" + + idp_id: Required[str] + """UID of the identity provider to federate. + + Must be an existing identity provider in this account. One-time pin and + Cloudflare-managed identity providers cannot be federated. + """ diff --git a/src/cloudflare/types/zero_trust/access/idp_federation_grant_delete_response.py b/src/cloudflare/types/zero_trust/access/idp_federation_grant_delete_response.py new file mode 100644 index 00000000000..768c2517ce1 --- /dev/null +++ b/src/cloudflare/types/zero_trust/access/idp_federation_grant_delete_response.py @@ -0,0 +1,12 @@ +# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. + +from typing import Optional + +from ...._models import BaseModel + +__all__ = ["IdPFederationGrantDeleteResponse"] + + +class IdPFederationGrantDeleteResponse(BaseModel): + id: Optional[str] = None + """UID of the deleted IdP federation grant.""" diff --git a/src/cloudflare/types/zero_trust/access/idp_federation_grant_list_response.py b/src/cloudflare/types/zero_trust/access/idp_federation_grant_list_response.py new file mode 100644 index 00000000000..dfd7e168333 --- /dev/null +++ b/src/cloudflare/types/zero_trust/access/idp_federation_grant_list_response.py @@ -0,0 +1,10 @@ +# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. + +from typing import List +from typing_extensions import TypeAlias + +from .idp_federation_grant import IdPFederationGrant + +__all__ = ["IdPFederationGrantListResponse"] + +IdPFederationGrantListResponse: TypeAlias = List[IdPFederationGrant] diff --git a/src/cloudflare/types/zero_trust/dex/devices/__init__.py b/src/cloudflare/types/zero_trust/dex/devices/__init__.py new file mode 100644 index 00000000000..a923e772912 --- /dev/null +++ b/src/cloudflare/types/zero_trust/dex/devices/__init__.py @@ -0,0 +1,6 @@ +# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. + +from __future__ import annotations + +from .isps import ISPs as ISPs +from .isp_list_params import ISPListParams as ISPListParams diff --git a/src/cloudflare/types/zero_trust/dex/devices/isp_list_params.py b/src/cloudflare/types/zero_trust/dex/devices/isp_list_params.py new file mode 100644 index 00000000000..127afcc2b87 --- /dev/null +++ b/src/cloudflare/types/zero_trust/dex/devices/isp_list_params.py @@ -0,0 +1,36 @@ +# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. + +from __future__ import annotations + +from typing import Union +from datetime import datetime +from typing_extensions import Literal, Required, Annotated, TypedDict + +from ....._utils import PropertyInfo + +__all__ = ["ISPListParams"] + + +class ISPListParams(TypedDict, total=False): + account_id: Required[str] + + per_page: Required[int] + """Number of items per page""" + + cursor: str + """Cursor for cursor-based pagination. Mutually exclusive with page.""" + + from_: Annotated[Union[str, datetime], PropertyInfo(alias="from", format="iso8601")] + """Start time for the query in ISO 8601 format""" + + page: int + """Page number of paginated results. Mutually exclusive with cursor.""" + + sort_by: Literal["time_start"] + """The field to sort results by""" + + sort_order: Literal["ASC", "DESC"] + """The order to sort results""" + + to: Annotated[Union[str, datetime], PropertyInfo(format="iso8601")] + """End time for the query in ISO 8601 format""" diff --git a/src/cloudflare/types/zero_trust/dex/devices/isps.py b/src/cloudflare/types/zero_trust/dex/devices/isps.py new file mode 100644 index 00000000000..86840403985 --- /dev/null +++ b/src/cloudflare/types/zero_trust/dex/devices/isps.py @@ -0,0 +1,86 @@ +# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. + +from typing import List, Optional +from datetime import datetime + +from ....._models import BaseModel + +__all__ = ["ISPs", "ISP", "ISPIP", "ISPIPLocation"] + + +class ISPIPLocation(BaseModel): + """Geographic location information. + + All fields are returned as the literal string `"REDACTED"` for callers that do not have the PII permission. + """ + + city: Optional[str] = None + """City name. Returned as `"REDACTED"` without PII permission.""" + + country_iso: Optional[str] = None + """Country ISO code. Returned as `"REDACTED"` without PII permission.""" + + state_iso: Optional[str] = None + """State/province ISO code. Returned as `"REDACTED"` without PII permission.""" + + zip: Optional[str] = None + """ZIP/postal code. Returned as `"REDACTED"` without PII permission.""" + + +class ISPIP(BaseModel): + """IP address information for the ISP hop. + + Fields marked as PII-gated (`name`, `address`, `netmask`, and all `location` sub-fields) will be returned as the literal string `"REDACTED"` for callers that do not have the PII permission. `asn`, `aso`, and `version` are always returned regardless of PII access. + """ + + address: Optional[str] = None + """IP address. Returned as `"REDACTED"` without PII permission.""" + + asn: Optional[int] = None + """Autonomous System Number""" + + aso: Optional[str] = None + """Autonomous System Organization name""" + + location: Optional[ISPIPLocation] = None + """Geographic location information. + + All fields are returned as the literal string `"REDACTED"` for callers that do + not have the PII permission. + """ + + name: Optional[str] = None + """Named IP address (reverse DNS hostname when available). + + Returned as `"REDACTED"` without PII permission. + """ + + netmask: Optional[str] = None + """Network mask. Returned as `"REDACTED"` without PII permission.""" + + version: Optional[int] = None + """IP version (`1` for IPv4, `2` for IPv6, `0` if unknown)""" + + +class ISP(BaseModel): + test_id: str + """The test that generated this result""" + + test_result_id: str + """The specific test result""" + + time_start: datetime + """Timestamp of when the ISP was observed""" + + ip: Optional[ISPIP] = None + """IP address information for the ISP hop. + + Fields marked as PII-gated (`name`, `address`, `netmask`, and all `location` + sub-fields) will be returned as the literal string `"REDACTED"` for callers that + do not have the PII permission. `asn`, `aso`, and `version` are always returned + regardless of PII access. + """ + + +class ISPs(BaseModel): + isps: List[ISP] diff --git a/tests/api_resources/abuse_reports/test_mitigations.py b/tests/api_resources/abuse_reports/test_mitigations.py index 7975ce3809e..8fff01ce149 100644 --- a/tests/api_resources/abuse_reports/test_mitigations.py +++ b/tests/api_resources/abuse_reports/test_mitigations.py @@ -43,7 +43,7 @@ def test_method_list_with_all_params(self, client: Cloudflare) -> None: per_page=0, sort="type,asc", status="pending", - type="legal_block", + type="account_suspend", ) assert_matches_type(SyncV4PagePagination[Optional[MitigationListResponse]], mitigation, path=["response"]) @@ -200,7 +200,7 @@ async def test_method_list_with_all_params(self, async_client: AsyncCloudflare) per_page=0, sort="type,asc", status="pending", - type="legal_block", + type="account_suspend", ) assert_matches_type(AsyncV4PagePagination[Optional[MitigationListResponse]], mitigation, path=["response"]) diff --git a/tests/api_resources/dns/usage/__init__.py b/tests/api_resources/dns/usage/__init__.py new file mode 100644 index 00000000000..fd8019a9a1a --- /dev/null +++ b/tests/api_resources/dns/usage/__init__.py @@ -0,0 +1 @@ +# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. diff --git a/tests/api_resources/dns/usage/test_account.py b/tests/api_resources/dns/usage/test_account.py new file mode 100644 index 00000000000..03d86dca84a --- /dev/null +++ b/tests/api_resources/dns/usage/test_account.py @@ -0,0 +1,100 @@ +# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. + +from __future__ import annotations + +import os +from typing import Any, Optional, cast + +import pytest + +from cloudflare import Cloudflare, AsyncCloudflare +from tests.utils import assert_matches_type +from cloudflare.types.dns.usage import AccountGetResponse + +base_url = os.environ.get("TEST_API_BASE_URL", "http://127.0.0.1:4010") + + +class TestAccount: + parametrize = pytest.mark.parametrize("client", [False, True], indirect=True, ids=["loose", "strict"]) + + @parametrize + def test_method_get(self, client: Cloudflare) -> None: + account = client.dns.usage.account.get( + account_id="023e105f4ecef8ad9ca31a8372d0c353", + ) + assert_matches_type(Optional[AccountGetResponse], account, path=["response"]) + + @parametrize + def test_raw_response_get(self, client: Cloudflare) -> None: + response = client.dns.usage.account.with_raw_response.get( + account_id="023e105f4ecef8ad9ca31a8372d0c353", + ) + + assert response.is_closed is True + assert response.http_request.headers.get("X-Stainless-Lang") == "python" + account = response.parse() + assert_matches_type(Optional[AccountGetResponse], account, path=["response"]) + + @parametrize + def test_streaming_response_get(self, client: Cloudflare) -> None: + with client.dns.usage.account.with_streaming_response.get( + account_id="023e105f4ecef8ad9ca31a8372d0c353", + ) as response: + assert not response.is_closed + assert response.http_request.headers.get("X-Stainless-Lang") == "python" + + account = response.parse() + assert_matches_type(Optional[AccountGetResponse], account, path=["response"]) + + assert cast(Any, response.is_closed) is True + + @parametrize + def test_path_params_get(self, client: Cloudflare) -> None: + with pytest.raises(ValueError, match=r"Expected a non-empty value for `account_id` but received ''"): + client.dns.usage.account.with_raw_response.get( + account_id="", + ) + + +class TestAsyncAccount: + parametrize = pytest.mark.parametrize( + "async_client", [False, True, {"http_client": "aiohttp"}], indirect=True, ids=["loose", "strict", "aiohttp"] + ) + + @parametrize + async def test_method_get(self, async_client: AsyncCloudflare) -> None: + account = await async_client.dns.usage.account.get( + account_id="023e105f4ecef8ad9ca31a8372d0c353", + ) + assert_matches_type(Optional[AccountGetResponse], account, path=["response"]) + + @parametrize + async def test_raw_response_get(self, async_client: AsyncCloudflare) -> None: + response = await async_client.dns.usage.account.with_raw_response.get( + account_id="023e105f4ecef8ad9ca31a8372d0c353", + ) + + assert response.is_closed is True + assert response.http_request.headers.get("X-Stainless-Lang") == "python" + account = await response.parse() + assert_matches_type(Optional[AccountGetResponse], account, path=["response"]) + + @parametrize + async def test_streaming_response_get(self, async_client: AsyncCloudflare) -> None: + async with async_client.dns.usage.account.with_streaming_response.get( + account_id="023e105f4ecef8ad9ca31a8372d0c353", + ) as response: + assert not response.is_closed + assert response.http_request.headers.get("X-Stainless-Lang") == "python" + + account = await response.parse() + assert_matches_type(Optional[AccountGetResponse], account, path=["response"]) + + assert cast(Any, response.is_closed) is True + + @parametrize + async def test_path_params_get(self, async_client: AsyncCloudflare) -> None: + with pytest.raises(ValueError, match=r"Expected a non-empty value for `account_id` but received ''"): + await async_client.dns.usage.account.with_raw_response.get( + account_id="", + ) diff --git a/tests/api_resources/dns/usage/test_zone.py b/tests/api_resources/dns/usage/test_zone.py new file mode 100644 index 00000000000..be5c61715f1 --- /dev/null +++ b/tests/api_resources/dns/usage/test_zone.py @@ -0,0 +1,100 @@ +# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. + +from __future__ import annotations + +import os +from typing import Any, Optional, cast + +import pytest + +from cloudflare import Cloudflare, AsyncCloudflare +from tests.utils import assert_matches_type +from cloudflare.types.dns.usage import ZoneGetResponse + +base_url = os.environ.get("TEST_API_BASE_URL", "http://127.0.0.1:4010") + + +class TestZone: + parametrize = pytest.mark.parametrize("client", [False, True], indirect=True, ids=["loose", "strict"]) + + @parametrize + def test_method_get(self, client: Cloudflare) -> None: + zone = client.dns.usage.zone.get( + zone_id="023e105f4ecef8ad9ca31a8372d0c353", + ) + assert_matches_type(Optional[ZoneGetResponse], zone, path=["response"]) + + @parametrize + def test_raw_response_get(self, client: Cloudflare) -> None: + response = client.dns.usage.zone.with_raw_response.get( + zone_id="023e105f4ecef8ad9ca31a8372d0c353", + ) + + assert response.is_closed is True + assert response.http_request.headers.get("X-Stainless-Lang") == "python" + zone = response.parse() + assert_matches_type(Optional[ZoneGetResponse], zone, path=["response"]) + + @parametrize + def test_streaming_response_get(self, client: Cloudflare) -> None: + with client.dns.usage.zone.with_streaming_response.get( + zone_id="023e105f4ecef8ad9ca31a8372d0c353", + ) as response: + assert not response.is_closed + assert response.http_request.headers.get("X-Stainless-Lang") == "python" + + zone = response.parse() + assert_matches_type(Optional[ZoneGetResponse], zone, path=["response"]) + + assert cast(Any, response.is_closed) is True + + @parametrize + def test_path_params_get(self, client: Cloudflare) -> None: + with pytest.raises(ValueError, match=r"Expected a non-empty value for `zone_id` but received ''"): + client.dns.usage.zone.with_raw_response.get( + zone_id="", + ) + + +class TestAsyncZone: + parametrize = pytest.mark.parametrize( + "async_client", [False, True, {"http_client": "aiohttp"}], indirect=True, ids=["loose", "strict", "aiohttp"] + ) + + @parametrize + async def test_method_get(self, async_client: AsyncCloudflare) -> None: + zone = await async_client.dns.usage.zone.get( + zone_id="023e105f4ecef8ad9ca31a8372d0c353", + ) + assert_matches_type(Optional[ZoneGetResponse], zone, path=["response"]) + + @parametrize + async def test_raw_response_get(self, async_client: AsyncCloudflare) -> None: + response = await async_client.dns.usage.zone.with_raw_response.get( + zone_id="023e105f4ecef8ad9ca31a8372d0c353", + ) + + assert response.is_closed is True + assert response.http_request.headers.get("X-Stainless-Lang") == "python" + zone = await response.parse() + assert_matches_type(Optional[ZoneGetResponse], zone, path=["response"]) + + @parametrize + async def test_streaming_response_get(self, async_client: AsyncCloudflare) -> None: + async with async_client.dns.usage.zone.with_streaming_response.get( + zone_id="023e105f4ecef8ad9ca31a8372d0c353", + ) as response: + assert not response.is_closed + assert response.http_request.headers.get("X-Stainless-Lang") == "python" + + zone = await response.parse() + assert_matches_type(Optional[ZoneGetResponse], zone, path=["response"]) + + assert cast(Any, response.is_closed) is True + + @parametrize + async def test_path_params_get(self, async_client: AsyncCloudflare) -> None: + with pytest.raises(ValueError, match=r"Expected a non-empty value for `zone_id` but received ''"): + await async_client.dns.usage.zone.with_raw_response.get( + zone_id="", + ) diff --git a/tests/api_resources/resource_sharing/test_resources.py b/tests/api_resources/resource_sharing/test_resources.py index ccb14582074..a07aeebdca1 100644 --- a/tests/api_resources/resource_sharing/test_resources.py +++ b/tests/api_resources/resource_sharing/test_resources.py @@ -11,8 +11,11 @@ from tests.utils import assert_matches_type from cloudflare.pagination import SyncV4PagePaginationArray, AsyncV4PagePaginationArray from cloudflare.types.resource_sharing import ( + ResourceGetResponse, ResourceListResponse, ResourceCreateResponse, + ResourceDeleteResponse, + ResourceUpdateResponse, ) base_url = os.environ.get("TEST_API_BASE_URL", "http://127.0.0.1:4010") @@ -89,6 +92,72 @@ def test_path_params_create(self, client: Cloudflare) -> None: resource_type="custom-ruleset", ) + @parametrize + def test_method_update(self, client: Cloudflare) -> None: + resource = client.resource_sharing.resources.update( + share_resource_id="023e105f4ecef8ad9ca31a8372d0c353", + account_id="023e105f4ecef8ad9ca31a8372d0c353", + share_id="3fd85f74b32742f1bff64a85009dda07", + meta={}, + ) + assert_matches_type(Optional[ResourceUpdateResponse], resource, path=["response"]) + + @parametrize + def test_raw_response_update(self, client: Cloudflare) -> None: + response = client.resource_sharing.resources.with_raw_response.update( + share_resource_id="023e105f4ecef8ad9ca31a8372d0c353", + account_id="023e105f4ecef8ad9ca31a8372d0c353", + share_id="3fd85f74b32742f1bff64a85009dda07", + meta={}, + ) + + assert response.is_closed is True + assert response.http_request.headers.get("X-Stainless-Lang") == "python" + resource = response.parse() + assert_matches_type(Optional[ResourceUpdateResponse], resource, path=["response"]) + + @parametrize + def test_streaming_response_update(self, client: Cloudflare) -> None: + with client.resource_sharing.resources.with_streaming_response.update( + share_resource_id="023e105f4ecef8ad9ca31a8372d0c353", + account_id="023e105f4ecef8ad9ca31a8372d0c353", + share_id="3fd85f74b32742f1bff64a85009dda07", + meta={}, + ) as response: + assert not response.is_closed + assert response.http_request.headers.get("X-Stainless-Lang") == "python" + + resource = response.parse() + assert_matches_type(Optional[ResourceUpdateResponse], resource, path=["response"]) + + assert cast(Any, response.is_closed) is True + + @parametrize + def test_path_params_update(self, client: Cloudflare) -> None: + with pytest.raises(ValueError, match=r"Expected a non-empty value for `account_id` but received ''"): + client.resource_sharing.resources.with_raw_response.update( + share_resource_id="023e105f4ecef8ad9ca31a8372d0c353", + account_id="", + share_id="3fd85f74b32742f1bff64a85009dda07", + meta={}, + ) + + with pytest.raises(ValueError, match=r"Expected a non-empty value for `share_id` but received ''"): + client.resource_sharing.resources.with_raw_response.update( + share_resource_id="023e105f4ecef8ad9ca31a8372d0c353", + account_id="023e105f4ecef8ad9ca31a8372d0c353", + share_id="", + meta={}, + ) + + with pytest.raises(ValueError, match=r"Expected a non-empty value for `share_resource_id` but received ''"): + client.resource_sharing.resources.with_raw_response.update( + share_resource_id="", + account_id="023e105f4ecef8ad9ca31a8372d0c353", + share_id="3fd85f74b32742f1bff64a85009dda07", + meta={}, + ) + @parametrize def test_method_list(self, client: Cloudflare) -> None: resource = client.resource_sharing.resources.list( @@ -149,6 +218,126 @@ def test_path_params_list(self, client: Cloudflare) -> None: account_id="023e105f4ecef8ad9ca31a8372d0c353", ) + @parametrize + def test_method_delete(self, client: Cloudflare) -> None: + resource = client.resource_sharing.resources.delete( + share_resource_id="023e105f4ecef8ad9ca31a8372d0c353", + account_id="023e105f4ecef8ad9ca31a8372d0c353", + share_id="3fd85f74b32742f1bff64a85009dda07", + ) + assert_matches_type(Optional[ResourceDeleteResponse], resource, path=["response"]) + + @parametrize + def test_raw_response_delete(self, client: Cloudflare) -> None: + response = client.resource_sharing.resources.with_raw_response.delete( + share_resource_id="023e105f4ecef8ad9ca31a8372d0c353", + account_id="023e105f4ecef8ad9ca31a8372d0c353", + share_id="3fd85f74b32742f1bff64a85009dda07", + ) + + assert response.is_closed is True + assert response.http_request.headers.get("X-Stainless-Lang") == "python" + resource = response.parse() + assert_matches_type(Optional[ResourceDeleteResponse], resource, path=["response"]) + + @parametrize + def test_streaming_response_delete(self, client: Cloudflare) -> None: + with client.resource_sharing.resources.with_streaming_response.delete( + share_resource_id="023e105f4ecef8ad9ca31a8372d0c353", + account_id="023e105f4ecef8ad9ca31a8372d0c353", + share_id="3fd85f74b32742f1bff64a85009dda07", + ) as response: + assert not response.is_closed + assert response.http_request.headers.get("X-Stainless-Lang") == "python" + + resource = response.parse() + assert_matches_type(Optional[ResourceDeleteResponse], resource, path=["response"]) + + assert cast(Any, response.is_closed) is True + + @parametrize + def test_path_params_delete(self, client: Cloudflare) -> None: + with pytest.raises(ValueError, match=r"Expected a non-empty value for `account_id` but received ''"): + client.resource_sharing.resources.with_raw_response.delete( + share_resource_id="023e105f4ecef8ad9ca31a8372d0c353", + account_id="", + share_id="3fd85f74b32742f1bff64a85009dda07", + ) + + with pytest.raises(ValueError, match=r"Expected a non-empty value for `share_id` but received ''"): + client.resource_sharing.resources.with_raw_response.delete( + share_resource_id="023e105f4ecef8ad9ca31a8372d0c353", + account_id="023e105f4ecef8ad9ca31a8372d0c353", + share_id="", + ) + + with pytest.raises(ValueError, match=r"Expected a non-empty value for `share_resource_id` but received ''"): + client.resource_sharing.resources.with_raw_response.delete( + share_resource_id="", + account_id="023e105f4ecef8ad9ca31a8372d0c353", + share_id="3fd85f74b32742f1bff64a85009dda07", + ) + + @parametrize + def test_method_get(self, client: Cloudflare) -> None: + resource = client.resource_sharing.resources.get( + share_resource_id="023e105f4ecef8ad9ca31a8372d0c353", + account_id="023e105f4ecef8ad9ca31a8372d0c353", + share_id="3fd85f74b32742f1bff64a85009dda07", + ) + assert_matches_type(Optional[ResourceGetResponse], resource, path=["response"]) + + @parametrize + def test_raw_response_get(self, client: Cloudflare) -> None: + response = client.resource_sharing.resources.with_raw_response.get( + share_resource_id="023e105f4ecef8ad9ca31a8372d0c353", + account_id="023e105f4ecef8ad9ca31a8372d0c353", + share_id="3fd85f74b32742f1bff64a85009dda07", + ) + + assert response.is_closed is True + assert response.http_request.headers.get("X-Stainless-Lang") == "python" + resource = response.parse() + assert_matches_type(Optional[ResourceGetResponse], resource, path=["response"]) + + @parametrize + def test_streaming_response_get(self, client: Cloudflare) -> None: + with client.resource_sharing.resources.with_streaming_response.get( + share_resource_id="023e105f4ecef8ad9ca31a8372d0c353", + account_id="023e105f4ecef8ad9ca31a8372d0c353", + share_id="3fd85f74b32742f1bff64a85009dda07", + ) as response: + assert not response.is_closed + assert response.http_request.headers.get("X-Stainless-Lang") == "python" + + resource = response.parse() + assert_matches_type(Optional[ResourceGetResponse], resource, path=["response"]) + + assert cast(Any, response.is_closed) is True + + @parametrize + def test_path_params_get(self, client: Cloudflare) -> None: + with pytest.raises(ValueError, match=r"Expected a non-empty value for `account_id` but received ''"): + client.resource_sharing.resources.with_raw_response.get( + share_resource_id="023e105f4ecef8ad9ca31a8372d0c353", + account_id="", + share_id="3fd85f74b32742f1bff64a85009dda07", + ) + + with pytest.raises(ValueError, match=r"Expected a non-empty value for `share_id` but received ''"): + client.resource_sharing.resources.with_raw_response.get( + share_resource_id="023e105f4ecef8ad9ca31a8372d0c353", + account_id="023e105f4ecef8ad9ca31a8372d0c353", + share_id="", + ) + + with pytest.raises(ValueError, match=r"Expected a non-empty value for `share_resource_id` but received ''"): + client.resource_sharing.resources.with_raw_response.get( + share_resource_id="", + account_id="023e105f4ecef8ad9ca31a8372d0c353", + share_id="3fd85f74b32742f1bff64a85009dda07", + ) + class TestAsyncResources: parametrize = pytest.mark.parametrize( @@ -223,6 +412,72 @@ async def test_path_params_create(self, async_client: AsyncCloudflare) -> None: resource_type="custom-ruleset", ) + @parametrize + async def test_method_update(self, async_client: AsyncCloudflare) -> None: + resource = await async_client.resource_sharing.resources.update( + share_resource_id="023e105f4ecef8ad9ca31a8372d0c353", + account_id="023e105f4ecef8ad9ca31a8372d0c353", + share_id="3fd85f74b32742f1bff64a85009dda07", + meta={}, + ) + assert_matches_type(Optional[ResourceUpdateResponse], resource, path=["response"]) + + @parametrize + async def test_raw_response_update(self, async_client: AsyncCloudflare) -> None: + response = await async_client.resource_sharing.resources.with_raw_response.update( + share_resource_id="023e105f4ecef8ad9ca31a8372d0c353", + account_id="023e105f4ecef8ad9ca31a8372d0c353", + share_id="3fd85f74b32742f1bff64a85009dda07", + meta={}, + ) + + assert response.is_closed is True + assert response.http_request.headers.get("X-Stainless-Lang") == "python" + resource = await response.parse() + assert_matches_type(Optional[ResourceUpdateResponse], resource, path=["response"]) + + @parametrize + async def test_streaming_response_update(self, async_client: AsyncCloudflare) -> None: + async with async_client.resource_sharing.resources.with_streaming_response.update( + share_resource_id="023e105f4ecef8ad9ca31a8372d0c353", + account_id="023e105f4ecef8ad9ca31a8372d0c353", + share_id="3fd85f74b32742f1bff64a85009dda07", + meta={}, + ) as response: + assert not response.is_closed + assert response.http_request.headers.get("X-Stainless-Lang") == "python" + + resource = await response.parse() + assert_matches_type(Optional[ResourceUpdateResponse], resource, path=["response"]) + + assert cast(Any, response.is_closed) is True + + @parametrize + async def test_path_params_update(self, async_client: AsyncCloudflare) -> None: + with pytest.raises(ValueError, match=r"Expected a non-empty value for `account_id` but received ''"): + await async_client.resource_sharing.resources.with_raw_response.update( + share_resource_id="023e105f4ecef8ad9ca31a8372d0c353", + account_id="", + share_id="3fd85f74b32742f1bff64a85009dda07", + meta={}, + ) + + with pytest.raises(ValueError, match=r"Expected a non-empty value for `share_id` but received ''"): + await async_client.resource_sharing.resources.with_raw_response.update( + share_resource_id="023e105f4ecef8ad9ca31a8372d0c353", + account_id="023e105f4ecef8ad9ca31a8372d0c353", + share_id="", + meta={}, + ) + + with pytest.raises(ValueError, match=r"Expected a non-empty value for `share_resource_id` but received ''"): + await async_client.resource_sharing.resources.with_raw_response.update( + share_resource_id="", + account_id="023e105f4ecef8ad9ca31a8372d0c353", + share_id="3fd85f74b32742f1bff64a85009dda07", + meta={}, + ) + @parametrize async def test_method_list(self, async_client: AsyncCloudflare) -> None: resource = await async_client.resource_sharing.resources.list( @@ -282,3 +537,123 @@ async def test_path_params_list(self, async_client: AsyncCloudflare) -> None: share_id="", account_id="023e105f4ecef8ad9ca31a8372d0c353", ) + + @parametrize + async def test_method_delete(self, async_client: AsyncCloudflare) -> None: + resource = await async_client.resource_sharing.resources.delete( + share_resource_id="023e105f4ecef8ad9ca31a8372d0c353", + account_id="023e105f4ecef8ad9ca31a8372d0c353", + share_id="3fd85f74b32742f1bff64a85009dda07", + ) + assert_matches_type(Optional[ResourceDeleteResponse], resource, path=["response"]) + + @parametrize + async def test_raw_response_delete(self, async_client: AsyncCloudflare) -> None: + response = await async_client.resource_sharing.resources.with_raw_response.delete( + share_resource_id="023e105f4ecef8ad9ca31a8372d0c353", + account_id="023e105f4ecef8ad9ca31a8372d0c353", + share_id="3fd85f74b32742f1bff64a85009dda07", + ) + + assert response.is_closed is True + assert response.http_request.headers.get("X-Stainless-Lang") == "python" + resource = await response.parse() + assert_matches_type(Optional[ResourceDeleteResponse], resource, path=["response"]) + + @parametrize + async def test_streaming_response_delete(self, async_client: AsyncCloudflare) -> None: + async with async_client.resource_sharing.resources.with_streaming_response.delete( + share_resource_id="023e105f4ecef8ad9ca31a8372d0c353", + account_id="023e105f4ecef8ad9ca31a8372d0c353", + share_id="3fd85f74b32742f1bff64a85009dda07", + ) as response: + assert not response.is_closed + assert response.http_request.headers.get("X-Stainless-Lang") == "python" + + resource = await response.parse() + assert_matches_type(Optional[ResourceDeleteResponse], resource, path=["response"]) + + assert cast(Any, response.is_closed) is True + + @parametrize + async def test_path_params_delete(self, async_client: AsyncCloudflare) -> None: + with pytest.raises(ValueError, match=r"Expected a non-empty value for `account_id` but received ''"): + await async_client.resource_sharing.resources.with_raw_response.delete( + share_resource_id="023e105f4ecef8ad9ca31a8372d0c353", + account_id="", + share_id="3fd85f74b32742f1bff64a85009dda07", + ) + + with pytest.raises(ValueError, match=r"Expected a non-empty value for `share_id` but received ''"): + await async_client.resource_sharing.resources.with_raw_response.delete( + share_resource_id="023e105f4ecef8ad9ca31a8372d0c353", + account_id="023e105f4ecef8ad9ca31a8372d0c353", + share_id="", + ) + + with pytest.raises(ValueError, match=r"Expected a non-empty value for `share_resource_id` but received ''"): + await async_client.resource_sharing.resources.with_raw_response.delete( + share_resource_id="", + account_id="023e105f4ecef8ad9ca31a8372d0c353", + share_id="3fd85f74b32742f1bff64a85009dda07", + ) + + @parametrize + async def test_method_get(self, async_client: AsyncCloudflare) -> None: + resource = await async_client.resource_sharing.resources.get( + share_resource_id="023e105f4ecef8ad9ca31a8372d0c353", + account_id="023e105f4ecef8ad9ca31a8372d0c353", + share_id="3fd85f74b32742f1bff64a85009dda07", + ) + assert_matches_type(Optional[ResourceGetResponse], resource, path=["response"]) + + @parametrize + async def test_raw_response_get(self, async_client: AsyncCloudflare) -> None: + response = await async_client.resource_sharing.resources.with_raw_response.get( + share_resource_id="023e105f4ecef8ad9ca31a8372d0c353", + account_id="023e105f4ecef8ad9ca31a8372d0c353", + share_id="3fd85f74b32742f1bff64a85009dda07", + ) + + assert response.is_closed is True + assert response.http_request.headers.get("X-Stainless-Lang") == "python" + resource = await response.parse() + assert_matches_type(Optional[ResourceGetResponse], resource, path=["response"]) + + @parametrize + async def test_streaming_response_get(self, async_client: AsyncCloudflare) -> None: + async with async_client.resource_sharing.resources.with_streaming_response.get( + share_resource_id="023e105f4ecef8ad9ca31a8372d0c353", + account_id="023e105f4ecef8ad9ca31a8372d0c353", + share_id="3fd85f74b32742f1bff64a85009dda07", + ) as response: + assert not response.is_closed + assert response.http_request.headers.get("X-Stainless-Lang") == "python" + + resource = await response.parse() + assert_matches_type(Optional[ResourceGetResponse], resource, path=["response"]) + + assert cast(Any, response.is_closed) is True + + @parametrize + async def test_path_params_get(self, async_client: AsyncCloudflare) -> None: + with pytest.raises(ValueError, match=r"Expected a non-empty value for `account_id` but received ''"): + await async_client.resource_sharing.resources.with_raw_response.get( + share_resource_id="023e105f4ecef8ad9ca31a8372d0c353", + account_id="", + share_id="3fd85f74b32742f1bff64a85009dda07", + ) + + with pytest.raises(ValueError, match=r"Expected a non-empty value for `share_id` but received ''"): + await async_client.resource_sharing.resources.with_raw_response.get( + share_resource_id="023e105f4ecef8ad9ca31a8372d0c353", + account_id="023e105f4ecef8ad9ca31a8372d0c353", + share_id="", + ) + + with pytest.raises(ValueError, match=r"Expected a non-empty value for `share_resource_id` but received ''"): + await async_client.resource_sharing.resources.with_raw_response.get( + share_resource_id="", + account_id="023e105f4ecef8ad9ca31a8372d0c353", + share_id="3fd85f74b32742f1bff64a85009dda07", + ) diff --git a/tests/api_resources/test_ai_gateway.py b/tests/api_resources/test_ai_gateway.py index 20338d953cc..33015cc2c13 100644 --- a/tests/api_resources/test_ai_gateway.py +++ b/tests/api_resources/test_ai_gateway.py @@ -189,6 +189,28 @@ def test_method_update_with_all_params(self, client: Cloudflare) -> None: retry_backoff="constant", retry_delay=0, retry_max_attempts=1, + spend_limits={ + "enabled": True, + "rules": [ + { + "limit": 1, + "limit_type": "cost", + "window": 1, + "id": "x", + "enabled": True, + "metadata": {"foo": {"mode": "partition"}}, + "model": { + "mode": "filter", + "values": ["string"], + }, + "provider": { + "mode": "filter", + "values": ["string"], + }, + "technique": "fixed", + } + ], + }, store_id="store_id", stripe={ "authorization": "authorization", @@ -574,6 +596,28 @@ async def test_method_update_with_all_params(self, async_client: AsyncCloudflare retry_backoff="constant", retry_delay=0, retry_max_attempts=1, + spend_limits={ + "enabled": True, + "rules": [ + { + "limit": 1, + "limit_type": "cost", + "window": 1, + "id": "x", + "enabled": True, + "metadata": {"foo": {"mode": "partition"}}, + "model": { + "mode": "filter", + "values": ["string"], + }, + "provider": { + "mode": "filter", + "values": ["string"], + }, + "technique": "fixed", + } + ], + }, store_id="store_id", stripe={ "authorization": "authorization", diff --git a/tests/api_resources/test_workflows.py b/tests/api_resources/test_workflows.py index 50b603500c7..d8dc7b04888 100644 --- a/tests/api_resources/test_workflows.py +++ b/tests/api_resources/test_workflows.py @@ -41,6 +41,7 @@ def test_method_update_with_all_params(self, client: Cloudflare) -> None: class_name="x", script_name="x", limits={"steps": 1}, + schedules=[{"cron": "x"}], ) assert_matches_type(WorkflowUpdateResponse, workflow, path=["response"]) @@ -260,6 +261,7 @@ async def test_method_update_with_all_params(self, async_client: AsyncCloudflare class_name="x", script_name="x", limits={"steps": 1}, + schedules=[{"cron": "x"}], ) assert_matches_type(WorkflowUpdateResponse, workflow, path=["response"]) diff --git a/tests/api_resources/workflows/test_instances.py b/tests/api_resources/workflows/test_instances.py index 5ffbec6aa23..b3f99e55b80 100644 --- a/tests/api_resources/workflows/test_instances.py +++ b/tests/api_resources/workflows/test_instances.py @@ -15,6 +15,7 @@ InstanceGetResponse, InstanceBulkResponse, InstanceListResponse, + InstanceStepResponse, InstanceCreateResponse, ) @@ -286,6 +287,90 @@ def test_path_params_get(self, client: Cloudflare) -> None: workflow_name="x", ) + @parametrize + def test_method_step(self, client: Cloudflare) -> None: + instance = client.workflows.instances.step( + instance_id="x", + account_id="account_id", + workflow_name="x", + name="x", + type="step", + ) + assert_matches_type(InstanceStepResponse, instance, path=["response"]) + + @parametrize + def test_method_step_with_all_params(self, client: Cloudflare) -> None: + instance = client.workflows.instances.step( + instance_id="x", + account_id="account_id", + workflow_name="x", + name="x", + type="step", + attempt=1, + ) + assert_matches_type(InstanceStepResponse, instance, path=["response"]) + + @parametrize + def test_raw_response_step(self, client: Cloudflare) -> None: + response = client.workflows.instances.with_raw_response.step( + instance_id="x", + account_id="account_id", + workflow_name="x", + name="x", + type="step", + ) + + assert response.is_closed is True + assert response.http_request.headers.get("X-Stainless-Lang") == "python" + instance = response.parse() + assert_matches_type(InstanceStepResponse, instance, path=["response"]) + + @parametrize + def test_streaming_response_step(self, client: Cloudflare) -> None: + with client.workflows.instances.with_streaming_response.step( + instance_id="x", + account_id="account_id", + workflow_name="x", + name="x", + type="step", + ) as response: + assert not response.is_closed + assert response.http_request.headers.get("X-Stainless-Lang") == "python" + + instance = response.parse() + assert_matches_type(InstanceStepResponse, instance, path=["response"]) + + assert cast(Any, response.is_closed) is True + + @parametrize + def test_path_params_step(self, client: Cloudflare) -> None: + with pytest.raises(ValueError, match=r"Expected a non-empty value for `account_id` but received ''"): + client.workflows.instances.with_raw_response.step( + instance_id="x", + account_id="", + workflow_name="x", + name="x", + type="step", + ) + + with pytest.raises(ValueError, match=r"Expected a non-empty value for `workflow_name` but received ''"): + client.workflows.instances.with_raw_response.step( + instance_id="x", + account_id="account_id", + workflow_name="", + name="x", + type="step", + ) + + with pytest.raises(ValueError, match=r"Expected a non-empty value for `instance_id` but received ''"): + client.workflows.instances.with_raw_response.step( + instance_id="", + account_id="account_id", + workflow_name="x", + name="x", + type="step", + ) + class TestAsyncInstances: parametrize = pytest.mark.parametrize( @@ -553,3 +638,87 @@ async def test_path_params_get(self, async_client: AsyncCloudflare) -> None: account_id="account_id", workflow_name="x", ) + + @parametrize + async def test_method_step(self, async_client: AsyncCloudflare) -> None: + instance = await async_client.workflows.instances.step( + instance_id="x", + account_id="account_id", + workflow_name="x", + name="x", + type="step", + ) + assert_matches_type(InstanceStepResponse, instance, path=["response"]) + + @parametrize + async def test_method_step_with_all_params(self, async_client: AsyncCloudflare) -> None: + instance = await async_client.workflows.instances.step( + instance_id="x", + account_id="account_id", + workflow_name="x", + name="x", + type="step", + attempt=1, + ) + assert_matches_type(InstanceStepResponse, instance, path=["response"]) + + @parametrize + async def test_raw_response_step(self, async_client: AsyncCloudflare) -> None: + response = await async_client.workflows.instances.with_raw_response.step( + instance_id="x", + account_id="account_id", + workflow_name="x", + name="x", + type="step", + ) + + assert response.is_closed is True + assert response.http_request.headers.get("X-Stainless-Lang") == "python" + instance = await response.parse() + assert_matches_type(InstanceStepResponse, instance, path=["response"]) + + @parametrize + async def test_streaming_response_step(self, async_client: AsyncCloudflare) -> None: + async with async_client.workflows.instances.with_streaming_response.step( + instance_id="x", + account_id="account_id", + workflow_name="x", + name="x", + type="step", + ) as response: + assert not response.is_closed + assert response.http_request.headers.get("X-Stainless-Lang") == "python" + + instance = await response.parse() + assert_matches_type(InstanceStepResponse, instance, path=["response"]) + + assert cast(Any, response.is_closed) is True + + @parametrize + async def test_path_params_step(self, async_client: AsyncCloudflare) -> None: + with pytest.raises(ValueError, match=r"Expected a non-empty value for `account_id` but received ''"): + await async_client.workflows.instances.with_raw_response.step( + instance_id="x", + account_id="", + workflow_name="x", + name="x", + type="step", + ) + + with pytest.raises(ValueError, match=r"Expected a non-empty value for `workflow_name` but received ''"): + await async_client.workflows.instances.with_raw_response.step( + instance_id="x", + account_id="account_id", + workflow_name="", + name="x", + type="step", + ) + + with pytest.raises(ValueError, match=r"Expected a non-empty value for `instance_id` but received ''"): + await async_client.workflows.instances.with_raw_response.step( + instance_id="", + account_id="account_id", + workflow_name="x", + name="x", + type="step", + ) diff --git a/tests/api_resources/workflows/test_versions.py b/tests/api_resources/workflows/test_versions.py index ecdc89ad65b..d1b3f39217a 100644 --- a/tests/api_resources/workflows/test_versions.py +++ b/tests/api_resources/workflows/test_versions.py @@ -10,7 +10,11 @@ from cloudflare import Cloudflare, AsyncCloudflare from tests.utils import assert_matches_type from cloudflare.pagination import SyncV4PagePaginationArray, AsyncV4PagePaginationArray -from cloudflare.types.workflows import VersionGetResponse, VersionListResponse +from cloudflare.types.workflows import ( + VersionGetResponse, + VersionListResponse, + VersionGraphResponse, +) base_url = os.environ.get("TEST_API_BASE_URL", "http://127.0.0.1:4010") @@ -136,6 +140,66 @@ def test_path_params_get(self, client: Cloudflare) -> None: workflow_name="x", ) + @parametrize + def test_method_graph(self, client: Cloudflare) -> None: + version = client.workflows.versions.graph( + version_id="182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e", + account_id="account_id", + workflow_name="x", + ) + assert_matches_type(VersionGraphResponse, version, path=["response"]) + + @parametrize + def test_raw_response_graph(self, client: Cloudflare) -> None: + response = client.workflows.versions.with_raw_response.graph( + version_id="182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e", + account_id="account_id", + workflow_name="x", + ) + + assert response.is_closed is True + assert response.http_request.headers.get("X-Stainless-Lang") == "python" + version = response.parse() + assert_matches_type(VersionGraphResponse, version, path=["response"]) + + @parametrize + def test_streaming_response_graph(self, client: Cloudflare) -> None: + with client.workflows.versions.with_streaming_response.graph( + version_id="182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e", + account_id="account_id", + workflow_name="x", + ) as response: + assert not response.is_closed + assert response.http_request.headers.get("X-Stainless-Lang") == "python" + + version = response.parse() + assert_matches_type(VersionGraphResponse, version, path=["response"]) + + assert cast(Any, response.is_closed) is True + + @parametrize + def test_path_params_graph(self, client: Cloudflare) -> None: + with pytest.raises(ValueError, match=r"Expected a non-empty value for `account_id` but received ''"): + client.workflows.versions.with_raw_response.graph( + version_id="182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e", + account_id="", + workflow_name="x", + ) + + with pytest.raises(ValueError, match=r"Expected a non-empty value for `workflow_name` but received ''"): + client.workflows.versions.with_raw_response.graph( + version_id="182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e", + account_id="account_id", + workflow_name="", + ) + + with pytest.raises(ValueError, match=r"Expected a non-empty value for `version_id` but received ''"): + client.workflows.versions.with_raw_response.graph( + version_id="", + account_id="account_id", + workflow_name="x", + ) + class TestAsyncVersions: parametrize = pytest.mark.parametrize( @@ -259,3 +323,63 @@ async def test_path_params_get(self, async_client: AsyncCloudflare) -> None: account_id="account_id", workflow_name="x", ) + + @parametrize + async def test_method_graph(self, async_client: AsyncCloudflare) -> None: + version = await async_client.workflows.versions.graph( + version_id="182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e", + account_id="account_id", + workflow_name="x", + ) + assert_matches_type(VersionGraphResponse, version, path=["response"]) + + @parametrize + async def test_raw_response_graph(self, async_client: AsyncCloudflare) -> None: + response = await async_client.workflows.versions.with_raw_response.graph( + version_id="182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e", + account_id="account_id", + workflow_name="x", + ) + + assert response.is_closed is True + assert response.http_request.headers.get("X-Stainless-Lang") == "python" + version = await response.parse() + assert_matches_type(VersionGraphResponse, version, path=["response"]) + + @parametrize + async def test_streaming_response_graph(self, async_client: AsyncCloudflare) -> None: + async with async_client.workflows.versions.with_streaming_response.graph( + version_id="182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e", + account_id="account_id", + workflow_name="x", + ) as response: + assert not response.is_closed + assert response.http_request.headers.get("X-Stainless-Lang") == "python" + + version = await response.parse() + assert_matches_type(VersionGraphResponse, version, path=["response"]) + + assert cast(Any, response.is_closed) is True + + @parametrize + async def test_path_params_graph(self, async_client: AsyncCloudflare) -> None: + with pytest.raises(ValueError, match=r"Expected a non-empty value for `account_id` but received ''"): + await async_client.workflows.versions.with_raw_response.graph( + version_id="182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e", + account_id="", + workflow_name="x", + ) + + with pytest.raises(ValueError, match=r"Expected a non-empty value for `workflow_name` but received ''"): + await async_client.workflows.versions.with_raw_response.graph( + version_id="182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e", + account_id="account_id", + workflow_name="", + ) + + with pytest.raises(ValueError, match=r"Expected a non-empty value for `version_id` but received ''"): + await async_client.workflows.versions.with_raw_response.graph( + version_id="", + account_id="account_id", + workflow_name="x", + ) diff --git a/tests/api_resources/zero_trust/access/ai_controls/mcp/test_servers.py b/tests/api_resources/zero_trust/access/ai_controls/mcp/test_servers.py index 730d3ecb17d..33145a04d0d 100644 --- a/tests/api_resources/zero_trust/access/ai_controls/mcp/test_servers.py +++ b/tests/api_resources/zero_trust/access/ai_controls/mcp/test_servers.py @@ -46,6 +46,7 @@ def test_method_create_with_all_params(self, client: Cloudflare) -> None: name="My MCP Server", auth_credentials="auth_credentials", description="This is one remote mcp server", + is_shared_oauth_callback_enabled=True, updated_prompts=[ { "name": "name", @@ -123,6 +124,7 @@ def test_method_update_with_all_params(self, client: Cloudflare) -> None: account_id="a86a8f5c339544d7bdc89926de14fb8c", auth_credentials="auth_credentials", description="This is one remote mcp server", + is_shared_oauth_callback_enabled=True, name="My MCP Server", updated_prompts=[ { @@ -402,6 +404,7 @@ async def test_method_create_with_all_params(self, async_client: AsyncCloudflare name="My MCP Server", auth_credentials="auth_credentials", description="This is one remote mcp server", + is_shared_oauth_callback_enabled=True, updated_prompts=[ { "name": "name", @@ -479,6 +482,7 @@ async def test_method_update_with_all_params(self, async_client: AsyncCloudflare account_id="a86a8f5c339544d7bdc89926de14fb8c", auth_credentials="auth_credentials", description="This is one remote mcp server", + is_shared_oauth_callback_enabled=True, name="My MCP Server", updated_prompts=[ { diff --git a/tests/api_resources/zero_trust/access/test_idp_federation_grants.py b/tests/api_resources/zero_trust/access/test_idp_federation_grants.py new file mode 100644 index 00000000000..ab5896d9356 --- /dev/null +++ b/tests/api_resources/zero_trust/access/test_idp_federation_grants.py @@ -0,0 +1,380 @@ +# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. + +from __future__ import annotations + +import os +from typing import Any, Optional, cast + +import pytest + +from cloudflare import Cloudflare, AsyncCloudflare +from tests.utils import assert_matches_type +from cloudflare.types.zero_trust.access import ( + IdPFederationGrant, + IdPFederationGrantListResponse, + IdPFederationGrantDeleteResponse, +) + +base_url = os.environ.get("TEST_API_BASE_URL", "http://127.0.0.1:4010") + + +class TestIdPFederationGrants: + parametrize = pytest.mark.parametrize("client", [False, True], indirect=True, ids=["loose", "strict"]) + + @parametrize + def test_method_create(self, client: Cloudflare) -> None: + idp_federation_grant = client.zero_trust.access.idp_federation_grants.create( + account_id="023e105f4ecef8ad9ca31a8372d0c353", + idp_id="a79de439-0e7f-4ebb-8a02-222222222222", + ) + assert_matches_type(Optional[IdPFederationGrant], idp_federation_grant, path=["response"]) + + @parametrize + def test_raw_response_create(self, client: Cloudflare) -> None: + response = client.zero_trust.access.idp_federation_grants.with_raw_response.create( + account_id="023e105f4ecef8ad9ca31a8372d0c353", + idp_id="a79de439-0e7f-4ebb-8a02-222222222222", + ) + + assert response.is_closed is True + assert response.http_request.headers.get("X-Stainless-Lang") == "python" + idp_federation_grant = response.parse() + assert_matches_type(Optional[IdPFederationGrant], idp_federation_grant, path=["response"]) + + @parametrize + def test_streaming_response_create(self, client: Cloudflare) -> None: + with client.zero_trust.access.idp_federation_grants.with_streaming_response.create( + account_id="023e105f4ecef8ad9ca31a8372d0c353", + idp_id="a79de439-0e7f-4ebb-8a02-222222222222", + ) as response: + assert not response.is_closed + assert response.http_request.headers.get("X-Stainless-Lang") == "python" + + idp_federation_grant = response.parse() + assert_matches_type(Optional[IdPFederationGrant], idp_federation_grant, path=["response"]) + + assert cast(Any, response.is_closed) is True + + @parametrize + def test_path_params_create(self, client: Cloudflare) -> None: + with pytest.raises(ValueError, match=r"Expected a non-empty value for `account_id` but received ''"): + client.zero_trust.access.idp_federation_grants.with_raw_response.create( + account_id="", + idp_id="a79de439-0e7f-4ebb-8a02-222222222222", + ) + + @parametrize + def test_method_list(self, client: Cloudflare) -> None: + idp_federation_grant = client.zero_trust.access.idp_federation_grants.list( + account_id="023e105f4ecef8ad9ca31a8372d0c353", + ) + assert_matches_type(Optional[IdPFederationGrantListResponse], idp_federation_grant, path=["response"]) + + @parametrize + def test_raw_response_list(self, client: Cloudflare) -> None: + response = client.zero_trust.access.idp_federation_grants.with_raw_response.list( + account_id="023e105f4ecef8ad9ca31a8372d0c353", + ) + + assert response.is_closed is True + assert response.http_request.headers.get("X-Stainless-Lang") == "python" + idp_federation_grant = response.parse() + assert_matches_type(Optional[IdPFederationGrantListResponse], idp_federation_grant, path=["response"]) + + @parametrize + def test_streaming_response_list(self, client: Cloudflare) -> None: + with client.zero_trust.access.idp_federation_grants.with_streaming_response.list( + account_id="023e105f4ecef8ad9ca31a8372d0c353", + ) as response: + assert not response.is_closed + assert response.http_request.headers.get("X-Stainless-Lang") == "python" + + idp_federation_grant = response.parse() + assert_matches_type(Optional[IdPFederationGrantListResponse], idp_federation_grant, path=["response"]) + + assert cast(Any, response.is_closed) is True + + @parametrize + def test_path_params_list(self, client: Cloudflare) -> None: + with pytest.raises(ValueError, match=r"Expected a non-empty value for `account_id` but received ''"): + client.zero_trust.access.idp_federation_grants.with_raw_response.list( + account_id="", + ) + + @parametrize + def test_method_delete(self, client: Cloudflare) -> None: + idp_federation_grant = client.zero_trust.access.idp_federation_grants.delete( + grant_id="023e105f4ecef8ad9ca31a8372d0c353", + account_id="023e105f4ecef8ad9ca31a8372d0c353", + ) + assert_matches_type(Optional[IdPFederationGrantDeleteResponse], idp_federation_grant, path=["response"]) + + @parametrize + def test_raw_response_delete(self, client: Cloudflare) -> None: + response = client.zero_trust.access.idp_federation_grants.with_raw_response.delete( + grant_id="023e105f4ecef8ad9ca31a8372d0c353", + account_id="023e105f4ecef8ad9ca31a8372d0c353", + ) + + assert response.is_closed is True + assert response.http_request.headers.get("X-Stainless-Lang") == "python" + idp_federation_grant = response.parse() + assert_matches_type(Optional[IdPFederationGrantDeleteResponse], idp_federation_grant, path=["response"]) + + @parametrize + def test_streaming_response_delete(self, client: Cloudflare) -> None: + with client.zero_trust.access.idp_federation_grants.with_streaming_response.delete( + grant_id="023e105f4ecef8ad9ca31a8372d0c353", + account_id="023e105f4ecef8ad9ca31a8372d0c353", + ) as response: + assert not response.is_closed + assert response.http_request.headers.get("X-Stainless-Lang") == "python" + + idp_federation_grant = response.parse() + assert_matches_type(Optional[IdPFederationGrantDeleteResponse], idp_federation_grant, path=["response"]) + + assert cast(Any, response.is_closed) is True + + @parametrize + def test_path_params_delete(self, client: Cloudflare) -> None: + with pytest.raises(ValueError, match=r"Expected a non-empty value for `account_id` but received ''"): + client.zero_trust.access.idp_federation_grants.with_raw_response.delete( + grant_id="023e105f4ecef8ad9ca31a8372d0c353", + account_id="", + ) + + with pytest.raises(ValueError, match=r"Expected a non-empty value for `grant_id` but received ''"): + client.zero_trust.access.idp_federation_grants.with_raw_response.delete( + grant_id="", + account_id="023e105f4ecef8ad9ca31a8372d0c353", + ) + + @parametrize + def test_method_get(self, client: Cloudflare) -> None: + idp_federation_grant = client.zero_trust.access.idp_federation_grants.get( + grant_id="023e105f4ecef8ad9ca31a8372d0c353", + account_id="023e105f4ecef8ad9ca31a8372d0c353", + ) + assert_matches_type(Optional[IdPFederationGrant], idp_federation_grant, path=["response"]) + + @parametrize + def test_raw_response_get(self, client: Cloudflare) -> None: + response = client.zero_trust.access.idp_federation_grants.with_raw_response.get( + grant_id="023e105f4ecef8ad9ca31a8372d0c353", + account_id="023e105f4ecef8ad9ca31a8372d0c353", + ) + + assert response.is_closed is True + assert response.http_request.headers.get("X-Stainless-Lang") == "python" + idp_federation_grant = response.parse() + assert_matches_type(Optional[IdPFederationGrant], idp_federation_grant, path=["response"]) + + @parametrize + def test_streaming_response_get(self, client: Cloudflare) -> None: + with client.zero_trust.access.idp_federation_grants.with_streaming_response.get( + grant_id="023e105f4ecef8ad9ca31a8372d0c353", + account_id="023e105f4ecef8ad9ca31a8372d0c353", + ) as response: + assert not response.is_closed + assert response.http_request.headers.get("X-Stainless-Lang") == "python" + + idp_federation_grant = response.parse() + assert_matches_type(Optional[IdPFederationGrant], idp_federation_grant, path=["response"]) + + assert cast(Any, response.is_closed) is True + + @parametrize + def test_path_params_get(self, client: Cloudflare) -> None: + with pytest.raises(ValueError, match=r"Expected a non-empty value for `account_id` but received ''"): + client.zero_trust.access.idp_federation_grants.with_raw_response.get( + grant_id="023e105f4ecef8ad9ca31a8372d0c353", + account_id="", + ) + + with pytest.raises(ValueError, match=r"Expected a non-empty value for `grant_id` but received ''"): + client.zero_trust.access.idp_federation_grants.with_raw_response.get( + grant_id="", + account_id="023e105f4ecef8ad9ca31a8372d0c353", + ) + + +class TestAsyncIdPFederationGrants: + parametrize = pytest.mark.parametrize( + "async_client", [False, True, {"http_client": "aiohttp"}], indirect=True, ids=["loose", "strict", "aiohttp"] + ) + + @parametrize + async def test_method_create(self, async_client: AsyncCloudflare) -> None: + idp_federation_grant = await async_client.zero_trust.access.idp_federation_grants.create( + account_id="023e105f4ecef8ad9ca31a8372d0c353", + idp_id="a79de439-0e7f-4ebb-8a02-222222222222", + ) + assert_matches_type(Optional[IdPFederationGrant], idp_federation_grant, path=["response"]) + + @parametrize + async def test_raw_response_create(self, async_client: AsyncCloudflare) -> None: + response = await async_client.zero_trust.access.idp_federation_grants.with_raw_response.create( + account_id="023e105f4ecef8ad9ca31a8372d0c353", + idp_id="a79de439-0e7f-4ebb-8a02-222222222222", + ) + + assert response.is_closed is True + assert response.http_request.headers.get("X-Stainless-Lang") == "python" + idp_federation_grant = await response.parse() + assert_matches_type(Optional[IdPFederationGrant], idp_federation_grant, path=["response"]) + + @parametrize + async def test_streaming_response_create(self, async_client: AsyncCloudflare) -> None: + async with async_client.zero_trust.access.idp_federation_grants.with_streaming_response.create( + account_id="023e105f4ecef8ad9ca31a8372d0c353", + idp_id="a79de439-0e7f-4ebb-8a02-222222222222", + ) as response: + assert not response.is_closed + assert response.http_request.headers.get("X-Stainless-Lang") == "python" + + idp_federation_grant = await response.parse() + assert_matches_type(Optional[IdPFederationGrant], idp_federation_grant, path=["response"]) + + assert cast(Any, response.is_closed) is True + + @parametrize + async def test_path_params_create(self, async_client: AsyncCloudflare) -> None: + with pytest.raises(ValueError, match=r"Expected a non-empty value for `account_id` but received ''"): + await async_client.zero_trust.access.idp_federation_grants.with_raw_response.create( + account_id="", + idp_id="a79de439-0e7f-4ebb-8a02-222222222222", + ) + + @parametrize + async def test_method_list(self, async_client: AsyncCloudflare) -> None: + idp_federation_grant = await async_client.zero_trust.access.idp_federation_grants.list( + account_id="023e105f4ecef8ad9ca31a8372d0c353", + ) + assert_matches_type(Optional[IdPFederationGrantListResponse], idp_federation_grant, path=["response"]) + + @parametrize + async def test_raw_response_list(self, async_client: AsyncCloudflare) -> None: + response = await async_client.zero_trust.access.idp_federation_grants.with_raw_response.list( + account_id="023e105f4ecef8ad9ca31a8372d0c353", + ) + + assert response.is_closed is True + assert response.http_request.headers.get("X-Stainless-Lang") == "python" + idp_federation_grant = await response.parse() + assert_matches_type(Optional[IdPFederationGrantListResponse], idp_federation_grant, path=["response"]) + + @parametrize + async def test_streaming_response_list(self, async_client: AsyncCloudflare) -> None: + async with async_client.zero_trust.access.idp_federation_grants.with_streaming_response.list( + account_id="023e105f4ecef8ad9ca31a8372d0c353", + ) as response: + assert not response.is_closed + assert response.http_request.headers.get("X-Stainless-Lang") == "python" + + idp_federation_grant = await response.parse() + assert_matches_type(Optional[IdPFederationGrantListResponse], idp_federation_grant, path=["response"]) + + assert cast(Any, response.is_closed) is True + + @parametrize + async def test_path_params_list(self, async_client: AsyncCloudflare) -> None: + with pytest.raises(ValueError, match=r"Expected a non-empty value for `account_id` but received ''"): + await async_client.zero_trust.access.idp_federation_grants.with_raw_response.list( + account_id="", + ) + + @parametrize + async def test_method_delete(self, async_client: AsyncCloudflare) -> None: + idp_federation_grant = await async_client.zero_trust.access.idp_federation_grants.delete( + grant_id="023e105f4ecef8ad9ca31a8372d0c353", + account_id="023e105f4ecef8ad9ca31a8372d0c353", + ) + assert_matches_type(Optional[IdPFederationGrantDeleteResponse], idp_federation_grant, path=["response"]) + + @parametrize + async def test_raw_response_delete(self, async_client: AsyncCloudflare) -> None: + response = await async_client.zero_trust.access.idp_federation_grants.with_raw_response.delete( + grant_id="023e105f4ecef8ad9ca31a8372d0c353", + account_id="023e105f4ecef8ad9ca31a8372d0c353", + ) + + assert response.is_closed is True + assert response.http_request.headers.get("X-Stainless-Lang") == "python" + idp_federation_grant = await response.parse() + assert_matches_type(Optional[IdPFederationGrantDeleteResponse], idp_federation_grant, path=["response"]) + + @parametrize + async def test_streaming_response_delete(self, async_client: AsyncCloudflare) -> None: + async with async_client.zero_trust.access.idp_federation_grants.with_streaming_response.delete( + grant_id="023e105f4ecef8ad9ca31a8372d0c353", + account_id="023e105f4ecef8ad9ca31a8372d0c353", + ) as response: + assert not response.is_closed + assert response.http_request.headers.get("X-Stainless-Lang") == "python" + + idp_federation_grant = await response.parse() + assert_matches_type(Optional[IdPFederationGrantDeleteResponse], idp_federation_grant, path=["response"]) + + assert cast(Any, response.is_closed) is True + + @parametrize + async def test_path_params_delete(self, async_client: AsyncCloudflare) -> None: + with pytest.raises(ValueError, match=r"Expected a non-empty value for `account_id` but received ''"): + await async_client.zero_trust.access.idp_federation_grants.with_raw_response.delete( + grant_id="023e105f4ecef8ad9ca31a8372d0c353", + account_id="", + ) + + with pytest.raises(ValueError, match=r"Expected a non-empty value for `grant_id` but received ''"): + await async_client.zero_trust.access.idp_federation_grants.with_raw_response.delete( + grant_id="", + account_id="023e105f4ecef8ad9ca31a8372d0c353", + ) + + @parametrize + async def test_method_get(self, async_client: AsyncCloudflare) -> None: + idp_federation_grant = await async_client.zero_trust.access.idp_federation_grants.get( + grant_id="023e105f4ecef8ad9ca31a8372d0c353", + account_id="023e105f4ecef8ad9ca31a8372d0c353", + ) + assert_matches_type(Optional[IdPFederationGrant], idp_federation_grant, path=["response"]) + + @parametrize + async def test_raw_response_get(self, async_client: AsyncCloudflare) -> None: + response = await async_client.zero_trust.access.idp_federation_grants.with_raw_response.get( + grant_id="023e105f4ecef8ad9ca31a8372d0c353", + account_id="023e105f4ecef8ad9ca31a8372d0c353", + ) + + assert response.is_closed is True + assert response.http_request.headers.get("X-Stainless-Lang") == "python" + idp_federation_grant = await response.parse() + assert_matches_type(Optional[IdPFederationGrant], idp_federation_grant, path=["response"]) + + @parametrize + async def test_streaming_response_get(self, async_client: AsyncCloudflare) -> None: + async with async_client.zero_trust.access.idp_federation_grants.with_streaming_response.get( + grant_id="023e105f4ecef8ad9ca31a8372d0c353", + account_id="023e105f4ecef8ad9ca31a8372d0c353", + ) as response: + assert not response.is_closed + assert response.http_request.headers.get("X-Stainless-Lang") == "python" + + idp_federation_grant = await response.parse() + assert_matches_type(Optional[IdPFederationGrant], idp_federation_grant, path=["response"]) + + assert cast(Any, response.is_closed) is True + + @parametrize + async def test_path_params_get(self, async_client: AsyncCloudflare) -> None: + with pytest.raises(ValueError, match=r"Expected a non-empty value for `account_id` but received ''"): + await async_client.zero_trust.access.idp_federation_grants.with_raw_response.get( + grant_id="023e105f4ecef8ad9ca31a8372d0c353", + account_id="", + ) + + with pytest.raises(ValueError, match=r"Expected a non-empty value for `grant_id` but received ''"): + await async_client.zero_trust.access.idp_federation_grants.with_raw_response.get( + grant_id="", + account_id="023e105f4ecef8ad9ca31a8372d0c353", + ) diff --git a/tests/api_resources/zero_trust/dex/devices/__init__.py b/tests/api_resources/zero_trust/dex/devices/__init__.py new file mode 100644 index 00000000000..fd8019a9a1a --- /dev/null +++ b/tests/api_resources/zero_trust/dex/devices/__init__.py @@ -0,0 +1 @@ +# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. diff --git a/tests/api_resources/zero_trust/dex/devices/test_isps.py b/tests/api_resources/zero_trust/dex/devices/test_isps.py new file mode 100644 index 00000000000..85455da30ec --- /dev/null +++ b/tests/api_resources/zero_trust/dex/devices/test_isps.py @@ -0,0 +1,162 @@ +# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. + +from __future__ import annotations + +import os +from typing import Any, Optional, cast + +import pytest + +from cloudflare import Cloudflare, AsyncCloudflare +from tests.utils import assert_matches_type +from cloudflare._utils import parse_datetime +from cloudflare.pagination import SyncV4PagePagination, AsyncV4PagePagination +from cloudflare.types.zero_trust.dex.devices import ISPs + +base_url = os.environ.get("TEST_API_BASE_URL", "http://127.0.0.1:4010") + + +class TestISPs: + parametrize = pytest.mark.parametrize("client", [False, True], indirect=True, ids=["loose", "strict"]) + + @parametrize + def test_method_list(self, client: Cloudflare) -> None: + isp = client.zero_trust.dex.devices.isps.list( + device_id="f174e90a-fafe-4643-bbbc-4a0ed4fc8415", + account_id="01a7362d577a6c3019a474fd6f485823", + per_page=1, + ) + assert_matches_type(SyncV4PagePagination[Optional[ISPs]], isp, path=["response"]) + + @parametrize + def test_method_list_with_all_params(self, client: Cloudflare) -> None: + isp = client.zero_trust.dex.devices.isps.list( + device_id="f174e90a-fafe-4643-bbbc-4a0ed4fc8415", + account_id="01a7362d577a6c3019a474fd6f485823", + per_page=1, + cursor="cursor", + from_=parse_datetime("2019-12-27T18:11:19.117Z"), + page=1, + sort_by="time_start", + sort_order="ASC", + to=parse_datetime("2019-12-27T18:11:19.117Z"), + ) + assert_matches_type(SyncV4PagePagination[Optional[ISPs]], isp, path=["response"]) + + @parametrize + def test_raw_response_list(self, client: Cloudflare) -> None: + response = client.zero_trust.dex.devices.isps.with_raw_response.list( + device_id="f174e90a-fafe-4643-bbbc-4a0ed4fc8415", + account_id="01a7362d577a6c3019a474fd6f485823", + per_page=1, + ) + + assert response.is_closed is True + assert response.http_request.headers.get("X-Stainless-Lang") == "python" + isp = response.parse() + assert_matches_type(SyncV4PagePagination[Optional[ISPs]], isp, path=["response"]) + + @parametrize + def test_streaming_response_list(self, client: Cloudflare) -> None: + with client.zero_trust.dex.devices.isps.with_streaming_response.list( + device_id="f174e90a-fafe-4643-bbbc-4a0ed4fc8415", + account_id="01a7362d577a6c3019a474fd6f485823", + per_page=1, + ) as response: + assert not response.is_closed + assert response.http_request.headers.get("X-Stainless-Lang") == "python" + + isp = response.parse() + assert_matches_type(SyncV4PagePagination[Optional[ISPs]], isp, path=["response"]) + + assert cast(Any, response.is_closed) is True + + @parametrize + def test_path_params_list(self, client: Cloudflare) -> None: + with pytest.raises(ValueError, match=r"Expected a non-empty value for `account_id` but received ''"): + client.zero_trust.dex.devices.isps.with_raw_response.list( + device_id="f174e90a-fafe-4643-bbbc-4a0ed4fc8415", + account_id="", + per_page=1, + ) + + with pytest.raises(ValueError, match=r"Expected a non-empty value for `device_id` but received ''"): + client.zero_trust.dex.devices.isps.with_raw_response.list( + device_id="", + account_id="01a7362d577a6c3019a474fd6f485823", + per_page=1, + ) + + +class TestAsyncISPs: + parametrize = pytest.mark.parametrize( + "async_client", [False, True, {"http_client": "aiohttp"}], indirect=True, ids=["loose", "strict", "aiohttp"] + ) + + @parametrize + async def test_method_list(self, async_client: AsyncCloudflare) -> None: + isp = await async_client.zero_trust.dex.devices.isps.list( + device_id="f174e90a-fafe-4643-bbbc-4a0ed4fc8415", + account_id="01a7362d577a6c3019a474fd6f485823", + per_page=1, + ) + assert_matches_type(AsyncV4PagePagination[Optional[ISPs]], isp, path=["response"]) + + @parametrize + async def test_method_list_with_all_params(self, async_client: AsyncCloudflare) -> None: + isp = await async_client.zero_trust.dex.devices.isps.list( + device_id="f174e90a-fafe-4643-bbbc-4a0ed4fc8415", + account_id="01a7362d577a6c3019a474fd6f485823", + per_page=1, + cursor="cursor", + from_=parse_datetime("2019-12-27T18:11:19.117Z"), + page=1, + sort_by="time_start", + sort_order="ASC", + to=parse_datetime("2019-12-27T18:11:19.117Z"), + ) + assert_matches_type(AsyncV4PagePagination[Optional[ISPs]], isp, path=["response"]) + + @parametrize + async def test_raw_response_list(self, async_client: AsyncCloudflare) -> None: + response = await async_client.zero_trust.dex.devices.isps.with_raw_response.list( + device_id="f174e90a-fafe-4643-bbbc-4a0ed4fc8415", + account_id="01a7362d577a6c3019a474fd6f485823", + per_page=1, + ) + + assert response.is_closed is True + assert response.http_request.headers.get("X-Stainless-Lang") == "python" + isp = await response.parse() + assert_matches_type(AsyncV4PagePagination[Optional[ISPs]], isp, path=["response"]) + + @parametrize + async def test_streaming_response_list(self, async_client: AsyncCloudflare) -> None: + async with async_client.zero_trust.dex.devices.isps.with_streaming_response.list( + device_id="f174e90a-fafe-4643-bbbc-4a0ed4fc8415", + account_id="01a7362d577a6c3019a474fd6f485823", + per_page=1, + ) as response: + assert not response.is_closed + assert response.http_request.headers.get("X-Stainless-Lang") == "python" + + isp = await response.parse() + assert_matches_type(AsyncV4PagePagination[Optional[ISPs]], isp, path=["response"]) + + assert cast(Any, response.is_closed) is True + + @parametrize + async def test_path_params_list(self, async_client: AsyncCloudflare) -> None: + with pytest.raises(ValueError, match=r"Expected a non-empty value for `account_id` but received ''"): + await async_client.zero_trust.dex.devices.isps.with_raw_response.list( + device_id="f174e90a-fafe-4643-bbbc-4a0ed4fc8415", + account_id="", + per_page=1, + ) + + with pytest.raises(ValueError, match=r"Expected a non-empty value for `device_id` but received ''"): + await async_client.zero_trust.dex.devices.isps.with_raw_response.list( + device_id="", + account_id="01a7362d577a6c3019a474fd6f485823", + per_page=1, + )