# This file was auto-generated by Fern from our API Definition.

import typing
from ...core.client_wrapper import SyncClientWrapper
from .raw_client import RawCustomAttributesClient
from ...requests.bulk_delete_location_custom_attributes_request_location_custom_attribute_delete_request import (
    BulkDeleteLocationCustomAttributesRequestLocationCustomAttributeDeleteRequestParams,
)
from ...core.request_options import RequestOptions
from ...types.bulk_delete_location_custom_attributes_response import BulkDeleteLocationCustomAttributesResponse
from ...requests.bulk_upsert_location_custom_attributes_request_location_custom_attribute_upsert_request import (
    BulkUpsertLocationCustomAttributesRequestLocationCustomAttributeUpsertRequestParams,
)
from ...types.bulk_upsert_location_custom_attributes_response import BulkUpsertLocationCustomAttributesResponse
from ...types.visibility_filter import VisibilityFilter
from ...core.pagination import SyncPager
from ...types.custom_attribute import CustomAttribute
from ...core.jsonable_encoder import jsonable_encoder
from ...types.list_location_custom_attributes_response import ListLocationCustomAttributesResponse
from ...core.unchecked_base_model import construct_type
from json.decoder import JSONDecodeError
from ...core.api_error import ApiError
from ...types.retrieve_location_custom_attribute_response import RetrieveLocationCustomAttributeResponse
from ...requests.custom_attribute import CustomAttributeParams
from ...types.upsert_location_custom_attribute_response import UpsertLocationCustomAttributeResponse
from ...types.delete_location_custom_attribute_response import DeleteLocationCustomAttributeResponse
from ...core.client_wrapper import AsyncClientWrapper
from .raw_client import AsyncRawCustomAttributesClient
from ...core.pagination import AsyncPager

# this is used as the default value for optional parameters
OMIT = typing.cast(typing.Any, ...)


class CustomAttributesClient:
    def __init__(self, *, client_wrapper: SyncClientWrapper):
        self._raw_client = RawCustomAttributesClient(client_wrapper=client_wrapper)

    @property
    def with_raw_response(self) -> RawCustomAttributesClient:
        """
        Retrieves a raw implementation of this client that returns raw responses.

        Returns
        -------
        RawCustomAttributesClient
        """
        return self._raw_client

    def batch_delete(
        self,
        *,
        values: typing.Dict[str, BulkDeleteLocationCustomAttributesRequestLocationCustomAttributeDeleteRequestParams],
        request_options: typing.Optional[RequestOptions] = None,
    ) -> BulkDeleteLocationCustomAttributesResponse:
        """
        Deletes [custom attributes](entity:CustomAttribute) for locations as a bulk operation.
        To delete a custom attribute owned by another application, the `visibility` setting must be
        `VISIBILITY_READ_WRITE_VALUES`.

        Parameters
        ----------
        values : typing.Dict[str, BulkDeleteLocationCustomAttributesRequestLocationCustomAttributeDeleteRequestParams]
            The data used to update the `CustomAttribute` objects.
            The keys must be unique and are used to map to the corresponding response.

        request_options : typing.Optional[RequestOptions]
            Request-specific configuration.

        Returns
        -------
        BulkDeleteLocationCustomAttributesResponse
            Success

        Examples
        --------
        from square import Square

        client = Square(
            token="YOUR_TOKEN",
        )
        client.locations.custom_attributes.batch_delete(
            values={
                "id1": {"key": "bestseller"},
                "id2": {"key": "bestseller"},
                "id3": {"key": "phone-number"},
            },
        )
        """
        response = self._raw_client.batch_delete(values=values, request_options=request_options)
        return response.data

    def batch_upsert(
        self,
        *,
        values: typing.Dict[str, BulkUpsertLocationCustomAttributesRequestLocationCustomAttributeUpsertRequestParams],
        request_options: typing.Optional[RequestOptions] = None,
    ) -> BulkUpsertLocationCustomAttributesResponse:
        """
        Creates or updates [custom attributes](entity:CustomAttribute) for locations as a bulk operation.
        Use this endpoint to set the value of one or more custom attributes for one or more locations.
        A custom attribute is based on a custom attribute definition in a Square seller account, which is
        created using the [CreateLocationCustomAttributeDefinition](api-endpoint:LocationCustomAttributes-CreateLocationCustomAttributeDefinition) endpoint.
        This `BulkUpsertLocationCustomAttributes` endpoint accepts a map of 1 to 25 individual upsert
        requests and returns a map of individual upsert responses. Each upsert request has a unique ID
        and provides a location ID and custom attribute. Each upsert response is returned with the ID
        of the corresponding request.
        To create or update a custom attribute owned by another application, the `visibility` setting
        must be `VISIBILITY_READ_WRITE_VALUES`.

        Parameters
        ----------
        values : typing.Dict[str, BulkUpsertLocationCustomAttributesRequestLocationCustomAttributeUpsertRequestParams]
            A map containing 1 to 25 individual upsert requests. For each request, provide an
            arbitrary ID that is unique for this `BulkUpsertLocationCustomAttributes` request and the
            information needed to create or update a custom attribute.

        request_options : typing.Optional[RequestOptions]
            Request-specific configuration.

        Returns
        -------
        BulkUpsertLocationCustomAttributesResponse
            Success

        Examples
        --------
        from square import Square

        client = Square(
            token="YOUR_TOKEN",
        )
        client.locations.custom_attributes.batch_upsert(
            values={
                "id1": {
                    "location_id": "L0TBCBTB7P8RQ",
                    "custom_attribute": {"key": "bestseller", "value": "hot cocoa"},
                },
                "id2": {
                    "location_id": "L9XMD04V3STJX",
                    "custom_attribute": {
                        "key": "bestseller",
                        "value": "berry smoothie",
                    },
                },
                "id3": {
                    "location_id": "L0TBCBTB7P8RQ",
                    "custom_attribute": {
                        "key": "phone-number",
                        "value": "+12223334444",
                    },
                },
            },
        )
        """
        response = self._raw_client.batch_upsert(values=values, request_options=request_options)
        return response.data

    def list(
        self,
        location_id: str,
        *,
        visibility_filter: typing.Optional[VisibilityFilter] = None,
        limit: typing.Optional[int] = None,
        cursor: typing.Optional[str] = None,
        with_definitions: typing.Optional[bool] = None,
        request_options: typing.Optional[RequestOptions] = None,
    ) -> SyncPager[CustomAttribute]:
        """
        Lists the [custom attributes](entity:CustomAttribute) associated with a location.
        You can use the `with_definitions` query parameter to also retrieve custom attribute definitions
        in the same call.
        When all response pages are retrieved, the results include all custom attributes that are
        visible to the requesting application, including those that are owned by other applications
        and set to `VISIBILITY_READ_ONLY` or `VISIBILITY_READ_WRITE_VALUES`.

        Parameters
        ----------
        location_id : str
            The ID of the target [location](entity:Location).

        visibility_filter : typing.Optional[VisibilityFilter]
            Filters the `CustomAttributeDefinition` results by their `visibility` values.

        limit : typing.Optional[int]
            The maximum number of results to return in a single paged response. This limit is advisory.
            The response might contain more or fewer results. The minimum value is 1 and the maximum value is 100.
            The default value is 20. For more information, see [Pagination](https://developer.squareup.com/docs/build-basics/common-api-patterns/pagination).

        cursor : typing.Optional[str]
            The cursor returned in the paged response from the previous call to this endpoint.
            Provide this cursor to retrieve the next page of results for your original request. For more
            information, see [Pagination](https://developer.squareup.com/docs/build-basics/common-api-patterns/pagination).

        with_definitions : typing.Optional[bool]
            Indicates whether to return the [custom attribute definition](entity:CustomAttributeDefinition) in the `definition` field of each
            custom attribute. Set this parameter to `true` to get the name and description of each custom
            attribute, information about the data type, or other definition details. The default value is `false`.

        request_options : typing.Optional[RequestOptions]
            Request-specific configuration.

        Returns
        -------
        SyncPager[CustomAttribute]
            Success

        Examples
        --------
        from square import Square

        client = Square(
            token="YOUR_TOKEN",
        )
        response = client.locations.custom_attributes.list(
            location_id="location_id",
        )
        for item in response:
            yield item
        # alternatively, you can paginate page-by-page
        for page in response.iter_pages():
            yield page
        """
        _response = self._raw_client._client_wrapper.httpx_client.request(
            f"v2/locations/{jsonable_encoder(location_id)}/custom-attributes",
            method="GET",
            params={
                "visibility_filter": visibility_filter,
                "limit": limit,
                "cursor": cursor,
                "with_definitions": with_definitions,
            },
            request_options=request_options,
        )
        try:
            if 200 <= _response.status_code < 300:
                _parsed_response = typing.cast(
                    ListLocationCustomAttributesResponse,
                    construct_type(
                        type_=ListLocationCustomAttributesResponse,  # type: ignore
                        object_=_response.json(),
                    ),
                )
                _parsed_next = _parsed_response.cursor
                _has_next = _parsed_next is not None and _parsed_next != ""
                _get_next = lambda: self.list(
                    location_id,
                    visibility_filter=visibility_filter,
                    limit=limit,
                    cursor=_parsed_next,
                    with_definitions=with_definitions,
                    request_options=request_options,
                )
                _items = _parsed_response.custom_attributes
                return SyncPager(has_next=_has_next, items=_items, get_next=_get_next)
            _response_json = _response.json()
        except JSONDecodeError:
            raise ApiError(status_code=_response.status_code, body=_response.text)
        raise ApiError(status_code=_response.status_code, body=_response_json)

    def get(
        self,
        location_id: str,
        key: str,
        *,
        with_definition: typing.Optional[bool] = None,
        version: typing.Optional[int] = None,
        request_options: typing.Optional[RequestOptions] = None,
    ) -> RetrieveLocationCustomAttributeResponse:
        """
        Retrieves a [custom attribute](entity:CustomAttribute) associated with a location.
        You can use the `with_definition` query parameter to also retrieve the custom attribute definition
        in the same call.
        To retrieve a custom attribute owned by another application, the `visibility` setting must be
        `VISIBILITY_READ_ONLY` or `VISIBILITY_READ_WRITE_VALUES`.

        Parameters
        ----------
        location_id : str
            The ID of the target [location](entity:Location).

        key : str
            The key of the custom attribute to retrieve. This key must match the `key` of a custom
            attribute definition in the Square seller account. If the requesting application is not the
            definition owner, you must use the qualified key.

        with_definition : typing.Optional[bool]
            Indicates whether to return the [custom attribute definition](entity:CustomAttributeDefinition) in the `definition` field of
            the custom attribute. Set this parameter to `true` to get the name and description of the custom
            attribute, information about the data type, or other definition details. The default value is `false`.

        version : typing.Optional[int]
            The current version of the custom attribute, which is used for strongly consistent reads to
            guarantee that you receive the most up-to-date data. When included in the request, Square
            returns the specified version or a higher version if one exists. If the specified version is
            higher than the current version, Square returns a `BAD_REQUEST` error.

        request_options : typing.Optional[RequestOptions]
            Request-specific configuration.

        Returns
        -------
        RetrieveLocationCustomAttributeResponse
            Success

        Examples
        --------
        from square import Square

        client = Square(
            token="YOUR_TOKEN",
        )
        client.locations.custom_attributes.get(
            location_id="location_id",
            key="key",
        )
        """
        response = self._raw_client.get(
            location_id, key, with_definition=with_definition, version=version, request_options=request_options
        )
        return response.data

    def upsert(
        self,
        location_id: str,
        key: str,
        *,
        custom_attribute: CustomAttributeParams,
        idempotency_key: typing.Optional[str] = OMIT,
        request_options: typing.Optional[RequestOptions] = None,
    ) -> UpsertLocationCustomAttributeResponse:
        """
        Creates or updates a [custom attribute](entity:CustomAttribute) for a location.
        Use this endpoint to set the value of a custom attribute for a specified location.
        A custom attribute is based on a custom attribute definition in a Square seller account, which
        is created using the [CreateLocationCustomAttributeDefinition](api-endpoint:LocationCustomAttributes-CreateLocationCustomAttributeDefinition) endpoint.
        To create or update a custom attribute owned by another application, the `visibility` setting
        must be `VISIBILITY_READ_WRITE_VALUES`.

        Parameters
        ----------
        location_id : str
            The ID of the target [location](entity:Location).

        key : str
            The key of the custom attribute to create or update. This key must match the `key` of a
            custom attribute definition in the Square seller account. If the requesting application is not
            the definition owner, you must use the qualified key.

        custom_attribute : CustomAttributeParams
            The custom attribute to create or update, with the following fields:
            - `value`. This value must conform to the `schema` specified by the definition.
            For more information, see [Supported data types](https://developer.squareup.com/docs/devtools/customattributes/overview#supported-data-types).
            - `version`. To enable [optimistic concurrency](https://developer.squareup.com/docs/build-basics/common-api-patterns/optimistic-concurrency)
            control for an update operation, include the current version of the custom attribute.
            If this is not important for your application, version can be set to -1.

        idempotency_key : typing.Optional[str]
            A unique identifier for this request, used to ensure idempotency. For more information,
            see [Idempotency](https://developer.squareup.com/docs/build-basics/common-api-patterns/idempotency).

        request_options : typing.Optional[RequestOptions]
            Request-specific configuration.

        Returns
        -------
        UpsertLocationCustomAttributeResponse
            Success

        Examples
        --------
        from square import Square

        client = Square(
            token="YOUR_TOKEN",
        )
        client.locations.custom_attributes.upsert(
            location_id="location_id",
            key="key",
            custom_attribute={"value": "hot cocoa"},
        )
        """
        response = self._raw_client.upsert(
            location_id,
            key,
            custom_attribute=custom_attribute,
            idempotency_key=idempotency_key,
            request_options=request_options,
        )
        return response.data

    def delete(
        self, location_id: str, key: str, *, request_options: typing.Optional[RequestOptions] = None
    ) -> DeleteLocationCustomAttributeResponse:
        """
        Deletes a [custom attribute](entity:CustomAttribute) associated with a location.
        To delete a custom attribute owned by another application, the `visibility` setting must be
        `VISIBILITY_READ_WRITE_VALUES`.

        Parameters
        ----------
        location_id : str
            The ID of the target [location](entity:Location).

        key : str
            The key of the custom attribute to delete. This key must match the `key` of a custom
            attribute definition in the Square seller account. If the requesting application is not the
            definition owner, you must use the qualified key.

        request_options : typing.Optional[RequestOptions]
            Request-specific configuration.

        Returns
        -------
        DeleteLocationCustomAttributeResponse
            Success

        Examples
        --------
        from square import Square

        client = Square(
            token="YOUR_TOKEN",
        )
        client.locations.custom_attributes.delete(
            location_id="location_id",
            key="key",
        )
        """
        response = self._raw_client.delete(location_id, key, request_options=request_options)
        return response.data


class AsyncCustomAttributesClient:
    def __init__(self, *, client_wrapper: AsyncClientWrapper):
        self._raw_client = AsyncRawCustomAttributesClient(client_wrapper=client_wrapper)

    @property
    def with_raw_response(self) -> AsyncRawCustomAttributesClient:
        """
        Retrieves a raw implementation of this client that returns raw responses.

        Returns
        -------
        AsyncRawCustomAttributesClient
        """
        return self._raw_client

    async def batch_delete(
        self,
        *,
        values: typing.Dict[str, BulkDeleteLocationCustomAttributesRequestLocationCustomAttributeDeleteRequestParams],
        request_options: typing.Optional[RequestOptions] = None,
    ) -> BulkDeleteLocationCustomAttributesResponse:
        """
        Deletes [custom attributes](entity:CustomAttribute) for locations as a bulk operation.
        To delete a custom attribute owned by another application, the `visibility` setting must be
        `VISIBILITY_READ_WRITE_VALUES`.

        Parameters
        ----------
        values : typing.Dict[str, BulkDeleteLocationCustomAttributesRequestLocationCustomAttributeDeleteRequestParams]
            The data used to update the `CustomAttribute` objects.
            The keys must be unique and are used to map to the corresponding response.

        request_options : typing.Optional[RequestOptions]
            Request-specific configuration.

        Returns
        -------
        BulkDeleteLocationCustomAttributesResponse
            Success

        Examples
        --------
        import asyncio

        from square import AsyncSquare

        client = AsyncSquare(
            token="YOUR_TOKEN",
        )


        async def main() -> None:
            await client.locations.custom_attributes.batch_delete(
                values={
                    "id1": {"key": "bestseller"},
                    "id2": {"key": "bestseller"},
                    "id3": {"key": "phone-number"},
                },
            )


        asyncio.run(main())
        """
        response = await self._raw_client.batch_delete(values=values, request_options=request_options)
        return response.data

    async def batch_upsert(
        self,
        *,
        values: typing.Dict[str, BulkUpsertLocationCustomAttributesRequestLocationCustomAttributeUpsertRequestParams],
        request_options: typing.Optional[RequestOptions] = None,
    ) -> BulkUpsertLocationCustomAttributesResponse:
        """
        Creates or updates [custom attributes](entity:CustomAttribute) for locations as a bulk operation.
        Use this endpoint to set the value of one or more custom attributes for one or more locations.
        A custom attribute is based on a custom attribute definition in a Square seller account, which is
        created using the [CreateLocationCustomAttributeDefinition](api-endpoint:LocationCustomAttributes-CreateLocationCustomAttributeDefinition) endpoint.
        This `BulkUpsertLocationCustomAttributes` endpoint accepts a map of 1 to 25 individual upsert
        requests and returns a map of individual upsert responses. Each upsert request has a unique ID
        and provides a location ID and custom attribute. Each upsert response is returned with the ID
        of the corresponding request.
        To create or update a custom attribute owned by another application, the `visibility` setting
        must be `VISIBILITY_READ_WRITE_VALUES`.

        Parameters
        ----------
        values : typing.Dict[str, BulkUpsertLocationCustomAttributesRequestLocationCustomAttributeUpsertRequestParams]
            A map containing 1 to 25 individual upsert requests. For each request, provide an
            arbitrary ID that is unique for this `BulkUpsertLocationCustomAttributes` request and the
            information needed to create or update a custom attribute.

        request_options : typing.Optional[RequestOptions]
            Request-specific configuration.

        Returns
        -------
        BulkUpsertLocationCustomAttributesResponse
            Success

        Examples
        --------
        import asyncio

        from square import AsyncSquare

        client = AsyncSquare(
            token="YOUR_TOKEN",
        )


        async def main() -> None:
            await client.locations.custom_attributes.batch_upsert(
                values={
                    "id1": {
                        "location_id": "L0TBCBTB7P8RQ",
                        "custom_attribute": {"key": "bestseller", "value": "hot cocoa"},
                    },
                    "id2": {
                        "location_id": "L9XMD04V3STJX",
                        "custom_attribute": {
                            "key": "bestseller",
                            "value": "berry smoothie",
                        },
                    },
                    "id3": {
                        "location_id": "L0TBCBTB7P8RQ",
                        "custom_attribute": {
                            "key": "phone-number",
                            "value": "+12223334444",
                        },
                    },
                },
            )


        asyncio.run(main())
        """
        response = await self._raw_client.batch_upsert(values=values, request_options=request_options)
        return response.data

    async def list(
        self,
        location_id: str,
        *,
        visibility_filter: typing.Optional[VisibilityFilter] = None,
        limit: typing.Optional[int] = None,
        cursor: typing.Optional[str] = None,
        with_definitions: typing.Optional[bool] = None,
        request_options: typing.Optional[RequestOptions] = None,
    ) -> AsyncPager[CustomAttribute]:
        """
        Lists the [custom attributes](entity:CustomAttribute) associated with a location.
        You can use the `with_definitions` query parameter to also retrieve custom attribute definitions
        in the same call.
        When all response pages are retrieved, the results include all custom attributes that are
        visible to the requesting application, including those that are owned by other applications
        and set to `VISIBILITY_READ_ONLY` or `VISIBILITY_READ_WRITE_VALUES`.

        Parameters
        ----------
        location_id : str
            The ID of the target [location](entity:Location).

        visibility_filter : typing.Optional[VisibilityFilter]
            Filters the `CustomAttributeDefinition` results by their `visibility` values.

        limit : typing.Optional[int]
            The maximum number of results to return in a single paged response. This limit is advisory.
            The response might contain more or fewer results. The minimum value is 1 and the maximum value is 100.
            The default value is 20. For more information, see [Pagination](https://developer.squareup.com/docs/build-basics/common-api-patterns/pagination).

        cursor : typing.Optional[str]
            The cursor returned in the paged response from the previous call to this endpoint.
            Provide this cursor to retrieve the next page of results for your original request. For more
            information, see [Pagination](https://developer.squareup.com/docs/build-basics/common-api-patterns/pagination).

        with_definitions : typing.Optional[bool]
            Indicates whether to return the [custom attribute definition](entity:CustomAttributeDefinition) in the `definition` field of each
            custom attribute. Set this parameter to `true` to get the name and description of each custom
            attribute, information about the data type, or other definition details. The default value is `false`.

        request_options : typing.Optional[RequestOptions]
            Request-specific configuration.

        Returns
        -------
        AsyncPager[CustomAttribute]
            Success

        Examples
        --------
        import asyncio

        from square import AsyncSquare

        client = AsyncSquare(
            token="YOUR_TOKEN",
        )


        async def main() -> None:
            response = await client.locations.custom_attributes.list(
                location_id="location_id",
            )
            async for item in response:
                yield item
            # alternatively, you can paginate page-by-page
            async for page in response.iter_pages():
                yield page


        asyncio.run(main())
        """
        _response = await self._raw_client._client_wrapper.httpx_client.request(
            f"v2/locations/{jsonable_encoder(location_id)}/custom-attributes",
            method="GET",
            params={
                "visibility_filter": visibility_filter,
                "limit": limit,
                "cursor": cursor,
                "with_definitions": with_definitions,
            },
            request_options=request_options,
        )
        try:
            if 200 <= _response.status_code < 300:
                _parsed_response = typing.cast(
                    ListLocationCustomAttributesResponse,
                    construct_type(
                        type_=ListLocationCustomAttributesResponse,  # type: ignore
                        object_=_response.json(),
                    ),
                )
                _parsed_next = _parsed_response.cursor
                _has_next = _parsed_next is not None and _parsed_next != ""
                _get_next = lambda: self.list(
                    location_id,
                    visibility_filter=visibility_filter,
                    limit=limit,
                    cursor=_parsed_next,
                    with_definitions=with_definitions,
                    request_options=request_options,
                )
                _items = _parsed_response.custom_attributes
                return AsyncPager(has_next=_has_next, items=_items, get_next=_get_next)
            _response_json = _response.json()
        except JSONDecodeError:
            raise ApiError(status_code=_response.status_code, body=_response.text)
        raise ApiError(status_code=_response.status_code, body=_response_json)

    async def get(
        self,
        location_id: str,
        key: str,
        *,
        with_definition: typing.Optional[bool] = None,
        version: typing.Optional[int] = None,
        request_options: typing.Optional[RequestOptions] = None,
    ) -> RetrieveLocationCustomAttributeResponse:
        """
        Retrieves a [custom attribute](entity:CustomAttribute) associated with a location.
        You can use the `with_definition` query parameter to also retrieve the custom attribute definition
        in the same call.
        To retrieve a custom attribute owned by another application, the `visibility` setting must be
        `VISIBILITY_READ_ONLY` or `VISIBILITY_READ_WRITE_VALUES`.

        Parameters
        ----------
        location_id : str
            The ID of the target [location](entity:Location).

        key : str
            The key of the custom attribute to retrieve. This key must match the `key` of a custom
            attribute definition in the Square seller account. If the requesting application is not the
            definition owner, you must use the qualified key.

        with_definition : typing.Optional[bool]
            Indicates whether to return the [custom attribute definition](entity:CustomAttributeDefinition) in the `definition` field of
            the custom attribute. Set this parameter to `true` to get the name and description of the custom
            attribute, information about the data type, or other definition details. The default value is `false`.

        version : typing.Optional[int]
            The current version of the custom attribute, which is used for strongly consistent reads to
            guarantee that you receive the most up-to-date data. When included in the request, Square
            returns the specified version or a higher version if one exists. If the specified version is
            higher than the current version, Square returns a `BAD_REQUEST` error.

        request_options : typing.Optional[RequestOptions]
            Request-specific configuration.

        Returns
        -------
        RetrieveLocationCustomAttributeResponse
            Success

        Examples
        --------
        import asyncio

        from square import AsyncSquare

        client = AsyncSquare(
            token="YOUR_TOKEN",
        )


        async def main() -> None:
            await client.locations.custom_attributes.get(
                location_id="location_id",
                key="key",
            )


        asyncio.run(main())
        """
        response = await self._raw_client.get(
            location_id, key, with_definition=with_definition, version=version, request_options=request_options
        )
        return response.data

    async def upsert(
        self,
        location_id: str,
        key: str,
        *,
        custom_attribute: CustomAttributeParams,
        idempotency_key: typing.Optional[str] = OMIT,
        request_options: typing.Optional[RequestOptions] = None,
    ) -> UpsertLocationCustomAttributeResponse:
        """
        Creates or updates a [custom attribute](entity:CustomAttribute) for a location.
        Use this endpoint to set the value of a custom attribute for a specified location.
        A custom attribute is based on a custom attribute definition in a Square seller account, which
        is created using the [CreateLocationCustomAttributeDefinition](api-endpoint:LocationCustomAttributes-CreateLocationCustomAttributeDefinition) endpoint.
        To create or update a custom attribute owned by another application, the `visibility` setting
        must be `VISIBILITY_READ_WRITE_VALUES`.

        Parameters
        ----------
        location_id : str
            The ID of the target [location](entity:Location).

        key : str
            The key of the custom attribute to create or update. This key must match the `key` of a
            custom attribute definition in the Square seller account. If the requesting application is not
            the definition owner, you must use the qualified key.

        custom_attribute : CustomAttributeParams
            The custom attribute to create or update, with the following fields:
            - `value`. This value must conform to the `schema` specified by the definition.
            For more information, see [Supported data types](https://developer.squareup.com/docs/devtools/customattributes/overview#supported-data-types).
            - `version`. To enable [optimistic concurrency](https://developer.squareup.com/docs/build-basics/common-api-patterns/optimistic-concurrency)
            control for an update operation, include the current version of the custom attribute.
            If this is not important for your application, version can be set to -1.

        idempotency_key : typing.Optional[str]
            A unique identifier for this request, used to ensure idempotency. For more information,
            see [Idempotency](https://developer.squareup.com/docs/build-basics/common-api-patterns/idempotency).

        request_options : typing.Optional[RequestOptions]
            Request-specific configuration.

        Returns
        -------
        UpsertLocationCustomAttributeResponse
            Success

        Examples
        --------
        import asyncio

        from square import AsyncSquare

        client = AsyncSquare(
            token="YOUR_TOKEN",
        )


        async def main() -> None:
            await client.locations.custom_attributes.upsert(
                location_id="location_id",
                key="key",
                custom_attribute={"value": "hot cocoa"},
            )


        asyncio.run(main())
        """
        response = await self._raw_client.upsert(
            location_id,
            key,
            custom_attribute=custom_attribute,
            idempotency_key=idempotency_key,
            request_options=request_options,
        )
        return response.data

    async def delete(
        self, location_id: str, key: str, *, request_options: typing.Optional[RequestOptions] = None
    ) -> DeleteLocationCustomAttributeResponse:
        """
        Deletes a [custom attribute](entity:CustomAttribute) associated with a location.
        To delete a custom attribute owned by another application, the `visibility` setting must be
        `VISIBILITY_READ_WRITE_VALUES`.

        Parameters
        ----------
        location_id : str
            The ID of the target [location](entity:Location).

        key : str
            The key of the custom attribute to delete. This key must match the `key` of a custom
            attribute definition in the Square seller account. If the requesting application is not the
            definition owner, you must use the qualified key.

        request_options : typing.Optional[RequestOptions]
            Request-specific configuration.

        Returns
        -------
        DeleteLocationCustomAttributeResponse
            Success

        Examples
        --------
        import asyncio

        from square import AsyncSquare

        client = AsyncSquare(
            token="YOUR_TOKEN",
        )


        async def main() -> None:
            await client.locations.custom_attributes.delete(
                location_id="location_id",
                key="key",
            )


        asyncio.run(main())
        """
        response = await self._raw_client.delete(location_id, key, request_options=request_options)
        return response.data
