diff --git a/IPython/ColorANSI.py b/IPython/ColorANSI.py new file mode 100644 index 0000000..420f706 --- /dev/null +++ b/IPython/ColorANSI.py @@ -0,0 +1,155 @@ +# -*- coding: utf-8 -*- +"""Tools for coloring text in ANSI terminals. + +$Id: ColorANSI.py 410 2004-11-04 07:58:17Z fperez $""" + +#***************************************************************************** +# Copyright (C) 2002-2004 Fernando Perez. <fperez@colorado.edu> +# +# Distributed under the terms of the BSD License. The full license is in +# the file COPYING, distributed as part of this software. +#***************************************************************************** + +from IPython import Release +__author__ = '%s <%s>' % Release.authors['Fernando'] +__license__ = Release.license + +__all__ = ['TermColors','InputTermColors','ColorScheme','ColorSchemeTable'] + +import os +from UserDict import UserDict + +from IPython.Struct import Struct + +def make_color_table(in_class): + """Build a set of color attributes in a class. + + Helper function for building the *TermColors classes.""" + + color_templates = ( + ("Black" , "0;30"), + ("Red" , "0;31"), + ("Green" , "0;32"), + ("Brown" , "0;33"), + ("Blue" , "0;34"), + ("Purple" , "0;35"), + ("Cyan" , "0;36"), + ("LightGray" , "0;37"), + ("DarkGray" , "1;30"), + ("LightRed" , "1;31"), + ("LightGreen" , "1;32"), + ("Yellow" , "1;33"), + ("LightBlue" , "1;34"), + ("LightPurple" , "1;35"), + ("LightCyan" , "1;36"), + ("White" , "1;37"), ) + + for name,value in color_templates: + setattr(in_class,name,in_class._base % value) + +class TermColors: + """Color escape sequences. + + This class defines the escape sequences for all the standard (ANSI?) + colors in terminals. Also defines a NoColor escape which is just the null + string, suitable for defining 'dummy' color schemes in terminals which get + confused by color escapes. + + This class should be used as a mixin for building color schemes.""" + + NoColor = '' # for color schemes in color-less terminals. + Normal = '\033[0m' # Reset normal coloring + _base = '\033[%sm' # Template for all other colors + +# Build the actual color table as a set of class attributes: +make_color_table(TermColors) + +class InputTermColors: + """Color escape sequences for input prompts. + + This class is similar to TermColors, but the escapes are wrapped in \001 + and \002 so that readline can properly know the length of each line and + can wrap lines accordingly. Use this class for any colored text which + needs to be used in input prompts, such as in calls to raw_input(). + + This class defines the escape sequences for all the standard (ANSI?) + colors in terminals. Also defines a NoColor escape which is just the null + string, suitable for defining 'dummy' color schemes in terminals which get + confused by color escapes. + + This class should be used as a mixin for building color schemes.""" + + NoColor = '' # for color schemes in color-less terminals. + Normal = '\001\033[0m\002' # Reset normal coloring + _base = '\001\033[%sm\002' # Template for all other colors + +# Build the actual color table as a set of class attributes: +make_color_table(InputTermColors) + +class ColorScheme: + """Generic color scheme class. Just a name and a Struct.""" + def __init__(self,__scheme_name_,colordict=None,**colormap): + self.name = __scheme_name_ + if colordict is None: + self.colors = Struct(**colormap) + else: + self.colors = Struct(colordict) + +class ColorSchemeTable(UserDict): + """General class to handle tables of color schemes. + + It's basically a dict of color schemes with a couple of shorthand + attributes and some convenient methods. + + active_scheme_name -> obvious + active_colors -> actual color table of the active scheme""" + + def __init__(self,scheme_list=None,default_scheme=''): + """Create a table of color schemes. + + The table can be created empty and manually filled or it can be + created with a list of valid color schemes AND the specification for + the default active scheme. + """ + + UserDict.__init__(self) + if scheme_list is None: + self.active_scheme_name = '' + self.active_colors = None + else: + if default_scheme == '': + raise ValueError,'you must specify the default color scheme' + for scheme in scheme_list: + self.add_scheme(scheme) + self.set_active_scheme(default_scheme) + + def add_scheme(self,new_scheme): + """Add a new color scheme to the table.""" + if not isinstance(new_scheme,ColorScheme): + raise ValueError,'ColorSchemeTable only accepts ColorScheme instances' + self[new_scheme.name] = new_scheme + + def set_active_scheme(self,scheme,case_sensitive=0): + """Set the currently active scheme. + + Names are by default compared in a case-insensitive way, but this can + be changed by setting the parameter case_sensitive to true.""" + + scheme_list = self.keys() + if case_sensitive: + valid_schemes = scheme_list + scheme_test = scheme + else: + valid_schemes = [s.lower() for s in scheme_list] + scheme_test = scheme.lower() + try: + scheme_idx = valid_schemes.index(scheme_test) + except ValueError: + raise ValueError,'Unrecognized color scheme: ' + scheme + \ + '\nValid schemes: '+str(scheme_list).replace("'', ",'') + else: + active = scheme_list[scheme_idx] + self.active_scheme_name = active + self.active_colors = self[active].colors + # Now allow using '' as an index for the current active scheme + self[''] = self[active] diff --git a/IPython/ConfigLoader.py b/IPython/ConfigLoader.py new file mode 100644 index 0000000..192a92e --- /dev/null +++ b/IPython/ConfigLoader.py @@ -0,0 +1,116 @@ +# -*- coding: utf-8 -*- +"""Configuration loader + +$Id: ConfigLoader.py 525 2005-02-19 10:53:12Z fperez $""" + +#***************************************************************************** +# Copyright (C) 2001-2004 Fernando Perez. <fperez@colorado.edu> +# +# Distributed under the terms of the BSD License. The full license is in +# the file COPYING, distributed as part of this software. +#***************************************************************************** + +from IPython import Release +__author__ = '%s <%s>' % Release.authors['Fernando'] +__license__ = Release.license + +import os +from pprint import pprint +import exceptions + +from IPython import ultraTB +from IPython.Struct import Struct +from IPython.genutils import * + +class ConfigLoaderError(exceptions.Exception): + """Exception for ConfigLoader class.""" + + def __init__(self,args=None): + self.args = args + +class ConfigLoader: + + """Configuration file loader capable of handling recursive inclusions and + with parametrized conflict resolution for multiply found keys.""" + + def __init__(self,conflict=None,field_sep=None,reclimit=15): + + """The reclimit parameter controls the number of recursive + configuration file inclusions. This way we can stop early on (before + python's own recursion limit is hit) if there is a circular + inclusion. + + - conflict: dictionary for conflict resolutions (see Struct.merge()) + + """ + self.conflict = conflict + self.field_sep = field_sep + self.reset(reclimit) + + def reset(self,reclimit=15): + self.reclimit = reclimit + self.recdepth = 0 + self.included = [] + + def load(self,fname,convert=None,recurse_key='',incpath = '.',**kw): + """Load a configuration file, return the resulting Struct. + + Call: load_config(fname,convert=None,conflict=None,recurse_key='') + + - fname: file to load from. + - convert: dictionary of type conversions (see read_dict()) + - recurse_key: keyword in dictionary to trigger recursive file + inclusions. + """ + + if self.recdepth > self.reclimit: + raise ConfigLoaderError, 'maximum recursive inclusion of rcfiles '+\ + 'exceeded: ' + `self.recdepth` + \ + '.\nMaybe you have a circular chain of inclusions?' + self.recdepth += 1 + fname = filefind(fname,incpath) + data = Struct() + # avoid including the same file more than once + if fname in self.included: + return data + Xinfo = ultraTB.AutoFormattedTB() + if convert==None and recurse_key : convert = {qwflat:recurse_key} + # for production, change warn to 0: + data.merge(read_dict(fname,convert,fs=self.field_sep,strip=1, + warn=0,no_empty=0,**kw)) + # keep track of successfully loaded files + self.included.append(fname) + if recurse_key in data.keys(): + for incfilename in data[recurse_key]: + found=0 + try: + incfile = filefind(incfilename,incpath) + except IOError: + if os.name in ['nt','dos']: + try: + # Try again with '.ini' extension + incfilename += '.ini' + incfile = filefind(incfilename,incpath) + except IOError: + found = 0 + else: + found = 1 + else: + found = 0 + else: + found = 1 + if found: + try: + data.merge(self.load(incfile,convert,recurse_key, + incpath,**kw), + self.conflict) + except: + Xinfo() + warn('Problem loading included file: '+ + `incfilename` + '. Ignoring it...') + else: + warn('File `%s` not found. Included by %s' % (incfilename,fname)) + + return data + +# end ConfigLoader diff --git a/IPython/CrashHandler.py b/IPython/CrashHandler.py new file mode 100644 index 0000000..12acbd6 --- /dev/null +++ b/IPython/CrashHandler.py @@ -0,0 +1,109 @@ +# -*- coding: utf-8 -*- +"""sys.excepthook for IPython itself, leaves a detailed report on disk. + +$Id: CrashHandler.py 410 2004-11-04 07:58:17Z fperez $""" + +#***************************************************************************** +# Copyright (C) 2001-2004 Fernando Perez. <fperez@colorado.edu> +# +# Distributed under the terms of the BSD License. The full license is in +# the file COPYING, distributed as part of this software. +#***************************************************************************** + +from IPython import Release +__author__ = '%s <%s>' % Release.authors['Fernando'] +__license__ = Release.license +__version__ = Release.version + +#**************************************************************************** +# Required modules + +# From the standard library +import os,sys +from pprint import pprint,pformat + +# Homebrewed +from IPython.genutils import * +from IPython.Itpl import Itpl,itpl,printpl +from IPython import ultraTB +from IPython.ultraTB import ColorScheme,ColorSchemeTable # too long names + +#**************************************************************************** +class CrashHandler: + """sys.excepthook for IPython itself, leaves a detailed report on disk.""" + + def __init__(self,IP): + self.IP = IP # IPython instance + self.bug_contact = Release.authors['Fernando'][0] + self.mailto = Release.authors['Fernando'][1] + + def __call__(self,etype, evalue, etb): + + # Report tracebacks shouldn't use color in general (safer for users) + color_scheme = 'NoColor' + + # Use this ONLY for developer debugging (keep commented out for release) + #color_scheme = 'Linux' # dbg + + try: + rptdir = self.IP.rc.ipythondir + except: + rptdir = os.getcwd() + if not os.path.isdir(rptdir): + rptdir = os.getcwd() + self.report_name = os.path.join(rptdir,'IPython_crash_report.txt') + self.TBhandler = ultraTB.VerboseTB(color_scheme=color_scheme,long_header=1) + traceback = self.TBhandler.text(etype,evalue,etb,context=31) + + # print traceback to screen + print >> sys.stderr, traceback + + # and generate a complete report on disk + try: + report = open(self.report_name,'w') + except: + print >> sys.stderr, 'Could not create crash report on disk.' + return + + msg = itpl('\n'+'*'*70+'\n' +""" +Oops, IPython crashed. We do our best to make it stable, but... + +A crash report was automatically generated with the following information: + - A verbatim copy of the traceback above this text. + - A copy of your input history during this session. + - Data on your current IPython configuration. + +It was left in the file named: +\t'$self.report_name' +If you can email this file to the developers, the information in it will help +them in understanding and correcting the problem. + +You can mail it to $self.bug_contact at $self.mailto +with the subject 'IPython Crash Report'. + +If you want to do it now, the following command will work (under Unix): +mail -s 'IPython Crash Report' $self.mailto < $self.report_name + +To ensure accurate tracking of this issue, please file a report about it at: +http://www.scipy.net/roundup/ipython (IPython's online bug tracker). +""") + print >> sys.stderr, msg + + sec_sep = '\n\n'+'*'*75+'\n\n' + report.write('*'*75+'\n\n'+'IPython post-mortem report\n\n') + report.write('IPython version: %s \n\n' % __version__) + report.write('Platform info : os.name -> %s, sys.platform -> %s' % + (os.name,sys.platform) ) + report.write(sec_sep+'Current user configuration structure:\n\n') + report.write(pformat(self.IP.rc.dict())) + report.write(sec_sep+'Crash traceback:\n\n' + traceback) + try: + report.write(sec_sep+"History of session input:") + for line in self.IP.user_ns['_ih']: + report.write(line) + report.write('\n*** Last line of input (may not be in above history):\n') + report.write(self.IP._last_input_line+'\n') + except: + pass + report.close() diff --git a/IPython/DPyGetOpt.py b/IPython/DPyGetOpt.py new file mode 100644 index 0000000..75a7461 --- /dev/null +++ b/IPython/DPyGetOpt.py @@ -0,0 +1,671 @@ +# -*- coding: utf-8 -*- +"""DPyGetOpt -- Demiurge Python GetOptions Module + + $Id: DPyGetOpt.py 389 2004-10-09 07:59:30Z fperez $ + +This module is modeled after perl's Getopt::Long module-- which +is, in turn, modeled after GNU's extended getopt() function. + +Upon instantiation, the option specification should be a sequence +(list) of option definitions. + +Options that take no arguments should simply contain the name of +the option. If a ! is post-pended, the option can be negated by +prepending 'no'; ie 'debug!' specifies that -debug and -nodebug +should be accepted. + +Mandatory arguments to options are specified using a postpended +'=' + a type specifier. '=s' specifies a mandatory string +argument, '=i' specifies a mandatory integer argument, and '=f' +specifies a mandatory real number. In all cases, the '=' can be +substituted with ':' to specify that the argument is optional. + +Dashes '-' in option names are allowed. + +If an option has the character '@' postpended (after the +argumentation specification), it can appear multiple times within +each argument list that is processed. The results will be stored +in a list. + +The option name can actually be a list of names separated by '|' +characters; ie-- 'foo|bar|baz=f@' specifies that all -foo, -bar, +and -baz options that appear on within the parsed argument list +must have a real number argument and that the accumulated list +of values will be available under the name 'foo' + +$Id: DPyGetOpt.py 389 2004-10-09 07:59:30Z fperez $""" + +#***************************************************************************** +# +# Copyright (c) 2001 Bill Bumgarner <bbum@friday.com> +# +# +# Published under the terms of the MIT license, hereby reproduced: +# +# Permission is hereby granted, free of charge, to any person obtaining a copy +# of this software and associated documentation files (the "Software"), to +# deal in the Software without restriction, including without limitation the +# rights to use, copy, modify, merge, publish, distribute, sublicense, and/or +# sell copies of the Software, and to permit persons to whom the Software is +# furnished to do so, subject to the following conditions: +# +# The above copyright notice and this permission notice shall be included in +# all copies or substantial portions of the Software. +# +# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING +# FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS +# IN THE SOFTWARE. +# +#***************************************************************************** + +__author__ = 'Bill Bumgarner <bbum@friday.com>' +__license__ = 'MIT' +__version__ = '1.2' + +# Modified to use re instead of regex and regsub modules. +# 2001/5/7, Jonathan Hogg <jonathan@onegoodidea.com> + +import string +import re +import sys +import types + +arg_error = 'DPyGetOpt Argument Error' +spec_error = 'DPyGetOpt Specification Error' +term_error = 'DPyGetOpt Termination Error' + +specificationExpr = re.compile('(?P<required>.)(?P<type>.)(?P<multi>@?)') + +ArgRequired = 'Requires an Argument' +ArgOptional = 'Argument Optional' + +# The types modules is not used for these identifiers because there +# is no identifier for 'boolean' or 'generic' +StringArgType = 'String Argument Type' +IntegerArgType = 'Integer Argument Type' +RealArgType = 'Real Argument Type' +BooleanArgType = 'Boolean Argument Type' +GenericArgType = 'Generic Argument Type' + +# dictionary of conversion functions-- boolean and generic options +# do not accept arguments and do not need conversion functions; +# the identity function is used purely for convenience. +ConversionFunctions = { + StringArgType : lambda x: x, + IntegerArgType : string.atoi, + RealArgType : string.atof, + BooleanArgType : lambda x: x, + GenericArgType : lambda x: x, + } + +class DPyGetOpt: + + def __init__(self, spec = None, terminators = ['--']): + """ + Declare and intialize instance variables + + Yes, declaration is not necessary... but one of the things + I sorely miss from C/Obj-C is the concept of having an + interface definition that clearly declares all instance + variables and methods without providing any implementation + details. it is a useful reference! + + all instance variables are initialized to 0/Null/None of + the appropriate type-- not even the default value... + """ + +# sys.stderr.write(string.join(spec) + "\n") + + self.allowAbbreviations = 1 # boolean, 1 if abbreviations will + # be expanded + self.freeValues = [] # list, contains free values + self.ignoreCase = 0 # boolean, YES if ignoring case + self.needsParse = 0 # boolean, YES if need to reparse parameter spec + self.optionNames = {} # dict, all option names-- value is index of tuple + self.optionStartExpr = None # regexp defining the start of an option (ie; '-', '--') + self.optionTuples = [] # list o' tuples containing defn of options AND aliases + self.optionValues = {} # dict, option names (after alias expansion) -> option value(s) + self.orderMixed = 0 # boolean, YES if options can be mixed with args + self.posixCompliance = 0 # boolean, YES indicates posix like behaviour + self.spec = [] # list, raw specs (in case it must be reparsed) + self.terminators = terminators # list, strings that terminate argument processing + self.termValues = [] # list, values after terminator + self.terminator = None # full name of terminator that ended + # option processing + + # set up defaults + self.setPosixCompliance() + self.setIgnoreCase() + self.setAllowAbbreviations() + + # parse spec-- if present + if spec: + self.parseConfiguration(spec) + + def setPosixCompliance(self, aFlag = 0): + """ + Enables and disables posix compliance. + + When enabled, '+' can be used as an option prefix and free + values can be mixed with options. + """ + self.posixCompliance = aFlag + self.needsParse = 1 + + if self.posixCompliance: + self.optionStartExpr = re.compile('(--|-)(?P<option>[A-Za-z0-9_-]+)(?P<arg>=.*)?') + self.orderMixed = 0 + else: + self.optionStartExpr = re.compile('(--|-|\+)(?P<option>[A-Za-z0-9_-]+)(?P<arg>=.*)?') + self.orderMixed = 1 + + def isPosixCompliant(self): + """ + Returns the value of the posix compliance flag. + """ + return self.posixCompliance + + def setIgnoreCase(self, aFlag = 1): + """ + Enables and disables ignoring case during option processing. + """ + self.needsParse = 1 + self.ignoreCase = aFlag + + def ignoreCase(self): + """ + Returns 1 if the option processor will ignore case when + processing options. + """ + return self.ignoreCase + + def setAllowAbbreviations(self, aFlag = 1): + """ + Enables and disables the expansion of abbreviations during + option processing. + """ + self.allowAbbreviations = aFlag + + def willAllowAbbreviations(self): + """ + Returns 1 if abbreviated options will be automatically + expanded to the non-abbreviated form (instead of causing an + unrecognized option error). + """ + return self.allowAbbreviations + + def addTerminator(self, newTerm): + """ + Adds newTerm as terminator of option processing. + + Whenever the option processor encounters one of the terminators + during option processing, the processing of options terminates + immediately, all remaining options are stored in the termValues + instance variable and the full name of the terminator is stored + in the terminator instance variable. + """ + self.terminators = self.terminators + [newTerm] + + def _addOption(self, oTuple): + """ + Adds the option described by oTuple (name, (type, mode, + default), alias) to optionTuples. Adds index keyed under name + to optionNames. Raises spec_error if name already in + optionNames + """ + (name, (type, mode, default, multi), realName) = oTuple + + # verify name and add to option names dictionary + if self.optionNames.has_key(name): + if realName: + raise spec_error, 'Alias \'' + name + '\' for \'' + realName + \ + '\' already used for another option or alias.' + else: + raise spec_error, 'Option named \'' + name + \ + '\' specified more than once. Specification: ' + option + + # validated. add to optionNames + self.optionNames[name] = self.tupleIndex + self.tupleIndex = self.tupleIndex + 1 + + # add to optionTuples + self.optionTuples = self.optionTuples + [oTuple] + + # if type is boolean, add negation + if type == BooleanArgType: + alias = 'no' + name + specTuple = (type, mode, 0, multi) + oTuple = (alias, specTuple, name) + + # verify name and add to option names dictionary + if self.optionNames.has_key(alias): + if realName: + raise spec_error, 'Negated alias \'' + name + '\' for \'' + realName + \ + '\' already used for another option or alias.' + else: + raise spec_error, 'Negated option named \'' + name + \ + '\' specified more than once. Specification: ' + option + + # validated. add to optionNames + self.optionNames[alias] = self.tupleIndex + self.tupleIndex = self.tupleIndex + 1 + + # add to optionTuples + self.optionTuples = self.optionTuples + [oTuple] + + def addOptionConfigurationTuple(self, oTuple): + (name, argSpec, realName) = oTuple + if self.ignoreCase: + name = string.lower(name) + if realName: + realName = string.lower(realName) + else: + realName = name + + oTuple = (name, argSpec, realName) + + # add option + self._addOption(oTuple) + + def addOptionConfigurationTuples(self, oTuple): + if type(oTuple) is ListType: + for t in oTuple: + self.addOptionConfigurationTuple(t) + else: + self.addOptionConfigurationTuple(oTuple) + + def parseConfiguration(self, spec): + # destroy previous stored information + store raw spec + self.spec = spec + self.optionTuples = [] + self.optionNames = {} + self.tupleIndex = 0 + + tupleIndex = 0 + + # create some regex's for parsing each spec + splitExpr = \ + re.compile('(?P<names>\w+[-A-Za-z0-9|]*)?(?P<spec>!|[=:][infs]@?)?') + for option in spec: + # push to lower case (does not negatively affect + # specification) + if self.ignoreCase: + option = string.lower(option) + + # break into names, specification + match = splitExpr.match(option) + if match is None: + raise spec_error, 'Invalid specification {' + option + '}' + + names = match.group('names') + specification = match.group('spec') + + # break name into name, aliases + nlist = string.split(names, '|') + + # get name + name = nlist[0] + aliases = nlist[1:] + + # specificationExpr = regex.symcomp('\(<required>.\)\(<type>.\)\(<multi>@?\)') + if not specification: + #spec tuple is ('type', 'arg mode', 'default value', 'multiple') + argType = GenericArgType + argMode = None + argDefault = 1 + argMultiple = 0 + elif specification == '!': + argType = BooleanArgType + argMode = None + argDefault = 1 + argMultiple = 0 + else: + # parse + match = specificationExpr.match(specification) + if match is None: + # failed to parse, die + raise spec_error, 'Invalid configuration for option \'' + option + '\'' + + # determine mode + required = match.group('required') + if required == '=': + argMode = ArgRequired + elif required == ':': + argMode = ArgOptional + else: + raise spec_error, 'Unknown requirement configuration \'' + required + '\'' + + # determine type + type = match.group('type') + if type == 's': + argType = StringArgType + argDefault = '' + elif type == 'i': + argType = IntegerArgType + argDefault = 1 + elif type == 'f' or type == 'n': + argType = RealArgType + argDefault = 1 + else: + raise spec_error, 'Unknown type specifier \'' + type + '\'' + + # determine quantity + if match.group('multi') == '@': + argMultiple = 1 + else: + argMultiple = 0 + ## end else (of not specification) + + # construct specification tuple + specTuple = (argType, argMode, argDefault, argMultiple) + + # add the option-- option tuple is (name, specTuple, real name) + oTuple = (name, specTuple, name) + self._addOption(oTuple) + + for alias in aliases: + # drop to all lower (if configured to do so) + if self.ignoreCase: + alias = string.lower(alias) + # create configuration tuple + oTuple = (alias, specTuple, name) + # add + self._addOption(oTuple) + + # successfully parsed.... + self.needsParse = 0 + + def _getArgTuple(self, argName): + """ + Returns a list containing all the specification tuples that + match argName. If none match, None is returned. If one + matches, a list with one tuple is returned. If more than one + match, a list containing all the tuples that matched is + returned. + + In other words, this function does not pass judgement upon the + validity of multiple matches. + """ + # is it in the optionNames dict? + + try: +# sys.stderr.write(argName + string.join(self.optionNames.keys()) + "\n") + + # yes, get index + tupleIndex = self.optionNames[argName] + # and return tuple as element of list + return [self.optionTuples[tupleIndex]] + except KeyError: + # are abbreviations allowed? + if not self.allowAbbreviations: + # No! terefore, this cannot be valid argument-- nothing found + return None + + # argName might be an abbreviation (and, abbreviations must + # be allowed... or this would not have been reached!) + + # create regex for argName + argExpr = re.compile('^' + argName) + + tuples = filter(lambda x, argExpr=argExpr: argExpr.search(x[0]) is not None, + self.optionTuples) + + if not len(tuples): + return None + else: + return tuples + + def _isTerminator(self, optionName): + """ + Returns the full name of the terminator if optionName is a valid + terminator. If it is, sets self.terminator to the full name of + the terminator. + + If more than one terminator matched, raises a term_error with a + string describing the ambiguity. + """ + +# sys.stderr.write(optionName + "\n") +# sys.stderr.write(repr(self.terminators)) + + if optionName in self.terminators: + self.terminator = optionName + elif not self.allowAbbreviations: + return None + +# regex thing in bogus +# termExpr = regex.compile('^' + optionName) + + terms = filter(lambda x, on=optionName: string.find(x,on) == 0, self.terminators) + + if not len(terms): + return None + elif len(terms) > 1: + raise term_error, 'Ambiguous terminator \'' + optionName + \ + '\' matches ' + repr(terms) + + self.terminator = terms[0] + return self.terminator + + def processArguments(self, args = None): + """ + Processes args, a list of arguments (including options). + + If args is the same as sys.argv, automatically trims the first + argument (the executable name/path). + + If an exception is not raised, the argument list was parsed + correctly. + + Upon successful completion, the freeValues instance variable + will contain all the arguments that were not associated with an + option in the order they were encountered. optionValues is a + dictionary containing the value of each option-- the method + valueForOption() can be used to query this dictionary. + terminator will contain the argument encountered that terminated + option processing (or None, if a terminator was never + encountered) and termValues will contain all of the options that + appeared after the Terminator (or an empty list). + """ + + if hasattr(sys, "argv") and args == sys.argv: + args = sys.argv[1:] + + max = len(args) # maximum index + 1 + self.freeValues = [] # array to hold return values + self.optionValues= {} + index = 0 # initial index + self.terminator = None + self.termValues = [] + + while index < max: + # obtain argument + arg = args[index] + # increment index -- REMEMBER; it is NOW incremented + index = index + 1 + + # terminate immediately if option terminator encountered + if self._isTerminator(arg): + self.freeValues = self.freeValues + args[index:] + self.termValues = args[index:] + return + + # is this possibly an option? + match = self.optionStartExpr.match(arg) + if match is None: + # not an option-- add to freeValues + self.freeValues = self.freeValues + [arg] + if not self.orderMixed: + # mixing not allowed; add rest of args as freeValues + self.freeValues = self.freeValues + args[index:] + # return to caller + return + else: + continue + + # grab name + optName = match.group('option') + + # obtain next argument-- index has already been incremented + nextArg = match.group('arg') + if nextArg: + nextArg = nextArg[1:] + index = index - 1 # put it back + else: + try: + nextArg = args[index] + except: + nextArg = None + + # transpose to lower case, if necessary + if self.ignoreCase: + optName = string.lower(optName) + + # obtain defining tuple + tuples = self._getArgTuple(optName) + + if tuples == None: + raise arg_error, 'Illegal option \'' + arg + '\'' + elif len(tuples) > 1: + raise arg_error, 'Ambiguous option \'' + arg + '\'; matches ' + \ + repr(map(lambda x: x[0], tuples)) + else: + config = tuples[0] + + # config is now set to the configuration tuple for the + # argument + (fullName, spec, realName) = config + (optType, optMode, optDefault, optMultiple) = spec + + # if opt mode required, but nextArg is none, raise an error + if (optMode == ArgRequired): + if (not nextArg) or self._isTerminator(nextArg): +# print nextArg + raise arg_error, 'Option \'' + arg + \ + '\' requires an argument of type ' + optType + + if (not optMode == None) and nextArg and (not self._isTerminator(nextArg)): + # nextArg defined, option configured to possibly consume arg + try: + # grab conversion function-- the try is more for internal diagnostics + func = ConversionFunctions[optType] + try: + optionValue = func(nextArg) + index = index + 1 + except: + # only raise conversion error if REQUIRED to consume argument + if optMode == ArgRequired: + raise arg_error, 'Invalid argument to option \'' + arg + \ + '\'; should be \'' + optType + '\'' + else: + optionValue = optDefault + except arg_error: + raise arg_error, sys.exc_value + except: + raise arg_error, '(' + arg + \ + ') Conversion function for \'' + optType + '\' not found.' + else: + optionValue = optDefault + + # add value to options dictionary + if optMultiple: + # can be multiple values + try: + # try to append element + self.optionValues[realName] = self.optionValues[realName] + [optionValue] + except: + # failed-- must not exist; add it + self.optionValues[realName] = [optionValue] + else: + # only one value per + if self.isPosixCompliant and self.optionValues.has_key(realName): + raise arg_error, 'Argument \'' + arg + '\' occurs multiple times.' + + self.optionValues[realName] = optionValue + + def valueForOption(self, optionName, defaultValue = None): + """ + Return the value associated with optionName. If optionName was + not encountered during parsing of the arguments, returns the + defaultValue (which defaults to None). + """ + try: + optionValue = self.optionValues[optionName] + except: + optionValue = defaultValue + + return optionValue + +## +## test/example section +## +test_error = 'Test Run Amok!' +def _test(): + """ + A relatively complete test suite. + """ + try: + DPyGetOpt(['foo', 'bar=s', 'foo']) + except: + print 'EXCEPTION (should be \'foo\' already used..): ' + sys.exc_value + + try: + DPyGetOpt(['foo|bar|apple=s@', 'baz|apple!']) + except: + print 'EXCEPTION (should be duplicate alias/name error): ' + sys.exc_value + + x = DPyGetOpt(['apple|atlas=i@', 'application|executable=f@']) + try: + x.processArguments(['-app', '29.3']) + except: + print 'EXCEPTION (should be ambiguous argument): ' + sys.exc_value + + x = DPyGetOpt(['foo'], ['antigravity', 'antithesis']) + try: + x.processArguments(['-foo', 'anti']) + except: + print 'EXCEPTION (should be ambiguous terminator): ' + sys.exc_value + + profile = ['plain-option', + 'boolean-option!', + 'list-of-integers=i@', + 'list-real-option|list-real-alias|list-real-pseudonym=f@', + 'optional-string-option:s', + 'abbreviated-string-list=s@'] + + terminators = ['terminator'] + + args = ['-plain-option', + '+noboolean-option', + '--list-of-integers', '1', + '+list-of-integers', '2', + '-list-of-integers', '3', + 'freeargone', + '-list-real-option', '1.1', + '+list-real-alias', '1.2', + '--list-real-pseudonym', '1.3', + 'freeargtwo', + '-abbreviated-string-list', 'String1', + '--abbreviated-s', 'String2', + '-abbrev', 'String3', + '-a', 'String4', + '-optional-string-option', + 'term', + 'next option should look like an invalid arg', + '-a'] + + + print 'Using profile: ' + repr(profile) + print 'With terminator: ' + repr(terminators) + print 'Processing arguments: ' + repr(args) + + go = DPyGetOpt(profile, terminators) + go.processArguments(args) + + print 'Options (and values): ' + repr(go.optionValues) + print 'free args: ' + repr(go.freeValues) + print 'term args: ' + repr(go.termValues) diff --git a/IPython/Debugger.py b/IPython/Debugger.py new file mode 100644 index 0000000..5a030bc --- /dev/null +++ b/IPython/Debugger.py @@ -0,0 +1,53 @@ +# -*- coding: utf-8 -*- +""" +Pdb debugger class. + +Modified from the standard pdb.Pdb class to avoid including readline, so that +the command line completion of other programs which include this isn't +damaged. + +In the future, this class will be expanded with improvements over the standard +pdb. + +The code in this file is mainly lifted out of cmd.py in Python 2.2, with minor +changes. Licensing should therefore be under the standard Python terms. For +details on the PSF (Python Software Foundation) standard license, see: + +http://www.python.org/2.2.3/license.html + +$Id: Debugger.py 590 2005-05-30 06:26:51Z fperez $""" + +from IPython import Release +__author__ = '%s <%s>' % Release.authors['Fernando'] +__license__ = 'Python' + +import pdb,bdb,cmd,os,sys + +class Pdb(pdb.Pdb): + """Modified Pdb class, does not load readline.""" + def __init__(self): + bdb.Bdb.__init__(self) + cmd.Cmd.__init__(self,completekey=None) # don't load readline + self.prompt = '(Pdb) ' + self.aliases = {} + + # Read $HOME/.pdbrc and ./.pdbrc + self.rcLines = [] + if os.environ.has_key('HOME'): + envHome = os.environ['HOME'] + try: + rcFile = open(os.path.join(envHome, ".pdbrc")) + except IOError: + pass + else: + for line in rcFile.readlines(): + self.rcLines.append(line) + rcFile.close() + try: + rcFile = open(".pdbrc") + except IOError: + pass + else: + for line in rcFile.readlines(): + self.rcLines.append(line) + rcFile.close() diff --git a/IPython/Extensions/InterpreterExec.py b/IPython/Extensions/InterpreterExec.py new file mode 100644 index 0000000..f4fb63a --- /dev/null +++ b/IPython/Extensions/InterpreterExec.py @@ -0,0 +1,270 @@ +# -*- coding: utf-8 -*- +"""Modified input prompt for executing files. + +We define a special input line filter to allow typing lines which begin with +'~', '/' or '.'. If one of those strings is encountered, it is automatically +executed. + +$Id: InterpreterExec.py 573 2005-04-08 08:38:09Z fperez $""" + +#***************************************************************************** +# Copyright (C) 2004 W.J. van der Laan <gnufnork@hetdigitalegat.nl> +# Copyright (C) 2004 Fernando Perez <fperez@colorado.edu> +# +# Distributed under the terms of the BSD License. The full license is in +# the file COPYING, distributed as part of this software. +#***************************************************************************** + +from IPython import Release +__author__ = 'W.J. van der Laan <gnufnork@hetdigitalegat.nl>, '\ + '%s <%s>' % Release.authors['Fernando'] +__license__ = Release.license + +def prefilter_shell(self,line,continuation): + """Alternate prefilter, modified for shell-like functionality. + + - Execute all lines beginning with '~', '/' or '.' + - $var=cmd <=> %sc var=cmd + - $$var=cmd <=> %sc -l var=cmd + """ + + if line: + l0 = line[0] + if l0 in '~/.': + return self._prefilter("!%s"%line,continuation) + elif l0=='$': + lrest = line[1:] + if lrest.startswith('$'): + # $$var=cmd <=> %sc -l var=cmd + return self._prefilter("%ssc -l %s" % (self.ESC_MAGIC,lrest[1:]), + continuation) + else: + # $var=cmd <=> %sc var=cmd + return self._prefilter("%ssc %s" % (self.ESC_MAGIC,lrest), + continuation) + else: + return self._prefilter(line,continuation) + else: + return self._prefilter(line,continuation) + +# Rebind this to be the new IPython prefilter: +from IPython.iplib import InteractiveShell +InteractiveShell.prefilter = prefilter_shell +# Clean up the namespace. +del InteractiveShell,prefilter_shell + +# Provide pysh and further shell-oriented services +import os,sys,shutil +from IPython.genutils import system,shell,getoutput,getoutputerror + +# Short aliases for getting shell output as a string and a list +sout = getoutput +lout = lambda cmd: getoutput(cmd,split=1) + +# Empty function, meant as a docstring holder so help(pysh) works. +def pysh(): + """Pysh is a set of modules and extensions to IPython which make shell-like + usage with Python syntax more convenient. Keep in mind that pysh is NOT a + full-blown shell, so don't try to make it your /etc/passwd entry! + + In particular, it has no job control, so if you type Ctrl-Z (under Unix), + you'll suspend pysh itself, not the process you just started. + + Since pysh is really nothing but a customized IPython, you should + familiarize yourself with IPython's features. This brief help mainly + documents areas in which pysh differs from the normal IPython. + + ALIASES + ------- + All of your $PATH has been loaded as IPython aliases, so you should be + able to type any normal system command and have it executed. See %alias? + and %unalias? for details on the alias facilities. + + SPECIAL SYNTAX + -------------- + Any lines which begin with '~', '/' and '.' will be executed as shell + commands instead of as Python code. The special escapes below are also + recognized. !cmd is valid in single or multi-line input, all others are + only valid in single-line input: + + !cmd - pass 'cmd' directly to the shell + !!cmd - execute 'cmd' and return output as a list (split on '\\n') + $var=cmd - capture output of cmd into var, as a string + $$var=cmd - capture output of cmd into var, as a list (split on '\\n') + + The $/$$ syntaxes make Python variables from system output, which you can + later use for further scripting. The converse is also possible: when + executing an alias or calling to the system via !/!!, you can expand any + python variable or expression by prepending it with $. Full details of + the allowed syntax can be found in Python's PEP 215. + + A few brief examples will illustrate these: + + fperez[~/test]|3> !ls *s.py + scopes.py strings.py + + ls is an internal alias, so there's no need to use !: + fperez[~/test]|4> ls *s.py + scopes.py* strings.py + + !!ls will return the output into a Python variable: + fperez[~/test]|5> !!ls *s.py + <5> ['scopes.py', 'strings.py'] + fperez[~/test]|6> print _5 + ['scopes.py', 'strings.py'] + + $ and $$ allow direct capture to named variables: + fperez[~/test]|7> $astr = ls *s.py + fperez[~/test]|8> astr + <8> 'scopes.py\\nstrings.py' + + fperez[~/test]|9> $$alist = ls *s.py + fperez[~/test]|10> alist + <10> ['scopes.py', 'strings.py'] + + alist is now a normal python list you can loop over. Using $ will expand + back the python values when alias calls are made: + fperez[~/test]|11> for f in alist: + |..> print 'file',f, + |..> wc -l $f + |..> + file scopes.py 13 scopes.py + file strings.py 4 strings.py + + Note that you may need to protect your variables with braces if you want + to append strings to their names. To copy all files in alist to .bak + extensions, you must use: + fperez[~/test]|12> for f in alist: + |..> cp $f ${f}.bak + + If you try using $f.bak, you'll get an AttributeError exception saying + that your string object doesn't have a .bak attribute. This is because + the $ expansion mechanism allows you to expand full Python expressions: + fperez[~/test]|13> echo "sys.platform is: $sys.platform" + sys.platform is: linux2 + + IPython's input history handling is still active, which allows you to + rerun a single block of multi-line input by simply using exec: + fperez[~/test]|14> $$alist = ls *.eps + fperez[~/test]|15> exec _i11 + file image2.eps 921 image2.eps + file image.eps 921 image.eps + + While these are new special-case syntaxes, they are designed to allow very + efficient use of the shell with minimal typing. At an interactive shell + prompt, conciseness of expression wins over readability. + + USEFUL FUNCTIONS AND MODULES + ---------------------------- + The os, sys and shutil modules from the Python standard library are + automatically loaded. Some additional functions, useful for shell usage, + are listed below. You can request more help about them with '?'. + + shell - execute a command in the underlying system shell + system - like shell(), but return the exit status of the command + sout - capture the output of a command as a string + lout - capture the output of a command as a list (split on '\\n') + getoutputerror - capture (output,error) of a shell command + + sout/lout are the functional equivalents of $/$$. They are provided to + allow you to capture system output in the middle of true python code, + function definitions, etc (where $ and $$ are invalid). + + DIRECTORY MANAGEMENT + -------------------- + Since each command passed by pysh to the underlying system is executed in + a subshell which exits immediately, you can NOT use !cd to navigate the + filesystem. + + Pysh provides its own builtin '%cd' magic command to move in the + filesystem (the % is not required with automagic on). It also maintains a + list of visited directories (use %dhist to see it) and allows direct + switching to any of them. Type 'cd?' for more details. + + %pushd, %popd and %dirs are provided for directory stack handling. + + PROMPT CUSTOMIZATION + -------------------- + + The supplied ipythonrc-pysh profile comes with an example of a very + colored and detailed prompt, mainly to serve as an illustration. The + valid escape sequences, besides color names, are: + + \\# - Prompt number. + \\D - Dots, as many as there are digits in \\# (so they align). + \\w - Current working directory (cwd). + \\W - Basename of current working directory. + \\XN - Where N=0..5. N terms of the cwd, with $HOME written as ~. + \\YN - Where N=0..5. Like XN, but if ~ is term N+1 it's also shown. + \\u - Username. + \\H - Full hostname. + \\h - Hostname up to first '.' + \\$ - Root symbol ($ or #). + \\t - Current time, in H:M:S format. + \\v - IPython release version. + \\n - Newline. + \\r - Carriage return. + \\\\ - An explicitly escaped '\\'. + + You can configure your prompt colors using any ANSI color escape. Each + color escape sets the color for any subsequent text, until another escape + comes in and changes things. The valid color escapes are: + + \\C_Black + \\C_Blue + \\C_Brown + \\C_Cyan + \\C_DarkGray + \\C_Green + \\C_LightBlue + \\C_LightCyan + \\C_LightGray + \\C_LightGreen + \\C_LightPurple + \\C_LightRed + \\C_Purple + \\C_Red + \\C_White + \\C_Yellow + \\C_Normal - Stop coloring, defaults to your terminal settings. + """ + pass + +# Configure a few things. Much of this is fairly hackish, since IPython +# doesn't really expose a clean API for it. Be careful if you start making +# many modifications here. + +print """\ +Welcome to pysh, a set of extensions to IPython for shell usage. +help(pysh) -> help on the installed shell extensions and syntax. +""" + +# Set the 'cd' command to quiet mode, a more shell-like behavior +__IPYTHON__.default_option('cd','-q') + +# Load all of $PATH as aliases +if os.name == 'posix': + # %rehash is very fast, but it doesn't check for executability, it simply + # dumps everything in $PATH as an alias. Use rehashx if you want more + # checks. + __IPYTHON__.magic_rehash() +else: + # Windows users: the list of extensions considered executable is read from + # the environment variable 'pathext'. If this is undefined, IPython + # defaults to EXE, COM and BAT. + # %rehashx is the one which does extension analysis, at the cost of + # being much slower than %rehash. + __IPYTHON__.magic_rehashx() + +# Remove %sc,%sx if present as aliases +__IPYTHON__.magic_unalias('sc') +__IPYTHON__.magic_unalias('sx') + +# We need different criteria for line-splitting, so that aliases such as +# 'gnome-terminal' are interpreted as a single alias instead of variable +# 'gnome' minus variable 'terminal'. +import re +__IPYTHON__.line_split = re.compile(r'^(\s*)([\?\w\.\-\+]+\w*\s*)(\(?.*$)') + +# Namespace cleanup +del re diff --git a/IPython/Extensions/InterpreterPasteInput.py b/IPython/Extensions/InterpreterPasteInput.py new file mode 100644 index 0000000..fb325fe --- /dev/null +++ b/IPython/Extensions/InterpreterPasteInput.py @@ -0,0 +1,91 @@ +# -*- coding: utf-8 -*- +"""Modified input prompt for entering text with >>> or ... at the start. + +We define a special input line filter to allow typing lines which begin with +'>>> ' or '... '. These two strings, if present at the start of the input +line, are stripped. This allows for direct pasting of code from examples such +as those available in the standard Python tutorial. + +Normally pasting such code is one chunk is impossible because of the +extraneous >>> and ..., requiring one to do a line by line paste with careful +removal of those characters. This module allows pasting that kind of +multi-line examples in one pass. + +Here is an 'screenshot' of a section of the tutorial pasted into IPython with +this feature enabled: + +In [1]: >>> def fib2(n): # return Fibonacci series up to n + ...: ... '''Return a list containing the Fibonacci series up to n.''' + ...: ... result = [] + ...: ... a, b = 0, 1 + ...: ... while b < n: + ...: ... result.append(b) # see below + ...: ... a, b = b, a+b + ...: ... return result + ...: + +In [2]: fib2(10) +Out[2]: [1, 1, 2, 3, 5, 8] + +The >>> and ... are stripped from the input so that the python interpreter +only sees the real part of the code. + +All other input is processed normally. +""" +#***************************************************************************** +# Copyright (C) 2001-2004 Fernando Perez <fperez@colorado.edu> +# +# Distributed under the terms of the BSD License. The full license is in +# the file COPYING, distributed as part of this software. +#***************************************************************************** + +from IPython import Release +__author__ = '%s <%s>' % Release.authors['Fernando'] +__license__ = Release.license + +# This file is an example of how to modify IPython's line-processing behavior +# without touching the internal code. We'll define an alternate pre-processing +# stage which allows a special form of input (which is invalid Python syntax) +# for certain quantities, rewrites a line of proper Python in those cases, and +# then passes it off to IPython's normal processor for further work. + +# With this kind of customization, IPython can be adapted for many +# special-purpose scenarios providing alternate input syntaxes. + +# This file can be imported like a regular module. + +# IPython has a prefilter() function that analyzes each input line. We redefine +# it here to first pre-process certain forms of input + +# The prototype of any alternate prefilter must be like this one (the name +# doesn't matter): +# - line is a string containing the user input line. +# - continuation is a parameter which tells us if we are processing a first line of +# user input or the second or higher of a multi-line statement. + +def prefilter_paste(self,line,continuation): + """Alternate prefilter for input of pasted code from an interpreter. + """ + + from re import match + + if match(r'^>>> |^\.\.\. ',line): + # In the end, always call the default IPython _prefilter() function. + # Note that self must be passed explicitly, b/c we're calling the + # unbound class method (since this method will overwrite the instance + # prefilter()) + return self._prefilter(line[4:],continuation) + elif line.strip() == '...': + return self._prefilter('',continuation) + else: + return self._prefilter(line,continuation) + +# Rebind this to be the new IPython prefilter: +from IPython.iplib import InteractiveShell +InteractiveShell.prefilter = prefilter_paste + +# Clean up the namespace. +del InteractiveShell,prefilter_paste + +# Just a heads up at the console +print '*** Pasting of code with ">>>" or "..." has been enabled.' diff --git a/IPython/Extensions/PhysicalQInput.py b/IPython/Extensions/PhysicalQInput.py new file mode 100644 index 0000000..c8d4929 --- /dev/null +++ b/IPython/Extensions/PhysicalQInput.py @@ -0,0 +1,83 @@ +# -*- coding: utf-8 -*- +"""Modified input prompt for entering quantities with units. + +Modify the behavior of the interactive interpreter to allow direct input of +quantities with units without having to make a function call. + +Now the following forms are accepted: + +x = 4 m +y = -.45e3 m/s +g = 9.8 m/s**2 +a = 2.3 m/s^2 # ^ -> ** automatically + +All other input is processed normally. +""" +#***************************************************************************** +# Copyright (C) 2001-2004 Fernando Perez <fperez@colorado.edu> +# +# Distributed under the terms of the BSD License. The full license is in +# the file COPYING, distributed as part of this software. +#***************************************************************************** + +from IPython import Release +__author__ = '%s <%s>' % Release.authors['Fernando'] +__license__ = Release.license + +# This file is an example of how to modify IPython's line-processing behavior +# without touching the internal code. We'll define an alternate pre-processing +# stage which allows a special form of input (which is invalid Python syntax) +# for certain quantities, rewrites a line of proper Python in those cases, and +# then passes it off to IPython's normal processor for further work. + +# With this kind of customization, IPython can be adapted for many +# special-purpose scenarios providing alternate input syntaxes. + +# This file can be imported like a regular module. + +# IPython has a prefilter() function that analyzes each input line. We redefine +# it here to first pre-process certain forms of input + +# The prototype of any alternate prefilter must be like this one (the name +# doesn't matter): +# - line is a string containing the user input line. +# - continuation is a parameter which tells us if we are processing a first line of +# user input or the second or higher of a multi-line statement. + +def prefilter_PQ(self,line,continuation): + """Alternate prefilter for input of PhysicalQuantityInteractive objects. + + This assumes that the function PhysicalQuantityInteractive() has been + imported.""" + + from re import match + from IPython.iplib import InteractiveShell + + # This regexp is what does the real work + unit_split = match(r'\s*(\w+)\s*=\s*(-?\d*\.?\d*[eE]?-?\d*)\s+([a-zA-Z].*)', + line) + + # If special input was ecnountered, process it: + if unit_split: + var,val,units = unit_split.groups() + if var and val and units: + units = units.replace('^','**') + # Now a valid line needs to be constructed for IPython to process: + line = var +" = PhysicalQuantityInteractive(" + val + ", '" + \ + units + "')" + #print 'New line:',line # dbg + + # In the end, always call the default IPython _prefilter() function. Note + # that self must be passed explicitly, b/c we're calling the unbound class + # method (since this method will overwrite the instance prefilter()) + return InteractiveShell._prefilter(self,line,continuation) + +# Rebind this to be the new IPython prefilter: +from IPython.iplib import InteractiveShell +InteractiveShell.prefilter = prefilter_PQ + +# Clean up the namespace. +del InteractiveShell,prefilter_PQ + +# Just a heads up at the console +print '*** Simplified input for physical quantities enabled.' diff --git a/IPython/Extensions/PhysicalQInteractive.py b/IPython/Extensions/PhysicalQInteractive.py new file mode 100644 index 0000000..8d26117 --- /dev/null +++ b/IPython/Extensions/PhysicalQInteractive.py @@ -0,0 +1,88 @@ +# -*- coding: utf-8 -*- +"""Modify the PhysicalQuantities class for more convenient interactive use. + +Also redefine some math functions to operate on PhysQties with no need for +special method syntax. This just means moving them out to the global +namespace. + +This module should always be loaded *after* math or Numeric, so it can +overwrite math functions with the versions that handle units.""" + +#***************************************************************************** +# Copyright (C) 2001-2004 Fernando Perez <fperez@colorado.edu> +# +# Distributed under the terms of the BSD License. The full license is in +# the file COPYING, distributed as part of this software. +#***************************************************************************** + +from IPython import Release +__author__ = '%s <%s>' % Release.authors['Fernando'] +__license__ = Release.license + +from Scientific.Physics.PhysicalQuantities import PhysicalQuantity + +# This code can be set up to work with Numeric or with math for providing the +# mathematical functions. Uncomment the one you prefer to use below. + +# If you use math, sin(x) won't work for x an array, only float or PhysQty +import math + +# If you use Numeric, sin(x) works for x a float, PhysQty an array. +#import Numeric as math + +class PhysicalQuantityFunction: + """Generic function wrapper for PhysicalQuantity instances. + + Calls functions from either the math library or the instance's methods as + required. Allows using sin(theta) or sqrt(v**2) syntax irrespective of + whether theta is a pure number or a PhysicalQuantity. + + This is *slow*. It's meant for convenient interactive use, not for + speed.""" + + def __init__(self,name): + self.name = name + + def __call__(self,x): + if isinstance(x,PhysicalQuantity): + return PhysicalQuantity.__dict__[self.name](x) + else: + return math.__dict__[self.name](x) + +class PhysicalQuantityInteractive(PhysicalQuantity): + """Physical quantity with units - modified for Interactive use. + + Basically, the __str__ and __repr__ methods have been swapped for more + convenient interactive use. Powers are shown as ^ instead of ** and only 4 + significant figures are shown. + + Also adds the following aliases for commonly used methods: + b = PhysicalQuantity.inBaseUnits + u = PhysicalQuantity.inUnitsOf + + These are useful when doing a lot of interactive calculations. + """ + + # shorthands for the most useful unit conversions + b = PhysicalQuantity.inBaseUnits # so you can just type x.b to get base units + u = PhysicalQuantity.inUnitsOf + + # This can be done, but it can get dangerous when coupled with IPython's + # auto-calling. Everything ends up shown in baseunits and things like x*2 + # get automatically converted to k(*2), which doesn't work. + # Probably not a good idea in general... + #__call__ = b + + def __str__(self): + return PhysicalQuantity.__repr__(self) + + def __repr__(self): + value = '%.4G' % self.value + units = self.unit.name().replace('**','^') + return value + ' ' + units + +# implement the methods defined in PhysicalQuantity as PhysicalQuantityFunctions +sin = PhysicalQuantityFunction('sin') +cos = PhysicalQuantityFunction('cos') +tan = PhysicalQuantityFunction('tan') +sqrt = PhysicalQuantityFunction('sqrt') diff --git a/IPython/Extensions/__init__.py b/IPython/Extensions/__init__.py new file mode 100644 index 0000000..abc363b --- /dev/null +++ b/IPython/Extensions/__init__.py @@ -0,0 +1,13 @@ +# -*- coding: utf-8 -*- +"""This directory is meant for special-purpose extensions to IPython. + +This can include things which alter the syntax processing stage (see +PhysicalQ_Input for an example of how to do this). + +Any file located here can be called with an 'execfile =' option as + + execfile = Extensions/filename.py + +since the IPython directory itself is already part of the search path for +files listed as 'execfile ='. +""" diff --git a/IPython/Extensions/numeric_formats.py b/IPython/Extensions/numeric_formats.py new file mode 100644 index 0000000..05905a0 --- /dev/null +++ b/IPython/Extensions/numeric_formats.py @@ -0,0 +1,41 @@ +# -*- coding: utf-8 -*- +""" +Extension for printing Numeric Arrays in flexible ways. +""" + +def num_display(self,arg): + """Display method for printing which treats Numeric arrays specially. + """ + + # Non-numpy variables are printed using the system default + if type(arg) != ArrayType: + self._display(arg) + return + # Otherwise, we do work. + format = __IPYTHON__.runtime_rc.numarray_print_format + print 'NumPy array, format:',format + # Here is where all the printing logic needs to be implemented + print arg # nothing yet :) + + +def magic_format(self,parameter_s=''): + """Specifies format of numerical output. + + This command is similar to Ocave's format command. + """ + + valid_formats = ['long','short'] + + if parameter_s in valid_formats: + self.runtime_rc.numarray_print_format = parameter_s + print 'Numeric output format is now:',parameter_s + else: + print 'Invalid format:',parameter_s + print 'Valid formats:',valid_formats + +# setup default format +__IPYTHON__.runtime_rc.numarray_print_format = 'long' + +# Bind our new functions to the interpreter +__IPYTHON__.__class__.magic_format = magic_format +__IPYTHON__.hooks.display = num_display diff --git a/IPython/FakeModule.py b/IPython/FakeModule.py new file mode 100644 index 0000000..c3cac63 --- /dev/null +++ b/IPython/FakeModule.py @@ -0,0 +1,48 @@ +# -*- coding: utf-8 -*- +""" +Class which mimics a module. + +Needed to allow pickle to correctly resolve namespaces during IPython +sessions. + +$Id: FakeModule.py 410 2004-11-04 07:58:17Z fperez $""" + +#***************************************************************************** +# Copyright (C) 2002-2004 Fernando Perez. <fperez@colorado.edu> +# +# Distributed under the terms of the BSD License. The full license is in +# the file COPYING, distributed as part of this software. +#***************************************************************************** + +class FakeModule: + """Simple class with attribute access to fake a module. + + This is not meant to replace a module, but to allow inserting a fake + module in sys.modules so that systems which rely on run-time module + importing (like shelve and pickle) work correctly in interactive IPython + sessions. + + Do NOT use this code for anything other than this IPython private hack.""" + + def __init__(self,adict): + + # It seems pydoc (and perhaps others) needs any module instance to + # implement a __nonzero__ method, so we add it if missing: + if '__nonzero__' not in adict: + def __nonzero__(): + return 1 + adict['__nonzero__'] = __nonzero__ + + self.__dict__ = adict + + def __getattr__(self,key): + try: + return self.__dict__[key] + except KeyError, e: + raise AttributeError("FakeModule object has no attribute %s" % e) + + def __str__(self): + return "<IPython.FakeModule instance>" + + def __repr__(self): + return str(self) diff --git a/IPython/FlexCompleter.py b/IPython/FlexCompleter.py new file mode 100644 index 0000000..5fe88f8 --- /dev/null +++ b/IPython/FlexCompleter.py @@ -0,0 +1,198 @@ +# -*- coding: utf-8 -*- +"""Word completion for GNU readline 2.0. + +--------------------------------------------------------------------------- +NOTE: This version is a re-implementation of rlcompleter with selectable +namespace. + +The problem with rlcompleter is that it's hardwired to work with +__main__.__dict__, and in some cases one may have 'sandboxed' namespaces. So +this class is a ripoff of rlcompleter, with the namespace to work in as an +optional parameter. + +This class can be used just like rlcompleter, but the Completer class now has +a constructor with the optional 'namespace' parameter. + +A patch has been submitted to Python@sourceforge for these changes to go in +the standard Python distribution. + +The patch went in for Python 2.3. Once IPython drops support for Python 2.2, +this file can be significantly reduced. +--------------------------------------------------------------------------- + +Original rlcompleter documentation: + +This requires the latest extension to the readline module (the +completes keywords, built-ins and globals in __main__; when completing +NAME.NAME..., it evaluates (!) the expression up to the last dot and +completes its attributes. + +It's very cool to do "import string" type "string.", hit the +completion key (twice), and see the list of names defined by the +string module! + +Tip: to use the tab key as the completion key, call + + readline.parse_and_bind("tab: complete") + +Notes: + +- Exceptions raised by the completer function are *ignored* (and +generally cause the completion to fail). This is a feature -- since +readline sets the tty device in raw (or cbreak) mode, printing a +traceback wouldn't work well without some complicated hoopla to save, +reset and restore the tty state. + +- The evaluation of the NAME.NAME... form may cause arbitrary +application defined code to be executed if an object with a +__getattr__ hook is found. Since it is the responsibility of the +application (or the user) to enable this feature, I consider this an +acceptable risk. More complicated expressions (e.g. function calls or +indexing operations) are *not* evaluated. + +- GNU readline is also used by the built-in functions input() and +raw_input(), and thus these also benefit/suffer from the completer +features. Clearly an interactive application can benefit by +specifying its own completer function and using raw_input() for all +its input. + +- When the original stdin is not a tty device, GNU readline is never +used, and this module (and the readline module) are silently inactive. + +""" + +#***************************************************************************** +# +# Since this file is essentially a minimally modified copy of the rlcompleter +# module which is part of the standard Python distribution, I assume that the +# proper procedure is to maintain its copyright as belonging to the Python +# Software Foundation: +# +# Copyright (C) 2001 Python Software Foundation, www.python.org +# +# Distributed under the terms of the Python Software Foundation license. +# +# Full text available at: +# +# http://www.python.org/2.1/license.html +# +#***************************************************************************** + +import readline +import __builtin__ +import __main__ + +__all__ = ["Completer"] + +class Completer: + def __init__(self, namespace = None): + """Create a new completer for the command line. + + Completer([namespace]) -> completer instance. + + If unspecified, the default namespace where completions are performed + is __main__ (technically, __main__.__dict__). Namespaces should be + given as dictionaries. + + Completer instances should be used as the completion mechanism of + readline via the set_completer() call: + + readline.set_completer(Completer(my_namespace).complete) + """ + + if namespace and type(namespace) != type({}): + raise TypeError,'namespace must be a dictionary' + + # Don't bind to namespace quite yet, but flag whether the user wants a + # specific namespace or to use __main__.__dict__. This will allow us + # to bind to __main__.__dict__ at completion time, not now. + if namespace is None: + self.use_main_ns = 1 + else: + self.use_main_ns = 0 + self.namespace = namespace + + def complete(self, text, state): + """Return the next possible completion for 'text'. + + This is called successively with state == 0, 1, 2, ... until it + returns None. The completion should begin with 'text'. + + """ + if self.use_main_ns: + self.namespace = __main__.__dict__ + + if state == 0: + if "." in text: + self.matches = self.attr_matches(text) + else: + self.matches = self.global_matches(text) + try: + return self.matches[state] + except IndexError: + return None + + def global_matches(self, text): + """Compute matches when text is a simple name. + + Return a list of all keywords, built-in functions and names currently + defined in self.namespace that match. + + """ + import keyword + matches = [] + n = len(text) + for list in [keyword.kwlist, + __builtin__.__dict__.keys(), + self.namespace.keys()]: + for word in list: + if word[:n] == text and word != "__builtins__": + matches.append(word) + return matches + + def attr_matches(self, text): + """Compute matches when text contains a dot. + + Assuming the text is of the form NAME.NAME....[NAME], and is + evaluatable in self.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 + + # Another option, seems to work great. Catches things like ''.<tab> + m = re.match(r"(\S+(\.\w+)*)\.(\w*)$", text) + + if not m: + return [] + expr, attr = m.group(1, 3) + object = eval(expr, self.namespace) + words = dir(object) + if hasattr(object,'__class__'): + words.append('__class__') + words.extend(get_class_members(object.__class__)) + n = len(attr) + matches = [] + for word in words: + try: + if word[:n] == attr and word != "__builtins__": + matches.append("%s.%s" % (expr, word)) + except: + # some badly behaved objects pollute dir() with non-strings, + # which cause the completion to fail. This way we skip the + # bad entries and can still continue processing the others. + pass + return matches + +def get_class_members(klass): + ret = dir(klass) + if hasattr(klass,'__bases__'): + for base in klass.__bases__: + ret.extend(get_class_members(base)) + return ret + +readline.set_completer(Completer().complete) diff --git a/IPython/Gnuplot2.py b/IPython/Gnuplot2.py new file mode 100644 index 0000000..4fe431f --- /dev/null +++ b/IPython/Gnuplot2.py @@ -0,0 +1,655 @@ +# -*- coding: utf-8 -*- +"""Improved replacement for the Gnuplot.Gnuplot class. + +This module imports Gnuplot and replaces some of its functionality with +improved versions. They add better handling of arrays for plotting and more +convenient PostScript generation, plus some fixes for hardcopy(). + +It also adds a convenient plot2 method for plotting dictionaries and +lists/tuples of arrays. + +This module is meant to be used as a drop-in replacement to the original +Gnuplot, so it should be safe to do: + +import IPython.Gnuplot2 as Gnuplot + +$Id: Gnuplot2.py 392 2004-10-09 22:01:51Z fperez $""" + +import string,os,time,types +import cStringIO +import sys +import tempfile +import Numeric +import Gnuplot as Gnuplot_ori +from IPython.genutils import popkey,xsys + +# needed by hardcopy(): +gp = Gnuplot_ori.gp + +# Patch for Gnuplot.py 1.6 compatibility. +# Thanks to Hayden Callow <h.callow@elec.canterbury.ac.nz> +try: + OptionException = Gnuplot_ori.PlotItems.OptionException +except AttributeError: + OptionException = Gnuplot_ori.Errors.OptionError + +# exhibit a similar interface to Gnuplot so it can be somewhat drop-in +Data = Gnuplot_ori.Data +Func = Gnuplot_ori.Func +GridData = Gnuplot_ori.GridData +PlotItem = Gnuplot_ori.PlotItem +PlotItems = Gnuplot_ori.PlotItems + +# Modify some of Gnuplot's functions with improved versions (or bugfixed, in +# hardcopy's case). In order to preserve the docstrings at runtime, I've +# copied them from the original code. + +# After some significant changes in v 1.7 of Gnuplot.py, we need to do a bit +# of version checking. + +if Gnuplot_ori.__version__ <= '1.6': + _BaseFileItem = PlotItems.File + _BaseTempFileItem = PlotItems.TempFile + + # Fix the File class to add the 'index' option for Gnuplot versions < 1.7 + class File(_BaseFileItem): + + _option_list = _BaseFileItem._option_list.copy() + _option_list.update({ + 'index' : lambda self, index: self.set_option_index(index), + }) + + # A new initializer is needed b/c we want to add a modified + # _option_sequence list which includes 'index' in the right place. + def __init__(self,*args,**kw): + self._option_sequence = ['binary', 'index', 'using', 'smooth', 'axes', + 'title', 'with'] + + _BaseFileItem.__init__(self,*args,**kw) + + # Let's fix the constructor docstring + __newdoc = \ + """Additional Keyword arguments added by IPython: + + 'index=<int>' -- similar to the `index` keyword in Gnuplot. + This allows only some of the datasets in a file to be + plotted. Datasets within a file are assumed to be separated + by _pairs_ of blank lines, and the first one is numbered as + 0 (similar to C/Python usage).""" + __init__.__doc__ = PlotItems.File.__init__.__doc__ + __newdoc + + def set_option_index(self, index): + if index is None: + self.clear_option('index') + elif type(index) in [type(''), type(1)]: + self._options['index'] = (index, 'index %s' % index) + elif type(index) is type(()): + self._options['index'] = (index,'index %s' % + string.join(map(repr, index), ':')) + else: + raise OptionException('index=%s' % (index,)) + + # We need a FileClass with a different name from 'File', which is a + # factory function in 1.7, so that our String class can subclass FileClass + # in any version. + _FileClass = File + +else: # Gnuplot.py version 1.7 and greater + _FileClass = _BaseFileItem = PlotItems._FileItem + _BaseTempFileItem = PlotItems._TempFileItem + File = PlotItems.File + +# Now, we can add our generic code which is version independent + +# First some useful utilities +def eps_fix_bbox(fname): + """Fix the bounding box of an eps file by running ps2eps on it. + + If its name ends in .eps, the original file is removed. + + This is particularly useful for plots made by Gnuplot with square aspect + ratio: there is a bug in Gnuplot which makes it generate a bounding box + which is far wider than the actual plot. + + This function assumes that ps2eps is installed in your system.""" + + # note: ps2ps and eps2eps do NOT work, ONLY ps2eps works correctly. The + # others make output with bitmapped fonts, which looks horrible. + print 'Fixing eps file: <%s>' % fname + xsys('ps2eps -f -q -l %s' % fname) + if fname.endswith('.eps'): + os.rename(fname+'.eps',fname) + +def is_list1d(x,containers = [types.ListType,types.TupleType]): + """Returns true if x appears to be a 1d list/tuple/array. + + The heuristics are: identify Numeric arrays, or lists/tuples whose first + element is not itself a list/tuple. This way zipped lists should work like + the original Gnuplot. There's no inexpensive way to know if a list doesn't + have a composite object after its first element, so that kind of input + will produce an error. But it should work well in most cases. + """ + x_type = type(x) + + return x_type == Numeric.ArrayType and len(x.shape)==1 or \ + (x_type in containers and + type(x[0]) not in containers + [Numeric.ArrayType]) + +def zip_items(items,titles=None): + """zip together neighboring 1-d arrays, and zip standalone ones + with their index. Leave other plot items alone.""" + + class StandaloneItem(Exception): pass + + def get_titles(titles): + """Return the next title and the input titles array. + + The input array may be changed to None when no titles are left to + prevent extra unnecessary calls to this function.""" + + try: + title = titles[tit_ct[0]] # tit_ct[0] is in zip_items'scope + except IndexError: + titles = None # so we don't enter again + title = None + else: + tit_ct[0] += 1 + return title,titles + + new_items = [] + + if titles: + # Initialize counter. It was put in a list as a hack to allow the + # nested get_titles to modify it without raising a NameError. + tit_ct = [0] + + n = 0 # this loop needs to be done by hand + while n < len(items): + item = items[n] + try: + if is_list1d(item): + if n==len(items)-1: # last in list + raise StandaloneItem + else: # check the next item and zip together if needed + next_item = items[n+1] + if next_item is None: + n += 1 + raise StandaloneItem + elif is_list1d(next_item): + # this would be best done with an iterator + if titles: + title,titles = get_titles(titles) + else: + title = None + new_items.append(Data(zip(item,next_item), + title=title)) + n += 1 # avoid double-inclusion of next item + else: # can't zip with next, zip with own index list + raise StandaloneItem + else: # not 1-d array + new_items.append(item) + except StandaloneItem: + if titles: + title,titles = get_titles(titles) + else: + title = None + new_items.append(Data(zip(range(len(item)),item),title=title)) + except AttributeError: + new_items.append(item) + n+=1 + + return new_items + +# And some classes with enhanced functionality. +class String(_FileClass): + """Make a PlotItem from data in a string with the same format as a File. + + This allows writing data directly inside python scripts using the exact + same format and manipulation options which would be used for external + files.""" + + def __init__(self, data_str, **keyw): + """Construct a String object. + + <data_str> is a string formatted exactly like a valid Gnuplot data + file would be. All options from the File constructor are valid here. + + Warning: when used for interactive plotting in scripts which exit + immediately, you may get an error because the temporary file used to + hold the string data was deleted before Gnuplot had a chance to see + it. You can work around this problem by putting a raw_input() call at + the end of the script. + + This problem does not appear when generating PostScript output, only + with Gnuplot windows.""" + + self.tmpfile = _BaseTempFileItem() + tmpfile = file(self.tmpfile.filename,'w') + tmpfile.write(data_str) + _BaseFileItem.__init__(self,self.tmpfile,**keyw) + + +class Gnuplot(Gnuplot_ori.Gnuplot): + """Improved Gnuplot class. + + Enhancements: better plot,replot and hardcopy methods. New methods for + quick range setting. + """ + + def xrange(self,min='*',max='*'): + """Set xrange. If min/max is omitted, it is set to '*' (auto). + + Note that this is different from the regular Gnuplot behavior, where + an unspecified limit means no change. Here any unspecified limit is + set to autoscaling, allowing these functions to be used for full + autoscaling when called with no arguments. + + To preserve one limit's current value while changing the other, an + explicit '' argument must be given as the limit to be kept. + + Similar functions exist for [y{2}z{2}rtuv]range.""" + + self('set xrange [%s:%s]' % (min,max)) + + def yrange(self,min='*',max='*'): + self('set yrange [%s:%s]' % (min,max)) + + def zrange(self,min='*',max='*'): + self('set zrange [%s:%s]' % (min,max)) + + def x2range(self,min='*',max='*'): + self('set xrange [%s:%s]' % (min,max)) + + def y2range(self,min='*',max='*'): + self('set yrange [%s:%s]' % (min,max)) + + def z2range(self,min='*',max='*'): + self('set zrange [%s:%s]' % (min,max)) + + def rrange(self,min='*',max='*'): + self('set rrange [%s:%s]' % (min,max)) + + def trange(self,min='*',max='*'): + self('set trange [%s:%s]' % (min,max)) + + def urange(self,min='*',max='*'): + self('set urange [%s:%s]' % (min,max)) + + def vrange(self,min='*',max='*'): + self('set vrange [%s:%s]' % (min,max)) + + def set_ps(self,option): + """Set an option for the PostScript terminal and reset default term.""" + + self('set terminal postscript %s ' % option) + self('set terminal %s' % gp.GnuplotOpts.default_term) + + def __plot_ps(self, plot_method,*items, **keyw): + """Wrapper for plot/splot/replot, with processing of hardcopy options. + + For internal use only.""" + + # Filter out PostScript options which will crash the normal plot/replot + psargs = {'filename':None, + 'mode':None, + 'eps':None, + 'enhanced':None, + 'color':None, + 'solid':None, + 'duplexing':None, + 'fontname':None, + 'fontsize':None, + 'debug':0 } + + for k in psargs.keys(): + if keyw.has_key(k): + psargs[k] = keyw[k] + del keyw[k] + + # Filter out other options the original plot doesn't know + hardcopy = popkey(keyw,'hardcopy',psargs['filename'] is not None) + titles = popkey(keyw,'titles',0) + + # the filename keyword should control hardcopy generation, this is an + # override switch only which needs to be explicitly set to zero + if hardcopy: + if psargs['filename'] is None: + raise ValueError, \ + 'If you request hardcopy, you must give a filename.' + + # set null output so nothing goes to screen. hardcopy() restores output + self('set term dumb') + # I don't know how to prevent screen output in Windows + if os.name == 'posix': + self('set output "/dev/null"') + + new_items = zip_items(items,titles) + # plot_method is either plot or replot from the original Gnuplot class: + plot_method(self,*new_items,**keyw) + + # Do hardcopy if requested + if hardcopy: + if psargs['filename'].endswith('.eps'): + psargs['eps'] = 1 + self.hardcopy(**psargs) + + def plot(self, *items, **keyw): + """Draw a new plot. + + Clear the current plot and create a new 2-d plot containing + the specified items. Each arguments should be of the + following types: + + 'PlotItem' (e.g., 'Data', 'File', 'Func') -- This is the most + flexible way to call plot because the PlotItems can + contain suboptions. Moreover, PlotItems can be saved to + variables so that their lifetime is longer than one plot + command; thus they can be replotted with minimal overhead. + + 'string' (e.g., 'sin(x)') -- The string is interpreted as + 'Func(string)' (a function that is computed by gnuplot). + + Anything else -- The object, which should be convertible to an + array, is passed to the 'Data' constructor, and thus + plotted as data. If the conversion fails, an exception is + raised. + + + This is a modified version of plot(). Compared to the original in + Gnuplot.py, this version has several enhancements, listed below. + + + Modifications to the input arguments + ------------------------------------ + + (1-d array means Numeric array, list or tuple): + + (i) Any 1-d array which is NOT followed by another 1-d array, is + automatically zipped with range(len(array_1d)). Typing g.plot(y) will + plot y against its indices. + + (ii) If two 1-d arrays are contiguous in the argument list, they are + automatically zipped together. So g.plot(x,y) plots y vs. x, and + g.plot(x1,y1,x2,y2) plots y1 vs. x1 and y2 vs. x2. + + (iii) Any 1-d array which is followed by None is automatically zipped + with range(len(array_1d)). In this form, typing g.plot(y1,None,y2) + will plot both y1 and y2 against their respective indices (and NOT + versus one another). The None prevents zipping y1 and y2 together, and + since y2 is unpaired it is automatically zipped to its indices by (i) + + (iv) Any other arguments which don't match these cases are left alone and + passed to the code below. + + For lists or tuples, the heuristics used to determine whether they are + in fact 1-d is fairly simplistic: their first element is checked, and + if it is not a list or tuple itself, it is assumed that the whole + object is one-dimensional. + + An additional optional keyword 'titles' has been added: it must be a + list of strings to be used as labels for the individual plots which + are NOT PlotItem objects (since those objects carry their own labels + within). + + + PostScript generation + --------------------- + + This version of plot() also handles automatically the production of + PostScript output. The main options are (given as keyword arguments): + + - filename: a string, typically ending in .eps. If given, the plot is + sent to this file in PostScript format. + + - hardcopy: this can be set to 0 to override 'filename'. It does not + need to be given to produce PostScript, its purpose is to allow + switching PostScript output off globally in scripts without having to + manually change 'filename' values in multiple calls. + + All other keywords accepted by Gnuplot.hardcopy() are transparently + passed, and safely ignored if output is sent to the screen instead of + PostScript. + + For example: + + In [1]: x=frange(0,2*pi,npts=100) + + Generate a plot in file 'sin.eps': + + In [2]: plot(x,sin(x),filename = 'sin.eps') + + Plot to screen instead, without having to change the filename: + + In [3]: plot(x,sin(x),filename = 'sin.eps',hardcopy=0) + + Pass the 'color=0' option to hardcopy for monochrome output: + + In [4]: plot(x,sin(x),filename = 'sin.eps',color=0) + + PostScript generation through plot() is useful mainly for scripting + uses where you are not interested in interactive plotting. For + interactive use, the hardcopy() function is typically more convenient: + + In [5]: plot(x,sin(x)) + + In [6]: hardcopy('sin.eps') """ + + self.__plot_ps(Gnuplot_ori.Gnuplot.plot,*items,**keyw) + + def plot2(self,arg,**kw): + """Plot the entries of a dictionary or a list/tuple of arrays. + + This simple utility calls plot() with a list of Gnuplot.Data objects + constructed either from the values of the input dictionary, or the entries + in it if it is a tuple or list. Each item gets labeled with the key/index + in the Gnuplot legend. + + Each item is plotted by zipping it with a list of its indices. + + Any keywords are passed directly to plot().""" + + if hasattr(arg,'keys'): + keys = arg.keys() + keys.sort() + else: + keys = range(len(arg)) + + pitems = [Data(zip(range(len(arg[k])),arg[k]),title=`k`) for k in keys] + self.plot(*pitems,**kw) + + def splot(self, *items, **keyw): + """Draw a new three-dimensional plot. + + Clear the current plot and create a new 3-d plot containing + the specified items. Arguments can be of the following types: + + 'PlotItem' (e.g., 'Data', 'File', 'Func', 'GridData' ) -- This + is the most flexible way to call plot because the + PlotItems can contain suboptions. Moreover, PlotItems can + be saved to variables so that their lifetime is longer + than one plot command--thus they can be replotted with + minimal overhead. + + 'string' (e.g., 'sin(x*y)') -- The string is interpreted as a + 'Func()' (a function that is computed by gnuplot). + + Anything else -- The object is converted to a Data() item, and + thus plotted as data. Note that each data point should + normally have at least three values associated with it + (i.e., x, y, and z). If the conversion fails, an + exception is raised. + + This is a modified version of splot(). Compared to the original in + Gnuplot.py, this version has several enhancements, listed in the + plot() documentation. + """ + + self.__plot_ps(Gnuplot_ori.Gnuplot.splot,*items,**keyw) + + def replot(self, *items, **keyw): + """Replot the data, possibly adding new 'PlotItem's. + + Replot the existing graph, using the items in the current + itemlist. If arguments are specified, they are interpreted as + additional items to be plotted alongside the existing items on + the same graph. See 'plot' for details. + + If you want to replot to a postscript file, you MUST give the + 'filename' keyword argument in each call to replot. The Gnuplot python + interface has no way of knowing that your previous call to + Gnuplot.plot() was meant for PostScript output.""" + + self.__plot_ps(Gnuplot_ori.Gnuplot.replot,*items,**keyw) + + # The original hardcopy has a bug. See fix at the end. The rest of the code + # was lifted verbatim from the original, so that people using IPython get the + # benefits without having to manually patch Gnuplot.py + def hardcopy(self, filename=None, + mode=None, + eps=None, + enhanced=None, + color=None, + solid=None, + duplexing=None, + fontname=None, + fontsize=None, + debug = 0, + ): + """Create a hardcopy of the current plot. + + Create a postscript hardcopy of the current plot to the + default printer (if configured) or to the specified filename. + + Note that gnuplot remembers the postscript suboptions across + terminal changes. Therefore if you set, for example, color=1 + for one hardcopy then the next hardcopy will also be color + unless you explicitly choose color=0. Alternately you can + force all of the options to their defaults by setting + mode='default'. I consider this to be a bug in gnuplot. + + Keyword arguments: + + 'filename=<string>' -- if a filename is specified, save the + output in that file; otherwise print it immediately + using the 'default_lpr' configuration option. If the + filename ends in '.eps', EPS mode is automatically + selected (like manually specifying eps=1 or mode='eps'). + + 'mode=<string>' -- set the postscript submode ('landscape', + 'portrait', 'eps', or 'default'). The default is + to leave this option unspecified. + + 'eps=<bool>' -- shorthand for 'mode="eps"'; asks gnuplot to + generate encapsulated postscript. + + 'enhanced=<bool>' -- if set (the default), then generate + enhanced postscript, which allows extra features like + font-switching, superscripts, and subscripts in axis + labels. (Some old gnuplot versions do not support + enhanced postscript; if this is the case set + gp.GnuplotOpts.prefer_enhanced_postscript=None.) + + 'color=<bool>' -- if set, create a plot with color. Default + is to leave this option unchanged. + + 'solid=<bool>' -- if set, force lines to be solid (i.e., not + dashed). + + 'duplexing=<string>' -- set duplexing option ('defaultplex', + 'simplex', or 'duplex'). Only request double-sided + printing if your printer can handle it. Actually this + option is probably meaningless since hardcopy() can only + print a single plot at a time. + + 'fontname=<string>' -- set the default font to <string>, + which must be a valid postscript font. The default is + to leave this option unspecified. + + 'fontsize=<double>' -- set the default font size, in + postscript points. + + 'debug=<bool>' -- print extra debugging information (useful if + your PostScript files are misteriously not being created). + """ + + if filename is None: + assert gp.GnuplotOpts.default_lpr is not None, \ + OptionException('default_lpr is not set, so you can only ' + 'print to a file.') + filename = gp.GnuplotOpts.default_lpr + lpr_output = 1 + else: + if filename.endswith('.eps'): + eps = 1 + lpr_output = 0 + + # Be careful processing the options. If the user didn't + # request an option explicitly, do not specify it on the 'set + # terminal' line (don't even specify the default value for the + # option). This is to avoid confusing older versions of + # gnuplot that do not support all of these options. The + # exception is 'enhanced', which is just too useful to have to + # specify each time! + + setterm = ['set', 'terminal', 'postscript'] + if eps: + assert mode is None or mode=='eps', \ + OptionException('eps option and mode are incompatible') + setterm.append('eps') + else: + if mode is not None: + assert mode in ['landscape', 'portrait', 'eps', 'default'], \ + OptionException('illegal mode "%s"' % mode) + setterm.append(mode) + if enhanced is None: + enhanced = gp.GnuplotOpts.prefer_enhanced_postscript + if enhanced is not None: + if enhanced: setterm.append('enhanced') + else: setterm.append('noenhanced') + if color is not None: + if color: setterm.append('color') + else: setterm.append('monochrome') + if solid is not None: + if solid: setterm.append('solid') + else: setterm.append('dashed') + if duplexing is not None: + assert duplexing in ['defaultplex', 'simplex', 'duplex'], \ + OptionException('illegal duplexing mode "%s"' % duplexing) + setterm.append(duplexing) + if fontname is not None: + setterm.append('"%s"' % fontname) + if fontsize is not None: + setterm.append('%s' % fontsize) + + self(string.join(setterm)) + self.set_string('output', filename) + # replot the current figure (to the printer): + self.refresh() + + # fperez. Ugly kludge: often for some reason the file is NOT created + # and we must reissue the creation commands. I have no idea why! + if not lpr_output: + #print 'Hardcopy <%s>' % filename # dbg + maxtries = 20 + delay = 0.1 # delay (in seconds) between print attempts + for i in range(maxtries): + time.sleep(0.05) # safety, very small delay + if os.path.isfile(filename): + if debug: + print 'Hardcopy to file <%s> success at attempt #%s.' \ + % (filename,i+1) + break + time.sleep(delay) + # try again, issue all commands just in case + self(string.join(setterm)) + self.set_string('output', filename) + self.refresh() + if not os.path.isfile(filename): + print >> sys.stderr,'ERROR: Tried %s times and failed to '\ + 'create hardcopy file `%s`' % (maxtries,filename) + + # reset the terminal to its `default' setting: + self('set terminal %s' % gp.GnuplotOpts.default_term) + self.set_string('output') + +#********************** End of file <Gnuplot2.py> ************************ diff --git a/IPython/GnuplotInteractive.py b/IPython/GnuplotInteractive.py new file mode 100644 index 0000000..0e99ba6 --- /dev/null +++ b/IPython/GnuplotInteractive.py @@ -0,0 +1,148 @@ +# -*- coding: utf-8 -*- +"""Interactive functions and magic functions for Gnuplot usage. + +This requires the Gnuplot.py module for interfacing python with Gnuplot, which +can be downloaded from: + +http://gnuplot-py.sourceforge.net/ + +See gphelp() below for details on the services offered by this module. + +Inspired by a suggestion/request from Arnd Baecker. + +$Id: GnuplotInteractive.py 389 2004-10-09 07:59:30Z fperez $""" + +__all__ = ['Gnuplot','gp','gp_new','plot','plot2','splot','replot', + 'hardcopy','gpdata','gpfile','gpstring','gpfunc','gpgrid', + 'gphelp'] + +import IPython.GnuplotRuntime as GRun +from IPython.genutils import page,warn + +# Set global names for interactive use +Gnuplot = GRun.Gnuplot +gp_new = GRun.gp_new +gp = GRun.gp +plot = gp.plot +plot2 = gp.plot2 +splot = gp.splot +replot = gp.replot +hardcopy = gp.hardcopy + +# Accessors for the main plot object constructors: +gpdata = Gnuplot.Data +gpfile = Gnuplot.File +gpstring = Gnuplot.String +gpfunc = Gnuplot.Func +gpgrid = Gnuplot.GridData + +def gphelp(): + """Print information about the Gnuplot facilities in IPython.""" + + page(""" +IPython provides an interface to access the Gnuplot scientific plotting +system, in an environment similar to that of Mathematica or Matlab. + +New top-level global objects +---------------------------- + +Please see their respective docstrings for further details. + +- gp: a running Gnuplot instance. You can access its methods as +gp.<method>. gp(`a string`) will execute the given string as if it had been +typed in an interactive gnuplot window. + +- plot, splot, replot and hardcopy: aliases to the methods of the same name in +the global running Gnuplot instance gp. These allow you to simply type: + +In [1]: plot(x,sin(x),title='Sin(x)') # assuming x is a Numeric array + +and obtain a plot of sin(x) vs x with the title 'Sin(x)'. + +- gp_new: a function which returns a new Gnuplot instance. This can be used to +have multiple Gnuplot instances running in your session to compare different +plots, each in a separate window. + +- Gnuplot: alias to the Gnuplot2 module, an improved drop-in replacement for +the original Gnuplot.py. Gnuplot2 needs Gnuplot but redefines several of its +functions with improved versions (Gnuplot2 comes with IPython). + +- gpdata, gpfile, gpstring, gpfunc, gpgrid: aliases to Gnuplot.Data, +Gnuplot.File, Gnuplot.String, Gnuplot.Func and Gnuplot.GridData +respectively. These functions create objects which can then be passed to the +plotting commands. See the Gnuplot.py documentation for details. + +Keep in mind that all commands passed to a Gnuplot instance are executed in +the Gnuplot namespace, where no Python variables exist. For example, for +plotting sin(x) vs x as above, typing + +In [2]: gp('plot x,sin(x)') + +would not work. Instead, you would get the plot of BOTH the functions 'x' and +'sin(x)', since Gnuplot doesn't know about the 'x' Python array. The plot() +method lives in python and does know about these variables. + + +New magic functions +------------------- + +%gpc: pass one command to Gnuplot and execute it or open a Gnuplot shell where +each line of input is executed. + +%gp_set_default: reset the value of IPython's global Gnuplot instance.""") + +# Code below is all for IPython use +# Define the magic functions for communicating with the above gnuplot instance. +def magic_gpc(self,parameter_s=''): + """Execute a gnuplot command or open a gnuplot shell. + + Usage (omit the % if automagic is on). There are two ways to use it: + + 1) %gpc 'command' -> passes 'command' directly to the gnuplot instance. + + 2) %gpc -> will open up a prompt (gnuplot>>>) which takes input like the + standard gnuplot interactive prompt. If you need to type a multi-line + command, use \\ at the end of each intermediate line. + + Upon exiting of the gnuplot sub-shell, you return to your IPython + session (the gnuplot sub-shell can be invoked as many times as needed). + """ + + if parameter_s.strip(): + self.shell.gnuplot(parameter_s) + else: + self.shell.gnuplot.interact() + +def magic_gp_set_default(self,parameter_s=''): + """Set the default gnuplot instance accessed by the %gp magic function. + + %gp_set_default name + + Call with the name of the new instance at the command line. If you want to + set this instance in your own code (using an embedded IPython, for + example), simply set the variable __IPYTHON__.gnuplot to your own gnuplot + instance object.""" + + gname = parameter_s.strip() + G = eval(gname,self.shell.user_ns) + self.shell.gnuplot = G + self.shell.user_ns.update({'plot':G.plot,'splot':G.splot,'plot2':G.plot2, + 'replot':G.replot,'hardcopy':G.hardcopy}) + +try: + __IPYTHON__ +except NameError: + pass +else: + # make the global Gnuplot instance known to IPython + __IPYTHON__.gnuplot = GRun.gp + __IPYTHON__.gnuplot.shell_first_time = 1 + + print """*** Type `gphelp` for help on the Gnuplot integration features.""" + + # Add the new magic functions to the class dict + from IPython.iplib import InteractiveShell + InteractiveShell.magic_gpc = magic_gpc + InteractiveShell.magic_gp_set_default = magic_gp_set_default + +#********************** End of file <GnuplotInteractive.py> ******************* diff --git a/IPython/GnuplotRuntime.py b/IPython/GnuplotRuntime.py new file mode 100644 index 0000000..1e99dba --- /dev/null +++ b/IPython/GnuplotRuntime.py @@ -0,0 +1,147 @@ +# -*- coding: utf-8 -*- +"""Basic Gnuplot functionality for inclusion in other code. + +This module creates a running Gnuplot instance called 'gp' and builds other +convenient globals for quick use in running scripts. It is intended to allow +you to script plotting tasks in Python with a minimum of effort. A typical +usage would be: + +import IPython.GnuplotRuntime as GP # or some other short name +GP.gp.plot(GP.File('your_data.dat')) + + +This module exposes the following objects: + +- gp: a running Gnuplot instance. You can access its methods as +gp.<method>. gp(`a string`) will execute the given string as if it had been +typed in an interactive gnuplot window. + +- gp_new: a function which returns a new Gnuplot instance. This can be used to +have multiple Gnuplot instances running in your session to compare different +plots. + +- Gnuplot: alias to the Gnuplot2 module, an improved drop-in replacement for +the original Gnuplot.py. Gnuplot2 needs Gnuplot but redefines several of its +functions with improved versions (Gnuplot2 comes with IPython). + +- Data: alias to Gnuplot.Data, makes a PlotItem from array data. + +- File: alias to Gnuplot.File, makes a PlotItem from a file. + +- String: alias to Gnuplot.String, makes a PlotItem from a string formatted +exactly like a file for Gnuplot.File would be. + +- Func: alias to Gnuplot.Func, makes a PlotItem from a function string. + +- GridData: alias to Gnuplot.GridData, makes a PlotItem from grid data. + +- pm3d_config: a string with Gnuplot commands to set up the pm3d mode for +surface plotting. You can activate it simply by calling gp(pm3d_config). + +- eps_fix_bbox: A Unix-only function to fix eps files with bad bounding boxes +(which Gnuplot generates when the plot size is set to square). + +This requires the Gnuplot.py module for interfacing Python with Gnuplot, which +can be downloaded from: + +http://gnuplot-py.sourceforge.net/ + +Inspired by a suggestion/request from Arnd Baecker. + +$Id: GnuplotRuntime.py 389 2004-10-09 07:59:30Z fperez $""" + +__all__ = ['Gnuplot','gp','gp_new','Data','File','Func','GridData', + 'pm3d_config','eps_fix_bbox'] + +import os,tempfile,sys +from IPython.genutils import getoutput + +#--------------------------------------------------------------------------- +# Notes on mouse support for Gnuplot.py + +# If you do not have a mouse-enabled gnuplot, set gnuplot_mouse to 0. If you +# use gnuplot, you should really grab a recent, mouse enabled copy. It is an +# extremely useful feature. Mouse support is official as of gnuplot 4.0, +# released in April 2004. + +# For the mouse features to work correctly, you MUST set your Gnuplot.py +# module to use temporary files instead of 'inline data' for data +# communication. Note that this is the default, so unless you've manually +# fiddled with it you should be ok. If you need to make changes, in the +# Gnuplot module directory, loook for the gp_unix.py file and make sure the +# prefer_inline_data variable is set to 0. If you set it to 1 Gnuplot.py will +# try to pass the data to gnuplot via standard input, which completely +# confuses the mouse control system (even though it may be a bit faster than +# using temp files). + +# As of Gnuplot.py v1.7, a new option was added to use FIFOs (pipes). This +# mechanism, while fast, also breaks the mouse system. You must therefore set +# the variable prefer_fifo_data to 0 in gp_unix.py. + +tmpname = tempfile.mktemp() +open(tmpname,'w').write('set mouse') +gnu_out = getoutput('gnuplot '+ tmpname) +os.unlink(tmpname) +if gnu_out: # Gnuplot won't print anything if it has mouse support + print "*** Your version of Gnuplot appears not to have mouse support." + gnuplot_mouse = 0 +else: + gnuplot_mouse = 1 +del tmpname,gnu_out + +# Default state for persistence of new gnuplot instances +if os.name in ['nt','dos'] or sys.platform == 'cygwin': + gnuplot_persist = 0 +else: + gnuplot_persist = 1 + +import IPython.Gnuplot2 as Gnuplot + +class NotGiven: pass + +def gp_new(mouse=NotGiven,persist=NotGiven): + """Return a new Gnuplot instance. + + The instance returned uses the improved methods defined in Gnuplot2. + + Options (boolean): + + - mouse: if unspecified, the module global gnuplot_mouse is used. + + - persist: if unspecified, the module global gnuplot_persist is used.""" + + if mouse is NotGiven: + mouse = gnuplot_mouse + if persist is NotGiven: + persist = gnuplot_persist + g = Gnuplot.Gnuplot(persist=persist) + if mouse: + g('set mouse') + return g + +# Global-level names. + +# A global Gnuplot instance for interactive use: +gp = gp_new() + +# Accessors for the main plot object constructors: +Data = Gnuplot.Data +File = Gnuplot.File +Func = Gnuplot.Func +String = Gnuplot.String +GridData = Gnuplot.GridData + +# A Unix-only function to fix eps files with bad bounding boxes (which Gnuplot +# generates when the plot size is set to square): +eps_fix_bbox = Gnuplot.eps_fix_bbox + +# String for configuring pm3d. Simply call g(pm3d_config) to execute it. pm3d +# is a very nice mode for plotting colormaps on surfaces. Modify the defaults +# below to suit your taste. +pm3d_config = """ +set pm3d solid +set hidden3d +unset surface +set isosamples 50 +""" +#******************** End of file <GnuplotRuntime.py> ****************** diff --git a/IPython/Itpl.py b/IPython/Itpl.py new file mode 100644 index 0000000..c62ab4f --- /dev/null +++ b/IPython/Itpl.py @@ -0,0 +1,253 @@ +# -*- coding: utf-8 -*- +"""String interpolation for Python (by Ka-Ping Yee, 14 Feb 2000). + +This module lets you quickly and conveniently interpolate values into +strings (in the flavour of Perl or Tcl, but with less extraneous +punctuation). You get a bit more power than in the other languages, +because this module allows subscripting, slicing, function calls, +attribute lookup, or arbitrary expressions. Variables and expressions +are evaluated in the namespace of the caller. + +The itpl() function returns the result of interpolating a string, and +printpl() prints out an interpolated string. Here are some examples: + + from Itpl import printpl + printpl("Here is a $string.") + printpl("Here is a $module.member.") + printpl("Here is an $object.member.") + printpl("Here is a $functioncall(with, arguments).") + printpl("Here is an ${arbitrary + expression}.") + printpl("Here is an $array[3] member.") + printpl("Here is a $dictionary['member'].") + +The filter() function filters a file object so that output through it +is interpolated. This lets you produce the illusion that Python knows +how to do interpolation: + + import Itpl + sys.stdout = Itpl.filter() + f = "fancy" + print "Isn't this $f?" + print "Standard output has been replaced with a $sys.stdout object." + sys.stdout = Itpl.unfilter() + print "Okay, back $to $normal." + +Under the hood, the Itpl class represents a string that knows how to +interpolate values. An instance of the class parses the string once +upon initialization; the evaluation and substitution can then be done +each time the instance is evaluated with str(instance). For example: + + from Itpl import Itpl + s = Itpl("Here is $foo.") + foo = 5 + print str(s) + foo = "bar" + print str(s) + +$Id: Itpl.py 542 2005-03-18 09:16:04Z fperez $ +""" # ' -> close an open quote for stupid emacs + +#***************************************************************************** +# +# Copyright (c) 2001 Ka-Ping Yee <ping@lfw.org> +# +# +# Published under the terms of the MIT license, hereby reproduced: +# +# Permission is hereby granted, free of charge, to any person obtaining a copy +# of this software and associated documentation files (the "Software"), to +# deal in the Software without restriction, including without limitation the +# rights to use, copy, modify, merge, publish, distribute, sublicense, and/or +# sell copies of the Software, and to permit persons to whom the Software is +# furnished to do so, subject to the following conditions: +# +# The above copyright notice and this permission notice shall be included in +# all copies or substantial portions of the Software. +# +# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING +# FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS +# IN THE SOFTWARE. +# +#***************************************************************************** + +__author__ = 'Ka-Ping Yee <ping@lfw.org>' +__license__ = 'MIT' + +import sys, string +from types import StringType +from tokenize import tokenprog + +class ItplError(ValueError): + def __init__(self, text, pos): + self.text = text + self.pos = pos + def __str__(self): + return "unfinished expression in %s at char %d" % ( + repr(self.text), self.pos) + +def matchorfail(text, pos): + match = tokenprog.match(text, pos) + if match is None: + raise ItplError(text, pos) + return match, match.end() + +class Itpl: + """Class representing a string with interpolation abilities. + + Upon creation, an instance works out what parts of the format + string are literal and what parts need to be evaluated. The + evaluation and substitution happens in the namespace of the + caller when str(instance) is called.""" + + def __init__(self, format): + """The single argument to this constructor is a format string. + + The format string is parsed according to the following rules: + + 1. A dollar sign and a name, possibly followed by any of: + - an open-paren, and anything up to the matching paren + - an open-bracket, and anything up to the matching bracket + - a period and a name + any number of times, is evaluated as a Python expression. + + 2. A dollar sign immediately followed by an open-brace, and + anything up to the matching close-brace, is evaluated as + a Python expression. + + 3. Outside of the expressions described in the above two rules, + two dollar signs in a row give you one literal dollar sign.""" + + if type(format) != StringType: + raise TypeError, "needs string initializer" + self.format = format + + namechars = "abcdefghijklmnopqrstuvwxyz" \ + "ABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789_"; + chunks = [] + pos = 0 + + while 1: + dollar = string.find(format, "$", pos) + if dollar < 0: break + nextchar = format[dollar+1] + + if nextchar == "{": + chunks.append((0, format[pos:dollar])) + pos, level = dollar+2, 1 + while level: + match, pos = matchorfail(format, pos) + tstart, tend = match.regs[3] + token = format[tstart:tend] + if token == "{": level = level+1 + elif token == "}": level = level-1 + chunks.append((1, format[dollar+2:pos-1])) + + elif nextchar in namechars: + chunks.append((0, format[pos:dollar])) + match, pos = matchorfail(format, dollar+1) + while pos < len(format): + if format[pos] == "." and \ + pos+1 < len(format) and format[pos+1] in namechars: + match, pos = matchorfail(format, pos+1) + elif format[pos] in "([": + pos, level = pos+1, 1 + while level: + match, pos = matchorfail(format, pos) + tstart, tend = match.regs[3] + token = format[tstart:tend] + if token[0] in "([": level = level+1 + elif token[0] in ")]": level = level-1 + else: break + chunks.append((1, format[dollar+1:pos])) + + else: + chunks.append((0, format[pos:dollar+1])) + pos = dollar + 1 + (nextchar == "$") + + if pos < len(format): chunks.append((0, format[pos:])) + self.chunks = chunks + + def __repr__(self): + return "<Itpl %s >" % repr(self.format) + + def __str__(self): + """Evaluate and substitute the appropriate parts of the string.""" + + # We need to skip enough frames to get to the actual caller outside of + # Itpl. + frame = sys._getframe(1) + while frame.f_globals["__name__"] == __name__: frame = frame.f_back + loc, glob = frame.f_locals, frame.f_globals + + result = [] + for live, chunk in self.chunks: + if live: result.append(str(eval(chunk,glob,loc))) + else: result.append(chunk) + + return ''.join(result) + +class ItplNS(Itpl): + """Class representing a string with interpolation abilities. + + This inherits from Itpl, but at creation time a namespace is provided + where the evaluation will occur. The interpolation becomes a bit more + efficient, as no traceback needs to be extracte. It also allows the + caller to supply a different namespace for the interpolation to occur than + its own.""" + + def __init__(self, format,globals,locals=None): + """ItplNS(format,globals[,locals]) -> interpolating string instance. + + This constructor, besides a format string, takes a globals dictionary + and optionally a locals (which defaults to globals if not provided). + + For further details, see the Itpl constructor.""" + + if locals is None: + locals = globals + self.globals = globals + self.locals = locals + Itpl.__init__(self,format) + + def __str__(self): + """Evaluate and substitute the appropriate parts of the string.""" + glob = self.globals + loc = self.locals + result = [] + for live, chunk in self.chunks: + if live: result.append(str(eval(chunk,glob,loc))) + else: result.append(chunk) + return ''.join(result) + +# utilities for fast printing +def itpl(text): return str(Itpl(text)) +def printpl(text): print itpl(text) +# versions with namespace +def itplns(text,globals,locals=None): return str(ItplNS(text,globals,locals)) +def printplns(text,globals,locals=None): print itplns(text,globals,locals) + +class ItplFile: + """A file object that filters each write() through an interpolator.""" + def __init__(self, file): self.file = file + def __repr__(self): return "<interpolated " + repr(self.file) + ">" + def __getattr__(self, attr): return getattr(self.file, attr) + def write(self, text): self.file.write(str(Itpl(text))) + +def filter(file=sys.stdout): + """Return an ItplFile that filters writes to the given file object. + + 'file = filter(file)' replaces 'file' with a filtered object that + has a write() method. When called with no argument, this creates + a filter to sys.stdout.""" + return ItplFile(file) + +def unfilter(ifile=None): + """Return the original file that corresponds to the given ItplFile. + + 'file = unfilter(file)' undoes the effect of 'file = filter(file)'. + 'sys.stdout = unfilter()' undoes the effect of 'sys.stdout = filter()'.""" + return ifile and ifile.file or sys.stdout.file diff --git a/IPython/Logger.py b/IPython/Logger.py new file mode 100644 index 0000000..ae721aa --- /dev/null +++ b/IPython/Logger.py @@ -0,0 +1,185 @@ +# -*- coding: utf-8 -*- +""" +Logger class for IPython's logging facilities. + +$Id: Logger.py 430 2004-11-30 08:52:05Z fperez $ +""" + +#***************************************************************************** +# Copyright (C) 2001 Janko Hauser <jhauser@zscout.de> and +# Copyright (C) 2001-2004 Fernando Perez <fperez@colorado.edu> +# +# Distributed under the terms of the BSD License. The full license is in +# the file COPYING, distributed as part of this software. +#***************************************************************************** + +#**************************************************************************** +# Modules and globals + +from IPython import Release +__author__ = '%s <%s>\n%s <%s>' % \ + ( Release.authors['Janko'] + Release.authors['Fernando'] ) +__license__ = Release.license + +# Python standard modules +import os,sys,glob + +# Homebrewed +from IPython.genutils import * + +#**************************************************************************** +# FIXME: The logger class shouldn't be a mixin, it throws too many things into +# the InteractiveShell namespace. Rather make it a standalone tool, and create +# a Logger instance in InteractiveShell that uses it. Doing this will require +# tracking down a *lot* of nasty uses of the Logger attributes in +# InteractiveShell, but will clean up things quite a bit. + +class Logger: + """A Logfile Mixin class with different policies for file creation""" + + # FIXME: once this isn't a mixin, log_ns should just be 'namespace', since the + # names won't collide anymore. + def __init__(self,log_ns): + self._i00,self._i,self._ii,self._iii = '','','','' + self.do_full_cache = 0 # FIXME. There's also a do_full.. in OutputCache + self.log_ns = log_ns + # defaults + self.LOGMODE = 'backup' + self.defname = 'logfile' + + def create_log(self,header='',fname='',defname='.Logger.log'): + """Generate a new log-file with a default header""" + if fname: + self.LOG = fname + + if self.LOG: + self.logfname = self.LOG + else: + self.logfname = defname + + if self.LOGMODE == 'over': + if os.path.isfile(self.logfname): + os.remove(self.logfname) + self.logfile = open(self.logfname,'w') + if self.LOGMODE == 'backup': + if os.path.isfile(self.logfname): + backup_logname = self.logfname+'~' + # Manually remove any old backup, since os.rename may fail + # under Windows. + if os.path.isfile(backup_logname): + os.remove(backup_logname) + os.rename(self.logfname,backup_logname) + self.logfile = open(self.logfname,'w') + elif self.LOGMODE == 'global': + self.logfname = os.path.join(self.home_dir, self.defname) + self.logfile = open(self.logfname, 'a') + self.LOG = self.logfname + elif self.LOGMODE == 'rotate': + if os.path.isfile(self.logfname): + if os.path.isfile(self.logfname+'.001~'): + old = glob.glob(self.logfname+'.*~') + old.sort() + old.reverse() + for f in old: + root, ext = os.path.splitext(f) + num = int(ext[1:-1])+1 + os.rename(f, root+'.'+`num`.zfill(3)+'~') + os.rename(self.logfname, self.logfname+'.001~') + self.logfile = open(self.logfname,'w') + elif self.LOGMODE == 'append': + self.logfile = open(self.logfname,'a') + + if self.LOGMODE != 'append': + self.logfile.write(header) + self.logfile.flush() + + def logstart(self, header='',parameter_s = ''): + if not hasattr(self, 'LOG'): + logfname = self.LOG or parameter_s or './'+self.defname + self.create_log(header,logfname) + elif parameter_s and hasattr(self,'logfname') and \ + parameter_s != self.logfname: + self.close_log() + self.create_log(header,parameter_s) + + self._dolog = 1 + + def switch_log(self,val): + """Switch logging on/off. val should be ONLY 0 or 1.""" + + if not val in [0,1]: + raise ValueError, \ + 'Call switch_log ONLY with 0 or 1 as argument, not with:',val + + label = {0:'OFF',1:'ON'} + + try: + _ = self.logfile + except AttributeError: + print """ +Logging hasn't been started yet (use %logstart for that). + +%logon/%logoff are for temporarily starting and stopping logging for a logfile +which already exists. But you must first start the logging process with +%logstart (optionally giving a logfile name).""" + + else: + if self._dolog == val: + print 'Logging is already',label[val] + else: + print 'Switching logging',label[val] + self._dolog = 1 - self._dolog + + def logstate(self): + """Print a status message about the logger.""" + try: + logfile = self.logfname + except: + print 'Logging has not been activated.' + else: + state = self._dolog and 'active' or 'temporarily suspended' + print """ +File:\t%s +Mode:\t%s +State:\t%s """ % (logfile,self.LOGMODE,state) + + + def log(self, line,continuation=None): + """Write the line to a log and create input cache variables _i*.""" + + # update the auto _i tables + #print '***logging line',line # dbg + #print '***cache_count', self.outputcache.prompt_count # dbg + input_hist = self.log_ns['_ih'] + if not continuation and line: + self._iii = self._ii + self._ii = self._i + self._i = self._i00 + # put back the final \n of every input line + self._i00 = line+'\n' + #print 'Logging input:<%s>' % line # dbg + input_hist.append(self._i00) + + # hackish access to top-level namespace to create _i1,_i2... dynamically + to_main = {'_i':self._i,'_ii':self._ii,'_iii':self._iii} + if self.do_full_cache: + in_num = self.outputcache.prompt_count + # add blank lines if the input cache fell out of sync. This can happen + # for embedded instances which get killed via C-D and then get resumed. + while in_num >= len(input_hist): + input_hist.append('\n') + new_i = '_i%s' % in_num + if continuation: + self._i00 = '%s%s\n' % (self.log_ns[new_i],line) + input_hist[in_num] = self._i00 + to_main[new_i] = self._i00 + self.log_ns.update(to_main) + + if self._dolog and line: + self.logfile.write(line+'\n') + self.logfile.flush() + + def close_log(self): + if hasattr(self, 'logfile'): + self.logfile.close() + self.logfname = '' diff --git a/IPython/Magic.py b/IPython/Magic.py new file mode 100644 index 0000000..2096c73 --- /dev/null +++ b/IPython/Magic.py @@ -0,0 +1,2490 @@ +# -*- coding: utf-8 -*- +"""Magic functions for InteractiveShell. + +$Id: Magic.py 583 2005-05-13 21:20:33Z fperez $""" + +#***************************************************************************** +# Copyright (C) 2001 Janko Hauser <jhauser@zscout.de> and +# Copyright (C) 2001-2004 Fernando Perez <fperez@colorado.edu> +# +# Distributed under the terms of the BSD License. The full license is in +# the file COPYING, distributed as part of this software. +#***************************************************************************** + +#**************************************************************************** +# Modules and globals + +from IPython import Release +__author__ = '%s <%s>\n%s <%s>' % \ + ( Release.authors['Janko'] + Release.authors['Fernando'] ) +__license__ = Release.license + +# Python standard modules +import __builtin__ +import os,sys,inspect,pydoc,re,tempfile,shlex,pdb,bdb,time +try: + import profile,pstats +except ImportError: + profile = pstats = None +from getopt import getopt +from pprint import pprint, pformat +from cStringIO import StringIO + +# Homebrewed +from IPython.Struct import Struct +from IPython.Itpl import Itpl, itpl, printpl,itplns +from IPython.FakeModule import FakeModule +from IPython import OInspect +from IPython.genutils import * + +# Globals to be set later by Magic constructor +MAGIC_PREFIX = '' +MAGIC_ESCAPE = '' + +#*************************************************************************** +# Utility functions +def magic2python(cmd): + """Convert a command string of magic syntax to valid Python code.""" + + if cmd.startswith('#'+MAGIC_ESCAPE) or \ + cmd.startswith(MAGIC_ESCAPE): + if cmd[0]=='#': + cmd = cmd[1:] + # we need to return the proper line end later + if cmd[-1] == '\n': + endl = '\n' + else: + endl = '' + try: + func,args = cmd[1:].split(' ',1) + except: + func,args = cmd[1:].rstrip(),'' + args = args.replace('"','\\"').replace("'","\\'").rstrip() + return '%s%s ("%s")%s' % (MAGIC_PREFIX,func,args,endl) + else: + return cmd + +def on_off(tag): + """Return an ON/OFF string for a 1/0 input. Simple utility function.""" + return ['OFF','ON'][tag] + +def get_py_filename(name): + """Return a valid python filename in the current directory. + + If the given name is not a file, it adds '.py' and searches again. + Raises IOError with an informative message if the file isn't found.""" + + name = os.path.expanduser(name) + if not os.path.isfile(name) and not name.endswith('.py'): + name += '.py' + if os.path.isfile(name): + return name + else: + raise IOError,'File `%s` not found.' % name + +# Try to use shlex.split for converting an input string into a sys.argv-type +# list. This appeared in Python 2.3, so here's a quick backport for 2.2. +try: + shlex_split = shlex.split +except AttributeError: + _quotesre = re.compile(r'[\'"](.*)[\'"]') + _wordchars = ('abcdfeghijklmnopqrstuvwxyz' + 'ABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789_-.~*?' + 'ßàáâãäåæçèéêëìíîïðñòóôõöøùúûüýþÿ' + 'ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖØÙÚÛÜÝÞ%s' + % os.sep) + + def shlex_split(s): + """Simplified backport to Python 2.2 of shlex.split(). + + This is a quick and dirty hack, since the shlex module under 2.2 lacks + several of the features needed to really match the functionality of + shlex.split() in 2.3.""" + + lex = shlex.shlex(StringIO(s)) + # Try to get options, extensions and path separators as characters + lex.wordchars = _wordchars + lex.commenters = '' + # Make a list out of the lexer by hand, since in 2.2 it's not an + # iterator. + lout = [] + while 1: + token = lex.get_token() + if token == '': + break + # Try to handle quoted tokens correctly + quotes = _quotesre.match(token) + if quotes: + token = quotes.group(1) + lout.append(token) + return lout + +#**************************************************************************** +# Utility classes +class Macro: + """Simple class to store the value of macros as strings. + + This allows us to later exec them by checking when something is an + instance of this class.""" + + def __init__(self,cmds): + """Build a macro from a list of commands.""" + + # Since the list may include multi-line entries, first make sure that + # they've been all broken up before passing it to magic2python + cmdlist = map(magic2python,''.join(cmds).split('\n')) + self.value = '\n'.join(cmdlist) + + def __str__(self): + return self.value + +#*************************************************************************** +# Main class implementing Magic functionality +class Magic: + """Magic functions for InteractiveShell. + + Shell functions which can be reached as %function_name. All magic + functions should accept a string, which they can parse for their own + needs. This can make some functions easier to type, eg `%cd ../` + vs. `%cd("../")` + + ALL definitions MUST begin with the prefix magic_. The user won't need it + at the command line, but it is is needed in the definition. """ + + # class globals + auto_status = ['Automagic is OFF, % prefix IS needed for magic functions.', + 'Automagic is ON, % prefix NOT needed for magic functions.'] + + #...................................................................... + # some utility functions + + def __init__(self,shell): + # XXX This is hackish, clean up later to avoid these messy globals + global MAGIC_PREFIX, MAGIC_ESCAPE + + self.options_table = {} + MAGIC_PREFIX = shell.name+'.magic_' + MAGIC_ESCAPE = shell.ESC_MAGIC + if profile is None: + self.magic_prun = self.profile_missing_notice + + 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.""") + + def default_option(self,fn,optstr): + """Make an entry in the options_table for fn, with value optstr""" + + if fn not in self.lsmagic(): + error("%s is not a magic function" % fn) + self.options_table[fn] = optstr + + def lsmagic(self): + """Return a list of currently available magic functions. + + Gives a list of the bare names after mangling (['ls','cd', ...], not + ['magic_ls','magic_cd',...]""" + + # FIXME. This needs a cleanup, in the way the magics list is built. + + # magics in class definition + class_magic = lambda fn: fn.startswith('magic_') and \ + callable(Magic.__dict__[fn]) + # in instance namespace (run-time user additions) + inst_magic = lambda fn: fn.startswith('magic_') and \ + callable(self.__dict__[fn]) + # and bound magics by user (so they can access self): + inst_bound_magic = lambda fn: fn.startswith('magic_') and \ + callable(self.__class__.__dict__[fn]) + magics = filter(class_magic,Magic.__dict__.keys()) + \ + filter(inst_magic,self.__dict__.keys()) + \ + filter(inst_bound_magic,self.__class__.__dict__.keys()) + out = [] + for fn in magics: + out.append(fn.replace('magic_','',1)) + out.sort() + return out + + def set_shell(self,shell): + self.shell = shell + self.alias_table = shell.alias_table + + def extract_input_slices(self,slices): + """Return as a string a set of input history slices. + + The set of slices is given as a list of strings (like ['1','4:8','9'], + since this function is for use by magic functions which get their + arguments as strings.""" + + cmds = [] + for chunk in slices: + if ':' in chunk: + ini,fin = map(int,chunk.split(':')) + else: + ini = int(chunk) + fin = ini+1 + cmds.append(self.shell.input_hist[ini:fin]) + return cmds + + def _ofind(self,oname): + """Find an object in the available namespaces. + + self._ofind(oname) -> dict with keys: found,obj,ospace,ismagic + + Has special code to detect magic functions. + """ + + oname = oname.strip() + + # Namespaces to search in: + user_ns = self.shell.user_ns + internal_ns = self.shell.internal_ns + builtin_ns = __builtin__.__dict__ + alias_ns = self.shell.alias_table + + # Put them in a list. The order is important so that we find things in + # the same order that Python finds them. + namespaces = [ ('Interactive',user_ns), + ('IPython internal',internal_ns), + ('Python builtin',builtin_ns), + ('Alias',alias_ns), + ] + + # initialize results to 'null' + found = 0; obj = None; ospace = None; ds = None; + ismagic = 0; isalias = 0 + + # Look for the given name by splitting it in parts. If the head is + # found, then we look for all the remaining parts as members, and only + # declare success if we can find them all. + oname_parts = oname.split('.') + oname_head, oname_rest = oname_parts[0],oname_parts[1:] + for nsname,ns in namespaces: + try: + obj = ns[oname_head] + except KeyError: + continue + else: + for part in oname_rest: + try: + obj = getattr(obj,part) + except: + # Blanket except b/c some badly implemented objects + # allow __getattr__ to raise exceptions other than + # AttributeError, which then crashes IPython. + break + else: + # If we finish the for loop (no break), we got all members + found = 1 + ospace = nsname + if ns == alias_ns: + isalias = 1 + break # namespace loop + + # Try to see if it's magic + if not found: + if oname.startswith(self.shell.ESC_MAGIC): + oname = oname[1:] + obj = getattr(self,'magic_'+oname,None) + if obj is not None: + found = 1 + ospace = 'IPython internal' + ismagic = 1 + + # Last try: special-case some literals like '', [], {}, etc: + if not found and oname_head in ["''",'""','[]','{}','()']: + obj = eval(oname_head) + found = 1 + ospace = 'Interactive' + + return {'found':found, 'obj':obj, 'namespace':ospace, + 'ismagic':ismagic, 'isalias':isalias} + + def arg_err(self,func): + """Print docstring if incorrect arguments were passed""" + print 'Error in arguments:' + print OInspect.getdoc(func) + + + def format_latex(self,str): + """Format a string for latex inclusion.""" + + # Characters that need to be escaped for latex: + escape_re = re.compile(r'(%|_|\$)',re.MULTILINE) + # Magic command names as headers: + cmd_name_re = re.compile(r'^(%s.*?):' % self.shell.ESC_MAGIC, + re.MULTILINE) + # Magic commands + cmd_re = re.compile(r'(?P<cmd>%s.+?\b)(?!\}\}:)' % self.shell.ESC_MAGIC, + re.MULTILINE) + # Paragraph continue + par_re = re.compile(r'\\$',re.MULTILINE) + + str = cmd_name_re.sub(r'\n\\texttt{\\textsl{\\large \1}}:',str) + str = cmd_re.sub(r'\\texttt{\g<cmd>}',str) + str = par_re.sub(r'\\\\',str) + str = escape_re.sub(r'\\\1',str) + return str + + def format_screen(self,str): + """Format a string for screen printing. + + This removes some latex-type format codes.""" + # Paragraph continue + par_re = re.compile(r'\\$',re.MULTILINE) + str = par_re.sub('',str) + return str + + def parse_options(self,arg_str,opt_str,*long_opts,**kw): + """Parse options passed to an argument string. + + The interface is similar to that of getopt(), but it returns back a + Struct with the options as keys and the stripped argument string still + as a string. + + arg_str is quoted as a true sys.argv vector by calling on the fly a + python process in a subshell. This allows us to easily expand + variables, glob files, quote arguments, etc, with all the power and + correctness of the underlying system shell. + + Options: + -mode: default 'string'. If given as 'list', the argument string is + returned as a list (split on whitespace) instead of a string. + + -list_all: put all option values in lists. Normally only options + appearing more than once are put in a list.""" + + # inject default options at the beginning of the input line + caller = sys._getframe(1).f_code.co_name.replace('magic_','') + arg_str = '%s %s' % (self.options_table.get(caller,''),arg_str) + + mode = kw.get('mode','string') + if mode not in ['string','list']: + raise ValueError,'incorrect mode given: %s' % mode + # Get options + list_all = kw.get('list_all',0) + + # Check if we have more than one argument to warrant extra processing: + odict = {} # Dictionary with options + args = arg_str.split() + if len(args) >= 1: + # If the list of inputs only has 0 or 1 thing in it, there's no + # need to look for options + argv = shlex_split(arg_str) + # Do regular option processing + opts,args = getopt(argv,opt_str,*long_opts) + for o,a in opts: + if o.startswith('--'): + o = o[2:] + else: + o = o[1:] + try: + odict[o].append(a) + except AttributeError: + odict[o] = [odict[o],a] + except KeyError: + if list_all: + odict[o] = [a] + else: + odict[o] = a + + # Prepare opts,args for return + opts = Struct(odict) + if mode == 'string': + args = ' '.join(args) + + return opts,args + + #...................................................................... + # And now the actual magic functions + + # Functions for IPython shell work (vars,funcs, config, etc) + def magic_lsmagic(self, parameter_s = ''): + """List currently available magic functions.""" + mesc = self.shell.ESC_MAGIC + print 'Available magic functions:\n'+mesc+\ + (' '+mesc).join(self.lsmagic()) + print '\n' + Magic.auto_status[self.shell.rc.automagic] + return None + + def magic_magic(self, parameter_s = ''): + """Print information about the magic function system.""" + + mode = '' + try: + if parameter_s.split()[0] == '-latex': + mode = 'latex' + except: + pass + + magic_docs = [] + for fname in self.lsmagic(): + mname = 'magic_' + fname + for space in (Magic,self,self.__class__): + try: + fn = space.__dict__[mname] + except KeyError: + pass + else: + break + magic_docs.append('%s%s:\n\t%s\n' %(self.shell.ESC_MAGIC, + fname,fn.__doc__)) + magic_docs = ''.join(magic_docs) + + if mode == 'latex': + print self.format_latex(magic_docs) + return + else: + magic_docs = self.format_screen(magic_docs) + + outmsg = """ +IPython's 'magic' functions +=========================== + +The magic function system provides a series of functions which allow you to +control the behavior of IPython itself, plus a lot of system-type +features. All these functions are prefixed with a % character, but parameters +are given without parentheses or quotes. + +NOTE: If you have 'automagic' enabled (via the command line option or with the +%automagic function), you don't need to type in the % explicitly. By default, +IPython ships with automagic on, so you should only rarely need the % escape. + +Example: typing '%cd mydir' (without the quotes) changes you working directory +to 'mydir', if it exists. + +You can define your own magic functions to extend the system. See the supplied +ipythonrc and example-magic.py files for details (in your ipython +configuration directory, typically $HOME/.ipython/). + +You can also define your own aliased names for magic functions. In your +ipythonrc file, placing a line like: + + execute __IPYTHON__.magic_pf = __IPYTHON__.magic_profile + +will define %pf as a new name for %profile. + +You can also call magics in code using the ipmagic() function, which IPython +automatically adds to the builtin namespace. Type 'ipmagic?' for details. + +For a list of the available magic functions, use %lsmagic. For a description +of any of them, type %magic_name?, e.g. '%cd?'. + +Currently the magic system has the following functions:\n""" + + mesc = self.shell.ESC_MAGIC + outmsg = ("%s\n%s\n\nSummary of magic functions (from %slsmagic):" + "\n\n%s%s\n\n%s" % (outmsg, + magic_docs,mesc,mesc, + (' '+mesc).join(self.lsmagic()), + Magic.auto_status[self.shell.rc.automagic] ) ) + + page(outmsg,screen_lines=self.shell.rc.screen_length) + + def magic_automagic(self, parameter_s = ''): + """Make magic functions callable without having to type the initial %. + + Toggles on/off (when off, you must call it as %automagic, of + course). Note that magic functions have lowest priority, so if there's + a variable whose name collides with that of a magic fn, automagic + won't work for that function (you get the variable instead). However, + if you delete the variable (del var), the previously shadowed magic + function becomes visible to automagic again.""" + + rc = self.shell.rc + rc.automagic = not rc.automagic + print '\n' + Magic.auto_status[rc.automagic] + + def magic_autocall(self, parameter_s = ''): + """Make functions callable without having to type parentheses. + + This toggles the autocall command line option on and off.""" + + rc = self.shell.rc + rc.autocall = not rc.autocall + print "Automatic calling is:",['OFF','ON'][rc.autocall] + + def magic_autoindent(self, parameter_s = ''): + """Toggle autoindent on/off (if available).""" + + self.shell.set_autoindent() + print "Automatic indentation is:",['OFF','ON'][self.shell.autoindent] + + def magic_system_verbose(self, parameter_s = ''): + """Toggle verbose printing of system calls on/off.""" + + self.shell.rc_set_toggle('system_verbose') + print "System verbose printing is:",\ + ['OFF','ON'][self.shell.rc.system_verbose] + + def magic_history(self, parameter_s = ''): + """Print input history (_i<n> variables), with most recent last. + + %history [-n] -> print at most 40 inputs (some may be multi-line)\\ + %history [-n] n -> print at most n inputs\\ + %history [-n] n1 n2 -> print inputs between n1 and n2 (n2 not included)\\ + + Each input's number <n> is shown, and is accessible as the + automatically generated variable _i<n>. Multi-line statements are + printed starting at a new line for easy copy/paste. + + If option -n is used, input numbers are not printed. This is useful if + you want to get a printout of many lines which can be directly pasted + into a text editor. + + This feature is only available if numbered prompts are in use.""" + + if not self.do_full_cache: + print 'This feature is only available if numbered prompts are in use.' + return + opts,args = self.parse_options(parameter_s,'n',mode='list') + + default_length = 40 + if len(args) == 0: + final = self.outputcache.prompt_count + init = max(1,final-default_length) + elif len(args) == 1: + final = self.outputcache.prompt_count + init = max(1,final-int(args[0])) + elif len(args) == 2: + init,final = map(int,args) + else: + warn('%hist takes 0, 1 or 2 arguments separated by spaces.') + print self.magic_hist.__doc__ + return + width = len(str(final)) + line_sep = ['','\n'] + input_hist = self.shell.input_hist + print_nums = not opts.has_key('n') + for in_num in range(init,final): + inline = input_hist[in_num] + multiline = inline.count('\n') > 1 + if print_nums: + print str(in_num).ljust(width)+':'+ line_sep[multiline], + if inline.startswith('#'+self.shell.ESC_MAGIC) or \ + inline.startswith('#!'): + print inline[1:], + else: + print inline, + + def magic_hist(self, parameter_s=''): + """Alternate name for %history.""" + return self.magic_history(parameter_s) + + def magic_p(self, parameter_s=''): + """Just a short alias for Python's 'print'.""" + exec 'print ' + parameter_s in self.shell.user_ns + + def magic_r(self, parameter_s=''): + """Repeat previous input. + + If given an argument, repeats the previous command which starts with + the same string, otherwise it just repeats the previous input. + + Shell escaped commands (with ! as first character) are not recognized + by this system, only pure python code and magic commands. + """ + + start = parameter_s.strip() + esc_magic = self.shell.ESC_MAGIC + # Identify magic commands even if automagic is on (which means + # the in-memory version is different from that typed by the user). + if self.shell.rc.automagic: + start_magic = esc_magic+start + else: + start_magic = start + # Look through the input history in reverse + for n in range(len(self.shell.input_hist)-2,0,-1): + input = self.shell.input_hist[n] + # skip plain 'r' lines so we don't recurse to infinity + if input != 'ipmagic("r")\n' and \ + (input.startswith(start) or input.startswith(start_magic)): + #print 'match',`input` # dbg + if input.startswith(esc_magic): + input = magic2python(input) + #print 'modified',`input` # dbg + print 'Executing:',input, + exec input in self.shell.user_ns + return + print 'No previous input matching `%s` found.' % start + + def magic_page(self, parameter_s=''): + """Pretty print the object and display it through a pager. + + If no parameter is given, use _ (last output).""" + # After a function contributed by Olivier Aubert, slightly modified. + + oname = parameter_s and parameter_s or '_' + info = self._ofind(oname) + if info['found']: + page(pformat(info['obj'])) + else: + print 'Object `%s` not found' % oname + + def magic_profile(self, parameter_s=''): + """Print your currently active IPyhton profile.""" + if self.shell.rc.profile: + printpl('Current IPython profile: $self.shell.rc.profile.') + else: + print 'No profile active.' + + def _inspect(self,meth,oname,**kw): + """Generic interface to the inspector system. + + This function is meant to be called by pdef, pdoc & friends.""" + + oname = oname.strip() + info = Struct(self._ofind(oname)) + if info.found: + pmethod = getattr(self.shell.inspector,meth) + formatter = info.ismagic and self.format_screen or None + if meth == 'pdoc': + pmethod(info.obj,oname,formatter) + elif meth == 'pinfo': + pmethod(info.obj,oname,formatter,info,**kw) + else: + pmethod(info.obj,oname) + else: + print 'Object `%s` not found.' % oname + return 'not found' # so callers can take other action + + def magic_pdef(self, parameter_s=''): + """Print the definition header for any callable object. + + If the object is a class, print the constructor information.""" + self._inspect('pdef',parameter_s) + + def magic_pdoc(self, parameter_s=''): + """Print the docstring for an object. + + If the given object is a class, it will print both the class and the + constructor docstrings.""" + self._inspect('pdoc',parameter_s) + + def magic_psource(self, parameter_s=''): + """Print (or run through pager) the source code for an object.""" + self._inspect('psource',parameter_s) + + def magic_pfile(self, parameter_s=''): + """Print (or run through pager) the file where an object is defined. + + The file opens at the line where the object definition begins. IPython + will honor the environment variable PAGER if set, and otherwise will + do its best to print the file in a convenient form. + + If the given argument is not an object currently defined, IPython will + try to interpret it as a filename (automatically adding a .py extension + if needed). You can thus use %pfile as a syntax highlighting code + viewer.""" + + # first interpret argument as an object name + out = self._inspect('pfile',parameter_s) + # if not, try the input as a filename + if out == 'not found': + try: + filename = get_py_filename(parameter_s) + except IOError,msg: + print msg + return + page(self.shell.inspector.format(file(filename).read())) + + def magic_pinfo(self, parameter_s=''): + """Provide detailed information about an object. + + '%pinfo object' is just a synonym for object? or ?object.""" + + #print 'pinfo par: <%s>' % parameter_s # dbg + + # detail_level: 0 -> obj? , 1 -> obj?? + detail_level = 0 + # We need to detect if we got called as 'pinfo pinfo foo', which can + # happen if the user types 'pinfo foo?' at the cmd line. + pinfo,qmark1,oname,qmark2 = \ + re.match('(pinfo )?(\?*)(.*?)(\??$)',parameter_s).groups() + if pinfo or qmark1 or qmark2: + detail_level = 1 + self._inspect('pinfo',oname,detail_level=detail_level) + + def magic_who_ls(self, parameter_s=''): + """Return a sorted list of all interactive variables. + + If arguments are given, only variables of types matching these + arguments are returned.""" + + user_ns = self.shell.user_ns + out = [] + typelist = parameter_s.split() + for i in self.shell.user_ns.keys(): + if not (i.startswith('_') or i.startswith('_i')) \ + and not (self.internal_ns.has_key(i) or + self.user_config_ns.has_key(i)): + if typelist: + if type(user_ns[i]).__name__ in typelist: + out.append(i) + else: + out.append(i) + out.sort() + return out + + def magic_who(self, parameter_s=''): + """Print all interactive variables, with some minimal formatting. + + If any arguments are given, only variables whose type matches one of + these are printed. For example: + + %who function str + + will only list functions and strings, excluding all other types of + variables. To find the proper type names, simply use type(var) at a + command line to see how python prints type names. For example: + + In [1]: type('hello')\\ + Out[1]: <type 'str'> + + indicates that the type name for strings is 'str'. + + %who always excludes executed names loaded through your configuration + file and things which are internal to IPython. + + This is deliberate, as typically you may load many modules and the + purpose of %who is to show you only what you've manually defined.""" + + varlist = self.magic_who_ls(parameter_s) + if not varlist: + print 'Interactive namespace is empty.' + return + + # if we have variables, move on... + + # stupid flushing problem: when prompts have no separators, stdout is + # getting lost. I'm starting to think this is a python bug. I'm having + # to force a flush with a print because even a sys.stdout.flush + # doesn't seem to do anything! + + count = 0 + for i in varlist: + print i+'\t', + count += 1 + if count > 8: + count = 0 + print + sys.stdout.flush() # FIXME. Why the hell isn't this flushing??? + + print # well, this does force a flush at the expense of an extra \n + + def magic_whos(self, parameter_s=''): + """Like %who, but gives some extra information about each variable. + + The same type filtering of %who can be applied here. + + For all variables, the type is printed. Additionally it prints: + + - For {},[],(): their length. + + - For Numeric arrays, a summary with shape, number of elements, + typecode and size in memory. + + - Everything else: a string representation, snipping their middle if + too long.""" + + varnames = self.magic_who_ls(parameter_s) + if not varnames: + print 'Interactive namespace is empty.' + return + + # if we have variables, move on... + + # for these types, show len() instead of data: + seq_types = [types.DictType,types.ListType,types.TupleType] + + # for Numeric arrays, display summary info + try: + import Numeric + except ImportError: + array_type = None + else: + array_type = Numeric.ArrayType.__name__ + + # Find all variable names and types so we can figure out column sizes + get_vars = lambda i: self.locals[i] + type_name = lambda v: type(v).__name__ + varlist = map(get_vars,varnames) + typelist = map(type_name,varlist) + # column labels and # of spaces as separator + varlabel = 'Variable' + typelabel = 'Type' + datalabel = 'Data/Info' + colsep = 3 + # variable format strings + vformat = "$vname.ljust(varwidth)$vtype.ljust(typewidth)" + vfmt_short = '$vstr[:25]<...>$vstr[-25:]' + aformat = "%s: %s elems, type `%s`, %s bytes" + # find the size of the columns to format the output nicely + varwidth = max(max(map(len,varnames)), len(varlabel)) + colsep + typewidth = max(max(map(len,typelist)), len(typelabel)) + colsep + # table header + print varlabel.ljust(varwidth) + typelabel.ljust(typewidth) + \ + ' '+datalabel+'\n' + '-'*(varwidth+typewidth+len(datalabel)+1) + # and the table itself + kb = 1024 + Mb = 1048576 # kb**2 + for vname,var,vtype in zip(varnames,varlist,typelist): + print itpl(vformat), + if vtype in seq_types: + print len(var) + elif vtype==array_type: + vshape = str(var.shape).replace(',','').replace(' ','x')[1:-1] + vsize = Numeric.size(var) + vbytes = vsize*var.itemsize() + if vbytes < 100000: + print aformat % (vshape,vsize,var.typecode(),vbytes) + else: + print aformat % (vshape,vsize,var.typecode(),vbytes), + if vbytes < Mb: + print '(%s kb)' % (vbytes/kb,) + else: + print '(%s Mb)' % (vbytes/Mb,) + else: + vstr = str(var) + if len(vstr) < 50: + print vstr + else: + printpl(vfmt_short) + + def magic_reset(self, parameter_s=''): + """Resets the namespace by removing all names defined by the user. + + Input/Output history are left around in case you need them.""" + + ans = raw_input( + "Once deleted, variables cannot be recovered. Proceed (y/n)? ") + if not ans.lower() == 'y': + print 'Nothing done.' + return + for i in self.magic_who_ls(): + del(self.locals[i]) + + def magic_config(self,parameter_s=''): + """Show IPython's internal configuration.""" + + page('Current configuration structure:\n'+ + pformat(self.shell.rc.dict())) + + def magic_logstart(self,parameter_s=''): + """Start logging anywhere in a session. + + %logstart [log_name [log_mode]] + + If no name is given, it defaults to a file named 'ipython.log' in your + current directory, in 'rotate' mode (see below). + + '%logstart name' saves to file 'name' in 'backup' mode. It saves your + history up to that point and then continues logging. + + %logstart takes a second optional parameter: logging mode. This can be one + of (note that the modes are given unquoted):\\ + over: overwrite existing log.\\ + backup: rename (if exists) to name~ and start name.\\ + append: well, that says it.\\ + rotate: create rotating logs name.1~, name.2~, etc. + """ + + #FIXME. This function should all be moved to the Logger class. + + valid_modes = qw('over backup append rotate') + if self.LOG: + print 'Logging is already in place. Logfile:',self.LOG + return + + par = parameter_s.strip() + if not par: + logname = self.LOGDEF + logmode = 'rotate' # use rotate for the auto-generated logs + else: + try: + logname,logmode = par.split() + except: + try: + logname = par + logmode = 'backup' + except: + warn('Usage: %log [log_name [log_mode]]') + return + if not logmode in valid_modes: + warn('Logging NOT activated.\n' + 'Usage: %log [log_name [log_mode]]\n' + 'Valid modes: '+str(valid_modes)) + return + + # If we made it this far, I think we're ok: + print 'Activating auto-logging.' + print 'Current session state plus future input saved to:',logname + print 'Logging mode: ',logmode + # put logname into rc struct as if it had been called on the command line, + # so it ends up saved in the log header + # Save it in case we need to restore it... + old_logfile = self.shell.rc.opts.get('logfile','') + logname = os.path.expanduser(logname) + self.shell.rc.opts.logfile = logname + self.LOGMODE = logmode # FIXME: this should be set through a function. + try: + header = str(self.LOGHEAD) + self.create_log(header,logname) + self.logstart(header,logname) + except: + self.LOG = '' # we are NOT logging, something went wrong + self.shell.rc.opts.logfile = old_logfile + warn("Couldn't start log: "+str(sys.exc_info()[1])) + else: # log input history up to this point + self.logfile.write(self.shell.user_ns['_ih'][1:]) + self.logfile.flush() + + def magic_logoff(self,parameter_s=''): + """Temporarily stop logging. + + You must have previously started logging.""" + self.switch_log(0) + + def magic_logon(self,parameter_s=''): + """Restart logging. + + This function is for restarting logging which you've temporarily + stopped with %logoff. For starting logging for the first time, you + must use the %logstart function, which allows you to specify an + optional log filename.""" + + self.switch_log(1) + + def magic_logstate(self,parameter_s=''): + """Print the status of the logging system.""" + + self.logstate() + + def magic_pdb(self, parameter_s=''): + """Control the calling of the pdb interactive debugger. + + Call as '%pdb on', '%pdb 1', '%pdb off' or '%pdb 0'. If called without + argument it works as a toggle. + + When an exception is triggered, IPython can optionally call the + interactive pdb debugger after the traceback printout. %pdb toggles + this feature on and off.""" + + par = parameter_s.strip().lower() + + if par: + try: + pdb = {'off':0,'0':0,'on':1,'1':1}[par] + except KeyError: + print 'Incorrect argument. Use on/1, off/0 or nothing for a toggle.' + return + else: + self.shell.InteractiveTB.call_pdb = pdb + else: + self.shell.InteractiveTB.call_pdb = 1 - self.shell.InteractiveTB.call_pdb + print 'Automatic pdb calling has been turned',\ + on_off(self.shell.InteractiveTB.call_pdb) + + + def magic_prun(self, parameter_s ='',user_mode=1, + opts=None,arg_lst=None,prog_ns=None): + + """Run a statement through the python code profiler. + + Usage:\\ + %prun [options] statement + + The given statement (which doesn't require quote marks) is run via the + python profiler in a manner similar to the profile.run() function. + Namespaces are internally managed to work correctly; profile.run + cannot be used in IPython because it makes certain assumptions about + namespaces which do not hold under IPython. + + Options: + + -l <limit>: you can place restrictions on what or how much of the + profile gets printed. The limit value can be: + + * A string: only information for function names containing this string + is printed. + + * An integer: only these many lines are printed. + + * A float (between 0 and 1): this fraction of the report is printed + (for example, use a limit of 0.4 to see the topmost 40% only). + + You can combine several limits with repeated use of the option. For + example, '-l __init__ -l 5' will print only the topmost 5 lines of + information about class constructors. + + -r: return the pstats.Stats object generated by the profiling. This + object has all the information about the profile in it, and you can + later use it for further analysis or in other functions. + + Since magic functions have a particular form of calling which prevents + you from writing something like:\\ + In [1]: p = %prun -r print 4 # invalid!\\ + you must instead use IPython's automatic variables to assign this:\\ + In [1]: %prun -r print 4 \\ + Out[1]: <pstats.Stats instance at 0x8222cec>\\ + In [2]: stats = _ + + If you really need to assign this value via an explicit function call, + you can always tap directly into the true name of the magic function + by using the ipmagic function (which IPython automatically adds to the + builtins):\\ + In [3]: stats = ipmagic('prun','-r print 4') + + You can type ipmagic? for more details on ipmagic. + + -s <key>: sort profile by given key. You can provide more than one key + by using the option several times: '-s key1 -s key2 -s key3...'. The + default sorting key is 'time'. + + The following is copied verbatim from the profile documentation + referenced below: + + When more than one key is provided, additional keys are used as + secondary criteria when the there is equality in all keys selected + before them. + + Abbreviations can be used for any key names, as long as the + abbreviation is unambiguous. The following are the keys currently + defined: + + Valid Arg Meaning\\ + "calls" call count\\ + "cumulative" cumulative time\\ + "file" file name\\ + "module" file name\\ + "pcalls" primitive call count\\ + "line" line number\\ + "name" function name\\ + "nfl" name/file/line\\ + "stdname" standard name\\ + "time" internal time + + Note that all sorts on statistics are in descending order (placing + most time consuming items first), where as name, file, and line number + searches are in ascending order (i.e., alphabetical). The subtle + distinction between "nfl" and "stdname" is that the standard name is a + sort of the name as printed, which means that the embedded line + numbers get compared in an odd way. For example, lines 3, 20, and 40 + would (if the file names were the same) appear in the string order + "20" "3" and "40". In contrast, "nfl" does a numeric compare of the + line numbers. In fact, sort_stats("nfl") is the same as + sort_stats("name", "file", "line"). + + -T <filename>: save profile results as shown on screen to a text + file. The profile is still shown on screen. + + -D <filename>: save (via dump_stats) profile statistics to given + filename. This data is in a format understod by the pstats module, and + is generated by a call to the dump_stats() method of profile + objects. The profile is still shown on screen. + + If you want to run complete programs under the profiler's control, use + '%run -p [prof_opts] filename.py [args to program]' where prof_opts + contains profiler specific options as described here. + + You can read the complete documentation for the profile module with:\\ + In [1]: import profile; profile.help() """ + + opts_def = Struct(D=[''],l=[],s=['time'],T=['']) + # protect user quote marks + parameter_s = parameter_s.replace('"',r'\"').replace("'",r"\'") + + if user_mode: # regular user call + opts,arg_str = self.parse_options(parameter_s,'D:l:rs:T:', + list_all=1) + namespace = self.shell.user_ns + else: # called to run a program by %run -p + try: + filename = get_py_filename(arg_lst[0]) + except IOError,msg: + error(msg) + return + + arg_str = 'execfile(filename,prog_ns)' + namespace = locals() + + opts.merge(opts_def) + + prof = profile.Profile() + try: + prof = prof.runctx(arg_str,namespace,namespace) + sys_exit = '' + except SystemExit: + sys_exit = """*** SystemExit exception caught in code being profiled.""" + + stats = pstats.Stats(prof).strip_dirs().sort_stats(*opts.s) + + lims = opts.l + if lims: + lims = [] # rebuild lims with ints/floats/strings + for lim in opts.l: + try: + lims.append(int(lim)) + except ValueError: + try: + lims.append(float(lim)) + except ValueError: + lims.append(lim) + + # trap output + sys_stdout = sys.stdout + stdout_trap = StringIO() + try: + sys.stdout = stdout_trap + stats.print_stats(*lims) + finally: + sys.stdout = sys_stdout + output = stdout_trap.getvalue() + output = output.rstrip() + + page(output,screen_lines=self.shell.rc.screen_length) + print sys_exit, + + dump_file = opts.D[0] + text_file = opts.T[0] + if dump_file: + prof.dump_stats(dump_file) + print '\n*** Profile stats marshalled to file',\ + `dump_file`+'.',sys_exit + if text_file: + file(text_file,'w').write(output) + print '\n*** Profile printout saved to text file',\ + `text_file`+'.',sys_exit + + if opts.has_key('r'): + return stats + else: + return None + + def magic_run(self, parameter_s ='',runner=None): + """Run the named file inside IPython as a program. + + Usage:\\ + %run [-n -i -t [-N<N>] -d [-b<N>] -p [profile options]] file [args] + + Parameters after the filename are passed as command-line arguments to + the program (put in sys.argv). Then, control returns to IPython's + prompt. + + This is similar to running at a system prompt:\\ + $ python file args\\ + but with the advantage of giving you IPython's tracebacks, and of + loading all variables into your interactive namespace for further use + (unless -p is used, see below). + + The file is executed in a namespace initially consisting only of + __name__=='__main__' and sys.argv constructed as indicated. It thus + sees its environment as if it were being run as a stand-alone + program. But after execution, the IPython interactive namespace gets + updated with all variables defined in the program (except for __name__ + and sys.argv). This allows for very convenient loading of code for + interactive work, while giving each program a 'clean sheet' to run in. + + Options: + + -n: __name__ is NOT set to '__main__', but to the running file's name + without extension (as python does under import). This allows running + scripts and reloading the definitions in them without calling code + protected by an ' if __name__ == "__main__" ' clause. + + -i: run the file in IPython's namespace instead of an empty one. This + is useful if you are experimenting with code written in a text editor + which depends on variables defined interactively. + + -e: ignore sys.exit() calls or SystemExit exceptions in the script + being run. This is particularly useful if IPython is being used to + run unittests, which always exit with a sys.exit() call. In such + cases you are interested in the output of the test results, not in + seeing a traceback of the unittest module. + + -t: print timing information at the end of the run. IPython will give + you an estimated CPU time consumption for your script, which under + Unix uses the resource module to avoid the wraparound problems of + time.clock(). Under Unix, an estimate of time spent on system tasks + is also given (for Windows platforms this is reported as 0.0). + + If -t is given, an additional -N<N> option can be given, where <N> + must be an integer indicating how many times you want the script to + run. The final timing report will include total and per run results. + + For example (testing the script uniq_stable.py): + + In [1]: run -t uniq_stable + + IPython CPU timings (estimated):\\ + User : 0.19597 s.\\ + System: 0.0 s.\\ + + In [2]: run -t -N5 uniq_stable + + IPython CPU timings (estimated):\\ + Total runs performed: 5\\ + Times : Total Per run\\ + User : 0.910862 s, 0.1821724 s.\\ + System: 0.0 s, 0.0 s. + + -d: run your program under the control of pdb, the Python debugger. + This allows you to execute your program step by step, watch variables, + etc. Internally, what IPython does is similar to calling: + + pdb.run('execfile("YOURFILENAME")') + + with a breakpoint set on line 1 of your file. You can change the line + number for this automatic breakpoint to be <N> by using the -bN option + (where N must be an integer). For example: + + %run -d -b40 myscript + + will set the first breakpoint at line 40 in myscript.py. Note that + the first breakpoint must be set on a line which actually does + something (not a comment or docstring) for it to stop execution. + + When the pdb debugger starts, you will see a (Pdb) prompt. You must + first enter 'c' (without qoutes) to start execution up to the first + breakpoint. + + Entering 'help' gives information about the use of the debugger. You + can easily see pdb's full documentation with "import pdb;pdb.help()" + at a prompt. + + -p: run program under the control of the Python profiler module (which + prints a detailed report of execution times, function calls, etc). + + You can pass other options after -p which affect the behavior of the + profiler itself. See the docs for %prun for details. + + In this mode, the program's variables do NOT propagate back to the + IPython interactive namespace (because they remain in the namespace + where the profiler executes them). + + Internally this triggers a call to %prun, see its documentation for + details on the options available specifically for profiling.""" + + # get arguments and set sys.argv for program to be run. + opts,arg_lst = self.parse_options(parameter_s,'nidtN:b:pD:l:rs:T:e', + mode='list',list_all=1) + + try: + filename = get_py_filename(arg_lst[0]) + except IndexError: + warn('you must provide at least a filename.') + print '\n%run:\n',OInspect.getdoc(self.magic_run) + return + except IOError,msg: + error(msg) + return + + # Control the response to exit() calls made by the script being run + exit_ignore = opts.has_key('e') + + # Make sure that the running script gets a proper sys.argv as if it + # were run from a system shell. + save_argv = sys.argv # save it for later restoring + sys.argv = [filename]+ arg_lst[1:] # put in the proper filename + + if opts.has_key('i'): + prog_ns = self.shell.user_ns + __name__save = self.shell.user_ns['__name__'] + prog_ns['__name__'] = '__main__' + else: + if opts.has_key('n'): + name = os.path.splitext(os.path.basename(filename))[0] + else: + name = '__main__' + prog_ns = {'__name__':name} + + # pickle fix. See iplib for an explanation + sys.modules[prog_ns['__name__']] = FakeModule(prog_ns) + + stats = None + try: + if opts.has_key('p'): + stats = self.magic_prun('',0,opts,arg_lst,prog_ns) + else: + if opts.has_key('d'): + deb = pdb.Pdb() + # reset Breakpoint state, which is moronically kept + # in a class + bdb.Breakpoint.next = 1 + bdb.Breakpoint.bplist = {} + bdb.Breakpoint.bpbynumber = [None] + # Set an initial breakpoint to stop execution + maxtries = 10 + bp = int(opts.get('b',[1])[0]) + checkline = deb.checkline(filename,bp) + if not checkline: + for bp in range(bp+1,bp+maxtries+1): + if deb.checkline(filename,bp): + break + else: + msg = ("\nI failed to find a valid line to set " + "a breakpoint\n" + "after trying up to line: %s.\n" + "Please set a valid breakpoint manually " + "with the -b option." % bp) + error(msg) + return + # if we find a good linenumber, set the breakpoint + deb.do_break('%s:%s' % (filename,bp)) + # Start file run + print "NOTE: Enter 'c' at the", + print "(Pdb) prompt to start your script." + deb.run('execfile("%s")' % filename,prog_ns) + else: + if runner is None: + runner = self.shell.safe_execfile + if opts.has_key('t'): + try: + nruns = int(opts['N'][0]) + if nruns < 1: + error('Number of runs must be >=1') + return + except (KeyError): + nruns = 1 + if nruns == 1: + t0 = clock2() + runner(filename,prog_ns,prog_ns,exit_ignore=exit_ignore) + t1 = clock2() + t_usr = t1[0]-t0[0] + t_sys = t1[1]-t1[1] + print "\nIPython CPU timings (estimated):" + print " User : %10s s." % t_usr + print " System: %10s s." % t_sys + else: + runs = range(nruns) + t0 = clock2() + for nr in runs: + runner(filename,prog_ns,prog_ns,exit_ignore=exit_ignore) + t1 = clock2() + t_usr = t1[0]-t0[0] + t_sys = t1[1]-t1[1] + print "\nIPython CPU timings (estimated):" + print "Total runs performed:",nruns + print " Times : %10s %10s" % ('Total','Per run') + print " User : %10s s, %10s s." % (t_usr,t_usr/nruns) + print " System: %10s s, %10s s." % (t_sys,t_sys/nruns) + + else: + runner(filename,prog_ns,prog_ns,exit_ignore=exit_ignore) + if opts.has_key('i'): + self.shell.user_ns['__name__'] = __name__save + else: + # update IPython interactive namespace + del prog_ns['__name__'] + self.shell.user_ns.update(prog_ns) + finally: + sys.argv = save_argv + return stats + + def magic_runlog(self, parameter_s =''): + """Run files as logs. + + Usage:\\ + %runlog file1 file2 ... + + Run the named files (treating them as log files) in sequence inside + the interpreter, and return to the prompt. This is much slower than + %run because each line is executed in a try/except block, but it + allows running files with syntax errors in them. + + Normally IPython will guess when a file is one of its own logfiles, so + you can typically use %run even for logs. This shorthand allows you to + force any file to be treated as a log file.""" + + for f in parameter_s.split(): + self.shell.safe_execfile(f,self.shell.user_ns, + self.shell.user_ns,islog=1) + + def magic_time(self,parameter_s = ''): + """Time execution of a Python statement or expression. + + The CPU and wall clock times are printed, and the value of the + expression (if any) is returned. Note that under Win32, system time + is always reported as 0, since it can not be measured. + + This function provides very basic timing functionality. In Python + 2.3, the timeit module offers more control and sophistication, but for + now IPython supports Python 2.2, so we can not rely on timeit being + present. + + Some examples: + + In [1]: time 2**128 + CPU times: user 0.00 s, sys: 0.00 s, total: 0.00 s + Wall time: 0.00 + Out[1]: 340282366920938463463374607431768211456L + + In [2]: n = 1000000 + + In [3]: time sum(range(n)) + CPU times: user 1.20 s, sys: 0.05 s, total: 1.25 s + Wall time: 1.37 + Out[3]: 499999500000L + + In [4]: time print 'hello world' + hello world + CPU times: user 0.00 s, sys: 0.00 s, total: 0.00 s + Wall time: 0.00 + """ + + # fail immediately if the given expression can't be compiled + try: + mode = 'eval' + code = compile(parameter_s,'<timed eval>',mode) + except SyntaxError: + mode = 'exec' + code = compile(parameter_s,'<timed exec>',mode) + # skew measurement as little as possible + glob = self.shell.user_ns + clk = clock2 + wtime = time.time + # time execution + wall_st = wtime() + if mode=='eval': + st = clk() + out = eval(code,glob) + end = clk() + else: + st = clk() + exec code in glob + end = clk() + out = None + wall_end = wtime() + # Compute actual times and report + wall_time = wall_end-wall_st + cpu_user = end[0]-st[0] + cpu_sys = end[1]-st[1] + cpu_tot = cpu_user+cpu_sys + print "CPU times: user %.2f s, sys: %.2f s, total: %.2f s" % \ + (cpu_user,cpu_sys,cpu_tot) + print "Wall time: %.2f" % wall_time + return out + + def magic_macro(self,parameter_s = ''): + """Define a set of input lines as a macro for future re-execution. + + Usage:\\ + %macro name n1:n2 n3:n4 ... n5 .. n6 ... + + This will define a global variable called `name` which is a string + made of joining the slices and lines you specify (n1,n2,... numbers + above) from your input history into a single string. This variable + acts like an automatic function which re-executes those lines as if + you had typed them. You just type 'name' at the prompt and the code + executes. + + Note that the slices use the standard Python slicing notation (5:8 + means include lines numbered 5,6,7). + + For example, if your history contains (%hist prints it): + + 44: x=1\\ + 45: y=3\\ + 46: z=x+y\\ + 47: print x\\ + 48: a=5\\ + 49: print 'x',x,'y',y\\ + + you can create a macro with lines 44 through 47 (included) and line 49 + called my_macro with: + + In [51]: %macro my_macro 44:48 49 + + Now, typing `my_macro` (without quotes) will re-execute all this code + in one pass. + + You don't need to give the line-numbers in order, and any given line + number can appear multiple times. You can assemble macros with any + lines from your input history in any order. + + The macro is a simple object which holds its value in an attribute, + but IPython's display system checks for macros and executes them as + code instead of printing them when you type their name. + + You can view a macro's contents by explicitly printing it with: + + 'print macro_name'. + + For one-off cases which DON'T contain magic function calls in them you + can obtain similar results by explicitly executing slices from your + input history with: + + In [60]: exec In[44:48]+In[49]""" + + args = parameter_s.split() + name,ranges = args[0], args[1:] + #print 'rng',ranges # dbg + cmds = self.extract_input_slices(ranges) + macro = Macro(cmds) + self.shell.user_ns.update({name:macro}) + print 'Macro `%s` created. To execute, type its name (without quotes).' % name + print 'Macro contents:' + print str(macro).rstrip(), + + def magic_save(self,parameter_s = ''): + """Save a set of lines to a given filename. + + Usage:\\ + %save filename n1:n2 n3:n4 ... n5 .. n6 ... + + This function uses the same syntax as %macro for line extraction, but + instead of creating a macro it saves the resulting string to the + filename you specify. + + It adds a '.py' extension to the file if you don't do so yourself, and + it asks for confirmation before overwriting existing files.""" + + args = parameter_s.split() + fname,ranges = args[0], args[1:] + if not fname.endswith('.py'): + fname += '.py' + if os.path.isfile(fname): + ans = raw_input('File `%s` exists. Overwrite (y/[N])? ' % fname) + if ans.lower() not in ['y','yes']: + print 'Operation cancelled.' + return + cmds = ''.join(self.extract_input_slices(ranges)) + f = file(fname,'w') + f.write(cmds) + f.close() + print 'The following commands were written to file `%s`:' % fname + print cmds + + def magic_ed(self,parameter_s = ''): + """Alias to %edit.""" + return self.magic_edit(parameter_s) + + def magic_edit(self,parameter_s = '',last_call=['','']): + """Bring up an editor and execute the resulting code. + + Usage: + %edit [options] [args] + + %edit runs IPython's editor hook. The default version of this hook is + set to call the __IPYTHON__.rc.editor command. This is read from your + environment variable $EDITOR. If this isn't found, it will default to + vi under Linux/Unix and to notepad under Windows. See the end of this + docstring for how to change the editor hook. + + You can also set the value of this editor via the command line option + '-editor' or in your ipythonrc file. This is useful if you wish to use + specifically for IPython an editor different from your typical default + (and for Windows users who typically don't set environment variables). + + This command allows you to conveniently edit multi-line code right in + your IPython session. + + If called without arguments, %edit opens up an empty editor with a + temporary file and will execute the contents of this file when you + close it (don't forget to save it!). + + Options: + + -p: this will call the editor with the same data as the previous time + it was used, regardless of how long ago (in your current session) it + was. + + -x: do not execute the edited code immediately upon exit. This is + mainly useful if you are editing programs which need to be called with + command line arguments, which you can then do using %run. + + Arguments: + + If arguments are given, the following possibilites exist: + + - The arguments are numbers or pairs of colon-separated numbers (like + 1 4:8 9). These are interpreted as lines of previous input to be + loaded into the editor. The syntax is the same of the %macro command. + + - If the argument doesn't start with a number, it is evaluated as a + variable and its contents loaded into the editor. You can thus edit + any string which contains python code (including the result of + previous edits). + + - If the argument is the name of an object (other than a string), + IPython will try to locate the file where it was defined and open the + editor at the point where it is defined. You can use `%edit function` + to load an editor exactly at the point where 'function' is defined, + edit it and have the file be executed automatically. + + Note: opening at an exact line is only supported under Unix, and some + editors (like kedit and gedit up to Gnome 2.8) do not understand the + '+NUMBER' parameter necessary for this feature. Good editors like + (X)Emacs, vi, jed, pico and joe all do. + + - If the argument is not found as a variable, IPython will look for a + file with that name (adding .py if necessary) and load it into the + editor. It will execute its contents with execfile() when you exit, + loading any code in the file into your interactive namespace. + + After executing your code, %edit will return as output the code you + typed in the editor (except when it was an existing file). This way + you can reload the code in further invocations of %edit as a variable, + via _<NUMBER> or Out[<NUMBER>], where <NUMBER> is the prompt number of + the output. + + Note that %edit is also available through the alias %ed. + + This is an example of creating a simple function inside the editor and + then modifying it. First, start up the editor: + + In [1]: ed\\ + Editing... done. Executing edited code...\\ + Out[1]: 'def foo():\\n print "foo() was defined in an editing session"\\n' + + We can then call the function foo(): + + In [2]: foo()\\ + foo() was defined in an editing session + + Now we edit foo. IPython automatically loads the editor with the + (temporary) file where foo() was previously defined: + + In [3]: ed foo\\ + Editing... done. Executing edited code... + + And if we call foo() again we get the modified version: + + In [4]: foo()\\ + foo() has now been changed! + + Here is an example of how to edit a code snippet successive + times. First we call the editor: + + In [8]: ed\\ + Editing... done. Executing edited code...\\ + hello\\ + Out[8]: "print 'hello'\\n" + + Now we call it again with the previous output (stored in _): + + In [9]: ed _\\ + Editing... done. Executing edited code...\\ + hello world\\ + Out[9]: "print 'hello world'\\n" + + Now we call it with the output #8 (stored in _8, also as Out[8]): + + In [10]: ed _8\\ + Editing... done. Executing edited code...\\ + hello again\\ + Out[10]: "print 'hello again'\\n" + + + Changing the default editor hook: + + If you wish to write your own editor hook, you can put it in a + configuration file which you load at startup time. The default hook + is defined in the IPython.hooks module, and you can use that as a + starting example for further modifications. That file also has + general instructions on how to set a new hook for use once you've + defined it.""" + + # FIXME: This function has become a convoluted mess. It needs a + # ground-up rewrite with clean, simple logic. + + def make_filename(arg): + "Make a filename from the given args" + try: + filename = get_py_filename(arg) + except IOError: + if args.endswith('.py'): + filename = arg + else: + filename = None + return filename + + # custom exceptions + class DataIsObject(Exception): pass + + opts,args = self.parse_options(parameter_s,'px') + + # Default line number value + lineno = None + if opts.has_key('p'): + args = '_%s' % last_call[0] + if not self.shell.user_ns.has_key(args): + args = last_call[1] + + # use last_call to remember the state of the previous call, but don't + # let it be clobbered by successive '-p' calls. + try: + last_call[0] = self.shell.outputcache.prompt_count + if not opts.has_key('p'): + last_call[1] = parameter_s + except: + pass + + # by default this is done with temp files, except when the given + # arg is a filename + use_temp = 1 + + if re.match(r'\d',args): + # Mode where user specifies ranges of lines, like in %macro. + # This means that you can't edit files whose names begin with + # numbers this way. Tough. + ranges = args.split() + data = ''.join(self.extract_input_slices(ranges)) + elif args.endswith('.py'): + filename = make_filename(args) + data = '' + use_temp = 0 + elif args: + try: + # Load the parameter given as a variable. If not a string, + # process it as an object instead (below) + + #print '*** args',args,'type',type(args) # dbg + data = eval(args,self.shell.user_ns) + if not type(data) in StringTypes: + raise DataIsObject + except (NameError,SyntaxError): + # given argument is not a variable, try as a filename + filename = make_filename(args) + if filename is None: + warn("Argument given (%s) can't be found as a variable " + "or as a filename." % args) + return + data = '' + use_temp = 0 + except DataIsObject: + # For objects, try to edit the file where they are defined + try: + filename = inspect.getabsfile(data) + datafile = 1 + except TypeError: + filename = make_filename(args) + datafile = 1 + warn('Could not find file where `%s` is defined.\n' + 'Opening a file named `%s`' % (args,filename)) + # Now, make sure we can actually read the source (if it was in + # a temp file it's gone by now). + if datafile: + try: + lineno = inspect.getsourcelines(data)[1] + except IOError: + filename = make_filename(args) + if filename is None: + warn('The file `%s` where `%s` was defined cannot ' + 'be read.' % (filename,data)) + return + use_temp = 0 + else: + data = '' + + if use_temp: + filename = tempfile.mktemp('.py') + self.shell.tempfiles.append(filename) + + if data and use_temp: + tmp_file = open(filename,'w') + tmp_file.write(data) + tmp_file.close() + + # do actual editing here + print 'Editing...', + sys.stdout.flush() + self.shell.hooks.editor(filename,lineno) + if opts.has_key('x'): # -x prevents actual execution + print + else: + print 'done. Executing edited code...' + try: + execfile(filename,self.shell.user_ns) + except IOError,msg: + if msg.filename == filename: + warn('File not found. Did you forget to save?') + return + else: + self.shell.showtraceback() + except: + self.shell.showtraceback() + if use_temp: + contents = open(filename).read() + return contents + + def magic_xmode(self,parameter_s = ''): + """Switch modes for the exception handlers. + + Valid modes: Plain, Context and Verbose. + + If called without arguments, acts as a toggle.""" + + new_mode = parameter_s.strip().capitalize() + try: + self.InteractiveTB.set_mode(mode = new_mode) + print 'Exception reporting mode:',self.InteractiveTB.mode + except: + warn('Error changing exception modes.\n' + str(sys.exc_info()[1])) + + def magic_colors(self,parameter_s = ''): + """Switch color scheme for prompts, info system and exception handlers. + + Currently implemented schemes: NoColor, Linux, LightBG. + + Color scheme names are not case-sensitive.""" + + new_scheme = parameter_s.strip() + if not new_scheme: + print 'You must specify a color scheme.' + return + # Under Windows, check for Gary Bishop's readline, which is necessary + # for ANSI coloring + if os.name in ['nt','dos']: + try: + import readline + except ImportError: + has_readline = 0 + else: + try: + readline.GetOutputFile() + except AttributeError: + has_readline = 0 + else: + has_readline = 1 + if not has_readline: + msg = """\ +Proper color support under MS Windows requires Gary Bishop's readline library. +You can find it at: +http://sourceforge.net/projects/uncpythontools +Gary's readline needs the ctypes module, from: +http://starship.python.net/crew/theller/ctypes + +Defaulting color scheme to 'NoColor'""" + new_scheme = 'NoColor' + warn(msg) + + # Set prompt colors + try: + self.shell.outputcache.set_colors(new_scheme) + except: + warn('Error changing prompt color schemes.\n' + + str(sys.exc_info()[1])) + else: + self.shell.rc.colors = \ + self.shell.outputcache.color_table.active_scheme_name + # Set exception colors + try: + self.shell.InteractiveTB.set_colors(scheme = new_scheme) + self.shell.SyntaxTB.set_colors(scheme = new_scheme) + except: + warn('Error changing exception color schemes.\n' + + str(sys.exc_info()[1])) + # Set info (for 'object?') colors + if self.shell.rc.color_info: + try: + self.shell.inspector.set_active_scheme(new_scheme) + except: + warn('Error changing object inspector color schemes.\n' + + str(sys.exc_info()[1])) + else: + self.shell.inspector.set_active_scheme('NoColor') + + def magic_color_info(self,parameter_s = ''): + """Toggle color_info. + + The color_info configuration parameter controls whether colors are + used for displaying object details (by things like %psource, %pfile or + the '?' system). This function toggles this value with each call. + + Note that unless you have a fairly recent pager (less works better + than more) in your system, using colored object information displays + will not work properly. Test it and see.""" + + self.shell.rc.color_info = 1 - self.shell.rc.color_info + self.magic_colors(self.shell.rc.colors) + print 'Object introspection functions have now coloring:', + print ['OFF','ON'][self.shell.rc.color_info] + + def magic_Pprint(self, parameter_s=''): + """Toggle pretty printing on/off.""" + + self.shell.outputcache.Pprint = 1 - self.shell.outputcache.Pprint + print 'Pretty printing has been turned', \ + ['OFF','ON'][self.shell.outputcache.Pprint] + + def magic_Exit(self, parameter_s=''): + """Exit IPython without confirmation.""" + + self.shell.exit_now = True + + def magic_Quit(self, parameter_s=''): + """Exit IPython without confirmation (like %Exit).""" + + self.shell.exit_now = True + + #...................................................................... + # Functions to implement unix shell-type things + + def magic_alias(self, parameter_s = ''): + """Define an alias for a system command. + + '%alias alias_name cmd' defines 'alias_name' as an alias for 'cmd' + + Then, typing 'alias_name params' will execute the system command 'cmd + params' (from your underlying operating system). + + Aliases have lower precedence than magic functions and Python normal + variables, so if 'foo' is both a Python variable and an alias, the + alias can not be executed until 'del foo' removes the Python variable. + + You can use the %l specifier in an alias definition to represent the + whole line when the alias is called. For example: + + In [2]: alias all echo "Input in brackets: <%l>"\\ + In [3]: all hello world\\ + Input in brackets: <hello world> + + You can also define aliases with parameters using %s specifiers (one + per parameter): + + In [1]: alias parts echo first %s second %s\\ + In [2]: %parts A B\\ + first A second B\\ + In [3]: %parts A\\ + Incorrect number of arguments: 2 expected.\\ + parts is an alias to: 'echo first %s second %s' + + Note that %l and %s are mutually exclusive. You can only use one or + the other in your aliases. + + Aliases expand Python variables just like system calls using ! or !! + do: all expressions prefixed with '$' get expanded. For details of + the semantic rules, see PEP-215: + http://www.python.org/peps/pep-0215.html. This is the library used by + IPython for variable expansion. If you want to access a true shell + variable, an extra $ is necessary to prevent its expansion by IPython: + + In [6]: alias show echo\\ + In [7]: PATH='A Python string'\\ + In [8]: show $PATH\\ + A Python string\\ + In [9]: show $$PATH\\ + /usr/local/lf9560/bin:/usr/local/intel/compiler70/ia32/bin:... + + You can use the alias facility to acess all of $PATH. See the %rehash + and %rehashx functions, which automatically create aliases for the + contents of your $PATH. + + If called with no parameters, %alias prints the current alias table.""" + + par = parameter_s.strip() + if not par: + if self.shell.rc.automagic: + prechar = '' + else: + prechar = self.shell.ESC_MAGIC + print 'Alias\t\tSystem Command\n'+'-'*30 + atab = self.shell.alias_table + aliases = atab.keys() + aliases.sort() + for alias in aliases: + print prechar+alias+'\t\t'+atab[alias][1] + print '-'*30+'\nTotal number of aliases:',len(aliases) + return + try: + alias,cmd = par.split(None,1) + except: + print OInspect.getdoc(self.magic_alias) + else: + nargs = cmd.count('%s') + if nargs>0 and cmd.find('%l')>=0: + error('The %s and %l specifiers are mutually exclusive ' + 'in alias definitions.') + else: # all looks OK + self.shell.alias_table[alias] = (nargs,cmd) + self.shell.alias_table_validate(verbose=1) + # end magic_alias + + def magic_unalias(self, parameter_s = ''): + """Remove an alias""" + + aname = parameter_s.strip() + if aname in self.shell.alias_table: + del self.shell.alias_table[aname] + + def magic_rehash(self, parameter_s = ''): + """Update the alias table with all entries in $PATH. + + This version does no checks on execute permissions or whether the + contents of $PATH are truly files (instead of directories or something + else). For such a safer (but slower) version, use %rehashx.""" + + # This function (and rehashx) manipulate the alias_table directly + # rather than calling magic_alias, for speed reasons. A rehash on a + # typical Linux box involves several thousand entries, so efficiency + # here is a top concern. + + path = filter(os.path.isdir,os.environ['PATH'].split(os.pathsep)) + alias_table = self.shell.alias_table + for pdir in path: + for ff in os.listdir(pdir): + # each entry in the alias table must be (N,name), where + # N is the number of positional arguments of the alias. + alias_table[ff] = (0,ff) + # Make sure the alias table doesn't contain keywords or builtins + self.shell.alias_table_validate() + # Call again init_auto_alias() so we get 'rm -i' and other modified + # aliases since %rehash will probably clobber them + self.shell.init_auto_alias() + + def magic_rehashx(self, parameter_s = ''): + """Update the alias table with all executable files in $PATH. + + This version explicitly checks that every entry in $PATH is a file + with execute access (os.X_OK), so it is much slower than %rehash. + + Under Windows, it checks executability as a match agains a + '|'-separated string of extensions, stored in the IPython config + variable win_exec_ext. This defaults to 'exe|com|bat'. """ + + path = filter(os.path.isdir,os.environ['PATH'].split(os.pathsep)) + alias_table = self.shell.alias_table + + if os.name == 'posix': + isexec = lambda fname:os.path.isfile(fname) and \ + os.access(fname,os.X_OK) + else: + + try: + winext = os.environ['pathext'].replace(';','|').replace('.','') + except KeyError: + winext = 'exe|com|bat' + + execre = re.compile(r'(.*)\.(%s)$' % winext,re.IGNORECASE) + isexec = lambda fname:os.path.isfile(fname) and execre.match(fname) + savedir = os.getcwd() + try: + # write the whole loop for posix/Windows so we don't have an if in + # the innermost part + if os.name == 'posix': + for pdir in path: + os.chdir(pdir) + for ff in os.listdir(pdir): + if isexec(ff): + # each entry in the alias table must be (N,name), + # where N is the number of positional arguments of the + # alias. + alias_table[ff] = (0,ff) + else: + for pdir in path: + os.chdir(pdir) + for ff in os.listdir(pdir): + if isexec(ff): + alias_table[execre.sub(r'\1',ff)] = (0,ff) + # Make sure the alias table doesn't contain keywords or builtins + self.shell.alias_table_validate() + # Call again init_auto_alias() so we get 'rm -i' and other + # modified aliases since %rehashx will probably clobber them + self.shell.init_auto_alias() + finally: + os.chdir(savedir) + + def magic_pwd(self, parameter_s = ''): + """Return the current working directory path.""" + return os.getcwd() + + def magic_cd(self, parameter_s=''): + """Change the current working directory. + + This command automatically maintains an internal list of directories + you visit during your IPython session, in the variable _dh. The + command %dhist shows this history nicely formatted. + + Usage: + + cd 'dir': changes to directory 'dir'. + + cd -: changes to the last visited directory. + + cd -<n>: changes to the n-th directory in the directory history. + + cd -b <bookmark_name>: jump to a bookmark set by %bookmark + (note: cd <bookmark_name> is enough if there is no + directory <bookmark_name>, but a bookmark with the name exists.) + + Options: + + -q: quiet. Do not print the working directory after the cd command is + executed. By default IPython's cd command does print this directory, + since the default prompts do not display path information. + + Note that !cd doesn't work for this purpose because the shell where + !command runs is immediately discarded after executing 'command'.""" + + parameter_s = parameter_s.strip() + bkms = self.shell.persist.get("bookmarks",{}) + + numcd = re.match(r'(-)(\d+)$',parameter_s) + # jump in directory history by number + if numcd: + nn = int(numcd.group(2)) + try: + ps = self.shell.user_ns['_dh'][nn] + except IndexError: + print 'The requested directory does not exist in history.' + return + else: + opts = {} + else: + opts,ps = self.parse_options(parameter_s,'qb',mode='string') + # jump to previous + if ps == '-': + try: + ps = self.shell.user_ns['_dh'][-2] + except IndexError: + print 'No previous directory to change to.' + return + # jump to bookmark + elif opts.has_key('b') or (bkms.has_key(ps) and not os.path.isdir(ps)): + if bkms.has_key(ps): + target = bkms[ps] + print '(bookmark:%s) -> %s' % (ps,target) + ps = target + else: + if bkms: + error("Bookmark '%s' not found. " + "Use '%bookmark -l' to see your bookmarks." % ps) + else: + print "Bookmarks not set - use %bookmark <bookmarkname>" + return + + # at this point ps should point to the target dir + if ps: + try: + os.chdir(os.path.expanduser(ps)) + except OSError: + print sys.exc_info()[1] + else: + self.shell.user_ns['_dh'].append(os.getcwd()) + else: + os.chdir(self.home_dir) + self.shell.user_ns['_dh'].append(os.getcwd()) + if not 'q' in opts: + print self.shell.user_ns['_dh'][-1] + + def magic_dhist(self, parameter_s=''): + """Print your history of visited directories. + + %dhist -> print full history\\ + %dhist n -> print last n entries only\\ + %dhist n1 n2 -> print entries between n1 and n2 (n1 not included)\\ + + This history is automatically maintained by the %cd command, and + always available as the global list variable _dh. You can use %cd -<n> + to go to directory number <n>.""" + + dh = self.shell.user_ns['_dh'] + if parameter_s: + try: + args = map(int,parameter_s.split()) + except: + self.arg_err(Magic.magic_dhist) + return + if len(args) == 1: + ini,fin = max(len(dh)-(args[0]),0),len(dh) + elif len(args) == 2: + ini,fin = args + else: + self.arg_err(Magic.magic_dhist) + return + else: + ini,fin = 0,len(dh) + nlprint(dh, + header = 'Directory history (kept in _dh)', + start=ini,stop=fin) + + def magic_env(self, parameter_s=''): + """List environment variables.""" + + # environ is an instance of UserDict + return os.environ.data + + def magic_pushd(self, parameter_s=''): + """Place the current dir on stack and change directory. + + Usage:\\ + %pushd ['dirname'] + + %pushd with no arguments does a %pushd to your home directory. + """ + if parameter_s == '': parameter_s = '~' + if len(self.dir_stack)>0 and os.path.expanduser(parameter_s) != \ + os.path.expanduser(self.dir_stack[0]): + try: + self.magic_cd(parameter_s) + self.dir_stack.insert(0,os.getcwd().replace(self.home_dir,'~')) + self.magic_dirs() + except: + print 'Invalid directory' + else: + print 'You are already there!' + + def magic_popd(self, parameter_s=''): + """Change to directory popped off the top of the stack. + """ + if len (self.dir_stack) > 1: + self.dir_stack.pop(0) + self.magic_cd(self.dir_stack[0]) + print self.dir_stack[0] + else: + print "You can't remove the starting directory from the stack:",\ + self.dir_stack + + def magic_dirs(self, parameter_s=''): + """Return the current directory stack.""" + + return self.dir_stack[:] + + def magic_sc(self, parameter_s=''): + """Shell capture - execute a shell command and capture its output. + + %sc [options] varname=command + + IPython will run the given command using commands.getoutput(), and + will then update the user's interactive namespace with a variable + called varname, containing the value of the call. Your command can + contain shell wildcards, pipes, etc. + + The '=' sign in the syntax is mandatory, and the variable name you + supply must follow Python's standard conventions for valid names. + + Options: + + -l: list output. Split the output on newlines into a list before + assigning it to the given variable. By default the output is stored + as a single string. + + -v: verbose. Print the contents of the variable. + + In most cases you should not need to split as a list, because the + returned value is a special type of string which can automatically + provide its contents either as a list (split on newlines) or as a + space-separated string. These are convenient, respectively, either + for sequential processing or to be passed to a shell command. + + For example: + + # Capture into variable a + In [9]: sc a=ls *py + + # a is a string with embedded newlines + In [10]: a + Out[10]: 'setup.py\nwin32_manual_post_install.py' + + # which can be seen as a list: + In [11]: a.l + Out[11]: ['setup.py', 'win32_manual_post_install.py'] + + # or as a whitespace-separated string: + In [12]: a.s + Out[12]: 'setup.py win32_manual_post_install.py' + + # a.s is useful to pass as a single command line: + In [13]: !wc -l $a.s + 146 setup.py + 130 win32_manual_post_install.py + 276 total + + # while the list form is useful to loop over: + In [14]: for f in a.l: + ....: !wc -l $f + ....: + 146 setup.py + 130 win32_manual_post_install.py + + Similiarly, the lists returned by the -l option are also special, in + the sense that you can equally invoke the .s attribute on them to + automatically get a whitespace-separated string from their contents: + + In [1]: sc -l b=ls *py + + In [2]: b + Out[2]: ['setup.py', 'win32_manual_post_install.py'] + + In [3]: b.s + Out[3]: 'setup.py win32_manual_post_install.py' + + In summary, both the lists and strings used for ouptut capture have + the following special attributes: + + .l (or .list) : value as list. + .n (or .nlstr): value as newline-separated string. + .s (or .spstr): value as space-separated string. + """ + + opts,args = self.parse_options(parameter_s,'lv') + # Try to get a variable name and command to run + try: + # the variable name must be obtained from the parse_options + # output, which uses shlex.split to strip options out. + var,_ = args.split('=',1) + var = var.strip() + # But the the command has to be extracted from the original input + # parameter_s, not on what parse_options returns, to avoid the + # quote stripping which shlex.split performs on it. + _,cmd = parameter_s.split('=',1) + except ValueError: + var,cmd = '','' + if not var: + error('you must specify a variable to assign the command to.') + return + # If all looks ok, proceed + out,err = self.shell.getoutputerror(cmd) + if err: + print >> Term.cerr,err + if opts.has_key('l'): + out = SList(out.split('\n')) + else: + out = LSString(out) + if opts.has_key('v'): + print '%s ==\n%s' % (var,pformat(out)) + self.shell.user_ns.update({var:out}) + + def magic_sx(self, parameter_s=''): + """Shell execute - run a shell command and capture its output. + + %sx command + + IPython will run the given command using commands.getoutput(), and + return the result formatted as a list (split on '\\n'). Since the + output is _returned_, it will be stored in ipython's regular output + cache Out[N] and in the '_N' automatic variables. + + Notes: + + 1) If an input line begins with '!!', then %sx is automatically + invoked. That is, while: + !ls + causes ipython to simply issue system('ls'), typing + !!ls + is a shorthand equivalent to: + %sx ls + + 2) %sx differs from %sc in that %sx automatically splits into a list, + like '%sc -l'. The reason for this is to make it as easy as possible + to process line-oriented shell output via further python commands. + %sc is meant to provide much finer control, but requires more + typing. + + 3) Just like %sc -l, this is a list with special attributes: + + .l (or .list) : value as list. + .n (or .nlstr): value as newline-separated string. + .s (or .spstr): value as whitespace-separated string. + + This is very useful when trying to use such lists as arguments to + system commands.""" + + if parameter_s: + out,err = self.shell.getoutputerror(parameter_s) + if err: + print >> Term.cerr,err + return SList(out.split('\n')) + + def magic_bg(self, parameter_s=''): + """Run a job in the background, in a separate thread. + + For example, + + %bg myfunc(x,y,z=1) + + will execute 'myfunc(x,y,z=1)' in a background thread. As soon as the + execution starts, a message will be printed indicating the job + number. If your job number is 5, you can use + + myvar = jobs.result(5) or myvar = jobs[5].result + + to assign this result to variable 'myvar'. + + IPython has a job manager, accessible via the 'jobs' object. You can + type jobs? to get more information about it, and use jobs.<TAB> to see + its attributes. All attributes not starting with an underscore are + meant for public use. + + In particular, look at the jobs.new() method, which is used to create + new jobs. This magic %bg function is just a convenience wrapper + around jobs.new(), for expression-based jobs. If you want to create a + new job with an explicit function object and arguments, you must call + jobs.new() directly. + + The jobs.new docstring also describes in detail several important + caveats associated with a thread-based model for background job + execution. Type jobs.new? for details. + + You can check the status of all jobs with jobs.status(). + + The jobs variable is set by IPython into the Python builtin namespace. + If you ever declare a variable named 'jobs', you will shadow this + name. You can either delete your global jobs variable to regain + access to the job manager, or make a new name and assign it manually + to the manager (stored in IPython's namespace). For example, to + assign the job manager to the Jobs name, use: + + Jobs = __builtins__.jobs""" + + self.shell.jobs.new(parameter_s,self.shell.user_ns) + + def magic_bookmark(self, parameter_s=''): + """Manage IPython's bookmark system. + + %bookmark <name> - set bookmark to current dir + %bookmark <name> <dir> - set bookmark to <dir> + %bookmark -l - list all bookmarks + %bookmark -d <name> - remove bookmark + %bookmark -r - remove all bookmarks + + You can later on access a bookmarked folder with: + %cd -b <name> + or simply '%cd <name>' if there is no directory called <name> AND + there is such a bookmark defined. + + Your bookmarks persist through IPython sessions, but they are + associated with each profile.""" + + opts,args = self.parse_options(parameter_s,'drl',mode='list') + if len(args) > 2: + error('You can only give at most two arguments') + return + + bkms = self.shell.persist.get('bookmarks',{}) + + if opts.has_key('d'): + try: + todel = args[0] + except IndexError: + error('You must provide a bookmark to delete') + else: + try: + del bkms[todel] + except: + error("Can't delete bookmark '%s'" % todel) + elif opts.has_key('r'): + bkms = {} + elif opts.has_key('l'): + bks = bkms.keys() + bks.sort() + if bks: + size = max(map(len,bks)) + else: + size = 0 + fmt = '%-'+str(size)+'s -> %s' + print 'Current bookmarks:' + for bk in bks: + print fmt % (bk,bkms[bk]) + else: + if not args: + error("You must specify the bookmark name") + elif len(args)==1: + bkms[args[0]] = os.getcwd() + elif len(args)==2: + bkms[args[0]] = args[1] + self.persist['bookmarks'] = bkms +# end Magic diff --git a/IPython/OInspect.py b/IPython/OInspect.py new file mode 100644 index 0000000..dfe72a1 --- /dev/null +++ b/IPython/OInspect.py @@ -0,0 +1,398 @@ +# -*- coding: utf-8 -*- +"""Tools for inspecting Python objects. + +Uses syntax highlighting for presenting the various information elements. + +Similar in spirit to the inspect module, but all calls take a name argument to +reference the name under which an object is being read. + +$Id: OInspect.py 575 2005-04-08 14:16:44Z fperez $ +""" + +#***************************************************************************** +# Copyright (C) 2001-2004 Fernando Perez <fperez@colorado.edu> +# +# Distributed under the terms of the BSD License. The full license is in +# the file COPYING, distributed as part of this software. +#***************************************************************************** + +from IPython import Release +__author__ = '%s <%s>' % Release.authors['Fernando'] +__license__ = Release.license + +__all__ = ['Inspector','InspectColors'] + +# stdlib modules +import inspect,linecache,types,StringIO,string + +# IPython's own +from IPython.Itpl import itpl +from IPython.genutils import page,indent,Term +from IPython import PyColorize +from IPython.ColorANSI import * + +#**************************************************************************** +# Builtin color schemes + +Colors = TermColors # just a shorthand + +# Build a few color schemes +NoColor = ColorScheme( + 'NoColor',{ + 'header' : Colors.NoColor, + 'normal' : Colors.NoColor # color off (usu. Colors.Normal) + } ) + +LinuxColors = ColorScheme( + 'Linux',{ + 'header' : Colors.LightRed, + 'normal' : Colors.Normal # color off (usu. Colors.Normal) + } ) + +LightBGColors = ColorScheme( + 'LightBG',{ + 'header' : Colors.Red, + 'normal' : Colors.Normal # color off (usu. Colors.Normal) + } ) + +# Build table of color schemes (needed by the parser) +InspectColors = ColorSchemeTable([NoColor,LinuxColors,LightBGColors], + 'Linux') + +#**************************************************************************** +# Auxiliary functions +def getdoc(obj): + """Stable wrapper around inspect.getdoc. + + This can't crash because of attribute problems. + + It also attempts to call a getdoc() method on the given object. This + allows objects which provide their docstrings via non-standard mechanisms + (like Pyro proxies) to still be inspected by ipython's ? system.""" + + ds = None # default return value + try: + ds = inspect.getdoc(obj) + except: + # Harden against an inspect failure, which can occur with + # SWIG-wrapped extensions. + pass + # Allow objects to offer customized documentation via a getdoc method: + try: + ds2 = obj.getdoc() + except: + pass + else: + # if we get extra info, we add it to the normal docstring. + if ds is None: + ds = ds2 + else: + ds = '%s\n%s' % (ds,ds2) + return ds + +#**************************************************************************** +# Class definitions + +class myStringIO(StringIO.StringIO): + """Adds a writeln method to normal StringIO.""" + def writeln(self,*arg,**kw): + """Does a write() and then a write('\n')""" + self.write(*arg,**kw) + self.write('\n') + +class Inspector: + def __init__(self,color_table,code_color_table,scheme): + self.color_table = color_table + self.parser = PyColorize.Parser(code_color_table,out='str') + self.format = self.parser.format + self.set_active_scheme(scheme) + + def __getargspec(self,obj): + """Get the names and default values of a function's arguments. + + A tuple of four things is returned: (args, varargs, varkw, defaults). + 'args' is a list of the argument names (it may contain nested lists). + 'varargs' and 'varkw' are the names of the * and ** arguments or None. + 'defaults' is an n-tuple of the default values of the last n arguments. + + Modified version of inspect.getargspec from the Python Standard + Library.""" + + if inspect.isfunction(obj): + func_obj = obj + elif inspect.ismethod(obj): + func_obj = obj.im_func + else: + raise TypeError, 'arg is not a Python function' + args, varargs, varkw = inspect.getargs(func_obj.func_code) + return args, varargs, varkw, func_obj.func_defaults + + def __getdef(self,obj,oname=''): + """Return the definition header for any callable object. + + If any exception is generated, None is returned instead and the + exception is suppressed.""" + + try: + return oname + inspect.formatargspec(*self.__getargspec(obj)) + except: + return None + + def __head(self,h): + """Return a header string with proper colors.""" + return '%s%s%s' % (self.color_table.active_colors.header,h, + self.color_table.active_colors.normal) + + def set_active_scheme(self,scheme): + self.color_table.set_active_scheme(scheme) + self.parser.color_table.set_active_scheme(scheme) + + def noinfo(self,msg,oname): + """Generic message when no information is found.""" + print 'No %s found' % msg, + if oname: + print 'for %s' % oname + else: + print + + def pdef(self,obj,oname=''): + """Print the definition header for any callable object. + + If the object is a class, print the constructor information.""" + + if not callable(obj): + print 'Object is not callable.' + return + + header = '' + if type(obj) is types.ClassType: + header = self.__head('Class constructor information:\n') + obj = obj.__init__ + elif type(obj) is types.InstanceType: + obj = obj.__call__ + + output = self.__getdef(obj,oname) + if output is None: + self.noinfo('definition header',oname) + else: + print >>Term.cout, header,self.format(output), + + def pdoc(self,obj,oname='',formatter = None): + """Print the docstring for any object. + + Optional: + -formatter: a function to run the docstring through for specially + formatted docstrings.""" + + head = self.__head # so that itpl can find it even if private + ds = getdoc(obj) + if formatter: + ds = formatter(ds) + if type(obj) is types.ClassType: + init_ds = getdoc(obj.__init__) + output = itpl('$head("Class Docstring:")\n' + '$indent(ds)\n' + '$head("Constructor Docstring"):\n' + '$indent(init_ds)') + elif type(obj) is types.InstanceType and hasattr(obj,'__call__'): + call_ds = getdoc(obj.__call__) + if call_ds: + output = itpl('$head("Class Docstring:")\n$indent(ds)\n' + '$head("Calling Docstring:")\n$indent(call_ds)') + else: + output = ds + else: + output = ds + if output is None: + self.noinfo('documentation',oname) + return + page(output) + + def psource(self,obj,oname=''): + """Print the source code for an object.""" + + # Flush the source cache because inspect can return out-of-date source + linecache.checkcache() + try: + src = inspect.getsource(obj) + except: + self.noinfo('source',oname) + else: + page(self.format(src)) + + def pfile(self,obj,oname=''): + """Show the whole file where an object was defined.""" + try: + sourcelines,lineno = inspect.getsourcelines(obj) + except: + self.noinfo('file',oname) + else: + # run contents of file through pager starting at line + # where the object is defined + page(self.format(open(inspect.getabsfile(obj)).read()),lineno) + + def pinfo(self,obj,oname='',formatter=None,info=None,detail_level=0): + """Show detailed information about an object. + + Optional arguments: + + - oname: name of the variable pointing to the object. + + - formatter: special formatter for docstrings (see pdoc) + + - info: a structure with some information fields which may have been + precomputed already. + + - detail_level: if set to 1, more information is given. + """ + + obj_type = type(obj) + + header = self.__head + if info is None: + ismagic = 0 + isalias = 0 + ospace = '' + else: + ismagic = info.ismagic + isalias = info.isalias + ospace = info.namespace + # Get docstring, special-casing aliases: + if isalias: + ds = "Alias to the system command:\n %s" % obj[1] + else: + ds = getdoc(obj) + if formatter is not None: + ds = formatter(ds) + + # store output in a list which gets joined with \n at the end. + out = myStringIO() + + string_max = 200 # max size of strings to show (snipped if longer) + shalf = int((string_max -5)/2) + + if ismagic: + obj_type_name = 'Magic function' + elif isalias: + obj_type_name = 'System alias' + else: + obj_type_name = obj_type.__name__ + out.writeln(header('Type:\t\t')+obj_type_name) + + try: + bclass = obj.__class__ + out.writeln(header('Base Class:\t')+str(bclass)) + except: pass + + # String form, but snip if too long in ? form (full in ??) + try: + ostr = str(obj) + str_head = 'String Form:' + if not detail_level and len(ostr)>string_max: + ostr = ostr[:shalf] + ' <...> ' + ostr[-shalf:] + ostr = ("\n" + " " * len(str_head.expandtabs())).\ + join(map(string.strip,ostr.split("\n"))) + if ostr.find('\n') > -1: + # Print multi-line strings starting at the next line. + str_sep = '\n' + else: + str_sep = '\t' + out.writeln("%s%s%s" % (header(str_head),str_sep,ostr)) + except: + pass + + if ospace: + out.writeln(header('Namespace:\t')+ospace) + + # Length (for strings and lists) + try: + length = str(len(obj)) + out.writeln(header('Length:\t\t')+length) + except: pass + + # Filename where object was defined + try: + file = inspect.getabsfile(obj) + if file.endswith('<string>'): + file = 'Dynamically generated function. No source code available.' + out.writeln(header('File:\t\t')+file) + except: pass + + # reconstruct the function definition and print it: + defln = self.__getdef(obj,oname) + if defln: + out.write(header('Definition:\t')+self.format(defln)) + + # Docstrings only in detail 0 mode, since source contains them (we + # avoid repetitions). If source fails, we add them back, see below. + if ds and detail_level == 0: + out.writeln(header('Docstring:\n') + indent(ds)) + + # Original source code for any callable + if detail_level: + # Flush the source cache because inspect can return out-of-date source + linecache.checkcache() + try: + source = self.format(inspect.getsource(obj)) + out.write(header('Source:\n')+source.rstrip()) + except: + if ds: + out.writeln(header('Docstring:\n') + indent(ds)) + + # Constructor docstring for classes + if obj_type is types.ClassType: + # reconstruct the function definition and print it: + try: + obj_init = obj.__init__ + except AttributeError: + init_def = init_ds = None + else: + init_def = self.__getdef(obj_init,oname) + init_ds = getdoc(obj_init) + + if init_def or init_ds: + out.writeln(header('\nConstructor information:')) + if init_def: + out.write(header('Definition:\t')+ self.format(init_def)) + if init_ds: + out.writeln(header('Docstring:\n') + indent(init_ds)) + # and class docstring for instances: + elif obj_type is types.InstanceType: + + # First, check whether the instance docstring is identical to the + # class one, and print it separately if they don't coincide. In + # most cases they will, but it's nice to print all the info for + # objects which use instance-customized docstrings. + if ds: + class_ds = getdoc(obj.__class__) + if class_ds and ds != class_ds: + out.writeln(header('Class Docstring:\n') + + indent(class_ds)) + + # Next, try to show constructor docstrings + try: + init_ds = getdoc(obj.__init__) + except AttributeError: + init_ds = None + if init_ds: + out.writeln(header('Constructor Docstring:\n') + + indent(init_ds)) + + # Call form docstring for callable instances + if hasattr(obj,'__call__'): + out.writeln(header('Callable:\t')+'Yes') + call_def = self.__getdef(obj.__call__,oname) + if call_def is None: + out.write(header('Call def:\t')+ + 'Calling definition not available.') + else: + out.write(header('Call def:\t')+self.format(call_def)) + call_ds = getdoc(obj.__call__) + if call_ds: + out.writeln(header('Call docstring:\n') + indent(call_ds)) + + # Finally send to printer/pager + output = out.getvalue() + if output: + page(output) + # end pinfo diff --git a/IPython/OutputTrap.py b/IPython/OutputTrap.py new file mode 100644 index 0000000..670aa5a --- /dev/null +++ b/IPython/OutputTrap.py @@ -0,0 +1,262 @@ +# -*- coding: utf-8 -*- +"""Class to trap stdout and stderr and log them separately. + +$Id: OutputTrap.py 542 2005-03-18 09:16:04Z fperez $""" + +#***************************************************************************** +# Copyright (C) 2001-2004 Fernando Perez <fperez@colorado.edu> +# +# Distributed under the terms of the BSD License. The full license is in +# the file COPYING, distributed as part of this software. +#***************************************************************************** + +from IPython import Release +__author__ = '%s <%s>' % Release.authors['Fernando'] +__license__ = Release.license + +import exceptions,sys +from cStringIO import StringIO + +class OutputTrapError(exceptions.Exception): + """Exception for OutputTrap class.""" + + def __init__(self,args=None): + exceptions.Exception.__init__(self) + self.args = args + +class OutputTrap: + + """Class to trap standard output and standard error. They get logged in + StringIO objects which are available as <instance>.out and + <instance>.err. The class also offers summary methods which format this + data a bit. + + A word of caution: because it blocks messages, using this class can make + debugging very tricky. If you are having bizarre problems silently, try + turning your output traps off for a while. You can call the constructor + with the parameter debug=1 for these cases. This turns actual trapping + off, but you can keep the rest of your code unchanged (this has already + been a life saver). + + Example: + + # config: trapper with a line of dots as log separator (final '\\n' needed) + config = OutputTrap('Config','Out ','Err ','.'*80+'\\n') + + # start trapping output + config.trap_all() + + # now all output is logged ... + # do stuff... + + # output back to normal: + config.release_all() + + # print all that got logged: + print config.summary() + + # print individual raw data: + print config.out.getvalue() + print config.err.getvalue() + """ + + def __init__(self,name='Generic Output Trap', + out_head='Standard Output. ',err_head='Standard Error. ', + sum_sep='\n',debug=0,trap_out=0,trap_err=0, + quiet_out=0,quiet_err=0): + self.name = name + self.out_head = out_head + self.err_head = err_head + self.sum_sep = sum_sep + self.out = StringIO() + self.err = StringIO() + self.out_save = None + self.err_save = None + self.debug = debug + self.quiet_out = quiet_out + self.quiet_err = quiet_err + if trap_out: + self.trap_out() + if trap_err: + self.trap_err() + + def trap_out(self): + """Trap and log stdout.""" + if sys.stdout is self.out: + raise OutputTrapError,'You are already trapping stdout.' + if not self.debug: + self._out_save = sys.stdout + sys.stdout = self.out + + def release_out(self): + """Release stdout.""" + if not self.debug: + if not sys.stdout is self.out: + raise OutputTrapError,'You are not trapping stdout.' + sys.stdout = self._out_save + self.out_save = None + + def summary_out(self): + """Return as a string the log from stdout.""" + out = self.out.getvalue() + if out: + if self.quiet_out: + return out + else: + return self.out_head + 'Log by '+ self.name + ':\n' + out + else: + return '' + + def flush_out(self): + """Flush the stdout log. All data held in the log is lost.""" + + self.out.close() + self.out = StringIO() + + def trap_err(self): + """Trap and log stderr.""" + if sys.stderr is self.err: + raise OutputTrapError,'You are already trapping stderr.' + if not self.debug: + self._err_save = sys.stderr + sys.stderr = self.err + + def release_err(self): + """Release stderr.""" + if not self.debug: + if not sys.stderr is self.err: + raise OutputTrapError,'You are not trapping stderr.' + sys.stderr = self._err_save + self.err_save = None + + def summary_err(self): + """Return as a string the log from stderr.""" + err = self.err.getvalue() + if err: + if self.quiet_err: + return err + else: + return self.err_head + 'Log by '+ self.name + ':\n' + err + else: + return '' + + def flush_err(self): + """Flush the stdout log. All data held in the log is lost.""" + + self.err.close() + self.err = StringIO() + + def trap_all(self): + """Trap and log both stdout and stderr. + + Cacthes and discards OutputTrapError exceptions raised.""" + try: + self.trap_out() + except OutputTrapError: + pass + try: + self.trap_err() + except OutputTrapError: + pass + + def release_all(self): + """Release both stdout and stderr. + + Cacthes and discards OutputTrapError exceptions raised.""" + try: + self.release_out() + except OutputTrapError: + pass + try: + self.release_err() + except OutputTrapError: + pass + + def summary_all(self): + """Return as a string the log from stdout and stderr, prepending a separator + to each (defined in __init__ as sum_sep).""" + sum = '' + sout = self.summary_out() + if sout: + sum += self.sum_sep + sout + serr = self.summary_err() + if serr: + sum += '\n'+self.sum_sep + serr + return sum + + def flush_all(self): + """Flush stdout and stderr""" + self.flush_out() + self.flush_err() + + # a few shorthands + trap = trap_all + release = release_all + summary = summary_all + flush = flush_all +# end OutputTrap + + +#**************************************************************************** +# Module testing. Incomplete, I'm lazy... + +def _test_all(): + + """Module testing functions, activated when the module is called as a + script (not imported).""" + + # Put tests for this module in here. + # Define them as nested functions so they don't clobber the + # pydoc-generated docs + + def _test_(): + name = '' + print '#'*50+'\nRunning test for ' + name + # ... + print 'Finished test for '+ name +'\n'+'#'*50 + + def _test_OutputTrap(): + trap = OutputTrap(name = 'Test Trap', sum_sep = '.'*50+'\n', + out_head = 'SOut. ', err_head = 'SErr. ') + + name = 'OutputTrap class' + print '#'*50+'\nRunning test for ' + name + print 'Trapping out' + trap.trap_out() + print >>sys.stdout, '>>stdout. stdout is trapped.' + print >>sys.stderr, '>>stderr. stdout is trapped.' + trap.release_out() + print trap.summary_out() + + print 'Trapping err' + trap.trap_err() + print >>sys.stdout, '>>stdout. stderr is trapped.' + print >>sys.stderr, '>>stderr. stderr is trapped.' + trap.release_err() + print trap.summary_err() + + print 'Trapping all (no flushing)' + trap.trap_all() + print >>sys.stdout, '>>stdout. stdout/err is trapped.' + print >>sys.stderr, '>>stderr. stdout/err is trapped.' + trap.release_all() + print trap.summary_all() + + print 'Trapping all (flushing first)' + trap.flush() + trap.trap_all() + print >>sys.stdout, '>>stdout. stdout/err is trapped.' + print >>sys.stderr, '>>stderr. stdout/err is trapped.' + trap.release_all() + print trap.summary_all() + print 'Finished test for '+ name +'\n'+'#'*50 + + # call the actual tests here: + _test_OutputTrap() + + +if __name__=="__main__": + # _test_all() # XXX BROKEN. + pass + +#************************ end of file <OutputTrap.py> ************************ diff --git a/IPython/Prompts.py b/IPython/Prompts.py new file mode 100644 index 0000000..361e8ac --- /dev/null +++ b/IPython/Prompts.py @@ -0,0 +1,574 @@ +# -*- coding: utf-8 -*- +""" +Classes for handling input/output prompts. + +$Id: Prompts.py 564 2005-03-26 22:43:58Z fperez $""" + +#***************************************************************************** +# Copyright (C) 2001-2004 Fernando Perez <fperez@colorado.edu> +# +# Distributed under the terms of the BSD License. The full license is in +# the file COPYING, distributed as part of this software. +#***************************************************************************** + +from IPython import Release +__author__ = '%s <%s>' % Release.authors['Fernando'] +__license__ = Release.license +__version__ = Release.version + +#**************************************************************************** +# Required modules +import __builtin__ +import os,sys,socket +import time +from pprint import pprint,pformat + +# IPython's own +from IPython.genutils import * +from IPython.Struct import Struct +from IPython.Magic import Macro +from IPython.Itpl import ItplNS +from IPython import ColorANSI + +#**************************************************************************** +#Color schemes for Prompts. + +PromptColors = ColorANSI.ColorSchemeTable() +InputColors = ColorANSI.InputTermColors # just a shorthand +Colors = ColorANSI.TermColors # just a shorthand + +PromptColors.add_scheme(ColorANSI.ColorScheme( + 'NoColor', + in_prompt = InputColors.NoColor, # Input prompt + in_number = InputColors.NoColor, # Input prompt number + in_prompt2 = InputColors.NoColor, # Continuation prompt + in_normal = InputColors.NoColor, # color off (usu. Colors.Normal) + + out_prompt = Colors.NoColor, # Output prompt + out_number = Colors.NoColor, # Output prompt number + + normal = Colors.NoColor # color off (usu. Colors.Normal) + )) +# make some schemes as instances so we can copy them for modification easily: +__PColLinux = ColorANSI.ColorScheme( + 'Linux', + in_prompt = InputColors.Green, + in_number = InputColors.LightGreen, + in_prompt2 = InputColors.Green, + in_normal = InputColors.Normal, # color off (usu. Colors.Normal) + + out_prompt = Colors.Red, + out_number = Colors.LightRed, + + normal = Colors.Normal + ) +# Don't forget to enter it into the table! +PromptColors.add_scheme(__PColLinux) +# Slightly modified Linux for light backgrounds +__PColLightBG = ColorANSI.ColorScheme('LightBG',**__PColLinux.colors.dict().copy()) + +__PColLightBG.colors.update( + in_prompt = InputColors.Blue, + in_number = InputColors.LightBlue, + in_prompt2 = InputColors.Blue +) +PromptColors.add_scheme(__PColLightBG) + +del Colors,InputColors + +#----------------------------------------------------------------------------- +def multiple_replace(dict, text): + """ Replace in 'text' all occurences of any key in the given + dictionary by its corresponding value. Returns the new string.""" + + # Function by Xavier Defrang, originally found at: + # http://aspn.activestate.com/ASPN/Cookbook/Python/Recipe/81330 + + # Create a regular expression from the dictionary keys + regex = re.compile("(%s)" % "|".join(map(re.escape, dict.keys()))) + # For each match, look-up corresponding value in dictionary + return regex.sub(lambda mo: dict[mo.string[mo.start():mo.end()]], text) + +#----------------------------------------------------------------------------- +# Special characters that can be used in prompt templates, mainly bash-like + +# If $HOME isn't defined (Windows), make it an absurd string so that it can +# never be expanded out into '~'. Basically anything which can never be a +# reasonable directory name will do, we just want the $HOME -> '~' operation +# to become a no-op. We pre-compute $HOME here so it's not done on every +# prompt call. + +# FIXME: + +# - This should be turned into a class which does proper namespace management, +# since the prompt specials need to be evaluated in a certain namespace. +# Currently it's just globals, which need to be managed manually by code +# below. + +# - I also need to split up the color schemes from the prompt specials +# somehow. I don't have a clean design for that quite yet. + +HOME = os.environ.get("HOME","//////:::::ZZZZZ,,,~~~") + +# We precompute a few more strings here for the prompt_specials, which are +# fixed once ipython starts. This reduces the runtime overhead of computing +# prompt strings. +USER = os.environ.get("USER") +HOSTNAME = socket.gethostname() +HOSTNAME_SHORT = HOSTNAME.split(".")[0] +ROOT_SYMBOL = "$#"[os.name=='nt' or os.getuid()==0] + +prompt_specials_color = { + # Prompt/history count + '%n' : '${self.col_num}' '${self.cache.prompt_count}' '${self.col_p}', + '\\#': '${self.col_num}' '${self.cache.prompt_count}' '${self.col_p}', + # Prompt/history count, with the actual digits replaced by dots. Used + # mainly in continuation prompts (prompt_in2) + '\\D': '${"."*len(str(self.cache.prompt_count))}', + # Current working directory + '\\w': '${os.getcwd()}', + # Current time + '\\t' : '${time.strftime("%H:%M:%S")}', + # Basename of current working directory. + # (use os.sep to make this portable across OSes) + '\\W' : '${os.getcwd().split("%s")[-1]}' % os.sep, + # These X<N> are an extension to the normal bash prompts. They return + # N terms of the path, after replacing $HOME with '~' + '\\X0': '${os.getcwd().replace("%s","~")}' % HOME, + '\\X1': '${self.cwd_filt(1)}', + '\\X2': '${self.cwd_filt(2)}', + '\\X3': '${self.cwd_filt(3)}', + '\\X4': '${self.cwd_filt(4)}', + '\\X5': '${self.cwd_filt(5)}', + # Y<N> are similar to X<N>, but they show '~' if it's the directory + # N+1 in the list. Somewhat like %cN in tcsh. + '\\Y0': '${self.cwd_filt2(0)}', + '\\Y1': '${self.cwd_filt2(1)}', + '\\Y2': '${self.cwd_filt2(2)}', + '\\Y3': '${self.cwd_filt2(3)}', + '\\Y4': '${self.cwd_filt2(4)}', + '\\Y5': '${self.cwd_filt2(5)}', + # Hostname up to first . + '\\h': HOSTNAME_SHORT, + # Full hostname + '\\H': HOSTNAME, + # Username of current user + '\\u': USER, + # Escaped '\' + '\\\\': '\\', + # Newline + '\\n': '\n', + # Carriage return + '\\r': '\r', + # Release version + '\\v': __version__, + # Root symbol ($ or #) + '\\$': ROOT_SYMBOL, + } + +# A copy of the prompt_specials dictionary but with all color escapes removed, +# so we can correctly compute the prompt length for the auto_rewrite method. +prompt_specials_nocolor = prompt_specials_color.copy() +prompt_specials_nocolor['%n'] = '${self.cache.prompt_count}' +prompt_specials_nocolor['\\#'] = '${self.cache.prompt_count}' + +# Add in all the InputTermColors color escapes as valid prompt characters. +# They all get added as \\C_COLORNAME, so that we don't have any conflicts +# with a color name which may begin with a letter used by any other of the +# allowed specials. This of course means that \\C will never be allowed for +# anything else. +input_colors = ColorANSI.InputTermColors +for _color in dir(input_colors): + if _color[0] != '_': + c_name = '\\C_'+_color + prompt_specials_color[c_name] = getattr(input_colors,_color) + prompt_specials_nocolor[c_name] = '' + +# we default to no color for safety. Note that prompt_specials is a global +# variable used by all prompt objects. +prompt_specials = prompt_specials_nocolor + +#----------------------------------------------------------------------------- +def str_safe(arg): + """Convert to a string, without ever raising an exception. + + If str(arg) fails, <ERROR: ... > is returned, where ... is the exception + error message.""" + + try: + return str(arg) + except Exception,msg: + return '<ERROR: %s>' % msg + +class BasePrompt: + """Interactive prompt similar to Mathematica's.""" + def __init__(self,cache,sep,prompt,pad_left=False): + + # Hack: we access information about the primary prompt through the + # cache argument. We need this, because we want the secondary prompt + # to be aligned with the primary one. Color table info is also shared + # by all prompt classes through the cache. Nice OO spaghetti code! + self.cache = cache + self.sep = sep + + # regexp to count the number of spaces at the end of a prompt + # expression, useful for prompt auto-rewriting + self.rspace = re.compile(r'(\s*)$') + # Flag to left-pad prompt strings to match the length of the primary + # prompt + self.pad_left = pad_left + # Set template to create each actual prompt (where numbers change) + self.p_template = prompt + self.set_p_str() + + def set_p_str(self): + """ Set the interpolating prompt strings. + + This must be called every time the color settings change, because the + prompt_specials global may have changed.""" + + import os,time # needed in locals for prompt string handling + loc = locals() + self.p_str = ItplNS('%s%s%s' % + ('${self.sep}${self.col_p}', + multiple_replace(prompt_specials, self.p_template), + '${self.col_norm}'),self.cache.user_ns,loc) + + self.p_str_nocolor = ItplNS(multiple_replace(prompt_specials_nocolor, + self.p_template), + self.cache.user_ns,loc) + + def write(self,msg): # dbg + sys.stdout.write(msg) + return '' + + def __str__(self): + """Return a string form of the prompt. + + This for is useful for continuation and output prompts, since it is + left-padded to match lengths with the primary one (if the + self.pad_left attribute is set).""" + + out_str = str_safe(self.p_str) + if self.pad_left: + # We must find the amount of padding required to match lengths, + # taking the color escapes (which are invisible on-screen) into + # account. + esc_pad = len(out_str) - len(str_safe(self.p_str_nocolor)) + format = '%%%ss' % (len(str(self.cache.last_prompt))+esc_pad) + return format % out_str + else: + return out_str + + # these path filters are put in as methods so that we can control the + # namespace where the prompt strings get evaluated + def cwd_filt(self,depth): + """Return the last depth elements of the current working directory. + + $HOME is always replaced with '~'. + If depth==0, the full path is returned.""" + + cwd = os.getcwd().replace(HOME,"~") + out = os.sep.join(cwd.split(os.sep)[-depth:]) + if out: + return out + else: + return os.sep + + def cwd_filt2(self,depth): + """Return the last depth elements of the current working directory. + + $HOME is always replaced with '~'. + If depth==0, the full path is returned.""" + + cwd = os.getcwd().replace(HOME,"~").split(os.sep) + if '~' in cwd and len(cwd) == depth+1: + depth += 1 + out = os.sep.join(cwd[-depth:]) + if out: + return out + else: + return os.sep + +class Prompt1(BasePrompt): + """Input interactive prompt similar to Mathematica's.""" + + def __init__(self,cache,sep='\n',prompt='In [\\#]: ',pad_left=True): + BasePrompt.__init__(self,cache,sep,prompt,pad_left) + + def set_colors(self): + self.set_p_str() + Colors = self.cache.color_table.active_colors # shorthand + self.col_p = Colors.in_prompt + self.col_num = Colors.in_number + self.col_norm = Colors.in_normal + # We need a non-input version of these escapes for the '--->' + # auto-call prompts used in the auto_rewrite() method. + self.col_p_ni = self.col_p.replace('\001','').replace('\002','') + self.col_norm_ni = Colors.normal + + def __str__(self): + self.cache.prompt_count += 1 + self.cache.last_prompt = str_safe(self.p_str_nocolor).split('\n')[-1] + return str_safe(self.p_str) + + def auto_rewrite(self): + """Print a string of the form '--->' which lines up with the previous + input string. Useful for systems which re-write the user input when + handling automatically special syntaxes.""" + + curr = str(self.cache.last_prompt) + nrspaces = len(self.rspace.search(curr).group()) + return '%s%s>%s%s' % (self.col_p_ni,'-'*(len(curr)-nrspaces-1), + ' '*nrspaces,self.col_norm_ni) + +class PromptOut(BasePrompt): + """Output interactive prompt similar to Mathematica's.""" + + def __init__(self,cache,sep='',prompt='Out[\\#]: ',pad_left=True): + BasePrompt.__init__(self,cache,sep,prompt,pad_left) + if not self.p_template: + self.__str__ = lambda: '' + + def set_colors(self): + self.set_p_str() + Colors = self.cache.color_table.active_colors # shorthand + self.col_p = Colors.out_prompt + self.col_num = Colors.out_number + self.col_norm = Colors.normal + +class Prompt2(BasePrompt): + """Interactive continuation prompt.""" + + def __init__(self,cache,prompt=' .\\D.: ',pad_left=True): + self.cache = cache + self.p_template = prompt + self.pad_left = pad_left + self.set_p_str() + + def set_p_str(self): + import os,time # needed in locals for prompt string handling + loc = locals() + self.p_str = ItplNS('%s%s%s' % + ('${self.col_p2}', + multiple_replace(prompt_specials, self.p_template), + '$self.col_norm'), + self.cache.user_ns,loc) + self.p_str_nocolor = ItplNS(multiple_replace(prompt_specials_nocolor, + self.p_template), + self.cache.user_ns,loc) + + def set_colors(self): + self.set_p_str() + Colors = self.cache.color_table.active_colors + self.col_p2 = Colors.in_prompt2 + self.col_norm = Colors.in_normal + # FIXME (2004-06-16) HACK: prevent crashes for users who haven't + # updated their prompt_in2 definitions. Remove eventually. + self.col_p = Colors.out_prompt + self.col_num = Colors.out_number + +#----------------------------------------------------------------------------- +class CachedOutput: + """Class for printing output from calculations while keeping a cache of + reults. It dynamically creates global variables prefixed with _ which + contain these results. + + Meant to be used as a sys.displayhook replacement, providing numbered + prompts and cache services. + + Initialize with initial and final values for cache counter (this defines + the maximum size of the cache.""" + + def __init__(self,cache_size,Pprint,colors='NoColor',input_sep='\n', + output_sep='\n',output_sep2='',user_ns={}, + ps1 = None, ps2 = None,ps_out = None, + input_hist = None,pad_left=True): + + cache_size_min = 20 + if cache_size <= 0: + self.do_full_cache = 0 + cache_size = 0 + elif cache_size < cache_size_min: + self.do_full_cache = 0 + cache_size = 0 + warn('caching was disabled (min value for cache size is %s).' % + cache_size_min,level=3) + else: + self.do_full_cache = 1 + + self.cache_size = cache_size + self.input_sep = input_sep + + # we need a reference to the user-level namespace + self.user_ns = user_ns + # and to the user's input + self.input_hist = input_hist + + # Set input prompt strings and colors + if cache_size == 0: + if ps1.find('%n') > -1 or ps1.find('\\#') > -1: ps1 = '>>> ' + if ps2.find('%n') > -1 or ps2.find('\\#') > -1: ps2 = '... ' + self.ps1_str = self._set_prompt_str(ps1,'In [\\#]: ','>>> ') + self.ps2_str = self._set_prompt_str(ps2,' .\\D.: ','... ') + self.ps_out_str = self._set_prompt_str(ps_out,'Out[\\#]: ','') + + self.prompt1 = Prompt1(self,sep=input_sep,prompt=self.ps1_str, + pad_left=pad_left) + self.prompt2 = Prompt2(self,prompt=self.ps2_str,pad_left=pad_left) + self.prompt_out = PromptOut(self,sep='',prompt=self.ps_out_str, + pad_left=pad_left) + self.color_table = PromptColors + self.set_colors(colors) + + # other more normal stuff + # b/c each call to the In[] prompt raises it by 1, even the first. + self.prompt_count = 0 + self.cache_count = 1 + # Store the last prompt string each time, we need it for aligning + # continuation and auto-rewrite prompts + self.last_prompt = '' + self.entries = [None] # output counter starts at 1 for the user + self.Pprint = Pprint + self.output_sep = output_sep + self.output_sep2 = output_sep2 + self._,self.__,self.___ = '','','' + self.pprint_types = map(type,[(),[],{}]) + + # these are deliberately global: + to_user_ns = {'_':self._,'__':self.__,'___':self.___} + self.user_ns.update(to_user_ns) + + def _set_prompt_str(self,p_str,cache_def,no_cache_def): + if p_str is None: + if self.do_full_cache: + return cache_def + else: + return no_cache_def + else: + return p_str + + def set_colors(self,colors): + """Set the active color scheme and configure colors for the three + prompt subsystems.""" + + # FIXME: the prompt_specials global should be gobbled inside this + # class instead. Do it when cleaning up the whole 3-prompt system. + global prompt_specials + if colors.lower()=='nocolor': + prompt_specials = prompt_specials_nocolor + else: + prompt_specials = prompt_specials_color + + self.color_table.set_active_scheme(colors) + self.prompt1.set_colors() + self.prompt2.set_colors() + self.prompt_out.set_colors() + + def __call__(self,arg=None): + """Printing with history cache management. + + This is invoked everytime the interpreter needs to print, and is + activated by setting the variable sys.displayhook to it.""" + + # If something injected a '_' variable in __builtin__, delete + # ipython's automatic one so we don't clobber that. gettext() in + # particular uses _, so we need to stay away from it. + if '_' in __builtin__.__dict__: + try: + del self.user_ns['_'] + except KeyError: + pass + if arg is not None: + # first handle the cache and counters + self.update(arg) + # do not print output if input ends in ';' + if self.input_hist[self.prompt_count].endswith(';\n'): + return + # don't use print, puts an extra space + Term.cout.write(self.output_sep) + if self.do_full_cache: + Term.cout.write(str(self.prompt_out)) + + if isinstance(arg,Macro): + print 'Executing Macro...' + # in case the macro takes a long time to execute + Term.cout.flush() + exec arg.value in self.user_ns + return None + + # and now call a possibly user-defined print mechanism + self.display(arg) + Term.cout.write(self.output_sep2) + Term.cout.flush() + + def _display(self,arg): + """Default printer method, uses pprint. + + This can be over-ridden by the users to implement special formatting + of certain types of output.""" + + if self.Pprint: + # The following is an UGLY kludge, b/c python fails to properly + # identify instances of classes imported in the user namespace + # (they have different memory locations, I guess). Structs are + # essentially dicts but pprint doesn't know what to do with them. + try: + if arg.__class__.__module__ == 'Struct' and \ + arg.__class__.__name__ == 'Struct': + out = 'Struct:\n%s' % pformat(arg.dict()) + else: + out = pformat(arg) + except: + out = pformat(arg) + if '\n' in out: + # So that multi-line strings line up with the left column of + # the screen, instead of having the output prompt mess up + # their first line. + Term.cout.write('\n') + print >>Term.cout, out + else: + print >>Term.cout, arg + + # Assign the default display method: + display = _display + + def update(self,arg): + #print '***cache_count', self.cache_count # dbg + if self.cache_count >= self.cache_size and self.do_full_cache: + self.flush() + # Don't overwrite '_' and friends if '_' is in __builtin__ (otherwise + # we cause buggy behavior for things like gettext). + if '_' not in __builtin__.__dict__: + self.___ = self.__ + self.__ = self._ + self._ = arg + self.user_ns.update({'_':self._,'__':self.__,'___':self.___}) + + # hackish access to top-level namespace to create _1,_2... dynamically + to_main = {} + if self.do_full_cache: + self.cache_count += 1 + self.entries.append(arg) + new_result = '_'+`self.prompt_count` + to_main[new_result] = self.entries[-1] + self.user_ns.update(to_main) + self.user_ns['_oh'][self.prompt_count] = arg + + def flush(self): + if not self.do_full_cache: + raise ValueError,"You shouldn't have reached the cache flush "\ + "if full caching is not enabled!" + warn('Output cache limit (currently '+\ + `self.cache_count`+' entries) hit.\n' + 'Flushing cache and resetting history counter...\n' + 'The only history variables available will be _,__,___ and _1\n' + 'with the current result.') + # delete auto-generated vars from global namespace + for n in range(1,self.prompt_count + 1): + key = '_'+`n` + try: + del self.user_ns[key] + except: pass + self.prompt_count = 1 + self.cache_count = 1 diff --git a/IPython/PyColorize.py b/IPython/PyColorize.py new file mode 100755 index 0000000..1481725 --- /dev/null +++ b/IPython/PyColorize.py @@ -0,0 +1,255 @@ +# -*- coding: utf-8 -*- +""" + Class and program to colorize python source code for ANSI terminals. + + Based on an HTML code highlighter by Jurgen Hermann found at: + http://aspn.activestate.com/ASPN/Cookbook/Python/Recipe/52298 + + Modifications by Fernando Perez (fperez@colorado.edu). + + Information on the original HTML highlighter follows: + + MoinMoin - Python Source Parser + + Title:olorize Python source using the built-in tokenizer + + Submitter: Jurgen Hermann + Last Updated:2001/04/06 + + Version no:1.2 + + Description: + + This code is part of MoinMoin (http://moin.sourceforge.net/) and converts + Python source code to HTML markup, rendering comments, keywords, + operators, numeric and string literals in different colors. + + It shows how to use the built-in keyword, token and tokenize modules to + scan Python source code and re-emit it with no changes to its original + formatting (which is the hard part). + + $Id: PyColorize.py 485 2005-01-27 19:15:39Z fperez $""" + +__all__ = ['ANSICodeColors','Parser'] + +_scheme_default = 'Linux' + +# Imports +import string, sys, os, cStringIO +import keyword, token, tokenize + +from IPython.ColorANSI import * + +############################################################################# +### Python Source Parser (does Hilighting) +############################################################################# + +_KEYWORD = token.NT_OFFSET + 1 +_TEXT = token.NT_OFFSET + 2 + +#**************************************************************************** +# Builtin color schemes + +Colors = TermColors # just a shorthand + +# Build a few color schemes +NoColor = ColorScheme( + 'NoColor',{ + token.NUMBER : Colors.NoColor, + token.OP : Colors.NoColor, + token.STRING : Colors.NoColor, + tokenize.COMMENT : Colors.NoColor, + token.NAME : Colors.NoColor, + token.ERRORTOKEN : Colors.NoColor, + + _KEYWORD : Colors.NoColor, + _TEXT : Colors.NoColor, + + 'normal' : Colors.NoColor # color off (usu. Colors.Normal) + } ) + +LinuxColors = ColorScheme( + 'Linux',{ + token.NUMBER : Colors.LightCyan, + token.OP : Colors.Yellow, + token.STRING : Colors.LightBlue, + tokenize.COMMENT : Colors.LightRed, + token.NAME : Colors.White, + token.ERRORTOKEN : Colors.Red, + + _KEYWORD : Colors.LightGreen, + _TEXT : Colors.Yellow, + + 'normal' : Colors.Normal # color off (usu. Colors.Normal) + } ) + +LightBGColors = ColorScheme( + 'LightBG',{ + token.NUMBER : Colors.Cyan, + token.OP : Colors.Blue, + token.STRING : Colors.Blue, + tokenize.COMMENT : Colors.Red, + token.NAME : Colors.Black, + token.ERRORTOKEN : Colors.Red, + + _KEYWORD : Colors.Green, + _TEXT : Colors.Blue, + + 'normal' : Colors.Normal # color off (usu. Colors.Normal) + } ) + +# Build table of color schemes (needed by the parser) +ANSICodeColors = ColorSchemeTable([NoColor,LinuxColors,LightBGColors], + _scheme_default) + +class Parser: + """ Format colored Python source. + """ + + def __init__(self, color_table=None,out = sys.stdout): + """ Create a parser with a specified color table and output channel. + + Call format() to process code. + """ + self.color_table = color_table and color_table or ANSICodeColors + self.out = out + + def format(self, raw, out = None, scheme = ''): + """ Parse and send the colored source. + + If out and scheme are not specified, the defaults (given to + constructor) are used. + + out should be a file-type object. Optionally, out can be given as the + string 'str' and the parser will automatically return the output in a + string.""" + + self.raw = string.strip(string.expandtabs(raw)) + string_output = 0 + if out == 'str' or self.out == 'str': + out_old = self.out + self.out = cStringIO.StringIO() + string_output = 1 + elif out is not None: + self.out = out + # local shorthand + colors = self.color_table[scheme].colors + self.colors = colors # put in object so __call__ sees it + # store line offsets in self.lines + self.lines = [0, 0] + pos = 0 + while 1: + pos = string.find(self.raw, '\n', pos) + 1 + if not pos: break + self.lines.append(pos) + self.lines.append(len(self.raw)) + + # parse the source and write it + self.pos = 0 + text = cStringIO.StringIO(self.raw) + #self.out.write('<pre><font face="Courier New">') + try: + tokenize.tokenize(text.readline, self) + except tokenize.TokenError, ex: + msg = ex[0] + line = ex[1][0] + self.out.write("%s\n\n*** ERROR: %s%s%s\n" % + (colors[token.ERRORTOKEN], + msg, self.raw[self.lines[line]:], + colors.normal) + ) + self.out.write(colors.normal+'\n') + if string_output: + output = self.out.getvalue() + self.out = out_old + return output + + def __call__(self, toktype, toktext, (srow,scol), (erow,ecol), line): + """ Token handler, with syntax highlighting.""" + + # local shorthand + colors = self.colors + + # line separator, so this works across platforms + linesep = os.linesep + + # calculate new positions + oldpos = self.pos + newpos = self.lines[srow] + scol + self.pos = newpos + len(toktext) + + # handle newlines + if toktype in [token.NEWLINE, tokenize.NL]: + self.out.write(linesep) + return + + # send the original whitespace, if needed + if newpos > oldpos: + self.out.write(self.raw[oldpos:newpos]) + + # skip indenting tokens + if toktype in [token.INDENT, token.DEDENT]: + self.pos = newpos + return + + # map token type to a color group + if token.LPAR <= toktype and toktype <= token.OP: + toktype = token.OP + elif toktype == token.NAME and keyword.iskeyword(toktext): + toktype = _KEYWORD + color = colors.get(toktype, colors[_TEXT]) + + #print '<%s>' % toktext, # dbg + + # Triple quoted strings must be handled carefully so that backtracking + # in pagers works correctly. We need color terminators on _each_ line. + if linesep in toktext: + toktext = toktext.replace(linesep, '%s%s%s' % + (colors.normal,linesep,color)) + + # send text + self.out.write('%s%s%s' % (color,toktext,colors.normal)) + +def main(): + """Colorize a python file using ANSI color escapes and print to stdout. + + Usage: + %s [-s scheme] filename + + Options: + + -s scheme: give the color scheme to use. Currently only 'Linux' + (default) and 'LightBG' and 'NoColor' are implemented (give without + quotes). """ + + def usage(): + print >> sys.stderr, main.__doc__ % sys.argv[0] + sys.exit(1) + + # FIXME: rewrite this to at least use getopt + try: + if sys.argv[1] == '-s': + scheme_name = sys.argv[2] + del sys.argv[1:3] + else: + scheme_name = _scheme_default + + except: + usage() + + try: + fname = sys.argv[1] + except: + usage() + + # write colorized version to stdout + parser = Parser() + try: + parser.format(file(fname).read(),scheme = scheme_name) + except IOError,msg: + # if user reads through a pager and quits, don't print traceback + if msg.args != (32,'Broken pipe'): + raise + +if __name__ == "__main__": + main() diff --git a/IPython/Release.py b/IPython/Release.py new file mode 100644 index 0000000..a6b5db0 --- /dev/null +++ b/IPython/Release.py @@ -0,0 +1,69 @@ +# -*- coding: utf-8 -*- +"""Release data for the IPython project. + +$Id: Release.py 605 2005-06-09 14:09:03Z fperez $""" + +#***************************************************************************** +# Copyright (C) 2001-2005 Fernando Perez <fperez@colorado.edu> +# +# Copyright (c) 2001 Janko Hauser <jhauser@zscout.de> and Nathaniel Gray +# <n8gray@caltech.edu> +# +# Distributed under the terms of the BSD License. The full license is in +# the file COPYING, distributed as part of this software. +#***************************************************************************** + +# Name of the package for release purposes. This is the name which labels +# the tarballs and RPMs made by distutils, so it's best to lowercase it. +name = 'ipython' + +# For versions with substrings (like 0.6.7_rc1), use _ but NOT -, since +# bdist_rpm chokes on dashes in the version string. +version = '0.6.16_cvs' + +description = "An enhanced interactive Python shell." + +long_description = \ +""" +IPython provides a replacement for the interactive Python interpreter with +extra functionality. + +Main features: + + * Comprehensive object introspection. + + * Input history, persistent across sessions. + + * Caching of output results during a session with automatically generated + references. + + * Readline based name completion. + + * Extensible system of 'magic' commands for controlling the environment and + performing many tasks related either to IPython or the operating system. + + * Configuration system with easy switching between different setups (simpler + than changing $PYTHONSTARTUP environment variables every time). + + * Session logging and reloading. + + * Extensible syntax processing for special purpose situations. + + * Access to the system shell with user-extensible alias system. + + * Easily embeddable in other Python programs. + + * Integrated access to the pdb debugger and the Python profiler. """ + +license = 'BSD' + +authors = {'Fernando' : ('Fernando Perez','fperez@colorado.edu'), + 'Janko' : ('Janko Hauser','jhauser@zscout.de'), + 'Nathan' : ('Nathaniel Gray','n8gray@caltech.edu') + } + +url = 'http://ipython.scipy.org' + +platforms = ['Linux','Mac OSX','Windows XP/2000/NT','Windows 95/98/ME'] + +keywords = ['Interactive','Interpreter','Shell'] diff --git a/IPython/Shell.py b/IPython/Shell.py new file mode 100644 index 0000000..6e95fed --- /dev/null +++ b/IPython/Shell.py @@ -0,0 +1,894 @@ +# -*- coding: utf-8 -*- +"""IPython Shell classes. + +All the matplotlib support code was co-developed with John Hunter, +matplotlib's author. + +$Id: Shell.py 605 2005-06-09 14:09:03Z fperez $""" + +#***************************************************************************** +# Copyright (C) 2001-2004 Fernando Perez <fperez@colorado.edu> +# +# Distributed under the terms of the BSD License. The full license is in +# the file COPYING, distributed as part of this software. +#***************************************************************************** + +from IPython import Release +__author__ = '%s <%s>' % Release.authors['Fernando'] +__license__ = Release.license + +# Code begins +import __main__ +import __builtin__ +import sys +import os +import code +import threading +import signal + +import IPython +from IPython.iplib import InteractiveShell +from IPython.ipmaker import make_IPython +from IPython.genutils import Term,warn,error,flag_calls +from IPython.Struct import Struct +from IPython.Magic import Magic +from IPython import ultraTB + +# global flag to pass around information about Ctrl-C without exceptions +KBINT = False + +# global flag to turn on/off Tk support. +USE_TK = False + +#----------------------------------------------------------------------------- +# 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. + +class IPShell: + """Create an IPython instance.""" + + def __init__(self,argv=None,user_ns=None,debug=1, + shell_class=InteractiveShell): + self.IP = make_IPython(argv,user_ns=user_ns,debug=debug, + shell_class=shell_class) + + def mainloop(self,sys_exit=0,banner=None): + self.IP.mainloop(banner) + if sys_exit: + sys.exit() + +#----------------------------------------------------------------------------- +class IPShellEmbed: + """Allow embedding an IPython shell into a running program. + + Instances of this class are callable, with the __call__ method being an + alias to the embed() method of an InteractiveShell instance. + + Usage (see also the example-embed.py file for a running example): + + ipshell = IPShellEmbed([argv,banner,exit_msg,rc_override]) + + - argv: list containing valid command-line options for IPython, as they + would appear in sys.argv[1:]. + + For example, the following command-line options: + + $ ipython -prompt_in1 'Input <\\#>' -colors LightBG + + would be passed in the argv list as: + + ['-prompt_in1','Input <\\#>','-colors','LightBG'] + + - banner: string which gets printed every time the interpreter starts. + + - exit_msg: string which gets printed every time the interpreter exits. + + - rc_override: a dict or Struct of configuration options such as those + used by IPython. These options are read from your ~/.ipython/ipythonrc + file when the Shell object is created. Passing an explicit rc_override + dict with any options you want allows you to override those values at + creation time without having to modify the file. This way you can create + embeddable instances configured in any way you want without editing any + global files (thus keeping your interactive IPython configuration + unchanged). + + Then the ipshell instance can be called anywhere inside your code: + + ipshell(header='') -> Opens up an IPython shell. + + - header: string printed by the IPython shell upon startup. This can let + you know where in your code you are when dropping into the shell. Note + that 'banner' gets prepended to all calls, so header is used for + location-specific information. + + For more details, see the __call__ method below. + + When the IPython shell is exited with Ctrl-D, normal program execution + resumes. + + This functionality was inspired by a posting on comp.lang.python by cmkl + <cmkleffner@gmx.de> on Dec. 06/01 concerning similar uses of pyrepl, and + by the IDL stop/continue commands.""" + + def __init__(self,argv=None,banner='',exit_msg=None,rc_override=None): + """Note that argv here is a string, NOT a list.""" + self.set_banner(banner) + self.set_exit_msg(exit_msg) + self.set_dummy_mode(0) + + # sys.displayhook is a global, we need to save the user's original + # Don't rely on __displayhook__, as the user may have changed that. + self.sys_displayhook_ori = sys.displayhook + + # save readline completer status + try: + #print 'Save completer',sys.ipcompleter # dbg + self.sys_ipcompleter_ori = sys.ipcompleter + except: + pass # not nested with IPython + + # FIXME. Passing user_ns breaks namespace handling. + #self.IP = make_IPython(argv,user_ns=__main__.__dict__) + self.IP = make_IPython(argv,rc_override=rc_override,embedded=True) + + self.IP.name_space_init() + # mark this as an embedded instance so we know if we get a crash + # post-mortem + self.IP.rc.embedded = 1 + # copy our own displayhook also + self.sys_displayhook_embed = sys.displayhook + # and leave the system's display hook clean + sys.displayhook = self.sys_displayhook_ori + # don't use the ipython crash handler so that user exceptions aren't + # trapped + sys.excepthook = ultraTB.FormattedTB(color_scheme = self.IP.rc.colors, + mode = self.IP.rc.xmode, + call_pdb = self.IP.rc.pdb) + self.restore_system_completer() + + def restore_system_completer(self): + """Restores the readline completer which was in place. + + This allows embedded IPython within IPython not to disrupt the + parent's completion. + """ + + try: + self.IP.readline.set_completer(self.sys_ipcompleter_ori) + sys.ipcompleter = self.sys_ipcompleter_ori + except: + pass + + def __call__(self,header='',local_ns=None,global_ns=None,dummy=None): + """Activate the interactive interpreter. + + __call__(self,header='',local_ns=None,global_ns,dummy=None) -> Start + the interpreter shell with the given local and global namespaces, and + optionally print a header string at startup. + + The shell can be globally activated/deactivated using the + set/get_dummy_mode methods. This allows you to turn off a shell used + for debugging globally. + + However, *each* time you call the shell you can override the current + state of dummy_mode with the optional keyword parameter 'dummy'. For + example, if you set dummy mode on with IPShell.set_dummy_mode(1), you + can still have a specific call work by making it as IPShell(dummy=0). + + The optional keyword parameter dummy controls whether the call + actually does anything. """ + + # Allow the dummy parameter to override the global __dummy_mode + if dummy or (dummy != 0 and self.__dummy_mode): + return + + # Set global subsystems (display,completions) to our values + sys.displayhook = self.sys_displayhook_embed + if self.IP.has_readline: + self.IP.readline.set_completer(self.IP.Completer.complete) + + if self.banner and header: + format = '%s\n%s\n' + else: + format = '%s%s\n' + banner = format % (self.banner,header) + + # Call the embedding code with a stack depth of 1 so it can skip over + # our call and get the original caller's namespaces. + self.IP.embed_mainloop(banner,local_ns,global_ns,stack_depth=1) + + if self.exit_msg: + print self.exit_msg + + # Restore global systems (display, completion) + sys.displayhook = self.sys_displayhook_ori + self.restore_system_completer() + + def set_dummy_mode(self,dummy): + """Sets the embeddable shell's dummy mode parameter. + + set_dummy_mode(dummy): dummy = 0 or 1. + + This parameter is persistent and makes calls to the embeddable shell + silently return without performing any action. This allows you to + globally activate or deactivate a shell you're using with a single call. + + If you need to manually""" + + if dummy not in [0,1]: + raise ValueError,'dummy parameter must be 0 or 1' + self.__dummy_mode = dummy + + def get_dummy_mode(self): + """Return the current value of the dummy mode parameter. + """ + return self.__dummy_mode + + def set_banner(self,banner): + """Sets the global banner. + + This banner gets prepended to every header printed when the shell + instance is called.""" + + self.banner = banner + + def set_exit_msg(self,exit_msg): + """Sets the global exit_msg. + + This exit message gets printed upon exiting every time the embedded + shell is called. It is None by default. """ + + self.exit_msg = exit_msg + +#----------------------------------------------------------------------------- +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 <Enter> to continue.', + Term.cout.flush() + # Set global flag so that runsource can know that Ctrl-C was hit + KBINT = True + +class MTInteractiveShell(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. + + def __init__(self,name,usage=None,rc=Struct(opts=None,args=None), + user_ns = None, banner2='',**kw): + """Similar to the normal InteractiveShell, but with threading control""" + + IPython.iplib.InteractiveShell.__init__(self,name,usage,rc,user_ns,banner2) + + # Locking control variable + self.thread_ready = threading.Condition() + + # Stuff to do at closing time + self._kill = False + on_kill = kw.get('on_kill') + if on_kill is None: + 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 + + def runsource(self, source, filename="<input>", 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 + + 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 + + # Case 3 + # Store code in self, so the execution thread can handle it + self.thread_ready.acquire() + self.code_to_run_src = source + self.code_to_run = code + self.thread_ready.wait() # Wait until processed in timeout interval + self.thread_ready.release() + + return False + + def runcode(self): + """Execute a code object. + + Multithreaded wrapper around IPython's runcode().""" + + # lock thread-protected stuff + self.thread_ready.acquire() + + # Install sigint handler + try: + signal.signal(signal.SIGINT, sigint_handler) + except SystemError: + # This happens under Windows, which seems to have all sorts + # of problems with signal handling. Oh well... + pass + + if self._kill: + print >>Term.cout, 'Closing threads...', + Term.cout.flush() + for tokill in self.on_kill: + tokill() + print >>Term.cout, 'Done.' + + # Run pending code by calling parent class + if self.code_to_run is not None: + self.thread_ready.notify() + InteractiveShell.runcode(self,self.code_to_run) + + # We're done with thread-protected variables + self.thread_ready.release() + # 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.thread_ready.acquire() + self._kill = True + self.thread_ready.release() + +class MatplotlibShellBase: + """Mixin class to provide the necessary modifications to regular IPython + shell classes for matplotlib support. + + Given Python's MRO, this should be used as the FIRST class in the + inheritance hierarchy, so that it overrides the relevant methods.""" + + def _matplotlib_config(self,name): + """Return various items needed to setup the user's shell with matplotlib""" + + # Initialize matplotlib to interactive mode always + import matplotlib + from matplotlib import backends + matplotlib.interactive(True) + + def use(arg): + """IPython wrapper for matplotlib's backend switcher. + + In interactive use, we can not allow switching to a different + interactive backend, since thread conflicts will most likely crash + the python interpreter. This routine does a safety check first, + and refuses to perform a dangerous switch. It still allows + switching to non-interactive backends.""" + + if arg in backends.interactive_bk and arg != self.mpl_backend: + m=('invalid matplotlib backend switch.\n' + 'This script attempted to switch to the interactive ' + 'backend: `%s`\n' + 'Your current choice of interactive backend is: `%s`\n\n' + 'Switching interactive matplotlib backends at runtime\n' + 'would crash the python interpreter, ' + 'and IPython has blocked it.\n\n' + 'You need to either change your choice of matplotlib backend\n' + 'by editing your .matplotlibrc file, or run this script as a \n' + 'standalone file from the command line, not using IPython.\n' % + (arg,self.mpl_backend) ) + raise RuntimeError, m + else: + self.mpl_use(arg) + self.mpl_use._called = True + + self.matplotlib = matplotlib + + # Take control of matplotlib's error handling, which can normally + # lock up the python interpreter when raw_input() is called + import matplotlib.backends as backend + backend.error_msg = error + + # we'll handle the mainloop, tell show not to + import matplotlib.backends + matplotlib.backends.show._needmain = False + self.mpl_backend = matplotlib.rcParams['backend'] + + # we also need to block switching of interactive backends by use() + self.mpl_use = matplotlib.use + self.mpl_use._called = False + # overwrite the original matplotlib.use with our wrapper + matplotlib.use = use + + # We need to detect at runtime whether show() is called by the user. + # For this, we wrap it into a decorator which adds a 'called' flag. + backend.draw_if_interactive = flag_calls(backend.draw_if_interactive) + + # This must be imported last in the matplotlib series, after + # backend/interactivity choices have been made + try: + import matplotlib.pylab as pylab + self.pylab = pylab + self.pylab_name = 'pylab' + except ImportError: + import matplotlib.matlab as matlab + self.pylab = matlab + self.pylab_name = 'matlab' + + # Build a user namespace initialized with matplotlib/matlab features. + user_ns = {'__name__':'__main__', + '__builtins__' : __builtin__ } + + # Be careful not to remove the final \n in the code string below, or + # things will break badly with py22 (I think it's a python bug, 2.3 is + # OK). + pname = self.pylab_name # Python can't interpolate dotted var names + exec ("import matplotlib\n" + "import matplotlib.%(pname)s as %(pname)s\n" + "from matplotlib.%(pname)s import *\n" % locals()) in user_ns + + # Build matplotlib info banner + b=""" + Welcome to pylab, a matplotlib-based Python environment. + For more information, type 'help(pylab)'. +""" + return user_ns,b + + def mplot_exec(self,fname,*where,**kw): + """Execute a matplotlib script. + + This is a call to execfile(), but wrapped in safeties to properly + handle interactive rendering and backend switching.""" + + #print '*** Matplotlib runner ***' # dbg + # turn off rendering until end of script + isInteractive = self.matplotlib.rcParams['interactive'] + self.matplotlib.interactive(False) + self.safe_execfile(fname,*where,**kw) + self.matplotlib.interactive(isInteractive) + # make rendering call now, if the user tried to do it + if self.pylab.draw_if_interactive.called: + self.pylab.draw() + self.pylab.draw_if_interactive.called = False + + # if a backend switch was performed, reverse it now + if self.mpl_use._called: + self.matplotlib.rcParams['backend'] = self.mpl_backend + + def magic_run(self,parameter_s=''): + Magic.magic_run(self,parameter_s,runner=self.mplot_exec) + + # Fix the docstring so users see the original as well + magic_run.__doc__ = "%s\n%s" % (Magic.magic_run.__doc__, + "\n *** Modified %run for Matplotlib," + " with proper interactive handling ***") + +# Now we provide 2 versions of a matplotlib-aware IPython base shells, single +# and multithreaded. Note that these are meant for internal use, the IPShell* +# classes below are the ones meant for public consumption. + +class MatplotlibShell(MatplotlibShellBase,InteractiveShell): + """Single-threaded shell with matplotlib support.""" + + def __init__(self,name,usage=None,rc=Struct(opts=None,args=None), + user_ns = None, **kw): + user_ns,b2 = self._matplotlib_config(name) + InteractiveShell.__init__(self,name,usage,rc,user_ns,banner2=b2,**kw) + +class MatplotlibMTShell(MatplotlibShellBase,MTInteractiveShell): + """Multi-threaded shell with matplotlib support.""" + + def __init__(self,name,usage=None,rc=Struct(opts=None,args=None), + user_ns = None, **kw): + user_ns,b2 = self._matplotlib_config(name) + MTInteractiveShell.__init__(self,name,usage,rc,user_ns,banner2=b2,**kw) + +#----------------------------------------------------------------------------- +# Utility functions for the different GUI enabled IPShell* classes. + +def get_tk(): + """Tries to import Tkinter and returns a withdrawn Tkinter root + window. If Tkinter is already imported or not available, this + returns None. This function calls `hijack_tk` underneath. + """ + if not USE_TK or sys.modules.has_key('Tkinter'): + return None + else: + try: + import Tkinter + except ImportError: + return None + else: + hijack_tk() + r = Tkinter.Tk() + r.withdraw() + return r + +def hijack_tk(): + """Modifies Tkinter's mainloop with a dummy so when a module calls + mainloop, it does not block. + + """ + def misc_mainloop(self, n=0): + pass + def tkinter_mainloop(n=0): + pass + + import Tkinter + Tkinter.Misc.mainloop = misc_mainloop + Tkinter.mainloop = tkinter_mainloop + +def update_tk(tk): + """Updates the Tkinter event loop. This is typically called from + the respective WX or GTK mainloops. + """ + if tk: + tk.update() + +def hijack_wx(): + """Modifies wxPython's MainLoop with a dummy so user code does not + block IPython. The hijacked mainloop function is returned. + """ + def dummy_mainloop(*args, **kw): + pass + import wxPython + ver = wxPython.__version__ + orig_mainloop = None + if ver[:3] >= '2.5': + import wx + if hasattr(wx, '_core_'): core = getattr(wx, '_core_') + elif hasattr(wx, '_core'): core = getattr(wx, '_core') + else: raise AttributeError('Could not find wx core module') + orig_mainloop = core.PyApp_MainLoop + core.PyApp_MainLoop = dummy_mainloop + elif ver[:3] == '2.4': + orig_mainloop = wxPython.wxc.wxPyApp_MainLoop + wxPython.wxc.wxPyApp_MainLoop = dummy_mainloop + else: + warn("Unable to find either wxPython version 2.4 or >= 2.5.") + return orig_mainloop + +def hijack_gtk(): + """Modifies pyGTK's mainloop with a dummy so user code does not + block IPython. This function returns the original `gtk.mainloop` + function that has been hijacked. + + NOTE: Make sure you import this *AFTER* you call + pygtk.require(...). + """ + def dummy_mainloop(*args, **kw): + pass + import gtk + if gtk.pygtk_version >= (2,4,0): orig_mainloop = gtk.main + else: orig_mainloop = gtk.mainloop + gtk.mainloop = dummy_mainloop + gtk.main = dummy_mainloop + return orig_mainloop + +#----------------------------------------------------------------------------- +# The IPShell* classes below are the ones meant to be run by external code as +# IPython instances. Note that unless a specific threading strategy is +# desired, the factory function start() below should be used instead (it +# selects the proper threaded class). + +class IPShellGTK(threading.Thread): + """Run a gtk mainloop() in a separate thread. + + Python commands can be passed to the thread where they will be executed. + This is implemented by periodically checking for passed code using a + GTK timeout callback.""" + + TIMEOUT = 100 # Millisecond interval between timeouts. + + def __init__(self,argv=None,user_ns=None,debug=1, + shell_class=MTInteractiveShell): + + import pygtk + pygtk.require("2.0") + import gtk + + self.gtk = gtk + self.gtk_mainloop = hijack_gtk() + + # Allows us to use both Tk and GTK. + self.tk = get_tk() + + if gtk.pygtk_version >= (2,4,0): mainquit = self.gtk.main_quit + else: mainquit = self.gtk.mainquit + + 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.IP.kill() + + def mainloop(self): + + if self.gtk.pygtk_version >= (2,4,0): + import gobject + gobject.timeout_add(self.TIMEOUT, self.on_timer) + else: + self.gtk.timeout_add(self.TIMEOUT, self.on_timer) + + if sys.platform != 'win32': + try: + if self.gtk.gtk_version[0] >= 2: + self.gtk.threads_init() + except AttributeError: + pass + except RuntimeError: + error('Your pyGTK likely has not been compiled with ' + 'threading support.\n' + 'The exception printout is below.\n' + 'You can either rebuild pyGTK with threads, or ' + 'try using \n' + 'matplotlib with a different backend (like Tk or WX).\n' + 'Note that matplotlib will most likely not work in its ' + 'current state!') + self.IP.InteractiveTB() + self.start() + self.gtk.threads_enter() + self.gtk_mainloop() + self.gtk.threads_leave() + self.join() + + def on_timer(self): + update_tk(self.tk) + return self.IP.runcode() + + +class IPShellWX(threading.Thread): + """Run a wx mainloop() in a separate thread. + + Python commands can be passed to the thread where they will be executed. + This is implemented by periodically checking for passed code using a + GTK timeout callback.""" + + TIMEOUT = 100 # Millisecond interval between timeouts. + + def __init__(self,argv=None,user_ns=None,debug=1, + shell_class=MTInteractiveShell): + + import wxPython.wx as wx + + threading.Thread.__init__(self) + self.wx = wx + self.wx_mainloop = hijack_wx() + + # Allows us to use both Tk and GTK. + self.tk = get_tk() + + self.IP = make_IPython(argv,user_ns=user_ns,debug=debug, + shell_class=shell_class, + on_kill=[self.wxexit]) + self.app = None + + def wxexit(self, *args): + if self.app is not None: + self.app.agent.timer.Stop() + self.app.ExitMainLoop() + + def run(self): + self.IP.mainloop() + self.IP.kill() + + def mainloop(self): + + self.start() + + class TimerAgent(self.wx.wxMiniFrame): + wx = self.wx + IP = self.IP + tk = self.tk + def __init__(self, parent, interval): + style = self.wx.wxDEFAULT_FRAME_STYLE | self.wx.wxTINY_CAPTION_HORIZ + self.wx.wxMiniFrame.__init__(self, parent, -1, ' ', pos=(200, 200), + size=(100, 100),style=style) + self.Show(False) + self.interval = interval + self.timerId = self.wx.wxNewId() + + def StartWork(self): + self.timer = self.wx.wxTimer(self, self.timerId) + self.wx.EVT_TIMER(self, self.timerId, self.OnTimer) + self.timer.Start(self.interval) + + def OnTimer(self, event): + update_tk(self.tk) + self.IP.runcode() + + class App(self.wx.wxApp): + wx = self.wx + TIMEOUT = self.TIMEOUT + def OnInit(self): + 'Create the main window and insert the custom frame' + self.agent = TimerAgent(None, self.TIMEOUT) + self.agent.Show(self.wx.false) + self.agent.StartWork() + return self.wx.true + + self.app = App(redirect=False) + self.wx_mainloop(self.app) + self.join() + + +class IPShellQt(threading.Thread): + """Run a Qt event loop in a separate thread. + + Python commands can be passed to the thread where they will be executed. + This is implemented by periodically checking for passed code using a + Qt timer / slot.""" + + TIMEOUT = 100 # Millisecond interval between timeouts. + + def __init__(self,argv=None,user_ns=None,debug=0, + shell_class=MTInteractiveShell): + + import qt + + class newQApplication: + def __init__( self ): + self.QApplication = qt.QApplication + + def __call__( *args, **kwargs ): + return qt.qApp + + def exec_loop( *args, **kwargs ): + pass + + def __getattr__( self, name ): + return getattr( self.QApplication, name ) + + qt.QApplication = newQApplication() + + # Allows us to use both Tk and QT. + self.tk = get_tk() + + self.IP = make_IPython(argv,user_ns=user_ns,debug=debug, + shell_class=shell_class, + on_kill=[qt.qApp.exit]) + + threading.Thread.__init__(self) + + def run(self): + #sys.excepthook = self.IP.excepthook # dbg + self.IP.mainloop() + self.IP.kill() + + def mainloop(self): + import qt, sys + if qt.QApplication.startingUp(): + a = qt.QApplication.QApplication( sys.argv ) + self.timer = qt.QTimer() + qt.QObject.connect( self.timer, qt.SIGNAL( 'timeout()' ), self.on_timer ) + + self.start() + self.timer.start( self.TIMEOUT, True ) + while True: + if self.IP._kill: break + qt.qApp.exec_loop() + self.join() + + def on_timer(self): + update_tk(self.tk) + result = self.IP.runcode() + self.timer.start( self.TIMEOUT, True ) + return result + +# A set of matplotlib public IPython shell classes, for single-threaded +# (Tk* and FLTK* backends) and multithreaded (GTK* and WX* backends) use. +class IPShellMatplotlib(IPShell): + """Subclass IPShell with MatplotlibShell as the internal shell. + + Single-threaded class, meant for the Tk* and FLTK* backends. + + Having this on a separate class simplifies the external driver code.""" + + def __init__(self,argv=None,user_ns=None,debug=1): + IPShell.__init__(self,argv,user_ns,debug,shell_class=MatplotlibShell) + +class IPShellMatplotlibGTK(IPShellGTK): + """Subclass IPShellGTK with MatplotlibMTShell as the internal shell. + + Multi-threaded class, meant for the GTK* backends.""" + + def __init__(self,argv=None,user_ns=None,debug=1): + IPShellGTK.__init__(self,argv,user_ns,debug,shell_class=MatplotlibMTShell) + +class IPShellMatplotlibWX(IPShellWX): + """Subclass IPShellWX with MatplotlibMTShell as the internal shell. + + Multi-threaded class, meant for the WX* backends.""" + + def __init__(self,argv=None,user_ns=None,debug=1): + IPShellWX.__init__(self,argv,user_ns,debug,shell_class=MatplotlibMTShell) + +class IPShellMatplotlibQt(IPShellQt): + """Subclass IPShellQt with MatplotlibMTShell as the internal shell. + + Multi-threaded class, meant for the Qt* backends.""" + + def __init__(self,argv=None,user_ns=None,debug=1): + IPShellQt.__init__(self,argv,user_ns,debug,shell_class=MatplotlibMTShell) + +#----------------------------------------------------------------------------- +# Factory functions to actually start the proper thread-aware shell + +def _matplotlib_shell_class(): + """Factory function to handle shell class selection for matplotlib. + + The proper shell class to use depends on the matplotlib backend, since + each backend requires a different threading strategy.""" + + try: + import matplotlib + except ImportError: + error('matplotlib could NOT be imported! Starting normal IPython.') + sh_class = IPShell + else: + backend = matplotlib.rcParams['backend'] + if backend.startswith('GTK'): + sh_class = IPShellMatplotlibGTK + elif backend.startswith('WX'): + sh_class = IPShellMatplotlibWX + elif backend.startswith('Qt'): + sh_class = IPShellMatplotlibQt + else: + sh_class = IPShellMatplotlib + #print 'Using %s with the %s backend.' % (sh_class,backend) # dbg + return sh_class + +# This is the one which should be called by external code. +def start(): + """Return a running shell instance, dealing with threading options. + + This is a factory function which will instantiate the proper IPython shell + based on the user's threading choice. Such a selector is needed because + different GUI toolkits require different thread handling details.""" + + global USE_TK + # Crude sys.argv hack to extract the threading options. + if len(sys.argv) > 1: + if len(sys.argv) > 2: + arg2 = sys.argv[2] + if arg2.endswith('-tk'): + USE_TK = True + arg1 = sys.argv[1] + if arg1.endswith('-gthread'): + shell = IPShellGTK + elif arg1.endswith( '-qthread' ): + shell = IPShellQt + elif arg1.endswith('-wthread'): + shell = IPShellWX + elif arg1.endswith('-pylab'): + shell = _matplotlib_shell_class() + else: + shell = IPShell + else: + shell = IPShell + return shell() + +# Some aliases for backwards compatibility +IPythonShell = IPShell +IPythonShellEmbed = IPShellEmbed +#************************ End of file <Shell.py> *************************** diff --git a/IPython/Struct.py b/IPython/Struct.py new file mode 100644 index 0000000..da316f9 --- /dev/null +++ b/IPython/Struct.py @@ -0,0 +1,376 @@ +# -*- coding: utf-8 -*- +"""Mimic C structs with lots of extra functionality. + +$Id: Struct.py 410 2004-11-04 07:58:17Z fperez $""" + +#***************************************************************************** +# Copyright (C) 2001-2004 Fernando Perez <fperez@colorado.edu> +# +# Distributed under the terms of the BSD License. The full license is in +# the file COPYING, distributed as part of this software. +#***************************************************************************** + +from IPython import Release +__author__ = '%s <%s>' % Release.authors['Fernando'] +__license__ = Release.license + +__all__ = ['Struct'] + +import types +from IPython.genutils import list2dict2 + +class Struct: + """Class to mimic C structs but also provide convenient dictionary-like + functionality. + + Instances can be initialized with a dictionary, a list of key=value pairs + or both. If both are present, the dictionary must come first. + + Because Python classes provide direct assignment to their members, it's + easy to overwrite normal methods (S.copy = 1 would destroy access to + S.copy()). For this reason, all builtin method names are protected and + can't be assigned to. An attempt to do s.copy=1 or s['copy']=1 will raise + a KeyError exception. If you really want to, you can bypass this + protection by directly assigning to __dict__: s.__dict__['copy']=1 will + still work. Doing this will break functionality, though. As in most of + Python, namespace protection is weakly enforced, so feel free to shoot + yourself if you really want to. + + Note that this class uses more memory and is *much* slower than a regular + dictionary, so be careful in situations where memory or performance are + critical. But for day to day use it should behave fine. It is particularly + convenient for storing configuration data in programs. + + +,+=,- and -= are implemented. +/+= do merges (non-destructive updates), + -/-= remove keys from the original. See the method descripitions. + + This class allows a quick access syntax: both s.key and s['key'] are + valid. This syntax has a limitation: each 'key' has to be explicitly + accessed by its original name. The normal s.key syntax doesn't provide + access to the keys via variables whose values evaluate to the desired + keys. An example should clarify this: + + Define a dictionary and initialize both with dict and k=v pairs: + >>> d={'a':1,'b':2} + >>> s=Struct(d,hi=10,ho=20) + The return of __repr__ can be used to create a new instance: + >>> s + Struct({'ho': 20, 'b': 2, 'hi': 10, 'a': 1}) + __str__ (called by print) shows it's not quite a regular dictionary: + >>> print s + Struct {a: 1, b: 2, hi: 10, ho: 20} + Access by explicitly named key with dot notation: + >>> s.a + 1 + Or like a dictionary: + >>> s['a'] + 1 + If you want a variable to hold the key value, only dictionary access works: + >>> key='hi' + >>> s.key + Traceback (most recent call last): + File "<stdin>", line 1, in ? + AttributeError: Struct instance has no attribute 'key' + >>> s[key] + 10 + + Another limitation of the s.key syntax (and Struct(key=val) + initialization): keys can't be numbers. But numeric keys can be used and + accessed using the dictionary syntax. Again, an example: + + This doesn't work: + >>> s=Struct(4='hi') + SyntaxError: keyword can't be an expression + But this does: + >>> s=Struct() + >>> s[4]='hi' + >>> s + Struct({4: 'hi'}) + >>> s[4] + 'hi' + """ + + # Attributes to which __setitem__ and __setattr__ will block access. + # Note: much of this will be moot in Python 2.2 and will be done in a much + # cleaner way. + __protected = ('copy dict dictcopy get has_attr has_key items keys ' + 'merge popitem setdefault update values ' + '__make_dict __dict_invert ').split() + + def __init__(self,dict=None,**kw): + """Initialize with a dictionary, another Struct, or by giving + explicitly the list of attributes. + + Both can be used, but the dictionary must come first: + Struct(dict), Struct(k1=v1,k2=v2) or Struct(dict,k1=v1,k2=v2). + """ + if dict is None: + dict = {} + if isinstance(dict,Struct): + dict = dict.dict() + elif dict and type(dict) is not types.DictType: + raise TypeError,\ + 'Initialize with a dictionary or key=val pairs.' + dict.update(kw) + # do the updating by hand to guarantee that we go through the + # safety-checked __setitem__ + for k,v in dict.items(): + self[k] = v + + def __setitem__(self,key,value): + """Used when struct[key] = val calls are made.""" + if key in Struct.__protected: + raise KeyError,'Key '+`key`+' is a protected key of class Struct.' + self.__dict__[key] = value + + def __setattr__(self, key, value): + """Used when struct.key = val calls are made.""" + self.__setitem__(key,value) + + def __str__(self): + """Gets called by print.""" + + return 'Struct('+str(self.__dict__)+')' + + def __repr__(self): + """Gets called by repr. + + A Struct can be recreated with S_new=eval(repr(S_old)).""" + return 'Struct('+str(self.__dict__)+')' + + def __getitem__(self,key): + """Allows struct[key] access.""" + return self.__dict__[key] + + def __contains__(self,key): + """Allows use of the 'in' operator.""" + return self.__dict__.has_key(key) + + def __iadd__(self,other): + """S += S2 is a shorthand for S.merge(S2).""" + self.merge(other) + return self + + def __add__(self,other): + """S + S2 -> New Struct made form S and S.merge(S2)""" + Sout = self.copy() + Sout.merge(other) + return Sout + + def __sub__(self,other): + """Return S1-S2, where all keys in S2 have been deleted (if present) + from S1.""" + Sout = self.copy() + Sout -= other + return Sout + + def __isub__(self,other): + """Do in place S = S - S2, meaning all keys in S2 have been deleted + (if present) from S1.""" + + for k in other.keys(): + if self.has_key(k): + del self.__dict__[k] + + def __make_dict(self,__loc_data__,**kw): + "Helper function for update and merge. Return a dict from data." + + if __loc_data__ == None: + dict = {} + elif type(__loc_data__) is types.DictType: + dict = __loc_data__ + elif isinstance(__loc_data__,Struct): + dict = __loc_data__.__dict__ + else: + raise TypeError, 'Update with a dict, a Struct or key=val pairs.' + if kw: + dict.update(kw) + return dict + + def __dict_invert(self,dict): + """Helper function for merge. Takes a dictionary whose values are + lists and returns a dict. with the elements of each list as keys and + the original keys as values.""" + + outdict = {} + for k,lst in dict.items(): + if type(lst) is types.StringType: + lst = lst.split() + for entry in lst: + outdict[entry] = k + return outdict + + def clear(self): + """Clear all attributes.""" + self.__dict__.clear() + + def copy(self): + """Return a (shallow) copy of a Struct.""" + return Struct(self.__dict__.copy()) + + def dict(self): + """Return the Struct's dictionary.""" + return self.__dict__ + + def dictcopy(self): + """Return a (shallow) copy of the Struct's dictionary.""" + return self.__dict__.copy() + + def popitem(self): + """S.popitem() -> (k, v), remove and return some (key, value) pair as + a 2-tuple; but raise KeyError if S is empty.""" + return self.__dict__.popitem() + + def update(self,__loc_data__=None,**kw): + """Update (merge) with data from another Struct or from a dictionary. + Optionally, one or more key=value pairs can be given at the end for + direct update.""" + + # The funny name __loc_data__ is to prevent a common variable name which + # could be a fieled of a Struct to collide with this parameter. The problem + # would arise if the function is called with a keyword with this same name + # that a user means to add as a Struct field. + newdict = Struct.__make_dict(self,__loc_data__,**kw) + for k,v in newdict.items(): + self[k] = v + + def merge(self,__loc_data__=None,__conflict_solve=None,**kw): + """S.merge(data,conflict,k=v1,k=v2,...) -> merge data and k=v into S. + + This is similar to update(), but much more flexible. First, a dict is + made from data+key=value pairs. When merging this dict with the Struct + S, the optional dictionary 'conflict' is used to decide what to do. + + If conflict is not given, the default behavior is to preserve any keys + with their current value (the opposite of the update method's + behavior). + + conflict is a dictionary of binary functions which will be used to + solve key conflicts. It must have the following structure: + + conflict == { fn1 : [Skey1,Skey2,...], fn2 : [Skey3], etc } + + Values must be lists or whitespace separated strings which are + automatically converted to lists of strings by calling string.split(). + + Each key of conflict is a function which defines a policy for + resolving conflicts when merging with the input data. Each fn must be + a binary function which returns the desired outcome for a key + conflict. These functions will be called as fn(old,new). + + An example is probably in order. Suppose you are merging the struct S + with a dict D and the following conflict policy dict: + + S.merge(D,{fn1:['a','b',4], fn2:'key_c key_d'}) + + If the key 'a' is found in both S and D, the merge method will call: + + S['a'] = fn1(S['a'],D['a']) + + As a convenience, merge() provides five (the most commonly needed) + pre-defined policies: preserve, update, add, add_flip and add_s. The + easiest explanation is their implementation: + + preserve = lambda old,new: old + update = lambda old,new: new + add = lambda old,new: old + new + add_flip = lambda old,new: new + old # note change of order! + add_s = lambda old,new: old + ' ' + new # only works for strings! + + You can use those four words (as strings) as keys in conflict instead + of defining them as functions, and the merge method will substitute + the appropriate functions for you. That is, the call + + S.merge(D,{'preserve':'a b c','add':[4,5,'d'],my_function:[6]}) + + will automatically substitute the functions preserve and add for the + names 'preserve' and 'add' before making any function calls. + + For more complicated conflict resolution policies, you still need to + construct your own functions. """ + + data_dict = Struct.__make_dict(self,__loc_data__,**kw) + + # policies for conflict resolution: two argument functions which return + # the value that will go in the new struct + preserve = lambda old,new: old + update = lambda old,new: new + add = lambda old,new: old + new + add_flip = lambda old,new: new + old # note change of order! + add_s = lambda old,new: old + ' ' + new + + # default policy is to keep current keys when there's a conflict + conflict_solve = list2dict2(self.keys(),default = preserve) + + # the conflict_solve dictionary is given by the user 'inverted': we + # need a name-function mapping, it comes as a function -> names + # dict. Make a local copy (b/c we'll make changes), replace user + # strings for the three builtin policies and invert it. + if __conflict_solve: + inv_conflict_solve_user = __conflict_solve.copy() + for name, func in [('preserve',preserve), ('update',update), + ('add',add), ('add_flip',add_flip), ('add_s',add_s)]: + if name in inv_conflict_solve_user.keys(): + inv_conflict_solve_user[func] = inv_conflict_solve_user[name] + del inv_conflict_solve_user[name] + conflict_solve.update(Struct.__dict_invert(self,inv_conflict_solve_user)) + #print 'merge. conflict_solve: '; pprint(conflict_solve) # dbg + # after Python 2.2, use iterators: for key in data_dict will then work + #print '*'*50,'in merger. conflict_solver:'; pprint(conflict_solve) + for key in data_dict.keys(): + if key not in self: + self[key] = data_dict[key] + else: + self[key] = conflict_solve[key](self[key],data_dict[key]) + + def has_key(self,key): + """Like has_key() dictionary method.""" + return self.__dict__.has_key(key) + + def hasattr(self,key): + """hasattr function available as a method. + + Implemented like has_key, to make sure that all available keys in the + internal dictionary of the Struct appear also as attributes (even + numeric keys).""" + return self.__dict__.has_key(key) + + def items(self): + """Return the items in the Struct's dictionary, in the same format + as a call to {}.items().""" + return self.__dict__.items() + + def keys(self): + """Return the keys in the Struct's dictionary, in the same format + as a call to {}.keys().""" + return self.__dict__.keys() + + def values(self,keys=None): + """Return the values in the Struct's dictionary, in the same format + as a call to {}.values(). + + Can be called with an optional argument keys, which must be a list or + tuple of keys. In this case it returns only the values corresponding + to those keys (allowing a form of 'slicing' for Structs).""" + if not keys: + return self.__dict__.values() + else: + ret=[] + for k in keys: + ret.append(self[k]) + return ret + + def get(self,attr,val=None): + """S.get(k[,d]) -> S[k] if S.has_key(k), else d. d defaults to None.""" + try: + return self[attr] + except KeyError: + return val + + def setdefault(self,attr,val=None): + """S.setdefault(k[,d]) -> S.get(k,d), also set S[k]=d if not S.has_key(k)""" + if not self.has_key(attr): + self[attr] = val + return self.get(attr,val) +# end class Struct + diff --git a/IPython/UserConfig/ipythonrc b/IPython/UserConfig/ipythonrc new file mode 100644 index 0000000..4062050 --- /dev/null +++ b/IPython/UserConfig/ipythonrc @@ -0,0 +1,546 @@ +# -*- Mode: Shell-Script -*- Not really, but shows comments correctly +# $Id: ipythonrc 596 2005-06-01 17:01:13Z fperez $ + +#*************************************************************************** +# +# Configuration file for IPython -- ipythonrc format +# +# The format of this file is simply one of 'key value' lines. +# Lines containing only whitespace at the beginning and then a # are ignored +# as comments. But comments can NOT be put on lines with data. + +# The meaning and use of each key are explained below. + +#--------------------------------------------------------------------------- +# Section: included files + +# Put one or more *config* files (with the syntax of this file) you want to +# include. For keys with a unique value the outermost file has precedence. For +# keys with multiple values, they all get assembled into a list which then +# gets loaded by IPython. + +# In this file, all lists of things should simply be space-separated. + +# This allows you to build hierarchies of files which recursively load +# lower-level services. If this is your main ~/.ipython/ipythonrc file, you +# should only keep here basic things you always want available. Then you can +# include it in every other special-purpose config file you create. +include + +#--------------------------------------------------------------------------- +# Section: startup setup + +# These are mostly things which parallel a command line option of the same +# name. + +# Keys in this section should only appear once. If any key from this section +# is encountered more than once, the last value remains, all earlier ones get +# discarded. + +# Automatic calling of callable objects. If set to true, callable objects are +# automatically called when invoked at the command line, even if you don't +# type parentheses. IPython adds the parentheses for you. For example: + +#In [1]: str 45 +#------> str(45) +#Out[1]: '45' + +# IPython reprints your line with '---->' indicating that it added +# parentheses. While this option is very convenient for interactive use, it +# may occasionally cause problems with objects which have side-effects if +# called unexpectedly. Set it to 0 if you want to disable it. + +# Note that even with autocall off, you can still use '/' at the start of a +# line to treat the first argument on the command line as a function and add +# parentheses to it: + +#In [8]: /str 43 +#------> str(43) +#Out[8]: '43' + +autocall 1 + +# Auto-indent. IPython can recognize lines ending in ':' and indent the next +# line, while also un-indenting automatically after 'raise' or 'return'. + +# This feature uses the readline library, so it will honor your ~/.inputrc +# configuration (or whatever file your INPUTRC variable points to). Adding +# the following lines to your .inputrc file can make indent/unindenting more +# convenient (M-i indents, M-u unindents): + +# $if Python +# "\M-i": " " +# "\M-u": "\d\d\d\d" +# $endif + +# The feature is potentially a bit dangerous, because it can cause problems +# with pasting of indented code (the pasted code gets re-indented on each +# line). But it's a huge time-saver when working interactively. The magic +# function @autoindent allows you to toggle it on/off at runtime. + +autoindent 1 + +# Auto-magic. This gives you access to all the magic functions without having +# to prepend them with an @ sign. If you define a variable with the same name +# as a magic function (say who=1), you will need to access the magic function +# with @ (@who in this example). However, if later you delete your variable +# (del who), you'll recover the automagic calling form. + +# Considering that many magic functions provide a lot of shell-like +# functionality, automagic gives you something close to a full Python+system +# shell environment (and you can extend it further if you want). + +automagic 1 + +# Size of the output cache. After this many entries are stored, the cache will +# get flushed. Depending on the size of your intermediate calculations, you +# may have memory problems if you make it too big, since keeping things in the +# cache prevents Python from reclaiming the memory for old results. Experiment +# with a value that works well for you. + +# If you choose cache_size 0 IPython will revert to python's regular >>> +# unnumbered prompt. You will still have _, __ and ___ for your last three +# results, but that will be it. No dynamic _1, _2, etc. will be created. If +# you are running on a slow machine or with very limited memory, this may +# help. + +cache_size 1000 + +# Classic mode: Setting 'classic 1' you lose many of IPython niceties, +# but that's your choice! Classic 1 -> same as IPython -classic. +# Note that this is _not_ the normal python interpreter, it's simply +# IPython emulating most of the classic interpreter's behavior. +classic 0 + +# colors - Coloring option for prompts and traceback printouts. + +# Currently available schemes: NoColor, Linux, LightBG. + +# This option allows coloring the prompts and traceback printouts. This +# requires a terminal which can properly handle color escape sequences. If you +# are having problems with this, use the NoColor scheme (uses no color escapes +# at all). + +# The Linux option works well in linux console type environments: dark +# background with light fonts. + +# LightBG is similar to Linux but swaps dark/light colors to be more readable +# in light background terminals. + +# keep uncommented only the one you want: +colors Linux +#colors LightBG +#colors NoColor + +######################## +# Note to Windows users +# +# Color and readline support is avaialble to Windows users via Gary Bishop's +# readline library. You can find Gary's tools at +# http://sourceforge.net/projects/uncpythontools. +# Note that his readline module requires in turn the ctypes library, available +# at http://starship.python.net/crew/theller/ctypes. +######################## + +# color_info: 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. This information is passed through a +# pager (it defaults to 'less' if $PAGER is not set). + +# If your pager has problems, try to setting it to properly handle escapes +# (see the less manpage for detail), or disable this option. The magic +# function @color_info allows you to toggle this interactively for testing. + +color_info 1 + +# confirm_exit: set to 1 if you want IPython to confirm when you try to exit +# with an EOF (Control-d in Unix, Control-Z/Enter in Windows). Note that using +# the magic functions @Exit or @Quit you can force a direct exit, bypassing +# any confirmation. + +confirm_exit 1 + +# Use deep_reload() as a substitute for reload() by default. deep_reload() is +# still available as dreload() and appears as a builtin. + +deep_reload 0 + +# Which editor to use with the @edit command. If you leave this at 0, IPython +# will honor your EDITOR environment variable. 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. + +# For Emacs users, setting up your Emacs server properly as described in the +# manual is a good idea. An alternative is to use jed, a very light editor +# with much of the feel of Emacs (though not as powerful for heavy-duty work). + +editor 0 + +# log 1 -> same as ipython -log. This automatically logs to ./ipython.log +log 0 + +# Same as ipython -Logfile YourLogfileName. +# Don't use with log 1 (use one or the other) +logfile '' + +# banner 0 -> same as ipython -nobanner +banner 1 + +# messages 0 -> same as ipython -nomessages +messages 1 + +# 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. +pdb 0 + +# Enable the pprint module for printing. pprint tends to give a more readable +# display (than print) for complex nested data structures. +pprint 1 + +# Prompt strings + +# Most bash-like escapes can be used to customize IPython's prompts, as well as +# a few additional ones which are IPython-specific. All valid prompt escapes +# are described in detail in the Customization section of the IPython HTML/PDF +# manual. + +# Use \# to represent the current prompt number, and quote them to protect +# spaces. +prompt_in1 'In [\#]: ' + +# \D is replaced by as many dots as there are digits in the +# current value of \#. +prompt_in2 ' .\D.: ' + +prompt_out 'Out[\#]: ' + +# Select whether to left-pad the output prompts to match the length of the +# input ones. This allows you for example to use a simple '>' as an output +# prompt, and yet have the output line up with the input. If set to false, +# the output prompts will be unpadded (flush left). +prompts_pad_left 1 + +# quick 1 -> same as ipython -quick +quick 0 + +# Use the readline library (1) or not (0). Most users will want this on, but +# if you experience strange problems with line management (mainly when using +# IPython inside Emacs buffers) you may try disabling it. Not having it on +# prevents you from getting command history with the arrow keys, searching and +# name completion using TAB. + +readline 1 + +# Screen Length: 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 paged with the less command instead of directly printed. + +# The default value for this is 0, which means IPython will auto-detect your +# screen size every time it needs to print. If for some reason this isn't +# working well (it needs curses support), specify it yourself. Otherwise don't +# change the default. + +screen_length 0 + +# Prompt separators for input and output. +# Use \n for newline explicitly, without quotes. +# Use 0 (like at the cmd line) to turn off a given separator. + +# The structure of prompt printing is: +# (SeparateIn)Input.... +# (SeparateOut)Output... +# (SeparateOut2), # that is, no newline is printed after Out2 +# By choosing these you can organize your output any way you want. + +separate_in \n +separate_out 0 +separate_out2 0 + +# 'nosep 1' is a shorthand for '-SeparateIn 0 -SeparateOut 0 -SeparateOut2 0'. +# Simply removes all input/output separators, overriding the choices above. +nosep 0 + +# xmode - Exception reporting mode. + +# Valid modes: Plain, Context and Verbose. + +# Plain: similar to python's normal traceback printing. + +# Context: prints 5 lines of context source code around each line in the +# traceback. + +# 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). + +#xmode Plain +xmode Context +#xmode Verbose + +# multi_line_specials: if true, allow magics, aliases and shell escapes (via +# !cmd) to be used in multi-line input (like for loops). For example, if you +# have this active, the following is valid in IPython: +# +#In [17]: for i in range(3): +# ....: mkdir $i +# ....: !touch $i/hello +# ....: ls -l $i + +multi_line_specials 1 + +#--------------------------------------------------------------------------- +# Section: Readline configuration (readline is not available for MS-Windows) + +# This is done via the following options: + +# (i) readline_parse_and_bind: this option can appear as many times as you +# want, each time defining a string to be executed via a +# readline.parse_and_bind() command. The syntax for valid commands of this +# kind can be found by reading the documentation for the GNU readline library, +# as these commands are of the kind which readline accepts in its +# configuration file. + +# The TAB key can be used to complete names at the command line in one of two +# ways: 'complete' and 'menu-complete'. The difference is that 'complete' only +# completes as much as possible while 'menu-complete' cycles through all +# possible completions. Leave the one you prefer uncommented. + +readline_parse_and_bind tab: complete +#readline_parse_and_bind tab: menu-complete + +# This binds Control-l to printing the list of all possible completions when +# there is more than one (what 'complete' does when hitting TAB twice, or at +# the first TAB if show-all-if-ambiguous is on) +readline_parse_and_bind "\C-l": possible-completions + +# This forces readline to automatically print the above list when tab +# completion is set to 'complete'. You can still get this list manually by +# using the key bound to 'possible-completions' (Control-l by default) or by +# hitting TAB twice. Turning this on makes the printing happen at the first +# TAB. +readline_parse_and_bind set show-all-if-ambiguous on + +# If you have TAB set to complete names, you can rebind any key (Control-o by +# default) to insert a true TAB character. +readline_parse_and_bind "\C-o": tab-insert + +# These commands allow you to indent/unindent easily, with the 4-space +# convention of the Python coding standards. Since IPython's internal +# auto-indent system also uses 4 spaces, you should not change the number of +# spaces in the code below. +readline_parse_and_bind "\M-i": " " +readline_parse_and_bind "\M-o": "\d\d\d\d" +readline_parse_and_bind "\M-I": "\d\d\d\d" + +# Bindings for incremental searches in the history. These searches use the +# string typed so far on the command line and search anything in the previous +# input history containing them. +readline_parse_and_bind "\C-r": reverse-search-history +readline_parse_and_bind "\C-s": forward-search-history + +# Bindings for completing the current line in the history of previous +# commands. This allows you to recall any previous command by typing its first +# few letters and hitting Control-p, bypassing all intermediate commands which +# may be in the history (much faster than hitting up-arrow 50 times!) +readline_parse_and_bind "\C-p": history-search-backward +readline_parse_and_bind "\C-n": history-search-forward + +# I also like to have the same functionality on the plain arrow keys. If you'd +# rather have the arrows use all the history (and not just match what you've +# typed so far), comment out or delete the next two lines. +readline_parse_and_bind "\e[A": history-search-backward +readline_parse_and_bind "\e[B": history-search-forward + +# (ii) readline_remove_delims: a string of characters to be removed from the +# default word-delimiters list used by readline, so that completions may be +# performed on strings which contain them. + +readline_remove_delims -/~ + +# (iii) readline_merge_completions: whether to merge the result of all +# possible completions or not. If true, IPython will complete filenames, +# python names and aliases and return all possible completions. If you set it +# to false, each completer is used at a time, and only if it doesn't return +# any completions is the next one used. + +# The default order is: [python_matches, file_matches, alias_matches] + +readline_merge_completions 1 + +# (iv) readline_omit__names: normally hitting <tab> after a '.' in a name +# will complete all attributes of an object, including all the special methods +# whose names start with single or double underscores (like __getitem__ or +# __class__). + +# This variable allows you to control this completion behavior: + +# readline_omit__names 1 -> completion will omit showing any names starting +# with two __, but it will still show names starting with one _. + +# readline_omit__names 2 -> completion will omit all names beginning with one +# _ (which obviously means filtering out the double __ ones). + +# Even when this option is set, you can still see those names by explicitly +# typing a _ after the period and hitting <tab>: 'name._<tab>' will always +# complete attribute names starting with '_'. + +# This option is off by default so that new users see all attributes of any +# objects they are dealing with. + +readline_omit__names 0 + +#--------------------------------------------------------------------------- +# Section: modules to be loaded with 'import ...' + +# List, separated by spaces, the names of the modules you want to import + +# Example: +# import_mod sys os +# will produce internally the statements +# import sys +# import os + +# Each import is executed in its own try/except block, so if one module +# fails to load the others will still be ok. + +import_mod + +#--------------------------------------------------------------------------- +# Section: modules to import some functions from: 'from ... import ...' + +# List, one per line, the modules for which you want only to import some +# functions. Give the module name first and then the name of functions to be +# imported from that module. + +# Example: + +# import_some IPython.genutils timing timings +# will produce internally the statement +# from IPython.genutils import timing, timings + +# timing() and timings() are two IPython utilities for timing the execution of +# your own functions, which you may find useful. Just commment out the above +# line if you want to test them. + +# If you have more than one modules_some line, each gets its own try/except +# block (like modules, see above). + +import_some + +#--------------------------------------------------------------------------- +# Section: modules to import all from : 'from ... import *' + +# List (same syntax as import_mod above) those modules for which you want to +# import all functions. Remember, this is a potentially dangerous thing to do, +# since it is very easy to overwrite names of things you need. Use with +# caution. + +# Example: +# import_all sys os +# will produce internally the statements +# from sys import * +# from os import * + +# As before, each will be called in a separate try/except block. + +import_all + +#--------------------------------------------------------------------------- +# Section: Python code to execute. + +# Put here code to be explicitly executed (keep it simple!) +# Put one line of python code per line. All whitespace is removed (this is a +# feature, not a bug), so don't get fancy building loops here. +# This is just for quick convenient creation of things you want available. + +# Example: +# execute x = 1 +# execute print 'hello world'; y = z = 'a' +# will produce internally +# x = 1 +# print 'hello world'; y = z = 'a' +# and each *line* (not each statement, we don't do python syntax parsing) is +# executed in its own try/except block. + +execute + +# Note for the adventurous: you can use this to define your own names for the +# magic functions, by playing some namespace tricks: + +# execute __IPYTHON__.magic_pf = __IPYTHON__.magic_profile + +# defines @pf as a new name for @profile. + +#--------------------------------------------------------------------------- +# Section: Pyhton files to load and execute. + +# Put here the full names of files you want executed with execfile(file). If +# you want complicated initialization, just write whatever you want in a +# regular python file and load it from here. + +# Filenames defined here (which *must* include the extension) are searched for +# through all of sys.path. Since IPython adds your .ipython directory to +# sys.path, they can also be placed in your .ipython dir and will be +# found. Otherwise (if you want to execute things not in .ipyton nor in +# sys.path) give a full path (you can use ~, it gets expanded) + +# Example: +# execfile file1.py ~/file2.py +# will generate +# execfile('file1.py') +# execfile('_path_to_your_home/file2.py') + +# As before, each file gets its own try/except block. + +execfile + +# If you are feeling adventurous, you can even add functionality to IPython +# through here. IPython works through a global variable called __ip which +# exists at the time when these files are read. If you know what you are doing +# (read the source) you can add functions to __ip in files loaded here. + +# The file example-magic.py contains a simple but correct example. Try it: + +# execfile example-magic.py + +# Look at the examples in IPython/iplib.py for more details on how these magic +# functions need to process their arguments. + +#--------------------------------------------------------------------------- +# Section: aliases for system shell commands + +# Here you can define your own names for system commands. The syntax is +# similar to that of the builtin @alias function: + +# alias alias_name command_string + +# The resulting aliases are auto-generated magic functions (hence usable as +# @alias_name) + +# For example: + +# alias myls ls -la + +# will define 'myls' as an alias for executing the system command 'ls -la'. +# This allows you to customize IPython's environment to have the same aliases +# you are accustomed to from your own shell. + +# You can also define aliases with parameters using %s specifiers (one per +# parameter): + +# alias parts echo first %s second %s + +# will give you in IPython: +# >>> @parts A B +# first A second B + +# Use one 'alias' statement per alias you wish to define. + +# alias + +#************************* end of file <ipythonrc> ************************ diff --git a/IPython/UserConfig/ipythonrc-math b/IPython/UserConfig/ipythonrc-math new file mode 100644 index 0000000..c32bcd1 --- /dev/null +++ b/IPython/UserConfig/ipythonrc-math @@ -0,0 +1,36 @@ +# -*- Mode: Shell-Script -*- Not really, but shows comments correctly +#*************************************************************************** +# +# Configuration file for ipython -- ipythonrc format +# +# The format of this file is one of 'key value' lines. +# Lines containing only whitespace at the beginning and then a # are ignored +# as comments. But comments can NOT be put on lines with data. +#*************************************************************************** + +# This is an example of a 'profile' file which includes a base file and adds +# some customizaton for a particular purpose. + +# If this file is found in the user's ~/.ipython directory as ipythonrc-math, +# it can be loaded by calling passing the '-profile math' (or '-p math') +# option to IPython. + +# This example is a light customization to have ipython have basic math functions +# readily available, effectively making the python prompt a very capable scientific +# calculator + +# include base config and only add some extras +include ipythonrc + +# load the complex math functions but keep them in a separate namespace +import_mod cmath + +# from ... import * +# load the real math functions in the global namespace for convenience +import_all math + +# from ... import ... +import_some + +# code to execute +execute print "*** math functions available globally, cmath as a module" diff --git a/IPython/UserConfig/ipythonrc-numeric b/IPython/UserConfig/ipythonrc-numeric new file mode 100644 index 0000000..1700ca0 --- /dev/null +++ b/IPython/UserConfig/ipythonrc-numeric @@ -0,0 +1,57 @@ +# -*- Mode: Shell-Script -*- Not really, but shows comments correctly +#*************************************************************************** +# +# Configuration file for ipython -- ipythonrc format +# +# The format of this file is one of 'key value' lines. +# Lines containing only whitespace at the beginning and then a # are ignored +# as comments. But comments can NOT be put on lines with data. +#*************************************************************************** + +# This is an example of a 'profile' file which includes a base file and adds +# some customizaton for a particular purpose. + +# If this file is found in the user's ~/.ipython directory as +# ipythonrc-numeric, it can be loaded by calling passing the '-profile +# numeric' (or '-p numeric') option to IPython. + +# A simple alias numpy -> 'ipython -p numeric' makes life very convenient. + +# This example is meant to load several modules to turn IPython into a very +# capable environment for high-end numerical work, similar to IDL or MatLab +# but with the beauty and flexibility of the Python language. + +# Load the user's basic configuration +include ipythonrc + +# import ... + +# Load Numeric by itself so that 'help Numeric' works +import_mod Numeric + +# from ... import * +# GnuplotRuntime loads Gnuplot and adds enhancements for use in IPython +import_all Numeric IPython.numutils IPython.GnuplotInteractive + +# a simple line at zero, often useful for an x-axis +execute xaxis=gpfunc('0',title='',with='lines lt -1') + +# Below are optional things off by default. Uncomment them if desired. + +# MA (MaskedArray) modifies the Numeric printing mechanism so that huge arrays +# are only summarized and not printed (which may freeze the machine for a +# _long_ time). + +#import_mod MA + + +# gracePlot is a Python interface to the plotting package Grace. +# For more details go to: http://www.idyll.org/~n8gray/code/index.html +# Uncomment lines below if you have grace and its python support code + +#import_mod gracePlot +#execute grace = gracePlot.gracePlot # alias to make gracePlot instances +#execute print '*** grace is an alias for gracePlot.gracePlot' + +# Files to execute +execfile diff --git a/IPython/UserConfig/ipythonrc-physics b/IPython/UserConfig/ipythonrc-physics new file mode 100644 index 0000000..fe2bc64 --- /dev/null +++ b/IPython/UserConfig/ipythonrc-physics @@ -0,0 +1,43 @@ +# -*- Mode: Shell-Script -*- Not really, but shows comments correctly +#*************************************************************************** +# +# Configuration file for ipython -- ipythonrc format +# +# The format of this file is one of 'key value' lines. +# Lines containing only whitespace at the beginning and then a # are ignored +# as comments. But comments can NOT be put on lines with data. +#*************************************************************************** + +# If this file is found in the user's ~/.ipython directory as +# ipythonrc-physics, it can be loaded by calling passing the '-profile +# physics' (or '-p physics') option to IPython. + +# This profile loads modules useful for doing interactive calculations with +# physical quantities (with units). It relies on modules from Konrad Hinsen's +# ScientificPython (http://starship.python.net/crew/hinsen/) + +# First load basic user configuration +include ipythonrc + +# import ... +# Module with alternate input syntax for PhysicalQuantity objects. +import_mod IPython.Extensions.PhysicalQInput + +# from ... import * +# math CANNOT be imported after PhysicalQInteractive. It will override the +# functions defined there. +import_all math IPython.Extensions.PhysicalQInteractive + +# from ... import ... +import_some + +# code +execute q = PhysicalQuantityInteractive +execute g = PhysicalQuantityInteractive('9.8 m/s**2') +ececute rad = pi/180. +execute print '*** q is an alias for PhysicalQuantityInteractive' +execute print '*** g = 9.8 m/s^2 has been defined' +execute print '*** rad = pi/180 has been defined' + +# Files to execute +execfile diff --git a/IPython/UserConfig/ipythonrc-pysh b/IPython/UserConfig/ipythonrc-pysh new file mode 100644 index 0000000..2c7d204 --- /dev/null +++ b/IPython/UserConfig/ipythonrc-pysh @@ -0,0 +1,94 @@ +# -*- Mode: Shell-Script -*- Not really, but shows comments correctly +#*************************************************************************** +# Configuration file for ipython -- ipythonrc format +# +# The format of this file is one of 'key value' lines. +# Lines containing only whitespace at the beginning and then a # are ignored +# as comments. But comments can NOT be put on lines with data. +#*************************************************************************** + +# If this file is found in the user's ~/.ipython directory as ipythonrc-pysh, +# it can be loaded by calling passing the '-profile pysh' (or '-p pysh') +# option to IPython. + +# This profile turns IPython into a lightweight system shell with python +# syntax. + +# We only set a few options here, the rest is done in the companion pysh.py +# file. In the future _all_ of IPython's configuration will be done via +# proper python code. + +############################################################################ +# First load common user configuration +include ipythonrc + +############################################################################ +# Load all the actual syntax extensions for shell-like operation, which live +# in the InterpreterExec standard extension. +import_all IPython.Extensions.InterpreterExec + +############################################################################ +# PROMPTS +# +# Configure prompt for more shell-like usage. + +# Most bash-like escapes can be used to customize IPython's prompts, as well as +# a few additional ones which are IPython-specific. All valid prompt escapes +# are described in detail in the Customization section of the IPython HTML/PDF +# manual. + +prompt_in1 '\C_LightGreen\u@\h\C_LightBlue[\C_LightCyan\Y1\C_LightBlue]\C_Green|\#> ' +prompt_in2 '\C_Green|\C_LightGreen\D\C_Green> ' +prompt_out '<\#> ' + +# Here's a more complex prompt, showing the hostname and more path depth (\Y3) +#prompt_in1 '\C_LightRed\u\C_Blue@\C_Red\h\C_LightBlue[\C_LightCyan\Y3\C_LightBlue]\C_LightGreen\#> ' + +# Select whether to left-pad the output prompts to match the length of the +# input ones. This allows you for example to use a simple '>' as an output +# prompt, and yet have the output line up with the input. If set to false, +# the output prompts will be unpadded (flush left). +prompts_pad_left 1 + + +# Remove all blank lines in between prompts, like a normal shell. +separate_in 0 +separate_out 0 +separate_out2 0 + +# Allow special syntax (!, magics and aliases) in multiline input +multi_line_specials 1 + +############################################################################ +# ALIASES + +# Declare some common aliases. Type alias? at an ipython prompt for details on +# the syntax, use @unalias to delete existing aliases. + +# Don't go too crazy here, the file pysh.py called below runs @rehash, which +# loads ALL of your $PATH as aliases (except for Python keywords and +# builtins). + +# Some examples: + +# A simple alias without arguments +#alias cl clear + +# An alias which expands the full line before the end of the alias. This +# lists only directories: +#alias ldir pwd;ls -oF --color %l | grep /$ + +# An alias with two positional arguments: +#alias parts echo 'First <%s> Second <%s>' + +# In use these two aliases give (note that ldir is already built into IPython +# for Unix): + +#fperez[IPython]16> ldir +#/usr/local/home/fperez/ipython/ipython/IPython +#drwxr-xr-x 2 fperez 4096 Jun 21 01:01 CVS/ +#drwxr-xr-x 3 fperez 4096 Jun 21 01:10 Extensions/ +#drwxr-xr-x 3 fperez 4096 Jun 21 01:27 UserConfig/ + +#fperez[IPython]17> parts Hello world and goodbye +#First <Hello> Second <world> and goodbye diff --git a/IPython/UserConfig/ipythonrc-scipy b/IPython/UserConfig/ipythonrc-scipy new file mode 100644 index 0000000..76d55f2 --- /dev/null +++ b/IPython/UserConfig/ipythonrc-scipy @@ -0,0 +1,43 @@ +# -*- Mode: Shell-Script -*- Not really, but shows comments correctly +#*************************************************************************** +# +# Configuration file for ipython -- ipythonrc format +# +# The format of this file is one of 'key value' lines. +# Lines containing only whitespace at the beginning and then a # are ignored +# as comments. But comments can NOT be put on lines with data. +#*************************************************************************** + +# This is an example of a 'profile' file which includes a base file and adds +# some customizaton for a particular purpose. + +# If this file is found in the user's ~/.ipython directory as ipythonrc-scipy, +# it can be loaded by calling passing the '-profile scipy' (or '-p scipy') +# option to IPython. + +# This example is meant to load several modules to turn ipython into a very +# capable environment for high-end numerical work, similar to IDL or MatLab +# but with the beauty of the Python language. + +# load our basic configuration with generic options +include ipythonrc + +# import ... +# Load SciPy by itself so that 'help scipy' works +import_mod scipy + +# from ... import ... +import_some + +# Now we load all of SciPy +# from ... import * +import_all scipy IPython.numutils + +# code +execute print 'Welcome to the SciPy Scientific Computing Environment.' +execute scipy.alter_numeric() + +# File with alternate printer system for Numeric Arrays. +# Files in the 'Extensions' directory will be found by IPython automatically +# (otherwise give the explicit path): +execfile Extensions/numeric_formats.py diff --git a/IPython/UserConfig/ipythonrc-tutorial b/IPython/UserConfig/ipythonrc-tutorial new file mode 100644 index 0000000..6c97569 --- /dev/null +++ b/IPython/UserConfig/ipythonrc-tutorial @@ -0,0 +1,37 @@ +# -*- Mode: Shell-Script -*- Not really, but shows comments correctly +#*************************************************************************** +# +# Configuration file for ipython -- ipythonrc format +# +# The format of this file is one of 'key value' lines. +# Lines containing only whitespace at the beginning and then a # are ignored +# as comments. But comments can NOT be put on lines with data. +#*************************************************************************** + +# If this file is found in the user's ~/.ipython directory as +# ipythonrc-tutorial, it can be loaded by calling passing the '-profile +# tutorial' (or '-p tutorial') option to IPython. + +# This profile loads a special input line filter to allow typing lines which +# begin with '>>> ' or '... '. These two strings, if present at the start of +# the input line, are stripped. This allows for direct pasting of code from +# examples such as those available in the standard Python tutorial. + +# First load basic user configuration +include ipythonrc + +# import ... +# Module with alternate input syntax for pasting python input +import_mod IPython.Extensions.InterpreterPasteInput + +# from ... import * +import_all + +# from ... import ... +import_some + +# code +execute + +# Files to execute +execfile diff --git a/IPython/__init__.py b/IPython/__init__.py new file mode 100644 index 0000000..ff74c49 --- /dev/null +++ b/IPython/__init__.py @@ -0,0 +1,63 @@ +# -*- coding: utf-8 -*- +""" +IPython -- An enhanced Interactive Python + +One of Python's nicest features is its interactive interpreter. This 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 fairly primitive (and IDLE isn't really +much better). + +IPython tries to: + + i - provide an efficient environment for interactive work in Python + programming. It tries to address what we see as shortcomings of the standard + Python prompt, and adds many features to make interactive work much more + efficient. + + ii - offer a flexible framework so that it can be used as the base + environment for other projects and problems where Python can be the + underlying language. Specifically scientific environments like Mathematica, + IDL and Mathcad inspired its design, but similar ideas can be useful in many + fields. Python is a fabulous language for implementing this kind of system + (due to its dynamic and introspective features), and with suitable libraries + entire systems could be built leveraging Python's power. + + iii - serve as an embeddable, ready to go interpreter for your own programs. + +IPython requires Python 2.2 or newer. + +$Id: __init__.py 530 2005-03-02 07:11:15Z fperez $""" + +#***************************************************************************** +# Copyright (C) 2001-2004 Fernando Perez. <fperez@colorado.edu> +# +# Distributed under the terms of the BSD License. The full license is in +# the file COPYING, distributed as part of this software. +#***************************************************************************** + +# Enforce proper version requirements +import sys +if sys.version[0:3] < '2.2': + raise ImportError, 'Python Version 2.2 or above is required.' + +# Define what gets imported with a 'from IPython import *' +__all__ = ['deep_reload','genutils','ultraTB','DPyGetOpt','Itpl','hooks', + 'ConfigLoader','OutputTrap','Release','Struct','Shell'] + +# Load __all__ in IPython namespace so that a simple 'import IPython' gives +# access to them via IPython.<name> +glob,loc = globals(),locals() +for name in __all__: + __import__(name,glob,loc,[]) + +# Release data +from IPython import Release # do it explicitly so pydoc can see it - pydoc bug +__author__ = '%s <%s>\n%s <%s>\n%s <%s>' % \ + ( Release.authors['Fernando'] + Release.authors['Janko'] + \ + Release.authors['Nathan'] ) +__license__ = Release.license +__version__ = Release.version + +# Namespace cleanup +del name,glob,loc diff --git a/IPython/background_jobs.py b/IPython/background_jobs.py new file mode 100644 index 0000000..aaa2c81 --- /dev/null +++ b/IPython/background_jobs.py @@ -0,0 +1,504 @@ +# -*- coding: utf-8 -*- +"""Manage background (threaded) jobs conveniently from an interactive shell. + +This module provides a BackgroundJobManager class. This is the main class +meant for public usage, it implements an object which can create and manage +new background jobs. + +It also provides the actual job classes managed by these BackgroundJobManager +objects, see their docstrings below. + + +This system was inspired by discussions with B. Granger and the +BackgroundCommand class described in the book Python Scripting for +Computational Science, by H. P. Langtangen: + +http://folk.uio.no/hpl/scripting + +(although ultimately no code from this text was used, as IPython's system is a +separate implementation). + +$Id: background_jobs.py 515 2005-02-15 07:41:41Z fperez $ +""" + +#***************************************************************************** +# Copyright (C) 2005 Fernando Perez <fperez@colorado.edu> +# +# Distributed under the terms of the BSD License. The full license is in +# the file COPYING, distributed as part of this software. +#***************************************************************************** + +from IPython import Release +__author__ = '%s <%s>' % Release.authors['Fernando'] +__license__ = Release.license + +# Code begins +import threading,sys + +from IPython.ultraTB import AutoFormattedTB +from IPython.genutils import warn,error + +# declares Python 2.2 compatibility symbols: +try: + basestring +except NameError: + import types + basestring = (types.StringType, types.UnicodeType) + True = 1==1 + False = 1==0 + +class BackgroundJobManager: + """Class to manage a pool of backgrounded threaded jobs. + + Below, we assume that 'jobs' is a BackgroundJobManager instance. + + Usage summary (see the method docstrings for details): + + jobs.new(...) -> start a new job + + jobs() or jobs.status() -> print status summary of all jobs + + jobs[N] -> returns job number N. + + foo = jobs[N].result -> assign to variable foo the result of job N + + jobs[N].traceback() -> print the traceback of dead job N + + jobs.remove(N) -> remove (finished) job N + + jobs.flush_finished() -> remove all finished jobs + + As a convenience feature, BackgroundJobManager instances provide the + utility result and traceback methods which retrieve the corresponding + information from the jobs list: + + jobs.result(N) <--> jobs[N].result + jobs.traceback(N) <--> jobs[N].traceback() + + While this appears minor, it allows you to use tab completion + interactively on the job manager instance. + + In interactive mode, IPython provides the magic fuction %bg for quick + creation of backgrounded expression-based jobs. Type bg? for details.""" + + def __init__(self): + # Lists for job management + self.jobs_run = [] + self.jobs_comp = [] + self.jobs_dead = [] + # A dict of all jobs, so users can easily access any of them + self.jobs_all = {} + # For reporting + self._comp_report = [] + self._dead_report = [] + # Store status codes locally for fast lookups + self._s_created = BackgroundJobBase.stat_created_c + self._s_running = BackgroundJobBase.stat_running_c + self._s_completed = BackgroundJobBase.stat_completed_c + self._s_dead = BackgroundJobBase.stat_dead_c + + def new(self,func_or_exp,*args,**kwargs): + """Add a new background job and start it in a separate thread. + + There are two types of jobs which can be created: + + 1. Jobs based on expressions which can be passed to an eval() call. + The expression must be given as a string. For example: + + job_manager.new('myfunc(x,y,z=1)'[,glob[,loc]]) + + The given expression is passed to eval(), along with the optional + global/local dicts provided. If no dicts are given, they are + extracted automatically from the caller's frame. + + A Python statement is NOT a valid eval() expression. Basically, you + can only use as an eval() argument something which can go on the right + of an '=' sign and be assigned to a variable. + + For example,"print 'hello'" is not valid, but '2+3' is. + + 2. Jobs given a function object, optionally passing additional + positional arguments: + + job_manager.new(myfunc,x,y) + + The function is called with the given arguments. + + If you need to pass keyword arguments to your function, you must + supply them as a dict named kw: + + job_manager.new(myfunc,x,y,kw=dict(z=1)) + + The reason for this assymmetry is that the new() method needs to + maintain access to its own keywords, and this prevents name collisions + between arguments to new() and arguments to your own functions. + + In both cases, the result is stored in the job.result field of the + background job object. + + + Notes and caveats: + + 1. All threads running share the same standard output. Thus, if your + background jobs generate output, it will come out on top of whatever + you are currently writing. For this reason, background jobs are best + used with silent functions which simply return their output. + + 2. Threads also all work within the same global namespace, and this + system does not lock interactive variables. So if you send job to the + background which operates on a mutable object for a long time, and + start modifying that same mutable object interactively (or in another + backgrounded job), all sorts of bizarre behaviour will occur. + + 3. If a background job is spending a lot of time inside a C extension + module which does not release the Python Global Interpreter Lock + (GIL), this will block the IPython prompt. This is simply because the + Python interpreter can only switch between threads at Python + bytecodes. While the execution is inside C code, the interpreter must + simply wait unless the extension module releases the GIL. + + 4. There is no way, due to limitations in the Python threads library, + to kill a thread once it has started.""" + + if callable(func_or_exp): + kw = kwargs.get('kw',{}) + job = BackgroundJobFunc(func_or_exp,*args,**kw) + elif isinstance(func_or_exp,basestring): + if not args: + frame = sys._getframe(1) + glob, loc = frame.f_globals, frame.f_locals + elif len(args)==1: + glob = loc = args[0] + elif len(args)==2: + glob,loc = args + else: + raise ValueError,\ + 'Expression jobs take at most 2 args (globals,locals)' + job = BackgroundJobExpr(func_or_exp,glob,loc) + else: + raise + jkeys = self.jobs_all.keys() + if jkeys: + job.num = max(jkeys)+1 + else: + job.num = 0 + self.jobs_run.append(job) + self.jobs_all[job.num] = job + print 'Starting job # %s in a separate thread.' % job.num + job.start() + return job + + def __getitem__(self,key): + return self.jobs_all[key] + + def __call__(self): + """An alias to self.status(), + + This allows you to simply call a job manager instance much like the + Unix jobs shell command.""" + + return self.status() + + def _update_status(self): + """Update the status of the job lists. + + This method moves finished jobs to one of two lists: + - self.jobs_comp: jobs which completed successfully + - self.jobs_dead: jobs which finished but died. + + It also copies those jobs to corresponding _report lists. These lists + are used to report jobs completed/dead since the last update, and are + then cleared by the reporting function after each call.""" + + run,comp,dead = self._s_running,self._s_completed,self._s_dead + jobs_run = self.jobs_run + for num in range(len(jobs_run)): + job = jobs_run[num] + stat = job.stat_code + if stat == run: + continue + elif stat == comp: + self.jobs_comp.append(job) + self._comp_report.append(job) + jobs_run[num] = False + elif stat == dead: + self.jobs_dead.append(job) + self._dead_report.append(job) + jobs_run[num] = False + self.jobs_run = filter(None,self.jobs_run) + + def _group_report(self,group,name): + """Report summary for a given job group. + + Return True if the group had any elements.""" + + if group: + print '%s jobs:' % name + for job in group: + print '%s : %s' % (job.num,job) + print + return True + + def _group_flush(self,group,name): + """Flush a given job group + + Return True if the group had any elements.""" + + njobs = len(group) + if njobs: + plural = {1:''}.setdefault(njobs,'s') + print 'Flushing %s %s job%s.' % (njobs,name,plural) + group[:] = [] + return True + + def _status_new(self): + """Print the status of newly finished jobs. + + Return True if any new jobs are reported. + + This call resets its own state every time, so it only reports jobs + which have finished since the last time it was called.""" + + self._update_status() + new_comp = self._group_report(self._comp_report,'Completed') + new_dead = self._group_report(self._dead_report, + 'Dead, call job.traceback() for details') + self._comp_report[:] = [] + self._dead_report[:] = [] + return new_comp or new_dead + + def status(self,verbose=0): + """Print a status of all jobs currently being managed.""" + + self._update_status() + self._group_report(self.jobs_run,'Running') + self._group_report(self.jobs_comp,'Completed') + self._group_report(self.jobs_dead,'Dead') + # Also flush the report queues + self._comp_report[:] = [] + self._dead_report[:] = [] + + def remove(self,num): + """Remove a finished (completed or dead) job.""" + + try: + job = self.jobs_all[num] + except KeyError: + error('Job #%s not found' % num) + else: + stat_code = job.stat_code + if stat_code == self._s_running: + error('Job #%s is still running, it can not be removed.' % num) + return + elif stat_code == self._s_completed: + self.jobs_comp.remove(job) + elif stat_code == self._s_dead: + self.jobs_dead.remove(job) + + def flush_finished(self): + """Flush all jobs finished (completed and dead) from lists. + + Running jobs are never flushed. + + It first calls _status_new(), to update info. If any jobs have + completed since the last _status_new() call, the flush operation + aborts.""" + + if self._status_new(): + error('New jobs completed since last '\ + '_status_new(), aborting flush.') + return + + # Remove the finished jobs from the master dict + jobs_all = self.jobs_all + for job in self.jobs_comp+self.jobs_dead: + del(jobs_all[job.num]) + + # Now flush these lists completely + fl_comp = self._group_flush(self.jobs_comp,'Completed') + fl_dead = self._group_flush(self.jobs_dead,'Dead') + if not (fl_comp or fl_dead): + print 'No jobs to flush.' + + def result(self,num): + """result(N) -> return the result of job N.""" + try: + return self.jobs_all[num].result + except KeyError: + error('Job #%s not found' % num) + + def traceback(self,num): + try: + self.jobs_all[num].traceback() + except KeyError: + error('Job #%s not found' % num) + + +class BackgroundJobBase(threading.Thread): + """Base class to build BackgroundJob classes. + + The derived classes must implement: + + - Their own __init__, since the one here raises NotImplementedError. The + derived constructor must call self._init() at the end, to provide common + initialization. + + - A strform attribute used in calls to __str__. + + - A call() method, which will make the actual execution call and must + return a value to be held in the 'result' field of the job object.""" + + # Class constants for status, in string and as numerical codes (when + # updating jobs lists, we don't want to do string comparisons). This will + # be done at every user prompt, so it has to be as fast as possible + stat_created = 'Created'; stat_created_c = 0 + stat_running = 'Running'; stat_running_c = 1 + stat_completed = 'Completed'; stat_completed_c = 2 + stat_dead = 'Dead (Exception), call job.traceback() for details' + stat_dead_c = -1 + + def __init__(self): + raise NotImplementedError, \ + "This class can not be instantiated directly." + + def _init(self): + """Common initialization for all BackgroundJob objects""" + + for attr in ['call','strform']: + assert hasattr(self,attr), "Missing attribute <%s>" % attr + + # The num tag can be set by an external job manager + self.num = None + + self.status = BackgroundJobBase.stat_created + self.stat_code = BackgroundJobBase.stat_created_c + self.finished = False + self.result = '<BackgroundJob has not completed>' + # reuse the ipython traceback handler if we can get to it, otherwise + # make a new one + try: + self._make_tb = __IPYTHON__.InteractiveTB.text + except: + self._make_tb = AutoFormattedTB(mode = 'Context', + color_scheme='NoColor', + tb_offset = 1).text + # Hold a formatted traceback if one is generated. + self._tb = None + + threading.Thread.__init__(self) + + def __str__(self): + return self.strform + + def __repr__(self): + return '<BackgroundJob: %s>' % self.strform + + def traceback(self): + print self._tb + + def run(self): + try: + self.status = BackgroundJobBase.stat_running + self.stat_code = BackgroundJobBase.stat_running_c + self.result = self.call() + except: + self.status = BackgroundJobBase.stat_dead + self.stat_code = BackgroundJobBase.stat_dead_c + self.finished = None + self.result = ('<BackgroundJob died, call job.traceback() for details>') + self._tb = self._make_tb() + else: + self.status = BackgroundJobBase.stat_completed + self.stat_code = BackgroundJobBase.stat_completed_c + self.finished = True + +class BackgroundJobExpr(BackgroundJobBase): + """Evaluate an expression as a background job (uses a separate thread).""" + + def __init__(self,expression,glob=None,loc=None): + """Create a new job from a string which can be fed to eval(). + + global/locals dicts can be provided, which will be passed to the eval + call.""" + + # fail immediately if the given expression can't be compiled + self.code = compile(expression,'<BackgroundJob compilation>','eval') + + if glob is None: + glob = {} + if loc is None: + loc = {} + + self.expression = self.strform = expression + self.glob = glob + self.loc = loc + self._init() + + def call(self): + return eval(self.code,self.glob,self.loc) + +class BackgroundJobFunc(BackgroundJobBase): + """Run a function call as a background job (uses a separate thread).""" + + def __init__(self,func,*args,**kwargs): + """Create a new job from a callable object. + + Any positional arguments and keyword args given to this constructor + after the initial callable are passed directly to it.""" + + assert callable(func),'first argument must be callable' + + if args is None: + args = [] + if kwargs is None: + kwargs = {} + + self.func = func + self.args = args + self.kwargs = kwargs + # The string form will only include the function passed, because + # generating string representations of the arguments is a potentially + # _very_ expensive operation (e.g. with large arrays). + self.strform = str(func) + self._init() + + def call(self): + return self.func(*self.args,**self.kwargs) + + +if __name__=='__main__': + + import time + + def sleepfunc(interval=2,*a,**kw): + args = dict(interval=interval, + args=a, + kwargs=kw) + time.sleep(interval) + return args + + def diefunc(interval=2,*a,**kw): + time.sleep(interval) + die + + def printfunc(interval=1,reps=5): + for n in range(reps): + time.sleep(interval) + print 'In the background...' + + jobs = BackgroundJobManager() + # first job will have # 0 + jobs.new(sleepfunc,4) + jobs.new(sleepfunc,kw={'reps':2}) + # This makes a job which will die + jobs.new(diefunc,1) + jobs.new('printfunc(1,3)') + + # after a while, you can get the traceback of a dead job. Run the line + # below again interactively until it prints a traceback (check the status + # of the job): + print jobs[1].status + jobs[1].traceback() + + # Run this line again until the printed result changes + print "The result of job #0 is:",jobs[0].result diff --git a/IPython/deep_reload.py b/IPython/deep_reload.py new file mode 100644 index 0000000..eb8dd11 --- /dev/null +++ b/IPython/deep_reload.py @@ -0,0 +1,184 @@ +# -*- coding: utf-8 -*- +""" +A module to change reload() so that it acts recursively. +To enable it type: + >>> import __builtin__, deep_reload + >>> __builtin__.reload = deep_reload.reload +You can then disable it with: + >>> __builtin__.reload = deep_reload.original_reload + +Alternatively, you can add a dreload builtin alongside normal reload with: + >>> __builtin__.dreload = deep_reload.reload + +This code is almost entirely based on knee.py from the standard library. + +$Id: deep_reload.py 410 2004-11-04 07:58:17Z fperez $""" + +#***************************************************************************** +# Copyright (C) 2001 Nathaniel Gray <n8gray@caltech.edu> +# +# Distributed under the terms of the BSD License. The full license is in +# the file COPYING, distributed as part of this software. +#***************************************************************************** + +from IPython import Release # do it explicitly so pydoc can see it - pydoc bug +__author__ = '%s <%s>' % Release.authors['Nathan'] +__license__ = Release.license +__version__ = "0.5" +__date__ = "21 August 2001" + +import sys, imp, __builtin__ + +# Replacement for __import__() +def deep_import_hook(name, globals=None, locals=None, fromlist=None): + parent = determine_parent(globals) + q, tail = find_head_package(parent, name) + m = load_tail(q, tail) + if not fromlist: + return q + if hasattr(m, "__path__"): + ensure_fromlist(m, fromlist) + return m + +def determine_parent(globals): + if not globals or not globals.has_key("__name__"): + return None + pname = globals['__name__'] + if globals.has_key("__path__"): + parent = sys.modules[pname] + assert globals is parent.__dict__ + return parent + if '.' in pname: + i = pname.rfind('.') + pname = pname[:i] + parent = sys.modules[pname] + assert parent.__name__ == pname + return parent + return None + +def find_head_package(parent, name): + # Import the first + if '.' in name: + # 'some.nested.package' -> head = 'some', tail = 'nested.package' + i = name.find('.') + head = name[:i] + tail = name[i+1:] + else: + # 'packagename' -> head = 'packagename', tail = '' + head = name + tail = "" + if parent: + # If this is a subpackage then qname = parent's name + head + qname = "%s.%s" % (parent.__name__, head) + else: + qname = head + q = import_module(head, qname, parent) + if q: return q, tail + if parent: + qname = head + parent = None + q = import_module(head, qname, parent) + if q: return q, tail + raise ImportError, "No module named " + qname + +def load_tail(q, tail): + m = q + while tail: + i = tail.find('.') + if i < 0: i = len(tail) + head, tail = tail[:i], tail[i+1:] + + # fperez: fix dotted.name reloading failures by changing: + #mname = "%s.%s" % (m.__name__, head) + # to: + mname = m.__name__ + # This needs more testing!!! (I don't understand this module too well) + + #print '** head,tail=|%s|->|%s|, mname=|%s|' % (head,tail,mname) # dbg + m = import_module(head, mname, m) + if not m: + raise ImportError, "No module named " + mname + return m + +def ensure_fromlist(m, fromlist, recursive=0): + for sub in fromlist: + if sub == "*": + if not recursive: + try: + all = m.__all__ + except AttributeError: + pass + else: + ensure_fromlist(m, all, 1) + continue + if sub != "*" and not hasattr(m, sub): + subname = "%s.%s" % (m.__name__, sub) + submod = import_module(sub, subname, m) + if not submod: + raise ImportError, "No module named " + subname + +# Need to keep track of what we've already reloaded to prevent cyclic evil +found_now = {} + +def import_module(partname, fqname, parent): + global found_now + if found_now.has_key(fqname): + try: + return sys.modules[fqname] + except KeyError: + pass + + print 'Reloading', fqname #, sys.excepthook is sys.__excepthook__, \ + #sys.displayhook is sys.__displayhook__ + + found_now[fqname] = 1 + try: + fp, pathname, stuff = imp.find_module(partname, + parent and parent.__path__) + except ImportError: + return None + + try: + m = imp.load_module(fqname, fp, pathname, stuff) + finally: + if fp: fp.close() + + if parent: + setattr(parent, partname, m) + + return m + +def deep_reload_hook(module): + name = module.__name__ + if '.' not in name: + return import_module(name, name, None) + i = name.rfind('.') + pname = name[:i] + parent = sys.modules[pname] + return import_module(name[i+1:], name, parent) + +# Save the original hooks +original_reload = __builtin__.reload + +# Replacement for reload() +def reload(module, exclude=['sys', '__builtin__', '__main__']): + """Recursively reload all modules used in the given module. Optionally + takes a list of modules to exclude from reloading. The default exclude + list contains sys, __main__, and __builtin__, to prevent, e.g., resetting + display, exception, and io hooks. + """ + global found_now + for i in exclude: + found_now[i] = 1 + original_import = __builtin__.__import__ + __builtin__.__import__ = deep_import_hook + try: + ret = deep_reload_hook(module) + finally: + __builtin__.__import__ = original_import + found_now = {} + return ret + +# Uncomment the following to automatically activate deep reloading whenever +# this module is imported +#__builtin__.reload = reload diff --git a/IPython/genutils.py b/IPython/genutils.py new file mode 100644 index 0000000..8682525 --- /dev/null +++ b/IPython/genutils.py @@ -0,0 +1,1519 @@ +# -*- coding: utf-8 -*- +""" +General purpose utilities. + +This is a grab-bag of stuff I find useful in most programs I write. Some of +these things are also convenient when working at the command line. + +$Id: genutils.py 543 2005-03-18 09:23:48Z fperez $""" + +#***************************************************************************** +# Copyright (C) 2001-2004 Fernando Perez. <fperez@colorado.edu> +# +# Distributed under the terms of the BSD License. The full license is in +# the file COPYING, distributed as part of this software. +#***************************************************************************** + +from IPython import Release +__author__ = '%s <%s>' % Release.authors['Fernando'] +__license__ = Release.license + +#**************************************************************************** +# required modules +import __main__ +import types,commands,time,sys,os,re,shutil +import tempfile +from IPython.Itpl import Itpl,itpl,printpl +from IPython import DPyGetOpt + +#**************************************************************************** +# Exceptions +class Error(Exception): + """Base class for exceptions in this module.""" + pass + +#---------------------------------------------------------------------------- +class Stream: + """Simple class to hold the various I/O streams in Term""" + + def __init__(self,stream,name): + self.stream = stream + self.name = name + try: + self.fileno = stream.fileno() + except AttributeError: + msg = ("Stream <%s> looks suspicious: it lacks a 'fileno' attribute." + % name) + print >> sys.stderr, 'WARNING:',msg + try: + self.mode = stream.mode + except AttributeError: + msg = ("Stream <%s> looks suspicious: it lacks a 'mode' attribute." + % name) + print >> sys.stderr, 'WARNING:',msg + +class Term: + """ Term holds the file or file-like objects for handling I/O operations. + + These are normally just sys.stdin, sys.stdout and sys.stderr but for + Windows they can can replaced to allow editing the strings before they are + displayed.""" + + # In the future, having IPython channel all its I/O operations through + # this class will make it easier to embed it into other environments which + # are not a normal terminal (such as a GUI-based shell) + in_s = Stream(sys.stdin,'cin') + out_s = Stream(sys.stdout,'cout') + err_s = Stream(sys.stderr,'cerr') + + # Store the three streams in (err,out,in) order so that if we need to reopen + # them, the error channel is reopened first to provide info. + streams = [err_s,out_s,in_s] + + # The class globals should be the actual 'bare' streams for normal I/O to work + cin = streams[2].stream + cout = streams[1].stream + cerr = streams[0].stream + + def reopen_all(cls): + """Reopen all streams if necessary. + + This should only be called if it is suspected that someting closed + accidentally one of the I/O streams.""" + + any_closed = 0 + + for sn in range(len(cls.streams)): + st = cls.streams[sn] + if st.stream.closed: + any_closed = 1 + new_stream = os.fdopen(os.dup(st.fileno), st.mode,0) + cls.streams[sn] = Stream(new_stream,st.name) + print >> cls.streams[0].stream, \ + '\nWARNING:\nStream Term.%s had to be reopened!' % st.name + + # Rebuild the class globals + cls.cin = cls.streams[2].stream + cls.cout = cls.streams[1].stream + cls.cerr = cls.streams[0].stream + + reopen_all = classmethod(reopen_all) + + def set_stdout(cls,stream): + """Set the stream """ + cls.cout = stream + set_stdout = classmethod(set_stdout) + + def set_stderr(cls,stream): + cls.cerr = stream + set_stderr = classmethod(set_stderr) + +# Windows-specific code to load Gary Bishop's readline and configure it +# automatically for the users +# Note: os.name on cygwin returns posix, so this should only pick up 'native' +# windows. Cygwin returns 'cygwin' for sys.platform. +if os.name == 'nt': + try: + import readline + except ImportError: + pass + else: + try: + _out = readline.GetOutputFile() + except AttributeError: + pass + else: + Term.set_stdout(_out) + Term.set_stderr(_out) + del _out + +#**************************************************************************** +# Generic warning/error printer, used by everything else +def warn(msg,level=2,exit_val=1): + """Standard warning printer. Gives formatting consistency. + + Output is sent to Term.cerr (sys.stderr by default). + + Options: + + -level(2): allows finer control: + 0 -> Do nothing, dummy function. + 1 -> Print message. + 2 -> Print 'WARNING:' + message. (Default level). + 3 -> Print 'ERROR:' + message. + 4 -> Print 'FATAL ERROR:' + message and trigger a sys.exit(exit_val). + + -exit_val (1): exit value returned by sys.exit() for a level 4 + warning. Ignored for all other levels.""" + + if level>0: + header = ['','','WARNING: ','ERROR: ','FATAL ERROR: '] + print >> Term.cerr, '%s%s' % (header[level],msg) + if level == 4: + print >> Term.cerr,'Exiting.\n' + sys.exit(exit_val) + +def info(msg): + """Equivalent to warn(msg,level=1).""" + + warn(msg,level=1) + +def error(msg): + """Equivalent to warn(msg,level=3).""" + + warn(msg,level=3) + +def fatal(msg,exit_val=1): + """Equivalent to warn(msg,exit_val=exit_val,level=4).""" + + warn(msg,exit_val=exit_val,level=4) + +#---------------------------------------------------------------------------- +StringTypes = types.StringTypes + +# Basic timing functionality + +# If possible (Unix), use the resource module instead of time.clock() +try: + import resource + def clock(): + """clock() -> floating point number + + Return the CPU time in seconds (user time only, system time is + ignored) since the start of the process. This is done via a call to + resource.getrusage, so it avoids the wraparound problems in + time.clock().""" + + return resource.getrusage(resource.RUSAGE_SELF)[0] + + def clock2(): + """clock2() -> (t_user,t_system) + + Similar to clock(), but return a tuple of user/system times.""" + return resource.getrusage(resource.RUSAGE_SELF)[:2] + +except ImportError: + clock = time.clock + def clock2(): + """Under windows, system CPU time can't be measured. + + This just returns clock() and zero.""" + return time.clock(),0.0 + +def timings_out(reps,func,*args,**kw): + """timings_out(reps,func,*args,**kw) -> (t_total,t_per_call,output) + + Execute a function reps times, return a tuple with the elapsed total + CPU time in seconds, the time per call and the function's output. + + Under Unix, the return value is the sum of user+system time consumed by + the process, computed via the resource module. This prevents problems + related to the wraparound effect which the time.clock() function has. + + Under Windows the return value is in wall clock seconds. See the + documentation for the time module for more details.""" + + reps = int(reps) + assert reps >=1, 'reps must be >= 1' + if reps==1: + start = clock() + out = func(*args,**kw) + tot_time = clock()-start + else: + rng = xrange(reps-1) # the last time is executed separately to store output + start = clock() + for dummy in rng: func(*args,**kw) + out = func(*args,**kw) # one last time + tot_time = clock()-start + av_time = tot_time / reps + return tot_time,av_time,out + +def timings(reps,func,*args,**kw): + """timings(reps,func,*args,**kw) -> (t_total,t_per_call) + + Execute a function reps times, return a tuple with the elapsed total CPU + time in seconds and the time per call. These are just the first two values + in timings_out().""" + + return timings_out(reps,func,*args,**kw)[0:2] + +def timing(func,*args,**kw): + """timing(func,*args,**kw) -> t_total + + Execute a function once, return the elapsed total CPU time in + seconds. This is just the first value in timings_out().""" + + return timings_out(1,func,*args,**kw)[0] + +#**************************************************************************** +# file and system + +def system(cmd,verbose=0,debug=0,header=''): + """Execute a system command, return its exit status. + + Options: + + - verbose (0): print the command to be executed. + + - debug (0): only print, do not actually execute. + + - header (''): Header to print on screen prior to the executed command (it + is only prepended to the command, no newlines are added). + + Note: a stateful version of this function is available through the + SystemExec class.""" + + stat = 0 + if verbose or debug: print header+cmd + sys.stdout.flush() + if not debug: stat = os.system(cmd) + return stat + +def shell(cmd,verbose=0,debug=0,header=''): + """Execute a command in the system shell, always return None. + + Options: + + - verbose (0): print the command to be executed. + + - debug (0): only print, do not actually execute. + + - header (''): Header to print on screen prior to the executed command (it + is only prepended to the command, no newlines are added). + + Note: this is similar to genutils.system(), but it returns None so it can + be conveniently used in interactive loops without getting the return value + (typically 0) printed many times.""" + + stat = 0 + if verbose or debug: print header+cmd + # flush stdout so we don't mangle python's buffering + sys.stdout.flush() + if not debug: + os.system(cmd) + +def getoutput(cmd,verbose=0,debug=0,header='',split=0): + """Dummy substitute for perl's backquotes. + + Executes a command and returns the output. + + Accepts the same arguments as system(), plus: + + - split(0): if true, the output is returned as a list split on newlines. + + Note: a stateful version of this function is available through the + SystemExec class.""" + + if verbose or debug: print header+cmd + if not debug: + output = commands.getoutput(cmd) + if split: + return output.split('\n') + else: + return output + +def getoutputerror(cmd,verbose=0,debug=0,header='',split=0): + """Return (standard output,standard error) of executing cmd in a shell. + + Accepts the same arguments as system(), plus: + + - split(0): if true, each of stdout/err is returned as a list split on + newlines. + + Note: a stateful version of this function is available through the + SystemExec class.""" + + if verbose or debug: print header+cmd + if not cmd: + if split: + return [],[] + else: + return '','' + if not debug: + pin,pout,perr = os.popen3(cmd) + tout = pout.read().rstrip() + terr = perr.read().rstrip() + pin.close() + pout.close() + perr.close() + if split: + return tout.split('\n'),terr.split('\n') + else: + return tout,terr + +# for compatibility with older naming conventions +xsys = system +bq = getoutput + +class SystemExec: + """Access the system and getoutput functions through a stateful interface. + + Note: here we refer to the system and getoutput functions from this + library, not the ones from the standard python library. + + This class offers the system and getoutput functions as methods, but the + verbose, debug and header parameters can be set for the instance (at + creation time or later) so that they don't need to be specified on each + call. + + For efficiency reasons, there's no way to override the parameters on a + per-call basis other than by setting instance attributes. If you need + local overrides, it's best to directly call system() or getoutput(). + + The following names are provided as alternate options: + - xsys: alias to system + - bq: alias to getoutput + + An instance can then be created as: + >>> sysexec = SystemExec(verbose=1,debug=0,header='Calling: ') + + And used as: + >>> sysexec.xsys('pwd') + >>> dirlist = sysexec.bq('ls -l') + """ + + def __init__(self,verbose=0,debug=0,header='',split=0): + """Specify the instance's values for verbose, debug and header.""" + setattr_list(self,'verbose debug header split') + + def system(self,cmd): + """Stateful interface to system(), with the same keyword parameters.""" + + system(cmd,self.verbose,self.debug,self.header) + + def shell(self,cmd): + """Stateful interface to shell(), with the same keyword parameters.""" + + shell(cmd,self.verbose,self.debug,self.header) + + xsys = system # alias + + def getoutput(self,cmd): + """Stateful interface to getoutput().""" + + return getoutput(cmd,self.verbose,self.debug,self.header,self.split) + + def getoutputerror(self,cmd): + """Stateful interface to getoutputerror().""" + + return getoutputerror(cmd,self.verbose,self.debug,self.header,self.split) + + bq = getoutput # alias + +#----------------------------------------------------------------------------- +def mutex_opts(dict,ex_op): + """Check for presence of mutually exclusive keys in a dict. + + Call: mutex_opts(dict,[[op1a,op1b],[op2a,op2b]...]""" + for op1,op2 in ex_op: + if op1 in dict and op2 in dict: + raise ValueError,'\n*** ERROR in Arguments *** '\ + 'Options '+op1+' and '+op2+' are mutually exclusive.' + +#----------------------------------------------------------------------------- +def filefind(fname,alt_dirs = None): + """Return the given filename either in the current directory, if it + exists, or in a specified list of directories. + + ~ expansion is done on all file and directory names. + + Upon an unsuccessful search, raise an IOError exception.""" + + if alt_dirs is None: + try: + alt_dirs = get_home_dir() + except HomeDirError: + alt_dirs = os.getcwd() + search = [fname] + list_strings(alt_dirs) + search = map(os.path.expanduser,search) + #print 'search list for',fname,'list:',search # dbg + fname = search[0] + if os.path.isfile(fname): + return fname + for direc in search[1:]: + testname = os.path.join(direc,fname) + #print 'testname',testname # dbg + if os.path.isfile(testname): + return testname + raise IOError,'File' + `fname` + \ + ' not found in current or supplied directories:' + `alt_dirs` + +#---------------------------------------------------------------------------- +def target_outdated(target,deps): + """Determine whether a target is out of date. + + target_outdated(target,deps) -> 1/0 + + deps: list of filenames which MUST exist. + target: single filename which may or may not exist. + + If target doesn't exist or is older than any file listed in deps, return + true, otherwise return false. + """ + try: + target_time = os.path.getmtime(target) + except os.error: + return 1 + for dep in deps: + dep_time = os.path.getmtime(dep) + if dep_time > target_time: + #print "For target",target,"Dep failed:",dep # dbg + #print "times (dep,tar):",dep_time,target_time # dbg + return 1 + return 0 + +#----------------------------------------------------------------------------- +def target_update(target,deps,cmd): + """Update a target with a given command given a list of dependencies. + + target_update(target,deps,cmd) -> runs cmd if target is outdated. + + This is just a wrapper around target_outdated() which calls the given + command if target is outdated.""" + + if target_outdated(target,deps): + xsys(cmd) + +#---------------------------------------------------------------------------- +def unquote_ends(istr): + """Remove a single pair of quotes from the endpoints of a string.""" + + if not istr: + return istr + if (istr[0]=="'" and istr[-1]=="'") or \ + (istr[0]=='"' and istr[-1]=='"'): + return istr[1:-1] + else: + return istr + +#---------------------------------------------------------------------------- +def process_cmdline(argv,names=[],defaults={},usage=''): + """ Process command-line options and arguments. + + Arguments: + + - argv: list of arguments, typically sys.argv. + + - names: list of option names. See DPyGetOpt docs for details on options + syntax. + + - defaults: dict of default values. + + - usage: optional usage notice to print if a wrong argument is passed. + + Return a dict of options and a list of free arguments.""" + + getopt = DPyGetOpt.DPyGetOpt() + getopt.setIgnoreCase(0) + getopt.parseConfiguration(names) + + try: + getopt.processArguments(argv) + except: + print usage + warn(`sys.exc_value`,level=4) + + defaults.update(getopt.optionValues) + args = getopt.freeValues + + return defaults,args + +#---------------------------------------------------------------------------- +def optstr2types(ostr): + """Convert a string of option names to a dict of type mappings. + + optstr2types(str) -> {None:'string_opts',int:'int_opts',float:'float_opts'} + + This is used to get the types of all the options in a string formatted + with the conventions of DPyGetOpt. The 'type' None is used for options + which are strings (they need no further conversion). This function's main + use is to get a typemap for use with read_dict(). + """ + + typeconv = {None:'',int:'',float:''} + typemap = {'s':None,'i':int,'f':float} + opt_re = re.compile(r'([\w]*)([^:=]*:?=?)([sif]?)') + + for w in ostr.split(): + oname,alias,otype = opt_re.match(w).groups() + if otype == '' or alias == '!': # simple switches are integers too + otype = 'i' + typeconv[typemap[otype]] += oname + ' ' + return typeconv + +#---------------------------------------------------------------------------- +def read_dict(filename,type_conv=None,**opt): + + """Read a dictionary of key=value pairs from an input file, optionally + performing conversions on the resulting values. + + read_dict(filename,type_conv,**opt) -> dict + + Only one value per line is accepted, the format should be + # optional comments are ignored + key value\n + + Args: + + - type_conv: A dictionary specifying which keys need to be converted to + which types. By default all keys are read as strings. This dictionary + should have as its keys valid conversion functions for strings + (int,long,float,complex, or your own). The value for each key + (converter) should be a whitespace separated string containing the names + of all the entries in the file to be converted using that function. For + keys to be left alone, use None as the conversion function (only needed + with purge=1, see below). + + - opt: dictionary with extra options as below (default in parens) + + purge(0): if set to 1, all keys *not* listed in type_conv are purged out + of the dictionary to be returned. If purge is going to be used, the + set of keys to be left as strings also has to be explicitly specified + using the (non-existent) conversion function None. + + fs(None): field separator. This is the key/value separator to be used + when parsing the file. The None default means any whitespace [behavior + of string.split()]. + + strip(0): if 1, strip string values of leading/trailinig whitespace. + + warn(1): warning level if requested keys are not found in file. + - 0: silently ignore. + - 1: inform but proceed. + - 2: raise KeyError exception. + + no_empty(0): if 1, remove keys with whitespace strings as a value. + + unique([]): list of keys (or space separated string) which can't be + repeated. If one such key is found in the file, each new instance + overwrites the previous one. For keys not listed here, the behavior is + to make a list of all appearances. + + Example: + If the input file test.ini has: + i 3 + x 4.5 + y 5.5 + s hi ho + Then: + + >>> type_conv={int:'i',float:'x',None:'s'} + >>> read_dict('test.ini') + {'i': '3', 's': 'hi ho', 'x': '4.5', 'y': '5.5'} + >>> read_dict('test.ini',type_conv) + {'i': 3, 's': 'hi ho', 'x': 4.5, 'y': '5.5'} + >>> read_dict('test.ini',type_conv,purge=1) + {'i': 3, 's': 'hi ho', 'x': 4.5} + """ + + # starting config + opt.setdefault('purge',0) + opt.setdefault('fs',None) # field sep defaults to any whitespace + opt.setdefault('strip',0) + opt.setdefault('warn',1) + opt.setdefault('no_empty',0) + opt.setdefault('unique','') + if type(opt['unique']) in StringTypes: + unique_keys = qw(opt['unique']) + elif type(opt['unique']) in (types.TupleType,types.ListType): + unique_keys = opt['unique'] + else: + raise ValueError, 'Unique keys must be given as a string, List or Tuple' + + dict = {} + # first read in table of values as strings + file = open(filename,'r') + for line in file.readlines(): + line = line.strip() + if len(line) and line[0]=='#': continue + if len(line)>0: + lsplit = line.split(opt['fs'],1) + try: + key,val = lsplit + except ValueError: + key,val = lsplit[0],'' + key = key.strip() + if opt['strip']: val = val.strip() + if val == "''" or val == '""': val = '' + if opt['no_empty'] and (val=='' or val.isspace()): + continue + # if a key is found more than once in the file, build a list + # unless it's in the 'unique' list. In that case, last found in file + # takes precedence. User beware. + try: + if dict[key] and key in unique_keys: + dict[key] = val + elif type(dict[key]) is types.ListType: + dict[key].append(val) + else: + dict[key] = [dict[key],val] + except KeyError: + dict[key] = val + # purge if requested + if opt['purge']: + accepted_keys = qwflat(type_conv.values()) + for key in dict.keys(): + if key in accepted_keys: continue + del(dict[key]) + # now convert if requested + if type_conv==None: return dict + conversions = type_conv.keys() + try: conversions.remove(None) + except: pass + for convert in conversions: + for val in qw(type_conv[convert]): + try: + dict[val] = convert(dict[val]) + except KeyError,e: + if opt['warn'] == 0: + pass + elif opt['warn'] == 1: + print >>sys.stderr, 'Warning: key',val,\ + 'not found in file',filename + elif opt['warn'] == 2: + raise KeyError,e + else: + raise ValueError,'Warning level must be 0,1 or 2' + + return dict + +#---------------------------------------------------------------------------- +def flag_calls(func): + """Wrap a function to detect and flag when it gets called. + + This is a decorator which takes a function and wraps it in a function with + a 'called' attribute. wrapper.called is initialized to False. + + The wrapper.called attribute is set to False right before each call to the + wrapped function, so if the call fails it remains False. After the call + completes, wrapper.called is set to True and the output is returned. + + Testing for truth in wrapper.called allows you to determine if a call to + func() was attempted and succeeded.""" + + def wrapper(*args,**kw): + wrapper.called = False + out = func(*args,**kw) + wrapper.called = True + return out + + wrapper.called = False + wrapper.__doc__ = func.__doc__ + return wrapper + +#---------------------------------------------------------------------------- +class HomeDirError(Error): + pass + +def get_home_dir(): + """Return the closest possible equivalent to a 'home' directory. + + We first try $HOME. Absent that, on NT it's $HOMEDRIVE\$HOMEPATH. + + Currently only Posix and NT are implemented, a HomeDirError exception is + raised for all other OSes. """ #' + + try: + return os.environ['HOME'] + except KeyError: + if os.name == 'posix': + raise HomeDirError,'undefined $HOME, IPython can not proceed.' + elif os.name == 'nt': + # For some strange reason, win9x returns 'nt' for os.name. + try: + return os.path.join(os.environ['HOMEDRIVE'],os.environ['HOMEPATH']) + except: + try: + # Use the registry to get the 'My Documents' folder. + import _winreg as wreg + key = wreg.OpenKey(wreg.HKEY_CURRENT_USER, + "Software\Microsoft\Windows\CurrentVersion\Explorer\Shell Folders") + homedir = wreg.QueryValueEx(key,'Personal')[0] + key.Close() + return homedir + except: + return 'C:\\' + elif os.name == 'dos': + # Desperate, may do absurd things in classic MacOS. May work under DOS. + return 'C:\\' + else: + raise HomeDirError,'support for your operating system not implemented.' + +#**************************************************************************** +# strings and text + +class LSString(str): + """String derivative with a special access attributes. + + These are normal strings, but with the special attributes: + + .l (or .list) : value as list (split on newlines). + .n (or .nlstr): original value (the string itself). + .s (or .spstr): value as whitespace-separated string. + + Any values which require transformations are computed only once and + cached. + + Such strings are very useful to efficiently interact with the shell, which + typically only understands whitespace-separated options for commands.""" + + def get_list(self): + try: + return self.__list + except AttributeError: + self.__list = self.split('\n') + return self.__list + + l = list = property(get_list) + + def get_spstr(self): + try: + return self.__spstr + except AttributeError: + self.__spstr = self.replace('\n',' ') + return self.__spstr + + s = spstr = property(get_spstr) + + def get_nlstr(self): + return self + + n = nlstr = property(get_nlstr) + +class SList(list): + """List derivative with a special access attributes. + + These are normal lists, but with the special attributes: + + .l (or .list) : value as list (the list itself). + .n (or .nlstr): value as a string, joined on newlines. + .s (or .spstr): value as a string, joined on spaces. + + Any values which require transformations are computed only once and + cached.""" + + def get_list(self): + return self + + l = list = property(get_list) + + def get_spstr(self): + try: + return self.__spstr + except AttributeError: + self.__spstr = ' '.join(self) + return self.__spstr + + s = spstr = property(get_spstr) + + def get_nlstr(self): + try: + return self.__nlstr + except AttributeError: + self.__nlstr = '\n'.join(self) + return self.__nlstr + + n = nlstr = property(get_nlstr) + +def raw_input_multi(header='', ps1='==> ', ps2='..> ',terminate_str = '.'): + """Take multiple lines of input. + + A list with each line of input as a separate element is returned when a + termination string is entered (defaults to a single '.'). Input can also + terminate via EOF (^D in Unix, ^Z-RET in Windows). + + Lines of input which end in \\ are joined into single entries (and a + secondary continuation prompt is issued as long as the user terminates + lines with \\). This allows entering very long strings which are still + meant to be treated as single entities. + """ + + try: + if header: + header += '\n' + lines = [raw_input(header + ps1)] + except EOFError: + return [] + terminate = [terminate_str] + try: + while lines[-1:] != terminate: + new_line = raw_input(ps1) + while new_line.endswith('\\'): + new_line = new_line[:-1] + raw_input(ps2) + lines.append(new_line) + + return lines[:-1] # don't return the termination command + except EOFError: + print + return lines + +#---------------------------------------------------------------------------- +def raw_input_ext(prompt='', ps2='... '): + """Similar to raw_input(), but accepts extended lines if input ends with \\.""" + + line = raw_input(prompt) + while line.endswith('\\'): + line = line[:-1] + raw_input(ps2) + return line + +#---------------------------------------------------------------------------- +def ask_yes_no(prompt,default=None): + """Asks a question and returns an integer 1/0 (y/n) answer. + + If default is given (one of 'y','n'), it is used if the user input is + empty. Otherwise the question is repeated until an answer is given. + If EOF occurs 20 times consecutively, the default answer is assumed, + or if there is no default, an exception is raised to prevent infinite + loops. + + Valid answers are: y/yes/n/no (match is not case sensitive).""" + + answers = {'y':1,'n':0,'yes':1,'no':0} + ans = None + eofs, max_eofs = 0, 20 + while ans not in answers.keys(): + try: + ans = raw_input(prompt+' ').lower() + if not ans: # response was an empty string + ans = default + eofs = 0 + except (EOFError,KeyboardInterrupt): + eofs = eofs + 1 + if eofs >= max_eofs: + if default in answers.keys(): + ans = default + else: + raise + + return answers[ans] + +#---------------------------------------------------------------------------- +class EvalDict: + """ + Emulate a dict which evaluates its contents in the caller's frame. + + Usage: + >>>number = 19 + >>>text = "python" + >>>print "%(text.capitalize())s %(number/9.0).1f rules!" % EvalDict() + """ + + # This version is due to sismex01@hebmex.com on c.l.py, and is basically a + # modified (shorter) version of: + # http://aspn.activestate.com/ASPN/Cookbook/Python/Recipe/66018 by + # Skip Montanaro (skip@pobox.com). + + def __getitem__(self, name): + frame = sys._getframe(1) + return eval(name, frame.f_globals, frame.f_locals) + +EvalString = EvalDict # for backwards compatibility +#---------------------------------------------------------------------------- +def qw(words,flat=0,sep=None,maxsplit=-1): + """Similar to Perl's qw() operator, but with some more options. + + qw(words,flat=0,sep=' ',maxsplit=-1) -> words.split(sep,maxsplit) + + words can also be a list itself, and with flat=1, the output will be + recursively flattened. Examples: + + >>> qw('1 2') + ['1', '2'] + >>> qw(['a b','1 2',['m n','p q']]) + [['a', 'b'], ['1', '2'], [['m', 'n'], ['p', 'q']]] + >>> qw(['a b','1 2',['m n','p q']],flat=1) + ['a', 'b', '1', '2', 'm', 'n', 'p', 'q'] """ + + if type(words) in StringTypes: + return [word.strip() for word in words.split(sep,maxsplit) + if word and not word.isspace() ] + if flat: + return flatten(map(qw,words,[1]*len(words))) + return map(qw,words) + +#---------------------------------------------------------------------------- +def qwflat(words,sep=None,maxsplit=-1): + """Calls qw(words) in flat mode. It's just a convenient shorthand.""" + return qw(words,1,sep,maxsplit) + +#----------------------------------------------------------------------------- +def list_strings(arg): + """Always return a list of strings, given a string or list of strings + as input.""" + + if type(arg) in StringTypes: return [arg] + else: return arg + +#---------------------------------------------------------------------------- +def grep(pat,list,case=1): + """Simple minded grep-like function. + grep(pat,list) returns occurrences of pat in list, None on failure. + + It only does simple string matching, with no support for regexps. Use the + option case=0 for case-insensitive matching.""" + + # This is pretty crude. At least it should implement copying only references + # to the original data in case it's big. Now it copies the data for output. + out=[] + if case: + for term in list: + if term.find(pat)>-1: out.append(term) + else: + lpat=pat.lower() + for term in list: + if term.lower().find(lpat)>-1: out.append(term) + + if len(out): return out + else: return None + +#---------------------------------------------------------------------------- +def dgrep(pat,*opts): + """Return grep() on dir()+dir(__builtins__). + + A very common use of grep() when working interactively.""" + + return grep(pat,dir(__main__)+dir(__main__.__builtins__),*opts) + +#---------------------------------------------------------------------------- +def idgrep(pat): + """Case-insensitive dgrep()""" + + return dgrep(pat,0) + +#---------------------------------------------------------------------------- +def igrep(pat,list): + """Synonym for case-insensitive grep.""" + + return grep(pat,list,case=0) + +#---------------------------------------------------------------------------- +def indent(str,nspaces=4,ntabs=0): + """Indent a string a given number of spaces or tabstops. + + indent(str,nspaces=4,ntabs=0) -> indent str by ntabs+nspaces. + """ + if str is None: + return + ind = '\t'*ntabs+' '*nspaces + outstr = '%s%s' % (ind,str.replace(os.linesep,os.linesep+ind)) + if outstr.endswith(os.linesep+ind): + return outstr[:-len(ind)] + else: + return outstr + +#----------------------------------------------------------------------------- +def native_line_ends(filename,backup=1): + """Convert (in-place) a file to line-ends native to the current OS. + + If the optional backup argument is given as false, no backup of the + original file is left. """ + + backup_suffixes = {'posix':'~','dos':'.bak','nt':'.bak','mac':'.bak'} + + bak_filename = filename + backup_suffixes[os.name] + + original = open(filename).read() + shutil.copy2(filename,bak_filename) + try: + new = open(filename,'wb') + new.write(os.linesep.join(original.splitlines())) + new.write(os.linesep) # ALWAYS put an eol at the end of the file + new.close() + except: + os.rename(bak_filename,filename) + if not backup: + try: + os.remove(bak_filename) + except: + pass + +#---------------------------------------------------------------------------- +def get_pager_cmd(pager_cmd = None): + """Return a pager command. + + Makes some attempts at finding an OS-correct one.""" + + if os.name == 'posix': + default_pager_cmd = 'less -r' # -r for color control sequences + elif os.name in ['nt','dos']: + default_pager_cmd = 'type' + + if pager_cmd is None: + try: + pager_cmd = os.environ['PAGER'] + except: + pager_cmd = default_pager_cmd + return pager_cmd + +#----------------------------------------------------------------------------- +def get_pager_start(pager,start): + """Return the string for paging files with an offset. + + This is the '+N' argument which less and more (under Unix) accept. + """ + + if pager in ['less','more']: + if start: + start_string = '+' + str(start) + else: + start_string = '' + else: + start_string = '' + return start_string + +#---------------------------------------------------------------------------- +def page_dumb(strng,start=0,screen_lines=25): + """Very dumb 'pager' in Python, for when nothing else works. + + Only moves forward, same interface as page(), except for pager_cmd and + mode.""" + + out_ln = strng.splitlines()[start:] + screens = chop(out_ln,screen_lines-1) + if len(screens) == 1: + print >>Term.cout, os.linesep.join(screens[0]) + else: + for scr in screens[0:-1]: + print >>Term.cout, os.linesep.join(scr) + ans = raw_input('---Return to continue, q to quit--- ') + if ans.lower().startswith('q'): + return + print >>Term.cout, os.linesep.join(screens[-1]) + +#---------------------------------------------------------------------------- +def page(strng,start=0,screen_lines=0,pager_cmd = None): + """Print a string, piping through a pager after a certain length. + + The screen_lines parameter specifies the number of *usable* lines of your + terminal screen (total lines minus lines you need to reserve to show other + information). + + If you set screen_lines to a number <=0, page() will try to auto-determine + your screen size and will only use up to (screen_size+screen_lines) for + printing, paging after that. That is, if you want auto-detection but need + to reserve the bottom 3 lines of the screen, use screen_lines = -3, and for + auto-detection without any lines reserved simply use screen_lines = 0. + + If a string won't fit in the allowed lines, it is sent through the + specified pager command. If none given, look for PAGER in the environment, + and ultimately default to less. + + If no system pager works, the string is sent through a 'dumb pager' + written in python, very simplistic. + """ + + # Ugly kludge, but calling curses.initscr() flat out crashes in emacs + TERM = os.environ.get('TERM','dumb') + if TERM in ['dumb','emacs'] and os.name != 'nt': + print strng + return + # chop off the topmost part of the string we don't want to see + str_lines = strng.split(os.linesep)[start:] + str_toprint = os.linesep.join(str_lines) + num_newlines = len(str_lines) + len_str = len(str_toprint) + + # Dumb heuristics to guesstimate number of on-screen lines the string + # takes. Very basic, but good enough for docstrings in reasonable + # terminals. If someone later feels like refining it, it's not hard. + numlines = max(num_newlines,int(len_str/80)+1) + + screen_lines_def = 25 # default value if we can't auto-determine + + # 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 + else: + # curses causes problems on many terminals other than xterm. + use_curses = 0 + 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 + else: + screen_lines += screen_lines_def + + #print 'numlines',numlines,'screenlines',screen_lines # dbg + if numlines <= screen_lines : + #print '*** normal print' # dbg + print >>Term.cout, str_toprint + else: + # Try to open pager and default to internal one if that fails. + # All failure modes are tagged as 'retval=1', to match the return + # value of a failed system command. If any intermediate attempt + # sets retval to 1, at the end we resort to our own page_dumb() pager. + pager_cmd = get_pager_cmd(pager_cmd) + pager_cmd += ' ' + get_pager_start(pager_cmd,start) + if os.name == 'nt': + if pager_cmd.startswith('type'): + # The default WinXP 'type' command is failing on complex strings. + retval = 1 + else: + tmpname = tempfile.mktemp('.txt') + tmpfile = file(tmpname,'wt') + tmpfile.write(strng) + tmpfile.close() + cmd = "%s < %s" % (pager_cmd,tmpname) + if os.system(cmd): + retval = 1 + else: + retval = None + os.remove(tmpname) + else: + try: + retval = None + # if I use popen4, things hang. No idea why. + #pager,shell_out = os.popen4(pager_cmd) + pager = os.popen(pager_cmd,'w') + pager.write(strng) + pager.close() + retval = pager.close() # success returns None + except IOError,msg: # broken pipe when user quits + if msg.args == (32,'Broken pipe'): + retval = None + else: + retval = 1 + except OSError: + # Other strange problems, sometimes seen in Win2k/cygwin + retval = 1 + if retval is not None: + page_dumb(strng,screen_lines=screen_lines) + +#---------------------------------------------------------------------------- +def page_file(fname,start = 0, pager_cmd = None): + """Page a file, using an optional pager command and starting line. + """ + + pager_cmd = get_pager_cmd(pager_cmd) + pager_cmd += ' ' + get_pager_start(pager_cmd,start) + + try: + if os.environ['TERM'] in ['emacs','dumb']: + raise EnvironmentError + xsys(pager_cmd + ' ' + fname) + except: + try: + if start > 0: + start -= 1 + page(open(fname).read(),start) + except: + print 'Unable to show file',`fname` + +#---------------------------------------------------------------------------- +def snip_print(str,width = 75,print_full = 0,header = ''): + """Print a string snipping the midsection to fit in width. + + print_full: mode control: + - 0: only snip long strings + - 1: send to page() directly. + - 2: snip long strings and ask for full length viewing with page() + Return 1 if snipping was necessary, 0 otherwise.""" + + if print_full == 1: + page(header+str) + return 0 + + print header, + if len(str) < width: + print str + snip = 0 + else: + whalf = int((width -5)/2) + print str[:whalf] + ' <...> ' + str[-whalf:] + snip = 1 + if snip and print_full == 2: + if raw_input(header+' Snipped. View (y/n)? [N]').lower() == 'y': + page(str) + return snip + +#**************************************************************************** +# lists, dicts and structures + +def belong(candidates,checklist): + """Check whether a list of items appear in a given list of options. + + Returns a list of 1 and 0, one for each candidate given.""" + + return [x in checklist for x in candidates] + +#---------------------------------------------------------------------------- +def uniq_stable(elems): + """uniq_stable(elems) -> list + + Return from an iterable, a list of all the unique elements in the input, + but maintaining the order in which they first appear. + + A naive solution to this problem which just makes a dictionary with the + elements as keys fails to respect the stability condition, since + dictionaries are unsorted by nature. + + Note: All elements in the input must be valid dictionary keys for this + routine to work, as it internally uses a dictionary for efficiency + reasons.""" + + unique = [] + unique_dict = {} + for nn in elems: + if nn not in unique_dict: + unique.append(nn) + unique_dict[nn] = None + return unique + +#---------------------------------------------------------------------------- +class NLprinter: + """Print an arbitrarily nested list, indicating index numbers. + + An instance of this class called nlprint is available and callable as a + function. + + nlprint(list,indent=' ',sep=': ') -> prints indenting each level by 'indent' + and using 'sep' to separate the index from the value. """ + + def __init__(self): + self.depth = 0 + + def __call__(self,lst,pos='',**kw): + """Prints the nested list numbering levels.""" + kw.setdefault('indent',' ') + kw.setdefault('sep',': ') + kw.setdefault('start',0) + kw.setdefault('stop',len(lst)) + # we need to remove start and stop from kw so they don't propagate + # into a recursive call for a nested list. + start = kw['start']; del kw['start'] + stop = kw['stop']; del kw['stop'] + if self.depth == 0 and 'header' in kw.keys(): + print kw['header'] + + for idx in range(start,stop): + elem = lst[idx] + if type(elem)==type([]): + self.depth += 1 + self.__call__(elem,itpl('$pos$idx,'),**kw) + self.depth -= 1 + else: + printpl(kw['indent']*self.depth+'$pos$idx$kw["sep"]$elem') + +nlprint = NLprinter() +#---------------------------------------------------------------------------- +def all_belong(candidates,checklist): + """Check whether a list of items ALL appear in a given list of options. + + Returns a single 1 or 0 value.""" + + return 1-(0 in [x in checklist for x in candidates]) + +#---------------------------------------------------------------------------- +def sort_compare(lst1,lst2,inplace = 1): + """Sort and compare two lists. + + By default it does it in place, thus modifying the lists. Use inplace = 0 + to avoid that (at the cost of temporary copy creation).""" + if not inplace: + lst1 = lst1[:] + lst2 = lst2[:] + lst1.sort(); lst2.sort() + return lst1 == lst2 + +#---------------------------------------------------------------------------- +def mkdict(**kwargs): + """Return a dict from a keyword list. + + It's just syntactic sugar for making ditcionary creation more convenient: + # the standard way + >>>data = { 'red' : 1, 'green' : 2, 'blue' : 3 } + # a cleaner way + >>>data = dict(red=1, green=2, blue=3) + + If you need more than this, look at the Struct() class.""" + + return kwargs + +#---------------------------------------------------------------------------- +def list2dict(lst): + """Takes a list of (key,value) pairs and turns it into a dict.""" + + dic = {} + for k,v in lst: dic[k] = v + return dic + +#---------------------------------------------------------------------------- +def list2dict2(lst,default=''): + """Takes a list and turns it into a dict. + Much slower than list2dict, but more versatile. This version can take + lists with sublists of arbitrary length (including sclars).""" + + dic = {} + for elem in lst: + if type(elem) in (types.ListType,types.TupleType): + size = len(elem) + if size == 0: + pass + elif size == 1: + dic[elem] = default + else: + k,v = elem[0], elem[1:] + if len(v) == 1: v = v[0] + dic[k] = v + else: + dic[elem] = default + return dic + +#---------------------------------------------------------------------------- +def flatten(seq): + """Flatten a list of lists (NOT recursive, only works for 2d lists).""" + + # bug in python??? (YES. Fixed in 2.2, let's leave the kludgy fix in). + + # if the x=0 isn't made, a *global* variable x is left over after calling + # this function, with the value of the last element in the return + # list. This does seem like a bug big time to me. + + # the problem is fixed with the x=0, which seems to force the creation of + # a local name + + x = 0 + return [x for subseq in seq for x in subseq] + +#---------------------------------------------------------------------------- +def get_slice(seq,start=0,stop=None,step=1): + """Get a slice of a sequence with variable step. Specify start,stop,step.""" + if stop == None: + stop = len(seq) + item = lambda i: seq[i] + return map(item,xrange(start,stop,step)) + +#---------------------------------------------------------------------------- +def chop(seq,size): + """Chop a sequence into chunks of the given size.""" + chunk = lambda i: seq[i:i+size] + return map(chunk,xrange(0,len(seq),size)) + +#---------------------------------------------------------------------------- +def with(object, **args): + """Set multiple attributes for an object, similar to Pascal's with. + + Example: + with(jim, + born = 1960, + haircolour = 'Brown', + eyecolour = 'Green') + + Credit: Greg Ewing, in + http://mail.python.org/pipermail/python-list/2001-May/040703.html""" + + object.__dict__.update(args) + +#---------------------------------------------------------------------------- +def setattr_list(obj,alist,nspace = None): + """Set a list of attributes for an object taken from a namespace. + + setattr_list(obj,alist,nspace) -> sets in obj all the attributes listed in + alist with their values taken from nspace, which must be a dict (something + like locals() will often do) If nspace isn't given, locals() of the + *caller* is used, so in most cases you can omit it. + + Note that alist can be given as a string, which will be automatically + split into a list on whitespace. If given as a list, it must be a list of + *strings* (the variable names themselves), not of variables.""" + + # this grabs the local variables from the *previous* call frame -- that is + # the locals from the function that called setattr_list(). + # - snipped from weave.inline() + if nspace is None: + call_frame = sys._getframe().f_back + nspace = call_frame.f_locals + + if type(alist) in StringTypes: + alist = alist.split() + for attr in alist: + val = eval(attr,nspace) + setattr(obj,attr,val) + +#---------------------------------------------------------------------------- +def getattr_list(obj,alist,*args): + """getattr_list(obj,alist[, default]) -> attribute list. + + Get a list of named attributes for an object. When a default argument is + given, it is returned when the attribute doesn't exist; without it, an + exception is raised in that case. + + Note that alist can be given as a string, which will be automatically + split into a list on whitespace. If given as a list, it must be a list of + *strings* (the variable names themselves), not of variables.""" + + if type(alist) in StringTypes: + alist = alist.split() + if args: + if len(args)==1: + default = args[0] + return map(lambda attr: getattr(obj,attr,default),alist) + else: + raise ValueError,'getattr_list() takes only one optional argument' + else: + return map(lambda attr: getattr(obj,attr),alist) + +#---------------------------------------------------------------------------- +def map_method(method,object_list,*argseq,**kw): + """map_method(method,object_list,*args,**kw) -> list + + Return a list of the results of applying the methods to the items of the + argument sequence(s). If more than one sequence is given, the method is + called with an argument list consisting of the corresponding item of each + sequence. All sequences must be of the same length. + + Keyword arguments are passed verbatim to all objects called. + + This is Python code, so it's not nearly as fast as the builtin map().""" + + out_list = [] + idx = 0 + for object in object_list: + try: + handler = getattr(object, method) + except AttributeError: + out_list.append(None) + else: + if argseq: + args = map(lambda lst:lst[idx],argseq) + #print 'ob',object,'hand',handler,'ar',args # dbg + out_list.append(handler(args,**kw)) + else: + out_list.append(handler(**kw)) + idx += 1 + return out_list + +#---------------------------------------------------------------------------- +# Proposed popitem() extension, written as a method + +class NotGiven: pass + +def popkey(dct,key,default=NotGiven): + """Return dct[key] and delete dct[key]. + + If default is given, return it if dct[key] doesn't exist, otherwise raise + KeyError. """ + + try: + val = dct[key] + except KeyError: + if default is NotGiven: + raise + else: + return default + else: + del dct[key] + return val +#*************************** end of file <genutils.py> ********************** + diff --git a/IPython/hooks.py b/IPython/hooks.py new file mode 100644 index 0000000..1c02757 --- /dev/null +++ b/IPython/hooks.py @@ -0,0 +1,72 @@ +"""hooks for IPython. + +In Python, it is possible to overwrite any method of any object if you really +want to. But IPython exposes a few 'hooks', methods which are _designed_ to +be overwritten by users for customization purposes. This module defines the +default versions of all such hooks, which get used by IPython if not +overridden by the user. + +hooks are simple functions, but they should be declared with 'self' as their +first argument, because when activated they are registered into IPython as +instance methods. The self argument will be the IPython running instance +itself, so hooks have full access to the entire IPython object. + +If you wish to define a new hook and activate it, you need to put the +necessary code into a python file which can be either imported or execfile()'d +from within your ipythonrc configuration. + +For example, suppose that you have a module called 'myiphooks' in your +PYTHONPATH, which contains the following definition: + +import os +def calljed(self,filename, linenum): + "My editor hook calls the jed editor directly." + print "Calling my own editor, jed ..." + os.system('jed +%d %s' % (linenum,filename)) + +You can then execute the following line of code to make it the new IPython +editor hook, after having imported 'myiphooks': + +ip_set_hook('editor',myiphooks.calljed) + +The ip_set_hook function is put by IPython into the builtin namespace, so it +is always available from all running code. + +$Id: hooks.py 535 2005-03-02 08:42:25Z fperez $""" + +#***************************************************************************** +# Copyright (C) 2005 Fernando Perez. <fperez@colorado.edu> +# +# Distributed under the terms of the BSD License. The full license is in +# the file COPYING, distributed as part of this software. +#***************************************************************************** + +from IPython import Release +__author__ = '%s <%s>' % Release.authors['Fernando'] +__license__ = Release.license +__version__ = Release.version + +import os + +# List here all the default hooks. For now it's just the editor, but over +# time we'll move here all the public API for user-accessible things. +__all__ = ['editor'] + +def editor(self,filename, linenum): + """Open the default editor at the given filename and linenumber. + + This is IPython's default editor hook, you can use it as an example to + write your own modified one. To set your own editor function as the + new editor hook, call ip_set_hook('editor',yourfunc).""" + + # IPython configures a default editor at startup by reading $EDITOR from + # the environment, and falling back on vi (unix) or notepad (win32). + editor = self.rc.editor + + # marker for at which line to open the file (for existing objects) + if linenum is None or editor=='notepad': + linemark = '' + else: + linemark = '+%d' % linenum + # Call the actual editor + os.system('%s %s %s' % (editor,linemark,filename)) diff --git a/IPython/iplib.py b/IPython/iplib.py new file mode 100644 index 0000000..434c709 --- /dev/null +++ b/IPython/iplib.py @@ -0,0 +1,2084 @@ +# -*- coding: utf-8 -*- +""" +IPython -- An enhanced Interactive Python + +Requires Python 2.1 or newer. + +This file contains all the classes and helper functions specific to IPython. + +$Id: iplib.py 602 2005-06-09 03:02:30Z fperez $ +""" + +#***************************************************************************** +# Copyright (C) 2001 Janko Hauser <jhauser@zscout.de> and +# Copyright (C) 2001-2004 Fernando Perez. <fperez@colorado.edu> +# +# Distributed under the terms of the BSD License. The full license is in +# the file COPYING, distributed as part of this software. +# +# Note: this code originally subclassed code.InteractiveConsole from the +# Python standard library. Over time, much of that class has been copied +# verbatim here for modifications which could not be accomplished by +# subclassing. The Python License (sec. 2) allows for this, but it's always +# nice to acknowledge credit where credit is due. +#***************************************************************************** + +#**************************************************************************** +# Modules and globals + +from __future__ import generators # for 2.2 backwards-compatibility + +from IPython import Release +__author__ = '%s <%s>\n%s <%s>' % \ + ( Release.authors['Janko'] + Release.authors['Fernando'] ) +__license__ = Release.license +__version__ = Release.version + +# Python standard modules +import __main__ +import __builtin__ +import exceptions +import keyword +import new +import os, sys, shutil +import code, glob, types, re +import string, StringIO +import inspect, pydoc +import bdb, pdb +import UserList # don't subclass list so this works with Python2.1 +from pprint import pprint, pformat +import cPickle as pickle +import traceback + +# IPython's own modules +import IPython +from IPython import OInspect,PyColorize,ultraTB +from IPython.ultraTB import ColorScheme,ColorSchemeTable # too long names +from IPython.Logger import Logger +from IPython.Magic import Magic,magic2python,shlex_split +from IPython.usage import cmd_line_usage,interactive_usage +from IPython.Struct import Struct +from IPython.Itpl import Itpl,itpl,printpl,ItplNS,itplns +from IPython.FakeModule import FakeModule +from IPython.background_jobs import BackgroundJobManager +from IPython.genutils import * + +# Global pointer to the running + +# store the builtin raw_input globally, and use this always, in case user code +# overwrites it (like wx.py.PyShell does) +raw_input_original = raw_input + +# declares Python 2.2 compatibility symbols: +try: + enumerate +except NameError: + def enumerate(obj): + i = -1 + for item in obj: + i += 1 + yield i, item +#**************************************************************************** +# Some utility function definitions + +class Bunch: pass + +def esc_quotes(strng): + """Return the input string with single and double quotes escaped out""" + + return strng.replace('"','\\"').replace("'","\\'") + +def import_fail_info(mod_name,fns=None): + """Inform load failure for a module.""" + + if fns == None: + warn("Loading of %s failed.\n" % (mod_name,)) + else: + warn("Loading of %s from %s failed.\n" % (fns,mod_name)) + +def qw_lol(indata): + """qw_lol('a b') -> [['a','b']], + otherwise it's just a call to qw(). + + We need this to make sure the modules_some keys *always* end up as a + list of lists.""" + + if type(indata) in StringTypes: + return [qw(indata)] + else: + return qw(indata) + +def ipmagic(arg_s): + """Call a magic function by name. + + Input: a string containing the name of the magic function to call and any + additional arguments to be passed to the magic. + + ipmagic('name -opt foo bar') is equivalent to typing at the ipython + prompt: + + In[1]: %name -opt foo bar + + To call a magic without arguments, simply use ipmagic('name'). + + This provides a proper Python function to call IPython's magics in any + valid Python code you can type at the interpreter, including loops and + compound statements. It is added by IPython to the Python builtin + namespace upon initialization.""" + + args = arg_s.split(' ',1) + magic_name = args[0] + if magic_name.startswith(__IPYTHON__.ESC_MAGIC): + magic_name = magic_name[1:] + try: + magic_args = args[1] + except IndexError: + magic_args = '' + fn = getattr(__IPYTHON__,'magic_'+magic_name,None) + if fn is None: + error("Magic function `%s` not found." % magic_name) + else: + magic_args = __IPYTHON__.var_expand(magic_args) + return fn(magic_args) + +def ipalias(arg_s): + """Call an alias by name. + + Input: a string containing the name of the alias to call and any + additional arguments to be passed to the magic. + + ipalias('name -opt foo bar') is equivalent to typing at the ipython + prompt: + + In[1]: name -opt foo bar + + To call an alias without arguments, simply use ipalias('name'). + + This provides a proper Python function to call IPython's aliases in any + valid Python code you can type at the interpreter, including loops and + compound statements. It is added by IPython to the Python builtin + namespace upon initialization.""" + + args = arg_s.split(' ',1) + alias_name = args[0] + try: + alias_args = args[1] + except IndexError: + alias_args = '' + if alias_name in __IPYTHON__.alias_table: + __IPYTHON__.call_alias(alias_name,alias_args) + else: + error("Alias `%s` not found." % alias_name) + +#----------------------------------------------------------------------------- +# Local use classes +try: + from IPython import FlexCompleter + + class MagicCompleter(FlexCompleter.Completer): + """Extension of the completer class to work on %-prefixed lines.""" + + def __init__(self,shell,namespace=None,omit__names=0,alias_table=None): + """MagicCompleter() -> completer + + Return a completer object suitable for use by the readline library + via readline.set_completer(). + + Inputs: + + - shell: a pointer to the ipython shell itself. This is needed + because this completer knows about magic functions, and those can + only be accessed via the ipython instance. + + - namespace: an optional dict where completions are performed. + + - The optional omit__names parameter sets the completer to omit the + 'magic' names (__magicname__) for python objects unless the text + to be completed explicitly starts with one or more underscores. + + - If alias_table is supplied, it should be a dictionary of aliases + to complete. """ + + FlexCompleter.Completer.__init__(self,namespace) + self.magic_prefix = shell.name+'.magic_' + self.magic_escape = shell.ESC_MAGIC + self.readline = FlexCompleter.readline + delims = self.readline.get_completer_delims() + delims = delims.replace(self.magic_escape,'') + self.readline.set_completer_delims(delims) + self.get_line_buffer = self.readline.get_line_buffer + self.omit__names = omit__names + self.merge_completions = shell.rc.readline_merge_completions + + if alias_table is None: + alias_table = {} + self.alias_table = alias_table + # Regexp to split filenames with spaces in them + self.space_name_re = re.compile(r'([^\\] )') + # Hold a local ref. to glob.glob for speed + self.glob = glob.glob + # Special handling of backslashes needed in win32 platforms + if sys.platform == "win32": + self.clean_glob = self._clean_glob_win32 + else: + self.clean_glob = self._clean_glob + self.matchers = [self.python_matches, + self.file_matches, + self.alias_matches, + self.python_func_kw_matches] + + # Code contributed by Alex Schmolck, for ipython/emacs integration + def all_completions(self, text): + """Return all possible completions for the benefit of emacs.""" + + completions = [] + try: + for i in xrange(sys.maxint): + res = self.complete(text, i) + + if not res: break + + completions.append(res) + #XXX workaround for ``notDefined.<tab>`` + except NameError: + pass + return completions + # /end Alex Schmolck code. + + def _clean_glob(self,text): + return self.glob("%s*" % text) + + def _clean_glob_win32(self,text): + return [f.replace("\\","/") + for f in self.glob("%s*" % text)] + + def file_matches(self, text): + """Match filneames, expanding ~USER type strings. + + Most of the seemingly convoluted logic in this completer is an + attempt to handle filenames with spaces in them. And yet it's not + quite perfect, because Python's readline doesn't expose all of the + GNU readline details needed for this to be done correctly. + + For a filename with a space in it, the printed completions will be + only the parts after what's already been typed (instead of the + full completions, as is normally done). I don't think with the + current (as of Python 2.3) Python readline it's possible to do + better.""" + + #print 'Completer->file_matches: <%s>' % text # dbg + + # chars that require escaping with backslash - i.e. chars + # that readline treats incorrectly as delimiters, but we + # don't want to treat as delimiters in filename matching + # when escaped with backslash + + protectables = ' ()[]{}' + + def protect_filename(s): + return "".join([(ch in protectables and '\\' + ch or ch) + for ch in s]) + + lbuf = self.get_line_buffer()[:self.readline.get_endidx()] + open_quotes = 0 # track strings with open quotes + try: + lsplit = shlex_split(lbuf)[-1] + except ValueError: + # typically an unmatched ", or backslash without escaped char. + if lbuf.count('"')==1: + open_quotes = 1 + lsplit = lbuf.split('"')[-1] + elif lbuf.count("'")==1: + open_quotes = 1 + lsplit = lbuf.split("'")[-1] + else: + return None + except IndexError: + # tab pressed on empty line + lsplit = "" + + if lsplit != protect_filename(lsplit): + # if protectables are found, do matching on the whole escaped + # name + has_protectables = 1 + text0,text = text,lsplit + else: + has_protectables = 0 + text = os.path.expanduser(text) + + if text == "": + return [protect_filename(f) for f in self.glob("*")] + + m0 = self.clean_glob(text.replace('\\','')) + if has_protectables: + # If we had protectables, we need to revert our changes to the + # beginning of filename so that we don't double-write the part + # of the filename we have so far + len_lsplit = len(lsplit) + matches = [text0 + protect_filename(f[len_lsplit:]) for f in m0] + else: + if open_quotes: + # if we have a string with an open quote, we don't need to + # protect the names at all (and we _shouldn't_, as it + # would cause bugs when the filesystem call is made). + matches = m0 + else: + matches = [protect_filename(f) for f in m0] + 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. + matches[0] += '/' + return matches + + def alias_matches(self, text): + """Match internal system aliases""" + #print 'Completer->alias_matches:',text # dbg + text = os.path.expanduser(text) + aliases = self.alias_table.keys() + if text == "": + return aliases + else: + return [alias for alias in aliases if alias.startswith(text)] + + def python_matches(self,text): + """Match attributes or global python names""" + #print 'Completer->python_matches' # dbg + if "." in text: + try: + matches = self.attr_matches(text) + if text.endswith('.') and self.omit__names: + if self.omit__names == 1: + # true if txt is _not_ a __ name, false otherwise: + no__name = (lambda txt: + re.match(r'.*\.__.*?__',txt) is None) + else: + # true if txt is _not_ a _ name, false otherwise: + no__name = (lambda txt: + re.match(r'.*\._.*?',txt) is None) + matches = filter(no__name, matches) + except NameError: + # catches <undefined attributes>.<tab> + matches = [] + else: + matches = self.global_matches(text) + # this is so completion finds magics when automagic is on: + if matches == [] and not text.startswith(os.sep): + matches = self.attr_matches(self.magic_prefix+text) + return matches + + def _default_arguments(self, obj): + """Return the list of default arguments of obj if it is callable, + or empty list otherwise.""" + + if not (inspect.isfunction(obj) or inspect.ismethod(obj)): + # for classes, check for __init__,__new__ + if inspect.isclass(obj): + obj = (getattr(obj,'__init__',None) or + getattr(obj,'__new__',None)) + # for all others, check if they are __call__able + elif hasattr(obj, '__call__'): + obj = obj.__call__ + # XXX: is there a way to handle the builtins ? + try: + args,_,_1,defaults = inspect.getargspec(obj) + if defaults: + return args[-len(defaults):] + except TypeError: pass + return [] + + def python_func_kw_matches(self,text): + """Match named parameters (kwargs) of the last open function""" + + if "." in text: # a parameter cannot be dotted + return [] + try: regexp = self.__funcParamsRegex + except AttributeError: + regexp = self.__funcParamsRegex = re.compile(r''' + '.*?' | # single quoted strings or + ".*?" | # double quoted strings or + \w+ | # identifier + \S # other characters + ''', re.VERBOSE | re.DOTALL) + # 1. find the nearest identifier that comes before an unclosed + # parenthesis e.g. for "foo (1+bar(x), pa", the candidate is "foo" + tokens = regexp.findall(self.get_line_buffer()) + tokens.reverse() + iterTokens = iter(tokens); openPar = 0 + for token in iterTokens: + if token == ')': + openPar -= 1 + elif token == '(': + openPar += 1 + if openPar > 0: + # found the last unclosed parenthesis + break + else: + return [] + # 2. Concatenate any dotted names (e.g. "foo.bar" for "foo.bar(x, pa" ) + ids = [] + isId = re.compile(r'\w+$').match + while True: + try: + ids.append(iterTokens.next()) + if not isId(ids[-1]): + ids.pop(); break + if not iterTokens.next() == '.': + break + except StopIteration: + break + # lookup the candidate callable matches either using global_matches + # or attr_matches for dotted names + if len(ids) == 1: + callableMatches = self.global_matches(ids[0]) + else: + callableMatches = self.attr_matches('.'.join(ids[::-1])) + argMatches = [] + for callableMatch in callableMatches: + try: namedArgs = self._default_arguments(eval(callableMatch, + self.namespace)) + except: continue + for namedArg in namedArgs: + if namedArg.startswith(text): + argMatches.append("%s=" %namedArg) + return argMatches + + def complete(self, text, state): + """Return the next possible completion for 'text'. + + This is called successively with state == 0, 1, 2, ... until it + returns None. The completion should begin with 'text'. """ + + #print '\n*** COMPLETE: <%s> (%s)' % (text,state) # dbg + magic_escape = self.magic_escape + magic_prefix = self.magic_prefix + + try: + if text.startswith(magic_escape): + text = text.replace(magic_escape,magic_prefix) + elif text.startswith('~'): + text = os.path.expanduser(text) + if state == 0: + # Extend the list of completions with the results of each + # matcher, so we return results to the user from all + # namespaces. + if self.merge_completions: + self.matches = [] + for matcher in self.matchers: + self.matches.extend(matcher(text)) + else: + for matcher in self.matchers: + self.matches = matcher(text) + if self.matches: + break + + try: + return self.matches[state].replace(magic_prefix,magic_escape) + except IndexError: + return None + except: + # If completion fails, don't annoy the user. + pass + +except ImportError: + pass # no readline support + +except KeyError: + pass # Windows doesn't set TERM, it doesn't matter + + +class InputList(UserList.UserList): + """Class to store user input. + + It's basically a list, but slices return a string instead of a list, thus + allowing things like (assuming 'In' is an instance): + + exec In[4:7] + + or + + exec In[5:9] + In[14] + In[21:25]""" + + def __getslice__(self,i,j): + return ''.join(UserList.UserList.__getslice__(self,i,j)) + +#**************************************************************************** +# Local use exceptions +class SpaceInInput(exceptions.Exception): + pass + +#**************************************************************************** +# Main IPython class + +class InteractiveShell(code.InteractiveConsole, Logger, Magic): + """An enhanced console for Python.""" + + def __init__(self,name,usage=None,rc=Struct(opts=None,args=None), + user_ns = None,banner2='', + custom_exceptions=((),None)): + + # Put a reference to self in builtins so that any form of embedded or + # imported code can test for being inside IPython. + __builtin__.__IPYTHON__ = self + + # And load into builtins ipmagic/ipalias as well + __builtin__.ipmagic = ipmagic + __builtin__.ipalias = ipalias + + # Add to __builtin__ other parts of IPython's public API + __builtin__.ip_set_hook = self.set_hook + + # Keep in the builtins a flag for when IPython is active. We set it + # with setdefault so that multiple nested IPythons don't clobber one + # another. Each will increase its value by one upon being activated, + # which also gives us a way to determine the nesting level. + __builtin__.__dict__.setdefault('__IPYTHON__active',0) + + # Inform the user of ipython's fast exit magics. + _exit = ' Use %Exit or %Quit to exit without confirmation.' + __builtin__.exit += _exit + __builtin__.quit += _exit + + # Create the namespace where the user will operate: + + # FIXME. For some strange reason, __builtins__ is showing up at user + # level as a dict instead of a module. This is a manual fix, but I + # should really track down where the problem is coming from. Alex + # Schmolck reported this problem first. + + # A useful post by Alex Martelli on this topic: + # Re: inconsistent value from __builtins__ + # Von: Alex Martelli <aleaxit@yahoo.com> + # Datum: Freitag 01 Oktober 2004 04:45:34 nachmittags/abends + # Gruppen: comp.lang.python + # Referenzen: 1 + + # Michael Hohn <hohn@hooknose.lbl.gov> wrote: + # > >>> print type(builtin_check.get_global_binding('__builtins__')) + # > <type 'dict'> + # > >>> print type(__builtins__) + # > <type 'module'> + # > Is this difference in return value intentional? + + # Well, it's documented that '__builtins__' can be either a dictionary + # or a module, and it's been that way for a long time. Whether it's + # intentional (or sensible), I don't know. In any case, the idea is that + # if you need to access the built-in namespace directly, you should start + # with "import __builtin__" (note, no 's') which will definitely give you + # a module. Yeah, it's somewhat confusing:-(. + + if user_ns is None: + # Set __name__ to __main__ to better match the behavior of the + # normal interpreter. + self.user_ns = {'__name__' :'__main__', + '__builtins__' : __builtin__, + } + else: + self.user_ns = user_ns + + # The user namespace MUST have a pointer to the shell itself. + self.user_ns[name] = self + + # We need to insert into sys.modules something that looks like a + # module but which accesses the IPython namespace, for shelve and + # pickle to work interactively. Normally they rely on getting + # everything out of __main__, but for embedding purposes each IPython + # instance has its own private namespace, so we can't go shoving + # everything into __main__. + + try: + main_name = self.user_ns['__name__'] + except KeyError: + raise KeyError,'user_ns dictionary MUST have a "__name__" key' + else: + #print "pickle hack in place" # dbg + sys.modules[main_name] = FakeModule(self.user_ns) + + # List of input with multi-line handling. + # Fill its zero entry, user counter starts at 1 + self.input_hist = InputList(['\n']) + + # list of visited directories + self.dir_hist = [os.getcwd()] + + # dict of output history + self.output_hist = {} + + # dict of names to be treated as system aliases. Each entry in the + # alias table must be a 2-tuple of the form (N,name), where N is the + # number of positional arguments of the alias. + self.alias_table = {} + + # dict of things NOT to alias (keywords and builtins) + self.no_alias = {} + for key in keyword.kwlist: + self.no_alias[key] = 1 + self.no_alias.update(__builtin__.__dict__) + + # make global variables for user access to these + self.user_ns['_ih'] = self.input_hist + self.user_ns['_oh'] = self.output_hist + self.user_ns['_dh'] = self.dir_hist + + # user aliases to input and output histories + self.user_ns['In'] = self.input_hist + self.user_ns['Out'] = self.output_hist + + # Store the actual shell's name + self.name = name + + # Object variable to store code object waiting execution. This is + # used mainly by the multithreaded shells, but it can come in handy in + # other situations. No need to use a Queue here, since it's a single + # item which gets cleared once run. + self.code_to_run = None + self.code_to_run_src = '' # corresponding source + + # Job manager (for jobs run as background threads) + self.jobs = BackgroundJobManager() + # Put the job manager into builtins so it's always there. + __builtin__.jobs = self.jobs + + # escapes for automatic behavior on the command line + self.ESC_SHELL = '!' + self.ESC_HELP = '?' + self.ESC_MAGIC = '%' + self.ESC_QUOTE = ',' + self.ESC_QUOTE2 = ';' + self.ESC_PAREN = '/' + + # And their associated handlers + self.esc_handlers = {self.ESC_PAREN:self.handle_auto, + self.ESC_QUOTE:self.handle_auto, + self.ESC_QUOTE2:self.handle_auto, + self.ESC_MAGIC:self.handle_magic, + self.ESC_HELP:self.handle_help, + self.ESC_SHELL:self.handle_shell_escape, + } + + # class initializations + code.InteractiveConsole.__init__(self,locals = self.user_ns) + Logger.__init__(self,log_ns = self.user_ns) + Magic.__init__(self,self) + + # an ugly hack to get a pointer to the shell, so I can start writing + # magic code via this pointer instead of the current mixin salad. + Magic.set_shell(self,self) + + # hooks holds pointers used for user-side customizations + self.hooks = Struct() + + # Set all default hooks, defined in the IPython.hooks module. + hooks = IPython.hooks + for hook_name in hooks.__all__: + self.set_hook(hook_name,getattr(hooks,hook_name)) + + # Flag to mark unconditional exit + self.exit_now = False + + self.usage_min = """\ + An enhanced console for Python. + Some of its features are: + - Readline support if the readline library is present. + - Tab completion in the local namespace. + - Logging of input, see command-line options. + - System shell escape via ! , eg !ls. + - Magic commands, starting with a % (like %ls, %pwd, %cd, etc.) + - Keeps track of locally defined variables via %who, %whos. + - Show object information with a ? eg ?x or x? (use ?? for more info). + """ + if usage: self.usage = usage + else: self.usage = self.usage_min + + # Storage + self.rc = rc # This will hold all configuration information + self.inputcache = [] + self._boundcache = [] + self.pager = 'less' + # temporary files used for various purposes. Deleted at exit. + self.tempfiles = [] + + # for pushd/popd management + try: + self.home_dir = get_home_dir() + except HomeDirError,msg: + fatal(msg) + + self.dir_stack = [os.getcwd().replace(self.home_dir,'~')] + + # Functions to call the underlying shell. + + # utility to expand user variables via Itpl + self.var_expand = lambda cmd: str(ItplNS(cmd.replace('#','\#'), + self.user_ns)) + # The first is similar to os.system, but it doesn't return a value, + # and it allows interpolation of variables in the user's namespace. + self.system = lambda cmd: shell(self.var_expand(cmd), + header='IPython system call: ', + verbose=self.rc.system_verbose) + # These are for getoutput and getoutputerror: + self.getoutput = lambda cmd: \ + getoutput(self.var_expand(cmd), + header='IPython system call: ', + verbose=self.rc.system_verbose) + self.getoutputerror = lambda cmd: \ + getoutputerror(str(ItplNS(cmd.replace('#','\#'), + self.user_ns)), + header='IPython system call: ', + verbose=self.rc.system_verbose) + + # RegExp for splitting line contents into pre-char//first + # word-method//rest. For clarity, each group in on one line. + + # WARNING: update the regexp if the above escapes are changed, as they + # are hardwired in. + + # Don't get carried away with trying to make the autocalling catch too + # much: it's better to be conservative rather than to trigger hidden + # evals() somewhere and end up causing side effects. + + self.line_split = re.compile(r'^([\s*,;/])' + r'([\?\w\.]+\w*\s*)' + r'(\(?.*$)') + + # Original re, keep around for a while in case changes break something + #self.line_split = re.compile(r'(^[\s*!\?%,/]?)' + # r'(\s*[\?\w\.]+\w*\s*)' + # r'(\(?.*$)') + + # RegExp to identify potential function names + self.re_fun_name = re.compile(r'[a-zA-Z_]([a-zA-Z0-9_.]*) *$') + # RegExp to exclude strings with this start from autocalling + self.re_exclude_auto = re.compile('^[!=()<>,\*/\+-]|^is ') + # try to catch also methods for stuff in lists/tuples/dicts: off + # (experimental). For this to work, the line_split regexp would need + # to be modified so it wouldn't break things at '['. That line is + # nasty enough that I shouldn't change it until I can test it _well_. + #self.re_fun_name = re.compile (r'[a-zA-Z_]([a-zA-Z0-9_.\[\]]*) ?$') + + # keep track of where we started running (mainly for crash post-mortem) + self.starting_dir = os.getcwd() + + # Attributes for Logger mixin class, make defaults here + self._dolog = 0 + self.LOG = '' + self.LOGDEF = '.InteractiveShell.log' + self.LOGMODE = 'over' + self.LOGHEAD = Itpl( +"""#log# Automatic Logger file. *** THIS MUST BE THE FIRST LINE *** +#log# DO NOT CHANGE THIS LINE OR THE TWO BELOW +#log# opts = $self.rc.opts +#log# args = $self.rc.args +#log# It is safe to make manual edits below here. +#log#----------------------------------------------------------------------- +""") + # Various switches which can be set + self.CACHELENGTH = 5000 # this is cheap, it's just text + self.BANNER = "Python %(version)s on %(platform)s\n" % sys.__dict__ + self.banner2 = banner2 + + # TraceBack handlers: + # Need two, one for syntax errors and one for other exceptions. + self.SyntaxTB = ultraTB.ListTB(color_scheme='NoColor') + # This one is initialized with an offset, meaning we always want to + # remove the topmost item in the traceback, which is our own internal + # code. Valid modes: ['Plain','Context','Verbose'] + self.InteractiveTB = ultraTB.AutoFormattedTB(mode = 'Plain', + color_scheme='NoColor', + tb_offset = 1) + # and add any custom exception handlers the user may have specified + self.set_custom_exc(*custom_exceptions) + + # Object inspector + ins_colors = OInspect.InspectColors + code_colors = PyColorize.ANSICodeColors + self.inspector = OInspect.Inspector(ins_colors,code_colors,'NoColor') + self.autoindent = 0 + + # Make some aliases automatically + # Prepare list of shell aliases to auto-define + if os.name == 'posix': + auto_alias = ('mkdir mkdir', 'rmdir rmdir', + 'mv mv -i','rm rm -i','cp cp -i', + 'cat cat','less less','clear clear', + # a better ls + 'ls ls -F', + # long ls + 'll ls -lF', + # color ls + 'lc ls -F -o --color', + # ls normal files only + 'lf ls -F -o --color %l | grep ^-', + # ls symbolic links + 'lk ls -F -o --color %l | grep ^l', + # directories or links to directories, + 'ldir ls -F -o --color %l | grep /$', + # things which are executable + 'lx ls -F -o --color %l | grep ^-..x', + ) + elif os.name in ['nt','dos']: + auto_alias = ('dir dir /on', 'ls dir /on', + 'ddir dir /ad /on', 'ldir dir /ad /on', + 'mkdir mkdir','rmdir rmdir','echo echo', + 'ren ren','cls cls','copy copy') + else: + auto_alias = () + self.auto_alias = map(lambda s:s.split(None,1),auto_alias) + # Call the actual (public) initializer + self.init_auto_alias() + # end __init__ + + def set_hook(self,name,hook): + """set_hook(name,hook) -> sets an internal IPython hook. + + IPython exposes some of its internal API as user-modifiable hooks. By + resetting one of these hooks, you can modify IPython's behavior to + call at runtime your own routines.""" + + # At some point in the future, this should validate the hook before it + # accepts it. Probably at least check that the hook takes the number + # of args it's supposed to. + setattr(self.hooks,name,new.instancemethod(hook,self,self.__class__)) + + def set_custom_exc(self,exc_tuple,handler): + """set_custom_exc(exc_tuple,handler) + + Set a custom exception handler, which will be called if any of the + exceptions in exc_tuple occur in the mainloop (specifically, in the + runcode() method. + + Inputs: + + - exc_tuple: a *tuple* of valid exceptions to call the defined + handler for. It is very important that you use a tuple, and NOT A + LIST here, because of the way Python's except statement works. If + you only want to trap a single exception, use a singleton tuple: + + exc_tuple == (MyCustomException,) + + - handler: this must be defined as a function with the following + basic interface: def my_handler(self,etype,value,tb). + + This will be made into an instance method (via new.instancemethod) + of IPython itself, and it will be called if any of the exceptions + listed in the exc_tuple are caught. If the handler is None, an + internal basic one is used, which just prints basic info. + + WARNING: by putting in your own exception handler into IPython's main + execution loop, you run a very good chance of nasty crashes. This + facility should only be used if you really know what you are doing.""" + + assert type(exc_tuple)==type(()) , \ + "The custom exceptions must be given AS A TUPLE." + + def dummy_handler(self,etype,value,tb): + print '*** Simple custom exception handler ***' + print 'Exception type :',etype + print 'Exception value:',value + print 'Traceback :',tb + print 'Source code :',self.code_to_run_src + + if handler is None: handler = dummy_handler + + self.CustomTB = new.instancemethod(handler,self,self.__class__) + self.custom_exceptions = exc_tuple + + def set_custom_completer(self,completer,pos=0): + """set_custom_completer(completer,pos=0) + + Adds a new custom completer function. + + The position argument (defaults to 0) is the index in the completers + list where you want the completer to be inserted.""" + + newcomp = new.instancemethod(completer,self.Completer, + self.Completer.__class__) + self.Completer.matchers.insert(pos,newcomp) + + def post_config_initialization(self): + """Post configuration init method + + This is called after the configuration files have been processed to + 'finalize' the initialization.""" + + # dynamic data that survives through sessions + # XXX make the filename a config option? + persist_base = 'persist' + if self.rc.profile: + persist_base += '_%s' % self.rc.profile + self.persist_fname = os.path.join(self.rc.ipythondir,persist_base) + + try: + self.persist = pickle.load(file(self.persist_fname)) + except: + self.persist = {} + + def init_auto_alias(self): + """Define some aliases automatically. + + These are ALL parameter-less aliases""" + for alias,cmd in self.auto_alias: + self.alias_table[alias] = (0,cmd) + + def alias_table_validate(self,verbose=0): + """Update information about the alias table. + + In particular, make sure no Python keywords/builtins are in it.""" + + no_alias = self.no_alias + for k in self.alias_table.keys(): + if k in no_alias: + del self.alias_table[k] + if verbose: + print ("Deleting alias <%s>, it's a Python " + "keyword or builtin." % k) + + def set_autoindent(self,value=None): + """Set the autoindent flag, checking for readline support. + + If called with no arguments, it acts as a toggle.""" + + if not self.has_readline: + if os.name == 'posix': + warn("The auto-indent feature requires the readline library") + self.autoindent = 0 + return + if value is None: + self.autoindent = not self.autoindent + else: + self.autoindent = value + + def rc_set_toggle(self,rc_field,value=None): + """Set or toggle a field in IPython's rc config. structure. + + If called with no arguments, it acts as a toggle. + + If called with a non-existent field, the resulting AttributeError + exception will propagate out.""" + + rc_val = getattr(self.rc,rc_field) + if value is None: + value = not rc_val + setattr(self.rc,rc_field,value) + + def user_setup(self,ipythondir,rc_suffix,mode='install'): + """Install the user configuration directory. + + Can be called when running for the first time or to upgrade the user's + .ipython/ directory with the mode parameter. Valid modes are 'install' + and 'upgrade'.""" + + def wait(): + try: + raw_input("Please press <RETURN> to start IPython.") + except EOFError: + print >> Term.cout + print '*'*70 + + cwd = os.getcwd() # remember where we started + glb = glob.glob + print '*'*70 + if mode == 'install': + print \ +"""Welcome to IPython. I will try to create a personal configuration directory +where you can customize many aspects of IPython's functionality in:\n""" + else: + print 'I am going to upgrade your configuration in:' + + print ipythondir + + rcdirend = os.path.join('IPython','UserConfig') + cfg = lambda d: os.path.join(d,rcdirend) + try: + rcdir = filter(os.path.isdir,map(cfg,sys.path))[0] + except IOError: + warning = """ +Installation error. IPython's directory was not found. + +Check the following: + +The ipython/IPython directory should be in a directory belonging to your +PYTHONPATH environment variable (that is, it should be in a directory +belonging to sys.path). You can copy it explicitly there or just link to it. + +IPython will proceed with builtin defaults. +""" + warn(warning) + wait() + return + + if mode == 'install': + try: + shutil.copytree(rcdir,ipythondir) + os.chdir(ipythondir) + rc_files = glb("ipythonrc*") + for rc_file in rc_files: + os.rename(rc_file,rc_file+rc_suffix) + except: + warning = """ + +There was a problem with the installation: +%s +Try to correct it or contact the developers if you think it's a bug. +IPython will proceed with builtin defaults.""" % sys.exc_info()[1] + warn(warning) + wait() + return + + elif mode == 'upgrade': + try: + os.chdir(ipythondir) + except: + print """ +Can not upgrade: changing to directory %s failed. Details: +%s +""" % (ipythondir,sys.exc_info()[1]) + wait() + return + else: + sources = glb(os.path.join(rcdir,'[A-Za-z]*')) + for new_full_path in sources: + new_filename = os.path.basename(new_full_path) + if new_filename.startswith('ipythonrc'): + new_filename = new_filename + rc_suffix + # The config directory should only contain files, skip any + # directories which may be there (like CVS) + if os.path.isdir(new_full_path): + continue + if os.path.exists(new_filename): + old_file = new_filename+'.old' + if os.path.exists(old_file): + os.remove(old_file) + os.rename(new_filename,old_file) + shutil.copy(new_full_path,new_filename) + else: + raise ValueError,'unrecognized mode for install:',`mode` + + # Fix line-endings to those native to each platform in the config + # directory. + try: + os.chdir(ipythondir) + except: + print """ +Problem: changing to directory %s failed. +Details: +%s + +Some configuration files may have incorrect line endings. This should not +cause any problems during execution. """ % (ipythondir,sys.exc_info()[1]) + wait() + else: + for fname in glb('ipythonrc*'): + try: + native_line_ends(fname,backup=0) + except IOError: + pass + + if mode == 'install': + print """ +Successful installation! + +Please read the sections 'Initial Configuration' and 'Quick Tips' in the +IPython manual (there are both HTML and PDF versions supplied with the +distribution) to make sure that your system environment is properly configured +to take advantage of IPython's features.""" + else: + print """ +Successful upgrade! + +All files in your directory: +%(ipythondir)s +which would have been overwritten by the upgrade were backed up with a .old +extension. If you had made particular customizations in those files you may +want to merge them back into the new files.""" % locals() + wait() + os.chdir(cwd) + # end user_setup() + + def atexit_operations(self): + """This will be executed at the time of exit. + + Saving of persistent data should be performed here. """ + + # input history + self.savehist() + + # Cleanup all tempfiles left around + for tfile in self.tempfiles: + try: + os.unlink(tfile) + except OSError: + pass + + # save the "persistent data" catch-all dictionary + try: + pickle.dump(self.persist, open(self.persist_fname,"w")) + except: + print "*** ERROR *** persistent data saving failed." + + def savehist(self): + """Save input history to a file (via readline library).""" + try: + self.readline.write_history_file(self.histfile) + except: + print 'Unable to save IPython command history to file: ' + \ + `self.histfile` + + def pre_readline(self): + """readline hook to be used at the start of each line. + + Currently it handles auto-indent only.""" + + self.readline.insert_text(' '* self.readline_indent) + + def init_readline(self): + """Command history completion/saving/reloading.""" + try: + import readline + self.Completer = MagicCompleter(self, + self.user_ns, + self.rc.readline_omit__names, + self.alias_table) + except ImportError,NameError: + # If FlexCompleter failed to import, MagicCompleter won't be + # defined. This can happen because of a problem with readline + self.has_readline = 0 + # no point in bugging windows users with this every time: + if os.name == 'posix': + warn('Readline services not available on this platform.') + else: + import atexit + + # Platform-specific configuration + if os.name == 'nt': + # readline under Windows modifies the default exit behavior + # from being Ctrl-Z/Return to the Unix Ctrl-D one. + __builtin__.exit = __builtin__.quit = \ + ('Use Ctrl-D (i.e. EOF) to exit. ' + 'Use %Exit or %Quit to exit without confirmation.') + self.readline_startup_hook = readline.set_pre_input_hook + else: + self.readline_startup_hook = readline.set_startup_hook + + # Load user's initrc file (readline config) + inputrc_name = os.environ.get('INPUTRC') + if inputrc_name is None: + home_dir = get_home_dir() + if home_dir is not None: + inputrc_name = os.path.join(home_dir,'.inputrc') + if os.path.isfile(inputrc_name): + try: + readline.read_init_file(inputrc_name) + except: + warn('Problems reading readline initialization file <%s>' + % inputrc_name) + + self.has_readline = 1 + self.readline = readline + self.readline_indent = 0 # for auto-indenting via readline + # save this in sys so embedded copies can restore it properly + sys.ipcompleter = self.Completer.complete + readline.set_completer(self.Completer.complete) + + # Configure readline according to user's prefs + for rlcommand in self.rc.readline_parse_and_bind: + readline.parse_and_bind(rlcommand) + + # remove some chars from the delimiters list + delims = readline.get_completer_delims() + delims = delims.translate(string._idmap, + self.rc.readline_remove_delims) + readline.set_completer_delims(delims) + # otherwise we end up with a monster history after a while: + readline.set_history_length(1000) + try: + #print '*** Reading readline history' # dbg + readline.read_history_file(self.histfile) + except IOError: + pass # It doesn't exist yet. + + atexit.register(self.atexit_operations) + del atexit + + # Configure auto-indent for all platforms + self.set_autoindent(self.rc.autoindent) + + def showsyntaxerror(self, filename=None): + """Display the syntax error that just occurred. + + This doesn't display a stack trace because there isn't one. + + If a filename is given, it is stuffed in the exception instead + of what was there before (because Python's parser always uses + "<string>" when reading from a string). + """ + type, value, sys.last_traceback = sys.exc_info() + sys.last_type = type + sys.last_value = value + if filename and type is SyntaxError: + # Work hard to stuff the correct filename in the exception + try: + msg, (dummy_filename, lineno, offset, line) = value + except: + # Not the format we expect; leave it alone + pass + else: + # Stuff in the right filename + try: + # Assume SyntaxError is a class exception + value = SyntaxError(msg, (filename, lineno, offset, line)) + except: + # If that failed, assume SyntaxError is a string + value = msg, (filename, lineno, offset, line) + self.SyntaxTB(type,value,[]) + + def debugger(self): + """Call the pdb debugger.""" + + if not self.rc.pdb: + return + pdb.pm() + + def showtraceback(self,exc_tuple = None): + """Display the exception that just occurred.""" + + # Though this won't be called by syntax errors in the input line, + # there may be SyntaxError cases whith imported code. + if exc_tuple is None: + type, value, tb = sys.exc_info() + else: + type, value, tb = exc_tuple + if type is SyntaxError: + self.showsyntaxerror() + else: + sys.last_type = type + sys.last_value = value + sys.last_traceback = tb + self.InteractiveTB() + if self.InteractiveTB.call_pdb and self.has_readline: + # pdb mucks up readline, fix it back + self.readline.set_completer(self.Completer.complete) + + def update_cache(self, line): + """puts line into cache""" + self.inputcache.insert(0, line) # This copies the cache every time ... :-( + if len(self.inputcache) >= self.CACHELENGTH: + self.inputcache.pop() # This not :-) + + def name_space_init(self): + """Create local namespace.""" + # We want this to be a method to facilitate embedded initialization. + code.InteractiveConsole.__init__(self,self.user_ns) + + def mainloop(self,banner=None): + """Creates the local namespace and starts the mainloop. + + If an optional banner argument is given, it will override the + internally created default banner.""" + + self.name_space_init() + if self.rc.c: # Emulate Python's -c option + self.exec_init_cmd() + if banner is None: + if self.rc.banner: + banner = self.BANNER+self.banner2 + else: + banner = '' + self.interact(banner) + + def exec_init_cmd(self): + """Execute a command given at the command line. + + This emulates Python's -c option.""" + + sys.argv = ['-c'] + self.push(self.rc.c) + + def embed_mainloop(self,header='',local_ns=None,global_ns=None,stack_depth=0): + """Embeds IPython into a running python program. + + Input: + + - header: An optional header message can be specified. + + - local_ns, global_ns: working namespaces. If given as None, the + IPython-initialized one is updated with __main__.__dict__, so that + program variables become visible but user-specific configuration + remains possible. + + - stack_depth: specifies how many levels in the stack to go to + looking for namespaces (when local_ns and global_ns are None). This + allows an intermediate caller to make sure that this function gets + the namespace from the intended level in the stack. By default (0) + it will get its locals and globals from the immediate caller. + + Warning: it's possible to use this in a program which is being run by + IPython itself (via %run), but some funny things will happen (a few + globals get overwritten). In the future this will be cleaned up, as + there is no fundamental reason why it can't work perfectly.""" + + # Patch for global embedding to make sure that things don't overwrite + # user globals accidentally. Thanks to Richard <rxe@renre-europe.com> + # FIXME. Test this a bit more carefully (the if.. is new) + if local_ns is None and global_ns is None: + self.user_ns.update(__main__.__dict__) + + # Get locals and globals from caller + if local_ns is None or global_ns is None: + call_frame = sys._getframe(stack_depth).f_back + + if local_ns is None: + local_ns = call_frame.f_locals + if global_ns is None: + global_ns = call_frame.f_globals + + # Update namespaces and fire up interpreter + self.user_ns.update(local_ns) + self.interact(header) + + # Remove locals from namespace + for k in local_ns.keys(): + del self.user_ns[k] + + def interact(self, banner=None): + """Closely emulate the interactive Python console. + + The optional banner argument specify the banner to print + before the first interaction; by default it prints a banner + similar to the one printed by the real Python interpreter, + followed by the current class name in parentheses (so as not + to confuse this with the real interpreter -- since it's so + close!). + + """ + cprt = 'Type "copyright", "credits" or "license" for more information.' + if banner is None: + self.write("Python %s on %s\n%s\n(%s)\n" % + (sys.version, sys.platform, cprt, + self.__class__.__name__)) + else: + self.write(banner) + + more = 0 + + # Mark activity in the builtins + __builtin__.__dict__['__IPYTHON__active'] += 1 + while 1: + # This is set by a call to %Exit or %Quit + if self.exit_now: + break + try: + if more: + prompt = self.outputcache.prompt2 + if self.autoindent: + self.readline_startup_hook(self.pre_readline) + else: + prompt = self.outputcache.prompt1 + try: + line = self.raw_input(prompt) + if self.autoindent: + self.readline_startup_hook(None) + except EOFError: + if self.autoindent: + self.readline_startup_hook(None) + self.write("\n") + if self.rc.confirm_exit: + if ask_yes_no('Do you really want to exit ([y]/n)?','y'): + break + else: + break + else: + more = self.push(line) + # Auto-indent management + if self.autoindent: + if line: + ini_spaces = re.match('^(\s+)',line) + if ini_spaces: + nspaces = ini_spaces.end() + else: + nspaces = 0 + self.readline_indent = nspaces + + if line[-1] == ':': + self.readline_indent += 4 + elif re.match(r'^\s+raise|^\s+return',line): + self.readline_indent -= 4 + else: + self.readline_indent = 0 + + except KeyboardInterrupt: + self.write("\nKeyboardInterrupt\n") + self.resetbuffer() + more = 0 + # keep cache in sync with the prompt counter: + self.outputcache.prompt_count -= 1 + + if self.autoindent: + self.readline_indent = 0 + + except bdb.BdbQuit: + warn("The Python debugger has exited with a BdbQuit exception.\n" + "Because of how pdb handles the stack, it is impossible\n" + "for IPython to properly format this particular exception.\n" + "IPython will resume normal operation.") + except: + # We should never get here except in fairly bizarre situations + # (or b/c of an IPython bug). One reasonable exception is if + # the user sets stdin/out/err to a broken object (or closes + # any of them!) + + fixed_in_out_err = 0 + + # Call the Term I/O class and have it reopen any stream which + # the user might have closed. + Term.reopen_all() + + # Do the same manually for sys.stderr/out/in + + # err first, so we can print at least warnings + if sys.__stderr__.closed: + sys.__stderr__ = os.fdopen(os.dup(2),'w',0) + fixed_err_err = 1 + print >> sys.__stderr__,""" +WARNING: +sys.__stderr__ was closed! +I've tried to reopen it, but bear in mind that things may not work normally +from now. In particular, readline support may have broken. +""" + # Next, check stdin/out + if sys.__stdin__.closed: + sys.__stdin__ = os.fdopen(os.dup(0),'r',0) + fixed_in_out_err = 1 + print >> sys.__stderr__,""" +WARNING: +sys.__stdin__ was closed! +I've tried to reopen it, but bear in mind that things may not work normally +from now. In particular, readline support may have broken. +""" + if sys.__stdout__.closed: + sys.__stdout__ = os.fdopen(os.dup(1),'w',0) + fixed_in_out_err = 1 + print >> sys.__stderr__,""" +WARNING: +sys.__stdout__ was closed! +I've tried to reopen it, but bear in mind that things may not work normally +from now. In particular, readline support may have broken. +""" + + # Now, check mismatch of objects + if sys.stdin is not sys.__stdin__: + sys.stdin = sys.__stdin__ + fixed_in_out_err = 1 + print >> sys.__stderr__,""" +WARNING: +sys.stdin has been reset to sys.__stdin__. +There seemed to be a problem with your sys.stdin. +""" + if sys.stdout is not sys.__stdout__: + sys.stdout = sys.__stdout__ + fixed_in_out_err = 1 + print >> sys.__stderr__,""" +WARNING: +sys.stdout has been reset to sys.__stdout__. +There seemed to be a problem with your sys.stdout. +""" + + if sys.stderr is not sys.__stderr__: + sys.stderr = sys.__stderr__ + fixed_in_out_err = 1 + print >> sys.__stderr__,""" +WARNING: +sys.stderr has been reset to sys.__stderr__. +There seemed to be a problem with your sys.stderr. +""" + # If the problem wasn't a broken out/err, it's an IPython bug + # I wish we could ask the user whether to crash or not, but + # calling any function at this point messes up the stack. + if not fixed_in_out_err: + raise + + # We are off again... + __builtin__.__dict__['__IPYTHON__active'] -= 1 + + def excepthook(self, type, value, tb): + """One more defense for GUI apps that call sys.excepthook. + + GUI frameworks like wxPython trap exceptions and call + sys.excepthook themselves. I guess this is a feature that + enables them to keep running after exceptions that would + otherwise kill their mainloop. This is a bother for IPython + which excepts to catch all of the program exceptions with a try: + except: statement. + + Normally, IPython sets sys.excepthook to a CrashHandler instance, so if + any app directly invokes sys.excepthook, it will look to the user like + IPython crashed. In order to work around this, we can disable the + CrashHandler and replace it with this excepthook instead, which prints a + regular traceback using our InteractiveTB. In this fashion, apps which + call sys.excepthook will generate a regular-looking exception from + IPython, and the CrashHandler will only be triggered by real IPython + crashes. + + This hook should be used sparingly, only in places which are not likely + to be true IPython errors. + """ + + self.InteractiveTB(type, value, tb, tb_offset=0) + if self.InteractiveTB.call_pdb and self.has_readline: + self.readline.set_completer(self.Completer.complete) + + def call_alias(self,alias,rest=''): + """Call an alias given its name and the rest of the line. + + This function MUST be given a proper alias, because it doesn't make + any checks when looking up into the alias table. The caller is + responsible for invoking it only with a valid alias.""" + + #print 'ALIAS: <%s>+<%s>' % (alias,rest) # dbg + nargs,cmd = self.alias_table[alias] + # Expand the %l special to be the user's input line + if cmd.find('%l') >= 0: + cmd = cmd.replace('%l',rest) + rest = '' + if nargs==0: + # Simple, argument-less aliases + cmd = '%s %s' % (cmd,rest) + else: + # Handle aliases with positional arguments + args = rest.split(None,nargs) + if len(args)< nargs: + error('Alias <%s> requires %s arguments, %s given.' % + (alias,nargs,len(args))) + return + cmd = '%s %s' % (cmd % tuple(args[:nargs]),' '.join(args[nargs:])) + # Now call the macro, evaluating in the user's namespace + try: + self.system(cmd) + except: + self.showtraceback() + + def runlines(self,lines): + """Run a string of one or more lines of source. + + This method is capable of running a string containing multiple source + lines, as if they had been entered at the IPython prompt. Since it + exposes IPython's processing machinery, the given strings can contain + magic calls (%magic), special shell access (!cmd), etc.""" + + # We must start with a clean buffer, in case this is run from an + # interactive IPython session (via a magic, for example). + self.resetbuffer() + lines = lines.split('\n') + more = 0 + for line in lines: + # skip blank lines so we don't mess up the prompt counter, but do + # NOT skip even a blank line if we are in a code block (more is + # true) + if line or more: + more = self.push((self.prefilter(line,more))) + # IPython's runsource returns None if there was an error + # compiling the code. This allows us to stop processing right + # away, so the user gets the error message at the right place. + if more is None: + break + # final newline in case the input didn't have it, so that the code + # actually does get executed + if more: + self.push('\n') + + def runsource(self, source, filename="<input>", symbol="single"): + """Compile and run some source in the interpreter. + + Arguments are as for compile_command(). + + One several things can happen: + + 1) The input is incorrect; compile_command() raised an + exception (SyntaxError or OverflowError). A syntax traceback + will be printed by calling the showsyntaxerror() method. + + 2) The input is incomplete, and more input is required; + compile_command() returned None. Nothing happens. + + 3) The input is complete; compile_command() returned a code + object. The code is executed by calling self.runcode() (which + also handles run-time exceptions, except for SystemExit). + + The return value is: + + - True in case 2 + + - False in the other cases, unless an exception is raised, where + None is returned instead. This can be used by external callers to + know whether to continue feeding input or not. + + The return value can be used to decide whether to use sys.ps1 or + sys.ps2 to prompt the next line.""" + try: + code = self.compile(source, filename, symbol) + except (OverflowError, SyntaxError, ValueError): + # Case 1 + self.showsyntaxerror(filename) + return None + + if code is None: + # Case 2 + return True + + # Case 3 + # We store the code source and object so that threaded shells and + # custom exception handlers can access all this info if needed. + self.code_to_run_src = source + self.code_to_run = code + # now actually execute the code object + if self.runcode(code) == 0: + return False + else: + return None + + def runcode(self,code_obj): + """Execute a code object. + + When an exception occurs, self.showtraceback() is called to display a + traceback. + + Return value: a flag indicating whether the code to be run completed + successfully: + + - 0: successful execution. + - 1: an error occurred. + """ + + # Set our own excepthook in case the user code tries to call it + # directly, so that the IPython crash handler doesn't get triggered + old_excepthook,sys.excepthook = sys.excepthook, self.excepthook + outflag = 1 # happens in more places, so it's easier as default + try: + try: + exec code_obj in self.locals + finally: + # Reset our crash handler in place + sys.excepthook = old_excepthook + except SystemExit: + self.resetbuffer() + self.showtraceback() + warn( __builtin__.exit,level=1) + except self.custom_exceptions: + etype,value,tb = sys.exc_info() + self.CustomTB(etype,value,tb) + except: + self.showtraceback() + else: + outflag = 0 + if code.softspace(sys.stdout, 0): + print + # Flush out code object which has been run (and source) + self.code_to_run = None + self.code_to_run_src = '' + return outflag + + def raw_input(self, prompt=""): + """Write a prompt and read a line. + + The returned line does not include the trailing newline. + When the user enters the EOF key sequence, EOFError is raised. + + The base implementation uses the built-in function + raw_input(); a subclass may replace this with a different + implementation. + """ + return self.prefilter(raw_input_original(prompt), + prompt==self.outputcache.prompt2) + + def split_user_input(self,line): + """Split user input into pre-char, function part and rest.""" + + lsplit = self.line_split.match(line) + if lsplit is None: # no regexp match returns None + try: + iFun,theRest = line.split(None,1) + except ValueError: + iFun,theRest = line,'' + pre = re.match('^(\s*)(.*)',line).groups()[0] + else: + pre,iFun,theRest = lsplit.groups() + + #print 'line:<%s>' % line # dbg + #print 'pre <%s> iFun <%s> rest <%s>' % (pre,iFun.strip(),theRest) # dbg + return pre,iFun.strip(),theRest + + def _prefilter(self, line, continue_prompt): + """Calls different preprocessors, depending on the form of line.""" + + # All handlers *must* return a value, even if it's blank (''). + + # Lines are NOT logged here. Handlers should process the line as + # needed, update the cache AND log it (so that the input cache array + # stays synced). + + # This function is _very_ delicate, and since it's also the one which + # determines IPython's response to user input, it must be as efficient + # as possible. For this reason it has _many_ returns in it, trying + # always to exit as quickly as it can figure out what it needs to do. + + # This function is the main responsible for maintaining IPython's + # behavior respectful of Python's semantics. So be _very_ careful if + # making changes to anything here. + + #..................................................................... + # Code begins + + #if line.startswith('%crash'): raise RuntimeError,'Crash now!' # dbg + + # save the line away in case we crash, so the post-mortem handler can + # record it + self._last_input_line = line + + #print '***line: <%s>' % line # dbg + + # the input history needs to track even empty lines + if not line.strip(): + if not continue_prompt: + self.outputcache.prompt_count -= 1 + return self.handle_normal('',continue_prompt) + + # print '***cont',continue_prompt # dbg + # special handlers are only allowed for single line statements + if continue_prompt and not self.rc.multi_line_specials: + return self.handle_normal(line,continue_prompt) + + # For the rest, we need the structure of the input + pre,iFun,theRest = self.split_user_input(line) + #print 'pre <%s> iFun <%s> rest <%s>' % (pre,iFun,theRest) # dbg + + # First check for explicit escapes in the last/first character + handler = None + if line[-1] == self.ESC_HELP: + handler = self.esc_handlers.get(line[-1]) # the ? can be at the end + if handler is None: + # look at the first character of iFun, NOT of line, so we skip + # leading whitespace in multiline input + handler = self.esc_handlers.get(iFun[0:1]) + if handler is not None: + return handler(line,continue_prompt,pre,iFun,theRest) + # Emacs ipython-mode tags certain input lines + if line.endswith('# PYTHON-MODE'): + return self.handle_emacs(line,continue_prompt) + + # Next, check if we can automatically execute this thing + + # Allow ! in multi-line statements if multi_line_specials is on: + if continue_prompt and self.rc.multi_line_specials and \ + iFun.startswith(self.ESC_SHELL): + return self.handle_shell_escape(line,continue_prompt, + pre=pre,iFun=iFun, + theRest=theRest) + + # Let's try to find if the input line is a magic fn + oinfo = None + if hasattr(self,'magic_'+iFun): + oinfo = self._ofind(iFun) # FIXME - _ofind is part of Magic + if oinfo['ismagic']: + # Be careful not to call magics when a variable assignment is + # being made (ls='hi', for example) + if self.rc.automagic and \ + (len(theRest)==0 or theRest[0] not in '!=()<>,') and \ + (self.rc.multi_line_specials or not continue_prompt): + return self.handle_magic(line,continue_prompt, + pre,iFun,theRest) + else: + return self.handle_normal(line,continue_prompt) + + # If the rest of the line begins with an (in)equality, assginment or + # function call, we should not call _ofind but simply execute it. + # This avoids spurious geattr() accesses on objects upon assignment. + # + # It also allows users to assign to either alias or magic names true + # python variables (the magic/alias systems always take second seat to + # true python code). + if theRest and theRest[0] in '!=()': + return self.handle_normal(line,continue_prompt) + + if oinfo is None: + oinfo = self._ofind(iFun) # FIXME - _ofind is part of Magic + + if not oinfo['found']: + return self.handle_normal(line,continue_prompt) + else: + #print 'iFun <%s> rest <%s>' % (iFun,theRest) # dbg + if oinfo['isalias']: + return self.handle_alias(line,continue_prompt, + pre,iFun,theRest) + + if self.rc.autocall and \ + not self.re_exclude_auto.match(theRest) and \ + self.re_fun_name.match(iFun) and \ + callable(oinfo['obj']) : + #print 'going auto' # dbg + return self.handle_auto(line,continue_prompt,pre,iFun,theRest) + else: + #print 'was callable?', callable(oinfo['obj']) # dbg + return self.handle_normal(line,continue_prompt) + + # If we get here, we have a normal Python line. Log and return. + return self.handle_normal(line,continue_prompt) + + def _prefilter_dumb(self, line, continue_prompt): + """simple prefilter function, for debugging""" + return self.handle_normal(line,continue_prompt) + + # Set the default prefilter() function (this can be user-overridden) + prefilter = _prefilter + + def handle_normal(self,line,continue_prompt=None, + pre=None,iFun=None,theRest=None): + """Handle normal input lines. Use as a template for handlers.""" + + self.log(line,continue_prompt) + self.update_cache(line) + return line + + def handle_alias(self,line,continue_prompt=None, + pre=None,iFun=None,theRest=None): + """Handle alias input lines. """ + + theRest = esc_quotes(theRest) + line_out = "%s%s.call_alias('%s','%s')" % (pre,self.name,iFun,theRest) + self.log(line_out,continue_prompt) + self.update_cache(line_out) + return line_out + + def handle_shell_escape(self, line, continue_prompt=None, + pre=None,iFun=None,theRest=None): + """Execute the line in a shell, empty return value""" + + # Example of a special handler. Others follow a similar pattern. + if continue_prompt: # multi-line statements + if iFun.startswith('!!'): + print 'SyntaxError: !! is not allowed in multiline statements' + return pre + else: + cmd = ("%s %s" % (iFun[1:],theRest)).replace('"','\\"') + line_out = '%s%s.system("%s")' % (pre,self.name,cmd) + else: # single-line input + if line.startswith('!!'): + # rewrite iFun/theRest to properly hold the call to %sx and + # the actual command to be executed, so handle_magic can work + # correctly + theRest = '%s %s' % (iFun[2:],theRest) + iFun = 'sx' + return self.handle_magic('%ssx %s' % (self.ESC_MAGIC,line[2:]), + continue_prompt,pre,iFun,theRest) + else: + cmd = esc_quotes(line[1:]) + line_out = '%s.system("%s")' % (self.name,cmd) + # update cache/log and return + self.log(line_out,continue_prompt) + self.update_cache(line_out) # readline cache gets normal line + return line_out + + def handle_magic(self, line, continue_prompt=None, + pre=None,iFun=None,theRest=None): + """Execute magic functions. + + Also log them with a prepended # so the log is clean Python.""" + + cmd = '%sipmagic("%s")' % (pre,esc_quotes('%s %s' % (iFun,theRest))) + self.log(cmd,continue_prompt) + self.update_cache(line) + #print 'in handle_magic, cmd=<%s>' % cmd # dbg + return cmd + + def handle_auto(self, line, continue_prompt=None, + pre=None,iFun=None,theRest=None): + """Hande lines which can be auto-executed, quoting if requested.""" + + #print 'pre <%s> iFun <%s> rest <%s>' % (pre,iFun,theRest) # dbg + + # This should only be active for single-line input! + if continue_prompt: + return line + + if pre == self.ESC_QUOTE: + # Auto-quote splitting on whitespace + newcmd = '%s("%s")\n' % (iFun,'", "'.join(theRest.split()) ) + elif pre == self.ESC_QUOTE2: + # Auto-quote whole string + newcmd = '%s("%s")\n' % (iFun,theRest) + else: + # Auto-paren + if theRest[0:1] in ('=','['): + # Don't autocall in these cases. They can be either + # rebindings of an existing callable's name, or item access + # for an object which is BOTH callable and implements + # __getitem__. + return '%s %s\n' % (iFun,theRest) + if theRest.endswith(';'): + newcmd = '%s(%s);\n' % (iFun.rstrip(),theRest[:-1]) + else: + newcmd = '%s(%s)\n' % (iFun.rstrip(),theRest) + + print >>Term.cout, self.outputcache.prompt1.auto_rewrite() + newcmd, + # log what is now valid Python, not the actual user input (without the + # final newline) + self.log(newcmd.strip(),continue_prompt) + return newcmd + + def handle_help(self, line, continue_prompt=None, + pre=None,iFun=None,theRest=None): + """Try to get some help for the object. + + obj? or ?obj -> basic information. + obj?? or ??obj -> more details. + """ + + # We need to make sure that we don't process lines which would be + # otherwise valid python, such as "x=1 # what?" + try: + code.compile_command(line) + except SyntaxError: + # We should only handle as help stuff which is NOT valid syntax + if line[0]==self.ESC_HELP: + line = line[1:] + elif line[-1]==self.ESC_HELP: + line = line[:-1] + self.log('#?'+line) + self.update_cache(line) + if line: + self.magic_pinfo(line) + else: + page(self.usage,screen_lines=self.rc.screen_length) + return '' # Empty string is needed here! + except: + # Pass any other exceptions through to the normal handler + return self.handle_normal(line,continue_prompt) + else: + # If the code compiles ok, we should handle it normally + return self.handle_normal(line,continue_prompt) + + def handle_emacs(self,line,continue_prompt=None, + pre=None,iFun=None,theRest=None): + """Handle input lines marked by python-mode.""" + + # Currently, nothing is done. Later more functionality can be added + # here if needed. + + # The input cache shouldn't be updated + + return line + + def write(self,data): + """Write a string to the default output""" + Term.cout.write(data) + + def write_err(self,data): + """Write a string to the default error output""" + Term.cerr.write(data) + + def safe_execfile(self,fname,*where,**kw): + fname = os.path.expanduser(fname) + + # find things also in current directory + dname = os.path.dirname(fname) + if not sys.path.count(dname): + sys.path.append(dname) + + try: + xfile = open(fname) + except: + print >> Term.cerr, \ + 'Could not open file <%s> for safe execution.' % fname + return None + + kw.setdefault('islog',0) + kw.setdefault('quiet',1) + kw.setdefault('exit_ignore',0) + first = xfile.readline() + _LOGHEAD = str(self.LOGHEAD).split('\n',1)[0].strip() + xfile.close() + # line by line execution + if first.startswith(_LOGHEAD) or kw['islog']: + print 'Loading log file <%s> one line at a time...' % fname + if kw['quiet']: + stdout_save = sys.stdout + sys.stdout = StringIO.StringIO() + try: + globs,locs = where[0:2] + except: + try: + globs = locs = where[0] + except: + globs = locs = globals() + badblocks = [] + + # we also need to identify indented blocks of code when replaying + # logs and put them together before passing them to an exec + # statement. This takes a bit of regexp and look-ahead work in the + # file. It's easiest if we swallow the whole thing in memory + # first, and manually walk through the lines list moving the + # counter ourselves. + indent_re = re.compile('\s+\S') + xfile = open(fname) + filelines = xfile.readlines() + xfile.close() + nlines = len(filelines) + lnum = 0 + while lnum < nlines: + line = filelines[lnum] + lnum += 1 + # don't re-insert logger status info into cache + if line.startswith('#log#'): + continue + elif line.startswith('#%s'% self.ESC_MAGIC): + self.update_cache(line[1:]) + line = magic2python(line) + elif line.startswith('#!'): + self.update_cache(line[1:]) + else: + # build a block of code (maybe a single line) for execution + block = line + try: + next = filelines[lnum] # lnum has already incremented + except: + next = None + while next and indent_re.match(next): + block += next + lnum += 1 + try: + next = filelines[lnum] + except: + next = None + # now execute the block of one or more lines + try: + exec block in globs,locs + self.update_cache(block.rstrip()) + except SystemExit: + pass + except: + badblocks.append(block.rstrip()) + if kw['quiet']: # restore stdout + sys.stdout.close() + sys.stdout = stdout_save + print 'Finished replaying log file <%s>' % fname + if badblocks: + print >> sys.stderr, \ + '\nThe following lines/blocks in file <%s> reported errors:' \ + % fname + for badline in badblocks: + print >> sys.stderr, badline + else: # regular file execution + try: + execfile(fname,*where) + except SyntaxError: + etype, evalue = sys.exc_info()[0:2] + self.SyntaxTB(etype,evalue,[]) + warn('Failure executing file: <%s>' % fname) + except SystemExit,status: + if not kw['exit_ignore']: + self.InteractiveTB() + warn('Failure executing file: <%s>' % fname) + except: + self.InteractiveTB() + warn('Failure executing file: <%s>' % fname) + +#************************* end of file <iplib.py> ***************************** diff --git a/IPython/ipmaker.py b/IPython/ipmaker.py new file mode 100644 index 0000000..cff6035 --- /dev/null +++ b/IPython/ipmaker.py @@ -0,0 +1,736 @@ +# -*- coding: utf-8 -*- +""" +IPython -- An enhanced Interactive Python + +Requires Python 2.1 or better. + +This file contains the main make_IPython() starter function. + +$Id: ipmaker.py 582 2005-05-13 21:20:00Z fperez $""" + +#***************************************************************************** +# Copyright (C) 2001-2004 Fernando Perez. <fperez@colorado.edu> +# +# Distributed under the terms of the BSD License. The full license is in +# the file COPYING, distributed as part of this software. +#***************************************************************************** + +from IPython import Release +__author__ = '%s <%s>' % Release.authors['Fernando'] +__license__ = Release.license +__version__ = Release.version + +credits._Printer__data = """ +Python: %s + +IPython: Fernando Perez, Janko Hauser, Nathan Gray, and many users. +See http://ipython.scipy.org for more information.""" \ +% credits._Printer__data + +copyright._Printer__data += """ + +Copyright (c) 2001-2004 Fernando Perez, Janko Hauser, Nathan Gray. +All Rights Reserved.""" + +#**************************************************************************** +# Required modules + +# From the standard library +import __main__, __builtin__ +import os,sys,types,re +from pprint import pprint,pformat + +# Our own +from IPython import DPyGetOpt +from IPython.Struct import Struct +from IPython.OutputTrap import OutputTrap +from IPython.ConfigLoader import ConfigLoader +from IPython.iplib import InteractiveShell,qw_lol,import_fail_info +from IPython.usage import cmd_line_usage,interactive_usage +from IPython.Prompts import CachedOutput +from IPython.genutils import * + +#----------------------------------------------------------------------------- +def make_IPython(argv=None,user_ns=None,debug=1,rc_override=None, + shell_class=InteractiveShell,embedded=False,**kw): + """This is a dump of IPython into a single function. + + Later it will have to be broken up in a sensible manner. + + Arguments: + + - argv: a list similar to sys.argv[1:]. It should NOT contain the desired + script name, b/c DPyGetOpt strips the first argument only for the real + sys.argv. + + - user_ns: a dict to be used as the user's namespace.""" + + #---------------------------------------------------------------------- + # Defaults and initialization + + # For developer debugging, deactivates crash handler and uses pdb. + DEVDEBUG = False + + if argv is None: + argv = sys.argv + + # __IP is the main global that lives throughout and represents the whole + # application. If the user redefines it, all bets are off as to what + # happens. + + # __IP is the name of he global which the caller will have accessible as + # __IP.name. We set its name via the first parameter passed to + # InteractiveShell: + + IP = shell_class('__IP',user_ns=user_ns,**kw) + + # Put 'help' in the user namespace + try: + from site import _Helper + except ImportError: + # Use the _Helper class from Python 2.2 for older Python versions + class _Helper: + def __repr__(self): + return "Type help() for interactive help, " \ + "or help(object) for help about object." + def __call__(self, *args, **kwds): + import pydoc + return pydoc.help(*args, **kwds) + else: + IP.user_ns['help'] = _Helper() + + if DEVDEBUG: + # For developer debugging only (global flag) + from IPython import ultraTB + sys.excepthook = ultraTB.VerboseTB(call_pdb=1) + else: + # IPython itself shouldn't crash. This will produce a detailed + # post-mortem if it does + from IPython import CrashHandler + sys.excepthook = CrashHandler.CrashHandler(IP) + + IP.BANNER_PARTS = ['Python %s\n' + 'Type "copyright", "credits" or "license" ' + 'for more information.\n' + % (sys.version.split('\n')[0],), + "IPython %s -- An enhanced Interactive Python." + % (__version__,), +"""? -> Introduction to IPython's features. +%magic -> Information about IPython's 'magic' % functions. +help -> Python's own help system. +object? -> Details about 'object'. ?object also works, ?? prints more. +""" ] + + IP.usage = interactive_usage + + # Platform-dependent suffix and directory names + if os.name == 'posix': + rc_suffix = '' + ipdir_def = '.ipython' + else: + rc_suffix = '.ini' + ipdir_def = '_ipython' + + # default directory for configuration + ipythondir = os.path.abspath(os.environ.get('IPYTHONDIR', + os.path.join(IP.home_dir,ipdir_def))) + + # we need the directory where IPython itself is installed + import IPython + IPython_dir = os.path.dirname(IPython.__file__) + del IPython + + #------------------------------------------------------------------------- + # Command line handling + + # Valid command line options (uses DPyGetOpt syntax, like Perl's + # GetOpt::Long) + + # Any key not listed here gets deleted even if in the file (like session + # or profile). That's deliberate, to maintain the rc namespace clean. + + # Each set of options appears twice: under _conv only the names are + # listed, indicating which type they must be converted to when reading the + # ipythonrc file. And under DPyGetOpt they are listed with the regular + # DPyGetOpt syntax (=s,=i,:f,etc). + + # Make sure there's a space before each end of line (they get auto-joined!) + cmdline_opts = ('autocall! autoindent! automagic! banner! cache_size|cs=i ' + 'c=s classic|cl color_info! colors=s confirm_exit! ' + 'debug! deep_reload! editor=s log|l messages! nosep pdb! ' + 'pprint! prompt_in1|pi1=s prompt_in2|pi2=s prompt_out|po=s ' + 'quick screen_length|sl=i prompts_pad_left=i ' + 'logfile|lf=s logplay|lp=s profile|p=s ' + 'readline! readline_merge_completions! ' + 'readline_omit__names! ' + 'rcfile=s separate_in|si=s separate_out|so=s ' + 'separate_out2|so2=s xmode=s ' + 'magic_docstrings system_verbose! ' + 'multi_line_specials!') + + # 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 ignore|i ipythondir=s Version upgrade ' + 'gthread! qthread! wthread! pylab! tk!') + + # Build the actual name list to be used by DPyGetOpt + opts_names = qw(cmdline_opts) + qw(cmdline_only) + + # Set sensible command line defaults. + # This should have everything from cmdline_opts and cmdline_only + opts_def = Struct(autocall = 1, + autoindent=0, + automagic = 1, + banner = 1, + cache_size = 1000, + c = '', + classic = 0, + colors = 'NoColor', + color_info = 0, + confirm_exit = 1, + debug = 0, + deep_reload = 0, + editor = '0', + help = 0, + ignore = 0, + ipythondir = ipythondir, + log = 0, + logfile = '', + logplay = '', + multi_line_specials = 1, + messages = 1, + nosep = 0, + pdb = 0, + pprint = 0, + profile = '', + prompt_in1 = 'In [\\#]:', + prompt_in2 = ' .\\D.:', + prompt_out = 'Out[\\#]:', + prompts_pad_left = 1, + quick = 0, + readline = 1, + readline_merge_completions = 1, + readline_omit__names = 0, + rcfile = 'ipythonrc' + rc_suffix, + screen_length = 0, + separate_in = '\n', + separate_out = '\n', + separate_out2 = '', + system_verbose = 0, + gthread = 0, + qthread = 0, + wthread = 0, + pylab = 0, + tk = 0, + upgrade = 0, + Version = 0, + xmode = 'Verbose', + magic_docstrings = 0, # undocumented, for doc generation + ) + + # Things that will *only* appear in rcfiles (not at the command line). + # Make sure there's a space before each end of line (they get auto-joined!) + rcfile_opts = { qwflat: 'include import_mod import_all execfile ', + qw_lol: 'import_some ', + # for things with embedded whitespace: + list_strings:'execute alias readline_parse_and_bind ', + # Regular strings need no conversion: + None:'readline_remove_delims ', + } + # Default values for these + rc_def = Struct(include = [], + import_mod = [], + import_all = [], + import_some = [[]], + execute = [], + execfile = [], + alias = [], + readline_parse_and_bind = [], + readline_remove_delims = '', + ) + + # Build the type conversion dictionary from the above tables: + typeconv = rcfile_opts.copy() + typeconv.update(optstr2types(cmdline_opts)) + + # FIXME: the None key appears in both, put that back together by hand. Ugly! + typeconv[None] += ' ' + rcfile_opts[None] + + # Remove quotes at ends of all strings (used to protect spaces) + typeconv[unquote_ends] = typeconv[None] + del typeconv[None] + + # Build the list we'll use to make all config decisions with defaults: + opts_all = opts_def.copy() + opts_all.update(rc_def) + + # Build conflict resolver for recursive loading of config files: + # - preserve means the outermost file maintains the value, it is not + # overwritten if an included file has the same key. + # - add_flip applies + to the two values, so it better make sense to add + # those types of keys. But it flips them first so that things loaded + # deeper in the inclusion chain have lower precedence. + conflict = {'preserve': ' '.join([ typeconv[int], + typeconv[unquote_ends] ]), + 'add_flip': ' '.join([ typeconv[qwflat], + typeconv[qw_lol], + typeconv[list_strings] ]) + } + + # Now actually process the command line + getopt = DPyGetOpt.DPyGetOpt() + getopt.setIgnoreCase(0) + + getopt.parseConfiguration(opts_names) + + try: + getopt.processArguments(argv) + except: + print cmd_line_usage + warn('\nError in Arguments: ' + `sys.exc_value`) + sys.exit() + + # convert the options dict to a struct for much lighter syntax later + opts = Struct(getopt.optionValues) + args = getopt.freeValues + + # this is the struct (which has default values at this point) with which + # we make all decisions: + opts_all.update(opts) + + # Options that force an immediate exit + if opts_all.help: + page(cmd_line_usage) + sys.exit() + + if opts_all.Version: + print __version__ + sys.exit() + + if opts_all.magic_docstrings: + IP.magic_magic('-latex') + sys.exit() + + # Create user config directory if it doesn't exist. This must be done + # *after* getting the cmd line options. + if not os.path.isdir(opts_all.ipythondir): + IP.user_setup(opts_all.ipythondir,rc_suffix,'install') + + # upgrade user config files while preserving a copy of the originals + if opts_all.upgrade: + IP.user_setup(opts_all.ipythondir,rc_suffix,'upgrade') + + # check mutually exclusive options in the *original* command line + mutex_opts(opts,[qw('log logfile'),qw('rcfile profile'), + qw('classic profile'),qw('classic rcfile')]) + + # default logfilename used when -log is called. + IP.LOGDEF = 'ipython.log' + + #--------------------------------------------------------------------------- + # Log replay + + # if -logplay, we need to 'become' the other session. That basically means + # replacing the current command line environment with that of the old + # session and moving on. + + # this is needed so that later we know we're in session reload mode, as + # opts_all will get overwritten: + load_logplay = 0 + + if opts_all.logplay: + load_logplay = opts_all.logplay + opts_debug_save = opts_all.debug + try: + logplay = open(opts_all.logplay) + except IOError: + if opts_all.debug: IP.InteractiveTB() + warn('Could not open logplay file '+`opts_all.logplay`) + # restore state as if nothing had happened and move on, but make + # sure that later we don't try to actually load the session file + logplay = None + load_logplay = 0 + del opts_all.logplay + else: + try: + logplay.readline() + logplay.readline(); + # this reloads that session's command line + cmd = logplay.readline()[6:] + exec cmd + # restore the true debug flag given so that the process of + # session loading itself can be monitored. + opts.debug = opts_debug_save + # save the logplay flag so later we don't overwrite the log + opts.logplay = load_logplay + # now we must update our own structure with defaults + opts_all.update(opts) + # now load args + cmd = logplay.readline()[6:] + exec cmd + logplay.close() + except: + logplay.close() + if opts_all.debug: IP.InteractiveTB() + warn("Logplay file lacking full configuration information.\n" + "I'll try to read it, but some things may not work.") + + #------------------------------------------------------------------------- + # set up output traps: catch all output from files, being run, modules + # loaded, etc. Then give it to the user in a clean form at the end. + + msg_out = 'Output messages. ' + msg_err = 'Error messages. ' + msg_sep = '\n' + msg = Struct(config = OutputTrap('Configuration Loader',msg_out, + msg_err,msg_sep,debug, + quiet_out=1), + user_exec = OutputTrap('User File Execution',msg_out, + msg_err,msg_sep,debug), + logplay = OutputTrap('Log Loader',msg_out, + msg_err,msg_sep,debug), + summary = '' + ) + + #------------------------------------------------------------------------- + # Process user ipythonrc-type configuration files + + # turn on output trapping and log to msg.config + # remember that with debug on, trapping is actually disabled + msg.config.trap_all() + + # look for rcfile in current or default directory + try: + opts_all.rcfile = filefind(opts_all.rcfile,opts_all.ipythondir) + except IOError: + if opts_all.debug: IP.InteractiveTB() + warn('Configuration file %s not found. Ignoring request.' + % (opts_all.rcfile) ) + + # 'profiles' are a shorthand notation for config filenames + if opts_all.profile: + try: + opts_all.rcfile = filefind('ipythonrc-' + opts_all.profile + + rc_suffix, + opts_all.ipythondir) + except IOError: + if opts_all.debug: IP.InteractiveTB() + opts.profile = '' # remove profile from options if invalid + warn('Profile configuration file %s not found. Ignoring request.' + % (opts_all.profile) ) + + # load the config file + rcfiledata = None + if opts_all.quick: + print 'Launching IPython in quick mode. No config file read.' + elif opts_all.classic: + print 'Launching IPython in classic mode. No config file read.' + elif opts_all.rcfile: + try: + cfg_loader = ConfigLoader(conflict) + rcfiledata = cfg_loader.load(opts_all.rcfile,typeconv, + 'include',opts_all.ipythondir, + purge = 1, + unique = conflict['preserve']) + except: + IP.InteractiveTB() + warn('Problems loading configuration file '+ + `opts_all.rcfile`+ + '\nStarting with default -bare bones- configuration.') + else: + warn('No valid configuration file found in either currrent directory\n'+ + 'or in the IPython config. directory: '+`opts_all.ipythondir`+ + '\nProceeding with internal defaults.') + + #------------------------------------------------------------------------ + # Set exception handlers in mode requested by user. + otrap = OutputTrap(trap_out=1) # trap messages from magic_xmode + IP.magic_xmode(opts_all.xmode) + otrap.release_out() + + #------------------------------------------------------------------------ + # Execute user config + + # first, create a valid config structure with the right precedence order: + # defaults < rcfile < command line + IP.rc = rc_def.copy() + IP.rc.update(opts_def) + if rcfiledata: + # now we can update + IP.rc.update(rcfiledata) + IP.rc.update(opts) + IP.rc.update(rc_override) + + # Store the original cmd line for reference: + IP.rc.opts = opts + IP.rc.args = args + + # create a *runtime* Struct like rc for holding parameters which may be + # created and/or modified by runtime user extensions. + IP.runtime_rc = Struct() + + # from this point on, all config should be handled through IP.rc, + # opts* shouldn't be used anymore. + + # add personal .ipython dir to sys.path so that users can put things in + # there for customization + sys.path.append(IP.rc.ipythondir) + sys.path.insert(0, '') # add . to sys.path. Fix from Prabhu Ramachandran + + # update IP.rc with some special things that need manual + # tweaks. Basically options which affect other options. I guess this + # should just be written so that options are fully orthogonal and we + # wouldn't worry about this stuff! + + if IP.rc.classic: + IP.rc.quick = 1 + IP.rc.cache_size = 0 + IP.rc.pprint = 0 + IP.rc.prompt_in1 = '>>> ' + IP.rc.prompt_in2 = '... ' + IP.rc.prompt_out = '' + IP.rc.separate_in = IP.rc.separate_out = IP.rc.separate_out2 = '0' + IP.rc.colors = 'NoColor' + IP.rc.xmode = 'Plain' + + # configure readline + # Define the history file for saving commands in between sessions + if IP.rc.profile: + histfname = 'history-%s' % IP.rc.profile + else: + histfname = 'history' + IP.histfile = os.path.join(opts_all.ipythondir,histfname) + # Load readline proper + if IP.rc.readline: + IP.init_readline() + + # update exception handlers with rc file status + otrap.trap_out() # I don't want these messages ever. + IP.magic_xmode(IP.rc.xmode) + otrap.release_out() + + # activate logging if requested and not reloading a log + if IP.rc.logplay: + IP.magic_logstart(IP.rc.logplay + ' append') + elif IP.rc.logfile: + IP.magic_logstart(IP.rc.logfile) + elif IP.rc.log: + IP.magic_logstart() + + # find user editor so that it we don't have to look it up constantly + if IP.rc.editor.strip()=='0': + try: + ed = os.environ['EDITOR'] + except KeyError: + if os.name == 'posix': + ed = 'vi' # the only one guaranteed to be there! + else: + ed = 'notepad' # same in Windows! + IP.rc.editor = ed + + # Recursive reload + try: + from IPython import deep_reload + if IP.rc.deep_reload: + __builtin__.reload = deep_reload.reload + else: + __builtin__.dreload = deep_reload.reload + del deep_reload + except ImportError: + pass + + # Save the current state of our namespace so that the interactive shell + # can later know which variables have been created by us from config files + # and loading. This way, loading a file (in any way) is treated just like + # defining things on the command line, and %who works as expected. + + # DON'T do anything that affects the namespace beyond this point! + IP.internal_ns = __main__.__dict__.copy() + + #IP.internal_ns.update(locals()) # so our stuff doesn't show up in %who + + # Now run through the different sections of the users's config + if IP.rc.debug: + print 'Trying to execute the following configuration structure:' + print '(Things listed first are deeper in the inclusion tree and get' + print 'loaded first).\n' + pprint(IP.rc.__dict__) + + for mod in IP.rc.import_mod: + try: + exec 'import '+mod in IP.user_ns + except : + IP.InteractiveTB() + import_fail_info(mod) + + for mod_fn in IP.rc.import_some: + if mod_fn == []: break + mod,fn = mod_fn[0],','.join(mod_fn[1:]) + try: + exec 'from '+mod+' import '+fn in IP.user_ns + except : + IP.InteractiveTB() + import_fail_info(mod,fn) + + for mod in IP.rc.import_all: + try: + exec 'from '+mod+' import *' in IP.user_ns + except : + IP.InteractiveTB() + import_fail_info(mod) + + for code in IP.rc.execute: + try: + exec code in IP.user_ns + except: + IP.InteractiveTB() + warn('Failure executing code: ' + `code`) + + # Execute the files the user wants in ipythonrc + for file in IP.rc.execfile: + try: + file = filefind(file,sys.path+[IPython_dir]) + except IOError: + warn(itpl('File $file not found. Skipping it.')) + else: + IP.safe_execfile(os.path.expanduser(file),IP.user_ns) + + # Load user aliases + for alias in IP.rc.alias: + IP.magic_alias(alias) + + # release stdout and stderr and save config log into a global summary + msg.config.release_all() + if IP.rc.messages: + msg.summary += msg.config.summary_all() + + #------------------------------------------------------------------------ + # Setup interactive session + + # Now we should be fully configured. We can then execute files or load + # things only needed for interactive use. Then we'll open the shell. + + # Take a snapshot of the user namespace before opening the shell. That way + # we'll be able to identify which things were interactively defined and + # which were defined through config files. + IP.user_config_ns = IP.user_ns.copy() + + # Force reading a file as if it were a session log. Slower but safer. + if load_logplay: + print 'Replaying log...' + try: + if IP.rc.debug: + logplay_quiet = 0 + else: + logplay_quiet = 1 + + msg.logplay.trap_all() + IP.safe_execfile(load_logplay,IP.user_ns, + islog = 1, quiet = logplay_quiet) + msg.logplay.release_all() + if IP.rc.messages: + msg.summary += msg.logplay.summary_all() + except: + warn('Problems replaying logfile %s.' % load_logplay) + IP.InteractiveTB() + + # Load remaining files in command line + msg.user_exec.trap_all() + + # Do NOT execute files named in the command line as scripts to be loaded + # by embedded instances. Doing so has the potential for an infinite + # recursion if there are exceptions thrown in the process. + + # XXX FIXME: the execution of user files should be moved out to after + # ipython is fully initialized, just as if they were run via %run at the + # ipython prompt. This would also give them the benefit of ipython's + # nice tracebacks. + + if not embedded and IP.rc.args: + name_save = IP.user_ns['__name__'] + IP.user_ns['__name__'] = '__main__' + try: + # Set our own excepthook in case the user code tries to call it + # directly. This prevents triggering the IPython crash handler. + old_excepthook,sys.excepthook = sys.excepthook, IP.excepthook + for run in args: + IP.safe_execfile(run,IP.user_ns) + finally: + # Reset our crash handler in place + sys.excepthook = old_excepthook + + IP.user_ns['__name__'] = name_save + + msg.user_exec.release_all() + if IP.rc.messages: + msg.summary += msg.user_exec.summary_all() + + # since we can't specify a null string on the cmd line, 0 is the equivalent: + if IP.rc.nosep: + IP.rc.separate_in = IP.rc.separate_out = IP.rc.separate_out2 = '0' + if IP.rc.separate_in == '0': IP.rc.separate_in = '' + if IP.rc.separate_out == '0': IP.rc.separate_out = '' + if IP.rc.separate_out2 == '0': IP.rc.separate_out2 = '' + IP.rc.separate_in = IP.rc.separate_in.replace('\\n','\n') + IP.rc.separate_out = IP.rc.separate_out.replace('\\n','\n') + IP.rc.separate_out2 = IP.rc.separate_out2.replace('\\n','\n') + + # Determine how many lines at the bottom of the screen are needed for + # showing prompts, so we can know wheter long strings are to be printed or + # paged: + num_lines_bot = IP.rc.separate_in.count('\n')+1 + IP.rc.screen_length = IP.rc.screen_length - num_lines_bot + # Initialize cache, set in/out prompts and printing system + IP.outputcache = CachedOutput(IP.rc.cache_size, + IP.rc.pprint, + input_sep = IP.rc.separate_in, + output_sep = IP.rc.separate_out, + output_sep2 = IP.rc.separate_out2, + ps1 = IP.rc.prompt_in1, + ps2 = IP.rc.prompt_in2, + ps_out = IP.rc.prompt_out, + user_ns = IP.user_ns, + input_hist = IP.input_hist, + pad_left = IP.rc.prompts_pad_left) + + # Set user colors (don't do it in the constructor above so that it doesn't + # crash if colors option is invalid) + IP.magic_colors(IP.rc.colors) + + # user may have over-ridden the default print hook: + try: + IP.outputcache.__class__.display = IP.hooks.display + except AttributeError: + pass + + # Set calling of pdb on exceptions + IP.InteractiveTB.call_pdb = IP.rc.pdb + + # I don't like assigning globally to sys, because it means when embedding + # instances, each embedded instance overrides the previous choice. But + # sys.displayhook seems to be called internally by exec, so I don't see a + # way around it. + sys.displayhook = IP.outputcache + + # we need to know globally if we're caching i/o or not + IP.do_full_cache = IP.outputcache.do_full_cache + + # configure startup banner + if IP.rc.c: # regular python doesn't print the banner with -c + IP.rc.banner = 0 + if IP.rc.banner: + IP.BANNER = '\n'.join(IP.BANNER_PARTS) + else: + IP.BANNER = '' + + if IP.rc.profile: IP.BANNER += '\nIPython profile: '+IP.rc.profile+'\n' + + # add message log (possibly empty) + IP.BANNER += msg.summary + + IP.post_config_initialization() + + return IP +#************************ end of file <ipmaker.py> ************************** diff --git a/IPython/numutils.py b/IPython/numutils.py new file mode 100644 index 0000000..4d924e9 --- /dev/null +++ b/IPython/numutils.py @@ -0,0 +1,305 @@ +# -*- coding: utf-8 -*- +""" +A set of convenient utilities for numerical work. + +Most of this module requires Numerical Python or is meant to be used with it. +See http://www.pfdubois.com/numpy for details. + +$Id: numutils.py 486 2005-01-27 19:34:21Z fperez $""" + +#***************************************************************************** +# Copyright (C) 2001-2005 Fernando Perez <fperez@colorado.edu> +# +# Distributed under the terms of the BSD License. The full license is in +# the file COPYING, distributed as part of this software. +#***************************************************************************** + +from IPython import Release +__author__ = '%s <%s>' % Release.authors['Fernando'] +__license__ = Release.license + +__all__ = ['sum_flat','mean_flat','rms_flat','base_repr','binary_repr', + 'amin','amax','amap','zeros_like','empty_like', + 'frange','diagonal_matrix','identity', + 'fromfunction_kw','log2','ispower2', + 'norm','l1norm','l2norm','exp_safe', + 'inf','infty','Infinity', + 'Numeric'] + +#**************************************************************************** +# required modules +import __main__ +import sys,operator +import math +import Numeric +from Numeric import * + +#***************************************************************************** +# Globals + +# useful for testing infinities in results of array divisions (which don't +# raise an exception) +# Python, LaTeX and Mathematica names. +inf = infty = Infinity = (array([1])/0.0)[0] + +#**************************************************************************** +# function definitions +exp_safe_MIN = math.log(2.2250738585072014e-308) +exp_safe_MAX = 1.7976931348623157e+308 + +def exp_safe(x): + """Compute exponentials which safely underflow to zero. + + Slow but convenient to use. Note that NumArray will introduce proper + floating point exception handling with access to the underlying + hardware.""" + + if type(x) is ArrayType: + return exp(clip(x,exp_safe_MIN,exp_safe_MAX)) + else: + return math.exp(x) + +def amap(fn,*args): + """amap(function, sequence[, sequence, ...]) -> array. + + Works like map(), but it returns an array. This is just a convenient + shorthand for Numeric.array(map(...))""" + return array(map(fn,*args)) + +def amin(m,axis=0): + """amin(m,axis=0) returns the minimum of m along dimension axis. + """ + return minimum.reduce(asarray(m),axis) + +def amax(m,axis=0): + """amax(m,axis=0) returns the maximum of m along dimension axis. + """ + return maximum.reduce(asarray(m),axis) + +def zeros_like(a): + """Return an array of zeros of the shape and typecode of a. + + If you don't explicitly need the array to be zeroed, you should instead + use empty_like(), which is faster as it only allocates memory.""" + + return zeros(a.shape,a.typecode()) + +def empty_like(a): + """Return an empty (uninitialized) array of the shape and typecode of a. + + Note that this does NOT initialize the returned array. If you require + your array to be initialized, you should use zeros_like(). + + This requires Numeric.empty(), which appeared in Numeric 23.7.""" + + return empty(a.shape,a.typecode()) + +def sum_flat(a): + """Return the sum of all the elements of a, flattened out. + + It uses a.flat, and if a is not contiguous, a call to ravel(a) is made.""" + + if a.iscontiguous(): + return Numeric.sum(a.flat) + else: + return Numeric.sum(ravel(a)) + +def mean_flat(a): + """Return the mean of all the elements of a, flattened out.""" + + return sum_flat(a)/float(size(a)) + +def rms_flat(a): + """Return the root mean square of all the elements of a, flattened out.""" + + return math.sqrt(sum_flat(absolute(a)**2)/float(size(a))) + +def l1norm(a): + """Return the l1 norm of a, flattened out. + + Implemented as a separate function (not a call to norm() for speed). + + Ref: http://mathworld.wolfram.com/L1-Norm.html""" + + return sum_flat(absolute(a)) + +def l2norm(a): + """Return the l2 norm of a, flattened out. + + Implemented as a separate function (not a call to norm() for speed). + + Ref: http://mathworld.wolfram.com/L2-Norm.html""" + + return math.sqrt(sum_flat(absolute(a)**2)) + +def norm(a,p=2): + """norm(a,p=2) -> l-p norm of a.flat + + Return the l-p norm of a, considered as a flat array. This is NOT a true + matrix norm, since arrays of arbitrary rank are always flattened. + + p can be a number or one of the strings ('inf','Infinity') to get the + L-infinity norm. + + Ref: http://mathworld.wolfram.com/VectorNorm.html + http://mathworld.wolfram.com/L-Infinity-Norm.html""" + + if p in ('inf','Infinity'): + return max(absolute(a).flat) + else: + return (sum_flat(absolute(a)**p))**(1.0/p) + +def frange(xini,xfin=None,delta=None,**kw): + """frange([start,] stop[, step, keywords]) -> array of floats + + Return a Numeric array() containing a progression of floats. Similar to + arange(), but defaults to a closed interval. + + frange(x0, x1) returns [x0, x0+1, x0+2, ..., x1]; start defaults to 0, and + the endpoint *is included*. This behavior is different from that of + range() and arange(). This is deliberate, since frange will probably be + more useful for generating lists of points for function evaluation, and + endpoints are often desired in this use. The usual behavior of range() can + be obtained by setting the keyword 'closed=0', in this case frange() + basically becomes arange(). + + When step is given, it specifies the increment (or decrement). All + arguments can be floating point numbers. + + frange(x0,x1,d) returns [x0,x0+d,x0+2d,...,xfin] where xfin<=x1. + + frange can also be called with the keyword 'npts'. This sets the number of + points the list should contain (and overrides the value 'step' might have + been given). arange() doesn't offer this option. + + Examples: + >>> frange(3) + array([ 0., 1., 2., 3.]) + >>> frange(3,closed=0) + array([ 0., 1., 2.]) + >>> frange(1,6,2) + array([1, 3, 5]) + >>> frange(1,6.5,npts=5) + array([ 1. , 2.375, 3.75 , 5.125, 6.5 ]) + """ + + #defaults + kw.setdefault('closed',1) + endpoint = kw['closed'] != 0 + + # funny logic to allow the *first* argument to be optional (like range()) + # This was modified with a simpler version from a similar frange() found + # at http://aspn.activestate.com/ASPN/Cookbook/Python/Recipe/66472 + if xfin == None: + xfin = xini + 0.0 + xini = 0.0 + + if delta == None: + delta = 1.0 + + # compute # of points, spacing and return final list + try: + npts=kw['npts'] + delta=(xfin-xini)/float(npts-endpoint) + except KeyError: + # round() gets npts right even with the vagaries of floating point. + npts=int(round((xfin-xini)/delta+endpoint)) + + return arange(npts)*delta+xini + +def diagonal_matrix(diag): + """Return square diagonal matrix whose non-zero elements are given by the + input array.""" + + return diag*identity(len(diag)) + +def identity(n,rank=2,typecode='l'): + """identity(n,r) returns the identity matrix of shape (n,n,...,n) (rank r). + + For ranks higher than 2, this object is simply a multi-index Kronecker + delta: + / 1 if i0=i1=...=iR, + id[i0,i1,...,iR] = -| + \ 0 otherwise. + + Optionally a typecode may be given (it defaults to 'l'). + + Since rank defaults to 2, this function behaves in the default case (when + only n is given) like the Numeric identity function.""" + + iden = zeros((n,)*rank,typecode=typecode) + for i in range(n): + idx = (i,)*rank + iden[idx] = 1 + return iden + +def base_repr (number, base = 2, padding = 0): + """Return the representation of a number in any given base.""" + chars = '0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ' + if number < base: \ + return (padding - 1) * chars [0] + chars [int (number)] + max_exponent = int (math.log (number)/math.log (base)) + max_power = long (base) ** max_exponent + lead_digit = int (number/max_power) + return chars [lead_digit] + \ + base_repr (number - max_power * lead_digit, base, \ + max (padding - 1, max_exponent)) + +def binary_repr(number, max_length = 1025): + """Return the binary representation of the input number as a string. + + This is more efficient than using base_repr with base 2. + + Increase the value of max_length for very large numbers. Note that on + 32-bit machines, 2**1023 is the largest integer power of 2 which can be + converted to a Python float.""" + + assert number < 2L << max_length + shifts = map (operator.rshift, max_length * [number], \ + range (max_length - 1, -1, -1)) + digits = map (operator.mod, shifts, max_length * [2]) + if not digits.count (1): return 0 + digits = digits [digits.index (1):] + return ''.join (map (repr, digits)).replace('L','') + +def log2(x,ln2 = math.log(2.0)): + """Return the log(x) in base 2. + + This is a _slow_ function but which is guaranteed to return the correct + integer value if the input is an ineger exact power of 2.""" + + try: + bin_n = binary_repr(x)[1:] + except (AssertionError,TypeError): + return math.log(x)/ln2 + else: + if '1' in bin_n: + return math.log(x)/ln2 + else: + return len(bin_n) + +def ispower2(n): + """Returns the log base 2 of n if n is a power of 2, zero otherwise. + + Note the potential ambiguity if n==1: 2**0==1, interpret accordingly.""" + + bin_n = binary_repr(n)[1:] + if '1' in bin_n: + return 0 + else: + return len(bin_n) + +def fromfunction_kw(function, dimensions, **kwargs): + """Drop-in replacement for fromfunction() from Numerical Python. + + Allows passing keyword arguments to the desired function. + + Call it as (keywords are optional): + fromfunction_kw(MyFunction, dimensions, keywords) + + The function MyFunction() is responsible for handling the dictionary of + keywords it will recieve.""" + + return function(tuple(indices(dimensions)),**kwargs) + +#**************************** end file <numutils.py> ************************ diff --git a/IPython/ultraTB.py b/IPython/ultraTB.py new file mode 100644 index 0000000..43f29ec --- /dev/null +++ b/IPython/ultraTB.py @@ -0,0 +1,855 @@ +# -*- coding: utf-8 -*- +""" +ultraTB.py -- Spice up your tracebacks! + +* ColorTB +I've always found it a bit hard to visually parse tracebacks in Python. The +ColorTB class is a solution to that problem. It colors the different parts of a +traceback in a manner similar to what you would expect from a syntax-highlighting +text editor. + +Installation instructions for ColorTB: + import sys,ultraTB + sys.excepthook = ultraTB.ColorTB() + +* VerboseTB +I've also included a port of Ka-Ping Yee's "cgitb.py" that produces all kinds +of useful info when a traceback occurs. Ping originally had it spit out HTML +and intended it for CGI programmers, but why should they have all the fun? I +altered it to spit out colored text to the terminal. It's a bit overwhelming, +but kind of neat, and maybe useful for long-running programs that you believe +are bug-free. If a crash *does* occur in that type of program you want details. +Give it a shot--you'll love it or you'll hate it. + +Note: + + The Verbose mode 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). + + If you encounter this kind of situation often, you may want to use the + Verbose_novars mode instead of the regular Verbose, which avoids formatting + variables (but otherwise includes the information and context given by + Verbose). + + +Installation instructions for ColorTB: + import sys,ultraTB + sys.excepthook = ultraTB.VerboseTB() + +Note: Much of the code in this module was lifted verbatim from the standard +library module 'traceback.py' and Ka-Ping Yee's 'cgitb.py'. + +* Color schemes +The colors are defined in the class TBTools through the use of the +ColorSchemeTable class. Currently the following exist: + + - NoColor: allows all of this module to be used in any terminal (the color + escapes are just dummy blank strings). + + - Linux: is meant to look good in a terminal like the Linux console (black + or very dark background). + + - LightBG: similar to Linux but swaps dark/light colors to be more readable + in light background terminals. + +You can implement other color schemes easily, the syntax is fairly +self-explanatory. Please send back new schemes you develop to the author for +possible inclusion in future releases. + +$Id: ultraTB.py 589 2005-05-30 06:26:28Z fperez $""" + +#***************************************************************************** +# Copyright (C) 2001 Nathaniel Gray <n8gray@caltech.edu> +# Copyright (C) 2001-2004 Fernando Perez <fperez@colorado.edu> +# +# Distributed under the terms of the BSD License. The full license is in +# the file COPYING, distributed as part of this software. +#***************************************************************************** + +from IPython import Release +__author__ = '%s <%s>\n%s <%s>' % (Release.authors['Nathan']+ + Release.authors['Fernando']) +__license__ = Release.license + +# Required modules +import sys, os, traceback, types, string, time +import keyword, tokenize, linecache, inspect, pydoc +from UserDict import UserDict + +# IPython's own modules +# Modified pdb which doesn't damage IPython's readline handling +from IPython import Debugger + +from IPython.Struct import Struct +from IPython.ColorANSI import * +from IPython.genutils import Term,uniq_stable,error,info + +#--------------------------------------------------------------------------- +# Code begins + +def inspect_error(): + """Print a message about internal inspect errors. + + These are unfortunately quite common.""" + + error('Internal Python error in the inspect module.\n' + 'Below is the traceback from this internal error.\n') + +class TBTools: + """Basic tools used by all traceback printer classes.""" + + def __init__(self,color_scheme = 'NoColor',call_pdb=0): + # Whether to call the interactive pdb debugger after printing + # tracebacks or not + self.call_pdb = call_pdb + if call_pdb: + self.pdb = Debugger.Pdb() + else: + self.pdb = None + + # Create color table + self.ColorSchemeTable = ColorSchemeTable() + + # Populate it with color schemes + C = TermColors # shorthand and local lookup + self.ColorSchemeTable.add_scheme(ColorScheme( + 'NoColor', + # The color to be used for the top line + topline = C.NoColor, + + # The colors to be used in the traceback + filename = C.NoColor, + lineno = C.NoColor, + name = C.NoColor, + vName = C.NoColor, + val = C.NoColor, + em = C.NoColor, + + # Emphasized colors for the last frame of the traceback + normalEm = C.NoColor, + filenameEm = C.NoColor, + linenoEm = C.NoColor, + nameEm = C.NoColor, + valEm = C.NoColor, + + # Colors for printing the exception + excName = C.NoColor, + line = C.NoColor, + caret = C.NoColor, + Normal = C.NoColor + )) + + # make some schemes as instances so we can copy them for modification easily: + self.ColorSchemeTable.add_scheme(ColorScheme( + 'Linux', + # The color to be used for the top line + topline = C.LightRed, + + # The colors to be used in the traceback + filename = C.Green, + lineno = C.Green, + name = C.Purple, + vName = C.Cyan, + val = C.Green, + em = C.LightCyan, + + # Emphasized colors for the last frame of the traceback + normalEm = C.LightCyan, + filenameEm = C.LightGreen, + linenoEm = C.LightGreen, + nameEm = C.LightPurple, + valEm = C.LightBlue, + + # Colors for printing the exception + excName = C.LightRed, + line = C.Yellow, + caret = C.White, + Normal = C.Normal + )) + + # For light backgrounds, swap dark/light colors + self.ColorSchemeTable.add_scheme(ColorScheme( + 'LightBG', + # The color to be used for the top line + topline = C.Red, + + # The colors to be used in the traceback + filename = C.LightGreen, + lineno = C.LightGreen, + name = C.LightPurple, + vName = C.Cyan, + val = C.LightGreen, + em = C.Cyan, + + # Emphasized colors for the last frame of the traceback + normalEm = C.Cyan, + filenameEm = C.Green, + linenoEm = C.Green, + nameEm = C.Purple, + valEm = C.Blue, + + # Colors for printing the exception + excName = C.Red, + #line = C.Brown, # brown often is displayed as yellow + line = C.Red, + caret = C.Normal, + Normal = C.Normal + )) + + self.set_colors(color_scheme) + self.old_scheme = color_scheme # save initial value for toggles + + def set_colors(self,*args,**kw): + """Shorthand access to the color table scheme selector method.""" + + self.ColorSchemeTable.set_active_scheme(*args,**kw) + # for convenience, set Colors to the active scheme + self.Colors = self.ColorSchemeTable.active_colors + + def color_toggle(self): + """Toggle between the currently active color scheme and NoColor.""" + + if self.ColorSchemeTable.active_scheme_name == 'NoColor': + self.ColorSchemeTable.set_active_scheme(self.old_scheme) + self.Colors = self.ColorSchemeTable.active_colors + else: + self.old_scheme = self.ColorSchemeTable.active_scheme_name + self.ColorSchemeTable.set_active_scheme('NoColor') + self.Colors = self.ColorSchemeTable.active_colors + +#--------------------------------------------------------------------------- +class ListTB(TBTools): + """Print traceback information from a traceback list, with optional color. + + Calling: requires 3 arguments: + (etype, evalue, elist) + as would be obtained by: + etype, evalue, tb = sys.exc_info() + if tb: + elist = traceback.extract_tb(tb) + else: + elist = None + + It can thus be used by programs which need to process the traceback before + printing (such as console replacements based on the code module from the + standard library). + + Because they are meant to be called without a full traceback (only a + list), instances of this class can't call the interactive pdb debugger.""" + + def __init__(self,color_scheme = 'NoColor'): + TBTools.__init__(self,color_scheme = color_scheme,call_pdb=0) + + def __call__(self, etype, value, elist): + print >> Term.cerr, self.text(etype,value,elist) + + def text(self,etype, value, elist,context=5): + """Return a color formatted string with the traceback info.""" + + Colors = self.Colors + out_string = ['%s%s%s\n' % (Colors.topline,'-'*60,Colors.Normal)] + if elist: + out_string.append('Traceback %s(most recent call last)%s:' % \ + (Colors.normalEm, Colors.Normal) + '\n') + out_string.extend(self._format_list(elist)) + lines = self._format_exception_only(etype, value) + for line in lines[:-1]: + out_string.append(" "+line) + out_string.append(lines[-1]) + return ''.join(out_string) + + def _format_list(self, extracted_list): + """Format a list of traceback entry tuples for printing. + + Given a list of tuples as returned by extract_tb() or + extract_stack(), return a list of strings ready for printing. + Each string in the resulting list corresponds to the item with the + same index in the argument list. Each string ends in a newline; + the strings may contain internal newlines as well, for those items + whose source text line is not None. + + Lifted almost verbatim from traceback.py + """ + + Colors = self.Colors + list = [] + for filename, lineno, name, line in extracted_list[:-1]: + item = ' File %s"%s"%s, line %s%d%s, in %s%s%s\n' % \ + (Colors.filename, filename, Colors.Normal, + Colors.lineno, lineno, Colors.Normal, + Colors.name, name, Colors.Normal) + if line: + item = item + ' %s\n' % line.strip() + list.append(item) + # Emphasize the last entry + filename, lineno, name, line = extracted_list[-1] + item = '%s File %s"%s"%s, line %s%d%s, in %s%s%s%s\n' % \ + (Colors.normalEm, + Colors.filenameEm, filename, Colors.normalEm, + Colors.linenoEm, lineno, Colors.normalEm, + Colors.nameEm, name, Colors.normalEm, + Colors.Normal) + if line: + item = item + '%s %s%s\n' % (Colors.line, line.strip(), + Colors.Normal) + list.append(item) + return list + + def _format_exception_only(self, etype, value): + """Format the exception part of a traceback. + + The arguments are the exception type and value such as given by + sys.last_type and sys.last_value. The return value is a list of + strings, each ending in a newline. Normally, the list contains a + single string; however, for SyntaxError exceptions, it contains + several lines that (when printed) display detailed information + about where the syntax error occurred. The message indicating + which exception occurred is the always last string in the list. + + Also lifted nearly verbatim from traceback.py + """ + + Colors = self.Colors + list = [] + if type(etype) == types.ClassType: + stype = Colors.excName + etype.__name__ + Colors.Normal + else: + stype = etype # String exceptions don't get special coloring + if value is None: + list.append( str(stype) + '\n') + else: + if etype is SyntaxError: + try: + msg, (filename, lineno, offset, line) = value + except: + pass + else: + #print 'filename is',filename # dbg + if not filename: filename = "<string>" + list.append('%s File %s"%s"%s, line %s%d%s\n' % \ + (Colors.normalEm, + Colors.filenameEm, filename, Colors.normalEm, + Colors.linenoEm, lineno, Colors.Normal )) + if line is not None: + i = 0 + while i < len(line) and line[i].isspace(): + i = i+1 + list.append('%s %s%s\n' % (Colors.line, + line.strip(), + Colors.Normal)) + if offset is not None: + s = ' ' + for c in line[i:offset-1]: + if c.isspace(): + s = s + c + else: + s = s + ' ' + list.append('%s%s^%s\n' % (Colors.caret, s, + Colors.Normal) ) + value = msg + s = self._some_str(value) + if s: + list.append('%s%s:%s %s\n' % (str(stype), Colors.excName, + Colors.Normal, s)) + else: + list.append('%s\n' % str(stype)) + return list + + def _some_str(self, value): + # Lifted from traceback.py + try: + return str(value) + except: + return '<unprintable %s object>' % type(value).__name__ + +#---------------------------------------------------------------------------- +class VerboseTB(TBTools): + """A port of Ka-Ping Yee's cgitb.py module that outputs color text instead + of HTML. Requires inspect and pydoc. Crazy, man. + + Modified version which optionally strips the topmost entries from the + traceback, to be used with alternate interpreters (because their own code + would appear in the traceback).""" + + def __init__(self,color_scheme = 'Linux',tb_offset=0,long_header=0, + call_pdb = 0, include_vars=1): + """Specify traceback offset, headers and color scheme. + + Define how many frames to drop from the tracebacks. Calling it with + tb_offset=1 allows use of this handler in interpreters which will have + their own code at the top of the traceback (VerboseTB will first + remove that frame before printing the traceback info).""" + TBTools.__init__(self,color_scheme=color_scheme,call_pdb=call_pdb) + self.tb_offset = tb_offset + self.long_header = long_header + self.include_vars = include_vars + + def text(self, etype, evalue, etb, context=5): + """Return a nice text document describing the traceback.""" + + # some locals + Colors = self.Colors # just a shorthand + quicker name lookup + ColorsNormal = Colors.Normal # used a lot + indent_size = 8 # we need some space to put line numbers before + indent = ' '*indent_size + numbers_width = indent_size - 1 # leave space between numbers & code + text_repr = pydoc.text.repr + exc = '%s%s%s' % (Colors.excName, str(etype), ColorsNormal) + em_normal = '%s\n%s%s' % (Colors.valEm, indent,ColorsNormal) + undefined = '%sundefined%s' % (Colors.em, ColorsNormal) + + # some internal-use functions + def eqrepr(value, repr=text_repr): return '=%s' % repr(value) + def nullrepr(value, repr=text_repr): return '' + + # meat of the code begins + if type(etype) is types.ClassType: + etype = etype.__name__ + + if self.long_header: + # Header with the exception type, python version, and date + pyver = 'Python ' + string.split(sys.version)[0] + ': ' + sys.executable + date = time.ctime(time.time()) + + head = '%s%s%s\n%s%s%s\n%s' % (Colors.topline, '-'*75, ColorsNormal, + exc, ' '*(75-len(str(etype))-len(pyver)), + pyver, string.rjust(date, 75) ) + head += "\nA problem occured executing Python code. Here is the sequence of function"\ + "\ncalls leading up to the error, with the most recent (innermost) call last." + else: + # Simplified header + head = '%s%s%s\n%s%s' % (Colors.topline, '-'*75, ColorsNormal,exc, + string.rjust('Traceback (most recent call last)', + 75 - len(str(etype)) ) ) + frames = [] + # Flush cache before calling inspect. This helps alleviate some of the + # problems with python 2.3's inspect.py. + linecache.checkcache() + # Drop topmost frames if requested + try: + records = inspect.getinnerframes(etb, context)[self.tb_offset:] + except: + + # FIXME: I've been getting many crash reports from python 2.3 + # users, traceable to inspect.py. If I can find a small test-case + # to reproduce this, I should either write a better workaround or + # file a bug report against inspect (if that's the real problem). + # So far, I haven't been able to find an isolated example to + # reproduce the problem. + inspect_error() + traceback.print_exc(file=Term.cerr) + info('\nUnfortunately, your original traceback can not be constructed.\n') + return '' + + # build some color string templates outside these nested loops + tpl_link = '%s%%s%s' % (Colors.filenameEm,ColorsNormal) + tpl_call = 'in %s%%s%s%%s%s' % (Colors.vName, Colors.valEm, + ColorsNormal) + tpl_call_fail = 'in %s%%s%s(***failed resolving arguments***)%s' % \ + (Colors.vName, Colors.valEm, ColorsNormal) + tpl_local_var = '%s%%s%s' % (Colors.vName, ColorsNormal) + tpl_global_var = '%sglobal%s %s%%s%s' % (Colors.em, ColorsNormal, + Colors.vName, ColorsNormal) + tpl_name_val = '%%s %s= %%s%s' % (Colors.valEm, ColorsNormal) + tpl_line = '%s%%s%s %%s' % (Colors.lineno, ColorsNormal) + tpl_line_em = '%s%%s%s %%s%s' % (Colors.linenoEm,Colors.line, + ColorsNormal) + + # now, loop over all records printing context and info + abspath = os.path.abspath + for frame, file, lnum, func, lines, index in records: + #print '*** record:',file,lnum,func,lines,index # dbg + try: + file = file and abspath(file) or '?' + except OSError: + # if file is '<console>' or something not in the filesystem, + # the abspath call will throw an OSError. Just ignore it and + # keep the original file string. + pass + link = tpl_link % file + try: + args, varargs, varkw, locals = inspect.getargvalues(frame) + except: + # This can happen due to a bug in python2.3. We should be + # able to remove this try/except when 2.4 becomes a + # requirement. Bug details at http://python.org/sf/1005466 + inspect_error() + traceback.print_exc(file=Term.cerr) + info("\nIPython's exception reporting continues...\n") + + if func == '?': + call = '' + else: + # Decide whether to include variable details or not + var_repr = self.include_vars and eqrepr or nullrepr + try: + call = tpl_call % (func,inspect.formatargvalues(args, + varargs, varkw, + locals,formatvalue=var_repr)) + except KeyError: + # Very odd crash from inspect.formatargvalues(). The + # scenario under which it appeared was a call to + # view(array,scale) in NumTut.view.view(), where scale had + # been defined as a scalar (it should be a tuple). Somehow + # inspect messes up resolving the argument list of view() + # and barfs out. At some point I should dig into this one + # and file a bug report about it. + inspect_error() + traceback.print_exc(file=Term.cerr) + info("\nIPython's exception reporting continues...\n") + call = tpl_call_fail % func + + # Initialize a list of names on the current line, which the + # tokenizer below will populate. + names = [] + + def tokeneater(token_type, token, start, end, line): + """Stateful tokeneater which builds dotted names. + + The list of names it appends to (from the enclosing scope) can + contain repeated composite names. This is unavoidable, since + there is no way to disambguate partial dotted structures until + the full list is known. The caller is responsible for pruning + the final list of duplicates before using it.""" + + # build composite names + if token == '.': + try: + names[-1] += '.' + # store state so the next token is added for x.y.z names + tokeneater.name_cont = True + return + except IndexError: + pass + if token_type == tokenize.NAME and token not in keyword.kwlist: + if tokeneater.name_cont: + # Dotted names + names[-1] += token + tokeneater.name_cont = False + else: + # Regular new names. We append everything, the caller + # will be responsible for pruning the list later. It's + # very tricky to try to prune as we go, b/c composite + # names can fool us. The pruning at the end is easy + # to do (or the caller can print a list with repeated + # names if so desired. + names.append(token) + elif token_type == tokenize.NEWLINE: + raise IndexError + # we need to store a bit of state in the tokenizer to build + # dotted names + tokeneater.name_cont = False + + def linereader(file=file, lnum=[lnum], getline=linecache.getline): + line = getline(file, lnum[0]) + lnum[0] += 1 + return line + + # Build the list of names on this line of code where the exception + # occurred. + try: + # This builds the names list in-place by capturing it from the + # enclosing scope. + tokenize.tokenize(linereader, tokeneater) + except IndexError: + # signals exit of tokenizer + pass + except tokenize.TokenError,msg: + _m = ("An unexpected error occurred while tokenizing input\n" + "The following traceback may be corrupted or invalid\n" + "The error message is: %s\n" % msg) + error(_m) + + # prune names list of duplicates, but keep the right order + unique_names = uniq_stable(names) + + # Start loop over vars + lvals = [] + if self.include_vars: + for name_full in unique_names: + name_base = name_full.split('.',1)[0] + if name_base in frame.f_code.co_varnames: + if locals.has_key(name_base): + try: + value = repr(eval(name_full,locals)) + except: + value = undefined + else: + value = undefined + name = tpl_local_var % name_full + else: + if frame.f_globals.has_key(name_base): + try: + value = repr(eval(name_full,frame.f_globals)) + except: + value = undefined + else: + value = undefined + name = tpl_global_var % name_full + lvals.append(tpl_name_val % (name,value)) + if lvals: + lvals = '%s%s' % (indent,em_normal.join(lvals)) + else: + lvals = '' + + level = '%s %s\n' % (link,call) + excerpt = [] + if index is not None: + i = lnum - index + for line in lines: + if i == lnum: + # This is the line with the error + pad = numbers_width - len(str(i)) + if pad >= 3: + marker = '-'*(pad-3) + '-> ' + elif pad == 2: + marker = '> ' + elif pad == 1: + marker = '>' + else: + marker = '' + num = '%s%s' % (marker,i) + line = tpl_line_em % (num,line) + else: + num = '%*s' % (numbers_width,i) + line = tpl_line % (num,line) + + excerpt.append(line) + if self.include_vars and i == lnum: + excerpt.append('%s\n' % lvals) + i += 1 + frames.append('%s%s' % (level,''.join(excerpt)) ) + + # Get (safely) a string form of the exception info + try: + etype_str,evalue_str = map(str,(etype,evalue)) + except: + # User exception is improperly defined. + etype,evalue = str,sys.exc_info()[:2] + etype_str,evalue_str = map(str,(etype,evalue)) + # ... and format it + exception = ['%s%s%s: %s' % (Colors.excName, etype_str, + ColorsNormal, evalue_str)] + if type(evalue) is types.InstanceType: + for name in dir(evalue): + value = text_repr(getattr(evalue, name)) + exception.append('\n%s%s = %s' % (indent, name, value)) + # return all our info assembled as a single string + return '%s\n\n%s\n%s' % (head,'\n'.join(frames),''.join(exception[0]) ) + + def debugger(self): + """Call up the pdb debugger if desired, always clean up the tb reference. + + If the call_pdb flag is set, the pdb interactive debugger is + invoked. In all cases, the self.tb reference to the current traceback + is deleted to prevent lingering references which hamper memory + management. + + Note that each call to pdb() does an 'import readline', so if your app + requires a special setup for the readline completers, you'll have to + fix that by hand after invoking the exception handler.""" + + if self.call_pdb: + if self.pdb is None: + self.pdb = Debugger.Pdb() + # the system displayhook may have changed, restore the original for pdb + dhook = sys.displayhook + sys.displayhook = sys.__displayhook__ + self.pdb.reset() + while self.tb.tb_next is not None: + self.tb = self.tb.tb_next + try: + self.pdb.interaction(self.tb.tb_frame, self.tb) + except: + print '*** ERROR ***' + print 'This version of pdb has a bug and crashed.' + print 'Returning to IPython...' + sys.displayhook = dhook + del self.tb + + def handler(self, info=None): + (etype, evalue, etb) = info or sys.exc_info() + self.tb = etb + print >> Term.cerr, self.text(etype, evalue, etb) + + # Changed so an instance can just be called as VerboseTB_inst() and print + # out the right info on its own. + def __call__(self, etype=None, evalue=None, etb=None): + """This hook can replace sys.excepthook (for Python 2.1 or higher).""" + if etb is not None: + self.handler((etype, evalue, etb)) + else: + self.handler() + self.debugger() + +#---------------------------------------------------------------------------- +class FormattedTB(VerboseTB,ListTB): + """Subclass ListTB but allow calling with a traceback. + + It can thus be used as a sys.excepthook for Python > 2.1. + + Also adds 'Context' and 'Verbose' modes, not available in ListTB. + + Allows a tb_offset to be specified. This is useful for situations where + one needs to remove a number of topmost frames from the traceback (such as + occurs with python programs that themselves execute other python code, + like Python shells). """ + + def __init__(self, mode = 'Plain', color_scheme='Linux', + tb_offset = 0,long_header=0,call_pdb=0,include_vars=0): + + # NEVER change the order of this list. Put new modes at the end: + self.valid_modes = ['Plain','Context','Verbose'] + self.verbose_modes = self.valid_modes[1:3] + + VerboseTB.__init__(self,color_scheme,tb_offset,long_header, + call_pdb=call_pdb,include_vars=include_vars) + self.set_mode(mode) + + def _extract_tb(self,tb): + if tb: + return traceback.extract_tb(tb) + else: + return None + + def text(self, etype, value, tb,context=5,mode=None): + """Return formatted traceback. + + If the optional mode parameter is given, it overrides the current + mode.""" + + if mode is None: + mode = self.mode + if mode in self.verbose_modes: + # verbose modes need a full traceback + return VerboseTB.text(self,etype, value, tb,context=5) + else: + # We must check the source cache because otherwise we can print + # out-of-date source code. + linecache.checkcache() + # Now we can extract and format the exception + elist = self._extract_tb(tb) + if len(elist) > self.tb_offset: + del elist[:self.tb_offset] + return ListTB.text(self,etype,value,elist) + + def set_mode(self,mode=None): + """Switch to the desired mode. + + If mode is not specified, cycles through the available modes.""" + + if not mode: + new_idx = ( self.valid_modes.index(self.mode) + 1 ) % \ + len(self.valid_modes) + self.mode = self.valid_modes[new_idx] + elif mode not in self.valid_modes: + raise ValueError, 'Unrecognized mode in FormattedTB: <'+mode+'>\n'\ + 'Valid modes: '+str(self.valid_modes) + else: + self.mode = mode + # include variable details only in 'Verbose' mode + self.include_vars = (self.mode == self.valid_modes[2]) + + # some convenient shorcuts + def plain(self): + self.set_mode(self.valid_modes[0]) + + def context(self): + self.set_mode(self.valid_modes[1]) + + def verbose(self): + self.set_mode(self.valid_modes[2]) + +#---------------------------------------------------------------------------- +class AutoFormattedTB(FormattedTB): + """A traceback printer which can be called on the fly. + + It will find out about exceptions by itself. + + A brief example: + + AutoTB = AutoFormattedTB(mode = 'Verbose',color_scheme='Linux') + try: + ... + except: + AutoTB() # or AutoTB(out=logfile) where logfile is an open file object + """ + def __call__(self,etype=None,evalue=None,etb=None, + out=None,tb_offset=None): + """Print out a formatted exception traceback. + + Optional arguments: + - out: an open file-like object to direct output to. + + - tb_offset: the number of frames to skip over in the stack, on a + per-call basis (this overrides temporarily the instance's tb_offset + given at initialization time. """ + + if out is None: + out = Term.cerr + 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() + self.debugger() + + def text(self,etype=None,value=None,tb=None,context=5,mode=None): + if etype is None: + etype,value,tb = sys.exc_info() + self.tb = tb + return FormattedTB.text(self,etype,value,tb,context=5,mode=mode) + +#--------------------------------------------------------------------------- +# A simple class to preserve Nathan's original functionality. +class ColorTB(FormattedTB): + """Shorthand to initialize a FormattedTB in Linux colors mode.""" + def __init__(self,color_scheme='Linux',call_pdb=0): + FormattedTB.__init__(self,color_scheme=color_scheme, + call_pdb=call_pdb) + +#---------------------------------------------------------------------------- +# module testing (minimal) +if __name__ == "__main__": + def spam(c, (d, e)): + x = c + d + y = c * d + foo(x, y) + + def foo(a, b, bar=1): + eggs(a, b + bar) + + def eggs(f, g, z=globals()): + h = f + g + i = f - g + return h / i + + print '' + print '*** Before ***' + try: + print spam(1, (2, 3)) + except: + traceback.print_exc() + print '' + + handler = ColorTB() + print '*** ColorTB ***' + try: + print spam(1, (2, 3)) + except: + apply(handler, sys.exc_info() ) + print '' + + handler = VerboseTB() + print '*** VerboseTB ***' + try: + print spam(1, (2, 3)) + except: + apply(handler, sys.exc_info() ) + print '' + diff --git a/IPython/usage.py b/IPython/usage.py new file mode 100644 index 0000000..495fef8 --- /dev/null +++ b/IPython/usage.py @@ -0,0 +1,586 @@ +# -*- coding: utf-8 -*- +#***************************************************************************** +# Copyright (C) 2001-2004 Fernando Perez. <fperez@colorado.edu> +# +# Distributed under the terms of the BSD License. The full license is in +# the file COPYING, distributed as part of this software. +#***************************************************************************** + +# $Id: usage.py 578 2005-05-13 21:16:51Z fperez $ + +from IPython import Release +__author__ = '%s <%s>' % Release.authors['Fernando'] +__license__ = Release.license +__version__ = Release.version + +__doc__ = """ +IPython -- An enhanced Interactive Python +========================================= + +A Python shell with automatic history (input and output), dynamic object +introspection, easier configuration, command completion, access to the system +shell and more. + +IPython can also be embedded in running programs. See EMBEDDING below. + + +USAGE + ipython [options] files + + 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 python -i will + only execute one file and will ignore your configuration setup. + + 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 $HOME/.ipython directory. + + For Windows users, $HOME resolves to C:\\Documents and + Settings\\YourUserName in most instances, and _ipython is used instead + of .ipython, since some Win32 programs have problems with dotted names + in directories. + + In the rest of this text, we will refer to this directory as + IPYTHONDIR. + + +SPECIAL THREADING OPTIONS + 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. + + -gthread, -qthread, -wthread, -pylab + + 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, QT + and WXWidgets toolkits, and for the matplotlib library. + + With any of the first three 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 three provide + essentially the same functionality, respectively for GTK, QT and + WXWidgets (via their Python interfaces). + + If -pylab is given, IPython loads special support for the mat- + plotlib library (http://matplotlib.sourceforge.net), allowing + interactive usage of any of its backends as defined in the + user's .matplotlibrc file. It automatically activates GTK, QT + or WX threading for IPyhton if the choice of matplotlib backend + requires it. It also modifies the %run command to correctly + execute (without blocking) any matplotlib-based script which + calls show() at the end. + + -tk The -g/q/wthread options, and -pylab (if matplotlib is + configured to use GTK, QT or WX), will normally block Tk + graphical interfaces. This means that when 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, -tk, is available to address this + issue. It can ONLY be given as a SECOND option after any of the + above (-gthread, -qthread, -wthread or -pylab). + + If -tk 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. + + There is unfortunately no way for IPython to determine at run- + time whether -tk will work reliably or not, so you will need to + do some experiments before relying on it for regular work. + +A WARNING ABOUT SIGNALS AND THREADS + + When any of the thread systems (GTK, QT or WX) are active, either + directly or via -pylab with a threaded backend, it is impossible to + interrupt long-running Python code via Ctrl-C. IPython can not pass + the KeyboardInterrupt exception (or the underlying SIGINT) across + threads, so any long-running process started from IPython will run to + completion, or will have to be killed via an external (OS-based) + mechanism. + + To the best of my knowledge, this limitation is imposed by the Python + interpreter itself, and it comes from the difficulty of writing + portable signal/threaded code. If any user is an expert on this topic + and can suggest a better solution, I would love to hear about it. In + the IPython sources, look at the Shell.py module, and in particular at + the runcode() method. + +REGULAR OPTIONS + 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 |. + + Most options can also be set from your ipythonrc configuration file. + See the provided examples for assistance. Options given on the comman- + dline override the values set in the ipythonrc file. + + All options with a no| prepended can be specified in ’no’ form (-noop- + tion instead of -option) to turn the feature off. + + -h, --help + Show summary of options. + + -pylab This can only be given as the first option passed to IPython (it + will have no effect in any other position). It adds special sup- + port for the matplotlib library (http://matplotlib.source- + forge.net), allowing interactive usage of any of its backends as + defined in the user’s .matplotlibrc file. It automatically + activates GTK or WX threading for IPyhton if the choice of mat- + plotlib backend requires it. It also modifies the @run command + to correctly execute (without blocking) any matplotlib-based + script which calls show() at the end. + + -no|autocall + Make IPython automatically call any callable object even if you + didn’t type explicit parentheses. For example, ’str 43’ becomes + ’str(43)’ automatically. + + -no|autoindent + Turn automatic indentation on/off. + + -no|automagic + Make magic commands automatic (without needing their first char- + acter to be @). Type @magic at the IPython prompt for more + information. + + -no|autoparens + Make IPython automatically call any callable object even if you + didn’t type explicit parentheses. For example, ’str 43’ becomes + ’str(43)’ automatically. + + -no|banner + Print the intial information banner (default on). + + -c <command> + Execute the given command string, and set sys.argv to [’c’]. + This is similar to the -c option in the normal Python inter- + preter. + + -cache_size|cs <n> + 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. + + -classic|cl + Gives IPython a similar feel to the classic Python prompt. + + -colors <scheme> + Color scheme for prompts and exception reporting. Currently + implemented: NoColor, Linux, and LightBG. + + -no|color_info + IPython can display information about objects via a set of func- + tions, and optionally can use colors for this, syntax highlight- + ing 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. + + Test it and turn it on permanently if it works with your system. + The magic function @color_info allows you to toggle this inter- + actively for testing. + + -no|confirm_exit + Set to confirm when you try to exit IPython with an EOF (Con- + trol-D in Unix, Control-Z/Enter in Windows). Note that using the + magic functions @Exit or @Quit you can force a direct exit, + bypassing any confirmation. + + -no|debug + Show information about the loading process. Very useful to pin + down problems with your configuration files or to get details + about session restores. + + -no|deep_reload + IPython can use the deep_reload module which reloads changes in + modules recursively (it replaces the reload() function, so you + don’t need to change anything to use it). deep_reload() forces a + full reload of modules whose code may have changed, which the + default reload() function does not. + + When deep_reload is off, IPython will use the normal reload(), + but deep_reload will still be available as dreload(). This fea- + ture is off by default [which means that you have both normal + reload() and dreload()]. + + -editor <name> + Which editor to use with the @edit command. By default, IPython + will honor your EDITOR 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 EDITOR is something like Emacs). + + -ipythondir <name> + The name of your IPython configuration directory IPYTHONDIR. + This can also be specified through the environment variable + IPYTHONDIR. + + -log|l Generate a log file of all input. The file is named ipython.log + 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 -logplay (see below). + + -logfile|lf + Specifu the name of your logfile. + + -logplay|lp + Replay a previous log. For restoring a session as close as pos- + sible to the state you left it in, use this option (don’t just + run the logfile). With -logplay, IPython will try to reconstruct + the previous working environment in full, not just execute the + commands in the logfile. + 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. + + Caveats: there are limitations in this option. The history vari- + ables _i*,_* and _dh don’t get restored properly. In the future + we will try to implement full session saving by writing and + retrieving a failed because of inherent limitations of Python’s + Pickle module, so this may have to wait. + + -no|messages + Print messages which IPython collects about its startup process + (default on). + + -no|pdb + Automatically call the pdb debugger after every uncaught excep- + tion. 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. + + -no|pprint + 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 per- + manently in your config file (default off). + + -profile|p <name> + Assume that your config file is ipythonrc-<name> (looks in cur- + rent dir first, then in IPYTHONDIR). 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 IPYTHONDIR/ipythonrc file and then have other ’profiles’ + which include this one and load extra things for particular + tasks. For example: + + 1) $HOME/.ipython/ipythonrc : load basic things you always want. + 2) $HOME/.ipython/ipythonrc-math : load (1) and basic math- + related modules. + 3) $HOME/.ipython/ipythonrc-numeric : load (1) and Numeric and + plotting modules. + + Since it is possible to create an endless loop by having circu- + lar file inclusions, IPython will stop if it reaches 15 recur- + sive inclusions. + + -prompt_in1|pi1 <string> + Specify the string used for input prompts. Note that if you are + using numbered prompts, the number is represented with a ’\#’ in + the string. Don’t forget to quote strings with spaces embedded + in them. Default: ’In [\#]:’. + + Most bash-like escapes can be used to customize IPython’s + prompts, as well as a few additional ones which are IPython-spe- + cific. All valid prompt escapes are described in detail in the + Customization section of the IPython HTML/PDF manual. + + -prompt_in2|pi2 <string> + Similar to the previous option, but used for the continuation + prompts. The special sequence ’\D’ is similar to ’\#’, but with + all digits replaced dots (so you can have your continuation + prompt aligned with your input prompt). Default: ’ .\D.:’ + (note three spaces at the start for alignment with ’In [\#]’). + + -prompt_out|po <string> + String used for output prompts, also uses numbers like + prompt_in1. Default: ’Out[\#]:’. + + -quick Start in bare bones mode (no config file loaded). + + -rcfile <name> + Name of your IPython resource configuration file. normally + IPython loads ipythonrc (from current directory) or + IPYTHONDIR/ipythonrc. If the loading of your config file fails, + IPython starts with a bare bones configuration (no modules + loaded at all). + + -no|readline + Use the readline library, which is needed to support name com- + pletion 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. + + Note that emacs ’eterm’ buffers (opened with M-x term) support + IPython’s readline and syntax coloring fine, only ’emacs’ (M-x + shell and C-c !) buffers do not. + + -screen_length|sl <n> + Number of lines of your screen. This is used to control print- + ing of very long strings. Strings longer than this number of + lines will be sent through a pager instead of directly printed. + + 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. + + -separate_in|si <string> + Separator before input prompts. Default ’0. + + -separate_out|so <string> + Separator before output prompts. Default: 0 (nothing). + + -separate_out2|so2 <string> + Separator after output prompts. Default: 0 (nothing). + + -nosep Shorthand for ’-separate_in 0 -separate_out 0 -separate_out2 0’. + Simply removes all input/output separators. + + -upgrade + Allows you to upgrade your IPYTHONDIR configuration when you + install a new version of IPython. Since new versions may + include new command lines options or example files, this copies + updated ipythonrc-type files. However, it backs up (with a .old + extension) all files which it overwrites so that you can merge + back any custimizations you might have in your personal files. + + -Version + Print version information and exit. + + -xmode <modename> + Mode for exception reporting. The valid modes are Plain, Con- + text, and Verbose. + + - Plain: similar to python’s normal traceback printing. + + - Context: prints 5 lines of context source code around each + line in the traceback. + + - Verbose: similar to Context, but additionally prints the vari- + ables 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 repre- + sentation 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). + + +EMBEDDING + It is possible to start an IPython instance inside your own Python pro- + grams. In the documentation example files there are some illustrations + on how to do this. + + This feature allows you to evalutate dynamically the state of your + code, operate with your variables, analyze them, etc. Note however + that any changes you make to values while in the shell do NOT propagate + back to the running code, so it is safe to modify your values because + you won’t break your code in bizarre ways by doing so. +""" + +cmd_line_usage = __doc__ + +#--------------------------------------------------------------------------- +interactive_usage = """ +IPython -- An enhanced Interactive Python +========================================= + +IPython offers a combination of convenient shell features, special commands +and a history mechanism for both input (command history) and output (results +caching, similar to Mathematica). It is intended to be a fully compatible +replacement for the standard Python interpreter, while offering vastly +improved functionality and flexibility. + +At your system command line, type 'ipython -help' to see the command line +options available. This document only describes interactive features. + +Warning: IPython relies on the existence of a global variable called __IP which +controls the shell itself. If you redefine __IP to anything, bizarre behavior +will quickly occur. + +MAIN FEATURES + +* Access to the standard Python help. As of Python 2.1, a help system is + available with access to object docstrings and the Python manuals. Simply + type 'help' (no quotes) to access it. + +* Magic commands: type %magic for information on the magic subsystem. + +* System command aliases, via the %alias command or the ipythonrc config file. + +* Dynamic object information: + + Typing ?word or word? 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. + + Typing ??word or word?? gives access to the full information without + snipping long strings. Long strings are sent to the screen through the less + pager if longer than the screen, printed otherwise. + + The ?/?? system gives access to the full source code for any object (if + available), shows function prototypes and other useful information. + + If you just want to see an object's docstring, type '%pdoc object' (without + quotes, and without % if you have automagic on). + + Both %pdoc and ?/?? give you access to documentation even on things which are + not explicitely defined. Try for example typing {}.get? or after import os, + type os.path.abspath??. The magic functions %pdef, %source and %file operate + similarly. + +* Completion in the local namespace, by typing TAB at the prompt. + + At any time, hitting tab will complete any available python commands or + variable names, and show you a list of the possible completions if there's + no unambiguous one. It will also complete filenames in the current directory. + + This feature requires the readline and rlcomplete modules, so it won't work + if your Python lacks readline support (such as under Windows). + +* Search previous command history in two ways (also requires readline): + + - Start typing, and then use Ctrl-p (previous,up) and Ctrl-n (next,down) to + search through only the history items that match what you've typed so + far. If you use Ctrl-p/Ctrl-n at a blank prompt, they just behave like + normal arrow keys. + + - Hit Ctrl-r: opens a search prompt. Begin typing and the system searches + your history for lines that match what you've typed so far, completing as + much as it can. + +* Persistent command history across sessions (readline required). + +* Logging of input with the ability to save and restore a working session. + +* System escape with !. Typing !ls will run 'ls' in the current directory. + +* The reload command does a 'deep' reload of a module: changes made to the + module since you imported will actually be available without having to exit. + +* Verbose and colored exception traceback printouts. See the magic xmode and + xcolor functions for details (just type %magic). + +* Input caching system: + + IPython offers numbered prompts (In/Out) with input and output caching. All + input is saved and can be retrieved as variables (besides the usual arrow + key recall). + + The following GLOBAL variables always exist (so don't overwrite them!): + _i: stores previous input. + _ii: next previous. + _iii: next-next previous. + _ih : a list of all input _ih[n] is the input from line n. + + Additionally, global variables named _i<n> are dynamically created (<n> + being the prompt counter), such that _i<n> == _ih[<n>] + + For example, what you typed at prompt 14 is available as _i14 and _ih[14]. + + You can create macros which contain multiple input lines from this history, + for later re-execution, with the %macro function. + + The history function %hist allows you to see any part of your input history + by printing a range of the _i variables. Note that inputs which contain + magic functions (%) appear in the history with a prepended comment. This is + because they aren't really valid Python code, so you can't exec them. + +* Output caching system: + + For output that is returned from actions, a system similar to the input + cache exists but using _ instead of _i. Only actions that produce a result + (NOT assignments, for example) are cached. If you are familiar with + Mathematica, IPython's _ variables behave exactly like Mathematica's % + variables. + + The following GLOBAL variables always exist (so don't overwrite them!): + _ (one underscore): previous output. + __ (two underscores): next previous. + ___ (three underscores): next-next previous. + + Global variables named _<n> are dynamically created (<n> being the prompt + counter), such that the result of output <n> is always available as _<n>. + + Finally, a global dictionary named _oh exists with entries for all lines + which generated output. + +* Directory history: + + Your history of visited directories is kept in the global list _dh, and the + magic %cd command can be used to go to any entry in that list. + +* Auto-parentheses and auto-quotes (adapted from Nathan Gray's LazyPython) + + 1. Auto-parentheses + Callable objects (i.e. functions, methods, etc) can be invoked like + this (notice the commas between the arguments): + >>> callable_ob arg1, arg2, arg3 + and the input will be translated to this: + --> callable_ob(arg1, arg2, arg3) + You can force auto-parentheses by using '/' as the first character + of a line. For example: + >>> /globals # becomes 'globals()' + Note that the '/' MUST be the first character on the line! This + won't work: + >>> print /globals # syntax error + + In most cases the automatic algorithm should work, so you should + rarely need to explicitly invoke /. One notable exception is if you + are trying to call a function with a list of tuples as arguments (the + parenthesis will confuse IPython): + In [1]: zip (1,2,3),(4,5,6) # won't work + but this will work: + In [2]: /zip (1,2,3),(4,5,6) + ------> zip ((1,2,3),(4,5,6)) + Out[2]= [(1, 4), (2, 5), (3, 6)] + + IPython tells you that it has altered your command line by + displaying the new command line preceded by -->. e.g.: + In [18]: callable list + -------> callable (list) + + 2. Auto-Quoting + You can force auto-quoting of a function's arguments by using ',' as + the first character of a line. For example: + >>> ,my_function /home/me # becomes my_function("/home/me") + + If you use ';' instead, the whole argument is quoted as a single + string (while ',' splits on whitespace): + >>> ,my_function a b c # becomes my_function("a","b","c") + >>> ;my_function a b c # becomes my_function("a b c") + + Note that the ',' MUST be the first character on the line! This + won't work: + >>> x = ,my_function /home/me # syntax error +""" diff --git a/MANIFEST.in b/MANIFEST.in new file mode 100644 index 0000000..745ee70 --- /dev/null +++ b/MANIFEST.in @@ -0,0 +1,29 @@ +include README_Windows.txt +include win32_manual_post_install.py + +graft scripts + +graft setupext + +graft IPython/UserConfig + +graft doc +exclude doc/*.1 +exclude doc/*.lyx +exclude doc/ChangeLog.* +exclude doc/#* +exclude doc/magic.tex +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 + +global-exclude *~ +global-exclude *.flc +global-exclude *.pyc +global-exclude .dircopy.log diff --git a/README b/README new file mode 100644 index 0000000..3cfe159 --- /dev/null +++ b/README @@ -0,0 +1,12 @@ +Please see the doc/ directory for full manuals and other documents. The manual is +prepared using the LyX system (www.lyx.org), but in the doc/manual directory +you'll find HTML and PDF versions. + +These manuals normally get installed to $PREFIX/share/doc/ipython-VERSION, unless you +redirect the installer via a --prefix/--home option. Normally, $PREFIX is +/usr, but your Python may be installed elsewhere. You can see its value by +running: + +python -c "import sys;print sys.prefix" + +# testing notes... diff --git a/README_Windows.txt b/README_Windows.txt new file mode 100644 index 0000000..b69bfce --- /dev/null +++ b/README_Windows.txt @@ -0,0 +1,42 @@ +Notes for Windows Users +======================= + +These are just minimal notes. The manual contains more detailed +information. + +Requirements +------------ + +IPython runs under (as far as the Windows family is concerned): + +- Windows XP (I think WinNT/2000 are ok): works well. It needs: + + * PyWin32, the win32 Python extensions from + http://starship.python.net/crew/mhammond. + + * Gary Bishop's readline from + http://sourceforge.net/projects/uncpythontools. + + * This in turn requires Tomas Heller's ctypes from + http://starship.python.net/crew/theller/ctypes. + +- Windows 95/98/ME: I have no idea. It should work, but I can't test. + +- CygWin environments should work, they are basically Posix. + +It needs Python 2.2 or newer. + + +Installation +------------ + +Double-click the supplied .exe installer file. If all goes well, that's all +you need to do. You should now have an IPython entry in your Start Menu. + +In case the automatic installer does not work for some reason, you can +download the ipython-XXX.tar.gz file, which contains the full IPython source +distribution (the popular WinZip can read .tar.gz files). After uncompressing +the archive, you can install it at a command terminal just like any other +Python module, by using python setup.py install'. After this completes, you +can run the supplied win32_manual_post_install.py script which will add +the relevant shortcuts to your startup menu. diff --git a/debian/changelog b/debian/changelog new file mode 100644 index 0000000..a5d262d --- /dev/null +++ b/debian/changelog @@ -0,0 +1,70 @@ +ipython (0.6.4-1) unstable; urgency=low + + * Fix dpatch dependency (Closes: #280505) + + -- Fernando Perez <fperez@colorado.edu> Wed Nov 17 22:54:23 MST 2004 + +ipython (0.6.3-1) unstable; urgency=low + + * New upstream release (Closes: #262244, #252525) + + -- Jack Moffitt <jack@xiph.org> Wed, 22 Sep 2004 21:39:38 -0600 + +ipython (0.6.0-1) unstable; urgency=low + + * New upstream release + + -- Jack Moffitt <jack@xiph.org> Sun, 9 May 2004 17:38:00 +0200 + +ipython (0.4.0-1.1) unstable; urgency=low + + * Non maintainer upload with maintainer consensus. + * Updated buil-dep to depend on python-2.3 (Closes: #206653) + * Included encoding comment string in modules under IPython to + avoid python2.3 Warnigs (upstream noticed). + + -- Marco Presi (Zufus) <zufus@debian.org> Mon, 25 Aug 2003 19:02:20 +0200 + +ipython (0.4.0-1) unstable; urgency=low + + * New upstream release (Closes #195215) + * Updated Build-Depends (Closes #200021) + + -- Jack Moffitt <jack@xiph.org> Fri, 25 Jul 2003 10:16:12 -0600 + +ipython (0.2.15pre3-4) unstable; urgency=low + + * Add python-dev Build-Depends (Closes: #189901) + + -- Jack Moffitt <jack@babyjesus.cantcode.com> Mon, 12 May 2003 23:33:43 -0600 + +ipython (0.2.15pre3-3) unstable; urgency=low + + * Fix for accidently converting home directory files' line ends + instead of just the appropriate ipython configuration files + (Closes: #189042) + + -- Jack Moffitt <jack@xiph.org> Mon, 14 Apr 2003 21:18:18 -0600 + +ipython (0.2.15pre3-2) unstable; urgency=low + + * Added text of the PSF license to debian/copyright. + + -- Jack Moffitt <jack@xiph.org> Sat, 5 Apr 2003 11:41:31 -0700 + +ipython (0.2.15pre3-1) unstable; urgency=low + + * Updated documentation to point to the new homepage - + http://ipython.scipy.org + * Removed doc/COPYING and doc/GNU-LGPL to fix lintian warnings + * Public release ready (Closes: #185789) + + -- Jack Moffitt <jack@xiph.org> Tue, 1 Apr 2003 20:53:31 -0700 + +ipython (0.2.15pre3-0a) unstable; urgency=low + + * Initial Release. + * This is my first Debian package + + -- Jack Moffitt <jack@xiph.org> Wed, 12 Mar 2003 21:04:22 -0700 + diff --git a/debian/compat b/debian/compat new file mode 100644 index 0000000..b8626c4 --- /dev/null +++ b/debian/compat @@ -0,0 +1 @@ +4 diff --git a/debian/control b/debian/control new file mode 100644 index 0000000..86a2d96 --- /dev/null +++ b/debian/control @@ -0,0 +1,21 @@ +Source: ipython +Section: devel +Priority: optional +Maintainer: Jack Moffitt <jack@xiph.org> +Build-Depends-Indep: debhelper (>> 4.1.65), dpatch, python-dev +Standards-Version: 3.6.1 + +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. diff --git a/debian/copyright b/debian/copyright new file mode 100644 index 0000000..01691e5 --- /dev/null +++ b/debian/copyright @@ -0,0 +1,204 @@ +This package was debianized by Jack Moffitt <jack@xiph.org> on +Wed, 12 Mar 2003 20:38:14 -0700. + +It was downloaded from http://ipython.scipy.org/ + +Upstream Author: Fernando Perez <fperez@colorado.edu>, + Janko Hauser <jhauser@zscout.de>, + Nathaniel Gray <n8gray@caltech.edu> + +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 <fperez@colorado.edu>. + +Copyright (c) 2001 Janko Hauser <jhauser@zscout.de> and Nathaniel Gray +<n8gray@caltech.edu>. + +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. + + +DPyGetOpt.py is copyright (C) 2001 by Bill Bumgarner <bbum@friday.com> +and is licensed under the MIT license, reproduced below: + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to +deal in the Software without restriction, including without limitation the +rights to use, copy, modify, merge, publish, distribute, sublicense, and/or +sell copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING +FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS +IN THE SOFTWARE. + +FlexCompleter.py is copyright (C) 2001 by the Python Software +Foundation and licensed under the terms of the Python Software +Foundation License, reproduced below: + +A. HISTORY OF THE SOFTWARE +========================== + +Python was created in the early 1990s by Guido van Rossum at Stichting +Mathematisch Centrum (CWI) in the Netherlands as a successor of a +language called ABC. Guido is Python's principal author, although it +includes many contributions from others. The last version released +from CWI was Python 1.2. In 1995, Guido continued his work on Python +at the Corporation for National Research Initiatives (CNRI) in Reston, +Virginia where he released several versions of the software. Python +1.6 was the last of the versions released by CNRI. In 2000, Guido and +the Python core development team moved to BeOpen.com to form the +BeOpen PythonLabs team. Python 2.0 was the first and only release +from BeOpen.com. + +Following the release of Python 1.6, and after Guido van Rossum left +CNRI to work with commercial software developers, it became clear that +the ability to use Python with software available under the GNU Public +License (GPL) was very desirable. CNRI and the Free Software +Foundation (FSF) interacted to develop enabling wording changes to the +Python license. Python 1.6.1 is essentially the same as Python 1.6, +with a few minor bug fixes, and with a different license that enables +later versions to be GPL-compatible. Python 2.1 is a derivative work +of Python 1.6.1, as well as of Python 2.0. + +After Python 2.0 was released by BeOpen.com, Guido van Rossum and the +other PythonLabs developers joined Digital Creations. All +intellectual property added from this point on, starting with Python +2.1 and its alpha and beta releases, is owned by the Python Software +Foundation (PSF), a non-profit modeled after the Apache Software +Foundation. See http://www.python.org/psf/ for more information about +the PSF. + +Thanks to the many outside volunteers who have worked under Guido's +direction to make these releases possible. + + +B. TERMS AND CONDITIONS FOR ACCESSING OR OTHERWISE USING PYTHON +=============================================================== + +PSF LICENSE AGREEMENT +--------------------- + +1. This LICENSE AGREEMENT is between the Python Software Foundation +("PSF"), and the Individual or Organization ("Licensee") accessing and +otherwise using Python 2.1 software in source or binary form and its +associated documentation. + +2. Subject to the terms and conditions of this License Agreement, PSF +hereby grants Licensee a nonexclusive, royalty-free, world-wide +license to reproduce, analyze, test, perform and/or display publicly, +prepare derivative works, distribute, and otherwise use Python 2.1 +alone or in any derivative version, provided, however, that PSF's +License Agreement and PSF's notice of copyright, i.e., "Copyright (c) +2001 Python Software Foundation; All Rights Reserved" are retained in +Python 2.1 alone or in any derivative version prepared by Licensee. + +3. In the event Licensee prepares a derivative work that is based on +or incorporates Python 2.1 or any part thereof, and wants to make +the derivative work available to others as provided herein, then +Licensee hereby agrees to include in any such work a brief summary of +the changes made to Python 2.1. + +4. PSF is making Python 2.1 available to Licensee on an "AS IS" +basis. PSF MAKES NO REPRESENTATIONS OR WARRANTIES, EXPRESS OR +IMPLIED. BY WAY OF EXAMPLE, BUT NOT LIMITATION, PSF MAKES NO AND +DISCLAIMS ANY REPRESENTATION OR WARRANTY OF MERCHANTABILITY OR FITNESS +FOR ANY PARTICULAR PURPOSE OR THAT THE USE OF PYTHON 2.1 WILL NOT +INFRINGE ANY THIRD PARTY RIGHTS. + +5. PSF SHALL NOT BE LIABLE TO LICENSEE OR ANY OTHER USERS OF PYTHON +2.1 FOR ANY INCIDENTAL, SPECIAL, OR CONSEQUENTIAL DAMAGES OR LOSS AS A +RESULT OF MODIFYING, DISTRIBUTING, OR OTHERWISE USING PYTHON 2.1, OR +ANY DERIVATIVE THEREOF, EVEN IF ADVISED OF THE POSSIBILITY THEREOF. + +6. This License Agreement will automatically terminate upon a material +breach of its terms and conditions. + +7. This License Agreement shall be governed by the federal +intellectual property law of the United States, including without +limitation the federal copyright law, and, to the extent such +U.S. federal law does not apply, by the law of the Commonwealth of +Virginia, excluding Virginia's conflict of law provisions. +Notwithstanding the foregoing, with regard to derivative works based +on Python 1.6.1 that incorporate non-separable material that was +previously distributed under the GNU General Public License (GPL), the +law of the Commonwealth of Virginia shall govern this License +Agreement only as to issues arising under or with respect to +Paragraphs 4, 5, and 7 of this License Agreement. Nothing in this +License Agreement shall be deemed to create any relationship of +agency, partnership, or joint venture between CNRI and Licensee. This +License Agreement does not grant permission to use CNRI trademarks or +trade name in a trademark sense to endorse or promote products or +services of Licensee, or any third party. + +8. By clicking on the "ACCEPT" button where indicated, or by copying, +installing or otherwise using Python 1.6.1, Licensee agrees to be +bound by the terms and conditions of this License Agreement. + + ACCEPT + + +CWI PERMISSIONS STATEMENT AND DISCLAIMER +---------------------------------------- + +Copyright (c) 1991 - 1995, Stichting Mathematisch Centrum Amsterdam, +The Netherlands. All rights reserved. + +Permission to use, copy, modify, and distribute this software and its +documentation for any purpose and without fee is hereby granted, +provided that the above copyright notice appear in all copies and that +both that copyright notice and this permission notice appear in +supporting documentation, and that the name of Stichting Mathematisch +Centrum or CWI not be used in advertising or publicity pertaining to +distribution of the software without specific, written prior +permission. + +STICHTING MATHEMATISCH CENTRUM DISCLAIMS ALL WARRANTIES WITH REGARD TO +THIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND +FITNESS, IN NO EVENT SHALL STICHTING MATHEMATISCH CENTRUM BE LIABLE +FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES +WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN +ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT +OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + +Itpl.py is copyright (C) 2001 Ka-Ping Yee <ping@lfw.org> and licensed +under the MIT license reproduced above. diff --git a/debian/ipython.doc-base b/debian/ipython.doc-base new file mode 100644 index 0000000..ddb97e9 --- /dev/null +++ b/debian/ipython.doc-base @@ -0,0 +1,14 @@ +Document: ipython +Title: IPython Manual +Author: Fernando Perez <fperez@colorado.edu> +Abstract: Full documentation on all features of IPython. +Section: devel + +Format: pdf +Files: /usr/share/doc/ipython/ipython.pdf + +Format: HTML +Index: /usr/share/doc/ipython/manual/index.html +Files: /usr/share/doc/ipython/manual/*.html + + diff --git a/debian/postinst b/debian/postinst new file mode 100644 index 0000000..96b2706 --- /dev/null +++ b/debian/postinst @@ -0,0 +1,13 @@ +#!/bin/sh +set -e + +OLD_MODDIR=/usr/lib/python2.2/site-packages/IPython + +if [ $1 = "configure" ]; then + if [ -d $OLD_MODDIR ];then + echo "Removing old python2.2 modules" + rm -fr $OLD_MODDIR >&2 + fi +fi + +#DEBHELPER# diff --git a/debian/rules b/debian/rules new file mode 100755 index 0000000..6bb593f --- /dev/null +++ b/debian/rules @@ -0,0 +1,98 @@ +#!/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 + + # 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 diff --git a/doc/COPYING b/doc/COPYING new file mode 100644 index 0000000..78bb2f4 --- /dev/null +++ b/doc/COPYING @@ -0,0 +1,52 @@ +IPython copyright and licensing notes +===================================== + +Unless indicated otherwise, files in this project are covered by a BSD-type +license, included below. + +Individual authors are the holders of the copyright for their code and are +listed in each file. + +Some files (DPyGetOpt.py, for example) may be licensed under different +conditions. Ultimately each file indicates clearly the conditions under which +its author/authors have decided to publish the code. + + +IPython license +--------------- + +IPython is released under a BSD-type license. + +Copyright (c) 2001, 2002, 2003, 2004 Fernando Perez <fperez@colorado.edu>. + +Copyright (c) 2001 Janko Hauser <jhauser@zscout.de> and Nathaniel Gray +<n8gray@caltech.edu>. + +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. diff --git a/doc/ChangeLog b/doc/ChangeLog new file mode 100644 index 0000000..a77e57f --- /dev/null +++ b/doc/ChangeLog @@ -0,0 +1,4243 @@ +2005-06-08 Fernando Perez <fperez@colorado.edu> + + * IPython/iplib.py (write/write_err): Add methods to abstract all + I/O a bit more. + + * IPython/Shell.py (IPShellGTK.mainloop): Fix GTK deprecation + warning, reported by Aric Hagberg, fix by JD Hunter. + +2005-06-02 *** Released version 0.6.15 + +2005-06-01 Fernando Perez <fperez@colorado.edu> + + * IPython/iplib.py (MagicCompleter.file_matches): Fix + tab-completion of filenames within open-quoted strings. Note that + this requires that in ~/.ipython/ipythonrc, users change the + readline delimiters configuration to read: + + readline_remove_delims -/~ + + +2005-05-31 *** Released version 0.6.14 + +2005-05-29 Fernando Perez <fperez@colorado.edu> + + * IPython/ultraTB.py (VerboseTB.text): Fix crash for tracebacks + with files not on the filesystem. Reported by Eliyahu Sandler + <eli@gondolin.net> + +2005-05-22 Fernando Perez <fperez@colorado.edu> + + * IPython/iplib.py: Fix a few crashes in the --upgrade option. + After an initial report by LUK ShunTim <shuntim.luk@polyu.edu.hk>. + +2005-05-19 Fernando Perez <fperez@colorado.edu> + + * IPython/iplib.py (safe_execfile): close a file which could be + left open (causing problems in win32, which locks open files). + Thanks to a bug report by D Brown <dbrown2@yahoo.com>. + +2005-05-18 Fernando Perez <fperez@colorado.edu> + + * IPython/Shell.py (MatplotlibShellBase.mplot_exec): pass all + keyword arguments correctly to safe_execfile(). + +2005-05-13 Fernando Perez <fperez@colorado.edu> + + * ipython.1: Added info about Qt to manpage, and threads warning + to usage page (invoked with --help). + + * IPython/iplib.py (MagicCompleter.python_func_kw_matches): Added + new matcher (it goes at the end of the priority list) to do + tab-completion on named function arguments. Submitted by George + Sakkis <gsakkis-AT-eden.rutgers.edu>. See the thread at + http://www.scipy.net/pipermail/ipython-dev/2005-April/000436.html + for more details. + + * IPython/Magic.py (magic_run): Added new -e flag to ignore + SystemExit exceptions in the script being run. Thanks to a report + by danny shevitz <danny_shevitz-AT-yahoo.com>, about this + producing very annoying behavior when running unit tests. + +2005-05-12 Fernando Perez <fperez@colorado.edu> + + * IPython/iplib.py (handle_auto): fixed auto-quoting and parens, + which I'd broken (again) due to a changed regexp. In the process, + added ';' as an escape to auto-quote the whole line without + splitting its arguments. Thanks to a report by Jerry McRae + <qrs0xyc02-AT-sneakemail.com>. + + * IPython/ultraTB.py (VerboseTB.text): protect against rare but + possible crashes caused by a TokenError. Reported by Ed Schofield + <schofield-AT-ftw.at>. + +2005-05-06 Fernando Perez <fperez@colorado.edu> + + * IPython/Shell.py (hijack_wx): Fix to work with WX v.2.6. + +2005-04-29 Fernando Perez <fperez@colorado.edu> + + * IPython/Shell.py (IPShellQt): Thanks to Denis Rivière + <nudz-AT-free.fr>, Yann Cointepas <yann-AT-sapetnioc.org> and Benjamin + Thyreau <Benji2-AT-decideur.info>, we now have a -qthread option + which provides support for Qt interactive usage (similar to the + existing one for WX and GTK). This had been often requested. + +2005-04-14 *** Released version 0.6.13 + +2005-04-08 Fernando Perez <fperez@colorado.edu> + + * IPython/Magic.py (Magic._ofind): remove docstring evaluation + from _ofind, which gets called on almost every input line. Now, + we only try to get docstrings if they are actually going to be + used (the overhead of fetching unnecessary docstrings can be + noticeable for certain objects, such as Pyro proxies). + + * IPython/iplib.py (MagicCompleter.python_matches): Change the API + for completers. For some reason I had been passing them the state + variable, which completers never actually need, and was in + conflict with the rlcompleter API. Custom completers ONLY need to + take the text parameter. + + * IPython/Extensions/InterpreterExec.py: Fix regexp so that magics + work correctly in pysh. I've also moved all the logic which used + to be in pysh.py here, which will prevent problems with future + upgrades. However, this time I must warn users to update their + pysh profile to include the line + + import_all IPython.Extensions.InterpreterExec + + because otherwise things won't work for them. They MUST also + delete pysh.py and the line + + execfile pysh.py + + from their ipythonrc-pysh. + + * IPython/FlexCompleter.py (Completer.attr_matches): Make more + robust in the face of objects whose dir() returns non-strings + (which it shouldn't, but some broken libs like ITK do). Thanks to + a patch by John Hunter (implemented differently, though). Also + minor improvements by using .extend instead of + on lists. + + * pysh.py: + +2005-04-06 Fernando Perez <fperez@colorado.edu> + + * IPython/ipmaker.py (make_IPython): Make multi_line_specials on + by default, so that all users benefit from it. Those who don't + want it can still turn it off. + + * IPython/UserConfig/ipythonrc: Add multi_line_specials to the + config file, I'd forgotten about this, so users were getting it + off by default. + + * IPython/iplib.py (ipmagic): big overhaul of the magic system for + consistency. Now magics can be called in multiline statements, + and python variables can be expanded in magic calls via $var. + This makes the magic system behave just like aliases or !system + calls. + +2005-03-28 Fernando Perez <fperez@colorado.edu> + + * IPython/iplib.py (handle_auto): cleanup to use %s instead of + expensive string additions for building command. Add support for + trailing ';' when autocall is used. + +2005-03-26 Fernando Perez <fperez@colorado.edu> + + * ipython.el: Fix http://www.scipy.net/roundup/ipython/issue31. + Bugfix by A. Schmolck, the ipython.el maintainer. Also make + ipython.el robust against prompts with any number of spaces + (including 0) after the ':' character. + + * IPython/Prompts.py (Prompt2.set_p_str): Fix spurious space in + continuation prompt, which misled users to think the line was + already indented. Closes debian Bug#300847, reported to me by + Norbert Tretkowski <tretkowski-AT-inittab.de>. + +2005-03-23 Fernando Perez <fperez@colorado.edu> + + * IPython/Prompts.py (Prompt1.__str__): Make sure that prompts are + properly aligned if they have embedded newlines. + + * IPython/iplib.py (runlines): Add a public method to expose + IPython's code execution machinery, so that users can run strings + as if they had been typed at the prompt interactively. + (InteractiveShell.__init__): Added getoutput() to the __IPYTHON__ + methods which can call the system shell, but with python variable + expansion. The three such methods are: __IPYTHON__.system, + .getoutput and .getoutputerror. These need to be documented in a + 'public API' section (to be written) of the manual. + +2005-03-20 Fernando Perez <fperez@colorado.edu> + + * IPython/iplib.py (InteractiveShell.set_custom_exc): new system + for custom exception handling. This is quite powerful, and it + allows for user-installable exception handlers which can trap + custom exceptions at runtime and treat them separately from + IPython's default mechanisms. At the request of Frédéric + Mantegazza <mantegazza-AT-ill.fr>. + (InteractiveShell.set_custom_completer): public API function to + add new completers at runtime. + +2005-03-19 Fernando Perez <fperez@colorado.edu> + + * IPython/OInspect.py (getdoc): Add a call to obj.getdoc(), to + allow objects which provide their docstrings via non-standard + mechanisms (like Pyro proxies) to still be inspected by ipython's + ? system. + + * IPython/iplib.py (InteractiveShell.__init__): back off the _o/_e + automatic capture system. I tried quite hard to make it work + reliably, and simply failed. I tried many combinations with the + subprocess module, but eventually nothing worked in all needed + cases (not blocking stdin for the child, duplicating stdout + without blocking, etc). The new %sc/%sx still do capture to these + magical list/string objects which make shell use much more + conveninent, so not all is lost. + + XXX - FIX MANUAL for the change above! + + (runsource): I copied code.py's runsource() into ipython to modify + it a bit. Now the code object and source to be executed are + stored in ipython. This makes this info accessible to third-party + tools, like custom exception handlers. After a request by Frédéric + Mantegazza <mantegazza-AT-ill.fr>. + + * IPython/UserConfig/ipythonrc: Add up/down arrow keys to + history-search via readline (like C-p/C-n). I'd wanted this for a + long time, but only recently found out how to do it. For users + who already have their ipythonrc files made and want this, just + add: + + readline_parse_and_bind "\e[A": history-search-backward + readline_parse_and_bind "\e[B": history-search-forward + +2005-03-18 Fernando Perez <fperez@colorado.edu> + + * IPython/Magic.py (magic_sc): %sc and %sx now use the fancy + LSString and SList classes which allow transparent conversions + between list mode and whitespace-separated string. + (magic_r): Fix recursion problem in %r. + + * IPython/genutils.py (LSString): New class to be used for + automatic storage of the results of all alias/system calls in _o + and _e (stdout/err). These provide a .l/.list attribute which + does automatic splitting on newlines. This means that for most + uses, you'll never need to do capturing of output with %sc/%sx + anymore, since ipython keeps this always done for you. Note that + only the LAST results are stored, the _o/e variables are + overwritten on each call. If you need to save their contents + further, simply bind them to any other name. + +2005-03-17 Fernando Perez <fperez@colorado.edu> + + * IPython/Prompts.py (BasePrompt.cwd_filt): a few more fixes for + prompt namespace handling. + +2005-03-16 Fernando Perez <fperez@colorado.edu> + + * IPython/Prompts.py (CachedOutput.__init__): Fix default and + classic prompts to be '>>> ' (final space was missing, and it + trips the emacs python mode). + (BasePrompt.__str__): Added safe support for dynamic prompt + strings. Now you can set your prompt string to be '$x', and the + value of x will be printed from your interactive namespace. The + interpolation syntax includes the full Itpl support, so + ${foo()+x+bar()} is a valid prompt string now, and the function + calls will be made at runtime. + +2005-03-15 Fernando Perez <fperez@colorado.edu> + + * IPython/Magic.py (magic_history): renamed %hist to %history, to + avoid name clashes in pylab. %hist still works, it just forwards + the call to %history. + +2005-03-02 *** Released version 0.6.12 + +2005-03-02 Fernando Perez <fperez@colorado.edu> + + * IPython/iplib.py (handle_magic): log magic calls properly as + ipmagic() function calls. + + * IPython/Magic.py (magic_time): Improved %time to support + statements and provide wall-clock as well as CPU time. + +2005-02-27 Fernando Perez <fperez@colorado.edu> + + * IPython/hooks.py: New hooks module, to expose user-modifiable + IPython functionality in a clean manner. For now only the editor + hook is actually written, and other thigns which I intend to turn + into proper hooks aren't yet there. The display and prefilter + stuff, for example, should be hooks. But at least now the + framework is in place, and the rest can be moved here with more + time later. IPython had had a .hooks variable for a long time for + this purpose, but I'd never actually used it for anything. + +2005-02-26 Fernando Perez <fperez@colorado.edu> + + * IPython/ipmaker.py (make_IPython): make the default ipython + directory be called _ipython under win32, to follow more the + naming peculiarities of that platform (where buggy software like + Visual Sourcesafe breaks with .named directories). Reported by + Ville Vainio. + +2005-02-23 Fernando Perez <fperez@colorado.edu> + + * IPython/iplib.py (InteractiveShell.__init__): removed a few + auto_aliases for win32 which were causing problems. Users can + define the ones they personally like. + +2005-02-21 Fernando Perez <fperez@colorado.edu> + + * IPython/Magic.py (magic_time): new magic to time execution of + expressions. After a request by Charles Moad <cmoad-AT-indiana.edu>. + +2005-02-19 Fernando Perez <fperez@colorado.edu> + + * IPython/ConfigLoader.py (ConfigLoader.load): Allow empty strings + into keys (for prompts, for example). + + * IPython/Prompts.py (BasePrompt.set_p_str): Fix to allow empty + prompts in case users want them. This introduces a small behavior + change: ipython does not automatically add a space to all prompts + anymore. To get the old prompts with a space, users should add it + manually to their ipythonrc file, so for example prompt_in1 should + now read 'In [\#]: ' instead of 'In [\#]:'. + (BasePrompt.__init__): New option prompts_pad_left (only in rc + file) to control left-padding of secondary prompts. + + * IPython/Magic.py (Magic.profile_missing_notice): Don't crash if + the profiler can't be imported. Fix for Debian, which removed + profile.py because of License issues. I applied a slightly + modified version of the original Debian patch at + http://bugs.debian.org/cgi-bin/bugreport.cgi?bug=294500. + +2005-02-17 Fernando Perez <fperez@colorado.edu> + + * IPython/genutils.py (native_line_ends): Fix bug which would + cause improper line-ends under win32 b/c I was not opening files + in binary mode. Bug report and fix thanks to Ville. + + * IPython/iplib.py (handle_auto): Fix bug which I introduced when + trying to catch spurious foo[1] autocalls. My fix actually broke + ',/' autoquote/call with explicit escape (bad regexp). + +2005-02-15 *** Released version 0.6.11 + +2005-02-14 Fernando Perez <fperez@colorado.edu> + + * IPython/background_jobs.py: New background job management + subsystem. This is implemented via a new set of classes, and + IPython now provides a builtin 'jobs' object for background job + execution. A convenience %bg magic serves as a lightweight + frontend for starting the more common type of calls. This was + inspired by discussions with B. Granger and the BackgroundCommand + class described in the book Python Scripting for Computational + Science, by H. P. Langtangen: http://folk.uio.no/hpl/scripting + (although ultimately no code from this text was used, as IPython's + system is a separate implementation). + + * IPython/iplib.py (MagicCompleter.python_matches): add new option + to control the completion of single/double underscore names + separately. As documented in the example ipytonrc file, the + readline_omit__names variable can now be set to 2, to omit even + single underscore names. Thanks to a patch by Brian Wong + <BrianWong-AT-AirgoNetworks.Com>. + (InteractiveShell.__init__): Fix bug which would cause foo[1] to + be autocalled as foo([1]) if foo were callable. A problem for + things which are both callable and implement __getitem__. + (init_readline): Fix autoindentation for win32. Thanks to a patch + by Vivian De Smedt <vivian-AT-vdesmedt.com>. + +2005-02-12 Fernando Perez <fperez@colorado.edu> + + * IPython/ipmaker.py (make_IPython): Disabled the stout traps + which I had written long ago to sort out user error messages which + may occur during startup. This seemed like a good idea initially, + but it has proven a disaster in retrospect. I don't want to + change much code for now, so my fix is to set the internal 'debug' + flag to true everywhere, whose only job was precisely to control + this subsystem. This closes issue 28 (as well as avoiding all + sorts of strange hangups which occur from time to time). + +2005-02-07 Fernando Perez <fperez@colorado.edu> + + * IPython/Magic.py (magic_edit): Fix 'ed -p' not working when the + previous call produced a syntax error. + + * IPython/OInspect.py (Inspector.pinfo): Fix crash when inspecting + classes without constructor. + +2005-02-06 Fernando Perez <fperez@colorado.edu> + + * IPython/iplib.py (MagicCompleter.complete): Extend the list of + completions with the results of each matcher, so we return results + to the user from all namespaces. This breaks with ipython + tradition, but I think it's a nicer behavior. Now you get all + possible completions listed, from all possible namespaces (python, + filesystem, magics...) After a request by John Hunter + <jdhunter-AT-nitace.bsd.uchicago.edu>. + +2005-02-05 Fernando Perez <fperez@colorado.edu> + + * IPython/Magic.py (magic_prun): Fix bug where prun would fail if + the call had quote characters in it (the quotes were stripped). + +2005-01-31 Fernando Perez <fperez@colorado.edu> + + * IPython/iplib.py (InteractiveShell.__init__): reduce reliance on + Itpl.itpl() to make the code more robust against psyco + optimizations. + + * IPython/Itpl.py (Itpl.__str__): Use a _getframe() call instead + of causing an exception. Quicker, cleaner. + +2005-01-28 Fernando Perez <fperez@colorado.edu> + + * scripts/ipython_win_post_install.py (install): hardcode + sys.prefix+'python.exe' as the executable path. It turns out that + during the post-installation run, sys.executable resolves to the + name of the binary installer! I should report this as a distutils + bug, I think. I updated the .10 release with this tiny fix, to + avoid annoying the lists further. + +2005-01-27 *** Released version 0.6.10 + +2005-01-27 Fernando Perez <fperez@colorado.edu> + + * IPython/numutils.py (norm): Added 'inf' as optional name for + L-infinity norm, included references to mathworld.com for vector + norm definitions. + (amin/amax): added amin/amax for array min/max. Similar to what + pylab ships with after the recent reorganization of names. + (spike/spike_odd): removed deprecated spike/spike_odd functions. + + * ipython.el: committed Alex's recent fixes and improvements. + Tested with python-mode from CVS, and it looks excellent. Since + python-mode hasn't released anything in a while, I'm temporarily + putting a copy of today's CVS (v 4.70) of python-mode in: + http://ipython.scipy.org/tmp/python-mode.el + + * scripts/ipython_win_post_install.py (install): Win32 fix to use + sys.executable for the executable name, instead of assuming it's + called 'python.exe' (the post-installer would have produced broken + setups on systems with a differently named python binary). + + * IPython/PyColorize.py (Parser.__call__): change explicit '\n' + references to os.linesep, to make the code more + platform-independent. This is also part of the win32 coloring + fixes. + + * IPython/genutils.py (page_dumb): Remove attempts to chop long + lines, which actually cause coloring bugs because the length of + the line is very difficult to correctly compute with embedded + escapes. This was the source of all the coloring problems under + Win32. I think that _finally_, Win32 users have a properly + working ipython in all respects. This would never have happened + if not for Gary Bishop and Viktor Ransmayr's great help and work. + +2005-01-26 *** Released version 0.6.9 + +2005-01-25 Fernando Perez <fperez@colorado.edu> + + * setup.py: finally, we have a true Windows installer, thanks to + the excellent work of Viktor Ransmayr + <viktor.ransmayr-AT-t-online.de>. The docs have been updated for + Windows users. The setup routine is quite a bit cleaner thanks to + this, and the post-install script uses the proper functions to + allow a clean de-installation using the standard Windows Control + Panel. + + * IPython/genutils.py (get_home_dir): changed to use the $HOME + environment variable under all OSes (including win32) if + available. This will give consistency to win32 users who have set + this variable for any reason. If os.environ['HOME'] fails, the + previous policy of using HOMEDRIVE\HOMEPATH kicks in. + +2005-01-24 Fernando Perez <fperez@colorado.edu> + + * IPython/numutils.py (empty_like): add empty_like(), similar to + zeros_like() but taking advantage of the new empty() Numeric routine. + +2005-01-23 *** Released version 0.6.8 + +2005-01-22 Fernando Perez <fperez@colorado.edu> + + * IPython/Shell.py (MatplotlibShellBase.mplot_exec): I removed the + automatic show() calls. After discussing things with JDH, it + turns out there are too many corner cases where this can go wrong. + It's best not to try to be 'too smart', and simply have ipython + reproduce as much as possible the default behavior of a normal + python shell. + + * IPython/iplib.py (InteractiveShell.__init__): Modified the + line-splitting regexp and _prefilter() to avoid calling getattr() + on assignments. This closes + http://www.scipy.net/roundup/ipython/issue24. Note that Python's + readline uses getattr(), so a simple <TAB> keypress is still + enough to trigger getattr() calls on an object. + +2005-01-21 Fernando Perez <fperez@colorado.edu> + + * IPython/Shell.py (MatplotlibShellBase.magic_run): Fix the %run + docstring under pylab so it doesn't mask the original. + +2005-01-21 *** Released version 0.6.7 + +2005-01-21 Fernando Perez <fperez@colorado.edu> + + * IPython/Shell.py (MTInteractiveShell.runcode): Trap a crash with + signal handling for win32 users in multithreaded mode. + +2005-01-17 Fernando Perez <fperez@colorado.edu> + + * IPython/OInspect.py (Inspector.pinfo): Fix crash when inspecting + instances with no __init__. After a crash report by Norbert Nemec + <Norbert-AT-nemec-online.de>. + +2005-01-14 Fernando Perez <fperez@colorado.edu> + + * IPython/ultraTB.py (VerboseTB.text): Fix bug in reporting of + names for verbose exceptions, when multiple dotted names and the + 'parent' object were present on the same line. + +2005-01-11 Fernando Perez <fperez@colorado.edu> + + * IPython/genutils.py (flag_calls): new utility to trap and flag + calls in functions. I need it to clean up matplotlib support. + Also removed some deprecated code in genutils. + + * IPython/Shell.py (MatplotlibShellBase.mplot_exec): small fix so + that matplotlib scripts called with %run, which don't call show() + themselves, still have their plotting windows open. + +2005-01-05 Fernando Perez <fperez@colorado.edu> + + * IPython/Shell.py (IPShellGTK.__init__): Patch by Andrew Straw + <astraw-AT-caltech.edu>, to fix gtk deprecation warnings. + +2004-12-19 Fernando Perez <fperez@colorado.edu> + + * IPython/Shell.py (MTInteractiveShell.runcode): Get rid of + parent_runcode, which was an eyesore. The same result can be + obtained with Python's regular superclass mechanisms. + +2004-12-17 Fernando Perez <fperez@colorado.edu> + + * IPython/Magic.py (Magic.magic_sc): Fix quote stripping problem + reported by Prabhu. + (Magic.magic_sx): direct all errors to Term.cerr (defaults to + sys.stderr) instead of explicitly calling sys.stderr. This helps + maintain our I/O abstractions clean, for future GUI embeddings. + + * IPython/genutils.py (info): added new utility for sys.stderr + unified info message handling (thin wrapper around warn()). + + * IPython/ultraTB.py (VerboseTB.text): Fix misreported global + composite (dotted) names on verbose exceptions. + (VerboseTB.nullrepr): harden against another kind of errors which + Python's inspect module can trigger, and which were crashing + IPython. Thanks to a report by Marco Lombardi + <mlombard-AT-ma010192.hq.eso.org>. + +2004-12-13 *** Released version 0.6.6 + +2004-12-12 Fernando Perez <fperez@colorado.edu> + + * IPython/Shell.py (IPShellGTK.mainloop): catch RuntimeErrors + generated by pygtk upon initialization if it was built without + threads (for matplotlib users). After a crash reported by + Leguijt, Jaap J SIEP-EPT-RES <Jaap.Leguijt-AT-shell.com>. + + * IPython/ipmaker.py (make_IPython): fix small bug in the + import_some parameter for multiple imports. + + * IPython/iplib.py (ipmagic): simplified the interface of + ipmagic() to take a single string argument, just as it would be + typed at the IPython cmd line. + (ipalias): Added new ipalias() with an interface identical to + ipmagic(). This completes exposing a pure python interface to the + alias and magic system, which can be used in loops or more complex + code where IPython's automatic line mangling is not active. + + * IPython/genutils.py (timing): changed interface of timing to + simply run code once, which is the most common case. timings() + remains unchanged, for the cases where you want multiple runs. + + * IPython/Shell.py (MatplotlibShellBase._matplotlib_config): Fix a + bug where Python2.2 crashes with exec'ing code which does not end + in a single newline. Python 2.3 is OK, so I hadn't noticed this + before. + +2004-12-10 Fernando Perez <fperez@colorado.edu> + + * IPython/Magic.py (Magic.magic_prun): changed name of option from + -t to -T, to accomodate the new -t flag in %run (the %run and + %prun options are kind of intermixed, and it's not easy to change + this with the limitations of python's getopt). + + * IPython/Magic.py (Magic.magic_run): Added new -t option to time + the execution of scripts. It's not as fine-tuned as timeit.py, + but it works from inside ipython (and under 2.2, which lacks + timeit.py). Optionally a number of runs > 1 can be given for + timing very short-running code. + + * IPython/genutils.py (uniq_stable): new routine which returns a + list of unique elements in any iterable, but in stable order of + appearance. I needed this for the ultraTB fixes, and it's a handy + utility. + + * IPython/ultraTB.py (VerboseTB.text): Fix proper reporting of + dotted names in Verbose exceptions. This had been broken since + the very start, now x.y will properly be printed in a Verbose + traceback, instead of x being shown and y appearing always as an + 'undefined global'. Getting this to work was a bit tricky, + because by default python tokenizers are stateless. Saved by + python's ability to easily add a bit of state to an arbitrary + function (without needing to build a full-blown callable object). + + Also big cleanup of this code, which had horrendous runtime + lookups of zillions of attributes for colorization. Moved all + this code into a few templates, which make it cleaner and quicker. + + Printout quality was also improved for Verbose exceptions: one + variable per line, and memory addresses are printed (this can be + quite handy in nasty debugging situations, which is what Verbose + is for). + + * IPython/ipmaker.py (make_IPython): Do NOT execute files named in + the command line as scripts to be loaded by embedded instances. + Doing so has the potential for an infinite recursion if there are + exceptions thrown in the process. This fixes a strange crash + reported by Philippe MULLER <muller-AT-irit.fr>. + +2004-12-09 Fernando Perez <fperez@colorado.edu> + + * IPython/Shell.py (MatplotlibShellBase.use): Change pylab support + to reflect new names in matplotlib, which now expose the + matlab-compatible interface via a pylab module instead of the + 'matlab' name. The new code is backwards compatible, so users of + all matplotlib versions are OK. Patch by J. Hunter. + + * IPython/OInspect.py (Inspector.pinfo): Add to object? printing + of __init__ docstrings for instances (class docstrings are already + automatically printed). Instances with customized docstrings + (indep. of the class) are also recognized and all 3 separate + docstrings are printed (instance, class, constructor). After some + comments/suggestions by J. Hunter. + +2004-12-05 Fernando Perez <fperez@colorado.edu> + + * IPython/iplib.py (MagicCompleter.complete): Remove annoying + warnings when tab-completion fails and triggers an exception. + +2004-12-03 Fernando Perez <fperez@colorado.edu> + + * IPython/Magic.py (magic_prun): Fix bug where an exception would + be triggered when using 'run -p'. An incorrect option flag was + being set ('d' instead of 'D'). + (manpage): fix missing escaped \- sign. + +2004-11-30 *** Released version 0.6.5 + +2004-11-30 Fernando Perez <fperez@colorado.edu> + + * IPython/Magic.py (Magic.magic_run): Fix bug in breakpoint + setting with -d option. + + * setup.py (docfiles): Fix problem where the doc glob I was using + was COMPLETELY BROKEN. It was giving the right files by pure + accident, but failed once I tried to include ipython.el. Note: + glob() does NOT allow you to do exclusion on multiple endings! + +2004-11-29 Fernando Perez <fperez@colorado.edu> + + * IPython/usage.py (__doc__): cleaned up usage docstring, by using + the manpage as the source. Better formatting & consistency. + + * IPython/Magic.py (magic_run): Added new -d option, to run + scripts under the control of the python pdb debugger. Note that + this required changing the %prun option -d to -D, to avoid a clash + (since %run must pass options to %prun, and getopt is too dumb to + handle options with string values with embedded spaces). Thanks + to a suggestion by Matthew Arnison <maffew-AT-cat.org.au>. + (magic_who_ls): added type matching to %who and %whos, so that one + can filter their output to only include variables of certain + types. Another suggestion by Matthew. + (magic_whos): Added memory summaries in kb and Mb for arrays. + (magic_who): Improve formatting (break lines every 9 vars). + +2004-11-28 Fernando Perez <fperez@colorado.edu> + + * IPython/Logger.py (Logger.log): Fix bug in syncing the input + cache when empty lines were present. + +2004-11-24 Fernando Perez <fperez@colorado.edu> + + * IPython/usage.py (__doc__): document the re-activated threading + options for WX and GTK. + +2004-11-23 Fernando Perez <fperez@colorado.edu> + + * IPython/Shell.py (start): Added Prabhu's big patch to reactivate + the -wthread and -gthread options, along with a new -tk one to try + and coordinate Tk threading with wx/gtk. The tk support is very + platform dependent, since it seems to require Tcl and Tk to be + built with threads (Fedora1/2 appears NOT to have it, but in + Prabhu's Debian boxes it works OK). But even with some Tk + limitations, this is a great improvement. + + * IPython/Prompts.py (prompt_specials_color): Added \t for time + info in user prompts. Patch by Prabhu. + +2004-11-18 Fernando Perez <fperez@colorado.edu> + + * IPython/genutils.py (ask_yes_no): Add check for a max of 20 + EOFErrors and bail, to avoid infinite loops if a non-terminating + file is fed into ipython. Patch submitted in issue 19 by user, + many thanks. + + * IPython/iplib.py (InteractiveShell.handle_auto): do NOT trigger + autoquote/parens in continuation prompts, which can cause lots of + problems. Closes roundup issue 20. + +2004-11-17 Fernando Perez <fperez@colorado.edu> + + * debian/control (Build-Depends-Indep): Fix dpatch dependency, + reported as debian bug #280505. I'm not sure my local changelog + entry has the proper debian format (Jack?). + +2004-11-08 *** Released version 0.6.4 + +2004-11-08 Fernando Perez <fperez@colorado.edu> + + * IPython/iplib.py (init_readline): Fix exit message for Windows + when readline is active. Thanks to a report by Eric Jones + <eric-AT-enthought.com>. + +2004-11-07 Fernando Perez <fperez@colorado.edu> + + * IPython/genutils.py (page): Add a trap for OSError exceptions, + sometimes seen by win2k/cygwin users. + +2004-11-06 Fernando Perez <fperez@colorado.edu> + + * IPython/iplib.py (interact): Change the handling of %Exit from + trying to propagate a SystemExit to an internal ipython flag. + This is less elegant than using Python's exception mechanism, but + I can't get that to work reliably with threads, so under -pylab + %Exit was hanging IPython. Cross-thread exception handling is + really a bitch. Thaks to a bug report by Stephen Walton + <stephen.walton-AT-csun.edu>. + +2004-11-04 Fernando Perez <fperez@colorado.edu> + + * IPython/iplib.py (raw_input_original): store a pointer to the + true raw_input to harden against code which can modify it + (wx.py.PyShell does this and would otherwise crash ipython). + Thanks to a bug report by Jim Flowers <james.flowers-AT-lgx.com>. + + * IPython/Shell.py (MTInteractiveShell.runsource): Cleaner fix for + Ctrl-C problem, which does not mess up the input line. + +2004-11-03 Fernando Perez <fperez@colorado.edu> + + * IPython/Release.py: Changed licensing to BSD, in all files. + (name): lowercase name for tarball/RPM release. + + * IPython/OInspect.py (getdoc): wrap inspect.getdoc() safely for + use throughout ipython. + + * IPython/Magic.py (Magic._ofind): Switch to using the new + OInspect.getdoc() function. + + * IPython/Shell.py (sigint_handler): Hack to ignore the execution + of the line currently being canceled via Ctrl-C. It's extremely + ugly, but I don't know how to do it better (the problem is one of + handling cross-thread exceptions). + +2004-10-28 Fernando Perez <fperez@colorado.edu> + + * IPython/Shell.py (signal_handler): add signal handlers to trap + SIGINT and SIGSEGV in threaded code properly. Thanks to a bug + report by Francesc Alted. + +2004-10-21 Fernando Perez <fperez@colorado.edu> + + * IPython/Extensions/InterpreterExec.py (prefilter_shell): Fix @ + to % for pysh syntax extensions. + +2004-10-09 Fernando Perez <fperez@colorado.edu> + + * IPython/Magic.py (Magic.magic_whos): modify output of Numeric + arrays to print a more useful summary, without calling str(arr). + This avoids the problem of extremely lengthy computations which + occur if arr is large, and appear to the user as a system lockup + with 100% cpu activity. After a suggestion by Kristian Sandberg + <Kristian.Sandberg@colorado.edu>. + (Magic.__init__): fix bug in global magic escapes not being + correctly set. + +2004-10-08 Fernando Perez <fperez@colorado.edu> + + * IPython/Magic.py (__license__): change to absolute imports of + ipython's own internal packages, to start adapting to the absolute + import requirement of PEP-328. + + * IPython/genutils.py (__author__): Fix coding to utf-8 on all + files, and standardize author/license marks through the Release + module instead of having per/file stuff (except for files with + particular licenses, like the MIT/PSF-licensed codes). + + * IPython/Debugger.py: remove dead code for python 2.1 + +2004-10-04 Fernando Perez <fperez@colorado.edu> + + * IPython/iplib.py (ipmagic): New function for accessing magics + via a normal python function call. + + * IPython/Magic.py (Magic.magic_magic): Change the magic escape + from '@' to '%', to accomodate the new @decorator syntax of python + 2.4. + +2004-09-29 Fernando Perez <fperez@colorado.edu> + + * IPython/Shell.py (MatplotlibShellBase.use): Added a wrapper to + matplotlib.use to prevent running scripts which try to switch + interactive backends from within ipython. This will just crash + the python interpreter, so we can't allow it (but a detailed error + is given to the user). + +2004-09-28 Fernando Perez <fperez@colorado.edu> + + * IPython/Shell.py (MatplotlibShellBase.mplot_exec): + matplotlib-related fixes so that using @run with non-matplotlib + scripts doesn't pop up spurious plot windows. This requires + matplotlib >= 0.63, where I had to make some changes as well. + + * IPython/ipmaker.py (make_IPython): update version requirement to + python 2.2. + + * IPython/iplib.py (InteractiveShell.mainloop): Add an optional + banner arg for embedded customization. + + * IPython/Magic.py (Magic.__init__): big cleanup to remove all + explicit uses of __IP as the IPython's instance name. Now things + are properly handled via the shell.name value. The actual code + is a bit ugly b/c I'm doing it via a global in Magic.py, but this + is much better than before. I'll clean things completely when the + magic stuff gets a real overhaul. + + * ipython.1: small fixes, sent in by Jack Moffit. He also sent in + minor changes to debian dir. + + * IPython/iplib.py (InteractiveShell.__init__): Fix adding a + pointer to the shell itself in the interactive namespace even when + a user-supplied dict is provided. This is needed for embedding + purposes (found by tests with Michel Sanner). + +2004-09-27 Fernando Perez <fperez@colorado.edu> + + * IPython/UserConfig/ipythonrc: remove []{} from + readline_remove_delims, so that things like [modname.<TAB> do + proper completion. This disables [].TAB, but that's a less common + case than module names in list comprehensions, for example. + Thanks to a report by Andrea Riciputi. + +2004-09-09 Fernando Perez <fperez@colorado.edu> + + * IPython/Shell.py (IPShellGTK.mainloop): reorder to avoid + blocking problems in win32 and osx. Fix by John. + +2004-09-08 Fernando Perez <fperez@colorado.edu> + + * IPython/Shell.py (IPShellWX.OnInit): Fix output redirection bug + for Win32 and OSX. Fix by John Hunter. + +2004-08-30 *** Released version 0.6.3 + +2004-08-30 Fernando Perez <fperez@colorado.edu> + + * setup.py (isfile): Add manpages to list of dependent files to be + updated. + +2004-08-27 Fernando Perez <fperez@colorado.edu> + + * IPython/Shell.py (start): I've disabled -wthread and -gthread + for now. They don't really work with standalone WX/GTK code + (though matplotlib IS working fine with both of those backends). + This will neeed much more testing. I disabled most things with + comments, so turning it back on later should be pretty easy. + + * IPython/iplib.py (InteractiveShell.__init__): Fix accidental + autocalling of expressions like r'foo', by modifying the line + split regexp. Closes + http://www.scipy.net/roundup/ipython/issue18, reported by Nicholas + Riley <ipythonbugs-AT-sabi.net>. + (InteractiveShell.mainloop): honor --nobanner with banner + extensions. + + * IPython/Shell.py: Significant refactoring of all classes, so + that we can really support ALL matplotlib backends and threading + models (John spotted a bug with Tk which required this). Now we + should support single-threaded, WX-threads and GTK-threads, both + for generic code and for matplotlib. + + * IPython/ipmaker.py (__call__): Changed -mpthread option to + -pylab, to simplify things for users. Will also remove the pylab + profile, since now all of matplotlib configuration is directly + handled here. This also reduces startup time. + + * IPython/Shell.py (IPShellGTK.run): Fixed bug where mainloop() of + shell wasn't being correctly called. Also in IPShellWX. + + * IPython/iplib.py (InteractiveShell.__init__): Added option to + fine-tune banner. + + * IPython/numutils.py (spike): Deprecate these spike functions, + delete (long deprecated) gnuplot_exec handler. + +2004-08-26 Fernando Perez <fperez@colorado.edu> + + * ipython.1: Update for threading options, plus some others which + were missing. + + * IPython/ipmaker.py (__call__): Added -wthread option for + wxpython thread handling. Make sure threading options are only + valid at the command line. + + * scripts/ipython: moved shell selection into a factory function + in Shell.py, to keep the starter script to a minimum. + +2004-08-25 Fernando Perez <fperez@colorado.edu> + + * IPython/Shell.py (IPShellWX.wxexit): fixes to WX threading, by + John. Along with some recent changes he made to matplotlib, the + next versions of both systems should work very well together. + +2004-08-24 Fernando Perez <fperez@colorado.edu> + + * IPython/Magic.py (Magic.magic_prun): cleanup some dead code. I + tried to switch the profiling to using hotshot, but I'm getting + strange errors from prof.runctx() there. I may be misreading the + docs, but it looks weird. For now the profiling code will + continue to use the standard profiler. + +2004-08-23 Fernando Perez <fperez@colorado.edu> + + * IPython/Shell.py (IPShellWX.__init__): Improvements to the WX + threaded shell, by John Hunter. It's not quite ready yet, but + close. + +2004-08-22 Fernando Perez <fperez@colorado.edu> + + * IPython/iplib.py (InteractiveShell.interact): tab cleanups, also + in Magic and ultraTB. + + * ipython.1: document threading options in manpage. + + * scripts/ipython: Changed name of -thread option to -gthread, + since this is GTK specific. I want to leave the door open for a + -wthread option for WX, which will most likely be necessary. This + change affects usage and ipmaker as well. + + * IPython/Shell.py (matplotlib_shell): Add a factory function to + handle the matplotlib shell issues. Code by John Hunter + <jdhunter-AT-nitace.bsd.uchicago.edu>. + (IPShellMatplotlibWX.__init__): Rudimentary WX support. It's + broken (and disabled for end users) for now, but it puts the + infrastructure in place. + +2004-08-21 Fernando Perez <fperez@colorado.edu> + + * ipythonrc-pylab: Add matplotlib support. + + * matplotlib_config.py: new files for matplotlib support, part of + the pylab profile. + + * IPython/usage.py (__doc__): documented the threading options. + +2004-08-20 Fernando Perez <fperez@colorado.edu> + + * ipython: Modified the main calling routine to handle the -thread + and -mpthread options. This needs to be done as a top-level hack, + because it determines which class to instantiate for IPython + itself. + + * IPython/Shell.py (MTInteractiveShell.__init__): New set of + classes to support multithreaded GTK operation without blocking, + and matplotlib with all backends. This is a lot of still very + experimental code, and threads are tricky. So it may still have a + few rough edges... This code owes a lot to + http://aspn.activestate.com/ASPN/Cookbook/Python/Recipe/65109, by + Brian # McErlean and John Finlay, to Antoon Pardon for fixes, and + to John Hunter for all the matplotlib work. + + * IPython/ipmaker.py (__call__): Added -thread and -mpthread + options for gtk thread and matplotlib support. + +2004-08-16 Fernando Perez <fperez@colorado.edu> + + * IPython/iplib.py (InteractiveShell.__init__): don't trigger + autocall for things like p*q,p/q,p+q,p-q, when p is callable. Bug + reported by Stephen Walton <stephen.walton-AT-csun.edu>. + +2004-08-11 Fernando Perez <fperez@colorado.edu> + + * setup.py (isfile): Fix build so documentation gets updated for + rpms (it was only done for .tgz builds). + +2004-08-10 Fernando Perez <fperez@colorado.edu> + + * genutils.py (Term): Fix misspell of stdin stream (sin->cin). + + * iplib.py : Silence syntax error exceptions in tab-completion. + +2004-08-05 Fernando Perez <fperez@colorado.edu> + + * IPython/Prompts.py (Prompt2.set_colors): Fix incorrectly set + 'color off' mark for continuation prompts. This was causing long + continuation lines to mis-wrap. + +2004-08-01 Fernando Perez <fperez@colorado.edu> + + * IPython/ipmaker.py (make_IPython): Allow the shell class used + for building ipython to be a parameter. All this is necessary + right now to have a multithreaded version, but this insane + non-design will be cleaned up soon. For now, it's a hack that + works. + + * IPython/Shell.py (IPShell.__init__): Stop using mutable default + args in various places. No bugs so far, but it's a dangerous + practice. + +2004-07-31 Fernando Perez <fperez@colorado.edu> + + * IPython/iplib.py (complete): ignore SyntaxError exceptions to + fix completion of files with dots in their names under most + profiles (pysh was OK because the completion order is different). + +2004-07-27 Fernando Perez <fperez@colorado.edu> + + * IPython/iplib.py (InteractiveShell.__init__): build dict of + keywords manually, b/c the one in keyword.py was removed in python + 2.4. Patch by Anakim Border <aborder-AT-users.sourceforge.net>. + This is NOT a bug under python 2.3 and earlier. + +2004-07-26 Fernando Perez <fperez@colorado.edu> + + * IPython/ultraTB.py (VerboseTB.text): Add another + linecache.checkcache() call to try to prevent inspect.py from + crashing under python 2.3. I think this fixes + http://www.scipy.net/roundup/ipython/issue17. + +2004-07-26 *** Released version 0.6.2 + +2004-07-26 Fernando Perez <fperez@colorado.edu> + + * IPython/Magic.py (Magic.magic_cd): Fix bug where 'cd -N' would + fail for any number. + (Magic.magic_bookmark): Fix bug where 'bookmark -l' would fail for + empty bookmarks. + +2004-07-26 *** Released version 0.6.1 + +2004-07-26 Fernando Perez <fperez@colorado.edu> + + * ipython_win_post_install.py (run): Added pysh shortcut for Windows. + + * IPython/iplib.py (protect_filename): Applied Ville's patch for + escaping '()[]{}' in filenames. + + * IPython/Magic.py (shlex_split): Fix handling of '*' and '?' for + Python 2.2 users who lack a proper shlex.split. + +2004-07-19 Fernando Perez <fperez@colorado.edu> + + * IPython/iplib.py (InteractiveShell.init_readline): Add support + for reading readline's init file. I follow the normal chain: + $INPUTRC is honored, otherwise ~/.inputrc is used. Thanks to a + report by Mike Heeter. This closes + http://www.scipy.net/roundup/ipython/issue16. + +2004-07-18 Fernando Perez <fperez@colorado.edu> + + * IPython/iplib.py (__init__): Add better handling of '\' under + Win32 for filenames. After a patch by Ville. + +2004-07-17 Fernando Perez <fperez@colorado.edu> + + * IPython/iplib.py (InteractiveShell._prefilter): fix bug where + autocalling would be triggered for 'foo is bar' if foo is + callable. I also cleaned up the autocall detection code to use a + regexp, which is faster. Bug reported by Alexander Schmolck. + + * IPython/Magic.py (Magic.magic_pinfo): Fix bug where strings with + '?' in them would confuse the help system. Reported by Alex + Schmolck. + +2004-07-16 Fernando Perez <fperez@colorado.edu> + + * IPython/GnuplotInteractive.py (__all__): added plot2. + + * IPython/Gnuplot2.py (Gnuplot.plot2): added new function for + plotting dictionaries, lists or tuples of 1d arrays. + + * IPython/Magic.py (Magic.magic_hist): small clenaups and + optimizations. + + * IPython/iplib.py:Remove old Changelog info for cleanup. This is + the information which was there from Janko's original IPP code: + + 03.05.99 20:53 porto.ifm.uni-kiel.de + --Started changelog. + --make clear do what it say it does + --added pretty output of lines from inputcache + --Made Logger a mixin class, simplifies handling of switches + --Added own completer class. .string<TAB> expands to last history + line which starts with string. The new expansion is also present + with Ctrl-r from the readline library. But this shows, who this + can be done for other cases. + --Added convention that all shell functions should accept a + parameter_string This opens the door for different behaviour for + each function. @cd is a good example of this. + + 04.05.99 12:12 porto.ifm.uni-kiel.de + --added logfile rotation + --added new mainloop method which freezes first the namespace + + 07.05.99 21:24 porto.ifm.uni-kiel.de + --added the docreader classes. Now there is a help system. + -This is only a first try. Currently it's not easy to put new + stuff in the indices. But this is the way to go. Info would be + better, but HTML is every where and not everybody has an info + system installed and it's not so easy to change html-docs to info. + --added global logfile option + --there is now a hook for object inspection method pinfo needs to + be provided for this. Can be reached by two '??'. + + 08.05.99 20:51 porto.ifm.uni-kiel.de + --added a README + --bug in rc file. Something has changed so functions in the rc + file need to reference the shell and not self. Not clear if it's a + bug or feature. + --changed rc file for new behavior + +2004-07-15 Fernando Perez <fperez@colorado.edu> + + * IPython/Logger.py (Logger.log): fixed recent bug where the input + cache was falling out of sync in bizarre manners when multi-line + input was present. Minor optimizations and cleanup. + + (Logger): Remove old Changelog info for cleanup. This is the + information which was there from Janko's original code: + + Changes to Logger: - made the default log filename a parameter + + - put a check for lines beginning with !@? in log(). Needed + (even if the handlers properly log their lines) for mid-session + logging activation to work properly. Without this, lines logged + in mid session, which get read from the cache, would end up + 'bare' (with !@? in the open) in the log. Now they are caught + and prepended with a #. + + * IPython/iplib.py (InteractiveShell.init_readline): added check + in case MagicCompleter fails to be defined, so we don't crash. + +2004-07-13 Fernando Perez <fperez@colorado.edu> + + * IPython/Gnuplot2.py (Gnuplot.hardcopy): add automatic generation + of EPS if the requested filename ends in '.eps'. + +2004-07-04 Fernando Perez <fperez@colorado.edu> + + * IPython/iplib.py (InteractiveShell.handle_shell_escape): Fix + escaping of quotes when calling the shell. + +2004-07-02 Fernando Perez <fperez@colorado.edu> + + * IPython/Prompts.py (CachedOutput.update): Fix problem with + gettext not working because we were clobbering '_'. Fixes + http://www.scipy.net/roundup/ipython/issue6. + +2004-07-01 Fernando Perez <fperez@colorado.edu> + + * IPython/Magic.py (Magic.magic_cd): integrated bookmark handling + into @cd. Patch by Ville. + + * IPython/iplib.py (InteractiveShell.post_config_initialization): + new function to store things after ipmaker runs. Patch by Ville. + Eventually this will go away once ipmaker is removed and the class + gets cleaned up, but for now it's ok. Key functionality here is + the addition of the persistent storage mechanism, a dict for + keeping data across sessions (for now just bookmarks, but more can + be implemented later). + + * IPython/Magic.py (Magic.magic_bookmark): New bookmark system, + persistent across sections. Patch by Ville, I modified it + soemwhat to allow bookmarking arbitrary dirs other than CWD. Also + added a '-l' option to list all bookmarks. + + * IPython/iplib.py (InteractiveShell.atexit_operations): new + center for cleanup. Registered with atexit.register(). I moved + here the old exit_cleanup(). After a patch by Ville. + + * IPython/Magic.py (get_py_filename): added '~' to the accepted + characters in the hacked shlex_split for python 2.2. + + * IPython/iplib.py (file_matches): more fixes to filenames with + whitespace in them. It's not perfect, but limitations in python's + readline make it impossible to go further. + +2004-06-29 Fernando Perez <fperez@colorado.edu> + + * IPython/iplib.py (file_matches): escape whitespace correctly in + filename completions. Bug reported by Ville. + +2004-06-28 Fernando Perez <fperez@colorado.edu> + + * IPython/ipmaker.py (__call__): Added per-profile histories. Now + the history file will be called 'history-PROFNAME' (or just + 'history' if no profile is loaded). I was getting annoyed at + getting my Numerical work history clobbered by pysh sessions. + + * IPython/iplib.py (InteractiveShell.__init__): Internal + getoutputerror() function so that we can honor the system_verbose + flag for _all_ system calls. I also added escaping of # + characters here to avoid confusing Itpl. + + * IPython/Magic.py (shlex_split): removed call to shell in + parse_options and replaced it with shlex.split(). The annoying + part was that in Python 2.2, shlex.split() doesn't exist, so I had + to backport it from 2.3, with several frail hacks (the shlex + module is rather limited in 2.2). Thanks to a suggestion by Ville + Vainio <vivainio@kolumbus.fi>. For Python 2.3 there should be no + problem. + + (Magic.magic_system_verbose): new toggle to print the actual + system calls made by ipython. Mainly for debugging purposes. + + * IPython/GnuplotRuntime.py (gnu_out): fix bug for cygwin, which + doesn't support persistence. Reported (and fix suggested) by + Travis Caldwell <travis_caldwell2000@yahoo.com>. + +2004-06-26 Fernando Perez <fperez@colorado.edu> + + * IPython/Logger.py (Logger.log): fix to handle correctly empty + continue prompts. + + * IPython/Extensions/InterpreterExec.py (pysh): moved the pysh() + function (basically a big docstring) and a few more things here to + speedup startup. pysh.py is now very lightweight. We want because + it gets execfile'd, while InterpreterExec gets imported, so + byte-compilation saves time. + +2004-06-25 Fernando Perez <fperez@colorado.edu> + + * IPython/Magic.py (Magic.magic_cd): Fixed to restore usage of 'cd + -NUM', which was recently broken. + + * IPython/iplib.py (InteractiveShell.handle_shell_escape): allow ! + in multi-line input (but not !!, which doesn't make sense there). + + * IPython/UserConfig/ipythonrc: made autoindent on by default. + It's just too useful, and people can turn it off in the less + common cases where it's a problem. + +2004-06-24 Fernando Perez <fperez@colorado.edu> + + * IPython/iplib.py (InteractiveShell._prefilter): big change - + special syntaxes (like alias calling) is now allied in multi-line + input. This is still _very_ experimental, but it's necessary for + efficient shell usage combining python looping syntax with system + calls. For now it's restricted to aliases, I don't think it + really even makes sense to have this for magics. + +2004-06-23 Fernando Perez <fperez@colorado.edu> + + * IPython/Extensions/InterpreterExec.py (prefilter_shell): Added + $var=cmd <=> @sc var=cmd and $$var=cmd <=> @sc -l var=cmd. + + * IPython/Magic.py (Magic.magic_rehashx): modified to handle + extensions under Windows (after code sent by Gary Bishop). The + extensions considered 'executable' are stored in IPython's rc + structure as win_exec_ext. + + * IPython/genutils.py (shell): new function, like system() but + without return value. Very useful for interactive shell work. + + * IPython/Magic.py (Magic.magic_unalias): New @unalias function to + delete aliases. + + * IPython/iplib.py (InteractiveShell.alias_table_update): make + sure that the alias table doesn't contain python keywords. + +2004-06-21 Fernando Perez <fperez@colorado.edu> + + * IPython/Magic.py (Magic.magic_rehash): Fix crash when + non-existent items are found in $PATH. Reported by Thorsten. + +2004-06-20 Fernando Perez <fperez@colorado.edu> + + * IPython/iplib.py (complete): modified the completer so that the + order of priorities can be easily changed at runtime. + + * IPython/Extensions/InterpreterExec.py (prefilter_shell): + Modified to auto-execute all lines beginning with '~', '/' or '.'. + + * IPython/Magic.py (Magic.magic_sx): modified @sc and @sx to + expand Python variables prepended with $ in all system calls. The + same was done to InteractiveShell.handle_shell_escape. Now all + system access mechanisms (!, !!, @sc, @sx and aliases) allow the + expansion of python variables and expressions according to the + syntax of PEP-215 - http://www.python.org/peps/pep-0215.html. + + Though PEP-215 has been rejected, a similar (but simpler) one + seems like it will go into Python 2.4, PEP-292 - + http://www.python.org/peps/pep-0292.html. + + I'll keep the full syntax of PEP-215, since IPython has since the + start used Ka-Ping Yee's reference implementation discussed there + (Itpl), and I actually like the powerful semantics it offers. + + In order to access normal shell variables, the $ has to be escaped + via an extra $. For example: + + In [7]: PATH='a python variable' + + In [8]: !echo $PATH + a python variable + + In [9]: !echo $$PATH + /usr/local/lf9560/bin:/usr/local/intel/compiler70/ia32/bin:... + + (Magic.parse_options): escape $ so the shell doesn't evaluate + things prematurely. + + * IPython/iplib.py (InteractiveShell.call_alias): added the + ability for aliases to expand python variables via $. + + * IPython/Magic.py (Magic.magic_rehash): based on the new alias + system, now there's a @rehash/@rehashx pair of magics. These work + like the csh rehash command, and can be invoked at any time. They + build a table of aliases to everything in the user's $PATH + (@rehash uses everything, @rehashx is slower but only adds + executable files). With this, the pysh.py-based shell profile can + now simply call rehash upon startup, and full access to all + programs in the user's path is obtained. + + * IPython/iplib.py (InteractiveShell.call_alias): The new alias + functionality is now fully in place. I removed the old dynamic + code generation based approach, in favor of a much lighter one + based on a simple dict. The advantage is that this allows me to + now have thousands of aliases with negligible cost (unthinkable + with the old system). + +2004-06-19 Fernando Perez <fperez@colorado.edu> + + * IPython/iplib.py (__init__): extended MagicCompleter class to + also complete (last in priority) on user aliases. + + * IPython/Itpl.py (Itpl.__str__): fixed order of globals/locals in + call to eval. + (ItplNS.__init__): Added a new class which functions like Itpl, + but allows configuring the namespace for the evaluation to occur + in. + +2004-06-18 Fernando Perez <fperez@colorado.edu> + + * IPython/iplib.py (InteractiveShell.runcode): modify to print a + better message when 'exit' or 'quit' are typed (a common newbie + confusion). + + * IPython/Magic.py (Magic.magic_colors): Added the runtime color + check for Windows users. + + * IPython/iplib.py (InteractiveShell.user_setup): removed + disabling of colors for Windows. I'll test at runtime and issue a + warning if Gary's readline isn't found, as to nudge users to + download it. + +2004-06-16 Fernando Perez <fperez@colorado.edu> + + * IPython/genutils.py (Stream.__init__): changed to print errors + to sys.stderr. I had a circular dependency here. Now it's + possible to run ipython as IDLE's shell (consider this pre-alpha, + since true stdout things end up in the starting terminal instead + of IDLE's out). + + * IPython/Prompts.py (Prompt2.set_colors): prevent crashes for + users who haven't # updated their prompt_in2 definitions. Remove + eventually. + (multiple_replace): added credit to original ASPN recipe. + +2004-06-15 Fernando Perez <fperez@colorado.edu> + + * IPython/iplib.py (InteractiveShell.__init__): add 'cp' to the + list of auto-defined aliases. + +2004-06-13 Fernando Perez <fperez@colorado.edu> + + * setup.py (scriptfiles): Don't trigger win_post_install unless an + install was really requested (so setup.py can be used for other + things under Windows). + +2004-06-10 Fernando Perez <fperez@colorado.edu> + + * IPython/Logger.py (Logger.create_log): Manually remove any old + backup, since os.remove may fail under Windows. Fixes bug + reported by Thorsten. + +2004-06-09 Fernando Perez <fperez@colorado.edu> + + * examples/example-embed.py: fixed all references to %n (replaced + with \\# for ps1/out prompts and with \\D for ps2 prompts). Done + for all examples and the manual as well. + +2004-06-08 Fernando Perez <fperez@colorado.edu> + + * IPython/Prompts.py (Prompt2.set_p_str): fixed all prompt + alignment and color management. All 3 prompt subsystems now + inherit from BasePrompt. + + * tools/release: updates for windows installer build and tag rpms + with python version (since paths are fixed). + + * IPython/UserConfig/ipythonrc: modified to use \# instead of %n, + which will become eventually obsolete. Also fixed the default + prompt_in2 to use \D, so at least new users start with the correct + defaults. + WARNING: Users with existing ipythonrc files will need to apply + this fix manually! + + * setup.py: make windows installer (.exe). This is finally the + integration of an old patch by Cory Dodt <dodt-AT-fcoe.k12.ca.us>, + which I hadn't included because it required Python 2.3 (or recent + distutils). + + * IPython/usage.py (__doc__): update docs (and manpage) to reflect + usage of new '\D' escape. + + * IPython/Prompts.py (ROOT_SYMBOL): Small fix for Windows (which + lacks os.getuid()) + (CachedOutput.set_colors): Added the ability to turn coloring + on/off with @colors even for manually defined prompt colors. It + uses a nasty global, but it works safely and via the generic color + handling mechanism. + (Prompt2.__init__): Introduced new escape '\D' for continuation + prompts. It represents the counter ('\#') as dots. + *** NOTE *** THIS IS A BACKWARDS-INCOMPATIBLE CHANGE. Users will + need to update their ipythonrc files and replace '%n' with '\D' in + their prompt_in2 settings everywhere. Sorry, but there's + otherwise no clean way to get all prompts to properly align. The + ipythonrc shipped with IPython has been updated. + +2004-06-07 Fernando Perez <fperez@colorado.edu> + + * setup.py (isfile): Pass local_icons option to latex2html, so the + resulting HTML file is self-contained. Thanks to + dryice-AT-liu.com.cn for the tip. + + * pysh.py: I created a new profile 'shell', which implements a + _rudimentary_ IPython-based shell. This is in NO WAY a realy + system shell, nor will it become one anytime soon. It's mainly + meant to illustrate the use of the new flexible bash-like prompts. + I guess it could be used by hardy souls for true shell management, + but it's no tcsh/bash... pysh.py is loaded by the 'shell' + profile. This uses the InterpreterExec extension provided by + W.J. van der Laan <gnufnork-AT-hetdigitalegat.nl> + + * IPython/Prompts.py (PromptOut.__str__): now it will correctly + auto-align itself with the length of the previous input prompt + (taking into account the invisible color escapes). + (CachedOutput.__init__): Large restructuring of this class. Now + all three prompts (primary1, primary2, output) are proper objects, + managed by the 'parent' CachedOutput class. The code is still a + bit hackish (all prompts share state via a pointer to the cache), + but it's overall far cleaner than before. + + * IPython/genutils.py (getoutputerror): modified to add verbose, + debug and header options. This makes the interface of all getout* + functions uniform. + (SystemExec.getoutputerror): added getoutputerror to SystemExec. + + * IPython/Magic.py (Magic.default_option): added a function to + allow registering default options for any magic command. This + makes it easy to have profiles which customize the magics globally + for a certain use. The values set through this function are + picked up by the parse_options() method, which all magics should + use to parse their options. + + * IPython/genutils.py (warn): modified the warnings framework to + use the Term I/O class. I'm trying to slowly unify all of + IPython's I/O operations to pass through Term. + + * IPython/Prompts.py (Prompt2._str_other): Added functionality in + the secondary prompt to correctly match the length of the primary + one for any prompt. Now multi-line code will properly line up + even for path dependent prompts, such as the new ones available + via the prompt_specials. + +2004-06-06 Fernando Perez <fperez@colorado.edu> + + * IPython/Prompts.py (prompt_specials): Added the ability to have + bash-like special sequences in the prompts, which get + automatically expanded. Things like hostname, current working + directory and username are implemented already, but it's easy to + add more in the future. Thanks to a patch by W.J. van der Laan + <gnufnork-AT-hetdigitalegat.nl> + (prompt_specials): Added color support for prompt strings, so + users can define arbitrary color setups for their prompts. + +2004-06-05 Fernando Perez <fperez@colorado.edu> + + * IPython/genutils.py (Term.reopen_all): Added Windows-specific + code to load Gary Bishop's readline and configure it + automatically. Thanks to Gary for help on this. + +2004-06-01 Fernando Perez <fperez@colorado.edu> + + * IPython/Logger.py (Logger.create_log): fix bug for logging + with no filename (previous fix was incomplete). + +2004-05-25 Fernando Perez <fperez@colorado.edu> + + * IPython/Magic.py (Magic.parse_options): fix bug where naked + parens would get passed to the shell. + +2004-05-20 Fernando Perez <fperez@colorado.edu> + + * IPython/Magic.py (Magic.magic_prun): changed default profile + sort order to 'time' (the more common profiling need). + + * IPython/OInspect.py (Inspector.pinfo): flush the inspect cache + so that source code shown is guaranteed in sync with the file on + disk (also changed in psource). Similar fix to the one for + ultraTB on 2004-05-06. Thanks to a bug report by Yann Le Du + <yann.ledu-AT-noos.fr>. + + * IPython/Magic.py (Magic.parse_options): Fixed bug where commands + with a single option would not be correctly parsed. Closes + http://www.scipy.net/roundup/ipython/issue14. This bug had been + introduced in 0.6.0 (on 2004-05-06). + +2004-05-13 *** Released version 0.6.0 + +2004-05-13 Fernando Perez <fperez@colorado.edu> + + * debian/: Added debian/ directory to CVS, so that debian support + is publicly accessible. The debian package is maintained by Jack + Moffit <jack-AT-xiph.org>. + + * Documentation: included the notes about an ipython-based system + shell (the hypothetical 'pysh') into the new_design.pdf document, + so that these ideas get distributed to users along with the + official documentation. + +2004-05-10 Fernando Perez <fperez@colorado.edu> + + * IPython/Logger.py (Logger.create_log): fix recently introduced + bug (misindented line) where logstart would fail when not given an + explicit filename. + +2004-05-09 Fernando Perez <fperez@colorado.edu> + + * IPython/Magic.py (Magic.parse_options): skip system call when + there are no options to look for. Faster, cleaner for the common + case. + + * Documentation: many updates to the manual: describing Windows + support better, Gnuplot updates, credits, misc small stuff. Also + updated the new_design doc a bit. + +2004-05-06 *** Released version 0.6.0.rc1 + +2004-05-06 Fernando Perez <fperez@colorado.edu> + + * IPython/ultraTB.py (ListTB.text): modified a ton of string += + operations to use the vastly more efficient list/''.join() method. + (FormattedTB.text): Fix + http://www.scipy.net/roundup/ipython/issue12 - exception source + extract not updated after reload. Thanks to Mike Salib + <msalib-AT-mit.edu> for pinning the source of the problem. + Fortunately, the solution works inside ipython and doesn't require + any changes to python proper. + + * IPython/Magic.py (Magic.parse_options): Improved to process the + argument list as a true shell would (by actually using the + underlying system shell). This way, all @magics automatically get + shell expansion for variables. Thanks to a comment by Alex + Schmolck. + +2004-04-04 Fernando Perez <fperez@colorado.edu> + + * IPython/iplib.py (InteractiveShell.interact): Added a special + trap for a debugger quit exception, which is basically impossible + to handle by normal mechanisms, given what pdb does to the stack. + This fixes a crash reported by <fgibbons-AT-llama.med.harvard.edu>. + +2004-04-03 Fernando Perez <fperez@colorado.edu> + + * IPython/genutils.py (Term): Standardized the names of the Term + class streams to cin/cout/cerr, following C++ naming conventions + (I can't use in/out/err because 'in' is not a valid attribute + name). + + * IPython/iplib.py (InteractiveShell.interact): don't increment + the prompt if there's no user input. By Daniel 'Dang' Griffith + <pythondev-dang-AT-lazytwinacres.net>, after a suggestion from + Francois Pinard. + +2004-04-02 Fernando Perez <fperez@colorado.edu> + + * IPython/genutils.py (Stream.__init__): Modified to survive at + least importing in contexts where stdin/out/err aren't true file + objects, such as PyCrust (they lack fileno() and mode). However, + the recovery facilities which rely on these things existing will + not work. + +2004-04-01 Fernando Perez <fperez@colorado.edu> + + * IPython/Magic.py (Magic.magic_sx): modified (as well as @sc) to + use the new getoutputerror() function, so it properly + distinguishes stdout/err. + + * IPython/genutils.py (getoutputerror): added a function to + capture separately the standard output and error of a command. + After a comment from dang on the mailing lists. This code is + basically a modified version of commands.getstatusoutput(), from + the standard library. + + * IPython/iplib.py (InteractiveShell.handle_shell_escape): added + '!!' as a special syntax (shorthand) to access @sx. + + * IPython/Magic.py (Magic.magic_sx): new magic, to execute a shell + command and return its output as a list split on '\n'. + +2004-03-31 Fernando Perez <fperez@colorado.edu> + + * IPython/FakeModule.py (FakeModule.__init__): added __nonzero__ + method to dictionaries used as FakeModule instances if they lack + it. At least pydoc in python2.3 breaks for runtime-defined + functions without this hack. At some point I need to _really_ + understand what FakeModule is doing, because it's a gross hack. + But it solves Arnd's problem for now... + +2004-02-27 Fernando Perez <fperez@colorado.edu> + + * IPython/Logger.py (Logger.create_log): Fix bug where 'rotate' + mode would behave erratically. Also increased the number of + possible logs in rotate mod to 999. Thanks to Rod Holland + <rhh@StructureLABS.com> for the report and fixes. + +2004-02-26 Fernando Perez <fperez@colorado.edu> + + * IPython/genutils.py (page): Check that the curses module really + has the initscr attribute before trying to use it. For some + reason, the Solaris curses module is missing this. I think this + should be considered a Solaris python bug, but I'm not sure. + +2004-01-17 Fernando Perez <fperez@colorado.edu> + + * IPython/genutils.py (Stream.__init__): Changes to try to make + ipython robust against stdin/out/err being closed by the user. + This is 'user error' (and blocks a normal python session, at least + the stdout case). However, Ipython should be able to survive such + instances of abuse as gracefully as possible. To simplify the + coding and maintain compatibility with Gary Bishop's Term + contributions, I've made use of classmethods for this. I think + this introduces a dependency on python 2.2. + +2004-01-13 Fernando Perez <fperez@colorado.edu> + + * IPython/numutils.py (exp_safe): simplified the code a bit and + removed the need for importing the kinds module altogether. + +2004-01-06 Fernando Perez <fperez@colorado.edu> + + * IPython/Magic.py (Magic.magic_sc): Made the shell capture system + a magic function instead, after some community feedback. No + special syntax will exist for it, but its name is deliberately + very short. + +2003-12-20 Fernando Perez <fperez@colorado.edu> + + * IPython/iplib.py (InteractiveShell.handle_shell_assign): Added + new functionality, to automagically assign the result of a shell + command to a variable. I'll solicit some community feedback on + this before making it permanent. + + * IPython/OInspect.py (Inspector.pinfo): Fix crash when info was + requested about callables for which inspect couldn't obtain a + proper argspec. Thanks to a crash report sent by Etienne + Posthumus <etienne-AT-apple01.cs.vu.nl>. + +2003-12-09 Fernando Perez <fperez@colorado.edu> + + * IPython/genutils.py (page): patch for the pager to work across + various versions of Windows. By Gary Bishop. + +2003-12-04 Fernando Perez <fperez@colorado.edu> + + * IPython/Gnuplot2.py (PlotItems): Fixes for working with + Gnuplot.py version 1.7, whose internal names changed quite a bit. + While I tested this and it looks ok, there may still be corner + cases I've missed. + +2003-12-01 Fernando Perez <fperez@colorado.edu> + + * IPython/iplib.py (InteractiveShell._prefilter): Fixed a bug + where a line like 'p,q=1,2' would fail because the automagic + system would be triggered for @p. + + * IPython/DPyGetOpt.py (DPyGetOpt.processArguments): Tab-related + cleanups, code unmodified. + + * IPython/genutils.py (Term): added a class for IPython to handle + output. In most cases it will just be a proxy for stdout/err, but + having this allows modifications to be made for some platforms, + such as handling color escapes under Windows. All of this code + was contributed by Gary Bishop, with minor modifications by me. + The actual changes affect many files. + +2003-11-30 Fernando Perez <fperez@colorado.edu> + + * IPython/iplib.py (file_matches): new completion code, courtesy + of Jeff Collins. This enables filename completion again under + python 2.3, which disabled it at the C level. + +2003-11-11 Fernando Perez <fperez@colorado.edu> + + * IPython/numutils.py (amap): Added amap() fn. Simple shorthand + for Numeric.array(map(...)), but often convenient. + +2003-11-05 Fernando Perez <fperez@colorado.edu> + + * IPython/numutils.py (frange): Changed a call from int() to + int(round()) to prevent a problem reported with arange() in the + numpy list. + +2003-10-06 Fernando Perez <fperez@colorado.edu> + + * IPython/DPyGetOpt.py (DPyGetOpt.processArguments): changed to + prevent crashes if sys lacks an argv attribute (it happens with + embedded interpreters which build a bare-bones sys module). + Thanks to a report/bugfix by Adam Hupp <hupp-AT-cs.wisc.edu>. + +2003-09-24 Fernando Perez <fperez@colorado.edu> + + * IPython/Magic.py (Magic._ofind): blanket except around getattr() + to protect against poorly written user objects where __getattr__ + raises exceptions other than AttributeError. Thanks to a bug + report by Oliver Sander <osander-AT-gmx.de>. + + * IPython/FakeModule.py (FakeModule.__repr__): this method was + missing. Thanks to bug report by Ralf Schmitt <ralf-AT-brainbot.com>. + +2003-09-09 Fernando Perez <fperez@colorado.edu> + + * IPython/iplib.py (InteractiveShell._prefilter): fix bug where + unpacking a list whith a callable as first element would + mistakenly trigger autocalling. Thanks to a bug report by Jeffery + Collins. + +2003-08-25 *** Released version 0.5.0 + +2003-08-22 Fernando Perez <fperez@colorado.edu> + + * IPython/ultraTB.py (VerboseTB.linereader): Improved handling of + improperly defined user exceptions. Thanks to feedback from Mark + Russell <mrussell-AT-verio.net>. + +2003-08-20 Fernando Perez <fperez@colorado.edu> + + * IPython/OInspect.py (Inspector.pinfo): changed String Form + printing so that it would print multi-line string forms starting + with a new line. This way the formatting is better respected for + objects which work hard to make nice string forms. + + * IPython/iplib.py (InteractiveShell.handle_auto): Fix bug where + autocall would overtake data access for objects with both + __getitem__ and __call__. + +2003-08-19 *** Released version 0.5.0-rc1 + +2003-08-19 Fernando Perez <fperez@colorado.edu> + + * IPython/deep_reload.py (load_tail): single tiny change here + seems to fix the long-standing bug of dreload() failing to work + for dotted names. But this module is pretty tricky, so I may have + missed some subtlety. Needs more testing!. + + * IPython/ultraTB.py (VerboseTB.linereader): harden against user + exceptions which have badly implemented __str__ methods. + (VerboseTB.text): harden against inspect.getinnerframes crashing, + which I've been getting reports about from Python 2.3 users. I + wish I had a simple test case to reproduce the problem, so I could + either write a cleaner workaround or file a bug report if + necessary. + + * IPython/Magic.py (Magic.magic_edit): fixed bug where after + making a class 'foo', file 'foo.py' couldn't be edited. Thanks to + a bug report by Tjabo Kloppenburg. + + * IPython/ultraTB.py (VerboseTB.debugger): hardened against pdb + crashes. Wrapped the pdb call in a blanket try/except, since pdb + seems rather unstable. Thanks to a bug report by Tjabo + Kloppenburg <tjabo.kloppenburg-AT-unix-ag.uni-siegen.de>. + + * IPython/Release.py (version): release 0.5.0-rc1. I want to put + this out soon because of the critical fixes in the inner loop for + generators. + + * IPython/Magic.py (Magic.getargspec): removed. This (and + _get_def) have been obsoleted by OInspect for a long time, I + hadn't noticed that they were dead code. + (Magic._ofind): restored _ofind functionality for a few literals + (those in ["''",'""','[]','{}','()']). But it won't work anymore + for things like "hello".capitalize?, since that would require a + potentially dangerous eval() again. + + * IPython/iplib.py (InteractiveShell._prefilter): reorganized the + logic a bit more to clean up the escapes handling and minimize the + use of _ofind to only necessary cases. The interactive 'feel' of + IPython should have improved quite a bit with the changes in + _prefilter and _ofind (besides being far safer than before). + + * IPython/Magic.py (Magic.magic_edit): Fixed old bug (but rather + obscure, never reported). Edit would fail to find the object to + edit under some circumstances. + (Magic._ofind): CRITICAL FIX. Finally removed the eval() calls + which were causing double-calling of generators. Those eval calls + were _very_ dangerous, since code with side effects could be + triggered. As they say, 'eval is evil'... These were the + nastiest evals in IPython. Besides, _ofind is now far simpler, + and it should also be quite a bit faster. Its use of inspect is + also safer, so perhaps some of the inspect-related crashes I've + seen lately with Python 2.3 might be taken care of. That will + need more testing. + +2003-08-17 Fernando Perez <fperez@colorado.edu> + + * IPython/iplib.py (InteractiveShell._prefilter): significant + simplifications to the logic for handling user escapes. Faster + and simpler code. + +2003-08-14 Fernando Perez <fperez@colorado.edu> + + * IPython/numutils.py (sum_flat): rewrote to be non-recursive. + Now it requires O(N) storage (N=size(a)) for non-contiguous input, + but it should be quite a bit faster. And the recursive version + generated O(log N) intermediate storage for all rank>1 arrays, + even if they were contiguous. + (l1norm): Added this function. + (norm): Added this function for arbitrary norms (including + l-infinity). l1 and l2 are still special cases for convenience + and speed. + +2003-08-03 Fernando Perez <fperez@colorado.edu> + + * IPython/Magic.py (Magic.magic_edit): Removed all remaining string + exceptions, which now raise PendingDeprecationWarnings in Python + 2.3. There were some in Magic and some in Gnuplot2. + +2003-06-30 Fernando Perez <fperez@colorado.edu> + + * IPython/genutils.py (page): modified to call curses only for + terminals where TERM=='xterm'. After problems under many other + terminals were reported by Keith Beattie <KSBeattie-AT-lbl.gov>. + + * IPython/iplib.py (complete): removed spurious 'print "IE"' which + would be triggered when readline was absent. This was just an old + debugging statement I'd forgotten to take out. + +2003-06-20 Fernando Perez <fperez@colorado.edu> + + * IPython/genutils.py (clock): modified to return only user time + (not counting system time), after a discussion on scipy. While + system time may be a useful quantity occasionally, it may much + more easily be skewed by occasional swapping or other similar + activity. + +2003-06-05 Fernando Perez <fperez@colorado.edu> + + * IPython/numutils.py (identity): new function, for building + arbitrary rank Kronecker deltas (mostly backwards compatible with + Numeric.identity) + +2003-06-03 Fernando Perez <fperez@colorado.edu> + + * IPython/iplib.py (InteractiveShell.handle_magic): protect + arguments passed to magics with spaces, to allow trailing '\' to + work normally (mainly for Windows users). + +2003-05-29 Fernando Perez <fperez@colorado.edu> + + * IPython/ipmaker.py (make_IPython): Load site._Helper() as help + instead of pydoc.help. This fixes a bizarre behavior where + printing '%s' % locals() would trigger the help system. Now + ipython behaves like normal python does. + + Note that if one does 'from pydoc import help', the bizarre + behavior returns, but this will also happen in normal python, so + it's not an ipython bug anymore (it has to do with how pydoc.help + is implemented). + +2003-05-22 Fernando Perez <fperez@colorado.edu> + + * IPython/FlexCompleter.py (Completer.attr_matches): fixed to + return [] instead of None when nothing matches, also match to end + of line. Patch by Gary Bishop. + + * IPython/ipmaker.py (make_IPython): Added same sys.excepthook + protection as before, for files passed on the command line. This + prevents the CrashHandler from kicking in if user files call into + sys.excepthook (such as PyQt and WxWindows have a nasty habit of + doing). After a report by Kasper Souren <Kasper.Souren-AT-ircam.fr> + +2003-05-20 *** Released version 0.4.0 + +2003-05-20 Fernando Perez <fperez@colorado.edu> + + * setup.py: added support for manpages. It's a bit hackish b/c of + a bug in the way the bdist_rpm distutils target handles gzipped + manpages, but it works. After a patch by Jack. + +2003-05-19 Fernando Perez <fperez@colorado.edu> + + * IPython/numutils.py: added a mockup of the kinds module, since + it was recently removed from Numeric. This way, numutils will + work for all users even if they are missing kinds. + + * IPython/Magic.py (Magic._ofind): Harden against an inspect + failure, which can occur with SWIG-wrapped extensions. After a + crash report from Prabhu. + +2003-05-16 Fernando Perez <fperez@colorado.edu> + + * IPython/iplib.py (InteractiveShell.excepthook): New method to + protect ipython from user code which may call directly + sys.excepthook (this looks like an ipython crash to the user, even + when it isn't). After a patch by Gary Bishop <gb-AT-cs.unc.edu>. + This is especially important to help users of WxWindows, but may + also be useful in other cases. + + * IPython/ultraTB.py (AutoFormattedTB.__call__): Changed to allow + an optional tb_offset to be specified, and to preserve exception + info if given. After a patch by Gary Bishop <gb-AT-cs.unc.edu>. + + * ipython.1 (Default): Thanks to Jack's work, we now have manpages! + +2003-05-15 Fernando Perez <fperez@colorado.edu> + + * IPython/iplib.py (InteractiveShell.user_setup): Fix crash when + installing for a new user under Windows. + +2003-05-12 Fernando Perez <fperez@colorado.edu> + + * IPython/iplib.py (InteractiveShell.handle_emacs): New line + handler for Emacs comint-based lines. Currently it doesn't do + much (but importantly, it doesn't update the history cache). In + the future it may be expanded if Alex needs more functionality + there. + + * IPython/CrashHandler.py (CrashHandler.__call__): Added platform + info to crash reports. + + * IPython/iplib.py (InteractiveShell.mainloop): Added -c option, + just like Python's -c. Also fixed crash with invalid -color + option value at startup. Thanks to Will French + <wfrench-AT-bestweb.net> for the bug report. + +2003-05-09 Fernando Perez <fperez@colorado.edu> + + * IPython/genutils.py (EvalDict.__getitem__): Renamed EvalString + to EvalDict (it's a mapping, after all) and simplified its code + quite a bit, after a nice discussion on c.l.py where Gustavo + Córdova <gcordova-AT-sismex.com> suggested the new version. + +2003-04-30 Fernando Perez <fperez@colorado.edu> + + * IPython/genutils.py (timings_out): modified it to reduce its + overhead in the common reps==1 case. + +2003-04-29 Fernando Perez <fperez@colorado.edu> + + * IPython/genutils.py (timings_out): Modified to use the resource + module, which avoids the wraparound problems of time.clock(). + +2003-04-17 *** Released version 0.2.15pre4 + +2003-04-17 Fernando Perez <fperez@colorado.edu> + + * setup.py (scriptfiles): Split windows-specific stuff over to a + separate file, in an attempt to have a Windows GUI installer. + That didn't work, but part of the groundwork is done. + + * IPython/UserConfig/ipythonrc: Added M-i, M-o and M-I for + indent/unindent with 4 spaces. Particularly useful in combination + with the new auto-indent option. + +2003-04-16 Fernando Perez <fperez@colorado.edu> + + * IPython/Magic.py: various replacements of self.rc for + self.shell.rc. A lot more remains to be done to fully disentangle + this class from the main Shell class. + + * IPython/GnuplotRuntime.py: added checks for mouse support so + that we don't try to enable it if the current gnuplot doesn't + really support it. Also added checks so that we don't try to + enable persist under Windows (where Gnuplot doesn't recognize the + option). + + * IPython/iplib.py (InteractiveShell.interact): Added optional + auto-indenting code, after a patch by King C. Shu + <kingshu-AT-myrealbox.com>. It's off by default because it doesn't + get along well with pasting indented code. If I ever figure out + how to make that part go well, it will become on by default. + + * IPython/Prompts.py (Prompt1.auto_rewrite): Fixed bug which would + crash ipython if there was an unmatched '%' in the user's prompt + string. Reported by Thorsten Kampe <thorsten-AT-thorstenkampe.de>. + + * IPython/iplib.py (InteractiveShell.interact): removed the + ability to ask the user whether he wants to crash or not at the + 'last line' exception handler. Calling functions at that point + changes the stack, and the error reports would have incorrect + tracebacks. + + * IPython/Magic.py (Magic.magic_page): Added new @page magic, to + pass through a peger a pretty-printed form of any object. After a + contribution by Olivier Aubert <oaubert-AT-bat710.univ-lyon1.fr> + +2003-04-14 Fernando Perez <fperez@colorado.edu> + + * IPython/iplib.py (InteractiveShell.user_setup): Fixed bug where + all files in ~ would be modified at first install (instead of + ~/.ipython). This could be potentially disastrous, as the + modification (make line-endings native) could damage binary files. + +2003-04-10 Fernando Perez <fperez@colorado.edu> + + * IPython/iplib.py (InteractiveShell.handle_help): Modified to + handle only lines which are invalid python. This now means that + lines like 'x=1 #?' execute properly. Thanks to Jeffery Collins + for the bug report. + +2003-04-01 Fernando Perez <fperez@colorado.edu> + + * IPython/iplib.py (InteractiveShell.showtraceback): Fixed bug + where failing to set sys.last_traceback would crash pdb.pm(). + Thanks to Jeffery D. Collins <Jeff.Collins-AT-vexcel.com> for the bug + report. + +2003-03-25 Fernando Perez <fperez@colorado.edu> + + * IPython/Magic.py (Magic.magic_prun): rstrip() output of profiler + before printing it (it had a lot of spurious blank lines at the + end). + + * IPython/Gnuplot2.py (Gnuplot.hardcopy): fixed bug where lpr + output would be sent 21 times! Obviously people don't use this + too often, or I would have heard about it. + +2003-03-24 Fernando Perez <fperez@colorado.edu> + + * setup.py (scriptfiles): renamed the data_files parameter from + 'base' to 'data' to fix rpm build issues. Thanks to Ralf Ahlbrink + for the patch. + +2003-03-20 Fernando Perez <fperez@colorado.edu> + + * IPython/genutils.py (error): added error() and fatal() + functions. + +2003-03-18 *** Released version 0.2.15pre3 + +2003-03-18 Fernando Perez <fperez@colorado.edu> + + * setupext/install_data_ext.py + (install_data_ext.initialize_options): Class contributed by Jack + Moffit for fixing the old distutils hack. He is sending this to + the distutils folks so in the future we may not need it as a + private fix. + + * MANIFEST.in: Extensive reorganization, based on Jack Moffit's + changes for Debian packaging. See his patch for full details. + The old distutils hack of making the ipythonrc* files carry a + bogus .py extension is gone, at last. Examples were moved to a + separate subdir under doc/, and the separate executable scripts + now live in their own directory. Overall a great cleanup. The + manual was updated to use the new files, and setup.py has been + fixed for this setup. + + * IPython/PyColorize.py (Parser.usage): made non-executable and + created a pycolor wrapper around it to be included as a script. + +2003-03-12 *** Released version 0.2.15pre2 + +2003-03-12 Fernando Perez <fperez@colorado.edu> + + * IPython/ColorANSI.py (make_color_table): Finally fixed the + long-standing problem with garbage characters in some terminals. + The issue was really that the \001 and \002 escapes must _only_ be + passed to input prompts (which call readline), but _never_ to + normal text to be printed on screen. I changed ColorANSI to have + two classes: TermColors and InputTermColors, each with the + appropriate escapes for input prompts or normal text. The code in + Prompts.py got slightly more complicated, but this very old and + annoying bug is finally fixed. + + All the credit for nailing down the real origin of this problem + and the correct solution goes to Jack Moffit <jack-AT-xiph.org>. + *Many* thanks to him for spending quite a bit of effort on this. + +2003-03-05 *** Released version 0.2.15pre1 + +2003-03-03 Fernando Perez <fperez@colorado.edu> + + * IPython/FakeModule.py: Moved the former _FakeModule to a + separate file, because it's also needed by Magic (to fix a similar + pickle-related issue in @run). + +2003-03-02 Fernando Perez <fperez@colorado.edu> + + * IPython/Magic.py (Magic.magic_autocall): new magic to control + the autocall option at runtime. + (Magic.magic_dhist): changed self.user_ns to self.shell.user_ns + across Magic.py to start separating Magic from InteractiveShell. + (Magic._ofind): Fixed to return proper namespace for dotted + names. Before, a dotted name would always return 'not currently + defined', because it would find the 'parent'. s.x would be found, + but since 'x' isn't defined by itself, it would get confused. + (Magic.magic_run): Fixed pickling problems reported by Ralf + Ahlbrink <RAhlbrink-AT-RosenInspection.net>. The fix was similar to + that I'd used when Mike Heeter reported similar issues at the + top-level, but now for @run. It boils down to injecting the + namespace where code is being executed with something that looks + enough like a module to fool pickle.dump(). Since a pickle stores + a named reference to the importing module, we need this for + pickles to save something sensible. + + * IPython/ipmaker.py (make_IPython): added an autocall option. + + * IPython/iplib.py (InteractiveShell._prefilter): reordered all of + the auto-eval code. Now autocalling is an option, and the code is + also vastly safer. There is no more eval() involved at all. + +2003-03-01 Fernando Perez <fperez@colorado.edu> + + * IPython/Magic.py (Magic._ofind): Changed interface to return a + dict with named keys instead of a tuple. + + * IPython: Started using CVS for IPython as of 0.2.15pre1. + + * setup.py (make_shortcut): Fixed message about directories + created during Windows installation (the directories were ok, just + the printed message was misleading). Thanks to Chris Liechti + <cliechti-AT-gmx.net> for the heads up. + +2003-02-21 Fernando Perez <fperez@colorado.edu> + + * IPython/iplib.py (InteractiveShell._prefilter): Fixed catching + of ValueError exception when checking for auto-execution. This + one is raised by things like Numeric arrays arr.flat when the + array is non-contiguous. + +2003-01-31 Fernando Perez <fperez@colorado.edu> + + * IPython/genutils.py (SystemExec.bq): Fixed bug where bq would + not return any value at all (even though the command would get + executed). + (xsys): Flush stdout right after printing the command to ensure + proper ordering of commands and command output in the total + output. + (SystemExec/xsys/bq): Switched the names of xsys/bq and + system/getoutput as defaults. The old ones are kept for + compatibility reasons, so no code which uses this library needs + changing. + +2003-01-27 *** Released version 0.2.14 + +2003-01-25 Fernando Perez <fperez@colorado.edu> + + * IPython/Magic.py (Magic.magic_edit): Fixed problem where + functions defined in previous edit sessions could not be re-edited + (because the temp files were immediately removed). Now temp files + are removed only at IPython's exit. + (Magic.magic_run): Improved @run to perform shell-like expansions + on its arguments (~users and $VARS). With this, @run becomes more + like a normal command-line. + + * IPython/Shell.py (IPShellEmbed.__call__): Fixed a bunch of small + bugs related to embedding and cleaned up that code. A fairly + important one was the impossibility to access the global namespace + through the embedded IPython (only local variables were visible). + +2003-01-14 Fernando Perez <fperez@colorado.edu> + + * IPython/iplib.py (InteractiveShell._prefilter): Fixed + auto-calling to be a bit more conservative. Now it doesn't get + triggered if any of '!=()<>' are in the rest of the input line, to + allow comparing callables. Thanks to Alex for the heads up. + +2003-01-07 Fernando Perez <fperez@colorado.edu> + + * IPython/genutils.py (page): fixed estimation of the number of + lines in a string to be paged to simply count newlines. This + prevents over-guessing due to embedded escape sequences. A better + long-term solution would involve stripping out the control chars + for the count, but it's potentially so expensive I just don't + think it's worth doing. + +2002-12-19 *** Released version 0.2.14pre50 + +2002-12-19 Fernando Perez <fperez@colorado.edu> + + * tools/release (version): Changed release scripts to inform + Andrea and build a NEWS file with a list of recent changes. + + * IPython/ColorANSI.py (__all__): changed terminal detection + code. Seems to work better for xterms without breaking + konsole. Will need more testing to determine if WinXP and Mac OSX + also work ok. + +2002-12-18 *** Released version 0.2.14pre49 + +2002-12-18 Fernando Perez <fperez@colorado.edu> + + * Docs: added new info about Mac OSX, from Andrea. + + * IPython/Gnuplot2.py (String): Added a String PlotItem class to + allow direct plotting of python strings whose format is the same + of gnuplot data files. + +2002-12-16 Fernando Perez <fperez@colorado.edu> + + * IPython/iplib.py (InteractiveShell.interact): fixed default (y) + value of exit question to be acknowledged. + +2002-12-03 Fernando Perez <fperez@colorado.edu> + + * IPython/ipmaker.py: removed generators, which had been added + by mistake in an earlier debugging run. This was causing trouble + to users of python 2.1.x. Thanks to Abel Daniel <abli-AT-freemail.hu> + for pointing this out. + +2002-11-17 Fernando Perez <fperez@colorado.edu> + + * Manual: updated the Gnuplot section. + + * IPython/GnuplotRuntime.py: refactored a lot all this code, with + a much better split of what goes in Runtime and what goes in + Interactive. + + * IPython/ipmaker.py: fixed bug where import_fail_info wasn't + being imported from iplib. + + * IPython/GnuplotInteractive.py (magic_gpc): renamed @gp to @gpc + for command-passing. Now the global Gnuplot instance is called + 'gp' instead of 'g', which was really a far too fragile and + common name. + + * IPython/Gnuplot2.py (eps_fix_bbox): added this to fix broken + bounding boxes generated by Gnuplot for square plots. + + * IPython/genutils.py (popkey): new function added. I should + suggest this on c.l.py as a dict method, it seems useful. + + * IPython/Gnuplot2.py (Gnuplot.plot): Overhauled plot and replot + to transparently handle PostScript generation. MUCH better than + the previous plot_eps/replot_eps (which I removed now). The code + is also fairly clean and well documented now (including + docstrings). + +2002-11-13 Fernando Perez <fperez@colorado.edu> + + * IPython/Magic.py (Magic.magic_edit): fixed docstring + (inconsistent with options). + + * IPython/Gnuplot2.py (Gnuplot.hardcopy): hardcopy had been + manually disabled, I don't know why. Fixed it. + (Gnuplot._plot_eps): added new plot_eps/replot_eps to get directly + eps output. + +2002-11-12 Fernando Perez <fperez@colorado.edu> + + * IPython/genutils.py (ask_yes_no): trap EOF and ^C so that they + don't propagate up to caller. Fixes crash reported by François + Pinard. + +2002-11-09 Fernando Perez <fperez@colorado.edu> + + * IPython/ipmaker.py (make_IPython): fixed problem with writing + history file for new users. + (make_IPython): fixed bug where initial install would leave the + user running in the .ipython dir. + (make_IPython): fixed bug where config dir .ipython would be + created regardless of the given -ipythondir option. Thanks to Cory + Dodt <cdodt-AT-fcoe.k12.ca.us> for the bug report. + + * IPython/genutils.py (ask_yes_no): new function for asking yes/no + type confirmations. Will need to use it in all of IPython's code + consistently. + + * IPython/CrashHandler.py (CrashHandler.__call__): changed the + context to print 31 lines instead of the default 5. This will make + the crash reports extremely detailed in case the problem is in + libraries I don't have access to. + + * IPython/iplib.py (InteractiveShell.interact): changed the 'last + line of defense' code to still crash, but giving users fair + warning. I don't want internal errors to go unreported: if there's + an internal problem, IPython should crash and generate a full + report. + +2002-11-08 Fernando Perez <fperez@colorado.edu> + + * IPython/iplib.py (InteractiveShell.interact): added code to trap + otherwise uncaught exceptions which can appear if people set + sys.stdout to something badly broken. Thanks to a crash report + from henni-AT-mail.brainbot.com. + +2002-11-04 Fernando Perez <fperez@colorado.edu> + + * IPython/iplib.py (InteractiveShell.interact): added + __IPYTHON__active to the builtins. It's a flag which goes on when + the interaction starts and goes off again when it stops. This + allows embedding code to detect being inside IPython. Before this + was done via __IPYTHON__, but that only shows that an IPython + instance has been created. + + * IPython/Magic.py (Magic.magic_env): I realized that in a + UserDict, instance.data holds the data as a normal dict. So I + modified @env to return os.environ.data instead of rebuilding a + dict by hand. + +2002-11-02 Fernando Perez <fperez@colorado.edu> + + * IPython/genutils.py (warn): changed so that level 1 prints no + header. Level 2 is now the default (with 'WARNING' header, as + before). I think I tracked all places where changes were needed in + IPython, but outside code using the old level numbering may have + broken. + + * IPython/iplib.py (InteractiveShell.runcode): added this to + handle the tracebacks in SystemExit traps correctly. The previous + code (through interact) was printing more of the stack than + necessary, showing IPython internal code to the user. + + * IPython/UserConfig/ipythonrc.py: Made confirm_exit 1 by + default. Now that the default at the confirmation prompt is yes, + it's not so intrusive. François' argument that ipython sessions + tend to be complex enough not to lose them from an accidental C-d, + is a valid one. + + * IPython/iplib.py (InteractiveShell.interact): added a + showtraceback() call to the SystemExit trap, and modified the exit + confirmation to have yes as the default. + + * IPython/UserConfig/ipythonrc.py: removed 'session' option from + this file. It's been gone from the code for a long time, this was + simply leftover junk. + +2002-11-01 Fernando Perez <fperez@colorado.edu> + + * IPython/UserConfig/ipythonrc.py: new confirm_exit option + added. If set, IPython now traps EOF and asks for + confirmation. After a request by François Pinard. + + * IPython/Magic.py (Magic.magic_Exit): New @Exit and @Quit instead + of @abort, and with a new (better) mechanism for handling the + exceptions. + +2002-10-27 Fernando Perez <fperez@colorado.edu> + + * IPython/usage.py (__doc__): updated the --help information and + the ipythonrc file to indicate that -log generates + ./ipython.log. Also fixed the corresponding info in @logstart. + This and several other fixes in the manuals thanks to reports by + François Pinard <pinard-AT-iro.umontreal.ca>. + + * IPython/Logger.py (Logger.switch_log): Fixed error message to + refer to @logstart (instead of @log, which doesn't exist). + + * IPython/iplib.py (InteractiveShell._prefilter): fixed + AttributeError crash. Thanks to Christopher Armstrong + <radix-AT-twistedmatrix.com> for the report/fix. This bug had been + introduced recently (in 0.2.14pre37) with the fix to the eval + problem mentioned below. + +2002-10-17 Fernando Perez <fperez@colorado.edu> + + * IPython/ConfigLoader.py (ConfigLoader.load): Fixes for Windows + installation. Thanks to Leonardo Santagada <retype-AT-terra.com.br>. + + * IPython/iplib.py (InteractiveShell._prefilter): Many changes to + this function to fix a problem reported by Alex Schmolck. He saw + it with list comprehensions and generators, which were getting + called twice. The real problem was an 'eval' call in testing for + automagic which was evaluating the input line silently. + + This is a potentially very nasty bug, if the input has side + effects which must not be repeated. The code is much cleaner now, + without any blanket 'except' left and with a regexp test for + actual function names. + + But an eval remains, which I'm not fully comfortable with. I just + don't know how to find out if an expression could be a callable in + the user's namespace without doing an eval on the string. However + that string is now much more strictly checked so that no code + slips by, so the eval should only happen for things that can + really be only function/method names. + +2002-10-15 Fernando Perez <fperez@colorado.edu> + + * Updated LyX to 1.2.1 so I can work on the docs again. Added Mac + OSX information to main manual, removed README_Mac_OSX file from + distribution. Also updated credits for recent additions. + +2002-10-10 Fernando Perez <fperez@colorado.edu> + + * README_Mac_OSX: Added a README for Mac OSX users for fixing + terminal-related issues. Many thanks to Andrea Riciputi + <andrea.riciputi-AT-libero.it> for writing it. + + * IPython/UserConfig/ipythonrc.py: Fixes to various small issues, + thanks to Thorsten Kampe <thorsten-AT-thorstenkampe.de>. + + * setup.py (make_shortcut): Fixes for Windows installation. Thanks + to Fredrik Kant <fredrik.kant-AT-front.com> and Syver Enstad + <syver-en-AT-online.no> who both submitted patches for this problem. + + * IPython/iplib.py (InteractiveShell.embed_mainloop): Patch for + global embedding to make sure that things don't overwrite user + globals accidentally. Thanks to Richard <rxe-AT-renre-europe.com> + + * IPython/Gnuplot2.py (gp): Patch for Gnuplot.py 1.6 + compatibility. Thanks to Hayden Callow + <h.callow-AT-elec.canterbury.ac.nz> + +2002-10-04 Fernando Perez <fperez@colorado.edu> + + * IPython/Gnuplot2.py (PlotItem): Added 'index' option for + Gnuplot.File objects. + +2002-07-23 Fernando Perez <fperez@colorado.edu> + + * IPython/genutils.py (timing): Added timings() and timing() for + quick access to the most commonly needed data, the execution + times. Old timing() renamed to timings_out(). + +2002-07-18 Fernando Perez <fperez@colorado.edu> + + * IPython/Shell.py (IPShellEmbed.restore_system_completer): fixed + bug with nested instances disrupting the parent's tab completion. + + * IPython/iplib.py (all_completions): Added Alex Schmolck's + all_completions code to begin the emacs integration. + + * IPython/Gnuplot2.py (zip_items): Added optional 'titles' + argument to allow titling individual arrays when plotting. + +2002-07-15 Fernando Perez <fperez@colorado.edu> + + * setup.py (make_shortcut): changed to retrieve the value of + 'Program Files' directory from the registry (this value changes in + non-english versions of Windows). Thanks to Thomas Fanslau + <tfanslau-AT-gmx.de> for the report. + +2002-07-10 Fernando Perez <fperez@colorado.edu> + + * IPython/ultraTB.py (VerboseTB.debugger): enabled workaround for + a bug in pdb, which crashes if a line with only whitespace is + entered. Bug report submitted to sourceforge. + +2002-07-09 Fernando Perez <fperez@colorado.edu> + + * IPython/ultraTB.py (VerboseTB.nullrepr): fixed rare crash when + reporting exceptions (it's a bug in inspect.py, I just set a + workaround). + +2002-07-08 Fernando Perez <fperez@colorado.edu> + + * IPython/iplib.py (InteractiveShell.__init__): fixed reference to + __IPYTHON__ in __builtins__ to show up in user_ns. + +2002-07-03 Fernando Perez <fperez@colorado.edu> + + * IPython/GnuplotInteractive.py (magic_gp_set_default): changed + name from @gp_set_instance to @gp_set_default. + + * IPython/ipmaker.py (make_IPython): default editor value set to + '0' (a string), to match the rc file. Otherwise will crash when + .strip() is called on it. + + +2002-06-28 Fernando Perez <fperez@colorado.edu> + + * IPython/iplib.py (InteractiveShell.safe_execfile): fix importing + of files in current directory when a file is executed via + @run. Patch also by RA <ralf_ahlbrink-AT-web.de>. + + * setup.py (manfiles): fix for rpm builds, submitted by RA + <ralf_ahlbrink-AT-web.de>. Now we have RPMs! + + * IPython/ipmaker.py (make_IPython): fixed lookup of default + editor when set to '0'. Problem was, '0' evaluates to True (it's a + string!). A. Schmolck caught this one. + +2002-06-27 Fernando Perez <fperez@colorado.edu> + + * IPython/ipmaker.py (make_IPython): fixed bug when running user + defined files at the cmd line. __name__ wasn't being set to + __main__. + + * IPython/Gnuplot2.py (zip_items): improved it so it can plot also + regular lists and tuples besides Numeric arrays. + + * IPython/Prompts.py (CachedOutput.__call__): Added output + supression for input ending with ';'. Similar to Mathematica and + Matlab. The _* vars and Out[] list are still updated, just like + Mathematica behaves. + +2002-06-25 Fernando Perez <fperez@colorado.edu> + + * IPython/ConfigLoader.py (ConfigLoader.load): fixed checking of + .ini extensions for profiels under Windows. + + * IPython/OInspect.py (Inspector.pinfo): improved alignment of + string form. Fix contributed by Alexander Schmolck + <a.schmolck-AT-gmx.net> + + * IPython/GnuplotRuntime.py (gp_new): new function. Returns a + pre-configured Gnuplot instance. + +2002-06-21 Fernando Perez <fperez@colorado.edu> + + * IPython/numutils.py (exp_safe): new function, works around the + underflow problems in Numeric. + (log2): New fn. Safe log in base 2: returns exact integer answer + for exact integer powers of 2. + + * IPython/Magic.py (get_py_filename): fixed it not expanding '~' + properly. + +2002-06-20 Fernando Perez <fperez@colorado.edu> + + * IPython/genutils.py (timing): new function like + Mathematica's. Similar to time_test, but returns more info. + +2002-06-18 Fernando Perez <fperez@colorado.edu> + + * IPython/Magic.py (Magic.magic_save): modified @save and @r + according to Mike Heeter's suggestions. + +2002-06-16 Fernando Perez <fperez@colorado.edu> + + * IPython/GnuplotRuntime.py: Massive overhaul to the Gnuplot + system. GnuplotMagic is gone as a user-directory option. New files + make it easier to use all the gnuplot stuff both from external + programs as well as from IPython. Had to rewrite part of + hardcopy() b/c of a strange bug: often the ps files simply don't + get created, and require a repeat of the command (often several + times). + + * IPython/ultraTB.py (AutoFormattedTB.__call__): changed to + resolve output channel at call time, so that if sys.stderr has + been redirected by user this gets honored. + +2002-06-13 Fernando Perez <fperez@colorado.edu> + + * IPython/Shell.py (IPShell.__init__): Changed IPythonShell to + IPShell. Kept a copy with the old names to avoid breaking people's + embedded code. + + * IPython/ipython: simplified it to the bare minimum after + Holger's suggestions. Added info about how to use it in + PYTHONSTARTUP. + + * IPython/Shell.py (IPythonShell): changed the options passing + from a string with funky %s replacements to a straight list. Maybe + a bit more typing, but it follows sys.argv conventions, so there's + less special-casing to remember. + +2002-06-12 Fernando Perez <fperez@colorado.edu> + + * IPython/Magic.py (Magic.magic_r): new magic auto-repeat + command. Thanks to a suggestion by Mike Heeter. + (Magic.magic_pfile): added behavior to look at filenames if given + arg is not a defined object. + (Magic.magic_save): New @save function to save code snippets. Also + a Mike Heeter idea. + + * IPython/UserConfig/GnuplotMagic.py (plot): Improvements to + plot() and replot(). Much more convenient now, especially for + interactive use. + + * IPython/Magic.py (Magic.magic_run): Added .py automatically to + filenames. + +2002-06-02 Fernando Perez <fperez@colorado.edu> + + * IPython/Struct.py (Struct.__init__): modified to admit + initialization via another struct. + + * IPython/genutils.py (SystemExec.__init__): New stateful + interface to xsys and bq. Useful for writing system scripts. + +2002-05-30 Fernando Perez <fperez@colorado.edu> + + * MANIFEST.in: Changed docfile selection to exclude all the lyx + documents. This will make the user download smaller (it's getting + too big). + +2002-05-29 Fernando Perez <fperez@colorado.edu> + + * IPython/iplib.py (_FakeModule.__init__): New class introduced to + fix problems with shelve and pickle. Seems to work, but I don't + know if corner cases break it. Thanks to Mike Heeter + <korora-AT-SDF.LONESTAR.ORG> for the bug reports and test cases. + +2002-05-24 Fernando Perez <fperez@colorado.edu> + + * IPython/Magic.py (Macro.__init__): fixed magics embedded in + macros having broken. + +2002-05-21 Fernando Perez <fperez@colorado.edu> + + * IPython/Magic.py (Magic.magic_logstart): fixed recently + introduced logging bug: all history before logging started was + being written one character per line! This came from the redesign + of the input history as a special list which slices to strings, + not to lists. + +2002-05-20 Fernando Perez <fperez@colorado.edu> + + * IPython/Prompts.py (CachedOutput.__init__): made the color table + be an attribute of all classes in this module. The design of these + classes needs some serious overhauling. + + * IPython/DPyGetOpt.py (DPyGetOpt.setPosixCompliance): fixed bug + which was ignoring '_' in option names. + + * IPython/ultraTB.py (FormattedTB.__init__): Changed + 'Verbose_novars' to 'Context' and made it the new default. It's a + bit more readable and also safer than verbose. + + * IPython/PyColorize.py (Parser.__call__): Fixed coloring of + triple-quoted strings. + + * IPython/OInspect.py (__all__): new module exposing the object + introspection facilities. Now the corresponding magics are dummy + wrappers around this. Having this module will make it much easier + to put these functions into our modified pdb. + This new object inspector system uses the new colorizing module, + so source code and other things are nicely syntax highlighted. + +2002-05-18 Fernando Perez <fperez@colorado.edu> + + * IPython/ColorANSI.py: Split the coloring tools into a separate + module so I can use them in other code easier (they were part of + ultraTB). + +2002-05-17 Fernando Perez <fperez@colorado.edu> + + * IPython/UserConfig/GnuplotMagic.py (magic_gp_set_instance): + fixed it to set the global 'g' also to the called instance, as + long as 'g' was still a gnuplot instance (so it doesn't overwrite + user's 'g' variables). + + * IPython/iplib.py (InteractiveShell.__init__): Added In/Out + global variables (aliases to _ih,_oh) so that users which expect + In[5] or Out[7] to work aren't unpleasantly surprised. + (InputList.__getslice__): new class to allow executing slices of + input history directly. Very simple class, complements the use of + macros. + +2002-05-16 Fernando Perez <fperez@colorado.edu> + + * setup.py (docdirbase): make doc directory be just doc/IPython + without version numbers, it will reduce clutter for users. + + * IPython/Magic.py (Magic.magic_run): Add explicit local dict to + execfile call to prevent possible memory leak. See for details: + http://mail.python.org/pipermail/python-list/2002-February/088476.html + +2002-05-15 Fernando Perez <fperez@colorado.edu> + + * IPython/Magic.py (Magic.magic_psource): made the object + introspection names be more standard: pdoc, pdef, pfile and + psource. They all print/page their output, and it makes + remembering them easier. Kept old names for compatibility as + aliases. + +2002-05-14 Fernando Perez <fperez@colorado.edu> + + * IPython/UserConfig/GnuplotMagic.py: I think I finally understood + what the mouse problem was. The trick is to use gnuplot with temp + files and NOT with pipes (for data communication), because having + both pipes and the mouse on is bad news. + +2002-05-13 Fernando Perez <fperez@colorado.edu> + + * IPython/Magic.py (Magic._ofind): fixed namespace order search + bug. Information would be reported about builtins even when + user-defined functions overrode them. + +2002-05-11 Fernando Perez <fperez@colorado.edu> + + * IPython/__init__.py (__all__): removed FlexCompleter from + __all__ so that things don't fail in platforms without readline. + +2002-05-10 Fernando Perez <fperez@colorado.edu> + + * IPython/__init__.py (__all__): removed numutils from __all__ b/c + it requires Numeric, effectively making Numeric a dependency for + IPython. + + * Released 0.2.13 + + * IPython/Magic.py (Magic.magic_prun): big overhaul to the + profiler interface. Now all the major options from the profiler + module are directly supported in IPython, both for single + expressions (@prun) and for full programs (@run -p). + +2002-05-09 Fernando Perez <fperez@colorado.edu> + + * IPython/Magic.py (Magic.magic_doc): fixed to show docstrings of + magic properly formatted for screen. + + * setup.py (make_shortcut): Changed things to put pdf version in + doc/ instead of doc/manual (had to change lyxport a bit). + + * IPython/Magic.py (Profile.string_stats): made profile runs go + through pager (they are long and a pager allows searching, saving, + etc.) + +2002-05-08 Fernando Perez <fperez@colorado.edu> + + * Released 0.2.12 + +2002-05-06 Fernando Perez <fperez@colorado.edu> + + * IPython/Magic.py (Magic.magic_hist): small bug fixed (recently + introduced); 'hist n1 n2' was broken. + (Magic.magic_pdb): added optional on/off arguments to @pdb + (Magic.magic_run): added option -i to @run, which executes code in + the IPython namespace instead of a clean one. Also added @irun as + an alias to @run -i. + + * IPython/UserConfig/GnuplotMagic.py (magic_gp_set_instance): + fixed (it didn't really do anything, the namespaces were wrong). + + * IPython/Debugger.py (__init__): Added workaround for python 2.1 + + * IPython/__init__.py (__all__): Fixed package namespace, now + 'import IPython' does give access to IPython.<all> as + expected. Also renamed __release__ to Release. + + * IPython/Debugger.py (__license__): created new Pdb class which + functions like a drop-in for the normal pdb.Pdb but does NOT + import readline by default. This way it doesn't muck up IPython's + readline handling, and now tab-completion finally works in the + debugger -- sort of. It completes things globally visible, but the + completer doesn't track the stack as pdb walks it. That's a bit + tricky, and I'll have to implement it later. + +2002-05-05 Fernando Perez <fperez@colorado.edu> + + * IPython/Magic.py (Magic.magic_oinfo): fixed formatting bug for + magic docstrings when printed via ? (explicit \'s were being + printed). + + * IPython/ipmaker.py (make_IPython): fixed namespace + identification bug. Now variables loaded via logs or command-line + files are recognized in the interactive namespace by @who. + + * IPython/iplib.py (InteractiveShell.safe_execfile): Fixed bug in + log replay system stemming from the string form of Structs. + + * IPython/Magic.py (Macro.__init__): improved macros to properly + handle magic commands in them. + (Magic.magic_logstart): usernames are now expanded so 'logstart + ~/mylog' now works. + + * IPython/iplib.py (complete): fixed bug where paths starting with + '/' would be completed as magic names. + +2002-05-04 Fernando Perez <fperez@colorado.edu> + + * IPython/Magic.py (Magic.magic_run): added options -p and -f to + allow running full programs under the profiler's control. + + * IPython/ultraTB.py (FormattedTB.__init__): Added Verbose_novars + mode to report exceptions verbosely but without formatting + variables. This addresses the issue of ipython 'freezing' (it's + not frozen, but caught in an expensive formatting loop) when huge + variables are in the context of an exception. + (VerboseTB.text): Added '--->' markers at line where exception was + triggered. Much clearer to read, especially in NoColor modes. + + * IPython/Magic.py (Magic.magic_run): bugfix: -n option had been + implemented in reverse when changing to the new parse_options(). + +2002-05-03 Fernando Perez <fperez@colorado.edu> + + * IPython/Magic.py (Magic.parse_options): new function so that + magics can parse options easier. + (Magic.magic_prun): new function similar to profile.run(), + suggested by Chris Hart. + (Magic.magic_cd): fixed behavior so that it only changes if + directory actually is in history. + + * IPython/usage.py (__doc__): added information about potential + slowness of Verbose exception mode when there are huge data + structures to be formatted (thanks to Archie Paulson). + + * IPython/ipmaker.py (make_IPython): Changed default logging + (when simply called with -log) to use curr_dir/ipython.log in + rotate mode. Fixed crash which was occuring with -log before + (thanks to Jim Boyle). + +2002-05-01 Fernando Perez <fperez@colorado.edu> + + * Released 0.2.11 for these fixes (mainly the ultraTB one which + was nasty -- though somewhat of a corner case). + + * IPython/ultraTB.py (AutoFormattedTB.text): renamed __text to + text (was a bug). + +2002-04-30 Fernando Perez <fperez@colorado.edu> + + * IPython/UserConfig/GnuplotMagic.py (magic_gp): Minor fix to add + a print after ^D or ^C from the user so that the In[] prompt + doesn't over-run the gnuplot one. + +2002-04-29 Fernando Perez <fperez@colorado.edu> + + * Released 0.2.10 + + * IPython/__release__.py (version): get date dynamically. + + * Misc. documentation updates thanks to Arnd's comments. Also ran + a full spellcheck on the manual (hadn't been done in a while). + +2002-04-27 Fernando Perez <fperez@colorado.edu> + + * IPython/Magic.py (Magic.magic_logstart): Fixed bug where + starting a log in mid-session would reset the input history list. + +2002-04-26 Fernando Perez <fperez@colorado.edu> + + * IPython/iplib.py (InteractiveShell.wait): Fixed bug where not + all files were being included in an update. Now anything in + UserConfig that matches [A-Za-z]*.py will go (this excludes + __init__.py) + +2002-04-25 Fernando Perez <fperez@colorado.edu> + + * IPython/iplib.py (InteractiveShell.__init__): Added __IPYTHON__ + to __builtins__ so that any form of embedded or imported code can + test for being inside IPython. + + * IPython/UserConfig/GnuplotMagic.py: (magic_gp_set_instance): + changed to GnuplotMagic because it's now an importable module, + this makes the name follow that of the standard Gnuplot module. + GnuplotMagic can now be loaded at any time in mid-session. + +2002-04-24 Fernando Perez <fperez@colorado.edu> + + * IPython/numutils.py: removed SIUnits. It doesn't properly set + the globals (IPython has its own namespace) and the + PhysicalQuantity stuff is much better anyway. + + * IPython/UserConfig/example-gnuplot.py (g2): Added gnuplot + embedding example to standard user directory for + distribution. Also put it in the manual. + + * IPython/numutils.py (gnuplot_exec): Changed to take a gnuplot + instance as first argument (so it doesn't rely on some obscure + hidden global). + + * IPython/UserConfig/ipythonrc.py: put () back in accepted + delimiters. While it prevents ().TAB from working, it allows + completions in open (... expressions. This is by far a more common + case. + +2002-04-23 Fernando Perez <fperez@colorado.edu> + + * IPython/Extensions/InterpreterPasteInput.py: new + syntax-processing module for pasting lines with >>> or ... at the + start. + + * IPython/Extensions/PhysicalQ_Interactive.py + (PhysicalQuantityInteractive.__int__): fixed to work with either + Numeric or math. + + * IPython/UserConfig/ipythonrc-numeric.py: reorganized the + provided profiles. Now we have: + -math -> math module as * and cmath with its own namespace. + -numeric -> Numeric as *, plus gnuplot & grace + -physics -> same as before + + * IPython/Magic.py (Magic.magic_magic): Fixed bug where + user-defined magics wouldn't be found by @magic if they were + defined as class methods. Also cleaned up the namespace search + logic and the string building (to use %s instead of many repeated + string adds). + + * IPython/UserConfig/example-magic.py (magic_foo): updated example + of user-defined magics to operate with class methods (cleaner, in + line with the gnuplot code). + +2002-04-22 Fernando Perez <fperez@colorado.edu> + + * setup.py: updated dependency list so that manual is updated when + all included files change. + + * IPython/ipmaker.py (make_IPython): Fixed bug which was ignoring + the delimiter removal option (the fix is ugly right now). + + * IPython/UserConfig/ipythonrc-physics.py: simplified not to load + all of the math profile (quicker loading, no conflict between + g-9.8 and g-gnuplot). + + * IPython/CrashHandler.py (CrashHandler.__call__): changed default + name of post-mortem files to IPython_crash_report.txt. + + * Cleanup/update of the docs. Added all the new readline info and + formatted all lists as 'real lists'. + + * IPython/ipmaker.py (make_IPython): removed now-obsolete + tab-completion options, since the full readline parse_and_bind is + now accessible. + + * IPython/iplib.py (InteractiveShell.init_readline): Changed + handling of readline options. Now users can specify any string to + be passed to parse_and_bind(), as well as the delimiters to be + removed. + (InteractiveShell.__init__): Added __name__ to the global + namespace so that things like Itpl which rely on its existence + don't crash. + (InteractiveShell._prefilter): Defined the default with a _ so + that prefilter() is easier to override, while the default one + remains available. + +2002-04-18 Fernando Perez <fperez@colorado.edu> + + * Added information about pdb in the docs. + +2002-04-17 Fernando Perez <fperez@colorado.edu> + + * IPython/ipmaker.py (make_IPython): added rc_override option to + allow passing config options at creation time which may override + anything set in the config files or command line. This is + particularly useful for configuring embedded instances. + +2002-04-15 Fernando Perez <fperez@colorado.edu> + + * IPython/Logger.py (Logger.log): Fixed a nasty bug which could + crash embedded instances because of the input cache falling out of + sync with the output counter. + + * IPython/Shell.py (IPythonShellEmbed.__init__): added a debug + mode which calls pdb after an uncaught exception in IPython itself. + +2002-04-14 Fernando Perez <fperez@colorado.edu> + + * IPython/iplib.py (InteractiveShell.showtraceback): pdb mucks up + readline, fix it back after each call. + + * IPython/ultraTB.py (AutoFormattedTB.__text): made text a private + method to force all access via __call__(), which guarantees that + traceback references are properly deleted. + + * IPython/Prompts.py (CachedOutput._display): minor fixes to + improve printing when pprint is in use. + +2002-04-13 Fernando Perez <fperez@colorado.edu> + + * IPython/Shell.py (IPythonShellEmbed.__call__): SystemExit + exceptions aren't caught anymore. If the user triggers one, he + should know why he's doing it and it should go all the way up, + just like any other exception. So now @abort will fully kill the + embedded interpreter and the embedding code (unless that happens + to catch SystemExit). + + * IPython/ultraTB.py (VerboseTB.__init__): added a call_pdb flag + and a debugger() method to invoke the interactive pdb debugger + after printing exception information. Also added the corresponding + -pdb option and @pdb magic to control this feature, and updated + the docs. After a suggestion from Christopher Hart + (hart-AT-caltech.edu). + +2002-04-12 Fernando Perez <fperez@colorado.edu> + + * IPython/Shell.py (IPythonShellEmbed.__init__): modified to use + the exception handlers defined by the user (not the CrashHandler) + so that user exceptions don't trigger an ipython bug report. + + * IPython/ultraTB.py (ColorTB.__init__): made the color scheme + configurable (it should have always been so). + +2002-03-26 Fernando Perez <fperez@colorado.edu> + + * IPython/Shell.py (IPythonShellEmbed.__call__): many changes here + and there to fix embedding namespace issues. This should all be + done in a more elegant way. + +2002-03-25 Fernando Perez <fperez@colorado.edu> + + * IPython/genutils.py (get_home_dir): Try to make it work under + win9x also. + +2002-03-20 Fernando Perez <fperez@colorado.edu> + + * IPython/Shell.py (IPythonShellEmbed.__init__): leave + sys.displayhook untouched upon __init__. + +2002-03-19 Fernando Perez <fperez@colorado.edu> + + * Released 0.2.9 (for embedding bug, basically). + + * IPython/Shell.py (IPythonShellEmbed.__call__): Trap SystemExit + exceptions so that enclosing shell's state can be restored. + + * Changed magic_gnuplot.py to magic-gnuplot.py to standardize + naming conventions in the .ipython/ dir. + + * IPython/iplib.py (InteractiveShell.init_readline): removed '-' + from delimiters list so filenames with - in them get expanded. + + * IPython/Shell.py (IPythonShellEmbed.__call__): fixed bug with + sys.displayhook not being properly restored after an embedded call. + + 2002-03-18 Fernando Perez <fperez@colorado.edu> + + * Released 0.2.8 + + * IPython/iplib.py (InteractiveShell.user_setup): fixed bug where + some files weren't being included in a -upgrade. + (InteractiveShell.init_readline): Added 'set show-all-if-ambiguous + on' so that the first tab completes. + (InteractiveShell.handle_magic): fixed bug with spaces around + quotes breaking many magic commands. + + * setup.py: added note about ignoring the syntax error messages at + installation. + + * IPython/UserConfig/magic_gnuplot.py (magic_gp): finished + streamlining the gnuplot interface, now there's only one magic @gp. + +2002-03-17 Fernando Perez <fperez@colorado.edu> + + * IPython/UserConfig/magic_gnuplot.py: new name for the + example-magic_pm.py file. Much enhanced system, now with a shell + for communicating directly with gnuplot, one command at a time. + + * IPython/Magic.py (Magic.magic_run): added option -n to prevent + setting __name__=='__main__'. + + * IPython/UserConfig/example-magic_pm.py (magic_pm): Added + mini-shell for accessing gnuplot from inside ipython. Should + extend it later for grace access too. Inspired by Arnd's + suggestion. + + * IPython/iplib.py (InteractiveShell.handle_magic): fixed bug when + calling magic functions with () in their arguments. Thanks to Arnd + Baecker for pointing this to me. + + * IPython/numutils.py (sum_flat): fixed bug. Would recurse + infinitely for integer or complex arrays (only worked with floats). + +2002-03-16 Fernando Perez <fperez@colorado.edu> + + * setup.py: Merged setup and setup_windows into a single script + which properly handles things for windows users. + +2002-03-15 Fernando Perez <fperez@colorado.edu> + + * Big change to the manual: now the magics are all automatically + documented. This information is generated from their docstrings + and put in a latex file included by the manual lyx file. This way + we get always up to date information for the magics. The manual + now also has proper version information, also auto-synced. + + For this to work, an undocumented --magic_docstrings option was added. + +2002-03-13 Fernando Perez <fperez@colorado.edu> + + * IPython/ultraTB.py (TermColors): fixed problem with dark colors + under CDE terminals. An explicit ;2 color reset is needed in the escapes. + +2002-03-12 Fernando Perez <fperez@colorado.edu> + + * IPython/ultraTB.py (TermColors): changed color escapes again to + fix the (old, reintroduced) line-wrapping bug. Basically, if + \001..\002 aren't given in the color escapes, lines get wrapped + weirdly. But giving those screws up old xterms and emacs terms. So + I added some logic for emacs terms to be ok, but I can't identify old + xterms separately ($TERM=='xterm' for many terminals, like konsole). + +2002-03-10 Fernando Perez <fperez@colorado.edu> + + * IPython/usage.py (__doc__): Various documentation cleanups and + updates, both in usage docstrings and in the manual. + + * IPython/Prompts.py (CachedOutput.set_colors): cleanups for + handling of caching. Set minimum acceptabe value for having a + cache at 20 values. + + * IPython/iplib.py (InteractiveShell.user_setup): moved the + install_first_time function to a method, renamed it and added an + 'upgrade' mode. Now people can update their config directory with + a simple command line switch (-upgrade, also new). + + * IPython/Magic.py (Magic.magic_pfile): Made @pfile an alias to + @file (convenient for automagic users under Python >= 2.2). + Removed @files (it seemed more like a plural than an abbrev. of + 'file show'). + + * IPython/iplib.py (install_first_time): Fixed crash if there were + backup files ('~') in .ipython/ install directory. + + * IPython/ipmaker.py (make_IPython): fixes for new prompt + system. Things look fine, but these changes are fairly + intrusive. Test them for a few days. + + * IPython/Prompts.py (CachedOutput.__init__): Massive rewrite of + the prompts system. Now all in/out prompt strings are user + controllable. This is particularly useful for embedding, as one + can tag embedded instances with particular prompts. + + Also removed global use of sys.ps1/2, which now allows nested + embeddings without any problems. Added command-line options for + the prompt strings. + +2002-03-08 Fernando Perez <fperez@colorado.edu> + + * IPython/UserConfig/example-embed-short.py (ipshell): added + example file with the bare minimum code for embedding. + + * IPython/Shell.py (IPythonShellEmbed.set_dummy_mode): added + functionality for the embeddable shell to be activated/deactivated + either globally or at each call. + + * IPython/Prompts.py (Prompt1.auto_rewrite): Fixes the problem of + rewriting the prompt with '--->' for auto-inputs with proper + coloring. Now the previous UGLY hack in handle_auto() is gone, and + this is handled by the prompts class itself, as it should. + +2002-03-05 Fernando Perez <fperez@colorado.edu> + + * IPython/Magic.py (Magic.magic_logstart): Changed @log to + @logstart to avoid name clashes with the math log function. + + * Big updates to X/Emacs section of the manual. + + * Removed ipython_emacs. Milan explained to me how to pass + arguments to ipython through Emacs. Some day I'm going to end up + learning some lisp... + +2002-03-04 Fernando Perez <fperez@colorado.edu> + + * IPython/ipython_emacs: Created script to be used as the + py-python-command Emacs variable so we can pass IPython + parameters. I can't figure out how to tell Emacs directly to pass + parameters to IPython, so a dummy shell script will do it. + + Other enhancements made for things to work better under Emacs' + various types of terminals. Many thanks to Milan Zamazal + <pdm-AT-zamazal.org> for all the suggestions and pointers. + +2002-03-01 Fernando Perez <fperez@colorado.edu> + + * IPython/ipmaker.py (make_IPython): added a --readline! option so + that loading of readline is now optional. This gives better + control to emacs users. + + * IPython/ultraTB.py (__date__): Modified color escape sequences + and now things work fine under xterm and in Emacs' term buffers + (though not shell ones). Well, in emacs you get colors, but all + seem to be 'light' colors (no difference between dark and light + ones). But the garbage chars are gone, and also in xterms. It + seems that now I'm using 'cleaner' ansi sequences. + +2002-02-21 Fernando Perez <fperez@colorado.edu> + + * Released 0.2.7 (mainly to publish the scoping fix). + + * IPython/Logger.py (Logger.logstate): added. A corresponding + @logstate magic was created. + + * IPython/Magic.py: fixed nested scoping problem under Python + 2.1.x (automagic wasn't working). + +2002-02-20 Fernando Perez <fperez@colorado.edu> + + * Released 0.2.6. + + * IPython/OutputTrap.py (OutputTrap.__init__): added a 'quiet' + option so that logs can come out without any headers at all. + + * IPython/UserConfig/ipythonrc-scipy.py: created a profile for + SciPy. + + * IPython/iplib.py (InteractiveShell.embed_mainloop): Changed so + that embedded IPython calls don't require vars() to be explicitly + passed. Now they are extracted from the caller's frame (code + snatched from Eric Jones' weave). Added better documentation to + the section on embedding and the example file. + + * IPython/genutils.py (page): Changed so that under emacs, it just + prints the string. You can then page up and down in the emacs + buffer itself. This is how the builtin help() works. + + * IPython/Prompts.py (CachedOutput.__call__): Fixed issue with + macro scoping: macros need to be executed in the user's namespace + to work as if they had been typed by the user. + + * IPython/Magic.py (Magic.magic_macro): Changed macros so they + execute automatically (no need to type 'exec...'). They then + behave like 'true macros'. The printing system was also modified + for this to work. + +2002-02-19 Fernando Perez <fperez@colorado.edu> + + * IPython/genutils.py (page_file): new function for paging files + in an OS-independent way. Also necessary for file viewing to work + well inside Emacs buffers. + (page): Added checks for being in an emacs buffer. + (page): fixed bug for Windows ($TERM isn't set in Windows). Fixed + same bug in iplib. + +2002-02-18 Fernando Perez <fperez@colorado.edu> + + * IPython/iplib.py (InteractiveShell.init_readline): modified use + of readline so that IPython can work inside an Emacs buffer. + + * IPython/ultraTB.py (AutoFormattedTB.__call__): some fixes to + method signatures (they weren't really bugs, but it looks cleaner + and keeps PyChecker happy). + + * IPython/ipmaker.py (make_IPython): added hooks Struct to __IP + for implementing various user-defined hooks. Currently only + display is done. + + * IPython/Prompts.py (CachedOutput._display): changed display + functions so that they can be dynamically changed by users easily. + + * IPython/Extensions/numeric_formats.py (num_display): added an + extension for printing NumPy arrays in flexible manners. It + doesn't do anything yet, but all the structure is in + place. Ultimately the plan is to implement output format control + like in Octave. + + * IPython/Magic.py (Magic.lsmagic): changed so that bound magic + methods are found at run-time by all the automatic machinery. + +2002-02-17 Fernando Perez <fperez@colorado.edu> + + * setup_Windows.py (make_shortcut): documented. Cleaned up the + whole file a little. + + * ToDo: closed this document. Now there's a new_design.lyx + document for all new ideas. Added making a pdf of it for the + end-user distro. + + * IPython/Logger.py (Logger.switch_log): Created this to replace + logon() and logoff(). It also fixes a nasty crash reported by + Philip Hisley <compsys-AT-starpower.net>. Many thanks to him. + + * IPython/iplib.py (complete): got auto-completion to work with + automagic (I had wanted this for a long time). + + * IPython/Magic.py (Magic.magic_files): Added @files as an alias + to @file, since file() is now a builtin and clashes with automagic + for @file. + + * Made some new files: Prompts, CrashHandler, Magic, Logger. All + of this was previously in iplib, which had grown to more than 2000 + lines, way too long. No new functionality, but it makes managing + the code a bit easier. + + * IPython/iplib.py (IPythonCrashHandler.__call__): Added version + information to crash reports. + +2002-02-12 Fernando Perez <fperez@colorado.edu> + + * Released 0.2.5. + +2002-02-11 Fernando Perez <fperez@colorado.edu> + + * Wrote a relatively complete Windows installer. It puts + everything in place, creates Start Menu entries and fixes the + color issues. Nothing fancy, but it works. + +2002-02-10 Fernando Perez <fperez@colorado.edu> + + * IPython/iplib.py (InteractiveShell.safe_execfile): added an + os.path.expanduser() call so that we can type @run ~/myfile.py and + have thigs work as expected. + + * IPython/genutils.py (page): fixed exception handling so things + work both in Unix and Windows correctly. Quitting a pager triggers + an IOError/broken pipe in Unix, and in windows not finding a pager + is also an IOError, so I had to actually look at the return value + of the exception, not just the exception itself. Should be ok now. + + * IPython/ultraTB.py (ColorSchemeTable.set_active_scheme): + modified to allow case-insensitive color scheme changes. + +2002-02-09 Fernando Perez <fperez@colorado.edu> + + * IPython/genutils.py (native_line_ends): new function to leave + user config files with os-native line-endings. + + * README and manual updates. + + * IPython/genutils.py: fixed unicode bug: use types.StringTypes + instead of StringType to catch Unicode strings. + + * IPython/genutils.py (filefind): fixed bug for paths with + embedded spaces (very common in Windows). + + * IPython/ipmaker.py (make_IPython): added a '.ini' to the rc + files under Windows, so that they get automatically associated + with a text editor. Windows makes it a pain to handle + extension-less files. + + * IPython/iplib.py (InteractiveShell.init_readline): Made the + warning about readline only occur for Posix. In Windows there's no + way to get readline, so why bother with the warning. + + * IPython/Struct.py (Struct.__str__): fixed to use self.__dict__ + for __str__ instead of dir(self), since dir() changed in 2.2. + + * Ported to Windows! Tested on XP, I suspect it should work fine + on NT/2000, but I don't think it will work on 98 et al. That + series of Windows is such a piece of junk anyway that I won't try + porting it there. The XP port was straightforward, showed a few + bugs here and there (fixed all), in particular some string + handling stuff which required considering Unicode strings (which + Windows uses). This is good, but hasn't been too tested :) No + fancy installer yet, I'll put a note in the manual so people at + least make manually a shortcut. + + * IPython/iplib.py (Magic.magic_colors): Unified the color options + into a single one, "colors". This now controls both prompt and + exception color schemes, and can be changed both at startup + (either via command-line switches or via ipythonrc files) and at + runtime, with @colors. + (Magic.magic_run): renamed @prun to @run and removed the old + @run. The two were too similar to warrant keeping both. + +2002-02-03 Fernando Perez <fperez@colorado.edu> + + * IPython/iplib.py (install_first_time): Added comment on how to + configure the color options for first-time users. Put a <return> + request at the end so that small-terminal users get a chance to + read the startup info. + +2002-01-23 Fernando Perez <fperez@colorado.edu> + + * IPython/iplib.py (CachedOutput.update): Changed output memory + variable names from _o,_oo,_ooo,_o<n> to simply _,__,___,_<n>. For + input history we still use _i. Did this b/c these variable are + very commonly used in interactive work, so the less we need to + type the better off we are. + (Magic.magic_prun): updated @prun to better handle the namespaces + the file will run in, including a fix for __name__ not being set + before. + +2002-01-20 Fernando Perez <fperez@colorado.edu> + + * IPython/ultraTB.py (VerboseTB.linereader): Fixed printing of + extra garbage for Python 2.2. Need to look more carefully into + this later. + +2002-01-19 Fernando Perez <fperez@colorado.edu> + + * IPython/iplib.py (InteractiveShell.showtraceback): fixed to + display SyntaxError exceptions properly formatted when they occur + (they can be triggered by imported code). + +2002-01-18 Fernando Perez <fperez@colorado.edu> + + * IPython/iplib.py (InteractiveShell.safe_execfile): now + SyntaxError exceptions are reported nicely formatted, instead of + spitting out only offset information as before. + (Magic.magic_prun): Added the @prun function for executing + programs with command line args inside IPython. + +2002-01-16 Fernando Perez <fperez@colorado.edu> + + * IPython/iplib.py (Magic.magic_hist): Changed @hist and @dhist + to *not* include the last item given in a range. This brings their + behavior in line with Python's slicing: + a[n1:n2] -> a[n1]...a[n2-1] + It may be a bit less convenient, but I prefer to stick to Python's + conventions *everywhere*, so users never have to wonder. + (Magic.magic_macro): Added @macro function to ease the creation of + macros. + +2002-01-05 Fernando Perez <fperez@colorado.edu> + + * Released 0.2.4. + + * IPython/iplib.py (Magic.magic_pdef): + (InteractiveShell.safe_execfile): report magic lines and error + lines without line numbers so one can easily copy/paste them for + re-execution. + + * Updated manual with recent changes. + + * IPython/iplib.py (Magic.magic_oinfo): added constructor + docstring printing when class? is called. Very handy for knowing + how to create class instances (as long as __init__ is well + documented, of course :) + (Magic.magic_doc): print both class and constructor docstrings. + (Magic.magic_pdef): give constructor info if passed a class and + __call__ info for callable object instances. + +2002-01-04 Fernando Perez <fperez@colorado.edu> + + * Made deep_reload() off by default. It doesn't always work + exactly as intended, so it's probably safer to have it off. It's + still available as dreload() anyway, so nothing is lost. + +2002-01-02 Fernando Perez <fperez@colorado.edu> + + * Released 0.2.3 (contacted R.Singh at CU about biopython course, + so I wanted an updated release). + +2001-12-27 Fernando Perez <fperez@colorado.edu> + + * IPython/iplib.py (InteractiveShell.interact): Added the original + code from 'code.py' for this module in order to change the + handling of a KeyboardInterrupt. This was necessary b/c otherwise + the history cache would break when the user hit Ctrl-C, and + interact() offers no way to add any hooks to it. + +2001-12-23 Fernando Perez <fperez@colorado.edu> + + * setup.py: added check for 'MANIFEST' before trying to remove + it. Thanks to Sean Reifschneider. + +2001-12-22 Fernando Perez <fperez@colorado.edu> + + * Released 0.2.2. + + * Finished (reasonably) writing the manual. Later will add the + python-standard navigation stylesheets, but for the time being + it's fairly complete. Distribution will include html and pdf + versions. + + * Bugfix: '.' wasn't being added to sys.path. Thanks to Prabhu + (MayaVi author). + +2001-12-21 Fernando Perez <fperez@colorado.edu> + + * Released 0.2.1. Barring any nasty bugs, this is it as far as a + good public release, I think (with the manual and the distutils + installer). The manual can use some work, but that can go + slowly. Otherwise I think it's quite nice for end users. Next + summer, rewrite the guts of it... + + * Changed format of ipythonrc files to use whitespace as the + separator instead of an explicit '='. Cleaner. + +2001-12-20 Fernando Perez <fperez@colorado.edu> + + * Started a manual in LyX. For now it's just a quick merge of the + various internal docstrings and READMEs. Later it may grow into a + nice, full-blown manual. + + * Set up a distutils based installer. Installation should now be + trivially simple for end-users. + +2001-12-11 Fernando Perez <fperez@colorado.edu> + + * Released 0.2.0. First public release, announced it at + comp.lang.python. From now on, just bugfixes... + + * Went through all the files, set copyright/license notices and + cleaned up things. Ready for release. + +2001-12-10 Fernando Perez <fperez@colorado.edu> + + * Changed the first-time installer not to use tarfiles. It's more + robust now and less unix-dependent. Also makes it easier for + people to later upgrade versions. + + * Changed @exit to @abort to reflect the fact that it's pretty + brutal (a sys.exit()). The difference between @abort and Ctrl-D + becomes significant only when IPyhton is embedded: in that case, + C-D closes IPython only, but @abort kills the enclosing program + too (unless it had called IPython inside a try catching + SystemExit). + + * Created Shell module which exposes the actuall IPython Shell + classes, currently the normal and the embeddable one. This at + least offers a stable interface we won't need to change when + (later) the internals are rewritten. That rewrite will be confined + to iplib and ipmaker, but the Shell interface should remain as is. + + * Added embed module which offers an embeddable IPShell object, + useful to fire up IPython *inside* a running program. Great for + debugging or dynamical data analysis. + +2001-12-08 Fernando Perez <fperez@colorado.edu> + + * Fixed small bug preventing seeing info from methods of defined + objects (incorrect namespace in _ofind()). + + * Documentation cleanup. Moved the main usage docstrings to a + separate file, usage.py (cleaner to maintain, and hopefully in the + future some perlpod-like way of producing interactive, man and + html docs out of it will be found). + + * Added @profile to see your profile at any time. + + * Added @p as an alias for 'print'. It's especially convenient if + using automagic ('p x' prints x). + + * Small cleanups and fixes after a pychecker run. + + * Changed the @cd command to handle @cd - and @cd -<n> for + visiting any directory in _dh. + + * Introduced _dh, a history of visited directories. @dhist prints + it out with numbers. + +2001-12-07 Fernando Perez <fperez@colorado.edu> + + * Released 0.1.22 + + * Made initialization a bit more robust against invalid color + options in user input (exit, not traceback-crash). + + * Changed the bug crash reporter to write the report only in the + user's .ipython directory. That way IPython won't litter people's + hard disks with crash files all over the place. Also print on + screen the necessary mail command. + + * With the new ultraTB, implemented LightBG color scheme for light + background terminals. A lot of people like white backgrounds, so I + guess we should at least give them something readable. + +2001-12-06 Fernando Perez <fperez@colorado.edu> + + * Modified the structure of ultraTB. Now there's a proper class + for tables of color schemes which allow adding schemes easily and + switching the active scheme without creating a new instance every + time (which was ridiculous). The syntax for creating new schemes + is also cleaner. I think ultraTB is finally done, with a clean + class structure. Names are also much cleaner (now there's proper + color tables, no need for every variable to also have 'color' in + its name). + + * Broke down genutils into separate files. Now genutils only + contains utility functions, and classes have been moved to their + own files (they had enough independent functionality to warrant + it): ConfigLoader, OutputTrap, Struct. + +2001-12-05 Fernando Perez <fperez@colorado.edu> + + * IPython turns 21! Released version 0.1.21, as a candidate for + public consumption. If all goes well, release in a few days. + + * Fixed path bug (files in Extensions/ directory wouldn't be found + unless IPython/ was explicitly in sys.path). + + * Extended the FlexCompleter class as MagicCompleter to allow + completion of @-starting lines. + + * Created __release__.py file as a central repository for release + info that other files can read from. + + * Fixed small bug in logging: when logging was turned on in + mid-session, old lines with special meanings (!@?) were being + logged without the prepended comment, which is necessary since + they are not truly valid python syntax. This should make session + restores produce less errors. + + * The namespace cleanup forced me to make a FlexCompleter class + which is nothing but a ripoff of rlcompleter, but with selectable + namespace (rlcompleter only works in __main__.__dict__). I'll try + to submit a note to the authors to see if this change can be + incorporated in future rlcompleter releases (Dec.6: done) + + * More fixes to namespace handling. It was a mess! Now all + explicit references to __main__.__dict__ are gone (except when + really needed) and everything is handled through the namespace + dicts in the IPython instance. We seem to be getting somewhere + with this, finally... + + * Small documentation updates. + + * Created the Extensions directory under IPython (with an + __init__.py). Put the PhysicalQ stuff there. This directory should + be used for all special-purpose extensions. + + * File renaming: + ipythonlib --> ipmaker + ipplib --> iplib + This makes a bit more sense in terms of what these files actually do. + + * Moved all the classes and functions in ipythonlib to ipplib, so + now ipythonlib only has make_IPython(). This will ease up its + splitting in smaller functional chunks later. + + * Cleaned up (done, I think) output of @whos. Better column + formatting, and now shows str(var) for as much as it can, which is + typically what one gets with a 'print var'. + +2001-12-04 Fernando Perez <fperez@colorado.edu> + + * Fixed namespace problems. Now builtin/IPyhton/user names get + properly reported in their namespace. Internal namespace handling + is finally getting decent (not perfect yet, but much better than + the ad-hoc mess we had). + + * Removed -exit option. If people just want to run a python + script, that's what the normal interpreter is for. Less + unnecessary options, less chances for bugs. + + * Added a crash handler which generates a complete post-mortem if + IPython crashes. This will help a lot in tracking bugs down the + road. + + * Fixed nasty bug in auto-evaluation part of prefilter(). Names + which were boud to functions being reassigned would bypass the + logger, breaking the sync of _il with the prompt counter. This + would then crash IPython later when a new line was logged. + +2001-12-02 Fernando Perez <fperez@colorado.edu> + + * Made IPython a package. This means people don't have to clutter + their sys.path with yet another directory. Changed the INSTALL + file accordingly. + + * Cleaned up the output of @who_ls, @who and @whos. @who_ls now + sorts its output (so @who shows it sorted) and @whos formats the + table according to the width of the first column. Nicer, easier to + read. Todo: write a generic table_format() which takes a list of + lists and prints it nicely formatted, with optional row/column + separators and proper padding and justification. + + * Released 0.1.20 + + * Fixed bug in @log which would reverse the inputcache list (a + copy operation was missing). + + * Code cleanup. @config was changed to use page(). Better, since + its output is always quite long. + + * Itpl is back as a dependency. I was having too many problems + getting the parametric aliases to work reliably, and it's just + easier to code weird string operations with it than playing %()s + games. It's only ~6k, so I don't think it's too big a deal. + + * Found (and fixed) a very nasty bug with history. !lines weren't + getting cached, and the out of sync caches would crash + IPython. Fixed it by reorganizing the prefilter/handlers/logger + division of labor a bit better. Bug fixed, cleaner structure. + +2001-12-01 Fernando Perez <fperez@colorado.edu> + + * Released 0.1.19 + + * Added option -n to @hist to prevent line number printing. Much + easier to copy/paste code this way. + + * Created global _il to hold the input list. Allows easy + re-execution of blocks of code by slicing it (inspired by Janko's + comment on 'macros'). + + * Small fixes and doc updates. + + * Rewrote @history function (was @h). Renamed it to @hist, @h is + much too fragile with automagic. Handles properly multi-line + statements and takes parameters. + +2001-11-30 Fernando Perez <fperez@colorado.edu> + + * Version 0.1.18 released. + + * Fixed nasty namespace bug in initial module imports. + + * Added copyright/license notes to all code files (except + DPyGetOpt). For the time being, LGPL. That could change. + + * Rewrote a much nicer README, updated INSTALL, cleaned up + ipythonrc-* samples. + + * Overall code/documentation cleanup. Basically ready for + release. Only remaining thing: licence decision (LGPL?). + + * Converted load_config to a class, ConfigLoader. Now recursion + control is better organized. Doesn't include the same file twice. + +2001-11-29 Fernando Perez <fperez@colorado.edu> + + * Got input history working. Changed output history variables from + _p to _o so that _i is for input and _o for output. Just cleaner + convention. + + * Implemented parametric aliases. This pretty much allows the + alias system to offer full-blown shell convenience, I think. + + * Version 0.1.17 released, 0.1.18 opened. + + * dot_ipython/ipythonrc (alias): added documentation. + (xcolor): Fixed small bug (xcolors -> xcolor) + + * Changed the alias system. Now alias is a magic command to define + aliases just like the shell. Rationale: the builtin magics should + be there for things deeply connected to IPython's + architecture. And this is a much lighter system for what I think + is the really important feature: allowing users to define quickly + magics that will do shell things for them, so they can customize + IPython easily to match their work habits. If someone is really + desperate to have another name for a builtin alias, they can + always use __IP.magic_newname = __IP.magic_oldname. Hackish but + works. + +2001-11-28 Fernando Perez <fperez@colorado.edu> + + * Changed @file so that it opens the source file at the proper + line. Since it uses less, if your EDITOR environment is + configured, typing v will immediately open your editor of choice + right at the line where the object is defined. Not as quick as + having a direct @edit command, but for all intents and purposes it + works. And I don't have to worry about writing @edit to deal with + all the editors, less does that. + + * Version 0.1.16 released, 0.1.17 opened. + + * Fixed some nasty bugs in the page/page_dumb combo that could + crash IPython. + +2001-11-27 Fernando Perez <fperez@colorado.edu> + + * Version 0.1.15 released, 0.1.16 opened. + + * Finally got ? and ?? to work for undefined things: now it's + possible to type {}.get? and get information about the get method + of dicts, or os.path? even if only os is defined (so technically + os.path isn't). Works at any level. For example, after import os, + os?, os.path?, os.path.abspath? all work. This is great, took some + work in _ofind. + + * Fixed more bugs with logging. The sanest way to do it was to add + to @log a 'mode' parameter. Killed two in one shot (this mode + option was a request of Janko's). I think it's finally clean + (famous last words). + + * Added a page_dumb() pager which does a decent job of paging on + screen, if better things (like less) aren't available. One less + unix dependency (someday maybe somebody will port this to + windows). + + * Fixed problem in magic_log: would lock of logging out if log + creation failed (because it would still think it had succeeded). + + * Improved the page() function using curses to auto-detect screen + size. Now it can make a much better decision on whether to print + or page a string. Option screen_length was modified: a value 0 + means auto-detect, and that's the default now. + + * Version 0.1.14 released, 0.1.15 opened. I think this is ready to + go out. I'll test it for a few days, then talk to Janko about + licences and announce it. + + * Fixed the length of the auto-generated ---> prompt which appears + for auto-parens and auto-quotes. Getting this right isn't trivial, + with all the color escapes, different prompt types and optional + separators. But it seems to be working in all the combinations. + +2001-11-26 Fernando Perez <fperez@colorado.edu> + + * Wrote a regexp filter to get option types from the option names + string. This eliminates the need to manually keep two duplicate + lists. + + * Removed the unneeded check_option_names. Now options are handled + in a much saner manner and it's easy to visually check that things + are ok. + + * Updated version numbers on all files I modified to carry a + notice so Janko and Nathan have clear version markers. + + * Updated docstring for ultraTB with my changes. I should send + this to Nathan. + + * Lots of small fixes. Ran everything through pychecker again. + + * Made loading of deep_reload an cmd line option. If it's not too + kosher, now people can just disable it. With -nodeep_reload it's + still available as dreload(), it just won't overwrite reload(). + + * Moved many options to the no| form (-opt and -noopt + accepted). Cleaner. + + * Changed magic_log so that if called with no parameters, it uses + 'rotate' mode. That way auto-generated logs aren't automatically + over-written. For normal logs, now a backup is made if it exists + (only 1 level of backups). A new 'backup' mode was added to the + Logger class to support this. This was a request by Janko. + + * Added @logoff/@logon to stop/restart an active log. + + * Fixed a lot of bugs in log saving/replay. It was pretty + broken. Now special lines (!@,/) appear properly in the command + history after a log replay. + + * Tried and failed to implement full session saving via pickle. My + idea was to pickle __main__.__dict__, but modules can't be + pickled. This would be a better alternative to replaying logs, but + seems quite tricky to get to work. Changed -session to be called + -logplay, which more accurately reflects what it does. And if we + ever get real session saving working, -session is now available. + + * Implemented color schemes for prompts also. As for tracebacks, + currently only NoColor and Linux are supported. But now the + infrastructure is in place, based on a generic ColorScheme + class. So writing and activating new schemes both for the prompts + and the tracebacks should be straightforward. + + * Version 0.1.13 released, 0.1.14 opened. + + * Changed handling of options for output cache. Now counter is + hardwired starting at 1 and one specifies the maximum number of + entries *in the outcache* (not the max prompt counter). This is + much better, since many statements won't increase the cache + count. It also eliminated some confusing options, now there's only + one: cache_size. + + * Added 'alias' magic function and magic_alias option in the + ipythonrc file. Now the user can easily define whatever names he + wants for the magic functions without having to play weird + namespace games. This gives IPython a real shell-like feel. + + * Fixed doc/?/?? for magics. Now all work, in all forms (explicit + @ or not). + + This was one of the last remaining 'visible' bugs (that I know + of). I think if I can clean up the session loading so it works + 100% I'll release a 0.2.0 version on c.p.l (talk to Janko first + about licensing). + +2001-11-25 Fernando Perez <fperez@colorado.edu> + + * Rewrote somewhat oinfo (?/??). Nicer, now uses page() and + there's a cleaner distinction between what ? and ?? show. + + * Added screen_length option. Now the user can define his own + screen size for page() operations. + + * Implemented magic shell-like functions with automatic code + generation. Now adding another function is just a matter of adding + an entry to a dict, and the function is dynamically generated at + run-time. Python has some really cool features! + + * Renamed many options to cleanup conventions a little. Now all + are lowercase, and only underscores where needed. Also in the code + option name tables are clearer. + + * Changed prompts a little. Now input is 'In [n]:' instead of + 'In[n]:='. This allows it the numbers to be aligned with the + Out[n] numbers, and removes usage of ':=' which doesn't exist in + Python (it was a Mathematica thing). The '...' continuation prompt + was also changed a little to align better. + + * Fixed bug when flushing output cache. Not all _p<n> variables + exist, so their deletion needs to be wrapped in a try: + + * Figured out how to properly use inspect.formatargspec() (it + requires the args preceded by *). So I removed all the code from + _get_pdef in Magic, which was just replicating that. + + * Added test to prefilter to allow redefining magic function names + as variables. This is ok, since the @ form is always available, + but whe should allow the user to define a variable called 'ls' if + he needs it. + + * Moved the ToDo information from README into a separate ToDo. + + * General code cleanup and small bugfixes. I think it's close to a + state where it can be released, obviously with a big 'beta' + warning on it. + + * Got the magic function split to work. Now all magics are defined + in a separate class. It just organizes things a bit, and now + Xemacs behaves nicer (it was choking on InteractiveShell b/c it + was too long). + + * Changed @clear to @reset to avoid potential confusions with + the shell command clear. Also renamed @cl to @clear, which does + exactly what people expect it to from their shell experience. + + Added a check to the @reset command (since it's so + destructive, it's probably a good idea to ask for confirmation). + But now reset only works for full namespace resetting. Since the + del keyword is already there for deleting a few specific + variables, I don't see the point of having a redundant magic + function for the same task. + +2001-11-24 Fernando Perez <fperez@colorado.edu> + + * Updated the builtin docs (esp. the ? ones). + + * Ran all the code through pychecker. Not terribly impressed with + it: lots of spurious warnings and didn't really find anything of + substance (just a few modules being imported and not used). + + * Implemented the new ultraTB functionality into IPython. New + option: xcolors. This chooses color scheme. xmode now only selects + between Plain and Verbose. Better orthogonality. + + * Large rewrite of ultraTB. Much cleaner now, with a separation of + mode and color scheme for the exception handlers. Now it's + possible to have the verbose traceback with no coloring. + +2001-11-23 Fernando Perez <fperez@colorado.edu> + + * Version 0.1.12 released, 0.1.13 opened. + + * Removed option to set auto-quote and auto-paren escapes by + user. The chances of breaking valid syntax are just too high. If + someone *really* wants, they can always dig into the code. + + * Made prompt separators configurable. + +2001-11-22 Fernando Perez <fperez@colorado.edu> + + * Small bugfixes in many places. + + * Removed the MyCompleter class from ipplib. It seemed redundant + with the C-p,C-n history search functionality. Less code to + maintain. + + * Moved all the original ipython.py code into ipythonlib.py. Right + now it's just one big dump into a function called make_IPython, so + no real modularity has been gained. But at least it makes the + wrapper script tiny, and since ipythonlib is a module, it gets + compiled and startup is much faster. + + This is a reasobably 'deep' change, so we should test it for a + while without messing too much more with the code. + +2001-11-21 Fernando Perez <fperez@colorado.edu> + + * Version 0.1.11 released, 0.1.12 opened for further work. + + * Removed dependency on Itpl. It was only needed in one place. It + would be nice if this became part of python, though. It makes life + *a lot* easier in some cases. + + * Simplified the prefilter code a bit. Now all handlers are + expected to explicitly return a value (at least a blank string). + + * Heavy edits in ipplib. Removed the help system altogether. Now + obj?/?? is used for inspecting objects, a magic @doc prints + docstrings, and full-blown Python help is accessed via the 'help' + keyword. This cleans up a lot of code (less to maintain) and does + the job. Since 'help' is now a standard Python component, might as + well use it and remove duplicate functionality. + + Also removed the option to use ipplib as a standalone program. By + now it's too dependent on other parts of IPython to function alone. + + * Fixed bug in genutils.pager. It would crash if the pager was + exited immediately after opening (broken pipe). + + * Trimmed down the VerboseTB reporting a little. The header is + much shorter now and the repeated exception arguments at the end + have been removed. For interactive use the old header seemed a bit + excessive. + + * Fixed small bug in output of @whos for variables with multi-word + types (only first word was displayed). + +2001-11-17 Fernando Perez <fperez@colorado.edu> + + * Version 0.1.10 released, 0.1.11 opened for further work. + + * Modified dirs and friends. dirs now *returns* the stack (not + prints), so one can manipulate it as a variable. Convenient to + travel along many directories. + + * Fixed bug in magic_pdef: would only work with functions with + arguments with default values. + +2001-11-14 Fernando Perez <fperez@colorado.edu> + + * Added the PhysicsInput stuff to dot_ipython so it ships as an + example with IPython. Various other minor fixes and cleanups. + + * Version 0.1.9 released, 0.1.10 opened for further work. + + * Added sys.path to the list of directories searched in the + execfile= option. It used to be the current directory and the + user's IPYTHONDIR only. + +2001-11-13 Fernando Perez <fperez@colorado.edu> + + * Reinstated the raw_input/prefilter separation that Janko had + initially. This gives a more convenient setup for extending the + pre-processor from the outside: raw_input always gets a string, + and prefilter has to process it. We can then redefine prefilter + from the outside and implement extensions for special + purposes. + + Today I got one for inputting PhysicalQuantity objects + (from Scientific) without needing any function calls at + all. Extremely convenient, and it's all done as a user-level + extension (no IPython code was touched). Now instead of: + a = PhysicalQuantity(4.2,'m/s**2') + one can simply say + a = 4.2 m/s**2 + or even + a = 4.2 m/s^2 + + I use this, but it's also a proof of concept: IPython really is + fully user-extensible, even at the level of the parsing of the + command line. It's not trivial, but it's perfectly doable. + + * Added 'add_flip' method to inclusion conflict resolver. Fixes + the problem of modules being loaded in the inverse order in which + they were defined in + + * Version 0.1.8 released, 0.1.9 opened for further work. + + * Added magics pdef, source and file. They respectively show the + definition line ('prototype' in C), source code and full python + file for any callable object. The object inspector oinfo uses + these to show the same information. + + * Version 0.1.7 released, 0.1.8 opened for further work. + + * Separated all the magic functions into a class called Magic. The + InteractiveShell class was becoming too big for Xemacs to handle + (de-indenting a line would lock it up for 10 seconds while it + backtracked on the whole class!) + + FIXME: didn't work. It can be done, but right now namespaces are + all messed up. Do it later (reverted it for now, so at least + everything works as before). + + * Got the object introspection system (magic_oinfo) working! I + think this is pretty much ready for release to Janko, so he can + test it for a while and then announce it. Pretty much 100% of what + I wanted for the 'phase 1' release is ready. Happy, tired. + +2001-11-12 Fernando Perez <fperez@colorado.edu> + + * Version 0.1.6 released, 0.1.7 opened for further work. + + * Fixed bug in printing: it used to test for truth before + printing, so 0 wouldn't print. Now checks for None. + + * Fixed bug where auto-execs increase the prompt counter by 2 (b/c + they have to call len(str(sys.ps1)) ). But the fix is ugly, it + reaches by hand into the outputcache. Think of a better way to do + this later. + + * Various small fixes thanks to Nathan's comments. + + * Changed magic_pprint to magic_Pprint. This way it doesn't + collide with pprint() and the name is consistent with the command + line option. + + * Changed prompt counter behavior to be fully like + Mathematica's. That is, even input that doesn't return a result + raises the prompt counter. The old behavior was kind of confusing + (getting the same prompt number several times if the operation + didn't return a result). + + * Fixed Nathan's last name in a couple of places (Gray, not Graham). + + * Fixed -Classic mode (wasn't working anymore). + + * Added colored prompts using Nathan's new code. Colors are + currently hardwired, they can be user-configurable. For + developers, they can be chosen in file ipythonlib.py, at the + beginning of the CachedOutput class def. + +2001-11-11 Fernando Perez <fperez@colorado.edu> + + * Version 0.1.5 released, 0.1.6 opened for further work. + + * Changed magic_env to *return* the environment as a dict (not to + print it). This way it prints, but it can also be processed. + + * Added Verbose exception reporting to interactive + exceptions. Very nice, now even 1/0 at the prompt gives a verbose + traceback. Had to make some changes to the ultraTB file. This is + probably the last 'big' thing in my mental todo list. This ties + in with the next entry: + + * Changed -Xi and -Xf to a single -xmode option. Now all the user + has to specify is Plain, Color or Verbose for all exception + handling. + + * Removed ShellServices option. All this can really be done via + the magic system. It's easier to extend, cleaner and has automatic + namespace protection and documentation. + +2001-11-09 Fernando Perez <fperez@colorado.edu> + + * Fixed bug in output cache flushing (missing parameter to + __init__). Other small bugs fixed (found using pychecker). + + * Version 0.1.4 opened for bugfixing. + +2001-11-07 Fernando Perez <fperez@colorado.edu> + + * Version 0.1.3 released, mainly because of the raw_input bug. + + * Fixed NASTY bug in raw_input: input line wasn't properly parsed + and when testing for whether things were callable, a call could + actually be made to certain functions. They would get called again + once 'really' executed, with a resulting double call. A disaster + in many cases (list.reverse() would never work!). + + * Removed prefilter() function, moved its code to raw_input (which + after all was just a near-empty caller for prefilter). This saves + a function call on every prompt, and simplifies the class a tiny bit. + + * Fix _ip to __ip name in magic example file. + + * Changed 'tar -x -f' to 'tar xvf' in auto-installer. This should + work with non-gnu versions of tar. + +2001-11-06 Fernando Perez <fperez@colorado.edu> + + * Version 0.1.2. Just to keep track of the recent changes. + + * Fixed nasty bug in output prompt routine. It used to check 'if + arg != None...'. Problem is, this fails if arg implements a + special comparison (__cmp__) which disallows comparing to + None. Found it when trying to use the PhysicalQuantity module from + ScientificPython. + +2001-11-05 Fernando Perez <fperez@colorado.edu> + + * Also added dirs. Now the pushd/popd/dirs family functions + basically like the shell, with the added convenience of going home + when called with no args. + + * pushd/popd slightly modified to mimic shell behavior more + closely. + + * Added env,pushd,popd from ShellServices as magic functions. I + think the cleanest will be to port all desired functions from + ShellServices as magics and remove ShellServices altogether. This + will provide a single, clean way of adding functionality + (shell-type or otherwise) to IP. + +2001-11-04 Fernando Perez <fperez@colorado.edu> + + * Added .ipython/ directory to sys.path. This way users can keep + customizations there and access them via import. + +2001-11-03 Fernando Perez <fperez@colorado.edu> + + * Opened version 0.1.1 for new changes. + + * Changed version number to 0.1.0: first 'public' release, sent to + Nathan and Janko. + + * Lots of small fixes and tweaks. + + * Minor changes to whos format. Now strings are shown, snipped if + too long. + + * Changed ShellServices to work on __main__ so they show up in @who + + * Help also works with ? at the end of a line: + ?sin and sin? + both produce the same effect. This is nice, as often I use the + tab-complete to find the name of a method, but I used to then have + to go to the beginning of the line to put a ? if I wanted more + info. Now I can just add the ? and hit return. Convenient. + +2001-11-02 Fernando Perez <fperez@colorado.edu> + + * Python version check (>=2.1) added. + + * Added LazyPython documentation. At this point the docs are quite + a mess. A cleanup is in order. + + * Auto-installer created. For some bizarre reason, the zipfiles + module isn't working on my system. So I made a tar version + (hopefully the command line options in various systems won't kill + me). + + * Fixes to Struct in genutils. Now all dictionary-like methods are + protected (reasonably). + + * Added pager function to genutils and changed ? to print usage + note through it (it was too long). + + * Added the LazyPython functionality. Works great! I changed the + auto-quote escape to ';', it's on home row and next to '. But + both auto-quote and auto-paren (still /) escapes are command-line + parameters. + + +2001-11-01 Fernando Perez <fperez@colorado.edu> + + * Version changed to 0.0.7. Fairly large change: configuration now + is all stored in a directory, by default .ipython. There, all + config files have normal looking names (not .names) + + * Version 0.0.6 Released first to Lucas and Archie as a test + run. Since it's the first 'semi-public' release, change version to + > 0.0.6 for any changes now. + + * Stuff I had put in the ipplib.py changelog: + + Changes to InteractiveShell: + + - Made the usage message a parameter. + + - Require the name of the shell variable to be given. It's a bit + of a hack, but allows the name 'shell' not to be hardwire in the + magic (@) handler, which is problematic b/c it requires + polluting the global namespace with 'shell'. This in turn is + fragile: if a user redefines a variable called shell, things + break. + + - magic @: all functions available through @ need to be defined + as magic_<name>, even though they can be called simply as + @<name>. This allows the special command @magic to gather + information automatically about all existing magic functions, + even if they are run-time user extensions, by parsing the shell + instance __dict__ looking for special magic_ names. + + - mainloop: added *two* local namespace parameters. This allows + the class to differentiate between parameters which were there + before and after command line initialization was processed. This + way, later @who can show things loaded at startup by the + user. This trick was necessary to make session saving/reloading + really work: ideally after saving/exiting/reloading a session, + *everythin* should look the same, including the output of @who. I + was only able to make this work with this double namespace + trick. + + - added a header to the logfile which allows (almost) full + session restoring. + + - prepend lines beginning with @ or !, with a and log + them. Why? !lines: may be useful to know what you did @lines: + they may affect session state. So when restoring a session, at + least inform the user of their presence. I couldn't quite get + them to properly re-execute, but at least the user is warned. + + * Started ChangeLog. diff --git a/doc/README.txt b/doc/README.txt new file mode 100644 index 0000000..6a6745a --- /dev/null +++ b/doc/README.txt @@ -0,0 +1,14 @@ +Current version information +--------------------------- + +Please open manual.pdf for a PDF version of IPython's user manual, or go to +the manual/ directory for an HTML version. + + +Bugs and future developments +---------------------------- + +The new_design.pdf document is a description of the goals for IPython's future +development. It includes a TODO/bugs section listing all currently known bugs +in IPython. Please report any bug you encounter if it is not already listed +there. diff --git a/doc/README_Windows.txt b/doc/README_Windows.txt new file mode 100644 index 0000000..0f90694 --- /dev/null +++ b/doc/README_Windows.txt @@ -0,0 +1,39 @@ +Notes for Windows Users +======================= + +These are just minimal notes. The manual contains more detailed +information. + +Requirements +------------ + +IPython runs under (as far as the Windows family is concerned): + +- Windows XP (I think WinNT/2000 are ok): works well. It needs: + + * Gary Bishop's readline from + http://sourceforge.net/projects/uncpythontools. + + * This in turn requires Tomas Heller's ctypes from + http://starship.python.net/crew/theller/ctypes. + +- Windows 95/98/ME: I have no idea. It should work, but I can't test. + +- CygWin environments should work, they are basically Posix. + +It needs Python 2.2 or newer. + + +Installation +------------ + +Double-click the supplied .exe installer file. If all goes well, that's all +you need to do. You should now have an IPython entry in your Start Menu. + +In case the automatic installer does not work for some reason, you can +download the ipython-XXX.tar.gz file, which contains the full IPython source +distribution (the popular WinZip can read .tar.gz files). After uncompressing +the archive, you can install it at a command terminal just like any other +Python module, by using python setup.py install'. After this completes, you +can run the supplied win32_manual_post_install.py script which will add +the relevant shortcuts to your startup menu. diff --git a/doc/examples/example-embed-short.py b/doc/examples/example-embed-short.py new file mode 100644 index 0000000..4b2e735 --- /dev/null +++ b/doc/examples/example-embed-short.py @@ -0,0 +1,51 @@ +"""Quick code snippets for embedding IPython into other programs. + +See example-embed.py for full details, this file has the bare minimum code for +cut and paste use once you understand how to use the system.""" + +#--------------------------------------------------------------------------- +# This code loads IPython but modifies a few things if it detects it's running +# embedded in another IPython session (helps avoid confusion) + +try: + __IPYTHON__ +except NameError: + argv = [''] + banner = exit_msg = '' +else: + # Command-line options for IPython (a list like sys.argv) + argv = ['-pi1','In <\\#>:','-pi2',' .\\D.:','-po','Out<\\#>:'] + banner = '*** Nested interpreter ***' + exit_msg = '*** Back in main IPython ***' + +# First import the embeddable shell class +from IPython.Shell import IPShellEmbed +# Now create the IPython shell instance. Put ipshell() anywhere in your code +# where you want it to open. +ipshell = IPShellEmbed(argv,banner=banner,exit_msg=exit_msg) + +#--------------------------------------------------------------------------- +# This code will load an embeddable IPython shell always with no changes for +# nested embededings. + +from IPython.Shell import IPShellEmbed +ipshell = IPShellEmbed() +# Now ipshell() will open IPython anywhere in the code. + +#--------------------------------------------------------------------------- +# This code loads an embeddable shell only if NOT running inside +# IPython. Inside IPython, the embeddable shell variable ipshell is just a +# dummy function. + +try: + __IPYTHON__ +except NameError: + from IPython.Shell import IPShellEmbed + ipshell = IPShellEmbed() + # Now ipshell() will open IPython anywhere in the code +else: + # Define a dummy ipshell() so the same code doesn't crash inside an + # interactive IPython + def ipshell(): pass + +#******************* End of file <example-embed-short.py> ******************** diff --git a/doc/examples/example-embed.py b/doc/examples/example-embed.py new file mode 100755 index 0000000..88d67f5 --- /dev/null +++ b/doc/examples/example-embed.py @@ -0,0 +1,127 @@ +#!/usr/bin/env python + +"""An example of how to embed an IPython shell into a running program. + +Please see the documentation in the IPython.Shell module for more details. + +The accompanying file example-embed-short.py has quick code fragments for +embedding which you can cut and paste in your code once you understand how +things work. + +The code in this file is deliberately extra-verbose, meant for learning.""" + +# The basics to get you going: + +# IPython sets the __IPYTHON__ variable so you can know if you have nested +# copies running. + +# Try running this code both at the command line and from inside IPython (with +# %run example-embed.py) +try: + __IPYTHON__ +except NameError: + nested = 0 + args = [''] +else: + print "Running nested copies of IPython." + print "The prompts for the nested copy have been modified" + nested = 1 + # what the embedded instance will see as sys.argv: + args = ['-pi1','In <\\#>:','-pi2',' .\\D.:','-po','Out<\\#>:','-nosep'] + +# First import the embeddable shell class +from IPython.Shell import IPShellEmbed + +# Now create an instance of the embeddable shell. The first argument is a +# string with options exactly as you would type them if you were starting +# IPython at the system command line. Any parameters you want to define for +# configuration can thus be specified here. +ipshell = IPShellEmbed(args, + banner = 'Dropping into IPython', + exit_msg = 'Leaving Interpreter, back to program.') + +# Make a second instance, you can have as many as you want. +if nested: + args[1] = 'In2<\\#>' +else: + args = ['-pi1','In2<\\#>:','-pi2',' .\\D.:','-po','Out<\\#>:','-nosep'] +ipshell2 = IPShellEmbed(args,banner = 'Second IPython instance.') + +print '\nHello. This is printed from the main controller program.\n' + +# You can then call ipshell() anywhere you need it (with an optional +# message): +ipshell('***Called from top level. ' + 'Hit Ctrl-D to exit interpreter and continue program.') + +print '\nBack in caller program, moving along...\n' + +#--------------------------------------------------------------------------- +# More details: + +# IPShellEmbed instances don't print the standard system banner and +# messages. The IPython banner (which actually may contain initialization +# messages) is available as <instance>.IP.BANNER in case you want it. + +# IPShellEmbed instances print the following information everytime they +# start: + +# - A global startup banner. + +# - A call-specific header string, which you can use to indicate where in the +# execution flow the shell is starting. + +# They also print an exit message every time they exit. + +# Both the startup banner and the exit message default to None, and can be set +# either at the instance constructor or at any other time with the +# set_banner() and set_exit_msg() methods. + +# The shell instance can be also put in 'dummy' mode globally or on a per-call +# basis. This gives you fine control for debugging without having to change +# code all over the place. + +# The code below illustrates all this. + + +# This is how the global banner and exit_msg can be reset at any point +ipshell.set_banner('Entering interpreter - New Banner') +ipshell.set_exit_msg('Leaving interpreter - New exit_msg') + +def foo(m): + s = 'spam' + ipshell('***In foo(). Try @whos, or print s or m:') + print 'foo says m = ',m + +def bar(n): + s = 'eggs' + ipshell('***In bar(). Try @whos, or print s or n:') + print 'bar says n = ',n + +# Some calls to the above functions which will trigger IPython: +print 'Main program calling foo("eggs")\n' +foo('eggs') + +# The shell can be put in 'dummy' mode where calls to it silently return. This +# allows you, for example, to globally turn off debugging for a program with a +# single call. +ipshell.set_dummy_mode(1) +print '\nTrying to call IPython which is now "dummy":' +ipshell() +print 'Nothing happened...' +# The global 'dummy' mode can still be overridden for a single call +print '\nOverriding dummy mode manually:' +ipshell(dummy=0) + +# Reactivate the IPython shell +ipshell.set_dummy_mode(0) + +print 'You can even have multiple embedded instances:' +ipshell2() + +print '\nMain program calling bar("spam")\n' +bar('spam') + +print 'Main program finished. Bye!' + +#********************** End of file <example-embed.py> *********************** diff --git a/doc/examples/example-gnuplot.py b/doc/examples/example-gnuplot.py new file mode 100755 index 0000000..c585fd5 --- /dev/null +++ b/doc/examples/example-gnuplot.py @@ -0,0 +1,36 @@ +#!/usr/bin/env python +""" +Example code showing how to use Gnuplot and an embedded IPython shell. +""" + +from Numeric import * +from IPython.numutils import * +from IPython.Shell import IPShellEmbed + +# Arguments to start IPython shell with. Load numeric profile. +ipargs = ['-profile','numeric'] +ipshell = IPShellEmbed(ipargs) + +# Compute sin(x) over the 0..2pi range at 200 points +x = frange(0,2*pi,npts=200) +y = sin(x) + +# In the 'numeric' profile, IPython has an internal gnuplot instance: +g = ipshell.IP.gnuplot + +# Change some defaults +g('set style data lines') + +# Or also call a multi-line set of gnuplot commands on it: +g(""" +set xrange [0:pi] # Set the visible range to half the data only +set title 'Half sine' # Global gnuplot labels +set xlabel 'theta' +set ylabel 'sin(theta)' +""") + +# Now start an embedded ipython. +ipshell('Starting the embedded IPyhton.\n' + 'Try calling plot(x,y), or @gpc for direct access to Gnuplot"\n') + +#********************** End of file <example-gnuplot.py> ********************* diff --git a/doc/examples/example-magic.py b/doc/examples/example-magic.py new file mode 100644 index 0000000..449061b --- /dev/null +++ b/doc/examples/example-magic.py @@ -0,0 +1,36 @@ +"""Example of how to define a magic function for extending IPython. + +The name of the function *must* begin with magic_. IPython mangles it so +that magic_foo() becomes available as %foo. + +The argument list must be *exactly* (self,parameter_s=''). + +The single string parameter_s will have the user's input. It is the magic +function's responsability to parse this string. + +That is, if the user types +>>>%foo a b c + +The followinng internal call is generated: + self.magic_foo(parameter_s='a b c'). + +To have any functions defined here available as magic functions in your +IPython environment, import this file in your configuration file with an +execfile = this_file.py statement. See the details at the end of the sample +ipythonrc file. """ + +# fisrt define a function with the proper form: +def magic_foo(self,parameter_s=''): + """My very own magic!. (Use docstrings, IPython reads them).""" + print 'Magic function. Passed parameter is between < >: <'+parameter_s+'>' + print 'The self object is:',self + +# Add the new magic function to the class dict: +from IPython.iplib import InteractiveShell +InteractiveShell.magic_foo = magic_foo + +# And remove the global name to keep global namespace clean. Don't worry, the +# copy bound to IPython stays, we're just removing the global name. +del magic_foo + +#********************** End of file <example-magic.py> *********************** diff --git a/doc/examples/magic_grepl.py b/doc/examples/magic_grepl.py new file mode 100644 index 0000000..9e50113 --- /dev/null +++ b/doc/examples/magic_grepl.py @@ -0,0 +1,60 @@ +"""This function implements a simple grep-like function in pure python. + +You can enable it by copying it to your ~/.ipython directory and putting + +execfile = magic_grepl.py + +in your ipythonrc file. + +Code contributed by Gever Tulley <gever@helium.com>, minor changes applied. +""" + +import glob +import re +import os + +def magic_grepl(self, parameter_s=''): + """Search for a pattern in a list of files. + + It prints the names of the files containing the pattern. Similar to 'grep + -l' in Unix-like environments. + + Usage: @grepl pattern [files] + + - pattern: any regular expression pattern which re.compile() will accept. + - files: list of files to scan. It can contain standard unix wildcards. + """ + + # argument processing + params = parameter_s.split() + if len(params) > 1: + target = params[0] # first one is the target + file_patterns = params[1:] # all the rest are filenames or patterns + + # build the regular expression + expr = re.compile(target) + + for pattern in file_patterns: + flist = [f for f in glob.glob(pattern) if os.path.isfile(f)] + for filename in flist: + # open and read the whole file + f = open(filename,'r') + data = f.read() + f.close() + + # see if pattern occurs in the file + if expr.search(data): + print filename + else: + # no parameters given + print("Usage: @grepl pattern [files]"); + +# Add the new magic function to the class dict: +from IPython.iplib import InteractiveShell +InteractiveShell.magic_grepl = magic_grepl + +# And remove the global name to keep global namespace clean. Don't worry, the +# copy bound to IPython stays, we're just removing the global name. +del magic_grepl + +#********************** End of file <magic_grepl.py> *********************** diff --git a/doc/ipnb_google_soc.lyx b/doc/ipnb_google_soc.lyx new file mode 100644 index 0000000..f931c7c --- /dev/null +++ b/doc/ipnb_google_soc.lyx @@ -0,0 +1,645 @@ +#LyX 1.3 created this file. For more info see http://www.lyx.org/ +\lyxformat 221 +\textclass article +\begin_preamble +\usepackage{hyperref} + +\usepackage{color} +\definecolor{orange}{cmyk}{0,0.4,0.8,0.2} +\definecolor{brown}{cmyk}{0,0.75,0.75,0.35} + +% Use and configure listings package for nicely formatted code +\usepackage{listings} +\lstset{ + language=Python, + basicstyle=\small\ttfamily, + commentstyle=\ttfamily\color{blue}, + stringstyle=\ttfamily\color{brown}, + showstringspaces=false, + breaklines=true, + postbreak = \space\dots +} +\end_preamble +\language english +\inputencoding auto +\fontscheme palatino +\graphics default +\paperfontsize 11 +\spacing single +\papersize Default +\paperpackage a4 +\use_geometry 1 +\use_amsmath 0 +\use_natbib 0 +\use_numerical_citations 0 +\paperorientation portrait +\leftmargin 1in +\topmargin 0.9in +\rightmargin 1in +\bottommargin 0.9in +\secnumdepth 3 +\tocdepth 3 +\paragraph_separation skip +\defskip medskip +\quotes_language english +\quotes_times 2 +\papercolumns 1 +\papersides 1 +\paperpagestyle default + +\layout Title + +Interactive Notebooks for Python +\newline + +\size small +An IPython project for Google's Summer of Code 2005 +\layout Author + +Fernando P +\begin_inset ERT +status Collapsed + +\layout Standard + +\backslash +'{e} +\end_inset + +rez +\begin_inset Foot +collapsed true + +\layout Standard + + +\family typewriter +\size small +Fernando.Perez@colorado.edu +\end_inset + + +\layout Abstract + +This project aims to develop a file format and interactive support for documents + which can combine Python code with rich text and embedded graphics. + The initial requirements only aim at being able to edit such documents + with a normal programming editor, with final rendering to PDF or HTML being + done by calling an external program. + The editing component would have to be integrated with IPython. + +\layout Abstract + +This document was written by the IPython developer; it is made available + to students looking for projects of interest and for inclusion in their + application. +\layout Section + +Project overview +\layout Standard + +Python's interactive interpreter is one of the language's most appealing + features for certain types of usage, yet the basic shell which ships with + the language is very limited. + Over the last few years, IPython +\begin_inset Foot +collapsed true + +\layout Standard + + +\begin_inset LatexCommand \htmlurl{http://ipython.scipy.org} + +\end_inset + + +\end_inset + + has become the de facto standard interactive shell in the scientific computing + community, and it enjoys wide popularity with general audiences. + All the major Linux distributions (Fedora Core via Extras, SUSE, Debian) + and OS X (via fink) carry IPython, and Windows users report using it as + a viable system shell. +\layout Standard + +However, IPython is currently a command-line only application, based on + the readline library and hence with single-line editing capabilities. + While this kind of usage is sufficient for many contexts, there are usage + cases where integration in a graphical user interface (GUI) is desirable. + +\layout Standard + +In particular, we wish to have an interface where users can execute Python + code, input regular text (neither code nor comments) and keep inline graphics, + which we will call +\emph on +Python notebooks +\emph default +. + This kind of system is very popular in scientific computing; well known + implementations can be found in Mathematica +\begin_inset ERT +status Collapsed + +\layout Standard + +\backslash +texttrademark +\end_inset + +\SpecialChar ~ + +\begin_inset Foot +collapsed true + +\layout Standard + + +\begin_inset LatexCommand \htmlurl{http://www.wolfram.com/products/mathematica} + +\end_inset + + +\end_inset + + and Maple +\begin_inset ERT +status Collapsed + +\layout Standard + +\backslash +texttrademark +\end_inset + +\SpecialChar ~ + +\begin_inset Foot +collapsed true + +\layout Standard + + +\begin_inset LatexCommand \htmlurl{http://www.maplesoft.com} + +\end_inset + + +\end_inset + +, among others. + However, these are proprietary (and quite expensive) systems aimed at an + audience of mathematicians, scientists and engineers. +\layout Standard + +The full-blown implementation of a graphical shell supporting this kind + of work model is probably too ambitious for a summer project. + Simultaneous support for rich-text editing, embedded graphics and syntax-highli +ghted code is extremely complex, and likely to require far more effort than + can be mustered by an individual developer for a short-term project. +\layout Standard + +This project will thus aim to build the necessary base infrastructure to + be able to edit such documents from a plain text editor, and to render + them to suitable formats for printing or online distribution, such as HTML, + PDF or PostScript. + This model follows that for the production of LaTeX documents, which can + be edited with any text editor. +\layout Standard + +Such documents would be extremely useful for many audiences beyond scientists: + one can use them to produce additionally documented code, to explore a + problem with Python and maintain all relevant information in the same place, + as a way to distribute enhanced Python-based educational materials, etc. +\layout Standard + +Demand for such a system exists, as evidenced by repeated requests made + to me by IPython users over the last few years. + Unfortunately IPython is only a spare-time project for me, and I have not + had the time to devote to this, despite being convinced of its long term + value and wide appeal. +\layout Standard + +If this project is successful, the infrastructure laid out by it will be + immediately useful for Python users wishing to maintain `literate' programs + which include rich formatting. + In addition, this will open the door for the future development of graphical + shells which can render such documents in real time: this is exactly the + development model successfully followed by the LyX +\begin_inset Foot +collapsed true + +\layout Standard + + +\begin_inset LatexCommand \htmlurl{http://www.lyx.org} + +\end_inset + + +\end_inset + + document processing system. +\layout Section + +Implementation effort +\layout Subsection + +Specific goals +\layout Standard + +This is a brief outline of the main points of this project. + The next section provides details on all of them. + The student(s) working on the project would need to: +\layout Enumerate + +Make design decisions for the internal file structure to enable valid Python + notebooks. + +\layout Enumerate + +Implement the rendering library, capable of processing an input notebook + through reST or LaTeX and producing HTML or PDF output, as well as exporting + a `pure-code' Python file stripped of all markup calls. +\layout Enumerate + +Study existing programming editor widgets to find the most suitable one + for extending with an IPython connector for interactive execution of the + notebooks. +\layout Subsection + +Complexity level +\layout Standard + +This project is relatively complicated. + While I will gladly assist the student with design and implementation issues, + it will require a fair amount of thinking in terms of overall library architect +ure. + The actual implementation does not require any sophisticated concepts, + but rather a reasonably broad knowledge of a wide set of topics (markup, + interaction with external programs and libraries, namespace tricks to provide + runtime changes in the effect of the markup calls, etc.) +\layout Standard + +While raw novices are welcome to try, I suspect that it may be a bit too + much for them. + Students wanting to apply should keep in mind, if the money is an important + consideration, that Google only gives the $4500 reward upon +\emph on +successful completion +\emph default + of the project. + So don't bite more than you can chew. + Obviously if this doesn't matter, anyone is welcome to participate, since + the project can be a very interesting learning experience, and it will + provide a genuinely useful tool for many. +\layout Section + +Technical details +\layout Subsection + +The files +\layout Standard + +A basic requirement of this project will be that the Python notebooks shall + be valid Python source files, typically with a +\family typewriter +.py +\family default + extension. + A renderer program can be used to process the markup calls in them and + generate output. + If run at a regular command line, these files should execute like normal + Python files. + But when run via a special rendering script, the result should be a properly + formatted file. + Output formats could be PDF or HTML depending on user-supplied options. +\layout Standard + +A reST markup mode should be implemented, as reST is already widely used + in the Python community and is a very simple format to write. + The following is a sketch of what such files could look like using reST + markup: +\layout Standard + + +\begin_inset ERT +status Open + +\layout Standard + +\backslash +lstinputlisting{nbexample.py} +\end_inset + + +\layout Standard + +Additionally, a LaTeX markup mode should also be implemented. + Here's a mockup example of what code using the LaTeX mode could look like. +\layout Standard + + +\begin_inset ERT +status Open + +\layout Standard + +\backslash +lstinputlisting{nbexample_latex.py} +\end_inset + + +\layout Standard + +At this point, it must be noted that the code above is simply a sketch of + these ideas, not a finalized design. + An important part of this project will be to think about what the best + API and structure for this problem should be. +\layout Subsection + +From notebooks to PDF, HTML or Python +\layout Standard + +Once a clean API for markup has been specified, converters will be written + to take a python source file which uses notebook constructs, and generate + final output in printable formats, such as HTML or PDF. + For example, if +\family typewriter +nbfile.py +\family default + is a python notebook, then +\layout LyX-Code + +$ pynb --export=pdf nbfile.py +\layout Standard + +should produce +\family typewriter +nbfile.pdf +\family default +, while +\layout LyX-Code + +$ pynb --export=html nbfile.py +\layout Standard + +would produce an HTML version. + The actual rendering will be done by calling appropriate utilities, such + as the reST toolchain or LaTeX, depending on the markup used by the file. +\layout Standard + +Additionally, while the notebooks will be valid Python files, if executed + on their own, all the markup calls will still return their results, which + are not really needed when the file is being treated as pure code. + For this reason, a module to execute these files turning the markup calls + into no-ops should be written. + Using Python 2.4's -m switch, one can then use something like +\layout LyX-Code + +$ python -m notebook nbfile.py +\layout Standard + +and the notebook file +\family typewriter +nbfile.py +\family default + will be executed without any overhead introduced by the markup (other than + making calls to functions which return immediately). + Finally, an exporter to clean code can be trivially implemented, so that: +\layout LyX-Code + +$ pynb --export=python nbfile.py nbcode.py +\layout Standard + +would export only the code in +\family typewriter +nbfile.py +\family default + to +\family typewriter +nbcode.py +\family default +, removing the markup completely. + This can be used to generate final production versions of large modules + implemented as notebooks, if one wants to eliminate the markup overhead. +\layout Subsection + +The editing environment +\layout Standard + +The first and most important part of the project should be the definition + of a clean API and the implementation of the exporter modules as indicated + above. + Ultimately, such files can be developed using any text editor, since they + are nothing more than regular Python code. +\layout Standard + +But once these goals are reached, further integration with an editor will + be done, without the need for a full-blown GUI shell. + In fact, already today the (X)Emacs editors can provide for interactive + usage of such files. + Using python-mode in (X)Emacs, one can pass highlighted regions of a file + for execution to an underlying python process, and the results are printed + in the python window. + With recent versions of python-mode, IPython can be used instead of the + plain python interpreter, so that IPython's extended interactive capabilities + become available within (X)Emacs (improved tracebacks, automatic debugger + integration, variable information, easy filesystem access to Python, etc). +\layout Standard + +But even with IPython integration, the usage within (X)Emacs is not ideal + for a notebook environment, since the python process buffer is separate + from the python file. + Therefore, the next stage of the project will be to enable tighter integration + between the editing and execution environments. + The basic idea is to provide an easy way to mark regions of the file to + be executed interactively, and to have the output inserted automatically + into the file. + The following listing is a mockup of what the resulting file could look + like +\layout Standard + + +\begin_inset ERT +status Open + +\layout Standard + +\backslash +lstinputlisting{nbexample_output.py} +\end_inset + + +\layout Standard + +Basically, the editor will execute +\family typewriter +add(2,3) +\family default + and insert the string representation of the output into the file, so it + can be used for rendering later. + +\layout Section + +Available resources +\layout Standard + +IPython currently has all the necessary infrastructure for code execution, + albeit in a rather messy code base. + Most I/O is already abstracted out, a necessary condition for embedding + in a GUI (since you are not writing to stdout/err but to the GUI's text + area). + +\layout Standard + +For interaction with an editor, it will be necessary to identify a good + programming editor with a Python-compatible license, which can be extended + to communicate with the underlying IPython engine. + IDLE, the Tk-based IDE which ships with Python, should obviously be considered. + The Scintilla editing component +\begin_inset Foot +collapsed true + +\layout Standard + + +\begin_inset LatexCommand \htmlurl{http://www.scintilla.org} + +\end_inset + + +\end_inset + + may also be a viable candidate. + +\layout Standard + +It will also be interesting to look at the LyX editor +\begin_inset Foot +collapsed true + +\layout Standard + + +\begin_inset LatexCommand \htmlurl{http://www.lyx.org} + +\end_inset + + +\end_inset + +, which already offers a Python client +\begin_inset Foot +collapsed true + +\layout Standard + + +\begin_inset LatexCommand \htmlurl{http://wiki.lyx.org/Tools/PyClient} + +\end_inset + + +\end_inset + +. + Since LyX has very sophisticated LaTeX support, this is a very interesting + direction to consider for the future (though LyX makes a poor programming + editor). +\layout Section + +Support offered to the students +\layout Standard + +The IPython project already has an established Open Source infrastructure, + including CVS repositories, a bug tracker and mailing lists. + As the main author and sole maintainer of IPython, I will personally assist + the student(s) funded with architectural and design guidance, preferably + on the public development mailing list. + I expect them to start working by submitting patches until they show, by + the quality of their work, that they can be granted CVS write access. + I expect most actual implementation work to be done by the students, though + I will provide assistance if they need it with a specific technical issue. +\layout Standard + +If more than one applicant is accepted to work on this project, there is + more than enough work to be done which can be coordinated between them. +\layout Section + +Licensing and copyright +\layout Standard + +IPython is licensed under BSD terms, and copyright of all sources rests + with the original authors of the core modules. + Over the years, all external contributions have been small enough patches + that they have been simply folded into the main source tree without additional + copyright attributions, though explicit credit has always been given to + all contributors. +\layout Standard + +I expect the students participating in this project to contribute enough + standalone code that they can retain the copyright to it if they so desire, + as long as they accept all their work to be licensed under BSD terms. +\layout Section + +Acknowledgements +\layout Standard + +I'd like to thank John D. + Hunter, the author of matplotlib +\begin_inset Foot +collapsed true + +\layout Standard + + +\begin_inset LatexCommand \htmlurl{http://matplotlib.sf.net} + +\end_inset + + +\end_inset + +, for lengthy discussions which helped clarify much of this project. + In particular, the important decision of embedding the notebook markup + calls in true Python functions instead of specially-tagged strings or comments + was an idea I thank him for pushing hard enough to convince me of using. + +\layout Standard + +My conversations with Brian Granger, the author of PyXG +\begin_inset Foot +collapsed true + +\layout Standard + + +\begin_inset LatexCommand \htmlurl{http://hammonds.scu.edu/~classes/pyxg.html} + +\end_inset + + +\end_inset + + and braid +\begin_inset Foot +collapsed true + +\layout Standard + + +\begin_inset LatexCommand \htmlurl{http://hammonds.scu.edu/~classes/braid.html} + +\end_inset + + +\end_inset + +, have also been very useful in clarifying details of the necessary underlying + infrastructure and future evolution of IPython for this kind of system. +\layout Standard + +Thank you also to the IPython users who have, in the past, discussed this + topic with me either in private or on the IPython or Scipy lists. +\the_end diff --git a/doc/ipython.1 b/doc/ipython.1 new file mode 100644 index 0000000..ac873a3 --- /dev/null +++ b/doc/ipython.1 @@ -0,0 +1,392 @@ +.\" Hey, EMACS: -*- nroff -*- +.\" First parameter, NAME, should be all caps +.\" Second parameter, SECTION, should be 1-8, maybe w/ subsection +.\" other parameters are allowed: see man(7), man(1) +.TH IPYTHON 1 "November 30, 2004" +.\" Please adjust this date whenever revising the manpage. +.\" +.\" Some roff macros, for reference: +.\" .nh disable hyphenation +.\" .hy enable hyphenation +.\" .ad l left justify +.\" .ad b justify to both left and right margins +.\" .nf disable filling +.\" .fi enable filling +.\" .br insert line break +.\" .sp <n> insert n+1 empty lines +.\" for manpage-specific macros, see man(7) and groff_man(7) +.\" .SH section heading +.\" .SS secondary section heading +.\" +.\" +.\" To preview this page as plain text: nroff -man ipython.1 +.\" +.SH NAME +ipython \- An Enhanced Interactive Python +.SH SYNOPSIS +.B ipython +.RI [ options ] " files" ... +.SH DESCRIPTION +An interactive Python shell with automatic history (input and output), +dynamic object introspection, easier configuration, command +completion, access to the system shell, integration with numerical and +scientific computing tools, and more. +.SH SPECIAL THREADING OPTIONS +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, \-wthread, \-pylab +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, QT and WXWidgets toolkits, and for the +matplotlib library. +.br +.sp 1 +With any of the first three 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 +three provide essentially the same functionality, respectively for GTK, QT and +WXWidgets (via their Python interfaces). +.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 +activates GTK, QT or WX threading for IPyhton if the choice of matplotlib +backend requires it. It also modifies the %run command to correctly execute +(without blocking) any matplotlib-based script which calls show() at the end. +.TP +.B \-tk +The \-g/q/wthread options, and \-pylab (if matplotlib is configured to use +GTK, QT or WX), will normally block Tk graphical interfaces. This means that +when 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, \-tk, is available to address this issue. It can ONLY be +given as a SECOND option after any of the above (\-gthread, \-qthread, +\-wthread or \-pylab). +.br +.sp 1 +If \-tk 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), 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. +.br +.sp 1 +There is unfortunately no way for IPython to determine at runtime whether \-tk +will work reliably or not, so you will need to do some experiments before +relying on it for regular work. +. +.SS A WARNING ABOUT SIGNALS AND THREADS +When any of the thread systems (GTK, QT or WX) are active, either directly or +via \-pylab with a threaded backend, it is impossible to interrupt +long-running Python code via Ctrl\-C. IPython can not pass the +KeyboardInterrupt exception (or the underlying SIGINT) across threads, so any +long-running process started from IPython will run to completion, or will have +to be killed via an external (OS-based) mechanism. +.br +.sp 1 +To the best of my knowledge, this limitation is imposed by the Python +interpreter itself, and it comes from the difficulty of writing portable +signal/threaded code. If any user is an expert on this topic and can suggest +a better solution, I would love to hear about it. In the IPython sources, +look at the Shell.py module, and in particular at the runcode() method. +. +.SH REGULAR OPTIONS +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 |. +.br +.sp 1 +Most options can also be set from your ipythonrc configuration file. +See the provided examples for assistance. Options given on the +commandline override the values set in the ipythonrc file. +.br +.sp 1 +All options with a no| prepended can be specified in 'no' form +(\-nooption instead of \-option) to turn the feature off. +.TP +.B \-h, \-\-help +Show summary of options. +.TP +.B \-no|autocall +Make IPython automatically call any callable object even if you didn't type +explicit parentheses. For example, 'str 43' becomes 'str(43)' automatically. +.TP +.B \-no|autoindent +Turn automatic indentation on/off. +.TP +.B \-no|automagic +Make magic commands automatic (without needing their first character +to be @). Type @magic at the IPython prompt for more information. +.TP +.B \-no|autoparens +Make IPython automatically call any callable object even if you didn't +type explicit parentheses. For example, 'str 43' becomes 'str(43)' +automatically. +.TP +.B \-no|banner +Print the intial information banner (default on). +.TP +.B \-c <command> +Execute the given command string, and set sys.argv to ['c']. This is similar +to the \-c option in the normal Python interpreter. +.TP +.B \-cache_size|cs <n> +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. +.TP +.B \-classic|cl +Gives IPython a similar feel to the classic Python prompt. +.TP +.B \-colors <scheme> +Color scheme for prompts and exception reporting. Currently +implemented: NoColor, Linux, and LightBG. +.TP +.B \-no|color_info +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. +.br +.sp 1 +Test it and turn it on permanently if it works with your system. The +magic function @color_info allows you to toggle this interactively for +testing. +.TP +.B \-no|confirm_exit +Set to confirm when you try to exit IPython with an EOF (Control-D in +Unix, Control-Z/Enter in Windows). Note that using the magic functions +@Exit or @Quit you can force a direct exit, bypassing any +confirmation. +.TP +.B \-no|debug +Show information about the loading process. Very useful to pin down +problems with your configuration files or to get details about session +restores. +.TP +.B \-no|deep_reload +IPython can use the deep_reload module which reloads changes in +modules recursively (it replaces the reload() function, so you don't +need to change anything to use it). deep_reload() forces a full reload +of modules whose code may have changed, which the default reload() +function does not. +.br +.sp 1 +When deep_reload is off, IPython will use the normal reload(), but +deep_reload will still be available as dreload(). This feature is off +by default [which means that you have both normal reload() and +dreload()]. +.TP +.B \-editor <name> +Which editor to use with the @edit command. By default, IPython will +honor your EDITOR 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 +EDITOR is something like Emacs). +.TP +.B \-ipythondir <name> +The name of your IPython configuration directory IPYTHONDIR. This can +also be specified through the environment variable IPYTHONDIR. +.TP +.B \-log|l +Generate a log file of all input. The file is named ipython.log 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 +-logplay (see below). +.TP +.B \-logfile|lf +Specifu the name of your logfile. +.TP +.B \-logplay|lp +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 \-logplay, IPython will try to reconstruct the previous +working environment in full, not just execute the commands in the +logfile. +.br +.sh 1 +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. +.br +.sp 1 +Caveats: there are limitations in this option. The history variables +_i*,_* and _dh 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. +.TP +.B \-no|messages +Print messages which IPython collects about its startup process +(default on). +.TP +.B \-no|pdb +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. +.TP +.B \-no|pprint +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). +.TP +.B \-profile|p <name> +Assume that your config file is ipythonrc-<name> (looks in current dir +first, then in IPYTHONDIR). 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 +IPYTHONDIR/ipythonrc file and then have other 'profiles' which include +this one and load extra things for particular tasks. For example: +.br +.sp 1 +1) $HOME/.ipython/ipythonrc : load basic things you always want. +.br +2) $HOME/.ipython/ipythonrc-math : load (1) and basic math-related +modules. +.br +3) $HOME/.ipython/ipythonrc-numeric : load (1) and Numeric and +plotting modules. +.br +.sp 1 +Since it is possible to create an endless loop by having circular file +inclusions, IPython will stop if it reaches 15 recursive inclusions. +.TP +.B \-prompt_in1|pi1 <string> +Specify the string used for input prompts. Note that if you are using +numbered prompts, the number is represented with a '\\#' in the +string. Don't forget to quote strings with spaces embedded in +them. Default: 'In [\\#]:'. +.br +.sp 1 +Most bash-like escapes can be used to customize IPython's prompts, as well as +a few additional ones which are IPython-specific. All valid prompt escapes +are described in detail in the Customization section of the IPython HTML/PDF +manual. +.TP +.B \-prompt_in2|pi2 <string> +Similar to the previous option, but used for the continuation prompts. The +special sequence '\\D' is similar to '\\#', but with all digits replaced dots +(so you can have your continuation prompt aligned with your input +prompt). Default: ' .\\D.:' (note three spaces at the start for alignment +with 'In [\\#]'). +.TP +.B \-prompt_out|po <string> +String used for output prompts, also uses numbers like prompt_in1. +Default: 'Out[\\#]:'. +.TP +.B \-quick +Start in bare bones mode (no config file loaded). +.TP +.B \-rcfile <name> +Name of your IPython resource configuration file. normally IPython +loads ipythonrc (from current directory) or IPYTHONDIR/ipythonrc. If +the loading of your config file fails, IPython starts with a bare +bones configuration (no modules loaded at all). +.TP +.B \-no|readline +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. +.br +.sp 1 +Note that emacs 'eterm' buffers (opened with M-x term) support +IPython's readline and syntax coloring fine, only 'emacs' (M-x shell +and C-c !) buffers do not. +.TP +.B \-screen_length|sl <n> +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. +.br +.sp 1 +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. +.TP +.B \-separate_in|si <string> +Separator before input prompts. Default '\n'. +.TP +.B \-separate_out|so <string> +Separator before output prompts. Default: 0 (nothing). +.TP +.B \-separate_out2|so2 <string> +Separator after output prompts. Default: 0 (nothing). +.TP +.B \-nosep +Shorthand for '\-separate_in 0 \-separate_out 0 \-separate_out2 0'. +Simply removes all input/output separators. +.TP +.B \-upgrade +Allows you to upgrade your IPYTHONDIR configuration when you install a +new version of IPython. Since new versions may include new command +lines options or example files, this copies updated ipythonrc-type +files. However, it backs up (with a .old extension) all files which +it overwrites so that you can merge back any custimizations you might +have in your personal files. +.TP +.B \-Version +Print version information and exit. +.TP +.B \-xmode <modename> +Mode for exception reporting. The valid modes are Plain, Context, and +Verbose. +.br +.sp 1 +\- Plain: similar to python's normal traceback printing. +.br +.sp 1 +\- Context: prints 5 lines of context source code around each line in the +traceback. +.br +.sp 1 +\- 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). +. +.SH EMBEDDING +It is possible to start an IPython instance inside your own Python +programs. In the documentation example files there are some +illustrations on how to do this. +.br +.sp 1 +This feature allows you to evalutate dynamically the state of your +code, operate with your variables, analyze them, etc. Note however +that any changes you make to values while in the shell do NOT +propagate back to the running code, so it is safe to modify your +values because you won't break your code in bizarre ways by doing so. +.SH AUTHOR +IPython was written by Fernando Perez <fperez@colorado.edu>, based on earlier +code by Janko Hauser <jh@comunit.de> and Nathaniel Gray +<n8gray@caltech.edu>. This manual page was written by Jack Moffitt +<jack@xiph.org>, for the Debian project (but may be used by others). diff --git a/doc/ipython.el b/doc/ipython.el new file mode 100644 index 0000000..36e7b35 --- /dev/null +++ b/doc/ipython.el @@ -0,0 +1,398 @@ +;;; ipython.el --- Adds support for IPython to python-mode.el + +;; Copyright (C) 2002, 2003, 2004, 2005 Alexander Schmolck +;; Author: Alexander Schmolck +;; Keywords: ipython python languages oop +;; URL: http://ipython.scipy.org +;; Compatibility: Emacs21, XEmacs21 +;; FIXME: #$@! INPUT RING +(defconst ipython-version "$Revision: 565 $" + "VC version number.") + +;;; Commentary +;; This library makes all the functionality python-mode has when running with +;; the normal python-interpreter available for ipython, too. It also enables a +;; persistent py-shell command history accross sessions (if you exit python +;; with C-d in py-shell) and defines the command `ipython-to-doctest', which +;; can be used to convert bits of a ipython session into something that can be +;; used for doctests. To install, put this file somewhere in your emacs +;; `load-path' [1] and add the following line to your ~/.emacs file (the first +;; line only needed if the default (``"ipython"``) is wrong):: +;; +;; (setq ipython-command "/SOME-PATH/ipython") +;; (require 'ipython) +;; +;; Ipython will be set as the default python shell, but only if the ipython +;; executable is in the path. For ipython sessions autocompletion with <tab> +;; is also enabled (experimental feature!). Please also note that all the +;; terminal functions in py-shell are handled by emacs's comint, **not** by +;; (i)python, so importing readline etc. will have 0 effect. +;; +;; To start an interactive ipython session run `py-shell' with ``M-x py-shell`` +;; (or the default keybinding ``C-c C-!``). +;; +;; NOTE: This mode is currently somewhat alpha and although I hope that it +;; will work fine for most cases, doing certain things (like the +;; autocompletion and a decent scheme to switch between python interpreters) +;; properly will also require changes to ipython that will likely have to wait +;; for a larger rewrite scheduled some time in the future. +;; +;; Also note that you currently NEED THE CVS VERSION OF PYTHON.EL. +;; +;; Further note that I don't know whether this runs under windows or not and +;; that if it doesn't I can't really help much, not being afflicted myself. +;; +;; +;; Hints for effective usage +;; ------------------------- +;; +;; - IMO the best feature by far of the ipython/emacs combo is how much easier it +;; makes it to find and fix bugs thanks to the ``@pdb on``/ pdbtrack combo. Try +;; it: first in the ipython to shell do ``@pdb on`` then do something that will +;; raise an exception (FIXME nice example) -- and be amazed how easy it is to +;; inspect the live objects in each stack frames and to jump to the +;; corresponding sourcecode locations as you walk up and down the stack trace +;; (even without ``%pdb on`` you can always use ``C-c -`` (`py-up-exception') +;; to jump to the corresponding source code locations). +;; +;; - emacs gives you much more powerful commandline editing and output searching +;; capabilities than ipython-standalone -- isearch is your friend if you +;; quickly want to print 'DEBUG ...' to stdout out etc. +;; +;; - This is not really specific to ipython, but for more convenient history +;; access you might want to add something like the following to *the beggining* +;; of your ``.emacs`` (if you want behavior that's more similar to stand-alone +;; ipython, you can change ``meta p`` etc. for ``control p``):: +;; +;; (require 'comint) +;; (define-key comint-mode-map [(meta p)] +;; 'comint-previous-matching-input-from-input) +;; (define-key comint-mode-map [(meta n)] +;; 'comint-next-matching-input-from-input) +;; (define-key comint-mode-map [(control meta n)] +;; 'comint-next-input) +;; (define-key comint-mode-map [(control meta p)] +;; 'comint-previous-input) +;; +;; - Be aware that if you customize py-python-command previously, this value +;; will override what ipython.el does (because loading the customization +;; variables comes later). +;; +;; Please send comments and feedback to the ipython-list +;; (<ipython-user@scipy.net>) where I (a.s.) or someone else will try to +;; answer them (it helps if you specify your emacs version, OS etc; +;; familiarity with <http://www.catb.org/~esr/faqs/smart-questions.html> might +;; speed up things further). +;; +;; Footnotes: +;; +;; [1] If you don't know what `load-path' is, C-h v load-path will tell +;; you; if required you can also add a new directory. So assuming that +;; ipython.el resides in ~/el/, put this in your emacs: +;; +;; +;; (add-to-list 'load-path "~/el") +;; (setq ipython-command "/some-path/ipython") +;; (require 'ipython) +;; +;; +;; +;; +;; TODO: +;; - do autocompletion properly +;; - implement a proper switching between python interpreters +;; +;; BUGS: +;; - neither:: +;; +;; (py-shell "-c print 'FOOBAR'") +;; +;; nor:: +;; +;; (let ((py-python-command-args (append py-python-command-args +;; '("-c" "print 'FOOBAR'")))) +;; (py-shell)) +;; +;; seem to print anything as they should +;; +;; - look into init priority issues with `py-python-command' (if it's set +;; via custom) + + +;;; Code +(require 'cl) +(require 'shell) +(require 'executable) +(require 'ansi-color) + +(defcustom ipython-command "ipython" + "*Shell command used to start ipython." + :type 'string + :group 'python) + +;; Users can set this to nil +(defvar py-shell-initial-switch-buffers t + "If nil, don't switch to the *Python* buffer on the first call to + `py-shell'.") + +(defvar ipython-backup-of-py-python-command nil + "HACK") + + +(defvar ipython-de-input-prompt-regexp "\\(?: +In \\[[0-9]+\\]: *.* +----+> \\(.* +\\)[\n]?\\)\\|\\(?: +In \\[[0-9]+\\]: *\\(.* +\\)\\)\\|^[ ]\\{3\\}[.]\\{3,\\}: *\\(.* +\\)" + "A regular expression to match the IPython input prompt and the python +command after it. The first match group is for a command that is rewritten, +the second for a 'normal' command, and the third for a multiline command.") +(defvar ipython-de-output-prompt-regexp "^Out\\[[0-9]+\\]: " + "A regular expression to match the output prompt of IPython.") + + +(if (not (executable-find ipython-command)) + (message (format "Can't find executable %s - ipython.el *NOT* activated!!!" + ipython-command)) + ;; XXX load python-mode, so that we can screw around with its variables + ;; this has the disadvantage that python-mode is loaded even if no + ;; python-file is ever edited etc. but it means that `py-shell' works + ;; without loading a python-file first. Obviously screwing around with + ;; python-mode's variables like this is a mess, but well. + (require 'python-mode) + ;; turn on ansi colors for ipython and activate completion + (defun ipython-shell-hook () + ;; the following is to synchronize dir-changes + (make-local-variable 'shell-dirstack) + (setq shell-dirstack nil) + (make-local-variable 'shell-last-dir) + (setq shell-last-dir nil) + (make-local-variable 'shell-dirtrackp) + (setq shell-dirtrackp t) + (add-hook 'comint-input-filter-functions 'shell-directory-tracker nil t) + + (ansi-color-for-comint-mode-on) + (define-key py-shell-map [tab] 'ipython-complete) + ;;XXX this is really just a cheap hack, it only completes symbols in the + ;;interactive session -- useful nonetheless. + (define-key py-mode-map [(meta tab)] 'ipython-complete)) + (add-hook 'py-shell-hook 'ipython-shell-hook) + ;; Regular expression that describes tracebacks for IPython in context and + ;; verbose mode. + + ;;Adapt python-mode settings for ipython. + ;; (this works for %xmode 'verbose' or 'context') + + ;; XXX putative regexps for syntax errors; unfortunately the + ;; current python-mode traceback-line-re scheme is too primitive, + ;; so it's either matching syntax errors, *or* everything else + ;; (XXX: should ask Fernando for a change) + ;;"^ File \"\\(.*?\\)\", line \\([0-9]+\\).*\n.*\n.*\nSyntaxError:" + ;;^ File \"\\(.*?\\)\", line \\([0-9]+\\)" + (setq py-traceback-line-re + "\\(^[^\t ].+?\\.py\\).*\n +[0-9]+[^\00]*?\n-+> \\([0-9]+\\) +") + + (setq py-shell-input-prompt-1-regexp "^In \\[[0-9]+\\]: *" + py-shell-input-prompt-2-regexp "^ [.][.][.]+: *" ) + ;; select a suitable color-scheme + (unless (member "-colors" py-python-command-args) + (setq py-python-command-args + (nconc py-python-command-args + (list "-colors" + (cond + ((eq frame-background-mode 'dark) + "DarkBG") + ((eq frame-background-mode 'light) + "LightBG") + (t ; default (backg-mode isn't always set by XEmacs) + "LightBG")))))) + (unless (equal ipython-backup-of-py-python-command py-python-command) + (setq ipython-backup-of-py-python-command py-python-command)) + (setq py-python-command ipython-command)) + + +;; MODIFY py-shell so that it loads the editing history +(defadvice py-shell (around py-shell-with-history) + "Add persistent command-history support (in +$PYTHONHISTORY (or \"~/.ipython/history\", if we use IPython)). Also, if +`py-shell-initial-switch-buffers' is nil, it only switches to *Python* if that +buffer already exists." + (if (comint-check-proc "*Python*") + ad-do-it + (setq comint-input-ring-file-name + (if (string-equal py-python-command ipython-command) + (concat (or (getenv "IPYTHONDIR") "~/.ipython") "/history") + (or (getenv "PYTHONHISTORY") "~/.python-history.py"))) + (comint-read-input-ring t) + (let ((buf (current-buffer))) + ad-do-it + (unless py-shell-initial-switch-buffers + (switch-to-buffer-other-window buf))))) +(ad-activate 'py-shell) +;; (defadvice py-execute-region (before py-execute-buffer-ensure-process) +;; "HACK: test that ipython is already running before executing something. +;; Doing this properly seems not worth the bother (unless people actually +;; request it)." +;; (unless (comint-check-proc "*Python*") +;; (error "Sorry you have to first do M-x py-shell to send something to ipython."))) +;; (ad-activate 'py-execute-region) + +(defadvice py-execute-region (around py-execute-buffer-ensure-process) + "HACK: if `py-shell' is not active or ASYNC is explicitly desired, fall back + to python instead of ipython." + (let ((py-python-command (if (and (comint-check-proc "*Python*") (not async)) + py-python-command + ipython-backup-of-py-python-command))) + ad-do-it)) +(ad-activate 'py-execute-region) + +(defun ipython-to-doctest (start end) + "Transform a cut-and-pasted bit from an IPython session into something that +looks like it came from a normal interactive python session, so that it can +be used in doctests. Example: + + + In [1]: import sys + + In [2]: sys.stdout.write 'Hi!\n' + ------> sys.stdout.write ('Hi!\n') + Hi! + + In [3]: 3 + 4 + Out[3]: 7 + +gets converted to: + + >>> import sys + >>> sys.stdout.write ('Hi!\n') + Hi! + >>> 3 + 4 + 7 + +" + (interactive "*r\n") + ;(message (format "###DEBUG s:%de:%d" start end)) + (save-excursion + (save-match-data + ;; replace ``In [3]: bla`` with ``>>> bla`` and + ;; ``... : bla`` with ``... bla`` + (goto-char start) + (while (re-search-forward ipython-de-input-prompt-regexp end t) + ;(message "finding 1") + (cond ((match-string 3) ;continued + (replace-match "... \\3" t nil)) + (t + (replace-match ">>> \\1\\2" t nil)))) + ;; replace `` + (goto-char start) + (while (re-search-forward ipython-de-output-prompt-regexp end t) + (replace-match "" t nil))))) + +(defvar ipython-completion-command-string + "print ';'.join(__IP.Completer.all_completions('%s')) #PYTHON-MODE SILENT\n" + "The string send to ipython to query for all possible completions") + + +;; xemacs doesn't have `comint-preoutput-filter-functions' so we'll try the +;; following wonderful hack to work around this case +(if (featurep 'xemacs) + ;;xemacs + (defun ipython-complete () + "Try to complete the python symbol before point. Only knows about the stuff +in the current *Python* session." + (interactive) + (let* ((ugly-return nil) + (sep ";") + ;; XXX currently we go backwards to find the beginning of an + ;; expression part; a more powerful approach in the future might be + ;; to let ipython have the complete line, so that context can be used + ;; to do things like filename completion etc. + (beg (save-excursion (skip-chars-backward "a-z0-9A-Z_." (point-at-bol)) + (point))) + (end (point)) + (pattern (buffer-substring-no-properties beg end)) + (completions nil) + (completion-table nil) + completion + (comint-output-filter-functions + (append comint-output-filter-functions + '(ansi-color-filter-apply + (lambda (string) + ;(message (format "DEBUG filtering: %s" string)) + (setq ugly-return (concat ugly-return string)) + (delete-region comint-last-output-start + (process-mark (get-buffer-process (current-buffer))))))))) + ;(message (format "#DEBUG pattern: '%s'" pattern)) + (process-send-string (or (get-buffer-process (current-buffer)) + (get-process py-which-bufname)) ;XXX hack for .py buffers + (format ipython-completion-command-string pattern)) + (accept-process-output (get-buffer-process (current-buffer))) + ;(message (format "DEBUG return: %s" ugly-return)) + (setq completions + (split-string (substring ugly-return 0 (position ?\n ugly-return)) sep)) + (setq completion-table (loop for str in completions + collect (list str nil))) + (setq completion (try-completion pattern completion-table)) + (cond ((eq completion t)) + ((null completion) + (message "Can't find completion for \"%s\"" pattern) + (ding)) + ((not (string= pattern completion)) + (delete-region beg end) + (insert completion)) + (t + (message "Making completion list...") + (with-output-to-temp-buffer "*Python Completions*" + (display-completion-list (all-completions pattern completion-table))) + (message "Making completion list...%s" "done"))))) + ;; emacs + (defun ipython-complete () + "Try to complete the python symbol before point. Only knows about the stuff +in the current *Python* session." + (interactive) + (let* ((ugly-return nil) + (sep ";") + ;; XXX currently we go backwards to find the beginning of an + ;; expression part; a more powerful approach in the future might be + ;; to let ipython have the complete line, so that context can be used + ;; to do things like filename completion etc. + (beg (save-excursion (skip-chars-backward "a-z0-9A-Z_." (point-at-bol)) + (point))) + (end (point)) + (pattern (buffer-substring-no-properties beg end)) + (completions nil) + (completion-table nil) + completion + (comint-preoutput-filter-functions + (append comint-preoutput-filter-functions + '(ansi-color-filter-apply + (lambda (string) + (setq ugly-return (concat ugly-return string)) + ""))))) + (process-send-string (or (get-buffer-process (current-buffer)) + (get-process py-which-bufname)) ;XXX hack for .py buffers + (format ipython-completion-command-string pattern)) + (accept-process-output (get-buffer-process (current-buffer))) + (setq completions + (split-string (substring ugly-return 0 (position ?\n ugly-return)) sep)) + ;(message (format "DEBUG completions: %S" completions)) + (setq completion-table (loop for str in completions + collect (list str nil))) + (setq completion (try-completion pattern completion-table)) + (cond ((eq completion t)) + ((null completion) + (message "Can't find completion for \"%s\"" pattern) + (ding)) + ((not (string= pattern completion)) + (delete-region beg end) + (insert completion)) + (t + (message "Making completion list...") + (with-output-to-temp-buffer "*IPython Completions*" + (display-completion-list (all-completions pattern completion-table))) + (message "Making completion list...%s" "done"))))) +) + +(provide 'ipython) diff --git a/doc/manual_base.lyx b/doc/manual_base.lyx new file mode 100644 index 0000000..5031150 --- /dev/null +++ b/doc/manual_base.lyx @@ -0,0 +1,8777 @@ +#LyX 1.3 created this file. For more info see http://www.lyx.org/ +\lyxformat 221 +\textclass article +\begin_preamble +\usepackage{ae,aecompl} +\usepackage{hyperref} +\usepackage{html} +\end_preamble +\language english +\inputencoding latin1 +\fontscheme default +\graphics default +\paperfontsize default +\spacing single +\papersize Default +\paperpackage a4 +\use_geometry 1 +\use_amsmath 0 +\use_natbib 0 +\use_numerical_citations 0 +\paperorientation portrait +\leftmargin 1.25in +\topmargin 1in +\rightmargin 1.25in +\bottommargin 1in +\secnumdepth 3 +\tocdepth 3 +\paragraph_separation skip +\defskip medskip +\quotes_language english +\quotes_times 2 +\papercolumns 1 +\papersides 1 +\paperpagestyle fancy + +\layout Title + +IPython +\newline + +\size larger +An enhanced Interactive Python +\size large + +\newline +User Manual, v. + __version__ +\layout Author + +Fernando P�rez +\layout Standard + + +\begin_inset ERT +status Collapsed + +\layout Standard + +\backslash +latex{ +\end_inset + + +\begin_inset LatexCommand \tableofcontents{} + +\end_inset + + +\begin_inset ERT +status Collapsed + +\layout Standard +} +\end_inset + + +\layout Standard + + +\begin_inset ERT +status Open + +\layout Standard + +\backslash +html{ +\backslash +bodytext{bgcolor=#ffffff}} +\end_inset + + +\layout Section +\pagebreak_top +Overview +\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. +\layout Standard + +IPython is a free software project (released under the BSD license) which + tries to: +\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). +\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. +\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. +\layout Subsection + +Main features +\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 +'). +\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. +\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. +\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. +\layout Itemize + +Alias facility for defining your own system aliases. +\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. +\layout Itemize + +All calls to the system (via aliases or via !) have their standard output/error + automatically stored as strings, and also available as lists. +\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 +. +\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 +). +\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. +\layout Itemize + +Automatic indentation (optional) of code as you type (through the readline + library). +\layout Itemize + +Macro system for quickly re-executing multiple lines of previous input with + a single name. +\layout Itemize + +Session logging (you can then later use these logs as code in your programs). +\layout Itemize + +Session restoring: logs can be replayed to restore a previous session to + the state where you left it. +\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). +\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 +'. +\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\SpecialChar ~ +b' +\family default + becomes automatically +\family typewriter +`my_function("a","b")' +\family default +, while +\family typewriter +`;my_function a\SpecialChar ~ +b' +\family default + becomes +\family typewriter +`my_function("a b")' +\family default +. +\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. +\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. +\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). +\layout Itemize + +Easy debugger access. + You can set IPython to call up the Python debugger (pdb) 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. +\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 the standard +\family typewriter +profile +\family default + module, 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. +\layout Subsection + +Portability and Python requirements +\layout Standard + + +\series bold +Python requirements: +\series default +IPython works with Python version 2.2 or newer. + It has been tested with Python 2.4 and no problems have been reported. + Support for Python 2.1 hasn't been recently tested, since I don't have access + to it on any of my systems. + But I suspect there may be some problems with Python 2.1, because some of + the newer code may use 2.2 features. +\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). +\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. +\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. +\layout Standard + + +\series bold +Windows +\series default +: it works well under Windows XP/2k, and I suspect NT should behave similarly. + Section\SpecialChar ~ + +\begin_inset LatexCommand \ref{sub:Under-Windows} + +\end_inset + + describes installation details for Windows, including some additional tools + needed on this platform. +\layout Standard + +Windows 9x support is present, and has been reported to work fine (at least + on WinME). +\layout Standard + +Please note, however, that I have very little access to and experience with + Windows development. + For this reason, Windows-specific bugs tend to linger far longer than I + would like, and often I just can't find a satisfactory solution. + If any Windows user wants to join in with development help, all hands are + always welcome. +\layout Subsection + +Location +\layout Standard + +IPython is generously hosted at +\begin_inset LatexCommand \htmlurl{http://ipython.scipy.org} + +\end_inset + + by the SciPy project. + This site offers downloads, CVS 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. +\layout Section + + +\begin_inset LatexCommand \label{sec:install} + +\end_inset + +Installation +\layout Subsection + +Instant instructions +\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. +\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. +\layout Standard + +See the notes in sec. + +\begin_inset LatexCommand \ref{sec:upgrade} + +\end_inset + + for upgrading IPython versions. +\layout Subsection + +Detailed Unix instructions (Linux, Mac OS X, etc.) +\layout Standard + + +\begin_inset ERT +status Open + +\layout Standard + +\backslash +html{ +\backslash +textbf{A warning to readers of the HTML version of this manual}: all options below are preceded with with TWO dashes and no intervening space between the dashes (e.g. Dash-Dash-home). The default HTML conversion tools mangle these into a single dash.} +\end_inset + + +\layout Standard + +For RPM based systems, simply install the supplied package in the usual + manner. + If you download the tar archive, the process is: +\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. + +\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. +\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 +\family typewriter +--home +\family default + option (or +\family typewriter +--prefix +\family default +). + For example: +\newline + +\family typewriter +$ python setup.py install --home $HOME/local +\family default + +\newline +will install +\begin_inset Foot +collapsed true + +\layout Standard + +If you are reading these instructions in HTML format, please note that the + option is --home, with +\emph on +two +\emph default + dashes. + The automatic HTML conversion program seems to eat up one of the dashes, + unfortunately (it's ok in the PDF version). +\end_inset + + IPython into +\family typewriter +$HOME/local +\family default +and its subdirectories (creating them if necessary). +\newline +You can type +\newline + +\family typewriter +$ python setup.py --help +\family default + +\newline +for more details. +\newline +Note that if you change the default location for +\family typewriter +--home +\family default + 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 +\family typewriter +--home +\family default + plus +\family typewriter +/lib/python +\family default +). +\layout Subsubsection + +Mac OSX information +\layout Subsubsection* + +GUI problems +\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. +\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. +\layout Standard + +So when installing under OSX, it is best to use the following command +\begin_inset ERT +status Collapsed + +\layout Standard + +\backslash +html{ +\backslash +emph{[Again, in the HTML manual, the option is called -~-install=scripts, with TWO dashes and no intervening space between the dashes]}} +\end_inset + +: +\family typewriter + +\newline +\SpecialChar ~ +\SpecialChar ~ +$ sudo pythonw setup.py install --install-scripts=/usr/local/bin +\family default + +\newline +or +\family typewriter + +\newline +\SpecialChar ~ +\SpecialChar ~ +$ sudo pythonw setup.py install --install-scripts=/usr/bin +\newline + +\family default +depending on where you like to keep hand-installed executables. +\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-<python-version> +\family default + directory. + Delete that directory and rerun the +\family typewriter +setup.py +\family default +. + +\layout Standard + +It is also a good idea to use the special flag +\family typewriter +--install-scripts +\family default + 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). +\layout Subsubsection* + +Readline problems +\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 + + +\layout Standard + +At this point I don't know of such a released version for OSX 10.4 (Tiger), + or if the problem even occurs with Tiger at all (feedback welcome). +\layout Standard + +Users installing against fink's Python or a properly hand-built one should + not have this problem. +\layout Subsection + + +\begin_inset LatexCommand \label{sub:Under-Windows} + +\end_inset + +Windows instructions +\layout Standard + +While you can use IPython under Windows with only a stock Python installation, + there is one extension, +\family typewriter +readline +\family default +, which will make the whole experience a lot more pleasant. + It is almost a requirement, since IPython will complain in its absence + (though it will function). + +\layout Standard + +The +\family typewriter + readline +\family default + extension needs two other libraries to work, so in all you need: +\layout Enumerate + + +\family typewriter +PyWin32 +\family default + from +\begin_inset LatexCommand \htmlurl{http://starship.python.net/crew/mhammond} + +\end_inset + +. +\layout Enumerate + + +\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). +\layout Enumerate + + +\family typewriter +Readline +\family default + for Windows from +\begin_inset LatexCommand \htmlurl{http://sourceforge.net/projects/uncpythontools} + +\end_inset + +. +\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. +\layout Subsubsection + +Gary Bishop's readline and color support for Windows +\layout Standard + +Some of IPython's very useful features are: +\layout Itemize + +Integrated readline support (Tab-based file, object and attribute completion, + input history across sessions, editable command line, etc.) +\layout Itemize + +Coloring of prompts, code and tracebacks. +\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 implements 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. +\layout Standard + +You can find Gary's tools at +\begin_inset LatexCommand \htmlurl{http://sourceforge.net/projects/uncpythontools} + +\end_inset + +; Gary's +\family typewriter +readline +\family default + requires in turn the +\family typewriter +ctypes +\family default + library by Thomas Heller, available at +\begin_inset LatexCommand \htmlurl{http://starship.python.net/crew/theller/ctypes} + +\end_inset + +, and Mark Hammond's +\family typewriter +PyWin32 +\family default + from +\begin_inset LatexCommand \htmlurl{http://starship.python.net/crew/mhammond} + +\end_inset + + ( +\family typewriter +PyWin32 +\family default + is great for anything Windows-related anyway, so you might as well get + it). +\layout Standard + +Under MS\SpecialChar ~ +Windows, IPython will complain if it can not find this +\family typewriter +readline +\family default + library at startup and any time the +\family typewriter +%colors +\family default + command is issued, so you can consider it to be a quasi-requirement. +\layout Subsubsection + +Installation procedure +\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. + +\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. +\layout Paragraph + +Upgrading +\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. +\layout Paragraph + +Manual installation under Win32 +\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 +. + +\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. +\layout Subsection + + +\begin_inset LatexCommand \label{sec:upgrade} + +\end_inset + +Upgrading from a previous version +\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. +\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. +\layout Section + + +\begin_inset LatexCommand \label{sec:good_config} + +\end_inset + + +\begin_inset OptArg +collapsed true + +\layout Standard + +Initial configuration +\begin_inset ERT +status Collapsed + +\layout Standard + +\backslash +ldots +\end_inset + + +\end_inset + +Initial configuration of your environment +\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 +. +\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. +\layout Subsection + + +\begin_inset LatexCommand \label{sec:help-access} + +\end_inset + +Access to the Python help system +\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. + +\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: +\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 +\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. +\layout Standard + +Under Windows it seems that pydoc finds the documentation automatically, + so no extra setup appears necessary. +\layout Subsection + +Editor +\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. + +\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: +\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 + +\layout Standard + +\backslash +hspace*{0mm} +\end_inset + +\SpecialChar ~ +\SpecialChar ~ +(server-start) +\newline + +\begin_inset ERT +status Collapsed + +\layout Standard + +\backslash +hspace*{0mm} +\end_inset + +\SpecialChar ~ +\SpecialChar ~ +(defun fp-kill-server-with-buffer-routine () +\newline + +\begin_inset ERT +status Collapsed + +\layout Standard + +\backslash +hspace*{0mm} +\end_inset + +\SpecialChar ~ +\SpecialChar ~ +\SpecialChar ~ +\SpecialChar ~ +(and server-buffer-clients (server-done))) +\newline + +\begin_inset ERT +status Collapsed + +\layout Standard + +\backslash +hspace*{0mm} +\end_inset + +\SpecialChar ~ +\SpecialChar ~ +(add-hook 'kill-buffer-hook 'fp-kill-server-with-buffer-routine)) +\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). +\layout Subsection + +Color +\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. +\layout Standard + +The following terminals seem to handle the color sequences fine: +\layout Itemize + +Linux main text console, KDE Konsole, Gnome Terminal, E-term, rxvt, xterm. +\layout Itemize + +CDE terminal (tested under Solaris). + This one boldfaces light colors. +\layout Itemize + +(X)Emacs buffers. + See sec. +\begin_inset LatexCommand \ref{sec:emacs} + +\end_inset + + for more details on using IPython with (X)Emacs. +\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.\SpecialChar ~ + +\begin_inset LatexCommand \ref{sub:Under-Windows} + +\end_inset + +. +\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. +\layout Standard + +These have shown problems: +\layout Itemize + +Windows command prompt in WinXP/2k logged into a Linux machine via telnet + or ssh. +\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. +\layout Standard + +Currently the following color schemes are available: +\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. +\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. +\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. +\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. +\layout Subsubsection + +Input/Output prompts and exception tracebacks +\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 +'. + +\layout Standard + +You can try using a different terminal emulator program. + 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. +\layout Subsubsection + +Object details (types, docstrings, source code, etc.) +\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. +\layout Standard + +In order to configure +\family typewriter +less +\family default + as your default pager, do the following: +\layout Enumerate + +Set the environment +\family typewriter +PAGER +\family default + variable to +\family typewriter +less +\family default +. +\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. +\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: +\layout Standard + + +\family typewriter +setenv PAGER less +\newline +setenv LESS -r +\layout Standard + +There is similar syntax for other Unix shells, look at your system documentation + for details. +\layout Standard + +If you are on a system which lacks proper data pagers (such as Windows), + IPython will use a very limited builtin pager. +\layout Subsection + + +\begin_inset LatexCommand \label{sec:emacs} + +\end_inset + +(X)Emacs configuration +\layout Standard + +Thanks to the work of Alexander Schmolck and Prabhu Ramachandran, currently + (X)Emacs and IPython get along very well. + +\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. +\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). +\layout Standard + +Once you put these files in your Emacs path, all you need in your +\family typewriter +.emacs +\family default + file is: +\layout Standard + + +\family typewriter +(require 'ipython) +\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\SpecialChar ~ +! +\family default +, etc. + +\layout Subsubsection* + +Notes +\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\SpecialChar ~ +| +\family default +. + Simply type +\family typewriter +C-c\SpecialChar ~ +! +\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 ]). +\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. + +\layout Itemize + +This code is still somewhat experimental so it's a bit rough around the + edges (although in practice, it works quite well). +\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). +\layout Section + + +\begin_inset LatexCommand \label{sec:quick_tips} + +\end_inset + +Quick tips +\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. +\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 + + +\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.<TAB> +\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. + +\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. +\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. +\layout Itemize + +Use the Python debugger, +\family typewriter +pdb +\family default + +\begin_inset Foot +collapsed true + +\layout Standard + +Thanks to Christian Hart and Matthew Arnison for the suggestions leading + to IPython's improved debugger and profiler support. +\end_inset + +. + The +\family typewriter +%pdb +\family default + command allows you to toggle on and off the automatic invocation of the + pdb debugger at any uncaught exception. + The advantage of this is that pdb 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 +Running 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.\SpecialChar ~ + +\begin_inset LatexCommand \ref{sec:cache_output} + +\end_inset + + for details. +\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.\SpecialChar ~ + +\begin_inset LatexCommand \ref{sec:cache_output} + +\end_inset + + for more. +\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. +\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. +\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. +\layout Itemize + +Define your own macros with +\family typewriter +%macro +\family default +. + This can be useful for automating sequences of expressions when working + interactively. +\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 +%ds +\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. +\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. +\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.\SpecialChar ~ + +\begin_inset LatexCommand \ref{sub:System-shell-access} + +\end_inset + + for more. +\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.\SpecialChar ~ + +\begin_inset LatexCommand \ref{sec:profiles} + +\end_inset + + for more. +\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.\SpecialChar ~ + +\begin_inset LatexCommand \ref{sec:embed} + +\end_inset + + for more. +\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). +\layout Itemize + +Use +\family typewriter +%edit +\family default + to have almost multiline editing. + While IPython doesn't support true multiline editing, this command allows + you to call an editor on the spot, and IPython will execute the code you + type in there as if it were typed interactively. +\layout Standard + +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! +\layout Section + +Command-line use +\layout Standard + +You start IPython with the command: +\layout Standard + + +\family typewriter +$ ipython [options] files +\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. +\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 +. +\layout Subsection + + +\begin_inset LatexCommand \label{sec:threading-opts} + +\end_inset + +Special Threading Options +\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. +\layout List +\labelwidthstring 00.00.0000 + + +\family typewriter +\series bold +-gthread,\SpecialChar ~ +-wthread,\SpecialChar ~ +-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 and WXPython toolkits, and for + the matplotlib library. +\layout List +\labelwidthstring 00.00.0000 + +\SpecialChar ~ + If +\family typewriter +-gthread +\family default + is given, IPython starts running a separate thread for GTK operation, so + that pyGTK-based programs can open and control GUIs without blocking IPython. + +\layout List +\labelwidthstring 00.00.0000 + +\SpecialChar ~ + Similarly, +\family typewriter +-wthread +\family default + instantiates IPython with threading support for the WXPython toolkit. + You can control WX application windows from within IPython. +\layout List +\labelwidthstring 00.00.0000 + +\SpecialChar ~ + 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 + .matplotlibrc 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. + +\layout List +\labelwidthstring 00.00.0000 + + +\family typewriter +\series bold +-tk +\family default +\series default + The +\family typewriter +-g/wthread +\family default + options, and +\family typewriter +-pylab +\family default + (if matplotlib is configured to use WX or GTK), will normally block Tk + graphical interfaces. + This means that when either GTK or WX threading is active, any attempt + to open a Tk GUI will result in a dead window, and pos- sibly 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 +). +\layout List +\labelwidthstring 00.00.0000 + +\SpecialChar ~ + If +\family typewriter +-tk +\family default + is given, IPython will try to coordinate Tk threading with WX or GTK. + 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), 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. +\layout List +\labelwidthstring 00.00.0000 + +\SpecialChar ~ + 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. + +\layout Subsection + + +\begin_inset LatexCommand \label{sec:cmd-line-opts} + +\end_inset + +Regular Options +\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 +. +\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. +\layout Standard + +All options with a +\family typewriter +no| +\family default + prepended can be specified in 'no' form ( +\family typewriter +-nooption +\family default + instead of +\family typewriter +-option +\family default +) to turn the feature off. +\layout List +\labelwidthstring 00.00.0000 + + +\family typewriter +\series bold +-help +\family default +\series default +: print a help message and exit. +\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.\SpecialChar ~ + +\begin_inset LatexCommand \ref{sec:matplotlib-support} + +\end_inset + + for more details. +\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. +\layout List +\labelwidthstring 00.00.0000 + + +\family typewriter +\series bold +-no|banner +\series default +: +\family default + Print the initial information banner (default on). +\layout List +\labelwidthstring 00.00.0000 + + +\family typewriter +\series bold +-c\SpecialChar ~ +<command>: +\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. + +\layout List +\labelwidthstring 00.00.0000 + + +\family typewriter +\series bold +-cache_size|cs\SpecialChar ~ +<n> +\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. +\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. +\layout List +\labelwidthstring 00.00.0000 + + +\family typewriter +\series bold +-colors\SpecialChar ~ +<scheme>: +\family default +\series default + Color scheme for prompts and exception reporting. + Currently implemented: NoColor, Linux and LightBG. +\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. +\layout List +\labelwidthstring 00.00.0000 + +\SpecialChar ~ + 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. +\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. +\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. +\layout List +\labelwidthstring 00.00.0000 + +\SpecialChar ~ + 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 +]. +\layout List +\labelwidthstring 00.00.0000 + + +\family typewriter +\series bold +-editor\SpecialChar ~ +<name> +\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). +\layout List +\labelwidthstring 00.00.0000 + + +\family typewriter +\series bold +-ipythondir\SpecialChar ~ +<name> +\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 +. +\layout List +\labelwidthstring 00.00.0000 + + +\family typewriter +\series bold +-log|l +\family default +\series default +: generate a log file of all input. + Defaults to +\family typewriter +$IPYTHONDIR/log +\family default +. + 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). +\layout List +\labelwidthstring 00.00.0000 + + +\family typewriter +\series bold +-logfile|lf\SpecialChar ~ +<name> +\series default +: +\family default +specify the name of your logfile. +\layout List +\labelwidthstring 00.00.0000 + + +\family typewriter +\series bold +-logplay|lp\SpecialChar ~ +<name> +\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. +\layout List +\labelwidthstring 00.00.0000 + +\SpecialChar ~ + 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. +\layout List +\labelwidthstring 00.00.0000 + +\SpecialChar ~ + 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. +\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). +\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. +\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). +\layout List +\labelwidthstring 00.00.0000 + + +\family typewriter +\series bold +-profile|p <name> +\series default +: +\family default + assume that your config file is +\family typewriter +ipythonrc-<name> +\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: +\layout List +\labelwidthstring 00.00.0000 + + +\family typewriter +\SpecialChar ~ + +\family default +1. + +\family typewriter + $HOME/.ipython/ipythonrc +\family default + : load basic things you always want. +\layout List +\labelwidthstring 00.00.0000 + + +\family typewriter +\SpecialChar ~ + +\family default +2. + +\family typewriter + $HOME/.ipython/ipythonrc-math +\family default + : load (1) and basic math-related modules. + +\layout List +\labelwidthstring 00.00.0000 + + +\family typewriter +\SpecialChar ~ + +\family default +3. + +\family typewriter + $HOME/.ipython/ipythonrc-numeric +\family default + : load (1) and Numeric and plotting modules. +\layout List +\labelwidthstring 00.00.0000 + +\SpecialChar ~ + Since it is possible to create an endless loop by having circular file + inclusions, IPython will stop if it reaches 15 recursive inclusions. +\layout List +\labelwidthstring 00.00.0000 + + +\family typewriter +\series bold +-prompt_in1|pi1\SpecialChar ~ +<string>: +\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\SpecialChar ~ +[ +\backslash +#]: +\family default +'. + Sec.\SpecialChar ~ + +\begin_inset LatexCommand \ref{sec:prompts} + +\end_inset + + discusses in detail all the available escapes to customize your prompts. +\layout List +\labelwidthstring 00.00.0000 + + +\family typewriter +\series bold +-prompt_in2|pi2\SpecialChar ~ +<string>: +\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 +\SpecialChar ~ +\SpecialChar ~ +\SpecialChar ~ +. +\backslash +D.: +\family default +' (note three spaces at the start for alignment with ' +\family typewriter +In\SpecialChar ~ +[ +\backslash +#] +\family default +'). +\layout List +\labelwidthstring 00.00.0000 + + +\family typewriter +\series bold +-prompt_out|po\SpecialChar ~ +<string>: +\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 +' +\layout List +\labelwidthstring 00.00.0000 + + +\family typewriter +\series bold +-quick +\family default +\series default +: start in bare bones mode (no config file loaded). +\layout List +\labelwidthstring 00.00.0000 + + +\family typewriter +\series bold +-rcfile\SpecialChar ~ +<name> +\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 +. +\layout List +\labelwidthstring 00.00.0000 + +\SpecialChar ~ + If the loading of your config file fails, IPython starts with a bare bones + configuration (no modules loaded at all). +\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. +\layout List +\labelwidthstring 00.00.0000 + +\SpecialChar ~ + Note that X/Emacs 'eterm' buffers (opened with +\family typewriter +M-x\SpecialChar ~ +term +\family default +) support IPython's readline and syntax coloring fine, only 'emacs' ( +\family typewriter +M-x\SpecialChar ~ +shell +\family default + and +\family typewriter +C-c\SpecialChar ~ +! +\family default +) buffers do not. +\layout List +\labelwidthstring 00.00.0000 + + +\family typewriter +\series bold +-screen_length|sl\SpecialChar ~ +<n> +\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. +\layout List +\labelwidthstring 00.00.0000 + +\SpecialChar ~ + 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. +\layout List +\labelwidthstring 00.00.0000 + + +\family typewriter +\series bold +-separate_in|si\SpecialChar ~ +<string> +\series default +: +\family default + separator before input prompts. + Default: ' +\family typewriter + +\backslash +n +\family default +' +\layout List +\labelwidthstring 00.00.0000 + + +\family typewriter +\series bold +-separate_out|so\SpecialChar ~ +<string> +\family default +\series default +: separator before output prompts. + Default: nothing. +\layout List +\labelwidthstring 00.00.0000 + + +\family typewriter +\series bold +-separate_out2|so2\SpecialChar ~ +<string> +\series default +: +\family default + separator after output prompts. + Default: nothing. +\layout List +\labelwidthstring 00.00.0000 + +\SpecialChar ~ + For these three options, use the value 0 to specify no separator. +\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. +\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. +\layout List +\labelwidthstring 00.00.0000 + + +\family typewriter +\series bold +-Version +\series default +: +\family default + print version information and exit. +\layout List +\labelwidthstring 00.00.0000 + + +\family typewriter +\series bold +-xmode <modename> +\series default +: +\family default + Mode for exception reporting. +\layout List +\labelwidthstring 00.00.0000 + +\SpecialChar ~ + Valid modes: Plain, Context and Verbose. +\layout List +\labelwidthstring 00.00.0000 + +\SpecialChar ~ + Plain: similar to python's normal traceback printing. +\layout List +\labelwidthstring 00.00.0000 + +\SpecialChar ~ + Context: prints 5 lines of context source code around each line in the + traceback. +\layout List +\labelwidthstring 00.00.0000 + +\SpecialChar ~ + 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). +\layout Section + +Interactive use +\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. +\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. +\layout Subsection + +Caution for Windows users +\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. +\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 +\layout Standard + +There is no sensible thing IPython can do to truly work around this flaw + in Windows +\begin_inset Foot +collapsed true + +\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_inset + +. +\layout Subsection + + +\begin_inset LatexCommand \label{sec:magic} + +\end_inset + +Magic command system +\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. +\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. +\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. +\layout Standard + +An example (with automagic on) should clarify all this: +\layout LyX-Code + +In [1]: cd ipython # %cd is called by automagic +\layout LyX-Code + +/home/fperez/ipython +\layout LyX-Code + +In [2]: cd=1 # now cd is just a variable +\layout LyX-Code + +In [3]: cd .. + # and doesn't work as a function anymore +\layout LyX-Code + +------------------------------------------------------------ +\layout LyX-Code + + File "<console>", line 1 +\layout LyX-Code + + cd .. +\layout LyX-Code + + ^ +\layout LyX-Code + +SyntaxError: invalid syntax +\layout LyX-Code + +\layout LyX-Code + +In [4]: %cd .. + # but %cd always works +\layout LyX-Code + +/home/fperez +\layout LyX-Code + +In [5]: del cd # if you remove the cd variable +\layout LyX-Code + +In [6]: cd ipython # automagic can work again +\layout LyX-Code + +/home/fperez/ipython +\layout Standard + +You can define your own magic functions to extend the system. + The following is a snippet of code which shows how to do it. + It is provided as file +\family typewriter +example-magic.py +\family default + in the examples directory: +\layout Standard + + +\begin_inset Include \verbatiminput{examples/example-magic.py} +preview false + +\end_inset + + +\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: +\layout Standard + + +\family typewriter +execute __IP.magic_cl = __IP.magic_clear +\layout Standard + +will define +\family typewriter +%cl +\family default + as a new name for +\family typewriter +%clear +\family default +. +\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. +\layout Subsubsection + +Magic commands +\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. +\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. +\layout Standard + + +\begin_inset Include \input{magic.tex} +preview false + +\end_inset + + +\layout Subsection + +Access to the standard Python help +\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. +\layout Subsection + + +\begin_inset LatexCommand \label{sec:dyn-object-info} + +\end_inset + +Dynamic object information +\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. +\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. +\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: +\layout List +\labelwidthstring 00.00.0000 + + +\family typewriter +\series bold +%pdoc\SpecialChar ~ +<object> +\family default +\series default +: Print (or run through a pager if too long) the docstring for an object. + If the given object is a class, it will print both the class and the constructo +r docstrings. +\layout List +\labelwidthstring 00.00.0000 + + +\family typewriter +\series bold +%pdef\SpecialChar ~ +<object> +\family default +\series default +: Print the definition header for any callable object. + If the object is a class, print the constructor information. +\layout List +\labelwidthstring 00.00.0000 + + +\family typewriter +\series bold +%psource\SpecialChar ~ +<object> +\family default +\series default +: Print (or run through a pager if too long) the source code for an object. +\layout List +\labelwidthstring 00.00.0000 + + +\family typewriter +\series bold +%pfile\SpecialChar ~ +<object> +\family default +\series default +: Show the entire source file where an object was defined via a pager, opening + it at the line where the object definition begins. +\layout List +\labelwidthstring 00.00.0000 + + +\family typewriter +\series bold +%who/%whos +\family default +\series default +: These functions give information about identifiers you have defined interactiv +ely (not things you loaded or defined in your configuration files). + +\family typewriter +%who +\family default + just prints a list of identifiers and +\family typewriter +%whos +\family default + prints a table with some basic details about each identifier. +\layout Standard + +Note that the dynamic object information functions ( +\family typewriter +?/??, %pdoc, %pfile, %pdef, %psource +\family default +) give you access to documentation even on things which are not really defined + as separate identifiers. + Try for example typing +\family typewriter +{}.get? +\family default + or after doing +\family typewriter +import os +\family default +, type +\family typewriter +os.path.abspath?? +\family default +. +\layout Subsection + + +\begin_inset LatexCommand \label{sec:readline} + +\end_inset + +Readline-based features +\layout Standard + +These features require the GNU readline library, so they won't work if your + Python installation lacks readline support. + We will first describe the default behavior IPython uses, and then how + to change it to suit your preferences. +\layout Subsubsection + +Command line completion +\layout Standard + +At any time, hitting TAB will complete any available python commands or + variable names, and show you a list of the possible completions if there's + no unambiguous one. + It will also complete filenames in the current directory if no python names + match what you've typed so far. +\layout Subsubsection + +Search command history +\layout Standard + +IPython provides two ways for searching through previous input and thus + reduce the need for repetitive typing: +\layout Enumerate + +Start typing, and then use +\family typewriter +Ctrl-p +\family default + (previous,up) and +\family typewriter +Ctrl-n +\family default + (next,down) to search through only the history items that match what you've + typed so far. + If you use +\family typewriter +Ctrl-p/Ctrl-n +\family default + at a blank prompt, they just behave like normal arrow keys. +\layout Enumerate + +Hit +\family typewriter +Ctrl-r +\family default +: opens a search prompt. + Begin typing and the system searches your history for lines that contain + what you've typed so far, completing as much as it can. +\layout Subsubsection + +Persistent command history across sessions +\layout Standard + +IPython will save your input history when it leaves and reload it next time + you restart it. + By default, the history file is named +\family typewriter +$IPYTHONDIR/history +\family default +, but if you've loaded a named profile, ' +\family typewriter +-PROFILE_NAME +\family default +' is appended to the name. + This allows you to keep separate histories related to various tasks: commands + related to numerical work will not be clobbered by a system shell history, + for example. +\layout Subsubsection + +Autoindent +\layout Standard + +IPython can recognize lines ending in ':' and indent the next line, while + also un-indenting automatically after 'raise' or 'return'. + +\layout Standard + +This feature uses the readline library, so it will honor your +\family typewriter +~/.inputrc +\family default + configuration (or whatever file your +\family typewriter +INPUTRC +\family default + variable points to). + Adding the following lines to your +\family typewriter +.inputrc +\family default + file can make indenting/unindenting more convenient ( +\family typewriter +M-i +\family default + indents, +\family typewriter +M-u +\family default + unindents): +\layout Standard + + +\family typewriter +$if Python +\newline +" +\backslash +M-i": "\SpecialChar ~ +\SpecialChar ~ +\SpecialChar ~ +\SpecialChar ~ +" +\newline +" +\backslash +M-u": " +\backslash +d +\backslash +d +\backslash +d +\backslash +d" +\newline +$endif +\layout Standard + +Note that there are 4 spaces between the quote marks after +\family typewriter +"M-i" +\family default + above. +\layout Standard + + +\series bold +Warning: +\series default + this feature is ON by default, but it can cause problems with the pasting + of multi-line indented code (the pasted code gets re-indented on each line). + A magic function +\family typewriter +%autoindent +\family default + allows you to toggle it on/off at runtime. + You can also disable it permanently on in your +\family typewriter +ipythonrc +\family default + file (set +\family typewriter +autoindent 0 +\family default +). +\layout Subsubsection + +Customizing readline behavior +\layout Standard + +All these features are based on the GNU readline library, which has an extremely + customizable interface. + Normally, readline is configured via a file which defines the behavior + of the library; the details of the syntax for this can be found in the + readline documentation available with your system or on the Internet. + IPython doesn't read this file (if it exists) directly, but it does support + passing to readline valid options via a simple interface. + In brief, you can customize readline by setting the following options in + your +\family typewriter +ipythonrc +\family default + configuration file (note that these options can +\emph on +not +\emph default + be specified at the command line): +\layout List +\labelwidthstring 00.00.0000 + + +\family typewriter +\series bold +readline_parse_and_bind: +\family default +\series default + this option can appear as many times as you want, each time defining a + string to be executed via a +\family typewriter +readline.parse_and_bind() +\family default + command. + The syntax for valid commands of this kind can be found by reading the + documentation for the GNU readline library, as these commands are of the + kind which readline accepts in its configuration file. +\layout List +\labelwidthstring 00.00.0000 + + +\family typewriter +\series bold +readline_remove_delims: +\family default +\series default + a string of characters to be removed from the default word-delimiters list + used by readline, so that completions may be performed on strings which + contain them. + Do not change the default value unless you know what you're doing. +\layout List +\labelwidthstring 00.00.0000 + + +\family typewriter +\series bold +readline_omit__names +\family default +\series default +: when tab-completion is enabled, hitting +\family typewriter +<tab> +\family default + after a ' +\family typewriter +. +\family default +' in a name will complete all attributes of an object, including all the + special methods whose names include double underscores (like +\family typewriter +__getitem__ +\family default + or +\family typewriter +__class__ +\family default +). + If you'd rather not see these names by default, you can set this option + to 1. + Note that even when this option is set, you can still see those names by + explicitly typing a +\family typewriter +_ +\family default + after the period and hitting +\family typewriter +<tab> +\family default +: ' +\family typewriter +name._<tab> +\family default +' will always complete attribute names starting with ' +\family typewriter +_ +\family default +'. +\layout List +\labelwidthstring 00.00.0000 + +\SpecialChar ~ + This option is off by default so that new users see all attributes of any + objects they are dealing with. +\layout Standard + +You will find the default values along with a corresponding detailed explanation + in your +\family typewriter +ipythonrc +\family default + file. +\layout Subsection + +Session logging and restoring +\layout Standard + +You can log all input from a session either by starting IPython with the + command line switches +\family typewriter +-log +\family default + or +\family typewriter +-logfile +\family default +(see sec. + +\begin_inset LatexCommand \ref{sec:cmd-line-opts} + +\end_inset + +)or by activating the logging at any moment with the magic function +\family typewriter +%logstart +\family default +. + +\layout Standard + +Log files can later be reloaded with the +\family typewriter +-logplay +\family default + option and IPython will attempt to 'replay' the log by executing all the + lines in it, thus restoring the state of a previous session. + This feature is not quite perfect, but can still be useful in many cases. +\layout Standard + +The log files can also be used as a way to have a permanent record of any + code you wrote while experimenting. + Log files are regular text files which you can later open in your favorite + text editor to extract code or to 'clean them up' before using them to + replay a session. +\layout Standard + +The +\family typewriter +%logstart +\family default + function for activating logging in mid-session is used as follows: +\layout Standard + + +\family typewriter +%logstart [log_name [log_mode]] +\layout Standard + +If no name is given, it defaults to a file named +\family typewriter +'log' +\family default + in your IPYTHONDIR directory, in +\family typewriter +'rotate' +\family default + mode (see below). +\layout Standard + +' +\family typewriter +%logstart name +\family default +' saves to file +\family typewriter +'name' +\family default + in +\family typewriter +'backup' +\family default + mode. + It saves your history up to that point and then continues logging. +\layout Standard + + +\family typewriter +%logstart +\family default + takes a second optional parameter: logging mode. + This can be one of (note that the modes are given unquoted): +\layout List +\labelwidthstring 00.00.0000 + + +\family typewriter +over +\family default +: overwrite existing +\family typewriter +log_name +\family default +. +\layout List +\labelwidthstring 00.00.0000 + + +\family typewriter +backup +\family default +: rename (if exists) to +\family typewriter +log_name~ +\family default + and start +\family typewriter +log_name +\family default +. +\layout List +\labelwidthstring 00.00.0000 + + +\family typewriter +append +\family default +: well, that says it. +\layout List +\labelwidthstring 00.00.0000 + + +\family typewriter +rotate +\family default +: create rotating logs +\family typewriter +log_name +\family default +. +\family typewriter +1~ +\family default +, +\family typewriter +log_name.2~ +\family default +, etc. +\layout Standard + +The +\family typewriter +%logoff +\family default + and +\family typewriter +%logon +\family default + functions allow you to temporarily stop and resume logging to a file which + had previously been started with +\family typewriter +%logstart +\family default +. + They will fail (with an explanation) if you try to use them before logging + has been started. +\layout Subsection + + +\begin_inset LatexCommand \label{sub:System-shell-access} + +\end_inset + +System shell access +\layout Standard + +Any input line beginning with a +\family typewriter +! +\family default + character is passed verbatim (minus the +\family typewriter +! +\family default +, of course) to the underlying operating system. + For example, typing +\family typewriter +!ls +\family default + will run +\family typewriter +'ls' +\family default + in the current directory. +\layout Subsubsection + +Manual capture of command output +\layout Standard + +If the input line begins with +\emph on +two +\emph default + exclamation marks, +\family typewriter +!! +\family default +, the command is executed but its output is captured and returned as a python + list, split on newlines. + Any output sent by the subprocess to standard error is printed separately, + so that the resulting list only captures standard output. + The +\family typewriter +!! +\family default + syntax is a shorthand for the +\family typewriter +%sx +\family default + magic command. +\layout Standard + +Finally, the +\family typewriter +%sc +\family default + magic (short for `shell capture') is similar to +\family typewriter +%sx +\family default +, but allowing more fine-grained control of the capture details, and storing + the result directly into a named variable. +\layout Standard + +See Sec.\SpecialChar ~ + +\begin_inset LatexCommand \ref{sec:magic} + +\end_inset + + for details on the magics +\family typewriter +%sc +\family default + and +\family typewriter +%sx +\family default +, or use IPython's own help ( +\family typewriter +sc? +\family default + and +\family typewriter +sx? +\family default +) for further details. +\layout Standard + +IPython also allows you to expand the value of python variables when making + system calls. + Any python variable or expression which you prepend with +\family typewriter +$ +\family default + will get expanded before the system call is made. + +\layout Standard + + +\family typewriter +In [1]: pyvar='Hello world' +\newline +In [2]: !echo "A python variable: $pyvar" +\newline +A python variable: Hello world +\layout Standard + +If you want the shell to actually see a literal +\family typewriter +$ +\family default +, you need to type it twice: +\layout Standard + + +\family typewriter +In [3]: !echo "A system variable: $$HOME" +\newline +A system variable: /home/fperez +\layout Standard + +You can pass arbitrary expressions, though you'll need to delimit them with + +\family typewriter +{} +\family default + if there is ambiguity as to the extent of the expression: +\layout Standard + + +\family typewriter +In [5]: x=10 +\newline +In [6]: y=20 +\newline +In [13]: !echo $x+y +\newline +10+y +\newline +In [7]: !echo ${x+y} +\newline +30 +\layout Standard + +Even object attributes can be expanded: +\layout Standard + + +\family typewriter +In [12]: !echo $sys.argv +\newline +[/home/fperez/usr/bin/ipython] +\layout Subsection + +System command aliases +\layout Standard + +The +\family typewriter +%alias +\family default + magic function and the +\family typewriter +alias +\family default + option in the +\family typewriter +ipythonrc +\family default + configuration file allow you to define magic functions which are in fact + system shell commands. + These aliases can have parameters. + +\layout Standard + +' +\family typewriter +%alias alias_name cmd +\family default +' defines ' +\family typewriter +alias_name +\family default +' as an alias for ' +\family typewriter +cmd +\family default +' +\layout Standard + +Then, typing ' +\family typewriter +%alias_name params +\family default +' will execute the system command ' +\family typewriter +cmd params +\family default +' (from your underlying operating system). + +\layout Standard + +You can also define aliases with parameters using +\family typewriter +%s +\family default + specifiers (one per parameter). + The following example defines the +\family typewriter +%parts +\family default + function as an alias to the command ' +\family typewriter +echo first %s second %s +\family default +' where each +\family typewriter +%s +\family default + will be replaced by a positional parameter to the call to +\family typewriter +%parts: +\layout Standard + + +\family typewriter +In [1]: alias parts echo first %s second %s +\newline +In [2]: %parts A B +\newline +first A second B +\newline +In [3]: %parts A +\newline +Incorrect number of arguments: 2 expected. + +\newline +parts is an alias to: 'echo first %s second %s' +\layout Standard + +If called with no parameters, +\family typewriter +%alias +\family default + prints the table of currently defined aliases. +\layout Standard + +The +\family typewriter +%rehash/rehashx +\family default + magics allow you to load your entire +\family typewriter +$PATH +\family default + as ipython aliases. + See their respective docstrings (or sec.\SpecialChar ~ + +\begin_inset LatexCommand \ref{sec:magic} + +\end_inset + + for further details). +\layout Subsection + + +\begin_inset LatexCommand \label{sec:dreload} + +\end_inset + +Recursive reload +\layout Standard + +The +\family typewriter +%dreload +\family default + command does a recursive reload of a module: changes made to the module + since you imported will actually be available without having to exit. +\layout Subsection + +Verbose and colored exception traceback printouts +\layout Standard + +IPython provides the option to see very detailed exception tracebacks, which + can be especially useful when debugging large programs. + You can run any Python file with the +\family typewriter +%run +\family default + function to benefit from these detailed tracebacks. + Furthermore, both normal and verbose tracebacks can be colored (if your + terminal supports it) which makes them much easier to parse visually. +\layout Standard + +See the magic +\family typewriter +xmode +\family default + and +\family typewriter +colors +\family default + functions for details (just type +\family typewriter +%magic +\family default +). +\layout Standard + +These features are basically a terminal version of Ka-Ping Yee's +\family typewriter +cgitb +\family default + module, now part of the standard Python library. +\layout Subsection + + +\begin_inset LatexCommand \label{sec:cache_input} + +\end_inset + +Input caching system +\layout Standard + +IPython offers numbered prompts (In/Out) with input and output caching. + All input is saved and can be retrieved as variables (besides the usual + arrow key recall). +\layout Standard + +The following GLOBAL variables always exist (so don't overwrite them!): + +\family typewriter +_i +\family default +: stores previous input. + +\family typewriter +_ii +\family default +: next previous. + +\family typewriter +_iii +\family default +: next-next previous. + +\family typewriter +_ih +\family default + : a list of all input +\family typewriter +_ih[n] +\family default + is the input from line +\family typewriter +n +\family default + and this list is aliased to the global variable +\family typewriter +In +\family default +. + If you overwrite +\family typewriter +In +\family default + with a variable of your own, you can remake the assignment to the internal + list with a simple +\family typewriter +'In=_ih' +\family default +. +\layout Standard + +Additionally, global variables named +\family typewriter +_i<n> +\family default + are dynamically created ( +\family typewriter +<n> +\family default + being the prompt counter), such that +\newline + +\family typewriter +_i<n> == _ih[<n>] == In[<n>]. +\layout Standard + +For example, what you typed at prompt 14 is available as +\family typewriter +_i14, +\family default + +\family typewriter +_ih[14] +\family default + and +\family typewriter +In[14] +\family default +. +\layout Standard + +This allows you to easily cut and paste multi line interactive prompts by + printing them out: they print like a clean string, without prompt characters. + You can also manipulate them like regular variables (they are strings), + modify or exec them (typing +\family typewriter +'exec _i9' +\family default + will re-execute the contents of input prompt 9, ' +\family typewriter +exec In[9:14]+In[18] +\family default +' will re-execute lines 9 through 13 and line 18). +\layout Standard + +You can also re-execute multiple lines of input easily by using the magic + +\family typewriter +%macro +\family default + function (which automates the process and allows re-execution without having + to type ' +\family typewriter +exec +\family default +' every time). + The macro system also allows you to re-execute previous lines which include + magic function calls (which require special processing). + Type +\family typewriter +%macro? +\family default + or see sec. + +\begin_inset LatexCommand \ref{sec:magic} + +\end_inset + + for more details on the macro system. +\layout Standard + +A history function +\family typewriter +%hist +\family default + allows you to see any part of your input history by printing a range of + the +\family typewriter +_i +\family default + variables. +\layout Subsection + + +\begin_inset LatexCommand \label{sec:cache_output} + +\end_inset + +Output caching system +\layout Standard + +For output that is returned from actions, a system similar to the input + cache exists but using +\family typewriter +_ +\family default + instead of +\family typewriter +_i +\family default +. + Only actions that produce a result (NOT assignments, for example) are cached. + If you are familiar with Mathematica, IPython's +\family typewriter +_ +\family default + variables behave exactly like Mathematica's +\family typewriter +% +\family default + variables. +\layout Standard + +The following GLOBAL variables always exist (so don't overwrite them!): + +\layout List +\labelwidthstring 00.00.0000 + + +\family typewriter +\series bold +_ +\family default +\series default + (a +\emph on +single +\emph default + underscore) : stores previous output, like Python's default interpreter. +\layout List +\labelwidthstring 00.00.0000 + + +\family typewriter +\series bold +__ +\family default +\series default + (two underscores): next previous. +\layout List +\labelwidthstring 00.00.0000 + + +\family typewriter +\series bold +___ +\family default +\series default + (three underscores): next-next previous. +\layout Standard + +Additionally, global variables named +\family typewriter +_<n> +\family default +are dynamically created ( +\family typewriter +<n> +\family default + being the prompt counter), such that the result of output +\family typewriter +<n> +\family default + is always available as +\family typewriter +_<n> +\family default + (don't use the angle brackets, just the number, e.g. + +\family typewriter +_21 +\family default +). +\layout Standard + +These global variables are all stored in a global dictionary (not a list, + since it only has entries for lines which returned a result) available + under the names +\family typewriter +_oh +\family default + and +\family typewriter +Out +\family default + (similar to +\family typewriter +_ih +\family default + and +\family typewriter +In +\family default +). + So the output from line 12 can be obtained as +\family typewriter +_12 +\family default +, +\family typewriter +Out[12] +\family default + or +\family typewriter +_oh[12] +\family default +. + If you accidentally overwrite the +\family typewriter +Out +\family default + variable you can recover it by typing +\family typewriter +'Out=_oh +\family default +' at the prompt. +\layout Standard + +This system obviously can potentially put heavy memory demands on your system, + since it prevents Python's garbage collector from removing any previously + computed results. + You can control how many results are kept in memory with the option (at + the command line or in your +\family typewriter +ipythonrc +\family default + file) +\family typewriter +cache_size +\family default +. + If you set it to 0, the whole system is completely disabled and the prompts + revert to the classic +\family typewriter +'>>>' +\family default + of normal Python. +\layout Subsection + +Directory history +\layout Standard + +Your history of visited directories is kept in the global list +\family typewriter +_dh +\family default +, and the magic +\family typewriter +%cd +\family default + command can be used to go to any entry in that list. + The +\family typewriter +%dhist +\family default + command allows you to view this history. +\layout Subsection + +Automatic parentheses and quotes +\layout Standard + +These features were adapted from Nathan Gray's LazyPython. + They are meant to allow less typing for common situations. +\layout Subsubsection + +Automatic parentheses +\layout Standard + +Callable objects (i.e. + functions, methods, etc) can be invoked like this (notice the commas between + the arguments): +\layout Standard + + +\family typewriter +>>> callable_ob arg1, arg2, arg3 +\layout Standard + +and the input will be translated to this: +\layout Standard + + +\family typewriter +--> callable_ob(arg1, arg2, arg3) +\layout Standard + +You can force automatic parentheses by using '/' as the first character + of a line. + For example: +\layout Standard + + +\family typewriter +>>> /globals # becomes 'globals()' +\layout Standard + +Note that the '/' MUST be the first character on the line! This won't work: + +\layout Standard + + +\family typewriter +>>> print /globals # syntax error +\layout Standard + +In most cases the automatic algorithm should work, so you should rarely + need to explicitly invoke /. + One notable exception is if you are trying to call a function with a list + of tuples as arguments (the parenthesis will confuse IPython): +\layout Standard + + +\family typewriter +In [1]: zip (1,2,3),(4,5,6) # won't work +\layout Standard + +but this will work: +\layout Standard + + +\family typewriter +In [2]: /zip (1,2,3),(4,5,6) +\newline +------> zip ((1,2,3),(4,5,6)) +\newline +Out[2]= [(1, 4), (2, 5), (3, 6)] +\layout Standard + +IPython tells you that it has altered your command line by displaying the + new command line preceded by +\family typewriter +--> +\family default +. + e.g.: +\layout Standard + + +\family typewriter +In [18]: callable list +\newline +-------> callable (list) +\layout Subsubsection + +Automatic quoting +\layout Standard + +You can force automatic quoting of a function's arguments by using +\family typewriter +`,' +\family default + or +\family typewriter +`;' +\family default + as the first character of a line. + For example: +\layout Standard + + +\family typewriter +>>> ,my_function /home/me # becomes my_function("/home/me") +\layout Standard + +If you use +\family typewriter +`;' +\family default + instead, the whole argument is quoted as a single string (while +\family typewriter +`,' +\family default + splits on whitespace): +\layout Standard + + +\family typewriter +>>> ,my_function a b c # becomes my_function("a","b","c") +\layout Standard + + +\family typewriter +>>> ;my_function a b c # becomes my_function("a b c") +\layout Standard + +Note that the ` +\family typewriter +, +\family default +' or ` +\family typewriter +; +\family default +' MUST be the first character on the line! This won't work: +\layout Standard + + +\family typewriter +>>> x = ,my_function /home/me # syntax error +\layout Section + + +\begin_inset LatexCommand \label{sec:customization} + +\end_inset + +Customization +\layout Standard + +As we've already mentioned, IPython reads a configuration file which can + be specified at the command line ( +\family typewriter +-rcfile +\family default +) or which by default is assumed to be called +\family typewriter +ipythonrc +\family default +. + Such a file is looked for in the current directory where IPython is started + and then in your +\family typewriter +IPYTHONDIR +\family default +, which allows you to have local configuration files for specific projects. + In this section we will call these types of configuration files simply + rcfiles (short for resource configuration file). +\layout Standard + +The syntax of an rcfile is one of key-value pairs separated by whitespace, + one per line. + Lines beginning with a +\family typewriter +# +\family default + are ignored as comments, but comments can +\series bold +not +\series default + be put on lines with data (the parser is fairly primitive). + Note that these are not python files, and this is deliberate, because it + allows us to do some things which would be quite tricky to implement if + they were normal python files. +\layout Standard + +First, an rcfile can contain permanent default values for almost all command + line options (except things like +\family typewriter +-help +\family default + or +\family typewriter +-Version +\family default +). + Sec\SpecialChar ~ + +\begin_inset LatexCommand \ref{sec:cmd-line-opts} + +\end_inset + + contains a description of all command-line options. + However, values you explicitly specify at the command line override the + values defined in the rcfile. +\layout Standard + +Besides command line option values, the rcfile can specify values for certain + extra special options which are not available at the command line. + These options are briefly described below. + +\layout Standard + +Each of these options may appear as many times as you need it in the file. +\layout List +\labelwidthstring 00.00.0000 + + +\family typewriter +\series bold +include\SpecialChar ~ +<file1>\SpecialChar ~ +<file2>\SpecialChar ~ +... +\family default +\series default +: you can name +\emph on +other +\emph default +rcfiles you want to recursively load up to 15 levels (don't use the +\family typewriter +<> +\family default + brackets in your names!). + This feature allows you to define a 'base' rcfile with general options + and special-purpose files which can be loaded only when needed with particular + configuration options. + To make this more convenient, IPython accepts the +\family typewriter +-profile <name> +\family default + option (abbreviates to +\family typewriter +-p <name +\family default +>) +\family typewriter + which +\family default + tells it to look for an rcfile named +\family typewriter +ipythonrc-<name> +\family default +. + +\layout List +\labelwidthstring 00.00.0000 + + +\family typewriter +\series bold +import_mod\SpecialChar ~ +<mod1>\SpecialChar ~ +<mod2>\SpecialChar ~ +... +\family default +\series default +: import modules with ' +\family typewriter +import +\family default + +\family typewriter +<mod1>,<mod2>,... +\family default +' +\layout List +\labelwidthstring 00.00.0000 + + +\family typewriter +\series bold +import_some\SpecialChar ~ +<mod>\SpecialChar ~ +<f1>\SpecialChar ~ +<f2>\SpecialChar ~ +... +\family default +\series default +: import functions with ' +\family typewriter +from <mod> import +\family default + +\family typewriter +<f1>,<f2>,... +\family default +' +\layout List +\labelwidthstring 00.00.0000 + + +\family typewriter +\series bold +import_all\SpecialChar ~ +<mod1>\SpecialChar ~ +<mod2>\SpecialChar ~ +... +\family default +\series default +: for each module listed import functions with ' +\family typewriter +from <mod> import * +\family default +' +\layout List +\labelwidthstring 00.00.0000 + + +\family typewriter +\series bold +execute\SpecialChar ~ +<python\SpecialChar ~ +code> +\family default +\series default +: give any single-line python code to be executed. +\layout List +\labelwidthstring 00.00.0000 + + +\family typewriter +\series bold +execfile\SpecialChar ~ +<filename> +\family default +\series default +: execute the python file given with an ' +\family typewriter +execfile(filename) +\family default +' command. + Username expansion is performed on the given names. + So if you need any amount of extra fancy customization that won't fit in + any of the above 'canned' options, you can just put it in a separate python + file and execute it. +\layout List +\labelwidthstring 00.00.0000 + + +\family typewriter +\series bold +alias\SpecialChar ~ +<alias_def> +\family default +\series default +: this is equivalent to calling ' +\family typewriter +%alias\SpecialChar ~ +<alias_def> +\family default +' at the IPython command line. + This way, from within IPython you can do common system tasks without having + to exit it or use the +\family typewriter +! +\family default + escape. + IPython isn't meant to be a shell replacement, but it is often very useful + to be able to do things with files while testing code. + This gives you the flexibility to have within IPython any aliases you may + be used to under your normal system shell. +\layout Subsection + + +\begin_inset LatexCommand \label{sec:ipytonrc-sample} + +\end_inset + +Sample +\family typewriter +ipythonrc +\family default + file +\layout Standard + +The default rcfile, called +\family typewriter +ipythonrc +\family default + and supplied in your +\family typewriter +IPYTHONDIR +\family default +directory contains lots of comments on all of these options. + We reproduce it here for reference: +\layout Standard + + +\begin_inset Include \verbatiminput{../IPython/UserConfig/ipythonrc} +preview false + +\end_inset + + +\layout Subsection + + +\begin_inset LatexCommand \label{sec:prompts} + +\end_inset + +Fine-tuning your prompt +\layout Standard + +IPython's prompts can be customized using a syntax similar to that of the + +\family typewriter +bash +\family default + shell. + Many of +\family typewriter +bash +\family default +'s escapes are supported, as well as a few additional ones. + We list them below: +\layout Description + + +\backslash +# the prompt/history count number +\layout Description + + +\backslash +D the prompt/history count, with the actual digits replaced by dots. + Used mainly in continuation prompts (prompt_in2) +\layout Description + + +\backslash +w the current working directory +\layout Description + + +\backslash +W the basename of current working directory +\layout Description + + +\backslash +X +\emph on +n +\emph default + where +\begin_inset Formula $n=0\ldots5.$ +\end_inset + + The current working directory, with +\family typewriter +$HOME +\family default + replaced by +\family typewriter +~ +\family default +, and filtered out to contain only +\begin_inset Formula $n$ +\end_inset + + path elements +\layout Description + + +\backslash +Y +\emph on +n +\emph default + Similar to +\backslash +X +\emph on +n +\emph default +, but with the +\begin_inset Formula $n+1$ +\end_inset + + element included if it is +\family typewriter +~ +\family default + (this is similar to the behavior of the %c +\emph on +n +\emph default + escapes in +\family typewriter +tcsh +\family default +) +\layout Description + + +\backslash +u the username of the current user +\layout Description + + +\backslash +$ if the effective UID is 0, a #, otherwise a $ +\layout Description + + +\backslash +h the hostname up to the first `.' +\layout Description + + +\backslash +H the hostname +\layout Description + + +\backslash +n a newline +\layout Description + + +\backslash +r a carriage return +\layout Description + + +\backslash +v IPython version string +\layout Standard + +In addition to these, ANSI color escapes can be insterted into the prompts, + as +\family typewriter + +\backslash +C_ +\emph on +ColorName +\family default +\emph default +. + The list of valid color names is: Black, Blue, Brown, Cyan, DarkGray, Green, + LightBlue, LightCyan, LightGray, LightGreen, LightPurple, LightRed, NoColor, + Normal, Purple, Red, White, Yellow. +\layout Standard + +Finally, IPython supports the evaluation of arbitrary expressions in your + prompt string. + The prompt strings are evaluated through the syntax of PEP 215, but basically + you can use +\family typewriter +$x.y +\family default + to expand the value of +\family typewriter +x.y +\family default +, and for more complicated expressions you can use braces: +\family typewriter +${foo()+x} +\family default + will call function +\family typewriter +foo +\family default + and add to it the value of +\family typewriter +x +\family default +, before putting the result into your prompt. + For example, using +\newline + +\family typewriter +prompt_in1 '${commands.getoutput("uptime")} +\backslash +nIn [ +\backslash +#]: ' +\newline + +\family default +will print the result of the uptime command on each prompt (assuming the + +\family typewriter +commands +\family default + module has been imported in your +\family typewriter +ipythonrc +\family default + file). +\layout Subsubsection + +Prompt examples +\layout Standard + +The following options in an ipythonrc file will give you IPython's default + prompts: +\layout Standard + + +\family typewriter +prompt_in1 'In [ +\backslash +#]:' +\newline +prompt_in2 '\SpecialChar ~ +\SpecialChar ~ +\SpecialChar ~ +. +\backslash +D.:' +\newline +prompt_out 'Out[ +\backslash +#]:' +\layout Standard + +which look like this: +\layout Standard + + +\family typewriter +In [1]: 1+2 +\newline +Out[1]: 3 +\layout Standard + + +\family typewriter +In [2]: for i in (1,2,3): +\newline + +\begin_inset ERT +status Collapsed + +\layout Standard + +\backslash +hspace*{0mm} +\end_inset + +\SpecialChar ~ +\SpecialChar ~ +\SpecialChar ~ +...: \SpecialChar ~ +\SpecialChar ~ +\SpecialChar ~ +\SpecialChar ~ +print i, +\newline + +\begin_inset ERT +status Collapsed + +\layout Standard + +\backslash +hspace*{0mm} +\end_inset + +\SpecialChar ~ +\SpecialChar ~ +\SpecialChar ~ +...: +\newline +1 2 3 +\layout Standard + +These will give you a very colorful prompt with path information: +\layout Standard + + +\family typewriter +#prompt_in1 ' +\backslash +C_Red +\backslash +u +\backslash +C_Blue[ +\backslash +C_Cyan +\backslash +Y1 +\backslash +C_Blue] +\backslash +C_LightGreen +\backslash +#>' +\newline +prompt_in2 ' .. +\backslash +D>' +\newline +prompt_out '< +\backslash +#>' +\layout Standard + +which look like this: +\layout Standard + + +\family typewriter +\color red +fperez +\color blue +[ +\color cyan +~/ipython +\color blue +] +\color green +1> +\color default + 1+2 +\newline + +\begin_inset ERT +status Collapsed + +\layout Standard + +\backslash +hspace*{0mm} +\end_inset + +\SpecialChar ~ +\SpecialChar ~ +\SpecialChar ~ +\SpecialChar ~ +\SpecialChar ~ +\SpecialChar ~ +\SpecialChar ~ +\SpecialChar ~ +\SpecialChar ~ +\SpecialChar ~ +\SpecialChar ~ +\SpecialChar ~ +\SpecialChar ~ +\SpecialChar ~ +\SpecialChar ~ +\SpecialChar ~ + +\color red +<1> +\color default + 3 +\newline + +\color red +fperez +\color blue +[ +\color cyan +~/ipython +\color blue +] +\color green +2> +\color default + for i in (1,2,3): +\newline + +\begin_inset ERT +status Collapsed + +\layout Standard + +\backslash +hspace*{0mm} +\end_inset + +\SpecialChar ~ +\SpecialChar ~ +\SpecialChar ~ +\SpecialChar ~ +\SpecialChar ~ +\SpecialChar ~ +\SpecialChar ~ +\SpecialChar ~ +\SpecialChar ~ +\SpecialChar ~ +\SpecialChar ~ +\SpecialChar ~ +\SpecialChar ~ +\SpecialChar ~ +\SpecialChar ~ + +\color green +...> +\color default + \SpecialChar ~ +\SpecialChar ~ +\SpecialChar ~ +\SpecialChar ~ +print i, +\newline + +\begin_inset ERT +status Collapsed + +\layout Standard + +\backslash +hspace*{0mm} +\end_inset + +\SpecialChar ~ +\SpecialChar ~ +\SpecialChar ~ +\SpecialChar ~ +\SpecialChar ~ +\SpecialChar ~ +\SpecialChar ~ +\SpecialChar ~ +\SpecialChar ~ +\SpecialChar ~ +\SpecialChar ~ +\SpecialChar ~ +\SpecialChar ~ +\SpecialChar ~ +\SpecialChar ~ + +\color green +...> +\color default + +\newline +1 2 3 +\layout Standard + +The following shows the usage of dynamic expression evaluation: +\layout Subsection + + +\begin_inset LatexCommand \label{sec:profiles} + +\end_inset + +IPython profiles +\layout Standard + +As we already mentioned, IPython supports the +\family typewriter +-profile +\family default + command-line option (see sec. + +\begin_inset LatexCommand \ref{sec:cmd-line-opts} + +\end_inset + +). + A profile is nothing more than a particular configuration file like your + basic +\family typewriter +ipythonrc +\family default + one, but with particular customizations for a specific purpose. + When you start IPython with ' +\family typewriter +ipython -profile <name> +\family default +', it assumes that in your +\family typewriter +IPYTHONDIR +\family default + there is a file called +\family typewriter +ipythonrc-<name> +\family default +, and loads it instead of the normal +\family typewriter +ipythonrc +\family default +. +\layout Standard + +This system allows you to maintain multiple configurations which load modules, + set options, define functions, etc. + suitable for different tasks and activate them in a very simple manner. + In order to avoid having to repeat all of your basic options (common things + that don't change such as your color preferences, for example), any profile + can include another configuration file. + The most common way to use profiles is then to have each one include your + basic +\family typewriter +ipythonrc +\family default + file as a starting point, and then add further customizations. +\layout Standard + +In sections +\begin_inset LatexCommand \ref{sec:syntax-extensions} + +\end_inset + + and +\begin_inset LatexCommand \ref{sec:Gnuplot} + +\end_inset + + we discuss some particular profiles which come as part of the standard + IPython distribution. + You may also look in your +\family typewriter +IPYTHONDIR +\family default + directory, any file whose name begins with +\family typewriter +ipythonrc- +\family default + is a profile. + You can use those as examples for further customizations to suit your own + needs. +\layout Section + + +\begin_inset OptArg +collapsed false + +\layout Standard + +IPython as default... +\end_inset + +IPython as your default Python environment +\layout Standard + +Python honors the environment variable +\family typewriter +PYTHONSTARTUP +\family default +and will execute at startup the file referenced by this variable. + If you put at the end of this file the following two lines of code: +\layout Standard + + +\family typewriter +import IPython +\newline +IPython.Shell.IPShell().mainloop(sys_exit=1) +\layout Standard + +then IPython will be your working environment anytime you start Python. + The +\family typewriter +sys_exit=1 +\family default + is needed to have IPython issue a call to +\family typewriter +sys.exit() +\family default + when it finishes, otherwise you'll be back at the normal Python ' +\family typewriter +>>> +\family default +' prompt +\begin_inset Foot +collapsed true + +\layout Standard + +Based on an idea by Holger Krekel. +\end_inset + +. +\layout Standard + +This is probably useful to developers who manage multiple Python versions + and don't want to have correspondingly multiple IPython versions. + Note that in this mode, there is no way to pass IPython any command-line + options, as those are trapped first by Python itself. +\layout Section + + +\begin_inset LatexCommand \label{sec:embed} + +\end_inset + +Embedding IPython +\layout Standard + +It is possible to start an IPython instance +\emph on +inside +\emph default + your own Python programs. + This allows you to evaluate dynamically the state of your code, operate + with your variables, analyze them, etc. + Note however that any changes you make to values while in the shell do + +\emph on +not +\emph default + propagate back to the running code, so it is safe to modify your values + because you won't break your code in bizarre ways by doing so. +\layout Standard + +This feature allows you to easily have a fully functional python environment + for doing object introspection anywhere in your code with a simple function + call. + In some cases a simple print statement is enough, but if you need to do + more detailed analysis of a code fragment this feature can be very valuable. +\layout Standard + +It can also be useful in scientific computing situations where it is common + to need to do some automatic, computationally intensive part and then stop + to look at data, plots, etc +\begin_inset Foot +collapsed true + +\layout Standard + +This functionality was inspired by IDL's combination of the +\family typewriter +stop +\family default + keyword and the +\family typewriter +.continue +\family default + executive command, which I have found very useful in the past, and by a + posting on comp.lang.python by cmkl <cmkleffner-AT-gmx.de> on Dec. + 06/01 concerning similar uses of pyrepl. +\end_inset + +. + Opening an IPython instance will give you full access to your data and + functions, and you can resume program execution once you are done with + the interactive part (perhaps to stop again later, as many times as needed). +\layout Standard + +The following code snippet is the bare minimum you need to include in your + Python programs for this to work (detailed examples follow later): +\layout LyX-Code + +from IPython.Shell import IPShellEmbed +\layout LyX-Code + +ipshell = IPShellEmbed() +\layout LyX-Code + +ipshell() # this call anywhere in your program will start IPython +\layout Standard + +You can run embedded instances even in code which is itself being run at + the IPython interactive prompt with ' +\family typewriter +%run\SpecialChar ~ +<filename> +\family default +'. + Since it's easy to get lost as to where you are (in your top-level IPython + or in your embedded one), it's a good idea in such cases to set the in/out + prompts to something different for the embedded instances. + The code examples below illustrate this. +\layout Standard + +You can also have multiple IPython instances in your program and open them + separately, for example with different options for data presentation. + If you close and open the same instance multiple times, its prompt counters + simply continue from each execution to the next. +\layout Standard + +Please look at the docstrings in the +\family typewriter +Shell.py +\family default + module for more details on the use of this system. +\layout Standard + +The following sample file illustrating how to use the embedding functionality + is provided in the examples directory as +\family typewriter +example-embed.py +\family default +. + It should be fairly self-explanatory: +\layout Standard + + +\begin_inset Include \verbatiminput{examples/example-embed.py} +preview false + +\end_inset + + +\layout Standard + +Once you understand how the system functions, you can use the following + code fragments in your programs which are ready for cut and paste: +\layout Standard + + +\begin_inset Include \verbatiminput{examples/example-embed-short.py} +preview false + +\end_inset + + +\layout Section + + +\begin_inset LatexCommand \label{sec:using-pdb} + +\end_inset + +Using the Python debugger ( +\family typewriter +pdb +\family default +) +\layout Subsection + +Running entire programs via +\family typewriter +pdb +\layout Standard + + +\family typewriter +pdb +\family default +, the Python debugger, is a powerful interactive debugger which allows you + to step through code, set breakpoints, watch variables, etc. + IPython makes it very easy to start any script under the control of +\family typewriter +pdb +\family default +, regardless of whether you have wrapped it into a +\family typewriter +`main()' +\family default + function or not. + For this, simply type +\family typewriter +`%run -d myscript' +\family default + at an IPython prompt. + See the +\family typewriter +%run +\family default + command's documentation (via +\family typewriter +`%run?' +\family default + or in Sec.\SpecialChar ~ + +\begin_inset LatexCommand \ref{sec:magic} + +\end_inset + +) for more details, including how to control where +\family typewriter +pdb +\family default + will stop execution first. +\layout Standard + +For more information on the use of the +\family typewriter +pdb +\family default + debugger, read the included +\family typewriter +pdb.doc +\family default + file (part of the standard Python distribution). + On a stock Linux system it is located at +\family typewriter +/usr/lib/python2.3/pdb.doc +\family default +, but the easiest way to read it is by using the +\family typewriter +help() +\family default + function of the +\family typewriter +pdb +\family default + module as follows (in an IPython prompt): +\layout Standard + + +\family typewriter +In [1]: import pdb +\newline +In [2]: pdb.help() +\layout Standard + +This will load the +\family typewriter +pdb.doc +\family default + document in a file viewer for you automatically. +\layout Subsection + +Automatic invocation of +\family typewriter +pdb +\family default + on exceptions +\layout Standard + +IPython, if started with the +\family typewriter +-pdb +\family default + option (or if the option is set in your rc file) can call the Python +\family typewriter +pdb +\family default + debugger every time your code triggers an uncaught exception +\begin_inset Foot +collapsed true + +\layout Standard + +Many thanks to Christopher Hart for the request which prompted adding this + feature to IPython. +\end_inset + +. + This feature can also be toggled at any time with the +\family typewriter +%pdb +\family default + magic command. + This can be extremely useful in order to find the origin of subtle bugs, + because +\family typewriter +pdb +\family default + opens up at the point in your code which triggered the exception, and while + your program is at this point `dead', all the data is still available and + you can walk up and down the stack frame and understand the origin of the + problem. +\layout Standard + +Furthermore, you can use these debugging facilities both with the embedded + IPython mode and without IPython at all. + For an embedded shell (see sec. + +\begin_inset LatexCommand \ref{sec:embed} + +\end_inset + +), simply call the constructor with +\family typewriter +`-pdb' +\family default + in the argument string and automatically +\family typewriter +pdb +\family default + will be called if an uncaught exception is triggered by your code. + +\layout Standard + +For stand-alone use of the feature in your programs which do not use IPython + at all, put the following lines toward the top of your `main' routine: +\layout Standard +\align left + +\family typewriter +import sys,IPython.ultraTB +\newline +sys.excepthook = IPython.ultraTB.FormattedTB(mode=`Verbose', color_scheme=`Linux', + call_pdb=1) +\layout Standard + +The +\family typewriter +mode +\family default + keyword can be either +\family typewriter +`Verbose' +\family default + or +\family typewriter +`Plain' +\family default +, giving either very detailed or normal tracebacks respectively. + The +\family typewriter +color_scheme +\family default + keyword can be one of +\family typewriter +`NoColor' +\family default +, +\family typewriter +`Linux' +\family default + (default) or +\family typewriter +`LightBG' +\family default +. + These are the same options which can be set in IPython with +\family typewriter +-colors +\family default + and +\family typewriter +-xmode +\family default +. +\layout Standard + +This will give any of your programs detailed, colored tracebacks with automatic + invocation of +\family typewriter +pdb +\family default +. +\layout Section + + +\begin_inset LatexCommand \label{sec:syntax-extensions} + +\end_inset + +Extensions for syntax processing +\layout Standard + +This isn't for the faint of heart, because the potential for breaking things + is quite high. + But it can be a very powerful and useful feature. + In a nutshell, you can redefine the way IPython processes the user input + line to accept new, special extensions to the syntax without needing to + change any of IPython's own code. +\layout Standard + +In the +\family typewriter +IPython/Extensions +\family default + directory you will find some examples supplied, which we will briefly describe + now. + These can be used `as is' (and both provide very useful functionality), + or you can use them as a starting point for writing your own extensions. +\layout Subsection + +Pasting of code starting with +\family typewriter +`>>> +\family default +' or +\family typewriter +`... + +\family default +' +\layout Standard + +In the python tutorial it is common to find code examples which have been + taken from real python sessions. + The problem with those is that all the lines begin with either +\family typewriter +`>>> +\family default +' or +\family typewriter +`... + +\family default +', which makes it impossible to paste them all at once. + One must instead do a line by line manual copying, carefully removing the + leading extraneous characters. +\layout Standard + +This extension identifies those starting characters and removes them from + the input automatically, so that one can paste multi-line examples directly + into IPython, saving a lot of time. + Please look at the file +\family typewriter +InterpreterPasteInput.py +\family default + in the +\family typewriter +IPython/Extensions +\family default + directory for details on how this is done. +\layout Standard + +IPython comes with a special profile enabling this feature, called +\family typewriter +tutorial +\family default +\emph on +. + +\emph default + Simply start IPython via +\family typewriter +`ipython\SpecialChar ~ +-p\SpecialChar ~ +tutorial' +\family default + and the feature will be available. + In a normal IPython session you can activate the feature by importing the + corresponding module with: +\newline + +\family typewriter +In [1]: import IPython.Extensions.InterpreterPasteInput +\layout Standard + +The following is a 'screenshot' of how things work when this extension is + on, copying an example from the standard tutorial: +\layout Standard + + +\family typewriter +IPython profile: tutorial +\newline +\SpecialChar ~ + +\newline +*** Pasting of code with ">>>" or "..." has been enabled. +\newline +\SpecialChar ~ + +\newline +In [1]: >>> def fib2(n): # return Fibonacci series up to n +\newline + +\begin_inset ERT +status Collapsed + +\layout Standard + +\backslash +hspace*{0mm} +\end_inset + +\SpecialChar ~ +\SpecialChar ~ + ...: ...\SpecialChar ~ +\SpecialChar ~ +\SpecialChar ~ +\SpecialChar ~ + """Return a list containing the Fibonacci series up to n.""" +\newline + +\begin_inset ERT +status Collapsed + +\layout Standard + +\backslash +hspace*{0mm} +\end_inset + +\SpecialChar ~ +\SpecialChar ~ + ...: ...\SpecialChar ~ +\SpecialChar ~ +\SpecialChar ~ +\SpecialChar ~ + result = [] +\newline + +\begin_inset ERT +status Collapsed + +\layout Standard + +\backslash +hspace*{0mm} +\end_inset + +\SpecialChar ~ +\SpecialChar ~ + ...: ...\SpecialChar ~ +\SpecialChar ~ +\SpecialChar ~ +\SpecialChar ~ + a, b = 0, 1 +\newline + +\begin_inset ERT +status Collapsed + +\layout Standard + +\backslash +hspace*{0mm} +\end_inset + +\SpecialChar ~ +\SpecialChar ~ + ...: ...\SpecialChar ~ +\SpecialChar ~ +\SpecialChar ~ +\SpecialChar ~ + while b < n: +\newline + +\begin_inset ERT +status Collapsed + +\layout Standard + +\backslash +hspace*{0mm} +\end_inset + +\SpecialChar ~ +\SpecialChar ~ + ...: ...\SpecialChar ~ +\SpecialChar ~ +\SpecialChar ~ +\SpecialChar ~ +\SpecialChar ~ +\SpecialChar ~ +\SpecialChar ~ +\SpecialChar ~ + result.append(b)\SpecialChar ~ +\SpecialChar ~ +\SpecialChar ~ + # see below +\newline + +\begin_inset ERT +status Collapsed + +\layout Standard + +\backslash +hspace*{0mm} +\end_inset + +\SpecialChar ~ +\SpecialChar ~ + ...: ...\SpecialChar ~ +\SpecialChar ~ +\SpecialChar ~ +\SpecialChar ~ +\SpecialChar ~ +\SpecialChar ~ +\SpecialChar ~ +\SpecialChar ~ + a, b = b, a+b +\newline + +\begin_inset ERT +status Collapsed + +\layout Standard + +\backslash +hspace*{0mm} +\end_inset + +\SpecialChar ~ +\SpecialChar ~ + ...: ...\SpecialChar ~ +\SpecialChar ~ +\SpecialChar ~ +\SpecialChar ~ + return result +\newline + +\begin_inset ERT +status Collapsed + +\layout Standard + +\backslash +hspace*{0mm} +\end_inset + +\SpecialChar ~ +\SpecialChar ~ + ...: +\newline +\SpecialChar ~ + +\newline +In [2]: fib2(10) +\newline +Out[2]: [1, 1, 2, 3, 5, 8] +\layout Standard + +Note that as currently written, this extension does +\emph on +not +\emph default +recognize IPython's prompts for pasting. + Those are more complicated, since the user can change them very easily, + they involve numbers and can vary in length. + One could however extract all the relevant information from the IPython + instance and build an appropriate regular expression. + This is left as an exercise for the reader. +\layout Subsection + +Input of physical quantities with units +\layout Standard + +The module +\family typewriter +PhysicalQInput +\family default + allows a simplified form of input for physical quantities with units. + This file is meant to be used in conjunction with the +\family typewriter +PhysicalQInteractive +\family default + module (in the same directory) and +\family typewriter +Physics.PhysicalQuantities +\family default + from Konrad Hinsen's ScientificPython ( +\begin_inset LatexCommand \htmlurl{http://starship.python.net/crew/hinsen/scientific.html} + +\end_inset + +). +\layout Standard + +The +\family typewriter +Physics.PhysicalQuantities +\family default + module defines +\family typewriter +PhysicalQuantity +\family default + objects, but these must be declared as instances of a class. + For example, to define +\family typewriter +v +\family default + as a velocity of 3\SpecialChar ~ +m/s, normally you would write: +\family typewriter + +\newline +In [1]: v = PhysicalQuantity(3,'m/s') +\layout Standard + +Using the +\family typewriter +PhysicalQ_Input +\family default + extension this can be input instead as: +\family typewriter + +\newline +In [1]: v = 3 m/s +\family default + +\newline +which is much more convenient for interactive use (even though it is blatantly + invalid Python syntax). +\layout Standard + +The +\family typewriter +physics +\family default + profile supplied with IPython (enabled via +\family typewriter +'ipython -p physics' +\family default +) uses these extensions, which you can also activate with: +\layout Standard + + +\family typewriter +from math import * # math MUST be imported BEFORE PhysicalQInteractive +\newline +from IPython.Extensions.PhysicalQInteractive import * +\newline +import IPython.Extensions.PhysicalQInput +\layout Section + +IPython as a system shell +\layout Standard + +IPython ships with a special profile called +\family typewriter +pysh +\family default +, which you can activate at the command line as +\family typewriter +`ipython -p pysh' +\family default +. + This loads +\family typewriter +InterpreterExec +\family default +, along with some additional facilities and a prompt customized for filesystem + navigation. +\layout Standard + +Note that this does +\emph on +not +\emph default + make IPython a full-fledged system shell. + In particular, it has no job control, so if you type Ctrl-Z (under Unix), + you'll suspend pysh itself, not the process you just started. + +\layout Standard + +What the shell profile allows you to do is to use the convenient and powerful + syntax of Python to do quick scripting at the command line. + Below we describe some of its features. +\layout Subsection + +Aliases +\layout Standard + +All of your +\family typewriter +$PATH +\family default + has been loaded as IPython aliases, so you should be able to type any normal + system command and have it executed. + See +\family typewriter +%alias? +\family default + and +\family typewriter +%unalias? +\family default + for details on the alias facilities. + See also +\family typewriter +%rehash? +\family default + and +\family typewriter +%rehashx? +\family default +for details on the mechanism used to load +\family typewriter +$PATH +\family default +. +\layout Subsection + +Special syntax +\layout Standard + +Any lines which begin with +\family typewriter +`~' +\family default +, +\family typewriter +`/' +\family default + and +\family typewriter +`.' +\family default + will be executed as shell commands instead of as Python code. + The special escapes below are also recognized. + +\family typewriter +!cmd +\family default + is valid in single or multi-line input, all others are only valid in single-lin +e input: +\layout Description + + +\family typewriter +!cmd +\family default + pass `cmd' directly to the shell +\layout Description + + +\family typewriter +!!cmd +\family default + execute `cmd' and return output as a list (split on ` +\backslash +n') +\layout Description + + +\family typewriter +$var=cmd +\family default + capture output of cmd into var, as a string +\layout Description + + +\family typewriter +$$var=cmd +\family default + capture output of cmd into var, as a list (split on ` +\backslash +n') +\layout Standard + +The +\family typewriter +$ +\family default +/ +\family typewriter +$$ +\family default + syntaxes make Python variables from system output, which you can later + use for further scripting. + The converse is also possible: when executing an alias or calling to the + system via +\family typewriter +! +\family default +/ +\family typewriter +!! +\family default +, you can expand any python variable or expression by prepending it with + +\family typewriter +$ +\family default +. + Full details of the allowed syntax can be found in Python's PEP 215. +\layout Standard + +A few brief examples will illustrate these (note that the indentation below + may be incorrectly displayed): +\layout Standard + + +\family typewriter +fperez[~/test]|3> !ls *s.py +\newline +scopes.py strings.py +\layout Standard + +ls is an internal alias, so there's no need to use +\family typewriter +! +\family default +: +\layout Standard + + +\family typewriter +fperez[~/test]|4> ls *s.py +\newline +scopes.py* strings.py +\layout Standard + +!!ls will return the output into a Python variable: +\layout Standard + + +\family typewriter +fperez[~/test]|5> !!ls *s.py +\newline + +\begin_inset ERT +status Collapsed + +\layout Standard + +\backslash +hspace*{0mm} +\end_inset + +\SpecialChar ~ +\SpecialChar ~ +\SpecialChar ~ +\SpecialChar ~ +\SpecialChar ~ +\SpecialChar ~ +\SpecialChar ~ +\SpecialChar ~ +\SpecialChar ~ +\SpecialChar ~ +\SpecialChar ~ +\SpecialChar ~ +\SpecialChar ~ +\SpecialChar ~ +<5> ['scopes.py', 'strings.py'] +\newline +fperez[~/test]|6> print _5 +\newline +['scopes.py', 'strings.py'] +\layout Standard + + +\family typewriter +$ +\family default + and +\family typewriter +$$ +\family default + allow direct capture to named variables: +\layout Standard + + +\family typewriter +fperez[~/test]|7> $astr = ls *s.py +\newline +fperez[~/test]|8> astr +\newline + +\begin_inset ERT +status Collapsed + +\layout Standard + +\backslash +hspace*{0mm} +\end_inset + +\SpecialChar ~ +\SpecialChar ~ +\SpecialChar ~ +\SpecialChar ~ +\SpecialChar ~ +\SpecialChar ~ +\SpecialChar ~ +\SpecialChar ~ +\SpecialChar ~ +\SpecialChar ~ +\SpecialChar ~ +\SpecialChar ~ +\SpecialChar ~ +\SpecialChar ~ +<8> 'scopes.py +\backslash +nstrings.py' +\layout Standard + + +\family typewriter +fperez[~/test]|9> $$alist = ls *s.py +\newline +fperez[~/test]|10> alist +\newline + +\begin_inset ERT +status Collapsed + +\layout Standard + +\backslash +hspace*{0mm} +\end_inset + +\SpecialChar ~ +\SpecialChar ~ +\SpecialChar ~ +\SpecialChar ~ +\SpecialChar ~ +\SpecialChar ~ +\SpecialChar ~ +\SpecialChar ~ +\SpecialChar ~ +\SpecialChar ~ +\SpecialChar ~ +\SpecialChar ~ +\SpecialChar ~ +\SpecialChar ~ +<10> ['scopes.py', 'strings.py'] +\layout Standard + +alist is now a normal python list you can loop over. + Using +\family typewriter +$ +\family default + will expand back the python values when alias calls are made: +\layout Standard + + +\family typewriter +fperez[~/test]|11> for f in alist: +\newline + +\begin_inset ERT +status Collapsed + +\layout Standard + +\backslash +hspace*{0mm} +\end_inset + +\SpecialChar ~ +\SpecialChar ~ +\SpecialChar ~ +\SpecialChar ~ +\SpecialChar ~ +\SpecialChar ~ +\SpecialChar ~ +\SpecialChar ~ +\SpecialChar ~ +\SpecialChar ~ +\SpecialChar ~ +\SpecialChar ~ +\SpecialChar ~ +\SpecialChar ~ +|..> \SpecialChar ~ +\SpecialChar ~ +\SpecialChar ~ +\SpecialChar ~ +print 'file',f, +\newline + +\begin_inset ERT +status Collapsed + +\layout Standard + +\backslash +hspace*{0mm} +\end_inset + +\SpecialChar ~ +\SpecialChar ~ +\SpecialChar ~ +\SpecialChar ~ +\SpecialChar ~ +\SpecialChar ~ +\SpecialChar ~ +\SpecialChar ~ +\SpecialChar ~ +\SpecialChar ~ +\SpecialChar ~ +\SpecialChar ~ +\SpecialChar ~ +\SpecialChar ~ +|..> \SpecialChar ~ +\SpecialChar ~ +\SpecialChar ~ +\SpecialChar ~ +wc -l $f +\newline + +\begin_inset ERT +status Collapsed + +\layout Standard + +\backslash +hspace*{0mm} +\end_inset + +\SpecialChar ~ +\SpecialChar ~ +\SpecialChar ~ +\SpecialChar ~ +\SpecialChar ~ +\SpecialChar ~ +\SpecialChar ~ +\SpecialChar ~ +\SpecialChar ~ +\SpecialChar ~ +\SpecialChar ~ +\SpecialChar ~ +\SpecialChar ~ +\SpecialChar ~ +|..> +\newline +file scopes.py 13 scopes.py +\newline +file strings.py 4 strings.py +\layout Standard + +Note that you may need to protect your variables with braces if you want + to append strings to their names. + To copy all files in alist to +\family typewriter +.bak +\family default + extensions, you must use: +\layout Standard + + +\family typewriter +fperez[~/test]|12> for f in alist: +\newline + +\begin_inset ERT +status Collapsed + +\layout Standard + +\backslash +hspace*{0mm} +\end_inset + +\SpecialChar ~ +\SpecialChar ~ +\SpecialChar ~ +\SpecialChar ~ +\SpecialChar ~ +\SpecialChar ~ +\SpecialChar ~ +\SpecialChar ~ +\SpecialChar ~ +\SpecialChar ~ +\SpecialChar ~ +\SpecialChar ~ +\SpecialChar ~ +\SpecialChar ~ +|..> \SpecialChar ~ +\SpecialChar ~ +\SpecialChar ~ +\SpecialChar ~ +cp $f ${f}.bak +\layout Standard + +If you try using +\family typewriter +$f.bak +\family default +, you'll get an AttributeError exception saying that your string object + doesn't have a +\family typewriter +.bak +\family default + attribute. + This is because the +\family typewriter +$ +\family default + expansion mechanism allows you to expand full Python expressions: +\layout Standard + + +\family typewriter +fperez[~/test]|13> echo "sys.platform is: $sys.platform" +\newline +sys.platform is: linux2 +\layout Standard + +IPython's input history handling is still active, which allows you to rerun + a single block of multi-line input by simply using exec: +\newline + +\family typewriter +fperez[~/test]|14> $$alist = ls *.eps +\newline +fperez[~/test]|15> exec _i11 +\newline +file image2.eps 921 image2.eps +\newline +file image.eps 921 image.eps +\layout Standard + +While these are new special-case syntaxes, they are designed to allow very + efficient use of the shell with minimal typing. + At an interactive shell prompt, conciseness of expression wins over readability. +\layout Subsection + +Useful functions and modules +\layout Standard + +The os, sys and shutil modules from the Python standard library are automaticall +y loaded. + Some additional functions, useful for shell usage, are listed below. + You can request more help about them with ` +\family typewriter +? +\family default +'. +\layout Description + + +\family typewriter +shell +\family default + - execute a command in the underlying system shell +\layout Description + + +\family typewriter +system +\family default + - like +\family typewriter +shell() +\family default +, but return the exit status of the command +\layout Description + + +\family typewriter +sout +\family default + - capture the output of a command as a string +\layout Description + + +\family typewriter +lout +\family default + - capture the output of a command as a list (split on ` +\backslash +n') +\layout Description + + +\family typewriter +getoutputerror +\family default + - capture (output,error) of a shell commandss +\layout Standard + + +\family typewriter +sout +\family default +/ +\family typewriter +lout +\family default + are the functional equivalents of +\family typewriter +$ +\family default +/ +\family typewriter +$$ +\family default +. + They are provided to allow you to capture system output in the middle of + true python code, function definitions, etc (where +\family typewriter +$ +\family default + and +\family typewriter +$$ +\family default + are invalid). +\layout Subsection + +Directory management +\layout Standard + +Since each command passed by pysh to the underlying system is executed in + a subshell which exits immediately, you can NOT use !cd to navigate the + filesystem. +\layout Standard + +Pysh provides its own builtin +\family typewriter +`%cd +\family default +' magic command to move in the filesystem (the +\family typewriter +% +\family default + is not required with automagic on). + It also maintains a list of visited directories (use +\family typewriter +%dhist +\family default + to see it) and allows direct switching to any of them. + Type +\family typewriter +`cd? +\family default +' for more details. +\layout Standard + + +\family typewriter +%pushd +\family default +, +\family typewriter +%popd +\family default + and +\family typewriter +%dirs +\family default + are provided for directory stack handling. +\layout Subsection + +Prompt customization +\layout Standard + +The supplied +\family typewriter +ipythonrc-pysh +\family default + profile comes with an example of a very colored and detailed prompt, mainly + to serve as an illustration. + The valid escape sequences, besides color names, are: +\layout Description + + +\backslash +# - Prompt number. +\layout Description + + +\backslash +D - Dots, as many as there are digits in +\backslash +# (so they align). +\layout Description + + +\backslash +w - Current working directory (cwd). +\layout Description + + +\backslash +W - Basename of current working directory. +\layout Description + + +\backslash +X +\emph on +N +\emph default + - Where +\emph on +N +\emph default +=0..5. + N terms of the cwd, with $HOME written as ~. +\layout Description + + +\backslash +Y +\emph on +N +\emph default + - Where +\emph on +N +\emph default +=0..5. + Like X +\emph on +N +\emph default +, but if ~ is term +\emph on +N +\emph default ++1 it's also shown. +\layout Description + + +\backslash +u - Username. +\layout Description + + +\backslash +H - Full hostname. +\layout Description + + +\backslash +h - Hostname up to first '.' +\layout Description + + +\backslash +$ - Root symbol ($ or #). + +\layout Description + + +\backslash +t - Current time, in H:M:S format. +\layout Description + + +\backslash +v - IPython release version. + +\layout Description + + +\backslash +n - Newline. + +\layout Description + + +\backslash +r - Carriage return. + +\layout Description + + +\backslash + +\backslash + - An explicitly escaped ' +\backslash +'. +\layout Standard + +You can configure your prompt colors using any ANSI color escape. + Each color escape sets the color for any subsequent text, until another + escape comes in and changes things. + The valid color escapes are: +\layout Description + + +\backslash +C_Black +\layout Description + + +\backslash +C_Blue +\layout Description + + +\backslash +C_Brown +\layout Description + + +\backslash +C_Cyan +\layout Description + + +\backslash +C_DarkGray +\layout Description + + +\backslash +C_Green +\layout Description + + +\backslash +C_LightBlue +\layout Description + + +\backslash +C_LightCyan +\layout Description + + +\backslash +C_LightGray +\layout Description + + +\backslash +C_LightGreen +\layout Description + + +\backslash +C_LightPurple +\layout Description + + +\backslash +C_LightRed +\layout Description + + +\backslash +C_Purple +\layout Description + + +\backslash +C_Red +\layout Description + + +\backslash +C_White +\layout Description + + +\backslash +C_Yellow +\layout Description + + +\backslash +C_Normal Stop coloring, defaults to your terminal settings. +\layout Section + + +\begin_inset LatexCommand \label{sec:Threading-support} + +\end_inset + +Threading support +\layout Standard + + +\series bold +WARNING: +\series default +The threading support is still somewhat experimental, and it has only seen + reasonable testing under Linux. + Threaded code is particularly tricky to debug, and it tends to show extremely + platform-dependent behavior. + Since I only have access to Linux machines, I will have to rely on user's + experiences and assistance for this area of IPython to improve under other + platforms. +\layout Standard + +IPython, via the +\family typewriter +-gthread +\family default + and +\family typewriter +-wthread +\family default + options (described in Sec.\SpecialChar ~ + +\begin_inset LatexCommand \ref{sec:threading-opts} + +\end_inset + +), can run in multithreaded mode to support pyGTK and WXPython applications + respectively. + Both of these GUI toolkits need to control the python main loop of execution, + so under a normal Python interpreter, starting a pyGTK (or WXPython) applicatio +n will immediately freeze the shell. + +\layout Standard + +IPython, with one of these options (you can only use one at a time), separates + the graphical loop and IPython's code execution run into different threads. + This allows you to test interactively (with +\family typewriter +%run +\family default +, for example) your GUI code without blocking. +\layout Subsection + +Tk issues +\layout Standard + +As indicated in Sec.\SpecialChar ~ + +\begin_inset LatexCommand \ref{sec:threading-opts} + +\end_inset + +, a special +\family typewriter +-tk +\family default + option is provided to try and allow Tk graphical applications to coexist + interactively with WX or GTK ones. + Whether this works at all, however, is very platform and configuration + dependent. + Please experiment with simple test cases before committing to using this + combination of Tk and WX/GTK threading in a production environment. +\layout Subsection + +Signals and Threads +\layout Standard + +When any of the thread systems (WX or GTK) are active, either directly or + via +\family typewriter +-pylab +\family default + with a threaded backend, it is impossible to interrupt long-running Python + code via +\family typewriter +Ctrl-C +\family default +. + IPython can not pass the KeyboardInterrupt exception (or the underlying + +\family typewriter +SIGINT +\family default +) across threads, so any long-running process started from IPython will + run to completion, or will have to be killed via an external (OS-based) + mechanism. +\layout Standard + +To the best of my knowledge, this limitation is imposed by the Python interprete +r itself, and it comes from the difficulty of writing portable signal/threaded + code. + If any user is an expert on this topic and can suggest a better solution, + I would love to hear about it. + In the IPython sources, look at the +\family typewriter +Shell.py +\family default + module, and in particular at the +\family typewriter +runcode() +\family default + method. + +\layout Subsection + +I/O pitfalls +\layout Standard + +Be mindful that the Python interpreter switches between threads every +\begin_inset Formula $N$ +\end_inset + + bytecodes, where the default value as of Python\SpecialChar ~ +2.3 is +\begin_inset Formula $N=100.$ +\end_inset + + This value can be read by using the +\family typewriter +sys.getcheckinterval() +\family default + function, and it can be reset via +\family typewriter +sys.setcheckinterval( +\emph on +N +\emph default +) +\family default +. + This switching of threads can cause subtly confusing effects if one of + your threads is doing file I/O. + In text mode, most systems only flush file buffers when they encounter + a +\family typewriter +` +\backslash +n' +\family default +. + An instruction as simple as +\family typewriter + +\newline +\SpecialChar ~ +\SpecialChar ~ +print >> filehandle, +\begin_inset Quotes eld +\end_inset + +hello world +\begin_inset Quotes erd +\end_inset + + +\family default + +\newline +actually consists of several bytecodes, so it is possible that the newline + does not reach your file before the next thread switch. + Similarly, if you are writing to a file in binary mode, the file won't + be flushed until the buffer fills, and your other thread may see apparently + truncated files. + +\layout Standard + +For this reason, if you are using IPython's thread support and have (for + example) a GUI application which will read data generated by files written + to from the IPython thread, the safest approach is to open all of your + files in unbuffered mode (the third argument to the +\family typewriter +file/open +\family default + function is the buffering value): +\newline + +\family typewriter +\SpecialChar ~ +\SpecialChar ~ +filehandle = open(filename,mode,0) +\layout Standard + +This is obviously a brute force way of avoiding race conditions with the + file buffering. + If you want to do it cleanly, and you have a resource which is being shared + by the interactive IPython loop and your GUI thread, you should really + handle it with thread locking and syncrhonization properties. + The Python documentation discusses these. +\layout Section + + +\begin_inset LatexCommand \label{sec:matplotlib-support} + +\end_inset + +Plotting with +\family typewriter +matplotlib +\family default + +\layout Standard + +The matplotlib library ( +\begin_inset LatexCommand \htmlurl[http://matplotlib.sourceforge.net]{http://matplotlib.sourceforge.net} + +\end_inset + +) provides high quality 2D plotting for Python. + Matplotlib can produce plots on screen using a variety of GUI toolkits, + including Tk, GTK and WXPython. + It also provides a number of commands useful for scientific computing, + all with a syntax compatible with that of the popular Matlab program. +\layout Standard + +IPython accepts the special option +\family typewriter +-pylab +\family default + (Sec.\SpecialChar ~ + +\begin_inset LatexCommand \ref{sec:cmd-line-opts} + +\end_inset + +). + This configures it to support matplotlib, honoring the settings in the + +\family typewriter +.matplotlibrc +\family default + file. + IPython will detect the user's choice of matplotlib GUI backend, and automatica +lly select the proper threading model to prevent blocking. + It also sets matplotlib in interactive mode and modifies +\family typewriter +%run +\family default + slightly, so that any matplotlib-based script can be executed using +\family typewriter +%run +\family default + and the final +\family typewriter +show() +\family default + command does not block the interactive shell. +\layout Standard + +The +\family typewriter +-pylab +\family default + option must be given first in order for IPython to configure its threading + mode. + However, you can still issue other options afterwards. + This allows you to have a matplotlib-based environment customized with + additional modules using the standard IPython profile mechanism (Sec.\SpecialChar ~ + +\begin_inset LatexCommand \ref{sec:profiles} + +\end_inset + +): `` +\family typewriter +ipython -pylab -p myprofile +\family default +'' will load the profile defined in +\family typewriter +ipythonrc-myprofile +\family default + after configuring matplotlib. +\layout Section + + +\begin_inset LatexCommand \label{sec:Gnuplot} + +\end_inset + +Plotting with +\family typewriter +Gnuplot +\layout Standard + +Through the magic extension system described in sec. + +\begin_inset LatexCommand \ref{sec:magic} + +\end_inset + +, IPython incorporates a mechanism for conveniently interfacing with the + Gnuplot system ( +\begin_inset LatexCommand \htmlurl{http://www.gnuplot.info} + +\end_inset + +). + Gnuplot is a very complete 2D and 3D plotting package available for many + operating systems and commonly included in modern Linux distributions. + +\layout Standard + +Besides having Gnuplot installed, this functionality requires the +\family typewriter +Gnuplot.py +\family default + module for interfacing python with Gnuplot. + It can be downloaded from: +\begin_inset LatexCommand \htmlurl{http://gnuplot-py.sourceforge.net} + +\end_inset + +. +\layout Subsection + +Proper Gnuplot configuration +\layout Standard + +As of version 4.0, Gnuplot has excellent mouse and interactive keyboard support. + However, as of +\family typewriter +Gnuplot.py +\family default + version 1.7, a new option was added to communicate between Python and Gnuplot + via FIFOs (pipes). + This mechanism, while fast, also breaks the mouse system. + You must therefore set the variable +\family typewriter +prefer_fifo_data +\family default + to +\family typewriter +0 +\family default + in file +\family typewriter +gp_unix.py +\family default + if you wish to keep the interactive mouse and keyboard features working + properly ( +\family typewriter +prefer_inline_data +\family default + also must be +\family typewriter +0 +\family default +, but this is the default so unless you've changed it manually you should + be fine). +\layout Standard + +'Out of the box', Gnuplot is configured with a rather poor set of size, + color and linewidth choices which make the graphs fairly hard to read on + modern high-resolution displays (although they work fine on old 640x480 + ones). + Below is a section of my +\family typewriter +.Xdefaults +\family default + file which I use for having a more convenient Gnuplot setup. + Remember to load it by running +\family typewriter +`xrdb .Xdefaults` +\family default +: +\layout Standard + + +\family typewriter +!****************************************************************** +\newline +! gnuplot options +\newline +! modify this for a convenient window size +\newline +gnuplot*geometry: 780x580 +\layout Standard + + +\family typewriter +! on-screen font (not for PostScript) +\newline +gnuplot*font: -misc-fixed-bold-r-normal--15-120-100-100-c-90-iso8859-1 +\layout Standard + + +\family typewriter +! color options +\newline +gnuplot*background: black +\newline +gnuplot*textColor: white +\newline +gnuplot*borderColor: white +\newline +gnuplot*axisColor: white +\newline +gnuplot*line1Color: red +\newline +gnuplot*line2Color: green +\newline +gnuplot*line3Color: blue +\newline +gnuplot*line4Color: magenta +\newline +gnuplot*line5Color: cyan +\newline +gnuplot*line6Color: sienna +\newline +gnuplot*line7Color: orange +\newline +gnuplot*line8Color: coral +\layout Standard + + +\family typewriter +! multiplicative factor for point styles +\newline +gnuplot*pointsize: 2 +\layout Standard + + +\family typewriter +! line width options (in pixels) +\newline +gnuplot*borderWidth: 2 +\newline +gnuplot*axisWidth: 2 +\newline +gnuplot*line1Width: 2 +\newline +gnuplot*line2Width: 2 +\newline +gnuplot*line3Width: 2 +\newline +gnuplot*line4Width: 2 +\newline +gnuplot*line5Width: 2 +\newline +gnuplot*line6Width: 2 +\newline +gnuplot*line7Width: 2 +\newline +gnuplot*line8Width: 2 +\layout Subsection + +The +\family typewriter +IPython.GnuplotRuntime +\family default + module +\layout Standard + +IPython includes a module called +\family typewriter +Gnuplot2.py +\family default + which extends and improves the default +\family typewriter +Gnuplot +\family default +. +\family typewriter +py +\family default + (which it still relies upon). + For example, the new +\family typewriter +plot +\family default + function adds several improvements to the original making it more convenient + for interactive use, and +\family typewriter +hardcopy +\family default + fixes a bug in the original which under some circumstances blocks the creation + of PostScript output. +\layout Standard + +For scripting use, +\family typewriter +GnuplotRuntime.py +\family default + is provided, which wraps +\family typewriter +Gnuplot2.py +\family default + and creates a series of global aliases. + These make it easy to control Gnuplot plotting jobs through the Python + language. +\layout Standard + +Below is some example code which illustrates how to configure Gnuplot inside + your own programs but have it available for further interactive use through + an embedded IPython instance. + Simply run this file at a system prompt. + This file is provided as +\family typewriter +example-gnuplot.py +\family default + in the examples directory: +\layout Standard + + +\begin_inset Include \verbatiminput{examples/example-gnuplot.py} +preview false + +\end_inset + + +\layout Subsection + +The +\family typewriter +numeric +\family default + profile: a scientific computing environment +\layout Standard + +The +\family typewriter +numeric +\family default + IPython profile, which you can activate with +\family typewriter +`ipython -p numeric +\family default +' will automatically load the IPython Gnuplot extensions (plus Numeric and + other useful things for numerical computing), contained in the +\family typewriter +IPython.GnuplotInteractive +\family default + module. + This will create the globals +\family typewriter +Gnuplot +\family default +(an alias to the improved Gnuplot2 module), +\family typewriter +gp +\family default + (a Gnuplot active instance), the new magic commands +\family typewriter +%gpc +\family default + and +\family typewriter +%gp_set_instance +\family default + and several other convenient globals. + Type +\family typewriter +gphelp() +\family default + for further details. +\layout Standard + +This should turn IPython into a convenient environment for numerical computing, + with all the functions in the NumPy library and the Gnuplot facilities + for plotting. + Further improvements can be obtained by loading the SciPy libraries for + scientific computing, available at +\begin_inset LatexCommand \htmlurl{http://scipy.org} + +\end_inset + +. +\layout Standard + +If you are in the middle of a working session with numerical objects and + need to plot them but you didn't start the +\family typewriter +numeric +\family default + profile, you can load these extensions at any time by typing +\newline + +\family typewriter +from IPython.GnuplotInteractive import * +\newline + +\family default +at the IPython prompt. + This will allow you to keep your objects intact and start using Gnuplot + to view them. +\layout Section + +Reporting bugs +\layout Subsection* + +Automatic crash reports +\layout Standard + +Ideally, IPython itself shouldn't crash. + It will catch exceptions produced by you, but bugs in its internals will + still crash it. +\layout Standard + +In such a situation, IPython will leave a file named +\family typewriter +IPython_crash_report.txt +\family default + in your IPYTHONDIR directory (that way if crashes happen several times + it won't litter many directories, the post-mortem file is always located + in the same place and new occurrences just overwrite the previous one). + If you can mail this file to the developers (see sec. + +\begin_inset LatexCommand \ref{sec:credits} + +\end_inset + + for names and addresses), it will help us +\emph on +a lot +\emph default + in understanding the cause of the problem and fixing it sooner. +\layout Subsection* + +The bug tracker +\layout Standard + +IPython also has an online bug-tracker, located at +\begin_inset LatexCommand \htmlurl{http://www.scipy.net/roundup/ipython} + +\end_inset + +. + In addition to mailing the developers, it would be a good idea to file + a bug report here. + This will ensure that the issue is properly followed to conclusion. +\layout Standard + +You can also use this bug tracker to file feature requests. +\layout Section + +Brief history +\layout Subsection + +Origins +\layout Standard + +The current IPython system grew out of the following three projects: +\layout List +\labelwidthstring 00.00.0000 + +ipython by Fernando P�rez. + I was working on adding Mathematica-type prompts and a flexible configuration + system (something better than +\family typewriter +$PYTHONSTARTUP +\family default +) to the standard Python interactive interpreter. +\layout List +\labelwidthstring 00.00.0000 + +IPP by Janko Hauser. + Very well organized, great usability. + Had an old help system. + IPP was used as the `container' code into which I added the functionality + from ipython and LazyPython. +\layout List +\labelwidthstring 00.00.0000 + +LazyPython by Nathan Gray. + Simple but +\emph on +very +\emph default + powerful. + The quick syntax (auto parens, auto quotes) and verbose/colored tracebacks + were all taken from here. +\layout Standard + +When I found out (see sec. + +\begin_inset LatexCommand \ref{figgins} + +\end_inset + +) about IPP and LazyPython I tried to join all three into a unified system. + I thought this could provide a very nice working environment, both for + regular programming and scientific computing: shell-like features, IDL/Matlab + numerics, Mathematica-type prompt history and great object introspection + and help facilities. + I think it worked reasonably well, though it was a lot more work than I + had initially planned. +\layout Subsection + +Current status +\layout Standard + +The above listed features work, and quite well for the most part. + But until a major internal restructuring is done (see below), only bug + fixing will be done, no other features will be added (unless very minor + and well localized in the cleaner parts of the code). +\layout Standard + +IPython consists of some 12000 lines of pure python code, of which roughly + 50% are fairly clean. + The other 50% are fragile, messy code which needs a massive restructuring + before any further major work is done. + Even the messy code is fairly well documented though, and most of the problems + in the (non-existent) class design are well pointed to by a PyChecker run. + So the rewriting work isn't that bad, it will just be time-consuming. +\layout Subsection + +Future +\layout Standard + +See the separate +\family typewriter +new_design +\family default + document for details. + Ultimately, I would like to see IPython become part of the standard Python + distribution as a `big brother with batteries' to the standard Python interacti +ve interpreter. + But that will never happen with the current state of the code, so all contribut +ions are welcome. +\layout Section + +License +\layout Standard + +IPython is released under the terms of the BSD license, whose general form + can be found at: +\begin_inset LatexCommand \htmlurl{http://www.opensource.org/licenses/bsd-license.php} + +\end_inset + +. + The full text of the IPython license is reproduced below: +\layout Quote + + +\family typewriter +\size small +IPython is released under a BSD-type license. +\layout Quote + + +\family typewriter +\size small +Copyright (c) 2001, 2002, 2003, 2004 Fernando Perez <fperez@colorado.edu>. +\layout Quote + + +\family typewriter +\size small +Copyright (c) 2001 Janko Hauser <jhauser@zscout.de> and +\newline +Nathaniel Gray <n8gray@caltech.edu>. +\layout Quote + + +\family typewriter +\size small +All rights reserved. +\layout Quote + + +\family typewriter +\size small +Redistribution and use in source and binary forms, with or without modification, + are permitted provided that the following conditions are met: +\layout Quote + + +\family typewriter +\size small +a. + Redistributions of source code must retain the above copyright notice, + this list of conditions and the following disclaimer. +\layout Quote + + +\family typewriter +\size small +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. +\layout Quote + + +\family typewriter +\size small +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. +\layout Quote + + +\family typewriter +\size small +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. + +\layout Standard + +Individual authors are the holders of the copyright for their code and are + listed in each file. +\layout Standard + +Some files ( +\family typewriter +DPyGetOpt.py +\family default +, for example) may be licensed under different conditions. + Ultimately each file indicates clearly the conditions under which its author/au +thors have decided to publish the code. +\layout Standard + +Versions of IPython up to and including 0.6.3 were released under the GNU + Lesser General Public License (LGPL), available at +\begin_inset LatexCommand \htmlurl{http://www.gnu.org/copyleft/lesser.html} + +\end_inset + +. +\layout Section + + +\begin_inset LatexCommand \label{sec:credits} + +\end_inset + +Credits +\layout Standard + +IPython is mainly developed by Fernando P�rez +\family typewriter +<fperez@colorado.edu> +\family default +, but the project was born from mixing in Fernando's code with the IPP project + by Janko Hauser +\family typewriter +<jhauser-AT-zscout.de> +\family default + and LazyPython by Nathan Gray +\family typewriter +<n8gray-AT-caltech.edu> +\family default +. + For all IPython-related requests, please contact Fernando. + User or development help should be requested via the IPython mailing lists: +\layout Description + +User\SpecialChar ~ +list: +\begin_inset LatexCommand \htmlurl{http://scipy.net/mailman/listinfo/ipython-user} + +\end_inset + + +\layout Description + +Developer's\SpecialChar ~ +list: +\begin_inset LatexCommand \htmlurl{http://scipy.net/mailman/listinfo/ipython-dev} + +\end_inset + + +\layout Standard + +The IPython project is also very grateful to +\begin_inset Foot +collapsed true + +\layout Standard + +I've mangled email addresses to reduce spam, since the IPython manuals can + be accessed online. +\end_inset + +: +\layout Standard + +Bill Bumgarner +\family typewriter +<bbum-AT-friday.com> +\family default +: for providing the DPyGetOpt module which gives very powerful and convenient + handling of command-line options (light years ahead of what Python 2.1.1's + getopt module does). +\layout Standard + +Ka-Ping Yee +\family typewriter +<ping-AT-lfw.org> +\family default +: for providing the Itpl module for convenient and powerful string interpolation + with a much nicer syntax than formatting through the '%' operator. +\layout Standard + +Arnd B�cker +\family typewriter +<baecker-AT-physik.tu-dresden.de> +\family default +: for his many very useful suggestions and comments, and lots of help with + testing and documentation checking. + Many of IPython's newer features are a result of discussions with him (bugs + are still my fault, not his). +\layout Standard + +Obviously Guido van\SpecialChar ~ +Rossum and the whole Python development team, that goes + without saying. +\layout Standard + +IPython's website is generously hosted at +\begin_inset LatexCommand \htmlurl{http://ipython.scipy.org} + +\end_inset + + by Enthought ( +\begin_inset LatexCommand \htmlurl{http://www.enthought.com} + +\end_inset + +). + I am very grateful to them and all of the SciPy team for their contribution. +\layout Standard + + +\begin_inset LatexCommand \label{figgins} + +\end_inset + +Fernando would also like to thank Stephen Figgins +\family typewriter +<fig-AT-monitor.net> +\family default +, an O'Reilly Python editor. + His Oct/11/2001 article about IPP and LazyPython, was what got this project + started. + You can read it at: +\begin_inset LatexCommand \htmlurl{http://www.onlamp.com/pub/a/python/2001/10/11/pythonnews.html} + +\end_inset + +. +\layout Standard + +And last but not least, all the kind IPython users who have emailed new + code, bug reports, fixes, comments and ideas. + A brief list follows, please let me know if I have ommitted your name by + accident: +\layout List +\labelwidthstring 00.00.0000 + +Jack\SpecialChar ~ +Moffit +\family typewriter +<jack-AT-xiph.org> +\family default + Bug fixes, including the infamous color problem. + This bug alone caused many lost hours and frustration, many thanks to him + for the fix. + I've always been a fan of Ogg & friends, now I have one more reason to + like these folks. +\newline +Jack is also contributing with Debian packaging and many other things. +\layout List +\labelwidthstring 00.00.0000 + +Alexander\SpecialChar ~ +Schmolck +\family typewriter +<a.schmolck-AT-gmx.net> +\family default +Emacs work, bug reports, bug fixes, ideas, lots more. + The ipython.el mode for (X)Emacs is Alex's code, providing full support + for IPython under (X)Emacs. +\layout List +\labelwidthstring 00.00.0000 + +Andrea\SpecialChar ~ +Riciputi +\family typewriter +<andrea.riciputi-AT-libero.it> +\family default + Mac OSX information, Fink package management. +\layout List +\labelwidthstring 00.00.0000 + +Gary\SpecialChar ~ +Bishop +\family typewriter +<gb-AT-cs.unc.edu> +\family default + Bug reports, and patches to work around the exception handling idiosyncracies + of WxPython. + Readline and color support for Windows. +\layout List +\labelwidthstring 00.00.0000 + +Jeffrey\SpecialChar ~ +Collins +\family typewriter +<Jeff.Collins-AT-vexcel.com> +\family default + Bug reports. + Much improved readline support, including fixes for Python 2.3. +\layout List +\labelwidthstring 00.00.0000 + +Dryice\SpecialChar ~ +Liu +\family typewriter +<dryice-AT-liu.com.cn> +\family default + FreeBSD port. +\layout List +\labelwidthstring 00.00.0000 + +Mike\SpecialChar ~ +Heeter +\family typewriter +<korora-AT-SDF.LONESTAR.ORG> +\layout List +\labelwidthstring 00.00.0000 + +Christopher\SpecialChar ~ +Hart +\family typewriter +<hart-AT-caltech.edu> +\family default + PDB integration. +\layout List +\labelwidthstring 00.00.0000 + +Milan\SpecialChar ~ +Zamazal +\family typewriter +<pdm-AT-zamazal.org> +\family default + Emacs info. +\layout List +\labelwidthstring 00.00.0000 + +Philip\SpecialChar ~ +Hisley +\family typewriter +<compsys-AT-starpower.net> +\layout List +\labelwidthstring 00.00.0000 + +Holger\SpecialChar ~ +Krekel +\family typewriter +<pyth-AT-devel.trillke.net> +\family default + Tab completion, lots more. +\layout List +\labelwidthstring 00.00.0000 + +Robin\SpecialChar ~ +Siebler +\family typewriter +<robinsiebler-AT-starband.net> +\layout List +\labelwidthstring 00.00.0000 + +Ralf\SpecialChar ~ +Ahlbrink +\family typewriter + <ralf_ahlbrink-AT-web.de> +\layout List +\labelwidthstring 00.00.0000 + +Thorsten\SpecialChar ~ +Kampe +\family typewriter +<thorsten-AT-thorstenkampe.de> +\layout List +\labelwidthstring 00.00.0000 + +Fredrik\SpecialChar ~ +Kant +\family typewriter +<fredrik.kant-AT-front.com> +\family default + Windows setup. +\layout List +\labelwidthstring 00.00.0000 + +Syver\SpecialChar ~ +Enstad +\family typewriter +<syver-en-AT-online.no> +\family default + Windows setup. +\layout List +\labelwidthstring 00.00.0000 + +Richard +\family typewriter +<rxe-AT-renre-europe.com> +\family default + Global embedding. +\layout List +\labelwidthstring 00.00.0000 + +Hayden\SpecialChar ~ +Callow +\family typewriter +<h.callow-AT-elec.canterbury.ac.nz> +\family default + Gnuplot.py 1.6 compatibility. +\layout List +\labelwidthstring 00.00.0000 + +Leonardo\SpecialChar ~ +Santagada +\family typewriter +<retype-AT-terra.com.br> +\family default + Fixes for Windows installation. +\layout List +\labelwidthstring 00.00.0000 + +Christopher\SpecialChar ~ +Armstrong +\family typewriter +<radix-AT-twistedmatrix.com> +\family default + Bugfixes. +\layout List +\labelwidthstring 00.00.0000 + +Francois\SpecialChar ~ +Pinard +\family typewriter +<pinard-AT-iro.umontreal.ca> +\family default + Code and documentation fixes. +\layout List +\labelwidthstring 00.00.0000 + +Cory\SpecialChar ~ +Dodt +\family typewriter +<cdodt-AT-fcoe.k12.ca.us> +\family default + Bug reports and Windows ideas. + Patches for Windows installer. +\layout List +\labelwidthstring 00.00.0000 + +Olivier\SpecialChar ~ +Aubert +\family typewriter +<oaubert-AT-bat710.univ-lyon1.fr> +\family default + New magics. +\layout List +\labelwidthstring 00.00.0000 + +King\SpecialChar ~ +C.\SpecialChar ~ +Shu +\family typewriter +<kingshu-AT-myrealbox.com> +\family default + Autoindent patch. +\layout List +\labelwidthstring 00.00.0000 + +Chris\SpecialChar ~ +Drexler +\family typewriter +<chris-AT-ac-drexler.de> +\family default + Readline packages for Win32/CygWin. +\layout List +\labelwidthstring 00.00.0000 + +Gustavo\SpecialChar ~ +C�rdova\SpecialChar ~ +Avila +\family typewriter +<gcordova-AT-sismex.com> +\family default + EvalDict code for nice, lightweight string interpolation. +\layout List +\labelwidthstring 00.00.0000 + +Kasper\SpecialChar ~ +Souren +\family typewriter +<Kasper.Souren-AT-ircam.fr> +\family default + Bug reports, ideas. +\layout List +\labelwidthstring 00.00.0000 + +Gever\SpecialChar ~ +Tulley +\family typewriter +<gever-AT-helium.com> +\family default + Code contributions. +\layout List +\labelwidthstring 00.00.0000 + +Ralf\SpecialChar ~ +Schmitt +\family typewriter +<ralf-AT-brainbot.com> +\family default + Bug reports & fixes. +\layout List +\labelwidthstring 00.00.0000 + +Oliver\SpecialChar ~ +Sander +\family typewriter +<osander-AT-gmx.de> +\family default + Bug reports. +\layout List +\labelwidthstring 00.00.0000 + +Rod\SpecialChar ~ +Holland +\family typewriter +<rhh-AT-structurelabs.com> +\family default + Bug reports and fixes to logging module. +\layout List +\labelwidthstring 00.00.0000 + +Daniel\SpecialChar ~ +'Dang'\SpecialChar ~ +Griffith +\family typewriter +<pythondev-dang-AT-lazytwinacres.net> +\family default + Fixes, enhancement suggestions for system shell use. +\layout List +\labelwidthstring 00.00.0000 + +Viktor\SpecialChar ~ +Ransmayr +\family typewriter +<viktor.ransmayr-AT-t-online.de> +\family default + Tests and reports on Windows installation issues. + Contributed a true Windows binary installer. +\layout List +\labelwidthstring 00.00.0000 + +Mike\SpecialChar ~ +Salib +\family typewriter +<msalib-AT-mit.edu> +\family default + Help fixing a subtle bug related to traceback printing. +\layout List +\labelwidthstring 00.00.0000 + +W.J.\SpecialChar ~ +van\SpecialChar ~ +der\SpecialChar ~ +Laan +\family typewriter +<gnufnork-AT-hetdigitalegat.nl> +\family default + Bash-like prompt specials. +\layout List +\labelwidthstring 00.00.0000 + +Ville\SpecialChar ~ +Vainio +\family typewriter +<vivainio-AT-kolumbus.fi> +\family default + Bugfixes and suggestions. + Excellent patches for many new features. +\layout List +\labelwidthstring 00.00.0000 + +Antoon\SpecialChar ~ +Pardon +\family typewriter +<Antoon.Pardon-AT-rece.vub.ac.be> +\family default + Critical fix for the multithreaded IPython. +\layout List +\labelwidthstring 00.00.0000 + +John\SpecialChar ~ +Hunter +\family typewriter +<jdhunter-AT-nitace.bsd.uchicago.edu> +\family default + Matplotlib author, helped with all the development of support for matplotlib + in IPyhton, including making necessary changes to matplotlib itself. +\layout List +\labelwidthstring 00.00.0000 + +Matthew\SpecialChar ~ +Arnison +\family typewriter +<maffew-AT-cat.org.au> +\family default + Bug reports, ` +\family typewriter +%run -d +\family default +' idea. +\layout List +\labelwidthstring 00.00.0000 + +Prabhu\SpecialChar ~ +Ramachandran +\family typewriter +<prabhu_r-AT-users.sourceforge.net> +\family default + Help with (X)Emacs support, threading patches, ideas... +\layout List +\labelwidthstring 00.00.0000 + +Norbert\SpecialChar ~ +Tretkowski +\family typewriter +<tretkowski-AT-inittab.de> +\family default + help with Debian packaging and distribution. +\layout List +\labelwidthstring 00.00.0000 + +Robert\SpecialChar ~ +Kern +\family typewriter +<rkern-AT-ucsd.edu> +\family default + help with OSX issues, much help in general with various Python topics, + especially related to scientific computing. +\layout List +\labelwidthstring 00.00.0000 + +George\SpecialChar ~ +Sakkis < +\family typewriter +gsakkis-AT-eden.rutgers.edu> +\family default + New matcher for tab-completing named arguments of user-defined functions. +\the_end diff --git a/doc/nbexample.py b/doc/nbexample.py new file mode 100644 index 0000000..7bc2727 --- /dev/null +++ b/doc/nbexample.py @@ -0,0 +1,11 @@ +from notebook.markup import rest + +rest.title('This is a Python Notebook') +rest.heading(1,'A first-level heading') +rest.text("""\ +Some plain text, without any special formatting. + +Below, we define a simple function to add two numbers.""") + +def add(x,y): + return x+y diff --git a/doc/nbexample_latex.py b/doc/nbexample_latex.py new file mode 100644 index 0000000..673cb4b --- /dev/null +++ b/doc/nbexample_latex.py @@ -0,0 +1,25 @@ +from notebook.markup import latex + +latex.document_class('article') +latex.title('This is a Python Notebook') + +latex.section('A section title',label='sec:intro') + +latex.text(r"""Below, we define a simple function +\begin{equation} +f: (x,y) \rightarrow x+y^2 +\end{equation}""") + +def f(x,y): + return x+y**2 + +# since the .text method passes directly to latex, all markup could be input +# in that way if so desired +latex.text(r""" +\section{Another section} + +More text... + +And now a picture showing our important results...""") + +latex.include_graphic('foo.png') diff --git a/doc/nbexample_output.py b/doc/nbexample_output.py new file mode 100644 index 0000000..8dfe099 --- /dev/null +++ b/doc/nbexample_output.py @@ -0,0 +1,20 @@ +from notebook.markup import rest + +rest.title('This is a Python Notebook') +rest.text("""\ +Some plain text, without any special formatting. + +Below, we define a simple function to add two numbers.""") + +def add(x,y): + return x+y + +rest.text("Let's use it with x=2,y=3:") +# This simply means that all code until the next markup call is to be executed +# as a single call. The editing screen should mark the whole group of lines +# with a single In[NN] tag (like IPython does, but with multi-line capabilities) +rest.input() +add(2,3) +# This output would appear on-screen (in the editing window) simply marked +# with an Out[NN] tag +rest.output("5") diff --git a/doc/new_design.lyx b/doc/new_design.lyx new file mode 100644 index 0000000..cb4a3a3 --- /dev/null +++ b/doc/new_design.lyx @@ -0,0 +1,1345 @@ +#LyX 1.3 created this file. For more info see http://www.lyx.org/ +\lyxformat 221 +\textclass article +\begin_preamble +\usepackage{ae,aecompl} +\usepackage{hyperref} +\usepackage{html} +\end_preamble +\language english +\inputencoding auto +\fontscheme default +\graphics default +\paperfontsize default +\spacing single +\papersize Default +\paperpackage a4 +\use_geometry 1 +\use_amsmath 0 +\use_natbib 0 +\use_numerical_citations 0 +\paperorientation portrait +\leftmargin 1.25in +\topmargin 1in +\rightmargin 1.25in +\bottommargin 1in +\secnumdepth 3 +\tocdepth 3 +\paragraph_separation skip +\defskip medskip +\quotes_language english +\quotes_times 2 +\papercolumns 1 +\papersides 1 +\paperpagestyle default + +\layout Title + +IPython +\newline + +\size larger +New design notes +\layout Author + +Fernando P�rez +\layout Section + +Introduction +\layout Standard + +This is a draft document with notes and ideas for the IPython rewrite. + The section order and structure of this document roughly reflects in which + order things should be done and what the dependencies are. + This document is mainly a draft for developers, a pdf version is provided + with the standard distribution in case regular users are interested and + wish to contribute ideas. +\layout Standard + +A tentative plan for the future: +\layout Itemize + +0.6.x series: in practice, enough people are using IPython for real work that + I think it warrants a higher number. + This series will continue to evolve with bugfixes and incremental improvements. +\layout Itemize + +0.7.x series: (maybe) If resources allow, there may be a branch for 'unstable' + development, where the architectural rewrite may take place. +\layout Standard + +However, I am starting to doubt it is feasible to keep two separate branches. + I am leaning more towards a +\begin_inset ERT +status Collapsed + +\layout Standard + +\backslash +LyX +\end_inset + +-like approach, where the main branch slowly transforms and evolves. + Having CVS support now makes this a reasonable alternative, as I don't + have to make pre-releases as often. + The active branch can remain the mainline of development, and users interested + in the bleeding-edge stuff can always grab the CVS code. +\layout Standard + +Ideally, IPython should have a clean class setup that would allow further + extensions for special-purpose systems. + I view IPython as a base system that provides a great interactive environment + with full access to the Python language, and which could be used in many + different contexts. + The basic hooks are there: the magic extension syntax and the flexible + system of recursive configuration files and profiles. + But with a code as messy as the current one, nobody is going to touch it. +\layout Section + +Immediate TODO and bug list +\layout Standard + +Things that should be done for the current series, before starting major + changes. +\layout Itemize + +Fix any bugs reported at the online bug tracker. +\layout Itemize + + +\series bold +Redesign the output traps. + +\series default + They cause problems when users try to execute code which relies on sys.stdout + being the 'true' sys.stdout. + They also prevent scripts which use raw_input() to work as command-line + arguments. +\newline +The best solution is probably to print the banner first, and then just execute + all the user code straight with no output traps at all. + Whatever comes out comes out. + This makes the ipython code actually simpler, and eliminates the problem + altogether. +\newline +These things need to be ripped out, they cause no end of problems. + For example, if user code requires acces to stdin during startup, the process + just hangs indefinitely. + For now I've just disabled them, and I'll live with the ugly error messages. +\layout Itemize + +The prompt specials dictionary should be turned into a class which does + proper namespace management, since the prompt specials need to be evaluated + in a certain namespace. + Currently it's just globals, which need to be managed manually by code + below. + +\layout Itemize + +Fix coloring of prompts: the pysh color strings don't have any effect on + prompt numbers, b/c these are controlled by the global scheme. + Make the prompts fully user-definable, colors and all. + This is what I said to a user: +\newline +As far as the green +\backslash +#, this is a minor bug of the coloring code due to the vagaries of history. + While the color strings allow you to control the coloring of most elements, + there are a few which are still controlled by the old ipython internal + coloring code, which only accepts a global 'color scheme' choice. + So basically the input/output numbers are hardwired to the choice in the + color scheme, and there are only 'Linux', 'LightBG' and 'NoColor' schemes + to choose from. + +\layout Itemize + +Clean up FakeModule issues. + Currently, unittesting with embedded ipython breaks because a FakeModule + instance overwrites __main__. + Maybe ipython should revert back to using __main__ directly as the user + namespace? Handling a separate namespace is proving +\emph on +very +\emph default + tricky in all corner cases. +\layout Itemize + +Make the output cache depth independent of the input one. + This way one can have say only the last 10 results stored and still have + a long input history/cache. +\layout Itemize + +Fix the fact that importing a shell for embedding screws up the command-line + history. + This can be done by not importing the history file when the shell is already + inside ipython. +\layout Itemize + +Lay out the class structure so that embedding into a gtk/wx/qt app is trivial, + much like the multithreaded gui shells now provide command-line coexistence + with the gui toolkits. + See +\begin_inset LatexCommand \url{http://www.livejournal.com/users/glyf/32396.html} + +\end_inset + + +\layout Itemize + +Get Holger's completer in, once he adds filename completion. +\layout Standard + +Lower priority stuff: +\layout Itemize + +Add @showopt/@setopt (decide name) for viewing/setting all options. + The existing option-setting magics should become aliases for setopt calls. +\layout Itemize + +It would be nice to be able to continue with python stuff after an @ command. + For instance "@run something; test_stuff()" in order to test stuff even + faster. + Suggestion by Kasper Souren <Kasper.Souren@ircam.fr> +\layout Itemize + +Run a 'first time wizard' which configures a few things for the user, such + as color_info, editor and the like. +\layout Itemize + +Logging: @logstart and -log should start logfiles in ~.ipython, but with + unique names in case of collisions. + This would prevent ipython.log files all over while also allowing multiple + sessions. + Also the -log option should take an optional filename, instead of having + a separate -logfile option. +\newline +In general the logging system needs a serious cleanup. + Many functions now in Magic should be moved to Logger, and the magic @s + should be very simple wrappers to the Logger methods. +\layout Section + +Lighten the code +\layout Standard + +If we decide to base future versions of IPython on Python 2.3, which has + the new Optik module (called optparse), it should be possible to drop DPyGetOpt. + We should also remove the need for Itpl. + Another area for trimming is the Gnuplot stuff: much of that could be merged + into the mainline project. +\layout Standard + +Double check whether we really need FlexCompleter. + This was written as an enhanced rlcompleter, but my patches went in for + python 2.2 (or 2.3, can't remember). +\layout Standard + +With these changes we could shed a fair bit of code from the main trunk. +\layout Section + +Unit testing +\layout Standard + +All new code should use a testing framework. + Python seems to have very good testing facilities, I just need to learn + how to use them. + I should also check out QMTest at +\begin_inset LatexCommand \htmlurl{http://www.codesourcery.com/qm/qmtest} + +\end_inset + +, it sounds interesting (it's Python-based too). +\layout Section + +Configuration system +\layout Standard + +Move away from the current ipythonrc format to using standard python files + for configuration. + This will require users to be slightly more careful in their syntax, but + reduces code in IPython, is more in line with Python's normal form (using + the $PYTHONSTARTUP file) and allows much more flexibility. + I also think it's more 'pythonic', in using a single language for everything. +\layout Standard + +Options can be set up with a function call which takes keywords and updates + the options Struct. +\layout Standard + +In order to maintain the recursive inclusion system, write an 'include' + function which is basically a wrapper around safe_execfile(). + Also for alias definitions an alias() function will do. + All functionality which we want to have at startup time for the users can + be wrapped in a small module so that config files look like: +\layout Standard + + +\family typewriter +from IPython.Startup import * +\newline +... +\newline +set_options(automagic=1,colors='NoColor',...) +\newline +... +\newline +include('mysetup.py') +\newline +... +\newline +alias('ls ls --color -l') +\newline +... + etc. +\layout Standard + +Also, put +\series bold +all +\series default + aliases in here, out of the core code. +\layout Standard + +The new system should allow for more seamless upgrading, so that: +\layout Itemize + +It automatically recognizes when the config files need updating and does + the upgrade. +\layout Itemize + +It simply adds the new options to the user's config file without overwriting + it. + The current system is annoying since users need to manually re-sync their + configuration after every update. +\layout Itemize + +It detects obsolete options and informs the user to remove them from his + config file. +\layout Standard + +Here's a copy of Arnd Baecker suggestions on the matter: +\layout Standard + +1.) upgrade: it might be nice to have an "auto" upgrade procedure: i.e. + imagine that IPython is installed system-wide and gets upgraded, how does + a user know, that an upgrade of the stuff in ~/.ipython is necessary ? So + maybe one has to a keep a version number in ~/.ipython and if there is a + mismatch with the started ipython, then invoke the upgrade procedure. +\layout Standard + +2.) upgrade: I find that replacing the old files in ~/.ipython (after copying + them to .old not optimal (for example, after every update, I have to change + my color settings (and some others) in ~/.ipython/ipthonrc). + So somehow keeping the old files and merging the new features would be + nice. + (but how to distinguish changes from version to version with changes made + by the user ?) For, example, I would have to change in GnuplotMagic.py gnuplot_m +ouse to 1 after every upgrade ... +\layout Standard + +This is surely a minor point - also things will change during the "BIG" + rewrite, but maybe this is a point to keep in mind for this ? +\layout Standard + +3.) upgrade: old, sometimes obsolete files stay in the ~/.ipython subdirectory. + (hmm, maybe one could move all these into some subdirectory, but which + name for that (via version-number ?) ?) +\layout Subsection + +Command line options +\layout Standard + +It would be great to design the command-line processing system so that it + can be dynamically modified in some easy way. + This would allow systems based on IPython to include their own command-line + processing to either extend or fully replace IPython's. + Probably moving to the new optparse library (also known as optik) will + make this a lot easier. +\layout Section + +OS-dependent code +\layout Standard + +Options which are OS-dependent (such as colors and aliases) should be loaded + via include files. + That is, the general file will have: +\layout Standard + + +\family typewriter +if os.name == 'posix': +\newline +include('ipythonrc-posix.py') +\newline +elif os.name == 'nt': +\newline +include('ipythonrc-nt.py')... +\layout Standard + +In the +\family typewriter +-posix +\family default +, +\family typewriter +-nt +\family default +, etc. + files we'll set all os-specific options. +\layout Section + +Merging with other shell systems +\layout Standard + +This is listed before the big design issues, as it is something which should + be kept in mind when that design is made. +\layout Standard + +The following shell systems are out there and I think the whole design of + IPython should try to be modular enough to make it possible to integrate + its features into these. + In all cases IPython should exist as a stand-alone, terminal based program. + But it would be great if users of these other shells (some of them which + have very nice features of their own, especially the graphical ones) could + keep their environment but gain IPython's features. +\layout List +\labelwidthstring 00.00.0000 + +IDLE This is the standard, distributed as part of Python. + +\layout List +\labelwidthstring 00.00.0000 + +pyrepl +\begin_inset LatexCommand \htmlurl{http://starship.python.net/crew/mwh/hacks/pyrepl.html} + +\end_inset + +. + This is a text (curses-based) shell-like replacement which doesn't have + some of IPython's features, but has a crucially useful (and hard to implement) + one: full multi-line editing. + This turns the interactive interpreter into a true code testing and development + environment. + +\layout List +\labelwidthstring 00.00.0000 + +PyCrust +\begin_inset LatexCommand \htmlurl{http://sourceforge.net/projects/pycrust} + +\end_inset + +. + Very nice, wxWindows based system. +\layout List +\labelwidthstring 00.00.0000 + +PythonWin +\begin_inset LatexCommand \htmlurl{http://starship.python.net/crew/mhammond} + +\end_inset + +. + Similar to PyCrust in some respects, a very good and free Python development + environment for Windows systems. +\layout Section + +Class design +\layout Standard + +This is the big one. + Currently classes use each other in a very messy way, poking inside one + another for data and methods. + ipmaker() adds tons of stuff to the main __IP instance by hand, and the + mix-ins used (Logger, Magic, etc) mean the final __IP instance has a million + things in it. + All that needs to be cleanly broken down with well defined interfaces amongst + the different classes, and probably no mix-ins. +\layout Standard + +The best approach is probably to have all the sub-systems which are currently + mixins be fully independent classes which talk back only to the main instance + (and +\series bold +not +\series default + to each other). + In the main instance there should be an object whose job is to handle communica +tion with the sub-systems. +\layout Standard + +I should probably learn a little UML and diagram this whole thing before + I start coding. +\layout Subsection + +Magic +\layout Standard + +Now all methods which will become publicly available are called Magic.magic_name, + the magic_ should go away. + Then, Magic instead of being a mix-in should simply be an attribute of + __IP: +\layout Standard + +__IP.Magic = Magic() +\layout Standard + +This will then give all the magic functions as __IP.Magic.name(), which is + much cleaner. + This will also force a better separation so that Magic doesn't poke inside + __IP so much. + In the constructor, Magic should get whatever information it needs to know + about __IP (even if it means a pointer to __IP itself, but at least we'll + know where it is. + Right now since it's a mix-in, there's no way to know which variables belong + to whom). +\layout Standard + +Build a class MagicFunction so that adding new functions is a matter of: +\layout Standard + + +\family typewriter +my_magic = MagicFunction(category = 'System utilities') +\newline +my_magic.__call__ = ... +\layout Standard + +Features: +\layout Itemize + +The class constructor should automatically register the functions and keep + a table with category sections for easy sorting/viewing. +\layout Itemize + +The object interface must allow automatic building of a GUI for them. + This requires registering the options the command takes, the number of + arguments, etc, in a formal way. + The advantage of this approach is that it allows not only to add GUIs to + the magics, but also for a much more intelligent building of docstrings, + and better parsing of options and arguments. +\layout Standard + +Also think through better an alias system for magics. + Since the magic system is like a command shell inside ipython, the relation + between these aliases and system aliases should be cleanly thought out. +\layout Subsection + +Color schemes +\layout Standard + +These should be loaded from some kind of resource file so they are easier + to modify by the user. +\layout Section + +Hooks +\layout Standard + +IPython should have a modular system where functions can register themselves + for certain tasks. + Currently changing functionality requires overriding certain specific methods, + there should be a clean API for this to be done. +\layout Subsection + +whos hook +\layout Standard + +This was a very nice suggestion from Alexander Schmolck <a.schmolck@gmx.net>: +\layout Standard + +2. + I think it would also be very helpful if there where some sort of hook + for ``whos`` that let one customize display formaters depending on the + object type. +\layout Standard + +For example I'd rather have a whos that formats an array like: +\layout Standard + + +\family typewriter +Variable Type Data/Length +\newline +------------------------------ +\newline +a array size: 4x3 type: 'Float' +\layout Standard + +than +\layout Standard + + +\family typewriter +Variable Type Data/Length +\newline +------------------------------ +\newline +a array [[ 0. + 1. + 2. + 3<...> 8. + 9. + 10. + 11.]] +\layout Section + +Parallel support +\layout Standard + +For integration with graphical shells and other systems, it will be best + if ipython is split into a kernel/client model, much like Mathematica works. + This simultaneously opens the door for support of interactive parallel + computing. + Currenlty %bg provides a threads-based proof of concept, and Brian Granger's + XGrid project is a much more realistic such system. + The new design should integrates ideas as core elements. + Some notes from Brian on this topic: +\layout Standard + +1. + How should the remote python server/kernel be designed? Multithreaded? + Blocking? Connected/disconnected modes? Load balancing? +\layout Standard + +2. + What APi/protocol should the server/kernel expose to clients? +\layout Standard + +3. + How should the client classes (which the user uses to interact with the + cluster) be designed? +\layout Standard + +4. + What API should the client classes expose? +\layout Standard + +5. + How should the client API be wrapped in a few simple magic functions? +\layout Standard + +6. + How should security be handled? +\layout Standard + +7. + How to work around the issues of the GIL and threads? +\layout Standard + +I think the most important things to work out are the client API (#4) the + server/kernel API/protocol (#2) and the magic function API (#5). + We should let these determine the design and architecture of the components. +\layout Standard + +One other thing. + What is your impression of twisted? I have been looking at it and it looks + like a _very_ powerful set of tools for this type of stuff. + I am wondering if it might make sense to think about using twisted for + this project. +\layout Section + +Manuals +\layout Standard + +The documentation should be generated from docstrings for the command line + args and all the magic commands. + Look into one of the simple text markup systems to see if we can get latex + (for reLyXing later) out of this. + Part of the build command would then be to make an update of the docs based + on this, thus giving more complete manual (and guaranteed to be in sync + with the code docstrings). +\layout Standard + +[PARTLY DONE] At least now all magics are auto-documented, works farily + well. + Limited Latex formatting yet. +\layout Subsection + +Integration with pydoc-help +\layout Standard + +It should be possible to have access to the manual via the pydoc help system + somehow. + This might require subclassing the pydoc help, or figuring out how to add + the IPython docs in the right form so that help() finds them. +\layout Standard + +Some comments from Arnd and my reply on this topic: +\layout Standard + +> ((Generally I would like to have the nice documentation > more easily + accessable from within ipython ... + > Many people just don't read documentation, even if it is > as good as + the one of IPython )) +\layout Standard + +That's an excellent point. + I've added a note to this effect in new_design. + Basically I'd like help() to naturally access the IPython docs. + Since they are already there in html for the user, it's probably a matter + of playing a bit with pydoc to tell it where to find them. + It would definitely make for a much cleaner system. + Right now the information on IPython is: +\layout Standard + +-ipython --help at the command line: info on command line switches +\layout Standard + +-? at the ipython prompt: overview of IPython +\layout Standard + +-magic at the ipython prompt: overview of the magic system +\layout Standard + +-external docs (html/pdf) +\layout Standard + +All that should be better integrated seamlessly in the help() system, so + that you can simply say: +\layout Standard + +help ipython -> full documentation access +\layout Standard + +help magic -> magic overview +\layout Standard + +help profile -> help on current profile +\layout Standard + +help -> normal python help access. +\layout Section + +Graphical object browsers +\layout Standard + +I'd like a system for graphically browsing through objects. + +\family typewriter +@obrowse +\family default + should open a widged with all the things which +\family typewriter +@who +\family default + lists, but cliking on each object would open a dedicated object viewer + (also accessible as +\family typewriter +@oview <object> +\family default +). + This object viewer could show a summary of what +\family typewriter +<object>? +\family default + currently shows, but also colorize source code and show it via an html + browser, show all attributes and methods of a given object (themselves + openable in their own viewers, since in Python everything is an object), + links to the parent classes, etc. +\layout Standard + +The object viewer widget should be extensible, so that one can add methods + to view certain types of objects in a special way (for example, plotting + Numeric arrays via grace or gnuplot). + This would be very useful when using IPython as part of an interactive + complex system for working with certain types of data. +\layout Standard + +I should look at what PyCrust has to offer along these lines, at least as + a starting point. +\layout Section + +Miscellaneous small things +\layout Itemize + +Collect whatever variables matter from the environment in some globals for + __IP, so we're not testing for them constantly (like $HOME, $TERM, etc.) +\layout Section + +Session restoring +\layout Standard + +I've convinced myself that session restore by log replay is too fragile + and tricky to ever work reliably. + Plus it can be dog slow. + I'd rather have a way of saving/restoring the *current* memory state of + IPython. + I tried with pickle but failed (can't pickle modules). + This seems the right way to do it to me, but it will have to wait until + someone tells me of a robust way of dumping/reloading *all* of the user + namespace in a file. +\layout Standard + +Probably the best approach will be to pickle as much as possible and record + what can not be pickled for manual reload (such as modules). + This is not trivial to get to work reliably, so it's best left for after + the code restructuring. +\layout Standard + +The following issues exist (old notes, see above paragraph for my current + take on the issue): +\layout Itemize + +magic lines aren't properly re-executed when a log file is reloaded (and + some of them, like clear or run, may change the environment). + So session restore isn't 100% perfect. +\layout Itemize + +auto-quote/parens lines aren't replayed either. + All this could be done, but it needs some work. + Basically it requires re-running the log through IPython itself, not through + python. +\layout Itemize + +_p variables aren't restored with a session. + Fix: same as above. +\layout Section + +Tips system +\layout Standard + +It would be nice to have a tip() function which gives tips to users in some + situations, but keeps track of already-given tips so they aren't given + every time. + This could be done by pickling a dict of given tips to IPYTHONDIR. +\layout Section + +TAB completer +\layout Standard + +Some suggestions from Arnd Baecker: +\layout Standard + +a) For file related commands (ls, cat, ...) it would be nice to be able to + TAB complete the files in the current directory. + (once you started typing something which is uniquely a file, this leads + to this effect, apart from going through the list of possible completions + ...). + (I know that this point is in your documentation.) +\layout Standard + +More general, this might lead to something like command specific completion + ? +\layout Standard + +Here's John Hunter's suggestion: +\layout Standard + +The *right way to do it* would be to make intelligent or customizable choices + about which namespace to add to the completion list depending on the string + match up to the prompt, eg programmed completions. + In the simplest implementation, one would only complete on files and directorie +s if the line preceding the tab press matched 'cd ' or 'run ' (eg you don't + want callable showing up in 'cd ca<TAB>') +\layout Standard + +In a more advanced scenario, you might imaging that functions supplied the + TAB namespace, and the user could configure a dictionary that mapped regular + expressions to namespace providing functions (with sensible defaults). + Something like +\layout Standard + +completed = { +\newline +'^cd +\backslash +s+(.*)' : complete_files_and_dirs, +\newline +'^run +\backslash +s+(.*)' : complete_files_and_dirs, +\newline +'^run +\backslash +s+(-.*)' : complete_run_options, +\newline +} +\layout Standard + +I don't know if this is feasible, but I really like programmed completions, + which I use extensively in tcsh. + My feeling is that something like this is eminently doable in ipython. +\layout Standard + +/JDH +\layout Standard + +For something like this to work cleanly, the magic command system needs + also a clean options framework, so all valid options for a given magic + can be extracted programatically. +\layout Section + +Debugger +\layout Standard + +Current system uses a minimally tweaked pdb. + Fine-tune it a bit, to provide at least: +\layout Itemize + +Tab-completion in each stack frame. + See email to Chris Hart for details. +\layout Itemize + +Object information via ? at least. + Break up magic_oinfo a bit so that pdb can call it without loading all + of IPython. + If possible, also have the other magics for object study: doc, source, + pdef and pfile. +\layout Itemize + +Shell access via ! +\layout Itemize + +Syntax highlighting in listings. + Use py2html code, implement color schemes. +\layout Section + +A Python-based system shell - pysh? +\layout Standard + +Note: as of IPython 0.6.1, most of this functionality has actually been implemente +d. +\layout Standard + +This section is meant as a working draft for discussions on the possibility + of having a python-based system shell. + It is the result of my own thinking about these issues as much of discussions + on the ipython lists. + I apologize in advance for not giving individual credit to the various + contributions, but right now I don't have the time to track down each message + from the archives. + So please consider this as the result of a collective effort by the ipython + user community. +\layout Standard + +While IPyhton is (and will remain) a python shell first, it does offer a + fair amount of system access functionality: +\layout Standard + +- ! and !! for direct system access, +\layout Standard + +- magic commands which wrap various system commands, +\layout Standard + +- @sc and @sx, for shell output capture into python variables, +\layout Standard + +- @alias, for aliasing system commands. +\layout Standard + +This has prompted many users, over time, to ask for a way of extending ipython + to the point where it could be used as a full-time replacement over typical + user shells like bash, csh or tcsh. + While my interest in ipython is such that I'll concentrate my personal + efforts on other fronts (debugging, architecture, improvements for scientific + use, gui access), I will be happy to do anything which could make such + a development possible. + It would be the responsibility of someone else to maintain the code, but + I would do all necessary architectural changes to ipython for such an extension + to be feasible. +\layout Standard + +I'll try to outline here what I see as the key issues which need to be taken + into account. + This document should be considered an evolving draft. + Feel free to submit comments/improvements, even in the form of patches. +\layout Standard + +In what follows, I'll represent the hypothetical python-based shell ('pysh' + for now) prompt with '>>'. +\layout Subsection + +Basic design principles +\layout Standard + +I think the basic design guideline should be the following: a hypothetical + python system shell should behave, as much as possible, like a normal shell + that users are familiar with (bash, tcsh, etc). + This means: +\layout Standard + +1. + System commands can be issued directly at the prompt with no special syntax: +\layout Standard + +>> ls +\layout Standard + +>> xemacs +\layout Standard + +should just work like a user expects. +\layout Standard + +2. + The facilities of the python language should always be available, like + they are in ipython: +\layout Standard + +>> 3+4 +\newline +7 +\layout Standard + +3. + It should be possible to easily capture shell output into a variable. + bash and friends use backquotes, I think using a command (@sc) like ipython + currently does is an acceptable compromise. +\layout Standard + +4. + It should also be possible to expand python variables/commands in the middle + of system commands. + I thihk this will make it necessary to use $var for name expansions: +\layout Standard + +>> var='hello' # var is a Python variable +\newline +>> print var hello # This is the result of a Python print command +\newline +>> echo $var hello # This calls the echo command, expanding 'var'. +\layout Standard + +5. + The above capabilities should remain possible for multi-line commands. + One of the most annoying things I find about tcsh, is that I never quite + remember the syntactic details of looping. + I often want to do something at the shell which involves a simple loop, + but I can never remember how to do it in tcsh. + This often means I just write a quick throwaway python script to do it + (Perl is great for this kind of quick things, but I've forgotten most its + syntax as well). +\layout Standard + +It should be possible to write code like: +\layout Standard + +>> for ext in ['.jpg','.gif']: +\newline +.. + ls file$ext +\layout Standard + +And have it work as 'ls file.jpg;ls file.gif'. +\layout Subsection + +Smaller details +\layout Standard + +If the above are considered as valid guiding principles for how such a python + system shell should behave, then some smaller considerations and comments + to keep in mind are listed below. +\layout Standard + +- it's ok for shell builtins (in this case this includes the python language) + to override system commands on the path. + See tcsh's 'time' vs '/usr/bin/time'. + This settles the 'print' issue and related. +\layout Standard + +- pysh should take +\layout Standard + +foo args +\layout Standard + +as a command if (foo args is NOT valid python) and (foo is in $PATH). +\layout Standard + +If the user types +\layout Standard + +>> ./foo args +\layout Standard + +it should be considered a system command always. +\layout Standard + +- _, __ and ___ should automatically remember the previous 3 outputs captured + from stdout. + In parallel, there should be _e, __e and ___e for stderr. + Whether capture is done as a single string or in list mode should be a + user preference. + If users have numbered prompts, ipython's full In/Out cache system should + be available. +\layout Standard + +But regardless of how variables are captured, the printout should be like + that of a plain shell (without quotes or braces to indicate strings/lists). + The everyday 'feel' of pysh should be more that of bash/tcsh than that + of ipython. +\layout Standard + +- filename completion first. + Tab completion could work like in ipython, but with the order of priorities + reversed: first files, then python names. +\layout Standard + +- configuration via standard python files. + Instead of 'setenv' you'd simply write into the os.environ[] dictionary. + This assumes that IPython itself has been fixed to be configured via normal + python files, instead of the current clunky ipythonrc format. +\layout Standard + +- IPython can already configure the prompt in fairly generic ways. + It should be able to generate almost any kind of prompt which bash/tcsh + can (within reason). +\layout Standard + +- Keep the Magics system. + They provide a lightweight syntax for configuring and modifying the state + of the user's session itself. + Plus, they are an extensible system so why not give the users one more + tool which is fairly flexible by nature? Finally, having the @magic optional + syntax allows a user to always be able to access the shell's control system, + regardless of name collisions with defined variables or system commands. +\layout Standard + +But we need to move all magic functionality into a protected namespace, + instead of the current messy name-mangling tricks (which don't scale well). + +\layout Section + +Future improvements +\layout Itemize + +When from <mod> import * is used, first check the existing namespace and + at least issue a warning on screen if names are overwritten. +\layout Itemize + +Auto indent? Done, for users with readline support. +\layout Subsection + +Better completion a la zsh +\layout Standard + +This was suggested by Arnd: +\layout Standard + +> >\SpecialChar ~ +\SpecialChar ~ +\SpecialChar ~ + More general, this might lead to something like +\layout Standard + +> >\SpecialChar ~ +\SpecialChar ~ +\SpecialChar ~ + command specific completion ? +\layout Standard + +> +\layout Standard + +> I'm not sure what you mean here. +\layout Standard + +\SpecialChar ~ + +\layout Standard + +Sorry, that was not understandable, indeed ... +\layout Standard + +I thought of something like +\layout Standard + +\SpecialChar ~ +- cd and then use TAB to go through the list of directories +\layout Standard + +\SpecialChar ~ +- ls and then TAB to consider all files and directories +\layout Standard + +\SpecialChar ~ +- cat and TAB: only files (no directories ...) +\layout Standard + +\SpecialChar ~ + +\layout Standard + +For zsh things like this are established by defining in .zshrc +\layout Standard + +\SpecialChar ~ + +\layout Standard + +compctl -g '*.dvi' xdvi +\layout Standard + +compctl -g '*.dvi' dvips +\layout Standard + +compctl -g '*.tex' latex +\layout Standard + +compctl -g '*.tex' tex +\layout Standard + +... +\layout Section + +Outline of steps +\layout Standard + +Here's a rough outline of the order in which to start implementing the various + parts of the redesign. + The first 'test of success' should be a clean pychecker run (not the mess + we get right now). +\layout Itemize + +Make Logger and Magic not be mixins but attributes of the main class. + +\begin_deeper +\layout Itemize + +Magic should have a pointer back to the main instance (even if this creates + a recursive structure) so it can control it with minimal message-passing + machinery. + +\layout Itemize + +Logger can be a standalone object, simply with a nice, clean interface. +\layout Itemize + +Logger currently handles part of the prompt caching, but other parts of + that are in the prompts class itself. + Clean up. +\end_deeper +\layout Itemize + +Change to python-based config system. +\layout Itemize + +Move make_IPython() into the main shell class, as part of the constructor. + Do this +\emph on +after +\emph default +the config system has been changed, debugging will be a lot easier then. +\layout Itemize + +Merge the embeddable class and the normal one into one. + After all, the standard ipython script +\emph on +is +\emph default + a python program with IPython embedded in it. + There's no need for two separate classes ( +\emph on +maybe +\emph default + keep the old one around for the sake of backwards compatibility). +\layout Section + +Ville Vainio's suggestions +\layout Standard + +Some notes sent in by Ville Vainio +\family typewriter +<vivainio@kolumbus.fi> +\family default + on Tue, 29 Jun 2004. + Keep here for reference, some of it replicates things already said above. +\layout Standard + +Current ipython seems to "special case" lots of stuff - aliases, magics + etc. + It would seem to yield itself to a simpler and more extensible architecture, + consisting of multple dictionaries, where just the order of search is determine +d by profile/prefix. + All the functionality would just be "pushed" to ipython core, i.e. + the objects that represent the functionality are instantiated on "plugins" + and they are registered with ipython core. + i.e. +\layout Standard + +def magic_f(options, args): pass +\layout Standard + +m = MyMagic(magic_f) m.arghandler = stockhandlers.OptParseArgHandler m.options + = .... + # optparse options, for easy passing to magic_f and help display +\layout Standard + +# note that arghandler takes a peek at the instance, sees options, and proceeds + # accordingly. + Various arg handlers can ask for arbitrary options. + # some handler might optionally glob the filenames, search data folders + for filenames etc. +\layout Standard + +ipythonregistry.register(category = "magic", name = "mymagic", obj = m) +\layout Standard + +I bet most of the current functionality could easily be added to such a + registry by just instantiating e.g. + "Magic" class and registering all the functions with some sensible default + args. + Supporting legacy stuff in general would be easy - just implement new handlers + (arg and otherwise) for new stuff, and have the old handlers around forever + / as long as is deemed appropriate. + The 'python' namespace (locals() + globals()) should be special, of course. +\layout Standard + +It should be easy to have arbitrary number of "categories" (like 'magic', + 'shellcommand','projectspecific_myproject', 'projectspecific_otherproject'). + It would only influence the order in which the completions are suggested, + and in case of name collision which one is selected. + Also, I think all completions should be shown, even the ones in "later" + categories in the case of a match in an "earlier" category. +\layout Standard + +The "functionality object" might also have a callable object 'expandarg', + and ipython would run it (with the arg index) when tab completion is attempted + after typing the function name. + It would return the possible completions for that particular command... + or None to "revert to default file completions". + Such functionality could be useful in making ipython an "operating console" + of a sort. + I'm talking about: +\layout Standard + +>> lscat reactor # list commands in category - reactor is "project specific" + category +\layout Standard + +r_operate +\layout Standard + +>> r_operate <tab> start shutdown notify_meltdown evacuate +\layout Standard + +>> r_operate shutdown <tab> +\layout Standard + +1 2 5 6 # note that 3 and 4 are already shut down +\layout Standard + +>> r_operate shutdown 2 +\layout Standard + +Shutting down.. + ok. +\layout Standard + +>> r_operate start <tab> +\layout Standard + +2 3 4 # 2 was shut down, can be started now +\layout Standard + +>> r_operate start 2 +\layout Standard + +Starting.... + ok. +\layout Standard + +I'm talking about having a super-configurable man-machine language here! + Like cmd.Cmd on steroids, as a free addition to ipython! +\the_end diff --git a/doc/pycolor.1 b/doc/pycolor.1 new file mode 100644 index 0000000..34cf5d5 --- /dev/null +++ b/doc/pycolor.1 @@ -0,0 +1,33 @@ +.\" Hey, EMACS: -*- nroff -*- +.\" First parameter, NAME, should be all caps +.\" Second parameter, SECTION, should be 1-8, maybe w/ subsection +.\" other parameters are allowed: see man(7), man(1) +.TH PYCOLOR 1 "March 21, 2003" +.\" Please adjust this date whenever revising the manpage. +.\" +.\" Some roff macros, for reference: +.\" .nh disable hyphenation +.\" .hy enable hyphenation +.\" .ad l left justify +.\" .ad b justify to both left and right margins +.\" .nf disable filling +.\" .fi enable filling +.\" .br insert line break +.\" .sp <n> insert n+1 empty lines +.\" for manpage-specific macros, see man(7) +.SH NAME +pycolor \- Colorize a python file using ANSI and print to stdout. +.SH SYNOPSIS +.B pycolor +.RI [ options ] " file" +.SH DESCRIPTION +Prints a colorized version of the input file to standard out. +.SH OPTIONS +.TP +.B \-s <scheme> +Give the color scheme to use. Currently only Linux (default), +LightBG, and NOColor are implemented. +.SH AUTHOR +pycolor was written by Fernando Perez <fperez@colorado.edu>. +This manual page was written by Jack Moffitt <jack@xiph.org>, +for the Debian project (but may be used by others). diff --git a/doc/pycon.ico b/doc/pycon.ico new file mode 100644 index 0000000000000000000000000000000000000000..a54682d91c85164fe9c910f5831935bd7fd6983c GIT binary patch literal 766 zc$|fjt!~3G6orrLNl`P<qR|BoM!L*skFrN73n_?F(6NnXC{mbF`379Hfl7Ua!aYJk zrR-j(ag(Uqj(zNW$3IDA1By$M%pv-o0C(I!uoLzpTj9o!<rDm(+*jmz+ewj#8|NG+ zjjw2$wv!@}H2*2edRhR-=bqNgFHO)<cyU=f^IXbfY>CpAr*F0bs3vL|Wi5dXJbl$1 z=(=N+&{lS6IW{ImU1@V>%i;-P+!|vnPw3VYkug<l^_f%B9N54_enw#J1FFLJw1Fmc z-viBA_&?xw^S(*@>^|I|Jen^%4w(G*p2yk^1Z4YDvu}1MhR<aNtS^IK%PZ?gl4CpY rDf2DSd}UN{1XZY96?kH&?713@k6f@<Ikqbov1dac?zh+0$h&_4nYGO+ literal 0 Hc$@<O00001 diff --git a/doc/update_magic.sh b/doc/update_magic.sh new file mode 100755 index 0000000..71098a8 --- /dev/null +++ b/doc/update_magic.sh @@ -0,0 +1,2 @@ +#!/bin/sh +ipython --magic_docstrings > magic.tex \ No newline at end of file diff --git a/doc/update_version.sh b/doc/update_version.sh new file mode 100755 index 0000000..4e09ef0 --- /dev/null +++ b/doc/update_version.sh @@ -0,0 +1,3 @@ +#!/bin/sh +ver=`ipython -V` +sed "s/__version__/${ver}/" manual_base.lyx > manual.lyx diff --git a/scripts/ipython b/scripts/ipython new file mode 100755 index 0000000..a7a78a4 --- /dev/null +++ b/scripts/ipython @@ -0,0 +1,28 @@ +#!/usr/bin/env python +# -*- coding: utf-8 -*- +"""IPython -- An enhanced Interactive Python + +This is just the startup wrapper script, kept deliberately to a minimum. + +The shell's mainloop() takes an optional argument, sys_exit (default=0). If +set to 1, it calls sys.exit() at exit time. You can use the following code in +your PYTHONSTARTUP file: + +import IPython +IPython.Shell.IPShell().mainloop(sys_exit=1) + +[or simply IPython.Shell.IPShell().mainloop(1) ] + +and IPython will be your working environment when you start python. The final +sys.exit() call will make python exit transparently when IPython finishes, so +you don't have an extra prompt to get out of. + +This is probably useful to developers who manage multiple Python versions and +don't want to have correspondingly multiple IPython versions. Note that in +this mode, there is no way to pass IPython any command-line options, as those +are trapped first by Python itself. +""" + +import IPython + +IPython.Shell.start().mainloop() diff --git a/scripts/ipython_win_post_install.py b/scripts/ipython_win_post_install.py new file mode 100755 index 0000000..efe573d --- /dev/null +++ b/scripts/ipython_win_post_install.py @@ -0,0 +1,78 @@ +#!python +"""Windows-specific part of the installation""" + +import os, sys + +def create_shortcut_safe(target,description,link_file,*args,**kw): + """make a shortcut if it doesn't exist, and register its creation""" + + if not os.path.isfile(link_file): + create_shortcut(target, description, link_file,*args,**kw) + file_created(link_file) + +def install(): + """Routine to be run by the win32 installer with the -install switch.""" + + from IPython.Release import version + + # Get some system constants + prefix = sys.prefix + python = prefix + r'\python.exe' + # Lookup path to common startmenu ... + ip_dir = get_special_folder_path('CSIDL_COMMON_PROGRAMS') + r'\IPython' + + # Some usability warnings at installation time. I don't want them at the + # top-level, so they don't appear if the user is uninstalling. + try: + import ctypes + except ImportError: + print ('To take full advantage of IPython, you need ctypes from:\n' + 'http://sourceforge.net/projects/ctypes') + + try: + import win32con + except ImportError: + print ('To take full advantage of IPython, you need pywin32 from:\n' + 'http://starship.python.net/crew/mhammond/win32/Downloads.html') + + try: + import readline + except ImportError: + print ('To take full advantage of IPython, you need readline from:\n' + 'http://sourceforge.net/projects/uncpythontools') + + # Create IPython entry ... + if not os.path.isdir(ip_dir): + os.mkdir(ip_dir) + directory_created(ip_dir) + + # Create program shortcuts ... + f = ip_dir + r'\IPython.lnk' + a = prefix + r'\scripts\ipython' + create_shortcut_safe(python,'IPython',f,a) + + f = ip_dir + r'\pysh.lnk' + a = prefix + r'\scripts\ipython -p pysh' + create_shortcut_safe(python,'pysh',f,a) + + # Create documentation shortcuts ... + t = prefix + r'\share\doc\ipython-%s\manual.pdf' % version + f = ip_dir + r'\Manual in PDF.lnk' + create_shortcut_safe(t,r'IPython Manual - PDF-Format',f) + + t = prefix + r'\share\doc\ipython-%s\manual\manual.html' % version + f = ip_dir + r'\Manual in HTML.lnk' + create_shortcut_safe(t,'IPython Manual - HTML-Format',f) + +def remove(): + """Routine to be run by the win32 installer with the -remove switch.""" + pass + +# main() +if len(sys.argv) > 1: + if sys.argv[1] == '-install': + install() + elif sys.argv[1] == '-remove': + remove() + else: + print "Script was called with option %s" % sys.argv[1] diff --git a/scripts/pycolor b/scripts/pycolor new file mode 100755 index 0000000..9006717 --- /dev/null +++ b/scripts/pycolor @@ -0,0 +1,6 @@ +#!/usr/bin/env python +# -*- coding: utf-8 -*- +"""Simple wrapper around PyColorize, which colorizes python sources.""" + +import IPython.PyColorize +IPython.PyColorize.main() diff --git a/setup.py b/setup.py new file mode 100755 index 0000000..d11fee8 --- /dev/null +++ b/setup.py @@ -0,0 +1,146 @@ +#!/usr/bin/env python +# -*- coding: utf-8 -*- +"""Setup script for IPython. + +Under Posix environments it works like a typical setup.py script. +Under Windows, the command sdist is not supported, since IPython +requires utilities, which are not available under Windows.""" + +#***************************************************************************** +# Copyright (C) 2001-2005 Fernando Perez <fperez@colorado.edu> +# +# Distributed under the terms of the BSD License. The full license is in +# the file COPYING, distributed as part of this software. +#***************************************************************************** + +import sys, os +from glob import glob +from setupext import install_data_ext +isfile = os.path.isfile + +# BEFORE importing distutils, remove MANIFEST. distutils doesn't properly +# update it when the contents of directories change. +if os.path.exists('MANIFEST'): os.remove('MANIFEST') + +if os.name == 'posix': + os_name = 'posix' +elif os.name in ['nt','dos']: + os_name = 'windows' +else: + print 'Unsupported operating system:',os.name + sys.exit(1) + +# Under Windows, 'sdist' is not supported, since it requires lyxport (and +# hence lyx,perl,latex,pdflatex,latex2html,sh,...) +if os_name == 'windows' and sys.argv[1] == 'sdist': + print 'The sdist command is not available under Windows. Exiting.' + sys.exit(1) + +from distutils.core import setup + +# update the manuals when building a source dist +if len(sys.argv) >= 2 and sys.argv[1] in ('sdist','bdist_rpm'): + from IPython.genutils import target_update + # list of things to be updated. Each entry is a triplet of args for + # target_update() + to_update = [('doc/magic.tex', + ['IPython/Magic.py'], + "cd doc && ./update_magic.sh" ), + + ('doc/manual.lyx', + ['IPython/Release.py','doc/manual_base.lyx'], + "cd doc && ./update_version.sh" ), + + ('doc/manual/manual.html', + ['doc/manual.lyx', + 'doc/magic.tex', + 'doc/examples/example-gnuplot.py', + 'doc/examples/example-magic.py', + 'doc/examples/example-embed.py', + 'doc/examples/example-embed-short.py', + 'IPython/UserConfig/ipythonrc', + ], + "cd doc && " + "lyxport -tt --leave --pdf " + "--html -o '-noinfo -split +1 -local_icons' manual.lyx"), + + ('doc/new_design.pdf', + ['doc/new_design.lyx'], + "cd doc && lyxport -tt --pdf new_design.lyx"), + + ('doc/ipython.1.gz', + ['doc/ipython.1'], + "cd doc && gzip -9c ipython.1 > ipython.1.gz"), + + ('doc/pycolor.1.gz', + ['doc/pycolor.1'], + "cd doc && gzip -9c pycolor.1 > pycolor.1.gz"), + ] + for target in to_update: + target_update(*target) + +# Release.py contains version, authors, license, url, keywords, etc. +execfile(os.path.join('IPython','Release.py')) + +# A little utility we'll need below, since glob() does NOT allow you to do +# exclusion on multiple endings! +def file_doesnt_endwith(test,endings): + """Return true if test is a file and its name does NOT end with any + of the strings listed in endings.""" + if not isfile(test): + return False + for e in endings: + if test.endswith(e): + return False + return True + +# I can't find how to make distutils create a nested dir. structure, so +# in the meantime do it manually. Butt ugly. +docdirbase = 'share/doc/ipython-%s' % version +manpagebase = 'share/man/man1' + +# We only need to exclude from this things NOT already excluded in the +# MANIFEST.in file. +exclude = ('.sh','.1.gz') +docfiles = filter(lambda f:file_doesnt_endwith(f,exclude),glob('doc/*')) + +examfiles = filter(isfile, glob('doc/examples/*.py')) +manfiles = filter(isfile, glob('doc/manual/*.html')) + \ + filter(isfile, glob('doc/manual/*.css')) + \ + filter(isfile, glob('doc/manual/*.png')) +manpages = filter(isfile, glob('doc/*.1.gz')) +cfgfiles = filter(isfile, glob('IPython/UserConfig/*')) +scriptfiles = filter(isfile, ['scripts/ipython','scripts/pycolor']) + +# Script to be run by the windows binary installer after the default setup +# routine, to add shortcuts and similar windows-only things. Windows +# post-install scripts MUST reside in the scripts/ dir, otherwise distutils +# doesn't find them. +if 'bdist_wininst' in sys.argv: + if len(sys.argv) > 2 and ('sdist' in sys.argv or 'bdist_rpm' in sys.argv): + print >> sys.stderr,"ERROR: bdist_wininst must be run alone. Exiting." + sys.exit(1) + scriptfiles.append('scripts/ipython_win_post_install.py') + +# Call the setup() routine which does most of the work +setup(name = name, + version = version, + description = description, + long_description = long_description, + author = authors['Fernando'][0], + author_email = authors['Fernando'][1], + url = url, + license = license, + platforms = platforms, + keywords = keywords, + packages = ['IPython', 'IPython.Extensions'], + scripts = scriptfiles, + cmdclass = {'install_data': install_data_ext}, + data_files = [('data', docdirbase, docfiles), + ('data', os.path.join(docdirbase, 'examples'), + examfiles), + ('data', os.path.join(docdirbase, 'manual'), + manfiles), + ('data', manpagebase, manpages), + ('lib', 'IPython/UserConfig', cfgfiles)] + ) diff --git a/setupext/__init__.py b/setupext/__init__.py new file mode 100644 index 0000000..5f93fe1 --- /dev/null +++ b/setupext/__init__.py @@ -0,0 +1,3 @@ +# load extended setup modules for distuils + +from install_data_ext import install_data_ext diff --git a/setupext/install_data_ext.py b/setupext/install_data_ext.py new file mode 100644 index 0000000..f2ce894 --- /dev/null +++ b/setupext/install_data_ext.py @@ -0,0 +1,80 @@ +# install_data_ext.py +# +# Subclass of normal distutils install_data command to allow more +# configurable installation of data files. + +import os +from distutils.command.install_data import install_data +from distutils.util import change_root, convert_path + +class install_data_ext(install_data): + + def initialize_options(self): + self.install_base = None + self.install_platbase = None + self.install_purelib = None + self.install_headers = None + self.install_lib = None + self.install_scripts = None + self.install_data = None + + self.outfiles = [] + self.root = None + self.force = 0 + self.data_files = self.distribution.data_files + self.warn_dir = 1 + + + def finalize_options(self): + self.set_undefined_options('install', + ('root', 'root'), + ('force', 'force'), + ('install_base', 'install_base'), + ('install_platbase', + 'install_platbase'), + ('install_purelib', + 'install_purelib'), + ('install_headers', + 'install_headers'), + ('install_lib', 'install_lib'), + ('install_scripts', + 'install_scripts'), + ('install_data', 'install_data')) + + + def run(self): + """ + This is where the meat is. Basically the data_files list must + now be a list of tuples of 3 entries. The first + entry is one of 'base', 'platbase', etc, which indicates which + base to install from. The second entry is the path to install + too. The third entry is a list of files to install. + """ + for lof in self.data_files: + if lof[0]: + base = getattr(self, 'install_' + lof[0]) + else: + base = getattr(self, 'install_base') + dir = convert_path(lof[1]) + if not os.path.isabs(dir): + dir = os.path.join(base, dir) + elif self.root: + dir = change_root(self.root, dir) + self.mkpath(dir) + + files = lof[2] + if len(files) == 0: + # If there are no files listed, the user must be + # trying to create an empty directory, so add the the + # directory to the list of output files. + self.outfiles.append(dir) + else: + # Copy files, adding them to the list of output files. + for f in files: + f = convert_path(f) + (out, _) = self.copy_file(f, dir) + #print "DEBUG: ", out # dbg + self.outfiles.append(out) + + + return self.outfiles diff --git a/tools/bkp.py b/tools/bkp.py new file mode 100755 index 0000000..4fd2fb4 --- /dev/null +++ b/tools/bkp.py @@ -0,0 +1,72 @@ +#!/usr/bin/env python +"""Backup directories using rsync. Quick and dirty. + +backup.py config_file final_actions +""" + +#---------------------------------------------------------------------------- +# configure in this section + +# all dirs relative to current dir. + +# output directory for backups +outdir = '' + +# list directories to backup as a dict with 1 or 0 values for +# recursive (or not) descent: +to_backup = {} + +# list exclude patterns here (space-separated): +# if the pattern ends with a / then it will only match a directory, not a +# file, link or device. +# see man rsync for more details on the exclude patterns +exc_pats = '#*# *~ *.pyc *.pyo *.o ' + +# global options for rsync +rsync_opts='-v -t -a --delete --delete-excluded' + +#---------------------------------------------------------------------------- +# real code begins +import os,string,re,sys +from IPython.genutils import * +from IPython.Itpl import itpl + +# config file can redefine final actions +def final(): + pass + +# load config from cmd line config file or default bkprc.py +try: + execfile(sys.argv[1]) +except: + try: + execfile('bkprc.py') + except IOError: + print 'You need to provide a config file: bkp.py rcfile' + sys.exit() + +# make output dir if needed +outdir = os.path.expanduser(outdir) +try: + os.makedirs(outdir) +except OSError: # raised if dir already exists -> no need to make it + pass + +# build rsync command and call: +exclude = re.sub(r'([^\s].*?)(\s|$)',r'--exclude "\1"\2',exc_pats) +rsync = itpl('rsync $rsync_opts $exclude') + +# the same can also be done with lists (keep it for reference): +#exclude = string.join(['--exclude "'+p+'"' for p in qw(exc_pats)]) + +# rsync takes -r as a flag, not 0/1 so translate: +rec_flag = {0:'',1:'-r'} + +# loop over user specified directories calling rsync +for bakdir,rec in to_backup.items(): + bakdir = os.path.expanduser(bakdir) + xsys(itpl('$rsync $rec_flag[rec] $bakdir $outdir'), + debug=0,verbose=1,header='\n### ') + +# final actions? +final() diff --git a/tools/bkprc.py b/tools/bkprc.py new file mode 100644 index 0000000..6903150 --- /dev/null +++ b/tools/bkprc.py @@ -0,0 +1,22 @@ +# config file for a quick'n dirty backup script that uses rsync + +# output directory for backups +outdir = '~/tmp' + +# list directories to backup as a dict with 1 or 0 values for +# recursive (or not) descent: +to_backup = {'~/ipython/ipython':1} + +# exclude patterns. anything ending in / is considered a directory +exc_pats = '#*# *~ *.o *.pyc *.pyo MANIFEST *.pdf *.flc build/ dist/ ' \ +' doc/manual/ doc/manual.lyx ChangeLog.* magic.tex *.1.gz ' + +# final actions after doing the backup +def final(): + dbg = 0 + version = bq('ipython -V') + out_tgz = outdir+'/ipython-'+version+'.tgz' + xsys(itpl('cd $outdir; pwd;tar -czf $out_tgz ipython'),debug=dbg,verbose=1) + #xsys(itpl('cp $out_tgz /mnt/card/fperez/ipython'),debug=dbg,verbose=1) + xsys(itpl('mv $out_tgz ~/ipython/backup'),debug=dbg,verbose=1) + xsys(itpl('rm -rf ${outdir}/ipython'),debug=dbg,verbose=1) diff --git a/tools/release b/tools/release new file mode 100755 index 0000000..4ca7455 --- /dev/null +++ b/tools/release @@ -0,0 +1,99 @@ +#!/bin/sh +# IPython release script + +PYVER=`python -V 2>&1 | awk '{print $2}' | awk -F '.' '{print $1$2}' ` +version=`ipython -Version` +ipdir=~/ipython/ipython + +echo +echo "Releasing IPython version $version" +echo "==================================" + +echo "Marking ChangeLog with release information and making NEWS file..." + +# Stamp changelog and save a copy of the status at each version, in case later +# we want the NEWS file to start from a point before the very last release (if +# very small interim releases have no significant changes). + +cd $ipdir/doc +cp ChangeLog ChangeLog.old +cp ChangeLog ChangeLog.$version +daystamp=`date +%Y-%m-%d` +echo $daystamp " ***" Released version $version > ChangeLog +echo >> ChangeLog +cat ChangeLog.old >> ChangeLog +rm ChangeLog.old + +# Build NEWS file +echo "Changes between the last two releases (major or minor)" > NEWS +echo "Note that this is an auto-generated diff of the ChangeLogs" >> NEWS +echo >> NEWS +diff ChangeLog.previous ChangeLog | grep -v '^0a' | sed 's/^> //g' >> NEWS +cp ChangeLog ChangeLog.previous + +# Clean up build/dist directories +rm -rf $ipdir/build/* +rm -rf $ipdir/dist/* + +# Perform local backup +cd $ipdir/tools +./bkp.py + +# Build source and binary distros +cd $ipdir +./setup.py sdist --formats=gztar +#./setup.py bdist_rpm --release=py$PYVER +python2.3 ./setup.py bdist_rpm --release=py23 --python=/usr/bin/python2.3 + +# A 2.4-specific RPM, where we must use the --python option to ensure that +# the resulting RPM is really built with 2.4 (so things go to +# lib/python2.4/...) +python2.4 ./setup.py bdist_rpm --release=py24 --python=/usr/bin/python2.4 + +# Call the windows build separately, so that the extra Windows scripts don't +# get pulled into Unix builds (setup.py has code which checks for +# bdist_wininst) +#./setup.py bdist_wininst --install-script=ipython_win_post_install.py + +# For now, make the win32 installer with a hand-built 2.3.5 python, which is +# the only one that fixes a crash in the post-install phase. +$HOME/tmp/local/bin/python2.3 setup.py bdist_wininst \ + --install-script=ipython_win_post_install.py + + +# Register with the Python Package Index (PyPI) +echo "Registering with PyPI..." +cd $ipdir +./setup.py register + +# Upload all files +cd $ipdir/dist +echo "Uploading distribution files..." +scp * fperez@scipy.org:www/dist/ + +echo "Uploading backup files..." +cd ~/ipython/backup +scp `ls -1tr | tail -1` fperez@scipy.org:www/backup/ + +echo "Updating webpage..." +cd $ipdir/doc +www=~/ipython/homepage +cp ChangeLog NEWS $www +rm -rf $www/doc/* +cp -r manual.pdf manual/ $www/doc +cd $www +./update + +# Alert package maintainers +echo "Alerting package maintainers..." +maintainers='fperez@colorado.edu ariciputi@users.sourceforge.net jack@xiph.org tretkowski@inittab.de dryice@hotpop.com' +#maintainers='fperez@colorado.edu' + +for email in $maintainers + do + echo "Emailing $email..." + mail -s "[Package maintainer notice] A new IPython is out. Version: $version" \ + $email < NEWS + done + +echo "Done!" diff --git a/tools/testrel b/tools/testrel new file mode 100755 index 0000000..458f819 --- /dev/null +++ b/tools/testrel @@ -0,0 +1,27 @@ +#!/bin/sh + +# release test +PYVER=`python -V 2>&1 | awk '{print $2}' | awk -F '.' '{print $1$2}' ` + +# clean up build/dist directories +rm -rf ~/ipython/ipython/build/* +rm -rf ~/ipython/ipython/dist/* + +# build source distros +cd ~/ipython/ipython + +./setup.py sdist --formats=gztar + +#./setup.py bdist_rpm --release=py$PYVER +python2.3 ./setup.py bdist_rpm --release=py23 --python=/usr/bin/python2.3 +python2.4 ./setup.py bdist_rpm --release=py24 --python=/usr/bin/python2.4 + +# Call the windows build separately, so that the extra Windows scripts don't +# get pulled into Unix builds (setup.py has code which checks for +# bdist_wininst) +#./setup.py bdist_wininst --install-script=ipython_win_post_install.py + +# For now, make the win32 installer with a hand-built 2.3.5 python, which is +# the only one that fixes a crash in the post-install phase. +$HOME/tmp/local/bin/python2.3 setup.py bdist_wininst \ + --install-script=ipython_win_post_install.py diff --git a/win32_manual_post_install.py b/win32_manual_post_install.py new file mode 100644 index 0000000..40addde --- /dev/null +++ b/win32_manual_post_install.py @@ -0,0 +1,130 @@ +#!python +"""Windows-specific part of the installation""" + +import os, sys + +try: + import shutil,pythoncom + from win32com.shell import shell + import _winreg as wreg +except ImportError: + print """ +You seem to be missing the PythonWin extensions necessary for automatic +installation. You can get them (free) from +http://starship.python.net/crew/mhammond/ + +Please see the manual for details if you want to finish the installation by +hand, or get PythonWin and repeat the procedure. + +Press <Enter> to exit this installer.""" + raw_input() + sys.exit() + + +def make_shortcut(fname,target,args='',start_in='',comment='',icon=None): + """Make a Windows shortcut (.lnk) file. + + make_shortcut(fname,target,args='',start_in='',comment='',icon=None) + + Arguments: + fname - name of the final shortcut file (include the .lnk) + target - what the shortcut will point to + args - additional arguments to pass to the target program + start_in - directory where the target command will be called + comment - for the popup tooltips + icon - optional icon file. This must be a tuple of the type + (icon_file,index), where index is the index of the icon you want + in the file. For single .ico files, index=0, but for icon libraries + contained in a single file it can be >0. + """ + + shortcut = pythoncom.CoCreateInstance( + shell.CLSID_ShellLink, None, + pythoncom.CLSCTX_INPROC_SERVER, shell.IID_IShellLink + ) + shortcut.SetPath(target) + shortcut.SetArguments(args) + shortcut.SetWorkingDirectory(start_in) + shortcut.SetDescription(comment) + if icon: + shortcut.SetIconLocation(*icon) + shortcut.QueryInterface(pythoncom.IID_IPersistFile).Save(fname,0) + + +def run(wait=0): + # Find where the Start Menu and My Documents are on the filesystem + key = wreg.OpenKey(wreg.HKEY_CURRENT_USER, + r'Software\Microsoft\Windows\CurrentVersion' + r'\Explorer\Shell Folders') + + programs_dir = wreg.QueryValueEx(key,'Programs')[0] + my_documents_dir = wreg.QueryValueEx(key,'Personal')[0] + key.Close() + + # Find where the 'program files' directory is + key = wreg.OpenKey(wreg.HKEY_LOCAL_MACHINE, + r'SOFTWARE\Microsoft\Windows\CurrentVersion') + + program_files_dir = wreg.QueryValueEx(key,'ProgramFilesDir')[0] + key.Close() + + + # File and directory names + ip_dir = program_files_dir + '\\IPython' + ip_prog_dir = programs_dir + '\\IPython' + doc_dir = ip_dir+'\\doc' + ip_filename = ip_dir+'\\IPython_shell.py' + pycon_icon = doc_dir+'\\pycon.ico' + + if not os.path.isdir(ip_dir): + os.mkdir(ip_dir) + + # Copy startup script and documentation + shutil.copy(sys.prefix+'\\Scripts\\ipython',ip_filename) + if os.path.isdir(doc_dir): + shutil.rmtree(doc_dir) + shutil.copytree('doc',doc_dir) + + # make shortcuts for IPython, html and pdf docs. + print 'Making entries for IPython in Start Menu...', + + # Create shortcuts in Programs\IPython: + if not os.path.isdir(ip_prog_dir): + os.mkdir(ip_prog_dir) + os.chdir(ip_prog_dir) + + man_pdf = doc_dir + '\\manual.pdf' + man_htm = doc_dir + '\\manual\\manual.html' + + make_shortcut('IPython.lnk',sys.executable, '"%s"' % ip_filename, + my_documents_dir, + 'IPython - Enhanced python command line interpreter', + (pycon_icon,0)) + make_shortcut('pysh.lnk',sys.executable, '"%s" -p pysh' % ip_filename, + my_documents_dir, + 'pysh - a system shell with Python syntax (IPython based)', + (pycon_icon,0)) + make_shortcut('Manual in HTML format.lnk',man_htm,'','', + 'IPython Manual - HTML format') + make_shortcut('Manual in PDF format.lnk',man_pdf,'','', + 'IPython Manual - PDF format') + + print """Done. + +I created the directory %s. There you will find the +IPython startup script and manuals. + +An IPython menu was also created in your Start Menu, with entries for +IPython itself and the manual in HTML and PDF formats. + +For reading PDF documents you need the freely available Adobe Acrobat +Reader. If you don't have it, you can download it from: +http://www.adobe.com/products/acrobat/readstep2.html +""" % ip_dir + + if wait: + print "Finished with IPython installation. Press Enter to exit this installer.", + raw_input() + +if __name__ == '__main__': + run()