@@ -250,6 +250,7 @@ func (py *Python) GenerateRules(args language.GenerateArgs) language.GenerateRes
250250 srcs .Remove (name )
251251 }
252252 }
253+
253254 sort .Strings (mainFileNames )
254255 for _ , filename := range mainFileNames {
255256 pyBinaryTargetName := strings .TrimSuffix (filepath .Base (filename ), ".py" )
@@ -259,9 +260,15 @@ func (py *Python) GenerateRules(args language.GenerateArgs) language.GenerateRes
259260 fqTarget .String (), actualPyBinaryKind , err )
260261 continue
261262 }
263+
264+ // Add any sibling .pyi files to pyi_srcs
265+ filenames := treeset .NewWith (godsutils .StringComparator , filename )
266+ pyiSrcs , _ := getPyiFilenames (filenames , cfg .GeneratePyiSrcs (), args .Dir )
267+
262268 pyBinary := newTargetBuilder (pyBinaryKind , pyBinaryTargetName , pythonProjectRoot , args .Rel , pyFileNames , cfg .ResolveSiblingImports ()).
263269 addVisibility (visibility ).
264270 addSrc (filename ).
271+ addPyiSrcs (pyiSrcs ).
265272 addModuleDependencies (mainModules [filename ]).
266273 addResolvedDependencies (annotations .includeDeps ).
267274 generateImportsAttribute ().
@@ -289,6 +296,9 @@ func (py *Python) GenerateRules(args language.GenerateArgs) language.GenerateRes
289296 }
290297 }
291298
299+ // Add any sibling .pyi files to pyi_srcs
300+ pyiSrcs , _ := getPyiFilenames (srcs , cfg .GeneratePyiSrcs (), args .Dir )
301+
292302 // Check if a target with the same name we are generating already
293303 // exists, and if it is of a different kind from the one we are
294304 // generating. If so, we have to throw an error since Gazelle won't
@@ -304,6 +314,7 @@ func (py *Python) GenerateRules(args language.GenerateArgs) language.GenerateRes
304314 pyLibrary := newTargetBuilder (pyLibraryKind , pyLibraryTargetName , pythonProjectRoot , args .Rel , pyFileNames , cfg .ResolveSiblingImports ()).
305315 addVisibility (visibility ).
306316 addSrcs (srcs ).
317+ addPyiSrcs (pyiSrcs ).
307318 addModuleDependencies (allDeps ).
308319 addResolvedDependencies (annotations .includeDeps ).
309320 generateImportsAttribute ().
@@ -354,10 +365,15 @@ func (py *Python) GenerateRules(args language.GenerateArgs) language.GenerateRes
354365 collisionErrors .Add (err )
355366 }
356367
368+ // Add any sibling .pyi files to pyi_srcs
369+ filenames := treeset .NewWith (godsutils .StringComparator , pyBinaryEntrypointFilename )
370+ pyiSrcs , _ := getPyiFilenames (filenames , cfg .GeneratePyiSrcs (), args .Dir )
371+
357372 pyBinaryTarget := newTargetBuilder (pyBinaryKind , pyBinaryTargetName , pythonProjectRoot , args .Rel , pyFileNames , cfg .ResolveSiblingImports ()).
358373 setMain (pyBinaryEntrypointFilename ).
359374 addVisibility (visibility ).
360375 addSrc (pyBinaryEntrypointFilename ).
376+ addPyiSrcs (pyiSrcs ).
361377 addModuleDependencies (deps ).
362378 addResolvedDependencies (annotations .includeDeps ).
363379 setAnnotations (* annotations ).
@@ -387,8 +403,13 @@ func (py *Python) GenerateRules(args language.GenerateArgs) language.GenerateRes
387403 collisionErrors .Add (err )
388404 }
389405
406+ // Add any sibling .pyi files to pyi_srcs
407+ filenames := treeset .NewWith (godsutils .StringComparator , conftestFilename )
408+ pyiSrcs , _ := getPyiFilenames (filenames , cfg .GeneratePyiSrcs (), args .Dir )
409+
390410 conftestTarget := newTargetBuilder (pyLibraryKind , conftestTargetname , pythonProjectRoot , args .Rel , pyFileNames , cfg .ResolveSiblingImports ()).
391411 addSrc (conftestFilename ).
412+ addPyiSrcs (pyiSrcs ).
392413 addModuleDependencies (deps ).
393414 addResolvedDependencies (annotations .includeDeps ).
394415 setAnnotations (* annotations ).
@@ -419,8 +440,13 @@ func (py *Python) GenerateRules(args language.GenerateArgs) language.GenerateRes
419440 fqTarget .String (), actualPyTestKind , err , pythonconfig .TestNamingConvention )
420441 collisionErrors .Add (err )
421442 }
443+
444+ // Add any sibling .pyi files to pyi_srcs
445+ pyiSrcs , _ := getPyiFilenames (srcs , cfg .GeneratePyiSrcs (), args .Dir )
446+
422447 return newTargetBuilder (pyTestKind , pyTestTargetName , pythonProjectRoot , args .Rel , pyFileNames , cfg .ResolveSiblingImports ()).
423448 addSrcs (srcs ).
449+ addPyiSrcs (pyiSrcs ).
424450 addModuleDependencies (deps ).
425451 addResolvedDependencies (annotations .includeDeps ).
426452 setAnnotations (* annotations ).
@@ -627,3 +653,23 @@ func generateProtoLibraries(args language.GenerateArgs, cfg *pythonconfig.Config
627653 }
628654
629655}
656+
657+ // getPyiFilenames returns a set of existing .pyi source file names for a given set of source
658+ // file names if GeneratePyiSrcs is set. Otherwise, returns an empty set.
659+ func getPyiFilenames (filenames * treeset.Set , generatePyiSrcs bool , basePath string ) (* treeset.Set , error ) {
660+ pyiSrcs := treeset .NewWith (godsutils .StringComparator )
661+ if generatePyiSrcs {
662+ it := filenames .Iterator ()
663+ for it .Next () {
664+ pyiFilename := it .Value ().(string ) + "i" // foo.py --> foo.pyi
665+
666+ _ , err := os .Stat (filepath .Join (basePath , pyiFilename ))
667+ // If the file DNE or there's some other error, there's nothing to do.
668+ if err == nil {
669+ // pyi file exists, add it
670+ pyiSrcs .Add (pyiFilename )
671+ }
672+ }
673+ }
674+ return pyiSrcs , nil
675+ }
0 commit comments