Skip to content

Commit db07880

Browse files
committed
warning module start
1 parent 4a0be5a commit db07880

File tree

3 files changed

+112
-23
lines changed

3 files changed

+112
-23
lines changed

vm/src/lib.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -74,6 +74,7 @@ pub mod types;
7474
pub mod utils;
7575
pub mod version;
7676
pub mod vm;
77+
pub mod warn;
7778

7879
pub use self::convert::{TryFromBorrowedObject, TryFromObject};
7980
pub use self::object::{

vm/src/stdlib/warnings.rs

Lines changed: 8 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -5,8 +5,7 @@ mod _warnings {
55
use crate::{
66
builtins::{PyStrRef, PyTypeRef},
77
function::OptionalArg,
8-
stdlib::sys::PyStderr,
9-
AsObject, PyResult, VirtualMachine,
8+
PyResult, VirtualMachine,
109
};
1110

1211
#[derive(FromArgs)]
@@ -21,27 +20,13 @@ mod _warnings {
2120

2221
#[pyfunction]
2322
fn warn(args: WarnArgs, vm: &VirtualMachine) -> PyResult<()> {
24-
// TODO: Implement correctly
2523
let level = args.stacklevel.unwrap_or(1);
26-
let category = if let OptionalArg::Present(category) = args.category {
27-
if !category.fast_issubclass(&vm.ctx.exceptions.warning) {
28-
return Err(vm.new_type_error(format!(
29-
"category must be a Warning subclass, not '{}'",
30-
category.class().name()
31-
)));
32-
}
33-
category
34-
} else {
35-
vm.ctx.exceptions.user_warning.clone()
36-
};
37-
let stderr = PyStderr(vm);
38-
writeln!(
39-
stderr,
40-
"level:{}: {}: {}",
41-
level,
42-
category.name(),
43-
args.message
44-
);
45-
Ok(())
24+
crate::warn::warn(
25+
args.message,
26+
args.category.into_option(),
27+
level as isize,
28+
None,
29+
vm,
30+
)
4631
}
4732
}

vm/src/warn.rs

Lines changed: 103 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,103 @@
1+
use crate::{
2+
builtins::{PyDict, PyStrRef, PyTypeRef},
3+
AsObject, PyObjectRef, PyResult, VirtualMachine,
4+
};
5+
6+
pub fn warn(
7+
message: PyStrRef,
8+
category: Option<PyTypeRef>,
9+
stack_level: isize,
10+
source: Option<PyObjectRef>,
11+
vm: &VirtualMachine,
12+
) -> PyResult<()> {
13+
let (filename, lineno, module, registry) = setup_context(stack_level, vm)?;
14+
warn_explicit(
15+
category, message, filename, lineno, module, registry, None, source, vm,
16+
)
17+
}
18+
19+
#[allow(clippy::too_many_arguments)]
20+
fn warn_explicit(
21+
category: Option<PyTypeRef>,
22+
message: PyStrRef,
23+
_filename: PyStrRef,
24+
_lineno: usize,
25+
_module: PyObjectRef,
26+
_registry: PyObjectRef,
27+
_source_line: Option<PyObjectRef>,
28+
_source: Option<PyObjectRef>,
29+
vm: &VirtualMachine,
30+
) -> PyResult<()> {
31+
// TODO: Implement correctly
32+
let category = if let Some(category) = category {
33+
if !category.fast_issubclass(&vm.ctx.exceptions.warning) {
34+
return Err(vm.new_type_error(format!(
35+
"category must be a Warning subclass, not '{}'",
36+
category.class().name()
37+
)));
38+
}
39+
category
40+
} else {
41+
vm.ctx.exceptions.user_warning.clone()
42+
};
43+
let stderr = crate::stdlib::sys::PyStderr(vm);
44+
writeln!(stderr, "{}: {}", category.name(), message.as_str(),);
45+
Ok(())
46+
}
47+
48+
// filename, module, and registry are new refs, globals is borrowed
49+
// Returns 0 on error (no new refs), 1 on success
50+
fn setup_context(
51+
_stack_level: isize,
52+
vm: &VirtualMachine,
53+
) -> PyResult<
54+
// filename, lineno, module, registry
55+
(PyStrRef, usize, PyObjectRef, PyObjectRef),
56+
> {
57+
let __warningregistry__ = "__warningregistry__";
58+
let __name__ = "__name__";
59+
60+
// Setup globals, filename and lineno.
61+
let frame = vm.current_frame();
62+
63+
// PyThreadState *tstate = _PyThreadState_GET();
64+
// PyFrameObject *f = PyThreadState_GetFrame(tstate);
65+
// // Stack level comparisons to Python code is off by one as there is no
66+
// // warnings-related stack level to avoid.
67+
// if (stack_level <= 0 || is_internal_frame(f)) {
68+
// while (--stack_level > 0 && f != NULL) {
69+
// PyFrameObject *back = PyFrame_GetBack(f);
70+
// Py_DECREF(f);
71+
// f = back;
72+
// }
73+
// }
74+
// else {
75+
// while (--stack_level > 0 && f != NULL) {
76+
// f = next_external_frame(f);
77+
// }
78+
// }
79+
80+
let (globals, filename, lineno) = if let Some(f) = frame {
81+
// TODO:
82+
let lineno = 1;
83+
// *lineno = PyFrame_GetLineNumber(f);
84+
// *filename = code->co_filename;
85+
(f.globals.clone(), f.code.source_path.clone(), lineno)
86+
} else {
87+
(vm.current_globals().clone(), vm.ctx.new_str("sys"), 1)
88+
};
89+
90+
let registry = if let Ok(registry) = globals.get_item(__warningregistry__, vm) {
91+
registry
92+
} else {
93+
let registry = PyDict::new_ref(&vm.ctx);
94+
globals.set_item(__warningregistry__, registry.clone().into(), vm)?;
95+
registry.into()
96+
};
97+
98+
// Setup module.
99+
let module = globals
100+
.get_item(__name__, vm)
101+
.unwrap_or_else(|_| vm.new_pyobj("<string>"));
102+
Ok((filename, lineno, module, registry))
103+
}

0 commit comments

Comments
 (0)