mirror of https://github.com/databricks/cli.git
Rename libs/config -> libs/dyn (#1086)
## Changes The name "dynamic value", or "dyn" for short, is more descriptive than the opaque "config". Also, it conveniently does not alias with other packages in the repository, or (popular ones) elsewhere. (discussed with @andrewnester) ## Tests n/a
This commit is contained in:
parent
a1297d71fd
commit
938eb1600c
|
@ -1,76 +0,0 @@
|
|||
package config_test
|
||||
|
||||
import (
|
||||
"testing"
|
||||
|
||||
"github.com/databricks/cli/libs/config"
|
||||
"github.com/stretchr/testify/assert"
|
||||
)
|
||||
|
||||
func TestPathAppend(t *testing.T) {
|
||||
p := config.NewPath(config.Key("foo"))
|
||||
|
||||
// Single arg.
|
||||
p1 := p.Append(config.Key("bar"))
|
||||
assert.True(t, p1.Equal(config.NewPath(config.Key("foo"), config.Key("bar"))))
|
||||
|
||||
// Multiple args.
|
||||
p2 := p.Append(config.Key("bar"), config.Index(1))
|
||||
assert.True(t, p2.Equal(config.NewPath(config.Key("foo"), config.Key("bar"), config.Index(1))))
|
||||
}
|
||||
|
||||
func TestPathJoin(t *testing.T) {
|
||||
p := config.NewPath(config.Key("foo"))
|
||||
|
||||
// Single arg.
|
||||
p1 := p.Join(config.NewPath(config.Key("bar")))
|
||||
assert.True(t, p1.Equal(config.NewPath(config.Key("foo"), config.Key("bar"))))
|
||||
|
||||
// Multiple args.
|
||||
p2 := p.Join(config.NewPath(config.Key("bar")), config.NewPath(config.Index(1)))
|
||||
assert.True(t, p2.Equal(config.NewPath(config.Key("foo"), config.Key("bar"), config.Index(1))))
|
||||
}
|
||||
|
||||
func TestPathEqualEmpty(t *testing.T) {
|
||||
assert.True(t, config.EmptyPath.Equal(config.EmptyPath))
|
||||
}
|
||||
|
||||
func TestPathEqual(t *testing.T) {
|
||||
p1 := config.NewPath(config.Key("foo"), config.Index(1))
|
||||
p2 := config.NewPath(config.Key("bar"), config.Index(2))
|
||||
assert.False(t, p1.Equal(p2), "expected %q to not equal %q", p1, p2)
|
||||
|
||||
p3 := config.NewPath(config.Key("foo"), config.Index(1))
|
||||
assert.True(t, p1.Equal(p3), "expected %q to equal %q", p1, p3)
|
||||
|
||||
p4 := config.NewPath(config.Key("foo"), config.Index(1), config.Key("bar"), config.Index(2))
|
||||
assert.False(t, p1.Equal(p4), "expected %q to not equal %q", p1, p4)
|
||||
}
|
||||
|
||||
func TestPathHasPrefixEmpty(t *testing.T) {
|
||||
empty := config.EmptyPath
|
||||
nonEmpty := config.NewPath(config.Key("foo"))
|
||||
assert.True(t, empty.HasPrefix(empty))
|
||||
assert.True(t, nonEmpty.HasPrefix(empty))
|
||||
assert.False(t, empty.HasPrefix(nonEmpty))
|
||||
}
|
||||
|
||||
func TestPathHasPrefix(t *testing.T) {
|
||||
p1 := config.NewPath(config.Key("foo"), config.Index(1))
|
||||
p2 := config.NewPath(config.Key("bar"), config.Index(2))
|
||||
assert.False(t, p1.HasPrefix(p2), "expected %q to not have prefix %q", p1, p2)
|
||||
|
||||
p3 := config.NewPath(config.Key("foo"))
|
||||
assert.True(t, p1.HasPrefix(p3), "expected %q to have prefix %q", p1, p3)
|
||||
}
|
||||
|
||||
func TestPathString(t *testing.T) {
|
||||
p1 := config.NewPath(config.Key("foo"), config.Index(1))
|
||||
assert.Equal(t, "foo[1]", p1.String())
|
||||
|
||||
p2 := config.NewPath(config.Key("bar"), config.Index(2), config.Key("baz"))
|
||||
assert.Equal(t, "bar[2].baz", p2.String())
|
||||
|
||||
p3 := config.NewPath(config.Key("foo"), config.Index(1), config.Key("bar"), config.Index(2), config.Key("baz"))
|
||||
assert.Equal(t, "foo[1].bar[2].baz", p3.String())
|
||||
}
|
|
@ -3,7 +3,7 @@ package diag
|
|||
import (
|
||||
"fmt"
|
||||
|
||||
"github.com/databricks/cli/libs/config"
|
||||
"github.com/databricks/cli/libs/dyn"
|
||||
)
|
||||
|
||||
type Diagnostic struct {
|
||||
|
@ -19,7 +19,7 @@ type Diagnostic struct {
|
|||
|
||||
// Location is a source code location associated with the diagnostic message.
|
||||
// It may be zero if there is no associated location.
|
||||
Location config.Location
|
||||
Location dyn.Location
|
||||
}
|
||||
|
||||
// Errorf creates a new error diagnostic.
|
||||
|
|
|
@ -3,13 +3,13 @@ package convert
|
|||
import (
|
||||
"testing"
|
||||
|
||||
"github.com/databricks/cli/libs/config"
|
||||
"github.com/databricks/cli/libs/dyn"
|
||||
"github.com/stretchr/testify/assert"
|
||||
"github.com/stretchr/testify/require"
|
||||
)
|
||||
|
||||
func assertFromTypedToTypedEqual[T any](t *testing.T, src T) {
|
||||
nv, err := FromTyped(src, config.NilValue)
|
||||
nv, err := FromTyped(src, dyn.NilValue)
|
||||
require.NoError(t, err)
|
||||
|
||||
var dst T
|
|
@ -3,11 +3,11 @@ package convert
|
|||
import (
|
||||
"fmt"
|
||||
|
||||
"github.com/databricks/cli/libs/config"
|
||||
"github.com/databricks/cli/libs/dyn"
|
||||
)
|
||||
|
||||
type TypeError struct {
|
||||
value config.Value
|
||||
value dyn.Value
|
||||
msg string
|
||||
}
|
||||
|
|
@ -4,18 +4,18 @@ import (
|
|||
"fmt"
|
||||
"reflect"
|
||||
|
||||
"github.com/databricks/cli/libs/config"
|
||||
"github.com/databricks/cli/libs/dyn"
|
||||
)
|
||||
|
||||
// FromTyped converts changes made in the typed structure w.r.t. the configuration value
|
||||
// back to the configuration value, retaining existing location information where possible.
|
||||
func FromTyped(src any, ref config.Value) (config.Value, error) {
|
||||
func FromTyped(src any, ref dyn.Value) (dyn.Value, error) {
|
||||
srcv := reflect.ValueOf(src)
|
||||
|
||||
// Dereference pointer if necessary
|
||||
for srcv.Kind() == reflect.Pointer {
|
||||
if srcv.IsNil() {
|
||||
return config.NilValue, nil
|
||||
return dyn.NilValue, nil
|
||||
}
|
||||
srcv = srcv.Elem()
|
||||
}
|
||||
|
@ -37,53 +37,53 @@ func FromTyped(src any, ref config.Value) (config.Value, error) {
|
|||
return fromTypedFloat(srcv, ref)
|
||||
}
|
||||
|
||||
return config.NilValue, fmt.Errorf("unsupported type: %s", srcv.Kind())
|
||||
return dyn.NilValue, fmt.Errorf("unsupported type: %s", srcv.Kind())
|
||||
}
|
||||
|
||||
func fromTypedStruct(src reflect.Value, ref config.Value) (config.Value, error) {
|
||||
func fromTypedStruct(src reflect.Value, ref dyn.Value) (dyn.Value, error) {
|
||||
// Check that the reference value is compatible or nil.
|
||||
switch ref.Kind() {
|
||||
case config.KindMap, config.KindNil:
|
||||
case dyn.KindMap, dyn.KindNil:
|
||||
default:
|
||||
return config.Value{}, fmt.Errorf("unhandled type: %s", ref.Kind())
|
||||
return dyn.Value{}, fmt.Errorf("unhandled type: %s", ref.Kind())
|
||||
}
|
||||
|
||||
out := make(map[string]config.Value)
|
||||
out := make(map[string]dyn.Value)
|
||||
info := getStructInfo(src.Type())
|
||||
for k, v := range info.FieldValues(src) {
|
||||
// Convert the field taking into account the reference value (may be equal to config.NilValue).
|
||||
nv, err := FromTyped(v.Interface(), ref.Get(k))
|
||||
if err != nil {
|
||||
return config.Value{}, err
|
||||
return dyn.Value{}, err
|
||||
}
|
||||
|
||||
if nv != config.NilValue {
|
||||
if nv != dyn.NilValue {
|
||||
out[k] = nv
|
||||
}
|
||||
}
|
||||
|
||||
// If the struct was equal to its zero value, emit a nil.
|
||||
if len(out) == 0 {
|
||||
return config.NilValue, nil
|
||||
return dyn.NilValue, nil
|
||||
}
|
||||
|
||||
return config.NewValue(out, ref.Location()), nil
|
||||
return dyn.NewValue(out, ref.Location()), nil
|
||||
}
|
||||
|
||||
func fromTypedMap(src reflect.Value, ref config.Value) (config.Value, error) {
|
||||
func fromTypedMap(src reflect.Value, ref dyn.Value) (dyn.Value, error) {
|
||||
// Check that the reference value is compatible or nil.
|
||||
switch ref.Kind() {
|
||||
case config.KindMap, config.KindNil:
|
||||
case dyn.KindMap, dyn.KindNil:
|
||||
default:
|
||||
return config.Value{}, fmt.Errorf("unhandled type: %s", ref.Kind())
|
||||
return dyn.Value{}, fmt.Errorf("unhandled type: %s", ref.Kind())
|
||||
}
|
||||
|
||||
// Return nil if the map is nil.
|
||||
if src.IsNil() {
|
||||
return config.NilValue, nil
|
||||
return dyn.NilValue, nil
|
||||
}
|
||||
|
||||
out := make(map[string]config.Value)
|
||||
out := make(map[string]dyn.Value)
|
||||
iter := src.MapRange()
|
||||
for iter.Next() {
|
||||
k := iter.Key().String()
|
||||
|
@ -92,7 +92,7 @@ func fromTypedMap(src reflect.Value, ref config.Value) (config.Value, error) {
|
|||
// Convert entry taking into account the reference value (may be equal to config.NilValue).
|
||||
nv, err := FromTyped(v.Interface(), ref.Get(k))
|
||||
if err != nil {
|
||||
return config.Value{}, err
|
||||
return dyn.Value{}, err
|
||||
}
|
||||
|
||||
// Every entry is represented, even if it is a nil.
|
||||
|
@ -100,115 +100,115 @@ func fromTypedMap(src reflect.Value, ref config.Value) (config.Value, error) {
|
|||
out[k] = nv
|
||||
}
|
||||
|
||||
return config.NewValue(out, ref.Location()), nil
|
||||
return dyn.NewValue(out, ref.Location()), nil
|
||||
}
|
||||
|
||||
func fromTypedSlice(src reflect.Value, ref config.Value) (config.Value, error) {
|
||||
func fromTypedSlice(src reflect.Value, ref dyn.Value) (dyn.Value, error) {
|
||||
// Check that the reference value is compatible or nil.
|
||||
switch ref.Kind() {
|
||||
case config.KindSequence, config.KindNil:
|
||||
case dyn.KindSequence, dyn.KindNil:
|
||||
default:
|
||||
return config.Value{}, fmt.Errorf("unhandled type: %s", ref.Kind())
|
||||
return dyn.Value{}, fmt.Errorf("unhandled type: %s", ref.Kind())
|
||||
}
|
||||
|
||||
// Return nil if the slice is nil.
|
||||
if src.IsNil() {
|
||||
return config.NilValue, nil
|
||||
return dyn.NilValue, nil
|
||||
}
|
||||
|
||||
out := make([]config.Value, src.Len())
|
||||
out := make([]dyn.Value, src.Len())
|
||||
for i := 0; i < src.Len(); i++ {
|
||||
v := src.Index(i)
|
||||
|
||||
// Convert entry taking into account the reference value (may be equal to config.NilValue).
|
||||
nv, err := FromTyped(v.Interface(), ref.Index(i))
|
||||
if err != nil {
|
||||
return config.Value{}, err
|
||||
return dyn.Value{}, err
|
||||
}
|
||||
|
||||
out[i] = nv
|
||||
}
|
||||
|
||||
return config.NewValue(out, ref.Location()), nil
|
||||
return dyn.NewValue(out, ref.Location()), nil
|
||||
}
|
||||
|
||||
func fromTypedString(src reflect.Value, ref config.Value) (config.Value, error) {
|
||||
func fromTypedString(src reflect.Value, ref dyn.Value) (dyn.Value, error) {
|
||||
switch ref.Kind() {
|
||||
case config.KindString:
|
||||
case dyn.KindString:
|
||||
value := src.String()
|
||||
if value == ref.MustString() {
|
||||
return ref, nil
|
||||
}
|
||||
|
||||
return config.V(value), nil
|
||||
case config.KindNil:
|
||||
return dyn.V(value), nil
|
||||
case dyn.KindNil:
|
||||
// This field is not set in the reference, so we only include it if it has a non-zero value.
|
||||
// Otherwise, we would always include all zero valued fields.
|
||||
if src.IsZero() {
|
||||
return config.NilValue, nil
|
||||
return dyn.NilValue, nil
|
||||
}
|
||||
return config.V(src.String()), nil
|
||||
return dyn.V(src.String()), nil
|
||||
}
|
||||
|
||||
return config.Value{}, fmt.Errorf("unhandled type: %s", ref.Kind())
|
||||
return dyn.Value{}, fmt.Errorf("unhandled type: %s", ref.Kind())
|
||||
}
|
||||
|
||||
func fromTypedBool(src reflect.Value, ref config.Value) (config.Value, error) {
|
||||
func fromTypedBool(src reflect.Value, ref dyn.Value) (dyn.Value, error) {
|
||||
switch ref.Kind() {
|
||||
case config.KindBool:
|
||||
case dyn.KindBool:
|
||||
value := src.Bool()
|
||||
if value == ref.MustBool() {
|
||||
return ref, nil
|
||||
}
|
||||
return config.V(value), nil
|
||||
case config.KindNil:
|
||||
return dyn.V(value), nil
|
||||
case dyn.KindNil:
|
||||
// This field is not set in the reference, so we only include it if it has a non-zero value.
|
||||
// Otherwise, we would always include all zero valued fields.
|
||||
if src.IsZero() {
|
||||
return config.NilValue, nil
|
||||
return dyn.NilValue, nil
|
||||
}
|
||||
return config.V(src.Bool()), nil
|
||||
return dyn.V(src.Bool()), nil
|
||||
}
|
||||
|
||||
return config.Value{}, fmt.Errorf("unhandled type: %s", ref.Kind())
|
||||
return dyn.Value{}, fmt.Errorf("unhandled type: %s", ref.Kind())
|
||||
}
|
||||
|
||||
func fromTypedInt(src reflect.Value, ref config.Value) (config.Value, error) {
|
||||
func fromTypedInt(src reflect.Value, ref dyn.Value) (dyn.Value, error) {
|
||||
switch ref.Kind() {
|
||||
case config.KindInt:
|
||||
case dyn.KindInt:
|
||||
value := src.Int()
|
||||
if value == ref.MustInt() {
|
||||
return ref, nil
|
||||
}
|
||||
return config.V(value), nil
|
||||
case config.KindNil:
|
||||
return dyn.V(value), nil
|
||||
case dyn.KindNil:
|
||||
// This field is not set in the reference, so we only include it if it has a non-zero value.
|
||||
// Otherwise, we would always include all zero valued fields.
|
||||
if src.IsZero() {
|
||||
return config.NilValue, nil
|
||||
return dyn.NilValue, nil
|
||||
}
|
||||
return config.V(src.Int()), nil
|
||||
return dyn.V(src.Int()), nil
|
||||
}
|
||||
|
||||
return config.Value{}, fmt.Errorf("unhandled type: %s", ref.Kind())
|
||||
return dyn.Value{}, fmt.Errorf("unhandled type: %s", ref.Kind())
|
||||
}
|
||||
|
||||
func fromTypedFloat(src reflect.Value, ref config.Value) (config.Value, error) {
|
||||
func fromTypedFloat(src reflect.Value, ref dyn.Value) (dyn.Value, error) {
|
||||
switch ref.Kind() {
|
||||
case config.KindFloat:
|
||||
case dyn.KindFloat:
|
||||
value := src.Float()
|
||||
if value == ref.MustFloat() {
|
||||
return ref, nil
|
||||
}
|
||||
return config.V(value), nil
|
||||
case config.KindNil:
|
||||
return dyn.V(value), nil
|
||||
case dyn.KindNil:
|
||||
// This field is not set in the reference, so we only include it if it has a non-zero value.
|
||||
// Otherwise, we would always include all zero valued fields.
|
||||
if src.IsZero() {
|
||||
return config.NilValue, nil
|
||||
return dyn.NilValue, nil
|
||||
}
|
||||
return config.V(src.Float()), nil
|
||||
return dyn.V(src.Float()), nil
|
||||
}
|
||||
|
||||
return config.Value{}, fmt.Errorf("unhandled type: %s", ref.Kind())
|
||||
return dyn.Value{}, fmt.Errorf("unhandled type: %s", ref.Kind())
|
||||
}
|
|
@ -3,7 +3,7 @@ package convert
|
|||
import (
|
||||
"testing"
|
||||
|
||||
"github.com/databricks/cli/libs/config"
|
||||
"github.com/databricks/cli/libs/dyn"
|
||||
"github.com/stretchr/testify/assert"
|
||||
"github.com/stretchr/testify/require"
|
||||
)
|
||||
|
@ -15,11 +15,11 @@ func TestFromTypedStructZeroFields(t *testing.T) {
|
|||
}
|
||||
|
||||
src := Tmp{}
|
||||
ref := config.NilValue
|
||||
ref := dyn.NilValue
|
||||
|
||||
nv, err := FromTyped(src, ref)
|
||||
require.NoError(t, err)
|
||||
assert.Equal(t, config.NilValue, nv)
|
||||
assert.Equal(t, dyn.NilValue, nv)
|
||||
}
|
||||
|
||||
func TestFromTypedStructSetFields(t *testing.T) {
|
||||
|
@ -33,12 +33,12 @@ func TestFromTypedStructSetFields(t *testing.T) {
|
|||
Bar: "bar",
|
||||
}
|
||||
|
||||
ref := config.NilValue
|
||||
ref := dyn.NilValue
|
||||
nv, err := FromTyped(src, ref)
|
||||
require.NoError(t, err)
|
||||
assert.Equal(t, config.V(map[string]config.Value{
|
||||
"foo": config.V("foo"),
|
||||
"bar": config.V("bar"),
|
||||
assert.Equal(t, dyn.V(map[string]dyn.Value{
|
||||
"foo": dyn.V("foo"),
|
||||
"bar": dyn.V("bar"),
|
||||
}), nv)
|
||||
}
|
||||
|
||||
|
@ -53,45 +53,45 @@ func TestFromTypedStructSetFieldsRetainLocationIfUnchanged(t *testing.T) {
|
|||
Bar: "qux",
|
||||
}
|
||||
|
||||
ref := config.V(map[string]config.Value{
|
||||
"foo": config.NewValue("bar", config.Location{File: "foo"}),
|
||||
"bar": config.NewValue("baz", config.Location{File: "bar"}),
|
||||
ref := dyn.V(map[string]dyn.Value{
|
||||
"foo": dyn.NewValue("bar", dyn.Location{File: "foo"}),
|
||||
"bar": dyn.NewValue("baz", dyn.Location{File: "bar"}),
|
||||
})
|
||||
|
||||
nv, err := FromTyped(src, ref)
|
||||
require.NoError(t, err)
|
||||
|
||||
// Assert foo has retained its location.
|
||||
assert.Equal(t, config.NewValue("bar", config.Location{File: "foo"}), nv.Get("foo"))
|
||||
assert.Equal(t, dyn.NewValue("bar", dyn.Location{File: "foo"}), nv.Get("foo"))
|
||||
|
||||
// Assert bar lost its location (because it was overwritten).
|
||||
assert.Equal(t, config.NewValue("qux", config.Location{}), nv.Get("bar"))
|
||||
assert.Equal(t, dyn.NewValue("qux", dyn.Location{}), nv.Get("bar"))
|
||||
}
|
||||
|
||||
func TestFromTypedMapNil(t *testing.T) {
|
||||
var src map[string]string = nil
|
||||
|
||||
ref := config.V(map[string]config.Value{
|
||||
"foo": config.V("bar"),
|
||||
"bar": config.V("baz"),
|
||||
ref := dyn.V(map[string]dyn.Value{
|
||||
"foo": dyn.V("bar"),
|
||||
"bar": dyn.V("baz"),
|
||||
})
|
||||
|
||||
nv, err := FromTyped(src, ref)
|
||||
require.NoError(t, err)
|
||||
assert.Equal(t, config.NilValue, nv)
|
||||
assert.Equal(t, dyn.NilValue, nv)
|
||||
}
|
||||
|
||||
func TestFromTypedMapEmpty(t *testing.T) {
|
||||
var src = map[string]string{}
|
||||
|
||||
ref := config.V(map[string]config.Value{
|
||||
"foo": config.V("bar"),
|
||||
"bar": config.V("baz"),
|
||||
ref := dyn.V(map[string]dyn.Value{
|
||||
"foo": dyn.V("bar"),
|
||||
"bar": dyn.V("baz"),
|
||||
})
|
||||
|
||||
nv, err := FromTyped(src, ref)
|
||||
require.NoError(t, err)
|
||||
assert.Equal(t, config.V(map[string]config.Value{}), nv)
|
||||
assert.Equal(t, dyn.V(map[string]dyn.Value{}), nv)
|
||||
}
|
||||
|
||||
func TestFromTypedMapNonEmpty(t *testing.T) {
|
||||
|
@ -100,12 +100,12 @@ func TestFromTypedMapNonEmpty(t *testing.T) {
|
|||
"bar": "bar",
|
||||
}
|
||||
|
||||
ref := config.NilValue
|
||||
ref := dyn.NilValue
|
||||
nv, err := FromTyped(src, ref)
|
||||
require.NoError(t, err)
|
||||
assert.Equal(t, config.V(map[string]config.Value{
|
||||
"foo": config.V("foo"),
|
||||
"bar": config.V("bar"),
|
||||
assert.Equal(t, dyn.V(map[string]dyn.Value{
|
||||
"foo": dyn.V("foo"),
|
||||
"bar": dyn.V("bar"),
|
||||
}), nv)
|
||||
}
|
||||
|
||||
|
@ -115,19 +115,19 @@ func TestFromTypedMapNonEmptyRetainLocationIfUnchanged(t *testing.T) {
|
|||
"bar": "qux",
|
||||
}
|
||||
|
||||
ref := config.V(map[string]config.Value{
|
||||
"foo": config.NewValue("bar", config.Location{File: "foo"}),
|
||||
"bar": config.NewValue("baz", config.Location{File: "bar"}),
|
||||
ref := dyn.V(map[string]dyn.Value{
|
||||
"foo": dyn.NewValue("bar", dyn.Location{File: "foo"}),
|
||||
"bar": dyn.NewValue("baz", dyn.Location{File: "bar"}),
|
||||
})
|
||||
|
||||
nv, err := FromTyped(src, ref)
|
||||
require.NoError(t, err)
|
||||
|
||||
// Assert foo has retained its location.
|
||||
assert.Equal(t, config.NewValue("bar", config.Location{File: "foo"}), nv.Get("foo"))
|
||||
assert.Equal(t, dyn.NewValue("bar", dyn.Location{File: "foo"}), nv.Get("foo"))
|
||||
|
||||
// Assert bar lost its location (because it was overwritten).
|
||||
assert.Equal(t, config.NewValue("qux", config.Location{}), nv.Get("bar"))
|
||||
assert.Equal(t, dyn.NewValue("qux", dyn.Location{}), nv.Get("bar"))
|
||||
}
|
||||
|
||||
func TestFromTypedMapFieldWithZeroValue(t *testing.T) {
|
||||
|
@ -135,38 +135,38 @@ func TestFromTypedMapFieldWithZeroValue(t *testing.T) {
|
|||
"foo": "",
|
||||
}
|
||||
|
||||
ref := config.NilValue
|
||||
ref := dyn.NilValue
|
||||
nv, err := FromTyped(src, ref)
|
||||
require.NoError(t, err)
|
||||
assert.Equal(t, config.V(map[string]config.Value{
|
||||
"foo": config.NilValue,
|
||||
assert.Equal(t, dyn.V(map[string]dyn.Value{
|
||||
"foo": dyn.NilValue,
|
||||
}), nv)
|
||||
}
|
||||
|
||||
func TestFromTypedSliceNil(t *testing.T) {
|
||||
var src []string = nil
|
||||
|
||||
ref := config.V([]config.Value{
|
||||
config.V("bar"),
|
||||
config.V("baz"),
|
||||
ref := dyn.V([]dyn.Value{
|
||||
dyn.V("bar"),
|
||||
dyn.V("baz"),
|
||||
})
|
||||
|
||||
nv, err := FromTyped(src, ref)
|
||||
require.NoError(t, err)
|
||||
assert.Equal(t, config.NilValue, nv)
|
||||
assert.Equal(t, dyn.NilValue, nv)
|
||||
}
|
||||
|
||||
func TestFromTypedSliceEmpty(t *testing.T) {
|
||||
var src = []string{}
|
||||
|
||||
ref := config.V([]config.Value{
|
||||
config.V("bar"),
|
||||
config.V("baz"),
|
||||
ref := dyn.V([]dyn.Value{
|
||||
dyn.V("bar"),
|
||||
dyn.V("baz"),
|
||||
})
|
||||
|
||||
nv, err := FromTyped(src, ref)
|
||||
require.NoError(t, err)
|
||||
assert.Equal(t, config.V([]config.Value{}), nv)
|
||||
assert.Equal(t, dyn.V([]dyn.Value{}), nv)
|
||||
}
|
||||
|
||||
func TestFromTypedSliceNonEmpty(t *testing.T) {
|
||||
|
@ -175,12 +175,12 @@ func TestFromTypedSliceNonEmpty(t *testing.T) {
|
|||
"bar",
|
||||
}
|
||||
|
||||
ref := config.NilValue
|
||||
ref := dyn.NilValue
|
||||
nv, err := FromTyped(src, ref)
|
||||
require.NoError(t, err)
|
||||
assert.Equal(t, config.V([]config.Value{
|
||||
config.V("foo"),
|
||||
config.V("bar"),
|
||||
assert.Equal(t, dyn.V([]dyn.Value{
|
||||
dyn.V("foo"),
|
||||
dyn.V("bar"),
|
||||
}), nv)
|
||||
}
|
||||
|
||||
|
@ -190,205 +190,205 @@ func TestFromTypedSliceNonEmptyRetainLocationIfUnchanged(t *testing.T) {
|
|||
"bar",
|
||||
}
|
||||
|
||||
ref := config.V([]config.Value{
|
||||
config.NewValue("foo", config.Location{File: "foo"}),
|
||||
config.NewValue("baz", config.Location{File: "baz"}),
|
||||
ref := dyn.V([]dyn.Value{
|
||||
dyn.NewValue("foo", dyn.Location{File: "foo"}),
|
||||
dyn.NewValue("baz", dyn.Location{File: "baz"}),
|
||||
})
|
||||
|
||||
nv, err := FromTyped(src, ref)
|
||||
require.NoError(t, err)
|
||||
|
||||
// Assert foo has retained its location.
|
||||
assert.Equal(t, config.NewValue("foo", config.Location{File: "foo"}), nv.Index(0))
|
||||
assert.Equal(t, dyn.NewValue("foo", dyn.Location{File: "foo"}), nv.Index(0))
|
||||
|
||||
// Assert bar lost its location (because it was overwritten).
|
||||
assert.Equal(t, config.NewValue("bar", config.Location{}), nv.Index(1))
|
||||
assert.Equal(t, dyn.NewValue("bar", dyn.Location{}), nv.Index(1))
|
||||
}
|
||||
|
||||
func TestFromTypedStringEmpty(t *testing.T) {
|
||||
var src string
|
||||
var ref = config.NilValue
|
||||
var ref = dyn.NilValue
|
||||
nv, err := FromTyped(src, ref)
|
||||
require.NoError(t, err)
|
||||
assert.Equal(t, config.NilValue, nv)
|
||||
assert.Equal(t, dyn.NilValue, nv)
|
||||
}
|
||||
|
||||
func TestFromTypedStringEmptyOverwrite(t *testing.T) {
|
||||
var src string
|
||||
var ref = config.V("old")
|
||||
var ref = dyn.V("old")
|
||||
nv, err := FromTyped(src, ref)
|
||||
require.NoError(t, err)
|
||||
assert.Equal(t, config.V(""), nv)
|
||||
assert.Equal(t, dyn.V(""), nv)
|
||||
}
|
||||
|
||||
func TestFromTypedStringNonEmpty(t *testing.T) {
|
||||
var src string = "new"
|
||||
var ref = config.NilValue
|
||||
var ref = dyn.NilValue
|
||||
nv, err := FromTyped(src, ref)
|
||||
require.NoError(t, err)
|
||||
assert.Equal(t, config.V("new"), nv)
|
||||
assert.Equal(t, dyn.V("new"), nv)
|
||||
}
|
||||
|
||||
func TestFromTypedStringNonEmptyOverwrite(t *testing.T) {
|
||||
var src string = "new"
|
||||
var ref = config.V("old")
|
||||
var ref = dyn.V("old")
|
||||
nv, err := FromTyped(src, ref)
|
||||
require.NoError(t, err)
|
||||
assert.Equal(t, config.V("new"), nv)
|
||||
assert.Equal(t, dyn.V("new"), nv)
|
||||
}
|
||||
|
||||
func TestFromTypedStringRetainsLocationsIfUnchanged(t *testing.T) {
|
||||
var src string = "foo"
|
||||
var ref = config.NewValue("foo", config.Location{File: "foo"})
|
||||
var ref = dyn.NewValue("foo", dyn.Location{File: "foo"})
|
||||
nv, err := FromTyped(src, ref)
|
||||
require.NoError(t, err)
|
||||
assert.Equal(t, config.NewValue("foo", config.Location{File: "foo"}), nv)
|
||||
assert.Equal(t, dyn.NewValue("foo", dyn.Location{File: "foo"}), nv)
|
||||
}
|
||||
|
||||
func TestFromTypedStringTypeError(t *testing.T) {
|
||||
var src string = "foo"
|
||||
var ref = config.V(1234)
|
||||
var ref = dyn.V(1234)
|
||||
_, err := FromTyped(src, ref)
|
||||
require.Error(t, err)
|
||||
}
|
||||
|
||||
func TestFromTypedBoolEmpty(t *testing.T) {
|
||||
var src bool
|
||||
var ref = config.NilValue
|
||||
var ref = dyn.NilValue
|
||||
nv, err := FromTyped(src, ref)
|
||||
require.NoError(t, err)
|
||||
assert.Equal(t, config.NilValue, nv)
|
||||
assert.Equal(t, dyn.NilValue, nv)
|
||||
}
|
||||
|
||||
func TestFromTypedBoolEmptyOverwrite(t *testing.T) {
|
||||
var src bool
|
||||
var ref = config.V(true)
|
||||
var ref = dyn.V(true)
|
||||
nv, err := FromTyped(src, ref)
|
||||
require.NoError(t, err)
|
||||
assert.Equal(t, config.V(false), nv)
|
||||
assert.Equal(t, dyn.V(false), nv)
|
||||
}
|
||||
|
||||
func TestFromTypedBoolNonEmpty(t *testing.T) {
|
||||
var src bool = true
|
||||
var ref = config.NilValue
|
||||
var ref = dyn.NilValue
|
||||
nv, err := FromTyped(src, ref)
|
||||
require.NoError(t, err)
|
||||
assert.Equal(t, config.V(true), nv)
|
||||
assert.Equal(t, dyn.V(true), nv)
|
||||
}
|
||||
|
||||
func TestFromTypedBoolNonEmptyOverwrite(t *testing.T) {
|
||||
var src bool = true
|
||||
var ref = config.V(false)
|
||||
var ref = dyn.V(false)
|
||||
nv, err := FromTyped(src, ref)
|
||||
require.NoError(t, err)
|
||||
assert.Equal(t, config.V(true), nv)
|
||||
assert.Equal(t, dyn.V(true), nv)
|
||||
}
|
||||
|
||||
func TestFromTypedBoolRetainsLocationsIfUnchanged(t *testing.T) {
|
||||
var src bool = true
|
||||
var ref = config.NewValue(true, config.Location{File: "foo"})
|
||||
var ref = dyn.NewValue(true, dyn.Location{File: "foo"})
|
||||
nv, err := FromTyped(src, ref)
|
||||
require.NoError(t, err)
|
||||
assert.Equal(t, config.NewValue(true, config.Location{File: "foo"}), nv)
|
||||
assert.Equal(t, dyn.NewValue(true, dyn.Location{File: "foo"}), nv)
|
||||
}
|
||||
|
||||
func TestFromTypedBoolTypeError(t *testing.T) {
|
||||
var src bool = true
|
||||
var ref = config.V("string")
|
||||
var ref = dyn.V("string")
|
||||
_, err := FromTyped(src, ref)
|
||||
require.Error(t, err)
|
||||
}
|
||||
|
||||
func TestFromTypedIntEmpty(t *testing.T) {
|
||||
var src int
|
||||
var ref = config.NilValue
|
||||
var ref = dyn.NilValue
|
||||
nv, err := FromTyped(src, ref)
|
||||
require.NoError(t, err)
|
||||
assert.Equal(t, config.NilValue, nv)
|
||||
assert.Equal(t, dyn.NilValue, nv)
|
||||
}
|
||||
|
||||
func TestFromTypedIntEmptyOverwrite(t *testing.T) {
|
||||
var src int
|
||||
var ref = config.V(1234)
|
||||
var ref = dyn.V(1234)
|
||||
nv, err := FromTyped(src, ref)
|
||||
require.NoError(t, err)
|
||||
assert.Equal(t, config.V(int64(0)), nv)
|
||||
assert.Equal(t, dyn.V(int64(0)), nv)
|
||||
}
|
||||
|
||||
func TestFromTypedIntNonEmpty(t *testing.T) {
|
||||
var src int = 1234
|
||||
var ref = config.NilValue
|
||||
var ref = dyn.NilValue
|
||||
nv, err := FromTyped(src, ref)
|
||||
require.NoError(t, err)
|
||||
assert.Equal(t, config.V(int64(1234)), nv)
|
||||
assert.Equal(t, dyn.V(int64(1234)), nv)
|
||||
}
|
||||
|
||||
func TestFromTypedIntNonEmptyOverwrite(t *testing.T) {
|
||||
var src int = 1234
|
||||
var ref = config.V(1233)
|
||||
var ref = dyn.V(1233)
|
||||
nv, err := FromTyped(src, ref)
|
||||
require.NoError(t, err)
|
||||
assert.Equal(t, config.V(int64(1234)), nv)
|
||||
assert.Equal(t, dyn.V(int64(1234)), nv)
|
||||
}
|
||||
|
||||
func TestFromTypedIntRetainsLocationsIfUnchanged(t *testing.T) {
|
||||
var src int = 1234
|
||||
var ref = config.NewValue(1234, config.Location{File: "foo"})
|
||||
var ref = dyn.NewValue(1234, dyn.Location{File: "foo"})
|
||||
nv, err := FromTyped(src, ref)
|
||||
require.NoError(t, err)
|
||||
assert.Equal(t, config.NewValue(1234, config.Location{File: "foo"}), nv)
|
||||
assert.Equal(t, dyn.NewValue(1234, dyn.Location{File: "foo"}), nv)
|
||||
}
|
||||
|
||||
func TestFromTypedIntTypeError(t *testing.T) {
|
||||
var src int = 1234
|
||||
var ref = config.V("string")
|
||||
var ref = dyn.V("string")
|
||||
_, err := FromTyped(src, ref)
|
||||
require.Error(t, err)
|
||||
}
|
||||
|
||||
func TestFromTypedFloatEmpty(t *testing.T) {
|
||||
var src float64
|
||||
var ref = config.NilValue
|
||||
var ref = dyn.NilValue
|
||||
nv, err := FromTyped(src, ref)
|
||||
require.NoError(t, err)
|
||||
assert.Equal(t, config.NilValue, nv)
|
||||
assert.Equal(t, dyn.NilValue, nv)
|
||||
}
|
||||
|
||||
func TestFromTypedFloatEmptyOverwrite(t *testing.T) {
|
||||
var src float64
|
||||
var ref = config.V(1.23)
|
||||
var ref = dyn.V(1.23)
|
||||
nv, err := FromTyped(src, ref)
|
||||
require.NoError(t, err)
|
||||
assert.Equal(t, config.V(0.0), nv)
|
||||
assert.Equal(t, dyn.V(0.0), nv)
|
||||
}
|
||||
|
||||
func TestFromTypedFloatNonEmpty(t *testing.T) {
|
||||
var src float64 = 1.23
|
||||
var ref = config.NilValue
|
||||
var ref = dyn.NilValue
|
||||
nv, err := FromTyped(src, ref)
|
||||
require.NoError(t, err)
|
||||
assert.Equal(t, config.V(1.23), nv)
|
||||
assert.Equal(t, dyn.V(1.23), nv)
|
||||
}
|
||||
|
||||
func TestFromTypedFloatNonEmptyOverwrite(t *testing.T) {
|
||||
var src float64 = 1.23
|
||||
var ref = config.V(1.24)
|
||||
var ref = dyn.V(1.24)
|
||||
nv, err := FromTyped(src, ref)
|
||||
require.NoError(t, err)
|
||||
assert.Equal(t, config.V(1.23), nv)
|
||||
assert.Equal(t, dyn.V(1.23), nv)
|
||||
}
|
||||
|
||||
func TestFromTypedFloatRetainsLocationsIfUnchanged(t *testing.T) {
|
||||
var src float64 = 1.23
|
||||
var ref = config.NewValue(1.23, config.Location{File: "foo"})
|
||||
var ref = dyn.NewValue(1.23, dyn.Location{File: "foo"})
|
||||
nv, err := FromTyped(src, ref)
|
||||
require.NoError(t, err)
|
||||
assert.Equal(t, config.NewValue(1.23, config.Location{File: "foo"}), nv)
|
||||
assert.Equal(t, dyn.NewValue(1.23, dyn.Location{File: "foo"}), nv)
|
||||
}
|
||||
|
||||
func TestFromTypedFloatTypeError(t *testing.T) {
|
||||
var src float64 = 1.23
|
||||
var ref = config.V("string")
|
||||
var ref = dyn.V("string")
|
||||
_, err := FromTyped(src, ref)
|
||||
require.Error(t, err)
|
||||
}
|
|
@ -5,15 +5,15 @@ import (
|
|||
"reflect"
|
||||
"strconv"
|
||||
|
||||
"github.com/databricks/cli/libs/config"
|
||||
"github.com/databricks/cli/libs/diag"
|
||||
"github.com/databricks/cli/libs/dyn"
|
||||
)
|
||||
|
||||
func Normalize(dst any, src config.Value) (config.Value, diag.Diagnostics) {
|
||||
func Normalize(dst any, src dyn.Value) (dyn.Value, diag.Diagnostics) {
|
||||
return normalizeType(reflect.TypeOf(dst), src)
|
||||
}
|
||||
|
||||
func normalizeType(typ reflect.Type, src config.Value) (config.Value, diag.Diagnostics) {
|
||||
func normalizeType(typ reflect.Type, src dyn.Value) (dyn.Value, diag.Diagnostics) {
|
||||
for typ.Kind() == reflect.Pointer {
|
||||
typ = typ.Elem()
|
||||
}
|
||||
|
@ -35,10 +35,10 @@ func normalizeType(typ reflect.Type, src config.Value) (config.Value, diag.Diagn
|
|||
return normalizeFloat(typ, src)
|
||||
}
|
||||
|
||||
return config.NilValue, diag.Errorf("unsupported type: %s", typ.Kind())
|
||||
return dyn.NilValue, diag.Errorf("unsupported type: %s", typ.Kind())
|
||||
}
|
||||
|
||||
func typeMismatch(expected config.Kind, src config.Value) diag.Diagnostic {
|
||||
func typeMismatch(expected dyn.Kind, src dyn.Value) diag.Diagnostic {
|
||||
return diag.Diagnostic{
|
||||
Severity: diag.Error,
|
||||
Summary: fmt.Sprintf("expected %s, found %s", expected, src.Kind()),
|
||||
|
@ -46,12 +46,12 @@ func typeMismatch(expected config.Kind, src config.Value) diag.Diagnostic {
|
|||
}
|
||||
}
|
||||
|
||||
func normalizeStruct(typ reflect.Type, src config.Value) (config.Value, diag.Diagnostics) {
|
||||
func normalizeStruct(typ reflect.Type, src dyn.Value) (dyn.Value, diag.Diagnostics) {
|
||||
var diags diag.Diagnostics
|
||||
|
||||
switch src.Kind() {
|
||||
case config.KindMap:
|
||||
out := make(map[string]config.Value)
|
||||
case dyn.KindMap:
|
||||
out := make(map[string]dyn.Value)
|
||||
info := getStructInfo(typ)
|
||||
for k, v := range src.MustMap() {
|
||||
index, ok := info.Fields[k]
|
||||
|
@ -77,20 +77,20 @@ func normalizeStruct(typ reflect.Type, src config.Value) (config.Value, diag.Dia
|
|||
out[k] = v
|
||||
}
|
||||
|
||||
return config.NewValue(out, src.Location()), diags
|
||||
case config.KindNil:
|
||||
return dyn.NewValue(out, src.Location()), diags
|
||||
case dyn.KindNil:
|
||||
return src, diags
|
||||
}
|
||||
|
||||
return config.NilValue, diags.Append(typeMismatch(config.KindMap, src))
|
||||
return dyn.NilValue, diags.Append(typeMismatch(dyn.KindMap, src))
|
||||
}
|
||||
|
||||
func normalizeMap(typ reflect.Type, src config.Value) (config.Value, diag.Diagnostics) {
|
||||
func normalizeMap(typ reflect.Type, src dyn.Value) (dyn.Value, diag.Diagnostics) {
|
||||
var diags diag.Diagnostics
|
||||
|
||||
switch src.Kind() {
|
||||
case config.KindMap:
|
||||
out := make(map[string]config.Value)
|
||||
case dyn.KindMap:
|
||||
out := make(map[string]dyn.Value)
|
||||
for k, v := range src.MustMap() {
|
||||
// Normalize the value according to the map element type.
|
||||
v, err := normalizeType(typ.Elem(), v)
|
||||
|
@ -105,20 +105,20 @@ func normalizeMap(typ reflect.Type, src config.Value) (config.Value, diag.Diagno
|
|||
out[k] = v
|
||||
}
|
||||
|
||||
return config.NewValue(out, src.Location()), diags
|
||||
case config.KindNil:
|
||||
return dyn.NewValue(out, src.Location()), diags
|
||||
case dyn.KindNil:
|
||||
return src, diags
|
||||
}
|
||||
|
||||
return config.NilValue, diags.Append(typeMismatch(config.KindMap, src))
|
||||
return dyn.NilValue, diags.Append(typeMismatch(dyn.KindMap, src))
|
||||
}
|
||||
|
||||
func normalizeSlice(typ reflect.Type, src config.Value) (config.Value, diag.Diagnostics) {
|
||||
func normalizeSlice(typ reflect.Type, src dyn.Value) (dyn.Value, diag.Diagnostics) {
|
||||
var diags diag.Diagnostics
|
||||
|
||||
switch src.Kind() {
|
||||
case config.KindSequence:
|
||||
out := make([]config.Value, 0, len(src.MustSequence()))
|
||||
case dyn.KindSequence:
|
||||
out := make([]dyn.Value, 0, len(src.MustSequence()))
|
||||
for _, v := range src.MustSequence() {
|
||||
// Normalize the value according to the slice element type.
|
||||
v, err := normalizeType(typ.Elem(), v)
|
||||
|
@ -133,42 +133,42 @@ func normalizeSlice(typ reflect.Type, src config.Value) (config.Value, diag.Diag
|
|||
out = append(out, v)
|
||||
}
|
||||
|
||||
return config.NewValue(out, src.Location()), diags
|
||||
case config.KindNil:
|
||||
return dyn.NewValue(out, src.Location()), diags
|
||||
case dyn.KindNil:
|
||||
return src, diags
|
||||
}
|
||||
|
||||
return config.NilValue, diags.Append(typeMismatch(config.KindSequence, src))
|
||||
return dyn.NilValue, diags.Append(typeMismatch(dyn.KindSequence, src))
|
||||
}
|
||||
|
||||
func normalizeString(typ reflect.Type, src config.Value) (config.Value, diag.Diagnostics) {
|
||||
func normalizeString(typ reflect.Type, src dyn.Value) (dyn.Value, diag.Diagnostics) {
|
||||
var diags diag.Diagnostics
|
||||
var out string
|
||||
|
||||
switch src.Kind() {
|
||||
case config.KindString:
|
||||
case dyn.KindString:
|
||||
out = src.MustString()
|
||||
case config.KindBool:
|
||||
case dyn.KindBool:
|
||||
out = strconv.FormatBool(src.MustBool())
|
||||
case config.KindInt:
|
||||
case dyn.KindInt:
|
||||
out = strconv.FormatInt(src.MustInt(), 10)
|
||||
case config.KindFloat:
|
||||
case dyn.KindFloat:
|
||||
out = strconv.FormatFloat(src.MustFloat(), 'f', -1, 64)
|
||||
default:
|
||||
return config.NilValue, diags.Append(typeMismatch(config.KindString, src))
|
||||
return dyn.NilValue, diags.Append(typeMismatch(dyn.KindString, src))
|
||||
}
|
||||
|
||||
return config.NewValue(out, src.Location()), diags
|
||||
return dyn.NewValue(out, src.Location()), diags
|
||||
}
|
||||
|
||||
func normalizeBool(typ reflect.Type, src config.Value) (config.Value, diag.Diagnostics) {
|
||||
func normalizeBool(typ reflect.Type, src dyn.Value) (dyn.Value, diag.Diagnostics) {
|
||||
var diags diag.Diagnostics
|
||||
var out bool
|
||||
|
||||
switch src.Kind() {
|
||||
case config.KindBool:
|
||||
case dyn.KindBool:
|
||||
out = src.MustBool()
|
||||
case config.KindString:
|
||||
case dyn.KindString:
|
||||
// See https://github.com/go-yaml/yaml/blob/f6f7691b1fdeb513f56608cd2c32c51f8194bf51/decode.go#L684-L693.
|
||||
switch src.MustString() {
|
||||
case "true", "y", "Y", "yes", "Yes", "YES", "on", "On", "ON":
|
||||
|
@ -177,59 +177,59 @@ func normalizeBool(typ reflect.Type, src config.Value) (config.Value, diag.Diagn
|
|||
out = false
|
||||
default:
|
||||
// Cannot interpret as a boolean.
|
||||
return config.NilValue, diags.Append(typeMismatch(config.KindBool, src))
|
||||
return dyn.NilValue, diags.Append(typeMismatch(dyn.KindBool, src))
|
||||
}
|
||||
default:
|
||||
return config.NilValue, diags.Append(typeMismatch(config.KindBool, src))
|
||||
return dyn.NilValue, diags.Append(typeMismatch(dyn.KindBool, src))
|
||||
}
|
||||
|
||||
return config.NewValue(out, src.Location()), diags
|
||||
return dyn.NewValue(out, src.Location()), diags
|
||||
}
|
||||
|
||||
func normalizeInt(typ reflect.Type, src config.Value) (config.Value, diag.Diagnostics) {
|
||||
func normalizeInt(typ reflect.Type, src dyn.Value) (dyn.Value, diag.Diagnostics) {
|
||||
var diags diag.Diagnostics
|
||||
var out int64
|
||||
|
||||
switch src.Kind() {
|
||||
case config.KindInt:
|
||||
case dyn.KindInt:
|
||||
out = src.MustInt()
|
||||
case config.KindString:
|
||||
case dyn.KindString:
|
||||
var err error
|
||||
out, err = strconv.ParseInt(src.MustString(), 10, 64)
|
||||
if err != nil {
|
||||
return config.NilValue, diags.Append(diag.Diagnostic{
|
||||
return dyn.NilValue, diags.Append(diag.Diagnostic{
|
||||
Severity: diag.Error,
|
||||
Summary: fmt.Sprintf("cannot parse %q as an integer", src.MustString()),
|
||||
Location: src.Location(),
|
||||
})
|
||||
}
|
||||
default:
|
||||
return config.NilValue, diags.Append(typeMismatch(config.KindInt, src))
|
||||
return dyn.NilValue, diags.Append(typeMismatch(dyn.KindInt, src))
|
||||
}
|
||||
|
||||
return config.NewValue(out, src.Location()), diags
|
||||
return dyn.NewValue(out, src.Location()), diags
|
||||
}
|
||||
|
||||
func normalizeFloat(typ reflect.Type, src config.Value) (config.Value, diag.Diagnostics) {
|
||||
func normalizeFloat(typ reflect.Type, src dyn.Value) (dyn.Value, diag.Diagnostics) {
|
||||
var diags diag.Diagnostics
|
||||
var out float64
|
||||
|
||||
switch src.Kind() {
|
||||
case config.KindFloat:
|
||||
case dyn.KindFloat:
|
||||
out = src.MustFloat()
|
||||
case config.KindString:
|
||||
case dyn.KindString:
|
||||
var err error
|
||||
out, err = strconv.ParseFloat(src.MustString(), 64)
|
||||
if err != nil {
|
||||
return config.NilValue, diags.Append(diag.Diagnostic{
|
||||
return dyn.NilValue, diags.Append(diag.Diagnostic{
|
||||
Severity: diag.Error,
|
||||
Summary: fmt.Sprintf("cannot parse %q as a floating point number", src.MustString()),
|
||||
Location: src.Location(),
|
||||
})
|
||||
}
|
||||
default:
|
||||
return config.NilValue, diags.Append(typeMismatch(config.KindFloat, src))
|
||||
return dyn.NilValue, diags.Append(typeMismatch(dyn.KindFloat, src))
|
||||
}
|
||||
|
||||
return config.NewValue(out, src.Location()), diags
|
||||
return dyn.NewValue(out, src.Location()), diags
|
||||
}
|
|
@ -3,8 +3,8 @@ package convert
|
|||
import (
|
||||
"testing"
|
||||
|
||||
"github.com/databricks/cli/libs/config"
|
||||
"github.com/databricks/cli/libs/diag"
|
||||
"github.com/databricks/cli/libs/dyn"
|
||||
"github.com/stretchr/testify/assert"
|
||||
)
|
||||
|
||||
|
@ -15,9 +15,9 @@ func TestNormalizeStruct(t *testing.T) {
|
|||
}
|
||||
|
||||
var typ Tmp
|
||||
vin := config.V(map[string]config.Value{
|
||||
"foo": config.V("bar"),
|
||||
"bar": config.V("baz"),
|
||||
vin := dyn.V(map[string]dyn.Value{
|
||||
"foo": dyn.V("bar"),
|
||||
"bar": dyn.V("baz"),
|
||||
})
|
||||
|
||||
vout, err := Normalize(typ, vin)
|
||||
|
@ -32,9 +32,9 @@ func TestNormalizeStructElementDiagnostic(t *testing.T) {
|
|||
}
|
||||
|
||||
var typ Tmp
|
||||
vin := config.V(map[string]config.Value{
|
||||
"foo": config.V("bar"),
|
||||
"bar": config.V(map[string]config.Value{"an": config.V("error")}),
|
||||
vin := dyn.V(map[string]dyn.Value{
|
||||
"foo": dyn.V("bar"),
|
||||
"bar": dyn.V(map[string]dyn.Value{"an": dyn.V("error")}),
|
||||
})
|
||||
|
||||
vout, err := Normalize(typ, vin)
|
||||
|
@ -42,7 +42,7 @@ func TestNormalizeStructElementDiagnostic(t *testing.T) {
|
|||
assert.Equal(t, diag.Diagnostic{
|
||||
Severity: diag.Error,
|
||||
Summary: `expected string, found map`,
|
||||
Location: config.Location{},
|
||||
Location: dyn.Location{},
|
||||
}, err[0])
|
||||
|
||||
// Elements that encounter an error during normalization are dropped.
|
||||
|
@ -57,9 +57,9 @@ func TestNormalizeStructUnknownField(t *testing.T) {
|
|||
}
|
||||
|
||||
var typ Tmp
|
||||
vin := config.V(map[string]config.Value{
|
||||
"foo": config.V("bar"),
|
||||
"bar": config.V("baz"),
|
||||
vin := dyn.V(map[string]dyn.Value{
|
||||
"foo": dyn.V("bar"),
|
||||
"bar": dyn.V("baz"),
|
||||
})
|
||||
|
||||
vout, err := Normalize(typ, vin)
|
||||
|
@ -82,7 +82,7 @@ func TestNormalizeStructNil(t *testing.T) {
|
|||
}
|
||||
|
||||
var typ Tmp
|
||||
vin := config.NilValue
|
||||
vin := dyn.NilValue
|
||||
vout, err := Normalize(typ, vin)
|
||||
assert.Empty(t, err)
|
||||
assert.Equal(t, vin, vout)
|
||||
|
@ -94,7 +94,7 @@ func TestNormalizeStructError(t *testing.T) {
|
|||
}
|
||||
|
||||
var typ Tmp
|
||||
vin := config.V("string")
|
||||
vin := dyn.V("string")
|
||||
_, err := Normalize(typ, vin)
|
||||
assert.Len(t, err, 1)
|
||||
assert.Equal(t, diag.Diagnostic{
|
||||
|
@ -106,9 +106,9 @@ func TestNormalizeStructError(t *testing.T) {
|
|||
|
||||
func TestNormalizeMap(t *testing.T) {
|
||||
var typ map[string]string
|
||||
vin := config.V(map[string]config.Value{
|
||||
"foo": config.V("bar"),
|
||||
"bar": config.V("baz"),
|
||||
vin := dyn.V(map[string]dyn.Value{
|
||||
"foo": dyn.V("bar"),
|
||||
"bar": dyn.V("baz"),
|
||||
})
|
||||
|
||||
vout, err := Normalize(typ, vin)
|
||||
|
@ -118,9 +118,9 @@ func TestNormalizeMap(t *testing.T) {
|
|||
|
||||
func TestNormalizeMapElementDiagnostic(t *testing.T) {
|
||||
var typ map[string]string
|
||||
vin := config.V(map[string]config.Value{
|
||||
"foo": config.V("bar"),
|
||||
"bar": config.V(map[string]config.Value{"an": config.V("error")}),
|
||||
vin := dyn.V(map[string]dyn.Value{
|
||||
"foo": dyn.V("bar"),
|
||||
"bar": dyn.V(map[string]dyn.Value{"an": dyn.V("error")}),
|
||||
})
|
||||
|
||||
vout, err := Normalize(typ, vin)
|
||||
|
@ -128,7 +128,7 @@ func TestNormalizeMapElementDiagnostic(t *testing.T) {
|
|||
assert.Equal(t, diag.Diagnostic{
|
||||
Severity: diag.Error,
|
||||
Summary: `expected string, found map`,
|
||||
Location: config.Location{},
|
||||
Location: dyn.Location{},
|
||||
}, err[0])
|
||||
|
||||
// Elements that encounter an error during normalization are dropped.
|
||||
|
@ -139,7 +139,7 @@ func TestNormalizeMapElementDiagnostic(t *testing.T) {
|
|||
|
||||
func TestNormalizeMapNil(t *testing.T) {
|
||||
var typ map[string]string
|
||||
vin := config.NilValue
|
||||
vin := dyn.NilValue
|
||||
vout, err := Normalize(typ, vin)
|
||||
assert.Empty(t, err)
|
||||
assert.Equal(t, vin, vout)
|
||||
|
@ -147,7 +147,7 @@ func TestNormalizeMapNil(t *testing.T) {
|
|||
|
||||
func TestNormalizeMapError(t *testing.T) {
|
||||
var typ map[string]string
|
||||
vin := config.V("string")
|
||||
vin := dyn.V("string")
|
||||
_, err := Normalize(typ, vin)
|
||||
assert.Len(t, err, 1)
|
||||
assert.Equal(t, diag.Diagnostic{
|
||||
|
@ -159,9 +159,9 @@ func TestNormalizeMapError(t *testing.T) {
|
|||
|
||||
func TestNormalizeSlice(t *testing.T) {
|
||||
var typ []string
|
||||
vin := config.V([]config.Value{
|
||||
config.V("foo"),
|
||||
config.V("bar"),
|
||||
vin := dyn.V([]dyn.Value{
|
||||
dyn.V("foo"),
|
||||
dyn.V("bar"),
|
||||
})
|
||||
|
||||
vout, err := Normalize(typ, vin)
|
||||
|
@ -171,10 +171,10 @@ func TestNormalizeSlice(t *testing.T) {
|
|||
|
||||
func TestNormalizeSliceElementDiagnostic(t *testing.T) {
|
||||
var typ []string
|
||||
vin := config.V([]config.Value{
|
||||
config.V("foo"),
|
||||
config.V("bar"),
|
||||
config.V(map[string]config.Value{"an": config.V("error")}),
|
||||
vin := dyn.V([]dyn.Value{
|
||||
dyn.V("foo"),
|
||||
dyn.V("bar"),
|
||||
dyn.V(map[string]dyn.Value{"an": dyn.V("error")}),
|
||||
})
|
||||
|
||||
vout, err := Normalize(typ, vin)
|
||||
|
@ -182,7 +182,7 @@ func TestNormalizeSliceElementDiagnostic(t *testing.T) {
|
|||
assert.Equal(t, diag.Diagnostic{
|
||||
Severity: diag.Error,
|
||||
Summary: `expected string, found map`,
|
||||
Location: config.Location{},
|
||||
Location: dyn.Location{},
|
||||
}, err[0])
|
||||
|
||||
// Elements that encounter an error during normalization are dropped.
|
||||
|
@ -191,7 +191,7 @@ func TestNormalizeSliceElementDiagnostic(t *testing.T) {
|
|||
|
||||
func TestNormalizeSliceNil(t *testing.T) {
|
||||
var typ []string
|
||||
vin := config.NilValue
|
||||
vin := dyn.NilValue
|
||||
vout, err := Normalize(typ, vin)
|
||||
assert.Empty(t, err)
|
||||
assert.Equal(t, vin, vout)
|
||||
|
@ -199,7 +199,7 @@ func TestNormalizeSliceNil(t *testing.T) {
|
|||
|
||||
func TestNormalizeSliceError(t *testing.T) {
|
||||
var typ []string
|
||||
vin := config.V("string")
|
||||
vin := dyn.V("string")
|
||||
_, err := Normalize(typ, vin)
|
||||
assert.Len(t, err, 1)
|
||||
assert.Equal(t, diag.Diagnostic{
|
||||
|
@ -211,7 +211,7 @@ func TestNormalizeSliceError(t *testing.T) {
|
|||
|
||||
func TestNormalizeString(t *testing.T) {
|
||||
var typ string
|
||||
vin := config.V("string")
|
||||
vin := dyn.V("string")
|
||||
vout, err := Normalize(&typ, vin)
|
||||
assert.Empty(t, err)
|
||||
assert.Equal(t, vin, vout)
|
||||
|
@ -219,7 +219,7 @@ func TestNormalizeString(t *testing.T) {
|
|||
|
||||
func TestNormalizeStringNil(t *testing.T) {
|
||||
var typ string
|
||||
vin := config.NewValue(nil, config.Location{File: "file", Line: 1, Column: 1})
|
||||
vin := dyn.NewValue(nil, dyn.Location{File: "file", Line: 1, Column: 1})
|
||||
_, err := Normalize(&typ, vin)
|
||||
assert.Len(t, err, 1)
|
||||
assert.Equal(t, diag.Diagnostic{
|
||||
|
@ -231,51 +231,51 @@ func TestNormalizeStringNil(t *testing.T) {
|
|||
|
||||
func TestNormalizeStringFromBool(t *testing.T) {
|
||||
var typ string
|
||||
vin := config.NewValue(true, config.Location{File: "file", Line: 1, Column: 1})
|
||||
vin := dyn.NewValue(true, dyn.Location{File: "file", Line: 1, Column: 1})
|
||||
vout, err := Normalize(&typ, vin)
|
||||
assert.Empty(t, err)
|
||||
assert.Equal(t, config.NewValue("true", vin.Location()), vout)
|
||||
assert.Equal(t, dyn.NewValue("true", vin.Location()), vout)
|
||||
}
|
||||
|
||||
func TestNormalizeStringFromInt(t *testing.T) {
|
||||
var typ string
|
||||
vin := config.NewValue(123, config.Location{File: "file", Line: 1, Column: 1})
|
||||
vin := dyn.NewValue(123, dyn.Location{File: "file", Line: 1, Column: 1})
|
||||
vout, err := Normalize(&typ, vin)
|
||||
assert.Empty(t, err)
|
||||
assert.Equal(t, config.NewValue("123", vin.Location()), vout)
|
||||
assert.Equal(t, dyn.NewValue("123", vin.Location()), vout)
|
||||
}
|
||||
|
||||
func TestNormalizeStringFromFloat(t *testing.T) {
|
||||
var typ string
|
||||
vin := config.NewValue(1.20, config.Location{File: "file", Line: 1, Column: 1})
|
||||
vin := dyn.NewValue(1.20, dyn.Location{File: "file", Line: 1, Column: 1})
|
||||
vout, err := Normalize(&typ, vin)
|
||||
assert.Empty(t, err)
|
||||
assert.Equal(t, config.NewValue("1.2", vin.Location()), vout)
|
||||
assert.Equal(t, dyn.NewValue("1.2", vin.Location()), vout)
|
||||
}
|
||||
|
||||
func TestNormalizeStringError(t *testing.T) {
|
||||
var typ string
|
||||
vin := config.V(map[string]config.Value{"an": config.V("error")})
|
||||
vin := dyn.V(map[string]dyn.Value{"an": dyn.V("error")})
|
||||
_, err := Normalize(&typ, vin)
|
||||
assert.Len(t, err, 1)
|
||||
assert.Equal(t, diag.Diagnostic{
|
||||
Severity: diag.Error,
|
||||
Summary: `expected string, found map`,
|
||||
Location: config.Location{},
|
||||
Location: dyn.Location{},
|
||||
}, err[0])
|
||||
}
|
||||
|
||||
func TestNormalizeBool(t *testing.T) {
|
||||
var typ bool
|
||||
vin := config.V(true)
|
||||
vin := dyn.V(true)
|
||||
vout, err := Normalize(&typ, vin)
|
||||
assert.Empty(t, err)
|
||||
assert.Equal(t, config.V(true), vout)
|
||||
assert.Equal(t, dyn.V(true), vout)
|
||||
}
|
||||
|
||||
func TestNormalizeBoolNil(t *testing.T) {
|
||||
var typ bool
|
||||
vin := config.NewValue(nil, config.Location{File: "file", Line: 1, Column: 1})
|
||||
vin := dyn.NewValue(nil, dyn.Location{File: "file", Line: 1, Column: 1})
|
||||
_, err := Normalize(&typ, vin)
|
||||
assert.Len(t, err, 1)
|
||||
assert.Equal(t, diag.Diagnostic{
|
||||
|
@ -299,16 +299,16 @@ func TestNormalizeBoolFromString(t *testing.T) {
|
|||
{"on", true},
|
||||
{"off", false},
|
||||
} {
|
||||
vin := config.V(c.Input)
|
||||
vin := dyn.V(c.Input)
|
||||
vout, err := Normalize(&typ, vin)
|
||||
assert.Empty(t, err)
|
||||
assert.Equal(t, config.V(c.Output), vout)
|
||||
assert.Equal(t, dyn.V(c.Output), vout)
|
||||
}
|
||||
}
|
||||
|
||||
func TestNormalizeBoolFromStringError(t *testing.T) {
|
||||
var typ bool
|
||||
vin := config.V("abc")
|
||||
vin := dyn.V("abc")
|
||||
_, err := Normalize(&typ, vin)
|
||||
assert.Len(t, err, 1)
|
||||
assert.Equal(t, diag.Diagnostic{
|
||||
|
@ -320,27 +320,27 @@ func TestNormalizeBoolFromStringError(t *testing.T) {
|
|||
|
||||
func TestNormalizeBoolError(t *testing.T) {
|
||||
var typ bool
|
||||
vin := config.V(map[string]config.Value{"an": config.V("error")})
|
||||
vin := dyn.V(map[string]dyn.Value{"an": dyn.V("error")})
|
||||
_, err := Normalize(&typ, vin)
|
||||
assert.Len(t, err, 1)
|
||||
assert.Equal(t, diag.Diagnostic{
|
||||
Severity: diag.Error,
|
||||
Summary: `expected bool, found map`,
|
||||
Location: config.Location{},
|
||||
Location: dyn.Location{},
|
||||
}, err[0])
|
||||
}
|
||||
|
||||
func TestNormalizeInt(t *testing.T) {
|
||||
var typ int
|
||||
vin := config.V(123)
|
||||
vin := dyn.V(123)
|
||||
vout, err := Normalize(&typ, vin)
|
||||
assert.Empty(t, err)
|
||||
assert.Equal(t, config.V(int64(123)), vout)
|
||||
assert.Equal(t, dyn.V(int64(123)), vout)
|
||||
}
|
||||
|
||||
func TestNormalizeIntNil(t *testing.T) {
|
||||
var typ int
|
||||
vin := config.NewValue(nil, config.Location{File: "file", Line: 1, Column: 1})
|
||||
vin := dyn.NewValue(nil, dyn.Location{File: "file", Line: 1, Column: 1})
|
||||
_, err := Normalize(&typ, vin)
|
||||
assert.Len(t, err, 1)
|
||||
assert.Equal(t, diag.Diagnostic{
|
||||
|
@ -352,15 +352,15 @@ func TestNormalizeIntNil(t *testing.T) {
|
|||
|
||||
func TestNormalizeIntFromString(t *testing.T) {
|
||||
var typ int
|
||||
vin := config.V("123")
|
||||
vin := dyn.V("123")
|
||||
vout, err := Normalize(&typ, vin)
|
||||
assert.Empty(t, err)
|
||||
assert.Equal(t, config.V(int64(123)), vout)
|
||||
assert.Equal(t, dyn.V(int64(123)), vout)
|
||||
}
|
||||
|
||||
func TestNormalizeIntFromStringError(t *testing.T) {
|
||||
var typ int
|
||||
vin := config.V("abc")
|
||||
vin := dyn.V("abc")
|
||||
_, err := Normalize(&typ, vin)
|
||||
assert.Len(t, err, 1)
|
||||
assert.Equal(t, diag.Diagnostic{
|
||||
|
@ -372,27 +372,27 @@ func TestNormalizeIntFromStringError(t *testing.T) {
|
|||
|
||||
func TestNormalizeIntError(t *testing.T) {
|
||||
var typ int
|
||||
vin := config.V(map[string]config.Value{"an": config.V("error")})
|
||||
vin := dyn.V(map[string]dyn.Value{"an": dyn.V("error")})
|
||||
_, err := Normalize(&typ, vin)
|
||||
assert.Len(t, err, 1)
|
||||
assert.Equal(t, diag.Diagnostic{
|
||||
Severity: diag.Error,
|
||||
Summary: `expected int, found map`,
|
||||
Location: config.Location{},
|
||||
Location: dyn.Location{},
|
||||
}, err[0])
|
||||
}
|
||||
|
||||
func TestNormalizeFloat(t *testing.T) {
|
||||
var typ float64
|
||||
vin := config.V(1.2)
|
||||
vin := dyn.V(1.2)
|
||||
vout, err := Normalize(&typ, vin)
|
||||
assert.Empty(t, err)
|
||||
assert.Equal(t, config.V(1.2), vout)
|
||||
assert.Equal(t, dyn.V(1.2), vout)
|
||||
}
|
||||
|
||||
func TestNormalizeFloatNil(t *testing.T) {
|
||||
var typ float64
|
||||
vin := config.NewValue(nil, config.Location{File: "file", Line: 1, Column: 1})
|
||||
vin := dyn.NewValue(nil, dyn.Location{File: "file", Line: 1, Column: 1})
|
||||
_, err := Normalize(&typ, vin)
|
||||
assert.Len(t, err, 1)
|
||||
assert.Equal(t, diag.Diagnostic{
|
||||
|
@ -404,15 +404,15 @@ func TestNormalizeFloatNil(t *testing.T) {
|
|||
|
||||
func TestNormalizeFloatFromString(t *testing.T) {
|
||||
var typ float64
|
||||
vin := config.V("1.2")
|
||||
vin := dyn.V("1.2")
|
||||
vout, err := Normalize(&typ, vin)
|
||||
assert.Empty(t, err)
|
||||
assert.Equal(t, config.V(1.2), vout)
|
||||
assert.Equal(t, dyn.V(1.2), vout)
|
||||
}
|
||||
|
||||
func TestNormalizeFloatFromStringError(t *testing.T) {
|
||||
var typ float64
|
||||
vin := config.V("abc")
|
||||
vin := dyn.V("abc")
|
||||
_, err := Normalize(&typ, vin)
|
||||
assert.Len(t, err, 1)
|
||||
assert.Equal(t, diag.Diagnostic{
|
||||
|
@ -424,12 +424,12 @@ func TestNormalizeFloatFromStringError(t *testing.T) {
|
|||
|
||||
func TestNormalizeFloatError(t *testing.T) {
|
||||
var typ float64
|
||||
vin := config.V(map[string]config.Value{"an": config.V("error")})
|
||||
vin := dyn.V(map[string]dyn.Value{"an": dyn.V("error")})
|
||||
_, err := Normalize(&typ, vin)
|
||||
assert.Len(t, err, 1)
|
||||
assert.Equal(t, diag.Diagnostic{
|
||||
Severity: diag.Error,
|
||||
Summary: `expected float, found map`,
|
||||
Location: config.Location{},
|
||||
Location: dyn.Location{},
|
||||
}, err[0])
|
||||
}
|
|
@ -5,16 +5,16 @@ import (
|
|||
"strings"
|
||||
"sync"
|
||||
|
||||
"github.com/databricks/cli/libs/config"
|
||||
"github.com/databricks/cli/libs/dyn"
|
||||
)
|
||||
|
||||
// structInfo holds the type information we need to efficiently
|
||||
// convert data from a [config.Value] to a Go struct.
|
||||
// convert data from a [dyn.Value] to a Go struct.
|
||||
type structInfo struct {
|
||||
// Fields maps the JSON-name of the field to the field's index for use with [FieldByIndex].
|
||||
Fields map[string][]int
|
||||
|
||||
// ValueField maps to the field with a [config.Value].
|
||||
// ValueField maps to the field with a [dyn.Value].
|
||||
// The underlying type is expected to only have one of these.
|
||||
ValueField []int
|
||||
}
|
||||
|
@ -74,10 +74,10 @@ func buildStructInfo(typ reflect.Type) structInfo {
|
|||
continue
|
||||
}
|
||||
|
||||
// If this field has type [config.Value], we populate it with the source [config.Value] from [ToTyped].
|
||||
// If this field has type [dyn.Value], we populate it with the source [dyn.Value] from [ToTyped].
|
||||
if sf.IsExported() && sf.Type == configValueType {
|
||||
if out.ValueField != nil {
|
||||
panic("multiple config.Value fields")
|
||||
panic("multiple dyn.Value fields")
|
||||
}
|
||||
out.ValueField = append(prefix, sf.Index...)
|
||||
continue
|
||||
|
@ -129,5 +129,5 @@ func (s *structInfo) FieldValues(v reflect.Value) map[string]reflect.Value {
|
|||
return out
|
||||
}
|
||||
|
||||
// Type of [config.Value].
|
||||
var configValueType = reflect.TypeOf((*config.Value)(nil)).Elem()
|
||||
// Type of [dyn.Value].
|
||||
var configValueType = reflect.TypeOf((*dyn.Value)(nil)).Elem()
|
|
@ -4,7 +4,7 @@ import (
|
|||
"reflect"
|
||||
"testing"
|
||||
|
||||
"github.com/databricks/cli/libs/config"
|
||||
"github.com/databricks/cli/libs/dyn"
|
||||
"github.com/stretchr/testify/assert"
|
||||
)
|
||||
|
||||
|
@ -207,7 +207,7 @@ func TestStructInfoValueFieldAbsent(t *testing.T) {
|
|||
|
||||
func TestStructInfoValueFieldPresent(t *testing.T) {
|
||||
type Tmp struct {
|
||||
Foo config.Value
|
||||
Foo dyn.Value
|
||||
}
|
||||
|
||||
si := getStructInfo(reflect.TypeOf(Tmp{}))
|
||||
|
@ -216,8 +216,8 @@ func TestStructInfoValueFieldPresent(t *testing.T) {
|
|||
|
||||
func TestStructInfoValueFieldMultiple(t *testing.T) {
|
||||
type Tmp struct {
|
||||
Foo config.Value
|
||||
Bar config.Value
|
||||
Foo dyn.Value
|
||||
Bar dyn.Value
|
||||
}
|
||||
|
||||
assert.Panics(t, func() {
|
|
@ -5,17 +5,17 @@ import (
|
|||
"reflect"
|
||||
"strconv"
|
||||
|
||||
"github.com/databricks/cli/libs/config"
|
||||
"github.com/databricks/cli/libs/dyn"
|
||||
)
|
||||
|
||||
func ToTyped(dst any, src config.Value) error {
|
||||
func ToTyped(dst any, src dyn.Value) error {
|
||||
dstv := reflect.ValueOf(dst)
|
||||
|
||||
// Dereference pointer if necessary
|
||||
for dstv.Kind() == reflect.Pointer {
|
||||
// If the source value is nil and the destination is a settable pointer,
|
||||
// set the destination to nil. Also see `end_to_end_test.go`.
|
||||
if dstv.CanSet() && src == config.NilValue {
|
||||
if dstv.CanSet() && src == dyn.NilValue {
|
||||
dstv.SetZero()
|
||||
return nil
|
||||
}
|
||||
|
@ -50,9 +50,9 @@ func ToTyped(dst any, src config.Value) error {
|
|||
return fmt.Errorf("unsupported type: %s", dstv.Kind())
|
||||
}
|
||||
|
||||
func toTypedStruct(dst reflect.Value, src config.Value) error {
|
||||
func toTypedStruct(dst reflect.Value, src dyn.Value) error {
|
||||
switch src.Kind() {
|
||||
case config.KindMap:
|
||||
case dyn.KindMap:
|
||||
info := getStructInfo(dst.Type())
|
||||
for k, v := range src.MustMap() {
|
||||
index, ok := info.Fields[k]
|
||||
|
@ -83,14 +83,14 @@ func toTypedStruct(dst reflect.Value, src config.Value) error {
|
|||
}
|
||||
}
|
||||
|
||||
// Populate field(s) for [config.Value], if any.
|
||||
// Populate field(s) for [dyn.Value], if any.
|
||||
if info.ValueField != nil {
|
||||
vv := dst.FieldByIndex(info.ValueField)
|
||||
vv.Set(reflect.ValueOf(src))
|
||||
}
|
||||
|
||||
return nil
|
||||
case config.KindNil:
|
||||
case dyn.KindNil:
|
||||
dst.SetZero()
|
||||
return nil
|
||||
}
|
||||
|
@ -101,9 +101,9 @@ func toTypedStruct(dst reflect.Value, src config.Value) error {
|
|||
}
|
||||
}
|
||||
|
||||
func toTypedMap(dst reflect.Value, src config.Value) error {
|
||||
func toTypedMap(dst reflect.Value, src dyn.Value) error {
|
||||
switch src.Kind() {
|
||||
case config.KindMap:
|
||||
case dyn.KindMap:
|
||||
m := src.MustMap()
|
||||
|
||||
// Always overwrite.
|
||||
|
@ -118,7 +118,7 @@ func toTypedMap(dst reflect.Value, src config.Value) error {
|
|||
dst.SetMapIndex(kv, vv.Elem())
|
||||
}
|
||||
return nil
|
||||
case config.KindNil:
|
||||
case dyn.KindNil:
|
||||
dst.SetZero()
|
||||
return nil
|
||||
}
|
||||
|
@ -129,9 +129,9 @@ func toTypedMap(dst reflect.Value, src config.Value) error {
|
|||
}
|
||||
}
|
||||
|
||||
func toTypedSlice(dst reflect.Value, src config.Value) error {
|
||||
func toTypedSlice(dst reflect.Value, src dyn.Value) error {
|
||||
switch src.Kind() {
|
||||
case config.KindSequence:
|
||||
case dyn.KindSequence:
|
||||
seq := src.MustSequence()
|
||||
|
||||
// Always overwrite.
|
||||
|
@ -143,7 +143,7 @@ func toTypedSlice(dst reflect.Value, src config.Value) error {
|
|||
}
|
||||
}
|
||||
return nil
|
||||
case config.KindNil:
|
||||
case dyn.KindNil:
|
||||
dst.SetZero()
|
||||
return nil
|
||||
}
|
||||
|
@ -154,18 +154,18 @@ func toTypedSlice(dst reflect.Value, src config.Value) error {
|
|||
}
|
||||
}
|
||||
|
||||
func toTypedString(dst reflect.Value, src config.Value) error {
|
||||
func toTypedString(dst reflect.Value, src dyn.Value) error {
|
||||
switch src.Kind() {
|
||||
case config.KindString:
|
||||
case dyn.KindString:
|
||||
dst.SetString(src.MustString())
|
||||
return nil
|
||||
case config.KindBool:
|
||||
case dyn.KindBool:
|
||||
dst.SetString(strconv.FormatBool(src.MustBool()))
|
||||
return nil
|
||||
case config.KindInt:
|
||||
case dyn.KindInt:
|
||||
dst.SetString(strconv.FormatInt(src.MustInt(), 10))
|
||||
return nil
|
||||
case config.KindFloat:
|
||||
case dyn.KindFloat:
|
||||
dst.SetString(strconv.FormatFloat(src.MustFloat(), 'f', -1, 64))
|
||||
return nil
|
||||
}
|
||||
|
@ -176,12 +176,12 @@ func toTypedString(dst reflect.Value, src config.Value) error {
|
|||
}
|
||||
}
|
||||
|
||||
func toTypedBool(dst reflect.Value, src config.Value) error {
|
||||
func toTypedBool(dst reflect.Value, src dyn.Value) error {
|
||||
switch src.Kind() {
|
||||
case config.KindBool:
|
||||
case dyn.KindBool:
|
||||
dst.SetBool(src.MustBool())
|
||||
return nil
|
||||
case config.KindString:
|
||||
case dyn.KindString:
|
||||
// See https://github.com/go-yaml/yaml/blob/f6f7691b1fdeb513f56608cd2c32c51f8194bf51/decode.go#L684-L693.
|
||||
switch src.MustString() {
|
||||
case "y", "Y", "yes", "Yes", "YES", "on", "On", "ON":
|
||||
|
@ -199,12 +199,12 @@ func toTypedBool(dst reflect.Value, src config.Value) error {
|
|||
}
|
||||
}
|
||||
|
||||
func toTypedInt(dst reflect.Value, src config.Value) error {
|
||||
func toTypedInt(dst reflect.Value, src dyn.Value) error {
|
||||
switch src.Kind() {
|
||||
case config.KindInt:
|
||||
case dyn.KindInt:
|
||||
dst.SetInt(src.MustInt())
|
||||
return nil
|
||||
case config.KindString:
|
||||
case dyn.KindString:
|
||||
if i64, err := strconv.ParseInt(src.MustString(), 10, 64); err == nil {
|
||||
dst.SetInt(i64)
|
||||
return nil
|
||||
|
@ -217,12 +217,12 @@ func toTypedInt(dst reflect.Value, src config.Value) error {
|
|||
}
|
||||
}
|
||||
|
||||
func toTypedFloat(dst reflect.Value, src config.Value) error {
|
||||
func toTypedFloat(dst reflect.Value, src dyn.Value) error {
|
||||
switch src.Kind() {
|
||||
case config.KindFloat:
|
||||
case dyn.KindFloat:
|
||||
dst.SetFloat(src.MustFloat())
|
||||
return nil
|
||||
case config.KindString:
|
||||
case dyn.KindString:
|
||||
if f64, err := strconv.ParseFloat(src.MustString(), 64); err == nil {
|
||||
dst.SetFloat(f64)
|
||||
return nil
|
|
@ -3,7 +3,7 @@ package convert
|
|||
import (
|
||||
"testing"
|
||||
|
||||
"github.com/databricks/cli/libs/config"
|
||||
"github.com/databricks/cli/libs/dyn"
|
||||
"github.com/stretchr/testify/assert"
|
||||
"github.com/stretchr/testify/require"
|
||||
)
|
||||
|
@ -21,9 +21,9 @@ func TestToTypedStruct(t *testing.T) {
|
|||
}
|
||||
|
||||
var out Tmp
|
||||
v := config.V(map[string]config.Value{
|
||||
"foo": config.V("bar"),
|
||||
"bar": config.V("baz"),
|
||||
v := dyn.V(map[string]dyn.Value{
|
||||
"foo": dyn.V("bar"),
|
||||
"bar": dyn.V("baz"),
|
||||
})
|
||||
|
||||
err := ToTyped(&out, v)
|
||||
|
@ -48,9 +48,9 @@ func TestToTypedStructOverwrite(t *testing.T) {
|
|||
Foo: "baz",
|
||||
Bar: "qux",
|
||||
}
|
||||
v := config.V(map[string]config.Value{
|
||||
"foo": config.V("bar"),
|
||||
"bar": config.V("baz"),
|
||||
v := dyn.V(map[string]dyn.Value{
|
||||
"foo": dyn.V("bar"),
|
||||
"bar": dyn.V("baz"),
|
||||
})
|
||||
|
||||
err := ToTyped(&out, v)
|
||||
|
@ -74,9 +74,9 @@ func TestToTypedStructAnonymousByValue(t *testing.T) {
|
|||
}
|
||||
|
||||
var out Tmp
|
||||
v := config.V(map[string]config.Value{
|
||||
"foo": config.V("bar"),
|
||||
"bar": config.V("baz"),
|
||||
v := dyn.V(map[string]dyn.Value{
|
||||
"foo": dyn.V("bar"),
|
||||
"bar": dyn.V("baz"),
|
||||
})
|
||||
|
||||
err := ToTyped(&out, v)
|
||||
|
@ -100,9 +100,9 @@ func TestToTypedStructAnonymousByPointer(t *testing.T) {
|
|||
}
|
||||
|
||||
var out Tmp
|
||||
v := config.V(map[string]config.Value{
|
||||
"foo": config.V("bar"),
|
||||
"bar": config.V("baz"),
|
||||
v := dyn.V(map[string]dyn.Value{
|
||||
"foo": dyn.V("bar"),
|
||||
"bar": dyn.V("baz"),
|
||||
})
|
||||
|
||||
err := ToTyped(&out, v)
|
||||
|
@ -117,7 +117,7 @@ func TestToTypedStructNil(t *testing.T) {
|
|||
}
|
||||
|
||||
var out = Tmp{}
|
||||
err := ToTyped(&out, config.NilValue)
|
||||
err := ToTyped(&out, dyn.NilValue)
|
||||
require.NoError(t, err)
|
||||
assert.Equal(t, Tmp{}, out)
|
||||
}
|
||||
|
@ -128,7 +128,7 @@ func TestToTypedStructNilOverwrite(t *testing.T) {
|
|||
}
|
||||
|
||||
var out = Tmp{"bar"}
|
||||
err := ToTyped(&out, config.NilValue)
|
||||
err := ToTyped(&out, dyn.NilValue)
|
||||
require.NoError(t, err)
|
||||
assert.Equal(t, Tmp{}, out)
|
||||
}
|
||||
|
@ -137,12 +137,12 @@ func TestToTypedStructWithValueField(t *testing.T) {
|
|||
type Tmp struct {
|
||||
Foo string `json:"foo"`
|
||||
|
||||
ConfigValue config.Value
|
||||
ConfigValue dyn.Value
|
||||
}
|
||||
|
||||
var out Tmp
|
||||
v := config.V(map[string]config.Value{
|
||||
"foo": config.V("bar"),
|
||||
v := dyn.V(map[string]dyn.Value{
|
||||
"foo": dyn.V("bar"),
|
||||
})
|
||||
|
||||
err := ToTyped(&out, v)
|
||||
|
@ -154,8 +154,8 @@ func TestToTypedStructWithValueField(t *testing.T) {
|
|||
func TestToTypedMap(t *testing.T) {
|
||||
var out = map[string]string{}
|
||||
|
||||
v := config.V(map[string]config.Value{
|
||||
"key": config.V("value"),
|
||||
v := dyn.V(map[string]dyn.Value{
|
||||
"key": dyn.V("value"),
|
||||
})
|
||||
|
||||
err := ToTyped(&out, v)
|
||||
|
@ -169,8 +169,8 @@ func TestToTypedMapOverwrite(t *testing.T) {
|
|||
"foo": "bar",
|
||||
}
|
||||
|
||||
v := config.V(map[string]config.Value{
|
||||
"bar": config.V("qux"),
|
||||
v := dyn.V(map[string]dyn.Value{
|
||||
"bar": dyn.V("qux"),
|
||||
})
|
||||
|
||||
err := ToTyped(&out, v)
|
||||
|
@ -182,8 +182,8 @@ func TestToTypedMapOverwrite(t *testing.T) {
|
|||
func TestToTypedMapWithPointerElement(t *testing.T) {
|
||||
var out map[string]*string
|
||||
|
||||
v := config.V(map[string]config.Value{
|
||||
"key": config.V("value"),
|
||||
v := dyn.V(map[string]dyn.Value{
|
||||
"key": dyn.V("value"),
|
||||
})
|
||||
|
||||
err := ToTyped(&out, v)
|
||||
|
@ -194,7 +194,7 @@ func TestToTypedMapWithPointerElement(t *testing.T) {
|
|||
|
||||
func TestToTypedMapNil(t *testing.T) {
|
||||
var out = map[string]string{}
|
||||
err := ToTyped(&out, config.NilValue)
|
||||
err := ToTyped(&out, dyn.NilValue)
|
||||
require.NoError(t, err)
|
||||
assert.Nil(t, out)
|
||||
}
|
||||
|
@ -203,7 +203,7 @@ func TestToTypedMapNilOverwrite(t *testing.T) {
|
|||
var out = map[string]string{
|
||||
"foo": "bar",
|
||||
}
|
||||
err := ToTyped(&out, config.NilValue)
|
||||
err := ToTyped(&out, dyn.NilValue)
|
||||
require.NoError(t, err)
|
||||
assert.Nil(t, out)
|
||||
}
|
||||
|
@ -211,9 +211,9 @@ func TestToTypedMapNilOverwrite(t *testing.T) {
|
|||
func TestToTypedSlice(t *testing.T) {
|
||||
var out []string
|
||||
|
||||
v := config.V([]config.Value{
|
||||
config.V("foo"),
|
||||
config.V("bar"),
|
||||
v := dyn.V([]dyn.Value{
|
||||
dyn.V("foo"),
|
||||
dyn.V("bar"),
|
||||
})
|
||||
|
||||
err := ToTyped(&out, v)
|
||||
|
@ -226,9 +226,9 @@ func TestToTypedSlice(t *testing.T) {
|
|||
func TestToTypedSliceOverwrite(t *testing.T) {
|
||||
var out = []string{"qux"}
|
||||
|
||||
v := config.V([]config.Value{
|
||||
config.V("foo"),
|
||||
config.V("bar"),
|
||||
v := dyn.V([]dyn.Value{
|
||||
dyn.V("foo"),
|
||||
dyn.V("bar"),
|
||||
})
|
||||
|
||||
err := ToTyped(&out, v)
|
||||
|
@ -241,9 +241,9 @@ func TestToTypedSliceOverwrite(t *testing.T) {
|
|||
func TestToTypedSliceWithPointerElement(t *testing.T) {
|
||||
var out []*string
|
||||
|
||||
v := config.V([]config.Value{
|
||||
config.V("foo"),
|
||||
config.V("bar"),
|
||||
v := dyn.V([]dyn.Value{
|
||||
dyn.V("foo"),
|
||||
dyn.V("bar"),
|
||||
})
|
||||
|
||||
err := ToTyped(&out, v)
|
||||
|
@ -255,63 +255,63 @@ func TestToTypedSliceWithPointerElement(t *testing.T) {
|
|||
|
||||
func TestToTypedSliceNil(t *testing.T) {
|
||||
var out []string
|
||||
err := ToTyped(&out, config.NilValue)
|
||||
err := ToTyped(&out, dyn.NilValue)
|
||||
require.NoError(t, err)
|
||||
assert.Nil(t, out)
|
||||
}
|
||||
|
||||
func TestToTypedSliceNilOverwrite(t *testing.T) {
|
||||
var out = []string{"foo"}
|
||||
err := ToTyped(&out, config.NilValue)
|
||||
err := ToTyped(&out, dyn.NilValue)
|
||||
require.NoError(t, err)
|
||||
assert.Nil(t, out)
|
||||
}
|
||||
|
||||
func TestToTypedString(t *testing.T) {
|
||||
var out string
|
||||
err := ToTyped(&out, config.V("foo"))
|
||||
err := ToTyped(&out, dyn.V("foo"))
|
||||
require.NoError(t, err)
|
||||
assert.Equal(t, "foo", out)
|
||||
}
|
||||
|
||||
func TestToTypedStringOverwrite(t *testing.T) {
|
||||
var out string = "bar"
|
||||
err := ToTyped(&out, config.V("foo"))
|
||||
err := ToTyped(&out, dyn.V("foo"))
|
||||
require.NoError(t, err)
|
||||
assert.Equal(t, "foo", out)
|
||||
}
|
||||
|
||||
func TestToTypedStringFromBool(t *testing.T) {
|
||||
var out string
|
||||
err := ToTyped(&out, config.V(true))
|
||||
err := ToTyped(&out, dyn.V(true))
|
||||
require.NoError(t, err)
|
||||
assert.Equal(t, "true", out)
|
||||
}
|
||||
|
||||
func TestToTypedStringFromInt(t *testing.T) {
|
||||
var out string
|
||||
err := ToTyped(&out, config.V(123))
|
||||
err := ToTyped(&out, dyn.V(123))
|
||||
require.NoError(t, err)
|
||||
assert.Equal(t, "123", out)
|
||||
}
|
||||
|
||||
func TestToTypedStringFromFloat(t *testing.T) {
|
||||
var out string
|
||||
err := ToTyped(&out, config.V(1.2))
|
||||
err := ToTyped(&out, dyn.V(1.2))
|
||||
require.NoError(t, err)
|
||||
assert.Equal(t, "1.2", out)
|
||||
}
|
||||
|
||||
func TestToTypedBool(t *testing.T) {
|
||||
var out bool
|
||||
err := ToTyped(&out, config.V(true))
|
||||
err := ToTyped(&out, dyn.V(true))
|
||||
require.NoError(t, err)
|
||||
assert.Equal(t, true, out)
|
||||
}
|
||||
|
||||
func TestToTypedBoolOverwrite(t *testing.T) {
|
||||
var out bool = true
|
||||
err := ToTyped(&out, config.V(false))
|
||||
err := ToTyped(&out, dyn.V(false))
|
||||
require.NoError(t, err)
|
||||
assert.Equal(t, false, out)
|
||||
}
|
||||
|
@ -321,128 +321,128 @@ func TestToTypedBoolFromString(t *testing.T) {
|
|||
|
||||
// True-ish
|
||||
for _, v := range []string{"y", "yes", "on"} {
|
||||
err := ToTyped(&out, config.V(v))
|
||||
err := ToTyped(&out, dyn.V(v))
|
||||
require.NoError(t, err)
|
||||
assert.Equal(t, true, out)
|
||||
}
|
||||
|
||||
// False-ish
|
||||
for _, v := range []string{"n", "no", "off"} {
|
||||
err := ToTyped(&out, config.V(v))
|
||||
err := ToTyped(&out, dyn.V(v))
|
||||
require.NoError(t, err)
|
||||
assert.Equal(t, false, out)
|
||||
}
|
||||
|
||||
// Other
|
||||
err := ToTyped(&out, config.V("${var.foo}"))
|
||||
err := ToTyped(&out, dyn.V("${var.foo}"))
|
||||
require.Error(t, err)
|
||||
}
|
||||
|
||||
func TestToTypedInt(t *testing.T) {
|
||||
var out int
|
||||
err := ToTyped(&out, config.V(1234))
|
||||
err := ToTyped(&out, dyn.V(1234))
|
||||
require.NoError(t, err)
|
||||
assert.Equal(t, int(1234), out)
|
||||
}
|
||||
|
||||
func TestToTypedInt32(t *testing.T) {
|
||||
var out32 int32
|
||||
err := ToTyped(&out32, config.V(1235))
|
||||
err := ToTyped(&out32, dyn.V(1235))
|
||||
require.NoError(t, err)
|
||||
assert.Equal(t, int32(1235), out32)
|
||||
}
|
||||
|
||||
func TestToTypedInt64(t *testing.T) {
|
||||
var out64 int64
|
||||
err := ToTyped(&out64, config.V(1236))
|
||||
err := ToTyped(&out64, dyn.V(1236))
|
||||
require.NoError(t, err)
|
||||
assert.Equal(t, int64(1236), out64)
|
||||
}
|
||||
|
||||
func TestToTypedIntOverwrite(t *testing.T) {
|
||||
var out int = 123
|
||||
err := ToTyped(&out, config.V(1234))
|
||||
err := ToTyped(&out, dyn.V(1234))
|
||||
require.NoError(t, err)
|
||||
assert.Equal(t, int(1234), out)
|
||||
}
|
||||
|
||||
func TestToTypedInt32Overwrite(t *testing.T) {
|
||||
var out32 int32 = 123
|
||||
err := ToTyped(&out32, config.V(1234))
|
||||
err := ToTyped(&out32, dyn.V(1234))
|
||||
require.NoError(t, err)
|
||||
assert.Equal(t, int32(1234), out32)
|
||||
}
|
||||
|
||||
func TestToTypedInt64Overwrite(t *testing.T) {
|
||||
var out64 int64 = 123
|
||||
err := ToTyped(&out64, config.V(1234))
|
||||
err := ToTyped(&out64, dyn.V(1234))
|
||||
require.NoError(t, err)
|
||||
assert.Equal(t, int64(1234), out64)
|
||||
}
|
||||
|
||||
func TestToTypedIntFromStringError(t *testing.T) {
|
||||
var out int
|
||||
err := ToTyped(&out, config.V("abc"))
|
||||
err := ToTyped(&out, dyn.V("abc"))
|
||||
require.Error(t, err)
|
||||
}
|
||||
|
||||
func TestToTypedIntFromStringInt(t *testing.T) {
|
||||
var out int
|
||||
err := ToTyped(&out, config.V("123"))
|
||||
err := ToTyped(&out, dyn.V("123"))
|
||||
require.NoError(t, err)
|
||||
assert.Equal(t, int(123), out)
|
||||
}
|
||||
|
||||
func TestToTypedFloat32(t *testing.T) {
|
||||
var out float32
|
||||
err := ToTyped(&out, config.V(float32(1.0)))
|
||||
err := ToTyped(&out, dyn.V(float32(1.0)))
|
||||
require.NoError(t, err)
|
||||
assert.Equal(t, float32(1.0), out)
|
||||
}
|
||||
|
||||
func TestToTypedFloat64(t *testing.T) {
|
||||
var out float64
|
||||
err := ToTyped(&out, config.V(float64(1.0)))
|
||||
err := ToTyped(&out, dyn.V(float64(1.0)))
|
||||
require.NoError(t, err)
|
||||
assert.Equal(t, float64(1.0), out)
|
||||
}
|
||||
|
||||
func TestToTypedFloat32Overwrite(t *testing.T) {
|
||||
var out float32 = 1.0
|
||||
err := ToTyped(&out, config.V(float32(2.0)))
|
||||
err := ToTyped(&out, dyn.V(float32(2.0)))
|
||||
require.NoError(t, err)
|
||||
assert.Equal(t, float32(2.0), out)
|
||||
}
|
||||
|
||||
func TestToTypedFloat64Overwrite(t *testing.T) {
|
||||
var out float64 = 1.0
|
||||
err := ToTyped(&out, config.V(float64(2.0)))
|
||||
err := ToTyped(&out, dyn.V(float64(2.0)))
|
||||
require.NoError(t, err)
|
||||
assert.Equal(t, float64(2.0), out)
|
||||
}
|
||||
|
||||
func TestToTypedFloat32FromStringError(t *testing.T) {
|
||||
var out float32
|
||||
err := ToTyped(&out, config.V("abc"))
|
||||
err := ToTyped(&out, dyn.V("abc"))
|
||||
require.Error(t, err)
|
||||
}
|
||||
|
||||
func TestToTypedFloat64FromStringError(t *testing.T) {
|
||||
var out float64
|
||||
err := ToTyped(&out, config.V("abc"))
|
||||
err := ToTyped(&out, dyn.V("abc"))
|
||||
require.Error(t, err)
|
||||
}
|
||||
|
||||
func TestToTypedFloat32FromString(t *testing.T) {
|
||||
var out float32
|
||||
err := ToTyped(&out, config.V("1.2"))
|
||||
err := ToTyped(&out, dyn.V("1.2"))
|
||||
require.NoError(t, err)
|
||||
assert.Equal(t, float32(1.2), out)
|
||||
}
|
||||
|
||||
func TestToTypedFloat64FromString(t *testing.T) {
|
||||
var out float64
|
||||
err := ToTyped(&out, config.V("1.2"))
|
||||
err := ToTyped(&out, dyn.V("1.2"))
|
||||
require.NoError(t, err)
|
||||
assert.Equal(t, float64(1.2), out)
|
||||
}
|
|
@ -1,4 +1,4 @@
|
|||
package config
|
||||
package dyn
|
||||
|
||||
import "time"
|
||||
|
|
@ -1,4 +1,4 @@
|
|||
package config
|
||||
package dyn
|
||||
|
||||
import "fmt"
|
||||
|
|
@ -1,13 +1,13 @@
|
|||
package config_test
|
||||
package dyn_test
|
||||
|
||||
import (
|
||||
"testing"
|
||||
|
||||
"github.com/databricks/cli/libs/config"
|
||||
"github.com/databricks/cli/libs/dyn"
|
||||
"github.com/stretchr/testify/assert"
|
||||
)
|
||||
|
||||
func TestLocation(t *testing.T) {
|
||||
loc := config.Location{File: "file", Line: 1, Column: 2}
|
||||
loc := dyn.Location{File: "file", Line: 1, Column: 2}
|
||||
assert.Equal(t, "file:1:2", loc.String())
|
||||
}
|
|
@ -3,7 +3,7 @@ package merge
|
|||
import (
|
||||
"fmt"
|
||||
|
||||
"github.com/databricks/cli/libs/config"
|
||||
"github.com/databricks/cli/libs/dyn"
|
||||
)
|
||||
|
||||
// Merge recursively merges the specified values.
|
||||
|
@ -12,46 +12,46 @@ import (
|
|||
// * Merging x with nil or nil with x always yields x.
|
||||
// * Merging maps a and b means entries from map b take precedence.
|
||||
// * Merging sequences a and b means concatenating them.
|
||||
func Merge(a, b config.Value) (config.Value, error) {
|
||||
func Merge(a, b dyn.Value) (dyn.Value, error) {
|
||||
return merge(a, b)
|
||||
}
|
||||
|
||||
func merge(a, b config.Value) (config.Value, error) {
|
||||
func merge(a, b dyn.Value) (dyn.Value, error) {
|
||||
ak := a.Kind()
|
||||
bk := b.Kind()
|
||||
|
||||
// If a is nil, return b.
|
||||
if ak == config.KindNil {
|
||||
if ak == dyn.KindNil {
|
||||
return b, nil
|
||||
}
|
||||
|
||||
// If b is nil, return a.
|
||||
if bk == config.KindNil {
|
||||
if bk == dyn.KindNil {
|
||||
return a, nil
|
||||
}
|
||||
|
||||
// Call the appropriate merge function based on the kind of a and b.
|
||||
switch ak {
|
||||
case config.KindMap:
|
||||
if bk != config.KindMap {
|
||||
return config.NilValue, fmt.Errorf("cannot merge map with %s", bk)
|
||||
case dyn.KindMap:
|
||||
if bk != dyn.KindMap {
|
||||
return dyn.NilValue, fmt.Errorf("cannot merge map with %s", bk)
|
||||
}
|
||||
return mergeMap(a, b)
|
||||
case config.KindSequence:
|
||||
if bk != config.KindSequence {
|
||||
return config.NilValue, fmt.Errorf("cannot merge sequence with %s", bk)
|
||||
case dyn.KindSequence:
|
||||
if bk != dyn.KindSequence {
|
||||
return dyn.NilValue, fmt.Errorf("cannot merge sequence with %s", bk)
|
||||
}
|
||||
return mergeSequence(a, b)
|
||||
default:
|
||||
if ak != bk {
|
||||
return config.NilValue, fmt.Errorf("cannot merge %s with %s", ak, bk)
|
||||
return dyn.NilValue, fmt.Errorf("cannot merge %s with %s", ak, bk)
|
||||
}
|
||||
return mergePrimitive(a, b)
|
||||
}
|
||||
}
|
||||
|
||||
func mergeMap(a, b config.Value) (config.Value, error) {
|
||||
out := make(map[string]config.Value)
|
||||
func mergeMap(a, b dyn.Value) (dyn.Value, error) {
|
||||
out := make(map[string]dyn.Value)
|
||||
am := a.MustMap()
|
||||
bm := b.MustMap()
|
||||
|
||||
|
@ -66,7 +66,7 @@ func mergeMap(a, b config.Value) (config.Value, error) {
|
|||
// If the key already exists, merge the values.
|
||||
merged, err := merge(out[k], v)
|
||||
if err != nil {
|
||||
return config.NilValue, err
|
||||
return dyn.NilValue, err
|
||||
}
|
||||
out[k] = merged
|
||||
} else {
|
||||
|
@ -76,23 +76,23 @@ func mergeMap(a, b config.Value) (config.Value, error) {
|
|||
}
|
||||
|
||||
// Preserve the location of the first value.
|
||||
return config.NewValue(out, a.Location()), nil
|
||||
return dyn.NewValue(out, a.Location()), nil
|
||||
}
|
||||
|
||||
func mergeSequence(a, b config.Value) (config.Value, error) {
|
||||
func mergeSequence(a, b dyn.Value) (dyn.Value, error) {
|
||||
as := a.MustSequence()
|
||||
bs := b.MustSequence()
|
||||
|
||||
// Merging sequences means concatenating them.
|
||||
out := make([]config.Value, len(as)+len(bs))
|
||||
out := make([]dyn.Value, len(as)+len(bs))
|
||||
copy(out[:], as)
|
||||
copy(out[len(as):], bs)
|
||||
|
||||
// Preserve the location of the first value.
|
||||
return config.NewValue(out, a.Location()), nil
|
||||
return dyn.NewValue(out, a.Location()), nil
|
||||
}
|
||||
|
||||
func mergePrimitive(a, b config.Value) (config.Value, error) {
|
||||
func mergePrimitive(a, b dyn.Value) (dyn.Value, error) {
|
||||
// Merging primitive values means using the incoming value.
|
||||
return b, nil
|
||||
}
|
|
@ -3,19 +3,19 @@ package merge
|
|||
import (
|
||||
"testing"
|
||||
|
||||
"github.com/databricks/cli/libs/config"
|
||||
"github.com/databricks/cli/libs/dyn"
|
||||
"github.com/stretchr/testify/assert"
|
||||
)
|
||||
|
||||
func TestMergeMaps(t *testing.T) {
|
||||
v1 := config.V(map[string]config.Value{
|
||||
"foo": config.V("bar"),
|
||||
"bar": config.V("baz"),
|
||||
v1 := dyn.V(map[string]dyn.Value{
|
||||
"foo": dyn.V("bar"),
|
||||
"bar": dyn.V("baz"),
|
||||
})
|
||||
|
||||
v2 := config.V(map[string]config.Value{
|
||||
"bar": config.V("qux"),
|
||||
"qux": config.V("foo"),
|
||||
v2 := dyn.V(map[string]dyn.Value{
|
||||
"bar": dyn.V("qux"),
|
||||
"qux": dyn.V("foo"),
|
||||
})
|
||||
|
||||
// Merge v2 into v1.
|
||||
|
@ -42,13 +42,13 @@ func TestMergeMaps(t *testing.T) {
|
|||
}
|
||||
|
||||
func TestMergeMapsNil(t *testing.T) {
|
||||
v := config.V(map[string]config.Value{
|
||||
"foo": config.V("bar"),
|
||||
v := dyn.V(map[string]dyn.Value{
|
||||
"foo": dyn.V("bar"),
|
||||
})
|
||||
|
||||
// Merge nil into v.
|
||||
{
|
||||
out, err := Merge(v, config.NilValue)
|
||||
out, err := Merge(v, dyn.NilValue)
|
||||
assert.NoError(t, err)
|
||||
assert.Equal(t, map[string]any{
|
||||
"foo": "bar",
|
||||
|
@ -57,7 +57,7 @@ func TestMergeMapsNil(t *testing.T) {
|
|||
|
||||
// Merge v into nil.
|
||||
{
|
||||
out, err := Merge(config.NilValue, v)
|
||||
out, err := Merge(dyn.NilValue, v)
|
||||
assert.NoError(t, err)
|
||||
assert.Equal(t, map[string]any{
|
||||
"foo": "bar",
|
||||
|
@ -66,29 +66,29 @@ func TestMergeMapsNil(t *testing.T) {
|
|||
}
|
||||
|
||||
func TestMergeMapsError(t *testing.T) {
|
||||
v := config.V(map[string]config.Value{
|
||||
"foo": config.V("bar"),
|
||||
v := dyn.V(map[string]dyn.Value{
|
||||
"foo": dyn.V("bar"),
|
||||
})
|
||||
|
||||
other := config.V("string")
|
||||
other := dyn.V("string")
|
||||
|
||||
// Merge a string into v.
|
||||
{
|
||||
out, err := Merge(v, other)
|
||||
assert.EqualError(t, err, "cannot merge map with string")
|
||||
assert.Equal(t, config.NilValue, out)
|
||||
assert.Equal(t, dyn.NilValue, out)
|
||||
}
|
||||
}
|
||||
|
||||
func TestMergeSequences(t *testing.T) {
|
||||
v1 := config.V([]config.Value{
|
||||
config.V("bar"),
|
||||
config.V("baz"),
|
||||
v1 := dyn.V([]dyn.Value{
|
||||
dyn.V("bar"),
|
||||
dyn.V("baz"),
|
||||
})
|
||||
|
||||
v2 := config.V([]config.Value{
|
||||
config.V("qux"),
|
||||
config.V("foo"),
|
||||
v2 := dyn.V([]dyn.Value{
|
||||
dyn.V("qux"),
|
||||
dyn.V("foo"),
|
||||
})
|
||||
|
||||
// Merge v2 into v1.
|
||||
|
@ -117,13 +117,13 @@ func TestMergeSequences(t *testing.T) {
|
|||
}
|
||||
|
||||
func TestMergeSequencesNil(t *testing.T) {
|
||||
v := config.V([]config.Value{
|
||||
config.V("bar"),
|
||||
v := dyn.V([]dyn.Value{
|
||||
dyn.V("bar"),
|
||||
})
|
||||
|
||||
// Merge nil into v.
|
||||
{
|
||||
out, err := Merge(v, config.NilValue)
|
||||
out, err := Merge(v, dyn.NilValue)
|
||||
assert.NoError(t, err)
|
||||
assert.Equal(t, []any{
|
||||
"bar",
|
||||
|
@ -132,7 +132,7 @@ func TestMergeSequencesNil(t *testing.T) {
|
|||
|
||||
// Merge v into nil.
|
||||
{
|
||||
out, err := Merge(config.NilValue, v)
|
||||
out, err := Merge(dyn.NilValue, v)
|
||||
assert.NoError(t, err)
|
||||
assert.Equal(t, []any{
|
||||
"bar",
|
||||
|
@ -141,23 +141,23 @@ func TestMergeSequencesNil(t *testing.T) {
|
|||
}
|
||||
|
||||
func TestMergeSequencesError(t *testing.T) {
|
||||
v := config.V([]config.Value{
|
||||
config.V("bar"),
|
||||
v := dyn.V([]dyn.Value{
|
||||
dyn.V("bar"),
|
||||
})
|
||||
|
||||
other := config.V("string")
|
||||
other := dyn.V("string")
|
||||
|
||||
// Merge a string into v.
|
||||
{
|
||||
out, err := Merge(v, other)
|
||||
assert.EqualError(t, err, "cannot merge sequence with string")
|
||||
assert.Equal(t, config.NilValue, out)
|
||||
assert.Equal(t, dyn.NilValue, out)
|
||||
}
|
||||
}
|
||||
|
||||
func TestMergePrimitives(t *testing.T) {
|
||||
v1 := config.V("bar")
|
||||
v2 := config.V("baz")
|
||||
v1 := dyn.V("bar")
|
||||
v2 := dyn.V("baz")
|
||||
|
||||
// Merge v2 into v1.
|
||||
{
|
||||
|
@ -175,33 +175,33 @@ func TestMergePrimitives(t *testing.T) {
|
|||
}
|
||||
|
||||
func TestMergePrimitivesNil(t *testing.T) {
|
||||
v := config.V("bar")
|
||||
v := dyn.V("bar")
|
||||
|
||||
// Merge nil into v.
|
||||
{
|
||||
out, err := Merge(v, config.NilValue)
|
||||
out, err := Merge(v, dyn.NilValue)
|
||||
assert.NoError(t, err)
|
||||
assert.Equal(t, "bar", out.AsAny())
|
||||
}
|
||||
|
||||
// Merge v into nil.
|
||||
{
|
||||
out, err := Merge(config.NilValue, v)
|
||||
out, err := Merge(dyn.NilValue, v)
|
||||
assert.NoError(t, err)
|
||||
assert.Equal(t, "bar", out.AsAny())
|
||||
}
|
||||
}
|
||||
|
||||
func TestMergePrimitivesError(t *testing.T) {
|
||||
v := config.V("bar")
|
||||
other := config.V(map[string]config.Value{
|
||||
"foo": config.V("bar"),
|
||||
v := dyn.V("bar")
|
||||
other := dyn.V(map[string]dyn.Value{
|
||||
"foo": dyn.V("bar"),
|
||||
})
|
||||
|
||||
// Merge a map into v.
|
||||
{
|
||||
out, err := Merge(v, other)
|
||||
assert.EqualError(t, err, "cannot merge string with map")
|
||||
assert.Equal(t, config.NilValue, out)
|
||||
assert.Equal(t, dyn.NilValue, out)
|
||||
}
|
||||
}
|
|
@ -1,4 +1,4 @@
|
|||
package config
|
||||
package dyn
|
||||
|
||||
import (
|
||||
"bytes"
|
|
@ -1,4 +1,4 @@
|
|||
package config
|
||||
package dyn
|
||||
|
||||
import (
|
||||
"fmt"
|
|
@ -1,10 +1,10 @@
|
|||
package config_test
|
||||
package dyn_test
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"testing"
|
||||
|
||||
. "github.com/databricks/cli/libs/config"
|
||||
. "github.com/databricks/cli/libs/dyn"
|
||||
"github.com/stretchr/testify/assert"
|
||||
)
|
||||
|
|
@ -0,0 +1,76 @@
|
|||
package dyn_test
|
||||
|
||||
import (
|
||||
"testing"
|
||||
|
||||
"github.com/databricks/cli/libs/dyn"
|
||||
"github.com/stretchr/testify/assert"
|
||||
)
|
||||
|
||||
func TestPathAppend(t *testing.T) {
|
||||
p := dyn.NewPath(dyn.Key("foo"))
|
||||
|
||||
// Single arg.
|
||||
p1 := p.Append(dyn.Key("bar"))
|
||||
assert.True(t, p1.Equal(dyn.NewPath(dyn.Key("foo"), dyn.Key("bar"))))
|
||||
|
||||
// Multiple args.
|
||||
p2 := p.Append(dyn.Key("bar"), dyn.Index(1))
|
||||
assert.True(t, p2.Equal(dyn.NewPath(dyn.Key("foo"), dyn.Key("bar"), dyn.Index(1))))
|
||||
}
|
||||
|
||||
func TestPathJoin(t *testing.T) {
|
||||
p := dyn.NewPath(dyn.Key("foo"))
|
||||
|
||||
// Single arg.
|
||||
p1 := p.Join(dyn.NewPath(dyn.Key("bar")))
|
||||
assert.True(t, p1.Equal(dyn.NewPath(dyn.Key("foo"), dyn.Key("bar"))))
|
||||
|
||||
// Multiple args.
|
||||
p2 := p.Join(dyn.NewPath(dyn.Key("bar")), dyn.NewPath(dyn.Index(1)))
|
||||
assert.True(t, p2.Equal(dyn.NewPath(dyn.Key("foo"), dyn.Key("bar"), dyn.Index(1))))
|
||||
}
|
||||
|
||||
func TestPathEqualEmpty(t *testing.T) {
|
||||
assert.True(t, dyn.EmptyPath.Equal(dyn.EmptyPath))
|
||||
}
|
||||
|
||||
func TestPathEqual(t *testing.T) {
|
||||
p1 := dyn.NewPath(dyn.Key("foo"), dyn.Index(1))
|
||||
p2 := dyn.NewPath(dyn.Key("bar"), dyn.Index(2))
|
||||
assert.False(t, p1.Equal(p2), "expected %q to not equal %q", p1, p2)
|
||||
|
||||
p3 := dyn.NewPath(dyn.Key("foo"), dyn.Index(1))
|
||||
assert.True(t, p1.Equal(p3), "expected %q to equal %q", p1, p3)
|
||||
|
||||
p4 := dyn.NewPath(dyn.Key("foo"), dyn.Index(1), dyn.Key("bar"), dyn.Index(2))
|
||||
assert.False(t, p1.Equal(p4), "expected %q to not equal %q", p1, p4)
|
||||
}
|
||||
|
||||
func TestPathHasPrefixEmpty(t *testing.T) {
|
||||
empty := dyn.EmptyPath
|
||||
nonEmpty := dyn.NewPath(dyn.Key("foo"))
|
||||
assert.True(t, empty.HasPrefix(empty))
|
||||
assert.True(t, nonEmpty.HasPrefix(empty))
|
||||
assert.False(t, empty.HasPrefix(nonEmpty))
|
||||
}
|
||||
|
||||
func TestPathHasPrefix(t *testing.T) {
|
||||
p1 := dyn.NewPath(dyn.Key("foo"), dyn.Index(1))
|
||||
p2 := dyn.NewPath(dyn.Key("bar"), dyn.Index(2))
|
||||
assert.False(t, p1.HasPrefix(p2), "expected %q to not have prefix %q", p1, p2)
|
||||
|
||||
p3 := dyn.NewPath(dyn.Key("foo"))
|
||||
assert.True(t, p1.HasPrefix(p3), "expected %q to have prefix %q", p1, p3)
|
||||
}
|
||||
|
||||
func TestPathString(t *testing.T) {
|
||||
p1 := dyn.NewPath(dyn.Key("foo"), dyn.Index(1))
|
||||
assert.Equal(t, "foo[1]", p1.String())
|
||||
|
||||
p2 := dyn.NewPath(dyn.Key("bar"), dyn.Index(2), dyn.Key("baz"))
|
||||
assert.Equal(t, "bar[2].baz", p2.String())
|
||||
|
||||
p3 := dyn.NewPath(dyn.Key("foo"), dyn.Index(1), dyn.Key("bar"), dyn.Index(2), dyn.Key("baz"))
|
||||
assert.Equal(t, "foo[1].bar[2].baz", p3.String())
|
||||
}
|
|
@ -1,4 +1,4 @@
|
|||
package config
|
||||
package dyn
|
||||
|
||||
import (
|
||||
"fmt"
|
|
@ -1,35 +1,35 @@
|
|||
package config_test
|
||||
package dyn_test
|
||||
|
||||
import (
|
||||
"testing"
|
||||
|
||||
"github.com/databricks/cli/libs/config"
|
||||
"github.com/databricks/cli/libs/dyn"
|
||||
"github.com/stretchr/testify/assert"
|
||||
)
|
||||
|
||||
func TestValueIsAnchor(t *testing.T) {
|
||||
var zero config.Value
|
||||
var zero dyn.Value
|
||||
assert.False(t, zero.IsAnchor())
|
||||
mark := zero.MarkAnchor()
|
||||
assert.True(t, mark.IsAnchor())
|
||||
}
|
||||
|
||||
func TestValueAsMap(t *testing.T) {
|
||||
var zeroValue config.Value
|
||||
var zeroValue dyn.Value
|
||||
m, ok := zeroValue.AsMap()
|
||||
assert.False(t, ok)
|
||||
assert.Nil(t, m)
|
||||
|
||||
var intValue = config.NewValue(1, config.Location{})
|
||||
var intValue = dyn.NewValue(1, dyn.Location{})
|
||||
m, ok = intValue.AsMap()
|
||||
assert.False(t, ok)
|
||||
assert.Nil(t, m)
|
||||
|
||||
var mapValue = config.NewValue(
|
||||
map[string]config.Value{
|
||||
"key": config.NewValue("value", config.Location{File: "file", Line: 1, Column: 2}),
|
||||
var mapValue = dyn.NewValue(
|
||||
map[string]dyn.Value{
|
||||
"key": dyn.NewValue("value", dyn.Location{File: "file", Line: 1, Column: 2}),
|
||||
},
|
||||
config.Location{File: "file", Line: 1, Column: 2},
|
||||
dyn.Location{File: "file", Line: 1, Column: 2},
|
||||
)
|
||||
m, ok = mapValue.AsMap()
|
||||
assert.True(t, ok)
|
||||
|
@ -37,8 +37,8 @@ func TestValueAsMap(t *testing.T) {
|
|||
}
|
||||
|
||||
func TestValueIsValid(t *testing.T) {
|
||||
var zeroValue config.Value
|
||||
var zeroValue dyn.Value
|
||||
assert.False(t, zeroValue.IsValid())
|
||||
var intValue = config.NewValue(1, config.Location{})
|
||||
var intValue = dyn.NewValue(1, dyn.Location{})
|
||||
assert.True(t, intValue.IsValid())
|
||||
}
|
|
@ -1,4 +1,4 @@
|
|||
package config
|
||||
package dyn
|
||||
|
||||
import "errors"
|
||||
|
|
@ -1,10 +1,10 @@
|
|||
package config_test
|
||||
package dyn_test
|
||||
|
||||
import (
|
||||
"errors"
|
||||
"testing"
|
||||
|
||||
. "github.com/databricks/cli/libs/config"
|
||||
. "github.com/databricks/cli/libs/dyn"
|
||||
"github.com/stretchr/testify/assert"
|
||||
"github.com/stretchr/testify/require"
|
||||
)
|
|
@ -7,7 +7,7 @@ import (
|
|||
"strings"
|
||||
"time"
|
||||
|
||||
"github.com/databricks/cli/libs/config"
|
||||
"github.com/databricks/cli/libs/dyn"
|
||||
"gopkg.in/yaml.v3"
|
||||
)
|
||||
|
||||
|
@ -15,7 +15,7 @@ type loader struct {
|
|||
path string
|
||||
}
|
||||
|
||||
func errorf(loc config.Location, format string, args ...interface{}) error {
|
||||
func errorf(loc dyn.Location, format string, args ...interface{}) error {
|
||||
return fmt.Errorf("yaml (%s): %s", loc, fmt.Sprintf(format, args...))
|
||||
}
|
||||
|
||||
|
@ -25,22 +25,22 @@ func newLoader(path string) *loader {
|
|||
}
|
||||
}
|
||||
|
||||
func (d *loader) location(node *yaml.Node) config.Location {
|
||||
return config.Location{
|
||||
func (d *loader) location(node *yaml.Node) dyn.Location {
|
||||
return dyn.Location{
|
||||
File: d.path,
|
||||
Line: node.Line,
|
||||
Column: node.Column,
|
||||
}
|
||||
}
|
||||
|
||||
func (d *loader) load(node *yaml.Node) (config.Value, error) {
|
||||
loc := config.Location{
|
||||
func (d *loader) load(node *yaml.Node) (dyn.Value, error) {
|
||||
loc := dyn.Location{
|
||||
File: d.path,
|
||||
Line: node.Line,
|
||||
Column: node.Column,
|
||||
}
|
||||
|
||||
var value config.Value
|
||||
var value dyn.Value
|
||||
var err error
|
||||
|
||||
switch node.Kind {
|
||||
|
@ -55,7 +55,7 @@ func (d *loader) load(node *yaml.Node) (config.Value, error) {
|
|||
case yaml.AliasNode:
|
||||
value, err = d.loadAlias(node, loc)
|
||||
default:
|
||||
return config.NilValue, errorf(loc, "unknown node kind: %v", node.Kind)
|
||||
return dyn.NilValue, errorf(loc, "unknown node kind: %v", node.Kind)
|
||||
}
|
||||
|
||||
if err != nil {
|
||||
|
@ -71,35 +71,35 @@ func (d *loader) load(node *yaml.Node) (config.Value, error) {
|
|||
return value, nil
|
||||
}
|
||||
|
||||
func (d *loader) loadDocument(node *yaml.Node, loc config.Location) (config.Value, error) {
|
||||
func (d *loader) loadDocument(node *yaml.Node, loc dyn.Location) (dyn.Value, error) {
|
||||
return d.load(node.Content[0])
|
||||
}
|
||||
|
||||
func (d *loader) loadSequence(node *yaml.Node, loc config.Location) (config.Value, error) {
|
||||
acc := make([]config.Value, len(node.Content))
|
||||
func (d *loader) loadSequence(node *yaml.Node, loc dyn.Location) (dyn.Value, error) {
|
||||
acc := make([]dyn.Value, len(node.Content))
|
||||
for i, n := range node.Content {
|
||||
v, err := d.load(n)
|
||||
if err != nil {
|
||||
return config.NilValue, err
|
||||
return dyn.NilValue, err
|
||||
}
|
||||
|
||||
acc[i] = v
|
||||
}
|
||||
|
||||
return config.NewValue(acc, loc), nil
|
||||
return dyn.NewValue(acc, loc), nil
|
||||
}
|
||||
|
||||
func (d *loader) loadMapping(node *yaml.Node, loc config.Location) (config.Value, error) {
|
||||
func (d *loader) loadMapping(node *yaml.Node, loc dyn.Location) (dyn.Value, error) {
|
||||
var merge *yaml.Node
|
||||
|
||||
acc := make(map[string]config.Value)
|
||||
acc := make(map[string]dyn.Value)
|
||||
for i := 0; i < len(node.Content); i += 2 {
|
||||
key := node.Content[i]
|
||||
val := node.Content[i+1]
|
||||
|
||||
// Assert that keys are strings
|
||||
if key.Kind != yaml.ScalarNode {
|
||||
return config.NilValue, errorf(loc, "key is not a scalar")
|
||||
return dyn.NilValue, errorf(loc, "key is not a scalar")
|
||||
}
|
||||
|
||||
st := key.ShortTag()
|
||||
|
@ -113,19 +113,19 @@ func (d *loader) loadMapping(node *yaml.Node, loc config.Location) (config.Value
|
|||
merge = val
|
||||
continue
|
||||
default:
|
||||
return config.NilValue, errorf(loc, "invalid key tag: %v", st)
|
||||
return dyn.NilValue, errorf(loc, "invalid key tag: %v", st)
|
||||
}
|
||||
|
||||
v, err := d.load(val)
|
||||
if err != nil {
|
||||
return config.NilValue, err
|
||||
return dyn.NilValue, err
|
||||
}
|
||||
|
||||
acc[key.Value] = v
|
||||
}
|
||||
|
||||
if merge == nil {
|
||||
return config.NewValue(acc, loc), nil
|
||||
return dyn.NewValue(acc, loc), nil
|
||||
}
|
||||
|
||||
// Build location for the merge node.
|
||||
|
@ -141,68 +141,68 @@ func (d *loader) loadMapping(node *yaml.Node, loc config.Location) (config.Value
|
|||
case yaml.AliasNode:
|
||||
mnodes = []*yaml.Node{merge}
|
||||
default:
|
||||
return config.NilValue, merr
|
||||
return dyn.NilValue, merr
|
||||
}
|
||||
|
||||
// Build a sequence of values to merge.
|
||||
// The entries that we already accumulated have precedence.
|
||||
var seq []map[string]config.Value
|
||||
var seq []map[string]dyn.Value
|
||||
for _, n := range mnodes {
|
||||
v, err := d.load(n)
|
||||
if err != nil {
|
||||
return config.NilValue, err
|
||||
return dyn.NilValue, err
|
||||
}
|
||||
m, ok := v.AsMap()
|
||||
if !ok {
|
||||
return config.NilValue, merr
|
||||
return dyn.NilValue, merr
|
||||
}
|
||||
seq = append(seq, m)
|
||||
}
|
||||
|
||||
// Append the accumulated entries to the sequence.
|
||||
seq = append(seq, acc)
|
||||
out := make(map[string]config.Value)
|
||||
out := make(map[string]dyn.Value)
|
||||
for _, m := range seq {
|
||||
for k, v := range m {
|
||||
out[k] = v
|
||||
}
|
||||
}
|
||||
|
||||
return config.NewValue(out, loc), nil
|
||||
return dyn.NewValue(out, loc), nil
|
||||
}
|
||||
|
||||
func (d *loader) loadScalar(node *yaml.Node, loc config.Location) (config.Value, error) {
|
||||
func (d *loader) loadScalar(node *yaml.Node, loc dyn.Location) (dyn.Value, error) {
|
||||
st := node.ShortTag()
|
||||
switch st {
|
||||
case "!!str":
|
||||
return config.NewValue(node.Value, loc), nil
|
||||
return dyn.NewValue(node.Value, loc), nil
|
||||
case "!!bool":
|
||||
switch strings.ToLower(node.Value) {
|
||||
case "true":
|
||||
return config.NewValue(true, loc), nil
|
||||
return dyn.NewValue(true, loc), nil
|
||||
case "false":
|
||||
return config.NewValue(false, loc), nil
|
||||
return dyn.NewValue(false, loc), nil
|
||||
default:
|
||||
return config.NilValue, errorf(loc, "invalid bool value: %v", node.Value)
|
||||
return dyn.NilValue, errorf(loc, "invalid bool value: %v", node.Value)
|
||||
}
|
||||
case "!!int":
|
||||
i64, err := strconv.ParseInt(node.Value, 10, 64)
|
||||
if err != nil {
|
||||
return config.NilValue, errorf(loc, "invalid int value: %v", node.Value)
|
||||
return dyn.NilValue, errorf(loc, "invalid int value: %v", node.Value)
|
||||
}
|
||||
// Use regular int type instead of int64 if possible.
|
||||
if i64 >= math.MinInt32 && i64 <= math.MaxInt32 {
|
||||
return config.NewValue(int(i64), loc), nil
|
||||
return dyn.NewValue(int(i64), loc), nil
|
||||
}
|
||||
return config.NewValue(i64, loc), nil
|
||||
return dyn.NewValue(i64, loc), nil
|
||||
case "!!float":
|
||||
f64, err := strconv.ParseFloat(node.Value, 64)
|
||||
if err != nil {
|
||||
return config.NilValue, errorf(loc, "invalid float value: %v", node.Value)
|
||||
return dyn.NilValue, errorf(loc, "invalid float value: %v", node.Value)
|
||||
}
|
||||
return config.NewValue(f64, loc), nil
|
||||
return dyn.NewValue(f64, loc), nil
|
||||
case "!!null":
|
||||
return config.NewValue(nil, loc), nil
|
||||
return dyn.NewValue(nil, loc), nil
|
||||
case "!!timestamp":
|
||||
// Try a couple of layouts
|
||||
for _, layout := range []string{
|
||||
|
@ -213,15 +213,15 @@ func (d *loader) loadScalar(node *yaml.Node, loc config.Location) (config.Value,
|
|||
} {
|
||||
t, terr := time.Parse(layout, node.Value)
|
||||
if terr == nil {
|
||||
return config.NewValue(t, loc), nil
|
||||
return dyn.NewValue(t, loc), nil
|
||||
}
|
||||
}
|
||||
return config.NilValue, errorf(loc, "invalid timestamp value: %v", node.Value)
|
||||
return dyn.NilValue, errorf(loc, "invalid timestamp value: %v", node.Value)
|
||||
default:
|
||||
return config.NilValue, errorf(loc, "unknown tag: %v", st)
|
||||
return dyn.NilValue, errorf(loc, "unknown tag: %v", st)
|
||||
}
|
||||
}
|
||||
|
||||
func (d *loader) loadAlias(node *yaml.Node, loc config.Location) (config.Value, error) {
|
||||
func (d *loader) loadAlias(node *yaml.Node, loc dyn.Location) (dyn.Value, error) {
|
||||
return d.load(node.Alias)
|
||||
}
|
|
@ -3,19 +3,19 @@ package yamlloader
|
|||
import (
|
||||
"io"
|
||||
|
||||
"github.com/databricks/cli/libs/config"
|
||||
"github.com/databricks/cli/libs/dyn"
|
||||
"gopkg.in/yaml.v3"
|
||||
)
|
||||
|
||||
func LoadYAML(path string, r io.Reader) (config.Value, error) {
|
||||
func LoadYAML(path string, r io.Reader) (dyn.Value, error) {
|
||||
var node yaml.Node
|
||||
dec := yaml.NewDecoder(r)
|
||||
err := dec.Decode(&node)
|
||||
if err != nil {
|
||||
if err == io.EOF {
|
||||
return config.NilValue, nil
|
||||
return dyn.NilValue, nil
|
||||
}
|
||||
return config.NilValue, err
|
||||
return dyn.NilValue, err
|
||||
}
|
||||
|
||||
return newLoader(path).load(&node)
|
|
@ -3,14 +3,14 @@ package yamlloader_test
|
|||
import (
|
||||
"testing"
|
||||
|
||||
"github.com/databricks/cli/libs/config"
|
||||
"github.com/databricks/cli/libs/dyn"
|
||||
"github.com/stretchr/testify/assert"
|
||||
)
|
||||
|
||||
func TestYAMLAnchor01(t *testing.T) {
|
||||
file := "testdata/anchor_01.yml"
|
||||
self := loadYAML(t, file)
|
||||
assert.NotEqual(t, config.NilValue, self)
|
||||
assert.NotEqual(t, dyn.NilValue, self)
|
||||
|
||||
assert.True(t, self.Get("defaults").IsAnchor())
|
||||
assert.False(t, self.Get("shirt1").IsAnchor())
|
||||
|
@ -18,31 +18,31 @@ func TestYAMLAnchor01(t *testing.T) {
|
|||
|
||||
pattern := self.Get("shirt1").Get("pattern")
|
||||
assert.Equal(t, "striped", pattern.AsAny())
|
||||
assert.Equal(t, config.Location{File: file, Line: 8, Column: 12}, pattern.Location())
|
||||
assert.Equal(t, dyn.Location{File: file, Line: 8, Column: 12}, pattern.Location())
|
||||
}
|
||||
|
||||
func TestYAMLAnchor02(t *testing.T) {
|
||||
file := "testdata/anchor_02.yml"
|
||||
self := loadYAML(t, file)
|
||||
assert.NotEqual(t, config.NilValue, self)
|
||||
assert.NotEqual(t, dyn.NilValue, self)
|
||||
|
||||
color := self.Get("shirt").Get("color")
|
||||
assert.Equal(t, "red", color.AsAny())
|
||||
assert.Equal(t, config.Location{File: file, Line: 4, Column: 10}, color.Location())
|
||||
assert.Equal(t, dyn.Location{File: file, Line: 4, Column: 10}, color.Location())
|
||||
|
||||
primary := self.Get("shirt").Get("primary")
|
||||
assert.Equal(t, "cotton", primary.AsAny())
|
||||
assert.Equal(t, config.Location{File: file, Line: 8, Column: 12}, primary.Location())
|
||||
assert.Equal(t, dyn.Location{File: file, Line: 8, Column: 12}, primary.Location())
|
||||
|
||||
pattern := self.Get("shirt").Get("pattern")
|
||||
assert.Equal(t, "striped", pattern.AsAny())
|
||||
assert.Equal(t, config.Location{File: file, Line: 13, Column: 12}, pattern.Location())
|
||||
assert.Equal(t, dyn.Location{File: file, Line: 13, Column: 12}, pattern.Location())
|
||||
}
|
||||
|
||||
func TestYAMLAnchor03(t *testing.T) {
|
||||
file := "testdata/anchor_03.yml"
|
||||
self := loadYAML(t, file)
|
||||
assert.NotEqual(t, config.NilValue, self)
|
||||
assert.NotEqual(t, dyn.NilValue, self)
|
||||
|
||||
// Assert the override took place.
|
||||
blue := self.Get("shirt").Get("color")
|
||||
|
@ -55,63 +55,63 @@ func TestYAMLAnchor03(t *testing.T) {
|
|||
func TestYAMLAnchor04(t *testing.T) {
|
||||
file := "testdata/anchor_04.yml"
|
||||
self := loadYAML(t, file)
|
||||
assert.NotEqual(t, config.NilValue, self)
|
||||
assert.NotEqual(t, dyn.NilValue, self)
|
||||
|
||||
p1 := self.Get("person1").Get("address").Get("city")
|
||||
assert.Equal(t, "San Francisco", p1.AsAny())
|
||||
assert.Equal(t, config.Location{File: file, Line: 4, Column: 9}, p1.Location())
|
||||
assert.Equal(t, dyn.Location{File: file, Line: 4, Column: 9}, p1.Location())
|
||||
|
||||
p2 := self.Get("person2").Get("address").Get("city")
|
||||
assert.Equal(t, "Los Angeles", p2.AsAny())
|
||||
assert.Equal(t, config.Location{File: file, Line: 16, Column: 11}, p2.Location())
|
||||
assert.Equal(t, dyn.Location{File: file, Line: 16, Column: 11}, p2.Location())
|
||||
}
|
||||
|
||||
func TestYAMLAnchor05(t *testing.T) {
|
||||
file := "testdata/anchor_05.yml"
|
||||
self := loadYAML(t, file)
|
||||
assert.NotEqual(t, config.NilValue, self)
|
||||
assert.NotEqual(t, dyn.NilValue, self)
|
||||
|
||||
features := self.Get("phone1").Get("features")
|
||||
assert.Equal(t, "wifi", features.Index(0).AsAny())
|
||||
assert.Equal(t, config.Location{File: file, Line: 4, Column: 5}, features.Index(0).Location())
|
||||
assert.Equal(t, dyn.Location{File: file, Line: 4, Column: 5}, features.Index(0).Location())
|
||||
assert.Equal(t, "bluetooth", features.Index(1).AsAny())
|
||||
assert.Equal(t, config.Location{File: file, Line: 5, Column: 5}, features.Index(1).Location())
|
||||
assert.Equal(t, dyn.Location{File: file, Line: 5, Column: 5}, features.Index(1).Location())
|
||||
}
|
||||
|
||||
func TestYAMLAnchor06(t *testing.T) {
|
||||
file := "testdata/anchor_06.yml"
|
||||
self := loadYAML(t, file)
|
||||
assert.NotEqual(t, config.NilValue, self)
|
||||
assert.NotEqual(t, dyn.NilValue, self)
|
||||
|
||||
greeting := self.Get("greeting1")
|
||||
assert.Equal(t, "Hello, World!", greeting.AsAny())
|
||||
assert.Equal(t, config.Location{File: file, Line: 2, Column: 16}, greeting.Location())
|
||||
assert.Equal(t, dyn.Location{File: file, Line: 2, Column: 16}, greeting.Location())
|
||||
}
|
||||
|
||||
func TestYAMLAnchor07(t *testing.T) {
|
||||
file := "testdata/anchor_07.yml"
|
||||
self := loadYAML(t, file)
|
||||
assert.NotEqual(t, config.NilValue, self)
|
||||
assert.NotEqual(t, dyn.NilValue, self)
|
||||
|
||||
name := self.Get("person1").Get("name")
|
||||
assert.Equal(t, "Alice", name.AsAny())
|
||||
assert.Equal(t, config.Location{File: file, Line: 5, Column: 9}, name.Location())
|
||||
assert.Equal(t, dyn.Location{File: file, Line: 5, Column: 9}, name.Location())
|
||||
|
||||
age := self.Get("person1").Get("age")
|
||||
assert.Equal(t, 25, age.AsAny())
|
||||
assert.Equal(t, config.Location{File: file, Line: 2, Column: 13}, age.Location())
|
||||
assert.Equal(t, dyn.Location{File: file, Line: 2, Column: 13}, age.Location())
|
||||
}
|
||||
|
||||
func TestYAMLAnchor08(t *testing.T) {
|
||||
file := "testdata/anchor_08.yml"
|
||||
self := loadYAML(t, file)
|
||||
assert.NotEqual(t, config.NilValue, self)
|
||||
assert.NotEqual(t, dyn.NilValue, self)
|
||||
|
||||
username := self.Get("user1").Get("username")
|
||||
assert.Equal(t, "user1", username.AsAny())
|
||||
assert.Equal(t, config.Location{File: file, Line: 5, Column: 13}, username.Location())
|
||||
assert.Equal(t, dyn.Location{File: file, Line: 5, Column: 13}, username.Location())
|
||||
|
||||
active := self.Get("user1").Get("active")
|
||||
assert.Equal(t, true, active.AsAny())
|
||||
assert.Equal(t, config.Location{File: file, Line: 2, Column: 11}, active.Location())
|
||||
assert.Equal(t, dyn.Location{File: file, Line: 2, Column: 11}, active.Location())
|
||||
}
|
|
@ -5,7 +5,7 @@ import (
|
|||
"os"
|
||||
"testing"
|
||||
|
||||
"github.com/databricks/cli/libs/config/yamlloader"
|
||||
"github.com/databricks/cli/libs/dyn/yamlloader"
|
||||
"github.com/stretchr/testify/assert"
|
||||
"github.com/stretchr/testify/require"
|
||||
"gopkg.in/yaml.v3"
|
|
@ -3,14 +3,14 @@ package yamlloader_test
|
|||
import (
|
||||
"testing"
|
||||
|
||||
"github.com/databricks/cli/libs/config"
|
||||
"github.com/databricks/cli/libs/dyn"
|
||||
"github.com/stretchr/testify/assert"
|
||||
)
|
||||
|
||||
func TestYAMLMix01(t *testing.T) {
|
||||
file := "testdata/mix_01.yml"
|
||||
self := loadYAML(t, file)
|
||||
assert.NotEqual(t, config.NilValue, self)
|
||||
assert.NotEqual(t, dyn.NilValue, self)
|
||||
|
||||
assert.True(t, self.Get("base_address").IsAnchor())
|
||||
assert.False(t, self.Get("office_address").IsAnchor())
|
||||
|
@ -19,7 +19,7 @@ func TestYAMLMix01(t *testing.T) {
|
|||
func TestYAMLMix02(t *testing.T) {
|
||||
file := "testdata/mix_02.yml"
|
||||
self := loadYAML(t, file)
|
||||
assert.NotEqual(t, config.NilValue, self)
|
||||
assert.NotEqual(t, dyn.NilValue, self)
|
||||
|
||||
assert.True(t, self.Get("base_colors").IsAnchor())
|
||||
assert.False(t, self.Get("theme").IsAnchor())
|
|
@ -5,14 +5,14 @@ import (
|
|||
"os"
|
||||
"testing"
|
||||
|
||||
"github.com/databricks/cli/libs/config"
|
||||
"github.com/databricks/cli/libs/config/yamlloader"
|
||||
"github.com/databricks/cli/libs/dyn"
|
||||
"github.com/databricks/cli/libs/dyn/yamlloader"
|
||||
"github.com/stretchr/testify/assert"
|
||||
"github.com/stretchr/testify/require"
|
||||
"gopkg.in/yaml.v3"
|
||||
)
|
||||
|
||||
func loadYAML(t *testing.T, path string) config.Value {
|
||||
func loadYAML(t *testing.T, path string) dyn.Value {
|
||||
input, err := os.ReadFile(path)
|
||||
require.NoError(t, err)
|
||||
|
||||
|
@ -31,5 +31,5 @@ func loadYAML(t *testing.T, path string) config.Value {
|
|||
|
||||
func TestYAMLEmpty(t *testing.T) {
|
||||
self := loadYAML(t, "testdata/empty.yml")
|
||||
assert.Equal(t, config.NilValue, self)
|
||||
assert.Equal(t, dyn.NilValue, self)
|
||||
}
|
Loading…
Reference in New Issue