mirror of
https://github.com/RustPython/RustPython.git
synced 2026-10-29 03:04:38 +08:00
fix item protocol use sequence protocol
This commit is contained in:
1 parent
0abe90dd0a
commit
c6ee563088
4 files changed
+81
-50
No files matched your search
@@ -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 {
|
||||
|
||||
@@ -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
@@ -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
@@ -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]
|
||||
|
||||
Reference in new issue
Block a user