bazel-contrib/bazel-mypy-integration

Target using pytest fail with "Untyped decorator makes function untyped"

wbekerom opened this issue · 2 comments

I just implemented this integration and for the most part things went smooth. But now I stumbled into a case that I cannot seem to solve, see the example below.

Running below in a virtual env where pytest is installed works, however running it from the base env (without pytest) fails. All other pip depencies do get loaded correctly via bazel, only a few pytest decorators give errors. Running mypy test_foo.py also passes in the virutalenv (using the same mypy.ini file).

I'm relatively new to bazel and mypy, so not sure where to start digging. Any thoughts?

WORKSPACE

workspace(name = "myproject")
load("@bazel_tools//tools/build_defs/repo:http.bzl", "http_archive")

#############################################################################
# Python Rules
#############################################################################
http_archive(
    name = "rules_python",
    sha256 = "b6d46438523a3ec0f3cead544190ee13223a52f6a6765a29eae7b7cc24cc83a0",
    url = "https://github.com/bazelbuild/rules_python/releases/download/0.1.0/rules_python-0.1.0.tar.gz",
)
load("@rules_python//python:repositories.bzl", "py_repositories")
py_repositories()
load("@rules_python//python:pip.bzl", "pip_install")

# Create a central repo that knows about the dependencies needed for
# requirements.txt.
pip_install(
    name = "eng_pip_deps",
    requirements = "//:requirements.txt",
)

#############################################################################
# Mypy aspect plugin
#############################################################################
mypy_integration_version = "0.1.0"  # latest @ November 15th 2020
http_archive(
    name = "mypy_integration",
    sha256 = "511ca642294129b7abebf6afd48aa63e7d91de3ec5fa0689d60d1dc6a94a7d1a",
    strip_prefix = "bazel-mypy-integration-{version}".format(version = mypy_integration_version),
    url = "https://github.com/thundergolfer/bazel-mypy-integration/archive/{version}.tar.gz".format(
        version = mypy_integration_version,
    ),
)
load(
    "@mypy_integration//repositories:repositories.bzl",
    mypy_integration_repositories = "repositories",
)
mypy_integration_repositories()
load("@mypy_integration//:config.bzl", "mypy_configuration")
mypy_configuration(mypy_config_file = "//:mypy.ini")
load("@mypy_integration//repositories:deps.bzl", mypy_integration_deps = "deps")
mypy_integration_deps(mypy_requirements_file = "//:mypy_version.txt")

BUILD

load("@eng_pip_deps//:requirements.bzl", "requirement")
load("@rules_python//python:defs.bzl", "py_test")

py_test(
    name = "test_foo",
    srcs = ["test_foo.py"],
    python_version = "PY3",
    deps = [
        requirement("pytest"),
        requirement("pytest-asyncio"),
    ],
)

test_foo.py

import pytest

@pytest.mark.asyncio
async def test_foo_noop() -> None:
    pass

result

$ bazel build //:test_foo                                                                                                                                                                       [16:49:26]
(16:49:33) INFO: Current date is 2021-01-19
(16:49:33) INFO: Analyzed target //:test_foo (0 packages loaded, 0 targets configured).
(16:49:33) INFO: Found 1 target...
(16:49:34) ERROR: /home/myproject/BUILD:4:8: Couldn't build file test_foo_dummy_out: Type-checking //:test_foo failed (Exit 1): test_foo_mypy_exe failed: error executing command bazel-out/k8-fastbuild/bin/test_foo_mypy_exe

Use --sandbox_debug to see verbose messages from the sandbox test_foo_mypy_exe failed: error executing command bazel-out/k8-fastbuild/bin/test_foo_mypy_exe

Use --sandbox_debug to see verbose messages from the sandbox
test_foo.py:3: error: Untyped decorator makes function "test_foo_noop" untyped
    @pytest.mark.asyncio
     ^
Found 1 error in 1 file (checked 1 source file)
Aspect @mypy_integration//:mypy.bzl%mypy_aspect of //:test_foo failed to build
Use --verbose_failures to see the command lines of failed build steps.
(16:49:34) INFO: Elapsed time: 1.803s, Critical Path: 1.61s
(16:49:34) INFO: 2 processes: 2 internal.
(16:49:34) FAILED: Build did NOT complete successfully
FAIL

To add to this, I noted that I was ignoring missing imports for mypy-pytest.*. I now removed this such that my ini looks like:

mypy.ini

[mypy]
pretty = True
strict = True

And I get the following from bazel build:

test_foo.py:2: error: Cannot find implementation or library stub for module
named 'pytest'
    import pytest
    ^
test_foo.py:2: note: See https://mypy.readthedocs.io/en/latest/running_mypy.html#missing-imports
test_foo.py:5: error: Untyped decorator makes function "test_foo_noop" untyped
    @pytest.mark.asyncio
     ^
Found 2 errors in 1 file (checked 1 source file)

The folder bazel-out/k8-fastbuild/bin/test_foo.runfiles/eng_pip_deps/pypi__pytest does exist, but for some reason mypy cannot find it.

When running mypy directly on a virtualenv with only pytest installed it passes.

Thanks for the issue report. The main repo I work on that has the integration in use has:

[mypy-pytest]
ignore_missing_imports = True

So there's likely something going wrong here.