From ce5bb72ed05bd8f3bf074dc6f2604d24af5c0442 Mon Sep 17 00:00:00 2001 From: Windel Bouwman Date: Mon, 5 Nov 2018 20:46:32 +0100 Subject: [PATCH] Minor delta on super class. --- tests/snippets/class.py | 25 +++++++++++++++++++++- vm/src/obj/objsuper.rs | 46 +++++++++++++++++++++++++++++++++++++++-- vm/src/pyobject.rs | 2 +- 3 files changed, 69 insertions(+), 4 deletions(-) diff --git a/tests/snippets/class.py b/tests/snippets/class.py index f5dce2425..0da77a4db 100644 --- a/tests/snippets/class.py +++ b/tests/snippets/class.py @@ -8,12 +8,14 @@ class Foo: y = 7 + foo = Foo(5) assert foo.y == Foo.y assert foo.x == 5 assert foo.square() == 25 + class Fubar: def __init__(self): self.x = 100 @@ -31,6 +33,12 @@ assert f.foo == 101 class Bar: + def __init__(self, x): + self.x = x + + def get_x(self): + return self.x + @classmethod def fubar(cls, x): assert cls is Bar @@ -41,10 +49,25 @@ class Bar: assert x == 3 -bar = Bar() +bar = Bar(42) bar.fubar(2) Bar.fubar(2) bar.kungfu(3) Bar.kungfu(3) + + +class Bar2(Bar): + def __init__(self): + super().__init__(101) + + +# TODO: make this work: +# bar2 = Bar2() +# assert bar2.get_x() == 101 + +a = super(int, 2) +assert isinstance(a, super) +assert type(a) is super + diff --git a/vm/src/obj/objsuper.rs b/vm/src/obj/objsuper.rs index a4980474e..c430dc95d 100644 --- a/vm/src/obj/objsuper.rs +++ b/vm/src/obj/objsuper.rs @@ -1,5 +1,9 @@ /*! Python `super` class. +See also: + +https://github.com/python/cpython/blob/50b48572d9a90c5bb36e2bef6179548ea927a35a/Objects/typeobject.c#L7663 + */ use super::super::pyobject::{ @@ -15,9 +19,47 @@ pub fn init(context: &PyContext) { fn super_init(vm: &mut VirtualMachine, args: PyFuncArgs) -> PyResult { trace!("super.__init__ {:?}", args.args); - arg_check!(vm, args, required = [(_inst, None)]); + arg_check!( + vm, + args, + required = [(inst, None)], + optional = [(py_type, None), (py_obj, None)] + ); - // TODO: implement complex logic here.... + // Get the type: + let py_type = if let Some(ty) = py_type { + ty.clone() + } else { + // TODO: implement complex logic here.... + vm.get_none() + }; + + // Check type argument: + if !objtype::isinstance(&py_type, &vm.get_type()) { + let type_name = objtype::get_type_name(&py_type.typ()); + return Err(vm.new_type_error(format!( + "super() argument 1 must be type, not {}", + type_name + ))); + } + + // Get the bound object: + let py_obj = if let Some(obj) = py_obj { + obj.clone() + } else { + vm.get_none() + }; + + // Check obj type: + if !(objtype::isinstance(&py_obj, &py_type) || objtype::issubclass(&py_obj, &py_type)) { + return Err(vm.new_type_error(format!( + "super(type, obj): obj must be an instance or subtype of type" + ))); + } + + // TODO: how to store those types? + inst.set_attr("type", py_type); + inst.set_attr("obj", py_obj); Ok(vm.get_none()) } diff --git a/vm/src/pyobject.rs b/vm/src/pyobject.rs index 1ff5e9f2a..00a119e74 100644 --- a/vm/src/pyobject.rs +++ b/vm/src/pyobject.rs @@ -150,7 +150,7 @@ impl PyContext { let staticmethod_type = create_type("staticmethod", &type_type, &object_type, &dict_type); let function_type = create_type("function", &type_type, &object_type, &dict_type); let property_type = create_type("property", &type_type, &object_type, &dict_type); - let super_type = create_type("property", &type_type, &object_type, &dict_type); + let super_type = create_type("super", &type_type, &object_type, &dict_type); let generator_type = create_type("generator", &type_type, &object_type, &dict_type); let bound_method_type = create_type("method", &type_type, &object_type, &dict_type); let member_descriptor_type =