luci: go.chromium.org/luci/starlark/builtins Index | Files

package builtins

import "go.chromium.org/luci/starlark/builtins"

Package builtins is a collection of potentially useful Starlark builtins.

Index

Package Files

doc.go fail.go regexp.go stacktrace.go struct.go to_json.go

Variables

var (
    // Struct is struct(**kwargs) builtin.
    //
    //  def struct(**kwargs):
    //    """Returns an immutable object with fields set to given values."""
    Struct = starlark.NewBuiltin("struct", starlarkstruct.Make)

    // GenStruct is genstruct(name) builtin.
    //
    //  def genstruct(name):
    //    """Returns a callable constructor for "branded" struct instances."""
    GenStruct = starlark.NewBuiltin("genstruct", func(_ *starlark.Thread, _ *starlark.Builtin, args starlark.Tuple, kwargs []starlark.Tuple) (starlark.Value, error) {
        var name string
        if err := starlark.UnpackArgs("genstruct", args, kwargs, "name", &name); err != nil {
            return nil, err
        }
        return &ctor{name: name}, nil
    })

    // Ctor is ctor(obj) builtin.
    //
    //  def ctor(obj):
    //    """Returns a constructor used to construct this struct or None."""
    Ctor = starlark.NewBuiltin("ctor", func(_ *starlark.Thread, _ *starlark.Builtin, args starlark.Tuple, kwargs []starlark.Tuple) (starlark.Value, error) {
        var obj starlark.Value
        if err := starlark.UnpackArgs("ctor", args, kwargs, "obj", &obj); err != nil {
            return nil, err
        }
        if st, ok := obj.(*starlarkstruct.Struct); ok {
            return st.Constructor(), nil
        }
        return starlark.None, nil
    })
)
var Fail = starlark.NewBuiltin("fail", func(th *starlark.Thread, _ *starlark.Builtin, args starlark.Tuple, kwargs []starlark.Tuple) (starlark.Value, error) {
    sep := " "
    var trace starlark.Value
    err := starlark.UnpackArgs("fail", nil, kwargs,
        "sep?", &sep,
        "trace?", &trace)
    if err != nil {
        return nil, err
    }

    var userTrace *CapturedStacktrace
    if trace != nil && trace != starlark.None {
        if userTrace, _ = trace.(*CapturedStacktrace); userTrace == nil {
            return nil, fmt.Errorf("fail: bad 'trace' - got %s, expecting stacktrace", trace.Type())
        }
    }

    buf := strings.Builder{}
    for i, v := range args {
        if i > 0 {
            buf.WriteString(sep)
        }
        if s, ok := starlark.AsString(v); ok {
            buf.WriteString(s)
        } else {
            buf.WriteString(v.String())
        }
    }
    msg := buf.String()

    if fc := GetFailureCollector(th); fc != nil {
        failTrace, _ := CaptureStacktrace(th, 0)
        fc.failure = &Failure{
            Message:   msg,
            UserTrace: userTrace,
            FailTrace: failTrace,
        }
    }

    return nil, errors.New(msg)
})

Fail is fail(*args, sep=" ", trace=None) builtin.

def fail(*args, sep=" ", trace=None):
  """Aborts the script execution with an error message."

  Args:
    args: values to print in the message.
    sep: separator to use between values from `args`.
    trace: a trace (as returned by stacktrace()) to attach to the error.
  """

Custom stack traces are recoverable through FailureCollector. This is due to Starlark's insistence on stringying all errors. If there's no FailureCollector in the thread locals, custom traces are silently ignored.

Note that the assert.fails(...) check in the default starlark tests library doesn't clear the failure collector state when it "catches" an error, so tests that use assert.fails(...) should be careful with using the failure collector (or just don't use it at all).

var Stacktrace = starlark.NewBuiltin("stacktrace", func(th *starlark.Thread, _ *starlark.Builtin, args starlark.Tuple, kwargs []starlark.Tuple) (starlark.Value, error) {
    skip := starlark.MakeInt(0)
    if err := starlark.UnpackArgs("stacktrace", args, kwargs, "skip?", &skip); err != nil {
        return nil, err
    }
    switch lvl, err := starlark.AsInt32(skip); {
    case err != nil:
        return nil, fmt.Errorf("stacktrace: bad 'skip' value %s - %s", skip, err)
    case lvl < 0:
        return nil, fmt.Errorf("stacktrace: bad 'skip' value %d - must be non-negative", lvl)
    default:
        return CaptureStacktrace(th, lvl)
    }
})

Stacktrace is stacktrace(...) builtin.

def stacktrace(skip=0):
  """Capture and returns a stack trace of the caller.

  A captured stacktrace is an opaque object that can be stringified to get a
  nice looking trace (e.g. for error messages).

  Args:
    skip: how many inner most frames to skip.
  """
var ToJSON = starlark.NewBuiltin("to_json", func(_ *starlark.Thread, fn *starlark.Builtin, args starlark.Tuple, kwargs []starlark.Tuple) (starlark.Value, error) {
    var v starlark.Value
    if err := starlark.UnpackPositionalArgs(fn.Name(), args, kwargs, 1, &v); err != nil {
        return nil, err
    }
    obj, err := toGoNative(v, visitingSet{})
    if err != nil {
        return nil, err
    }
    blob, err := json.Marshal(obj)
    if err != nil {
        return nil, err
    }
    return starlark.String(blob), nil
})

ToJSON is to_json(value) builtin.

def to_json(value):
  """Serializes a value to compact JSON.

  Doesn't support integers that do not fit int64. Fails if the value being
  converted has cycles.

  Args:
    value: a starlark value: scalars, lists, tuples, dicts containing only
      starlark values.

  Returns:
    A string with its compact JSON serialization.
  """

func NormalizeStacktrace Uses

func NormalizeStacktrace(trace string) string

NormalizeStacktrace removes mentions of line and column numbers from a rendered stack trace: "main:1:5: in <toplevel>" => "main: in <toplevel>".

Useful when comparing stack traces in tests to make the comparison less brittle.

func RegexpMatcher Uses

func RegexpMatcher(name string) *starlark.Builtin

RegexpMatcher returns a function (with given name) that allows Starlark code to do regular expression matches:

def submatches(pattern, str):
  """Returns a tuple of submatches with the leftmost match of the regular
  expression.

  The returned tuple has the full match as a first item, followed by
  subexpression matches.

  If the string doesn't match the expression returns an empty tuple. Fails if
  the regular expression can't be compiled.
  """

Uses Go regexp engine, which is slightly different from Python's. API also explicitly does NOT try to mimic Python's 're' module.

Each separate instance of the builtin holds a cache of compiled regular expressions internally. The cache is never cleaned up. Errors are not cached, since we don't expect to see them often.

Safe for concurrent use.

type CapturedStacktrace Uses

type CapturedStacktrace struct {
    // contains filtered or unexported fields
}

CapturedStacktrace represents a stack trace returned by stacktrace(...).

At the present time it can only be stringified (via str(...) in Starlark or via .String() in Go).

func CaptureStacktrace Uses

func CaptureStacktrace(th *starlark.Thread, skip int) (*CapturedStacktrace, error)

CaptureStacktrace captures thread's stack trace, skipping some number of innermost frames.

Returns an error if the stack is not deep enough to skip the requested number of frames.

func (*CapturedStacktrace) Freeze Uses

func (*CapturedStacktrace) Freeze()

Freeze is part of starlark.Value interface.

func (*CapturedStacktrace) Hash Uses

func (*CapturedStacktrace) Hash() (uint32, error)

Hash is part of starlark.Value interface.

func (*CapturedStacktrace) String Uses

func (s *CapturedStacktrace) String() string

String is part of starlark.Value interface.

Renders the stack trace as string.

func (*CapturedStacktrace) Truth Uses

func (*CapturedStacktrace) Truth() starlark.Bool

Truth is part of starlark.Value interface.

func (*CapturedStacktrace) Type Uses

func (*CapturedStacktrace) Type() string

Type is part of starlark.Value interface.

type Failure Uses

type Failure struct {
    Message   string              // the error message, as passed to fail(...)
    UserTrace *CapturedStacktrace // value of 'trace' passed to fail or nil
    FailTrace *CapturedStacktrace // where 'fail' itself was called
}

Failure is an error emitted by fail(...) and captured by FailureCollector.

func (*Failure) Backtrace Uses

func (f *Failure) Backtrace() string

Backtrace returns a user-friendly error message describing the stack of calls that led to this error.

If fail(...) was called with a custom stack trace, this trace is shown here. Otherwise the trace of where fail(...) happened is used.

func (*Failure) Error Uses

func (f *Failure) Error() string

Error is the short error message, as passed to fail(...).

type FailureCollector Uses

type FailureCollector struct {
    // contains filtered or unexported fields
}

FailureCollector receives structured error messages from fail(...).

It should be installed into Starlark thread locals (via Install) for fail(...) to be able to discover it. If it's not there, fail(...) will not return any additional information (like a custom stack trace) besides the information contained in *starlark.EvalError.

func GetFailureCollector Uses

func GetFailureCollector(th *starlark.Thread) *FailureCollector

GetFailureCollector returns a failure collector installed in the thread.

func (*FailureCollector) Clear Uses

func (fc *FailureCollector) Clear()

Clear resets the state.

Useful if the same FailureCollector is reused between calls to Starlark.

func (*FailureCollector) Install Uses

func (fc *FailureCollector) Install(t *starlark.Thread)

Install installs this failure collector into the thread.

func (*FailureCollector) LatestFailure Uses

func (fc *FailureCollector) LatestFailure() *Failure

LatestFailure returns the latest captured failure or nil if there are none.

Package builtins imports 8 packages (graph) and is imported by 6 packages. Updated 2019-10-21. Refresh now. Tools for package owners.