@@ -20,6 +20,7 @@ use super::objweakref::PyWeak;
2020#[ derive( Debug ) ]
2121pub struct PyClass {
2222 pub name : String ,
23+ pub bases : Vec < PyClassRef > ,
2324 pub mro : Vec < PyClassRef > ,
2425 pub subclasses : RefCell < Vec < PyWeak > > ,
2526 pub attributes : RefCell < PyAttributes > ,
@@ -94,6 +95,11 @@ impl PyClassRef {
9495 Err ( vm. new_attribute_error ( "read-only attribute" . to_string ( ) ) )
9596 }
9697
98+ fn bases ( self , vm : & VirtualMachine ) -> PyObjectRef {
99+ vm. ctx
100+ . new_tuple ( self . bases . iter ( ) . map ( |x| x. as_object ( ) . clone ( ) ) . collect ( ) )
101+ }
102+
97103 fn dir ( self , vm : & VirtualMachine ) -> PyList {
98104 let attributes = get_attributes ( self ) ;
99105 let attributes: Vec < PyObjectRef > = attributes
@@ -241,6 +247,7 @@ pub fn init(ctx: &PyContext) {
241247 . add_getter( PyClassRef :: mro)
242248 . add_setter( PyClassRef :: set_mro)
243249 . create( ) ,
250+ "__bases__" => ctx. new_property( PyClassRef :: bases) ,
244251 "__name__" => ctx. new_property( PyClassRef :: name) ,
245252 "__repr__" => ctx. new_rustfunc( PyClassRef :: repr) ,
246253 "__qualname__" => ctx. new_property( PyClassRef :: qualname) ,
@@ -290,8 +297,12 @@ fn type_new_slot(metatype: PyClassRef, args: PyFuncArgs, vm: &VirtualMachine) ->
290297
291298 let ( name, bases, dict) : ( PyStringRef , PyIterable < PyClassRef > , PyDictRef ) = args. bind ( vm) ?;
292299
293- let mut bases: Vec < PyClassRef > = bases. iter ( vm) ?. collect :: < Result < Vec < _ > , _ > > ( ) ?;
294- bases. push ( vm. ctx . object ( ) ) ;
300+ let bases: Vec < PyClassRef > = bases. iter ( vm) ?. collect :: < Result < Vec < _ > , _ > > ( ) ?;
301+ let bases = if bases. is_empty ( ) {
302+ vec ! [ vm. ctx. object( ) ]
303+ } else {
304+ bases
305+ } ;
295306
296307 let attributes = dict. to_attributes ( ) ;
297308
@@ -446,13 +457,10 @@ fn linearise_mro(mut bases: Vec<Vec<PyClassRef>>) -> Option<Vec<PyClassRef>> {
446457 if ( & bases) . iter ( ) . all ( Vec :: is_empty) {
447458 break ;
448459 }
449- match take_next_base ( bases) {
450- Some ( ( head, new_bases) ) => {
451- result. push ( head) ;
452- bases = new_bases;
453- }
454- None => return None ,
455- }
460+ let ( head, new_bases) = take_next_base ( bases) ?;
461+
462+ result. push ( head) ;
463+ bases = new_bases;
456464 }
457465 Some ( result)
458466}
@@ -468,6 +476,7 @@ pub fn new(
468476 let new_type = PyObject {
469477 payload : PyClass {
470478 name : String :: from ( name) ,
479+ bases,
471480 mro,
472481 subclasses : RefCell :: default ( ) ,
473482 attributes : RefCell :: new ( dict) ,
@@ -477,13 +486,16 @@ pub fn new(
477486 typ,
478487 }
479488 . into_ref ( ) ;
480- for base in bases {
489+
490+ let new_type: PyClassRef = new_type. downcast ( ) . unwrap ( ) ;
491+
492+ for base in & new_type. bases {
481493 base. subclasses
482494 . borrow_mut ( )
483- . push ( PyWeak :: downgrade ( & new_type) ) ;
495+ . push ( PyWeak :: downgrade ( new_type. as_object ( ) ) ) ;
484496 }
485497
486- Ok ( new_type. downcast ( ) . unwrap ( ) )
498+ Ok ( new_type)
487499}
488500
489501#[ cfg( test) ]
0 commit comments