@@ -60,51 +60,50 @@ def newsuper(typ=_SENTINEL, type_or_obj=_SENTINEL, framedepth=1):
6060 raise RuntimeError ('super() used in a function with no args' )
6161
6262 try :
63- # Get the MRO so we can crawl it.
64- mro = type_or_obj . __mro__
65- except ( AttributeError , RuntimeError ): # see issue #160
63+ typ = find_owner ( type_or_obj , f . f_code )
64+ except ( AttributeError , RuntimeError , TypeError ):
65+ # see issues #160, #267
6666 try :
67- mro = type_or_obj .__class__ . __mro__
67+ typ = find_owner ( type_or_obj .__class__ , f . f_code )
6868 except AttributeError :
69- raise RuntimeError ('super() used with a non-newstyle class' )
70-
71- # A ``for...else`` block? Yes! It's odd, but useful.
72- # If unfamiliar with for...else, see:
73- #
74- # http://psung.blogspot.com/2007/12/for-else-in-python.html
75- for typ in mro :
76- # Find the class that owns the currently-executing method.
77- for meth in typ .__dict__ .values ():
78- # Drill down through any wrappers to the underlying func.
79- # This handles e.g. classmethod() and staticmethod().
80- try :
81- while not isinstance (meth ,FunctionType ):
82- if isinstance (meth , property ):
83- # Calling __get__ on the property will invoke
84- # user code which might throw exceptions or have
85- # side effects
86- meth = meth .fget
87- else :
88- try :
89- meth = meth .__func__
90- except AttributeError :
91- meth = meth .__get__ (type_or_obj , typ )
92- except (AttributeError , TypeError ):
93- continue
94- if meth .func_code is f .f_code :
95- break # Aha! Found you.
96- else :
97- continue # Not found! Move onto the next class in MRO.
98- break # Found! Break out of the search loop.
99- else :
100- raise RuntimeError ('super() called outside a method' )
69+ raise RuntimeError ('super() used with an old-style class' )
70+ except TypeError :
71+ raise RuntimeError ('super() called outside a method' )
10172
10273 # Dispatch to builtin super().
10374 if type_or_obj is not _SENTINEL :
10475 return _builtin_super (typ , type_or_obj )
10576 return _builtin_super (typ )
10677
10778
79+ def find_owner (cls , code ):
80+ '''Find the class that owns the currently-executing method.
81+ '''
82+ for typ in cls .__mro__ :
83+ for meth in typ .__dict__ .values ():
84+ # Drill down through any wrappers to the underlying func.
85+ # This handles e.g. classmethod() and staticmethod().
86+ try :
87+ while not isinstance (meth ,FunctionType ):
88+ if isinstance (meth , property ):
89+ # Calling __get__ on the property will invoke
90+ # user code which might throw exceptions or have
91+ # side effects
92+ meth = meth .fget
93+ else :
94+ try :
95+ meth = meth .__func__
96+ except AttributeError :
97+ meth = meth .__get__ (cls , typ )
98+ except (AttributeError , TypeError ):
99+ continue
100+ if meth .func_code is code :
101+ return typ # Aha! Found you.
102+ # Not found! Move onto the next class in MRO.
103+
104+ raise TypeError
105+
106+
108107def superm (* args , ** kwds ):
109108 f = sys ._getframe (1 )
110109 nm = f .f_code .co_name
0 commit comments