Motivation
To ensure a consistent Python code style across the project and automate a manual, error-prone process, we should integrate the black code formatter directly into our Bazel build system. We already use black in our CI pipeline, but don't expose it for local usage.
Below is a proposed approach, but we're open to do thing this other ways.
Proposed Solution
We will implement two separate Bazel targets to achieve this:
-
A bazel run Target for Fixing:
- A target named
black_fix will be created.
- Running
bazel run //:black_fix -- . will execute black on the entire workspace, reformatting any non-compliant Python files in-place.
-
A bazel test Target for Checking (Optional):
- A target named
black_check will be created.
- Running
bazel test //:black_check (or as part of bazel test //...) will execute black --check --diff.
- This test will pass if all files are correctly formatted and fail otherwise, printing a diff of the required changes. This is ideal for CI integration.
Implementation Plan
-
Add black as a Bazel Dependency:
- Modify
MODULE.bazel to use the pip.parse extension from rules_python.
- Create a
requirements.txt file to declare a dependency on black==24.8.0 and its necessary transitive dependencies.
-
Create a py_binary for the Formatter:
- In the root
BUILD file, define a py_binary target named black_binary.
- This target will use the
entry_point attribute set to "black" to directly use the black command-line tool provided by the pip package.
-
Implement the "Fix" Command:
- Create a
sh_binary named black_fix that simply calls the black_binary target with the provided arguments (e.g., . to format the whole project). This will be the user-facing command run with bazel run.
-
Implement the "Check" Test:
- Create a
sh_test named black_check.
- This test will execute the
black_binary target with the --check and --diff flags. The test will succeed only if black returns a zero exit code (indicating no changes are needed).
Motivation
To ensure a consistent Python code style across the project and automate a manual, error-prone process, we should integrate the
blackcode formatter directly into our Bazel build system. We already useblackin our CI pipeline, but don't expose it for local usage.Below is a proposed approach, but we're open to do thing this other ways.
Proposed Solution
We will implement two separate Bazel targets to achieve this:
A
bazel runTarget for Fixing:black_fixwill be created.bazel run //:black_fix -- .will executeblackon the entire workspace, reformatting any non-compliant Python files in-place.A
bazel testTarget for Checking (Optional):black_checkwill be created.bazel test //:black_check(or as part ofbazel test //...) will executeblack --check --diff.Implementation Plan
Add
blackas a Bazel Dependency:MODULE.bazelto use thepip.parseextension fromrules_python.requirements.txtfile to declare a dependency onblack==24.8.0and its necessary transitive dependencies.Create a
py_binaryfor the Formatter:BUILDfile, define apy_binarytarget namedblack_binary.entry_pointattribute set to"black"to directly use theblackcommand-line tool provided by the pip package.Implement the "Fix" Command:
sh_binarynamedblack_fixthat simply calls theblack_binarytarget with the provided arguments (e.g.,.to format the whole project). This will be the user-facing command run withbazel run.Implement the "Check" Test:
sh_testnamedblack_check.black_binarytarget with the--checkand--diffflags. The test will succeed only ifblackreturns a zero exit code (indicating no changes are needed).