# Buggy code
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
    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 = dacl.ace_perms[obj_type]["basic"].get(
        permission.lower(),
        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, dacl.dacl.GetAceCount()):
        ace = dacl.dacl.GetAce(i)
        if ace[2] == sid and 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 for the exact permission in the ACE
    if exact:
        return chk_flag == cur_flag

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


# Traceback (NameError)
Feb 10 14:33:00 echo salt-master[2373]: [ERROR   ] Failed to import utils win_dacl, this is due most likely to a syntax error:
Feb 10 14:33:00 echo salt-master[2373]: Traceback (most recent call last):
Feb 10 14:33:00 echo salt-master[2373]:   File "/usr/lib/python2.7/dist-packages/salt/loader.py", line 1334, in _load_module
Feb 10 14:33:00 echo salt-master[2373]:     ), fn_, fpath, desc)
Feb 10 14:33:00 echo salt-master[2373]:   File "/usr/lib/python2.7/dist-packages/salt/utils/win_dacl.py", line 154, in <module>
Feb 10 14:33:00 echo salt-master[2373]:     class Flags(object):
Feb 10 14:33:00 echo salt-master[2373]:   File "/usr/lib/python2.7/dist-packages/salt/utils/win_dacl.py", line 366, in Flags
Feb 10 14:33:00 echo salt-master[2373]:     'grant': win32security.ACCESS_ALLOWED_ACE_TYPE,
Feb 10 14:33:00 echo salt-master[2373]: NameError: name 'win32security' is not defined
Feb 10 14:33:00 echo salt-master[2373]: [ERROR   ] Failed to import utils saltminionservice, this is due most likely to a syntax error:
Feb 10 14:33:00 echo salt-master[2373]: Traceback (most recent call last):
Feb 10 14:33:00 echo salt-master[2373]:   File "/usr/lib/python2.7/dist-packages/salt/loader.py", line 1334, in _load_module
Feb 10 14:33:00 echo salt-master[2373]:     ), fn_, fpath, desc)
Feb 10 14:33:00 echo salt-master[2373]:   File "/usr/lib/python2.7/dist-packages/salt/utils/saltminionservice.py", line 8, in <module>
Feb 10 14:33:00 echo salt-master[2373]:     from salt.utils.winservice import Service, instart
Feb 10 14:33:00 echo salt-master[2373]:   File "/usr/lib/python2.7/dist-packages/salt/utils/winservice.py", line 33, in <module>
Feb 10 14:33:00 echo salt-master[2373]:     class Service(win32serviceutil.ServiceFramework):
Feb 10 14:33:00 echo salt-master[2373]: NameError: name 'win32serviceutil' is not defined
Feb 10 14:33:00 echo salt-master[2373]: [ERROR   ] Failed to import utils winservice, this is due most likely to a syntax error:
Feb 10 14:33:00 echo salt-master[2373]: Traceback (most recent call last):
Feb 10 14:33:00 echo salt-master[2373]:   File "/usr/lib/python2.7/dist-packages/salt/loader.py", line 1334, in _load_module
Feb 10 14:33:00 echo salt-master[2373]:     ), fn_, fpath, desc)
Feb 10 14:33:00 echo salt-master[2373]:   File "/usr/lib/python2.7/dist-packages/salt/utils/winservice.py", line 33, in <module>
Feb 10 14:33:00 echo salt-master[2373]:     class Service(win32serviceutil.ServiceFramework):
Feb 10 14:33:00 echo salt-master[2373]: NameError: name 'win32serviceutil' is not defined
Feb 10 14:33:01 echo salt-master[2373]: [ERROR   ] Failed to import utils win_osinfo, this is due most likely to a syntax error:
Feb 10 14:33:01 echo salt-master[2373]: Traceback (most recent call last):
Feb 10 14:33:01 echo salt-master[2373]:   File "/usr/lib/python2.7/dist-packages/salt/loader.py", line 1334, in _load_module
Feb 10 14:33:01 echo salt-master[2373]:     ), fn_, fpath, desc)
Feb 10 14:33:01 echo salt-master[2373]:   File "/usr/lib/python2.7/dist-packages/salt/utils/win_osinfo.py", line 32, in <module>
Feb 10 14:33:01 echo salt-master[2373]:     class OSVERSIONINFO(ctypes.Structure):
Feb 10 14:33:01 echo salt-master[2373]:   File "/usr/lib/python2.7/dist-packages/salt/utils/win_osinfo.py", line 33, in OSVERSIONINFO
Feb 10 14:33:01 echo salt-master[2373]:     _fields_ = (('dwOSVersionInfoSize', DWORD),
Feb 10 14:33:01 echo salt-master[2373]: NameError: name 'DWORD' is not defined
Feb 10 14:33:01 echo salt-master[2373]: [ERROR   ] Exception raised when processing __virtual__ function for boto_kinesis. Module will not be loaded 'boto3.assign_funcs'
Feb 10 14:33:01 echo salt-master[2373]: [WARNING ] salt.loaded.int.module.boto_kinesis.__virtual__() is wrongly returning `None`. It should either return `True`, `False` or a new name. If you're the developer of the module 'boto_kinesis', please fix this.

# Fixed code
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 for the exact permission in the ACE
    if exact:
        return chk_flag == cur_flag

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