Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
10 changes: 10 additions & 0 deletions gazelle/docs/annotations.md
Original file line number Diff line number Diff line change
Expand Up @@ -198,3 +198,13 @@ py_test(
```

See {gh-issue}`3076` for more information.

When a {bzl:obj}`py_test` has multiple source files, the annotation may be
omitted from some files. If multiple source files set the annotation, they must
all set it to the same value; Gazelle reports an error if the values conflict.

:::{versionchanged} VERSION_NEXT_PATCH
For multi-source {bzl:obj}`py_test` targets, annotations in different source
files must agree. An annotation in one source file is no longer overwritten by
an unset value in another source file.
:::
4 changes: 4 additions & 0 deletions gazelle/python/BUILD.bazel
Original file line number Diff line number Diff line change
Expand Up @@ -120,10 +120,14 @@ go_test(
name = "default_test",
srcs = [
"file_parser_test.go",
"parser_test.go",
"std_modules_test.go",
],
embed = [":python"],
deps = [
"@com_github_emirpasic_gods//sets/treeset:go_default_library",
"@com_github_emirpasic_gods//utils:go_default_library",
"@com_github_stretchr_testify//assert",
"@com_github_stretchr_testify//require",
],
)
19 changes: 18 additions & 1 deletion gazelle/python/parser.go
Original file line number Diff line number Diff line change
Expand Up @@ -92,6 +92,8 @@ func (p *python3Parser) parse(pyFilenames *treeset.Set) (*treeset.Set, map[strin
mainModules := make(map[string]*treeset.Set, len(chRes))
allAnnotations := new(annotations)
allAnnotations.ignore = make(map[string]struct{})
var includesPytestConftest bool
var excludesPytestConftest bool
for res := range chRes {
if res.HasMain {
mainModules[res.FileName] = treeset.NewWith(moduleComparator)
Expand Down Expand Up @@ -125,9 +127,24 @@ func (p *python3Parser) parse(pyFilenames *treeset.Set) (*treeset.Set, map[strin
allAnnotations.ignore[k] = v
}
allAnnotations.includeDeps = append(allAnnotations.includeDeps, annotations.includeDeps...)
allAnnotations.includePytestConftest = annotations.includePytestConftest
if annotations.includePytestConftest != nil {
if *annotations.includePytestConftest {
includesPytestConftest = true
} else {
excludesPytestConftest = true
}
}
}

if includesPytestConftest && excludesPytestConftest {
return nil, nil, nil, fmt.Errorf(
"conflicting values for the %q annotation across Python source files",
annotationKindIncludePytestConftest,
)
Comment thread
amartani marked this conversation as resolved.
}
if includesPytestConftest || excludesPytestConftest {
allAnnotations.includePytestConftest = &includesPytestConftest
}
allAnnotations.includeDeps = removeDupesFromStringTreeSetSlice(allAnnotations.includeDeps)

return modules, mainModules, allAnnotations, nil
Expand Down
92 changes: 92 additions & 0 deletions gazelle/python/parser_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,92 @@
package python

import (
"os"
"path/filepath"
"testing"

"github.com/emirpasic/gods/sets/treeset"
godsutils "github.com/emirpasic/gods/utils"
"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/require"
)

func TestParseIncludePytestConftestAnnotations(t *testing.T) {
t.Parallel()

boolPointer := func(value bool) *bool {
return &value
}
tests := []struct {
name string
contents []string
expected *bool
expectErr string
}{
{
name: "all unset",
contents: []string{"", ""},
},
{
name: "false and unset",
contents: []string{"# gazelle:include_pytest_conftest false", ""},
expected: boolPointer(false),
},
{
name: "true and unset",
contents: []string{"", "# gazelle:include_pytest_conftest true"},
expected: boolPointer(true),
},
{
name: "matching false values",
contents: []string{
"# gazelle:include_pytest_conftest false",
"# gazelle:include_pytest_conftest false",
"",
},
expected: boolPointer(false),
},
{
name: "matching true values",
contents: []string{
"# gazelle:include_pytest_conftest true",
"",
"# gazelle:include_pytest_conftest true",
},
expected: boolPointer(true),
},
{
name: "conflicting values",
contents: []string{
"# gazelle:include_pytest_conftest false",
"",
"# gazelle:include_pytest_conftest true",
},
expectErr: "conflicting values for the \"include_pytest_conftest\" annotation " +
"across Python source files",
},
}

for _, test := range tests {
t.Run(test.name, func(t *testing.T) {
t.Parallel()
repoRoot := t.TempDir()
filenames := treeset.NewWith(godsutils.StringComparator)
for index, contents := range test.contents {
filename := string(rune('a'+index)) + "_test.py"
require.NoError(t, os.WriteFile(filepath.Join(repoRoot, filename), []byte(contents), 0o600))
filenames.Add(filename)
}

parser := newPython3Parser(repoRoot, "", func(string) bool { return false })
_, _, annotations, err := parser.parse(filenames)
if test.expectErr != "" {
assert.EqualError(t, err, test.expectErr)
return
}

require.NoError(t, err)
assert.Equal(t, test.expected, annotations.includePytestConftest)
})
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
# gazelle:python_generation_mode package
# gazelle:python_generation_mode_per_package_require_test_entry_point false
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
# gazelle:python_generation_mode package
# gazelle:python_generation_mode_per_package_require_test_entry_point false
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
# Conflicting `include_pytest_conftest` annotations

This test case asserts that Gazelle fails when source files in the same
`py_test` set `include_pytest_conftest` to conflicting values.
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
# This is a Bazel workspace for the Gazelle test data.
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@

Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
# gazelle:include_pytest_conftest false
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
---
expect:
exit_code: 1
stderr: >-
gazelle: ERROR: conflicting values for the
"include_pytest_conftest" annotation across Python source files
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
# gazelle:include_pytest_conftest true
4 changes: 4 additions & 0 deletions news/gazelle-pytest-conftest.fixed.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
(gazelle) Preserve explicitly set `include_pytest_conftest` annotations in
multi-source tests when other source files omit the annotation, and report an
error when explicitly set values conflict
([#3076](https://github.com/bazel-contrib/rules_python/issues/3076)).
Loading