Pick' the complete column under the cursor (i.e. the attribute under the
-cursor) from all currently fetched objects. These attributes will be returned
-as a list.
-
-
enter (E)
-
Enter the object under the cursor. (what this mean depends on the object
-itself, i.e. how it implements iteration). This opens a new browser 'level'.
-
-
enterattr (Shift-E)
-
Enter the attribute under the cursor.
-
-
detail (D)
-
Show a detail view of the object under the cursor. This shows the name,
-type, doc string and value of the object attributes (and it might show more
-attributes than in the list view, depending on the object).
-
-
detailattr (Shift-D)
-
Show a detail view of the attribute under the cursor.
-
-
pickrows (M)
-
Pick multiple selected rows (M)
-
-
pickrowsattr (CTRL-M)
-
From multiple selected rows pick the cells matching the attribute the cursor is in (CTRL-M)
-
-
find (CTRL-F)
-
Find text
-
-
find_next (F3)
-
Find next occurrence of the searchtext
-
-
find_previous (Shift-F3)
-
Find previous occurrence of the searchtext
-
-
sortattrasc (V)
-
Sort the objects (in ascending order) using the attribute under the cursor as the sort key.
-
-
sortattrdesc (Shift-V)
-
Sort the objects (in descending order) using the attribute under the cursor as the sort key.
-
-
leave (Backspace, DEL, X)
-
Close current tab (and all the tabs to the right of the current one).
-
-
quit (ESC,Q)
-
Quit igrid and return to the IPython prompt.
-
-
-
Navigation
-
-
-
Jump to the last column of the current row (END, CTRL-E, CTRL-Right)
-
-
Jump to the first column of the current row (HOME, CTRL-A, CTRL-Left)
-
-
Move the cursor one column to the left (<)
-
-
Move the cursor one column to the right (>)
-
-
Jump to the first row in the current column (CTRL-Up)
-
-
Jump to the last row in the current column (CTRL-Down)
-
-
-
+
+
+
+
+
+
+igrid help
+
+
+
igrid help
+
+
+
Commands
+
+
+
pick (P)
+
Pick the whole row (object is available as "_")
+
+
pickattr (Shift-P)
+
Pick the attribute under the cursor
+
+
pickallattrs (Shift-C)
+
Pick' the complete column under the cursor (i.e. the attribute under the
+cursor) from all currently fetched objects. These attributes will be returned
+as a list.
+
+
enter (E)
+
Enter the object under the cursor. (what this mean depends on the object
+itself, i.e. how it implements iteration). This opens a new browser 'level'.
+
+
enterattr (Shift-E)
+
Enter the attribute under the cursor.
+
+
detail (D)
+
Show a detail view of the object under the cursor. This shows the name,
+type, doc string and value of the object attributes (and it might show more
+attributes than in the list view, depending on the object).
+
+
detailattr (Shift-D)
+
Show a detail view of the attribute under the cursor.
+
+
pickrows (M)
+
Pick multiple selected rows (M)
+
+
pickrowsattr (CTRL-M)
+
From multiple selected rows pick the cells matching the attribute the cursor is in (CTRL-M)
+
+
find (CTRL-F)
+
Find text
+
+
find_next (F3)
+
Find next occurrence of the searchtext
+
+
find_previous (Shift-F3)
+
Find previous occurrence of the searchtext
+
+
sortattrasc (V)
+
Sort the objects (in ascending order) using the attribute under the cursor as the sort key.
+
+
sortattrdesc (Shift-V)
+
Sort the objects (in descending order) using the attribute under the cursor as the sort key.
+
+
leave (Backspace, DEL, X)
+
Close current tab (and all the tabs to the right of the current one).
+
+
quit (ESC,Q)
+
Quit igrid and return to the IPython prompt.
+
+
+
Navigation
+
+
+
Jump to the last column of the current row (END, CTRL-E, CTRL-Right)
+
+
Jump to the first column of the current row (HOME, CTRL-A, CTRL-Left)
+
+
Move the cursor one column to the left (<)
+
+
Move the cursor one column to the right (>)
+
+
Jump to the first row in the current column (CTRL-Up)
+
+
Jump to the last row in the current column (CTRL-Down)
+
+
+
diff --git a/IPython/Extensions/ipy_app_completers.py b/IPython/Extensions/ipy_app_completers.py
index 4d2ca5b..629ef79 100644
--- a/IPython/Extensions/ipy_app_completers.py
+++ b/IPython/Extensions/ipy_app_completers.py
@@ -14,4 +14,6 @@ from ipy_completers import *
ip.set_hook('complete_command', apt_completer, re_key = '.*apt-get')
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')
+
+# the old bzr completer is deprecated, we recommend ipy_bzr
+#ip.set_hook('complete_command', bzr_completer, str_key = 'bzr')
diff --git a/IPython/Extensions/ipy_autoreload.py b/IPython/Extensions/ipy_autoreload.py
new file mode 100644
index 0000000..5e71c78
--- /dev/null
+++ b/IPython/Extensions/ipy_autoreload.py
@@ -0,0 +1,244 @@
+"""
+IPython extension: autoreload modules before executing the next line
+
+Try::
+
+ %autoreload?
+
+for documentation.
+"""
+
+# Pauli Virtanen , 2008.
+# Thomas Heller, 2000.
+#
+# This IPython module is written by Pauli Virtanen, based on the autoreload
+# code by Thomas Heller.
+
+#------------------------------------------------------------------------------
+# Autoreload functionality
+#------------------------------------------------------------------------------
+
+import time, os, threading, sys, types, imp, inspect, traceback, atexit
+
+def _get_compiled_ext():
+ """Official way to get the extension of compiled files (.pyc or .pyo)"""
+ for ext, mode, typ in imp.get_suffixes():
+ if typ == imp.PY_COMPILED:
+ return ext
+
+PY_COMPILED_EXT = _get_compiled_ext()
+
+class ModuleReloader(object):
+ skipped = {}
+ """Modules that failed to reload: {module: mtime-on-failed-reload, ...}"""
+
+ modules = {}
+ """Modules specially marked as autoreloadable."""
+
+ skip_modules = {}
+ """Modules specially marked as not autoreloadable."""
+
+ check_all = True
+ """Autoreload all modules, not just those listed in 'modules'"""
+
+ def check(self, check_all=False):
+ """Check whether some modules need to be reloaded."""
+
+ if check_all or self.check_all:
+ modules = sys.modules.keys()
+ else:
+ modules = self.modules.keys()
+
+ for modname in modules:
+ m = sys.modules.get(modname, None)
+
+ if modname in self.skip_modules:
+ continue
+
+ if not hasattr(m, '__file__'):
+ continue
+
+ if m.__name__ == '__main__':
+ # we cannot reload(__main__)
+ continue
+
+ filename = m.__file__
+ dirname = os.path.dirname(filename)
+ path, ext = os.path.splitext(filename)
+
+ if ext.lower() == '.py':
+ ext = PY_COMPILED_EXT
+ filename = os.path.join(dirname, path + PY_COMPILED_EXT)
+
+ if ext != PY_COMPILED_EXT:
+ continue
+
+ try:
+ pymtime = os.stat(filename[:-1]).st_mtime
+ if pymtime <= os.stat(filename).st_mtime:
+ continue
+ if self.skipped.get(filename[:-1], None) == pymtime:
+ continue
+ except OSError:
+ continue
+
+ try:
+ superreload(m)
+ if filename[:-1] in self.skipped:
+ del self.skipped[filename[:-1]]
+ except:
+ self.skipped[filename[:-1]] = pymtime
+
+def update_function(old, new, attrnames):
+ for name in attrnames:
+ setattr(old, name, getattr(new, name))
+
+def superreload(module, reload=reload):
+ """Enhanced version of the builtin reload function.
+
+ superreload replaces the class dictionary of every top-level
+ class in the module with the new one automatically,
+ as well as every function's code object.
+
+ """
+
+ module = reload(module)
+
+ # iterate over all objects and update them
+ count = 0
+ for name, new_obj in module.__dict__.items():
+ key = (module.__name__, name)
+ if _old_objects.has_key(key):
+ for old_obj in _old_objects[key]:
+ if type(new_obj) == types.ClassType:
+ old_obj.__dict__.update(new_obj.__dict__)
+ count += 1
+ elif type(new_obj) == types.FunctionType:
+ update_function(old_obj,
+ new_obj,
+ "func_code func_defaults func_doc".split())
+ count += 1
+ elif type(new_obj) == types.MethodType:
+ update_function(old_obj.im_func,
+ new_obj.im_func,
+ "func_code func_defaults func_doc".split())
+ count += 1
+
+ return module
+
+reloader = ModuleReloader()
+
+#------------------------------------------------------------------------------
+# IPython monkey-patching
+#------------------------------------------------------------------------------
+
+import IPython.iplib
+
+autoreload_enabled = False
+
+def runcode_hook(self):
+ if not autoreload_enabled:
+ raise IPython.ipapi.TryNext
+ try:
+ reloader.check()
+ except:
+ pass
+
+
+def enable_autoreload():
+ global autoreload_enabled
+ autoreload_enabled = True
+
+
+def disable_autoreload():
+ global autoreload_enabled
+ autoreload_enabled = False
+
+#------------------------------------------------------------------------------
+# IPython connectivity
+#------------------------------------------------------------------------------
+
+import IPython.ipapi
+ip = IPython.ipapi.get()
+
+def autoreload_f(self, parameter_s=''):
+ r""" %autoreload => Reload modules automatically
+
+ %autoreload
+ Reload all modules (except thoses excluded by %aimport) automatically now.
+
+ %autoreload 1
+ Reload all modules imported with %aimport every time before executing
+ the Python code typed.
+
+ %autoreload 2
+ Reload all modules (except thoses excluded by %aimport) every time
+ before executing the Python code typed.
+
+ Reloading Python modules in a reliable way is in general
+ difficult, and unexpected things may occur. Some of the common
+ caveats relevant for 'autoreload' are:
+
+ - Modules are not reloaded in any specific order, and no dependency
+ analysis is done. For example, modules with 'from xxx import foo'
+ retain old versions of 'foo' when 'xxx' is autoreloaded.
+ - Functions or objects imported from the autoreloaded module to
+ the interactive namespace are not updated.
+ - C extension modules cannot be reloaded, and so cannot be
+ autoreloaded.
+ """
+ if parameter_s == '':
+ reloader.check(True)
+ elif parameter_s == '0':
+ disable_autoreload()
+ elif parameter_s == '1':
+ reloader.check_all = False
+ enable_autoreload()
+ elif parameter_s == '2':
+ reloader.check_all = True
+ enable_autoreload()
+
+def aimport_f(self, parameter_s=''):
+ """%aimport => Import modules for automatic reloading.
+
+ %aimport
+ List modules to automatically import and not to import.
+
+ %aimport foo
+ Import module 'foo' and mark it to be autoreloaded for %autoreload 1
+
+ %aimport -foo
+ Mark module 'foo' to not be autoreloaded for %autoreload 1
+
+ """
+
+ modname = parameter_s
+ if not modname:
+ to_reload = reloader.modules.keys()
+ to_reload.sort()
+ to_skip = reloader.skip_modules.keys()
+ to_skip.sort()
+ if reloader.check_all:
+ print "Modules to reload:\nall-expect-skipped"
+ else:
+ print "Modules to reload:\n%s" % ' '.join(to_reload)
+ print "\nModules to skip:\n%s" % ' '.join(to_skip)
+ elif modname.startswith('-'):
+ modname = modname[1:]
+ try: del reloader.modules[modname]
+ except KeyError: pass
+ reloader.skip_modules[modname] = True
+ else:
+ try: del reloader.skip_modules[modname]
+ except KeyError: pass
+ reloader.modules[modname] = True
+
+ mod = __import__(modname)
+ ip.to_user_ns({modname: mod})
+
+def init():
+ ip.expose_magic('autoreload', autoreload_f)
+ ip.expose_magic('aimport', aimport_f)
+ ip.set_hook('pre_runcode_hook', runcode_hook)
+
+init()
\ No newline at end of file
diff --git a/IPython/Extensions/ipy_bzr.py b/IPython/Extensions/ipy_bzr.py
new file mode 100644
index 0000000..873a84f
--- /dev/null
+++ b/IPython/Extensions/ipy_bzr.py
@@ -0,0 +1,343 @@
+""" Extension for bzr command tab completer. Supports comlpeting commands and options
+
+Unlike the core IPython, you should note that this extension is under GPL, not BSD.
+
+Based on "shell" bzr plugin by Aaron Bentley, license is below. The IPython additions
+are at the bottom of the file, the rest is left untouched.
+
+Must be loaded with ip.load('ipy_bzr')
+
+"""
+
+# Copyright (C) 2004, 2005 Aaron Bentley
+#
+#
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 2 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software
+# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+
+import cmd
+from itertools import chain
+import os
+import shlex
+import stat
+import string
+import sys
+
+from bzrlib import osutils
+from bzrlib.branch import Branch
+from bzrlib.config import config_dir, ensure_config_dir_exists
+from bzrlib.commands import get_cmd_object, get_all_cmds, get_alias
+from bzrlib.errors import BzrError
+from bzrlib.workingtree import WorkingTree
+import bzrlib.plugin
+
+
+SHELL_BLACKLIST = set(['rm', 'ls'])
+COMPLETION_BLACKLIST = set(['shell'])
+
+
+class BlackListedCommand(BzrError):
+ def __init__(self, command):
+ BzrError.__init__(self, "The command %s is blacklisted for shell use" %
+ command)
+
+
+class CompletionContext(object):
+ def __init__(self, text, command=None, prev_opt=None, arg_pos=None):
+ self.text = text
+ self.command = command
+ self.prev_opt = prev_opt
+ self.arg_pos = None
+
+ def get_completions(self):
+ try:
+ return self.get_completions_or_raise()
+ except Exception, e:
+ print e, type(e)
+ return []
+
+ def get_option_completions(self):
+ try:
+ command_obj = get_cmd_object(self.command)
+ except BzrError:
+ return []
+ opts = [o+" " for o in iter_opt_completions(command_obj)]
+ return list(filter_completions(opts, self.text))
+
+ def get_completions_or_raise(self):
+ if self.command is None:
+ if '/' in self.text:
+ iter = iter_executables(self.text)
+ else:
+ iter = (c+" " for c in iter_command_names() if
+ c not in COMPLETION_BLACKLIST)
+ return list(filter_completions(iter, self.text))
+ if self.prev_opt is None:
+ completions = self.get_option_completions()
+ if self.command == "cd":
+ iter = iter_dir_completions(self.text)
+ completions.extend(list(filter_completions(iter, self.text)))
+ else:
+ iter = iter_file_completions(self.text)
+ completions.extend(filter_completions(iter, self.text))
+ return completions
+
+
+class PromptCmd(cmd.Cmd):
+
+ def __init__(self):
+ cmd.Cmd.__init__(self)
+ self.prompt = "bzr> "
+ try:
+ self.tree = WorkingTree.open_containing('.')[0]
+ except:
+ self.tree = None
+ self.set_title()
+ self.set_prompt()
+ self.identchars += '-'
+ ensure_config_dir_exists()
+ self.history_file = osutils.pathjoin(config_dir(), 'shell-history')
+ readline.set_completer_delims(string.whitespace)
+ if os.access(self.history_file, os.R_OK) and \
+ os.path.isfile(self.history_file):
+ readline.read_history_file(self.history_file)
+ self.cwd = os.getcwd()
+
+ def write_history(self):
+ readline.write_history_file(self.history_file)
+
+ def do_quit(self, args):
+ self.write_history()
+ raise StopIteration
+
+ def do_exit(self, args):
+ self.do_quit(args)
+
+ def do_EOF(self, args):
+ print
+ self.do_quit(args)
+
+ def postcmd(self, line, bar):
+ self.set_title()
+ self.set_prompt()
+
+ def set_prompt(self):
+ if self.tree is not None:
+ try:
+ prompt_data = (self.tree.branch.nick, self.tree.branch.revno(),
+ self.tree.relpath('.'))
+ prompt = " %s:%d/%s" % prompt_data
+ except:
+ prompt = ""
+ else:
+ prompt = ""
+ self.prompt = "bzr%s> " % prompt
+
+ def set_title(self, command=None):
+ try:
+ b = Branch.open_containing('.')[0]
+ version = "%s:%d" % (b.nick, b.revno())
+ except:
+ version = "[no version]"
+ if command is None:
+ command = ""
+ sys.stdout.write(terminal.term_title("bzr %s %s" % (command, version)))
+
+ def do_cd(self, line):
+ if line == "":
+ line = "~"
+ line = os.path.expanduser(line)
+ if os.path.isabs(line):
+ newcwd = line
+ else:
+ newcwd = self.cwd+'/'+line
+ newcwd = os.path.normpath(newcwd)
+ try:
+ os.chdir(newcwd)
+ self.cwd = newcwd
+ except Exception, e:
+ print e
+ try:
+ self.tree = WorkingTree.open_containing(".")[0]
+ except:
+ self.tree = None
+
+ def do_help(self, line):
+ self.default("help "+line)
+
+ def default(self, line):
+ args = shlex.split(line)
+ alias_args = get_alias(args[0])
+ if alias_args is not None:
+ args[0] = alias_args.pop(0)
+
+ commandname = args.pop(0)
+ for char in ('|', '<', '>'):
+ commandname = commandname.split(char)[0]
+ if commandname[-1] in ('|', '<', '>'):
+ commandname = commandname[:-1]
+ try:
+ if commandname in SHELL_BLACKLIST:
+ raise BlackListedCommand(commandname)
+ cmd_obj = get_cmd_object(commandname)
+ except (BlackListedCommand, BzrError):
+ return os.system(line)
+
+ try:
+ if too_complicated(line):
+ return os.system("bzr "+line)
+ else:
+ return (cmd_obj.run_argv_aliases(args, alias_args) or 0)
+ except BzrError, e:
+ print e
+ except KeyboardInterrupt, e:
+ print "Interrupted"
+ except Exception, e:
+# print "Unhandled error:\n%s" % errors.exception_str(e)
+ print "Unhandled error:\n%s" % (e)
+
+
+ def completenames(self, text, line, begidx, endidx):
+ return CompletionContext(text).get_completions()
+
+ def completedefault(self, text, line, begidx, endidx):
+ """Perform completion for native commands.
+
+ :param text: The text to complete
+ :type text: str
+ :param line: The entire line to complete
+ :type line: str
+ :param begidx: The start of the text in the line
+ :type begidx: int
+ :param endidx: The end of the text in the line
+ :type endidx: int
+ """
+ (cmd, args, foo) = self.parseline(line)
+ if cmd == "bzr":
+ cmd = None
+ return CompletionContext(text, command=cmd).get_completions()
+
+
+def run_shell():
+ try:
+ prompt = PromptCmd()
+ try:
+ prompt.cmdloop()
+ finally:
+ prompt.write_history()
+ except StopIteration:
+ pass
+
+
+def iter_opt_completions(command_obj):
+ for option_name, option in command_obj.options().items():
+ yield "--" + option_name
+ short_name = option.short_name()
+ if short_name:
+ yield "-" + short_name
+
+
+def iter_file_completions(arg, only_dirs = False):
+ """Generate an iterator that iterates through filename completions.
+
+ :param arg: The filename fragment to match
+ :type arg: str
+ :param only_dirs: If true, match only directories
+ :type only_dirs: bool
+ """
+ cwd = os.getcwd()
+ if cwd != "/":
+ extras = [".", ".."]
+ else:
+ extras = []
+ (dir, file) = os.path.split(arg)
+ if dir != "":
+ listingdir = os.path.expanduser(dir)
+ else:
+ listingdir = cwd
+ for file in chain(os.listdir(listingdir), extras):
+ if dir != "":
+ userfile = dir+'/'+file
+ else:
+ userfile = file
+ if userfile.startswith(arg):
+ if os.path.isdir(listingdir+'/'+file):
+ userfile+='/'
+ yield userfile
+ elif not only_dirs:
+ yield userfile + ' '
+
+
+def iter_dir_completions(arg):
+ """Generate an iterator that iterates through directory name completions.
+
+ :param arg: The directory name fragment to match
+ :type arg: str
+ """
+ return iter_file_completions(arg, True)
+
+
+def iter_command_names(hidden=False):
+ for real_cmd_name, cmd_class in get_all_cmds():
+ if not hidden and cmd_class.hidden:
+ continue
+ for name in [real_cmd_name] + cmd_class.aliases:
+ # Don't complete on aliases that are prefixes of the canonical name
+ if name == real_cmd_name or not real_cmd_name.startswith(name):
+ yield name
+
+
+def iter_executables(path):
+ dirname, partial = os.path.split(path)
+ for filename in os.listdir(dirname):
+ if not filename.startswith(partial):
+ continue
+ fullpath = os.path.join(dirname, filename)
+ mode=os.lstat(fullpath)[stat.ST_MODE]
+ if stat.S_ISREG(mode) and 0111 & mode:
+ yield fullpath + ' '
+
+
+def filter_completions(iter, arg):
+ return (c for c in iter if c.startswith(arg))
+
+
+def iter_munged_completions(iter, arg, text):
+ for completion in iter:
+ completion = str(completion)
+ if completion.startswith(arg):
+ yield completion[len(arg)-len(text):]+" "
+
+
+def too_complicated(line):
+ for char in '|<>*?':
+ if char in line:
+ return True
+ return False
+
+
+### IPython mods start
+
+def init_ipython(ip):
+ def bzr_completer(self,ev):
+ #print "bzr complete"
+ tup = ev.line.split(None,2)
+ if len(tup) > 2:
+ cmd = tup[1]
+ else:
+ cmd = None
+
+ return CompletionContext(ev.symbol, command = cmd).get_completions()
+ bzrlib.plugin.load_plugins()
+ ip.set_hook('complete_command', bzr_completer, str_key = 'bzr')
diff --git a/IPython/Extensions/ipy_completers.py b/IPython/Extensions/ipy_completers.py
index f1b3f78..1e88db4 100644
--- a/IPython/Extensions/ipy_completers.py
+++ b/IPython/Extensions/ipy_completers.py
@@ -1,4 +1,3 @@
-#!/usr/bin/env python
""" Implementations for various useful completers
@@ -12,6 +11,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,13 +86,18 @@ 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,'*'))
folder_list = [p for p in folder_list \
if os.path.exists(os.path.join(path, p,'__init__.py'))\
or p[-3:] in ('.py','.so')\
- or p[-4:] in ('.pyc','.pyo')]
+ or p[-4:] in ('.pyc','.pyo','.pyd')]
folder_list = [os.path.basename(p).split('.')[0] for p in folder_list]
return folder_list
@@ -211,15 +216,15 @@ def hg_completer(self,event):
-bzr_commands = """
-add annotate bind branch break-lock bundle-revisions cat check
-checkout commit conflicts deleted diff export gannotate gbranch
-gcommit gdiff help ignore ignored info init init-repository inventory
-log merge missing mkdir mv nick pull push reconcile register-branch
-remerge remove renames resolve revert revno root serve sign-my-commits
-status testament unbind uncommit unknowns update upgrade version
-version-info visualise whoami
-"""
+__bzr_commands = None
+
+def bzr_commands():
+ global __bzr_commands
+ if __bzr_commands is not None:
+ return __bzr_commands
+ out = os.popen('bzr help commands')
+ __bzr_commands = [l.split()[0] for l in out]
+ return __bzr_commands
def bzr_completer(self,event):
""" Completer for bazaar commands """
@@ -232,7 +237,7 @@ def bzr_completer(self,event):
param = cmd_param[-1]
output_file = (param == '--output=')
if cmd == 'help':
- return bzr_commands.split()
+ return bzr_commands()
elif cmd in ['bundle-revisions','conflicts',
'deleted','nick','register-branch',
'serve','unbind','upgrade','version',
@@ -242,7 +247,7 @@ def bzr_completer(self,event):
# the rest are probably file names
return ip.IP.Completer.file_matches(event.symbol)
- return bzr_commands.split()
+ return bzr_commands()
def shlex_split(x):
@@ -326,7 +331,29 @@ def cd_completer(self, event):
if os.path.isdir(relpath):
return [relpath]
raise IPython.ipapi.TryNext
- return found
+
+
+ def single_dir_expand(matches):
+ "Recursively expand match lists containing a single dir."
+
+ if len(matches) == 1 and os.path.isdir(matches[0]):
+ # Takes care of links to directories also. Use '/'
+ # explicitly, even under Windows, so that name completions
+ # don't end up escaped.
+ d = matches[0]
+ if d[-1] in ['/','\\']:
+ d = d[:-1]
+
+ subdirs = [p for p in os.listdir(d) if os.path.isdir( d + '/' + p)]
+ if subdirs:
+ matches = [ (d + '/' + p) for p in subdirs ]
+ return single_dir_expand(matches)
+ else:
+ return matches
+ else:
+ return matches
+
+ return single_dir_expand(found)
def apt_get_packages(prefix):
out = os.popen('apt-cache pkgnames')
diff --git a/IPython/Extensions/ipy_greedycompleter.py b/IPython/Extensions/ipy_greedycompleter.py
new file mode 100644
index 0000000..3b44751
--- /dev/null
+++ b/IPython/Extensions/ipy_greedycompleter.py
@@ -0,0 +1,75 @@
+""" Greedy completer extension for IPython
+
+Normal tab completer refuses to evaluate nonsafe stuff. This will evaluate
+everything, so you need to consider the consequences of pressing tab
+yourself!
+
+Note that this extension simplifies readline interaction by setting
+only whitespace as completer delimiter. If this works well, we will
+do the same in default completer.
+
+"""
+from IPython import generics,ipapi
+from IPython.genutils import dir2
+
+def attr_matches(self, text):
+ """Compute matches when text contains a dot.
+
+ MONKEYPATCHED VERSION (ipy_greedycompleter.py)
+
+ Assuming the text is of the form NAME.NAME....[NAME], and is
+ evaluatable in self.namespace or self.global_namespace, it will be
+ evaluated and its attributes (as revealed by dir()) are used as
+ possible completions. (For class instances, class members are are
+ also considered.)
+
+ WARNING: this can still invoke arbitrary C code, if an object
+ with a __getattr__ hook is evaluated.
+
+ """
+ import re
+
+ force_complete = 1
+ # Another option, seems to work great. Catches things like ''.
+ m = re.match(r"(\S+(\.\w+)*)\.(\w*)$", text)
+
+ if m:
+ expr, attr = m.group(1, 3)
+ else:
+ # force match - eval anything that ends with colon
+ if not force_complete:
+ return []
+
+ m2 = re.match(r"(.+)\.(\w*)$", self.lbuf)
+ if not m2:
+ return []
+ expr, attr = m2.group(1,2)
+
+
+ try:
+ obj = eval(expr, self.namespace)
+ except:
+ try:
+ obj = eval(expr, self.global_namespace)
+ except:
+ return []
+
+ words = dir2(obj)
+
+ try:
+ words = generics.complete_object(obj, words)
+ except ipapi.TryNext:
+ pass
+ # Build match list to return
+ n = len(attr)
+ res = ["%s.%s" % (expr, w) for w in words if w[:n] == attr ]
+ return res
+
+def main():
+ import readline
+ readline.set_completer_delims(" \n\t")
+ # monkeypatch - the code will be folded to normal completer later on
+ import IPython.completer
+ IPython.completer.Completer.attr_matches = attr_matches
+
+main()
\ No newline at end of file
diff --git a/IPython/Extensions/ipy_jot.py b/IPython/Extensions/ipy_jot.py
new file mode 100644
index 0000000..dd71967
--- /dev/null
+++ b/IPython/Extensions/ipy_jot.py
@@ -0,0 +1,311 @@
+# -*- coding: utf-8 -*-
+"""
+%jot magic for lightweight persistence.
+
+Stores variables in Struct with some notes in PicleShare database
+
+
+"""
+
+from datetime import datetime
+import IPython.ipapi
+ip = IPython.ipapi.get()
+
+import pickleshare
+
+import inspect,pickle,os,sys,textwrap
+from IPython.FakeModule import FakeModule
+from IPython.ipstruct import Struct
+
+
+def refresh_variables(ip, key=None):
+ db = ip.db
+ if key is None:
+ keys = db.keys('jot/*')
+ else:
+ keys = db.keys('jot/'+key)
+ for key in keys:
+ # strip autorestore
+ justkey = os.path.basename(key)
+ print "Restoring from", justkey, "..."
+ try:
+ obj = db[key]
+ except KeyError:
+ print "Unable to restore variable '%s', ignoring (use %%jot -d to forget!)" % justkey
+ print "The error was:",sys.exc_info()[0]
+ else:
+ #print "restored",justkey,"=",obj #dbg
+ try:
+ origname = obj.name
+ except:
+ ip.user_ns[justkey] = obj
+ print "Restored", justkey
+ else:
+ ip.user_ns[origname] = obj['val']
+ print "Restored", origname
+
+def read_variables(ip, key=None):
+ db = ip.db
+ if key is None:
+ return None
+ else:
+ keys = db.keys('jot/'+key)
+ for key in keys:
+ # strip autorestore
+ justkey = os.path.basename(key)
+ print "restoring from ", justkey
+ try:
+ obj = db[key]
+ except KeyError:
+ print "Unable to read variable '%s', ignoring (use %%jot -d to forget!)" % justkey
+ print "The error was:",sys.exc_info()[0]
+ else:
+ return obj
+
+
+def detail_variables(ip, key=None):
+ db, get = ip.db, ip.db.get
+
+ if key is None:
+ keys = db.keys('jot/*')
+ else:
+ keys = db.keys('jot/'+key)
+ if keys:
+ size = max(map(len,keys))
+ else:
+ size = 0
+
+ fmthead = '%-'+str(size)+'s [%s]'
+ fmtbody = 'Comment:\n %s'
+ fmtdata = 'Data:\n %s, %s'
+ for key in keys:
+ v = get(key,'')
+ justkey = os.path.basename(key)
+ try:
+ print fmthead % (justkey, datetime.ctime(v.get('time','')))
+ print fmtbody % (v.get('comment',''))
+ d = v.get('val','unavailable')
+ print fmtdata % (repr(type(d)), '')
+ print repr(d)[0:200]
+ print
+ print
+ except AttributeError:
+ print fmt % (justkey, '', '', repr(v)[:50])
+
+
+def intm(n):
+ try:
+ return int(n)
+ except:
+ return 0
+
+def jot_obj(self, obj, name, comment=''):
+ """
+ write obj data to the note database, with whatever that should be noted.
+ """
+ had = self.db.keys('jot/'+name+'*')
+ # if it the same name but a later version, we stupidly add a number to the
+ # so the name doesn't collide. Any better idea?
+ suffix = ''
+ if len(had)>0:
+ pre = os.path.commonprefix(had)
+ suf = [n.split(pre)[1] for n in had]
+ versions = map(intm, suf)
+ suffix = str(max(versions)+1)
+
+ uname = 'jot/'+name+suffix
+
+ # which one works better?
+ #all = ip.IP.shadowhist.all()
+ all = ip.IP.shell.input_hist
+
+ # We may actually want to make snapshot of files that are run-ned.
+
+ # get the comment
+ try:
+ comment = ip.IP.magic_edit('-x').strip()
+ except:
+ print "No comment is recorded."
+ comment = ''
+
+ self.db[uname] = Struct({'val':obj,
+ 'time' : datetime.now(),
+ 'hist' : all,
+ 'name' : name,
+ 'comment' : comment,})
+
+ print "Jotted down notes for '%s' (%s)" % (uname, obj.__class__.__name__)
+
+
+
+def magic_jot(self, parameter_s=''):
+ """Lightweight persistence for python variables.
+
+ Example:
+
+ ville@badger[~]|1> A = ['hello',10,'world']\\
+ ville@badger[~]|2> %jot A\\
+ ville@badger[~]|3> Exit
+
+ (IPython session is closed and started again...)
+
+ ville@badger:~$ ipython -p pysh\\
+ ville@badger[~]|1> print A
+
+ ['hello', 10, 'world']
+
+ Usage:
+
+ %jot - Show list of all variables and their current values\\
+ %jot -l - Show list of all variables and their current values in detail\\
+ %jot -l - Show one variable and its current values in detail\\
+ %jot - Store the *current* value of the variable to disk\\
+ %jot -d - Remove the variable and its value from storage\\
+ %jot -z - Remove all variables from storage (disabled)\\
+ %jot -r - Refresh/Load variable from jot (delete current vals)\\
+ %jot foo >a.txt - Store value of foo to new file a.txt\\
+ %jot foo >>a.txt - Append value of foo to file a.txt\\
+
+ It should be noted that if you change the value of a variable, you
+ need to %note it again if you want to persist the new value.
+
+ Note also that the variables will need to be pickleable; most basic
+ python types can be safely %stored.
+
+ """
+
+ opts,argsl = self.parse_options(parameter_s,'drzl',mode='string')
+ args = argsl.split(None,1)
+ ip = self.getapi()
+ db = ip.db
+ # delete
+ if opts.has_key('d'):
+ try:
+ todel = args[0]
+ except IndexError:
+ error('You must provide the variable to forget')
+ else:
+ try:
+ del db['jot/' + todel]
+ except:
+ error("Can't delete variable '%s'" % todel)
+ # reset the whole database
+ elif opts.has_key('z'):
+ print "reseting the whole database has been disabled."
+ #for k in db.keys('autorestore/*'):
+ # del db[k]
+
+ elif opts.has_key('r'):
+ try:
+ toret = args[0]
+ except:
+ print "restoring all the variables jotted down..."
+ refresh_variables(ip)
+ else:
+ refresh_variables(ip, toret)
+
+ elif opts.has_key('l'):
+ try:
+ tolist = args[0]
+ except:
+ print "List details for all the items."
+ detail_variables(ip)
+ else:
+ print "Details for", tolist, ":"
+ detail_variables(ip, tolist)
+
+ # run without arguments -> list noted variables & notes
+ elif not args:
+ vars = self.db.keys('jot/*')
+ vars.sort()
+ if vars:
+ size = max(map(len,vars)) - 4
+ else:
+ size = 0
+
+ print 'Variables and their in-db values:'
+ fmt = '%-'+str(size)+'s [%s] -> %s'
+ get = db.get
+ for var in vars:
+ justkey = os.path.basename(var)
+ v = get(var,'')
+ try:
+ print fmt % (justkey,\
+ datetime.ctime(v.get('time','')),\
+ v.get('comment','')[:70].replace('\n',' '),)
+ except AttributeError:
+ print fmt % (justkey, '', '', repr(v)[:50])
+
+
+ # default action - store the variable
+ else:
+ # %store foo >file.txt or >>file.txt
+ if len(args) > 1 and args[1].startswith('>'):
+ fnam = os.path.expanduser(args[1].lstrip('>').lstrip())
+ if args[1].startswith('>>'):
+ fil = open(fnam,'a')
+ else:
+ fil = open(fnam,'w')
+ obj = ip.ev(args[0])
+ print "Writing '%s' (%s) to file '%s'." % (args[0],
+ obj.__class__.__name__, fnam)
+
+
+ if not isinstance (obj,basestring):
+ from pprint import pprint
+ pprint(obj,fil)
+ else:
+ fil.write(obj)
+ if not obj.endswith('\n'):
+ fil.write('\n')
+
+ fil.close()
+ return
+
+ # %note foo
+ try:
+ obj = ip.user_ns[args[0]]
+ except KeyError:
+ # this should not be alias, for aliases, use %store
+ print
+ print "Error: %s doesn't exist." % args[0]
+ print
+ print "Use %note -r to retrieve variables. This should not be used " +\
+ "to store alias, for saving aliases, use %store"
+ return
+ else:
+ if isinstance(inspect.getmodule(obj), FakeModule):
+ print textwrap.dedent("""\
+ Warning:%s is %s
+ Proper storage of interactively declared classes (or instances
+ of those classes) is not possible! Only instances
+ of classes in real modules on file system can be %%store'd.
+ """ % (args[0], obj) )
+ return
+ #pickled = pickle.dumps(obj)
+ #self.db[ 'jot/' + args[0] ] = obj
+ jot_obj(self, obj, args[0])
+
+
+def magic_read(self, parameter_s=''):
+ """
+ %read - Load variable from data that is jotted down.\\
+
+ """
+
+ opts,argsl = self.parse_options(parameter_s,'drzl',mode='string')
+ args = argsl.split(None,1)
+ ip = self.getapi()
+ db = ip.db
+ #if opts.has_key('r'):
+ try:
+ toret = args[0]
+ except:
+ print "which record do you want to read out?"
+ return
+ else:
+ return read_variables(ip, toret)
+
+
+ip.expose_magic('jot',magic_jot)
+ip.expose_magic('read',magic_read)
diff --git a/IPython/Extensions/ipy_leo.py b/IPython/Extensions/ipy_leo.py
index c20b639..124292a 100644
--- a/IPython/Extensions/ipy_leo.py
+++ b/IPython/Extensions/ipy_leo.py
@@ -1,248 +1,592 @@
-""" Leo plugin for IPython
-
-Example use:
-
-nodes.foo = "hello world"
-
- -> create '@ipy foo' node with text "hello world"
-
-Access works also, and so does tab completion.
-
-"""
-import IPython.ipapi
-import IPython.genutils
-import IPython.generics
-import re
-
-
-
-ip = IPython.ipapi.get()
-leo = ip.user_ns['leox']
-c,g = leo.c, leo.g
-
-# will probably be overwritten by user, but handy for experimentation early on
-ip.user_ns['c'] = c
-ip.user_ns['g'] = g
-
-
-from IPython.external.simplegeneric import generic
-import pprint
-
-@generic
-def format_for_leo(obj):
- """ Convert obj to string representiation (for editing in Leo)"""
- return pprint.pformat(obj)
-
-@format_for_leo.when_type(list)
-def format_list(obj):
- return "\n".join(str(s) for s in obj)
-
-nodename_re = r'(@ipy?[\w-]+)?\s?(\w+)'
-
-def all_cells():
- d = {}
- for p in c.allNodes_iter():
- h = p.headString()
- if h.startswith('@') and len(h.split()) == 1:
- continue
- mo = re.match(nodename_re, h)
- if not mo:
- continue
- d[mo.group(2)] = p.copy()
- return d
-
-
-class TrivialLeoWorkbook:
- """ class to find cells with simple syntax
-
- """
- def __getattr__(self, key):
- cells = all_cells()
- p = cells[key]
- body = p.bodyString()
- return eval_body(body)
- def __setattr__(self,key,val):
- cells = all_cells()
- p = cells.get(key,None)
- if p is None:
- add_var(key,val)
- else:
- c.setBodyString(p,format_for_leo(val))
- def __str__(self):
- return ""
- __repr__ = __str__
-
-ip.user_ns['nodes'] = TrivialLeoWorkbook()
-
-
-class LeoNode(object):
- def __init__(self,p):
- self.p = p.copy()
-
- def get_h(self): return self.p.headString()
- def set_h(self,val):
- print "set head",val
- c.beginUpdate()
- try:
- c.setHeadString(self.p,val)
- finally:
- c.endUpdate()
-
- h = property( get_h, set_h)
-
- def get_b(self): return self.p.bodyString()
- def set_b(self,val):
- print "set body",val
- c.beginUpdate()
- try:
- c.setBodyString(self.p, val)
- finally:
- c.endUpdate()
-
- b = property(get_b, set_b)
-
- def set_val(self, val):
- self.b = pprint.pformat(val)
-
- v = property(lambda self: ip.ev(self.b.strip()), set_val)
-
- def set_l(self,val):
- self.b = '\n'.join(val )
- l = property(lambda self : IPython.genutils.SList(self.b.splitlines()),
- set_l)
-
- def __iter__(self):
- return (LeoNode(p) for p in self.p.children_iter())
-
-
-class LeoWorkbook:
- """ class for 'advanced' node access """
- def __getattr__(self, key):
- if key.startswith('_') or key == 'trait_names':
- raise AttributeError
- cells = all_cells()
- p = cells.get(key, None)
- if p is None:
- p = add_var(key,None)
-
- return LeoNode(p)
-
- def __str__(self):
- return ""
- __repr__ = __str__
-ip.user_ns['wb'] = LeoWorkbook()
-
-
-_dummyval = object()
-@IPython.generics.complete_object.when_type(LeoWorkbook)
-def workbook_complete(obj, prev):
- return all_cells().keys()
-
-
-def add_var(varname, value = _dummyval):
- c.beginUpdate()
- try:
-
- nodename = '@ipy-var ' + varname
- p2 = g.findNodeAnywhere(c,nodename)
- if not c.positionExists(p2):
- p2 = c.currentPosition().insertAfter()
- c.setHeadString(p2,'@ipy ' + varname)
-
- c.setCurrentPosition(p2)
- if value is _dummyval:
- val = ip.user_ns[varname]
- else:
- val = value
- if val is not None:
- formatted = format_for_leo(val)
- c.setBodyString(p2,formatted)
- return p2
- finally:
- c.endUpdate()
-
-def add_file(self,fname):
- p2 = c.currentPosition().insertAfter()
-
-def push_script(p):
- c.beginUpdate()
- try:
- ohist = ip.IP.output_hist
- hstart = len(ip.IP.input_hist)
- script = g.getScript(c,p,useSelectedText=False,forcePythonSentinels=False,useSentinels=False)
-
- script = g.splitLines(script + '\n')
- script = ''.join(z for z in script if z.strip())
-
- ip.runlines(script)
-
- has_output = False
- for idx in range(hstart,len(ip.IP.input_hist)):
- val = ohist.get(idx,None)
- if val is None:
- continue
- has_output = True
- inp = ip.IP.input_hist[idx]
- if inp.strip():
- g.es('In: %s' % (inp[:40], ), tabName = 'IPython')
-
- g.es('<%d> %s' % (idx, pprint.pformat(ohist[idx],width = 40)), tabName = 'IPython')
-
- if not has_output:
- g.es('ipy run: %s' %( p.headString(),), tabName = 'IPython')
- finally:
- c.endUpdate()
-
-
-def eval_body(body):
- try:
- val = ip.ev(body)
- except:
- # just use stringlist if it's not completely legal python expression
- val = IPython.genutils.SList(body.splitlines())
- return val
-
-def push_variable(p,varname):
- body = p.bodyString()
- val = eval_body(body.strip())
- ip.user_ns[varname] = val
- g.es('ipy var: %s' % (varname,), tabName = "IPython")
-
-def push_from_leo(p):
- tup = p.headString().split(None,1)
- # @ipy foo is variable foo
- if len(tup) == 2 and tup[0] == '@ipy':
- varname = tup[1]
- push_variable(p,varname)
- return
-
- push_script(p)
- return
-
-
-ip.user_ns['leox'].push = push_from_leo
-
-def leo_f(self,s):
- """ open file(s) in Leo
-
- Takes an mglob pattern, e.g. '%leo *.cpp' or %leo 'rec:*.cpp'
- """
- import os
- from IPython.external import mglob
-
- files = mglob.expand(s)
- c.beginUpdate()
- try:
- for fname in files:
- p = g.findNodeAnywhere(c,'@auto ' + fname)
- if not p:
- p = c.currentPosition().insertAfter()
-
- p.setHeadString('@auto ' + fname)
- if os.path.isfile(fname):
- c.setBodyString(p,open(fname).read())
- c.selectPosition(p)
- finally:
- c.endUpdate()
-
-ip.expose_magic('leo',leo_f)
+""" ILeo - Leo plugin for IPython
+
+
+"""
+import IPython.ipapi
+import IPython.genutils
+import IPython.generics
+from IPython.hooks import CommandChainDispatcher
+import re
+import UserDict
+from IPython.ipapi import TryNext
+import IPython.macro
+import IPython.Shell
+
+def init_ipython(ipy):
+ """ This will be run by _ip.load('ipy_leo')
+
+ Leo still needs to run update_commander() after this.
+
+ """
+ global ip
+ ip = ipy
+ IPython.Shell.hijack_tk()
+ ip.set_hook('complete_command', mb_completer, str_key = '%mb')
+ ip.expose_magic('mb',mb_f)
+ ip.expose_magic('lee',lee_f)
+ ip.expose_magic('leoref',leoref_f)
+ expose_ileo_push(push_cl_node,100)
+ # this should be the LAST one that will be executed, and it will never raise TryNext
+ expose_ileo_push(push_ipython_script, 1000)
+ expose_ileo_push(push_plain_python, 100)
+ expose_ileo_push(push_ev_node, 100)
+ global wb
+ wb = LeoWorkbook()
+ ip.user_ns['wb'] = wb
+
+ show_welcome()
+
+
+def update_commander(new_leox):
+ """ Set the Leo commander to use
+
+ This will be run every time Leo does ipython-launch; basically,
+ when the user switches the document he is focusing on, he should do
+ ipython-launch to tell ILeo what document the commands apply to.
+
+ """
+
+ global c,g
+ c,g = new_leox.c, new_leox.g
+ print "Set Leo Commander:",c.frame.getTitle()
+
+ # will probably be overwritten by user, but handy for experimentation early on
+ ip.user_ns['c'] = c
+ ip.user_ns['g'] = g
+ ip.user_ns['_leo'] = new_leox
+
+ new_leox.push = push_position_from_leo
+ run_leo_startup_node()
+
+from IPython.external.simplegeneric import generic
+import pprint
+
+def es(s):
+ g.es(s, tabName = 'IPython')
+ pass
+
+@generic
+def format_for_leo(obj):
+ """ Convert obj to string representiation (for editing in Leo)"""
+ return pprint.pformat(obj)
+
+@format_for_leo.when_type(list)
+def format_list(obj):
+ return "\n".join(str(s) for s in obj)
+
+
+attribute_re = re.compile('^[a-zA-Z_][a-zA-Z0-9_]*$')
+def valid_attribute(s):
+ return attribute_re.match(s)
+
+_rootnode = None
+def rootnode():
+ """ Get ileo root node (@ipy-root)
+
+ if node has become invalid or has not been set, return None
+
+ Note that the root is the *first* @ipy-root item found
+ """
+ global _rootnode
+ if _rootnode is None:
+ return None
+ if c.positionExists(_rootnode.p):
+ return _rootnode
+ _rootnode = None
+ return None
+
+def all_cells():
+ global _rootnode
+ d = {}
+ r = rootnode()
+ if r is not None:
+ nodes = r.p.children_iter()
+ else:
+ nodes = c.allNodes_iter()
+
+ for p in nodes:
+ h = p.headString()
+ if h.strip() == '@ipy-root':
+ # update root node (found it for the first time)
+ _rootnode = LeoNode(p)
+ # the next recursive call will use the children of new root
+ return all_cells()
+
+ if h.startswith('@a '):
+ d[h.lstrip('@a ').strip()] = p.parent().copy()
+ elif not valid_attribute(h):
+ continue
+ d[h] = p.copy()
+ return d
+
+def eval_node(n):
+ body = n.b
+ if not body.startswith('@cl'):
+ # plain python repr node, just eval it
+ return ip.ev(n.b)
+ # @cl nodes deserve special treatment - first eval the first line (minus cl), then use it to call the rest of body
+ first, rest = body.split('\n',1)
+ tup = first.split(None, 1)
+ # @cl alone SPECIAL USE-> dump var to user_ns
+ if len(tup) == 1:
+ val = ip.ev(rest)
+ ip.user_ns[n.h] = val
+ es("%s = %s" % (n.h, repr(val)[:20] ))
+ return val
+
+ cl, hd = tup
+
+ xformer = ip.ev(hd.strip())
+ es('Transform w/ %s' % repr(xformer))
+ return xformer(rest, n)
+
+class LeoNode(object, UserDict.DictMixin):
+ """ Node in Leo outline
+
+ Most important attributes (getters/setters available:
+ .v - evaluate node, can also be alligned
+ .b, .h - body string, headline string
+ .l - value as string list
+
+ Also supports iteration,
+
+ setitem / getitem (indexing):
+ wb.foo['key'] = 12
+ assert wb.foo['key'].v == 12
+
+ Note the asymmetry on setitem and getitem! Also other
+ dict methods are available.
+
+ .ipush() - run push-to-ipython
+
+ Minibuffer command access (tab completion works):
+
+ mb save-to-file
+
+ """
+ def __init__(self,p):
+ self.p = p.copy()
+
+ def __str__(self):
+ return "" % str(self.p)
+
+ __repr__ = __str__
+
+ def __get_h(self): return self.p.headString()
+ def __set_h(self,val):
+ print "set head",val
+ c.beginUpdate()
+ try:
+ c.setHeadString(self.p,val)
+ finally:
+ c.endUpdate()
+
+ h = property( __get_h, __set_h, doc = "Node headline string")
+
+ def __get_b(self): return self.p.bodyString()
+ def __set_b(self,val):
+ print "set body",val
+ c.beginUpdate()
+ try:
+ c.setBodyString(self.p, val)
+ finally:
+ c.endUpdate()
+
+ b = property(__get_b, __set_b, doc = "Nody body string")
+
+ def __set_val(self, val):
+ self.b = format_for_leo(val)
+
+ v = property(lambda self: eval_node(self), __set_val, doc = "Node evaluated value")
+
+ def __set_l(self,val):
+ self.b = '\n'.join(val )
+ l = property(lambda self : IPython.genutils.SList(self.b.splitlines()),
+ __set_l, doc = "Node value as string list")
+
+ def __iter__(self):
+ """ Iterate through nodes direct children """
+
+ return (LeoNode(p) for p in self.p.children_iter())
+
+ def __children(self):
+ d = {}
+ for child in self:
+ head = child.h
+ tup = head.split(None,1)
+ if len(tup) > 1 and tup[0] == '@k':
+ d[tup[1]] = child
+ continue
+
+ if not valid_attribute(head):
+ d[head] = child
+ continue
+ return d
+ def keys(self):
+ d = self.__children()
+ return d.keys()
+ def __getitem__(self, key):
+ """ wb.foo['Some stuff'] Return a child node with headline 'Some stuff'
+
+ If key is a valid python name (e.g. 'foo'), look for headline '@k foo' as well
+ """
+ key = str(key)
+ d = self.__children()
+ return d[key]
+ def __setitem__(self, key, val):
+ """ You can do wb.foo['My Stuff'] = 12 to create children
+
+ This will create 'My Stuff' as a child of foo (if it does not exist), and
+ do .v = 12 assignment.
+
+ Exception:
+
+ wb.foo['bar'] = 12
+
+ will create a child with headline '@k bar', because bar is a valid python name
+ and we don't want to crowd the WorkBook namespace with (possibly numerous) entries
+ """
+ key = str(key)
+ d = self.__children()
+ if key in d:
+ d[key].v = val
+ return
+
+ if not valid_attribute(key):
+ head = key
+ else:
+ head = '@k ' + key
+ p = c.createLastChildNode(self.p, head, '')
+ LeoNode(p).v = val
+
+ def ipush(self):
+ """ Does push-to-ipython on the node """
+ push_from_leo(self)
+
+ def go(self):
+ """ Set node as current node (to quickly see it in Outline) """
+ c.beginUpdate()
+ try:
+ c.setCurrentPosition(self.p)
+ finally:
+ c.endUpdate()
+
+ def script(self):
+ """ Method to get the 'tangled' contents of the node
+
+ (parse @others, << section >> references etc.)
+ """
+ return g.getScript(c,self.p,useSelectedText=False,useSentinels=False)
+
+ def __get_uA(self):
+ p = self.p
+ # Create the uA if necessary.
+ if not hasattr(p.v.t,'unknownAttributes'):
+ p.v.t.unknownAttributes = {}
+
+ d = p.v.t.unknownAttributes.setdefault('ipython', {})
+ return d
+
+ uA = property(__get_uA, doc = "Access persistent unknownAttributes of node")
+
+
+class LeoWorkbook:
+ """ class for 'advanced' node access
+
+ Has attributes for all "discoverable" nodes. Node is discoverable if it
+ either
+
+ - has a valid python name (Foo, bar_12)
+ - is a parent of an anchor node (if it has a child '@a foo', it is visible as foo)
+
+ """
+ def __getattr__(self, key):
+ if key.startswith('_') or key == 'trait_names' or not valid_attribute(key):
+ raise AttributeError
+ cells = all_cells()
+ p = cells.get(key, None)
+ if p is None:
+ return add_var(key)
+
+ return LeoNode(p)
+
+ def __str__(self):
+ return ""
+ def __setattr__(self,key, val):
+ raise AttributeError("Direct assignment to workbook denied, try wb.%s.v = %s" % (key,val))
+
+ __repr__ = __str__
+
+ def __iter__(self):
+ """ Iterate all (even non-exposed) nodes """
+ cells = all_cells()
+ return (LeoNode(p) for p in c.allNodes_iter())
+
+ current = property(lambda self: LeoNode(c.currentPosition()), doc = "Currently selected node")
+
+ def match_h(self, regex):
+ cmp = re.compile(regex)
+ for node in self:
+ if re.match(cmp, node.h, re.IGNORECASE):
+ yield node
+ return
+
+@IPython.generics.complete_object.when_type(LeoWorkbook)
+def workbook_complete(obj, prev):
+ return all_cells().keys() + [s for s in prev if not s.startswith('_')]
+
+
+def add_var(varname):
+ c.beginUpdate()
+ r = rootnode()
+ try:
+ if r is None:
+ p2 = g.findNodeAnywhere(c,varname)
+ else:
+ p2 = g.findNodeInChildren(c, r.p, varname)
+ if p2:
+ return LeoNode(p2)
+
+ if r is not None:
+ p2 = r.p.insertAsLastChild()
+
+ else:
+ p2 = c.currentPosition().insertAfter()
+
+ c.setHeadString(p2,varname)
+ return LeoNode(p2)
+ finally:
+ c.endUpdate()
+
+def add_file(self,fname):
+ p2 = c.currentPosition().insertAfter()
+
+push_from_leo = CommandChainDispatcher()
+
+def expose_ileo_push(f, prio = 0):
+ push_from_leo.add(f, prio)
+
+def push_ipython_script(node):
+ """ Execute the node body in IPython, as if it was entered in interactive prompt """
+ c.beginUpdate()
+ try:
+ ohist = ip.IP.output_hist
+ hstart = len(ip.IP.input_hist)
+ script = node.script()
+
+ ip.user_ns['_p'] = node
+ ip.runlines(script)
+ ip.user_ns.pop('_p',None)
+
+ has_output = False
+ for idx in range(hstart,len(ip.IP.input_hist)):
+ val = ohist.get(idx,None)
+ if val is None:
+ continue
+ has_output = True
+ inp = ip.IP.input_hist[idx]
+ if inp.strip():
+ es('In: %s' % (inp[:40], ))
+
+ es('<%d> %s' % (idx, pprint.pformat(ohist[idx],width = 40)))
+
+ if not has_output:
+ es('ipy run: %s (%d LL)' %( node.h,len(script)))
+ finally:
+ c.endUpdate()
+
+
+def eval_body(body):
+ try:
+ val = ip.ev(body)
+ except:
+ # just use stringlist if it's not completely legal python expression
+ val = IPython.genutils.SList(body.splitlines())
+ return val
+
+def push_plain_python(node):
+ if not node.h.endswith('P'):
+ raise TryNext
+ script = node.script()
+ lines = script.count('\n')
+ try:
+ exec script in ip.user_ns
+ except:
+ print " -- Exception in script:\n"+script + "\n --"
+ raise
+ es('ipy plain: %s (%d LL)' % (node.h,lines))
+
+
+def push_cl_node(node):
+ """ If node starts with @cl, eval it
+
+ The result is put as last child of @ipy-results node, if it exists
+ """
+ if not node.b.startswith('@cl'):
+ raise TryNext
+
+ p2 = g.findNodeAnywhere(c,'@ipy-results')
+ val = node.v
+ if p2:
+ es("=> @ipy-results")
+ LeoNode(p2).v = val
+ es(val)
+
+def push_ev_node(node):
+ """ If headline starts with @ev, eval it and put result in body """
+ if not node.h.startswith('@ev '):
+ raise TryNext
+ expr = node.h.lstrip('@ev ')
+ es('ipy eval ' + expr)
+ res = ip.ev(expr)
+ node.v = res
+
+
+def push_position_from_leo(p):
+ try:
+ push_from_leo(LeoNode(p))
+ except AttributeError,e:
+ if e.args == ("Commands instance has no attribute 'frame'",):
+ es("Error: ILeo not associated with .leo document")
+ es("Press alt+shift+I to fix!")
+ else:
+ raise
+
+@generic
+def edit_object_in_leo(obj, varname):
+ """ Make it @cl node so it can be pushed back directly by alt+I """
+ node = add_var(varname)
+ formatted = format_for_leo(obj)
+ if not formatted.startswith('@cl'):
+ formatted = '@cl\n' + formatted
+ node.b = formatted
+ node.go()
+
+@edit_object_in_leo.when_type(IPython.macro.Macro)
+def edit_macro(obj,varname):
+ bod = '_ip.defmacro("""\\\n' + obj.value + '""")'
+ node = add_var('Macro_' + varname)
+ node.b = bod
+ node.go()
+
+def get_history(hstart = 0):
+ res = []
+ ohist = ip.IP.output_hist
+
+ for idx in range(hstart, len(ip.IP.input_hist)):
+ val = ohist.get(idx,None)
+ has_output = True
+ inp = ip.IP.input_hist_raw[idx]
+ if inp.strip():
+ res.append('In [%d]: %s' % (idx, inp))
+ if val:
+ res.append(pprint.pformat(val))
+ res.append('\n')
+ return ''.join(res)
+
+
+def lee_f(self,s):
+ """ Open file(s)/objects in Leo
+
+ - %lee hist -> open full session history in leo
+ - Takes an object. l = [1,2,"hello"]; %lee l. Alt+I in leo pushes the object back
+ - Takes an mglob pattern, e.g. '%lee *.cpp' or %lee 'rec:*.cpp'
+ - Takes input history indices: %lee 4 6-8 10 12-47
+ """
+ import os
+
+ c.beginUpdate()
+ try:
+ if s == 'hist':
+ wb.ipython_history.b = get_history()
+ wb.ipython_history.go()
+ return
+
+
+ if s and s[0].isdigit():
+ # numbers; push input slices to leo
+ lines = self.extract_input_slices(s.strip().split(), True)
+ v = add_var('stored_ipython_input')
+ v.b = '\n'.join(lines)
+ return
+
+
+ # try editing the object directly
+ obj = ip.user_ns.get(s, None)
+ if obj is not None:
+ edit_object_in_leo(obj,s)
+ return
+
+
+ # if it's not object, it's a file name / mglob pattern
+ from IPython.external import mglob
+
+ files = (os.path.abspath(f) for f in mglob.expand(s))
+ for fname in files:
+ p = g.findNodeAnywhere(c,'@auto ' + fname)
+ if not p:
+ p = c.currentPosition().insertAfter()
+
+ p.setHeadString('@auto ' + fname)
+ if os.path.isfile(fname):
+ c.setBodyString(p,open(fname).read())
+ c.selectPosition(p)
+ print "Editing file(s), press ctrl+shift+w in Leo to write @auto nodes"
+ finally:
+ c.endUpdate()
+
+
+
+def leoref_f(self,s):
+ """ Quick reference for ILeo """
+ import textwrap
+ print textwrap.dedent("""\
+ %leoe file/object - open file / object in leo
+ wb.foo.v - eval node foo (i.e. headstring is 'foo' or '@ipy foo')
+ wb.foo.v = 12 - assign to body of node foo
+ wb.foo.b - read or write the body of node foo
+ wb.foo.l - body of node foo as string list
+
+ for el in wb.foo:
+ print el.v
+
+ """
+ )
+
+
+
+def mb_f(self, arg):
+ """ Execute leo minibuffer commands
+
+ Example:
+ mb save-to-file
+ """
+ c.executeMinibufferCommand(arg)
+
+def mb_completer(self,event):
+ """ Custom completer for minibuffer """
+ cmd_param = event.line.split()
+ if event.line.endswith(' '):
+ cmd_param.append('')
+ if len(cmd_param) > 2:
+ return ip.IP.Completer.file_matches(event.symbol)
+ cmds = c.commandsDict.keys()
+ cmds.sort()
+ return cmds
+
+def show_welcome():
+ print "------------------"
+ print "Welcome to Leo-enabled IPython session!"
+ print "Try %leoref for quick reference."
+ import IPython.platutils
+ IPython.platutils.set_term_title('ILeo')
+ IPython.platutils.freeze_term_title()
+
+def run_leo_startup_node():
+ p = g.findNodeAnywhere(c,'@ipy-startup')
+ if p:
+ print "Running @ipy-startup nodes"
+ for n in LeoNode(p):
+ push_from_leo(n)
+
+
diff --git a/IPython/Extensions/ipy_lookfor.py b/IPython/Extensions/ipy_lookfor.py
new file mode 100644
index 0000000..eb56f3d
--- /dev/null
+++ b/IPython/Extensions/ipy_lookfor.py
@@ -0,0 +1,234 @@
+"""
+IPython extension: %lookfor command for searching docstrings
+
+"""
+# Pauli Virtanen , 2008.
+
+import re, inspect, pkgutil, pydoc
+
+#------------------------------------------------------------------------------
+# Lookfor functionality
+#------------------------------------------------------------------------------
+
+# Cache for lookfor: {id(module): {name: (docstring, kind, index), ...}...}
+# where kind: "func", "class", "module", "object"
+# and index: index in breadth-first namespace traversal
+_lookfor_caches = {}
+
+# regexp whose match indicates that the string may contain a function signature
+_function_signature_re = re.compile(r"[a-z_]+\(.*[,=].*\)", re.I)
+
+def lookfor(what, modules=None, import_modules=True, regenerate=False):
+ """
+ Search for objects whose documentation contains all given words.
+ Shows a summary of matching objects, sorted roughly by relevance.
+
+ Parameters
+ ----------
+ what : str
+ String containing words to look for.
+
+ module : str, module
+ Module whose docstrings to go through.
+ import_modules : bool
+ Whether to import sub-modules in packages.
+ Will import only modules in __all__
+ regenerate: bool
+ Re-generate the docstring cache
+
+ """
+ # Cache
+ cache = {}
+ for module in modules:
+ try:
+ c = _lookfor_generate_cache(module, import_modules, regenerate)
+ cache.update(c)
+ except ImportError:
+ pass
+
+ # Search
+ # XXX: maybe using a real stemming search engine would be better?
+ found = []
+ whats = str(what).lower().split()
+ if not whats: return
+
+ for name, (docstring, kind, index) in cache.iteritems():
+ if kind in ('module', 'object'):
+ # don't show modules or objects
+ continue
+ ok = True
+ doc = docstring.lower()
+ for w in whats:
+ if w not in doc:
+ ok = False
+ break
+ if ok:
+ found.append(name)
+
+ # Relevance sort
+ # XXX: this is full Harrison-Stetson heuristics now,
+ # XXX: it probably could be improved
+
+ kind_relevance = {'func': 1000, 'class': 1000,
+ 'module': -1000, 'object': -1000}
+
+ def relevance(name, docstr, kind, index):
+ r = 0
+ # do the keywords occur within the start of the docstring?
+ first_doc = "\n".join(docstr.lower().strip().split("\n")[:3])
+ r += sum([200 for w in whats if w in first_doc])
+ # do the keywords occur in the function name?
+ r += sum([30 for w in whats if w in name])
+ # is the full name long?
+ r += -len(name) * 5
+ # is the object of bad type?
+ r += kind_relevance.get(kind, -1000)
+ # is the object deep in namespace hierarchy?
+ r += -name.count('.') * 10
+ r += max(-index / 100, -100)
+ return r
+
+ def relevance_sort(a, b):
+ dr = relevance(b, *cache[b]) - relevance(a, *cache[a])
+ if dr != 0: return dr
+ else: return cmp(a, b)
+ found.sort(relevance_sort)
+
+ # Pretty-print
+ s = "Search results for '%s'" % (' '.join(whats))
+ help_text = [s, "-"*len(s)]
+ for name in found:
+ doc, kind, ix = cache[name]
+
+ doclines = [line.strip() for line in doc.strip().split("\n")
+ if line.strip()]
+
+ # find a suitable short description
+ try:
+ first_doc = doclines[0].strip()
+ if _function_signature_re.search(first_doc):
+ first_doc = doclines[1].strip()
+ except IndexError:
+ first_doc = ""
+ help_text.append("%s\n %s" % (name, first_doc))
+
+ # Output
+ if len(help_text) > 10:
+ pager = pydoc.getpager()
+ pager("\n".join(help_text))
+ else:
+ print "\n".join(help_text)
+
+def _lookfor_generate_cache(module, import_modules, regenerate):
+ """
+ Generate docstring cache for given module.
+
+ Parameters
+ ----------
+ module : str, None, module
+ Module for which to generate docstring cache
+ import_modules : bool
+ Whether to import sub-modules in packages.
+ Will import only modules in __all__
+ regenerate: bool
+ Re-generate the docstring cache
+
+ Returns
+ -------
+ cache : dict {obj_full_name: (docstring, kind, index), ...}
+ Docstring cache for the module, either cached one (regenerate=False)
+ or newly generated.
+
+ """
+ global _lookfor_caches
+
+ if module is None:
+ module = "numpy"
+
+ if isinstance(module, str):
+ module = __import__(module)
+
+ if id(module) in _lookfor_caches and not regenerate:
+ return _lookfor_caches[id(module)]
+
+ # walk items and collect docstrings
+ cache = {}
+ _lookfor_caches[id(module)] = cache
+ seen = {}
+ index = 0
+ stack = [(module.__name__, module)]
+ while stack:
+ name, item = stack.pop(0)
+ if id(item) in seen: continue
+ seen[id(item)] = True
+
+ index += 1
+ kind = "object"
+
+ if inspect.ismodule(item):
+ kind = "module"
+ try:
+ _all = item.__all__
+ except AttributeError:
+ _all = None
+ # import sub-packages
+ if import_modules and hasattr(item, '__path__'):
+ for m in pkgutil.iter_modules(item.__path__):
+ if _all is not None and m[1] not in _all:
+ continue
+ try:
+ __import__("%s.%s" % (name, m[1]))
+ except ImportError:
+ continue
+ for n, v in inspect.getmembers(item):
+ if _all is not None and n not in _all:
+ continue
+ stack.append(("%s.%s" % (name, n), v))
+ elif inspect.isclass(item):
+ kind = "class"
+ for n, v in inspect.getmembers(item):
+ stack.append(("%s.%s" % (name, n), v))
+ elif callable(item):
+ kind = "func"
+
+ doc = inspect.getdoc(item)
+ if doc is not None:
+ cache[name] = (doc, kind, index)
+
+ return cache
+
+#------------------------------------------------------------------------------
+# IPython connectivity
+#------------------------------------------------------------------------------
+
+import IPython.ipapi
+ip = IPython.ipapi.get()
+
+_lookfor_modules = ['numpy', 'scipy']
+
+def lookfor_f(self, arg=''):
+ r"""
+ Search for objects whose documentation contains all given words.
+ Shows a summary of matching objects, sorted roughly by relevance.
+
+ Usage
+ -----
+ %lookfor +numpy some words
+ Search module 'numpy'
+
+ %lookfor_modules numpy scipy
+ Set default modules whose docstrings to search
+
+ """
+ lookfor(arg, modules=_lookfor_modules)
+
+def lookfor_modules_f(self, arg=''):
+ global _lookfor_modules
+ if not arg:
+ print "Modules included in %lookfor search:", _lookfor_modules
+ else:
+ _lookfor_modules = arg.split()
+
+ip.expose_magic('lookfor', lookfor_f)
+ip.expose_magic('lookfor_modules', lookfor_modules_f)
+
diff --git a/IPython/Extensions/ipy_profile_sh.py b/IPython/Extensions/ipy_profile_sh.py
index adf2b81..c25afef 100644
--- a/IPython/Extensions/ipy_profile_sh.py
+++ b/IPython/Extensions/ipy_profile_sh.py
@@ -43,11 +43,13 @@ def main():
# %store foo
# %store bar
import ipy_rehashdir
- import ipy_signals
+
+ # does not work without subprocess module!
+ #import ipy_signals
ip.ex('import os')
ip.ex("def up(): os.chdir('..')")
-
+ ip.user_ns['LA'] = LastArgFinder()
# Nice prompt
o.prompt_in1= r'\C_LightBlue[\C_LightCyan\Y2\C_LightBlue]\C_Green|\#> '
@@ -117,6 +119,29 @@ def main():
extend_shell_behavior(ip)
+class LastArgFinder:
+ """ Allow $LA to work as "last argument of previous command", like $! in bash
+
+ To call this in normal IPython code, do LA()
+ """
+ def __call__(self, hist_idx = None):
+ ip = ipapi.get()
+ if hist_idx is None:
+ return str(self)
+ return ip.IP.input_hist_raw[hist_idx].strip().split()[-1]
+ def __str__(self):
+ ip = ipapi.get()
+ for cmd in reversed(ip.IP.input_hist_raw):
+ parts = cmd.strip().split()
+ if len(parts) < 2 or parts[-1] in ['$LA', 'LA()']:
+ continue
+ return parts[-1]
+ return ""
+
+
+
+
+
# XXX You do not need to understand the next function!
# This should probably be moved out of profile
diff --git a/IPython/Extensions/ipy_vimserver.py b/IPython/Extensions/ipy_vimserver.py
new file mode 100644
index 0000000..f23b712
--- /dev/null
+++ b/IPython/Extensions/ipy_vimserver.py
@@ -0,0 +1,239 @@
+""" Integration with gvim, by Erich Heine
+
+Provides a %vim magic command, and reuses the same vim session. Uses
+unix domain sockets for communication between vim and IPython. ipy.vim is
+available in doc/examples of the IPython distribution.
+
+Slightly touched up email announcement (and description how to use it) by
+Erich Heine is here:
+
+Ive recently been playing with ipython, and like it quite a bit. I did
+however discover a bit of frustration, namely with editor interaction.
+I am a gvim user, and using the command edit on a new file causes
+ipython to try and run that file as soon as the text editor opens
+up. The -x command of course fixes this, but its still a bit annoying,
+switching windows to do a run file, then back to the text
+editor. Being a heavy tab user in gvim, another annoyance is not being
+able to specify weather a new tab is how I choose to open the file.
+
+Not being one to shirk my open source duties (and seeing this as a
+good excuse to poke around ipython internals), Ive created a script
+for having gvim and ipython work very nicely together. Ive attached
+both to this email (hoping of course that the mailing list allows such
+things).
+
+There are 2 files:
+
+ipy_vimserver.py -- this file contains the ipython stuff
+ipy.vim -- this file contains the gvim stuff
+
+In combination they allow for a few functionalities:
+
+#1. the vim magic command. This is a fancy wrapper around the edit
+magic, that allows for a new option, -t, which opens the text in a new
+gvim tab. Otherwise it works the same as edit -x. (it internally
+calls edit -x). This magic command also juggles vim server management,
+so when it is called when there is not a gvim running, it creates a
+new gvim instance, named after the ipython session name. Once such a
+gvim instance is running, it will be used for subsequent uses of the
+vim command.
+
+#2. ipython - gvim interaction. Once a file has been opened with the
+vim magic (and a session set up, see below), pressing the F5 key in
+vim will cause the calling ipython instance to execute run
+filename.py. (if you typo like I do, this is very useful)
+
+#3. ipython server - this is a thread wich listens on a unix domain
+socket, and runs commands sent to that socket.
+
+Note, this only works on POSIX systems, that allow for AF_UNIX type
+sockets. It has only been tested on linux (a fairly recent debian
+testing distro).
+
+To install it put, the ipserver.py in your favorite locaion for
+sourcing ipython scripts. I put the ipy.vim in
+~/.vim/after/ftplugin/python/.
+
+To use (this can be scripted im sure, but i usually have 2 or 3
+ipythons and corresponding gvims open):
+
+import ipy_vimserver
+ipy_vimserver.setup('sessionname')
+
+(Editors note - you can probably add these to your ipy_user_conf.py)
+
+Then use ipython as you normally would, until you need to edit
+something. Instead of edit, use the vim magic. Thats it!
+
+"""
+
+import IPython.ipapi
+#import ipythonhooks
+import socket, select
+import os, threading, subprocess
+import re
+
+ERRCONDS = select.POLLHUP|select.POLLERR
+SERVER = None
+ip = IPython.ipapi.get()
+
+# this listens to a unix domain socket in a separate thread, so that comms
+# between a vim instance and ipython can happen in a fun and productive way
+class IpyServer(threading.Thread):
+ def __init__(self, sname):
+ super(IpyServer, self).__init__()
+ self.keep_running = True
+ self.__sname = sname
+ self.socket = socket.socket(socket.AF_UNIX)
+ self.poller = select.poll()
+ self.current_conns = dict()
+ self.setDaemon(True)
+
+ def listen(self):
+ self.socket.bind(self.__sname)
+ self.socket.listen(1)
+
+ def __handle_error(self, socket):
+ if socket == self.socket.fileno():
+ self.keep_running = False
+ for a in self.current_conns.values():
+ a.close()
+ return False
+ else:
+ y = self.current_conns[socket]
+ del self.current_conns[socket]
+ y.close()
+ self.poller.unregister(socket)
+
+ def serve_me(self):
+ self.listen()
+ self.poller.register(self.socket,select.POLLIN|ERRCONDS)
+
+ while self.keep_running:
+ try:
+ avail = self.poller.poll(1)
+ except:
+ continue
+
+ if not avail: continue
+
+ for sock, conds in avail:
+ if conds & (ERRCONDS):
+ if self.__handle_error(sock): continue
+ else: break
+
+ if sock == self.socket.fileno():
+ y = self.socket.accept()[0]
+ self.poller.register(y, select.POLLIN|ERRCONDS)
+ self.current_conns[y.fileno()] = y
+ else: y = self.current_conns.get(sock)
+
+ self.handle_request(y)
+
+ os.remove(self.__sname)
+
+ run = serve_me
+
+ def stop(self):
+ self.keep_running = False
+
+ def handle_request(self,sock):
+ sock.settimeout(1)
+ while self.keep_running:
+ try:
+ x = sock.recv(4096)
+ except socket.timeout:
+ pass
+ else:
+ break
+ self.do_it(x)
+
+ def do_it(self, data):
+ data = data.split('\n')
+ cmds = list()
+ for line in data:
+ cmds.append(line)
+ ip.runlines(cmds)
+
+
+# try to help ensure that the unix domain socket is cleaned up proper
+def shutdown_server(self):
+ if SERVER:
+ SERVER.stop()
+ SERVER.join(3)
+ raise IPython.ipapi.TryNext
+
+ip.set_hook('shutdown_hook', shutdown_server, 10)
+
+# this fun function exists to make setup easier for all, and makes the
+# vimhook function ready for instance specific communication
+def setup(sessionname='',socketdir=os.path.expanduser('~/.ipython/')):
+ global SERVER
+
+ if sessionname:
+ session = sessionname
+ elif os.environ.get('IPY_SESSION'):
+ session = os.environ.get('IPY_SESSION')
+ else:
+ session = 'IPYS'
+ vimhook.vimserver=session
+ vimhook.ipyserver = os.path.join(socketdir, session)
+ if not SERVER:
+ SERVER = IpyServer(vimhook.ipyserver)
+ SERVER.start()
+
+
+
+# calls gvim, with all ops happening on the correct gvim instance for this
+# ipython instance. it then calls edit -x (since gvim will return right away)
+# things of note: it sets up a special environment, so that the ipy.vim script
+# can connect back to the ipython instance and do fun things, like run the file
+def vimhook(self, fname, line):
+ env = os.environ.copy()
+ vserver = vimhook.vimserver.upper()
+ check = subprocess.Popen('gvim --serverlist', stdout = subprocess.PIPE,
+ shell=True)
+ check.wait()
+ cval = [l for l in check.stdout.readlines() if vserver in l]
+
+ if cval:
+ vimargs = '--remote%s' % (vimhook.extras,)
+ else:
+ vimargs = ''
+ vimhook.extras = ''
+
+ env['IPY_SESSION'] = vimhook.vimserver
+ env['IPY_SERVER'] = vimhook.ipyserver
+
+ if line is None: line = ''
+ else: line = '+' + line
+ vim_cmd = 'gvim --servername %s %s %s %s' % (vimhook.vimserver, vimargs,
+ line, fname)
+ subprocess.call(vim_cmd, env=env, shell=True)
+
+
+#default values to keep it sane...
+vimhook.vimserver = ''
+vimhook.ipyserver = ''
+
+ip.set_hook('editor',vimhook)
+
+# this is set up so more vim specific commands can be added, instead of just
+# the current -t. all thats required is a compiled regex, a call to do_arg(pat)
+# and the logic to deal with the new feature
+newtab = re.compile(r'-t(?:\s|$)')
+def vim(self, argstr):
+ def do_arg(pat, rarg):
+ x = len(pat.findall(argstr))
+ if x:
+ a = pat.sub('',argstr)
+ return rarg, a
+ else: return '', argstr
+
+ t, argstr = do_arg(newtab, '-tab')
+ vimhook.extras = t
+ argstr = 'edit -x ' + argstr
+ ip.magic(argstr)
+
+ip.expose_magic('vim', vim)
+
diff --git a/IPython/Extensions/ipy_winpdb.py b/IPython/Extensions/ipy_winpdb.py
new file mode 100644
index 0000000..6992013
--- /dev/null
+++ b/IPython/Extensions/ipy_winpdb.py
@@ -0,0 +1,73 @@
+""" Debug a script (like %run -d) in IPython process, Using WinPdb
+
+Usage:
+
+%wdb test.py
+ run test.py, with a winpdb breakpoint at start of the file
+
+%wdb pass
+ Change the password (e.g. if you have forgotten the old one)
+"""
+
+import os
+
+import IPython.ipapi
+import rpdb2
+
+ip = IPython.ipapi.get()
+
+rpdb_started = False
+
+def wdb_f(self, arg):
+ """ Debug a script (like %run -d) in IPython process, Using WinPdb
+
+ Usage:
+
+ %wdb test.py
+ run test.py, with a winpdb breakpoint at start of the file
+
+ %wdb pass
+ Change the password (e.g. if you have forgotten the old one)
+
+ Note that after the script has been run, you need to do "Go" (f5)
+ in WinPdb to resume normal IPython operation.
+ """
+
+ global rpdb_started
+ if not arg.strip():
+ print __doc__
+ return
+
+ if arg.strip() == 'pass':
+ passwd = raw_input('Enter new winpdb session password: ')
+ ip.db['winpdb_pass'] = passwd
+ print "Winpdb password changed"
+ if rpdb_started:
+ print "You need to restart IPython to use the new password"
+ return
+
+ path = os.path.abspath(arg)
+ if not os.path.isfile(path):
+ raise IPython.ipapi.UsageError("%%wdb: file %s does not exist" % path)
+ if not rpdb_started:
+ passwd = ip.db.get('winpdb_pass', None)
+ if passwd is None:
+ import textwrap
+ print textwrap.dedent("""\
+ Winpdb sessions need a password that you use for attaching the external
+ winpdb session. IPython will remember this. You can change the password later
+ by '%wpdb pass'
+ """)
+ passwd = raw_input('Enter new winpdb session password: ')
+ ip.db['winpdb_pass'] = passwd
+
+ print "Starting rpdb2 in IPython process"
+ rpdb2.start_embedded_debugger(passwd, timeout = 0)
+ rpdb_started = True
+
+ rpdb2.set_temp_breakpoint(path)
+ print 'It is time to attach with WinPdb (launch WinPdb if needed, File -> Attach)'
+ ip.magic('%run ' + arg)
+
+
+ip.expose_magic('wdb', wdb_f)
diff --git a/IPython/Extensions/jobctrl.py b/IPython/Extensions/jobctrl.py
index 9f87121..5cff41d 100755
--- a/IPython/Extensions/jobctrl.py
+++ b/IPython/Extensions/jobctrl.py
@@ -41,8 +41,9 @@ Now launch a new IPython prompt and kill the process:
(you don't need to specify PID for %kill if only one task is running)
"""
-from subprocess import Popen,PIPE
+from subprocess import *
import os,shlex,sys,time
+import threading,Queue
from IPython import genutils
@@ -71,15 +72,70 @@ def startjob(job):
p.line = job
return p
+class AsyncJobQ(threading.Thread):
+ def __init__(self):
+ threading.Thread.__init__(self)
+ self.q = Queue.Queue()
+ self.output = []
+ self.stop = False
+ def run(self):
+ while 1:
+ cmd,cwd = self.q.get()
+ if self.stop:
+ self.output.append("** Discarding: '%s' - %s" % (cmd,cwd))
+ continue
+ self.output.append("** Task started: '%s' - %s" % (cmd,cwd))
+
+ p = Popen(cmd, shell=True, stdout=PIPE, stderr=STDOUT, cwd = cwd)
+ out = p.stdout.read()
+ self.output.append("** Task complete: '%s'\n" % cmd)
+ self.output.append(out)
+
+ def add(self,cmd):
+ self.q.put_nowait((cmd, os.getcwd()))
+
+ def dumpoutput(self):
+ while self.output:
+ item = self.output.pop(0)
+ print item
+
+_jobq = None
+
+def jobqueue_f(self, line):
+
+ global _jobq
+ if not _jobq:
+ print "Starting jobqueue - do '&some_long_lasting_system_command' to enqueue"
+ _jobq = AsyncJobQ()
+ _jobq.setDaemon(True)
+ _jobq.start()
+ ip.jobq = _jobq.add
+ return
+ if line.strip() == 'stop':
+ print "Stopping and clearing jobqueue, %jobqueue start to start again"
+ _jobq.stop = True
+ return
+ if line.strip() == 'start':
+ _jobq.stop = False
+ return
+
def jobctrl_prefilter_f(self,line):
if line.startswith('&'):
pre,fn,rest = self.split_user_input(line[1:])
line = ip.IP.expand_aliases(fn,rest)
- return '_ip.startjob(%s)' % genutils.make_quoted_expr(line)
+ if not _jobq:
+ return '_ip.startjob(%s)' % genutils.make_quoted_expr(line)
+ return '_ip.jobq(%s)' % genutils.make_quoted_expr(line)
raise IPython.ipapi.TryNext
+def jobq_output_hook(self):
+ if not _jobq:
+ return
+ _jobq.dumpoutput()
+
+
def job_list(ip):
keys = ip.db.keys('tasks/*')
@@ -91,8 +147,16 @@ def magic_tasks(self,line):
A 'task' is a process that has been started in IPython when 'jobctrl' extension is enabled.
Tasks can be killed with %kill.
+
+ '%tasks clear' clears the task list (from stale tasks)
"""
ip = self.getapi()
+ if line.strip() == 'clear':
+ for k in ip.db.keys('tasks/*'):
+ print "Clearing",ip.db[k]
+ del ip.db[k]
+ return
+
ents = job_list(ip)
if not ents:
print "No tasks running"
@@ -125,7 +189,7 @@ def magic_kill(self,line):
magic_tasks(self,line)
if sys.platform == 'win32':
- shell_internal_commands = 'break chcp cls copy ctty date del erase dir md mkdir path prompt rd rmdir time type ver vol'.split()
+ shell_internal_commands = 'break chcp cls copy ctty date del erase dir md mkdir path prompt rd rmdir start time type ver vol'.split()
else:
# todo linux commands
shell_internal_commands = []
@@ -133,20 +197,33 @@ else:
def jobctrl_shellcmd(ip,cmd):
""" os.system replacement that stores process info to db['tasks/t1234'] """
+ cmd = cmd.strip()
cmdname = cmd.split(None,1)[0]
- if cmdname in shell_internal_commands:
+ if cmdname in shell_internal_commands or '|' in cmd or '>' in cmd or '<' in cmd:
use_shell = True
else:
use_shell = False
- p = Popen(cmd,shell = use_shell)
- jobentry = 'tasks/t' + str(p.pid)
-
+ jobentry = None
try:
+ try:
+ p = Popen(cmd,shell = use_shell)
+ except WindowsError:
+ if use_shell:
+ # try with os.system
+ os.system(cmd)
+ return
+ else:
+ # have to go via shell, sucks
+ p = Popen(cmd,shell = True)
+
+ jobentry = 'tasks/t' + str(p.pid)
ip.db[jobentry] = (p.pid,cmd,os.getcwd(),time.time())
- p.communicate()
+ p.communicate()
+
finally:
- del ip.db[jobentry]
+ if jobentry:
+ del ip.db[jobentry]
def install():
@@ -158,5 +235,6 @@ def install():
ip.set_hook('shell_hook', jobctrl_shellcmd)
ip.expose_magic('kill',magic_kill)
ip.expose_magic('tasks',magic_tasks)
-
+ ip.expose_magic('jobqueue',jobqueue_f)
+ ip.set_hook('pre_prompt_hook', jobq_output_hook)
install()
diff --git a/IPython/Itpl.py b/IPython/Itpl.py
index ce21a87..0003e30 100644
--- a/IPython/Itpl.py
+++ b/IPython/Itpl.py
@@ -94,8 +94,16 @@ def matchorfail(text, pos):
match = tokenprog.match(text, pos)
if match is None:
raise ItplError(text, pos)
+
return match, match.end()
+try:
+ itpl_encoding = sys.stdin.encoding or 'ascii'
+except AttributeError:
+ itpl_encoding = 'ascii'
+
+
+
class Itpl:
"""Class representing a string with interpolation abilities.
@@ -104,7 +112,7 @@ class Itpl:
evaluation and substitution happens in the namespace of the
caller when str(instance) is called."""
- def __init__(self, format,codec=sys.stdin.encoding,encoding_errors='backslashreplace'):
+ def __init__(self, format,codec=itpl_encoding,encoding_errors='backslashreplace'):
"""The single mandatory argument to this constructor is a format
string.
diff --git a/IPython/Magic.py b/IPython/Magic.py
index fc93242..6c0c488 100644
--- a/IPython/Magic.py
+++ b/IPython/Magic.py
@@ -115,9 +115,9 @@ class Magic:
def profile_missing_notice(self, *args, **kwargs):
error("""\
-The profile module could not be found. If you are a Debian user,
-it has been removed from the standard Debian package because of its non-free
-license. To use profiling, please install"python2.3-profiler" from non-free.""")
+The profile module could not be found. It has been removed from the standard
+python packages because of its non-free license. To use profiling, install the
+python-profiler package from non-free.""")
def default_option(self,fn,optstr):
"""Make an entry in the options_table for fn, with value optstr"""
@@ -147,7 +147,7 @@ license. To use profiling, please install"python2.3-profiler" from non-free.""")
filter(inst_magic,self.__dict__.keys()) + \
filter(inst_bound_magic,self.__class__.__dict__.keys())
out = []
- for fn in magics:
+ for fn in Set(magics):
out.append(fn.replace('magic_','',1))
out.sort()
return out
@@ -386,7 +386,10 @@ license. To use profiling, please install"python2.3-profiler" from non-free.""")
return None
def magic_magic(self, parameter_s = ''):
- """Print information about the magic function system."""
+ """Print information about the magic function system.
+
+ Supported formats: -latex, -brief, -rest
+ """
mode = ''
try:
@@ -394,6 +397,9 @@ license. To use profiling, please install"python2.3-profiler" from non-free.""")
mode = 'latex'
if parameter_s.split()[0] == '-brief':
mode = 'brief'
+ if parameter_s.split()[0] == '-rest':
+ mode = 'rest'
+ rest_docs = []
except:
pass
@@ -409,14 +415,26 @@ license. To use profiling, please install"python2.3-profiler" from non-free.""")
break
if mode == 'brief':
# only first line
- fndoc = fn.__doc__.split('\n',1)[0]
+ if fn.__doc__:
+ fndoc = fn.__doc__.split('\n',1)[0]
+ else:
+ fndoc = 'No documentation'
+ else:
+ fndoc = fn.__doc__.rstrip()
+
+ if mode == 'rest':
+ rest_docs.append('**%s%s**::\n\n\t%s\n\n' %(self.shell.ESC_MAGIC,
+ fname,fndoc))
+
else:
- fndoc = fn.__doc__
+ magic_docs.append('%s%s:\n\t%s\n' %(self.shell.ESC_MAGIC,
+ fname,fndoc))
- magic_docs.append('%s%s:\n\t%s\n' %(self.shell.ESC_MAGIC,
- fname,fndoc))
magic_docs = ''.join(magic_docs)
+ if mode == 'rest':
+ return "".join(rest_docs)
+
if mode == 'latex':
print self.format_latex(magic_docs)
return
@@ -2612,7 +2630,7 @@ Defaulting color scheme to 'NoColor'"""
os.chdir(pdir)
for ff in os.listdir(pdir):
base, ext = os.path.splitext(ff)
- if isexec(ff) and base not in self.shell.no_alias:
+ if isexec(ff) and base.lower() not in self.shell.no_alias:
if ext.lower() == '.exe':
ff = base
alias_table[base.lower()] = (0,ff)
@@ -2667,6 +2685,7 @@ Defaulting color scheme to 'NoColor'"""
parameter_s = parameter_s.strip()
#bkms = self.shell.persist.get("bookmarks",{})
+ oldcwd = os.getcwd()
numcd = re.match(r'(-)(\d+)$',parameter_s)
# jump in directory history by number
if numcd:
@@ -2705,7 +2724,7 @@ Defaulting color scheme to 'NoColor'"""
# at this point ps should point to the target dir
if ps:
- try:
+ try:
os.chdir(os.path.expanduser(ps))
if self.shell.rc.term_title:
#print 'set term title:',self.shell.rc.term_title # dbg
@@ -2716,8 +2735,9 @@ Defaulting color scheme to 'NoColor'"""
else:
cwd = os.getcwd()
dhist = self.shell.user_ns['_dh']
- dhist.append(cwd)
- self.db['dhist'] = compress_dhist(dhist)[-100:]
+ if oldcwd != cwd:
+ dhist.append(cwd)
+ self.db['dhist'] = compress_dhist(dhist)[-100:]
else:
os.chdir(self.shell.home_dir)
@@ -2725,8 +2745,10 @@ Defaulting color scheme to 'NoColor'"""
platutils.set_term_title("IPy ~")
cwd = os.getcwd()
dhist = self.shell.user_ns['_dh']
- dhist.append(cwd)
- self.db['dhist'] = compress_dhist(dhist)[-100:]
+
+ if oldcwd != cwd:
+ dhist.append(cwd)
+ self.db['dhist'] = compress_dhist(dhist)[-100:]
if not 'q' in opts and self.shell.user_ns['_dh']:
print self.shell.user_ns['_dh'][-1]
@@ -3118,7 +3140,7 @@ Defaulting color scheme to 'NoColor'"""
screen_lines=self.shell.rc.screen_length)
def magic_cpaste(self, parameter_s=''):
- """Allows you to paste & execute a pre-formatted code block from clipboard
+ """Allows you to paste & execute a pre-formatted code block from clipboard.
You must terminate the block with '--' (two minus-signs) alone on the
line. You can also provide your own sentinel with '%paste -s %%' ('%%'
@@ -3126,13 +3148,14 @@ Defaulting color scheme to 'NoColor'"""
The block is dedented prior to execution to enable execution of method
definitions. '>' and '+' characters at the beginning of a line are
- ignored, to allow pasting directly from e-mails or diff files. The
+ ignored, to allow pasting directly from e-mails, diff files and
+ doctests (the '...' continuation prompt is also stripped). The
executed block is also assigned to variable named 'pasted_block' for
later editing with '%edit pasted_block'.
You can also pass a variable name as an argument, e.g. '%cpaste foo'.
This assigns the pasted block to variable 'foo' as string, without
- dedenting or executing it.
+ dedenting or executing it (preceding >>> and + is still stripped)
Do not be alarmed by garbled output on Windows (it's a readline bug).
Just press enter and type -- (and press enter again) and the block
@@ -3143,6 +3166,15 @@ Defaulting color scheme to 'NoColor'"""
opts,args = self.parse_options(parameter_s,'s:',mode='string')
par = args.strip()
sentinel = opts.get('s','--')
+
+ # Regular expressions that declare text we strip from the input:
+ strip_re = [r'^\s*In \[\d+\]:', # IPython input prompt
+ r'^\s*(\s?>)+', # Python input prompt
+ r'^\s*\.{3,}', # Continuation prompts
+ r'^\++',
+ ]
+
+ strip_from_start = map(re.compile,strip_re)
from IPython import iplib
lines = []
@@ -3151,7 +3183,11 @@ Defaulting color scheme to 'NoColor'"""
l = iplib.raw_input_original(':')
if l ==sentinel:
break
- lines.append(l.lstrip('>').lstrip('+'))
+
+ for pat in strip_from_start:
+ l = pat.sub('',l)
+ lines.append(l)
+
block = "\n".join(lines) + '\n'
#print "block:\n",block
if not par:
diff --git a/IPython/OInspect.py b/IPython/OInspect.py
index f932beb..16d0415 100644
--- a/IPython/OInspect.py
+++ b/IPython/OInspect.py
@@ -404,7 +404,13 @@ class Inspector:
# Filename where object was defined
binary_file = False
try:
- fname = inspect.getabsfile(obj)
+ try:
+ fname = inspect.getabsfile(obj)
+ except TypeError:
+ # For an instance, the file that matters is where its class was
+ # declared.
+ if hasattr(obj,'__class__'):
+ fname = inspect.getabsfile(obj.__class__)
if fname.endswith(''):
fname = 'Dynamically generated function. No source code available.'
if (fname.endswith('.so') or fname.endswith('.dll')):
@@ -432,8 +438,13 @@ class Inspector:
linecache.checkcache()
source_success = False
try:
- source = self.format(getsource(obj,binary_file))
- if source:
+ try:
+ src = getsource(obj,binary_file)
+ except TypeError:
+ if hasattr(obj,'__class__'):
+ src = getsource(obj.__class__,binary_file)
+ if src is not None:
+ source = self.format(src)
out.write(header('Source:\n')+source.rstrip())
source_success = True
except Exception, msg:
diff --git a/IPython/Release.py b/IPython/Release.py
index 23d7b41..cc9e745 100644
--- a/IPython/Release.py
+++ b/IPython/Release.py
@@ -22,9 +22,15 @@ name = 'ipython'
# because bdist_rpm does not accept dashes (an RPM) convention, and
# bdist_deb does not accept underscores (a Debian convention).
-revision = '3001'
+revision = '128'
+branch = 'ipython'
-version = '0.8.3.svn.r' + revision.rstrip('M')
+if branch == 'ipython':
+ version = '0.8.4.bzr.r' + revision
+else:
+ version = '0.8.4.bzr.r%s.%s' % (revision,branch)
+
+version = '0.8.4'
description = "An enhanced interactive Python shell."
diff --git a/IPython/Shell.py b/IPython/Shell.py
index 1bff3fc..69d2062 100644
--- a/IPython/Shell.py
+++ b/IPython/Shell.py
@@ -46,6 +46,13 @@ from IPython.ipmaker import make_IPython
from IPython.Magic import Magic
from IPython.ipstruct import Struct
+try: # Python 2.3 compatibility
+ set
+except NameError:
+ import sets
+ set = sets.Set
+
+
# Globals
# global flag to pass around information about Ctrl-C without exceptions
KBINT = False
@@ -358,36 +365,37 @@ class MTInteractiveShell(InteractiveShell):
InteractiveShell.__init__(self,name,usage,rc,user_ns,
user_global_ns,banner2)
- # Locking control variable.
- self.thread_ready = threading.Condition(threading.RLock())
- # A queue to hold the code to be executed. A scalar variable is NOT
- # enough, because uses like macros cause reentrancy.
+ # A queue to hold the code to be executed.
self.code_queue = Queue.Queue()
# Stuff to do at closing time
- self._kill = False
- on_kill = kw.get('on_kill')
- if on_kill is None:
- on_kill = []
+ self._kill = None
+ on_kill = kw.get('on_kill', [])
# Check that all things to kill are callable:
for t in on_kill:
if not callable(t):
raise TypeError,'on_kill must be a list of callables'
self.on_kill = on_kill
-
+ # thread identity of the "worker thread" (that may execute code directly)
+ self.worker_ident = None
+
def runsource(self, source, filename="", symbol="single"):
"""Compile and run some source in the interpreter.
Modified version of code.py's runsource(), to handle threading issues.
See the original for full docstring details."""
-
+
global KBINT
# If Ctrl-C was typed, we reset the flag and return right away
if KBINT:
KBINT = False
return False
+
+ if self._kill:
+ # can't queue new code if we are being killed
+ return True
try:
code = self.compile(source, filename, symbol)
@@ -400,29 +408,40 @@ class MTInteractiveShell(InteractiveShell):
# Case 2
return True
+ # shortcut - if we are in worker thread, or the worker thread is not running,
+ # execute directly (to allow recursion and prevent deadlock if code is run early
+ # in IPython construction)
+
+ if (self.worker_ident is None or self.worker_ident == thread.get_ident()):
+ InteractiveShell.runcode(self,code)
+ return
+
# Case 3
# Store code in queue, so the execution thread can handle it.
- # Note that with macros and other applications, we MAY re-enter this
- # section, so we have to acquire the lock with non-blocking semantics,
- # else we deadlock.
- got_lock = self.thread_ready.acquire()
- self.code_queue.put(code)
- if got_lock:
- self.thread_ready.wait() # Wait until processed in timeout interval
- self.thread_ready.release()
-
+ completed_ev, received_ev = threading.Event(), threading.Event()
+
+ self.code_queue.put((code,completed_ev, received_ev))
+ # first make sure the message was received, with timeout
+ received_ev.wait(5)
+ if not received_ev.isSet():
+ # the mainloop is dead, start executing code directly
+ print "Warning: Timeout for mainloop thread exceeded"
+ print "switching to nonthreaded mode (until mainloop wakes up again)"
+ self.worker_ident = None
+ else:
+ completed_ev.wait()
return False
def runcode(self):
"""Execute a code object.
Multithreaded wrapper around IPython's runcode()."""
-
+
global CODE_RUN
-
- # lock thread-protected stuff
- got_lock = self.thread_ready.acquire()
+
+ # we are in worker thread, stash out the id for runsource()
+ self.worker_ident = thread.get_ident()
if self._kill:
print >>Term.cout, 'Closing threads...',
@@ -430,6 +449,9 @@ class MTInteractiveShell(InteractiveShell):
for tokill in self.on_kill:
tokill()
print >>Term.cout, 'Done.'
+ # allow kill() to return
+ self._kill.set()
+ return True
# Install sigint handler. We do it every time to ensure that if user
# code modifies it, we restore our own handling.
@@ -445,10 +467,11 @@ class MTInteractiveShell(InteractiveShell):
code_to_run = None
while 1:
try:
- code_to_run = self.code_queue.get_nowait()
+ code_to_run, completed_ev, received_ev = self.code_queue.get_nowait()
except Queue.Empty:
break
-
+ received_ev.set()
+
# Exceptions need to be raised differently depending on which
# thread is active. This convoluted try/except is only there to
# protect against asynchronous exceptions, to ensure that a KBINT
@@ -462,28 +485,23 @@ class MTInteractiveShell(InteractiveShell):
except KeyboardInterrupt:
print "Keyboard interrupted in mainloop"
while not self.code_queue.empty():
- self.code_queue.get_nowait()
+ code, ev1,ev2 = self.code_queue.get_nowait()
+ ev1.set()
+ ev2.set()
break
finally:
- if got_lock:
- CODE_RUN = False
-
- # We're done with thread-protected variables
- if code_to_run is not None:
- self.thread_ready.notify()
- self.thread_ready.release()
-
- # We're done...
- CODE_RUN = False
+ CODE_RUN = False
+ # allow runsource() return from wait
+ completed_ev.set()
+
+
# This MUST return true for gtk threading to work
return True
def kill(self):
"""Kill the thread, returning when it has been shut down."""
- got_lock = self.thread_ready.acquire(False)
- self._kill = True
- if got_lock:
- self.thread_ready.release()
+ self._kill = threading.Event()
+ self._kill.wait()
class MatplotlibShellBase:
"""Mixin class to provide the necessary modifications to regular IPython
@@ -1051,7 +1069,9 @@ def _load_pylab(user_ns):
ip = IPython.ipapi.get()
if ip.options.pylab_import_all:
- exec "from matplotlib.pylab import *" in user_ns
+ ip.ex("from matplotlib.pylab import *")
+ ip.IP.user_config_ns.update(ip.user_ns)
+
class IPShellMatplotlib(IPShell):
"""Subclass IPShell with MatplotlibShell as the internal shell.
@@ -1144,7 +1164,7 @@ def _select_shell(argv):
all_opts = set(['tk','pylab','gthread','qthread','q4thread','wthread',
'tkthread'])
user_opts = set([s.replace('-','') for s in argv[:3]])
- special_opts = user_opts & all_opts
+ special_opts = user_opts & all_opts
if 'tk' in special_opts:
USE_TK = True
diff --git a/IPython/UserConfig/ipy_user_conf.py b/IPython/UserConfig/ipy_user_conf.py
index 33d158b..2500a18 100644
--- a/IPython/UserConfig/ipy_user_conf.py
+++ b/IPython/UserConfig/ipy_user_conf.py
@@ -72,6 +72,27 @@ def main():
#o.autoexec.append('%colors NoColor')
#o.autoexec.append('%colors Linux')
+ # for sane integer division that converts to float (1/2 == 0.5)
+ #o.autoexec.append('from __future__ import division')
+
+ # For %tasks and %kill
+ #import jobctrl
+
+ # For autoreloading of modules (%autoreload, %aimport)
+ #import ipy_autoreload
+
+ # For winpdb support (%wdb)
+ #import ipy_winpdb
+
+ # For bzr completer, requires bzrlib (the python installation of bzr)
+ #ip.load('ipy_bzr')
+
+ # Tab completer that is not quite so picky (i.e.
+ # "foo". and str(2). will work). Complete
+ # at your own risk!
+ #import ipy_greedycompleter
+
+
# some config helper functions you can use
def import_all(modules):
diff --git a/IPython/completer.py b/IPython/completer.py
index 8d8ec63..0962604 100644
--- a/IPython/completer.py
+++ b/IPython/completer.py
@@ -321,7 +321,7 @@ class IPCompleter(Completer):
# don't want to treat as delimiters in filename matching
# when escaped with backslash
- protectables = ' ()[]{}'
+ protectables = ' '
if text.startswith('!'):
text = text[1:]
diff --git a/IPython/deep_reload.py b/IPython/deep_reload.py
index f8da73c..a0a6236 100644
--- a/IPython/deep_reload.py
+++ b/IPython/deep_reload.py
@@ -32,7 +32,9 @@ import imp
import sys
# Replacement for __import__()
-def deep_import_hook(name, globals=None, locals=None, fromlist=None):
+def deep_import_hook(name, globals=None, locals=None, fromlist=None, level=-1):
+ # For now level is ignored, it's just there to prevent crash
+ # with from __future__ import absolute_import
parent = determine_parent(globals)
q, tail = find_head_package(parent, name)
m = load_tail(q, tail)
diff --git a/IPython/external/mglob.py b/IPython/external/mglob.py
index 37d6a6c..f5e436c 100644
--- a/IPython/external/mglob.py
+++ b/IPython/external/mglob.py
@@ -34,35 +34,35 @@ License: MIT Open Source license
#Assigned in variable for "usage" printing convenience"
globsyntax = """\
-This program allows specifying filenames with "mglob" mechanism.
-Supported syntax in globs (wilcard matching patterns)::
-
- *.cpp ?ellowo*
- - obvious. Differs from normal glob in that dirs are not included.
- Unix users might want to write this as: "*.cpp" "?ellowo*"
- rec:/usr/share=*.txt,*.doc
- - get all *.txt and *.doc under /usr/share,
- recursively
- rec:/usr/share
- - All files under /usr/share, recursively
- rec:*.py
- - All .py files under current working dir, recursively
- foo
- - File or dir foo
- !*.bak readme*
- - readme*, exclude files ending with .bak
- !.svn/ !.hg/ !*_Data/ rec:.
- - Skip .svn, .hg, foo_Data dirs (and their subdirs) in recurse.
- Trailing / is the key, \ does not work!
- dir:foo
- - the directory foo if it exists (not files in foo)
- dir:*
- - all directories in current folder
- foo.py bar.* !h* rec:*.py
- - Obvious. !h* exclusion only applies for rec:*.py.
- foo.py is *not* included twice.
- @filelist.txt
- - All files listed in 'filelist.txt' file, on separate lines.
+ This program allows specifying filenames with "mglob" mechanism.
+ Supported syntax in globs (wilcard matching patterns)::
+
+ *.cpp ?ellowo*
+ - obvious. Differs from normal glob in that dirs are not included.
+ Unix users might want to write this as: "*.cpp" "?ellowo*"
+ rec:/usr/share=*.txt,*.doc
+ - get all *.txt and *.doc under /usr/share,
+ recursively
+ rec:/usr/share
+ - All files under /usr/share, recursively
+ rec:*.py
+ - All .py files under current working dir, recursively
+ foo
+ - File or dir foo
+ !*.bak readme*
+ - readme*, exclude files ending with .bak
+ !.svn/ !.hg/ !*_Data/ rec:.
+ - Skip .svn, .hg, foo_Data dirs (and their subdirs) in recurse.
+ Trailing / is the key, \ does not work!
+ dir:foo
+ - the directory foo if it exists (not files in foo)
+ dir:*
+ - all directories in current folder
+ foo.py bar.* !h* rec:*.py
+ - Obvious. !h* exclusion only applies for rec:*.py.
+ foo.py is *not* included twice.
+ @filelist.txt
+ - All files listed in 'filelist.txt' file, on separate lines.
"""
diff --git a/IPython/external/path.py b/IPython/external/path.py
index 038d7ce..6b0f952 100644
--- a/IPython/external/path.py
+++ b/IPython/external/path.py
@@ -29,7 +29,10 @@ Date: 9 Mar 2007
from __future__ import generators
-import sys, warnings, os, fnmatch, glob, shutil, codecs, md5
+import sys, warnings, os, fnmatch, glob, shutil, codecs
+# deprecated in python 2.6
+warnings.filterwarnings('ignore', r'.*md5.*')
+import md5
__version__ = '2.2'
__all__ = ['path']
diff --git a/IPython/genutils.py b/IPython/genutils.py
index 1aa989f..422f5c5 100644
--- a/IPython/genutils.py
+++ b/IPython/genutils.py
@@ -22,7 +22,10 @@ __license__ = Release.license
# required modules from the Python standard library
import __main__
import commands
-import doctest
+try:
+ import doctest
+except ImportError:
+ pass
import os
import re
import shlex
@@ -33,6 +36,18 @@ import time
import types
import warnings
+# Curses and termios are Unix-only modules
+try:
+ import curses
+ # We need termios as well, so if its import happens to raise, we bail on
+ # using curses altogether.
+ import termios
+except ImportError:
+ USE_CURSES = False
+else:
+ # Curses on Solaris may not be complete, so we can't use it there
+ USE_CURSES = hasattr(curses,'initscr')
+
# Other IPython utilities
import IPython
from IPython.Itpl import Itpl,itpl,printpl
@@ -1052,25 +1067,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 +1113,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.
@@ -1532,26 +1563,30 @@ def page(strng,start=0,screen_lines=0,pager_cmd = None):
# auto-determine screen size
if screen_lines <= 0:
if TERM=='xterm':
- try:
- import curses
- if hasattr(curses,'initscr'):
- use_curses = 1
- else:
- use_curses = 0
- except ImportError:
- use_curses = 0
+ use_curses = USE_CURSES
else:
# curses causes problems on many terminals other than xterm.
- use_curses = 0
+ use_curses = False
if use_curses:
- scr = curses.initscr()
- screen_lines_real,screen_cols = scr.getmaxyx()
- curses.endwin()
- screen_lines += screen_lines_real
- #print '***Screen size:',screen_lines_real,'lines x',\
- #screen_cols,'columns.' # dbg
+ # There is a bug in curses, where *sometimes* it fails to properly
+ # initialize, and then after the endwin() call is made, the
+ # terminal is left in an unusable state. Rather than trying to
+ # check everytime for this (by requesting and comparing termios
+ # flags each time), we just save the initial terminal state and
+ # unconditionally reset it every time. It's cheaper than making
+ # the checks.
+ term_flags = termios.tcgetattr(sys.stdout)
+ scr = curses.initscr()
+ screen_lines_real,screen_cols = scr.getmaxyx()
+ curses.endwin()
+ # Restore terminal state in case endwin() didn't.
+ termios.tcsetattr(sys.stdout,termios.TCSANOW,term_flags)
+ # Now we have what we needed: the screen size in rows/columns
+ screen_lines += screen_lines_real
+ #print '***Screen size:',screen_lines_real,'lines x',\
+ #screen_cols,'columns.' # dbg
else:
- screen_lines += screen_lines_def
+ screen_lines += screen_lines_def
#print 'numlines',numlines,'screenlines',screen_lines # dbg
if numlines <= screen_lines :
diff --git a/IPython/gui/wx/ipshell_nonblocking.py b/IPython/gui/wx/ipshell_nonblocking.py
new file mode 100644
index 0000000..93e9dae
--- /dev/null
+++ b/IPython/gui/wx/ipshell_nonblocking.py
@@ -0,0 +1,460 @@
+#!/usr/bin/python
+# -*- coding: iso-8859-15 -*-
+'''
+Provides IPython remote instance.
+
+@author: Laurent Dufrechou
+laurent.dufrechou _at_ gmail.com
+@license: BSD
+
+All rights reserved. This program and the accompanying materials are made
+available under the terms of the BSD which accompanies this distribution, and
+is available at U{http://www.opensource.org/licenses/bsd-license.php}
+'''
+
+__version__ = 0.9
+__author__ = "Laurent Dufrechou"
+__email__ = "laurent.dufrechou _at_ gmail.com"
+__license__ = "BSD"
+
+import re
+import sys
+import os
+import locale
+import time
+import pydoc,__builtin__,site
+from thread_ex import ThreadEx
+from StringIO import StringIO
+
+try:
+ import IPython
+except Exception,e:
+ raise "Error importing IPython (%s)" % str(e)
+
+##############################################################################
+class _Helper(object):
+ """Redefine the built-in 'help'.
+ This is a wrapper around pydoc.help (with a twist).
+ """
+
+ def __init__(self,pager):
+ self._pager = pager
+
+ def __repr__(self):
+ return "Type help() for interactive help, " \
+ "or help(object) for help about object."
+
+ def __call__(self, *args, **kwds):
+ class DummyWriter(object):
+ def __init__(self,pager):
+ self._pager = pager
+
+ def write(self,data):
+ self._pager(data)
+
+ import pydoc
+ pydoc.help.output = DummyWriter(self._pager)
+ pydoc.help.interact = lambda :1
+
+ return pydoc.help(*args, **kwds)
+
+
+##############################################################################
+class _CodeExecutor(ThreadEx):
+
+ def __init__(self, instance, after):
+ ThreadEx.__init__(self)
+ self.instance = instance
+ self._afterExecute=after
+
+ def run(self):
+ try:
+ self.instance._doc_text = None
+ self.instance._help_text = None
+ self.instance._execute()
+ # used for uper class to generate event after execution
+ self._afterExecute()
+
+ except KeyboardInterrupt:
+ pass
+
+
+##############################################################################
+class NonBlockingIPShell(object):
+ '''
+ Create an IPython instance, running the commands in a separate,
+ non-blocking thread.
+ This allows embedding in any GUI without blockage.
+
+ Note: The ThreadEx class supports asynchroneous function call
+ via raise_exc()
+ '''
+
+ def __init__(self,argv=[],user_ns={},user_global_ns=None,
+ cin=None, cout=None, cerr=None,
+ ask_exit_handler=None):
+ '''
+ @param argv: Command line options for IPython
+ @type argv: list
+ @param user_ns: User namespace.
+ @type user_ns: dictionary
+ @param user_global_ns: User global namespace.
+ @type user_global_ns: dictionary.
+ @param cin: Console standard input.
+ @type cin: IO stream
+ @param cout: Console standard output.
+ @type cout: IO stream
+ @param cerr: Console standard error.
+ @type cerr: IO stream
+ @param exit_handler: Replacement for builtin exit() function
+ @type exit_handler: function
+ @param time_loop: Define the sleep time between two thread's loop
+ @type int
+ '''
+ #ipython0 initialisation
+ self.initIpython0(argv, user_ns, user_global_ns,
+ cin, cout, cerr,
+ ask_exit_handler)
+
+ #vars used by _execute
+ self._iter_more = 0
+ self._history_level = 0
+ self._complete_sep = re.compile('[\s\{\}\[\]\(\)\=]')
+ self._prompt = str(self._IP.outputcache.prompt1).strip()
+
+ #thread working vars
+ self._line_to_execute = ''
+
+ #vars that will be checked by GUI loop to handle thread states...
+ #will be replaced later by PostEvent GUI funtions...
+ self._doc_text = None
+ self._help_text = None
+ self._add_button = None
+
+ def initIpython0(self, argv=[], user_ns={}, user_global_ns=None,
+ cin=None, cout=None, cerr=None,
+ ask_exit_handler=None):
+ #first we redefine in/out/error functions of IPython
+ if cin:
+ IPython.Shell.Term.cin = cin
+ if cout:
+ IPython.Shell.Term.cout = cout
+ if cerr:
+ IPython.Shell.Term.cerr = cerr
+
+ # This is to get rid of the blockage that accurs during
+ # IPython.Shell.InteractiveShell.user_setup()
+ IPython.iplib.raw_input = lambda x: None
+
+ self._term = IPython.genutils.IOTerm(cin=cin, cout=cout, cerr=cerr)
+
+ excepthook = sys.excepthook
+
+ self._IP = IPython.Shell.make_IPython(
+ argv,user_ns=user_ns,
+ user_global_ns=user_global_ns,
+ embedded=True,
+ shell_class=IPython.Shell.InteractiveShell)
+
+ #we replace IPython default encoding by wx locale encoding
+ loc = locale.getpreferredencoding()
+ if loc:
+ self._IP.stdin_encoding = loc
+ #we replace the ipython default pager by our pager
+ self._IP.set_hook('show_in_pager',self._pager)
+
+ #we replace the ipython default shell command caller by our shell handler
+ self._IP.set_hook('shell_hook',self._shell)
+
+ #we replace the ipython default input command caller by our method
+ 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
+
+ #----------------------- Thread management section ----------------------
+ def doExecute(self,line):
+ """
+ Tell the thread to process the 'line' command
+ """
+
+ self._line_to_execute = line
+ #we launch the ipython line execution in a thread to make it interruptible
+ self.ce = _CodeExecutor(self,self._afterExecute)
+ self.ce.start()
+
+ #----------------------- IPython management section ----------------------
+ def getDocText(self):
+ """
+ Returns the output of the processing that need to be paged (if any)
+
+ @return: The std output string.
+ @rtype: string
+ """
+ return self._doc_text
+
+ def getHelpText(self):
+ """
+ Returns the output of the processing that need to be paged via help pager(if any)
+
+ @return: The std output string.
+ @rtype: string
+ """
+ return self._help_text
+
+ def getBanner(self):
+ """
+ Returns the IPython banner for useful info on IPython instance
+
+ @return: The banner string.
+ @rtype: string
+ """
+ return self._IP.BANNER
+
+ def getPromptCount(self):
+ """
+ Returns the prompt number.
+ Each time a user execute a line in the IPython shell the prompt count is increased
+
+ @return: The prompt number
+ @rtype: int
+ """
+ return self._IP.outputcache.prompt_count
+
+ def getPrompt(self):
+ """
+ Returns current prompt inside IPython instance
+ (Can be In [...]: ot ...:)
+
+ @return: The current prompt.
+ @rtype: string
+ """
+ return self._prompt
+
+ def getIndentation(self):
+ """
+ Returns the current indentation level
+ Usefull to put the caret at the good start position if we want to do autoindentation.
+
+ @return: The indentation level.
+ @rtype: int
+ """
+ return self._IP.indent_current_nsp
+
+ def updateNamespace(self, ns_dict):
+ '''
+ Add the current dictionary to the shell namespace.
+
+ @param ns_dict: A dictionary of symbol-values.
+ @type ns_dict: dictionary
+ '''
+ self._IP.user_ns.update(ns_dict)
+
+ def complete(self, line):
+ '''
+ Returns an auto completed line and/or posibilities for completion.
+
+ @param line: Given line so far.
+ @type line: string
+
+ @return: Line completed as for as possible,
+ and possible further completions.
+ @rtype: tuple
+ '''
+ split_line = self._complete_sep.split(line)
+ possibilities = self._IP.complete(split_line[-1])
+ if possibilities:
+
+ def _commonPrefix(str1, str2):
+ '''
+ Reduction function. returns common prefix of two given strings.
+
+ @param str1: First string.
+ @type str1: string
+ @param str2: Second string
+ @type str2: string
+
+ @return: Common prefix to both strings.
+ @rtype: string
+ '''
+ for i in range(len(str1)):
+ if not str2.startswith(str1[:i+1]):
+ return str1[:i]
+ return str1
+ common_prefix = reduce(_commonPrefix, possibilities)
+ completed = line[:-len(split_line[-1])]+common_prefix
+ else:
+ completed = line
+ return completed, possibilities
+
+ def historyBack(self):
+ '''
+ Provides one history command back.
+
+ @return: The command string.
+ @rtype: string
+ '''
+ history = ''
+ #the below while loop is used to suppress empty history lines
+ while((history == '' or history == '\n') and self._history_level >0):
+ if self._history_level>=1:
+ self._history_level -= 1
+ history = self._getHistory()
+ return history
+
+ def historyForward(self):
+ '''
+ Provides one history command forward.
+
+ @return: The command string.
+ @rtype: string
+ '''
+ history = ''
+ #the below while loop is used to suppress empty history lines
+ while((history == '' or history == '\n') and self._history_level <= self._getHistoryMaxIndex()):
+ if self._history_level < self._getHistoryMaxIndex():
+ self._history_level += 1
+ history = self._getHistory()
+ else:
+ if self._history_level == self._getHistoryMaxIndex():
+ history = self._getHistory()
+ self._history_level += 1
+ else:
+ history = ''
+ return history
+
+ def initHistoryIndex(self):
+ '''
+ set history to last command entered
+ '''
+ self._history_level = self._getHistoryMaxIndex()+1
+
+ #----------------------- IPython PRIVATE management section --------------
+ def _afterExecute(self):
+ '''
+ Can be redefined to generate post event after excution is done
+ '''
+ 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
+
+ @return: history length
+ @rtype: int
+ '''
+ return len(self._IP.input_hist_raw)-1
+
+ def _getHistory(self):
+ '''
+ Get's the command string of the current history level.
+
+ @return: Historic command stri
+ @rtype: string
+ '''
+ rv = self._IP.input_hist_raw[self._history_level].strip('\n')
+ return rv
+
+ def _pager_help(self,text):
+ '''
+ This function is used as a callback replacment to IPython help pager function
+
+ It puts the 'text' value inside the self._help_text string that can be retrived via getHelpText
+ function.
+ '''
+ if self._help_text == None:
+ self._help_text = text
+ else:
+ self._help_text += text
+
+ def _pager(self,IP,text):
+ '''
+ This function is used as a callback replacment to IPython pager function
+
+ It puts the 'text' value inside the self._doc_text string that can be retrived via getDocText
+ function.
+ '''
+ 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.
+ '''
+ orig_stdout = sys.stdout
+ sys.stdout = IPython.Shell.Term.cout
+
+ try:
+ line = self._IP.raw_input(None, self._iter_more)
+ if self._IP.autoindent:
+ self._IP.readline_startup_hook(None)
+
+ except KeyboardInterrupt:
+ self._IP.write('\nKeyboardInterrupt\n')
+ self._IP.resetbuffer()
+ # keep cache in sync with the prompt counter:
+ self._IP.outputcache.prompt_count -= 1
+
+ if self._IP.autoindent:
+ self._IP.indent_current_nsp = 0
+ self._iter_more = 0
+ except:
+ self._IP.showtraceback()
+ else:
+ self._iter_more = self._IP.push(line)
+ if (self._IP.SyntaxTB.last_syntax_error and
+ self._IP.rc.autoedit_syntax):
+ self._IP.edit_syntax_error()
+ if self._iter_more:
+ self._prompt = str(self._IP.outputcache.prompt2).strip()
+ if self._IP.autoindent:
+ self._IP.readline_startup_hook(self._IP.pre_readline)
+ else:
+ self._prompt = str(self._IP.outputcache.prompt1).strip()
+ self._IP.indent_current_nsp = 0 #we set indentation to 0
+ sys.stdout = orig_stdout
+
+ def _shell(self, ip, cmd):
+ '''
+ Replacement method to allow shell commands without them blocking.
+
+ @param ip: Ipython instance, same as self._IP
+ @type cmd: Ipython instance
+ @param cmd: Shell command to execute.
+ @type cmd: string
+ '''
+ stdin, stdout = os.popen4(cmd)
+ result = stdout.read().decode('cp437').encode(locale.getpreferredencoding())
+ #we use print command because the shell command is called inside IPython instance and thus is
+ #redirected to thread cout
+ #"\x01\x1b[1;36m\x02" <-- add colour to the text...
+ print "\x01\x1b[1;36m\x02"+result
+ stdout.close()
+ stdin.close()
diff --git a/IPython/gui/wx/ipython_history.py b/IPython/gui/wx/ipython_history.py
index 90d7570..5053886 100644
--- a/IPython/gui/wx/ipython_history.py
+++ b/IPython/gui/wx/ipython_history.py
@@ -28,10 +28,30 @@ class IPythonHistoryPanel(wx.Panel):
self.filter_cmd = wx.CheckBox(self, -1, "!: Sys commands")
self.filter_magic = wx.CheckBox(self, -1, "%: Magic keys")
- self.filter_empty.SetValue(flt_empty)
- self.filter_doc.SetValue(flt_doc)
- self.filter_cmd.SetValue(flt_cmd)
- self.filter_magic.SetValue(flt_magic)
+ self.options={'filter_empty':{'value':'True',
+ 'checkbox':self.filter_empty,'True':True,'False':False,
+ 'setfunc':lambda x:None},
+ 'filter_doc':{'value':'True',
+ 'checkbox':self.filter_doc,'True':True,'False':False,
+ 'setfunc':lambda x:None},
+ 'filter_cmd':{'value':'True',
+ 'checkbox':self.filter_cmd,'True':True,'False':False,
+ 'setfunc':lambda x:None},
+ 'filter_magic':{'value':'True',
+ 'checkbox':self.filter_magic,'True':True,'False':False,
+ 'setfunc':lambda x:None},
+ }
+ self.reloadOptions(self.options)
+
+ self.filter_empty.Bind(wx.EVT_CHECKBOX, self.evtCheckEmptyFilter)
+ self.filter_doc.Bind(wx.EVT_CHECKBOX, self.evtCheckDocFilter)
+ self.filter_cmd.Bind(wx.EVT_CHECKBOX, self.evtCheckCmdFilter)
+ self.filter_magic.Bind(wx.EVT_CHECKBOX, self.evtCheckMagicFilter)
+
+ #self.filter_empty.SetValue(flt_empty)
+ #self.filter_doc.SetValue(flt_doc)
+ #self.filter_cmd.SetValue(flt_cmd)
+ #self.filter_magic.SetValue(flt_magic)
sizer = wx.BoxSizer(wx.VERTICAL)
@@ -70,10 +90,54 @@ class IPythonHistoryPanel(wx.Panel):
add = False
if self.filter_magic.GetValue() == True and history_line[0] == '%':
add = False
- if add:
- self.text_ctrl.AppendText(history_line+'\n')
+ if add:
+ self.text_ctrl.AppendText(history_line+'\n')
+
+#------------------------ Option Section -----------------------------------
+ def processOptionCheckedEvt(self, event, name):
+ if event.IsChecked():
+ self.options[name]['value']='True'
+ else:
+ self.options[name]['value']='False'
+ self.updateOptionTracker(name,
+ self.options[name]['value'])
+
+ def evtCheckEmptyFilter(self, event):
+ self.processOptionCheckedEvt(event, 'filter_empty')
+
+ def evtCheckDocFilter(self, event):
+ self.processOptionCheckedEvt(event, 'filter_doc')
+ def evtCheckCmdFilter(self, event):
+ self.processOptionCheckedEvt(event, 'filter_cmd')
+ def evtCheckMagicFilter(self, event):
+ self.processOptionCheckedEvt(event, 'filter_magic')
+
+ def getOptions(self):
+ return self.options
+
+ def reloadOptions(self,options):
+ self.options = options
+ for key in self.options.keys():
+ value = self.options[key]['value']
+ self.options[key]['checkbox'].SetValue(self.options[key][value])
+ self.options[key]['setfunc'](value)
+
+#------------------------ Hook Section -----------------------------------
+ def updateOptionTracker(self,name,value):
+ '''
+ Default history tracker (does nothing)
+ '''
+ pass
+
+ def setOptionTrackerHook(self,func):
+ '''
+ Define a new history tracker
+ '''
+ self.updateOptionTracker = func
+
+
#----------------------------------------------------------------------
# Font definition for Styled Text Control
diff --git a/IPython/gui/wx/ipython_view.py b/IPython/gui/wx/ipython_view.py
index 04e8c34..940dd8e 100644
--- a/IPython/gui/wx/ipython_view.py
+++ b/IPython/gui/wx/ipython_view.py
@@ -1,7 +1,7 @@
#!/usr/bin/python
# -*- coding: iso-8859-15 -*-
'''
-Provides IPython WX console widget.
+Provides IPython WX console widgets.
@author: Laurent Dufrechou
laurent.dufrechou _at_ gmail.com
@@ -26,433 +26,88 @@ __license__ = "BSD"
import wx
import wx.stc as stc
-import wx.lib.newevent
import re
import sys
-import os
import locale
-import time
-from ThreadEx import Thread
from StringIO import StringIO
-
try:
import IPython
except Exception,e:
raise "Error importing IPython (%s)" % str(e)
-class IterableIPShell(Thread):
+from ipshell_nonblocking import NonBlockingIPShell
+
+class WxNonBlockingIPShell(NonBlockingIPShell):
'''
- Create an IPython instance inside a dedicated thread.
- Does not start a blocking event loop, instead allow single iterations.
- This allows embedding in any GUI without blockage.
- The thread is a slave one, in that it doesn't interact directly with the GUI.
- Note Thread class comes from ThreadEx that supports asynchroneous function call
- via raise_exc()
+ An NonBlockingIPShell Thread that is WX dependent.
'''
-
- def __init__(self,argv=[],user_ns=None,user_global_ns=None,
+ def __init__(self, parent,
+ argv=[],user_ns={},user_global_ns=None,
cin=None, cout=None, cerr=None,
- exit_handler=None,time_loop = 0.1):
- '''
- @param argv: Command line options for IPython
- @type argv: list
- @param user_ns: User namespace.
- @type user_ns: dictionary
- @param user_global_ns: User global namespace.
- @type user_global_ns: dictionary.
- @param cin: Console standard input.
- @type cin: IO stream
- @param cout: Console standard output.
- @type cout: IO stream
- @param cerr: Console standard error.
- @type cerr: IO stream
- @param exit_handler: Replacement for builtin exit() function
- @type exit_handler: function
- @param time_loop: Define the sleep time between two thread's loop
- @type int
- '''
- Thread.__init__(self)
-
- #first we redefine in/out/error functions of IPython
- if cin:
- IPython.Shell.Term.cin = cin
- if cout:
- IPython.Shell.Term.cout = cout
- if cerr:
- IPython.Shell.Term.cerr = cerr
-
- # This is to get rid of the blockage that accurs during
- # IPython.Shell.InteractiveShell.user_setup()
- IPython.iplib.raw_input = lambda x: None
-
- self._term = IPython.genutils.IOTerm(cin=cin, cout=cout, cerr=cerr)
-
- excepthook = sys.excepthook
- self._IP = IPython.Shell.make_IPython(
- argv,user_ns=user_ns,
- user_global_ns=user_global_ns,
- embedded=True,
- shell_class=IPython.Shell.InteractiveShell)
-
- #we replace IPython default encoding by wx locale encoding
- loc = locale.getpreferredencoding()
- if loc:
- self._IP.stdin_encoding = loc
- #we replace the ipython default pager by our pager
- self._IP.set_hook('show_in_pager',self._pager)
-
- #we replace the ipython default shell command caller by our shell handler
- self._IP.set_hook('shell_hook',self._shell)
-
- #we replace the ipython default input command caller by our method
- IPython.iplib.raw_input_original = self._raw_input
- #we replace the ipython default exit command by our method
- self._IP.exit = self._setAskExit
-
- sys.excepthook = excepthook
-
- self._iter_more = 0
- self._history_level = 0
- self._complete_sep = re.compile('[\s\{\}\[\]\(\)]')
- self._prompt = str(self._IP.outputcache.prompt1).strip()
-
- #thread working vars
- self._terminate = False
- self._time_loop = time_loop
- self._has_doc = False
- self._do_execute = False
- self._line_to_execute = ''
- self._doc_text = None
- self._ask_exit = False
-
- #----------------------- Thread management section ----------------------
- def run (self):
- """
- Thread main loop
- The thread will run until self._terminate will be set to True via shutdown() function
- Command processing can be interrupted with Instance.raise_exc(KeyboardInterrupt) call in the
- GUI thread.
- """
- while(not self._terminate):
- try:
- if self._do_execute:
- self._doc_text = None
- self._execute()
- self._do_execute = False
-
- except KeyboardInterrupt:
- pass
-
- time.sleep(self._time_loop)
-
- def shutdown(self):
- """
- Shutdown the tread
- """
- self._terminate = True
-
- def doExecute(self,line):
- """
- Tell the thread to process the 'line' command
- """
- self._do_execute = True
- self._line_to_execute = line
-
- def isExecuteDone(self):
- """
- Returns the processing state
- """
- return not self._do_execute
-
- #----------------------- IPython management section ----------------------
- def getAskExit(self):
- '''
- returns the _ask_exit variable that can be checked by GUI to see if
- IPython request an exit handling
- '''
- return self._ask_exit
-
- def clearAskExit(self):
- '''
- clear the _ask_exit var when GUI as handled the request.
- '''
- self._ask_exit = False
-
- def getDocText(self):
- """
- Returns the output of the processing that need to be paged (if any)
-
- @return: The std output string.
- @rtype: string
- """
- return self._doc_text
-
- def getBanner(self):
- """
- Returns the IPython banner for useful info on IPython instance
-
- @return: The banner string.
- @rtype: string
- """
- return self._IP.BANNER
-
- def getPromptCount(self):
- """
- Returns the prompt number.
- Each time a user execute a line in the IPython shell the prompt count is increased
-
- @return: The prompt number
- @rtype: int
- """
- return self._IP.outputcache.prompt_count
-
- def getPrompt(self):
- """
- Returns current prompt inside IPython instance
- (Can be In [...]: ot ...:)
-
- @return: The current prompt.
- @rtype: string
- """
- return self._prompt
-
- def getIndentation(self):
- """
- Returns the current indentation level
- Usefull to put the caret at the good start position if we want to do autoindentation.
-
- @return: The indentation level.
- @rtype: int
- """
- return self._IP.indent_current_nsp
+ ask_exit_handler=None):
- def updateNamespace(self, ns_dict):
- '''
- Add the current dictionary to the shell namespace.
+ NonBlockingIPShell.__init__(self,argv,user_ns,user_global_ns,
+ cin, cout, cerr,
+ ask_exit_handler)
- @param ns_dict: A dictionary of symbol-values.
- @type ns_dict: dictionary
- '''
- self._IP.user_ns.update(ns_dict)
+ self.parent = parent
- def complete(self, line):
- '''
- Returns an auto completed line and/or posibilities for completion.
+ self.ask_exit_callback = ask_exit_handler
+ self._IP.exit = self._askExit
- @param line: Given line so far.
- @type line: string
+ def addGUIShortcut(self,text,func):
+ wx.CallAfter(self.parent.add_button_handler,
+ button_info={ 'text':text,
+ 'func':self.parent.doExecuteLine(func)})
- @return: Line completed as for as possible,
- and possible further completions.
- @rtype: tuple
- '''
- split_line = self._complete_sep.split(line)
- possibilities = self._IP.complete(split_line[-1])
- if possibilities:
-
- def _commonPrefix(str1, str2):
- '''
- Reduction function. returns common prefix of two given strings.
-
- @param str1: First string.
- @type str1: string
- @param str2: Second string
- @type str2: string
-
- @return: Common prefix to both strings.
- @rtype: string
- '''
- for i in range(len(str1)):
- if not str2.startswith(str1[:i+1]):
- return str1[:i]
- return str1
- common_prefix = reduce(_commonPrefix, possibilities)
- completed = line[:-len(split_line[-1])]+common_prefix
- else:
- completed = line
- return completed, possibilities
+ def _askExit(self):
+ wx.CallAfter(self.ask_exit_callback, ())
- def historyBack(self):
- '''
- Provides one history command back.
+ def _afterExecute(self):
+ wx.CallAfter(self.parent.evtStateExecuteDone, ())
- @return: The command string.
- @rtype: string
- '''
- history = ''
- #the below while loop is used to suppress empty history lines
- while((history == '' or history == '\n') and self._history_level >0):
- if self._history_level>=1:
- self._history_level -= 1
- history = self._getHistory()
- return history
-
- def historyForward(self):
- '''
- Provides one history command forward.
-
- @return: The command string.
- @rtype: string
- '''
- history = ''
- #the below while loop is used to suppress empty history lines
- while((history == '' or history == '\n') and self._history_level <= self._getHistoryMaxIndex()):
- if self._history_level < self._getHistoryMaxIndex():
- self._history_level += 1
- history = self._getHistory()
- else:
- if self._history_level == self._getHistoryMaxIndex():
- history = self._getHistory()
- self._history_level += 1
- else:
- history = ''
- return history
-
- def initHistoryIndex(self):
- '''
- set history to last command entered
- '''
- self._history_level = self._getHistoryMaxIndex()+1
-
- #----------------------- IPython PRIVATE management section ----------------------
- def _setAskExit(self):
- '''
- set the _ask_exit variable that can be cjhecked by GUI to see if
- IPython request an exit handling
- '''
- self._ask_exit = True
-
- def _getHistoryMaxIndex(self):
- '''
- returns the max length of the history buffer
-
- @return: history length
- @rtype: int
- '''
- return len(self._IP.input_hist_raw)-1
-
- def _getHistory(self):
- '''
- Get's the command string of the current history level.
-
- @return: Historic command string.
- @rtype: string
- '''
- rv = self._IP.input_hist_raw[self._history_level].strip('\n')
- return rv
-
- def _pager(self,IP,text):
- '''
- This function is used as a callback replacment to IPython pager function
-
- It puts the 'text' value inside the self._doc_text string that can be retrived via getDocText
- function.
- '''
- 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.
- '''
- orig_stdout = sys.stdout
- sys.stdout = IPython.Shell.Term.cout
- try:
- line = self._IP.raw_input(None, self._iter_more)
- if self._IP.autoindent:
- self._IP.readline_startup_hook(None)
-
- except KeyboardInterrupt:
- self._IP.write('\nKeyboardInterrupt\n')
- self._IP.resetbuffer()
- # keep cache in sync with the prompt counter:
- self._IP.outputcache.prompt_count -= 1
-
- if self._IP.autoindent:
- self._IP.indent_current_nsp = 0
- self._iter_more = 0
- except:
- self._IP.showtraceback()
- else:
- self._iter_more = self._IP.push(line)
- if (self._IP.SyntaxTB.last_syntax_error and
- self._IP.rc.autoedit_syntax):
- self._IP.edit_syntax_error()
- if self._iter_more:
- self._prompt = str(self._IP.outputcache.prompt2).strip()
- if self._IP.autoindent:
- self._IP.readline_startup_hook(self._IP.pre_readline)
- else:
- self._prompt = str(self._IP.outputcache.prompt1).strip()
- self._IP.indent_current_nsp = 0 #we set indentation to 0
- sys.stdout = orig_stdout
-
- def _shell(self, ip, cmd):
- '''
- Replacement method to allow shell commands without them blocking.
-
- @param ip: Ipython instance, same as self._IP
- @type cmd: Ipython instance
- @param cmd: Shell command to execute.
- @type cmd: string
- '''
- stdin, stdout = os.popen4(cmd)
- result = stdout.read().decode('cp437').encode(locale.getpreferredencoding())
- #we use print command because the shell command is called inside IPython instance and thus is
- #redirected to thread cout
- #"\x01\x1b[1;36m\x02" <-- add colour to the text...
- print "\x01\x1b[1;36m\x02"+result
- stdout.close()
- stdin.close()
-
class WxConsoleView(stc.StyledTextCtrl):
'''
Specialized styled text control view for console-like workflow.
- We use here a scintilla frontend thus it can be reused in any GUI taht supports
- scintilla with less work.
+ We use here a scintilla frontend thus it can be reused in any GUI that
+ supports scintilla with less work.
- @cvar ANSI_COLORS_BLACK: Mapping of terminal colors to X11 names.(with Black background)
+ @cvar ANSI_COLORS_BLACK: Mapping of terminal colors to X11 names.
+ (with Black background)
@type ANSI_COLORS_BLACK: dictionary
- @cvar ANSI_COLORS_WHITE: Mapping of terminal colors to X11 names.(with White background)
+ @cvar ANSI_COLORS_WHITE: Mapping of terminal colors to X11 names.
+ (with White background)
@type ANSI_COLORS_WHITE: dictionary
@ivar color_pat: Regex of terminal color pattern
@type color_pat: _sre.SRE_Pattern
'''
- ANSI_STYLES_BLACK ={'0;30': [0,'WHITE'], '0;31': [1,'RED'],
- '0;32': [2,'GREEN'], '0;33': [3,'BROWN'],
- '0;34': [4,'BLUE'], '0;35': [5,'PURPLE'],
- '0;36': [6,'CYAN'], '0;37': [7,'LIGHT GREY'],
- '1;30': [8,'DARK GREY'], '1;31': [9,'RED'],
- '1;32': [10,'SEA GREEN'], '1;33': [11,'YELLOW'],
- '1;34': [12,'LIGHT BLUE'], '1;35': [13,'MEDIUM VIOLET RED'],
- '1;36': [14,'LIGHT STEEL BLUE'], '1;37': [15,'YELLOW']}
-
- ANSI_STYLES_WHITE ={'0;30': [0,'BLACK'], '0;31': [1,'RED'],
- '0;32': [2,'GREEN'], '0;33': [3,'BROWN'],
- '0;34': [4,'BLUE'], '0;35': [5,'PURPLE'],
- '0;36': [6,'CYAN'], '0;37': [7,'LIGHT GREY'],
- '1;30': [8,'DARK GREY'], '1;31': [9,'RED'],
- '1;32': [10,'SEA GREEN'], '1;33': [11,'YELLOW'],
- '1;34': [12,'LIGHT BLUE'], '1;35': [13,'MEDIUM VIOLET RED'],
- '1;36': [14,'LIGHT STEEL BLUE'], '1;37': [15,'YELLOW']}
-
- def __init__(self,parent,prompt,intro="",background_color="BLACK",pos=wx.DefaultPosition, ID = -1, size=wx.DefaultSize,
- style=0):
+ ANSI_STYLES_BLACK={'0;30': [0,'WHITE'], '0;31': [1,'RED'],
+ '0;32': [2,'GREEN'], '0;33': [3,'BROWN'],
+ '0;34': [4,'BLUE'], '0;35': [5,'PURPLE'],
+ '0;36': [6,'CYAN'], '0;37': [7,'LIGHT GREY'],
+ '1;30': [8,'DARK GREY'], '1;31': [9,'RED'],
+ '1;32': [10,'SEA GREEN'], '1;33': [11,'YELLOW'],
+ '1;34': [12,'LIGHT BLUE'], '1;35':
+ [13,'MEDIUM VIOLET RED'],
+ '1;36': [14,'LIGHT STEEL BLUE'],'1;37': [15,'YELLOW']}
+
+ ANSI_STYLES_WHITE={'0;30': [0,'BLACK'], '0;31': [1,'RED'],
+ '0;32': [2,'GREEN'], '0;33': [3,'BROWN'],
+ '0;34': [4,'BLUE'], '0;35': [5,'PURPLE'],
+ '0;36': [6,'CYAN'], '0;37': [7,'LIGHT GREY'],
+ '1;30': [8,'DARK GREY'], '1;31': [9,'RED'],
+ '1;32': [10,'SEA GREEN'], '1;33': [11,'YELLOW'],
+ '1;34': [12,'LIGHT BLUE'], '1;35':
+ [13,'MEDIUM VIOLET RED'],
+ '1;36': [14,'LIGHT STEEL BLUE'],'1;37': [15,'YELLOW']}
+
+ def __init__(self,parent,prompt,intro="",background_color="BLACK",
+ pos=wx.DefaultPosition, ID = -1, size=wx.DefaultSize,
+ style=0, autocomplete_mode = 'IPYTHON'):
'''
Initialize console view.
@@ -464,15 +119,61 @@ class WxConsoleView(stc.StyledTextCtrl):
@param background_color: Can be BLACK or WHITE
@type background_color: string
@param other: init param of styledTextControl (can be used as-is)
+ @param autocomplete_mode: Can be 'IPYTHON' or 'STC'
+ 'IPYTHON' show autocompletion the ipython way
+ 'STC" show it scintilla text control way
'''
stc.StyledTextCtrl.__init__(self, parent, ID, pos, size, style)
- ####### Scintilla configuration ##################################################
+ ####### Scintilla configuration ###################################
- # Ctrl + B or Ctrl + N can be used to zoomin/zoomout the text inside the widget
+ # Ctrl + B or Ctrl + N can be used to zoomin/zoomout the text inside
+ # the widget
self.CmdKeyAssign(ord('B'), stc.STC_SCMOD_CTRL, stc.STC_CMD_ZOOMIN)
self.CmdKeyAssign(ord('N'), stc.STC_SCMOD_CTRL, stc.STC_CMD_ZOOMOUT)
+ #We draw a line at position 80
+ self.SetEdgeMode(stc.STC_EDGE_LINE)
+ self.SetEdgeColumn(80)
+ self.SetEdgeColour(wx.LIGHT_GREY)
+
+ #self.SetViewWhiteSpace(True)
+ #self.SetViewEOL(True)
+ self.SetEOLMode(stc.STC_EOL_CRLF)
+ #self.SetWrapMode(stc.STC_WRAP_CHAR)
+ #self.SetWrapMode(stc.STC_WRAP_WORD)
+ self.SetBufferedDraw(True)
+ #self.SetUseAntiAliasing(True)
+ self.SetLayoutCache(stc.STC_CACHE_PAGE)
+ self.SetUndoCollection(False)
+ self.SetUseTabs(True)
+ self.SetIndent(4)
+ self.SetTabWidth(4)
+
+ self.EnsureCaretVisible()
+
+ self.SetMargins(3,3) #text is moved away from border with 3px
+ # Suppressing Scintilla margins
+ self.SetMarginWidth(0,0)
+ self.SetMarginWidth(1,0)
+ self.SetMarginWidth(2,0)
+
+ self.background_color = background_color
+ self.buildStyles()
+
+ self.indent = 0
+ self.prompt_count = 0
+ self.color_pat = re.compile('\x01?\x1b\[(.*?)m\x02?')
+
+ self.write(intro)
+ self.setPrompt(prompt)
+ self.showPrompt()
+
+ self.autocomplete_mode = autocomplete_mode
+
+ self.Bind(wx.EVT_KEY_DOWN, self._onKeypress)
+
+ def buildStyles(self):
#we define platform specific fonts
if wx.Platform == '__WXMSW__':
faces = { 'times': 'Times New Roman',
@@ -499,61 +200,64 @@ class WxConsoleView(stc.StyledTextCtrl):
'size2': 8,
}
- #We draw a line at position 80
- self.SetEdgeMode(stc.STC_EDGE_LINE)
- self.SetEdgeColumn(80)
- self.SetEdgeColour(wx.LIGHT_GREY)
-
- #self.SetViewWhiteSpace(True)
- #self.SetViewEOL(True)
- self.SetEOLMode(stc.STC_EOL_CRLF)
- #self.SetWrapMode(stc.STC_WRAP_CHAR)
- #self.SetWrapMode(stc.STC_WRAP_WORD)
- self.SetBufferedDraw(True)
- #self.SetUseAntiAliasing(True)
- self.SetLayoutCache(stc.STC_CACHE_PAGE)
-
- self.EnsureCaretVisible()
-
- self.SetMargins(3,3) #text is moved away from border with 3px
- # Suppressing Scintilla margins
- self.SetMarginWidth(0,0)
- self.SetMarginWidth(1,0)
- self.SetMarginWidth(2,0)
-
# make some styles
- if background_color != "BLACK":
+ if self.background_color != "BLACK":
self.background_color = "WHITE"
self.SetCaretForeground("BLACK")
self.ANSI_STYLES = self.ANSI_STYLES_WHITE
else:
- self.background_color = background_color
self.SetCaretForeground("WHITE")
self.ANSI_STYLES = self.ANSI_STYLES_BLACK
- self.StyleSetSpec(stc.STC_STYLE_DEFAULT, "fore:%s,back:%s,size:%d,face:%s" % (self.ANSI_STYLES['0;30'][1],
- self.background_color,
- faces['size'], faces['mono']))
+ self.StyleSetSpec(stc.STC_STYLE_DEFAULT,
+ "fore:%s,back:%s,size:%d,face:%s"
+ % (self.ANSI_STYLES['0;30'][1],
+ self.background_color,
+ faces['size'], faces['mono']))
self.StyleClearAll()
- self.StyleSetSpec(stc.STC_STYLE_BRACELIGHT, "fore:#FF0000,back:#0000FF,bold")
- self.StyleSetSpec(stc.STC_STYLE_BRACEBAD, "fore:#000000,back:#FF0000,bold")
-
+ self.StyleSetSpec(stc.STC_STYLE_BRACELIGHT,
+ "fore:#FF0000,back:#0000FF,bold")
+ self.StyleSetSpec(stc.STC_STYLE_BRACEBAD,
+ "fore:#000000,back:#FF0000,bold")
+
for style in self.ANSI_STYLES.values():
self.StyleSetSpec(style[0], "bold,fore:%s" % style[1])
#######################################################################
- self.indent = 0
- self.prompt_count = 0
- self.color_pat = re.compile('\x01?\x1b\[(.*?)m\x02?')
+ def setBackgroundColor(self,color):
+ self.background_color = color
+ self.buildStyles()
+
+ def getBackgroundColor(self,color):
+ return self.background_color
- self.write(intro)
- self.setPrompt(prompt)
- self.showPrompt()
+ 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'
- self.Bind(wx.EVT_KEY_DOWN, self._onKeypress, self)
- #self.Bind(stc.EVT_STC_UPDATEUI, self.OnUpdateUI)
-
+
def write(self, text):
'''
Write given text to buffer.
@@ -641,18 +345,6 @@ class WxConsoleView(stc.StyledTextCtrl):
return self.GetTextRange(self.getCurrentPromptStart(),
self.getCurrentLineEnd())
- def showReturned(self, text):
- '''
- Show returned text from last command and print new prompt.
-
- @param text: Text to show.
- @type text: string
- '''
- self.write('\n'+text)
- if text:
- self.write('\n')
- self.showPrompt()
-
def moveCursorOnNewValidKey(self):
#If cursor is at wrong position put it at last line...
if self.GetCurrentPos() < self.getCurrentPromptStart():
@@ -679,33 +371,53 @@ class WxConsoleView(stc.StyledTextCtrl):
def writeHistory(self,history):
self.removeFromTo(self.getCurrentPromptStart(),self.getCurrentLineEnd())
self.changeLine(history)
+
+ def setCompletionMethod(self, completion):
+ if completion in ['IPYTHON','STC']:
+ self.autocomplete_mode = completion
+ else:
+ raise AttributeError
+
+ def getCompletionMethod(self, completion):
+ return self.autocomplete_mode
def writeCompletion(self, possibilities):
- max_len = len(max(possibilities,key=len))
- max_symbol =' '*max_len
-
- #now we check how much symbol we can put on a line...
- cursor_pos = self.getCursorPos()
- test_buffer = max_symbol + ' '*4
- current_lines = self.GetLineCount()
-
- allowed_symbols = 80/len(test_buffer)
- if allowed_symbols == 0:
- allowed_symbols = 1
+ if self.autocomplete_mode == 'IPYTHON':
+ max_len = len(max(possibilities,key=len))
+ max_symbol =' '*max_len
+
+ #now we check how much symbol we can put on a line...
+ cursor_pos = self.getCursorPos()
+ test_buffer = max_symbol + ' '*4
+ current_lines = self.GetLineCount()
+
+ allowed_symbols = 80/len(test_buffer)
+ if allowed_symbols == 0:
+ allowed_symbols = 1
+
+ pos = 1
+ buf = ''
+ for symbol in possibilities:
+ #buf += symbol+'\n'#*spaces)
+ if pos self.getCurrentPromptStart():
- self.removeFromTo(self.getCursorPos()-1,self.getCursorPos())
- return True
-
- if skip:
- if event.GetKeyCode() not in [wx.WXK_PAGEUP,wx.WXK_PAGEDOWN] and event.Modifiers == wx.MOD_NONE:
+ return True
+ elif event.Modifiers == wx.MOD_SHIFT:
+ self.moveCursorOnNewValidKey()
+ self.selectFromTo(self.getCurrentPromptStart(),self.getCursorPos())
+ return True
+ else:
+ return False
+
+ elif event.GetKeyCode() == wx.WXK_LEFT:
+ if event.Modifiers == wx.MOD_NONE:
+ self.moveCursorOnNewValidKey()
+
+ self.moveCursor(self.getCursorPos()-1)
+ if self.getCursorPos() < self.getCurrentPromptStart():
+ self.moveCursor(self.getCurrentPromptStart())
+ return True
+
+ elif event.GetKeyCode() == wx.WXK_BACK:
self.moveCursorOnNewValidKey()
-
+ if self.getCursorPos() > self.getCurrentPromptStart():
+ event.Skip()
+ return True
+
+ if skip:
+ if event.GetKeyCode() not in [wx.WXK_PAGEUP,wx.WXK_PAGEDOWN] and event.Modifiers == wx.MOD_NONE:
+ self.moveCursorOnNewValidKey()
+
+ event.Skip()
+ return True
+ return False
+ else:
event.Skip()
- return True
- return False
-
+
def OnUpdateUI(self, evt):
# check for matching braces
braceAtCaret = -1
@@ -791,49 +506,90 @@ class WxConsoleView(stc.StyledTextCtrl):
#print pt
#self.Refresh(False)
-class WxIPythonViewPanel(wx.Panel):
+class IPShellWidget(wx.Panel):
'''
This is wx.Panel that embbed the IPython Thread and the wx.StyledTextControl
- If you want to port this to any other GUI toolkit, just replace the WxConsoleView
- by YOURGUIConsoleView and make YOURGUIIPythonView derivate from whatever container you want.
- I've choosed to derivate from a wx.Panel because it seems to be ore usefull
- Any idea to make it more 'genric' welcomed.
+ If you want to port this to any other GUI toolkit, just replace the
+ WxConsoleView by YOURGUIConsoleView and make YOURGUIIPythonView derivate
+ from whatever container you want. I've choosed to derivate from a wx.Panel
+ because it seems to be more useful
+ Any idea to make it more 'generic' welcomed.
'''
- def __init__(self,parent,exit_handler=None,intro=None,background_color="BLACK"):
+
+ def __init__(self, parent, intro=None,
+ background_color="BLACK", add_button_handler=None,
+ wx_ip_shell=None, user_ns={},user_global_ns=None,
+ ):
'''
Initialize.
Instanciate an IPython thread.
Instanciate a WxConsoleView.
Redirect I/O to console.
'''
- wx.Panel.__init__(self,parent,-1)
+ wx.Panel.__init__(self,parent,wx.ID_ANY)
- ### IPython thread instanciation ###
+ self.parent = parent
+ ### IPython non blocking shell instanciation ###
self.cout = StringIO()
- self.IP = IterableIPShell(cout=self.cout,cerr=self.cout,
- exit_handler = exit_handler,
- time_loop = 0.1)
- self.IP.start()
-
+ self.add_button_handler = add_button_handler
+
+ if wx_ip_shell is not None:
+ self.IP = wx_ip_shell
+ else:
+ self.IP = WxNonBlockingIPShell(self,
+ cout = self.cout, cerr = self.cout,
+ ask_exit_handler = self.askExitCallback)
+
### IPython wx console view instanciation ###
#If user didn't defined an intro text, we create one for him
- #If you really wnat an empty intrp just call wxIPythonViewPanel with intro=''
- if intro == None:
+ #If you really wnat an empty intro just call wxIPythonViewPanel
+ #with intro=''
+ if intro is None:
welcome_text = "Welcome to WxIPython Shell.\n\n"
welcome_text+= self.IP.getBanner()
welcome_text+= "!command -> Execute command in shell\n"
welcome_text+= "TAB -> Autocompletion\n"
+ else:
+ welcome_text = intro
self.text_ctrl = WxConsoleView(self,
self.IP.getPrompt(),
intro=welcome_text,
background_color=background_color)
-
- self.text_ctrl.Bind(wx.EVT_KEY_DOWN, self.keyPress, self.text_ctrl)
+ self.cout.write = self.text_ctrl.asyncWrite
+
+ option_text = wx.StaticText(self, -1, "Options:")
+ self.completion_option = wx.CheckBox(self, -1, "Scintilla Completion")
+ #self.completion_option.SetValue(False)
+ self.background_option = wx.CheckBox(self, -1, "White Background")
+ #self.background_option.SetValue(False)
+
+ self.options={'completion':{'value':'IPYTHON',
+ 'checkbox':self.completion_option,'STC':True,'IPYTHON':False,
+ 'setfunc':self.text_ctrl.setCompletionMethod},
+ 'background_color':{'value':'BLACK',
+ 'checkbox':self.background_option,'WHITE':True,'BLACK':False,
+ 'setfunc':self.text_ctrl.setBackgroundColor},
+ }
+ self.reloadOptions(self.options)
+
+ self.text_ctrl.Bind(wx.EVT_KEY_DOWN, self.keyPress)
+ self.completion_option.Bind(wx.EVT_CHECKBOX, self.evtCheckOptionCompletion)
+ self.background_option.Bind(wx.EVT_CHECKBOX, self.evtCheckOptionBackgroundColor)
+
### making the layout of the panel ###
sizer = wx.BoxSizer(wx.VERTICAL)
sizer.Add(self.text_ctrl, 1, wx.EXPAND)
+ option_sizer = wx.BoxSizer(wx.HORIZONTAL)
+ sizer.Add(option_sizer, 0)
+ option_sizer.AddMany([(10, 20),
+ (option_text, 0, wx.ALIGN_CENTER_VERTICAL),
+ (5, 5),
+ (self.completion_option, 0, wx.ALIGN_CENTER_VERTICAL),
+ (8, 8),
+ (self.background_option, 0, wx.ALIGN_CENTER_VERTICAL)
+ ])
self.SetAutoLayout(True)
sizer.Fit(self)
sizer.SetSizeHints(self)
@@ -841,158 +597,151 @@ class WxIPythonViewPanel(wx.Panel):
#and we focus on the widget :)
self.SetFocus()
- ### below are the thread communication variable ###
- # the IPython thread is managed via unidirectional communication.
- # It's a thread slave that can't interact by itself with the GUI.
- # When the GUI event loop is done runStateMachine() is called and the thread sate is then
- # managed.
-
- #Initialize the state machine #kept for information
- #self.states = ['IDLE',
- # 'DO_EXECUTE_LINE',
- # 'WAIT_END_OF_EXECUTION',
- # 'SHOW_DOC',
- # 'SHOW_PROMPT']
-
- self.cur_state = 'IDLE'
- self.pager_state = 'DONE'
- #wx.CallAfter(self.runStateMachine)
+ #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):
+ lines=self.text_ctrl.getCurrentLine()
+ self.text_ctrl.write('\n')
+ lines_to_execute = lines.replace('\t',' '*4)
+ lines_to_execute = lines_to_execute.replace('\r','')
+ self.IP.doExecute(lines_to_execute.encode('cp1252'))
+ self.updateHistoryTracker(lines)
+ self.setCurrentState('WAIT_END_OF_EXECUTION')
+
+ def evtStateExecuteDone(self,evt):
+ self.doc = self.IP.getDocText()
+ self.help = self.IP.getHelpText()
+ if self.doc:
+ self.pager_lines = self.doc[7:].split('\n')
+ self.pager_state = 'INIT'
+ self.setCurrentState('SHOW_DOC')
+ self.pager(self.doc)
+ elif self.help:
+ self.pager_lines = self.help.split('\n')
+ self.pager_state = 'INIT'
+ self.setCurrentState('SHOW_DOC')
+ self.pager(self.help)
+ else:
+ self.stateShowPrompt()
+
+ def stateShowPrompt(self):
+ self.setCurrentState('SHOW_PROMPT')
+ self.text_ctrl.setPrompt(self.IP.getPrompt())
+ self.text_ctrl.setIndentation(self.IP.getIndentation())
+ self.text_ctrl.setPromptCount(self.IP.getPromptCount())
+ self.text_ctrl.showPrompt()
+ self.IP.initHistoryIndex()
+ self.setCurrentState('IDLE')
+
+ def setCurrentState(self, state):
+ self.cur_state = state
+ self.updateStatusTracker(self.cur_state)
- # This creates a new Event class and a EVT binder function
- (self.AskExitEvent, EVT_ASK_EXIT) = wx.lib.newevent.NewEvent()
+ def pager(self,text):
- self.Bind(wx.EVT_IDLE, self.runStateMachine)
- self.Bind(EVT_ASK_EXIT, exit_handler)
-
- def __del__(self):
- self.IP.shutdown()
- self.IP.join()
- WxConsoleView.__del__()
-
- #---------------------------- IPython Thread Management ---------------------------------------
- def runStateMachine(self,event):
- #print >>self.sys_stdout,"state:",self.cur_state
- self.updateStatusTracker(self.cur_state)
-
- if self.cur_state == 'DO_EXECUTE_LINE':
- #print >>self.sys_stdout,"command:",self.getCurrentLine()
- self.IP.doExecute(self.text_ctrl.getCurrentLine().replace('\t',' '*4))
- self.updateHistoryTracker(self.text_ctrl.getCurrentLine())
- self.cur_state = 'WAIT_END_OF_EXECUTION'
-
- if self.cur_state == 'WAIT_END_OF_EXECUTION':
- if self.IP.isExecuteDone():
- self.doc = self.IP.getDocText()
- if self.IP.getAskExit():
- evt = self.AskExitEvent()
- wx.PostEvent(self, evt)
- self.IP.clearAskExit()
- if self.doc:
- self.pager_state = 'INIT'
- self.cur_state = 'SHOW_DOC'
+ if self.pager_state == 'INIT':
+ #print >>sys.__stdout__,"PAGER state:",self.pager_state
+ self.pager_nb_lines = len(self.pager_lines)
+ self.pager_index = 0
+ self.pager_do_remove = False
+ self.text_ctrl.write('\n')
+ self.pager_state = 'PROCESS_LINES'
+
+ if self.pager_state == 'PROCESS_LINES':
+ #print >>sys.__stdout__,"PAGER state:",self.pager_state
+ if self.pager_do_remove == True:
+ self.text_ctrl.removeCurrentLine()
+ self.pager_do_remove = False
+
+ if self.pager_nb_lines > 10:
+ #print >>sys.__stdout__,"PAGER processing 10 lines"
+ if self.pager_index > 0:
+ self.text_ctrl.write(">\x01\x1b[1;36m\x02"+self.pager_lines[self.pager_index]+'\n')
+ else:
+ self.text_ctrl.write("\x01\x1b[1;36m\x02 "+self.pager_lines[self.pager_index]+'\n')
+
+ for line in self.pager_lines[self.pager_index+1:self.pager_index+9]:
+ self.text_ctrl.write("\x01\x1b[1;36m\x02 "+line+'\n')
+ self.pager_index += 10
+ self.pager_nb_lines -= 10
+ self.text_ctrl.write("--- Push Enter to continue or 'Q' to quit---")
+ self.pager_do_remove = True
+ self.pager_state = 'WAITING'
+ return
else:
- self.cur_state = 'SHOW_PROMPT'
-
- if self.cur_state == 'SHOW_PROMPT':
- self.text_ctrl.setPrompt(self.IP.getPrompt())
- self.text_ctrl.setIndentation(self.IP.getIndentation())
- self.text_ctrl.setPromptCount(self.IP.getPromptCount())
- rv = self.cout.getvalue()
- if rv: rv = rv.strip('\n')
- self.text_ctrl.showReturned(rv)
- self.cout.truncate(0)
- self.IP.initHistoryIndex()
- self.cur_state = 'IDLE'
-
- if self.cur_state == 'SHOW_DOC':
- self.pager(self.doc)
- if self.pager_state == 'DONE':
- self.cur_state = 'SHOW_PROMPT'
-
- event.Skip()
-
- #---------------------------- IPython pager ---------------------------------------
- def pager(self,text):#,start=0,screen_lines=0,pager_cmd = None):
- if self.pager_state == 'WAITING':
- #print >>self.sys_stdout,"PAGER waiting"
- return
-
- if self.pager_state == 'INIT':
- #print >>self.sys_stdout,"PAGER state:",self.pager_state
- self.pager_lines = text[7:].split('\n')
- self.pager_nb_lines = len(self.pager_lines)
- self.pager_index = 0
- self.pager_do_remove = False
- self.text_ctrl.write('\n')
- self.pager_state = 'PROCESS_LINES'
-
- if self.pager_state == 'PROCESS_LINES':
- #print >>self.sys_stdout,"PAGER state:",self.pager_state
- if self.pager_do_remove == True:
- self.text_ctrl.removeCurrentLine()
- self.pager_do_remove = False
-
- if self.pager_nb_lines > 10:
- #print >>self.sys_stdout,"PAGER processing 10 lines"
- if self.pager_index > 0:
- self.text_ctrl.write(">\x01\x1b[1;36m\x02"+self.pager_lines[self.pager_index]+'\n')
- else:
- self.text_ctrl.write("\x01\x1b[1;36m\x02 "+self.pager_lines[self.pager_index]+'\n')
-
- for line in self.pager_lines[self.pager_index+1:self.pager_index+9]:
- self.text_ctrl.write("\x01\x1b[1;36m\x02 "+line+'\n')
- self.pager_index += 10
- self.pager_nb_lines -= 10
- self.text_ctrl.write("--- Push Enter to continue or 'Q' to quit---")
- self.pager_do_remove = True
- self.pager_state = 'WAITING'
- return
- else:
- #print >>self.sys_stdout,"PAGER processing last lines"
- if self.pager_nb_lines > 0:
- if self.pager_index > 0:
- self.text_ctrl.write(">\x01\x1b[1;36m\x02"+self.pager_lines[self.pager_index]+'\n')
- else:
- self.text_ctrl.write("\x01\x1b[1;36m\x02 "+self.pager_lines[self.pager_index]+'\n')
-
- self.pager_index += 1
+ #print >>sys.__stdout__,"PAGER processing last lines"
+ if self.pager_nb_lines > 0:
+ if self.pager_index > 0:
+ self.text_ctrl.write(">\x01\x1b[1;36m\x02"+self.pager_lines[self.pager_index]+'\n')
+ else:
+ self.text_ctrl.write("\x01\x1b[1;36m\x02 "+self.pager_lines[self.pager_index]+'\n')
+
+ self.pager_index += 1
self.pager_nb_lines -= 1
- if self.pager_nb_lines > 0:
- for line in self.pager_lines[self.pager_index:]:
- self.text_ctrl.write("\x01\x1b[1;36m\x02 "+line+'\n')
- self.pager_nb_lines = 0
- self.pager_state = 'DONE'
+ if self.pager_nb_lines > 0:
+ for line in self.pager_lines[self.pager_index:]:
+ self.text_ctrl.write("\x01\x1b[1;36m\x02 "+line+'\n')
+ self.pager_nb_lines = 0
+ self.pager_state = 'DONE'
+ self.stateShowPrompt()
- #---------------------------- Key Handler --------------------------------------------
+ #------------------------ Key Handler ------------------------------------
def keyPress(self, event):
'''
Key press callback with plenty of shell goodness, like history,
autocompletions, etc.
'''
-
if event.GetKeyCode() == ord('C'):
- if event.Modifiers == wx.MOD_CONTROL:
+ if event.Modifiers == wx.MOD_CONTROL or event.Modifiers == wx.MOD_ALT:
if self.cur_state == 'WAIT_END_OF_EXECUTION':
#we raise an exception inside the IPython thread container
- self.IP.raise_exc(KeyboardInterrupt)
+ self.IP.ce.raise_exc(KeyboardInterrupt)
return
+ #let this before 'wx.WXK_RETURN' because we have to put 'IDLE'
+ #mode if AutoComp has been set as inactive
+ if self.cur_state == 'COMPLETING':
+ if not self.text_ctrl.AutoCompActive():
+ self.cur_state = 'IDLE'
+ else:
+ event.Skip()
+
if event.KeyCode == wx.WXK_RETURN:
if self.cur_state == 'IDLE':
#we change the state ot the state machine
- self.cur_state = 'DO_EXECUTE_LINE'
+ self.setCurrentState('DO_EXECUTE_LINE')
+ self.stateDoExecuteLine()
return
+
if self.pager_state == 'WAITING':
self.pager_state = 'PROCESS_LINES'
+ self.pager(self.doc)
return
+ if self.cur_state == 'WAITING_USER_INPUT':
+ line=self.text_ctrl.getCurrentLine()
+ self.text_ctrl.write('\n')
+ self.setCurrentState('WAIT_END_OF_EXECUTION')
+ return
+
if event.GetKeyCode() in [ord('q'),ord('Q')]:
if self.pager_state == 'WAITING':
self.pager_state = 'DONE'
+ self.text_ctrl.write('\n')
+ self.stateShowPrompt()
return
+
+ if self.cur_state == 'WAITING_USER_INPUT':
+ event.Skip()
- #scroll_position = self.text_ctrl.GetScrollPos(wx.VERTICAL)
- if self.cur_state == 'IDLE':
+ if self.cur_state == 'IDLE':
if event.KeyCode == wx.WXK_UP:
history = self.IP.historyBack()
self.text_ctrl.writeHistory(history)
@@ -1008,19 +757,68 @@ class WxIPythonViewPanel(wx.Panel):
return
completed, possibilities = self.IP.complete(self.text_ctrl.getCurrentLine())
if len(possibilities) > 1:
- cur_slice = self.text_ctrl.getCurrentLine()
- self.text_ctrl.write('\n')
- self.text_ctrl.writeCompletion(possibilities)
- self.text_ctrl.write('\n')
-
- self.text_ctrl.showPrompt()
- self.text_ctrl.write(cur_slice)
- self.text_ctrl.changeLine(completed or cur_slice)
-
+ if self.text_ctrl.autocomplete_mode == 'IPYTHON':
+ cur_slice = self.text_ctrl.getCurrentLine()
+ self.text_ctrl.write('\n')
+ self.text_ctrl.writeCompletion(possibilities)
+ self.text_ctrl.write('\n')
+
+ self.text_ctrl.showPrompt()
+ self.text_ctrl.write(cur_slice)
+ self.text_ctrl.changeLine(completed or cur_slice)
+ else:
+ self.cur_state = 'COMPLETING'
+ self.text_ctrl.writeCompletion(possibilities)
+ else:
+ self.text_ctrl.changeLine(completed or cur_slice)
return
event.Skip()
-
- #---------------------------- Hook Section --------------------------------------------
+
+ #------------------------ Option Section ---------------------------------
+ def evtCheckOptionCompletion(self, event):
+ if event.IsChecked():
+ self.options['completion']['value']='STC'
+ else:
+ self.options['completion']['value']='IPYTHON'
+ self.text_ctrl.setCompletionMethod(self.options['completion']['value'])
+ self.updateOptionTracker('completion',
+ self.options['completion']['value'])
+ self.text_ctrl.SetFocus()
+
+ def evtCheckOptionBackgroundColor(self, event):
+ if event.IsChecked():
+ self.options['background_color']['value']='WHITE'
+ else:
+ self.options['background_color']['value']='BLACK'
+ self.text_ctrl.setBackgroundColor(self.options['background_color']['value'])
+ self.updateOptionTracker('background_color',
+ self.options['background_color']['value'])
+ self.text_ctrl.SetFocus()
+
+ def getOptions(self):
+ return self.options
+
+ def reloadOptions(self,options):
+ self.options = options
+ for key in self.options.keys():
+ value = self.options[key]['value']
+ self.options[key]['checkbox'].SetValue(self.options[key][value])
+ self.options[key]['setfunc'](value)
+
+
+ #------------------------ Hook Section -----------------------------------
+ def updateOptionTracker(self,name,value):
+ '''
+ Default history tracker (does nothing)
+ '''
+ pass
+
+ def setOptionTrackerHook(self,func):
+ '''
+ Define a new history tracker
+ '''
+ self.updateOptionTracker = func
+
def updateHistoryTracker(self,command_line):
'''
Default history tracker (does nothing)
@@ -1032,6 +830,7 @@ class WxIPythonViewPanel(wx.Panel):
Define a new history tracker
'''
self.updateHistoryTracker = func
+
def updateStatusTracker(self,status):
'''
Default status tracker (does nothing)
@@ -1043,4 +842,36 @@ class WxIPythonViewPanel(wx.Panel):
Define a new status tracker
'''
self.updateStatusTracker = func
-
+
+ def askExitHandler(self, event):
+ '''
+ Default exit handler
+ '''
+ self.text_ctrl.write('\nExit callback has not been set.')
+
+ def setAskExitHandler(self, func):
+ '''
+ Define an exit handler
+ '''
+ self.askExitHandler = func
+
+if __name__ == '__main__':
+ # Some simple code to test the shell widget.
+ class MainWindow(wx.Frame):
+ def __init__(self, parent, id, title):
+ wx.Frame.__init__(self, parent, id, title, size=(300,250))
+ self._sizer = wx.BoxSizer(wx.VERTICAL)
+ self.shell = IPShellWidget(self)
+ self._sizer.Add(self.shell, 1, wx.EXPAND)
+ self.SetSizer(self._sizer)
+ self.SetAutoLayout(1)
+ self.Show(True)
+
+ app = wx.PySimpleApp()
+ frame = MainWindow(None, wx.ID_ANY, 'Ipython')
+ frame.SetSize((780, 460))
+ shell = frame.shell
+
+ app.MainLoop()
+
+
diff --git a/IPython/gui/wx/options.conf b/IPython/gui/wx/options.conf
new file mode 100644
index 0000000..b202640
--- /dev/null
+++ b/IPython/gui/wx/options.conf
@@ -0,0 +1,6 @@
+completion=IPYTHON
+background_color=BLACK
+filter_empty=True
+filter_magic=True
+filter_doc=True
+filter_cmd=True
diff --git a/IPython/gui/wx/ThreadEx.py b/IPython/gui/wx/thread_ex.py
similarity index 89%
rename from IPython/gui/wx/ThreadEx.py
rename to IPython/gui/wx/thread_ex.py
index 071f50a..0af86d0 100644
--- a/IPython/gui/wx/ThreadEx.py
+++ b/IPython/gui/wx/thread_ex.py
@@ -1,45 +1,50 @@
-import threading
-import inspect
-import ctypes
-
-
-def _async_raise(tid, exctype):
- """raises the exception, performs cleanup if needed"""
- if not inspect.isclass(exctype):
- raise TypeError("Only types can be raised (not instances)")
- res = ctypes.pythonapi.PyThreadState_SetAsyncExc(tid, ctypes.py_object(exctype))
- if res == 0:
- raise ValueError("invalid thread id")
- elif res != 1:
- # """if it returns a number greater than one, you're in trouble,
- # and you should call it again with exc=NULL to revert the effect"""
- ctypes.pythonapi.PyThreadState_SetAsyncExc(tid, 0)
- raise SystemError("PyThreadState_SetAsyncExc failed")
-
-
-class Thread(threading.Thread):
- def _get_my_tid(self):
- """determines this (self's) thread id"""
- if not self.isAlive():
- raise threading.ThreadError("the thread is not active")
-
- # do we have it cached?
- if hasattr(self, "_thread_id"):
- return self._thread_id
-
- # no, look for it in the _active dict
- for tid, tobj in threading._active.items():
- if tobj is self:
- self._thread_id = tid
- return tid
-
- raise AssertionError("could not determine the thread's id")
-
- def raise_exc(self, exctype):
- """raises the given exception type in the context of this thread"""
- _async_raise(self._get_my_tid(), exctype)
-
- def kill(self):
- """raises SystemExit in the context of the given thread, which should
- cause the thread to exit silently (unless caught)"""
- self.raise_exc(SystemExit)
+"""
+Thread subclass that can deal with asynchronously function calls via
+raise_exc.
+"""
+
+import threading
+import inspect
+import ctypes
+
+
+def _async_raise(tid, exctype):
+ """raises the exception, performs cleanup if needed"""
+ if not inspect.isclass(exctype):
+ raise TypeError("Only types can be raised (not instances)")
+ res = ctypes.pythonapi.PyThreadState_SetAsyncExc(tid, ctypes.py_object(exctype))
+ if res == 0:
+ raise ValueError("invalid thread id")
+ elif res != 1:
+ # """if it returns a number greater than one, you're in trouble,
+ # and you should call it again with exc=NULL to revert the effect"""
+ ctypes.pythonapi.PyThreadState_SetAsyncExc(tid, 0)
+ raise SystemError("PyThreadState_SetAsyncExc failed")
+
+
+class ThreadEx(threading.Thread):
+ def _get_my_tid(self):
+ """determines this (self's) thread id"""
+ if not self.isAlive():
+ raise threading.ThreadError("the thread is not active")
+
+ # do we have it cached?
+ if hasattr(self, "_thread_id"):
+ return self._thread_id
+
+ # no, look for it in the _active dict
+ for tid, tobj in threading._active.items():
+ if tobj is self:
+ self._thread_id = tid
+ return tid
+
+ raise AssertionError("could not determine the thread's id")
+
+ def raise_exc(self, exctype):
+ """raises the given exception type in the context of this thread"""
+ _async_raise(self._get_my_tid(), exctype)
+
+ def kill(self):
+ """raises SystemExit in the context of the given thread, which should
+ cause the thread to exit silently (unless caught)"""
+ self.raise_exc(SystemExit)
diff --git a/IPython/gui/wx/wxIPython.py b/IPython/gui/wx/wxIPython.py
old mode 100644
new mode 100755
index 18d0fd7..972acfa
--- a/IPython/gui/wx/wxIPython.py
+++ b/IPython/gui/wx/wxIPython.py
@@ -2,11 +2,13 @@
# -*- coding: iso-8859-15 -*-
import wx.aui
-import wx.py
+
+#used for about dialog
from wx.lib.wordwrap import wordwrap
-from ipython_view import *
-from ipython_history import *
+#used for ipython GUI objects
+from IPython.gui.wx.ipython_view import IPShellWidget
+from IPython.gui.wx.ipython_history import IPythonHistoryPanel
__version__ = 0.8
__author__ = "Laurent Dufrechou"
@@ -20,7 +22,8 @@ __license__ = "BSD"
class MyFrame(wx.Frame):
"""Creating one main frame for our
application with movables windows"""
- def __init__(self, parent=None, id=-1, title="WxIPython", pos=wx.DefaultPosition,
+ def __init__(self, parent=None, id=-1, title="WxIPython",
+ pos=wx.DefaultPosition,
size=(800, 600), style=wx.DEFAULT_FRAME_STYLE):
wx.Frame.__init__(self, parent, id, title, pos, size, style)
self._mgr = wx.aui.AuiManager()
@@ -30,15 +33,18 @@ class MyFrame(wx.Frame):
#create differents panels and make them persistant
self.history_panel = IPythonHistoryPanel(self)
+
+ self.history_panel.setOptionTrackerHook(self.optionSave)
- self.ipython_panel = WxIPythonViewPanel(self,self.OnExitDlg,
- background_color = "BLACK")
-
- #self.ipython_panel = WxIPythonViewPanel(self,self.OnExitDlg,
- # background_color = "WHITE")
-
+ self.ipython_panel = IPShellWidget(self,background_color = "BLACK")
+ #self.ipython_panel = IPShellWidget(self,background_color = "WHITE")
+
self.ipython_panel.setHistoryTrackerHook(self.history_panel.write)
self.ipython_panel.setStatusTrackerHook(self.updateStatus)
+ self.ipython_panel.setAskExitHandler(self.OnExitDlg)
+ self.ipython_panel.setOptionTrackerHook(self.optionSave)
+
+ self.optionLoad()
self.statusbar = self.createStatus()
self.createMenu()
@@ -48,13 +54,11 @@ class MyFrame(wx.Frame):
# main panels
self._mgr.AddPane(self.ipython_panel , wx.CENTER, "IPython Shell")
self._mgr.AddPane(self.history_panel , wx.RIGHT, "IPython history")
-
+
# now we specify some panel characteristics
self._mgr.GetPane(self.ipython_panel).CaptionVisible(True);
self._mgr.GetPane(self.history_panel).CaptionVisible(True);
self._mgr.GetPane(self.history_panel).MinSize((200,400));
-
-
# tell the manager to "commit" all the changes just made
self._mgr.Update()
@@ -66,7 +70,7 @@ class MyFrame(wx.Frame):
self.Bind(wx.EVT_MENU, self.OnShowHistoryPanel,id=wx.ID_HIGHEST+2)
self.Bind(wx.EVT_MENU, self.OnShowAbout, id=wx.ID_HIGHEST+3)
self.Bind(wx.EVT_MENU, self.OnShowAllPanel,id=wx.ID_HIGHEST+6)
-
+
warn_text = 'Hello from IPython and wxPython.\n'
warn_text +='Please Note that this work is still EXPERIMENTAL\n'
warn_text +='It does NOT emulate currently all the IPython functions.\n'
@@ -78,7 +82,41 @@ class MyFrame(wx.Frame):
)
dlg.ShowModal()
dlg.Destroy()
-
+
+ def optionSave(self, name, value):
+ opt = open('options.conf','w')
+
+ try:
+ options_ipython_panel = self.ipython_panel.getOptions()
+ options_history_panel = self.history_panel.getOptions()
+
+ for key in options_ipython_panel.keys():
+ opt.write(key + '=' + options_ipython_panel[key]['value']+'\n')
+ for key in options_history_panel.keys():
+ opt.write(key + '=' + options_history_panel[key]['value']+'\n')
+ finally:
+ opt.close()
+
+ def optionLoad(self):
+ opt = open('options.conf','r')
+ lines = opt.readlines()
+ opt.close()
+
+ options_ipython_panel = self.ipython_panel.getOptions()
+ options_history_panel = self.history_panel.getOptions()
+
+ for line in lines:
+ key = line.split('=')[0]
+ value = line.split('=')[1].replace('\n','').replace('\r','')
+ if key in options_ipython_panel.keys():
+ options_ipython_panel[key]['value'] = value
+ elif key in options_history_panel.keys():
+ options_history_panel[key]['value'] = value
+ else:
+ print >>sys.__stdout__,"Warning: key ",key,"not found in widget options. Check Options.conf"
+ self.ipython_panel.reloadOptions(options_ipython_panel)
+ self.history_panel.reloadOptions(options_history_panel)
+
def createMenu(self):
"""local method used to create one menu bar"""
@@ -121,6 +159,7 @@ class MyFrame(wx.Frame):
states = {'IDLE':'Idle',
'DO_EXECUTE_LINE':'Send command',
'WAIT_END_OF_EXECUTION':'Running command',
+ 'WAITING_USER_INPUT':'Waiting user input',
'SHOW_DOC':'Showing doc',
'SHOW_PROMPT':'Showing prompt'}
self.statusbar.SetStatusText(states[text], 0)
diff --git a/IPython/hooks.py b/IPython/hooks.py
index 67e79d4..777f308 100644
--- a/IPython/hooks.py
+++ b/IPython/hooks.py
@@ -56,7 +56,7 @@ from pprint import PrettyPrinter
__all__ = ['editor', 'fix_error_editor', 'result_display',
'input_prefilter', 'shutdown_hook', 'late_startup_hook',
'generate_prompt', 'generate_output_prompt','shell_hook',
- 'show_in_pager']
+ 'show_in_pager','pre_prompt_hook', 'pre_runcode_hook']
pformat = PrettyPrinter().pformat
@@ -227,11 +227,17 @@ def show_in_pager(self,s):
# raising TryNext here will use the default paging functionality
raise ipapi.TryNext
-def pre_command_hook(self,cmd):
- """" Executed before starting to execute a command """
+def pre_prompt_hook(self):
+ """ Run before displaying the next prompt
+
+ Use this e.g. to display output from asynchronous operations (in order
+ to not mess up text entry)
+ """
+
return None
-def post_command_hook(self,cmd):
- """ Executed after executing a command """
+def pre_runcode_hook(self):
+ """ Executed before running the (prefiltered) code in IPython """
+ return None
diff --git a/IPython/ipapi.py b/IPython/ipapi.py
index 57c8960..de23da0 100644
--- a/IPython/ipapi.py
+++ b/IPython/ipapi.py
@@ -273,15 +273,27 @@ class IPApi:
"""
res = []
lines = script.splitlines()
+
level = 0
for l in lines:
- stripped = l.lstrip()
- if not l.strip():
+ lstripped = l.lstrip()
+ stripped = l.strip()
+ if not stripped:
continue
- newlevel = len(l) - len(stripped)
- if level > 0 and newlevel == 0:
+ newlevel = len(l) - len(lstripped)
+ def is_secondary_block_start(s):
+ if not s.endswith(':'):
+ return False
+ if (s.startswith('elif') or
+ s.startswith('else') or
+ s.startswith('except') or
+ s.startswith('finally')):
+ return True
+
+ if level > 0 and newlevel == 0 and not is_secondary_block_start(stripped):
# add empty line
res.append('')
+
res.append(l)
level = newlevel
return '\n'.join(res) + '\n'
@@ -291,7 +303,7 @@ class IPApi:
else:
script = '\n'.join(lines)
clean=cleanup_ipy_script(script)
-
+ # print "_ip.runlines() script:\n",clean #dbg
self.IP.runlines(clean)
def to_user_ns(self,vars, interactive = True):
"""Inject a group of variables into the IPython user namespace.
@@ -533,7 +545,7 @@ class DebugTools:
if name in self.hotnames:
self.debug_stack( "HotName '%s' caught" % name)
-def launch_new_instance(user_ns = None):
+def launch_new_instance(user_ns = None,shellclass = None):
""" Make and start a new ipython instance.
This can be called even without having an already initialized
@@ -542,7 +554,7 @@ def launch_new_instance(user_ns = None):
This is also used as the egg entry point for the 'ipython' script.
"""
- ses = make_session(user_ns)
+ ses = make_session(user_ns,shellclass)
ses.mainloop()
@@ -578,7 +590,7 @@ def make_user_global_ns(ns = None):
return ns
-def make_session(user_ns = None):
+def make_session(user_ns = None, shellclass = None):
"""Makes, but does not launch an IPython session.
Later on you can call obj.mainloop() on the returned object.
@@ -591,6 +603,6 @@ def make_session(user_ns = None):
WARNING: This should *not* be run when a session exists already."""
import IPython.Shell
- return IPython.Shell.start(user_ns)
-
-
+ if shellclass is None:
+ return IPython.Shell.start(user_ns)
+ return shellclass(user_ns = user_ns)
diff --git a/IPython/iplib.py b/IPython/iplib.py
index ed051bc..4355beb 100644
--- a/IPython/iplib.py
+++ b/IPython/iplib.py
@@ -6,7 +6,6 @@ Requires Python 2.3 or newer.
This file contains all the classes and helper functions specific to IPython.
-$Id: iplib.py 3005 2008-02-01 16:43:34Z vivainio $
"""
#*****************************************************************************
@@ -55,6 +54,8 @@ import sys
import tempfile
import traceback
import types
+import warnings
+warnings.filterwarnings('ignore', r'.*sets module*')
from sets import Set
from pprint import pprint, pformat
@@ -377,7 +378,10 @@ class InteractiveShell(object,Magic):
# Get system encoding at startup time. Certain terminals (like Emacs
# under Win32 have it set to None, and we need to have a known valid
# encoding to use in the raw_input() method
- self.stdin_encoding = sys.stdin.encoding or 'ascii'
+ try:
+ self.stdin_encoding = sys.stdin.encoding or 'ascii'
+ except AttributeError:
+ self.stdin_encoding = 'ascii'
# dict of things NOT to alias (keywords, builtins and some magics)
no_alias = {}
@@ -698,7 +702,10 @@ class InteractiveShell(object,Magic):
# Do a proper resetting of doctest, including the necessary displayhook
# monkeypatching
- doctest_reload()
+ try:
+ doctest_reload()
+ except ImportError:
+ warn("doctest module does not exist.")
# Set user colors (don't do it in the constructor above so that it
# doesn't crash if colors option is invalid)
@@ -1266,8 +1273,12 @@ want to merge them back into the new files.""" % locals()
"""Reload the input history from disk file."""
if self.has_readline:
- self.readline.clear_history()
- self.readline.read_history_file(self.shell.histfile)
+ try:
+ self.readline.clear_history()
+ self.readline.read_history_file(self.shell.histfile)
+ except AttributeError:
+ pass
+
def history_saving_wrapper(self, func):
""" Wrap func for readline history saving
@@ -1744,6 +1755,7 @@ want to merge them back into the new files.""" % locals()
# exit_now is set by a call to %Exit or %Quit
while not self.exit_now:
+ self.hooks.pre_prompt_hook()
if more:
try:
prompt = self.hooks.generate_prompt(True)
@@ -2009,7 +2021,7 @@ want to merge them back into the new files.""" % locals()
try:
code = self.compile(source,filename,symbol)
- except (OverflowError, SyntaxError, ValueError):
+ except (OverflowError, SyntaxError, ValueError, TypeError):
# Case 1
self.showsyntaxerror(filename)
return None
@@ -2053,6 +2065,7 @@ want to merge them back into the new files.""" % locals()
outflag = 1 # happens in more places, so it's easier as default
try:
try:
+ self.hooks.pre_runcode_hook()
# Embedded instances require separate global/local namespaces
# so they can see both the surrounding (local) namespace and
# the module-level globals when called inside another function.
diff --git a/IPython/ipmaker.py b/IPython/ipmaker.py
index d281077..8652c50 100644
--- a/IPython/ipmaker.py
+++ b/IPython/ipmaker.py
@@ -58,6 +58,14 @@ from IPython.iplib import InteractiveShell
from IPython.usage import cmd_line_usage,interactive_usage
from IPython.genutils import *
+def force_import(modname):
+ if modname in sys.modules:
+ print "reload",modname
+ reload(sys.modules[modname])
+ else:
+ __import__(modname)
+
+
#-----------------------------------------------------------------------------
def make_IPython(argv=None,user_ns=None,user_global_ns=None,debug=1,
rc_override=None,shell_class=InteractiveShell,
@@ -95,9 +103,12 @@ def make_IPython(argv=None,user_ns=None,user_global_ns=None,debug=1,
embedded=embedded,**kw)
# Put 'help' in the user namespace
- from site import _Helper
+ try:
+ from site import _Helper
+ IP.user_ns['help'] = _Helper()
+ except ImportError:
+ warn('help() not available - check site.py')
IP.user_config_ns = {}
- IP.user_ns['help'] = _Helper()
if DEVDEBUG:
@@ -176,10 +187,10 @@ object? -> Details about 'object'. ?object also works, ?? prints more.
# Options that can *only* appear at the cmd line (not in rcfiles).
- # The "ignore" option is a kludge so that Emacs buffers don't crash, since
- # the 'C-c !' command in emacs automatically appends a -i option at the end.
cmdline_only = ('help interact|i ipythondir=s Version upgrade '
- 'gthread! qthread! q4thread! wthread! tkthread! pylab! tk!')
+ 'gthread! qthread! q4thread! wthread! tkthread! pylab! tk! '
+ # 'twisted!' # disabled for now.
+ )
# Build the actual name list to be used by DPyGetOpt
opts_names = qw(cmdline_opts) + qw(cmdline_only)
@@ -203,7 +214,7 @@ object? -> Details about 'object'. ?object also works, ?? prints more.
editor = '0',
gthread = 0,
help = 0,
- interact = 1,
+ interact = 0,
ipythondir = ipythondir_def,
log = 0,
logfile = '',
@@ -237,6 +248,7 @@ object? -> Details about 'object'. ?object also works, ?? prints more.
system_verbose = 0,
term_title = 1,
tk = 0,
+ #twisted= 0, # disabled for now
upgrade = 0,
Version = 0,
wildcards_case_sensitive = 1,
@@ -633,15 +645,17 @@ object? -> Details about 'object'. ?object also works, ?? prints more.
if opts_all.profile and not profile_handled_by_legacy:
profmodname = 'ipy_profile_' + opts_all.profile
try:
- __import__(profmodname)
+
+ force_import(profmodname)
except:
IP.InteractiveTB()
print "Error importing",profmodname,"- perhaps you should run %upgrade?"
import_fail_info(profmodname)
else:
- import ipy_profile_none
- try:
- import ipy_user_conf
+ force_import('ipy_profile_none')
+ try:
+
+ force_import('ipy_user_conf')
except:
conf = opts_all.ipythondir + "/ipy_user_conf.py"
diff --git a/IPython/platutils_posix.py b/IPython/platutils_posix.py
index ef80ad6..fa46ce8 100644
--- a/IPython/platutils_posix.py
+++ b/IPython/platutils_posix.py
@@ -23,12 +23,17 @@ __license__ = Release.license
import sys
import os
+ignore_termtitle = False
def _dummy_op(*a, **b):
""" A no-op function """
def _set_term_title_xterm(title):
""" Change virtual terminal title in xterm-workalikes """
+
+ if ignore_termtitle:
+ return
+
sys.stdout.write('\033]%d;%s\007' % (0,title))
@@ -37,4 +42,6 @@ if os.environ.get('TERM','') == 'xterm':
else:
set_term_title = _dummy_op
-
+def freeze_term_title():
+ global ignore_termtitle
+ ignore_termtitle = True
diff --git a/IPython/platutils_win32.py b/IPython/platutils_win32.py
index 364afbc..76e5333 100644
--- a/IPython/platutils_win32.py
+++ b/IPython/platutils_win32.py
@@ -50,4 +50,7 @@ def set_term_title(title):
return
_set_term_title(title)
+def freeze_term_title():
+ global ignore_termtitle
+ ignore_termtitle = 1
diff --git a/IPython/shellglobals.py b/IPython/shellglobals.py
new file mode 100644
index 0000000..48994bf
--- /dev/null
+++ b/IPython/shellglobals.py
@@ -0,0 +1,96 @@
+from IPython.genutils import Term,warn,error,flag_calls, ask_yes_no
+
+import thread,inspect
+
+try:
+ import ctypes
+ HAS_CTYPES = True
+except ImportError:
+ HAS_CTYPES = False
+
+
+# Globals
+# global flag to pass around information about Ctrl-C without exceptions
+KBINT = False
+
+# global flag to turn on/off Tk support.
+USE_TK = False
+
+# ID for the main thread, used for cross-thread exceptions
+MAIN_THREAD_ID = thread.get_ident()
+
+# Tag when runcode() is active, for exception handling
+CODE_RUN = None
+
+
+#-----------------------------------------------------------------------------
+# This class is trivial now, but I want to have it in to publish a clean
+# interface. Later when the internals are reorganized, code that uses this
+# shouldn't have to change.
+
+
+if HAS_CTYPES:
+ # Add async exception support. Trick taken from:
+ # http://sebulba.wikispaces.com/recipe+thread2
+ def _async_raise(tid, exctype):
+ """raises the exception, performs cleanup if needed"""
+ if not inspect.isclass(exctype):
+ raise TypeError("Only types can be raised (not instances)")
+ res = ctypes.pythonapi.PyThreadState_SetAsyncExc(tid,
+ ctypes.py_object(exctype))
+ if res == 0:
+ raise ValueError("invalid thread id")
+ elif res != 1:
+ # """if it returns a number greater than one, you're in trouble,
+ # and you should call it again with exc=NULL to revert the effect"""
+ ctypes.pythonapi.PyThreadState_SetAsyncExc(tid, 0)
+ raise SystemError("PyThreadState_SetAsyncExc failed")
+
+ def sigint_handler (signum,stack_frame):
+ """Sigint handler for threaded apps.
+
+ This is a horrible hack to pass information about SIGINT _without_
+ using exceptions, since I haven't been able to properly manage
+ cross-thread exceptions in GTK/WX. In fact, I don't think it can be
+ done (or at least that's my understanding from a c.l.py thread where
+ this was discussed)."""
+
+ global KBINT
+
+ if CODE_RUN:
+ _async_raise(MAIN_THREAD_ID,KeyboardInterrupt)
+ else:
+ KBINT = True
+ print '\nKeyboardInterrupt - Press to continue.',
+ Term.cout.flush()
+
+else:
+ def sigint_handler (signum,stack_frame):
+ """Sigint handler for threaded apps.
+
+ This is a horrible hack to pass information about SIGINT _without_
+ using exceptions, since I haven't been able to properly manage
+ cross-thread exceptions in GTK/WX. In fact, I don't think it can be
+ done (or at least that's my understanding from a c.l.py thread where
+ this was discussed)."""
+
+ global KBINT
+
+ print '\nKeyboardInterrupt - Press to continue.',
+ Term.cout.flush()
+ # Set global flag so that runsource can know that Ctrl-C was hit
+ KBINT = True
+
+def run_in_frontend(src):
+ """ Check if source snippet can be run in the REPL thread, as opposed to GUI mainloop
+
+ (to prevent unnecessary hanging of mainloop).
+
+ """
+
+ if src.startswith('_ip.system(') and not '\n' in src:
+ return True
+ return False
+
+
+
diff --git a/IPython/twshell.py b/IPython/twshell.py
new file mode 100644
index 0000000..c14c15a
--- /dev/null
+++ b/IPython/twshell.py
@@ -0,0 +1,278 @@
+import sys
+
+from twisted.internet import reactor, threads
+
+from IPython.ipmaker import make_IPython
+from IPython.iplib import InteractiveShell
+from IPython.ipstruct import Struct
+import Queue,thread,threading,signal
+from signal import signal, SIGINT
+from IPython.genutils import Term,warn,error,flag_calls, ask_yes_no
+import shellglobals
+
+def install_gtk2():
+ """ Install gtk2 reactor, needs to be called bef """
+ from twisted.internet import gtk2reactor
+ gtk2reactor.install()
+
+
+def hijack_reactor():
+ """Modifies Twisted's reactor with a dummy so user code does
+ not block IPython. This function returns the original
+ 'twisted.internet.reactor' that has been hijacked.
+
+ NOTE: Make sure you call this *AFTER* you've installed
+ the reactor of your choice.
+ """
+ from twisted import internet
+ orig_reactor = internet.reactor
+
+ class DummyReactor(object):
+ def run(self):
+ pass
+ def __getattr__(self, name):
+ return getattr(orig_reactor, name)
+ def __setattr__(self, name, value):
+ return setattr(orig_reactor, name, value)
+
+ internet.reactor = DummyReactor()
+ return orig_reactor
+
+class TwistedInteractiveShell(InteractiveShell):
+ """Simple multi-threaded shell."""
+
+ # Threading strategy taken from:
+ # http://aspn.activestate.com/ASPN/Cookbook/Python/Recipe/65109, by Brian
+ # McErlean and John Finlay. Modified with corrections by Antoon Pardon,
+ # from the pygtk mailing list, to avoid lockups with system calls.
+
+ # class attribute to indicate whether the class supports threads or not.
+ # Subclasses with thread support should override this as needed.
+ isthreaded = True
+
+ def __init__(self,name,usage=None,rc=Struct(opts=None,args=None),
+ user_ns=None,user_global_ns=None,banner2='',**kw):
+ """Similar to the normal InteractiveShell, but with threading control"""
+
+ InteractiveShell.__init__(self,name,usage,rc,user_ns,
+ user_global_ns,banner2)
+
+
+ # A queue to hold the code to be executed.
+ self.code_queue = Queue.Queue()
+
+ # Stuff to do at closing time
+ self._kill = None
+ on_kill = kw.get('on_kill', [])
+ # Check that all things to kill are callable:
+ for t in on_kill:
+ if not callable(t):
+ raise TypeError,'on_kill must be a list of callables'
+ self.on_kill = on_kill
+ # thread identity of the "worker thread" (that may execute code directly)
+ self.worker_ident = None
+ self.reactor_started = False
+ self.first_run = True
+
+ def runsource(self, source, filename="", symbol="single"):
+ """Compile and run some source in the interpreter.
+
+ Modified version of code.py's runsource(), to handle threading issues.
+ See the original for full docstring details."""
+
+ # If Ctrl-C was typed, we reset the flag and return right away
+ if shellglobals.KBINT:
+ shellglobals.KBINT = False
+ return False
+
+ if self._kill:
+ # can't queue new code if we are being killed
+ return True
+
+ try:
+ code = self.compile(source, filename, symbol)
+ except (OverflowError, SyntaxError, ValueError):
+ # Case 1
+ self.showsyntaxerror(filename)
+ return False
+
+ if code is None:
+ # Case 2
+ return True
+
+ # shortcut - if we are in worker thread, or the worker thread is not running,
+ # execute directly (to allow recursion and prevent deadlock if code is run early
+ # in IPython construction)
+
+ if (not self.reactor_started or (self.worker_ident is None and not self.first_run)
+ or self.worker_ident == thread.get_ident() or shellglobals.run_in_frontend(source)):
+ InteractiveShell.runcode(self,code)
+ return
+
+ # Case 3
+ # Store code in queue, so the execution thread can handle it.
+
+ self.first_run = False
+ completed_ev, received_ev = threading.Event(), threading.Event()
+
+ self.code_queue.put((code,completed_ev, received_ev))
+
+ reactor.callLater(0.0,self.runcode)
+ received_ev.wait(5)
+ if not received_ev.isSet():
+ # the mainloop is dead, start executing code directly
+ print "Warning: Timeout for mainloop thread exceeded"
+ print "switching to nonthreaded mode (until mainloop wakes up again)"
+ self.worker_ident = None
+ else:
+ completed_ev.wait()
+
+ return False
+
+ def runcode(self):
+ """Execute a code object.
+
+ Multithreaded wrapper around IPython's runcode()."""
+
+
+ # we are in worker thread, stash out the id for runsource()
+ self.worker_ident = thread.get_ident()
+
+ if self._kill:
+ print >>Term.cout, 'Closing threads...',
+ Term.cout.flush()
+ for tokill in self.on_kill:
+ tokill()
+ print >>Term.cout, 'Done.'
+ # allow kill() to return
+ self._kill.set()
+ return True
+
+ # Install SIGINT handler. We do it every time to ensure that if user
+ # code modifies it, we restore our own handling.
+ try:
+ pass
+ signal(SIGINT,shellglobals.sigint_handler)
+ except SystemError:
+ # This happens under Windows, which seems to have all sorts
+ # of problems with signal handling. Oh well...
+ pass
+
+ # Flush queue of pending code by calling the run methood of the parent
+ # class with all items which may be in the queue.
+ code_to_run = None
+ while 1:
+ try:
+ code_to_run, completed_ev, received_ev = self.code_queue.get_nowait()
+ except Queue.Empty:
+ break
+ received_ev.set()
+
+
+ # Exceptions need to be raised differently depending on which
+ # thread is active. This convoluted try/except is only there to
+ # protect against asynchronous exceptions, to ensure that a shellglobals.KBINT
+ # at the wrong time doesn't deadlock everything. The global
+ # CODE_TO_RUN is set to true/false as close as possible to the
+ # runcode() call, so that the KBINT handler is correctly informed.
+ try:
+ try:
+ shellglobals.CODE_RUN = True
+ InteractiveShell.runcode(self,code_to_run)
+ except KeyboardInterrupt:
+ print "Keyboard interrupted in mainloop"
+ while not self.code_queue.empty():
+ code = self.code_queue.get_nowait()
+ break
+ finally:
+ shellglobals.CODE_RUN = False
+ # allow runsource() return from wait
+ completed_ev.set()
+
+ # This MUST return true for gtk threading to work
+ return True
+
+ def kill(self):
+ """Kill the thread, returning when it has been shut down."""
+ self._kill = threading.Event()
+ reactor.callLater(0.0,self.runcode)
+ self._kill.wait()
+
+
+
+class IPShellTwisted:
+ """Run a Twisted reactor while in an IPython session.
+
+ Python commands can be passed to the thread where they will be
+ executed. This is implemented by periodically checking for
+ passed code using a Twisted reactor callback.
+ """
+
+ TIMEOUT = 0.01 # Millisecond interval between reactor runs.
+
+ def __init__(self, argv=None, user_ns=None, debug=1,
+ shell_class=TwistedInteractiveShell):
+
+ from twisted.internet import reactor
+ self.reactor = hijack_reactor()
+
+ mainquit = self.reactor.stop
+
+ # Make sure IPython keeps going after reactor stop.
+ def reactorstop():
+ pass
+ self.reactor.stop = reactorstop
+ reactorrun_orig = self.reactor.run
+ self.quitting = False
+ def reactorrun():
+ while True and not self.quitting:
+ reactorrun_orig()
+ self.reactor.run = reactorrun
+
+ self.IP = make_IPython(argv, user_ns=user_ns, debug=debug,
+ shell_class=shell_class,
+ on_kill=[mainquit])
+
+ # threading.Thread.__init__(self)
+
+ def run(self):
+ self.IP.mainloop()
+ self.quitting = True
+ self.IP.kill()
+
+ def mainloop(self):
+ def mainLoopThreadDeath(r):
+ print "mainLoopThreadDeath: ", str(r)
+ def spawnMainloopThread():
+ d=threads.deferToThread(self.run)
+ d.addBoth(mainLoopThreadDeath)
+ reactor.callWhenRunning(spawnMainloopThread)
+ self.IP.reactor_started = True
+ self.reactor.run()
+ print "mainloop ending...."
+
+exists = True
+
+
+if __name__ == '__main__':
+ # Sample usage.
+
+ # Create the shell object. This steals twisted.internet.reactor
+ # for its own purposes, to make sure you've already installed a
+ # reactor of your choice.
+ shell = IPShellTwisted(
+ argv=[],
+ user_ns={'__name__': '__example__',
+ 'hello': 'world',
+ },
+ )
+
+ # Run the mainloop. This runs the actual reactor.run() method.
+ # The twisted.internet.reactor object at this point is a dummy
+ # object that passes through to the actual reactor, but prevents
+ # run() from being called on it again.
+ shell.mainloop()
+
+ # You must exit IPython to terminate your program.
+ print 'Goodbye!'
+
diff --git a/IPython/ultraTB.py b/IPython/ultraTB.py
index bccdcac..eb2e579 100644
--- a/IPython/ultraTB.py
+++ b/IPython/ultraTB.py
@@ -377,8 +377,8 @@ class ListTB(TBTools):
def __call__(self, etype, value, elist):
Term.cout.flush()
- Term.cerr.flush()
print >> Term.cerr, self.text(etype,value,elist)
+ Term.cerr.flush()
def text(self,etype, value, elist,context=5):
"""Return a color formatted string with the traceback info."""
@@ -855,8 +855,8 @@ class VerboseTB(TBTools):
(etype, evalue, etb) = info or sys.exc_info()
self.tb = etb
Term.cout.flush()
- Term.cerr.flush()
print >> Term.cerr, self.text(etype, evalue, etb)
+ Term.cerr.flush()
# Changed so an instance can just be called as VerboseTB_inst() and print
# out the right info on its own.
@@ -977,13 +977,13 @@ class AutoFormattedTB(FormattedTB):
if out is None:
out = Term.cerr
Term.cout.flush()
- out.flush()
if tb_offset is not None:
tb_offset, self.tb_offset = self.tb_offset, tb_offset
print >> out, self.text(etype, evalue, etb)
self.tb_offset = tb_offset
else:
print >> out, self.text(etype, evalue, etb)
+ out.flush()
try:
self.debugger()
except KeyboardInterrupt:
diff --git a/MANIFEST.in b/MANIFEST.in
index 4e3de84..4ff6ecb 100644
--- a/MANIFEST.in
+++ b/MANIFEST.in
@@ -9,22 +9,23 @@ graft setupext
graft IPython/UserConfig
graft doc
+exclude doc/\#*
exclude doc/*.1
-exclude doc/manual_base*
exclude doc/ChangeLog.*
-exclude doc/\#*
-exclude doc/update_magic.sh
exclude doc/update_version.sh
-exclude doc/manual_base*
-exclude doc/manual/WARNINGS
-exclude doc/manual/*.aux
-exclude doc/manual/*.log
-exclude doc/manual/*.out
-exclude doc/manual/*.pl
-exclude doc/manual/*.tex
+
+# There seems to be no way of excluding whole subdirectories, other than
+# manually excluding all their subdirs. distutils really is horrible...
+exclude doc/attic/*
+exclude doc/build/doctrees/*
+exclude doc/build/html/_sources/*
+exclude doc/build/html/_static/*
+exclude doc/build/html/*
+exclude doc/build/latex/*
global-exclude *~
global-exclude *.flc
global-exclude *.pyc
global-exclude .dircopy.log
global-exclude .svn
+global-exclude .bzr
diff --git a/debian/changelog b/debian/changelog
index a5d262d..4cc4527 100644
--- a/debian/changelog
+++ b/debian/changelog
@@ -1,8 +1,330 @@
+ipython (0.8.1-2) unstable; urgency=low
+
+ [ Piotr Ożarowski ]
+ * Homepage field added
+ * Rename XS-Vcs-* fields to Vcs-* (dpkg supports them now)
+ * Add 04_remove_shebang patch
+ * Removing lintian overrides, adding proper patches instead.
+
+ [ Bernd Zeimetz ]
+ * Replacing Recommends by Suggests to stop ipython from installing ~500MB
+ of dependencies. Thanks to Marcela Tiznado (Closes: #451887).
+
+ -- Bernd Zeimetz Mon, 19 Nov 2007 19:10:14 +0100
+
+ipython (0.8.1-1) unstable; urgency=low
+
+ [ Bernd Zeimetz ]
+ * debian/control:
+ - adding python-matplotlib to Recommends because
+ it is needed to run ipython -pylab
+
+ [ Norbert Tretkowski ]
+ * New upstream release. (closes: #428398)
+
+ [ Reinhard Tartler ]
+ * Install ipython.el properly.
+
+ -- Norbert Tretkowski Mon, 11 Jun 2007 20:05:30 +0200
+
+ipython (0.8.0-2) unstable; urgency=low
+
+ * debian/changelog:
+ - adding missing colons to Closes entries to fix two
+ lintian warnings
+ * debian/compat:
+ - bumping compat level to 5
+ * debian/control:
+ - adding XS-Vcs-Browser
+ - remove no longer needed X*-Python-Version fields
+ - moving python-pexpect from Recommends to Depends because
+ /usr/bin/irunner is not useable without it
+ - moving debhelper and dpatch from Build-Depends-Indep to
+ Build-Depends, fixing the following lintian errors:
+ - clean-should-be-satisfied-by-build-depends debhelper
+ - clean-should-be-satisfied-by-build-depends dpatch
+ - removing unnecessary Build-Depends-Indep on python-all-dev,
+ adding python to Build-Depends instead
+ - replacing python-central by python-support to be able to
+ fix #420134 without hassle
+ - adding ${misc:Depends}
+ - adding the missing identation for Homepage:
+ - adding cdbs as Build-Depends
+ - adding myself to Uploaders
+ - removing the short description from the long description
+ * debian/patches/03_ipy_gnuglobal.dpatch:
+ - fix the location of the global binary - we're not on windows
+ * debian/rules:
+ - removing old crust, using cdbs to make things clear again
+ - using python-support instead of python-central to make
+ modules for 2.5 avaiable now. (Closes: #420134)
+ - making sure the bogus /usr/IPython directory is not
+ included in the package again
+ - do not remove docs/ipython.el (Closes: #198505, #415427)
+ * adding lintian ovverrides for several scripts included in the
+ IPython/Extensions directory.
+ * adding a manpage for /usr/bin/irunner
+
+ -- Bernd Zeimetz Tue, 24 Apr 2007 02:47:26 +0200
+
+ipython (0.8.0-1) unstable; urgency=low
+
+ * New upstream release. (closes: #419716)
+ * Removed patches merged upstream.
+
+ -- Norbert Tretkowski Tue, 17 Apr 2007 20:26:43 +0200
+
+ipython (0.7.3-2) unstable; urgency=low
+
+ * Added a new patch from svn to fix jobctrl to work properly on posix.
+
+ -- Norbert Tretkowski Thu, 21 Dec 2006 20:13:57 +0100
+
+ipython (0.7.3-1) unstable; urgency=low
+
+ * New upstream release.
+
+ -- Norbert Tretkowski Mon, 18 Dec 2006 22:23:55 +0100
+
+ipython (0.7.3~rc2-1) experimental; urgency=low
+
+ * New upstream release candidate.
+
+ -- Norbert Tretkowski Sat, 16 Dec 2006 02:20:13 +0100
+
+ipython (0.7.3~beta2-1) experimental; urgency=low
+
+ * New upstream beta release.
+
+ -- Norbert Tretkowski Fri, 8 Dec 2006 08:02:16 +0100
+
+ipython (0.7.3~beta1-1) experimental; urgency=low
+
+ * New upstream beta release.
+ * Removed backported patch added in 0.7.2-5 to workaround bugs in python
+ 2.3's inspect module.
+
+ -- Norbert Tretkowski Wed, 29 Nov 2006 12:35:22 +0100
+
+ipython (0.7.2-6) UNRELEASED; urgency=low
+
+ * Added XS-Vcs-Svn field.
+
+ -- Piotr Ozarowski Thu, 23 Nov 2006 14:44:43 +0100
+
+ipython (0.7.2-5) unstable; urgency=low
+
+ * Added a new patch from svn to workaround bugs in python 2.3's inspect
+ module. (closes: #374625)
+
+ -- Norbert Tretkowski Thu, 10 Aug 2006 18:36:12 +0200
+
+ipython (0.7.2-4) unstable; urgency=low
+
+ * Fixed spelling error in description. (closes: #363976)
+ * Ack NMU 0.7.2-3.1, thanks Matthias. (closes: #377787)
+
+ -- Norbert Tretkowski Tue, 1 Aug 2006 22:45:11 +0200
+
+ipython (0.7.2-3.1) unstable; urgency=medium
+
+ * NMU.
+ * Convert to updated Python policy. (closes: #377787)
+
+ -- Matthias Klose Thu, 13 Jul 2006 17:42:06 +0000
+
+ipython (0.7.2-3ubuntu1) edgy; urgency=low
+
+ * Synchronize with Debian unstable.
+ * Convert to updated Python policy. Collapse all packages into one
+ ipython package, don't handle ipython using alternatives.
+
+ -- Matthias Klose Tue, 11 Jul 2006 09:47:37 +0000
+
+ipython (0.7.2-3) unstable; urgency=low
+
+ * Removed alternative for irunner manpage.
+
+ -- Norbert Tretkowski Sat, 17 Jun 2006 09:49:10 +0200
+
+ipython (0.7.2-2) unstable; urgency=medium
+
+ * Fixed conflict in irunner. (closes: #373874)
+ * Added recommendation for python-pexpect. (closes: #373794)
+
+ -- Norbert Tretkowski Fri, 16 Jun 2006 10:43:45 +0200
+
+ipython (0.7.2-1) unstable; urgency=low
+
+ [ Piotr Ozarowski ]
+ * Added watch file.
+
+ [ Norbert Tretkowski ]
+ * New upstream release.
+
+ -- Norbert Tretkowski Thu, 8 Jun 2006 23:36:03 +0200
+
+ipython (0.7.1.fix1+0.7.2.rc1-1) experimental; urgency=low
+
+ * New upstream release candidate.
+ * Updated Standards-Version to 3.7.2.0, no changes required.
+
+ -- Norbert Tretkowski Sat, 27 May 2006 14:49:24 +0200
+
+ipython (0.7.1.fix1-2) unstable; urgency=low
+
+ * Set maintainer to Debian Python modules team and added myself to
+ uploaders.
+
+ -- Norbert Tretkowski Sun, 16 Apr 2006 15:53:43 +0200
+
+ipython (0.7.1.fix1-1) unstable; urgency=low
+
+ * New upstream bugfix release.
+ * Removed backported patch which was added in 0.7.1-3 to catch
+ KeyboardInterrupt exceptions properly, it's part of this release.
+ * Fixed names of pdfs in doc-base file to shut up linda.
+
+ -- Norbert Tretkowski Tue, 14 Feb 2006 23:51:17 +0100
+
+ipython (0.7.1-3) unstable; urgency=low
+
+ * Added a new patch from upstream to catch KeyboardInterrupt exceptions
+ properly.
+
+ -- Norbert Tretkowski Mon, 30 Jan 2006 19:42:31 +0100
+
+ipython (0.7.1-2) unstable; urgency=low
+
+ * Really remove alternatives on purge, thanks Lars Wirzenius for finding
+ the problem. (closes: #317269)
+
+ -- Norbert Tretkowski Sun, 29 Jan 2006 23:11:28 +0100
+
+ipython (0.7.1-1) unstable; urgency=low
+
+ * New upstream release.
+
+ -- Norbert Tretkowski Tue, 24 Jan 2006 21:42:33 +0100
+
+ipython (0.7.0-2) unstable; urgency=low
+
+ * Fixed circular dependencies (closes: #341980)
+ * Added version to dependency on ipython dummy package. (closes: #320235)
+ * Removed python2.2 package, ipython now depends on python >= 2.3.
+ * Bumped up standards-version, no changes needed.
+
+ -- Norbert Tretkowski Sat, 21 Jan 2006 23:27:53 +0100
+
+ipython (0.7.0-1) unstable; urgency=low
+
+ * New upstream release.
+ * Updated 01_docdir-base.dpatch and 02_profiler-message.dpatch.
+
+ -- Norbert Tretkowski Sat, 21 Jan 2006 20:08:23 +0100
+
+ipython (0.6.15-2) unstable; urgency=low
+
+ * New maintainer, thanks Jack for your work.
+
+ -- Norbert Tretkowski Sun, 28 Aug 2005 19:57:09 +0200
+
+ipython (0.6.15-1) unstable; urgency=low
+
+ * New upstream release.
+
+ -- Norbert Tretkowski Thu, 2 Jun 2005 23:51:45 +0200
+
+ipython (0.6.14-1) unstable; urgency=low
+
+ * New upstream release.
+
+ -- Norbert Tretkowski Tue, 31 May 2005 22:53:25 +0200
+
+ipython (0.6.13-1) unstable; urgency=low
+
+ * New upstream release.
+ * Removed backported patch which was added in 0.6.12-3 to fix misleading
+ prompt, it's part of this release.
+
+ -- Norbert Tretkowski Fri, 15 Apr 2005 09:42:35 +0200
+
+ipython (0.6.12-4) unstable; urgency=medium
+
+ * Re-added python build-dependency, it got lost in 0.6.12-2.
+ (closes: #301636)
+
+ -- Norbert Tretkowski Sun, 27 Mar 2005 14:28:26 +0200
+
+ipython (0.6.12-3) unstable; urgency=low
+
+ * Added a new patch from cvs to fix misleading prompt2. (closes: #300847)
+
+ -- Norbert Tretkowski Sun, 27 Mar 2005 00:05:26 +0100
+
+ipython (0.6.12-2) unstable; urgency=low
+
+ * Added packages for python2.2 and python2.4, ipython package is now a dummy
+ package depending on ipython built for Debians default python.
+ (closes: #292537)
+ * Split out generic files into separate ipython-common package.
+ * Enhanced package descriptions.
+ * Removed CFLAGS settings from debian/rules, not required.
+ * Tweaked message displayed when profiler support is missing.
+ * Suggest the python-profiler package.
+
+ -- Norbert Tretkowski Fri, 25 Mar 2005 20:24:36 +0100
+
+ipython (0.6.12-1) unstable; urgency=low
+
+ * New upstream release.
+ * Removed patch which was added in 0.6.5-1.1 to make profiling support
+ optional, it was merged upstream.
+
+ -- Norbert Tretkowski Wed, 2 Mar 2005 12:15:09 +0100
+
+ipython (0.6.11-1) unstable; urgency=low
+
+ * New upstream release.
+ + Fixed broken profiling support unless -D is specified. (closes: #295779)
+ * Acknowledged NMUs. (closes: #206653, #294500, #294861, #280505)
+ * New co-maintainer, added myself to uploaders.
+
+ -- Norbert Tretkowski Tue, 1 Mar 2005 12:40:33 +0100
+
+ipython (0.6.5-1.2) unstable; urgency=low
+
+ * Non-maintainer upload.
+ * Rebuild with a python version that is actually in Debian.
+
+ -- Wichert Akkerman Thu, 17 Feb 2005 23:08:52 +0100
+
+ipython (0.6.5-1.1) unstable; urgency=low
+
+ * NMU to apply patch making profiling support optional (provided by
+ Torsten Marek). (closes: #294500)
+
+ -- Steven R. Baker Thu, 17 Feb 2005 05:02:55 -0400
+
+ipython (0.6.5-1) unstable; urgency=low
+
+ * New upstream release
+
+ -- Jack Moffitt Thu, 2 Dec 2004 15:49:27 -0700
+
+ipython (0.6.4-1.1) unstable; urgency=low
+
+ * NMU from BSP Frankfurt:
+ - Added Build-Depends on dpatch (Closes: #280505)
+
+ -- Joerg Jaspert Sat, 27 Nov 2004 18:28:17 +0100
+
ipython (0.6.4-1) unstable; urgency=low
- * Fix dpatch dependency (Closes: #280505)
+ * New upstream release
+ * Updated debian/rules to use dpatch and added debian/patches/*
- -- Fernando Perez Wed Nov 17 22:54:23 MST 2004
+ -- Jack Moffitt Tue, 9 Nov 2004 10:38:51 -0700
ipython (0.6.3-1) unstable; urgency=low
@@ -27,8 +349,8 @@ ipython (0.4.0-1.1) unstable; urgency=low
ipython (0.4.0-1) unstable; urgency=low
- * New upstream release (Closes #195215)
- * Updated Build-Depends (Closes #200021)
+ * New upstream release (Closes: #195215)
+ * Updated Build-Depends (Closes: #200021)
-- Jack Moffitt Fri, 25 Jul 2003 10:16:12 -0600
diff --git a/debian/compat b/debian/compat
index b8626c4..7ed6ff8 100644
--- a/debian/compat
+++ b/debian/compat
@@ -1 +1 @@
-4
+5
diff --git a/debian/control b/debian/control
index 86a2d96..cdb61a0 100644
--- a/debian/control
+++ b/debian/control
@@ -1,21 +1,26 @@
Source: ipython
-Section: devel
+Section: python
Priority: optional
-Maintainer: Jack Moffitt
-Build-Depends-Indep: debhelper (>> 4.1.65), dpatch, python-dev
-Standards-Version: 3.6.1
+Maintainer: Debian Python Modules Team
+Uploaders: Norbert Tretkowski , Bernd Zeimetz
+Build-Depends: debhelper (>= 5.0.37.2), dpatch (>= 2.0.10), cdbs (>= 0.4.43), python, python-support (>= 0.4)
+Homepage: http://ipython.scipy.org/
+Vcs-Svn: svn://svn.debian.org/python-modules/packages/ipython/trunk/
+Vcs-Browser: http://svn.debian.org/wsvn/python-modules/packages/ipython/trunk/
+Standards-Version: 3.7.2.2
Package: ipython
Architecture: all
-Depends: ${python:Depends}
-Recommends: python-numeric, python-numeric-ext
-Description: An enhanced interactive Python shell
- IPython is an enhanced interactive Python shell. It can be used as a
- replacement for the standard Python shell, or it can be used as a
- complete working environment for scientific computing (like Matlab or
- Mathematica) when paired with the standard Python scientific and
- numerical tools. It supports dynamic object introspections, numbered
- input/output prompts, a macro system, session logging, session
- restoring, complete system shell access, verbose and colored
- traceback reports, auto-parentheses, auto-quoting, and is
- embeddedable in other Python programs.
+Depends: ${python:Depends}, ${misc:Depends}, python-pexpect
+Conflicts: python2.3-ipython, python2.4-ipython, ipython-common
+Replaces: python2.3-ipython, python2.4-ipython, ipython-common
+Suggests: python-profiler, python-numeric, python-numeric-ext, python-matplotlib
+Description: enhanced interactive Python shell
+ IPython can be used as a replacement for the standard Python shell,
+ or it can be used as a complete working environment for scientific
+ computing (like Matlab or Mathematica) when paired with the standard
+ Python scientific and numerical tools. It supports dynamic object
+ introspections, numbered input/output prompts, a macro system,
+ session logging, session restoring, complete system shell access,
+ verbose and colored traceback reports, auto-parentheses, auto-quoting,
+ and is embeddable in other Python programs.
diff --git a/debian/copyright b/debian/copyright
index 01691e5..c4c326b 100644
--- a/debian/copyright
+++ b/debian/copyright
@@ -4,51 +4,15 @@ Wed, 12 Mar 2003 20:38:14 -0700.
It was downloaded from http://ipython.scipy.org/
Upstream Author: Fernando Perez ,
- Janko Hauser ,
+ Janko Hauser ,
Nathaniel Gray
Copyright:
-Most IPython code is copyright (C) 2001-2004 by Fernando Perez, Janko Hauser,
-and Nathaniel Gray. All code is licensed under a BSD-type License except as
-explicitly mentioned below. The full IPython license is:
-
-IPython is released under a BSD-type license.
-
-Copyright (c) 2001, 2002, 2003, 2004 Fernando Perez .
-
-Copyright (c) 2001 Janko Hauser and Nathaniel Gray
-.
-
-All rights reserved.
-
-Redistribution and use in source and binary forms, with or without
-modification, are permitted provided that the following conditions are met:
-
- a. Redistributions of source code must retain the above copyright notice,
- this list of conditions and the following disclaimer.
-
- b. Redistributions in binary form must reproduce the above copyright
- notice, this list of conditions and the following disclaimer in the
- documentation and/or other materials provided with the distribution.
-
- c. Neither the name of the copyright holders nor the names of any
- contributors to this software may be used to endorse or promote products
- derived from this software without specific prior written permission.
-
-
-THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
-AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
-IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
-ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR
-ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
-DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
-SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
-CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
-LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
-OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
-DAMAGE.
-
+Most IPython code is copyright (C) 2001 by Fernando Perez, Janko
+Hauser, and Nathaniel Gray. All code is licensed under the GNU Lesser
+General Public License (LGPL) except as explicitly mentioned below.
+Its full text is included in the file /usr/share/common-licenses/LGPL.
DPyGetOpt.py is copyright (C) 2001 by Bill Bumgarner
and is licensed under the MIT license, reproduced below:
diff --git a/debian/install b/debian/install
new file mode 100644
index 0000000..2f61d73
--- /dev/null
+++ b/debian/install
@@ -0,0 +1 @@
+doc/ipython.el usr/share/emacs/site-lisp
diff --git a/debian/irunner.1 b/debian/irunner.1
new file mode 100644
index 0000000..71c9c55
--- /dev/null
+++ b/debian/irunner.1
@@ -0,0 +1,52 @@
+.TH IRUNNER 1 "April 24, 2007" "" ""
+.SH NAME
+\fBirunner \- interactive runner interface
+.SH SYNOPSIS
+.nf
+.fam C
+\fBirunner\fP [\fIoptions\fP] \fIfile_to_run\fP
+.fam T
+.fi
+.SH DESCRIPTION
+irunner is an interface to the various interactive runners
+available in IPython's \fBirunner\fP module.
+.PP
+The already implemented runners are listed below; adding
+one for a new program is a trivial task, see the source
+for examples.
+.SH OPTIONS
+.TP
+.B
+\-h, \-\-help
+show this help message and exit
+.TP
+.B
+\-\-ipython
+IPython interactive runner (default).
+.TP
+.B
+\-\-python
+Python interactive runner.
+.TP
+.B
+\-\-sage
+SAGE interactive runner.
+.SH EXAMPLE
+irunner.py \-\-python \-\- \-\-help
+will pass \-\-help to the python runner.
+Similarly,
+irunner.py \-\-ipython \-\- \-\-interact script.ipy
+.SH SEE ALSO
+.BR ipython(1)
+.br
+.SH BUGS
+The SAGE runner only works if you manually configure your SAGE
+copy to use 'colors NoColor' in the ipythonrc config file, since
+currently the prompt matching regexp does not identify color sequences.
+.SH AUTHOR
+\fBirunner\fP is an extension of Ken Schutte 's
+script contributed on the ipython-user list:
+http://scipy.net/pipermail/ipython-user/2006-May/001705.html
+.PP
+This manual page was written by Bernd Zeimetz ,
+for the Debian project (but may be used by others).
diff --git a/debian/manpages b/debian/manpages
new file mode 100644
index 0000000..58da2e3
--- /dev/null
+++ b/debian/manpages
@@ -0,0 +1 @@
+debian/irunner.1
diff --git a/debian/pycompat b/debian/pycompat
new file mode 100644
index 0000000..0cfbf08
--- /dev/null
+++ b/debian/pycompat
@@ -0,0 +1 @@
+2
diff --git a/debian/rules b/debian/rules
index 6bb593f..6bc02e7 100755
--- a/debian/rules
+++ b/debian/rules
@@ -1,98 +1,25 @@
#!/usr/bin/make -f
-# Sample debian/rules that uses debhelper.
-# GNU copyright 1997 to 1999 by Joey Hess.
-
-# Uncomment this to turn on verbose mode.
-#export DH_VERBOSE=1
-
-
-
-
-CFLAGS = -Wall -g
-
-ifneq (,$(findstring noopt,$(DEB_BUILD_OPTIONS)))
- CFLAGS += -O0
-else
- CFLAGS += -O2
-endif
-ifeq (,$(findstring nostrip,$(DEB_BUILD_OPTIONS)))
- INSTALL_PROGRAM += -s
-endif
-
-configure: configure-stamp
-configure-stamp:
- dh_testdir
-
- python setup.py config
-
- touch configure-stamp
-
-
-build: build-stamp
-
-build-stamp: configure-stamp
- dh_testdir
-
- python setup.py build
-
- touch build-stamp
-
-clean:
- dh_testdir
- dh_testroot
- rm -f build-stamp configure-stamp
-
- -python setup.py clean --all
- rm -f setupext/*.pyc
-
- dh_clean
-
-install: build
- dh_testdir
- dh_testroot
- dh_clean -k
- dh_installdirs
-
- python setup.py install --prefix $(CURDIR)/debian/ipython/usr
-
- # remove extra license docs that get installed
- rm -f $(CURDIR)/debian/ipython/usr/share/doc/ipython/COPYING
- #rm -f $(CURDIR)/debian/ipython/usr/share/doc/ipython/GNU-LGPL
-
+# ipython debian/rules file
+DEB_PYTHON_SYSTEM=pysupport
+include /usr/share/cdbs/1/rules/debhelper.mk
+include /usr/share/cdbs/1/class/python-distutils.mk
+include /usr/share/cdbs/1/rules/dpatch.mk
+
+install/ipython::
+ # remove documentation
+ rm $(CURDIR)/debian/ipython/usr/share/doc/ipython/COPYING
+ rm $(CURDIR)/debian/ipython/usr/share/doc/ipython/ChangeLog
+ rm $(CURDIR)/debian/ipython/usr/share/doc/ipython/README_Windows.txt
+ rm $(CURDIR)/debian/ipython/usr/share/doc/ipython/pycon.ico
+
# change permission on scripts
- chmod 755 $(CURDIR)/debian/ipython/usr/share/doc/ipython/examples/example-embed.py
- chmod 755 $(CURDIR)/debian/ipython/usr/share/doc/ipython/examples/example-gnuplot.py
-
-binary-indep: build install
- dh_testdir
- dh_testroot
- dh_installchangelogs doc/ChangeLog
- dh_installdocs
-# dh_installexamples
- dh_install
-# dh_installmenu
-# dh_installdebconf
-# dh_installlogrotate
-# dh_installemacsen
-# dh_installpam
-# dh_installmime
-# dh_installinit
-# dh_installcron
-# dh_installinfo
- dh_installman doc/ipython.1.gz doc/pycolor.1.gz
- dh_compress
- dh_fixperms
- dh_python
-# dh_makeshlibs
- dh_installdeb
-# dh_shlibdeps
- dh_gencontrol
- dh_md5sums
- dh_builddeb
-
-# Build architecture-dependent files here.
-binary-arch: build install
-# We have nothing to do by default.
-
-binary: binary-indep binary-arch
-.PHONY: build clean binary-indep binary-arch binary install configure
+ chmod a-x $(CURDIR)/debian/ipython/usr/share/doc/ipython/examples/*
+
+ # removing bogus usr/IPython directory
+ rm -rf $(CURDIR)/debian/ipython/usr/IPython
+
+binary-fixup/ipython::
+ # fix lintian warnings (see also patches/04_remove_shebang.dpatch)
+ chmod +x $(CURDIR)/debian/ipython/usr/share/python-support/ipython/IPython/upgrade_dir.py
+ chmod +x $(CURDIR)/debian/ipython/usr/share/python-support/ipython/IPython/Extensions/pickleshare.py
+ chmod +x $(CURDIR)/debian/ipython/usr/share/python-support/ipython/IPython/irunner.py
diff --git a/debian/watch b/debian/watch
new file mode 100644
index 0000000..1a2b269
--- /dev/null
+++ b/debian/watch
@@ -0,0 +1,2 @@
+version=3
+http://ipython.scipy.org/dist/ ipython-(.*)\.tar\.gz
diff --git a/doc/ChangeLog b/doc/ChangeLog
index 293f46d..6a17f31 100644
--- a/doc/ChangeLog
+++ b/doc/ChangeLog
@@ -1,11 +1,232 @@
+2008-05-31 *** Released version 0.8.4
+
+2008-05-31 Fernando Perez
+
+ * IPython/ipmaker.py (make_IPython): The -twisted option is fully
+ disabled.
+
+ * IPython/Shell.py (_select_shell): completely disable -twisted.
+ This code is of dubious quality and normal users should not
+ encounter it until we can clarify things further, even under
+ win32. Since we need a quick emergency 0.8.4 release, it is now
+ disabled completely. Users who want to run it can use the
+ following command (it's easy to put it in an alias or script):
+
+ python -c"from IPython import twshell;twshell.IPShellTwisted().mainloop()"
+
+2008-05-30 Ville Vainio
+
+ * shell.py: disable -twisted on non-win32 platforms.
+ import sets module on python 2.3.
+
+ * ipy_profile_sh.py: disable ipy_signals. Now, ipython
+ is verified to work with python 2.3
+
+ * Release.py: update version to 0.8.4 for quick point fix
+
+2008-05-28 *** Released version 0.8.3
+
+2008-05-28 Fernando Perez
+
+ * ../win32_manual_post_install.py (run): Fix the windows installer
+ so the links to the docs are correct.
+
+ * IPython/ultraTB.py: flush stderr after writing to it to fix
+ problems with exception traceback ordering in some platforms.
+ Thanks to a report/fix by Jie Tang .
+
+ * IPython/Magic.py (magic_cpaste): add stripping of continuation
+ prompts, feature requested by Stefan vdW.
+
+ * ../setup.py: updates to build and release tools in preparation
+ for 0.8.3 release.
+
+2008-05-27 Ville Vainio
+
+ * iplib.py, ipmaker.py: survive lack of doctest and site._Helper
+ for minimal environments (e.g. Maemo sdk python)
+
+ * Magic.py: cpaste strips whitespace before >>> (allow pasting
+ doctests)
+
+ * ipy_completers.py: cd completer now does recursive path expand
+ (old behaviour is buggy on some readline versions)
+
+2008-05-14 Ville Vainio
+
+ * Extensions/ipy_greedycompleter.py:
+ New extension that enables a bit more "relaxed" tab
+ completer that evaluates code without safety checks
+ (i.e. there can be side effects like function calls)
+
+2008-04-20 Ville Vainio
+
+ * Extensions/ipy_lookfor.py: add %lookfor magic command
+ (search docstrings for words) by Pauli Virtanen. Close #245.
+
+ * Extension/ipy_jot.py: %jot and %read magics, analogous
+ to %store but you can specify some notes. Not read
+ in automatically on startup, you need %read.
+ Contributed by Yichun Wei.
+
+2008-04-18 Fernando Perez
+
+ * IPython/genutils.py (page): apply workaround to curses bug that
+ can leave terminal corrupted after a call to initscr().
+
+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
+ absolute_import. Close #244.
+
+2008-04-02 Ville Vainio
+
+ * ipy_winpdb.py: New extension for winpdb integration. %wdb
+ test.py is winpdb equivalent of %run -d test.py. winpdb is a
+ crossplatform remote GUI debugger based on wxpython.
+
+2008-03-29 Ville Vainio
+
+ * ipython.rst, do_sphinx.py: New documentation base, based on
+ reStucturedText and Sphinx (html/pdf generation). The old Lyx
+ based documentation will not be updated anymore.
+
+ * jobctrl.py: Use shell in Popen for 'start' command (in windows).
+
+2008-03-24 Ville Vainio
+
+ * ipython.rst, do_sphinx.py: New documentation base, based on
+ reStucturedText and Sphinx (html/pdf generation). The old Lyx
+ based documentation will not be updated anymore.
+
+ ipython.rst has up to date documentation on matters that were not
+ documented at all, and it also removes various
+ misdocumented/deprecated features.
+
+2008-03-22 Ville Vainio
+
+ * Shell.py: Merge mtexp branch:
+ https://code.launchpad.net/~ipython/ipython/mtexp
+
+ Privides simpler and more robust MTInteractiveShell that won't
+ deadlock, even when the worker thread (GUI) stops doing runcode()
+ regularly. r71.
+
+2008-03-20 Ville Vainio
+
+ * twshell.py: New shell that runs IPython code in Twisted reactor.
+ Launch by doing ipython -twisted. r67.
+
+2008-03-19 Ville Vainio
+
+ * Magic.py: %rehashx works correctly when shadowed system commands
+ have upper case characters (e.g. Print.exe). r64.
+
+ * ipy_bzr.py, ipy_app_completers.py: new bzr completer that also
+ knows options to commands, based on bzrtools. Uses bzrlib
+ directly. r66.
+
+2008-03-16 Ville Vainio
+
+ * make_tarball.py: Fixed for bzr.
+
+ * ipapi.py: Better _ip.runlines() script cleanup. r56,r79.
+
+ * ipy_vimserver.py, ipy.vim: New extension for vim server mode,
+ by Erich Heine.
+
+2008-03-12 Ville Vainio
+
+ * ipmaker.py: Force (reload?) import of ipy_user_conf and
+ ipy_profile_foo, so that embedded instances can be relaunched and
+ configuration is still done. r50
+
+ * ipapi.py, test_embed.py: Allow specifying shell class in
+ launch_new_instance & make_new instance. Use this in
+ test_embed.py. r51.
+
+ test_embed.py is also a good and simple demo of embedding IPython.
+
+
+2008-03-10 Ville Vainio
+
+ * tool/update_revnum.py: Change to bzr revisioning scheme in
+ revision numbers.
+
+ * Shell.py: Threading improvements:
+
+ In multithreaded shells, do not hang on macros and o.autoexec
+ commands (or anything executed with _ip.runlines()) anymore. Allow
+ recursive execution of IPython code in
+ MTInteractiveShell.runsource by checking if we are already in
+ worker thread, and execute code directly if we are. r48.
+
+ MTInteractiveShell.runsource: execute code directly if worker
+ thread is not running yet (this is the case in config files). r49.
+
+2008-03-09 Ville Vainio
+
+ * ipy_profile_sh.py: You can now use $LA or LA() to refer to last
+ argument of previous command in sh profile. Similar to bash '!$'.
+ LA(3) or $LA(3) stands for last argument of input history command
+ 3.
+
+ * Shell.py: -pylab names don't clutter %whos listing.
+
+2008-03-07 Ville Vainio
+
+ * ipy_autoreload.py: new extension (by Pauli Virtanen) for
+ autoreloading modules; try %autoreload and %aimport. Close #154.
+ Uses the new pre_runcode_hook.
+
+2008-02-24 Ville Vainio
+
+ * platutils_posix.py: freeze_term_title works
+
+2008-02-21 Ville Vainio
+
+ * Magic.py: %quickref does not crash with empty docstring
+
+2008-02-20 Ville Vainio
+
+ * completer.py: do not treat [](){} as protectable chars anymore,
+ close #233.
+
+ * completer.py: do not treat [](){} as protectable chars anymore
+
+ * magic.py, test_cpaste.py: Allow different prefix for pasting
+ from email
+
+2008-02-17 Ville Vainio
+
+ * Switched over to Launchpad/bzr as primary VCS.
+
+2008-02-14 Ville Vainio
+
+ * ipapi.py: _ip.runlines() is now much more liberal about
+ indentation - it cleans up the scripts it gets
+
+2008-02-14 Ville Vainio
+
+ * Extensions/ipy_leo.py: created 'ILeo' IPython-Leo bridge.
+ Changes to it (later on) are too numerous to list in ChangeLog
+ until it stabilizes
+
2008-02-07 Darren Dale
- * IPython/Shell.py: Call QtCore.pyqtRemoveInputHook() when creating
- an IPShellQt4. PyQt4-4.2.1 and later uses PyOS_InputHook to improve
- interaction in the interpreter (like Tkinter does), but it seems to
- partially interfere with the IPython implementation and exec_()
- still seems to block. So we disable the PyQt implementation and
- stick with the IPython one for now.
+ * IPython/Shell.py: Call QtCore.pyqtRemoveInputHook() when creating
+ an IPShellQt4. PyQt4-4.2.1 and later uses PyOS_InputHook to improve
+ interaction in the interpreter (like Tkinter does), but it seems to
+ partially interfere with the IPython implementation and exec_()
+ still seems to block. So we disable the PyQt implementation and
+ stick with the IPython one for now.
2008-02-02 Walter Doerwald
diff --git a/doc/ipnb_google_soc.lyx b/doc/attic/ipnb_google_soc.lyx
similarity index 100%
rename from doc/ipnb_google_soc.lyx
rename to doc/attic/ipnb_google_soc.lyx
diff --git a/doc/nbexample.py b/doc/attic/nbexample.py
similarity index 100%
rename from doc/nbexample.py
rename to doc/attic/nbexample.py
diff --git a/doc/nbexample_latex.py b/doc/attic/nbexample_latex.py
similarity index 100%
rename from doc/nbexample_latex.py
rename to doc/attic/nbexample_latex.py
diff --git a/doc/nbexample_output.py b/doc/attic/nbexample_output.py
similarity index 100%
rename from doc/nbexample_output.py
rename to doc/attic/nbexample_output.py
diff --git a/doc/new_design.lyx b/doc/attic/new_design.lyx
similarity index 100%
rename from doc/new_design.lyx
rename to doc/attic/new_design.lyx
diff --git a/doc/build_doc_instruction.txt b/doc/build_doc_instruction.txt
deleted file mode 100644
index b546509..0000000
--- a/doc/build_doc_instruction.txt
+++ /dev/null
@@ -1,28 +0,0 @@
-How to generate IPython documentation
-=====================================
-
-The doc is written using lyx http://www.lyx.org, which is a gui for latex
-documents. LyX also requires a latex installation.
-
-The file manual_base.lyx is the template file that should be edited if you
-want to do changes to the docs.
-
-A final version is generated by running
-
-./update_manual.py
-
-or
-
-ipython update_manual.py
-
-(note that "python update_manual.py" won't work, it's an ipython script!)
-
-The script update_manual.py will insert the current version number into the
-template and also generate magic.tex, a file containing documentation for
-the doc strings of the magic commands.
-
-The script creates manual.lyx which can be opened by lyx to generate pdf or
-postscript versions of the docs.
-
-update_magic.sh and update_version.sh work too, but are slated for
-deprecation.
diff --git a/doc/do_sphinx.py b/doc/do_sphinx.py
new file mode 100755
index 0000000..ead5a58
--- /dev/null
+++ b/doc/do_sphinx.py
@@ -0,0 +1,74 @@
+#!/usr/bin/env python
+"""Script to build documentation using Sphinx.
+"""
+
+import fileinput,os,sys
+
+def oscmd(c):
+ os.system(c)
+
+# html manual.
+oscmd('sphinx-build -d build/doctrees source build/html')
+
+if sys.platform != 'win32':
+ # LaTeX format.
+ oscmd('sphinx-build -b latex -d build/doctrees source build/latex')
+
+ # Produce pdf.
+ topdir = os.getcwd()
+ os.chdir('build/latex')
+
+ # Change chapter style to section style: allows chapters to start on
+ # the current page. Works much better for the short chapters we have.
+ # This must go in the class file rather than the preamble, so we modify
+ # manual.cls at runtime.
+ chapter_cmds=r'''
+% Local changes.
+\renewcommand\chapter{
+ \thispagestyle{plain}
+ \global\@topnum\z@
+ \@afterindentfalse
+ \secdef\@chapter\@schapter
+}
+\def\@makechapterhead#1{
+ \vspace*{10\p@}
+ {\raggedright \reset@font \Huge \bfseries \thechapter \quad #1}
+ \par\nobreak
+ \hrulefill
+ \par\nobreak
+ \vspace*{10\p@}
+}
+\def\@makeschapterhead#1{
+ \vspace*{10\p@}
+ {\raggedright \reset@font \Huge \bfseries #1}
+ \par\nobreak
+ \hrulefill
+ \par\nobreak
+ \vspace*{10\p@}
+}
+'''
+
+ unmodified=True
+ for line in fileinput.FileInput('manual.cls',inplace=1):
+ if 'Support for module synopsis' in line and unmodified:
+ line=chapter_cmds+line
+ elif 'makechapterhead' in line:
+ # Already have altered manual.cls: don't need to again.
+ unmodified=False
+ print line,
+
+ # Copying the makefile produced by sphinx...
+ oscmd('pdflatex ipython.tex')
+ oscmd('pdflatex ipython.tex')
+ oscmd('pdflatex ipython.tex')
+ oscmd('makeindex -s python.ist ipython.idx')
+ oscmd('makeindex -s python.ist modipython.idx')
+ oscmd('pdflatex ipython.tex')
+ oscmd('pdflatex ipython.tex')
+
+ # Create a manual/ directory with final html/pdf output
+ os.chdir(topdir)
+ oscmd('rm -rf manual')
+ oscmd('mkdir manual')
+ oscmd('cp -r build/html/*.html build/html/_static manual/')
+ oscmd('cp build/latex/ipython.pdf manual/')
diff --git a/doc/examples/extension.py b/doc/examples/extension.py
index 9ac667f..61add1b 100644
--- a/doc/examples/extension.py
+++ b/doc/examples/extension.py
@@ -1,20 +1,20 @@
-# -*- coding: utf-8 -*-
-
-import IPython.ipapi
-ip = IPython.ipapi.get()
-
-def ${name}_f(self, arg):
- r""" Short explanation
-
- Long explanation, examples
-
- """
-
- # opts,args = self.parse_options(arg,'rx')
- # if 'r' in opts: pass
-
-
-
-ip.expose_magic("${name}",${name}_f)
-
-
+# -*- coding: utf-8 -*-
+
+import IPython.ipapi
+ip = IPython.ipapi.get()
+
+def ${name}_f(self, arg):
+ r""" Short explanation
+
+ Long explanation, examples
+
+ """
+
+ # opts,args = self.parse_options(arg,'rx')
+ # if 'r' in opts: pass
+
+
+
+ip.expose_magic("${name}",${name}_f)
+
+
diff --git a/doc/examples/ipy.vim b/doc/examples/ipy.vim
new file mode 100644
index 0000000..cb05cf5
--- /dev/null
+++ b/doc/examples/ipy.vim
@@ -0,0 +1,67 @@
+if !exists("$IPY_SESSION")
+ finish
+endif
+
+" set up the python interpreter within vim, to have all the right modules
+" imported, as well as certain useful globals set
+python import socket
+python import os
+python import vim
+python IPYSERVER = None
+
+python << EOF
+# do we have a connection to the ipython instance?
+def check_server():
+ global IPYSERVER
+ if IPYSERVER:
+ return True
+ else:
+ return False
+
+# connect to the ipython server, if we need to
+def connect():
+ global IPYSERVER
+ if check_server():
+ return
+ try:
+ IPYSERVER = socket.socket(socket.AF_UNIX)
+ IPYSERVER.connect(os.environ.get('IPY_SERVER'))
+ except:
+ IPYSERVER = None
+
+def disconnect():
+ if IPYSERVER:
+ IPYSERVER.close()
+
+def send(cmd):
+ x = 0
+ while True:
+ x += IPYSERVER.send(cmd)
+ if x < len(cmd):
+ cmd = cmd[x:]
+ else:
+ break
+
+def run_this_file():
+ if check_server():
+ send('run %s' % (vim.current.buffer.name,))
+ else:
+ raise Exception, "Not connected to an IPython server"
+EOF
+
+fun! toggle_send_on_save()
+ if exists("s:ssos") && s:ssos == 1
+ let s:ssos = 0
+ au! BufWritePost *.py :py run_this_file()
+ echo "Autosend Off"
+ else
+ let s:ssos = 1
+ au BufWritePost *.py :py run_this_file()
+ echo "Autowsend On"
+ endif
+endfun
+
+map :python run_this_file()
+imap a
+map :call toggle_send_on_save()
+py connect()
diff --git a/doc/examples/ipython_here_shell_extension.reg b/doc/examples/ipython_here_shell_extension.reg
index 3ed6367..934a3ac 100644
--- a/doc/examples/ipython_here_shell_extension.reg
+++ b/doc/examples/ipython_here_shell_extension.reg
@@ -1,6 +1,6 @@
- Windows Registry Editor Version 5.00
-
-[HKEY_CLASSES_ROOT\Directory\shell\IPython here]
-
-[HKEY_CLASSES_ROOT\Directory\shell\IPython here\Command]
+ Windows Registry Editor Version 5.00
+
+[HKEY_CLASSES_ROOT\Directory\shell\IPython here]
+
+[HKEY_CLASSES_ROOT\Directory\shell\IPython here\Command]
@="cmd.exe /C ipython.py -p sh -i -c \"%cd %1\""
\ No newline at end of file
diff --git a/doc/examples/leo_bridge_demo.leo b/doc/examples/leo_bridge_demo.leo
new file mode 100644
index 0000000..052a930
--- /dev/null
+++ b/doc/examples/leo_bridge_demo.leo
@@ -0,0 +1,552 @@
+
+
+
+
+
+
+
+
+
+
+
+Documentation
+@nosent ILeo_doc.txt
+Documentation
+Introduction
+Installation
+Accessing IPython from Leo
+Accessing Leo nodes from IPython
+Cl definitions
+Special node types
+Custom push
+Code snippets
+Acknowledgements and history
+
+
+
+@chapters
+@settings
+@@string ipython_argv = ipython -pylab
+@enabled-plugins
+
+@ipy-startup
+b
+Some classes P
+File-like access
+csv data
+String list
+slist to leo
+
+
+Class tests
+csvr
+tempfile
+rfile
+strlist
+
+IPython script push tests
+Direct variables
+bar
+
+pylab tests
+Generate testarr
+testarr
+Call plotter on testarr
+
+test stuff
+@ipy-results
+foo
+
+spam
+
+
+?
+?Direct children of this node will be pushed at ipython bridge startup
+
+This node itself will *not* be pushed
+print "world"
+def rfile(body,n):
+ """ @cl rfile
+
+ produces a StringIO (file like obj of the rest of the body) """
+
+ import StringIO
+ return StringIO.StringIO(body)
+
+def tmpfile(body,n):
+ """ @cl tmpfile
+
+ Produces a temporary file, with node body as contents
+
+ """
+ import tempfile
+ h, fname = tempfile.mkstemp()
+ f = open(fname,'w')
+ f.write(body)
+ f.close()
+ return fname
+
+@cl tmpfile
+
+Hello
+?
+@cl rfile
+These
+lines
+should
+be
+readable
+@others
+def csvdata(body,n):
+ import csv
+ d = csv.Sniffer().sniff(body)
+ reader = csv.reader(body.splitlines(), dialect = d)
+ return reader
+@cl csvdata
+
+a,b,b
+1,2,2
+
+@cl
+"hello world"
+import IPython.genutils
+def slist(body,n):
+ return IPython.genutils.SList(body.splitlines())
+
+@cl slist
+hello
+world
+on
+many
+lines
+
+import ipy_leo
+@ipy_leo.format_for_leo.when_type(IPython.genutils.SList)
+def format_slist(obj):
+ return "@cl slist\n" + obj.n
+
+?
+@wrap
+@nocolor
+# test ipython script 'cleanup' with complex blocks
+1+2
+print "hello"
+3+4
+
+def f(x):
+ return x.upper()
+
+
+if 0:
+ print "foo"
+else:
+ print "bar"
+
+def g():
+ pass
+
+g()
+
+if 1:
+ if 1:
+ print "hello"
+
+ print "world"
+
+if 1:
+ print "hello"
+
+ print "word"
+else:
+ print "foo"
+
+ print "bar"
+ print "baz"
+
+try:
+ raise Exception
+except:
+ print "exc ok"
+
+@cl rfile
+hello
+world
+and whatever
+@others
+
+
+ipython.py
+
+Introduction
+============
+
+The purpose of ILeo, or leo-ipython bridge, is being a two-way communication
+channel between Leo and IPython. The level of integration is much deeper than
+conventional integration in IDEs; most notably, you are able to store *data* in
+Leo nodes, in addition to mere program code. The possibilities of this are
+endless, and this degree of integration has not been seen previously in the python
+world.
+
+IPython users are accustomed to using things like %edit to produce non-trivial
+functions/classes (i.e. something that they don't want to enter directly on the
+interactive prompt, but creating a proper script/module involves too much
+overhead). In ILeo, this task consists just going to the Leo window, creating a node
+and writing the code there, and pressing alt+I (push-to-ipython).
+
+Obviously, you can save the Leo document as usual - this is a great advantage
+of ILeo over using %edit, you can save your experimental scripts all at one
+time, without having to organize them into script/module files (before you
+really want to, of course!)
+
+
+Installation
+============
+
+You need at least Leo 4.4.7, and the development version of IPython (ILeo
+will be incorporated to IPython 0.8.3).
+
+You can get IPython from Launchpad by installing bzr and doing
+
+bzr branch lp:ipython
+
+and running "setup.py install".
+
+You need to enable the 'ipython.py' plugin in Leo:
+
+- Help -> Open LeoSettings.leo
+
+- Edit @settings-->Plugins-->@enabled-plugins, add/uncomment 'ipython.py'
+
+- Alternatively, you can add @settings-->@enabled-plugins with body ipython.py to your leo document.
+
+- Restart Leo. Be sure that you have the console window open (start leo.py from console, or double-click leo.py on windows)
+
+- Press alt+5 OR alt-x start-ipython to launch IPython in the console that
+started leo. You can start entering IPython commands normally, and Leo will keep
+running at the same time.
+
+
+Accessing IPython from Leo
+==========================
+
+IPython code
+------------
+
+Just enter IPython commands on a Leo node and press alt-I to execute
+push-to-ipython in order to execute the script in IPython. 'commands' is
+interpreted loosely here - you can enter function and class definitions, in
+addition to the things you would usually enter at IPython prompt - calculations,
+system commands etc.
+
+Everything that would be legal to enter on IPython prompt is legal to execute
+from ILeo.
+
+Results will be shows in Leo log window for convenience, in addition to the console.
+
+Suppose that a node had the following contents:
+{{{
+1+2
+print "hello"
+3+4
+
+def f(x):
+ return x.upper()
+
+f('hello world')
+}}}
+
+If you press alt+I on that node, you will see the following in Leo log window (IPython tab):
+
+{{{
+In: 1+2
+<2> 3
+In: 3+4
+<4> 7
+In: f('hello world')
+<6> 'HELLO WORLD'
+}}}
+
+(numbers like <6> mean IPython output history indices; the actual object can be
+referenced with _6 as usual in IPython).
+
+
+Plain Python code
+-----------------
+
+If the headline of the node ends with capital P, alt-I will not run the code
+through IPython translation mechanism but use the direct python 'exec' statement
+(in IPython user namespace) to execute the code. It wont be shown in IPython
+history, and sometimes it is safer (and more efficient) to execute things as
+plain Python statements. Large class definitions are good candidates for P
+nodes.
+
+
+Accessing Leo nodes from IPython
+================================
+
+The real fun starts when you start entering text to leo nodes, and are using
+that as data (input/output) for your IPython work.
+
+Accessing Leo nodes happens through the variable 'wb' (short for "WorkBook")
+that exist in the IPython user namespace. Nodes that are directly accessible are
+the ones that have simple names which could also be Python variable names;
+'foo_1' will be accessible directly from IPython, whereas 'my scripts' will not.
+If you want to access a node with arbitrary headline, add a child node '@a foo'
+(@a stands for 'anchor'). Then, the parent of '@a foo' is accessible through
+'wb.foo'.
+
+You can see what nodes are accessible be entering (in IPython) wb.<TAB>. Example:
+
+[C:leo/src]|12> wb.
+wb.b wb.tempfile wb.rfile wb.NewHeadline
+wb.bar wb.Docs wb.strlist wb.csvr
+[C:leo/src]|12> wb.tempfile
+ <12> <ipy_leo.LeoNode object at 0x044B6D90>
+
+So here, we meet the 'LeoNode' class that is your key to manipulating Leo
+content from IPython!
+
+LeoNode
+-------
+
+Suppose that we had a node with headline 'spam' and body:
+
+['12',2222+32]
+
+we can access it from IPython (or from scripts entered into other Leo nodes!) by doing:
+
+C:leo/src]|19> wb.spam.v
+ <19> ['12', 2254]
+
+'v' attribute stands for 'value', which means the node contents will be run
+through 'eval' and everything you would be able to enter into IPython prompt
+will be converted to objects. This mechanism can be extended far beyond direct
+evaluation (see '@cl definitions').
+
+'v' attribute also has a setter, i.e. you can do:
+
+wb.spam.v = "mystring"
+
+Which will result in the node 'spam' having the following text:
+
+'mystring'
+
+What assignment to 'v' does can be configured through generic functions
+('simplegeneric' module, will be explained later).
+
+Besides v, you can set the body text directly through
+
+wb.spam.b = "some\nstring",
+
+headline by
+
+wb.spam.h = 'new_headline'
+
+(obviously you must access the node through wb.new_headline from that point
+onwards), and access the contents as string list (IPython SList) through
+'wb.spam.l'.
+
+If you do 'wb.foo.v = 12' when node named 'foo' does not exist, the node titled
+'foo' will be automatically created and assigned body 12.
+
+LeoNode also supports go() that focuses the node in the Leo window, and ipush()
+that simulates pressing alt+I on the node.
+
+You can access unknownAttributes by .uA property dictionary. Unknown attributes
+allow you to store arbitrary (pickleable) python objects in the Leo nodes; the
+attributes are stored when you save the .leo document, and recreated when you
+open the document again. The attributes are not visible anywhere, but can be
+used for domain-specific metatada. Example:
+
+ [C:leo/src]|12> wb.spam.uA['coords'] = (12,222)
+ [C:leo/src]|13> wb.spam.uA
+ <13> {'coords': (12, 222)}
+
+Accessing children with iteration and dict notation
+---------------------------------------------------
+
+Sometimes, you may want to treat a node as a 'database', where the nodes
+children represent elements in the database. You can create a new child node for
+node 'spam', with headline 'foo bar' like this:
+
+ wb.spam['foo bar'] = "Hello"
+
+And assign a new value for it by doing
+
+ wb.spam['foo bar'].v = "Hello again"
+
+Note how you can't use .v when you first create the node - i.e. the node needs
+to be initialized by simple assignment, that will be interpreted as assignment
+to '.v'. This is a conscious design choice.
+
+If you try to do wb.spam['bar'] = 'Hello', ILeo will assign '@k bar' as the
+headline for the child instead, because 'bar' is a legal python name (and as
+such would be incorporated in the workbook namespace). This is done to avoid
+crowding the workbook namespace with extraneous items. The item will still be
+accessible as wb.spam['bar']
+
+LeoNodes are iterable, so to see the headlines of all the children of 'spam' do:
+
+ for n in wb.spam:
+ print n.h
+
+
+@cl definitions
+===============
+
+If the first line in the body text is of the form '@cl sometext', IPython will
+evaluate 'sometext' and call the result with the rest of the body when you do
+'wb.foo.v'. An example is in place here. Suppose that we have defined a class (I
+use the term class in a non-python sense here)
+
+{{{
+def rfile(body,node):
+ """ @cl rfile
+
+ produces a StringIO (file like obj) of the rest of the body """
+
+ import StringIO
+ return StringIO.StringIO(body)
+}}}
+
+(note that node is ignored here - but it could be used to access headline,
+children etc.),
+
+Now, let's say you have node 'spam' with text
+
+{{{
+@cl rfile
+hello
+world
+and whatever
+}}}
+
+Now, in IPython, we can do this:
+
+{{{
+[C:leo/src]|22> f = wb.spam.v
+[C:leo/src]|23> f
+ <23> <StringIO.StringIO instance at 0x04E7E490>
+[C:leo/src]|24> f.readline()
+ <24> u'hello\n'
+[C:leo/src]|25> f.readline()
+ <25> u'world\n'
+[C:leo/src]|26> f.readline()
+ <26> u'and whatever'
+[C:leo/src]|27> f.readline()
+ <27> u''
+}}}
+
+You should declare new @cl types to make ILeo as convenient your problem domain
+as possible. For example, a "@cl etree" could return the elementtree object for
+xml content.
+
+
+Special node types
+==================
+
+@ipy-startup
+------------
+
+If this node exist, the *direct children* of this will be pushed to IPython when
+ILeo is started (you press alt+5). Use it to push your own @cl definitions etc.
+The contents of of the node itself will be ignored.
+
+@ipy-results
+------------
+
+When you create a new node (wb.foo.v = 'stuff'), the node foo will be created as
+a child of this node. If @ipy-results does not exist, the new node will be created after the currently selected node.
+
+@a nodes
+--------
+
+You can attach these as children of existing nodes to provide a way to access
+nodes with arbitrary headlines, or to provide aliases to other nodes. If
+multiple @a nodes are attached as children of a node, all the names can be used
+to access the same object.
+
+
+Acknowledgements & History
+==========================
+
+This idea got started when I (Ville) saw this post by Edward Ream (the author of
+Leo) on IPython developer mailing list:
+
+ http://lists.ipython.scipy.org/pipermail/ipython-dev/2008-January/003551.html
+
+I was using FreeMind as mind mapping software, and so I had an immediate use
+case for Leo (which, incidentally, is superior to FreeMind as mind mapper). The
+wheels started rolling, I got obsessed with the power of this concept
+(everything clicked together), and Edwards excitement paralleled mine.
+Everything was mind-bogglingly easy/trivial, something that is typical of all
+revolutionary technologies (think Python here).
+
+The discussion that "built" ILeo is here:
+ http://sourceforge.net/forum/forum.php?thread_id=1911662&forum_id=10226
+
+?
+
+Declaring custom push-to-ipython handlers
+=========================================
+
+Sometimes, you might want to configure what alt+I on a node does. You can do
+that by creating your own push function and expose it using
+ipy_leo.expose_ileo_push(f, priority). The function should check whether the
+node should by handled by the function and raise IPython.ipapi.TryNext if it
+will not do the handling, giving the next function in the chain a chance to see
+whether it should handle the push.
+
+This example would print an uppercase version of node body if the node headline ends
+with U (yes, this is completely useless!):
+
+{{{
+def push_upcase(node):
+ if not node.h.endswith('U'):
+ raise TryNext
+ print node.b.upper()
+
+ipy_leo.expose_ileo_push(push_upcase, 12)
+}}}
+
+(the priority should be between 0-100 - typically, you don't need to care about
+it and can usually omit the argument altogether)
+
+
+Example code snippets
+=====================
+
+Get list of all headlines of all the nodes in leo:
+
+ [node.h for node in wb]
+
+Create node with headline 'baz', empty body:
+ wb.baz
+
+Create 10 child nodes for baz, where i is headline and 'Hello ' + i is body:
+
+ for i in range(10):
+ wb.baz[i] = 'Hello %d' % i
+
+
+
+
+12
+array([[ 0, 1, 2],
+ [ 3, 4, 5],
+ [ 6, 7, 8],
+ [ 9, 10, 11]])
+# press alt+i here to plot testarr
+
+plot(wb.testarr.v)
+
+Quickstart:
+ easy_install numpy
+ easy_install matplotlib
+
+Make sure you have '@string ipython-argv = ipython -pylab' in @settings. We currently recommend using TkAgg as the backend (it's also the default)
+#press alt+i here to generate an array for plotter
+
+wb.testarr.v = arange(12).reshape(4,3)
+
+
diff --git a/doc/ipython.1 b/doc/ipython.1
index be9ce42..5b11cf7 100644
--- a/doc/ipython.1
+++ b/doc/ipython.1
@@ -36,11 +36,11 @@ The following special options are ONLY valid at the beginning of the command
line, and not later. This is because they control the initialization of
ipython itself, before the normal option-handling mechanism is active.
.TP
-.B \-gthread, \-qthread, \-q4thread, \-wthread, \-pylab
+.B \-gthread, \-qthread, \-q4thread, \-wthread, \-pylab, \-twisted
Only ONE of these can be given, and it can only be given as the first option
passed to IPython (it will have no effect in any other position). They provide
-threading support for the GTK, QT3, QT4 and WXWidgets toolkits, and for the
-matplotlib library.
+threading support for the GTK, QT3, QT4 and WXWidgets toolkits, for the
+matplotlib library and Twisted reactor.
.br
.sp 1
With any of the first four options, IPython starts running a separate thread
@@ -56,6 +56,10 @@ request a specific version of wx to be used. This requires that you have the
distributions.
.br
.sp 1
+If \-twisted is given, IPython start a Twisted reactor and runs IPython mainloop
+in a dedicated thread, passing commands to be run inside the Twisted reactor.
+.br
+.sp 1
If \-pylab is given, IPython loads special support for the matplotlib library
(http://matplotlib.sourceforge.net), allowing interactive usage of any of its
backends as defined in the user's .matplotlibrc file. It automatically
diff --git a/doc/manual_base.lyx b/doc/manual_base.lyx
deleted file mode 100644
index 3f385cd..0000000
--- a/doc/manual_base.lyx
+++ /dev/null
@@ -1,10507 +0,0 @@
-#LyX 1.4.3 created this file. For more info see http://www.lyx.org/
-\lyxformat 245
-\begin_document
-\begin_header
-\textclass article
-\begin_preamble
-%\usepackage{ae,aecompl}
-\usepackage{color}
-
-% A few colors to replace the defaults for certain link types
-\definecolor{orange}{cmyk}{0,0.4,0.8,0.2}
-\definecolor{darkorange}{rgb}{.71,0.21,0.01}
-\definecolor{darkred}{rgb}{.52,0.08,0.01}
-\definecolor{darkgreen}{rgb}{.12,.54,.11}
-
-% Use and configure listings package for nicely formatted code
-\usepackage{listings}
-\lstset{
- language=Python,
- basicstyle=\small\ttfamily,
- commentstyle=\ttfamily\color{blue},
- stringstyle=\ttfamily\color{darkorange},
- showstringspaces=false,
- breaklines=true,
- postbreak = \space\dots
-}
-
-\usepackage[%pdftex, % needed for pdflatex
- breaklinks=true, % so long urls are correctly broken across lines
- colorlinks=true,
- urlcolor=blue,
- linkcolor=darkred,
- citecolor=darkgreen,
- ]{hyperref}
-
-\usepackage{html}
-
-% This helps prevent overly long lines that stretch beyond the margins
-\sloppy
-
-% Define a \codelist command which either uses listings for latex, or
-% plain verbatim for html (since latex2html doesn't understand the
-% listings package).
-\usepackage{verbatim}
-\newcommand{\codelist}[1] {
-\latex{\lstinputlisting{#1}}
-\html{\verbatiminput{#1}}
-}
-\end_preamble
-\language english
-\inputencoding latin1
-\fontscheme palatino
-\graphics default
-\paperfontsize 11
-\spacing single
-\papersize default
-\use_geometry true
-\use_amsmath 1
-\cite_engine basic
-\use_bibtopic false
-\paperorientation portrait
-\leftmargin 1in
-\topmargin 1in
-\rightmargin 1in
-\bottommargin 1in
-\secnumdepth 3
-\tocdepth 3
-\paragraph_separation skip
-\defskip medskip
-\quotes_language english
-\papercolumns 1
-\papersides 2
-\paperpagestyle fancy
-\tracking_changes false
-\output_changes true
-\end_header
-
-\begin_body
-
-\begin_layout Title
-IPython
-\newline
-
-\size larger
-An enhanced Interactive Python
-\size large
-
-\newline
-User Manual, v.
- __version__
-\end_layout
-
-\begin_layout Author
-Fernando P�rez
-\begin_inset Foot
-status collapsed
-
-\begin_layout Standard
-
-\size scriptsize
-Department of Applied Mathematics, University of Colorado at Boulder.
-
-\family typewriter
-
-\end_layout
-
-\end_inset
-
-
-\end_layout
-
-\begin_layout Standard
-\begin_inset ERT
-status collapsed
-
-\begin_layout Standard
-
-
-\backslash
-latex{
-\end_layout
-
-\end_inset
-
-
-\begin_inset LatexCommand \tableofcontents{}
-
-\end_inset
-
-
-\begin_inset ERT
-status collapsed
-
-\begin_layout Standard
-
-}
-\end_layout
-
-\end_inset
-
-
-\end_layout
-
-\begin_layout Standard
-\begin_inset ERT
-status open
-
-\begin_layout Standard
-
-
-\backslash
-html{
-\backslash
-bodytext{bgcolor=#ffffff}}
-\end_layout
-
-\end_inset
-
-
-\end_layout
-
-\begin_layout Standard
-
-\newpage
-
-\end_layout
-
-\begin_layout Section
-Overview
-\end_layout
-
-\begin_layout Standard
-One of Python's most useful features is its interactive interpreter.
- This system allows very fast testing of ideas without the overhead of creating
- test files as is typical in most programming languages.
- However, the interpreter supplied with the standard Python distribution
- is somewhat limited for extended interactive use.
-\end_layout
-
-\begin_layout Standard
-IPython is a free software project (released under the BSD license) which
- tries to:
-\end_layout
-
-\begin_layout Enumerate
-Provide an interactive shell superior to Python's default.
- IPython has many features for object introspection, system shell access,
- and its own special command system for adding functionality when working
- interactively.
- It tries to be a very efficient environment both for Python code development
- and for exploration of problems using Python objects (in situations like
- data analysis).
-\end_layout
-
-\begin_layout Enumerate
-Serve as an embeddable, ready to use interpreter for your own programs.
- IPython can be started with a single call from inside another program,
- providing access to the current namespace.
- This can be very useful both for debugging purposes and for situations
- where a blend of batch-processing and interactive exploration are needed.
-\end_layout
-
-\begin_layout Enumerate
-Offer a flexible framework which can be used as the base environment for
- other systems with Python as the underlying language.
- Specifically scientific environments like Mathematica, IDL and Matlab inspired
- its design, but similar ideas can be useful in many fields.
-\end_layout
-
-\begin_layout Enumerate
-Allow interactive testing of threaded graphical toolkits.
- IPython has support for interactive, non-blocking control of GTK, Qt and
- WX applications via special threading flags.
- The normal Python shell can only do this for Tkinter applications.
-\end_layout
-
-\begin_layout Subsection
-Main features
-\end_layout
-
-\begin_layout Itemize
-Dynamic object introspection.
- One can access docstrings, function definition prototypes, source code,
- source files and other details of any object accessible to the interpreter
- with a single keystroke (`
-\family typewriter
-?
-\family default
-', and using `
-\family typewriter
-??
-\family default
-' provides additional detail).
-\end_layout
-
-\begin_layout Itemize
-Searching through modules and namespaces with `
-\family typewriter
-*
-\family default
-' wildcards, both when using the `
-\family typewriter
-?
-\family default
-' system and via the
-\family typewriter
-%psearch
-\family default
- command.
-\end_layout
-
-\begin_layout Itemize
-Completion in the local namespace, by typing TAB at the prompt.
- This works for keywords, methods, variables and files in the current directory.
- This is supported via the readline library, and full access to configuring
- readline's behavior is provided.
-\end_layout
-
-\begin_layout Itemize
-Numbered input/output prompts with command history (persistent across sessions
- and tied to each profile), full searching in this history and caching of
- all input and output.
-\end_layout
-
-\begin_layout Itemize
-User-extensible `magic' commands.
- A set of commands prefixed with
-\family typewriter
-%
-\family default
- is available for controlling IPython itself and provides directory control,
- namespace information and many aliases to common system shell commands.
-\end_layout
-
-\begin_layout Itemize
-Alias facility for defining your own system aliases.
-\end_layout
-
-\begin_layout Itemize
-Complete system shell access.
- Lines starting with ! are passed directly to the system shell, and using
- !! captures shell output into python variables for further use.
-\end_layout
-
-\begin_layout Itemize
-Background execution of Python commands in a separate thread.
- IPython has an internal job manager called
-\family typewriter
-jobs
-\family default
-, and a conveninence backgrounding magic function called
-\family typewriter
-%bg
-\family default
-.
-\end_layout
-
-\begin_layout Itemize
-The ability to expand python variables when calling the system shell.
- In a shell command, any python variable prefixed with
-\family typewriter
-$
-\family default
- is expanded.
- A double
-\family typewriter
-$$
-\family default
- allows passing a literal
-\family typewriter
-$
-\family default
- to the shell (for access to shell and environment variables like
-\family typewriter
-$PATH
-\family default
-).
-\end_layout
-
-\begin_layout Itemize
-Filesystem navigation, via a magic
-\family typewriter
-%cd
-\family default
- command, along with a persistent bookmark system (using
-\family typewriter
-%bookmark
-\family default
-) for fast access to frequently visited directories.
-\end_layout
-
-\begin_layout Itemize
-A lightweight persistence framework via the
-\family typewriter
-%store
-\family default
- command, which allows you to save arbitrary Python variables.
- These get restored automatically when your session restarts.
-\end_layout
-
-\begin_layout Itemize
-Automatic indentation (optional) of code as you type (through the readline
- library).
-\end_layout
-
-\begin_layout Itemize
-Macro system for quickly re-executing multiple lines of previous input with
- a single name.
- Macros can be stored persistently via
-\family typewriter
-%store
-\family default
- and edited via
-\family typewriter
-%edit
-\family default
-.
-
-\end_layout
-
-\begin_layout Itemize
-Session logging (you can then later use these logs as code in your programs).
- Logs can optionally timestamp all input, and also store session output
- (marked as comments, so the log remains valid Python source code).
-\end_layout
-
-\begin_layout Itemize
-Session restoring: logs can be replayed to restore a previous session to
- the state where you left it.
-\end_layout
-
-\begin_layout Itemize
-Verbose and colored exception traceback printouts.
- Easier to parse visually, and in verbose mode they produce a lot of useful
- debugging information (basically a terminal version of the cgitb module).
-\end_layout
-
-\begin_layout Itemize
-Auto-parentheses: callable objects can be executed without parentheses:
-
-\family typewriter
-`sin 3'
-\family default
- is automatically converted to
-\family typewriter
-`sin(3)
-\family default
-'.
-\end_layout
-
-\begin_layout Itemize
-Auto-quoting: using `
-\family typewriter
-,
-\family default
-' or `
-\family typewriter
-;
-\family default
-' as the first character forces auto-quoting of the rest of the line:
-\family typewriter
-`,my_function a\InsetSpace ~
-b'
-\family default
- becomes automatically
-\family typewriter
-`my_function("a","b")'
-\family default
-, while
-\family typewriter
-`;my_function a\InsetSpace ~
-b'
-\family default
- becomes
-\family typewriter
-`my_function("a b")'
-\family default
-.
-\end_layout
-
-\begin_layout Itemize
-Extensible input syntax.
- You can define filters that pre-process user input to simplify input in
- special situations.
- This allows for example pasting multi-line code fragments which start with
-
-\family typewriter
-`>>>'
-\family default
- or
-\family typewriter
-`...'
-\family default
- such as those from other python sessions or the standard Python documentation.
-\end_layout
-
-\begin_layout Itemize
-Flexible configuration system.
- It uses a configuration file which allows permanent setting of all command-line
- options, module loading, code and file execution.
- The system allows recursive file inclusion, so you can have a base file
- with defaults and layers which load other customizations for particular
- projects.
-\end_layout
-
-\begin_layout Itemize
-Embeddable.
- You can call IPython as a python shell inside your own python programs.
- This can be used both for debugging code or for providing interactive abilities
- to your programs with knowledge about the local namespaces (very useful
- in debugging and data analysis situations).
-\end_layout
-
-\begin_layout Itemize
-Easy debugger access.
- You can set IPython to call up an enhanced version of the Python debugger
- (
-\family typewriter
-pdb
-\family default
-) every time there is an uncaught exception.
- This drops you inside the code which triggered the exception with all the
- data live and it is possible to navigate the stack to rapidly isolate the
- source of a bug.
- The
-\family typewriter
-%run
-\family default
- magic command --with the
-\family typewriter
--d
-\family default
- option-- can run any script under
-\family typewriter
-pdb
-\family default
-'s control, automatically setting initial breakpoints for you.
- This version of
-\family typewriter
-pdb
-\family default
- has IPython-specific improvements, including tab-completion and traceback
- coloring support.
-\end_layout
-
-\begin_layout Itemize
-Profiler support.
- You can run single statements (similar to
-\family typewriter
-profile.run()
-\family default
-) or complete programs under the profiler's control.
- While this is possible with standard
-\family typewriter
-cProfile
-\family default
- or
-\family typewriter
-profile
-\family default
- modules, IPython wraps this functionality with magic commands (see
-\family typewriter
-`%prun'
-\family default
- and
-\family typewriter
-`%run -p
-\family default
-') convenient for rapid interactive work.
-\end_layout
-
-\begin_layout Itemize
-Doctest support.
- The special
-\family typewriter
-%doctest_mode
-\family default
- command toggles a mode that allows you to paste existing doctests (with
- leading `
-\family typewriter
->>>
-\family default
-' prompts and whitespace) and uses doctest-compatible prompts and output,
- so you can use IPython sessions as doctest code.
-\end_layout
-
-\begin_layout Subsection
-Portability and Python requirements
-\end_layout
-
-\begin_layout Standard
-
-\series bold
-Python requirements:
-\series default
-IPython requires with Python version 2.3 or newer.
- If you are still using Python 2.2 and can not upgrade, the last version
- of IPython which worked with Python 2.2 was 0.6.15, so you will have to use
- that.
-\end_layout
-
-\begin_layout Standard
-IPython is developed under
-\series bold
-Linux
-\series default
-, but it should work in any reasonable Unix-type system (tested OK under
- Solaris and the *BSD family, for which a port exists thanks to Dryice Liu).
-\end_layout
-
-\begin_layout Standard
-
-\series bold
-Mac OS X
-\series default
-: it works, apparently without any problems (thanks to Jim Boyle at Lawrence
- Livermore for the information).
- Thanks to Andrea Riciputi, Fink support is available.
-\end_layout
-
-\begin_layout Standard
-
-\series bold
-CygWin
-\series default
-: it works mostly OK, though some users have reported problems with prompt
- coloring.
- No satisfactory solution to this has been found so far, you may want to
- disable colors permanently in the
-\family typewriter
-ipythonrc
-\family default
- configuration file if you experience problems.
- If you have proper color support under cygwin, please post to the IPython
- mailing list so this issue can be resolved for all users.
-\end_layout
-
-\begin_layout Standard
-
-\series bold
-Windows
-\series default
-: it works well under Windows XP/2k, and I suspect NT should behave similarly.
- Section\InsetSpace ~
-
-\begin_inset LatexCommand \ref{sub:Under-Windows}
-
-\end_inset
-
- describes installation details for Windows, including some additional tools
- needed on this platform.
-\end_layout
-
-\begin_layout Standard
-Windows 9x support is present, and has been reported to work fine (at least
- on WinME).
-\end_layout
-
-\begin_layout Standard
-Note, that I have very little access to and experience with Windows development.
- However, an excellent group of Win32 users (led by Ville Vainio), consistently
- contribute bugfixes and platform-specific enhancements, so they more than
- make up for my deficiencies on that front.
- In fact, Win32 users report using IPython as a system shell (see Sec.\InsetSpace ~
-
-\begin_inset LatexCommand \ref{sec:IPython-as-shell}
-
-\end_inset
-
- for details), as it offers a level of control and features which the default
-
-\family typewriter
-cmd.exe
-\family default
- doesn't provide.
-\end_layout
-
-\begin_layout Subsection
-Location
-\end_layout
-
-\begin_layout Standard
-IPython is generously hosted at
-\begin_inset LatexCommand \htmlurl{http://ipython.scipy.org}
-
-\end_inset
-
- by the Enthought, Inc and the SciPy project.
- This site offers downloads, subversion access, mailing lists and a bug
- tracking system.
- I am very grateful to Enthought (
-\begin_inset LatexCommand \htmlurl{http://www.enthought.com}
-
-\end_inset
-
-) and all of the SciPy team for their contribution.
-\end_layout
-
-\begin_layout Section
-\begin_inset LatexCommand \label{sec:install}
-
-\end_inset
-
-Installation
-\end_layout
-
-\begin_layout Subsection
-Instant instructions
-\end_layout
-
-\begin_layout Standard
-If you are of the impatient kind, under Linux/Unix simply untar/unzip the
- download, then install with
-\family typewriter
-`python setup.py install'
-\family default
-.
- Under Windows, double-click on the provided
-\family typewriter
-.exe
-\family default
- binary installer.
-\end_layout
-
-\begin_layout Standard
-Then, take a look at Sections
-\begin_inset LatexCommand \ref{sec:good_config}
-
-\end_inset
-
- for configuring things optimally and
-\begin_inset LatexCommand \ref{sec:quick_tips}
-
-\end_inset
-
- for quick tips on efficient use of IPython.
- You can later refer to the rest of the manual for all the gory details.
-\end_layout
-
-\begin_layout Standard
-See the notes in sec.
-
-\begin_inset LatexCommand \ref{sec:upgrade}
-
-\end_inset
-
- for upgrading IPython versions.
-\end_layout
-
-\begin_layout Subsection
-Detailed Unix instructions (Linux, Mac OS X, etc.)
-\end_layout
-
-\begin_layout Standard
-For RPM based systems, simply install the supplied package in the usual
- manner.
- If you download the tar archive, the process is:
-\end_layout
-
-\begin_layout Enumerate
-Unzip/untar the
-\family typewriter
-ipython-XXX.tar.gz
-\family default
- file wherever you want (
-\family typewriter
-XXX
-\family default
- is the version number).
- It will make a directory called
-\family typewriter
-ipython-XXX.
-
-\family default
-Change into that directory where you will find the files
-\family typewriter
-README
-\family default
- and
-\family typewriter
-setup.py
-\family default
-.
-
-\family typewriter
- O
-\family default
-nce you've completed the installation, you can safely remove this directory.
-
-\end_layout
-
-\begin_layout Enumerate
-If you are installing over a previous installation of version 0.2.0 or earlier,
- first remove your
-\family typewriter
-$HOME/.ipython
-\family default
- directory, since the configuration file format has changed somewhat (the
- '=' were removed from all option specifications).
- Or you can call ipython with the
-\family typewriter
--upgrade
-\family default
- option and it will do this automatically for you.
-\end_layout
-
-\begin_layout Enumerate
-IPython uses distutils, so you can install it by simply typing at the system
- prompt (don't type the
-\family typewriter
-$
-\family default
-)
-\newline
-
-\family typewriter
-$ python setup.py install
-\family default
-
-\newline
-Note that this assumes you have root access to your machine.
- If you don't have root access or don't want IPython to go in the default
- python directories, you'll need to use the
-\begin_inset ERT
-status collapsed
-
-\begin_layout Standard
-
-
-\backslash
-verb|--home|
-\end_layout
-
-\end_inset
-
- option (or
-\begin_inset ERT
-status collapsed
-
-\begin_layout Standard
-
-
-\backslash
-verb|--prefix|
-\end_layout
-
-\end_inset
-
-).
- For example:
-\newline
-
-\begin_inset ERT
-status collapsed
-
-\begin_layout Standard
-
-
-\backslash
-verb|$ python setup.py install --home $HOME/local|
-\end_layout
-
-\end_inset
-
-
-\newline
-will install IPython into
-\family typewriter
-$HOME/local
-\family default
-and its subdirectories (creating them if necessary).
-\newline
-You can type
-\newline
-
-\begin_inset ERT
-status collapsed
-
-\begin_layout Standard
-
-
-\backslash
-verb|$ python setup.py --help|
-\end_layout
-
-\end_inset
-
-
-\newline
-for more details.
-\newline
-Note that if you change the default location for
-\begin_inset ERT
-status collapsed
-
-\begin_layout Standard
-
-
-\backslash
-verb|--home|
-\end_layout
-
-\end_inset
-
- at installation, IPython may end up installed at a location which is not
- part of your
-\family typewriter
-$PYTHONPATH
-\family default
- environment variable.
- In this case, you'll need to configure this variable to include the actual
- directory where the
-\family typewriter
-IPython/
-\family default
- directory ended (typically the value you give to
-\begin_inset ERT
-status collapsed
-
-\begin_layout Standard
-
-
-\backslash
-verb|--home|
-\end_layout
-
-\end_inset
-
- plus
-\family typewriter
-/lib/python
-\family default
-).
-\end_layout
-
-\begin_layout Subsubsection
-Mac OSX information
-\end_layout
-
-\begin_layout Standard
-Under OSX, there is a choice you need to make.
- Apple ships its own build of Python, which lives in the core OSX filesystem
- hierarchy.
- You can also manually install a separate Python, either purely by hand
- (typically in
-\family typewriter
-/usr/local
-\family default
-) or by using Fink, which puts everything under
-\family typewriter
-/sw
-\family default
-.
- Which route to follow is a matter of personal preference, as I've seen
- users who favor each of the approaches.
- Here I will simply list the known installation issues under OSX, along
- with their solutions.
-\end_layout
-
-\begin_layout Standard
-This page:
-\begin_inset LatexCommand \htmlurl{http://geosci.uchicago.edu/~tobis/pylab.html}
-
-\end_inset
-
- contains information on this topic, with additional details on how to make
- IPython and matplotlib play nicely under OSX.
-\end_layout
-
-\begin_layout Subsubsection*
-GUI problems
-\end_layout
-
-\begin_layout Standard
-The following instructions apply to an install of IPython under OSX from
- unpacking the
-\family typewriter
-.tar.gz
-\family default
- distribution and installing it for the default Python interpreter shipped
- by Apple.
- If you are using a fink install, fink will take care of these details for
- you, by installing IPython against fink's Python.
-\end_layout
-
-\begin_layout Standard
-IPython offers various forms of support for interacting with graphical applicati
-ons from the command line, from simple Tk apps (which are in principle always
- supported by Python) to interactive control of WX, Qt and GTK apps.
- Under OSX, however, this requires that ipython is installed by calling
- the special
-\family typewriter
-pythonw
-\family default
- script at installation time, which takes care of coordinating things with
- Apple's graphical environment.
-\end_layout
-
-\begin_layout Standard
-So when installing under OSX, it is best to use the following command:
-\family typewriter
-
-\newline
-
-\family default
-
-\begin_inset ERT
-status collapsed
-
-\begin_layout Standard
-
-
-\backslash
-verb| $ sudo pythonw setup.py install --install-scripts=/usr/local/bin|
-\end_layout
-
-\end_inset
-
-
-\newline
- or
-\newline
-
-\begin_inset ERT
-status collapsed
-
-\begin_layout Standard
-
-
-\backslash
-verb| $ sudo pythonw setup.py install --install-scripts=/usr/bin|
-\end_layout
-
-\end_inset
-
-
-\newline
-depending on where you like to keep hand-installed executables.
-\end_layout
-
-\begin_layout Standard
-The resulting script will have an appropriate shebang line (the first line
- in the script whic begins with
-\family typewriter
-#!...
-\family default
-) such that the ipython interpreter can interact with the OS X GUI.
- If the installed version does not work and has a shebang line that points
- to, for example, just
-\family typewriter
-/usr/bin/python
-\family default
-, then you might have a stale, cached version in your
-\family typewriter
-build/scripts-
-\family default
- directory.
- Delete that directory and rerun the
-\family typewriter
-setup.py
-\family default
-.
-
-\end_layout
-
-\begin_layout Standard
-It is also a good idea to use the special flag
-\begin_inset ERT
-status collapsed
-
-\begin_layout Standard
-
-
-\backslash
-verb|--install-scripts|
-\end_layout
-
-\end_inset
-
- as indicated above, to ensure that the ipython scripts end up in a location
- which is part of your
-\family typewriter
-$PATH
-\family default
-.
- Otherwise Apple's Python will put the scripts in an internal directory
- not available by default at the command line (if you use
-\family typewriter
-/usr/local/bin
-\family default
-, you need to make sure this is in your
-\family typewriter
-$PATH
-\family default
-, which may not be true by default).
-\end_layout
-
-\begin_layout Subsubsection*
-Readline problems
-\end_layout
-
-\begin_layout Standard
-By default, the Python version shipped by Apple does
-\emph on
-not
-\emph default
- include the readline library, so central to IPython's behavior.
- If you install IPython against Apple's Python, you will not have arrow
- keys, tab completion, etc.
- For Mac OSX 10.3 (Panther), you can find a prebuilt readline library here:
-\newline
-
-\begin_inset LatexCommand \htmlurl{http://pythonmac.org/packages/readline-5.0-py2.3-macosx10.3.zip}
-
-\end_inset
-
-
-\end_layout
-
-\begin_layout Standard
-If you are using OSX 10.4 (Tiger), after installing this package you need
- to either:
-\end_layout
-
-\begin_layout Enumerate
-move
-\family typewriter
-readline.so
-\family default
- from
-\family typewriter
-/Library/Python/2.3
-\family default
- to
-\family typewriter
-/Library/Python/2.3/site-packages
-\family default
-, or
-\end_layout
-
-\begin_layout Enumerate
-install
-\begin_inset LatexCommand \htmlurl{http://pythonmac.org/packages/TigerPython23Compat.pkg.zip}
-
-\end_inset
-
-
-\end_layout
-
-\begin_layout Standard
-Users installing against Fink's Python or a properly hand-built one should
- not have this problem.
-\end_layout
-
-\begin_layout Subsubsection*
-DarwinPorts
-\end_layout
-
-\begin_layout Standard
-I report here a message from an OSX user, who suggests an alternative means
- of using IPython under this operating system with good results.
- Please let me know of any updates that may be useful for this section.
- His message is reproduced verbatim below:
-\end_layout
-
-\begin_layout Quote
-From: Markus Banfi
-\family typewriter
-
-\end_layout
-
-\begin_layout Quote
-As a MacOS X (10.4.2) user I prefer to install software using DawinPorts instead
- of Fink.
- I had no problems installing ipython with DarwinPorts.
- It's just:
-\end_layout
-
-\begin_layout Quote
-
-\family typewriter
-sudo port install py-ipython
-\end_layout
-
-\begin_layout Quote
-It automatically resolved all dependencies (python24, readline, py-readline).
- So far I did not encounter any problems with the DarwinPorts port of ipython.
-
-\end_layout
-
-\begin_layout Subsection
-\begin_inset LatexCommand \label{sub:Under-Windows}
-
-\end_inset
-
-Windows instructions
-\end_layout
-
-\begin_layout Standard
-Some of IPython's very useful features are:
-\end_layout
-
-\begin_layout Itemize
-Integrated readline support (Tab-based file, object and attribute completion,
- input history across sessions, editable command line, etc.)
-\end_layout
-
-\begin_layout Itemize
-Coloring of prompts, code and tracebacks.
-\end_layout
-
-\begin_layout Standard
-These, by default, are only available under Unix-like operating systems.
- However, thanks to Gary Bishop's work, Windows XP/2k users can also benefit
- from them.
- His readline library originally implemented both GNU readline functionality
- and color support, so that IPython under Windows XP/2k can be as friendly
- and powerful as under Unix-like environments.
-
-\end_layout
-
-\begin_layout Standard
-This library, now named
-\family typewriter
-PyReadline
-\family default
-, has been absorbed by the IPython team (J�rgen Stenarson, in particular),
- and it continues to be developed with new features, as well as being distribute
-d directly from the IPython site.
-\end_layout
-
-\begin_layout Standard
-The
-\family typewriter
- PyReadline
-\family default
- extension requires
-\family typewriter
-CTypes
-\family default
- and the windows IPython installer needs
-\family typewriter
-PyWin32
-\family default
-, so in all you need:
-\end_layout
-
-\begin_layout Enumerate
-
-\family typewriter
-PyWin32
-\family default
- from
-\begin_inset LatexCommand \htmlurl{http://sourceforge.net/projects/pywin32}
-
-\end_inset
-
-.
-\end_layout
-
-\begin_layout Enumerate
-
-\family typewriter
-PyReadline
-\family default
- for Windows from
-\begin_inset LatexCommand \htmlurl{http://ipython.scipy.org/moin/PyReadline/Intro}
-
-\end_inset
-
-.
- That page contains further details on using and configuring the system
- to your liking.
-\end_layout
-
-\begin_layout Enumerate
-Finally,
-\emph on
-only
-\emph default
-if you are using Python 2.3 or 2.4, you need
-\family typewriter
-CTypes
-\family default
- from
-\begin_inset LatexCommand \htmlurl{http://starship.python.net/crew/theller/ctypes}
-
-\end_inset
-
- (you
-\emph on
-must
-\emph default
- use version 0.9.1 or newer).
- This package is included in Python 2.5, so you don't need to manually get
- it if your Python version is 2.5 or newer.
-\end_layout
-
-\begin_layout Standard
-
-\series bold
-Warning about a broken readline-like library:
-\series default
- several users have reported problems stemming from using the pseudo-readline
- library at
-\begin_inset LatexCommand \htmlurl{http://newcenturycomputers.net/projects/readline.html}
-
-\end_inset
-
-.
- This is a broken library which, while called readline, only implements
- an incomplete subset of the readline API.
- Since it is still called readline, it fools IPython's detection mechanisms
- and causes unpredictable crashes later.
- If you wish to use IPython under Windows, you must NOT use this library,
- which for all purposes is (at least as of version 1.6) terminally broken.
-\end_layout
-
-\begin_layout Subsubsection
-Installation procedure
-\end_layout
-
-\begin_layout Standard
-Once you have the above installed, from the IPython download directory grab
- the
-\family typewriter
-ipython-XXX.win32.exe
-\family default
- file, where
-\family typewriter
-XXX
-\family default
- represents the version number.
- This is a regular windows executable installer, which you can simply double-cli
-ck to install.
- It will add an entry for IPython to your Start Menu, as well as registering
- IPython in the Windows list of applications, so you can later uninstall
- it from the Control Panel.
-
-\end_layout
-
-\begin_layout Standard
-IPython tries to install the configuration information in a directory named
-
-\family typewriter
-.ipython
-\family default
- (
-\family typewriter
-_ipython
-\family default
- under Windows) located in your `home' directory.
- IPython sets this directory by looking for a
-\family typewriter
-HOME
-\family default
- environment variable; if such a variable does not exist, it uses
-\family typewriter
-HOMEDRIVE
-\backslash
-HOMEPATH
-\family default
-(these are always defined by Windows).
- This typically gives something like
-\family typewriter
-C:
-\backslash
-Documents and Settings
-\backslash
-YourUserName
-\family default
-, but your local details may vary.
- In this directory you will find all the files that configure IPython's
- defaults, and you can put there your profiles and extensions.
- This directory is automatically added by IPython to
-\family typewriter
-sys.path
-\family default
-, so anything you place there can be found by
-\family typewriter
-import
-\family default
- statements.
-\end_layout
-
-\begin_layout Paragraph
-Upgrading
-\end_layout
-
-\begin_layout Standard
-For an IPython upgrade, you should first uninstall the previous version.
- This will ensure that all files and directories (such as the documentation)
- which carry embedded version strings in their names are properly removed.
-\end_layout
-
-\begin_layout Paragraph
-Manual installation under Win32
-\end_layout
-
-\begin_layout Standard
-In case the automatic installer does not work for some reason, you can download
- the
-\family typewriter
-ipython-XXX.tar.gz
-\family default
- file, which contains the full IPython source distribution (the popular
- WinZip can read
-\family typewriter
-.tar.gz
-\family default
- files).
- After uncompressing the archive, you can install it at a command terminal
- just like any other Python module, by using
-\family typewriter
-`python setup.py install'
-\family default
-.
-
-\end_layout
-
-\begin_layout Standard
-After the installation, run the supplied
-\family typewriter
-win32_manual_post_install.py
-\family default
-script, which creates the necessary Start Menu shortcuts for you.
-\end_layout
-
-\begin_layout Subsection
-\begin_inset LatexCommand \label{sec:upgrade}
-
-\end_inset
-
-Upgrading from a previous version
-\end_layout
-
-\begin_layout Standard
-If you are upgrading from a previous version of IPython, after doing the
- routine installation described above, you should call IPython with the
-
-\family typewriter
--upgrade
-\family default
- option the first time you run your new copy.
- This will automatically update your configuration directory while preserving
- copies of your old files.
- You can then later merge back any personal customizations you may have
- made into the new files.
- It is a good idea to do this as there may be new options available in the
- new configuration files which you will not have.
-\end_layout
-
-\begin_layout Standard
-Under Windows, if you don't know how to call python scripts with arguments
- from a command line, simply delete the old config directory and IPython
- will make a new one.
- Win2k and WinXP users will find it in
-\family typewriter
-C:
-\backslash
-Documents and Settings
-\backslash
-YourUserName
-\backslash
-_ipython
-\family default
-, and Win 9x users under
-\family typewriter
-C:
-\backslash
-Program Files
-\backslash
-IPython
-\backslash
-_ipython.
-\end_layout
-
-\begin_layout Section
-\begin_inset LatexCommand \label{sec:good_config}
-
-\end_inset
-
-
-\begin_inset OptArg
-status collapsed
-
-\begin_layout Standard
-Initial configuration
-\begin_inset ERT
-status collapsed
-
-\begin_layout Standard
-
-
-\backslash
-ldots
-\end_layout
-
-\end_inset
-
-
-\end_layout
-
-\end_inset
-
-Initial configuration of your environment
-\end_layout
-
-\begin_layout Standard
-This section will help you set various things in your environment for your
- IPython sessions to be as efficient as possible.
- All of IPython's configuration information, along with several example
- files, is stored in a directory named by default
-\family typewriter
-$HOME/.ipython
-\family default
-.
- You can change this by defining the environment variable
-\family typewriter
-IPYTHONDIR
-\family default
-, or at runtime with the command line option
-\family typewriter
--ipythondir
-\family default
-.
-\end_layout
-
-\begin_layout Standard
-If all goes well, the first time you run IPython it should automatically
- create a user copy of the config directory for you, based on its builtin
- defaults.
- You can look at the files it creates to learn more about configuring the
- system.
- The main file you will modify to configure IPython's behavior is called
-
-\family typewriter
-ipythonrc
-\family default
- (with a
-\family typewriter
-.ini
-\family default
- extension under Windows), included for reference in Sec.
-
-\begin_inset LatexCommand \ref{sec:ipytonrc-sample}
-
-\end_inset
-
-.
- This file is very commented and has many variables you can change to suit
- your taste, you can find more details in Sec.
-
-\begin_inset LatexCommand \ref{sec:customization}
-
-\end_inset
-
-.
- Here we discuss the basic things you will want to make sure things are
- working properly from the beginning.
-\end_layout
-
-\begin_layout Subsection
-\begin_inset LatexCommand \label{sec:help-access}
-
-\end_inset
-
-Access to the Python help system
-\end_layout
-
-\begin_layout Standard
-This is true for Python in general (not just for IPython): you should have
- an environment variable called
-\family typewriter
-PYTHONDOCS
-\family default
- pointing to the directory where your HTML Python documentation lives.
- In my system it's
-\family typewriter
-/usr/share/doc/python-docs-2.3.4/html
-\family default
-, check your local details or ask your systems administrator.
-
-\end_layout
-
-\begin_layout Standard
-This is the directory which holds the HTML version of the Python manuals.
- Unfortunately it seems that different Linux distributions package these
- files differently, so you may have to look around a bit.
- Below I show the contents of this directory on my system for reference:
-\end_layout
-
-\begin_layout Standard
-
-\family typewriter
-[html]> ls
-\newline
-about.dat acks.html dist/ ext/ index.html lib/ modindex.html stdabout.dat
- tut/ about.html api/ doc/ icons/ inst/ mac/ ref/ style.css
-\end_layout
-
-\begin_layout Standard
-You should really make sure this variable is correctly set so that Python's
- pydoc-based help system works.
- It is a powerful and convenient system with full access to the Python manuals
- and all modules accessible to you.
-\end_layout
-
-\begin_layout Standard
-Under Windows it seems that pydoc finds the documentation automatically,
- so no extra setup appears necessary.
-\end_layout
-
-\begin_layout Subsection
-Editor
-\end_layout
-
-\begin_layout Standard
-The
-\family typewriter
-%edit
-\family default
- command (and its alias
-\family typewriter
-%ed
-\family default
-) will invoke the editor set in your environment as
-\family typewriter
-EDITOR
-\family default
-.
- If this variable is not set, it will default to
-\family typewriter
-vi
-\family default
- under Linux/Unix and to
-\family typewriter
-notepad
-\family default
- under Windows.
- You may want to set this variable properly and to a lightweight editor
- which doesn't take too long to start (that is, something other than a new
- instance of
-\family typewriter
-Emacs
-\family default
-).
- This way you can edit multi-line code quickly and with the power of a real
- editor right inside IPython.
-
-\end_layout
-
-\begin_layout Standard
-If you are a dedicated
-\family typewriter
-Emacs
-\family default
- user, you should set up the
-\family typewriter
-Emacs
-\family default
- server so that new requests are handled by the original process.
- This means that almost no time is spent in handling the request (assuming
- an
-\family typewriter
-Emacs
-\family default
- process is already running).
- For this to work, you need to set your
-\family typewriter
-EDITOR
-\family default
-environment variable to
-\family typewriter
-'emacsclient'
-\family default
-.
-
-\family typewriter
-
-\family default
-The code below, supplied by Francois Pinard, can then be used in your
-\family typewriter
-.emacs
-\family default
- file to enable the server:
-\end_layout
-
-\begin_layout Standard
-
-\family typewriter
-(defvar server-buffer-clients)
-\newline
-(when (and (fboundp 'server-start) (string-equal
- (getenv "TERM") 'xterm))
-\newline
-
-\begin_inset ERT
-status collapsed
-
-\begin_layout Standard
-
-
-\backslash
-hspace*{0mm}
-\end_layout
-
-\end_inset
-
-\InsetSpace ~
-\InsetSpace ~
-(server-start)
-\newline
-
-\begin_inset ERT
-status collapsed
-
-\begin_layout Standard
-
-
-\backslash
-hspace*{0mm}
-\end_layout
-
-\end_inset
-
-\InsetSpace ~
-\InsetSpace ~
-(defun fp-kill-server-with-buffer-routine ()
-\newline
-
-\begin_inset ERT
-status collapsed
-
-\begin_layout Standard
-
-
-\backslash
-hspace*{0mm}
-\end_layout
-
-\end_inset
-
-\InsetSpace ~
-\InsetSpace ~
-\InsetSpace ~
-\InsetSpace ~
-(and server-buffer-clients (server-done)))
-\newline
-
-\begin_inset ERT
-status collapsed
-
-\begin_layout Standard
-
-
-\backslash
-hspace*{0mm}
-\end_layout
-
-\end_inset
-
-\InsetSpace ~
-\InsetSpace ~
-(add-hook 'kill-buffer-hook 'fp-kill-server-with-buffer-routine))
-\end_layout
-
-\begin_layout Standard
-You can also set the value of this editor via the commmand-line option '-
-\family typewriter
-editor'
-\family default
- or in your
-\family typewriter
-ipythonrc
-\family default
- file.
- This is useful if you wish to use specifically for IPython an editor different
- from your typical default (and for Windows users who tend to use fewer
- environment variables).
-\end_layout
-
-\begin_layout Subsection
-Color
-\end_layout
-
-\begin_layout Standard
-The default IPython configuration has most bells and whistles turned on
- (they're pretty safe).
- But there's one that
-\emph on
-may
-\emph default
- cause problems on some systems: the use of color on screen for displaying
- information.
- This is very useful, since IPython can show prompts and exception tracebacks
- with various colors, display syntax-highlighted source code, and in general
- make it easier to visually parse information.
-\end_layout
-
-\begin_layout Standard
-The following terminals seem to handle the color sequences fine:
-\end_layout
-
-\begin_layout Itemize
-Linux main text console, KDE Konsole, Gnome Terminal, E-term, rxvt, xterm.
-\end_layout
-
-\begin_layout Itemize
-CDE terminal (tested under Solaris).
- This one boldfaces light colors.
-\end_layout
-
-\begin_layout Itemize
-(X)Emacs buffers.
- See sec.
-\begin_inset LatexCommand \ref{sec:emacs}
-
-\end_inset
-
- for more details on using IPython with (X)Emacs.
-\end_layout
-
-\begin_layout Itemize
-A Windows (XP/2k) command prompt
-\emph on
-with Gary Bishop's support extensions
-\emph default
-.
- Gary's extensions are discussed in Sec.\InsetSpace ~
-
-\begin_inset LatexCommand \ref{sub:Under-Windows}
-
-\end_inset
-
-.
-\end_layout
-
-\begin_layout Itemize
-A Windows (XP/2k) CygWin shell.
- Although some users have reported problems; it is not clear whether there
- is an issue for everyone or only under specific configurations.
- If you have full color support under cygwin, please post to the IPython
- mailing list so this issue can be resolved for all users.
-\end_layout
-
-\begin_layout Standard
-These have shown problems:
-\end_layout
-
-\begin_layout Itemize
-Windows command prompt in WinXP/2k logged into a Linux machine via telnet
- or ssh.
-\end_layout
-
-\begin_layout Itemize
-Windows native command prompt in WinXP/2k,
-\emph on
-without
-\emph default
-Gary Bishop's extensions.
- Once Gary's readline library is installed, the normal WinXP/2k command
- prompt works perfectly.
-\end_layout
-
-\begin_layout Standard
-Currently the following color schemes are available:
-\end_layout
-
-\begin_layout Itemize
-
-\family typewriter
-NoColor
-\family default
-: uses no color escapes at all (all escapes are empty
-\begin_inset Quotes eld
-\end_inset
-
-
-\begin_inset Quotes eld
-\end_inset
-
- strings).
- This 'scheme' is thus fully safe to use in any terminal.
-\end_layout
-
-\begin_layout Itemize
-
-\family typewriter
-Linux
-\family default
-: works well in Linux console type environments: dark background with light
- fonts.
- It uses bright colors for information, so it is difficult to read if you
- have a light colored background.
-\end_layout
-
-\begin_layout Itemize
-
-\family typewriter
-LightBG
-\family default
-: the basic colors are similar to those in the
-\family typewriter
-Linux
-\family default
- scheme but darker.
- It is easy to read in terminals with light backgrounds.
-\end_layout
-
-\begin_layout Standard
-IPython uses colors for two main groups of things: prompts and tracebacks
- which are directly printed to the terminal, and the object introspection
- system which passes large sets of data through a pager.
-\end_layout
-
-\begin_layout Subsubsection
-Input/Output prompts and exception tracebacks
-\end_layout
-
-\begin_layout Standard
-You can test whether the colored prompts and tracebacks work on your system
- interactively by typing
-\family typewriter
-'%colors Linux'
-\family default
- at the prompt (use '
-\family typewriter
-%colors LightBG'
-\family default
- if your terminal has a light background).
- If the input prompt shows garbage like:
-\newline
-
-\family typewriter
-[0;32mIn [[1;32m1[0;32m]: [0;00m
-\family default
-
-\newline
-instead of (in color) something like:
-\newline
-
-\family typewriter
-In [1]:
-\family default
-
-\newline
-this means that your terminal doesn't properly handle color escape sequences.
- You can go to a 'no color' mode by typing '
-\family typewriter
-%colors NoColor
-\family default
-'.
-
-\end_layout
-
-\begin_layout Standard
-You can try using a different terminal emulator program (Emacs users, see
- below).
- To permanently set your color preferences, edit the file
-\family typewriter
- $HOME/.ipython/ipythonrc
-\family default
-and set the
-\family typewriter
-colors
-\family default
- option to the desired value.
-\end_layout
-
-\begin_layout Subsubsection
-Object details (types, docstrings, source code, etc.)
-\end_layout
-
-\begin_layout Standard
-IPython has a set of special functions for studying the objects you are
- working with, discussed in detail in Sec.
-
-\begin_inset LatexCommand \ref{sec:dyn-object-info}
-
-\end_inset
-
-.
- But this system relies on passing information which is longer than your
- screen through a data pager, such as the common Unix
-\family typewriter
-less
-\family default
- and
-\family typewriter
-more
-\family default
- programs.
- In order to be able to see this information in color, your pager needs
- to be properly configured.
- I strongly recommend using
-\family typewriter
-less
-\family default
- instead of
-\family typewriter
-more
-\family default
-, as it seems that
-\family typewriter
-more
-\family default
- simply can not understand colored text correctly.
-\end_layout
-
-\begin_layout Standard
-In order to configure
-\family typewriter
-less
-\family default
- as your default pager, do the following:
-\end_layout
-
-\begin_layout Enumerate
-Set the environment
-\family typewriter
-PAGER
-\family default
- variable to
-\family typewriter
-less
-\family default
-.
-\end_layout
-
-\begin_layout Enumerate
-Set the environment
-\family typewriter
-LESS
-\family default
- variable to
-\family typewriter
--r
-\family default
- (plus any other options you always want to pass to
-\family typewriter
-less
-\family default
- by default).
- This tells
-\family typewriter
-less
-\family default
- to properly interpret control sequences, which is how color information
- is given to your terminal.
-\end_layout
-
-\begin_layout Standard
-For the
-\family typewriter
-csh
-\family default
- or
-\family typewriter
-tcsh
-\family default
- shells, add to your
-\family typewriter
-~/.cshrc
-\family default
- file the lines:
-\end_layout
-
-\begin_layout Standard
-
-\family typewriter
-setenv PAGER less
-\newline
-setenv LESS -r
-\end_layout
-
-\begin_layout Standard
-There is similar syntax for other Unix shells, look at your system documentation
- for details.
-\end_layout
-
-\begin_layout Standard
-If you are on a system which lacks proper data pagers (such as Windows),
- IPython will use a very limited builtin pager.
-\end_layout
-
-\begin_layout Subsection
-\begin_inset LatexCommand \label{sec:emacs}
-
-\end_inset
-
-(X)Emacs configuration
-\end_layout
-
-\begin_layout Standard
-Thanks to the work of Alexander Schmolck and Prabhu Ramachandran, currently
- (X)Emacs and IPython get along very well.
-
-\end_layout
-
-\begin_layout Standard
-
-\series bold
-Important note:
-\series default
- You will need to use a recent enough version of
-\family typewriter
-python-mode.el
-\family default
-, along with the file
-\family typewriter
-ipython.el
-\family default
-.
- You can check that the version you have of
-\family typewriter
-python-mode.el
-\family default
- is new enough by either looking at the revision number in the file itself,
- or asking for it in (X)Emacs via
-\family typewriter
-M-x py-version
-\family default
-.
- Versions 4.68 and newer contain the necessary fixes for proper IPython support.
-\end_layout
-
-\begin_layout Standard
-The file
-\family typewriter
-ipython.el
-\family default
- is included with the IPython distribution, in the documentation directory
- (where this manual resides in PDF and HTML formats).
-\end_layout
-
-\begin_layout Standard
-Once you put these files in your Emacs path, all you need in your
-\family typewriter
-.emacs
-\family default
- file is:
-\end_layout
-
-\begin_layout LyX-Code
-(require 'ipython)
-\end_layout
-
-\begin_layout Standard
-This should give you full support for executing code snippets via IPython,
- opening IPython as your Python shell via
-\family typewriter
-C-c\InsetSpace ~
-!
-\family default
-, etc.
-
-\end_layout
-
-\begin_layout Standard
-If you happen to get garbage instead of colored prompts as described in
- the previous section, you may need to set also in your
-\family typewriter
-.emacs
-\family default
- file:
-\end_layout
-
-\begin_layout LyX-Code
-(setq ansi-color-for-comint-mode t)
-\end_layout
-
-\begin_layout Subsubsection*
-Notes
-\end_layout
-
-\begin_layout Itemize
-There is one caveat you should be aware of: you must start the IPython shell
-
-\emph on
-before
-\emph default
- attempting to execute any code regions via
-\family typewriter
-C-c\InsetSpace ~
-|
-\family default
-.
- Simply type
-\family typewriter
-C-c\InsetSpace ~
-!
-\family default
- to start IPython before passing any code regions to the interpreter, and
- you shouldn't experience any problems.
-\newline
-This is due to a bug in Python itself,
- which has been fixed for Python 2.3, but exists as of Python 2.2.2 (reported
- as SF bug [ 737947 ]).
-\end_layout
-
-\begin_layout Itemize
-The (X)Emacs support is maintained by Alexander Schmolck, so all comments/reques
-ts should be directed to him through the IPython mailing lists.
-
-\end_layout
-
-\begin_layout Itemize
-This code is still somewhat experimental so it's a bit rough around the
- edges (although in practice, it works quite well).
-\end_layout
-
-\begin_layout Itemize
-Be aware that if you customize
-\family typewriter
-py-python-command
-\family default
- previously, this value will override what
-\family typewriter
-ipython.el
-\family default
- does (because loading the customization variables comes later).
-\end_layout
-
-\begin_layout Section
-\begin_inset LatexCommand \label{sec:quick_tips}
-
-\end_inset
-
-Quick tips
-\end_layout
-
-\begin_layout Standard
-IPython can be used as an improved replacement for the Python prompt, and
- for that you don't really need to read any more of this manual.
- But in this section we'll try to summarize a few tips on how to make the
- most effective use of it for everyday Python development, highlighting
- things you might miss in the rest of the manual (which is getting long).
- We'll give references to parts in the manual which provide more detail
- when appropriate.
-\end_layout
-
-\begin_layout Standard
-The following article by Jeremy Jones provides an introductory tutorial
- about IPython:
-\newline
-
-\begin_inset LatexCommand \htmlurl{http://www.onlamp.com/pub/a/python/2005/01/27/ipython.html}
-
-\end_inset
-
-
-\end_layout
-
-\begin_layout Itemize
-The TAB key.
- TAB-completion, especially for attributes, is a convenient way to explore
- the structure of any object you're dealing with.
- Simply type
-\family typewriter
-object_name.
-\family default
- and a list of the object's attributes will be printed (see sec.
-
-\begin_inset LatexCommand \ref{sec:readline}
-
-\end_inset
-
- for more).
- Tab completion also works on file and directory names, which combined with
- IPython's alias system allows you to do from within IPython many of the
- things you normally would need the system shell for.
-
-\end_layout
-
-\begin_layout Itemize
-Explore your objects.
- Typing
-\family typewriter
-object_name?
-\family default
- will print all sorts of details about any object, including docstrings,
- function definition lines (for call arguments) and constructor details
- for classes.
- The magic commands
-\family typewriter
-%pdoc
-\family default
-,
-\family typewriter
-%pdef
-\family default
-,
-\family typewriter
-%psource
-\family default
- and
-\family typewriter
-%pfile
-\family default
- will respectively print the docstring, function definition line, full source
- code and the complete file for any object (when they can be found).
- If automagic is on (it is by default), you don't need to type the '
-\family typewriter
-%
-\family default
-' explicitly.
- See sec.
-
-\begin_inset LatexCommand \ref{sec:dyn-object-info}
-
-\end_inset
-
- for more.
-\end_layout
-
-\begin_layout Itemize
-The
-\family typewriter
-%run
-\family default
- magic command allows you to run any python script and load all of its data
- directly into the interactive namespace.
- Since the file is re-read from disk each time, changes you make to it are
- reflected immediately (in contrast to the behavior of
-\family typewriter
-import
-\family default
-).
- I rarely use
-\family typewriter
-import
-\family default
- for code I am testing, relying on
-\family typewriter
-%run
-\family default
- instead.
- See sec.
-
-\begin_inset LatexCommand \ref{sec:magic}
-
-\end_inset
-
- for more on this and other magic commands, or type the name of any magic
- command and ? to get details on it.
- See also sec.
-
-\begin_inset LatexCommand \ref{sec:dreload}
-
-\end_inset
-
- for a recursive reload command.
-\newline
-
-\family typewriter
-%run
-\family default
- also has special flags for timing the execution of your scripts (
-\family typewriter
--t
-\family default
-) and for executing them under the control of either Python's
-\family typewriter
-pdb
-\family default
-debugger (
-\family typewriter
--d
-\family default
-) or profiler (
-\family typewriter
--p
-\family default
-).
- With all of these,
-\family typewriter
-%run
-\family default
- can be used as the main tool for efficient interactive development of code
- which you write in your editor of choice.
-\end_layout
-
-\begin_layout Itemize
-Use the Python debugger,
-\family typewriter
-pdb
-\family default
-
-\begin_inset Foot
-status collapsed
-
-\begin_layout Standard
-Thanks to Christian Hart and Matthew Arnison for the suggestions leading
- to IPython's improved debugger and profiler support.
-\end_layout
-
-\end_inset
-
-.
- The
-\family typewriter
-%pdb
-\family default
- command allows you to toggle on and off the automatic invocation of an
- IPython-enhanced
-\family typewriter
-pdb
-\family default
- debugger (with coloring, tab completion and more) at any uncaught exception.
- The advantage of this is that
-\family typewriter
-pdb
-\family default
- starts
-\emph on
-inside
-\emph default
- the function where the exception occurred, with all data still available.
- You can print variables, see code, execute statements and even walk up
- and down the call stack to track down the true source of the problem (which
- often is many layers in the stack above where the exception gets triggered).
-\newline
-Runn
-ing programs with
-\family typewriter
-%run
-\family default
- and pdb active can be an efficient to develop and debug code, in many cases
- eliminating the need for
-\family typewriter
-print
-\family default
- statements or external debugging tools.
- I often simply put a
-\family typewriter
-1/0
-\family default
- in a place where I want to take a look so that pdb gets called, quickly
- view whatever variables I need to or test various pieces of code and then
- remove the
-\family typewriter
-1/0
-\family default
-.
-\newline
-Note also that `
-\family typewriter
-%run -d
-\family default
-' activates
-\family typewriter
-pdb
-\family default
- and automatically sets initial breakpoints for you to step through your
- code, watch variables, etc.
- See Sec.\InsetSpace ~
-
-\begin_inset LatexCommand \ref{sec:cache_output}
-
-\end_inset
-
- for details.
-\end_layout
-
-\begin_layout Itemize
-Use the output cache.
- All output results are automatically stored in a global dictionary named
-
-\family typewriter
-Out
-\family default
- and variables named
-\family typewriter
-_1
-\family default
-,
-\family typewriter
-_2
-\family default
-, etc.
- alias them.
- For example, the result of input line 4 is available either as
-\family typewriter
-Out[4]
-\family default
- or as
-\family typewriter
-_4
-\family default
-.
- Additionally, three variables named
-\family typewriter
-_
-\family default
-,
-\family typewriter
-__
-\family default
- and
-\family typewriter
-___
-\family default
- are always kept updated with the for the last three results.
- This allows you to recall any previous result and further use it for new
- calculations.
- See Sec.\InsetSpace ~
-
-\begin_inset LatexCommand \ref{sec:cache_output}
-
-\end_inset
-
- for more.
-\end_layout
-
-\begin_layout Itemize
-Put a '
-\family typewriter
-;
-\family default
-' at the end of a line to supress the printing of output.
- This is useful when doing calculations which generate long output you are
- not interested in seeing.
- The
-\family typewriter
-_*
-\family default
- variables and the
-\family typewriter
-Out[]
-\family default
- list do get updated with the contents of the output, even if it is not
- printed.
- You can thus still access the generated results this way for further processing.
-\end_layout
-
-\begin_layout Itemize
-A similar system exists for caching input.
- All input is stored in a global list called
-\family typewriter
-In
-\family default
- , so you can re-execute lines 22 through 28 plus line 34 by typing
-\family typewriter
-'exec In[22:29]+In[34]'
-\family default
- (using Python slicing notation).
- If you need to execute the same set of lines often, you can assign them
- to a macro with the
-\family typewriter
-%macro
-\family default
-
-\family typewriter
-function.
-
-\family default
-See sec.
-
-\begin_inset LatexCommand \ref{sec:cache_input}
-
-\end_inset
-
- for more.
-\end_layout
-
-\begin_layout Itemize
-Use your input history.
- The
-\family typewriter
-%hist
-\family default
- command can show you all previous input, without line numbers if desired
- (option
-\family typewriter
--n
-\family default
-) so you can directly copy and paste code either back in IPython or in a
- text editor.
- You can also save all your history by turning on logging via
-\family typewriter
-%logstart
-\family default
-; these logs can later be either reloaded as IPython sessions or used as
- code for your programs.
-\end_layout
-
-\begin_layout Itemize
-Define your own system aliases.
- Even though IPython gives you access to your system shell via the
-\family typewriter
-!
-\family default
- prefix, it is convenient to have aliases to the system commands you use
- most often.
- This allows you to work seamlessly from inside IPython with the same commands
- you are used to in your system shell.
-\newline
-IPython comes with some pre-defined
- aliases and a complete system for changing directories, both via a stack
- (see
-\family typewriter
-%pushd
-\family default
-,
-\family typewriter
-%popd
-\family default
- and
-\family typewriter
-%dhist
-\family default
-) and via direct
-\family typewriter
-%cd
-\family default
-.
- The latter keeps a history of visited directories and allows you to go
- to any previously visited one.
-\end_layout
-
-\begin_layout Itemize
-Use Python to manipulate the results of system commands.
- The `
-\family typewriter
-!!
-\family default
-' special syntax, and the
-\family typewriter
-%sc
-\family default
- and
-\family typewriter
-%sx
-\family default
- magic commands allow you to capture system output into Python variables.
-\end_layout
-
-\begin_layout Itemize
-Expand python variables when calling the shell (either via
-\family typewriter
-`!'
-\family default
- and
-\family typewriter
-`!!'
-\family default
- or via aliases) by prepending a
-\family typewriter
-$
-\family default
- in front of them.
- You can also expand complete python expressions.
- See sec.\InsetSpace ~
-
-\begin_inset LatexCommand \ref{sub:System-shell-access}
-
-\end_inset
-
- for more.
-\end_layout
-
-\begin_layout Itemize
-Use profiles to maintain different configurations (modules to load, function
- definitions, option settings) for particular tasks.
- You can then have customized versions of IPython for specific purposes.
- See sec.\InsetSpace ~
-
-\begin_inset LatexCommand \ref{sec:profiles}
-
-\end_inset
-
- for more.
-\end_layout
-
-\begin_layout Itemize
-Embed IPython in your programs.
- A few lines of code are enough to load a complete IPython inside your own
- programs, giving you the ability to work with your data interactively after
- automatic processing has been completed.
- See sec.\InsetSpace ~
-
-\begin_inset LatexCommand \ref{sec:embed}
-
-\end_inset
-
- for more.
-\end_layout
-
-\begin_layout Itemize
-Use the Python profiler.
- When dealing with performance issues, the
-\family typewriter
-%run
-\family default
- command with a
-\family typewriter
--p
-\family default
- option allows you to run complete programs under the control of the Python
- profiler.
- The
-\family typewriter
-%prun
-\family default
- command does a similar job for single Python expressions (like function
- calls).
-\end_layout
-
-\begin_layout Itemize
-Use the IPython.demo.Demo class to load any Python script as an interactive
- demo.
- With a minimal amount of simple markup, you can control the execution of
- the script, stopping as needed.
- See sec.\InsetSpace ~
-
-\begin_inset LatexCommand \ref{sec:interactive-demos}
-
-\end_inset
-
- for more.
-\end_layout
-
-\begin_layout Itemize
-Run your doctests from within IPython for development and debugging.
- The special
-\family typewriter
-%doctest_mode
-\family default
- command toggles a mode where the prompt, output and exceptions display
- matches as closely as possible that of the default Python interpreter.
- In addition, this mode allows you to directly paste in code that contains
- leading `
-\family typewriter
->>>
-\family default
-' prompts, even if they have extra leading whitespace (as is common in doctest
- files).
- This combined with the `
-\family typewriter
-%history -t
-\family default
-n' call to see your translated history (with these extra prompts removed
- and no line numbers) allows for an easy doctest workflow, where you can
- go from doctest to interactive execution to pasting into valid Python code
- as needed.
-\end_layout
-
-\begin_layout Subsection
-Source code handling tips
-\end_layout
-
-\begin_layout Standard
-IPython is a line-oriented program, without full control of the terminal.
- Therefore, it doesn't support true multiline editing.
- However, it has a number of useful tools to help you in dealing effectively
- with more complex editing.
-\end_layout
-
-\begin_layout Standard
-The
-\family typewriter
-%edit
-\family default
- command gives a reasonable approximation of multiline editing, by invoking
- your favorite editor on the spot.
- IPython will execute the code you type in there as if it were typed interactive
-ly.
- Type
-\family typewriter
-%edit?
-\family default
- for the full details on the edit command.
-\end_layout
-
-\begin_layout Standard
-If you have typed various commands during a session, which you'd like to
- reuse, IPython provides you with a number of tools.
- Start by using
-\family typewriter
-%hist
-\family default
- to see your input history, so you can see the line numbers of all input.
- Let us say that you'd like to reuse lines 10 through 20, plus lines 24
- and 28.
- All the commands below can operate on these with the syntax
-\end_layout
-
-\begin_layout LyX-Code
-%command 10-20 24 28
-\end_layout
-
-\begin_layout Standard
-where the command given can be:
-\end_layout
-
-\begin_layout Itemize
-
-\family typewriter
-%macro
-\family default
-: this stores the lines into a variable which, when called at the prompt,
- re-executes the input.
- Macros can be edited later using
-\family typewriter
-`%edit macroname
-\family default
-', and they can be stored persistently across sessions with `
-\family typewriter
-%store macroname
-\family default
-' (the storage system is per-profile).
- The combination of quick macros, persistent storage and editing, allows
- you to easily refine quick-and-dirty interactive input into permanent utilities
-, always available both in IPython and as files for general reuse.
-\end_layout
-
-\begin_layout Itemize
-
-\family typewriter
-%edit
-\family default
-: this will open a text editor with those lines pre-loaded for further modificat
-ion.
- It will then execute the resulting file's contents as if you had typed
- it at the prompt.
-\end_layout
-
-\begin_layout Itemize
-
-\family typewriter
-%save
-\family default
-: this saves the lines directly to a named file on disk.
-\end_layout
-
-\begin_layout Standard
-While
-\family typewriter
-%macro
-\family default
- saves input lines into memory for interactive re-execution, sometimes you'd
- like to save your input directly to a file.
- The
-\family typewriter
-%save
-\family default
- magic does this: its input sytnax is the same as
-\family typewriter
-%macro
-\family default
-, but it saves your input directly to a Python file.
- Note that the
-\family typewriter
-%logstart
-\family default
- command also saves input, but it logs
-\emph on
-all
-\emph default
- input to disk (though you can temporarily suspend it and reactivate it
- with
-\family typewriter
-%logoff/%logon
-\family default
-);
-\family typewriter
-%save
-\family default
- allows you to select which lines of input you need to save.
-\end_layout
-
-\begin_layout Subsubsection*
-Lightweight 'version control'
-\end_layout
-
-\begin_layout Standard
-When you call
-\family typewriter
-%edit
-\family default
- with no arguments, IPython opens an empty editor with a temporary file,
- and it returns the contents of your editing session as a string variable.
- Thanks to IPython's output caching mechanism, this is automatically stored:
-\end_layout
-
-\begin_layout LyX-Code
-In [1]: %edit
-\end_layout
-
-\begin_layout LyX-Code
-IPython will make a temporary file named: /tmp/ipython_edit_yR-HCN.py
-\end_layout
-
-\begin_layout LyX-Code
-Editing...
- done.
- Executing edited code...
-\end_layout
-
-\begin_layout LyX-Code
-hello - this is a temporary file
-\end_layout
-
-\begin_layout LyX-Code
-Out[1]: "print 'hello - this is a temporary file'
-\backslash
-n"
-\end_layout
-
-\begin_layout Standard
-Now, if you call
-\family typewriter
-`%edit -p'
-\family default
-, IPython tries to open an editor with the same data as the last time you
- used
-\family typewriter
-%edit
-\family default
-.
- So if you haven't used
-\family typewriter
-%edit
-\family default
- in the meantime, this same contents will reopen; however, it will be done
- in a
-\emph on
-new file
-\emph default
-.
- This means that if you make changes and you later want to find an old version,
- you can always retrieve it by using its output number, via
-\family typewriter
-`%edit _NN'
-\family default
-, where
-\family typewriter
-NN
-\family default
- is the number of the output prompt.
-\end_layout
-
-\begin_layout Standard
-Continuing with the example above, this should illustrate this idea:
-\end_layout
-
-\begin_layout LyX-Code
-In [2]: edit -p
-\end_layout
-
-\begin_layout LyX-Code
-IPython will make a temporary file named: /tmp/ipython_edit_nA09Qk.py
-\end_layout
-
-\begin_layout LyX-Code
-Editing...
- done.
- Executing edited code...
-\end_layout
-
-\begin_layout LyX-Code
-hello - now I made some changes
-\end_layout
-
-\begin_layout LyX-Code
-Out[2]: "print 'hello - now I made some changes'
-\backslash
-n"
-\end_layout
-
-\begin_layout LyX-Code
-In [3]: edit _1
-\end_layout
-
-\begin_layout LyX-Code
-IPython will make a temporary file named: /tmp/ipython_edit_gy6-zD.py
-\end_layout
-
-\begin_layout LyX-Code
-Editing...
- done.
- Executing edited code...
-\end_layout
-
-\begin_layout LyX-Code
-hello - this is a temporary file
-\end_layout
-
-\begin_layout LyX-Code
-IPython version control at work :)
-\end_layout
-
-\begin_layout LyX-Code
-Out[3]: "print 'hello - this is a temporary file'
-\backslash
-nprint 'IPython version control at work :)'
-\backslash
-n"
-\end_layout
-
-\begin_layout Standard
-This section was written after a contribution by Alexander Belchenko on
- the IPython user list.
-\end_layout
-
-\begin_layout LyX-Code
-
-\end_layout
-
-\begin_layout Subsection
-Effective logging
-\end_layout
-
-\begin_layout Standard
-A very useful suggestion sent in by Robert Kern follows:
-\end_layout
-
-\begin_layout Standard
-I recently happened on a nifty way to keep tidy per-project log files.
- I made a profile for my project (which is called "parkfield").
-\end_layout
-
-\begin_layout LyX-Code
-include ipythonrc
-\end_layout
-
-\begin_layout LyX-Code
-# cancel earlier logfile invocation:
-\end_layout
-
-\begin_layout LyX-Code
-logfile ''
-\end_layout
-
-\begin_layout LyX-Code
-execute import time
-\end_layout
-
-\begin_layout LyX-Code
-execute __cmd = '/Users/kern/research/logfiles/parkfield-%s.log rotate'
-\end_layout
-
-\begin_layout LyX-Code
-execute __IP.magic_logstart(__cmd % time.strftime('%Y-%m-%d'))
-\end_layout
-
-\begin_layout Standard
-I also added a shell alias for convenience:
-\end_layout
-
-\begin_layout LyX-Code
-alias parkfield="ipython -pylab -profile parkfield"
-\end_layout
-
-\begin_layout Standard
-Now I have a nice little directory with everything I ever type in, organized
- by project and date.
-\end_layout
-
-\begin_layout Standard
-
-\series bold
-Contribute your own:
-\series default
-If you have your own favorite tip on using IPython efficiently for a certain
- task (especially things which can't be done in the normal Python interpreter),
- don't hesitate to send it!
-\end_layout
-
-\begin_layout Section
-Command-line use
-\end_layout
-
-\begin_layout Standard
-You start IPython with the command:
-\end_layout
-
-\begin_layout Standard
-
-\family typewriter
-$ ipython [options] files
-\end_layout
-
-\begin_layout Standard
-If invoked with no options, it executes all the files listed in sequence
- and drops you into the interpreter while still acknowledging any options
- you may have set in your ipythonrc file.
- This behavior is different from standard Python, which when called as
-\family typewriter
-python -i
-\family default
- will only execute one file and ignore your configuration setup.
-\end_layout
-
-\begin_layout Standard
-Please note that some of the configuration options are not available at
- the command line, simply because they are not practical here.
- Look into your ipythonrc configuration file for details on those.
- This file typically installed in the
-\family typewriter
-$HOME/.ipython
-\family default
- directory.
- For Windows users,
-\family typewriter
-$HOME
-\family default
- resolves to
-\family typewriter
-C:
-\backslash
-
-\backslash
-Documents and Settings
-\backslash
-
-\backslash
-YourUserName
-\family default
- in most instances.
- In the rest of this text, we will refer to this directory as
-\family typewriter
-IPYTHONDIR
-\family default
-.
-\end_layout
-
-\begin_layout Subsection
-\begin_inset LatexCommand \label{sec:threading-opts}
-
-\end_inset
-
-Special Threading Options
-\end_layout
-
-\begin_layout Standard
-The following special options are ONLY valid at the beginning of the command
- line, and not later.
- This is because they control the initial- ization of ipython itself, before
- the normal option-handling mechanism is active.
-\end_layout
-
-\begin_layout List
-\labelwidthstring 00.00.0000
-
-\family typewriter
-\series bold
--gthread,\InsetSpace ~
--qthread,\InsetSpace ~
--q4thread,\InsetSpace ~
--wthread,\InsetSpace ~
--pylab:
-\family default
-\series default
- Only
-\emph on
-one
-\emph default
- of these can be given, and it can only be given as the first option passed
- to IPython (it will have no effect in any other position).
- They provide threading support for the GTK, Qt (versions 3 and 4) and WXPython
- toolkits, and for the matplotlib library.
-\end_layout
-
-\begin_layout List
-\labelwidthstring 00.00.0000
-\InsetSpace ~
- With any of the first four options, IPython starts running a separate thread
- for the graphical toolkit's operation, so that you can open and control
- graphical elements from within an IPython command line, without blocking.
- All four provide essentially the same functionality, respectively for GTK,
- Qt3, Qt4 and WXWidgets (via their Python interfaces).
-\end_layout
-
-\begin_layout List
-\labelwidthstring 00.00.0000
-\InsetSpace ~
- Note that with
-\family typewriter
--wthread
-\family default
-, you can additionally use the -wxversion option to request a specific version
- of wx to be used.
- This requires that you have the
-\family typewriter
-wxversion
-\family default
- Python module installed, which is part of recent wxPython distributions.
-\end_layout
-
-\begin_layout List
-\labelwidthstring 00.00.0000
-\InsetSpace ~
- If
-\family typewriter
--pylab
-\family default
- is given, IPython loads special support for the mat plotlib library (
-\begin_inset LatexCommand \htmlurl{http://matplotlib.sourceforge.net}
-
-\end_inset
-
-), allowing interactive usage of any of its backends as defined in the user's
-
-\family typewriter
-~/.matplotlib/matplotlibrc
-\family default
- file.
- It automatically activates GTK, Qt or WX threading for IPyhton if the choice
- of matplotlib backend requires it.
- It also modifies the
-\family typewriter
-%run
-\family default
- command to correctly execute (without blocking) any matplotlib-based script
- which calls
-\family typewriter
-show()
-\family default
- at the end.
-
-\end_layout
-
-\begin_layout List
-\labelwidthstring 00.00.0000
-
-\family typewriter
-\series bold
--tk
-\family default
-\series default
- The
-\family typewriter
--g/q/q4/wthread
-\family default
- options, and
-\family typewriter
--pylab
-\family default
- (if matplotlib is configured to use GTK, Qt3, Qt4 or WX), will normally
- block Tk graphical interfaces.
- This means that when either GTK, Qt or WX threading is active, any attempt
- to open a Tk GUI will result in a dead window, and possibly cause the Python
- interpreter to crash.
- An extra option,
-\family typewriter
--tk
-\family default
-, is available to address this issue.
- It can
-\emph on
-only
-\emph default
- be given as a
-\emph on
-second
-\emph default
- option after any of the above (
-\family typewriter
--gthread
-\family default
-,
-\family typewriter
--wthread
-\family default
- or
-\family typewriter
--pylab
-\family default
-).
-\end_layout
-
-\begin_layout List
-\labelwidthstring 00.00.0000
-\InsetSpace ~
- If
-\family typewriter
--tk
-\family default
- is given, IPython will try to coordinate Tk threading with GTK, Qt or WX.
- This is however potentially unreliable, and you will have to test on your
- platform and Python configuration to determine whether it works for you.
- Debian users have reported success, apparently due to the fact that Debian
- builds all of Tcl, Tk, Tkinter and Python with pthreads support.
- Under other Linux environments (such as Fedora Core 2/3), this option has
- caused random crashes and lockups of the Python interpreter.
- Under other operating systems (Mac OSX and Windows), you'll need to try
- it to find out, since currently no user reports are available.
-\end_layout
-
-\begin_layout List
-\labelwidthstring 00.00.0000
-\InsetSpace ~
- There is unfortunately no way for IPython to determine at run time whether
-
-\family typewriter
--tk
-\family default
- will work reliably or not, so you will need to do some experiments before
- relying on it for regular work.
-
-\end_layout
-
-\begin_layout Subsection
-\begin_inset LatexCommand \label{sec:cmd-line-opts}
-
-\end_inset
-
-Regular Options
-\end_layout
-
-\begin_layout Standard
-After the above threading options have been given, regular options can follow
- in any order.
- All options can be abbreviated to their shortest non-ambiguous form and
- are case-sensitive.
- One or two dashes can be used.
- Some options have an alternate short form, indicated after a
-\family typewriter
-|
-\family default
-.
-\end_layout
-
-\begin_layout Standard
-Most options can also be set from your ipythonrc configuration file.
- See the provided example for more details on what the options do.
- Options given at the command line override the values set in the ipythonrc
- file.
-\end_layout
-
-\begin_layout Standard
-All options with a
-\family typewriter
-[no]
-\family default
- prepended can be specified in negated form (
-\family typewriter
--nooption
-\family default
- instead of
-\family typewriter
--option
-\family default
-) to turn the feature off.
-\end_layout
-
-\begin_layout List
-\labelwidthstring 00.00.0000
-
-\family typewriter
-\series bold
--help
-\family default
-\series default
-: print a help message and exit.
-\end_layout
-
-\begin_layout List
-\labelwidthstring 00.00.0000
-
-\family typewriter
-\series bold
--pylab:
-\family default
-\series default
- this can
-\emph on
-only
-\emph default
- be given as the
-\emph on
-first
-\emph default
- option passed to IPython (it will have no effect in any other position).
- It adds special support for the matplotlib library (
-\begin_inset LatexCommand \htmlurl[http://matplotlib.sourceforge.net]{http://matplotlib.sourceforge.net}
-
-\end_inset
-
-), allowing interactive usage of any of its backends as defined in the user's
-
-\family typewriter
-.matplotlibrc
-\family default
- file.
- It automatically activates GTK or WX threading for IPyhton if the choice
- of matplotlib backend requires it.
- It also modifies the
-\family typewriter
-%run
-\family default
- command to correctly execute (without blocking) any matplotlib-based script
- which calls
-\family typewriter
-show()
-\family default
- at the end.
- See Sec.\InsetSpace ~
-
-\begin_inset LatexCommand \ref{sec:matplotlib-support}
-
-\end_inset
-
- for more details.
-\end_layout
-
-\begin_layout List
-\labelwidthstring 00.00.0000
-
-\family typewriter
-\series bold
--autocall :
-\family default
-\series default
- Make IPython automatically call any callable object even if you didn't
- type explicit parentheses.
- For example, `str 43' becomes `str(43)' automatically.
- The value can be `0' to disable the feature, `1' for
-\emph on
-smart
-\emph default
- autocall, where it is not applied if there are no more arguments on the
- line, and `2' for
-\emph on
-full
-\emph default
- autocall, where all callable objects are automatically called (even if
- no arguments are present).
- The default is `1'.
-\end_layout
-
-\begin_layout List
-\labelwidthstring 00.00.0000
-
-\family typewriter
-\series bold
--[no]autoindent:
-\family default
-\series default
- Turn automatic indentation on/off.
-\end_layout
-
-\begin_layout List
-\labelwidthstring 00.00.0000
-
-\family typewriter
-\series bold
--[no]automagic
-\series default
-:
-\family default
- make magic commands automatic (without needing their first character to
- be
-\family typewriter
-%
-\family default
-).
- Type
-\family typewriter
-%magic
-\family default
- at the IPython prompt for more information.
-\end_layout
-
-\begin_layout List
-\labelwidthstring 00.00.0000
-
-\family typewriter
-\series bold
--[no]autoedit_syntax:
-\family default
-\series default
- When a syntax error occurs after editing a file, automatically open the
- file to the trouble causing line for convenient fixing.
-
-\end_layout
-
-\begin_layout List
-\labelwidthstring 00.00.0000
-
-\family typewriter
-\series bold
--[no]banner
-\series default
-:
-\family default
- Print the initial information banner (default on).
-\end_layout
-
-\begin_layout List
-\labelwidthstring 00.00.0000
-
-\family typewriter
-\series bold
--c\InsetSpace ~
-:
-\family default
-\series default
- execute the given command string, and set sys.argv to
-\family typewriter
-['c']
-\family default
-.
- This is similar to the
-\family typewriter
--c
-\family default
- option in the normal Python interpreter.
-
-\end_layout
-
-\begin_layout List
-\labelwidthstring 00.00.0000
-
-\family typewriter
-\series bold
--cache_size|cs\InsetSpace ~
-
-\series default
-:
-\family default
- size of the output cache (maximum number of entries to hold in memory).
- The default is 1000, you can change it permanently in your config file.
- Setting it to 0 completely disables the caching system, and the minimum
- value accepted is 20 (if you provide a value less than 20, it is reset
- to 0 and a warning is issued) This limit is defined because otherwise you'll
- spend more time re-flushing a too small cache than working.
-\end_layout
-
-\begin_layout List
-\labelwidthstring 00.00.0000
-
-\family typewriter
-\series bold
--classic|cl
-\series default
-:
-\family default
- Gives IPython a similar feel to the classic Python prompt.
-\end_layout
-
-\begin_layout List
-\labelwidthstring 00.00.0000
-
-\family typewriter
-\series bold
--colors\InsetSpace ~
-:
-\family default
-\series default
- Color scheme for prompts and exception reporting.
- Currently implemented: NoColor, Linux and LightBG.
-\end_layout
-
-\begin_layout List
-\labelwidthstring 00.00.0000
-
-\family typewriter
-\series bold
--[no]color_info:
-\family default
-\series default
- IPython can display information about objects via a set of functions, and
- optionally can use colors for this, syntax highlighting source code and
- various other elements.
- However, because this information is passed through a pager (like 'less')
- and many pagers get confused with color codes, this option is off by default.
- You can test it and turn it on permanently in your ipythonrc file if it
- works for you.
- As a reference, the 'less' pager supplied with Mandrake 8.2 works ok, but
- that in RedHat 7.2 doesn't.
-\end_layout
-
-\begin_layout List
-\labelwidthstring 00.00.0000
-\InsetSpace ~
- Test it and turn it on permanently if it works with your system.
- The magic function
-\family typewriter
-%color_info
-\family default
- allows you to toggle this interactively for testing.
-\end_layout
-
-\begin_layout List
-\labelwidthstring 00.00.0000
-
-\family typewriter
-\series bold
--[no]debug
-\family default
-\series default
-: Show information about the loading process.
- Very useful to pin down problems with your configuration files or to get
- details about session restores.
-\end_layout
-
-\begin_layout List
-\labelwidthstring 00.00.0000
-
-\family typewriter
-\series bold
--[no]deep_reload
-\series default
-:
-\family default
- IPython can use the
-\family typewriter
-deep_reload
-\family default
- module which reloads changes in modules recursively (it replaces the
-\family typewriter
-reload()
-\family default
- function, so you don't need to change anything to use it).
-
-\family typewriter
-deep_reload()
-\family default
- forces a full reload of modules whose code may have changed, which the
- default
-\family typewriter
-reload()
-\family default
- function does not.
-\end_layout
-
-\begin_layout List
-\labelwidthstring 00.00.0000
-\InsetSpace ~
- When deep_reload is off, IPython will use the normal
-\family typewriter
-reload()
-\family default
-, but deep_reload will still be available as
-\family typewriter
-dreload()
-\family default
-.
- This feature is off by default [which means that you have both normal
-\family typewriter
-reload()
-\family default
- and
-\family typewriter
-dreload()
-\family default
-].
-\end_layout
-
-\begin_layout List
-\labelwidthstring 00.00.0000
-
-\family typewriter
-\series bold
--editor\InsetSpace ~
-
-\family default
-\series default
-: Which editor to use with the
-\family typewriter
-%edit
-\family default
- command.
- By default, IPython will honor your
-\family typewriter
-EDITOR
-\family default
- environment variable (if not set, vi is the Unix default and notepad the
- Windows one).
- Since this editor is invoked on the fly by IPython and is meant for editing
- small code snippets, you may want to use a small, lightweight editor here
- (in case your default
-\family typewriter
-EDITOR
-\family default
- is something like Emacs).
-\end_layout
-
-\begin_layout List
-\labelwidthstring 00.00.0000
-
-\family typewriter
-\series bold
--ipythondir\InsetSpace ~
-
-\series default
-:
-\family default
- name of your IPython configuration directory
-\family typewriter
-IPYTHONDIR
-\family default
-.
- This can also be specified through the environment variable
-\family typewriter
-IPYTHONDIR
-\family default
-.
-\end_layout
-
-\begin_layout List
-\labelwidthstring 00.00.0000
-
-\family typewriter
-\series bold
--log|l
-\family default
-\series default
-: generate a log file of all input.
- The file is named
-\family typewriter
-ipython_log.py
-\family default
- in your current directory (which prevents logs from multiple IPython sessions
- from trampling each other).
- You can use this to later restore a session by loading your logfile as
- a file to be executed with option
-\family typewriter
--logplay
-\family default
- (see below).
-\end_layout
-
-\begin_layout List
-\labelwidthstring 00.00.0000
-
-\family typewriter
-\series bold
--logfile|lf\InsetSpace ~
-
-\series default
-:
-\family default
-specify the name of your logfile.
-\end_layout
-
-\begin_layout List
-\labelwidthstring 00.00.0000
-
-\family typewriter
-\series bold
--logplay|lp\InsetSpace ~
-
-\series default
-:
-\family default
- you can replay a previous log.
- For restoring a session as close as possible to the state you left it in,
- use this option (don't just run the logfile).
- With
-\family typewriter
--logplay
-\family default
-, IPython will try to reconstruct the previous working environment in full,
- not just execute the commands in the logfile.
-\end_layout
-
-\begin_layout List
-\labelwidthstring 00.00.0000
-\InsetSpace ~
- When a session is restored, logging is automatically turned on again with
- the name of the logfile it was invoked with (it is read from the log header).
- So once you've turned logging on for a session, you can quit IPython and
- reload it as many times as you want and it will continue to log its history
- and restore from the beginning every time.
-\end_layout
-
-\begin_layout List
-\labelwidthstring 00.00.0000
-\InsetSpace ~
- Caveats: there are limitations in this option.
- The history variables
-\family typewriter
-_i*
-\family default
-,
-\family typewriter
-_*
-\family default
- and
-\family typewriter
-_dh
-\family default
- don't get restored properly.
- In the future we will try to implement full session saving by writing and
- retrieving a 'snapshot' of the memory state of IPython.
- But our first attempts failed because of inherent limitations of Python's
- Pickle module, so this may have to wait.
-\end_layout
-
-\begin_layout List
-\labelwidthstring 00.00.0000
-
-\family typewriter
-\series bold
--[no]messages
-\series default
-:
-\family default
- Print messages which IPython collects about its startup process (default
- on).
-\end_layout
-
-\begin_layout List
-\labelwidthstring 00.00.0000
-
-\family typewriter
-\series bold
--[no]pdb
-\family default
-\series default
-: Automatically call the pdb debugger after every uncaught exception.
- If you are used to debugging using pdb, this puts you automatically inside
- of it after any call (either in IPython or in code called by it) which
- triggers an exception which goes uncaught.
-\end_layout
-
-\begin_layout List
-\labelwidthstring 00.00.0000
-
-\family typewriter
-\series bold
--[no]pprint
-\series default
-:
-\family default
- ipython can optionally use the pprint (pretty printer) module for displaying
- results.
- pprint tends to give a nicer display of nested data structures.
- If you like it, you can turn it on permanently in your config file (default
- off).
-\end_layout
-
-\begin_layout List
-\labelwidthstring 00.00.0000
-
-\family typewriter
-\series bold
--profile|p
-\series default
-:
-\family default
- assume that your config file is
-\family typewriter
-ipythonrc-
-\family default
- (looks in current dir first, then in
-\family typewriter
-IPYTHONDIR
-\family default
-).
- This is a quick way to keep and load multiple config files for different
- tasks, especially if you use the include option of config files.
- You can keep a basic
-\family typewriter
-IPYTHONDIR/ipythonrc
-\family default
- file and then have other 'profiles' which include this one and load extra
- things for particular tasks.
- For example:
-\end_layout
-
-\begin_layout List
-\labelwidthstring 00.00.0000
-
-\family typewriter
-\InsetSpace ~
-
-\family default
-1.
-
-\family typewriter
- $HOME/.ipython/ipythonrc
-\family default
- : load basic things you always want.
-\end_layout
-
-\begin_layout List
-\labelwidthstring 00.00.0000
-
-\family typewriter
-\InsetSpace ~
-
-\family default
-2.
-
-\family typewriter
- $HOME/.ipython/ipythonrc-math
-\family default
- : load (1) and basic math-related modules.
-
-\end_layout
-
-\begin_layout List
-\labelwidthstring 00.00.0000
-
-\family typewriter
-\InsetSpace ~
-
-\family default
-3.
-
-\family typewriter
- $HOME/.ipython/ipythonrc-numeric
-\family default
- : load (1) and Numeric and plotting modules.
-\end_layout
-
-\begin_layout List
-\labelwidthstring 00.00.0000
-\InsetSpace ~
- Since it is possible to create an endless loop by having circular file
- inclusions, IPython will stop if it reaches 15 recursive inclusions.
-\end_layout
-
-\begin_layout List
-\labelwidthstring 00.00.0000
-
-\family typewriter
-\series bold
--prompt_in1|pi1\InsetSpace ~
-:
-\family default
-\series default
- Specify the string used for input prompts.
- Note that if you are using numbered prompts, the number is represented
- with a '
-\backslash
-#' in the string.
- Don't forget to quote strings with spaces embedded in them.
- Default: '
-\family typewriter
-In\InsetSpace ~
-[
-\backslash
-#]:
-\family default
-'.
- Sec.\InsetSpace ~
-
-\begin_inset LatexCommand \ref{sec:prompts}
-
-\end_inset
-
- discusses in detail all the available escapes to customize your prompts.
-\end_layout
-
-\begin_layout List
-\labelwidthstring 00.00.0000
-
-\family typewriter
-\series bold
--prompt_in2|pi2\InsetSpace ~
-:
-\family default
-\series default
- Similar to the previous option, but used for the continuation prompts.
- The special sequence '
-\family typewriter
-
-\backslash
-D
-\family default
-' is similar to '
-\family typewriter
-
-\backslash
-#
-\family default
-', but with all digits replaced dots (so you can have your continuation
- prompt aligned with your input prompt).
- Default: '
-\family typewriter
-\InsetSpace ~
-\InsetSpace ~
-\InsetSpace ~
-.
-\backslash
-D.:
-\family default
-' (note three spaces at the start for alignment with '
-\family typewriter
-In\InsetSpace ~
-[
-\backslash
-#]
-\family default
-').
-\end_layout
-
-\begin_layout List
-\labelwidthstring 00.00.0000
-
-\family typewriter
-\series bold
--prompt_out|po\InsetSpace ~
-:
-\family default
-\series default
- String used for output prompts, also uses numbers like
-\family typewriter
-prompt_in1
-\family default
-.
- Default: '
-\family typewriter
-Out[
-\backslash
-#]:
-\family default
-'
-\end_layout
-
-\begin_layout List
-\labelwidthstring 00.00.0000
-
-\family typewriter
-\series bold
--quick
-\family default
-\series default
-: start in bare bones mode (no config file loaded).
-\end_layout
-
-\begin_layout List
-\labelwidthstring 00.00.0000
-
-\family typewriter
-\series bold
--rcfile\InsetSpace ~
-
-\series default
-:
-\family default
- name of your IPython resource configuration file.
- Normally IPython loads ipythonrc (from current directory) or
-\family typewriter
- IPYTHONDIR/ipythonrc
-\family default
-.
-\end_layout
-
-\begin_layout List
-\labelwidthstring 00.00.0000
-\InsetSpace ~
- If the loading of your config file fails, IPython starts with a bare bones
- configuration (no modules loaded at all).
-\end_layout
-
-\begin_layout List
-\labelwidthstring 00.00.0000
-
-\family typewriter
-\series bold
--[no]readline
-\family default
-\series default
-: use the readline library, which is needed to support name completion and
- command history, among other things.
- It is enabled by default, but may cause problems for users of X/Emacs in
- Python comint or shell buffers.
-\end_layout
-
-\begin_layout List
-\labelwidthstring 00.00.0000
-\InsetSpace ~
- Note that X/Emacs 'eterm' buffers (opened with
-\family typewriter
-M-x\InsetSpace ~
-term
-\family default
-) support IPython's readline and syntax coloring fine, only 'emacs' (
-\family typewriter
-M-x\InsetSpace ~
-shell
-\family default
- and
-\family typewriter
-C-c\InsetSpace ~
-!
-\family default
-) buffers do not.
-\end_layout
-
-\begin_layout List
-\labelwidthstring 00.00.0000
-
-\family typewriter
-\series bold
--screen_length|sl\InsetSpace ~
-
-\series default
-:
-\family default
- number of lines of your screen.
- This is used to control printing of very long strings.
- Strings longer than this number of lines will be sent through a pager instead
- of directly printed.
-\end_layout
-
-\begin_layout List
-\labelwidthstring 00.00.0000
-\InsetSpace ~
- The default value for this is 0, which means IPython will auto-detect your
- screen size every time it needs to print certain potentially long strings
- (this doesn't change the behavior of the 'print' keyword, it's only triggered
- internally).
- If for some reason this isn't working well (it needs curses support), specify
- it yourself.
- Otherwise don't change the default.
-\end_layout
-
-\begin_layout List
-\labelwidthstring 00.00.0000
-
-\family typewriter
-\series bold
--separate_in|si\InsetSpace ~
-
-\series default
-:
-\family default
- separator before input prompts.
- Default: '
-\family typewriter
-
-\backslash
-n
-\family default
-'
-\end_layout
-
-\begin_layout List
-\labelwidthstring 00.00.0000
-
-\family typewriter
-\series bold
--separate_out|so\InsetSpace ~
-
-\family default
-\series default
-: separator before output prompts.
- Default: nothing.
-\end_layout
-
-\begin_layout List
-\labelwidthstring 00.00.0000
-
-\family typewriter
-\series bold
--separate_out2|so2\InsetSpace ~
-
-\series default
-:
-\family default
- separator after output prompts.
- Default: nothing.
-\end_layout
-
-\begin_layout List
-\labelwidthstring 00.00.0000
-\InsetSpace ~
- For these three options, use the value 0 to specify no separator.
-\end_layout
-
-\begin_layout List
-\labelwidthstring 00.00.0000
-
-\family typewriter
-\series bold
--nosep
-\series default
-:
-\family default
-shorthand for
-\family typewriter
-'-SeparateIn 0 -SeparateOut 0 -SeparateOut2 0'
-\family default
-.
- Simply removes all input/output separators.
-\end_layout
-
-\begin_layout List
-\labelwidthstring 00.00.0000
-
-\family typewriter
-\series bold
--upgrade
-\family default
-\series default
-: allows you to upgrade your
-\family typewriter
-IPYTHONDIR
-\family default
- configuration when you install a new version of IPython.
- Since new versions may include new command line options or example files,
- this copies updated ipythonrc-type files.
- However, it backs up (with a
-\family typewriter
-.old
-\family default
- extension) all files which it overwrites so that you can merge back any
- customizations you might have in your personal files.
-\end_layout
-
-\begin_layout List
-\labelwidthstring 00.00.0000
-
-\family typewriter
-\series bold
--Version
-\series default
-:
-\family default
- print version information and exit.
-\end_layout
-
-\begin_layout List
-\labelwidthstring 00.00.0000
-
-\family typewriter
-\series bold
--wxversion\InsetSpace ~
-:
-\family default
-\series default
- Select a specific version of wxPython (used in conjunction with
-\family typewriter
--wthread
-\family default
-).
- Requires the wxversion module, part of recent wxPython distributions
-\end_layout
-
-\begin_layout List
-\labelwidthstring 00.00.0000
-
-\family typewriter
-\series bold
--xmode\InsetSpace ~
-
-\series default
-:
-\family default
- Mode for exception reporting.
-\end_layout
-
-\begin_layout List
-\labelwidthstring 00.00.0000
-\InsetSpace ~
- Valid modes: Plain, Context and Verbose.
-\end_layout
-
-\begin_layout List
-\labelwidthstring 00.00.0000
-\InsetSpace ~
- Plain: similar to python's normal traceback printing.
-\end_layout
-
-\begin_layout List
-\labelwidthstring 00.00.0000
-\InsetSpace ~
- Context: prints 5 lines of context source code around each line in the
- traceback.
-\end_layout
-
-\begin_layout List
-\labelwidthstring 00.00.0000
-\InsetSpace ~
- Verbose: similar to Context, but additionally prints the variables currently
- visible where the exception happened (shortening their strings if too long).
- This can potentially be very slow, if you happen to have a huge data structure
- whose string representation is complex to compute.
- Your computer may appear to freeze for a while with cpu usage at 100%.
- If this occurs, you can cancel the traceback with Ctrl-C (maybe hitting
- it more than once).
-\end_layout
-
-\begin_layout Section
-Interactive use
-\end_layout
-
-\begin_layout Standard
-
-\series bold
-Warning
-\series default
-: IPython relies on the existence of a global variable called
-\family typewriter
-__IP
-\family default
- which controls the shell itself.
- If you redefine
-\family typewriter
-__IP
-\family default
- to anything, bizarre behavior will quickly occur.
-\end_layout
-
-\begin_layout Standard
-Other than the above warning, IPython is meant to work as a drop-in replacement
- for the standard interactive interpreter.
- As such, any code which is valid python should execute normally under IPython
- (cases where this is not true should be reported as bugs).
- It does, however, offer many features which are not available at a standard
- python prompt.
- What follows is a list of these.
-\end_layout
-
-\begin_layout Subsection
-Caution for Windows users
-\end_layout
-
-\begin_layout Standard
-Windows, unfortunately, uses the `
-\family typewriter
-
-\backslash
-
-\family default
-' character as a path separator.
- This is a terrible choice, because `
-\family typewriter
-
-\backslash
-
-\family default
-' also represents the escape character in most modern programming languages,
- including Python.
- For this reason, issuing many of the commands discussed below (especially
- magics which affect the filesystem) with `
-\family typewriter
-
-\backslash
-
-\family default
-' in them will cause strange errors.
-\end_layout
-
-\begin_layout Standard
-A partial solution is to use instead the `
-\family typewriter
-/
-\family default
-' character as a path separator, which Windows recognizes in
-\emph on
-most
-\emph default
- situations.
- However, in Windows commands `
-\family typewriter
-/
-\family default
-' flags options, so you can not use it for the root directory.
- This means that paths beginning at the root must be typed in a contrived
- manner like:
-\newline
-
-\family typewriter
-%copy
-\backslash
-opt/foo/bar.txt
-\backslash
-tmp
-\end_layout
-
-\begin_layout Standard
-There is no sensible thing IPython can do to truly work around this flaw
- in Windows
-\begin_inset Foot
-status collapsed
-
-\begin_layout Standard
-If anyone comes up with a
-\emph on
-clean
-\emph default
- solution which works consistently and does not negatively impact other
- platforms at all, I'll gladly accept a patch.
-\end_layout
-
-\end_inset
-
-.
-\end_layout
-
-\begin_layout Subsection
-\begin_inset LatexCommand \label{sec:magic}
-
-\end_inset
-
-Magic command system
-\end_layout
-
-\begin_layout Standard
-IPython will treat any line whose first character is a
-\family typewriter
-%
-\family default
- as a special call to a 'magic' function.
- These allow you to control the behavior of IPython itself, plus a lot of
- system-type features.
- They are all prefixed with a
-\family typewriter
-%
-\family default
- character, but parameters are given without parentheses or quotes.
-\end_layout
-
-\begin_layout Standard
-Example: typing
-\family typewriter
-'%cd mydir'
-\family default
- (without the quotes) changes you working directory to
-\family typewriter
-'mydir'
-\family default
-, if it exists.
-\end_layout
-
-\begin_layout Standard
-If you have 'automagic' enabled (in your
-\family typewriter
-ipythonrc
-\family default
- file, via the command line option
-\family typewriter
--automagic
-\family default
-or with the
-\family typewriter
-%automagic
-\family default
- function), you don't need to type in the
-\family typewriter
-%
-\family default
- explicitly.
- IPython will scan its internal list of magic functions and call one if
- it exists.
- With automagic on you can then just type '
-\family typewriter
-cd mydir
-\family default
-' to go to directory '
-\family typewriter
-mydir
-\family default
-'.
- The automagic system has the lowest possible precedence in name searches,
- so defining an identifier with the same name as an existing magic function
- will shadow it for automagic use.
- You can still access the shadowed magic function by explicitly using the
-
-\family typewriter
-%
-\family default
- character at the beginning of the line.
-\end_layout
-
-\begin_layout Standard
-An example (with automagic on) should clarify all this:
-\end_layout
-
-\begin_layout LyX-Code
-In [1]: cd ipython # %cd is called by automagic
-\end_layout
-
-\begin_layout LyX-Code
-/home/fperez/ipython
-\end_layout
-
-\begin_layout LyX-Code
-In [2]: cd=1 # now cd is just a variable
-\end_layout
-
-\begin_layout LyX-Code
-In [3]: cd ..
- # and doesn't work as a function anymore
-\end_layout
-
-\begin_layout LyX-Code
-------------------------------------------------------------
-\end_layout
-
-\begin_layout LyX-Code
- File "", line 1
-\end_layout
-
-\begin_layout LyX-Code
- cd ..
-\end_layout
-
-\begin_layout LyX-Code
- ^
-\end_layout
-
-\begin_layout LyX-Code
-SyntaxError: invalid syntax
-\end_layout
-
-\begin_layout LyX-Code
-
-\end_layout
-
-\begin_layout LyX-Code
-In [4]: %cd ..
- # but %cd always works
-\end_layout
-
-\begin_layout LyX-Code
-/home/fperez
-\end_layout
-
-\begin_layout LyX-Code
-In [5]: del cd # if you remove the cd variable
-\end_layout
-
-\begin_layout LyX-Code
-In [6]: cd ipython # automagic can work again
-\end_layout
-
-\begin_layout LyX-Code
-/home/fperez/ipython
-\end_layout
-
-\begin_layout Standard
-You can define your own magic functions to extend the system.
- The following example defines a new magic command,
-\family typewriter
-%impall
-\family default
-:
-\end_layout
-
-\begin_layout LyX-Code
-import IPython.ipapi
-\end_layout
-
-\begin_layout LyX-Code
-ip = IPython.ipapi.get()
-\end_layout
-
-\begin_layout LyX-Code
-
-\end_layout
-
-\begin_layout LyX-Code
-def doimp(self, arg):
-\end_layout
-
-\begin_layout LyX-Code
- ip = self.api
-\end_layout
-
-\begin_layout LyX-Code
- ip.ex("import %s; reload(%s); from %s import *" % (
-\end_layout
-
-\begin_layout LyX-Code
- arg,arg,arg)
-\end_layout
-
-\begin_layout LyX-Code
- )
-\end_layout
-
-\begin_layout LyX-Code
-ip.expose_magic('impall', doimp)
-\end_layout
-
-\begin_layout Standard
-You can also define your own aliased names for magic functions.
- In your
-\family typewriter
-ipythonrc
-\family default
- file, placing a line like:
-\end_layout
-
-\begin_layout Standard
-
-\family typewriter
-execute __IP.magic_cl = __IP.magic_clear
-\end_layout
-
-\begin_layout Standard
-will define
-\family typewriter
-%cl
-\family default
- as a new name for
-\family typewriter
-%clear
-\family default
-.
-\end_layout
-
-\begin_layout Standard
-Type
-\family typewriter
-%magic
-\family default
- for more information, including a list of all available magic functions
- at any time and their docstrings.
- You can also type
-\family typewriter
-%magic_function_name?
-\family default
- (see sec.
-
-\begin_inset LatexCommand \ref{sec:dyn-object-info}
-
-\end_inset
-
- for information on the
-\family typewriter
-'?'
-\family default
- system) to get information about any particular magic function you are
- interested in.
-\end_layout
-
-\begin_layout Subsubsection
-Magic commands
-\end_layout
-
-\begin_layout Standard
-The rest of this section is automatically generated for each release from
- the docstrings in the IPython code.
- Therefore the formatting is somewhat minimal, but this method has the advantage
- of having information always in sync with the code.
-\end_layout
-
-\begin_layout Standard
-A list of all the magic commands available in IPython's
-\emph on
-default
-\emph default
- installation follows.
- This is similar to what you'll see by simply typing
-\family typewriter
-%magic
-\family default
- at the prompt, but that will also give you information about magic commands
- you may have added as part of your personal customizations.
-\end_layout
-
-\begin_layout Standard
-\begin_inset Include \input{magic.tex}
-preview false
-
-\end_inset
-
-
-\end_layout
-
-\begin_layout Subsection
-Access to the standard Python help
-\end_layout
-
-\begin_layout Standard
-As of Python 2.1, a help system is available with access to object docstrings
- and the Python manuals.
- Simply type
-\family typewriter
-'help'
-\family default
- (no quotes) to access it.
- You can also type
-\family typewriter
-help(object)
-\family default
- to obtain information about a given object, and
-\family typewriter
-help('keyword')
-\family default
- for information on a keyword.
- As noted in sec.
-
-\begin_inset LatexCommand \ref{sec:help-access}
-
-\end_inset
-
-, you need to properly configure your environment variable
-\family typewriter
-PYTHONDOCS
-\family default
- for this feature to work correctly.
-\end_layout
-
-\begin_layout Subsection
-\begin_inset LatexCommand \label{sec:dyn-object-info}
-
-\end_inset
-
-Dynamic object information
-\end_layout
-
-\begin_layout Standard
-Typing
-\family typewriter
-?word
-\family default
- or
-\family typewriter
-word?
-\family default
- prints detailed information about an object.
- If certain strings in the object are too long (docstrings, code, etc.) they
- get snipped in the center for brevity.
- This system gives access variable types and values, full source code for
- any object (if available), function prototypes and other useful information.
-\end_layout
-
-\begin_layout Standard
-Typing
-\family typewriter
-??word
-\family default
- or
-\family typewriter
-word??
-\family default
- gives access to the full information without snipping long strings.
- Long strings are sent to the screen through the
-\family typewriter
-less
-\family default
- pager if longer than the screen and printed otherwise.
- On systems lacking the
-\family typewriter
-less
-\family default
- command, IPython uses a very basic internal pager.
-\end_layout
-
-\begin_layout Standard
-The following magic functions are particularly useful for gathering information
- about your working environment.
- You can get more details by typing
-\family typewriter
-%magic
-\family default
- or querying them individually (use
-\family typewriter
-%function_name?
-\family default
- with or without the
-\family typewriter
-%
-\family default
-), this is just a summary:
-\end_layout
-
-\begin_layout List
-\labelwidthstring 00.00.0000
-
-\family typewriter
-\series bold
-%pdoc\InsetSpace ~
-