mirror of
				https://github.com/TomWright/dasel.git
				synced 2022-05-22 02:32:45 +03:00 
			
		
		
		
	| @@ -36,21 +36,19 @@ func (c EqualCondition) Check(other reflect.Value) (bool, error) { | ||||
| 		return c.check(value.Interface(), c.Value) | ||||
| 	} | ||||
|  | ||||
| 	switch value.Kind() { | ||||
| 	case reflect.Map, reflect.Slice: | ||||
| 		subRootNode := New(value.Interface()) | ||||
| 		foundNode, err := subRootNode.Query(c.Key) | ||||
| 		if err != nil { | ||||
| 			var valueNotFound = &ValueNotFound{} | ||||
| 			if errors.As(err, &valueNotFound) { | ||||
| 				return false, nil | ||||
| 			} | ||||
|  | ||||
| 			return false, fmt.Errorf("subquery failed: %w", err) | ||||
| 	subRootNode := New(value.Interface()) | ||||
| 	foundNode, err := subRootNode.Query(c.Key) | ||||
| 	if err != nil { | ||||
| 		var valueNotFound = &ValueNotFound{} | ||||
| 		if errors.As(err, &valueNotFound) { | ||||
| 			return false, nil | ||||
| 		} | ||||
| 		var unsupportedType = &UnsupportedTypeForSelector{} | ||||
| 		if errors.As(err, &unsupportedType) { | ||||
| 			return false, nil | ||||
| 		} | ||||
|  | ||||
| 		return c.check(foundNode.InterfaceValue(), c.Value) | ||||
| 		return false, fmt.Errorf("subquery failed: %w", err) | ||||
| 	} | ||||
|  | ||||
| 	return false, &UnhandledCheckType{Value: value.String()} | ||||
| 	return c.check(foundNode.InterfaceValue(), c.Value) | ||||
| } | ||||
|   | ||||
| @@ -31,37 +31,32 @@ 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 { | ||||
| 			var valueNotFound = &ValueNotFound{} | ||||
| 			if errors.As(err, &valueNotFound) { | ||||
| 				return false, nil | ||||
| 			} | ||||
|  | ||||
| 			return false, fmt.Errorf("subquery failed: %w", err) | ||||
| 	subRootNode := New(value.Interface()) | ||||
| 	foundNode, err := subRootNode.Query(c.Key) | ||||
| 	if err != nil { | ||||
| 		var valueNotFound = &ValueNotFound{} | ||||
| 		if errors.As(err, &valueNotFound) { | ||||
| 			return false, nil | ||||
| 		} | ||||
|  | ||||
| 		foundValueStr := fmt.Sprint(foundNode.InterfaceValue()) | ||||
|  | ||||
| 		// Check if the values are equal | ||||
| 		if foundValueStr == c.Value { | ||||
| 			return c.Equal, nil | ||||
| 		} | ||||
|  | ||||
| 		sortedVals := []string{foundValueStr, c.Value} | ||||
| 		sort.Strings(sortedVals) | ||||
|  | ||||
| 		if !c.After && sortedVals[1] == c.Value { | ||||
| 			return true, nil | ||||
| 		} else if c.After && sortedVals[0] == c.Value { | ||||
| 			return true, nil | ||||
| 		} | ||||
|  | ||||
| 		return false, nil | ||||
| 		return false, fmt.Errorf("subquery failed: %w", err) | ||||
| 	} | ||||
|  | ||||
| 	return false, &UnhandledCheckType{Value: value.String()} | ||||
| 	foundValueStr := fmt.Sprint(foundNode.InterfaceValue()) | ||||
|  | ||||
| 	// Check if the values are equal | ||||
| 	if foundValueStr == c.Value { | ||||
| 		return c.Equal, nil | ||||
| 	} | ||||
|  | ||||
| 	sortedVals := []string{foundValueStr, c.Value} | ||||
| 	sort.Strings(sortedVals) | ||||
|  | ||||
| 	if !c.After && sortedVals[1] == c.Value { | ||||
| 		return true, nil | ||||
| 	} else if c.After && sortedVals[0] == c.Value { | ||||
| 		return true, nil | ||||
| 	} | ||||
|  | ||||
| 	return false, nil | ||||
| } | ||||
|   | ||||
| @@ -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
	 Tom Wright
					Tom Wright