@@ -273,6 +273,7 @@ func (py *Python) GenerateRules(args language.GenerateArgs) language.GenerateRes
273273 srcs .Remove (name )
274274 }
275275 }
276+
276277 sort .Strings (mainFileNames )
277278 for _ , filename := range mainFileNames {
278279 pyBinaryTargetName := strings .TrimSuffix (filepath .Base (filename ), ".py" )
@@ -282,9 +283,15 @@ func (py *Python) GenerateRules(args language.GenerateArgs) language.GenerateRes
282283 fqTarget .String (), actualPyBinaryKind , err )
283284 continue
284285 }
286+
287+ // Add any sibling .pyi files to pyi_srcs
288+ filenames := treeset .NewWith (godsutils .StringComparator , filename )
289+ pyiSrcs , _ := getPyiFilenames (filenames , cfg .GeneratePyiSrcs (), args .Dir )
290+
285291 pyBinary := newTargetBuilder (pyBinaryKind , pyBinaryTargetName , pythonProjectRoot , args .Rel , pyFileNames , cfg .ResolveSiblingImports ()).
286292 addVisibility (visibility ).
287293 addSrc (filename ).
294+ addPyiSrcs (pyiSrcs ).
288295 addModuleDependencies (mainModules [filename ]).
289296 addResolvedDependencies (annotations .includeDeps ).
290297 generateImportsAttribute ().
@@ -312,6 +319,9 @@ func (py *Python) GenerateRules(args language.GenerateArgs) language.GenerateRes
312319 }
313320 }
314321
322+ // Add any sibling .pyi files to pyi_srcs
323+ pyiSrcs , _ := getPyiFilenames (srcs , cfg .GeneratePyiSrcs (), args .Dir )
324+
315325 // Check if a target with the same name we are generating already
316326 // exists, and if it is of a different kind from the one we are
317327 // generating. If so, we have to throw an error since Gazelle won't
@@ -327,6 +337,7 @@ func (py *Python) GenerateRules(args language.GenerateArgs) language.GenerateRes
327337 pyLibrary := newTargetBuilder (pyLibraryKind , pyLibraryTargetName , pythonProjectRoot , args .Rel , pyFileNames , cfg .ResolveSiblingImports ()).
328338 addVisibility (visibility ).
329339 addSrcs (srcs ).
340+ addPyiSrcs (pyiSrcs ).
330341 addModuleDependencies (allDeps ).
331342 addResolvedDependencies (annotations .includeDeps ).
332343 generateImportsAttribute ().
@@ -377,10 +388,15 @@ func (py *Python) GenerateRules(args language.GenerateArgs) language.GenerateRes
377388 collisionErrors .Add (err )
378389 }
379390
391+ // Add any sibling .pyi files to pyi_srcs
392+ filenames := treeset .NewWith (godsutils .StringComparator , pyBinaryEntrypointFilename )
393+ pyiSrcs , _ := getPyiFilenames (filenames , cfg .GeneratePyiSrcs (), args .Dir )
394+
380395 pyBinaryTarget := newTargetBuilder (pyBinaryKind , pyBinaryTargetName , pythonProjectRoot , args .Rel , pyFileNames , cfg .ResolveSiblingImports ()).
381396 setMain (pyBinaryEntrypointFilename ).
382397 addVisibility (visibility ).
383398 addSrc (pyBinaryEntrypointFilename ).
399+ addPyiSrcs (pyiSrcs ).
384400 addModuleDependencies (deps ).
385401 addResolvedDependencies (annotations .includeDeps ).
386402 setAnnotations (* annotations ).
@@ -411,8 +427,13 @@ func (py *Python) GenerateRules(args language.GenerateArgs) language.GenerateRes
411427 collisionErrors .Add (err )
412428 }
413429
430+ // Add any sibling .pyi files to pyi_srcs
431+ filenames := treeset .NewWith (godsutils .StringComparator , conftestFilename )
432+ pyiSrcs , _ := getPyiFilenames (filenames , cfg .GeneratePyiSrcs (), args .Dir )
433+
414434 conftestTarget := newTargetBuilder (pyLibraryKind , conftestTargetname , pythonProjectRoot , args .Rel , pyFileNames , cfg .ResolveSiblingImports ()).
415435 addSrc (conftestFilename ).
436+ addPyiSrcs (pyiSrcs ).
416437 addModuleDependencies (deps ).
417438 addResolvedDependencies (annotations .includeDeps ).
418439 setAnnotations (* annotations ).
@@ -443,8 +464,13 @@ func (py *Python) GenerateRules(args language.GenerateArgs) language.GenerateRes
443464 fqTarget .String (), actualPyTestKind , err , pythonconfig .TestNamingConvention )
444465 collisionErrors .Add (err )
445466 }
467+
468+ // Add any sibling .pyi files to pyi_srcs
469+ pyiSrcs , _ := getPyiFilenames (srcs , cfg .GeneratePyiSrcs (), args .Dir )
470+
446471 return newTargetBuilder (pyTestKind , pyTestTargetName , pythonProjectRoot , args .Rel , pyFileNames , cfg .ResolveSiblingImports ()).
447472 addSrcs (srcs ).
473+ addPyiSrcs (pyiSrcs ).
448474 addModuleDependencies (deps ).
449475 addResolvedDependencies (annotations .includeDeps ).
450476 setAnnotations (* annotations ).
@@ -691,3 +717,25 @@ func generateProtoLibraries(args language.GenerateArgs, cfg *pythonconfig.Config
691717 }
692718
693719}
720+
721+ // getPyiFilenames returns a set of existing .pyi source file names for a given set of source
722+ // file names if GeneratePyiSrcs is set. Otherwise, returns an empty set.
723+ func getPyiFilenames (filenames * treeset.Set , generatePyiSrcs bool , basePath string ) (* treeset.Set , error ) {
724+ pyiSrcs := treeset .NewWith (godsutils .StringComparator )
725+ if ! generatePyiSrcs {
726+ return pyiSrcs , nil
727+ }
728+
729+ it := filenames .Iterator ()
730+ for it .Next () {
731+ pyiFilename := it .Value ().(string ) + "i" // foo.py --> foo.pyi
732+
733+ _ , err := os .Stat (filepath .Join (basePath , pyiFilename ))
734+ // If the file DNE or there's some other error, there's nothing to do.
735+ if err == nil {
736+ // pyi file exists, add it
737+ pyiSrcs .Add (pyiFilename )
738+ }
739+ }
740+ return pyiSrcs , nil
741+ }
0 commit comments