github.com/tilt-dev/tilt@v0.33.15-0.20240515162809-0a22ed45d8a0/internal/tiltfile/loaddynamic/load.go (about)

     1  package loaddynamic
     2  
     3  import (
     4  	"go.starlark.net/starlark"
     5  
     6  	"github.com/tilt-dev/tilt/internal/tiltfile/starkit"
     7  	"github.com/tilt-dev/tilt/internal/tiltfile/value"
     8  )
     9  
    10  // Implements the load_dynamic() built-in.
    11  //
    12  // Most programming languages only support static import - where the module
    13  // being loaded and the local variables being bound must be determinable at
    14  // compile-time (i.e., without executing the code).
    15  //
    16  // Dynamic import tends to be fairly contentious. Here's a good discussion on the topic:
    17  //
    18  // https://github.com/tc39/proposal-dynamic-import
    19  //
    20  // (TC39 - the JavaScript committee - is a generally good resource for
    21  // programming language theory discussion, because there are so many open-source
    22  // implementations of the core language.)
    23  //
    24  // load_dynamic() provides a dynamic import, with semantics similar to nodejs
    25  // require(), where it returns a dictionary of symbols that can be introspected
    26  // on. It does no binding of local variables.
    27  type LoadDynamicFn struct {
    28  }
    29  
    30  func NewPlugin() LoadDynamicFn {
    31  	return LoadDynamicFn{}
    32  }
    33  
    34  func (LoadDynamicFn) OnStart(e *starkit.Environment) error {
    35  	return e.AddBuiltin("load_dynamic", loadDynamic)
    36  }
    37  
    38  func loadDynamic(t *starlark.Thread, fn *starlark.Builtin, args starlark.Tuple, kwargs []starlark.Tuple) (starlark.Value, error) {
    39  	var p value.Stringable
    40  	err := starkit.UnpackArgs(t, fn.Name(), args, kwargs, "path", &p)
    41  	if err != nil {
    42  		return nil, err
    43  	}
    44  
    45  	module, err := t.Load(t, p.Value)
    46  	if err != nil {
    47  		return nil, err
    48  	}
    49  
    50  	dict := starlark.NewDict(len(module))
    51  	for key, val := range module {
    52  		err = dict.SetKey(starlark.String(key), val)
    53  		if err != nil {
    54  			return nil, err
    55  		}
    56  	}
    57  	dict.Freeze()
    58  	return dict, err
    59  }