Skip to content
New issue

Have a question about this project? # for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “#”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? # to your account

[Python] Support recursive shapes that are boxed in Rust #2476

Closed
Tracked by #1367
crisidev opened this issue Mar 21, 2023 · 1 comment · Fixed by #2541
Closed
Tracked by #1367

[Python] Support recursive shapes that are boxed in Rust #2476

crisidev opened this issue Mar 21, 2023 · 1 comment · Fixed by #2541
Labels
bug Something isn't working python-server Python server SDK

Comments

@crisidev
Copy link
Contributor

crisidev commented Mar 21, 2023

Recursive shapes are Boxed in Rust and pyo3 does not implement FromPyObj and IntoPy for Box<T>.

This can be solved by implementing these 2 traits for Box<T> and Option<Box<T> where T is not any concrete type.

More info PyO3/pyo3#2090

@crisidev crisidev added bug Something isn't working python-server Python server SDK labels Mar 21, 2023
@crisidev crisidev changed the title Support recursive shapes that are boxed in Rust [Python] Support recursive shapes that are boxed in Rust Mar 21, 2023
@crisidev
Copy link
Contributor Author

crisidev commented Mar 21, 2023

For anything that is part of a pyo3 function definition like

#[pymethods]
impl MyStruct {
    pub fn newpy(
        arg1: Box<OtherStruct>, 
        arg2: Option<Box<OtherStruct>>, 
    ) -> Self {
        ...
    }
}

we can use the macro #[pyo3(from_py_with = "extractor_func")]

For example:

fn make_box<T>(src: &pyo3::PyAny) -> pyo3::PyResult<Box<T>>
where
    T: for<'a> pyo3::FromPyObject<'a>
{
    src.extract().map(Box::new)
}
fn make_optional_box<T>(src: &pyo3::PyAny) -> pyo3::PyResult<Option<Box<T>>>
where
    T: for<'a> pyo3::FromPyObject<'a> 
{
    ...
}

The implementation will become:

#[pymethods]
impl MyStruct {
    pub fn newpy(
        #[pyo3(from_py_with = "make_box")]
        arg1: Box<OtherStruct>, 
        #[pyo3(from_py_with = "make_optional_box")]
        arg2: Option<Box<OtherStruct>>, 
    ) -> Self {
        ...
    }
}

But I think this is not enough and it would be better to just generate the implementation of FromPyObj and IntoPy traits as from_py_with seems to be useable only in function signature and not in structure definitions.

# for free to join this conversation on GitHub. Already have an account? # to comment
Labels
bug Something isn't working python-server Python server SDK
Projects
None yet
Development

Successfully merging a pull request may close this issue.

1 participant