Skip to content

Commit 674c3bf

Browse files
committed
Add workaround for old-style class with broken __getattr__ (fixes #536)
Signed-off-by: Sebastian Ramacher <sebastian+dev@ramacher.at>
1 parent e74bbd2 commit 674c3bf

File tree

2 files changed

+20
-3
lines changed

2 files changed

+20
-3
lines changed

bpython/autocomplete.py

Lines changed: 18 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -296,7 +296,7 @@ def attr_lookup(self, obj, expr, attr):
296296
"""Second half of original attr_matches method factored out so it can
297297
be wrapped in a safe try/finally block in case anything bad happens to
298298
restore the original __getattribute__ method."""
299-
words = dir(obj)
299+
words = self.list_attributes(obj)
300300
if hasattr(obj, '__class__'):
301301
words.append('__class__')
302302
words = words + rlcompleter.get_class_members(obj.__class__)
@@ -317,6 +317,23 @@ def attr_lookup(self, obj, expr, attr):
317317
matches.append("%s.%s" % (expr, word))
318318
return matches
319319

320+
if py3:
321+
def list_attributes(self, obj):
322+
return dir(obj)
323+
else:
324+
def list_attributes(self, obj):
325+
if isinstance(obj, InstanceType):
326+
try:
327+
return dir(obj)
328+
except Exception:
329+
# This is a case where we can not prevent user code from
330+
# running. We return a default list attributes on error
331+
# instead. (#536)
332+
return ['__doc__', '__module__']
333+
else:
334+
return dir(obj)
335+
336+
320337

321338
class DictKeyCompletion(BaseCompletionType):
322339

bpython/test/test_autocomplete.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -252,14 +252,14 @@ def test_att_matches_found_on_old_style_class_object(self):
252252
self.com.matches(3, 'A._', locals_={'A': OldStyleFoo}))
253253

254254
@skip_old_style
255-
@unittest.expectedFailure
256255
def test_issue536(self):
257256
class OldStyleWithBrokenGetAttr:
258257
def __getattr__(self, attr):
259258
raise Exception()
260259

261260
locals_ = {'a': OldStyleWithBrokenGetAttr()}
262-
self.com.matches(2, 'a.', locals_=locals_)
261+
self.assertIn(u'a.__module__',
262+
self.com.matches(3, 'a._', locals_=locals_))
263263

264264

265265
class TestMagicMethodCompletion(unittest.TestCase):

0 commit comments

Comments
 (0)