Fix mypy linting non-python source files with custom rules (#105)
If you write a custom rule that is designed to interop with python rules
you need to return PyInfo, in this case rules_mypy was attempting to
lint the source files of the target even if they were not python. This
is now scoped to only `.py` and `.pyi` files.
One example case for this is if you write a custom rule that creates a
python native extension and you want to be able to add it to the `deps`
of python rules.
diff --git a/examples/demo/custom_rule/BUILD.bazel b/examples/demo/custom_rule/BUILD.bazel
new file mode 100644
index 0000000..a8eac7c
--- /dev/null
+++ b/examples/demo/custom_rule/BUILD.bazel
@@ -0,0 +1,6 @@
+load(":foo.bzl", "foo")
+
+foo(
+ name = "foo",
+ srcs = ["foo.txt"],
+)
diff --git a/examples/demo/custom_rule/foo.bzl b/examples/demo/custom_rule/foo.bzl
new file mode 100644
index 0000000..64a85b0
--- /dev/null
+++ b/examples/demo/custom_rule/foo.bzl
@@ -0,0 +1,22 @@
+"""A custom rule that exposes PyInfo"""
+
+load("@rules_python//python:py_info.bzl", "PyInfo")
+
+def _impl(ctx):
+ return [
+ DefaultInfo(
+ files = depset(ctx.files.srcs),
+ ),
+ PyInfo(
+ transitive_sources = depset(ctx.files.srcs),
+ ),
+ ]
+
+foo = rule(
+ implementation = _impl,
+ attrs = {
+ "data": attr.label_list(allow_files = True),
+ "srcs": attr.label_list(allow_files = True),
+ "deps": attr.label_list(),
+ },
+)
diff --git a/examples/demo/custom_rule/foo.txt b/examples/demo/custom_rule/foo.txt
new file mode 100644
index 0000000..22cfb2b
--- /dev/null
+++ b/examples/demo/custom_rule/foo.txt
@@ -0,0 +1 @@
+Invalid python syntax example
diff --git a/mypy/private/mypy.bzl b/mypy/private/mypy.bzl
index 35467b7..b788973 100644
--- a/mypy/private/mypy.bzl
+++ b/mypy/private/mypy.bzl
@@ -84,6 +84,15 @@
if not hasattr(ctx.rule.files, "srcs"):
return []
+ # Exclude non-python sources from custom rules that return PyInfo
+ lintable_srcs = [
+ s
+ for s in ctx.rule.files.srcs
+ if "/_virtual_imports/" not in s.short_path and s.extension in ("py", "pyi")
+ ]
+ if not lintable_srcs:
+ return []
+
# we need to help mypy map the location of external deps by setting
# MYPYPATH to include the site-packages directories.
external_deps = {}
@@ -188,7 +197,7 @@
outputs = [output_file]
args.add_all([c.path for c in upstream_caches], before_each = "--upstream-cache")
- args.add_all([s for s in ctx.rule.files.srcs if "/_virtual_imports/" not in s.short_path])
+ args.add_all(lintable_srcs)
if hasattr(ctx.attr, "_mypy_ini"):
args.add("--mypy-ini", ctx.file._mypy_ini.path)