1*60517a1eSAndroid Build Coastguard Worker# Python Gazelle plugin 2*60517a1eSAndroid Build Coastguard Worker 3*60517a1eSAndroid Build Coastguard Worker[Gazelle](https://github.com/bazelbuild/bazel-gazelle) 4*60517a1eSAndroid Build Coastguard Workeris a build file generator for Bazel projects. It can create new BUILD.bazel files for a project that follows language conventions, and it can update existing build files to include new sources, dependencies, and options. 5*60517a1eSAndroid Build Coastguard Worker 6*60517a1eSAndroid Build Coastguard WorkerGazelle may be run by Bazel using the gazelle rule, or it may be installed and run as a command line tool. 7*60517a1eSAndroid Build Coastguard Worker 8*60517a1eSAndroid Build Coastguard WorkerThis directory contains a plugin for 9*60517a1eSAndroid Build Coastguard Worker[Gazelle](https://github.com/bazelbuild/bazel-gazelle) 10*60517a1eSAndroid Build Coastguard Workerthat generates BUILD files content for Python code. When Gazelle is run as a command line tool with this plugin, it embeds a Python interpreter resolved during the plugin build. 11*60517a1eSAndroid Build Coastguard WorkerThe behavior of the plugin is slightly different with different version of the interpreter as the Python `stdlib` changes with every minor version release. 12*60517a1eSAndroid Build Coastguard WorkerDistributors of Gazelle binaries should, therefore, build a Gazelle binary for each OS+CPU architecture+Minor Python version combination they are targeting. 13*60517a1eSAndroid Build Coastguard Worker 14*60517a1eSAndroid Build Coastguard WorkerThe following instructions are for when you use [bzlmod](https://docs.bazel.build/versions/5.0.0/bzlmod.html). 15*60517a1eSAndroid Build Coastguard WorkerPlease refer to older documentation that includes instructions on how to use Gazelle 16*60517a1eSAndroid Build Coastguard Workerwithout using bzlmod as your dependency manager. 17*60517a1eSAndroid Build Coastguard Worker 18*60517a1eSAndroid Build Coastguard Worker## Example 19*60517a1eSAndroid Build Coastguard Worker 20*60517a1eSAndroid Build Coastguard WorkerWe have an example of using Gazelle with Python located [here](https://github.com/bazelbuild/rules_python/tree/main/examples/bzlmod). 21*60517a1eSAndroid Build Coastguard WorkerA fully-working example without using bzlmod is in [`examples/build_file_generation`](../examples/build_file_generation). 22*60517a1eSAndroid Build Coastguard Worker 23*60517a1eSAndroid Build Coastguard WorkerThe following documentation covers using bzlmod. 24*60517a1eSAndroid Build Coastguard Worker 25*60517a1eSAndroid Build Coastguard Worker## Adding Gazelle to your project 26*60517a1eSAndroid Build Coastguard Worker 27*60517a1eSAndroid Build Coastguard WorkerFirst, you'll need to add Gazelle to your `MODULES.bazel` file. 28*60517a1eSAndroid Build Coastguard WorkerGet the current version of Gazelle from there releases here: https://github.com/bazelbuild/bazel-gazelle/releases/. 29*60517a1eSAndroid Build Coastguard Worker 30*60517a1eSAndroid Build Coastguard Worker 31*60517a1eSAndroid Build Coastguard WorkerSee the installation `MODULE.bazel` snippet on the Releases page: 32*60517a1eSAndroid Build Coastguard Workerhttps://github.com/bazelbuild/rules_python/releases in order to configure rules_python. 33*60517a1eSAndroid Build Coastguard Worker 34*60517a1eSAndroid Build Coastguard WorkerYou will also need to add the `bazel_dep` for configuration for `rules_python_gazelle_plugin`. 35*60517a1eSAndroid Build Coastguard Worker 36*60517a1eSAndroid Build Coastguard WorkerHere is a snippet of a `MODULE.bazel` file. 37*60517a1eSAndroid Build Coastguard Worker 38*60517a1eSAndroid Build Coastguard Worker```starlark 39*60517a1eSAndroid Build Coastguard Worker# The following stanza defines the dependency rules_python. 40*60517a1eSAndroid Build Coastguard Workerbazel_dep(name = "rules_python", version = "0.22.0") 41*60517a1eSAndroid Build Coastguard Worker 42*60517a1eSAndroid Build Coastguard Worker# The following stanza defines the dependency rules_python_gazelle_plugin. 43*60517a1eSAndroid Build Coastguard Worker# For typical setups you set the version. 44*60517a1eSAndroid Build Coastguard Workerbazel_dep(name = "rules_python_gazelle_plugin", version = "0.22.0") 45*60517a1eSAndroid Build Coastguard Worker 46*60517a1eSAndroid Build Coastguard Worker# The following stanza defines the dependency gazelle. 47*60517a1eSAndroid Build Coastguard Workerbazel_dep(name = "gazelle", version = "0.31.0", repo_name = "bazel_gazelle") 48*60517a1eSAndroid Build Coastguard Worker 49*60517a1eSAndroid Build Coastguard Worker# Import the python repositories generated by the given module extension into the scope of the current module. 50*60517a1eSAndroid Build Coastguard Workeruse_repo(python, "python3_9") 51*60517a1eSAndroid Build Coastguard Workeruse_repo(python, "python3_9_toolchains") 52*60517a1eSAndroid Build Coastguard Worker 53*60517a1eSAndroid Build Coastguard Worker# Register an already-defined toolchain so that Bazel can use it during toolchain resolution. 54*60517a1eSAndroid Build Coastguard Workerregister_toolchains( 55*60517a1eSAndroid Build Coastguard Worker "@python3_9_toolchains//:all", 56*60517a1eSAndroid Build Coastguard Worker) 57*60517a1eSAndroid Build Coastguard Worker 58*60517a1eSAndroid Build Coastguard Worker# Use the pip extension 59*60517a1eSAndroid Build Coastguard Workerpip = use_extension("@rules_python//python:extensions.bzl", "pip") 60*60517a1eSAndroid Build Coastguard Worker 61*60517a1eSAndroid Build Coastguard Worker# Use the extension to call the `pip_repository` rule that invokes `pip`, with `incremental` set. 62*60517a1eSAndroid Build Coastguard Worker# Accepts a locked/compiled requirements file and installs the dependencies listed within. 63*60517a1eSAndroid Build Coastguard Worker# Those dependencies become available in a generated `requirements.bzl` file. 64*60517a1eSAndroid Build Coastguard Worker# You can instead check this `requirements.bzl` file into your repo. 65*60517a1eSAndroid Build Coastguard Worker# Because this project has different requirements for windows vs other 66*60517a1eSAndroid Build Coastguard Worker# operating systems, we have requirements for each. 67*60517a1eSAndroid Build Coastguard Workerpip.parse( 68*60517a1eSAndroid Build Coastguard Worker name = "pip", 69*60517a1eSAndroid Build Coastguard Worker requirements_lock = "//:requirements_lock.txt", 70*60517a1eSAndroid Build Coastguard Worker requirements_windows = "//:requirements_windows.txt", 71*60517a1eSAndroid Build Coastguard Worker) 72*60517a1eSAndroid Build Coastguard Worker 73*60517a1eSAndroid Build Coastguard Worker# Imports the pip toolchain generated by the given module extension into the scope of the current module. 74*60517a1eSAndroid Build Coastguard Workeruse_repo(pip, "pip") 75*60517a1eSAndroid Build Coastguard Worker``` 76*60517a1eSAndroid Build Coastguard WorkerNext, we'll fetch metadata about your Python dependencies, so that gazelle can 77*60517a1eSAndroid Build Coastguard Workerdetermine which package a given import statement comes from. This is provided 78*60517a1eSAndroid Build Coastguard Workerby the `modules_mapping` rule. We'll make a target for consuming this 79*60517a1eSAndroid Build Coastguard Worker`modules_mapping`, and writing it as a manifest file for Gazelle to read. 80*60517a1eSAndroid Build Coastguard WorkerThis is checked into the repo for speed, as it takes some time to calculate 81*60517a1eSAndroid Build Coastguard Workerin a large monorepo. 82*60517a1eSAndroid Build Coastguard Worker 83*60517a1eSAndroid Build Coastguard WorkerGazelle will walk up the filesystem from a Python file to find this metadata, 84*60517a1eSAndroid Build Coastguard Workerlooking for a file called `gazelle_python.yaml` in an ancestor folder of the Python code. 85*60517a1eSAndroid Build Coastguard WorkerCreate an empty file with this name. It might be next to your `requirements.txt` file. 86*60517a1eSAndroid Build Coastguard Worker(You can just use `touch` at this point, it just needs to exist.) 87*60517a1eSAndroid Build Coastguard Worker 88*60517a1eSAndroid Build Coastguard WorkerTo keep the metadata updated, put this in your `BUILD.bazel` file next to `gazelle_python.yaml`: 89*60517a1eSAndroid Build Coastguard Worker 90*60517a1eSAndroid Build Coastguard Worker```starlark 91*60517a1eSAndroid Build Coastguard Workerload("@pip//:requirements.bzl", "all_whl_requirements") 92*60517a1eSAndroid Build Coastguard Workerload("@rules_python_gazelle_plugin//manifest:defs.bzl", "gazelle_python_manifest") 93*60517a1eSAndroid Build Coastguard Workerload("@rules_python_gazelle_plugin//modules_mapping:def.bzl", "modules_mapping") 94*60517a1eSAndroid Build Coastguard Worker 95*60517a1eSAndroid Build Coastguard Worker# This rule fetches the metadata for python packages we depend on. That data is 96*60517a1eSAndroid Build Coastguard Worker# required for the gazelle_python_manifest rule to update our manifest file. 97*60517a1eSAndroid Build Coastguard Workermodules_mapping( 98*60517a1eSAndroid Build Coastguard Worker name = "modules_map", 99*60517a1eSAndroid Build Coastguard Worker wheels = all_whl_requirements, 100*60517a1eSAndroid Build Coastguard Worker) 101*60517a1eSAndroid Build Coastguard Worker 102*60517a1eSAndroid Build Coastguard Worker# Gazelle python extension needs a manifest file mapping from 103*60517a1eSAndroid Build Coastguard Worker# an import to the installed package that provides it. 104*60517a1eSAndroid Build Coastguard Worker# This macro produces two targets: 105*60517a1eSAndroid Build Coastguard Worker# - //:gazelle_python_manifest.update can be used with `bazel run` 106*60517a1eSAndroid Build Coastguard Worker# to recalculate the manifest 107*60517a1eSAndroid Build Coastguard Worker# - //:gazelle_python_manifest.test is a test target ensuring that 108*60517a1eSAndroid Build Coastguard Worker# the manifest doesn't need to be updated 109*60517a1eSAndroid Build Coastguard Workergazelle_python_manifest( 110*60517a1eSAndroid Build Coastguard Worker name = "gazelle_python_manifest", 111*60517a1eSAndroid Build Coastguard Worker modules_mapping = ":modules_map", 112*60517a1eSAndroid Build Coastguard Worker # This is what we called our `pip_parse` rule, where third-party 113*60517a1eSAndroid Build Coastguard Worker # python libraries are loaded in BUILD files. 114*60517a1eSAndroid Build Coastguard Worker pip_repository_name = "pip", 115*60517a1eSAndroid Build Coastguard Worker # This should point to wherever we declare our python dependencies 116*60517a1eSAndroid Build Coastguard Worker # (the same as what we passed to the modules_mapping rule in WORKSPACE) 117*60517a1eSAndroid Build Coastguard Worker # This argument is optional. If provided, the `.test` target is very 118*60517a1eSAndroid Build Coastguard Worker # fast because it just has to check an integrity field. If not provided, 119*60517a1eSAndroid Build Coastguard Worker # the integrity field is not added to the manifest which can help avoid 120*60517a1eSAndroid Build Coastguard Worker # merge conflicts in large repos. 121*60517a1eSAndroid Build Coastguard Worker requirements = "//:requirements_lock.txt", 122*60517a1eSAndroid Build Coastguard Worker) 123*60517a1eSAndroid Build Coastguard Worker``` 124*60517a1eSAndroid Build Coastguard Worker 125*60517a1eSAndroid Build Coastguard WorkerFinally, you create a target that you'll invoke to run the Gazelle tool 126*60517a1eSAndroid Build Coastguard Workerwith the rules_python extension included. This typically goes in your root 127*60517a1eSAndroid Build Coastguard Worker`/BUILD.bazel` file: 128*60517a1eSAndroid Build Coastguard Worker 129*60517a1eSAndroid Build Coastguard Worker```starlark 130*60517a1eSAndroid Build Coastguard Workerload("@bazel_gazelle//:def.bzl", "gazelle") 131*60517a1eSAndroid Build Coastguard Worker 132*60517a1eSAndroid Build Coastguard Worker# Our gazelle target points to the python gazelle binary. 133*60517a1eSAndroid Build Coastguard Worker# This is the simple case where we only need one language supported. 134*60517a1eSAndroid Build Coastguard Worker# If you also had proto, go, or other gazelle-supported languages, 135*60517a1eSAndroid Build Coastguard Worker# you would also need a gazelle_binary rule. 136*60517a1eSAndroid Build Coastguard Worker# See https://github.com/bazelbuild/bazel-gazelle/blob/master/extend.rst#example 137*60517a1eSAndroid Build Coastguard Workergazelle( 138*60517a1eSAndroid Build Coastguard Worker name = "gazelle", 139*60517a1eSAndroid Build Coastguard Worker gazelle = "@rules_python_gazelle_plugin//python:gazelle_binary", 140*60517a1eSAndroid Build Coastguard Worker) 141*60517a1eSAndroid Build Coastguard Worker``` 142*60517a1eSAndroid Build Coastguard Worker 143*60517a1eSAndroid Build Coastguard WorkerThat's it, now you can finally run `bazel run //:gazelle` anytime 144*60517a1eSAndroid Build Coastguard Workeryou edit Python code, and it should update your `BUILD` files correctly. 145*60517a1eSAndroid Build Coastguard Worker 146*60517a1eSAndroid Build Coastguard Worker## Usage 147*60517a1eSAndroid Build Coastguard Worker 148*60517a1eSAndroid Build Coastguard WorkerGazelle is non-destructive. 149*60517a1eSAndroid Build Coastguard WorkerIt will try to leave your edits to BUILD files alone, only making updates to `py_*` targets. 150*60517a1eSAndroid Build Coastguard WorkerHowever it will remove dependencies that appear to be unused, so it's a 151*60517a1eSAndroid Build Coastguard Workergood idea to check in your work before running Gazelle so you can easily 152*60517a1eSAndroid Build Coastguard Workerrevert any changes it made. 153*60517a1eSAndroid Build Coastguard Worker 154*60517a1eSAndroid Build Coastguard WorkerThe rules_python extension assumes some conventions about your Python code. 155*60517a1eSAndroid Build Coastguard WorkerThese are noted below, and might require changes to your existing code. 156*60517a1eSAndroid Build Coastguard Worker 157*60517a1eSAndroid Build Coastguard WorkerNote that the `gazelle` program has multiple commands. At present, only the `update` command (the default) does anything for Python code. 158*60517a1eSAndroid Build Coastguard Worker 159*60517a1eSAndroid Build Coastguard Worker### Directives 160*60517a1eSAndroid Build Coastguard Worker 161*60517a1eSAndroid Build Coastguard WorkerYou can configure the extension using directives, just like for other 162*60517a1eSAndroid Build Coastguard Workerlanguages. These are just comments in the `BUILD.bazel` file which 163*60517a1eSAndroid Build Coastguard Workergovern behavior of the extension when processing files under that 164*60517a1eSAndroid Build Coastguard Workerfolder. 165*60517a1eSAndroid Build Coastguard Worker 166*60517a1eSAndroid Build Coastguard WorkerSee https://github.com/bazelbuild/bazel-gazelle#directives 167*60517a1eSAndroid Build Coastguard Workerfor some general directives that may be useful. 168*60517a1eSAndroid Build Coastguard WorkerIn particular, the `resolve` directive is language-specific 169*60517a1eSAndroid Build Coastguard Workerand can be used with Python. 170*60517a1eSAndroid Build Coastguard WorkerExamples of these directives in use can be found in the 171*60517a1eSAndroid Build Coastguard Worker/gazelle/testdata folder in the rules_python repo. 172*60517a1eSAndroid Build Coastguard Worker 173*60517a1eSAndroid Build Coastguard WorkerPython-specific directives are as follows: 174*60517a1eSAndroid Build Coastguard Worker 175*60517a1eSAndroid Build Coastguard Worker| **Directive** | **Default value** | 176*60517a1eSAndroid Build Coastguard Worker|-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|-------------------| 177*60517a1eSAndroid Build Coastguard Worker| `# gazelle:python_extension` | `enabled` | 178*60517a1eSAndroid Build Coastguard Worker| Controls whether the Python extension is enabled or not. Sub-packages inherit this value. Can be either "enabled" or "disabled". | | 179*60517a1eSAndroid Build Coastguard Worker| [`# gazelle:python_root`](#directive-python_root) | n/a | 180*60517a1eSAndroid Build Coastguard Worker| Sets a Bazel package as a Python root. This is used on monorepos with multiple Python projects that don't share the top-level of the workspace as the root. See [Directive: `python_root`](#directive-python_root) below. | | 181*60517a1eSAndroid Build Coastguard Worker| `# gazelle:python_manifest_file_name` | `gazelle_python.yaml` | 182*60517a1eSAndroid Build Coastguard Worker| Overrides the default manifest file name. | | 183*60517a1eSAndroid Build Coastguard Worker| `# gazelle:python_ignore_files` | n/a | 184*60517a1eSAndroid Build Coastguard Worker| Controls the files which are ignored from the generated targets. | | 185*60517a1eSAndroid Build Coastguard Worker| `# gazelle:python_ignore_dependencies` | n/a | 186*60517a1eSAndroid Build Coastguard Worker| Controls the ignored dependencies from the generated targets. | | 187*60517a1eSAndroid Build Coastguard Worker| `# gazelle:python_validate_import_statements` | `true` | 188*60517a1eSAndroid Build Coastguard Worker| Controls whether the Python import statements should be validated. Can be "true" or "false" | | 189*60517a1eSAndroid Build Coastguard Worker| `# gazelle:python_generation_mode` | `package` | 190*60517a1eSAndroid Build Coastguard Worker| Controls the target generation mode. Can be "file", "package", or "project" | | 191*60517a1eSAndroid Build Coastguard Worker| `# gazelle:python_generation_mode_per_file_include_init` | `false` | 192*60517a1eSAndroid Build Coastguard Worker| Controls whether `__init__.py` files are included as srcs in each generated target when target generation mode is "file". Can be "true", or "false" | | 193*60517a1eSAndroid Build Coastguard Worker| [`# gazelle:python_generation_mode_per_package_require_test_entry_point`](#directive-python_generation_mode_per_package_require_test_entry_point) | `true` | 194*60517a1eSAndroid Build Coastguard Worker| Controls whether a file called `__test__.py` or a target called `__test__` is required to generate one test target per package in package mode. || 195*60517a1eSAndroid Build Coastguard Worker| `# gazelle:python_library_naming_convention` | `$package_name$` | 196*60517a1eSAndroid Build Coastguard Worker| Controls the `py_library` naming convention. It interpolates `$package_name$` with the Bazel package name. E.g. if the Bazel package name is `foo`, setting this to `$package_name$_my_lib` would result in a generated target named `foo_my_lib`. | | 197*60517a1eSAndroid Build Coastguard Worker| `# gazelle:python_binary_naming_convention` | `$package_name$_bin` | 198*60517a1eSAndroid Build Coastguard Worker| Controls the `py_binary` naming convention. Follows the same interpolation rules as `python_library_naming_convention`. | | 199*60517a1eSAndroid Build Coastguard Worker| `# gazelle:python_test_naming_convention` | `$package_name$_test` | 200*60517a1eSAndroid Build Coastguard Worker| Controls the `py_test` naming convention. Follows the same interpolation rules as `python_library_naming_convention`. | | 201*60517a1eSAndroid Build Coastguard Worker| `# gazelle:resolve py ...` | n/a | 202*60517a1eSAndroid Build Coastguard Worker| Instructs the plugin what target to add as a dependency to satisfy a given import statement. The syntax is `# gazelle:resolve py import-string label` where `import-string` is the symbol in the python `import` statement, and `label` is the Bazel label that Gazelle should write in `deps`. | | 203*60517a1eSAndroid Build Coastguard Worker| [`# gazelle:python_default_visibility labels`](#directive-python_default_visibility) | | 204*60517a1eSAndroid Build Coastguard Worker| Instructs gazelle to use these visibility labels on all python targets. `labels` is a comma-separated list of labels (without spaces). | `//$python_root$:__subpackages__` | 205*60517a1eSAndroid Build Coastguard Worker| [`# gazelle:python_visibility label`](#directive-python_visibility) | | 206*60517a1eSAndroid Build Coastguard Worker| Appends additional visibility labels to each generated target. This directive can be set multiple times. | | 207*60517a1eSAndroid Build Coastguard Worker| [`# gazelle:python_test_file_pattern`](#directive-python_test_file_pattern) | `*_test.py,test_*.py` | 208*60517a1eSAndroid Build Coastguard Worker| Filenames matching these comma-separated `glob`s will be mapped to `py_test` targets. | 209*60517a1eSAndroid Build Coastguard Worker| `# gazelle:python_label_convention` | `$distribution_name$` | 210*60517a1eSAndroid Build Coastguard Worker| Defines the format of the distribution name in labels to third-party deps. Useful for using Gazelle plugin with other rules with different repository conventions (e.g. `rules_pycross`). Full label is always prepended with (pip) repository name, e.g. `@pip//numpy`. | 211*60517a1eSAndroid Build Coastguard Worker| `# gazelle:python_label_normalization` | `snake_case` | 212*60517a1eSAndroid Build Coastguard Worker| Controls how distribution names in labels to third-party deps are normalized. Useful for using Gazelle plugin with other rules with different label conventions (e.g. `rules_pycross` uses PEP-503). Can be "snake_case", "none", or "pep503". | 213*60517a1eSAndroid Build Coastguard Worker 214*60517a1eSAndroid Build Coastguard Worker#### Directive: `python_root`: 215*60517a1eSAndroid Build Coastguard Worker 216*60517a1eSAndroid Build Coastguard WorkerSet this directive within the Bazel package that you want to use as the Python root. 217*60517a1eSAndroid Build Coastguard WorkerFor example, if using a `src` dir (as recommended by the [Python Packaging User 218*60517a1eSAndroid Build Coastguard WorkerGuide][python-packaging-user-guide]), then set this directive in `src/BUILD.bazel`: 219*60517a1eSAndroid Build Coastguard Worker 220*60517a1eSAndroid Build Coastguard Worker```starlark 221*60517a1eSAndroid Build Coastguard Worker# ./src/BUILD.bazel 222*60517a1eSAndroid Build Coastguard Worker# Tell gazelle that are python root is the same dir as this Bazel package. 223*60517a1eSAndroid Build Coastguard Worker# gazelle:python_root 224*60517a1eSAndroid Build Coastguard Worker``` 225*60517a1eSAndroid Build Coastguard Worker 226*60517a1eSAndroid Build Coastguard WorkerNote that the directive does not have any arguments. 227*60517a1eSAndroid Build Coastguard Worker 228*60517a1eSAndroid Build Coastguard WorkerGazelle will then add the necessary `imports` attribute to all targets that it 229*60517a1eSAndroid Build Coastguard Workergenerates: 230*60517a1eSAndroid Build Coastguard Worker 231*60517a1eSAndroid Build Coastguard Worker```starlark 232*60517a1eSAndroid Build Coastguard Worker# in ./src/foo/BUILD.bazel 233*60517a1eSAndroid Build Coastguard Workerpy_libary( 234*60517a1eSAndroid Build Coastguard Worker ... 235*60517a1eSAndroid Build Coastguard Worker imports = [".."], # Gazelle adds this 236*60517a1eSAndroid Build Coastguard Worker ... 237*60517a1eSAndroid Build Coastguard Worker) 238*60517a1eSAndroid Build Coastguard Worker 239*60517a1eSAndroid Build Coastguard Worker# in ./src/foo/bar/BUILD.bazel 240*60517a1eSAndroid Build Coastguard Workerpy_libary( 241*60517a1eSAndroid Build Coastguard Worker ... 242*60517a1eSAndroid Build Coastguard Worker imports = ["../.."], # Gazelle adds this 243*60517a1eSAndroid Build Coastguard Worker ... 244*60517a1eSAndroid Build Coastguard Worker) 245*60517a1eSAndroid Build Coastguard Worker``` 246*60517a1eSAndroid Build Coastguard Worker 247*60517a1eSAndroid Build Coastguard Worker[python-packaging-user-guide]: https://github.com/pypa/packaging.python.org/blob/4c86169a/source/tutorials/packaging-projects.rst 248*60517a1eSAndroid Build Coastguard Worker 249*60517a1eSAndroid Build Coastguard Worker 250*60517a1eSAndroid Build Coastguard Worker#### Directive: `python_default_visibility`: 251*60517a1eSAndroid Build Coastguard Worker 252*60517a1eSAndroid Build Coastguard WorkerInstructs gazelle to use these visibility labels on all _python_ targets 253*60517a1eSAndroid Build Coastguard Worker(typically `py_*`, but can be modified via the `map_kind` directive). The arg 254*60517a1eSAndroid Build Coastguard Workerto this directive is a a comma-separated list (without spaces) of labels. 255*60517a1eSAndroid Build Coastguard Worker 256*60517a1eSAndroid Build Coastguard WorkerFor example: 257*60517a1eSAndroid Build Coastguard Worker 258*60517a1eSAndroid Build Coastguard Worker```starlark 259*60517a1eSAndroid Build Coastguard Worker# gazelle:python_default_visibility //:__subpackages__,//tests:__subpackages__ 260*60517a1eSAndroid Build Coastguard Worker``` 261*60517a1eSAndroid Build Coastguard Worker 262*60517a1eSAndroid Build Coastguard Workerproduces the following visibility attribute: 263*60517a1eSAndroid Build Coastguard Worker 264*60517a1eSAndroid Build Coastguard Worker```starlark 265*60517a1eSAndroid Build Coastguard Workerpy_library( 266*60517a1eSAndroid Build Coastguard Worker ..., 267*60517a1eSAndroid Build Coastguard Worker visibility = [ 268*60517a1eSAndroid Build Coastguard Worker "//:__subpackages__", 269*60517a1eSAndroid Build Coastguard Worker "//tests:__subpackages__", 270*60517a1eSAndroid Build Coastguard Worker ], 271*60517a1eSAndroid Build Coastguard Worker ..., 272*60517a1eSAndroid Build Coastguard Worker) 273*60517a1eSAndroid Build Coastguard Worker``` 274*60517a1eSAndroid Build Coastguard Worker 275*60517a1eSAndroid Build Coastguard WorkerYou can also inject the `python_root` value by using the exact string 276*60517a1eSAndroid Build Coastguard Worker`$python_root$`. All instances of this string will be replaced by the `python_root` 277*60517a1eSAndroid Build Coastguard Workervalue. 278*60517a1eSAndroid Build Coastguard Worker 279*60517a1eSAndroid Build Coastguard Worker```starlark 280*60517a1eSAndroid Build Coastguard Worker# gazelle:python_default_visibility //$python_root$:__pkg__,//foo/$python_root$/tests:__subpackages__ 281*60517a1eSAndroid Build Coastguard Worker 282*60517a1eSAndroid Build Coastguard Worker# Assuming the "# gazelle:python_root" directive is set in ./py/src/BUILD.bazel, 283*60517a1eSAndroid Build Coastguard Worker# the results will be: 284*60517a1eSAndroid Build Coastguard Workerpy_library( 285*60517a1eSAndroid Build Coastguard Worker ..., 286*60517a1eSAndroid Build Coastguard Worker visibility = [ 287*60517a1eSAndroid Build Coastguard Worker "//foo/py/src/tests:__subpackages__", # sorted alphabetically 288*60517a1eSAndroid Build Coastguard Worker "//py/src:__pkg__", 289*60517a1eSAndroid Build Coastguard Worker ], 290*60517a1eSAndroid Build Coastguard Worker ..., 291*60517a1eSAndroid Build Coastguard Worker) 292*60517a1eSAndroid Build Coastguard Worker``` 293*60517a1eSAndroid Build Coastguard Worker 294*60517a1eSAndroid Build Coastguard WorkerTwo special values are also accepted as an argument to the directive: 295*60517a1eSAndroid Build Coastguard Worker 296*60517a1eSAndroid Build Coastguard Worker+ `NONE`: This removes all default visibility. Labels added by the 297*60517a1eSAndroid Build Coastguard Worker `python_visibility` directive are still included. 298*60517a1eSAndroid Build Coastguard Worker+ `DEFAULT`: This resets the default visibility. 299*60517a1eSAndroid Build Coastguard Worker 300*60517a1eSAndroid Build Coastguard WorkerFor example: 301*60517a1eSAndroid Build Coastguard Worker 302*60517a1eSAndroid Build Coastguard Worker```starlark 303*60517a1eSAndroid Build Coastguard Worker# gazelle:python_default_visibility NONE 304*60517a1eSAndroid Build Coastguard Worker 305*60517a1eSAndroid Build Coastguard Workerpy_library( 306*60517a1eSAndroid Build Coastguard Worker name = "...", 307*60517a1eSAndroid Build Coastguard Worker srcs = [...], 308*60517a1eSAndroid Build Coastguard Worker) 309*60517a1eSAndroid Build Coastguard Worker``` 310*60517a1eSAndroid Build Coastguard Worker 311*60517a1eSAndroid Build Coastguard Worker```starlark 312*60517a1eSAndroid Build Coastguard Worker# gazelle:python_default_visibility //foo:bar 313*60517a1eSAndroid Build Coastguard Worker# gazelle:python_default_visibility DEFAULT 314*60517a1eSAndroid Build Coastguard Worker 315*60517a1eSAndroid Build Coastguard Workerpy_library( 316*60517a1eSAndroid Build Coastguard Worker ..., 317*60517a1eSAndroid Build Coastguard Worker visibility = ["//:__subpackages__"], 318*60517a1eSAndroid Build Coastguard Worker ..., 319*60517a1eSAndroid Build Coastguard Worker) 320*60517a1eSAndroid Build Coastguard Worker``` 321*60517a1eSAndroid Build Coastguard Worker 322*60517a1eSAndroid Build Coastguard WorkerThese special values can be useful for sub-packages. 323*60517a1eSAndroid Build Coastguard Worker 324*60517a1eSAndroid Build Coastguard Worker 325*60517a1eSAndroid Build Coastguard Worker#### Directive: `python_visibility`: 326*60517a1eSAndroid Build Coastguard Worker 327*60517a1eSAndroid Build Coastguard WorkerAppends additional `visibility` labels to each generated target. 328*60517a1eSAndroid Build Coastguard Worker 329*60517a1eSAndroid Build Coastguard WorkerThis directive can be set multiple times. The generated `visibility` attribute 330*60517a1eSAndroid Build Coastguard Workerwill include the default visibility and all labels defined by this directive. 331*60517a1eSAndroid Build Coastguard WorkerAll labels will be ordered alphabetically. 332*60517a1eSAndroid Build Coastguard Worker 333*60517a1eSAndroid Build Coastguard Worker```starlark 334*60517a1eSAndroid Build Coastguard Worker# ./BUILD.bazel 335*60517a1eSAndroid Build Coastguard Worker# gazelle:python_visibility //tests:__pkg__ 336*60517a1eSAndroid Build Coastguard Worker# gazelle:python_visibility //bar:baz 337*60517a1eSAndroid Build Coastguard Worker 338*60517a1eSAndroid Build Coastguard Workerpy_library( 339*60517a1eSAndroid Build Coastguard Worker ... 340*60517a1eSAndroid Build Coastguard Worker visibility = [ 341*60517a1eSAndroid Build Coastguard Worker "//:__subpackages__", # default visibility 342*60517a1eSAndroid Build Coastguard Worker "//bar:baz", 343*60517a1eSAndroid Build Coastguard Worker "//tests:__pkg__", 344*60517a1eSAndroid Build Coastguard Worker ], 345*60517a1eSAndroid Build Coastguard Worker ... 346*60517a1eSAndroid Build Coastguard Worker) 347*60517a1eSAndroid Build Coastguard Worker``` 348*60517a1eSAndroid Build Coastguard Worker 349*60517a1eSAndroid Build Coastguard WorkerChild Bazel packages inherit values from parents: 350*60517a1eSAndroid Build Coastguard Worker 351*60517a1eSAndroid Build Coastguard Worker```starlark 352*60517a1eSAndroid Build Coastguard Worker# ./bar/BUILD.bazel 353*60517a1eSAndroid Build Coastguard Worker# gazelle:python_visibility //tests:__subpackages__ 354*60517a1eSAndroid Build Coastguard Worker 355*60517a1eSAndroid Build Coastguard Workerpy_library( 356*60517a1eSAndroid Build Coastguard Worker ... 357*60517a1eSAndroid Build Coastguard Worker visibility = [ 358*60517a1eSAndroid Build Coastguard Worker "//:__subpackages__", # default visibility 359*60517a1eSAndroid Build Coastguard Worker "//bar:baz", # defined in ../BUILD.bazel 360*60517a1eSAndroid Build Coastguard Worker "//tests:__pkg__", # defined in ../BUILD.bazel 361*60517a1eSAndroid Build Coastguard Worker "//tests:__subpackages__", # defined in this ./BUILD.bazel 362*60517a1eSAndroid Build Coastguard Worker ], 363*60517a1eSAndroid Build Coastguard Worker ... 364*60517a1eSAndroid Build Coastguard Worker) 365*60517a1eSAndroid Build Coastguard Worker 366*60517a1eSAndroid Build Coastguard Worker``` 367*60517a1eSAndroid Build Coastguard Worker 368*60517a1eSAndroid Build Coastguard WorkerThis directive also supports the `$python_root$` placeholder that 369*60517a1eSAndroid Build Coastguard Worker`# gazelle:python_default_visibility` supports. 370*60517a1eSAndroid Build Coastguard Worker 371*60517a1eSAndroid Build Coastguard Worker```starlark 372*60517a1eSAndroid Build Coastguard Worker# gazlle:python_visibility //$python_root$/foo:bar 373*60517a1eSAndroid Build Coastguard Worker 374*60517a1eSAndroid Build Coastguard Workerpy_library( 375*60517a1eSAndroid Build Coastguard Worker ... 376*60517a1eSAndroid Build Coastguard Worker visibility = ["//this_is_my_python_root/foo:bar"], 377*60517a1eSAndroid Build Coastguard Worker ... 378*60517a1eSAndroid Build Coastguard Worker) 379*60517a1eSAndroid Build Coastguard Worker``` 380*60517a1eSAndroid Build Coastguard Worker 381*60517a1eSAndroid Build Coastguard Worker 382*60517a1eSAndroid Build Coastguard Worker#### Directive: `python_test_file_pattern`: 383*60517a1eSAndroid Build Coastguard Worker 384*60517a1eSAndroid Build Coastguard WorkerThis directive adjusts which python files will be mapped to the `py_test` rule. 385*60517a1eSAndroid Build Coastguard Worker 386*60517a1eSAndroid Build Coastguard Worker+ The default is `*_test.py,test_*.py`: both `test_*.py` and `*_test.py` files 387*60517a1eSAndroid Build Coastguard Worker will generate `py_test` targets. 388*60517a1eSAndroid Build Coastguard Worker+ This directive must have a value. If no value is given, an error will be raised. 389*60517a1eSAndroid Build Coastguard Worker+ It is recommended, though not necessary, to include the `.py` extension in 390*60517a1eSAndroid Build Coastguard Worker the `glob`s: `foo*.py,?at.py`. 391*60517a1eSAndroid Build Coastguard Worker+ Like most directives, it applies to the current Bazel package and all subpackages 392*60517a1eSAndroid Build Coastguard Worker until the directive is set again. 393*60517a1eSAndroid Build Coastguard Worker+ This directive accepts multiple `glob` patterns, separated by commas without spaces: 394*60517a1eSAndroid Build Coastguard Worker 395*60517a1eSAndroid Build Coastguard Worker```starlark 396*60517a1eSAndroid Build Coastguard Worker# gazelle:python_test_file_pattern foo*.py,?at 397*60517a1eSAndroid Build Coastguard Worker 398*60517a1eSAndroid Build Coastguard Workerpy_library( 399*60517a1eSAndroid Build Coastguard Worker name = "mylib", 400*60517a1eSAndroid Build Coastguard Worker srcs = ["mylib.py"], 401*60517a1eSAndroid Build Coastguard Worker) 402*60517a1eSAndroid Build Coastguard Worker 403*60517a1eSAndroid Build Coastguard Workerpy_test( 404*60517a1eSAndroid Build Coastguard Worker name = "foo_bar", 405*60517a1eSAndroid Build Coastguard Worker srcs = ["foo_bar.py"], 406*60517a1eSAndroid Build Coastguard Worker) 407*60517a1eSAndroid Build Coastguard Worker 408*60517a1eSAndroid Build Coastguard Workerpy_test( 409*60517a1eSAndroid Build Coastguard Worker name = "cat", 410*60517a1eSAndroid Build Coastguard Worker srcs = ["cat.py"], 411*60517a1eSAndroid Build Coastguard Worker) 412*60517a1eSAndroid Build Coastguard Worker 413*60517a1eSAndroid Build Coastguard Workerpy_test( 414*60517a1eSAndroid Build Coastguard Worker name = "hat", 415*60517a1eSAndroid Build Coastguard Worker srcs = ["hat.py"], 416*60517a1eSAndroid Build Coastguard Worker) 417*60517a1eSAndroid Build Coastguard Worker``` 418*60517a1eSAndroid Build Coastguard Worker 419*60517a1eSAndroid Build Coastguard Worker 420*60517a1eSAndroid Build Coastguard Worker##### Notes 421*60517a1eSAndroid Build Coastguard Worker 422*60517a1eSAndroid Build Coastguard WorkerResetting to the default value (such as in a subpackage) is manual. Set: 423*60517a1eSAndroid Build Coastguard Worker 424*60517a1eSAndroid Build Coastguard Worker```starlark 425*60517a1eSAndroid Build Coastguard Worker# gazelle:python_test_file_pattern *_test.py,test_*.py 426*60517a1eSAndroid Build Coastguard Worker``` 427*60517a1eSAndroid Build Coastguard Worker 428*60517a1eSAndroid Build Coastguard WorkerThere currently is no way to tell gazelle that _no_ files in a package should 429*60517a1eSAndroid Build Coastguard Workerbe mapped to `py_test` targets (see [Issue #1826][issue-1826]). The workaround 430*60517a1eSAndroid Build Coastguard Workeris to set this directive to a pattern that will never match a `.py` file, such 431*60517a1eSAndroid Build Coastguard Workeras `foo.bar`: 432*60517a1eSAndroid Build Coastguard Worker 433*60517a1eSAndroid Build Coastguard Worker```starlark 434*60517a1eSAndroid Build Coastguard Worker# No files in this package should be mapped to py_test targets. 435*60517a1eSAndroid Build Coastguard Worker# gazelle:python_test_file_pattern foo.bar 436*60517a1eSAndroid Build Coastguard Worker 437*60517a1eSAndroid Build Coastguard Workerpy_library( 438*60517a1eSAndroid Build Coastguard Worker name = "my_test", 439*60517a1eSAndroid Build Coastguard Worker srcs = ["my_test.py"], 440*60517a1eSAndroid Build Coastguard Worker) 441*60517a1eSAndroid Build Coastguard Worker``` 442*60517a1eSAndroid Build Coastguard Worker 443*60517a1eSAndroid Build Coastguard Worker[issue-1826]: https://github.com/bazelbuild/rules_python/issues/1826 444*60517a1eSAndroid Build Coastguard Worker 445*60517a1eSAndroid Build Coastguard Worker#### Directive: `python_generation_mode_per_package_require_test_entry_point`: 446*60517a1eSAndroid Build Coastguard WorkerWhen `# gazelle:python_generation_mode package`, whether a file called `__test__.py` or a target called `__test__`, a.k.a., entry point, is required to generate one test target per package. If this is set to true but no entry point is found, Gazelle will fall back to file mode and generate one test target per file. Setting this directive to false forces Gazelle to generate one test target per package even without entry point. However, this means the `main` attribute of the `py_test` will not be set and the target will not be runnable unless either: 447*60517a1eSAndroid Build Coastguard Worker1. there happen to be a file in the `srcs` with the same name as the `py_test` target, or 448*60517a1eSAndroid Build Coastguard Worker2. a macro populating the `main` attribute of `py_test` is configured with `gazelle:map_kind` to replace `py_test` when Gazelle is generating Python test targets. For example, user can provide such a macro to Gazelle: 449*60517a1eSAndroid Build Coastguard Worker 450*60517a1eSAndroid Build Coastguard Worker```starlark 451*60517a1eSAndroid Build Coastguard Workerload("@rules_python//python:defs.bzl", _py_test="py_test") 452*60517a1eSAndroid Build Coastguard Workerload("@aspect_rules_py//py:defs.bzl", "py_pytest_main") 453*60517a1eSAndroid Build Coastguard Worker 454*60517a1eSAndroid Build Coastguard Workerdef py_test(name, main=None, **kwargs): 455*60517a1eSAndroid Build Coastguard Worker deps = kwargs.pop("deps", []) 456*60517a1eSAndroid Build Coastguard Worker if not main: 457*60517a1eSAndroid Build Coastguard Worker py_pytest_main( 458*60517a1eSAndroid Build Coastguard Worker name = "__test__", 459*60517a1eSAndroid Build Coastguard Worker deps = ["@pip_pytest//:pkg"], # change this to the pytest target in your repo. 460*60517a1eSAndroid Build Coastguard Worker ) 461*60517a1eSAndroid Build Coastguard Worker 462*60517a1eSAndroid Build Coastguard Worker deps.append(":__test__") 463*60517a1eSAndroid Build Coastguard Worker main = ":__test__.py" 464*60517a1eSAndroid Build Coastguard Worker 465*60517a1eSAndroid Build Coastguard Worker _py_test( 466*60517a1eSAndroid Build Coastguard Worker name = name, 467*60517a1eSAndroid Build Coastguard Worker main = main, 468*60517a1eSAndroid Build Coastguard Worker deps = deps, 469*60517a1eSAndroid Build Coastguard Worker **kwargs, 470*60517a1eSAndroid Build Coastguard Worker) 471*60517a1eSAndroid Build Coastguard Worker``` 472*60517a1eSAndroid Build Coastguard Worker 473*60517a1eSAndroid Build Coastguard Worker### Annotations 474*60517a1eSAndroid Build Coastguard Worker 475*60517a1eSAndroid Build Coastguard Worker*Annotations* refer to comments found _within Python files_ that configure how 476*60517a1eSAndroid Build Coastguard WorkerGazelle acts for that particular file. 477*60517a1eSAndroid Build Coastguard Worker 478*60517a1eSAndroid Build Coastguard WorkerAnnotations have the form: 479*60517a1eSAndroid Build Coastguard Worker 480*60517a1eSAndroid Build Coastguard Worker```python 481*60517a1eSAndroid Build Coastguard Worker# gazelle:annotation_name value 482*60517a1eSAndroid Build Coastguard Worker``` 483*60517a1eSAndroid Build Coastguard Worker 484*60517a1eSAndroid Build Coastguard Workerand can reside anywhere within a Python file where comments are valid. For example: 485*60517a1eSAndroid Build Coastguard Worker 486*60517a1eSAndroid Build Coastguard Worker```python 487*60517a1eSAndroid Build Coastguard Workerimport foo 488*60517a1eSAndroid Build Coastguard Worker# gazelle:annotation_name value 489*60517a1eSAndroid Build Coastguard Worker 490*60517a1eSAndroid Build Coastguard Workerdef bar(): # gazelle:annotation_name value 491*60517a1eSAndroid Build Coastguard Worker pass 492*60517a1eSAndroid Build Coastguard Worker``` 493*60517a1eSAndroid Build Coastguard Worker 494*60517a1eSAndroid Build Coastguard WorkerThe annotations are: 495*60517a1eSAndroid Build Coastguard Worker 496*60517a1eSAndroid Build Coastguard Worker| **Annotation** | **Default value** | 497*60517a1eSAndroid Build Coastguard Worker|---------------------------------------------------------------|-------------------| 498*60517a1eSAndroid Build Coastguard Worker| [`# gazelle:ignore imports`](#annotation-ignore) | N/A | 499*60517a1eSAndroid Build Coastguard Worker| Tells Gazelle to ignore import statements. `imports` is a comma-separated list of imports to ignore. | | 500*60517a1eSAndroid Build Coastguard Worker| [`# gazelle:include_dep targets`](#annotation-include_dep) | N/A | 501*60517a1eSAndroid Build Coastguard Worker| Tells Gazelle to include a set of dependencies, even if they are not imported in a Python module. `targets` is a comma-separated list of target names to include as dependencies. | | 502*60517a1eSAndroid Build Coastguard Worker 503*60517a1eSAndroid Build Coastguard Worker 504*60517a1eSAndroid Build Coastguard Worker#### Annotation: `ignore` 505*60517a1eSAndroid Build Coastguard Worker 506*60517a1eSAndroid Build Coastguard WorkerThis annotation accepts a comma-separated string of values. Values are names of Python 507*60517a1eSAndroid Build Coastguard Workerimports that Gazelle should _not_ include in target dependencies. 508*60517a1eSAndroid Build Coastguard Worker 509*60517a1eSAndroid Build Coastguard WorkerThe annotation can be added multiple times, and all values are combined and 510*60517a1eSAndroid Build Coastguard Workerde-duplicated. 511*60517a1eSAndroid Build Coastguard Worker 512*60517a1eSAndroid Build Coastguard WorkerFor `python_generation_mode = "package"`, the `ignore` annotations 513*60517a1eSAndroid Build Coastguard Workerfound across all files included in the generated target are removed from `deps`. 514*60517a1eSAndroid Build Coastguard Worker 515*60517a1eSAndroid Build Coastguard WorkerExample: 516*60517a1eSAndroid Build Coastguard Worker 517*60517a1eSAndroid Build Coastguard Worker```python 518*60517a1eSAndroid Build Coastguard Workerimport numpy # a pypi package 519*60517a1eSAndroid Build Coastguard Worker 520*60517a1eSAndroid Build Coastguard Worker# gazelle:ignore bar.baz.hello,foo 521*60517a1eSAndroid Build Coastguard Workerimport bar.baz.hello 522*60517a1eSAndroid Build Coastguard Workerimport foo 523*60517a1eSAndroid Build Coastguard Worker 524*60517a1eSAndroid Build Coastguard Worker# Ignore this import because _reasons_ 525*60517a1eSAndroid Build Coastguard Workerimport baz # gazelle:ignore baz 526*60517a1eSAndroid Build Coastguard Worker``` 527*60517a1eSAndroid Build Coastguard Worker 528*60517a1eSAndroid Build Coastguard Workerwill cause Gazelle to generate: 529*60517a1eSAndroid Build Coastguard Worker 530*60517a1eSAndroid Build Coastguard Worker```starlark 531*60517a1eSAndroid Build Coastguard Workerdeps = ["@pypi//numpy"], 532*60517a1eSAndroid Build Coastguard Worker``` 533*60517a1eSAndroid Build Coastguard Worker 534*60517a1eSAndroid Build Coastguard Worker 535*60517a1eSAndroid Build Coastguard Worker#### Annotation: `include_dep` 536*60517a1eSAndroid Build Coastguard Worker 537*60517a1eSAndroid Build Coastguard WorkerThis annotation accepts a comma-separated string of values. Values _must_ 538*60517a1eSAndroid Build Coastguard Workerbe Python targets, but _no validation is done_. If a value is not a Python 539*60517a1eSAndroid Build Coastguard Workertarget, building will result in an error saying: 540*60517a1eSAndroid Build Coastguard Worker 541*60517a1eSAndroid Build Coastguard Worker``` 542*60517a1eSAndroid Build Coastguard Worker<target> does not have mandatory providers: 'PyInfo' or 'CcInfo' or 'PyInfo'. 543*60517a1eSAndroid Build Coastguard Worker``` 544*60517a1eSAndroid Build Coastguard Worker 545*60517a1eSAndroid Build Coastguard WorkerAdding non-Python targets to the generated target is a feature request being 546*60517a1eSAndroid Build Coastguard Workertracked in [Issue #1865](https://github.com/bazelbuild/rules_python/issues/1865). 547*60517a1eSAndroid Build Coastguard Worker 548*60517a1eSAndroid Build Coastguard WorkerThe annotation can be added multiple times, and all values are combined 549*60517a1eSAndroid Build Coastguard Workerand de-duplicated. 550*60517a1eSAndroid Build Coastguard Worker 551*60517a1eSAndroid Build Coastguard WorkerFor `python_generation_mode = "package"`, the `include_dep` annotations 552*60517a1eSAndroid Build Coastguard Workerfound across all files included in the generated target are included in `deps`. 553*60517a1eSAndroid Build Coastguard Worker 554*60517a1eSAndroid Build Coastguard WorkerExample: 555*60517a1eSAndroid Build Coastguard Worker 556*60517a1eSAndroid Build Coastguard Worker```python 557*60517a1eSAndroid Build Coastguard Worker# gazelle:include_dep //foo:bar,:hello_world,//:abc 558*60517a1eSAndroid Build Coastguard Worker# gazelle:include_dep //:def,//foo:bar 559*60517a1eSAndroid Build Coastguard Workerimport numpy # a pypi package 560*60517a1eSAndroid Build Coastguard Worker``` 561*60517a1eSAndroid Build Coastguard Worker 562*60517a1eSAndroid Build Coastguard Workerwill cause Gazelle to generate: 563*60517a1eSAndroid Build Coastguard Worker 564*60517a1eSAndroid Build Coastguard Worker```starlark 565*60517a1eSAndroid Build Coastguard Workerdeps = [ 566*60517a1eSAndroid Build Coastguard Worker ":hello_world", 567*60517a1eSAndroid Build Coastguard Worker "//:abc", 568*60517a1eSAndroid Build Coastguard Worker "//:def", 569*60517a1eSAndroid Build Coastguard Worker "//foo:bar", 570*60517a1eSAndroid Build Coastguard Worker "@pypi//numpy", 571*60517a1eSAndroid Build Coastguard Worker] 572*60517a1eSAndroid Build Coastguard Worker``` 573*60517a1eSAndroid Build Coastguard Worker 574*60517a1eSAndroid Build Coastguard Worker 575*60517a1eSAndroid Build Coastguard Worker### Libraries 576*60517a1eSAndroid Build Coastguard Worker 577*60517a1eSAndroid Build Coastguard WorkerPython source files are those ending in `.py` but not ending in `_test.py`. 578*60517a1eSAndroid Build Coastguard Worker 579*60517a1eSAndroid Build Coastguard WorkerFirst, we look for the nearest ancestor BUILD file starting from the folder 580*60517a1eSAndroid Build Coastguard Workercontaining the Python source file. 581*60517a1eSAndroid Build Coastguard Worker 582*60517a1eSAndroid Build Coastguard WorkerIn package generation mode, if there is no `py_library` in this BUILD file, one 583*60517a1eSAndroid Build Coastguard Workeris created using the package name as the target's name. This makes it the 584*60517a1eSAndroid Build Coastguard Workerdefault target in the package. Next, all source files are collected into the 585*60517a1eSAndroid Build Coastguard Worker`srcs` of the `py_library`. 586*60517a1eSAndroid Build Coastguard Worker 587*60517a1eSAndroid Build Coastguard WorkerIn project generation mode, all source files in subdirectories (that don't have 588*60517a1eSAndroid Build Coastguard WorkerBUILD files) are also collected. 589*60517a1eSAndroid Build Coastguard Worker 590*60517a1eSAndroid Build Coastguard WorkerIn file generation mode, each file is given its own target. 591*60517a1eSAndroid Build Coastguard Worker 592*60517a1eSAndroid Build Coastguard WorkerFinally, the `import` statements in the source files are parsed, and 593*60517a1eSAndroid Build Coastguard Workerdependencies are added to the `deps` attribute. 594*60517a1eSAndroid Build Coastguard Worker 595*60517a1eSAndroid Build Coastguard Worker### Unit Tests 596*60517a1eSAndroid Build Coastguard Worker 597*60517a1eSAndroid Build Coastguard WorkerA `py_test` target is added to the BUILD file when gazelle encounters 598*60517a1eSAndroid Build Coastguard Workera file named `__test__.py`. 599*60517a1eSAndroid Build Coastguard WorkerOften, Python unit test files are named with the suffix `_test`. 600*60517a1eSAndroid Build Coastguard WorkerFor example, if we had a folder that is a package named "foo" we could have a Python file named `foo_test.py` 601*60517a1eSAndroid Build Coastguard Workerand gazelle would create a `py_test` block for the file. 602*60517a1eSAndroid Build Coastguard Worker 603*60517a1eSAndroid Build Coastguard WorkerThe following is an example of a `py_test` target that gazelle would add when 604*60517a1eSAndroid Build Coastguard Workerit encounters a file named `__test__.py`. 605*60517a1eSAndroid Build Coastguard Worker 606*60517a1eSAndroid Build Coastguard Worker```starlark 607*60517a1eSAndroid Build Coastguard Workerpy_test( 608*60517a1eSAndroid Build Coastguard Worker name = "build_file_generation_test", 609*60517a1eSAndroid Build Coastguard Worker srcs = ["__test__.py"], 610*60517a1eSAndroid Build Coastguard Worker main = "__test__.py", 611*60517a1eSAndroid Build Coastguard Worker deps = [":build_file_generation"], 612*60517a1eSAndroid Build Coastguard Worker) 613*60517a1eSAndroid Build Coastguard Worker``` 614*60517a1eSAndroid Build Coastguard Worker 615*60517a1eSAndroid Build Coastguard WorkerYou can control the naming convention for test targets by adding a gazelle directive named 616*60517a1eSAndroid Build Coastguard Worker`# gazelle:python_test_naming_convention`. See the instructions in the section above that 617*60517a1eSAndroid Build Coastguard Workercovers directives. 618*60517a1eSAndroid Build Coastguard Worker 619*60517a1eSAndroid Build Coastguard Worker### Binaries 620*60517a1eSAndroid Build Coastguard Worker 621*60517a1eSAndroid Build Coastguard WorkerWhen a `__main__.py` file is encountered, this indicates the entry point 622*60517a1eSAndroid Build Coastguard Workerof a Python program. A `py_binary` target will be created, named `[package]_bin`. 623*60517a1eSAndroid Build Coastguard Worker 624*60517a1eSAndroid Build Coastguard WorkerWhen no such entry point exists, Gazelle will look for a line like this in the top level in every module: 625*60517a1eSAndroid Build Coastguard Worker 626*60517a1eSAndroid Build Coastguard Worker```python 627*60517a1eSAndroid Build Coastguard Workerif __name == "__main__": 628*60517a1eSAndroid Build Coastguard Worker``` 629*60517a1eSAndroid Build Coastguard Worker 630*60517a1eSAndroid Build Coastguard WorkerGazelle will create a `py_binary` target for every module with such a line, with 631*60517a1eSAndroid Build Coastguard Workerthe target name the same as the module name. 632*60517a1eSAndroid Build Coastguard Worker 633*60517a1eSAndroid Build Coastguard WorkerIf `python_generation_mode` is set to `file`, then instead of one `py_binary` 634*60517a1eSAndroid Build Coastguard Workertarget per module, Gazelle will create one `py_binary` target for each file with 635*60517a1eSAndroid Build Coastguard Workersuch a line, and the name of the target will match the name of the script. 636*60517a1eSAndroid Build Coastguard Worker 637*60517a1eSAndroid Build Coastguard WorkerNote that it's possible for another script to depend on a `py_binary` target and 638*60517a1eSAndroid Build Coastguard Workerimport from the `py_binary`'s scripts. This can have possible negative effects on 639*60517a1eSAndroid Build Coastguard WorkerBazel analysis time and runfiles size compared to depending on a `py_library` 640*60517a1eSAndroid Build Coastguard Workertarget. The simplest way to avoid these negative effects is to extract library 641*60517a1eSAndroid Build Coastguard Workercode into a separate script without a `main` line. Gazelle will then create a 642*60517a1eSAndroid Build Coastguard Worker`py_library` target for that library code, and other scripts can depend on that 643*60517a1eSAndroid Build Coastguard Worker`py_library` target. 644*60517a1eSAndroid Build Coastguard Worker 645*60517a1eSAndroid Build Coastguard Worker## Developer Notes 646*60517a1eSAndroid Build Coastguard Worker 647*60517a1eSAndroid Build Coastguard WorkerGazelle extensions are written in Go. This gazelle plugin is a hybrid, as it uses Go to execute a 648*60517a1eSAndroid Build Coastguard WorkerPython interpreter as a subprocess to parse Python source files. 649*60517a1eSAndroid Build Coastguard WorkerSee the gazelle documentation https://github.com/bazelbuild/bazel-gazelle/blob/master/extend.md 650*60517a1eSAndroid Build Coastguard Workerfor more information on extending Gazelle. 651*60517a1eSAndroid Build Coastguard Worker 652*60517a1eSAndroid Build Coastguard WorkerIf you add new Go dependencies to the plugin source code, you need to "tidy" the go.mod file. 653*60517a1eSAndroid Build Coastguard WorkerAfter changing that file, run `go mod tidy` or `bazel run @go_sdk//:bin/go -- mod tidy` 654*60517a1eSAndroid Build Coastguard Workerto update the go.mod and go.sum files. Then run `bazel run //:gazelle_update_repos` to have gazelle 655*60517a1eSAndroid Build Coastguard Workeradd the new dependenies to the deps.bzl file. The deps.bzl file is used as defined in our /WORKSPACE 656*60517a1eSAndroid Build Coastguard Workerto include the external repos Bazel loads Go dependencies from. 657*60517a1eSAndroid Build Coastguard Worker 658*60517a1eSAndroid Build Coastguard WorkerThen after editing Go code, run `bazel run //:gazelle` to generate/update the rules in the 659*60517a1eSAndroid Build Coastguard WorkerBUILD.bazel files in our repo. 660