Skip to content

Commit 54397d7

Browse files
authored
docs(gazelle): Migrate Gazelle docs to ReadTheDocs, part 2/5: installation and usage (#3132)
Part of #3082 2nd of probably 5 PRs. + Migrate installation and usage info from `gazelle/README.md` to `gazelle/docs/installation_and_usage.md` + Slight rewording and reformatting of the `Example` section. + Reorganized and modernized the `MODULE.bazel` and `BUILD.bazel` examples: + less details on rules_python as that's available in other docs + default to gazelle multilang support now that #3057 is merged. + Mechanical updates: + Wrap at ~80 chars + Use MyST directives and roles.
1 parent 2fc5f1c commit 54397d7

File tree

3 files changed

+152
-139
lines changed

3 files changed

+152
-139
lines changed

gazelle/README.md

Lines changed: 0 additions & 139 deletions
Original file line numberDiff line numberDiff line change
@@ -6,145 +6,6 @@ ReadTheDocs. Please see https://rules-python.readthedocs.io/gazelle/docs/index.h
66
:::
77

88

9-
## Example
10-
11-
We have an example of using Gazelle with Python located [here](https://github.com/bazel-contrib/rules_python/tree/main/examples/bzlmod).
12-
A fully-working example without using bzlmod is in [`examples/build_file_generation`](../examples/build_file_generation).
13-
14-
The following documentation covers using bzlmod.
15-
16-
## Adding Gazelle to your project
17-
18-
First, you'll need to add Gazelle to your `MODULE.bazel` file.
19-
Get the current version of Gazelle from there releases here: https://github.com/bazelbuild/bazel-gazelle/releases/.
20-
21-
22-
See the installation `MODULE.bazel` snippet on the Releases page:
23-
https://github.com/bazel-contrib/rules_python/releases in order to configure rules_python.
24-
25-
You will also need to add the `bazel_dep` for configuration for `rules_python_gazelle_plugin`.
26-
27-
Here is a snippet of a `MODULE.bazel` file.
28-
29-
```starlark
30-
# The following stanza defines the dependency rules_python.
31-
bazel_dep(name = "rules_python", version = "0.22.0")
32-
33-
# The following stanza defines the dependency rules_python_gazelle_plugin.
34-
# For typical setups you set the version.
35-
bazel_dep(name = "rules_python_gazelle_plugin", version = "0.22.0")
36-
37-
# The following stanza defines the dependency gazelle.
38-
bazel_dep(name = "gazelle", version = "0.31.0", repo_name = "bazel_gazelle")
39-
40-
# Import the python repositories generated by the given module extension into the scope of the current module.
41-
use_repo(python, "python3_9")
42-
use_repo(python, "python3_9_toolchains")
43-
44-
# Register an already-defined toolchain so that Bazel can use it during toolchain resolution.
45-
register_toolchains(
46-
"@python3_9_toolchains//:all",
47-
)
48-
49-
# Use the pip extension
50-
pip = use_extension("@rules_python//python:extensions.bzl", "pip")
51-
52-
# Use the extension to call the `pip_repository` rule that invokes `pip`, with `incremental` set.
53-
# Accepts a locked/compiled requirements file and installs the dependencies listed within.
54-
# Those dependencies become available in a generated `requirements.bzl` file.
55-
# You can instead check this `requirements.bzl` file into your repo.
56-
# Because this project has different requirements for windows vs other
57-
# operating systems, we have requirements for each.
58-
pip.parse(
59-
name = "pip",
60-
requirements_lock = "//:requirements_lock.txt",
61-
requirements_windows = "//:requirements_windows.txt",
62-
)
63-
64-
# Imports the pip toolchain generated by the given module extension into the scope of the current module.
65-
use_repo(pip, "pip")
66-
```
67-
Next, we'll fetch metadata about your Python dependencies, so that gazelle can
68-
determine which package a given import statement comes from. This is provided
69-
by the `modules_mapping` rule. We'll make a target for consuming this
70-
`modules_mapping`, and writing it as a manifest file for Gazelle to read.
71-
This is checked into the repo for speed, as it takes some time to calculate
72-
in a large monorepo.
73-
74-
Gazelle will walk up the filesystem from a Python file to find this metadata,
75-
looking for a file called `gazelle_python.yaml` in an ancestor folder of the Python code.
76-
Create an empty file with this name. It might be next to your `requirements.txt` file.
77-
(You can just use `touch` at this point, it just needs to exist.)
78-
79-
To keep the metadata updated, put this in your `BUILD.bazel` file next to `gazelle_python.yaml`:
80-
81-
```starlark
82-
load("@pip//:requirements.bzl", "all_whl_requirements")
83-
load("@rules_python_gazelle_plugin//manifest:defs.bzl", "gazelle_python_manifest")
84-
load("@rules_python_gazelle_plugin//modules_mapping:def.bzl", "modules_mapping")
85-
86-
# This rule fetches the metadata for python packages we depend on. That data is
87-
# required for the gazelle_python_manifest rule to update our manifest file.
88-
modules_mapping(
89-
name = "modules_map",
90-
wheels = all_whl_requirements,
91-
)
92-
93-
# Gazelle python extension needs a manifest file mapping from
94-
# an import to the installed package that provides it.
95-
# This macro produces two targets:
96-
# - //:gazelle_python_manifest.update can be used with `bazel run`
97-
# to recalculate the manifest
98-
# - //:gazelle_python_manifest.test is a test target ensuring that
99-
# the manifest doesn't need to be updated
100-
gazelle_python_manifest(
101-
name = "gazelle_python_manifest",
102-
modules_mapping = ":modules_map",
103-
# This is what we called our `pip_parse` rule, where third-party
104-
# python libraries are loaded in BUILD files.
105-
pip_repository_name = "pip",
106-
# This should point to wherever we declare our python dependencies
107-
# (the same as what we passed to the modules_mapping rule in WORKSPACE)
108-
# This argument is optional. If provided, the `.test` target is very
109-
# fast because it just has to check an integrity field. If not provided,
110-
# the integrity field is not added to the manifest which can help avoid
111-
# merge conflicts in large repos.
112-
requirements = "//:requirements_lock.txt",
113-
# include_stub_packages: bool (default: False)
114-
# If set to True, this flag automatically includes any corresponding type stub packages
115-
# for the third-party libraries that are present and used. For example, if you have
116-
# `boto3` as a dependency, and this flag is enabled, the corresponding `boto3-stubs`
117-
# package will be automatically included in the BUILD file.
118-
#
119-
# Enabling this feature helps ensure that type hints and stubs are readily available
120-
# for tools like type checkers and IDEs, improving the development experience and
121-
# reducing manual overhead in managing separate stub packages.
122-
include_stub_packages = True
123-
)
124-
```
125-
126-
Finally, you create a target that you'll invoke to run the Gazelle tool
127-
with the rules_python extension included. This typically goes in your root
128-
`/BUILD.bazel` file:
129-
130-
```starlark
131-
load("@bazel_gazelle//:def.bzl", "gazelle")
132-
133-
# Our gazelle target points to the python gazelle binary.
134-
# This is the simple case where we only need one language supported.
135-
# If you also had proto, go, or other gazelle-supported languages,
136-
# you would also need a gazelle_binary rule.
137-
# See https://github.com/bazelbuild/bazel-gazelle/blob/master/extend.rst#example
138-
gazelle(
139-
name = "gazelle",
140-
gazelle = "@rules_python_gazelle_plugin//python:gazelle_binary",
141-
)
142-
```
143-
144-
That's it, now you can finally run `bazel run //:gazelle` anytime
145-
you edit Python code, and it should update your `BUILD` files correctly.
146-
147-
1489
### Directives
14910

15011
You can configure the extension using directives, just like for other

gazelle/docs/index.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -42,4 +42,5 @@ the `update` command (the default) does anything for Python code.
4242

4343
```{toctree}
4444
:maxdepth: 1
45+
installation_and_usage
4546
```
Lines changed: 151 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,151 @@
1+
# Installation and Usage
2+
3+
## Example
4+
5+
Examples of using Gazelle with Python can be found in the `rules_python`
6+
repo:
7+
8+
* bzlmod: {gh-path}`examples/bzlmod_build_file_generation`
9+
* WORKSPACE: {gh-path}`examples/build_file_generation`
10+
11+
:::{note}
12+
The following documentation covers using bzlmod.
13+
:::
14+
15+
16+
## Adding Gazelle to your project
17+
18+
First, you'll need to add Gazelle to your `MODULE.bazel` file. Get the current
19+
version of [Gazelle][bcr-gazelle] from the [Bazel Central Registry][bcr]. Then
20+
do the same for [`rules_python`][bcr-rules-python] and
21+
[`rules_python_gazelle_plugin`][bcr-rules-python-gazelle-plugin].
22+
23+
[bcr-gazelle]: https://registry.bazel.build/modules/gazelle
24+
[bcr]: https://registry.bazel.build/
25+
[bcr-rules-python]: https://registry.bazel.build/modules/rules_python
26+
[bcr-rules-python-gazelle-plugin]: https://registry.bazel.build/modules/rules_python_gazelle_plugin
27+
28+
Here is a snippet of a `MODULE.bazel` file. Note that most of it is just
29+
general config for `rules_python` itself - the Gazelle plugin is only two lines
30+
at the end.
31+
32+
```starlark
33+
################################################
34+
## START rules_python CONFIG ##
35+
## See the main rules_python docs for details ##
36+
################################################
37+
bazel_dep(name = "rules_python", version = "1.5.1")
38+
39+
python = use_extension("@rules_python//python/extensions:python.bzl", "python")
40+
python.toolchain(python_version = "3.12.2")
41+
use_repo(python, "python_3_12_2")
42+
43+
pip = use_extension("@rules_python//python:extensions.bzl", "pip")
44+
pip.parse(
45+
hub_name = "pip",
46+
requirements_lock = "//:requirements_lock.txt",
47+
requirements_windows = "//:requirements_windows.txt",
48+
)
49+
use_repo(pip, "pip")
50+
51+
##############################################
52+
## START rules_python_gazelle_plugin CONFIG ##
53+
##############################################
54+
55+
# The Gazelle plugin depends on Gazelle.
56+
bazel_dep(name = "gazelle", version = "0.33.0", repo_name = "bazel_gazelle")
57+
58+
# Typically rules_python_gazelle_plugin is version matched to rules_python.
59+
bazel_dep(name = "rules_python_gazelle_plugin", version = "1.5.1")
60+
```
61+
62+
Next, we'll fetch metadata about your Python dependencies, so that gazelle can
63+
determine which package a given import statement comes from. This is provided
64+
by the `modules_mapping` rule. We'll make a target for consuming this
65+
`modules_mapping`, and writing it as a manifest file for Gazelle to read.
66+
This is checked into the repo for speed, as it takes some time to calculate
67+
in a large monorepo.
68+
69+
Gazelle will walk up the filesystem from a Python file to find this metadata,
70+
looking for a file called `gazelle_python.yaml` in an ancestor folder
71+
of the Python code. Create an empty file with this name. It might be next
72+
to your `requirements.txt` file. (You can just use {command}`touch` at
73+
this point, it just needs to exist.)
74+
75+
To keep the metadata updated, put this in your `BUILD.bazel` file next
76+
to `gazelle_python.yaml`:
77+
78+
```starlark
79+
# `@pip` is the hub_name from pip.parse in MODULE.bazel.
80+
load("@pip//:requirements.bzl", "all_whl_requirements")
81+
load("@rules_python_gazelle_plugin//manifest:defs.bzl", "gazelle_python_manifest")
82+
load("@rules_python_gazelle_plugin//modules_mapping:def.bzl", "modules_mapping")
83+
84+
# This rule fetches the metadata for python packages we depend on. That data is
85+
# required for the gazelle_python_manifest rule to update our manifest file.
86+
modules_mapping(
87+
name = "modules_map",
88+
wheels = all_whl_requirements,
89+
)
90+
91+
# Gazelle python extension needs a manifest file mapping from
92+
# an import to the installed package that provides it.
93+
# This macro produces two targets:
94+
# - //:gazelle_python_manifest.update can be used with `bazel run`
95+
# to recalculate the manifest
96+
# - //:gazelle_python_manifest.test is a test target ensuring that
97+
# the manifest doesn't need to be updated
98+
gazelle_python_manifest(
99+
name = "gazelle_python_manifest",
100+
modules_mapping = ":modules_map",
101+
102+
# This is what we called our `pip.parse` rule in MODULE.bazel, where third-party
103+
# python libraries are loaded in BUILD files.
104+
pip_repository_name = "pip",
105+
106+
# This should point to wherever we declare our python dependencies
107+
# (the same as what we passed to the modules_mapping rule in WORKSPACE)
108+
# This argument is optional. If provided, the `.test` target is very
109+
# fast because it just has to check an integrity field. If not provided,
110+
# the integrity field is not added to the manifest which can help avoid
111+
# merge conflicts in large repos.
112+
requirements = "//:requirements_lock.txt",
113+
114+
# include_stub_packages: bool (default: False)
115+
# If set to True, this flag automatically includes any corresponding type stub packages
116+
# for the third-party libraries that are present and used. For example, if you have
117+
# `boto3` as a dependency, and this flag is enabled, the corresponding `boto3-stubs`
118+
# package will be automatically included in the BUILD file.
119+
# Enabling this feature helps ensure that type hints and stubs are readily available
120+
# for tools like type checkers and IDEs, improving the development experience and
121+
# reducing manual overhead in managing separate stub packages.
122+
include_stub_packages = True
123+
)
124+
```
125+
126+
Finally, you create a target that you'll invoke to run the Gazelle tool
127+
with the `rules_python` extension included. This typically goes in your root
128+
`/BUILD.bazel` file:
129+
130+
```starlark
131+
load("@bazel_gazelle//:def.bzl", "gazelle", "gazelle_binary")
132+
133+
gazelle_binary(
134+
name = "gazelle_multilang",
135+
languages = [
136+
# List of language plugins.
137+
# If you want to generate py_proto_library targets PR #3057), then
138+
# the proto language plugin _must_ come before the rules_python plugin.
139+
#"@bazel_gazelle//lanugage/proto",
140+
"@rules_python_gazelle_plugin//python",
141+
],
142+
)
143+
144+
gazelle(
145+
name = "gazelle",
146+
gazelle = ":gazelle_multilang",
147+
)
148+
```
149+
150+
That's it, now you can finally run `bazel run //:gazelle` anytime
151+
you edit Python code, and it should update your `BUILD` files correctly.

0 commit comments

Comments
 (0)