Skip to content

Use explicit __init__.py files instead of implicit creation - #1082

Open
onnosteenbergen-samotics wants to merge 3 commits into
bazelbuild:mainfrom
onnosteenbergen-samotics:explicit-init-py
Open

onnosteenbergen-samotics wants to merge 3 commits into
bazelbuild:mainfrom
onnosteenbergen-samotics:explicit-init-py

Conversation

@onnosteenbergen-samotics

@onnosteenbergen-samotics onnosteenbergen-samotics commented Sep 28, 2026 •

Copy link
Copy Markdown

Fixes #1081.

rules_python warns for executables that rely on implicit __init__.py creation (bazel-contrib/rules_python#2945).

  • Add the missing __init__.py files to the packages under pkg/ that are imported, and put each one in the srcs of a py_library (//pkg:init, //pkg/private:init).
  • Enable explicit_init_py for the rules_pkg module. This requires rules_python 2.3.0 as the new minimum.
  • Add //tests:explicit_init_test, which fails if a package is imported as a namespace package.
  • Read Windows runfiles junctions with os.readlink in verify_archive_test, pkg_install and the tests (//tests/util:runfiles_util). rules_python ≥ 1.9 enables runfiles trees on Windows, where file runfiles may be junctions that can't be opened. os.path.realpath fails on these with WinError 267, so this also replaces the fix from fix(install): follow Windows runfiles junctions when copying files #1076.

The module setting only covers rules_pkg's own targets (build_tar, build_zip, make_deb, …). Targets created by pkg_install and verify_archive_test belong to the calling module, so users silence those by setting explicit_init_py in their own MODULE.bazel (or passing --incompatible_default_to_explicit_init_py).

@google-cla

google-cla Bot commented Sep 28, 2026

Copy link
Copy Markdown

Thanks for your pull request! It looks like this may be your first contribution to a Google open source project. Before we can look at your pull request, you'll need to sign a Contributor License Agreement (CLA).

View this failed invocation of the CLA check for more information.

For the most up to date status, view the checks section at the bottom of the pull request.

@onnosteenbergen-samotics

Copy link
Copy Markdown
Author

I've signed the CLA, but the co-author is Claude.ai. Don't know how to solve that one.

@tonyaiuto tonyaiuto left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Have you tried this without setting legacy_create_init? ISTM that it should still work without that, and be backwards compatible with older python rules

@aiuto

aiuto commented Sep 30, 2026

Copy link
Copy Markdown
Collaborator

I've signed the CLA, but the co-author is Claude.ai. Don't know how to solve that one.

The only author that matters is onnosteenbergen-samotics.
The check is failling. Did you use that github identity?

@onnosteenbergen-samotics

Copy link
Copy Markdown
Author

Re-ran the check and it still marks Claude as failed.

Will verify if legacy_init_create = 0 is required, would indeed make sense to leave it out.

@onnosteenbergen-samotics

Copy link
Copy Markdown
Author
┌─────────────────────────────────────────────────────────────────────┬──────────────┬──────────┐
│                          rules_pkg variant                          │ rules_python │ Warnings │
├─────────────────────────────────────────────────────────────────────┼──────────────┼──────────┤
│ with legacy_create_init = 0                                         │ 2.3.2        │ 0        │
├─────────────────────────────────────────────────────────────────────┼──────────────┼──────────┤
│ without                                                             │ 2.3.2        │ 5        │
├─────────────────────────────────────────────────────────────────────┼──────────────┼──────────┤
│ with                                                                │ 1.7.0        │ 0        │
├─────────────────────────────────────────────────────────────────────┼──────────────┼──────────┤
│ without                                                             │ 1.7.0        │ 0        │
├─────────────────────────────────────────────────────────────────────┼──────────────┼──────────┤
│ without, consumer passes --incompatible_default_to_explicit_init_py │ 2.3.2        │ 0        │
└─────────────────────────────────────────────────────────────────────┴──────────────┴──────────┘

The 5 warnings in the "without" run on 2.3.2:

WARNING: Target @@rules_pkg+//pkg/private/tar:build_tar is using implicit __init__.py creation.
WARNING: Target @@//:demo_install is using implicit __init__.py creation.
WARNING: Target @@rules_pkg+//pkg/private/zip:build_zip is using implicit __init__.py creation.
WARNING: Target @@//:demo_tar_test is using implicit __init__.py creation.
WARNING: Target @@rules_pkg+//pkg/private/deb:make_deb is using implicit __init__.py creation.

The tar, zip and deb outputs had the same sha256 in every run (e.g. demo_tar.tar is 0639fb21…).

  • The warning doesn't look at the files. rules_python 2.3.2 decides only from the target's legacy_create_init, then the owning module's explicit_init_py config, then the CLI flag. Whether __init__.py files exist doesn't matter, so this might be something that rules_python needs to fix.
  • rules_pkg could set explicit_init_py in its own MODULE.bazel, but that requires rules_python 2.3 or newer as a minimum. The attribute works on 1.7.0, the version rules_pkg currently requires.
  • Without the attribute, users can silence the warning themselves with the flag (last row of the table). Before this PR, that flag didn't make the packages proper Python packages.

@aiuto

aiuto commented Oct 6, 2026

Copy link
Copy Markdown
Collaborator

The legacy_init thing is such an ugly wart to work around a library being extra verbose.
Since you seem to have claude doing this, why don't you try it without any of that, but add in the missing init.py to all the packages missing it.

And you also have to figure out the CLA. Try dropping any mention of claude from the PR description.

rules_python now warns for every executable target that relies on
implicit __init__.py creation (bazel-contrib/rules_python#2945), so
depending on rules_pkg prints that warning for build_tar, build_zip,
make_deb, and for targets created by pkg_install and
verify_archive_test.

Add the missing __init__.py files (pkg/private/tar, pkg/private/deb),
put every __init__.py in the srcs of a py_library (//pkg:init,
//pkg/private:init) that the importing libraries depend on, and set
legacy_create_init = 0 on all py_binary and py_test targets under pkg/.

The per-target attribute is used rather than the module-wide
explicit_init_py setting because the latter requires rules_python 2.3.
@onnosteenbergen-samotics

Copy link
Copy Markdown
Author

I'd picked the legacy_init route to not force an upgrade of rules_python to 2.3.0. The upgrade it triggering some extra issues on Windows it seems.

About the CLA: I've removed Claude as Co-Author, but for a repository with a CLAUDE.md I would suggest updating the CLA script to allow AI submissions. Not tagging commits as done by AI is in my opinion worse.

@onnosteenbergen-samotics
onnosteenbergen-samotics force-pushed the explicit-init-py branch 2 times, most recently from 5b1cca8 to 3a061a7 Compare October 7, 2026 07:42
Drop legacy_create_init = 0 from all targets and instead enable the
rules_python explicit_init_py setting for the rules_pkg module, which
requires raising the minimum rules_python version to 2.3.0.

The setting only applies to targets in rules_pkg itself. Targets created
by pkg_install and verify_archive_test belong to the calling module, so
users silence those by setting explicit_init_py in their own MODULE.bazel
(or with --incompatible_default_to_explicit_init_py).
Since rules_python 1.9, py_binary/py_test default to --enable_runfiles
on Windows. Bazel may then create a directory junction for a file
runfile, which can not be opened or executed ("Permission denied").
Raising the minimum rules_python to 2.3.0 exposed this in our Windows
tests and in verify_archive_test.

os.path.realpath does not help: on Windows it fails on such a junction
with WinError 267. Read the junction target with os.readlink instead,
in verify_archive_test, in pkg_install (replacing the realpath from
bazelbuild#1076) and, through //tests/util:runfiles_util, in the tests.
@onnosteenbergen-samotics

Copy link
Copy Markdown
Author

PR is in working condition again, it now is more a rules_python upgrade to 2.3.0 then just the fix for the original warnings.

@onnosteenbergen-samotics

onnosteenbergen-samotics commented Oct 9, 2026 •

Copy link
Copy Markdown
Author

@aiuto Do you have any remaining feedback on this PR?

yes. Now you're mixing things . This was supposed to be about init, and now it has a fix to pkg_install.
Can you back that out and let's deal with it separately.
It feels like you're letting a coding agent drive "things that can be done", rather than thinking it through.
This module is used by virtually every project, backwards compatibility wins over fixes many times.

@aiuto

aiuto commented Oct 14, 2026

Copy link
Copy Markdown
Collaborator

ISTM that the original intent can be a tiny PR. See #1087

This branch has not been deployed

No deployments
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Targets rely on implicit __init__.py creation, causing rules_python deprecation warnings

3 participants