u"""
    Converts a wildmatch pattern to a regex

    Note that the EXTMATCH (ksh extended glob patterns) option is not available

    :type pattern: text_type
    :param pattern: A wildmatch pattern
    :type no_escape: bool
    :param no_escape: Disable backslash escaping
    :type path_name: bool
    :param path_name: Separator (slash) in text cannot be matched by an asterisk, question-mark nor
                      bracket expression in pattern (only a literal).
    :type wild_star: bool
    :param wild_star: A True value forces the `path_name` flag to True. This allows the
                      double-asterisk `**` to match any (0 to many) number of directories
    :type period: bool
    :param period: A leading period in text cannot be matched by an asterisk, question-mark nor
                   bracket expression in pattern (only a literal). A period is "leading" if:
                   - it is the first character of `text`
                   OR
                   - path_name (or wild_star) is True and the previous character is a slash
    :type case_fold: bool
    :param case_fold: Perform a case insensitive match (GNU Extension)
    :type closed_regex: bool
    :param closed_regex: Includes anchors to match start and end of string. You might want to
                         disable this flag if you want to compose regular expressions.
    :rtype: RegexType
    :return: A compiled regex object

def translate(pattern, no_escape=False, path_name=True, wild_star=True, period=False,
              case_fold=False, closed_regex=True):
    u"""
    Converts a wildmatch pattern to a regex

    Note that the EXTMATCH (ksh extended glob patterns) option is not available

    :type pattern: text_type
    :param pattern: A wildmatch pattern
    :type no_escape: bool
    :param no_escape: Disable backslash escaping
    :type path_name: bool
    :param path_name: Separator (slash) in text cannot be matched by an asterisk, question-mark nor
                      bracket expression in pattern (only a literal).
    :type wild_star: bool
    :param wild_star: A True value forces the `path_name` flag to True. This allows the
                      double-asterisk `**` to match any (0 to many) number of directories
    :type period: bool
    :param period: A leading period in text cannot be matched by an asterisk, question-mark nor
                   bracket expression in pattern (only a literal). A period is "leading" if:
                   - it is the first character of `text`
                   OR
                   - path_name (or wild_star) is True and the previous character is a slash
    :type case_fold: bool
    :param case_fold: Perform a case insensitive match (GNU Extension)
    :type closed_regex: bool
    :param closed_regex: Includes anchors to match start and end of string. You might want to
                         disable this flag if you want to compose regular expressions.
    :rtype: RegexType
    :return: A compiled regex object
    """

    # wild_star implies path_name
    if wild_star:
        path_name = True

    if case_fold:
        raise NotImplementedError(u'case_fold is not supported by wildmatch.translate')

    if period:
        raise NotImplementedError(u'period is not supported by wildmatch.translate')

    result = []

    i = 0

    # head_wild_star = False  # Wildstar at the start of the string
    tail_wild_star = False  # Wildstar at the end of the string

    while i < len(pattern):
        # Literal escape \
        if not no_escape and pattern[i:i+len(_ESCAPE)] == _ESCAPE:
            i += len(_ESCAPE)
            if i >= len(pattern):
                raise ValueError(u'Invalid pattern, incomplete escape sequence')
            result.append(re.escape(pattern[i:i + 1]))
            i += 1

        # Bracket expression [a]
        elif pattern[i:i+len(_BE_OPEN)] == _BE_OPEN:
            be, be_len = _parse_bracket_expression(pattern, i, no_escape=no_escape)
            translated_be = _py_pattern_from_bracket_expression(be, path_name=path_name)
            result.append(translated_be)
            i += be_len

        # Wildstar ** (matched before asterisk)
        elif wild_star and pattern[i:i+len(_WILD_STAR)] == _WILD_STAR:
            if i == 0:
                # Uncomment the following line to detect wild stars at start of pattern
                # head_wild_star = True
                pass
            else:
                if pattern[i - 1] != _SLASH:
                    raise ValueError(u'Invalid pattern: wild star ** can only start pattern or '
                                     u'follow a slash')
            i += len(_WILD_STAR)
            while True:  # Consume stars, example: foo/**/****/***/bar is equivalent to foo/**/bar
                if i == len(pattern):
                    tail_wild_star = True
                    break
                if pattern[i:i+len(_ASTERISK)] == _ASTERISK:
                    i += len(_ASTERISK)
                    continue
                elif pattern[i:i+len(_SLASH)] == _SLASH:
                    if pattern[i:i + len(_SLASH) + len(_WILD_STAR)] == _SLASH + _WILD_STAR:
                        i += len(_ASTERISK) + len(_WILD_STAR)
                        continue
                    else:
                        i += len(_SLASH)
                        break
                else:
                    raise ValueError(u'Invalid pattern: wild star ** can only end pattern or '
                                     u'be followed by a slash')

            if tail_wild_star:  # Pattern like ** or foo/**:
                result.append(u'.*')
            else:  # Pattern like **/foo or foo/**/bar, the slash following ** is already consumed
                result.append(u'(?:.*\\/)?')

        # Asterisk *
        elif pattern[i:i+len(_ASTERISK)] == _ASTERISK:
            if path_name:
                result.append(u'[^/]*')
            else:
                result.append(u'.*')
            i += len(_ASTERISK)

        # Question mark ?
        elif pattern[i:i + len(_QUESTION_MARK)] == _QUESTION_MARK:
            if path_name:
                result.append(u'[^/]')
            else:
                result.append(u'.')
            i += len(_QUESTION_MARK)

        # Literal
        else:
            result.append(re.escape(pattern[i:i+1]))
            i += 1

        if i > len(pattern):
            raise ValueError(u'InvalidPattern: parse error, index out of bounds')

    pattern = u''.join(result)
    if closed_regex:
        pattern = u'\\A' + pattern + u'\\Z'
    return re.compile(pattern)