mirror of
https://github.com/RustPython/RustPython.git
synced 2026-06-17 01:51:39 +09:00
Add getset_descriptor
This commit is contained in:
@@ -17,6 +17,7 @@ pub mod objfloat;
|
||||
pub mod objframe;
|
||||
pub mod objfunction;
|
||||
pub mod objgenerator;
|
||||
pub mod objgetset;
|
||||
pub mod objint;
|
||||
pub mod objiter;
|
||||
pub mod objlist;
|
||||
|
||||
71
vm/src/obj/objgetset.rs
Normal file
71
vm/src/obj/objgetset.rs
Normal file
@@ -0,0 +1,71 @@
|
||||
/*! Python `attribute` descriptor class. (PyGetSet)
|
||||
|
||||
*/
|
||||
use super::objtype::PyClassRef;
|
||||
use crate::function::OptionalArg;
|
||||
use crate::pyobject::{PyClassImpl, PyContext, PyObjectRef, PyRef, PyResult, PyValue};
|
||||
use crate::slots::PyBuiltinDescriptor;
|
||||
use crate::vm::VirtualMachine;
|
||||
|
||||
pub type PyGetter = dyn Fn(PyObjectRef, &VirtualMachine) -> PyResult;
|
||||
pub type PySetter = dyn Fn(PyObjectRef, PyObjectRef, &VirtualMachine) -> PyResult<()>;
|
||||
|
||||
#[pyclass]
|
||||
pub struct PyGetSet {
|
||||
// name: String,
|
||||
getter: Box<PyGetter>,
|
||||
setter: Box<PySetter>,
|
||||
// doc: Option<String>,
|
||||
}
|
||||
|
||||
impl std::fmt::Debug for PyGetSet {
|
||||
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
|
||||
write!(
|
||||
f,
|
||||
"PyGetSet {{ getter: {:p}, setter: {:p} }}",
|
||||
self.getter, self.setter
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
impl PyValue for PyGetSet {
|
||||
fn class(vm: &VirtualMachine) -> PyClassRef {
|
||||
vm.ctx.getset_type()
|
||||
}
|
||||
}
|
||||
|
||||
pub type PyGetSetRef = PyRef<PyGetSet>;
|
||||
|
||||
impl PyBuiltinDescriptor for PyGetSet {
|
||||
fn get(
|
||||
zelf: PyRef<Self>,
|
||||
obj: PyObjectRef,
|
||||
_cls: OptionalArg<PyObjectRef>,
|
||||
vm: &VirtualMachine,
|
||||
) -> PyResult {
|
||||
(zelf.getter)(obj, vm)
|
||||
}
|
||||
}
|
||||
|
||||
impl PyGetSet {
|
||||
pub fn new(getter: &'static PyGetter, setter: &'static PySetter) -> Self {
|
||||
Self {
|
||||
getter: Box::new(getter),
|
||||
setter: Box::new(setter),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[pyimpl(with(PyBuiltinDescriptor))]
|
||||
impl PyGetSet {
|
||||
// Descriptor methods
|
||||
|
||||
#[pymethod(magic)]
|
||||
fn set(&self, obj: PyObjectRef, value: PyObjectRef, vm: &VirtualMachine) -> PyResult<()> {
|
||||
(self.setter)(obj, value, vm)
|
||||
}
|
||||
}
|
||||
|
||||
pub(crate) fn init(context: &PyContext) {
|
||||
PyGetSet::extend_class(context, &context.types.getset_type);
|
||||
}
|
||||
@@ -175,12 +175,12 @@ impl PyBaseObject {
|
||||
}
|
||||
|
||||
#[pyproperty(name = "__class__")]
|
||||
fn _class(obj: PyObjectRef, _vm: &VirtualMachine) -> PyObjectRef {
|
||||
fn get_class(obj: PyObjectRef, _vm: &VirtualMachine) -> PyObjectRef {
|
||||
obj.class().into_object()
|
||||
}
|
||||
|
||||
#[pyproperty(name = "__class__", setter)]
|
||||
fn _set_class(instance: PyObjectRef, _value: PyObjectRef, vm: &VirtualMachine) -> PyResult<()> {
|
||||
fn set_class(instance: PyObjectRef, _value: PyObjectRef, vm: &VirtualMachine) -> PyResult<()> {
|
||||
let type_repr = vm.to_pystr(&instance.class())?;
|
||||
Err(vm.new_type_error(format!("can't change class of type '{}'", type_repr)))
|
||||
}
|
||||
|
||||
@@ -330,6 +330,10 @@ impl PyContext {
|
||||
self.types.readonly_property_type.clone()
|
||||
}
|
||||
|
||||
pub fn getset_type(&self) -> PyClassRef {
|
||||
self.types.getset_type.clone()
|
||||
}
|
||||
|
||||
pub fn classmethod_type(&self) -> PyClassRef {
|
||||
self.types.classmethod_type.clone()
|
||||
}
|
||||
|
||||
@@ -14,6 +14,7 @@ use crate::obj::objfloat;
|
||||
use crate::obj::objframe;
|
||||
use crate::obj::objfunction;
|
||||
use crate::obj::objgenerator;
|
||||
use crate::obj::objgetset;
|
||||
use crate::obj::objint;
|
||||
use crate::obj::objiter;
|
||||
use crate::obj::objlist;
|
||||
@@ -94,6 +95,7 @@ pub struct TypeZoo {
|
||||
pub method_descriptor_type: PyClassRef,
|
||||
pub property_type: PyClassRef,
|
||||
pub readonly_property_type: PyClassRef,
|
||||
pub getset_type: PyClassRef,
|
||||
pub module_type: PyClassRef,
|
||||
pub namespace_type: PyClassRef,
|
||||
pub bound_method_type: PyClassRef,
|
||||
@@ -125,6 +127,7 @@ impl TypeZoo {
|
||||
let method_descriptor_type = create_type("method_descriptor", &type_type, &object_type);
|
||||
let property_type = create_type("property", &type_type, &object_type);
|
||||
let readonly_property_type = create_type("readonly_property", &type_type, &object_type);
|
||||
let getset_type = create_type("getset_descriptor", &type_type, &object_type);
|
||||
let super_type = create_type("super", &type_type, &object_type);
|
||||
let weakref_type = create_type("ref", &type_type, &object_type);
|
||||
let weakproxy_type = create_type("weakproxy", &type_type, &object_type);
|
||||
@@ -220,6 +223,7 @@ impl TypeZoo {
|
||||
mappingproxy_type,
|
||||
property_type,
|
||||
readonly_property_type,
|
||||
getset_type,
|
||||
generator_type,
|
||||
module_type,
|
||||
namespace_type,
|
||||
@@ -381,6 +385,7 @@ pub fn initialize_types(context: &PyContext) {
|
||||
objbytes::init(&context);
|
||||
objbytearray::init(&context);
|
||||
objproperty::init(&context);
|
||||
objgetset::init(&context);
|
||||
objmemory::init(&context);
|
||||
objstr::init(&context);
|
||||
objrange::init(&context);
|
||||
|
||||
Reference in New Issue
Block a user