Repository: go-go-golems/glazed
Pull request #244 (2023-03-23 03:48:15)

Fix RenderValue of Date
- :art: :umbrella: Add some RenderValue unit tests
- :ambulance: Fix render of Date
- :ambulance: Fix render of Object and ObjectList preliminarily



Patch:
diff --git a/pkg/cmds/parameters/cobra.go b/pkg/cmds/parameters/cobra.go
index ef2b22f..c78f9c8 100644
--- a/pkg/cmds/parameters/cobra.go
+++ b/pkg/cmds/parameters/cobra.go
@@ -194,7 +194,7 @@ func AddFlagsToCobraCommand(
 			defaultValue := 0
 
 			if parameter.Default != nil {
-				defaultValue, ok = cast.CastInterfaceToInt[int](parameter.Default)
+				defaultValue, ok = cast.CastNumberInterfaceToInt[int](parameter.Default)
 				if !ok {
 					return errors.Errorf("Default value for parameter %s is not an integer: %v", parameter.Name, parameter.Default)
 				}
diff --git a/pkg/cmds/parameters/parameters.go b/pkg/cmds/parameters/parameters.go
index fce71d3..d62dda8 100644
--- a/pkg/cmds/parameters/parameters.go
+++ b/pkg/cmds/parameters/parameters.go
@@ -105,7 +105,7 @@ func (p *ParameterDefinition) SetDefaultFromInterface(i interface{}) error {
 		}
 		p.Default = v
 	case ParameterTypeInteger:
-		v, ok := cast.CastInterfaceToInt[int64](i)
+		v, ok := cast.CastNumberInterfaceToInt[int64](i)
 		if !ok {
 			return errors.Errorf("expected int64 for parameter %s, got %T", p.Name, i)
 		}
@@ -647,7 +647,7 @@ func (p *ParameterDefinition) CheckValueValidity(v interface{}) error {
 		}
 
 	case ParameterTypeInteger:
-		_, ok := cast.CastInterfaceToInt[int64](v)
+		_, ok := cast.CastNumberInterfaceToInt[int64](v)
 		if !ok {
 			return errors.Errorf("Default value for parameter %s is not an integer: %v", p.Name, v)
 		}
diff --git a/pkg/cmds/parameters/render.go b/pkg/cmds/parameters/render.go
index 5f54f63..d09b00f 100644
--- a/pkg/cmds/parameters/render.go
+++ b/pkg/cmds/parameters/render.go
@@ -5,6 +5,7 @@ import (
 	"github.com/go-go-golems/glazed/pkg/helpers/cast"
 	"github.com/pkg/errors"
 	"strings"
+	"time"
 )
 
 func RenderValue(type_ ParameterType, value interface{}) (string, error) {
@@ -13,14 +14,6 @@ func RenderValue(type_ ParameterType, value interface{}) (string, error) {
 		fallthrough
 	case ParameterTypeStringFromFile:
 		fallthrough
-	case ParameterTypeObjectListFromFile:
-		fallthrough
-	case ParameterTypeObjectFromFile:
-		fallthrough
-	case ParameterTypeStringListFromFile:
-		fallthrough
-	case ParameterTypeDate:
-		fallthrough
 	case ParameterTypeChoice:
 		s, ok := value.(string)
 		if !ok {
@@ -28,6 +21,21 @@ func RenderValue(type_ ParameterType, value interface{}) (string, error) {
 		}
 		return s, nil
 
+	case ParameterTypeObjectListFromFile:
+		fallthrough
+	case ParameterTypeObjectFromFile:
+		return fmt.Sprintf("%v", value), nil
+
+	case ParameterTypeDate:
+		switch v := value.(type) {
+		case string:
+			return v, nil
+		case time.Time:
+			return v.Format(time.RFC3339), nil
+		default:
+			return "", errors.Errorf("expected string or time.Time, got %T", value)
+		}
+
 	case ParameterTypeKeyValue:
 		m, ok := cast.CastInterfaceToStringMap[string, interface{}](value)
 		if !ok {
@@ -40,10 +48,18 @@ func RenderValue(type_ ParameterType, value interface{}) (string, error) {
 		return strings.Join(s, ","), nil
 
 	case ParameterTypeInteger:
-		return fmt.Sprintf("%d", value), nil
+		v, ok := cast.CastNumberInterfaceToInt[int64](value)
+		if !ok {
+			return "", errors.Errorf("expected int, got %T", value)
+		}
+		return fmt.Sprintf("%d", v), nil
 
 	case ParameterTypeFloat:
-		return fmt.Sprintf("%f", value), nil
+		v, ok := cast.CastNumberInterfaceToFloat[float64](value)
+		if !ok {
+			return "", errors.Errorf("expected float, got %T", v)
+		}
+		return fmt.Sprintf("%f", v), nil
 
 	case ParameterTypeBool:
 		v, ok := value.(bool)
@@ -55,6 +71,8 @@ func RenderValue(type_ ParameterType, value interface{}) (string, error) {
 		}
 		return "false", nil
 
+	case ParameterTypeStringListFromFile:
+		fallthrough
 	case ParameterTypeStringList:
 		l, ok := cast.CastList2[string, interface{}](value)
 		if !ok {
@@ -63,14 +81,10 @@ func RenderValue(type_ ParameterType, value interface{}) (string, error) {
 		return strings.Join(l, ","), nil
 
 	case ParameterTypeIntegerList:
-		v, ok := cast.CastList2[interface{}, interface{}](value)
+		l, ok := cast.CastListToIntList2[int64](value)
 		if !ok {
 			return "", errors.Errorf("expected []interface{}, got %T", value)
 		}
-		l, ok := cast.CastInterfaceListToIntList[int64](v)
-		if !ok {
-			return "", errors.Errorf("expected []int64, got %T", value)
-		}
 		s := []string{}
 		for _, i := range l {
 			s = append(s, fmt.Sprintf("%d", i))
@@ -78,14 +92,10 @@ func RenderValue(type_ ParameterType, value interface{}) (string, error) {
 		return strings.Join(s, ","), nil
 
 	case ParameterTypeFloatList:
-		v, ok := cast.CastList2[interface{}, interface{}](value)
+		l, ok := cast.CastListToFloatList2[float64](value)
 		if !ok {
 			return "", errors.Errorf("expected []interface{}, got %T", value)
 		}
-		l, ok := cast.CastInterfaceListToFloatList[float64](v)
-		if !ok {
-			return "", errors.Errorf("expected []float64, got %T", value)
-		}
 		s := []string{}
 		for _, i := range l {
 			s = append(s, fmt.Sprintf("%f", i))
diff --git a/pkg/helpers/cast/cast.go b/pkg/helpers/cast/cast.go
index c0eda6a..0db7aa2 100644
--- a/pkg/helpers/cast/cast.go
+++ b/pkg/helpers/cast/cast.go
@@ -71,11 +71,42 @@ func CastToNumberList[To Number, From Number](list []From) ([]To, bool) {
 	return ret, true
 }
 
+func CastListToIntList2[To SignedInt | UnsignedInt](list interface{}) ([]To, bool) {
+	switch t := list.(type) {
+	case []interface{}:
+		return CastInterfaceListToIntList[To](t)
+	case []int:
+		return CastToNumberList[To, int](t)
+	case []int8:
+		return CastToNumberList[To, int8](t)
+	case []int16:
+		return CastToNumberList[To, int16](t)
+	case []int32:
+		return CastToNumberList[To, int32](t)
+	case []int64:
+		return CastToNumberList[To, int64](t)
+	case []uint:
+		return CastToNumberList[To, uint](t)
+	case []uint8:
+		return CastToNumberList[To, uint8](t)
+	case []uint16:
+		return CastToNumberList[To, uint16](t)
+	case []uint32:
+		return CastToNumberList[To, uint32](t)
+	case []uint64:
+		return CastToNumberList[To, uint64](t)
+	case []uintptr:
+		return CastToNumberList[To, uintptr](t)
+	default:
+		return []To{}, false
+	}
+}
+
 func CastInterfaceListToIntList[To SignedInt | UnsignedInt](list []interface{}) ([]To, bool) {
 	ret := []To{}
 
 	for _, item := range list {
-		f, ok := CastInterfaceToInt[To](item)
+		f, ok := CastNumberInterfaceToInt[To](item)
 		if !ok {
 			return ret, false
 		}
@@ -85,6 +116,19 @@ func CastInterfaceListToIntList[To SignedInt | UnsignedInt](list []interface{})
 	return ret, true
 }
 
+func CastListToFloatList2[To FloatNumber](list interface{}) ([]To, bool) {
+	switch t := list.(type) {
+	case []interface{}:
+		return CastInterfaceListToFloatList[To](t)
+	case []float32:
+		return CastToNumberList[To, float32](t)
+	case []float64:
+		return CastToNumberList[To, float64](t)
+	default:
+		return []To{}, false
+	}
+}
+
 func CastInterfaceListToFloatList[To FloatNumber](list []interface{}) ([]To, bool) {
 	ret := []To{}
 
@@ -139,7 +183,7 @@ func CastMapToInterfaceMap[From any](m map[string]From) map[string]interface{} {
 	return ret
 }
 
-func CastInterfaceToInt[To SignedInt | UnsignedInt](i interface{}) (To, bool) {
+func CastNumberInterfaceToInt[To SignedInt | UnsignedInt](i interface{}) (To, bool) {
 	switch i := i.(type) {
 	case To:
 		return i, true
diff --git a/pkg/helpers/templating/templating.go b/pkg/helpers/templating/templating.go
index 5e5d088..8848577 100644
--- a/pkg/helpers/templating/templating.go
+++ b/pkg/helpers/templating/templating.go
@@ -411,7 +411,7 @@ func stripNewlines(s string) string {
 
 // rpad adds padding to the right of a string.
 func rpad(s string, padding_ interface{}) string {
-	padding, ok := cast.CastInterfaceToInt[int](padding_)
+	padding, ok := cast.CastNumberInterfaceToInt[int](padding_)
 	if !ok {
 		panic("padding must be an int")
 	}


Test patch:
diff --git a/pkg/cmds/parameters/render_test.go b/pkg/cmds/parameters/render_test.go
new file mode 100644
index 0000000..a32395f
--- /dev/null
+++ b/pkg/cmds/parameters/render_test.go
@@ -0,0 +1,100 @@
+package parameters
+
+import (
+	"github.com/stretchr/testify/assert"
+	"github.com/stretchr/testify/require"
+	"testing"
+	"time"
+)
+
+func TestRenderString(t *testing.T) {
+	v, err := RenderValue(ParameterTypeString, "foobar")
+	require.NoError(t, err)
+	assert.Equal(t, "foobar", v)
+
+	_, err = RenderValue(ParameterTypeString, 1)
+	require.Error(t, err)
+
+	v, err = RenderValue(ParameterTypeStringFromFile, "foobar")
+	require.NoError(t, err)
+	assert.Equal(t, "foobar", v)
+
+	v, err = RenderValue(ParameterTypeChoice, "foobar")
+	require.NoError(t, err)
+	assert.Equal(t, "foobar", v)
+}
+
+func TestRenderStringList(t *testing.T) {
+	v, err := RenderValue(ParameterTypeStringList, []string{"foobar", "barfoo"})
+	require.NoError(t, err)
+	assert.Equal(t, "foobar,barfoo", v)
+
+	v, err = RenderValue(ParameterTypeStringListFromFile, []string{"foobar", "barfoo"})
+	require.NoError(t, err)
+	assert.Equal(t, "foobar,barfoo", v)
+
+	v, err = RenderValue(ParameterTypeStringList, []string{"foobar"})
+	require.NoError(t, err)
+	assert.Equal(t, "foobar", v)
+
+	_, err = RenderValue(ParameterTypeStringList, 1)
+	require.Error(t, err)
+
+	_, err = RenderValue(ParameterTypeStringList, "foobar")
+	require.Error(t, err)
+}
+
+func TestRenderInt(t *testing.T) {
+	v, err := RenderValue(ParameterTypeInteger, 1)
+	require.NoError(t, err)
+	assert.Equal(t, "1", v)
+
+	_, err = RenderValue(ParameterTypeInteger, "foobar")
+	require.Error(t, err)
+
+	v, err = RenderValue(ParameterTypeIntegerList, []int{1, 2, 3})
+	require.NoError(t, err)
+	assert.Equal(t, "1,2,3", v)
+
+	v, err = RenderValue(ParameterTypeIntegerList, []int{1})
+	require.NoError(t, err)
+	assert.Equal(t, "1", v)
+}
+
+func TestRenderFloat(t *testing.T) {
+	v, err := RenderValue(ParameterTypeFloat, 1.1)
+	require.NoError(t, err)
+	assert.Equal(t, "1.100000", v)
+
+	_, err = RenderValue(ParameterTypeFloat, "foobar")
+	require.Error(t, err)
+
+	v, err = RenderValue(ParameterTypeFloatList, []float64{1.1, 2.2, 3.3})
+	require.NoError(t, err)
+	assert.Equal(t, "1.100000,2.200000,3.300000", v)
+
+	v, err = RenderValue(ParameterTypeFloatList, []float64{1.1})
+	require.NoError(t, err)
+	assert.Equal(t, "1.100000", v)
+}
+
+func TestRenderDate(t *testing.T) {
+	v, err := RenderValue(ParameterTypeDate, "2019-01-01")
+	require.NoError(t, err)
+	assert.Equal(t, "2019-01-01", v)
+
+	_, err = RenderValue(ParameterTypeDate, 1)
+	require.Error(t, err)
+
+	d, err := time.Parse("2006-01-02", "2019-01-01")
+	require.NoError(t, err)
+	v, err = RenderValue(ParameterTypeDate, d)
+	require.NoError(t, err)
+	assert.Equal(t, "2019-01-01T00:00:00Z", v)
+
+	t_, err := time.Parse("2006-01-02 15:04:05", "2019-01-01 12:00:00")
+	require.NoError(t, err)
+	v, err = RenderValue(ParameterTypeDate, t_)
+	require.NoError(t, err)
+	assert.Equal(t, "2019-01-01T12:00:00Z", v)
+}