Пример #1
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)
Пример #2
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)
Пример #3
0
def test_invalid_container_multiple_packages():
    graph = ImportGraph()

    contract = LayersContract(
        name="Layer contract",
        session_options={"root_packages": ["packageone", "packagetwo"]},
        contract_options={"containers": ["notinpackages"], "layers": ["high", "medium", "low"]},
    )

    with pytest.raises(
        ValueError,
        match=(
            r"Invalid container 'notinpackages': a container must either be a root package, "
            r"or a subpackage of one of them. \(The root packages are: packageone, packagetwo.\)"
        ),
    ):
        contract.check(graph=graph)
Пример #4
0
 def _build_contract(self):
     return LayersContract(
         name="Layer contract",
         session_options={"root_packages": ["mypackage"]},
         contract_options={
             "containers": ["mypackage.one", "mypackage.two", "mypackage.three"],
             "layers": ["high", "medium", "low"],
         },
     )
Пример #5
0
 def _build_contract(self, ignore_imports):
     return LayersContract(
         name="Layer contract",
         session_options={"root_packages": ["mypackage"]},
         contract_options={
             "containers": ["mypackage"],
             "layers": ["high", "medium", "low"],
             "ignore_imports": ignore_imports,
         },
     )
Пример #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)
Пример #7
0
 def _build_contract_without_containers(self, layers, root_packages=["mypackage"]):
     return LayersContract(
         name="Layer contract",
         session_options={"root_packages": root_packages},
         contract_options={"layers": layers},
     )
Пример #8
0
def test_render_broken_contract():
    settings.configure(PRINTER=FakePrinter())
    contract = LayersContract(
        name="Layers contract",
        session_options={"root_packages": ["mypackage"]},
        contract_options={"containers": ["mypackage"], "layers": ["high", "medium", "low"]},
    )
    check = ContractCheck(
        kept=False,
        metadata={
            "invalid_chains": [
                {
                    "higher_layer": "mypackage.high",
                    "lower_layer": "mypackage.low",
                    "chains": [
                        [
                            {
                                "importer": "mypackage.low.blue",
                                "imported": "mypackage.utils.red",
                                "line_numbers": (8, 16),
                            },
                            {
                                "importer": "mypackage.utils.red",
                                "imported": "mypackage.utils.yellow",
                                "line_numbers": (1,),
                            },
                            {
                                "importer": "mypackage.utils.yellow",
                                "imported": "mypackage.high.green",
                                "line_numbers": (3,),
                            },
                        ],
                        [
                            {
                                "importer": "mypackage.low.purple",
                                "imported": "mypackage.high.brown",
                                "line_numbers": (9,),
                            }
                        ],
                    ],
                },
                {
                    "higher_layer": "mypackage.medium",
                    "lower_layer": "mypackage.low",
                    "chains": [
                        [
                            {
                                "importer": "mypackage.low.blue",
                                "imported": "mypackage.medium.yellow",
                                "line_numbers": (6,),
                            }
                        ]
                    ],
                },
                {
                    "higher_layer": "mypackage.high",
                    "lower_layer": "mypackage.medium",
                    "chains": [
                        [
                            {
                                "importer": "mypackage.medium",
                                "imported": "mypackage.high.cyan.alpha",
                                "line_numbers": (2,),
                            }
                        ]
                    ],
                },
            ]
        },
    )

    contract.render_broken_contract(check)

    settings.PRINTER.pop_and_assert(
        """
        mypackage.low is not allowed to import mypackage.high:

        -   mypackage.low.blue -> mypackage.utils.red (l.8, l.16)
            mypackage.utils.red -> mypackage.utils.yellow (l.1)
            mypackage.utils.yellow -> mypackage.high.green (l.3)

        -   mypackage.low.purple -> mypackage.high.brown (l.9)


        mypackage.low is not allowed to import mypackage.medium:

        -   mypackage.low.blue -> mypackage.medium.yellow (l.6)


        mypackage.medium is not allowed to import mypackage.high:

        -   mypackage.medium -> mypackage.high.cyan.alpha (l.2)


        """
    )
Пример #9
0
def test_layer_contract_populates_metadata():
    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)
    graph.add_import(
        importer="mypackage.low.white.gamma",
        imported="mypackage.utils.foo",
        line_number=3,
        line_contents="-",
    ),
    graph.add_import(
        importer="mypackage.utils.foo",
        imported="mypackage.utils.bar",
        line_number=1,
        line_contents="-",
    ),
    graph.add_import(
        importer="mypackage.utils.foo",
        imported="mypackage.utils.bar",
        line_number=101,
        line_contents="-",
    ),
    graph.add_import(
        importer="mypackage.utils.bar",
        imported="mypackage.high.yellow.alpha",
        line_number=13,
        line_contents="-",
    ),
    graph.add_import(
        importer="mypackage.medium.orange.beta",
        imported="mypackage.high.blue",
        line_number=2,
        line_contents="-",
    ),
    graph.add_import(
        importer="mypackage.low.black",
        imported="mypackage.utils.baz",
        line_number=2,
        line_contents="-",
    ),
    graph.add_import(
        importer="mypackage.utils.baz",
        imported="mypackage.medium.red",
        line_number=3,
        line_contents="-",
    ),

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

    contract_check = contract.check(graph=graph)

    assert contract_check.kept is False

    assert contract_check.metadata == {
        "invalid_chains": [
            {
                "higher_layer": "mypackage.high",
                "lower_layer": "mypackage.medium",
                "chains": [
                    [
                        {
                            "importer": "mypackage.medium.orange.beta",
                            "imported": "mypackage.high.blue",
                            "line_numbers": (2,),
                        }
                    ]
                ],
            },
            {
                "higher_layer": "mypackage.high",
                "lower_layer": "mypackage.low",
                "chains": [
                    [
                        {
                            "importer": "mypackage.low.white.gamma",
                            "imported": "mypackage.utils.foo",
                            "line_numbers": (3,),
                        },
                        {
                            "importer": "mypackage.utils.foo",
                            "imported": "mypackage.utils.bar",
                            "line_numbers": (1, 101),
                        },
                        {
                            "importer": "mypackage.utils.bar",
                            "imported": "mypackage.high.yellow.alpha",
                            "line_numbers": (13,),
                        },
                    ]
                ],
            },
            {
                "higher_layer": "mypackage.medium",
                "lower_layer": "mypackage.low",
                "chains": [
                    [
                        {
                            "importer": "mypackage.low.black",
                            "imported": "mypackage.utils.baz",
                            "line_numbers": (2,),
                        },
                        {
                            "importer": "mypackage.utils.baz",
                            "imported": "mypackage.medium.red",
                            "line_numbers": (3,),
                        },
                    ]
                ],
            },
        ]
    }