Skip to content

Commit f2f8eca

Browse files
authored
Merge pull request RustPython#4559 from youknowone/importlib-requirements
Add (fake) frozenmodule __origname__ and _imp.find_frozen
2 parents 204643b + 10de265 commit f2f8eca

4 files changed

Lines changed: 75 additions & 10 deletions

File tree

.cspell.json

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -65,6 +65,7 @@
6565
"PYTHONWARNINGS",
6666
"basicsize",
6767
"itemsize",
68+
"origname",
6869
"getattro",
6970
"setattro",
7071
"iternext",

vm/build.rs

Lines changed: 7 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2,11 +2,16 @@ use itertools::Itertools;
22
use std::{env, io::prelude::*, path::PathBuf, process::Command};
33

44
fn main() {
5-
#[cfg(feature = "freeze-stdlib")]
6-
for entry in glob::glob("Lib/*/*.py").expect("Lib/ exists?").flatten() {
5+
let frozen_libs = if cfg!(feature = "freeze-stdlib") {
6+
"Lib/*/*.py"
7+
} else {
8+
"Lib/python_builtins/*.py"
9+
};
10+
for entry in glob::glob(frozen_libs).expect("Lib/ exists?").flatten() {
711
let display = entry.display();
812
println!("cargo:rerun-if-changed={display}");
913
}
14+
println!("cargo:rerun-if-changed=../Lib/importlib/_bootstrap.py");
1015

1116
println!("cargo:rustc-env=RUSTPYTHON_GIT_HASH={}", git_hash());
1217
println!(

vm/src/import.rs

Lines changed: 11 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -21,11 +21,11 @@ pub(crate) fn init_importlib_base(vm: &mut VirtualMachine) -> PyResult<PyObjectR
2121
import_builtin(vm, "_weakref")?;
2222

2323
let importlib = thread::enter_vm(vm, || {
24-
let importlib = import_frozen(vm, "_frozen_importlib")?;
25-
let impmod = import_builtin(vm, "_imp")?;
26-
let install = importlib.get_attr("_install", vm)?;
27-
vm.invoke(&install, (vm.sys_module.clone(), impmod))?;
28-
Ok(importlib)
24+
let bootstrap = import_frozen(vm, "_frozen_importlib")?;
25+
let install = bootstrap.get_attr("_install", vm)?;
26+
let imp = import_builtin(vm, "_imp")?;
27+
vm.invoke(&install, (vm.sys_module.clone(), imp))?;
28+
Ok(bootstrap)
2929
})?;
3030
vm.import_func = importlib.get_attr(identifier!(vm, __import__).to_owned(), vm)?;
3131
Ok(importlib)
@@ -81,7 +81,12 @@ pub fn make_frozen(vm: &VirtualMachine, name: &str) -> PyResult<PyRef<PyCode>> {
8181
}
8282

8383
pub fn import_frozen(vm: &VirtualMachine, module_name: &str) -> PyResult {
84-
make_frozen(vm, module_name).and_then(|frozen| import_codeobj(vm, module_name, frozen, false))
84+
make_frozen(vm, module_name).and_then(|frozen| {
85+
let module = import_codeobj(vm, module_name, frozen, false)?;
86+
// TODO: give a correct origname here
87+
module.set_attr("__origname__", vm.ctx.new_str(module_name.to_owned()), vm)?;
88+
Ok(module)
89+
})
8590
}
8691

8792
pub fn import_builtin(vm: &VirtualMachine, module_name: &str) -> PyResult {

vm/src/stdlib/imp.rs

Lines changed: 56 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
use crate::{PyObjectRef, VirtualMachine};
1+
use crate::{builtins::PyBaseExceptionRef, bytecode::FrozenModule, PyObjectRef, VirtualMachine};
22

33
pub fn make_module(vm: &VirtualMachine) -> PyObjectRef {
44
let module = _imp::make_module(vm);
@@ -48,10 +48,40 @@ mod lock {
4848
}
4949
}
5050

51+
#[allow(dead_code)]
52+
enum FrozenError {
53+
BadName, // The given module name wasn't valid.
54+
NotFound, // It wasn't in PyImport_FrozenModules.
55+
Disabled, // -X frozen_modules=off (and not essential)
56+
Excluded, // The PyImport_FrozenModules entry has NULL "code"
57+
// (module is present but marked as unimportable, stops search).
58+
Invalid, // The PyImport_FrozenModules entry is bogus
59+
// (eg. does not contain executable code).
60+
}
61+
62+
impl FrozenError {
63+
fn to_pyexception(&self, mod_name: &str, vm: &VirtualMachine) -> PyBaseExceptionRef {
64+
use FrozenError::*;
65+
let msg = match self {
66+
BadName | NotFound => format!("No such frozen object named {mod_name}"),
67+
Disabled => format!("Frozen modules are disabled and the frozen object named {mod_name} is not essential"),
68+
Excluded => format!("Excluded frozen object named {mod_name}"),
69+
Invalid => format!("Frozen object named {mod_name} is invalid"),
70+
};
71+
vm.new_import_error(msg, mod_name)
72+
}
73+
}
74+
75+
// find_frozen in frozen.c
76+
fn find_frozen<'a>(name: &str, vm: &'a VirtualMachine) -> Result<&'a FrozenModule, FrozenError> {
77+
vm.state.frozen.get(name).ok_or(FrozenError::NotFound)
78+
}
79+
5180
#[pymodule]
5281
mod _imp {
5382
use crate::{
54-
builtins::{PyBytesRef, PyCode, PyModule, PyStrRef},
83+
builtins::{PyBytesRef, PyCode, PyMemoryView, PyModule, PyStrRef},
84+
function::OptionalArg,
5585
import, PyObjectRef, PyRef, PyResult, TryFromObject, VirtualMachine,
5686
};
5787

@@ -126,6 +156,30 @@ mod _imp {
126156
// TODO:
127157
}
128158

159+
#[allow(clippy::type_complexity)]
160+
#[pyfunction]
161+
fn find_frozen(
162+
name: PyStrRef,
163+
withdata: OptionalArg<bool>,
164+
vm: &VirtualMachine,
165+
) -> PyResult<Option<(Option<PyRef<PyMemoryView>>, bool, PyStrRef)>> {
166+
use super::FrozenError::*;
167+
168+
if withdata.into_option().is_some() {
169+
// this is keyword-only argument in CPython
170+
unimplemented!();
171+
}
172+
173+
let info = match super::find_frozen(name.as_str(), vm) {
174+
Ok(info) => info,
175+
Err(NotFound | Disabled | BadName) => return Ok(None),
176+
Err(e) => return Err(e.to_pyexception(name.as_str(), vm)),
177+
};
178+
179+
let origname = name; // FIXME: origname != name
180+
Ok(Some((None, info.package, origname)))
181+
}
182+
129183
#[pyfunction]
130184
fn source_hash(key: u64, source: PyBytesRef) -> Vec<u8> {
131185
let hash: u64 = crate::common::hash::keyed_hash(key, source.as_bytes());

0 commit comments

Comments
 (0)