bazel-contrib / bazel-contrib/rules_python

Bazel can overwrite __init__.py with empty file in source tree

Open
#2,947 5 comments 0 reactions 0 assignees View on GitHub
core-rules type: bug
Dominant language
Starlark
Stars
688
Forks
721
Avg merge
15h 7m
Merged PRs (30d)
76

Description

### Description of the bug:

If I mess up my BUILD structure, and forget to include `srcs = ["__init__.py"]`, it seems it can happen that Bazel overwrites the existing `__init__.py` with an empty file.

### Reproduce:

Setup the directory:
```
cd $(mktemp -d)
cat > MODULE.bazel <<-EOF
module(name = "test_module")

bazel_dep(name = "rules_python", version = "1.4.1")
EOF
mkdir some_package
cat > some_package/BUILD.bazel <<-EOF
load("@rules_python//python:defs.bzl", "py_library", "py_test")
py_library(
name = "_some_library",
srcs = ["_some_library.py"],
)
py_library(
name = "some_package",
srcs = ["__init__.py"],
deps = [":_some_library"],
)
py_test(
name = "correct_test",
srcs = ["test.py"],
main = "test.py",
deps = [":some_package"],
)
py_test(
name = "bad_dep_test",
srcs = ["test.py"],
main = "test.py",
deps = [":_some_library"],
)
EOF
cat > some_package/__init__.py <<-EOF
import some_package._some_library
method=_some_library.method
EOF
cat > some_package/_some_library.py <<-EOF
def method():
pass
EOF
cat > some_package/test.py <<-EOF
import some_package
some_package.method()
EOF
```

Double check the with `tree`. This gives:
```
.
├── MODULE.bazel
└── some_package
├── BUILD.bazel
├── __init__.py
├── _some_library.py
└── test.py
```

Run the good test -- it will pass.
```
bazel test //some_package:correct_test
```

Then run the bad test. It fails and overwrites `__init__.py`.
```
bazel test //some_package:bad_dep_test
```

The run the good test. It now fails.
```
bazel test //some_package:correct_test
```

Note: Setting common --incompatible_default_to_explicit_init_py in .bazelrc fixes this.

See also https://github.com/bazel-contrib/rules_python/issues/2945.

Contributor guide

Open the contributing guide

Research direction

Reproduce the behavior from the issue using MODULE.bazel and some_package/BUILD.bazel, then inspect how the two py_test targets handle some_package/__init__.py. Run correct_test, bad_dep_test, and correct_test again to confirm the overwrite; done means the bad test no longer empties the source file and the good test continues to pass.

Written by the indexing model from the issue text.

Assessment

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

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.