Compare commits

..

No commits in common. "71bc701eed24f192f6d6cad5e0ec92219abdbbc5" and "75948368a3b44c26eb2e21b44b90152943e1079a" have entirely different histories.

6 changed files with 42 additions and 54 deletions

View File

@ -263,11 +263,34 @@ func Render(ctx context.Context, v any) error {
return renderWithTemplate(newRenderer(v), ctx, c.outputFormat, c.out, c.headerTemplate, c.template)
}
func RenderWithDiagnostics(ctx context.Context, v any, diags diag.Diagnostics) error {
c := fromContext(ctx)
if _, ok := v.(listingInterface); ok {
panic("use RenderIterator instead")
}
err := renderWithTemplate(newRenderer(v), ctx, c.outputFormat, c.out, c.headerTemplate, c.template)
if err != nil {
return err
}
return RenderDiagnostics(c.out, diags)
}
func RenderIterator[T any](ctx context.Context, i listing.Iterator[T]) error {
c := fromContext(ctx)
return renderWithTemplate(newIteratorRenderer(i), ctx, c.outputFormat, c.out, c.headerTemplate, c.template)
}
func RenderIteratorWithDiagnostics[T any](ctx context.Context, i listing.Iterator[T], diags diag.Diagnostics) error {
c := fromContext(ctx)
err := renderWithTemplate(newIteratorRenderer(i), ctx, c.outputFormat, c.out, c.headerTemplate, c.template)
if err != nil {
return err
}
return RenderDiagnostics(c.err, diags)
}
func RenderWithTemplate(ctx context.Context, v any, headerTemplate, template string) error {
c := fromContext(ctx)
if _, ok := v.(listingInterface); ok {

View File

@ -248,9 +248,7 @@ func toTypedInt(dst reflect.Value, src dyn.Value) error {
return nil
case dyn.KindFloat:
v := src.MustFloat()
if v == float64(int64(v)) {
// If the destination is smaller than int64, but the value to set is bigger
// then destination overflows and is set to -1
if canConvertToInt(v) {
dst.SetInt(int64(src.MustFloat()))
return nil
}
@ -277,6 +275,10 @@ func toTypedInt(dst reflect.Value, src dyn.Value) error {
}
}
func canConvertToInt(v float64) bool {
return v == float64(int64(v))
}
func toTypedFloat(dst reflect.Value, src dyn.Value) error {
switch src.Kind() {
case dyn.KindFloat:

View File

@ -34,19 +34,13 @@ func decodeValue(decoder *json.Decoder, o *Offset) (dyn.Value, error) {
return dyn.InvalidValue, err
}
// Get the current byte offset and the location.
// We will later use this location to store the location of the value in the file
// For objects and arrays, we will store the location of the opening '{' or '['
// For primitive types, we will store the location of the value itself (end of the value)
// We can't reliably calculate the beginning of the value for primitive types because
// the decoder doesn't provide the offset of the beginning of the value and the value might or might not be quoted.
// Get the current byte offset
offset := decoder.InputOffset()
location := o.GetPosition(offset)
switch tok := token.(type) {
case json.Delim:
if tok == '{' {
location = o.GetPosition(offset - 1)
// Decode JSON object
obj := dyn.NewMapping()
for decoder.More() {
@ -60,10 +54,7 @@ func decodeValue(decoder *json.Decoder, o *Offset) (dyn.Value, error) {
return invalidValueWithLocation(decoder, o), fmt.Errorf("expected string for object key")
}
// Get the offset of the key by subtracting the length of the key and the '"' character
keyOffset := decoder.InputOffset() - int64(len(key)+1)
keyVal := dyn.NewValue(key, []dyn.Location{o.GetPosition(keyOffset)})
keyVal := dyn.NewValue(key, []dyn.Location{o.GetPosition(decoder.InputOffset())})
// Decode the value recursively
val, err := decodeValue(decoder, o)
if err != nil {
@ -78,7 +69,6 @@ func decodeValue(decoder *json.Decoder, o *Offset) (dyn.Value, error) {
}
return dyn.NewValue(obj, []dyn.Location{location}), nil
} else if tok == '[' {
location = o.GetPosition(offset - 1)
// Decode JSON array
var arr []dyn.Value
for decoder.More() {
@ -95,6 +85,7 @@ func decodeValue(decoder *json.Decoder, o *Offset) (dyn.Value, error) {
return dyn.NewValue(arr, []dyn.Location{location}), nil
}
default:
// Primitive types: string, number, bool, or null
return dyn.NewValue(tok, []dyn.Location{location}), nil
}

View File

@ -4,8 +4,8 @@ import (
"testing"
"github.com/databricks/cli/libs/dyn/convert"
"github.com/databricks/cli/libs/dyn/dynassert"
"github.com/databricks/databricks-sdk-go/service/jobs"
"github.com/stretchr/testify/require"
)
const jsonData = `
@ -45,11 +45,11 @@ const jsonData = `
func TestJsonLoader(t *testing.T) {
v, err := LoadJSON([]byte(jsonData), "(inline)")
dynassert.NoError(t, err)
require.NoError(t, err)
var r jobs.ResetJob
err = convert.ToTyped(&r, v)
dynassert.NoError(t, err)
require.NoError(t, err)
}
const malformedMap = `
@ -64,7 +64,7 @@ const malformedMap = `
func TestJsonLoaderMalformedMap(t *testing.T) {
_, err := LoadJSON([]byte(malformedMap), "(inline)")
dynassert.ErrorContains(t, err, "error decoding JSON at (inline):6:16: invalid character ',' after object key")
require.ErrorContains(t, err, "error decoding JSON at (inline):6:16: invalid character ',' after object key")
}
const malformedArray = `
@ -78,7 +78,7 @@ const malformedArray = `
func TestJsonLoaderMalformedArray(t *testing.T) {
_, err := LoadJSON([]byte(malformedArray), "path/to/file.json")
dynassert.ErrorContains(t, err, "error decoding JSON at path/to/file.json:6:28: invalid character ']' looking for beginning of value")
require.ErrorContains(t, err, "error decoding JSON at path/to/file.json:6:28: invalid character ']' looking for beginning of value")
}
const eofData = `
@ -89,5 +89,5 @@ const eofData = `
func TestJsonLoaderEOF(t *testing.T) {
_, err := LoadJSON([]byte(eofData), "path/to/file.json")
dynassert.ErrorContains(t, err, "unexpected end of JSON input")
require.ErrorContains(t, err, "unexpected end of JSON input")
}

View File

@ -52,7 +52,7 @@ func (j *JsonFlag) Unmarshal(v any) diag.Diagnostics {
// It will convert all the values to the correct types.
// For example string literals for booleans and integers will be converted to the correct types.
nv, diags := convert.Normalize(v, dv)
if diags.HasError() {
if len(diags) > 0 {
return diags
}
@ -60,17 +60,17 @@ func (j *JsonFlag) Unmarshal(v any) diag.Diagnostics {
// It will serialize all set data with the correct types.
data, err := json.Marshal(nv.AsAny())
if err != nil {
return diags.Extend(diag.FromErr(err))
return diag.FromErr(err)
}
// Finally unmarshal the normalized data to the output.
// It will fill in the ForceSendFields field if the struct contains it.
err = marshal.Unmarshal(data, v)
if err != nil {
return diags.Extend(diag.FromErr(err))
return diag.FromErr(err)
}
return diags
return nil
}
func (j *JsonFlag) Type() string {

View File

@ -182,7 +182,7 @@ func TestJsonUnmarshalRequestMismatch(t *testing.T) {
{
File: "(inline)",
Line: 3,
Column: 6,
Column: 15,
},
},
Paths: []dyn.Path{{}},
@ -222,34 +222,6 @@ const wrontTypeJsonData = `{
func TestJsonUnmarshalWrongTypeReportsCorrectLocation(t *testing.T) {
var body JsonFlag
var r jobs.ResetJob
err := body.Set(`{
"job_id": [1, 2, 3]
}
`)
require.NoError(t, err)
diags := body.Unmarshal(&r)
assert.NoError(t, diags.Error())
assert.NotEmpty(t, diags)
assert.Contains(t, diags, diag.Diagnostic{
Severity: diag.Warning,
Summary: "expected int, found sequence",
Locations: []dyn.Location{
{
File: "(inline)",
Line: 2,
Column: 15,
},
},
Paths: []dyn.Path{dyn.NewPath(dyn.Key("job_id"))},
})
}
func TestJsonUnmarshalArrayInsteadOfIntReportsCorrectLocation(t *testing.T) {
var body JsonFlag
var r jobs.ResetJob
err := body.Set(wrontTypeJsonData)
require.NoError(t, err)