Exemple #1
0
def test_unconnected_stable():
    nodes = list(range(1, 100))
    random.shuffle(nodes)

    graph = Graph()
    for node in nodes:
        graph.add_node(node)

    assert topological_sort(graph) == nodes
Exemple #2
0
def test_topological_sort_chain():
    graph = Graph()

    graph.add_node(1)
    graph.add_node(2)
    graph.add_node(3)
    graph.add_node(4)

    graph.add_dependency(2, 1)
    graph.add_dependency(3, 2)
    graph.add_dependency(4, 3)

    assert topological_sort(graph) == [1, 2, 3, 4]
Exemple #3
0
def test_topological_sort_root():
    graph = Graph()

    graph.add_node(1)
    graph.add_node(2)
    graph.add_node(3)
    graph.add_node(4)

    graph.add_dependency(1, 4)
    graph.add_dependency(2, 4)
    graph.add_dependency(3, 4)

    assert topological_sort(graph) == [4, 1, 2, 3]
Exemple #4
0
def test_topological_sort_tree():
    graph = Graph()

    graph.add_node(1)
    graph.add_node(2)
    graph.add_node(3)
    graph.add_node(4)
    graph.add_node(5)

    graph.add_dependency(3, 2)
    graph.add_dependency(5, 4)
    graph.add_dependency(5, 3)

    assert topological_sort(graph) == [1, 2, 3, 4, 5]
Exemple #5
0
def test_random_stable():
    nodes = list(range(100))
    random.shuffle(nodes)

    graph = Graph()

    for node in nodes:
        graph.add_node(node)

    for _ in range(200):
        src_index = random.randrange(1, 100)
        tgt_index = random.randrange(src_index)
        graph.add_dependency(nodes[src_index], nodes[tgt_index])

    assert topological_sort(graph) == nodes
Exemple #6
0
def ssort(
    text,
    *,
    filename="<unknown>",
    on_unknown_encoding_error="raise",
    on_decoding_error="raise",
    on_parse_error="raise",
    on_unresolved="raise",
    on_wildcard_import="raise",
):
    on_unknown_encoding_error = _interpret_on_unknown_encoding_action(
        on_unknown_encoding_error)
    on_decoding_error = _interpret_on_decoding_error_action(on_decoding_error)
    on_parse_error = _interpret_on_parse_error_action(on_parse_error)
    on_unresolved = _interpret_on_unresolved_action(on_unresolved)
    on_wildcard_import = _interpret_on_wildcard_import_action(
        on_wildcard_import)

    try:
        encoding = None
        if isinstance(text, bytes):
            encoding = detect_encoding(text)
            text = text.decode(encoding)
    except UnknownEncodingError as exc:
        on_unknown_encoding_error(str(exc), encoding=exc.encoding)
        return text

    except UnicodeDecodeError as exc:
        on_decoding_error(str(exc))
        return text

    newline = detect_newline(text)
    text = normalize_newlines(text)

    try:
        statements = list(parse(text, filename=filename))
    except ParseError as exc:
        on_parse_error(str(exc), lineno=exc.lineno, col_offset=exc.col_offset)
        return text

    if not statements:
        return text

    graph = module_statements_graph(
        statements,
        on_unresolved=on_unresolved,
        on_wildcard_import=on_wildcard_import,
    )
    if graph is None:
        return text

    replace_cycles(graph, key=sort_key_from_iter(statements))

    sorted_statements = topological_sort(statements, graph=graph)

    assert is_topologically_sorted(sorted_statements, graph=graph)

    output = "\n".join(
        statement_text_sorted(statement) for statement in sorted_statements)
    if output:
        output += "\n"

    if newline != "\n":
        output = re.sub("\n", newline, output)
    if encoding is not None:
        output = output.encode(encoding)
    return output
Exemple #7
0
def _statement_text_sorted_class(statement):
    head_text, statements = split_class(statement)

    # Take a snapshot of any hard dependencies between statements so that we can
    # restore them later.
    initialisation_graph = class_statements_initialisation_graph(statements)

    # === Split up the statements into high level groups =======================
    if _is_string(statements[0]):
        docstrings, statements = statements[:1], statements[1:]
    else:
        docstrings = []

    special_properties, statements = _partition(statements,
                                                _is_special_property)

    lifecycle_operations, statements = _partition(statements,
                                                  _is_lifecycle_operation)

    regular_operations, statements = _partition(statements,
                                                _is_regular_operation)

    inner_classes, statements = _partition(statements, _is_class)

    properties, statements = _partition(statements, _is_property)

    methods, statements = statements, []

    sorted_statements = []

    # === Join groups back together in the correct order =======================
    sorted_statements += docstrings

    # Special properties (in hard-coded order).
    sorted_statements += sorted(
        special_properties,
        key=_statement_binding_sort_key(
            sort_key_from_iter(SPECIAL_PROPERTIES)),
    )

    # Inner classes (in original order).
    sorted_statements += inner_classes

    # Regular properties (in original order).
    sorted_statements += properties

    # Special lifecycle methods (in hard-coded order).
    sorted_statements += sorted(
        lifecycle_operations,
        key=_statement_binding_sort_key(
            sort_key_from_iter(LIFECYCLE_OPERATIONS)),
    )

    # Regular methods.
    sorted_statements += methods

    # Special operations (in hard-coded order).
    sorted_statements += sorted(
        regular_operations,
        key=_statement_binding_sort_key(
            sort_key_from_iter(REGULAR_OPERATIONS)),
    )

    # === Re-sort based on dependencies between statements =====================

    # Fix any hard dependencies.
    sorted_statements = topological_sort(sorted_statements,
                                         graph=initialisation_graph)

    # Attempt to resolve soft dependencies on private attributes, but with hard
    # dependencies taking priority, and always preserving the original order
    # where there are cycles.
    runtime_graph = class_statements_runtime_graph(sorted_statements,
                                                   ignore_public=True)
    runtime_graph.update(initialisation_graph)
    replace_cycles(runtime_graph, key=sort_key_from_iter(sorted_statements))

    sorted_statements = topological_sort(sorted_statements,
                                         graph=runtime_graph)

    return (head_text + "\n" + "\n".join(
        statement_text_sorted(body_statement)
        for body_statement in sorted_statements))