@@ -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
15011You can configure the extension using directives, just like for other
@@ -529,191 +390,6 @@ py_proto_library(
529390
530391When ` false ` , Gazelle will ignore any ` py_proto_library ` , including previously-generated or hand-created rules.
531392
532- ### Annotations
533-
534- * Annotations* refer to comments found _ within Python files_ that configure how
535- Gazelle acts for that particular file.
536-
537- Annotations have the form:
538-
539- ``` python
540- # gazelle:annotation_name value
541- ```
542-
543- and can reside anywhere within a Python file where comments are valid. For example:
544-
545- ``` python
546- import foo
547- # gazelle:annotation_name value
548-
549- def bar (): # gazelle:annotation_name value
550- pass
551- ```
552-
553- The annotations are:
554-
555- | ** Annotation** | ** Default value** |
556- | ---------------------------------------------------------------| -------------------|
557- | [ ` # gazelle:ignore imports ` ] ( #annotation-ignore ) | N/A |
558- | Tells Gazelle to ignore import statements. ` imports ` is a comma-separated list of imports to ignore. | |
559- | [ ` # gazelle:include_dep targets ` ] ( #annotation-include_dep ) | N/A |
560- | 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. | |
561- | [ ` # gazelle:include_pytest_conftest bool ` ] ( #annotation-include_pytest_conftest ) | N/A |
562- | Whether or not to include a sibling ` :conftest ` target in the deps of a ` py_test ` target. Default behaviour is to include ` :conftest ` . | |
563-
564-
565- #### Annotation: ` ignore `
566-
567- This annotation accepts a comma-separated string of values. Values are names of Python
568- imports that Gazelle should _ not_ include in target dependencies.
569-
570- The annotation can be added multiple times, and all values are combined and
571- de-duplicated.
572-
573- For ` python_generation_mode = "package" ` , the ` ignore ` annotations
574- found across all files included in the generated target are removed from ` deps ` .
575-
576- Example:
577-
578- ``` python
579- import numpy # a pypi package
580-
581- # gazelle:ignore bar.baz.hello,foo
582- import bar.baz.hello
583- import foo
584-
585- # Ignore this import because _reasons_
586- import baz # gazelle:ignore baz
587- ```
588-
589- will cause Gazelle to generate:
590-
591- ``` starlark
592- deps = [" @pypi//numpy" ],
593- ```
594-
595-
596- #### Annotation: ` include_dep `
597-
598- This annotation accepts a comma-separated string of values. Values _ must_
599- be Python targets, but _ no validation is done_ . If a value is not a Python
600- target, building will result in an error saying:
601-
602- ```
603- <target> does not have mandatory providers: 'PyInfo' or 'CcInfo' or 'PyInfo'.
604- ```
605-
606- Adding non-Python targets to the generated target is a feature request being
607- tracked in [ Issue #1865 ] ( https://github.com/bazel-contrib/rules_python/issues/1865 ) .
608-
609- The annotation can be added multiple times, and all values are combined
610- and de-duplicated.
611-
612- For ` python_generation_mode = "package" ` , the ` include_dep ` annotations
613- found across all files included in the generated target are included in ` deps ` .
614-
615- Example:
616-
617- ``` python
618- # gazelle:include_dep //foo:bar,:hello_world,//:abc
619- # gazelle:include_dep //:def,//foo:bar
620- import numpy # a pypi package
621- ```
622-
623- will cause Gazelle to generate:
624-
625- ``` starlark
626- deps = [
627- " :hello_world" ,
628- " //:abc" ,
629- " //:def" ,
630- " //foo:bar" ,
631- " @pypi//numpy" ,
632- ]
633- ```
634-
635- #### Annotation: ` include_pytest_conftest `
636-
637- Added in [ #3080 ] [ gh3080 ] .
638-
639- [ gh3080 ] : https://github.com/bazel-contrib/rules_python/pull/3080
640-
641- This annotation accepts any string that can be parsed by go's
642- [ ` strconv.ParseBool ` ] [ ParseBool ] . If an unparsable string is passed, the
643- annotation is ignored.
644-
645- [ ParseBool ] : https://pkg.go.dev/strconv#ParseBool
646-
647- Starting with [ ` rules_python ` 0.14.0] [ rules-python-0.14.0 ] (specifically [ PR #879 ] [ gh879 ] ),
648- Gazelle will include a ` :conftest ` dependency to an ` py_test ` target that is in
649- the same directory as ` conftest.py ` .
650-
651- [ rules-python-0.14.0 ] : https://github.com/bazel-contrib/rules_python/releases/tag/0.14.0
652- [ gh879 ] : https://github.com/bazel-contrib/rules_python/pull/879
653-
654- This annotation allows users to adjust that behavior. To disable the behavior, set
655- the annotation value to "false":
656-
657- ```
658- # some_file_test.py
659- # gazelle:include_pytest_conftest false
660- ```
661-
662- Example:
663-
664- Given a directory tree like:
665-
666- ```
667- .
668- ├── BUILD.bazel
669- ├── conftest.py
670- └── some_file_test.py
671- ```
672-
673- The default Gazelle behavior would create:
674-
675- ``` starlark
676- py_library(
677- name = " conftest" ,
678- testonly = True ,
679- srcs = [" conftest.py" ],
680- visibility = [" //:__subpackages__" ],
681- )
682-
683- py_test(
684- name = " some_file_test" ,
685- srcs = [" some_file_test.py" ],
686- deps = [" :conftest" ],
687- )
688- ```
689-
690- When ` # gazelle:include_pytest_conftest false ` is found in ` some_file_test.py `
691-
692- ``` python
693- # some_file_test.py
694- # gazelle:include_pytest_conftest false
695- ```
696-
697- Gazelle will generate:
698-
699- ``` starlark
700- py_library(
701- name = " conftest" ,
702- testonly = True ,
703- srcs = [" conftest.py" ],
704- visibility = [" //:__subpackages__" ],
705- )
706-
707- py_test(
708- name = " some_file_test" ,
709- srcs = [" some_file_test.py" ],
710- )
711- ```
712-
713- See [ Issue #3076 ] [ gh3076 ] for more information.
714-
715- [ gh3076 ] : https://github.com/bazel-contrib/rules_python/issues/3076
716-
717393
718394#### Directive: ` python_experimental_allow_relative_imports `
719395Enables experimental support for resolving relative imports in
0 commit comments