Merge pull request #189 from RustPython/getattr_bugfixes

type.__getattribute__ should be bound to type!
This commit is contained in:
Windel Bouwman
2018-11-04 22:50:27 +01:00
committed by GitHub
5 changed files with 28 additions and 17 deletions

View File

@@ -42,12 +42,9 @@ class Bar:
bar = Bar()
bar.fubar(2)
# TODO: make below work:
# Bar.fubar(2)
bar.fubar(2)
Bar.fubar(2)
bar.kungfu(3)
# TODO: make below work:
# Bar.kungfu(3)
Bar.kungfu(3)

View File

@@ -1,6 +1,6 @@
use super::super::pyobject::{
AttributeProtocol, PyContext, PyFuncArgs, PyObject, PyObjectKind, PyObjectRef, PyResult,
TypeProtocol,
AttributeProtocol, IdProtocol, PyContext, PyFuncArgs, PyObject, PyObjectKind, PyObjectRef,
PyResult, TypeProtocol,
};
use super::super::vm::VirtualMachine;
use super::objtype;
@@ -22,7 +22,17 @@ pub fn init(context: &PyContext) {
}
fn bind_method(vm: &mut VirtualMachine, args: PyFuncArgs) -> PyResult {
Ok(vm.new_bound_method(args.args[0].clone(), args.args[1].clone()))
arg_check!(
vm,
args,
required = [(function, None), (obj, None), (cls, None)]
);
if obj.is(&vm.get_none()) && !cls.is(&obj.typ()) {
Ok(function.clone())
} else {
Ok(vm.ctx.new_bound_method(function.clone(), obj.clone()))
}
}
fn member_get(vm: &mut VirtualMachine, mut args: PyFuncArgs) -> PyResult {
@@ -50,7 +60,7 @@ fn classmethod_get(vm: &mut VirtualMachine, args: PyFuncArgs) -> PyResult {
match cls.get_attr("function") {
Some(function) => {
let py_obj = owner.clone();
let py_method = vm.new_bound_method(function, py_obj);
let py_method = vm.ctx.new_bound_method(function, py_obj);
Ok(py_method)
}
None => {

View File

@@ -31,7 +31,7 @@ fn property_get(vm: &mut VirtualMachine, args: PyFuncArgs) -> PyResult {
match cls.get_attr("fget") {
Some(getter) => {
let py_method = vm.new_bound_method(getter, inst.clone());
let py_method = vm.ctx.new_bound_method(getter, inst.clone());
vm.invoke(py_method, PyFuncArgs::default())
}
None => {

View File

@@ -29,6 +29,7 @@ pub fn init(context: &PyContext) {
type_type.set_attr("__class__", context.new_member_descriptor(type_new));
type_type.set_attr("__repr__", context.new_rustfunc(type_repr));
type_type.set_attr("__prepare__", context.new_rustfunc(type_prepare));
type_type.set_attr("__getattribute__", context.new_rustfunc(type_getattribute));
}
fn type_mro(vm: &mut VirtualMachine, args: PyFuncArgs) -> PyResult {
@@ -85,7 +86,7 @@ pub fn get_type_name(typ: &PyObjectRef) -> String {
}
pub fn type_new(vm: &mut VirtualMachine, args: PyFuncArgs) -> PyResult {
debug!("type.__new__{:?}", args);
debug!("type.__new__ {:?}", args);
if args.args.len() == 2 {
arg_check!(
vm,

View File

@@ -92,10 +92,6 @@ impl VirtualMachine {
self.ctx.none()
}
pub fn new_bound_method(&self, function: PyObjectRef, object: PyObjectRef) -> PyObjectRef {
self.ctx.new_bound_method(function, object)
}
pub fn get_type(&self) -> PyObjectRef {
self.ctx.type_type()
}
@@ -202,7 +198,13 @@ impl VirtualMachine {
let cls = obj.typ();
match cls.get_attr(method_name) {
Some(func) => {
trace!("vm.call_method {:?} {:?} -> {:?}", obj, method_name, func);
trace!(
"vm.call_method {:?} {:?} {:?} -> {:?}",
obj,
cls,
method_name,
func
);
let wrapped = self.call_get_descriptor(func, obj.clone())?;
self.invoke(wrapped, args)
}
@@ -423,6 +425,7 @@ impl VirtualMachine {
// get_attribute should be used for full attribute access (usually from user code).
pub fn get_attribute(&mut self, obj: PyObjectRef, attr_name: PyObjectRef) -> PyResult {
trace!("vm.__getattribute__: {:?} {:?}", obj, attr_name);
self.call_method(&obj, "__getattribute__", vec![attr_name])
}