Skip to content

Commit da10ac4

Browse files
authored
feat(gazelle): Add "python_visibility" directive that appends additional visibility labels (bazel-contrib#1784)
Fixes bazel-contrib#1783. Add a new gazelle directive, `python_visibility`, that allows users to add labels to the `visibility` attribute of generated targets. out by the way, hence this PR), I noticed that the docs were a little This directive acts similar to[^1] the [`go_visibility` directive](https://github.com/bazelbuild/bazel-gazelle#directives). The primary use case is for python projects that separate unit test files from the python packages/modules that they test, like so: ``` packaging_tutorial/ ├── LICENSE ├── pyproject.toml ├── README.md ├── src/ │ └── mypackage/ │ ├── __init__.py │ └── foo.py └── tests/ ├── __init__.py └── test_foo.py ``` A future PR will add an example to the `./examples` directory (issue bazel-contrib#1775). [^1]: At least, similar based on docs. I haven't done any actual comparison.
1 parent 3f40e98 commit da10ac4

File tree

15 files changed

+141
-4
lines changed

15 files changed

+141
-4
lines changed

gazelle/README.md

Lines changed: 46 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -198,6 +198,8 @@ Python-specific directives are as follows:
198198
| Controls the `py_test` naming convention. Follows the same interpolation rules as `python_library_naming_convention`. | |
199199
| `# gazelle:resolve py ...` | n/a |
200200
| 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`. | |
201+
| [`# gazelle:python_visibility label`](#directive-python_visibility) | |
202+
| Appends additional visibility labels to each generated target. This directive can be set multiple times. | |
201203

202204

203205
#### Directive: `python_root`:
@@ -236,6 +238,50 @@ py_libary(
236238
[python-packaging-user-guide]: https://github.com/pypa/packaging.python.org/blob/4c86169a/source/tutorials/packaging-projects.rst
237239

238240

241+
#### Directive: `python_visibility`:
242+
243+
Appends additional `visibility` labels to each generated target.
244+
245+
This directive can be set multiple times. The generated `visibility` attribute
246+
will include the default visibility and all labels defined by this directive.
247+
All labels will be ordered alphabetically.
248+
249+
```starlark
250+
# ./BUILD.bazel
251+
# gazelle:python_visibility //tests:__pkg__
252+
# gazelle:python_visibility //bar:baz
253+
254+
py_library(
255+
...
256+
visibility = [
257+
"//:__subpackages__", # default visibility
258+
"//bar:baz",
259+
"//tests:__pkg__",
260+
],
261+
...
262+
)
263+
```
264+
265+
Child Bazel packages inherit values from parents:
266+
267+
```starlark
268+
# ./bar/BUILD.bazel
269+
# gazelle:python_visibility //tests:__subpackages__
270+
271+
py_library(
272+
...
273+
visibility = [
274+
"//:__subpackages__", # default visibility
275+
"//bar:baz", # defined in ../BUILD.bazel
276+
"//tests:__pkg__", # defined in ../BUILD.bazel
277+
"//tests:__subpackages__", # defined in this ./BUILD.bazel
278+
],
279+
...
280+
)
281+
282+
```
283+
284+
239285
### Libraries
240286

241287
Python source files are those ending in `.py` but not ending in `_test.py`.

gazelle/python/configure.go

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -63,6 +63,7 @@ func (py *Configurer) KnownDirectives() []string {
6363
pythonconfig.LibraryNamingConvention,
6464
pythonconfig.BinaryNamingConvention,
6565
pythonconfig.TestNamingConvention,
66+
pythonconfig.Visibility,
6667
}
6768
}
6869

@@ -162,6 +163,8 @@ func (py *Configurer) Configure(c *config.Config, rel string, f *rule.File) {
162163
config.SetBinaryNamingConvention(strings.TrimSpace(d.Value))
163164
case pythonconfig.TestNamingConvention:
164165
config.SetTestNamingConvention(strings.TrimSpace(d.Value))
166+
case pythonconfig.Visibility:
167+
config.AppendVisibility(strings.TrimSpace(d.Value))
165168
}
166169
}
167170

gazelle/python/generate.go

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -212,7 +212,8 @@ func (py *Python) GenerateRules(args language.GenerateArgs) language.GenerateRes
212212
}
213213

214214
parser := newPython3Parser(args.Config.RepoRoot, args.Rel, cfg.IgnoresDependency)
215-
visibility := fmt.Sprintf("//%s:__subpackages__", pythonProjectRoot)
215+
visibility := []string{fmt.Sprintf("//%s:__subpackages__", pythonProjectRoot)}
216+
visibility = append(visibility, cfg.Visibility()...)
216217

217218
var result language.GenerateResult
218219
result.Gen = make([]*rule.Rule, 0)

gazelle/python/target.go

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -99,9 +99,11 @@ func (t *targetBuilder) addResolvedDependency(dep string) *targetBuilder {
9999
return t
100100
}
101101

102-
// addVisibility adds a visibility to the target.
103-
func (t *targetBuilder) addVisibility(visibility string) *targetBuilder {
104-
t.visibility.Add(visibility)
102+
// addVisibility adds visibility labels to the target.
103+
func (t *targetBuilder) addVisibility(visibility []string) *targetBuilder {
104+
for _, item := range visibility {
105+
t.visibility.Add(item)
106+
}
105107
return t
106108
}
107109

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
# Directives can be added in any order. They will be ordered alphabetically
2+
# when added.
3+
# gazelle:python_visibility //tests:__pkg__
4+
# gazelle:python_visibility //bar:baz
Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
load("@rules_python//python:defs.bzl", "py_library")
2+
3+
# Directives can be added in any order. They will be ordered alphabetically
4+
# when added.
5+
# gazelle:python_visibility //tests:__pkg__
6+
# gazelle:python_visibility //bar:baz
7+
8+
py_library(
9+
name = "directive_python_visibility",
10+
srcs = ["foo.py"],
11+
visibility = [
12+
"//:__subpackages__",
13+
"//bar:baz",
14+
"//tests:__pkg__",
15+
],
16+
)
Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
# Directive: `python_visibility`
2+
3+
This test case asserts that the `# gazelle:python_visibility` directive correctly
4+
appends multiple labels to the target's `visibility` parameter.
Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
# This is a Bazel workspace for the Gazelle test data.
Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
def func():
2+
print("library_func")
Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
# python_visibilty directive applies to all child bazel packages.
2+
# Thus, the generated file for this package will also have vis for
3+
# //tests:__pkg__ and //bar:baz in addition to the default.
4+
# gazelle:python_visibility //tests:__subpackages__

0 commit comments

Comments
 (0)