Skip to content

Commit 0045d74

Browse files
Merge pull request RustPython#189 from RustPython/getattr_bugfixes
type.__getattribute__ should be bound to type!
2 parents a389b55 + a2ce4c8 commit 0045d74

File tree

5 files changed

+28
-17
lines changed

5 files changed

+28
-17
lines changed

tests/snippets/class.py

+3-6
Original file line numberDiff line numberDiff line change
@@ -42,12 +42,9 @@ def kungfu(x):
4242

4343

4444
bar = Bar()
45-
bar.fubar(2)
4645

47-
# TODO: make below work:
48-
# Bar.fubar(2)
46+
bar.fubar(2)
47+
Bar.fubar(2)
4948

5049
bar.kungfu(3)
51-
# TODO: make below work:
52-
# Bar.kungfu(3)
53-
50+
Bar.kungfu(3)

vm/src/obj/objfunction.rs

+14-4
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
use super::super::pyobject::{
2-
AttributeProtocol, PyContext, PyFuncArgs, PyObject, PyObjectKind, PyObjectRef, PyResult,
3-
TypeProtocol,
2+
AttributeProtocol, IdProtocol, PyContext, PyFuncArgs, PyObject, PyObjectKind, PyObjectRef,
3+
PyResult, TypeProtocol,
44
};
55
use super::super::vm::VirtualMachine;
66
use super::objtype;
@@ -22,7 +22,17 @@ pub fn init(context: &PyContext) {
2222
}
2323

2424
fn bind_method(vm: &mut VirtualMachine, args: PyFuncArgs) -> PyResult {
25-
Ok(vm.new_bound_method(args.args[0].clone(), args.args[1].clone()))
25+
arg_check!(
26+
vm,
27+
args,
28+
required = [(function, None), (obj, None), (cls, None)]
29+
);
30+
31+
if obj.is(&vm.get_none()) && !cls.is(&obj.typ()) {
32+
Ok(function.clone())
33+
} else {
34+
Ok(vm.ctx.new_bound_method(function.clone(), obj.clone()))
35+
}
2636
}
2737

2838
fn member_get(vm: &mut VirtualMachine, mut args: PyFuncArgs) -> PyResult {
@@ -50,7 +60,7 @@ fn classmethod_get(vm: &mut VirtualMachine, args: PyFuncArgs) -> PyResult {
5060
match cls.get_attr("function") {
5161
Some(function) => {
5262
let py_obj = owner.clone();
53-
let py_method = vm.new_bound_method(function, py_obj);
63+
let py_method = vm.ctx.new_bound_method(function, py_obj);
5464
Ok(py_method)
5565
}
5666
None => {

vm/src/obj/objproperty.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -31,7 +31,7 @@ fn property_get(vm: &mut VirtualMachine, args: PyFuncArgs) -> PyResult {
3131

3232
match cls.get_attr("fget") {
3333
Some(getter) => {
34-
let py_method = vm.new_bound_method(getter, inst.clone());
34+
let py_method = vm.ctx.new_bound_method(getter, inst.clone());
3535
vm.invoke(py_method, PyFuncArgs::default())
3636
}
3737
None => {

vm/src/obj/objtype.rs

+2-1
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,7 @@ pub fn init(context: &PyContext) {
2929
type_type.set_attr("__class__", context.new_member_descriptor(type_new));
3030
type_type.set_attr("__repr__", context.new_rustfunc(type_repr));
3131
type_type.set_attr("__prepare__", context.new_rustfunc(type_prepare));
32+
type_type.set_attr("__getattribute__", context.new_rustfunc(type_getattribute));
3233
}
3334

3435
fn type_mro(vm: &mut VirtualMachine, args: PyFuncArgs) -> PyResult {
@@ -85,7 +86,7 @@ pub fn get_type_name(typ: &PyObjectRef) -> String {
8586
}
8687

8788
pub fn type_new(vm: &mut VirtualMachine, args: PyFuncArgs) -> PyResult {
88-
debug!("type.__new__{:?}", args);
89+
debug!("type.__new__ {:?}", args);
8990
if args.args.len() == 2 {
9091
arg_check!(
9192
vm,

vm/src/vm.rs

+8-5
Original file line numberDiff line numberDiff line change
@@ -92,10 +92,6 @@ impl VirtualMachine {
9292
self.ctx.none()
9393
}
9494

95-
pub fn new_bound_method(&self, function: PyObjectRef, object: PyObjectRef) -> PyObjectRef {
96-
self.ctx.new_bound_method(function, object)
97-
}
98-
9995
pub fn get_type(&self) -> PyObjectRef {
10096
self.ctx.type_type()
10197
}
@@ -202,7 +198,13 @@ impl VirtualMachine {
202198
let cls = obj.typ();
203199
match cls.get_attr(method_name) {
204200
Some(func) => {
205-
trace!("vm.call_method {:?} {:?} -> {:?}", obj, method_name, func);
201+
trace!(
202+
"vm.call_method {:?} {:?} {:?} -> {:?}",
203+
obj,
204+
cls,
205+
method_name,
206+
func
207+
);
206208
let wrapped = self.call_get_descriptor(func, obj.clone())?;
207209
self.invoke(wrapped, args)
208210
}
@@ -423,6 +425,7 @@ impl VirtualMachine {
423425

424426
// get_attribute should be used for full attribute access (usually from user code).
425427
pub fn get_attribute(&mut self, obj: PyObjectRef, attr_name: PyObjectRef) -> PyResult {
428+
trace!("vm.__getattribute__: {:?} {:?}", obj, attr_name);
426429
self.call_method(&obj, "__getattribute__", vec![attr_name])
427430
}
428431

0 commit comments

Comments
 (0)