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',
+ 'break', 'continue', 'pass',
+ '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 not in seen:
+ seen.add(word)
matches.append(self._callable_postfix(val, word))
return matches
def test_complete(self):
completer = rlcompleter.Completer()
self.assertEqual(completer.complete('', 0), '\t')
- self.assertEqual(completer.complete('a', 0), 'and')
- self.assertEqual(completer.complete('a', 1), 'as')
- self.assertEqual(completer.complete('as', 2), 'assert')
- self.assertEqual(completer.complete('an', 0), 'and')
+ self.assertEqual(completer.complete('a', 0), 'and ')
+ self.assertEqual(completer.complete('a', 1), 'as ')
+ self.assertEqual(completer.complete('as', 2), 'assert ')
+ self.assertEqual(completer.complete('an', 0), 'and ')
+ self.assertEqual(completer.complete('pa', 0), 'pass')
+ self.assertEqual(completer.complete('Fa', 0), 'False')
+ self.assertEqual(completer.complete('el', 0), 'elif ')
+ self.assertEqual(completer.complete('el', 1), 'else')
+ self.assertEqual(completer.complete('tr', 0), 'try:')
+ def test_duplicate_globals(self):
+ namespace = {
+ 'False': None, # Keyword vs builtin vs namespace
+ 'assert': None, # Keyword vs namespace
+ 'try': lambda: None, # Keyword vs callable
+ 'memoryview': None, # Callable builtin vs non-callable
+ 'Ellipsis': lambda: None, # Non-callable builtin vs callable
+ }
+ completer = rlcompleter.Completer(namespace)
+ self.assertEqual(completer.complete('False', 0), 'False')
+ self.assertIsNone(completer.complete('False', 1)) # No duplicates
+ self.assertEqual(completer.complete('assert', 0), 'assert')
+ self.assertIsNone(completer.complete('assert', 1))
+ self.assertEqual(completer.complete('try', 0), 'try')
+ self.assertIsNone(completer.complete('try', 1))
+ # No opening bracket "(" because we overrode the built-in class
+ self.assertEqual(completer.complete('memoryview', 0), 'memoryview')
+ self.assertIsNone(completer.complete('memoryview', 1))
+ self.assertEqual(completer.complete('Ellipsis', 0), 'Ellipsis(')
+ self.assertIsNone(completer.complete('Ellipsis', 1))
+
if __name__ == '__main__':
unittest.main()
Library
-------
++- Issue #25663: In the Readline completer, avoid listing duplicate global
++ names, and search the global namespace before searching builtins.
++
+- Issue #25688: Fixed file leak in ElementTree.iterparse() raising an error.
+
+- Issue #23914: Fixed SystemError raised by unpickler on broken pickle data.
+
+- Issue #25691: Fixed crash on deleting ElementTree.Element attributes.
+
+- Issue #25624: ZipFile now always writes a ZIP_STORED header for directory
+ entries. Patch by Dingyuan Wang.
+
- Issue #25626: Change three zlib functions to accept sizes that fit in
Py_ssize_t, but internally cap those sizes to UINT_MAX. This resolves a
regression in 3.5 where GzipFile.read() failed to read chunks larger than 2