diff --git a/api.md b/api.md index 4fe18906944..0e8cce382be 100644 --- a/api.md +++ b/api.md @@ -10,7 +10,6 @@ from cloudflare.types import ( PaginationInfo, ResponseInfo, Result, - User, ) ``` @@ -19,7 +18,14 @@ from cloudflare.types import ( Types: ```python -from cloudflare.types import Account, AccountUpdateResponse, AccountListResponse, AccountGetResponse +from cloudflare.types import ( + Account, + Role, + User, + AccountUpdateResponse, + AccountListResponse, + AccountGetResponse, +) ``` Methods: @@ -33,33 +39,28 @@ Methods: Types: ```python -from cloudflare.types.accounts import ( - MemberRole, - MemberWithInviteCode, - MemberListResponse, - MemberDeleteResponse, -) +from cloudflare.types.accounts import UserWithInviteCode, MemberListResponse, MemberDeleteResponse ``` Methods: -- client.accounts.members.create(\*, account_id, \*\*params) -> MemberWithInviteCode -- client.accounts.members.update(member_id, \*, account_id, \*\*params) -> User +- client.accounts.members.create(\*, account_id, \*\*params) -> UserWithInviteCode +- client.accounts.members.update(member_id, \*, account_id, \*\*params) -> User - client.accounts.members.list(\*, account_id, \*\*params) -> SyncV4PagePaginationArray[MemberListResponse] - client.accounts.members.delete(member_id, \*, account_id, \*\*params) -> Optional -- client.accounts.members.get(member_id, \*, account_id) -> User +- client.accounts.members.get(member_id, \*, account_id) -> User ## Roles Types: ```python -from cloudflare.types.accounts import PermissionGrant, RoleListResponse, RoleGetResponse +from cloudflare.types.accounts import PermissionGrant, RoleGetResponse ``` Methods: -- client.accounts.roles.list(\*, account_id) -> SyncSinglePage[RoleListResponse] +- client.accounts.roles.list(\*, account_id) -> SyncSinglePage[Role] - client.accounts.roles.get(role_id, \*, account_id) -> RoleGetResponse # OriginCACertificates diff --git a/src/cloudflare/resources/accounts/members.py b/src/cloudflare/resources/accounts/members.py index 7bcb1a714ab..41b7eac0cfc 100644 --- a/src/cloudflare/resources/accounts/members.py +++ b/src/cloudflare/resources/accounts/members.py @@ -7,6 +7,7 @@ import httpx +from ...types import User from ..._types import NOT_GIVEN, Body, Query, Headers, NotGiven from ..._utils import ( maybe_transform, @@ -26,12 +27,10 @@ AsyncPaginator, make_request_options, ) -from ...types.shared import User from ...types.accounts import ( - MemberRoleParam, MemberListResponse, + UserWithInviteCode, MemberDeleteResponse, - MemberWithInviteCode, member_list_params, member_create_params, member_delete_params, @@ -63,7 +62,7 @@ def create( extra_query: Query | None = None, extra_body: Body | None = None, timeout: float | httpx.Timeout | None | NotGiven = NOT_GIVEN, - ) -> MemberWithInviteCode: + ) -> UserWithInviteCode: """ Add a user to the list of members for this account. @@ -97,7 +96,7 @@ def create( timeout=timeout, post_parser=ResultWrapper._unwrapper, ), - cast_to=cast(Type[MemberWithInviteCode], ResultWrapper[MemberWithInviteCode]), + cast_to=cast(Type[UserWithInviteCode], ResultWrapper[UserWithInviteCode]), ) def update( @@ -105,7 +104,7 @@ def update( member_id: str, *, account_id: object, - roles: Iterable[MemberRoleParam], + roles: Iterable[member_update_params.Role], # 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, @@ -309,7 +308,7 @@ async def create( extra_query: Query | None = None, extra_body: Body | None = None, timeout: float | httpx.Timeout | None | NotGiven = NOT_GIVEN, - ) -> MemberWithInviteCode: + ) -> UserWithInviteCode: """ Add a user to the list of members for this account. @@ -343,7 +342,7 @@ async def create( timeout=timeout, post_parser=ResultWrapper._unwrapper, ), - cast_to=cast(Type[MemberWithInviteCode], ResultWrapper[MemberWithInviteCode]), + cast_to=cast(Type[UserWithInviteCode], ResultWrapper[UserWithInviteCode]), ) async def update( @@ -351,7 +350,7 @@ async def update( member_id: str, *, account_id: object, - roles: Iterable[MemberRoleParam], + roles: Iterable[member_update_params.Role], # 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, diff --git a/src/cloudflare/resources/accounts/roles.py b/src/cloudflare/resources/accounts/roles.py index c3d7190308e..694e09bb31c 100644 --- a/src/cloudflare/resources/accounts/roles.py +++ b/src/cloudflare/resources/accounts/roles.py @@ -6,6 +6,7 @@ import httpx +from ...types import Role from ..._types import NOT_GIVEN, Body, Query, Headers, NotGiven from ..._compat import cached_property from ..._resource import SyncAPIResource, AsyncAPIResource @@ -21,7 +22,7 @@ AsyncPaginator, make_request_options, ) -from ...types.accounts import RoleGetResponse, RoleListResponse +from ...types.accounts import RoleGetResponse __all__ = ["Roles", "AsyncRoles"] @@ -45,7 +46,7 @@ def list( extra_query: Query | None = None, extra_body: Body | None = None, timeout: float | httpx.Timeout | None | NotGiven = NOT_GIVEN, - ) -> SyncSinglePage[RoleListResponse]: + ) -> SyncSinglePage[Role]: """ Get all available roles for an account. @@ -60,11 +61,11 @@ def list( """ return self._get_api_list( f"/accounts/{account_id}/roles", - page=SyncSinglePage[RoleListResponse], + page=SyncSinglePage[Role], options=make_request_options( extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout ), - model=RoleListResponse, + model=Role, ) def get( @@ -128,7 +129,7 @@ def list( extra_query: Query | None = None, extra_body: Body | None = None, timeout: float | httpx.Timeout | None | NotGiven = NOT_GIVEN, - ) -> AsyncPaginator[RoleListResponse, AsyncSinglePage[RoleListResponse]]: + ) -> AsyncPaginator[Role, AsyncSinglePage[Role]]: """ Get all available roles for an account. @@ -143,11 +144,11 @@ def list( """ return self._get_api_list( f"/accounts/{account_id}/roles", - page=AsyncSinglePage[RoleListResponse], + page=AsyncSinglePage[Role], options=make_request_options( extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout ), - model=RoleListResponse, + model=Role, ) async def get( diff --git a/src/cloudflare/types/__init__.py b/src/cloudflare/types/__init__.py index bad3e5d09ca..8434e540549 100644 --- a/src/cloudflare/types/__init__.py +++ b/src/cloudflare/types/__init__.py @@ -8,6 +8,8 @@ from .host import Host as Host from .info import Info as Info from .pcap import PCAP as PCAP +from .role import Role as Role +from .user import User as User from .zone import Zone as Zone from .queue import Queue as Queue from .route import Route as Route @@ -19,7 +21,6 @@ from .header import Header as Header from .origin import Origin as Origin from .shared import ( - User as User, Result as Result, AuditLog as AuditLog, ErrorData as ErrorData, diff --git a/src/cloudflare/types/accounts/__init__.py b/src/cloudflare/types/accounts/__init__.py index bedf04b227a..f9a21b53a23 100644 --- a/src/cloudflare/types/accounts/__init__.py +++ b/src/cloudflare/types/accounts/__init__.py @@ -2,16 +2,13 @@ from __future__ import annotations -from .member_role import MemberRole as MemberRole from .permission_grant import PermissionGrant as PermissionGrant -from .member_role_param import MemberRoleParam as MemberRoleParam from .role_get_response import RoleGetResponse as RoleGetResponse from .member_list_params import MemberListParams as MemberListParams -from .role_list_response import RoleListResponse as RoleListResponse from .member_create_params import MemberCreateParams as MemberCreateParams from .member_delete_params import MemberDeleteParams as MemberDeleteParams from .member_list_response import MemberListResponse as MemberListResponse from .member_update_params import MemberUpdateParams as MemberUpdateParams +from .user_with_invite_code import UserWithInviteCode as UserWithInviteCode from .member_delete_response import MemberDeleteResponse as MemberDeleteResponse from .permission_grant_param import PermissionGrantParam as PermissionGrantParam -from .member_with_invite_code import MemberWithInviteCode as MemberWithInviteCode diff --git a/src/cloudflare/types/accounts/member_list_response.py b/src/cloudflare/types/accounts/member_list_response.py index ae7b932f3c0..5edc940927c 100644 --- a/src/cloudflare/types/accounts/member_list_response.py +++ b/src/cloudflare/types/accounts/member_list_response.py @@ -3,24 +3,10 @@ from typing import List, Optional from typing_extensions import Literal +from ..role import Role from ..._models import BaseModel -from ..user.tokens import Permission -__all__ = ["MemberListResponse", "Role"] - - -class Role(BaseModel): - id: str - """Role identifier tag.""" - - description: str - """Description of role's permissions.""" - - name: str - """Role Name.""" - - permissions: List[Permission] - """Access permissions for this User.""" +__all__ = ["MemberListResponse"] class MemberListResponse(BaseModel): diff --git a/src/cloudflare/types/accounts/member_role_param.py b/src/cloudflare/types/accounts/member_role_param.py deleted file mode 100644 index 70bce379300..00000000000 --- a/src/cloudflare/types/accounts/member_role_param.py +++ /dev/null @@ -1,12 +0,0 @@ -# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. - -from __future__ import annotations - -from typing_extensions import Required, TypedDict - -__all__ = ["MemberRoleParam"] - - -class MemberRoleParam(TypedDict, total=False): - id: Required[str] - """Role identifier tag.""" diff --git a/src/cloudflare/types/accounts/member_update_params.py b/src/cloudflare/types/accounts/member_update_params.py index fa8bc46954b..69867eb443e 100644 --- a/src/cloudflare/types/accounts/member_update_params.py +++ b/src/cloudflare/types/accounts/member_update_params.py @@ -5,13 +5,16 @@ from typing import Iterable from typing_extensions import Required, TypedDict -from .member_role_param import MemberRoleParam - -__all__ = ["MemberUpdateParams"] +__all__ = ["MemberUpdateParams", "Role"] class MemberUpdateParams(TypedDict, total=False): account_id: Required[object] - roles: Required[Iterable[MemberRoleParam]] + roles: Required[Iterable[Role]] """Roles assigned to this member.""" + + +class Role(TypedDict, total=False): + id: Required[str] + """Role identifier tag.""" diff --git a/src/cloudflare/types/accounts/member_with_invite_code.py b/src/cloudflare/types/accounts/member_with_invite_code.py deleted file mode 100644 index 7584f6b2c26..00000000000 --- a/src/cloudflare/types/accounts/member_with_invite_code.py +++ /dev/null @@ -1,43 +0,0 @@ -# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. - -from typing import List, Optional - -from ..._models import BaseModel -from .member_role import MemberRole - -__all__ = ["MemberWithInviteCode", "User"] - - -class User(BaseModel): - email: str - """The contact email address of the user.""" - - id: Optional[str] = None - """Identifier""" - - first_name: Optional[str] = None - """User's first name""" - - last_name: Optional[str] = None - """User's last name""" - - two_factor_authentication_enabled: Optional[bool] = None - """Indicates whether two-factor authentication is enabled for the user account. - - Does not apply to API authentication. - """ - - -class MemberWithInviteCode(BaseModel): - id: str - """Membership identifier tag.""" - - roles: List[MemberRole] - """Roles assigned to this member.""" - - status: object - - user: User - - code: Optional[str] = None - """The unique activation code for the account membership.""" diff --git a/src/cloudflare/types/accounts/user_with_invite_code.py b/src/cloudflare/types/accounts/user_with_invite_code.py new file mode 100644 index 00000000000..4d121d69f1f --- /dev/null +++ b/src/cloudflare/types/accounts/user_with_invite_code.py @@ -0,0 +1,82 @@ +# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. + +from typing import List, Optional + +from ..._models import BaseModel +from .permission_grant import PermissionGrant + +__all__ = ["UserWithInviteCode", "Role", "RolePermissions", "User"] + + +class RolePermissions(BaseModel): + analytics: Optional[PermissionGrant] = None + + billing: Optional[PermissionGrant] = None + + cache_purge: Optional[PermissionGrant] = None + + dns: Optional[PermissionGrant] = None + + dns_records: Optional[PermissionGrant] = None + + lb: Optional[PermissionGrant] = None + + logs: Optional[PermissionGrant] = None + + organization: Optional[PermissionGrant] = None + + ssl: Optional[PermissionGrant] = None + + waf: Optional[PermissionGrant] = None + + zone_settings: Optional[PermissionGrant] = None + + zones: Optional[PermissionGrant] = None + + +class Role(BaseModel): + id: str + """Role identifier tag.""" + + description: str + """Description of role's permissions.""" + + name: str + """Role name.""" + + permissions: RolePermissions + + +class User(BaseModel): + email: str + """The contact email address of the user.""" + + id: Optional[str] = None + """Identifier""" + + first_name: Optional[str] = None + """User's first name""" + + last_name: Optional[str] = None + """User's last name""" + + two_factor_authentication_enabled: Optional[bool] = None + """Indicates whether two-factor authentication is enabled for the user account. + + Does not apply to API authentication. + """ + + +class UserWithInviteCode(BaseModel): + id: str + """Membership identifier tag.""" + + roles: List[Role] + """Roles assigned to this member.""" + + status: object + + user: User + + code: Optional[str] = None + """The unique activation code for the account membership.""" diff --git a/src/cloudflare/types/accounts/role_list_response.py b/src/cloudflare/types/role.py similarity index 71% rename from src/cloudflare/types/accounts/role_list_response.py rename to src/cloudflare/types/role.py index a2ed62ad78b..ff30e675f69 100644 --- a/src/cloudflare/types/accounts/role_list_response.py +++ b/src/cloudflare/types/role.py @@ -2,13 +2,13 @@ from typing import List -from ..._models import BaseModel -from ..user.tokens import Permission +from .._models import BaseModel +from .user.tokens import Permission -__all__ = ["RoleListResponse"] +__all__ = ["Role"] -class RoleListResponse(BaseModel): +class Role(BaseModel): id: str """Role identifier tag.""" diff --git a/src/cloudflare/types/shared/__init__.py b/src/cloudflare/types/shared/__init__.py index 5ff5f4f0c0c..aed721f25f7 100644 --- a/src/cloudflare/types/shared/__init__.py +++ b/src/cloudflare/types/shared/__init__.py @@ -1,6 +1,5 @@ # File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. -from .user import User as User from .result import Result as Result from .audit_log import AuditLog as AuditLog from .error_data import ErrorData as ErrorData diff --git a/src/cloudflare/types/shared/user.py b/src/cloudflare/types/shared/user.py deleted file mode 100644 index 94dc38fde36..00000000000 --- a/src/cloudflare/types/shared/user.py +++ /dev/null @@ -1,20 +0,0 @@ -# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. - -from typing import List - -from ..._models import BaseModel -from ..accounts import MemberRole - -__all__ = ["User"] - - -class User(BaseModel): - id: str - """Membership identifier tag.""" - - roles: List[MemberRole] - """Roles assigned to this member.""" - - status: object - - user: User diff --git a/src/cloudflare/types/accounts/member_role.py b/src/cloudflare/types/user.py similarity index 65% rename from src/cloudflare/types/accounts/member_role.py rename to src/cloudflare/types/user.py index fd4e70fa932..5224ee9c5e5 100644 --- a/src/cloudflare/types/accounts/member_role.py +++ b/src/cloudflare/types/user.py @@ -1,14 +1,14 @@ # File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. -from typing import Optional +from typing import List, Optional -from ..._models import BaseModel -from .permission_grant import PermissionGrant +from .._models import BaseModel +from .accounts import PermissionGrant -__all__ = ["MemberRole", "Permissions"] +__all__ = ["User", "Role", "RolePermissions"] -class Permissions(BaseModel): +class RolePermissions(BaseModel): analytics: Optional[PermissionGrant] = None billing: Optional[PermissionGrant] = None @@ -34,7 +34,7 @@ class Permissions(BaseModel): zones: Optional[PermissionGrant] = None -class MemberRole(BaseModel): +class Role(BaseModel): id: str """Role identifier tag.""" @@ -44,4 +44,16 @@ class MemberRole(BaseModel): name: str """Role name.""" - permissions: Permissions + permissions: RolePermissions + + +class User(BaseModel): + id: str + """Membership identifier tag.""" + + roles: List[Role] + """Roles assigned to this member.""" + + status: object + + user: User diff --git a/src/cloudflare/types/user/invite.py b/src/cloudflare/types/user/invite.py index fe493799a7a..4177387f9c7 100644 --- a/src/cloudflare/types/user/invite.py +++ b/src/cloudflare/types/user/invite.py @@ -4,24 +4,10 @@ from datetime import datetime from typing_extensions import Literal -from .tokens import Permission +from ..role import Role from ..._models import BaseModel -__all__ = ["Invite", "Role"] - - -class Role(BaseModel): - id: str - """Role identifier tag.""" - - description: str - """Description of role's permissions.""" - - name: str - """Role Name.""" - - permissions: List[Permission] - """Access permissions for this User.""" +__all__ = ["Invite"] class Invite(BaseModel): diff --git a/tests/api_resources/accounts/test_members.py b/tests/api_resources/accounts/test_members.py index bfb36a0055b..f340ce21f73 100644 --- a/tests/api_resources/accounts/test_members.py +++ b/tests/api_resources/accounts/test_members.py @@ -9,12 +9,12 @@ from cloudflare import Cloudflare, AsyncCloudflare from tests.utils import assert_matches_type +from cloudflare.types import User from cloudflare.pagination import SyncV4PagePaginationArray, AsyncV4PagePaginationArray -from cloudflare.types.shared import User from cloudflare.types.accounts import ( MemberListResponse, + UserWithInviteCode, MemberDeleteResponse, - MemberWithInviteCode, ) base_url = os.environ.get("TEST_API_BASE_URL", "http://127.0.0.1:4010") @@ -35,7 +35,7 @@ def test_method_create(self, client: Cloudflare) -> None: "3536bcfad5faccb999b47003c79917fb", ], ) - assert_matches_type(MemberWithInviteCode, member, path=["response"]) + assert_matches_type(UserWithInviteCode, member, path=["response"]) @pytest.mark.skip() @parametrize @@ -50,7 +50,7 @@ def test_method_create_with_all_params(self, client: Cloudflare) -> None: ], status="accepted", ) - assert_matches_type(MemberWithInviteCode, member, path=["response"]) + assert_matches_type(UserWithInviteCode, member, path=["response"]) @pytest.mark.skip() @parametrize @@ -68,7 +68,7 @@ def test_raw_response_create(self, client: Cloudflare) -> None: assert response.is_closed is True assert response.http_request.headers.get("X-Stainless-Lang") == "python" member = response.parse() - assert_matches_type(MemberWithInviteCode, member, path=["response"]) + assert_matches_type(UserWithInviteCode, member, path=["response"]) @pytest.mark.skip() @parametrize @@ -86,7 +86,7 @@ def test_streaming_response_create(self, client: Cloudflare) -> None: assert response.http_request.headers.get("X-Stainless-Lang") == "python" member = response.parse() - assert_matches_type(MemberWithInviteCode, member, path=["response"]) + assert_matches_type(UserWithInviteCode, member, path=["response"]) assert cast(Any, response.is_closed) is True @@ -315,7 +315,7 @@ async def test_method_create(self, async_client: AsyncCloudflare) -> None: "3536bcfad5faccb999b47003c79917fb", ], ) - assert_matches_type(MemberWithInviteCode, member, path=["response"]) + assert_matches_type(UserWithInviteCode, member, path=["response"]) @pytest.mark.skip() @parametrize @@ -330,7 +330,7 @@ async def test_method_create_with_all_params(self, async_client: AsyncCloudflare ], status="accepted", ) - assert_matches_type(MemberWithInviteCode, member, path=["response"]) + assert_matches_type(UserWithInviteCode, member, path=["response"]) @pytest.mark.skip() @parametrize @@ -348,7 +348,7 @@ async def test_raw_response_create(self, async_client: AsyncCloudflare) -> None: assert response.is_closed is True assert response.http_request.headers.get("X-Stainless-Lang") == "python" member = await response.parse() - assert_matches_type(MemberWithInviteCode, member, path=["response"]) + assert_matches_type(UserWithInviteCode, member, path=["response"]) @pytest.mark.skip() @parametrize @@ -366,7 +366,7 @@ async def test_streaming_response_create(self, async_client: AsyncCloudflare) -> assert response.http_request.headers.get("X-Stainless-Lang") == "python" member = await response.parse() - assert_matches_type(MemberWithInviteCode, member, path=["response"]) + assert_matches_type(UserWithInviteCode, member, path=["response"]) assert cast(Any, response.is_closed) is True diff --git a/tests/api_resources/accounts/test_roles.py b/tests/api_resources/accounts/test_roles.py index 2cbdcfab4c5..fcb935fa3f4 100644 --- a/tests/api_resources/accounts/test_roles.py +++ b/tests/api_resources/accounts/test_roles.py @@ -9,8 +9,9 @@ from cloudflare import Cloudflare, AsyncCloudflare from tests.utils import assert_matches_type +from cloudflare.types import Role from cloudflare.pagination import SyncSinglePage, AsyncSinglePage -from cloudflare.types.accounts import RoleGetResponse, RoleListResponse +from cloudflare.types.accounts import RoleGetResponse base_url = os.environ.get("TEST_API_BASE_URL", "http://127.0.0.1:4010") @@ -24,7 +25,7 @@ def test_method_list(self, client: Cloudflare) -> None: role = client.accounts.roles.list( account_id={}, ) - assert_matches_type(SyncSinglePage[RoleListResponse], role, path=["response"]) + assert_matches_type(SyncSinglePage[Role], role, path=["response"]) @pytest.mark.skip() @parametrize @@ -36,7 +37,7 @@ def test_raw_response_list(self, client: Cloudflare) -> None: assert response.is_closed is True assert response.http_request.headers.get("X-Stainless-Lang") == "python" role = response.parse() - assert_matches_type(SyncSinglePage[RoleListResponse], role, path=["response"]) + assert_matches_type(SyncSinglePage[Role], role, path=["response"]) @pytest.mark.skip() @parametrize @@ -48,7 +49,7 @@ def test_streaming_response_list(self, client: Cloudflare) -> None: assert response.http_request.headers.get("X-Stainless-Lang") == "python" role = response.parse() - assert_matches_type(SyncSinglePage[RoleListResponse], role, path=["response"]) + assert_matches_type(SyncSinglePage[Role], role, path=["response"]) assert cast(Any, response.is_closed) is True @@ -99,7 +100,7 @@ async def test_method_list(self, async_client: AsyncCloudflare) -> None: role = await async_client.accounts.roles.list( account_id={}, ) - assert_matches_type(AsyncSinglePage[RoleListResponse], role, path=["response"]) + assert_matches_type(AsyncSinglePage[Role], role, path=["response"]) @pytest.mark.skip() @parametrize @@ -111,7 +112,7 @@ async def test_raw_response_list(self, async_client: AsyncCloudflare) -> None: assert response.is_closed is True assert response.http_request.headers.get("X-Stainless-Lang") == "python" role = await response.parse() - assert_matches_type(AsyncSinglePage[RoleListResponse], role, path=["response"]) + assert_matches_type(AsyncSinglePage[Role], role, path=["response"]) @pytest.mark.skip() @parametrize @@ -123,7 +124,7 @@ async def test_streaming_response_list(self, async_client: AsyncCloudflare) -> N assert response.http_request.headers.get("X-Stainless-Lang") == "python" role = await response.parse() - assert_matches_type(AsyncSinglePage[RoleListResponse], role, path=["response"]) + assert_matches_type(AsyncSinglePage[Role], role, path=["response"]) assert cast(Any, response.is_closed) is True