Skip to main content

nautilus_sandbox/python/
mod.rs

1// -------------------------------------------------------------------------------------------------
2//  Copyright (C) 2015-2026 Nautech Systems Pty Ltd. All rights reserved.
3//  https://nautechsystems.io
4//
5//  Licensed under the GNU Lesser General Public License Version 3.0 (the "License");
6//  You may not use this file except in compliance with the License.
7//  You may obtain a copy of the License at https://www.gnu.org/licenses/lgpl-3.0.en.html
8//
9//  Unless required by applicable law or agreed to in writing, software
10//  distributed under the License is distributed on an "AS IS" BASIS,
11//  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12//  See the License for the specific language governing permissions and
13//  limitations under the License.
14// -------------------------------------------------------------------------------------------------
15
16//! Python bindings from `pyo3`.
17
18pub mod config;
19pub mod factories;
20
21use nautilus_common::factories::{ClientConfig, SimulatedExecutionClientFactory};
22use nautilus_core::python::{to_pyruntime_err, to_pyvalue_err};
23use nautilus_system::get_global_pyo3_registry;
24use pyo3::prelude::*;
25
26use crate::{config::SandboxExecutionClientConfig, factory::SandboxExecutionClientFactory};
27
28#[expect(clippy::needless_pass_by_value)]
29fn extract_sandbox_exec_factory(
30    py: Python<'_>,
31    factory: Py<PyAny>,
32) -> PyResult<Box<dyn SimulatedExecutionClientFactory>> {
33    match factory.extract::<SandboxExecutionClientFactory>(py) {
34        Ok(f) => Ok(Box::new(f)),
35        Err(e) => Err(to_pyvalue_err(format!(
36            "Failed to extract SandboxExecutionClientFactory: {e}"
37        ))),
38    }
39}
40
41#[expect(clippy::needless_pass_by_value)]
42fn extract_sandbox_exec_config(
43    py: Python<'_>,
44    config: Py<PyAny>,
45) -> PyResult<Box<dyn ClientConfig>> {
46    match config.extract::<SandboxExecutionClientConfig>(py) {
47        Ok(c) => Ok(Box::new(c)),
48        Err(e) => Err(to_pyvalue_err(format!(
49            "Failed to extract SandboxExecutionClientConfig: {e}"
50        ))),
51    }
52}
53
54/// Loaded as `nautilus_pyo3.sandbox`.
55///
56/// # Errors
57///
58/// Returns an error if the module registration fails or if adding functions/classes fails.
59#[pymodule]
60pub fn sandbox(_: Python<'_>, m: &Bound<'_, PyModule>) -> PyResult<()> {
61    m.add_class::<crate::config::SandboxExecutionClientConfig>()?;
62    m.add_class::<crate::factory::SandboxExecutionClientFactory>()?;
63
64    let registry = get_global_pyo3_registry();
65
66    if let Err(e) = registry
67        .register_sim_exec_factory_extractor("SANDBOX".to_string(), extract_sandbox_exec_factory)
68    {
69        return Err(to_pyruntime_err(format!(
70            "Failed to register Sandbox simulated exec factory extractor: {e}"
71        )));
72    }
73
74    if let Err(e) = registry.register_config_extractor(
75        "SandboxExecutionClientConfig".to_string(),
76        extract_sandbox_exec_config,
77    ) {
78        return Err(to_pyruntime_err(format!(
79            "Failed to register Sandbox execution config extractor: {e}"
80        )));
81    }
82
83    Ok(())
84}