Skip to content

Commit a7fe7a6

Browse files
committed
feat(gazelle) generate conftest dependencies on parent folders
1 parent 2e95803 commit a7fe7a6

File tree

20 files changed

+116
-134
lines changed

20 files changed

+116
-134
lines changed

gazelle/python/generate.go

Lines changed: 63 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -657,10 +657,12 @@ func (py *Python) GenerateRules(args language.GenerateArgs) language.GenerateRes
657657
}
658658

659659
for _, pyTestTarget := range pyTestTargets {
660-
if conftest != nil {
661-
// Add conftest as a local dependency
662-
pyTestTarget.addResolvedDependency(":" + conftestTargetname)
660+
// Add conftest files as module dependencies with proper Python module paths
661+
parentConftestModules := findConftestFiles(args.Rel, pythonProjectRoot, args.Config.RepoRoot)
662+
for _, module := range parentConftestModules {
663+
pyTestTarget.addModuleDependency(module)
663664
}
665+
664666
pyTest := pyTestTarget.build()
665667

666668
result.Gen = append(result.Gen, pyTest)
@@ -744,3 +746,61 @@ func ensureNoCollision(file *rule.File, targetName, kind string) error {
744746
}
745747
return nil
746748
}
749+
750+
// findConftestFiles finds conftest.py files in parent directories up to and including the python_root.
751+
// It returns a list of Module objects with Python module paths relative to python_root.
752+
func findConftestFiles(currentRel string, pythonProjectRoot string, repoRoot string) []Module {
753+
var conftestModules []Module
754+
755+
// If currentRel is empty (root), no parent directories to check
756+
if currentRel == "" {
757+
return conftestModules
758+
}
759+
760+
// Determine the python_root path relative to repo root
761+
pythonRootRel := ""
762+
if pythonProjectRoot != "" {
763+
pythonRootRel = pythonProjectRoot
764+
}
765+
766+
// Start from currentRel
767+
current := currentRel
768+
769+
// Walk up the directory tree until we reach the repo root
770+
for {
771+
// Check if conftest.py exists in this directory
772+
conftestPath := filepath.Join(repoRoot, current, conftestFilename)
773+
if _, err := os.Stat(conftestPath); err == nil {
774+
// Calculate the Python module path relative to python_root
775+
var modulePath string
776+
if pythonRootRel == "" {
777+
// If python_root is at repo root, use the full path
778+
modulePath = strings.ReplaceAll(current, "/", ".") + ".conftest"
779+
} else {
780+
// Calculate relative path from python_root
781+
relPath, err := filepath.Rel(pythonRootRel, current)
782+
if err != nil || relPath == "." {
783+
// If we can't get relative path or it's the python_root itself
784+
modulePath = "conftest"
785+
} else {
786+
modulePath = strings.ReplaceAll(relPath, "/", ".") + ".conftest"
787+
}
788+
}
789+
790+
module := Module{
791+
Name: modulePath,
792+
}
793+
conftestModules = append(conftestModules, module)
794+
}
795+
796+
// Stop if we've reached the python_root
797+
if current == pythonRootRel || current == "." {
798+
break
799+
}
800+
801+
// Move to parent directory
802+
current = filepath.Dir(current)
803+
}
804+
805+
return conftestModules
806+
}

gazelle/python/testdata/simple_test_with_conftest/BUILD.out

Lines changed: 1 addition & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -9,19 +9,9 @@ py_library(
99
visibility = ["//:__subpackages__"],
1010
)
1111

12-
py_library(
13-
name = "conftest",
14-
testonly = True,
15-
srcs = ["conftest.py"],
16-
visibility = ["//:__subpackages__"],
17-
)
18-
1912
py_test(
2013
name = "simple_test_with_conftest_test",
2114
srcs = ["__test__.py"],
2215
main = "__test__.py",
23-
deps = [
24-
":conftest",
25-
":simple_test_with_conftest",
26-
],
16+
deps = [":simple_test_with_conftest"],
2717
)
Lines changed: 0 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -1,17 +0,0 @@
1-
# Copyright 2023 The Bazel Authors. All rights reserved.
2-
#
3-
# Licensed under the Apache License, Version 2.0 (the "License");
4-
# you may not use this file except in compliance with the License.
5-
# You may obtain a copy of the License at
6-
#
7-
# http://www.apache.org/licenses/LICENSE-2.0
8-
#
9-
# Unless required by applicable law or agreed to in writing, software
10-
# distributed under the License is distributed on an "AS IS" BASIS,
11-
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12-
# See the License for the specific language governing permissions and
13-
# limitations under the License.
14-
15-
from foo import foo
16-
17-
_ = foo

gazelle/python/testdata/simple_test_with_conftest/__test__.py

Lines changed: 1 addition & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -1,20 +1,6 @@
1-
# Copyright 2023 The Bazel Authors. All rights reserved.
2-
#
3-
# Licensed under the Apache License, Version 2.0 (the "License");
4-
# you may not use this file except in compliance with the License.
5-
# You may obtain a copy of the License at
6-
#
7-
# http://www.apache.org/licenses/LICENSE-2.0
8-
#
9-
# Unless required by applicable law or agreed to in writing, software
10-
# distributed under the License is distributed on an "AS IS" BASIS,
11-
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12-
# See the License for the specific language governing permissions and
13-
# limitations under the License.
14-
151
import unittest
162

17-
from __init__ import foo
3+
from foo import foo
184

195

206
class FooTest(unittest.TestCase):
Lines changed: 0 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -1,17 +0,0 @@
1-
# Copyright 2023 The Bazel Authors. All rights reserved.
2-
#
3-
# Licensed under the Apache License, Version 2.0 (the "License");
4-
# you may not use this file except in compliance with the License.
5-
# You may obtain a copy of the License at
6-
#
7-
# http://www.apache.org/licenses/LICENSE-2.0
8-
#
9-
# Unless required by applicable law or agreed to in writing, software
10-
# distributed under the License is distributed on an "AS IS" BASIS,
11-
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12-
# See the License for the specific language governing permissions and
13-
# limitations under the License.
14-
15-
from bar.bar import bar
16-
17-
_ = bar

gazelle/python/testdata/simple_test_with_conftest/bar/__test__.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,7 @@
1414

1515
import unittest
1616

17-
from bar.__init__ import bar
17+
from bar import bar
1818

1919

2020
class BarTest(unittest.TestCase):
Lines changed: 0 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -1,17 +1,2 @@
1-
# Copyright 2023 The Bazel Authors. All rights reserved.
2-
#
3-
# Licensed under the Apache License, Version 2.0 (the "License");
4-
# you may not use this file except in compliance with the License.
5-
# You may obtain a copy of the License at
6-
#
7-
# http://www.apache.org/licenses/LICENSE-2.0
8-
#
9-
# Unless required by applicable law or agreed to in writing, software
10-
# distributed under the License is distributed on an "AS IS" BASIS,
11-
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12-
# See the License for the specific language governing permissions and
13-
# limitations under the License.
14-
15-
161
def bar():
172
return "bar"
Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
load("@rules_python//python:defs.bzl", "py_library")
Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,24 @@
1+
load("@rules_python//python:defs.bzl", "py_library", "py_test")
2+
3+
py_library(
4+
name = "baz",
5+
srcs = ["__init__.py"],
6+
visibility = ["//:__subpackages__"],
7+
)
8+
9+
py_library(
10+
name = "conftest",
11+
testonly = True,
12+
srcs = ["conftest.py"],
13+
visibility = ["//:__subpackages__"],
14+
)
15+
16+
py_test(
17+
name = "baz_test",
18+
srcs = ["__test__.py"],
19+
main = "__test__.py",
20+
deps = [
21+
":conftest",
22+
"//bar:conftest",
23+
],
24+
)

gazelle/python/testdata/simple_test_with_conftest/bar/baz/__init__.py

Whitespace-only changes.

0 commit comments

Comments
 (0)