Directives
You can configure the extension using directives, just like for other
languages. These are just comments in the BUILD.bazel file which
govern behavior of the extension when processing files under that
folder.
See the Gazelle docs on directives for some general
directives that may be useful. In particular, the resolve directive
is language-specific and can be used with Python. Examples of these and
the Python-specific directives in use can be found in the
gazelle/testdata folder in the rules_python repo.
The Python-specific directives are:
# gazelle:python_extension valueControls whether the Python extension is enabled or not. Sub-packages inherit this value.
Default:
enabledAllowed Values:
enabled,disabled
# gazelle:python_rootSets 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.
Default: n/a
Allowed Values: None. This direcive does not consume values.
# gazelle:python_manifest_file_name valueOverrides the default manifest file name.
Default:
gazelle_python.yamlAllowed Values: A string
# gazelle:python_ignore_files valueControls the files which are ignored from the generated targets.
Default: n/a
Allowed Values: A comma-separated list of strings.
# gazelle:python_ignore_dependencies valueControls the ignored dependencies from the generated targets.
Default: n/a
Allowed Values: A comma-separated list of strings.
# gazelle:python_validate_import_statements boolControls whether the Python import statements should be validated.
Default:
trueAllowed Values:
true,false
# gazelle:python_generation_mode valueControls the target generation mode.
Default:
packageAllowed Values:
file,package,project
# gazelle:python_generation_mode_per_file_include_init boolControls whether
__init__.pyfiles are included as srcs in each generated target when target generation mode is “file”.Default:
falseAllowed Values:
true,false
# gazelle:python_generation_mode_per_package_require_test_entry_point boolControls whether a file called
__test__.pyor a target called__test__is required to generate one test target per package in package mode.Default:
trueAllowed Values:
true,false
# gazelle:python_library_naming_convention valueControls the
py_librarynaming convention. It interpolates$package_name$with the Bazel package name. E.g. if the Bazel package name isfoo, setting this to$package_name$_my_libwould result in a generated target namedfoo_my_lib.Default:
$package_name$Allowed Values: A string containing
"$package_name$"
# gazelle:python_binary_naming_convention valueControls the
py_binarynaming convention. Follows the same interpolation rules aspython_library_naming_convention.Default:
$package_name$_binAllowed Values: A string containing
"$package_name$"
# gazelle:python_test_naming_convention valueControls the
py_testnaming convention. Follows the same interpolation rules aspython_library_naming_convention.Default:
$package_name$_testAllowed Values: A string containing
"$package_name$"
# gazelle:python_proto_naming_convention valueControls the
py_proto_librarynaming convention. It interpolates$proto_name$with theproto_libraryrule name, minus any trailing_proto. E.g. if theproto_libraryname isfoo_proto, setting this to$proto_name$_my_libwould render tofoo_my_lib.Default:
$proto_name$_py_pb2Allowed Values: A string containing
"$proto_name$"
# gazelle:resolve py import-lang import-string labelInstructs the plugin what target to add as a dependency to satisfy a given import statement. The syntax is
# gazelle:resolve py import-string labelwhereimport-stringis the symbol in the pythonimportstatement, andlabelis the Bazel label that Gazelle should write indeps.Default: n/a
Allowed Values: See the bazel-gazelle docs
# gazelle:python_default_visibility labelsInstructs gazelle to use these visibility labels on all python targets.
labelsis a comma-separated list of labels (without spaces).Default:
//$python_root$:__subpackages__Allowed Values: A string
# gazelle:python_visibility labelAppends additional visibility labels to each generated target. This r directive can be set multiple times.
Default: n/a
Allowed Values: A string
# gazelle:python_test_file_pattern valueFilenames matching these comma-separated globs will be mapped to
py_testtargets.Default:
*_test.py,test_*.pyAllowed Values: A glob string
# gazelle:python_label_convention valueDefines 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 thepiprepository name, e.g.@pip//numpyif yourMODULE.bazelhasuse_repo(pip, "pip")or@pypi//numpyif yourMODULE.bazelhasuse_repo(pip, "pypi").Default:
$distribution_name$Allowed Values: A string
# gazelle:python_label_normalization valueControls 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_pycrossuses PEP-503).Default:
snake_caseAllowed Values:
snake_case,none,pep503
# gazelle:python_experimental_allow_relative_imports boolControls whether Gazelle resolves dependencies for import statements that use paths relative to the current package.
Default:
falseAllowed Values:
true,false
# gazelle:python_generate_pyi_deps boolControls whether to generate a separate
pyi_depsattribute for type-checking dependencies or merge them into the regulardepsattribute. Whenfalse(default), type-checking dependencies are merged intodepsfor backward compatibility. Whentrue, generates separatepyi_deps. Imports in blocks with the formatif typing.TYPE_CHECKING:orif TYPE_CHECKING:and type-only stub packages (eg. boto3-stubs) are recognized as type-checking dependencies.Default:
falseAllowed Values:
true,false
# gazelle:python_generate_pyi_srcs boolControls whether to generate a
pyi_srcsattribute if a sibling.pyifile is found. Whenfalse(default), thepyi_srcsattribute is not added.Default:
falseAllowed Values:
true,false
# gazelle:python_generate_proto boolControls whether to generate a
py_proto_libraryfor eachproto_libraryin the package. By default we load this rule from the@protobufrepository; usegazelle:map_kindif you need to load this from somewhere else.Default:
falseAllowed Values:
true,false
# gazelle:python_resolve_sibling_imports boolAllows absolute imports to be resolved to sibling modules (Python 2’s behavior without
absolute_import).Default:
falseAllowed Values:
true,false
python_extension
Error
Detailed docs are not yet written.
python_root
Set this directive within the Bazel package that you want to use as the Python root.
For example, if using a src dir (as recommended by the Python Packaging User
Guide), then set this directive in src/BUILD.bazel:
# ./src/BUILD.bazel
# Tell gazelle that are python root is the same dir as this Bazel package.
# gazelle:python_root
Note that the directive does not have any arguments.
Gazelle will then add the necessary imports attribute to all targets that it
generates:
# in ./src/foo/BUILD.bazel
py_libary(
...
imports = [".."], # Gazelle adds this
...
)
# in ./src/foo/bar/BUILD.bazel
py_libary(
...
imports = ["../.."], # Gazelle adds this
...
)
python_manifest_file_name
Error
Detailed docs are not yet written.
python_ignore_files
Error
Detailed docs are not yet written.
python_ignore_dependencies
Error
Detailed docs are not yet written.
python_validate_import_statements
Error
Detailed docs are not yet written.
python_generation_mode
Error
Detailed docs are not yet written.
python_generation_mode_per_file_include_init
Error
Detailed docs are not yet written.
python_generation_mode_per_package_require_test_entry_point
When # 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:
there happen to be a file in the
srcswith the same name as thepy_testtarget, ora macro populating the
mainattribute ofpy_testis configured withgazelle:map_kindto replacepy_testwhen Gazelle is generating Python test targets. For example, user can provide such a macro to Gazelle:
load("@rules_python//python:defs.bzl", _py_test="py_test")
load("@aspect_rules_py//py:defs.bzl", "py_pytest_main")
def py_test(name, main=None, **kwargs):
deps = kwargs.pop("deps", [])
if not main:
py_pytest_main(
name = "__test__",
deps = ["@pip_pytest//:pkg"], # change this to the pytest target in your repo.
)
deps.append(":__test__")
main = ":__test__.py"
_py_test(
name = name,
main = main,
deps = deps,
**kwargs,
)
python_library_naming_convention
Error
Detailed docs are not yet written.
python_binary_naming_convention
Error
Detailed docs are not yet written.
python_test_naming_convention
Error
Detailed docs are not yet written.
python_proto_naming_convention
Set this directive to a string pattern to control how the generated
py_proto_library targets are named. When generating new
py_proto_library rules, Gazelle will replace $proto_name$ in the
pattern with the name of the proto_library rule, stripping out a
trailing _proto. For example:
# gazelle:python_generate_proto true
# gazelle:python_proto_naming_convention my_custom_$proto_name$_pattern
proto_library(
name = "foo_proto",
srcs = ["foo.proto"],
)
produces the following py_proto_library rule:
py_proto_library(
name = "my_custom_foo_pattern",
deps = [":foo_proto"],
)
The default naming convention is $proto_name$_pb2_py in accordance with
the Bazel py_proto_library convention, so by default
in the above example Gazelle would generate foo_pb2_py. Any pre-existing
rules are left in place and not renamed.
Note that the Python library will always be imported as foo_pb2 in Python
code, regardless of the naming convention. Also note that Gazelle is currently
not able to map said imports, e.g. import foo_pb2, to fill in
py_proto_library targets as dependencies of other rules. See
#1703 issue.
resolve py
Error
Detailed docs are not yet written.
python_default_visibility
Instructs gazelle to use these visibility labels on all python targets
(typically py_*, but can be modified via the map_kind directive). The arg
to this directive is a comma-separated list (without spaces) of labels.
For example:
# gazelle:python_default_visibility //:__subpackages__,//tests:__subpackages__
produces the following visibility attribute:
py_library(
...,
visibility = [
"//:__subpackages__",
"//tests:__subpackages__",
],
...,
)
You can also inject the python_root value by using the exact string
$python_root$. All instances of this string will be replaced by the python_root
value.
# gazelle:python_default_visibility //$python_root$:__pkg__,//foo/$python_root$/tests:__subpackages__
# Assuming the "# gazelle:python_root" directive is set in ./py/src/BUILD.bazel,
# the results will be:
py_library(
...,
visibility = [
"//foo/py/src/tests:__subpackages__", # sorted alphabetically
"//py/src:__pkg__",
],
...,
)
Two special values are also accepted as an argument to the directive:
NONE: This removes all default visibility. Labels added by thepython_visibilitydirective are still included.DEFAULT: This resets the default visibility.
For example:
# gazelle:python_default_visibility NONE
py_library(
name = "...",
srcs = [...],
)
# gazelle:python_default_visibility //foo:bar
# gazelle:python_default_visibility DEFAULT
py_library(
...,
visibility = ["//:__subpackages__"],
...,
)
These special values can be useful for sub-packages.
python_visibility
Appends additional visibility labels to each generated target.
This directive can be set multiple times. The generated visibility attribute
will include the default visibility and all labels defined by this directive.
All labels will be ordered alphabetically.
# ./BUILD.bazel
# gazelle:python_visibility //tests:__pkg__
# gazelle:python_visibility //bar:baz
py_library(
...
visibility = [
"//:__subpackages__", # default visibility
"//bar:baz",
"//tests:__pkg__",
],
...
)
Child Bazel packages inherit values from parents:
# ./bar/BUILD.bazel
# gazelle:python_visibility //tests:__subpackages__
py_library(
...
visibility = [
"//:__subpackages__", # default visibility
"//bar:baz", # defined in ../BUILD.bazel
"//tests:__pkg__", # defined in ../BUILD.bazel
"//tests:__subpackages__", # defined in this ./BUILD.bazel
],
...
)
This directive also supports the $python_root$ placeholder that
# gazelle:python_default_visibility supports.
# gazlle:python_visibility //$python_root$/foo:bar
py_library(
...
visibility = ["//this_is_my_python_root/foo:bar"],
...
)
python_test_file_pattern
This directive adjusts which python files will be mapped to the py_test rule.
The default is
*_test.py,test_*.py: bothtest_*.pyand*_test.pyfiles will generatepy_testtargets.This directive must have a value. If no value is given, an error will be raised.
It is recommended, though not necessary, to include the
.pyextension in the glob:foo*.py,?at.py.Like most directives, it applies to the current Bazel package and all subpackages until the directive is set again.
This directive accepts multiple glob patterns, separated by commas without spaces:
# gazelle:python_test_file_pattern foo*.py,?at
py_library(
name = "mylib",
srcs = ["mylib.py"],
)
py_test(
name = "foo_bar",
srcs = ["foo_bar.py"],
)
py_test(
name = "cat",
srcs = ["cat.py"],
)
py_test(
name = "hat",
srcs = ["hat.py"],
)
Notes
Resetting to the default value (such as in a subpackage) is manual. Set:
# gazelle:python_test_file_pattern *_test.py,test_*.py
There currently is no way to tell gazelle that no files in a package should
be mapped to py_test targets (see #1826 issue). The workaround
is to set this directive to a pattern that will never match a .py file, such
as foo.bar:
# No files in this package should be mapped to py_test targets.
# gazelle:python_test_file_pattern foo.bar
py_library(
name = "my_test",
srcs = ["my_test.py"],
)
python_label_convention
Error
Detailed docs are not yet written.
python_label_normalization
Error
Detailed docs are not yet written.
python_experimental_allow_relative_imports
Enables experimental support for resolving relative imports in
python_generation_mode package.
By default, when # gazelle:python_generation_mode package is enabled,
relative imports (e.g., from .library import foo) are not added to the
deps field of the generated target. This results in incomplete py_library
rules that lack required dependencies on sibling packages.
Example:
Given this Python file import:
from .library import add as _add
from .library import subtract as _subtract
Expected BUILD file output:
py_library(
name = "py_default_library",
srcs = ["__init__.py"],
deps = [
"//example/library:py_default_library",
],
visibility = ["//visibility:public"],
)
Actual output without this annotation:
py_library(
name = "py_default_library",
srcs = ["__init__.py"],
visibility = ["//visibility:public"],
)
If the directive is set to true, gazelle will resolve imports
that are relative to the current package.
python_generate_pyi_deps
Error
Detailed docs are not yet written.
python_generate_pyi_deps
When true, include any sibling .pyi files in the pyi_srcs target attribute.
For example, assume you have the following files:
foo.py
foo.pyi
The generated target will be:
py_library(
name = "foo",
srcs = ["foo.py"],
pyi_srcs = ["foo.pyi"],
)
python_generate_proto
When # gazelle:python_generate_proto true, Gazelle will generate one
py_proto_library for each proto_library, generating Python clients for
protobuf in each package. By default this is turned off. Gazelle will also
generate a load statement for the py_proto_library - attempting to detect
the configured name for the @protobuf / @com_google_protobuf repo in your
MODULE.bazel, and otherwise falling back to @com_google_protobuf for
compatibility with WORKSPACE.
Note
In order to use this, you must manually configure Gazelle to target multiple
languages. Place this in your root BUILD.bazel file:
load("@bazel_gazelle//:def.bzl", "gazelle", "gazelle_binary")
gazelle_binary(
name = "gazelle_multilang",
languages = [
"@bazel_gazelle//language/proto",
# The python gazelle plugin must be listed _after_ the proto language.
"@rules_python_gazelle_plugin//python",
],
)
gazelle(
name = "gazelle",
gazelle = "//:gazelle_multilang",
)
For example, in a package with # gazelle:python_generate_proto true and a
foo.proto, if you have both the proto extension and the Python extension
loaded into Gazelle, you’ll get something like:
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"],
)
When false, Gazelle will ignore any py_proto_library, including
previously-generated or hand-created rules.
python_resolve_sibling_imports
Error
Detailed docs are not yet written.