Skip to content

Implement missing methods to MappingProxy #3898

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 0 additions & 4 deletions Lib/test/test_dataclasses.py
Original file line number Diff line number Diff line change
Expand Up @@ -1769,8 +1769,6 @@ def from_file(cls, filename):

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

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

# TODO: RUSTPYTHON
@unittest.expectedFailure
def test_field_metadata_mapping(self):
# Make sure only a mapping can be passed as metadata
# zero length.
Expand Down
8 changes: 0 additions & 8 deletions Lib/test/test_enum.py
Original file line number Diff line number Diff line change
Expand Up @@ -1533,8 +1533,6 @@ class SomeTuple(tuple, Enum):
globals()['SomeTuple'] = SomeTuple
test_pickle_dump_load(self.assertIs, SomeTuple.first)

# TODO: RUSTPYTHON
@unittest.expectedFailure
def test_duplicate_values_give_unique_enum_items(self):
class AutoNumber(Enum):
first = ()
Expand All @@ -1555,8 +1553,6 @@ def __int__(self):
self.assertEqual(AutoNumber.third.value, 3)
self.assertIs(AutoNumber(1), AutoNumber.first)

# TODO: RUSTPYTHON
@unittest.expectedFailure
def test_inherited_new_from_enhanced_enum(self):
class AutoNumber(Enum):
def __new__(cls):
Expand All @@ -1573,8 +1569,6 @@ class Color(AutoNumber):
self.assertEqual(list(Color), [Color.red, Color.green, Color.blue])
self.assertEqual(list(map(int, Color)), [1, 2, 3])

# TODO: RUSTPYTHON
@unittest.expectedFailure
def test_inherited_new_from_mixed_enum(self):
class AutoNumber(IntEnum):
def __new__(cls):
Expand Down Expand Up @@ -1745,8 +1739,6 @@ def __new__(cls, value, period):
self.assertTrue(Period.month_1 is Period.day_30)
self.assertTrue(Period.week_4 is Period.day_28)

# TODO: RUSTPYTHON
@unittest.expectedFailure
def test_nonhash_value(self):
class AutoNumberInAList(Enum):
def __new__(cls):
Expand Down
8 changes: 0 additions & 8 deletions Lib/test/test_types.py
Original file line number Diff line number Diff line change
Expand Up @@ -999,8 +999,6 @@ class userdict(dict):
self.assertRaises(TypeError, self.mappingproxy, ("a", "tuple"))
self.assertRaises(TypeError, self.mappingproxy, ["a", "list"])

# TODO: RUSTPYTHON
@unittest.expectedFailure
def test_methods(self):
attrs = set(dir(self.mappingproxy({}))) - set(dir(object()))
self.assertEqual(attrs, {
Expand Down Expand Up @@ -1095,8 +1093,6 @@ def get(self, key, default=None):
self.assertEqual(view.keys(), 'keys')
self.assertEqual(view.values(), 'values')

# TODO: RUSTPYTHON
@unittest.expectedFailure
def test_chainmap(self):
d1 = {'x': 1}
d2 = {'y': 2}
Expand Down Expand Up @@ -1142,8 +1138,6 @@ def test_views(self):
self.assertEqual(list(values), ['value'])
self.assertEqual(list(items), [('key', 'value')])

# TODO: RUSTPYTHON
@unittest.expectedFailure
def test_len(self):
for expected in range(6):
data = dict.fromkeys('abcde'[:expected])
Expand All @@ -1161,8 +1155,6 @@ def test_iterators(self):
self.assertEqual(set(view.values()), set(values))
self.assertEqual(set(view.items()), set(items))

# TODO: RUSTPYTHON
@unittest.expectedFailure
def test_reversed(self):
d = {'a': 1, 'b': 2, 'foo': 0, 'c': 3, 'd': 4}
mp = self.mappingproxy(d)
Expand Down
43 changes: 40 additions & 3 deletions vm/src/builtins/mappingproxy.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,8 +3,8 @@ use crate::{
class::PyClassImpl,
convert::ToPyObject,
function::{ArgMapping, OptionalArg},
protocol::{PyMapping, PyMappingMethods, PySequence, PySequenceMethods},
types::{AsMapping, AsSequence, Constructor, Iterable},
protocol::{PyMapping, PyMappingMethods, PyNumberMethods, PySequence, PySequenceMethods},
types::{AsMapping, AsNumber, AsSequence, Constructor, Iterable},
AsObject, Context, Py, PyObject, PyObjectRef, PyPayload, PyRef, PyResult, VirtualMachine,
};

Expand Down Expand Up @@ -143,11 +143,40 @@ impl PyMappingProxy {
fn class_getitem(cls: PyTypeRef, args: PyObjectRef, vm: &VirtualMachine) -> PyGenericAlias {
PyGenericAlias::new(cls, args, vm)
}

#[pymethod(magic)]
fn len(&self, vm: &VirtualMachine) -> PyResult<usize> {
let obj = self.to_object(vm)?;
obj.length(vm)
}

#[pymethod(magic)]
fn reversed(&self, vm: &VirtualMachine) -> PyResult {
vm.call_method(
self.to_object(vm)?.as_object(),
identifier!(vm, __reversed__).as_str(),
(),
)
}

#[pymethod(magic)]
fn ior(&self, _args: PyObjectRef, vm: &VirtualMachine) -> PyResult {
Err(vm.new_type_error(format!(
"\"'|=' is not supported by {}; use '|' instead\"",
Self::class(vm)
)))
}

#[pymethod(name = "__ror__")]
#[pymethod(magic)]
fn or(&self, args: PyObjectRef, vm: &VirtualMachine) -> PyResult {
vm._or(self.copy(vm)?.as_ref(), args.as_ref())
}
}

impl AsMapping for PyMappingProxy {
const AS_MAPPING: PyMappingMethods = PyMappingMethods {
length: None,
length: Some(|mapping, vm| Self::mapping_downcast(mapping).len(vm)),
subscript: Some(|mapping, needle, vm| {
Self::mapping_downcast(mapping).getitem(needle.to_owned(), vm)
}),
Expand All @@ -162,6 +191,14 @@ impl AsSequence for PyMappingProxy {
};
}

impl AsNumber for PyMappingProxy {
const AS_NUMBER: PyNumberMethods = PyNumberMethods {
or: Some(|num, args, vm| Self::number_downcast(num).or(args.to_pyobject(vm), vm)),
inplace_or: Some(|num, args, vm| Self::number_downcast(num).ior(args.to_pyobject(vm), vm)),
..PyNumberMethods::NOT_IMPLEMENTED
};
}

impl Iterable for PyMappingProxy {
fn iter(zelf: PyRef<Self>, vm: &VirtualMachine) -> PyResult {
let obj = zelf.to_object(vm)?;
Expand Down