(graph, pattern, address=None)
Yields a series of keys in the given graph matching the given "glob"
    string.

    This function implements the same glob features found in the `fnmatch`
    module in the Python standard library: ``*`` matches any number of
    characters, ``?`` matches any single character, `[abc]` matches any of
    the characters in the list, and ``[!abc]`` matches any character not in
    the list. (Use ``[[]`` to match an open bracket.) As ``fnmatch``, the star
    is greedy.

    :param graph: a :class:`GraphReader` object.
    :param pattern: a string specifying the glob to match, e.g.
        `"a*b?c[def]"`.
Yields a series of keys in the given graph matching the given "glob"
    string.
Yields a series of keys in the given graph matching the given glob string .
def glob(graph, pattern, address=None):
    """Yields a series of keys in the given graph matching the given "glob"
    string.

    This function implements the same glob features found in the `fnmatch`
    module in the Python standard library: ``*`` matches any number of
    characters, ``?`` matches any single character, `[abc]` matches any of
    the characters in the list, and ``[!abc]`` matches any character not in
    the list. (Use ``[[]`` to match an open bracket.) As ``fnmatch``, the star
    is greedy.

    :param graph: a :class:`GraphReader` object.
    :param pattern: a string specifying the glob to match, e.g.
        `"a*b?c[def]"`.
    """

    address = address if address is not None else graph._root
    if not isinstance(pattern, list):
        pattern = parse_glob(pattern)

    # address, pos, sofar, accept
    states = [(address, 0, [], False)]
    seen = set()
    arc = Arc()
    times = 0
    while states:
        ns = []
        for address, pos, sofar, accept in states:
            times += 1
            op = pattern[pos]
            code = op[0]
            if accept and code == _END:
                if sofar not in seen:
                    yield sofar
                    seen.add(sofar)
            if code == _END:
                continue

            # Zero width match
            if code == _STAR:
                ns.append((address, pos + 1, sofar, accept))

            if address is None:
                continue
            if code == _STAR:
                for arc in graph.iter_arcs(address, arc):
                    ns.append((arc.target, pos + 1, sofar + [arc.label],
                               arc.accept))
                    ns.append((arc.target, pos, sofar + [arc.label],
                               arc.accept))
            elif code == _QUEST:
                for arc in graph.iter_arcs(address, arc):
                    ns.append((arc.target, pos + 1, sofar + [arc.label],
                               arc.accept))
            elif code == _LIT:
                labels = op[1]
                for label in labels:
                    arc = graph.find_arc(address, label)
                    address = arc.target
                    if address is None:
                        break
                if address is not None:
                    ns.append((address, pos + 1, sofar + labels, arc.accept))
            elif code == _RANGE:
                chars = op[1]
                negate = op[2]
                for arc in graph.iter_arcs(address, arc):
                    take = (arc.label in chars) ^ negate
                    if take:
                        ns.append((arc.target, pos + 1, sofar + [arc.label],
                                   arc.accept))
            else:
                raise ValueError(code)
        states = ns
def glob ( graph , pattern , address = None ) : address = address if address is not None else graph . _root if not isinstance ( pattern , list ) : pattern = parse_glob ( pattern ) # address, pos, sofar, accept states = [ ( address , 0 , [ ] , False ) ] seen = set ( ) arc = Arc ( ) times = 0 while states : ns = [ ] for address , pos , sofar , accept in states : times += 1 op = pattern [ pos ] code = op [ 0 ] if accept and code == _END : if sofar not in seen : yield sofar seen . add ( sofar ) if code == _END : continue # Zero width match if code == _STAR : ns . append ( ( address , pos + 1 , sofar , accept ) ) if address is None : continue if code == _STAR : for arc in graph . iter_arcs ( address , arc ) : ns . append ( ( arc . target , pos + 1 , sofar + [ arc . label ] , arc . accept ) ) ns . append ( ( arc . target , pos , sofar + [ arc . label ] , arc . accept ) ) elif code == _QUEST : for arc in graph . iter_arcs ( address , arc ) : ns . append ( ( arc . target , pos + 1 , sofar + [ arc . label ] , arc . accept ) ) elif code == _LIT : labels = op [ 1 ] for label in labels : arc = graph . find_arc ( address , label ) address = arc . target if address is None : break if address is not None : ns . append ( ( address , pos + 1 , sofar + labels , arc . accept ) ) elif code == _RANGE : chars = op [ 1 ] negate = op [ 2 ] for arc in graph . iter_arcs ( address , arc ) : take = ( arc . label in chars ) ^ negate if take : ns . append ( ( arc . target , pos + 1 , sofar + [ arc . label ] , arc . accept ) ) else : raise ValueError ( code ) states = ns