Skip to content

Commit eaae134

Browse files
authored
Merge pull request RustPython#3259 from Jack-R-lantern/__contains__
Add contains in dict_items
2 parents c83eb12 + a0a61a6 commit eaae134

File tree

3 files changed

+32
-2
lines changed

3 files changed

+32
-2
lines changed

Lib/test/test_dict.py

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1300,8 +1300,6 @@ def __eq__(self, other):
13001300
except RuntimeError: # implementation defined
13011301
pass
13021302

1303-
# TODO: RUSTPYTHON
1304-
@unittest.expectedFailure
13051303
def test_dictitems_contains_use_after_free(self):
13061304
class X:
13071305
def __eq__(self, other):

extra_tests/snippets/builtin_dict.py

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -26,3 +26,14 @@
2626
next(dict_reversed)
2727
assert 'dict' in dict().__doc__
2828

29+
d = {'a': 123, 'b': 456}
30+
assert 1 not in d.items()
31+
assert 'a' not in d.items()
32+
assert 'a', 123 not in d.items()
33+
assert () not in d.items()
34+
assert (1) not in d.items()
35+
assert ('a') not in d.items()
36+
assert ('a', 123) in d.items()
37+
assert ('b', 456) in d.items()
38+
assert ('a', 123, 3) not in d.items()
39+
assert ('a', 123, 'b', 456) not in d.items()

vm/src/builtins/dict.rs

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@ use super::{
33
PyTypeRef,
44
};
55
use crate::{
6+
builtins::PyTuple,
67
common::ascii,
78
dictdatatype::{self, DictKey},
89
function::{ArgIterable, FuncArgs, IntoPyObject, KwArgs, OptionalArg},
@@ -982,6 +983,26 @@ impl PyDictItems {
982983
let inner = zelf.difference(other, vm)?;
983984
Ok(PySet { inner })
984985
}
986+
987+
#[pymethod(magic)]
988+
fn contains(zelf: PyRef<Self>, needle: PyObjectRef, vm: &VirtualMachine) -> PyResult<bool> {
989+
let needle = match_class! {
990+
match needle {
991+
tuple @ PyTuple => tuple,
992+
_ => return Ok(false),
993+
}
994+
};
995+
if needle.len() != 2 {
996+
return Ok(false);
997+
}
998+
let key = needle.fast_getitem(0);
999+
if !zelf.dict().contains(key.clone(), vm)? {
1000+
return Ok(false);
1001+
}
1002+
let value = needle.fast_getitem(1);
1003+
let found = PyDict::getitem(zelf.dict().clone(), key, vm)?;
1004+
vm.identical_or_equal(&found, &value)
1005+
}
9851006
}
9861007

9871008
pub(crate) fn init(context: &PyContext) {

0 commit comments

Comments
 (0)