diff --git a/.stats.yml b/.stats.yml
index ff2efbe667d..21c949824d8 100644
--- a/.stats.yml
+++ b/.stats.yml
@@ -1,2 +1,2 @@
-configured_endpoints: 1343
+configured_endpoints: 1352
openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/cloudflare%2Fcloudflare-e3875d4464358c7aee5cbb9a4e0e39f0e400536dfadb684e8f217a2800897d0e.yml
diff --git a/api.md b/api.md
index 0fcdd96ea84..d3993e81805 100644
--- a/api.md
+++ b/api.md
@@ -3131,6 +3131,7 @@ Types:
```python
from cloudflare.types.page_shield import (
+ Policy,
PolicyCreateResponse,
PolicyUpdateResponse,
PolicyListResponse,
@@ -3172,6 +3173,19 @@ Methods:
- client.page_shield.scripts.list(\*, zone_id, \*\*params) -> SyncSinglePage[Script]
- client.page_shield.scripts.get(script_id, \*, zone_id) -> Optional
+## Cookies
+
+Types:
+
+```python
+from cloudflare.types.page_shield import CookieListResponse, CookieGetResponse
+```
+
+Methods:
+
+- client.page_shield.cookies.list(\*, zone_id, \*\*params) -> SyncSinglePage[CookieListResponse]
+- client.page_shield.cookies.get(cookie_id, \*, zone_id) -> Optional
+
# Rulesets
Types:
@@ -7882,3 +7896,40 @@ from cloudflare.types.ai_gateway import LogGetResponse
Methods:
- client.ai_gateway.logs.get(id, \*, account_id, \*\*params) -> LogGetResponse
+
+# Iam
+
+## PermissionGroups
+
+Types:
+
+```python
+from cloudflare.types.iam import PermissionGroupListResponse, PermissionGroupGetResponse
+```
+
+Methods:
+
+- client.iam.permission_groups.list(\*, account_id, \*\*params) -> SyncV4PagePaginationArray[object]
+- client.iam.permission_groups.get(permission_group_id, \*, account_id) -> PermissionGroupGetResponse
+
+## ResourceGroups
+
+Types:
+
+```python
+from cloudflare.types.iam import (
+ ResourceGroupCreateResponse,
+ ResourceGroupUpdateResponse,
+ ResourceGroupListResponse,
+ ResourceGroupDeleteResponse,
+ ResourceGroupGetResponse,
+)
+```
+
+Methods:
+
+- client.iam.resource_groups.create(\*, account_id, \*\*params) -> ResourceGroupCreateResponse
+- client.iam.resource_groups.update(resource_group_id, \*, account_id, \*\*params) -> ResourceGroupUpdateResponse
+- client.iam.resource_groups.list(\*, account_id, \*\*params) -> SyncV4PagePaginationArray[object]
+- client.iam.resource_groups.delete(resource_group_id, \*, account_id) -> Optional
+- client.iam.resource_groups.get(resource_group_id, \*, account_id) -> ResourceGroupGetResponse
diff --git a/src/cloudflare/_client.py b/src/cloudflare/_client.py
index c31dee6829f..1c536763963 100644
--- a/src/cloudflare/_client.py
+++ b/src/cloudflare/_client.py
@@ -130,6 +130,7 @@ class Cloudflare(SyncAPIClient):
cloudforce_one: resources.CloudforceOneResource
event_notifications: resources.EventNotificationsResource
ai_gateway: resources.AIGatewayResource
+ iam: resources.IamResource
with_raw_response: CloudflareWithRawResponse
with_streaming_response: CloudflareWithStreamedResponse
@@ -288,6 +289,7 @@ def __init__(
self.cloudforce_one = resources.CloudforceOneResource(self)
self.event_notifications = resources.EventNotificationsResource(self)
self.ai_gateway = resources.AIGatewayResource(self)
+ self.iam = resources.IamResource(self)
self.with_raw_response = CloudflareWithRawResponse(self)
self.with_streaming_response = CloudflareWithStreamedResponse(self)
@@ -549,6 +551,7 @@ class AsyncCloudflare(AsyncAPIClient):
cloudforce_one: resources.AsyncCloudforceOneResource
event_notifications: resources.AsyncEventNotificationsResource
ai_gateway: resources.AsyncAIGatewayResource
+ iam: resources.AsyncIamResource
with_raw_response: AsyncCloudflareWithRawResponse
with_streaming_response: AsyncCloudflareWithStreamedResponse
@@ -707,6 +710,7 @@ def __init__(
self.cloudforce_one = resources.AsyncCloudforceOneResource(self)
self.event_notifications = resources.AsyncEventNotificationsResource(self)
self.ai_gateway = resources.AsyncAIGatewayResource(self)
+ self.iam = resources.AsyncIamResource(self)
self.with_raw_response = AsyncCloudflareWithRawResponse(self)
self.with_streaming_response = AsyncCloudflareWithStreamedResponse(self)
@@ -979,6 +983,7 @@ def __init__(self, client: Cloudflare) -> None:
self.cloudforce_one = resources.CloudforceOneResourceWithRawResponse(client.cloudforce_one)
self.event_notifications = resources.EventNotificationsResourceWithRawResponse(client.event_notifications)
self.ai_gateway = resources.AIGatewayResourceWithRawResponse(client.ai_gateway)
+ self.iam = resources.IamResourceWithRawResponse(client.iam)
class AsyncCloudflareWithRawResponse:
@@ -1080,6 +1085,7 @@ def __init__(self, client: AsyncCloudflare) -> None:
self.cloudforce_one = resources.AsyncCloudforceOneResourceWithRawResponse(client.cloudforce_one)
self.event_notifications = resources.AsyncEventNotificationsResourceWithRawResponse(client.event_notifications)
self.ai_gateway = resources.AsyncAIGatewayResourceWithRawResponse(client.ai_gateway)
+ self.iam = resources.AsyncIamResourceWithRawResponse(client.iam)
class CloudflareWithStreamedResponse:
@@ -1181,6 +1187,7 @@ def __init__(self, client: Cloudflare) -> None:
self.cloudforce_one = resources.CloudforceOneResourceWithStreamingResponse(client.cloudforce_one)
self.event_notifications = resources.EventNotificationsResourceWithStreamingResponse(client.event_notifications)
self.ai_gateway = resources.AIGatewayResourceWithStreamingResponse(client.ai_gateway)
+ self.iam = resources.IamResourceWithStreamingResponse(client.iam)
class AsyncCloudflareWithStreamedResponse:
@@ -1290,6 +1297,7 @@ def __init__(self, client: AsyncCloudflare) -> None:
client.event_notifications
)
self.ai_gateway = resources.AsyncAIGatewayResourceWithStreamingResponse(client.ai_gateway)
+ self.iam = resources.AsyncIamResourceWithStreamingResponse(client.iam)
Client = Cloudflare
diff --git a/src/cloudflare/resources/__init__.py b/src/cloudflare/resources/__init__.py
index 5eacc4bdd5c..e5fa7b69add 100644
--- a/src/cloudflare/resources/__init__.py
+++ b/src/cloudflare/resources/__init__.py
@@ -40,6 +40,14 @@
DNSResourceWithStreamingResponse,
AsyncDNSResourceWithStreamingResponse,
)
+from .iam import (
+ IamResource,
+ AsyncIamResource,
+ IamResourceWithRawResponse,
+ AsyncIamResourceWithRawResponse,
+ IamResourceWithStreamingResponse,
+ AsyncIamResourceWithStreamingResponse,
+)
from .ips import (
IPsResource,
AsyncIPsResource,
@@ -1164,4 +1172,10 @@
"AsyncAIGatewayResourceWithRawResponse",
"AIGatewayResourceWithStreamingResponse",
"AsyncAIGatewayResourceWithStreamingResponse",
+ "IamResource",
+ "AsyncIamResource",
+ "IamResourceWithRawResponse",
+ "AsyncIamResourceWithRawResponse",
+ "IamResourceWithStreamingResponse",
+ "AsyncIamResourceWithStreamingResponse",
]
diff --git a/src/cloudflare/resources/iam/__init__.py b/src/cloudflare/resources/iam/__init__.py
new file mode 100644
index 00000000000..0384bf2c0e0
--- /dev/null
+++ b/src/cloudflare/resources/iam/__init__.py
@@ -0,0 +1,47 @@
+# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details.
+
+from .iam import (
+ IamResource,
+ AsyncIamResource,
+ IamResourceWithRawResponse,
+ AsyncIamResourceWithRawResponse,
+ IamResourceWithStreamingResponse,
+ AsyncIamResourceWithStreamingResponse,
+)
+from .resource_groups import (
+ ResourceGroupsResource,
+ AsyncResourceGroupsResource,
+ ResourceGroupsResourceWithRawResponse,
+ AsyncResourceGroupsResourceWithRawResponse,
+ ResourceGroupsResourceWithStreamingResponse,
+ AsyncResourceGroupsResourceWithStreamingResponse,
+)
+from .permission_groups import (
+ PermissionGroupsResource,
+ AsyncPermissionGroupsResource,
+ PermissionGroupsResourceWithRawResponse,
+ AsyncPermissionGroupsResourceWithRawResponse,
+ PermissionGroupsResourceWithStreamingResponse,
+ AsyncPermissionGroupsResourceWithStreamingResponse,
+)
+
+__all__ = [
+ "PermissionGroupsResource",
+ "AsyncPermissionGroupsResource",
+ "PermissionGroupsResourceWithRawResponse",
+ "AsyncPermissionGroupsResourceWithRawResponse",
+ "PermissionGroupsResourceWithStreamingResponse",
+ "AsyncPermissionGroupsResourceWithStreamingResponse",
+ "ResourceGroupsResource",
+ "AsyncResourceGroupsResource",
+ "ResourceGroupsResourceWithRawResponse",
+ "AsyncResourceGroupsResourceWithRawResponse",
+ "ResourceGroupsResourceWithStreamingResponse",
+ "AsyncResourceGroupsResourceWithStreamingResponse",
+ "IamResource",
+ "AsyncIamResource",
+ "IamResourceWithRawResponse",
+ "AsyncIamResourceWithRawResponse",
+ "IamResourceWithStreamingResponse",
+ "AsyncIamResourceWithStreamingResponse",
+]
diff --git a/src/cloudflare/resources/iam/iam.py b/src/cloudflare/resources/iam/iam.py
new file mode 100644
index 00000000000..ec7756d7f63
--- /dev/null
+++ b/src/cloudflare/resources/iam/iam.py
@@ -0,0 +1,112 @@
+# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details.
+
+from __future__ import annotations
+
+from ..._compat import cached_property
+from ..._resource import SyncAPIResource, AsyncAPIResource
+from .resource_groups import (
+ ResourceGroupsResource,
+ AsyncResourceGroupsResource,
+ ResourceGroupsResourceWithRawResponse,
+ AsyncResourceGroupsResourceWithRawResponse,
+ ResourceGroupsResourceWithStreamingResponse,
+ AsyncResourceGroupsResourceWithStreamingResponse,
+)
+from .permission_groups import (
+ PermissionGroupsResource,
+ AsyncPermissionGroupsResource,
+ PermissionGroupsResourceWithRawResponse,
+ AsyncPermissionGroupsResourceWithRawResponse,
+ PermissionGroupsResourceWithStreamingResponse,
+ AsyncPermissionGroupsResourceWithStreamingResponse,
+)
+
+__all__ = ["IamResource", "AsyncIamResource"]
+
+
+class IamResource(SyncAPIResource):
+ @cached_property
+ def permission_groups(self) -> PermissionGroupsResource:
+ return PermissionGroupsResource(self._client)
+
+ @cached_property
+ def resource_groups(self) -> ResourceGroupsResource:
+ return ResourceGroupsResource(self._client)
+
+ @cached_property
+ def with_raw_response(self) -> IamResourceWithRawResponse:
+ return IamResourceWithRawResponse(self)
+
+ @cached_property
+ def with_streaming_response(self) -> IamResourceWithStreamingResponse:
+ return IamResourceWithStreamingResponse(self)
+
+
+class AsyncIamResource(AsyncAPIResource):
+ @cached_property
+ def permission_groups(self) -> AsyncPermissionGroupsResource:
+ return AsyncPermissionGroupsResource(self._client)
+
+ @cached_property
+ def resource_groups(self) -> AsyncResourceGroupsResource:
+ return AsyncResourceGroupsResource(self._client)
+
+ @cached_property
+ def with_raw_response(self) -> AsyncIamResourceWithRawResponse:
+ return AsyncIamResourceWithRawResponse(self)
+
+ @cached_property
+ def with_streaming_response(self) -> AsyncIamResourceWithStreamingResponse:
+ return AsyncIamResourceWithStreamingResponse(self)
+
+
+class IamResourceWithRawResponse:
+ def __init__(self, iam: IamResource) -> None:
+ self._iam = iam
+
+ @cached_property
+ def permission_groups(self) -> PermissionGroupsResourceWithRawResponse:
+ return PermissionGroupsResourceWithRawResponse(self._iam.permission_groups)
+
+ @cached_property
+ def resource_groups(self) -> ResourceGroupsResourceWithRawResponse:
+ return ResourceGroupsResourceWithRawResponse(self._iam.resource_groups)
+
+
+class AsyncIamResourceWithRawResponse:
+ def __init__(self, iam: AsyncIamResource) -> None:
+ self._iam = iam
+
+ @cached_property
+ def permission_groups(self) -> AsyncPermissionGroupsResourceWithRawResponse:
+ return AsyncPermissionGroupsResourceWithRawResponse(self._iam.permission_groups)
+
+ @cached_property
+ def resource_groups(self) -> AsyncResourceGroupsResourceWithRawResponse:
+ return AsyncResourceGroupsResourceWithRawResponse(self._iam.resource_groups)
+
+
+class IamResourceWithStreamingResponse:
+ def __init__(self, iam: IamResource) -> None:
+ self._iam = iam
+
+ @cached_property
+ def permission_groups(self) -> PermissionGroupsResourceWithStreamingResponse:
+ return PermissionGroupsResourceWithStreamingResponse(self._iam.permission_groups)
+
+ @cached_property
+ def resource_groups(self) -> ResourceGroupsResourceWithStreamingResponse:
+ return ResourceGroupsResourceWithStreamingResponse(self._iam.resource_groups)
+
+
+class AsyncIamResourceWithStreamingResponse:
+ def __init__(self, iam: AsyncIamResource) -> None:
+ self._iam = iam
+
+ @cached_property
+ def permission_groups(self) -> AsyncPermissionGroupsResourceWithStreamingResponse:
+ return AsyncPermissionGroupsResourceWithStreamingResponse(self._iam.permission_groups)
+
+ @cached_property
+ def resource_groups(self) -> AsyncResourceGroupsResourceWithStreamingResponse:
+ return AsyncResourceGroupsResourceWithStreamingResponse(self._iam.resource_groups)
diff --git a/src/cloudflare/resources/iam/permission_groups.py b/src/cloudflare/resources/iam/permission_groups.py
new file mode 100644
index 00000000000..1bb7effc98d
--- /dev/null
+++ b/src/cloudflare/resources/iam/permission_groups.py
@@ -0,0 +1,305 @@
+# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details.
+
+from __future__ import annotations
+
+import httpx
+
+from ..._types import NOT_GIVEN, Body, Query, Headers, NotGiven
+from ..._utils import maybe_transform
+from ..._compat import cached_property
+from ..._resource import SyncAPIResource, AsyncAPIResource
+from ..._response import (
+ to_raw_response_wrapper,
+ to_streamed_response_wrapper,
+ async_to_raw_response_wrapper,
+ async_to_streamed_response_wrapper,
+)
+from ...types.iam import permission_group_list_params
+from ...pagination import SyncV4PagePaginationArray, AsyncV4PagePaginationArray
+from ..._base_client import (
+ AsyncPaginator,
+ make_request_options,
+)
+from ...types.iam.permission_group_get_response import PermissionGroupGetResponse
+
+__all__ = ["PermissionGroupsResource", "AsyncPermissionGroupsResource"]
+
+
+class PermissionGroupsResource(SyncAPIResource):
+ @cached_property
+ def with_raw_response(self) -> PermissionGroupsResourceWithRawResponse:
+ return PermissionGroupsResourceWithRawResponse(self)
+
+ @cached_property
+ def with_streaming_response(self) -> PermissionGroupsResourceWithStreamingResponse:
+ return PermissionGroupsResourceWithStreamingResponse(self)
+
+ def list(
+ self,
+ *,
+ account_id: str,
+ id: str | NotGiven = NOT_GIVEN,
+ label: str | NotGiven = NOT_GIVEN,
+ name: str | NotGiven = NOT_GIVEN,
+ page: float | NotGiven = NOT_GIVEN,
+ per_page: float | NotGiven = NOT_GIVEN,
+ # Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs.
+ # The extra values given here take precedence over values defined on the client or passed to this method.
+ extra_headers: Headers | None = None,
+ extra_query: Query | None = None,
+ extra_body: Body | None = None,
+ timeout: float | httpx.Timeout | None | NotGiven = NOT_GIVEN,
+ ) -> SyncV4PagePaginationArray[object]:
+ """
+ List all the permissions groups for an account.
+
+ Args:
+ account_id: Account identifier tag.
+
+ id: ID of the permission group to be fetched.
+
+ label: Label of the permission group to be fetched.
+
+ name: Name of the permission group to be fetched.
+
+ page: Page number of paginated results.
+
+ per_page: Maximum number of results per page.
+
+ 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_api_list(
+ f"/accounts/{account_id}/iam/permission_groups",
+ page=SyncV4PagePaginationArray[object],
+ options=make_request_options(
+ extra_headers=extra_headers,
+ extra_query=extra_query,
+ extra_body=extra_body,
+ timeout=timeout,
+ query=maybe_transform(
+ {
+ "id": id,
+ "label": label,
+ "name": name,
+ "page": page,
+ "per_page": per_page,
+ },
+ permission_group_list_params.PermissionGroupListParams,
+ ),
+ ),
+ model=object,
+ )
+
+ def get(
+ self,
+ permission_group_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,
+ ) -> PermissionGroupGetResponse:
+ """
+ Get information about a specific permission group in an account.
+
+ Args:
+ account_id: Account identifier tag.
+
+ permission_group_id: Permission Group identifier tag.
+
+ 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 permission_group_id:
+ raise ValueError(
+ f"Expected a non-empty value for `permission_group_id` but received {permission_group_id!r}"
+ )
+ return self._get(
+ f"/accounts/{account_id}/iam/permission_groups/{permission_group_id}",
+ options=make_request_options(
+ extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout
+ ),
+ cast_to=PermissionGroupGetResponse,
+ )
+
+
+class AsyncPermissionGroupsResource(AsyncAPIResource):
+ @cached_property
+ def with_raw_response(self) -> AsyncPermissionGroupsResourceWithRawResponse:
+ return AsyncPermissionGroupsResourceWithRawResponse(self)
+
+ @cached_property
+ def with_streaming_response(self) -> AsyncPermissionGroupsResourceWithStreamingResponse:
+ return AsyncPermissionGroupsResourceWithStreamingResponse(self)
+
+ def list(
+ self,
+ *,
+ account_id: str,
+ id: str | NotGiven = NOT_GIVEN,
+ label: str | NotGiven = NOT_GIVEN,
+ name: str | NotGiven = NOT_GIVEN,
+ page: float | NotGiven = NOT_GIVEN,
+ per_page: float | NotGiven = NOT_GIVEN,
+ # Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs.
+ # The extra values given here take precedence over values defined on the client or passed to this method.
+ extra_headers: Headers | None = None,
+ extra_query: Query | None = None,
+ extra_body: Body | None = None,
+ timeout: float | httpx.Timeout | None | NotGiven = NOT_GIVEN,
+ ) -> AsyncPaginator[object, AsyncV4PagePaginationArray[object]]:
+ """
+ List all the permissions groups for an account.
+
+ Args:
+ account_id: Account identifier tag.
+
+ id: ID of the permission group to be fetched.
+
+ label: Label of the permission group to be fetched.
+
+ name: Name of the permission group to be fetched.
+
+ page: Page number of paginated results.
+
+ per_page: Maximum number of results per page.
+
+ 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_api_list(
+ f"/accounts/{account_id}/iam/permission_groups",
+ page=AsyncV4PagePaginationArray[object],
+ options=make_request_options(
+ extra_headers=extra_headers,
+ extra_query=extra_query,
+ extra_body=extra_body,
+ timeout=timeout,
+ query=maybe_transform(
+ {
+ "id": id,
+ "label": label,
+ "name": name,
+ "page": page,
+ "per_page": per_page,
+ },
+ permission_group_list_params.PermissionGroupListParams,
+ ),
+ ),
+ model=object,
+ )
+
+ async def get(
+ self,
+ permission_group_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,
+ ) -> PermissionGroupGetResponse:
+ """
+ Get information about a specific permission group in an account.
+
+ Args:
+ account_id: Account identifier tag.
+
+ permission_group_id: Permission Group identifier tag.
+
+ 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 permission_group_id:
+ raise ValueError(
+ f"Expected a non-empty value for `permission_group_id` but received {permission_group_id!r}"
+ )
+ return await self._get(
+ f"/accounts/{account_id}/iam/permission_groups/{permission_group_id}",
+ options=make_request_options(
+ extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout
+ ),
+ cast_to=PermissionGroupGetResponse,
+ )
+
+
+class PermissionGroupsResourceWithRawResponse:
+ def __init__(self, permission_groups: PermissionGroupsResource) -> None:
+ self._permission_groups = permission_groups
+
+ self.list = to_raw_response_wrapper(
+ permission_groups.list,
+ )
+ self.get = to_raw_response_wrapper(
+ permission_groups.get,
+ )
+
+
+class AsyncPermissionGroupsResourceWithRawResponse:
+ def __init__(self, permission_groups: AsyncPermissionGroupsResource) -> None:
+ self._permission_groups = permission_groups
+
+ self.list = async_to_raw_response_wrapper(
+ permission_groups.list,
+ )
+ self.get = async_to_raw_response_wrapper(
+ permission_groups.get,
+ )
+
+
+class PermissionGroupsResourceWithStreamingResponse:
+ def __init__(self, permission_groups: PermissionGroupsResource) -> None:
+ self._permission_groups = permission_groups
+
+ self.list = to_streamed_response_wrapper(
+ permission_groups.list,
+ )
+ self.get = to_streamed_response_wrapper(
+ permission_groups.get,
+ )
+
+
+class AsyncPermissionGroupsResourceWithStreamingResponse:
+ def __init__(self, permission_groups: AsyncPermissionGroupsResource) -> None:
+ self._permission_groups = permission_groups
+
+ self.list = async_to_streamed_response_wrapper(
+ permission_groups.list,
+ )
+ self.get = async_to_streamed_response_wrapper(
+ permission_groups.get,
+ )
diff --git a/src/cloudflare/resources/iam/resource_groups.py b/src/cloudflare/resources/iam/resource_groups.py
new file mode 100644
index 00000000000..9d524bcea8e
--- /dev/null
+++ b/src/cloudflare/resources/iam/resource_groups.py
@@ -0,0 +1,628 @@
+# 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 NOT_GIVEN, Body, Query, Headers, NotGiven
+from ..._utils import (
+ 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 ...types.iam import resource_group_list_params, resource_group_create_params, resource_group_update_params
+from ...pagination import SyncV4PagePaginationArray, AsyncV4PagePaginationArray
+from ..._base_client import (
+ AsyncPaginator,
+ make_request_options,
+)
+from ...types.iam.resource_group_get_response import ResourceGroupGetResponse
+from ...types.iam.resource_group_create_response import ResourceGroupCreateResponse
+from ...types.iam.resource_group_delete_response import ResourceGroupDeleteResponse
+from ...types.iam.resource_group_update_response import ResourceGroupUpdateResponse
+
+__all__ = ["ResourceGroupsResource", "AsyncResourceGroupsResource"]
+
+
+class ResourceGroupsResource(SyncAPIResource):
+ @cached_property
+ def with_raw_response(self) -> ResourceGroupsResourceWithRawResponse:
+ return ResourceGroupsResourceWithRawResponse(self)
+
+ @cached_property
+ def with_streaming_response(self) -> ResourceGroupsResourceWithStreamingResponse:
+ return ResourceGroupsResourceWithStreamingResponse(self)
+
+ def create(
+ self,
+ *,
+ account_id: str,
+ scope: resource_group_create_params.Scope,
+ meta: object | NotGiven = NOT_GIVEN,
+ # Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs.
+ # The extra values given here take precedence over values defined on the client or passed to this method.
+ extra_headers: Headers | None = None,
+ extra_query: Query | None = None,
+ extra_body: Body | None = None,
+ timeout: float | httpx.Timeout | None | NotGiven = NOT_GIVEN,
+ ) -> ResourceGroupCreateResponse:
+ """
+ Create a new Resource Group under the specified account.
+
+ Args:
+ account_id: Account identifier tag.
+
+ scope: A scope is a combination of scope objects which provides additional context.
+
+ meta: Attributes associated to the resource group.
+
+ 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(
+ f"/accounts/{account_id}/iam/resource_groups",
+ body=maybe_transform(
+ {
+ "scope": scope,
+ "meta": meta,
+ },
+ resource_group_create_params.ResourceGroupCreateParams,
+ ),
+ options=make_request_options(
+ extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout
+ ),
+ cast_to=ResourceGroupCreateResponse,
+ )
+
+ def update(
+ self,
+ resource_group_id: str,
+ *,
+ account_id: str,
+ scope: resource_group_update_params.Scope,
+ meta: object | NotGiven = NOT_GIVEN,
+ # Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs.
+ # The extra values given here take precedence over values defined on the client or passed to this method.
+ extra_headers: Headers | None = None,
+ extra_query: Query | None = None,
+ extra_body: Body | None = None,
+ timeout: float | httpx.Timeout | None | NotGiven = NOT_GIVEN,
+ ) -> ResourceGroupUpdateResponse:
+ """
+ Modify an existing resource group.
+
+ Args:
+ account_id: Account identifier tag.
+
+ resource_group_id: Resource Group identifier tag.
+
+ scope: A scope is a combination of scope objects which provides additional context.
+
+ meta: Attributes associated to the resource group.
+
+ 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 resource_group_id:
+ raise ValueError(f"Expected a non-empty value for `resource_group_id` but received {resource_group_id!r}")
+ return self._put(
+ f"/accounts/{account_id}/iam/resource_groups/{resource_group_id}",
+ body=maybe_transform(
+ {
+ "scope": scope,
+ "meta": meta,
+ },
+ resource_group_update_params.ResourceGroupUpdateParams,
+ ),
+ options=make_request_options(
+ extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout
+ ),
+ cast_to=ResourceGroupUpdateResponse,
+ )
+
+ def list(
+ self,
+ *,
+ account_id: str,
+ id: str | NotGiven = NOT_GIVEN,
+ name: str | NotGiven = NOT_GIVEN,
+ page: float | NotGiven = NOT_GIVEN,
+ per_page: float | NotGiven = NOT_GIVEN,
+ # Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs.
+ # The extra values given here take precedence over values defined on the client or passed to this method.
+ extra_headers: Headers | None = None,
+ extra_query: Query | None = None,
+ extra_body: Body | None = None,
+ timeout: float | httpx.Timeout | None | NotGiven = NOT_GIVEN,
+ ) -> SyncV4PagePaginationArray[object]:
+ """
+ List all the resource groups for an account.
+
+ Args:
+ account_id: Account identifier tag.
+
+ id: ID of the resource group to be fetched.
+
+ name: Name of the resource group to be fetched.
+
+ page: Page number of paginated results.
+
+ per_page: Maximum number of results per page.
+
+ 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_api_list(
+ f"/accounts/{account_id}/iam/resource_groups",
+ page=SyncV4PagePaginationArray[object],
+ options=make_request_options(
+ extra_headers=extra_headers,
+ extra_query=extra_query,
+ extra_body=extra_body,
+ timeout=timeout,
+ query=maybe_transform(
+ {
+ "id": id,
+ "name": name,
+ "page": page,
+ "per_page": per_page,
+ },
+ resource_group_list_params.ResourceGroupListParams,
+ ),
+ ),
+ model=object,
+ )
+
+ def delete(
+ self,
+ resource_group_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[ResourceGroupDeleteResponse]:
+ """
+ Remove a resource group from an account.
+
+ Args:
+ account_id: Account identifier tag.
+
+ resource_group_id: Resource Group identifier tag.
+
+ 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 resource_group_id:
+ raise ValueError(f"Expected a non-empty value for `resource_group_id` but received {resource_group_id!r}")
+ return self._delete(
+ f"/accounts/{account_id}/iam/resource_groups/{resource_group_id}",
+ options=make_request_options(
+ extra_headers=extra_headers,
+ extra_query=extra_query,
+ extra_body=extra_body,
+ timeout=timeout,
+ post_parser=ResultWrapper[Optional[ResourceGroupDeleteResponse]]._unwrapper,
+ ),
+ cast_to=cast(Type[Optional[ResourceGroupDeleteResponse]], ResultWrapper[ResourceGroupDeleteResponse]),
+ )
+
+ def get(
+ self,
+ resource_group_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,
+ ) -> ResourceGroupGetResponse:
+ """
+ Get information about a specific resource group in an account.
+
+ Args:
+ account_id: Account identifier tag.
+
+ resource_group_id: Resource Group identifier tag.
+
+ 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 resource_group_id:
+ raise ValueError(f"Expected a non-empty value for `resource_group_id` but received {resource_group_id!r}")
+ return self._get(
+ f"/accounts/{account_id}/iam/resource_groups/{resource_group_id}",
+ options=make_request_options(
+ extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout
+ ),
+ cast_to=ResourceGroupGetResponse,
+ )
+
+
+class AsyncResourceGroupsResource(AsyncAPIResource):
+ @cached_property
+ def with_raw_response(self) -> AsyncResourceGroupsResourceWithRawResponse:
+ return AsyncResourceGroupsResourceWithRawResponse(self)
+
+ @cached_property
+ def with_streaming_response(self) -> AsyncResourceGroupsResourceWithStreamingResponse:
+ return AsyncResourceGroupsResourceWithStreamingResponse(self)
+
+ async def create(
+ self,
+ *,
+ account_id: str,
+ scope: resource_group_create_params.Scope,
+ meta: object | NotGiven = NOT_GIVEN,
+ # Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs.
+ # The extra values given here take precedence over values defined on the client or passed to this method.
+ extra_headers: Headers | None = None,
+ extra_query: Query | None = None,
+ extra_body: Body | None = None,
+ timeout: float | httpx.Timeout | None | NotGiven = NOT_GIVEN,
+ ) -> ResourceGroupCreateResponse:
+ """
+ Create a new Resource Group under the specified account.
+
+ Args:
+ account_id: Account identifier tag.
+
+ scope: A scope is a combination of scope objects which provides additional context.
+
+ meta: Attributes associated to the resource group.
+
+ 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(
+ f"/accounts/{account_id}/iam/resource_groups",
+ body=await async_maybe_transform(
+ {
+ "scope": scope,
+ "meta": meta,
+ },
+ resource_group_create_params.ResourceGroupCreateParams,
+ ),
+ options=make_request_options(
+ extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout
+ ),
+ cast_to=ResourceGroupCreateResponse,
+ )
+
+ async def update(
+ self,
+ resource_group_id: str,
+ *,
+ account_id: str,
+ scope: resource_group_update_params.Scope,
+ meta: object | NotGiven = NOT_GIVEN,
+ # Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs.
+ # The extra values given here take precedence over values defined on the client or passed to this method.
+ extra_headers: Headers | None = None,
+ extra_query: Query | None = None,
+ extra_body: Body | None = None,
+ timeout: float | httpx.Timeout | None | NotGiven = NOT_GIVEN,
+ ) -> ResourceGroupUpdateResponse:
+ """
+ Modify an existing resource group.
+
+ Args:
+ account_id: Account identifier tag.
+
+ resource_group_id: Resource Group identifier tag.
+
+ scope: A scope is a combination of scope objects which provides additional context.
+
+ meta: Attributes associated to the resource group.
+
+ 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 resource_group_id:
+ raise ValueError(f"Expected a non-empty value for `resource_group_id` but received {resource_group_id!r}")
+ return await self._put(
+ f"/accounts/{account_id}/iam/resource_groups/{resource_group_id}",
+ body=await async_maybe_transform(
+ {
+ "scope": scope,
+ "meta": meta,
+ },
+ resource_group_update_params.ResourceGroupUpdateParams,
+ ),
+ options=make_request_options(
+ extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout
+ ),
+ cast_to=ResourceGroupUpdateResponse,
+ )
+
+ def list(
+ self,
+ *,
+ account_id: str,
+ id: str | NotGiven = NOT_GIVEN,
+ name: str | NotGiven = NOT_GIVEN,
+ page: float | NotGiven = NOT_GIVEN,
+ per_page: float | NotGiven = NOT_GIVEN,
+ # Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs.
+ # The extra values given here take precedence over values defined on the client or passed to this method.
+ extra_headers: Headers | None = None,
+ extra_query: Query | None = None,
+ extra_body: Body | None = None,
+ timeout: float | httpx.Timeout | None | NotGiven = NOT_GIVEN,
+ ) -> AsyncPaginator[object, AsyncV4PagePaginationArray[object]]:
+ """
+ List all the resource groups for an account.
+
+ Args:
+ account_id: Account identifier tag.
+
+ id: ID of the resource group to be fetched.
+
+ name: Name of the resource group to be fetched.
+
+ page: Page number of paginated results.
+
+ per_page: Maximum number of results per page.
+
+ 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_api_list(
+ f"/accounts/{account_id}/iam/resource_groups",
+ page=AsyncV4PagePaginationArray[object],
+ options=make_request_options(
+ extra_headers=extra_headers,
+ extra_query=extra_query,
+ extra_body=extra_body,
+ timeout=timeout,
+ query=maybe_transform(
+ {
+ "id": id,
+ "name": name,
+ "page": page,
+ "per_page": per_page,
+ },
+ resource_group_list_params.ResourceGroupListParams,
+ ),
+ ),
+ model=object,
+ )
+
+ async def delete(
+ self,
+ resource_group_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[ResourceGroupDeleteResponse]:
+ """
+ Remove a resource group from an account.
+
+ Args:
+ account_id: Account identifier tag.
+
+ resource_group_id: Resource Group identifier tag.
+
+ 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 resource_group_id:
+ raise ValueError(f"Expected a non-empty value for `resource_group_id` but received {resource_group_id!r}")
+ return await self._delete(
+ f"/accounts/{account_id}/iam/resource_groups/{resource_group_id}",
+ options=make_request_options(
+ extra_headers=extra_headers,
+ extra_query=extra_query,
+ extra_body=extra_body,
+ timeout=timeout,
+ post_parser=ResultWrapper[Optional[ResourceGroupDeleteResponse]]._unwrapper,
+ ),
+ cast_to=cast(Type[Optional[ResourceGroupDeleteResponse]], ResultWrapper[ResourceGroupDeleteResponse]),
+ )
+
+ async def get(
+ self,
+ resource_group_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,
+ ) -> ResourceGroupGetResponse:
+ """
+ Get information about a specific resource group in an account.
+
+ Args:
+ account_id: Account identifier tag.
+
+ resource_group_id: Resource Group identifier tag.
+
+ 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 resource_group_id:
+ raise ValueError(f"Expected a non-empty value for `resource_group_id` but received {resource_group_id!r}")
+ return await self._get(
+ f"/accounts/{account_id}/iam/resource_groups/{resource_group_id}",
+ options=make_request_options(
+ extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout
+ ),
+ cast_to=ResourceGroupGetResponse,
+ )
+
+
+class ResourceGroupsResourceWithRawResponse:
+ def __init__(self, resource_groups: ResourceGroupsResource) -> None:
+ self._resource_groups = resource_groups
+
+ self.create = to_raw_response_wrapper(
+ resource_groups.create,
+ )
+ self.update = to_raw_response_wrapper(
+ resource_groups.update,
+ )
+ self.list = to_raw_response_wrapper(
+ resource_groups.list,
+ )
+ self.delete = to_raw_response_wrapper(
+ resource_groups.delete,
+ )
+ self.get = to_raw_response_wrapper(
+ resource_groups.get,
+ )
+
+
+class AsyncResourceGroupsResourceWithRawResponse:
+ def __init__(self, resource_groups: AsyncResourceGroupsResource) -> None:
+ self._resource_groups = resource_groups
+
+ self.create = async_to_raw_response_wrapper(
+ resource_groups.create,
+ )
+ self.update = async_to_raw_response_wrapper(
+ resource_groups.update,
+ )
+ self.list = async_to_raw_response_wrapper(
+ resource_groups.list,
+ )
+ self.delete = async_to_raw_response_wrapper(
+ resource_groups.delete,
+ )
+ self.get = async_to_raw_response_wrapper(
+ resource_groups.get,
+ )
+
+
+class ResourceGroupsResourceWithStreamingResponse:
+ def __init__(self, resource_groups: ResourceGroupsResource) -> None:
+ self._resource_groups = resource_groups
+
+ self.create = to_streamed_response_wrapper(
+ resource_groups.create,
+ )
+ self.update = to_streamed_response_wrapper(
+ resource_groups.update,
+ )
+ self.list = to_streamed_response_wrapper(
+ resource_groups.list,
+ )
+ self.delete = to_streamed_response_wrapper(
+ resource_groups.delete,
+ )
+ self.get = to_streamed_response_wrapper(
+ resource_groups.get,
+ )
+
+
+class AsyncResourceGroupsResourceWithStreamingResponse:
+ def __init__(self, resource_groups: AsyncResourceGroupsResource) -> None:
+ self._resource_groups = resource_groups
+
+ self.create = async_to_streamed_response_wrapper(
+ resource_groups.create,
+ )
+ self.update = async_to_streamed_response_wrapper(
+ resource_groups.update,
+ )
+ self.list = async_to_streamed_response_wrapper(
+ resource_groups.list,
+ )
+ self.delete = async_to_streamed_response_wrapper(
+ resource_groups.delete,
+ )
+ self.get = async_to_streamed_response_wrapper(
+ resource_groups.get,
+ )
diff --git a/src/cloudflare/resources/page_shield/__init__.py b/src/cloudflare/resources/page_shield/__init__.py
index 42a42e10c4d..31bb6daa0ad 100644
--- a/src/cloudflare/resources/page_shield/__init__.py
+++ b/src/cloudflare/resources/page_shield/__init__.py
@@ -1,5 +1,13 @@
# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details.
+from .cookies import (
+ CookiesResource,
+ AsyncCookiesResource,
+ CookiesResourceWithRawResponse,
+ AsyncCookiesResourceWithRawResponse,
+ CookiesResourceWithStreamingResponse,
+ AsyncCookiesResourceWithStreamingResponse,
+)
from .scripts import (
ScriptsResource,
AsyncScriptsResource,
@@ -52,6 +60,12 @@
"AsyncScriptsResourceWithRawResponse",
"ScriptsResourceWithStreamingResponse",
"AsyncScriptsResourceWithStreamingResponse",
+ "CookiesResource",
+ "AsyncCookiesResource",
+ "CookiesResourceWithRawResponse",
+ "AsyncCookiesResourceWithRawResponse",
+ "CookiesResourceWithStreamingResponse",
+ "AsyncCookiesResourceWithStreamingResponse",
"PageShieldResource",
"AsyncPageShieldResource",
"PageShieldResourceWithRawResponse",
diff --git a/src/cloudflare/resources/page_shield/cookies.py b/src/cloudflare/resources/page_shield/cookies.py
new file mode 100644
index 00000000000..d35ffba6734
--- /dev/null
+++ b/src/cloudflare/resources/page_shield/cookies.py
@@ -0,0 +1,412 @@
+# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details.
+
+from __future__ import annotations
+
+from typing import Type, Optional, cast
+from typing_extensions import Literal
+
+import httpx
+
+from ..._types import NOT_GIVEN, Body, Query, Headers, NotGiven
+from ..._utils import maybe_transform
+from ..._compat import cached_property
+from ..._resource import SyncAPIResource, AsyncAPIResource
+from ..._response import (
+ to_raw_response_wrapper,
+ to_streamed_response_wrapper,
+ async_to_raw_response_wrapper,
+ async_to_streamed_response_wrapper,
+)
+from ..._wrappers import ResultWrapper
+from ...pagination import SyncSinglePage, AsyncSinglePage
+from ..._base_client import (
+ AsyncPaginator,
+ make_request_options,
+)
+from ...types.page_shield import cookie_list_params
+from ...types.page_shield.cookie_get_response import CookieGetResponse
+from ...types.page_shield.cookie_list_response import CookieListResponse
+
+__all__ = ["CookiesResource", "AsyncCookiesResource"]
+
+
+class CookiesResource(SyncAPIResource):
+ @cached_property
+ def with_raw_response(self) -> CookiesResourceWithRawResponse:
+ return CookiesResourceWithRawResponse(self)
+
+ @cached_property
+ def with_streaming_response(self) -> CookiesResourceWithStreamingResponse:
+ return CookiesResourceWithStreamingResponse(self)
+
+ def list(
+ self,
+ *,
+ zone_id: str,
+ direction: Literal["asc", "desc"] | NotGiven = NOT_GIVEN,
+ domain: str | NotGiven = NOT_GIVEN,
+ export: Literal["csv"] | NotGiven = NOT_GIVEN,
+ hosts: str | NotGiven = NOT_GIVEN,
+ http_only: bool | NotGiven = NOT_GIVEN,
+ name: str | NotGiven = NOT_GIVEN,
+ order_by: Literal["first_seen_at", "last_seen_at"] | NotGiven = NOT_GIVEN,
+ page: str | NotGiven = NOT_GIVEN,
+ page_url: str | NotGiven = NOT_GIVEN,
+ path: str | NotGiven = NOT_GIVEN,
+ per_page: float | NotGiven = NOT_GIVEN,
+ same_site: Literal["lax", "strict", "none"] | NotGiven = NOT_GIVEN,
+ secure: bool | NotGiven = NOT_GIVEN,
+ type: Literal["first_party", "unknown"] | NotGiven = NOT_GIVEN,
+ # Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs.
+ # The extra values given here take precedence over values defined on the client or passed to this method.
+ extra_headers: Headers | None = None,
+ extra_query: Query | None = None,
+ extra_body: Body | None = None,
+ timeout: float | httpx.Timeout | None | NotGiven = NOT_GIVEN,
+ ) -> SyncSinglePage[CookieListResponse]:
+ """
+ Lists all cookies collected by Page Shield.
+
+ Args:
+ zone_id: Identifier
+
+ direction: The direction used to sort returned cookies.'
+
+ domain: Filters the returned cookies that match the specified domain attribute
+
+ export: Export the list of cookies as a file. Cannot be used with per_page or page
+ options.
+
+ hosts: Includes cookies that match one or more URL-encoded hostnames separated by
+ commas.
+
+ Wildcards are supported at the start and end of each hostname to support starts
+ with, ends with and contains. If no wildcards are used, results will be filtered
+ by exact match
+
+ http_only: Filters the returned cookies that are set with HttpOnly
+
+ name: Filters the returned cookies that match the specified name. Wildcards are
+ supported at the start and end to support starts with, ends with and contains.
+ e.g. session\\**
+
+ order_by: The field used to sort returned cookies.
+
+ page: The current page number of the paginated results.
+
+ page_url: Includes connections that match one or more page URLs (separated by commas)
+ where they were last seen
+
+ Wildcards are supported at the start and end of each page URL to support starts
+ with, ends with and contains. If no wildcards are used, results will be filtered
+ by exact match
+
+ path: Filters the returned cookies that match the specified path attribute
+
+ per_page: The number of results per page.
+
+ same_site: Filters the returned cookies that match the specified same_site attribute
+
+ secure: Filters the returned cookies that are set with Secure
+
+ type: Filters the returned cookies that match the specified type attribute
+
+ 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_api_list(
+ f"/zones/{zone_id}/page_shield/cookies",
+ page=SyncSinglePage[CookieListResponse],
+ options=make_request_options(
+ extra_headers=extra_headers,
+ extra_query=extra_query,
+ extra_body=extra_body,
+ timeout=timeout,
+ query=maybe_transform(
+ {
+ "direction": direction,
+ "domain": domain,
+ "export": export,
+ "hosts": hosts,
+ "http_only": http_only,
+ "name": name,
+ "order_by": order_by,
+ "page": page,
+ "page_url": page_url,
+ "path": path,
+ "per_page": per_page,
+ "same_site": same_site,
+ "secure": secure,
+ "type": type,
+ },
+ cookie_list_params.CookieListParams,
+ ),
+ ),
+ model=CookieListResponse,
+ )
+
+ def get(
+ self,
+ cookie_id: str,
+ *,
+ 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[CookieGetResponse]:
+ """
+ Fetches a cookie collected by Page Shield by cookie ID.
+
+ Args:
+ zone_id: Identifier
+
+ cookie_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}")
+ if not cookie_id:
+ raise ValueError(f"Expected a non-empty value for `cookie_id` but received {cookie_id!r}")
+ return self._get(
+ f"/zones/{zone_id}/page_shield/cookies/{cookie_id}",
+ options=make_request_options(
+ extra_headers=extra_headers,
+ extra_query=extra_query,
+ extra_body=extra_body,
+ timeout=timeout,
+ post_parser=ResultWrapper[Optional[CookieGetResponse]]._unwrapper,
+ ),
+ cast_to=cast(Type[Optional[CookieGetResponse]], ResultWrapper[CookieGetResponse]),
+ )
+
+
+class AsyncCookiesResource(AsyncAPIResource):
+ @cached_property
+ def with_raw_response(self) -> AsyncCookiesResourceWithRawResponse:
+ return AsyncCookiesResourceWithRawResponse(self)
+
+ @cached_property
+ def with_streaming_response(self) -> AsyncCookiesResourceWithStreamingResponse:
+ return AsyncCookiesResourceWithStreamingResponse(self)
+
+ def list(
+ self,
+ *,
+ zone_id: str,
+ direction: Literal["asc", "desc"] | NotGiven = NOT_GIVEN,
+ domain: str | NotGiven = NOT_GIVEN,
+ export: Literal["csv"] | NotGiven = NOT_GIVEN,
+ hosts: str | NotGiven = NOT_GIVEN,
+ http_only: bool | NotGiven = NOT_GIVEN,
+ name: str | NotGiven = NOT_GIVEN,
+ order_by: Literal["first_seen_at", "last_seen_at"] | NotGiven = NOT_GIVEN,
+ page: str | NotGiven = NOT_GIVEN,
+ page_url: str | NotGiven = NOT_GIVEN,
+ path: str | NotGiven = NOT_GIVEN,
+ per_page: float | NotGiven = NOT_GIVEN,
+ same_site: Literal["lax", "strict", "none"] | NotGiven = NOT_GIVEN,
+ secure: bool | NotGiven = NOT_GIVEN,
+ type: Literal["first_party", "unknown"] | NotGiven = NOT_GIVEN,
+ # Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs.
+ # The extra values given here take precedence over values defined on the client or passed to this method.
+ extra_headers: Headers | None = None,
+ extra_query: Query | None = None,
+ extra_body: Body | None = None,
+ timeout: float | httpx.Timeout | None | NotGiven = NOT_GIVEN,
+ ) -> AsyncPaginator[CookieListResponse, AsyncSinglePage[CookieListResponse]]:
+ """
+ Lists all cookies collected by Page Shield.
+
+ Args:
+ zone_id: Identifier
+
+ direction: The direction used to sort returned cookies.'
+
+ domain: Filters the returned cookies that match the specified domain attribute
+
+ export: Export the list of cookies as a file. Cannot be used with per_page or page
+ options.
+
+ hosts: Includes cookies that match one or more URL-encoded hostnames separated by
+ commas.
+
+ Wildcards are supported at the start and end of each hostname to support starts
+ with, ends with and contains. If no wildcards are used, results will be filtered
+ by exact match
+
+ http_only: Filters the returned cookies that are set with HttpOnly
+
+ name: Filters the returned cookies that match the specified name. Wildcards are
+ supported at the start and end to support starts with, ends with and contains.
+ e.g. session\\**
+
+ order_by: The field used to sort returned cookies.
+
+ page: The current page number of the paginated results.
+
+ page_url: Includes connections that match one or more page URLs (separated by commas)
+ where they were last seen
+
+ Wildcards are supported at the start and end of each page URL to support starts
+ with, ends with and contains. If no wildcards are used, results will be filtered
+ by exact match
+
+ path: Filters the returned cookies that match the specified path attribute
+
+ per_page: The number of results per page.
+
+ same_site: Filters the returned cookies that match the specified same_site attribute
+
+ secure: Filters the returned cookies that are set with Secure
+
+ type: Filters the returned cookies that match the specified type attribute
+
+ 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_api_list(
+ f"/zones/{zone_id}/page_shield/cookies",
+ page=AsyncSinglePage[CookieListResponse],
+ options=make_request_options(
+ extra_headers=extra_headers,
+ extra_query=extra_query,
+ extra_body=extra_body,
+ timeout=timeout,
+ query=maybe_transform(
+ {
+ "direction": direction,
+ "domain": domain,
+ "export": export,
+ "hosts": hosts,
+ "http_only": http_only,
+ "name": name,
+ "order_by": order_by,
+ "page": page,
+ "page_url": page_url,
+ "path": path,
+ "per_page": per_page,
+ "same_site": same_site,
+ "secure": secure,
+ "type": type,
+ },
+ cookie_list_params.CookieListParams,
+ ),
+ ),
+ model=CookieListResponse,
+ )
+
+ async def get(
+ self,
+ cookie_id: str,
+ *,
+ 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[CookieGetResponse]:
+ """
+ Fetches a cookie collected by Page Shield by cookie ID.
+
+ Args:
+ zone_id: Identifier
+
+ cookie_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}")
+ if not cookie_id:
+ raise ValueError(f"Expected a non-empty value for `cookie_id` but received {cookie_id!r}")
+ return await self._get(
+ f"/zones/{zone_id}/page_shield/cookies/{cookie_id}",
+ options=make_request_options(
+ extra_headers=extra_headers,
+ extra_query=extra_query,
+ extra_body=extra_body,
+ timeout=timeout,
+ post_parser=ResultWrapper[Optional[CookieGetResponse]]._unwrapper,
+ ),
+ cast_to=cast(Type[Optional[CookieGetResponse]], ResultWrapper[CookieGetResponse]),
+ )
+
+
+class CookiesResourceWithRawResponse:
+ def __init__(self, cookies: CookiesResource) -> None:
+ self._cookies = cookies
+
+ self.list = to_raw_response_wrapper(
+ cookies.list,
+ )
+ self.get = to_raw_response_wrapper(
+ cookies.get,
+ )
+
+
+class AsyncCookiesResourceWithRawResponse:
+ def __init__(self, cookies: AsyncCookiesResource) -> None:
+ self._cookies = cookies
+
+ self.list = async_to_raw_response_wrapper(
+ cookies.list,
+ )
+ self.get = async_to_raw_response_wrapper(
+ cookies.get,
+ )
+
+
+class CookiesResourceWithStreamingResponse:
+ def __init__(self, cookies: CookiesResource) -> None:
+ self._cookies = cookies
+
+ self.list = to_streamed_response_wrapper(
+ cookies.list,
+ )
+ self.get = to_streamed_response_wrapper(
+ cookies.get,
+ )
+
+
+class AsyncCookiesResourceWithStreamingResponse:
+ def __init__(self, cookies: AsyncCookiesResource) -> None:
+ self._cookies = cookies
+
+ self.list = async_to_streamed_response_wrapper(
+ cookies.list,
+ )
+ self.get = async_to_streamed_response_wrapper(
+ cookies.get,
+ )
diff --git a/src/cloudflare/resources/page_shield/page_shield.py b/src/cloudflare/resources/page_shield/page_shield.py
index 655f3b4c4fd..9e7d2e27f74 100644
--- a/src/cloudflare/resources/page_shield/page_shield.py
+++ b/src/cloudflare/resources/page_shield/page_shield.py
@@ -6,6 +6,14 @@
import httpx
+from .cookies import (
+ CookiesResource,
+ AsyncCookiesResource,
+ CookiesResourceWithRawResponse,
+ AsyncCookiesResourceWithRawResponse,
+ CookiesResourceWithStreamingResponse,
+ AsyncCookiesResourceWithStreamingResponse,
+)
from .scripts import (
ScriptsResource,
AsyncScriptsResource,
@@ -67,6 +75,10 @@ def connections(self) -> ConnectionsResource:
def scripts(self) -> ScriptsResource:
return ScriptsResource(self._client)
+ @cached_property
+ def cookies(self) -> CookiesResource:
+ return CookiesResource(self._client)
+
@cached_property
def with_raw_response(self) -> PageShieldResourceWithRawResponse:
return PageShieldResourceWithRawResponse(self)
@@ -185,6 +197,10 @@ def connections(self) -> AsyncConnectionsResource:
def scripts(self) -> AsyncScriptsResource:
return AsyncScriptsResource(self._client)
+ @cached_property
+ def cookies(self) -> AsyncCookiesResource:
+ return AsyncCookiesResource(self._client)
+
@cached_property
def with_raw_response(self) -> AsyncPageShieldResourceWithRawResponse:
return AsyncPageShieldResourceWithRawResponse(self)
@@ -313,6 +329,10 @@ def connections(self) -> ConnectionsResourceWithRawResponse:
def scripts(self) -> ScriptsResourceWithRawResponse:
return ScriptsResourceWithRawResponse(self._page_shield.scripts)
+ @cached_property
+ def cookies(self) -> CookiesResourceWithRawResponse:
+ return CookiesResourceWithRawResponse(self._page_shield.cookies)
+
class AsyncPageShieldResourceWithRawResponse:
def __init__(self, page_shield: AsyncPageShieldResource) -> None:
@@ -337,6 +357,10 @@ def connections(self) -> AsyncConnectionsResourceWithRawResponse:
def scripts(self) -> AsyncScriptsResourceWithRawResponse:
return AsyncScriptsResourceWithRawResponse(self._page_shield.scripts)
+ @cached_property
+ def cookies(self) -> AsyncCookiesResourceWithRawResponse:
+ return AsyncCookiesResourceWithRawResponse(self._page_shield.cookies)
+
class PageShieldResourceWithStreamingResponse:
def __init__(self, page_shield: PageShieldResource) -> None:
@@ -361,6 +385,10 @@ def connections(self) -> ConnectionsResourceWithStreamingResponse:
def scripts(self) -> ScriptsResourceWithStreamingResponse:
return ScriptsResourceWithStreamingResponse(self._page_shield.scripts)
+ @cached_property
+ def cookies(self) -> CookiesResourceWithStreamingResponse:
+ return CookiesResourceWithStreamingResponse(self._page_shield.cookies)
+
class AsyncPageShieldResourceWithStreamingResponse:
def __init__(self, page_shield: AsyncPageShieldResource) -> None:
@@ -384,3 +412,7 @@ def connections(self) -> AsyncConnectionsResourceWithStreamingResponse:
@cached_property
def scripts(self) -> AsyncScriptsResourceWithStreamingResponse:
return AsyncScriptsResourceWithStreamingResponse(self._page_shield.scripts)
+
+ @cached_property
+ def cookies(self) -> AsyncCookiesResourceWithStreamingResponse:
+ return AsyncCookiesResourceWithStreamingResponse(self._page_shield.cookies)
diff --git a/src/cloudflare/types/iam/__init__.py b/src/cloudflare/types/iam/__init__.py
new file mode 100644
index 00000000000..5982e2443a2
--- /dev/null
+++ b/src/cloudflare/types/iam/__init__.py
@@ -0,0 +1,13 @@
+# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details.
+
+from __future__ import annotations
+
+from .resource_group_list_params import ResourceGroupListParams as ResourceGroupListParams
+from .resource_group_get_response import ResourceGroupGetResponse as ResourceGroupGetResponse
+from .permission_group_list_params import PermissionGroupListParams as PermissionGroupListParams
+from .resource_group_create_params import ResourceGroupCreateParams as ResourceGroupCreateParams
+from .resource_group_update_params import ResourceGroupUpdateParams as ResourceGroupUpdateParams
+from .permission_group_get_response import PermissionGroupGetResponse as PermissionGroupGetResponse
+from .resource_group_create_response import ResourceGroupCreateResponse as ResourceGroupCreateResponse
+from .resource_group_delete_response import ResourceGroupDeleteResponse as ResourceGroupDeleteResponse
+from .resource_group_update_response import ResourceGroupUpdateResponse as ResourceGroupUpdateResponse
diff --git a/src/cloudflare/types/iam/permission_group_get_response.py b/src/cloudflare/types/iam/permission_group_get_response.py
new file mode 100644
index 00000000000..bfafb28bc92
--- /dev/null
+++ b/src/cloudflare/types/iam/permission_group_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__ = ["PermissionGroupGetResponse"]
+
+
+class PermissionGroupGetResponse(BaseModel):
+ id: str
+ """Identifier of the group."""
+
+ meta: Optional[object] = None
+ """Attributes associated to the permission group."""
+
+ name: Optional[str] = None
+ """Name of the group."""
diff --git a/src/cloudflare/types/iam/permission_group_list_params.py b/src/cloudflare/types/iam/permission_group_list_params.py
new file mode 100644
index 00000000000..04f58ce75ce
--- /dev/null
+++ b/src/cloudflare/types/iam/permission_group_list_params.py
@@ -0,0 +1,27 @@
+# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details.
+
+from __future__ import annotations
+
+from typing_extensions import Required, TypedDict
+
+__all__ = ["PermissionGroupListParams"]
+
+
+class PermissionGroupListParams(TypedDict, total=False):
+ account_id: Required[str]
+ """Account identifier tag."""
+
+ id: str
+ """ID of the permission group to be fetched."""
+
+ label: str
+ """Label of the permission group to be fetched."""
+
+ name: str
+ """Name of the permission group to be fetched."""
+
+ page: float
+ """Page number of paginated results."""
+
+ per_page: float
+ """Maximum number of results per page."""
diff --git a/src/cloudflare/types/iam/resource_group_create_params.py b/src/cloudflare/types/iam/resource_group_create_params.py
new file mode 100644
index 00000000000..7f583c5f87c
--- /dev/null
+++ b/src/cloudflare/types/iam/resource_group_create_params.py
@@ -0,0 +1,41 @@
+# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details.
+
+from __future__ import annotations
+
+from typing import Iterable
+from typing_extensions import Required, TypedDict
+
+__all__ = ["ResourceGroupCreateParams", "Scope", "ScopeObject"]
+
+
+class ResourceGroupCreateParams(TypedDict, total=False):
+ account_id: Required[str]
+ """Account identifier tag."""
+
+ scope: Required[Scope]
+ """A scope is a combination of scope objects which provides additional context."""
+
+ meta: object
+ """Attributes associated to the resource group."""
+
+
+class ScopeObject(TypedDict, total=False):
+ key: Required[str]
+ """
+ This is a combination of pre-defined resource name and identifier (like Zone ID
+ etc.)
+ """
+
+
+class Scope(TypedDict, total=False):
+ key: Required[str]
+ """
+ This is a combination of pre-defined resource name and identifier (like Account
+ ID etc.)
+ """
+
+ objects: Required[Iterable[ScopeObject]]
+ """A list of scope objects for additional context.
+
+ The number of Scope objects should not be zero.
+ """
diff --git a/src/cloudflare/types/iam/resource_group_create_response.py b/src/cloudflare/types/iam/resource_group_create_response.py
new file mode 100644
index 00000000000..a6c3b5dc1b0
--- /dev/null
+++ b/src/cloudflare/types/iam/resource_group_create_response.py
@@ -0,0 +1,40 @@
+# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details.
+
+from typing import List, Optional
+
+from ..._models import BaseModel
+
+__all__ = ["ResourceGroupCreateResponse", "Scope", "ScopeObject"]
+
+
+class ScopeObject(BaseModel):
+ key: str
+ """
+ This is a combination of pre-defined resource name and identifier (like Zone ID
+ etc.)
+ """
+
+
+class Scope(BaseModel):
+ key: str
+ """
+ This is a combination of pre-defined resource name and identifier (like Account
+ ID etc.)
+ """
+
+ objects: List[ScopeObject]
+ """A list of scope objects for additional context.
+
+ The number of Scope objects should not be zero.
+ """
+
+
+class ResourceGroupCreateResponse(BaseModel):
+ id: Optional[str] = None
+ """Identifier of the group."""
+
+ meta: Optional[object] = None
+ """Attributes associated to the resource group."""
+
+ scope: Optional[Scope] = None
+ """A scope is a combination of scope objects which provides additional context."""
diff --git a/src/cloudflare/types/iam/resource_group_delete_response.py b/src/cloudflare/types/iam/resource_group_delete_response.py
new file mode 100644
index 00000000000..604eafbe8f0
--- /dev/null
+++ b/src/cloudflare/types/iam/resource_group_delete_response.py
@@ -0,0 +1,12 @@
+# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details.
+
+
+
+from ..._models import BaseModel
+
+__all__ = ["ResourceGroupDeleteResponse"]
+
+
+class ResourceGroupDeleteResponse(BaseModel):
+ id: str
+ """Identifier"""
diff --git a/src/cloudflare/types/iam/resource_group_get_response.py b/src/cloudflare/types/iam/resource_group_get_response.py
new file mode 100644
index 00000000000..26cc4314edc
--- /dev/null
+++ b/src/cloudflare/types/iam/resource_group_get_response.py
@@ -0,0 +1,40 @@
+# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details.
+
+from typing import List, Optional
+
+from ..._models import BaseModel
+
+__all__ = ["ResourceGroupGetResponse", "Scope", "ScopeObject"]
+
+
+class ScopeObject(BaseModel):
+ key: str
+ """
+ This is a combination of pre-defined resource name and identifier (like Zone ID
+ etc.)
+ """
+
+
+class Scope(BaseModel):
+ key: str
+ """
+ This is a combination of pre-defined resource name and identifier (like Account
+ ID etc.)
+ """
+
+ objects: List[ScopeObject]
+ """A list of scope objects for additional context."""
+
+
+class ResourceGroupGetResponse(BaseModel):
+ id: str
+ """Identifier of the group."""
+
+ scope: List[Scope]
+ """The scope associated to the resource group"""
+
+ meta: Optional[object] = None
+ """Attributes associated to the resource group."""
+
+ name: Optional[str] = None
+ """Name of the resource group."""
diff --git a/src/cloudflare/types/iam/resource_group_list_params.py b/src/cloudflare/types/iam/resource_group_list_params.py
new file mode 100644
index 00000000000..f6153181a2f
--- /dev/null
+++ b/src/cloudflare/types/iam/resource_group_list_params.py
@@ -0,0 +1,24 @@
+# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details.
+
+from __future__ import annotations
+
+from typing_extensions import Required, TypedDict
+
+__all__ = ["ResourceGroupListParams"]
+
+
+class ResourceGroupListParams(TypedDict, total=False):
+ account_id: Required[str]
+ """Account identifier tag."""
+
+ id: str
+ """ID of the resource group to be fetched."""
+
+ name: str
+ """Name of the resource group to be fetched."""
+
+ page: float
+ """Page number of paginated results."""
+
+ per_page: float
+ """Maximum number of results per page."""
diff --git a/src/cloudflare/types/iam/resource_group_update_params.py b/src/cloudflare/types/iam/resource_group_update_params.py
new file mode 100644
index 00000000000..eb50831f7be
--- /dev/null
+++ b/src/cloudflare/types/iam/resource_group_update_params.py
@@ -0,0 +1,41 @@
+# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details.
+
+from __future__ import annotations
+
+from typing import Iterable
+from typing_extensions import Required, TypedDict
+
+__all__ = ["ResourceGroupUpdateParams", "Scope", "ScopeObject"]
+
+
+class ResourceGroupUpdateParams(TypedDict, total=False):
+ account_id: Required[str]
+ """Account identifier tag."""
+
+ scope: Required[Scope]
+ """A scope is a combination of scope objects which provides additional context."""
+
+ meta: object
+ """Attributes associated to the resource group."""
+
+
+class ScopeObject(TypedDict, total=False):
+ key: Required[str]
+ """
+ This is a combination of pre-defined resource name and identifier (like Zone ID
+ etc.)
+ """
+
+
+class Scope(TypedDict, total=False):
+ key: Required[str]
+ """
+ This is a combination of pre-defined resource name and identifier (like Account
+ ID etc.)
+ """
+
+ objects: Required[Iterable[ScopeObject]]
+ """A list of scope objects for additional context.
+
+ The number of Scope objects should not be zero.
+ """
diff --git a/src/cloudflare/types/iam/resource_group_update_response.py b/src/cloudflare/types/iam/resource_group_update_response.py
new file mode 100644
index 00000000000..8aa70682f42
--- /dev/null
+++ b/src/cloudflare/types/iam/resource_group_update_response.py
@@ -0,0 +1,40 @@
+# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details.
+
+from typing import List, Optional
+
+from ..._models import BaseModel
+
+__all__ = ["ResourceGroupUpdateResponse", "Scope", "ScopeObject"]
+
+
+class ScopeObject(BaseModel):
+ key: str
+ """
+ This is a combination of pre-defined resource name and identifier (like Zone ID
+ etc.)
+ """
+
+
+class Scope(BaseModel):
+ key: str
+ """
+ This is a combination of pre-defined resource name and identifier (like Account
+ ID etc.)
+ """
+
+ objects: List[ScopeObject]
+ """A list of scope objects for additional context."""
+
+
+class ResourceGroupUpdateResponse(BaseModel):
+ id: str
+ """Identifier of the group."""
+
+ scope: List[Scope]
+ """The scope associated to the resource group"""
+
+ meta: Optional[object] = None
+ """Attributes associated to the resource group."""
+
+ name: Optional[str] = None
+ """Name of the resource group."""
diff --git a/src/cloudflare/types/page_shield/__init__.py b/src/cloudflare/types/page_shield/__init__.py
index 1442bda6660..a115366d760 100644
--- a/src/cloudflare/types/page_shield/__init__.py
+++ b/src/cloudflare/types/page_shield/__init__.py
@@ -2,12 +2,16 @@
from __future__ import annotations
+from .policy import Policy as Policy
from .script import Script as Script
from .setting import Setting as Setting
from .connection import Connection as Connection
+from .cookie_list_params import CookieListParams as CookieListParams
from .script_list_params import ScriptListParams as ScriptListParams
+from .cookie_get_response import CookieGetResponse as CookieGetResponse
from .policy_get_response import PolicyGetResponse as PolicyGetResponse
from .script_get_response import ScriptGetResponse as ScriptGetResponse
+from .cookie_list_response import CookieListResponse as CookieListResponse
from .policy_create_params import PolicyCreateParams as PolicyCreateParams
from .policy_list_response import PolicyListResponse as PolicyListResponse
from .policy_update_params import PolicyUpdateParams as PolicyUpdateParams
diff --git a/src/cloudflare/types/page_shield/cookie_get_response.py b/src/cloudflare/types/page_shield/cookie_get_response.py
new file mode 100644
index 00000000000..45735f30051
--- /dev/null
+++ b/src/cloudflare/types/page_shield/cookie_get_response.py
@@ -0,0 +1,40 @@
+# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details.
+
+from typing import List, Optional
+from datetime import datetime
+from typing_extensions import Literal
+
+from ..._models import BaseModel
+
+__all__ = ["CookieGetResponse"]
+
+
+class CookieGetResponse(BaseModel):
+ id: str
+ """Identifier"""
+
+ first_seen_at: datetime
+
+ host: str
+
+ last_seen_at: datetime
+
+ name: str
+
+ type: Literal["first_party", "unknown"]
+
+ domain_attribute: Optional[str] = None
+
+ expires_attribute: Optional[datetime] = None
+
+ http_only_attribute: Optional[bool] = None
+
+ max_age_attribute: Optional[int] = None
+
+ page_urls: Optional[List[str]] = None
+
+ path_attribute: Optional[str] = None
+
+ same_site_attribute: Optional[Literal["lax", "strict", "none"]] = None
+
+ secure_attribute: Optional[bool] = None
diff --git a/src/cloudflare/types/page_shield/cookie_list_params.py b/src/cloudflare/types/page_shield/cookie_list_params.py
new file mode 100644
index 00000000000..3daf5bdee9c
--- /dev/null
+++ b/src/cloudflare/types/page_shield/cookie_list_params.py
@@ -0,0 +1,75 @@
+# 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__ = ["CookieListParams"]
+
+
+class CookieListParams(TypedDict, total=False):
+ zone_id: Required[str]
+ """Identifier"""
+
+ direction: Literal["asc", "desc"]
+ """The direction used to sort returned cookies.'"""
+
+ domain: str
+ """Filters the returned cookies that match the specified domain attribute"""
+
+ export: Literal["csv"]
+ """Export the list of cookies as a file.
+
+ Cannot be used with per_page or page options.
+ """
+
+ hosts: str
+ """
+ Includes cookies that match one or more URL-encoded hostnames separated by
+ commas.
+
+ Wildcards are supported at the start and end of each hostname to support starts
+ with, ends with and contains. If no wildcards are used, results will be filtered
+ by exact match
+ """
+
+ http_only: bool
+ """Filters the returned cookies that are set with HttpOnly"""
+
+ name: str
+ """
+ Filters the returned cookies that match the specified name. Wildcards are
+ supported at the start and end to support starts with, ends with and contains.
+ e.g. session\\**
+ """
+
+ order_by: Literal["first_seen_at", "last_seen_at"]
+ """The field used to sort returned cookies."""
+
+ page: str
+ """The current page number of the paginated results."""
+
+ page_url: str
+ """
+ Includes connections that match one or more page URLs (separated by commas)
+ where they were last seen
+
+ Wildcards are supported at the start and end of each page URL to support starts
+ with, ends with and contains. If no wildcards are used, results will be filtered
+ by exact match
+ """
+
+ path: str
+ """Filters the returned cookies that match the specified path attribute"""
+
+ per_page: float
+ """The number of results per page."""
+
+ same_site: Literal["lax", "strict", "none"]
+ """Filters the returned cookies that match the specified same_site attribute"""
+
+ secure: bool
+ """Filters the returned cookies that are set with Secure"""
+
+ type: Literal["first_party", "unknown"]
+ """Filters the returned cookies that match the specified type attribute"""
diff --git a/src/cloudflare/types/page_shield/cookie_list_response.py b/src/cloudflare/types/page_shield/cookie_list_response.py
new file mode 100644
index 00000000000..144fd84b510
--- /dev/null
+++ b/src/cloudflare/types/page_shield/cookie_list_response.py
@@ -0,0 +1,40 @@
+# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details.
+
+from typing import List, Optional
+from datetime import datetime
+from typing_extensions import Literal
+
+from ..._models import BaseModel
+
+__all__ = ["CookieListResponse"]
+
+
+class CookieListResponse(BaseModel):
+ id: str
+ """Identifier"""
+
+ first_seen_at: datetime
+
+ host: str
+
+ last_seen_at: datetime
+
+ name: str
+
+ type: Literal["first_party", "unknown"]
+
+ domain_attribute: Optional[str] = None
+
+ expires_attribute: Optional[datetime] = None
+
+ http_only_attribute: Optional[bool] = None
+
+ max_age_attribute: Optional[int] = None
+
+ page_urls: Optional[List[str]] = None
+
+ path_attribute: Optional[str] = None
+
+ same_site_attribute: Optional[Literal["lax", "strict", "none"]] = None
+
+ secure_attribute: Optional[bool] = None
diff --git a/src/cloudflare/types/page_shield/policy.py b/src/cloudflare/types/page_shield/policy.py
new file mode 100644
index 00000000000..e2c5e6b02a5
--- /dev/null
+++ b/src/cloudflare/types/page_shield/policy.py
@@ -0,0 +1,27 @@
+# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details.
+
+from typing_extensions import Literal
+
+from ..._models import BaseModel
+
+__all__ = ["Policy"]
+
+
+class Policy(BaseModel):
+ action: Literal["allow", "log"]
+ """The action to take if the expression matches"""
+
+ description: str
+ """A description for the policy"""
+
+ enabled: bool
+ """Whether the policy is enabled"""
+
+ expression: str
+ """
+ The expression which must match for the policy to be applied, using the
+ Cloudflare Firewall rule expression syntax
+ """
+
+ value: str
+ """The policy which will be applied"""
diff --git a/tests/api_resources/iam/__init__.py b/tests/api_resources/iam/__init__.py
new file mode 100644
index 00000000000..fd8019a9a1a
--- /dev/null
+++ b/tests/api_resources/iam/__init__.py
@@ -0,0 +1 @@
+# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details.
diff --git a/tests/api_resources/iam/test_permission_groups.py b/tests/api_resources/iam/test_permission_groups.py
new file mode 100644
index 00000000000..298235ce84e
--- /dev/null
+++ b/tests/api_resources/iam/test_permission_groups.py
@@ -0,0 +1,219 @@
+# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details.
+
+from __future__ import annotations
+
+import os
+from typing import Any, cast
+
+import pytest
+
+from cloudflare import Cloudflare, AsyncCloudflare
+from tests.utils import assert_matches_type
+from cloudflare.types.iam import PermissionGroupGetResponse
+from cloudflare.pagination import SyncV4PagePaginationArray, AsyncV4PagePaginationArray
+
+base_url = os.environ.get("TEST_API_BASE_URL", "http://127.0.0.1:4010")
+
+
+class TestPermissionGroups:
+ parametrize = pytest.mark.parametrize("client", [False, True], indirect=True, ids=["loose", "strict"])
+
+ @parametrize
+ def test_method_list(self, client: Cloudflare) -> None:
+ permission_group = client.iam.permission_groups.list(
+ account_id="eb78d65290b24279ba6f44721b3ea3c4",
+ )
+ assert_matches_type(SyncV4PagePaginationArray[object], permission_group, path=["response"])
+
+ @parametrize
+ def test_method_list_with_all_params(self, client: Cloudflare) -> None:
+ permission_group = client.iam.permission_groups.list(
+ account_id="eb78d65290b24279ba6f44721b3ea3c4",
+ id="6d7f2f5f5b1d4a0e9081fdc98d432fd1",
+ label="labelOfThePermissionGroup",
+ name="NameOfThePermissionGroup",
+ page=1,
+ per_page=5,
+ )
+ assert_matches_type(SyncV4PagePaginationArray[object], permission_group, path=["response"])
+
+ @parametrize
+ def test_raw_response_list(self, client: Cloudflare) -> None:
+ response = client.iam.permission_groups.with_raw_response.list(
+ account_id="eb78d65290b24279ba6f44721b3ea3c4",
+ )
+
+ assert response.is_closed is True
+ assert response.http_request.headers.get("X-Stainless-Lang") == "python"
+ permission_group = response.parse()
+ assert_matches_type(SyncV4PagePaginationArray[object], permission_group, path=["response"])
+
+ @parametrize
+ def test_streaming_response_list(self, client: Cloudflare) -> None:
+ with client.iam.permission_groups.with_streaming_response.list(
+ account_id="eb78d65290b24279ba6f44721b3ea3c4",
+ ) as response:
+ assert not response.is_closed
+ assert response.http_request.headers.get("X-Stainless-Lang") == "python"
+
+ permission_group = response.parse()
+ assert_matches_type(SyncV4PagePaginationArray[object], permission_group, 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.iam.permission_groups.with_raw_response.list(
+ account_id="",
+ )
+
+ @parametrize
+ def test_method_get(self, client: Cloudflare) -> None:
+ permission_group = client.iam.permission_groups.get(
+ "6d7f2f5f5b1d4a0e9081fdc98d432fd1",
+ account_id="eb78d65290b24279ba6f44721b3ea3c4",
+ )
+ assert_matches_type(PermissionGroupGetResponse, permission_group, path=["response"])
+
+ @parametrize
+ def test_raw_response_get(self, client: Cloudflare) -> None:
+ response = client.iam.permission_groups.with_raw_response.get(
+ "6d7f2f5f5b1d4a0e9081fdc98d432fd1",
+ account_id="eb78d65290b24279ba6f44721b3ea3c4",
+ )
+
+ assert response.is_closed is True
+ assert response.http_request.headers.get("X-Stainless-Lang") == "python"
+ permission_group = response.parse()
+ assert_matches_type(PermissionGroupGetResponse, permission_group, path=["response"])
+
+ @parametrize
+ def test_streaming_response_get(self, client: Cloudflare) -> None:
+ with client.iam.permission_groups.with_streaming_response.get(
+ "6d7f2f5f5b1d4a0e9081fdc98d432fd1",
+ account_id="eb78d65290b24279ba6f44721b3ea3c4",
+ ) as response:
+ assert not response.is_closed
+ assert response.http_request.headers.get("X-Stainless-Lang") == "python"
+
+ permission_group = response.parse()
+ assert_matches_type(PermissionGroupGetResponse, permission_group, 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.iam.permission_groups.with_raw_response.get(
+ "6d7f2f5f5b1d4a0e9081fdc98d432fd1",
+ account_id="",
+ )
+
+ with pytest.raises(ValueError, match=r"Expected a non-empty value for `permission_group_id` but received ''"):
+ client.iam.permission_groups.with_raw_response.get(
+ "",
+ account_id="eb78d65290b24279ba6f44721b3ea3c4",
+ )
+
+
+class TestAsyncPermissionGroups:
+ parametrize = pytest.mark.parametrize("async_client", [False, True], indirect=True, ids=["loose", "strict"])
+
+ @parametrize
+ async def test_method_list(self, async_client: AsyncCloudflare) -> None:
+ permission_group = await async_client.iam.permission_groups.list(
+ account_id="eb78d65290b24279ba6f44721b3ea3c4",
+ )
+ assert_matches_type(AsyncV4PagePaginationArray[object], permission_group, path=["response"])
+
+ @parametrize
+ async def test_method_list_with_all_params(self, async_client: AsyncCloudflare) -> None:
+ permission_group = await async_client.iam.permission_groups.list(
+ account_id="eb78d65290b24279ba6f44721b3ea3c4",
+ id="6d7f2f5f5b1d4a0e9081fdc98d432fd1",
+ label="labelOfThePermissionGroup",
+ name="NameOfThePermissionGroup",
+ page=1,
+ per_page=5,
+ )
+ assert_matches_type(AsyncV4PagePaginationArray[object], permission_group, path=["response"])
+
+ @parametrize
+ async def test_raw_response_list(self, async_client: AsyncCloudflare) -> None:
+ response = await async_client.iam.permission_groups.with_raw_response.list(
+ account_id="eb78d65290b24279ba6f44721b3ea3c4",
+ )
+
+ assert response.is_closed is True
+ assert response.http_request.headers.get("X-Stainless-Lang") == "python"
+ permission_group = await response.parse()
+ assert_matches_type(AsyncV4PagePaginationArray[object], permission_group, path=["response"])
+
+ @parametrize
+ async def test_streaming_response_list(self, async_client: AsyncCloudflare) -> None:
+ async with async_client.iam.permission_groups.with_streaming_response.list(
+ account_id="eb78d65290b24279ba6f44721b3ea3c4",
+ ) as response:
+ assert not response.is_closed
+ assert response.http_request.headers.get("X-Stainless-Lang") == "python"
+
+ permission_group = await response.parse()
+ assert_matches_type(AsyncV4PagePaginationArray[object], permission_group, 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.iam.permission_groups.with_raw_response.list(
+ account_id="",
+ )
+
+ @parametrize
+ async def test_method_get(self, async_client: AsyncCloudflare) -> None:
+ permission_group = await async_client.iam.permission_groups.get(
+ "6d7f2f5f5b1d4a0e9081fdc98d432fd1",
+ account_id="eb78d65290b24279ba6f44721b3ea3c4",
+ )
+ assert_matches_type(PermissionGroupGetResponse, permission_group, path=["response"])
+
+ @parametrize
+ async def test_raw_response_get(self, async_client: AsyncCloudflare) -> None:
+ response = await async_client.iam.permission_groups.with_raw_response.get(
+ "6d7f2f5f5b1d4a0e9081fdc98d432fd1",
+ account_id="eb78d65290b24279ba6f44721b3ea3c4",
+ )
+
+ assert response.is_closed is True
+ assert response.http_request.headers.get("X-Stainless-Lang") == "python"
+ permission_group = await response.parse()
+ assert_matches_type(PermissionGroupGetResponse, permission_group, path=["response"])
+
+ @parametrize
+ async def test_streaming_response_get(self, async_client: AsyncCloudflare) -> None:
+ async with async_client.iam.permission_groups.with_streaming_response.get(
+ "6d7f2f5f5b1d4a0e9081fdc98d432fd1",
+ account_id="eb78d65290b24279ba6f44721b3ea3c4",
+ ) as response:
+ assert not response.is_closed
+ assert response.http_request.headers.get("X-Stainless-Lang") == "python"
+
+ permission_group = await response.parse()
+ assert_matches_type(PermissionGroupGetResponse, permission_group, 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.iam.permission_groups.with_raw_response.get(
+ "6d7f2f5f5b1d4a0e9081fdc98d432fd1",
+ account_id="",
+ )
+
+ with pytest.raises(ValueError, match=r"Expected a non-empty value for `permission_group_id` but received ''"):
+ await async_client.iam.permission_groups.with_raw_response.get(
+ "",
+ account_id="eb78d65290b24279ba6f44721b3ea3c4",
+ )
diff --git a/tests/api_resources/iam/test_resource_groups.py b/tests/api_resources/iam/test_resource_groups.py
new file mode 100644
index 00000000000..a08c3160026
--- /dev/null
+++ b/tests/api_resources/iam/test_resource_groups.py
@@ -0,0 +1,700 @@
+# 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.iam import (
+ ResourceGroupGetResponse,
+ ResourceGroupCreateResponse,
+ ResourceGroupDeleteResponse,
+ ResourceGroupUpdateResponse,
+)
+from cloudflare.pagination import SyncV4PagePaginationArray, AsyncV4PagePaginationArray
+
+base_url = os.environ.get("TEST_API_BASE_URL", "http://127.0.0.1:4010")
+
+
+class TestResourceGroups:
+ parametrize = pytest.mark.parametrize("client", [False, True], indirect=True, ids=["loose", "strict"])
+
+ @parametrize
+ def test_method_create(self, client: Cloudflare) -> None:
+ resource_group = client.iam.resource_groups.create(
+ account_id="eb78d65290b24279ba6f44721b3ea3c4",
+ scope={
+ "key": "com.cloudflare.api.account.eb78d65290b24279ba6f44721b3ea3c4",
+ "objects": [
+ {"key": "com.cloudflare.api.account.zone.23f8d65290b24279ba6f44721b3eaad5"},
+ {"key": "com.cloudflare.api.account.zone.23f8d65290b24279ba6f44721b3eaad5"},
+ {"key": "com.cloudflare.api.account.zone.23f8d65290b24279ba6f44721b3eaad5"},
+ ],
+ },
+ )
+ assert_matches_type(ResourceGroupCreateResponse, resource_group, path=["response"])
+
+ @parametrize
+ def test_method_create_with_all_params(self, client: Cloudflare) -> None:
+ resource_group = client.iam.resource_groups.create(
+ account_id="eb78d65290b24279ba6f44721b3ea3c4",
+ scope={
+ "key": "com.cloudflare.api.account.eb78d65290b24279ba6f44721b3ea3c4",
+ "objects": [
+ {"key": "com.cloudflare.api.account.zone.23f8d65290b24279ba6f44721b3eaad5"},
+ {"key": "com.cloudflare.api.account.zone.23f8d65290b24279ba6f44721b3eaad5"},
+ {"key": "com.cloudflare.api.account.zone.23f8d65290b24279ba6f44721b3eaad5"},
+ ],
+ },
+ meta={"editable": "false"},
+ )
+ assert_matches_type(ResourceGroupCreateResponse, resource_group, path=["response"])
+
+ @parametrize
+ def test_raw_response_create(self, client: Cloudflare) -> None:
+ response = client.iam.resource_groups.with_raw_response.create(
+ account_id="eb78d65290b24279ba6f44721b3ea3c4",
+ scope={
+ "key": "com.cloudflare.api.account.eb78d65290b24279ba6f44721b3ea3c4",
+ "objects": [
+ {"key": "com.cloudflare.api.account.zone.23f8d65290b24279ba6f44721b3eaad5"},
+ {"key": "com.cloudflare.api.account.zone.23f8d65290b24279ba6f44721b3eaad5"},
+ {"key": "com.cloudflare.api.account.zone.23f8d65290b24279ba6f44721b3eaad5"},
+ ],
+ },
+ )
+
+ assert response.is_closed is True
+ assert response.http_request.headers.get("X-Stainless-Lang") == "python"
+ resource_group = response.parse()
+ assert_matches_type(ResourceGroupCreateResponse, resource_group, path=["response"])
+
+ @parametrize
+ def test_streaming_response_create(self, client: Cloudflare) -> None:
+ with client.iam.resource_groups.with_streaming_response.create(
+ account_id="eb78d65290b24279ba6f44721b3ea3c4",
+ scope={
+ "key": "com.cloudflare.api.account.eb78d65290b24279ba6f44721b3ea3c4",
+ "objects": [
+ {"key": "com.cloudflare.api.account.zone.23f8d65290b24279ba6f44721b3eaad5"},
+ {"key": "com.cloudflare.api.account.zone.23f8d65290b24279ba6f44721b3eaad5"},
+ {"key": "com.cloudflare.api.account.zone.23f8d65290b24279ba6f44721b3eaad5"},
+ ],
+ },
+ ) as response:
+ assert not response.is_closed
+ assert response.http_request.headers.get("X-Stainless-Lang") == "python"
+
+ resource_group = response.parse()
+ assert_matches_type(ResourceGroupCreateResponse, resource_group, 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.iam.resource_groups.with_raw_response.create(
+ account_id="",
+ scope={
+ "key": "com.cloudflare.api.account.eb78d65290b24279ba6f44721b3ea3c4",
+ "objects": [
+ {"key": "com.cloudflare.api.account.zone.23f8d65290b24279ba6f44721b3eaad5"},
+ {"key": "com.cloudflare.api.account.zone.23f8d65290b24279ba6f44721b3eaad5"},
+ {"key": "com.cloudflare.api.account.zone.23f8d65290b24279ba6f44721b3eaad5"},
+ ],
+ },
+ )
+
+ @parametrize
+ def test_method_update(self, client: Cloudflare) -> None:
+ resource_group = client.iam.resource_groups.update(
+ "6d7f2f5f5b1d4a0e9081fdc98d432fd1",
+ account_id="eb78d65290b24279ba6f44721b3ea3c4",
+ scope={
+ "key": "com.cloudflare.api.account.eb78d65290b24279ba6f44721b3ea3c4",
+ "objects": [
+ {"key": "com.cloudflare.api.account.zone.23f8d65290b24279ba6f44721b3eaad5"},
+ {"key": "com.cloudflare.api.account.zone.23f8d65290b24279ba6f44721b3eaad5"},
+ {"key": "com.cloudflare.api.account.zone.23f8d65290b24279ba6f44721b3eaad5"},
+ ],
+ },
+ )
+ assert_matches_type(ResourceGroupUpdateResponse, resource_group, path=["response"])
+
+ @parametrize
+ def test_method_update_with_all_params(self, client: Cloudflare) -> None:
+ resource_group = client.iam.resource_groups.update(
+ "6d7f2f5f5b1d4a0e9081fdc98d432fd1",
+ account_id="eb78d65290b24279ba6f44721b3ea3c4",
+ scope={
+ "key": "com.cloudflare.api.account.eb78d65290b24279ba6f44721b3ea3c4",
+ "objects": [
+ {"key": "com.cloudflare.api.account.zone.23f8d65290b24279ba6f44721b3eaad5"},
+ {"key": "com.cloudflare.api.account.zone.23f8d65290b24279ba6f44721b3eaad5"},
+ {"key": "com.cloudflare.api.account.zone.23f8d65290b24279ba6f44721b3eaad5"},
+ ],
+ },
+ meta={"editable": "false"},
+ )
+ assert_matches_type(ResourceGroupUpdateResponse, resource_group, path=["response"])
+
+ @parametrize
+ def test_raw_response_update(self, client: Cloudflare) -> None:
+ response = client.iam.resource_groups.with_raw_response.update(
+ "6d7f2f5f5b1d4a0e9081fdc98d432fd1",
+ account_id="eb78d65290b24279ba6f44721b3ea3c4",
+ scope={
+ "key": "com.cloudflare.api.account.eb78d65290b24279ba6f44721b3ea3c4",
+ "objects": [
+ {"key": "com.cloudflare.api.account.zone.23f8d65290b24279ba6f44721b3eaad5"},
+ {"key": "com.cloudflare.api.account.zone.23f8d65290b24279ba6f44721b3eaad5"},
+ {"key": "com.cloudflare.api.account.zone.23f8d65290b24279ba6f44721b3eaad5"},
+ ],
+ },
+ )
+
+ assert response.is_closed is True
+ assert response.http_request.headers.get("X-Stainless-Lang") == "python"
+ resource_group = response.parse()
+ assert_matches_type(ResourceGroupUpdateResponse, resource_group, path=["response"])
+
+ @parametrize
+ def test_streaming_response_update(self, client: Cloudflare) -> None:
+ with client.iam.resource_groups.with_streaming_response.update(
+ "6d7f2f5f5b1d4a0e9081fdc98d432fd1",
+ account_id="eb78d65290b24279ba6f44721b3ea3c4",
+ scope={
+ "key": "com.cloudflare.api.account.eb78d65290b24279ba6f44721b3ea3c4",
+ "objects": [
+ {"key": "com.cloudflare.api.account.zone.23f8d65290b24279ba6f44721b3eaad5"},
+ {"key": "com.cloudflare.api.account.zone.23f8d65290b24279ba6f44721b3eaad5"},
+ {"key": "com.cloudflare.api.account.zone.23f8d65290b24279ba6f44721b3eaad5"},
+ ],
+ },
+ ) as response:
+ assert not response.is_closed
+ assert response.http_request.headers.get("X-Stainless-Lang") == "python"
+
+ resource_group = response.parse()
+ assert_matches_type(ResourceGroupUpdateResponse, resource_group, 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.iam.resource_groups.with_raw_response.update(
+ "6d7f2f5f5b1d4a0e9081fdc98d432fd1",
+ account_id="",
+ scope={
+ "key": "com.cloudflare.api.account.eb78d65290b24279ba6f44721b3ea3c4",
+ "objects": [
+ {"key": "com.cloudflare.api.account.zone.23f8d65290b24279ba6f44721b3eaad5"},
+ {"key": "com.cloudflare.api.account.zone.23f8d65290b24279ba6f44721b3eaad5"},
+ {"key": "com.cloudflare.api.account.zone.23f8d65290b24279ba6f44721b3eaad5"},
+ ],
+ },
+ )
+
+ with pytest.raises(ValueError, match=r"Expected a non-empty value for `resource_group_id` but received ''"):
+ client.iam.resource_groups.with_raw_response.update(
+ "",
+ account_id="eb78d65290b24279ba6f44721b3ea3c4",
+ scope={
+ "key": "com.cloudflare.api.account.eb78d65290b24279ba6f44721b3ea3c4",
+ "objects": [
+ {"key": "com.cloudflare.api.account.zone.23f8d65290b24279ba6f44721b3eaad5"},
+ {"key": "com.cloudflare.api.account.zone.23f8d65290b24279ba6f44721b3eaad5"},
+ {"key": "com.cloudflare.api.account.zone.23f8d65290b24279ba6f44721b3eaad5"},
+ ],
+ },
+ )
+
+ @parametrize
+ def test_method_list(self, client: Cloudflare) -> None:
+ resource_group = client.iam.resource_groups.list(
+ account_id="eb78d65290b24279ba6f44721b3ea3c4",
+ )
+ assert_matches_type(SyncV4PagePaginationArray[object], resource_group, path=["response"])
+
+ @parametrize
+ def test_method_list_with_all_params(self, client: Cloudflare) -> None:
+ resource_group = client.iam.resource_groups.list(
+ account_id="eb78d65290b24279ba6f44721b3ea3c4",
+ id="6d7f2f5f5b1d4a0e9081fdc98d432fd1",
+ name="NameOfTheResourceGroup",
+ page=1,
+ per_page=5,
+ )
+ assert_matches_type(SyncV4PagePaginationArray[object], resource_group, path=["response"])
+
+ @parametrize
+ def test_raw_response_list(self, client: Cloudflare) -> None:
+ response = client.iam.resource_groups.with_raw_response.list(
+ account_id="eb78d65290b24279ba6f44721b3ea3c4",
+ )
+
+ assert response.is_closed is True
+ assert response.http_request.headers.get("X-Stainless-Lang") == "python"
+ resource_group = response.parse()
+ assert_matches_type(SyncV4PagePaginationArray[object], resource_group, path=["response"])
+
+ @parametrize
+ def test_streaming_response_list(self, client: Cloudflare) -> None:
+ with client.iam.resource_groups.with_streaming_response.list(
+ account_id="eb78d65290b24279ba6f44721b3ea3c4",
+ ) as response:
+ assert not response.is_closed
+ assert response.http_request.headers.get("X-Stainless-Lang") == "python"
+
+ resource_group = response.parse()
+ assert_matches_type(SyncV4PagePaginationArray[object], resource_group, 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.iam.resource_groups.with_raw_response.list(
+ account_id="",
+ )
+
+ @parametrize
+ def test_method_delete(self, client: Cloudflare) -> None:
+ resource_group = client.iam.resource_groups.delete(
+ "6d7f2f5f5b1d4a0e9081fdc98d432fd1",
+ account_id="eb78d65290b24279ba6f44721b3ea3c4",
+ )
+ assert_matches_type(Optional[ResourceGroupDeleteResponse], resource_group, path=["response"])
+
+ @parametrize
+ def test_raw_response_delete(self, client: Cloudflare) -> None:
+ response = client.iam.resource_groups.with_raw_response.delete(
+ "6d7f2f5f5b1d4a0e9081fdc98d432fd1",
+ account_id="eb78d65290b24279ba6f44721b3ea3c4",
+ )
+
+ assert response.is_closed is True
+ assert response.http_request.headers.get("X-Stainless-Lang") == "python"
+ resource_group = response.parse()
+ assert_matches_type(Optional[ResourceGroupDeleteResponse], resource_group, path=["response"])
+
+ @parametrize
+ def test_streaming_response_delete(self, client: Cloudflare) -> None:
+ with client.iam.resource_groups.with_streaming_response.delete(
+ "6d7f2f5f5b1d4a0e9081fdc98d432fd1",
+ account_id="eb78d65290b24279ba6f44721b3ea3c4",
+ ) as response:
+ assert not response.is_closed
+ assert response.http_request.headers.get("X-Stainless-Lang") == "python"
+
+ resource_group = response.parse()
+ assert_matches_type(Optional[ResourceGroupDeleteResponse], resource_group, 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.iam.resource_groups.with_raw_response.delete(
+ "6d7f2f5f5b1d4a0e9081fdc98d432fd1",
+ account_id="",
+ )
+
+ with pytest.raises(ValueError, match=r"Expected a non-empty value for `resource_group_id` but received ''"):
+ client.iam.resource_groups.with_raw_response.delete(
+ "",
+ account_id="eb78d65290b24279ba6f44721b3ea3c4",
+ )
+
+ @parametrize
+ def test_method_get(self, client: Cloudflare) -> None:
+ resource_group = client.iam.resource_groups.get(
+ "6d7f2f5f5b1d4a0e9081fdc98d432fd1",
+ account_id="eb78d65290b24279ba6f44721b3ea3c4",
+ )
+ assert_matches_type(ResourceGroupGetResponse, resource_group, path=["response"])
+
+ @parametrize
+ def test_raw_response_get(self, client: Cloudflare) -> None:
+ response = client.iam.resource_groups.with_raw_response.get(
+ "6d7f2f5f5b1d4a0e9081fdc98d432fd1",
+ account_id="eb78d65290b24279ba6f44721b3ea3c4",
+ )
+
+ assert response.is_closed is True
+ assert response.http_request.headers.get("X-Stainless-Lang") == "python"
+ resource_group = response.parse()
+ assert_matches_type(ResourceGroupGetResponse, resource_group, path=["response"])
+
+ @parametrize
+ def test_streaming_response_get(self, client: Cloudflare) -> None:
+ with client.iam.resource_groups.with_streaming_response.get(
+ "6d7f2f5f5b1d4a0e9081fdc98d432fd1",
+ account_id="eb78d65290b24279ba6f44721b3ea3c4",
+ ) as response:
+ assert not response.is_closed
+ assert response.http_request.headers.get("X-Stainless-Lang") == "python"
+
+ resource_group = response.parse()
+ assert_matches_type(ResourceGroupGetResponse, resource_group, 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.iam.resource_groups.with_raw_response.get(
+ "6d7f2f5f5b1d4a0e9081fdc98d432fd1",
+ account_id="",
+ )
+
+ with pytest.raises(ValueError, match=r"Expected a non-empty value for `resource_group_id` but received ''"):
+ client.iam.resource_groups.with_raw_response.get(
+ "",
+ account_id="eb78d65290b24279ba6f44721b3ea3c4",
+ )
+
+
+class TestAsyncResourceGroups:
+ parametrize = pytest.mark.parametrize("async_client", [False, True], indirect=True, ids=["loose", "strict"])
+
+ @parametrize
+ async def test_method_create(self, async_client: AsyncCloudflare) -> None:
+ resource_group = await async_client.iam.resource_groups.create(
+ account_id="eb78d65290b24279ba6f44721b3ea3c4",
+ scope={
+ "key": "com.cloudflare.api.account.eb78d65290b24279ba6f44721b3ea3c4",
+ "objects": [
+ {"key": "com.cloudflare.api.account.zone.23f8d65290b24279ba6f44721b3eaad5"},
+ {"key": "com.cloudflare.api.account.zone.23f8d65290b24279ba6f44721b3eaad5"},
+ {"key": "com.cloudflare.api.account.zone.23f8d65290b24279ba6f44721b3eaad5"},
+ ],
+ },
+ )
+ assert_matches_type(ResourceGroupCreateResponse, resource_group, path=["response"])
+
+ @parametrize
+ async def test_method_create_with_all_params(self, async_client: AsyncCloudflare) -> None:
+ resource_group = await async_client.iam.resource_groups.create(
+ account_id="eb78d65290b24279ba6f44721b3ea3c4",
+ scope={
+ "key": "com.cloudflare.api.account.eb78d65290b24279ba6f44721b3ea3c4",
+ "objects": [
+ {"key": "com.cloudflare.api.account.zone.23f8d65290b24279ba6f44721b3eaad5"},
+ {"key": "com.cloudflare.api.account.zone.23f8d65290b24279ba6f44721b3eaad5"},
+ {"key": "com.cloudflare.api.account.zone.23f8d65290b24279ba6f44721b3eaad5"},
+ ],
+ },
+ meta={"editable": "false"},
+ )
+ assert_matches_type(ResourceGroupCreateResponse, resource_group, path=["response"])
+
+ @parametrize
+ async def test_raw_response_create(self, async_client: AsyncCloudflare) -> None:
+ response = await async_client.iam.resource_groups.with_raw_response.create(
+ account_id="eb78d65290b24279ba6f44721b3ea3c4",
+ scope={
+ "key": "com.cloudflare.api.account.eb78d65290b24279ba6f44721b3ea3c4",
+ "objects": [
+ {"key": "com.cloudflare.api.account.zone.23f8d65290b24279ba6f44721b3eaad5"},
+ {"key": "com.cloudflare.api.account.zone.23f8d65290b24279ba6f44721b3eaad5"},
+ {"key": "com.cloudflare.api.account.zone.23f8d65290b24279ba6f44721b3eaad5"},
+ ],
+ },
+ )
+
+ assert response.is_closed is True
+ assert response.http_request.headers.get("X-Stainless-Lang") == "python"
+ resource_group = await response.parse()
+ assert_matches_type(ResourceGroupCreateResponse, resource_group, path=["response"])
+
+ @parametrize
+ async def test_streaming_response_create(self, async_client: AsyncCloudflare) -> None:
+ async with async_client.iam.resource_groups.with_streaming_response.create(
+ account_id="eb78d65290b24279ba6f44721b3ea3c4",
+ scope={
+ "key": "com.cloudflare.api.account.eb78d65290b24279ba6f44721b3ea3c4",
+ "objects": [
+ {"key": "com.cloudflare.api.account.zone.23f8d65290b24279ba6f44721b3eaad5"},
+ {"key": "com.cloudflare.api.account.zone.23f8d65290b24279ba6f44721b3eaad5"},
+ {"key": "com.cloudflare.api.account.zone.23f8d65290b24279ba6f44721b3eaad5"},
+ ],
+ },
+ ) as response:
+ assert not response.is_closed
+ assert response.http_request.headers.get("X-Stainless-Lang") == "python"
+
+ resource_group = await response.parse()
+ assert_matches_type(ResourceGroupCreateResponse, resource_group, 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.iam.resource_groups.with_raw_response.create(
+ account_id="",
+ scope={
+ "key": "com.cloudflare.api.account.eb78d65290b24279ba6f44721b3ea3c4",
+ "objects": [
+ {"key": "com.cloudflare.api.account.zone.23f8d65290b24279ba6f44721b3eaad5"},
+ {"key": "com.cloudflare.api.account.zone.23f8d65290b24279ba6f44721b3eaad5"},
+ {"key": "com.cloudflare.api.account.zone.23f8d65290b24279ba6f44721b3eaad5"},
+ ],
+ },
+ )
+
+ @parametrize
+ async def test_method_update(self, async_client: AsyncCloudflare) -> None:
+ resource_group = await async_client.iam.resource_groups.update(
+ "6d7f2f5f5b1d4a0e9081fdc98d432fd1",
+ account_id="eb78d65290b24279ba6f44721b3ea3c4",
+ scope={
+ "key": "com.cloudflare.api.account.eb78d65290b24279ba6f44721b3ea3c4",
+ "objects": [
+ {"key": "com.cloudflare.api.account.zone.23f8d65290b24279ba6f44721b3eaad5"},
+ {"key": "com.cloudflare.api.account.zone.23f8d65290b24279ba6f44721b3eaad5"},
+ {"key": "com.cloudflare.api.account.zone.23f8d65290b24279ba6f44721b3eaad5"},
+ ],
+ },
+ )
+ assert_matches_type(ResourceGroupUpdateResponse, resource_group, path=["response"])
+
+ @parametrize
+ async def test_method_update_with_all_params(self, async_client: AsyncCloudflare) -> None:
+ resource_group = await async_client.iam.resource_groups.update(
+ "6d7f2f5f5b1d4a0e9081fdc98d432fd1",
+ account_id="eb78d65290b24279ba6f44721b3ea3c4",
+ scope={
+ "key": "com.cloudflare.api.account.eb78d65290b24279ba6f44721b3ea3c4",
+ "objects": [
+ {"key": "com.cloudflare.api.account.zone.23f8d65290b24279ba6f44721b3eaad5"},
+ {"key": "com.cloudflare.api.account.zone.23f8d65290b24279ba6f44721b3eaad5"},
+ {"key": "com.cloudflare.api.account.zone.23f8d65290b24279ba6f44721b3eaad5"},
+ ],
+ },
+ meta={"editable": "false"},
+ )
+ assert_matches_type(ResourceGroupUpdateResponse, resource_group, path=["response"])
+
+ @parametrize
+ async def test_raw_response_update(self, async_client: AsyncCloudflare) -> None:
+ response = await async_client.iam.resource_groups.with_raw_response.update(
+ "6d7f2f5f5b1d4a0e9081fdc98d432fd1",
+ account_id="eb78d65290b24279ba6f44721b3ea3c4",
+ scope={
+ "key": "com.cloudflare.api.account.eb78d65290b24279ba6f44721b3ea3c4",
+ "objects": [
+ {"key": "com.cloudflare.api.account.zone.23f8d65290b24279ba6f44721b3eaad5"},
+ {"key": "com.cloudflare.api.account.zone.23f8d65290b24279ba6f44721b3eaad5"},
+ {"key": "com.cloudflare.api.account.zone.23f8d65290b24279ba6f44721b3eaad5"},
+ ],
+ },
+ )
+
+ assert response.is_closed is True
+ assert response.http_request.headers.get("X-Stainless-Lang") == "python"
+ resource_group = await response.parse()
+ assert_matches_type(ResourceGroupUpdateResponse, resource_group, path=["response"])
+
+ @parametrize
+ async def test_streaming_response_update(self, async_client: AsyncCloudflare) -> None:
+ async with async_client.iam.resource_groups.with_streaming_response.update(
+ "6d7f2f5f5b1d4a0e9081fdc98d432fd1",
+ account_id="eb78d65290b24279ba6f44721b3ea3c4",
+ scope={
+ "key": "com.cloudflare.api.account.eb78d65290b24279ba6f44721b3ea3c4",
+ "objects": [
+ {"key": "com.cloudflare.api.account.zone.23f8d65290b24279ba6f44721b3eaad5"},
+ {"key": "com.cloudflare.api.account.zone.23f8d65290b24279ba6f44721b3eaad5"},
+ {"key": "com.cloudflare.api.account.zone.23f8d65290b24279ba6f44721b3eaad5"},
+ ],
+ },
+ ) as response:
+ assert not response.is_closed
+ assert response.http_request.headers.get("X-Stainless-Lang") == "python"
+
+ resource_group = await response.parse()
+ assert_matches_type(ResourceGroupUpdateResponse, resource_group, 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.iam.resource_groups.with_raw_response.update(
+ "6d7f2f5f5b1d4a0e9081fdc98d432fd1",
+ account_id="",
+ scope={
+ "key": "com.cloudflare.api.account.eb78d65290b24279ba6f44721b3ea3c4",
+ "objects": [
+ {"key": "com.cloudflare.api.account.zone.23f8d65290b24279ba6f44721b3eaad5"},
+ {"key": "com.cloudflare.api.account.zone.23f8d65290b24279ba6f44721b3eaad5"},
+ {"key": "com.cloudflare.api.account.zone.23f8d65290b24279ba6f44721b3eaad5"},
+ ],
+ },
+ )
+
+ with pytest.raises(ValueError, match=r"Expected a non-empty value for `resource_group_id` but received ''"):
+ await async_client.iam.resource_groups.with_raw_response.update(
+ "",
+ account_id="eb78d65290b24279ba6f44721b3ea3c4",
+ scope={
+ "key": "com.cloudflare.api.account.eb78d65290b24279ba6f44721b3ea3c4",
+ "objects": [
+ {"key": "com.cloudflare.api.account.zone.23f8d65290b24279ba6f44721b3eaad5"},
+ {"key": "com.cloudflare.api.account.zone.23f8d65290b24279ba6f44721b3eaad5"},
+ {"key": "com.cloudflare.api.account.zone.23f8d65290b24279ba6f44721b3eaad5"},
+ ],
+ },
+ )
+
+ @parametrize
+ async def test_method_list(self, async_client: AsyncCloudflare) -> None:
+ resource_group = await async_client.iam.resource_groups.list(
+ account_id="eb78d65290b24279ba6f44721b3ea3c4",
+ )
+ assert_matches_type(AsyncV4PagePaginationArray[object], resource_group, path=["response"])
+
+ @parametrize
+ async def test_method_list_with_all_params(self, async_client: AsyncCloudflare) -> None:
+ resource_group = await async_client.iam.resource_groups.list(
+ account_id="eb78d65290b24279ba6f44721b3ea3c4",
+ id="6d7f2f5f5b1d4a0e9081fdc98d432fd1",
+ name="NameOfTheResourceGroup",
+ page=1,
+ per_page=5,
+ )
+ assert_matches_type(AsyncV4PagePaginationArray[object], resource_group, path=["response"])
+
+ @parametrize
+ async def test_raw_response_list(self, async_client: AsyncCloudflare) -> None:
+ response = await async_client.iam.resource_groups.with_raw_response.list(
+ account_id="eb78d65290b24279ba6f44721b3ea3c4",
+ )
+
+ assert response.is_closed is True
+ assert response.http_request.headers.get("X-Stainless-Lang") == "python"
+ resource_group = await response.parse()
+ assert_matches_type(AsyncV4PagePaginationArray[object], resource_group, path=["response"])
+
+ @parametrize
+ async def test_streaming_response_list(self, async_client: AsyncCloudflare) -> None:
+ async with async_client.iam.resource_groups.with_streaming_response.list(
+ account_id="eb78d65290b24279ba6f44721b3ea3c4",
+ ) as response:
+ assert not response.is_closed
+ assert response.http_request.headers.get("X-Stainless-Lang") == "python"
+
+ resource_group = await response.parse()
+ assert_matches_type(AsyncV4PagePaginationArray[object], resource_group, 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.iam.resource_groups.with_raw_response.list(
+ account_id="",
+ )
+
+ @parametrize
+ async def test_method_delete(self, async_client: AsyncCloudflare) -> None:
+ resource_group = await async_client.iam.resource_groups.delete(
+ "6d7f2f5f5b1d4a0e9081fdc98d432fd1",
+ account_id="eb78d65290b24279ba6f44721b3ea3c4",
+ )
+ assert_matches_type(Optional[ResourceGroupDeleteResponse], resource_group, path=["response"])
+
+ @parametrize
+ async def test_raw_response_delete(self, async_client: AsyncCloudflare) -> None:
+ response = await async_client.iam.resource_groups.with_raw_response.delete(
+ "6d7f2f5f5b1d4a0e9081fdc98d432fd1",
+ account_id="eb78d65290b24279ba6f44721b3ea3c4",
+ )
+
+ assert response.is_closed is True
+ assert response.http_request.headers.get("X-Stainless-Lang") == "python"
+ resource_group = await response.parse()
+ assert_matches_type(Optional[ResourceGroupDeleteResponse], resource_group, path=["response"])
+
+ @parametrize
+ async def test_streaming_response_delete(self, async_client: AsyncCloudflare) -> None:
+ async with async_client.iam.resource_groups.with_streaming_response.delete(
+ "6d7f2f5f5b1d4a0e9081fdc98d432fd1",
+ account_id="eb78d65290b24279ba6f44721b3ea3c4",
+ ) as response:
+ assert not response.is_closed
+ assert response.http_request.headers.get("X-Stainless-Lang") == "python"
+
+ resource_group = await response.parse()
+ assert_matches_type(Optional[ResourceGroupDeleteResponse], resource_group, 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.iam.resource_groups.with_raw_response.delete(
+ "6d7f2f5f5b1d4a0e9081fdc98d432fd1",
+ account_id="",
+ )
+
+ with pytest.raises(ValueError, match=r"Expected a non-empty value for `resource_group_id` but received ''"):
+ await async_client.iam.resource_groups.with_raw_response.delete(
+ "",
+ account_id="eb78d65290b24279ba6f44721b3ea3c4",
+ )
+
+ @parametrize
+ async def test_method_get(self, async_client: AsyncCloudflare) -> None:
+ resource_group = await async_client.iam.resource_groups.get(
+ "6d7f2f5f5b1d4a0e9081fdc98d432fd1",
+ account_id="eb78d65290b24279ba6f44721b3ea3c4",
+ )
+ assert_matches_type(ResourceGroupGetResponse, resource_group, path=["response"])
+
+ @parametrize
+ async def test_raw_response_get(self, async_client: AsyncCloudflare) -> None:
+ response = await async_client.iam.resource_groups.with_raw_response.get(
+ "6d7f2f5f5b1d4a0e9081fdc98d432fd1",
+ account_id="eb78d65290b24279ba6f44721b3ea3c4",
+ )
+
+ assert response.is_closed is True
+ assert response.http_request.headers.get("X-Stainless-Lang") == "python"
+ resource_group = await response.parse()
+ assert_matches_type(ResourceGroupGetResponse, resource_group, path=["response"])
+
+ @parametrize
+ async def test_streaming_response_get(self, async_client: AsyncCloudflare) -> None:
+ async with async_client.iam.resource_groups.with_streaming_response.get(
+ "6d7f2f5f5b1d4a0e9081fdc98d432fd1",
+ account_id="eb78d65290b24279ba6f44721b3ea3c4",
+ ) as response:
+ assert not response.is_closed
+ assert response.http_request.headers.get("X-Stainless-Lang") == "python"
+
+ resource_group = await response.parse()
+ assert_matches_type(ResourceGroupGetResponse, resource_group, 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.iam.resource_groups.with_raw_response.get(
+ "6d7f2f5f5b1d4a0e9081fdc98d432fd1",
+ account_id="",
+ )
+
+ with pytest.raises(ValueError, match=r"Expected a non-empty value for `resource_group_id` but received ''"):
+ await async_client.iam.resource_groups.with_raw_response.get(
+ "",
+ account_id="eb78d65290b24279ba6f44721b3ea3c4",
+ )
diff --git a/tests/api_resources/page_shield/test_cookies.py b/tests/api_resources/page_shield/test_cookies.py
new file mode 100644
index 00000000000..7c516ab4e7d
--- /dev/null
+++ b/tests/api_resources/page_shield/test_cookies.py
@@ -0,0 +1,237 @@
+# 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.pagination import SyncSinglePage, AsyncSinglePage
+from cloudflare.types.page_shield import CookieGetResponse, CookieListResponse
+
+base_url = os.environ.get("TEST_API_BASE_URL", "http://127.0.0.1:4010")
+
+
+class TestCookies:
+ parametrize = pytest.mark.parametrize("client", [False, True], indirect=True, ids=["loose", "strict"])
+
+ @parametrize
+ def test_method_list(self, client: Cloudflare) -> None:
+ cookie = client.page_shield.cookies.list(
+ zone_id="023e105f4ecef8ad9ca31a8372d0c353",
+ )
+ assert_matches_type(SyncSinglePage[CookieListResponse], cookie, path=["response"])
+
+ @parametrize
+ def test_method_list_with_all_params(self, client: Cloudflare) -> None:
+ cookie = client.page_shield.cookies.list(
+ zone_id="023e105f4ecef8ad9ca31a8372d0c353",
+ direction="asc",
+ domain="example.com",
+ export="csv",
+ hosts="blog.cloudflare.com,www.example*,*cloudflare.com",
+ http_only=True,
+ name="session_id",
+ order_by="first_seen_at",
+ page="2",
+ page_url="example.com/page,*/checkout,example.com/*,*checkout*",
+ path="/",
+ per_page=100,
+ same_site="strict",
+ secure=True,
+ type="first_party",
+ )
+ assert_matches_type(SyncSinglePage[CookieListResponse], cookie, path=["response"])
+
+ @parametrize
+ def test_raw_response_list(self, client: Cloudflare) -> None:
+ response = client.page_shield.cookies.with_raw_response.list(
+ zone_id="023e105f4ecef8ad9ca31a8372d0c353",
+ )
+
+ assert response.is_closed is True
+ assert response.http_request.headers.get("X-Stainless-Lang") == "python"
+ cookie = response.parse()
+ assert_matches_type(SyncSinglePage[CookieListResponse], cookie, path=["response"])
+
+ @parametrize
+ def test_streaming_response_list(self, client: Cloudflare) -> None:
+ with client.page_shield.cookies.with_streaming_response.list(
+ zone_id="023e105f4ecef8ad9ca31a8372d0c353",
+ ) as response:
+ assert not response.is_closed
+ assert response.http_request.headers.get("X-Stainless-Lang") == "python"
+
+ cookie = response.parse()
+ assert_matches_type(SyncSinglePage[CookieListResponse], cookie, 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 `zone_id` but received ''"):
+ client.page_shield.cookies.with_raw_response.list(
+ zone_id="",
+ )
+
+ @parametrize
+ def test_method_get(self, client: Cloudflare) -> None:
+ cookie = client.page_shield.cookies.get(
+ "023e105f4ecef8ad9ca31a8372d0c353",
+ zone_id="023e105f4ecef8ad9ca31a8372d0c353",
+ )
+ assert_matches_type(Optional[CookieGetResponse], cookie, path=["response"])
+
+ @parametrize
+ def test_raw_response_get(self, client: Cloudflare) -> None:
+ response = client.page_shield.cookies.with_raw_response.get(
+ "023e105f4ecef8ad9ca31a8372d0c353",
+ zone_id="023e105f4ecef8ad9ca31a8372d0c353",
+ )
+
+ assert response.is_closed is True
+ assert response.http_request.headers.get("X-Stainless-Lang") == "python"
+ cookie = response.parse()
+ assert_matches_type(Optional[CookieGetResponse], cookie, path=["response"])
+
+ @parametrize
+ def test_streaming_response_get(self, client: Cloudflare) -> None:
+ with client.page_shield.cookies.with_streaming_response.get(
+ "023e105f4ecef8ad9ca31a8372d0c353",
+ zone_id="023e105f4ecef8ad9ca31a8372d0c353",
+ ) as response:
+ assert not response.is_closed
+ assert response.http_request.headers.get("X-Stainless-Lang") == "python"
+
+ cookie = response.parse()
+ assert_matches_type(Optional[CookieGetResponse], cookie, 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.page_shield.cookies.with_raw_response.get(
+ "023e105f4ecef8ad9ca31a8372d0c353",
+ zone_id="",
+ )
+
+ with pytest.raises(ValueError, match=r"Expected a non-empty value for `cookie_id` but received ''"):
+ client.page_shield.cookies.with_raw_response.get(
+ "",
+ zone_id="023e105f4ecef8ad9ca31a8372d0c353",
+ )
+
+
+class TestAsyncCookies:
+ parametrize = pytest.mark.parametrize("async_client", [False, True], indirect=True, ids=["loose", "strict"])
+
+ @parametrize
+ async def test_method_list(self, async_client: AsyncCloudflare) -> None:
+ cookie = await async_client.page_shield.cookies.list(
+ zone_id="023e105f4ecef8ad9ca31a8372d0c353",
+ )
+ assert_matches_type(AsyncSinglePage[CookieListResponse], cookie, path=["response"])
+
+ @parametrize
+ async def test_method_list_with_all_params(self, async_client: AsyncCloudflare) -> None:
+ cookie = await async_client.page_shield.cookies.list(
+ zone_id="023e105f4ecef8ad9ca31a8372d0c353",
+ direction="asc",
+ domain="example.com",
+ export="csv",
+ hosts="blog.cloudflare.com,www.example*,*cloudflare.com",
+ http_only=True,
+ name="session_id",
+ order_by="first_seen_at",
+ page="2",
+ page_url="example.com/page,*/checkout,example.com/*,*checkout*",
+ path="/",
+ per_page=100,
+ same_site="strict",
+ secure=True,
+ type="first_party",
+ )
+ assert_matches_type(AsyncSinglePage[CookieListResponse], cookie, path=["response"])
+
+ @parametrize
+ async def test_raw_response_list(self, async_client: AsyncCloudflare) -> None:
+ response = await async_client.page_shield.cookies.with_raw_response.list(
+ zone_id="023e105f4ecef8ad9ca31a8372d0c353",
+ )
+
+ assert response.is_closed is True
+ assert response.http_request.headers.get("X-Stainless-Lang") == "python"
+ cookie = await response.parse()
+ assert_matches_type(AsyncSinglePage[CookieListResponse], cookie, path=["response"])
+
+ @parametrize
+ async def test_streaming_response_list(self, async_client: AsyncCloudflare) -> None:
+ async with async_client.page_shield.cookies.with_streaming_response.list(
+ zone_id="023e105f4ecef8ad9ca31a8372d0c353",
+ ) as response:
+ assert not response.is_closed
+ assert response.http_request.headers.get("X-Stainless-Lang") == "python"
+
+ cookie = await response.parse()
+ assert_matches_type(AsyncSinglePage[CookieListResponse], cookie, 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 `zone_id` but received ''"):
+ await async_client.page_shield.cookies.with_raw_response.list(
+ zone_id="",
+ )
+
+ @parametrize
+ async def test_method_get(self, async_client: AsyncCloudflare) -> None:
+ cookie = await async_client.page_shield.cookies.get(
+ "023e105f4ecef8ad9ca31a8372d0c353",
+ zone_id="023e105f4ecef8ad9ca31a8372d0c353",
+ )
+ assert_matches_type(Optional[CookieGetResponse], cookie, path=["response"])
+
+ @parametrize
+ async def test_raw_response_get(self, async_client: AsyncCloudflare) -> None:
+ response = await async_client.page_shield.cookies.with_raw_response.get(
+ "023e105f4ecef8ad9ca31a8372d0c353",
+ zone_id="023e105f4ecef8ad9ca31a8372d0c353",
+ )
+
+ assert response.is_closed is True
+ assert response.http_request.headers.get("X-Stainless-Lang") == "python"
+ cookie = await response.parse()
+ assert_matches_type(Optional[CookieGetResponse], cookie, path=["response"])
+
+ @parametrize
+ async def test_streaming_response_get(self, async_client: AsyncCloudflare) -> None:
+ async with async_client.page_shield.cookies.with_streaming_response.get(
+ "023e105f4ecef8ad9ca31a8372d0c353",
+ zone_id="023e105f4ecef8ad9ca31a8372d0c353",
+ ) as response:
+ assert not response.is_closed
+ assert response.http_request.headers.get("X-Stainless-Lang") == "python"
+
+ cookie = await response.parse()
+ assert_matches_type(Optional[CookieGetResponse], cookie, 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.page_shield.cookies.with_raw_response.get(
+ "023e105f4ecef8ad9ca31a8372d0c353",
+ zone_id="",
+ )
+
+ with pytest.raises(ValueError, match=r"Expected a non-empty value for `cookie_id` but received ''"):
+ await async_client.page_shield.cookies.with_raw_response.get(
+ "",
+ zone_id="023e105f4ecef8ad9ca31a8372d0c353",
+ )