mirror of
https://github.com/RustPython/RustPython.git
synced 2026-10-28 18:59:04 +08:00
Implement MemberDescrObject setter
This commit is contained in:
1 parent
768a8e5148
commit
e7b39bdc8a
5 files changed
+79
-8
No files matched your search
@@ -694,7 +694,7 @@ where
|
||||
quote_spanned! { ident.span() =>
|
||||
class.set_str_attr(
|
||||
#py_name,
|
||||
ctx.new_member(#py_name, Self::#ident, class),
|
||||
ctx.new_member(#py_name, Self::#ident, None, class),
|
||||
ctx,
|
||||
);
|
||||
}
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
use super::{PyStr, PyType, PyTypeRef};
|
||||
use crate::{
|
||||
class::PyClassImpl,
|
||||
function::PySetterValue,
|
||||
types::{Constructor, GetDescriptor, Unconstructible},
|
||||
AsObject, Context, Py, PyObjectRef, PyPayload, PyRef, PyResult, VirtualMachine,
|
||||
};
|
||||
@@ -18,15 +19,23 @@ pub enum MemberKind {
|
||||
ObjectEx = 16,
|
||||
}
|
||||
|
||||
pub type MemberSetterFunc = Option<fn(&VirtualMachine, PyObjectRef, PySetterValue) -> PyResult<()>>;
|
||||
|
||||
pub enum MemberGetter {
|
||||
Getter(fn(&VirtualMachine, PyObjectRef) -> PyResult),
|
||||
Offset(usize),
|
||||
}
|
||||
|
||||
pub enum MemberSetter {
|
||||
Setter(MemberSetterFunc),
|
||||
Offset(usize),
|
||||
}
|
||||
|
||||
pub struct MemberDef {
|
||||
pub name: String,
|
||||
pub kind: MemberKind,
|
||||
pub getter: MemberGetter,
|
||||
pub setter: MemberSetter,
|
||||
pub doc: Option<String>,
|
||||
}
|
||||
|
||||
@@ -37,6 +46,21 @@ impl MemberDef {
|
||||
MemberGetter::Offset(offset) => get_slot_from_object(obj, offset, self, vm),
|
||||
}
|
||||
}
|
||||
|
||||
fn set(
|
||||
&self,
|
||||
obj: PyObjectRef,
|
||||
value: PySetterValue<PyObjectRef>,
|
||||
vm: &VirtualMachine,
|
||||
) -> PyResult<()> {
|
||||
match self.setter {
|
||||
MemberSetter::Setter(setter) => match setter {
|
||||
Some(setter) => (setter)(vm, obj, value),
|
||||
None => Err(vm.new_attribute_error("readonly attribute".to_string())),
|
||||
},
|
||||
MemberSetter::Offset(offset) => set_slot_at_object(obj, offset, self, value, vm),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl std::fmt::Debug for MemberDef {
|
||||
@@ -103,6 +127,17 @@ impl MemberDescrObject {
|
||||
qualname.to_owned()
|
||||
})
|
||||
}
|
||||
|
||||
#[pyslot]
|
||||
fn descr_set(
|
||||
zelf: PyObjectRef,
|
||||
obj: PyObjectRef,
|
||||
value: PySetterValue<PyObjectRef>,
|
||||
vm: &VirtualMachine,
|
||||
) -> PyResult<()> {
|
||||
let zelf = Self::_zelf(zelf, vm)?;
|
||||
zelf.member.set(obj, value, vm)
|
||||
}
|
||||
}
|
||||
|
||||
// PyMember_GetOne
|
||||
@@ -124,6 +159,24 @@ fn get_slot_from_object(
|
||||
Ok(slot)
|
||||
}
|
||||
|
||||
// PyMember_SetOne
|
||||
fn set_slot_at_object(
|
||||
obj: PyObjectRef,
|
||||
offset: usize,
|
||||
member: &MemberDef,
|
||||
value: PySetterValue,
|
||||
_vm: &VirtualMachine,
|
||||
) -> PyResult<()> {
|
||||
match member.kind {
|
||||
MemberKind::ObjectEx => match value {
|
||||
PySetterValue::Assign(v) => obj.set_slot(offset, Some(v)),
|
||||
PySetterValue::Delete => obj.set_slot(offset, None),
|
||||
},
|
||||
}
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
impl Unconstructible for MemberDescrObject {}
|
||||
|
||||
impl GetDescriptor for MemberDescrObject {
|
||||
|
||||
@@ -4,7 +4,11 @@ use super::{
|
||||
};
|
||||
use crate::{
|
||||
builtins::PyBaseExceptionRef,
|
||||
builtins::{descriptor::MemberGetter, function::PyCellRef, tuple::PyTupleTyped},
|
||||
builtins::{
|
||||
descriptor::{MemberGetter, MemberSetter},
|
||||
function::PyCellRef,
|
||||
tuple::PyTupleTyped,
|
||||
},
|
||||
class::{PyClassImpl, StaticType},
|
||||
convert::ToPyObject,
|
||||
function::{FuncArgs, KwArgs, OptionalArg, PySetterValue},
|
||||
@@ -689,6 +693,7 @@ impl PyType {
|
||||
name: member.to_string(),
|
||||
kind: MemberKind::ObjectEx,
|
||||
getter: MemberGetter::Offset(offset),
|
||||
setter: MemberSetter::Offset(offset),
|
||||
doc: None,
|
||||
};
|
||||
let member_descriptor: PyRef<MemberDescrObject> = vm.new_pyref(MemberDescrObject {
|
||||
|
||||
+13
-5
@@ -25,6 +25,7 @@ use crate::{
|
||||
builtins::{PyDictRef, PyTypeRef},
|
||||
vm::VirtualMachine,
|
||||
};
|
||||
use itertools::Itertools;
|
||||
use std::{
|
||||
any::TypeId,
|
||||
borrow::Borrow,
|
||||
@@ -115,7 +116,7 @@ struct PyInner<T> {
|
||||
weak_list: WeakRefList,
|
||||
|
||||
payload: T,
|
||||
slots: Vec<Option<PyObjectRef>>,
|
||||
slots: Box<[PyRwLock<Option<PyObjectRef>>]>,
|
||||
}
|
||||
|
||||
impl<T: fmt::Debug> fmt::Debug for PyInner<T> {
|
||||
@@ -436,7 +437,10 @@ impl<T: PyObjectPayload> PyInner<T> {
|
||||
dict: dict.map(InstanceDict::new),
|
||||
weak_list: WeakRefList::new(),
|
||||
payload,
|
||||
slots: vec![None; member_count],
|
||||
slots: std::iter::repeat_with(|| PyRwLock::new(None))
|
||||
.take(member_count)
|
||||
.collect_vec()
|
||||
.into_boxed_slice(),
|
||||
})
|
||||
}
|
||||
}
|
||||
@@ -799,7 +803,11 @@ impl PyObject {
|
||||
}
|
||||
|
||||
pub(crate) fn get_slot(&self, offset: usize) -> Option<PyObjectRef> {
|
||||
self.0.slots[offset].clone()
|
||||
self.0.slots[offset].read().clone()
|
||||
}
|
||||
|
||||
pub(crate) fn set_slot(&self, offset: usize, value: Option<PyObjectRef>) {
|
||||
*self.0.slots[offset].write() = value;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1131,7 +1139,7 @@ pub(crate) fn init_type_hierarchy() -> (PyTypeRef, PyTypeRef, PyTypeRef) {
|
||||
dict: None,
|
||||
weak_list: WeakRefList::new(),
|
||||
payload: type_payload,
|
||||
slots: Vec::new(),
|
||||
slots: Box::new([]),
|
||||
},
|
||||
Uninit { typ }
|
||||
)));
|
||||
@@ -1143,7 +1151,7 @@ pub(crate) fn init_type_hierarchy() -> (PyTypeRef, PyTypeRef, PyTypeRef) {
|
||||
dict: None,
|
||||
weak_list: WeakRefList::new(),
|
||||
payload: object_payload,
|
||||
slots: Vec::new(),
|
||||
slots: Box::new([]),
|
||||
},
|
||||
Uninit { typ },
|
||||
)));
|
||||
|
||||
@@ -3,7 +3,10 @@ use crate::{
|
||||
builtinfunc::{PyBuiltinFunction, PyBuiltinMethod, PyNativeFuncDef},
|
||||
bytes,
|
||||
code::{self, PyCode},
|
||||
descriptor::{DescrObject, MemberDef, MemberDescrObject, MemberGetter, MemberKind},
|
||||
descriptor::{
|
||||
DescrObject, MemberDef, MemberDescrObject, MemberGetter, MemberKind, MemberSetter,
|
||||
MemberSetterFunc,
|
||||
},
|
||||
getset::PyGetSet,
|
||||
object, pystr,
|
||||
type_::PyAttributes,
|
||||
@@ -458,12 +461,14 @@ impl Context {
|
||||
&self,
|
||||
name: &str,
|
||||
getter: fn(&VirtualMachine, PyObjectRef) -> PyResult,
|
||||
setter: MemberSetterFunc,
|
||||
class: &'static Py<PyType>,
|
||||
) -> PyRef<MemberDescrObject> {
|
||||
let member_def = MemberDef {
|
||||
name: name.to_owned(),
|
||||
kind: MemberKind::ObjectEx,
|
||||
getter: MemberGetter::Getter(getter),
|
||||
setter: MemberSetter::Setter(setter),
|
||||
doc: None,
|
||||
};
|
||||
let member_descriptor = MemberDescrObject {
|
||||
|
||||
Reference in new issue
Block a user