diff -r 93d325c64104 Lib/idlelib/autocomplete.py --- a/Lib/idlelib/autocomplete.py Fri Jul 15 02:43:03 2016 -0400 +++ b/Lib/idlelib/autocomplete.py Fri Jul 15 19:35:30 2016 -0400 @@ -8,17 +8,12 @@ import string from idlelib.config import idleConf - -# This string includes all chars that may be in an identifier -ID_CHARS = string.ascii_letters + string.digits + "_" +from idlelib.hyperparser import HyperParser +from idlelib.run import COMPLETE_ATTRIBUTES, COMPLETE_FILES, completion_list +from idlelib import autocomplete_w -# These constants represent the two different types of completions -COMPLETE_ATTRIBUTES, COMPLETE_FILES = range(1, 2+1) - -from idlelib import autocomplete_w -from idlelib.hyperparser import HyperParser - -import __main__ +# The chars that may be in an identifier. (XXX Fix for 3.x.) +ID_CHARS = string.ascii_letters + string.digits + "_" SEPS = os.sep if os.altsep: # e.g. '/' on Windows... @@ -82,14 +77,13 @@ """ if hasattr(event, "mc_state") and event.mc_state: # A modifier was pressed along with the tab, continue as usual. - return + return None if self.autocompletewindow and self.autocompletewindow.is_active(): self.autocompletewindow.complete() return "break" else: opened = self.open_completions(False, True, True) - if opened: - return "break" + return "break" if opened else None def _open_completions_later(self, *args): self._delayed_completion_index = self.text.index("insert") @@ -148,84 +142,45 @@ comp_what = hp.get_expression() if not comp_what or \ (not evalfuncs and comp_what.find('(') != -1): - return + return None else: comp_what = "" else: - return + return None if complete and not comp_what and not comp_start: - return + return None comp_lists = self.fetch_completions(comp_what, mode) if not comp_lists[0]: - return + return None, 1 self.autocompletewindow = self._make_autocomplete_window() return not self.autocompletewindow.show_window( comp_lists, "insert-%dc" % len(comp_start), complete, mode, userWantsWin) def fetch_completions(self, what, mode): - """Return a pair of lists of completions for something. The first list - is a sublist of the second. Both are sorted. + """Return a pair of sorted lists of completions for something. - If there is a Python subprocess, get the comp. list there. Otherwise, - either fetch_completions() is running in the subprocess itself or it - was called in an IDLE EditorWindow before any script had been run. + The first list is a sublist of the second. - The subprocess environment is that of the most recently run script. If - two unrelated modules are being edited some calltips in the current - module may be inoperative if the module was not the last to run. + If there is a Python subprocess, get the list there. Otherwise, + IDLE is running in a single process or fetch_completions() was + called in an IDLE EditorWindow before any script had been run. + + The subprocess environment is that of the most recently run + script. If two unrelated modules are being edited some calltips + in the current module may be inoperative if the module was not + the last to run. """ try: rpcclt = self.editwin.flist.pyshell.interp.rpcclt - except: + except AttributeError: rpcclt = None if rpcclt: return rpcclt.remotecall("exec", "get_the_completion_list", (what, mode), {}) else: - if mode == COMPLETE_ATTRIBUTES: - if what == "": - namespace = __main__.__dict__.copy() - namespace.update(__main__.__builtins__.__dict__) - bigl = eval("dir()", namespace) - bigl.sort() - if "__all__" in bigl: - smalll = sorted(eval("__all__", namespace)) - else: - smalll = [s for s in bigl if s[:1] != '_'] - else: - try: - entity = self.get_entity(what) - bigl = dir(entity) - bigl.sort() - if "__all__" in bigl: - smalll = sorted(entity.__all__) - else: - smalll = [s for s in bigl if s[:1] != '_'] - except: - return [], [] - - elif mode == COMPLETE_FILES: - if what == "": - what = "." - try: - expandedpath = os.path.expanduser(what) - bigl = os.listdir(expandedpath) - bigl.sort() - smalll = [s for s in bigl if s[:1] != '.'] - except OSError: - return [], [] - - if not smalll: - smalll = bigl - return smalll, bigl - - def get_entity(self, name): - """Lookup name in a namespace spanning sys.modules and __main.dict__""" - namespace = sys.modules.copy() - namespace.update(__main__.__dict__) - return eval(name, namespace) + return completion_list(what, mode) if __name__ == '__main__': diff -r 93d325c64104 Lib/idlelib/idle_test/test_autocomplete.py --- a/Lib/idlelib/idle_test/test_autocomplete.py Fri Jul 15 02:43:03 2016 -0400 +++ b/Lib/idlelib/idle_test/test_autocomplete.py Fri Jul 15 19:35:30 2016 -0400 @@ -1,4 +1,4 @@ -''' Test autocomplete and autocomple_w +''' Test idlelib.autocomplete and idlelib.autocomple_w Coverage of autocomple: 56% ''' @@ -136,11 +136,6 @@ # and a small list containing files that do not start with '.' pass - def test_get_entity(self): - # Test that a name is in the namespace of sys.modules and - # __main__.__dict__ - pass - if __name__ == '__main__': unittest.main(verbosity=2) diff -r 93d325c64104 Lib/idlelib/run.py --- a/Lib/idlelib/run.py Fri Jul 15 02:43:03 2016 -0400 +++ b/Lib/idlelib/run.py Fri Jul 15 19:35:30 2016 -0400 @@ -1,5 +1,6 @@ import io import linecache +import os import queue import sys import _thread as thread @@ -9,7 +10,6 @@ import tkinter from idlelib import calltips -from idlelib import autocomplete from idlelib import debugger_r from idlelib import debugobj_r @@ -437,13 +437,64 @@ thread.interrupt_main() +# Functions used in Executive methods and sometimes in IDLE process. +# Constants and completion_list are imported into autocomplete. + +# Define the two different types of completions. +COMPLETE_ATTRIBUTES, COMPLETE_FILES = 1, 2 + + +def completion_list(what, mode): + """Return a pair of sorted lists of completions for something. + + The first list is a sublist of the second. + """ + if mode == COMPLETE_ATTRIBUTES: + if what == "": + namespace = __main__.__dict__.copy() + namespace.update(__main__.__builtins__.__dict__) + big = eval("dir()", namespace) + big.sort() + if "__all__" in big: + small = sorted(eval("__all__", namespace)) + else: + small = [s for s in big if s[:1] != '_'] + else: + try: + namespace = sys.modules.copy() + namespace.update(__main__.__dict__) + entity = eval(name, namespace) + big = dir(entity) + big.sort() + if "__all__" in big: + small = sorted(entity.__all__) + else: + small = [s for s in big if s[:1] != '_'] + except: + return [], [] + + elif mode == COMPLETE_FILES: + if what == "": + what = "." + try: + expandedpath = os.path.expanduser(what) + big = os.listdir(expandedpath) + big.sort() + small = [s for s in big if s[:1] != '.'] + except OSError: + return [], [] + + if not small: + small = big + return small, big + + class Executive(object): def __init__(self, rpchandler): self.rpchandler = rpchandler self.locals = __main__.__dict__ self.calltip = calltips.CallTips() - self.autocomplete = autocomplete.AutoComplete() def runcode(self, code): global interruptable @@ -485,7 +536,7 @@ return self.calltip.fetch_tip(name) def get_the_completion_list(self, what, mode): - return self.autocomplete.fetch_completions(what, mode) + return completion_list(what, mode) def stackviewer(self, flist_oid=None): if self.usr_exc_info: @@ -502,4 +553,5 @@ item = stackviewer.StackTreeItem(flist, tb) return debugobj_r.remote_object_tree_item(item) + capture_warnings(False) # Make sure turned off; see issue 18081