From 6183681a3b05a7ef00db573df23340c5aa5d1552 Mon Sep 17 00:00:00 2001
From: "stainless-app[bot]"
<142633134+stainless-app[bot]@users.noreply.github.com>
Date: Fri, 13 Dec 2024 01:23:01 +0000
Subject: [PATCH] feat(api): fix internal URL mappings (#2267)
---
.stats.yml | 2 +-
api.md | 56 ++
src/cloudflare/_client.py | 37 ++
src/cloudflare/resources/abuse_reports.py | 492 ++++++++++++++++++
.../resources/zero_trust/devices/__init__.py | 14 +
.../resources/zero_trust/devices/devices.py | 32 ++
.../zero_trust/devices/fleet_status.py | 220 ++++++++
.../resources/zero_trust/dex/__init__.py | 14 +
.../zero_trust/dex/commands/__init__.py | 47 ++
.../zero_trust/dex/commands/commands.py | 417 +++++++++++++++
.../zero_trust/dex/commands/downloads.py | 190 +++++++
.../zero_trust/dex/commands/quota.py | 176 +++++++
.../resources/zero_trust/dex/dex.py | 33 ++
src/cloudflare/resources/zones/holds.py | 134 ++++-
.../types/abuse_reports/__init__.py | 6 +
.../abuse_report_create_params.py | 140 +++++
.../abuse_report_create_response.py | 7 +
.../types/zero_trust/devices/__init__.py | 2 +
.../devices/fleet_status_get_params.py | 20 +
.../devices/fleet_status_get_response.py | 268 ++++++++++
.../types/zero_trust/dex/__init__.py | 4 +
.../zero_trust/dex/command_create_params.py | 57 ++
.../zero_trust/dex/command_create_response.py | 30 ++
.../zero_trust/dex/command_list_params.py | 39 ++
.../zero_trust/dex/command_list_response.py | 30 ++
.../types/zero_trust/dex/commands/__init__.py | 2 +
.../dex/commands/quota_get_response.py | 18 +
src/cloudflare/types/zones/__init__.py | 1 +
.../types/zones/hold_edit_params.py | 29 ++
tests/api_resources/test_abuse_reports.py | 233 +++++++++
.../zero_trust/devices/test_fleet_status.py | 150 ++++++
.../zero_trust/dex/commands/__init__.py | 1 +
.../zero_trust/dex/commands/test_downloads.py | 184 +++++++
.../zero_trust/dex/commands/test_quota.py | 98 ++++
.../zero_trust/dex/test_commands.py | 281 ++++++++++
tests/api_resources/zones/test_holds.py | 94 ++++
36 files changed, 3556 insertions(+), 2 deletions(-)
create mode 100644 src/cloudflare/resources/abuse_reports.py
create mode 100644 src/cloudflare/resources/zero_trust/devices/fleet_status.py
create mode 100644 src/cloudflare/resources/zero_trust/dex/commands/__init__.py
create mode 100644 src/cloudflare/resources/zero_trust/dex/commands/commands.py
create mode 100644 src/cloudflare/resources/zero_trust/dex/commands/downloads.py
create mode 100644 src/cloudflare/resources/zero_trust/dex/commands/quota.py
create mode 100644 src/cloudflare/types/abuse_reports/__init__.py
create mode 100644 src/cloudflare/types/abuse_reports/abuse_report_create_params.py
create mode 100644 src/cloudflare/types/abuse_reports/abuse_report_create_response.py
create mode 100644 src/cloudflare/types/zero_trust/devices/fleet_status_get_params.py
create mode 100644 src/cloudflare/types/zero_trust/devices/fleet_status_get_response.py
create mode 100644 src/cloudflare/types/zero_trust/dex/command_create_params.py
create mode 100644 src/cloudflare/types/zero_trust/dex/command_create_response.py
create mode 100644 src/cloudflare/types/zero_trust/dex/command_list_params.py
create mode 100644 src/cloudflare/types/zero_trust/dex/command_list_response.py
create mode 100644 src/cloudflare/types/zero_trust/dex/commands/quota_get_response.py
create mode 100644 src/cloudflare/types/zones/hold_edit_params.py
create mode 100644 tests/api_resources/test_abuse_reports.py
create mode 100644 tests/api_resources/zero_trust/devices/test_fleet_status.py
create mode 100644 tests/api_resources/zero_trust/dex/commands/__init__.py
create mode 100644 tests/api_resources/zero_trust/dex/commands/test_downloads.py
create mode 100644 tests/api_resources/zero_trust/dex/commands/test_quota.py
create mode 100644 tests/api_resources/zero_trust/dex/test_commands.py
diff --git a/.stats.yml b/.stats.yml
index 3b704f87bcf..5d7b2c16a46 100644
--- a/.stats.yml
+++ b/.stats.yml
@@ -1,2 +1,2 @@
-configured_endpoints: 1455
+configured_endpoints: 1462
openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/cloudflare%2Fcloudflare-4118c37824cecf34c05447175906b84c57105e89ea6a092fee7047b46613e094.yml
diff --git a/api.md b/api.md
index 6e0daf9fc74..1d108198dc0 100644
--- a/api.md
+++ b/api.md
@@ -417,6 +417,7 @@ Methods:
- client.zones.holds.create(\*, zone_id, \*\*params) -> ZoneHold
- client.zones.holds.delete(\*, zone_id, \*\*params) -> ZoneHold
+- client.zones.holds.edit(\*, zone_id, \*\*params) -> ZoneHold
- client.zones.holds.get(\*, zone_id) -> ZoneHold
## Subscriptions
@@ -4841,6 +4842,18 @@ Methods:
- client.zero_trust.devices.networks.delete(network_id, \*, account_id) -> Optional[NetworkDeleteResponse]
- client.zero_trust.devices.networks.get(network_id, \*, account_id) -> Optional[DeviceNetwork]
+### FleetStatus
+
+Types:
+
+```python
+from cloudflare.types.zero_trust.devices import FleetStatusGetResponse
+```
+
+Methods:
+
+- client.zero_trust.devices.fleet_status.get(device_id, \*, account_id, \*\*params) -> FleetStatusGetResponse
+
### Policies
Types:
@@ -5579,6 +5592,37 @@ from cloudflare.types.zero_trust import (
)
```
+### Commands
+
+Types:
+
+```python
+from cloudflare.types.zero_trust.dex import CommandCreateResponse, CommandListResponse
+```
+
+Methods:
+
+- client.zero_trust.dex.commands.create(\*, account_id, \*\*params) -> Optional[CommandCreateResponse]
+- client.zero_trust.dex.commands.list(\*, account_id, \*\*params) -> SyncV4PagePagination[Optional[CommandListResponse]]
+
+#### Downloads
+
+Methods:
+
+- client.zero_trust.dex.commands.downloads.get(filename, \*, account_id, command_id) -> BinaryAPIResponse
+
+#### Quota
+
+Types:
+
+```python
+from cloudflare.types.zero_trust.dex.commands import QuotaGetResponse
+```
+
+Methods:
+
+- client.zero_trust.dex.commands.quota.get(\*, account_id) -> Optional[QuotaGetResponse]
+
### Colos
Types:
@@ -8359,3 +8403,15 @@ from cloudflare.types.content_scanning import SettingGetResponse
Methods:
- client.content_scanning.settings.get(\*, zone_id) -> SettingGetResponse
+
+# AbuseReports
+
+Types:
+
+```python
+from cloudflare.types.abuse_reports import AbuseReportCreateResponse
+```
+
+Methods:
+
+- client.abuse_reports.create(report_type, \*, account_id, \*\*params) -> str
diff --git a/src/cloudflare/_client.py b/src/cloudflare/_client.py
index ec966ca654c..4d5c2d1b7ff 100644
--- a/src/cloudflare/_client.py
+++ b/src/cloudflare/_client.py
@@ -91,6 +91,7 @@
dns_firewall,
healthchecks,
security_txt,
+ abuse_reports,
email_routing,
magic_transit,
waiting_rooms,
@@ -711,6 +712,12 @@ def content_scanning(self) -> content_scanning.ContentScanningResource:
return ContentScanningResource(self)
+ @cached_property
+ def abuse_reports(self) -> abuse_reports.AbuseReportsResource:
+ from .resources.abuse_reports import AbuseReportsResource
+
+ return AbuseReportsResource(self)
+
@cached_property
def with_raw_response(self) -> CloudflareWithRawResponse:
return CloudflareWithRawResponse(self)
@@ -1470,6 +1477,12 @@ def content_scanning(self) -> content_scanning.AsyncContentScanningResource:
return AsyncContentScanningResource(self)
+ @cached_property
+ def abuse_reports(self) -> abuse_reports.AsyncAbuseReportsResource:
+ from .resources.abuse_reports import AsyncAbuseReportsResource
+
+ return AsyncAbuseReportsResource(self)
+
@cached_property
def with_raw_response(self) -> AsyncCloudflareWithRawResponse:
return AsyncCloudflareWithRawResponse(self)
@@ -2164,6 +2177,12 @@ def content_scanning(self) -> content_scanning.ContentScanningResourceWithRawRes
return ContentScanningResourceWithRawResponse(self._client.content_scanning)
+ @cached_property
+ def abuse_reports(self) -> abuse_reports.AbuseReportsResourceWithRawResponse:
+ from .resources.abuse_reports import AbuseReportsResourceWithRawResponse
+
+ return AbuseReportsResourceWithRawResponse(self._client.abuse_reports)
+
class AsyncCloudflareWithRawResponse:
_client: AsyncCloudflare
@@ -2677,6 +2696,12 @@ def content_scanning(self) -> content_scanning.AsyncContentScanningResourceWithR
return AsyncContentScanningResourceWithRawResponse(self._client.content_scanning)
+ @cached_property
+ def abuse_reports(self) -> abuse_reports.AsyncAbuseReportsResourceWithRawResponse:
+ from .resources.abuse_reports import AsyncAbuseReportsResourceWithRawResponse
+
+ return AsyncAbuseReportsResourceWithRawResponse(self._client.abuse_reports)
+
class CloudflareWithStreamedResponse:
_client: Cloudflare
@@ -3190,6 +3215,12 @@ def content_scanning(self) -> content_scanning.ContentScanningResourceWithStream
return ContentScanningResourceWithStreamingResponse(self._client.content_scanning)
+ @cached_property
+ def abuse_reports(self) -> abuse_reports.AbuseReportsResourceWithStreamingResponse:
+ from .resources.abuse_reports import AbuseReportsResourceWithStreamingResponse
+
+ return AbuseReportsResourceWithStreamingResponse(self._client.abuse_reports)
+
class AsyncCloudflareWithStreamedResponse:
_client: AsyncCloudflare
@@ -3713,6 +3744,12 @@ def content_scanning(self) -> content_scanning.AsyncContentScanningResourceWithS
return AsyncContentScanningResourceWithStreamingResponse(self._client.content_scanning)
+ @cached_property
+ def abuse_reports(self) -> abuse_reports.AsyncAbuseReportsResourceWithStreamingResponse:
+ from .resources.abuse_reports import AsyncAbuseReportsResourceWithStreamingResponse
+
+ return AsyncAbuseReportsResourceWithStreamingResponse(self._client.abuse_reports)
+
Client = Cloudflare
diff --git a/src/cloudflare/resources/abuse_reports.py b/src/cloudflare/resources/abuse_reports.py
new file mode 100644
index 00000000000..45241233b4a
--- /dev/null
+++ b/src/cloudflare/resources/abuse_reports.py
@@ -0,0 +1,492 @@
+# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details.
+
+from __future__ import annotations
+
+from typing import Type, cast
+from typing_extensions import Literal
+
+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 .._base_client import make_request_options
+from ..types.abuse_reports import abuse_report_create_params
+from ..types.abuse_reports.abuse_report_create_response import AbuseReportCreateResponse
+
+__all__ = ["AbuseReportsResource", "AsyncAbuseReportsResource"]
+
+
+class AbuseReportsResource(SyncAPIResource):
+ @cached_property
+ def with_raw_response(self) -> AbuseReportsResourceWithRawResponse:
+ """
+ This property can be used as a prefix for any HTTP method call to return the
+ the raw response object instead of the parsed content.
+
+ For more information, see https://www.github.com/cloudflare/cloudflare-python#accessing-raw-response-data-eg-headers
+ """
+ return AbuseReportsResourceWithRawResponse(self)
+
+ @cached_property
+ def with_streaming_response(self) -> AbuseReportsResourceWithStreamingResponse:
+ """
+ An alternative to `.with_raw_response` that doesn't eagerly read the response body.
+
+ For more information, see https://www.github.com/cloudflare/cloudflare-python#with_streaming_response
+ """
+ return AbuseReportsResourceWithStreamingResponse(self)
+
+ def create(
+ self,
+ report_type: Literal[
+ "abuse_dmca",
+ "abuse_trademark",
+ "abuse_general",
+ "abuse_phishing",
+ "abuse_children",
+ "abuse_threat",
+ "abuse_registrar_whois",
+ "abuse_ncsei",
+ ],
+ *,
+ account_id: str,
+ act: Literal[
+ "abuse_dmca",
+ "abuse_trademark",
+ "abuse_general",
+ "abuse_phishing",
+ "abuse_children",
+ "abuse_threat",
+ "abuse_registrar_whois",
+ "abuse_ncsei",
+ ],
+ email: str,
+ email2: str,
+ host_notification: Literal["send", "send-anon", "none"],
+ ncmec_notification: Literal["send", "send-anon", "none"],
+ owner_notification: Literal["send", "send-anon", "none"],
+ urls: str,
+ address1: str | NotGiven = NOT_GIVEN,
+ agent_name: str | NotGiven = NOT_GIVEN,
+ agree: Literal[0, 1] | NotGiven = NOT_GIVEN,
+ city: str | NotGiven = NOT_GIVEN,
+ comments: str | NotGiven = NOT_GIVEN,
+ company: str | NotGiven = NOT_GIVEN,
+ country: str | NotGiven = NOT_GIVEN,
+ destination_ips: str | NotGiven = NOT_GIVEN,
+ justification: str | NotGiven = NOT_GIVEN,
+ name: str | NotGiven = NOT_GIVEN,
+ ncsei_subject_representation: bool | NotGiven = NOT_GIVEN,
+ original_work: str | NotGiven = NOT_GIVEN,
+ ports_protocols: str | NotGiven = NOT_GIVEN,
+ signature: str | NotGiven = NOT_GIVEN,
+ source_ips: str | NotGiven = NOT_GIVEN,
+ state: str | NotGiven = NOT_GIVEN,
+ tele: str | NotGiven = NOT_GIVEN,
+ title: str | NotGiven = NOT_GIVEN,
+ trademark_number: str | NotGiven = NOT_GIVEN,
+ trademark_office: str | NotGiven = NOT_GIVEN,
+ trademark_symbol: str | 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,
+ ) -> str:
+ """
+ Submit the Abuse Report of a particular type
+
+ Args:
+ report_type: The abuse report type
+
+ act: The abuse report type
+
+ email: A valid email of the abuse reporter
+
+ email2: Should match the value provided in `email`
+
+ host_notification: Notification type based on the abuse type. NOTE: Copyright (DMCA) and Trademark
+ reports cannot be anonymous.
+
+ ncmec_notification: Notification type based on the abuse type. NOTE: Copyright (DMCA) and Trademark
+ reports cannot be anonymous.
+
+ owner_notification: Notification type based on the abuse type. NOTE: Copyright (DMCA) and Trademark
+ reports cannot be anonymous.
+
+ urls: A list of valid URLs separated by ‘ ’ (new line character). The list of the URLs
+ should not exceed 250 URLs. All URLs should have the same hostname. Each URL
+ should be unique
+
+ address1: Text not exceeding 100 characters
+
+ agent_name: The name of the copyright holder. Text not exceeding 60 characters.
+
+ agree: Can be 0 or 1
+
+ city: Text not exceeding 255 characters
+
+ comments: Any additional comments about the infringement not exceeding 2000 characters
+
+ company: Text not exceeding 100 characters
+
+ country: Text not exceeding 255 characters
+
+ destination_ips: A list of IP addresses separated by ‘ ’ (new line character). The list of
+ destination IPs should not exceed 30 IP addresses. Each one of the IP addresses
+ ought to be unique
+
+ justification: A detailed description of the infringement, including any necessary access
+ details and the exact steps needed to view the content, not exceeding 5000
+ characters
+
+ name: Text not exceeding 255 characters
+
+ ncsei_subject_representation: If the submitter is the target of NCSEI in the URLs of the abuse report
+
+ original_work: Text not exceeding 255 characters
+
+ ports_protocols: A comma separated list of ports and protocols e.g. 80/TCP, 22/UDP. The total
+ size of the field should not exceed 2000 characters. Each individual
+ port/protocol should not exceed 100 characters. The list should not have more
+ than 30 unique ports and protocols.
+
+ signature: Required for DMCA reports, should be same as Name. An affirmation that all
+ information in the report is true and accurate while agreeing to the policies of
+ Cloudflare's abuse reports
+
+ source_ips: A list of IP addresses separated by ‘ ’ (new line character). The list of source
+ IPs should not exceed 30 IP addresses. Each one of the IP addresses ought to be
+ unique
+
+ state: Text not exceeding 255 characters
+
+ tele: Text not exceeding 20 characters
+
+ title: Text not exceeding 255 characters
+
+ trademark_number: Text not exceeding 1000 characters
+
+ trademark_office: Text not exceeding 1000 characters
+
+ trademark_symbol: Text not exceeding 1000 characters
+
+ 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 report_type:
+ raise ValueError(f"Expected a non-empty value for `report_type` but received {report_type!r}")
+ return self._post(
+ f"/accounts/{account_id}/v1/abuse-reports/{report_type}",
+ body=maybe_transform(
+ {
+ "act": act,
+ "email": email,
+ "email2": email2,
+ "host_notification": host_notification,
+ "ncmec_notification": ncmec_notification,
+ "owner_notification": owner_notification,
+ "urls": urls,
+ "address1": address1,
+ "agent_name": agent_name,
+ "agree": agree,
+ "city": city,
+ "comments": comments,
+ "company": company,
+ "country": country,
+ "destination_ips": destination_ips,
+ "justification": justification,
+ "name": name,
+ "ncsei_subject_representation": ncsei_subject_representation,
+ "original_work": original_work,
+ "ports_protocols": ports_protocols,
+ "signature": signature,
+ "source_ips": source_ips,
+ "state": state,
+ "tele": tele,
+ "title": title,
+ "trademark_number": trademark_number,
+ "trademark_office": trademark_office,
+ "trademark_symbol": trademark_symbol,
+ },
+ abuse_report_create_params.AbuseReportCreateParams,
+ ),
+ options=make_request_options(
+ extra_headers=extra_headers,
+ extra_query=extra_query,
+ extra_body=extra_body,
+ timeout=timeout,
+ post_parser=ResultWrapper[AbuseReportCreateResponse]._unwrapper,
+ ),
+ cast_to=cast(Type[str], ResultWrapper[str]),
+ )
+
+
+class AsyncAbuseReportsResource(AsyncAPIResource):
+ @cached_property
+ def with_raw_response(self) -> AsyncAbuseReportsResourceWithRawResponse:
+ """
+ This property can be used as a prefix for any HTTP method call to return the
+ the raw response object instead of the parsed content.
+
+ For more information, see https://www.github.com/cloudflare/cloudflare-python#accessing-raw-response-data-eg-headers
+ """
+ return AsyncAbuseReportsResourceWithRawResponse(self)
+
+ @cached_property
+ def with_streaming_response(self) -> AsyncAbuseReportsResourceWithStreamingResponse:
+ """
+ An alternative to `.with_raw_response` that doesn't eagerly read the response body.
+
+ For more information, see https://www.github.com/cloudflare/cloudflare-python#with_streaming_response
+ """
+ return AsyncAbuseReportsResourceWithStreamingResponse(self)
+
+ async def create(
+ self,
+ report_type: Literal[
+ "abuse_dmca",
+ "abuse_trademark",
+ "abuse_general",
+ "abuse_phishing",
+ "abuse_children",
+ "abuse_threat",
+ "abuse_registrar_whois",
+ "abuse_ncsei",
+ ],
+ *,
+ account_id: str,
+ act: Literal[
+ "abuse_dmca",
+ "abuse_trademark",
+ "abuse_general",
+ "abuse_phishing",
+ "abuse_children",
+ "abuse_threat",
+ "abuse_registrar_whois",
+ "abuse_ncsei",
+ ],
+ email: str,
+ email2: str,
+ host_notification: Literal["send", "send-anon", "none"],
+ ncmec_notification: Literal["send", "send-anon", "none"],
+ owner_notification: Literal["send", "send-anon", "none"],
+ urls: str,
+ address1: str | NotGiven = NOT_GIVEN,
+ agent_name: str | NotGiven = NOT_GIVEN,
+ agree: Literal[0, 1] | NotGiven = NOT_GIVEN,
+ city: str | NotGiven = NOT_GIVEN,
+ comments: str | NotGiven = NOT_GIVEN,
+ company: str | NotGiven = NOT_GIVEN,
+ country: str | NotGiven = NOT_GIVEN,
+ destination_ips: str | NotGiven = NOT_GIVEN,
+ justification: str | NotGiven = NOT_GIVEN,
+ name: str | NotGiven = NOT_GIVEN,
+ ncsei_subject_representation: bool | NotGiven = NOT_GIVEN,
+ original_work: str | NotGiven = NOT_GIVEN,
+ ports_protocols: str | NotGiven = NOT_GIVEN,
+ signature: str | NotGiven = NOT_GIVEN,
+ source_ips: str | NotGiven = NOT_GIVEN,
+ state: str | NotGiven = NOT_GIVEN,
+ tele: str | NotGiven = NOT_GIVEN,
+ title: str | NotGiven = NOT_GIVEN,
+ trademark_number: str | NotGiven = NOT_GIVEN,
+ trademark_office: str | NotGiven = NOT_GIVEN,
+ trademark_symbol: str | 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,
+ ) -> str:
+ """
+ Submit the Abuse Report of a particular type
+
+ Args:
+ report_type: The abuse report type
+
+ act: The abuse report type
+
+ email: A valid email of the abuse reporter
+
+ email2: Should match the value provided in `email`
+
+ host_notification: Notification type based on the abuse type. NOTE: Copyright (DMCA) and Trademark
+ reports cannot be anonymous.
+
+ ncmec_notification: Notification type based on the abuse type. NOTE: Copyright (DMCA) and Trademark
+ reports cannot be anonymous.
+
+ owner_notification: Notification type based on the abuse type. NOTE: Copyright (DMCA) and Trademark
+ reports cannot be anonymous.
+
+ urls: A list of valid URLs separated by ‘ ’ (new line character). The list of the URLs
+ should not exceed 250 URLs. All URLs should have the same hostname. Each URL
+ should be unique
+
+ address1: Text not exceeding 100 characters
+
+ agent_name: The name of the copyright holder. Text not exceeding 60 characters.
+
+ agree: Can be 0 or 1
+
+ city: Text not exceeding 255 characters
+
+ comments: Any additional comments about the infringement not exceeding 2000 characters
+
+ company: Text not exceeding 100 characters
+
+ country: Text not exceeding 255 characters
+
+ destination_ips: A list of IP addresses separated by ‘ ’ (new line character). The list of
+ destination IPs should not exceed 30 IP addresses. Each one of the IP addresses
+ ought to be unique
+
+ justification: A detailed description of the infringement, including any necessary access
+ details and the exact steps needed to view the content, not exceeding 5000
+ characters
+
+ name: Text not exceeding 255 characters
+
+ ncsei_subject_representation: If the submitter is the target of NCSEI in the URLs of the abuse report
+
+ original_work: Text not exceeding 255 characters
+
+ ports_protocols: A comma separated list of ports and protocols e.g. 80/TCP, 22/UDP. The total
+ size of the field should not exceed 2000 characters. Each individual
+ port/protocol should not exceed 100 characters. The list should not have more
+ than 30 unique ports and protocols.
+
+ signature: Required for DMCA reports, should be same as Name. An affirmation that all
+ information in the report is true and accurate while agreeing to the policies of
+ Cloudflare's abuse reports
+
+ source_ips: A list of IP addresses separated by ‘ ’ (new line character). The list of source
+ IPs should not exceed 30 IP addresses. Each one of the IP addresses ought to be
+ unique
+
+ state: Text not exceeding 255 characters
+
+ tele: Text not exceeding 20 characters
+
+ title: Text not exceeding 255 characters
+
+ trademark_number: Text not exceeding 1000 characters
+
+ trademark_office: Text not exceeding 1000 characters
+
+ trademark_symbol: Text not exceeding 1000 characters
+
+ 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 report_type:
+ raise ValueError(f"Expected a non-empty value for `report_type` but received {report_type!r}")
+ return await self._post(
+ f"/accounts/{account_id}/v1/abuse-reports/{report_type}",
+ body=await async_maybe_transform(
+ {
+ "act": act,
+ "email": email,
+ "email2": email2,
+ "host_notification": host_notification,
+ "ncmec_notification": ncmec_notification,
+ "owner_notification": owner_notification,
+ "urls": urls,
+ "address1": address1,
+ "agent_name": agent_name,
+ "agree": agree,
+ "city": city,
+ "comments": comments,
+ "company": company,
+ "country": country,
+ "destination_ips": destination_ips,
+ "justification": justification,
+ "name": name,
+ "ncsei_subject_representation": ncsei_subject_representation,
+ "original_work": original_work,
+ "ports_protocols": ports_protocols,
+ "signature": signature,
+ "source_ips": source_ips,
+ "state": state,
+ "tele": tele,
+ "title": title,
+ "trademark_number": trademark_number,
+ "trademark_office": trademark_office,
+ "trademark_symbol": trademark_symbol,
+ },
+ abuse_report_create_params.AbuseReportCreateParams,
+ ),
+ options=make_request_options(
+ extra_headers=extra_headers,
+ extra_query=extra_query,
+ extra_body=extra_body,
+ timeout=timeout,
+ post_parser=ResultWrapper[AbuseReportCreateResponse]._unwrapper,
+ ),
+ cast_to=cast(Type[str], ResultWrapper[str]),
+ )
+
+
+class AbuseReportsResourceWithRawResponse:
+ def __init__(self, abuse_reports: AbuseReportsResource) -> None:
+ self._abuse_reports = abuse_reports
+
+ self.create = to_raw_response_wrapper(
+ abuse_reports.create,
+ )
+
+
+class AsyncAbuseReportsResourceWithRawResponse:
+ def __init__(self, abuse_reports: AsyncAbuseReportsResource) -> None:
+ self._abuse_reports = abuse_reports
+
+ self.create = async_to_raw_response_wrapper(
+ abuse_reports.create,
+ )
+
+
+class AbuseReportsResourceWithStreamingResponse:
+ def __init__(self, abuse_reports: AbuseReportsResource) -> None:
+ self._abuse_reports = abuse_reports
+
+ self.create = to_streamed_response_wrapper(
+ abuse_reports.create,
+ )
+
+
+class AsyncAbuseReportsResourceWithStreamingResponse:
+ def __init__(self, abuse_reports: AsyncAbuseReportsResource) -> None:
+ self._abuse_reports = abuse_reports
+
+ self.create = async_to_streamed_response_wrapper(
+ abuse_reports.create,
+ )
diff --git a/src/cloudflare/resources/zero_trust/devices/__init__.py b/src/cloudflare/resources/zero_trust/devices/__init__.py
index 3002bba6155..5b55d59405f 100644
--- a/src/cloudflare/resources/zero_trust/devices/__init__.py
+++ b/src/cloudflare/resources/zero_trust/devices/__init__.py
@@ -64,6 +64,14 @@
DEXTestsResourceWithStreamingResponse,
AsyncDEXTestsResourceWithStreamingResponse,
)
+from .fleet_status import (
+ FleetStatusResource,
+ AsyncFleetStatusResource,
+ FleetStatusResourceWithRawResponse,
+ AsyncFleetStatusResourceWithRawResponse,
+ FleetStatusResourceWithStreamingResponse,
+ AsyncFleetStatusResourceWithStreamingResponse,
+)
from .override_codes import (
OverrideCodesResource,
AsyncOverrideCodesResource,
@@ -86,6 +94,12 @@
"AsyncNetworksResourceWithRawResponse",
"NetworksResourceWithStreamingResponse",
"AsyncNetworksResourceWithStreamingResponse",
+ "FleetStatusResource",
+ "AsyncFleetStatusResource",
+ "FleetStatusResourceWithRawResponse",
+ "AsyncFleetStatusResourceWithRawResponse",
+ "FleetStatusResourceWithStreamingResponse",
+ "AsyncFleetStatusResourceWithStreamingResponse",
"PoliciesResource",
"AsyncPoliciesResource",
"PoliciesResourceWithRawResponse",
diff --git a/src/cloudflare/resources/zero_trust/devices/devices.py b/src/cloudflare/resources/zero_trust/devices/devices.py
index 73e50bc540a..c8da8b5a201 100644
--- a/src/cloudflare/resources/zero_trust/devices/devices.py
+++ b/src/cloudflare/resources/zero_trust/devices/devices.py
@@ -72,6 +72,14 @@
async_to_streamed_response_wrapper,
)
from ...._wrappers import ResultWrapper
+from .fleet_status import (
+ FleetStatusResource,
+ AsyncFleetStatusResource,
+ FleetStatusResourceWithRawResponse,
+ AsyncFleetStatusResourceWithRawResponse,
+ FleetStatusResourceWithStreamingResponse,
+ AsyncFleetStatusResourceWithStreamingResponse,
+)
from ....pagination import SyncSinglePage, AsyncSinglePage
from .override_codes import (
OverrideCodesResource,
@@ -99,6 +107,10 @@ def dex_tests(self) -> DEXTestsResource:
def networks(self) -> NetworksResource:
return NetworksResource(self._client)
+ @cached_property
+ def fleet_status(self) -> FleetStatusResource:
+ return FleetStatusResource(self._client)
+
@cached_property
def policies(self) -> PoliciesResource:
return PoliciesResource(self._client)
@@ -233,6 +245,10 @@ def dex_tests(self) -> AsyncDEXTestsResource:
def networks(self) -> AsyncNetworksResource:
return AsyncNetworksResource(self._client)
+ @cached_property
+ def fleet_status(self) -> AsyncFleetStatusResource:
+ return AsyncFleetStatusResource(self._client)
+
@cached_property
def policies(self) -> AsyncPoliciesResource:
return AsyncPoliciesResource(self._client)
@@ -377,6 +393,10 @@ def dex_tests(self) -> DEXTestsResourceWithRawResponse:
def networks(self) -> NetworksResourceWithRawResponse:
return NetworksResourceWithRawResponse(self._devices.networks)
+ @cached_property
+ def fleet_status(self) -> FleetStatusResourceWithRawResponse:
+ return FleetStatusResourceWithRawResponse(self._devices.fleet_status)
+
@cached_property
def policies(self) -> PoliciesResourceWithRawResponse:
return PoliciesResourceWithRawResponse(self._devices.policies)
@@ -421,6 +441,10 @@ def dex_tests(self) -> AsyncDEXTestsResourceWithRawResponse:
def networks(self) -> AsyncNetworksResourceWithRawResponse:
return AsyncNetworksResourceWithRawResponse(self._devices.networks)
+ @cached_property
+ def fleet_status(self) -> AsyncFleetStatusResourceWithRawResponse:
+ return AsyncFleetStatusResourceWithRawResponse(self._devices.fleet_status)
+
@cached_property
def policies(self) -> AsyncPoliciesResourceWithRawResponse:
return AsyncPoliciesResourceWithRawResponse(self._devices.policies)
@@ -465,6 +489,10 @@ def dex_tests(self) -> DEXTestsResourceWithStreamingResponse:
def networks(self) -> NetworksResourceWithStreamingResponse:
return NetworksResourceWithStreamingResponse(self._devices.networks)
+ @cached_property
+ def fleet_status(self) -> FleetStatusResourceWithStreamingResponse:
+ return FleetStatusResourceWithStreamingResponse(self._devices.fleet_status)
+
@cached_property
def policies(self) -> PoliciesResourceWithStreamingResponse:
return PoliciesResourceWithStreamingResponse(self._devices.policies)
@@ -509,6 +537,10 @@ def dex_tests(self) -> AsyncDEXTestsResourceWithStreamingResponse:
def networks(self) -> AsyncNetworksResourceWithStreamingResponse:
return AsyncNetworksResourceWithStreamingResponse(self._devices.networks)
+ @cached_property
+ def fleet_status(self) -> AsyncFleetStatusResourceWithStreamingResponse:
+ return AsyncFleetStatusResourceWithStreamingResponse(self._devices.fleet_status)
+
@cached_property
def policies(self) -> AsyncPoliciesResourceWithStreamingResponse:
return AsyncPoliciesResourceWithStreamingResponse(self._devices.policies)
diff --git a/src/cloudflare/resources/zero_trust/devices/fleet_status.py b/src/cloudflare/resources/zero_trust/devices/fleet_status.py
new file mode 100644
index 00000000000..57b2c298c03
--- /dev/null
+++ b/src/cloudflare/resources/zero_trust/devices/fleet_status.py
@@ -0,0 +1,220 @@
+# 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,
+ 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 ...._base_client import make_request_options
+from ....types.zero_trust.devices import fleet_status_get_params
+from ....types.zero_trust.devices.fleet_status_get_response import FleetStatusGetResponse
+
+__all__ = ["FleetStatusResource", "AsyncFleetStatusResource"]
+
+
+class FleetStatusResource(SyncAPIResource):
+ @cached_property
+ def with_raw_response(self) -> FleetStatusResourceWithRawResponse:
+ """
+ This property can be used as a prefix for any HTTP method call to return the
+ the raw response object instead of the parsed content.
+
+ For more information, see https://www.github.com/cloudflare/cloudflare-python#accessing-raw-response-data-eg-headers
+ """
+ return FleetStatusResourceWithRawResponse(self)
+
+ @cached_property
+ def with_streaming_response(self) -> FleetStatusResourceWithStreamingResponse:
+ """
+ An alternative to `.with_raw_response` that doesn't eagerly read the response body.
+
+ For more information, see https://www.github.com/cloudflare/cloudflare-python#with_streaming_response
+ """
+ return FleetStatusResourceWithStreamingResponse(self)
+
+ def get(
+ self,
+ device_id: str,
+ *,
+ account_id: str,
+ since_minutes: float,
+ colo: str | NotGiven = NOT_GIVEN,
+ time_now: str | 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,
+ ) -> FleetStatusGetResponse:
+ """
+ Get the live status of a latest device given device_id from the device_state
+ table
+
+ Args:
+ device_id: Device-specific ID, given as UUID v4
+
+ since_minutes: Number of minutes before current time
+
+ colo: List of data centers to filter results
+
+ time_now: Number of minutes before current time
+
+ extra_headers: Send extra headers
+
+ extra_query: Add additional query parameters to the request
+
+ extra_body: Add additional JSON properties to the request
+
+ timeout: Override the client-level default timeout for this request, in seconds
+ """
+ if not account_id:
+ raise ValueError(f"Expected a non-empty value for `account_id` but received {account_id!r}")
+ if not device_id:
+ raise ValueError(f"Expected a non-empty value for `device_id` but received {device_id!r}")
+ return self._get(
+ f"/accounts/{account_id}/dex/devices/{device_id}/fleet-status/live",
+ options=make_request_options(
+ extra_headers=extra_headers,
+ extra_query=extra_query,
+ extra_body=extra_body,
+ timeout=timeout,
+ query=maybe_transform(
+ {
+ "since_minutes": since_minutes,
+ "colo": colo,
+ "time_now": time_now,
+ },
+ fleet_status_get_params.FleetStatusGetParams,
+ ),
+ ),
+ cast_to=FleetStatusGetResponse,
+ )
+
+
+class AsyncFleetStatusResource(AsyncAPIResource):
+ @cached_property
+ def with_raw_response(self) -> AsyncFleetStatusResourceWithRawResponse:
+ """
+ This property can be used as a prefix for any HTTP method call to return the
+ the raw response object instead of the parsed content.
+
+ For more information, see https://www.github.com/cloudflare/cloudflare-python#accessing-raw-response-data-eg-headers
+ """
+ return AsyncFleetStatusResourceWithRawResponse(self)
+
+ @cached_property
+ def with_streaming_response(self) -> AsyncFleetStatusResourceWithStreamingResponse:
+ """
+ An alternative to `.with_raw_response` that doesn't eagerly read the response body.
+
+ For more information, see https://www.github.com/cloudflare/cloudflare-python#with_streaming_response
+ """
+ return AsyncFleetStatusResourceWithStreamingResponse(self)
+
+ async def get(
+ self,
+ device_id: str,
+ *,
+ account_id: str,
+ since_minutes: float,
+ colo: str | NotGiven = NOT_GIVEN,
+ time_now: str | 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,
+ ) -> FleetStatusGetResponse:
+ """
+ Get the live status of a latest device given device_id from the device_state
+ table
+
+ Args:
+ device_id: Device-specific ID, given as UUID v4
+
+ since_minutes: Number of minutes before current time
+
+ colo: List of data centers to filter results
+
+ time_now: Number of minutes before current time
+
+ extra_headers: Send extra headers
+
+ extra_query: Add additional query parameters to the request
+
+ extra_body: Add additional JSON properties to the request
+
+ timeout: Override the client-level default timeout for this request, in seconds
+ """
+ if not account_id:
+ raise ValueError(f"Expected a non-empty value for `account_id` but received {account_id!r}")
+ if not device_id:
+ raise ValueError(f"Expected a non-empty value for `device_id` but received {device_id!r}")
+ return await self._get(
+ f"/accounts/{account_id}/dex/devices/{device_id}/fleet-status/live",
+ options=make_request_options(
+ extra_headers=extra_headers,
+ extra_query=extra_query,
+ extra_body=extra_body,
+ timeout=timeout,
+ query=await async_maybe_transform(
+ {
+ "since_minutes": since_minutes,
+ "colo": colo,
+ "time_now": time_now,
+ },
+ fleet_status_get_params.FleetStatusGetParams,
+ ),
+ ),
+ cast_to=FleetStatusGetResponse,
+ )
+
+
+class FleetStatusResourceWithRawResponse:
+ def __init__(self, fleet_status: FleetStatusResource) -> None:
+ self._fleet_status = fleet_status
+
+ self.get = to_raw_response_wrapper(
+ fleet_status.get,
+ )
+
+
+class AsyncFleetStatusResourceWithRawResponse:
+ def __init__(self, fleet_status: AsyncFleetStatusResource) -> None:
+ self._fleet_status = fleet_status
+
+ self.get = async_to_raw_response_wrapper(
+ fleet_status.get,
+ )
+
+
+class FleetStatusResourceWithStreamingResponse:
+ def __init__(self, fleet_status: FleetStatusResource) -> None:
+ self._fleet_status = fleet_status
+
+ self.get = to_streamed_response_wrapper(
+ fleet_status.get,
+ )
+
+
+class AsyncFleetStatusResourceWithStreamingResponse:
+ def __init__(self, fleet_status: AsyncFleetStatusResource) -> None:
+ self._fleet_status = fleet_status
+
+ self.get = async_to_streamed_response_wrapper(
+ fleet_status.get,
+ )
diff --git a/src/cloudflare/resources/zero_trust/dex/__init__.py b/src/cloudflare/resources/zero_trust/dex/__init__.py
index b79e8e9ec69..defe96da107 100644
--- a/src/cloudflare/resources/zero_trust/dex/__init__.py
+++ b/src/cloudflare/resources/zero_trust/dex/__init__.py
@@ -24,6 +24,14 @@
TestsResourceWithStreamingResponse,
AsyncTestsResourceWithStreamingResponse,
)
+from .commands import (
+ CommandsResource,
+ AsyncCommandsResource,
+ CommandsResourceWithRawResponse,
+ AsyncCommandsResourceWithRawResponse,
+ CommandsResourceWithStreamingResponse,
+ AsyncCommandsResourceWithStreamingResponse,
+)
from .http_tests import (
HTTPTestsResource,
AsyncHTTPTestsResource,
@@ -58,6 +66,12 @@
)
__all__ = [
+ "CommandsResource",
+ "AsyncCommandsResource",
+ "CommandsResourceWithRawResponse",
+ "AsyncCommandsResourceWithRawResponse",
+ "CommandsResourceWithStreamingResponse",
+ "AsyncCommandsResourceWithStreamingResponse",
"ColosResource",
"AsyncColosResource",
"ColosResourceWithRawResponse",
diff --git a/src/cloudflare/resources/zero_trust/dex/commands/__init__.py b/src/cloudflare/resources/zero_trust/dex/commands/__init__.py
new file mode 100644
index 00000000000..4566edefe96
--- /dev/null
+++ b/src/cloudflare/resources/zero_trust/dex/commands/__init__.py
@@ -0,0 +1,47 @@
+# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details.
+
+from .quota import (
+ QuotaResource,
+ AsyncQuotaResource,
+ QuotaResourceWithRawResponse,
+ AsyncQuotaResourceWithRawResponse,
+ QuotaResourceWithStreamingResponse,
+ AsyncQuotaResourceWithStreamingResponse,
+)
+from .commands import (
+ CommandsResource,
+ AsyncCommandsResource,
+ CommandsResourceWithRawResponse,
+ AsyncCommandsResourceWithRawResponse,
+ CommandsResourceWithStreamingResponse,
+ AsyncCommandsResourceWithStreamingResponse,
+)
+from .downloads import (
+ DownloadsResource,
+ AsyncDownloadsResource,
+ DownloadsResourceWithRawResponse,
+ AsyncDownloadsResourceWithRawResponse,
+ DownloadsResourceWithStreamingResponse,
+ AsyncDownloadsResourceWithStreamingResponse,
+)
+
+__all__ = [
+ "DownloadsResource",
+ "AsyncDownloadsResource",
+ "DownloadsResourceWithRawResponse",
+ "AsyncDownloadsResourceWithRawResponse",
+ "DownloadsResourceWithStreamingResponse",
+ "AsyncDownloadsResourceWithStreamingResponse",
+ "QuotaResource",
+ "AsyncQuotaResource",
+ "QuotaResourceWithRawResponse",
+ "AsyncQuotaResourceWithRawResponse",
+ "QuotaResourceWithStreamingResponse",
+ "AsyncQuotaResourceWithStreamingResponse",
+ "CommandsResource",
+ "AsyncCommandsResource",
+ "CommandsResourceWithRawResponse",
+ "AsyncCommandsResourceWithRawResponse",
+ "CommandsResourceWithStreamingResponse",
+ "AsyncCommandsResourceWithStreamingResponse",
+]
diff --git a/src/cloudflare/resources/zero_trust/dex/commands/commands.py b/src/cloudflare/resources/zero_trust/dex/commands/commands.py
new file mode 100644
index 00000000000..f0041c4f8c9
--- /dev/null
+++ b/src/cloudflare/resources/zero_trust/dex/commands/commands.py
@@ -0,0 +1,417 @@
+# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details.
+
+from __future__ import annotations
+
+from typing import Type, Union, Iterable, Optional, cast
+from datetime import datetime
+from typing_extensions import Literal
+
+import httpx
+
+from .quota import (
+ QuotaResource,
+ AsyncQuotaResource,
+ QuotaResourceWithRawResponse,
+ AsyncQuotaResourceWithRawResponse,
+ QuotaResourceWithStreamingResponse,
+ AsyncQuotaResourceWithStreamingResponse,
+)
+from .downloads import (
+ DownloadsResource,
+ AsyncDownloadsResource,
+ DownloadsResourceWithRawResponse,
+ AsyncDownloadsResourceWithRawResponse,
+ DownloadsResourceWithStreamingResponse,
+ AsyncDownloadsResourceWithStreamingResponse,
+)
+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 .....pagination import SyncV4PagePagination, AsyncV4PagePagination
+from ....._base_client import AsyncPaginator, make_request_options
+from .....types.zero_trust.dex import command_list_params, command_create_params
+from .....types.zero_trust.dex.command_list_response import CommandListResponse
+from .....types.zero_trust.dex.command_create_response import CommandCreateResponse
+
+__all__ = ["CommandsResource", "AsyncCommandsResource"]
+
+
+class CommandsResource(SyncAPIResource):
+ @cached_property
+ def downloads(self) -> DownloadsResource:
+ return DownloadsResource(self._client)
+
+ @cached_property
+ def quota(self) -> QuotaResource:
+ return QuotaResource(self._client)
+
+ @cached_property
+ def with_raw_response(self) -> CommandsResourceWithRawResponse:
+ """
+ This property can be used as a prefix for any HTTP method call to return the
+ the raw response object instead of the parsed content.
+
+ For more information, see https://www.github.com/cloudflare/cloudflare-python#accessing-raw-response-data-eg-headers
+ """
+ return CommandsResourceWithRawResponse(self)
+
+ @cached_property
+ def with_streaming_response(self) -> CommandsResourceWithStreamingResponse:
+ """
+ An alternative to `.with_raw_response` that doesn't eagerly read the response body.
+
+ For more information, see https://www.github.com/cloudflare/cloudflare-python#with_streaming_response
+ """
+ return CommandsResourceWithStreamingResponse(self)
+
+ def create(
+ self,
+ *,
+ account_id: str,
+ commands: Iterable[command_create_params.Command],
+ # 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[CommandCreateResponse]:
+ """
+ Initiate commands for up to 10 devices per account
+
+ Args:
+ commands: List of device-level commands to execute
+
+ 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}/dex/commands",
+ body=maybe_transform({"commands": commands}, command_create_params.CommandCreateParams),
+ options=make_request_options(
+ extra_headers=extra_headers,
+ extra_query=extra_query,
+ extra_body=extra_body,
+ timeout=timeout,
+ post_parser=ResultWrapper[Optional[CommandCreateResponse]]._unwrapper,
+ ),
+ cast_to=cast(Type[Optional[CommandCreateResponse]], ResultWrapper[CommandCreateResponse]),
+ )
+
+ def list(
+ self,
+ *,
+ account_id: str,
+ page: float,
+ per_page: float,
+ command_type: str | NotGiven = NOT_GIVEN,
+ device_id: str | NotGiven = NOT_GIVEN,
+ from_: Union[str, datetime] | NotGiven = NOT_GIVEN,
+ status: Literal["PENDING_EXEC", "PENDING_UPLOAD", "SUCCESS", "FAILED"] | NotGiven = NOT_GIVEN,
+ to: Union[str, datetime] | NotGiven = NOT_GIVEN,
+ user_email: str | 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,
+ ) -> SyncV4PagePagination[Optional[CommandListResponse]]:
+ """
+ Retrieves a paginated list of commands issued to devices under the specified
+ account, optionally filtered by time range, device, or other parameters
+
+ Args:
+ page: Page number for pagination
+
+ per_page: Number of results per page
+
+ command_type: Optionally filter executed commands by command type
+
+ device_id: Unique identifier for a device
+
+ from_: Start time for the query in ISO (RFC3339 - ISO 8601) format
+
+ status: Optionally filter executed commands by status
+
+ to: End time for the query in ISO (RFC3339 - ISO 8601) format
+
+ user_email: Email tied to the device
+
+ 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}/dex/commands",
+ page=SyncV4PagePagination[Optional[CommandListResponse]],
+ options=make_request_options(
+ extra_headers=extra_headers,
+ extra_query=extra_query,
+ extra_body=extra_body,
+ timeout=timeout,
+ query=maybe_transform(
+ {
+ "page": page,
+ "per_page": per_page,
+ "command_type": command_type,
+ "device_id": device_id,
+ "from_": from_,
+ "status": status,
+ "to": to,
+ "user_email": user_email,
+ },
+ command_list_params.CommandListParams,
+ ),
+ ),
+ model=CommandListResponse,
+ )
+
+
+class AsyncCommandsResource(AsyncAPIResource):
+ @cached_property
+ def downloads(self) -> AsyncDownloadsResource:
+ return AsyncDownloadsResource(self._client)
+
+ @cached_property
+ def quota(self) -> AsyncQuotaResource:
+ return AsyncQuotaResource(self._client)
+
+ @cached_property
+ def with_raw_response(self) -> AsyncCommandsResourceWithRawResponse:
+ """
+ This property can be used as a prefix for any HTTP method call to return the
+ the raw response object instead of the parsed content.
+
+ For more information, see https://www.github.com/cloudflare/cloudflare-python#accessing-raw-response-data-eg-headers
+ """
+ return AsyncCommandsResourceWithRawResponse(self)
+
+ @cached_property
+ def with_streaming_response(self) -> AsyncCommandsResourceWithStreamingResponse:
+ """
+ An alternative to `.with_raw_response` that doesn't eagerly read the response body.
+
+ For more information, see https://www.github.com/cloudflare/cloudflare-python#with_streaming_response
+ """
+ return AsyncCommandsResourceWithStreamingResponse(self)
+
+ async def create(
+ self,
+ *,
+ account_id: str,
+ commands: Iterable[command_create_params.Command],
+ # 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[CommandCreateResponse]:
+ """
+ Initiate commands for up to 10 devices per account
+
+ Args:
+ commands: List of device-level commands to execute
+
+ 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}/dex/commands",
+ body=await async_maybe_transform({"commands": commands}, command_create_params.CommandCreateParams),
+ options=make_request_options(
+ extra_headers=extra_headers,
+ extra_query=extra_query,
+ extra_body=extra_body,
+ timeout=timeout,
+ post_parser=ResultWrapper[Optional[CommandCreateResponse]]._unwrapper,
+ ),
+ cast_to=cast(Type[Optional[CommandCreateResponse]], ResultWrapper[CommandCreateResponse]),
+ )
+
+ def list(
+ self,
+ *,
+ account_id: str,
+ page: float,
+ per_page: float,
+ command_type: str | NotGiven = NOT_GIVEN,
+ device_id: str | NotGiven = NOT_GIVEN,
+ from_: Union[str, datetime] | NotGiven = NOT_GIVEN,
+ status: Literal["PENDING_EXEC", "PENDING_UPLOAD", "SUCCESS", "FAILED"] | NotGiven = NOT_GIVEN,
+ to: Union[str, datetime] | NotGiven = NOT_GIVEN,
+ user_email: str | 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[Optional[CommandListResponse], AsyncV4PagePagination[Optional[CommandListResponse]]]:
+ """
+ Retrieves a paginated list of commands issued to devices under the specified
+ account, optionally filtered by time range, device, or other parameters
+
+ Args:
+ page: Page number for pagination
+
+ per_page: Number of results per page
+
+ command_type: Optionally filter executed commands by command type
+
+ device_id: Unique identifier for a device
+
+ from_: Start time for the query in ISO (RFC3339 - ISO 8601) format
+
+ status: Optionally filter executed commands by status
+
+ to: End time for the query in ISO (RFC3339 - ISO 8601) format
+
+ user_email: Email tied to the device
+
+ 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}/dex/commands",
+ page=AsyncV4PagePagination[Optional[CommandListResponse]],
+ options=make_request_options(
+ extra_headers=extra_headers,
+ extra_query=extra_query,
+ extra_body=extra_body,
+ timeout=timeout,
+ query=maybe_transform(
+ {
+ "page": page,
+ "per_page": per_page,
+ "command_type": command_type,
+ "device_id": device_id,
+ "from_": from_,
+ "status": status,
+ "to": to,
+ "user_email": user_email,
+ },
+ command_list_params.CommandListParams,
+ ),
+ ),
+ model=CommandListResponse,
+ )
+
+
+class CommandsResourceWithRawResponse:
+ def __init__(self, commands: CommandsResource) -> None:
+ self._commands = commands
+
+ self.create = to_raw_response_wrapper(
+ commands.create,
+ )
+ self.list = to_raw_response_wrapper(
+ commands.list,
+ )
+
+ @cached_property
+ def downloads(self) -> DownloadsResourceWithRawResponse:
+ return DownloadsResourceWithRawResponse(self._commands.downloads)
+
+ @cached_property
+ def quota(self) -> QuotaResourceWithRawResponse:
+ return QuotaResourceWithRawResponse(self._commands.quota)
+
+
+class AsyncCommandsResourceWithRawResponse:
+ def __init__(self, commands: AsyncCommandsResource) -> None:
+ self._commands = commands
+
+ self.create = async_to_raw_response_wrapper(
+ commands.create,
+ )
+ self.list = async_to_raw_response_wrapper(
+ commands.list,
+ )
+
+ @cached_property
+ def downloads(self) -> AsyncDownloadsResourceWithRawResponse:
+ return AsyncDownloadsResourceWithRawResponse(self._commands.downloads)
+
+ @cached_property
+ def quota(self) -> AsyncQuotaResourceWithRawResponse:
+ return AsyncQuotaResourceWithRawResponse(self._commands.quota)
+
+
+class CommandsResourceWithStreamingResponse:
+ def __init__(self, commands: CommandsResource) -> None:
+ self._commands = commands
+
+ self.create = to_streamed_response_wrapper(
+ commands.create,
+ )
+ self.list = to_streamed_response_wrapper(
+ commands.list,
+ )
+
+ @cached_property
+ def downloads(self) -> DownloadsResourceWithStreamingResponse:
+ return DownloadsResourceWithStreamingResponse(self._commands.downloads)
+
+ @cached_property
+ def quota(self) -> QuotaResourceWithStreamingResponse:
+ return QuotaResourceWithStreamingResponse(self._commands.quota)
+
+
+class AsyncCommandsResourceWithStreamingResponse:
+ def __init__(self, commands: AsyncCommandsResource) -> None:
+ self._commands = commands
+
+ self.create = async_to_streamed_response_wrapper(
+ commands.create,
+ )
+ self.list = async_to_streamed_response_wrapper(
+ commands.list,
+ )
+
+ @cached_property
+ def downloads(self) -> AsyncDownloadsResourceWithStreamingResponse:
+ return AsyncDownloadsResourceWithStreamingResponse(self._commands.downloads)
+
+ @cached_property
+ def quota(self) -> AsyncQuotaResourceWithStreamingResponse:
+ return AsyncQuotaResourceWithStreamingResponse(self._commands.quota)
diff --git a/src/cloudflare/resources/zero_trust/dex/commands/downloads.py b/src/cloudflare/resources/zero_trust/dex/commands/downloads.py
new file mode 100644
index 00000000000..57b8e0320aa
--- /dev/null
+++ b/src/cloudflare/resources/zero_trust/dex/commands/downloads.py
@@ -0,0 +1,190 @@
+# 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 ....._compat import cached_property
+from ....._resource import SyncAPIResource, AsyncAPIResource
+from ....._response import (
+ BinaryAPIResponse,
+ AsyncBinaryAPIResponse,
+ StreamedBinaryAPIResponse,
+ AsyncStreamedBinaryAPIResponse,
+ to_custom_raw_response_wrapper,
+ to_custom_streamed_response_wrapper,
+ async_to_custom_raw_response_wrapper,
+ async_to_custom_streamed_response_wrapper,
+)
+from ....._base_client import make_request_options
+
+__all__ = ["DownloadsResource", "AsyncDownloadsResource"]
+
+
+class DownloadsResource(SyncAPIResource):
+ @cached_property
+ def with_raw_response(self) -> DownloadsResourceWithRawResponse:
+ """
+ This property can be used as a prefix for any HTTP method call to return the
+ the raw response object instead of the parsed content.
+
+ For more information, see https://www.github.com/cloudflare/cloudflare-python#accessing-raw-response-data-eg-headers
+ """
+ return DownloadsResourceWithRawResponse(self)
+
+ @cached_property
+ def with_streaming_response(self) -> DownloadsResourceWithStreamingResponse:
+ """
+ An alternative to `.with_raw_response` that doesn't eagerly read the response body.
+
+ For more information, see https://www.github.com/cloudflare/cloudflare-python#with_streaming_response
+ """
+ return DownloadsResourceWithStreamingResponse(self)
+
+ def get(
+ self,
+ filename: str,
+ *,
+ account_id: str,
+ command_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,
+ ) -> BinaryAPIResponse:
+ """Downloads artifacts for an executed command.
+
+ Bulk downloads are not supported
+
+ Args:
+ command_id: Unique identifier for a command
+
+ 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 command_id:
+ raise ValueError(f"Expected a non-empty value for `command_id` but received {command_id!r}")
+ if not filename:
+ raise ValueError(f"Expected a non-empty value for `filename` but received {filename!r}")
+ extra_headers = {"Accept": "application/zip", **(extra_headers or {})}
+ return self._get(
+ f"/accounts/{account_id}/dex/commands/{command_id}/downloads/{filename}",
+ options=make_request_options(
+ extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout
+ ),
+ cast_to=BinaryAPIResponse,
+ )
+
+
+class AsyncDownloadsResource(AsyncAPIResource):
+ @cached_property
+ def with_raw_response(self) -> AsyncDownloadsResourceWithRawResponse:
+ """
+ This property can be used as a prefix for any HTTP method call to return the
+ the raw response object instead of the parsed content.
+
+ For more information, see https://www.github.com/cloudflare/cloudflare-python#accessing-raw-response-data-eg-headers
+ """
+ return AsyncDownloadsResourceWithRawResponse(self)
+
+ @cached_property
+ def with_streaming_response(self) -> AsyncDownloadsResourceWithStreamingResponse:
+ """
+ An alternative to `.with_raw_response` that doesn't eagerly read the response body.
+
+ For more information, see https://www.github.com/cloudflare/cloudflare-python#with_streaming_response
+ """
+ return AsyncDownloadsResourceWithStreamingResponse(self)
+
+ async def get(
+ self,
+ filename: str,
+ *,
+ account_id: str,
+ command_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,
+ ) -> AsyncBinaryAPIResponse:
+ """Downloads artifacts for an executed command.
+
+ Bulk downloads are not supported
+
+ Args:
+ command_id: Unique identifier for a command
+
+ 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 command_id:
+ raise ValueError(f"Expected a non-empty value for `command_id` but received {command_id!r}")
+ if not filename:
+ raise ValueError(f"Expected a non-empty value for `filename` but received {filename!r}")
+ extra_headers = {"Accept": "application/zip", **(extra_headers or {})}
+ return await self._get(
+ f"/accounts/{account_id}/dex/commands/{command_id}/downloads/{filename}",
+ options=make_request_options(
+ extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout
+ ),
+ cast_to=AsyncBinaryAPIResponse,
+ )
+
+
+class DownloadsResourceWithRawResponse:
+ def __init__(self, downloads: DownloadsResource) -> None:
+ self._downloads = downloads
+
+ self.get = to_custom_raw_response_wrapper(
+ downloads.get,
+ BinaryAPIResponse,
+ )
+
+
+class AsyncDownloadsResourceWithRawResponse:
+ def __init__(self, downloads: AsyncDownloadsResource) -> None:
+ self._downloads = downloads
+
+ self.get = async_to_custom_raw_response_wrapper(
+ downloads.get,
+ AsyncBinaryAPIResponse,
+ )
+
+
+class DownloadsResourceWithStreamingResponse:
+ def __init__(self, downloads: DownloadsResource) -> None:
+ self._downloads = downloads
+
+ self.get = to_custom_streamed_response_wrapper(
+ downloads.get,
+ StreamedBinaryAPIResponse,
+ )
+
+
+class AsyncDownloadsResourceWithStreamingResponse:
+ def __init__(self, downloads: AsyncDownloadsResource) -> None:
+ self._downloads = downloads
+
+ self.get = async_to_custom_streamed_response_wrapper(
+ downloads.get,
+ AsyncStreamedBinaryAPIResponse,
+ )
diff --git a/src/cloudflare/resources/zero_trust/dex/commands/quota.py b/src/cloudflare/resources/zero_trust/dex/commands/quota.py
new file mode 100644
index 00000000000..8a0ba05b4b3
--- /dev/null
+++ b/src/cloudflare/resources/zero_trust/dex/commands/quota.py
@@ -0,0 +1,176 @@
+# 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 ....._compat import cached_property
+from ....._resource import SyncAPIResource, AsyncAPIResource
+from ....._response import (
+ to_raw_response_wrapper,
+ to_streamed_response_wrapper,
+ async_to_raw_response_wrapper,
+ async_to_streamed_response_wrapper,
+)
+from ....._wrappers import ResultWrapper
+from ....._base_client import make_request_options
+from .....types.zero_trust.dex.commands.quota_get_response import QuotaGetResponse
+
+__all__ = ["QuotaResource", "AsyncQuotaResource"]
+
+
+class QuotaResource(SyncAPIResource):
+ @cached_property
+ def with_raw_response(self) -> QuotaResourceWithRawResponse:
+ """
+ This property can be used as a prefix for any HTTP method call to return the
+ the raw response object instead of the parsed content.
+
+ For more information, see https://www.github.com/cloudflare/cloudflare-python#accessing-raw-response-data-eg-headers
+ """
+ return QuotaResourceWithRawResponse(self)
+
+ @cached_property
+ def with_streaming_response(self) -> QuotaResourceWithStreamingResponse:
+ """
+ An alternative to `.with_raw_response` that doesn't eagerly read the response body.
+
+ For more information, see https://www.github.com/cloudflare/cloudflare-python#with_streaming_response
+ """
+ return QuotaResourceWithStreamingResponse(self)
+
+ def get(
+ self,
+ *,
+ account_id: str,
+ # Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs.
+ # The extra values given here take precedence over values defined on the client or passed to this method.
+ extra_headers: Headers | None = None,
+ extra_query: Query | None = None,
+ extra_body: Body | None = None,
+ timeout: float | httpx.Timeout | None | NotGiven = NOT_GIVEN,
+ ) -> Optional[QuotaGetResponse]:
+ """
+ Retrieves the current quota usage and limits for device commands within a
+ specific account, including the time when the quota will reset
+
+ Args:
+ extra_headers: Send extra headers
+
+ extra_query: Add additional query parameters to the request
+
+ extra_body: Add additional JSON properties to the request
+
+ timeout: Override the client-level default timeout for this request, in seconds
+ """
+ if not account_id:
+ raise ValueError(f"Expected a non-empty value for `account_id` but received {account_id!r}")
+ return self._get(
+ f"/accounts/{account_id}/dex/commands/quota",
+ options=make_request_options(
+ extra_headers=extra_headers,
+ extra_query=extra_query,
+ extra_body=extra_body,
+ timeout=timeout,
+ post_parser=ResultWrapper[Optional[QuotaGetResponse]]._unwrapper,
+ ),
+ cast_to=cast(Type[Optional[QuotaGetResponse]], ResultWrapper[QuotaGetResponse]),
+ )
+
+
+class AsyncQuotaResource(AsyncAPIResource):
+ @cached_property
+ def with_raw_response(self) -> AsyncQuotaResourceWithRawResponse:
+ """
+ This property can be used as a prefix for any HTTP method call to return the
+ the raw response object instead of the parsed content.
+
+ For more information, see https://www.github.com/cloudflare/cloudflare-python#accessing-raw-response-data-eg-headers
+ """
+ return AsyncQuotaResourceWithRawResponse(self)
+
+ @cached_property
+ def with_streaming_response(self) -> AsyncQuotaResourceWithStreamingResponse:
+ """
+ An alternative to `.with_raw_response` that doesn't eagerly read the response body.
+
+ For more information, see https://www.github.com/cloudflare/cloudflare-python#with_streaming_response
+ """
+ return AsyncQuotaResourceWithStreamingResponse(self)
+
+ async def get(
+ self,
+ *,
+ account_id: str,
+ # Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs.
+ # The extra values given here take precedence over values defined on the client or passed to this method.
+ extra_headers: Headers | None = None,
+ extra_query: Query | None = None,
+ extra_body: Body | None = None,
+ timeout: float | httpx.Timeout | None | NotGiven = NOT_GIVEN,
+ ) -> Optional[QuotaGetResponse]:
+ """
+ Retrieves the current quota usage and limits for device commands within a
+ specific account, including the time when the quota will reset
+
+ Args:
+ extra_headers: Send extra headers
+
+ extra_query: Add additional query parameters to the request
+
+ extra_body: Add additional JSON properties to the request
+
+ timeout: Override the client-level default timeout for this request, in seconds
+ """
+ if not account_id:
+ raise ValueError(f"Expected a non-empty value for `account_id` but received {account_id!r}")
+ return await self._get(
+ f"/accounts/{account_id}/dex/commands/quota",
+ options=make_request_options(
+ extra_headers=extra_headers,
+ extra_query=extra_query,
+ extra_body=extra_body,
+ timeout=timeout,
+ post_parser=ResultWrapper[Optional[QuotaGetResponse]]._unwrapper,
+ ),
+ cast_to=cast(Type[Optional[QuotaGetResponse]], ResultWrapper[QuotaGetResponse]),
+ )
+
+
+class QuotaResourceWithRawResponse:
+ def __init__(self, quota: QuotaResource) -> None:
+ self._quota = quota
+
+ self.get = to_raw_response_wrapper(
+ quota.get,
+ )
+
+
+class AsyncQuotaResourceWithRawResponse:
+ def __init__(self, quota: AsyncQuotaResource) -> None:
+ self._quota = quota
+
+ self.get = async_to_raw_response_wrapper(
+ quota.get,
+ )
+
+
+class QuotaResourceWithStreamingResponse:
+ def __init__(self, quota: QuotaResource) -> None:
+ self._quota = quota
+
+ self.get = to_streamed_response_wrapper(
+ quota.get,
+ )
+
+
+class AsyncQuotaResourceWithStreamingResponse:
+ def __init__(self, quota: AsyncQuotaResource) -> None:
+ self._quota = quota
+
+ self.get = async_to_streamed_response_wrapper(
+ quota.get,
+ )
diff --git a/src/cloudflare/resources/zero_trust/dex/dex.py b/src/cloudflare/resources/zero_trust/dex/dex.py
index 654a940a2a3..c8f838301e9 100644
--- a/src/cloudflare/resources/zero_trust/dex/dex.py
+++ b/src/cloudflare/resources/zero_trust/dex/dex.py
@@ -18,6 +18,14 @@
TestsResourceWithStreamingResponse,
AsyncTestsResourceWithStreamingResponse,
)
+from .commands import (
+ CommandsResource,
+ AsyncCommandsResource,
+ CommandsResourceWithRawResponse,
+ AsyncCommandsResourceWithRawResponse,
+ CommandsResourceWithStreamingResponse,
+ AsyncCommandsResourceWithStreamingResponse,
+)
from ...._compat import cached_property
from .http_tests import (
HTTPTestsResource,
@@ -45,6 +53,7 @@
TracerouteTestsResourceWithStreamingResponse,
AsyncTracerouteTestsResourceWithStreamingResponse,
)
+from .commands.commands import CommandsResource, AsyncCommandsResource
from .http_tests.http_tests import HTTPTestsResource, AsyncHTTPTestsResource
from .traceroute_test_results import (
TracerouteTestResultsResource,
@@ -64,6 +73,10 @@
class DEXResource(SyncAPIResource):
+ @cached_property
+ def commands(self) -> CommandsResource:
+ return CommandsResource(self._client)
+
@cached_property
def colos(self) -> ColosResource:
return ColosResource(self._client)
@@ -109,6 +122,10 @@ def with_streaming_response(self) -> DEXResourceWithStreamingResponse:
class AsyncDEXResource(AsyncAPIResource):
+ @cached_property
+ def commands(self) -> AsyncCommandsResource:
+ return AsyncCommandsResource(self._client)
+
@cached_property
def colos(self) -> AsyncColosResource:
return AsyncColosResource(self._client)
@@ -157,6 +174,10 @@ class DEXResourceWithRawResponse:
def __init__(self, dex: DEXResource) -> None:
self._dex = dex
+ @cached_property
+ def commands(self) -> CommandsResourceWithRawResponse:
+ return CommandsResourceWithRawResponse(self._dex.commands)
+
@cached_property
def colos(self) -> ColosResourceWithRawResponse:
return ColosResourceWithRawResponse(self._dex.colos)
@@ -186,6 +207,10 @@ class AsyncDEXResourceWithRawResponse:
def __init__(self, dex: AsyncDEXResource) -> None:
self._dex = dex
+ @cached_property
+ def commands(self) -> AsyncCommandsResourceWithRawResponse:
+ return AsyncCommandsResourceWithRawResponse(self._dex.commands)
+
@cached_property
def colos(self) -> AsyncColosResourceWithRawResponse:
return AsyncColosResourceWithRawResponse(self._dex.colos)
@@ -215,6 +240,10 @@ class DEXResourceWithStreamingResponse:
def __init__(self, dex: DEXResource) -> None:
self._dex = dex
+ @cached_property
+ def commands(self) -> CommandsResourceWithStreamingResponse:
+ return CommandsResourceWithStreamingResponse(self._dex.commands)
+
@cached_property
def colos(self) -> ColosResourceWithStreamingResponse:
return ColosResourceWithStreamingResponse(self._dex.colos)
@@ -244,6 +273,10 @@ class AsyncDEXResourceWithStreamingResponse:
def __init__(self, dex: AsyncDEXResource) -> None:
self._dex = dex
+ @cached_property
+ def commands(self) -> AsyncCommandsResourceWithStreamingResponse:
+ return AsyncCommandsResourceWithStreamingResponse(self._dex.commands)
+
@cached_property
def colos(self) -> AsyncColosResourceWithStreamingResponse:
return AsyncColosResourceWithStreamingResponse(self._dex.colos)
diff --git a/src/cloudflare/resources/zones/holds.py b/src/cloudflare/resources/zones/holds.py
index 38fbee1a43f..50ff188a172 100644
--- a/src/cloudflare/resources/zones/holds.py
+++ b/src/cloudflare/resources/zones/holds.py
@@ -20,7 +20,7 @@
async_to_streamed_response_wrapper,
)
from ..._wrappers import ResultWrapper
-from ...types.zones import hold_create_params, hold_delete_params
+from ...types.zones import hold_edit_params, hold_create_params, hold_delete_params
from ..._base_client import make_request_options
from ...types.zones.zone_hold import ZoneHold
@@ -140,6 +140,66 @@ def delete(
cast_to=cast(Type[ZoneHold], ResultWrapper[ZoneHold]),
)
+ def edit(
+ self,
+ *,
+ zone_id: str,
+ hold_after: str | NotGiven = NOT_GIVEN,
+ include_subdomains: bool | 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,
+ ) -> ZoneHold:
+ """
+ Update the `hold_after` and/or `include_subdomains` values on an existing zone
+ hold. The hold is enabled if the `hold_after` date-time value is in the past.
+
+ Args:
+ zone_id: Identifier
+
+ hold_after: If `hold_after` is provided and future-dated, the hold will be temporarily
+ disabled, then automatically re-enabled by the system at the time specified in
+ this RFC3339-formatted timestamp. A past-dated `hold_after` value will have no
+ effect on an existing, enabled hold. Providing an empty string will set its
+ value to the current time.
+
+ include_subdomains: If `true`, the zone hold will extend to block any subdomain of the given zone,
+ as well as SSL4SaaS Custom Hostnames. For example, a zone hold on a zone with
+ the hostname 'example.com' and include_subdomains=true will block 'example.com',
+ 'staging.example.com', 'api.staging.example.com', etc.
+
+ 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._patch(
+ f"/zones/{zone_id}/hold",
+ body=maybe_transform(
+ {
+ "hold_after": hold_after,
+ "include_subdomains": include_subdomains,
+ },
+ hold_edit_params.HoldEditParams,
+ ),
+ options=make_request_options(
+ extra_headers=extra_headers,
+ extra_query=extra_query,
+ extra_body=extra_body,
+ timeout=timeout,
+ post_parser=ResultWrapper[ZoneHold]._unwrapper,
+ ),
+ cast_to=cast(Type[ZoneHold], ResultWrapper[ZoneHold]),
+ )
+
def get(
self,
*,
@@ -296,6 +356,66 @@ async def delete(
cast_to=cast(Type[ZoneHold], ResultWrapper[ZoneHold]),
)
+ async def edit(
+ self,
+ *,
+ zone_id: str,
+ hold_after: str | NotGiven = NOT_GIVEN,
+ include_subdomains: bool | 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,
+ ) -> ZoneHold:
+ """
+ Update the `hold_after` and/or `include_subdomains` values on an existing zone
+ hold. The hold is enabled if the `hold_after` date-time value is in the past.
+
+ Args:
+ zone_id: Identifier
+
+ hold_after: If `hold_after` is provided and future-dated, the hold will be temporarily
+ disabled, then automatically re-enabled by the system at the time specified in
+ this RFC3339-formatted timestamp. A past-dated `hold_after` value will have no
+ effect on an existing, enabled hold. Providing an empty string will set its
+ value to the current time.
+
+ include_subdomains: If `true`, the zone hold will extend to block any subdomain of the given zone,
+ as well as SSL4SaaS Custom Hostnames. For example, a zone hold on a zone with
+ the hostname 'example.com' and include_subdomains=true will block 'example.com',
+ 'staging.example.com', 'api.staging.example.com', etc.
+
+ extra_headers: Send extra headers
+
+ extra_query: Add additional query parameters to the request
+
+ extra_body: Add additional JSON properties to the request
+
+ timeout: Override the client-level default timeout for this request, in seconds
+ """
+ if not zone_id:
+ raise ValueError(f"Expected a non-empty value for `zone_id` but received {zone_id!r}")
+ return await self._patch(
+ f"/zones/{zone_id}/hold",
+ body=await async_maybe_transform(
+ {
+ "hold_after": hold_after,
+ "include_subdomains": include_subdomains,
+ },
+ hold_edit_params.HoldEditParams,
+ ),
+ options=make_request_options(
+ extra_headers=extra_headers,
+ extra_query=extra_query,
+ extra_body=extra_body,
+ timeout=timeout,
+ post_parser=ResultWrapper[ZoneHold]._unwrapper,
+ ),
+ cast_to=cast(Type[ZoneHold], ResultWrapper[ZoneHold]),
+ )
+
async def get(
self,
*,
@@ -347,6 +467,9 @@ def __init__(self, holds: HoldsResource) -> None:
self.delete = to_raw_response_wrapper(
holds.delete,
)
+ self.edit = to_raw_response_wrapper(
+ holds.edit,
+ )
self.get = to_raw_response_wrapper(
holds.get,
)
@@ -362,6 +485,9 @@ def __init__(self, holds: AsyncHoldsResource) -> None:
self.delete = async_to_raw_response_wrapper(
holds.delete,
)
+ self.edit = async_to_raw_response_wrapper(
+ holds.edit,
+ )
self.get = async_to_raw_response_wrapper(
holds.get,
)
@@ -377,6 +503,9 @@ def __init__(self, holds: HoldsResource) -> None:
self.delete = to_streamed_response_wrapper(
holds.delete,
)
+ self.edit = to_streamed_response_wrapper(
+ holds.edit,
+ )
self.get = to_streamed_response_wrapper(
holds.get,
)
@@ -392,6 +521,9 @@ def __init__(self, holds: AsyncHoldsResource) -> None:
self.delete = async_to_streamed_response_wrapper(
holds.delete,
)
+ self.edit = async_to_streamed_response_wrapper(
+ holds.edit,
+ )
self.get = async_to_streamed_response_wrapper(
holds.get,
)
diff --git a/src/cloudflare/types/abuse_reports/__init__.py b/src/cloudflare/types/abuse_reports/__init__.py
new file mode 100644
index 00000000000..c17465cb40c
--- /dev/null
+++ b/src/cloudflare/types/abuse_reports/__init__.py
@@ -0,0 +1,6 @@
+# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details.
+
+from __future__ import annotations
+
+from .abuse_report_create_params import AbuseReportCreateParams as AbuseReportCreateParams
+from .abuse_report_create_response import AbuseReportCreateResponse as AbuseReportCreateResponse
diff --git a/src/cloudflare/types/abuse_reports/abuse_report_create_params.py b/src/cloudflare/types/abuse_reports/abuse_report_create_params.py
new file mode 100644
index 00000000000..ff19f93f7c5
--- /dev/null
+++ b/src/cloudflare/types/abuse_reports/abuse_report_create_params.py
@@ -0,0 +1,140 @@
+# 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__ = ["AbuseReportCreateParams"]
+
+
+class AbuseReportCreateParams(TypedDict, total=False):
+ account_id: Required[str]
+
+ act: Required[
+ Literal[
+ "abuse_dmca",
+ "abuse_trademark",
+ "abuse_general",
+ "abuse_phishing",
+ "abuse_children",
+ "abuse_threat",
+ "abuse_registrar_whois",
+ "abuse_ncsei",
+ ]
+ ]
+ """The abuse report type"""
+
+ email: Required[str]
+ """A valid email of the abuse reporter"""
+
+ email2: Required[str]
+ """Should match the value provided in `email`"""
+
+ host_notification: Required[Literal["send", "send-anon", "none"]]
+ """Notification type based on the abuse type.
+
+ NOTE: Copyright (DMCA) and Trademark reports cannot be anonymous.
+ """
+
+ ncmec_notification: Required[Literal["send", "send-anon", "none"]]
+ """Notification type based on the abuse type.
+
+ NOTE: Copyright (DMCA) and Trademark reports cannot be anonymous.
+ """
+
+ owner_notification: Required[Literal["send", "send-anon", "none"]]
+ """Notification type based on the abuse type.
+
+ NOTE: Copyright (DMCA) and Trademark reports cannot be anonymous.
+ """
+
+ urls: Required[str]
+ """A list of valid URLs separated by ‘ ’ (new line character).
+
+ The list of the URLs should not exceed 250 URLs. All URLs should have the same
+ hostname. Each URL should be unique
+ """
+
+ address1: str
+ """Text not exceeding 100 characters"""
+
+ agent_name: str
+ """The name of the copyright holder. Text not exceeding 60 characters."""
+
+ agree: Literal[0, 1]
+ """Can be 0 or 1"""
+
+ city: str
+ """Text not exceeding 255 characters"""
+
+ comments: str
+ """Any additional comments about the infringement not exceeding 2000 characters"""
+
+ company: str
+ """Text not exceeding 100 characters"""
+
+ country: str
+ """Text not exceeding 255 characters"""
+
+ destination_ips: str
+ """A list of IP addresses separated by ‘ ’ (new line character).
+
+ The list of destination IPs should not exceed 30 IP addresses. Each one of the
+ IP addresses ought to be unique
+ """
+
+ justification: str
+ """
+ A detailed description of the infringement, including any necessary access
+ details and the exact steps needed to view the content, not exceeding 5000
+ characters
+ """
+
+ name: str
+ """Text not exceeding 255 characters"""
+
+ ncsei_subject_representation: bool
+ """If the submitter is the target of NCSEI in the URLs of the abuse report"""
+
+ original_work: str
+ """Text not exceeding 255 characters"""
+
+ ports_protocols: str
+ """A comma separated list of ports and protocols e.g.
+
+ 80/TCP, 22/UDP. The total size of the field should not exceed 2000 characters.
+ Each individual port/protocol should not exceed 100 characters. The list should
+ not have more than 30 unique ports and protocols.
+ """
+
+ signature: str
+ """Required for DMCA reports, should be same as Name.
+
+ An affirmation that all information in the report is true and accurate while
+ agreeing to the policies of Cloudflare's abuse reports
+ """
+
+ source_ips: str
+ """A list of IP addresses separated by ‘ ’ (new line character).
+
+ The list of source IPs should not exceed 30 IP addresses. Each one of the IP
+ addresses ought to be unique
+ """
+
+ state: str
+ """Text not exceeding 255 characters"""
+
+ tele: str
+ """Text not exceeding 20 characters"""
+
+ title: str
+ """Text not exceeding 255 characters"""
+
+ trademark_number: str
+ """Text not exceeding 1000 characters"""
+
+ trademark_office: str
+ """Text not exceeding 1000 characters"""
+
+ trademark_symbol: str
+ """Text not exceeding 1000 characters"""
diff --git a/src/cloudflare/types/abuse_reports/abuse_report_create_response.py b/src/cloudflare/types/abuse_reports/abuse_report_create_response.py
new file mode 100644
index 00000000000..03fc4011e68
--- /dev/null
+++ b/src/cloudflare/types/abuse_reports/abuse_report_create_response.py
@@ -0,0 +1,7 @@
+# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details.
+
+from typing_extensions import TypeAlias
+
+__all__ = ["AbuseReportCreateResponse"]
+
+AbuseReportCreateResponse: TypeAlias = str
diff --git a/src/cloudflare/types/zero_trust/devices/__init__.py b/src/cloudflare/types/zero_trust/devices/__init__.py
index 831df46d499..37d71da7a5e 100644
--- a/src/cloudflare/types/zero_trust/devices/__init__.py
+++ b/src/cloudflare/types/zero_trust/devices/__init__.py
@@ -49,6 +49,7 @@
from .unique_client_id_input import UniqueClientIDInput as UniqueClientIDInput
from .unrevoke_create_params import UnrevokeCreateParams as UnrevokeCreateParams
from .crowdstrike_input_param import CrowdstrikeInputParam as CrowdstrikeInputParam
+from .fleet_status_get_params import FleetStatusGetParams as FleetStatusGetParams
from .network_delete_response import NetworkDeleteResponse as NetworkDeleteResponse
from .posture_delete_response import PostureDeleteResponse as PostureDeleteResponse
from .sentinelone_input_param import SentineloneInputParam as SentineloneInputParam
@@ -56,6 +57,7 @@
from .dex_test_delete_response import DEXTestDeleteResponse as DEXTestDeleteResponse
from .unrevoke_create_response import UnrevokeCreateResponse as UnrevokeCreateResponse
from .domain_joined_input_param import DomainJoinedInputParam as DomainJoinedInputParam
+from .fleet_status_get_response import FleetStatusGetResponse as FleetStatusGetResponse
from .workspace_one_input_param import WorkspaceOneInputParam as WorkspaceOneInputParam
from .split_tunnel_exclude_param import SplitTunnelExcludeParam as SplitTunnelExcludeParam
from .split_tunnel_include_param import SplitTunnelIncludeParam as SplitTunnelIncludeParam
diff --git a/src/cloudflare/types/zero_trust/devices/fleet_status_get_params.py b/src/cloudflare/types/zero_trust/devices/fleet_status_get_params.py
new file mode 100644
index 00000000000..09a81b98c51
--- /dev/null
+++ b/src/cloudflare/types/zero_trust/devices/fleet_status_get_params.py
@@ -0,0 +1,20 @@
+# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details.
+
+from __future__ import annotations
+
+from typing_extensions import Required, TypedDict
+
+__all__ = ["FleetStatusGetParams"]
+
+
+class FleetStatusGetParams(TypedDict, total=False):
+ account_id: Required[str]
+
+ since_minutes: Required[float]
+ """Number of minutes before current time"""
+
+ colo: str
+ """List of data centers to filter results"""
+
+ time_now: str
+ """Number of minutes before current time"""
diff --git a/src/cloudflare/types/zero_trust/devices/fleet_status_get_response.py b/src/cloudflare/types/zero_trust/devices/fleet_status_get_response.py
new file mode 100644
index 00000000000..f4feee2cb0c
--- /dev/null
+++ b/src/cloudflare/types/zero_trust/devices/fleet_status_get_response.py
@@ -0,0 +1,268 @@
+# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details.
+
+from typing import List, Optional
+
+from pydantic import Field as FieldInfo
+
+from ...._models import BaseModel
+
+__all__ = [
+ "FleetStatusGetResponse",
+ "CPUPctByApp",
+ "DeviceIPV4",
+ "DeviceIPV4Location",
+ "DeviceIPV6",
+ "DeviceIPV6Location",
+ "GatewayIPV4",
+ "GatewayIPV4Location",
+ "GatewayIPV6",
+ "GatewayIPV6Location",
+ "ISPIPV4",
+ "ISPIPV4Location",
+ "ISPIPV6",
+ "ISPIPV6Location",
+ "RamUsedPctByApp",
+]
+
+
+class CPUPctByApp(BaseModel):
+ cpu_pct: Optional[float] = None
+
+ name: Optional[str] = None
+
+
+class DeviceIPV4Location(BaseModel):
+ city: Optional[str] = None
+
+ country_iso: Optional[str] = None
+
+ state_iso: Optional[str] = None
+
+ zip: Optional[str] = None
+
+
+class DeviceIPV4(BaseModel):
+ address: Optional[str] = None
+
+ asn: Optional[int] = None
+
+ aso: Optional[str] = None
+
+ location: Optional[DeviceIPV4Location] = None
+
+ netmask: Optional[str] = None
+
+ version: Optional[str] = None
+
+
+class DeviceIPV6Location(BaseModel):
+ city: Optional[str] = None
+
+ country_iso: Optional[str] = None
+
+ state_iso: Optional[str] = None
+
+ zip: Optional[str] = None
+
+
+class DeviceIPV6(BaseModel):
+ address: Optional[str] = None
+
+ asn: Optional[int] = None
+
+ aso: Optional[str] = None
+
+ location: Optional[DeviceIPV6Location] = None
+
+ netmask: Optional[str] = None
+
+ version: Optional[str] = None
+
+
+class GatewayIPV4Location(BaseModel):
+ city: Optional[str] = None
+
+ country_iso: Optional[str] = None
+
+ state_iso: Optional[str] = None
+
+ zip: Optional[str] = None
+
+
+class GatewayIPV4(BaseModel):
+ address: Optional[str] = None
+
+ asn: Optional[int] = None
+
+ aso: Optional[str] = None
+
+ location: Optional[GatewayIPV4Location] = None
+
+ netmask: Optional[str] = None
+
+ version: Optional[str] = None
+
+
+class GatewayIPV6Location(BaseModel):
+ city: Optional[str] = None
+
+ country_iso: Optional[str] = None
+
+ state_iso: Optional[str] = None
+
+ zip: Optional[str] = None
+
+
+class GatewayIPV6(BaseModel):
+ address: Optional[str] = None
+
+ asn: Optional[int] = None
+
+ aso: Optional[str] = None
+
+ location: Optional[GatewayIPV6Location] = None
+
+ netmask: Optional[str] = None
+
+ version: Optional[str] = None
+
+
+class ISPIPV4Location(BaseModel):
+ city: Optional[str] = None
+
+ country_iso: Optional[str] = None
+
+ state_iso: Optional[str] = None
+
+ zip: Optional[str] = None
+
+
+class ISPIPV4(BaseModel):
+ address: Optional[str] = None
+
+ asn: Optional[int] = None
+
+ aso: Optional[str] = None
+
+ location: Optional[ISPIPV4Location] = None
+
+ netmask: Optional[str] = None
+
+ version: Optional[str] = None
+
+
+class ISPIPV6Location(BaseModel):
+ city: Optional[str] = None
+
+ country_iso: Optional[str] = None
+
+ state_iso: Optional[str] = None
+
+ zip: Optional[str] = None
+
+
+class ISPIPV6(BaseModel):
+ address: Optional[str] = None
+
+ asn: Optional[int] = None
+
+ aso: Optional[str] = None
+
+ location: Optional[ISPIPV6Location] = None
+
+ netmask: Optional[str] = None
+
+ version: Optional[str] = None
+
+
+class RamUsedPctByApp(BaseModel):
+ name: Optional[str] = None
+
+ ram_used_pct: Optional[float] = None
+
+
+class FleetStatusGetResponse(BaseModel):
+ colo: str
+ """Cloudflare colo"""
+
+ device_id: str = FieldInfo(alias="deviceId")
+ """Device identifier (UUID v4)"""
+
+ mode: str
+ """The mode under which the WARP client is run"""
+
+ platform: str
+ """Operating system"""
+
+ status: str
+ """Network status"""
+
+ timestamp: str
+ """Timestamp in ISO format"""
+
+ version: str
+ """WARP client version"""
+
+ always_on: Optional[bool] = FieldInfo(alias="alwaysOn", default=None)
+
+ battery_charging: Optional[bool] = FieldInfo(alias="batteryCharging", default=None)
+
+ battery_cycles: Optional[int] = FieldInfo(alias="batteryCycles", default=None)
+
+ battery_pct: Optional[float] = FieldInfo(alias="batteryPct", default=None)
+
+ connection_type: Optional[str] = FieldInfo(alias="connectionType", default=None)
+
+ cpu_pct: Optional[float] = FieldInfo(alias="cpuPct", default=None)
+
+ cpu_pct_by_app: Optional[List[List[CPUPctByApp]]] = FieldInfo(alias="cpuPctByApp", default=None)
+
+ device_ipv4: Optional[DeviceIPV4] = FieldInfo(alias="deviceIpv4", default=None)
+
+ device_ipv6: Optional[DeviceIPV6] = FieldInfo(alias="deviceIpv6", default=None)
+
+ device_name: Optional[str] = FieldInfo(alias="deviceName", default=None)
+ """Device identifier (human readable)"""
+
+ disk_read_bps: Optional[int] = FieldInfo(alias="diskReadBps", default=None)
+
+ disk_usage_pct: Optional[float] = FieldInfo(alias="diskUsagePct", default=None)
+
+ disk_write_bps: Optional[int] = FieldInfo(alias="diskWriteBps", default=None)
+
+ doh_subdomain: Optional[str] = FieldInfo(alias="dohSubdomain", default=None)
+
+ estimated_loss_pct: Optional[float] = FieldInfo(alias="estimatedLossPct", default=None)
+
+ firewall_enabled: Optional[bool] = FieldInfo(alias="firewallEnabled", default=None)
+
+ gateway_ipv4: Optional[GatewayIPV4] = FieldInfo(alias="gatewayIpv4", default=None)
+
+ gateway_ipv6: Optional[GatewayIPV6] = FieldInfo(alias="gatewayIpv6", default=None)
+
+ handshake_latency_ms: Optional[float] = FieldInfo(alias="handshakeLatencyMs", default=None)
+
+ isp_ipv4: Optional[ISPIPV4] = FieldInfo(alias="ispIpv4", default=None)
+
+ isp_ipv6: Optional[ISPIPV6] = FieldInfo(alias="ispIpv6", default=None)
+
+ metal: Optional[str] = None
+
+ network_rcvd_bps: Optional[int] = FieldInfo(alias="networkRcvdBps", default=None)
+
+ network_sent_bps: Optional[int] = FieldInfo(alias="networkSentBps", default=None)
+
+ network_ssid: Optional[str] = FieldInfo(alias="networkSsid", default=None)
+
+ person_email: Optional[str] = FieldInfo(alias="personEmail", default=None)
+ """User contact email address"""
+
+ ram_available_kb: Optional[int] = FieldInfo(alias="ramAvailableKb", default=None)
+
+ ram_used_pct: Optional[float] = FieldInfo(alias="ramUsedPct", default=None)
+
+ ram_used_pct_by_app: Optional[List[List[RamUsedPctByApp]]] = FieldInfo(alias="ramUsedPctByApp", default=None)
+
+ switch_locked: Optional[bool] = FieldInfo(alias="switchLocked", default=None)
+
+ wifi_strength_dbm: Optional[int] = FieldInfo(alias="wifiStrengthDbm", default=None)
diff --git a/src/cloudflare/types/zero_trust/dex/__init__.py b/src/cloudflare/types/zero_trust/dex/__init__.py
index d891e1d3a9d..cd977b0b14c 100644
--- a/src/cloudflare/types/zero_trust/dex/__init__.py
+++ b/src/cloudflare/types/zero_trust/dex/__init__.py
@@ -8,8 +8,12 @@
from .http_details import HTTPDetails as HTTPDetails
from .colo_list_params import ColoListParams as ColoListParams
from .test_list_params import TestListParams as TestListParams
+from .command_list_params import CommandListParams as CommandListParams
from .http_test_get_params import HTTPTestGetParams as HTTPTestGetParams
from .aggregate_time_period import AggregateTimePeriod as AggregateTimePeriod
+from .command_create_params import CommandCreateParams as CommandCreateParams
+from .command_list_response import CommandListResponse as CommandListResponse
+from .command_create_response import CommandCreateResponse as CommandCreateResponse
from .fleet_status_live_params import FleetStatusLiveParams as FleetStatusLiveParams
from .fleet_status_live_response import FleetStatusLiveResponse as FleetStatusLiveResponse
from .traceroute_test_get_params import TracerouteTestGetParams as TracerouteTestGetParams
diff --git a/src/cloudflare/types/zero_trust/dex/command_create_params.py b/src/cloudflare/types/zero_trust/dex/command_create_params.py
new file mode 100644
index 00000000000..cbab76ab1c1
--- /dev/null
+++ b/src/cloudflare/types/zero_trust/dex/command_create_params.py
@@ -0,0 +1,57 @@
+# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details.
+
+from __future__ import annotations
+
+from typing import List, Iterable
+from typing_extensions import Literal, Required, Annotated, TypedDict
+
+from ...._utils import PropertyInfo
+
+__all__ = ["CommandCreateParams", "Command", "CommandCommandArgs"]
+
+
+class CommandCreateParams(TypedDict, total=False):
+ account_id: Required[str]
+
+ commands: Required[Iterable[Command]]
+ """List of device-level commands to execute"""
+
+
+class CommandCommandArgs(TypedDict, total=False):
+ interfaces: List[Literal["default", "tunnel"]]
+ """List of interfaces to capture packets on"""
+
+ max_file_size_mb: Annotated[float, PropertyInfo(alias="max-file-size-mb")]
+ """Maximum file size (in MB) for the capture file.
+
+ Specifies the maximum file size of the warp-diag zip artifact that can be
+ uploaded. If the zip artifact exceeds the specified max file size, it will NOT
+ be uploaded
+ """
+
+ packet_size_bytes: Annotated[float, PropertyInfo(alias="packet-size-bytes")]
+ """Maximum number of bytes to save for each packet"""
+
+ test_all_routes: Annotated[bool, PropertyInfo(alias="test-all-routes")]
+ """Test an IP address from all included or excluded ranges.
+
+ Tests an IP address from all included or excluded ranges. Essentially the same
+ as running 'route get '' and collecting the results. This option may
+ increase the time taken to collect the warp-diag
+ """
+
+ time_limit_min: Annotated[float, PropertyInfo(alias="time-limit-min")]
+ """Limit on capture duration (in minutes)"""
+
+
+class Command(TypedDict, total=False):
+ command_type: Required[Literal["pcap", "warp-diag"]]
+ """Type of command to execute on the device"""
+
+ device_id: Required[str]
+ """Unique identifier for the device"""
+
+ user_email: Required[str]
+ """Email tied to the device"""
+
+ command_args: CommandCommandArgs
diff --git a/src/cloudflare/types/zero_trust/dex/command_create_response.py b/src/cloudflare/types/zero_trust/dex/command_create_response.py
new file mode 100644
index 00000000000..e3a1e432678
--- /dev/null
+++ b/src/cloudflare/types/zero_trust/dex/command_create_response.py
@@ -0,0 +1,30 @@
+# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details.
+
+from typing import Dict, List, Optional
+from typing_extensions import Literal
+
+from ...._models import BaseModel
+
+__all__ = ["CommandCreateResponse", "Command"]
+
+
+class Command(BaseModel):
+ id: Optional[str] = None
+ """Unique identifier for the command"""
+
+ args: Optional[Dict[str, str]] = None
+ """Command arguments"""
+
+ device_id: Optional[str] = None
+ """Identifier for the device associated with the command"""
+
+ status: Optional[Literal["PENDING_EXEC", "PENDING_UPLOAD", "SUCCESS", "FAILED"]] = None
+ """Current status of the command"""
+
+ type: Optional[str] = None
+ """Type of the command (e.g., "pcap" or "warp-diag")"""
+
+
+class CommandCreateResponse(BaseModel):
+ commands: Optional[List[Command]] = None
+ """List of created commands"""
diff --git a/src/cloudflare/types/zero_trust/dex/command_list_params.py b/src/cloudflare/types/zero_trust/dex/command_list_params.py
new file mode 100644
index 00000000000..cbe58116f27
--- /dev/null
+++ b/src/cloudflare/types/zero_trust/dex/command_list_params.py
@@ -0,0 +1,39 @@
+# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details.
+
+from __future__ import annotations
+
+from typing import Union
+from datetime import datetime
+from typing_extensions import Literal, Required, Annotated, TypedDict
+
+from ...._utils import PropertyInfo
+
+__all__ = ["CommandListParams"]
+
+
+class CommandListParams(TypedDict, total=False):
+ account_id: Required[str]
+
+ page: Required[float]
+ """Page number for pagination"""
+
+ per_page: Required[float]
+ """Number of results per page"""
+
+ command_type: str
+ """Optionally filter executed commands by command type"""
+
+ device_id: str
+ """Unique identifier for a device"""
+
+ from_: Annotated[Union[str, datetime], PropertyInfo(alias="from", format="iso8601")]
+ """Start time for the query in ISO (RFC3339 - ISO 8601) format"""
+
+ status: Literal["PENDING_EXEC", "PENDING_UPLOAD", "SUCCESS", "FAILED"]
+ """Optionally filter executed commands by status"""
+
+ to: Annotated[Union[str, datetime], PropertyInfo(format="iso8601")]
+ """End time for the query in ISO (RFC3339 - ISO 8601) format"""
+
+ user_email: str
+ """Email tied to the device"""
diff --git a/src/cloudflare/types/zero_trust/dex/command_list_response.py b/src/cloudflare/types/zero_trust/dex/command_list_response.py
new file mode 100644
index 00000000000..601cef906ce
--- /dev/null
+++ b/src/cloudflare/types/zero_trust/dex/command_list_response.py
@@ -0,0 +1,30 @@
+# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details.
+
+from typing import List, Optional
+from datetime import datetime
+
+from ...._models import BaseModel
+
+__all__ = ["CommandListResponse", "Command"]
+
+
+class Command(BaseModel):
+ id: Optional[str] = None
+
+ completed_date: Optional[datetime] = None
+
+ created_date: Optional[datetime] = None
+
+ device_id: Optional[str] = None
+
+ filename: Optional[str] = None
+
+ status: Optional[str] = None
+
+ type: Optional[str] = None
+
+ user_email: Optional[str] = None
+
+
+class CommandListResponse(BaseModel):
+ commands: Optional[List[Command]] = None
diff --git a/src/cloudflare/types/zero_trust/dex/commands/__init__.py b/src/cloudflare/types/zero_trust/dex/commands/__init__.py
index f8ee8b14b1c..83304891f5e 100644
--- a/src/cloudflare/types/zero_trust/dex/commands/__init__.py
+++ b/src/cloudflare/types/zero_trust/dex/commands/__init__.py
@@ -1,3 +1,5 @@
# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details.
from __future__ import annotations
+
+from .quota_get_response import QuotaGetResponse as QuotaGetResponse
diff --git a/src/cloudflare/types/zero_trust/dex/commands/quota_get_response.py b/src/cloudflare/types/zero_trust/dex/commands/quota_get_response.py
new file mode 100644
index 00000000000..df1cc7d0596
--- /dev/null
+++ b/src/cloudflare/types/zero_trust/dex/commands/quota_get_response.py
@@ -0,0 +1,18 @@
+# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details.
+
+from datetime import datetime
+
+from ....._models import BaseModel
+
+__all__ = ["QuotaGetResponse"]
+
+
+class QuotaGetResponse(BaseModel):
+ quota: float
+ """The remaining number of commands that can be initiated for an account"""
+
+ quota_usage: float
+ """The number of commands that have been initiated for an account"""
+
+ reset_time: datetime
+ """The time when the quota resets"""
diff --git a/src/cloudflare/types/zones/__init__.py b/src/cloudflare/types/zones/__init__.py
index f82d8f8e328..63621e80433 100644
--- a/src/cloudflare/types/zones/__init__.py
+++ b/src/cloudflare/types/zones/__init__.py
@@ -49,6 +49,7 @@
from .websocket_param import WebsocketParam as WebsocketParam
from .always_use_https import AlwaysUseHTTPS as AlwaysUseHTTPS
from .development_mode import DevelopmentMode as DevelopmentMode
+from .hold_edit_params import HoldEditParams as HoldEditParams
from .orange_to_orange import OrangeToOrange as OrangeToOrange
from .prefetch_preload import PrefetchPreload as PrefetchPreload
from .security_headers import SecurityHeaders as SecurityHeaders
diff --git a/src/cloudflare/types/zones/hold_edit_params.py b/src/cloudflare/types/zones/hold_edit_params.py
new file mode 100644
index 00000000000..fc5e878576f
--- /dev/null
+++ b/src/cloudflare/types/zones/hold_edit_params.py
@@ -0,0 +1,29 @@
+# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details.
+
+from __future__ import annotations
+
+from typing_extensions import Required, TypedDict
+
+__all__ = ["HoldEditParams"]
+
+
+class HoldEditParams(TypedDict, total=False):
+ zone_id: Required[str]
+ """Identifier"""
+
+ hold_after: str
+ """
+ If `hold_after` is provided and future-dated, the hold will be temporarily
+ disabled, then automatically re-enabled by the system at the time specified in
+ this RFC3339-formatted timestamp. A past-dated `hold_after` value will have no
+ effect on an existing, enabled hold. Providing an empty string will set its
+ value to the current time.
+ """
+
+ include_subdomains: bool
+ """
+ If `true`, the zone hold will extend to block any subdomain of the given zone,
+ as well as SSL4SaaS Custom Hostnames. For example, a zone hold on a zone with
+ the hostname 'example.com' and include_subdomains=true will block 'example.com',
+ 'staging.example.com', 'api.staging.example.com', etc.
+ """
diff --git a/tests/api_resources/test_abuse_reports.py b/tests/api_resources/test_abuse_reports.py
new file mode 100644
index 00000000000..105b9e07063
--- /dev/null
+++ b/tests/api_resources/test_abuse_reports.py
@@ -0,0 +1,233 @@
+# 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
+
+base_url = os.environ.get("TEST_API_BASE_URL", "http://127.0.0.1:4010")
+
+
+class TestAbuseReports:
+ parametrize = pytest.mark.parametrize("client", [False, True], indirect=True, ids=["loose", "strict"])
+
+ @parametrize
+ def test_method_create(self, client: Cloudflare) -> None:
+ abuse_report = client.abuse_reports.create(
+ report_type="abuse_dmca",
+ account_id="023e105f4ecef8ad9ca31a8372d0c353",
+ act="abuse_dmca",
+ email="email",
+ email2="email2",
+ host_notification="send",
+ ncmec_notification="send",
+ owner_notification="send",
+ urls="urls",
+ )
+ assert_matches_type(str, abuse_report, path=["response"])
+
+ @parametrize
+ def test_method_create_with_all_params(self, client: Cloudflare) -> None:
+ abuse_report = client.abuse_reports.create(
+ report_type="abuse_dmca",
+ account_id="023e105f4ecef8ad9ca31a8372d0c353",
+ act="abuse_dmca",
+ email="email",
+ email2="email2",
+ host_notification="send",
+ ncmec_notification="send",
+ owner_notification="send",
+ urls="urls",
+ address1="x",
+ agent_name="x",
+ agree=0,
+ city="x",
+ comments="x",
+ company="x",
+ country="x",
+ destination_ips="destination_ips",
+ justification="x",
+ name="x",
+ ncsei_subject_representation=True,
+ original_work="x",
+ ports_protocols="ports_protocols",
+ signature="signature",
+ source_ips="source_ips",
+ state="x",
+ tele="x",
+ title="x",
+ trademark_number="x",
+ trademark_office="x",
+ trademark_symbol="x",
+ )
+ assert_matches_type(str, abuse_report, path=["response"])
+
+ @parametrize
+ def test_raw_response_create(self, client: Cloudflare) -> None:
+ response = client.abuse_reports.with_raw_response.create(
+ report_type="abuse_dmca",
+ account_id="023e105f4ecef8ad9ca31a8372d0c353",
+ act="abuse_dmca",
+ email="email",
+ email2="email2",
+ host_notification="send",
+ ncmec_notification="send",
+ owner_notification="send",
+ urls="urls",
+ )
+
+ assert response.is_closed is True
+ assert response.http_request.headers.get("X-Stainless-Lang") == "python"
+ abuse_report = response.parse()
+ assert_matches_type(str, abuse_report, path=["response"])
+
+ @parametrize
+ def test_streaming_response_create(self, client: Cloudflare) -> None:
+ with client.abuse_reports.with_streaming_response.create(
+ report_type="abuse_dmca",
+ account_id="023e105f4ecef8ad9ca31a8372d0c353",
+ act="abuse_dmca",
+ email="email",
+ email2="email2",
+ host_notification="send",
+ ncmec_notification="send",
+ owner_notification="send",
+ urls="urls",
+ ) as response:
+ assert not response.is_closed
+ assert response.http_request.headers.get("X-Stainless-Lang") == "python"
+
+ abuse_report = response.parse()
+ assert_matches_type(str, abuse_report, 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.abuse_reports.with_raw_response.create(
+ report_type="abuse_dmca",
+ account_id="",
+ act="abuse_dmca",
+ email="email",
+ email2="email2",
+ host_notification="send",
+ ncmec_notification="send",
+ owner_notification="send",
+ urls="urls",
+ )
+
+
+class TestAsyncAbuseReports:
+ parametrize = pytest.mark.parametrize("async_client", [False, True], indirect=True, ids=["loose", "strict"])
+
+ @parametrize
+ async def test_method_create(self, async_client: AsyncCloudflare) -> None:
+ abuse_report = await async_client.abuse_reports.create(
+ report_type="abuse_dmca",
+ account_id="023e105f4ecef8ad9ca31a8372d0c353",
+ act="abuse_dmca",
+ email="email",
+ email2="email2",
+ host_notification="send",
+ ncmec_notification="send",
+ owner_notification="send",
+ urls="urls",
+ )
+ assert_matches_type(str, abuse_report, path=["response"])
+
+ @parametrize
+ async def test_method_create_with_all_params(self, async_client: AsyncCloudflare) -> None:
+ abuse_report = await async_client.abuse_reports.create(
+ report_type="abuse_dmca",
+ account_id="023e105f4ecef8ad9ca31a8372d0c353",
+ act="abuse_dmca",
+ email="email",
+ email2="email2",
+ host_notification="send",
+ ncmec_notification="send",
+ owner_notification="send",
+ urls="urls",
+ address1="x",
+ agent_name="x",
+ agree=0,
+ city="x",
+ comments="x",
+ company="x",
+ country="x",
+ destination_ips="destination_ips",
+ justification="x",
+ name="x",
+ ncsei_subject_representation=True,
+ original_work="x",
+ ports_protocols="ports_protocols",
+ signature="signature",
+ source_ips="source_ips",
+ state="x",
+ tele="x",
+ title="x",
+ trademark_number="x",
+ trademark_office="x",
+ trademark_symbol="x",
+ )
+ assert_matches_type(str, abuse_report, path=["response"])
+
+ @parametrize
+ async def test_raw_response_create(self, async_client: AsyncCloudflare) -> None:
+ response = await async_client.abuse_reports.with_raw_response.create(
+ report_type="abuse_dmca",
+ account_id="023e105f4ecef8ad9ca31a8372d0c353",
+ act="abuse_dmca",
+ email="email",
+ email2="email2",
+ host_notification="send",
+ ncmec_notification="send",
+ owner_notification="send",
+ urls="urls",
+ )
+
+ assert response.is_closed is True
+ assert response.http_request.headers.get("X-Stainless-Lang") == "python"
+ abuse_report = await response.parse()
+ assert_matches_type(str, abuse_report, path=["response"])
+
+ @parametrize
+ async def test_streaming_response_create(self, async_client: AsyncCloudflare) -> None:
+ async with async_client.abuse_reports.with_streaming_response.create(
+ report_type="abuse_dmca",
+ account_id="023e105f4ecef8ad9ca31a8372d0c353",
+ act="abuse_dmca",
+ email="email",
+ email2="email2",
+ host_notification="send",
+ ncmec_notification="send",
+ owner_notification="send",
+ urls="urls",
+ ) as response:
+ assert not response.is_closed
+ assert response.http_request.headers.get("X-Stainless-Lang") == "python"
+
+ abuse_report = await response.parse()
+ assert_matches_type(str, abuse_report, 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.abuse_reports.with_raw_response.create(
+ report_type="abuse_dmca",
+ account_id="",
+ act="abuse_dmca",
+ email="email",
+ email2="email2",
+ host_notification="send",
+ ncmec_notification="send",
+ owner_notification="send",
+ urls="urls",
+ )
diff --git a/tests/api_resources/zero_trust/devices/test_fleet_status.py b/tests/api_resources/zero_trust/devices/test_fleet_status.py
new file mode 100644
index 00000000000..308864477e0
--- /dev/null
+++ b/tests/api_resources/zero_trust/devices/test_fleet_status.py
@@ -0,0 +1,150 @@
+# 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.zero_trust.devices import FleetStatusGetResponse
+
+base_url = os.environ.get("TEST_API_BASE_URL", "http://127.0.0.1:4010")
+
+
+class TestFleetStatus:
+ parametrize = pytest.mark.parametrize("client", [False, True], indirect=True, ids=["loose", "strict"])
+
+ @parametrize
+ def test_method_get(self, client: Cloudflare) -> None:
+ fleet_status = client.zero_trust.devices.fleet_status.get(
+ device_id="cb49c27f-7f97-49c5-b6f3-f7c01ead0fd7",
+ account_id="01a7362d577a6c3019a474fd6f485823",
+ since_minutes=10,
+ )
+ assert_matches_type(FleetStatusGetResponse, fleet_status, path=["response"])
+
+ @parametrize
+ def test_method_get_with_all_params(self, client: Cloudflare) -> None:
+ fleet_status = client.zero_trust.devices.fleet_status.get(
+ device_id="cb49c27f-7f97-49c5-b6f3-f7c01ead0fd7",
+ account_id="01a7362d577a6c3019a474fd6f485823",
+ since_minutes=10,
+ colo="SJC",
+ time_now="2023-10-11T00:00:00Z",
+ )
+ assert_matches_type(FleetStatusGetResponse, fleet_status, path=["response"])
+
+ @parametrize
+ def test_raw_response_get(self, client: Cloudflare) -> None:
+ response = client.zero_trust.devices.fleet_status.with_raw_response.get(
+ device_id="cb49c27f-7f97-49c5-b6f3-f7c01ead0fd7",
+ account_id="01a7362d577a6c3019a474fd6f485823",
+ since_minutes=10,
+ )
+
+ assert response.is_closed is True
+ assert response.http_request.headers.get("X-Stainless-Lang") == "python"
+ fleet_status = response.parse()
+ assert_matches_type(FleetStatusGetResponse, fleet_status, path=["response"])
+
+ @parametrize
+ def test_streaming_response_get(self, client: Cloudflare) -> None:
+ with client.zero_trust.devices.fleet_status.with_streaming_response.get(
+ device_id="cb49c27f-7f97-49c5-b6f3-f7c01ead0fd7",
+ account_id="01a7362d577a6c3019a474fd6f485823",
+ since_minutes=10,
+ ) as response:
+ assert not response.is_closed
+ assert response.http_request.headers.get("X-Stainless-Lang") == "python"
+
+ fleet_status = response.parse()
+ assert_matches_type(FleetStatusGetResponse, fleet_status, path=["response"])
+
+ assert cast(Any, response.is_closed) is True
+
+ @parametrize
+ def test_path_params_get(self, client: Cloudflare) -> None:
+ with pytest.raises(ValueError, match=r"Expected a non-empty value for `account_id` but received ''"):
+ client.zero_trust.devices.fleet_status.with_raw_response.get(
+ device_id="cb49c27f-7f97-49c5-b6f3-f7c01ead0fd7",
+ account_id="",
+ since_minutes=10,
+ )
+
+ with pytest.raises(ValueError, match=r"Expected a non-empty value for `device_id` but received ''"):
+ client.zero_trust.devices.fleet_status.with_raw_response.get(
+ device_id="",
+ account_id="01a7362d577a6c3019a474fd6f485823",
+ since_minutes=10,
+ )
+
+
+class TestAsyncFleetStatus:
+ parametrize = pytest.mark.parametrize("async_client", [False, True], indirect=True, ids=["loose", "strict"])
+
+ @parametrize
+ async def test_method_get(self, async_client: AsyncCloudflare) -> None:
+ fleet_status = await async_client.zero_trust.devices.fleet_status.get(
+ device_id="cb49c27f-7f97-49c5-b6f3-f7c01ead0fd7",
+ account_id="01a7362d577a6c3019a474fd6f485823",
+ since_minutes=10,
+ )
+ assert_matches_type(FleetStatusGetResponse, fleet_status, path=["response"])
+
+ @parametrize
+ async def test_method_get_with_all_params(self, async_client: AsyncCloudflare) -> None:
+ fleet_status = await async_client.zero_trust.devices.fleet_status.get(
+ device_id="cb49c27f-7f97-49c5-b6f3-f7c01ead0fd7",
+ account_id="01a7362d577a6c3019a474fd6f485823",
+ since_minutes=10,
+ colo="SJC",
+ time_now="2023-10-11T00:00:00Z",
+ )
+ assert_matches_type(FleetStatusGetResponse, fleet_status, path=["response"])
+
+ @parametrize
+ async def test_raw_response_get(self, async_client: AsyncCloudflare) -> None:
+ response = await async_client.zero_trust.devices.fleet_status.with_raw_response.get(
+ device_id="cb49c27f-7f97-49c5-b6f3-f7c01ead0fd7",
+ account_id="01a7362d577a6c3019a474fd6f485823",
+ since_minutes=10,
+ )
+
+ assert response.is_closed is True
+ assert response.http_request.headers.get("X-Stainless-Lang") == "python"
+ fleet_status = await response.parse()
+ assert_matches_type(FleetStatusGetResponse, fleet_status, path=["response"])
+
+ @parametrize
+ async def test_streaming_response_get(self, async_client: AsyncCloudflare) -> None:
+ async with async_client.zero_trust.devices.fleet_status.with_streaming_response.get(
+ device_id="cb49c27f-7f97-49c5-b6f3-f7c01ead0fd7",
+ account_id="01a7362d577a6c3019a474fd6f485823",
+ since_minutes=10,
+ ) as response:
+ assert not response.is_closed
+ assert response.http_request.headers.get("X-Stainless-Lang") == "python"
+
+ fleet_status = await response.parse()
+ assert_matches_type(FleetStatusGetResponse, fleet_status, path=["response"])
+
+ assert cast(Any, response.is_closed) is True
+
+ @parametrize
+ async def test_path_params_get(self, async_client: AsyncCloudflare) -> None:
+ with pytest.raises(ValueError, match=r"Expected a non-empty value for `account_id` but received ''"):
+ await async_client.zero_trust.devices.fleet_status.with_raw_response.get(
+ device_id="cb49c27f-7f97-49c5-b6f3-f7c01ead0fd7",
+ account_id="",
+ since_minutes=10,
+ )
+
+ with pytest.raises(ValueError, match=r"Expected a non-empty value for `device_id` but received ''"):
+ await async_client.zero_trust.devices.fleet_status.with_raw_response.get(
+ device_id="",
+ account_id="01a7362d577a6c3019a474fd6f485823",
+ since_minutes=10,
+ )
diff --git a/tests/api_resources/zero_trust/dex/commands/__init__.py b/tests/api_resources/zero_trust/dex/commands/__init__.py
new file mode 100644
index 00000000000..fd8019a9a1a
--- /dev/null
+++ b/tests/api_resources/zero_trust/dex/commands/__init__.py
@@ -0,0 +1 @@
+# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details.
diff --git a/tests/api_resources/zero_trust/dex/commands/test_downloads.py b/tests/api_resources/zero_trust/dex/commands/test_downloads.py
new file mode 100644
index 00000000000..66711dbdd5a
--- /dev/null
+++ b/tests/api_resources/zero_trust/dex/commands/test_downloads.py
@@ -0,0 +1,184 @@
+# 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 httpx
+import pytest
+from respx import MockRouter
+
+from cloudflare import Cloudflare, AsyncCloudflare
+from cloudflare._response import (
+ BinaryAPIResponse,
+ AsyncBinaryAPIResponse,
+ StreamedBinaryAPIResponse,
+ AsyncStreamedBinaryAPIResponse,
+)
+
+base_url = os.environ.get("TEST_API_BASE_URL", "http://127.0.0.1:4010")
+
+
+class TestDownloads:
+ parametrize = pytest.mark.parametrize("client", [False, True], indirect=True, ids=["loose", "strict"])
+
+ @parametrize
+ @pytest.mark.respx(base_url=base_url)
+ def test_method_get(self, client: Cloudflare, respx_mock: MockRouter) -> None:
+ respx_mock.get(
+ "/accounts/01a7362d577a6c3019a474fd6f485823/dex/commands/5758fefe-ae7e-4538-a39b-1fef6abcb909/downloads/filename"
+ ).mock(return_value=httpx.Response(200, json={"foo": "bar"}))
+ download = client.zero_trust.dex.commands.downloads.get(
+ filename="filename",
+ account_id="01a7362d577a6c3019a474fd6f485823",
+ command_id="5758fefe-ae7e-4538-a39b-1fef6abcb909",
+ )
+ assert download.is_closed
+ assert download.json() == {"foo": "bar"}
+ assert cast(Any, download.is_closed) is True
+ assert isinstance(download, BinaryAPIResponse)
+
+ @parametrize
+ @pytest.mark.respx(base_url=base_url)
+ def test_raw_response_get(self, client: Cloudflare, respx_mock: MockRouter) -> None:
+ respx_mock.get(
+ "/accounts/01a7362d577a6c3019a474fd6f485823/dex/commands/5758fefe-ae7e-4538-a39b-1fef6abcb909/downloads/filename"
+ ).mock(return_value=httpx.Response(200, json={"foo": "bar"}))
+
+ download = client.zero_trust.dex.commands.downloads.with_raw_response.get(
+ filename="filename",
+ account_id="01a7362d577a6c3019a474fd6f485823",
+ command_id="5758fefe-ae7e-4538-a39b-1fef6abcb909",
+ )
+
+ assert download.is_closed is True
+ assert download.http_request.headers.get("X-Stainless-Lang") == "python"
+ assert download.json() == {"foo": "bar"}
+ assert isinstance(download, BinaryAPIResponse)
+
+ @parametrize
+ @pytest.mark.respx(base_url=base_url)
+ def test_streaming_response_get(self, client: Cloudflare, respx_mock: MockRouter) -> None:
+ respx_mock.get(
+ "/accounts/01a7362d577a6c3019a474fd6f485823/dex/commands/5758fefe-ae7e-4538-a39b-1fef6abcb909/downloads/filename"
+ ).mock(return_value=httpx.Response(200, json={"foo": "bar"}))
+ with client.zero_trust.dex.commands.downloads.with_streaming_response.get(
+ filename="filename",
+ account_id="01a7362d577a6c3019a474fd6f485823",
+ command_id="5758fefe-ae7e-4538-a39b-1fef6abcb909",
+ ) as download:
+ assert not download.is_closed
+ assert download.http_request.headers.get("X-Stainless-Lang") == "python"
+
+ assert download.json() == {"foo": "bar"}
+ assert cast(Any, download.is_closed) is True
+ assert isinstance(download, StreamedBinaryAPIResponse)
+
+ assert cast(Any, download.is_closed) is True
+
+ @parametrize
+ @pytest.mark.respx(base_url=base_url)
+ def test_path_params_get(self, client: Cloudflare) -> None:
+ with pytest.raises(ValueError, match=r"Expected a non-empty value for `account_id` but received ''"):
+ client.zero_trust.dex.commands.downloads.with_raw_response.get(
+ filename="filename",
+ account_id="",
+ command_id="5758fefe-ae7e-4538-a39b-1fef6abcb909",
+ )
+
+ with pytest.raises(ValueError, match=r"Expected a non-empty value for `command_id` but received ''"):
+ client.zero_trust.dex.commands.downloads.with_raw_response.get(
+ filename="filename",
+ account_id="01a7362d577a6c3019a474fd6f485823",
+ command_id="",
+ )
+
+ with pytest.raises(ValueError, match=r"Expected a non-empty value for `filename` but received ''"):
+ client.zero_trust.dex.commands.downloads.with_raw_response.get(
+ filename="",
+ account_id="01a7362d577a6c3019a474fd6f485823",
+ command_id="5758fefe-ae7e-4538-a39b-1fef6abcb909",
+ )
+
+
+class TestAsyncDownloads:
+ parametrize = pytest.mark.parametrize("async_client", [False, True], indirect=True, ids=["loose", "strict"])
+
+ @parametrize
+ @pytest.mark.respx(base_url=base_url)
+ async def test_method_get(self, async_client: AsyncCloudflare, respx_mock: MockRouter) -> None:
+ respx_mock.get(
+ "/accounts/01a7362d577a6c3019a474fd6f485823/dex/commands/5758fefe-ae7e-4538-a39b-1fef6abcb909/downloads/filename"
+ ).mock(return_value=httpx.Response(200, json={"foo": "bar"}))
+ download = await async_client.zero_trust.dex.commands.downloads.get(
+ filename="filename",
+ account_id="01a7362d577a6c3019a474fd6f485823",
+ command_id="5758fefe-ae7e-4538-a39b-1fef6abcb909",
+ )
+ assert download.is_closed
+ assert await download.json() == {"foo": "bar"}
+ assert cast(Any, download.is_closed) is True
+ assert isinstance(download, AsyncBinaryAPIResponse)
+
+ @parametrize
+ @pytest.mark.respx(base_url=base_url)
+ async def test_raw_response_get(self, async_client: AsyncCloudflare, respx_mock: MockRouter) -> None:
+ respx_mock.get(
+ "/accounts/01a7362d577a6c3019a474fd6f485823/dex/commands/5758fefe-ae7e-4538-a39b-1fef6abcb909/downloads/filename"
+ ).mock(return_value=httpx.Response(200, json={"foo": "bar"}))
+
+ download = await async_client.zero_trust.dex.commands.downloads.with_raw_response.get(
+ filename="filename",
+ account_id="01a7362d577a6c3019a474fd6f485823",
+ command_id="5758fefe-ae7e-4538-a39b-1fef6abcb909",
+ )
+
+ assert download.is_closed is True
+ assert download.http_request.headers.get("X-Stainless-Lang") == "python"
+ assert await download.json() == {"foo": "bar"}
+ assert isinstance(download, AsyncBinaryAPIResponse)
+
+ @parametrize
+ @pytest.mark.respx(base_url=base_url)
+ async def test_streaming_response_get(self, async_client: AsyncCloudflare, respx_mock: MockRouter) -> None:
+ respx_mock.get(
+ "/accounts/01a7362d577a6c3019a474fd6f485823/dex/commands/5758fefe-ae7e-4538-a39b-1fef6abcb909/downloads/filename"
+ ).mock(return_value=httpx.Response(200, json={"foo": "bar"}))
+ async with async_client.zero_trust.dex.commands.downloads.with_streaming_response.get(
+ filename="filename",
+ account_id="01a7362d577a6c3019a474fd6f485823",
+ command_id="5758fefe-ae7e-4538-a39b-1fef6abcb909",
+ ) as download:
+ assert not download.is_closed
+ assert download.http_request.headers.get("X-Stainless-Lang") == "python"
+
+ assert await download.json() == {"foo": "bar"}
+ assert cast(Any, download.is_closed) is True
+ assert isinstance(download, AsyncStreamedBinaryAPIResponse)
+
+ assert cast(Any, download.is_closed) is True
+
+ @parametrize
+ @pytest.mark.respx(base_url=base_url)
+ async def test_path_params_get(self, async_client: AsyncCloudflare) -> None:
+ with pytest.raises(ValueError, match=r"Expected a non-empty value for `account_id` but received ''"):
+ await async_client.zero_trust.dex.commands.downloads.with_raw_response.get(
+ filename="filename",
+ account_id="",
+ command_id="5758fefe-ae7e-4538-a39b-1fef6abcb909",
+ )
+
+ with pytest.raises(ValueError, match=r"Expected a non-empty value for `command_id` but received ''"):
+ await async_client.zero_trust.dex.commands.downloads.with_raw_response.get(
+ filename="filename",
+ account_id="01a7362d577a6c3019a474fd6f485823",
+ command_id="",
+ )
+
+ with pytest.raises(ValueError, match=r"Expected a non-empty value for `filename` but received ''"):
+ await async_client.zero_trust.dex.commands.downloads.with_raw_response.get(
+ filename="",
+ account_id="01a7362d577a6c3019a474fd6f485823",
+ command_id="5758fefe-ae7e-4538-a39b-1fef6abcb909",
+ )
diff --git a/tests/api_resources/zero_trust/dex/commands/test_quota.py b/tests/api_resources/zero_trust/dex/commands/test_quota.py
new file mode 100644
index 00000000000..5291e9d3113
--- /dev/null
+++ b/tests/api_resources/zero_trust/dex/commands/test_quota.py
@@ -0,0 +1,98 @@
+# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details.
+
+from __future__ import annotations
+
+import os
+from typing import Any, Optional, cast
+
+import pytest
+
+from cloudflare import Cloudflare, AsyncCloudflare
+from tests.utils import assert_matches_type
+from cloudflare.types.zero_trust.dex.commands import QuotaGetResponse
+
+base_url = os.environ.get("TEST_API_BASE_URL", "http://127.0.0.1:4010")
+
+
+class TestQuota:
+ parametrize = pytest.mark.parametrize("client", [False, True], indirect=True, ids=["loose", "strict"])
+
+ @parametrize
+ def test_method_get(self, client: Cloudflare) -> None:
+ quota = client.zero_trust.dex.commands.quota.get(
+ account_id="01a7362d577a6c3019a474fd6f485823",
+ )
+ assert_matches_type(Optional[QuotaGetResponse], quota, path=["response"])
+
+ @parametrize
+ def test_raw_response_get(self, client: Cloudflare) -> None:
+ response = client.zero_trust.dex.commands.quota.with_raw_response.get(
+ account_id="01a7362d577a6c3019a474fd6f485823",
+ )
+
+ assert response.is_closed is True
+ assert response.http_request.headers.get("X-Stainless-Lang") == "python"
+ quota = response.parse()
+ assert_matches_type(Optional[QuotaGetResponse], quota, path=["response"])
+
+ @parametrize
+ def test_streaming_response_get(self, client: Cloudflare) -> None:
+ with client.zero_trust.dex.commands.quota.with_streaming_response.get(
+ account_id="01a7362d577a6c3019a474fd6f485823",
+ ) as response:
+ assert not response.is_closed
+ assert response.http_request.headers.get("X-Stainless-Lang") == "python"
+
+ quota = response.parse()
+ assert_matches_type(Optional[QuotaGetResponse], quota, path=["response"])
+
+ assert cast(Any, response.is_closed) is True
+
+ @parametrize
+ def test_path_params_get(self, client: Cloudflare) -> None:
+ with pytest.raises(ValueError, match=r"Expected a non-empty value for `account_id` but received ''"):
+ client.zero_trust.dex.commands.quota.with_raw_response.get(
+ account_id="",
+ )
+
+
+class TestAsyncQuota:
+ parametrize = pytest.mark.parametrize("async_client", [False, True], indirect=True, ids=["loose", "strict"])
+
+ @parametrize
+ async def test_method_get(self, async_client: AsyncCloudflare) -> None:
+ quota = await async_client.zero_trust.dex.commands.quota.get(
+ account_id="01a7362d577a6c3019a474fd6f485823",
+ )
+ assert_matches_type(Optional[QuotaGetResponse], quota, path=["response"])
+
+ @parametrize
+ async def test_raw_response_get(self, async_client: AsyncCloudflare) -> None:
+ response = await async_client.zero_trust.dex.commands.quota.with_raw_response.get(
+ account_id="01a7362d577a6c3019a474fd6f485823",
+ )
+
+ assert response.is_closed is True
+ assert response.http_request.headers.get("X-Stainless-Lang") == "python"
+ quota = await response.parse()
+ assert_matches_type(Optional[QuotaGetResponse], quota, path=["response"])
+
+ @parametrize
+ async def test_streaming_response_get(self, async_client: AsyncCloudflare) -> None:
+ async with async_client.zero_trust.dex.commands.quota.with_streaming_response.get(
+ account_id="01a7362d577a6c3019a474fd6f485823",
+ ) as response:
+ assert not response.is_closed
+ assert response.http_request.headers.get("X-Stainless-Lang") == "python"
+
+ quota = await response.parse()
+ assert_matches_type(Optional[QuotaGetResponse], quota, path=["response"])
+
+ assert cast(Any, response.is_closed) is True
+
+ @parametrize
+ async def test_path_params_get(self, async_client: AsyncCloudflare) -> None:
+ with pytest.raises(ValueError, match=r"Expected a non-empty value for `account_id` but received ''"):
+ await async_client.zero_trust.dex.commands.quota.with_raw_response.get(
+ account_id="",
+ )
diff --git a/tests/api_resources/zero_trust/dex/test_commands.py b/tests/api_resources/zero_trust/dex/test_commands.py
new file mode 100644
index 00000000000..9692c4fde6c
--- /dev/null
+++ b/tests/api_resources/zero_trust/dex/test_commands.py
@@ -0,0 +1,281 @@
+# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details.
+
+from __future__ import annotations
+
+import os
+from typing import Any, Optional, cast
+
+import pytest
+
+from cloudflare import Cloudflare, AsyncCloudflare
+from tests.utils import assert_matches_type
+from cloudflare._utils import parse_datetime
+from cloudflare.pagination import SyncV4PagePagination, AsyncV4PagePagination
+from cloudflare.types.zero_trust.dex import (
+ CommandListResponse,
+ CommandCreateResponse,
+)
+
+base_url = os.environ.get("TEST_API_BASE_URL", "http://127.0.0.1:4010")
+
+
+class TestCommands:
+ parametrize = pytest.mark.parametrize("client", [False, True], indirect=True, ids=["loose", "strict"])
+
+ @parametrize
+ def test_method_create(self, client: Cloudflare) -> None:
+ command = client.zero_trust.dex.commands.create(
+ account_id="01a7362d577a6c3019a474fd6f485823",
+ commands=[
+ {
+ "command_type": "pcap",
+ "device_id": "device_id",
+ "user_email": "user_email",
+ }
+ ],
+ )
+ assert_matches_type(Optional[CommandCreateResponse], command, path=["response"])
+
+ @parametrize
+ def test_raw_response_create(self, client: Cloudflare) -> None:
+ response = client.zero_trust.dex.commands.with_raw_response.create(
+ account_id="01a7362d577a6c3019a474fd6f485823",
+ commands=[
+ {
+ "command_type": "pcap",
+ "device_id": "device_id",
+ "user_email": "user_email",
+ }
+ ],
+ )
+
+ assert response.is_closed is True
+ assert response.http_request.headers.get("X-Stainless-Lang") == "python"
+ command = response.parse()
+ assert_matches_type(Optional[CommandCreateResponse], command, path=["response"])
+
+ @parametrize
+ def test_streaming_response_create(self, client: Cloudflare) -> None:
+ with client.zero_trust.dex.commands.with_streaming_response.create(
+ account_id="01a7362d577a6c3019a474fd6f485823",
+ commands=[
+ {
+ "command_type": "pcap",
+ "device_id": "device_id",
+ "user_email": "user_email",
+ }
+ ],
+ ) as response:
+ assert not response.is_closed
+ assert response.http_request.headers.get("X-Stainless-Lang") == "python"
+
+ command = response.parse()
+ assert_matches_type(Optional[CommandCreateResponse], command, path=["response"])
+
+ assert cast(Any, response.is_closed) is True
+
+ @parametrize
+ def test_path_params_create(self, client: Cloudflare) -> None:
+ with pytest.raises(ValueError, match=r"Expected a non-empty value for `account_id` but received ''"):
+ client.zero_trust.dex.commands.with_raw_response.create(
+ account_id="",
+ commands=[
+ {
+ "command_type": "pcap",
+ "device_id": "device_id",
+ "user_email": "user_email",
+ }
+ ],
+ )
+
+ @parametrize
+ def test_method_list(self, client: Cloudflare) -> None:
+ command = client.zero_trust.dex.commands.list(
+ account_id="01a7362d577a6c3019a474fd6f485823",
+ page=1,
+ per_page=50,
+ )
+ assert_matches_type(SyncV4PagePagination[Optional[CommandListResponse]], command, path=["response"])
+
+ @parametrize
+ def test_method_list_with_all_params(self, client: Cloudflare) -> None:
+ command = client.zero_trust.dex.commands.list(
+ account_id="01a7362d577a6c3019a474fd6f485823",
+ page=1,
+ per_page=50,
+ command_type="command_type",
+ device_id="device_id",
+ from_=parse_datetime("2023-08-20T20:45:00Z"),
+ status="PENDING_EXEC",
+ to=parse_datetime("2023-08-24T20:45:00Z"),
+ user_email="user_email",
+ )
+ assert_matches_type(SyncV4PagePagination[Optional[CommandListResponse]], command, path=["response"])
+
+ @parametrize
+ def test_raw_response_list(self, client: Cloudflare) -> None:
+ response = client.zero_trust.dex.commands.with_raw_response.list(
+ account_id="01a7362d577a6c3019a474fd6f485823",
+ page=1,
+ per_page=50,
+ )
+
+ assert response.is_closed is True
+ assert response.http_request.headers.get("X-Stainless-Lang") == "python"
+ command = response.parse()
+ assert_matches_type(SyncV4PagePagination[Optional[CommandListResponse]], command, path=["response"])
+
+ @parametrize
+ def test_streaming_response_list(self, client: Cloudflare) -> None:
+ with client.zero_trust.dex.commands.with_streaming_response.list(
+ account_id="01a7362d577a6c3019a474fd6f485823",
+ page=1,
+ per_page=50,
+ ) as response:
+ assert not response.is_closed
+ assert response.http_request.headers.get("X-Stainless-Lang") == "python"
+
+ command = response.parse()
+ assert_matches_type(SyncV4PagePagination[Optional[CommandListResponse]], command, path=["response"])
+
+ assert cast(Any, response.is_closed) is True
+
+ @parametrize
+ def test_path_params_list(self, client: Cloudflare) -> None:
+ with pytest.raises(ValueError, match=r"Expected a non-empty value for `account_id` but received ''"):
+ client.zero_trust.dex.commands.with_raw_response.list(
+ account_id="",
+ page=1,
+ per_page=50,
+ )
+
+
+class TestAsyncCommands:
+ parametrize = pytest.mark.parametrize("async_client", [False, True], indirect=True, ids=["loose", "strict"])
+
+ @parametrize
+ async def test_method_create(self, async_client: AsyncCloudflare) -> None:
+ command = await async_client.zero_trust.dex.commands.create(
+ account_id="01a7362d577a6c3019a474fd6f485823",
+ commands=[
+ {
+ "command_type": "pcap",
+ "device_id": "device_id",
+ "user_email": "user_email",
+ }
+ ],
+ )
+ assert_matches_type(Optional[CommandCreateResponse], command, path=["response"])
+
+ @parametrize
+ async def test_raw_response_create(self, async_client: AsyncCloudflare) -> None:
+ response = await async_client.zero_trust.dex.commands.with_raw_response.create(
+ account_id="01a7362d577a6c3019a474fd6f485823",
+ commands=[
+ {
+ "command_type": "pcap",
+ "device_id": "device_id",
+ "user_email": "user_email",
+ }
+ ],
+ )
+
+ assert response.is_closed is True
+ assert response.http_request.headers.get("X-Stainless-Lang") == "python"
+ command = await response.parse()
+ assert_matches_type(Optional[CommandCreateResponse], command, path=["response"])
+
+ @parametrize
+ async def test_streaming_response_create(self, async_client: AsyncCloudflare) -> None:
+ async with async_client.zero_trust.dex.commands.with_streaming_response.create(
+ account_id="01a7362d577a6c3019a474fd6f485823",
+ commands=[
+ {
+ "command_type": "pcap",
+ "device_id": "device_id",
+ "user_email": "user_email",
+ }
+ ],
+ ) as response:
+ assert not response.is_closed
+ assert response.http_request.headers.get("X-Stainless-Lang") == "python"
+
+ command = await response.parse()
+ assert_matches_type(Optional[CommandCreateResponse], command, path=["response"])
+
+ assert cast(Any, response.is_closed) is True
+
+ @parametrize
+ async def test_path_params_create(self, async_client: AsyncCloudflare) -> None:
+ with pytest.raises(ValueError, match=r"Expected a non-empty value for `account_id` but received ''"):
+ await async_client.zero_trust.dex.commands.with_raw_response.create(
+ account_id="",
+ commands=[
+ {
+ "command_type": "pcap",
+ "device_id": "device_id",
+ "user_email": "user_email",
+ }
+ ],
+ )
+
+ @parametrize
+ async def test_method_list(self, async_client: AsyncCloudflare) -> None:
+ command = await async_client.zero_trust.dex.commands.list(
+ account_id="01a7362d577a6c3019a474fd6f485823",
+ page=1,
+ per_page=50,
+ )
+ assert_matches_type(AsyncV4PagePagination[Optional[CommandListResponse]], command, path=["response"])
+
+ @parametrize
+ async def test_method_list_with_all_params(self, async_client: AsyncCloudflare) -> None:
+ command = await async_client.zero_trust.dex.commands.list(
+ account_id="01a7362d577a6c3019a474fd6f485823",
+ page=1,
+ per_page=50,
+ command_type="command_type",
+ device_id="device_id",
+ from_=parse_datetime("2023-08-20T20:45:00Z"),
+ status="PENDING_EXEC",
+ to=parse_datetime("2023-08-24T20:45:00Z"),
+ user_email="user_email",
+ )
+ assert_matches_type(AsyncV4PagePagination[Optional[CommandListResponse]], command, path=["response"])
+
+ @parametrize
+ async def test_raw_response_list(self, async_client: AsyncCloudflare) -> None:
+ response = await async_client.zero_trust.dex.commands.with_raw_response.list(
+ account_id="01a7362d577a6c3019a474fd6f485823",
+ page=1,
+ per_page=50,
+ )
+
+ assert response.is_closed is True
+ assert response.http_request.headers.get("X-Stainless-Lang") == "python"
+ command = await response.parse()
+ assert_matches_type(AsyncV4PagePagination[Optional[CommandListResponse]], command, path=["response"])
+
+ @parametrize
+ async def test_streaming_response_list(self, async_client: AsyncCloudflare) -> None:
+ async with async_client.zero_trust.dex.commands.with_streaming_response.list(
+ account_id="01a7362d577a6c3019a474fd6f485823",
+ page=1,
+ per_page=50,
+ ) as response:
+ assert not response.is_closed
+ assert response.http_request.headers.get("X-Stainless-Lang") == "python"
+
+ command = await response.parse()
+ assert_matches_type(AsyncV4PagePagination[Optional[CommandListResponse]], command, path=["response"])
+
+ assert cast(Any, response.is_closed) is True
+
+ @parametrize
+ async def test_path_params_list(self, async_client: AsyncCloudflare) -> None:
+ with pytest.raises(ValueError, match=r"Expected a non-empty value for `account_id` but received ''"):
+ await async_client.zero_trust.dex.commands.with_raw_response.list(
+ account_id="",
+ page=1,
+ per_page=50,
+ )
diff --git a/tests/api_resources/zones/test_holds.py b/tests/api_resources/zones/test_holds.py
index bc033b8fdc7..b34e5066342 100644
--- a/tests/api_resources/zones/test_holds.py
+++ b/tests/api_resources/zones/test_holds.py
@@ -109,6 +109,53 @@ def test_path_params_delete(self, client: Cloudflare) -> None:
zone_id="",
)
+ @parametrize
+ def test_method_edit(self, client: Cloudflare) -> None:
+ hold = client.zones.holds.edit(
+ zone_id="023e105f4ecef8ad9ca31a8372d0c353",
+ )
+ assert_matches_type(ZoneHold, hold, path=["response"])
+
+ @parametrize
+ def test_method_edit_with_all_params(self, client: Cloudflare) -> None:
+ hold = client.zones.holds.edit(
+ zone_id="023e105f4ecef8ad9ca31a8372d0c353",
+ hold_after="2023-01-31T15:56:36+00:00",
+ include_subdomains=True,
+ )
+ assert_matches_type(ZoneHold, hold, path=["response"])
+
+ @parametrize
+ def test_raw_response_edit(self, client: Cloudflare) -> None:
+ response = client.zones.holds.with_raw_response.edit(
+ zone_id="023e105f4ecef8ad9ca31a8372d0c353",
+ )
+
+ assert response.is_closed is True
+ assert response.http_request.headers.get("X-Stainless-Lang") == "python"
+ hold = response.parse()
+ assert_matches_type(ZoneHold, hold, path=["response"])
+
+ @parametrize
+ def test_streaming_response_edit(self, client: Cloudflare) -> None:
+ with client.zones.holds.with_streaming_response.edit(
+ zone_id="023e105f4ecef8ad9ca31a8372d0c353",
+ ) as response:
+ assert not response.is_closed
+ assert response.http_request.headers.get("X-Stainless-Lang") == "python"
+
+ hold = response.parse()
+ assert_matches_type(ZoneHold, hold, path=["response"])
+
+ assert cast(Any, response.is_closed) is True
+
+ @parametrize
+ def test_path_params_edit(self, client: Cloudflare) -> None:
+ with pytest.raises(ValueError, match=r"Expected a non-empty value for `zone_id` but received ''"):
+ client.zones.holds.with_raw_response.edit(
+ zone_id="",
+ )
+
@parametrize
def test_method_get(self, client: Cloudflare) -> None:
hold = client.zones.holds.get(
@@ -243,6 +290,53 @@ async def test_path_params_delete(self, async_client: AsyncCloudflare) -> None:
zone_id="",
)
+ @parametrize
+ async def test_method_edit(self, async_client: AsyncCloudflare) -> None:
+ hold = await async_client.zones.holds.edit(
+ zone_id="023e105f4ecef8ad9ca31a8372d0c353",
+ )
+ assert_matches_type(ZoneHold, hold, path=["response"])
+
+ @parametrize
+ async def test_method_edit_with_all_params(self, async_client: AsyncCloudflare) -> None:
+ hold = await async_client.zones.holds.edit(
+ zone_id="023e105f4ecef8ad9ca31a8372d0c353",
+ hold_after="2023-01-31T15:56:36+00:00",
+ include_subdomains=True,
+ )
+ assert_matches_type(ZoneHold, hold, path=["response"])
+
+ @parametrize
+ async def test_raw_response_edit(self, async_client: AsyncCloudflare) -> None:
+ response = await async_client.zones.holds.with_raw_response.edit(
+ zone_id="023e105f4ecef8ad9ca31a8372d0c353",
+ )
+
+ assert response.is_closed is True
+ assert response.http_request.headers.get("X-Stainless-Lang") == "python"
+ hold = await response.parse()
+ assert_matches_type(ZoneHold, hold, path=["response"])
+
+ @parametrize
+ async def test_streaming_response_edit(self, async_client: AsyncCloudflare) -> None:
+ async with async_client.zones.holds.with_streaming_response.edit(
+ zone_id="023e105f4ecef8ad9ca31a8372d0c353",
+ ) as response:
+ assert not response.is_closed
+ assert response.http_request.headers.get("X-Stainless-Lang") == "python"
+
+ hold = await response.parse()
+ assert_matches_type(ZoneHold, hold, path=["response"])
+
+ assert cast(Any, response.is_closed) is True
+
+ @parametrize
+ async def test_path_params_edit(self, async_client: AsyncCloudflare) -> None:
+ with pytest.raises(ValueError, match=r"Expected a non-empty value for `zone_id` but received ''"):
+ await async_client.zones.holds.with_raw_response.edit(
+ zone_id="",
+ )
+
@parametrize
async def test_method_get(self, async_client: AsyncCloudflare) -> None:
hold = await async_client.zones.holds.get(