mirror of
https://github.com/RustPython/RustPython.git
synced 2026-10-28 10:44:36 +08:00
Fix DictUpdate validation
This commit is contained in:
1 parent
9467632e1b
commit
3f1d39e5db
2 files changed
+63
No files matched your search
@@ -358,3 +358,53 @@ next(it)
|
||||
assert it.__length_hint__() == 0
|
||||
assert_raises(StopIteration, next, it)
|
||||
assert it.__length_hint__() == 0
|
||||
|
||||
# Test dictionary unpacking with non-mapping objects
|
||||
# This should raise TypeError for non-mapping objects
|
||||
with assert_raises(TypeError) as cm:
|
||||
{**[1, 2]}
|
||||
assert "'list' object is not a mapping" in str(cm.exception)
|
||||
|
||||
with assert_raises(TypeError) as cm:
|
||||
{**[[1, 2], [3, 4]]}
|
||||
assert "'list' object is not a mapping" in str(cm.exception)
|
||||
|
||||
with assert_raises(TypeError) as cm:
|
||||
{**"string"}
|
||||
assert "'str' object is not a mapping" in str(cm.exception)
|
||||
|
||||
with assert_raises(TypeError) as cm:
|
||||
{**(1, 2, 3)}
|
||||
assert "'tuple' object is not a mapping" in str(cm.exception)
|
||||
|
||||
# Test that valid mappings still work
|
||||
assert {**{"a": 1}, **{"b": 2}} == {"a": 1, "b": 2}
|
||||
|
||||
# Test OrderedDict unpacking preserves order
|
||||
import collections
|
||||
|
||||
od = collections.OrderedDict([("a", 1), ("b", 2)])
|
||||
od.move_to_end("a") # Move 'a' to end: ['b', 'a']
|
||||
expected_order = list(od.items()) # [('b', 2), ('a', 1)]
|
||||
|
||||
|
||||
def test_func(**kwargs):
|
||||
return kwargs
|
||||
|
||||
|
||||
result = test_func(**od)
|
||||
assert list(result.items()) == expected_order, (
|
||||
f"Expected {expected_order}, got {list(result.items())}"
|
||||
)
|
||||
|
||||
# Test multiple OrderedDict unpacking
|
||||
od1 = collections.OrderedDict([("x", 10), ("y", 20)])
|
||||
od2 = collections.OrderedDict([("z", 30), ("w", 40)])
|
||||
od2.move_to_end("z") # Move 'z' to end: ['w', 'z']
|
||||
|
||||
result = test_func(**od1, **od2)
|
||||
# Should preserve order: x, y, w, z
|
||||
expected_keys = ["x", "y", "w", "z"]
|
||||
assert list(result.keys()) == expected_keys, (
|
||||
f"Expected {expected_keys}, got {list(result.keys())}"
|
||||
)
|
||||
@@ -796,6 +796,19 @@ impl ExecutingFrame<'_> {
|
||||
.top_value()
|
||||
.downcast_ref::<PyDict>()
|
||||
.expect("exact dict expected");
|
||||
|
||||
// For dictionary unpacking {**x}, x must be a mapping
|
||||
// Check if the object has the mapping protocol (keys method)
|
||||
if vm
|
||||
.get_method(other.clone(), vm.ctx.intern_str("keys"))
|
||||
.is_none()
|
||||
{
|
||||
return Err(vm.new_type_error(format!(
|
||||
"'{}' object is not a mapping",
|
||||
other.class().name()
|
||||
)));
|
||||
}
|
||||
|
||||
dict.merge_object(other, vm)?;
|
||||
Ok(None)
|
||||
}
|
||||
|
||||
Reference in new issue
Block a user