Example #1
0
def test_ignores_orphaned_python_files():
    # Python files in directories that don't contain an __init__.py should not be discovered.
    module_finder = ModuleFinder()

    file_system = FakeFileSystem(
        contents="""
            /path/to/mypackage/
                __init__.py
                two/
                    __init__.py
                    green.py
                noinitpackage/
                    green.py
                    orphan/
                        __init__.py
                        red.py
            """
    )

    result = module_finder.find_modules(
        package_name="mypackage",
        package_directory="/path/to/mypackage",
        file_system=file_system,
    )

    expected_modules = {
        Module("mypackage"),
        Module("mypackage.two"),
        Module("mypackage.two.green"),
    }
    assert set(result) == expected_modules
Example #2
0
def test_happy_path():
    module_finder = ModuleFinder()

    file_system = FakeFileSystem(
        contents="""
        /path/to/mypackage/
            __init__.py
            not-a-python-file.txt
            .hidden
            foo/
                __init__.py
                one.py
                two/
                    __init__.py
                    green.py
                    blue.py
        """
    )

    result = module_finder.find_modules(
        package_name="mypackage",
        package_directory="/path/to/mypackage",
        file_system=file_system,
    )

    expected_modules = {
        Module("mypackage"),
        Module("mypackage.foo"),
        Module("mypackage.foo.one"),
        Module("mypackage.foo.two"),
        Module("mypackage.foo.two.green"),
        Module("mypackage.foo.two.blue"),
    }
    assert set(result) == expected_modules
Example #3
0
def test_relative_from_imports():
    all_modules = {
        Module("foo.one.blue"),
        Module("foo.one.green"),
        Module("foo.two.brown"),
        Module("foo.two.yellow"),
        Module("foo.three"),
    }
    file_system = FakeFileSystem(
        contents="""
            /path/to/foo/
                __init__.py
                one/
                    __init__.py
                    blue.py
                    green.py
                two/
                    __init__.py
                    brown.py
                    yellow.py
                three.py
        """,
        content_map={
            "/path/to/foo/one/blue.py":
            """
                from . import green
                from ..two import yellow
                from .. import three
                arbitrary_expression = 1
            """
        },
    )

    import_scanner = ImportScanner(
        modules_by_package_directory={"/path/to/foo": all_modules},
        file_system=file_system,
    )

    result = import_scanner.scan_for_imports(Module("foo.one.blue"))

    assert result == {
        DirectImport(
            importer=Module("foo.one.blue"),
            imported=Module("foo.one.green"),
            line_number=1,
            line_contents="from . import green",
        ),
        DirectImport(
            importer=Module("foo.one.blue"),
            imported=Module("foo.two.yellow"),
            line_number=2,
            line_contents="from ..two import yellow",
        ),
        DirectImport(
            importer=Module("foo.one.blue"),
            imported=Module("foo.three"),
            line_number=3,
            line_contents="from .. import three",
        ),
    }
Example #4
0
def test_trims_to_known_modules(import_source):
    all_modules = {
        Module("foo"),
        Module("foo.one"),
        Module("foo.two"),
        Module("foo.two.yellow"),
    }
    file_system = FakeFileSystem(
        contents="""
                /path/to/foo/
                    __init__.py
                    one.py
                    two/
                        __init__.py
                        yellow.py
            """,
        content_map={"/path/to/foo/one.py": import_source},
    )

    import_scanner = ImportScanner(
        modules_by_package_directory={"/path/to/foo": all_modules},
        file_system=file_system,
    )

    result = import_scanner.scan_for_imports(Module("foo.one"))

    assert result == {
        DirectImport(
            importer=Module("foo.one"),
            imported=Module("foo.two.yellow"),
            line_number=1,
            line_contents=import_source,
        )
    }
Example #5
0
def test_trims_whitespace_from_start_of_line_contents():
    all_modules = {Module("foo"), Module("foo.one"), Module("foo.two")}
    file_system = FakeFileSystem(
        contents="""
                    /path/to/foo/
                        __init__.py
                        one.py
                        two.py
                """,
        content_map={
            "/path/to/foo/one.py":
            """
            def my_function():
                from . import two
            """
        },
    )

    import_scanner = ImportScanner(
        modules_by_package_directory={"/path/to/foo": all_modules},
        file_system=file_system,
    )

    result = import_scanner.scan_for_imports(Module("foo.one"))

    assert result == {
        DirectImport(
            importer=Module("foo.one"),
            imported=Module("foo.two"),
            line_number=2,
            line_contents="from . import two",
        )
    }
Example #6
0
def test_ignores_hidden_directories():
    module_finder = ModuleFinder()

    file_system = FakeFileSystem(
        contents="""
                /path/to/mypackage/
                    __init__.py
                    two/
                        __init__.py
                        green.py
                    .hidden/
                        green.py
                        orphan/
                            __init__.py
                            red.py
                """
    )

    result = module_finder.find_modules(
        package_name="mypackage",
        package_directory="/path/to/mypackage",
        file_system=file_system,
    )

    expected_modules = {
        Module("mypackage"),
        Module("mypackage.two"),
        Module("mypackage.two.green"),
    }
    assert set(result) == expected_modules
Example #7
0
    def test_happy_path(self, include_external_packages):
        file_system = FakeFileSystem(
            contents="""
                /path/to/mypackage/
                    __init__.py
                    foo/
                        __init__.py
                        one.py
                        two/
                            __init__.py
                            green.py
                            blue.py
            """,
            content_map={
                "/path/to/mypackage/foo/one.py":
                "import mypackage.foo.two.green",
                "/path/to/mypackage/foo/two/green.py":
                "import mypackage.foo.two.blue\n"
                "from external.subpackage import foobar\n"
                "import decimal",
            },
        )

        class FakePackageFinder(BaseFakePackageFinder):
            directory_map = {"mypackage": "/path/to/mypackage"}

        with override_settings(FILE_SYSTEM=file_system,
                               PACKAGE_FINDER=FakePackageFinder()):
            graph = usecases.build_graph(
                "mypackage",
                include_external_packages=include_external_packages)

        expected_import_map = {
            "mypackage": set(),
            "mypackage.foo": set(),
            "mypackage.foo.one": {"mypackage.foo.two.green"},
            "mypackage.foo.two": set(),
            "mypackage.foo.two.green": {"mypackage.foo.two.blue"},
            "mypackage.foo.two.blue": set(),
        }
        if include_external_packages:
            expected_import_map["decimal"] = set()
            expected_import_map["external"] = set()
            expected_import_map["mypackage.foo.two.green"] |= {
                "external", "decimal"
            }

        assert set(expected_import_map.keys()) == graph.modules
        for importer, imported_modules in expected_import_map.items():
            assert graph.find_modules_directly_imported_by(
                importer) == imported_modules

        # Check that the external packages are squashed modules.
        if include_external_packages:
            for module in ("external", "decimal"):
                with pytest.raises(
                        ValueError,
                        match="Cannot find children of a squashed module."):
                    graph.find_children(module)
Example #8
0
 def test_walk(self):
     file_system = FakeFileSystem("""
         /path/to/mypackage/
             __init__.py
             foo/
                 __init__.py
                 one.py
                 two/
                     __init__.py
                     green.py
                     blue.py
         /anotherpackage/
             another.txt
     """)
     assert [
         ("/path/to/mypackage", ["foo"], ["__init__.py"]),
         ("/path/to/mypackage/foo", ["two"], ["__init__.py", "one.py"]),
         ("/path/to/mypackage/foo/two", [],
          ["__init__.py", "green.py", "blue.py"]),
     ] == list(file_system.walk("/path/to/mypackage"))
Example #9
0
def test_trims_to_known_modules_within_init_file():
    all_modules = {
        Module("foo"),
        Module("foo.one"),
        Module("foo.one.yellow"),
        Module("foo.one.blue"),
        Module("foo.one.blue.alpha"),
    }
    file_system = FakeFileSystem(
        contents="""
                /path/to/foo/
                    __init__.py
                    one/
                        __init__.py
                        yellow.py
                        blue/
                            __init__.py
                            alpha.py
            """,
        content_map={
            "/path/to/foo/one/__init__.py": "from .yellow import my_function",
            "/path/to/foo/one/blue/__init__.py":
            "from .alpha import my_function",
        },
    )

    import_scanner = ImportScanner(
        modules_by_package_directory={"/path/to/foo": all_modules},
        file_system=file_system,
    )

    result = import_scanner.scan_for_imports(Module("foo.one"))

    assert result == {
        DirectImport(
            importer=Module("foo.one"),
            imported=Module("foo.one.yellow"),
            line_number=1,
            line_contents="from .yellow import my_function",
        )
    }

    result = import_scanner.scan_for_imports(Module("foo.one.blue"))

    assert result == {
        DirectImport(
            importer=Module("foo.one.blue"),
            imported=Module("foo.one.blue.alpha"),
            line_number=1,
            line_contents="from .alpha import my_function",
        )
    }
Example #10
0
 def test_read(self, file_name, expected_contents):
     file_system = FakeFileSystem(
         contents="""
         /path/to/mypackage/
             readme.txt
             foo/
                 one.txt
                 two/
                     green.txt
         """,
         content_map={
             "/path/to/mypackage/readme.txt": "Lorem",
             "/path/to/mypackage/foo/one.txt": "Ipsum",
             "/path/to/mypackage/foo/two/blue.txt": "Dolor sic",
         },
     )
     if isinstance(expected_contents, type) and issubclass(
             expected_contents, Exception):
         with pytest.raises(expected_contents):
             file_system.read(file_name)
     else:
         assert expected_contents == file_system.read(file_name)
Example #11
0
    def test_dirnames_can_be_modified_in_place(self):
        """
        From the os.walk docs:
            The caller can modify the dirnames list in-place (perhaps using del or slice
            assignment), and walk() will only recurse into the subdirectories whose names
            remain in dirnames; this can be used to prune the search, impose a specific order
            of visiting, or even to inform walk() about directories the caller creates or renames
            before it resumes walk() again.
        """
        file_system = FakeFileSystem("""
                    /path/to/mypackage/
                        foo/
                            one.txt
                            skipme/
                                two.txt
                            dontskip/
                                three.txt
                        bar/
                            four.txt
        """)

        expected_tuples = [
            ("/path/to/mypackage", ["foo", "bar"], []),
            ("/path/to/mypackage/foo", ["skipme", "dontskip"], ["one.txt"]),
            ("/path/to/mypackage/foo/dontskip", [], ["three.txt"]),
            ("/path/to/mypackage/bar", [], ["four.txt"]),
        ]

        actual_tuples = []
        for dirpath, dirs, files in file_system.walk("/path/to/mypackage"):
            # Ensure we make a copy of dirs (since we change it).
            actual_tuples.append((dirpath, copy(dirs), files))
            if "skipme" in dirs:
                dirs.remove("skipme")
                continue

        assert expected_tuples == actual_tuples
Example #12
0
def test_absolute_from_imports(include_external_packages, expected_result):
    all_modules = {
        Module("foo.one.blue"),
        Module("foo.one.green"),
        Module("foo.two.brown"),
        Module("foo.two.yellow"),
        Module("foo.three"),
    }
    file_system = FakeFileSystem(
        contents="""
            /path/to/foo/
                __init__.py
                one/
                    __init__.py
                    blue.py
                    green.py
                two/
                    __init__.py
                    brown.py
                    yellow.py
                three.py
        """,
        content_map={
            "/path/to/foo/one/blue.py":
            """
                from foo.one import green
                from foo.two import yellow
                from foo import three
                from external import one
                from external.two import blue
                arbitrary_expression = 1
            """
        },
    )

    import_scanner = ImportScanner(
        modules_by_package_directory={"/path/to/foo": all_modules},
        file_system=file_system,
        include_external_packages=include_external_packages,
    )

    result = import_scanner.scan_for_imports(Module("foo.one.blue"))

    assert expected_result == result
Example #13
0
def test_absolute_imports(include_external_packages, expected_result):
    all_modules = {Module("foo.one"), Module("foo.two")}
    file_system = FakeFileSystem(
        content_map={
            "/path/to/foo/one.py":
            """
                import foo.two
                import externalone
                import externaltwo.subpackage
                arbitrary_expression = 1
            """
        })

    import_scanner = ImportScanner(
        modules_by_package_directory={"/path/to/foo": all_modules},
        file_system=file_system,
        include_external_packages=include_external_packages,
    )

    result = import_scanner.scan_for_imports(Module("foo.one"))

    assert expected_result == result
Example #14
0
def test_scans_multiple_packages(statement):
    foo_modules = {Module("foo"), Module("foo.one"), Module("foo.two")}
    bar_modules = {Module("bar"), Module("bar.green"), Module("bar.blue")}
    file_system = FakeFileSystem(
        content_map={
            "/path/to/foo/one.py":
            f"""
                import foo.two
                {statement}
                import externalone

                arbitrary_expression = 1
            """
        })

    import_scanner = ImportScanner(
        modules_by_package_directory={
            "/path/to/foo": foo_modules,
            "/path/to/bar": bar_modules,
        },
        file_system=file_system,
    )

    result = import_scanner.scan_for_imports(Module("foo.one"))

    assert {
        DirectImport(
            importer=Module("foo.one"),
            imported=Module("foo.two"),
            line_number=1,
            line_contents="import foo.two",
        ),
        DirectImport(
            importer=Module("foo.one"),
            imported=Module("bar.blue"),
            line_number=2,
            line_contents=statement,
        ),
    } == result
Example #15
0
 def test_dirname(self):
     file_system = FakeFileSystem()
     assert "/path/to" == file_system.dirname("/path/to/file.txt")
Example #16
0
 def test_join(self):
     file_system = FakeFileSystem()
     assert "/path/to/mypackage/file.py" == file_system.join(
         "/path/to", "mypackage", "file.py")
Example #17
0
 def test_split(self):
     file_system = FakeFileSystem()
     assert ("/path/to/mypackage",
             "file.py") == file_system.split("/path/to/mypackage/file.py")
Example #18
0
 def test_empty_if_directory_does_not_exist(self):
     file_system = FakeFileSystem("""
         /path/to/mypackage/
             __init__.py
     """)
     assert [] == list(file_system.walk("/path/to/nonexistent/package"))