fix item protocol use sequence protocol

This commit is contained in:
Kangzhi Shi authored and Jeong YunWon committed 2022-03-12 16:12:12 +09:00
1 parent 0abe90dd0a
commit c6ee563088
4 files changed
+81 -50

No files matched your search

+1 -6
View File
@@ -380,12 +380,7 @@ impl PyRange {
impl PyRange {
fn protocol_length(&self, vm: &VirtualMachine) -> PyResult<usize> {
self.len()
.to_isize()
.ok_or_else(|| {
vm.new_overflow_error("RustPython int too large to convert to C ssize_t".to_owned())
})
.map(|x| x as usize)
PyInt::from(self.len()).try_to_primitive(vm)
}
const MAPPING_METHODS: PyMappingMethods = PyMappingMethods {
+33
View File
@@ -684,6 +684,7 @@ pub trait DictKey {
fn key_hash(&self, vm: &VirtualMachine) -> PyResult<HashValue>;
fn key_is(&self, other: &PyObject) -> bool;
fn key_eq(&self, vm: &VirtualMachine, other_key: &PyObject) -> PyResult<bool>;
fn key_as_isize(&self, vm: &VirtualMachine) -> PyResult<isize>;
}
/// Implement trait for PyObjectRef such that we can use python objects
@@ -701,6 +702,10 @@ impl DictKey for PyObjectRef {
fn key_eq(&self, vm: &VirtualMachine, other_key: &PyObject) -> PyResult<bool> {
(**self).key_eq(vm, other_key)
}
#[inline]
fn key_as_isize(&self, vm: &VirtualMachine) -> PyResult<isize> {
(**self).key_as_isize(vm)
}
}
impl DictKey for &PyObject {
@@ -716,7 +721,12 @@ impl DictKey for &PyObject {
fn key_eq(&self, vm: &VirtualMachine, other_key: &PyObject) -> PyResult<bool> {
(**self).key_eq(vm, other_key)
}
#[inline]
fn key_as_isize(&self, vm: &VirtualMachine) -> PyResult<isize> {
(**self).key_as_isize(vm)
}
}
impl DictKey for PyObject {
fn key_hash(&self, vm: &VirtualMachine) -> PyResult<HashValue> {
self.hash(vm)
@@ -729,6 +739,10 @@ impl DictKey for PyObject {
fn key_eq(&self, vm: &VirtualMachine, other_key: &PyObject) -> PyResult<bool> {
vm.identical_or_equal(self, other_key)
}
fn key_as_isize(&self, vm: &VirtualMachine) -> PyResult<isize> {
vm.to_index(self)?.try_to_primitive(vm)
}
}
impl DictKey for PyStrRef {
@@ -749,6 +763,10 @@ impl DictKey for PyStrRef {
vm.bool_eq(self.as_object(), other_key)
}
}
fn key_as_isize(&self, vm: &VirtualMachine) -> PyResult<isize> {
self.as_object().key_as_isize(vm)
}
}
impl DictKey for PyRefExact<PyStr> {
@@ -761,6 +779,9 @@ impl DictKey for PyRefExact<PyStr> {
fn key_eq(&self, vm: &VirtualMachine, other_key: &PyObject) -> PyResult<bool> {
(**self).key_eq(vm, other_key)
}
fn key_as_isize(&self, vm: &VirtualMachine) -> PyResult<isize> {
(**self).key_as_isize(vm)
}
}
// AsRef<str> fit this case but not possible in rust 1.46
@@ -788,6 +809,10 @@ impl DictKey for &str {
s.key_eq(vm, other_key)
}
}
fn key_as_isize(&self, vm: &VirtualMachine) -> PyResult<isize> {
Err(vm.new_type_error("'str' object cannot be interpreted as an integer".to_owned()))
}
}
impl DictKey for String {
@@ -802,6 +827,10 @@ impl DictKey for String {
fn key_eq(&self, vm: &VirtualMachine, other_key: &PyObject) -> PyResult<bool> {
self.as_str().key_eq(vm, other_key)
}
fn key_as_isize(&self, vm: &VirtualMachine) -> PyResult<isize> {
self.as_str().key_as_isize(vm)
}
}
impl DictKey for usize {
@@ -825,6 +854,10 @@ impl DictKey for usize {
vm.bool_eq(&int.into_object(), other_key)
}
}
fn key_as_isize(&self, _vm: &VirtualMachine) -> PyResult<isize> {
Ok(*self as isize)
}
}
fn str_exact<'a>(obj: &'a PyObject, vm: &VirtualMachine) -> Option<&'a PyStr> {
+28 -41
View File
@@ -81,11 +81,6 @@ impl PyObjectRef {
Ok(vm.length_hint_opt(self)?.unwrap_or(defaultvalue))
}
// item protocol
// PyObject *PyObject_GetItem(PyObject *o, PyObject *key)
// int PyObject_SetItem(PyObject *o, PyObject *key, PyObject *v)
// int PyObject_DelItem(PyObject *o, PyObject *key)
// PyObject *PyObject_Dir(PyObject *o)
/// Takes an object and returns an iterator for it.
@@ -431,23 +426,19 @@ impl PyObject {
if let Ok(mapping) = PyMapping::try_protocol(self, vm) {
mapping.subscript(&needle, vm)
} else if let Ok(seq) = PySequence::try_protocol(self, vm) {
let i = needle.key_as_isize(vm)?;
seq.get_item(i, vm)
} else {
// TODO: sequence protocol
match vm.get_special_method(self.to_owned(), "__getitem__")? {
Ok(special_method) => return special_method.invoke((needle,), vm),
Err(obj) => {
if obj.class().issubclass(&vm.ctx.types.type_type) {
if obj.is(&vm.ctx.types.type_type) {
return PyGenericAlias::new(obj.clone_class(), needle, vm)
.into_pyresult(vm);
}
if self.class().issubclass(&vm.ctx.types.type_type) {
if self.is(&vm.ctx.types.type_type) {
return PyGenericAlias::new(self.clone_class(), needle, vm).into_pyresult(vm);
}
if let Some(class_getitem) =
vm.get_attribute_opt(obj, "__class_getitem__")?
{
return vm.invoke(&class_getitem, (needle,));
}
}
if let Some(class_getitem) =
vm.get_attribute_opt(self.to_owned(), "__class_getitem__")?
{
return vm.invoke(&class_getitem, (needle,));
}
}
Err(vm.new_type_error(format!("'{}' object is not subscriptable", self.class())))
@@ -464,22 +455,20 @@ impl PyObject {
return dict.set_item(needle, value, vm);
}
let needle = needle.into_pyobject(vm);
let mapping = PyMapping::from(self);
let seq = PySequence::from(self);
if let Some(f) = mapping.methods(vm).ass_subscript {
let needle = needle.into_pyobject(vm);
f(&mapping, &needle, Some(value), vm)
} else if let Some(f) = seq.methods(vm).ass_item {
let i = needle.key_as_isize(vm)?;
f(&seq, i, Some(value), vm)
} else {
// TODO: sequence protocol
vm.get_special_method(self.to_owned(), "__setitem__")?
.map_err(|obj| {
vm.new_type_error(format!(
"'{}' does not support item assignment",
obj.class()
))
})?
.invoke((needle, value), vm)?;
Ok(())
Err(vm.new_type_error(format!(
"'{}' does not support item assignment",
self.class()
)))
}
}
@@ -492,19 +481,17 @@ impl PyObject {
return dict.del_item(needle, vm);
}
let needle = needle.into_pyobject(vm);
let mapping = PyMapping::from(self);
let seq = PySequence::from(self);
if let Some(f) = mapping.methods(vm).ass_subscript {
let needle = needle.into_pyobject(vm);
f(&mapping, &needle, None, vm)
} else if let Some(f) = seq.methods(vm).ass_item {
let i = needle.key_as_isize(vm)?;
f(&seq, i, None, vm)
} else {
//TODO: sequence protocol
vm.get_special_method(self.to_owned(), "__delitem__")?
.map_err(|obj| {
vm.new_type_error(format!("'{}' does not support item deletion", obj.class()))
})?
.invoke((needle,), vm)?;
Ok(())
Err(vm.new_type_error(format!("'{}' does not support item deletion", self.class())))
}
}
}
+19 -3
View File
@@ -9,9 +9,9 @@ mod _sre {
},
common::{ascii, hash::PyHash},
function::{ArgCallable, IntoPyObject, OptionalArg, PosArgs},
protocol::PyBuffer,
protocol::{PyBuffer, PyMappingMethods},
stdlib::sys,
types::{Comparable, Hashable},
types::{AsMapping, Comparable, Hashable},
PyComparisonValue, PyObject, PyObjectRef, PyRef, PyResult, PyValue, TryFromBorrowedObject,
TryFromObject, VirtualMachine,
};
@@ -553,7 +553,7 @@ mod _sre {
regs: Vec<(isize, isize)>,
}
#[pyimpl]
#[pyimpl(with(AsMapping))]
impl Match {
pub(crate) fn new(state: &State, pattern: PyRef<Pattern>, string: PyObjectRef) -> Self {
let mut regs = vec![(state.start as isize, state.string_position as isize)];
@@ -782,6 +782,22 @@ mod _sre {
fn class_getitem(cls: PyTypeRef, args: PyObjectRef, vm: &VirtualMachine) -> PyGenericAlias {
PyGenericAlias::new(cls, args, vm)
}
const MAPPING_METHODS: PyMappingMethods = PyMappingMethods {
length: None,
subscript: Some(|mapping, needle, vm| {
Self::mapping_downcast(mapping)
.getitem(needle.to_owned(), vm)
.map(|x| x.into_pyobject(vm))
}),
ass_subscript: None,
};
}
impl AsMapping for Match {
fn as_mapping(_zelf: &crate::PyObjectView<Self>, _vm: &VirtualMachine) -> PyMappingMethods {
Self::MAPPING_METHODS
}
}
#[pyattr]