diff --git a/.stats.yml b/.stats.yml
index 330be9e14a4..0440ff0afac 100644
--- a/.stats.yml
+++ b/.stats.yml
@@ -1,2 +1,2 @@
configured_endpoints: 1343
-openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/cloudflare%2Fcloudflare-0053e474edb7f838f2b1d38334a7ccb983db09216cca0173a3c3d5401cadcf82.yml
+openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/cloudflare%2Fcloudflare-d780b9eb98465e97c30112eb2c9e586883852508d23a6684bd28e5a9cb7da7a1.yml
diff --git a/api.md b/api.md
index 5295390d972..5d3170fce1e 100644
--- a/api.md
+++ b/api.md
@@ -3498,15 +3498,9 @@ Methods:
### Downloads
-Types:
-
-```python
-from cloudflare.types.addressing.loa_documents import DownloadGetResponse
-```
-
Methods:
-- client.addressing.loa_documents.downloads.get(loa_document_id, \*, account_id) -> object
+- client.addressing.loa_documents.downloads.get(loa_document_id, \*, account_id) -> BinaryAPIResponse
## Prefixes
diff --git a/src/cloudflare/resources/addressing/address_maps/address_maps.py b/src/cloudflare/resources/addressing/address_maps/address_maps.py
index bb2faee96ef..c92ddd937a3 100644
--- a/src/cloudflare/resources/addressing/address_maps/address_maps.py
+++ b/src/cloudflare/resources/addressing/address_maps/address_maps.py
@@ -2,7 +2,7 @@
from __future__ import annotations
-from typing import Type, Optional, cast
+from typing import List, Type, Iterable, Optional, cast
import httpx
@@ -85,6 +85,8 @@ def create(
account_id: str,
description: Optional[str] | NotGiven = NOT_GIVEN,
enabled: Optional[bool] | NotGiven = NOT_GIVEN,
+ ips: List[str] | NotGiven = NOT_GIVEN,
+ memberships: Iterable[address_map_create_params.Membership] | 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,
@@ -104,6 +106,9 @@ def create(
enabled: Whether the Address Map is enabled or not. Cloudflare's DNS will not respond
with IP addresses on an Address Map until the map is enabled.
+ memberships: Zones and Accounts which will be assigned IPs on this Address Map. A zone
+ membership will take priority over an account membership.
+
extra_headers: Send extra headers
extra_query: Add additional query parameters to the request
@@ -120,6 +125,8 @@ def create(
{
"description": description,
"enabled": enabled,
+ "ips": ips,
+ "memberships": memberships,
},
address_map_create_params.AddressMapCreateParams,
),
@@ -354,6 +361,8 @@ async def create(
account_id: str,
description: Optional[str] | NotGiven = NOT_GIVEN,
enabled: Optional[bool] | NotGiven = NOT_GIVEN,
+ ips: List[str] | NotGiven = NOT_GIVEN,
+ memberships: Iterable[address_map_create_params.Membership] | 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,
@@ -373,6 +382,9 @@ async def create(
enabled: Whether the Address Map is enabled or not. Cloudflare's DNS will not respond
with IP addresses on an Address Map until the map is enabled.
+ memberships: Zones and Accounts which will be assigned IPs on this Address Map. A zone
+ membership will take priority over an account membership.
+
extra_headers: Send extra headers
extra_query: Add additional query parameters to the request
@@ -389,6 +401,8 @@ async def create(
{
"description": description,
"enabled": enabled,
+ "ips": ips,
+ "memberships": memberships,
},
address_map_create_params.AddressMapCreateParams,
),
diff --git a/src/cloudflare/resources/addressing/loa_documents/downloads.py b/src/cloudflare/resources/addressing/loa_documents/downloads.py
index b29d0888acd..e333bc3e986 100644
--- a/src/cloudflare/resources/addressing/loa_documents/downloads.py
+++ b/src/cloudflare/resources/addressing/loa_documents/downloads.py
@@ -10,10 +10,14 @@
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,
+ 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,
@@ -42,7 +46,7 @@ def get(
extra_query: Query | None = None,
extra_body: Body | None = None,
timeout: float | httpx.Timeout | None | NotGiven = NOT_GIVEN,
- ) -> object:
+ ) -> BinaryAPIResponse:
"""
Download specified LOA document under the account.
@@ -63,12 +67,13 @@ def get(
raise ValueError(f"Expected a non-empty value for `account_id` but received {account_id!r}")
if not loa_document_id:
raise ValueError(f"Expected a non-empty value for `loa_document_id` but received {loa_document_id!r}")
+ extra_headers = {"Accept": "application/pdf", **(extra_headers or {})}
return self._get(
f"/accounts/{account_id}/addressing/loa_documents/{loa_document_id}/download",
options=make_request_options(
extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout
),
- cast_to=object,
+ cast_to=BinaryAPIResponse,
)
@@ -92,7 +97,7 @@ async def get(
extra_query: Query | None = None,
extra_body: Body | None = None,
timeout: float | httpx.Timeout | None | NotGiven = NOT_GIVEN,
- ) -> object:
+ ) -> AsyncBinaryAPIResponse:
"""
Download specified LOA document under the account.
@@ -113,12 +118,13 @@ async def get(
raise ValueError(f"Expected a non-empty value for `account_id` but received {account_id!r}")
if not loa_document_id:
raise ValueError(f"Expected a non-empty value for `loa_document_id` but received {loa_document_id!r}")
+ extra_headers = {"Accept": "application/pdf", **(extra_headers or {})}
return await self._get(
f"/accounts/{account_id}/addressing/loa_documents/{loa_document_id}/download",
options=make_request_options(
extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout
),
- cast_to=object,
+ cast_to=AsyncBinaryAPIResponse,
)
@@ -126,8 +132,9 @@ class DownloadsResourceWithRawResponse:
def __init__(self, downloads: DownloadsResource) -> None:
self._downloads = downloads
- self.get = to_raw_response_wrapper(
+ self.get = to_custom_raw_response_wrapper(
downloads.get,
+ BinaryAPIResponse,
)
@@ -135,8 +142,9 @@ class AsyncDownloadsResourceWithRawResponse:
def __init__(self, downloads: AsyncDownloadsResource) -> None:
self._downloads = downloads
- self.get = async_to_raw_response_wrapper(
+ self.get = async_to_custom_raw_response_wrapper(
downloads.get,
+ AsyncBinaryAPIResponse,
)
@@ -144,8 +152,9 @@ class DownloadsResourceWithStreamingResponse:
def __init__(self, downloads: DownloadsResource) -> None:
self._downloads = downloads
- self.get = to_streamed_response_wrapper(
+ self.get = to_custom_streamed_response_wrapper(
downloads.get,
+ StreamedBinaryAPIResponse,
)
@@ -153,6 +162,7 @@ class AsyncDownloadsResourceWithStreamingResponse:
def __init__(self, downloads: AsyncDownloadsResource) -> None:
self._downloads = downloads
- self.get = async_to_streamed_response_wrapper(
+ self.get = async_to_custom_streamed_response_wrapper(
downloads.get,
+ AsyncStreamedBinaryAPIResponse,
)
diff --git a/src/cloudflare/types/addressing/address_map_create_params.py b/src/cloudflare/types/addressing/address_map_create_params.py
index 5ecc49b6e6e..ac313102d61 100644
--- a/src/cloudflare/types/addressing/address_map_create_params.py
+++ b/src/cloudflare/types/addressing/address_map_create_params.py
@@ -2,10 +2,12 @@
from __future__ import annotations
-from typing import Optional
+from typing import List, Iterable, Optional
from typing_extensions import Required, TypedDict
-__all__ = ["AddressMapCreateParams"]
+from .kind import Kind
+
+__all__ = ["AddressMapCreateParams", "Membership"]
class AddressMapCreateParams(TypedDict, total=False):
@@ -24,3 +26,19 @@ class AddressMapCreateParams(TypedDict, total=False):
Cloudflare's DNS will not respond with IP addresses on an Address Map until the
map is enabled.
"""
+
+ ips: List[str]
+
+ memberships: Iterable[Membership]
+ """Zones and Accounts which will be assigned IPs on this Address Map.
+
+ A zone membership will take priority over an account membership.
+ """
+
+
+class Membership(TypedDict, total=False):
+ identifier: str
+ """The identifier for the membership (eg. a zone or account tag)."""
+
+ kind: Kind
+ """The type of the membership."""
diff --git a/src/cloudflare/types/addressing/address_map_create_response.py b/src/cloudflare/types/addressing/address_map_create_response.py
index d4eb788e2df..032e1166d18 100644
--- a/src/cloudflare/types/addressing/address_map_create_response.py
+++ b/src/cloudflare/types/addressing/address_map_create_response.py
@@ -23,7 +23,7 @@ class Membership(BaseModel):
created_at: Optional[datetime] = None
identifier: Optional[str] = None
- """Identifier"""
+ """The identifier for the membership (eg. a zone or account tag)."""
kind: Optional[Kind] = None
"""The type of the membership."""
diff --git a/src/cloudflare/types/addressing/address_map_get_response.py b/src/cloudflare/types/addressing/address_map_get_response.py
index 06bdfc92ed8..0eb306ccdbd 100644
--- a/src/cloudflare/types/addressing/address_map_get_response.py
+++ b/src/cloudflare/types/addressing/address_map_get_response.py
@@ -23,7 +23,7 @@ class Membership(BaseModel):
created_at: Optional[datetime] = None
identifier: Optional[str] = None
- """Identifier"""
+ """The identifier for the membership (eg. a zone or account tag)."""
kind: Optional[Kind] = None
"""The type of the membership."""
diff --git a/tests/api_resources/addressing/loa_documents/test_downloads.py b/tests/api_resources/addressing/loa_documents/test_downloads.py
index db82ee230fa..bd37633f548 100644
--- a/tests/api_resources/addressing/loa_documents/test_downloads.py
+++ b/tests/api_resources/addressing/loa_documents/test_downloads.py
@@ -5,10 +5,17 @@
import os
from typing import Any, cast
+import httpx
import pytest
+from respx import MockRouter
from cloudflare import Cloudflare, AsyncCloudflare
-from tests.utils import assert_matches_type
+from cloudflare._response import (
+ BinaryAPIResponse,
+ AsyncBinaryAPIResponse,
+ StreamedBinaryAPIResponse,
+ AsyncStreamedBinaryAPIResponse,
+)
base_url = os.environ.get("TEST_API_BASE_URL", "http://127.0.0.1:4010")
@@ -17,40 +24,58 @@ class TestDownloads:
parametrize = pytest.mark.parametrize("client", [False, True], indirect=True, ids=["loose", "strict"])
@parametrize
- def test_method_get(self, client: Cloudflare) -> None:
+ @pytest.mark.respx(base_url=base_url)
+ def test_method_get(self, client: Cloudflare, respx_mock: MockRouter) -> None:
+ respx_mock.get(
+ "/accounts/023e105f4ecef8ad9ca31a8372d0c353/addressing/loa_documents/d933b1530bc56c9953cf8ce166da8004/download"
+ ).mock(return_value=httpx.Response(200, json={"foo": "bar"}))
download = client.addressing.loa_documents.downloads.get(
"d933b1530bc56c9953cf8ce166da8004",
account_id="023e105f4ecef8ad9ca31a8372d0c353",
)
- assert_matches_type(object, download, path=["response"])
+ assert download.is_closed
+ assert download.json() == {"foo": "bar"}
+ assert cast(Any, download.is_closed) is True
+ assert isinstance(download, BinaryAPIResponse)
@parametrize
- def test_raw_response_get(self, client: Cloudflare) -> None:
- response = client.addressing.loa_documents.downloads.with_raw_response.get(
+ @pytest.mark.respx(base_url=base_url)
+ def test_raw_response_get(self, client: Cloudflare, respx_mock: MockRouter) -> None:
+ respx_mock.get(
+ "/accounts/023e105f4ecef8ad9ca31a8372d0c353/addressing/loa_documents/d933b1530bc56c9953cf8ce166da8004/download"
+ ).mock(return_value=httpx.Response(200, json={"foo": "bar"}))
+
+ download = client.addressing.loa_documents.downloads.with_raw_response.get(
"d933b1530bc56c9953cf8ce166da8004",
account_id="023e105f4ecef8ad9ca31a8372d0c353",
)
- assert response.is_closed is True
- assert response.http_request.headers.get("X-Stainless-Lang") == "python"
- download = response.parse()
- assert_matches_type(object, download, path=["response"])
+ 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
- def test_streaming_response_get(self, client: Cloudflare) -> None:
+ @pytest.mark.respx(base_url=base_url)
+ def test_streaming_response_get(self, client: Cloudflare, respx_mock: MockRouter) -> None:
+ respx_mock.get(
+ "/accounts/023e105f4ecef8ad9ca31a8372d0c353/addressing/loa_documents/d933b1530bc56c9953cf8ce166da8004/download"
+ ).mock(return_value=httpx.Response(200, json={"foo": "bar"}))
with client.addressing.loa_documents.downloads.with_streaming_response.get(
"d933b1530bc56c9953cf8ce166da8004",
account_id="023e105f4ecef8ad9ca31a8372d0c353",
- ) as response:
- assert not response.is_closed
- assert response.http_request.headers.get("X-Stainless-Lang") == "python"
+ ) as download:
+ assert not download.is_closed
+ assert download.http_request.headers.get("X-Stainless-Lang") == "python"
- download = response.parse()
- assert_matches_type(object, download, path=["response"])
+ assert download.json() == {"foo": "bar"}
+ assert cast(Any, download.is_closed) is True
+ assert isinstance(download, StreamedBinaryAPIResponse)
- assert cast(Any, response.is_closed) is True
+ 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.addressing.loa_documents.downloads.with_raw_response.get(
@@ -69,40 +94,58 @@ class TestAsyncDownloads:
parametrize = pytest.mark.parametrize("async_client", [False, True], indirect=True, ids=["loose", "strict"])
@parametrize
- async def test_method_get(self, async_client: AsyncCloudflare) -> None:
+ @pytest.mark.respx(base_url=base_url)
+ async def test_method_get(self, async_client: AsyncCloudflare, respx_mock: MockRouter) -> None:
+ respx_mock.get(
+ "/accounts/023e105f4ecef8ad9ca31a8372d0c353/addressing/loa_documents/d933b1530bc56c9953cf8ce166da8004/download"
+ ).mock(return_value=httpx.Response(200, json={"foo": "bar"}))
download = await async_client.addressing.loa_documents.downloads.get(
"d933b1530bc56c9953cf8ce166da8004",
account_id="023e105f4ecef8ad9ca31a8372d0c353",
)
- assert_matches_type(object, download, path=["response"])
+ assert download.is_closed
+ assert await download.json() == {"foo": "bar"}
+ assert cast(Any, download.is_closed) is True
+ assert isinstance(download, AsyncBinaryAPIResponse)
@parametrize
- async def test_raw_response_get(self, async_client: AsyncCloudflare) -> None:
- response = await async_client.addressing.loa_documents.downloads.with_raw_response.get(
+ @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/023e105f4ecef8ad9ca31a8372d0c353/addressing/loa_documents/d933b1530bc56c9953cf8ce166da8004/download"
+ ).mock(return_value=httpx.Response(200, json={"foo": "bar"}))
+
+ download = await async_client.addressing.loa_documents.downloads.with_raw_response.get(
"d933b1530bc56c9953cf8ce166da8004",
account_id="023e105f4ecef8ad9ca31a8372d0c353",
)
- assert response.is_closed is True
- assert response.http_request.headers.get("X-Stainless-Lang") == "python"
- download = await response.parse()
- assert_matches_type(object, download, path=["response"])
+ 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
- async def test_streaming_response_get(self, async_client: AsyncCloudflare) -> None:
+ @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/023e105f4ecef8ad9ca31a8372d0c353/addressing/loa_documents/d933b1530bc56c9953cf8ce166da8004/download"
+ ).mock(return_value=httpx.Response(200, json={"foo": "bar"}))
async with async_client.addressing.loa_documents.downloads.with_streaming_response.get(
"d933b1530bc56c9953cf8ce166da8004",
account_id="023e105f4ecef8ad9ca31a8372d0c353",
- ) as response:
- assert not response.is_closed
- assert response.http_request.headers.get("X-Stainless-Lang") == "python"
+ ) as download:
+ assert not download.is_closed
+ assert download.http_request.headers.get("X-Stainless-Lang") == "python"
- download = await response.parse()
- assert_matches_type(object, download, path=["response"])
+ assert await download.json() == {"foo": "bar"}
+ assert cast(Any, download.is_closed) is True
+ assert isinstance(download, AsyncStreamedBinaryAPIResponse)
- assert cast(Any, response.is_closed) is True
+ 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.addressing.loa_documents.downloads.with_raw_response.get(
diff --git a/tests/api_resources/addressing/test_address_maps.py b/tests/api_resources/addressing/test_address_maps.py
index 1a4e0b0a57c..a883e9dfd4b 100644
--- a/tests/api_resources/addressing/test_address_maps.py
+++ b/tests/api_resources/addressing/test_address_maps.py
@@ -36,6 +36,21 @@ def test_method_create_with_all_params(self, client: Cloudflare) -> None:
account_id="023e105f4ecef8ad9ca31a8372d0c353",
description="My Ecommerce zones",
enabled=True,
+ ips=["192.0.2.1", "192.0.2.1", "192.0.2.1"],
+ memberships=[
+ {
+ "identifier": "023e105f4ecef8ad9ca31a8372d0c353",
+ "kind": "zone",
+ },
+ {
+ "identifier": "023e105f4ecef8ad9ca31a8372d0c353",
+ "kind": "zone",
+ },
+ {
+ "identifier": "023e105f4ecef8ad9ca31a8372d0c353",
+ "kind": "zone",
+ },
+ ],
)
assert_matches_type(Optional[AddressMapCreateResponse], address_map, path=["response"])
@@ -280,6 +295,21 @@ async def test_method_create_with_all_params(self, async_client: AsyncCloudflare
account_id="023e105f4ecef8ad9ca31a8372d0c353",
description="My Ecommerce zones",
enabled=True,
+ ips=["192.0.2.1", "192.0.2.1", "192.0.2.1"],
+ memberships=[
+ {
+ "identifier": "023e105f4ecef8ad9ca31a8372d0c353",
+ "kind": "zone",
+ },
+ {
+ "identifier": "023e105f4ecef8ad9ca31a8372d0c353",
+ "kind": "zone",
+ },
+ {
+ "identifier": "023e105f4ecef8ad9ca31a8372d0c353",
+ "kind": "zone",
+ },
+ ],
)
assert_matches_type(Optional[AddressMapCreateResponse], address_map, path=["response"])