Repository navigation
Expand file tree
/
Copy pathpylifecycle.rs
More file actions
120 lines (102 loc) · 3.39 KB
/
Copy pathpylifecycle.rs
File metadata and controls
120 lines (102 loc) · 3.39 KB
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
use crate::get_main_interpreter;
use crate::pyerrors::init_exception_statics;
use crate::pystate::ensure_thread_has_vm_attached;
use alloc::ffi::CString;
use core::ffi::{c_char, c_int, c_ulong};
use rustpython_vm::common::rc::PyRc;
use rustpython_vm::stdlib::sys;
use rustpython_vm::version::{MAJOR, MICRO, MINOR, RUSTPYTHON_BUILD_INFO, VERSION_HEX};
use rustpython_vm::vm::thread::ThreadedVirtualMachine;
use rustpython_vm::{Context, Interpreter};
use std::sync::{LazyLock, Mutex};
pub(crate) static MAIN_INTERP: Mutex<Option<Interpreter>> = Mutex::new(None);
/// Request a thread local vm from the main interpreter
pub(crate) fn request_vm_from_interpreter() -> ThreadedVirtualMachine {
get_main_interpreter()
.as_ref()
.expect("Interpreter not initialized")
.enter(|vm| vm.new_thread())
}
#[unsafe(no_mangle)]
pub static Py_Version: c_ulong = VERSION_HEX as c_ulong;
#[unsafe(no_mangle)]
pub extern "C" fn Py_IsInitialized() -> c_int {
get_main_interpreter().is_some() as c_int
}
#[unsafe(no_mangle)]
pub extern "C" fn Py_Initialize() {
Py_InitializeEx(0);
}
#[unsafe(no_mangle)]
pub extern "C" fn Py_InitializeEx(_initsigs: c_int) {
let mut interp = get_main_interpreter();
if interp.is_none() {
// Safety: Interpreter was not initialized before, so we can safely assume the statics are not used
unsafe { init_exception_statics(&Context::genesis().exceptions) };
let builder = Interpreter::builder(Default::default());
let defs = rustpython_stdlib::stdlib_module_defs(&builder.ctx);
*interp = builder
.add_native_modules(&defs)
.init_hook(|vm| {
let state = PyRc::get_mut(&mut vm.state).unwrap();
let path = rustpython_pylib::LIB_PATH.to_owned();
state.config.paths.stdlib_dir = Some(path.clone());
state.config.paths.module_search_paths.insert(0, path);
})
.build()
.into();
drop(interp);
ensure_thread_has_vm_attached();
}
}
#[unsafe(no_mangle)]
pub extern "C" fn Py_Finalize() {
let _ = Py_FinalizeEx();
}
#[unsafe(no_mangle)]
pub extern "C" fn Py_FinalizeEx() -> c_int {
0
}
#[unsafe(no_mangle)]
pub extern "C" fn Py_IsFinalizing() -> c_int {
0
}
#[unsafe(no_mangle)]
pub extern "C" fn Py_GetVersion() -> *const c_char {
static VERSION: LazyLock<CString> = LazyLock::new(|| {
CString::new(format!("{MAJOR}.{MINOR}.{MICRO}"))
.expect("version string must not contain interior NULs")
});
VERSION.as_ptr()
}
#[unsafe(no_mangle)]
pub extern "C" fn Py_GetBuildInfo() -> *const c_char {
static BUILD_INFO: LazyLock<CString> = LazyLock::new(|| {
CString::new(RUSTPYTHON_BUILD_INFO).expect("build info must not contain interior NULs")
});
BUILD_INFO.as_ptr()
}
#[unsafe(no_mangle)]
pub extern "C" fn Py_GetCompiler() -> *const c_char {
c"[RUST]".as_ptr()
}
#[unsafe(no_mangle)]
pub extern "C" fn Py_GetCopyright() -> *const c_char {
sys::COPYRIGHT.as_ptr()
}
#[unsafe(no_mangle)]
pub extern "C" fn Py_GetPlatform() -> *const c_char {
sys::PLATFORM.as_ptr()
}
#[cfg(test)]
mod tests {
use pyo3::prelude::*;
#[test]
fn get_version() {
Python::attach(|py| {
let version = py.version_info();
assert!(version >= (3, 14));
});
assert!(unsafe { pyo3::ffi::Py_Version } >= 0x030d0000);
}
}