Skip to content

Commit

Permalink
Allow dicts to be passed in as keyword args.
Browse files Browse the repository at this point in the history
This is similar to the python ** convention that allows a dict to be
expanded into keyword args.

If a parameter is provided as the value `**` the function will replace
its args with the provided dict.

e.g.

LET Args <= dict(Foo=1)

SELECT * FROM plugin(`**`=Args)
  • Loading branch information
scudette committed Nov 19, 2024
1 parent 207766c commit 5263521
Show file tree
Hide file tree
Showing 12 changed files with 43 additions and 36 deletions.
5 changes: 0 additions & 5 deletions aliases.go
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,6 @@ import (
"context"

"github.com/Velocidex/ordereddict"
"www.velocidex.com/golang/vfilter/arg_parser"
"www.velocidex.com/golang/vfilter/functions"
"www.velocidex.com/golang/vfilter/plugins"
"www.velocidex.com/golang/vfilter/scope"
Expand Down Expand Up @@ -40,10 +39,6 @@ func NewScope() types.Scope {
return scope.NewScope()
}

func ExtractArgs(scope types.Scope, args *ordereddict.Dict, value interface{}) error {
return arg_parser.ExtractArgs(scope, args, value)
}

func RowToDict(
ctx context.Context,
scope types.Scope, row types.Row) *ordereddict.Dict {
Expand Down
36 changes: 22 additions & 14 deletions arg_parser/args.go
Original file line number Diff line number Diff line change
Expand Up @@ -33,26 +33,34 @@ import (
// field must be exported (i.e. name begins with cap) and it must have
// vfilter tags.

// Deprecate this in favor of ExtractArgsWithContext
func ExtractArgs(scope types.Scope, args *ordereddict.Dict, target interface{}) error {
v := reflect.ValueOf(target)
if v.Type().Kind() == reflect.Ptr {
v = v.Elem()
}
// Allow the caller to pass args explicitly- this is similar to
// Python's ** notation:
// LET d = lazy_dict(a={....})
// SELECT * FROM plugin(`**`=d)
func NormalizeArgs(args *ordereddict.Dict) *ordereddict.Dict {
alt_args_any, pres := args.Get("**")
if pres {
lazy_arg, ok := alt_args_any.(types.LazyExpr)
if ok {
ctx := context.Background()
alt_args_any = lazy_arg.Reduce(ctx)
}

parser, err := GetParser(v)
if err != nil {
scope.Explainer().ParseArgs(args, target, err)
return err
alt_args, ok := alt_args_any.(*ordereddict.Dict)
if ok {
return alt_args
}
}

err = parser.Parse(context.Background(), scope, args, v)
scope.Explainer().ParseArgs(args, target, err)
return err
return args
}

func ExtractArgsWithContext(
ctx context.Context, scope types.Scope, args *ordereddict.Dict, target interface{}) error {
ctx context.Context, scope types.Scope,
args *ordereddict.Dict, target interface{}) error {

args = NormalizeArgs(args)

v := reflect.ValueOf(target)
if v.Type().Kind() == reflect.Ptr {
v = v.Elem()
Expand Down
10 changes: 5 additions & 5 deletions functions/aggregates.go
Original file line number Diff line number Diff line change
Expand Up @@ -116,7 +116,7 @@ func (self _CountFunction) Call(
scope types.Scope,
args *ordereddict.Dict) types.Any {
arg := &_CountFunctionArgs{}
err := arg_parser.ExtractArgs(scope, args, arg)
err := arg_parser.ExtractArgsWithContext(ctx, scope, args, arg)
if err != nil {
scope.Log("count: %s", err.Error())
return types.Null{}
Expand Down Expand Up @@ -170,7 +170,7 @@ func (self _SumFunction) Call(
scope types.Scope,
args *ordereddict.Dict) types.Any {
arg := &_SumFunctionArgs{}
err := arg_parser.ExtractArgs(scope, args, arg)
err := arg_parser.ExtractArgsWithContext(ctx, scope, args, arg)
if err != nil {
scope.Log("sum: %s", err.Error())
return types.Null{}
Expand Down Expand Up @@ -224,7 +224,7 @@ func (self _MinFunction) Call(
args *ordereddict.Dict) types.Any {
arg := &_MinFunctionArgs{}

err := arg_parser.ExtractArgs(scope, args, arg)
err := arg_parser.ExtractArgsWithContext(ctx, scope, args, arg)
if err != nil {
scope.Log("min: %s", err.Error())
return types.Null{}
Expand Down Expand Up @@ -267,7 +267,7 @@ func (self _MaxFunction) Call(
scope types.Scope,
args *ordereddict.Dict) types.Any {
arg := &_MinFunctionArgs{}
err := arg_parser.ExtractArgs(scope, args, arg)
err := arg_parser.ExtractArgsWithContext(ctx, scope, args, arg)
if err != nil {
scope.Log("min: %s", err.Error())
return types.Null{}
Expand Down Expand Up @@ -314,7 +314,7 @@ func (self _EnumerateFunction) Call(
scope types.Scope,
args *ordereddict.Dict) types.Any {
arg := &_EnumeateFunctionArgs{}
err := arg_parser.ExtractArgs(scope, args, arg)
err := arg_parser.ExtractArgsWithContext(ctx, scope, args, arg)
if err != nil {
scope.Log("enumerate: %s", err.Error())
return types.Null{}
Expand Down
2 changes: 1 addition & 1 deletion functions/format.go
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@ func (self FormatFunction) Call(ctx context.Context,
scope types.Scope,
args *ordereddict.Dict) types.Any {
arg := &FormatArgs{}
err := arg_parser.ExtractArgs(scope, args, arg)
err := arg_parser.ExtractArgsWithContext(ctx, scope, args, arg)
if err != nil {
scope.Log("format: %v", err)
return false
Expand Down
10 changes: 5 additions & 5 deletions functions/functions.go
Original file line number Diff line number Diff line change
Expand Up @@ -50,7 +50,7 @@ func (self _Timestamp) Info(scope types.Scope, type_map *types.TypeMap) *types.F

func (self _Timestamp) Call(ctx context.Context, scope types.Scope, args *ordereddict.Dict) types.Any {
arg := &_TimestampArg{}
err := arg_parser.ExtractArgs(scope, args, arg)
err := arg_parser.ExtractArgsWithContext(ctx, scope, args, arg)
if err != nil {
scope.Log("timestamp: %s", err.Error())
return types.Null{}
Expand Down Expand Up @@ -88,7 +88,7 @@ func (self _SplitFunction) Info(scope types.Scope, type_map *types.TypeMap) *typ

func (self _SplitFunction) Call(ctx context.Context, scope types.Scope, args *ordereddict.Dict) types.Any {
arg := &_SplitFunctionArgs{}
err := arg_parser.ExtractArgs(scope, args, arg)
err := arg_parser.ExtractArgsWithContext(ctx, scope, args, arg)
if err != nil {
scope.Log("split: %s", err.Error())
return types.Null{}
Expand Down Expand Up @@ -129,7 +129,7 @@ func (self _GetFunction) Call(
scope types.Scope,
args *ordereddict.Dict) types.Any {
arg := &_GetFunctionArgs{}
err := arg_parser.ExtractArgs(scope, args, arg)
err := arg_parser.ExtractArgsWithContext(ctx, scope, args, arg)
if err != nil {
scope.Log("get: %s", err.Error())
return types.Null{}
Expand Down Expand Up @@ -183,7 +183,7 @@ func (self _EncodeFunction) Call(
scope types.Scope,
args *ordereddict.Dict) types.Any {
arg := &_EncodeFunctionArgs{}
err := arg_parser.ExtractArgs(scope, args, arg)
err := arg_parser.ExtractArgsWithContext(ctx, scope, args, arg)
if err != nil {
scope.Log("hex: %s", err.Error())
return types.Null{}
Expand Down Expand Up @@ -236,7 +236,7 @@ func (self LenFunction) Call(ctx context.Context,
scope types.Scope,
args *ordereddict.Dict) types.Any {
arg := &LenFunctionArgs{}
err := arg_parser.ExtractArgs(scope, args, arg)
err := arg_parser.ExtractArgsWithContext(ctx, scope, args, arg)
if err != nil {
scope.Log("len: %s", err.Error())
return &types.Null{}
Expand Down
2 changes: 1 addition & 1 deletion functions/if.go
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,7 @@ func (self _IfFunction) Call(
args *ordereddict.Dict) types.Any {

arg := &_IfFunctionArgs{}
err := arg_parser.ExtractArgs(scope, args, arg)
err := arg_parser.ExtractArgsWithContext(ctx, scope, args, arg)
if err != nil {
scope.Log("if: %v", err)
return types.Null{}
Expand Down
2 changes: 1 addition & 1 deletion plugins/flatten.go
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@ func (self _FlattenPluginImpl) Call(ctx context.Context,
defer close(output_chan)

arg := _FlattenPluginImplArgs{}
err := arg_parser.ExtractArgs(scope, args, &arg)
err := arg_parser.ExtractArgsWithContext(ctx, scope, args, &arg)
if err != nil {
scope.Log("flatten: %v", err)
return
Expand Down
2 changes: 1 addition & 1 deletion plugins/foreach.go
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,7 @@ func (self _ForeachPluginImpl) Call(ctx context.Context,
defer close(output_chan)

arg := _ForeachPluginImplArgs{}
err := arg_parser.ExtractArgs(scope, args, &arg)
err := arg_parser.ExtractArgsWithContext(ctx, scope, args, &arg)
if err != nil {
scope.Log("foreach: %v", err)
return
Expand Down
2 changes: 1 addition & 1 deletion plugins/if.go
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@ func (self _IfPlugin) Call(
output_chan := make(chan types.Row)

arg := &_IfPluginArg{}
err := arg_parser.ExtractArgs(scope, args, arg)
err := arg_parser.ExtractArgsWithContext(ctx, scope, args, arg)
if err != nil {
scope.Log("if: %s", err.Error())
close(output_chan)
Expand Down
2 changes: 1 addition & 1 deletion plugins/range.go
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,7 @@ func (self RangePlugin) Call(
defer close(output_chan)

arg := &RangePluginArgs{}
err := arg_parser.ExtractArgs(scope, args, arg)
err := arg_parser.ExtractArgsWithContext(ctx, scope, args, arg)
if err != nil {
scope.Log("range: %v", err)
return
Expand Down
2 changes: 1 addition & 1 deletion scope/version.go
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,7 @@ func (self _GetVersion) Info(scope types.Scope, type_map *types.TypeMap) *types.
func (self _GetVersion) Call(ctx context.Context,
scope_int types.Scope, args *ordereddict.Dict) types.Any {
arg := &_GetVersion{}
err := arg_parser.ExtractArgs(scope_int, args, arg)
err := arg_parser.ExtractArgsWithContext(ctx, scope_int, args, arg)
if err != nil {
scope_int.Log("version: %s", err.Error())
return types.Null{}
Expand Down
4 changes: 4 additions & 0 deletions visitor.go
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ import (
"strings"

"www.velocidex.com/golang/vfilter/arg_parser"
"www.velocidex.com/golang/vfilter/materializer"
"www.velocidex.com/golang/vfilter/types"
)

Expand Down Expand Up @@ -256,6 +257,9 @@ func (self *Visitor) Visit(node interface{}) {
case *arg_parser.LazyExpressionWrapper:
self.Visit(t.Delegate())

case *materializer.InMemoryMatrializer:
return

default:
self.scope.Log("FormatToString: Unable to visit %T", node)
}
Expand Down

0 comments on commit 5263521

Please sign in to comment.