@@ -618,23 +618,28 @@ 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)
642+ . unwrap_or ( Ok ( attr) )
638643 }
639644
640645 pub fn call_method < T > ( & self , obj : & PyObjectRef , method_name : & str , args : T ) -> PyResult
@@ -654,7 +659,7 @@ impl VirtualMachine {
654659 method_name,
655660 func
656661 ) ;
657- let wrapped = self . call_get_descriptor ( func, obj. clone ( ) ) ?;
662+ let wrapped = self . call_if_get_descriptor ( func, obj. clone ( ) ) ?;
658663 self . invoke ( & wrapped, args)
659664 }
660665 None => Err ( self . new_type_error ( format ! ( "Unsupported method: {}" , method_name) ) ) ,
@@ -787,7 +792,7 @@ impl VirtualMachine {
787792 {
788793 let cls = obj. class ( ) ;
789794 match cls. get_attr ( method_name) {
790- Some ( method) => self . call_get_descriptor ( method, obj. clone ( ) ) ,
795+ Some ( method) => self . call_if_get_descriptor ( method, obj. clone ( ) ) ,
791796 None => Err ( self . new_type_error ( err_msg ( ) ) ) ,
792797 }
793798 }
@@ -796,7 +801,7 @@ impl VirtualMachine {
796801 pub fn get_method ( & self , obj : PyObjectRef , method_name : & str ) -> Option < PyResult > {
797802 let cls = obj. class ( ) ;
798803 let method = cls. get_attr ( method_name) ?;
799- Some ( self . call_get_descriptor ( method, obj. clone ( ) ) )
804+ Some ( self . call_if_get_descriptor ( method, obj. clone ( ) ) )
800805 }
801806
802807 /// Calls a method on `obj` passing `arg`, if the method exists.
@@ -848,6 +853,7 @@ impl VirtualMachine {
848853 } )
849854 }
850855
856+ /// CPython _PyObject_GenericGetAttrWithDict
851857 pub fn generic_getattribute (
852858 & self ,
853859 obj : PyObjectRef ,
@@ -859,10 +865,8 @@ impl VirtualMachine {
859865 if let Some ( attr) = cls. get_attr ( & name) {
860866 let attr_class = attr. class ( ) ;
861867 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 ) ;
868+ if let Some ( r) = self . call_get_descriptor ( attr, obj. clone ( ) ) {
869+ return r. map ( Some ) ;
866870 }
867871 }
868872 }
@@ -876,7 +880,7 @@ impl VirtualMachine {
876880 if let Some ( obj_attr) = attr {
877881 Ok ( Some ( obj_attr) )
878882 } else if let Some ( attr) = cls. get_attr ( & name) {
879- self . call_get_descriptor ( attr, obj) . map ( Some )
883+ self . call_if_get_descriptor ( attr, obj) . map ( Some )
880884 } else if let Some ( getter) = cls. get_attr ( "__getattr__" ) {
881885 self . invoke ( & getter, vec ! [ obj, name_str. into_object( ) ] )
882886 . map ( Some )
0 commit comments