py_function_sync_async

Macro py_function_sync_async 

Source
macro_rules! py_function_sync_async {
    (
        $(#[$meta: meta])+
        async fn $name: ident($($(#[$arg_meta: meta])*$arg: ident : $kind: ty),* $(,)?) $(-> $ret: ty)? $body: block
    ) => { ... };
}
Expand description

Given a single implementation of an async function, create that function as private and two pyfunctions named after it that can be used to invoke either blocking or async variants of the same function.

In order to export the function to Python using pyo3 you must include the #[pyfunction] attribute. This isn’t included in the macro by default since one may wish to annotate #[pyfunction] with additional arguments.

The given function will be spawned on a Rust event loop this means functions like pyo3::Python::with_gil should not be used, as acquiring Python’s global interpreter lock from a Rust runtime isn’t possible.

This macro cannot be used when lifetime specifiers are required, or the pyfunction bodies need additional parameter handling besides simply calling out to the underlying py_async or py_sync macros.

// ... becomes python package "things"
create_init_submodule! {
    funcs: [
        py_do_thing,
        py_do_thing_async,
    ]
}

py_function_sync_async! {
    #[pyfunction]
    #[args(timeout = "None")]
    async fn do_thing(timeout: Option<u64>) -> PyResult<String> {
        // ... sleep for timeout ...
        Ok(String::from("done"))
    }
}

becomes in python:

from things import do_thing, do_thing_async
assert do_thing() == "done"
assert await do_thing_async() == "done"