From c4aff61cc6bcd9a71905d86b7f82139f853d6f96 2008-08-30 20:19:15 From: Gael Varoquaux Date: 2008-08-30 20:19:15 Subject: [PATCH] Fix a completion crasher (index error during completion). Fix completion for user-created object by refactoring --- diff --git a/IPython/frontend/linefrontendbase.py b/IPython/frontend/linefrontendbase.py index 6f60d75..10443b9 100644 --- a/IPython/frontend/linefrontendbase.py +++ b/IPython/frontend/linefrontendbase.py @@ -76,6 +76,11 @@ class LineFrontEndBase(FrontEndBase): if banner is not None: self.banner = banner + + def start(self): + """ Put the frontend in a state where it is ready for user + interaction. + """ if self.banner is not None: self.write(self.banner, refresh=False) @@ -210,9 +215,10 @@ class LineFrontEndBase(FrontEndBase): line = self.input_buffer new_line, completions = self.complete(line) if len(completions)>1: - self.write_completion(completions) - self.input_buffer = new_line + self.write_completion(completions, new_line=new_line) if self.debug: + print >>sys.__stdout__, 'line', line + print >>sys.__stdout__, 'new_line', new_line print >>sys.__stdout__, completions @@ -222,10 +228,15 @@ class LineFrontEndBase(FrontEndBase): return 80 - def write_completion(self, possibilities): + def write_completion(self, possibilities, new_line=None): """ Write the list of possible completions. + + new_line is the completed input line that should be displayed + after the completion are writen. If None, the input_buffer + before the completion is used. """ - current_buffer = self.input_buffer + if new_line is None: + new_line = self.input_buffer self.write('\n') max_len = len(max(possibilities, key=len)) + 1 @@ -246,7 +257,7 @@ class LineFrontEndBase(FrontEndBase): self.write(''.join(buf)) self.new_prompt(self.input_prompt_template.substitute( number=self.last_result['number'] + 1)) - self.input_buffer = current_buffer + self.input_buffer = new_line def new_prompt(self, prompt): diff --git a/IPython/frontend/prefilterfrontend.py b/IPython/frontend/prefilterfrontend.py index 8479132..c6da01c 100644 --- a/IPython/frontend/prefilterfrontend.py +++ b/IPython/frontend/prefilterfrontend.py @@ -24,6 +24,7 @@ __docformat__ = "restructuredtext en" import sys from linefrontendbase import LineFrontEndBase, common_prefix +from frontendbase import FrontEndBase from IPython.ipmaker import make_IPython from IPython.ipapi import IPApi @@ -34,6 +35,7 @@ from IPython.kernel.core.sync_traceback_trap import SyncTracebackTrap from IPython.genutils import Term import pydoc import os +import sys def mk_system_call(system_call_function, command): @@ -57,6 +59,8 @@ class PrefilterFrontEnd(LineFrontEndBase): to execute the statements and the ipython0 used for code completion... """ + + debug = False def __init__(self, ipython0=None, *args, **kwargs): """ Parameters: @@ -65,12 +69,24 @@ class PrefilterFrontEnd(LineFrontEndBase): ipython0: an optional ipython0 instance to use for command prefiltering and completion. """ + LineFrontEndBase.__init__(self, *args, **kwargs) + self.shell.output_trap = RedirectorOutputTrap( + out_callback=self.write, + err_callback=self.write, + ) + self.shell.traceback_trap = SyncTracebackTrap( + formatters=self.shell.traceback_trap.formatters, + ) + + # Start the ipython0 instance: self.save_output_hooks() if ipython0 is None: # Instanciate an IPython0 interpreter to be able to use the # prefiltering. # XXX: argv=[] is a bit bold. - ipython0 = make_IPython(argv=[]) + ipython0 = make_IPython(argv=[], + user_ns=self.shell.user_ns, + user_global_ns=self.shell.user_global_ns) self.ipython0 = ipython0 # Set the pager: self.ipython0.set_hook('show_in_pager', @@ -86,24 +102,24 @@ class PrefilterFrontEnd(LineFrontEndBase): 'ls -CF') # And now clean up the mess created by ipython0 self.release_output() + + if not 'banner' in kwargs and self.banner is None: - kwargs['banner'] = self.ipython0.BANNER + """ + self.banner = self.ipython0.BANNER + """ This is the wx frontend, by Gael Varoquaux. This is EXPERIMENTAL code.""" - LineFrontEndBase.__init__(self, *args, **kwargs) # XXX: Hack: mix the two namespaces - self.shell.user_ns.update(self.ipython0.user_ns) - self.ipython0.user_ns = self.shell.user_ns - self.shell.user_global_ns.update(self.ipython0.user_global_ns) - self.ipython0.user_global_ns = self.shell.user_global_ns +# self.shell.user_ns.update(self.ipython0.user_ns) +# self.ipython0.user_ns = self.shell.user_ns +# self.shell.user_global_ns.update(self.ipython0.user_global_ns) +# self.ipython0.user_global_ns = self.shell.user_global_ns + +# self.ipython0.user_ns.update(self.shell.user_ns) +# self.shell.user_ns = self.ipython0.user_ns +# self.ipython0.user_global_ns.update(self.shell.user_global_ns) +# self.shell.user_global_ns = self.ipython0.user_global_ns - self.shell.output_trap = RedirectorOutputTrap( - out_callback=self.write, - err_callback=self.write, - ) - self.shell.traceback_trap = SyncTracebackTrap( - formatters=self.shell.traceback_trap.formatters, - ) + self.start() #-------------------------------------------------------------------------- # FrontEndBase interface @@ -164,6 +180,8 @@ This is the wx frontend, by Gael Varoquaux. This is EXPERIMENTAL code.""" def complete(self, line): + # FIXME: This should be factored out in the linefrontendbase + # method. word = line.split('\n')[-1].split(' ')[-1] completions = self.ipython0.complete(word) # FIXME: The proper sort should be done in the complete method. diff --git a/IPython/frontend/wx/wx_frontend.py b/IPython/frontend/wx/wx_frontend.py index b695897..d88fba8 100644 --- a/IPython/frontend/wx/wx_frontend.py +++ b/IPython/frontend/wx/wx_frontend.py @@ -128,6 +128,7 @@ class WxController(ConsoleWidget, PrefilterFrontEnd): # while it is being swapped _out_buffer_lock = Lock() + # The different line markers used to higlight the prompts. _markers = dict() #-------------------------------------------------------------------------- @@ -238,9 +239,9 @@ class WxController(ConsoleWidget, PrefilterFrontEnd): true, open the menu. """ if self.debug: - print >>sys.__stdout__, "_popup_completion", + print >>sys.__stdout__, "_popup_completion" line = self.input_buffer - if (self.AutoCompActive() and not line[-1] == '.') \ + if (self.AutoCompActive() and line and not line[-1] == '.') \ or create==True: suggestion, completions = self.complete(line) offset=0 @@ -427,7 +428,7 @@ class WxController(ConsoleWidget, PrefilterFrontEnd): if event.KeyCode in (59, ord('.')): # Intercepting '.' event.Skip() - self._popup_completion(create=True) + wx.CallAfter(self._popup_completion, create=True) else: ConsoleWidget._on_key_up(self, event, skip=skip)