Python: Separate PyValue into PyToSlintValue and SlintToPyValue

For the latter, in the future, we need additional book-keeping.
This commit is contained in:
Simon Hausmann 2025-07-07 22:21:07 +02:00 committed by Simon Hausmann
parent b2b3a09d52
commit 94018778c9
3 changed files with 35 additions and 28 deletions

View file

@ -21,7 +21,7 @@ use pyo3::PyTraverseError;
use crate::errors::{
PyGetPropertyError, PyInvokeError, PyPlatformError, PySetCallbackError, PySetPropertyError,
};
use crate::value::{PyStruct, PyValue};
use crate::value::{PyStruct, PyToSlintValue, SlintToPyValue};
#[gen_stub_pyclass]
#[pyclass(unsendable)]
@ -300,12 +300,12 @@ impl ComponentInstance {
ComponentDefinition { definition: self.instance.definition() }
}
fn get_property(&self, name: &str) -> Result<PyValue, PyGetPropertyError> {
fn get_property(&self, name: &str) -> Result<SlintToPyValue, PyGetPropertyError> {
Ok(self.instance.get_property(name)?.into())
}
fn set_property(&self, name: &str, value: Bound<'_, PyAny>) -> PyResult<()> {
let pv: PyValue = value.extract()?;
let pv: PyToSlintValue = value.extract()?;
Ok(self.instance.set_property(name, pv.0).map_err(|e| PySetPropertyError(e))?)
}
@ -313,7 +313,7 @@ impl ComponentInstance {
&self,
global_name: &str,
prop_name: &str,
) -> Result<PyValue, PyGetPropertyError> {
) -> Result<SlintToPyValue, PyGetPropertyError> {
Ok(self.instance.get_global_property(global_name, prop_name)?.into())
}
@ -323,7 +323,7 @@ impl ComponentInstance {
prop_name: &str,
value: Bound<'_, PyAny>,
) -> PyResult<()> {
let pv: PyValue = value.extract()?;
let pv: PyToSlintValue = value.extract()?;
Ok(self
.instance
.set_global_property(global_name, prop_name, pv.0)
@ -331,10 +331,10 @@ impl ComponentInstance {
}
#[pyo3(signature = (callback_name, *args))]
fn invoke(&self, callback_name: &str, args: Bound<'_, PyTuple>) -> PyResult<PyValue> {
fn invoke(&self, callback_name: &str, args: Bound<'_, PyTuple>) -> PyResult<SlintToPyValue> {
let mut rust_args = vec![];
for arg in args.iter() {
let pv: PyValue = arg.extract()?;
let pv: PyToSlintValue = arg.extract()?;
rust_args.push(pv.0)
}
Ok(self.instance.invoke(callback_name, &rust_args).map_err(|e| PyInvokeError(e))?.into())
@ -346,10 +346,10 @@ impl ComponentInstance {
global_name: &str,
callback_name: &str,
args: Bound<'_, PyTuple>,
) -> PyResult<PyValue> {
) -> PyResult<SlintToPyValue> {
let mut rust_args = vec![];
for arg in args.iter() {
let pv: PyValue = arg.extract()?;
let pv: PyToSlintValue = arg.extract()?;
rust_args.push(pv.0)
}
Ok(self
@ -419,7 +419,8 @@ impl GcVisibleCallbacks {
let callables = callables.borrow();
let callable = callables.get(&name).unwrap();
Python::with_gil(|py| {
let py_args = PyTuple::new(py, args.iter().map(|v| PyValue(v.clone()))).unwrap();
let py_args =
PyTuple::new(py, args.iter().map(|v| SlintToPyValue(v.clone()))).unwrap();
let result = match callable.call(py, py_args, None) {
Ok(result) => result,
Err(err) => {
@ -429,7 +430,7 @@ impl GcVisibleCallbacks {
return Value::Void;
}
};
let pv: PyValue = match result.extract(py) {
let pv: PyToSlintValue = match result.extract(py) {
Ok(value) => value,
Err(err) => {
eprintln!("Python: Unable to convert return value of Python callback for {name} to Slint value: {err}");

View file

@ -11,7 +11,7 @@ use pyo3::gc::PyVisit;
use pyo3::prelude::*;
use pyo3::PyTraverseError;
use crate::value::PyValue;
use crate::value::{PyToSlintValue, SlintToPyValue};
pub struct PyModelShared {
notify: ModelNotify,
@ -119,7 +119,7 @@ impl i_slint_core::model::Model for PyModelShared {
}
};
match result.extract::<PyValue>(py) {
match result.extract::<PyToSlintValue>(py) {
Ok(pv) => Some(pv.0),
Err(err) => {
eprintln!("Python: Model implementation of row_data() returned value that cannot be converted to Rust: {err}");
@ -137,7 +137,9 @@ impl i_slint_core::model::Model for PyModelShared {
return;
};
if let Err(err) = obj.call_method1(py, "set_row_data", (row, PyValue::from(data))) {
if let Err(err) =
obj.call_method1(py, "set_row_data", (row, SlintToPyValue::from(data)))
{
eprintln!(
"Python: Model implementation of set_row_data() threw an exception: {err}"
);
@ -174,7 +176,7 @@ impl ReadOnlyRustModel {
self.0.row_count()
}
fn row_data(&self, row: usize) -> Option<PyValue> {
fn row_data(&self, row: usize) -> Option<SlintToPyValue> {
self.0.row_data(row).map(|value| value.into())
}
@ -186,7 +188,7 @@ impl ReadOnlyRustModel {
ReadOnlyRustModelIterator { model: slf.0.clone(), row: 0 }
}
fn __getitem__(&self, index: usize) -> Option<PyValue> {
fn __getitem__(&self, index: usize) -> Option<SlintToPyValue> {
self.row_data(index)
}
}
@ -209,7 +211,7 @@ impl ReadOnlyRustModelIterator {
slf
}
fn __next__(&mut self) -> Option<PyValue> {
fn __next__(&mut self) -> Option<SlintToPyValue> {
if self.row >= self.model.row_count() {
return None;
}

View file

@ -9,9 +9,12 @@ use pyo3_stub_gen::{derive::gen_stub_pyclass, derive::gen_stub_pymethods};
use std::collections::HashMap;
#[gen_stub_pyclass]
pub struct PyValue(pub slint_interpreter::Value);
pub struct PyToSlintValue(pub slint_interpreter::Value);
impl<'py> IntoPyObject<'py> for PyValue {
#[gen_stub_pyclass]
pub struct SlintToPyValue(pub slint_interpreter::Value);
impl<'py> IntoPyObject<'py> for SlintToPyValue {
type Target = PyAny;
type Output = Bound<'py, Self::Target>;
type Error = PyErr;
@ -45,10 +48,10 @@ impl<'py> IntoPyObject<'py> for PyValue {
}
}
impl<'py> FromPyObject<'py> for PyValue {
impl<'py> FromPyObject<'py> for PyToSlintValue {
fn extract_bound(ob: &Bound<'py, PyAny>) -> PyResult<Self> {
if ob.is_none() {
return Ok(slint_interpreter::Value::Void.into());
return Ok(Self(slint_interpreter::Value::Void));
}
let interpreter_val = ob
@ -89,7 +92,7 @@ impl<'py> FromPyObject<'py> for PyValue {
.iter()
.map(|(name, pyval)| {
let name = name.extract::<&str>()?.to_string();
let slintval = PyValue::extract_bound(&pyval)?;
let slintval = PyToSlintValue::extract_bound(&pyval)?;
Ok((name, slintval.0))
})
.collect::<Result<Vec<(_, _)>, PyErr>>();
@ -98,10 +101,11 @@ impl<'py> FromPyObject<'py> for PyValue {
))
})?;
Ok(PyValue(interpreter_val))
Ok(PyToSlintValue(interpreter_val))
}
}
impl From<slint_interpreter::Value> for PyValue {
impl From<slint_interpreter::Value> for SlintToPyValue {
fn from(value: slint_interpreter::Value) -> Self {
Self(value)
}
@ -122,7 +126,7 @@ impl PyStruct {
Default::default()
}
fn __getattr__(&self, key: &str) -> PyResult<PyValue> {
fn __getattr__(&self, key: &str) -> PyResult<SlintToPyValue> {
self.data.get_field(key).map_or_else(
|| {
Err(pyo3::exceptions::PyAttributeError::new_err(format!(
@ -133,7 +137,7 @@ impl PyStruct {
)
}
fn __setattr__(&mut self, py: Python<'_>, key: String, value: PyObject) -> PyResult<()> {
let pv: PyValue = value.extract(py)?;
let pv: PyToSlintValue = value.extract(py)?;
self.data.set_field(key, pv.0);
Ok(())
}
@ -173,7 +177,7 @@ impl PyStructFieldIterator {
slf
}
fn __next__(mut slf: PyRefMut<'_, Self>) -> Option<(String, PyValue)> {
slf.inner.next().map(|(name, val)| (name, PyValue(val)))
fn __next__(mut slf: PyRefMut<'_, Self>) -> Option<(String, SlintToPyValue)> {
slf.inner.next().map(|(name, val)| (name, SlintToPyValue(val)))
}
}