diff -r c2d7a30a5dcb Lib/rlcompleter.py --- a/Lib/rlcompleter.py Wed Oct 29 13:33:05 2014 +0000 +++ b/Lib/rlcompleter.py Wed Oct 29 13:46:32 2014 +0000 @@ -110,7 +110,7 @@ for word, val in nspace.items(): if word[:n] == text and word != "__builtins__": matches.append(self._callable_postfix(val, word)) - return matches + return list(set(matches)) def attr_matches(self, text): """Compute matches when text contains a dot. @@ -135,13 +135,13 @@ return [] # get the content of the object, except __builtins__ - words = dir(thisobject) + words = set(dir(thisobject)) if "__builtins__" in words: words.remove("__builtins__") if hasattr(thisobject, '__class__'): - words.append('__class__') - words.extend(get_class_members(thisobject.__class__)) + words.add('__class__') + words.update(get_class_members(thisobject.__class__)) matches = [] n = len(attr) for word in words: @@ -153,10 +153,10 @@ return matches def get_class_members(klass): - ret = dir(klass) + ret = set(dir(klass)) if hasattr(klass,'__bases__'): for base in klass.__bases__: - ret = ret + get_class_members(base) + ret.update(get_class_members(base)) return ret try: diff -r c2d7a30a5dcb Lib/test/test_rlcompleter.py --- a/Lib/test/test_rlcompleter.py Wed Oct 29 13:33:05 2014 +0000 +++ b/Lib/test/test_rlcompleter.py Wed Oct 29 13:46:32 2014 +0000 @@ -50,9 +50,9 @@ def test_attr_matches(self): # test with builtins namespace - self.assertEqual(self.stdcompleter.attr_matches('str.s'), - ['str.{}('.format(x) for x in dir(str) - if x.startswith('s')]) + self.assertEqual(sorted(self.stdcompleter.attr_matches('str.s')), + sorted(['str.{}('.format(x) for x in dir(str) + if x.startswith('s')])) self.assertEqual(self.stdcompleter.attr_matches('tuple.foospamegg'), []) # test with a customized namespace @@ -63,21 +63,33 @@ CompleteMe.me = CompleteMe self.assertEqual(self.completer.attr_matches('CompleteMe.me.me.sp'), ['CompleteMe.me.me.spam']) - self.assertEqual(self.completer.attr_matches('egg.s'), - ['egg.{}('.format(x) for x in dir(str) - if x.startswith('s')]) + self.assertEqual(sorted(self.completer.attr_matches('egg.s')), + sorted(['egg.{}('.format(x) for x in dir(str) + if x.startswith('s')])) # test that we don't return to many results (issue22141) class A(object): def foo(): pass def foobar(): pass c = rlcompleter.Completer(locals()) - self.assertEqual(c.complete("A.foo", 0), 'A.foo(') - self.assertEqual(c.complete("A.foo", 1), 'A.foobar(') - self.assertEqual(c.complete("A.foo", 2), None) + self.assertIn(c.complete("A.foo", 0), ['A.foo(', 'A.foobar(']) + self.assertIn(c.complete("A.foo", 1), ['A.foo(', 'A.foobar(']) + self.assertIsNone(c.complete("A.foo", 2)) self.assertEqual(c.complete("A.foo(", 0), 'A.foo(') - self.assertEqual(c.complete("A.foo(", 1), None) + self.assertIsNone(c.complete("A.foo(", 1)) + def test_inheritance_matching(self): + # test that matches are unique: see issue22143 + class A(object): + def foo(): pass + class B(A): + pass + b = B() + c = rlcompleter.Completer(locals()) + self.assertEqual(c.complete("b.foo", 0), 'b.foo(') + self.assertIsNone(c.complete("b.foo", 1)) + + def test_main(): support.run_unittest(TestRlcompleter)

AltStyle によって変換されたページ (->オリジナル) /