mirror of
https://github.com/TomWright/dasel.git
synced 2022-05-22 02:32:45 +03:00
Add type selector
This commit is contained in:
@@ -36,21 +36,22 @@ func (c EqualCondition) Check(other reflect.Value) (bool, error) {
|
||||
return c.check(value.Interface(), c.Value)
|
||||
}
|
||||
|
||||
switch value.Kind() {
|
||||
case reflect.Map, reflect.Slice:
|
||||
fmt.Println("here456")
|
||||
subRootNode := New(value.Interface())
|
||||
foundNode, err := subRootNode.Query(c.Key)
|
||||
fmt.Println("789", err)
|
||||
if err != nil {
|
||||
fmt.Println("here123")
|
||||
var valueNotFound = &ValueNotFound{}
|
||||
if errors.As(err, &valueNotFound) {
|
||||
return false, nil
|
||||
}
|
||||
var unsupportedType = &UnsupportedTypeForSelector{}
|
||||
if errors.As(err, &unsupportedType) {
|
||||
return false, nil
|
||||
}
|
||||
|
||||
return false, fmt.Errorf("subquery failed: %w", err)
|
||||
}
|
||||
|
||||
return c.check(foundNode.InterfaceValue(), c.Value)
|
||||
}
|
||||
|
||||
return false, &UnhandledCheckType{Value: value.String()}
|
||||
}
|
||||
|
||||
@@ -31,8 +31,6 @@ func (c SortedComparisonCondition) Check(other reflect.Value) (bool, error) {
|
||||
return fmt.Sprint(value.Interface()) == c.Value, nil
|
||||
}
|
||||
|
||||
switch value.Kind() {
|
||||
case reflect.Map, reflect.Slice:
|
||||
subRootNode := New(value.Interface())
|
||||
foundNode, err := subRootNode.Query(c.Key)
|
||||
if err != nil {
|
||||
@@ -62,6 +60,3 @@ func (c SortedComparisonCondition) Check(other reflect.Value) (bool, error) {
|
||||
|
||||
return false, nil
|
||||
}
|
||||
|
||||
return false, &UnhandledCheckType{Value: value.String()}
|
||||
}
|
||||
|
||||
@@ -67,11 +67,6 @@ func TestEqualCondition_Check(t *testing.T) {
|
||||
nil,
|
||||
false, &dasel.UnhandledCheckType{Value: nil},
|
||||
))
|
||||
t.Run("String", conditionTest(
|
||||
c,
|
||||
"",
|
||||
false, &dasel.UnhandledCheckType{Value: ""},
|
||||
))
|
||||
}
|
||||
|
||||
func TestSortedComparisonCondition_Check(t *testing.T) {
|
||||
@@ -163,11 +158,6 @@ func TestSortedComparisonCondition_Check(t *testing.T) {
|
||||
nil,
|
||||
false, &dasel.UnhandledCheckType{Value: nil},
|
||||
))
|
||||
t.Run("String", conditionTest(
|
||||
&dasel.SortedComparisonCondition{Key: "x", Value: "4"},
|
||||
"",
|
||||
false, &dasel.UnhandledCheckType{Value: ""},
|
||||
))
|
||||
}
|
||||
|
||||
func TestKeyEqualCondition_Check(t *testing.T) {
|
||||
|
||||
@@ -493,6 +493,44 @@ func TestRootCmd_Select_JSON(t *testing.T) {
|
||||
}
|
||||
`, nil, "--escape-html=false"))
|
||||
|
||||
t.Run("MixedDynamicSelectors", selectTest(`{
|
||||
"plugins": [
|
||||
"@semantic-release/commit-analyzer",
|
||||
"@semantic-release/release-notes-generator",
|
||||
"@semantic-release/gitlab",
|
||||
[
|
||||
"@semantic-release/git",
|
||||
{
|
||||
"assets": [
|
||||
"tbump.toml",
|
||||
"**/pyproject.toml",
|
||||
"**/setup.py",
|
||||
"README.md"
|
||||
],
|
||||
"message": "chore(release): ${nextRelease.version}\n\n${nextRelease.notes}"
|
||||
}
|
||||
],
|
||||
[
|
||||
"@semantic-release/git",
|
||||
{
|
||||
"assets": [
|
||||
"y"
|
||||
],
|
||||
"message": "chore(release): ${nextRelease.version}\n\n${nextRelease.notes}"
|
||||
}
|
||||
]
|
||||
]
|
||||
}`, "json", `.plugins.([@]=array).([@]=map).assets`, `[
|
||||
"tbump.toml",
|
||||
"**/pyproject.toml",
|
||||
"**/setup.py",
|
||||
"README.md"
|
||||
]
|
||||
[
|
||||
"y"
|
||||
]
|
||||
`, nil, "-m"))
|
||||
|
||||
}
|
||||
|
||||
func TestRootCmd_Select_YAML(t *testing.T) {
|
||||
|
||||
@@ -218,6 +218,37 @@ func findValueLength(n *Node, createIfNotExists bool) (reflect.Value, error) {
|
||||
return nilValue(), &UnsupportedTypeForSelector{Selector: n.Selector, Value: value}
|
||||
}
|
||||
|
||||
// findValueType returns the type of the current node.
|
||||
func findValueType(n *Node, createIfNotExists bool) (reflect.Value, error) {
|
||||
if !isValid(n.Previous.Value) {
|
||||
return nilValue(), &UnexpectedPreviousNilValue{Selector: n.Previous.Selector.Current}
|
||||
}
|
||||
|
||||
value := unwrapValue(n.Previous.Value)
|
||||
|
||||
switch value.Kind() {
|
||||
case reflect.Slice:
|
||||
return reflect.ValueOf("array"), nil
|
||||
|
||||
case reflect.Map:
|
||||
return reflect.ValueOf("map"), nil
|
||||
|
||||
case reflect.String:
|
||||
return reflect.ValueOf("string"), nil
|
||||
|
||||
case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64:
|
||||
return reflect.ValueOf("int"), nil
|
||||
|
||||
case reflect.Float32, reflect.Float64:
|
||||
return reflect.ValueOf("float"), nil
|
||||
|
||||
case reflect.Bool:
|
||||
return reflect.ValueOf("bool"), nil
|
||||
}
|
||||
|
||||
return nilValue(), &UnsupportedTypeForSelector{Selector: n.Selector, Value: value}
|
||||
}
|
||||
|
||||
// findValue finds the value for the given node.
|
||||
// The value is essentially pulled from the previous node, using the (already parsed) selector
|
||||
// information stored on the current node.
|
||||
@@ -242,6 +273,8 @@ func findValue(n *Node, createIfNotExists bool) (reflect.Value, error) {
|
||||
return findValueDynamic(n, createIfNotExists)
|
||||
case "LENGTH":
|
||||
return findValueLength(n, createIfNotExists)
|
||||
case "TYPE":
|
||||
return findValueType(n, createIfNotExists)
|
||||
default:
|
||||
return nilValue(), &UnsupportedSelector{Selector: n.Selector.Raw}
|
||||
}
|
||||
|
||||
@@ -145,32 +145,6 @@ func TestFindValueDynamic(t *testing.T) {
|
||||
return
|
||||
}
|
||||
})
|
||||
t.Run("UnsupportedCheckType", func(t *testing.T) {
|
||||
itemVal := 1
|
||||
val := []interface{}{
|
||||
itemVal,
|
||||
}
|
||||
n := getNodeWithValue(val)
|
||||
n.Selector.Current = "(name=x)"
|
||||
n.Selector.Conditions = []Condition{
|
||||
&EqualCondition{Key: "name", Value: "x"},
|
||||
}
|
||||
got, err := findValueDynamic(n, false)
|
||||
assertQueryResult(t, nilValue(), &UnhandledCheckType{Value: reflect.TypeOf(itemVal).Kind().String()}, got, err)
|
||||
})
|
||||
t.Run("UnsupportedCheckTypeMap", func(t *testing.T) {
|
||||
itemVal := 1
|
||||
val := map[string]interface{}{
|
||||
"x": itemVal,
|
||||
}
|
||||
n := getNodeWithValue(val)
|
||||
n.Selector.Current = "(name=x)"
|
||||
n.Selector.Conditions = []Condition{
|
||||
&EqualCondition{Key: "name", Value: "x"},
|
||||
}
|
||||
got, err := findValueDynamic(n, false)
|
||||
assertQueryResult(t, nilValue(), &UnhandledCheckType{Value: reflect.TypeOf(itemVal).Kind().String()}, got, err)
|
||||
})
|
||||
t.Run("UnsupportedType", func(t *testing.T) {
|
||||
val := 0
|
||||
n := getNodeWithValue(val)
|
||||
@@ -227,6 +201,57 @@ func TestFindValueLength(t *testing.T) {
|
||||
})
|
||||
}
|
||||
|
||||
func TestFindValueType(t *testing.T) {
|
||||
t.Run("NilValue", func(t *testing.T) {
|
||||
n := getNodeWithValue(nil)
|
||||
n.Previous.Selector.Current = ".[#]"
|
||||
got, err := findValueType(n, false)
|
||||
assertQueryResult(t, nilValue(), &UnexpectedPreviousNilValue{Selector: ".[#]"}, got, err)
|
||||
})
|
||||
t.Run("Int", func(t *testing.T) {
|
||||
val := 0
|
||||
n := getNodeWithValue(val)
|
||||
n.Selector.Current = ".[#]"
|
||||
got, err := findValueType(n, false)
|
||||
assertQueryResult(t, reflect.ValueOf("int"), nil, got, err)
|
||||
})
|
||||
t.Run("Float", func(t *testing.T) {
|
||||
val := 1.1
|
||||
n := getNodeWithValue(val)
|
||||
n.Selector.Current = ".[#]"
|
||||
got, err := findValueType(n, false)
|
||||
assertQueryResult(t, reflect.ValueOf("float"), nil, got, err)
|
||||
})
|
||||
t.Run("Bool", func(t *testing.T) {
|
||||
val := true
|
||||
n := getNodeWithValue(val)
|
||||
n.Selector.Current = ".[#]"
|
||||
got, err := findValueType(n, false)
|
||||
assertQueryResult(t, reflect.ValueOf("bool"), nil, got, err)
|
||||
})
|
||||
t.Run("String", func(t *testing.T) {
|
||||
val := "x"
|
||||
n := getNodeWithValue(val)
|
||||
n.Selector.Current = ".[#]"
|
||||
got, err := findValueType(n, false)
|
||||
assertQueryResult(t, reflect.ValueOf("string"), nil, got, err)
|
||||
})
|
||||
t.Run("Map", func(t *testing.T) {
|
||||
val := map[string]interface{}{"x": 1}
|
||||
n := getNodeWithValue(val)
|
||||
n.Selector.Current = ".[#]"
|
||||
got, err := findValueType(n, false)
|
||||
assertQueryResult(t, reflect.ValueOf("map"), nil, got, err)
|
||||
})
|
||||
t.Run("Array", func(t *testing.T) {
|
||||
val := []interface{}{1}
|
||||
n := getNodeWithValue(val)
|
||||
n.Selector.Current = ".[#]"
|
||||
got, err := findValueType(n, false)
|
||||
assertQueryResult(t, reflect.ValueOf("array"), nil, got, err)
|
||||
})
|
||||
}
|
||||
|
||||
func TestFindValue(t *testing.T) {
|
||||
t.Run("MissingPreviousNode", func(t *testing.T) {
|
||||
n := New(nil)
|
||||
|
||||
@@ -459,6 +459,61 @@ func findNodesLength(selector Selector, previousValue reflect.Value) ([]*Node, e
|
||||
return nil, &UnsupportedTypeForSelector{Selector: selector, Value: value}
|
||||
}
|
||||
|
||||
// findNodesType returns the length
|
||||
func findNodesType(selector Selector, previousValue reflect.Value) ([]*Node, error) {
|
||||
if !isValid(previousValue) {
|
||||
return nil, &UnexpectedPreviousNilValue{Selector: selector.Raw}
|
||||
}
|
||||
|
||||
value := unwrapValue(previousValue)
|
||||
|
||||
switch value.Kind() {
|
||||
case reflect.Slice:
|
||||
node := &Node{
|
||||
Value: reflect.ValueOf("array"),
|
||||
Selector: selector,
|
||||
}
|
||||
return []*Node{node}, nil
|
||||
|
||||
case reflect.Map:
|
||||
node := &Node{
|
||||
Value: reflect.ValueOf("map"),
|
||||
Selector: selector,
|
||||
}
|
||||
return []*Node{node}, nil
|
||||
|
||||
case reflect.String:
|
||||
node := &Node{
|
||||
Value: reflect.ValueOf("string"),
|
||||
Selector: selector,
|
||||
}
|
||||
return []*Node{node}, nil
|
||||
|
||||
case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64:
|
||||
node := &Node{
|
||||
Value: reflect.ValueOf("int"),
|
||||
Selector: selector,
|
||||
}
|
||||
return []*Node{node}, nil
|
||||
|
||||
case reflect.Float32, reflect.Float64:
|
||||
node := &Node{
|
||||
Value: reflect.ValueOf("float"),
|
||||
Selector: selector,
|
||||
}
|
||||
return []*Node{node}, nil
|
||||
|
||||
case reflect.Bool:
|
||||
node := &Node{
|
||||
Value: reflect.ValueOf("bool"),
|
||||
Selector: selector,
|
||||
}
|
||||
return []*Node{node}, nil
|
||||
}
|
||||
|
||||
return nil, &UnsupportedTypeForSelector{Selector: selector, Value: value}
|
||||
}
|
||||
|
||||
func initialiseEmptyValue(selector Selector, previousValue reflect.Value) reflect.Value {
|
||||
switch selector.Type {
|
||||
case "PROPERTY":
|
||||
@@ -489,6 +544,8 @@ func findNodes(selector Selector, previousNode *Node, createIfNotExists bool) ([
|
||||
res, err = findNodesAnyIndex(selector, previousNode.Value)
|
||||
case "LENGTH":
|
||||
res, err = findNodesLength(selector, previousNode.Value)
|
||||
case "TYPE":
|
||||
res, err = findNodesType(selector, previousNode.Value)
|
||||
case "DYNAMIC":
|
||||
res, err = findNodesDynamic(selector, previousNode.Value, createIfNotExists)
|
||||
case "SEARCH":
|
||||
|
||||
@@ -131,6 +131,50 @@ func TestFindNodesLength(t *testing.T) {
|
||||
})
|
||||
}
|
||||
|
||||
func TestFindNodesType(t *testing.T) {
|
||||
t.Run("NilValue", func(t *testing.T) {
|
||||
selector := Selector{Current: ".[#]", Raw: ".[#]"}
|
||||
got, err := findNodesType(selector, nilValue())
|
||||
assertQueryMultipleResult(t, []reflect.Value{}, &UnexpectedPreviousNilValue{Selector: ".[#]"}, got, err)
|
||||
})
|
||||
t.Run("Int", func(t *testing.T) {
|
||||
selector := Selector{Current: ".[#]", Raw: ".[#]"}
|
||||
val := 0
|
||||
got, err := findNodesType(selector, reflect.ValueOf(val))
|
||||
assertQueryMultipleResult(t, []reflect.Value{reflect.ValueOf("int")}, nil, got, err)
|
||||
})
|
||||
t.Run("Float", func(t *testing.T) {
|
||||
selector := Selector{Current: ".[#]", Raw: ".[#]"}
|
||||
val := 1.1
|
||||
got, err := findNodesType(selector, reflect.ValueOf(val))
|
||||
assertQueryMultipleResult(t, []reflect.Value{reflect.ValueOf("float")}, nil, got, err)
|
||||
})
|
||||
t.Run("Bool", func(t *testing.T) {
|
||||
selector := Selector{Current: ".[#]", Raw: ".[#]"}
|
||||
val := true
|
||||
got, err := findNodesType(selector, reflect.ValueOf(val))
|
||||
assertQueryMultipleResult(t, []reflect.Value{reflect.ValueOf("bool")}, nil, got, err)
|
||||
})
|
||||
t.Run("String", func(t *testing.T) {
|
||||
selector := Selector{Current: ".[#]", Raw: ".[#]"}
|
||||
val := "a"
|
||||
got, err := findNodesType(selector, reflect.ValueOf(val))
|
||||
assertQueryMultipleResult(t, []reflect.Value{reflect.ValueOf("string")}, nil, got, err)
|
||||
})
|
||||
t.Run("Map", func(t *testing.T) {
|
||||
selector := Selector{Current: ".[#]", Raw: ".[#]"}
|
||||
val := map[string]interface{}{"x": 1}
|
||||
got, err := findNodesType(selector, reflect.ValueOf(val))
|
||||
assertQueryMultipleResult(t, []reflect.Value{reflect.ValueOf("map")}, nil, got, err)
|
||||
})
|
||||
t.Run("Array", func(t *testing.T) {
|
||||
selector := Selector{Current: ".[#]", Raw: ".[#]"}
|
||||
val := []interface{}{"x"}
|
||||
got, err := findNodesType(selector, reflect.ValueOf(val))
|
||||
assertQueryMultipleResult(t, []reflect.Value{reflect.ValueOf("array")}, nil, got, err)
|
||||
})
|
||||
}
|
||||
|
||||
func TestFindNodesPropertyKeys(t *testing.T) {
|
||||
t.Run("NilValue", func(t *testing.T) {
|
||||
selector := Selector{Current: ".", Raw: "."}
|
||||
@@ -279,32 +323,6 @@ func TestFindNodesDynamic(t *testing.T) {
|
||||
return
|
||||
}
|
||||
})
|
||||
t.Run("UnsupportedCheckType", func(t *testing.T) {
|
||||
previousValue := reflect.ValueOf([]interface{}{
|
||||
1,
|
||||
})
|
||||
selector := Selector{
|
||||
Current: "(name=x)",
|
||||
Conditions: []Condition{
|
||||
&EqualCondition{Key: "name", Value: "x"},
|
||||
},
|
||||
}
|
||||
got, err := findNodesDynamic(selector, previousValue, false)
|
||||
assertQueryMultipleResult(t, []reflect.Value{}, &UnhandledCheckType{Value: previousValue.Kind().String()}, got, err)
|
||||
})
|
||||
t.Run("UnsupportedCheckTypeMap", func(t *testing.T) {
|
||||
previousValue := reflect.ValueOf(map[string]interface{}{
|
||||
"x": 1,
|
||||
})
|
||||
selector := Selector{
|
||||
Current: "(name=x)",
|
||||
Conditions: []Condition{
|
||||
&EqualCondition{Key: "name", Value: "x"},
|
||||
},
|
||||
}
|
||||
got, err := findNodesDynamic(selector, previousValue, false)
|
||||
assertQueryMultipleResult(t, []reflect.Value{}, &UnhandledCheckType{Value: previousValue.Kind().String()}, got, err)
|
||||
})
|
||||
t.Run("UnsupportedType", func(t *testing.T) {
|
||||
previousValue := reflect.ValueOf(0)
|
||||
selector := Selector{
|
||||
|
||||
@@ -37,6 +37,8 @@ func ParseSelector(selector string) (Selector, error) {
|
||||
sel, err = processParseSelectorIndexAny(nextSel, sel)
|
||||
case nextSel == "[#]":
|
||||
sel, err = processParseSelectorLength(nextSel, sel)
|
||||
case nextSel == "[@]":
|
||||
sel, err = processParseSelectorType(nextSel, sel)
|
||||
case strings.HasPrefix(nextSel, "[") && strings.HasSuffix(nextSel, "]"):
|
||||
sel, err = processParseSelectorIndex(nextSel, sel)
|
||||
default:
|
||||
@@ -168,6 +170,11 @@ func processParseSelectorLength(selector string, sel Selector) (Selector, error)
|
||||
return sel, nil
|
||||
}
|
||||
|
||||
func processParseSelectorType(selector string, sel Selector) (Selector, error) {
|
||||
sel.Type = "TYPE"
|
||||
return sel, nil
|
||||
}
|
||||
|
||||
func processParseSelectorIndex(selector string, sel Selector) (Selector, error) {
|
||||
sel.Type = "INDEX"
|
||||
indexStr := selector[1 : len(selector)-1]
|
||||
|
||||
Reference in New Issue
Block a user