diff --git a/Lib/idlelib/autocomplete.py b/Lib/idlelib/autocomplete.py index cd212ccb143a3c7..6517c04de1e8ae8 100644 --- a/Lib/idlelib/autocomplete.py +++ b/Lib/idlelib/autocomplete.py @@ -7,14 +7,10 @@ import string import sys -# These constants represent the two different types of completions. -# They must be defined here so autocomple_w can import them. -COMPLETE_ATTRIBUTES, COMPLETE_FILES = range(1, 2+1) - -from idlelib import autocomplete_w from idlelib.config import idleConf from idlelib.hyperparser import HyperParser -import __main__ +from idlelib.run import COMPLETE_ATTRIBUTES, COMPLETE_FILES, completion_list +from idlelib import autocomplete_w # This string includes all chars that may be in an identifier. # TODO Update this here and elsewhere. @@ -158,74 +154,35 @@ def open_completions(self, evalfuncs, complete, userWantsWin, mode=None): return None comp_lists = self.fetch_completions(comp_what, mode) if not comp_lists[0]: - return None + 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. + + The first list is a sublist of the second. - 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. + 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. + 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 --git a/Lib/idlelib/idle_test/test_autocomplete.py b/Lib/idlelib/idle_test/test_autocomplete.py index f3f2dea4246df00..f5e7f6665a5acb7 100644 --- a/Lib/idlelib/idle_test/test_autocomplete.py +++ b/Lib/idlelib/idle_test/test_autocomplete.py @@ -1,4 +1,4 @@ -''' Test autocomplete and autocomple_w +''' Test idlelib.autocomplete and idlelib.autocomple_w Coverage of autocomple: 56% ''' @@ -139,11 +139,6 @@ def test_fetch_completions(self): # 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 --git a/Lib/idlelib/run.py b/Lib/idlelib/run.py index 9f6604bb0acc58b..1701bcac15e54e9 100644 --- a/Lib/idlelib/run.py +++ b/Lib/idlelib/run.py @@ -1,5 +1,6 @@ import io import linecache +import os import queue import sys import time @@ -10,7 +11,6 @@ import tkinter # Tcl, deletions, messagebox if startup fails -from idlelib import autocomplete # AutoComplete, fetch_encodings from idlelib import calltips # CallTips from idlelib import debugger_r # start_debugger from idlelib import debugobj_r # remote_object_tree_item @@ -440,13 +440,64 @@ def decode_interrupthook(self): 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 @@ -488,7 +539,7 @@ def get_the_calltip(self, name): 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: @@ -505,4 +556,5 @@ def stackviewer(self, flist_oid=None): item = stackviewer.StackTreeItem(flist, tb) return debugobj_r.remote_object_tree_item(item) + capture_warnings(False) # Make sure turned off; see issue 18081