@@ -618,23 +618,27 @@ impl VirtualMachine {
618618 objbool:: boolval ( self , ret)
619619 }
620620
621- pub fn call_get_descriptor ( & self , attr : PyObjectRef , obj : PyObjectRef ) -> PyResult {
622- let attr_class = attr . class ( ) ;
623- let slots = attr_class . slots . borrow ( ) ;
624- if let Some ( descr_get) = slots. borrow ( ) . descr_get . as_ref ( ) {
621+ pub fn call_get_descriptor ( & self , descr : PyObjectRef , obj : PyObjectRef ) -> Option < PyResult > {
622+ let descr_class = descr . class ( ) ;
623+ let slots = descr_class . slots . borrow ( ) ;
624+ Some ( if let Some ( descr_get) = slots. borrow ( ) . descr_get . as_ref ( ) {
625625 let cls = obj. class ( ) ;
626626 descr_get (
627627 self ,
628- attr ,
628+ descr ,
629629 Some ( obj. clone ( ) ) ,
630630 OptionalArg :: Present ( cls. into_object ( ) ) ,
631631 )
632- } else if let Some ( ref descriptor) = attr_class . get_attr ( "__get__" ) {
632+ } else if let Some ( ref descriptor) = descr_class . get_attr ( "__get__" ) {
633633 let cls = obj. class ( ) ;
634- self . invoke ( descriptor, vec ! [ attr , obj. clone( ) , cls. into_object( ) ] )
634+ self . invoke ( descriptor, vec ! [ descr , obj. clone( ) , cls. into_object( ) ] )
635635 } else {
636- Ok ( attr)
637- }
636+ return None ;
637+ } )
638+ }
639+
640+ pub fn call_if_get_descriptor ( & self , attr : PyObjectRef , obj : PyObjectRef ) -> PyResult {
641+ self . call_get_descriptor ( attr. clone ( ) , obj) . unwrap_or ( Ok ( attr) )
638642 }
639643
640644 pub fn call_method < T > ( & self , obj : & PyObjectRef , method_name : & str , args : T ) -> PyResult
@@ -654,7 +658,7 @@ impl VirtualMachine {
654658 method_name,
655659 func
656660 ) ;
657- let wrapped = self . call_get_descriptor ( func, obj. clone ( ) ) ?;
661+ let wrapped = self . call_if_get_descriptor ( func, obj. clone ( ) ) ?;
658662 self . invoke ( & wrapped, args)
659663 }
660664 None => Err ( self . new_type_error ( format ! ( "Unsupported method: {}" , method_name) ) ) ,
@@ -787,7 +791,7 @@ impl VirtualMachine {
787791 {
788792 let cls = obj. class ( ) ;
789793 match cls. get_attr ( method_name) {
790- Some ( method) => self . call_get_descriptor ( method, obj. clone ( ) ) ,
794+ Some ( method) => self . call_if_get_descriptor ( method, obj. clone ( ) ) ,
791795 None => Err ( self . new_type_error ( err_msg ( ) ) ) ,
792796 }
793797 }
@@ -796,7 +800,7 @@ impl VirtualMachine {
796800 pub fn get_method ( & self , obj : PyObjectRef , method_name : & str ) -> Option < PyResult > {
797801 let cls = obj. class ( ) ;
798802 let method = cls. get_attr ( method_name) ?;
799- Some ( self . call_get_descriptor ( method, obj. clone ( ) ) )
803+ Some ( self . call_if_get_descriptor ( method, obj. clone ( ) ) )
800804 }
801805
802806 /// Calls a method on `obj` passing `arg`, if the method exists.
@@ -848,6 +852,7 @@ impl VirtualMachine {
848852 } )
849853 }
850854
855+ /// CPython _PyObject_GenericGetAttrWithDict
851856 pub fn generic_getattribute (
852857 & self ,
853858 obj : PyObjectRef ,
@@ -859,10 +864,8 @@ impl VirtualMachine {
859864 if let Some ( attr) = cls. get_attr ( & name) {
860865 let attr_class = attr. class ( ) ;
861866 if attr_class. has_attr ( "__set__" ) {
862- if let Some ( descriptor) = attr_class. get_attr ( "__get__" ) {
863- return self
864- . invoke ( & descriptor, vec ! [ attr, obj, cls. into_object( ) ] )
865- . map ( Some ) ;
867+ if let Some ( r) = self . call_get_descriptor ( attr, obj. clone ( ) ) {
868+ return r. map ( Some ) ;
866869 }
867870 }
868871 }
@@ -876,7 +879,7 @@ impl VirtualMachine {
876879 if let Some ( obj_attr) = attr {
877880 Ok ( Some ( obj_attr) )
878881 } else if let Some ( attr) = cls. get_attr ( & name) {
879- self . call_get_descriptor ( attr, obj) . map ( Some )
882+ self . call_if_get_descriptor ( attr, obj) . map ( Some )
880883 } else if let Some ( getter) = cls. get_attr ( "__getattr__" ) {
881884 self . invoke ( & getter, vec ! [ obj, name_str. into_object( ) ] )
882885 . map ( Some )
0 commit comments