mirror of
https://github.com/RustPython/RustPython.git
synced 2026-10-28 18:59:04 +08:00
Honor Python 3.15 frozen-module startup configuration (#9202)
* Honor frozen module startup selection Assisted-by: OpenAI Codex:model version unavailable * Match frozen option configuration diagnostics Assisted-by: OpenAI Codex:model version unavailable * Preserve frozen option initialization precedence Validate the first occurrence, then apply the final value as CPython does after getpath configuration normalization. Assisted-by: OpenAI Codex:model version unavailable
This commit is contained in:
1 parent
dfa3a1ae66
commit
c4681299c2
6 files changed
+57
-6
No files matched your search
@@ -180,10 +180,14 @@ fn find_frozen(name: &str, vm: &VirtualMachine) -> Result<FrozenModule, FrozenEr
|
||||
return Ok(frozen);
|
||||
}
|
||||
|
||||
// use_frozen(): override > 0 → true, override < 0 → false, 0 → default (true)
|
||||
// use_frozen(): override > 0 → true, override < 0 → false, 0 → startup setting
|
||||
// When disabled, non-bootstrap modules are simply not found (same as look_up_frozen)
|
||||
let override_val = vm.state.override_frozen_modules.load();
|
||||
if override_val < 0 {
|
||||
if override_val < 0
|
||||
|| (override_val == 0
|
||||
&& vm.import_bootstrap_complete
|
||||
&& !vm.state.config.settings.use_frozen_modules)
|
||||
{
|
||||
return Err(FrozenError::NotFound);
|
||||
}
|
||||
|
||||
|
||||
@@ -110,6 +110,7 @@ pub struct VirtualMachine {
|
||||
pub(crate) lazy_imports_resolving: RefCell<HashSet<usize>>,
|
||||
pub state: PyRc<PyGlobalState>,
|
||||
pub initialized: bool,
|
||||
pub(crate) import_bootstrap_complete: bool,
|
||||
recursion_depth: Cell<usize>,
|
||||
/// Depth of native recursion that pushes no Python frame, counted only
|
||||
/// where the stack pointer cannot be read. Everywhere else the native
|
||||
@@ -1370,6 +1371,7 @@ impl VirtualMachine {
|
||||
lazy_imports_resolving: RefCell::default(),
|
||||
state,
|
||||
initialized: false,
|
||||
import_bootstrap_complete: false,
|
||||
recursion_depth: Cell::new(0),
|
||||
#[cfg(any(miri, target_env = "musl"))]
|
||||
native_recursion_depth: Cell::new(0),
|
||||
@@ -1450,7 +1452,7 @@ impl VirtualMachine {
|
||||
// Use dotted names when freeze-stdlib is enabled (modules come from Lib/encodings/),
|
||||
// otherwise use underscored names (modules come from core_modules/).
|
||||
let (ascii_module_name, utf8_module_name, latin1_module_name) =
|
||||
if cfg!(feature = "freeze-stdlib") {
|
||||
if cfg!(feature = "freeze-stdlib") && self.state.config.settings.use_frozen_modules {
|
||||
("encodings.ascii", "encodings.utf_8", "encodings.latin_1")
|
||||
} else {
|
||||
("encodings_ascii", "encodings_utf_8", "encodings_latin_1")
|
||||
@@ -1644,6 +1646,7 @@ impl VirtualMachine {
|
||||
|
||||
let res = essential_init();
|
||||
let importlib = self.expect_pyresult(res, "essential initialization failed");
|
||||
self.import_bootstrap_complete = true;
|
||||
|
||||
#[cfg(feature = "host_env")]
|
||||
if self.state.config.settings.allow_external_library
|
||||
|
||||
@@ -139,7 +139,8 @@ pub struct Settings {
|
||||
/// --check-hash-based-pycs
|
||||
pub check_hash_pycs_mode: CheckHashPycsMode,
|
||||
|
||||
// int use_frozen_modules;
|
||||
/// -X frozen_modules=on|off (bootstrap modules remain available).
|
||||
pub use_frozen_modules: bool,
|
||||
/// -P
|
||||
pub safe_path: bool,
|
||||
|
||||
@@ -204,6 +205,7 @@ impl Default for Settings {
|
||||
install_signal_handlers: true,
|
||||
user_site_directory: true,
|
||||
import_site: true,
|
||||
use_frozen_modules: true,
|
||||
ignore_environment: false,
|
||||
verbose: 0,
|
||||
quiet: false,
|
||||
|
||||
@@ -1480,6 +1480,7 @@ impl VirtualMachine {
|
||||
lazy_imports_resolving: RefCell::default(),
|
||||
state: self.state.clone(),
|
||||
initialized: self.initialized,
|
||||
import_bootstrap_complete: self.import_bootstrap_complete,
|
||||
recursion_depth: Cell::new(0),
|
||||
#[cfg(any(miri, target_env = "musl"))]
|
||||
native_recursion_depth: Cell::new(0),
|
||||
|
||||
+7
-2
@@ -55,6 +55,11 @@ fn install_default_tls_provider(_vm: &mut crate::VirtualMachine) {
|
||||
fn set_frozen_stdlib_dir(vm: &mut crate::VirtualMachine) {
|
||||
use rustpython_vm::common::rc::PyRc;
|
||||
|
||||
if !vm.state.config.settings.use_frozen_modules {
|
||||
setup_dynamic_stdlib(vm);
|
||||
return;
|
||||
}
|
||||
|
||||
if use_build_stdlib(vm) {
|
||||
let state = PyRc::get_mut(&mut vm.state).unwrap();
|
||||
state.config.paths.stdlib_dir =
|
||||
@@ -63,7 +68,7 @@ fn set_frozen_stdlib_dir(vm: &mut crate::VirtualMachine) {
|
||||
}
|
||||
|
||||
/// Setup dynamic standard library loading from filesystem
|
||||
#[cfg(all(feature = "stdlib", not(feature = "freeze-stdlib")))]
|
||||
#[cfg(feature = "stdlib")]
|
||||
fn setup_dynamic_stdlib(vm: &mut crate::VirtualMachine) {
|
||||
use rustpython_vm::common::rc::PyRc;
|
||||
|
||||
@@ -117,7 +122,7 @@ fn canonical_stdlib_path(path: String) -> String {
|
||||
}
|
||||
|
||||
/// Collect standard library paths from build-time configuration
|
||||
#[cfg(all(feature = "stdlib", not(feature = "freeze-stdlib")))]
|
||||
#[cfg(feature = "stdlib")]
|
||||
fn collect_stdlib_paths() -> Vec<String> {
|
||||
// BUILDTIME_RUSTPYTHONPATH should be set when distributing
|
||||
if let Some(paths) = option_env!("BUILDTIME_RUSTPYTHONPATH") {
|
||||
|
||||
@@ -313,9 +313,15 @@ pub fn parse_opts() -> Result<(Settings, RunMode), lexopt::Error> {
|
||||
settings.import_time = parse_import_time(value.to_str(), "PYTHONPROFILEIMPORTTIME");
|
||||
}
|
||||
|
||||
if let Some(value) = get_env("PYTHON_FROZEN_MODULES").filter(|value| !value.is_empty()) {
|
||||
settings.use_frozen_modules =
|
||||
parse_frozen_modules(Some(&value.to_string_lossy()), "PYTHON_FROZEN_MODULES");
|
||||
}
|
||||
|
||||
// CPython uses the first occurrence of these -X options.
|
||||
let mut lazy_imports_option_seen = false;
|
||||
let mut import_time_option_seen = false;
|
||||
let mut frozen_modules_option_seen = false;
|
||||
let xopts = args.implementation_option.into_iter().map(|s| {
|
||||
let (name, value) = match s.split_once('=') {
|
||||
Some((name, value)) => (name.to_owned(), Some(value)),
|
||||
@@ -327,6 +333,11 @@ pub fn parse_opts() -> Result<(Settings, RunMode), lexopt::Error> {
|
||||
settings.import_time = parse_import_time(value, "-X importtime");
|
||||
import_time_option_seen = true;
|
||||
}
|
||||
"frozen_modules" if !frozen_modules_option_seen => {
|
||||
settings.use_frozen_modules =
|
||||
parse_frozen_modules(value, "option -X frozen_modules");
|
||||
frozen_modules_option_seen = true;
|
||||
}
|
||||
"faulthandler" => settings.faulthandler = true,
|
||||
"warn_default_encoding" => settings.warn_default_encoding = true,
|
||||
"utf8" => {
|
||||
@@ -398,6 +409,18 @@ pub fn parse_opts() -> Result<(Settings, RunMode), lexopt::Error> {
|
||||
});
|
||||
settings.xoptions.extend(xopts);
|
||||
|
||||
// CPython validates the first frozen_modules option before initialization,
|
||||
// then getpath's config dictionary round-trip keeps the last occurrence.
|
||||
if let Some((_, value)) = settings
|
||||
.xoptions
|
||||
.iter()
|
||||
.rev()
|
||||
.find(|(name, _)| name == "frozen_modules")
|
||||
{
|
||||
settings.use_frozen_modules =
|
||||
parse_frozen_modules(value.as_deref(), "option -X frozen_modules");
|
||||
}
|
||||
|
||||
// Resolve utf8_mode if not explicitly set by PYTHONUTF8 or -X utf8.
|
||||
// Default to UTF-8 mode since RustPython's locale encoding detection
|
||||
// is incomplete. Users can set PYTHONUTF8=0 or -X utf8=0 to disable.
|
||||
@@ -513,6 +536,19 @@ fn parse_cpu_count(value: Option<&str>) -> Result<Option<NonZeroI32>, ()> {
|
||||
}
|
||||
}
|
||||
|
||||
fn parse_frozen_modules(value: Option<&str>, source: &str) -> bool {
|
||||
match value {
|
||||
None | Some("" | "on") => true,
|
||||
Some("off") => false,
|
||||
_ => {
|
||||
eprintln!(
|
||||
"Fatal Python error: config_init_import: bad value for {source} (expected \"on\" or \"off\")"
|
||||
);
|
||||
std::process::exit(1);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// = config_init_import_time
|
||||
fn parse_import_time(value: Option<&str>, source: &str) -> u8 {
|
||||
let value = value
|
||||
|
||||
Reference in new issue
Block a user