@@ -6,7 +6,9 @@ https://github.com/python/cpython/blob/50b48572d9a90c5bb36e2bef6179548ea927a35a/
6
6
7
7
*/
8
8
9
+ use crate :: frame:: NameProtocol ;
9
10
use crate :: function:: PyFuncArgs ;
11
+ use crate :: obj:: objstr;
10
12
use crate :: obj:: objtype:: PyClass ;
11
13
use crate :: pyobject:: {
12
14
DictProtocol , PyContext , PyObject , PyObjectRef , PyResult , PyValue , TypeProtocol ,
@@ -18,6 +20,7 @@ use super::objtype;
18
20
#[ derive( Debug ) ]
19
21
pub struct PySuper {
20
22
obj : PyObjectRef ,
23
+ typ : PyObjectRef ,
21
24
}
22
25
23
26
impl PyValue for PySuper {
@@ -67,15 +70,20 @@ fn super_getattribute(vm: &VirtualMachine, args: PyFuncArgs) -> PyResult {
67
70
) ;
68
71
69
72
let inst = super_obj. payload :: < PySuper > ( ) . unwrap ( ) . obj . clone ( ) ;
73
+ let typ = super_obj. payload :: < PySuper > ( ) . unwrap ( ) . typ . clone ( ) ;
70
74
71
- match inst . typ ( ) . payload :: < PyClass > ( ) {
75
+ match typ. payload :: < PyClass > ( ) {
72
76
Some ( PyClass { ref mro, .. } ) => {
73
77
for class in mro {
74
78
if let Ok ( item) = vm. get_attribute ( class. as_object ( ) . clone ( ) , name_str. clone ( ) ) {
75
79
return Ok ( vm. ctx . new_bound_method ( item, inst. clone ( ) ) ) ;
76
80
}
77
81
}
78
- Err ( vm. new_attribute_error ( format ! ( "{} has no attribute '{}'" , inst, name_str) ) )
82
+ Err ( vm. new_attribute_error ( format ! (
83
+ "{} has no attribute '{}'" ,
84
+ inst,
85
+ objstr:: get_value( name_str)
86
+ ) ) )
79
87
}
80
88
_ => panic ! ( "not Class" ) ,
81
89
}
@@ -98,9 +106,13 @@ fn super_new(vm: &VirtualMachine, args: PyFuncArgs) -> PyResult {
98
106
let py_type = if let Some ( ty) = py_type {
99
107
ty. clone ( )
100
108
} else {
101
- match vm. get_locals ( ) . get_item ( "self" ) {
102
- Some ( obj) => obj. typ ( ) . clone ( ) ,
103
- _ => panic ! ( "No self" ) ,
109
+ match vm. current_scope ( ) . load_cell ( vm, "__class__" ) {
110
+ Some ( obj) => obj. clone ( ) ,
111
+ _ => {
112
+ return Err ( vm. new_type_error (
113
+ "super must be called with 1 argument or from inside class method" . to_string ( ) ,
114
+ ) ) ;
115
+ }
104
116
}
105
117
} ;
106
118
@@ -117,9 +129,19 @@ fn super_new(vm: &VirtualMachine, args: PyFuncArgs) -> PyResult {
117
129
let py_obj = if let Some ( obj) = py_obj {
118
130
obj. clone ( )
119
131
} else {
120
- match vm. get_locals ( ) . get_item ( "self" ) {
121
- Some ( obj) => obj,
122
- _ => panic ! ( "No self" ) ,
132
+ let frame = vm. current_frame ( ) ;
133
+ if let Some ( first_arg) = frame. code . arg_names . get ( 0 ) {
134
+ match vm. get_locals ( ) . get_item ( first_arg) {
135
+ Some ( obj) => obj. clone ( ) ,
136
+ _ => {
137
+ return Err ( vm
138
+ . new_type_error ( format ! ( "super arguement {} was not supplied" , first_arg) ) ) ;
139
+ }
140
+ }
141
+ } else {
142
+ return Err ( vm. new_type_error (
143
+ "super must be called with 1 argument or from inside class method" . to_string ( ) ,
144
+ ) ) ;
123
145
}
124
146
} ;
125
147
@@ -130,5 +152,11 @@ fn super_new(vm: &VirtualMachine, args: PyFuncArgs) -> PyResult {
130
152
) ) ;
131
153
}
132
154
133
- Ok ( PyObject :: new ( PySuper { obj : py_obj } , cls. clone ( ) ) )
155
+ Ok ( PyObject :: new (
156
+ PySuper {
157
+ obj : py_obj,
158
+ typ : py_type,
159
+ } ,
160
+ cls. clone ( ) ,
161
+ ) )
134
162
}
0 commit comments