### Bazel Downloader Configuration Example Source: https://github.com/bazel-contrib/rules_python/blob/main/docs/pypi/download.md This is an example configuration file for the Bazel downloader, used to redirect downloads to an internal mirror. It demonstrates how to block and rewrite URLs for custom registry setups. ```cfg all_blocked_message See internal.mirror.lan/registry/ for more information allow s3.amazon.com # Rewrite everything to files.pythonhosted to the internal mirror with two # capture groups: the first group matches the host and is appended first, # the second matches the entire path and is appended second rewrite (files.pythonhosted.org)/(.*) internal.mirror.lan/python/$1/$2 rewrite (pypi.python.org)/(.*) internal.mirror.lan/python/$1/$2 # Allow the internal mirror and block everything else allow internal.mirror.lan block * ``` -------------------------------- ### Start the default REPL Source: https://github.com/bazel-contrib/rules_python/blob/main/docs/repl.md Use this command to start the default REPL. The environment aims to be identical to what a py_binary creates. ```console $ bazel run @rules_python//python/bin:repl Python 3.11.11 (main, Mar 17 2025, 21:02:09) [Clang 20.1.0 ] on linux Type "help", "copyright", "credits" or "license" for more information. >>> ``` -------------------------------- ### Build and serve documentation Source: https://github.com/bazel-contrib/rules_python/blob/main/sphinxdocs/tests/sphinx_stardoc/index.md Executes the Bazel target to build the documentation and start a local HTTP server. ```bash bazel run //tests/sphinx_stardoc:docs.serve ``` -------------------------------- ### Pre-commit installation error log Source: https://github.com/bazel-contrib/rules_python/blob/main/CONTRIBUTING.md Example of an error output encountered during git commit when pre-commit hooks fail to install or execute. ```text [INFO] Installing environment for https://github.com/psf/black. [INFO] Once installed this environment will be reused. [INFO] This may take a few minutes... An unexpected error has occurred: CalledProcessError: command: ... ``` -------------------------------- ### Python Proto Generation Example Source: https://github.com/bazel-contrib/rules_python/blob/main/gazelle/docs/directives.md Example of generated `proto_library` and `py_proto_library` rules when `python_generate_proto` is enabled. ```starlark load("@protobuf//bazel:py_proto_library.bzl", "py_proto_library") load("@rules_proto//proto:defs.bzl", "proto_library") # gazelle:python_generate_proto true proto_library( name = "foo_proto", srcs = ["foo.proto"], visibility = ["//:__subpackages__"], ) py_proto_library( name = "foo_py_pb2", visibility = ["//:__subpackages__"], deps = [":foo_proto"], ) ``` -------------------------------- ### Install ibazel on Linux Source: https://github.com/bazel-contrib/rules_python/blob/main/docs/README.md Installs the ibazel tool globally using npm, which is used for automatically rebuilding documentation during development. Ensure npm is installed first. ```bash sudo apt install npm sudo npm install -g @bazel/ibazel ``` -------------------------------- ### Install and Set Up Python with pyenv Source: https://github.com/bazel-contrib/rules_python/blob/main/CONTRIBUTING.md Install `pyenv` to manage Python versions and then install and set Python 3.9.15 for development. The `pyenv shell` command sets the version for the current shell session. ```shell curl https://pyenv.run | bash pyenv install 3.9.15 pyenv shell 3.9.15 ``` -------------------------------- ### Example requirements.in Source: https://context7.com/bazel-contrib/rules_python/llms.txt A sample requirements.in file listing direct dependencies. This file is used as input for compile_pip_requirements. ```text # requirements.in requests>=2.28.0 numpy>=1.24.0 pandas>=2.0.0 pytest>=7.0.0 # dev dependency ``` -------------------------------- ### Install Pre-commit Hooks Source: https://github.com/bazel-contrib/rules_python/blob/main/CONTRIBUTING.md Install the `pre-commit` tool and then set up the Git pre-commit hooks for the repository. This automates code formatting and linting checks before commits are made. ```shell pre-commit install ``` -------------------------------- ### Start Python REPL Source: https://context7.com/bazel-contrib/rules_python/llms.txt Launch an interactive shell with project dependencies. Supports custom configurations via .bazelrc. ```bash # Basic REPL with default Python version bazel run @rules_python//python/bin:repl # REPL with specific Python version bazel run @rules_python//python/bin:repl \ --@rules_python//python/config_settings:python_version=3.12 # REPL with access to a specific target's dependencies bazel run @rules_python//python/bin:repl \ --@rules_python//python/bin:repl_dep=//my_package:my_lib # Run Python interpreter directly bazel run @rules_python//python/bin:python ``` ```bash # .bazelrc build --@rules_python//python/bin:repl_stub_dep=@pypi//ipython build --@rules_python//python/bin:repl_stub=//tools:ipython_stub.py ``` ```python # tools/ipython_stub.py import IPython IPython.start_ipython() ``` -------------------------------- ### Generate pyi Sources Example Source: https://github.com/bazel-contrib/rules_python/blob/main/gazelle/docs/directives.md Example of a generated `py_library` target that includes sibling `.pyi` files in the `pyi_srcs` attribute. ```starlark py_library( name = "foo", srcs = ["foo.py"], pyi_srcs = ["foo.pyi"], ) ``` -------------------------------- ### Define a py_binary with requirement dependencies Source: https://github.com/bazel-contrib/rules_python/blob/main/docs/pypi/circular-dependencies.md Example of a standard py_binary rule using a requirement from PyPI. ```starlark py_binary( name = "doctool", ... deps = [ requirement("sphinx"), ], ) ``` -------------------------------- ### Serve and Rebuild Docs Locally Source: https://github.com/bazel-contrib/rules_python/blob/main/docs/README.md Use this command to start a local HTTP server for viewing generated docs and automatically rebuild them as sources change. Run the serve command in a separate terminal. ```bash bazel run //docs:docs.serve # Run in separate terminal ibazel build //docs:docs # Automatically rebuilds docs ``` -------------------------------- ### Using MODULE.bazel toolchains in WORKSPACE Source: https://github.com/bazel-contrib/rules_python/blob/main/docs/toolchains.md Integrate Python toolchains defined in MODULE.bazel into a legacy WORKSPACE setup using the *_host repository. ```starlark # File: WORKSPACE load("@rules_python//python:repositories.bzl", "py_repositories") py_repositories() load("@rules_python//python:pip.bzl", "pip_parse") pip_parse( name = "third_party", requirements_lock = "//:requirements.txt", python_interpreter_target = "@python_3_10_host//:python", ) load("@third_party//:requirements.bzl", "install_deps") install_deps() # File: MODULE.bazel bazel_dep(name = "rules_python", version = "0.40.0") python = use_extension("@rules_python//python/extensions:python.bzl", "python") python.defaults(python_version = "3.10") python.toolchain(python_version = "3.10") use_repo(python, "python_3_10", "python_3_10_host") ``` -------------------------------- ### Configure .readthedocs.yaml for Bazel Source: https://github.com/bazel-contrib/rules_python/blob/main/sphinxdocs/docs/readthedocs.md Use the advanced `build.commands` in `.readthedocs.yaml` to install Bazel and run your build script. This ensures Bazel handles the documentation build process. ```yaml # File: .readthedocs.yaml version: 2 build: os: "ubuntu-22.04" tools: nodejs: "19" commands: - env - npm install -g @bazel/bazelisk - bazel version # Put the actual action behind a shell script because it's # easier to modify than the yaml config. - docs/readthedocs_build.sh ``` -------------------------------- ### Register Hermetic Toolchain and Install Dependencies Source: https://github.com/bazel-contrib/rules_python/blob/main/examples/pip_parse_vendored/README.md Use this to register a hermetic Python toolchain and then install dependencies. Ensure the toolchain is correctly registered before calling install_deps. ```python load("@rules_python//python:repositories.bzl", "python_register_toolchains") python_register_toolchains( name = "python39", python_version = "3.9", ) # Load dependencies vendored by some other ruleset. load("@some_rules//:py_deps.bzl", "install_deps") install_deps( python_interpreter_target = "@python39_host//:python", ) ``` -------------------------------- ### Configure Local Python Runtime and Toolchains Source: https://github.com/bazel-contrib/rules_python/blob/main/docs/toolchains.md Set up a local Python runtime and create corresponding Bazel toolchains. This allows Bazel to use a Python installation from your system's PATH. Ensure `dev_dependency = True` is set for the root module only. ```starlark # File: MODULE.bazel local_runtime_repo = use_repo_rule( "@rules_python//python/local_toolchains:repos.bzl", "local_runtime_repo", ) local_runtime_toolchains_repo = use_repo_rule( "@rules_python//python/local_toolchains:repos.bzl", "local_runtime_toolchains_repo", ) # Step 1: Define the Python runtime local_runtime_repo( name = "local_python3", interpreter_path = "python3", on_failure = "fail", dev_dependency = True ) # Step 2: Create toolchains for the runtimes local_runtime_toolchains_repo( name = "local_toolchains", runtimes = ["local_python3"], # TIP: The `target_settings` arg can be used to activate them based on # command line flags; see docs below. dev_dependency = True ) # Step 3: Register the toolchains register_toolchains("@local_toolchains//:all", dev_dependency = True) ``` -------------------------------- ### Example of rendered documentation for Square type Source: https://github.com/bazel-contrib/rules_python/blob/main/sphinxdocs/docs/starlark-docgen.md This shows the final rendered output of the user-defined type documentation, including the typedef, fields, and functions, as it would appear in Sphinx. ```markdown :::{bzl:currentfile} //example:square.bzl ::: ::::{bzl:typedef} Square A square with fixed size :::{bzl:field} width :type: int ::: :::{bzl:function} new() ... ::: :::{bzl:function} area() ... ::: :::: ``` -------------------------------- ### Start REPL with a specific Python version Source: https://github.com/bazel-contrib/rules_python/blob/main/docs/repl.md Specify a different Python version for the REPL using Bazel flags. This allows testing code against different Python interpreters. ```console $ bazel run @rules_python//python/bin:repl --@rules_python//python/config_settings:python_version=3.13 Python 3.13.2 (main, Mar 17 2025, 21:02:54) [Clang 20.1.0 ] on linux Type "help", "copyright", "credits" or "license" for more information. >>> ``` -------------------------------- ### Run default Python interpreter Source: https://github.com/bazel-contrib/rules_python/blob/main/docs/toolchains.md Use this target to run the default Python interpreter that Bazel will use. No specific setup is required. ```console bazel run @rules_python//python/bin:python ``` -------------------------------- ### Build Documentation Source: https://github.com/bazel-contrib/rules_python/blob/main/AGENTS.md Command to generate API documentation files. ```bash bazel build //docs:docs ``` -------------------------------- ### Build and verify the output Source: https://github.com/bazel-contrib/rules_python/blob/main/docs/howto/get-python-version.md Commands to execute the build and display the generated version file content. ```bash bazel build :show_python_version cat bazel-bin/show_python_version.txt ``` -------------------------------- ### Configure Additional Interpreter Arguments Source: https://github.com/bazel-contrib/rules_python/blob/main/docs/environment-variables.md Examples of how RULES_PYTHON_ADDITIONAL_INTERPRETER_ARGS modifies the Python execution command. ```bash python -Xaaa /path/to/file.py ``` ```bash python /path/to/debugger.py --port 12345 --file /path/to/file.py ``` -------------------------------- ### Bootstrap Environment Initialization Source: https://github.com/bazel-contrib/rules_python/blob/main/python/private/python_bootstrap_template.txt Initializes the runtime environment by logging configuration variables and setting up the execution path. ```python print_verbose("initial sys.path:", values=sys.path) print_verbose("IS_ZIPFILE:", IS_ZIPFILE) print_verbose("PYTHON_BINARY:", PYTHON_BINARY) print_verbose("PYTHON_BINARY_ACTUAL:", PYTHON_BINARY_ACTUAL) print_verbose("RECREATE_VENV_AT_RUNTIME:", RECREATE_VENV_AT_RUNTIME) print_verbose("RESOLVE_PYTHON_BINARY_AT_RUNTIME:", RESOLVE_PYTHON_BINARY_AT_RUNTIME) print_verbose("RUNTIME_VENV_SYMLINKS size:", len(RUNTIME_VENV_SYMLINKS)) print_verbose("STAGE2_BOOTSTRAP:", STAGE2_BOOTSTRAP) print_verbose("VENV_REL_SITE_PACKAGES:", VENV_REL_SITE_PACKAGES) print_verbose("WORKSPACE_NAME:", WORKSPACE_NAME ) print_verbose("bootstrap sys.executable:", sys.executable) print_verbose("bootstrap sys._base_executable:", sys._base_executable) print_verbose("bootstrap sys.version:", sys.version) args = sys.argv[1:] new_env = {} # NOTE: We call normpath for two reasons: # 1. Transform Bazel `foo/bar` to Windows `foo\bar` # 2. Transform `_main/../foo/main.py` to simply `foo/main.py`, which # matters if `_main` doesn't exist (which can occur if a binary # is packaged and needs no artifacts from the main repo) main_rel_path = os.path.normpath(STAGE2_BOOTSTRAP) print_verbose("main_rel_path:", main_rel_path) ``` -------------------------------- ### Generated Imports Attribute Source: https://github.com/bazel-contrib/rules_python/blob/main/gazelle/docs/directives.md Example of how Gazelle adds the `imports` attribute to `py_library` targets when `python_root` is set. ```starlark # in ./src/foo/BUILD.bazel py_libary( ... imports = [".."], # Gazelle adds this ... ) # in ./src/foo/bar/BUILD.bazel py_libary( ... imports = ["../.."], # Gazelle adds this ... ) ``` -------------------------------- ### Create virtual environment for Python Source: https://github.com/bazel-contrib/rules_python/blob/main/python/private/python_bootstrap_template.txt Sets up a virtual environment directory structure, including symlinks for binaries and site-packages, handling platform-specific requirements for Windows and Unix. ```python def _create_venv(runfiles_root, delete_dirs): rel_runfiles_venv = dirname(dirname(PYTHON_BINARY)) runfiles_venv = join(runfiles_root, rel_runfiles_venv) print_verbose("create_venv: runfiles venv:", runfiles_venv) if EXTRACT_ROOT: venv = join(EXTRACT_ROOT, rel_runfiles_venv) os.makedirs(venv, exist_ok=True) else: import tempfile venv = tempfile.mkdtemp("", f"bazel.{basename(runfiles_venv)}.") delete_dirs.append(venv) print_verbose("create_venv: created venv:", venv) python_exe_actual = find_binary(runfiles_root, PYTHON_BINARY_ACTUAL) if python_exe_actual is None: raise AssertionError('Could not find python binary: ' + repr(PYTHON_BINARY_ACTUAL)) # See stage1_bootstrap_template.sh for details on this code path. In short, # this handles when the build-time python version doesn't match runtime # and if the initially resolved python_exe_actual is a wrapper script. if RESOLVE_PYTHON_BINARY_AT_RUNTIME: venv_src = venv.replace("\\", "\\\\") # Escape backslashes src = f""" import sys, site print(sys.executable) print(sys.base_prefix) print(site.getsitepackages(["{venv_src}"])[-1]) """ print_verbose("prog:", src) output = subprocess.check_output([python_exe_actual, "-I"], shell=True, encoding = "utf8", input=src) output = output.strip().split("\n") python_exe_actual = output[0] python_home = output[1] if IS_WINDOWS else None venv_site_packages = output[2] os.makedirs(dirname(venv_site_packages), exist_ok=True) runfiles_venv_site_packages = join(runfiles_venv, VENV_REL_SITE_PACKAGES) else: # On unixy, Python can find home based on the symlink. python_home = dirname(python_exe_actual) if IS_WINDOWS else None venv_site_packages = join(venv, "lib") runfiles_venv_site_packages = join(runfiles_venv, "lib") venv_bin = join(venv, BIN_DIR_NAME) try: os.mkdir(venv_bin) except FileExistsError as e: pass # Match the basename; some tools, e.g. pyvenv key off the executable name venv_python_exe = join(venv_bin, os.path.basename(python_exe_actual)) _symlink_exist_ok(from_=venv_python_exe, to=python_exe_actual) # Windows requires supporting .dll files in the venv bin dir, but # they aren't known in advance when the interpreter is resolved at runtime. if RESOLVE_PYTHON_BINARY_AT_RUNTIME and IS_WINDOWS: files = os.listdir(python_home) for f in files: if not f.endswith((".dll", ".pdb")): continue venv_path = join(venv, BIN_DIR_NAME, f) target = join(python_home, f) _symlink_exist_ok(from_=venv_path, to=target) runfiles_venv_bin = join(runfiles_venv, BIN_DIR_NAME) # The runfiles bin directory may not exist if it's empty, e.g. # supports_build_time_venv=False and the interpreter is resolved at # runtime. if os.path.exists(runfiles_venv_bin): # Add any missing build-time entries under bin/. Do this before # the manual symlink creation to better mimic what the # regular runfiles directory looks like. for f_basename in os.listdir(runfiles_venv_bin): venv_path = join(venv, BIN_DIR_NAME, f_basename) target = join(runfiles_venv_bin, f_basename) _symlink_exist_ok(from_=venv_path, to=target) for venv_rel_path, link_to_rf_path in RUNTIME_VENV_SYMLINKS.items(): venv_abs_path = join(venv, venv_rel_path) link_to = normpath(join(runfiles_venv, link_to_rf_path)) os.makedirs(dirname(venv_abs_path), exist_ok=True) _symlink_exist_ok(from_=venv_abs_path, to=link_to) _symlink_exist_ok(from_=join(venv, "lib"), to=join(runfiles_venv, "lib")) _symlink_exist_ok(from_=venv_site_packages, to=runfiles_venv_site_packages) if IS_WINDOWS: print_verbose("create_venv: pyvenv.cfg home: ", python_home) venv_pyvenv_cfg = join(venv, "pyvenv.cfg") with open(venv_pyvenv_cfg, "w") as fp: # Until Windows supports a build-time generated venv using symlinks # to directories, we have to write the full, absolute, path to PYTHONHOME # so that support directories (e.g. DLLs, libs) can be found. fp.write("home = {}\n".format(python_home)) else: _symlink_exist_ok(from_=join(venv, "pyvenv.cfg"), to=join(runfiles_venv, "pyvenv.cfg")) return venv_python_exe ``` -------------------------------- ### Precompile Python bytecode Source: https://context7.com/bazel-contrib/rules_python/llms.txt Enable .pyc compilation at build time to improve startup performance. ```bash # Enable precompiling globally bazel build //... --@rules_python//python/config_settings:precompile=enabled # Pyc-only builds (no .py source files in output) bazel build //... \ --@rules_python//python/config_settings:precompile=enabled \ --@rules_python//python/config_settings:precompile_source_retention=omit_source ``` ```starlark # BUILD.bazel load("@rules_python//python:py_binary.bzl", "py_binary") py_binary( name = "production_app", srcs = ["app.py"], deps = [":my_lib"], pyc_collection = "include_pyc", # Enable precompiling for this target ) py_binary( name = "dev_app", srcs = ["app.py"], deps = [":my_lib"], pyc_collection = "disabled", # Disable precompiling ) ``` -------------------------------- ### Python Relative Imports Example Source: https://github.com/bazel-contrib/rules_python/blob/main/gazelle/docs/directives.md Demonstrates how `python_experimental_allow_relative_imports` affects BUILD file generation for Python targets with relative imports. ```python from .library import add as _add from .library import subtract as _subtract ``` -------------------------------- ### bootstrap_impl Flag Source: https://github.com/bazel-contrib/rules_python/blob/main/docs/api/rules_python/python/config_settings/index.md Defines how programs implement their startup process, choosing between system Python or an arbitrary script. ```APIDOC ## bootstrap_impl Flag ### Description Determine how programs implement their startup process. ### Values * `system_python`: (default) Use a bootstrap that requires a system Python available in order to start programs. This requires {obj}`PyRuntimeInfo.bootstrap_template` to be a Python program. * `script`: Use a bootstrap that uses an arbitrary executable script (usually a shell script) instead of requiring it be a Python program. :::{note} The `script` bootstrap requires the toolchain to provide the `PyRuntimeInfo` provider from `rules_python`. This loosely translates to using Bazel 7+ with a toolchain created by rules_python. Most notably, WORKSPACE builds default to using a legacy toolchain built into Bazel itself which doesn't support the script bootstrap. If not available, the `system_python` bootstrap will be used instead. ::: :::{seealso} {obj}`PyRuntimeInfo.bootstrap_template` and {obj}`PyRuntimeInfo.stage2_bootstrap_template` ::: :::{versionadded} 0.33.0 ::: ``` -------------------------------- ### Define Starlark analysis tests Source: https://github.com/bazel-contrib/rules_python/blob/main/AGENTS.md Use rules_testing to define analysis tests consisting of a setup function and an implementation function with assertions. ```Starlark # File: foo_tests.bzl load("@rules_testing//lib:analysis_test.bzl", "analysis_test") load("@rules_testing//lib:test_suite.bzl", "test_suite") _tests = [] def _test_foo(name): foo_library( name = name + "_subject", ) analysis_test( name = name, impl = _test_foo_impl, target = name + "_subject", ) _tests.append(_test_foo) def _test_foo_impl(env, target): env.expect.that_whatever(target[SomeInfo].whatever).equals(expected) def foo_test_suite(name): test_suite(name=name, tests=_tests) ``` -------------------------------- ### Python Version Override Example Source: https://github.com/bazel-contrib/rules_python/blob/main/docs/api/rules_python/python/config_settings/index.md Use `python.single_version_override` to re-introduce a desired Python version, ensuring the corresponding `//python/config_setting:is_python_XXX` target is generated. ```python flag_values = { "@rules_python//python/config_settings:python_version": "3.5.1", } ``` -------------------------------- ### Initial Dependency Structure Source: https://github.com/bazel-contrib/rules_python/blob/main/docs/howto/common-deps-with-multiple-pypi-versions.md Illustrates the problem of a common library needing to depend on a PyPI package from a repository that varies based on the consuming binary. ```bzl py_binary( name = "bin_alpha", deps = ["@pypi_alpha//requests", ":common"], ) py_binary( name = "bin_beta", deps = ["@pypi_beta//requests", ":common"], ) py_library( name = "common", deps = ["@pypi_???//more_itertools"] # <-- Which @pypi repo? ) ``` -------------------------------- ### Rendered Markdown for User-Defined Type Source: https://github.com/bazel-contrib/rules_python/blob/main/sphinxdocs/docs/starlark-docgen.md This is an example of the Markdown output generated by sphinx_stardoc for a user-defined type, using directives like bzl:typedef, bzl:field, and bzl:function. ```markdown ::::{bzl:typedef} Square A square with fixed size :::{bzl:field} width :type: int ::: :::{bzl:function} new() ...args etc from _Square_new... ::: :::{bzl:function} area() ...args etc from _Square_area... ::: :::: ``` -------------------------------- ### Configuring PyPI Hub Selection with Flags Source: https://github.com/bazel-contrib/rules_python/blob/main/docs/howto/common-deps-with-multiple-pypi-versions.md Sets up a custom string flag `//:pypi_hub` and configures binaries to use it, enabling `select()` to resolve dependencies based on the flag's value. ```bzl # File: MODULE.bazel rules_python_config.add_transition_setting( setting = "//:pypi_hub", ) # File: BUILD.bazel load("@bazel_skylib//rules:common_settings.bzl", "string_flag") string_flag( name = "pypi_hub", ) config_setting( name = "is_pypi_alpha", flag_values = {"//:pypi_hub": "alpha"}, ) config_setting( name = "is_pypi_beta", flag_values = {"//:pypi_hub": "beta"} ) py_binary( name = "bin_alpha", srcs = ["bin_alpha.py"], config_settings = { "//:pypi_hub": "alpha", }, deps = ["@pypi_alpha//requests", ":common"], ) py_binary( name = "bin_beta", srcs = ["bin_beta.py"], config_settings = { "//:pypi_hub": "beta", }, deps = ["@pypi_beta//requests", ":common"], ) py_library( name = "common", deps = select({ ":is_pypi_alpha": ["@pypi_alpha//more_itertools"], ":is_pypi_beta": ["@pypi_beta//more_itertools"], }), ) ``` -------------------------------- ### Inspect Target Definitions Source: https://github.com/bazel-contrib/rules_python/blob/main/AGENTS.md Use this command to view the build definitions of targets. ```bash bazel query --output=build ``` -------------------------------- ### Python Annotation Syntax Source: https://github.com/bazel-contrib/rules_python/blob/main/gazelle/docs/annotations.md Annotations are comments within Python files that start with '# gazelle:' and are used to configure Gazelle's behavior for that file. They can appear anywhere a comment is valid. ```python # gazelle:annotation_name value ``` ```python import foo # gazelle:annotation_name value def bar(): # gazelle:annotation_name value pass ``` -------------------------------- ### Include Pytest Conftest Annotation Example Source: https://github.com/bazel-contrib/rules_python/blob/main/gazelle/docs/annotations.md Control whether Gazelle includes a sibling ':conftest' target in the 'deps' of a py_test target. Set the annotation value to 'false' to disable this behavior. ```python # some_file_test.py # gazelle:include_pytest_conftest false ``` ```starlark py_library( name = "conftest", testonly = True, srcs = ["conftest.py"], visibility = ["//:__subpackages__"], ) py_test( name = "some_file_test", srcs = ["some_file_test.py"], ) ``` -------------------------------- ### Create runfiles root directory Source: https://github.com/bazel-contrib/rules_python/blob/main/python/private/python_bootstrap_template.txt Initializes a temporary directory for the runfiles tree by extracting a zip file. ```python def create_runfiles_root(): temp_dir = tempfile.mkdtemp('', 'Bazel.runfiles_') extract_zip(os.path.dirname(__file__), temp_dir) # IMPORTANT: Later code does `rm -fr` on dirname(runfiles_root) -- it's # important that deletion code be in sync with this directory structure return os.path.join(temp_dir, 'runfiles') ``` -------------------------------- ### Ignore Imports Annotation Example Source: https://github.com/bazel-contrib/rules_python/blob/main/gazelle/docs/annotations.md Use the 'ignore' annotation to specify Python imports that Gazelle should not include in target dependencies. This annotation can be added multiple times, and all values are combined and de-duplicated. ```python import numpy # a pypi package # gazelle:ignore bar.baz.hello,foo import bar.baz.hello import foo # Ignore this import because _reasons_ import baz # gazelle:ignore baz ``` ```starlark deps = ["@pypi//numpy"], ``` -------------------------------- ### Define readthedocs_install Rule in BUILD Source: https://github.com/bazel-contrib/rules_python/blob/main/sphinxdocs/docs/readthedocs.md Use the `readthedocs_install` rule in your `BUILD` file to manage the documentation build and output copying. It requires a `sphinx_docs` target as input. ```bzl # File: docs/BUILD load("//:readthedocs.bzl", "readthedocs_install") readthedocs_install( name = "readthedocs_install", docs = [":docs"], ) ``` -------------------------------- ### Generate Gazelle Python Manifest Source: https://github.com/bazel-contrib/rules_python/blob/main/gazelle/docs/installation_and_usage.md Configure your BUILD.bazel file to generate a Gazelle Python manifest, which maps imports to installed packages. This includes fetching metadata and optionally including stub packages. ```starlark # `@pip` is the hub_name from pip.parse in MODULE.bazel. load("@pip//:requirements.bzl", "all_whl_requirements") load("@rules_python_gazelle_plugin//manifest:defs.bzl", "gazelle_python_manifest") load("@rules_python_gazelle_plugin//modules_mapping:def.bzl", "modules_mapping") # This rule fetches the metadata for python packages we depend on. That data is # required for the gazelle_python_manifest rule to update our manifest file. modules_mapping( name = "modules_map", wheels = all_whl_requirements, # include_stub_packages: bool (default: False) # If set to True, this flag automatically includes any corresponding type stub packages # for the third-party libraries that are present and used. For example, if you have # `boto3` as a dependency, and this flag is enabled, the corresponding `boto3-stubs` # package will be automatically included in the BUILD file. # Enabling this feature helps ensure that type hints and stubs are readily available # for tools like type checkers and IDEs, improving the development experience and # reducing manual overhead in managing separate stub packages. include_stub_packages = True, ) # Gazelle python extension needs a manifest file mapping from # an import to the installed package that provides it. # This macro produces two targets: # - //:gazelle_python_manifest.update can be used with `bazel run` # to recalculate the manifest # - //:gazelle_python_manifest.test is a test target ensuring that ``` -------------------------------- ### Rebuild Docs with watch Source: https://github.com/bazel-contrib/rules_python/blob/main/docs/README.md A simple method to periodically rebuild documentation using the `watch` command. This is a less efficient alternative to `ibazel` or `inotify`. ```bash watch --interval 10 bazel build //docs:docs ``` -------------------------------- ### Starlark implementation of a user-defined type (Square) Source: https://github.com/bazel-contrib/rules_python/blob/main/sphinxdocs/docs/starlark-docgen.md This example demonstrates how to document user-defined types in Starlark using structs and lambdas, mimicking class documentation. It includes typedef, constructor, and method definitions. ```starlark def _Square_typedef(): """A square with fixed size. :::{field} width :type: int ::: """ def _Square_new(width): """Creates a Square. Args: width: {type}`int` width of square Returns: {type}`Square` """ self = struct( area = lambda *a, **k: _Square_area(self, *a, **k), width = width ) return self def _Square_area(self, ): """Tells the area of the square.""" return self.width * self.width Square = struct( TYPEDEF = _Square_typedef, new = _Square_new, area = _Square_area, ) ``` -------------------------------- ### Main Function for Initialization Source: https://github.com/bazel-contrib/rules_python/blob/main/python/private/python_bootstrap_template.txt The main entry point that prints verbose information about the Python environment, including version, arguments, current working directory, and environment variables. Useful for debugging initialization issues. ```python def main(): print_verbose("sys.version:", sys.version) print_verbose("initial argv:", values=sys.argv) print_verbose("initial cwd:", os.getcwd()) print_verbose("initial environ:", mapping=os.environ) ``` -------------------------------- ### Create a Bash Credential Helper Script Source: https://github.com/bazel-contrib/rules_python/blob/main/docs/pypi/download.md A simple bash script that outputs JSON to stdout, which Bazel uses to inject authentication headers. ```bash #!/bin/bash # cred_helper.sh ARG=$1 # but we don't do anything with it as it's always "get" # formatting is optional echo '{' echo ' "headers": {' echo ' "Authorization": ["Basic dGVzdDoxMjPCow=="]' echo ' }' echo '}' ``` -------------------------------- ### Register Hermetic Python Toolchain Source: https://github.com/bazel-contrib/rules_python/blob/main/docs/toolchains.md Register a hermetic Python toolchain for runtime execution. Ensure the `python_version` matches your team's standard. This setup is used in conjunction with `pip_parse` to specify the interpreter. ```starlark load("@rules_python//python:repositories.bzl", "python_register_toolchains") python_register_toolchains( name = "python_3_11", # Available versions are listed in @rules_python//python:versions.bzl. # We recommend using the same version your team is already standardized on. python_version = "3.11", ) load("@rules_python//python:pip.bzl", "pip_parse") pip_parse( ... python_interpreter_target = "@python_3_11_host//:python", ... ) ``` -------------------------------- ### Python Debugger Launcher Script for Bazel Source: https://github.com/bazel-contrib/rules_python/blob/main/docs/howto/debuggers.md This script is invoked by VS Code's launch.json to wrap Bazel commands, injecting the debugpy debugger into the runtime environment. Ensure debugpy is installed in your environment. ```python import argparse import os import shlex import subprocess import sys from typing import cast def main() -> None: parser = argparse.ArgumentParser(description="Launch bazel debugpy with test or run.") parser.add_argument("mode", choices=["test", "run"], help="Choose whether to run a bazel test or run.") parser.add_argument("args", help="The bazel target to test or run (e.g., //foo:bar) and any additional args") args = parser.parse_args() # Import debugpy, provided by VS Code try: # debugpy._vendored is needed for force_pydevd to perform path manipulation. import debugpy._vendored # type: ignore[import-not-found] # pydev_monkey patches os and subprocess functions to handle new launched processes. from _pydev_bundle import pydev_monkey # type: ignore[import-not-found] except ImportError as exc: print(f"Error: This script must be run via VS Code's debug adapter. Details: {exc}") sys.exit(-1) # Prepare arguments for the monkey-patched process. # is_exec=False ensures we don't replace the current process immediately. patched_args = cast(list[str], pydev_monkey.patch_args(["python", "dummy.py"], is_exec=False)) pydev_monkey.send_process_created_message() # Extract the injected arguments (skipping the dummy python executable and script). # These args invoke the pydevd entrypoint which connects back to the debugger. rules_python_interpreter_args = " ".join(patched_args[1:-1]) bzl_args = shlex.split(args.args) if not bzl_args: print("Error: At least one argument (the target) is required.") sys.exit(-1) cmd = [ "bazel", args.mode, # Propagate environment variables to the test/run environment. "--test_env=PYDEVD_RESOLVE_SYMLINKS", "--test_env=RULES_PYTHON_ADDITIONAL_INTERPRETER_ARGS", "--test_env=IDE_PROJECT_ROOTS", bzl_args[0], ] if bzl_args[1:]: if args.mode == "run": # Append extra arguments for 'run' mode. cmd.append("--") cmd.extend(bzl_args[1:]) elif args.mode == "test": # Append extra arguments for 'test' mode. cmd.extend([f"--test_arg={arg}" for arg in bzl_args[1:]]) env = { **os.environ.copy(), # Inject the debugger arguments into the rules_python toolchain. "RULES_PYTHON_ADDITIONAL_INTERPRETER_ARGS": rules_python_interpreter_args, # Ensure breakpoints hit the original source files, not Bazel's symlinks. "PYDEVD_RESOLVE_SYMLINKS": "1", } # Execute Bazel. result = subprocess.run(cmd, env=env, check=False) sys.exit(result.returncode) if __name__ == "__main__": main() ``` -------------------------------- ### Inspect External Dependencies in WORKSPACE Source: https://github.com/bazel-contrib/rules_python/blob/main/AGENTS.md Commands for listing and inspecting external dependencies in legacy WORKSPACE mode. ```bash bazel query //external:* ``` -------------------------------- ### Derive py_binary Rule with Platform Transition Source: https://github.com/bazel-contrib/rules_python/blob/main/docs/extending.md Use this pattern to create a new rule that forces a specific platform during the build. It requires importing `executables` and defining a custom implementation function. ```starlark load("@rules_python//python/api:executables.bzl", "executables") def _force_linux_impl(settings, attr, base_impl): settings = base_impl(settings, attr) settings["//command_line_option:platforms"] = ["//my/platforms:linux"] return settings def create_rule(): r = executables.py_binary_rule_builder() base_impl = r.cfg.implementation() r.cfg.set_implementation( lambda settings, attr: _force_linux_impl(settings, attr, base_impl) ) r.cfg.add_output("//command_line_option:platforms") return r.build() py_linux_binary = create_rule() ``` -------------------------------- ### Include Dependencies Annotation Example Source: https://github.com/bazel-contrib/rules_python/blob/main/gazelle/docs/annotations.md The 'include_dep' annotation allows you to specify Python targets that Gazelle should include as dependencies, even if they are not directly imported. Values must be Python targets; otherwise, building will result in an error. ```python # gazelle:include_dep //foo:bar,:hello_world,//:abc # gazelle:include_dep //:def,//foo:bar import numpy # a pypi package ``` ```starlark deps = [ ":hello_world", "//:abc", "//:def", "//foo:bar", "@pypi//numpy", ] ``` -------------------------------- ### Run All Bazel Tests Source: https://github.com/bazel-contrib/rules_python/blob/main/docs/devguide.md Execute all tests discoverable by Bazel. The initial run may be slow due to dependency downloads. Subsequent runs are faster. ```bash bazel test //... ``` -------------------------------- ### Manage multiple Python versions Source: https://github.com/bazel-contrib/rules_python/blob/main/docs/toolchains.md Configure multiple toolchains and set default versions in MODULE.bazel, then use them in BUILD files. ```starlark # MODULE.bazel python = use_extension("@rules_python//python/extensions:python.bzl", "python") python.defaults( # The environment variable takes precedence if set. python_version = "3.11", python_version_env = "BAZEL_PYTHON_VERSION", ) python.toolchain( python_version = "3.11", ) python.toolchain( python_version = "3.12", ) # BUILD.bazel load("@rules_python//python:py_binary.bzl", "py_binary") load("@rules_python//python:py_test.bzl", "py_test") # Defaults to 3.11 py_binary(...) py_test(...) # Explicitly use Python 3.11 py_binary(..., python_version = "3.11") py_test(..., python_version = "3.11") # Explicitly use Python 3.12 py_binary(..., python_version = "3.12") py_test(..., python_version = "3.12") ``` -------------------------------- ### Create Custom Rule with Validation Source: https://github.com/bazel-contrib/rules_python/blob/main/docs/extending.md This example demonstrates creating a custom `py_library` rule that validates source code for the word 'snakes'. It adds a checker program as a dependency and runs it on source files, adding the output to the `_validation` output group. Use this when you need to add specific validation logic to a base rule. ```python load("@rules_python//python/api:libraries.bzl", "libraries") load("@rules_python//python/api:attr_builders.bzl", "attrb") def _has_snakes_impl(ctx, base): providers = base(ctx) out = ctx.actions.declare_file(ctx.label.name + "_snakes.check") ctx.actions.run( inputs = ctx.files.srcs, outputs = [out], executable = ctx.attr._checker[DefaultInfo].files_to_run, args = [out.path] + [f.path for f in ctx.files.srcs], ) prior_ogi = None for i, p in enumerate(providers): if type(p) == "OutputGroupInfo": prior_ogi = (i, p) break if prior_ogi: groups = {k: getattr(prior_ogi[1], k) for k in dir(prior_ogi)} if "_validation" in groups: groups["_validation"] = depset([out], transitive=groups["_validation"]) else: groups["_validation"] = depset([out]) providers[prior_ogi[0]] = OutputGroupInfo(**groups) else: providers.append(OutputGroupInfo(_validation=depset([out]))) return providers def create_has_snakes_rule(): r = libraries.py_library_builder() base_impl = r.implementation() r.set_implementation(lambda ctx: _has_snakes_impl(ctx, base_impl)) r.attrs["_checker"] = attrb.Label( default="//:checker", executable = True, ) return r.build() has_snakes_library = create_has_snakes_rule() ``` -------------------------------- ### Explicitly create Runfiles implementations Source: https://github.com/bazel-contrib/rules_python/blob/main/python/runfiles/README.md Manually instantiate manifest-based or directory-based Runfiles objects. ```python r1 = Runfiles.CreateManifestBased("path/to/foo.runfiles_manifest") r2 = Runfiles.CreateDirectoryBased("path/to/foo.runfiles/") ``` -------------------------------- ### myfunc Source: https://github.com/bazel-contrib/rules_python/blob/main/sphinxdocs/tests/sphinx_stardoc/function.md Documentation for the myfunc Bazel function. ```APIDOC ## bzl:function myfunc(foo, bar=False, baz=[]) -> FooObj ### Description This is a bazel function. ### Method N/A (Bazel Starlark function) ### Endpoint N/A ### Parameters #### Path Parameters N/A #### Query Parameters N/A #### Request Body N/A ### Request Example N/A ### Response #### Success Response (200) - **return value** (list | int) - description #### Response Example N/A ### Deprecated Some doc about the deprecation ``` -------------------------------- ### Create an executable Python binary with py_binary Source: https://context7.com/bazel-contrib/rules_python/llms.txt Creates an executable Python program. Supports specifying source files, main entry point, dependencies, data files, environment variables, and Python versions. ```starlark # BUILD.bazel load("@rules_python//python:py_binary.bzl", "py_binary") # Basic binary py_binary( name = "main", srcs = ["main.py"], main = "main.py", deps = [ ":my_lib", "@pypi//click", ], ) # Binary with specific Python version py_binary( name = "app_3_12", srcs = ["app.py"], main = "app.py", python_version = "3.12", deps = ["@pypi//fastapi"], ) # Binary with data files and environment variables py_binary( name = "data_tool", srcs = ["tool.py"], data = [ "templates/report.html", "//resources:config_files", ], env = { "CONFIG_PATH": "$(rootpath templates/report.html)", "DEBUG": "true", }, deps = [":data_processing"], ) ``` ```bash bazel run //:main bazel run //:app_3_12 -- --port 8080 ``` -------------------------------- ### Rebuild documentation with ibazel Source: https://github.com/bazel-contrib/rules_python/blob/main/sphinxdocs/tests/sphinx_stardoc/index.md Uses ibazel to trigger an automatic rebuild of the documentation upon file changes. ```bash ibazel build //tests/sphinx_stardoc:docs ``` -------------------------------- ### Define bzl_library targets Source: https://github.com/bazel-contrib/rules_python/blob/main/AGENTS.md Create bzl_library targets for .bzl files, ensuring dependencies match load statements and targets are sorted alphabetically. ```Starlark bzl_library( name = "alpha_bzl", srcs = ["alpha.bzl"], deps = [":beta_bzl"], ) bzl_library( name = "beta_bzl", srcs = ["beta.bzl"] ) ``` -------------------------------- ### Build a basic wheel from a py_library Source: https://github.com/bazel-contrib/rules_python/blob/main/docs/howto/build-a-wheel.md Use py_wheel to package a py_library. Note that this only includes direct source files and not transitive dependencies. ```starlark # BUILD.bazel py_library( name = "my_project_lib", srcs = glob(["my_project/**/*.py"]), # ... ) py_wheel( name = "my_project_wheel", distribution = "my-project", version = "0.1.0", deps = [":my_project_lib"], ) ``` -------------------------------- ### Look up runfile paths Source: https://github.com/bazel-contrib/rules_python/blob/main/python/runfiles/README.md Create a Runfiles instance and use Rlocation to resolve file paths. ```python r = Runfiles.Create() # ... with open(r.Rlocation("my_workspace/path/to/my/data.txt"), "r") as f: contents = f.readlines() # ... ``` -------------------------------- ### enable_runfiles Source: https://github.com/bazel-contrib/rules_python/blob/main/docs/api/rules_python/command_line_option/index.md Special target representing the --enable_runfiles Bazel flag. ```APIDOC ## Target: enable_runfiles ### Description Special target for the Bazel-builtin //command_line_option:enable_runfiles flag. This can be used with config_settings to transition the flag value. ### Usage - The special value 'INHERIT' can be specified to use the existing flag value. ``` -------------------------------- ### Using Pip Dependencies in BUILD Files Source: https://context7.com/bazel-contrib/rules_python/llms.txt Reference pip dependencies directly using labels or the requirement helper function in BUILD files. Ensure the repository rule (e.g., use_repo(pip, 'pypi')) is defined. ```starlark # BUILD.bazel load("@pypi//:requirements.bzl", "requirement") py_binary( name = "app", srcs = ["app.py"], deps = [ # Direct label reference (preferred) "@pypi//requests", "@pypi//numpy", # Or using requirement helper requirement("pandas"), ], ) ``` -------------------------------- ### Configure gazelle_binary for multi-language support Source: https://github.com/bazel-contrib/rules_python/blob/main/gazelle/docs/installation_and_usage.md Set up the gazelle_binary rule to run Gazelle with multiple language plugins, including rules_python. Ensure the proto language plugin comes before rules_python if generating py_proto_library targets. ```starlark load("@bazel_gazelle//:def.bzl", "gazelle", "gazelle_binary") gazelle_binary( name = "gazelle_multilang", languages = [ # List of language plugins. # If you want to generate py_proto_library targets (PR #3057), then # the proto language plugin _must_ come before the rules_python plugin. #"@bazel_gazelle//language/proto", "@rules_python_gazelle_plugin//python", ], ) gazelle( name = "gazelle", gazelle = ":gazelle_multilang", ) ``` -------------------------------- ### Import Runfiles from Bazel Source: https://github.com/bazel-contrib/rules_python/blob/main/python/runfiles/README.md Import the Runfiles class when using the direct Bazel target. ```python from python.runfiles import Runfiles ``` -------------------------------- ### BUILD File Output without Relative Imports Source: https://github.com/bazel-contrib/rules_python/blob/main/gazelle/docs/directives.md Illustrates the BUILD file output when relative imports are not resolved, leading to missing dependencies. ```starlark py_library( name = "py_default_library", srcs = ["__init__.py"], visibility = ["//visibility:public"], ) ```