theoremlp / rules_mypy

a Bazel mypy aspect
Apache License 2.0
18 stars 6 forks source link

How to exclude files from being analysed? #32

Closed antspy closed 1 month ago

antspy commented 1 month ago

Hi,

I have setup mypy to automatically run on my bazel builds and tests. Thank you for the cool project! :)

I am using the py_pytest_main rule for tests from rules_py like so:

py_pytest_main(
    name = "__test__",
    deps = ["@pip//pytest"],
)

py_test(
    name = "mytest",
    size = "small",
    srcs = [
        "mytest.py",
        ":__test__",
    ],
    main = ":__test__.py",
    package_collisions = "warning",
    deps = [
        ":__test__",
        ":mylib",
    ],
)

The problem is that the library generates this __test.py__ file which mypy is not happy about. I have tried excluding it - this is the content of mypy.ini:

[mypy]
follow_imports = silent
follow_imports_for_stubs = true
exclude = .*__test__\.py$

but the build still fails with bazel-out/k8-fastbuild/bin/mypath/__test__.py:42: error: Need type annotation for "user_args" (hint: "user_args: list[<type>] = ...") [var-annotated].

I have verified that the mypy.ini file is taken into account, because if I change follow_imports from silent to normal, a lot more errors show up. So the problem seems to be that the exclude doesn't work, for some reason.

I believe the full invocation is:

bazel-out/k8-opt-exec-ST-95e819d23b38/bin/external/rules_mypy~/mypy/private/mypy --output bazel-out/k8-fastbuild/bin/mypath/__test__.mypy_stdout --cache-dir bazel-out/k8-fastbuild/bin/mypath/__test__.mypy_cache bazel-out/k8-fastbuild/bin/mypath/__test__.py --mypy-ini mypy.ini

I have also tried adding the tags = ["no-mypy"], to the py_pytest_main target above, but it results in the same error. (If I add the tag to mytest, then it's respected and the build runs fine, but that will actually prevent the test from being checked. I only want to stop mypy from checking the __test__.py file.

Any help will be greatly appreciated. Thank you! :)

mark-thm commented 1 month ago

If I'm reading correctly, you tried:

py_pytest_main(
    name = "__test__",
    deps = ["@pip//pytest"],
    tags = ["no-mypy"],
)
...

This will remove type-checking from this target, but not from mytest -- you explicitly include the py_pytest_main output as a source file in mytest:

    srcs = [
        "mytest.py",
        ":__test__",
    ],

The mypy.ini exclude does not work, I think, because we explicitly pass all the source files as arguments (as far as I can tell we have to do things this way).

As a workaround, you can define a macro for your py_test that will type-check your test sources while suppressing type checking on the test itself, something like:

def custom_py_test(name, srcs = [], deps = [], tags = [], **kwargs):
    py_library(
        name = name + ".lib"
        srcs = srcs,
        deps = deps,
        tags = tags,
    )

    py_test(
        name = name,
        size = "small",
        srcs = [":__test__"] + srcs,
        main = ":__test__.py",
        package_collisions = "warning",
        deps = [":__test__"] + deps,
        tags = ["no-mypy"] + tags,
        **kwargs
    )

Aside from that, we'd need to look at adding source-level suppressions, but I think the API might end up pretty awkward.

antspy commented 1 month ago

Thanks a lot for your quick answer! Let me try it and I will report back :)

antspy commented 1 month ago

That worked! Thank you for the workaround :)