1
1
use super :: objdict:: PyDictRef ;
2
2
use super :: objlist:: PyList ;
3
3
use super :: objstr:: PyStringRef ;
4
- use super :: objtype;
5
- use crate :: function:: PyFuncArgs ;
4
+ use super :: objtype:: { self , PyClassRef } ;
5
+ use crate :: function:: { OptionalArg , PyFuncArgs } ;
6
6
use crate :: obj:: objproperty:: PropertyBuilder ;
7
- use crate :: obj:: objtype:: PyClassRef ;
8
7
use crate :: pyhash;
9
8
use crate :: pyobject:: {
10
9
IdProtocol , ItemProtocol , PyAttributes , PyContext , PyObject , PyObjectRef , PyResult , PyValue ,
@@ -186,6 +185,8 @@ pub fn init(context: &PyContext) {
186
185
"__format__" => context. new_rustfunc( object_format) ,
187
186
"__getattribute__" => context. new_rustfunc( object_getattribute) ,
188
187
"__subclasshook__" => context. new_classmethod( object_subclasshook) ,
188
+ "__reduce__" => context. new_rustfunc( object_reduce) ,
189
+ "__reduce_ex__" => context. new_rustfunc( object_reduce_ex) ,
189
190
"__doc__" => context. new_str( object_doc. to_string( ) ) ,
190
191
} ) ;
191
192
}
@@ -211,7 +212,7 @@ fn object_dict(object: PyObjectRef, vm: &VirtualMachine) -> PyResult<PyDictRef>
211
212
if let Some ( ref dict) = object. dict {
212
213
Ok ( dict. clone ( ) )
213
214
} else {
214
- Err ( vm. new_type_error ( "TypeError: no dictionary.". to_string ( ) ) )
215
+ Err ( vm. new_attribute_error ( " no dictionary.". to_string ( ) ) )
215
216
}
216
217
}
217
218
@@ -230,3 +231,31 @@ fn object_getattribute(obj: PyObjectRef, name: PyStringRef, vm: &VirtualMachine)
230
231
vm. generic_getattribute ( obj. clone ( ) , name. clone ( ) ) ?
231
232
. ok_or_else ( || vm. new_attribute_error ( format ! ( "{} has no attribute '{}'" , obj, name) ) )
232
233
}
234
+
235
+ fn object_reduce ( obj : PyObjectRef , proto : OptionalArg < usize > , vm : & VirtualMachine ) -> PyResult {
236
+ common_reduce ( obj, proto. unwrap_or ( 0 ) , vm)
237
+ }
238
+
239
+ fn object_reduce_ex ( obj : PyObjectRef , proto : usize , vm : & VirtualMachine ) -> PyResult {
240
+ let cls = obj. class ( ) ;
241
+ if let Some ( reduce) = objtype:: class_get_attr ( & cls, "__reduce__" ) {
242
+ let object_reduce =
243
+ objtype:: class_get_attr ( & vm. ctx . types . object_type , "__reduce__" ) . unwrap ( ) ;
244
+ if !reduce. is ( & object_reduce) {
245
+ return vm. invoke ( & reduce, vec ! [ ] ) ;
246
+ }
247
+ }
248
+ common_reduce ( obj, proto, vm)
249
+ }
250
+
251
+ fn common_reduce ( obj : PyObjectRef , proto : usize , vm : & VirtualMachine ) -> PyResult {
252
+ if proto >= 2 {
253
+ let reducelib = vm. import ( "__reducelib" , & [ ] , 0 ) ?;
254
+ let reduce_2 = vm. get_attribute ( reducelib, "reduce_2" ) ?;
255
+ vm. invoke ( & reduce_2, vec ! [ obj] )
256
+ } else {
257
+ let copyreg = vm. import ( "copyreg" , & [ ] , 0 ) ?;
258
+ let reduce_ex = vm. get_attribute ( copyreg, "_reduce_ex" ) ?;
259
+ vm. invoke ( & reduce_ex, vec ! [ obj, vm. new_int( proto) ] )
260
+ }
261
+ }
0 commit comments