From c36cfa606283e082a6b218d17b3ba28c5249384c 2007-09-07 21:25:23
From: vivainio
Date: 2007-09-07 21:25:23
Subject: [PATCH] crlf normalization
---

diff --git a/IPython/Extensions/ipy_app_completers.py b/IPython/Extensions/ipy_app_completers.py
index 831cfd6..0277623 100644
--- a/IPython/Extensions/ipy_app_completers.py
+++ b/IPython/Extensions/ipy_app_completers.py
@@ -1,21 +1,21 @@
-""" Install various IPython completers
-
-IPython extension that installs the completers related to external apps.
-
-The actual implementations are in Extensions/ipy_completers.py
-
-"""
-import IPython.ipapi
-
-ip = IPython.ipapi.get()
-
-from ipy_completers import *
-
-ip.set_hook('complete_command', apt_completers, re_key = '.*apt-get')
-ip.set_hook('complete_command', apt_completers, re_key = '.*yum')
-
-ip.set_hook('complete_command', svn_completer, str_key = 'svn')
-
-ip.set_hook('complete_command', hg_completer, str_key = 'hg')
-
-ip.set_hook('complete_command', bzr_completer, str_key = 'bzr')
+""" Install various IPython completers
+
+IPython extension that installs the completers related to external apps.
+
+The actual implementations are in Extensions/ipy_completers.py
+
+"""
+import IPython.ipapi
+
+ip = IPython.ipapi.get()
+
+from ipy_completers import *
+
+ip.set_hook('complete_command', apt_completers, re_key = '.*apt-get')
+ip.set_hook('complete_command', apt_completers, re_key = '.*yum')
+
+ip.set_hook('complete_command', svn_completer, str_key = 'svn')
+
+ip.set_hook('complete_command', hg_completer, str_key = 'hg')
+
+ip.set_hook('complete_command', bzr_completer, str_key = 'bzr')
diff --git a/IPython/Extensions/ipy_editors.py b/IPython/Extensions/ipy_editors.py
index 6c00d11..09f940e 100644
--- a/IPython/Extensions/ipy_editors.py
+++ b/IPython/Extensions/ipy_editors.py
@@ -1,80 +1,80 @@
-""" 'editor' hooks for common editors that work well with ipython
-
-They should honor the line number argument, at least.
-
-Contributions are *very* welcome.
-"""
-
-import IPython.ipapi
-ip = IPython.ipapi.get()
-
-from IPython.Itpl import itplns
-import os
-
-def install_editor(run_template, wait = False):
-    """ Gets a template in format "myeditor bah bah $file bah bah $line"
-    
-    $file will be replaced by file name, $line by line number (or 0).
-    Installs the editor that is called by IPython, instead of the default
-    notepad or vi.
-    
-    If wait is true, wait until the user presses enter before returning,
-    to facilitate non-blocking editors that exit immediately after
-    the call.
-    """
-    
-    def call_editor(self, file, line):
-        if line is None:
-            line = 0
-        cmd = itplns(run_template, locals())
-        print ">",cmd
-        os.system(cmd)
-        if wait:
-            raw_input("Press Enter when done editing:")
-
-    ip.set_hook('editor',call_editor)
-
-
-# in these, exe is always the path/name of the executable. Useful
-# if you don't have the editor directory in your path
-
-def komodo(exe = 'komodo'):
-    """ Activestate Komodo [Edit] """
-    install_editor(exe + ' -l $line "$file"', wait = True)
-
-def scite(exe = "scite"):
-    """ SciTE or Sc1 """
-    install_editor(exe + ' "$file" -goto:$line')
-
-def notepadplusplus(exe = 'notepad++'):
-    """ Notepad++ http://notepad-plus.sourceforge.net """
-    install_editor(exe + ' -n$line "$file"')
-    
-def jed(exe = 'jed'):
-    """ JED, the lightweight emacsish editor """
-    install_editor(exe + ' +$line "$file"')
-
-def idle(exe = None):
-    """ Idle, the editor bundled with python
-    
-    Should be pretty smart about finding the executable.
-    """
-    if exe is None:
-        import idlelib
-        p = os.path.dirname(idlelib.__file__)
-        exe = p + '/idle.py'
-    install_editor(exe + ' "$file"')
-        
-
-# these are untested, report any problems
-
-def emacs(exe = 'emacs'):
-    install_editor(exe + ' +$line "$file"')
-
-def gnuclient(exe= 'gnuclient'):
-    install_editor(exe + ' -nw +$line "$file"')
-
-def crimson_editor(exe = 'cedt.exe'):
-    install_editor(exe + ' /L:%line "$file"')
-   
+""" 'editor' hooks for common editors that work well with ipython
+
+They should honor the line number argument, at least.
+
+Contributions are *very* welcome.
+"""
+
+import IPython.ipapi
+ip = IPython.ipapi.get()
+
+from IPython.Itpl import itplns
+import os
+
+def install_editor(run_template, wait = False):
+    """ Gets a template in format "myeditor bah bah $file bah bah $line"
+    
+    $file will be replaced by file name, $line by line number (or 0).
+    Installs the editor that is called by IPython, instead of the default
+    notepad or vi.
+    
+    If wait is true, wait until the user presses enter before returning,
+    to facilitate non-blocking editors that exit immediately after
+    the call.
+    """
+    
+    def call_editor(self, file, line):
+        if line is None:
+            line = 0
+        cmd = itplns(run_template, locals())
+        print ">",cmd
+        os.system(cmd)
+        if wait:
+            raw_input("Press Enter when done editing:")
+
+    ip.set_hook('editor',call_editor)
+
+
+# in these, exe is always the path/name of the executable. Useful
+# if you don't have the editor directory in your path
+
+def komodo(exe = 'komodo'):
+    """ Activestate Komodo [Edit] """
+    install_editor(exe + ' -l $line "$file"', wait = True)
+
+def scite(exe = "scite"):
+    """ SciTE or Sc1 """
+    install_editor(exe + ' "$file" -goto:$line')
+
+def notepadplusplus(exe = 'notepad++'):
+    """ Notepad++ http://notepad-plus.sourceforge.net """
+    install_editor(exe + ' -n$line "$file"')
+    
+def jed(exe = 'jed'):
+    """ JED, the lightweight emacsish editor """
+    install_editor(exe + ' +$line "$file"')
+
+def idle(exe = None):
+    """ Idle, the editor bundled with python
+    
+    Should be pretty smart about finding the executable.
+    """
+    if exe is None:
+        import idlelib
+        p = os.path.dirname(idlelib.__file__)
+        exe = p + '/idle.py'
+    install_editor(exe + ' "$file"')
+        
+
+# these are untested, report any problems
+
+def emacs(exe = 'emacs'):
+    install_editor(exe + ' +$line "$file"')
+
+def gnuclient(exe= 'gnuclient'):
+    install_editor(exe + ' -nw +$line "$file"')
+
+def crimson_editor(exe = 'cedt.exe'):
+    install_editor(exe + ' /L:%line "$file"')
+   
     
\ No newline at end of file
diff --git a/IPython/Extensions/ipy_fsops.py b/IPython/Extensions/ipy_fsops.py
index da93eb4..9e5ff9f 100644
--- a/IPython/Extensions/ipy_fsops.py
+++ b/IPython/Extensions/ipy_fsops.py
@@ -1,173 +1,173 @@
-""" File system operations
-
-Contains: Simple variants of normal unix shell commands (icp, imv, irm,
-imkdir, igrep).
-
-Some "otherwise handy" utils ('collect' for gathering files to
-~/_ipython/collect, 'inote' for collecting single note lines to
-~/_ipython/note.txt)
-
-Mostly of use for bare windows installations where cygwin/equivalent is not
-installed and you would otherwise need to deal with dos versions of the
-commands (that e.g. don't understand / as path separator). These can
-do some useful tricks on their own, though (like use 'mglob' patterns).
-
-Not to be confused with ipipe commands (ils etc.) that also start with i.
-"""
-
-import IPython.ipapi
-ip = IPython.ipapi.get()
-
-import shutil,os,shlex
-from IPython.external import mglob
-class IpyShellCmdException(Exception):
-    pass
-
-def parse_args(args):
-    """ Given arg string 'CMD files... target', return ([files], target) """
-    
-    tup = args.split(None, 1)
-    if len(tup) == 1:
-        raise IpyShellCmdException("Expected arguments for " + tup[0])
-    
-    tup2 = shlex.split(tup[1])
-    
-    flist, trg = mglob.expand(tup2[0:-1]), tup2[-1]
-    if not flist:
-        raise IpyShellCmdException("No files found:" + str(tup2[0:-1]))
-    return flist, trg
-    
-def icp(ip,arg):
-    """ icp files... targetdir
-    
-    Copy all files to target, creating dirs for target if necessary
-    
-    icp srcdir dstdir
-    
-    Copy srcdir to distdir
-    
-    """
-    import distutils.dir_util
-    
-    fs, targetdir = parse_args(arg)
-    if not os.path.isdir(targetdir):
-        distutils.dir_util.mkpath(targetdir,verbose =1)
-    for f in fs:
-        shutil.copy2(f,targetdir)
-    return fs
-ip.defalias("icp",icp)
-
-def imv(ip,arg):
-    """ imv src tgt
-    
-    Move source to target.
-    """
-    
-    fs, target = parse_args(arg)
-    if len(fs) > 1:
-        assert os.path.isdir(target)
-    for f in fs:        
-        shutil.move(f, target)
-    return fs
-ip.defalias("imv",imv)        
-
-def irm(ip,arg):
-    """ irm path[s]...
-    
-    Remove file[s] or dir[s] path. Dirs are deleted recursively.
-    """
-    paths = mglob.expand(arg.split(None,1)[1])
-    import distutils.dir_util
-    for p in paths:
-        print "rm",p
-        if os.path.isdir(p):
-            distutils.dir_util.remove_tree(p, verbose = 1)
-        else:
-            os.remove(p)
-
-ip.defalias("irm",irm)
-
-def imkdir(ip,arg):
-    """ imkdir path
-    
-    Creates dir path, and all dirs on the road
-    """
-    import distutils.dir_util
-    targetdir = arg.split(None,1)[1]
-    distutils.dir_util.mkpath(targetdir,verbose =1)    
-
-ip.defalias("imkdir",imkdir)    
-
-def igrep(ip,arg):
-    """ igrep PAT files...
-    
-    Very dumb file scan, case-insensitive.
-    
-    e.g.
-    
-    igrep "test this" rec:*.py
-    
-    """
-    elems = shlex.split(arg)
-    dummy, pat, fs = elems[0], elems[1], mglob.expand(elems[2:])
-    res = []
-    for f in fs:
-        found = False
-        for l in open(f):
-            if pat.lower() in l.lower():
-                if not found:
-                    print "[[",f,"]]"
-                    found = True
-                    res.append(f)
-                print l.rstrip()
-    return res
-
-ip.defalias("igrep",igrep)    
-
-def collect(ip,arg):
-    """ collect foo/a.txt rec:bar=*.py
-    
-    Copies foo/a.txt to ~/_ipython/collect/foo/a.txt and *.py from bar,
-    likewise
-    
-    Without args, try to open ~/_ipython/collect dir (in win32 at least).
-    """
-    from path import path
-    basedir = path(ip.options.ipythondir + '/collect')
-    try:    
-        fs = mglob.expand(arg.split(None,1)[1])
-    except IndexError:
-        os.startfile(basedir)
-        return
-    for f in fs:
-        f = path(f)
-        trg = basedir / f.splitdrive()[1].lstrip('/\\')
-        if f.isdir():
-            print "mkdir",trg
-            trg.makedirs()
-            continue
-        dname = trg.dirname()
-        if not dname.isdir():
-            dname.makedirs()
-        print f,"=>",trg
-        shutil.copy2(f,trg)
-
-ip.defalias("collect",collect)            
-
-def inote(ip,arg):
-    """ inote Hello world
-    
-    Adds timestamp and Hello world to ~/_ipython/notes.txt
-    
-    Without args, opens notes.txt for editing.
-    """
-    import time
-    fname = ip.options.ipythondir + '/notes.txt'
-    
-    try:
-        entry = " === " + time.asctime() + ': ===\n' + arg.split(None,1)[1] + '\n'
-        f= open(fname, 'a').write(entry)    
-    except IndexError:
-        ip.IP.hooks.editor(fname)        
-
-ip.defalias("inote",inote)
+""" File system operations
+
+Contains: Simple variants of normal unix shell commands (icp, imv, irm,
+imkdir, igrep).
+
+Some "otherwise handy" utils ('collect' for gathering files to
+~/_ipython/collect, 'inote' for collecting single note lines to
+~/_ipython/note.txt)
+
+Mostly of use for bare windows installations where cygwin/equivalent is not
+installed and you would otherwise need to deal with dos versions of the
+commands (that e.g. don't understand / as path separator). These can
+do some useful tricks on their own, though (like use 'mglob' patterns).
+
+Not to be confused with ipipe commands (ils etc.) that also start with i.
+"""
+
+import IPython.ipapi
+ip = IPython.ipapi.get()
+
+import shutil,os,shlex
+from IPython.external import mglob
+class IpyShellCmdException(Exception):
+    pass
+
+def parse_args(args):
+    """ Given arg string 'CMD files... target', return ([files], target) """
+    
+    tup = args.split(None, 1)
+    if len(tup) == 1:
+        raise IpyShellCmdException("Expected arguments for " + tup[0])
+    
+    tup2 = shlex.split(tup[1])
+    
+    flist, trg = mglob.expand(tup2[0:-1]), tup2[-1]
+    if not flist:
+        raise IpyShellCmdException("No files found:" + str(tup2[0:-1]))
+    return flist, trg
+    
+def icp(ip,arg):
+    """ icp files... targetdir
+    
+    Copy all files to target, creating dirs for target if necessary
+    
+    icp srcdir dstdir
+    
+    Copy srcdir to distdir
+    
+    """
+    import distutils.dir_util
+    
+    fs, targetdir = parse_args(arg)
+    if not os.path.isdir(targetdir):
+        distutils.dir_util.mkpath(targetdir,verbose =1)
+    for f in fs:
+        shutil.copy2(f,targetdir)
+    return fs
+ip.defalias("icp",icp)
+
+def imv(ip,arg):
+    """ imv src tgt
+    
+    Move source to target.
+    """
+    
+    fs, target = parse_args(arg)
+    if len(fs) > 1:
+        assert os.path.isdir(target)
+    for f in fs:        
+        shutil.move(f, target)
+    return fs
+ip.defalias("imv",imv)        
+
+def irm(ip,arg):
+    """ irm path[s]...
+    
+    Remove file[s] or dir[s] path. Dirs are deleted recursively.
+    """
+    paths = mglob.expand(arg.split(None,1)[1])
+    import distutils.dir_util
+    for p in paths:
+        print "rm",p
+        if os.path.isdir(p):
+            distutils.dir_util.remove_tree(p, verbose = 1)
+        else:
+            os.remove(p)
+
+ip.defalias("irm",irm)
+
+def imkdir(ip,arg):
+    """ imkdir path
+    
+    Creates dir path, and all dirs on the road
+    """
+    import distutils.dir_util
+    targetdir = arg.split(None,1)[1]
+    distutils.dir_util.mkpath(targetdir,verbose =1)    
+
+ip.defalias("imkdir",imkdir)    
+
+def igrep(ip,arg):
+    """ igrep PAT files...
+    
+    Very dumb file scan, case-insensitive.
+    
+    e.g.
+    
+    igrep "test this" rec:*.py
+    
+    """
+    elems = shlex.split(arg)
+    dummy, pat, fs = elems[0], elems[1], mglob.expand(elems[2:])
+    res = []
+    for f in fs:
+        found = False
+        for l in open(f):
+            if pat.lower() in l.lower():
+                if not found:
+                    print "[[",f,"]]"
+                    found = True
+                    res.append(f)
+                print l.rstrip()
+    return res
+
+ip.defalias("igrep",igrep)    
+
+def collect(ip,arg):
+    """ collect foo/a.txt rec:bar=*.py
+    
+    Copies foo/a.txt to ~/_ipython/collect/foo/a.txt and *.py from bar,
+    likewise
+    
+    Without args, try to open ~/_ipython/collect dir (in win32 at least).
+    """
+    from path import path
+    basedir = path(ip.options.ipythondir + '/collect')
+    try:    
+        fs = mglob.expand(arg.split(None,1)[1])
+    except IndexError:
+        os.startfile(basedir)
+        return
+    for f in fs:
+        f = path(f)
+        trg = basedir / f.splitdrive()[1].lstrip('/\\')
+        if f.isdir():
+            print "mkdir",trg
+            trg.makedirs()
+            continue
+        dname = trg.dirname()
+        if not dname.isdir():
+            dname.makedirs()
+        print f,"=>",trg
+        shutil.copy2(f,trg)
+
+ip.defalias("collect",collect)            
+
+def inote(ip,arg):
+    """ inote Hello world
+    
+    Adds timestamp and Hello world to ~/_ipython/notes.txt
+    
+    Without args, opens notes.txt for editing.
+    """
+    import time
+    fname = ip.options.ipythondir + '/notes.txt'
+    
+    try:
+        entry = " === " + time.asctime() + ': ===\n' + arg.split(None,1)[1] + '\n'
+        f= open(fname, 'a').write(entry)    
+    except IndexError:
+        ip.IP.hooks.editor(fname)        
+
+ip.defalias("inote",inote)
diff --git a/IPython/Extensions/ipy_kitcfg.py b/IPython/Extensions/ipy_kitcfg.py
index da77bf7..3a7e9f3 100644
--- a/IPython/Extensions/ipy_kitcfg.py
+++ b/IPython/Extensions/ipy_kitcfg.py
@@ -1,56 +1,56 @@
-import os,sys
-
-import ipy_rehashdir,glob
-from ipy_rehashdir import selflaunch, PyLauncher
-
-def pylaunchers():
-    """Create launchers for python scripts in cwd and store them in alias table
-    
-    This is useful if you want to invoke .py scripts from ipykit session,
-    just adding .py files in PATH does not work without file association.
-    
-    .ipy files will be run like macros.
-    
-    """
-    fs = glob.glob('*.?py*')
-    for f in fs:
-        l = PyLauncher(f)
-        n = os.path.splitext(f)[0]
-        ip.defalias(n, l)
-        ip.magic('store '+n)
-
-
-def exta_imports():
-    # add some modules that you'd want to be bundled in the ipykit
-    # library zip file here. Do this if you get ImportErrors from scripts you
-    # try to launch with 'py' or pylaunchers. In theory you could include
-    # the whole stdlib here for full script coverage
-    
-    # note that this is never run, it's just here for py2exe
-    import distutils.dir_util
-  
-def main():
-    root = os.environ.get('IPYKITROOT', None)
-    if not root:
-        print "Can't configure ipykit, IPYKITROOT should be set."
-        return
-    
-    os.environ["PATH"] = os.environ["PATH"] + ";" + root + "\\bin;"
-    ip.to_user_ns("pylaunchers")
-    
-    
-def ipython_firstrun(ip):
-    print "First run of ipykit - configuring"
-    ip.defalias('py',selflaunch)
-    ip.defalias('d','ls -F')
-    ip.defalias('ls','ls')
-    ip.magic('store py')
-    ip.magic('store d')
-    ip.magic('store ls')
-
-def init_ipython(ipy):
-    global ip
-    ip = ipy
-    main()
-
-
+import os,sys
+
+import ipy_rehashdir,glob
+from ipy_rehashdir import selflaunch, PyLauncher
+
+def pylaunchers():
+    """Create launchers for python scripts in cwd and store them in alias table
+    
+    This is useful if you want to invoke .py scripts from ipykit session,
+    just adding .py files in PATH does not work without file association.
+    
+    .ipy files will be run like macros.
+    
+    """
+    fs = glob.glob('*.?py*')
+    for f in fs:
+        l = PyLauncher(f)
+        n = os.path.splitext(f)[0]
+        ip.defalias(n, l)
+        ip.magic('store '+n)
+
+
+def exta_imports():
+    # add some modules that you'd want to be bundled in the ipykit
+    # library zip file here. Do this if you get ImportErrors from scripts you
+    # try to launch with 'py' or pylaunchers. In theory you could include
+    # the whole stdlib here for full script coverage
+    
+    # note that this is never run, it's just here for py2exe
+    import distutils.dir_util
+  
+def main():
+    root = os.environ.get('IPYKITROOT', None)
+    if not root:
+        print "Can't configure ipykit, IPYKITROOT should be set."
+        return
+    
+    os.environ["PATH"] = os.environ["PATH"] + ";" + root + "\\bin;"
+    ip.to_user_ns("pylaunchers")
+    
+    
+def ipython_firstrun(ip):
+    print "First run of ipykit - configuring"
+    ip.defalias('py',selflaunch)
+    ip.defalias('d','ls -F')
+    ip.defalias('ls','ls')
+    ip.magic('store py')
+    ip.magic('store d')
+    ip.magic('store ls')
+
+def init_ipython(ipy):
+    global ip
+    ip = ipy
+    main()
+
+
diff --git a/IPython/Extensions/ipy_workdir.py b/IPython/Extensions/ipy_workdir.py
index 07ae5d4..e27b476 100644
--- a/IPython/Extensions/ipy_workdir.py
+++ b/IPython/Extensions/ipy_workdir.py
@@ -1,43 +1,43 @@
-#!/usr/bin/env python
-
-import IPython.ipapi
-ip = IPython.ipapi.get()
-
-import os, subprocess
-
-workdir = None
-def workdir_f(ip,line):
-    """ Exceute commands residing in cwd elsewhere 
-    
-    Example::
-      
-      workdir /myfiles
-      cd bin
-      workdir myscript.py 
-      
-    executes myscript.py (stored in bin, but not in path) in /myfiles
-    """
-    global workdir
-    dummy,cmd  = line.split(None,1)
-    if os.path.isdir(cmd):
-        workdir = os.path.abspath(cmd)
-        print "Set workdir",workdir
-    elif workdir is None:
-        print "Please set workdir first by doing e.g. 'workdir q:/'"
-    else:
-        sp = cmd.split(None,1)
-        if len(sp) == 1:
-            head, tail = cmd, ''
-        else:
-            head, tail = sp
-        if os.path.isfile(head):
-            cmd = os.path.abspath(head) + ' ' + tail
-        print "Execute command '" + cmd+ "' in",workdir
-        olddir = os.getcwd()
-        os.chdir(workdir)
-        try:
-            os.system(cmd)
-        finally:
-            os.chdir(olddir)
-
-ip.defalias("workdir",workdir_f)
+#!/usr/bin/env python
+
+import IPython.ipapi
+ip = IPython.ipapi.get()
+
+import os, subprocess
+
+workdir = None
+def workdir_f(ip,line):
+    """ Exceute commands residing in cwd elsewhere 
+    
+    Example::
+      
+      workdir /myfiles
+      cd bin
+      workdir myscript.py 
+      
+    executes myscript.py (stored in bin, but not in path) in /myfiles
+    """
+    global workdir
+    dummy,cmd  = line.split(None,1)
+    if os.path.isdir(cmd):
+        workdir = os.path.abspath(cmd)
+        print "Set workdir",workdir
+    elif workdir is None:
+        print "Please set workdir first by doing e.g. 'workdir q:/'"
+    else:
+        sp = cmd.split(None,1)
+        if len(sp) == 1:
+            head, tail = cmd, ''
+        else:
+            head, tail = sp
+        if os.path.isfile(head):
+            cmd = os.path.abspath(head) + ' ' + tail
+        print "Execute command '" + cmd+ "' in",workdir
+        olddir = os.getcwd()
+        os.chdir(workdir)
+        try:
+            os.system(cmd)
+        finally:
+            os.chdir(olddir)
+
+ip.defalias("workdir",workdir_f)
diff --git a/IPython/generics.py b/IPython/generics.py
index 09a1462..61b11fc 100644
--- a/IPython/generics.py
+++ b/IPython/generics.py
@@ -1,30 +1,30 @@
-from IPython.ipapi import TryNext
-from IPython.external.simplegeneric import generic
-
-''' 'Generic' functions for extending IPython
-
-See http://cheeseshop.python.org/pypi/simplegeneric
-
-Here's an example from genutils.py:
-
-    def print_lsstring(arg):
-        """ Prettier (non-repr-like) and more informative printer for LSString """
-        print "LSString (.p, .n, .l, .s available). Value:"
-        print arg
-        
-    print_lsstring = result_display.when_type(LSString)(print_lsstring)
-
-(Yes, the nasty syntax is for python 2.3 compatibility. Your own extensions
-can use the niftier decorator syntax)
-
-'''
-
-def result_display(result):
-    """ print the result of computation """
-    raise TryNext
-
-result_display = generic(result_display)
-
-def inspect_object(obj):
-    """ Called when you do obj? """
-    raise TryNext
+from IPython.ipapi import TryNext
+from IPython.external.simplegeneric import generic
+
+''' 'Generic' functions for extending IPython
+
+See http://cheeseshop.python.org/pypi/simplegeneric
+
+Here's an example from genutils.py:
+
+    def print_lsstring(arg):
+        """ Prettier (non-repr-like) and more informative printer for LSString """
+        print "LSString (.p, .n, .l, .s available). Value:"
+        print arg
+        
+    print_lsstring = result_display.when_type(LSString)(print_lsstring)
+
+(Yes, the nasty syntax is for python 2.3 compatibility. Your own extensions
+can use the niftier decorator syntax)
+
+'''
+
+def result_display(result):
+    """ print the result of computation """
+    raise TryNext
+
+result_display = generic(result_display)
+
+def inspect_object(obj):
+    """ Called when you do obj? """
+    raise TryNext
diff --git a/IPython/history.py b/IPython/history.py
index ca2dc22..850095b 100644
--- a/IPython/history.py
+++ b/IPython/history.py
@@ -1,241 +1,241 @@
-# -*- coding: utf-8 -*-
-
-""" History related magics and functionality """
-
-import fnmatch
-
-def magic_history(self, parameter_s = ''):
-    """Print input history (_i<n> variables), with most recent last.
-    
-    %history       -> print at most 40 inputs (some may be multi-line)\\
-    %history n     -> print at most n inputs\\
-    %history n1 n2 -> print inputs between n1 and n2 (n2 not included)\\
-    
-    Each input's number <n> is shown, and is accessible as the
-    automatically generated variable _i<n>.  Multi-line statements are
-    printed starting at a new line for easy copy/paste.
-    
-
-    Options:
-
-      -n: do NOT print line numbers. This is useful if you want to get a
-      printout of many lines which can be directly pasted into a text
-      editor.
-
-      This feature is only available if numbered prompts are in use.
-
-      -t: (default) print the 'translated' history, as IPython understands it.
-      IPython filters your input and converts it all into valid Python source
-      before executing it (things like magics or aliases are turned into
-      function calls, for example). With this option, you'll see the native
-      history instead of the user-entered version: '%cd /' will be seen as
-      '_ip.magic("%cd /")' instead of '%cd /'.
-      
-      -r: print the 'raw' history, i.e. the actual commands you typed.
-      
-      -g: treat the arg as a pattern to grep for in (full) history.
-      This includes the "shadow history" (almost all commands ever written).
-      Use '%hist -g' to show full shadow history (may be very long).
-      In shadow history, every index nuwber starts with 0.
-      
-
-    """
-
-    ip = self.api
-    shell = self.shell
-    if not shell.outputcache.do_full_cache:
-        print 'This feature is only available if numbered prompts are in use.'
-        return
-    opts,args = self.parse_options(parameter_s,'gntsr',mode='list')
-
-    if opts.has_key('t'):
-        input_hist = shell.input_hist
-    elif opts.has_key('r'):
-        input_hist = shell.input_hist_raw
-    else:
-        input_hist = shell.input_hist
-        
-    
-    default_length = 40
-    pattern = None
-    if opts.has_key('g'):
-        init = 1
-        final = len(input_hist)
-        parts = parameter_s.split(None,1)
-        if len(parts) == 1:
-            parts += '*'
-        head, pattern = parts
-        pattern = "*" + pattern + "*"
-    elif len(args) == 0:
-        final = len(input_hist)
-        init = max(1,final-default_length)
-    elif len(args) == 1:
-        final = len(input_hist)
-        init = max(1,final-int(args[0]))
-    elif len(args) == 2:
-        init,final = map(int,args)
-    else:
-        warn('%hist takes 0, 1 or 2 arguments separated by spaces.')
-        print self.magic_hist.__doc__
-        return
-    width = len(str(final))
-    line_sep = ['','\n']
-    print_nums = not opts.has_key('n')
-    
-    found = False
-    if pattern is not None:
-        sh = ip.IP.shadowhist.all()
-        for idx, s in sh:
-            if fnmatch.fnmatch(s, pattern):
-                print "0%d: %s" %(idx, s)
-                found = True
-    
-    if found:
-        print "==="
-        print "^shadow history ends, fetch by %rep <number> (must start with 0)"
-        print "=== start of normal history ==="
-        
-    for in_num in range(init,final):        
-        inline = input_hist[in_num]
-        if pattern is not None and not fnmatch.fnmatch(inline, pattern):
-            continue
-            
-        multiline = int(inline.count('\n') > 1)
-        if print_nums:
-            print '%s:%s' % (str(in_num).ljust(width),line_sep[multiline]),
-        print inline,
-
-
-
-def magic_hist(self, parameter_s=''):
-    """Alternate name for %history."""
-    return self.magic_history(parameter_s)
-
-
-
-def rep_f(self, arg):
-    r""" Repeat a command, or get command to input line for editing
-
-    - %rep (no arguments):
-    
-    Place a string version of last computation result (stored in the special '_'
-    variable) to the next input prompt. Allows you to create elaborate command
-    lines without using copy-paste::
-    
-        $ l = ["hei", "vaan"]       
-        $ "".join(l)        
-        ==> heivaan        
-        $ %rep        
-        $ heivaan_ <== cursor blinking    
-    
-    %rep 45
-    
-    Place history line 45 to next input prompt. Use %hist to find out the
-    number.
-    
-    %rep 1-4 6-7 3
-    
-    Repeat the specified lines immediately. Input slice syntax is the same as
-    in %macro and %save.
-    
-    %rep foo
-    
-    Place the most recent line that has the substring "foo" to next input.
-    (e.g. 'svn ci -m foobar').
-    
-    """
-    
-    
-    opts,args = self.parse_options(arg,'',mode='list')
-    ip = self.api    
-    if not args:
-        ip.set_next_input(str(ip.user_ns["_"]))
-        return
-
-    if len(args) == 1 and not '-' in args[0]:
-        arg = args[0]
-        if len(arg) > 1 and arg.startswith('0'):
-            # get from shadow hist
-            num = int(arg[1:])
-            line = self.shadowhist.get(num)
-            ip.set_next_input(str(line))
-            return
-        try:
-            num = int(args[0])
-            ip.set_next_input(str(ip.IP.input_hist_raw[num]).rstrip())
-            return
-        except ValueError:
-            pass
-        
-        for h in reversed(self.shell.input_hist_raw):
-            if 'rep' in h:
-                continue
-            if fnmatch.fnmatch(h,'*' + arg + '*'):
-                ip.set_next_input(str(h).rstrip())
-                return
-        
-
-    try:
-        lines = self.extract_input_slices(args, True)
-        print "lines",lines
-        ip.runlines(lines)
-    except ValueError:
-        print "Not found in recent history:", args
-        
-
-
-_sentinel = object()
-
-class ShadowHist:
-    def __init__(self,db):
-        # cmd => idx mapping
-        self.curidx = 0
-        self.db = db
-    
-    def inc_idx(self):
-        idx = self.db.get('shadowhist_idx', 1)
-        self.db['shadowhist_idx'] = idx + 1
-        return idx
-        
-    def add(self, ent):
-        old = self.db.hget('shadowhist', ent, _sentinel)
-        if old is not _sentinel:
-            return
-        newidx = self.inc_idx()
-        #print "new",newidx # dbg
-        self.db.hset('shadowhist',ent, newidx)
-    
-    def all(self):
-        d = self.db.hdict('shadowhist')
-        items = [(i,s) for (s,i) in d.items()]
-        items.sort()
-        return items
-
-    def get(self, idx):
-        all = self.all()
-        
-        for k, v in all:
-            #print k,v
-            if k == idx:
-                return v
-
-def test_shist():
-    from IPython.Extensions import pickleshare
-    db = pickleshare.PickleShareDB('~/shist')
-    s = ShadowHist(db)
-    s.add('hello')
-    s.add('world')
-    s.add('hello')
-    s.add('hello')
-    s.add('karhu')
-    print "all",s.all()
-    print s.get(2)
-
-def init_ipython(ip):
-    ip.expose_magic("rep",rep_f)        
-    ip.expose_magic("hist",magic_hist)            
-    ip.expose_magic("history",magic_history)
-
-    import ipy_completers
-    ipy_completers.quick_completer('%hist' ,'-g -t -r -n')
-#test_shist()
+# -*- coding: utf-8 -*-
+
+""" History related magics and functionality """
+
+import fnmatch
+
+def magic_history(self, parameter_s = ''):
+    """Print input history (_i<n> variables), with most recent last.
+    
+    %history       -> print at most 40 inputs (some may be multi-line)\\
+    %history n     -> print at most n inputs\\
+    %history n1 n2 -> print inputs between n1 and n2 (n2 not included)\\
+    
+    Each input's number <n> is shown, and is accessible as the
+    automatically generated variable _i<n>.  Multi-line statements are
+    printed starting at a new line for easy copy/paste.
+    
+
+    Options:
+
+      -n: do NOT print line numbers. This is useful if you want to get a
+      printout of many lines which can be directly pasted into a text
+      editor.
+
+      This feature is only available if numbered prompts are in use.
+
+      -t: (default) print the 'translated' history, as IPython understands it.
+      IPython filters your input and converts it all into valid Python source
+      before executing it (things like magics or aliases are turned into
+      function calls, for example). With this option, you'll see the native
+      history instead of the user-entered version: '%cd /' will be seen as
+      '_ip.magic("%cd /")' instead of '%cd /'.
+      
+      -r: print the 'raw' history, i.e. the actual commands you typed.
+      
+      -g: treat the arg as a pattern to grep for in (full) history.
+      This includes the "shadow history" (almost all commands ever written).
+      Use '%hist -g' to show full shadow history (may be very long).
+      In shadow history, every index nuwber starts with 0.
+      
+
+    """
+
+    ip = self.api
+    shell = self.shell
+    if not shell.outputcache.do_full_cache:
+        print 'This feature is only available if numbered prompts are in use.'
+        return
+    opts,args = self.parse_options(parameter_s,'gntsr',mode='list')
+
+    if opts.has_key('t'):
+        input_hist = shell.input_hist
+    elif opts.has_key('r'):
+        input_hist = shell.input_hist_raw
+    else:
+        input_hist = shell.input_hist
+        
+    
+    default_length = 40
+    pattern = None
+    if opts.has_key('g'):
+        init = 1
+        final = len(input_hist)
+        parts = parameter_s.split(None,1)
+        if len(parts) == 1:
+            parts += '*'
+        head, pattern = parts
+        pattern = "*" + pattern + "*"
+    elif len(args) == 0:
+        final = len(input_hist)
+        init = max(1,final-default_length)
+    elif len(args) == 1:
+        final = len(input_hist)
+        init = max(1,final-int(args[0]))
+    elif len(args) == 2:
+        init,final = map(int,args)
+    else:
+        warn('%hist takes 0, 1 or 2 arguments separated by spaces.')
+        print self.magic_hist.__doc__
+        return
+    width = len(str(final))
+    line_sep = ['','\n']
+    print_nums = not opts.has_key('n')
+    
+    found = False
+    if pattern is not None:
+        sh = ip.IP.shadowhist.all()
+        for idx, s in sh:
+            if fnmatch.fnmatch(s, pattern):
+                print "0%d: %s" %(idx, s)
+                found = True
+    
+    if found:
+        print "==="
+        print "^shadow history ends, fetch by %rep <number> (must start with 0)"
+        print "=== start of normal history ==="
+        
+    for in_num in range(init,final):        
+        inline = input_hist[in_num]
+        if pattern is not None and not fnmatch.fnmatch(inline, pattern):
+            continue
+            
+        multiline = int(inline.count('\n') > 1)
+        if print_nums:
+            print '%s:%s' % (str(in_num).ljust(width),line_sep[multiline]),
+        print inline,
+
+
+
+def magic_hist(self, parameter_s=''):
+    """Alternate name for %history."""
+    return self.magic_history(parameter_s)
+
+
+
+def rep_f(self, arg):
+    r""" Repeat a command, or get command to input line for editing
+
+    - %rep (no arguments):
+    
+    Place a string version of last computation result (stored in the special '_'
+    variable) to the next input prompt. Allows you to create elaborate command
+    lines without using copy-paste::
+    
+        $ l = ["hei", "vaan"]       
+        $ "".join(l)        
+        ==> heivaan        
+        $ %rep        
+        $ heivaan_ <== cursor blinking    
+    
+    %rep 45
+    
+    Place history line 45 to next input prompt. Use %hist to find out the
+    number.
+    
+    %rep 1-4 6-7 3
+    
+    Repeat the specified lines immediately. Input slice syntax is the same as
+    in %macro and %save.
+    
+    %rep foo
+    
+    Place the most recent line that has the substring "foo" to next input.
+    (e.g. 'svn ci -m foobar').
+    
+    """
+    
+    
+    opts,args = self.parse_options(arg,'',mode='list')
+    ip = self.api    
+    if not args:
+        ip.set_next_input(str(ip.user_ns["_"]))
+        return
+
+    if len(args) == 1 and not '-' in args[0]:
+        arg = args[0]
+        if len(arg) > 1 and arg.startswith('0'):
+            # get from shadow hist
+            num = int(arg[1:])
+            line = self.shadowhist.get(num)
+            ip.set_next_input(str(line))
+            return
+        try:
+            num = int(args[0])
+            ip.set_next_input(str(ip.IP.input_hist_raw[num]).rstrip())
+            return
+        except ValueError:
+            pass
+        
+        for h in reversed(self.shell.input_hist_raw):
+            if 'rep' in h:
+                continue
+            if fnmatch.fnmatch(h,'*' + arg + '*'):
+                ip.set_next_input(str(h).rstrip())
+                return
+        
+
+    try:
+        lines = self.extract_input_slices(args, True)
+        print "lines",lines
+        ip.runlines(lines)
+    except ValueError:
+        print "Not found in recent history:", args
+        
+
+
+_sentinel = object()
+
+class ShadowHist:
+    def __init__(self,db):
+        # cmd => idx mapping
+        self.curidx = 0
+        self.db = db
+    
+    def inc_idx(self):
+        idx = self.db.get('shadowhist_idx', 1)
+        self.db['shadowhist_idx'] = idx + 1
+        return idx
+        
+    def add(self, ent):
+        old = self.db.hget('shadowhist', ent, _sentinel)
+        if old is not _sentinel:
+            return
+        newidx = self.inc_idx()
+        #print "new",newidx # dbg
+        self.db.hset('shadowhist',ent, newidx)
+    
+    def all(self):
+        d = self.db.hdict('shadowhist')
+        items = [(i,s) for (s,i) in d.items()]
+        items.sort()
+        return items
+
+    def get(self, idx):
+        all = self.all()
+        
+        for k, v in all:
+            #print k,v
+            if k == idx:
+                return v
+
+def test_shist():
+    from IPython.Extensions import pickleshare
+    db = pickleshare.PickleShareDB('~/shist')
+    s = ShadowHist(db)
+    s.add('hello')
+    s.add('world')
+    s.add('hello')
+    s.add('hello')
+    s.add('karhu')
+    print "all",s.all()
+    print s.get(2)
+
+def init_ipython(ip):
+    ip.expose_magic("rep",rep_f)        
+    ip.expose_magic("hist",magic_hist)            
+    ip.expose_magic("history",magic_history)
+
+    import ipy_completers
+    ipy_completers.quick_completer('%hist' ,'-g -t -r -n')
+#test_shist()