Python: Add the ability to invoke functions declared in Slint from Python

This commit is contained in:
Simon Hausmann 2024-06-05 20:26:41 +02:00 committed by Simon Hausmann
parent 37b63e4bd4
commit b98035526b
5 changed files with 65 additions and 3 deletions

View file

@ -154,6 +154,11 @@ impl ComponentDefinition {
self.definition.callbacks().collect()
}
#[getter]
fn functions(&self) -> Vec<String> {
self.definition.functions().collect()
}
#[getter]
fn globals(&self) -> Vec<String> {
self.definition.globals().collect()
@ -169,6 +174,10 @@ impl ComponentDefinition {
self.definition.global_callbacks(name).map(|callbackiter| callbackiter.collect())
}
fn global_functions(&self, name: &str) -> Option<Vec<String>> {
self.definition.global_functions(name).map(|functioniter| functioniter.collect())
}
fn create(&self) -> Result<ComponentInstance, crate::errors::PyPlatformError> {
Ok(ComponentInstance {
instance: self.definition.create()?,

View file

@ -74,6 +74,22 @@ def _build_global_class(compdef, global_name):
properties_and_callbacks[python_prop] = mk_setter_getter(callback_name)
for function_name in compdef.global_functions(global_name):
python_prop = _normalize_prop(function_name)
if python_prop in properties_and_callbacks:
logging.warning(f"Duplicated function {prop_name}")
continue
def mk_getter(function_name):
def getter(self):
def call(*args):
return self.__instance__.invoke_global(global_name, function_name, *args)
return call
return property(getter)
properties_and_callbacks[python_prop] = mk_getter(function_name)
return type("SlintGlobalClassWrapper", (), properties_and_callbacks)
@ -143,6 +159,22 @@ def _build_class(compdef):
properties_and_callbacks[python_prop] = mk_setter_getter(callback_name)
for function_name in compdef.functions:
python_prop = _normalize_prop(function_name)
if python_prop in properties_and_callbacks:
logging.warning(f"Duplicated function {prop_name}")
continue
def mk_getter(function_name):
def getter(self):
def call(*args):
return self.__instance__.invoke(function_name, *args)
return call
return property(getter)
properties_and_callbacks[python_prop] = mk_getter(function_name)
for global_name in compdef.globals:
global_class = _build_global_class(compdef, global_name)

View file

@ -3,7 +3,8 @@
import pytest
from slint import slint as native
from slint.slint import ValueType;
from slint.slint import ValueType
def test_basic_compiler():
compiler = native.ComponentCompiler()
@ -18,6 +19,7 @@ def test_basic_compiler():
export global TestGlobal {
in property <string> theglobalprop;
callback globallogic();
public function globalfun() {}
}
export component Test {
@ -31,6 +33,7 @@ def test_basic_compiler():
in property <[string]> modelprop;
callback test-callback();
public function ff() {}
}
""", "")
assert compdef != None
@ -38,21 +41,28 @@ def test_basic_compiler():
assert compdef.name == "Test"
props = [(name, type) for name, type in compdef.properties.items()]
assert props == [('boolprop', ValueType.Bool), ('brushprop', ValueType.Brush), ('colprop', ValueType.Brush), ('floatprop', ValueType.Number), ('imgprop', ValueType.Image), ('intprop', ValueType.Number), ('modelprop', ValueType.Model), ('strprop', ValueType.String)]
assert props == [('boolprop', ValueType.Bool), ('brushprop', ValueType.Brush), ('colprop', ValueType.Brush), ('floatprop', ValueType.Number),
('imgprop', ValueType.Image), ('intprop', ValueType.Number), ('modelprop', ValueType.Model), ('strprop', ValueType.String)]
assert compdef.callbacks == ["test-callback"]
assert compdef.functions == ["ff"]
assert compdef.globals == ["TestGlobal"]
assert compdef.global_properties("Garbage") == None
assert [(name, type) for name, type in compdef.global_properties("TestGlobal").items()] == [('theglobalprop', ValueType.String)]
assert [(name, type) for name, type in compdef.global_properties(
"TestGlobal").items()] == [('theglobalprop', ValueType.String)]
assert compdef.global_callbacks("Garbage") == None
assert compdef.global_callbacks("TestGlobal") == ["globallogic"]
assert compdef.global_functions("Garbage") == None
assert compdef.global_functions("TestGlobal") == ["globalfun"]
instance = compdef.create()
assert instance != None
def test_compiler_build_from_path():
compiler = native.ComponentCompiler()

View file

@ -35,8 +35,12 @@ def test_load_file_wrapper():
instance.say_hello = lambda x: "from here: " + x
assert instance.say_hello("wohoo") == "from here: wohoo"
assert instance.plus_one(42) == 43
assert instance.MyGlobal.global_prop == "This is global"
assert instance.MyGlobal.minus_one(100) == 99
del instance

View file

@ -4,6 +4,9 @@
export global MyGlobal {
in-out property <string> global-prop: "This is global";
callback global-callback(string) -> string;
public function minus-one(value: int) {
return value - 1;
}
}
export component App {
@ -26,6 +29,10 @@ export component App {
return MyGlobal.global-callback(arg);
}
public function plus-one(value: int) {
return value + 1;
}
Rectangle {
color: red;
}