Thanks to visit codestin.com
Credit goes to github.com

Skip to content

Commit 5eed597

Browse files
committed
Fix sysconfigdata platform-specific alias name registration
- Register _sysconfigdata under both short name and platform-specific name - Refactor sysconfigdata_name() to be reusable across modules - Add platform-specific name to sys.builtin_module_names - Eliminate code duplication in sysconfigdata name formatting This fixes the CI failure where sysconfig module imports '_sysconfigdata_t_darwin_aarch64-apple-darwin' but RustPython only registered '_sysconfigdata'. PyGlobalState
1 parent e97370a commit 5eed597

File tree

7 files changed

+114
-86
lines changed

7 files changed

+114
-86
lines changed

crates/vm/src/stdlib/nt.rs

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,14 +1,12 @@
11
// spell-checker:disable
22

3-
use crate::{PyRef, VirtualMachine, builtins::PyModule};
4-
53
pub(crate) use module::module_def;
64
pub use module::raw_set_handle_inheritable;
75

86
#[pymodule(name = "nt", with(super::os::_os))]
97
pub(crate) mod module {
108
use crate::{
11-
PyResult, TryFromObject, VirtualMachine,
9+
Py, PyResult, TryFromObject, VirtualMachine,
1210
builtins::{PyBaseExceptionRef, PyDictRef, PyListRef, PyStrRef, PyTupleRef},
1311
common::{crt_fd, suppress_iph, windows::ToWideString},
1412
convert::ToPyException,

crates/vm/src/stdlib/sys.rs

Lines changed: 6 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -166,9 +166,11 @@ mod sys {
166166

167167
#[pyattr]
168168
fn builtin_module_names(vm: &VirtualMachine) -> PyTupleRef {
169-
let mut module_names: Vec<&str> = vm.state.module_defs.keys().copied().collect();
170-
module_names.push("sys");
171-
module_names.push("builtins");
169+
let mut module_names: Vec<String> =
170+
vm.state.module_defs.keys().map(|&s| s.to_owned()).collect();
171+
module_names.push("sys".to_owned());
172+
module_names.push("builtins".to_owned());
173+
172174
module_names.sort();
173175
vm.ctx.new_tuple(
174176
module_names
@@ -1673,7 +1675,7 @@ pub fn get_stderr(vm: &VirtualMachine) -> PyResult {
16731675
.map_err(|_| vm.new_runtime_error("lost sys.stderr"))
16741676
}
16751677

1676-
pub(crate) fn sysconfigdata_name() -> String {
1678+
pub fn sysconfigdata_name() -> String {
16771679
format!(
16781680
"_sysconfigdata_{}_{}_{}",
16791681
sys::ABIFLAGS,

crates/vm/src/stdlib/sysconfigdata.rs

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -16,10 +16,12 @@ mod _sysconfigdata {
1616
let build_time_vars = build_time_vars(vm);
1717
module.set_attr("build_time_vars", build_time_vars, vm)?;
1818

19-
// Add CPython-compatible alias to sys.modules
20-
let sysconfigdata_name = sysconfigdata_name();
19+
// Ensure the module is registered under the platform-specific name
20+
// (import_builtin() already handles this, but double-check for safety)
2121
let sys_modules = vm.sys_module.get_attr("modules", vm)?;
22+
let sysconfigdata_name = sysconfigdata_name();
2223
sys_modules.set_item(sysconfigdata_name.as_str(), module.to_owned().into(), vm)?;
24+
2325
Ok(())
2426
}
2527

crates/vm/src/stdlib/winreg.rs

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,6 @@
11
// spell-checker:disable
22
#![allow(non_snake_case)]
33

4-
use crate::{PyRef, VirtualMachine, builtins::PyModule};
5-
64
pub(crate) use winreg::module_def;
75

86
#[pymodule]

crates/vm/src/vm/interpreter.rs

Lines changed: 90 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
use super::{Context, PyConfig, VirtualMachine, setting::Settings, thread};
1+
use super::{Context, PyConfig, PyGlobalState, VirtualMachine, setting::Settings, thread};
22
use crate::{
33
PyResult, builtins, common::rc::PyRc, getpath, stdlib::atexit, vm::PyBaseExceptionRef,
44
};
@@ -35,37 +35,111 @@ fn initialize_main_vm<F>(
3535
module_defs: Vec<&'static builtins::PyModuleDef>,
3636
init_hooks: Vec<InitFunc>,
3737
init: F,
38-
) -> VirtualMachine
38+
) -> (VirtualMachine, PyRc<PyGlobalState>)
3939
where
4040
F: FnOnce(&mut VirtualMachine),
4141
{
42+
use crate::codecs::CodecsRegistry;
43+
use crate::common::hash::HashSecret;
44+
use crate::common::lock::PyMutex;
45+
use crate::warn::WarningsState;
46+
use crossbeam_utils::atomic::AtomicCell;
47+
use std::sync::atomic::AtomicBool;
4248
let paths = getpath::init_path_config(&settings);
4349
let config = PyConfig::new(settings, paths);
4450

4551
crate::types::TypeZoo::extend(&ctx);
4652
crate::exceptions::ExceptionZoo::extend(&ctx);
4753

48-
let mut vm = VirtualMachine::new(config, ctx);
54+
// Build module_defs map from builtin modules + additional modules
55+
let mut all_module_defs: std::collections::BTreeMap<
56+
&'static str,
57+
&'static builtins::PyModuleDef,
58+
> = crate::stdlib::builtin_module_defs(&ctx)
59+
.into_iter()
60+
.map(|def| (def.name.as_str(), def))
61+
.collect();
4962

50-
// Register module definitions
63+
// Add additional module definitions
5164
for def in module_defs {
52-
PyRc::get_mut(&mut vm.state)
53-
.expect("there should not be multiple threads during initialization")
54-
.module_defs
55-
.insert(def.name.as_str(), def);
65+
all_module_defs.insert(def.name.as_str(), def);
5666
}
5767

58-
// Execute initialization hooks
68+
// Register sysconfigdata under platform-specific name as well
69+
if let Some(&sysconfigdata_def) = all_module_defs.get("_sysconfigdata") {
70+
let sysconfigdata_name = crate::stdlib::sys::sysconfigdata_name();
71+
// Leak the string to get a 'static lifetime for the key
72+
let leaked_name: &'static str = Box::leak(sysconfigdata_name.into_boxed_str());
73+
all_module_defs.insert(leaked_name, sysconfigdata_def);
74+
}
75+
76+
// Create hash secret
77+
let seed = match config.settings.hash_seed {
78+
Some(seed) => seed,
79+
None => super::process_hash_secret_seed(),
80+
};
81+
let hash_secret = HashSecret::new(seed);
82+
83+
// Create codec registry and warnings state
84+
let codec_registry = CodecsRegistry::new(&ctx);
85+
let warnings = WarningsState::init_state(&ctx);
86+
87+
// Create int_max_str_digits
88+
let int_max_str_digits = AtomicCell::new(match config.settings.int_max_str_digits {
89+
-1 => 4300,
90+
other => other,
91+
} as usize);
92+
93+
// Initialize frozen modules
94+
let frozen = super::core_frozen_inits().collect();
95+
96+
// Create PyGlobalState
97+
let global_state = PyRc::new(PyGlobalState {
98+
config,
99+
module_defs: all_module_defs,
100+
frozen,
101+
stacksize: AtomicCell::new(0),
102+
thread_count: AtomicCell::new(0),
103+
hash_secret,
104+
atexit_funcs: PyMutex::default(),
105+
codec_registry,
106+
finalizing: AtomicBool::new(false),
107+
warnings,
108+
override_frozen_modules: AtomicCell::new(0),
109+
before_forkers: PyMutex::default(),
110+
after_forkers_child: PyMutex::default(),
111+
after_forkers_parent: PyMutex::default(),
112+
int_max_str_digits,
113+
switch_interval: AtomicCell::new(0.005),
114+
global_trace_func: PyMutex::default(),
115+
global_profile_func: PyMutex::default(),
116+
#[cfg(feature = "threading")]
117+
main_thread_ident: AtomicCell::new(0),
118+
#[cfg(feature = "threading")]
119+
thread_frames: parking_lot::Mutex::new(std::collections::HashMap::new()),
120+
#[cfg(feature = "threading")]
121+
thread_handles: parking_lot::Mutex::new(Vec::new()),
122+
#[cfg(feature = "threading")]
123+
shutdown_handles: parking_lot::Mutex::new(Vec::new()),
124+
});
125+
126+
// Create VM with the global state
127+
// Note: Don't clone here - init_hooks need exclusive access to mutate state
128+
let mut vm = VirtualMachine::new(ctx, global_state);
129+
130+
// Execute initialization hooks (can mutate vm.state)
59131
for hook in init_hooks {
60132
hook(&mut vm);
61133
}
62134

63-
// Call custom init function
135+
// Call custom init function (can mutate vm.state)
64136
init(&mut vm);
65137

66138
vm.initialize();
67139

68-
vm
140+
// Clone global_state for Interpreter after all initialization is done
141+
let global_state = vm.state.clone();
142+
(vm, global_state)
69143
}
70144

71145
impl InterpreterBuilder {
@@ -172,14 +246,14 @@ impl InterpreterBuilder {
172246
///
173247
/// This consumes the configuration and returns a fully initialized Interpreter.
174248
pub fn build(self) -> Interpreter {
175-
let vm = initialize_main_vm(
249+
let (vm, global_state) = initialize_main_vm(
176250
self.settings,
177251
self.ctx,
178252
self.module_defs,
179253
self.init_hooks,
180254
|_| {}, // No additional init needed
181255
);
182-
Interpreter { vm }
256+
Interpreter { global_state, vm }
183257
}
184258

185259
/// Alias for `build()` for compatibility with the `interpreter()` pattern.
@@ -213,6 +287,7 @@ impl Default for InterpreterBuilder {
213287
/// });
214288
/// ```
215289
pub struct Interpreter {
290+
pub global_state: PyRc<PyGlobalState>,
216291
vm: VirtualMachine,
217292
}
218293

@@ -254,14 +329,14 @@ impl Interpreter {
254329
where
255330
F: FnOnce(&mut VirtualMachine),
256331
{
257-
let vm = initialize_main_vm(
332+
let (vm, global_state) = initialize_main_vm(
258333
settings,
259334
Context::genesis().clone(),
260335
Vec::new(), // No module_defs
261336
Vec::new(), // No init_hooks
262337
init,
263338
);
264-
Self { vm }
339+
Self { global_state, vm }
265340
}
266341

267342
/// Run a function with the main virtual machine and return a PyResult of the result.

crates/vm/src/vm/mod.rs

Lines changed: 4 additions & 54 deletions
Original file line numberDiff line numberDiff line change
@@ -144,7 +144,7 @@ pub fn process_hash_secret_seed() -> u32 {
144144

145145
impl VirtualMachine {
146146
/// Create a new `VirtualMachine` structure.
147-
fn new(config: PyConfig, ctx: PyRc<Context>) -> Self {
147+
pub(crate) fn new(ctx: PyRc<Context>, state: PyRc<PyGlobalState>) -> Self {
148148
flame_guard!("new VirtualMachine");
149149

150150
// make a new module without access to the vm; doesn't
@@ -169,27 +169,7 @@ impl VirtualMachine {
169169
const { RefCell::new([const { None }; signal::NSIG]) },
170170
));
171171

172-
let module_defs: std::collections::BTreeMap<&'static str, &'static builtins::PyModuleDef> =
173-
stdlib::builtin_module_defs(&ctx)
174-
.into_iter()
175-
.map(|def| (def.name.as_str(), def))
176-
.collect();
177-
178-
let seed = match config.settings.hash_seed {
179-
Some(seed) => seed,
180-
None => process_hash_secret_seed(),
181-
};
182-
let hash_secret = HashSecret::new(seed);
183-
184-
let codec_registry = CodecsRegistry::new(&ctx);
185-
186-
let warnings = WarningsState::init_state(&ctx);
187-
188-
let int_max_str_digits = AtomicCell::new(match config.settings.int_max_str_digits {
189-
-1 => 4300,
190-
other => other,
191-
} as usize);
192-
let mut vm = Self {
172+
let vm = Self {
193173
builtins,
194174
sys_module,
195175
ctx,
@@ -204,34 +184,7 @@ impl VirtualMachine {
204184
signal_handlers,
205185
signal_rx: None,
206186
repr_guards: RefCell::default(),
207-
state: PyRc::new(PyGlobalState {
208-
config,
209-
module_defs,
210-
frozen: HashMap::default(),
211-
stacksize: AtomicCell::new(0),
212-
thread_count: AtomicCell::new(0),
213-
hash_secret,
214-
atexit_funcs: PyMutex::default(),
215-
codec_registry,
216-
finalizing: AtomicBool::new(false),
217-
warnings,
218-
override_frozen_modules: AtomicCell::new(0),
219-
before_forkers: PyMutex::default(),
220-
after_forkers_child: PyMutex::default(),
221-
after_forkers_parent: PyMutex::default(),
222-
int_max_str_digits,
223-
switch_interval: AtomicCell::new(0.005),
224-
global_trace_func: PyMutex::default(),
225-
global_profile_func: PyMutex::default(),
226-
#[cfg(feature = "threading")]
227-
main_thread_ident: AtomicCell::new(0),
228-
#[cfg(feature = "threading")]
229-
thread_frames: parking_lot::Mutex::new(HashMap::new()),
230-
#[cfg(feature = "threading")]
231-
thread_handles: parking_lot::Mutex::new(Vec::new()),
232-
#[cfg(feature = "threading")]
233-
shutdown_handles: parking_lot::Mutex::new(Vec::new()),
234-
}),
187+
state,
235188
initialized: false,
236189
recursion_depth: Cell::new(0),
237190
c_stack_soft_limit: Cell::new(Self::calculate_c_stack_soft_limit()),
@@ -249,9 +202,6 @@ impl VirtualMachine {
249202
panic!("Interpreters in same process must share the hash seed");
250203
}
251204

252-
let frozen = core_frozen_inits().collect();
253-
PyRc::get_mut(&mut vm.state).unwrap().frozen = frozen;
254-
255205
vm.builtins.init_dict(
256206
vm.ctx.intern_str("builtins"),
257207
Some(vm.ctx.intern_str(stdlib::builtins::DOC.unwrap()).to_owned()),
@@ -1370,7 +1320,7 @@ pub fn resolve_frozen_alias(name: &str) -> &str {
13701320
}
13711321
}
13721322

1373-
fn core_frozen_inits() -> impl Iterator<Item = (&'static str, FrozenModule)> {
1323+
pub(crate) fn core_frozen_inits() -> impl Iterator<Item = (&'static str, FrozenModule)> {
13741324
let iter = core::iter::empty();
13751325
macro_rules! ext_modules {
13761326
($iter:ident, $($t:tt)*) => {

src/lib.rs

Lines changed: 9 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -7,15 +7,18 @@
77
//!
88
//! ```no_run
99
//! use rustpython::{InterpreterBuilder, InterpreterBuilderExt};
10-
//! use rustpython_vm::{pymodule, py_freeze};
10+
//! use rustpython_vm::{pymodule, py_freeze, VirtualMachine};
1111
//!
1212
//! fn main() -> std::process::ExitCode {
13-
//! let builder = InterpreterBuilder::new()
14-
//! .init_stdlib()
15-
//! .add_native_module_def("my_mod".to_owned(), my_mod::module_def)
16-
//! .init_hook(Box::new(|vm| {
13+
//! let builder = InterpreterBuilder::new().init_stdlib();
14+
//! // Add a native module using builder.ctx
15+
//! let my_mod_def = my_mod::module_def(&builder.ctx);
16+
//! let builder = builder
17+
//! .add_native_module(my_mod_def)
18+
//! .init_hook(|vm: &mut VirtualMachine| {
19+
//! // Add a frozen module
1720
//! vm.add_frozen(py_freeze!(source = "def foo(): pass", module_name = "other_thing"));
18-
//! }));
21+
//! });
1922
//!
2023
//! rustpython::run(builder)
2124
//! }

0 commit comments

Comments
 (0)