From a65f5f1231dd094b91715a5f38eef2ec0d62d1fc 2006-01-27 19:04:59 From: vivainio Date: 2006-01-27 19:04:59 Subject: [PATCH] a = !ls, a = %alias now work (captures output or gets ret val for aliases) IPApi.meta() provides session data storage for extensions. %alias without args returns a list of tuples instead of printing a list. __IP.meta is now Struct instead of dummy class "Bunch" --- diff --git a/IPython/Extensions/ext_rescapture.py b/IPython/Extensions/ext_rescapture.py new file mode 100644 index 0000000..adfe353 --- /dev/null +++ b/IPython/Extensions/ext_rescapture.py @@ -0,0 +1,66 @@ +# -*- coding: utf-8 -*- +""" IPython extension: new prefilters for output grabbing + +Provides + +var = %magic blah blah + +var = !ls + +$Id: genutils.py 1077 2006-01-24 18:15:27Z vivainio $ + +""" + +import IPython.ipapi +from IPython.genutils import * + +ip = IPython.ipapi.get() + +import re + +def hnd_magic(line,mo): + """ Handle a = %mymagic blah blah """ + #cmd = genutils.make_quoted_expr(mo.group('syscmd')) + #mag = 'ipmagic + #return "%s = %s" + var = mo.group('varname') + cmd = mo.group('cmd') + expr = make_quoted_expr(cmd) + return itpl('$var = ipmagic($expr)') + +def hnd_syscmd(line,mo): + """ Handle a = !ls """ + #cmd = genutils.make_quoted_expr(mo.group('syscmd')) + #mag = 'ipmagic + #return "%s = %s" + var = mo.group('varname') + cmd = mo.group('cmd') + expr = make_quoted_expr(itpl("sc -l =$cmd")) + return itpl('$var = ipmagic($expr)') + +def install_re_handler(pat, hnd): + ip.meta().re_prefilters.append((re.compile(pat), hnd)) + +def init_handlers(): + + ip.meta().re_prefilters = [] + + install_re_handler('(?P[\w\.]+)\s*=\s*%(?P.*)', + hnd_magic + ) + + install_re_handler('(?P[\w\.]+)\s*=\s*!(?P.*)', + hnd_syscmd + ) + +init_handlers() + +def regex_prefilter_f(self,line): + for pat, handler in ip.meta().re_prefilters: + mo = pat.match(line) + if mo: + return handler(line,mo) + + raise IPython.ipapi.TryNext + +ip.set_hook('input_prefilter', regex_prefilter_f) \ No newline at end of file diff --git a/IPython/Extensions/ipy_system_conf.py b/IPython/Extensions/ipy_system_conf.py index 42f86a3..a180611 100644 --- a/IPython/Extensions/ipy_system_conf.py +++ b/IPython/Extensions/ipy_system_conf.py @@ -14,6 +14,5 @@ import IPython.ipapi as ip import sys -if sys.version_info >= (2,4): - # rehashdir extension requires python 2.4 - import ext_rehashdir \ No newline at end of file +import ext_rehashdir # %rehashdir magic +import ext_rescapture # var = !ls and var = %magic diff --git a/IPython/Magic.py b/IPython/Magic.py index dc01d4d..f45647b 100644 --- a/IPython/Magic.py +++ b/IPython/Magic.py @@ -1,7 +1,7 @@ # -*- coding: utf-8 -*- """Magic functions for InteractiveShell. -$Id: Magic.py 1077 2006-01-24 18:15:27Z vivainio $""" +$Id: Magic.py 1089 2006-01-27 19:04:59Z vivainio $""" #***************************************************************************** # Copyright (C) 2001 Janko Hauser and @@ -2171,14 +2171,15 @@ Defaulting color scheme to 'NoColor'""" prechar = '' else: prechar = self.shell.ESC_MAGIC - print 'Alias\t\tSystem Command\n'+'-'*30 + #print 'Alias\t\tSystem Command\n'+'-'*30 atab = self.shell.alias_table aliases = atab.keys() aliases.sort() + res = [] for alias in aliases: - print prechar+alias+'\t\t'+atab[alias][1] - print '-'*30+'\nTotal number of aliases:',len(aliases) - return + res.append((alias, atab[alias][1])) + print "Total number of aliases:",len(aliases) + return res try: alias,cmd = par.split(None,1) except: @@ -2443,6 +2444,18 @@ Defaulting color scheme to 'NoColor'""" def magic_sc(self, parameter_s=''): """Shell capture - execute a shell command and capture its output. + DEPRECATED. Suboptimal, retained for backwards compatibility. + + You should use the form 'var = !command' instead. Example: + + "%sc -l myfiles = ls ~" should now be written as + + "myfiles = !ls ~" + + myfiles.s, myfiles.l and myfiles.n still apply as documented + below. + + -- %sc [options] varname=command IPython will run the given command using commands.getoutput(), and @@ -2452,6 +2465,8 @@ Defaulting color scheme to 'NoColor'""" The '=' sign in the syntax is mandatory, and the variable name you supply must follow Python's standard conventions for valid names. + + (A special format without variable name exists for internal use) Options: @@ -2530,9 +2545,6 @@ Defaulting color scheme to 'NoColor'""" _,cmd = parameter_s.split('=',1) except ValueError: var,cmd = '','' - if not var: - error('you must specify a variable to assign the command to.') - return # If all looks ok, proceed out,err = self.shell.getoutputerror(cmd) if err: @@ -2543,7 +2555,10 @@ Defaulting color scheme to 'NoColor'""" out = LSString(out) if opts.has_key('v'): print '%s ==\n%s' % (var,pformat(out)) - self.shell.user_ns.update({var:out}) + if var: + self.shell.user_ns.update({var:out}) + else: + return out def magic_sx(self, parameter_s=''): """Shell execute - run a shell command and capture its output. diff --git a/IPython/ipapi.py b/IPython/ipapi.py index b697d35..ed629a8 100644 --- a/IPython/ipapi.py +++ b/IPython/ipapi.py @@ -140,6 +140,15 @@ class IPApi: Returns the result of evaluation""" return eval(expr,self.user_ns()) + + def meta(self): + """ Get a session-specific data store + + Object returned by this method can be used to store + data that should persist through the ipython session. + """ + return self.IP.meta + def launch_new_instance(user_ns = None): """ Create and start a new ipython instance. diff --git a/IPython/iplib.py b/IPython/iplib.py index cbb3bac..0dc7b59 100644 --- a/IPython/iplib.py +++ b/IPython/iplib.py @@ -6,7 +6,7 @@ Requires Python 2.3 or newer. This file contains all the classes and helper functions specific to IPython. -$Id: iplib.py 1088 2006-01-27 17:16:45Z vivainio $ +$Id: iplib.py 1089 2006-01-27 19:04:59Z vivainio $ """ #***************************************************************************** @@ -242,7 +242,7 @@ class InteractiveShell(object,Magic): # convenient location for storing additional information and state # their extensions may require, without fear of collisions with other # ipython names that may develop later. - self.meta = Bunch() + self.meta = Struct() # Create the namespace where the user will operate. user_ns is # normally the only one used, and it is passed to the exec calls as @@ -724,6 +724,8 @@ class InteractiveShell(object,Magic): # accepts it. Probably at least check that the hook takes the number # of args it's supposed to. dp = getattr(self.hooks, name, None) + if name not in IPython.hooks.__all__: + print "Warning! Hook '%s' is not one of %s" % (name, IPython.hooks.__all__ ) if not dp: dp = IPython.hooks.CommandChainDispatcher() diff --git a/doc/ChangeLog b/doc/ChangeLog index 30990aa..c790d26 100644 --- a/doc/ChangeLog +++ b/doc/ChangeLog @@ -4,6 +4,16 @@ 'ipython' at argv[0]) executed through command line. NOTE: this DEPRECATES calling ipython with multiple scripts ("ipython a.py b.py c.py") + + * iplib.py, hooks.py: Added configurable input prefilter, + named 'input_prefilter'. See ext_rescapture.py for example + usage. + + * ext_rescapture.py, Magic.py: Better system command output capture + through 'var = !ls' (deprecates user-visible %sc). Same notation + applies for magics, 'var = %alias' assigns alias list to var. + + * ipapi.py: added meta() for accessing extension-usable data store. 2006-01-25 Fernando Perez