Instruction:
Create a Python 3 function for
getting an element s properties

Response:
def _get_element_properties(name, element_type, server=None):
    '''
    Get an element's properties
    '''
    properties = {}
    data = _api_get('{0}/{1}/property'.format(element_type, name), server)

    # Get properties into a dict
    if any(data['extraProperties']['properties']):
        for element in data['extraProperties']['properties']:
            properties[element['name']] = element['value']
        return properties
    return {}


Instruction:
Make a summary of the following Python 3 code
def _get_element(name, element_type, server=None, with_properties=True):
    '''
    Get an element with or without properties
    '''
    element = {}
    name = quote(name, safe='')
    data = _api_get('{0}/{1}'.format(element_type, name), server)

    # Format data, get properties if asked, and return the whole thing
    if any(data['extraProperties']['entity']):
        for key, value in data['extraProperties']['entity'].items():
            element[key] = value
        if with_properties:
            element['properties'] = _get_element_properties(name, element_type)
        return element
    return None

Response: Get an element with or without properties


Instruction:
Can you generate the documentation for the following Python 3 function
def _create_element(name, element_type, data, server=None):
    '''
    Create a new element
    '''
    # Define property and id from name and properties + remove SaltStack parameters
    if 'properties' in data:
        data['property'] = ''
        for key, value in data['properties'].items():
            if not data['property']:
                data['property'] += '{0}={1}'.format(key, value.replace(':', '\\:'))
            else:
                data['property'] += ':{0}={1}'.format(key, value.replace(':', '\\:'))
        del data['properties']

    # Send request
    _api_post(element_type, _clean_data(data), server)
    return unquote(name)

Response: Create a new element in the order they appear in the element list.


Instruction:
Can you generate the documentation for the following Python 3 function
def _update_element(name, element_type, data, server=None):
    '''
    Update an element, including it's properties
    '''
    # Urlencode the name (names may have slashes)
    name = quote(name, safe='')

    # Update properties first
    if 'properties' in data:
        properties = []
        for key, value in data['properties'].items():
            properties.append({'name': key, 'value': value})
        _api_post('{0}/{1}/property'.format(element_type, name), properties, server)
        del data['properties']

        # If the element only contained properties
        if not data:
            return unquote(name)

    # Get the current data then merge updated data into it
    update_data = _get_element(name, element_type, server, with_properties=False)
    if update_data:
        update_data.update(data)
    else:
        __context__['retcode'] = salt.defaults.exitcodes.SALT_BUILD_FAIL
        raise CommandExecutionError('Cannot update {0}'.format(name))

    # Finally, update the element
    _api_post('{0}/{1}'.format(element_type, name), _clean_data(update_data), server)
    return unquote(name)

Response: Update an element including it s properties and properties


Instruction:
Here you have a function in Python 3, explain what it does
def _delete_element(name, element_type, data, server=None):
    '''
    Delete an element
    '''
    _api_delete('{0}/{1}'.format(element_type, quote(name, safe='')), data, server)
    return name

Response: Delete an element from the sequence.


Instruction:
Implement a function in Python 3 to
create a connection pool

Response:
def create_connector_c_pool(name, server=None, **kwargs):
    '''
    Create a connection pool
    '''
    defaults = {
        'connectionDefinitionName': 'javax.jms.ConnectionFactory',
        'resourceAdapterName': 'jmsra',
        'associateWithThread': False,
        'connectionCreationRetryAttempts': 0,
        'connectionCreationRetryIntervalInSeconds': 0,
        'connectionLeakReclaim': False,
        'connectionLeakTimeoutInSeconds': 0,
        'description': '',
        'failAllConnections': False,
        'id': name,
        'idleTimeoutInSeconds': 300,
        'isConnectionValidationRequired': False,
        'lazyConnectionAssociation': False,
        'lazyConnectionEnlistment': False,
        'matchConnections': True,
        'maxConnectionUsageCount': 0,
        'maxPoolSize': 32,
        'maxWaitTimeInMillis': 60000,
        'ping': False,
        'poolResizeQuantity': 2,
        'pooling': True,
        'steadyPoolSize': 8,
        'target': 'server',
        'transactionSupport': '',
        'validateAtmostOncePeriodInSeconds': 0
    }

    # Data = defaults + merge kwargs + remove salt
    data = defaults
    data.update(kwargs)

    # Check TransactionSupport against acceptable values
    if data['transactionSupport'] and data['transactionSupport'] not in (
               'XATransaction',
               'LocalTransaction',
               'NoTransaction'
       ):
        raise CommandExecutionError('Invalid transaction support')

    return _create_element(name, 'resources/connector-connection-pool', data, server)


Instruction:
Can you write a function in Python 3 where it
updates a connector connection pool

Response:
def update_connector_c_pool(name, server=None, **kwargs):
    '''
    Update a connection pool
    '''
    if 'transactionSupport' in kwargs and kwargs['transactionSupport'] not in (
               'XATransaction',
               'LocalTransaction',
               'NoTransaction'
       ):
        raise CommandExecutionError('Invalid transaction support')
    return _update_element(name, 'resources/connector-connection-pool', kwargs, server)


Instruction:
Explain what the following Python 3 code does
def delete_connector_c_pool(name, target='server', cascade=True, server=None):
    '''
    Delete a connection pool
    '''
    data = {'target': target, 'cascade': cascade}
    return _delete_element(name, 'resources/connector-connection-pool', data, server)

Response: Delete a connector connection pool.


Instruction:
Create a Python 3 function for
creating a connection resource

Response:
def create_connector_resource(name, server=None, **kwargs):
    '''
    Create a connection resource
    '''
    defaults = {
        'description': '',
        'enabled': True,
        'id': name,
        'poolName': '',
        'objectType': 'user',
        'target': 'server'
    }

    # Data = defaults + merge kwargs + poolname
    data = defaults
    data.update(kwargs)

    if not data['poolName']:
        raise CommandExecutionError('No pool name!')

    # Fix for lowercase vs camelCase naming differences
    for key, value in list(data.items()):
        del data[key]
        data[key.lower()] = value

    return _create_element(name, 'resources/connector-resource', data, server)


Instruction:
Implement a Python 3 function for
updating a connection resource

Response:
def update_connector_resource(name, server=None, **kwargs):
    '''
    Update a connection resource
    '''
    # You're not supposed to update jndiName, if you do so, it will crash, silently
    if 'jndiName' in kwargs:
        del kwargs['jndiName']
    return _update_element(name, 'resources/connector-resource', kwargs, server)


Instruction:
Create a Python 3 function for
creating a JMS destination resource

Response:
def create_admin_object_resource(name, server=None, **kwargs):
    '''
    Create a JMS destination
    '''
    defaults = {
        'description': '',
        'className': 'com.sun.messaging.Queue',
        'enabled': True,
        'id': name,
        'resAdapter': 'jmsra',
        'resType': 'javax.jms.Queue',
        'target': 'server'
    }

    # Data = defaults + merge kwargs + poolname
    data = defaults
    data.update(kwargs)

    # ClassName isn't optional, even if the API says so
    if data['resType'] == 'javax.jms.Queue':
        data['className'] = 'com.sun.messaging.Queue'
    elif data['resType'] == 'javax.jms.Topic':
        data['className'] = 'com.sun.messaging.Topic'
    else:
        raise CommandExecutionError('resType should be "javax.jms.Queue" or "javax.jms.Topic"!')

    if data['resAdapter'] != 'jmsra':
        raise CommandExecutionError('resAdapter should be "jmsra"!')

    # Fix for lowercase vs camelCase naming differences
    if 'resType' in data:
        data['restype'] = data['resType']
        del data['resType']
    if 'className' in data:
        data['classname'] = data['className']
        del data['className']

    return _create_element(name, 'resources/admin-object-resource', data, server)


Instruction:
Make a summary of the following Python 3 code
def update_admin_object_resource(name, server=None, **kwargs):
    '''
    Update a JMS destination
    '''
    if 'jndiName' in kwargs:
        del kwargs['jndiName']
    return _update_element(name, 'resources/admin-object-resource', kwargs, server)

Response: Update an admin object resource


Instruction:
Implement a function in Python 3 to
create a new JDBC connection pool.

Response:
def create_jdbc_connection_pool(name, server=None, **kwargs):
    '''
    Create a connection resource
    '''
    defaults = {
        'allowNonComponentCallers': False,
        'associateWithThread': False,
        'connectionCreationRetryAttempts': '0',
        'connectionCreationRetryIntervalInSeconds': '10',
        'connectionLeakReclaim': False,
        'connectionLeakTimeoutInSeconds': '0',
        'connectionValidationMethod': 'table',
        'datasourceClassname': '',
        'description': '',
        'driverClassname': '',
        'failAllConnections': False,
        'idleTimeoutInSeconds': '300',
        'initSql': '',
        'isConnectionValidationRequired': False,
        'isIsolationLevelGuaranteed': True,
        'lazyConnectionAssociation': False,
        'lazyConnectionEnlistment': False,
        'matchConnections': False,
        'maxConnectionUsageCount': '0',
        'maxPoolSize': '32',
        'maxWaitTimeInMillis': 60000,
        'name': name,
        'nonTransactionalConnections': False,
        'ping': False,
        'poolResizeQuantity': '2',
        'pooling': True,
        'resType': '',
        'sqlTraceListeners': '',
        'statementCacheSize': '0',
        'statementLeakReclaim': False,
        'statementLeakTimeoutInSeconds': '0',
        'statementTimeoutInSeconds': '-1',
        'steadyPoolSize': '8',
        'target': 'server',
        'transactionIsolationLevel': '',
        'validateAtmostOncePeriodInSeconds': '0',
        'validationClassname': '',
        'validationTableName': '',
        'wrapJdbcObjects': True
    }

    # Data = defaults + merge kwargs + poolname
    data = defaults
    data.update(kwargs)

    # Check resType against acceptable values
    if data['resType'] not in (
            'javax.sql.DataSource',
            'javax.sql.XADataSource',
            'javax.sql.ConnectionPoolDataSource',
            'java.sql.Driver'
       ):
        raise CommandExecutionError('Invalid resource type')

    # Check connectionValidationMethod against acceptable velues
    if data['connectionValidationMethod'] not in (
            'auto-commit',
            'meta-data',
            'table',
            'custom-validation'
       ):
        raise CommandExecutionError('Invalid connection validation method')

    if data['transactionIsolationLevel'] \
       and data['transactionIsolationLevel'] not in (
               'read-uncommitted',
               'read-committed',
               'repeatable-read',
               'serializable'
       ):
        raise CommandExecutionError('Invalid transaction isolation level')

    if not data['datasourceClassname'] \
       and data['resType'] in (
               'javax.sql.DataSource',
               'javax.sql.ConnectionPoolDataSource',
               'javax.sql.XADataSource'
       ):
        raise CommandExecutionError('No datasource class name while using datasource resType')
    if not data['driverClassname'] and data['resType'] == 'java.sql.Driver':
        raise CommandExecutionError('No driver class nime while using driver resType')

    return _create_element(name, 'resources/jdbc-connection-pool', data, server)


Instruction:
Can you tell what is the following Python 3 function doing
def delete_jdbc_connection_pool(name, target='server', cascade=False, server=None):
    '''
    Delete a JDBC pool
    '''
    data = {'target': target, 'cascade': cascade}
    return _delete_element(name, 'resources/jdbc-connection-pool', data, server)

Response: Delete a JDBC connection pool.


Instruction:
How would you code a function in Python 3 to
create a JDBC resource

Response:
def create_jdbc_resource(name, server=None, **kwargs):
    '''
    Create a JDBC resource
    '''
    defaults = {
        'description': '',
        'enabled': True,
        'id': name,
        'poolName': '',
        'target': 'server'
    }

    # Data = defaults + merge kwargs + poolname
    data = defaults
    data.update(kwargs)

    if not data['poolName']:
        raise CommandExecutionError('No pool name!')

    return _create_element(name, 'resources/jdbc-resource', data, server)


Instruction:
Write a Python 3 script to
update a JDBC resource

Response:
def update_jdbc_resource(name, server=None, **kwargs):
    '''
    Update a JDBC resource
    '''
    # You're not supposed to update jndiName, if you do so, it will crash, silently
    if 'jndiName' in kwargs:
        del kwargs['jndiName']
    return _update_element(name, 'resources/jdbc-resource', kwargs, server)


Instruction:
Create a Python 3 function for
getting system properties from the server

Response:
def get_system_properties(server=None):
    '''
    Get system properties
    '''
    properties = {}
    data = _api_get('system-properties', server)

    # Get properties into a dict
    if any(data['extraProperties']['systemProperties']):
        for element in data['extraProperties']['systemProperties']:
            properties[element['name']] = element['value']
        return properties
    return {}


Instruction:
Given the following Python 3 function, write the documentation
def present(name, auth=None, **kwargs):
    '''
    Ensure a network exists and is up-to-date

    name
        Name of the network

    provider
        A dict of network provider options.

    shared
        Set the network as shared.

    external
        Whether this network is externally accessible.

    admin_state_up
         Set the network administrative state to up.

    vlan
        Vlan ID. Alias for provider

        - physical_network: provider
        - network_type: vlan
        - segmentation_id: (vlan id)
    '''
    ret = {'name': name,
           'changes': {},
           'result': True,
           'comment': ''}

    kwargs = __utils__['args.clean_kwargs'](**kwargs)

    __salt__['neutronng.setup_clouds'](auth)

    kwargs['name'] = name
    network = __salt__['neutronng.network_get'](name=name)

    if network is None:
        if __opts__['test'] is True:
            ret['result'] = None
            ret['changes'] = kwargs
            ret['comment'] = 'Network will be created.'
            return ret

        if 'vlan' in kwargs:
            kwargs['provider'] = {"physical_network": "provider",
                                  "network_type": "vlan",
                                  "segmentation_id": kwargs['vlan']}
            del kwargs['vlan']

        if 'project' in kwargs:
            projectname = kwargs['project']
            project = __salt__['keystoneng.project_get'](name=projectname)
            if project:
                kwargs['project_id'] = project.id
                del kwargs['project']
            else:
                ret['result'] = False
                ret['comment'] = "Project:{} not found.".format(projectname)
                return ret

        network = __salt__['neutronng.network_create'](**kwargs)
        ret['changes'] = network
        ret['comment'] = 'Created network'
        return ret

    changes = __salt__['neutronng.compare_changes'](network, **kwargs)

    # there's no method for network update in shade right now;
    # can only delete and recreate
    if changes:
        if __opts__['test'] is True:
            ret['result'] = None
            ret['changes'] = changes
            ret['comment'] = 'Project will be updated.'
            return ret

        __salt__['neutronng.network_delete'](name=network)
        __salt__['neutronng.network_create'](**kwargs)
        ret['changes'].update(changes)
        ret['comment'] = 'Updated network'

    return ret

Response: Ensure a network exists and is up - to - date and is up - to - date.


Instruction:
Can you generate a brief explanation for the following Python 3 code
def absent(name, auth=None, **kwargs):
    '''
    Ensure a network does not exists

    name
        Name of the network

    '''
    ret = {'name': name,
           'changes': {},
           'result': True,
           'comment': ''}

    kwargs = __utils__['args.clean_kwargs'](**kwargs)

    __salt__['neutronng.setup_clouds'](auth)

    kwargs['name'] = name
    network = __salt__['neutronng.network_get'](name=name)

    if network:
        if __opts__['test'] is True:
            ret['result'] = None
            ret['changes'] = {'id': network.id}
            ret['comment'] = 'Network will be deleted.'
            return ret

        __salt__['neutronng.network_delete'](name=network)
        ret['changes']['id'] = network.id
        ret['comment'] = 'Deleted network'

    return ret

Response: Ensure a network does not exists


Instruction:
Write a Python 3 script for
splitting a smartos docker uuid into repo and tag

Response:
def _split_docker_uuid(uuid):
    '''
    Split a smartos docker uuid into repo and tag
    '''
    if uuid:
        uuid = uuid.split(':')
        if len(uuid) == 2:
            tag = uuid[1]
            repo = uuid[0]
            return repo, tag
    return None, None


Instruction:
Can you generate a brief explanation for the following Python 3 code
def _is_uuid(uuid):
    '''
    Check if uuid is a valid smartos uuid

    Example: e69a0918-055d-11e5-8912-e3ceb6df4cf8
    '''
    if uuid and list((len(x) for x in uuid.split('-'))) == [8, 4, 4, 4, 12]:
        return True
    return False

Response: Check if uuid is a valid smartos uuid


Instruction:
Make a summary of the following Python 3 code
def version():
    '''
    Return imgadm version

    CLI Example:

    .. code-block:: bash

        salt '*' imgadm.version
    '''
    ret = {}
    cmd = 'imgadm --version'
    res = __salt__['cmd.run'](cmd).splitlines()
    ret = res[0].split()
    return ret[-1]

Response:
Return imgadm version

    CLI Example:

    .. code-block:: bash

        salt '*' imgadm.version


Instruction:
Write a Python 3 function for
getting the image uuid from an imported docker image .. versionadded:: 2019. 2. 0

Response:
def docker_to_uuid(uuid):
    '''
    Get the image uuid from an imported docker image

    .. versionadded:: 2019.2.0
    '''
    if _is_uuid(uuid):
        return uuid
    if _is_docker_uuid(uuid):
        images = list_installed(verbose=True)
        for image_uuid in images:
            if 'name' not in images[image_uuid]:
                continue
            if images[image_uuid]['name'] == uuid:
                return image_uuid
    return None


Instruction:
Explain what the following Python 3 code does
def avail(search=None, verbose=False):
    '''
    Return a list of available images

    search : string
        search keyword
    verbose : boolean (False)
        toggle verbose output

    CLI Example:

    .. code-block:: bash

        salt '*' imgadm.avail [percona]
        salt '*' imgadm.avail verbose=True
    '''
    ret = {}
    cmd = 'imgadm avail -j'
    res = __salt__['cmd.run_all'](cmd)
    retcode = res['retcode']
    if retcode != 0:
        ret['Error'] = _exit_status(retcode)
        return ret

    for image in salt.utils.json.loads(res['stdout']):
        if image['manifest']['disabled'] or not image['manifest']['public']:
            continue
        if search and search not in image['manifest']['name']:
            # we skip if we are searching but don't have a match
            continue
        uuid = image['manifest']['uuid']
        data = _parse_image_meta(image, verbose)
        if data:
            ret[uuid] = data

    return ret

Response: Return a list of available images


Instruction:
Given the following Python 3 function, write the documentation
def show(uuid):
    '''
    Show manifest of a given image

    uuid : string
        uuid of image

    CLI Example:

    .. code-block:: bash

        salt '*' imgadm.show e42f8c84-bbea-11e2-b920-078fab2aab1f
        salt '*' imgadm.show plexinc/pms-docker:plexpass
    '''
    ret = {}

    if _is_uuid(uuid) or _is_docker_uuid(uuid):
        cmd = 'imgadm show {0}'.format(uuid)
        res = __salt__['cmd.run_all'](cmd, python_shell=False)
        retcode = res['retcode']
        if retcode != 0:
            ret['Error'] = _exit_status(retcode, res['stderr'])
        else:
            ret = salt.utils.json.loads(res['stdout'])
    else:
        ret['Error'] = "{} is not a valid uuid.".format(uuid)

    return ret

Response:
Show manifest of a given image
Taxonomy


Instruction:
Create a Python 3 function to
import an image from the repository

Response:
def import_image(uuid, verbose=False):
    '''
    Import an image from the repository

    uuid : string
        uuid to import
    verbose : boolean (False)
        toggle verbose output

    CLI Example:

    .. code-block:: bash

        salt '*' imgadm.import e42f8c84-bbea-11e2-b920-078fab2aab1f [verbose=True]
    '''
    ret = {}
    cmd = 'imgadm import {0}'.format(uuid)
    res = __salt__['cmd.run_all'](cmd, python_shell=False)
    retcode = res['retcode']
    if retcode != 0:
        ret['Error'] = _exit_status(retcode)
        return ret

    uuid = docker_to_uuid(uuid)
    data = _parse_image_meta(get(uuid), verbose)
    return {uuid: data}


Instruction:
Implement a Python 3 function for
removing an installed image

Response:
def delete(uuid):
    '''
    Remove an installed image

    uuid : string
        Specifies uuid to import

    CLI Example:

    .. code-block:: bash

        salt '*' imgadm.delete e42f8c84-bbea-11e2-b920-078fab2aab1f
    '''
    ret = {}
    cmd = 'imgadm delete {0}'.format(uuid)
    res = __salt__['cmd.run_all'](cmd, python_shell=False)
    retcode = res['retcode']
    if retcode != 0:
        ret['Error'] = _exit_status(retcode)
        return ret
    # output: Deleted image d5b3865c-0804-11e5-be21-dbc4ce844ddc
    result = []
    for image in res['stdout'].splitlines():
        image = [var for var in image.split(" ") if var]
        result.append(image[2])

    return result


Instruction:
Write a Python 3 function for
removing unused images from the vacuum image list

Response:
def vacuum(verbose=False):
    '''
    Remove unused images

    verbose : boolean (False)
        toggle verbose output

    CLI Example:

    .. code-block:: bash

        salt '*' imgadm.vacuum [verbose=True]
    '''
    ret = {}
    cmd = 'imgadm vacuum -f'
    res = __salt__['cmd.run_all'](cmd)
    retcode = res['retcode']
    if retcode != 0:
        ret['Error'] = _exit_status(retcode)
        return ret
    # output: Deleted image d5b3865c-0804-11e5-be21-dbc4ce844ddc (lx-centos-6@20150601)
    result = {}
    for image in res['stdout'].splitlines():
        image = [var for var in image.split(" ") if var]
        result[image[2]] = {
            'name': image[3][1:image[3].index('@')],
            'version': image[3][image[3].index('@')+1:-1]
        }
    if verbose:
        return result
    else:
        return list(result.keys())


Instruction:
How would you implement a function in Python 3 that
returns a list of available sources

Response:
def sources(verbose=False):
    '''
    Return a list of available sources

    verbose : boolean (False)
        toggle verbose output

    .. versionadded:: 2019.2.0

    CLI Example:

    .. code-block:: bash

        salt '*' imgadm.sources
    '''
    ret = {}
    cmd = 'imgadm sources -j'
    res = __salt__['cmd.run_all'](cmd)
    retcode = res['retcode']
    if retcode != 0:
        ret['Error'] = _exit_status(retcode)
        return ret

    for src in salt.utils.json.loads(res['stdout']):
        ret[src['url']] = src
        del src['url']

    if not verbose:
        ret = list(ret)

    return ret


Instruction:
Implement a Python 3 function for
deleting a source from the

Response:
def source_delete(source):
    '''
    Delete a source

    source : string
        source url to delete

    .. versionadded:: 2019.2.0

    CLI Example:

    .. code-block:: bash

        salt '*' imgadm.source_delete https://updates.joyent.com
    '''
    ret = {}
    cmd = 'imgadm sources -d {0}'.format(source)
    res = __salt__['cmd.run_all'](cmd)
    retcode = res['retcode']
    if retcode != 0:
        ret['Error'] = _exit_status(retcode, res['stderr'])
        return ret

    return sources(False)


Instruction:
Given the following Python 3 function, write the documentation
def source_add(source, source_type='imgapi'):
    '''
    Add a new source

    source : string
        source url to add
    source_trype : string (imgapi)
        source type, either imgapi or docker

    .. versionadded:: 2019.2.0

    CLI Example:

    .. code-block:: bash

        salt '*' imgadm.source_add https://updates.joyent.com
        salt '*' imgadm.source_add https://docker.io docker
    '''
    ret = {}

    # NOTE: there are some undocumented deprecated source types
    #       so we just warn instead of error on those
    if source_type not in ['imgapi', 'docker']:
        log.warning('Possible unsupported imgage source type specified!')

    cmd = 'imgadm sources -a {0} -t {1}'.format(source, source_type)
    res = __salt__['cmd.run_all'](cmd)
    retcode = res['retcode']
    if retcode != 0:
        ret['Error'] = _exit_status(retcode, res['stderr'])
        return ret

    return sources(False)

Response: Add a new source to the


Instruction:
Write a Python 3 function for
returning an object containing all the flags for dealing with Windows permissions and permissions.

Response:
def flags(instantiated=True):
    '''
    Helper function for instantiating a Flags object

    Args:

        instantiated (bool):
            True to return an instantiated object, False to return the object
            definition. Use False if inherited by another class. Default is
            True.

    Returns:
        object: An instance of the Flags object or its definition
    '''
    if not HAS_WIN32:
        return

    class Flags(object):
        '''
        Object containing all the flags for dealing with Windows permissions
        '''
        # Flag Dicts
        ace_perms = {
            'file': {
                'basic': {
                    0x1f01ff: 'Full control',
                    0x1301bf: 'Modify',
                    0x1201bf: 'Read & execute with write',
                    0x1200a9: 'Read & execute',
                    0x120089: 'Read',
                    0x100116: 'Write',
                    'full_control': 0x1f01ff,
                    'modify': 0x1301bf,
                    'read_execute': 0x1200a9,
                    'read': 0x120089,
                    'write': 0x100116,
                },
                'advanced': {
                    # Advanced
                    0x0001: 'List folder / read data',
                    0x0002: 'Create files / write data',
                    0x0004: 'Create folders / append data',
                    0x0008: 'Read extended attributes',
                    0x0010: 'Write extended attributes',
                    0x0020: 'Traverse folder / execute file',
                    0x0040: 'Delete subfolders and files',
                    0x0080: 'Read attributes',
                    0x0100: 'Write attributes',
                    0x10000: 'Delete',
                    0x20000: 'Read permissions',
                    0x40000: 'Change permissions',
                    0x80000: 'Take ownership',
                    # 0x100000: 'SYNCHRONIZE',  # This is in all of them
                    'list_folder': 0x0001,
                    'read_data': 0x0001,
                    'create_files': 0x0002,
                    'write_data': 0x0002,
                    'create_folders': 0x0004,
                    'append_data': 0x0004,
                    'read_ea': 0x0008,
                    'write_ea': 0x0010,
                    'traverse_folder': 0x0020,
                    'execute_file': 0x0020,
                    'delete_subfolders_files': 0x0040,
                    'read_attributes': 0x0080,
                    'write_attributes': 0x0100,
                    'delete': 0x10000,
                    'read_permissions': 0x20000,
                    'change_permissions': 0x40000,
                    'take_ownership': 0x80000,
                },
            },
            'registry': {
                'basic': {
                    0xf003f: 'Full Control',
                    0x20019: 'Read',
                    0x20006: 'Write',
                    # Generic Values (These sometimes get hit)
                    0x10000000: 'Full Control',
                    0x20000000: 'Execute',
                    0x40000000: 'Write',
                    0xffffffff80000000: 'Read',
                    'full_control': 0xf003f,
                    'read': 0x20019,
                    'write': 0x20006,
                },
                'advanced': {
                    # Advanced
                    0x0001: 'Query Value',
                    0x0002: 'Set Value',
                    0x0004: 'Create Subkey',
                    0x0008: 'Enumerate Subkeys',
                    0x0010: 'Notify',
                    0x0020: 'Create Link',
                    0x10000: 'Delete',
                    0x20000: 'Read Control',
                    0x40000: 'Write DAC',
                    0x80000: 'Write Owner',
                    'query_value': 0x0001,
                    'set_value': 0x0002,
                    'create_subkey': 0x0004,
                    'enum_subkeys': 0x0008,
                    'notify': 0x0010,
                    'create_link': 0x0020,
                    'delete': 0x10000,
                    'read_control': 0x20000,
                    'write_dac': 0x40000,
                    'write_owner': 0x80000,
                },
            },
            'share': {
                'basic': {
                    0x1f01ff: 'Full control',
                    0x1301bf: 'Change',
                    0x1200a9: 'Read',
                    'full_control': 0x1f01ff,
                    'change': 0x1301bf,
                    'read': 0x1200a9,
                },
                'advanced': {},  # No 'advanced' for shares, needed for lookup
            },
            'printer': {
                'basic': {
                    0x20008: 'Print',
                    0xf000c: 'Manage this printer',
                    0xf0030: 'Manage documents',
                    'print': 0x20008,
                    'manage_printer': 0xf000c,
                    'manage_documents': 0xf0030,
                },
                'advanced': {
                    # Advanced
                    0x10004: 'Manage this printer',
                    0x0008: 'Print',
                    0x20000: 'Read permissions',
                    0x40000: 'Change permissions',
                    0x80000: 'Take ownership',
                    'manage_printer': 0x10004,
                    'print': 0x0008,
                    'read_permissions': 0x20000,
                    'change_permissions': 0x40000,
                    'take_ownership': 0x80000,
                },
            },
            'service': {
                'basic': {
                    0xf01ff: 'Full Control',
                    0x2008f: 'Read & Write',
                    0x2018d: 'Read',
                    0x20002: 'Write',
                    'full_control': 0xf01ff,
                    'read_write': 0x2008f,
                    'read': 0x2018d,
                    'write': 0x20002,
                },
                'advanced': {
                    0x0001: 'Query Config',
                    0x0002: 'Change Config',
                    0x0004: 'Query Status',
                    0x0008: 'Enumerate Dependents',
                    0x0010: 'Start',
                    0x0020: 'Stop',
                    0x0040: 'Pause/Resume',
                    0x0080: 'Interrogate',
                    0x0100: 'User-Defined Control',
                    # 0x10000: 'Delete',  # Not visible in the GUI
                    0x20000: 'Read Permissions',
                    0x40000: 'Change Permissions',
                    0x80000: 'Change Owner',
                    'query_config': 0x0001,
                    'change_config': 0x0002,
                    'query_status': 0x0004,
                    'enum_dependents': 0x0008,
                    'start': 0x0010,
                    'stop': 0x0020,
                    'pause_resume': 0x0040,
                    'interrogate': 0x0080,
                    'user_defined': 0x0100,
                    'read_permissions': 0x20000,
                    'change_permissions': 0x40000,
                    'change_owner': 0x80000,
                },
            }
        }

        # These denote inheritance
        # 0x0000 : Not inherited, I don't know the enumeration for this
        # 0x0010 : win32security.INHERITED_ACE

        # All the values in the dict below are combinations of the following
        # enumerations or'ed together
        # 0x0001 : win32security.OBJECT_INHERIT_ACE
        # 0x0002 : win32security.CONTAINER_INHERIT_ACE
        # 0x0004 : win32security.NO_PROPAGATE_INHERIT_ACE
        # 0x0008 : win32security.INHERIT_ONLY_ACE
        ace_prop = {
            'file': {
                # for report
                0x0000: 'Not Inherited (file)',
                0x0001: 'This folder and files',
                0x0002: 'This folder and subfolders',
                0x0003: 'This folder, subfolders and files',
                0x0006: 'This folder only',
                0x0009: 'Files only',
                0x000a: 'Subfolders only',
                0x000b: 'Subfolders and files only',
                0x0010: 'Inherited (file)',
                # for setting
                'this_folder_only': 0x0006,
                'this_folder_subfolders_files': 0x0003,
                'this_folder_subfolders': 0x0002,
                'this_folder_files': 0x0001,
                'subfolders_files': 0x000b,
                'subfolders_only': 0x000a,
                'files_only': 0x0009,
            },
            'registry': {
                0x0000: 'Not Inherited',
                0x0002: 'This key and subkeys',
                0x0006: 'This key only',
                0x000a: 'Subkeys only',
                0x0010: 'Inherited',
                'this_key_only': 0x0006,
                'this_key_subkeys': 0x0002,
                'subkeys_only': 0x000a,
            },
            'registry32': {
                0x0000: 'Not Inherited',
                0x0002: 'This key and subkeys',
                0x0006: 'This key only',
                0x000a: 'Subkeys only',
                0x0010: 'Inherited',
                'this_key_only': 0x0006,
                'this_key_subkeys': 0x0002,
                'subkeys_only': 0x000a,
            },
        }

        ace_type = {
            'grant': win32security.ACCESS_ALLOWED_ACE_TYPE,
            'deny': win32security.ACCESS_DENIED_ACE_TYPE,
            win32security.ACCESS_ALLOWED_ACE_TYPE: 'grant',
            win32security.ACCESS_DENIED_ACE_TYPE: 'deny',
        }

        element = {
            'dacl': win32security.DACL_SECURITY_INFORMATION,
            'group': win32security.GROUP_SECURITY_INFORMATION,
            'owner': win32security.OWNER_SECURITY_INFORMATION,
        }

        inheritance = {
            'protected': win32security.PROTECTED_DACL_SECURITY_INFORMATION,
            'unprotected': win32security.UNPROTECTED_DACL_SECURITY_INFORMATION,
        }

        obj_type = {
            'file': win32security.SE_FILE_OBJECT,
            'service': win32security.SE_SERVICE,
            'printer': win32security.SE_PRINTER,
            'registry': win32security.SE_REGISTRY_KEY,
            'registry32': win32security.SE_REGISTRY_WOW64_32KEY,
            'share': win32security.SE_LMSHARE,
        }

    return Flags() if instantiated else Flags


Instruction:
Create a Python 3 function to
return a new DACL object.

Response:
def dacl(obj_name=None, obj_type='file'):
    '''
    Helper function for instantiating a Dacl class.

    Args:

        obj_name (str):
            The full path to the object. If None, a blank DACL will be created.
            Default is None.

        obj_type (str):
            The type of object. Default is 'File'

    Returns:
        object: An instantiated Dacl object
    '''

    if not HAS_WIN32:
        return

    class Dacl(flags(False)):
        '''
        DACL Object
        '''
        def __init__(self, obj_name=None, obj_type='file'):
            '''
            Either load the DACL from the passed object or create an empty DACL.
            If `obj_name` is not passed, an empty DACL is created.

            Args:

                obj_name (str):
                    The full path to the object. If None, a blank DACL will be
                    created

                obj_type (Optional[str]):
                    The type of object.

            Returns:
                obj: A DACL object

            Usage:

            .. code-block:: python

                # Create an Empty DACL
                dacl = Dacl(obj_type=obj_type)

                # Load the DACL of the named object
                dacl = Dacl(obj_name, obj_type)
            '''
            # Validate obj_type
            if obj_type.lower() not in self.obj_type:
                raise SaltInvocationError(
                    'Invalid "obj_type" passed: {0}'.format(obj_type))

            self.dacl_type = obj_type.lower()

            if obj_name is None:
                self.dacl = win32security.ACL()
            else:
                if 'registry' in self.dacl_type:
                    obj_name = self.get_reg_name(obj_name)

                try:
                    sd = win32security.GetNamedSecurityInfo(
                        obj_name, self.obj_type[self.dacl_type], self.element['dacl'])
                except pywintypes.error as exc:
                    if 'The system cannot find' in exc.strerror:
                        msg = 'System cannot find {0}'.format(obj_name)
                        log.exception(msg)
                        raise CommandExecutionError(msg)
                    raise

                self.dacl = sd.GetSecurityDescriptorDacl()
                if self.dacl is None:
                    self.dacl = win32security.ACL()

        def get_reg_name(self, obj_name):
            '''
            Take the obj_name and convert the hive to a valid registry hive.

            Args:

                obj_name (str):
                    The full path to the registry key including the hive, eg:
                    ``HKLM\\SOFTWARE\\salt``. Valid options for the hive are:

                    - HKEY_LOCAL_MACHINE
                    - MACHINE
                    - HKLM
                    - HKEY_USERS
                    - USERS
                    - HKU
                    - HKEY_CURRENT_USER
                    - CURRENT_USER
                    - HKCU
                    - HKEY_CLASSES_ROOT
                    - CLASSES_ROOT
                    - HKCR

            Returns:
                str:
                    The full path to the registry key in the format expected by
                    the Windows API

            Usage:

            .. code-block:: python

                import salt.utils.win_dacl
                dacl = salt.utils.win_dacl.Dacl()
                valid_key = dacl.get_reg_name('HKLM\\SOFTWARE\\salt')

                # Returns: MACHINE\\SOFTWARE\\salt
            '''
            # Make sure the hive is correct
            # Should be MACHINE, USERS, CURRENT_USER, or CLASSES_ROOT
            hives = {
                # MACHINE
                'HKEY_LOCAL_MACHINE': 'MACHINE',
                'MACHINE': 'MACHINE',
                'HKLM': 'MACHINE',
                # USERS
                'HKEY_USERS': 'USERS',
                'USERS': 'USERS',
                'HKU': 'USERS',
                # CURRENT_USER
                'HKEY_CURRENT_USER': 'CURRENT_USER',
                'CURRENT_USER': 'CURRENT_USER',
                'HKCU': 'CURRENT_USER',
                # CLASSES ROOT
                'HKEY_CLASSES_ROOT': 'CLASSES_ROOT',
                'CLASSES_ROOT': 'CLASSES_ROOT',
                'HKCR': 'CLASSES_ROOT',
            }
            reg = obj_name.split('\\')
            passed_hive = reg.pop(0)

            try:
                valid_hive = hives[passed_hive.upper()]
            except KeyError:
                log.exception('Invalid Registry Hive: %s', passed_hive)
                raise CommandExecutionError(
                    'Invalid Registry Hive: {0}'.format(passed_hive))

            reg.insert(0, valid_hive)

            return r'\\'.join(reg)

        def add_ace(self, principal, access_mode, permissions, applies_to):
            '''
            Add an ACE to the DACL

            Args:

                principal (str):
                    The sid of the user/group to for the ACE

                access_mode (str):
                    Determines the type of ACE to add. Must be either ``grant``
                    or ``deny``.

                permissions (str, list):
                    The type of permissions to grant/deny the user. Can be one
                    of the basic permissions, or a list of advanced permissions.

                applies_to (str):
                    The objects to which these permissions will apply. Not all
                    these options apply to all object types.

            Returns:
                bool: True if successful, otherwise False

            Usage:

            .. code-block:: python

                dacl = Dacl(obj_type=obj_type)
                dacl.add_ace(sid, access_mode, permission, applies_to)
                dacl.save(obj_name, protected)
            '''
            sid = get_sid(principal)

            if self.dacl is None:
                raise SaltInvocationError(
                    'You must load the DACL before adding an ACE')

            # Get the permission flag
            perm_flag = 0
            if isinstance(permissions, six.string_types):
                try:
                    perm_flag = self.ace_perms[self.dacl_type]['basic'][permissions]
                except KeyError as exc:
                    msg = 'Invalid permission specified: {0}'.format(permissions)
                    log.exception(msg)
                    raise CommandExecutionError(msg, exc)
            else:
                try:
                    for perm in permissions:
                        perm_flag |= self.ace_perms[self.dacl_type]['advanced'][perm]
                except KeyError as exc:
                    msg = 'Invalid permission specified: {0}'.format(perm)
                    log.exception(msg)
                    raise CommandExecutionError(msg, exc)

            if access_mode.lower() not in ['grant', 'deny']:
                raise SaltInvocationError('Invalid Access Mode: {0}'.format(access_mode))

            # Add ACE to the DACL
            # Grant or Deny
            try:
                if access_mode.lower() == 'grant':
                    self.dacl.AddAccessAllowedAceEx(
                        win32security.ACL_REVISION_DS,
                        # Some types don't support propagation
                        # May need to use 0x0000 instead of None
                        self.ace_prop.get(self.dacl_type, {}).get(applies_to),
                        perm_flag,
                        sid)
                elif access_mode.lower() == 'deny':
                    self.dacl.AddAccessDeniedAceEx(
                        win32security.ACL_REVISION_DS,
                        self.ace_prop.get(self.dacl_type, {}).get(applies_to),
                        perm_flag,
                        sid)
                else:
                    log.exception('Invalid access mode: %s', access_mode)
                    raise SaltInvocationError(
                        'Invalid access mode: {0}'.format(access_mode))
            except Exception as exc:
                return False, 'Error: {0}'.format(exc)

            return True

        def order_acl(self):
            '''
            Put the ACEs in the ACL in the proper order. This is necessary
            because the add_ace function puts ACEs at the end of the list
            without regard for order. This will cause the following Windows
            Security dialog to appear when viewing the security for the object:

            ``The permissions on Directory are incorrectly ordered, which may
            cause some entries to be ineffective.``

            .. note:: Run this function after adding all your ACEs.

            Proper Orders is as follows:

                1. Implicit Deny
                2. Inherited Deny
                3. Implicit Deny Object
                4. Inherited Deny Object
                5. Implicit Allow
                6. Inherited Allow
                7. Implicit Allow Object
                8. Inherited Allow Object

            Usage:

            .. code-block:: python

                dacl = Dacl(obj_type=obj_type)
                dacl.add_ace(sid, access_mode, applies_to, permission)
                dacl.order_acl()
                dacl.save(obj_name, protected)
            '''
            new_dacl = Dacl()
            deny_dacl = Dacl()
            deny_obj_dacl = Dacl()
            allow_dacl = Dacl()
            allow_obj_dacl = Dacl()

            # Load Non-Inherited ACEs first
            for i in range(0, self.dacl.GetAceCount()):
                ace = self.dacl.GetAce(i)
                if ace[0][1] & win32security.INHERITED_ACE == 0:
                    if ace[0][0] == win32security.ACCESS_DENIED_ACE_TYPE:
                        deny_dacl.dacl.AddAccessDeniedAceEx(
                            win32security.ACL_REVISION_DS,
                            ace[0][1],
                            ace[1],
                            ace[2])
                    elif ace[0][0] == win32security.ACCESS_DENIED_OBJECT_ACE_TYPE:
                        deny_obj_dacl.dacl.AddAccessDeniedAceEx(
                            win32security.ACL_REVISION_DS,
                            ace[0][1],
                            ace[1],
                            ace[2])
                    elif ace[0][0] == win32security.ACCESS_ALLOWED_ACE_TYPE:
                        allow_dacl.dacl.AddAccessAllowedAceEx(
                            win32security.ACL_REVISION_DS,
                            ace[0][1],
                            ace[1],
                            ace[2])
                    elif ace[0][0] == win32security.ACCESS_ALLOWED_OBJECT_ACE_TYPE:
                        allow_obj_dacl.dacl.AddAccessAllowedAceEx(
                            win32security.ACL_REVISION_DS,
                            ace[0][1],
                            ace[1],
                            ace[2])

            # Load Inherited ACEs last
            for i in range(0, self.dacl.GetAceCount()):
                ace = self.dacl.GetAce(i)
                if ace[0][1] & win32security.INHERITED_ACE == \
                        win32security.INHERITED_ACE:
                    ace_prop = ace[0][1] ^ win32security.INHERITED_ACE
                    if ace[0][0] == win32security.ACCESS_DENIED_ACE_TYPE:
                        deny_dacl.dacl.AddAccessDeniedAceEx(
                            win32security.ACL_REVISION_DS,
                            ace_prop,
                            ace[1],
                            ace[2])
                    elif ace[0][0] == win32security.ACCESS_DENIED_OBJECT_ACE_TYPE:
                        deny_obj_dacl.dacl.AddAccessDeniedAceEx(
                            win32security.ACL_REVISION_DS,
                            ace_prop,
                            ace[1],
                            ace[2])
                    elif ace[0][0] == win32security.ACCESS_ALLOWED_ACE_TYPE:
                        allow_dacl.dacl.AddAccessAllowedAceEx(
                            win32security.ACL_REVISION_DS,
                            ace_prop,
                            ace[1],
                            ace[2])
                    elif ace[0][0] == win32security.ACCESS_ALLOWED_OBJECT_ACE_TYPE:
                        allow_obj_dacl.dacl.AddAccessAllowedAceEx(
                            win32security.ACL_REVISION_DS,
                            ace_prop,
                            ace[1],
                            ace[2])

            # Combine ACEs in the proper order
            # Deny, Deny Object, Allow, Allow Object
            # Deny
            for i in range(0, deny_dacl.dacl.GetAceCount()):
                ace = deny_dacl.dacl.GetAce(i)
                new_dacl.dacl.AddAccessDeniedAceEx(
                    win32security.ACL_REVISION_DS,
                    ace[0][1],
                    ace[1],
                    ace[2])

            # Deny Object
            for i in range(0, deny_obj_dacl.dacl.GetAceCount()):
                ace = deny_obj_dacl.dacl.GetAce(i)
                new_dacl.dacl.AddAccessDeniedAceEx(
                    win32security.ACL_REVISION_DS,
                    ace[0][1] ^ win32security.INHERITED_ACE,
                    ace[1],
                    ace[2])

            # Allow
            for i in range(0, allow_dacl.dacl.GetAceCount()):
                ace = allow_dacl.dacl.GetAce(i)
                new_dacl.dacl.AddAccessAllowedAceEx(
                    win32security.ACL_REVISION_DS,
                    ace[0][1],
                    ace[1],
                    ace[2])

            # Allow Object
            for i in range(0, allow_obj_dacl.dacl.GetAceCount()):
                ace = allow_obj_dacl.dacl.GetAce(i)
                new_dacl.dacl.AddAccessAllowedAceEx(
                    win32security.ACL_REVISION_DS,
                    ace[0][1] ^ win32security.INHERITED_ACE,
                    ace[1],
                    ace[2])

            # Set the new dacl
            self.dacl = new_dacl.dacl

        def get_ace(self, principal):
            '''
            Get the ACE for a specific principal.

            Args:

                principal (str):
                    The name of the user or group for which to get the ace. Can
                    also be a SID.

            Returns:
                dict: A dictionary containing the ACEs found for the principal

            Usage:

            .. code-block:: python

                dacl = Dacl(obj_type=obj_type)
                dacl.get_ace()
            '''
            principal = get_name(principal)
            aces = self.list_aces()

            # Filter for the principal
            ret = {}
            for inheritance in aces:
                if principal in aces[inheritance]:
                    ret[inheritance] = {principal: aces[inheritance][principal]}

            return ret

        def list_aces(self):
            '''
            List all Entries in the dacl.

            Returns:
                dict: A dictionary containing the ACEs for the object

            Usage:

            .. code-block:: python

                dacl = Dacl('C:\\Temp')
                dacl.list_aces()
            '''
            ret = {'Inherited': {},
                   'Not Inherited': {}}

            # loop through each ACE in the DACL
            for i in range(0, self.dacl.GetAceCount()):
                ace = self.dacl.GetAce(i)

                # Get ACE Elements
                user, a_type, a_prop, a_perms, inheritance = self._ace_to_dict(ace)

                if user in ret[inheritance]:
                    ret[inheritance][user][a_type] = {
                        'applies to': a_prop,
                        'permissions': a_perms,
                    }
                else:
                    ret[inheritance][user] = {
                        a_type: {
                            'applies to': a_prop,
                            'permissions': a_perms,
                        }}

            return ret

        def _ace_to_dict(self, ace):
            '''
            Helper function for creating the ACE return dictionary
            '''
            # Get the principal from the sid (object sid)
            sid = win32security.ConvertSidToStringSid(ace[2])
            try:
                principal = get_name(sid)
            except CommandExecutionError:
                principal = sid

            # Get the ace type
            ace_type = self.ace_type[ace[0][0]]

            # Is the inherited ace flag present
            inherited = ace[0][1] & win32security.INHERITED_ACE == 16

            # Ace Propagation
            ace_prop = 'NA'

            # Get the ace propagation properties
            if self.dacl_type in ['file', 'registry', 'registry32']:

                ace_prop = ace[0][1]

                # Remove the inherited ace flag and get propagation
                if inherited:
                    ace_prop = ace[0][1] ^ win32security.INHERITED_ACE

                # Lookup the propagation
                try:
                    ace_prop = self.ace_prop[self.dacl_type][ace_prop]
                except KeyError:
                    ace_prop = 'Unknown propagation'

            # Get the object type
            obj_type = 'registry' if self.dacl_type == 'registry32' \
                else self.dacl_type

            # Get the ace permissions
            # Check basic permissions first
            ace_perms = self.ace_perms[obj_type]['basic'].get(ace[1], [])

            # If it didn't find basic perms, check advanced permissions
            if not ace_perms:
                ace_perms = []
                for perm in self.ace_perms[obj_type]['advanced']:
                    # Don't match against the string perms
                    if isinstance(perm, six.string_types):
                        continue
                    if ace[1] & perm == perm:
                        ace_perms.append(
                            self.ace_perms[obj_type]['advanced'][perm])

            # If still nothing, it must be undefined
            if not ace_perms:
                ace_perms = ['Undefined Permission: {0}'.format(ace[1])]

            return principal, ace_type, ace_prop, ace_perms, \
                   'Inherited' if inherited else 'Not Inherited'

        def rm_ace(self, principal, ace_type='all'):
            '''
            Remove a specific ACE from the DACL.

            Args:

                principal (str):
                    The user whose ACE to remove. Can be the user name or a SID.

                ace_type (str):
                    The type of ACE to remove. If not specified, all ACEs will
                    be removed. Default is 'all'. Valid options are:

                    - 'grant'
                    - 'deny'
                    - 'all'

            Returns:
                list: List of removed aces

            Usage:

            .. code-block:: python

                dacl = Dacl(obj_name='C:\\temp', obj_type='file')
                dacl.rm_ace('Users')
                dacl.save(obj_name='C:\\temp')
            '''
            sid = get_sid(principal)
            offset = 0
            ret = []

            for i in range(0, self.dacl.GetAceCount()):
                ace = self.dacl.GetAce(i - offset)

                # Is the inherited ace flag present
                inherited = ace[0][1] & win32security.INHERITED_ACE == 16

                if ace[2] == sid and not inherited:
                    if self.ace_type[ace[0][0]] == ace_type.lower() or \
                            ace_type == 'all':
                        self.dacl.DeleteAce(i - offset)
                        ret.append(self._ace_to_dict(ace))
                        offset += 1

            if not ret:
                ret = ['ACE not found for {0}'.format(principal)]

            return ret

        def save(self, obj_name, protected=None):
            '''
            Save the DACL

            Args:

                obj_name (str):
                    The object for which to set permissions. This can be the
                    path to a file or folder, a registry key, printer, etc. For
                    more information about how to format the name see:

                    https://msdn.microsoft.com/en-us/library/windows/desktop/aa379593(v=vs.85).aspx

                protected (Optional[bool]):
                    True will disable inheritance for the object. False will
                    enable inheritance. None will make no change. Default is
                    ``None``.

            Returns:
                bool: True if successful, Otherwise raises an exception

            Usage:

            .. code-block:: python

                dacl = Dacl(obj_type='file')
                dacl.save('C:\\Temp', True)
            '''
            sec_info = self.element['dacl']

            if protected is not None:
                if protected:
                    sec_info = sec_info | self.inheritance['protected']
                else:
                    sec_info = sec_info | self.inheritance['unprotected']

            if self.dacl_type in ['registry', 'registry32']:
                obj_name = self.get_reg_name(obj_name)

            try:
                win32security.SetNamedSecurityInfo(
                    obj_name,
                    self.obj_type[self.dacl_type],
                    sec_info,
                    None, None, self.dacl, None)
            except pywintypes.error as exc:
                raise CommandExecutionError(
                    'Failed to set permissions: {0}'.format(obj_name),
                    exc.strerror)

            return True

    return Dacl(obj_name, obj_type)


Instruction:
Can you write a function in Python 3 where it
returns a sid or a sid from a user s name or a sid.

Response:
def get_sid(principal):
    '''
    Converts a username to a sid, or verifies a sid. Required for working with
    the DACL.

    Args:

        principal(str):
            The principal to lookup the sid. Can be a sid or a username.

    Returns:
        PySID Object: A sid

    Usage:

    .. code-block:: python

        # Get a user's sid
        salt.utils.win_dacl.get_sid('jsnuffy')

        # Verify that the sid is valid
        salt.utils.win_dacl.get_sid('S-1-5-32-544')
    '''
    # If None is passed, use the Universal Well-known SID "Null SID"
    if principal is None:
        principal = 'NULL SID'

    # Test if the user passed a sid or a name
    try:
        sid = salt.utils.win_functions.get_sid_from_name(principal)
    except CommandExecutionError:
        sid = principal

    # Test if the SID is valid
    try:
        sid = win32security.ConvertStringSidToSid(sid)
    except pywintypes.error:
        log.exception('Invalid user/group or sid: %s', principal)
        raise CommandExecutionError(
            'Invalid user/group or sid: {0}'.format(principal))
    except TypeError:
        raise CommandExecutionError

    return sid


Instruction:
How would you implement a function in Python 3 that
converts a PySID object to a string SID.

Response:
def get_sid_string(principal):
    '''
    Converts a PySID object to a string SID.

    Args:

        principal(str):
            The principal to lookup the sid. Must be a PySID object.

    Returns:
        str: A string sid

    Usage:

    .. code-block:: python

        # Get a PySID object
        py_sid = salt.utils.win_dacl.get_sid('jsnuffy')

        # Get the string version of the SID
        salt.utils.win_dacl.get_sid_string(py_sid)
    '''
    # If None is passed, use the Universal Well-known SID "Null SID"
    if principal is None:
        principal = 'NULL SID'

    try:
        return win32security.ConvertSidToStringSid(principal)
    except TypeError:
        # Not a PySID object
        principal = get_sid(principal)

    try:
        return win32security.ConvertSidToStringSid(principal)
    except pywintypes.error:
        log.exception('Invalid principal %s', principal)
        raise CommandExecutionError('Invalid principal {0}'.format(principal))


Instruction:
Write a Python 3 function that can
get the name from the specified principal.

Response:
def get_name(principal):
    '''
    Gets the name from the specified principal.

    Args:

        principal (str):
            Find the Normalized name based on this. Can be a PySID object, a SID
            string, or a user name in any capitalization.

            .. note::
                Searching based on the user name can be slow on hosts connected
                to large Active Directory domains.

    Returns:
        str: The name that corresponds to the passed principal

    Usage:

    .. code-block:: python

        salt.utils.win_dacl.get_name('S-1-5-32-544')
        salt.utils.win_dacl.get_name('adminisTrators')
    '''
    # If this is a PySID object, use it
    if isinstance(principal, pywintypes.SIDType):
        sid_obj = principal
    else:
        # If None is passed, use the Universal Well-known SID for "Null SID"
        if principal is None:
            principal = 'S-1-0-0'
        # Try Converting String SID to SID Object first as it's least expensive
        try:
            sid_obj = win32security.ConvertStringSidToSid(principal)
        except pywintypes.error:
            # Try Getting the SID Object by Name Lookup last
            # This is expensive, especially on large AD Domains
            try:
                sid_obj = win32security.LookupAccountName(None, principal)[0]
            except pywintypes.error:
                # This is not a PySID object, a SID String, or a valid Account
                # Name. Just pass it and let the LookupAccountSid function try
                # to resolve it
                sid_obj = principal

    # By now we should have a valid PySID object
    try:
        return win32security.LookupAccountSid(None, sid_obj)[0]
    except (pywintypes.error, TypeError) as exc:
        message = 'Error resolving "{0}"'.format(principal)
        if type(exc) == pywintypes.error:
            win_error = win32api.FormatMessage(exc.winerror).rstrip('\n')
            message = '{0}: {1}'.format(message, win_error)
        log.exception(message)
        raise CommandExecutionError(message, exc)


Instruction:
Explain what the following Python 3 code does
def get_primary_group(obj_name, obj_type='file'):
    r'''
    Gets the primary group of the passed object

    Args:

        obj_name (str):
            The path for which to obtain primary group information

        obj_type (str):
            The type of object to query. This value changes the format of the
            ``obj_name`` parameter as follows:

            - file: indicates a file or directory
                - a relative path, such as ``FileName.txt`` or ``..\FileName``
                - an absolute path, such as ``C:\DirName\FileName.txt``
                - A UNC name, such as ``\\ServerName\ShareName\FileName.txt``
            - service: indicates the name of a Windows service
            - printer: indicates the name of a printer
            - registry: indicates a registry key
                - Uses the following literal strings to denote the hive:
                    - HKEY_LOCAL_MACHINE
                    - MACHINE
                    - HKLM
                    - HKEY_USERS
                    - USERS
                    - HKU
                    - HKEY_CURRENT_USER
                    - CURRENT_USER
                    - HKCU
                    - HKEY_CLASSES_ROOT
                    - CLASSES_ROOT
                    - HKCR
                - Should be in the format of ``HIVE\Path\To\Key``. For example,
                    ``HKLM\SOFTWARE\Windows``
            - registry32: indicates a registry key under WOW64. Formatting is
                the same as it is for ``registry``
            - share: indicates a network share

    Returns:
        str: The primary group for the object

    Usage:

    .. code-block:: python

        salt.utils.win_dacl.get_primary_group('c:\\file')
    '''
    # Not all filesystems mountable within windows have SecurityDescriptors.
    # For instance, some mounted SAMBA shares, or VirtualBox shared folders. If
    # we can't load a file descriptor for the file, we default to "Everyone"
    # http://support.microsoft.com/kb/243330

    # Validate obj_type
    try:
        obj_type_flag = flags().obj_type[obj_type.lower()]
    except KeyError:
        raise SaltInvocationError(
            'Invalid "obj_type" passed: {0}'.format(obj_type))

    if 'registry' in obj_type.lower():
        obj_name = dacl().get_reg_name(obj_name)
        log.debug('Name converted to: %s', obj_name)

    try:
        security_descriptor = win32security.GetNamedSecurityInfo(
            obj_name, obj_type_flag, win32security.GROUP_SECURITY_INFORMATION)
        primary_group_gid = security_descriptor.GetSecurityDescriptorGroup()

    except MemoryError:
        # Generic Memory Error (Windows Server 2003+)
        primary_group_gid = 'S-1-0-0'

    except pywintypes.error as exc:
        # Incorrect function error (Windows Server 2008+)
        if exc.winerror == 1 or exc.winerror == 50:
            primary_group_gid = 'S-1-0-0'
        else:
            log.exception('Failed to get the primary group: %s', obj_name)
            raise CommandExecutionError(
                'Failed to get primary group: {0}'.format(obj_name),
                exc.strerror)

    return get_name(win32security.ConvertSidToStringSid(primary_group_gid))

Response: r Returns the primary group of the passed object.


Instruction:
How would you explain what the following Python 3 function does
def set_owner(obj_name, principal, obj_type='file'):
    '''
    Set the owner of an object. This can be a file, folder, registry key,
    printer, service, etc...

    Args:

        obj_name (str):
            The object for which to set owner. This can be the path to a file or
            folder, a registry key, printer, etc. For more information about how
            to format the name see:

            https://msdn.microsoft.com/en-us/library/windows/desktop/aa379593(v=vs.85).aspx

        principal (str):
            The name of the user or group to make owner of the object. Can also
            pass a SID.

        obj_type (Optional[str]):
            The type of object for which to set the owner. Default is ``file``

    Returns:
        bool: True if successful, raises an error otherwise

    Usage:

    .. code-block:: python

        salt.utils.win_dacl.set_owner('C:\\MyDirectory', 'jsnuffy', 'file')
    '''
    sid = get_sid(principal)

    obj_flags = flags()

    # Validate obj_type
    if obj_type.lower() not in obj_flags.obj_type:
        raise SaltInvocationError(
            'Invalid "obj_type" passed: {0}'.format(obj_type))

    if 'registry' in obj_type.lower():
        obj_name = dacl().get_reg_name(obj_name)

    # To set the owner to something other than the logged in user requires
    # SE_TAKE_OWNERSHIP_NAME and SE_RESTORE_NAME privileges
    # Enable them for the logged in user
    # Setup the privilege set
    new_privs = set()
    luid = win32security.LookupPrivilegeValue('', 'SeTakeOwnershipPrivilege')
    new_privs.add((luid, win32con.SE_PRIVILEGE_ENABLED))
    luid = win32security.LookupPrivilegeValue('', 'SeRestorePrivilege')
    new_privs.add((luid, win32con.SE_PRIVILEGE_ENABLED))

    # Get the current token
    p_handle = win32api.GetCurrentProcess()
    t_handle = win32security.OpenProcessToken(
        p_handle,
        win32security.TOKEN_ALL_ACCESS | win32con.TOKEN_ADJUST_PRIVILEGES)

    # Enable the privileges
    win32security.AdjustTokenPrivileges(t_handle, 0, new_privs)

    # Set the user
    try:
        win32security.SetNamedSecurityInfo(
            obj_name,
            obj_flags.obj_type[obj_type.lower()],
            obj_flags.element['owner'],
            sid,
            None, None, None)
    except pywintypes.error as exc:
        log.exception('Failed to make %s the owner: %s', principal, exc)
        raise CommandExecutionError(
            'Failed to set owner: {0}'.format(obj_name), exc.strerror)

    return True

Response: Set the owner of an object.


Instruction:
Can you generate a brief explanation for the following Python 3 code
def set_permissions(obj_name,
                    principal,
                    permissions,
                    access_mode='grant',
                    applies_to=None,
                    obj_type='file',
                    reset_perms=False,
                    protected=None):
    '''
    Set the permissions of an object. This can be a file, folder, registry key,
    printer, service, etc...

    Args:

        obj_name (str):
            The object for which to set permissions. This can be the path to a
            file or folder, a registry key, printer, etc. For more information
            about how to format the name see:

            https://msdn.microsoft.com/en-us/library/windows/desktop/aa379593(v=vs.85).aspx

        principal (str):
            The name of the user or group for which to set permissions. Can also
            pass a SID.

        permissions (str, list):
            The type of permissions to grant/deny the user. Can be one of the
            basic permissions, or a list of advanced permissions.

        access_mode (Optional[str]):
            Whether to grant or deny user the access. Valid options are:

            - grant (default): Grants the user access
            - deny: Denies the user access

        applies_to (Optional[str]):
            The objects to which these permissions will apply. Not all these
            options apply to all object types. Defaults to
            'this_folder_subfolders_files'

        obj_type (Optional[str]):
            The type of object for which to set permissions. Default is 'file'

        reset_perms (Optional[bool]):
            True will overwrite the permissions on the specified object. False
            will append the permissions. Default is False

        protected (Optional[bool]):
            True will disable inheritance for the object. False will enable
            inheritance. None will make no change. Default is None.

    Returns:
        bool: True if successful, raises an error otherwise

    Usage:

    .. code-block:: python

        salt.utils.win_dacl.set_permissions(
            'C:\\Temp', 'jsnuffy', 'full_control', 'grant')
    '''
    # Set up applies_to defaults used by registry and file types
    if applies_to is None:
        if 'registry' in obj_type.lower():
            applies_to = 'this_key_subkeys'
        elif obj_type.lower() == 'file':
            applies_to = 'this_folder_subfolders_files'

    # If you don't pass `obj_name` it will create a blank DACL
    # Otherwise, it will grab the existing DACL and add to it
    if reset_perms:
        obj_dacl = dacl(obj_type=obj_type)
    else:
        obj_dacl = dacl(obj_name, obj_type)
        obj_dacl.rm_ace(principal, access_mode)

    obj_dacl.add_ace(principal, access_mode, permissions, applies_to)

    obj_dacl.order_acl()

    obj_dacl.save(obj_name, protected)

    return True

Response: Set the permissions of an object in the specified order.


Instruction:
Here you have a function in Python 3, explain what it does
def get_permissions(obj_name, principal=None, obj_type='file'):
    '''
    Get the permissions for the passed object

    Args:

        obj_name (str):
            The name of or path to the object.

        principal (Optional[str]):
            The name of the user or group for which to get permissions. Can also
            pass a SID. If None, all ACEs defined on the object will be
            returned. Default is None

        obj_type (Optional[str]):
            The type of object for which to get permissions.

    Returns:
        dict: A dictionary representing the object permissions

    Usage:

    .. code-block:: python

        salt.utils.win_dacl.get_permissions('C:\\Temp')
    '''
    obj_dacl = dacl(obj_name, obj_type)

    if principal is None:
        return obj_dacl.list_aces()

    return obj_dacl.get_ace(principal)

Response: Get the permissions for the passed object


Instruction:
Explain what the following Python 3 code does
def has_permission(obj_name,
                   principal,
                   permission,
                   access_mode='grant',
                   obj_type='file',
                   exact=True):
    r'''
    Check if the object has a permission

    Args:

        obj_name (str):
            The name of or path to the object.

        principal (str):
            The name of the user or group for which to get permissions. Can also
            pass a SID.

        permission (str):
            The permission to verify. Valid options depend on the obj_type.

        access_mode (Optional[str]):
            The access mode to check. Is the user granted or denied the
            permission. Default is 'grant'. Valid options are:

            - grant
            - deny

        obj_type (Optional[str]):
            The type of object for which to check permissions. Default is 'file'

        exact (Optional[bool]):
            True for an exact match, otherwise check to see if the permission is
            included in the ACE. Default is True

    Returns:
        bool: True if the object has the permission, otherwise False

    Usage:

    .. code-block:: python

        # Does Joe have read permissions to C:\Temp
        salt.utils.win_dacl.has_permission(
            'C:\\Temp', 'joe', 'read', 'grant', False)

        # Does Joe have Full Control of C:\Temp
        salt.utils.win_dacl.has_permission(
            'C:\\Temp', 'joe', 'full_control', 'grant')
    '''
    # Validate access_mode
    if access_mode.lower() not in ['grant', 'deny']:
        raise SaltInvocationError(
            'Invalid "access_mode" passed: {0}'.format(access_mode))
    access_mode = access_mode.lower()

    # Get the DACL
    obj_dacl = dacl(obj_name, obj_type)

    obj_type = obj_type.lower()

    # Get a PySID object
    sid = get_sid(principal)

    # Get the passed permission flag, check basic first
    chk_flag = obj_dacl.ace_perms[obj_type]['basic'].get(
        permission.lower(),
        obj_dacl.ace_perms[obj_type]['advanced'].get(permission.lower(), False))
    if not chk_flag:
        raise SaltInvocationError(
            'Invalid "permission" passed: {0}'.format(permission))

    # Check each ace for sid and type
    cur_flag = None
    for i in range(0, obj_dacl.dacl.GetAceCount()):
        ace = obj_dacl.dacl.GetAce(i)
        if ace[2] == sid and obj_dacl.ace_type[ace[0][0]] == access_mode:
            cur_flag = ace[1]

    # If the ace is empty, return false
    if not cur_flag:
        return False

    # Check if the ACE contains the exact flag
    if exact:
        return cur_flag == chk_flag

    # Check if the ACE contains the permission
    return cur_flag & chk_flag == chk_flag

Response: r Check if the object has the permission


Instruction:
Make a summary of the following Python 3 code
def set_inheritance(obj_name, enabled, obj_type='file', clear=False):
    '''
    Enable or disable an objects inheritance.

    Args:

        obj_name (str):
            The name of the object

        enabled (bool):
            True to enable inheritance, False to disable

        obj_type (Optional[str]):
            The type of object. Only three objects allow inheritance. Valid
            objects are:

            - file (default): This is a file or directory
            - registry
            - registry32 (for WOW64)

        clear (Optional[bool]):
            True to clear existing ACEs, False to keep existing ACEs.
            Default is False

    Returns:
        bool: True if successful, otherwise an Error

    Usage:

    .. code-block:: python

        salt.utils.win_dacl.set_inheritance('C:\\Temp', False)
    '''
    if obj_type not in ['file', 'registry', 'registry32']:
        raise SaltInvocationError(
            'obj_type called with incorrect parameter: {0}'.format(obj_name))

    if clear:
        obj_dacl = dacl(obj_type=obj_type)
    else:
        obj_dacl = dacl(obj_name, obj_type)

    return obj_dacl.save(obj_name, not enabled)

Response: Enable or disable inheritance of an object in the ACEs.


Instruction:
Can you generate a brief explanation for the following Python 3 code
def get_inheritance(obj_name, obj_type='file'):
    '''
    Get an object's inheritance.

    Args:

        obj_name (str):
            The name of the object

        obj_type (Optional[str]):
            The type of object. Only three object types allow inheritance. Valid
            objects are:

            - file (default): This is a file or directory
            - registry
            - registry32 (for WOW64)

            The following should return False as there is no inheritance:

            - service
            - printer
            - share

    Returns:
        bool: True if enabled, otherwise False

    Usage:

    .. code-block:: python

        salt.utils.win_dacl.get_inheritance('HKLM\\SOFTWARE\\salt', 'registry')
    '''
    obj_dacl = dacl(obj_name=obj_name, obj_type=obj_type)
    inherited = win32security.INHERITED_ACE

    for i in range(0, obj_dacl.dacl.GetAceCount()):
        ace = obj_dacl.dacl.GetAce(i)
        if ace[0][1] & inherited == inherited:
            return True

    return False

Response: Get an object s inheritance.


Instruction:
How would you explain what the following Python 3 function does
def copy_security(source,
                  target,
                  obj_type='file',
                  copy_owner=True,
                  copy_group=True,
                  copy_dacl=True,
                  copy_sacl=True):
    r'''
    Copy the security descriptor of the Source to the Target. You can specify a
    specific portion of the security descriptor to copy using one of the
    `copy_*` parameters.

    .. note::
        At least one `copy_*` parameter must be ``True``

    .. note::
        The user account running this command must have the following
        privileges:

        - SeTakeOwnershipPrivilege
        - SeRestorePrivilege
        - SeSecurityPrivilege

    Args:

        source (str):
            The full path to the source. This is where the security info will be
            copied from

        target (str):
            The full path to the target. This is where the security info will be
            applied

        obj_type (str): file
            The type of object to query. This value changes the format of the
            ``obj_name`` parameter as follows:
            - file: indicates a file or directory
                - a relative path, such as ``FileName.txt`` or ``..\FileName``
                - an absolute path, such as ``C:\DirName\FileName.txt``
                - A UNC name, such as ``\\ServerName\ShareName\FileName.txt``
            - service: indicates the name of a Windows service
            - printer: indicates the name of a printer
            - registry: indicates a registry key
                - Uses the following literal strings to denote the hive:
                    - HKEY_LOCAL_MACHINE
                    - MACHINE
                    - HKLM
                    - HKEY_USERS
                    - USERS
                    - HKU
                    - HKEY_CURRENT_USER
                    - CURRENT_USER
                    - HKCU
                    - HKEY_CLASSES_ROOT
                    - CLASSES_ROOT
                    - HKCR
                - Should be in the format of ``HIVE\Path\To\Key``. For example,
                    ``HKLM\SOFTWARE\Windows``
            - registry32: indicates a registry key under WOW64. Formatting is
                the same as it is for ``registry``
            - share: indicates a network share

        copy_owner (bool): True
            ``True`` copies owner information. Default is ``True``

        copy_group (bool): True
            ``True`` copies group information. Default is ``True``

        copy_dacl (bool): True
            ``True`` copies the DACL. Default is ``True``

        copy_sacl (bool): True
            ``True`` copies the SACL. Default is ``True``

    Returns:
        bool: ``True`` if successful

    Raises:
        SaltInvocationError: When parameters are invalid
        CommandExecutionError: On failure to set security

    Usage:

    .. code-block:: python

        salt.utils.win_dacl.copy_security(
            source='C:\\temp\\source_file.txt',
            target='C:\\temp\\target_file.txt',
            obj_type='file')

        salt.utils.win_dacl.copy_security(
            source='HKLM\\SOFTWARE\\salt\\test_source',
            target='HKLM\\SOFTWARE\\salt\\test_target',
            obj_type='registry',
            copy_owner=False)
    '''
    obj_dacl = dacl(obj_type=obj_type)
    if 'registry' in obj_type.lower():
        source = obj_dacl.get_reg_name(source)
        log.info('Source converted to: %s', source)
        target = obj_dacl.get_reg_name(target)
        log.info('Target converted to: %s', target)

    # Set flags
    try:
        obj_type_flag = flags().obj_type[obj_type.lower()]
    except KeyError:
        raise SaltInvocationError(
            'Invalid "obj_type" passed: {0}'.format(obj_type))

    security_flags = 0
    if copy_owner:
        security_flags |= win32security.OWNER_SECURITY_INFORMATION
    if copy_group:
        security_flags |= win32security.GROUP_SECURITY_INFORMATION
    if copy_dacl:
        security_flags |= win32security.DACL_SECURITY_INFORMATION
    if copy_sacl:
        security_flags |= win32security.SACL_SECURITY_INFORMATION

    if not security_flags:
        raise SaltInvocationError(
            'One of copy_owner, copy_group, copy_dacl, or copy_sacl must be '
            'True')

    # To set the owner to something other than the logged in user requires
    # SE_TAKE_OWNERSHIP_NAME and SE_RESTORE_NAME privileges
    # Enable them for the logged in user
    # Setup the privilege set
    new_privs = set()
    luid = win32security.LookupPrivilegeValue('', 'SeTakeOwnershipPrivilege')
    new_privs.add((luid, win32con.SE_PRIVILEGE_ENABLED))
    luid = win32security.LookupPrivilegeValue('', 'SeRestorePrivilege')
    new_privs.add((luid, win32con.SE_PRIVILEGE_ENABLED))
    luid = win32security.LookupPrivilegeValue('', 'SeSecurityPrivilege')
    new_privs.add((luid, win32con.SE_PRIVILEGE_ENABLED))

    # Get the current token
    p_handle = win32api.GetCurrentProcess()
    t_handle = win32security.OpenProcessToken(
        p_handle,
        win32security.TOKEN_ALL_ACCESS | win32con.TOKEN_ADJUST_PRIVILEGES)

    # Enable the privileges
    win32security.AdjustTokenPrivileges(t_handle, 0, new_privs)

    # Load object Security Info from the Source
    sec = win32security.GetNamedSecurityInfo(
        source, obj_type_flag, security_flags)

    # The following return None if the corresponding flag is not set
    sd_sid = sec.GetSecurityDescriptorOwner()
    sd_gid = sec.GetSecurityDescriptorGroup()
    sd_dacl = sec.GetSecurityDescriptorDacl()
    sd_sacl = sec.GetSecurityDescriptorSacl()

    # Set Security info on the target
    try:
        win32security.SetNamedSecurityInfo(
            target, obj_type_flag, security_flags, sd_sid, sd_gid, sd_dacl,
            sd_sacl)
    except pywintypes.error as exc:
        raise CommandExecutionError(
            'Failed to set security info: {0}'.format(exc.strerror))

    return True

Response: r Copy the security info from one source to another.


Instruction:
How would you explain what the following Python 3 function does
def _check_perms(obj_name, obj_type, new_perms, cur_perms, access_mode, ret):
    '''
    Helper function used by ``check_perms`` for checking and setting Grant and
    Deny permissions.

    Args:

        obj_name (str):
            The name or full path to the object

        obj_type (Optional[str]):
            The type of object for which to check permissions. Default is 'file'

        new_perms (dict):
            A dictionary containing the user/group and the basic permissions to
            check/grant, ie: ``{'user': {'perms': 'basic_permission'}}``.

        cur_perms (dict):
            A dictionary containing the user/group permissions as they currently
            exists on the target object.

        access_mode (str):
            The access mode to set. Either ``grant`` or ``deny``

        ret (dict):
            A dictionary to append changes to and return. If not passed, will
            create a new dictionary to return.

    Returns:
        dict: A dictionary of return data as expected by the state system
    '''
    access_mode = access_mode.lower()
    changes = {}
    for user in new_perms:
        applies_to_text = ''
        # Check that user exists:
        try:
            user_name = get_name(principal=user)
        except CommandExecutionError:
            ret['comment'].append(
                '{0} Perms: User "{1}" missing from Target System'
                ''.format(access_mode.capitalize(), user))
            continue

        # Get the proper applies_to text
        if 'applies_to' in new_perms[user]:
            applies_to = new_perms[user]['applies_to']
            at_flag = flags().ace_prop['file'][applies_to]
            applies_to_text = flags().ace_prop['file'][at_flag]

        else:
            applies_to = None

        if user_name not in cur_perms['Not Inherited']:
            if user not in changes:
                changes[user] = {}
            changes[user][access_mode] = new_perms[user]['perms']
            if applies_to:
                changes[user]['applies_to'] = applies_to
        else:
            # Check Perms for basic perms
            if isinstance(new_perms[user]['perms'], six.string_types):
                if not has_permission(obj_name=obj_name,
                                      principal=user_name,
                                      permission=new_perms[user]['perms'],
                                      access_mode=access_mode,
                                      obj_type=obj_type,
                                      exact=False):

                    if user not in changes:
                        changes[user] = {}
                    changes[user][access_mode] = new_perms[user]['perms']
            # Check Perms for advanced perms
            else:
                for perm in new_perms[user]['perms']:
                    if not has_permission(obj_name=obj_name,
                                          principal=user_name,
                                          permission=perm,
                                          access_mode=access_mode,
                                          obj_type=obj_type,
                                          exact=False):
                        if user not in changes:
                            changes[user] = {access_mode: []}
                        changes[user][access_mode].append(perm)

            # Check if applies_to was passed
            if applies_to:
                # Is there a deny/grant permission set
                if access_mode in cur_perms['Not Inherited'][user_name]:
                    # If the applies to settings are different, use the new one
                    if not cur_perms['Not Inherited'][user_name][access_mode]['applies to'] == applies_to_text:
                        if user not in changes:
                            changes[user] = {}
                        changes[user]['applies_to'] = applies_to

    if changes:
        if 'perms' not in ret['changes']:
            ret['changes']['perms'] = {}
        for user in changes:
            user_name = get_name(principal=user)

            if __opts__['test'] is True:
                if user not in ret['changes']['perms']:
                    ret['changes']['perms'][user] = {}
                ret['changes']['perms'][user][access_mode] = changes[user][access_mode]
            else:
                # Get applies_to
                applies_to = None
                if 'applies_to' not in changes[user]:
                    # Get current "applies to" settings from the file
                    if user_name in cur_perms['Not Inherited'] and \
                            access_mode in cur_perms['Not Inherited'][user_name]:
                        for flag in flags().ace_prop[obj_type]:
                            if flags().ace_prop[obj_type][flag] == cur_perms['Not Inherited'][user_name][access_mode]['applies to']:
                                at_flag = flag
                                for flag1 in flags().ace_prop[obj_type]:
                                    if salt.utils.win_dacl.flags().ace_prop[obj_type][flag1] == at_flag:
                                        applies_to = flag1
                    if not applies_to:
                        if obj_type.lower() in ['registry', 'registry32']:
                            applies_to = 'this_key_subkeys'
                        else:
                            applies_to = 'this_folder_subfolders_files'
                else:
                    applies_to = changes[user]['applies_to']

                perms = []
                if access_mode not in changes[user]:
                    # Get current perms
                    # Check for basic perms
                    for perm in cur_perms['Not Inherited'][user_name][access_mode]['permissions']:
                        for flag in flags().ace_perms[obj_type]['basic']:
                            if flags().ace_perms[obj_type]['basic'][flag] == perm:
                                perm_flag = flag
                                for flag1 in flags().ace_perms[obj_type]['basic']:
                                    if flags().ace_perms[obj_type]['basic'][flag1] == perm_flag:
                                        perms = flag1
                    # Make a list of advanced perms
                    if not perms:
                        for perm in cur_perms['Not Inherited'][user_name][access_mode]['permissions']:
                            for flag in flags().ace_perms[obj_type]['advanced']:
                                if flags().ace_perms[obj_type]['advanced'][flag] == perm:
                                    perm_flag = flag
                                    for flag1 in flags().ace_perms[obj_type]['advanced']:
                                        if flags().ace_perms[obj_type]['advanced'][flag1] == perm_flag:
                                            perms.append(flag1)
                else:
                    perms = changes[user][access_mode]

                try:
                    set_permissions(
                        obj_name=obj_name,
                        principal=user_name,
                        permissions=perms,
                        access_mode=access_mode,
                        applies_to=applies_to,
                        obj_type=obj_type)
                    if user not in ret['changes']['perms']:
                        ret['changes']['perms'][user] = {}
                    ret['changes']['perms'][user][access_mode] = changes[user][access_mode]
                except CommandExecutionError as exc:
                    ret['result'] = False
                    ret['comment'].append(
                        'Failed to change {0} permissions for "{1}" to {2}\n'
                        'Error: {3}'.format(access_mode, user, changes[user], exc.strerror))

    return ret

Response: Helper function to check permissions for the object and return a dictionary of changes to the state system.