monarch_types/
lib.rs

1/*
2 * Copyright (c) Meta Platforms, Inc. and affiliates.
3 * All rights reserved.
4 *
5 * This source code is licensed under the BSD-style license found in the
6 * LICENSE file in the root directory of this source tree.
7 */
8
9#![feature(assert_matches)]
10
11mod pyobject;
12mod python;
13mod pytree;
14
15use pyo3::PyErr;
16use pyo3::exceptions::PyValueError;
17pub use pyobject::PickledPyObject;
18pub use python::SerializablePyErr;
19pub use python::TryIntoPyObjectUnsafe;
20pub use pytree::PyTree;
21
22/// Macro to generate a Python object lookup function with caching
23///
24/// # Arguments
25/// * `$fn_name` - Name of the Rust function to generate
26/// * `$python_path` - Path to the Python object as a string (e.g., "module.submodule.function")
27#[macro_export]
28macro_rules! py_global {
29    ($fn_name:ident, $python_module:literal, $python_class:literal) => {
30        fn $fn_name<'py>(py: ::pyo3::Python<'py>) -> ::pyo3::Bound<'py, ::pyo3::PyAny> {
31            static CACHE: ::pyo3::sync::PyOnceLock<::pyo3::Py<::pyo3::PyAny>> =
32                ::pyo3::sync::PyOnceLock::new();
33            CACHE
34                .import(py, $python_module, $python_class)
35                .unwrap()
36                .clone()
37        }
38    };
39}
40
41/// Macro to register a function to a Python module.
42#[macro_export]
43macro_rules! py_module_add_function {
44    ($mod:ident, $mod_name:literal, $fn:ident) => {
45        let f = pyo3::wrap_pyfunction!($fn, $mod)?;
46        f.setattr("__module__", $mod_name)?;
47        $mod.add_function(f)?;
48    };
49}
50
51pub trait MapPyErr<T> {
52    fn map_pyerr(self) -> Result<T, PyErr>;
53}
54impl<T, E> MapPyErr<T> for Result<T, E>
55where
56    E: ToString,
57{
58    fn map_pyerr(self) -> Result<T, PyErr> {
59        self.map_err(|err| PyErr::new::<PyValueError, _>(err.to_string()))
60    }
61}