feat: kubesphere 4.0 (#6115)

* feat: kubesphere 4.0

Signed-off-by: ci-bot <ci-bot@kubesphere.io>

* feat: kubesphere 4.0

Signed-off-by: ci-bot <ci-bot@kubesphere.io>

---------

Signed-off-by: ci-bot <ci-bot@kubesphere.io>
Co-authored-by: ks-ci-bot <ks-ci-bot@example.com>
Co-authored-by: joyceliu <joyceliu@yunify.com>
This commit is contained in:
KubeSphere CI Bot
2024-09-06 11:05:52 +08:00
committed by GitHub
parent b5015ec7b9
commit 447a51f08b
8557 changed files with 546695 additions and 1146174 deletions

View File

@@ -9,13 +9,14 @@ import (
"io"
"io/ioutil"
"log"
"math"
"math/big"
"sort"
"strings"
"sync/atomic"
"time"
"unicode"
"unicode/utf8"
"unsafe"
"go.starlark.net/internal/compile"
"go.starlark.net/internal/spell"
@@ -46,6 +47,21 @@ type Thread struct {
// See example_test.go for some example implementations of Load.
Load func(thread *Thread, module string) (StringDict, error)
// OnMaxSteps is called when the thread reaches the limit set by SetMaxExecutionSteps.
// The default behavior is to call thread.Cancel("too many steps").
OnMaxSteps func(thread *Thread)
// Steps a count of abstract computation steps executed
// by this thread. It is incremented by the interpreter. It may be used
// as a measure of the approximate cost of Starlark execution, by
// computing the difference in its value before and after a computation.
//
// The precise meaning of "step" is not specified and may change.
Steps, maxSteps uint64
// cancelReason records the reason from the first call to Cancel.
cancelReason *string
// locals holds arbitrary "thread-local" Go values belonging to the client.
// They are accessible to the client but not to any Starlark program.
locals map[string]interface{}
@@ -54,6 +70,42 @@ type Thread struct {
proftime time.Duration
}
// ExecutionSteps returns the current value of Steps.
func (thread *Thread) ExecutionSteps() uint64 {
return thread.Steps
}
// SetMaxExecutionSteps sets a limit on the number of Starlark
// computation steps that may be executed by this thread. If the
// thread's step counter exceeds this limit, the interpreter calls
// the optional OnMaxSteps function or the default behavior
// of calling thread.Cancel("too many steps").
func (thread *Thread) SetMaxExecutionSteps(max uint64) {
thread.maxSteps = max
}
// Uncancel resets the cancellation state.
//
// Unlike most methods of Thread, it is safe to call Uncancel from any
// goroutine, even if the thread is actively executing.
func (thread *Thread) Uncancel() {
atomic.StorePointer((*unsafe.Pointer)(unsafe.Pointer(&thread.cancelReason)), nil)
}
// Cancel causes execution of Starlark code in the specified thread to
// promptly fail with an EvalError that includes the specified reason.
// There may be a delay before the interpreter observes the cancellation
// if the thread is currently in a call to a built-in function.
//
// Call [Uncancel] to reset the cancellation state.
//
// Unlike most methods of Thread, it is safe to call Cancel from any
// goroutine, even if the thread is actively executing.
func (thread *Thread) Cancel(reason string) {
// Atomically set cancelReason, preserving earlier reason if any.
atomic.CompareAndSwapPointer((*unsafe.Pointer)(unsafe.Pointer(&thread.cancelReason)), nil, unsafe.Pointer(&reason))
}
// SetLocal sets the thread-local value associated with the specified key.
// It must not be called after execution begins.
func (thread *Thread) SetLocal(key string, value interface{}) {
@@ -178,7 +230,9 @@ func (stack *CallStack) Pop() CallFrame {
// String returns a user-friendly description of the stack.
func (stack CallStack) String() string {
out := new(strings.Builder)
fmt.Fprintf(out, "Traceback (most recent call last):\n")
if len(stack) > 0 {
fmt.Fprintf(out, "Traceback (most recent call last):\n")
}
for _, fr := range stack {
fmt.Fprintf(out, " %s: in %s\n", fr.Pos, fr.Name)
}
@@ -220,7 +274,15 @@ func (e *EvalError) Error() string { return e.Msg }
// Backtrace returns a user-friendly error message describing the stack
// of calls that led to this error.
func (e *EvalError) Backtrace() string {
return fmt.Sprintf("%sError: %s", e.CallStack, e.Msg)
// If the topmost stack frame is a built-in function,
// remove it from the stack and add print "Error in fn:".
stack := e.CallStack
suffix := ""
if last := len(stack) - 1; last >= 0 && stack[last].Pos.Filename() == builtinFilename {
suffix = " in " + stack[last].Name
stack = stack[:last]
}
return fmt.Sprintf("%sError%s: %s", stack, suffix, e.Msg)
}
func (e *EvalError) Unwrap() error { return e.cause }
@@ -429,6 +491,8 @@ func makeToplevelFunction(prog *compile.Program, predeclared StringDict) *Functi
v = MakeBigInt(c)
case string:
v = String(c)
case compile.Bytes:
v = Bytes(c)
case float64:
v = Float(c)
default:
@@ -674,14 +738,22 @@ func Binary(op syntax.Token, x, y Value) (Value, error) {
case Int:
return x.Add(y), nil
case Float:
return x.Float() + y, nil
xf, err := x.finiteFloat()
if err != nil {
return nil, err
}
return xf + y, nil
}
case Float:
switch y := y.(type) {
case Float:
return x + y, nil
case Int:
return x + y.Float(), nil
yf, err := y.finiteFloat()
if err != nil {
return nil, err
}
return x + yf, nil
}
case *List:
if y, ok := y.(*List); ok {
@@ -706,14 +778,22 @@ func Binary(op syntax.Token, x, y Value) (Value, error) {
case Int:
return x.Sub(y), nil
case Float:
return x.Float() - y, nil
xf, err := x.finiteFloat()
if err != nil {
return nil, err
}
return xf - y, nil
}
case Float:
switch y := y.(type) {
case Float:
return x - y, nil
case Int:
return x - y.Float(), nil
yf, err := y.finiteFloat()
if err != nil {
return nil, err
}
return x - yf, nil
}
}
@@ -724,9 +804,15 @@ func Binary(op syntax.Token, x, y Value) (Value, error) {
case Int:
return x.Mul(y), nil
case Float:
return x.Float() * y, nil
xf, err := x.finiteFloat()
if err != nil {
return nil, err
}
return xf * y, nil
case String:
return stringRepeat(y, x)
case Bytes:
return bytesRepeat(y, x)
case *List:
elems, err := tupleRepeat(Tuple(y.elems), x)
if err != nil {
@@ -741,12 +827,20 @@ func Binary(op syntax.Token, x, y Value) (Value, error) {
case Float:
return x * y, nil
case Int:
return x * y.Float(), nil
yf, err := y.finiteFloat()
if err != nil {
return nil, err
}
return x * yf, nil
}
case String:
if y, ok := y.(Int); ok {
return stringRepeat(x, y)
}
case Bytes:
if y, ok := y.(Int); ok {
return bytesRepeat(x, y)
}
case *List:
if y, ok := y.(Int); ok {
elems, err := tupleRepeat(Tuple(x.elems), y)
@@ -765,30 +859,40 @@ func Binary(op syntax.Token, x, y Value) (Value, error) {
case syntax.SLASH:
switch x := x.(type) {
case Int:
xf, err := x.finiteFloat()
if err != nil {
return nil, err
}
switch y := y.(type) {
case Int:
yf := y.Float()
if yf == 0.0 {
return nil, fmt.Errorf("real division by zero")
yf, err := y.finiteFloat()
if err != nil {
return nil, err
}
return x.Float() / yf, nil
if yf == 0.0 {
return nil, fmt.Errorf("floating-point division by zero")
}
return xf / yf, nil
case Float:
if y == 0.0 {
return nil, fmt.Errorf("real division by zero")
return nil, fmt.Errorf("floating-point division by zero")
}
return x.Float() / y, nil
return xf / y, nil
}
case Float:
switch y := y.(type) {
case Float:
if y == 0.0 {
return nil, fmt.Errorf("real division by zero")
return nil, fmt.Errorf("floating-point division by zero")
}
return x / y, nil
case Int:
yf := y.Float()
yf, err := y.finiteFloat()
if err != nil {
return nil, err
}
if yf == 0.0 {
return nil, fmt.Errorf("real division by zero")
return nil, fmt.Errorf("floating-point division by zero")
}
return x / yf, nil
}
@@ -804,10 +908,14 @@ func Binary(op syntax.Token, x, y Value) (Value, error) {
}
return x.Div(y), nil
case Float:
xf, err := x.finiteFloat()
if err != nil {
return nil, err
}
if y == 0.0 {
return nil, fmt.Errorf("floored division by zero")
}
return floor((x.Float() / y)), nil
return floor(xf / y), nil
}
case Float:
switch y := y.(type) {
@@ -817,7 +925,10 @@ func Binary(op syntax.Token, x, y Value) (Value, error) {
}
return floor(x / y), nil
case Int:
yf := y.Float()
yf, err := y.finiteFloat()
if err != nil {
return nil, err
}
if yf == 0.0 {
return nil, fmt.Errorf("floored division by zero")
}
@@ -835,23 +946,31 @@ func Binary(op syntax.Token, x, y Value) (Value, error) {
}
return x.Mod(y), nil
case Float:
if y == 0 {
return nil, fmt.Errorf("float modulo by zero")
xf, err := x.finiteFloat()
if err != nil {
return nil, err
}
return x.Float().Mod(y), nil
if y == 0 {
return nil, fmt.Errorf("floating-point modulo by zero")
}
return xf.Mod(y), nil
}
case Float:
switch y := y.(type) {
case Float:
if y == 0.0 {
return nil, fmt.Errorf("float modulo by zero")
return nil, fmt.Errorf("floating-point modulo by zero")
}
return Float(math.Mod(float64(x), float64(y))), nil
return x.Mod(y), nil
case Int:
if y.Sign() == 0 {
return nil, fmt.Errorf("float modulo by zero")
return nil, fmt.Errorf("floating-point modulo by zero")
}
return x.Mod(y.Float()), nil
yf, err := y.finiteFloat()
if err != nil {
return nil, err
}
return x.Mod(yf), nil
}
case String:
return interpolate(string(x), y)
@@ -898,6 +1017,19 @@ func Binary(op syntax.Token, x, y Value) (Value, error) {
return nil, fmt.Errorf("'in <string>' requires string as left operand, not %s", x.Type())
}
return Bool(strings.Contains(string(y), string(needle))), nil
case Bytes:
switch needle := x.(type) {
case Bytes:
return Bool(strings.Contains(string(y), string(needle))), nil
case Int:
var b byte
if err := AsInt(needle, &b); err != nil {
return nil, fmt.Errorf("int in bytes: %s", err)
}
return Bool(strings.IndexByte(string(y), b) >= 0), nil
default:
return nil, fmt.Errorf("'in bytes' requires bytes or int as left operand, not %s", x.Type())
}
case rangeValue:
i, err := NumberToInt(x)
if err != nil {
@@ -912,6 +1044,12 @@ func Binary(op syntax.Token, x, y Value) (Value, error) {
if y, ok := y.(Int); ok {
return x.Or(y), nil
}
case *Dict: // union
if y, ok := y.(*Dict); ok {
return x.Union(y), nil
}
case *Set: // union
if y, ok := y.(*Set); ok {
iter := Iterate(y)
@@ -932,10 +1070,10 @@ func Binary(op syntax.Token, x, y Value) (Value, error) {
if x.Len() > y.Len() {
x, y = y, x // opt: range over smaller set
}
for _, xelem := range x.elems() {
for xe := x.ht.head; xe != nil; xe = xe.next {
// Has, Insert cannot fail here.
if found, _ := y.Has(xelem); found {
set.Insert(xelem)
if found, _ := y.Has(xe.key); found {
set.Insert(xe.key)
}
}
return set, nil
@@ -951,14 +1089,14 @@ func Binary(op syntax.Token, x, y Value) (Value, error) {
case *Set: // symmetric difference
if y, ok := y.(*Set); ok {
set := new(Set)
for _, xelem := range x.elems() {
if found, _ := y.Has(xelem); !found {
set.Insert(xelem)
for xe := x.ht.head; xe != nil; xe = xe.next {
if found, _ := y.Has(xe.key); !found {
set.Insert(xe.key)
}
}
for _, yelem := range y.elems() {
if found, _ := x.Has(yelem); !found {
set.Insert(yelem)
for ye := y.ht.head; ye != nil; ye = ye.next {
if found, _ := x.Has(ye.key); !found {
set.Insert(ye.key)
}
}
return set, nil
@@ -1027,7 +1165,8 @@ func tupleRepeat(elems Tuple, n Int) (Tuple, error) {
// Inv: i > 0, len > 0
sz := len(elems) * i
if sz < 0 || sz >= maxAlloc { // sz < 0 => overflow
return nil, fmt.Errorf("excessive repeat (%d elements)", sz)
// Don't print sz.
return nil, fmt.Errorf("excessive repeat (%d * %d elements)", len(elems), i)
}
res := make([]Value, sz)
// copy elems into res, doubling each time
@@ -1039,6 +1178,11 @@ func tupleRepeat(elems Tuple, n Int) (Tuple, error) {
return res, nil
}
func bytesRepeat(b Bytes, n Int) (Bytes, error) {
res, err := stringRepeat(String(b), n)
return Bytes(res), err
}
func stringRepeat(s String, n Int) (String, error) {
if s == "" {
return "", nil
@@ -1053,7 +1197,8 @@ func stringRepeat(s String, n Int) (String, error) {
// Inv: i > 0, len > 0
sz := len(s) * i
if sz < 0 || sz >= maxAlloc { // sz < 0 => overflow
return "", fmt.Errorf("excessive repeat (%d elements)", sz)
// Don't print sz.
return "", fmt.Errorf("excessive repeat (%d * %d elements)", len(s), i)
}
return String(strings.Repeat(string(s), i)), nil
}
@@ -1075,13 +1220,35 @@ func Call(thread *Thread, fn Value, args Tuple, kwargs []Tuple) (Value, error) {
if fr == nil {
fr = new(frame)
}
if thread.stack == nil {
// one-time initialization of thread
if thread.maxSteps == 0 {
thread.maxSteps-- // (MaxUint64)
}
}
thread.stack = append(thread.stack, fr) // push
fr.callable = c
thread.beginProfSpan()
// Use defer to ensure that panics from built-ins
// pass through the interpreter without leaving
// it in a bad state.
defer func() {
thread.endProfSpan()
// clear out any references
// TODO(adonovan): opt: zero fr.Locals and
// reuse it if it is large enough.
*fr = frame{}
thread.stack = thread.stack[:len(thread.stack)-1] // pop
}()
result, err := c.CallInternal(thread, args, kwargs)
thread.endProfSpan()
// Sanity check: nil is not a valid Starlark value.
if result == nil && err == nil {
@@ -1095,9 +1262,6 @@ func Call(thread *Thread, fn Value, args Tuple, kwargs []Tuple) (Value, error) {
}
}
*fr = frame{} // clear out any references
thread.stack = thread.stack[:len(thread.stack)-1] // pop
return result, err
}
@@ -1113,7 +1277,7 @@ func slice(x, lo, hi, step_ Value) (Value, error) {
var err error
step, err = AsInt32(step_)
if err != nil {
return nil, fmt.Errorf("got %s for slice step, want int", step_.Type())
return nil, fmt.Errorf("invalid slice step: %s", err)
}
if step == 0 {
return nil, fmt.Errorf("zero is not a valid slice step")
@@ -1207,7 +1371,7 @@ func asIndex(v Value, len int, result *int) error {
var err error
*result, err = AsInt32(v)
if err != nil {
return fmt.Errorf("got %s, want int", v.Type())
return err
}
if *result < 0 {
*result += len
@@ -1448,20 +1612,7 @@ func interpolate(format string, x Value) (Value, error) {
if !ok {
return nil, fmt.Errorf("%%%c format requires float, not %s", c, arg.Type())
}
switch c {
case 'e':
fmt.Fprintf(buf, "%e", f)
case 'f':
fmt.Fprintf(buf, "%f", f)
case 'g':
fmt.Fprintf(buf, "%g", f)
case 'E':
fmt.Fprintf(buf, "%E", f)
case 'F':
fmt.Fprintf(buf, "%F", f)
case 'G':
fmt.Fprintf(buf, "%G", f)
}
Float(f).format(buf, c)
case 'c':
switch arg := arg.(type) {
case Int: