1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
//! # Eryx
//!
//! A Python sandbox with async callbacks, powered by WebAssembly.
//!
//! ## Safety
//!
//! By default, this crate uses `#![forbid(unsafe_code)]` for maximum safety.
//! When the `embedded` or `preinit` features are enabled, this is relaxed to
//! `#![deny(unsafe_code)]` to allow unsafe wasmtime APIs needed for pre-compiled
//! component loading and CPU feature configuration (e.g., disabling AVX-512).
//!
//! Eryx executes Python code in a secure WebAssembly sandbox with:
//!
//! - **Async callback mechanism** - Callbacks are exposed as direct async functions (e.g., `await get_time()`)
//! - **Parallel execution** - Multiple callbacks can run concurrently via `asyncio.gather()`
//! - **Execution tracing** - Line-level progress reporting via `sys.settrace`
//! - **Introspection** - Python can discover available callbacks at runtime
//! - **Composable runtime libraries** - Pre-built APIs with Python wrappers and type stubs
//!
//! ## Quick Start
//!
//! ```rust,no_run
//! use eryx::Sandbox;
//!
//! # #[cfg(feature = "embedded")]
//! #[tokio::main]
//! async fn main() -> Result<(), eryx::Error> {
//! // Use Sandbox::embedded() for zero-config setup (requires `embedded` feature)
//! let sandbox = Sandbox::embedded().build()?;
//!
//! let result = sandbox.execute("print('Hello from Python!')").await?;
//!
//! println!("Output: {}", result.stdout);
//! Ok(())
//! }
//! # #[cfg(not(feature = "embedded"))]
//! # fn main() {}
//! ```
// Safety lint configuration:
// - Default: forbid unsafe code entirely
// - With `embedded` feature: deny unsafe code, but allow it on specific items
// that need wasmtime's unsafe deserialization APIs
// - With `preinit` feature: deny unsafe code, needed for cranelift CPU feature flags
// during precompilation (e.g., disabling AVX-512 for portable builds)
/// Pre-initialization support for capturing Python memory state.
///
/// Pre-initialization runs Python's init + imports during build time and
/// captures the memory state into the component. This provides ~25x speedup
/// by avoiding the ~450ms startup cost on each sandbox creation.
///
/// Works with or without native extensions - can pre-import stdlib modules only.
pub use ;
pub use Error;
pub use RuntimeLibrary;
pub use ;
pub use ;
pub use ;
pub use ;
pub use ;
pub use ;
pub use ;
pub use ;
// Re-export precompilation utilities and internal types
pub use ;
// Re-export schema types at top level for convenience
pub use ;
// Re-export CancellationToken for convenient use with execute_cancellable
pub use CancellationToken;
// Re-export the callback proc macro when the macros feature is enabled
pub use callback;
/// Virtual filesystem support for sandboxed file operations.
///
/// When the `vfs` feature is enabled, sandboxes can use an in-memory filesystem
/// that persists across executions. This is useful for:
///
/// - Allowing Python code to read/write files without host filesystem access
/// - Persisting files across multiple executions
/// - Testing file operations in isolation
///
/// Virtual filesystem types for sandboxed file I/O.
///
/// VFS is available on `SessionExecutor` for persistent file storage across
/// multiple executions within a session.
///
/// # Example
///
/// ```rust,ignore
/// use eryx::vfs::InMemoryStorage;
/// use std::sync::Arc;
///
/// let storage = Arc::new(InMemoryStorage::new());
/// let session = SessionExecutor::new_with_vfs(executor, &[], storage).await?;
///
/// session.execute("open('/data/test.txt', 'w').write('hello')").run().await?;
/// session.execute("print(open('/data/test.txt').read())").run().await?; // prints "hello"
/// ```