@@ -329,10 +329,11 @@ def attr_matches(self, text):
329329 m = re .match (r"(\w+(\.\w+)*)\.(\w*)" , text )
330330 if not m :
331331 return []
332+
332333 expr , attr = m .group (1 , 3 )
333334 obj = eval (expr , self .interp .locals )
334335 type_ = type (obj )
335-
336+ f = None
336337 # Dark magic:
337338 if type_ != types .InstanceType :
338339 f = getattr (type_ , '__getattribute__' , None )
@@ -344,16 +345,24 @@ def attr_matches(self, text):
344345 f = None
345346 # /Dark magic
346347
348+ try :
349+ matches = self .attr_lookup (obj , expr , attr )
350+ finally :
351+ # Dark magic:
352+ if f is not None :
353+ setattr (type_ , '__getattribute__' , f )
354+ # /Dark magic
355+ return matches
356+
357+ def attr_lookup (self , obj , expr , attr ):
358+ """Second half of original attr_matches method factored out so it can
359+ be wrapped in a safe try/finally block in case anything bad happens to
360+ restore the original __getattribute__ method."""
347361 words = dir (obj )
348362 if hasattr (obj , '__class__' ):
349363 words .append ('__class__' )
350364 words = words + rlcompleter .get_class_members (obj .__class__ )
351365
352- # Dark magic:
353- if f is not None :
354- setattr (type_ , '__getattribute__' , f )
355- # /Dark magic
356-
357366 matches = []
358367 n = len (attr )
359368 for word in words :
0 commit comments