# coding=utf-8
# --------------------------------------------------------------------------
# Copyright (c) Microsoft Corporation. All rights reserved.
# Licensed under the MIT License. See License.txt in the project root for license information.
# Code generated by Microsoft (R) AutoRest Code Generator.
# Changes may cause incorrect behavior and will be lost if the code is regenerated.
# --------------------------------------------------------------------------
import functools
from typing import Any, Callable, Dict, Generic, Iterable, Optional, TypeVar
import warnings

from azure.core.exceptions import ClientAuthenticationError, HttpResponseError, ResourceExistsError, ResourceNotFoundError, map_error
from azure.core.paging import ItemPaged
from azure.core.pipeline import PipelineResponse
from azure.core.pipeline.transport import HttpResponse
from azure.core.rest import HttpRequest
from azure.core.tracing.decorator import distributed_trace
from azure.mgmt.core.exceptions import ARMErrorFormat
from msrest import Serializer

from .. import models as _models
from .._vendor import _convert_request, _format_url_section
T = TypeVar('T')
JSONType = Any
ClsType = Optional[Callable[[PipelineResponse[HttpRequest, HttpResponse], T, Dict[str, Any]], Any]]

_SERIALIZER = Serializer()
_SERIALIZER.client_side_validation = False

def build_delete_request(
    scope: str,
    policy_assignment_name: str,
    **kwargs: Any
) -> HttpRequest:
    api_version = "2020-09-01"
    accept = "application/json"
    # Construct URL
    url = kwargs.pop("template_url", '/{scope}/providers/Microsoft.Authorization/policyAssignments/{policyAssignmentName}')
    path_format_arguments = {
        "scope": _SERIALIZER.url("scope", scope, 'str', skip_quote=True),
        "policyAssignmentName": _SERIALIZER.url("policy_assignment_name", policy_assignment_name, 'str'),
    }

    url = _format_url_section(url, **path_format_arguments)

    # Construct parameters
    query_parameters = kwargs.pop("params", {})  # type: Dict[str, Any]
    query_parameters['api-version'] = _SERIALIZER.query("api_version", api_version, 'str')

    # Construct headers
    header_parameters = kwargs.pop("headers", {})  # type: Dict[str, Any]
    header_parameters['Accept'] = _SERIALIZER.header("accept", accept, 'str')

    return HttpRequest(
        method="DELETE",
        url=url,
        params=query_parameters,
        headers=header_parameters,
        **kwargs
    )


def build_create_request(
    scope: str,
    policy_assignment_name: str,
    *,
    json: JSONType = None,
    content: Any = None,
    **kwargs: Any
) -> HttpRequest:
    content_type = kwargs.pop('content_type', None)  # type: Optional[str]

    api_version = "2020-09-01"
    accept = "application/json"
    # Construct URL
    url = kwargs.pop("template_url", '/{scope}/providers/Microsoft.Authorization/policyAssignments/{policyAssignmentName}')
    path_format_arguments = {
        "scope": _SERIALIZER.url("scope", scope, 'str', skip_quote=True),
        "policyAssignmentName": _SERIALIZER.url("policy_assignment_name", policy_assignment_name, 'str'),
    }

    url = _format_url_section(url, **path_format_arguments)

    # Construct parameters
    query_parameters = kwargs.pop("params", {})  # type: Dict[str, Any]
    query_parameters['api-version'] = _SERIALIZER.query("api_version", api_version, 'str')

    # Construct headers
    header_parameters = kwargs.pop("headers", {})  # type: Dict[str, Any]
    if content_type is not None:
        header_parameters['Content-Type'] = _SERIALIZER.header("content_type", content_type, 'str')
    header_parameters['Accept'] = _SERIALIZER.header("accept", accept, 'str')

    return HttpRequest(
        method="PUT",
        url=url,
        params=query_parameters,
        headers=header_parameters,
        json=json,
        content=content,
        **kwargs
    )


def build_get_request(
    scope: str,
    policy_assignment_name: str,
    **kwargs: Any
) -> HttpRequest:
    api_version = "2020-09-01"
    accept = "application/json"
    # Construct URL
    url = kwargs.pop("template_url", '/{scope}/providers/Microsoft.Authorization/policyAssignments/{policyAssignmentName}')
    path_format_arguments = {
        "scope": _SERIALIZER.url("scope", scope, 'str', skip_quote=True),
        "policyAssignmentName": _SERIALIZER.url("policy_assignment_name", policy_assignment_name, 'str'),
    }

    url = _format_url_section(url, **path_format_arguments)

    # Construct parameters
    query_parameters = kwargs.pop("params", {})  # type: Dict[str, Any]
    query_parameters['api-version'] = _SERIALIZER.query("api_version", api_version, 'str')

    # Construct headers
    header_parameters = kwargs.pop("headers", {})  # type: Dict[str, Any]
    header_parameters['Accept'] = _SERIALIZER.header("accept", accept, 'str')

    return HttpRequest(
        method="GET",
        url=url,
        params=query_parameters,
        headers=header_parameters,
        **kwargs
    )


def build_list_for_resource_group_request(
    resource_group_name: str,
    subscription_id: str,
    *,
    filter: Optional[str] = None,
    top: Optional[int] = None,
    **kwargs: Any
) -> HttpRequest:
    api_version = "2020-09-01"
    accept = "application/json"
    # Construct URL
    url = kwargs.pop("template_url", '/subscriptions/{subscriptionId}/resourceGroups/{resourceGroupName}/providers/Microsoft.Authorization/policyAssignments')
    path_format_arguments = {
        "resourceGroupName": _SERIALIZER.url("resource_group_name", resource_group_name, 'str', max_length=90, min_length=1, pattern=r'^[-\w\._\(\)]+$'),
        "subscriptionId": _SERIALIZER.url("subscription_id", subscription_id, 'str'),
    }

    url = _format_url_section(url, **path_format_arguments)

    # Construct parameters
    query_parameters = kwargs.pop("params", {})  # type: Dict[str, Any]
    if filter is not None:
        query_parameters['$filter'] = _SERIALIZER.query("filter", filter, 'str', skip_quote=True)
    if top is not None:
        query_parameters['$top'] = _SERIALIZER.query("top", top, 'int', maximum=1000, minimum=1)
    query_parameters['api-version'] = _SERIALIZER.query("api_version", api_version, 'str')

    # Construct headers
    header_parameters = kwargs.pop("headers", {})  # type: Dict[str, Any]
    header_parameters['Accept'] = _SERIALIZER.header("accept", accept, 'str')

    return HttpRequest(
        method="GET",
        url=url,
        params=query_parameters,
        headers=header_parameters,
        **kwargs
    )


def build_list_for_resource_request(
    resource_group_name: str,
    resource_provider_namespace: str,
    parent_resource_path: str,
    resource_type: str,
    resource_name: str,
    subscription_id: str,
    *,
    filter: Optional[str] = None,
    top: Optional[int] = None,
    **kwargs: Any
) -> HttpRequest:
    api_version = "2020-09-01"
    accept = "application/json"
    # Construct URL
    url = kwargs.pop("template_url", '/subscriptions/{subscriptionId}/resourceGroups/{resourceGroupName}/providers/{resourceProviderNamespace}/{parentResourcePath}/{resourceType}/{resourceName}/providers/Microsoft.Authorization/policyAssignments')
    path_format_arguments = {
        "resourceGroupName": _SERIALIZER.url("resource_group_name", resource_group_name, 'str', max_length=90, min_length=1, pattern=r'^[-\w\._\(\)]+$'),
        "resourceProviderNamespace": _SERIALIZER.url("resource_provider_namespace", resource_provider_namespace, 'str'),
        "parentResourcePath": _SERIALIZER.url("parent_resource_path", parent_resource_path, 'str', skip_quote=True),
        "resourceType": _SERIALIZER.url("resource_type", resource_type, 'str', skip_quote=True),
        "resourceName": _SERIALIZER.url("resource_name", resource_name, 'str'),
        "subscriptionId": _SERIALIZER.url("subscription_id", subscription_id, 'str'),
    }

    url = _format_url_section(url, **path_format_arguments)

    # Construct parameters
    query_parameters = kwargs.pop("params", {})  # type: Dict[str, Any]
    if filter is not None:
        query_parameters['$filter'] = _SERIALIZER.query("filter", filter, 'str', skip_quote=True)
    if top is not None:
        query_parameters['$top'] = _SERIALIZER.query("top", top, 'int', maximum=1000, minimum=1)
    query_parameters['api-version'] = _SERIALIZER.query("api_version", api_version, 'str')

    # Construct headers
    header_parameters = kwargs.pop("headers", {})  # type: Dict[str, Any]
    header_parameters['Accept'] = _SERIALIZER.header("accept", accept, 'str')

    return HttpRequest(
        method="GET",
        url=url,
        params=query_parameters,
        headers=header_parameters,
        **kwargs
    )


def build_list_for_management_group_request(
    management_group_id: str,
    *,
    filter: Optional[str] = None,
    top: Optional[int] = None,
    **kwargs: Any
) -> HttpRequest:
    api_version = "2020-09-01"
    accept = "application/json"
    # Construct URL
    url = kwargs.pop("template_url", '/providers/Microsoft.Management/managementGroups/{managementGroupId}/providers/Microsoft.Authorization/policyAssignments')
    path_format_arguments = {
        "managementGroupId": _SERIALIZER.url("management_group_id", management_group_id, 'str'),
    }

    url = _format_url_section(url, **path_format_arguments)

    # Construct parameters
    query_parameters = kwargs.pop("params", {})  # type: Dict[str, Any]
    if filter is not None:
        query_parameters['$filter'] = _SERIALIZER.query("filter", filter, 'str', skip_quote=True)
    if top is not None:
        query_parameters['$top'] = _SERIALIZER.query("top", top, 'int', maximum=1000, minimum=1)
    query_parameters['api-version'] = _SERIALIZER.query("api_version", api_version, 'str')

    # Construct headers
    header_parameters = kwargs.pop("headers", {})  # type: Dict[str, Any]
    header_parameters['Accept'] = _SERIALIZER.header("accept", accept, 'str')

    return HttpRequest(
        method="GET",
        url=url,
        params=query_parameters,
        headers=header_parameters,
        **kwargs
    )


def build_list_request(
    subscription_id: str,
    *,
    filter: Optional[str] = None,
    top: Optional[int] = None,
    **kwargs: Any
) -> HttpRequest:
    api_version = "2020-09-01"
    accept = "application/json"
    # Construct URL
    url = kwargs.pop("template_url", '/subscriptions/{subscriptionId}/providers/Microsoft.Authorization/policyAssignments')
    path_format_arguments = {
        "subscriptionId": _SERIALIZER.url("subscription_id", subscription_id, 'str'),
    }

    url = _format_url_section(url, **path_format_arguments)

    # Construct parameters
    query_parameters = kwargs.pop("params", {})  # type: Dict[str, Any]
    if filter is not None:
        query_parameters['$filter'] = _SERIALIZER.query("filter", filter, 'str', skip_quote=True)
    if top is not None:
        query_parameters['$top'] = _SERIALIZER.query("top", top, 'int', maximum=1000, minimum=1)
    query_parameters['api-version'] = _SERIALIZER.query("api_version", api_version, 'str')

    # Construct headers
    header_parameters = kwargs.pop("headers", {})  # type: Dict[str, Any]
    header_parameters['Accept'] = _SERIALIZER.header("accept", accept, 'str')

    return HttpRequest(
        method="GET",
        url=url,
        params=query_parameters,
        headers=header_parameters,
        **kwargs
    )


def build_delete_by_id_request(
    policy_assignment_id: str,
    **kwargs: Any
) -> HttpRequest:
    api_version = "2020-09-01"
    accept = "application/json"
    # Construct URL
    url = kwargs.pop("template_url", '/{policyAssignmentId}')
    path_format_arguments = {
        "policyAssignmentId": _SERIALIZER.url("policy_assignment_id", policy_assignment_id, 'str', skip_quote=True),
    }

    url = _format_url_section(url, **path_format_arguments)

    # Construct parameters
    query_parameters = kwargs.pop("params", {})  # type: Dict[str, Any]
    query_parameters['api-version'] = _SERIALIZER.query("api_version", api_version, 'str')

    # Construct headers
    header_parameters = kwargs.pop("headers", {})  # type: Dict[str, Any]
    header_parameters['Accept'] = _SERIALIZER.header("accept", accept, 'str')

    return HttpRequest(
        method="DELETE",
        url=url,
        params=query_parameters,
        headers=header_parameters,
        **kwargs
    )


def build_create_by_id_request(
    policy_assignment_id: str,
    *,
    json: JSONType = None,
    content: Any = None,
    **kwargs: Any
) -> HttpRequest:
    content_type = kwargs.pop('content_type', None)  # type: Optional[str]

    api_version = "2020-09-01"
    accept = "application/json"
    # Construct URL
    url = kwargs.pop("template_url", '/{policyAssignmentId}')
    path_format_arguments = {
        "policyAssignmentId": _SERIALIZER.url("policy_assignment_id", policy_assignment_id, 'str', skip_quote=True),
    }

    url = _format_url_section(url, **path_format_arguments)

    # Construct parameters
    query_parameters = kwargs.pop("params", {})  # type: Dict[str, Any]
    query_parameters['api-version'] = _SERIALIZER.query("api_version", api_version, 'str')

    # Construct headers
    header_parameters = kwargs.pop("headers", {})  # type: Dict[str, Any]
    if content_type is not None:
        header_parameters['Content-Type'] = _SERIALIZER.header("content_type", content_type, 'str')
    header_parameters['Accept'] = _SERIALIZER.header("accept", accept, 'str')

    return HttpRequest(
        method="PUT",
        url=url,
        params=query_parameters,
        headers=header_parameters,
        json=json,
        content=content,
        **kwargs
    )


def build_get_by_id_request(
    policy_assignment_id: str,
    **kwargs: Any
) -> HttpRequest:
    api_version = "2020-09-01"
    accept = "application/json"
    # Construct URL
    url = kwargs.pop("template_url", '/{policyAssignmentId}')
    path_format_arguments = {
        "policyAssignmentId": _SERIALIZER.url("policy_assignment_id", policy_assignment_id, 'str', skip_quote=True),
    }

    url = _format_url_section(url, **path_format_arguments)

    # Construct parameters
    query_parameters = kwargs.pop("params", {})  # type: Dict[str, Any]
    query_parameters['api-version'] = _SERIALIZER.query("api_version", api_version, 'str')

    # Construct headers
    header_parameters = kwargs.pop("headers", {})  # type: Dict[str, Any]
    header_parameters['Accept'] = _SERIALIZER.header("accept", accept, 'str')

    return HttpRequest(
        method="GET",
        url=url,
        params=query_parameters,
        headers=header_parameters,
        **kwargs
    )

class PolicyAssignmentsOperations(object):
    """PolicyAssignmentsOperations operations.

    You should not instantiate this class directly. Instead, you should create a Client instance that
    instantiates it for you and attaches it as an attribute.

    :ivar models: Alias to model classes used in this operation group.
    :type models: ~azure.mgmt.resource.policy.v2020_09_01.models
    :param client: Client for service requests.
    :param config: Configuration of service client.
    :param serializer: An object model serializer.
    :param deserializer: An object model deserializer.
    """

    models = _models

    def __init__(self, client, config, serializer, deserializer):
        self._client = client
        self._serialize = serializer
        self._deserialize = deserializer
        self._config = config

    @distributed_trace
    def delete(
        self,
        scope: str,
        policy_assignment_name: str,
        **kwargs: Any
    ) -> Optional["_models.PolicyAssignment"]:
        """Deletes a policy assignment.

        This operation deletes a policy assignment, given its name and the scope it was created in. The
        scope of a policy assignment is the part of its ID preceding
        '/providers/Microsoft.Authorization/policyAssignments/{policyAssignmentName}'.

        :param scope: The scope of the policy assignment. Valid scopes are: management group (format:
         '/providers/Microsoft.Management/managementGroups/{managementGroup}'), subscription (format:
         '/subscriptions/{subscriptionId}'), resource group (format:
         '/subscriptions/{subscriptionId}/resourceGroups/{resourceGroupName}', or resource (format:
         '/subscriptions/{subscriptionId}/resourceGroups/{resourceGroupName}/providers/{resourceProviderNamespace}/[{parentResourcePath}/]{resourceType}/{resourceName}'.
        :type scope: str
        :param policy_assignment_name: The name of the policy assignment to delete.
        :type policy_assignment_name: str
        :keyword callable cls: A custom type or function that will be passed the direct response
        :return: PolicyAssignment, or the result of cls(response)
        :rtype: ~azure.mgmt.resource.policy.v2020_09_01.models.PolicyAssignment or None
        :raises: ~azure.core.exceptions.HttpResponseError
        """
        cls = kwargs.pop('cls', None)  # type: ClsType[Optional["_models.PolicyAssignment"]]
        error_map = {
            401: ClientAuthenticationError, 404: ResourceNotFoundError, 409: ResourceExistsError
        }
        error_map.update(kwargs.pop('error_map', {}))

        
        request = build_delete_request(
            scope=scope,
            policy_assignment_name=policy_assignment_name,
            template_url=self.delete.metadata['url'],
        )
        request = _convert_request(request)
        request.url = self._client.format_url(request.url)

        pipeline_response = self._client._pipeline.run(request, stream=False, **kwargs)
        response = pipeline_response.http_response

        if response.status_code not in [200, 204]:
            map_error(status_code=response.status_code, response=response, error_map=error_map)
            raise HttpResponseError(response=response, error_format=ARMErrorFormat)

        deserialized = None
        if response.status_code == 200:
            deserialized = self._deserialize('PolicyAssignment', pipeline_response)

        if cls:
            return cls(pipeline_response, deserialized, {})

        return deserialized

    delete.metadata = {'url': '/{scope}/providers/Microsoft.Authorization/policyAssignments/{policyAssignmentName}'}  # type: ignore


    @distributed_trace
    def create(
        self,
        scope: str,
        policy_assignment_name: str,
        parameters: "_models.PolicyAssignment",
        **kwargs: Any
    ) -> "_models.PolicyAssignment":
        """Creates or updates a policy assignment.

        This operation creates or updates a policy assignment with the given scope and name. Policy
        assignments apply to all resources contained within their scope. For example, when you assign a
        policy at resource group scope, that policy applies to all resources in the group.

        :param scope: The scope of the policy assignment. Valid scopes are: management group (format:
         '/providers/Microsoft.Management/managementGroups/{managementGroup}'), subscription (format:
         '/subscriptions/{subscriptionId}'), resource group (format:
         '/subscriptions/{subscriptionId}/resourceGroups/{resourceGroupName}', or resource (format:
         '/subscriptions/{subscriptionId}/resourceGroups/{resourceGroupName}/providers/{resourceProviderNamespace}/[{parentResourcePath}/]{resourceType}/{resourceName}'.
        :type scope: str
        :param policy_assignment_name: The name of the policy assignment.
        :type policy_assignment_name: str
        :param parameters: Parameters for the policy assignment.
        :type parameters: ~azure.mgmt.resource.policy.v2020_09_01.models.PolicyAssignment
        :keyword callable cls: A custom type or function that will be passed the direct response
        :return: PolicyAssignment, or the result of cls(response)
        :rtype: ~azure.mgmt.resource.policy.v2020_09_01.models.PolicyAssignment
        :raises: ~azure.core.exceptions.HttpResponseError
        """
        cls = kwargs.pop('cls', None)  # type: ClsType["_models.PolicyAssignment"]
        error_map = {
            401: ClientAuthenticationError, 404: ResourceNotFoundError, 409: ResourceExistsError
        }
        error_map.update(kwargs.pop('error_map', {}))

        content_type = kwargs.pop('content_type', "application/json")  # type: Optional[str]

        _json = self._serialize.body(parameters, 'PolicyAssignment')

        request = build_create_request(
            scope=scope,
            policy_assignment_name=policy_assignment_name,
            content_type=content_type,
            json=_json,
            template_url=self.create.metadata['url'],
        )
        request = _convert_request(request)
        request.url = self._client.format_url(request.url)

        pipeline_response = self._client._pipeline.run(request, stream=False, **kwargs)
        response = pipeline_response.http_response

        if response.status_code not in [201]:
            map_error(status_code=response.status_code, response=response, error_map=error_map)
            raise HttpResponseError(response=response, error_format=ARMErrorFormat)

        deserialized = self._deserialize('PolicyAssignment', pipeline_response)

        if cls:
            return cls(pipeline_response, deserialized, {})

        return deserialized

    create.metadata = {'url': '/{scope}/providers/Microsoft.Authorization/policyAssignments/{policyAssignmentName}'}  # type: ignore


    @distributed_trace
    def get(
        self,
        scope: str,
        policy_assignment_name: str,
        **kwargs: Any
    ) -> "_models.PolicyAssignment":
        """Retrieves a policy assignment.

        This operation retrieves a single policy assignment, given its name and the scope it was
        created at.

        :param scope: The scope of the policy assignment. Valid scopes are: management group (format:
         '/providers/Microsoft.Management/managementGroups/{managementGroup}'), subscription (format:
         '/subscriptions/{subscriptionId}'), resource group (format:
         '/subscriptions/{subscriptionId}/resourceGroups/{resourceGroupName}', or resource (format:
         '/subscriptions/{subscriptionId}/resourceGroups/{resourceGroupName}/providers/{resourceProviderNamespace}/[{parentResourcePath}/]{resourceType}/{resourceName}'.
        :type scope: str
        :param policy_assignment_name: The name of the policy assignment to get.
        :type policy_assignment_name: str
        :keyword callable cls: A custom type or function that will be passed the direct response
        :return: PolicyAssignment, or the result of cls(response)
        :rtype: ~azure.mgmt.resource.policy.v2020_09_01.models.PolicyAssignment
        :raises: ~azure.core.exceptions.HttpResponseError
        """
        cls = kwargs.pop('cls', None)  # type: ClsType["_models.PolicyAssignment"]
        error_map = {
            401: ClientAuthenticationError, 404: ResourceNotFoundError, 409: ResourceExistsError
        }
        error_map.update(kwargs.pop('error_map', {}))

        
        request = build_get_request(
            scope=scope,
            policy_assignment_name=policy_assignment_name,
            template_url=self.get.metadata['url'],
        )
        request = _convert_request(request)
        request.url = self._client.format_url(request.url)

        pipeline_response = self._client._pipeline.run(request, stream=False, **kwargs)
        response = pipeline_response.http_response

        if response.status_code not in [200]:
            map_error(status_code=response.status_code, response=response, error_map=error_map)
            raise HttpResponseError(response=response, error_format=ARMErrorFormat)

        deserialized = self._deserialize('PolicyAssignment', pipeline_response)

        if cls:
            return cls(pipeline_response, deserialized, {})

        return deserialized

    get.metadata = {'url': '/{scope}/providers/Microsoft.Authorization/policyAssignments/{policyAssignmentName}'}  # type: ignore


    @distributed_trace
    def list_for_resource_group(
        self,
        resource_group_name: str,
        filter: Optional[str] = None,
        top: Optional[int] = None,
        **kwargs: Any
    ) -> Iterable["_models.PolicyAssignmentListResult"]:
        """Retrieves all policy assignments that apply to a resource group.

        This operation retrieves the list of all policy assignments associated with the given resource
        group in the given subscription that match the optional given $filter. Valid values for $filter
        are: 'atScope()', 'atExactScope()' or 'policyDefinitionId eq '{value}''. If $filter is not
        provided, the unfiltered list includes all policy assignments associated with the resource
        group, including those that apply directly or apply from containing scopes, as well as any
        applied to resources contained within the resource group. If $filter=atScope() is provided, the
        returned list includes all policy assignments that apply to the resource group, which is
        everything in the unfiltered list except those applied to resources contained within the
        resource group. If $filter=atExactScope() is provided, the returned list only includes all
        policy assignments that at the resource group. If $filter=policyDefinitionId eq '{value}' is
        provided, the returned list includes all policy assignments of the policy definition whose id
        is {value} that apply to the resource group.

        :param resource_group_name: The name of the resource group that contains policy assignments.
        :type resource_group_name: str
        :param filter: The filter to apply on the operation. Valid values for $filter are: 'atScope()',
         'atExactScope()' or 'policyDefinitionId eq '{value}''. If $filter is not provided, no filtering
         is performed. If $filter=atScope() is provided, the returned list only includes all policy
         assignments that apply to the scope, which is everything in the unfiltered list except those
         applied to sub scopes contained within the given scope. If $filter=atExactScope() is provided,
         the returned list only includes all policy assignments that at the given scope. If
         $filter=policyDefinitionId eq '{value}' is provided, the returned list includes all policy
         assignments of the policy definition whose id is {value}.
        :type filter: str
        :param top: Maximum number of records to return. When the $top filter is not provided, it will
         return 500 records.
        :type top: int
        :keyword callable cls: A custom type or function that will be passed the direct response
        :return: An iterator like instance of either PolicyAssignmentListResult or the result of
         cls(response)
        :rtype:
         ~azure.core.paging.ItemPaged[~azure.mgmt.resource.policy.v2020_09_01.models.PolicyAssignmentListResult]
        :raises: ~azure.core.exceptions.HttpResponseError
        """
        cls = kwargs.pop('cls', None)  # type: ClsType["_models.PolicyAssignmentListResult"]
        error_map = {
            401: ClientAuthenticationError, 404: ResourceNotFoundError, 409: ResourceExistsError
        }
        error_map.update(kwargs.pop('error_map', {}))
        def prepare_request(next_link=None):
            if not next_link:
                
                request = build_list_for_resource_group_request(
                    resource_group_name=resource_group_name,
                    subscription_id=self._config.subscription_id,
                    filter=filter,
                    top=top,
                    template_url=self.list_for_resource_group.metadata['url'],
                )
                request = _convert_request(request)
                request.url = self._client.format_url(request.url)

            else:
                
                request = build_list_for_resource_group_request(
                    resource_group_name=resource_group_name,
                    subscription_id=self._config.subscription_id,
                    filter=filter,
                    top=top,
                    template_url=next_link,
                )
                request = _convert_request(request)
                request.url = self._client.format_url(request.url)
                request.method = "GET"
            return request

        def extract_data(pipeline_response):
            deserialized = self._deserialize("PolicyAssignmentListResult", pipeline_response)
            list_of_elem = deserialized.value
            if cls:
                list_of_elem = cls(list_of_elem)
            return deserialized.next_link or None, iter(list_of_elem)

        def get_next(next_link=None):
            request = prepare_request(next_link)

            pipeline_response = self._client._pipeline.run(request, stream=False, **kwargs)
            response = pipeline_response.http_response

            if response.status_code not in [200]:
                map_error(status_code=response.status_code, response=response, error_map=error_map)
                raise HttpResponseError(response=response, error_format=ARMErrorFormat)

            return pipeline_response


        return ItemPaged(
            get_next, extract_data
        )
    list_for_resource_group.metadata = {'url': '/subscriptions/{subscriptionId}/resourceGroups/{resourceGroupName}/providers/Microsoft.Authorization/policyAssignments'}  # type: ignore

    @distributed_trace
    def list_for_resource(
        self,
        resource_group_name: str,
        resource_provider_namespace: str,
        parent_resource_path: str,
        resource_type: str,
        resource_name: str,
        filter: Optional[str] = None,
        top: Optional[int] = None,
        **kwargs: Any
    ) -> Iterable["_models.PolicyAssignmentListResult"]:
        """Retrieves all policy assignments that apply to a resource.

        This operation retrieves the list of all policy assignments associated with the specified
        resource in the given resource group and subscription that match the optional given $filter.
        Valid values for $filter are: 'atScope()', 'atExactScope()' or 'policyDefinitionId eq
        '{value}''. If $filter is not provided, the unfiltered list includes all policy assignments
        associated with the resource, including those that apply directly or from all containing
        scopes, as well as any applied to resources contained within the resource. If $filter=atScope()
        is provided, the returned list includes all policy assignments that apply to the resource,
        which is everything in the unfiltered list except those applied to resources contained within
        the resource. If $filter=atExactScope() is provided, the returned list only includes all policy
        assignments that at the resource level. If $filter=policyDefinitionId eq '{value}' is provided,
        the returned list includes all policy assignments of the policy definition whose id is {value}
        that apply to the resource. Three parameters plus the resource name are used to identify a
        specific resource. If the resource is not part of a parent resource (the more common case), the
        parent resource path should not be provided (or provided as ''). For example a web app could be
        specified as ({resourceProviderNamespace} == 'Microsoft.Web', {parentResourcePath} == '',
        {resourceType} == 'sites', {resourceName} == 'MyWebApp'). If the resource is part of a parent
        resource, then all parameters should be provided. For example a virtual machine DNS name could
        be specified as ({resourceProviderNamespace} == 'Microsoft.Compute', {parentResourcePath} ==
        'virtualMachines/MyVirtualMachine', {resourceType} == 'domainNames', {resourceName} ==
        'MyComputerName'). A convenient alternative to providing the namespace and type name separately
        is to provide both in the {resourceType} parameter, format: ({resourceProviderNamespace} == '',
        {parentResourcePath} == '', {resourceType} == 'Microsoft.Web/sites', {resourceName} ==
        'MyWebApp').

        :param resource_group_name: The name of the resource group containing the resource.
        :type resource_group_name: str
        :param resource_provider_namespace: The namespace of the resource provider. For example, the
         namespace of a virtual machine is Microsoft.Compute (from Microsoft.Compute/virtualMachines).
        :type resource_provider_namespace: str
        :param parent_resource_path: The parent resource path. Use empty string if there is none.
        :type parent_resource_path: str
        :param resource_type: The resource type name. For example the type name of a web app is 'sites'
         (from Microsoft.Web/sites).
        :type resource_type: str
        :param resource_name: The name of the resource.
        :type resource_name: str
        :param filter: The filter to apply on the operation. Valid values for $filter are: 'atScope()',
         'atExactScope()' or 'policyDefinitionId eq '{value}''. If $filter is not provided, no filtering
         is performed. If $filter=atScope() is provided, the returned list only includes all policy
         assignments that apply to the scope, which is everything in the unfiltered list except those
         applied to sub scopes contained within the given scope. If $filter=atExactScope() is provided,
         the returned list only includes all policy assignments that at the given scope. If
         $filter=policyDefinitionId eq '{value}' is provided, the returned list includes all policy
         assignments of the policy definition whose id is {value}.
        :type filter: str
        :param top: Maximum number of records to return. When the $top filter is not provided, it will
         return 500 records.
        :type top: int
        :keyword callable cls: A custom type or function that will be passed the direct response
        :return: An iterator like instance of either PolicyAssignmentListResult or the result of
         cls(response)
        :rtype:
         ~azure.core.paging.ItemPaged[~azure.mgmt.resource.policy.v2020_09_01.models.PolicyAssignmentListResult]
        :raises: ~azure.core.exceptions.HttpResponseError
        """
        cls = kwargs.pop('cls', None)  # type: ClsType["_models.PolicyAssignmentListResult"]
        error_map = {
            401: ClientAuthenticationError, 404: ResourceNotFoundError, 409: ResourceExistsError
        }
        error_map.update(kwargs.pop('error_map', {}))
        def prepare_request(next_link=None):
            if not next_link:
                
                request = build_list_for_resource_request(
                    resource_group_name=resource_group_name,
                    resource_provider_namespace=resource_provider_namespace,
                    parent_resource_path=parent_resource_path,
                    resource_type=resource_type,
                    resource_name=resource_name,
                    subscription_id=self._config.subscription_id,
                    filter=filter,
                    top=top,
                    template_url=self.list_for_resource.metadata['url'],
                )
                request = _convert_request(request)
                request.url = self._client.format_url(request.url)

            else:
                
                request = build_list_for_resource_request(
                    resource_group_name=resource_group_name,
                    resource_provider_namespace=resource_provider_namespace,
                    parent_resource_path=parent_resource_path,
                    resource_type=resource_type,
                    resource_name=resource_name,
                    subscription_id=self._config.subscription_id,
                    filter=filter,
                    top=top,
                    template_url=next_link,
                )
                request = _convert_request(request)
                request.url = self._client.format_url(request.url)
                request.method = "GET"
            return request

        def extract_data(pipeline_response):
            deserialized = self._deserialize("PolicyAssignmentListResult", pipeline_response)
            list_of_elem = deserialized.value
            if cls:
                list_of_elem = cls(list_of_elem)
            return deserialized.next_link or None, iter(list_of_elem)

        def get_next(next_link=None):
            request = prepare_request(next_link)

            pipeline_response = self._client._pipeline.run(request, stream=False, **kwargs)
            response = pipeline_response.http_response

            if response.status_code not in [200]:
                map_error(status_code=response.status_code, response=response, error_map=error_map)
                raise HttpResponseError(response=response, error_format=ARMErrorFormat)

            return pipeline_response


        return ItemPaged(
            get_next, extract_data
        )
    list_for_resource.metadata = {'url': '/subscriptions/{subscriptionId}/resourceGroups/{resourceGroupName}/providers/{resourceProviderNamespace}/{parentResourcePath}/{resourceType}/{resourceName}/providers/Microsoft.Authorization/policyAssignments'}  # type: ignore

    @distributed_trace
    def list_for_management_group(
        self,
        management_group_id: str,
        filter: Optional[str] = None,
        top: Optional[int] = None,
        **kwargs: Any
    ) -> Iterable["_models.PolicyAssignmentListResult"]:
        """Retrieves all policy assignments that apply to a management group.

        This operation retrieves the list of all policy assignments applicable to the management group
        that match the given $filter. Valid values for $filter are: 'atScope()', 'atExactScope()' or
        'policyDefinitionId eq '{value}''. If $filter=atScope() is provided, the returned list includes
        all policy assignments that are assigned to the management group or the management group's
        ancestors. If $filter=atExactScope() is provided, the returned list only includes all policy
        assignments that at the management group. If $filter=policyDefinitionId eq '{value}' is
        provided, the returned list includes all policy assignments of the policy definition whose id
        is {value} that apply to the management group.

        :param management_group_id: The ID of the management group.
        :type management_group_id: str
        :param filter: The filter to apply on the operation. Valid values for $filter are: 'atScope()',
         'atExactScope()' or 'policyDefinitionId eq '{value}''. If $filter is not provided, no filtering
         is performed. If $filter=atScope() is provided, the returned list only includes all policy
         assignments that apply to the scope, which is everything in the unfiltered list except those
         applied to sub scopes contained within the given scope. If $filter=atExactScope() is provided,
         the returned list only includes all policy assignments that at the given scope. If
         $filter=policyDefinitionId eq '{value}' is provided, the returned list includes all policy
         assignments of the policy definition whose id is {value}.
        :type filter: str
        :param top: Maximum number of records to return. When the $top filter is not provided, it will
         return 500 records.
        :type top: int
        :keyword callable cls: A custom type or function that will be passed the direct response
        :return: An iterator like instance of either PolicyAssignmentListResult or the result of
         cls(response)
        :rtype:
         ~azure.core.paging.ItemPaged[~azure.mgmt.resource.policy.v2020_09_01.models.PolicyAssignmentListResult]
        :raises: ~azure.core.exceptions.HttpResponseError
        """
        cls = kwargs.pop('cls', None)  # type: ClsType["_models.PolicyAssignmentListResult"]
        error_map = {
            401: ClientAuthenticationError, 404: ResourceNotFoundError, 409: ResourceExistsError
        }
        error_map.update(kwargs.pop('error_map', {}))
        def prepare_request(next_link=None):
            if not next_link:
                
                request = build_list_for_management_group_request(
                    management_group_id=management_group_id,
                    filter=filter,
                    top=top,
                    template_url=self.list_for_management_group.metadata['url'],
                )
                request = _convert_request(request)
                request.url = self._client.format_url(request.url)

            else:
                
                request = build_list_for_management_group_request(
                    management_group_id=management_group_id,
                    filter=filter,
                    top=top,
                    template_url=next_link,
                )
                request = _convert_request(request)
                request.url = self._client.format_url(request.url)
                request.method = "GET"
            return request

        def extract_data(pipeline_response):
            deserialized = self._deserialize("PolicyAssignmentListResult", pipeline_response)
            list_of_elem = deserialized.value
            if cls:
                list_of_elem = cls(list_of_elem)
            return deserialized.next_link or None, iter(list_of_elem)

        def get_next(next_link=None):
            request = prepare_request(next_link)

            pipeline_response = self._client._pipeline.run(request, stream=False, **kwargs)
            response = pipeline_response.http_response

            if response.status_code not in [200]:
                map_error(status_code=response.status_code, response=response, error_map=error_map)
                raise HttpResponseError(response=response, error_format=ARMErrorFormat)

            return pipeline_response


        return ItemPaged(
            get_next, extract_data
        )
    list_for_management_group.metadata = {'url': '/providers/Microsoft.Management/managementGroups/{managementGroupId}/providers/Microsoft.Authorization/policyAssignments'}  # type: ignore

    @distributed_trace
    def list(
        self,
        filter: Optional[str] = None,
        top: Optional[int] = None,
        **kwargs: Any
    ) -> Iterable["_models.PolicyAssignmentListResult"]:
        """Retrieves all policy assignments that apply to a subscription.

        This operation retrieves the list of all policy assignments associated with the given
        subscription that match the optional given $filter. Valid values for $filter are: 'atScope()',
        'atExactScope()' or 'policyDefinitionId eq '{value}''. If $filter is not provided, the
        unfiltered list includes all policy assignments associated with the subscription, including
        those that apply directly or from management groups that contain the given subscription, as
        well as any applied to objects contained within the subscription. If $filter=atScope() is
        provided, the returned list includes all policy assignments that apply to the subscription,
        which is everything in the unfiltered list except those applied to objects contained within the
        subscription. If $filter=atExactScope() is provided, the returned list only includes all policy
        assignments that at the subscription. If $filter=policyDefinitionId eq '{value}' is provided,
        the returned list includes all policy assignments of the policy definition whose id is {value}.

        :param filter: The filter to apply on the operation. Valid values for $filter are: 'atScope()',
         'atExactScope()' or 'policyDefinitionId eq '{value}''. If $filter is not provided, no filtering
         is performed. If $filter=atScope() is provided, the returned list only includes all policy
         assignments that apply to the scope, which is everything in the unfiltered list except those
         applied to sub scopes contained within the given scope. If $filter=atExactScope() is provided,
         the returned list only includes all policy assignments that at the given scope. If
         $filter=policyDefinitionId eq '{value}' is provided, the returned list includes all policy
         assignments of the policy definition whose id is {value}.
        :type filter: str
        :param top: Maximum number of records to return. When the $top filter is not provided, it will
         return 500 records.
        :type top: int
        :keyword callable cls: A custom type or function that will be passed the direct response
        :return: An iterator like instance of either PolicyAssignmentListResult or the result of
         cls(response)
        :rtype:
         ~azure.core.paging.ItemPaged[~azure.mgmt.resource.policy.v2020_09_01.models.PolicyAssignmentListResult]
        :raises: ~azure.core.exceptions.HttpResponseError
        """
        cls = kwargs.pop('cls', None)  # type: ClsType["_models.PolicyAssignmentListResult"]
        error_map = {
            401: ClientAuthenticationError, 404: ResourceNotFoundError, 409: ResourceExistsError
        }
        error_map.update(kwargs.pop('error_map', {}))
        def prepare_request(next_link=None):
            if not next_link:
                
                request = build_list_request(
                    subscription_id=self._config.subscription_id,
                    filter=filter,
                    top=top,
                    template_url=self.list.metadata['url'],
                )
                request = _convert_request(request)
                request.url = self._client.format_url(request.url)

            else:
                
                request = build_list_request(
                    subscription_id=self._config.subscription_id,
                    filter=filter,
                    top=top,
                    template_url=next_link,
                )
                request = _convert_request(request)
                request.url = self._client.format_url(request.url)
                request.method = "GET"
            return request

        def extract_data(pipeline_response):
            deserialized = self._deserialize("PolicyAssignmentListResult", pipeline_response)
            list_of_elem = deserialized.value
            if cls:
                list_of_elem = cls(list_of_elem)
            return deserialized.next_link or None, iter(list_of_elem)

        def get_next(next_link=None):
            request = prepare_request(next_link)

            pipeline_response = self._client._pipeline.run(request, stream=False, **kwargs)
            response = pipeline_response.http_response

            if response.status_code not in [200]:
                map_error(status_code=response.status_code, response=response, error_map=error_map)
                raise HttpResponseError(response=response, error_format=ARMErrorFormat)

            return pipeline_response


        return ItemPaged(
            get_next, extract_data
        )
    list.metadata = {'url': '/subscriptions/{subscriptionId}/providers/Microsoft.Authorization/policyAssignments'}  # type: ignore

    @distributed_trace
    def delete_by_id(
        self,
        policy_assignment_id: str,
        **kwargs: Any
    ) -> Optional["_models.PolicyAssignment"]:
        """Deletes a policy assignment.

        This operation deletes the policy with the given ID. Policy assignment IDs have this format:
        '{scope}/providers/Microsoft.Authorization/policyAssignments/{policyAssignmentName}'. Valid
        formats for {scope} are: '/providers/Microsoft.Management/managementGroups/{managementGroup}'
        (management group), '/subscriptions/{subscriptionId}' (subscription),
        '/subscriptions/{subscriptionId}/resourceGroups/{resourceGroupName}' (resource group), or
        '/subscriptions/{subscriptionId}/resourceGroups/{resourceGroupName}/providers/{resourceProviderNamespace}/[{parentResourcePath}/]{resourceType}/{resourceName}'
        (resource).

        :param policy_assignment_id: The ID of the policy assignment to delete. Use the format
         '{scope}/providers/Microsoft.Authorization/policyAssignments/{policyAssignmentName}'.
        :type policy_assignment_id: str
        :keyword callable cls: A custom type or function that will be passed the direct response
        :return: PolicyAssignment, or the result of cls(response)
        :rtype: ~azure.mgmt.resource.policy.v2020_09_01.models.PolicyAssignment or None
        :raises: ~azure.core.exceptions.HttpResponseError
        """
        cls = kwargs.pop('cls', None)  # type: ClsType[Optional["_models.PolicyAssignment"]]
        error_map = {
            401: ClientAuthenticationError, 404: ResourceNotFoundError, 409: ResourceExistsError
        }
        error_map.update(kwargs.pop('error_map', {}))

        
        request = build_delete_by_id_request(
            policy_assignment_id=policy_assignment_id,
            template_url=self.delete_by_id.metadata['url'],
        )
        request = _convert_request(request)
        request.url = self._client.format_url(request.url)

        pipeline_response = self._client._pipeline.run(request, stream=False, **kwargs)
        response = pipeline_response.http_response

        if response.status_code not in [200, 204]:
            map_error(status_code=response.status_code, response=response, error_map=error_map)
            raise HttpResponseError(response=response, error_format=ARMErrorFormat)

        deserialized = None
        if response.status_code == 200:
            deserialized = self._deserialize('PolicyAssignment', pipeline_response)

        if cls:
            return cls(pipeline_response, deserialized, {})

        return deserialized

    delete_by_id.metadata = {'url': '/{policyAssignmentId}'}  # type: ignore


    @distributed_trace
    def create_by_id(
        self,
        policy_assignment_id: str,
        parameters: "_models.PolicyAssignment",
        **kwargs: Any
    ) -> "_models.PolicyAssignment":
        """Creates or updates a policy assignment.

        This operation creates or updates the policy assignment with the given ID. Policy assignments
        made on a scope apply to all resources contained in that scope. For example, when you assign a
        policy to a resource group that policy applies to all resources in the group. Policy assignment
        IDs have this format:
        '{scope}/providers/Microsoft.Authorization/policyAssignments/{policyAssignmentName}'. Valid
        scopes are: management group (format:
        '/providers/Microsoft.Management/managementGroups/{managementGroup}'), subscription (format:
        '/subscriptions/{subscriptionId}'), resource group (format:
        '/subscriptions/{subscriptionId}/resourceGroups/{resourceGroupName}', or resource (format:
        '/subscriptions/{subscriptionId}/resourceGroups/{resourceGroupName}/providers/{resourceProviderNamespace}/[{parentResourcePath}/]{resourceType}/{resourceName}'.

        :param policy_assignment_id: The ID of the policy assignment to create. Use the format
         '{scope}/providers/Microsoft.Authorization/policyAssignments/{policyAssignmentName}'.
        :type policy_assignment_id: str
        :param parameters: Parameters for policy assignment.
        :type parameters: ~azure.mgmt.resource.policy.v2020_09_01.models.PolicyAssignment
        :keyword callable cls: A custom type or function that will be passed the direct response
        :return: PolicyAssignment, or the result of cls(response)
        :rtype: ~azure.mgmt.resource.policy.v2020_09_01.models.PolicyAssignment
        :raises: ~azure.core.exceptions.HttpResponseError
        """
        cls = kwargs.pop('cls', None)  # type: ClsType["_models.PolicyAssignment"]
        error_map = {
            401: ClientAuthenticationError, 404: ResourceNotFoundError, 409: ResourceExistsError
        }
        error_map.update(kwargs.pop('error_map', {}))

        content_type = kwargs.pop('content_type', "application/json")  # type: Optional[str]

        _json = self._serialize.body(parameters, 'PolicyAssignment')

        request = build_create_by_id_request(
            policy_assignment_id=policy_assignment_id,
            content_type=content_type,
            json=_json,
            template_url=self.create_by_id.metadata['url'],
        )
        request = _convert_request(request)
        request.url = self._client.format_url(request.url)

        pipeline_response = self._client._pipeline.run(request, stream=False, **kwargs)
        response = pipeline_response.http_response

        if response.status_code not in [201]:
            map_error(status_code=response.status_code, response=response, error_map=error_map)
            raise HttpResponseError(response=response, error_format=ARMErrorFormat)

        deserialized = self._deserialize('PolicyAssignment', pipeline_response)

        if cls:
            return cls(pipeline_response, deserialized, {})

        return deserialized

    create_by_id.metadata = {'url': '/{policyAssignmentId}'}  # type: ignore


    @distributed_trace
    def get_by_id(
        self,
        policy_assignment_id: str,
        **kwargs: Any
    ) -> "_models.PolicyAssignment":
        """Retrieves the policy assignment with the given ID.

        The operation retrieves the policy assignment with the given ID. Policy assignment IDs have
        this format:
        '{scope}/providers/Microsoft.Authorization/policyAssignments/{policyAssignmentName}'. Valid
        scopes are: management group (format:
        '/providers/Microsoft.Management/managementGroups/{managementGroup}'), subscription (format:
        '/subscriptions/{subscriptionId}'), resource group (format:
        '/subscriptions/{subscriptionId}/resourceGroups/{resourceGroupName}', or resource (format:
        '/subscriptions/{subscriptionId}/resourceGroups/{resourceGroupName}/providers/{resourceProviderNamespace}/[{parentResourcePath}/]{resourceType}/{resourceName}'.

        :param policy_assignment_id: The ID of the policy assignment to get. Use the format
         '{scope}/providers/Microsoft.Authorization/policyAssignments/{policyAssignmentName}'.
        :type policy_assignment_id: str
        :keyword callable cls: A custom type or function that will be passed the direct response
        :return: PolicyAssignment, or the result of cls(response)
        :rtype: ~azure.mgmt.resource.policy.v2020_09_01.models.PolicyAssignment
        :raises: ~azure.core.exceptions.HttpResponseError
        """
        cls = kwargs.pop('cls', None)  # type: ClsType["_models.PolicyAssignment"]
        error_map = {
            401: ClientAuthenticationError, 404: ResourceNotFoundError, 409: ResourceExistsError
        }
        error_map.update(kwargs.pop('error_map', {}))

        
        request = build_get_by_id_request(
            policy_assignment_id=policy_assignment_id,
            template_url=self.get_by_id.metadata['url'],
        )
        request = _convert_request(request)
        request.url = self._client.format_url(request.url)

        pipeline_response = self._client._pipeline.run(request, stream=False, **kwargs)
        response = pipeline_response.http_response

        if response.status_code not in [200]:
            map_error(status_code=response.status_code, response=response, error_map=error_map)
            raise HttpResponseError(response=response, error_format=ARMErrorFormat)

        deserialized = self._deserialize('PolicyAssignment', pipeline_response)

        if cls:
            return cls(pipeline_response, deserialized, {})

        return deserialized

    get_by_id.metadata = {'url': '/{policyAssignmentId}'}  # type: ignore

