Esempio n. 1
0
def test_add_module():
    graph = ImportGraph()
    module = "foo"

    graph.add_module(module)

    assert graph.modules == {module}
Esempio n. 2
0
    def test_chains_that_reenter_imported_package_dont_stop_longer_chains_being_included(
        self, ):
        graph = ImportGraph()

        graph.add_module("green")
        graph.add_module("blue")

        # Chain that reenters imported package.
        graph.add_import(importer="green.foo", imported="blue.foo")
        graph.add_import(importer="blue.foo", imported="brown")
        graph.add_import(importer="brown", imported="blue.bar")

        # Long indirect import.
        graph.add_import(importer="green.foo", imported="yellow.four")
        graph.add_import(importer="yellow.four", imported="yellow.three")
        graph.add_import(importer="yellow.three", imported="yellow.two")
        graph.add_import(importer="yellow.two", imported="yellow.one")
        graph.add_import(importer="yellow.one", imported="blue.bar")

        result = graph.find_shortest_chains(importer="green", imported="blue")
        assert result == {
            ("green.foo", "blue.foo"),
            (
                "green.foo",
                "yellow.four",
                "yellow.three",
                "yellow.two",
                "yellow.one",
                "blue.bar",
            ),
        }
Esempio n. 3
0
def test_ignore_imports(ignore_imports, is_kept):
    graph = ImportGraph()
    graph.add_module("mypackage")
    graph.add_import(importer="mypackage.a",
                     imported="mypackage.irrelevant",
                     line_number=1,
                     line_contents="-")
    graph.add_import(importer="mypackage.a",
                     imported="mypackage.indirect",
                     line_number=1,
                     line_contents="-")
    graph.add_import(importer="mypackage.indirect",
                     imported="mypackage.b",
                     line_number=1,
                     line_contents="-")
    contract = IndependenceContract(
        name="Independence contract",
        session_options={"root_packages": ["mypackage"]},
        contract_options={
            "modules": ("mypackage.a", "mypackage.b"),
            "ignore_imports": ignore_imports,
        },
    )

    contract_check = contract.check(graph=graph)

    assert is_kept == contract_check.kept
Esempio n. 4
0
def test_ignore_imports_tolerates_duplicates():
    graph = ImportGraph()
    graph.add_module("mypackage")
    graph.add_import(importer="mypackage.a",
                     imported="mypackage.b",
                     line_number=1,
                     line_contents="-")
    graph.add_import(importer="mypackage.a",
                     imported="mypackage.c",
                     line_number=2,
                     line_contents="-")
    contract = IndependenceContract(
        name="Independence contract",
        session_options={"root_packages": ["mypackage"]},
        contract_options={
            "modules": ("mypackage.a", "mypackage.b"),
            "ignore_imports": [
                "mypackage.a -> mypackage.b",
                "mypackage.a -> mypackage.c",
                "mypackage.a -> mypackage.b",
            ],
        },
    )

    contract_check = contract.check(graph=graph)

    assert contract_check.kept
Esempio n. 5
0
    def _build_graph(self):
        graph = ImportGraph()
        for module in (
            "mypackage",
            "mypackage.high",
            "mypackage.high.green",
            "mypackage.high.blue",
            "mypackage.high.yellow",
            "mypackage.high.yellow.alpha",
            "mypackage.medium",
            "mypackage.medium.orange",
            "mypackage.medium.orange.beta",
            "mypackage.medium.red",
            "mypackage.low",
            "mypackage.low.black",
            "mypackage.low.white",
            "mypackage.low.white.gamma",
        ):
            graph.add_module(module)

        # Add some 'legal' imports.
        graph.add_import(importer="mypackage.high.green", imported="mypackage.medium.orange")
        graph.add_import(importer="mypackage.high.green", imported="mypackage.low.white.gamma")
        graph.add_import(importer="mypackage.medium.orange", imported="mypackage.low.white")
        graph.add_import(importer="mypackage.high.blue", imported="mypackage.utils")
        graph.add_import(importer="mypackage.utils", imported="mypackage.medium.red")

        return graph
Esempio n. 6
0
def test_optional_layers(include_parentheses, should_raise_exception):
    graph = ImportGraph()
    for module in (
        "mypackage",
        "mypackage.foo",
        "mypackage.foo.high",
        "mypackage.foo.high.blue",
        "mypackage.foo.low",
        "mypackage.foo.low.alpha",
    ):
        graph.add_module(module)

    contract = LayersContract(
        name="Layer contract",
        session_options={"root_packages": ["mypackage"]},
        contract_options={
            "containers": ["mypackage.foo"],
            "layers": ["high", "(medium)" if include_parentheses else "medium", "low"],
        },
    )

    if should_raise_exception:
        with pytest.raises(
            ValueError,
            match=(
                "Missing layer in container 'mypackage.foo': "
                "module mypackage.foo.medium does not exist."
            ),
        ):
            contract.check(graph=graph)
    else:
        contract.check(graph=graph)
Esempio n. 7
0
def test_invalid_container(container):
    graph = ImportGraph()
    for module in (
        "mypackage",
        "mypackage.foo",
        "mypackage.foo.high",
        "mypackage.foo.medium",
        "mypackage.foo.low",
        "notinpackage",
        "mypackagebeginscorrectly",
    ):
        graph.add_module(module)

    contract = LayersContract(
        name="Layer contract",
        session_options={"root_packages": ["mypackage"]},
        contract_options={
            "containers": ["mypackage.foo", container],
            "layers": ["high", "medium", "low"],
        },
    )

    with pytest.raises(
        ValueError,
        match=(
            f"Invalid container '{container}': a container must either be a subpackage of "
            "mypackage, or mypackage itself."
        ),
    ):
        contract.check(graph=graph)
Esempio n. 8
0
    def _build_legal_graph(self, container=None):
        graph = ImportGraph()
        if container:
            graph.add_module(container)
            namespace = f"{container}."
        else:
            namespace = ""

        for module in (
            f"{namespace}high",
            f"{namespace}high.green",
            f"{namespace}high.blue",
            f"{namespace}high.yellow",
            f"{namespace}high.yellow.alpha",
            f"{namespace}medium",
            f"{namespace}medium.orange",
            f"{namespace}medium.orange.beta",
            f"{namespace}medium.red",
            f"{namespace}low",
            f"{namespace}low.black",
            f"{namespace}low.white",
            f"{namespace}low.white.gamma",
        ):
            graph.add_module(module)

        # Add some 'legal' imports.
        graph.add_import(importer=f"{namespace}high.green", imported=f"{namespace}medium.orange")
        graph.add_import(importer=f"{namespace}high.green", imported=f"{namespace}low.white.gamma")
        graph.add_import(importer=f"{namespace}medium.orange", imported=f"{namespace}low.white")
        graph.add_import(importer=f"{namespace}high.blue", imported=f"{namespace}utils")
        graph.add_import(importer=f"{namespace}utils", imported=f"{namespace}medium.red")

        return graph
Esempio n. 9
0
    def test_import_between_top_level_and_child(self):
        graph = ImportGraph()
        graph.add_module("blue")
        graph.add_import(importer="green", imported="blue.foo")

        result = graph.find_shortest_chains(importer="green", imported="blue")

        assert result == {("green", "blue.foo")}
Esempio n. 10
0
    def test_can_repeatedly_add_same_squashed_module(self):
        graph = ImportGraph()
        module = "foo"

        graph.add_module(module, is_squashed=True)
        graph.add_module(module, is_squashed=True)

        assert graph.modules == {module}
Esempio n. 11
0
    def test_does_nothing_if_module_is_already_squashed(self):
        graph = ImportGraph()
        graph.add_module("foo", is_squashed=True)
        graph.add_import(importer="foo", imported="bar")

        graph.squash_module("foo")

        assert graph.direct_import_exists(importer="foo", imported="bar")
Esempio n. 12
0
def test_find_descendants_raises_exception_for_squashed_module():
    graph = ImportGraph()
    module = "foo"

    graph.add_module(module, is_squashed=True)

    with pytest.raises(ValueError,
                       match="Cannot find descendants of a squashed module."):
        graph.find_descendants(module)
Esempio n. 13
0
def test_find_children(module, expected_result):
    graph = ImportGraph()
    foo, bar = "foo", "bar"
    a, b, c = "foo.a", "foo.b", "foo.c"
    d, e, f = "foo.a.one", "foo.b.one", "bar.g"
    for module_to_add in (foo, bar, a, b, c, d, e, f):
        graph.add_module(module_to_add)

    assert expected_result == graph.find_children(module)
Esempio n. 14
0
    def test_finds_no_paths_if_none_exist(self):
        graph = ImportGraph()
        graph.add_module("foo")
        graph.add_module("bar")

        result = list(
            graph.find_all_simple_chains(importer="foo", imported="bar"))

        assert [] == result
Esempio n. 15
0
    def test_finds_no_paths_if_imported_but_not_importer(self):
        graph = ImportGraph()
        self._add_chain(graph, "foo", "bar")
        graph.add_module("baz")

        result = list(
            graph.find_all_simple_chains(importer="baz", imported="bar"))

        assert [] == result
Esempio n. 16
0
    def test_no_results_in_reverse_direction(self):
        graph = ImportGraph()
        graph.add_module("green")
        graph.add_module("blue")
        graph.add_import(importer="green.foo", imported="blue.bar")

        result = graph.find_shortest_chains(importer="blue", imported="green")

        assert result == set()
Esempio n. 17
0
    def test_grandchildren_import(self):
        graph = ImportGraph()
        graph.add_module("green")
        graph.add_module("blue")
        graph.add_import(importer="green.foo.one", imported="blue.bar.two")

        result = graph.find_shortest_chains(importer="green", imported="blue")

        assert result == {("green.foo.one", "blue.bar.two")}
Esempio n. 18
0
    def test_first_level_child_import(self):
        graph = ImportGraph()
        graph.add_module("green")
        graph.add_module("blue")
        graph.add_import(importer="green.foo", imported="blue.bar")

        result = graph.find_shortest_chains(importer="green", imported="blue")

        assert result == {("green.foo", "blue.bar")}
Esempio n. 19
0
    def test_cannot_add_descendant_of_squashed_module(self, module_name):
        graph = ImportGraph()

        graph.add_module("mypackage.foo", is_squashed=True)

        with pytest.raises(
                ValueError,
                match="Module is a descendant of squashed module mypackage.foo."
        ):
            graph.add_module(module_name)
Esempio n. 20
0
    def test_short_indirect_import(self):
        graph = ImportGraph()
        graph.add_module("green")
        graph.add_module("blue")
        graph.add_import(importer="green.indirect", imported="purple")
        graph.add_import(importer="purple", imported="blue.foo")

        result = graph.find_shortest_chains(importer="green", imported="blue")

        assert result == {("green.indirect", "purple", "blue.foo")}
Esempio n. 21
0
    def _build_graph(self):
        graph = ImportGraph()
        for module in (
            "mypackage",
            "mypackage.high",
            "mypackage.high.green",
            "mypackage.high.blue",
            "mypackage.high.yellow",
            "mypackage.high.yellow.alpha",
            "mypackage.medium",
            "mypackage.medium.orange",
            "mypackage.medium.orange.beta",
            "mypackage.medium.red",
            "mypackage.low",
            "mypackage.low.black",
            "mypackage.low.white",
            "mypackage.low.white.gamma",
        ):
            graph.add_module(module)

        # Add some 'legal' imports.
        graph.add_import(importer="mypackage.high.green", imported="mypackage.medium.orange")
        graph.add_import(importer="mypackage.high.green", imported="mypackage.low.white.gamma")
        graph.add_import(importer="mypackage.medium.orange", imported="mypackage.low.white")
        graph.add_import(importer="mypackage.high.blue", imported="mypackage.utils")
        graph.add_import(importer="mypackage.utils", imported="mypackage.medium.red")

        # Direct illegal import.
        graph.add_import(
            importer="mypackage.low.black",
            imported="mypackage.medium.orange",
            line_number=1,
            line_contents="-",
        )
        # Indirect illegal import.
        graph.add_import(
            importer="mypackage.low.white.gamma",
            imported="mypackage.utils.foo",
            line_number=1,
            line_contents="-",
        )
        graph.add_import(
            importer="mypackage.utils.foo",
            imported="mypackage.utils.bar",
            line_number=1,
            line_contents="-",
        )
        graph.add_import(
            importer="mypackage.utils.bar",
            imported="mypackage.high.yellow.alpha",
            line_number=1,
            line_contents="-",
        )

        return graph
Esempio n. 22
0
    def test_doesnt_error_if_imports_within_module(self):
        graph = ImportGraph()
        for module in [
                "foo",
                "foo.green",
                "foo.blue",
        ]:
            graph.add_module(module)
        graph.add_import(importer="foo.blue", imported="foo.green")

        graph.squash_module("foo")
Esempio n. 23
0
    def test_truncated(self):
        modules = ["one", "two", "three", "four", "five", "six"]
        graph = ImportGraph()
        for module in modules:
            graph.add_module(module)

        re_part = "(" + "|".join(modules) + ")"
        assert re.match(
            f"<ImportGraph: '{re_part}', '{re_part}', '{re_part}', "
            f"'{re_part}', '{re_part}', ...>",
            repr(graph),
        )
Esempio n. 24
0
    def test_marks_module_as_squashed(self):
        graph = ImportGraph()
        modules_to_squash = {
            "foo",
            "foo.green",
        }
        for module in modules_to_squash:
            graph.add_module(module)

        graph.squash_module("foo")

        assert graph.is_module_squashed("foo")
Esempio n. 25
0
    def test_contracts_import_to_descendant(self):
        graph = ImportGraph()
        for module in [
                "foo",
                "foo.green",
                "bar.blue",
        ]:
            graph.add_module(module)
        graph.add_import(importer="bar.blue", imported="foo.green")

        graph.squash_module("foo")

        assert graph.direct_import_exists(importer="bar.blue", imported="foo")
Esempio n. 26
0
def test_remove_module():
    graph = ImportGraph()
    a, b = {"mypackage.blue", "mypackage.green"}

    graph.add_module(a)
    graph.add_module(b)
    graph.add_import(importer=a, imported=b)

    graph.remove_module(b)
    assert {a} == graph.modules

    # Removing a non-existent module doesn't cause an error.
    graph.remove_module("mypackage.yellow")
Esempio n. 27
0
def test_missing_containerless_layers_raise_value_error():
    graph = ImportGraph()
    for module in ("foo", "foo.blue", "bar", "bar.green"):
        graph.add_module(module)

    contract = LayersContract(
        name="Layer contract",
        session_options={"root_packages": ["foo", "bar"]},
        contract_options={"containers": [], "layers": ["foo", "bar", "baz"]},
    )

    with pytest.raises(ValueError, match=("Missing layer 'baz': module baz does not exist.")):
        contract.check(graph=graph)
Esempio n. 28
0
def test_add_import(add_module):
    graph = ImportGraph()
    a, b = "foo", "bar"

    # Adding the module should make no difference to the result.
    if add_module:
        graph.add_module(a)

    graph.add_import(importer=a, imported=b)

    assert {a, b} == graph.modules
    assert {b} == graph.find_modules_directly_imported_by(a)
    assert set() == graph.find_modules_directly_imported_by(b)
Esempio n. 29
0
    def test_keeps_import_of_squashed_root(self):
        graph = ImportGraph()
        for module in [
                "foo",
                "foo.green",
                "bar.blue",
        ]:
            graph.add_module(module)
        graph.add_import(importer="bar.blue", imported="foo")

        graph.squash_module("foo")

        assert graph.direct_import_exists(importer="bar.blue", imported="foo")
Esempio n. 30
0
    def test_long_indirect_import(self):
        graph = ImportGraph()
        graph.add_module("green")
        graph.add_module("blue")
        graph.add_import(importer="green.baz", imported="yellow.three")
        graph.add_import(importer="yellow.three", imported="yellow.two")
        graph.add_import(importer="yellow.two", imported="yellow.one")
        graph.add_import(importer="yellow.one", imported="blue.foo")

        result = graph.find_shortest_chains(importer="green", imported="blue")

        assert result == {("green.baz", "yellow.three", "yellow.two",
                           "yellow.one", "blue.foo")}