mirror of
https://github.com/RustPython/RustPython.git
synced 2026-10-28 10:44:36 +08:00
Accept dict subclasses as warning module globals (#9062)
Preserve overridable loader lookup while reading module names from stored dictionary data. Assisted-by: OpenAI Codex:model identifier unavailable
This commit is contained in:
1 parent
c3e1276229
commit
140761e80b
3 files changed
+50
-3
No files matched your search
@@ -21,7 +21,7 @@ pub fn warn(
|
||||
mod _warnings {
|
||||
use crate::{
|
||||
AsObject, PyObject, PyObjectRef, PyResult, VirtualMachine,
|
||||
builtins::{PyDictRef, PyListRef, PyStrRef, PyTupleRef, PyTypeRef},
|
||||
builtins::{PyDict, PyDictRef, PyListRef, PyStrRef, PyTupleRef, PyTypeRef},
|
||||
convert::TryFromObject,
|
||||
function::OptionalArg,
|
||||
};
|
||||
@@ -180,7 +180,7 @@ mod _warnings {
|
||||
let source_line = if let Some(mg) = args.module_globals.into_option() {
|
||||
if vm.is_none(&mg) {
|
||||
None
|
||||
} else if !mg.class().is(vm.ctx.types.dict_type) {
|
||||
} else if mg.downcast_ref::<PyDict>().is_none() {
|
||||
return Err(vm.new_type_error(format!(
|
||||
"module_globals must be a dict, not '{}'",
|
||||
mg.class().name()
|
||||
|
||||
@@ -201,7 +201,7 @@ pub(crate) fn get_source_line(
|
||||
};
|
||||
|
||||
let module_name = if let Some(dict) = module_globals.downcast_ref::<PyDict>() {
|
||||
match dict.get_item_opt(identifier!(vm, __name__), vm)? {
|
||||
match dict.inner_getitem_opt(identifier!(vm, __name__), vm)? {
|
||||
Some(name) => name,
|
||||
None => return Ok(None),
|
||||
}
|
||||
|
||||
@@ -18,3 +18,50 @@ for category in (None, DeprecationWarning, int, 42):
|
||||
assert len(caught) == 1
|
||||
assert caught[0].message is message
|
||||
assert caught[0].category is CustomWarning
|
||||
|
||||
|
||||
from importlib.machinery import ModuleSpec
|
||||
|
||||
events = []
|
||||
|
||||
|
||||
class WarningLoader:
|
||||
def get_source(self, name):
|
||||
events.append(("source", name))
|
||||
return "source line\n"
|
||||
|
||||
|
||||
class WarningGlobals(dict):
|
||||
def get(self, key, default=None):
|
||||
events.append(("get", key))
|
||||
return super().get(key, default)
|
||||
|
||||
def __getitem__(self, key):
|
||||
raise AssertionError("module name must use stored dict lookup")
|
||||
|
||||
__missing__ = __getitem__
|
||||
|
||||
|
||||
loader = WarningLoader()
|
||||
module_globals = WarningGlobals(
|
||||
__name__="stored_name",
|
||||
__loader__=loader,
|
||||
__spec__=ModuleSpec("stored_name", loader),
|
||||
)
|
||||
for has_name in (True, False):
|
||||
events.clear()
|
||||
with warnings.catch_warnings(record=True) as caught:
|
||||
warnings.simplefilter("always")
|
||||
warnings.warn_explicit(
|
||||
"subclass globals",
|
||||
UserWarning,
|
||||
"fixed_ascii.py",
|
||||
1,
|
||||
module_globals=module_globals,
|
||||
)
|
||||
assert len(caught) == 1
|
||||
expected = [("get", "__loader__"), ("get", "__spec__")]
|
||||
if has_name:
|
||||
expected.append(("source", "stored_name"))
|
||||
del module_globals["__name__"]
|
||||
assert events == expected
|
||||
Reference in new issue
Block a user