# HG changeset patch # Parent 284187f3a7837a191d6fd5eb73914deafd72f023 Issue #. . .: Make rlcompleter avoid duplicate global names diff -r 284187f3a783 Lib/rlcompleter.py --- a/Lib/rlcompleter.py Wed Nov 18 12:44:59 2015 -0500 +++ b/Lib/rlcompleter.py Thu Nov 19 01:59:39 2015 +0000 @@ -103,9 +103,11 @@ """ import keyword matches = [] + seen = set() n = len(text) for word in keyword.kwlist: if word[:n] == text: + seen.add(word) if word in {'finally', 'try'}: word = word + ':' elif word not in {'False', 'None', 'True', @@ -113,9 +115,11 @@ 'else'}: word = word + ' ' matches.append(word) - for nspace in [builtins.__dict__, self.namespace]: + for nspace in [self.namespace, builtins.__dict__]: for word, val in nspace.items(): - if word[:n] == text and word != "__builtins__": + if (word[:n] == text and word != "__builtins__" and + word not in seen): + seen.add(word) matches.append(self._callable_postfix(val, word)) return matches diff -r 284187f3a783 Lib/test/test_rlcompleter.py --- a/Lib/test/test_rlcompleter.py Wed Nov 18 12:44:59 2015 -0500 +++ b/Lib/test/test_rlcompleter.py Thu Nov 19 01:59:39 2015 +0000 @@ -113,5 +113,21 @@ self.assertEqual(completer.complete('el', 1), 'else') self.assertEqual(completer.complete('tr', 0), 'try:') + def test_duplicate_globals(self): + namespace = { + "False": None, + "assert": None, + "memoryview": None, + } + completer = rlcompleter.Completer(namespace) + self.assertEqual(completer.complete('False', 0), 'False') + self.assertIsNone(completer.complete('False', 1)) # No duplicates + # Space added due to being a reserved keyword + self.assertEqual(completer.complete('assert', 0), 'assert ') + self.assertIsNone(completer.complete('assert', 1)) + # No opening bracket "(" because we overrode the built-in class + self.assertEqual(completer.complete('memoryview', 0), 'memoryview') + self.assertIsNone(completer.complete('memoryview', 1)) + if __name__ == '__main__': unittest.main() diff -r 284187f3a783 Misc/NEWS --- a/Misc/NEWS Wed Nov 18 12:44:59 2015 -0500 +++ b/Misc/NEWS Thu Nov 19 01:59:39 2015 +0000 @@ -95,6 +95,9 @@ Library ------- +- Issue #. . .: In the Readline completer, avoid listing duplicate global + names, and search the global namespace before searching builtins. + - Issue #6973: When we know a subprocess.Popen process has died, do not allow the send_signal(), terminate(), or kill() methods to do anything as they could potentially signal a different process.