mirror of
https://github.com/spf13/viper
synced 2024-12-23 03:57:01 +00:00
Add support for int slice flags (#637)
* Add support for int slice flags * Add int slice test to unmarshal
This commit is contained in:
parent
0da4d41b2d
commit
ad5ed02fa4
2 changed files with 80 additions and 2 deletions
12
viper.go
12
viper.go
|
@ -706,6 +706,8 @@ func (v *Viper) Get(key string) interface{} {
|
||||||
return cast.ToDuration(val)
|
return cast.ToDuration(val)
|
||||||
case []string:
|
case []string:
|
||||||
return cast.ToStringSlice(val)
|
return cast.ToStringSlice(val)
|
||||||
|
case []int:
|
||||||
|
return cast.ToIntSlice(val)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1013,6 +1015,11 @@ func (v *Viper) find(lcaseKey string) interface{} {
|
||||||
s = strings.TrimSuffix(s, "]")
|
s = strings.TrimSuffix(s, "]")
|
||||||
res, _ := readAsCSV(s)
|
res, _ := readAsCSV(s)
|
||||||
return res
|
return res
|
||||||
|
case "intSlice":
|
||||||
|
s := strings.TrimPrefix(flag.ValueString(), "[")
|
||||||
|
s = strings.TrimSuffix(s, "]")
|
||||||
|
res, _ := readAsCSV(s)
|
||||||
|
return cast.ToIntSlice(res)
|
||||||
default:
|
default:
|
||||||
return flag.ValueString()
|
return flag.ValueString()
|
||||||
}
|
}
|
||||||
|
@ -1082,6 +1089,11 @@ func (v *Viper) find(lcaseKey string) interface{} {
|
||||||
s = strings.TrimSuffix(s, "]")
|
s = strings.TrimSuffix(s, "]")
|
||||||
res, _ := readAsCSV(s)
|
res, _ := readAsCSV(s)
|
||||||
return res
|
return res
|
||||||
|
case "intSlice":
|
||||||
|
s := strings.TrimPrefix(flag.ValueString(), "[")
|
||||||
|
s = strings.TrimSuffix(s, "]")
|
||||||
|
res, _ := readAsCSV(s)
|
||||||
|
return cast.ToIntSlice(res)
|
||||||
default:
|
default:
|
||||||
return flag.ValueString()
|
return flag.ValueString()
|
||||||
}
|
}
|
||||||
|
|
|
@ -540,11 +540,13 @@ func TestUnmarshal(t *testing.T) {
|
||||||
SetDefault("port", 1313)
|
SetDefault("port", 1313)
|
||||||
Set("name", "Steve")
|
Set("name", "Steve")
|
||||||
Set("duration", "1s1ms")
|
Set("duration", "1s1ms")
|
||||||
|
Set("modes", []int{1, 2, 3})
|
||||||
|
|
||||||
type config struct {
|
type config struct {
|
||||||
Port int
|
Port int
|
||||||
Name string
|
Name string
|
||||||
Duration time.Duration
|
Duration time.Duration
|
||||||
|
Modes []int
|
||||||
}
|
}
|
||||||
|
|
||||||
var C config
|
var C config
|
||||||
|
@ -554,14 +556,33 @@ func TestUnmarshal(t *testing.T) {
|
||||||
t.Fatalf("unable to decode into struct, %v", err)
|
t.Fatalf("unable to decode into struct, %v", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
assert.Equal(t, &config{Name: "Steve", Port: 1313, Duration: time.Second + time.Millisecond}, &C)
|
assert.Equal(
|
||||||
|
t,
|
||||||
|
&config{
|
||||||
|
Name: "Steve",
|
||||||
|
Port: 1313,
|
||||||
|
Duration: time.Second + time.Millisecond,
|
||||||
|
Modes: []int{1, 2, 3},
|
||||||
|
},
|
||||||
|
&C,
|
||||||
|
)
|
||||||
|
|
||||||
Set("port", 1234)
|
Set("port", 1234)
|
||||||
err = Unmarshal(&C)
|
err = Unmarshal(&C)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatalf("unable to decode into struct, %v", err)
|
t.Fatalf("unable to decode into struct, %v", err)
|
||||||
}
|
}
|
||||||
assert.Equal(t, &config{Name: "Steve", Port: 1234, Duration: time.Second + time.Millisecond}, &C)
|
|
||||||
|
assert.Equal(
|
||||||
|
t,
|
||||||
|
&config{
|
||||||
|
Name: "Steve",
|
||||||
|
Port: 1234,
|
||||||
|
Duration: time.Second + time.Millisecond,
|
||||||
|
Modes: []int{1, 2, 3},
|
||||||
|
},
|
||||||
|
&C,
|
||||||
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestUnmarshalWithDecoderOptions(t *testing.T) {
|
func TestUnmarshalWithDecoderOptions(t *testing.T) {
|
||||||
|
@ -682,6 +703,51 @@ func TestBindPFlagsStringSlice(t *testing.T) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func TestBindPFlagsIntSlice(t *testing.T) {
|
||||||
|
tests := []struct {
|
||||||
|
Expected []int
|
||||||
|
Value string
|
||||||
|
}{
|
||||||
|
{nil, ""},
|
||||||
|
{[]int{1}, "1"},
|
||||||
|
{[]int{2, 3}, "2,3"},
|
||||||
|
}
|
||||||
|
|
||||||
|
v := New() // create independent Viper object
|
||||||
|
defaultVal := []int{0}
|
||||||
|
v.SetDefault("intslice", defaultVal)
|
||||||
|
|
||||||
|
for _, testValue := range tests {
|
||||||
|
flagSet := pflag.NewFlagSet("test", pflag.ContinueOnError)
|
||||||
|
flagSet.IntSlice("intslice", testValue.Expected, "test")
|
||||||
|
|
||||||
|
for _, changed := range []bool{true, false} {
|
||||||
|
flagSet.VisitAll(func(f *pflag.Flag) {
|
||||||
|
f.Value.Set(testValue.Value)
|
||||||
|
f.Changed = changed
|
||||||
|
})
|
||||||
|
|
||||||
|
err := v.BindPFlags(flagSet)
|
||||||
|
if err != nil {
|
||||||
|
t.Fatalf("error binding flag set, %v", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
type TestInt struct {
|
||||||
|
IntSlice []int
|
||||||
|
}
|
||||||
|
val := &TestInt{}
|
||||||
|
if err := v.Unmarshal(val); err != nil {
|
||||||
|
t.Fatalf("%+#v cannot unmarshal: %s", testValue.Value, err)
|
||||||
|
}
|
||||||
|
if changed {
|
||||||
|
assert.Equal(t, testValue.Expected, val.IntSlice)
|
||||||
|
} else {
|
||||||
|
assert.Equal(t, defaultVal, val.IntSlice)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
func TestBindPFlag(t *testing.T) {
|
func TestBindPFlag(t *testing.T) {
|
||||||
var testString = "testing"
|
var testString = "testing"
|
||||||
var testValue = newStringValue(testString, &testString)
|
var testValue = newStringValue(testString, &testString)
|
||||||
|
|
Loading…
Reference in a new issue