Skip to content

Commit b2ba6b2

Browse files
committed
objtype::class_*_attr into PyClassRef methods
1 parent ad2d82c commit b2ba6b2

7 files changed

Lines changed: 79 additions & 81 deletions

File tree

vm/src/obj/objmappingproxy.rs

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
use super::objdict::PyDictRef;
22
use super::objiter;
33
use super::objstr::PyStringRef;
4-
use super::objtype::{self, PyClassRef};
4+
use super::objtype::PyClassRef;
55
use crate::function::OptionalArg;
66
use crate::pyobject::{
77
ItemProtocol, PyClassImpl, PyContext, PyObjectRef, PyRef, PyResult, PyValue, TryFromObject,
@@ -48,7 +48,7 @@ impl PyMappingProxy {
4848
let opt = match &self.mapping {
4949
MappingProxyInner::Class(class) => {
5050
let key = PyStringRef::try_from_object(vm, key)?;
51-
objtype::class_get_attr(&class, key.as_str())
51+
class.get_attr(key.as_str())
5252
}
5353
MappingProxyInner::Dict(obj) => obj.get_item(&key, vm).ok(),
5454
};
@@ -75,7 +75,7 @@ impl PyMappingProxy {
7575
match &self.mapping {
7676
MappingProxyInner::Class(class) => {
7777
let key = PyStringRef::try_from_object(vm, key)?;
78-
Ok(vm.new_bool(objtype::class_has_attr(&class, key.as_str())))
78+
Ok(vm.new_bool(class.has_attr(key.as_str())))
7979
}
8080
MappingProxyInner::Dict(obj) => vm._membership(obj.clone(), key),
8181
}

vm/src/obj/objnone.rs

Lines changed: 7 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
use super::objproperty::PyPropertyRef;
22
use super::objstr::PyStringRef;
3-
use super::objtype::{class_get_attr, class_has_attr, PyClassRef};
3+
use super::objtype::PyClassRef;
44
use crate::pyobject::{
55
IntoPyObject, PyClassImpl, PyContext, PyObjectRef, PyRef, PyResult, PyValue, TryFromObject,
66
TypeProtocol,
@@ -79,10 +79,10 @@ impl PyNone {
7979
}
8080
}
8181

82-
if let Some(attr) = class_get_attr(&cls, name.as_str()) {
82+
if let Some(attr) = cls.get_attr(name.as_str()) {
8383
let attr_class = attr.class();
84-
if class_has_attr(&attr_class, "__set__") {
85-
if let Some(get_func) = class_get_attr(&attr_class, "__get__") {
84+
if attr_class.has_attr("__set__") {
85+
if let Some(get_func) = attr_class.get_attr("__get__") {
8686
return call_descriptor(
8787
attr,
8888
get_func,
@@ -98,14 +98,14 @@ impl PyNone {
9898
// if let Some(obj_attr) = zelf.as_object().get_attr(name.as_str()) {
9999
// Ok(obj_attr)
100100
// } else
101-
if let Some(attr) = class_get_attr(&cls, name.as_str()) {
101+
if let Some(attr) = cls.get_attr(name.as_str()) {
102102
let attr_class = attr.class();
103-
if let Some(get_func) = class_get_attr(&attr_class, "__get__") {
103+
if let Some(get_func) = attr_class.get_attr("__get__") {
104104
call_descriptor(attr, get_func, zelf.into_object(), cls.into_object(), vm)
105105
} else {
106106
Ok(attr)
107107
}
108-
} else if let Some(getter) = class_get_attr(&cls, "__getattr__") {
108+
} else if let Some(getter) = cls.get_attr("__getattr__") {
109109
vm.invoke(&getter, vec![zelf.into_object(), name.into_object()])
110110
} else {
111111
Err(vm.new_attribute_error(format!("{} has no attribute '{}'", zelf.as_object(), name)))

vm/src/obj/objobject.rs

Lines changed: 7 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -86,8 +86,8 @@ pub(crate) fn object_setattr(
8686
vm_trace!("object.__setattr__({:?}, {}, {:?})", obj, attr_name, value);
8787
let cls = obj.class();
8888

89-
if let Some(attr) = objtype::class_get_attr(&cls, attr_name.as_str()) {
90-
if let Some(descriptor) = objtype::class_get_attr(&attr.class(), "__set__") {
89+
if let Some(attr) = cls.get_attr(attr_name.as_str()) {
90+
if let Some(descriptor) = attr.class().get_attr("__set__") {
9191
return vm
9292
.invoke(&descriptor, vec![attr, obj.clone(), value])
9393
.map(|_| ());
@@ -109,8 +109,8 @@ pub(crate) fn object_setattr(
109109
fn object_delattr(obj: PyObjectRef, attr_name: PyStringRef, vm: &VirtualMachine) -> PyResult<()> {
110110
let cls = obj.class();
111111

112-
if let Some(attr) = objtype::class_get_attr(&cls, attr_name.as_str()) {
113-
if let Some(descriptor) = objtype::class_get_attr(&attr.class(), "__delete__") {
112+
if let Some(attr) = cls.get_attr(attr_name.as_str()) {
113+
if let Some(descriptor) = attr.class().get_attr("__delete__") {
114114
return vm.invoke(&descriptor, vec![attr, obj.clone()]).map(|_| ());
115115
}
116116
}
@@ -140,7 +140,7 @@ fn object_subclasshook(vm: &VirtualMachine, _args: PyFuncArgs) -> PyResult {
140140
}
141141

142142
pub fn object_dir(obj: PyObjectRef, vm: &VirtualMachine) -> PyResult<PyList> {
143-
let attributes: PyAttributes = objtype::get_attributes(obj.class());
143+
let attributes: PyAttributes = obj.class().get_attributes();
144144

145145
let dict = PyDictRef::from_attributes(attributes, vm)?;
146146

@@ -262,9 +262,8 @@ fn object_reduce(obj: PyObjectRef, proto: OptionalArg<usize>, vm: &VirtualMachin
262262

263263
fn object_reduce_ex(obj: PyObjectRef, proto: usize, vm: &VirtualMachine) -> PyResult {
264264
let cls = obj.class();
265-
if let Some(reduce) = objtype::class_get_attr(&cls, "__reduce__") {
266-
let object_reduce =
267-
objtype::class_get_attr(&vm.ctx.types.object_type, "__reduce__").unwrap();
265+
if let Some(reduce) = cls.get_attr("__reduce__") {
266+
let object_reduce = vm.ctx.types.object_type.get_attr("__reduce__").unwrap();
268267
if !reduce.is(&object_reduce) {
269268
return vm.invoke(&reduce, vec![]);
270269
}

vm/src/obj/objslice.rs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
use super::objint::PyInt;
2-
use super::objtype::{class_has_attr, PyClassRef};
2+
use super::objtype::PyClassRef;
33
use crate::function::{OptionalArg, PyFuncArgs};
44
use crate::pyobject::{
55
IdProtocol, PyClassImpl, PyContext, PyObjectRef, PyRef, PyResult, PyValue, TryIntoRef,
@@ -327,7 +327,7 @@ fn to_index_value(vm: &VirtualMachine, obj: &PyObjectRef) -> PyResult<Option<Big
327327
Ok(Some(val.as_bigint().clone()))
328328
} else {
329329
let cls = obj.class();
330-
if class_has_attr(&cls, "__index__") {
330+
if cls.has_attr("__index__") {
331331
let index_result = vm.call_method(obj, "__index__", vec![])?;
332332
if let Some(val) = index_result.payload::<PyInt>() {
333333
Ok(Some(val.as_bigint().clone()))

vm/src/obj/objtype.rs

Lines changed: 48 additions & 48 deletions
Original file line numberDiff line numberDiff line change
@@ -98,7 +98,7 @@ impl PyClassRef {
9898

9999
#[pymethod(magic)]
100100
fn dir(self, vm: &VirtualMachine) -> PyList {
101-
let attributes = get_attributes(self);
101+
let attributes = self.get_attributes();
102102
let attributes: Vec<PyObjectRef> = attributes
103103
.keys()
104104
.map(|k| vm.ctx.new_str(k.to_string()))
@@ -156,10 +156,10 @@ impl PyClassRef {
156156
vm_trace!("type.__getattribute__({:?}, {:?})", self, name);
157157
let mcl = self.class();
158158

159-
if let Some(attr) = class_get_attr(&mcl, &name) {
159+
if let Some(attr) = mcl.get_attr(&name) {
160160
let attr_class = attr.class();
161-
if class_has_attr(&attr_class, "__set__") {
162-
if let Some(ref descriptor) = class_get_attr(&attr_class, "__get__") {
161+
if attr_class.has_attr("__set__") {
162+
if let Some(ref descriptor) = attr_class.get_attr("__get__") {
163163
return vm.invoke(
164164
descriptor,
165165
vec![attr, self.into_object(), mcl.into_object()],
@@ -168,18 +168,18 @@ impl PyClassRef {
168168
}
169169
}
170170

171-
if let Some(attr) = class_get_attr(&self, &name) {
171+
if let Some(attr) = self.get_attr(&name) {
172172
let attr_class = attr.class();
173-
if let Some(ref descriptor) = class_get_attr(&attr_class, "__get__") {
173+
if let Some(ref descriptor) = attr_class.get_attr("__get__") {
174174
return vm.invoke(descriptor, vec![attr, vm.get_none(), self.into_object()]);
175175
}
176176
}
177177

178-
if let Some(cls_attr) = class_get_attr(&self, &name) {
178+
if let Some(cls_attr) = self.get_attr(&name) {
179179
Ok(cls_attr)
180-
} else if let Some(attr) = class_get_attr(&mcl, &name) {
180+
} else if let Some(attr) = mcl.get_attr(&name) {
181181
vm.call_get_descriptor(attr, self.into_object())
182-
} else if let Some(ref getter) = class_get_attr(&self, "__getattr__") {
182+
} else if let Some(ref getter) = self.get_attr("__getattr__") {
183183
vm.invoke(getter, vec![mcl.into_object(), name_ref.into_object()])
184184
} else {
185185
Err(vm.new_attribute_error(format!("{} has no attribute '{}'", self, name)))
@@ -193,8 +193,8 @@ impl PyClassRef {
193193
value: PyObjectRef,
194194
vm: &VirtualMachine,
195195
) -> PyResult<()> {
196-
if let Some(attr) = class_get_attr(&self.class(), attr_name.as_str()) {
197-
if let Some(ref descriptor) = class_get_attr(&attr.class(), "__set__") {
196+
if let Some(attr) = self.class().get_attr(attr_name.as_str()) {
197+
if let Some(ref descriptor) = attr.class().get_attr("__set__") {
198198
vm.invoke(descriptor, vec![attr, self.into_object(), value])?;
199199
return Ok(());
200200
}
@@ -208,15 +208,15 @@ impl PyClassRef {
208208

209209
#[pymethod(magic)]
210210
fn delattr(self, attr_name: PyStringRef, vm: &VirtualMachine) -> PyResult<()> {
211-
if let Some(attr) = class_get_attr(&self.class(), attr_name.as_str()) {
212-
if let Some(ref descriptor) = class_get_attr(&attr.class(), "__delete__") {
211+
if let Some(attr) = self.class().get_attr(attr_name.as_str()) {
212+
if let Some(ref descriptor) = attr.class().get_attr("__delete__") {
213213
return vm
214214
.invoke(descriptor, vec![attr, self.into_object()])
215215
.map(|_| ());
216216
}
217217
}
218218

219-
if class_get_attr(&self, attr_name.as_str()).is_some() {
219+
if self.get_attr(attr_name.as_str()).is_some() {
220220
self.attributes.borrow_mut().remove(attr_name.as_str());
221221
Ok(())
222222
} else {
@@ -397,48 +397,48 @@ fn type_dict_setter(
397397
))
398398
}
399399

400-
/// This is the internal get_attr implementation for fast lookup on a class.
401-
pub fn class_get_attr(class: &PyClassRef, attr_name: &str) -> Option<PyObjectRef> {
402-
flame_guard!(format!("class_get_attr({:?})", attr_name));
403-
404-
class
405-
.attributes
406-
.borrow()
407-
.get(attr_name)
408-
.cloned()
409-
.or_else(|| class_get_super_attr(class, attr_name))
410-
}
400+
impl PyClassRef {
401+
/// This is the internal get_attr implementation for fast lookup on a class.
402+
pub fn get_attr(&self, attr_name: &str) -> Option<PyObjectRef> {
403+
flame_guard!(format!("class_get_attr({:?})", attr_name));
411404

412-
pub fn class_get_super_attr(class: &PyClassRef, attr_name: &str) -> Option<PyObjectRef> {
413-
class
414-
.mro
415-
.iter()
416-
.find_map(|class| class.attributes.borrow().get(attr_name).cloned())
417-
}
405+
self.attributes
406+
.borrow()
407+
.get(attr_name)
408+
.cloned()
409+
.or_else(|| self.get_super_attr(attr_name))
410+
}
418411

419-
// This is the internal has_attr implementation for fast lookup on a class.
420-
pub fn class_has_attr(class: &PyClassRef, attr_name: &str) -> bool {
421-
class.attributes.borrow().contains_key(attr_name)
422-
|| class
423-
.mro
412+
pub fn get_super_attr(&self, attr_name: &str) -> Option<PyObjectRef> {
413+
self.mro
424414
.iter()
425-
.any(|c| c.attributes.borrow().contains_key(attr_name))
426-
}
415+
.find_map(|class| class.attributes.borrow().get(attr_name).cloned())
416+
}
417+
418+
// This is the internal has_attr implementation for fast lookup on a class.
419+
pub fn has_attr(&self, attr_name: &str) -> bool {
420+
self.attributes.borrow().contains_key(attr_name)
421+
|| self
422+
.mro
423+
.iter()
424+
.any(|c| c.attributes.borrow().contains_key(attr_name))
425+
}
427426

428-
pub fn get_attributes(cls: PyClassRef) -> PyAttributes {
429-
// Gather all members here:
430-
let mut attributes = PyAttributes::new();
427+
pub fn get_attributes(self) -> PyAttributes {
428+
// Gather all members here:
429+
let mut attributes = PyAttributes::new();
431430

432-
let mut base_classes: Vec<&PyClassRef> = cls.iter_mro().collect();
433-
base_classes.reverse();
431+
let mut base_classes: Vec<&PyClassRef> = self.iter_mro().collect();
432+
base_classes.reverse();
434433

435-
for bc in base_classes {
436-
for (name, value) in bc.attributes.borrow().iter() {
437-
attributes.insert(name.to_string(), value.clone());
434+
for bc in base_classes {
435+
for (name, value) in bc.attributes.borrow().iter() {
436+
attributes.insert(name.to_string(), value.clone());
437+
}
438438
}
439-
}
440439

441-
attributes
440+
attributes
441+
}
442442
}
443443

444444
fn take_next_base(mut bases: Vec<Vec<PyClassRef>>) -> Option<(PyClassRef, Vec<Vec<PyClassRef>>)> {

vm/src/stdlib/itertools.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -777,7 +777,7 @@ impl PyItertoolsTee {
777777
) -> PyResult<PyRef<PyTuple>> {
778778
let n = n.unwrap_or(2);
779779

780-
let copyable = if objtype::class_has_attr(&iterable.class(), "__copy__") {
780+
let copyable = if iterable.class().has_attr("__copy__") {
781781
vm.call_method(&iterable, "__copy__", PyFuncArgs::from(vec![]))?
782782
} else {
783783
PyItertoolsTee::from_iter(iterable, vm)?

vm/src/vm.rs

Lines changed: 11 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -624,7 +624,7 @@ impl VirtualMachine {
624624
if let Some(descr_get) = slots.borrow().descr_get.as_ref() {
625625
let cls = obj.class();
626626
descr_get(self, vec![attr, obj.clone(), cls.into_object()].into())
627-
} else if let Some(ref descriptor) = objtype::class_get_attr(&attr_class, "__get__") {
627+
} else if let Some(ref descriptor) = attr_class.get_attr("__get__") {
628628
let cls = obj.class();
629629
self.invoke(descriptor, vec![attr, obj.clone(), cls.into_object()])
630630
} else {
@@ -640,7 +640,7 @@ impl VirtualMachine {
640640

641641
// This is only used in the vm for magic methods, which use a greatly simplified attribute lookup.
642642
let cls = obj.class();
643-
match objtype::class_get_attr(&cls, method_name) {
643+
match cls.get_attr(method_name) {
644644
Some(func) => {
645645
vm_trace!(
646646
"vm.call_method {:?} {:?} {:?} -> {:?}",
@@ -666,7 +666,7 @@ impl VirtualMachine {
666666
let result = slot_call(self, args);
667667
self.trace_event(TraceEvent::Return)?;
668668
result
669-
} else if objtype::class_has_attr(&class, "__call__") {
669+
} else if class.has_attr("__call__") {
670670
let result = self.call_method(&callable, "__call__", args);
671671
result
672672
} else {
@@ -781,7 +781,7 @@ impl VirtualMachine {
781781
F: FnOnce() -> String,
782782
{
783783
let cls = obj.class();
784-
match objtype::class_get_attr(&cls, method_name) {
784+
match cls.get_attr(method_name) {
785785
Some(method) => self.call_get_descriptor(method, obj.clone()),
786786
None => Err(self.new_type_error(err_msg())),
787787
}
@@ -790,7 +790,7 @@ impl VirtualMachine {
790790
/// May return exception, if `__get__` descriptor raises one
791791
pub fn get_method(&self, obj: PyObjectRef, method_name: &str) -> Option<PyResult> {
792792
let cls = obj.class();
793-
let method = objtype::class_get_attr(&cls, method_name)?;
793+
let method = cls.get_attr(method_name)?;
794794
Some(self.call_get_descriptor(method, obj.clone()))
795795
}
796796

@@ -851,10 +851,10 @@ impl VirtualMachine {
851851
let name = name_str.as_str();
852852
let cls = obj.class();
853853

854-
if let Some(attr) = objtype::class_get_attr(&cls, &name) {
854+
if let Some(attr) = cls.get_attr(&name) {
855855
let attr_class = attr.class();
856-
if objtype::class_has_attr(&attr_class, "__set__") {
857-
if let Some(descriptor) = objtype::class_get_attr(&attr_class, "__get__") {
856+
if attr_class.has_attr("__set__") {
857+
if let Some(descriptor) = attr_class.get_attr("__get__") {
858858
return self
859859
.invoke(&descriptor, vec![attr, obj, cls.into_object()])
860860
.map(Some);
@@ -870,9 +870,9 @@ impl VirtualMachine {
870870

871871
if let Some(obj_attr) = attr {
872872
Ok(Some(obj_attr))
873-
} else if let Some(attr) = objtype::class_get_attr(&cls, &name) {
873+
} else if let Some(attr) = cls.get_attr(&name) {
874874
self.call_get_descriptor(attr, obj).map(Some)
875-
} else if let Some(getter) = objtype::class_get_attr(&cls, "__getattr__") {
875+
} else if let Some(getter) = cls.get_attr("__getattr__") {
876876
self.invoke(&getter, vec![obj, name_str.into_object()])
877877
.map(Some)
878878
} else {
@@ -881,8 +881,7 @@ impl VirtualMachine {
881881
}
882882

883883
pub fn is_callable(&self, obj: &PyObjectRef) -> bool {
884-
obj.class().slots.borrow().call.is_some()
885-
|| objtype::class_has_attr(&obj.class(), "__call__")
884+
obj.class().slots.borrow().call.is_some() || obj.class().has_attr("__call__")
886885
}
887886

888887
#[inline]

0 commit comments

Comments
 (0)