bazel-contrib / bazel-contrib/rules_mypy

'Module has no attribute "xxx"' when mixing `py_binary` deps and `__init__` reexports

Open
#74 2 comments 0 reactions 0 assignees View on GitHub
Dominant language
Starlark
Stars
12
Forks
13
PR merge metrics
No merged PRs in 30d

Description

Thanks for the great work on this project! We've adopted it throughout parts of our monorepo and we really like it.

While trying to expand our usage of `rules_mypy`, I've run into an issue which I believe is a bug. I was able to produce a minimal example, which seems to have something to do with `__init__.py` files that depend on `py_binary` targets (rather than `py_library`).

For clarity, `rules_python` allows depending on `py_binary` targets as if they were `py_library`s. There isn't really any difference, except the presence of a `if __name__ == "__main__":` block which is ignored. We have several library files with small main sections at the bottom for ad-hoc debugging.

# MRE

`example/BUILD.bazel`
```
py_binary(
name = "main",
srcs = ["main.py"],
deps = ["//example/foo:__init__"],
)
```

`example/main.py`
```python
import example.foo as foo

if __name__ == "__main__":
print(foo.do_something())
```

`example/foo/BUILD.bazel`
```
py_library(
name = "__init__",
srcs = ["__init__.py"],
deps = [":a"],
)

py_binary(
name = "a",
srcs = ["a.py"],
)
```

`example/foo/__init__.py`
```python
from example.foo.a import do_something

__all__ = ["do_something"]
```

`example/foo/a.py`
```python
def do_something():
return "hello"

if __name__ == "__main__":
print(do_something())
```

## Result

When I run `bazel build //example/...` I see the following error:

```bash
example/main.py:4: error: Module has no attribute "do_something" [attr-defined]
```

Removing the `if __name__ == "__main__"` from `a.py` and switching to a `py_library` target causes this example to succeed. Outside of bazel, mypy does not complain about either case.

Contributor guide

Open the contributing guide

Research direction

Start with the minimal reproduction in example/BUILD.bazel, example/main.py, example/foo/BUILD.bazel, example/foo/__init__.py, and example/foo/a.py. Run bazel build //example/... and compare the py_binary dependency case with the py_library case; done means the reproduced import no longer reports the missing do_something attribute.

Written by the indexing model from the issue text.

Assessment

Tech stack
python
Domain
build-system, tooling
Issue type
Bug
Difficulty
4/5
Estimated time
3-5 days
Activity status
Stale
Clarity
Clearly specified
Newbie friendliness
52/100

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.