Skip to content

Commit 715dac9

Browse files
authored
Merge pull request #3898 from jopemachine/add-missing-method-mapping-proxy
Implement missing methods to `MappingProxy`
2 parents 3664986 + 6364ad4 commit 715dac9

File tree

4 files changed

+40
-23
lines changed

4 files changed

+40
-23
lines changed

Lib/test/test_dataclasses.py

-4
Original file line numberDiff line numberDiff line change
@@ -1769,8 +1769,6 @@ def from_file(cls, filename):
17691769

17701770
self.assertEqual(C.from_file('filename').x, 20)
17711771

1772-
# TODO: RUSTPYTHON
1773-
@unittest.expectedFailure
17741772
def test_field_metadata_default(self):
17751773
# Make sure the default metadata is read-only and of
17761774
# zero length.
@@ -1784,8 +1782,6 @@ class C:
17841782
'does not support item assignment'):
17851783
fields(C)[0].metadata['test'] = 3
17861784

1787-
# TODO: RUSTPYTHON
1788-
@unittest.expectedFailure
17891785
def test_field_metadata_mapping(self):
17901786
# Make sure only a mapping can be passed as metadata
17911787
# zero length.

Lib/test/test_enum.py

-8
Original file line numberDiff line numberDiff line change
@@ -1533,8 +1533,6 @@ class SomeTuple(tuple, Enum):
15331533
globals()['SomeTuple'] = SomeTuple
15341534
test_pickle_dump_load(self.assertIs, SomeTuple.first)
15351535

1536-
# TODO: RUSTPYTHON
1537-
@unittest.expectedFailure
15381536
def test_duplicate_values_give_unique_enum_items(self):
15391537
class AutoNumber(Enum):
15401538
first = ()
@@ -1555,8 +1553,6 @@ def __int__(self):
15551553
self.assertEqual(AutoNumber.third.value, 3)
15561554
self.assertIs(AutoNumber(1), AutoNumber.first)
15571555

1558-
# TODO: RUSTPYTHON
1559-
@unittest.expectedFailure
15601556
def test_inherited_new_from_enhanced_enum(self):
15611557
class AutoNumber(Enum):
15621558
def __new__(cls):
@@ -1573,8 +1569,6 @@ class Color(AutoNumber):
15731569
self.assertEqual(list(Color), [Color.red, Color.green, Color.blue])
15741570
self.assertEqual(list(map(int, Color)), [1, 2, 3])
15751571

1576-
# TODO: RUSTPYTHON
1577-
@unittest.expectedFailure
15781572
def test_inherited_new_from_mixed_enum(self):
15791573
class AutoNumber(IntEnum):
15801574
def __new__(cls):
@@ -1745,8 +1739,6 @@ def __new__(cls, value, period):
17451739
self.assertTrue(Period.month_1 is Period.day_30)
17461740
self.assertTrue(Period.week_4 is Period.day_28)
17471741

1748-
# TODO: RUSTPYTHON
1749-
@unittest.expectedFailure
17501742
def test_nonhash_value(self):
17511743
class AutoNumberInAList(Enum):
17521744
def __new__(cls):

Lib/test/test_types.py

-8
Original file line numberDiff line numberDiff line change
@@ -999,8 +999,6 @@ class userdict(dict):
999999
self.assertRaises(TypeError, self.mappingproxy, ("a", "tuple"))
10001000
self.assertRaises(TypeError, self.mappingproxy, ["a", "list"])
10011001

1002-
# TODO: RUSTPYTHON
1003-
@unittest.expectedFailure
10041002
def test_methods(self):
10051003
attrs = set(dir(self.mappingproxy({}))) - set(dir(object()))
10061004
self.assertEqual(attrs, {
@@ -1093,8 +1091,6 @@ def get(self, key, default=None):
10931091
self.assertEqual(view.keys(), 'keys')
10941092
self.assertEqual(view.values(), 'values')
10951093

1096-
# TODO: RUSTPYTHON
1097-
@unittest.expectedFailure
10981094
def test_chainmap(self):
10991095
d1 = {'x': 1}
11001096
d2 = {'y': 2}
@@ -1140,8 +1136,6 @@ def test_views(self):
11401136
self.assertEqual(list(values), ['value'])
11411137
self.assertEqual(list(items), [('key', 'value')])
11421138

1143-
# TODO: RUSTPYTHON
1144-
@unittest.expectedFailure
11451139
def test_len(self):
11461140
for expected in range(6):
11471141
data = dict.fromkeys('abcde'[:expected])
@@ -1159,8 +1153,6 @@ def test_iterators(self):
11591153
self.assertEqual(set(view.values()), set(values))
11601154
self.assertEqual(set(view.items()), set(items))
11611155

1162-
# TODO: RUSTPYTHON
1163-
@unittest.expectedFailure
11641156
def test_reversed(self):
11651157
d = {'a': 1, 'b': 2, 'foo': 0, 'c': 3, 'd': 4}
11661158
mp = self.mappingproxy(d)

vm/src/builtins/mappingproxy.rs

+40-3
Original file line numberDiff line numberDiff line change
@@ -3,8 +3,8 @@ use crate::{
33
class::PyClassImpl,
44
convert::ToPyObject,
55
function::{ArgMapping, OptionalArg},
6-
protocol::{PyMapping, PyMappingMethods, PySequence, PySequenceMethods},
7-
types::{AsMapping, AsSequence, Constructor, Iterable},
6+
protocol::{PyMapping, PyMappingMethods, PyNumberMethods, PySequence, PySequenceMethods},
7+
types::{AsMapping, AsNumber, AsSequence, Constructor, Iterable},
88
AsObject, Context, Py, PyObject, PyObjectRef, PyPayload, PyRef, PyResult, VirtualMachine,
99
};
1010

@@ -154,11 +154,40 @@ impl PyMappingProxy {
154154
fn class_getitem(cls: PyTypeRef, args: PyObjectRef, vm: &VirtualMachine) -> PyGenericAlias {
155155
PyGenericAlias::new(cls, args, vm)
156156
}
157+
158+
#[pymethod(magic)]
159+
fn len(&self, vm: &VirtualMachine) -> PyResult<usize> {
160+
let obj = self.to_object(vm)?;
161+
obj.length(vm)
162+
}
163+
164+
#[pymethod(magic)]
165+
fn reversed(&self, vm: &VirtualMachine) -> PyResult {
166+
vm.call_method(
167+
self.to_object(vm)?.as_object(),
168+
identifier!(vm, __reversed__).as_str(),
169+
(),
170+
)
171+
}
172+
173+
#[pymethod(magic)]
174+
fn ior(&self, _args: PyObjectRef, vm: &VirtualMachine) -> PyResult {
175+
Err(vm.new_type_error(format!(
176+
"\"'|=' is not supported by {}; use '|' instead\"",
177+
Self::class(vm)
178+
)))
179+
}
180+
181+
#[pymethod(name = "__ror__")]
182+
#[pymethod(magic)]
183+
fn or(&self, args: PyObjectRef, vm: &VirtualMachine) -> PyResult {
184+
vm._or(self.copy(vm)?.as_ref(), args.as_ref())
185+
}
157186
}
158187

159188
impl AsMapping for PyMappingProxy {
160189
const AS_MAPPING: PyMappingMethods = PyMappingMethods {
161-
length: None,
190+
length: Some(|mapping, vm| Self::mapping_downcast(mapping).len(vm)),
162191
subscript: Some(|mapping, needle, vm| {
163192
Self::mapping_downcast(mapping).getitem(needle.to_owned(), vm)
164193
}),
@@ -173,6 +202,14 @@ impl AsSequence for PyMappingProxy {
173202
};
174203
}
175204

205+
impl AsNumber for PyMappingProxy {
206+
const AS_NUMBER: PyNumberMethods = PyNumberMethods {
207+
or: Some(|num, args, vm| Self::number_downcast(num).or(args.to_pyobject(vm), vm)),
208+
inplace_or: Some(|num, args, vm| Self::number_downcast(num).ior(args.to_pyobject(vm), vm)),
209+
..PyNumberMethods::NOT_IMPLEMENTED
210+
};
211+
}
212+
176213
impl Iterable for PyMappingProxy {
177214
fn iter(zelf: PyRef<Self>, vm: &VirtualMachine) -> PyResult {
178215
let obj = zelf.to_object(vm)?;

0 commit comments

Comments
 (0)