Skip to content

Commit

Permalink
Add option to include test types in the repl. (#855)
Browse files Browse the repository at this point in the history
Adds a repl option to include packages of linked in message types.
This allows using the types without preparing a hermetic set of
descriptors to load from file.
  • Loading branch information
jnthntatum authored Dec 28, 2023
1 parent 9c277eb commit 7f70747
Show file tree
Hide file tree
Showing 13 changed files with 253 additions and 48 deletions.
5 changes: 5 additions & 0 deletions repl/BUILD.bazel
Original file line number Diff line number Diff line change
Expand Up @@ -37,7 +37,12 @@ go_library(
"//interpreter:go_default_library",
"//repl/parser:go_default_library",
"@com_github_antlr4_go_antlr_v4//:go_default_library",
"@com_google_cel_spec//proto/test/v1/proto2:test_all_types_go_proto",
"@com_google_cel_spec//proto/test/v1/proto3:test_all_types_go_proto",
"@org_golang_google_protobuf//reflect/protoreflect:go_default_library",
"@org_golang_google_protobuf//reflect/protodesc:go_default_library",
"@org_golang_google_genproto_googleapis_api//expr/v1alpha1:go_default_library",
"@org_golang_google_genproto_googleapis_rpc//context/attribute_context:go_default_library",
"@org_golang_google_protobuf//encoding/prototext:go_default_library",
"@org_golang_google_protobuf//proto:go_default_library",
"@org_golang_google_protobuf//types/descriptorpb:go_default_library",
Expand Down
1 change: 1 addition & 0 deletions repl/appengine/go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ require github.com/google/cel-go/repl v0.0.0-20230406155237-b081aea03865
require (
github.com/antlr4-go/antlr/v4 v4.13.0 // indirect
github.com/google/cel-go v0.18.1 // indirect
github.com/google/cel-spec v0.13.0 // indirect
github.com/stoewer/go-strcase v1.3.0 // indirect
golang.org/x/exp v0.0.0-20230515195305-f3d0a9c9a5cc // indirect
golang.org/x/text v0.9.0 // indirect
Expand Down
4 changes: 4 additions & 0 deletions repl/appengine/go.sum
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,10 @@ github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSs
github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c=
github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
github.com/golang/protobuf v1.5.0/go.mod h1:FsONVRAS9T7sI+LIUmWTfcYkHO4aIWwzhcaSAoJOfIk=
github.com/google/cel-go v0.18.1 h1:V/lAXKq4C3BYLDy/ARzMtpkEEYfHQpZzVyzy69nEUjs=
github.com/google/cel-go v0.18.1/go.mod h1:PVAybmSnWkNMUZR/tEWFUiJ1Np4Hz0MHsZJcgC4zln4=
github.com/google/cel-spec v0.13.0 h1:5nfThDaiEQjx9cv+uB9DpDyWsP9j1gsSGWubZRHc4rg=
github.com/google/cel-spec v0.13.0/go.mod h1:kml2o4+MolVRtnyfTn6uTN+694OYIxnyIX1ARTkAYzM=
github.com/google/go-cmp v0.5.5/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
github.com/google/go-cmp v0.5.9 h1:O2Tfq5qg4qc4AmwVlvv0oLiVAGB7enBSJ2x2DqQFi38=
github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM=
Expand Down
60 changes: 30 additions & 30 deletions repl/appengine/web/package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

Original file line number Diff line number Diff line change
Expand Up @@ -48,6 +48,7 @@ <h1>References</h1>
<button mat-list-item (click)="startExample('errors')">Errors</button>
<button mat-list-item (click)="startExample('extension-functions')">Extension Functions</button>
<button mat-list-item (click)="startExample('json')">JSON</button>
<button mat-list-item (click)="startExample('structs')">Structs (protobuf)</button>
<button mat-list-item (click)="startExample('macros')">Macros</button>
</mat-action-list>
<p>Canonical Extensions</p>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -79,6 +79,23 @@ const examples = new Map<string, Example>([
]
}
}],
["structs", {
"request": {
commands: [
`%load_descriptors --pkg 'google-rpc'`,
`%option --container "google.rpc.context"`,
`%let now = timestamp("2001-01-01T00:00:01Z")`,
`%let sa_user = "example-service"`,
`AttributeContext.Request{
auth: AttributeContext.Auth{
principal: sa_user,
audiences: ['my-project'],
},
time: now
}`
]
}
}],
["macros", {
"request": {
commands: [
Expand Down
7 changes: 7 additions & 0 deletions repl/commands.go
Original file line number Diff line number Diff line change
Expand Up @@ -47,6 +47,12 @@ optional language features.
%option --container 'google.protobuf'
%option --extension 'all'`

loadDescriptorsUsage = `LoadDescriptors loads a protobuf descriptor file (google.protobuf.FileDescriptorSet)
from disk or from a predefined package. Supported packages are "cel-spec-test-types"
(TestAllTypes) and "google-rpc" (AttributeContext).
%load_descriptors 'path/to/descriptor_set.binarypb'
%load_descriptors --pkg 'cel-spec-test-types'`

exitUsage = `Exit terminates the REPL.
%exit`

Expand Down Expand Up @@ -184,6 +190,7 @@ func Parse(line string) (Cmder, error) {
deleteUsage,
letUsage,
optionUsage,
loadDescriptorsUsage,
helpUsage,
exitUsage,
}, "\n\n"))
Expand Down
6 changes: 6 additions & 0 deletions repl/commands_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -178,6 +178,12 @@ func TestParse(t *testing.T) {
optional language features.
%option --container 'google.protobuf'
%option --extension 'all'
LoadDescriptors loads a protobuf descriptor file (google.protobuf.FileDescriptorSet)
from disk or from a predefined package. Supported packages are "cel-spec-test-types"
(TestAllTypes) and "google-rpc" (AttributeContext).
%load_descriptors 'path/to/descriptor_set.binarypb'
%load_descriptors --pkg 'cel-spec-test-types'
Help prints usage information for the commands supported by the REPL.
%help
Expand Down
111 changes: 99 additions & 12 deletions repl/evaluator.go
Original file line number Diff line number Diff line change
Expand Up @@ -31,8 +31,13 @@ import (

"google.golang.org/protobuf/encoding/prototext"
"google.golang.org/protobuf/proto"
"google.golang.org/protobuf/reflect/protodesc"
"google.golang.org/protobuf/reflect/protoreflect"

test2pb "github.com/google/cel-spec/proto/test/v1/proto2/test_all_types"
test3pb "github.com/google/cel-spec/proto/test/v1/proto3/test_all_types"
exprpb "google.golang.org/genproto/googleapis/api/expr/v1alpha1"
attrpb "google.golang.org/genproto/googleapis/rpc/context/attribute_context"
descpb "google.golang.org/protobuf/types/descriptorpb"
)

Expand Down Expand Up @@ -656,12 +661,17 @@ func (e *Evaluator) applyContext() (*cel.Env, interpreter.Activation, error) {

// typeOption implements optioner for loading a set of types defined by a protobuf file descriptor set.
type typeOption struct {
path string
fds *descpb.FileDescriptorSet
path string
fds *descpb.FileDescriptorSet
isPkg bool
}

func (o *typeOption) String() string {
return fmt.Sprintf("%%load_descriptors '%s'", o.path)
flags := ""
if o.isPkg {
flags = "--pkg"
}
return fmt.Sprintf("%%load_descriptors %s '%s'", flags, o.path)
}

func (o *typeOption) Option() cel.EnvOption {
Expand Down Expand Up @@ -826,22 +836,50 @@ func loadFileDescriptorSet(path string, textfmt bool) (*descpb.FileDescriptorSet
return &fds, nil
}

func (e *Evaluator) loadDescriptors(args []string) error {
if len(args) < 1 {
return errors.New("expected path for load descriptors")
func deps(d protoreflect.FileDescriptor) []*descpb.FileDescriptorProto {
var descriptorProtos []*descpb.FileDescriptorProto

for i := 0; i < d.Imports().Len(); i++ {
descriptorProtos = append(descriptorProtos,
protodesc.ToFileDescriptorProto(d.Imports().Get(i)))
}

textfmt := true
return descriptorProtos
}

flags := args[:len(args)-1]
func (e *Evaluator) loadDescriptorFromPackage(pkg string) error {
if pkg == "cel-spec-test-types" {
fdp := (&test2pb.TestAllTypes{}).ProtoReflect().Type().Descriptor().ParentFile()
fdp2 := (&test3pb.TestAllTypes{}).ProtoReflect().Type().Descriptor().ParentFile()

for _, flag := range flags {
if flag == "--binarypb" {
textfmt = false
descriptorProtos := deps(fdp)

descriptorProtos = append(descriptorProtos,
protodesc.ToFileDescriptorProto(fdp),
protodesc.ToFileDescriptorProto(fdp2))

fds := descpb.FileDescriptorSet{
File: descriptorProtos,
}

return e.AddOption(&typeOption{pkg, &fds, true})
} else if pkg == "google-rpc" {
fdp := (&attrpb.AttributeContext{}).ProtoReflect().Type().Descriptor().ParentFile()

descriptorProtos := append(deps(fdp),
protodesc.ToFileDescriptorProto(fdp))

fds := descpb.FileDescriptorSet{
File: descriptorProtos,
}

return e.AddOption(&typeOption{pkg, &fds, true})
}

p := args[len(args)-1]
return fmt.Errorf("unknown type package: '%s'", pkg)
}

func (e *Evaluator) loadDescriptorFromFile(p string, textfmt bool) error {
fds, err := loadFileDescriptorSet(p, textfmt)
if err != nil {
return fmt.Errorf("error loading file: %v", err)
Expand All @@ -850,6 +888,55 @@ func (e *Evaluator) loadDescriptors(args []string) error {
return e.AddOption(&typeOption{path: p, fds: fds})
}

func (e *Evaluator) loadDescriptors(args []string) error {
if len(args) < 1 {
return errors.New("expected args for load descriptors")
}

textfmt := true

var paths []string
var pkgs []string
nextIsPkg := false
for _, flag := range args {
switch flag {
case "--binarypb":
{
textfmt = false
}
case "--pkg":
{
nextIsPkg = true
}
default:
{
if nextIsPkg {
pkgs = append(pkgs, flag)
nextIsPkg = false
} else {
paths = append(paths, flag)
}
}
}
}

for _, p := range paths {
err := e.loadDescriptorFromFile(p, textfmt)
if err != nil {
return err
}
}

for _, p := range pkgs {
err := e.loadDescriptorFromPackage(p)
if err != nil {
return err
}
}

return nil
}

// Process processes the command provided.
func (e *Evaluator) Process(cmd Cmder) (string, bool, error) {
switch cmd := cmd.(type) {
Expand Down
Loading

0 comments on commit 7f70747

Please sign in to comment.