def _py_pattern_from_bracket_expression(bracket_expression, path_name):
    u"""
    This does not handle exclusion of separators in the bracket expression when pathname is True
    :param bracket_expression:
    :return:
    """
    single_chars = set()
    multi_chars = set()
    ranges = set()
    matching, items = _read_bracket_expression(bracket_expression)
    for item in items:
        if _is_be_range(item):
            start_seq, end_seq = _read_be_range(item)
            if len(start_seq) != 1 or len(end_seq) != 1:
                raise ValueError(u'Ranges are only supported between single-char collating elems')
            ranges.add((start_seq, end_seq))
        elif _is_be_character_class(item):
            # TODO: handle character classes...
            # Idea: (?:[single r-an-ge-!]|multi1|multi2|[class1]|[class2])
            raise ValueError(u'Character classes are not supported')
        else:
            if _is_be_collating_element(item):
                sequence = _read_be_collating_element(item)
            elif _is_be_equivalence_class(item):
                sequence = _read_be_equivalence_class(item)
            else:
                raise ValueError(u'Unexpected item {}'.format(item))

            if len(sequence) == 0:
                raise ValueError(u'Empty string is not a valid collating element')
            elif len(sequence) == 1:
                single_chars.add(sequence)
            else:
                multi_chars.add(sequence)

    if path_name:  # bracket expression cannot match /
        if not matching:
            single_chars.add(_SLASH)  # Pretty easy!
        else:  # Remove slash from single_chars and ranges (we do not check multi_chars)
            if _SLASH in single_chars:
                single_chars.remove(_SLASH)

            slash_code_point = ord(_SLASH)
            cleared_ranges = set()
            for be_range in ranges:
                start_seq, end_seq = be_range
                if len(start_seq) != 1 or len(end_seq) != 1:
                    raise ValueError(u'Only ranges between single characters are supported in '
                                     u'bracket expression with the path_name flag')
                start_code_point = ord(start_seq)
                end_code_point = ord(end_seq)
                if start_code_point > end_code_point:
                    raise ValueError(u'Invalid range, wrong order of bounds: {}'.format(be_range))
                if slash_code_point < start_code_point or slash_code_point > end_code_point:
                    cleared_ranges.add(be_range)
                else:
                    if start_seq == slash_code_point:
                        if end_code_point == slash_code_point:  # /-/
                            continue
                        else:  # start = slash < end
                            start_seq = unichr(start_code_point + 1)
                            cleared_ranges.add((start_seq, end_seq))
                    else:
                        if end_code_point == slash_code_point:  # start < slash = end
                            end_seq = unichr(end_code_point - 1)
                            cleared_ranges.add((start_seq, end_seq))
                        else:  # start < slash < end
                            before_slash = unichr(slash_code_point - 1)
                            after_slash = unichr(slash_code_point + 1)
                            cleared_ranges.add((start_seq, before_slash))
                            cleared_ranges.add((after_slash, end_seq))
            ranges = cleared_ranges

    if len(single_chars) > 0 or len(ranges) > 0:
        primary_pattern = [u'['] if matching else [u'[^']

        for char in single_chars:
            primary_pattern.append(_escape_bracket_expression_character(char))

        for start, end in ranges:
            primary_pattern.append(_escape_bracket_expression_character(start))
            primary_pattern.append(u'-')
            primary_pattern.append(_escape_bracket_expression_character(end))

        primary_pattern.append(u']')
        primary_pattern = u''.join(primary_pattern)
    else:
        primary_pattern = None

    if len(multi_chars) > 0:
        if not matching:
            raise ValueError(u'Cannot perform negative match on bracket expression containing '
                             u'multi-character collating elements')
        alternate_pattern = u'|'.join(re.escape(seq) for seq in multi_chars)
    else:
        alternate_pattern = None

    if alternate_pattern is None:
        if primary_pattern is None:  # Can happen when removing characters
            return _PY_IMPOSSIBLE_MATCH
        else:
            return primary_pattern
    else:
        if primary_pattern is not None:
            alternate_pattern = primary_pattern + u'|' + alternate_pattern
        return u'(?:{})'.format(alternate_pattern)
def _py_pattern_from_bracket_expression ( bracket_expression , path_name ) : single_chars = set ( ) multi_chars = set ( ) ranges = set ( ) matching , items = _read_bracket_expression ( bracket_expression ) for item in items : if _is_be_range ( item ) : start_seq , end_seq = _read_be_range ( item ) if len ( start_seq ) != 1 or len ( end_seq ) != 1 : raise ValueError ( u'Ranges are only supported between single-char collating elems' ) ranges . add ( ( start_seq , end_seq ) ) elif _is_be_character_class ( item ) : raise ValueError ( u'Character classes are not supported' ) else : if _is_be_collating_element ( item ) : sequence = _read_be_collating_element ( item ) elif _is_be_equivalence_class ( item ) : sequence = _read_be_equivalence_class ( item ) else : raise ValueError ( u'Unexpected item {}' . format ( item ) ) if len ( sequence ) == 0 : raise ValueError ( u'Empty string is not a valid collating element' ) elif len ( sequence ) == 1 : single_chars . add ( sequence ) else : multi_chars . add ( sequence ) if path_name : if not matching : single_chars . add ( _SLASH ) else : if _SLASH in single_chars : single_chars . remove ( _SLASH ) slash_code_point = ord ( _SLASH ) cleared_ranges = set ( ) for be_range in ranges : start_seq , end_seq = be_range if len ( start_seq ) != 1 or len ( end_seq ) != 1 : raise ValueError ( u'Only ranges between single characters are supported in ' u'bracket expression with the path_name flag' ) start_code_point = ord ( start_seq ) end_code_point = ord ( end_seq ) if start_code_point > end_code_point : raise ValueError ( u'Invalid range, wrong order of bounds: {}' . format ( be_range ) ) if slash_code_point < start_code_point or slash_code_point > end_code_point : cleared_ranges . add ( be_range ) else : if start_seq == slash_code_point : if end_code_point == slash_code_point : continue else : start_seq = unichr ( start_code_point + 1 ) cleared_ranges . add ( ( start_seq , end_seq ) ) else : if end_code_point == slash_code_point : end_seq = unichr ( end_code_point - 1 ) cleared_ranges . add ( ( start_seq , end_seq ) ) else : before_slash = unichr ( slash_code_point - 1 ) after_slash = unichr ( slash_code_point + 1 ) cleared_ranges . add ( ( start_seq , before_slash ) ) cleared_ranges . add ( ( after_slash , end_seq ) ) ranges = cleared_ranges if len ( single_chars ) > 0 or len ( ranges ) > 0 : primary_pattern = [ u'[' ] if matching else [ u'[^' ] for char in single_chars : primary_pattern . append ( _escape_bracket_expression_character ( char ) ) for start , end in ranges : primary_pattern . append ( _escape_bracket_expression_character ( start ) ) primary_pattern . append ( u'-' ) primary_pattern . append ( _escape_bracket_expression_character ( end ) ) primary_pattern . append ( u']' ) primary_pattern = u'' . join ( primary_pattern ) else : primary_pattern = None if len ( multi_chars ) > 0 : if not matching : raise ValueError ( u'Cannot perform negative match on bracket expression containing ' u'multi-character collating elements' ) alternate_pattern = u'|' . join ( re . escape ( seq ) for seq in multi_chars ) else : alternate_pattern = None if alternate_pattern is None : if primary_pattern is None : return _PY_IMPOSSIBLE_MATCH else : return primary_pattern else : if primary_pattern is not None : alternate_pattern = primary_pattern + u'|' + alternate_pattern return u'(?:{})' . format ( alternate_pattern )
u"""
    This does not handle exclusion of separators in the bracket expression when pathname is True
    :param bracket_expression:
    :return: