Skip to content

Commit

Permalink
feat(python): add filter for test value
Browse files Browse the repository at this point in the history
adds a filter which, for simple types sets some value that is different
than the default value.
For enum it returns te second value (if present).
For the arrays it returns an element of that type
For structs it returns the default value.
This is used by a python template for #35 ticket
  • Loading branch information
dorotaphanSiili committed Sep 20, 2024
1 parent 8dbaa0b commit 4f39064
Show file tree
Hide file tree
Showing 4 changed files with 236 additions and 0 deletions.
1 change: 1 addition & 0 deletions pkg/gen/filters/filterpy/filters.go
Original file line number Diff line number Diff line change
Expand Up @@ -15,4 +15,5 @@ func PopulateFuncMap(fm template.FuncMap) {
fm["pyVars"] = pyVars
fm["pyType"] = pyType
fm["pyExtern"] = pyExtern
fm["pyTestValue"] = pyTestValue
}
93 changes: 93 additions & 0 deletions pkg/gen/filters/filterpy/py_testvalue.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,93 @@
package filterpy

import (
"fmt"

"github.com/apigear-io/cli/pkg/gen/filters/common"
"github.com/apigear-io/cli/pkg/model"
)

// ToTestValueString returns the test value string for a given schema.
// We intentionally ignore arrays in order to return the test value of the inner type.
func ToTestValueString(prefix string, schema *model.Schema) (string, error) {
if schema == nil {
return "xxx", fmt.Errorf("pyTestValue schema is nil")
}
if schema.Module == nil {
return "xxx", fmt.Errorf("pyTestValue schema module is nil")
}
var text string
switch schema.KindType {
case model.TypeString:
text = "\"xyz\""
case model.TypeInt, model.TypeInt32, model.TypeInt64:
text = "1"
case model.TypeFloat, model.TypeFloat32, model.TypeFloat64:
text = "1.1"
case model.TypeBool:
text = "True"
case model.TypeVoid:
return ToDefaultString(schema, prefix)
case model.TypeEnum:
e_local := schema.LookupEnum("", schema.Type)
e_imported := schema.LookupEnum(schema.Import, schema.Type)
if e_local == nil && e_imported == nil {
return "xxx", fmt.Errorf("pyTestValue enum not found: %s", schema.Dump())
}
// if enum is local it is found both as e_local and e_imported
name := common.CamelTitleCase(e_imported.Name)
member := common.SnakeUpperCase(e_imported.Members[0].Name)
if len(e_imported.Members) > 1 {
member = common.SnakeUpperCase(e_imported.Members[1].Name)
}
if e_local == nil {
prefix = fmt.Sprintf("%s.api.", e_imported.Module.Name)
}
text = fmt.Sprintf("%s%s.%s", prefix, name, member)
case model.TypeStruct:
s_local := schema.LookupStruct("", schema.Type)
s_imported := schema.LookupStruct(schema.Import, schema.Type)
if s_local == nil && s_imported == nil {
return "xxx", fmt.Errorf("pyTestValue struct not found: %s", schema.Dump())
}
// if struct is local it is found both as s_local and s_imported
ident := common.CamelTitleCase(s_imported.Name)
if s_local == nil {
prefix = fmt.Sprintf("%s.api.", s_imported.Module.Name)
}
text = fmt.Sprintf("%s%s()", prefix, ident)
case model.TypeExtern:
xe := parsePyExtern(schema)
if xe.Default != "" {
text = xe.Default
} else {
py_module := ""
if xe.Import != "" {
py_module = fmt.Sprintf("%s.", xe.Import)
}
text = fmt.Sprintf("%s%s()", py_module, xe.Name)
}
case model.TypeInterface:
i_local := schema.LookupInterface("", schema.Type)
i_imported := schema.LookupInterface(schema.Import, schema.Type)
if i_local == nil && i_imported == nil {
return "xxx", fmt.Errorf("pyTestValue interface not found: %s", schema.Dump())
}
// if interface is local it is found both as s_local and s_imported
ident := common.CamelTitleCase(i_imported.Name)
if i_local == nil {
prefix = fmt.Sprintf("%s.api.", i_imported.Module.Name)
}
text = fmt.Sprintf("%s%s()", prefix, ident)
default:
return "xxx", fmt.Errorf("pyTestValue unknown schema %s", schema.Dump())
}
return text, nil
}

func pyTestValue(prefix string, node *model.TypedNode) (string, error) {
if node == nil {
return "xxx", fmt.Errorf("pyTestValue node is nil")
}
return ToTestValueString(prefix, &node.Schema)
}
140 changes: 140 additions & 0 deletions pkg/gen/filters/filterpy/py_testvalue_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,140 @@
package filterpy

import (
"testing"

"github.com/stretchr/testify/assert"
)

// test with all the types
// properties, operation params, operation return, signal params, struct fields
func TestTestValueFromIdl(t *testing.T) {
t.Parallel()
syss := loadTestSystems(t)
var propTests = []struct {
mn string
in string
pn string
rt string
}{
{"test", "Test1", "propVoid", "None"},
{"test", "Test1", "propBool", "True"},
{"test", "Test1", "propInt", "1"},
{"test", "Test1", "propInt32", "1"},
{"test", "Test1", "propInt64", "1"},
{"test", "Test1", "propFloat", "1.1"},
{"test", "Test1", "propFloat32", "1.1"},
{"test", "Test1", "propFloat64", "1.1"},
{"test", "Test1", "propString", "\"xyz\""},
{"test", "Test1", "propBoolArray", "True"}, // all the array types return value intentionally, it may be put into empty array
{"test", "Test1", "propIntArray", "1"},
{"test", "Test1", "propInt32Array", "1"},
{"test", "Test1", "propInt64Array", "1"},
{"test", "Test1", "propFloatArray", "1.1"},
{"test", "Test1", "propFloat32Array", "1.1"},
{"test", "Test1", "propFloat64Array", "1.1"},
{"test", "Test1", "propStringArray", "\"xyz\""},
}
for _, sys := range syss {
for _, tt := range propTests {
t.Run(tt.pn, func(t *testing.T) {
prop := sys.LookupProperty(tt.mn, tt.in, tt.pn)
assert.NotNil(t, prop)
r, err := pyTestValue("", prop)
assert.NoError(t, err)
assert.Equal(t, tt.rt, r)
})
}
}
}

func TestTestValueSymbolsFromIdl(t *testing.T) {
t.Parallel()
syss := loadTestSystems(t)
var propTests = []struct {
mn string
in string
pn string
rt string
}{
{"test", "Test2", "propEnum", "Enum1.NOT_DEFAULT"},
{"test", "Test2", "propStruct", "Struct1()"},
{"test", "Test2", "propInterface", "Interface1()"},
{"test", "Test2", "propEnumArray", "Enum1.NOT_DEFAULT"},
{"test", "Test2", "propStructArray", "Struct1()"},
{"test", "Test2", "propInterfaceArray", "Interface1()"},
}
for _, sys := range syss {
for _, tt := range propTests {
t.Run(tt.pn, func(t *testing.T) {
prop := sys.LookupProperty(tt.mn, tt.in, tt.pn)
assert.NotNil(t, prop)
r, err := pyTestValue("", prop)
assert.NoError(t, err)
assert.Equal(t, tt.rt, r)
})
}
}
}

func TestTestValueWithErrors(t *testing.T) {
t.Parallel()
s, err := pyTestValue("", nil)
assert.Error(t, err)
assert.Equal(t, "xxx", s)
}

func TestTestValueReturnsExternDefault(t *testing.T) {
syss := loadExternSystems(t)
var propTests = []struct {
mn string
in string
pn string
rt string
}{
{"demo", "Iface1", "prop1", "XType1()"},
{"demo", "Iface1", "prop2", "XType2()"},
{"demo", "Iface1", "prop3", "XType3A()"},
}
for _, sys := range syss {
for _, tt := range propTests {
t.Run(tt.pn, func(t *testing.T) {
prop := sys.LookupProperty(tt.mn, tt.in, tt.pn)
assert.NotNil(t, prop)
r, err := pyTestValue("", prop)
assert.NoError(t, err)
assert.Equal(t, tt.rt, r)
})
}
}
}

func TestTestValueReturnsDefaultExterns(t *testing.T) {
t.Parallel()
table := []struct {
module_name string
interface_name string
operation_name string
result string
}{
{"test_apigear_next", "Iface1", "prop1", "XType1()"},
{"test_apigear_next", "Iface1", "prop2", "demo.x.XType2()"},
{"test_apigear_next", "Iface1", "prop3", "demo.x.createXType3A()"},
{"test_apigear_next", "Iface1", "propList", "demo.x.createXType3A()"},
{"test_apigear_next", "Iface1", "propImportedEnum", "test.api.Enum1.NOT_DEFAULT"},
{"test_apigear_next", "Iface1", "propImportedStruct", "test.api.Struct1()"},
}
syss := loadExternSystemsYAML(t)
prefix := "my_prefix::"
for _, sys := range syss {
for _, tt := range table {
t.Run(tt.operation_name, func(t *testing.T) {
prop := sys.LookupProperty(tt.module_name, tt.interface_name, tt.operation_name)
assert.NotNil(t, prop)
r, err := pyTestValue(prefix, prop)
assert.NoError(t, err)
assert.Equal(t, tt.result, r)
})
}
}
}
2 changes: 2 additions & 0 deletions pkg/gen/filters/testdata/test.module.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -319,9 +319,11 @@ enums:
- name: Enum1
members:
- name: Default
- name: NotDefault
- name: EnumLowerNames
members:
- name: firstValue
- name: secondValue

structs:
- name: Struct1

0 comments on commit 4f39064

Please sign in to comment.