"""Run ruff check and/or format on Python files across the project.
Mode is the first positional argument; remaining args are forwarded to ruff:
check -- ruff check --fix --show-fixes (pass --no-fix for CI verify mode)
format -- ruff format
both -- check then format (default when no mode given)
Usage:
bazel run //py:ruff-check -- [ruff check args]
bazel run //py:ruff-format -- [ruff format args]
bazel run //py:ruff -- [ruff check+format args]
"""
import os
import subprocess
import sys
from python.runfiles import Runfiles
ALL_DIRS = ["py", "scripts", "common", "dotnet", "java", "javascript", "rb"]
EXCLUDES = ["**/node_modules/**", "**/.bundle/**", "**/bidi/**", "**/devtools/**"]
def run_check(ruff, exclude_args, dirs, extra_args):
cmd = [ruff, "check", "--fix", "--show-fixes", "--config=py/pyproject.toml"]
return subprocess.run(cmd + exclude_args + dirs + extra_args).returncode
def run_format(ruff, exclude_args, dirs, extra_args):
cmd = [ruff, "format", "--config=py/pyproject.toml"]
return subprocess.run(cmd + exclude_args + dirs + extra_args).returncode
if __name__ == "__main__":
r = Runfiles.Create()
ruff = r.Rlocation("rules_multitool++multitool+multitool/tools/ruff/ruff")
os.chdir(os.environ["BUILD_WORKSPACE_DIRECTORY"])
exclude_args = []
for pattern in EXCLUDES:
exclude_args.extend(["--exclude", pattern])
mode = "both"
extra_args = sys.argv[1:]
if extra_args and extra_args[0] in ("check", "format", "both"):
mode = extra_args[0]
extra_args = extra_args[1:]
if mode == "check":
sys.exit(run_check(ruff, exclude_args, ALL_DIRS, extra_args))
elif mode == "format":
sys.exit(run_format(ruff, exclude_args, ALL_DIRS, extra_args))
else:
rc_check = run_check(ruff, exclude_args, ALL_DIRS, extra_args)
rc_format = run_format(ruff, exclude_args, ALL_DIRS, extra_args)
sys.exit(max(rc_check, rc_format))