Skip to content

Commit fe2c325

Browse files
authored
feat!: using Gazelle's lifecycle manager to manage external processes (bazel-contrib#1284)
Gazelle v0.30.0 introduced a lifecycle manager. We can use that to start and shutdown parser and stdmodule processes. So we don't need to use `init` function or creating `context.WithTimeout`. BREAKING CHANGES: This requires the users of this Gazelle extension to upgrade to Gazelle v0.30.0 or above.
1 parent 0d59fcf commit fe2c325

File tree

7 files changed

+73
-25
lines changed

7 files changed

+73
-25
lines changed

gazelle/go.mod

Lines changed: 6 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,9 @@ module github.com/bazelbuild/rules_python/gazelle
33
go 1.19
44

55
require (
6-
github.com/bazelbuild/buildtools v0.0.0-20221004120235-7186f635531b
6+
github.com/bazelbuild/bazel-gazelle v0.31.1
7+
github.com/bazelbuild/buildtools v0.0.0-20230510134650-37bd1811516d
8+
github.com/bazelbuild/rules_go v0.39.1
79
github.com/bmatcuk/doublestar v1.3.4
810
github.com/emirpasic/gods v1.18.1
911
github.com/ghodss/yaml v1.0.0
@@ -12,6 +14,7 @@ require (
1214

1315
require (
1416
github.com/google/go-cmp v0.5.9 // indirect
15-
golang.org/x/sys v0.0.0-20221010170243-090e33056c14 // indirect
16-
golang.org/x/tools v0.1.12 // indirect
17+
golang.org/x/mod v0.10.0 // indirect
18+
golang.org/x/sys v0.8.0 // indirect
19+
golang.org/x/tools v0.9.1 // indirect
1720
)

gazelle/go.sum

Lines changed: 12 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,11 @@
11
cloud.google.com/go v0.26.0/go.mod h1:aQUYkXzVsufM+DwF1aE+0xfcU+56JwCaLick0ClmMTw=
22
github.com/BurntSushi/toml v0.3.1/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03qcyfWMU=
3-
github.com/bazelbuild/bazel-gazelle v0.27.0 h1:+/ZhUxlDy4XnyMIGeKkbRZoIGssy1eO51GijwIvvuwE=
4-
github.com/bazelbuild/bazel-gazelle v0.27.0/go.mod h1:2K6B42/loq8ext4JObmam4gTYx4En1MUSzHFKQF8hPM=
5-
github.com/bazelbuild/buildtools v0.0.0-20221004120235-7186f635531b h1:jhiMzJ+8unnLRtV8rpbWBFE9pFNzIqgUTyZU5aA++w8=
6-
github.com/bazelbuild/buildtools v0.0.0-20221004120235-7186f635531b/go.mod h1:689QdV3hBP7Vo9dJMmzhoYIyo/9iMhEmHkJcnaPRCbo=
7-
github.com/bazelbuild/rules_go v0.35.0 h1:ViPR65vOrg74JKntAUFY6qZkheBKGB6to7wFd8gCRU4=
8-
github.com/bazelbuild/rules_go v0.35.0/go.mod h1:ahciH68Viyxtm/gvCQplaAiu8buhf/b+gWswcPjFixI=
3+
github.com/bazelbuild/bazel-gazelle v0.31.1 h1:ROyUyUHzoEdvoOs1e0haxJx1l5EjZX6AOqiKdVlaBbg=
4+
github.com/bazelbuild/bazel-gazelle v0.31.1/go.mod h1:Ul0pqz50f5wxz0QNzsZ+mrEu4AVAVJZEB5xLnHgIG9c=
5+
github.com/bazelbuild/buildtools v0.0.0-20230510134650-37bd1811516d h1:Fl1FfItZp34QIQmmDTbZXHB5XA6JfbNNfH7tRRGWvQo=
6+
github.com/bazelbuild/buildtools v0.0.0-20230510134650-37bd1811516d/go.mod h1:689QdV3hBP7Vo9dJMmzhoYIyo/9iMhEmHkJcnaPRCbo=
7+
github.com/bazelbuild/rules_go v0.39.1 h1:wkJLUDx59dntWMghuL8++GteoU1To6sRoKJXuyFtmf8=
8+
github.com/bazelbuild/rules_go v0.39.1/go.mod h1:TMHmtfpvyfsxaqfL9WnahCsXMWDMICTw7XeK9yVb+YU=
99
github.com/bmatcuk/doublestar v1.3.4 h1:gPypJ5xD31uhX6Tf54sDPUOBXTqKH4c9aPY66CyQrS0=
1010
github.com/bmatcuk/doublestar v1.3.4/go.mod h1:wiQtGV+rzVYxB7WIlirSN++5HPtPlXEo9MEoZQC/PmE=
1111
github.com/census-instrumentation/opencensus-proto v0.2.1/go.mod h1:f6KPmirojxKA12rnyqOA5BBL4O983OfeGPqjHWSTneU=
@@ -45,6 +45,8 @@ golang.org/x/exp v0.0.0-20190121172915-509febef88a4/go.mod h1:CJ0aWSM057203Lf6IL
4545
golang.org/x/lint v0.0.0-20181026193005-c67002cb31c3/go.mod h1:UVdnD1Gm6xHRNCYTkRU2/jEulfH38KcIWyp/GAMgvoE=
4646
golang.org/x/lint v0.0.0-20190227174305-5b3e6a55c961/go.mod h1:wehouNa3lNwaWXcvxsM5YxQ5yQlVC4a0KAMCusXpPoU=
4747
golang.org/x/lint v0.0.0-20190313153728-d0100b6bd8b3/go.mod h1:6SW0HCj/g11FgYtHlgUYUwCkIfeOF89ocIRzGO/8vkc=
48+
golang.org/x/mod v0.10.0 h1:lFO9qtOdlre5W1jxS3r/4szv2/6iXxScdzjoBMXNhYk=
49+
golang.org/x/mod v0.10.0/go.mod h1:iBbtSCu2XBx23ZKBPSOrRkjjQPZFPuis4dIYUhu/chs=
4850
golang.org/x/net v0.0.0-20180724234803-3673e40ba225/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
4951
golang.org/x/net v0.0.0-20180826012351-8a410e7b638d/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
5052
golang.org/x/net v0.0.0-20190213061140-3a22650c66bd/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
@@ -56,15 +58,15 @@ golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJ
5658
golang.org/x/sys v0.0.0-20180830151530-49385e6e1522/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
5759
golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
5860
golang.org/x/sys v0.0.0-20200930185726-fdedc70b468f/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
59-
golang.org/x/sys v0.0.0-20221010170243-090e33056c14 h1:k5II8e6QD8mITdi+okbbmR/cIyEbeXLBhy5Ha4nevyc=
60-
golang.org/x/sys v0.0.0-20221010170243-090e33056c14/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
61+
golang.org/x/sys v0.8.0 h1:EBmGv8NaZBZTWvrbjNoL6HVt+IVy3QDQpJs7VRIw3tU=
62+
golang.org/x/sys v0.8.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
6163
golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
6264
golang.org/x/tools v0.0.0-20190114222345-bf090417da8b/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
6365
golang.org/x/tools v0.0.0-20190226205152-f727befe758c/go.mod h1:9Yl7xja0Znq3iFh3HoIrodX9oNMXvdceNzlUR8zjMvY=
6466
golang.org/x/tools v0.0.0-20190311212946-11955173bddd/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs=
6567
golang.org/x/tools v0.0.0-20190524140312-2c0ae7006135/go.mod h1:RgjU9mgBXZiqYHBnxXauZ1Gv1EHHAz9KjViQ78xBX0Q=
66-
golang.org/x/tools v0.1.12 h1:VveCTK38A2rkS8ZqFY25HIDFscX5X9OoEhJd3quQmXU=
67-
golang.org/x/tools v0.1.12/go.mod h1:hNGJHUnrk76NpqgfD5Aqm5Crs+Hm0VOH/i9J2+nxYbc=
68+
golang.org/x/tools v0.9.1 h1:8WMNJAz3zrtPmnYC7ISf5dEn3MT0gY7jBJfw27yrrLo=
69+
golang.org/x/tools v0.9.1/go.mod h1:owI94Op576fPu3cIGQeHs3joujW/2Oc6MtlxbF5dfNc=
6870
golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
6971
golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
7072
google.golang.org/appengine v1.1.0/go.mod h1:EbEs0AVv82hx2wNQdGPgUI5lhzA/G0D9YwlJXL52JkM=

gazelle/python/BUILD.bazel

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@ go_library(
1010
"generate.go",
1111
"kinds.go",
1212
"language.go",
13+
"lifecycle.go",
1314
"parser.go",
1415
"resolve.go",
1516
"std_modules.go",

gazelle/python/language.go

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,7 @@ import (
2323
type Python struct {
2424
Configurer
2525
Resolver
26+
LifeCycleManager
2627
}
2728

2829
// NewLanguage initializes a new Python that satisfies the language.Language

gazelle/python/lifecycle.go

Lines changed: 37 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,37 @@
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+
package python
16+
17+
import (
18+
"context"
19+
"github.com/bazelbuild/bazel-gazelle/language"
20+
)
21+
22+
type LifeCycleManager struct {
23+
language.BaseLifecycleManager
24+
}
25+
26+
func (l *LifeCycleManager) Before(ctx context.Context) {
27+
startParserProcess(ctx)
28+
startStdModuleProcess(ctx)
29+
}
30+
31+
func (l *LifeCycleManager) DoneGeneratingRules() {
32+
shutdownParserProcess()
33+
}
34+
35+
func (l *LifeCycleManager) AfterResolvingDeps(ctx context.Context) {
36+
shutdownStdModuleProcess()
37+
}

gazelle/python/parser.go

Lines changed: 8 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -25,28 +25,25 @@ import (
2525
"os/exec"
2626
"strings"
2727
"sync"
28-
"time"
2928

3029
"github.com/bazelbuild/rules_go/go/tools/bazel"
3130
"github.com/emirpasic/gods/sets/treeset"
3231
godsutils "github.com/emirpasic/gods/utils"
3332
)
3433

3534
var (
36-
parserStdin io.Writer
35+
parserStdin io.WriteCloser
3736
parserStdout io.Reader
3837
parserMutex sync.Mutex
3938
)
4039

41-
func init() {
40+
func startParserProcess(ctx context.Context) {
4241
parseScriptRunfile, err := bazel.Runfile("python/parse")
4342
if err != nil {
4443
log.Printf("failed to initialize parser: %v\n", err)
4544
os.Exit(1)
4645
}
4746

48-
ctx := context.Background()
49-
ctx, parserCancel := context.WithTimeout(ctx, time.Minute*10)
5047
cmd := exec.CommandContext(ctx, parseScriptRunfile)
5148

5249
cmd.Stderr = os.Stderr
@@ -71,14 +68,19 @@ func init() {
7168
}
7269

7370
go func() {
74-
defer parserCancel()
7571
if err := cmd.Wait(); err != nil {
7672
log.Printf("failed to wait for parser: %v\n", err)
7773
os.Exit(1)
7874
}
7975
}()
8076
}
8177

78+
func shutdownParserProcess() {
79+
if err := parserStdin.Close(); err != nil {
80+
fmt.Fprintf(os.Stderr, "error closing parser: %v", err)
81+
}
82+
}
83+
8284
// python3Parser implements a parser for Python files that extracts the modules
8385
// as seen in the import statements.
8486
type python3Parser struct {

gazelle/python/std_modules.go

Lines changed: 8 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -25,19 +25,18 @@ import (
2525
"strconv"
2626
"strings"
2727
"sync"
28-
"time"
2928

3029
"github.com/bazelbuild/rules_go/go/tools/bazel"
3130
)
3231

3332
var (
34-
stdModulesStdin io.Writer
33+
stdModulesStdin io.WriteCloser
3534
stdModulesStdout io.Reader
3635
stdModulesMutex sync.Mutex
3736
stdModulesSeen map[string]struct{}
3837
)
3938

40-
func init() {
39+
func startStdModuleProcess(ctx context.Context) {
4140
stdModulesSeen = make(map[string]struct{})
4241

4342
stdModulesScriptRunfile, err := bazel.Runfile("python/std_modules")
@@ -46,8 +45,6 @@ func init() {
4645
os.Exit(1)
4746
}
4847

49-
ctx := context.Background()
50-
ctx, stdModulesCancel := context.WithTimeout(ctx, time.Minute*10)
5148
cmd := exec.CommandContext(ctx, stdModulesScriptRunfile)
5249

5350
cmd.Stderr = os.Stderr
@@ -73,14 +70,19 @@ func init() {
7370
}
7471

7572
go func() {
76-
defer stdModulesCancel()
7773
if err := cmd.Wait(); err != nil {
7874
log.Printf("failed to wait for std_modules: %v\n", err)
7975
os.Exit(1)
8076
}
8177
}()
8278
}
8379

80+
func shutdownStdModuleProcess() {
81+
if err := stdModulesStdin.Close(); err != nil {
82+
fmt.Fprintf(os.Stderr, "error closing std module: %v", err)
83+
}
84+
}
85+
8486
func isStdModule(m module) (bool, error) {
8587
if _, seen := stdModulesSeen[m.Name]; seen {
8688
return true, nil

0 commit comments

Comments
 (0)