diff --git a/bpython/autocomplete.py b/bpython/autocomplete.py index 6e3ddb900..3b64d0b2f 100644 --- a/bpython/autocomplete.py +++ b/bpython/autocomplete.py @@ -42,6 +42,9 @@ from bpython._py3compat import py3, try_decode from bpython.lazyre import LazyReCompile +if not py3: + from types import InstanceType, ClassType + # Autocomplete modes SIMPLE = 'simple' @@ -539,6 +542,9 @@ def attr_lookup(obj, expr, attr): words.remove('__abstractmethods__') except ValueError: pass + if not py3 and isinstance(obj, (InstanceType, ClassType)): + # Account for the __dict__ in an old-style class. + words.append('__dict__') matches = [] n = len(attr) diff --git a/bpython/test/test_autocomplete.py b/bpython/test/test_autocomplete.py index cad960e33..a6f2f153a 100644 --- a/bpython/test/test_autocomplete.py +++ b/bpython/test/test_autocomplete.py @@ -215,13 +215,42 @@ def method(self, x): pass +class OldStyleFoo: + a = 10 + + def __init__(self): + self.b = 20 + + def method(self, x): + pass + + +skip_old_style = unittest.skipIf(py3, + 'In Python 3 there are no old style classes') + + class TestAttrCompletion(unittest.TestCase): + @classmethod + def setUpClass(cls): + cls.com = autocomplete.AttrCompletion() def test_att_matches_found_on_instance(self): - com = autocomplete.AttrCompletion() - self.assertSetEqual(com.matches(2, 'a.', locals_={'a': Foo()}), + self.assertSetEqual(self.com.matches(2, 'a.', locals_={'a': Foo()}), set(['a.method', 'a.a', 'a.b'])) + @skip_old_style + def test_att_matches_found_on_old_style_instance(self): + self.assertSetEqual(self.com.matches(2, 'a.', + locals_={'a': OldStyleFoo()}), + set(['a.method', 'a.a', 'a.b'])) + self.assertIn(u'a.__dict__', + self.com.matches(3, 'a._', locals_={'a': OldStyleFoo()})) + + @skip_old_style + def test_att_matches_found_on_old_style_class_object(self): + self.assertIn(u'A.__dict__', + self.com.matches(3, 'A._', locals_={'A': OldStyleFoo})) + class TestMagicMethodCompletion(unittest.TestCase):