Automatic merge from release/2.1.0 -> release/2.2.0

* commit 'e03a31a65d32799840888d124d61f731382569ae':
  dep: update structarg
  climc: trim angle brackets for required options
  validators: add BoolValidator
  validators: add ValidatorStringMultiChoices
This commit is contained in:
邱剑
2018-09-11 00:12:39 +08:00
5 changed files with 219 additions and 16 deletions
Generated
+2 -2
View File
@@ -1171,11 +1171,11 @@
[[projects]]
branch = "master"
digest = "1:c69a05ea10fc186aaf589c10184d00dbfa3a46fbd7866ed1e52d6bd84f8607d5"
digest = "1:b62e87e9e21e5d6933164761e3f1861c580d0612fcde43cc8c6b2e4db34ce9f8"
name = "yunion.io/x/structarg"
packages = ["."]
pruneopts = "UT"
revision = "7dc6c41bf325ce7f2ce2a1cebbd8d396f7f6188e"
revision = "5a0eff15d64f686ee66801ac42284a797115e55f"
[solve-meta]
analyzer-name = "dep"
+8 -7
View File
@@ -76,15 +76,16 @@ func getSubcommandsParser() (*structarg.ArgumentParser, error) {
cmd := v.Command
for _, v := range _par.GetOptArgs() {
_name := strings.Replace(v.String(), "]", "", -1)
_name = strings.Replace(_name, "[", "", -1)
promputils.AppendOpt(cmd, _name, v.HelpString(""))
text := v.String()
text = strings.TrimLeft(text, "[<")
text = strings.TrimRight(text, "]>")
promputils.AppendOpt(cmd, text, v.HelpString(""))
}
for _, v := range _par.GetPosArgs() {
_name := strings.Replace(v.String(), "<", "", -1)
_name = strings.Replace(_name, ">", "", -1)
promputils.AppendPos(cmd, _name, v.HelpString(""))
text := v.String()
text = strings.TrimLeft(text, "[<")
text = strings.TrimRight(text, "]>")
promputils.AppendPos(cmd, text, v.HelpString(""))
}
}
return parse, nil
+125
View File
@@ -11,6 +11,7 @@ import (
"net"
"reflect"
"regexp"
"strings"
"yunion.io/x/jsonutils"
"yunion.io/x/onecloud/pkg/cloudcommon/db"
@@ -60,6 +61,11 @@ func (v *Validator) setDefault(data *jsonutils.JSONDict) bool {
v.value = jsonutils.NewString(s)
data.Set(v.Key, v.value)
return true
case bool:
b := v.defaultVal.(bool)
v.value = jsonutils.NewBool(b)
data.Set(v.Key, v.value)
return true
case int, int32, int64, uint, uint32, uint64:
value := reflect.ValueOf(v.defaultVal)
value64 := value.Convert(gotypes.Int64Type)
@@ -141,6 +147,125 @@ func (v *ValidatorStringChoices) Validate(data *jsonutils.JSONDict) error {
return nil
}
type ValidatorStringMultiChoices struct {
Validator
Choices Choices
defaultVal string
Value string
sep string
keepDup bool
}
func NewStringMultiChoicesValidator(key string, choices Choices) *ValidatorStringMultiChoices {
v := &ValidatorStringMultiChoices{
Validator: Validator{Key: key},
Choices: choices,
}
v.parent = v
return v
}
func (v *ValidatorStringMultiChoices) Sep(s string) *ValidatorStringMultiChoices {
v.sep = s
return v
}
func (v *ValidatorStringMultiChoices) KeepDup(b bool) *ValidatorStringMultiChoices {
v.keepDup = b
return v
}
func (v *ValidatorStringMultiChoices) validateString(s string) (string, bool) {
choices := strings.Split(s, v.sep)
j := 0
for i, choice := range choices {
if !v.Choices.Has(choice) {
return "", false
}
if !v.keepDup {
isDup := false
for k := 0; k < j; k++ {
if choices[k] == choices[i] {
isDup = true
}
}
if !isDup {
choices[j] = choices[i]
j += 1
}
}
}
if !v.keepDup {
choices = choices[:j]
}
s = strings.Join(choices, v.sep)
return s, true
}
func (v *ValidatorStringMultiChoices) Default(s string) IValidator {
s, ok := v.validateString(s)
if !ok {
panic("invalid default for " + v.Key)
}
v.Validator.Default(s)
return v
}
func (v *ValidatorStringMultiChoices) getValue() interface{} {
return v.Value
}
func (v *ValidatorStringMultiChoices) Validate(data *jsonutils.JSONDict) error {
if err, isSet := v.Validator.validateEx(data); err != nil || !isSet {
return err
}
s, err := v.value.GetString()
if err != nil {
return newGeneralError(v.Key, err)
}
s, ok := v.validateString(s)
if !ok {
return newInvalidChoiceError(v.Key, v.Choices, s)
}
// in case it's stringified from v.value
data.Set(v.Key, jsonutils.NewString(s))
v.Value = s
return nil
}
type ValidatorBool struct {
Validator
Value bool
}
func (v *ValidatorBool) getValue() interface{} {
return v.Value
}
func (v *ValidatorBool) Default(i bool) IValidator {
return v.Validator.Default(i)
}
func (v *ValidatorBool) Validate(data *jsonutils.JSONDict) error {
if err, isSet := v.Validator.validateEx(data); err != nil || !isSet {
return err
}
i, err := v.value.Bool()
if err != nil {
return newInvalidTypeError(v.Key, "bool", err)
}
data.Set(v.Key, jsonutils.NewBool(i))
v.Value = i
return nil
}
func NewBoolValidator(key string) *ValidatorBool {
v := &ValidatorBool{
Validator: Validator{Key: key},
}
v.parent = v
return v
}
type ValidatorRange struct {
Validator
Lower int64
@@ -143,6 +143,88 @@ func TestStringChoicesValidator(t *testing.T) {
}
}
func TestBoolValidator(t *testing.T) {
cases := []*C{
{
Name: "missing non-optional",
In: `{}`,
Out: `{}`,
Err: ERR_MISSING_KEY,
ValueWant: false,
},
{
Name: "missing optional",
In: `{}`,
Out: `{}`,
Optional: true,
ValueWant: false,
},
{
Name: "missing with default",
In: `{}`,
Out: `{s: true}`,
Default: true,
ValueWant: true,
},
{
Name: "true",
In: `{s: true}`,
Out: `{s: true}`,
ValueWant: true,
},
{
Name: "false",
In: `{s: false}`,
Out: `{s: false}`,
ValueWant: false,
},
{
Name: `parsed "true"`,
In: `{s: "true"}`,
Out: `{s: true}`,
ValueWant: true,
},
{
Name: `parsed "on"`,
In: `{s: "on"}`,
Out: `{s: true}`,
ValueWant: true,
},
{
Name: `parsed "yes"`,
In: `{s: "yes"}`,
Out: `{s: true}`,
ValueWant: true,
},
{
Name: `parsed "1"`,
In: `{s: "1"}`,
Out: `{s: true}`,
ValueWant: true,
},
{
Name: "parsed invalid",
In: `{s: "abc"}`,
Out: `{s: "abc"}`,
Err: ERR_INVALID_TYPE,
ValueWant: false,
},
}
for _, c := range cases {
t.Run(c.Name, func(t *testing.T) {
v := NewBoolValidator("s")
if c.Default != nil {
i := c.Default.(bool)
v.Default(i)
}
if c.Optional {
v.Optional(true)
}
testS(t, v, c)
})
}
}
func TestRangeValidator(t *testing.T) {
cases := []*C{
{
+2 -7
View File
@@ -459,12 +459,7 @@ func (this *SingleArgument) MetaVar() string {
if len(this.metavar) > 0 {
return this.metavar
} else if len(this.choices) > 0 {
choices := this.choices
if len(choices) > 2 {
choices = choices[:2]
choices = append(choices, "...")
}
return fmt.Sprintf("{%s}", strings.Join(choices, ","))
return fmt.Sprintf("{%s}", strings.Join(this.choices, ","))
} else {
return strings.ToUpper(strings.Replace(this.Token(), "-", "_", -1))
}
@@ -561,7 +556,7 @@ func (this *SingleArgument) SetValue(val string) error {
for i := 0; i < len(cands); i += 1 {
cands[i] = fmt.Sprintf("'%s'", cands[i])
}
msg = fmt.Sprintf("%s, do you mean %s?", msg, ChoicesString(cands))
msg = fmt.Sprintf("%s, did you mean %s?", msg, ChoicesString(cands))
}
return fmt.Errorf(msg)
}