mirror of
https://github.com/RustPython/RustPython.git
synced 2026-06-09 22:49:57 +09:00
objtype::class_*_attr into PyClassRef methods
This commit is contained in:
@@ -1,7 +1,7 @@
|
||||
use super::objdict::PyDictRef;
|
||||
use super::objiter;
|
||||
use super::objstr::PyStringRef;
|
||||
use super::objtype::{self, PyClassRef};
|
||||
use super::objtype::PyClassRef;
|
||||
use crate::function::OptionalArg;
|
||||
use crate::pyobject::{
|
||||
ItemProtocol, PyClassImpl, PyContext, PyObjectRef, PyRef, PyResult, PyValue, TryFromObject,
|
||||
@@ -48,7 +48,7 @@ impl PyMappingProxy {
|
||||
let opt = match &self.mapping {
|
||||
MappingProxyInner::Class(class) => {
|
||||
let key = PyStringRef::try_from_object(vm, key)?;
|
||||
objtype::class_get_attr(&class, key.as_str())
|
||||
class.get_attr(key.as_str())
|
||||
}
|
||||
MappingProxyInner::Dict(obj) => obj.get_item(&key, vm).ok(),
|
||||
};
|
||||
@@ -75,7 +75,7 @@ impl PyMappingProxy {
|
||||
match &self.mapping {
|
||||
MappingProxyInner::Class(class) => {
|
||||
let key = PyStringRef::try_from_object(vm, key)?;
|
||||
Ok(vm.new_bool(objtype::class_has_attr(&class, key.as_str())))
|
||||
Ok(vm.new_bool(class.has_attr(key.as_str())))
|
||||
}
|
||||
MappingProxyInner::Dict(obj) => vm._membership(obj.clone(), key),
|
||||
}
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
use super::objproperty::PyPropertyRef;
|
||||
use super::objstr::PyStringRef;
|
||||
use super::objtype::{class_get_attr, class_has_attr, PyClassRef};
|
||||
use super::objtype::PyClassRef;
|
||||
use crate::pyobject::{
|
||||
IntoPyObject, PyClassImpl, PyContext, PyObjectRef, PyRef, PyResult, PyValue, TryFromObject,
|
||||
TypeProtocol,
|
||||
@@ -79,10 +79,10 @@ impl PyNone {
|
||||
}
|
||||
}
|
||||
|
||||
if let Some(attr) = class_get_attr(&cls, name.as_str()) {
|
||||
if let Some(attr) = cls.get_attr(name.as_str()) {
|
||||
let attr_class = attr.class();
|
||||
if class_has_attr(&attr_class, "__set__") {
|
||||
if let Some(get_func) = class_get_attr(&attr_class, "__get__") {
|
||||
if attr_class.has_attr("__set__") {
|
||||
if let Some(get_func) = attr_class.get_attr("__get__") {
|
||||
return call_descriptor(
|
||||
attr,
|
||||
get_func,
|
||||
@@ -98,14 +98,14 @@ impl PyNone {
|
||||
// if let Some(obj_attr) = zelf.as_object().get_attr(name.as_str()) {
|
||||
// Ok(obj_attr)
|
||||
// } else
|
||||
if let Some(attr) = class_get_attr(&cls, name.as_str()) {
|
||||
if let Some(attr) = cls.get_attr(name.as_str()) {
|
||||
let attr_class = attr.class();
|
||||
if let Some(get_func) = class_get_attr(&attr_class, "__get__") {
|
||||
if let Some(get_func) = attr_class.get_attr("__get__") {
|
||||
call_descriptor(attr, get_func, zelf.into_object(), cls.into_object(), vm)
|
||||
} else {
|
||||
Ok(attr)
|
||||
}
|
||||
} else if let Some(getter) = class_get_attr(&cls, "__getattr__") {
|
||||
} else if let Some(getter) = cls.get_attr("__getattr__") {
|
||||
vm.invoke(&getter, vec![zelf.into_object(), name.into_object()])
|
||||
} else {
|
||||
Err(vm.new_attribute_error(format!("{} has no attribute '{}'", zelf.as_object(), name)))
|
||||
|
||||
@@ -86,8 +86,8 @@ pub(crate) fn object_setattr(
|
||||
vm_trace!("object.__setattr__({:?}, {}, {:?})", obj, attr_name, value);
|
||||
let cls = obj.class();
|
||||
|
||||
if let Some(attr) = objtype::class_get_attr(&cls, attr_name.as_str()) {
|
||||
if let Some(descriptor) = objtype::class_get_attr(&attr.class(), "__set__") {
|
||||
if let Some(attr) = cls.get_attr(attr_name.as_str()) {
|
||||
if let Some(descriptor) = attr.class().get_attr("__set__") {
|
||||
return vm
|
||||
.invoke(&descriptor, vec![attr, obj.clone(), value])
|
||||
.map(|_| ());
|
||||
@@ -109,8 +109,8 @@ pub(crate) fn object_setattr(
|
||||
fn object_delattr(obj: PyObjectRef, attr_name: PyStringRef, vm: &VirtualMachine) -> PyResult<()> {
|
||||
let cls = obj.class();
|
||||
|
||||
if let Some(attr) = objtype::class_get_attr(&cls, attr_name.as_str()) {
|
||||
if let Some(descriptor) = objtype::class_get_attr(&attr.class(), "__delete__") {
|
||||
if let Some(attr) = cls.get_attr(attr_name.as_str()) {
|
||||
if let Some(descriptor) = attr.class().get_attr("__delete__") {
|
||||
return vm.invoke(&descriptor, vec![attr, obj.clone()]).map(|_| ());
|
||||
}
|
||||
}
|
||||
@@ -140,7 +140,7 @@ fn object_subclasshook(vm: &VirtualMachine, _args: PyFuncArgs) -> PyResult {
|
||||
}
|
||||
|
||||
pub fn object_dir(obj: PyObjectRef, vm: &VirtualMachine) -> PyResult<PyList> {
|
||||
let attributes: PyAttributes = objtype::get_attributes(obj.class());
|
||||
let attributes: PyAttributes = obj.class().get_attributes();
|
||||
|
||||
let dict = PyDictRef::from_attributes(attributes, vm)?;
|
||||
|
||||
@@ -262,9 +262,8 @@ fn object_reduce(obj: PyObjectRef, proto: OptionalArg<usize>, vm: &VirtualMachin
|
||||
|
||||
fn object_reduce_ex(obj: PyObjectRef, proto: usize, vm: &VirtualMachine) -> PyResult {
|
||||
let cls = obj.class();
|
||||
if let Some(reduce) = objtype::class_get_attr(&cls, "__reduce__") {
|
||||
let object_reduce =
|
||||
objtype::class_get_attr(&vm.ctx.types.object_type, "__reduce__").unwrap();
|
||||
if let Some(reduce) = cls.get_attr("__reduce__") {
|
||||
let object_reduce = vm.ctx.types.object_type.get_attr("__reduce__").unwrap();
|
||||
if !reduce.is(&object_reduce) {
|
||||
return vm.invoke(&reduce, vec![]);
|
||||
}
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
use super::objint::PyInt;
|
||||
use super::objtype::{class_has_attr, PyClassRef};
|
||||
use super::objtype::PyClassRef;
|
||||
use crate::function::{OptionalArg, PyFuncArgs};
|
||||
use crate::pyobject::{
|
||||
IdProtocol, PyClassImpl, PyContext, PyObjectRef, PyRef, PyResult, PyValue, TryIntoRef,
|
||||
@@ -327,7 +327,7 @@ fn to_index_value(vm: &VirtualMachine, obj: &PyObjectRef) -> PyResult<Option<Big
|
||||
Ok(Some(val.as_bigint().clone()))
|
||||
} else {
|
||||
let cls = obj.class();
|
||||
if class_has_attr(&cls, "__index__") {
|
||||
if cls.has_attr("__index__") {
|
||||
let index_result = vm.call_method(obj, "__index__", vec![])?;
|
||||
if let Some(val) = index_result.payload::<PyInt>() {
|
||||
Ok(Some(val.as_bigint().clone()))
|
||||
|
||||
@@ -98,7 +98,7 @@ impl PyClassRef {
|
||||
|
||||
#[pymethod(magic)]
|
||||
fn dir(self, vm: &VirtualMachine) -> PyList {
|
||||
let attributes = get_attributes(self);
|
||||
let attributes = self.get_attributes();
|
||||
let attributes: Vec<PyObjectRef> = attributes
|
||||
.keys()
|
||||
.map(|k| vm.ctx.new_str(k.to_string()))
|
||||
@@ -156,10 +156,10 @@ impl PyClassRef {
|
||||
vm_trace!("type.__getattribute__({:?}, {:?})", self, name);
|
||||
let mcl = self.class();
|
||||
|
||||
if let Some(attr) = class_get_attr(&mcl, &name) {
|
||||
if let Some(attr) = mcl.get_attr(&name) {
|
||||
let attr_class = attr.class();
|
||||
if class_has_attr(&attr_class, "__set__") {
|
||||
if let Some(ref descriptor) = class_get_attr(&attr_class, "__get__") {
|
||||
if attr_class.has_attr("__set__") {
|
||||
if let Some(ref descriptor) = attr_class.get_attr("__get__") {
|
||||
return vm.invoke(
|
||||
descriptor,
|
||||
vec![attr, self.into_object(), mcl.into_object()],
|
||||
@@ -168,18 +168,18 @@ impl PyClassRef {
|
||||
}
|
||||
}
|
||||
|
||||
if let Some(attr) = class_get_attr(&self, &name) {
|
||||
if let Some(attr) = self.get_attr(&name) {
|
||||
let attr_class = attr.class();
|
||||
if let Some(ref descriptor) = class_get_attr(&attr_class, "__get__") {
|
||||
if let Some(ref descriptor) = attr_class.get_attr("__get__") {
|
||||
return vm.invoke(descriptor, vec![attr, vm.get_none(), self.into_object()]);
|
||||
}
|
||||
}
|
||||
|
||||
if let Some(cls_attr) = class_get_attr(&self, &name) {
|
||||
if let Some(cls_attr) = self.get_attr(&name) {
|
||||
Ok(cls_attr)
|
||||
} else if let Some(attr) = class_get_attr(&mcl, &name) {
|
||||
} else if let Some(attr) = mcl.get_attr(&name) {
|
||||
vm.call_get_descriptor(attr, self.into_object())
|
||||
} else if let Some(ref getter) = class_get_attr(&self, "__getattr__") {
|
||||
} else if let Some(ref getter) = self.get_attr("__getattr__") {
|
||||
vm.invoke(getter, vec![mcl.into_object(), name_ref.into_object()])
|
||||
} else {
|
||||
Err(vm.new_attribute_error(format!("{} has no attribute '{}'", self, name)))
|
||||
@@ -193,8 +193,8 @@ impl PyClassRef {
|
||||
value: PyObjectRef,
|
||||
vm: &VirtualMachine,
|
||||
) -> PyResult<()> {
|
||||
if let Some(attr) = class_get_attr(&self.class(), attr_name.as_str()) {
|
||||
if let Some(ref descriptor) = class_get_attr(&attr.class(), "__set__") {
|
||||
if let Some(attr) = self.class().get_attr(attr_name.as_str()) {
|
||||
if let Some(ref descriptor) = attr.class().get_attr("__set__") {
|
||||
vm.invoke(descriptor, vec![attr, self.into_object(), value])?;
|
||||
return Ok(());
|
||||
}
|
||||
@@ -208,15 +208,15 @@ impl PyClassRef {
|
||||
|
||||
#[pymethod(magic)]
|
||||
fn delattr(self, attr_name: PyStringRef, vm: &VirtualMachine) -> PyResult<()> {
|
||||
if let Some(attr) = class_get_attr(&self.class(), attr_name.as_str()) {
|
||||
if let Some(ref descriptor) = class_get_attr(&attr.class(), "__delete__") {
|
||||
if let Some(attr) = self.class().get_attr(attr_name.as_str()) {
|
||||
if let Some(ref descriptor) = attr.class().get_attr("__delete__") {
|
||||
return vm
|
||||
.invoke(descriptor, vec![attr, self.into_object()])
|
||||
.map(|_| ());
|
||||
}
|
||||
}
|
||||
|
||||
if class_get_attr(&self, attr_name.as_str()).is_some() {
|
||||
if self.get_attr(attr_name.as_str()).is_some() {
|
||||
self.attributes.borrow_mut().remove(attr_name.as_str());
|
||||
Ok(())
|
||||
} else {
|
||||
@@ -397,48 +397,48 @@ fn type_dict_setter(
|
||||
))
|
||||
}
|
||||
|
||||
/// This is the internal get_attr implementation for fast lookup on a class.
|
||||
pub fn class_get_attr(class: &PyClassRef, attr_name: &str) -> Option<PyObjectRef> {
|
||||
flame_guard!(format!("class_get_attr({:?})", attr_name));
|
||||
impl PyClassRef {
|
||||
/// This is the internal get_attr implementation for fast lookup on a class.
|
||||
pub fn get_attr(&self, attr_name: &str) -> Option<PyObjectRef> {
|
||||
flame_guard!(format!("class_get_attr({:?})", attr_name));
|
||||
|
||||
class
|
||||
.attributes
|
||||
.borrow()
|
||||
.get(attr_name)
|
||||
.cloned()
|
||||
.or_else(|| class_get_super_attr(class, attr_name))
|
||||
}
|
||||
|
||||
pub fn class_get_super_attr(class: &PyClassRef, attr_name: &str) -> Option<PyObjectRef> {
|
||||
class
|
||||
.mro
|
||||
.iter()
|
||||
.find_map(|class| class.attributes.borrow().get(attr_name).cloned())
|
||||
}
|
||||
|
||||
// This is the internal has_attr implementation for fast lookup on a class.
|
||||
pub fn class_has_attr(class: &PyClassRef, attr_name: &str) -> bool {
|
||||
class.attributes.borrow().contains_key(attr_name)
|
||||
|| class
|
||||
.mro
|
||||
.iter()
|
||||
.any(|c| c.attributes.borrow().contains_key(attr_name))
|
||||
}
|
||||
|
||||
pub fn get_attributes(cls: PyClassRef) -> PyAttributes {
|
||||
// Gather all members here:
|
||||
let mut attributes = PyAttributes::new();
|
||||
|
||||
let mut base_classes: Vec<&PyClassRef> = cls.iter_mro().collect();
|
||||
base_classes.reverse();
|
||||
|
||||
for bc in base_classes {
|
||||
for (name, value) in bc.attributes.borrow().iter() {
|
||||
attributes.insert(name.to_string(), value.clone());
|
||||
}
|
||||
self.attributes
|
||||
.borrow()
|
||||
.get(attr_name)
|
||||
.cloned()
|
||||
.or_else(|| self.get_super_attr(attr_name))
|
||||
}
|
||||
|
||||
attributes
|
||||
pub fn get_super_attr(&self, attr_name: &str) -> Option<PyObjectRef> {
|
||||
self.mro
|
||||
.iter()
|
||||
.find_map(|class| class.attributes.borrow().get(attr_name).cloned())
|
||||
}
|
||||
|
||||
// This is the internal has_attr implementation for fast lookup on a class.
|
||||
pub fn has_attr(&self, attr_name: &str) -> bool {
|
||||
self.attributes.borrow().contains_key(attr_name)
|
||||
|| self
|
||||
.mro
|
||||
.iter()
|
||||
.any(|c| c.attributes.borrow().contains_key(attr_name))
|
||||
}
|
||||
|
||||
pub fn get_attributes(self) -> PyAttributes {
|
||||
// Gather all members here:
|
||||
let mut attributes = PyAttributes::new();
|
||||
|
||||
let mut base_classes: Vec<&PyClassRef> = self.iter_mro().collect();
|
||||
base_classes.reverse();
|
||||
|
||||
for bc in base_classes {
|
||||
for (name, value) in bc.attributes.borrow().iter() {
|
||||
attributes.insert(name.to_string(), value.clone());
|
||||
}
|
||||
}
|
||||
|
||||
attributes
|
||||
}
|
||||
}
|
||||
|
||||
fn take_next_base(mut bases: Vec<Vec<PyClassRef>>) -> Option<(PyClassRef, Vec<Vec<PyClassRef>>)> {
|
||||
|
||||
@@ -777,7 +777,7 @@ impl PyItertoolsTee {
|
||||
) -> PyResult<PyRef<PyTuple>> {
|
||||
let n = n.unwrap_or(2);
|
||||
|
||||
let copyable = if objtype::class_has_attr(&iterable.class(), "__copy__") {
|
||||
let copyable = if iterable.class().has_attr("__copy__") {
|
||||
vm.call_method(&iterable, "__copy__", PyFuncArgs::from(vec![]))?
|
||||
} else {
|
||||
PyItertoolsTee::from_iter(iterable, vm)?
|
||||
|
||||
23
vm/src/vm.rs
23
vm/src/vm.rs
@@ -624,7 +624,7 @@ impl VirtualMachine {
|
||||
if let Some(descr_get) = slots.borrow().descr_get.as_ref() {
|
||||
let cls = obj.class();
|
||||
descr_get(self, vec![attr, obj.clone(), cls.into_object()].into())
|
||||
} else if let Some(ref descriptor) = objtype::class_get_attr(&attr_class, "__get__") {
|
||||
} else if let Some(ref descriptor) = attr_class.get_attr("__get__") {
|
||||
let cls = obj.class();
|
||||
self.invoke(descriptor, vec![attr, obj.clone(), cls.into_object()])
|
||||
} else {
|
||||
@@ -640,7 +640,7 @@ impl VirtualMachine {
|
||||
|
||||
// This is only used in the vm for magic methods, which use a greatly simplified attribute lookup.
|
||||
let cls = obj.class();
|
||||
match objtype::class_get_attr(&cls, method_name) {
|
||||
match cls.get_attr(method_name) {
|
||||
Some(func) => {
|
||||
vm_trace!(
|
||||
"vm.call_method {:?} {:?} {:?} -> {:?}",
|
||||
@@ -666,7 +666,7 @@ impl VirtualMachine {
|
||||
let result = slot_call(self, args);
|
||||
self.trace_event(TraceEvent::Return)?;
|
||||
result
|
||||
} else if objtype::class_has_attr(&class, "__call__") {
|
||||
} else if class.has_attr("__call__") {
|
||||
let result = self.call_method(&callable, "__call__", args);
|
||||
result
|
||||
} else {
|
||||
@@ -781,7 +781,7 @@ impl VirtualMachine {
|
||||
F: FnOnce() -> String,
|
||||
{
|
||||
let cls = obj.class();
|
||||
match objtype::class_get_attr(&cls, method_name) {
|
||||
match cls.get_attr(method_name) {
|
||||
Some(method) => self.call_get_descriptor(method, obj.clone()),
|
||||
None => Err(self.new_type_error(err_msg())),
|
||||
}
|
||||
@@ -790,7 +790,7 @@ impl VirtualMachine {
|
||||
/// May return exception, if `__get__` descriptor raises one
|
||||
pub fn get_method(&self, obj: PyObjectRef, method_name: &str) -> Option<PyResult> {
|
||||
let cls = obj.class();
|
||||
let method = objtype::class_get_attr(&cls, method_name)?;
|
||||
let method = cls.get_attr(method_name)?;
|
||||
Some(self.call_get_descriptor(method, obj.clone()))
|
||||
}
|
||||
|
||||
@@ -851,10 +851,10 @@ impl VirtualMachine {
|
||||
let name = name_str.as_str();
|
||||
let cls = obj.class();
|
||||
|
||||
if let Some(attr) = objtype::class_get_attr(&cls, &name) {
|
||||
if let Some(attr) = cls.get_attr(&name) {
|
||||
let attr_class = attr.class();
|
||||
if objtype::class_has_attr(&attr_class, "__set__") {
|
||||
if let Some(descriptor) = objtype::class_get_attr(&attr_class, "__get__") {
|
||||
if attr_class.has_attr("__set__") {
|
||||
if let Some(descriptor) = attr_class.get_attr("__get__") {
|
||||
return self
|
||||
.invoke(&descriptor, vec![attr, obj, cls.into_object()])
|
||||
.map(Some);
|
||||
@@ -870,9 +870,9 @@ impl VirtualMachine {
|
||||
|
||||
if let Some(obj_attr) = attr {
|
||||
Ok(Some(obj_attr))
|
||||
} else if let Some(attr) = objtype::class_get_attr(&cls, &name) {
|
||||
} else if let Some(attr) = cls.get_attr(&name) {
|
||||
self.call_get_descriptor(attr, obj).map(Some)
|
||||
} else if let Some(getter) = objtype::class_get_attr(&cls, "__getattr__") {
|
||||
} else if let Some(getter) = cls.get_attr("__getattr__") {
|
||||
self.invoke(&getter, vec![obj, name_str.into_object()])
|
||||
.map(Some)
|
||||
} else {
|
||||
@@ -881,8 +881,7 @@ impl VirtualMachine {
|
||||
}
|
||||
|
||||
pub fn is_callable(&self, obj: &PyObjectRef) -> bool {
|
||||
obj.class().slots.borrow().call.is_some()
|
||||
|| objtype::class_has_attr(&obj.class(), "__call__")
|
||||
obj.class().slots.borrow().call.is_some() || obj.class().has_attr("__call__")
|
||||
}
|
||||
|
||||
#[inline]
|
||||
|
||||
Reference in New Issue
Block a user