diff --git a/IPython/Extensions/ipy_completers.py b/IPython/Extensions/ipy_completers.py index e42c263..faedf6f 100644 --- a/IPython/Extensions/ipy_completers.py +++ b/IPython/Extensions/ipy_completers.py @@ -12,6 +12,7 @@ import IPython.ipapi import glob,os,shlex,sys import inspect from time import time +from zipimport import zipimporter ip = IPython.ipapi.get() try: @@ -86,6 +87,11 @@ def moduleList(path): if os.path.isdir(path): folder_list = os.listdir(path) + elif path.endswith('.egg'): + try: + folder_list = [f for f in zipimporter(path)._files] + except: + folder_list = [] else: folder_list = [] #folder_list = glob.glob(os.path.join(path,'*')) diff --git a/IPython/genutils.py b/IPython/genutils.py index 1aa989f..09cc9ea 100644 --- a/IPython/genutils.py +++ b/IPython/genutils.py @@ -1052,25 +1052,40 @@ class SList(list): p = paths = property(get_paths) - def grep(self, pattern, prune = False): + def grep(self, pattern, prune = False, field = None): """ Return all strings matching 'pattern' (a regex or callable) This is case-insensitive. If prune is true, return all items NOT matching the pattern. + If field is specified, the match must occur in the specified + whitespace-separated field. + Examples:: a.grep( lambda x: x.startswith('C') ) a.grep('Cha.*log', prune=1) + a.grep('chm', field=-1) """ + + def match_target(s): + if field is None: + return s + parts = s.split() + try: + tgt = parts[field] + return tgt + except IndexError: + return "" + if isinstance(pattern, basestring): pred = lambda x : re.search(pattern, x, re.IGNORECASE) else: pred = pattern if not prune: - return SList([el for el in self if pred(el)]) + return SList([el for el in self if pred(match_target(el))]) else: - return SList([el for el in self if not pred(el)]) + return SList([el for el in self if not pred(match_target(el))]) def fields(self, *fields): """ Collect whitespace-separated fields from string list @@ -1083,6 +1098,7 @@ class SList(list): a.fields(0) is ['-rwxrwxrwx', 'drwxrwxrwx+'] a.fields(1,0) is ['1 -rwxrwxrwx', '6 drwxrwxrwx+'] (note the joining by space). + a.fields(-1) is ['ChangeLog', 'IPython'] IndexErrors are ignored. diff --git a/IPython/gui/wx/ipshell_nonblocking.py b/IPython/gui/wx/ipshell_nonblocking.py index 8d34ced..6f3f548 100644 --- a/IPython/gui/wx/ipshell_nonblocking.py +++ b/IPython/gui/wx/ipshell_nonblocking.py @@ -92,7 +92,7 @@ class NonBlockingIPShell(object): def __init__(self,argv=[],user_ns={},user_global_ns=None, cin=None, cout=None, cerr=None, - ask_exit_handler=None, rawinput=None): + ask_exit_handler=None): ''' @param argv: Command line options for IPython @type argv: list @@ -114,7 +114,7 @@ class NonBlockingIPShell(object): #ipython0 initialisation self.initIpython0(argv, user_ns, user_global_ns, cin, cout, cerr, - ask_exit_handler, rawinput) + ask_exit_handler) #vars used by _execute self._iter_more = 0 @@ -133,7 +133,7 @@ class NonBlockingIPShell(object): def initIpython0(self, argv=[], user_ns={}, user_global_ns=None, cin=None, cout=None, cerr=None, - ask_exit_handler=None, rawinput=None): + ask_exit_handler=None): #first we redefine in/out/error functions of IPython if cin: IPython.Shell.Term.cin = cin @@ -167,12 +167,18 @@ class NonBlockingIPShell(object): self._IP.set_hook('shell_hook',self._shell) #we replace the ipython default input command caller by our method - IPython.iplib.raw_input_original = rawinput - + IPython.iplib.raw_input_original = self._raw_input #we replace the ipython default exit command by our method self._IP.exit = ask_exit_handler #we replace the help command self._IP.user_ns['help'] = _Helper(self._pager_help) + + #we disable cpase magic... until we found a way to use it properly. + #import IPython.ipapi + ip = IPython.ipapi.get() + def bypassMagic(self, arg): + print '%this magic is currently disabled.' + ip.expose_magic('cpaste', bypassMagic) sys.excepthook = excepthook @@ -340,6 +346,12 @@ class NonBlockingIPShell(object): ''' pass + #def _askExit(self): + # ''' + # Can be redefined to generate post event to exit the Ipython shell + # ''' + # pass + def _getHistoryMaxIndex(self): ''' returns the max length of the history buffer @@ -380,6 +392,18 @@ class NonBlockingIPShell(object): ''' self._doc_text = text + def _raw_input(self, prompt=''): + ''' + Custom raw_input() replacement. Get's current line from console buffer. + + @param prompt: Prompt to print. Here for compatability as replacement. + @type prompt: string + + @return: The current command line text. + @rtype: string + ''' + return self._line_to_execute + def _execute(self): ''' Executes the current line provided by the shell object. diff --git a/IPython/gui/wx/ipython_view.py b/IPython/gui/wx/ipython_view.py index 2ab605d..a7fcccd 100644 --- a/IPython/gui/wx/ipython_view.py +++ b/IPython/gui/wx/ipython_view.py @@ -47,12 +47,11 @@ class WxNonBlockingIPShell(NonBlockingIPShell): def __init__(self, parent, argv=[],user_ns={},user_global_ns=None, cin=None, cout=None, cerr=None, - ask_exit_handler=None, rawinput=None): + ask_exit_handler=None): NonBlockingIPShell.__init__(self,argv,user_ns,user_global_ns, cin, cout, cerr, - ask_exit_handler, - rawinput) + ask_exit_handler) self.parent = parent @@ -216,6 +215,31 @@ class WxConsoleView(stc.StyledTextCtrl): self.Bind(wx.EVT_KEY_DOWN, self._onKeypress, self) + def asyncWrite(self, text): + ''' + Write given text to buffer in an asynchroneous way. + It is used from another thread to be able to acces the GUI. + @param text: Text to append + @type text: string + ''' + try: + #print >>sys.__stdout__,'entering' + wx.MutexGuiEnter() + #print >>sys.__stdout__,'locking the GUI' + + #be sure not to be interrutpted before the MutexGuiLeave! + self.write(text) + #print >>sys.__stdout__,'done' + + except KeyboardInterrupt: + #print >>sys.__stdout__,'got keyboard interrupt' + wx.MutexGuiLeave() + #print >>sys.__stdout__,'interrupt unlock the GUI' + raise KeyboardInterrupt + wx.MutexGuiLeave() + #print >>sys.__stdout__,'normal unlock the GUI' + + def write(self, text): ''' Write given text to buffer. @@ -453,7 +477,7 @@ class IPShellWidget(wx.Panel): def __init__(self, parent, intro=None, background_color="BLACK", add_button_handler=None, - wx_ip_shell=None, + wx_ip_shell=None, user_ns={},user_global_ns=None, ): ''' Initialize. @@ -472,8 +496,7 @@ class IPShellWidget(wx.Panel): else: self.IP = WxNonBlockingIPShell(self, cout = self.cout, cerr = self.cout, - ask_exit_handler = self.askExitCallback, - rawinput = self.rawInput) + ask_exit_handler = self.askExitCallback) ### IPython wx console view instanciation ### #If user didn't defined an intro text, we create one for him @@ -492,7 +515,7 @@ class IPShellWidget(wx.Panel): intro=welcome_text, background_color=background_color) - self.cout.write = self.text_ctrl.write + self.cout.write = self.text_ctrl.asyncWrite self.text_ctrl.Bind(wx.EVT_KEY_DOWN, self.keyPress, self.text_ctrl) @@ -509,18 +532,19 @@ class IPShellWidget(wx.Panel): #widget state management (for key handling different cases) self.setCurrentState('IDLE') self.pager_state = 'DONE' + self.raw_input_current_line = 0 def askExitCallback(self, event): self.askExitHandler(event) #---------------------- IPython Thread Management ------------------------ def stateDoExecuteLine(self): - #print >>sys.__stdout__,"command:",self.getCurrentLine() lines=self.text_ctrl.getCurrentLine() self.text_ctrl.write('\n') - for line in lines.split('\n'): - self.IP.doExecute((line.replace('\t',' '*4)).encode('cp1252')) - self.updateHistoryTracker(self.text_ctrl.getCurrentLine()) + lines_to_execute = lines.replace('\t',' '*4) + lines_to_execute = lines_to_execute.replace('\r\n','\n') + self.IP.doExecute(lines.encode('cp1252')) + self.updateHistoryTracker(lines) self.setCurrentState('WAIT_END_OF_EXECUTION') def evtStateExecuteDone(self,evt): @@ -551,16 +575,7 @@ class IPShellWidget(wx.Panel): def setCurrentState(self, state): self.cur_state = state self.updateStatusTracker(self.cur_state) - #---------------------------- Ipython raw_input ----------------------------------- - def rawInput(self, prompt=''): - self.setCurrentState('WAITING_USER_INPUT') - while self.cur_state != 'WAIT_END_OF_EXECUTION': - pass - line = self.text_ctrl.getCurrentLine() - line = line.split('\n') - return line[-2] - - #---------------------------- IPython pager --------------------------------------- + def pager(self,text): if self.pager_state == 'INIT': diff --git a/doc/ChangeLog b/doc/ChangeLog index f5b621f..680ba37 100644 --- a/doc/ChangeLog +++ b/doc/ChangeLog @@ -1,3 +1,10 @@ +2008-04-15 Ville Vainio + + * genutils.py: SList.grep supports 'field' argument + + * ipy_completers.py: module completer looks inside + .egg zip files (patch by mc). Close #196. + 2008-04-09 Ville Vainio * deep_reload.py: do not crash on from __future__ import