Skip to content

Commit 57f819c

Browse files
authored
fix(gazelle) Fix dependency added as both deps and pyi_deps (#3036)
Fix an issue in #3014 where a dependency may end up being added in both `deps` and `pyi_deps`, in cases where the regular and the type-checking import refer to different python modules on the same `py_library` target. Other cases are already deduplicated earlier on, but this case can only be deduplicated in the resolve phase. (No new changelog entry since this is a fix to an unreleased feature that is already in the changelog)
1 parent 7719529 commit 57f819c

File tree

13 files changed

+49
-9
lines changed

13 files changed

+49
-9
lines changed

gazelle/python/resolve.go

Lines changed: 13 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -124,12 +124,16 @@ func (py *Resolver) Embeds(r *rule.Rule, from label.Label) []label.Label {
124124
}
125125

126126
// addDependency adds a dependency to either the regular deps or pyiDeps set based on
127-
// whether the module is type-checking only.
128-
func addDependency(dep string, mod Module, deps, pyiDeps *treeset.Set) {
129-
if mod.TypeCheckingOnly {
130-
pyiDeps.Add(dep)
127+
// whether the module is type-checking only. If a module is added as both
128+
// non-type-checking and type-checking, it should end up in deps and not pyiDeps.
129+
func addDependency(dep string, typeCheckingOnly bool, deps, pyiDeps *treeset.Set) {
130+
if typeCheckingOnly {
131+
if !deps.Contains(dep) {
132+
pyiDeps.Add(dep)
133+
}
131134
} else {
132135
deps.Add(dep)
136+
pyiDeps.Remove(dep)
133137
}
134138
}
135139

@@ -240,7 +244,7 @@ func (py *Resolver) Resolve(
240244
override.Repo = ""
241245
}
242246
dep := override.Rel(from.Repo, from.Pkg).String()
243-
addDependency(dep, mod, deps, pyiDeps)
247+
addDependency(dep, mod.TypeCheckingOnly, deps, pyiDeps)
244248
if explainDependency == dep {
245249
log.Printf("Explaining dependency (%s): "+
246250
"in the target %q, the file %q imports %q at line %d, "+
@@ -251,7 +255,7 @@ func (py *Resolver) Resolve(
251255
}
252256
} else {
253257
if dep, distributionName, ok := cfg.FindThirdPartyDependency(moduleName); ok {
254-
addDependency(dep, mod, deps, pyiDeps)
258+
addDependency(dep, mod.TypeCheckingOnly, deps, pyiDeps)
255259
// Add the type and stub dependencies if they exist.
256260
modules := []string{
257261
fmt.Sprintf("%s_stubs", strings.ToLower(distributionName)),
@@ -261,8 +265,8 @@ func (py *Resolver) Resolve(
261265
}
262266
for _, module := range modules {
263267
if dep, _, ok := cfg.FindThirdPartyDependency(module); ok {
264-
// Type stub packages always go to pyiDeps
265-
pyiDeps.Add(dep)
268+
// Type stub packages are added as type-checking only.
269+
addDependency(dep, true, deps, pyiDeps)
266270
}
267271
}
268272
if explainDependency == dep {
@@ -321,7 +325,7 @@ func (py *Resolver) Resolve(
321325
}
322326
matchLabel := filteredMatches[0].Label.Rel(from.Repo, from.Pkg)
323327
dep := matchLabel.String()
324-
addDependency(dep, mod, deps, pyiDeps)
328+
addDependency(dep, mod.TypeCheckingOnly, deps, pyiDeps)
325329
if explainDependency == dep {
326330
log.Printf("Explaining dependency (%s): "+
327331
"in the target %q, the file %q imports %q at line %d, "+
Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
# gazelle:python_generation_mode package
2+
# gazelle:python_generate_pyi_deps true
Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
# gazelle:python_generation_mode package
2+
# gazelle:python_generate_pyi_deps true
Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
# Overlapping deps and pyi_deps across packages
2+
3+
This test reproduces a case where a dependency may be added to both `deps` and
4+
`pyi_deps`. Package `b` imports `a.foo` normally and imports `a.bar` as a
5+
type-checking only import. The dependency on package `a` should appear only in
6+
`deps` (and not `pyi_deps`) of package `b`.
Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
workspace(name = "gazelle_python_test")

gazelle/python/testdata/type_checking_imports_across_packages/a/BUILD.in

Whitespace-only changes.
Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
load("@rules_python//python:defs.bzl", "py_library")
2+
3+
py_library(
4+
name = "a",
5+
srcs = [
6+
"bar.py",
7+
"foo.py",
8+
],
9+
visibility = ["//:__subpackages__"],
10+
)

gazelle/python/testdata/type_checking_imports_across_packages/a/bar.py

Whitespace-only changes.

gazelle/python/testdata/type_checking_imports_across_packages/a/foo.py

Whitespace-only changes.

gazelle/python/testdata/type_checking_imports_across_packages/b/BUILD.in

Whitespace-only changes.

0 commit comments

Comments
 (0)