1
0
Fork 0

Adding upstream version 1.34.4.

Signed-off-by: Daniel Baumann <daniel@debian.org>
This commit is contained in:
Daniel Baumann 2025-05-24 07:26:29 +02:00
parent e393c3af3f
commit 4978089aab
Signed by: daniel
GPG key ID: FBB4F0E80A80222F
4963 changed files with 677545 additions and 0 deletions

View file

@ -0,0 +1,308 @@
package starlark
import (
"errors"
"fmt"
"reflect"
"strings"
"go.starlark.net/starlark"
"github.com/influxdata/telegraf"
)
// FieldDict is a starlark.Value for the metric fields. It is heavily based on the
// starlark.Dict.
type FieldDict struct {
*Metric
}
func (d FieldDict) String() string {
buf := new(strings.Builder)
buf.WriteString("{")
sep := ""
for _, item := range d.Items() {
k, v := item[0], item[1]
buf.WriteString(sep)
buf.WriteString(k.String())
buf.WriteString(": ")
buf.WriteString(v.String())
sep = ", "
}
buf.WriteString("}")
return buf.String()
}
func (FieldDict) Type() string {
return "Fields"
}
func (d FieldDict) Freeze() {
// Disable linter check as the frozen variable is modified despite
// passing a value instead of a pointer, because `FieldDict` holds
// a pointer to the underlying metric containing the `frozen` field.
//revive:disable:modifies-value-receiver
d.frozen = true
}
func (d FieldDict) Truth() starlark.Bool {
return len(d.metric.FieldList()) != 0
}
func (FieldDict) Hash() (uint32, error) {
return 0, errors.New("not hashable")
}
// AttrNames implements the starlark.HasAttrs interface.
func (FieldDict) AttrNames() []string {
return builtinAttrNames(FieldDictMethods)
}
// Attr implements the starlark.HasAttrs interface.
func (d FieldDict) Attr(name string) (starlark.Value, error) {
return builtinAttr(d, name, FieldDictMethods)
}
var FieldDictMethods = map[string]builtinMethod{
"clear": dictClear,
"get": dictGet,
"items": dictItems,
"keys": dictKeys,
"pop": dictPop,
"popitem": dictPopitem,
"setdefault": dictSetdefault,
"update": dictUpdate,
"values": dictValues,
}
// Get implements the starlark.Mapping interface.
func (d FieldDict) Get(key starlark.Value) (v starlark.Value, found bool, err error) {
if k, ok := key.(starlark.String); ok {
gv, found := d.metric.GetField(k.GoString())
if !found {
return starlark.None, false, nil
}
v, err := asStarlarkValue(gv)
if err != nil {
return starlark.None, false, err
}
return v, true, nil
}
return starlark.None, false, errors.New("key must be of type 'str'")
}
// SetKey implements the starlark.HasSetKey interface to support map update
// using x[k]=v syntax, like a dictionary.
func (d FieldDict) SetKey(k, v starlark.Value) error {
if d.fieldIterCount > 0 {
return errors.New("cannot insert during iteration")
}
key, ok := k.(starlark.String)
if !ok {
return errors.New("field key must be of type 'str'")
}
gv, err := asGoValue(v)
if err != nil {
return err
}
d.metric.AddField(key.GoString(), gv)
return nil
}
// Items implements the starlark.IterableMapping interface.
func (d FieldDict) Items() []starlark.Tuple {
items := make([]starlark.Tuple, 0, len(d.metric.FieldList()))
for _, field := range d.metric.FieldList() {
key := starlark.String(field.Key)
sv, err := asStarlarkValue(field.Value)
if err != nil {
continue
}
pair := starlark.Tuple{key, sv}
items = append(items, pair)
}
return items
}
func (d FieldDict) Clear() error {
if d.fieldIterCount > 0 {
return errors.New("cannot delete during iteration")
}
keys := make([]string, 0, len(d.metric.FieldList()))
for _, field := range d.metric.FieldList() {
keys = append(keys, field.Key)
}
for _, key := range keys {
d.metric.RemoveField(key)
}
return nil
}
func (d FieldDict) PopItem() (starlark.Value, error) {
if d.fieldIterCount > 0 {
return nil, errors.New("cannot delete during iteration")
}
if len(d.metric.FieldList()) == 0 {
return nil, errors.New("popitem(): field dictionary is empty")
}
field := d.metric.FieldList()[0]
k := field.Key
v := field.Value
d.metric.RemoveField(k)
sk := starlark.String(k)
sv, err := asStarlarkValue(v)
if err != nil {
return nil, errors.New("could not convert to starlark value")
}
return starlark.Tuple{sk, sv}, nil
}
func (d FieldDict) Delete(k starlark.Value) (v starlark.Value, found bool, err error) {
if d.fieldIterCount > 0 {
return nil, false, errors.New("cannot delete during iteration")
}
if key, ok := k.(starlark.String); ok {
value, ok := d.metric.GetField(key.GoString())
if ok {
d.metric.RemoveField(key.GoString())
sv, err := asStarlarkValue(value)
return sv, ok, err
}
return starlark.None, false, nil
}
return starlark.None, false, errors.New("key must be of type 'str'")
}
// Iterate implements the starlark.Iterator interface.
func (d FieldDict) Iterate() starlark.Iterator {
d.fieldIterCount++
return &FieldIterator{Metric: d.Metric, fields: d.metric.FieldList()}
}
type FieldIterator struct {
*Metric
fields []*telegraf.Field
}
// Next implements the starlark.Iterator interface.
func (i *FieldIterator) Next(p *starlark.Value) bool {
if len(i.fields) == 0 {
return false
}
field := i.fields[0]
i.fields = i.fields[1:]
*p = starlark.String(field.Key)
return true
}
// Done implements the starlark.Iterator interface.
func (i *FieldIterator) Done() {
i.fieldIterCount--
}
// AsStarlarkValue converts a field value to a starlark.Value.
func asStarlarkValue(value interface{}) (starlark.Value, error) {
v := reflect.ValueOf(value)
switch v.Kind() {
case reflect.Slice:
length := v.Len()
array := make([]starlark.Value, 0, length)
for i := 0; i < length; i++ {
sVal, err := asStarlarkValue(v.Index(i).Interface())
if err != nil {
return starlark.None, err
}
array = append(array, sVal)
}
return starlark.NewList(array), nil
case reflect.Map:
dict := starlark.NewDict(v.Len())
iter := v.MapRange()
for iter.Next() {
sKey, err := asStarlarkValue(iter.Key().Interface())
if err != nil {
return starlark.None, err
}
sValue, err := asStarlarkValue(iter.Value().Interface())
if err != nil {
return starlark.None, err
}
if err := dict.SetKey(sKey, sValue); err != nil {
return starlark.None, err
}
}
return dict, nil
case reflect.Float32, reflect.Float64:
return starlark.Float(v.Float()), nil
case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64:
return starlark.MakeInt64(v.Int()), nil
case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64:
return starlark.MakeUint64(v.Uint()), nil
case reflect.String:
return starlark.String(v.String()), nil
case reflect.Bool:
return starlark.Bool(v.Bool()), nil
}
return nil, fmt.Errorf("invalid type %T", value)
}
// AsGoValue converts a starlark.Value to a field value.
func asGoValue(value interface{}) (interface{}, error) {
switch v := value.(type) {
case starlark.Float:
return float64(v), nil
case starlark.Int:
n, ok := v.Int64()
if !ok {
return nil, fmt.Errorf("cannot represent integer %v as int64", v)
}
return n, nil
case starlark.String:
return string(v), nil
case starlark.Bool:
return bool(v), nil
}
return nil, fmt.Errorf("invalid starlark type %T", value)
}
// ToFields converts a starlark.Value to a map of values.
func toFields(value starlark.Value) (map[string]interface{}, error) {
if value == nil {
return nil, nil
}
items, err := items(value, "The type %T is unsupported as type of collection of fields")
if err != nil {
return nil, err
}
result := make(map[string]interface{}, len(items))
for _, item := range items {
key, err := toString(item[0], "The type %T is unsupported as type of key for fields")
if err != nil {
return nil, err
}
value, err := asGoValue(item[1])
if err != nil {
return nil, err
}
result[key] = value
}
return result, nil
}