Skip to content

Commit

Permalink
Fix:(issue_1592) Add support for float64slice, uint, int, int64 for a…
Browse files Browse the repository at this point in the history
…ltsrc
  • Loading branch information
dearchap committed Jan 15, 2023
1 parent c891d79 commit a987887
Show file tree
Hide file tree
Showing 7 changed files with 437 additions and 0 deletions.
88 changes: 88 additions & 0 deletions altsrc/flag.go
Original file line number Diff line number Diff line change
Expand Up @@ -179,6 +179,37 @@ func (f *Int64SliceFlag) ApplyInputSourceValue(cCtx *cli.Context, isc InputSourc
return nil
}

// ApplyInputSourceValue applies a Float64Slice value if required
func (f *Float64SliceFlag) ApplyInputSourceValue(cCtx *cli.Context, isc InputSourceContext) error {
if f.set == nil || cCtx.IsSet(f.Name) || isEnvVarSet(f.EnvVars) {
return nil
}
for _, name := range f.Float64SliceFlag.Names() {
if !isc.isSet(name) {
continue
}
value, err := isc.Float64Slice(name)
if err != nil {
return err
}
if value == nil {
continue
}
var sliceValue = *(cli.NewFloat64Slice(value...))
for _, n := range f.Names() {
underlyingFlag := f.set.Lookup(n)
if underlyingFlag == nil {
continue
}
underlyingFlag.Value = &sliceValue
}
if f.Destination != nil {
f.Destination.Set(sliceValue.Serialize())
}
}
return nil
}

// ApplyInputSourceValue applies a Bool value to the flagSet if required
func (f *BoolFlag) ApplyInputSourceValue(cCtx *cli.Context, isc InputSourceContext) error {
if f.set == nil || cCtx.IsSet(f.Name) || isEnvVarSet(f.EnvVars) {
Expand Down Expand Up @@ -269,6 +300,63 @@ func (f *IntFlag) ApplyInputSourceValue(cCtx *cli.Context, isc InputSourceContex
return nil
}

func (f *Int64Flag) ApplyInputSourceValue(cCtx *cli.Context, isc InputSourceContext) error {
if f.set == nil || cCtx.IsSet(f.Name) || isEnvVarSet(f.EnvVars) {
return nil
}
for _, name := range f.Int64Flag.Names() {
if !isc.isSet(name) {
continue
}
value, err := isc.Int64(name)
if err != nil {
return err
}
for _, n := range f.Names() {
_ = f.set.Set(n, strconv.FormatInt(value, 10))
}
}
return nil
}

func (f *UintFlag) ApplyInputSourceValue(cCtx *cli.Context, isc InputSourceContext) error {
if f.set == nil || cCtx.IsSet(f.Name) || isEnvVarSet(f.EnvVars) {
return nil
}
for _, name := range f.UintFlag.Names() {
if !isc.isSet(name) {
continue
}
value, err := isc.Uint(name)
if err != nil {
return err
}
for _, n := range f.Names() {
_ = f.set.Set(n, strconv.FormatUint(uint64(value), 10))
}
}
return nil
}

func (f *Uint64Flag) ApplyInputSourceValue(cCtx *cli.Context, isc InputSourceContext) error {
if f.set == nil || cCtx.IsSet(f.Name) || isEnvVarSet(f.EnvVars) {
return nil
}
for _, name := range f.Uint64Flag.Names() {
if !isc.isSet(name) {
continue
}
value, err := isc.Uint64(name)
if err != nil {
return err
}
for _, n := range f.Names() {
_ = f.set.Set(n, strconv.FormatUint(value, 10))
}
}
return nil
}

// ApplyInputSourceValue applies a Duration value to the flagSet if required
func (f *DurationFlag) ApplyInputSourceValue(cCtx *cli.Context, isc InputSourceContext) error {
if f.set == nil || cCtx.IsSet(f.Name) || isEnvVarSet(f.EnvVars) {
Expand Down
118 changes: 118 additions & 0 deletions altsrc/flag_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -280,6 +280,29 @@ func TestInt64SliceFlagApplyInputSourceValue(t *testing.T) {
refute(t, dest.Value(), []int64{1, 2})
}

func TestFloat64SliceFlagApplyInputSourceValue(t *testing.T) {
dest := cli.NewFloat64Slice()
tis := testApplyInputSource{
Flag: NewFloat64SliceFlag(&cli.Float64SliceFlag{Name: "test", Destination: dest}),
FlagName: "test",
MapValue: []interface{}{float64(1.0), float64(2.1)},
}
c := runTest(t, tis)
expect(t, c.Float64Slice("test"), []float64{1.0, 2.1})
expect(t, dest.Value(), []float64{1.0, 2.1})

// reset dest
dest = cli.NewFloat64Slice()
tis = testApplyInputSource{
Flag: NewFloat64SliceFlag(&cli.Float64SliceFlag{Name: "test", Destination: dest}),
FlagName: "test",
MapValue: []interface{}{float64(1.0), float64(2.1)},
}
c = runRacyTest(t, tis)
refute(t, c.IntSlice("test"), []int64{1, 2})
refute(t, dest.Value(), []int64{1, 2})
}

func TestBoolApplyInputSourceMethodSet(t *testing.T) {
tis := testApplyInputSource{
Flag: NewBoolFlag(&cli.BoolFlag{Name: "test"}),
Expand Down Expand Up @@ -539,6 +562,101 @@ func TestIntApplyInputSourceMethodEnvVarSet(t *testing.T) {
refute(t, 12, c.Int("test"))
}

func TestUintApplyInputSourceMethodSet_Alias(t *testing.T) {
tis := testApplyInputSource{
Flag: NewUintFlag(&cli.UintFlag{Name: "test", Aliases: []string{"test_alias"}}),
FlagName: "test_alias",
MapValue: uint(15),
}
c := runTest(t, tis)
expect(t, uint(15), c.Uint("test_alias"))

c = runRacyTest(t, tis)
refute(t, uint(15), c.Uint("test_alias"))
}

func TestUintApplyInputSourceMethodSet(t *testing.T) {
tis := testApplyInputSource{
Flag: NewUintFlag(&cli.UintFlag{Name: "test"}),
FlagName: "test",
MapValue: uint(15),
}
c := runTest(t, tis)
expect(t, uint(15), c.Uint("test"))

c = runRacyTest(t, tis)
refute(t, uint(15), c.Uint("test"))
}

func TestUintApplyInputSourceMethodContextSet(t *testing.T) {
tis := testApplyInputSource{
Flag: NewUintFlag(&cli.UintFlag{Name: "test"}),
FlagName: "test",
MapValue: uint(15),
ContextValueString: "7",
}
c := runTest(t, tis)
expect(t, uint(7), c.Uint("test"))

c = runRacyTest(t, tis)
refute(t, uint(7), c.Uint("test"))
}

func TestUint64ApplyInputSourceMethodSet_Alias(t *testing.T) {
tis := testApplyInputSource{
Flag: NewUint64Flag(&cli.Uint64Flag{Name: "test", Aliases: []string{"test_alias"}}),
FlagName: "test_alias",
MapValue: uint64(15),
}
c := runTest(t, tis)
expect(t, uint64(15), c.Uint64("test_alias"))

c = runRacyTest(t, tis)
refute(t, uint64(15), c.Uint64("test_alias"))
}

func TestUint64ApplyInputSourceMethodSet(t *testing.T) {
tis := testApplyInputSource{
Flag: NewUint64Flag(&cli.Uint64Flag{Name: "test"}),
FlagName: "test",
MapValue: uint64(15),
}
c := runTest(t, tis)
expect(t, uint64(15), c.Uint64("test"))

c = runRacyTest(t, tis)
refute(t, uint64(15), c.Uint64("test"))
}

func TestUint64ApplyInputSourceMethodContextSet(t *testing.T) {
tis := testApplyInputSource{
Flag: NewUint64Flag(&cli.Uint64Flag{Name: "test"}),
FlagName: "test",
MapValue: uint64(15),
ContextValueString: "7",
}
c := runTest(t, tis)
expect(t, uint64(7), c.Uint64("test"))

c = runRacyTest(t, tis)
refute(t, uint64(7), c.Uint64("test"))
}

func TestUint64ApplyInputSourceMethodEnvVarSet(t *testing.T) {
tis := testApplyInputSource{
Flag: NewUint64Flag(&cli.Uint64Flag{Name: "test", EnvVars: []string{"TEST"}}),
FlagName: "test",
MapValue: uint64(15),
EnvVarName: "TEST",
EnvVarValue: "12",
}
c := runTest(t, tis)
expect(t, uint64(12), c.Uint64("test"))

c = runRacyTest(t, tis)
refute(t, uint64(12), c.Uint64("test"))
}

func TestDurationApplyInputSourceMethodSet_Alias(t *testing.T) {
tis := testApplyInputSource{
Flag: NewDurationFlag(&cli.DurationFlag{Name: "test", Aliases: []string{"test_alias"}}),
Expand Down
4 changes: 4 additions & 0 deletions altsrc/input_source_context.go
Original file line number Diff line number Diff line change
Expand Up @@ -15,12 +15,16 @@ type InputSourceContext interface {
Source() string

Int(name string) (int, error)
Int64(name string) (int64, error)
Uint(name string) (uint, error)
Uint64(name string) (uint64, error)
Duration(name string) (time.Duration, error)
Float64(name string) (float64, error)
String(name string) (string, error)
StringSlice(name string) ([]string, error)
IntSlice(name string) ([]int, error)
Int64Slice(name string) ([]int64, error)
Float64Slice(name string) ([]float64, error)
Generic(name string) (cli.Generic, error)
Bool(name string) (bool, error)

Expand Down
80 changes: 80 additions & 0 deletions altsrc/json_source_context.go
Original file line number Diff line number Diff line change
Expand Up @@ -78,6 +78,63 @@ func (x *jsonSource) Int(name string) (int, error) {
}
}

func (x *jsonSource) Int64(name string) (int64, error) {
i, err := x.getValue(name)
if err != nil {
return 0, err
}
switch v := i.(type) {
default:
return 0, fmt.Errorf("unexpected type %T for %q", i, name)
case int64:
return v, nil
case int:
return int64(v), nil
case float32:
return int64(v), nil
case float64:
return int64(v), nil
}
}

func (x *jsonSource) Uint(name string) (uint, error) {
i, err := x.getValue(name)
if err != nil {
return 0, err
}
switch v := i.(type) {
default:
return 0, fmt.Errorf("unexpected type %T for %q", i, name)
case uint:
return v, nil
case uint64:
return uint(v), nil
case float32:
return uint(v), nil
case float64:
return uint(v), nil
}
}

func (x *jsonSource) Uint64(name string) (uint64, error) {
i, err := x.getValue(name)
if err != nil {
return 0, err
}
switch v := i.(type) {
default:
return 0, fmt.Errorf("unexpected type %T for %q", i, name)
case uint64:
return v, nil
case uint:
return uint64(v), nil
case float32:
return uint64(v), nil
case float64:
return uint64(v), nil
}
}

func (x *jsonSource) Duration(name string) (time.Duration, error) {
i, err := x.getValue(name)
if err != nil {
Expand Down Expand Up @@ -183,6 +240,29 @@ func (x *jsonSource) Int64Slice(name string) ([]int64, error) {
}
}

func (x *jsonSource) Float64Slice(name string) ([]float64, error) {
i, err := x.getValue(name)
if err != nil {
return nil, err
}
switch v := i.(type) {
default:
return nil, fmt.Errorf("unexpected type %T for %q", i, name)
case []float64:
return v, nil
case []interface{}:
c := []float64{}
for _, s := range v {
if i2, ok := s.(float64); ok {
c = append(c, i2)
} else {
return c, fmt.Errorf("unexpected item type %T in %T for %q", s, c, name)
}
}
return c, nil
}
}

func (x *jsonSource) Generic(name string) (cli.Generic, error) {
i, err := x.getValue(name)
if err != nil {
Expand Down

0 comments on commit a987887

Please sign in to comment.