8000 Add sys._getframemodulename (#5873) · RustPython/RustPython@d5d3507 · GitHub
[go: up one dir, main page]

Skip to content

Commit d5d3507

Browse files
authored
Add sys._getframemodulename (#5873)
1 parent 3bde2dd commit d5d3507

File tree

6 files changed

+64
-1
lines changed

6 files changed

+64
-1
lines changed

.cspell.dict/python-more.txt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -78,6 +78,7 @@ getfilesystemencodeerrors
7878
getfilesystemencoding
7979
getformat
8080
getframe
81+
getframemodulename
8182
getnewargs
8283
getpip
8384
getrandom

extra_tests/snippets/stdlib_sys.py

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -147,3 +147,14 @@ def recursive_call(n):
147147
proc = subprocess.run(args, stdout=subprocess.PIPE, universal_newlines=True, env=env)
148148
assert proc.stdout.rstrip() == "True"
149149
assert proc.returncode == 0, proc
150+
151+
assert sys._getframemodulename() == "__main__", sys._getframemodulename()
152+
153+
154+
def test_getframemodulename():
155+
return sys._getframemodulename()
156+
157+
158+
test_getframemodulename.__module__ = "awesome_module"
159+
160+
assert test_getframemodulename() == "awesome_module"

vm/src/builtins/function.rs

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -315,7 +315,9 @@ impl PyFunction {
315315

316316
Ok(())
317317
}
318+
}
318319

320+
impl Py<PyFunction> {
319321
pub fn invoke_with_locals(
320322
&self,
321323
func_args: FuncArgs,
@@ -352,6 +354,7 @@ impl PyFunction {
352354
Scope::new(Some(locals), self.globals.clone()),
353355
vm.builtins.dict(),
354356
self.closure.as_ref().map_or(&[], |c| c.as_slice()),
357+
Some(self.to_owned().into()),
355358
vm,
356359
)
357360
.into_ref(&vm.ctx);

vm/src/frame.rs

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -97,6 +97,7 @@ type Lasti = std::cell::Cell<u32>;
9797
#[pyclass(module = false, name = "frame")]
9898
pub struct Frame {
9999
pub code: PyRef<PyCode>,
100+
pub func_obj: Option<PyObjectRef>,
100101

101102
pub fastlocals: PyMutex<Box<[Option<PyObjectRef>]>>,
102103
pub(crate) cells_frees: Box<[PyCellRef]>,
@@ -139,6 +140,7 @@ impl Frame {
139140
scope: Scope,
140141
builtins: PyDictRef,
141142
closure: &[PyCellRef],
143+
func_obj: Option<PyObjectRef>,
142144
vm: &VirtualMachine,
143145
) -> Frame {
144146
let cells_frees = std::iter::repeat_with(|| PyCell::default().into_ref(&vm.ctx))
@@ -160,6 +162,7 @@ impl Frame {
160162
globals: scope.globals,
161163
builtins,
162164
code,
165+
func_obj,
163166
lasti: Lasti::new(0),
164167
state: PyMutex::new(state),
165168
trace: PyMutex::new(vm.ctx.none()),

vm/src/stdlib/sys.rs

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -513,6 +513,32 @@ mod sys {
513513
Ok(frame.clone())
514514
}
515515

516+
#[pyfunction]
517+
fn _getframemodulename(depth: OptionalArg<usize>, vm: &VirtualMachine) -> PyResult {
518+
let depth = depth.into_option().unwrap_or(0);
519+
520+
// Get the frame at the specified depth
521+
if depth > vm.frames.borrow().len() - 1 {
522+
return Ok(vm.ctx.none());
523+
}
524+
525+
let idx = vm.frames.borrow().len() - depth - 1;
526+
let frame = &vm.frames.borrow()[idx];
527+
528+
// If the frame has a function object, return its __module__ attribute
529+
if let Some(func_obj) = &frame.func_obj {
530+
match func_obj.get_attr(identifier!(vm, __module__), vm) {
531+
Ok(module) => Ok(module),
532+
Err(_) => {
533+
// CPython clears the error and returns None
534+
Ok(vm.ctx.none())
535+
}
536+
}
537+
} else {
538+
Ok(vm.ctx.none())
539+
}
540+
}
541+
516542
#[pyfunction]
517543
fn gettrace(vm: &VirtualMachine) -> PyObjectRef {
518544
vm.trace_func.borrow().clone()

vm/src/vm/mod.rs

Lines changed: 20 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -449,7 +449,26 @@ impl VirtualMachine {
449449
}
450450

451451
pub fn run_code_obj(&self, code: PyRef<PyCode>, scope: Scope) -> PyResult {
452-
let frame = Frame::new(code, scope, self.builtins.dict(), &[], self).into_ref(&self.ctx);
452+
use crate::builtins::PyFunction;
453+
454+
// Create a function object for module code, similar to CPython's PyEval_EvalCode
455+
let qualname = self.ctx.new_str(code.obj_name.as_str());
456+
let func = PyFunction::new(
457+
code.clone(),
458+
scope.globals.clone(),
459+
None, // closure
460+
None, // defaults
461+
None, // kwdefaults
462+
qualname,
463+
self.ctx.new_tuple(vec![]), // type_params
464+
self.ctx.new_dict(), // annotations
465+
self.ctx.none(), // doc
466+
self,
467+
)?;
468+
let func_obj = func.into_ref(&self.ctx).into();
469+
470+
let frame = Frame::new(code, scope, self.builtins.dict(), &[], Some(func_obj), self)
471+
.into_ref(&self.ctx);
453472
self.run_frame(frame)
454473
}
455474

0 commit comments

Comments
 (0)
0