feat!: Following generation mode when generating test targets (#2044)
When `python_generation_mode` is `project` or `file` , the generated
`py_test` targets are consistent with `py_library`. However, when
`python_generation_mode` is `package`, it becomes inconsistent: it
requires either `__test__` target or `__test__.py` file to generate
`py_test` in package mode, otherwise it will fall back to file mode.
This PR relaxes this requirement with a new directive
`gazelle:python_generation_mode_per_package_require_test_entry_point`.
Whent it's set to false, Gazelle and generates one `py_test` target per
package in package mode even without entry points.
This allows people to use `gazelle:map_kind` to map `py_test` to a macro
that sets a default test runner, such as
[rules_python_pytest](https://github.com/caseyduquettesc/rules_python_pytest)
or [pytest-bazel](https://pypi.org/project/pytest-bazel/), and generate
one test target per package. The behavior when
`gazelle:python_generation_mode` is "file" or "project" remains the
same.
This fixes #1972 for supporting pytest from Gazelle. With this approach,
people can define a thin macro like this to use py_pytest_main:
```
load("@aspect_rules_py//py:defs.bzl", "py_pytest_main")
def py_test(name, **kwargs):
py_pytest_main(
name = "__test__",
deps = ["@pip_pytest//:pkg"], # change this to the pytest target in your repo.
)
deps = kwargs.pop("deps", [])
deps.append(":__test__")
py_test(
name = name,
main = ":__test__.py",
deps = deps,
**kwargs,
)
```
BREAKING CHANGES:
Without `gazelle:map_kind` or `__test__` target or `__test__.py`, the
package mode will now generate `py_test` without `main` attribute, which
may not be runnable. However, this is already an issue with
"python_generation_mode:project" before this PR.
The default value of
`gazelle:python_generation_mode_per_package_require_test_entry_point` is
true to preserve the current behavior. We will flip that default value
in the future.
---------
Co-authored-by: aignas <240938+aignas@users.noreply.github.com>diff --git a/CHANGELOG.md b/CHANGELOG.md
index d924f65..560c04e 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -39,7 +39,16 @@
containing ">" sign
### Added
-* Nothing yet
+* (gazelle) Added `python_generation_mode_per_package_require_test_entry_point`
+ in order to better accommodate users who use a custom macro,
+ [`pytest-bazel`][pytest_bazel], [rules_python_pytest] or `rules_py`
+ [py_test_main] in order to integrate with `pytest`. Currently the default
+ flag value is set to `true` for backwards compatible behaviour, but in the
+ future the flag will be flipped be `false` by default.
+
+[rules_python_pytest]: https://github.com/caseyduquettesc/rules_python_pytest
+[py_test_main]: https://docs.aspect.build/rulesets/aspect_rules_py/docs/rules/#py_pytest_main
+[pytest_bazel]: https://pypi.org/project/pytest-bazel
### Removed
* Nothing yet
diff --git a/gazelle/README.md b/gazelle/README.md
index d68b94d..c0494d1 100644
--- a/gazelle/README.md
+++ b/gazelle/README.md
@@ -172,42 +172,44 @@
Python-specific directives are as follows:
-| **Directive** | **Default value** |
-|--------------------------------------|-------------------|
-| `# gazelle:python_extension` | `enabled` |
-| Controls whether the Python extension is enabled or not. Sub-packages inherit this value. Can be either "enabled" or "disabled". | |
-| [`# gazelle:python_root`](#directive-python_root) | n/a |
-| 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. | |
-| `# gazelle:python_manifest_file_name`| `gazelle_python.yaml` |
-| Overrides the default manifest file name. | |
-| `# gazelle:python_ignore_files` | n/a |
-| Controls the files which are ignored from the generated targets. | |
-| `# gazelle:python_ignore_dependencies`| n/a |
-| Controls the ignored dependencies from the generated targets. | |
-| `# gazelle:python_validate_import_statements`| `true` |
-| Controls whether the Python import statements should be validated. Can be "true" or "false" | |
-| `# gazelle:python_generation_mode`| `package` |
-| Controls the target generation mode. Can be "file", "package", or "project" | |
-| `# gazelle:python_generation_mode_per_file_include_init`| `false` |
-| Controls whether `__init__.py` files are included as srcs in each generated target when target generation mode is "file". Can be "true", or "false" | |
-| `# gazelle:python_library_naming_convention`| `$package_name$` |
-| 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`. | |
-| `# gazelle:python_binary_naming_convention` | `$package_name$_bin` |
-| Controls the `py_binary` naming convention. Follows the same interpolation rules as `python_library_naming_convention`. | |
-| `# gazelle:python_test_naming_convention` | `$package_name$_test` |
-| Controls the `py_test` naming convention. Follows the same interpolation rules as `python_library_naming_convention`. | |
-| `# gazelle:resolve py ...` | n/a |
+| **Directive** | **Default value** |
+|-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|-------------------|
+| `# gazelle:python_extension` | `enabled` |
+| Controls whether the Python extension is enabled or not. Sub-packages inherit this value. Can be either "enabled" or "disabled". | |
+| [`# gazelle:python_root`](#directive-python_root) | n/a |
+| 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. | |
+| `# gazelle:python_manifest_file_name` | `gazelle_python.yaml` |
+| Overrides the default manifest file name. | |
+| `# gazelle:python_ignore_files` | n/a |
+| Controls the files which are ignored from the generated targets. | |
+| `# gazelle:python_ignore_dependencies` | n/a |
+| Controls the ignored dependencies from the generated targets. | |
+| `# gazelle:python_validate_import_statements` | `true` |
+| Controls whether the Python import statements should be validated. Can be "true" or "false" | |
+| `# gazelle:python_generation_mode` | `package` |
+| Controls the target generation mode. Can be "file", "package", or "project" | |
+| `# gazelle:python_generation_mode_per_file_include_init` | `false` |
+| Controls whether `__init__.py` files are included as srcs in each generated target when target generation mode is "file". Can be "true", or "false" | |
+| [`# gazelle:python_generation_mode_per_package_require_test_entry_point`](#directive-python_generation_mode_per_package_require_test_entry_point) | `true` |
+| Controls whether a file called `__test__.py` or a target called `__test__` is required to generate one test target per package in package mode. ||
+| `# gazelle:python_library_naming_convention` | `$package_name$` |
+| 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`. | |
+| `# gazelle:python_binary_naming_convention` | `$package_name$_bin` |
+| Controls the `py_binary` naming convention. Follows the same interpolation rules as `python_library_naming_convention`. | |
+| `# gazelle:python_test_naming_convention` | `$package_name$_test` |
+| Controls the `py_test` naming convention. Follows the same interpolation rules as `python_library_naming_convention`. | |
+| `# gazelle:resolve py ...` | n/a |
| 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`. | |
-| [`# gazelle:python_default_visibility labels`](#directive-python_default_visibility) | |
-| Instructs gazelle to use these visibility labels on all python targets. `labels` is a comma-separated list of labels (without spaces). | `//$python_root$:__subpackages__` |
-| [`# gazelle:python_visibility label`](#directive-python_visibility) | |
-| Appends additional visibility labels to each generated target. This directive can be set multiple times. | |
-| [`# gazelle:python_test_file_pattern`](#directive-python_test_file_pattern) | `*_test.py,test_*.py` |
-| Filenames matching these comma-separated `glob`s will be mapped to `py_test` targets. |
-| `# gazelle:python_label_convention` | `$distribution_name$` |
-| 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`. |
-| `# gazelle:python_label_normalization` | `snake_case` |
-| 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". |
+| [`# gazelle:python_default_visibility labels`](#directive-python_default_visibility) | |
+| Instructs gazelle to use these visibility labels on all python targets. `labels` is a comma-separated list of labels (without spaces). | `//$python_root$:__subpackages__` |
+| [`# gazelle:python_visibility label`](#directive-python_visibility) | |
+| Appends additional visibility labels to each generated target. This directive can be set multiple times. | |
+| [`# gazelle:python_test_file_pattern`](#directive-python_test_file_pattern) | `*_test.py,test_*.py` |
+| Filenames matching these comma-separated `glob`s will be mapped to `py_test` targets. |
+| `# gazelle:python_label_convention` | `$distribution_name$` |
+| 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`. |
+| `# gazelle:python_label_normalization` | `snake_case` |
+| 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". |
#### Directive: `python_root`:
@@ -440,6 +442,33 @@
[issue-1826]: https://github.com/bazelbuild/rules_python/issues/1826
+#### Directive: `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:
+1. there happen to be a file in the `srcs` with the same name as the `py_test` target, or
+2. 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:
+
+```starlark
+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,
+)
+```
### Annotations
diff --git a/gazelle/python/configure.go b/gazelle/python/configure.go
index b82dd81..a369a64 100644
--- a/gazelle/python/configure.go
+++ b/gazelle/python/configure.go
@@ -61,6 +61,7 @@
pythonconfig.ValidateImportStatementsDirective,
pythonconfig.GenerationMode,
pythonconfig.GenerationModePerFileIncludeInit,
+ pythonconfig.GenerationModePerPackageRequireTestEntryPoint,
pythonconfig.LibraryNamingConvention,
pythonconfig.BinaryNamingConvention,
pythonconfig.TestNamingConvention,
@@ -163,6 +164,14 @@
log.Fatal(err)
}
config.SetPerFileGenerationIncludeInit(v)
+ case pythonconfig.GenerationModePerPackageRequireTestEntryPoint:
+ v, err := strconv.ParseBool(strings.TrimSpace(d.Value))
+ if err != nil {
+ log.Printf("invalid value for gazelle:%s in %q: %q",
+ pythonconfig.GenerationModePerPackageRequireTestEntryPoint, rel, d.Value)
+ } else {
+ config.SetPerPackageGenerationRequireTestEntryPoint(v)
+ }
case pythonconfig.LibraryNamingConvention:
config.SetLibraryNamingConvention(strings.TrimSpace(d.Value))
case pythonconfig.BinaryNamingConvention:
diff --git a/gazelle/python/generate.go b/gazelle/python/generate.go
index ef49dd7..c563b47 100644
--- a/gazelle/python/generate.go
+++ b/gazelle/python/generate.go
@@ -421,7 +421,7 @@
addResolvedDependencies(annotations.includeDeps).
generateImportsAttribute()
}
- if (hasPyTestEntryPointFile || hasPyTestEntryPointTarget || cfg.CoarseGrainedGeneration()) && !cfg.PerFileGeneration() {
+ if (!cfg.PerPackageGenerationRequireTestEntryPoint() || hasPyTestEntryPointFile || hasPyTestEntryPointTarget || cfg.CoarseGrainedGeneration()) && !cfg.PerFileGeneration() {
// Create one py_test target per package
if hasPyTestEntryPointFile {
// Only add the pyTestEntrypointFilename to the pyTestFilenames if
@@ -441,7 +441,10 @@
setMain(main)
} else if hasPyTestEntryPointFile {
pyTestTarget.setMain(pyTestEntrypointFilename)
- }
+ } /* else:
+ main is not set, assuming there is a test file with the same name
+ as the target name, or there is a macro wrapping py_test and setting its main attribute.
+ */
pyTestTargets = append(pyTestTargets, pyTestTarget)
}
} else {
diff --git a/gazelle/python/testdata/per_package_test_target_without_entry_point/BUILD.in b/gazelle/python/testdata/per_package_test_target_without_entry_point/BUILD.in
new file mode 100644
index 0000000..27120f3
--- /dev/null
+++ b/gazelle/python/testdata/per_package_test_target_without_entry_point/BUILD.in
@@ -0,0 +1,2 @@
+# gazelle:python_generation_mode package
+# gazelle:python_generation_mode_per_package_require_test_entry_point false
\ No newline at end of file
diff --git a/gazelle/python/testdata/per_package_test_target_without_entry_point/BUILD.out b/gazelle/python/testdata/per_package_test_target_without_entry_point/BUILD.out
new file mode 100644
index 0000000..c4ec331
--- /dev/null
+++ b/gazelle/python/testdata/per_package_test_target_without_entry_point/BUILD.out
@@ -0,0 +1,18 @@
+load("@rules_python//python:defs.bzl", "py_library", "py_test")
+
+# gazelle:python_generation_mode package
+# gazelle:python_generation_mode_per_package_require_test_entry_point false
+
+py_library(
+ name = "per_package_test_target_without_entry_point",
+ srcs = ["__init__.py"],
+ visibility = ["//:__subpackages__"],
+)
+
+py_test(
+ name = "per_package_test_target_without_entry_point_test",
+ srcs = [
+ "bar_test.py",
+ "foo_test.py",
+ ],
+)
diff --git a/gazelle/python/testdata/per_package_test_target_without_entry_point/README.md b/gazelle/python/testdata/per_package_test_target_without_entry_point/README.md
new file mode 100644
index 0000000..8decb00
--- /dev/null
+++ b/gazelle/python/testdata/per_package_test_target_without_entry_point/README.md
@@ -0,0 +1,3 @@
+# One test target per package without entry point
+
+This test case asserts that one test target is generated per package without entry point when `gazelle:python_generation_mode_per_package_require_test_entry_point false`
diff --git a/gazelle/python/testdata/per_package_test_target_without_entry_point/WORKSPACE b/gazelle/python/testdata/per_package_test_target_without_entry_point/WORKSPACE
new file mode 100644
index 0000000..faff6af
--- /dev/null
+++ b/gazelle/python/testdata/per_package_test_target_without_entry_point/WORKSPACE
@@ -0,0 +1 @@
+# This is a Bazel workspace for the Gazelle test data.
diff --git a/gazelle/python/testdata/per_package_test_target_without_entry_point/__init__.py b/gazelle/python/testdata/per_package_test_target_without_entry_point/__init__.py
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/gazelle/python/testdata/per_package_test_target_without_entry_point/__init__.py
diff --git a/gazelle/python/testdata/per_package_test_target_without_entry_point/bar_test.py b/gazelle/python/testdata/per_package_test_target_without_entry_point/bar_test.py
new file mode 100644
index 0000000..9948f1c
--- /dev/null
+++ b/gazelle/python/testdata/per_package_test_target_without_entry_point/bar_test.py
@@ -0,0 +1,24 @@
+# Copyright 2023 The Bazel Authors. All rights reserved.
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+
+import unittest
+
+
+class BarTest(unittest.TestCase):
+ def test_foo(self):
+ pass
+
+
+if __name__ == "__main__":
+ unittest.main()
diff --git a/gazelle/python/testdata/per_package_test_target_without_entry_point/foo_test.py b/gazelle/python/testdata/per_package_test_target_without_entry_point/foo_test.py
new file mode 100644
index 0000000..a128adf
--- /dev/null
+++ b/gazelle/python/testdata/per_package_test_target_without_entry_point/foo_test.py
@@ -0,0 +1,24 @@
+# Copyright 2023 The Bazel Authors. All rights reserved.
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+
+import unittest
+
+
+class FooTest(unittest.TestCase):
+ def test_foo(self):
+ pass
+
+
+if __name__ == "__main__":
+ unittest.main()
diff --git a/gazelle/python/testdata/per_package_test_target_without_entry_point/test.yaml b/gazelle/python/testdata/per_package_test_target_without_entry_point/test.yaml
new file mode 100644
index 0000000..2410223
--- /dev/null
+++ b/gazelle/python/testdata/per_package_test_target_without_entry_point/test.yaml
@@ -0,0 +1,17 @@
+# Copyright 2023 The Bazel Authors. All rights reserved.
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+
+---
+expect:
+ exit_code: 0
diff --git a/gazelle/pythonconfig/pythonconfig.go b/gazelle/pythonconfig/pythonconfig.go
index 41a470a..a24a90e 100644
--- a/gazelle/pythonconfig/pythonconfig.go
+++ b/gazelle/pythonconfig/pythonconfig.go
@@ -55,6 +55,10 @@
// the "per_file" GenerationMode by including the package's __init__.py file.
// This is a boolean directive.
GenerationModePerFileIncludeInit = "python_generation_mode_per_file_include_init"
+ // GenerationModePerPackageRequireTestEntryPoint represents the directive that
+ // requires a test entry point to generate test targets in "package" GenerationMode.
+ // This is a boolean directive.
+ GenerationModePerPackageRequireTestEntryPoint = "python_generation_mode_per_package_require_test_entry_point"
// LibraryNamingConvention represents the directive that 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
@@ -148,21 +152,22 @@
pythonProjectRoot string
gazelleManifest *manifest.Manifest
- excludedPatterns *singlylinkedlist.List
- ignoreFiles map[string]struct{}
- ignoreDependencies map[string]struct{}
- validateImportStatements bool
- coarseGrainedGeneration bool
- perFileGeneration bool
- perFileGenerationIncludeInit bool
- libraryNamingConvention string
- binaryNamingConvention string
- testNamingConvention string
- defaultVisibility []string
- visibility []string
- testFilePattern []string
- labelConvention string
- labelNormalization LabelNormalizationType
+ excludedPatterns *singlylinkedlist.List
+ ignoreFiles map[string]struct{}
+ ignoreDependencies map[string]struct{}
+ validateImportStatements bool
+ coarseGrainedGeneration bool
+ perFileGeneration bool
+ perFileGenerationIncludeInit bool
+ perPackageGenerationRequireTestEntryPoint bool
+ libraryNamingConvention string
+ binaryNamingConvention string
+ testNamingConvention string
+ defaultVisibility []string
+ visibility []string
+ testFilePattern []string
+ labelConvention string
+ labelNormalization LabelNormalizationType
}
type LabelNormalizationType int
@@ -179,24 +184,25 @@
pythonProjectRoot string,
) *Config {
return &Config{
- extensionEnabled: true,
- repoRoot: repoRoot,
- pythonProjectRoot: pythonProjectRoot,
- excludedPatterns: singlylinkedlist.New(),
- ignoreFiles: make(map[string]struct{}),
- ignoreDependencies: make(map[string]struct{}),
- validateImportStatements: true,
- coarseGrainedGeneration: false,
- perFileGeneration: false,
- perFileGenerationIncludeInit: false,
- libraryNamingConvention: packageNameNamingConventionSubstitution,
- binaryNamingConvention: fmt.Sprintf("%s_bin", packageNameNamingConventionSubstitution),
- testNamingConvention: fmt.Sprintf("%s_test", packageNameNamingConventionSubstitution),
- defaultVisibility: []string{fmt.Sprintf(DefaultVisibilityFmtString, "")},
- visibility: []string{},
- testFilePattern: strings.Split(DefaultTestFilePatternString, ","),
- labelConvention: DefaultLabelConvention,
- labelNormalization: DefaultLabelNormalizationType,
+ extensionEnabled: true,
+ repoRoot: repoRoot,
+ pythonProjectRoot: pythonProjectRoot,
+ excludedPatterns: singlylinkedlist.New(),
+ ignoreFiles: make(map[string]struct{}),
+ ignoreDependencies: make(map[string]struct{}),
+ validateImportStatements: true,
+ coarseGrainedGeneration: false,
+ perFileGeneration: false,
+ perFileGenerationIncludeInit: false,
+ perPackageGenerationRequireTestEntryPoint: true,
+ libraryNamingConvention: packageNameNamingConventionSubstitution,
+ binaryNamingConvention: fmt.Sprintf("%s_bin", packageNameNamingConventionSubstitution),
+ testNamingConvention: fmt.Sprintf("%s_test", packageNameNamingConventionSubstitution),
+ defaultVisibility: []string{fmt.Sprintf(DefaultVisibilityFmtString, "")},
+ visibility: []string{},
+ testFilePattern: strings.Split(DefaultTestFilePatternString, ","),
+ labelConvention: DefaultLabelConvention,
+ labelNormalization: DefaultLabelNormalizationType,
}
}
@@ -220,14 +226,15 @@
coarseGrainedGeneration: c.coarseGrainedGeneration,
perFileGeneration: c.perFileGeneration,
perFileGenerationIncludeInit: c.perFileGenerationIncludeInit,
- libraryNamingConvention: c.libraryNamingConvention,
- binaryNamingConvention: c.binaryNamingConvention,
- testNamingConvention: c.testNamingConvention,
- defaultVisibility: c.defaultVisibility,
- visibility: c.visibility,
- testFilePattern: c.testFilePattern,
- labelConvention: c.labelConvention,
- labelNormalization: c.labelNormalization,
+ perPackageGenerationRequireTestEntryPoint: c.perPackageGenerationRequireTestEntryPoint,
+ libraryNamingConvention: c.libraryNamingConvention,
+ binaryNamingConvention: c.binaryNamingConvention,
+ testNamingConvention: c.testNamingConvention,
+ defaultVisibility: c.defaultVisibility,
+ visibility: c.visibility,
+ testFilePattern: c.testFilePattern,
+ labelConvention: c.labelConvention,
+ labelNormalization: c.labelNormalization,
}
}
@@ -398,6 +405,14 @@
return c.perFileGenerationIncludeInit
}
+func (c *Config) SetPerPackageGenerationRequireTestEntryPoint(perPackageGenerationRequireTestEntryPoint bool) {
+ c.perPackageGenerationRequireTestEntryPoint = perPackageGenerationRequireTestEntryPoint
+}
+
+func (c *Config) PerPackageGenerationRequireTestEntryPoint() bool {
+ return c.perPackageGenerationRequireTestEntryPoint
+}
+
// SetLibraryNamingConvention sets the py_library target naming convention.
func (c *Config) SetLibraryNamingConvention(libraryNamingConvention string) {
c.libraryNamingConvention = libraryNamingConvention
@@ -494,9 +509,9 @@
normConventionalDistributionName = strings.Trim(normConventionalDistributionName, "_")
case Pep503LabelNormalizationType:
// See https://packaging.python.org/en/latest/specifications/name-normalization/#name-format
- normConventionalDistributionName = strings.ToLower(conventionalDistributionName) // ... "should be lowercased"
+ normConventionalDistributionName = strings.ToLower(conventionalDistributionName) // ... "should be lowercased"
normConventionalDistributionName = regexp.MustCompile(`[-_.]+`).ReplaceAllString(normConventionalDistributionName, "-") // ... "all runs of the characters ., -, or _ replaced with a single -"
- normConventionalDistributionName = strings.Trim(normConventionalDistributionName, "-") // ... "must start and end with a letter or number"
+ normConventionalDistributionName = strings.Trim(normConventionalDistributionName, "-") // ... "must start and end with a letter or number"
default:
fallthrough
case NoLabelNormalizationType: