示例#1
0
def test_not_passing_rules_with_import_from() -> None:
    """
    Test result with a set rules that accept files.
    """
    # Given
    dep_rules = {
        "module": [ModuleWildcard("module%"), ModuleWildcard("amodule.submodule")]
    }
    configuration = Configuration(dep_rules)
    source_file = SourceFile(
        Module("module"), SourceCode("from amodule import othermodule, submodule\n")
    )
    report_printer = Mock()
    use_case = CheckDependenciesUC(
        configuration, report_printer, PARSER, iter([source_file])
    )

    # When
    with pytest.raises(ForbiddenDepencyError):
        use_case.run()

    # Then
    assert set(report_printer.print_report.call_args[0][0]) == set(
        (
            DependencyError(
                Module("module"),
                Module("amodule.othermodule"),
                tuple(sorted(dep_rules["module"])),
            ),
        )
    )
示例#2
0
def test_fold_module(source_files) -> None:
    """
    Test result with a set source files and a module to fold.
    """
    # Given
    conf_graph = {"fold_modules": ["amodule"]}
    drawer = Mock()
    use_case = DrawGraphUC(drawer, PARSER, source_files, conf_graph)

    # When
    use_case.run()

    # Then
    drawer.write.assert_called()  # type: ignore
    global_dep = drawer.write.call_args[0][0]

    assert global_dep == {
        "simple_module":
        set((
            Dependency(Module("module")),
            Dependency(Module("module.inside.module")),
            Dependency(Module("amodule")),
        )),
        "amodule":
        set((Dependency(Module("module")),
             Dependency(Module("module.inside.module")))),
    }
示例#3
0
def test_empty_rules(source_files) -> None:
    """
    Test result with no rule given.
    """
    # Given
    configuration = Configuration()
    report_printer = Mock()
    use_case = CheckDependenciesUC(configuration, report_printer, PARSER,
                                   source_files)

    # When
    with pytest.raises(ForbiddenDepencyError):
        use_case.run()

    # Then
    assert set(report_printer.print_report.call_args[0][0]) == set(
        (
            DependencyError(SIMPLE_FILE.module, Module("module"), tuple()),
            DependencyError(SIMPLE_FILE.module, Module("module.inside.module"),
                            tuple()),
            DependencyError(SIMPLE_FILE.module, Module("amodule.aclass"),
                            tuple()),
            DependencyError(FILE_WITH_LOCAL_IMPORT.module, Module("module"),
                            tuple()),
            DependencyError(FILE_WITH_LOCAL_IMPORT.module,
                            Module("module.inside.module"), tuple()),
            DependencyError(FILE_WITH_LOCAL_IMPORT.module,
                            Module("amodule.aclass"), tuple()),
            DependencyError(FILE_WITH_LOCAL_IMPORT.module,
                            Module("amodule.inside.aclass"), tuple()),
            DependencyError(FILE_WITH_STD_IMPORT.module, Module("module"),
                            tuple()),
            DependencyError(FILE_WITH_STD_IMPORT.module,
                            Module("module.inside.module"), tuple()),
        ))
示例#4
0
    def test_nested_module() -> None:
        """
        Test nested case.
        """
        # Given
        module = Module("toto.tata")

        # When
        parent = get_parent(module)

        # Then
        assert parent == Module("toto")
示例#5
0
    def test_long_nested_module() -> None:
        """
        Test long nested case.
        """
        # Given
        module = Module("toto.titi.tete.tata")

        # When
        parent = get_parent(module)

        # Then
        assert parent == Module("toto.titi.tete")
示例#6
0
def test_not_passing_rules(source_files) -> None:
    """
    Test result with a set rules that not accept files.
    """
    # Given
    dep_rules = {
        "simple_module": [ModuleWildcard("module.*"), ModuleWildcard("amodule")],
        "amodule.local_module": [
            ModuleWildcard("module"),
            ModuleWildcard("module.inside.*"),
            ModuleWildcard("amod"),
        ],
        "amodule.std_module": [ModuleWildcard("mod")],
    }

    configuration = Configuration(dependency_rules=dep_rules)
    report_printer = Mock()
    use_case = CheckDependenciesUC(configuration, report_printer, PARSER, source_files)

    # When
    with pytest.raises(ForbiddenDepencyError):
        use_case.run()

    # Then
    simple = SIMPLE_FILE.module
    local = FILE_WITH_LOCAL_IMPORT.module
    std = FILE_WITH_STD_IMPORT.module

    assert set(report_printer.print_report.call_args[0][0]) == set(
        (
            DependencyError(
                simple, Module("module"), tuple(sorted(dep_rules["simple_module"]))
            ),
            DependencyError(
                local,
                Module("amodule.aclass"),
                tuple(sorted(dep_rules["amodule.local_module"])),
            ),
            DependencyError(
                local,
                Module("amodule.inside.aclass"),
                tuple(sorted(dep_rules["amodule.local_module"])),
            ),
            DependencyError(
                std, Module("module"), tuple(sorted(dep_rules["amodule.std_module"]))
            ),
            DependencyError(
                std,
                Module("module.inside.module"),
                tuple(sorted(dep_rules["amodule.std_module"])),
            ),
        )
    )
示例#7
0
    def test_simple_module() -> None:
        """
        Test simple case.
        """
        # Given
        module = Module("toto")

        # When
        parent = get_parent(module)

        # Then
        assert parent == Module("")
示例#8
0
def test_pop_empty_module_from_dependencies(source_files) -> None:
    # Given
    drawer = Mock()
    config = {"hide_modules": ["module"]}
    use_case = DrawGraphUC(drawer, PARSER, source_files, config)

    # When
    use_case.run()

    # Then
    drawer.write.assert_called_with({
        "simple_module":
        set((Dependency(Module("amodule")), )),
        "amodule.local_module":
        set((Dependency(Module("amodule")),
             Dependency(Module("amodule.inside")))),
    })
示例#9
0
def test_fold_dep() -> None:
    """
    Test result of _fold_dep function with an empty fold module
    """
    # Given
    global_dep = GLOBAL_DEPENDENCIES
    fold_module = Module("amodule")

    # When
    global_dep = _fold_dep(global_dep, fold_module)

    # Then
    assert global_dep == {
        "simple_module":
        set((
            Dependency(Module("module")),
            Dependency(Module("module.inside.module")),
            Dependency(Module("amodule")),
        )),
        "amodule":
        set((
            Dependency(Module("module")),
            Dependency(Module("module.inside.module")),
            Dependency(Module("amodule")),
        )),
    }
示例#10
0
def test_hide_nominal(source_files) -> None:
    # Given
    drawer = Mock()
    config = {"hide_modules": ["amodule"]}
    use_case = DrawGraphUC(drawer, PARSER, source_files, config)

    # When
    use_case.run()

    # Then
    drawer.write.assert_called()  # type: ignore
    global_dep = drawer.write.call_args[0][0]

    assert global_dep == {
        "simple_module":
        set((Dependency(Module("module")),
             Dependency(Module("module.inside.module"))))
    }
示例#11
0
    def visit(self, node: Any) -> None:
        modules: FrozenSet[Dependency] = frozenset()
        if isinstance(node, ast.Import):
            modules = frozenset(
                Dependency(Module(alias.name)) for alias in node.names)

        elif isinstance(node, ast.ImportFrom):
            module = Module(node.module or "")
            if node.level:
                parent_module = ".".join(
                    self.current_module_parts[:-node.level])
                if node.module:
                    module = Module("{}.{}".format(parent_module, node.module))
                else:
                    module = Module(parent_module)
            modules = frozenset((Dependency(module), ))
        self._dependencies |= modules

        super().visit(node)
示例#12
0
    def test_multi_imports_after_from() -> None:
        # Given
        module = Module("module.toto")
        source_file = SourceFile(
            module=module,
            code=SourceCode(
                "from module import amodule, othermodule, moduleagain"),
        )

        # When
        dependencies = get_import_from_dependencies(source_file, PARSER)

        # Then
        assert dependencies == set((Dependency(
            Module("module"),
            frozenset((
                Module("amodule"),
                Module("othermodule"),
                Module("moduleagain"),
            )),
        ), ))
示例#13
0
    def test_empty() -> None:
        """
        Test empty case.
        """
        # Given
        module = Module("")

        # When
        parent = get_parent(module)

        # Then
        assert parent == ""
示例#14
0
    def test_local_import_case() -> None:
        """
        Test code with local import case.
        """
        # Given
        module = Module("module.toto")
        source_file = SourceFile(module=module, code=SourceCode(_LOCAL_CASE))

        # When
        dependencies = get_dependencies(source_file, PARSER)

        # Then
        assert dependencies == _LOCAL_RESULT
示例#15
0
    def test_simple_case() -> None:
        """
        Test simple code case.
        """
        # Given
        module = Module("toto_program")
        source_file = SourceFile(module=module, code=SourceCode(_SIMPLE_CASE))

        # When
        dependencies = get_dependencies(source_file, PARSER)

        # Then
        assert dependencies == _SIMPLE_RESULT
示例#16
0
def test_fold_dep_empty_dict() -> None:
    """
    Test result of _fold_dep function with an empty dictionary
    """
    # Given
    global_dep = {}
    fold_module = Module("module")

    # When
    global_dep = _fold_dep(global_dep, fold_module)

    # Then
    global_dep = {}
示例#17
0
def test_fold_dep_empty_module() -> None:
    """
    Test result of _fold_dep function with an empty fold module
    """
    # Given
    global_dep = GLOBAL_DEPENDENCIES
    fold_module = Module("")

    # When
    global_dep = _fold_dep(global_dep, fold_module)

    # Then
    global_dep = GLOBAL_DEPENDENCIES
示例#18
0
def test_empty() -> None:
    """
    Test empty code case.
    """
    # Given
    module = Module("")
    source_code = SourceCode("")
    source_file = SourceFile(module=module, code=source_code)

    # When
    dependencies = get_dependencies(source_file, PARSER)

    # Then
    assert dependencies == frozenset()
示例#19
0
def test_empty() -> None:
    """
    Test empty rules case.
    """
    # Given
    dependency = Dependency(Module("toto"))
    authorized_modules: List[ModuleWildcard] = []

    # When
    with raises(NotAllowedDependencyException) as error:
        check_dependency(PARSER, dependency, authorized_modules)

    # Then
    assert error
    assert error.value.dependency == dependency.main_import
    assert error.value.authorized_modules == authorized_modules
示例#20
0
def check_import_from_dependency(parser: IParser, dependency: Dependency,
                                 rules: Rules) -> Rules:
    used_rules: Rules = set()
    for import_module in dependency.sub_imports:
        used_rule = None
        for module, rule in rules:
            if re.match(
                    "{}$".format(parser.wildcard_to_regex(rule)),
                    f"{dependency.main_import}.{import_module}",
            ):
                used_rule = (module, rule)
                used_rules.add(used_rule)
        if not used_rule:
            raise NotAllowedDependencyException(
                Module(f"{dependency.main_import}.{import_module}"),
                [r for _, r in rules],
            )
    return used_rules
示例#21
0
def test_not_passing_case() -> None:
    """
    Test a not passing case.
    """
    # Given
    dependency = Dependency(Module("toto.tata"))
    rules: Rules = [
        (ModuleWildcard("toto.*"), ModuleWildcard("toto")),
        (ModuleWildcard("toto.*"), ModuleWildcard("te.*")),
        (ModuleWildcard("toto.*"), ModuleWildcard("titi\\.tata")),
    ]

    # When
    with raises(NotAllowedDependencyException) as error:
        check_dependency(PARSER, dependency, rules)

    # Then
    assert error
    assert error.value.dependency == dependency.main_import
    assert error.value.authorized_modules == [r for _, r in rules]
示例#22
0
def test_passing_case() -> None:
    """
    Test a passing case.
    """
    # Given
    dependency = Dependency(Module("toto"))
    rules: Rules = [
        (ModuleWildcard("toto"), ModuleWildcard("to*")),
        (ModuleWildcard("toto"), ModuleWildcard("titi.tata")),
    ]

    # When
    error = None
    try:
        check_dependency(PARSER, dependency, rules)
    except NotAllowedDependencyException as exception:
        error = exception

    # Then
    assert not error
示例#23
0
def source_file_iterator(root_dir: str,
                         file_extension: str) -> Iterator[SourceFile]:
    """
    Iterator of all python source files in a directory.
    """
    if file_extension == "py":
        project_root = _get_python_project_root(root_dir)
        separator = "."
    elif file_extension == "go":
        project_root = ""
        separator = "/"

    with _change_dir(root_dir):
        for file_path in Path(".").rglob(f"*.{file_extension}"):
            with open(str(file_path), "r") as stream:
                content = stream.read()
            yield SourceFile(
                Module(project_root +
                       _get_module_from_file_path(file_path, separator)),
                SourceCode(content),
            )
示例#24
0
    def run(self) -> None:
        global_dependencies: GlobalDependencies = {}
        for source_file in self.source_files:
            module = Module(source_file.module.replace(".__init__", ""))
            dependencies = get_dependencies(source_file, self.parser)
            dependencies = self.std_lib_filter.filter(dependencies)
            global_dependencies[module] = dependencies

        global_dependencies = self._hide(global_dependencies)

        for fold_module in self.config.get("fold_modules", []):
            global_dependencies = _fold_dep(global_dependencies, fold_module)

        # To avoid a module to point itself, and make the graph more readable
        for module, deps in list(global_dependencies.items()):
            deps -= {dep for dep in deps if dep.main_import == module}

            if not global_dependencies[module]:
                global_dependencies.pop(module, None)

        self.drawer.write(global_dependencies)
示例#25
0
def test_nominal() -> None:
    source_file = SourceFile(
        Module("string.string"),
        SourceCode("""package main
    import "fmt"
    import (
        "go/parser"
        "go/module"
        "othermodule"
    )
    import "amodule"
    """),
    )

    assert get_dependencies(source_file, PARSER) == {
        Dependency("fmt"),
        Dependency("go/parser"),
        Dependency("go/module"),
        Dependency("othermodule"),
        Dependency("amodule"),
    }
示例#26
0
def test_passing_rules_with_import_from() -> None:
    """
    Test result with a set rules that accept files.
    """
    # Given
    configuration = Configuration(
        dependency_rules={
            "module": [ModuleWildcard("module%"), ModuleWildcard("amodule.submodule")]
        }
    )
    source_file = SourceFile(
        Module("module"), SourceCode("from amodule import submodule")
    )
    report_printer = Mock()
    use_case = CheckDependenciesUC(
        configuration, report_printer, PARSER, iter([source_file])
    )

    # When
    use_case.run()

    # Then
    assert report_printer.print_report.call_args[0][0] == []
示例#27
0
def _get_module_from_file_path(path: Path, separator: str) -> Module:
    """
    Transform a filename into a corresponding python module.
    """
    path_without_extention = path.parents[0] / path.stem
    return Module(separator.join(path_without_extention.parts))
示例#28
0
"""
Tests about get_dependencies function.
"""
import re

from dep_check.dependency_finder import get_dependencies, get_import_from_dependencies
from dep_check.infra.python_parser import PythonParser
from dep_check.models import Dependency, Module, ModuleWildcard, SourceCode, SourceFile

_SIMPLE_CASE = """
import simple
import module.inside.module
from amodule import aclass
"""
_SIMPLE_RESULT = frozenset((
    Dependency(Module("simple")),
    Dependency(Module("amodule")),
    Dependency(Module("module.inside.module")),
))
_SIMPLE_RESULT_IMPORT_FROM = frozenset((
    Dependency(Module("simple")),
    Dependency(Module("amodule"), frozenset((Module("aclass"), ))),
    Dependency(Module("module.inside.module")),
))

_LOCAL_CASE = """
import simple
from . import aclass
from .inside.module import aclass
"""
_LOCAL_RESULT = set((
示例#29
0
from dep_check.models import Dependency, Module, SourceCode, SourceFile

SIMPLE_FILE = SourceFile(
    module=Module("simple_module"),
    code=SourceCode(
        """
import module
import module.inside.module
from amodule import aclass
"""
    ),
)
FILE_WITH_LOCAL_IMPORT = SourceFile(
    module=Module("amodule.local_module"),
    code=SourceCode(
        """
import module
import module.inside.module
from . import aclass
from .inside import aclass
"""
    ),
)
FILE_WITH_STD_IMPORT = SourceFile(
    module=Module("amodule.std_module"),
    code=SourceCode(
        """
import module
import module.inside.module
import itertools
from abc import ABC