##// END OF EJS Templates
Remove svn-style $Id marks from docstrings and Release imports....
Fernando Perez -
Show More

The requested changes are too big and content was truncated. Show full diff

@@ -1,182 +1,177 b''
1 1 # -*- coding: utf-8 -*-
2 2 """Tools for coloring text in ANSI terminals.
3
4 $Id: ColorANSI.py 2167 2007-03-21 06:57:50Z fperez $"""
3 """
5 4
6 5 #*****************************************************************************
7 6 # Copyright (C) 2002-2006 Fernando Perez. <fperez@colorado.edu>
8 7 #
9 8 # Distributed under the terms of the BSD License. The full license is in
10 9 # the file COPYING, distributed as part of this software.
11 10 #*****************************************************************************
12 11
13 from IPython import Release
14 __author__ = '%s <%s>' % Release.authors['Fernando']
15 __license__ = Release.license
16
17 12 __all__ = ['TermColors','InputTermColors','ColorScheme','ColorSchemeTable']
18 13
19 14 import os
20 15
21 16 from IPython.ipstruct import Struct
22 17
23 18 def make_color_table(in_class):
24 19 """Build a set of color attributes in a class.
25 20
26 21 Helper function for building the *TermColors classes."""
27 22
28 23 color_templates = (
29 24 # Dark colors
30 25 ("Black" , "0;30"),
31 26 ("Red" , "0;31"),
32 27 ("Green" , "0;32"),
33 28 ("Brown" , "0;33"),
34 29 ("Blue" , "0;34"),
35 30 ("Purple" , "0;35"),
36 31 ("Cyan" , "0;36"),
37 32 ("LightGray" , "0;37"),
38 33 # Light colors
39 34 ("DarkGray" , "1;30"),
40 35 ("LightRed" , "1;31"),
41 36 ("LightGreen" , "1;32"),
42 37 ("Yellow" , "1;33"),
43 38 ("LightBlue" , "1;34"),
44 39 ("LightPurple" , "1;35"),
45 40 ("LightCyan" , "1;36"),
46 41 ("White" , "1;37"),
47 42 # Blinking colors. Probably should not be used in anything serious.
48 43 ("BlinkBlack" , "5;30"),
49 44 ("BlinkRed" , "5;31"),
50 45 ("BlinkGreen" , "5;32"),
51 46 ("BlinkYellow" , "5;33"),
52 47 ("BlinkBlue" , "5;34"),
53 48 ("BlinkPurple" , "5;35"),
54 49 ("BlinkCyan" , "5;36"),
55 50 ("BlinkLightGray", "5;37"),
56 51 )
57 52
58 53 for name,value in color_templates:
59 54 setattr(in_class,name,in_class._base % value)
60 55
61 56 class TermColors:
62 57 """Color escape sequences.
63 58
64 59 This class defines the escape sequences for all the standard (ANSI?)
65 60 colors in terminals. Also defines a NoColor escape which is just the null
66 61 string, suitable for defining 'dummy' color schemes in terminals which get
67 62 confused by color escapes.
68 63
69 64 This class should be used as a mixin for building color schemes."""
70 65
71 66 NoColor = '' # for color schemes in color-less terminals.
72 67 Normal = '\033[0m' # Reset normal coloring
73 68 _base = '\033[%sm' # Template for all other colors
74 69
75 70 # Build the actual color table as a set of class attributes:
76 71 make_color_table(TermColors)
77 72
78 73 class InputTermColors:
79 74 """Color escape sequences for input prompts.
80 75
81 76 This class is similar to TermColors, but the escapes are wrapped in \001
82 77 and \002 so that readline can properly know the length of each line and
83 78 can wrap lines accordingly. Use this class for any colored text which
84 79 needs to be used in input prompts, such as in calls to raw_input().
85 80
86 81 This class defines the escape sequences for all the standard (ANSI?)
87 82 colors in terminals. Also defines a NoColor escape which is just the null
88 83 string, suitable for defining 'dummy' color schemes in terminals which get
89 84 confused by color escapes.
90 85
91 86 This class should be used as a mixin for building color schemes."""
92 87
93 88 NoColor = '' # for color schemes in color-less terminals.
94 89
95 90 if os.name == 'nt' and os.environ.get('TERM','dumb') == 'emacs':
96 91 # (X)emacs on W32 gets confused with \001 and \002 so we remove them
97 92 Normal = '\033[0m' # Reset normal coloring
98 93 _base = '\033[%sm' # Template for all other colors
99 94 else:
100 95 Normal = '\001\033[0m\002' # Reset normal coloring
101 96 _base = '\001\033[%sm\002' # Template for all other colors
102 97
103 98 # Build the actual color table as a set of class attributes:
104 99 make_color_table(InputTermColors)
105 100
106 101 class ColorScheme:
107 102 """Generic color scheme class. Just a name and a Struct."""
108 103 def __init__(self,__scheme_name_,colordict=None,**colormap):
109 104 self.name = __scheme_name_
110 105 if colordict is None:
111 106 self.colors = Struct(**colormap)
112 107 else:
113 108 self.colors = Struct(colordict)
114 109
115 110 def copy(self,name=None):
116 111 """Return a full copy of the object, optionally renaming it."""
117 112 if name is None:
118 113 name = self.name
119 114 return ColorScheme(name,self.colors.__dict__)
120 115
121 116 class ColorSchemeTable(dict):
122 117 """General class to handle tables of color schemes.
123 118
124 119 It's basically a dict of color schemes with a couple of shorthand
125 120 attributes and some convenient methods.
126 121
127 122 active_scheme_name -> obvious
128 123 active_colors -> actual color table of the active scheme"""
129 124
130 125 def __init__(self,scheme_list=None,default_scheme=''):
131 126 """Create a table of color schemes.
132 127
133 128 The table can be created empty and manually filled or it can be
134 129 created with a list of valid color schemes AND the specification for
135 130 the default active scheme.
136 131 """
137 132
138 133 # create object attributes to be set later
139 134 self.active_scheme_name = ''
140 135 self.active_colors = None
141 136
142 137 if scheme_list:
143 138 if default_scheme == '':
144 139 raise ValueError,'you must specify the default color scheme'
145 140 for scheme in scheme_list:
146 141 self.add_scheme(scheme)
147 142 self.set_active_scheme(default_scheme)
148 143
149 144 def copy(self):
150 145 """Return full copy of object"""
151 146 return ColorSchemeTable(self.values(),self.active_scheme_name)
152 147
153 148 def add_scheme(self,new_scheme):
154 149 """Add a new color scheme to the table."""
155 150 if not isinstance(new_scheme,ColorScheme):
156 151 raise ValueError,'ColorSchemeTable only accepts ColorScheme instances'
157 152 self[new_scheme.name] = new_scheme
158 153
159 154 def set_active_scheme(self,scheme,case_sensitive=0):
160 155 """Set the currently active scheme.
161 156
162 157 Names are by default compared in a case-insensitive way, but this can
163 158 be changed by setting the parameter case_sensitive to true."""
164 159
165 160 scheme_names = self.keys()
166 161 if case_sensitive:
167 162 valid_schemes = scheme_names
168 163 scheme_test = scheme
169 164 else:
170 165 valid_schemes = [s.lower() for s in scheme_names]
171 166 scheme_test = scheme.lower()
172 167 try:
173 168 scheme_idx = valid_schemes.index(scheme_test)
174 169 except ValueError:
175 170 raise ValueError,'Unrecognized color scheme: ' + scheme + \
176 171 '\nValid schemes: '+str(scheme_names).replace("'', ",'')
177 172 else:
178 173 active = scheme_names[scheme_idx]
179 174 self.active_scheme_name = active
180 175 self.active_colors = self[active].colors
181 176 # Now allow using '' as an index for the current active scheme
182 177 self[''] = self[active]
@@ -1,116 +1,111 b''
1 1 # -*- coding: utf-8 -*-
2 2 """Configuration loader
3
4 $Id: ConfigLoader.py 1005 2006-01-12 08:39:26Z fperez $"""
3 """
5 4
6 5 #*****************************************************************************
7 6 # Copyright (C) 2001-2006 Fernando Perez. <fperez@colorado.edu>
8 7 #
9 8 # Distributed under the terms of the BSD License. The full license is in
10 9 # the file COPYING, distributed as part of this software.
11 10 #*****************************************************************************
12 11
13 from IPython import Release
14 __author__ = '%s <%s>' % Release.authors['Fernando']
15 __license__ = Release.license
16
17 12 import exceptions
18 13 import os
19 14 from pprint import pprint
20 15
21 16 from IPython import ultraTB
22 17 from IPython.ipstruct import Struct
23 18 from IPython.genutils import *
24 19
25 20 class ConfigLoaderError(exceptions.Exception):
26 21 """Exception for ConfigLoader class."""
27 22
28 23 def __init__(self,args=None):
29 24 self.args = args
30 25
31 26 class ConfigLoader:
32 27
33 28 """Configuration file loader capable of handling recursive inclusions and
34 29 with parametrized conflict resolution for multiply found keys."""
35 30
36 31 def __init__(self,conflict=None,field_sep=None,reclimit=15):
37 32
38 33 """The reclimit parameter controls the number of recursive
39 34 configuration file inclusions. This way we can stop early on (before
40 35 python's own recursion limit is hit) if there is a circular
41 36 inclusion.
42 37
43 38 - conflict: dictionary for conflict resolutions (see Struct.merge())
44 39
45 40 """
46 41 self.conflict = conflict
47 42 self.field_sep = field_sep
48 43 self.reset(reclimit)
49 44
50 45 def reset(self,reclimit=15):
51 46 self.reclimit = reclimit
52 47 self.recdepth = 0
53 48 self.included = []
54 49
55 50 def load(self,fname,convert=None,recurse_key='',incpath = '.',**kw):
56 51 """Load a configuration file, return the resulting Struct.
57 52
58 53 Call: load_config(fname,convert=None,conflict=None,recurse_key='')
59 54
60 55 - fname: file to load from.
61 56 - convert: dictionary of type conversions (see read_dict())
62 57 - recurse_key: keyword in dictionary to trigger recursive file
63 58 inclusions.
64 59 """
65 60
66 61 if self.recdepth > self.reclimit:
67 62 raise ConfigLoaderError, 'maximum recursive inclusion of rcfiles '+\
68 63 'exceeded: ' + `self.recdepth` + \
69 64 '.\nMaybe you have a circular chain of inclusions?'
70 65 self.recdepth += 1
71 66 fname = filefind(fname,incpath)
72 67 data = Struct()
73 68 # avoid including the same file more than once
74 69 if fname in self.included:
75 70 return data
76 71 Xinfo = ultraTB.AutoFormattedTB(color_scheme='NoColor')
77 72 if convert==None and recurse_key : convert = {qwflat:recurse_key}
78 73 # for production, change warn to 0:
79 74 data.merge(read_dict(fname,convert,fs=self.field_sep,strip=1,
80 75 warn=0,no_empty=0,**kw))
81 76 # keep track of successfully loaded files
82 77 self.included.append(fname)
83 78 if recurse_key in data:
84 79 for incfilename in data[recurse_key]:
85 80 found=0
86 81 try:
87 82 incfile = filefind(incfilename,incpath)
88 83 except IOError:
89 84 if os.name in ['nt','dos']:
90 85 try:
91 86 # Try again with '.ini' extension
92 87 incfilename += '.ini'
93 88 incfile = filefind(incfilename,incpath)
94 89 except IOError:
95 90 found = 0
96 91 else:
97 92 found = 1
98 93 else:
99 94 found = 0
100 95 else:
101 96 found = 1
102 97 if found:
103 98 try:
104 99 data.merge(self.load(incfile,convert,recurse_key,
105 100 incpath,**kw),
106 101 self.conflict)
107 102 except:
108 103 Xinfo()
109 104 warn('Problem loading included file: '+
110 105 `incfilename` + '. Ignoring it...')
111 106 else:
112 107 warn('File `%s` not found. Included by %s' % (incfilename,fname))
113 108
114 109 return data
115 110
116 111 # end ConfigLoader
@@ -1,228 +1,227 b''
1 1 # -*- coding: utf-8 -*-
2 2 """sys.excepthook for IPython itself, leaves a detailed report on disk.
3
4 $Id: CrashHandler.py 2908 2007-12-30 21:07:46Z vivainio $"""
3 """
5 4
6 5 #*****************************************************************************
7 6 # Copyright (C) 2001-2006 Fernando Perez. <fperez@colorado.edu>
8 7 #
9 8 # Distributed under the terms of the BSD License. The full license is in
10 9 # the file COPYING, distributed as part of this software.
11 10 #*****************************************************************************
12 11
13 12 from IPython import Release
14 13 __author__ = '%s <%s>' % Release.authors['Fernando']
15 14 __license__ = Release.license
16 15 __version__ = Release.version
17 16
18 17 #****************************************************************************
19 18 # Required modules
20 19
21 20 # From the standard library
22 21 import os
23 22 import sys
24 23 from pprint import pprint,pformat
25 24
26 25 # Homebrewed
27 26 from IPython.Itpl import Itpl,itpl,printpl
28 27 from IPython.ColorANSI import ColorScheme,ColorSchemeTable # too long names
29 28 from IPython import ultraTB
30 29 from IPython.genutils import *
31 30
32 31 #****************************************************************************
33 32 class CrashHandler:
34 33 """Customizable crash handlers for IPython-based systems.
35 34
36 35 Instances of this class provide a __call__ method which can be used as a
37 36 sys.excepthook, i.e., the __call__ signature is:
38 37
39 38 def __call__(self,etype, evalue, etb)
40 39
41 40 """
42 41
43 42 def __init__(self,IP,app_name,contact_name,contact_email,
44 43 bug_tracker,crash_report_fname,
45 44 show_crash_traceback=True):
46 45 """New crash handler.
47 46
48 47 Inputs:
49 48
50 49 - IP: a running IPython instance, which will be queried at crash time
51 50 for internal information.
52 51
53 52 - app_name: a string containing the name of your application.
54 53
55 54 - contact_name: a string with the name of the person to contact.
56 55
57 56 - contact_email: a string with the email address of the contact.
58 57
59 58 - bug_tracker: a string with the URL for your project's bug tracker.
60 59
61 60 - crash_report_fname: a string with the filename for the crash report
62 61 to be saved in. These reports are left in the ipython user directory
63 62 as determined by the running IPython instance.
64 63
65 64 Optional inputs:
66 65
67 66 - show_crash_traceback(True): if false, don't print the crash
68 67 traceback on stderr, only generate the on-disk report
69 68
70 69
71 70 Non-argument instance attributes:
72 71
73 72 These instances contain some non-argument attributes which allow for
74 73 further customization of the crash handler's behavior. Please see the
75 74 source for further details.
76 75 """
77 76
78 77 # apply args into instance
79 78 self.IP = IP # IPython instance
80 79 self.app_name = app_name
81 80 self.contact_name = contact_name
82 81 self.contact_email = contact_email
83 82 self.bug_tracker = bug_tracker
84 83 self.crash_report_fname = crash_report_fname
85 84 self.show_crash_traceback = show_crash_traceback
86 85
87 86 # Hardcoded defaults, which can be overridden either by subclasses or
88 87 # at runtime for the instance.
89 88
90 89 # Template for the user message. Subclasses which completely override
91 90 # this, or user apps, can modify it to suit their tastes. It gets
92 91 # expanded using itpl, so calls of the kind $self.foo are valid.
93 92 self.user_message_template = """
94 93 Oops, $self.app_name crashed. We do our best to make it stable, but...
95 94
96 95 A crash report was automatically generated with the following information:
97 96 - A verbatim copy of the crash traceback.
98 97 - A copy of your input history during this session.
99 98 - Data on your current $self.app_name configuration.
100 99
101 100 It was left in the file named:
102 101 \t'$self.crash_report_fname'
103 102 If you can email this file to the developers, the information in it will help
104 103 them in understanding and correcting the problem.
105 104
106 105 You can mail it to: $self.contact_name at $self.contact_email
107 106 with the subject '$self.app_name Crash Report'.
108 107
109 108 If you want to do it now, the following command will work (under Unix):
110 109 mail -s '$self.app_name Crash Report' $self.contact_email < $self.crash_report_fname
111 110
112 111 To ensure accurate tracking of this issue, please file a report about it at:
113 112 $self.bug_tracker
114 113 """
115 114
116 115 def __call__(self,etype, evalue, etb):
117 116 """Handle an exception, call for compatible with sys.excepthook"""
118 117
119 118 # Report tracebacks shouldn't use color in general (safer for users)
120 119 color_scheme = 'NoColor'
121 120
122 121 # Use this ONLY for developer debugging (keep commented out for release)
123 122 #color_scheme = 'Linux' # dbg
124 123
125 124 try:
126 125 rptdir = self.IP.rc.ipythondir
127 126 except:
128 127 rptdir = os.getcwd()
129 128 if not os.path.isdir(rptdir):
130 129 rptdir = os.getcwd()
131 130 report_name = os.path.join(rptdir,self.crash_report_fname)
132 131 # write the report filename into the instance dict so it can get
133 132 # properly expanded out in the user message template
134 133 self.crash_report_fname = report_name
135 134 TBhandler = ultraTB.VerboseTB(color_scheme=color_scheme,
136 135 long_header=1)
137 136 traceback = TBhandler.text(etype,evalue,etb,context=31)
138 137
139 138 # print traceback to screen
140 139 if self.show_crash_traceback:
141 140 print >> sys.stderr, traceback
142 141
143 142 # and generate a complete report on disk
144 143 try:
145 144 report = open(report_name,'w')
146 145 except:
147 146 print >> sys.stderr, 'Could not create crash report on disk.'
148 147 return
149 148
150 149 # Inform user on stderr of what happened
151 150 msg = itpl('\n'+'*'*70+'\n'+self.user_message_template)
152 151 print >> sys.stderr, msg
153 152
154 153 # Construct report on disk
155 154 report.write(self.make_report(traceback))
156 155 report.close()
157 156 raw_input("Press enter to exit:")
158 157
159 158 def make_report(self,traceback):
160 159 """Return a string containing a crash report."""
161 160
162 161 sec_sep = '\n\n'+'*'*75+'\n\n'
163 162
164 163 report = []
165 164 rpt_add = report.append
166 165
167 166 rpt_add('*'*75+'\n\n'+'IPython post-mortem report\n\n')
168 167 rpt_add('IPython version: %s \n\n' % Release.version)
169 168 rpt_add('SVN revision : %s \n\n' % Release.revision)
170 169 rpt_add('Platform info : os.name -> %s, sys.platform -> %s' %
171 170 (os.name,sys.platform) )
172 171 rpt_add(sec_sep+'Current user configuration structure:\n\n')
173 172 rpt_add(pformat(self.IP.rc.dict()))
174 173 rpt_add(sec_sep+'Crash traceback:\n\n' + traceback)
175 174 try:
176 175 rpt_add(sec_sep+"History of session input:")
177 176 for line in self.IP.user_ns['_ih']:
178 177 rpt_add(line)
179 178 rpt_add('\n*** Last line of input (may not be in above history):\n')
180 179 rpt_add(self.IP._last_input_line+'\n')
181 180 except:
182 181 pass
183 182
184 183 return ''.join(report)
185 184
186 185 class IPythonCrashHandler(CrashHandler):
187 186 """sys.excepthook for IPython itself, leaves a detailed report on disk."""
188 187
189 188 def __init__(self,IP):
190 189
191 190 # Set here which of the IPython authors should be listed as contact
192 191 AUTHOR_CONTACT = 'Ville'
193 192
194 193 # Set argument defaults
195 194 app_name = 'IPython'
196 195 bug_tracker = 'http://projects.scipy.org/ipython/ipython/report'
197 196 contact_name,contact_email = Release.authors[AUTHOR_CONTACT][:2]
198 197 crash_report_fname = 'IPython_crash_report.txt'
199 198 # Call parent constructor
200 199 CrashHandler.__init__(self,IP,app_name,contact_name,contact_email,
201 200 bug_tracker,crash_report_fname)
202 201
203 202 def make_report(self,traceback):
204 203 """Return a string containing a crash report."""
205 204
206 205 sec_sep = '\n\n'+'*'*75+'\n\n'
207 206
208 207 report = []
209 208 rpt_add = report.append
210 209
211 210 rpt_add('*'*75+'\n\n'+'IPython post-mortem report\n\n')
212 211 rpt_add('IPython version: %s \n\n' % Release.version)
213 212 rpt_add('SVN revision : %s \n\n' % Release.revision)
214 213 rpt_add('Platform info : os.name -> %s, sys.platform -> %s' %
215 214 (os.name,sys.platform) )
216 215 rpt_add(sec_sep+'Current user configuration structure:\n\n')
217 216 rpt_add(pformat(self.IP.rc.dict()))
218 217 rpt_add(sec_sep+'Crash traceback:\n\n' + traceback)
219 218 try:
220 219 rpt_add(sec_sep+"History of session input:")
221 220 for line in self.IP.user_ns['_ih']:
222 221 rpt_add(line)
223 222 rpt_add('\n*** Last line of input (may not be in above history):\n')
224 223 rpt_add(self.IP._last_input_line+'\n')
225 224 except:
226 225 pass
227 226
228 227 return ''.join(report)
@@ -1,693 +1,690 b''
1 1 # -*- coding: utf-8 -*-
2 2 """DPyGetOpt -- Demiurge Python GetOptions Module
3 3
4 $Id: DPyGetOpt.py 2872 2007-11-25 17:58:05Z fperez $
5
6 4 This module is modeled after perl's Getopt::Long module-- which
7 5 is, in turn, modeled after GNU's extended getopt() function.
8 6
9 7 Upon instantiation, the option specification should be a sequence
10 8 (list) of option definitions.
11 9
12 10 Options that take no arguments should simply contain the name of
13 11 the option. If a ! is post-pended, the option can be negated by
14 12 prepending 'no'; ie 'debug!' specifies that -debug and -nodebug
15 13 should be accepted.
16 14
17 15 Mandatory arguments to options are specified using a postpended
18 16 '=' + a type specifier. '=s' specifies a mandatory string
19 17 argument, '=i' specifies a mandatory integer argument, and '=f'
20 18 specifies a mandatory real number. In all cases, the '=' can be
21 19 substituted with ':' to specify that the argument is optional.
22 20
23 21 Dashes '-' in option names are allowed.
24 22
25 23 If an option has the character '@' postpended (after the
26 24 argumentation specification), it can appear multiple times within
27 25 each argument list that is processed. The results will be stored
28 26 in a list.
29 27
30 28 The option name can actually be a list of names separated by '|'
31 29 characters; ie-- 'foo|bar|baz=f@' specifies that all -foo, -bar,
32 30 and -baz options that appear on within the parsed argument list
33 31 must have a real number argument and that the accumulated list
34 32 of values will be available under the name 'foo'
35
36 $Id: DPyGetOpt.py 2872 2007-11-25 17:58:05Z fperez $"""
33 """
37 34
38 35 #*****************************************************************************
39 36 #
40 37 # Copyright (c) 2001 Bill Bumgarner <bbum@friday.com>
41 38 #
42 39 #
43 40 # Published under the terms of the MIT license, hereby reproduced:
44 41 #
45 42 # Permission is hereby granted, free of charge, to any person obtaining a copy
46 43 # of this software and associated documentation files (the "Software"), to
47 44 # deal in the Software without restriction, including without limitation the
48 45 # rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
49 46 # sell copies of the Software, and to permit persons to whom the Software is
50 47 # furnished to do so, subject to the following conditions:
51 48 #
52 49 # The above copyright notice and this permission notice shall be included in
53 50 # all copies or substantial portions of the Software.
54 51 #
55 52 # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
56 53 # IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
57 54 # FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
58 55 # AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
59 56 # LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
60 57 # FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
61 58 # IN THE SOFTWARE.
62 59 #
63 60 #*****************************************************************************
64 61
65 62 __author__ = 'Bill Bumgarner <bbum@friday.com>'
66 63 __license__ = 'MIT'
67 64 __version__ = '1.2'
68 65
69 66 # Modified to use re instead of regex and regsub modules.
70 67 # 2001/5/7, Jonathan Hogg <jonathan@onegoodidea.com>
71 68
72 69 import re
73 70 import string
74 71 import sys
75 72 import types
76 73
77 74 class Error(Exception):
78 75 """Base class for exceptions in the DPyGetOpt module."""
79 76
80 77 class ArgumentError(Error):
81 78 """Exception indicating an error in the arguments passed to
82 79 DPyGetOpt.processArguments."""
83 80
84 81 class SpecificationError(Error):
85 82 """Exception indicating an error with an option specification."""
86 83
87 84 class TerminationError(Error):
88 85 """Exception indicating an error with an option processing terminator."""
89 86
90 87 specificationExpr = re.compile('(?P<required>.)(?P<type>.)(?P<multi>@?)')
91 88
92 89 ArgRequired = 'Requires an Argument'
93 90 ArgOptional = 'Argument Optional'
94 91
95 92 # The types modules is not used for these identifiers because there
96 93 # is no identifier for 'boolean' or 'generic'
97 94 StringArgType = 'String Argument Type'
98 95 IntegerArgType = 'Integer Argument Type'
99 96 RealArgType = 'Real Argument Type'
100 97 BooleanArgType = 'Boolean Argument Type'
101 98 GenericArgType = 'Generic Argument Type'
102 99
103 100 # dictionary of conversion functions-- boolean and generic options
104 101 # do not accept arguments and do not need conversion functions;
105 102 # the identity function is used purely for convenience.
106 103 ConversionFunctions = {
107 104 StringArgType : lambda x: x,
108 105 IntegerArgType : string.atoi,
109 106 RealArgType : string.atof,
110 107 BooleanArgType : lambda x: x,
111 108 GenericArgType : lambda x: x,
112 109 }
113 110
114 111 class DPyGetOpt:
115 112
116 113 def __init__(self, spec = None, terminators = ['--']):
117 114 """
118 115 Declare and intialize instance variables
119 116
120 117 Yes, declaration is not necessary... but one of the things
121 118 I sorely miss from C/Obj-C is the concept of having an
122 119 interface definition that clearly declares all instance
123 120 variables and methods without providing any implementation
124 121 details. it is a useful reference!
125 122
126 123 all instance variables are initialized to 0/Null/None of
127 124 the appropriate type-- not even the default value...
128 125 """
129 126
130 127 # sys.stderr.write(string.join(spec) + "\n")
131 128
132 129 self.allowAbbreviations = 1 # boolean, 1 if abbreviations will
133 130 # be expanded
134 131 self.freeValues = [] # list, contains free values
135 132 self.ignoreCase = 0 # boolean, YES if ignoring case
136 133 self.needsParse = 0 # boolean, YES if need to reparse parameter spec
137 134 self.optionNames = {} # dict, all option names-- value is index of tuple
138 135 self.optionStartExpr = None # regexp defining the start of an option (ie; '-', '--')
139 136 self.optionTuples = [] # list o' tuples containing defn of options AND aliases
140 137 self.optionValues = {} # dict, option names (after alias expansion) -> option value(s)
141 138 self.orderMixed = 0 # boolean, YES if options can be mixed with args
142 139 self.posixCompliance = 0 # boolean, YES indicates posix like behaviour
143 140 self.spec = [] # list, raw specs (in case it must be reparsed)
144 141 self.terminators = terminators # list, strings that terminate argument processing
145 142 self.termValues = [] # list, values after terminator
146 143 self.terminator = None # full name of terminator that ended
147 144 # option processing
148 145
149 146 # set up defaults
150 147 self.setPosixCompliance()
151 148 self.setIgnoreCase()
152 149 self.setAllowAbbreviations()
153 150
154 151 # parse spec-- if present
155 152 if spec:
156 153 self.parseConfiguration(spec)
157 154
158 155 def setPosixCompliance(self, aFlag = 0):
159 156 """
160 157 Enables and disables posix compliance.
161 158
162 159 When enabled, '+' can be used as an option prefix and free
163 160 values can be mixed with options.
164 161 """
165 162 self.posixCompliance = aFlag
166 163 self.needsParse = 1
167 164
168 165 if self.posixCompliance:
169 166 self.optionStartExpr = re.compile('(--|-)(?P<option>[A-Za-z0-9_-]+)(?P<arg>=.*)?')
170 167 self.orderMixed = 0
171 168 else:
172 169 self.optionStartExpr = re.compile('(--|-|\+)(?P<option>[A-Za-z0-9_-]+)(?P<arg>=.*)?')
173 170 self.orderMixed = 1
174 171
175 172 def isPosixCompliant(self):
176 173 """
177 174 Returns the value of the posix compliance flag.
178 175 """
179 176 return self.posixCompliance
180 177
181 178 def setIgnoreCase(self, aFlag = 1):
182 179 """
183 180 Enables and disables ignoring case during option processing.
184 181 """
185 182 self.needsParse = 1
186 183 self.ignoreCase = aFlag
187 184
188 185 def ignoreCase(self):
189 186 """
190 187 Returns 1 if the option processor will ignore case when
191 188 processing options.
192 189 """
193 190 return self.ignoreCase
194 191
195 192 def setAllowAbbreviations(self, aFlag = 1):
196 193 """
197 194 Enables and disables the expansion of abbreviations during
198 195 option processing.
199 196 """
200 197 self.allowAbbreviations = aFlag
201 198
202 199 def willAllowAbbreviations(self):
203 200 """
204 201 Returns 1 if abbreviated options will be automatically
205 202 expanded to the non-abbreviated form (instead of causing an
206 203 unrecognized option error).
207 204 """
208 205 return self.allowAbbreviations
209 206
210 207 def addTerminator(self, newTerm):
211 208 """
212 209 Adds newTerm as terminator of option processing.
213 210
214 211 Whenever the option processor encounters one of the terminators
215 212 during option processing, the processing of options terminates
216 213 immediately, all remaining options are stored in the termValues
217 214 instance variable and the full name of the terminator is stored
218 215 in the terminator instance variable.
219 216 """
220 217 self.terminators = self.terminators + [newTerm]
221 218
222 219 def _addOption(self, oTuple):
223 220 """
224 221 Adds the option described by oTuple (name, (type, mode,
225 222 default), alias) to optionTuples. Adds index keyed under name
226 223 to optionNames. Raises SpecificationError if name already in
227 224 optionNames
228 225 """
229 226 (name, (type, mode, default, multi), realName) = oTuple
230 227
231 228 # verify name and add to option names dictionary
232 229 if self.optionNames.has_key(name):
233 230 if realName:
234 231 raise SpecificationError('Alias \'' + name + '\' for \'' +
235 232 realName +
236 233 '\' already used for another option or alias.')
237 234 else:
238 235 raise SpecificationError('Option named \'' + name +
239 236 '\' specified more than once. Specification: '
240 237 + option)
241 238
242 239 # validated. add to optionNames
243 240 self.optionNames[name] = self.tupleIndex
244 241 self.tupleIndex = self.tupleIndex + 1
245 242
246 243 # add to optionTuples
247 244 self.optionTuples = self.optionTuples + [oTuple]
248 245
249 246 # if type is boolean, add negation
250 247 if type == BooleanArgType:
251 248 alias = 'no' + name
252 249 specTuple = (type, mode, 0, multi)
253 250 oTuple = (alias, specTuple, name)
254 251
255 252 # verify name and add to option names dictionary
256 253 if self.optionNames.has_key(alias):
257 254 if realName:
258 255 raise SpecificationError('Negated alias \'' + name +
259 256 '\' for \'' + realName +
260 257 '\' already used for another option or alias.')
261 258 else:
262 259 raise SpecificationError('Negated option named \'' + name +
263 260 '\' specified more than once. Specification: '
264 261 + option)
265 262
266 263 # validated. add to optionNames
267 264 self.optionNames[alias] = self.tupleIndex
268 265 self.tupleIndex = self.tupleIndex + 1
269 266
270 267 # add to optionTuples
271 268 self.optionTuples = self.optionTuples + [oTuple]
272 269
273 270 def addOptionConfigurationTuple(self, oTuple):
274 271 (name, argSpec, realName) = oTuple
275 272 if self.ignoreCase:
276 273 name = string.lower(name)
277 274 if realName:
278 275 realName = string.lower(realName)
279 276 else:
280 277 realName = name
281 278
282 279 oTuple = (name, argSpec, realName)
283 280
284 281 # add option
285 282 self._addOption(oTuple)
286 283
287 284 def addOptionConfigurationTuples(self, oTuple):
288 285 if type(oTuple) is ListType:
289 286 for t in oTuple:
290 287 self.addOptionConfigurationTuple(t)
291 288 else:
292 289 self.addOptionConfigurationTuple(oTuple)
293 290
294 291 def parseConfiguration(self, spec):
295 292 # destroy previous stored information + store raw spec
296 293 self.spec = spec
297 294 self.optionTuples = []
298 295 self.optionNames = {}
299 296 self.tupleIndex = 0
300 297
301 298 tupleIndex = 0
302 299
303 300 # create some regex's for parsing each spec
304 301 splitExpr = \
305 302 re.compile('(?P<names>\w+[-A-Za-z0-9|]*)?(?P<spec>!|[=:][infs]@?)?')
306 303 for option in spec:
307 304 # push to lower case (does not negatively affect
308 305 # specification)
309 306 if self.ignoreCase:
310 307 option = string.lower(option)
311 308
312 309 # break into names, specification
313 310 match = splitExpr.match(option)
314 311 if match is None:
315 312 raise SpecificationError('Invalid specification {' + option +
316 313 '}')
317 314
318 315 names = match.group('names')
319 316 specification = match.group('spec')
320 317
321 318 # break name into name, aliases
322 319 nlist = string.split(names, '|')
323 320
324 321 # get name
325 322 name = nlist[0]
326 323 aliases = nlist[1:]
327 324
328 325 # specificationExpr = regex.symcomp('\(<required>.\)\(<type>.\)\(<multi>@?\)')
329 326 if not specification:
330 327 #spec tuple is ('type', 'arg mode', 'default value', 'multiple')
331 328 argType = GenericArgType
332 329 argMode = None
333 330 argDefault = 1
334 331 argMultiple = 0
335 332 elif specification == '!':
336 333 argType = BooleanArgType
337 334 argMode = None
338 335 argDefault = 1
339 336 argMultiple = 0
340 337 else:
341 338 # parse
342 339 match = specificationExpr.match(specification)
343 340 if match is None:
344 341 # failed to parse, die
345 342 raise SpecificationError('Invalid configuration for option \''
346 343 + option + '\'')
347 344
348 345 # determine mode
349 346 required = match.group('required')
350 347 if required == '=':
351 348 argMode = ArgRequired
352 349 elif required == ':':
353 350 argMode = ArgOptional
354 351 else:
355 352 raise SpecificationError('Unknown requirement configuration \''
356 353 + required + '\'')
357 354
358 355 # determine type
359 356 type = match.group('type')
360 357 if type == 's':
361 358 argType = StringArgType
362 359 argDefault = ''
363 360 elif type == 'i':
364 361 argType = IntegerArgType
365 362 argDefault = 1
366 363 elif type == 'f' or type == 'n':
367 364 argType = RealArgType
368 365 argDefault = 1
369 366 else:
370 367 raise SpecificationError('Unknown type specifier \'' +
371 368 type + '\'')
372 369
373 370 # determine quantity
374 371 if match.group('multi') == '@':
375 372 argMultiple = 1
376 373 else:
377 374 argMultiple = 0
378 375 ## end else (of not specification)
379 376
380 377 # construct specification tuple
381 378 specTuple = (argType, argMode, argDefault, argMultiple)
382 379
383 380 # add the option-- option tuple is (name, specTuple, real name)
384 381 oTuple = (name, specTuple, name)
385 382 self._addOption(oTuple)
386 383
387 384 for alias in aliases:
388 385 # drop to all lower (if configured to do so)
389 386 if self.ignoreCase:
390 387 alias = string.lower(alias)
391 388 # create configuration tuple
392 389 oTuple = (alias, specTuple, name)
393 390 # add
394 391 self._addOption(oTuple)
395 392
396 393 # successfully parsed....
397 394 self.needsParse = 0
398 395
399 396 def _getArgTuple(self, argName):
400 397 """
401 398 Returns a list containing all the specification tuples that
402 399 match argName. If none match, None is returned. If one
403 400 matches, a list with one tuple is returned. If more than one
404 401 match, a list containing all the tuples that matched is
405 402 returned.
406 403
407 404 In other words, this function does not pass judgement upon the
408 405 validity of multiple matches.
409 406 """
410 407 # is it in the optionNames dict?
411 408
412 409 try:
413 410 # sys.stderr.write(argName + string.join(self.optionNames.keys()) + "\n")
414 411
415 412 # yes, get index
416 413 tupleIndex = self.optionNames[argName]
417 414 # and return tuple as element of list
418 415 return [self.optionTuples[tupleIndex]]
419 416 except KeyError:
420 417 # are abbreviations allowed?
421 418 if not self.allowAbbreviations:
422 419 # No! terefore, this cannot be valid argument-- nothing found
423 420 return None
424 421
425 422 # argName might be an abbreviation (and, abbreviations must
426 423 # be allowed... or this would not have been reached!)
427 424
428 425 # create regex for argName
429 426 argExpr = re.compile('^' + argName)
430 427
431 428 tuples = filter(lambda x, argExpr=argExpr: argExpr.search(x[0]) is not None,
432 429 self.optionTuples)
433 430
434 431 if not len(tuples):
435 432 return None
436 433 else:
437 434 return tuples
438 435
439 436 def _isTerminator(self, optionName):
440 437 """
441 438 Returns the full name of the terminator if optionName is a valid
442 439 terminator. If it is, sets self.terminator to the full name of
443 440 the terminator.
444 441
445 442 If more than one terminator matched, raises a TerminationError with a
446 443 string describing the ambiguity.
447 444 """
448 445
449 446 # sys.stderr.write(optionName + "\n")
450 447 # sys.stderr.write(repr(self.terminators))
451 448
452 449 if optionName in self.terminators:
453 450 self.terminator = optionName
454 451 elif not self.allowAbbreviations:
455 452 return None
456 453
457 454 # regex thing in bogus
458 455 # termExpr = regex.compile('^' + optionName)
459 456
460 457 terms = filter(lambda x, on=optionName: string.find(x,on) == 0, self.terminators)
461 458
462 459 if not len(terms):
463 460 return None
464 461 elif len(terms) > 1:
465 462 raise TerminationError('Ambiguous terminator \'' + optionName +
466 463 '\' matches ' + repr(terms))
467 464
468 465 self.terminator = terms[0]
469 466 return self.terminator
470 467
471 468 def processArguments(self, args = None):
472 469 """
473 470 Processes args, a list of arguments (including options).
474 471
475 472 If args is the same as sys.argv, automatically trims the first
476 473 argument (the executable name/path).
477 474
478 475 If an exception is not raised, the argument list was parsed
479 476 correctly.
480 477
481 478 Upon successful completion, the freeValues instance variable
482 479 will contain all the arguments that were not associated with an
483 480 option in the order they were encountered. optionValues is a
484 481 dictionary containing the value of each option-- the method
485 482 valueForOption() can be used to query this dictionary.
486 483 terminator will contain the argument encountered that terminated
487 484 option processing (or None, if a terminator was never
488 485 encountered) and termValues will contain all of the options that
489 486 appeared after the Terminator (or an empty list).
490 487 """
491 488
492 489 if hasattr(sys, "argv") and args == sys.argv:
493 490 args = sys.argv[1:]
494 491
495 492 max = len(args) # maximum index + 1
496 493 self.freeValues = [] # array to hold return values
497 494 self.optionValues= {}
498 495 index = 0 # initial index
499 496 self.terminator = None
500 497 self.termValues = []
501 498
502 499 while index < max:
503 500 # obtain argument
504 501 arg = args[index]
505 502 # increment index -- REMEMBER; it is NOW incremented
506 503 index = index + 1
507 504
508 505 # terminate immediately if option terminator encountered
509 506 if self._isTerminator(arg):
510 507 self.freeValues = self.freeValues + args[index:]
511 508 self.termValues = args[index:]
512 509 return
513 510
514 511 # is this possibly an option?
515 512 match = self.optionStartExpr.match(arg)
516 513 if match is None:
517 514 # not an option-- add to freeValues
518 515 self.freeValues = self.freeValues + [arg]
519 516 if not self.orderMixed:
520 517 # mixing not allowed; add rest of args as freeValues
521 518 self.freeValues = self.freeValues + args[index:]
522 519 # return to caller
523 520 return
524 521 else:
525 522 continue
526 523
527 524 # grab name
528 525 optName = match.group('option')
529 526
530 527 # obtain next argument-- index has already been incremented
531 528 nextArg = match.group('arg')
532 529 if nextArg:
533 530 nextArg = nextArg[1:]
534 531 index = index - 1 # put it back
535 532 else:
536 533 try:
537 534 nextArg = args[index]
538 535 except:
539 536 nextArg = None
540 537
541 538 # transpose to lower case, if necessary
542 539 if self.ignoreCase:
543 540 optName = string.lower(optName)
544 541
545 542 # obtain defining tuple
546 543 tuples = self._getArgTuple(optName)
547 544
548 545 if tuples == None:
549 546 raise ArgumentError('Illegal option \'' + arg + '\'')
550 547 elif len(tuples) > 1:
551 548 raise ArgumentError('Ambiguous option \'' + arg +
552 549 '\'; matches ' +
553 550 repr(map(lambda x: x[0], tuples)))
554 551 else:
555 552 config = tuples[0]
556 553
557 554 # config is now set to the configuration tuple for the
558 555 # argument
559 556 (fullName, spec, realName) = config
560 557 (optType, optMode, optDefault, optMultiple) = spec
561 558
562 559 # if opt mode required, but nextArg is none, raise an error
563 560 if (optMode == ArgRequired):
564 561 if (not nextArg) or self._isTerminator(nextArg):
565 562 # print nextArg
566 563 raise ArgumentError('Option \'' + arg +
567 564 '\' requires an argument of type ' +
568 565 optType)
569 566
570 567 if (not optMode == None) and nextArg and (not self._isTerminator(nextArg)):
571 568 # nextArg defined, option configured to possibly consume arg
572 569 try:
573 570 # grab conversion function-- the try is more for internal diagnostics
574 571 func = ConversionFunctions[optType]
575 572 try:
576 573 optionValue = func(nextArg)
577 574 index = index + 1
578 575 except:
579 576 # only raise conversion error if REQUIRED to consume argument
580 577 if optMode == ArgRequired:
581 578 raise ArgumentError('Invalid argument to option \''
582 579 + arg + '\'; should be \'' +
583 580 optType + '\'')
584 581 else:
585 582 optionValue = optDefault
586 583 except ArgumentError:
587 584 raise
588 585 except:
589 586 raise ArgumentError('(' + arg +
590 587 ') Conversion function for \'' +
591 588 optType + '\' not found.')
592 589 else:
593 590 optionValue = optDefault
594 591
595 592 # add value to options dictionary
596 593 if optMultiple:
597 594 # can be multiple values
598 595 try:
599 596 # try to append element
600 597 self.optionValues[realName] = self.optionValues[realName] + [optionValue]
601 598 except:
602 599 # failed-- must not exist; add it
603 600 self.optionValues[realName] = [optionValue]
604 601 else:
605 602 # only one value per
606 603 if self.isPosixCompliant and self.optionValues.has_key(realName):
607 604 raise ArgumentError('Argument \'' + arg +
608 605 '\' occurs multiple times.')
609 606
610 607 self.optionValues[realName] = optionValue
611 608
612 609 def valueForOption(self, optionName, defaultValue = None):
613 610 """
614 611 Return the value associated with optionName. If optionName was
615 612 not encountered during parsing of the arguments, returns the
616 613 defaultValue (which defaults to None).
617 614 """
618 615 try:
619 616 optionValue = self.optionValues[optionName]
620 617 except:
621 618 optionValue = defaultValue
622 619
623 620 return optionValue
624 621
625 622 ##
626 623 ## test/example section
627 624 ##
628 625 test_error = 'Test Run Amok!'
629 626 def _test():
630 627 """
631 628 A relatively complete test suite.
632 629 """
633 630 try:
634 631 DPyGetOpt(['foo', 'bar=s', 'foo'])
635 632 except Error, exc:
636 633 print 'EXCEPTION (should be \'foo\' already used..): %s' % exc
637 634
638 635 try:
639 636 DPyGetOpt(['foo|bar|apple=s@', 'baz|apple!'])
640 637 except Error, exc:
641 638 print 'EXCEPTION (should be duplicate alias/name error): %s' % exc
642 639
643 640 x = DPyGetOpt(['apple|atlas=i@', 'application|executable=f@'])
644 641 try:
645 642 x.processArguments(['-app', '29.3'])
646 643 except Error, exc:
647 644 print 'EXCEPTION (should be ambiguous argument): %s' % exc
648 645
649 646 x = DPyGetOpt(['foo'], ['antigravity', 'antithesis'])
650 647 try:
651 648 x.processArguments(['-foo', 'anti'])
652 649 except Error, exc:
653 650 print 'EXCEPTION (should be ambiguous terminator): %s' % exc
654 651
655 652 profile = ['plain-option',
656 653 'boolean-option!',
657 654 'list-of-integers=i@',
658 655 'list-real-option|list-real-alias|list-real-pseudonym=f@',
659 656 'optional-string-option:s',
660 657 'abbreviated-string-list=s@']
661 658
662 659 terminators = ['terminator']
663 660
664 661 args = ['-plain-option',
665 662 '+noboolean-option',
666 663 '--list-of-integers', '1',
667 664 '+list-of-integers', '2',
668 665 '-list-of-integers', '3',
669 666 'freeargone',
670 667 '-list-real-option', '1.1',
671 668 '+list-real-alias', '1.2',
672 669 '--list-real-pseudonym', '1.3',
673 670 'freeargtwo',
674 671 '-abbreviated-string-list', 'String1',
675 672 '--abbreviated-s', 'String2',
676 673 '-abbrev', 'String3',
677 674 '-a', 'String4',
678 675 '-optional-string-option',
679 676 'term',
680 677 'next option should look like an invalid arg',
681 678 '-a']
682 679
683 680
684 681 print 'Using profile: ' + repr(profile)
685 682 print 'With terminator: ' + repr(terminators)
686 683 print 'Processing arguments: ' + repr(args)
687 684
688 685 go = DPyGetOpt(profile, terminators)
689 686 go.processArguments(args)
690 687
691 688 print 'Options (and values): ' + repr(go.optionValues)
692 689 print 'free args: ' + repr(go.freeValues)
693 690 print 'term args: ' + repr(go.termValues)
@@ -1,528 +1,522 b''
1 1 # -*- coding: utf-8 -*-
2 2 """
3 3 Pdb debugger class.
4 4
5 5 Modified from the standard pdb.Pdb class to avoid including readline, so that
6 6 the command line completion of other programs which include this isn't
7 7 damaged.
8 8
9 9 In the future, this class will be expanded with improvements over the standard
10 10 pdb.
11 11
12 12 The code in this file is mainly lifted out of cmd.py in Python 2.2, with minor
13 13 changes. Licensing should therefore be under the standard Python terms. For
14 14 details on the PSF (Python Software Foundation) standard license, see:
15 15
16 http://www.python.org/2.2.3/license.html
17
18 $Id: Debugger.py 2913 2007-12-31 12:42:14Z vivainio $"""
16 http://www.python.org/2.2.3/license.html"""
19 17
20 18 #*****************************************************************************
21 19 #
22 20 # This file is licensed under the PSF license.
23 21 #
24 22 # Copyright (C) 2001 Python Software Foundation, www.python.org
25 23 # Copyright (C) 2005-2006 Fernando Perez. <fperez@colorado.edu>
26 24 #
27 25 #
28 26 #*****************************************************************************
29 27
30 from IPython import Release
31 __author__ = '%s <%s>' % Release.authors['Fernando']
32 __license__ = 'Python'
33
34 28 import bdb
35 29 import cmd
36 30 import linecache
37 31 import os
38 32 import sys
39 33
40 34 from IPython import PyColorize, ColorANSI, ipapi
41 35 from IPython.genutils import Term
42 36 from IPython.excolors import exception_colors
43 37
44 38 # See if we can use pydb.
45 39 has_pydb = False
46 40 prompt = 'ipdb> '
47 41 #We have to check this directly from sys.argv, config struct not yet available
48 42 if '-pydb' in sys.argv:
49 43 try:
50 44 import pydb
51 45 if hasattr(pydb.pydb, "runl") and pydb.version>'1.17':
52 46 # Version 1.17 is broken, and that's what ships with Ubuntu Edgy, so we
53 47 # better protect against it.
54 48 has_pydb = True
55 49 except ImportError:
56 50 print "Pydb (http://bashdb.sourceforge.net/pydb/) does not seem to be available"
57 51
58 52 if has_pydb:
59 53 from pydb import Pdb as OldPdb
60 54 #print "Using pydb for %run -d and post-mortem" #dbg
61 55 prompt = 'ipydb> '
62 56 else:
63 57 from pdb import Pdb as OldPdb
64 58
65 59 # Allow the set_trace code to operate outside of an ipython instance, even if
66 60 # it does so with some limitations. The rest of this support is implemented in
67 61 # the Tracer constructor.
68 62 def BdbQuit_excepthook(et,ev,tb):
69 63 if et==bdb.BdbQuit:
70 64 print 'Exiting Debugger.'
71 65 else:
72 66 BdbQuit_excepthook.excepthook_ori(et,ev,tb)
73 67
74 68 def BdbQuit_IPython_excepthook(self,et,ev,tb):
75 69 print 'Exiting Debugger.'
76 70
77 71 class Tracer(object):
78 72 """Class for local debugging, similar to pdb.set_trace.
79 73
80 74 Instances of this class, when called, behave like pdb.set_trace, but
81 75 providing IPython's enhanced capabilities.
82 76
83 77 This is implemented as a class which must be initialized in your own code
84 78 and not as a standalone function because we need to detect at runtime
85 79 whether IPython is already active or not. That detection is done in the
86 80 constructor, ensuring that this code plays nicely with a running IPython,
87 81 while functioning acceptably (though with limitations) if outside of it.
88 82 """
89 83
90 84 def __init__(self,colors=None):
91 85 """Create a local debugger instance.
92 86
93 87 :Parameters:
94 88
95 89 - `colors` (None): a string containing the name of the color scheme to
96 90 use, it must be one of IPython's valid color schemes. If not given, the
97 91 function will default to the current IPython scheme when running inside
98 92 IPython, and to 'NoColor' otherwise.
99 93
100 94 Usage example:
101 95
102 96 from IPython.Debugger import Tracer; debug_here = Tracer()
103 97
104 98 ... later in your code
105 99 debug_here() # -> will open up the debugger at that point.
106 100
107 101 Once the debugger activates, you can use all of its regular commands to
108 102 step through code, set breakpoints, etc. See the pdb documentation
109 103 from the Python standard library for usage details.
110 104 """
111 105
112 106 global __IPYTHON__
113 107 try:
114 108 __IPYTHON__
115 109 except NameError:
116 110 # Outside of ipython, we set our own exception hook manually
117 111 __IPYTHON__ = ipapi.get(True,False)
118 112 BdbQuit_excepthook.excepthook_ori = sys.excepthook
119 113 sys.excepthook = BdbQuit_excepthook
120 114 def_colors = 'NoColor'
121 115 try:
122 116 # Limited tab completion support
123 117 import rlcompleter,readline
124 118 readline.parse_and_bind('tab: complete')
125 119 except ImportError:
126 120 pass
127 121 else:
128 122 # In ipython, we use its custom exception handler mechanism
129 123 ip = ipapi.get()
130 124 def_colors = ip.options.colors
131 125 ip.set_custom_exc((bdb.BdbQuit,),BdbQuit_IPython_excepthook)
132 126
133 127 if colors is None:
134 128 colors = def_colors
135 129 self.debugger = Pdb(colors)
136 130
137 131 def __call__(self):
138 132 """Starts an interactive debugger at the point where called.
139 133
140 134 This is similar to the pdb.set_trace() function from the std lib, but
141 135 using IPython's enhanced debugger."""
142 136
143 137 self.debugger.set_trace(sys._getframe().f_back)
144 138
145 139 def decorate_fn_with_doc(new_fn, old_fn, additional_text=""):
146 140 """Make new_fn have old_fn's doc string. This is particularly useful
147 141 for the do_... commands that hook into the help system.
148 142 Adapted from from a comp.lang.python posting
149 143 by Duncan Booth."""
150 144 def wrapper(*args, **kw):
151 145 return new_fn(*args, **kw)
152 146 if old_fn.__doc__:
153 147 wrapper.__doc__ = old_fn.__doc__ + additional_text
154 148 return wrapper
155 149
156 150 def _file_lines(fname):
157 151 """Return the contents of a named file as a list of lines.
158 152
159 153 This function never raises an IOError exception: if the file can't be
160 154 read, it simply returns an empty list."""
161 155
162 156 try:
163 157 outfile = open(fname)
164 158 except IOError:
165 159 return []
166 160 else:
167 161 out = outfile.readlines()
168 162 outfile.close()
169 163 return out
170 164
171 165 class Pdb(OldPdb):
172 166 """Modified Pdb class, does not load readline."""
173 167
174 168 if sys.version[:3] >= '2.5' or has_pydb:
175 169 def __init__(self,color_scheme='NoColor',completekey=None,
176 170 stdin=None, stdout=None):
177 171
178 172 # Parent constructor:
179 173 if has_pydb and completekey is None:
180 174 OldPdb.__init__(self,stdin=stdin,stdout=Term.cout)
181 175 else:
182 176 OldPdb.__init__(self,completekey,stdin,stdout)
183 177
184 178 self.prompt = prompt # The default prompt is '(Pdb)'
185 179
186 180 # IPython changes...
187 181 self.is_pydb = has_pydb
188 182
189 183 if self.is_pydb:
190 184
191 185 # iplib.py's ipalias seems to want pdb's checkline
192 186 # which located in pydb.fn
193 187 import pydb.fns
194 188 self.checkline = lambda filename, lineno: \
195 189 pydb.fns.checkline(self, filename, lineno)
196 190
197 191 self.curframe = None
198 192 self.do_restart = self.new_do_restart
199 193
200 194 self.old_all_completions = __IPYTHON__.Completer.all_completions
201 195 __IPYTHON__.Completer.all_completions=self.all_completions
202 196
203 197 self.do_list = decorate_fn_with_doc(self.list_command_pydb,
204 198 OldPdb.do_list)
205 199 self.do_l = self.do_list
206 200 self.do_frame = decorate_fn_with_doc(self.new_do_frame,
207 201 OldPdb.do_frame)
208 202
209 203 self.aliases = {}
210 204
211 205 # Create color table: we copy the default one from the traceback
212 206 # module and add a few attributes needed for debugging
213 207 self.color_scheme_table = exception_colors()
214 208
215 209 # shorthands
216 210 C = ColorANSI.TermColors
217 211 cst = self.color_scheme_table
218 212
219 213 cst['NoColor'].colors.breakpoint_enabled = C.NoColor
220 214 cst['NoColor'].colors.breakpoint_disabled = C.NoColor
221 215
222 216 cst['Linux'].colors.breakpoint_enabled = C.LightRed
223 217 cst['Linux'].colors.breakpoint_disabled = C.Red
224 218
225 219 cst['LightBG'].colors.breakpoint_enabled = C.LightRed
226 220 cst['LightBG'].colors.breakpoint_disabled = C.Red
227 221
228 222 self.set_colors(color_scheme)
229 223
230 224 # Add a python parser so we can syntax highlight source while
231 225 # debugging.
232 226 self.parser = PyColorize.Parser()
233 227
234 228
235 229 else:
236 230 # Ugly hack: for Python 2.3-2.4, we can't call the parent constructor,
237 231 # because it binds readline and breaks tab-completion. This means we
238 232 # have to COPY the constructor here.
239 233 def __init__(self,color_scheme='NoColor'):
240 234 bdb.Bdb.__init__(self)
241 235 cmd.Cmd.__init__(self,completekey=None) # don't load readline
242 236 self.prompt = 'ipdb> ' # The default prompt is '(Pdb)'
243 237 self.aliases = {}
244 238
245 239 # These two lines are part of the py2.4 constructor, let's put them
246 240 # unconditionally here as they won't cause any problems in 2.3.
247 241 self.mainpyfile = ''
248 242 self._wait_for_mainpyfile = 0
249 243
250 244 # Read $HOME/.pdbrc and ./.pdbrc
251 245 try:
252 246 self.rcLines = _file_lines(os.path.join(os.environ['HOME'],
253 247 ".pdbrc"))
254 248 except KeyError:
255 249 self.rcLines = []
256 250 self.rcLines.extend(_file_lines(".pdbrc"))
257 251
258 252 # Create color table: we copy the default one from the traceback
259 253 # module and add a few attributes needed for debugging
260 254 self.color_scheme_table = exception_colors()
261 255
262 256 # shorthands
263 257 C = ColorANSI.TermColors
264 258 cst = self.color_scheme_table
265 259
266 260 cst['NoColor'].colors.breakpoint_enabled = C.NoColor
267 261 cst['NoColor'].colors.breakpoint_disabled = C.NoColor
268 262
269 263 cst['Linux'].colors.breakpoint_enabled = C.LightRed
270 264 cst['Linux'].colors.breakpoint_disabled = C.Red
271 265
272 266 cst['LightBG'].colors.breakpoint_enabled = C.LightRed
273 267 cst['LightBG'].colors.breakpoint_disabled = C.Red
274 268
275 269 self.set_colors(color_scheme)
276 270
277 271 # Add a python parser so we can syntax highlight source while
278 272 # debugging.
279 273 self.parser = PyColorize.Parser()
280 274
281 275 def set_colors(self, scheme):
282 276 """Shorthand access to the color table scheme selector method."""
283 277 self.color_scheme_table.set_active_scheme(scheme)
284 278
285 279 def interaction(self, frame, traceback):
286 280 __IPYTHON__.set_completer_frame(frame)
287 281 OldPdb.interaction(self, frame, traceback)
288 282
289 283 def new_do_up(self, arg):
290 284 OldPdb.do_up(self, arg)
291 285 __IPYTHON__.set_completer_frame(self.curframe)
292 286 do_u = do_up = decorate_fn_with_doc(new_do_up, OldPdb.do_up)
293 287
294 288 def new_do_down(self, arg):
295 289 OldPdb.do_down(self, arg)
296 290 __IPYTHON__.set_completer_frame(self.curframe)
297 291
298 292 do_d = do_down = decorate_fn_with_doc(new_do_down, OldPdb.do_down)
299 293
300 294 def new_do_frame(self, arg):
301 295 OldPdb.do_frame(self, arg)
302 296 __IPYTHON__.set_completer_frame(self.curframe)
303 297
304 298 def new_do_quit(self, arg):
305 299
306 300 if hasattr(self, 'old_all_completions'):
307 301 __IPYTHON__.Completer.all_completions=self.old_all_completions
308 302
309 303
310 304 return OldPdb.do_quit(self, arg)
311 305
312 306 do_q = do_quit = decorate_fn_with_doc(new_do_quit, OldPdb.do_quit)
313 307
314 308 def new_do_restart(self, arg):
315 309 """Restart command. In the context of ipython this is exactly the same
316 310 thing as 'quit'."""
317 311 self.msg("Restart doesn't make sense here. Using 'quit' instead.")
318 312 return self.do_quit(arg)
319 313
320 314 def postloop(self):
321 315 __IPYTHON__.set_completer_frame(None)
322 316
323 317 def print_stack_trace(self):
324 318 try:
325 319 for frame_lineno in self.stack:
326 320 self.print_stack_entry(frame_lineno, context = 5)
327 321 except KeyboardInterrupt:
328 322 pass
329 323
330 324 def print_stack_entry(self,frame_lineno,prompt_prefix='\n-> ',
331 325 context = 3):
332 326 #frame, lineno = frame_lineno
333 327 print >>Term.cout, self.format_stack_entry(frame_lineno, '', context)
334 328
335 329 # vds: >>
336 330 frame, lineno = frame_lineno
337 331 filename = frame.f_code.co_filename
338 332 __IPYTHON__.hooks.synchronize_with_editor(filename, lineno, 0)
339 333 # vds: <<
340 334
341 335 def format_stack_entry(self, frame_lineno, lprefix=': ', context = 3):
342 336 import linecache, repr
343 337
344 338 ret = []
345 339
346 340 Colors = self.color_scheme_table.active_colors
347 341 ColorsNormal = Colors.Normal
348 342 tpl_link = '%s%%s%s' % (Colors.filenameEm, ColorsNormal)
349 343 tpl_call = '%s%%s%s%%s%s' % (Colors.vName, Colors.valEm, ColorsNormal)
350 344 tpl_line = '%%s%s%%s %s%%s' % (Colors.lineno, ColorsNormal)
351 345 tpl_line_em = '%%s%s%%s %s%%s%s' % (Colors.linenoEm, Colors.line,
352 346 ColorsNormal)
353 347
354 348 frame, lineno = frame_lineno
355 349
356 350 return_value = ''
357 351 if '__return__' in frame.f_locals:
358 352 rv = frame.f_locals['__return__']
359 353 #return_value += '->'
360 354 return_value += repr.repr(rv) + '\n'
361 355 ret.append(return_value)
362 356
363 357 #s = filename + '(' + `lineno` + ')'
364 358 filename = self.canonic(frame.f_code.co_filename)
365 359 link = tpl_link % filename
366 360
367 361 if frame.f_code.co_name:
368 362 func = frame.f_code.co_name
369 363 else:
370 364 func = "<lambda>"
371 365
372 366 call = ''
373 367 if func != '?':
374 368 if '__args__' in frame.f_locals:
375 369 args = repr.repr(frame.f_locals['__args__'])
376 370 else:
377 371 args = '()'
378 372 call = tpl_call % (func, args)
379 373
380 374 # The level info should be generated in the same format pdb uses, to
381 375 # avoid breaking the pdbtrack functionality of python-mode in *emacs.
382 376 if frame is self.curframe:
383 377 ret.append('> ')
384 378 else:
385 379 ret.append(' ')
386 380 ret.append('%s(%s)%s\n' % (link,lineno,call))
387 381
388 382 start = lineno - 1 - context//2
389 383 lines = linecache.getlines(filename)
390 384 start = max(start, 0)
391 385 start = min(start, len(lines) - context)
392 386 lines = lines[start : start + context]
393 387
394 388 for i,line in enumerate(lines):
395 389 show_arrow = (start + 1 + i == lineno)
396 390 linetpl = (frame is self.curframe or show_arrow) \
397 391 and tpl_line_em \
398 392 or tpl_line
399 393 ret.append(self.__format_line(linetpl, filename,
400 394 start + 1 + i, line,
401 395 arrow = show_arrow) )
402 396
403 397 return ''.join(ret)
404 398
405 399 def __format_line(self, tpl_line, filename, lineno, line, arrow = False):
406 400 bp_mark = ""
407 401 bp_mark_color = ""
408 402
409 403 scheme = self.color_scheme_table.active_scheme_name
410 404 new_line, err = self.parser.format2(line, 'str', scheme)
411 405 if not err: line = new_line
412 406
413 407 bp = None
414 408 if lineno in self.get_file_breaks(filename):
415 409 bps = self.get_breaks(filename, lineno)
416 410 bp = bps[-1]
417 411
418 412 if bp:
419 413 Colors = self.color_scheme_table.active_colors
420 414 bp_mark = str(bp.number)
421 415 bp_mark_color = Colors.breakpoint_enabled
422 416 if not bp.enabled:
423 417 bp_mark_color = Colors.breakpoint_disabled
424 418
425 419 numbers_width = 7
426 420 if arrow:
427 421 # This is the line with the error
428 422 pad = numbers_width - len(str(lineno)) - len(bp_mark)
429 423 if pad >= 3:
430 424 marker = '-'*(pad-3) + '-> '
431 425 elif pad == 2:
432 426 marker = '> '
433 427 elif pad == 1:
434 428 marker = '>'
435 429 else:
436 430 marker = ''
437 431 num = '%s%s' % (marker, str(lineno))
438 432 line = tpl_line % (bp_mark_color + bp_mark, num, line)
439 433 else:
440 434 num = '%*s' % (numbers_width - len(bp_mark), str(lineno))
441 435 line = tpl_line % (bp_mark_color + bp_mark, num, line)
442 436
443 437 return line
444 438
445 439 def list_command_pydb(self, arg):
446 440 """List command to use if we have a newer pydb installed"""
447 441 filename, first, last = OldPdb.parse_list_cmd(self, arg)
448 442 if filename is not None:
449 443 self.print_list_lines(filename, first, last)
450 444
451 445 def print_list_lines(self, filename, first, last):
452 446 """The printing (as opposed to the parsing part of a 'list'
453 447 command."""
454 448 try:
455 449 Colors = self.color_scheme_table.active_colors
456 450 ColorsNormal = Colors.Normal
457 451 tpl_line = '%%s%s%%s %s%%s' % (Colors.lineno, ColorsNormal)
458 452 tpl_line_em = '%%s%s%%s %s%%s%s' % (Colors.linenoEm, Colors.line, ColorsNormal)
459 453 src = []
460 454 for lineno in range(first, last+1):
461 455 line = linecache.getline(filename, lineno)
462 456 if not line:
463 457 break
464 458
465 459 if lineno == self.curframe.f_lineno:
466 460 line = self.__format_line(tpl_line_em, filename, lineno, line, arrow = True)
467 461 else:
468 462 line = self.__format_line(tpl_line, filename, lineno, line, arrow = False)
469 463
470 464 src.append(line)
471 465 self.lineno = lineno
472 466
473 467 print >>Term.cout, ''.join(src)
474 468
475 469 except KeyboardInterrupt:
476 470 pass
477 471
478 472 def do_list(self, arg):
479 473 self.lastcmd = 'list'
480 474 last = None
481 475 if arg:
482 476 try:
483 477 x = eval(arg, {}, {})
484 478 if type(x) == type(()):
485 479 first, last = x
486 480 first = int(first)
487 481 last = int(last)
488 482 if last < first:
489 483 # Assume it's a count
490 484 last = first + last
491 485 else:
492 486 first = max(1, int(x) - 5)
493 487 except:
494 488 print '*** Error in argument:', `arg`
495 489 return
496 490 elif self.lineno is None:
497 491 first = max(1, self.curframe.f_lineno - 5)
498 492 else:
499 493 first = self.lineno + 1
500 494 if last is None:
501 495 last = first + 10
502 496 self.print_list_lines(self.curframe.f_code.co_filename, first, last)
503 497
504 498 # vds: >>
505 499 lineno = first
506 500 filename = self.curframe.f_code.co_filename
507 501 __IPYTHON__.hooks.synchronize_with_editor(filename, lineno, 0)
508 502 # vds: <<
509 503
510 504 do_l = do_list
511 505
512 506 def do_pdef(self, arg):
513 507 """The debugger interface to magic_pdef"""
514 508 namespaces = [('Locals', self.curframe.f_locals),
515 509 ('Globals', self.curframe.f_globals)]
516 510 __IPYTHON__.magic_pdef(arg, namespaces=namespaces)
517 511
518 512 def do_pdoc(self, arg):
519 513 """The debugger interface to magic_pdoc"""
520 514 namespaces = [('Locals', self.curframe.f_locals),
521 515 ('Globals', self.curframe.f_globals)]
522 516 __IPYTHON__.magic_pdoc(arg, namespaces=namespaces)
523 517
524 518 def do_pinfo(self, arg):
525 519 """The debugger equivalant of ?obj"""
526 520 namespaces = [('Locals', self.curframe.f_locals),
527 521 ('Globals', self.curframe.f_globals)]
528 522 __IPYTHON__.magic_pinfo("pinfo %s" % arg, namespaces=namespaces)
@@ -1,259 +1,253 b''
1 1 # -*- coding: utf-8 -*-
2 2 """Modified input prompt for executing files.
3 3
4 4 We define a special input line filter to allow typing lines which begin with
5 5 '~', '/' or '.'. If one of those strings is encountered, it is automatically
6 6 executed.
7
8 $Id: InterpreterExec.py 2724 2007-09-07 08:05:38Z fperez $"""
7 """
9 8
10 9 #*****************************************************************************
11 10 # Copyright (C) 2004 W.J. van der Laan <gnufnork@hetdigitalegat.nl>
12 11 # Copyright (C) 2004-2006 Fernando Perez <fperez@colorado.edu>
13 12 #
14 13 # Distributed under the terms of the BSD License. The full license is in
15 14 # the file COPYING, distributed as part of this software.
16 15 #*****************************************************************************
17 16
18 from IPython import Release
19 __author__ = 'W.J. van der Laan <gnufnork@hetdigitalegat.nl>, '\
20 '%s <%s>' % Release.authors['Fernando']
21 __license__ = Release.license
22
23 17 # TODO: deprecated
24 18 def prefilter_shell(self,line,continuation):
25 19 """Alternate prefilter, modified for shell-like functionality.
26 20
27 21 - Execute all lines beginning with '~', '/' or '.'
28 22 - $var=cmd <=> %sc var=cmd
29 23 - $$var=cmd <=> %sc -l var=cmd
30 24 """
31 25
32 26 if line:
33 27 l0 = line[0]
34 28 if l0 in '~/.':
35 29 return self._prefilter("!%s"%line,continuation)
36 30 elif l0=='$':
37 31 lrest = line[1:]
38 32 if lrest.startswith('$'):
39 33 # $$var=cmd <=> %sc -l var=cmd
40 34 return self._prefilter("%ssc -l %s" % (self.ESC_MAGIC,lrest[1:]),
41 35 continuation)
42 36 else:
43 37 # $var=cmd <=> %sc var=cmd
44 38 return self._prefilter("%ssc %s" % (self.ESC_MAGIC,lrest),
45 39 continuation)
46 40 else:
47 41 return self._prefilter(line,continuation)
48 42 else:
49 43 return self._prefilter(line,continuation)
50 44
51 45 # Rebind this to be the new IPython prefilter:
52 46 from IPython.iplib import InteractiveShell
53 47 InteractiveShell.prefilter = prefilter_shell
54 48 # Clean up the namespace.
55 49 del InteractiveShell,prefilter_shell
56 50
57 51 # Provide pysh and further shell-oriented services
58 52 import os,sys,shutil
59 53 from IPython.genutils import system,shell,getoutput,getoutputerror
60 54
61 55 # Short aliases for getting shell output as a string and a list
62 56 sout = getoutput
63 57 lout = lambda cmd: getoutput(cmd,split=1)
64 58
65 59 # Empty function, meant as a docstring holder so help(pysh) works.
66 60 def pysh():
67 61 """Pysh is a set of modules and extensions to IPython which make shell-like
68 62 usage with Python syntax more convenient. Keep in mind that pysh is NOT a
69 63 full-blown shell, so don't try to make it your /etc/passwd entry!
70 64
71 65 In particular, it has no job control, so if you type Ctrl-Z (under Unix),
72 66 you'll suspend pysh itself, not the process you just started.
73 67
74 68 Since pysh is really nothing but a customized IPython, you should
75 69 familiarize yourself with IPython's features. This brief help mainly
76 70 documents areas in which pysh differs from the normal IPython.
77 71
78 72 ALIASES
79 73 -------
80 74 All of your $PATH has been loaded as IPython aliases, so you should be
81 75 able to type any normal system command and have it executed. See %alias?
82 76 and %unalias? for details on the alias facilities.
83 77
84 78 SPECIAL SYNTAX
85 79 --------------
86 80 Any lines which begin with '~', '/' and '.' will be executed as shell
87 81 commands instead of as Python code. The special escapes below are also
88 82 recognized. !cmd is valid in single or multi-line input, all others are
89 83 only valid in single-line input:
90 84
91 85 !cmd - pass 'cmd' directly to the shell
92 86 !!cmd - execute 'cmd' and return output as a list (split on '\\n')
93 87 $var=cmd - capture output of cmd into var, as a string
94 88 $$var=cmd - capture output of cmd into var, as a list (split on '\\n')
95 89
96 90 The $/$$ syntaxes make Python variables from system output, which you can
97 91 later use for further scripting. The converse is also possible: when
98 92 executing an alias or calling to the system via !/!!, you can expand any
99 93 python variable or expression by prepending it with $. Full details of
100 94 the allowed syntax can be found in Python's PEP 215.
101 95
102 96 A few brief examples will illustrate these:
103 97
104 98 fperez[~/test]|3> !ls *s.py
105 99 scopes.py strings.py
106 100
107 101 ls is an internal alias, so there's no need to use !:
108 102 fperez[~/test]|4> ls *s.py
109 103 scopes.py* strings.py
110 104
111 105 !!ls will return the output into a Python variable:
112 106 fperez[~/test]|5> !!ls *s.py
113 107 <5> ['scopes.py', 'strings.py']
114 108 fperez[~/test]|6> print _5
115 109 ['scopes.py', 'strings.py']
116 110
117 111 $ and $$ allow direct capture to named variables:
118 112 fperez[~/test]|7> $astr = ls *s.py
119 113 fperez[~/test]|8> astr
120 114 <8> 'scopes.py\\nstrings.py'
121 115
122 116 fperez[~/test]|9> $$alist = ls *s.py
123 117 fperez[~/test]|10> alist
124 118 <10> ['scopes.py', 'strings.py']
125 119
126 120 alist is now a normal python list you can loop over. Using $ will expand
127 121 back the python values when alias calls are made:
128 122 fperez[~/test]|11> for f in alist:
129 123 |..> print 'file',f,
130 124 |..> wc -l $f
131 125 |..>
132 126 file scopes.py 13 scopes.py
133 127 file strings.py 4 strings.py
134 128
135 129 Note that you may need to protect your variables with braces if you want
136 130 to append strings to their names. To copy all files in alist to .bak
137 131 extensions, you must use:
138 132 fperez[~/test]|12> for f in alist:
139 133 |..> cp $f ${f}.bak
140 134
141 135 If you try using $f.bak, you'll get an AttributeError exception saying
142 136 that your string object doesn't have a .bak attribute. This is because
143 137 the $ expansion mechanism allows you to expand full Python expressions:
144 138 fperez[~/test]|13> echo "sys.platform is: $sys.platform"
145 139 sys.platform is: linux2
146 140
147 141 IPython's input history handling is still active, which allows you to
148 142 rerun a single block of multi-line input by simply using exec:
149 143 fperez[~/test]|14> $$alist = ls *.eps
150 144 fperez[~/test]|15> exec _i11
151 145 file image2.eps 921 image2.eps
152 146 file image.eps 921 image.eps
153 147
154 148 While these are new special-case syntaxes, they are designed to allow very
155 149 efficient use of the shell with minimal typing. At an interactive shell
156 150 prompt, conciseness of expression wins over readability.
157 151
158 152 USEFUL FUNCTIONS AND MODULES
159 153 ----------------------------
160 154 The os, sys and shutil modules from the Python standard library are
161 155 automatically loaded. Some additional functions, useful for shell usage,
162 156 are listed below. You can request more help about them with '?'.
163 157
164 158 shell - execute a command in the underlying system shell
165 159 system - like shell(), but return the exit status of the command
166 160 sout - capture the output of a command as a string
167 161 lout - capture the output of a command as a list (split on '\\n')
168 162 getoutputerror - capture (output,error) of a shell command
169 163
170 164 sout/lout are the functional equivalents of $/$$. They are provided to
171 165 allow you to capture system output in the middle of true python code,
172 166 function definitions, etc (where $ and $$ are invalid).
173 167
174 168 DIRECTORY MANAGEMENT
175 169 --------------------
176 170 Since each command passed by pysh to the underlying system is executed in
177 171 a subshell which exits immediately, you can NOT use !cd to navigate the
178 172 filesystem.
179 173
180 174 Pysh provides its own builtin '%cd' magic command to move in the
181 175 filesystem (the % is not required with automagic on). It also maintains a
182 176 list of visited directories (use %dhist to see it) and allows direct
183 177 switching to any of them. Type 'cd?' for more details.
184 178
185 179 %pushd, %popd and %dirs are provided for directory stack handling.
186 180
187 181 PROMPT CUSTOMIZATION
188 182 --------------------
189 183
190 184 The supplied ipythonrc-pysh profile comes with an example of a very
191 185 colored and detailed prompt, mainly to serve as an illustration. The
192 186 valid escape sequences, besides color names, are:
193 187
194 188 \\# - Prompt number.
195 189 \\D - Dots, as many as there are digits in \\# (so they align).
196 190 \\w - Current working directory (cwd).
197 191 \\W - Basename of current working directory.
198 192 \\XN - Where N=0..5. N terms of the cwd, with $HOME written as ~.
199 193 \\YN - Where N=0..5. Like XN, but if ~ is term N+1 it's also shown.
200 194 \\u - Username.
201 195 \\H - Full hostname.
202 196 \\h - Hostname up to first '.'
203 197 \\$ - Root symbol ($ or #).
204 198 \\t - Current time, in H:M:S format.
205 199 \\v - IPython release version.
206 200 \\n - Newline.
207 201 \\r - Carriage return.
208 202 \\\\ - An explicitly escaped '\\'.
209 203
210 204 You can configure your prompt colors using any ANSI color escape. Each
211 205 color escape sets the color for any subsequent text, until another escape
212 206 comes in and changes things. The valid color escapes are:
213 207
214 208 \\C_Black
215 209 \\C_Blue
216 210 \\C_Brown
217 211 \\C_Cyan
218 212 \\C_DarkGray
219 213 \\C_Green
220 214 \\C_LightBlue
221 215 \\C_LightCyan
222 216 \\C_LightGray
223 217 \\C_LightGreen
224 218 \\C_LightPurple
225 219 \\C_LightRed
226 220 \\C_Purple
227 221 \\C_Red
228 222 \\C_White
229 223 \\C_Yellow
230 224 \\C_Normal - Stop coloring, defaults to your terminal settings.
231 225 """
232 226 pass
233 227
234 228 # Configure a few things. Much of this is fairly hackish, since IPython
235 229 # doesn't really expose a clean API for it. Be careful if you start making
236 230 # many modifications here.
237 231
238 232
239 233 # Set the 'cd' command to quiet mode, a more shell-like behavior
240 234 __IPYTHON__.default_option('cd','-q')
241 235
242 236 # This is redundant, ipy_user_conf.py will determine this
243 237 # Load all of $PATH as aliases
244 238 __IPYTHON__.magic_rehashx()
245 239
246 240 # Remove %sc,%sx if present as aliases
247 241 __IPYTHON__.magic_unalias('sc')
248 242 __IPYTHON__.magic_unalias('sx')
249 243
250 244 # We need different criteria for line-splitting, so that aliases such as
251 245 # 'gnome-terminal' are interpreted as a single alias instead of variable
252 246 # 'gnome' minus variable 'terminal'.
253 247 import re
254 248 __IPYTHON__.line_split = re.compile(r'^([\s*,;/])'
255 249 r'([\?\w\.\-\+]+\w*\s*)'
256 250 r'(\(?.*$)')
257 251
258 252 # Namespace cleanup
259 253 del re
@@ -1,66 +1,63 b''
1 1 # -*- coding: utf-8 -*-
2 2 """ IPython extension: new prefilters for output grabbing
3 3
4 4 Provides
5 5
6 6 var = %magic blah blah
7 7
8 8 var = !ls
9
10 $Id: genutils.py 1077 2006-01-24 18:15:27Z vivainio $
11
12 9 """
13 10
14 11 import IPython.ipapi
15 12 from IPython.genutils import *
16 13
17 14 ip = IPython.ipapi.get()
18 15
19 16 import re
20 17
21 18 def hnd_magic(line,mo):
22 19 """ Handle a = %mymagic blah blah """
23 20 #cmd = genutils.make_quoted_expr(mo.group('syscmd'))
24 21 #mag = 'ipmagic
25 22 #return "%s = %s"
26 23 var = mo.group('varname')
27 24 cmd = mo.group('cmd')
28 25 expr = make_quoted_expr(cmd)
29 26 return itpl('$var = _ip.magic($expr)')
30 27
31 28 def hnd_syscmd(line,mo):
32 29 """ Handle a = !ls """
33 30 #cmd = genutils.make_quoted_expr(mo.group('syscmd'))
34 31 #mag = 'ipmagic
35 32 #return "%s = %s"
36 33 var = mo.group('varname')
37 34 cmd = mo.group('cmd')
38 35 expr = make_quoted_expr(itpl("sc -l =$cmd"))
39 36 return itpl('$var = _ip.magic($expr)')
40 37
41 38 def install_re_handler(pat, hnd):
42 39 ip.meta.re_prefilters.append((re.compile(pat), hnd))
43 40
44 41 def init_handlers():
45 42
46 43 ip.meta.re_prefilters = []
47 44
48 45 install_re_handler('(?P<varname>[\w\.]+)\s*=\s*%(?P<cmd>.*)',
49 46 hnd_magic
50 47 )
51 48
52 49 install_re_handler('(?P<varname>[\w\.]+)\s*=\s*!(?P<cmd>.*)',
53 50 hnd_syscmd
54 51 )
55 52
56 53 init_handlers()
57 54
58 55 def regex_prefilter_f(self,line):
59 56 for pat, handler in ip.meta.re_prefilters:
60 57 mo = pat.match(line)
61 58 if mo:
62 59 return handler(line,mo)
63 60
64 61 raise IPython.ipapi.TryNext
65 62
66 63 ip.set_hook('input_prefilter', regex_prefilter_f)
@@ -1,184 +1,182 b''
1 1 # -*- coding: utf-8 -*-
2 2 """
3 3 %store magic for lightweight persistence.
4 4
5 5 Stores variables, aliases etc. in PickleShare database.
6
7 $Id: iplib.py 1107 2006-01-30 19:02:20Z vivainio $
8 6 """
9 7
10 8 import IPython.ipapi
11 9 from IPython.ipapi import UsageError
12 10 ip = IPython.ipapi.get()
13 11
14 12 import pickleshare
15 13
16 14 import inspect,pickle,os,sys,textwrap
17 15 from IPython.FakeModule import FakeModule
18 16
19 17 def restore_aliases(self):
20 18 ip = self.getapi()
21 19 staliases = ip.db.get('stored_aliases', {})
22 20 for k,v in staliases.items():
23 21 #print "restore alias",k,v # dbg
24 22 #self.alias_table[k] = v
25 23 ip.defalias(k,v)
26 24
27 25
28 26 def refresh_variables(ip):
29 27 db = ip.db
30 28 for key in db.keys('autorestore/*'):
31 29 # strip autorestore
32 30 justkey = os.path.basename(key)
33 31 try:
34 32 obj = db[key]
35 33 except KeyError:
36 34 print "Unable to restore variable '%s', ignoring (use %%store -d to forget!)" % justkey
37 35 print "The error was:",sys.exc_info()[0]
38 36 else:
39 37 #print "restored",justkey,"=",obj #dbg
40 38 ip.user_ns[justkey] = obj
41 39
42 40
43 41 def restore_dhist(ip):
44 42 db = ip.db
45 43 ip.user_ns['_dh'] = db.get('dhist',[])
46 44
47 45 def restore_data(self):
48 46 ip = self.getapi()
49 47 refresh_variables(ip)
50 48 restore_aliases(self)
51 49 restore_dhist(self)
52 50 raise IPython.ipapi.TryNext
53 51
54 52 ip.set_hook('late_startup_hook', restore_data)
55 53
56 54 def magic_store(self, parameter_s=''):
57 55 """Lightweight persistence for python variables.
58 56
59 57 Example:
60 58
61 59 ville@badger[~]|1> A = ['hello',10,'world']\\
62 60 ville@badger[~]|2> %store A\\
63 61 ville@badger[~]|3> Exit
64 62
65 63 (IPython session is closed and started again...)
66 64
67 65 ville@badger:~$ ipython -p pysh\\
68 66 ville@badger[~]|1> print A
69 67
70 68 ['hello', 10, 'world']
71 69
72 70 Usage:
73 71
74 72 %store - Show list of all variables and their current values\\
75 73 %store <var> - Store the *current* value of the variable to disk\\
76 74 %store -d <var> - Remove the variable and its value from storage\\
77 75 %store -z - Remove all variables from storage\\
78 76 %store -r - Refresh all variables from store (delete current vals)\\
79 77 %store foo >a.txt - Store value of foo to new file a.txt\\
80 78 %store foo >>a.txt - Append value of foo to file a.txt\\
81 79
82 80 It should be noted that if you change the value of a variable, you
83 81 need to %store it again if you want to persist the new value.
84 82
85 83 Note also that the variables will need to be pickleable; most basic
86 84 python types can be safely %stored.
87 85
88 86 Also aliases can be %store'd across sessions.
89 87 """
90 88
91 89 opts,argsl = self.parse_options(parameter_s,'drz',mode='string')
92 90 args = argsl.split(None,1)
93 91 ip = self.getapi()
94 92 db = ip.db
95 93 # delete
96 94 if opts.has_key('d'):
97 95 try:
98 96 todel = args[0]
99 97 except IndexError:
100 98 raise UsageError('You must provide the variable to forget')
101 99 else:
102 100 try:
103 101 del db['autorestore/' + todel]
104 102 except:
105 103 raise UsageError("Can't delete variable '%s'" % todel)
106 104 # reset
107 105 elif opts.has_key('z'):
108 106 for k in db.keys('autorestore/*'):
109 107 del db[k]
110 108
111 109 elif opts.has_key('r'):
112 110 refresh_variables(ip)
113 111
114 112
115 113 # run without arguments -> list variables & values
116 114 elif not args:
117 115 vars = self.db.keys('autorestore/*')
118 116 vars.sort()
119 117 if vars:
120 118 size = max(map(len,vars))
121 119 else:
122 120 size = 0
123 121
124 122 print 'Stored variables and their in-db values:'
125 123 fmt = '%-'+str(size)+'s -> %s'
126 124 get = db.get
127 125 for var in vars:
128 126 justkey = os.path.basename(var)
129 127 # print 30 first characters from every var
130 128 print fmt % (justkey,repr(get(var,'<unavailable>'))[:50])
131 129
132 130 # default action - store the variable
133 131 else:
134 132 # %store foo >file.txt or >>file.txt
135 133 if len(args) > 1 and args[1].startswith('>'):
136 134 fnam = os.path.expanduser(args[1].lstrip('>').lstrip())
137 135 if args[1].startswith('>>'):
138 136 fil = open(fnam,'a')
139 137 else:
140 138 fil = open(fnam,'w')
141 139 obj = ip.ev(args[0])
142 140 print "Writing '%s' (%s) to file '%s'." % (args[0],
143 141 obj.__class__.__name__, fnam)
144 142
145 143
146 144 if not isinstance (obj,basestring):
147 145 from pprint import pprint
148 146 pprint(obj,fil)
149 147 else:
150 148 fil.write(obj)
151 149 if not obj.endswith('\n'):
152 150 fil.write('\n')
153 151
154 152 fil.close()
155 153 return
156 154
157 155 # %store foo
158 156 try:
159 157 obj = ip.user_ns[args[0]]
160 158 except KeyError:
161 159 # it might be an alias
162 160 if args[0] in self.alias_table:
163 161 staliases = db.get('stored_aliases',{})
164 162 staliases[ args[0] ] = self.alias_table[ args[0] ]
165 163 db['stored_aliases'] = staliases
166 164 print "Alias stored:", args[0], self.alias_table[ args[0] ]
167 165 return
168 166 else:
169 167 raise UsageError("Unknown variable '%s'" % args[0])
170 168
171 169 else:
172 170 if isinstance(inspect.getmodule(obj), FakeModule):
173 171 print textwrap.dedent("""\
174 172 Warning:%s is %s
175 173 Proper storage of interactively declared classes (or instances
176 174 of those classes) is not possible! Only instances
177 175 of classes in real modules on file system can be %%store'd.
178 176 """ % (args[0], obj) )
179 177 return
180 178 #pickled = pickle.dumps(obj)
181 179 self.db[ 'autorestore/' + args[0] ] = obj
182 180 print "Stored '%s' (%s)" % (args[0], obj.__class__.__name__)
183 181
184 182 ip.expose_magic('store',magic_store)
@@ -1,43 +1,42 b''
1 1 # -*- coding: utf-8 -*-
2 2 """
3 3 Class which mimics a module.
4 4
5 5 Needed to allow pickle to correctly resolve namespaces during IPython
6 6 sessions.
7
8 $Id: FakeModule.py 2754 2007-09-09 10:16:59Z fperez $"""
7 """
9 8
10 9 #*****************************************************************************
11 10 # Copyright (C) 2002-2004 Fernando Perez. <fperez@colorado.edu>
12 11 #
13 12 # Distributed under the terms of the BSD License. The full license is in
14 13 # the file COPYING, distributed as part of this software.
15 14 #*****************************************************************************
16 15
17 16 import types
18 17
19 18 class FakeModule(types.ModuleType):
20 19 """Simple class with attribute access to fake a module.
21 20
22 21 This is not meant to replace a module, but to allow inserting a fake
23 22 module in sys.modules so that systems which rely on run-time module
24 23 importing (like shelve and pickle) work correctly in interactive IPython
25 24 sessions.
26 25
27 26 Do NOT use this code for anything other than this IPython private hack."""
28 27
29 28 def __init__(self,adict=None):
30 29
31 30 # tmp to force __dict__ instance creation, else self.__dict__ fails
32 31 self.__iptmp = None
33 32
34 33 # It seems pydoc (and perhaps others) needs any module instance to
35 34 # implement a __nonzero__ method, so we add it if missing:
36 35 self.__dict__.setdefault('__nonzero__',lambda : True)
37 36 self.__dict__.setdefault('__file__',__file__)
38 37
39 38 # cleanup our temp trick
40 39 del self.__iptmp
41 40
42 41 if adict is not None:
43 42 self.__dict__.update(adict)
@@ -1,666 +1,665 b''
1 1 # -*- coding: utf-8 -*-
2 2 """Improved replacement for the Gnuplot.Gnuplot class.
3 3
4 4 This module imports Gnuplot and replaces some of its functionality with
5 5 improved versions. They add better handling of arrays for plotting and more
6 6 convenient PostScript generation, plus some fixes for hardcopy().
7 7
8 8 It also adds a convenient plot2 method for plotting dictionaries and
9 9 lists/tuples of arrays.
10 10
11 11 This module is meant to be used as a drop-in replacement to the original
12 12 Gnuplot, so it should be safe to do:
13 13
14 14 import IPython.Gnuplot2 as Gnuplot
15
16 $Id: Gnuplot2.py 1210 2006-03-13 01:19:31Z fperez $"""
15 """
17 16
18 17 import cStringIO
19 18 import os
20 19 import string
21 20 import sys
22 21 import tempfile
23 22 import time
24 23 import types
25 24
26 25 import Gnuplot as Gnuplot_ori
27 26 import Numeric
28 27
29 28 from IPython.genutils import popkey,xsys
30 29
31 30 # needed by hardcopy():
32 31 gp = Gnuplot_ori.gp
33 32
34 33 # Patch for Gnuplot.py 1.6 compatibility.
35 34 # Thanks to Hayden Callow <h.callow@elec.canterbury.ac.nz>
36 35 try:
37 36 OptionException = Gnuplot_ori.PlotItems.OptionException
38 37 except AttributeError:
39 38 OptionException = Gnuplot_ori.Errors.OptionError
40 39
41 40 # exhibit a similar interface to Gnuplot so it can be somewhat drop-in
42 41 Data = Gnuplot_ori.Data
43 42 Func = Gnuplot_ori.Func
44 43 GridData = Gnuplot_ori.GridData
45 44 PlotItem = Gnuplot_ori.PlotItem
46 45 PlotItems = Gnuplot_ori.PlotItems
47 46
48 47 # Modify some of Gnuplot's functions with improved versions (or bugfixed, in
49 48 # hardcopy's case). In order to preserve the docstrings at runtime, I've
50 49 # copied them from the original code.
51 50
52 51 # After some significant changes in v 1.7 of Gnuplot.py, we need to do a bit
53 52 # of version checking.
54 53
55 54 if Gnuplot_ori.__version__ <= '1.6':
56 55 _BaseFileItem = PlotItems.File
57 56 _BaseTempFileItem = PlotItems.TempFile
58 57
59 58 # Fix the File class to add the 'index' option for Gnuplot versions < 1.7
60 59 class File(_BaseFileItem):
61 60
62 61 _option_list = _BaseFileItem._option_list.copy()
63 62 _option_list.update({
64 63 'index' : lambda self, index: self.set_option_index(index),
65 64 })
66 65
67 66 # A new initializer is needed b/c we want to add a modified
68 67 # _option_sequence list which includes 'index' in the right place.
69 68 def __init__(self,*args,**kw):
70 69 self._option_sequence = ['binary', 'index', 'using', 'smooth', 'axes',
71 70 'title', 'with']
72 71
73 72 _BaseFileItem.__init__(self,*args,**kw)
74 73
75 74 # Let's fix the constructor docstring
76 75 __newdoc = \
77 76 """Additional Keyword arguments added by IPython:
78 77
79 78 'index=<int>' -- similar to the `index` keyword in Gnuplot.
80 79 This allows only some of the datasets in a file to be
81 80 plotted. Datasets within a file are assumed to be separated
82 81 by _pairs_ of blank lines, and the first one is numbered as
83 82 0 (similar to C/Python usage)."""
84 83 __init__.__doc__ = PlotItems.File.__init__.__doc__ + __newdoc
85 84
86 85 def set_option_index(self, index):
87 86 if index is None:
88 87 self.clear_option('index')
89 88 elif type(index) in [type(''), type(1)]:
90 89 self._options['index'] = (index, 'index %s' % index)
91 90 elif type(index) is type(()):
92 91 self._options['index'] = (index,'index %s' %
93 92 string.join(map(repr, index), ':'))
94 93 else:
95 94 raise OptionException('index=%s' % (index,))
96 95
97 96 # We need a FileClass with a different name from 'File', which is a
98 97 # factory function in 1.7, so that our String class can subclass FileClass
99 98 # in any version.
100 99 _FileClass = File
101 100
102 101 elif Gnuplot_ori.__version__ =='1.7':
103 102 _FileClass = _BaseFileItem = PlotItems._FileItem
104 103 _BaseTempFileItem = PlotItems._TempFileItem
105 104 File = PlotItems.File
106 105
107 106 else: # changes in the newer version (svn as of March'06)
108 107 _FileClass = _BaseFileItem = PlotItems._FileItem
109 108 _BaseTempFileItem = PlotItems._NewFileItem
110 109 File = PlotItems.File
111 110
112 111
113 112 # Now, we can add our generic code which is version independent
114 113
115 114 # First some useful utilities
116 115 def eps_fix_bbox(fname):
117 116 """Fix the bounding box of an eps file by running ps2eps on it.
118 117
119 118 If its name ends in .eps, the original file is removed.
120 119
121 120 This is particularly useful for plots made by Gnuplot with square aspect
122 121 ratio: there is a bug in Gnuplot which makes it generate a bounding box
123 122 which is far wider than the actual plot.
124 123
125 124 This function assumes that ps2eps is installed in your system."""
126 125
127 126 # note: ps2ps and eps2eps do NOT work, ONLY ps2eps works correctly. The
128 127 # others make output with bitmapped fonts, which looks horrible.
129 128 print 'Fixing eps file: <%s>' % fname
130 129 xsys('ps2eps -f -q -l %s' % fname)
131 130 if fname.endswith('.eps'):
132 131 os.rename(fname+'.eps',fname)
133 132
134 133 def is_list1d(x,containers = [types.ListType,types.TupleType]):
135 134 """Returns true if x appears to be a 1d list/tuple/array.
136 135
137 136 The heuristics are: identify Numeric arrays, or lists/tuples whose first
138 137 element is not itself a list/tuple. This way zipped lists should work like
139 138 the original Gnuplot. There's no inexpensive way to know if a list doesn't
140 139 have a composite object after its first element, so that kind of input
141 140 will produce an error. But it should work well in most cases.
142 141 """
143 142 x_type = type(x)
144 143
145 144 return x_type == Numeric.ArrayType and len(x.shape)==1 or \
146 145 (x_type in containers and
147 146 type(x[0]) not in containers + [Numeric.ArrayType])
148 147
149 148 def zip_items(items,titles=None):
150 149 """zip together neighboring 1-d arrays, and zip standalone ones
151 150 with their index. Leave other plot items alone."""
152 151
153 152 class StandaloneItem(Exception): pass
154 153
155 154 def get_titles(titles):
156 155 """Return the next title and the input titles array.
157 156
158 157 The input array may be changed to None when no titles are left to
159 158 prevent extra unnecessary calls to this function."""
160 159
161 160 try:
162 161 title = titles[tit_ct[0]] # tit_ct[0] is in zip_items'scope
163 162 except IndexError:
164 163 titles = None # so we don't enter again
165 164 title = None
166 165 else:
167 166 tit_ct[0] += 1
168 167 return title,titles
169 168
170 169 new_items = []
171 170
172 171 if titles:
173 172 # Initialize counter. It was put in a list as a hack to allow the
174 173 # nested get_titles to modify it without raising a NameError.
175 174 tit_ct = [0]
176 175
177 176 n = 0 # this loop needs to be done by hand
178 177 while n < len(items):
179 178 item = items[n]
180 179 try:
181 180 if is_list1d(item):
182 181 if n==len(items)-1: # last in list
183 182 raise StandaloneItem
184 183 else: # check the next item and zip together if needed
185 184 next_item = items[n+1]
186 185 if next_item is None:
187 186 n += 1
188 187 raise StandaloneItem
189 188 elif is_list1d(next_item):
190 189 # this would be best done with an iterator
191 190 if titles:
192 191 title,titles = get_titles(titles)
193 192 else:
194 193 title = None
195 194 new_items.append(Data(zip(item,next_item),
196 195 title=title))
197 196 n += 1 # avoid double-inclusion of next item
198 197 else: # can't zip with next, zip with own index list
199 198 raise StandaloneItem
200 199 else: # not 1-d array
201 200 new_items.append(item)
202 201 except StandaloneItem:
203 202 if titles:
204 203 title,titles = get_titles(titles)
205 204 else:
206 205 title = None
207 206 new_items.append(Data(zip(range(len(item)),item),title=title))
208 207 except AttributeError:
209 208 new_items.append(item)
210 209 n+=1
211 210
212 211 return new_items
213 212
214 213 # And some classes with enhanced functionality.
215 214 class String(_FileClass):
216 215 """Make a PlotItem from data in a string with the same format as a File.
217 216
218 217 This allows writing data directly inside python scripts using the exact
219 218 same format and manipulation options which would be used for external
220 219 files."""
221 220
222 221 def __init__(self, data_str, **keyw):
223 222 """Construct a String object.
224 223
225 224 <data_str> is a string formatted exactly like a valid Gnuplot data
226 225 file would be. All options from the File constructor are valid here.
227 226
228 227 Warning: when used for interactive plotting in scripts which exit
229 228 immediately, you may get an error because the temporary file used to
230 229 hold the string data was deleted before Gnuplot had a chance to see
231 230 it. You can work around this problem by putting a raw_input() call at
232 231 the end of the script.
233 232
234 233 This problem does not appear when generating PostScript output, only
235 234 with Gnuplot windows."""
236 235
237 236 self.tmpfile = _BaseTempFileItem()
238 237 tmpfile = file(self.tmpfile.filename,'w')
239 238 tmpfile.write(data_str)
240 239 _BaseFileItem.__init__(self,self.tmpfile,**keyw)
241 240
242 241
243 242 class Gnuplot(Gnuplot_ori.Gnuplot):
244 243 """Improved Gnuplot class.
245 244
246 245 Enhancements: better plot,replot and hardcopy methods. New methods for
247 246 quick range setting.
248 247 """
249 248
250 249 def xrange(self,min='*',max='*'):
251 250 """Set xrange. If min/max is omitted, it is set to '*' (auto).
252 251
253 252 Note that this is different from the regular Gnuplot behavior, where
254 253 an unspecified limit means no change. Here any unspecified limit is
255 254 set to autoscaling, allowing these functions to be used for full
256 255 autoscaling when called with no arguments.
257 256
258 257 To preserve one limit's current value while changing the other, an
259 258 explicit '' argument must be given as the limit to be kept.
260 259
261 260 Similar functions exist for [y{2}z{2}rtuv]range."""
262 261
263 262 self('set xrange [%s:%s]' % (min,max))
264 263
265 264 def yrange(self,min='*',max='*'):
266 265 self('set yrange [%s:%s]' % (min,max))
267 266
268 267 def zrange(self,min='*',max='*'):
269 268 self('set zrange [%s:%s]' % (min,max))
270 269
271 270 def x2range(self,min='*',max='*'):
272 271 self('set xrange [%s:%s]' % (min,max))
273 272
274 273 def y2range(self,min='*',max='*'):
275 274 self('set yrange [%s:%s]' % (min,max))
276 275
277 276 def z2range(self,min='*',max='*'):
278 277 self('set zrange [%s:%s]' % (min,max))
279 278
280 279 def rrange(self,min='*',max='*'):
281 280 self('set rrange [%s:%s]' % (min,max))
282 281
283 282 def trange(self,min='*',max='*'):
284 283 self('set trange [%s:%s]' % (min,max))
285 284
286 285 def urange(self,min='*',max='*'):
287 286 self('set urange [%s:%s]' % (min,max))
288 287
289 288 def vrange(self,min='*',max='*'):
290 289 self('set vrange [%s:%s]' % (min,max))
291 290
292 291 def set_ps(self,option):
293 292 """Set an option for the PostScript terminal and reset default term."""
294 293
295 294 self('set terminal postscript %s ' % option)
296 295 self('set terminal %s' % gp.GnuplotOpts.default_term)
297 296
298 297 def __plot_ps(self, plot_method,*items, **keyw):
299 298 """Wrapper for plot/splot/replot, with processing of hardcopy options.
300 299
301 300 For internal use only."""
302 301
303 302 # Filter out PostScript options which will crash the normal plot/replot
304 303 psargs = {'filename':None,
305 304 'mode':None,
306 305 'eps':None,
307 306 'enhanced':None,
308 307 'color':None,
309 308 'solid':None,
310 309 'duplexing':None,
311 310 'fontname':None,
312 311 'fontsize':None,
313 312 'debug':0 }
314 313
315 314 for k in psargs.keys():
316 315 if keyw.has_key(k):
317 316 psargs[k] = keyw[k]
318 317 del keyw[k]
319 318
320 319 # Filter out other options the original plot doesn't know
321 320 hardcopy = popkey(keyw,'hardcopy',psargs['filename'] is not None)
322 321 titles = popkey(keyw,'titles',0)
323 322
324 323 # the filename keyword should control hardcopy generation, this is an
325 324 # override switch only which needs to be explicitly set to zero
326 325 if hardcopy:
327 326 if psargs['filename'] is None:
328 327 raise ValueError, \
329 328 'If you request hardcopy, you must give a filename.'
330 329
331 330 # set null output so nothing goes to screen. hardcopy() restores output
332 331 self('set term dumb')
333 332 # I don't know how to prevent screen output in Windows
334 333 if os.name == 'posix':
335 334 self('set output "/dev/null"')
336 335
337 336 new_items = zip_items(items,titles)
338 337 # plot_method is either plot or replot from the original Gnuplot class:
339 338 plot_method(self,*new_items,**keyw)
340 339
341 340 # Do hardcopy if requested
342 341 if hardcopy:
343 342 if psargs['filename'].endswith('.eps'):
344 343 psargs['eps'] = 1
345 344 self.hardcopy(**psargs)
346 345
347 346 def plot(self, *items, **keyw):
348 347 """Draw a new plot.
349 348
350 349 Clear the current plot and create a new 2-d plot containing
351 350 the specified items. Each arguments should be of the
352 351 following types:
353 352
354 353 'PlotItem' (e.g., 'Data', 'File', 'Func') -- This is the most
355 354 flexible way to call plot because the PlotItems can
356 355 contain suboptions. Moreover, PlotItems can be saved to
357 356 variables so that their lifetime is longer than one plot
358 357 command; thus they can be replotted with minimal overhead.
359 358
360 359 'string' (e.g., 'sin(x)') -- The string is interpreted as
361 360 'Func(string)' (a function that is computed by gnuplot).
362 361
363 362 Anything else -- The object, which should be convertible to an
364 363 array, is passed to the 'Data' constructor, and thus
365 364 plotted as data. If the conversion fails, an exception is
366 365 raised.
367 366
368 367
369 368 This is a modified version of plot(). Compared to the original in
370 369 Gnuplot.py, this version has several enhancements, listed below.
371 370
372 371
373 372 Modifications to the input arguments
374 373 ------------------------------------
375 374
376 375 (1-d array means Numeric array, list or tuple):
377 376
378 377 (i) Any 1-d array which is NOT followed by another 1-d array, is
379 378 automatically zipped with range(len(array_1d)). Typing g.plot(y) will
380 379 plot y against its indices.
381 380
382 381 (ii) If two 1-d arrays are contiguous in the argument list, they are
383 382 automatically zipped together. So g.plot(x,y) plots y vs. x, and
384 383 g.plot(x1,y1,x2,y2) plots y1 vs. x1 and y2 vs. x2.
385 384
386 385 (iii) Any 1-d array which is followed by None is automatically zipped
387 386 with range(len(array_1d)). In this form, typing g.plot(y1,None,y2)
388 387 will plot both y1 and y2 against their respective indices (and NOT
389 388 versus one another). The None prevents zipping y1 and y2 together, and
390 389 since y2 is unpaired it is automatically zipped to its indices by (i)
391 390
392 391 (iv) Any other arguments which don't match these cases are left alone and
393 392 passed to the code below.
394 393
395 394 For lists or tuples, the heuristics used to determine whether they are
396 395 in fact 1-d is fairly simplistic: their first element is checked, and
397 396 if it is not a list or tuple itself, it is assumed that the whole
398 397 object is one-dimensional.
399 398
400 399 An additional optional keyword 'titles' has been added: it must be a
401 400 list of strings to be used as labels for the individual plots which
402 401 are NOT PlotItem objects (since those objects carry their own labels
403 402 within).
404 403
405 404
406 405 PostScript generation
407 406 ---------------------
408 407
409 408 This version of plot() also handles automatically the production of
410 409 PostScript output. The main options are (given as keyword arguments):
411 410
412 411 - filename: a string, typically ending in .eps. If given, the plot is
413 412 sent to this file in PostScript format.
414 413
415 414 - hardcopy: this can be set to 0 to override 'filename'. It does not
416 415 need to be given to produce PostScript, its purpose is to allow
417 416 switching PostScript output off globally in scripts without having to
418 417 manually change 'filename' values in multiple calls.
419 418
420 419 All other keywords accepted by Gnuplot.hardcopy() are transparently
421 420 passed, and safely ignored if output is sent to the screen instead of
422 421 PostScript.
423 422
424 423 For example:
425 424
426 425 In [1]: x=frange(0,2*pi,npts=100)
427 426
428 427 Generate a plot in file 'sin.eps':
429 428
430 429 In [2]: plot(x,sin(x),filename = 'sin.eps')
431 430
432 431 Plot to screen instead, without having to change the filename:
433 432
434 433 In [3]: plot(x,sin(x),filename = 'sin.eps',hardcopy=0)
435 434
436 435 Pass the 'color=0' option to hardcopy for monochrome output:
437 436
438 437 In [4]: plot(x,sin(x),filename = 'sin.eps',color=0)
439 438
440 439 PostScript generation through plot() is useful mainly for scripting
441 440 uses where you are not interested in interactive plotting. For
442 441 interactive use, the hardcopy() function is typically more convenient:
443 442
444 443 In [5]: plot(x,sin(x))
445 444
446 445 In [6]: hardcopy('sin.eps') """
447 446
448 447 self.__plot_ps(Gnuplot_ori.Gnuplot.plot,*items,**keyw)
449 448
450 449 def plot2(self,arg,**kw):
451 450 """Plot the entries of a dictionary or a list/tuple of arrays.
452 451
453 452 This simple utility calls plot() with a list of Gnuplot.Data objects
454 453 constructed either from the values of the input dictionary, or the entries
455 454 in it if it is a tuple or list. Each item gets labeled with the key/index
456 455 in the Gnuplot legend.
457 456
458 457 Each item is plotted by zipping it with a list of its indices.
459 458
460 459 Any keywords are passed directly to plot()."""
461 460
462 461 if hasattr(arg,'keys'):
463 462 keys = arg.keys()
464 463 keys.sort()
465 464 else:
466 465 keys = range(len(arg))
467 466
468 467 pitems = [Data(zip(range(len(arg[k])),arg[k]),title=`k`) for k in keys]
469 468 self.plot(*pitems,**kw)
470 469
471 470 def splot(self, *items, **keyw):
472 471 """Draw a new three-dimensional plot.
473 472
474 473 Clear the current plot and create a new 3-d plot containing
475 474 the specified items. Arguments can be of the following types:
476 475
477 476 'PlotItem' (e.g., 'Data', 'File', 'Func', 'GridData' ) -- This
478 477 is the most flexible way to call plot because the
479 478 PlotItems can contain suboptions. Moreover, PlotItems can
480 479 be saved to variables so that their lifetime is longer
481 480 than one plot command--thus they can be replotted with
482 481 minimal overhead.
483 482
484 483 'string' (e.g., 'sin(x*y)') -- The string is interpreted as a
485 484 'Func()' (a function that is computed by gnuplot).
486 485
487 486 Anything else -- The object is converted to a Data() item, and
488 487 thus plotted as data. Note that each data point should
489 488 normally have at least three values associated with it
490 489 (i.e., x, y, and z). If the conversion fails, an
491 490 exception is raised.
492 491
493 492 This is a modified version of splot(). Compared to the original in
494 493 Gnuplot.py, this version has several enhancements, listed in the
495 494 plot() documentation.
496 495 """
497 496
498 497 self.__plot_ps(Gnuplot_ori.Gnuplot.splot,*items,**keyw)
499 498
500 499 def replot(self, *items, **keyw):
501 500 """Replot the data, possibly adding new 'PlotItem's.
502 501
503 502 Replot the existing graph, using the items in the current
504 503 itemlist. If arguments are specified, they are interpreted as
505 504 additional items to be plotted alongside the existing items on
506 505 the same graph. See 'plot' for details.
507 506
508 507 If you want to replot to a postscript file, you MUST give the
509 508 'filename' keyword argument in each call to replot. The Gnuplot python
510 509 interface has no way of knowing that your previous call to
511 510 Gnuplot.plot() was meant for PostScript output."""
512 511
513 512 self.__plot_ps(Gnuplot_ori.Gnuplot.replot,*items,**keyw)
514 513
515 514 # The original hardcopy has a bug. See fix at the end. The rest of the code
516 515 # was lifted verbatim from the original, so that people using IPython get the
517 516 # benefits without having to manually patch Gnuplot.py
518 517 def hardcopy(self, filename=None,
519 518 mode=None,
520 519 eps=None,
521 520 enhanced=None,
522 521 color=None,
523 522 solid=None,
524 523 duplexing=None,
525 524 fontname=None,
526 525 fontsize=None,
527 526 debug = 0,
528 527 ):
529 528 """Create a hardcopy of the current plot.
530 529
531 530 Create a postscript hardcopy of the current plot to the
532 531 default printer (if configured) or to the specified filename.
533 532
534 533 Note that gnuplot remembers the postscript suboptions across
535 534 terminal changes. Therefore if you set, for example, color=1
536 535 for one hardcopy then the next hardcopy will also be color
537 536 unless you explicitly choose color=0. Alternately you can
538 537 force all of the options to their defaults by setting
539 538 mode='default'. I consider this to be a bug in gnuplot.
540 539
541 540 Keyword arguments:
542 541
543 542 'filename=<string>' -- if a filename is specified, save the
544 543 output in that file; otherwise print it immediately
545 544 using the 'default_lpr' configuration option. If the
546 545 filename ends in '.eps', EPS mode is automatically
547 546 selected (like manually specifying eps=1 or mode='eps').
548 547
549 548 'mode=<string>' -- set the postscript submode ('landscape',
550 549 'portrait', 'eps', or 'default'). The default is
551 550 to leave this option unspecified.
552 551
553 552 'eps=<bool>' -- shorthand for 'mode="eps"'; asks gnuplot to
554 553 generate encapsulated postscript.
555 554
556 555 'enhanced=<bool>' -- if set (the default), then generate
557 556 enhanced postscript, which allows extra features like
558 557 font-switching, superscripts, and subscripts in axis
559 558 labels. (Some old gnuplot versions do not support
560 559 enhanced postscript; if this is the case set
561 560 gp.GnuplotOpts.prefer_enhanced_postscript=None.)
562 561
563 562 'color=<bool>' -- if set, create a plot with color. Default
564 563 is to leave this option unchanged.
565 564
566 565 'solid=<bool>' -- if set, force lines to be solid (i.e., not
567 566 dashed).
568 567
569 568 'duplexing=<string>' -- set duplexing option ('defaultplex',
570 569 'simplex', or 'duplex'). Only request double-sided
571 570 printing if your printer can handle it. Actually this
572 571 option is probably meaningless since hardcopy() can only
573 572 print a single plot at a time.
574 573
575 574 'fontname=<string>' -- set the default font to <string>,
576 575 which must be a valid postscript font. The default is
577 576 to leave this option unspecified.
578 577
579 578 'fontsize=<double>' -- set the default font size, in
580 579 postscript points.
581 580
582 581 'debug=<bool>' -- print extra debugging information (useful if
583 582 your PostScript files are misteriously not being created).
584 583 """
585 584
586 585 if filename is None:
587 586 assert gp.GnuplotOpts.default_lpr is not None, \
588 587 OptionException('default_lpr is not set, so you can only '
589 588 'print to a file.')
590 589 filename = gp.GnuplotOpts.default_lpr
591 590 lpr_output = 1
592 591 else:
593 592 if filename.endswith('.eps'):
594 593 eps = 1
595 594 lpr_output = 0
596 595
597 596 # Be careful processing the options. If the user didn't
598 597 # request an option explicitly, do not specify it on the 'set
599 598 # terminal' line (don't even specify the default value for the
600 599 # option). This is to avoid confusing older versions of
601 600 # gnuplot that do not support all of these options. The
602 601 # exception is 'enhanced', which is just too useful to have to
603 602 # specify each time!
604 603
605 604 setterm = ['set', 'terminal', 'postscript']
606 605 if eps:
607 606 assert mode is None or mode=='eps', \
608 607 OptionException('eps option and mode are incompatible')
609 608 setterm.append('eps')
610 609 else:
611 610 if mode is not None:
612 611 assert mode in ['landscape', 'portrait', 'eps', 'default'], \
613 612 OptionException('illegal mode "%s"' % mode)
614 613 setterm.append(mode)
615 614 if enhanced is None:
616 615 enhanced = gp.GnuplotOpts.prefer_enhanced_postscript
617 616 if enhanced is not None:
618 617 if enhanced: setterm.append('enhanced')
619 618 else: setterm.append('noenhanced')
620 619 if color is not None:
621 620 if color: setterm.append('color')
622 621 else: setterm.append('monochrome')
623 622 if solid is not None:
624 623 if solid: setterm.append('solid')
625 624 else: setterm.append('dashed')
626 625 if duplexing is not None:
627 626 assert duplexing in ['defaultplex', 'simplex', 'duplex'], \
628 627 OptionException('illegal duplexing mode "%s"' % duplexing)
629 628 setterm.append(duplexing)
630 629 if fontname is not None:
631 630 setterm.append('"%s"' % fontname)
632 631 if fontsize is not None:
633 632 setterm.append('%s' % fontsize)
634 633
635 634 self(string.join(setterm))
636 635 self.set_string('output', filename)
637 636 # replot the current figure (to the printer):
638 637 self.refresh()
639 638
640 639 # fperez. Ugly kludge: often for some reason the file is NOT created
641 640 # and we must reissue the creation commands. I have no idea why!
642 641 if not lpr_output:
643 642 #print 'Hardcopy <%s>' % filename # dbg
644 643 maxtries = 20
645 644 delay = 0.1 # delay (in seconds) between print attempts
646 645 for i in range(maxtries):
647 646 time.sleep(0.05) # safety, very small delay
648 647 if os.path.isfile(filename):
649 648 if debug:
650 649 print 'Hardcopy to file <%s> success at attempt #%s.' \
651 650 % (filename,i+1)
652 651 break
653 652 time.sleep(delay)
654 653 # try again, issue all commands just in case
655 654 self(string.join(setterm))
656 655 self.set_string('output', filename)
657 656 self.refresh()
658 657 if not os.path.isfile(filename):
659 658 print >> sys.stderr,'ERROR: Tried %s times and failed to '\
660 659 'create hardcopy file `%s`' % (maxtries,filename)
661 660
662 661 # reset the terminal to its `default' setting:
663 662 self('set terminal %s' % gp.GnuplotOpts.default_term)
664 663 self.set_string('output')
665 664
666 665 #********************** End of file <Gnuplot2.py> ************************
@@ -1,148 +1,147 b''
1 1 # -*- coding: utf-8 -*-
2 2 """Interactive functions and magic functions for Gnuplot usage.
3 3
4 4 This requires the Gnuplot.py module for interfacing python with Gnuplot, which
5 5 can be downloaded from:
6 6
7 7 http://gnuplot-py.sourceforge.net/
8 8
9 9 See gphelp() below for details on the services offered by this module.
10 10
11 11 Inspired by a suggestion/request from Arnd Baecker.
12
13 $Id: GnuplotInteractive.py 389 2004-10-09 07:59:30Z fperez $"""
12 """
14 13
15 14 __all__ = ['Gnuplot','gp','gp_new','plot','plot2','splot','replot',
16 15 'hardcopy','gpdata','gpfile','gpstring','gpfunc','gpgrid',
17 16 'gphelp']
18 17
19 18 import IPython.GnuplotRuntime as GRun
20 19 from IPython.genutils import page,warn
21 20
22 21 # Set global names for interactive use
23 22 Gnuplot = GRun.Gnuplot
24 23 gp_new = GRun.gp_new
25 24 gp = GRun.gp
26 25 plot = gp.plot
27 26 plot2 = gp.plot2
28 27 splot = gp.splot
29 28 replot = gp.replot
30 29 hardcopy = gp.hardcopy
31 30
32 31 # Accessors for the main plot object constructors:
33 32 gpdata = Gnuplot.Data
34 33 gpfile = Gnuplot.File
35 34 gpstring = Gnuplot.String
36 35 gpfunc = Gnuplot.Func
37 36 gpgrid = Gnuplot.GridData
38 37
39 38 def gphelp():
40 39 """Print information about the Gnuplot facilities in IPython."""
41 40
42 41 page("""
43 42 IPython provides an interface to access the Gnuplot scientific plotting
44 43 system, in an environment similar to that of Mathematica or Matlab.
45 44
46 45 New top-level global objects
47 46 ----------------------------
48 47
49 48 Please see their respective docstrings for further details.
50 49
51 50 - gp: a running Gnuplot instance. You can access its methods as
52 51 gp.<method>. gp(`a string`) will execute the given string as if it had been
53 52 typed in an interactive gnuplot window.
54 53
55 54 - plot, splot, replot and hardcopy: aliases to the methods of the same name in
56 55 the global running Gnuplot instance gp. These allow you to simply type:
57 56
58 57 In [1]: plot(x,sin(x),title='Sin(x)') # assuming x is a Numeric array
59 58
60 59 and obtain a plot of sin(x) vs x with the title 'Sin(x)'.
61 60
62 61 - gp_new: a function which returns a new Gnuplot instance. This can be used to
63 62 have multiple Gnuplot instances running in your session to compare different
64 63 plots, each in a separate window.
65 64
66 65 - Gnuplot: alias to the Gnuplot2 module, an improved drop-in replacement for
67 66 the original Gnuplot.py. Gnuplot2 needs Gnuplot but redefines several of its
68 67 functions with improved versions (Gnuplot2 comes with IPython).
69 68
70 69 - gpdata, gpfile, gpstring, gpfunc, gpgrid: aliases to Gnuplot.Data,
71 70 Gnuplot.File, Gnuplot.String, Gnuplot.Func and Gnuplot.GridData
72 71 respectively. These functions create objects which can then be passed to the
73 72 plotting commands. See the Gnuplot.py documentation for details.
74 73
75 74 Keep in mind that all commands passed to a Gnuplot instance are executed in
76 75 the Gnuplot namespace, where no Python variables exist. For example, for
77 76 plotting sin(x) vs x as above, typing
78 77
79 78 In [2]: gp('plot x,sin(x)')
80 79
81 80 would not work. Instead, you would get the plot of BOTH the functions 'x' and
82 81 'sin(x)', since Gnuplot doesn't know about the 'x' Python array. The plot()
83 82 method lives in python and does know about these variables.
84 83
85 84
86 85 New magic functions
87 86 -------------------
88 87
89 88 %gpc: pass one command to Gnuplot and execute it or open a Gnuplot shell where
90 89 each line of input is executed.
91 90
92 91 %gp_set_default: reset the value of IPython's global Gnuplot instance.""")
93 92
94 93 # Code below is all for IPython use
95 94 # Define the magic functions for communicating with the above gnuplot instance.
96 95 def magic_gpc(self,parameter_s=''):
97 96 """Execute a gnuplot command or open a gnuplot shell.
98 97
99 98 Usage (omit the % if automagic is on). There are two ways to use it:
100 99
101 100 1) %gpc 'command' -> passes 'command' directly to the gnuplot instance.
102 101
103 102 2) %gpc -> will open up a prompt (gnuplot>>>) which takes input like the
104 103 standard gnuplot interactive prompt. If you need to type a multi-line
105 104 command, use \\ at the end of each intermediate line.
106 105
107 106 Upon exiting of the gnuplot sub-shell, you return to your IPython
108 107 session (the gnuplot sub-shell can be invoked as many times as needed).
109 108 """
110 109
111 110 if parameter_s.strip():
112 111 self.shell.gnuplot(parameter_s)
113 112 else:
114 113 self.shell.gnuplot.interact()
115 114
116 115 def magic_gp_set_default(self,parameter_s=''):
117 116 """Set the default gnuplot instance accessed by the %gp magic function.
118 117
119 118 %gp_set_default name
120 119
121 120 Call with the name of the new instance at the command line. If you want to
122 121 set this instance in your own code (using an embedded IPython, for
123 122 example), simply set the variable __IPYTHON__.gnuplot to your own gnuplot
124 123 instance object."""
125 124
126 125 gname = parameter_s.strip()
127 126 G = eval(gname,self.shell.user_ns)
128 127 self.shell.gnuplot = G
129 128 self.shell.user_ns.update({'plot':G.plot,'splot':G.splot,'plot2':G.plot2,
130 129 'replot':G.replot,'hardcopy':G.hardcopy})
131 130
132 131 try:
133 132 __IPYTHON__
134 133 except NameError:
135 134 pass
136 135 else:
137 136 # make the global Gnuplot instance known to IPython
138 137 __IPYTHON__.gnuplot = GRun.gp
139 138 __IPYTHON__.gnuplot.shell_first_time = 1
140 139
141 140 print """*** Type `gphelp` for help on the Gnuplot integration features."""
142 141
143 142 # Add the new magic functions to the class dict
144 143 from IPython.iplib import InteractiveShell
145 144 InteractiveShell.magic_gpc = magic_gpc
146 145 InteractiveShell.magic_gp_set_default = magic_gp_set_default
147 146
148 147 #********************** End of file <GnuplotInteractive.py> *******************
@@ -1,147 +1,146 b''
1 1 # -*- coding: utf-8 -*-
2 2 """Basic Gnuplot functionality for inclusion in other code.
3 3
4 4 This module creates a running Gnuplot instance called 'gp' and builds other
5 5 convenient globals for quick use in running scripts. It is intended to allow
6 6 you to script plotting tasks in Python with a minimum of effort. A typical
7 7 usage would be:
8 8
9 9 import IPython.GnuplotRuntime as GP # or some other short name
10 10 GP.gp.plot(GP.File('your_data.dat'))
11 11
12 12
13 13 This module exposes the following objects:
14 14
15 15 - gp: a running Gnuplot instance. You can access its methods as
16 16 gp.<method>. gp(`a string`) will execute the given string as if it had been
17 17 typed in an interactive gnuplot window.
18 18
19 19 - gp_new: a function which returns a new Gnuplot instance. This can be used to
20 20 have multiple Gnuplot instances running in your session to compare different
21 21 plots.
22 22
23 23 - Gnuplot: alias to the Gnuplot2 module, an improved drop-in replacement for
24 24 the original Gnuplot.py. Gnuplot2 needs Gnuplot but redefines several of its
25 25 functions with improved versions (Gnuplot2 comes with IPython).
26 26
27 27 - Data: alias to Gnuplot.Data, makes a PlotItem from array data.
28 28
29 29 - File: alias to Gnuplot.File, makes a PlotItem from a file.
30 30
31 31 - String: alias to Gnuplot.String, makes a PlotItem from a string formatted
32 32 exactly like a file for Gnuplot.File would be.
33 33
34 34 - Func: alias to Gnuplot.Func, makes a PlotItem from a function string.
35 35
36 36 - GridData: alias to Gnuplot.GridData, makes a PlotItem from grid data.
37 37
38 38 - pm3d_config: a string with Gnuplot commands to set up the pm3d mode for
39 39 surface plotting. You can activate it simply by calling gp(pm3d_config).
40 40
41 41 - eps_fix_bbox: A Unix-only function to fix eps files with bad bounding boxes
42 42 (which Gnuplot generates when the plot size is set to square).
43 43
44 44 This requires the Gnuplot.py module for interfacing Python with Gnuplot, which
45 45 can be downloaded from:
46 46
47 47 http://gnuplot-py.sourceforge.net/
48 48
49 49 Inspired by a suggestion/request from Arnd Baecker.
50
51 $Id: GnuplotRuntime.py 389 2004-10-09 07:59:30Z fperez $"""
50 """
52 51
53 52 __all__ = ['Gnuplot','gp','gp_new','Data','File','Func','GridData',
54 53 'pm3d_config','eps_fix_bbox']
55 54
56 55 import os,tempfile,sys
57 56 from IPython.genutils import getoutput
58 57
59 58 #---------------------------------------------------------------------------
60 59 # Notes on mouse support for Gnuplot.py
61 60
62 61 # If you do not have a mouse-enabled gnuplot, set gnuplot_mouse to 0. If you
63 62 # use gnuplot, you should really grab a recent, mouse enabled copy. It is an
64 63 # extremely useful feature. Mouse support is official as of gnuplot 4.0,
65 64 # released in April 2004.
66 65
67 66 # For the mouse features to work correctly, you MUST set your Gnuplot.py
68 67 # module to use temporary files instead of 'inline data' for data
69 68 # communication. Note that this is the default, so unless you've manually
70 69 # fiddled with it you should be ok. If you need to make changes, in the
71 70 # Gnuplot module directory, loook for the gp_unix.py file and make sure the
72 71 # prefer_inline_data variable is set to 0. If you set it to 1 Gnuplot.py will
73 72 # try to pass the data to gnuplot via standard input, which completely
74 73 # confuses the mouse control system (even though it may be a bit faster than
75 74 # using temp files).
76 75
77 76 # As of Gnuplot.py v1.7, a new option was added to use FIFOs (pipes). This
78 77 # mechanism, while fast, also breaks the mouse system. You must therefore set
79 78 # the variable prefer_fifo_data to 0 in gp_unix.py.
80 79
81 80 tmpname = tempfile.mktemp()
82 81 open(tmpname,'w').write('set mouse')
83 82 gnu_out = getoutput('gnuplot '+ tmpname)
84 83 os.unlink(tmpname)
85 84 if gnu_out: # Gnuplot won't print anything if it has mouse support
86 85 print "*** Your version of Gnuplot appears not to have mouse support."
87 86 gnuplot_mouse = 0
88 87 else:
89 88 gnuplot_mouse = 1
90 89 del tmpname,gnu_out
91 90
92 91 # Default state for persistence of new gnuplot instances
93 92 if os.name in ['nt','dos'] or sys.platform == 'cygwin':
94 93 gnuplot_persist = 0
95 94 else:
96 95 gnuplot_persist = 1
97 96
98 97 import IPython.Gnuplot2 as Gnuplot
99 98
100 99 class NotGiven: pass
101 100
102 101 def gp_new(mouse=NotGiven,persist=NotGiven):
103 102 """Return a new Gnuplot instance.
104 103
105 104 The instance returned uses the improved methods defined in Gnuplot2.
106 105
107 106 Options (boolean):
108 107
109 108 - mouse: if unspecified, the module global gnuplot_mouse is used.
110 109
111 110 - persist: if unspecified, the module global gnuplot_persist is used."""
112 111
113 112 if mouse is NotGiven:
114 113 mouse = gnuplot_mouse
115 114 if persist is NotGiven:
116 115 persist = gnuplot_persist
117 116 g = Gnuplot.Gnuplot(persist=persist)
118 117 if mouse:
119 118 g('set mouse')
120 119 return g
121 120
122 121 # Global-level names.
123 122
124 123 # A global Gnuplot instance for interactive use:
125 124 gp = gp_new()
126 125
127 126 # Accessors for the main plot object constructors:
128 127 Data = Gnuplot.Data
129 128 File = Gnuplot.File
130 129 Func = Gnuplot.Func
131 130 String = Gnuplot.String
132 131 GridData = Gnuplot.GridData
133 132
134 133 # A Unix-only function to fix eps files with bad bounding boxes (which Gnuplot
135 134 # generates when the plot size is set to square):
136 135 eps_fix_bbox = Gnuplot.eps_fix_bbox
137 136
138 137 # String for configuring pm3d. Simply call g(pm3d_config) to execute it. pm3d
139 138 # is a very nice mode for plotting colormaps on surfaces. Modify the defaults
140 139 # below to suit your taste.
141 140 pm3d_config = """
142 141 set pm3d solid
143 142 set hidden3d
144 143 unset surface
145 144 set isosamples 50
146 145 """
147 146 #******************** End of file <GnuplotRuntime.py> ******************
@@ -1,292 +1,290 b''
1 1 # -*- coding: utf-8 -*-
2 2 """String interpolation for Python (by Ka-Ping Yee, 14 Feb 2000).
3 3
4 4 This module lets you quickly and conveniently interpolate values into
5 5 strings (in the flavour of Perl or Tcl, but with less extraneous
6 6 punctuation). You get a bit more power than in the other languages,
7 7 because this module allows subscripting, slicing, function calls,
8 8 attribute lookup, or arbitrary expressions. Variables and expressions
9 9 are evaluated in the namespace of the caller.
10 10
11 11 The itpl() function returns the result of interpolating a string, and
12 12 printpl() prints out an interpolated string. Here are some examples:
13 13
14 14 from Itpl import printpl
15 15 printpl("Here is a $string.")
16 16 printpl("Here is a $module.member.")
17 17 printpl("Here is an $object.member.")
18 18 printpl("Here is a $functioncall(with, arguments).")
19 19 printpl("Here is an ${arbitrary + expression}.")
20 20 printpl("Here is an $array[3] member.")
21 21 printpl("Here is a $dictionary['member'].")
22 22
23 23 The filter() function filters a file object so that output through it
24 24 is interpolated. This lets you produce the illusion that Python knows
25 25 how to do interpolation:
26 26
27 27 import Itpl
28 28 sys.stdout = Itpl.filter()
29 29 f = "fancy"
30 print "Isn't this $f?"
30 print "Is this not $f?"
31 31 print "Standard output has been replaced with a $sys.stdout object."
32 32 sys.stdout = Itpl.unfilter()
33 33 print "Okay, back $to $normal."
34 34
35 35 Under the hood, the Itpl class represents a string that knows how to
36 36 interpolate values. An instance of the class parses the string once
37 37 upon initialization; the evaluation and substitution can then be done
38 38 each time the instance is evaluated with str(instance). For example:
39 39
40 40 from Itpl import Itpl
41 41 s = Itpl("Here is $foo.")
42 42 foo = 5
43 43 print str(s)
44 44 foo = "bar"
45 45 print str(s)
46
47 $Id: Itpl.py 2918 2007-12-31 14:34:47Z vivainio $
48 """ # ' -> close an open quote for stupid emacs
46 """
49 47
50 48 #*****************************************************************************
51 49 #
52 50 # Copyright (c) 2001 Ka-Ping Yee <ping@lfw.org>
53 51 #
54 52 #
55 53 # Published under the terms of the MIT license, hereby reproduced:
56 54 #
57 55 # Permission is hereby granted, free of charge, to any person obtaining a copy
58 56 # of this software and associated documentation files (the "Software"), to
59 57 # deal in the Software without restriction, including without limitation the
60 58 # rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
61 59 # sell copies of the Software, and to permit persons to whom the Software is
62 60 # furnished to do so, subject to the following conditions:
63 61 #
64 62 # The above copyright notice and this permission notice shall be included in
65 63 # all copies or substantial portions of the Software.
66 64 #
67 65 # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
68 66 # IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
69 67 # FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
70 68 # AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
71 69 # LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
72 70 # FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
73 71 # IN THE SOFTWARE.
74 72 #
75 73 #*****************************************************************************
76 74
77 75 __author__ = 'Ka-Ping Yee <ping@lfw.org>'
78 76 __license__ = 'MIT'
79 77
80 78 import string
81 79 import sys
82 80 from tokenize import tokenprog
83 81 from types import StringType
84 82
85 83 class ItplError(ValueError):
86 84 def __init__(self, text, pos):
87 85 self.text = text
88 86 self.pos = pos
89 87 def __str__(self):
90 88 return "unfinished expression in %s at char %d" % (
91 89 repr(self.text), self.pos)
92 90
93 91 def matchorfail(text, pos):
94 92 match = tokenprog.match(text, pos)
95 93 if match is None:
96 94 raise ItplError(text, pos)
97 95
98 96 return match, match.end()
99 97
100 98 try:
101 99 itpl_encoding = sys.stdin.encoding or 'ascii'
102 100 except AttributeError:
103 101 itpl_encoding = 'ascii'
104 102
105 103
106 104
107 105 class Itpl:
108 106 """Class representing a string with interpolation abilities.
109 107
110 108 Upon creation, an instance works out what parts of the format
111 109 string are literal and what parts need to be evaluated. The
112 110 evaluation and substitution happens in the namespace of the
113 111 caller when str(instance) is called."""
114 112
115 113 def __init__(self, format,codec=itpl_encoding,encoding_errors='backslashreplace'):
116 114 """The single mandatory argument to this constructor is a format
117 115 string.
118 116
119 117 The format string is parsed according to the following rules:
120 118
121 119 1. A dollar sign and a name, possibly followed by any of:
122 120 - an open-paren, and anything up to the matching paren
123 121 - an open-bracket, and anything up to the matching bracket
124 122 - a period and a name
125 123 any number of times, is evaluated as a Python expression.
126 124
127 125 2. A dollar sign immediately followed by an open-brace, and
128 126 anything up to the matching close-brace, is evaluated as
129 127 a Python expression.
130 128
131 129 3. Outside of the expressions described in the above two rules,
132 130 two dollar signs in a row give you one literal dollar sign.
133 131
134 132 Optional arguments:
135 133
136 134 - codec('utf_8'): a string containing the name of a valid Python
137 135 codec.
138 136
139 137 - encoding_errors('backslashreplace'): a string with a valid error handling
140 138 policy. See the codecs module documentation for details.
141 139
142 140 These are used to encode the format string if a call to str() fails on
143 141 the expanded result."""
144 142
145 143 if not isinstance(format,basestring):
146 144 raise TypeError, "needs string initializer"
147 145 self.format = format
148 146 self.codec = codec
149 147 self.encoding_errors = encoding_errors
150 148
151 149 namechars = "abcdefghijklmnopqrstuvwxyz" \
152 150 "ABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789_";
153 151 chunks = []
154 152 pos = 0
155 153
156 154 while 1:
157 155 dollar = string.find(format, "$", pos)
158 156 if dollar < 0: break
159 157 nextchar = format[dollar+1]
160 158
161 159 if nextchar == "{":
162 160 chunks.append((0, format[pos:dollar]))
163 161 pos, level = dollar+2, 1
164 162 while level:
165 163 match, pos = matchorfail(format, pos)
166 164 tstart, tend = match.regs[3]
167 165 token = format[tstart:tend]
168 166 if token == "{": level = level+1
169 167 elif token == "}": level = level-1
170 168 chunks.append((1, format[dollar+2:pos-1]))
171 169
172 170 elif nextchar in namechars:
173 171 chunks.append((0, format[pos:dollar]))
174 172 match, pos = matchorfail(format, dollar+1)
175 173 while pos < len(format):
176 174 if format[pos] == "." and \
177 175 pos+1 < len(format) and format[pos+1] in namechars:
178 176 match, pos = matchorfail(format, pos+1)
179 177 elif format[pos] in "([":
180 178 pos, level = pos+1, 1
181 179 while level:
182 180 match, pos = matchorfail(format, pos)
183 181 tstart, tend = match.regs[3]
184 182 token = format[tstart:tend]
185 183 if token[0] in "([": level = level+1
186 184 elif token[0] in ")]": level = level-1
187 185 else: break
188 186 chunks.append((1, format[dollar+1:pos]))
189 187
190 188 else:
191 189 chunks.append((0, format[pos:dollar+1]))
192 190 pos = dollar + 1 + (nextchar == "$")
193 191
194 192 if pos < len(format): chunks.append((0, format[pos:]))
195 193 self.chunks = chunks
196 194
197 195 def __repr__(self):
198 196 return "<Itpl %s >" % repr(self.format)
199 197
200 198 def _str(self,glob,loc):
201 199 """Evaluate to a string in the given globals/locals.
202 200
203 201 The final output is built by calling str(), but if this fails, the
204 202 result is encoded with the instance's codec and error handling policy,
205 203 via a call to out.encode(self.codec,self.encoding_errors)"""
206 204 result = []
207 205 app = result.append
208 206 for live, chunk in self.chunks:
209 207 if live:
210 208 val = eval(chunk,glob,loc)
211 209 try:
212 210 app(str(val))
213 211 except UnicodeEncodeError:
214 212 app(unicode(val))
215 213
216 214 else: app(chunk)
217 215 out = ''.join(result)
218 216 try:
219 217 return str(out)
220 218 except UnicodeError:
221 219 return out.encode(self.codec,self.encoding_errors)
222 220
223 221 def __str__(self):
224 222 """Evaluate and substitute the appropriate parts of the string."""
225 223
226 224 # We need to skip enough frames to get to the actual caller outside of
227 225 # Itpl.
228 226 frame = sys._getframe(1)
229 227 while frame.f_globals["__name__"] == __name__: frame = frame.f_back
230 228 loc, glob = frame.f_locals, frame.f_globals
231 229
232 230 return self._str(glob,loc)
233 231
234 232 class ItplNS(Itpl):
235 233 """Class representing a string with interpolation abilities.
236 234
237 235 This inherits from Itpl, but at creation time a namespace is provided
238 236 where the evaluation will occur. The interpolation becomes a bit more
239 237 efficient, as no traceback needs to be extracte. It also allows the
240 238 caller to supply a different namespace for the interpolation to occur than
241 239 its own."""
242 240
243 241 def __init__(self, format,globals,locals=None,
244 242 codec='utf_8',encoding_errors='backslashreplace'):
245 243 """ItplNS(format,globals[,locals]) -> interpolating string instance.
246 244
247 245 This constructor, besides a format string, takes a globals dictionary
248 246 and optionally a locals (which defaults to globals if not provided).
249 247
250 248 For further details, see the Itpl constructor."""
251 249
252 250 if locals is None:
253 251 locals = globals
254 252 self.globals = globals
255 253 self.locals = locals
256 254 Itpl.__init__(self,format,codec,encoding_errors)
257 255
258 256 def __str__(self):
259 257 """Evaluate and substitute the appropriate parts of the string."""
260 258 return self._str(self.globals,self.locals)
261 259
262 260 def __repr__(self):
263 261 return "<ItplNS %s >" % repr(self.format)
264 262
265 263 # utilities for fast printing
266 264 def itpl(text): return str(Itpl(text))
267 265 def printpl(text): print itpl(text)
268 266 # versions with namespace
269 267 def itplns(text,globals,locals=None): return str(ItplNS(text,globals,locals))
270 268 def printplns(text,globals,locals=None): print itplns(text,globals,locals)
271 269
272 270 class ItplFile:
273 271 """A file object that filters each write() through an interpolator."""
274 272 def __init__(self, file): self.file = file
275 273 def __repr__(self): return "<interpolated " + repr(self.file) + ">"
276 274 def __getattr__(self, attr): return getattr(self.file, attr)
277 275 def write(self, text): self.file.write(str(Itpl(text)))
278 276
279 277 def filter(file=sys.stdout):
280 278 """Return an ItplFile that filters writes to the given file object.
281 279
282 280 'file = filter(file)' replaces 'file' with a filtered object that
283 281 has a write() method. When called with no argument, this creates
284 282 a filter to sys.stdout."""
285 283 return ItplFile(file)
286 284
287 285 def unfilter(ifile=None):
288 286 """Return the original file that corresponds to the given ItplFile.
289 287
290 288 'file = unfilter(file)' undoes the effect of 'file = filter(file)'.
291 289 'sys.stdout = unfilter()' undoes the effect of 'sys.stdout = filter()'."""
292 290 return ifile and ifile.file or sys.stdout.file
@@ -1,270 +1,263 b''
1 1 # -*- coding: utf-8 -*-
2 2 """
3 3 Logger class for IPython's logging facilities.
4
5 $Id: Logger.py 2875 2007-11-26 08:37:39Z fperez $
6 4 """
7 5
8 6 #*****************************************************************************
9 7 # Copyright (C) 2001 Janko Hauser <jhauser@zscout.de> and
10 8 # Copyright (C) 2001-2006 Fernando Perez <fperez@colorado.edu>
11 9 #
12 10 # Distributed under the terms of the BSD License. The full license is in
13 11 # the file COPYING, distributed as part of this software.
14 12 #*****************************************************************************
15 13
16 14 #****************************************************************************
17 15 # Modules and globals
18 16
19 from IPython import Release
20 __author__ = '%s <%s>\n%s <%s>' % \
21 ( Release.authors['Janko'] + Release.authors['Fernando'] )
22 __license__ = Release.license
23
24 17 # Python standard modules
25 18 import glob
26 19 import os
27 20 import time
28 21
29 22 #****************************************************************************
30 23 # FIXME: This class isn't a mixin anymore, but it still needs attributes from
31 24 # ipython and does input cache management. Finish cleanup later...
32 25
33 26 class Logger(object):
34 27 """A Logfile class with different policies for file creation"""
35 28
36 29 def __init__(self,shell,logfname='Logger.log',loghead='',logmode='over'):
37 30
38 31 self._i00,self._i,self._ii,self._iii = '','','',''
39 32
40 33 # this is the full ipython instance, we need some attributes from it
41 34 # which won't exist until later. What a mess, clean up later...
42 35 self.shell = shell
43 36
44 37 self.logfname = logfname
45 38 self.loghead = loghead
46 39 self.logmode = logmode
47 40 self.logfile = None
48 41
49 42 # Whether to log raw or processed input
50 43 self.log_raw_input = False
51 44
52 45 # whether to also log output
53 46 self.log_output = False
54 47
55 48 # whether to put timestamps before each log entry
56 49 self.timestamp = False
57 50
58 51 # activity control flags
59 52 self.log_active = False
60 53
61 54 # logmode is a validated property
62 55 def _set_mode(self,mode):
63 56 if mode not in ['append','backup','global','over','rotate']:
64 57 raise ValueError,'invalid log mode %s given' % mode
65 58 self._logmode = mode
66 59
67 60 def _get_mode(self):
68 61 return self._logmode
69 62
70 63 logmode = property(_get_mode,_set_mode)
71 64
72 65 def logstart(self,logfname=None,loghead=None,logmode=None,
73 66 log_output=False,timestamp=False,log_raw_input=False):
74 67 """Generate a new log-file with a default header.
75 68
76 69 Raises RuntimeError if the log has already been started"""
77 70
78 71 if self.logfile is not None:
79 72 raise RuntimeError('Log file is already active: %s' %
80 73 self.logfname)
81 74
82 75 self.log_active = True
83 76
84 77 # The parameters can override constructor defaults
85 78 if logfname is not None: self.logfname = logfname
86 79 if loghead is not None: self.loghead = loghead
87 80 if logmode is not None: self.logmode = logmode
88 81
89 82 # Parameters not part of the constructor
90 83 self.timestamp = timestamp
91 84 self.log_output = log_output
92 85 self.log_raw_input = log_raw_input
93 86
94 87 # init depending on the log mode requested
95 88 isfile = os.path.isfile
96 89 logmode = self.logmode
97 90
98 91 if logmode == 'append':
99 92 self.logfile = open(self.logfname,'a')
100 93
101 94 elif logmode == 'backup':
102 95 if isfile(self.logfname):
103 96 backup_logname = self.logfname+'~'
104 97 # Manually remove any old backup, since os.rename may fail
105 98 # under Windows.
106 99 if isfile(backup_logname):
107 100 os.remove(backup_logname)
108 101 os.rename(self.logfname,backup_logname)
109 102 self.logfile = open(self.logfname,'w')
110 103
111 104 elif logmode == 'global':
112 105 self.logfname = os.path.join(self.shell.home_dir,self.logfname)
113 106 self.logfile = open(self.logfname, 'a')
114 107
115 108 elif logmode == 'over':
116 109 if isfile(self.logfname):
117 110 os.remove(self.logfname)
118 111 self.logfile = open(self.logfname,'w')
119 112
120 113 elif logmode == 'rotate':
121 114 if isfile(self.logfname):
122 115 if isfile(self.logfname+'.001~'):
123 116 old = glob.glob(self.logfname+'.*~')
124 117 old.sort()
125 118 old.reverse()
126 119 for f in old:
127 120 root, ext = os.path.splitext(f)
128 121 num = int(ext[1:-1])+1
129 122 os.rename(f, root+'.'+`num`.zfill(3)+'~')
130 123 os.rename(self.logfname, self.logfname+'.001~')
131 124 self.logfile = open(self.logfname,'w')
132 125
133 126 if logmode != 'append':
134 127 self.logfile.write(self.loghead)
135 128
136 129 self.logfile.flush()
137 130
138 131 def switch_log(self,val):
139 132 """Switch logging on/off. val should be ONLY a boolean."""
140 133
141 134 if val not in [False,True,0,1]:
142 135 raise ValueError, \
143 136 'Call switch_log ONLY with a boolean argument, not with:',val
144 137
145 138 label = {0:'OFF',1:'ON',False:'OFF',True:'ON'}
146 139
147 140 if self.logfile is None:
148 141 print """
149 142 Logging hasn't been started yet (use logstart for that).
150 143
151 144 %logon/%logoff are for temporarily starting and stopping logging for a logfile
152 145 which already exists. But you must first start the logging process with
153 146 %logstart (optionally giving a logfile name)."""
154 147
155 148 else:
156 149 if self.log_active == val:
157 150 print 'Logging is already',label[val]
158 151 else:
159 152 print 'Switching logging',label[val]
160 153 self.log_active = not self.log_active
161 154 self.log_active_out = self.log_active
162 155
163 156 def logstate(self):
164 157 """Print a status message about the logger."""
165 158 if self.logfile is None:
166 159 print 'Logging has not been activated.'
167 160 else:
168 161 state = self.log_active and 'active' or 'temporarily suspended'
169 162 print 'Filename :',self.logfname
170 163 print 'Mode :',self.logmode
171 164 print 'Output logging :',self.log_output
172 165 print 'Raw input log :',self.log_raw_input
173 166 print 'Timestamping :',self.timestamp
174 167 print 'State :',state
175 168
176 169 def log(self,line_ori,line_mod,continuation=None):
177 170 """Write the line to a log and create input cache variables _i*.
178 171
179 172 Inputs:
180 173
181 174 - line_ori: unmodified input line from the user. This is not
182 175 necessarily valid Python.
183 176
184 177 - line_mod: possibly modified input, such as the transformations made
185 178 by input prefilters or input handlers of various kinds. This should
186 179 always be valid Python.
187 180
188 181 - continuation: if True, indicates this is part of multi-line input."""
189 182
190 183 # update the auto _i tables
191 184 #print '***logging line',line_mod # dbg
192 185 #print '***cache_count', self.shell.outputcache.prompt_count # dbg
193 186 try:
194 187 input_hist = self.shell.user_ns['_ih']
195 188 except:
196 189 #print 'userns:',self.shell.user_ns.keys() # dbg
197 190 return
198 191
199 192 out_cache = self.shell.outputcache
200 193
201 194 # add blank lines if the input cache fell out of sync.
202 195 if out_cache.do_full_cache and \
203 196 out_cache.prompt_count +1 > len(input_hist):
204 197 input_hist.extend(['\n'] * (out_cache.prompt_count - len(input_hist)))
205 198
206 199 if not continuation and line_mod:
207 200 self._iii = self._ii
208 201 self._ii = self._i
209 202 self._i = self._i00
210 203 # put back the final \n of every input line
211 204 self._i00 = line_mod+'\n'
212 205 #print 'Logging input:<%s>' % line_mod # dbg
213 206 input_hist.append(self._i00)
214 207 #print '---[%s]' % (len(input_hist)-1,) # dbg
215 208
216 209 # hackish access to top-level namespace to create _i1,_i2... dynamically
217 210 to_main = {'_i':self._i,'_ii':self._ii,'_iii':self._iii}
218 211 if self.shell.outputcache.do_full_cache:
219 212 in_num = self.shell.outputcache.prompt_count
220 213
221 214 # but if the opposite is true (a macro can produce multiple inputs
222 215 # with no output display called), then bring the output counter in
223 216 # sync:
224 217 last_num = len(input_hist)-1
225 218 if in_num != last_num:
226 219 in_num = self.shell.outputcache.prompt_count = last_num
227 220 new_i = '_i%s' % in_num
228 221 if continuation:
229 222 self._i00 = '%s%s\n' % (self.shell.user_ns[new_i],line_mod)
230 223 input_hist[in_num] = self._i00
231 224 to_main[new_i] = self._i00
232 225 self.shell.user_ns.update(to_main)
233 226
234 227 # Write the log line, but decide which one according to the
235 228 # log_raw_input flag, set when the log is started.
236 229 if self.log_raw_input:
237 230 self.log_write(line_ori)
238 231 else:
239 232 self.log_write(line_mod)
240 233
241 234 def log_write(self,data,kind='input'):
242 235 """Write data to the log file, if active"""
243 236
244 237 #print 'data: %r' % data # dbg
245 238 if self.log_active and data:
246 239 write = self.logfile.write
247 240 if kind=='input':
248 241 if self.timestamp:
249 242 write(time.strftime('# %a, %d %b %Y %H:%M:%S\n',
250 243 time.localtime()))
251 244 write('%s\n' % data)
252 245 elif kind=='output' and self.log_output:
253 246 odata = '\n'.join(['#[Out]# %s' % s
254 247 for s in data.split('\n')])
255 248 write('%s\n' % odata)
256 249 self.logfile.flush()
257 250
258 251 def logstop(self):
259 252 """Fully stop logging and close log file.
260 253
261 254 In order to start logging again, a new logstart() call needs to be
262 255 made, possibly (though not necessarily) with a new filename, mode and
263 256 other options."""
264 257
265 258 self.logfile.close()
266 259 self.logfile = None
267 260 self.log_active = False
268 261
269 262 # For backwards compatibility, in case anyone was using this.
270 263 close_log = logstop
@@ -1,3416 +1,3415 b''
1 1 # -*- coding: utf-8 -*-
2 2 """Magic functions for InteractiveShell.
3
4 $Id: Magic.py 2996 2008-01-30 06:31:39Z fperez $"""
3 """
5 4
6 5 #*****************************************************************************
7 6 # Copyright (C) 2001 Janko Hauser <jhauser@zscout.de> and
8 7 # Copyright (C) 2001-2006 Fernando Perez <fperez@colorado.edu>
9 8 #
10 9 # Distributed under the terms of the BSD License. The full license is in
11 10 # the file COPYING, distributed as part of this software.
12 11 #*****************************************************************************
13 12
14 13 #****************************************************************************
15 14 # Modules and globals
16 15
17 16 from IPython import Release
18 17 __author__ = '%s <%s>\n%s <%s>' % \
19 18 ( Release.authors['Janko'] + Release.authors['Fernando'] )
20 19 __license__ = Release.license
21 20
22 21 # Python standard modules
23 22 import __builtin__
24 23 import bdb
25 24 import inspect
26 25 import os
27 26 import pdb
28 27 import pydoc
29 28 import sys
30 29 import re
31 30 import tempfile
32 31 import time
33 32 import cPickle as pickle
34 33 import textwrap
35 34 from cStringIO import StringIO
36 35 from getopt import getopt,GetoptError
37 36 from pprint import pprint, pformat
38 37 from sets import Set
39 38
40 39 # cProfile was added in Python2.5
41 40 try:
42 41 import cProfile as profile
43 42 import pstats
44 43 except ImportError:
45 44 # profile isn't bundled by default in Debian for license reasons
46 45 try:
47 46 import profile,pstats
48 47 except ImportError:
49 48 profile = pstats = None
50 49
51 50 # Homebrewed
52 51 import IPython
53 52 from IPython import Debugger, OInspect, wildcard
54 53 from IPython.FakeModule import FakeModule
55 54 from IPython.Itpl import Itpl, itpl, printpl,itplns
56 55 from IPython.PyColorize import Parser
57 56 from IPython.ipstruct import Struct
58 57 from IPython.macro import Macro
59 58 from IPython.genutils import *
60 59 from IPython import platutils
61 60 import IPython.generics
62 61 import IPython.ipapi
63 62 from IPython.ipapi import UsageError
64 63 from IPython.testing import decorators as testdec
65 64
66 65 #***************************************************************************
67 66 # Utility functions
68 67 def on_off(tag):
69 68 """Return an ON/OFF string for a 1/0 input. Simple utility function."""
70 69 return ['OFF','ON'][tag]
71 70
72 71 class Bunch: pass
73 72
74 73 def compress_dhist(dh):
75 74 head, tail = dh[:-10], dh[-10:]
76 75
77 76 newhead = []
78 77 done = Set()
79 78 for h in head:
80 79 if h in done:
81 80 continue
82 81 newhead.append(h)
83 82 done.add(h)
84 83
85 84 return newhead + tail
86 85
87 86
88 87 #***************************************************************************
89 88 # Main class implementing Magic functionality
90 89 class Magic:
91 90 """Magic functions for InteractiveShell.
92 91
93 92 Shell functions which can be reached as %function_name. All magic
94 93 functions should accept a string, which they can parse for their own
95 94 needs. This can make some functions easier to type, eg `%cd ../`
96 95 vs. `%cd("../")`
97 96
98 97 ALL definitions MUST begin with the prefix magic_. The user won't need it
99 98 at the command line, but it is is needed in the definition. """
100 99
101 100 # class globals
102 101 auto_status = ['Automagic is OFF, % prefix IS needed for magic functions.',
103 102 'Automagic is ON, % prefix NOT needed for magic functions.']
104 103
105 104 #......................................................................
106 105 # some utility functions
107 106
108 107 def __init__(self,shell):
109 108
110 109 self.options_table = {}
111 110 if profile is None:
112 111 self.magic_prun = self.profile_missing_notice
113 112 self.shell = shell
114 113
115 114 # namespace for holding state we may need
116 115 self._magic_state = Bunch()
117 116
118 117 def profile_missing_notice(self, *args, **kwargs):
119 118 error("""\
120 119 The profile module could not be found. It has been removed from the standard
121 120 python packages because of its non-free license. To use profiling, install the
122 121 python-profiler package from non-free.""")
123 122
124 123 def default_option(self,fn,optstr):
125 124 """Make an entry in the options_table for fn, with value optstr"""
126 125
127 126 if fn not in self.lsmagic():
128 127 error("%s is not a magic function" % fn)
129 128 self.options_table[fn] = optstr
130 129
131 130 def lsmagic(self):
132 131 """Return a list of currently available magic functions.
133 132
134 133 Gives a list of the bare names after mangling (['ls','cd', ...], not
135 134 ['magic_ls','magic_cd',...]"""
136 135
137 136 # FIXME. This needs a cleanup, in the way the magics list is built.
138 137
139 138 # magics in class definition
140 139 class_magic = lambda fn: fn.startswith('magic_') and \
141 140 callable(Magic.__dict__[fn])
142 141 # in instance namespace (run-time user additions)
143 142 inst_magic = lambda fn: fn.startswith('magic_') and \
144 143 callable(self.__dict__[fn])
145 144 # and bound magics by user (so they can access self):
146 145 inst_bound_magic = lambda fn: fn.startswith('magic_') and \
147 146 callable(self.__class__.__dict__[fn])
148 147 magics = filter(class_magic,Magic.__dict__.keys()) + \
149 148 filter(inst_magic,self.__dict__.keys()) + \
150 149 filter(inst_bound_magic,self.__class__.__dict__.keys())
151 150 out = []
152 151 for fn in Set(magics):
153 152 out.append(fn.replace('magic_','',1))
154 153 out.sort()
155 154 return out
156 155
157 156 def extract_input_slices(self,slices,raw=False):
158 157 """Return as a string a set of input history slices.
159 158
160 159 Inputs:
161 160
162 161 - slices: the set of slices is given as a list of strings (like
163 162 ['1','4:8','9'], since this function is for use by magic functions
164 163 which get their arguments as strings.
165 164
166 165 Optional inputs:
167 166
168 167 - raw(False): by default, the processed input is used. If this is
169 168 true, the raw input history is used instead.
170 169
171 170 Note that slices can be called with two notations:
172 171
173 172 N:M -> standard python form, means including items N...(M-1).
174 173
175 174 N-M -> include items N..M (closed endpoint)."""
176 175
177 176 if raw:
178 177 hist = self.shell.input_hist_raw
179 178 else:
180 179 hist = self.shell.input_hist
181 180
182 181 cmds = []
183 182 for chunk in slices:
184 183 if ':' in chunk:
185 184 ini,fin = map(int,chunk.split(':'))
186 185 elif '-' in chunk:
187 186 ini,fin = map(int,chunk.split('-'))
188 187 fin += 1
189 188 else:
190 189 ini = int(chunk)
191 190 fin = ini+1
192 191 cmds.append(hist[ini:fin])
193 192 return cmds
194 193
195 194 def _ofind(self, oname, namespaces=None):
196 195 """Find an object in the available namespaces.
197 196
198 197 self._ofind(oname) -> dict with keys: found,obj,ospace,ismagic
199 198
200 199 Has special code to detect magic functions.
201 200 """
202 201
203 202 oname = oname.strip()
204 203
205 204 alias_ns = None
206 205 if namespaces is None:
207 206 # Namespaces to search in:
208 207 # Put them in a list. The order is important so that we
209 208 # find things in the same order that Python finds them.
210 209 namespaces = [ ('Interactive', self.shell.user_ns),
211 210 ('IPython internal', self.shell.internal_ns),
212 211 ('Python builtin', __builtin__.__dict__),
213 212 ('Alias', self.shell.alias_table),
214 213 ]
215 214 alias_ns = self.shell.alias_table
216 215
217 216 # initialize results to 'null'
218 217 found = 0; obj = None; ospace = None; ds = None;
219 218 ismagic = 0; isalias = 0; parent = None
220 219
221 220 # Look for the given name by splitting it in parts. If the head is
222 221 # found, then we look for all the remaining parts as members, and only
223 222 # declare success if we can find them all.
224 223 oname_parts = oname.split('.')
225 224 oname_head, oname_rest = oname_parts[0],oname_parts[1:]
226 225 for nsname,ns in namespaces:
227 226 try:
228 227 obj = ns[oname_head]
229 228 except KeyError:
230 229 continue
231 230 else:
232 231 #print 'oname_rest:', oname_rest # dbg
233 232 for part in oname_rest:
234 233 try:
235 234 parent = obj
236 235 obj = getattr(obj,part)
237 236 except:
238 237 # Blanket except b/c some badly implemented objects
239 238 # allow __getattr__ to raise exceptions other than
240 239 # AttributeError, which then crashes IPython.
241 240 break
242 241 else:
243 242 # If we finish the for loop (no break), we got all members
244 243 found = 1
245 244 ospace = nsname
246 245 if ns == alias_ns:
247 246 isalias = 1
248 247 break # namespace loop
249 248
250 249 # Try to see if it's magic
251 250 if not found:
252 251 if oname.startswith(self.shell.ESC_MAGIC):
253 252 oname = oname[1:]
254 253 obj = getattr(self,'magic_'+oname,None)
255 254 if obj is not None:
256 255 found = 1
257 256 ospace = 'IPython internal'
258 257 ismagic = 1
259 258
260 259 # Last try: special-case some literals like '', [], {}, etc:
261 260 if not found and oname_head in ["''",'""','[]','{}','()']:
262 261 obj = eval(oname_head)
263 262 found = 1
264 263 ospace = 'Interactive'
265 264
266 265 return {'found':found, 'obj':obj, 'namespace':ospace,
267 266 'ismagic':ismagic, 'isalias':isalias, 'parent':parent}
268 267
269 268 def arg_err(self,func):
270 269 """Print docstring if incorrect arguments were passed"""
271 270 print 'Error in arguments:'
272 271 print OInspect.getdoc(func)
273 272
274 273 def format_latex(self,strng):
275 274 """Format a string for latex inclusion."""
276 275
277 276 # Characters that need to be escaped for latex:
278 277 escape_re = re.compile(r'(%|_|\$|#|&)',re.MULTILINE)
279 278 # Magic command names as headers:
280 279 cmd_name_re = re.compile(r'^(%s.*?):' % self.shell.ESC_MAGIC,
281 280 re.MULTILINE)
282 281 # Magic commands
283 282 cmd_re = re.compile(r'(?P<cmd>%s.+?\b)(?!\}\}:)' % self.shell.ESC_MAGIC,
284 283 re.MULTILINE)
285 284 # Paragraph continue
286 285 par_re = re.compile(r'\\$',re.MULTILINE)
287 286
288 287 # The "\n" symbol
289 288 newline_re = re.compile(r'\\n')
290 289
291 290 # Now build the string for output:
292 291 #strng = cmd_name_re.sub(r'\n\\texttt{\\textsl{\\large \1}}:',strng)
293 292 strng = cmd_name_re.sub(r'\n\\bigskip\n\\texttt{\\textbf{ \1}}:',
294 293 strng)
295 294 strng = cmd_re.sub(r'\\texttt{\g<cmd>}',strng)
296 295 strng = par_re.sub(r'\\\\',strng)
297 296 strng = escape_re.sub(r'\\\1',strng)
298 297 strng = newline_re.sub(r'\\textbackslash{}n',strng)
299 298 return strng
300 299
301 300 def format_screen(self,strng):
302 301 """Format a string for screen printing.
303 302
304 303 This removes some latex-type format codes."""
305 304 # Paragraph continue
306 305 par_re = re.compile(r'\\$',re.MULTILINE)
307 306 strng = par_re.sub('',strng)
308 307 return strng
309 308
310 309 def parse_options(self,arg_str,opt_str,*long_opts,**kw):
311 310 """Parse options passed to an argument string.
312 311
313 312 The interface is similar to that of getopt(), but it returns back a
314 313 Struct with the options as keys and the stripped argument string still
315 314 as a string.
316 315
317 316 arg_str is quoted as a true sys.argv vector by using shlex.split.
318 317 This allows us to easily expand variables, glob files, quote
319 318 arguments, etc.
320 319
321 320 Options:
322 321 -mode: default 'string'. If given as 'list', the argument string is
323 322 returned as a list (split on whitespace) instead of a string.
324 323
325 324 -list_all: put all option values in lists. Normally only options
326 325 appearing more than once are put in a list.
327 326
328 327 -posix (True): whether to split the input line in POSIX mode or not,
329 328 as per the conventions outlined in the shlex module from the
330 329 standard library."""
331 330
332 331 # inject default options at the beginning of the input line
333 332 caller = sys._getframe(1).f_code.co_name.replace('magic_','')
334 333 arg_str = '%s %s' % (self.options_table.get(caller,''),arg_str)
335 334
336 335 mode = kw.get('mode','string')
337 336 if mode not in ['string','list']:
338 337 raise ValueError,'incorrect mode given: %s' % mode
339 338 # Get options
340 339 list_all = kw.get('list_all',0)
341 340 posix = kw.get('posix',True)
342 341
343 342 # Check if we have more than one argument to warrant extra processing:
344 343 odict = {} # Dictionary with options
345 344 args = arg_str.split()
346 345 if len(args) >= 1:
347 346 # If the list of inputs only has 0 or 1 thing in it, there's no
348 347 # need to look for options
349 348 argv = arg_split(arg_str,posix)
350 349 # Do regular option processing
351 350 try:
352 351 opts,args = getopt(argv,opt_str,*long_opts)
353 352 except GetoptError,e:
354 353 raise UsageError('%s ( allowed: "%s" %s)' % (e.msg,opt_str,
355 354 " ".join(long_opts)))
356 355 for o,a in opts:
357 356 if o.startswith('--'):
358 357 o = o[2:]
359 358 else:
360 359 o = o[1:]
361 360 try:
362 361 odict[o].append(a)
363 362 except AttributeError:
364 363 odict[o] = [odict[o],a]
365 364 except KeyError:
366 365 if list_all:
367 366 odict[o] = [a]
368 367 else:
369 368 odict[o] = a
370 369
371 370 # Prepare opts,args for return
372 371 opts = Struct(odict)
373 372 if mode == 'string':
374 373 args = ' '.join(args)
375 374
376 375 return opts,args
377 376
378 377 #......................................................................
379 378 # And now the actual magic functions
380 379
381 380 # Functions for IPython shell work (vars,funcs, config, etc)
382 381 def magic_lsmagic(self, parameter_s = ''):
383 382 """List currently available magic functions."""
384 383 mesc = self.shell.ESC_MAGIC
385 384 print 'Available magic functions:\n'+mesc+\
386 385 (' '+mesc).join(self.lsmagic())
387 386 print '\n' + Magic.auto_status[self.shell.rc.automagic]
388 387 return None
389 388
390 389 def magic_magic(self, parameter_s = ''):
391 390 """Print information about the magic function system.
392 391
393 392 Supported formats: -latex, -brief, -rest
394 393 """
395 394
396 395 mode = ''
397 396 try:
398 397 if parameter_s.split()[0] == '-latex':
399 398 mode = 'latex'
400 399 if parameter_s.split()[0] == '-brief':
401 400 mode = 'brief'
402 401 if parameter_s.split()[0] == '-rest':
403 402 mode = 'rest'
404 403 rest_docs = []
405 404 except:
406 405 pass
407 406
408 407 magic_docs = []
409 408 for fname in self.lsmagic():
410 409 mname = 'magic_' + fname
411 410 for space in (Magic,self,self.__class__):
412 411 try:
413 412 fn = space.__dict__[mname]
414 413 except KeyError:
415 414 pass
416 415 else:
417 416 break
418 417 if mode == 'brief':
419 418 # only first line
420 419 if fn.__doc__:
421 420 fndoc = fn.__doc__.split('\n',1)[0]
422 421 else:
423 422 fndoc = 'No documentation'
424 423 else:
425 424 fndoc = fn.__doc__.rstrip()
426 425
427 426 if mode == 'rest':
428 427 rest_docs.append('**%s%s**::\n\n\t%s\n\n' %(self.shell.ESC_MAGIC,
429 428 fname,fndoc))
430 429
431 430 else:
432 431 magic_docs.append('%s%s:\n\t%s\n' %(self.shell.ESC_MAGIC,
433 432 fname,fndoc))
434 433
435 434 magic_docs = ''.join(magic_docs)
436 435
437 436 if mode == 'rest':
438 437 return "".join(rest_docs)
439 438
440 439 if mode == 'latex':
441 440 print self.format_latex(magic_docs)
442 441 return
443 442 else:
444 443 magic_docs = self.format_screen(magic_docs)
445 444 if mode == 'brief':
446 445 return magic_docs
447 446
448 447 outmsg = """
449 448 IPython's 'magic' functions
450 449 ===========================
451 450
452 451 The magic function system provides a series of functions which allow you to
453 452 control the behavior of IPython itself, plus a lot of system-type
454 453 features. All these functions are prefixed with a % character, but parameters
455 454 are given without parentheses or quotes.
456 455
457 456 NOTE: If you have 'automagic' enabled (via the command line option or with the
458 457 %automagic function), you don't need to type in the % explicitly. By default,
459 458 IPython ships with automagic on, so you should only rarely need the % escape.
460 459
461 460 Example: typing '%cd mydir' (without the quotes) changes you working directory
462 461 to 'mydir', if it exists.
463 462
464 463 You can define your own magic functions to extend the system. See the supplied
465 464 ipythonrc and example-magic.py files for details (in your ipython
466 465 configuration directory, typically $HOME/.ipython/).
467 466
468 467 You can also define your own aliased names for magic functions. In your
469 468 ipythonrc file, placing a line like:
470 469
471 470 execute __IPYTHON__.magic_pf = __IPYTHON__.magic_profile
472 471
473 472 will define %pf as a new name for %profile.
474 473
475 474 You can also call magics in code using the ipmagic() function, which IPython
476 475 automatically adds to the builtin namespace. Type 'ipmagic?' for details.
477 476
478 477 For a list of the available magic functions, use %lsmagic. For a description
479 478 of any of them, type %magic_name?, e.g. '%cd?'.
480 479
481 480 Currently the magic system has the following functions:\n"""
482 481
483 482 mesc = self.shell.ESC_MAGIC
484 483 outmsg = ("%s\n%s\n\nSummary of magic functions (from %slsmagic):"
485 484 "\n\n%s%s\n\n%s" % (outmsg,
486 485 magic_docs,mesc,mesc,
487 486 (' '+mesc).join(self.lsmagic()),
488 487 Magic.auto_status[self.shell.rc.automagic] ) )
489 488
490 489 page(outmsg,screen_lines=self.shell.rc.screen_length)
491 490
492 491
493 492 def magic_autoindent(self, parameter_s = ''):
494 493 """Toggle autoindent on/off (if available)."""
495 494
496 495 self.shell.set_autoindent()
497 496 print "Automatic indentation is:",['OFF','ON'][self.shell.autoindent]
498 497
499 498
500 499 def magic_automagic(self, parameter_s = ''):
501 500 """Make magic functions callable without having to type the initial %.
502 501
503 502 Without argumentsl toggles on/off (when off, you must call it as
504 503 %automagic, of course). With arguments it sets the value, and you can
505 504 use any of (case insensitive):
506 505
507 506 - on,1,True: to activate
508 507
509 508 - off,0,False: to deactivate.
510 509
511 510 Note that magic functions have lowest priority, so if there's a
512 511 variable whose name collides with that of a magic fn, automagic won't
513 512 work for that function (you get the variable instead). However, if you
514 513 delete the variable (del var), the previously shadowed magic function
515 514 becomes visible to automagic again."""
516 515
517 516 rc = self.shell.rc
518 517 arg = parameter_s.lower()
519 518 if parameter_s in ('on','1','true'):
520 519 rc.automagic = True
521 520 elif parameter_s in ('off','0','false'):
522 521 rc.automagic = False
523 522 else:
524 523 rc.automagic = not rc.automagic
525 524 print '\n' + Magic.auto_status[rc.automagic]
526 525
527 526 @testdec.skip_doctest
528 527 def magic_autocall(self, parameter_s = ''):
529 528 """Make functions callable without having to type parentheses.
530 529
531 530 Usage:
532 531
533 532 %autocall [mode]
534 533
535 534 The mode can be one of: 0->Off, 1->Smart, 2->Full. If not given, the
536 535 value is toggled on and off (remembering the previous state).
537 536
538 537 In more detail, these values mean:
539 538
540 539 0 -> fully disabled
541 540
542 541 1 -> active, but do not apply if there are no arguments on the line.
543 542
544 543 In this mode, you get:
545 544
546 545 In [1]: callable
547 546 Out[1]: <built-in function callable>
548 547
549 548 In [2]: callable 'hello'
550 549 ------> callable('hello')
551 550 Out[2]: False
552 551
553 552 2 -> Active always. Even if no arguments are present, the callable
554 553 object is called:
555 554
556 555 In [2]: float
557 556 ------> float()
558 557 Out[2]: 0.0
559 558
560 559 Note that even with autocall off, you can still use '/' at the start of
561 560 a line to treat the first argument on the command line as a function
562 561 and add parentheses to it:
563 562
564 563 In [8]: /str 43
565 564 ------> str(43)
566 565 Out[8]: '43'
567 566
568 567 # all-random (note for auto-testing)
569 568 """
570 569
571 570 rc = self.shell.rc
572 571
573 572 if parameter_s:
574 573 arg = int(parameter_s)
575 574 else:
576 575 arg = 'toggle'
577 576
578 577 if not arg in (0,1,2,'toggle'):
579 578 error('Valid modes: (0->Off, 1->Smart, 2->Full')
580 579 return
581 580
582 581 if arg in (0,1,2):
583 582 rc.autocall = arg
584 583 else: # toggle
585 584 if rc.autocall:
586 585 self._magic_state.autocall_save = rc.autocall
587 586 rc.autocall = 0
588 587 else:
589 588 try:
590 589 rc.autocall = self._magic_state.autocall_save
591 590 except AttributeError:
592 591 rc.autocall = self._magic_state.autocall_save = 1
593 592
594 593 print "Automatic calling is:",['OFF','Smart','Full'][rc.autocall]
595 594
596 595 def magic_system_verbose(self, parameter_s = ''):
597 596 """Set verbose printing of system calls.
598 597
599 598 If called without an argument, act as a toggle"""
600 599
601 600 if parameter_s:
602 601 val = bool(eval(parameter_s))
603 602 else:
604 603 val = None
605 604
606 605 self.shell.rc_set_toggle('system_verbose',val)
607 606 print "System verbose printing is:",\
608 607 ['OFF','ON'][self.shell.rc.system_verbose]
609 608
610 609
611 610 def magic_page(self, parameter_s=''):
612 611 """Pretty print the object and display it through a pager.
613 612
614 613 %page [options] OBJECT
615 614
616 615 If no object is given, use _ (last output).
617 616
618 617 Options:
619 618
620 619 -r: page str(object), don't pretty-print it."""
621 620
622 621 # After a function contributed by Olivier Aubert, slightly modified.
623 622
624 623 # Process options/args
625 624 opts,args = self.parse_options(parameter_s,'r')
626 625 raw = 'r' in opts
627 626
628 627 oname = args and args or '_'
629 628 info = self._ofind(oname)
630 629 if info['found']:
631 630 txt = (raw and str or pformat)( info['obj'] )
632 631 page(txt)
633 632 else:
634 633 print 'Object `%s` not found' % oname
635 634
636 635 def magic_profile(self, parameter_s=''):
637 636 """Print your currently active IPyhton profile."""
638 637 if self.shell.rc.profile:
639 638 printpl('Current IPython profile: $self.shell.rc.profile.')
640 639 else:
641 640 print 'No profile active.'
642 641
643 642 def magic_pinfo(self, parameter_s='', namespaces=None):
644 643 """Provide detailed information about an object.
645 644
646 645 '%pinfo object' is just a synonym for object? or ?object."""
647 646
648 647 #print 'pinfo par: <%s>' % parameter_s # dbg
649 648
650 649
651 650 # detail_level: 0 -> obj? , 1 -> obj??
652 651 detail_level = 0
653 652 # We need to detect if we got called as 'pinfo pinfo foo', which can
654 653 # happen if the user types 'pinfo foo?' at the cmd line.
655 654 pinfo,qmark1,oname,qmark2 = \
656 655 re.match('(pinfo )?(\?*)(.*?)(\??$)',parameter_s).groups()
657 656 if pinfo or qmark1 or qmark2:
658 657 detail_level = 1
659 658 if "*" in oname:
660 659 self.magic_psearch(oname)
661 660 else:
662 661 self._inspect('pinfo', oname, detail_level=detail_level,
663 662 namespaces=namespaces)
664 663
665 664 def magic_pdef(self, parameter_s='', namespaces=None):
666 665 """Print the definition header for any callable object.
667 666
668 667 If the object is a class, print the constructor information."""
669 668 self._inspect('pdef',parameter_s, namespaces)
670 669
671 670 def magic_pdoc(self, parameter_s='', namespaces=None):
672 671 """Print the docstring for an object.
673 672
674 673 If the given object is a class, it will print both the class and the
675 674 constructor docstrings."""
676 675 self._inspect('pdoc',parameter_s, namespaces)
677 676
678 677 def magic_psource(self, parameter_s='', namespaces=None):
679 678 """Print (or run through pager) the source code for an object."""
680 679 self._inspect('psource',parameter_s, namespaces)
681 680
682 681 def magic_pfile(self, parameter_s=''):
683 682 """Print (or run through pager) the file where an object is defined.
684 683
685 684 The file opens at the line where the object definition begins. IPython
686 685 will honor the environment variable PAGER if set, and otherwise will
687 686 do its best to print the file in a convenient form.
688 687
689 688 If the given argument is not an object currently defined, IPython will
690 689 try to interpret it as a filename (automatically adding a .py extension
691 690 if needed). You can thus use %pfile as a syntax highlighting code
692 691 viewer."""
693 692
694 693 # first interpret argument as an object name
695 694 out = self._inspect('pfile',parameter_s)
696 695 # if not, try the input as a filename
697 696 if out == 'not found':
698 697 try:
699 698 filename = get_py_filename(parameter_s)
700 699 except IOError,msg:
701 700 print msg
702 701 return
703 702 page(self.shell.inspector.format(file(filename).read()))
704 703
705 704 def _inspect(self,meth,oname,namespaces=None,**kw):
706 705 """Generic interface to the inspector system.
707 706
708 707 This function is meant to be called by pdef, pdoc & friends."""
709 708
710 709 #oname = oname.strip()
711 710 #print '1- oname: <%r>' % oname # dbg
712 711 try:
713 712 oname = oname.strip().encode('ascii')
714 713 #print '2- oname: <%r>' % oname # dbg
715 714 except UnicodeEncodeError:
716 715 print 'Python identifiers can only contain ascii characters.'
717 716 return 'not found'
718 717
719 718 info = Struct(self._ofind(oname, namespaces))
720 719
721 720 if info.found:
722 721 try:
723 722 IPython.generics.inspect_object(info.obj)
724 723 return
725 724 except IPython.ipapi.TryNext:
726 725 pass
727 726 # Get the docstring of the class property if it exists.
728 727 path = oname.split('.')
729 728 root = '.'.join(path[:-1])
730 729 if info.parent is not None:
731 730 try:
732 731 target = getattr(info.parent, '__class__')
733 732 # The object belongs to a class instance.
734 733 try:
735 734 target = getattr(target, path[-1])
736 735 # The class defines the object.
737 736 if isinstance(target, property):
738 737 oname = root + '.__class__.' + path[-1]
739 738 info = Struct(self._ofind(oname))
740 739 except AttributeError: pass
741 740 except AttributeError: pass
742 741
743 742 pmethod = getattr(self.shell.inspector,meth)
744 743 formatter = info.ismagic and self.format_screen or None
745 744 if meth == 'pdoc':
746 745 pmethod(info.obj,oname,formatter)
747 746 elif meth == 'pinfo':
748 747 pmethod(info.obj,oname,formatter,info,**kw)
749 748 else:
750 749 pmethod(info.obj,oname)
751 750 else:
752 751 print 'Object `%s` not found.' % oname
753 752 return 'not found' # so callers can take other action
754 753
755 754 def magic_psearch(self, parameter_s=''):
756 755 """Search for object in namespaces by wildcard.
757 756
758 757 %psearch [options] PATTERN [OBJECT TYPE]
759 758
760 759 Note: ? can be used as a synonym for %psearch, at the beginning or at
761 760 the end: both a*? and ?a* are equivalent to '%psearch a*'. Still, the
762 761 rest of the command line must be unchanged (options come first), so
763 762 for example the following forms are equivalent
764 763
765 764 %psearch -i a* function
766 765 -i a* function?
767 766 ?-i a* function
768 767
769 768 Arguments:
770 769
771 770 PATTERN
772 771
773 772 where PATTERN is a string containing * as a wildcard similar to its
774 773 use in a shell. The pattern is matched in all namespaces on the
775 774 search path. By default objects starting with a single _ are not
776 775 matched, many IPython generated objects have a single
777 776 underscore. The default is case insensitive matching. Matching is
778 777 also done on the attributes of objects and not only on the objects
779 778 in a module.
780 779
781 780 [OBJECT TYPE]
782 781
783 782 Is the name of a python type from the types module. The name is
784 783 given in lowercase without the ending type, ex. StringType is
785 784 written string. By adding a type here only objects matching the
786 785 given type are matched. Using all here makes the pattern match all
787 786 types (this is the default).
788 787
789 788 Options:
790 789
791 790 -a: makes the pattern match even objects whose names start with a
792 791 single underscore. These names are normally ommitted from the
793 792 search.
794 793
795 794 -i/-c: make the pattern case insensitive/sensitive. If neither of
796 795 these options is given, the default is read from your ipythonrc
797 796 file. The option name which sets this value is
798 797 'wildcards_case_sensitive'. If this option is not specified in your
799 798 ipythonrc file, IPython's internal default is to do a case sensitive
800 799 search.
801 800
802 801 -e/-s NAMESPACE: exclude/search a given namespace. The pattern you
803 802 specifiy can be searched in any of the following namespaces:
804 803 'builtin', 'user', 'user_global','internal', 'alias', where
805 804 'builtin' and 'user' are the search defaults. Note that you should
806 805 not use quotes when specifying namespaces.
807 806
808 807 'Builtin' contains the python module builtin, 'user' contains all
809 808 user data, 'alias' only contain the shell aliases and no python
810 809 objects, 'internal' contains objects used by IPython. The
811 810 'user_global' namespace is only used by embedded IPython instances,
812 811 and it contains module-level globals. You can add namespaces to the
813 812 search with -s or exclude them with -e (these options can be given
814 813 more than once).
815 814
816 815 Examples:
817 816
818 817 %psearch a* -> objects beginning with an a
819 818 %psearch -e builtin a* -> objects NOT in the builtin space starting in a
820 819 %psearch a* function -> all functions beginning with an a
821 820 %psearch re.e* -> objects beginning with an e in module re
822 821 %psearch r*.e* -> objects that start with e in modules starting in r
823 822 %psearch r*.* string -> all strings in modules beginning with r
824 823
825 824 Case sensitve search:
826 825
827 826 %psearch -c a* list all object beginning with lower case a
828 827
829 828 Show objects beginning with a single _:
830 829
831 830 %psearch -a _* list objects beginning with a single underscore"""
832 831 try:
833 832 parameter_s = parameter_s.encode('ascii')
834 833 except UnicodeEncodeError:
835 834 print 'Python identifiers can only contain ascii characters.'
836 835 return
837 836
838 837 # default namespaces to be searched
839 838 def_search = ['user','builtin']
840 839
841 840 # Process options/args
842 841 opts,args = self.parse_options(parameter_s,'cias:e:',list_all=True)
843 842 opt = opts.get
844 843 shell = self.shell
845 844 psearch = shell.inspector.psearch
846 845
847 846 # select case options
848 847 if opts.has_key('i'):
849 848 ignore_case = True
850 849 elif opts.has_key('c'):
851 850 ignore_case = False
852 851 else:
853 852 ignore_case = not shell.rc.wildcards_case_sensitive
854 853
855 854 # Build list of namespaces to search from user options
856 855 def_search.extend(opt('s',[]))
857 856 ns_exclude = ns_exclude=opt('e',[])
858 857 ns_search = [nm for nm in def_search if nm not in ns_exclude]
859 858
860 859 # Call the actual search
861 860 try:
862 861 psearch(args,shell.ns_table,ns_search,
863 862 show_all=opt('a'),ignore_case=ignore_case)
864 863 except:
865 864 shell.showtraceback()
866 865
867 866 def magic_who_ls(self, parameter_s=''):
868 867 """Return a sorted list of all interactive variables.
869 868
870 869 If arguments are given, only variables of types matching these
871 870 arguments are returned."""
872 871
873 872 user_ns = self.shell.user_ns
874 873 internal_ns = self.shell.internal_ns
875 874 user_config_ns = self.shell.user_config_ns
876 875 out = []
877 876 typelist = parameter_s.split()
878 877
879 878 for i in user_ns:
880 879 if not (i.startswith('_') or i.startswith('_i')) \
881 880 and not (i in internal_ns or i in user_config_ns):
882 881 if typelist:
883 882 if type(user_ns[i]).__name__ in typelist:
884 883 out.append(i)
885 884 else:
886 885 out.append(i)
887 886 out.sort()
888 887 return out
889 888
890 889 def magic_who(self, parameter_s=''):
891 890 """Print all interactive variables, with some minimal formatting.
892 891
893 892 If any arguments are given, only variables whose type matches one of
894 893 these are printed. For example:
895 894
896 895 %who function str
897 896
898 897 will only list functions and strings, excluding all other types of
899 898 variables. To find the proper type names, simply use type(var) at a
900 899 command line to see how python prints type names. For example:
901 900
902 901 In [1]: type('hello')\\
903 902 Out[1]: <type 'str'>
904 903
905 904 indicates that the type name for strings is 'str'.
906 905
907 906 %who always excludes executed names loaded through your configuration
908 907 file and things which are internal to IPython.
909 908
910 909 This is deliberate, as typically you may load many modules and the
911 910 purpose of %who is to show you only what you've manually defined."""
912 911
913 912 varlist = self.magic_who_ls(parameter_s)
914 913 if not varlist:
915 914 if parameter_s:
916 915 print 'No variables match your requested type.'
917 916 else:
918 917 print 'Interactive namespace is empty.'
919 918 return
920 919
921 920 # if we have variables, move on...
922 921 count = 0
923 922 for i in varlist:
924 923 print i+'\t',
925 924 count += 1
926 925 if count > 8:
927 926 count = 0
928 927 print
929 928 print
930 929
931 930 def magic_whos(self, parameter_s=''):
932 931 """Like %who, but gives some extra information about each variable.
933 932
934 933 The same type filtering of %who can be applied here.
935 934
936 935 For all variables, the type is printed. Additionally it prints:
937 936
938 937 - For {},[],(): their length.
939 938
940 939 - For numpy and Numeric arrays, a summary with shape, number of
941 940 elements, typecode and size in memory.
942 941
943 942 - Everything else: a string representation, snipping their middle if
944 943 too long."""
945 944
946 945 varnames = self.magic_who_ls(parameter_s)
947 946 if not varnames:
948 947 if parameter_s:
949 948 print 'No variables match your requested type.'
950 949 else:
951 950 print 'Interactive namespace is empty.'
952 951 return
953 952
954 953 # if we have variables, move on...
955 954
956 955 # for these types, show len() instead of data:
957 956 seq_types = [types.DictType,types.ListType,types.TupleType]
958 957
959 958 # for numpy/Numeric arrays, display summary info
960 959 try:
961 960 import numpy
962 961 except ImportError:
963 962 ndarray_type = None
964 963 else:
965 964 ndarray_type = numpy.ndarray.__name__
966 965 try:
967 966 import Numeric
968 967 except ImportError:
969 968 array_type = None
970 969 else:
971 970 array_type = Numeric.ArrayType.__name__
972 971
973 972 # Find all variable names and types so we can figure out column sizes
974 973 def get_vars(i):
975 974 return self.shell.user_ns[i]
976 975
977 976 # some types are well known and can be shorter
978 977 abbrevs = {'IPython.macro.Macro' : 'Macro'}
979 978 def type_name(v):
980 979 tn = type(v).__name__
981 980 return abbrevs.get(tn,tn)
982 981
983 982 varlist = map(get_vars,varnames)
984 983
985 984 typelist = []
986 985 for vv in varlist:
987 986 tt = type_name(vv)
988 987
989 988 if tt=='instance':
990 989 typelist.append( abbrevs.get(str(vv.__class__),
991 990 str(vv.__class__)))
992 991 else:
993 992 typelist.append(tt)
994 993
995 994 # column labels and # of spaces as separator
996 995 varlabel = 'Variable'
997 996 typelabel = 'Type'
998 997 datalabel = 'Data/Info'
999 998 colsep = 3
1000 999 # variable format strings
1001 1000 vformat = "$vname.ljust(varwidth)$vtype.ljust(typewidth)"
1002 1001 vfmt_short = '$vstr[:25]<...>$vstr[-25:]'
1003 1002 aformat = "%s: %s elems, type `%s`, %s bytes"
1004 1003 # find the size of the columns to format the output nicely
1005 1004 varwidth = max(max(map(len,varnames)), len(varlabel)) + colsep
1006 1005 typewidth = max(max(map(len,typelist)), len(typelabel)) + colsep
1007 1006 # table header
1008 1007 print varlabel.ljust(varwidth) + typelabel.ljust(typewidth) + \
1009 1008 ' '+datalabel+'\n' + '-'*(varwidth+typewidth+len(datalabel)+1)
1010 1009 # and the table itself
1011 1010 kb = 1024
1012 1011 Mb = 1048576 # kb**2
1013 1012 for vname,var,vtype in zip(varnames,varlist,typelist):
1014 1013 print itpl(vformat),
1015 1014 if vtype in seq_types:
1016 1015 print len(var)
1017 1016 elif vtype in [array_type,ndarray_type]:
1018 1017 vshape = str(var.shape).replace(',','').replace(' ','x')[1:-1]
1019 1018 if vtype==ndarray_type:
1020 1019 # numpy
1021 1020 vsize = var.size
1022 1021 vbytes = vsize*var.itemsize
1023 1022 vdtype = var.dtype
1024 1023 else:
1025 1024 # Numeric
1026 1025 vsize = Numeric.size(var)
1027 1026 vbytes = vsize*var.itemsize()
1028 1027 vdtype = var.typecode()
1029 1028
1030 1029 if vbytes < 100000:
1031 1030 print aformat % (vshape,vsize,vdtype,vbytes)
1032 1031 else:
1033 1032 print aformat % (vshape,vsize,vdtype,vbytes),
1034 1033 if vbytes < Mb:
1035 1034 print '(%s kb)' % (vbytes/kb,)
1036 1035 else:
1037 1036 print '(%s Mb)' % (vbytes/Mb,)
1038 1037 else:
1039 1038 try:
1040 1039 vstr = str(var)
1041 1040 except UnicodeEncodeError:
1042 1041 vstr = unicode(var).encode(sys.getdefaultencoding(),
1043 1042 'backslashreplace')
1044 1043 vstr = vstr.replace('\n','\\n')
1045 1044 if len(vstr) < 50:
1046 1045 print vstr
1047 1046 else:
1048 1047 printpl(vfmt_short)
1049 1048
1050 1049 def magic_reset(self, parameter_s=''):
1051 1050 """Resets the namespace by removing all names defined by the user.
1052 1051
1053 1052 Input/Output history are left around in case you need them."""
1054 1053
1055 1054 ans = self.shell.ask_yes_no(
1056 1055 "Once deleted, variables cannot be recovered. Proceed (y/[n])? ")
1057 1056 if not ans:
1058 1057 print 'Nothing done.'
1059 1058 return
1060 1059 user_ns = self.shell.user_ns
1061 1060 for i in self.magic_who_ls():
1062 1061 del(user_ns[i])
1063 1062
1064 1063 # Also flush the private list of module references kept for script
1065 1064 # execution protection
1066 1065 self.shell._user_main_modules[:] = []
1067 1066
1068 1067 def magic_logstart(self,parameter_s=''):
1069 1068 """Start logging anywhere in a session.
1070 1069
1071 1070 %logstart [-o|-r|-t] [log_name [log_mode]]
1072 1071
1073 1072 If no name is given, it defaults to a file named 'ipython_log.py' in your
1074 1073 current directory, in 'rotate' mode (see below).
1075 1074
1076 1075 '%logstart name' saves to file 'name' in 'backup' mode. It saves your
1077 1076 history up to that point and then continues logging.
1078 1077
1079 1078 %logstart takes a second optional parameter: logging mode. This can be one
1080 1079 of (note that the modes are given unquoted):\\
1081 1080 append: well, that says it.\\
1082 1081 backup: rename (if exists) to name~ and start name.\\
1083 1082 global: single logfile in your home dir, appended to.\\
1084 1083 over : overwrite existing log.\\
1085 1084 rotate: create rotating logs name.1~, name.2~, etc.
1086 1085
1087 1086 Options:
1088 1087
1089 1088 -o: log also IPython's output. In this mode, all commands which
1090 1089 generate an Out[NN] prompt are recorded to the logfile, right after
1091 1090 their corresponding input line. The output lines are always
1092 1091 prepended with a '#[Out]# ' marker, so that the log remains valid
1093 1092 Python code.
1094 1093
1095 1094 Since this marker is always the same, filtering only the output from
1096 1095 a log is very easy, using for example a simple awk call:
1097 1096
1098 1097 awk -F'#\\[Out\\]# ' '{if($2) {print $2}}' ipython_log.py
1099 1098
1100 1099 -r: log 'raw' input. Normally, IPython's logs contain the processed
1101 1100 input, so that user lines are logged in their final form, converted
1102 1101 into valid Python. For example, %Exit is logged as
1103 1102 '_ip.magic("Exit"). If the -r flag is given, all input is logged
1104 1103 exactly as typed, with no transformations applied.
1105 1104
1106 1105 -t: put timestamps before each input line logged (these are put in
1107 1106 comments)."""
1108 1107
1109 1108 opts,par = self.parse_options(parameter_s,'ort')
1110 1109 log_output = 'o' in opts
1111 1110 log_raw_input = 'r' in opts
1112 1111 timestamp = 't' in opts
1113 1112
1114 1113 rc = self.shell.rc
1115 1114 logger = self.shell.logger
1116 1115
1117 1116 # if no args are given, the defaults set in the logger constructor by
1118 1117 # ipytohn remain valid
1119 1118 if par:
1120 1119 try:
1121 1120 logfname,logmode = par.split()
1122 1121 except:
1123 1122 logfname = par
1124 1123 logmode = 'backup'
1125 1124 else:
1126 1125 logfname = logger.logfname
1127 1126 logmode = logger.logmode
1128 1127 # put logfname into rc struct as if it had been called on the command
1129 1128 # line, so it ends up saved in the log header Save it in case we need
1130 1129 # to restore it...
1131 1130 old_logfile = rc.opts.get('logfile','')
1132 1131 if logfname:
1133 1132 logfname = os.path.expanduser(logfname)
1134 1133 rc.opts.logfile = logfname
1135 1134 loghead = self.shell.loghead_tpl % (rc.opts,rc.args)
1136 1135 try:
1137 1136 started = logger.logstart(logfname,loghead,logmode,
1138 1137 log_output,timestamp,log_raw_input)
1139 1138 except:
1140 1139 rc.opts.logfile = old_logfile
1141 1140 warn("Couldn't start log: %s" % sys.exc_info()[1])
1142 1141 else:
1143 1142 # log input history up to this point, optionally interleaving
1144 1143 # output if requested
1145 1144
1146 1145 if timestamp:
1147 1146 # disable timestamping for the previous history, since we've
1148 1147 # lost those already (no time machine here).
1149 1148 logger.timestamp = False
1150 1149
1151 1150 if log_raw_input:
1152 1151 input_hist = self.shell.input_hist_raw
1153 1152 else:
1154 1153 input_hist = self.shell.input_hist
1155 1154
1156 1155 if log_output:
1157 1156 log_write = logger.log_write
1158 1157 output_hist = self.shell.output_hist
1159 1158 for n in range(1,len(input_hist)-1):
1160 1159 log_write(input_hist[n].rstrip())
1161 1160 if n in output_hist:
1162 1161 log_write(repr(output_hist[n]),'output')
1163 1162 else:
1164 1163 logger.log_write(input_hist[1:])
1165 1164 if timestamp:
1166 1165 # re-enable timestamping
1167 1166 logger.timestamp = True
1168 1167
1169 1168 print ('Activating auto-logging. '
1170 1169 'Current session state plus future input saved.')
1171 1170 logger.logstate()
1172 1171
1173 1172 def magic_logstop(self,parameter_s=''):
1174 1173 """Fully stop logging and close log file.
1175 1174
1176 1175 In order to start logging again, a new %logstart call needs to be made,
1177 1176 possibly (though not necessarily) with a new filename, mode and other
1178 1177 options."""
1179 1178 self.logger.logstop()
1180 1179
1181 1180 def magic_logoff(self,parameter_s=''):
1182 1181 """Temporarily stop logging.
1183 1182
1184 1183 You must have previously started logging."""
1185 1184 self.shell.logger.switch_log(0)
1186 1185
1187 1186 def magic_logon(self,parameter_s=''):
1188 1187 """Restart logging.
1189 1188
1190 1189 This function is for restarting logging which you've temporarily
1191 1190 stopped with %logoff. For starting logging for the first time, you
1192 1191 must use the %logstart function, which allows you to specify an
1193 1192 optional log filename."""
1194 1193
1195 1194 self.shell.logger.switch_log(1)
1196 1195
1197 1196 def magic_logstate(self,parameter_s=''):
1198 1197 """Print the status of the logging system."""
1199 1198
1200 1199 self.shell.logger.logstate()
1201 1200
1202 1201 def magic_pdb(self, parameter_s=''):
1203 1202 """Control the automatic calling of the pdb interactive debugger.
1204 1203
1205 1204 Call as '%pdb on', '%pdb 1', '%pdb off' or '%pdb 0'. If called without
1206 1205 argument it works as a toggle.
1207 1206
1208 1207 When an exception is triggered, IPython can optionally call the
1209 1208 interactive pdb debugger after the traceback printout. %pdb toggles
1210 1209 this feature on and off.
1211 1210
1212 1211 The initial state of this feature is set in your ipythonrc
1213 1212 configuration file (the variable is called 'pdb').
1214 1213
1215 1214 If you want to just activate the debugger AFTER an exception has fired,
1216 1215 without having to type '%pdb on' and rerunning your code, you can use
1217 1216 the %debug magic."""
1218 1217
1219 1218 par = parameter_s.strip().lower()
1220 1219
1221 1220 if par:
1222 1221 try:
1223 1222 new_pdb = {'off':0,'0':0,'on':1,'1':1}[par]
1224 1223 except KeyError:
1225 1224 print ('Incorrect argument. Use on/1, off/0, '
1226 1225 'or nothing for a toggle.')
1227 1226 return
1228 1227 else:
1229 1228 # toggle
1230 1229 new_pdb = not self.shell.call_pdb
1231 1230
1232 1231 # set on the shell
1233 1232 self.shell.call_pdb = new_pdb
1234 1233 print 'Automatic pdb calling has been turned',on_off(new_pdb)
1235 1234
1236 1235 def magic_debug(self, parameter_s=''):
1237 1236 """Activate the interactive debugger in post-mortem mode.
1238 1237
1239 1238 If an exception has just occurred, this lets you inspect its stack
1240 1239 frames interactively. Note that this will always work only on the last
1241 1240 traceback that occurred, so you must call this quickly after an
1242 1241 exception that you wish to inspect has fired, because if another one
1243 1242 occurs, it clobbers the previous one.
1244 1243
1245 1244 If you want IPython to automatically do this on every exception, see
1246 1245 the %pdb magic for more details.
1247 1246 """
1248 1247
1249 1248 self.shell.debugger(force=True)
1250 1249
1251 1250 @testdec.skip_doctest
1252 1251 def magic_prun(self, parameter_s ='',user_mode=1,
1253 1252 opts=None,arg_lst=None,prog_ns=None):
1254 1253
1255 1254 """Run a statement through the python code profiler.
1256 1255
1257 1256 Usage:
1258 1257 %prun [options] statement
1259 1258
1260 1259 The given statement (which doesn't require quote marks) is run via the
1261 1260 python profiler in a manner similar to the profile.run() function.
1262 1261 Namespaces are internally managed to work correctly; profile.run
1263 1262 cannot be used in IPython because it makes certain assumptions about
1264 1263 namespaces which do not hold under IPython.
1265 1264
1266 1265 Options:
1267 1266
1268 1267 -l <limit>: you can place restrictions on what or how much of the
1269 1268 profile gets printed. The limit value can be:
1270 1269
1271 1270 * A string: only information for function names containing this string
1272 1271 is printed.
1273 1272
1274 1273 * An integer: only these many lines are printed.
1275 1274
1276 1275 * A float (between 0 and 1): this fraction of the report is printed
1277 1276 (for example, use a limit of 0.4 to see the topmost 40% only).
1278 1277
1279 1278 You can combine several limits with repeated use of the option. For
1280 1279 example, '-l __init__ -l 5' will print only the topmost 5 lines of
1281 1280 information about class constructors.
1282 1281
1283 1282 -r: return the pstats.Stats object generated by the profiling. This
1284 1283 object has all the information about the profile in it, and you can
1285 1284 later use it for further analysis or in other functions.
1286 1285
1287 1286 -s <key>: sort profile by given key. You can provide more than one key
1288 1287 by using the option several times: '-s key1 -s key2 -s key3...'. The
1289 1288 default sorting key is 'time'.
1290 1289
1291 1290 The following is copied verbatim from the profile documentation
1292 1291 referenced below:
1293 1292
1294 1293 When more than one key is provided, additional keys are used as
1295 1294 secondary criteria when the there is equality in all keys selected
1296 1295 before them.
1297 1296
1298 1297 Abbreviations can be used for any key names, as long as the
1299 1298 abbreviation is unambiguous. The following are the keys currently
1300 1299 defined:
1301 1300
1302 1301 Valid Arg Meaning
1303 1302 "calls" call count
1304 1303 "cumulative" cumulative time
1305 1304 "file" file name
1306 1305 "module" file name
1307 1306 "pcalls" primitive call count
1308 1307 "line" line number
1309 1308 "name" function name
1310 1309 "nfl" name/file/line
1311 1310 "stdname" standard name
1312 1311 "time" internal time
1313 1312
1314 1313 Note that all sorts on statistics are in descending order (placing
1315 1314 most time consuming items first), where as name, file, and line number
1316 1315 searches are in ascending order (i.e., alphabetical). The subtle
1317 1316 distinction between "nfl" and "stdname" is that the standard name is a
1318 1317 sort of the name as printed, which means that the embedded line
1319 1318 numbers get compared in an odd way. For example, lines 3, 20, and 40
1320 1319 would (if the file names were the same) appear in the string order
1321 1320 "20" "3" and "40". In contrast, "nfl" does a numeric compare of the
1322 1321 line numbers. In fact, sort_stats("nfl") is the same as
1323 1322 sort_stats("name", "file", "line").
1324 1323
1325 1324 -T <filename>: save profile results as shown on screen to a text
1326 1325 file. The profile is still shown on screen.
1327 1326
1328 1327 -D <filename>: save (via dump_stats) profile statistics to given
1329 1328 filename. This data is in a format understod by the pstats module, and
1330 1329 is generated by a call to the dump_stats() method of profile
1331 1330 objects. The profile is still shown on screen.
1332 1331
1333 1332 If you want to run complete programs under the profiler's control, use
1334 1333 '%run -p [prof_opts] filename.py [args to program]' where prof_opts
1335 1334 contains profiler specific options as described here.
1336 1335
1337 1336 You can read the complete documentation for the profile module with::
1338 1337
1339 1338 In [1]: import profile; profile.help()
1340 1339 """
1341 1340
1342 1341 opts_def = Struct(D=[''],l=[],s=['time'],T=[''])
1343 1342 # protect user quote marks
1344 1343 parameter_s = parameter_s.replace('"',r'\"').replace("'",r"\'")
1345 1344
1346 1345 if user_mode: # regular user call
1347 1346 opts,arg_str = self.parse_options(parameter_s,'D:l:rs:T:',
1348 1347 list_all=1)
1349 1348 namespace = self.shell.user_ns
1350 1349 else: # called to run a program by %run -p
1351 1350 try:
1352 1351 filename = get_py_filename(arg_lst[0])
1353 1352 except IOError,msg:
1354 1353 error(msg)
1355 1354 return
1356 1355
1357 1356 arg_str = 'execfile(filename,prog_ns)'
1358 1357 namespace = locals()
1359 1358
1360 1359 opts.merge(opts_def)
1361 1360
1362 1361 prof = profile.Profile()
1363 1362 try:
1364 1363 prof = prof.runctx(arg_str,namespace,namespace)
1365 1364 sys_exit = ''
1366 1365 except SystemExit:
1367 1366 sys_exit = """*** SystemExit exception caught in code being profiled."""
1368 1367
1369 1368 stats = pstats.Stats(prof).strip_dirs().sort_stats(*opts.s)
1370 1369
1371 1370 lims = opts.l
1372 1371 if lims:
1373 1372 lims = [] # rebuild lims with ints/floats/strings
1374 1373 for lim in opts.l:
1375 1374 try:
1376 1375 lims.append(int(lim))
1377 1376 except ValueError:
1378 1377 try:
1379 1378 lims.append(float(lim))
1380 1379 except ValueError:
1381 1380 lims.append(lim)
1382 1381
1383 1382 # Trap output.
1384 1383 stdout_trap = StringIO()
1385 1384
1386 1385 if hasattr(stats,'stream'):
1387 1386 # In newer versions of python, the stats object has a 'stream'
1388 1387 # attribute to write into.
1389 1388 stats.stream = stdout_trap
1390 1389 stats.print_stats(*lims)
1391 1390 else:
1392 1391 # For older versions, we manually redirect stdout during printing
1393 1392 sys_stdout = sys.stdout
1394 1393 try:
1395 1394 sys.stdout = stdout_trap
1396 1395 stats.print_stats(*lims)
1397 1396 finally:
1398 1397 sys.stdout = sys_stdout
1399 1398
1400 1399 output = stdout_trap.getvalue()
1401 1400 output = output.rstrip()
1402 1401
1403 1402 page(output,screen_lines=self.shell.rc.screen_length)
1404 1403 print sys_exit,
1405 1404
1406 1405 dump_file = opts.D[0]
1407 1406 text_file = opts.T[0]
1408 1407 if dump_file:
1409 1408 prof.dump_stats(dump_file)
1410 1409 print '\n*** Profile stats marshalled to file',\
1411 1410 `dump_file`+'.',sys_exit
1412 1411 if text_file:
1413 1412 pfile = file(text_file,'w')
1414 1413 pfile.write(output)
1415 1414 pfile.close()
1416 1415 print '\n*** Profile printout saved to text file',\
1417 1416 `text_file`+'.',sys_exit
1418 1417
1419 1418 if opts.has_key('r'):
1420 1419 return stats
1421 1420 else:
1422 1421 return None
1423 1422
1424 1423 @testdec.skip_doctest
1425 1424 def magic_run(self, parameter_s ='',runner=None,
1426 1425 file_finder=get_py_filename):
1427 1426 """Run the named file inside IPython as a program.
1428 1427
1429 1428 Usage:\\
1430 1429 %run [-n -i -t [-N<N>] -d [-b<N>] -p [profile options]] file [args]
1431 1430
1432 1431 Parameters after the filename are passed as command-line arguments to
1433 1432 the program (put in sys.argv). Then, control returns to IPython's
1434 1433 prompt.
1435 1434
1436 1435 This is similar to running at a system prompt:\\
1437 1436 $ python file args\\
1438 1437 but with the advantage of giving you IPython's tracebacks, and of
1439 1438 loading all variables into your interactive namespace for further use
1440 1439 (unless -p is used, see below).
1441 1440
1442 1441 The file is executed in a namespace initially consisting only of
1443 1442 __name__=='__main__' and sys.argv constructed as indicated. It thus
1444 1443 sees its environment as if it were being run as a stand-alone program
1445 1444 (except for sharing global objects such as previously imported
1446 1445 modules). But after execution, the IPython interactive namespace gets
1447 1446 updated with all variables defined in the program (except for __name__
1448 1447 and sys.argv). This allows for very convenient loading of code for
1449 1448 interactive work, while giving each program a 'clean sheet' to run in.
1450 1449
1451 1450 Options:
1452 1451
1453 1452 -n: __name__ is NOT set to '__main__', but to the running file's name
1454 1453 without extension (as python does under import). This allows running
1455 1454 scripts and reloading the definitions in them without calling code
1456 1455 protected by an ' if __name__ == "__main__" ' clause.
1457 1456
1458 1457 -i: run the file in IPython's namespace instead of an empty one. This
1459 1458 is useful if you are experimenting with code written in a text editor
1460 1459 which depends on variables defined interactively.
1461 1460
1462 1461 -e: ignore sys.exit() calls or SystemExit exceptions in the script
1463 1462 being run. This is particularly useful if IPython is being used to
1464 1463 run unittests, which always exit with a sys.exit() call. In such
1465 1464 cases you are interested in the output of the test results, not in
1466 1465 seeing a traceback of the unittest module.
1467 1466
1468 1467 -t: print timing information at the end of the run. IPython will give
1469 1468 you an estimated CPU time consumption for your script, which under
1470 1469 Unix uses the resource module to avoid the wraparound problems of
1471 1470 time.clock(). Under Unix, an estimate of time spent on system tasks
1472 1471 is also given (for Windows platforms this is reported as 0.0).
1473 1472
1474 1473 If -t is given, an additional -N<N> option can be given, where <N>
1475 1474 must be an integer indicating how many times you want the script to
1476 1475 run. The final timing report will include total and per run results.
1477 1476
1478 1477 For example (testing the script uniq_stable.py):
1479 1478
1480 1479 In [1]: run -t uniq_stable
1481 1480
1482 1481 IPython CPU timings (estimated):\\
1483 1482 User : 0.19597 s.\\
1484 1483 System: 0.0 s.\\
1485 1484
1486 1485 In [2]: run -t -N5 uniq_stable
1487 1486
1488 1487 IPython CPU timings (estimated):\\
1489 1488 Total runs performed: 5\\
1490 1489 Times : Total Per run\\
1491 1490 User : 0.910862 s, 0.1821724 s.\\
1492 1491 System: 0.0 s, 0.0 s.
1493 1492
1494 1493 -d: run your program under the control of pdb, the Python debugger.
1495 1494 This allows you to execute your program step by step, watch variables,
1496 1495 etc. Internally, what IPython does is similar to calling:
1497 1496
1498 1497 pdb.run('execfile("YOURFILENAME")')
1499 1498
1500 1499 with a breakpoint set on line 1 of your file. You can change the line
1501 1500 number for this automatic breakpoint to be <N> by using the -bN option
1502 1501 (where N must be an integer). For example:
1503 1502
1504 1503 %run -d -b40 myscript
1505 1504
1506 1505 will set the first breakpoint at line 40 in myscript.py. Note that
1507 1506 the first breakpoint must be set on a line which actually does
1508 1507 something (not a comment or docstring) for it to stop execution.
1509 1508
1510 1509 When the pdb debugger starts, you will see a (Pdb) prompt. You must
1511 1510 first enter 'c' (without qoutes) to start execution up to the first
1512 1511 breakpoint.
1513 1512
1514 1513 Entering 'help' gives information about the use of the debugger. You
1515 1514 can easily see pdb's full documentation with "import pdb;pdb.help()"
1516 1515 at a prompt.
1517 1516
1518 1517 -p: run program under the control of the Python profiler module (which
1519 1518 prints a detailed report of execution times, function calls, etc).
1520 1519
1521 1520 You can pass other options after -p which affect the behavior of the
1522 1521 profiler itself. See the docs for %prun for details.
1523 1522
1524 1523 In this mode, the program's variables do NOT propagate back to the
1525 1524 IPython interactive namespace (because they remain in the namespace
1526 1525 where the profiler executes them).
1527 1526
1528 1527 Internally this triggers a call to %prun, see its documentation for
1529 1528 details on the options available specifically for profiling.
1530 1529
1531 1530 There is one special usage for which the text above doesn't apply:
1532 1531 if the filename ends with .ipy, the file is run as ipython script,
1533 1532 just as if the commands were written on IPython prompt.
1534 1533 """
1535 1534
1536 1535 # get arguments and set sys.argv for program to be run.
1537 1536 opts,arg_lst = self.parse_options(parameter_s,'nidtN:b:pD:l:rs:T:e',
1538 1537 mode='list',list_all=1)
1539 1538
1540 1539 try:
1541 1540 filename = file_finder(arg_lst[0])
1542 1541 except IndexError:
1543 1542 warn('you must provide at least a filename.')
1544 1543 print '\n%run:\n',OInspect.getdoc(self.magic_run)
1545 1544 return
1546 1545 except IOError,msg:
1547 1546 error(msg)
1548 1547 return
1549 1548
1550 1549 if filename.lower().endswith('.ipy'):
1551 1550 self.api.runlines(open(filename).read())
1552 1551 return
1553 1552
1554 1553 # Control the response to exit() calls made by the script being run
1555 1554 exit_ignore = opts.has_key('e')
1556 1555
1557 1556 # Make sure that the running script gets a proper sys.argv as if it
1558 1557 # were run from a system shell.
1559 1558 save_argv = sys.argv # save it for later restoring
1560 1559 sys.argv = [filename]+ arg_lst[1:] # put in the proper filename
1561 1560
1562 1561 if opts.has_key('i'):
1563 1562 # Run in user's interactive namespace
1564 1563 prog_ns = self.shell.user_ns
1565 1564 __name__save = self.shell.user_ns['__name__']
1566 1565 prog_ns['__name__'] = '__main__'
1567 1566 main_mod = FakeModule(prog_ns)
1568 1567 else:
1569 1568 # Run in a fresh, empty namespace
1570 1569 if opts.has_key('n'):
1571 1570 name = os.path.splitext(os.path.basename(filename))[0]
1572 1571 else:
1573 1572 name = '__main__'
1574 1573 main_mod = FakeModule()
1575 1574 prog_ns = main_mod.__dict__
1576 1575 prog_ns['__name__'] = name
1577 1576
1578 1577 # The shell MUST hold a reference to main_mod so after %run exits,
1579 1578 # the python deletion mechanism doesn't zero it out (leaving
1580 1579 # dangling references)
1581 1580
1582 1581 # XXX - the note above was written without further detail, but this
1583 1582 # code actually causes problems. By holding references to the
1584 1583 # namespace where every script is executed, we effectively disable
1585 1584 # just about all possible variable cleanup. In particular,
1586 1585 # generator expressions and other variables that point to open
1587 1586 # files are kept alive, and as a user session lives on, it may run
1588 1587 # out of available file descriptors. Such a bug has already been
1589 1588 # reported by JD Hunter. I'm disabling this for now, but we need
1590 1589 # to clarify exactly (and add tests) what from main_mod needs to be
1591 1590 # kept alive and what is save to remove... In fact, see note
1592 1591 # below, where we append main_mod to sys.modules and then delete it
1593 1592 # again. The final cleanup is rendered moot by this reference kept
1594 1593 # in _user_main_modules(), so we really need to look into this.
1595 1594
1596 1595 self.shell._user_main_modules.append(main_mod)
1597 1596
1598 1597 # /XXX
1599 1598
1600 1599 # Since '%run foo' emulates 'python foo.py' at the cmd line, we must
1601 1600 # set the __file__ global in the script's namespace
1602 1601 prog_ns['__file__'] = filename
1603 1602
1604 1603 # pickle fix. See iplib for an explanation. But we need to make sure
1605 1604 # that, if we overwrite __main__, we replace it at the end
1606 1605 main_mod_name = prog_ns['__name__']
1607 1606
1608 1607 if main_mod_name == '__main__':
1609 1608 restore_main = sys.modules['__main__']
1610 1609 else:
1611 1610 restore_main = False
1612 1611
1613 1612 # This needs to be undone at the end to prevent holding references to
1614 1613 # every single object ever created.
1615 1614 sys.modules[main_mod_name] = main_mod
1616 1615
1617 1616 stats = None
1618 1617 try:
1619 1618 self.shell.savehist()
1620 1619
1621 1620 if opts.has_key('p'):
1622 1621 stats = self.magic_prun('',0,opts,arg_lst,prog_ns)
1623 1622 else:
1624 1623 if opts.has_key('d'):
1625 1624 deb = Debugger.Pdb(self.shell.rc.colors)
1626 1625 # reset Breakpoint state, which is moronically kept
1627 1626 # in a class
1628 1627 bdb.Breakpoint.next = 1
1629 1628 bdb.Breakpoint.bplist = {}
1630 1629 bdb.Breakpoint.bpbynumber = [None]
1631 1630 # Set an initial breakpoint to stop execution
1632 1631 maxtries = 10
1633 1632 bp = int(opts.get('b',[1])[0])
1634 1633 checkline = deb.checkline(filename,bp)
1635 1634 if not checkline:
1636 1635 for bp in range(bp+1,bp+maxtries+1):
1637 1636 if deb.checkline(filename,bp):
1638 1637 break
1639 1638 else:
1640 1639 msg = ("\nI failed to find a valid line to set "
1641 1640 "a breakpoint\n"
1642 1641 "after trying up to line: %s.\n"
1643 1642 "Please set a valid breakpoint manually "
1644 1643 "with the -b option." % bp)
1645 1644 error(msg)
1646 1645 return
1647 1646 # if we find a good linenumber, set the breakpoint
1648 1647 deb.do_break('%s:%s' % (filename,bp))
1649 1648 # Start file run
1650 1649 print "NOTE: Enter 'c' at the",
1651 1650 print "%s prompt to start your script." % deb.prompt
1652 1651 try:
1653 1652 deb.run('execfile("%s")' % filename,prog_ns)
1654 1653
1655 1654 except:
1656 1655 etype, value, tb = sys.exc_info()
1657 1656 # Skip three frames in the traceback: the %run one,
1658 1657 # one inside bdb.py, and the command-line typed by the
1659 1658 # user (run by exec in pdb itself).
1660 1659 self.shell.InteractiveTB(etype,value,tb,tb_offset=3)
1661 1660 else:
1662 1661 if runner is None:
1663 1662 runner = self.shell.safe_execfile
1664 1663 if opts.has_key('t'):
1665 1664 # timed execution
1666 1665 try:
1667 1666 nruns = int(opts['N'][0])
1668 1667 if nruns < 1:
1669 1668 error('Number of runs must be >=1')
1670 1669 return
1671 1670 except (KeyError):
1672 1671 nruns = 1
1673 1672 if nruns == 1:
1674 1673 t0 = clock2()
1675 1674 runner(filename,prog_ns,prog_ns,
1676 1675 exit_ignore=exit_ignore)
1677 1676 t1 = clock2()
1678 1677 t_usr = t1[0]-t0[0]
1679 1678 t_sys = t1[1]-t1[1]
1680 1679 print "\nIPython CPU timings (estimated):"
1681 1680 print " User : %10s s." % t_usr
1682 1681 print " System: %10s s." % t_sys
1683 1682 else:
1684 1683 runs = range(nruns)
1685 1684 t0 = clock2()
1686 1685 for nr in runs:
1687 1686 runner(filename,prog_ns,prog_ns,
1688 1687 exit_ignore=exit_ignore)
1689 1688 t1 = clock2()
1690 1689 t_usr = t1[0]-t0[0]
1691 1690 t_sys = t1[1]-t1[1]
1692 1691 print "\nIPython CPU timings (estimated):"
1693 1692 print "Total runs performed:",nruns
1694 1693 print " Times : %10s %10s" % ('Total','Per run')
1695 1694 print " User : %10s s, %10s s." % (t_usr,t_usr/nruns)
1696 1695 print " System: %10s s, %10s s." % (t_sys,t_sys/nruns)
1697 1696
1698 1697 else:
1699 1698 # regular execution
1700 1699 runner(filename,prog_ns,prog_ns,exit_ignore=exit_ignore)
1701 1700 if opts.has_key('i'):
1702 1701 self.shell.user_ns['__name__'] = __name__save
1703 1702 else:
1704 1703 # update IPython interactive namespace
1705 1704 del prog_ns['__name__']
1706 1705 self.shell.user_ns.update(prog_ns)
1707 1706 finally:
1708 1707 # Ensure key global structures are restored
1709 1708 sys.argv = save_argv
1710 1709 if restore_main:
1711 1710 sys.modules['__main__'] = restore_main
1712 1711 else:
1713 1712 # Remove from sys.modules the reference to main_mod we'd
1714 1713 # added. Otherwise it will trap references to objects
1715 1714 # contained therein.
1716 1715 del sys.modules[main_mod_name]
1717 1716 self.shell.reloadhist()
1718 1717
1719 1718 return stats
1720 1719
1721 1720 def magic_runlog(self, parameter_s =''):
1722 1721 """Run files as logs.
1723 1722
1724 1723 Usage:\\
1725 1724 %runlog file1 file2 ...
1726 1725
1727 1726 Run the named files (treating them as log files) in sequence inside
1728 1727 the interpreter, and return to the prompt. This is much slower than
1729 1728 %run because each line is executed in a try/except block, but it
1730 1729 allows running files with syntax errors in them.
1731 1730
1732 1731 Normally IPython will guess when a file is one of its own logfiles, so
1733 1732 you can typically use %run even for logs. This shorthand allows you to
1734 1733 force any file to be treated as a log file."""
1735 1734
1736 1735 for f in parameter_s.split():
1737 1736 self.shell.safe_execfile(f,self.shell.user_ns,
1738 1737 self.shell.user_ns,islog=1)
1739 1738
1740 1739 @testdec.skip_doctest
1741 1740 def magic_timeit(self, parameter_s =''):
1742 1741 """Time execution of a Python statement or expression
1743 1742
1744 1743 Usage:\\
1745 1744 %timeit [-n<N> -r<R> [-t|-c]] statement
1746 1745
1747 1746 Time execution of a Python statement or expression using the timeit
1748 1747 module.
1749 1748
1750 1749 Options:
1751 1750 -n<N>: execute the given statement <N> times in a loop. If this value
1752 1751 is not given, a fitting value is chosen.
1753 1752
1754 1753 -r<R>: repeat the loop iteration <R> times and take the best result.
1755 1754 Default: 3
1756 1755
1757 1756 -t: use time.time to measure the time, which is the default on Unix.
1758 1757 This function measures wall time.
1759 1758
1760 1759 -c: use time.clock to measure the time, which is the default on
1761 1760 Windows and measures wall time. On Unix, resource.getrusage is used
1762 1761 instead and returns the CPU user time.
1763 1762
1764 1763 -p<P>: use a precision of <P> digits to display the timing result.
1765 1764 Default: 3
1766 1765
1767 1766
1768 1767 Examples:
1769 1768
1770 1769 In [1]: %timeit pass
1771 1770 10000000 loops, best of 3: 53.3 ns per loop
1772 1771
1773 1772 In [2]: u = None
1774 1773
1775 1774 In [3]: %timeit u is None
1776 1775 10000000 loops, best of 3: 184 ns per loop
1777 1776
1778 1777 In [4]: %timeit -r 4 u == None
1779 1778 1000000 loops, best of 4: 242 ns per loop
1780 1779
1781 1780 In [5]: import time
1782 1781
1783 1782 In [6]: %timeit -n1 time.sleep(2)
1784 1783 1 loops, best of 3: 2 s per loop
1785 1784
1786 1785
1787 1786 The times reported by %timeit will be slightly higher than those
1788 1787 reported by the timeit.py script when variables are accessed. This is
1789 1788 due to the fact that %timeit executes the statement in the namespace
1790 1789 of the shell, compared with timeit.py, which uses a single setup
1791 1790 statement to import function or create variables. Generally, the bias
1792 1791 does not matter as long as results from timeit.py are not mixed with
1793 1792 those from %timeit."""
1794 1793
1795 1794 import timeit
1796 1795 import math
1797 1796
1798 1797 units = [u"s", u"ms", u"\xb5s", u"ns"]
1799 1798 scaling = [1, 1e3, 1e6, 1e9]
1800 1799
1801 1800 opts, stmt = self.parse_options(parameter_s,'n:r:tcp:',
1802 1801 posix=False)
1803 1802 if stmt == "":
1804 1803 return
1805 1804 timefunc = timeit.default_timer
1806 1805 number = int(getattr(opts, "n", 0))
1807 1806 repeat = int(getattr(opts, "r", timeit.default_repeat))
1808 1807 precision = int(getattr(opts, "p", 3))
1809 1808 if hasattr(opts, "t"):
1810 1809 timefunc = time.time
1811 1810 if hasattr(opts, "c"):
1812 1811 timefunc = clock
1813 1812
1814 1813 timer = timeit.Timer(timer=timefunc)
1815 1814 # this code has tight coupling to the inner workings of timeit.Timer,
1816 1815 # but is there a better way to achieve that the code stmt has access
1817 1816 # to the shell namespace?
1818 1817
1819 1818 src = timeit.template % {'stmt': timeit.reindent(stmt, 8),
1820 1819 'setup': "pass"}
1821 1820 # Track compilation time so it can be reported if too long
1822 1821 # Minimum time above which compilation time will be reported
1823 1822 tc_min = 0.1
1824 1823
1825 1824 t0 = clock()
1826 1825 code = compile(src, "<magic-timeit>", "exec")
1827 1826 tc = clock()-t0
1828 1827
1829 1828 ns = {}
1830 1829 exec code in self.shell.user_ns, ns
1831 1830 timer.inner = ns["inner"]
1832 1831
1833 1832 if number == 0:
1834 1833 # determine number so that 0.2 <= total time < 2.0
1835 1834 number = 1
1836 1835 for i in range(1, 10):
1837 1836 number *= 10
1838 1837 if timer.timeit(number) >= 0.2:
1839 1838 break
1840 1839
1841 1840 best = min(timer.repeat(repeat, number)) / number
1842 1841
1843 1842 if best > 0.0:
1844 1843 order = min(-int(math.floor(math.log10(best)) // 3), 3)
1845 1844 else:
1846 1845 order = 3
1847 1846 print u"%d loops, best of %d: %.*g %s per loop" % (number, repeat,
1848 1847 precision,
1849 1848 best * scaling[order],
1850 1849 units[order])
1851 1850 if tc > tc_min:
1852 1851 print "Compiler time: %.2f s" % tc
1853 1852
1854 1853 @testdec.skip_doctest
1855 1854 def magic_time(self,parameter_s = ''):
1856 1855 """Time execution of a Python statement or expression.
1857 1856
1858 1857 The CPU and wall clock times are printed, and the value of the
1859 1858 expression (if any) is returned. Note that under Win32, system time
1860 1859 is always reported as 0, since it can not be measured.
1861 1860
1862 1861 This function provides very basic timing functionality. In Python
1863 1862 2.3, the timeit module offers more control and sophistication, so this
1864 1863 could be rewritten to use it (patches welcome).
1865 1864
1866 1865 Some examples:
1867 1866
1868 1867 In [1]: time 2**128
1869 1868 CPU times: user 0.00 s, sys: 0.00 s, total: 0.00 s
1870 1869 Wall time: 0.00
1871 1870 Out[1]: 340282366920938463463374607431768211456L
1872 1871
1873 1872 In [2]: n = 1000000
1874 1873
1875 1874 In [3]: time sum(range(n))
1876 1875 CPU times: user 1.20 s, sys: 0.05 s, total: 1.25 s
1877 1876 Wall time: 1.37
1878 1877 Out[3]: 499999500000L
1879 1878
1880 1879 In [4]: time print 'hello world'
1881 1880 hello world
1882 1881 CPU times: user 0.00 s, sys: 0.00 s, total: 0.00 s
1883 1882 Wall time: 0.00
1884 1883
1885 1884 Note that the time needed by Python to compile the given expression
1886 1885 will be reported if it is more than 0.1s. In this example, the
1887 1886 actual exponentiation is done by Python at compilation time, so while
1888 1887 the expression can take a noticeable amount of time to compute, that
1889 1888 time is purely due to the compilation:
1890 1889
1891 1890 In [5]: time 3**9999;
1892 1891 CPU times: user 0.00 s, sys: 0.00 s, total: 0.00 s
1893 1892 Wall time: 0.00 s
1894 1893
1895 1894 In [6]: time 3**999999;
1896 1895 CPU times: user 0.00 s, sys: 0.00 s, total: 0.00 s
1897 1896 Wall time: 0.00 s
1898 1897 Compiler : 0.78 s
1899 1898 """
1900 1899
1901 1900 # fail immediately if the given expression can't be compiled
1902 1901
1903 1902 expr = self.shell.prefilter(parameter_s,False)
1904 1903
1905 1904 # Minimum time above which compilation time will be reported
1906 1905 tc_min = 0.1
1907 1906
1908 1907 try:
1909 1908 mode = 'eval'
1910 1909 t0 = clock()
1911 1910 code = compile(expr,'<timed eval>',mode)
1912 1911 tc = clock()-t0
1913 1912 except SyntaxError:
1914 1913 mode = 'exec'
1915 1914 t0 = clock()
1916 1915 code = compile(expr,'<timed exec>',mode)
1917 1916 tc = clock()-t0
1918 1917 # skew measurement as little as possible
1919 1918 glob = self.shell.user_ns
1920 1919 clk = clock2
1921 1920 wtime = time.time
1922 1921 # time execution
1923 1922 wall_st = wtime()
1924 1923 if mode=='eval':
1925 1924 st = clk()
1926 1925 out = eval(code,glob)
1927 1926 end = clk()
1928 1927 else:
1929 1928 st = clk()
1930 1929 exec code in glob
1931 1930 end = clk()
1932 1931 out = None
1933 1932 wall_end = wtime()
1934 1933 # Compute actual times and report
1935 1934 wall_time = wall_end-wall_st
1936 1935 cpu_user = end[0]-st[0]
1937 1936 cpu_sys = end[1]-st[1]
1938 1937 cpu_tot = cpu_user+cpu_sys
1939 1938 print "CPU times: user %.2f s, sys: %.2f s, total: %.2f s" % \
1940 1939 (cpu_user,cpu_sys,cpu_tot)
1941 1940 print "Wall time: %.2f s" % wall_time
1942 1941 if tc > tc_min:
1943 1942 print "Compiler : %.2f s" % tc
1944 1943 return out
1945 1944
1946 1945 @testdec.skip_doctest
1947 1946 def magic_macro(self,parameter_s = ''):
1948 1947 """Define a set of input lines as a macro for future re-execution.
1949 1948
1950 1949 Usage:\\
1951 1950 %macro [options] name n1-n2 n3-n4 ... n5 .. n6 ...
1952 1951
1953 1952 Options:
1954 1953
1955 1954 -r: use 'raw' input. By default, the 'processed' history is used,
1956 1955 so that magics are loaded in their transformed version to valid
1957 1956 Python. If this option is given, the raw input as typed as the
1958 1957 command line is used instead.
1959 1958
1960 1959 This will define a global variable called `name` which is a string
1961 1960 made of joining the slices and lines you specify (n1,n2,... numbers
1962 1961 above) from your input history into a single string. This variable
1963 1962 acts like an automatic function which re-executes those lines as if
1964 1963 you had typed them. You just type 'name' at the prompt and the code
1965 1964 executes.
1966 1965
1967 1966 The notation for indicating number ranges is: n1-n2 means 'use line
1968 1967 numbers n1,...n2' (the endpoint is included). That is, '5-7' means
1969 1968 using the lines numbered 5,6 and 7.
1970 1969
1971 1970 Note: as a 'hidden' feature, you can also use traditional python slice
1972 1971 notation, where N:M means numbers N through M-1.
1973 1972
1974 1973 For example, if your history contains (%hist prints it):
1975 1974
1976 1975 44: x=1
1977 1976 45: y=3
1978 1977 46: z=x+y
1979 1978 47: print x
1980 1979 48: a=5
1981 1980 49: print 'x',x,'y',y
1982 1981
1983 1982 you can create a macro with lines 44 through 47 (included) and line 49
1984 1983 called my_macro with:
1985 1984
1986 1985 In [55]: %macro my_macro 44-47 49
1987 1986
1988 1987 Now, typing `my_macro` (without quotes) will re-execute all this code
1989 1988 in one pass.
1990 1989
1991 1990 You don't need to give the line-numbers in order, and any given line
1992 1991 number can appear multiple times. You can assemble macros with any
1993 1992 lines from your input history in any order.
1994 1993
1995 1994 The macro is a simple object which holds its value in an attribute,
1996 1995 but IPython's display system checks for macros and executes them as
1997 1996 code instead of printing them when you type their name.
1998 1997
1999 1998 You can view a macro's contents by explicitly printing it with:
2000 1999
2001 2000 'print macro_name'.
2002 2001
2003 2002 For one-off cases which DON'T contain magic function calls in them you
2004 2003 can obtain similar results by explicitly executing slices from your
2005 2004 input history with:
2006 2005
2007 2006 In [60]: exec In[44:48]+In[49]"""
2008 2007
2009 2008 opts,args = self.parse_options(parameter_s,'r',mode='list')
2010 2009 if not args:
2011 2010 macs = [k for k,v in self.shell.user_ns.items() if isinstance(v, Macro)]
2012 2011 macs.sort()
2013 2012 return macs
2014 2013 if len(args) == 1:
2015 2014 raise UsageError(
2016 2015 "%macro insufficient args; usage '%macro name n1-n2 n3-4...")
2017 2016 name,ranges = args[0], args[1:]
2018 2017
2019 2018 #print 'rng',ranges # dbg
2020 2019 lines = self.extract_input_slices(ranges,opts.has_key('r'))
2021 2020 macro = Macro(lines)
2022 2021 self.shell.user_ns.update({name:macro})
2023 2022 print 'Macro `%s` created. To execute, type its name (without quotes).' % name
2024 2023 print 'Macro contents:'
2025 2024 print macro,
2026 2025
2027 2026 def magic_save(self,parameter_s = ''):
2028 2027 """Save a set of lines to a given filename.
2029 2028
2030 2029 Usage:\\
2031 2030 %save [options] filename n1-n2 n3-n4 ... n5 .. n6 ...
2032 2031
2033 2032 Options:
2034 2033
2035 2034 -r: use 'raw' input. By default, the 'processed' history is used,
2036 2035 so that magics are loaded in their transformed version to valid
2037 2036 Python. If this option is given, the raw input as typed as the
2038 2037 command line is used instead.
2039 2038
2040 2039 This function uses the same syntax as %macro for line extraction, but
2041 2040 instead of creating a macro it saves the resulting string to the
2042 2041 filename you specify.
2043 2042
2044 2043 It adds a '.py' extension to the file if you don't do so yourself, and
2045 2044 it asks for confirmation before overwriting existing files."""
2046 2045
2047 2046 opts,args = self.parse_options(parameter_s,'r',mode='list')
2048 2047 fname,ranges = args[0], args[1:]
2049 2048 if not fname.endswith('.py'):
2050 2049 fname += '.py'
2051 2050 if os.path.isfile(fname):
2052 2051 ans = raw_input('File `%s` exists. Overwrite (y/[N])? ' % fname)
2053 2052 if ans.lower() not in ['y','yes']:
2054 2053 print 'Operation cancelled.'
2055 2054 return
2056 2055 cmds = ''.join(self.extract_input_slices(ranges,opts.has_key('r')))
2057 2056 f = file(fname,'w')
2058 2057 f.write(cmds)
2059 2058 f.close()
2060 2059 print 'The following commands were written to file `%s`:' % fname
2061 2060 print cmds
2062 2061
2063 2062 def _edit_macro(self,mname,macro):
2064 2063 """open an editor with the macro data in a file"""
2065 2064 filename = self.shell.mktempfile(macro.value)
2066 2065 self.shell.hooks.editor(filename)
2067 2066
2068 2067 # and make a new macro object, to replace the old one
2069 2068 mfile = open(filename)
2070 2069 mvalue = mfile.read()
2071 2070 mfile.close()
2072 2071 self.shell.user_ns[mname] = Macro(mvalue)
2073 2072
2074 2073 def magic_ed(self,parameter_s=''):
2075 2074 """Alias to %edit."""
2076 2075 return self.magic_edit(parameter_s)
2077 2076
2078 2077 @testdec.skip_doctest
2079 2078 def magic_edit(self,parameter_s='',last_call=['','']):
2080 2079 """Bring up an editor and execute the resulting code.
2081 2080
2082 2081 Usage:
2083 2082 %edit [options] [args]
2084 2083
2085 2084 %edit runs IPython's editor hook. The default version of this hook is
2086 2085 set to call the __IPYTHON__.rc.editor command. This is read from your
2087 2086 environment variable $EDITOR. If this isn't found, it will default to
2088 2087 vi under Linux/Unix and to notepad under Windows. See the end of this
2089 2088 docstring for how to change the editor hook.
2090 2089
2091 2090 You can also set the value of this editor via the command line option
2092 2091 '-editor' or in your ipythonrc file. This is useful if you wish to use
2093 2092 specifically for IPython an editor different from your typical default
2094 2093 (and for Windows users who typically don't set environment variables).
2095 2094
2096 2095 This command allows you to conveniently edit multi-line code right in
2097 2096 your IPython session.
2098 2097
2099 2098 If called without arguments, %edit opens up an empty editor with a
2100 2099 temporary file and will execute the contents of this file when you
2101 2100 close it (don't forget to save it!).
2102 2101
2103 2102
2104 2103 Options:
2105 2104
2106 2105 -n <number>: open the editor at a specified line number. By default,
2107 2106 the IPython editor hook uses the unix syntax 'editor +N filename', but
2108 2107 you can configure this by providing your own modified hook if your
2109 2108 favorite editor supports line-number specifications with a different
2110 2109 syntax.
2111 2110
2112 2111 -p: this will call the editor with the same data as the previous time
2113 2112 it was used, regardless of how long ago (in your current session) it
2114 2113 was.
2115 2114
2116 2115 -r: use 'raw' input. This option only applies to input taken from the
2117 2116 user's history. By default, the 'processed' history is used, so that
2118 2117 magics are loaded in their transformed version to valid Python. If
2119 2118 this option is given, the raw input as typed as the command line is
2120 2119 used instead. When you exit the editor, it will be executed by
2121 2120 IPython's own processor.
2122 2121
2123 2122 -x: do not execute the edited code immediately upon exit. This is
2124 2123 mainly useful if you are editing programs which need to be called with
2125 2124 command line arguments, which you can then do using %run.
2126 2125
2127 2126
2128 2127 Arguments:
2129 2128
2130 2129 If arguments are given, the following possibilites exist:
2131 2130
2132 2131 - The arguments are numbers or pairs of colon-separated numbers (like
2133 2132 1 4:8 9). These are interpreted as lines of previous input to be
2134 2133 loaded into the editor. The syntax is the same of the %macro command.
2135 2134
2136 2135 - If the argument doesn't start with a number, it is evaluated as a
2137 2136 variable and its contents loaded into the editor. You can thus edit
2138 2137 any string which contains python code (including the result of
2139 2138 previous edits).
2140 2139
2141 2140 - If the argument is the name of an object (other than a string),
2142 2141 IPython will try to locate the file where it was defined and open the
2143 2142 editor at the point where it is defined. You can use `%edit function`
2144 2143 to load an editor exactly at the point where 'function' is defined,
2145 2144 edit it and have the file be executed automatically.
2146 2145
2147 2146 If the object is a macro (see %macro for details), this opens up your
2148 2147 specified editor with a temporary file containing the macro's data.
2149 2148 Upon exit, the macro is reloaded with the contents of the file.
2150 2149
2151 2150 Note: opening at an exact line is only supported under Unix, and some
2152 2151 editors (like kedit and gedit up to Gnome 2.8) do not understand the
2153 2152 '+NUMBER' parameter necessary for this feature. Good editors like
2154 2153 (X)Emacs, vi, jed, pico and joe all do.
2155 2154
2156 2155 - If the argument is not found as a variable, IPython will look for a
2157 2156 file with that name (adding .py if necessary) and load it into the
2158 2157 editor. It will execute its contents with execfile() when you exit,
2159 2158 loading any code in the file into your interactive namespace.
2160 2159
2161 2160 After executing your code, %edit will return as output the code you
2162 2161 typed in the editor (except when it was an existing file). This way
2163 2162 you can reload the code in further invocations of %edit as a variable,
2164 2163 via _<NUMBER> or Out[<NUMBER>], where <NUMBER> is the prompt number of
2165 2164 the output.
2166 2165
2167 2166 Note that %edit is also available through the alias %ed.
2168 2167
2169 2168 This is an example of creating a simple function inside the editor and
2170 2169 then modifying it. First, start up the editor:
2171 2170
2172 2171 In [1]: ed
2173 2172 Editing... done. Executing edited code...
2174 2173 Out[1]: 'def foo():n print "foo() was defined in an editing session"n'
2175 2174
2176 2175 We can then call the function foo():
2177 2176
2178 2177 In [2]: foo()
2179 2178 foo() was defined in an editing session
2180 2179
2181 2180 Now we edit foo. IPython automatically loads the editor with the
2182 2181 (temporary) file where foo() was previously defined:
2183 2182
2184 2183 In [3]: ed foo
2185 2184 Editing... done. Executing edited code...
2186 2185
2187 2186 And if we call foo() again we get the modified version:
2188 2187
2189 2188 In [4]: foo()
2190 2189 foo() has now been changed!
2191 2190
2192 2191 Here is an example of how to edit a code snippet successive
2193 2192 times. First we call the editor:
2194 2193
2195 2194 In [5]: ed
2196 2195 Editing... done. Executing edited code...
2197 2196 hello
2198 2197 Out[5]: "print 'hello'n"
2199 2198
2200 2199 Now we call it again with the previous output (stored in _):
2201 2200
2202 2201 In [6]: ed _
2203 2202 Editing... done. Executing edited code...
2204 2203 hello world
2205 2204 Out[6]: "print 'hello world'n"
2206 2205
2207 2206 Now we call it with the output #8 (stored in _8, also as Out[8]):
2208 2207
2209 2208 In [7]: ed _8
2210 2209 Editing... done. Executing edited code...
2211 2210 hello again
2212 2211 Out[7]: "print 'hello again'n"
2213 2212
2214 2213
2215 2214 Changing the default editor hook:
2216 2215
2217 2216 If you wish to write your own editor hook, you can put it in a
2218 2217 configuration file which you load at startup time. The default hook
2219 2218 is defined in the IPython.hooks module, and you can use that as a
2220 2219 starting example for further modifications. That file also has
2221 2220 general instructions on how to set a new hook for use once you've
2222 2221 defined it."""
2223 2222
2224 2223 # FIXME: This function has become a convoluted mess. It needs a
2225 2224 # ground-up rewrite with clean, simple logic.
2226 2225
2227 2226 def make_filename(arg):
2228 2227 "Make a filename from the given args"
2229 2228 try:
2230 2229 filename = get_py_filename(arg)
2231 2230 except IOError:
2232 2231 if args.endswith('.py'):
2233 2232 filename = arg
2234 2233 else:
2235 2234 filename = None
2236 2235 return filename
2237 2236
2238 2237 # custom exceptions
2239 2238 class DataIsObject(Exception): pass
2240 2239
2241 2240 opts,args = self.parse_options(parameter_s,'prxn:')
2242 2241 # Set a few locals from the options for convenience:
2243 2242 opts_p = opts.has_key('p')
2244 2243 opts_r = opts.has_key('r')
2245 2244
2246 2245 # Default line number value
2247 2246 lineno = opts.get('n',None)
2248 2247
2249 2248 if opts_p:
2250 2249 args = '_%s' % last_call[0]
2251 2250 if not self.shell.user_ns.has_key(args):
2252 2251 args = last_call[1]
2253 2252
2254 2253 # use last_call to remember the state of the previous call, but don't
2255 2254 # let it be clobbered by successive '-p' calls.
2256 2255 try:
2257 2256 last_call[0] = self.shell.outputcache.prompt_count
2258 2257 if not opts_p:
2259 2258 last_call[1] = parameter_s
2260 2259 except:
2261 2260 pass
2262 2261
2263 2262 # by default this is done with temp files, except when the given
2264 2263 # arg is a filename
2265 2264 use_temp = 1
2266 2265
2267 2266 if re.match(r'\d',args):
2268 2267 # Mode where user specifies ranges of lines, like in %macro.
2269 2268 # This means that you can't edit files whose names begin with
2270 2269 # numbers this way. Tough.
2271 2270 ranges = args.split()
2272 2271 data = ''.join(self.extract_input_slices(ranges,opts_r))
2273 2272 elif args.endswith('.py'):
2274 2273 filename = make_filename(args)
2275 2274 data = ''
2276 2275 use_temp = 0
2277 2276 elif args:
2278 2277 try:
2279 2278 # Load the parameter given as a variable. If not a string,
2280 2279 # process it as an object instead (below)
2281 2280
2282 2281 #print '*** args',args,'type',type(args) # dbg
2283 2282 data = eval(args,self.shell.user_ns)
2284 2283 if not type(data) in StringTypes:
2285 2284 raise DataIsObject
2286 2285
2287 2286 except (NameError,SyntaxError):
2288 2287 # given argument is not a variable, try as a filename
2289 2288 filename = make_filename(args)
2290 2289 if filename is None:
2291 2290 warn("Argument given (%s) can't be found as a variable "
2292 2291 "or as a filename." % args)
2293 2292 return
2294 2293
2295 2294 data = ''
2296 2295 use_temp = 0
2297 2296 except DataIsObject:
2298 2297
2299 2298 # macros have a special edit function
2300 2299 if isinstance(data,Macro):
2301 2300 self._edit_macro(args,data)
2302 2301 return
2303 2302
2304 2303 # For objects, try to edit the file where they are defined
2305 2304 try:
2306 2305 filename = inspect.getabsfile(data)
2307 2306 if 'fakemodule' in filename.lower() and inspect.isclass(data):
2308 2307 # class created by %edit? Try to find source
2309 2308 # by looking for method definitions instead, the
2310 2309 # __module__ in those classes is FakeModule.
2311 2310 attrs = [getattr(data, aname) for aname in dir(data)]
2312 2311 for attr in attrs:
2313 2312 if not inspect.ismethod(attr):
2314 2313 continue
2315 2314 filename = inspect.getabsfile(attr)
2316 2315 if filename and 'fakemodule' not in filename.lower():
2317 2316 # change the attribute to be the edit target instead
2318 2317 data = attr
2319 2318 break
2320 2319
2321 2320 datafile = 1
2322 2321 except TypeError:
2323 2322 filename = make_filename(args)
2324 2323 datafile = 1
2325 2324 warn('Could not find file where `%s` is defined.\n'
2326 2325 'Opening a file named `%s`' % (args,filename))
2327 2326 # Now, make sure we can actually read the source (if it was in
2328 2327 # a temp file it's gone by now).
2329 2328 if datafile:
2330 2329 try:
2331 2330 if lineno is None:
2332 2331 lineno = inspect.getsourcelines(data)[1]
2333 2332 except IOError:
2334 2333 filename = make_filename(args)
2335 2334 if filename is None:
2336 2335 warn('The file `%s` where `%s` was defined cannot '
2337 2336 'be read.' % (filename,data))
2338 2337 return
2339 2338 use_temp = 0
2340 2339 else:
2341 2340 data = ''
2342 2341
2343 2342 if use_temp:
2344 2343 filename = self.shell.mktempfile(data)
2345 2344 print 'IPython will make a temporary file named:',filename
2346 2345
2347 2346 # do actual editing here
2348 2347 print 'Editing...',
2349 2348 sys.stdout.flush()
2350 2349 self.shell.hooks.editor(filename,lineno)
2351 2350
2352 2351 # XXX TODO: should this be generalized for all string vars?
2353 2352 # For now, this is special-cased to blocks created by cpaste
2354 2353 if args.strip() == 'pasted_block':
2355 2354 self.shell.user_ns['pasted_block'] = file_read(filename)
2356 2355
2357 2356 if opts.has_key('x'): # -x prevents actual execution
2358 2357 print
2359 2358 else:
2360 2359 print 'done. Executing edited code...'
2361 2360 if opts_r:
2362 2361 self.shell.runlines(file_read(filename))
2363 2362 else:
2364 2363 self.shell.safe_execfile(filename,self.shell.user_ns,
2365 2364 self.shell.user_ns)
2366 2365
2367 2366
2368 2367 if use_temp:
2369 2368 try:
2370 2369 return open(filename).read()
2371 2370 except IOError,msg:
2372 2371 if msg.filename == filename:
2373 2372 warn('File not found. Did you forget to save?')
2374 2373 return
2375 2374 else:
2376 2375 self.shell.showtraceback()
2377 2376
2378 2377 def magic_xmode(self,parameter_s = ''):
2379 2378 """Switch modes for the exception handlers.
2380 2379
2381 2380 Valid modes: Plain, Context and Verbose.
2382 2381
2383 2382 If called without arguments, acts as a toggle."""
2384 2383
2385 2384 def xmode_switch_err(name):
2386 2385 warn('Error changing %s exception modes.\n%s' %
2387 2386 (name,sys.exc_info()[1]))
2388 2387
2389 2388 shell = self.shell
2390 2389 new_mode = parameter_s.strip().capitalize()
2391 2390 try:
2392 2391 shell.InteractiveTB.set_mode(mode=new_mode)
2393 2392 print 'Exception reporting mode:',shell.InteractiveTB.mode
2394 2393 except:
2395 2394 xmode_switch_err('user')
2396 2395
2397 2396 # threaded shells use a special handler in sys.excepthook
2398 2397 if shell.isthreaded:
2399 2398 try:
2400 2399 shell.sys_excepthook.set_mode(mode=new_mode)
2401 2400 except:
2402 2401 xmode_switch_err('threaded')
2403 2402
2404 2403 def magic_colors(self,parameter_s = ''):
2405 2404 """Switch color scheme for prompts, info system and exception handlers.
2406 2405
2407 2406 Currently implemented schemes: NoColor, Linux, LightBG.
2408 2407
2409 2408 Color scheme names are not case-sensitive."""
2410 2409
2411 2410 def color_switch_err(name):
2412 2411 warn('Error changing %s color schemes.\n%s' %
2413 2412 (name,sys.exc_info()[1]))
2414 2413
2415 2414
2416 2415 new_scheme = parameter_s.strip()
2417 2416 if not new_scheme:
2418 2417 raise UsageError(
2419 2418 "%colors: you must specify a color scheme. See '%colors?'")
2420 2419 return
2421 2420 # local shortcut
2422 2421 shell = self.shell
2423 2422
2424 2423 import IPython.rlineimpl as readline
2425 2424
2426 2425 if not readline.have_readline and sys.platform == "win32":
2427 2426 msg = """\
2428 2427 Proper color support under MS Windows requires the pyreadline library.
2429 2428 You can find it at:
2430 2429 http://ipython.scipy.org/moin/PyReadline/Intro
2431 2430 Gary's readline needs the ctypes module, from:
2432 2431 http://starship.python.net/crew/theller/ctypes
2433 2432 (Note that ctypes is already part of Python versions 2.5 and newer).
2434 2433
2435 2434 Defaulting color scheme to 'NoColor'"""
2436 2435 new_scheme = 'NoColor'
2437 2436 warn(msg)
2438 2437
2439 2438 # readline option is 0
2440 2439 if not shell.has_readline:
2441 2440 new_scheme = 'NoColor'
2442 2441
2443 2442 # Set prompt colors
2444 2443 try:
2445 2444 shell.outputcache.set_colors(new_scheme)
2446 2445 except:
2447 2446 color_switch_err('prompt')
2448 2447 else:
2449 2448 shell.rc.colors = \
2450 2449 shell.outputcache.color_table.active_scheme_name
2451 2450 # Set exception colors
2452 2451 try:
2453 2452 shell.InteractiveTB.set_colors(scheme = new_scheme)
2454 2453 shell.SyntaxTB.set_colors(scheme = new_scheme)
2455 2454 except:
2456 2455 color_switch_err('exception')
2457 2456
2458 2457 # threaded shells use a verbose traceback in sys.excepthook
2459 2458 if shell.isthreaded:
2460 2459 try:
2461 2460 shell.sys_excepthook.set_colors(scheme=new_scheme)
2462 2461 except:
2463 2462 color_switch_err('system exception handler')
2464 2463
2465 2464 # Set info (for 'object?') colors
2466 2465 if shell.rc.color_info:
2467 2466 try:
2468 2467 shell.inspector.set_active_scheme(new_scheme)
2469 2468 except:
2470 2469 color_switch_err('object inspector')
2471 2470 else:
2472 2471 shell.inspector.set_active_scheme('NoColor')
2473 2472
2474 2473 def magic_color_info(self,parameter_s = ''):
2475 2474 """Toggle color_info.
2476 2475
2477 2476 The color_info configuration parameter controls whether colors are
2478 2477 used for displaying object details (by things like %psource, %pfile or
2479 2478 the '?' system). This function toggles this value with each call.
2480 2479
2481 2480 Note that unless you have a fairly recent pager (less works better
2482 2481 than more) in your system, using colored object information displays
2483 2482 will not work properly. Test it and see."""
2484 2483
2485 2484 self.shell.rc.color_info = 1 - self.shell.rc.color_info
2486 2485 self.magic_colors(self.shell.rc.colors)
2487 2486 print 'Object introspection functions have now coloring:',
2488 2487 print ['OFF','ON'][self.shell.rc.color_info]
2489 2488
2490 2489 def magic_Pprint(self, parameter_s=''):
2491 2490 """Toggle pretty printing on/off."""
2492 2491
2493 2492 self.shell.rc.pprint = 1 - self.shell.rc.pprint
2494 2493 print 'Pretty printing has been turned', \
2495 2494 ['OFF','ON'][self.shell.rc.pprint]
2496 2495
2497 2496 def magic_exit(self, parameter_s=''):
2498 2497 """Exit IPython, confirming if configured to do so.
2499 2498
2500 2499 You can configure whether IPython asks for confirmation upon exit by
2501 2500 setting the confirm_exit flag in the ipythonrc file."""
2502 2501
2503 2502 self.shell.exit()
2504 2503
2505 2504 def magic_quit(self, parameter_s=''):
2506 2505 """Exit IPython, confirming if configured to do so (like %exit)"""
2507 2506
2508 2507 self.shell.exit()
2509 2508
2510 2509 def magic_Exit(self, parameter_s=''):
2511 2510 """Exit IPython without confirmation."""
2512 2511
2513 2512 self.shell.ask_exit()
2514 2513
2515 2514 #......................................................................
2516 2515 # Functions to implement unix shell-type things
2517 2516
2518 2517 @testdec.skip_doctest
2519 2518 def magic_alias(self, parameter_s = ''):
2520 2519 """Define an alias for a system command.
2521 2520
2522 2521 '%alias alias_name cmd' defines 'alias_name' as an alias for 'cmd'
2523 2522
2524 2523 Then, typing 'alias_name params' will execute the system command 'cmd
2525 2524 params' (from your underlying operating system).
2526 2525
2527 2526 Aliases have lower precedence than magic functions and Python normal
2528 2527 variables, so if 'foo' is both a Python variable and an alias, the
2529 2528 alias can not be executed until 'del foo' removes the Python variable.
2530 2529
2531 2530 You can use the %l specifier in an alias definition to represent the
2532 2531 whole line when the alias is called. For example:
2533 2532
2534 2533 In [2]: alias all echo "Input in brackets: <%l>"
2535 2534 In [3]: all hello world
2536 2535 Input in brackets: <hello world>
2537 2536
2538 2537 You can also define aliases with parameters using %s specifiers (one
2539 2538 per parameter):
2540 2539
2541 2540 In [1]: alias parts echo first %s second %s
2542 2541 In [2]: %parts A B
2543 2542 first A second B
2544 2543 In [3]: %parts A
2545 2544 Incorrect number of arguments: 2 expected.
2546 2545 parts is an alias to: 'echo first %s second %s'
2547 2546
2548 2547 Note that %l and %s are mutually exclusive. You can only use one or
2549 2548 the other in your aliases.
2550 2549
2551 2550 Aliases expand Python variables just like system calls using ! or !!
2552 2551 do: all expressions prefixed with '$' get expanded. For details of
2553 2552 the semantic rules, see PEP-215:
2554 2553 http://www.python.org/peps/pep-0215.html. This is the library used by
2555 2554 IPython for variable expansion. If you want to access a true shell
2556 2555 variable, an extra $ is necessary to prevent its expansion by IPython:
2557 2556
2558 2557 In [6]: alias show echo
2559 2558 In [7]: PATH='A Python string'
2560 2559 In [8]: show $PATH
2561 2560 A Python string
2562 2561 In [9]: show $$PATH
2563 2562 /usr/local/lf9560/bin:/usr/local/intel/compiler70/ia32/bin:...
2564 2563
2565 2564 You can use the alias facility to acess all of $PATH. See the %rehash
2566 2565 and %rehashx functions, which automatically create aliases for the
2567 2566 contents of your $PATH.
2568 2567
2569 2568 If called with no parameters, %alias prints the current alias table."""
2570 2569
2571 2570 par = parameter_s.strip()
2572 2571 if not par:
2573 2572 stored = self.db.get('stored_aliases', {} )
2574 2573 atab = self.shell.alias_table
2575 2574 aliases = atab.keys()
2576 2575 aliases.sort()
2577 2576 res = []
2578 2577 showlast = []
2579 2578 for alias in aliases:
2580 2579 special = False
2581 2580 try:
2582 2581 tgt = atab[alias][1]
2583 2582 except (TypeError, AttributeError):
2584 2583 # unsubscriptable? probably a callable
2585 2584 tgt = atab[alias]
2586 2585 special = True
2587 2586 # 'interesting' aliases
2588 2587 if (alias in stored or
2589 2588 special or
2590 2589 alias.lower() != os.path.splitext(tgt)[0].lower() or
2591 2590 ' ' in tgt):
2592 2591 showlast.append((alias, tgt))
2593 2592 else:
2594 2593 res.append((alias, tgt ))
2595 2594
2596 2595 # show most interesting aliases last
2597 2596 res.extend(showlast)
2598 2597 print "Total number of aliases:",len(aliases)
2599 2598 return res
2600 2599 try:
2601 2600 alias,cmd = par.split(None,1)
2602 2601 except:
2603 2602 print OInspect.getdoc(self.magic_alias)
2604 2603 else:
2605 2604 nargs = cmd.count('%s')
2606 2605 if nargs>0 and cmd.find('%l')>=0:
2607 2606 error('The %s and %l specifiers are mutually exclusive '
2608 2607 'in alias definitions.')
2609 2608 else: # all looks OK
2610 2609 self.shell.alias_table[alias] = (nargs,cmd)
2611 2610 self.shell.alias_table_validate(verbose=0)
2612 2611 # end magic_alias
2613 2612
2614 2613 def magic_unalias(self, parameter_s = ''):
2615 2614 """Remove an alias"""
2616 2615
2617 2616 aname = parameter_s.strip()
2618 2617 if aname in self.shell.alias_table:
2619 2618 del self.shell.alias_table[aname]
2620 2619 stored = self.db.get('stored_aliases', {} )
2621 2620 if aname in stored:
2622 2621 print "Removing %stored alias",aname
2623 2622 del stored[aname]
2624 2623 self.db['stored_aliases'] = stored
2625 2624
2626 2625
2627 2626 def magic_rehashx(self, parameter_s = ''):
2628 2627 """Update the alias table with all executable files in $PATH.
2629 2628
2630 2629 This version explicitly checks that every entry in $PATH is a file
2631 2630 with execute access (os.X_OK), so it is much slower than %rehash.
2632 2631
2633 2632 Under Windows, it checks executability as a match agains a
2634 2633 '|'-separated string of extensions, stored in the IPython config
2635 2634 variable win_exec_ext. This defaults to 'exe|com|bat'.
2636 2635
2637 2636 This function also resets the root module cache of module completer,
2638 2637 used on slow filesystems.
2639 2638 """
2640 2639
2641 2640
2642 2641 ip = self.api
2643 2642
2644 2643 # for the benefit of module completer in ipy_completers.py
2645 2644 del ip.db['rootmodules']
2646 2645
2647 2646 path = [os.path.abspath(os.path.expanduser(p)) for p in
2648 2647 os.environ.get('PATH','').split(os.pathsep)]
2649 2648 path = filter(os.path.isdir,path)
2650 2649
2651 2650 alias_table = self.shell.alias_table
2652 2651 syscmdlist = []
2653 2652 if os.name == 'posix':
2654 2653 isexec = lambda fname:os.path.isfile(fname) and \
2655 2654 os.access(fname,os.X_OK)
2656 2655 else:
2657 2656
2658 2657 try:
2659 2658 winext = os.environ['pathext'].replace(';','|').replace('.','')
2660 2659 except KeyError:
2661 2660 winext = 'exe|com|bat|py'
2662 2661 if 'py' not in winext:
2663 2662 winext += '|py'
2664 2663 execre = re.compile(r'(.*)\.(%s)$' % winext,re.IGNORECASE)
2665 2664 isexec = lambda fname:os.path.isfile(fname) and execre.match(fname)
2666 2665 savedir = os.getcwd()
2667 2666 try:
2668 2667 # write the whole loop for posix/Windows so we don't have an if in
2669 2668 # the innermost part
2670 2669 if os.name == 'posix':
2671 2670 for pdir in path:
2672 2671 os.chdir(pdir)
2673 2672 for ff in os.listdir(pdir):
2674 2673 if isexec(ff) and ff not in self.shell.no_alias:
2675 2674 # each entry in the alias table must be (N,name),
2676 2675 # where N is the number of positional arguments of the
2677 2676 # alias.
2678 2677 # Dots will be removed from alias names, since ipython
2679 2678 # assumes names with dots to be python code
2680 2679 alias_table[ff.replace('.','')] = (0,ff)
2681 2680 syscmdlist.append(ff)
2682 2681 else:
2683 2682 for pdir in path:
2684 2683 os.chdir(pdir)
2685 2684 for ff in os.listdir(pdir):
2686 2685 base, ext = os.path.splitext(ff)
2687 2686 if isexec(ff) and base.lower() not in self.shell.no_alias:
2688 2687 if ext.lower() == '.exe':
2689 2688 ff = base
2690 2689 alias_table[base.lower().replace('.','')] = (0,ff)
2691 2690 syscmdlist.append(ff)
2692 2691 # Make sure the alias table doesn't contain keywords or builtins
2693 2692 self.shell.alias_table_validate()
2694 2693 # Call again init_auto_alias() so we get 'rm -i' and other
2695 2694 # modified aliases since %rehashx will probably clobber them
2696 2695
2697 2696 # no, we don't want them. if %rehashx clobbers them, good,
2698 2697 # we'll probably get better versions
2699 2698 # self.shell.init_auto_alias()
2700 2699 db = ip.db
2701 2700 db['syscmdlist'] = syscmdlist
2702 2701 finally:
2703 2702 os.chdir(savedir)
2704 2703
2705 2704 def magic_pwd(self, parameter_s = ''):
2706 2705 """Return the current working directory path."""
2707 2706 return os.getcwd()
2708 2707
2709 2708 def magic_cd(self, parameter_s=''):
2710 2709 """Change the current working directory.
2711 2710
2712 2711 This command automatically maintains an internal list of directories
2713 2712 you visit during your IPython session, in the variable _dh. The
2714 2713 command %dhist shows this history nicely formatted. You can also
2715 2714 do 'cd -<tab>' to see directory history conveniently.
2716 2715
2717 2716 Usage:
2718 2717
2719 2718 cd 'dir': changes to directory 'dir'.
2720 2719
2721 2720 cd -: changes to the last visited directory.
2722 2721
2723 2722 cd -<n>: changes to the n-th directory in the directory history.
2724 2723
2725 2724 cd --foo: change to directory that matches 'foo' in history
2726 2725
2727 2726 cd -b <bookmark_name>: jump to a bookmark set by %bookmark
2728 2727 (note: cd <bookmark_name> is enough if there is no
2729 2728 directory <bookmark_name>, but a bookmark with the name exists.)
2730 2729 'cd -b <tab>' allows you to tab-complete bookmark names.
2731 2730
2732 2731 Options:
2733 2732
2734 2733 -q: quiet. Do not print the working directory after the cd command is
2735 2734 executed. By default IPython's cd command does print this directory,
2736 2735 since the default prompts do not display path information.
2737 2736
2738 2737 Note that !cd doesn't work for this purpose because the shell where
2739 2738 !command runs is immediately discarded after executing 'command'."""
2740 2739
2741 2740 parameter_s = parameter_s.strip()
2742 2741 #bkms = self.shell.persist.get("bookmarks",{})
2743 2742
2744 2743 oldcwd = os.getcwd()
2745 2744 numcd = re.match(r'(-)(\d+)$',parameter_s)
2746 2745 # jump in directory history by number
2747 2746 if numcd:
2748 2747 nn = int(numcd.group(2))
2749 2748 try:
2750 2749 ps = self.shell.user_ns['_dh'][nn]
2751 2750 except IndexError:
2752 2751 print 'The requested directory does not exist in history.'
2753 2752 return
2754 2753 else:
2755 2754 opts = {}
2756 2755 elif parameter_s.startswith('--'):
2757 2756 ps = None
2758 2757 fallback = None
2759 2758 pat = parameter_s[2:]
2760 2759 dh = self.shell.user_ns['_dh']
2761 2760 # first search only by basename (last component)
2762 2761 for ent in reversed(dh):
2763 2762 if pat in os.path.basename(ent) and os.path.isdir(ent):
2764 2763 ps = ent
2765 2764 break
2766 2765
2767 2766 if fallback is None and pat in ent and os.path.isdir(ent):
2768 2767 fallback = ent
2769 2768
2770 2769 # if we have no last part match, pick the first full path match
2771 2770 if ps is None:
2772 2771 ps = fallback
2773 2772
2774 2773 if ps is None:
2775 2774 print "No matching entry in directory history"
2776 2775 return
2777 2776 else:
2778 2777 opts = {}
2779 2778
2780 2779
2781 2780 else:
2782 2781 #turn all non-space-escaping backslashes to slashes,
2783 2782 # for c:\windows\directory\names\
2784 2783 parameter_s = re.sub(r'\\(?! )','/', parameter_s)
2785 2784 opts,ps = self.parse_options(parameter_s,'qb',mode='string')
2786 2785 # jump to previous
2787 2786 if ps == '-':
2788 2787 try:
2789 2788 ps = self.shell.user_ns['_dh'][-2]
2790 2789 except IndexError:
2791 2790 raise UsageError('%cd -: No previous directory to change to.')
2792 2791 # jump to bookmark if needed
2793 2792 else:
2794 2793 if not os.path.isdir(ps) or opts.has_key('b'):
2795 2794 bkms = self.db.get('bookmarks', {})
2796 2795
2797 2796 if bkms.has_key(ps):
2798 2797 target = bkms[ps]
2799 2798 print '(bookmark:%s) -> %s' % (ps,target)
2800 2799 ps = target
2801 2800 else:
2802 2801 if opts.has_key('b'):
2803 2802 raise UsageError("Bookmark '%s' not found. "
2804 2803 "Use '%%bookmark -l' to see your bookmarks." % ps)
2805 2804
2806 2805 # at this point ps should point to the target dir
2807 2806 if ps:
2808 2807 try:
2809 2808 os.chdir(os.path.expanduser(ps))
2810 2809 if self.shell.rc.term_title:
2811 2810 #print 'set term title:',self.shell.rc.term_title # dbg
2812 2811 platutils.set_term_title('IPy ' + abbrev_cwd())
2813 2812 except OSError:
2814 2813 print sys.exc_info()[1]
2815 2814 else:
2816 2815 cwd = os.getcwd()
2817 2816 dhist = self.shell.user_ns['_dh']
2818 2817 if oldcwd != cwd:
2819 2818 dhist.append(cwd)
2820 2819 self.db['dhist'] = compress_dhist(dhist)[-100:]
2821 2820
2822 2821 else:
2823 2822 os.chdir(self.shell.home_dir)
2824 2823 if self.shell.rc.term_title:
2825 2824 platutils.set_term_title("IPy ~")
2826 2825 cwd = os.getcwd()
2827 2826 dhist = self.shell.user_ns['_dh']
2828 2827
2829 2828 if oldcwd != cwd:
2830 2829 dhist.append(cwd)
2831 2830 self.db['dhist'] = compress_dhist(dhist)[-100:]
2832 2831 if not 'q' in opts and self.shell.user_ns['_dh']:
2833 2832 print self.shell.user_ns['_dh'][-1]
2834 2833
2835 2834
2836 2835 def magic_env(self, parameter_s=''):
2837 2836 """List environment variables."""
2838 2837
2839 2838 return os.environ.data
2840 2839
2841 2840 def magic_pushd(self, parameter_s=''):
2842 2841 """Place the current dir on stack and change directory.
2843 2842
2844 2843 Usage:\\
2845 2844 %pushd ['dirname']
2846 2845 """
2847 2846
2848 2847 dir_s = self.shell.dir_stack
2849 2848 tgt = os.path.expanduser(parameter_s)
2850 2849 cwd = os.getcwd().replace(self.home_dir,'~')
2851 2850 if tgt:
2852 2851 self.magic_cd(parameter_s)
2853 2852 dir_s.insert(0,cwd)
2854 2853 return self.magic_dirs()
2855 2854
2856 2855 def magic_popd(self, parameter_s=''):
2857 2856 """Change to directory popped off the top of the stack.
2858 2857 """
2859 2858 if not self.shell.dir_stack:
2860 2859 raise UsageError("%popd on empty stack")
2861 2860 top = self.shell.dir_stack.pop(0)
2862 2861 self.magic_cd(top)
2863 2862 print "popd ->",top
2864 2863
2865 2864 def magic_dirs(self, parameter_s=''):
2866 2865 """Return the current directory stack."""
2867 2866
2868 2867 return self.shell.dir_stack
2869 2868
2870 2869 def magic_dhist(self, parameter_s=''):
2871 2870 """Print your history of visited directories.
2872 2871
2873 2872 %dhist -> print full history\\
2874 2873 %dhist n -> print last n entries only\\
2875 2874 %dhist n1 n2 -> print entries between n1 and n2 (n1 not included)\\
2876 2875
2877 2876 This history is automatically maintained by the %cd command, and
2878 2877 always available as the global list variable _dh. You can use %cd -<n>
2879 2878 to go to directory number <n>.
2880 2879
2881 2880 Note that most of time, you should view directory history by entering
2882 2881 cd -<TAB>.
2883 2882
2884 2883 """
2885 2884
2886 2885 dh = self.shell.user_ns['_dh']
2887 2886 if parameter_s:
2888 2887 try:
2889 2888 args = map(int,parameter_s.split())
2890 2889 except:
2891 2890 self.arg_err(Magic.magic_dhist)
2892 2891 return
2893 2892 if len(args) == 1:
2894 2893 ini,fin = max(len(dh)-(args[0]),0),len(dh)
2895 2894 elif len(args) == 2:
2896 2895 ini,fin = args
2897 2896 else:
2898 2897 self.arg_err(Magic.magic_dhist)
2899 2898 return
2900 2899 else:
2901 2900 ini,fin = 0,len(dh)
2902 2901 nlprint(dh,
2903 2902 header = 'Directory history (kept in _dh)',
2904 2903 start=ini,stop=fin)
2905 2904
2906 2905 @testdec.skip_doctest
2907 2906 def magic_sc(self, parameter_s=''):
2908 2907 """Shell capture - execute a shell command and capture its output.
2909 2908
2910 2909 DEPRECATED. Suboptimal, retained for backwards compatibility.
2911 2910
2912 2911 You should use the form 'var = !command' instead. Example:
2913 2912
2914 2913 "%sc -l myfiles = ls ~" should now be written as
2915 2914
2916 2915 "myfiles = !ls ~"
2917 2916
2918 2917 myfiles.s, myfiles.l and myfiles.n still apply as documented
2919 2918 below.
2920 2919
2921 2920 --
2922 2921 %sc [options] varname=command
2923 2922
2924 2923 IPython will run the given command using commands.getoutput(), and
2925 2924 will then update the user's interactive namespace with a variable
2926 2925 called varname, containing the value of the call. Your command can
2927 2926 contain shell wildcards, pipes, etc.
2928 2927
2929 2928 The '=' sign in the syntax is mandatory, and the variable name you
2930 2929 supply must follow Python's standard conventions for valid names.
2931 2930
2932 2931 (A special format without variable name exists for internal use)
2933 2932
2934 2933 Options:
2935 2934
2936 2935 -l: list output. Split the output on newlines into a list before
2937 2936 assigning it to the given variable. By default the output is stored
2938 2937 as a single string.
2939 2938
2940 2939 -v: verbose. Print the contents of the variable.
2941 2940
2942 2941 In most cases you should not need to split as a list, because the
2943 2942 returned value is a special type of string which can automatically
2944 2943 provide its contents either as a list (split on newlines) or as a
2945 2944 space-separated string. These are convenient, respectively, either
2946 2945 for sequential processing or to be passed to a shell command.
2947 2946
2948 2947 For example:
2949 2948
2950 2949 # all-random
2951 2950
2952 2951 # Capture into variable a
2953 2952 In [1]: sc a=ls *py
2954 2953
2955 2954 # a is a string with embedded newlines
2956 2955 In [2]: a
2957 2956 Out[2]: 'setup.py\\nwin32_manual_post_install.py'
2958 2957
2959 2958 # which can be seen as a list:
2960 2959 In [3]: a.l
2961 2960 Out[3]: ['setup.py', 'win32_manual_post_install.py']
2962 2961
2963 2962 # or as a whitespace-separated string:
2964 2963 In [4]: a.s
2965 2964 Out[4]: 'setup.py win32_manual_post_install.py'
2966 2965
2967 2966 # a.s is useful to pass as a single command line:
2968 2967 In [5]: !wc -l $a.s
2969 2968 146 setup.py
2970 2969 130 win32_manual_post_install.py
2971 2970 276 total
2972 2971
2973 2972 # while the list form is useful to loop over:
2974 2973 In [6]: for f in a.l:
2975 2974 ...: !wc -l $f
2976 2975 ...:
2977 2976 146 setup.py
2978 2977 130 win32_manual_post_install.py
2979 2978
2980 2979 Similiarly, the lists returned by the -l option are also special, in
2981 2980 the sense that you can equally invoke the .s attribute on them to
2982 2981 automatically get a whitespace-separated string from their contents:
2983 2982
2984 2983 In [7]: sc -l b=ls *py
2985 2984
2986 2985 In [8]: b
2987 2986 Out[8]: ['setup.py', 'win32_manual_post_install.py']
2988 2987
2989 2988 In [9]: b.s
2990 2989 Out[9]: 'setup.py win32_manual_post_install.py'
2991 2990
2992 2991 In summary, both the lists and strings used for ouptut capture have
2993 2992 the following special attributes:
2994 2993
2995 2994 .l (or .list) : value as list.
2996 2995 .n (or .nlstr): value as newline-separated string.
2997 2996 .s (or .spstr): value as space-separated string.
2998 2997 """
2999 2998
3000 2999 opts,args = self.parse_options(parameter_s,'lv')
3001 3000 # Try to get a variable name and command to run
3002 3001 try:
3003 3002 # the variable name must be obtained from the parse_options
3004 3003 # output, which uses shlex.split to strip options out.
3005 3004 var,_ = args.split('=',1)
3006 3005 var = var.strip()
3007 3006 # But the the command has to be extracted from the original input
3008 3007 # parameter_s, not on what parse_options returns, to avoid the
3009 3008 # quote stripping which shlex.split performs on it.
3010 3009 _,cmd = parameter_s.split('=',1)
3011 3010 except ValueError:
3012 3011 var,cmd = '',''
3013 3012 # If all looks ok, proceed
3014 3013 out,err = self.shell.getoutputerror(cmd)
3015 3014 if err:
3016 3015 print >> Term.cerr,err
3017 3016 if opts.has_key('l'):
3018 3017 out = SList(out.split('\n'))
3019 3018 else:
3020 3019 out = LSString(out)
3021 3020 if opts.has_key('v'):
3022 3021 print '%s ==\n%s' % (var,pformat(out))
3023 3022 if var:
3024 3023 self.shell.user_ns.update({var:out})
3025 3024 else:
3026 3025 return out
3027 3026
3028 3027 def magic_sx(self, parameter_s=''):
3029 3028 """Shell execute - run a shell command and capture its output.
3030 3029
3031 3030 %sx command
3032 3031
3033 3032 IPython will run the given command using commands.getoutput(), and
3034 3033 return the result formatted as a list (split on '\\n'). Since the
3035 3034 output is _returned_, it will be stored in ipython's regular output
3036 3035 cache Out[N] and in the '_N' automatic variables.
3037 3036
3038 3037 Notes:
3039 3038
3040 3039 1) If an input line begins with '!!', then %sx is automatically
3041 3040 invoked. That is, while:
3042 3041 !ls
3043 3042 causes ipython to simply issue system('ls'), typing
3044 3043 !!ls
3045 3044 is a shorthand equivalent to:
3046 3045 %sx ls
3047 3046
3048 3047 2) %sx differs from %sc in that %sx automatically splits into a list,
3049 3048 like '%sc -l'. The reason for this is to make it as easy as possible
3050 3049 to process line-oriented shell output via further python commands.
3051 3050 %sc is meant to provide much finer control, but requires more
3052 3051 typing.
3053 3052
3054 3053 3) Just like %sc -l, this is a list with special attributes:
3055 3054
3056 3055 .l (or .list) : value as list.
3057 3056 .n (or .nlstr): value as newline-separated string.
3058 3057 .s (or .spstr): value as whitespace-separated string.
3059 3058
3060 3059 This is very useful when trying to use such lists as arguments to
3061 3060 system commands."""
3062 3061
3063 3062 if parameter_s:
3064 3063 out,err = self.shell.getoutputerror(parameter_s)
3065 3064 if err:
3066 3065 print >> Term.cerr,err
3067 3066 return SList(out.split('\n'))
3068 3067
3069 3068 def magic_bg(self, parameter_s=''):
3070 3069 """Run a job in the background, in a separate thread.
3071 3070
3072 3071 For example,
3073 3072
3074 3073 %bg myfunc(x,y,z=1)
3075 3074
3076 3075 will execute 'myfunc(x,y,z=1)' in a background thread. As soon as the
3077 3076 execution starts, a message will be printed indicating the job
3078 3077 number. If your job number is 5, you can use
3079 3078
3080 3079 myvar = jobs.result(5) or myvar = jobs[5].result
3081 3080
3082 3081 to assign this result to variable 'myvar'.
3083 3082
3084 3083 IPython has a job manager, accessible via the 'jobs' object. You can
3085 3084 type jobs? to get more information about it, and use jobs.<TAB> to see
3086 3085 its attributes. All attributes not starting with an underscore are
3087 3086 meant for public use.
3088 3087
3089 3088 In particular, look at the jobs.new() method, which is used to create
3090 3089 new jobs. This magic %bg function is just a convenience wrapper
3091 3090 around jobs.new(), for expression-based jobs. If you want to create a
3092 3091 new job with an explicit function object and arguments, you must call
3093 3092 jobs.new() directly.
3094 3093
3095 3094 The jobs.new docstring also describes in detail several important
3096 3095 caveats associated with a thread-based model for background job
3097 3096 execution. Type jobs.new? for details.
3098 3097
3099 3098 You can check the status of all jobs with jobs.status().
3100 3099
3101 3100 The jobs variable is set by IPython into the Python builtin namespace.
3102 3101 If you ever declare a variable named 'jobs', you will shadow this
3103 3102 name. You can either delete your global jobs variable to regain
3104 3103 access to the job manager, or make a new name and assign it manually
3105 3104 to the manager (stored in IPython's namespace). For example, to
3106 3105 assign the job manager to the Jobs name, use:
3107 3106
3108 3107 Jobs = __builtins__.jobs"""
3109 3108
3110 3109 self.shell.jobs.new(parameter_s,self.shell.user_ns)
3111 3110
3112 3111 def magic_r(self, parameter_s=''):
3113 3112 """Repeat previous input.
3114 3113
3115 3114 Note: Consider using the more powerfull %rep instead!
3116 3115
3117 3116 If given an argument, repeats the previous command which starts with
3118 3117 the same string, otherwise it just repeats the previous input.
3119 3118
3120 3119 Shell escaped commands (with ! as first character) are not recognized
3121 3120 by this system, only pure python code and magic commands.
3122 3121 """
3123 3122
3124 3123 start = parameter_s.strip()
3125 3124 esc_magic = self.shell.ESC_MAGIC
3126 3125 # Identify magic commands even if automagic is on (which means
3127 3126 # the in-memory version is different from that typed by the user).
3128 3127 if self.shell.rc.automagic:
3129 3128 start_magic = esc_magic+start
3130 3129 else:
3131 3130 start_magic = start
3132 3131 # Look through the input history in reverse
3133 3132 for n in range(len(self.shell.input_hist)-2,0,-1):
3134 3133 input = self.shell.input_hist[n]
3135 3134 # skip plain 'r' lines so we don't recurse to infinity
3136 3135 if input != '_ip.magic("r")\n' and \
3137 3136 (input.startswith(start) or input.startswith(start_magic)):
3138 3137 #print 'match',`input` # dbg
3139 3138 print 'Executing:',input,
3140 3139 self.shell.runlines(input)
3141 3140 return
3142 3141 print 'No previous input matching `%s` found.' % start
3143 3142
3144 3143
3145 3144 def magic_bookmark(self, parameter_s=''):
3146 3145 """Manage IPython's bookmark system.
3147 3146
3148 3147 %bookmark <name> - set bookmark to current dir
3149 3148 %bookmark <name> <dir> - set bookmark to <dir>
3150 3149 %bookmark -l - list all bookmarks
3151 3150 %bookmark -d <name> - remove bookmark
3152 3151 %bookmark -r - remove all bookmarks
3153 3152
3154 3153 You can later on access a bookmarked folder with:
3155 3154 %cd -b <name>
3156 3155 or simply '%cd <name>' if there is no directory called <name> AND
3157 3156 there is such a bookmark defined.
3158 3157
3159 3158 Your bookmarks persist through IPython sessions, but they are
3160 3159 associated with each profile."""
3161 3160
3162 3161 opts,args = self.parse_options(parameter_s,'drl',mode='list')
3163 3162 if len(args) > 2:
3164 3163 raise UsageError("%bookmark: too many arguments")
3165 3164
3166 3165 bkms = self.db.get('bookmarks',{})
3167 3166
3168 3167 if opts.has_key('d'):
3169 3168 try:
3170 3169 todel = args[0]
3171 3170 except IndexError:
3172 3171 raise UsageError(
3173 3172 "%bookmark -d: must provide a bookmark to delete")
3174 3173 else:
3175 3174 try:
3176 3175 del bkms[todel]
3177 3176 except KeyError:
3178 3177 raise UsageError(
3179 3178 "%%bookmark -d: Can't delete bookmark '%s'" % todel)
3180 3179
3181 3180 elif opts.has_key('r'):
3182 3181 bkms = {}
3183 3182 elif opts.has_key('l'):
3184 3183 bks = bkms.keys()
3185 3184 bks.sort()
3186 3185 if bks:
3187 3186 size = max(map(len,bks))
3188 3187 else:
3189 3188 size = 0
3190 3189 fmt = '%-'+str(size)+'s -> %s'
3191 3190 print 'Current bookmarks:'
3192 3191 for bk in bks:
3193 3192 print fmt % (bk,bkms[bk])
3194 3193 else:
3195 3194 if not args:
3196 3195 raise UsageError("%bookmark: You must specify the bookmark name")
3197 3196 elif len(args)==1:
3198 3197 bkms[args[0]] = os.getcwd()
3199 3198 elif len(args)==2:
3200 3199 bkms[args[0]] = args[1]
3201 3200 self.db['bookmarks'] = bkms
3202 3201
3203 3202 def magic_pycat(self, parameter_s=''):
3204 3203 """Show a syntax-highlighted file through a pager.
3205 3204
3206 3205 This magic is similar to the cat utility, but it will assume the file
3207 3206 to be Python source and will show it with syntax highlighting. """
3208 3207
3209 3208 try:
3210 3209 filename = get_py_filename(parameter_s)
3211 3210 cont = file_read(filename)
3212 3211 except IOError:
3213 3212 try:
3214 3213 cont = eval(parameter_s,self.user_ns)
3215 3214 except NameError:
3216 3215 cont = None
3217 3216 if cont is None:
3218 3217 print "Error: no such file or variable"
3219 3218 return
3220 3219
3221 3220 page(self.shell.pycolorize(cont),
3222 3221 screen_lines=self.shell.rc.screen_length)
3223 3222
3224 3223 def magic_cpaste(self, parameter_s=''):
3225 3224 """Allows you to paste & execute a pre-formatted code block from clipboard.
3226 3225
3227 3226 You must terminate the block with '--' (two minus-signs) alone on the
3228 3227 line. You can also provide your own sentinel with '%paste -s %%' ('%%'
3229 3228 is the new sentinel for this operation)
3230 3229
3231 3230 The block is dedented prior to execution to enable execution of method
3232 3231 definitions. '>' and '+' characters at the beginning of a line are
3233 3232 ignored, to allow pasting directly from e-mails, diff files and
3234 3233 doctests (the '...' continuation prompt is also stripped). The
3235 3234 executed block is also assigned to variable named 'pasted_block' for
3236 3235 later editing with '%edit pasted_block'.
3237 3236
3238 3237 You can also pass a variable name as an argument, e.g. '%cpaste foo'.
3239 3238 This assigns the pasted block to variable 'foo' as string, without
3240 3239 dedenting or executing it (preceding >>> and + is still stripped)
3241 3240
3242 3241 '%cpaste -r' re-executes the block previously entered by cpaste.
3243 3242
3244 3243 Do not be alarmed by garbled output on Windows (it's a readline bug).
3245 3244 Just press enter and type -- (and press enter again) and the block
3246 3245 will be what was just pasted.
3247 3246
3248 3247 IPython statements (magics, shell escapes) are not supported (yet).
3249 3248 """
3250 3249 opts,args = self.parse_options(parameter_s,'rs:',mode='string')
3251 3250 par = args.strip()
3252 3251 if opts.has_key('r'):
3253 3252 b = self.user_ns.get('pasted_block', None)
3254 3253 if b is None:
3255 3254 raise UsageError('No previous pasted block available')
3256 3255 print "Re-executing '%s...' (%d chars)"% (b.split('\n',1)[0], len(b))
3257 3256 exec b in self.user_ns
3258 3257 return
3259 3258
3260 3259 sentinel = opts.get('s','--')
3261 3260
3262 3261 # Regular expressions that declare text we strip from the input:
3263 3262 strip_re = [r'^\s*In \[\d+\]:', # IPython input prompt
3264 3263 r'^\s*(\s?>)+', # Python input prompt
3265 3264 r'^\s*\.{3,}', # Continuation prompts
3266 3265 r'^\++',
3267 3266 ]
3268 3267
3269 3268 strip_from_start = map(re.compile,strip_re)
3270 3269
3271 3270 from IPython import iplib
3272 3271 lines = []
3273 3272 print "Pasting code; enter '%s' alone on the line to stop." % sentinel
3274 3273 while 1:
3275 3274 l = iplib.raw_input_original(':')
3276 3275 if l ==sentinel:
3277 3276 break
3278 3277
3279 3278 for pat in strip_from_start:
3280 3279 l = pat.sub('',l)
3281 3280 lines.append(l)
3282 3281
3283 3282 block = "\n".join(lines) + '\n'
3284 3283 #print "block:\n",block
3285 3284 if not par:
3286 3285 b = textwrap.dedent(block)
3287 3286 self.user_ns['pasted_block'] = b
3288 3287 exec b in self.user_ns
3289 3288 else:
3290 3289 self.user_ns[par] = SList(block.splitlines())
3291 3290 print "Block assigned to '%s'" % par
3292 3291
3293 3292 def magic_quickref(self,arg):
3294 3293 """ Show a quick reference sheet """
3295 3294 import IPython.usage
3296 3295 qr = IPython.usage.quick_reference + self.magic_magic('-brief')
3297 3296
3298 3297 page(qr)
3299 3298
3300 3299 def magic_upgrade(self,arg):
3301 3300 """ Upgrade your IPython installation
3302 3301
3303 3302 This will copy the config files that don't yet exist in your
3304 3303 ipython dir from the system config dir. Use this after upgrading
3305 3304 IPython if you don't wish to delete your .ipython dir.
3306 3305
3307 3306 Call with -nolegacy to get rid of ipythonrc* files (recommended for
3308 3307 new users)
3309 3308
3310 3309 """
3311 3310 ip = self.getapi()
3312 3311 ipinstallation = path(IPython.__file__).dirname()
3313 3312 upgrade_script = '%s "%s"' % (sys.executable,ipinstallation / 'upgrade_dir.py')
3314 3313 src_config = ipinstallation / 'UserConfig'
3315 3314 userdir = path(ip.options.ipythondir)
3316 3315 cmd = '%s "%s" "%s"' % (upgrade_script, src_config, userdir)
3317 3316 print ">",cmd
3318 3317 shell(cmd)
3319 3318 if arg == '-nolegacy':
3320 3319 legacy = userdir.files('ipythonrc*')
3321 3320 print "Nuking legacy files:",legacy
3322 3321
3323 3322 [p.remove() for p in legacy]
3324 3323 suffix = (sys.platform == 'win32' and '.ini' or '')
3325 3324 (userdir / ('ipythonrc' + suffix)).write_text('# Empty, see ipy_user_conf.py\n')
3326 3325
3327 3326
3328 3327 def magic_doctest_mode(self,parameter_s=''):
3329 3328 """Toggle doctest mode on and off.
3330 3329
3331 3330 This mode allows you to toggle the prompt behavior between normal
3332 3331 IPython prompts and ones that are as similar to the default IPython
3333 3332 interpreter as possible.
3334 3333
3335 3334 It also supports the pasting of code snippets that have leading '>>>'
3336 3335 and '...' prompts in them. This means that you can paste doctests from
3337 3336 files or docstrings (even if they have leading whitespace), and the
3338 3337 code will execute correctly. You can then use '%history -tn' to see
3339 3338 the translated history without line numbers; this will give you the
3340 3339 input after removal of all the leading prompts and whitespace, which
3341 3340 can be pasted back into an editor.
3342 3341
3343 3342 With these features, you can switch into this mode easily whenever you
3344 3343 need to do testing and changes to doctests, without having to leave
3345 3344 your existing IPython session.
3346 3345 """
3347 3346
3348 3347 # XXX - Fix this to have cleaner activate/deactivate calls.
3349 3348 from IPython.Extensions import InterpreterPasteInput as ipaste
3350 3349 from IPython.ipstruct import Struct
3351 3350
3352 3351 # Shorthands
3353 3352 shell = self.shell
3354 3353 oc = shell.outputcache
3355 3354 rc = shell.rc
3356 3355 meta = shell.meta
3357 3356 # dstore is a data store kept in the instance metadata bag to track any
3358 3357 # changes we make, so we can undo them later.
3359 3358 dstore = meta.setdefault('doctest_mode',Struct())
3360 3359 save_dstore = dstore.setdefault
3361 3360
3362 3361 # save a few values we'll need to recover later
3363 3362 mode = save_dstore('mode',False)
3364 3363 save_dstore('rc_pprint',rc.pprint)
3365 3364 save_dstore('xmode',shell.InteractiveTB.mode)
3366 3365 save_dstore('rc_separate_out',rc.separate_out)
3367 3366 save_dstore('rc_separate_out2',rc.separate_out2)
3368 3367 save_dstore('rc_prompts_pad_left',rc.prompts_pad_left)
3369 3368 save_dstore('rc_separate_in',rc.separate_in)
3370 3369
3371 3370 if mode == False:
3372 3371 # turn on
3373 3372 ipaste.activate_prefilter()
3374 3373
3375 3374 oc.prompt1.p_template = '>>> '
3376 3375 oc.prompt2.p_template = '... '
3377 3376 oc.prompt_out.p_template = ''
3378 3377
3379 3378 # Prompt separators like plain python
3380 3379 oc.input_sep = oc.prompt1.sep = ''
3381 3380 oc.output_sep = ''
3382 3381 oc.output_sep2 = ''
3383 3382
3384 3383 oc.prompt1.pad_left = oc.prompt2.pad_left = \
3385 3384 oc.prompt_out.pad_left = False
3386 3385
3387 3386 rc.pprint = False
3388 3387
3389 3388 shell.magic_xmode('Plain')
3390 3389
3391 3390 else:
3392 3391 # turn off
3393 3392 ipaste.deactivate_prefilter()
3394 3393
3395 3394 oc.prompt1.p_template = rc.prompt_in1
3396 3395 oc.prompt2.p_template = rc.prompt_in2
3397 3396 oc.prompt_out.p_template = rc.prompt_out
3398 3397
3399 3398 oc.input_sep = oc.prompt1.sep = dstore.rc_separate_in
3400 3399
3401 3400 oc.output_sep = dstore.rc_separate_out
3402 3401 oc.output_sep2 = dstore.rc_separate_out2
3403 3402
3404 3403 oc.prompt1.pad_left = oc.prompt2.pad_left = \
3405 3404 oc.prompt_out.pad_left = dstore.rc_prompts_pad_left
3406 3405
3407 3406 rc.pprint = dstore.rc_pprint
3408 3407
3409 3408 shell.magic_xmode(dstore.xmode)
3410 3409
3411 3410 # Store new mode and inform
3412 3411 dstore.mode = bool(1-int(mode))
3413 3412 print 'Doctest mode is:',
3414 3413 print ['OFF','ON'][dstore.mode]
3415 3414
3416 3415 # end Magic
@@ -1,613 +1,607 b''
1 1 # -*- coding: utf-8 -*-
2 2 """Tools for inspecting Python objects.
3 3
4 4 Uses syntax highlighting for presenting the various information elements.
5 5
6 6 Similar in spirit to the inspect module, but all calls take a name argument to
7 7 reference the name under which an object is being read.
8
9 $Id: OInspect.py 2843 2007-10-15 21:22:32Z fperez $
10 8 """
11 9
12 10 #*****************************************************************************
13 11 # Copyright (C) 2001-2004 Fernando Perez <fperez@colorado.edu>
14 12 #
15 13 # Distributed under the terms of the BSD License. The full license is in
16 14 # the file COPYING, distributed as part of this software.
17 15 #*****************************************************************************
18 16
19 from IPython import Release
20 __author__ = '%s <%s>' % Release.authors['Fernando']
21 __license__ = Release.license
22
23 17 __all__ = ['Inspector','InspectColors']
24 18
25 19 # stdlib modules
26 20 import __builtin__
27 21 import StringIO
28 22 import inspect
29 23 import linecache
30 24 import os
31 25 import string
32 26 import sys
33 27 import types
34 28
35 29 # IPython's own
36 30 from IPython import PyColorize
37 31 from IPython.genutils import page,indent,Term
38 32 from IPython.Itpl import itpl
39 33 from IPython.wildcard import list_namespace
40 34 from IPython.ColorANSI import *
41 35
42 36 #****************************************************************************
43 37 # HACK!!! This is a crude fix for bugs in python 2.3's inspect module. We
44 38 # simply monkeypatch inspect with code copied from python 2.4.
45 39 if sys.version_info[:2] == (2,3):
46 40 from inspect import ismodule, getabsfile, modulesbyfile
47 41 def getmodule(object):
48 42 """Return the module an object was defined in, or None if not found."""
49 43 if ismodule(object):
50 44 return object
51 45 if hasattr(object, '__module__'):
52 46 return sys.modules.get(object.__module__)
53 47 try:
54 48 file = getabsfile(object)
55 49 except TypeError:
56 50 return None
57 51 if file in modulesbyfile:
58 52 return sys.modules.get(modulesbyfile[file])
59 53 for module in sys.modules.values():
60 54 if hasattr(module, '__file__'):
61 55 modulesbyfile[
62 56 os.path.realpath(
63 57 getabsfile(module))] = module.__name__
64 58 if file in modulesbyfile:
65 59 return sys.modules.get(modulesbyfile[file])
66 60 main = sys.modules['__main__']
67 61 if not hasattr(object, '__name__'):
68 62 return None
69 63 if hasattr(main, object.__name__):
70 64 mainobject = getattr(main, object.__name__)
71 65 if mainobject is object:
72 66 return main
73 67 builtin = sys.modules['__builtin__']
74 68 if hasattr(builtin, object.__name__):
75 69 builtinobject = getattr(builtin, object.__name__)
76 70 if builtinobject is object:
77 71 return builtin
78 72
79 73 inspect.getmodule = getmodule
80 74
81 75 #****************************************************************************
82 76 # Builtin color schemes
83 77
84 78 Colors = TermColors # just a shorthand
85 79
86 80 # Build a few color schemes
87 81 NoColor = ColorScheme(
88 82 'NoColor',{
89 83 'header' : Colors.NoColor,
90 84 'normal' : Colors.NoColor # color off (usu. Colors.Normal)
91 85 } )
92 86
93 87 LinuxColors = ColorScheme(
94 88 'Linux',{
95 89 'header' : Colors.LightRed,
96 90 'normal' : Colors.Normal # color off (usu. Colors.Normal)
97 91 } )
98 92
99 93 LightBGColors = ColorScheme(
100 94 'LightBG',{
101 95 'header' : Colors.Red,
102 96 'normal' : Colors.Normal # color off (usu. Colors.Normal)
103 97 } )
104 98
105 99 # Build table of color schemes (needed by the parser)
106 100 InspectColors = ColorSchemeTable([NoColor,LinuxColors,LightBGColors],
107 101 'Linux')
108 102
109 103 #****************************************************************************
110 104 # Auxiliary functions
111 105 def getdoc(obj):
112 106 """Stable wrapper around inspect.getdoc.
113 107
114 108 This can't crash because of attribute problems.
115 109
116 110 It also attempts to call a getdoc() method on the given object. This
117 111 allows objects which provide their docstrings via non-standard mechanisms
118 112 (like Pyro proxies) to still be inspected by ipython's ? system."""
119 113
120 114 ds = None # default return value
121 115 try:
122 116 ds = inspect.getdoc(obj)
123 117 except:
124 118 # Harden against an inspect failure, which can occur with
125 119 # SWIG-wrapped extensions.
126 120 pass
127 121 # Allow objects to offer customized documentation via a getdoc method:
128 122 try:
129 123 ds2 = obj.getdoc()
130 124 except:
131 125 pass
132 126 else:
133 127 # if we get extra info, we add it to the normal docstring.
134 128 if ds is None:
135 129 ds = ds2
136 130 else:
137 131 ds = '%s\n%s' % (ds,ds2)
138 132 return ds
139 133
140 134
141 135 def getsource(obj,is_binary=False):
142 136 """Wrapper around inspect.getsource.
143 137
144 138 This can be modified by other projects to provide customized source
145 139 extraction.
146 140
147 141 Inputs:
148 142
149 143 - obj: an object whose source code we will attempt to extract.
150 144
151 145 Optional inputs:
152 146
153 147 - is_binary: whether the object is known to come from a binary source.
154 148 This implementation will skip returning any output for binary objects, but
155 149 custom extractors may know how to meaningfully process them."""
156 150
157 151 if is_binary:
158 152 return None
159 153 else:
160 154 try:
161 155 src = inspect.getsource(obj)
162 156 except TypeError:
163 157 if hasattr(obj,'__class__'):
164 158 src = inspect.getsource(obj.__class__)
165 159 return src
166 160
167 161 def getargspec(obj):
168 162 """Get the names and default values of a function's arguments.
169 163
170 164 A tuple of four things is returned: (args, varargs, varkw, defaults).
171 165 'args' is a list of the argument names (it may contain nested lists).
172 166 'varargs' and 'varkw' are the names of the * and ** arguments or None.
173 167 'defaults' is an n-tuple of the default values of the last n arguments.
174 168
175 169 Modified version of inspect.getargspec from the Python Standard
176 170 Library."""
177 171
178 172 if inspect.isfunction(obj):
179 173 func_obj = obj
180 174 elif inspect.ismethod(obj):
181 175 func_obj = obj.im_func
182 176 else:
183 177 raise TypeError, 'arg is not a Python function'
184 178 args, varargs, varkw = inspect.getargs(func_obj.func_code)
185 179 return args, varargs, varkw, func_obj.func_defaults
186 180
187 181 #****************************************************************************
188 182 # Class definitions
189 183
190 184 class myStringIO(StringIO.StringIO):
191 185 """Adds a writeln method to normal StringIO."""
192 186 def writeln(self,*arg,**kw):
193 187 """Does a write() and then a write('\n')"""
194 188 self.write(*arg,**kw)
195 189 self.write('\n')
196 190
197 191
198 192 class Inspector:
199 193 def __init__(self,color_table,code_color_table,scheme,
200 194 str_detail_level=0):
201 195 self.color_table = color_table
202 196 self.parser = PyColorize.Parser(code_color_table,out='str')
203 197 self.format = self.parser.format
204 198 self.str_detail_level = str_detail_level
205 199 self.set_active_scheme(scheme)
206 200
207 201 def __getdef(self,obj,oname=''):
208 202 """Return the definition header for any callable object.
209 203
210 204 If any exception is generated, None is returned instead and the
211 205 exception is suppressed."""
212 206
213 207 try:
214 208 return oname + inspect.formatargspec(*getargspec(obj))
215 209 except:
216 210 return None
217 211
218 212 def __head(self,h):
219 213 """Return a header string with proper colors."""
220 214 return '%s%s%s' % (self.color_table.active_colors.header,h,
221 215 self.color_table.active_colors.normal)
222 216
223 217 def set_active_scheme(self,scheme):
224 218 self.color_table.set_active_scheme(scheme)
225 219 self.parser.color_table.set_active_scheme(scheme)
226 220
227 221 def noinfo(self,msg,oname):
228 222 """Generic message when no information is found."""
229 223 print 'No %s found' % msg,
230 224 if oname:
231 225 print 'for %s' % oname
232 226 else:
233 227 print
234 228
235 229 def pdef(self,obj,oname=''):
236 230 """Print the definition header for any callable object.
237 231
238 232 If the object is a class, print the constructor information."""
239 233
240 234 if not callable(obj):
241 235 print 'Object is not callable.'
242 236 return
243 237
244 238 header = ''
245 239
246 240 if inspect.isclass(obj):
247 241 header = self.__head('Class constructor information:\n')
248 242 obj = obj.__init__
249 243 elif type(obj) is types.InstanceType:
250 244 obj = obj.__call__
251 245
252 246 output = self.__getdef(obj,oname)
253 247 if output is None:
254 248 self.noinfo('definition header',oname)
255 249 else:
256 250 print >>Term.cout, header,self.format(output),
257 251
258 252 def pdoc(self,obj,oname='',formatter = None):
259 253 """Print the docstring for any object.
260 254
261 255 Optional:
262 256 -formatter: a function to run the docstring through for specially
263 257 formatted docstrings."""
264 258
265 259 head = self.__head # so that itpl can find it even if private
266 260 ds = getdoc(obj)
267 261 if formatter:
268 262 ds = formatter(ds)
269 263 if inspect.isclass(obj):
270 264 init_ds = getdoc(obj.__init__)
271 265 output = itpl('$head("Class Docstring:")\n'
272 266 '$indent(ds)\n'
273 267 '$head("Constructor Docstring"):\n'
274 268 '$indent(init_ds)')
275 269 elif (type(obj) is types.InstanceType or isinstance(obj,object)) \
276 270 and hasattr(obj,'__call__'):
277 271 call_ds = getdoc(obj.__call__)
278 272 if call_ds:
279 273 output = itpl('$head("Class Docstring:")\n$indent(ds)\n'
280 274 '$head("Calling Docstring:")\n$indent(call_ds)')
281 275 else:
282 276 output = ds
283 277 else:
284 278 output = ds
285 279 if output is None:
286 280 self.noinfo('documentation',oname)
287 281 return
288 282 page(output)
289 283
290 284 def psource(self,obj,oname=''):
291 285 """Print the source code for an object."""
292 286
293 287 # Flush the source cache because inspect can return out-of-date source
294 288 linecache.checkcache()
295 289 try:
296 290 src = getsource(obj)
297 291 except:
298 292 self.noinfo('source',oname)
299 293 else:
300 294 page(self.format(src))
301 295
302 296 def pfile(self,obj,oname=''):
303 297 """Show the whole file where an object was defined."""
304 298
305 299 try:
306 300 try:
307 301 lineno = inspect.getsourcelines(obj)[1]
308 302 except TypeError:
309 303 # For instances, try the class object like getsource() does
310 304 if hasattr(obj,'__class__'):
311 305 lineno = inspect.getsourcelines(obj.__class__)[1]
312 306 # Adjust the inspected object so getabsfile() below works
313 307 obj = obj.__class__
314 308 except:
315 309 self.noinfo('file',oname)
316 310 return
317 311
318 312 # We only reach this point if object was successfully queried
319 313
320 314 # run contents of file through pager starting at line
321 315 # where the object is defined
322 316 ofile = inspect.getabsfile(obj)
323 317
324 318 if (ofile.endswith('.so') or ofile.endswith('.dll')):
325 319 print 'File %r is binary, not printing.' % ofile
326 320 elif not os.path.isfile(ofile):
327 321 print 'File %r does not exist, not printing.' % ofile
328 322 else:
329 323 # Print only text files, not extension binaries. Note that
330 324 # getsourcelines returns lineno with 1-offset and page() uses
331 325 # 0-offset, so we must adjust.
332 326 page(self.format(open(ofile).read()),lineno-1)
333 327
334 328 def pinfo(self,obj,oname='',formatter=None,info=None,detail_level=0):
335 329 """Show detailed information about an object.
336 330
337 331 Optional arguments:
338 332
339 333 - oname: name of the variable pointing to the object.
340 334
341 335 - formatter: special formatter for docstrings (see pdoc)
342 336
343 337 - info: a structure with some information fields which may have been
344 338 precomputed already.
345 339
346 340 - detail_level: if set to 1, more information is given.
347 341 """
348 342
349 343 obj_type = type(obj)
350 344
351 345 header = self.__head
352 346 if info is None:
353 347 ismagic = 0
354 348 isalias = 0
355 349 ospace = ''
356 350 else:
357 351 ismagic = info.ismagic
358 352 isalias = info.isalias
359 353 ospace = info.namespace
360 354 # Get docstring, special-casing aliases:
361 355 if isalias:
362 356 if not callable(obj):
363 357 try:
364 358 ds = "Alias to the system command:\n %s" % obj[1]
365 359 except:
366 360 ds = "Alias: " + str(obj)
367 361 else:
368 362 ds = "Alias to " + str(obj)
369 363 if obj.__doc__:
370 364 ds += "\nDocstring:\n" + obj.__doc__
371 365 else:
372 366 ds = getdoc(obj)
373 367 if ds is None:
374 368 ds = '<no docstring>'
375 369 if formatter is not None:
376 370 ds = formatter(ds)
377 371
378 372 # store output in a list which gets joined with \n at the end.
379 373 out = myStringIO()
380 374
381 375 string_max = 200 # max size of strings to show (snipped if longer)
382 376 shalf = int((string_max -5)/2)
383 377
384 378 if ismagic:
385 379 obj_type_name = 'Magic function'
386 380 elif isalias:
387 381 obj_type_name = 'System alias'
388 382 else:
389 383 obj_type_name = obj_type.__name__
390 384 out.writeln(header('Type:\t\t')+obj_type_name)
391 385
392 386 try:
393 387 bclass = obj.__class__
394 388 out.writeln(header('Base Class:\t')+str(bclass))
395 389 except: pass
396 390
397 391 # String form, but snip if too long in ? form (full in ??)
398 392 if detail_level >= self.str_detail_level:
399 393 try:
400 394 ostr = str(obj)
401 395 str_head = 'String Form:'
402 396 if not detail_level and len(ostr)>string_max:
403 397 ostr = ostr[:shalf] + ' <...> ' + ostr[-shalf:]
404 398 ostr = ("\n" + " " * len(str_head.expandtabs())).\
405 399 join(map(string.strip,ostr.split("\n")))
406 400 if ostr.find('\n') > -1:
407 401 # Print multi-line strings starting at the next line.
408 402 str_sep = '\n'
409 403 else:
410 404 str_sep = '\t'
411 405 out.writeln("%s%s%s" % (header(str_head),str_sep,ostr))
412 406 except:
413 407 pass
414 408
415 409 if ospace:
416 410 out.writeln(header('Namespace:\t')+ospace)
417 411
418 412 # Length (for strings and lists)
419 413 try:
420 414 length = str(len(obj))
421 415 out.writeln(header('Length:\t\t')+length)
422 416 except: pass
423 417
424 418 # Filename where object was defined
425 419 binary_file = False
426 420 try:
427 421 try:
428 422 fname = inspect.getabsfile(obj)
429 423 except TypeError:
430 424 # For an instance, the file that matters is where its class was
431 425 # declared.
432 426 if hasattr(obj,'__class__'):
433 427 fname = inspect.getabsfile(obj.__class__)
434 428 if fname.endswith('<string>'):
435 429 fname = 'Dynamically generated function. No source code available.'
436 430 if (fname.endswith('.so') or fname.endswith('.dll')):
437 431 binary_file = True
438 432 out.writeln(header('File:\t\t')+fname)
439 433 except:
440 434 # if anything goes wrong, we don't want to show source, so it's as
441 435 # if the file was binary
442 436 binary_file = True
443 437
444 438 # reconstruct the function definition and print it:
445 439 defln = self.__getdef(obj,oname)
446 440 if defln:
447 441 out.write(header('Definition:\t')+self.format(defln))
448 442
449 443 # Docstrings only in detail 0 mode, since source contains them (we
450 444 # avoid repetitions). If source fails, we add them back, see below.
451 445 if ds and detail_level == 0:
452 446 out.writeln(header('Docstring:\n') + indent(ds))
453 447
454 448 # Original source code for any callable
455 449 if detail_level:
456 450 # Flush the source cache because inspect can return out-of-date
457 451 # source
458 452 linecache.checkcache()
459 453 source_success = False
460 454 try:
461 455 try:
462 456 src = getsource(obj,binary_file)
463 457 except TypeError:
464 458 if hasattr(obj,'__class__'):
465 459 src = getsource(obj.__class__,binary_file)
466 460 if src is not None:
467 461 source = self.format(src)
468 462 out.write(header('Source:\n')+source.rstrip())
469 463 source_success = True
470 464 except Exception, msg:
471 465 pass
472 466
473 467 if ds and not source_success:
474 468 out.writeln(header('Docstring [source file open failed]:\n')
475 469 + indent(ds))
476 470
477 471 # Constructor docstring for classes
478 472 if inspect.isclass(obj):
479 473 # reconstruct the function definition and print it:
480 474 try:
481 475 obj_init = obj.__init__
482 476 except AttributeError:
483 477 init_def = init_ds = None
484 478 else:
485 479 init_def = self.__getdef(obj_init,oname)
486 480 init_ds = getdoc(obj_init)
487 481 # Skip Python's auto-generated docstrings
488 482 if init_ds and \
489 483 init_ds.startswith('x.__init__(...) initializes'):
490 484 init_ds = None
491 485
492 486 if init_def or init_ds:
493 487 out.writeln(header('\nConstructor information:'))
494 488 if init_def:
495 489 out.write(header('Definition:\t')+ self.format(init_def))
496 490 if init_ds:
497 491 out.writeln(header('Docstring:\n') + indent(init_ds))
498 492 # and class docstring for instances:
499 493 elif obj_type is types.InstanceType or \
500 494 isinstance(obj,object):
501 495
502 496 # First, check whether the instance docstring is identical to the
503 497 # class one, and print it separately if they don't coincide. In
504 498 # most cases they will, but it's nice to print all the info for
505 499 # objects which use instance-customized docstrings.
506 500 if ds:
507 501 try:
508 502 cls = getattr(obj,'__class__')
509 503 except:
510 504 class_ds = None
511 505 else:
512 506 class_ds = getdoc(cls)
513 507 # Skip Python's auto-generated docstrings
514 508 if class_ds and \
515 509 (class_ds.startswith('function(code, globals[,') or \
516 510 class_ds.startswith('instancemethod(function, instance,') or \
517 511 class_ds.startswith('module(name[,') ):
518 512 class_ds = None
519 513 if class_ds and ds != class_ds:
520 514 out.writeln(header('Class Docstring:\n') +
521 515 indent(class_ds))
522 516
523 517 # Next, try to show constructor docstrings
524 518 try:
525 519 init_ds = getdoc(obj.__init__)
526 520 # Skip Python's auto-generated docstrings
527 521 if init_ds and \
528 522 init_ds.startswith('x.__init__(...) initializes'):
529 523 init_ds = None
530 524 except AttributeError:
531 525 init_ds = None
532 526 if init_ds:
533 527 out.writeln(header('Constructor Docstring:\n') +
534 528 indent(init_ds))
535 529
536 530 # Call form docstring for callable instances
537 531 if hasattr(obj,'__call__'):
538 532 #out.writeln(header('Callable:\t')+'Yes')
539 533 call_def = self.__getdef(obj.__call__,oname)
540 534 #if call_def is None:
541 535 # out.writeln(header('Call def:\t')+
542 536 # 'Calling definition not available.')
543 537 if call_def is not None:
544 538 out.writeln(header('Call def:\t')+self.format(call_def))
545 539 call_ds = getdoc(obj.__call__)
546 540 # Skip Python's auto-generated docstrings
547 541 if call_ds and call_ds.startswith('x.__call__(...) <==> x(...)'):
548 542 call_ds = None
549 543 if call_ds:
550 544 out.writeln(header('Call docstring:\n') + indent(call_ds))
551 545
552 546 # Finally send to printer/pager
553 547 output = out.getvalue()
554 548 if output:
555 549 page(output)
556 550 # end pinfo
557 551
558 552 def psearch(self,pattern,ns_table,ns_search=[],
559 553 ignore_case=False,show_all=False):
560 554 """Search namespaces with wildcards for objects.
561 555
562 556 Arguments:
563 557
564 558 - pattern: string containing shell-like wildcards to use in namespace
565 559 searches and optionally a type specification to narrow the search to
566 560 objects of that type.
567 561
568 562 - ns_table: dict of name->namespaces for search.
569 563
570 564 Optional arguments:
571 565
572 566 - ns_search: list of namespace names to include in search.
573 567
574 568 - ignore_case(False): make the search case-insensitive.
575 569
576 570 - show_all(False): show all names, including those starting with
577 571 underscores.
578 572 """
579 573 #print 'ps pattern:<%r>' % pattern # dbg
580 574
581 575 # defaults
582 576 type_pattern = 'all'
583 577 filter = ''
584 578
585 579 cmds = pattern.split()
586 580 len_cmds = len(cmds)
587 581 if len_cmds == 1:
588 582 # Only filter pattern given
589 583 filter = cmds[0]
590 584 elif len_cmds == 2:
591 585 # Both filter and type specified
592 586 filter,type_pattern = cmds
593 587 else:
594 588 raise ValueError('invalid argument string for psearch: <%s>' %
595 589 pattern)
596 590
597 591 # filter search namespaces
598 592 for name in ns_search:
599 593 if name not in ns_table:
600 594 raise ValueError('invalid namespace <%s>. Valid names: %s' %
601 595 (name,ns_table.keys()))
602 596
603 597 #print 'type_pattern:',type_pattern # dbg
604 598 search_result = []
605 599 for ns_name in ns_search:
606 600 ns = ns_table[ns_name]
607 601 tmp_res = list(list_namespace(ns,type_pattern,filter,
608 602 ignore_case=ignore_case,
609 603 show_all=show_all))
610 604 search_result.extend(tmp_res)
611 605 search_result.sort()
612 606
613 607 page('\n'.join(search_result))
@@ -1,263 +1,258 b''
1 1 # -*- coding: utf-8 -*-
2 2 """Class to trap stdout and stderr and log them separately.
3
4 $Id: OutputTrap.py 958 2005-12-27 23:17:51Z fperez $"""
3 """
5 4
6 5 #*****************************************************************************
7 6 # Copyright (C) 2001-2004 Fernando Perez <fperez@colorado.edu>
8 7 #
9 8 # Distributed under the terms of the BSD License. The full license is in
10 9 # the file COPYING, distributed as part of this software.
11 10 #*****************************************************************************
12 11
13 from IPython import Release
14 __author__ = '%s <%s>' % Release.authors['Fernando']
15 __license__ = Release.license
16
17 12 import exceptions
18 13 import sys
19 14 from cStringIO import StringIO
20 15
21 16 class OutputTrapError(exceptions.Exception):
22 17 """Exception for OutputTrap class."""
23 18
24 19 def __init__(self,args=None):
25 20 exceptions.Exception.__init__(self)
26 21 self.args = args
27 22
28 23 class OutputTrap:
29 24
30 25 """Class to trap standard output and standard error. They get logged in
31 26 StringIO objects which are available as <instance>.out and
32 27 <instance>.err. The class also offers summary methods which format this
33 28 data a bit.
34 29
35 30 A word of caution: because it blocks messages, using this class can make
36 31 debugging very tricky. If you are having bizarre problems silently, try
37 32 turning your output traps off for a while. You can call the constructor
38 33 with the parameter debug=1 for these cases. This turns actual trapping
39 34 off, but you can keep the rest of your code unchanged (this has already
40 35 been a life saver).
41 36
42 37 Example:
43 38
44 39 # config: trapper with a line of dots as log separator (final '\\n' needed)
45 40 config = OutputTrap('Config','Out ','Err ','.'*80+'\\n')
46 41
47 42 # start trapping output
48 43 config.trap_all()
49 44
50 45 # now all output is logged ...
51 46 # do stuff...
52 47
53 48 # output back to normal:
54 49 config.release_all()
55 50
56 51 # print all that got logged:
57 52 print config.summary()
58 53
59 54 # print individual raw data:
60 55 print config.out.getvalue()
61 56 print config.err.getvalue()
62 57 """
63 58
64 59 def __init__(self,name='Generic Output Trap',
65 60 out_head='Standard Output. ',err_head='Standard Error. ',
66 61 sum_sep='\n',debug=0,trap_out=0,trap_err=0,
67 62 quiet_out=0,quiet_err=0):
68 63 self.name = name
69 64 self.out_head = out_head
70 65 self.err_head = err_head
71 66 self.sum_sep = sum_sep
72 67 self.out = StringIO()
73 68 self.err = StringIO()
74 69 self.out_save = None
75 70 self.err_save = None
76 71 self.debug = debug
77 72 self.quiet_out = quiet_out
78 73 self.quiet_err = quiet_err
79 74 if trap_out:
80 75 self.trap_out()
81 76 if trap_err:
82 77 self.trap_err()
83 78
84 79 def trap_out(self):
85 80 """Trap and log stdout."""
86 81 if sys.stdout is self.out:
87 82 raise OutputTrapError,'You are already trapping stdout.'
88 83 if not self.debug:
89 84 self._out_save = sys.stdout
90 85 sys.stdout = self.out
91 86
92 87 def release_out(self):
93 88 """Release stdout."""
94 89 if not self.debug:
95 90 if not sys.stdout is self.out:
96 91 raise OutputTrapError,'You are not trapping stdout.'
97 92 sys.stdout = self._out_save
98 93 self.out_save = None
99 94
100 95 def summary_out(self):
101 96 """Return as a string the log from stdout."""
102 97 out = self.out.getvalue()
103 98 if out:
104 99 if self.quiet_out:
105 100 return out
106 101 else:
107 102 return self.out_head + 'Log by '+ self.name + ':\n' + out
108 103 else:
109 104 return ''
110 105
111 106 def flush_out(self):
112 107 """Flush the stdout log. All data held in the log is lost."""
113 108
114 109 self.out.close()
115 110 self.out = StringIO()
116 111
117 112 def trap_err(self):
118 113 """Trap and log stderr."""
119 114 if sys.stderr is self.err:
120 115 raise OutputTrapError,'You are already trapping stderr.'
121 116 if not self.debug:
122 117 self._err_save = sys.stderr
123 118 sys.stderr = self.err
124 119
125 120 def release_err(self):
126 121 """Release stderr."""
127 122 if not self.debug:
128 123 if not sys.stderr is self.err:
129 124 raise OutputTrapError,'You are not trapping stderr.'
130 125 sys.stderr = self._err_save
131 126 self.err_save = None
132 127
133 128 def summary_err(self):
134 129 """Return as a string the log from stderr."""
135 130 err = self.err.getvalue()
136 131 if err:
137 132 if self.quiet_err:
138 133 return err
139 134 else:
140 135 return self.err_head + 'Log by '+ self.name + ':\n' + err
141 136 else:
142 137 return ''
143 138
144 139 def flush_err(self):
145 140 """Flush the stdout log. All data held in the log is lost."""
146 141
147 142 self.err.close()
148 143 self.err = StringIO()
149 144
150 145 def trap_all(self):
151 146 """Trap and log both stdout and stderr.
152 147
153 148 Cacthes and discards OutputTrapError exceptions raised."""
154 149 try:
155 150 self.trap_out()
156 151 except OutputTrapError:
157 152 pass
158 153 try:
159 154 self.trap_err()
160 155 except OutputTrapError:
161 156 pass
162 157
163 158 def release_all(self):
164 159 """Release both stdout and stderr.
165 160
166 161 Cacthes and discards OutputTrapError exceptions raised."""
167 162 try:
168 163 self.release_out()
169 164 except OutputTrapError:
170 165 pass
171 166 try:
172 167 self.release_err()
173 168 except OutputTrapError:
174 169 pass
175 170
176 171 def summary_all(self):
177 172 """Return as a string the log from stdout and stderr, prepending a separator
178 173 to each (defined in __init__ as sum_sep)."""
179 174 sum = ''
180 175 sout = self.summary_out()
181 176 if sout:
182 177 sum += self.sum_sep + sout
183 178 serr = self.summary_err()
184 179 if serr:
185 180 sum += '\n'+self.sum_sep + serr
186 181 return sum
187 182
188 183 def flush_all(self):
189 184 """Flush stdout and stderr"""
190 185 self.flush_out()
191 186 self.flush_err()
192 187
193 188 # a few shorthands
194 189 trap = trap_all
195 190 release = release_all
196 191 summary = summary_all
197 192 flush = flush_all
198 193 # end OutputTrap
199 194
200 195
201 196 #****************************************************************************
202 197 # Module testing. Incomplete, I'm lazy...
203 198
204 199 def _test_all():
205 200
206 201 """Module testing functions, activated when the module is called as a
207 202 script (not imported)."""
208 203
209 204 # Put tests for this module in here.
210 205 # Define them as nested functions so they don't clobber the
211 206 # pydoc-generated docs
212 207
213 208 def _test_():
214 209 name = ''
215 210 print '#'*50+'\nRunning test for ' + name
216 211 # ...
217 212 print 'Finished test for '+ name +'\n'+'#'*50
218 213
219 214 def _test_OutputTrap():
220 215 trap = OutputTrap(name = 'Test Trap', sum_sep = '.'*50+'\n',
221 216 out_head = 'SOut. ', err_head = 'SErr. ')
222 217
223 218 name = 'OutputTrap class'
224 219 print '#'*50+'\nRunning test for ' + name
225 220 print 'Trapping out'
226 221 trap.trap_out()
227 222 print >>sys.stdout, '>>stdout. stdout is trapped.'
228 223 print >>sys.stderr, '>>stderr. stdout is trapped.'
229 224 trap.release_out()
230 225 print trap.summary_out()
231 226
232 227 print 'Trapping err'
233 228 trap.trap_err()
234 229 print >>sys.stdout, '>>stdout. stderr is trapped.'
235 230 print >>sys.stderr, '>>stderr. stderr is trapped.'
236 231 trap.release_err()
237 232 print trap.summary_err()
238 233
239 234 print 'Trapping all (no flushing)'
240 235 trap.trap_all()
241 236 print >>sys.stdout, '>>stdout. stdout/err is trapped.'
242 237 print >>sys.stderr, '>>stderr. stdout/err is trapped.'
243 238 trap.release_all()
244 239 print trap.summary_all()
245 240
246 241 print 'Trapping all (flushing first)'
247 242 trap.flush()
248 243 trap.trap_all()
249 244 print >>sys.stdout, '>>stdout. stdout/err is trapped.'
250 245 print >>sys.stderr, '>>stderr. stdout/err is trapped.'
251 246 trap.release_all()
252 247 print trap.summary_all()
253 248 print 'Finished test for '+ name +'\n'+'#'*50
254 249
255 250 # call the actual tests here:
256 251 _test_OutputTrap()
257 252
258 253
259 254 if __name__=="__main__":
260 255 # _test_all() # XXX BROKEN.
261 256 pass
262 257
263 258 #************************ end of file <OutputTrap.py> ************************
@@ -1,625 +1,624 b''
1 1 # -*- coding: utf-8 -*-
2 2 """
3 3 Classes for handling input/output prompts.
4
5 $Id: Prompts.py 3026 2008-02-07 16:03:16Z vivainio $"""
4 """
6 5
7 6 #*****************************************************************************
8 7 # Copyright (C) 2001-2006 Fernando Perez <fperez@colorado.edu>
9 8 #
10 9 # Distributed under the terms of the BSD License. The full license is in
11 10 # the file COPYING, distributed as part of this software.
12 11 #*****************************************************************************
13 12
14 13 from IPython import Release
15 14 __author__ = '%s <%s>' % Release.authors['Fernando']
16 15 __license__ = Release.license
17 16 __version__ = Release.version
18 17
19 18 #****************************************************************************
20 19 # Required modules
21 20 import __builtin__
22 21 import os
23 22 import socket
24 23 import sys
25 24 import time
26 25
27 26 # IPython's own
28 27 from IPython import ColorANSI
29 28 from IPython.Itpl import ItplNS
30 29 from IPython.ipstruct import Struct
31 30 from IPython.macro import Macro
32 31 from IPython.genutils import *
33 32 from IPython.ipapi import TryNext
34 33
35 34 #****************************************************************************
36 35 #Color schemes for Prompts.
37 36
38 37 PromptColors = ColorANSI.ColorSchemeTable()
39 38 InputColors = ColorANSI.InputTermColors # just a shorthand
40 39 Colors = ColorANSI.TermColors # just a shorthand
41 40
42 41 PromptColors.add_scheme(ColorANSI.ColorScheme(
43 42 'NoColor',
44 43 in_prompt = InputColors.NoColor, # Input prompt
45 44 in_number = InputColors.NoColor, # Input prompt number
46 45 in_prompt2 = InputColors.NoColor, # Continuation prompt
47 46 in_normal = InputColors.NoColor, # color off (usu. Colors.Normal)
48 47
49 48 out_prompt = Colors.NoColor, # Output prompt
50 49 out_number = Colors.NoColor, # Output prompt number
51 50
52 51 normal = Colors.NoColor # color off (usu. Colors.Normal)
53 52 ))
54 53
55 54 # make some schemes as instances so we can copy them for modification easily:
56 55 __PColLinux = ColorANSI.ColorScheme(
57 56 'Linux',
58 57 in_prompt = InputColors.Green,
59 58 in_number = InputColors.LightGreen,
60 59 in_prompt2 = InputColors.Green,
61 60 in_normal = InputColors.Normal, # color off (usu. Colors.Normal)
62 61
63 62 out_prompt = Colors.Red,
64 63 out_number = Colors.LightRed,
65 64
66 65 normal = Colors.Normal
67 66 )
68 67 # Don't forget to enter it into the table!
69 68 PromptColors.add_scheme(__PColLinux)
70 69
71 70 # Slightly modified Linux for light backgrounds
72 71 __PColLightBG = __PColLinux.copy('LightBG')
73 72
74 73 __PColLightBG.colors.update(
75 74 in_prompt = InputColors.Blue,
76 75 in_number = InputColors.LightBlue,
77 76 in_prompt2 = InputColors.Blue
78 77 )
79 78 PromptColors.add_scheme(__PColLightBG)
80 79
81 80 del Colors,InputColors
82 81
83 82 #-----------------------------------------------------------------------------
84 83 def multiple_replace(dict, text):
85 84 """ Replace in 'text' all occurences of any key in the given
86 85 dictionary by its corresponding value. Returns the new string."""
87 86
88 87 # Function by Xavier Defrang, originally found at:
89 88 # http://aspn.activestate.com/ASPN/Cookbook/Python/Recipe/81330
90 89
91 90 # Create a regular expression from the dictionary keys
92 91 regex = re.compile("(%s)" % "|".join(map(re.escape, dict.keys())))
93 92 # For each match, look-up corresponding value in dictionary
94 93 return regex.sub(lambda mo: dict[mo.string[mo.start():mo.end()]], text)
95 94
96 95 #-----------------------------------------------------------------------------
97 96 # Special characters that can be used in prompt templates, mainly bash-like
98 97
99 98 # If $HOME isn't defined (Windows), make it an absurd string so that it can
100 99 # never be expanded out into '~'. Basically anything which can never be a
101 100 # reasonable directory name will do, we just want the $HOME -> '~' operation
102 101 # to become a no-op. We pre-compute $HOME here so it's not done on every
103 102 # prompt call.
104 103
105 104 # FIXME:
106 105
107 106 # - This should be turned into a class which does proper namespace management,
108 107 # since the prompt specials need to be evaluated in a certain namespace.
109 108 # Currently it's just globals, which need to be managed manually by code
110 109 # below.
111 110
112 111 # - I also need to split up the color schemes from the prompt specials
113 112 # somehow. I don't have a clean design for that quite yet.
114 113
115 114 HOME = os.environ.get("HOME","//////:::::ZZZZZ,,,~~~")
116 115
117 116 # We precompute a few more strings here for the prompt_specials, which are
118 117 # fixed once ipython starts. This reduces the runtime overhead of computing
119 118 # prompt strings.
120 119 USER = os.environ.get("USER")
121 120 HOSTNAME = socket.gethostname()
122 121 HOSTNAME_SHORT = HOSTNAME.split(".")[0]
123 122 ROOT_SYMBOL = "$#"[os.name=='nt' or os.getuid()==0]
124 123
125 124 prompt_specials_color = {
126 125 # Prompt/history count
127 126 '%n' : '${self.col_num}' '${self.cache.prompt_count}' '${self.col_p}',
128 127 r'\#': '${self.col_num}' '${self.cache.prompt_count}' '${self.col_p}',
129 128 # Just the prompt counter number, WITHOUT any coloring wrappers, so users
130 129 # can get numbers displayed in whatever color they want.
131 130 r'\N': '${self.cache.prompt_count}',
132 131 # Prompt/history count, with the actual digits replaced by dots. Used
133 132 # mainly in continuation prompts (prompt_in2)
134 133 r'\D': '${"."*len(str(self.cache.prompt_count))}',
135 134 # Current working directory
136 135 r'\w': '${os.getcwd()}',
137 136 # Current time
138 137 r'\t' : '${time.strftime("%H:%M:%S")}',
139 138 # Basename of current working directory.
140 139 # (use os.sep to make this portable across OSes)
141 140 r'\W' : '${os.getcwd().split("%s")[-1]}' % os.sep,
142 141 # These X<N> are an extension to the normal bash prompts. They return
143 142 # N terms of the path, after replacing $HOME with '~'
144 143 r'\X0': '${os.getcwd().replace("%s","~")}' % HOME,
145 144 r'\X1': '${self.cwd_filt(1)}',
146 145 r'\X2': '${self.cwd_filt(2)}',
147 146 r'\X3': '${self.cwd_filt(3)}',
148 147 r'\X4': '${self.cwd_filt(4)}',
149 148 r'\X5': '${self.cwd_filt(5)}',
150 149 # Y<N> are similar to X<N>, but they show '~' if it's the directory
151 150 # N+1 in the list. Somewhat like %cN in tcsh.
152 151 r'\Y0': '${self.cwd_filt2(0)}',
153 152 r'\Y1': '${self.cwd_filt2(1)}',
154 153 r'\Y2': '${self.cwd_filt2(2)}',
155 154 r'\Y3': '${self.cwd_filt2(3)}',
156 155 r'\Y4': '${self.cwd_filt2(4)}',
157 156 r'\Y5': '${self.cwd_filt2(5)}',
158 157 # Hostname up to first .
159 158 r'\h': HOSTNAME_SHORT,
160 159 # Full hostname
161 160 r'\H': HOSTNAME,
162 161 # Username of current user
163 162 r'\u': USER,
164 163 # Escaped '\'
165 164 '\\\\': '\\',
166 165 # Newline
167 166 r'\n': '\n',
168 167 # Carriage return
169 168 r'\r': '\r',
170 169 # Release version
171 170 r'\v': __version__,
172 171 # Root symbol ($ or #)
173 172 r'\$': ROOT_SYMBOL,
174 173 }
175 174
176 175 # A copy of the prompt_specials dictionary but with all color escapes removed,
177 176 # so we can correctly compute the prompt length for the auto_rewrite method.
178 177 prompt_specials_nocolor = prompt_specials_color.copy()
179 178 prompt_specials_nocolor['%n'] = '${self.cache.prompt_count}'
180 179 prompt_specials_nocolor[r'\#'] = '${self.cache.prompt_count}'
181 180
182 181 # Add in all the InputTermColors color escapes as valid prompt characters.
183 182 # They all get added as \\C_COLORNAME, so that we don't have any conflicts
184 183 # with a color name which may begin with a letter used by any other of the
185 184 # allowed specials. This of course means that \\C will never be allowed for
186 185 # anything else.
187 186 input_colors = ColorANSI.InputTermColors
188 187 for _color in dir(input_colors):
189 188 if _color[0] != '_':
190 189 c_name = r'\C_'+_color
191 190 prompt_specials_color[c_name] = getattr(input_colors,_color)
192 191 prompt_specials_nocolor[c_name] = ''
193 192
194 193 # we default to no color for safety. Note that prompt_specials is a global
195 194 # variable used by all prompt objects.
196 195 prompt_specials = prompt_specials_nocolor
197 196
198 197 #-----------------------------------------------------------------------------
199 198 def str_safe(arg):
200 199 """Convert to a string, without ever raising an exception.
201 200
202 201 If str(arg) fails, <ERROR: ... > is returned, where ... is the exception
203 202 error message."""
204 203
205 204 try:
206 205 out = str(arg)
207 206 except UnicodeError:
208 207 try:
209 208 out = arg.encode('utf_8','replace')
210 209 except Exception,msg:
211 210 # let's keep this little duplication here, so that the most common
212 211 # case doesn't suffer from a double try wrapping.
213 212 out = '<ERROR: %s>' % msg
214 213 except Exception,msg:
215 214 out = '<ERROR: %s>' % msg
216 215 return out
217 216
218 217 class BasePrompt(object):
219 218 """Interactive prompt similar to Mathematica's."""
220 219
221 220 def _get_p_template(self):
222 221 return self._p_template
223 222
224 223 def _set_p_template(self,val):
225 224 self._p_template = val
226 225 self.set_p_str()
227 226
228 227 p_template = property(_get_p_template,_set_p_template,
229 228 doc='Template for prompt string creation')
230 229
231 230 def __init__(self,cache,sep,prompt,pad_left=False):
232 231
233 232 # Hack: we access information about the primary prompt through the
234 233 # cache argument. We need this, because we want the secondary prompt
235 234 # to be aligned with the primary one. Color table info is also shared
236 235 # by all prompt classes through the cache. Nice OO spaghetti code!
237 236 self.cache = cache
238 237 self.sep = sep
239 238
240 239 # regexp to count the number of spaces at the end of a prompt
241 240 # expression, useful for prompt auto-rewriting
242 241 self.rspace = re.compile(r'(\s*)$')
243 242 # Flag to left-pad prompt strings to match the length of the primary
244 243 # prompt
245 244 self.pad_left = pad_left
246 245
247 246 # Set template to create each actual prompt (where numbers change).
248 247 # Use a property
249 248 self.p_template = prompt
250 249 self.set_p_str()
251 250
252 251 def set_p_str(self):
253 252 """ Set the interpolating prompt strings.
254 253
255 254 This must be called every time the color settings change, because the
256 255 prompt_specials global may have changed."""
257 256
258 257 import os,time # needed in locals for prompt string handling
259 258 loc = locals()
260 259 try:
261 260 self.p_str = ItplNS('%s%s%s' %
262 261 ('${self.sep}${self.col_p}',
263 262 multiple_replace(prompt_specials, self.p_template),
264 263 '${self.col_norm}'),self.cache.user_ns,loc)
265 264
266 265 self.p_str_nocolor = ItplNS(multiple_replace(prompt_specials_nocolor,
267 266 self.p_template),
268 267 self.cache.user_ns,loc)
269 268 except:
270 269 print "Illegal prompt template (check $ usage!):",self.p_template
271 270 self.p_str = self.p_template
272 271 self.p_str_nocolor = self.p_template
273 272
274 273 def write(self,msg): # dbg
275 274 sys.stdout.write(msg)
276 275 return ''
277 276
278 277 def __str__(self):
279 278 """Return a string form of the prompt.
280 279
281 280 This for is useful for continuation and output prompts, since it is
282 281 left-padded to match lengths with the primary one (if the
283 282 self.pad_left attribute is set)."""
284 283
285 284 out_str = str_safe(self.p_str)
286 285 if self.pad_left:
287 286 # We must find the amount of padding required to match lengths,
288 287 # taking the color escapes (which are invisible on-screen) into
289 288 # account.
290 289 esc_pad = len(out_str) - len(str_safe(self.p_str_nocolor))
291 290 format = '%%%ss' % (len(str(self.cache.last_prompt))+esc_pad)
292 291 return format % out_str
293 292 else:
294 293 return out_str
295 294
296 295 # these path filters are put in as methods so that we can control the
297 296 # namespace where the prompt strings get evaluated
298 297 def cwd_filt(self,depth):
299 298 """Return the last depth elements of the current working directory.
300 299
301 300 $HOME is always replaced with '~'.
302 301 If depth==0, the full path is returned."""
303 302
304 303 cwd = os.getcwd().replace(HOME,"~")
305 304 out = os.sep.join(cwd.split(os.sep)[-depth:])
306 305 if out:
307 306 return out
308 307 else:
309 308 return os.sep
310 309
311 310 def cwd_filt2(self,depth):
312 311 """Return the last depth elements of the current working directory.
313 312
314 313 $HOME is always replaced with '~'.
315 314 If depth==0, the full path is returned."""
316 315
317 316 full_cwd = os.getcwd()
318 317 cwd = full_cwd.replace(HOME,"~").split(os.sep)
319 318 if '~' in cwd and len(cwd) == depth+1:
320 319 depth += 1
321 320 drivepart = ''
322 321 if sys.platform == 'win32' and len(cwd) > depth:
323 322 drivepart = os.path.splitdrive(full_cwd)[0]
324 323 out = drivepart + '/'.join(cwd[-depth:])
325 324
326 325 if out:
327 326 return out
328 327 else:
329 328 return os.sep
330 329
331 330 def __nonzero__(self):
332 331 """Implement boolean behavior.
333 332
334 333 Checks whether the p_str attribute is non-empty"""
335 334
336 335 return bool(self.p_template)
337 336
338 337 class Prompt1(BasePrompt):
339 338 """Input interactive prompt similar to Mathematica's."""
340 339
341 340 def __init__(self,cache,sep='\n',prompt='In [\\#]: ',pad_left=True):
342 341 BasePrompt.__init__(self,cache,sep,prompt,pad_left)
343 342
344 343 def set_colors(self):
345 344 self.set_p_str()
346 345 Colors = self.cache.color_table.active_colors # shorthand
347 346 self.col_p = Colors.in_prompt
348 347 self.col_num = Colors.in_number
349 348 self.col_norm = Colors.in_normal
350 349 # We need a non-input version of these escapes for the '--->'
351 350 # auto-call prompts used in the auto_rewrite() method.
352 351 self.col_p_ni = self.col_p.replace('\001','').replace('\002','')
353 352 self.col_norm_ni = Colors.normal
354 353
355 354 def __str__(self):
356 355 self.cache.prompt_count += 1
357 356 self.cache.last_prompt = str_safe(self.p_str_nocolor).split('\n')[-1]
358 357 return str_safe(self.p_str)
359 358
360 359 def auto_rewrite(self):
361 360 """Print a string of the form '--->' which lines up with the previous
362 361 input string. Useful for systems which re-write the user input when
363 362 handling automatically special syntaxes."""
364 363
365 364 curr = str(self.cache.last_prompt)
366 365 nrspaces = len(self.rspace.search(curr).group())
367 366 return '%s%s>%s%s' % (self.col_p_ni,'-'*(len(curr)-nrspaces-1),
368 367 ' '*nrspaces,self.col_norm_ni)
369 368
370 369 class PromptOut(BasePrompt):
371 370 """Output interactive prompt similar to Mathematica's."""
372 371
373 372 def __init__(self,cache,sep='',prompt='Out[\\#]: ',pad_left=True):
374 373 BasePrompt.__init__(self,cache,sep,prompt,pad_left)
375 374 if not self.p_template:
376 375 self.__str__ = lambda: ''
377 376
378 377 def set_colors(self):
379 378 self.set_p_str()
380 379 Colors = self.cache.color_table.active_colors # shorthand
381 380 self.col_p = Colors.out_prompt
382 381 self.col_num = Colors.out_number
383 382 self.col_norm = Colors.normal
384 383
385 384 class Prompt2(BasePrompt):
386 385 """Interactive continuation prompt."""
387 386
388 387 def __init__(self,cache,prompt=' .\\D.: ',pad_left=True):
389 388 self.cache = cache
390 389 self.p_template = prompt
391 390 self.pad_left = pad_left
392 391 self.set_p_str()
393 392
394 393 def set_p_str(self):
395 394 import os,time # needed in locals for prompt string handling
396 395 loc = locals()
397 396 self.p_str = ItplNS('%s%s%s' %
398 397 ('${self.col_p2}',
399 398 multiple_replace(prompt_specials, self.p_template),
400 399 '$self.col_norm'),
401 400 self.cache.user_ns,loc)
402 401 self.p_str_nocolor = ItplNS(multiple_replace(prompt_specials_nocolor,
403 402 self.p_template),
404 403 self.cache.user_ns,loc)
405 404
406 405 def set_colors(self):
407 406 self.set_p_str()
408 407 Colors = self.cache.color_table.active_colors
409 408 self.col_p2 = Colors.in_prompt2
410 409 self.col_norm = Colors.in_normal
411 410 # FIXME (2004-06-16) HACK: prevent crashes for users who haven't
412 411 # updated their prompt_in2 definitions. Remove eventually.
413 412 self.col_p = Colors.out_prompt
414 413 self.col_num = Colors.out_number
415 414
416 415
417 416 #-----------------------------------------------------------------------------
418 417 class CachedOutput:
419 418 """Class for printing output from calculations while keeping a cache of
420 419 reults. It dynamically creates global variables prefixed with _ which
421 420 contain these results.
422 421
423 422 Meant to be used as a sys.displayhook replacement, providing numbered
424 423 prompts and cache services.
425 424
426 425 Initialize with initial and final values for cache counter (this defines
427 426 the maximum size of the cache."""
428 427
429 428 def __init__(self,shell,cache_size,Pprint,
430 429 colors='NoColor',input_sep='\n',
431 430 output_sep='\n',output_sep2='',
432 431 ps1 = None, ps2 = None,ps_out = None,pad_left=True):
433 432
434 433 cache_size_min = 3
435 434 if cache_size <= 0:
436 435 self.do_full_cache = 0
437 436 cache_size = 0
438 437 elif cache_size < cache_size_min:
439 438 self.do_full_cache = 0
440 439 cache_size = 0
441 440 warn('caching was disabled (min value for cache size is %s).' %
442 441 cache_size_min,level=3)
443 442 else:
444 443 self.do_full_cache = 1
445 444
446 445 self.cache_size = cache_size
447 446 self.input_sep = input_sep
448 447
449 448 # we need a reference to the user-level namespace
450 449 self.shell = shell
451 450 self.user_ns = shell.user_ns
452 451 # and to the user's input
453 452 self.input_hist = shell.input_hist
454 453 # and to the user's logger, for logging output
455 454 self.logger = shell.logger
456 455
457 456 # Set input prompt strings and colors
458 457 if cache_size == 0:
459 458 if ps1.find('%n') > -1 or ps1.find(r'\#') > -1 \
460 459 or ps1.find(r'\N') > -1:
461 460 ps1 = '>>> '
462 461 if ps2.find('%n') > -1 or ps2.find(r'\#') > -1 \
463 462 or ps2.find(r'\N') > -1:
464 463 ps2 = '... '
465 464 self.ps1_str = self._set_prompt_str(ps1,'In [\\#]: ','>>> ')
466 465 self.ps2_str = self._set_prompt_str(ps2,' .\\D.: ','... ')
467 466 self.ps_out_str = self._set_prompt_str(ps_out,'Out[\\#]: ','')
468 467
469 468 self.color_table = PromptColors
470 469 self.prompt1 = Prompt1(self,sep=input_sep,prompt=self.ps1_str,
471 470 pad_left=pad_left)
472 471 self.prompt2 = Prompt2(self,prompt=self.ps2_str,pad_left=pad_left)
473 472 self.prompt_out = PromptOut(self,sep='',prompt=self.ps_out_str,
474 473 pad_left=pad_left)
475 474 self.set_colors(colors)
476 475
477 476 # other more normal stuff
478 477 # b/c each call to the In[] prompt raises it by 1, even the first.
479 478 self.prompt_count = 0
480 479 # Store the last prompt string each time, we need it for aligning
481 480 # continuation and auto-rewrite prompts
482 481 self.last_prompt = ''
483 482 self.Pprint = Pprint
484 483 self.output_sep = output_sep
485 484 self.output_sep2 = output_sep2
486 485 self._,self.__,self.___ = '','',''
487 486 self.pprint_types = map(type,[(),[],{}])
488 487
489 488 # these are deliberately global:
490 489 to_user_ns = {'_':self._,'__':self.__,'___':self.___}
491 490 self.user_ns.update(to_user_ns)
492 491
493 492 def _set_prompt_str(self,p_str,cache_def,no_cache_def):
494 493 if p_str is None:
495 494 if self.do_full_cache:
496 495 return cache_def
497 496 else:
498 497 return no_cache_def
499 498 else:
500 499 return p_str
501 500
502 501 def set_colors(self,colors):
503 502 """Set the active color scheme and configure colors for the three
504 503 prompt subsystems."""
505 504
506 505 # FIXME: the prompt_specials global should be gobbled inside this
507 506 # class instead. Do it when cleaning up the whole 3-prompt system.
508 507 global prompt_specials
509 508 if colors.lower()=='nocolor':
510 509 prompt_specials = prompt_specials_nocolor
511 510 else:
512 511 prompt_specials = prompt_specials_color
513 512
514 513 self.color_table.set_active_scheme(colors)
515 514 self.prompt1.set_colors()
516 515 self.prompt2.set_colors()
517 516 self.prompt_out.set_colors()
518 517
519 518 def __call__(self,arg=None):
520 519 """Printing with history cache management.
521 520
522 521 This is invoked everytime the interpreter needs to print, and is
523 522 activated by setting the variable sys.displayhook to it."""
524 523
525 524 # If something injected a '_' variable in __builtin__, delete
526 525 # ipython's automatic one so we don't clobber that. gettext() in
527 526 # particular uses _, so we need to stay away from it.
528 527 if '_' in __builtin__.__dict__:
529 528 try:
530 529 del self.user_ns['_']
531 530 except KeyError:
532 531 pass
533 532 if arg is not None:
534 533 cout_write = Term.cout.write # fast lookup
535 534 # first handle the cache and counters
536 535
537 536 # do not print output if input ends in ';'
538 537 try:
539 538 if self.input_hist[self.prompt_count].endswith(';\n'):
540 539 return
541 540 except IndexError:
542 541 # some uses of ipshellembed may fail here
543 542 pass
544 543 # don't use print, puts an extra space
545 544 cout_write(self.output_sep)
546 545 outprompt = self.shell.hooks.generate_output_prompt()
547 546 if self.do_full_cache:
548 547 cout_write(outprompt)
549 548
550 549 # and now call a possibly user-defined print mechanism
551 550 manipulated_val = self.display(arg)
552 551
553 552 # user display hooks can change the variable to be stored in
554 553 # output history
555 554
556 555 if manipulated_val is not None:
557 556 arg = manipulated_val
558 557
559 558 # avoid recursive reference when displaying _oh/Out
560 559 if arg is not self.user_ns['_oh']:
561 560 self.update(arg)
562 561
563 562 if self.logger.log_output:
564 563 self.logger.log_write(repr(arg),'output')
565 564 cout_write(self.output_sep2)
566 565 Term.cout.flush()
567 566
568 567 def _display(self,arg):
569 568 """Default printer method, uses pprint.
570 569
571 570 Do ip.set_hook("result_display", my_displayhook) for custom result
572 571 display, e.g. when your own objects need special formatting.
573 572 """
574 573 try:
575 574 return IPython.generics.result_display(arg)
576 575 except TryNext:
577 576 return self.shell.hooks.result_display(arg)
578 577
579 578 # Assign the default display method:
580 579 display = _display
581 580
582 581 def update(self,arg):
583 582 #print '***cache_count', self.cache_count # dbg
584 583 if len(self.user_ns['_oh']) >= self.cache_size and self.do_full_cache:
585 584 warn('Output cache limit (currently '+
586 585 `self.cache_size`+' entries) hit.\n'
587 586 'Flushing cache and resetting history counter...\n'
588 587 'The only history variables available will be _,__,___ and _1\n'
589 588 'with the current result.')
590 589
591 590 self.flush()
592 591 # Don't overwrite '_' and friends if '_' is in __builtin__ (otherwise
593 592 # we cause buggy behavior for things like gettext).
594 593 if '_' not in __builtin__.__dict__:
595 594 self.___ = self.__
596 595 self.__ = self._
597 596 self._ = arg
598 597 self.user_ns.update({'_':self._,'__':self.__,'___':self.___})
599 598
600 599 # hackish access to top-level namespace to create _1,_2... dynamically
601 600 to_main = {}
602 601 if self.do_full_cache:
603 602 new_result = '_'+`self.prompt_count`
604 603 to_main[new_result] = arg
605 604 self.user_ns.update(to_main)
606 605 self.user_ns['_oh'][self.prompt_count] = arg
607 606
608 607 def flush(self):
609 608 if not self.do_full_cache:
610 609 raise ValueError,"You shouldn't have reached the cache flush "\
611 610 "if full caching is not enabled!"
612 611 # delete auto-generated vars from global namespace
613 612
614 613 for n in range(1,self.prompt_count + 1):
615 614 key = '_'+`n`
616 615 try:
617 616 del self.user_ns[key]
618 617 except: pass
619 618 self.user_ns['_oh'].clear()
620 619
621 620 if '_' not in __builtin__.__dict__:
622 621 self.user_ns.update({'_':None,'__':None, '___':None})
623 622 import gc
624 623 gc.collect() # xxx needed?
625 624
@@ -1,301 +1,300 b''
1 1 # -*- coding: utf-8 -*-
2 2 """
3 3 Class and program to colorize python source code for ANSI terminals.
4 4
5 5 Based on an HTML code highlighter by Jurgen Hermann found at:
6 6 http://aspn.activestate.com/ASPN/Cookbook/Python/Recipe/52298
7 7
8 8 Modifications by Fernando Perez (fperez@colorado.edu).
9 9
10 10 Information on the original HTML highlighter follows:
11 11
12 12 MoinMoin - Python Source Parser
13 13
14 14 Title: Colorize Python source using the built-in tokenizer
15 15
16 16 Submitter: Jurgen Hermann
17 17 Last Updated:2001/04/06
18 18
19 19 Version no:1.2
20 20
21 21 Description:
22 22
23 23 This code is part of MoinMoin (http://moin.sourceforge.net/) and converts
24 24 Python source code to HTML markup, rendering comments, keywords,
25 25 operators, numeric and string literals in different colors.
26 26
27 27 It shows how to use the built-in keyword, token and tokenize modules to
28 28 scan Python source code and re-emit it with no changes to its original
29 29 formatting (which is the hard part).
30
31 $Id: PyColorize.py 2586 2007-08-06 19:30:09Z vivainio $"""
30 """
32 31
33 32 __all__ = ['ANSICodeColors','Parser']
34 33
35 34 _scheme_default = 'Linux'
36 35
37 36 # Imports
38 37 import cStringIO
39 38 import keyword
40 39 import os
41 40 import optparse
42 41 import string
43 42 import sys
44 43 import token
45 44 import tokenize
46 45
47 46 from IPython.ColorANSI import *
48 47
49 48 #############################################################################
50 49 ### Python Source Parser (does Hilighting)
51 50 #############################################################################
52 51
53 52 _KEYWORD = token.NT_OFFSET + 1
54 53 _TEXT = token.NT_OFFSET + 2
55 54
56 55 #****************************************************************************
57 56 # Builtin color schemes
58 57
59 58 Colors = TermColors # just a shorthand
60 59
61 60 # Build a few color schemes
62 61 NoColor = ColorScheme(
63 62 'NoColor',{
64 63 token.NUMBER : Colors.NoColor,
65 64 token.OP : Colors.NoColor,
66 65 token.STRING : Colors.NoColor,
67 66 tokenize.COMMENT : Colors.NoColor,
68 67 token.NAME : Colors.NoColor,
69 68 token.ERRORTOKEN : Colors.NoColor,
70 69
71 70 _KEYWORD : Colors.NoColor,
72 71 _TEXT : Colors.NoColor,
73 72
74 73 'normal' : Colors.NoColor # color off (usu. Colors.Normal)
75 74 } )
76 75
77 76 LinuxColors = ColorScheme(
78 77 'Linux',{
79 78 token.NUMBER : Colors.LightCyan,
80 79 token.OP : Colors.Yellow,
81 80 token.STRING : Colors.LightBlue,
82 81 tokenize.COMMENT : Colors.LightRed,
83 82 token.NAME : Colors.White,
84 83 token.ERRORTOKEN : Colors.Red,
85 84
86 85 _KEYWORD : Colors.LightGreen,
87 86 _TEXT : Colors.Yellow,
88 87
89 88 'normal' : Colors.Normal # color off (usu. Colors.Normal)
90 89 } )
91 90
92 91 LightBGColors = ColorScheme(
93 92 'LightBG',{
94 93 token.NUMBER : Colors.Cyan,
95 94 token.OP : Colors.Blue,
96 95 token.STRING : Colors.Blue,
97 96 tokenize.COMMENT : Colors.Red,
98 97 token.NAME : Colors.Black,
99 98 token.ERRORTOKEN : Colors.Red,
100 99
101 100 _KEYWORD : Colors.Green,
102 101 _TEXT : Colors.Blue,
103 102
104 103 'normal' : Colors.Normal # color off (usu. Colors.Normal)
105 104 } )
106 105
107 106 # Build table of color schemes (needed by the parser)
108 107 ANSICodeColors = ColorSchemeTable([NoColor,LinuxColors,LightBGColors],
109 108 _scheme_default)
110 109
111 110 class Parser:
112 111 """ Format colored Python source.
113 112 """
114 113
115 114 def __init__(self, color_table=None,out = sys.stdout):
116 115 """ Create a parser with a specified color table and output channel.
117 116
118 117 Call format() to process code.
119 118 """
120 119 self.color_table = color_table and color_table or ANSICodeColors
121 120 self.out = out
122 121
123 122 def format(self, raw, out = None, scheme = ''):
124 123 return self.format2(raw, out, scheme)[0]
125 124
126 125 def format2(self, raw, out = None, scheme = ''):
127 126 """ Parse and send the colored source.
128 127
129 128 If out and scheme are not specified, the defaults (given to
130 129 constructor) are used.
131 130
132 131 out should be a file-type object. Optionally, out can be given as the
133 132 string 'str' and the parser will automatically return the output in a
134 133 string."""
135 134
136 135 string_output = 0
137 136 if out == 'str' or self.out == 'str' or \
138 137 isinstance(self.out,cStringIO.OutputType):
139 138 # XXX - I don't really like this state handling logic, but at this
140 139 # point I don't want to make major changes, so adding the
141 140 # isinstance() check is the simplest I can do to ensure correct
142 141 # behavior.
143 142 out_old = self.out
144 143 self.out = cStringIO.StringIO()
145 144 string_output = 1
146 145 elif out is not None:
147 146 self.out = out
148 147
149 148 # Fast return of the unmodified input for NoColor scheme
150 149 if scheme == 'NoColor':
151 150 error = False
152 151 self.out.write(raw)
153 152 if string_output:
154 153 return raw,error
155 154 else:
156 155 return None,error
157 156
158 157 # local shorthands
159 158 colors = self.color_table[scheme].colors
160 159 self.colors = colors # put in object so __call__ sees it
161 160
162 161 # Remove trailing whitespace and normalize tabs
163 162 self.raw = raw.expandtabs().rstrip()
164 163
165 164 # store line offsets in self.lines
166 165 self.lines = [0, 0]
167 166 pos = 0
168 167 raw_find = self.raw.find
169 168 lines_append = self.lines.append
170 169 while 1:
171 170 pos = raw_find('\n', pos) + 1
172 171 if not pos: break
173 172 lines_append(pos)
174 173 lines_append(len(self.raw))
175 174
176 175 # parse the source and write it
177 176 self.pos = 0
178 177 text = cStringIO.StringIO(self.raw)
179 178
180 179 error = False
181 180 try:
182 181 tokenize.tokenize(text.readline, self)
183 182 except tokenize.TokenError, ex:
184 183 msg = ex[0]
185 184 line = ex[1][0]
186 185 self.out.write("%s\n\n*** ERROR: %s%s%s\n" %
187 186 (colors[token.ERRORTOKEN],
188 187 msg, self.raw[self.lines[line]:],
189 188 colors.normal)
190 189 )
191 190 error = True
192 191 self.out.write(colors.normal+'\n')
193 192 if string_output:
194 193 output = self.out.getvalue()
195 194 self.out = out_old
196 195 return (output, error)
197 196 return (None, error)
198 197
199 198 def __call__(self, toktype, toktext, (srow,scol), (erow,ecol), line):
200 199 """ Token handler, with syntax highlighting."""
201 200
202 201 # local shorthands
203 202 colors = self.colors
204 203 owrite = self.out.write
205 204
206 205 # line separator, so this works across platforms
207 206 linesep = os.linesep
208 207
209 208 # calculate new positions
210 209 oldpos = self.pos
211 210 newpos = self.lines[srow] + scol
212 211 self.pos = newpos + len(toktext)
213 212
214 213 # handle newlines
215 214 if toktype in [token.NEWLINE, tokenize.NL]:
216 215 owrite(linesep)
217 216 return
218 217
219 218 # send the original whitespace, if needed
220 219 if newpos > oldpos:
221 220 owrite(self.raw[oldpos:newpos])
222 221
223 222 # skip indenting tokens
224 223 if toktype in [token.INDENT, token.DEDENT]:
225 224 self.pos = newpos
226 225 return
227 226
228 227 # map token type to a color group
229 228 if token.LPAR <= toktype and toktype <= token.OP:
230 229 toktype = token.OP
231 230 elif toktype == token.NAME and keyword.iskeyword(toktext):
232 231 toktype = _KEYWORD
233 232 color = colors.get(toktype, colors[_TEXT])
234 233
235 234 #print '<%s>' % toktext, # dbg
236 235
237 236 # Triple quoted strings must be handled carefully so that backtracking
238 237 # in pagers works correctly. We need color terminators on _each_ line.
239 238 if linesep in toktext:
240 239 toktext = toktext.replace(linesep, '%s%s%s' %
241 240 (colors.normal,linesep,color))
242 241
243 242 # send text
244 243 owrite('%s%s%s' % (color,toktext,colors.normal))
245 244
246 245 def main(argv=None):
247 246 """Run as a command-line script: colorize a python file or stdin using ANSI
248 247 color escapes and print to stdout.
249 248
250 249 Inputs:
251 250
252 251 - argv(None): a list of strings like sys.argv[1:] giving the command-line
253 252 arguments. If None, use sys.argv[1:].
254 253 """
255 254
256 255 usage_msg = """%prog [options] [filename]
257 256
258 257 Colorize a python file or stdin using ANSI color escapes and print to stdout.
259 258 If no filename is given, or if filename is -, read standard input."""
260 259
261 260 parser = optparse.OptionParser(usage=usage_msg)
262 261 newopt = parser.add_option
263 262 newopt('-s','--scheme',metavar='NAME',dest='scheme_name',action='store',
264 263 choices=['Linux','LightBG','NoColor'],default=_scheme_default,
265 264 help="give the color scheme to use. Currently only 'Linux'\
266 265 (default) and 'LightBG' and 'NoColor' are implemented (give without\
267 266 quotes)")
268 267
269 268 opts,args = parser.parse_args(argv)
270 269
271 270 if len(args) > 1:
272 271 parser.error("you must give at most one filename.")
273 272
274 273 if len(args) == 0:
275 274 fname = '-' # no filename given; setup to read from stdin
276 275 else:
277 276 fname = args[0]
278 277
279 278 if fname == '-':
280 279 stream = sys.stdin
281 280 else:
282 281 stream = file(fname)
283 282
284 283 parser = Parser()
285 284
286 285 # we need nested try blocks because pre-2.5 python doesn't support unified
287 286 # try-except-finally
288 287 try:
289 288 try:
290 289 # write colorized version to stdout
291 290 parser.format(stream.read(),scheme=opts.scheme_name)
292 291 except IOError,msg:
293 292 # if user reads through a pager and quits, don't print traceback
294 293 if msg.args != (32,'Broken pipe'):
295 294 raise
296 295 finally:
297 296 if stream is not sys.stdin:
298 297 stream.close() # in case a non-handled exception happened above
299 298
300 299 if __name__ == "__main__":
301 300 main()
@@ -1,1238 +1,1233 b''
1 1 # -*- coding: utf-8 -*-
2 2 """IPython Shell classes.
3 3
4 4 All the matplotlib support code was co-developed with John Hunter,
5 5 matplotlib's author.
6
7 $Id: Shell.py 3024 2008-02-07 15:34:42Z darren.dale $"""
6 """
8 7
9 8 #*****************************************************************************
10 9 # Copyright (C) 2001-2006 Fernando Perez <fperez@colorado.edu>
11 10 #
12 11 # Distributed under the terms of the BSD License. The full license is in
13 12 # the file COPYING, distributed as part of this software.
14 13 #*****************************************************************************
15 14
16 from IPython import Release
17 __author__ = '%s <%s>' % Release.authors['Fernando']
18 __license__ = Release.license
19
20 15 # Code begins
21 16 # Stdlib imports
22 17 import __builtin__
23 18 import __main__
24 19 import Queue
25 20 import inspect
26 21 import os
27 22 import sys
28 23 import thread
29 24 import threading
30 25 import time
31 26
32 27 from signal import signal, SIGINT
33 28
34 29 try:
35 30 import ctypes
36 31 HAS_CTYPES = True
37 32 except ImportError:
38 33 HAS_CTYPES = False
39 34
40 35 # IPython imports
41 36 import IPython
42 37 from IPython import ultraTB, ipapi
43 38 from IPython.Magic import Magic
44 39 from IPython.genutils import Term,warn,error,flag_calls, ask_yes_no
45 40 from IPython.iplib import InteractiveShell
46 41 from IPython.ipmaker import make_IPython
47 42 from IPython.ipstruct import Struct
48 43 from IPython.testing import decorators as testdec
49 44
50 45 # Globals
51 46 # global flag to pass around information about Ctrl-C without exceptions
52 47 KBINT = False
53 48
54 49 # global flag to turn on/off Tk support.
55 50 USE_TK = False
56 51
57 52 # ID for the main thread, used for cross-thread exceptions
58 53 MAIN_THREAD_ID = thread.get_ident()
59 54
60 55 # Tag when runcode() is active, for exception handling
61 56 CODE_RUN = None
62 57
63 58 # Default timeout for waiting for multithreaded shells (in seconds)
64 59 GUI_TIMEOUT = 10
65 60
66 61 #-----------------------------------------------------------------------------
67 62 # This class is trivial now, but I want to have it in to publish a clean
68 63 # interface. Later when the internals are reorganized, code that uses this
69 64 # shouldn't have to change.
70 65
71 66 class IPShell:
72 67 """Create an IPython instance."""
73 68
74 69 def __init__(self,argv=None,user_ns=None,user_global_ns=None,
75 70 debug=1,shell_class=InteractiveShell):
76 71 self.IP = make_IPython(argv,user_ns=user_ns,
77 72 user_global_ns=user_global_ns,
78 73 debug=debug,shell_class=shell_class)
79 74
80 75 def mainloop(self,sys_exit=0,banner=None):
81 76 self.IP.mainloop(banner)
82 77 if sys_exit:
83 78 sys.exit()
84 79
85 80 #-----------------------------------------------------------------------------
86 81 def kill_embedded(self,parameter_s=''):
87 82 """%kill_embedded : deactivate for good the current embedded IPython.
88 83
89 84 This function (after asking for confirmation) sets an internal flag so that
90 85 an embedded IPython will never activate again. This is useful to
91 86 permanently disable a shell that is being called inside a loop: once you've
92 87 figured out what you needed from it, you may then kill it and the program
93 88 will then continue to run without the interactive shell interfering again.
94 89 """
95 90
96 91 kill = ask_yes_no("Are you sure you want to kill this embedded instance "
97 92 "(y/n)? [y/N] ",'n')
98 93 if kill:
99 94 self.shell.embedded_active = False
100 95 print "This embedded IPython will not reactivate anymore once you exit."
101 96
102 97 class IPShellEmbed:
103 98 """Allow embedding an IPython shell into a running program.
104 99
105 100 Instances of this class are callable, with the __call__ method being an
106 101 alias to the embed() method of an InteractiveShell instance.
107 102
108 103 Usage (see also the example-embed.py file for a running example):
109 104
110 105 ipshell = IPShellEmbed([argv,banner,exit_msg,rc_override])
111 106
112 107 - argv: list containing valid command-line options for IPython, as they
113 108 would appear in sys.argv[1:].
114 109
115 110 For example, the following command-line options:
116 111
117 112 $ ipython -prompt_in1 'Input <\\#>' -colors LightBG
118 113
119 114 would be passed in the argv list as:
120 115
121 116 ['-prompt_in1','Input <\\#>','-colors','LightBG']
122 117
123 118 - banner: string which gets printed every time the interpreter starts.
124 119
125 120 - exit_msg: string which gets printed every time the interpreter exits.
126 121
127 122 - rc_override: a dict or Struct of configuration options such as those
128 123 used by IPython. These options are read from your ~/.ipython/ipythonrc
129 124 file when the Shell object is created. Passing an explicit rc_override
130 125 dict with any options you want allows you to override those values at
131 126 creation time without having to modify the file. This way you can create
132 127 embeddable instances configured in any way you want without editing any
133 128 global files (thus keeping your interactive IPython configuration
134 129 unchanged).
135 130
136 131 Then the ipshell instance can be called anywhere inside your code:
137 132
138 133 ipshell(header='') -> Opens up an IPython shell.
139 134
140 135 - header: string printed by the IPython shell upon startup. This can let
141 136 you know where in your code you are when dropping into the shell. Note
142 137 that 'banner' gets prepended to all calls, so header is used for
143 138 location-specific information.
144 139
145 140 For more details, see the __call__ method below.
146 141
147 142 When the IPython shell is exited with Ctrl-D, normal program execution
148 143 resumes.
149 144
150 145 This functionality was inspired by a posting on comp.lang.python by cmkl
151 146 <cmkleffner@gmx.de> on Dec. 06/01 concerning similar uses of pyrepl, and
152 147 by the IDL stop/continue commands."""
153 148
154 149 def __init__(self,argv=None,banner='',exit_msg=None,rc_override=None,
155 150 user_ns=None):
156 151 """Note that argv here is a string, NOT a list."""
157 152 self.set_banner(banner)
158 153 self.set_exit_msg(exit_msg)
159 154 self.set_dummy_mode(0)
160 155
161 156 # sys.displayhook is a global, we need to save the user's original
162 157 # Don't rely on __displayhook__, as the user may have changed that.
163 158 self.sys_displayhook_ori = sys.displayhook
164 159
165 160 # save readline completer status
166 161 try:
167 162 #print 'Save completer',sys.ipcompleter # dbg
168 163 self.sys_ipcompleter_ori = sys.ipcompleter
169 164 except:
170 165 pass # not nested with IPython
171 166
172 167 self.IP = make_IPython(argv,rc_override=rc_override,
173 168 embedded=True,
174 169 user_ns=user_ns)
175 170
176 171 ip = ipapi.IPApi(self.IP)
177 172 ip.expose_magic("kill_embedded",kill_embedded)
178 173
179 174 # copy our own displayhook also
180 175 self.sys_displayhook_embed = sys.displayhook
181 176 # and leave the system's display hook clean
182 177 sys.displayhook = self.sys_displayhook_ori
183 178 # don't use the ipython crash handler so that user exceptions aren't
184 179 # trapped
185 180 sys.excepthook = ultraTB.FormattedTB(color_scheme = self.IP.rc.colors,
186 181 mode = self.IP.rc.xmode,
187 182 call_pdb = self.IP.rc.pdb)
188 183 self.restore_system_completer()
189 184
190 185 def restore_system_completer(self):
191 186 """Restores the readline completer which was in place.
192 187
193 188 This allows embedded IPython within IPython not to disrupt the
194 189 parent's completion.
195 190 """
196 191
197 192 try:
198 193 self.IP.readline.set_completer(self.sys_ipcompleter_ori)
199 194 sys.ipcompleter = self.sys_ipcompleter_ori
200 195 except:
201 196 pass
202 197
203 198 def __call__(self,header='',local_ns=None,global_ns=None,dummy=None):
204 199 """Activate the interactive interpreter.
205 200
206 201 __call__(self,header='',local_ns=None,global_ns,dummy=None) -> Start
207 202 the interpreter shell with the given local and global namespaces, and
208 203 optionally print a header string at startup.
209 204
210 205 The shell can be globally activated/deactivated using the
211 206 set/get_dummy_mode methods. This allows you to turn off a shell used
212 207 for debugging globally.
213 208
214 209 However, *each* time you call the shell you can override the current
215 210 state of dummy_mode with the optional keyword parameter 'dummy'. For
216 211 example, if you set dummy mode on with IPShell.set_dummy_mode(1), you
217 212 can still have a specific call work by making it as IPShell(dummy=0).
218 213
219 214 The optional keyword parameter dummy controls whether the call
220 215 actually does anything. """
221 216
222 217 # If the user has turned it off, go away
223 218 if not self.IP.embedded_active:
224 219 return
225 220
226 221 # Normal exits from interactive mode set this flag, so the shell can't
227 222 # re-enter (it checks this variable at the start of interactive mode).
228 223 self.IP.exit_now = False
229 224
230 225 # Allow the dummy parameter to override the global __dummy_mode
231 226 if dummy or (dummy != 0 and self.__dummy_mode):
232 227 return
233 228
234 229 # Set global subsystems (display,completions) to our values
235 230 sys.displayhook = self.sys_displayhook_embed
236 231 if self.IP.has_readline:
237 232 self.IP.set_completer()
238 233
239 234 if self.banner and header:
240 235 format = '%s\n%s\n'
241 236 else:
242 237 format = '%s%s\n'
243 238 banner = format % (self.banner,header)
244 239
245 240 # Call the embedding code with a stack depth of 1 so it can skip over
246 241 # our call and get the original caller's namespaces.
247 242 self.IP.embed_mainloop(banner,local_ns,global_ns,stack_depth=1)
248 243
249 244 if self.exit_msg:
250 245 print self.exit_msg
251 246
252 247 # Restore global systems (display, completion)
253 248 sys.displayhook = self.sys_displayhook_ori
254 249 self.restore_system_completer()
255 250
256 251 def set_dummy_mode(self,dummy):
257 252 """Sets the embeddable shell's dummy mode parameter.
258 253
259 254 set_dummy_mode(dummy): dummy = 0 or 1.
260 255
261 256 This parameter is persistent and makes calls to the embeddable shell
262 257 silently return without performing any action. This allows you to
263 258 globally activate or deactivate a shell you're using with a single call.
264 259
265 260 If you need to manually"""
266 261
267 262 if dummy not in [0,1,False,True]:
268 263 raise ValueError,'dummy parameter must be boolean'
269 264 self.__dummy_mode = dummy
270 265
271 266 def get_dummy_mode(self):
272 267 """Return the current value of the dummy mode parameter.
273 268 """
274 269 return self.__dummy_mode
275 270
276 271 def set_banner(self,banner):
277 272 """Sets the global banner.
278 273
279 274 This banner gets prepended to every header printed when the shell
280 275 instance is called."""
281 276
282 277 self.banner = banner
283 278
284 279 def set_exit_msg(self,exit_msg):
285 280 """Sets the global exit_msg.
286 281
287 282 This exit message gets printed upon exiting every time the embedded
288 283 shell is called. It is None by default. """
289 284
290 285 self.exit_msg = exit_msg
291 286
292 287 #-----------------------------------------------------------------------------
293 288 if HAS_CTYPES:
294 289 # Add async exception support. Trick taken from:
295 290 # http://sebulba.wikispaces.com/recipe+thread2
296 291 def _async_raise(tid, exctype):
297 292 """raises the exception, performs cleanup if needed"""
298 293 if not inspect.isclass(exctype):
299 294 raise TypeError("Only types can be raised (not instances)")
300 295 res = ctypes.pythonapi.PyThreadState_SetAsyncExc(tid,
301 296 ctypes.py_object(exctype))
302 297 if res == 0:
303 298 raise ValueError("invalid thread id")
304 299 elif res != 1:
305 300 # """if it returns a number greater than one, you're in trouble,
306 301 # and you should call it again with exc=NULL to revert the effect"""
307 302 ctypes.pythonapi.PyThreadState_SetAsyncExc(tid, 0)
308 303 raise SystemError("PyThreadState_SetAsyncExc failed")
309 304
310 305 def sigint_handler (signum,stack_frame):
311 306 """Sigint handler for threaded apps.
312 307
313 308 This is a horrible hack to pass information about SIGINT _without_
314 309 using exceptions, since I haven't been able to properly manage
315 310 cross-thread exceptions in GTK/WX. In fact, I don't think it can be
316 311 done (or at least that's my understanding from a c.l.py thread where
317 312 this was discussed)."""
318 313
319 314 global KBINT
320 315
321 316 if CODE_RUN:
322 317 _async_raise(MAIN_THREAD_ID,KeyboardInterrupt)
323 318 else:
324 319 KBINT = True
325 320 print '\nKeyboardInterrupt - Press <Enter> to continue.',
326 321 Term.cout.flush()
327 322
328 323 else:
329 324 def sigint_handler (signum,stack_frame):
330 325 """Sigint handler for threaded apps.
331 326
332 327 This is a horrible hack to pass information about SIGINT _without_
333 328 using exceptions, since I haven't been able to properly manage
334 329 cross-thread exceptions in GTK/WX. In fact, I don't think it can be
335 330 done (or at least that's my understanding from a c.l.py thread where
336 331 this was discussed)."""
337 332
338 333 global KBINT
339 334
340 335 print '\nKeyboardInterrupt - Press <Enter> to continue.',
341 336 Term.cout.flush()
342 337 # Set global flag so that runsource can know that Ctrl-C was hit
343 338 KBINT = True
344 339
345 340
346 341 class MTInteractiveShell(InteractiveShell):
347 342 """Simple multi-threaded shell."""
348 343
349 344 # Threading strategy taken from:
350 345 # http://aspn.activestate.com/ASPN/Cookbook/Python/Recipe/65109, by Brian
351 346 # McErlean and John Finlay. Modified with corrections by Antoon Pardon,
352 347 # from the pygtk mailing list, to avoid lockups with system calls.
353 348
354 349 # class attribute to indicate whether the class supports threads or not.
355 350 # Subclasses with thread support should override this as needed.
356 351 isthreaded = True
357 352
358 353 def __init__(self,name,usage=None,rc=Struct(opts=None,args=None),
359 354 user_ns=None,user_global_ns=None,banner2='',
360 355 gui_timeout=GUI_TIMEOUT,**kw):
361 356 """Similar to the normal InteractiveShell, but with threading control"""
362 357
363 358 InteractiveShell.__init__(self,name,usage,rc,user_ns,
364 359 user_global_ns,banner2)
365 360
366 361 # Timeout we wait for GUI thread
367 362 self.gui_timeout = gui_timeout
368 363
369 364 # A queue to hold the code to be executed.
370 365 self.code_queue = Queue.Queue()
371 366
372 367 # Stuff to do at closing time
373 368 self._kill = None
374 369 on_kill = kw.get('on_kill', [])
375 370 # Check that all things to kill are callable:
376 371 for t in on_kill:
377 372 if not callable(t):
378 373 raise TypeError,'on_kill must be a list of callables'
379 374 self.on_kill = on_kill
380 375 # thread identity of the "worker thread" (that may execute code directly)
381 376 self.worker_ident = None
382 377
383 378 def runsource(self, source, filename="<input>", symbol="single"):
384 379 """Compile and run some source in the interpreter.
385 380
386 381 Modified version of code.py's runsource(), to handle threading issues.
387 382 See the original for full docstring details."""
388 383
389 384 global KBINT
390 385
391 386 # If Ctrl-C was typed, we reset the flag and return right away
392 387 if KBINT:
393 388 KBINT = False
394 389 return False
395 390
396 391 if self._kill:
397 392 # can't queue new code if we are being killed
398 393 return True
399 394
400 395 try:
401 396 code = self.compile(source, filename, symbol)
402 397 except (OverflowError, SyntaxError, ValueError):
403 398 # Case 1
404 399 self.showsyntaxerror(filename)
405 400 return False
406 401
407 402 if code is None:
408 403 # Case 2
409 404 return True
410 405
411 406 # shortcut - if we are in worker thread, or the worker thread is not
412 407 # running, execute directly (to allow recursion and prevent deadlock if
413 408 # code is run early in IPython construction)
414 409
415 410 if (self.worker_ident is None
416 411 or self.worker_ident == thread.get_ident() ):
417 412 InteractiveShell.runcode(self,code)
418 413 return
419 414
420 415 # Case 3
421 416 # Store code in queue, so the execution thread can handle it.
422 417
423 418 completed_ev, received_ev = threading.Event(), threading.Event()
424 419
425 420 self.code_queue.put((code,completed_ev, received_ev))
426 421 # first make sure the message was received, with timeout
427 422 received_ev.wait(self.gui_timeout)
428 423 if not received_ev.isSet():
429 424 # the mainloop is dead, start executing code directly
430 425 print "Warning: Timeout for mainloop thread exceeded"
431 426 print "switching to nonthreaded mode (until mainloop wakes up again)"
432 427 self.worker_ident = None
433 428 else:
434 429 completed_ev.wait()
435 430 return False
436 431
437 432 def runcode(self):
438 433 """Execute a code object.
439 434
440 435 Multithreaded wrapper around IPython's runcode()."""
441 436
442 437 global CODE_RUN
443 438
444 439 # we are in worker thread, stash out the id for runsource()
445 440 self.worker_ident = thread.get_ident()
446 441
447 442 if self._kill:
448 443 print >>Term.cout, 'Closing threads...',
449 444 Term.cout.flush()
450 445 for tokill in self.on_kill:
451 446 tokill()
452 447 print >>Term.cout, 'Done.'
453 448 # allow kill() to return
454 449 self._kill.set()
455 450 return True
456 451
457 452 # Install sigint handler. We do it every time to ensure that if user
458 453 # code modifies it, we restore our own handling.
459 454 try:
460 455 signal(SIGINT,sigint_handler)
461 456 except SystemError:
462 457 # This happens under Windows, which seems to have all sorts
463 458 # of problems with signal handling. Oh well...
464 459 pass
465 460
466 461 # Flush queue of pending code by calling the run methood of the parent
467 462 # class with all items which may be in the queue.
468 463 code_to_run = None
469 464 while 1:
470 465 try:
471 466 code_to_run, completed_ev, received_ev = self.code_queue.get_nowait()
472 467 except Queue.Empty:
473 468 break
474 469 received_ev.set()
475 470
476 471 # Exceptions need to be raised differently depending on which
477 472 # thread is active. This convoluted try/except is only there to
478 473 # protect against asynchronous exceptions, to ensure that a KBINT
479 474 # at the wrong time doesn't deadlock everything. The global
480 475 # CODE_TO_RUN is set to true/false as close as possible to the
481 476 # runcode() call, so that the KBINT handler is correctly informed.
482 477 try:
483 478 try:
484 479 CODE_RUN = True
485 480 InteractiveShell.runcode(self,code_to_run)
486 481 except KeyboardInterrupt:
487 482 print "Keyboard interrupted in mainloop"
488 483 while not self.code_queue.empty():
489 484 code, ev1,ev2 = self.code_queue.get_nowait()
490 485 ev1.set()
491 486 ev2.set()
492 487 break
493 488 finally:
494 489 CODE_RUN = False
495 490 # allow runsource() return from wait
496 491 completed_ev.set()
497 492
498 493
499 494 # This MUST return true for gtk threading to work
500 495 return True
501 496
502 497 def kill(self):
503 498 """Kill the thread, returning when it has been shut down."""
504 499 self._kill = threading.Event()
505 500 self._kill.wait()
506 501
507 502 class MatplotlibShellBase:
508 503 """Mixin class to provide the necessary modifications to regular IPython
509 504 shell classes for matplotlib support.
510 505
511 506 Given Python's MRO, this should be used as the FIRST class in the
512 507 inheritance hierarchy, so that it overrides the relevant methods."""
513 508
514 509 def _matplotlib_config(self,name,user_ns,user_global_ns=None):
515 510 """Return items needed to setup the user's shell with matplotlib"""
516 511
517 512 # Initialize matplotlib to interactive mode always
518 513 import matplotlib
519 514 from matplotlib import backends
520 515 matplotlib.interactive(True)
521 516
522 517 def use(arg):
523 518 """IPython wrapper for matplotlib's backend switcher.
524 519
525 520 In interactive use, we can not allow switching to a different
526 521 interactive backend, since thread conflicts will most likely crash
527 522 the python interpreter. This routine does a safety check first,
528 523 and refuses to perform a dangerous switch. It still allows
529 524 switching to non-interactive backends."""
530 525
531 526 if arg in backends.interactive_bk and arg != self.mpl_backend:
532 527 m=('invalid matplotlib backend switch.\n'
533 528 'This script attempted to switch to the interactive '
534 529 'backend: `%s`\n'
535 530 'Your current choice of interactive backend is: `%s`\n\n'
536 531 'Switching interactive matplotlib backends at runtime\n'
537 532 'would crash the python interpreter, '
538 533 'and IPython has blocked it.\n\n'
539 534 'You need to either change your choice of matplotlib backend\n'
540 535 'by editing your .matplotlibrc file, or run this script as a \n'
541 536 'standalone file from the command line, not using IPython.\n' %
542 537 (arg,self.mpl_backend) )
543 538 raise RuntimeError, m
544 539 else:
545 540 self.mpl_use(arg)
546 541 self.mpl_use._called = True
547 542
548 543 self.matplotlib = matplotlib
549 544 self.mpl_backend = matplotlib.rcParams['backend']
550 545
551 546 # we also need to block switching of interactive backends by use()
552 547 self.mpl_use = matplotlib.use
553 548 self.mpl_use._called = False
554 549 # overwrite the original matplotlib.use with our wrapper
555 550 matplotlib.use = use
556 551
557 552 # This must be imported last in the matplotlib series, after
558 553 # backend/interactivity choices have been made
559 554 import matplotlib.pylab as pylab
560 555 self.pylab = pylab
561 556
562 557 self.pylab.show._needmain = False
563 558 # We need to detect at runtime whether show() is called by the user.
564 559 # For this, we wrap it into a decorator which adds a 'called' flag.
565 560 self.pylab.draw_if_interactive = flag_calls(self.pylab.draw_if_interactive)
566 561
567 562 # Build a user namespace initialized with matplotlib/matlab features.
568 563 user_ns, user_global_ns = IPython.ipapi.make_user_namespaces(user_ns,
569 564 user_global_ns)
570 565
571 566 # Import numpy as np/pyplot as plt are conventions we're trying to
572 567 # somewhat standardize on. Making them available to users by default
573 568 # will greatly help this.
574 569 exec ("import numpy\n"
575 570 "import numpy as np\n"
576 571 "import matplotlib\n"
577 572 "import matplotlib.pylab as pylab\n"
578 573 "try:\n"
579 574 " import matplotlib.pyplot as plt\n"
580 575 "except ImportError:\n"
581 576 " pass\n"
582 577 ) in user_ns
583 578
584 579 # Build matplotlib info banner
585 580 b="""
586 581 Welcome to pylab, a matplotlib-based Python environment.
587 582 For more information, type 'help(pylab)'.
588 583 """
589 584 return user_ns,user_global_ns,b
590 585
591 586 def mplot_exec(self,fname,*where,**kw):
592 587 """Execute a matplotlib script.
593 588
594 589 This is a call to execfile(), but wrapped in safeties to properly
595 590 handle interactive rendering and backend switching."""
596 591
597 592 #print '*** Matplotlib runner ***' # dbg
598 593 # turn off rendering until end of script
599 594 isInteractive = self.matplotlib.rcParams['interactive']
600 595 self.matplotlib.interactive(False)
601 596 self.safe_execfile(fname,*where,**kw)
602 597 self.matplotlib.interactive(isInteractive)
603 598 # make rendering call now, if the user tried to do it
604 599 if self.pylab.draw_if_interactive.called:
605 600 self.pylab.draw()
606 601 self.pylab.draw_if_interactive.called = False
607 602
608 603 # if a backend switch was performed, reverse it now
609 604 if self.mpl_use._called:
610 605 self.matplotlib.rcParams['backend'] = self.mpl_backend
611 606
612 607 @testdec.skip_doctest
613 608 def magic_run(self,parameter_s=''):
614 609 Magic.magic_run(self,parameter_s,runner=self.mplot_exec)
615 610
616 611 # Fix the docstring so users see the original as well
617 612 magic_run.__doc__ = "%s\n%s" % (Magic.magic_run.__doc__,
618 613 "\n *** Modified %run for Matplotlib,"
619 614 " with proper interactive handling ***")
620 615
621 616 # Now we provide 2 versions of a matplotlib-aware IPython base shells, single
622 617 # and multithreaded. Note that these are meant for internal use, the IPShell*
623 618 # classes below are the ones meant for public consumption.
624 619
625 620 class MatplotlibShell(MatplotlibShellBase,InteractiveShell):
626 621 """Single-threaded shell with matplotlib support."""
627 622
628 623 def __init__(self,name,usage=None,rc=Struct(opts=None,args=None),
629 624 user_ns=None,user_global_ns=None,**kw):
630 625 user_ns,user_global_ns,b2 = self._matplotlib_config(name,user_ns,user_global_ns)
631 626 InteractiveShell.__init__(self,name,usage,rc,user_ns,user_global_ns,
632 627 banner2=b2,**kw)
633 628
634 629 class MatplotlibMTShell(MatplotlibShellBase,MTInteractiveShell):
635 630 """Multi-threaded shell with matplotlib support."""
636 631
637 632 def __init__(self,name,usage=None,rc=Struct(opts=None,args=None),
638 633 user_ns=None,user_global_ns=None, **kw):
639 634 user_ns,user_global_ns,b2 = self._matplotlib_config(name,user_ns,user_global_ns)
640 635 MTInteractiveShell.__init__(self,name,usage,rc,user_ns,user_global_ns,
641 636 banner2=b2,**kw)
642 637
643 638 #-----------------------------------------------------------------------------
644 639 # Utility functions for the different GUI enabled IPShell* classes.
645 640
646 641 def get_tk():
647 642 """Tries to import Tkinter and returns a withdrawn Tkinter root
648 643 window. If Tkinter is already imported or not available, this
649 644 returns None. This function calls `hijack_tk` underneath.
650 645 """
651 646 if not USE_TK or sys.modules.has_key('Tkinter'):
652 647 return None
653 648 else:
654 649 try:
655 650 import Tkinter
656 651 except ImportError:
657 652 return None
658 653 else:
659 654 hijack_tk()
660 655 r = Tkinter.Tk()
661 656 r.withdraw()
662 657 return r
663 658
664 659 def hijack_tk():
665 660 """Modifies Tkinter's mainloop with a dummy so when a module calls
666 661 mainloop, it does not block.
667 662
668 663 """
669 664 def misc_mainloop(self, n=0):
670 665 pass
671 666 def tkinter_mainloop(n=0):
672 667 pass
673 668
674 669 import Tkinter
675 670 Tkinter.Misc.mainloop = misc_mainloop
676 671 Tkinter.mainloop = tkinter_mainloop
677 672
678 673 def update_tk(tk):
679 674 """Updates the Tkinter event loop. This is typically called from
680 675 the respective WX or GTK mainloops.
681 676 """
682 677 if tk:
683 678 tk.update()
684 679
685 680 def hijack_wx():
686 681 """Modifies wxPython's MainLoop with a dummy so user code does not
687 682 block IPython. The hijacked mainloop function is returned.
688 683 """
689 684 def dummy_mainloop(*args, **kw):
690 685 pass
691 686
692 687 try:
693 688 import wx
694 689 except ImportError:
695 690 # For very old versions of WX
696 691 import wxPython as wx
697 692
698 693 ver = wx.__version__
699 694 orig_mainloop = None
700 695 if ver[:3] >= '2.5':
701 696 import wx
702 697 if hasattr(wx, '_core_'): core = getattr(wx, '_core_')
703 698 elif hasattr(wx, '_core'): core = getattr(wx, '_core')
704 699 else: raise AttributeError('Could not find wx core module')
705 700 orig_mainloop = core.PyApp_MainLoop
706 701 core.PyApp_MainLoop = dummy_mainloop
707 702 elif ver[:3] == '2.4':
708 703 orig_mainloop = wx.wxc.wxPyApp_MainLoop
709 704 wx.wxc.wxPyApp_MainLoop = dummy_mainloop
710 705 else:
711 706 warn("Unable to find either wxPython version 2.4 or >= 2.5.")
712 707 return orig_mainloop
713 708
714 709 def hijack_gtk():
715 710 """Modifies pyGTK's mainloop with a dummy so user code does not
716 711 block IPython. This function returns the original `gtk.mainloop`
717 712 function that has been hijacked.
718 713 """
719 714 def dummy_mainloop(*args, **kw):
720 715 pass
721 716 import gtk
722 717 if gtk.pygtk_version >= (2,4,0): orig_mainloop = gtk.main
723 718 else: orig_mainloop = gtk.mainloop
724 719 gtk.mainloop = dummy_mainloop
725 720 gtk.main = dummy_mainloop
726 721 return orig_mainloop
727 722
728 723 def hijack_qt():
729 724 """Modifies PyQt's mainloop with a dummy so user code does not
730 725 block IPython. This function returns the original
731 726 `qt.qApp.exec_loop` function that has been hijacked.
732 727 """
733 728 def dummy_mainloop(*args, **kw):
734 729 pass
735 730 import qt
736 731 orig_mainloop = qt.qApp.exec_loop
737 732 qt.qApp.exec_loop = dummy_mainloop
738 733 qt.QApplication.exec_loop = dummy_mainloop
739 734 return orig_mainloop
740 735
741 736 def hijack_qt4():
742 737 """Modifies PyQt4's mainloop with a dummy so user code does not
743 738 block IPython. This function returns the original
744 739 `QtGui.qApp.exec_` function that has been hijacked.
745 740 """
746 741 def dummy_mainloop(*args, **kw):
747 742 pass
748 743 from PyQt4 import QtGui, QtCore
749 744 orig_mainloop = QtGui.qApp.exec_
750 745 QtGui.qApp.exec_ = dummy_mainloop
751 746 QtGui.QApplication.exec_ = dummy_mainloop
752 747 QtCore.QCoreApplication.exec_ = dummy_mainloop
753 748 return orig_mainloop
754 749
755 750 #-----------------------------------------------------------------------------
756 751 # The IPShell* classes below are the ones meant to be run by external code as
757 752 # IPython instances. Note that unless a specific threading strategy is
758 753 # desired, the factory function start() below should be used instead (it
759 754 # selects the proper threaded class).
760 755
761 756 class IPThread(threading.Thread):
762 757 def run(self):
763 758 self.IP.mainloop(self._banner)
764 759 self.IP.kill()
765 760
766 761 class IPShellGTK(IPThread):
767 762 """Run a gtk mainloop() in a separate thread.
768 763
769 764 Python commands can be passed to the thread where they will be executed.
770 765 This is implemented by periodically checking for passed code using a
771 766 GTK timeout callback."""
772 767
773 768 TIMEOUT = 100 # Millisecond interval between timeouts.
774 769
775 770 def __init__(self,argv=None,user_ns=None,user_global_ns=None,
776 771 debug=1,shell_class=MTInteractiveShell):
777 772
778 773 import gtk
779 774
780 775 self.gtk = gtk
781 776 self.gtk_mainloop = hijack_gtk()
782 777
783 778 # Allows us to use both Tk and GTK.
784 779 self.tk = get_tk()
785 780
786 781 if gtk.pygtk_version >= (2,4,0): mainquit = self.gtk.main_quit
787 782 else: mainquit = self.gtk.mainquit
788 783
789 784 self.IP = make_IPython(argv,user_ns=user_ns,
790 785 user_global_ns=user_global_ns,
791 786 debug=debug,
792 787 shell_class=shell_class,
793 788 on_kill=[mainquit])
794 789
795 790 # HACK: slot for banner in self; it will be passed to the mainloop
796 791 # method only and .run() needs it. The actual value will be set by
797 792 # .mainloop().
798 793 self._banner = None
799 794
800 795 threading.Thread.__init__(self)
801 796
802 797 def mainloop(self,sys_exit=0,banner=None):
803 798
804 799 self._banner = banner
805 800
806 801 if self.gtk.pygtk_version >= (2,4,0):
807 802 import gobject
808 803 gobject.idle_add(self.on_timer)
809 804 else:
810 805 self.gtk.idle_add(self.on_timer)
811 806
812 807 if sys.platform != 'win32':
813 808 try:
814 809 if self.gtk.gtk_version[0] >= 2:
815 810 self.gtk.gdk.threads_init()
816 811 except AttributeError:
817 812 pass
818 813 except RuntimeError:
819 814 error('Your pyGTK likely has not been compiled with '
820 815 'threading support.\n'
821 816 'The exception printout is below.\n'
822 817 'You can either rebuild pyGTK with threads, or '
823 818 'try using \n'
824 819 'matplotlib with a different backend (like Tk or WX).\n'
825 820 'Note that matplotlib will most likely not work in its '
826 821 'current state!')
827 822 self.IP.InteractiveTB()
828 823
829 824 self.start()
830 825 self.gtk.gdk.threads_enter()
831 826 self.gtk_mainloop()
832 827 self.gtk.gdk.threads_leave()
833 828 self.join()
834 829
835 830 def on_timer(self):
836 831 """Called when GTK is idle.
837 832
838 833 Must return True always, otherwise GTK stops calling it"""
839 834
840 835 update_tk(self.tk)
841 836 self.IP.runcode()
842 837 time.sleep(0.01)
843 838 return True
844 839
845 840
846 841 class IPShellWX(IPThread):
847 842 """Run a wx mainloop() in a separate thread.
848 843
849 844 Python commands can be passed to the thread where they will be executed.
850 845 This is implemented by periodically checking for passed code using a
851 846 GTK timeout callback."""
852 847
853 848 TIMEOUT = 100 # Millisecond interval between timeouts.
854 849
855 850 def __init__(self,argv=None,user_ns=None,user_global_ns=None,
856 851 debug=1,shell_class=MTInteractiveShell):
857 852
858 853 self.IP = make_IPython(argv,user_ns=user_ns,
859 854 user_global_ns=user_global_ns,
860 855 debug=debug,
861 856 shell_class=shell_class,
862 857 on_kill=[self.wxexit])
863 858
864 859 wantedwxversion=self.IP.rc.wxversion
865 860 if wantedwxversion!="0":
866 861 try:
867 862 import wxversion
868 863 except ImportError:
869 864 error('The wxversion module is needed for WX version selection')
870 865 else:
871 866 try:
872 867 wxversion.select(wantedwxversion)
873 868 except:
874 869 self.IP.InteractiveTB()
875 870 error('Requested wxPython version %s could not be loaded' %
876 871 wantedwxversion)
877 872
878 873 import wx
879 874
880 875 threading.Thread.__init__(self)
881 876 self.wx = wx
882 877 self.wx_mainloop = hijack_wx()
883 878
884 879 # Allows us to use both Tk and GTK.
885 880 self.tk = get_tk()
886 881
887 882 # HACK: slot for banner in self; it will be passed to the mainloop
888 883 # method only and .run() needs it. The actual value will be set by
889 884 # .mainloop().
890 885 self._banner = None
891 886
892 887 self.app = None
893 888
894 889 def wxexit(self, *args):
895 890 if self.app is not None:
896 891 self.app.agent.timer.Stop()
897 892 self.app.ExitMainLoop()
898 893
899 894 def mainloop(self,sys_exit=0,banner=None):
900 895
901 896 self._banner = banner
902 897
903 898 self.start()
904 899
905 900 class TimerAgent(self.wx.MiniFrame):
906 901 wx = self.wx
907 902 IP = self.IP
908 903 tk = self.tk
909 904 def __init__(self, parent, interval):
910 905 style = self.wx.DEFAULT_FRAME_STYLE | self.wx.TINY_CAPTION_HORIZ
911 906 self.wx.MiniFrame.__init__(self, parent, -1, ' ', pos=(200, 200),
912 907 size=(100, 100),style=style)
913 908 self.Show(False)
914 909 self.interval = interval
915 910 self.timerId = self.wx.NewId()
916 911
917 912 def StartWork(self):
918 913 self.timer = self.wx.Timer(self, self.timerId)
919 914 self.wx.EVT_TIMER(self, self.timerId, self.OnTimer)
920 915 self.timer.Start(self.interval)
921 916
922 917 def OnTimer(self, event):
923 918 update_tk(self.tk)
924 919 self.IP.runcode()
925 920
926 921 class App(self.wx.App):
927 922 wx = self.wx
928 923 TIMEOUT = self.TIMEOUT
929 924 def OnInit(self):
930 925 'Create the main window and insert the custom frame'
931 926 self.agent = TimerAgent(None, self.TIMEOUT)
932 927 self.agent.Show(False)
933 928 self.agent.StartWork()
934 929 return True
935 930
936 931 self.app = App(redirect=False)
937 932 self.wx_mainloop(self.app)
938 933 self.join()
939 934
940 935
941 936 class IPShellQt(IPThread):
942 937 """Run a Qt event loop in a separate thread.
943 938
944 939 Python commands can be passed to the thread where they will be executed.
945 940 This is implemented by periodically checking for passed code using a
946 941 Qt timer / slot."""
947 942
948 943 TIMEOUT = 100 # Millisecond interval between timeouts.
949 944
950 945 def __init__(self, argv=None, user_ns=None, user_global_ns=None,
951 946 debug=0, shell_class=MTInteractiveShell):
952 947
953 948 import qt
954 949
955 950 self.exec_loop = hijack_qt()
956 951
957 952 # Allows us to use both Tk and QT.
958 953 self.tk = get_tk()
959 954
960 955 self.IP = make_IPython(argv,
961 956 user_ns=user_ns,
962 957 user_global_ns=user_global_ns,
963 958 debug=debug,
964 959 shell_class=shell_class,
965 960 on_kill=[qt.qApp.exit])
966 961
967 962 # HACK: slot for banner in self; it will be passed to the mainloop
968 963 # method only and .run() needs it. The actual value will be set by
969 964 # .mainloop().
970 965 self._banner = None
971 966
972 967 threading.Thread.__init__(self)
973 968
974 969 def mainloop(self, sys_exit=0, banner=None):
975 970
976 971 import qt
977 972
978 973 self._banner = banner
979 974
980 975 if qt.QApplication.startingUp():
981 976 a = qt.QApplication(sys.argv)
982 977
983 978 self.timer = qt.QTimer()
984 979 qt.QObject.connect(self.timer,
985 980 qt.SIGNAL('timeout()'),
986 981 self.on_timer)
987 982
988 983 self.start()
989 984 self.timer.start(self.TIMEOUT, True)
990 985 while True:
991 986 if self.IP._kill: break
992 987 self.exec_loop()
993 988 self.join()
994 989
995 990 def on_timer(self):
996 991 update_tk(self.tk)
997 992 result = self.IP.runcode()
998 993 self.timer.start(self.TIMEOUT, True)
999 994 return result
1000 995
1001 996
1002 997 class IPShellQt4(IPThread):
1003 998 """Run a Qt event loop in a separate thread.
1004 999
1005 1000 Python commands can be passed to the thread where they will be executed.
1006 1001 This is implemented by periodically checking for passed code using a
1007 1002 Qt timer / slot."""
1008 1003
1009 1004 TIMEOUT = 100 # Millisecond interval between timeouts.
1010 1005
1011 1006 def __init__(self, argv=None, user_ns=None, user_global_ns=None,
1012 1007 debug=0, shell_class=MTInteractiveShell):
1013 1008
1014 1009 from PyQt4 import QtCore, QtGui
1015 1010
1016 1011 try:
1017 1012 # present in PyQt4-4.2.1 or later
1018 1013 QtCore.pyqtRemoveInputHook()
1019 1014 except AttributeError:
1020 1015 pass
1021 1016
1022 1017 if QtCore.PYQT_VERSION_STR == '4.3':
1023 1018 warn('''PyQt4 version 4.3 detected.
1024 1019 If you experience repeated threading warnings, please update PyQt4.
1025 1020 ''')
1026 1021
1027 1022 self.exec_ = hijack_qt4()
1028 1023
1029 1024 # Allows us to use both Tk and QT.
1030 1025 self.tk = get_tk()
1031 1026
1032 1027 self.IP = make_IPython(argv,
1033 1028 user_ns=user_ns,
1034 1029 user_global_ns=user_global_ns,
1035 1030 debug=debug,
1036 1031 shell_class=shell_class,
1037 1032 on_kill=[QtGui.qApp.exit])
1038 1033
1039 1034 # HACK: slot for banner in self; it will be passed to the mainloop
1040 1035 # method only and .run() needs it. The actual value will be set by
1041 1036 # .mainloop().
1042 1037 self._banner = None
1043 1038
1044 1039 threading.Thread.__init__(self)
1045 1040
1046 1041 def mainloop(self, sys_exit=0, banner=None):
1047 1042
1048 1043 from PyQt4 import QtCore, QtGui
1049 1044
1050 1045 self._banner = banner
1051 1046
1052 1047 if QtGui.QApplication.startingUp():
1053 1048 a = QtGui.QApplication(sys.argv)
1054 1049
1055 1050 self.timer = QtCore.QTimer()
1056 1051 QtCore.QObject.connect(self.timer,
1057 1052 QtCore.SIGNAL('timeout()'),
1058 1053 self.on_timer)
1059 1054
1060 1055 self.start()
1061 1056 self.timer.start(self.TIMEOUT)
1062 1057 while True:
1063 1058 if self.IP._kill: break
1064 1059 self.exec_()
1065 1060 self.join()
1066 1061
1067 1062 def on_timer(self):
1068 1063 update_tk(self.tk)
1069 1064 result = self.IP.runcode()
1070 1065 self.timer.start(self.TIMEOUT)
1071 1066 return result
1072 1067
1073 1068
1074 1069 # A set of matplotlib public IPython shell classes, for single-threaded (Tk*
1075 1070 # and FLTK*) and multithreaded (GTK*, WX* and Qt*) backends to use.
1076 1071 def _load_pylab(user_ns):
1077 1072 """Allow users to disable pulling all of pylab into the top-level
1078 1073 namespace.
1079 1074
1080 1075 This little utility must be called AFTER the actual ipython instance is
1081 1076 running, since only then will the options file have been fully parsed."""
1082 1077
1083 1078 ip = IPython.ipapi.get()
1084 1079 if ip.options.pylab_import_all:
1085 1080 ip.ex("from matplotlib.pylab import *")
1086 1081 ip.IP.user_config_ns.update(ip.user_ns)
1087 1082
1088 1083
1089 1084 class IPShellMatplotlib(IPShell):
1090 1085 """Subclass IPShell with MatplotlibShell as the internal shell.
1091 1086
1092 1087 Single-threaded class, meant for the Tk* and FLTK* backends.
1093 1088
1094 1089 Having this on a separate class simplifies the external driver code."""
1095 1090
1096 1091 def __init__(self,argv=None,user_ns=None,user_global_ns=None,debug=1):
1097 1092 IPShell.__init__(self,argv,user_ns,user_global_ns,debug,
1098 1093 shell_class=MatplotlibShell)
1099 1094 _load_pylab(self.IP.user_ns)
1100 1095
1101 1096 class IPShellMatplotlibGTK(IPShellGTK):
1102 1097 """Subclass IPShellGTK with MatplotlibMTShell as the internal shell.
1103 1098
1104 1099 Multi-threaded class, meant for the GTK* backends."""
1105 1100
1106 1101 def __init__(self,argv=None,user_ns=None,user_global_ns=None,debug=1):
1107 1102 IPShellGTK.__init__(self,argv,user_ns,user_global_ns,debug,
1108 1103 shell_class=MatplotlibMTShell)
1109 1104 _load_pylab(self.IP.user_ns)
1110 1105
1111 1106 class IPShellMatplotlibWX(IPShellWX):
1112 1107 """Subclass IPShellWX with MatplotlibMTShell as the internal shell.
1113 1108
1114 1109 Multi-threaded class, meant for the WX* backends."""
1115 1110
1116 1111 def __init__(self,argv=None,user_ns=None,user_global_ns=None,debug=1):
1117 1112 IPShellWX.__init__(self,argv,user_ns,user_global_ns,debug,
1118 1113 shell_class=MatplotlibMTShell)
1119 1114 _load_pylab(self.IP.user_ns)
1120 1115
1121 1116 class IPShellMatplotlibQt(IPShellQt):
1122 1117 """Subclass IPShellQt with MatplotlibMTShell as the internal shell.
1123 1118
1124 1119 Multi-threaded class, meant for the Qt* backends."""
1125 1120
1126 1121 def __init__(self,argv=None,user_ns=None,user_global_ns=None,debug=1):
1127 1122 IPShellQt.__init__(self,argv,user_ns,user_global_ns,debug,
1128 1123 shell_class=MatplotlibMTShell)
1129 1124 _load_pylab(self.IP.user_ns)
1130 1125
1131 1126 class IPShellMatplotlibQt4(IPShellQt4):
1132 1127 """Subclass IPShellQt4 with MatplotlibMTShell as the internal shell.
1133 1128
1134 1129 Multi-threaded class, meant for the Qt4* backends."""
1135 1130
1136 1131 def __init__(self,argv=None,user_ns=None,user_global_ns=None,debug=1):
1137 1132 IPShellQt4.__init__(self,argv,user_ns,user_global_ns,debug,
1138 1133 shell_class=MatplotlibMTShell)
1139 1134 _load_pylab(self.IP.user_ns)
1140 1135
1141 1136 #-----------------------------------------------------------------------------
1142 1137 # Factory functions to actually start the proper thread-aware shell
1143 1138
1144 1139 def _select_shell(argv):
1145 1140 """Select a shell from the given argv vector.
1146 1141
1147 1142 This function implements the threading selection policy, allowing runtime
1148 1143 control of the threading mode, both for general users and for matplotlib.
1149 1144
1150 1145 Return:
1151 1146 Shell class to be instantiated for runtime operation.
1152 1147 """
1153 1148
1154 1149 global USE_TK
1155 1150
1156 1151 mpl_shell = {'gthread' : IPShellMatplotlibGTK,
1157 1152 'wthread' : IPShellMatplotlibWX,
1158 1153 'qthread' : IPShellMatplotlibQt,
1159 1154 'q4thread' : IPShellMatplotlibQt4,
1160 1155 'tkthread' : IPShellMatplotlib, # Tk is built-in
1161 1156 }
1162 1157
1163 1158 th_shell = {'gthread' : IPShellGTK,
1164 1159 'wthread' : IPShellWX,
1165 1160 'qthread' : IPShellQt,
1166 1161 'q4thread' : IPShellQt4,
1167 1162 'tkthread' : IPShell, # Tk is built-in
1168 1163 }
1169 1164
1170 1165 backends = {'gthread' : 'GTKAgg',
1171 1166 'wthread' : 'WXAgg',
1172 1167 'qthread' : 'QtAgg',
1173 1168 'q4thread' :'Qt4Agg',
1174 1169 'tkthread' :'TkAgg',
1175 1170 }
1176 1171
1177 1172 all_opts = set(['tk','pylab','gthread','qthread','q4thread','wthread',
1178 1173 'tkthread'])
1179 1174 user_opts = set([s.replace('-','') for s in argv[:3]])
1180 1175 special_opts = user_opts & all_opts
1181 1176
1182 1177 if 'tk' in special_opts:
1183 1178 USE_TK = True
1184 1179 special_opts.remove('tk')
1185 1180
1186 1181 if 'pylab' in special_opts:
1187 1182
1188 1183 try:
1189 1184 import matplotlib
1190 1185 except ImportError:
1191 1186 error('matplotlib could NOT be imported! Starting normal IPython.')
1192 1187 return IPShell
1193 1188
1194 1189 special_opts.remove('pylab')
1195 1190 # If there's any option left, it means the user wants to force the
1196 1191 # threading backend, else it's auto-selected from the rc file
1197 1192 if special_opts:
1198 1193 th_mode = special_opts.pop()
1199 1194 matplotlib.rcParams['backend'] = backends[th_mode]
1200 1195 else:
1201 1196 backend = matplotlib.rcParams['backend']
1202 1197 if backend.startswith('GTK'):
1203 1198 th_mode = 'gthread'
1204 1199 elif backend.startswith('WX'):
1205 1200 th_mode = 'wthread'
1206 1201 elif backend.startswith('Qt4'):
1207 1202 th_mode = 'q4thread'
1208 1203 elif backend.startswith('Qt'):
1209 1204 th_mode = 'qthread'
1210 1205 else:
1211 1206 # Any other backend, use plain Tk
1212 1207 th_mode = 'tkthread'
1213 1208
1214 1209 return mpl_shell[th_mode]
1215 1210 else:
1216 1211 # No pylab requested, just plain threads
1217 1212 try:
1218 1213 th_mode = special_opts.pop()
1219 1214 except KeyError:
1220 1215 th_mode = 'tkthread'
1221 1216 return th_shell[th_mode]
1222 1217
1223 1218
1224 1219 # This is the one which should be called by external code.
1225 1220 def start(user_ns = None):
1226 1221 """Return a running shell instance, dealing with threading options.
1227 1222
1228 1223 This is a factory function which will instantiate the proper IPython shell
1229 1224 based on the user's threading choice. Such a selector is needed because
1230 1225 different GUI toolkits require different thread handling details."""
1231 1226
1232 1227 shell = _select_shell(sys.argv)
1233 1228 return shell(user_ns = user_ns)
1234 1229
1235 1230 # Some aliases for backwards compatibility
1236 1231 IPythonShell = IPShell
1237 1232 IPythonShellEmbed = IPShellEmbed
1238 1233 #************************ End of file <Shell.py> ***************************
@@ -1,72 +1,71 b''
1 1 # -*- coding: utf-8 -*-
2 2 """
3 3 IPython -- An enhanced Interactive Python
4 4
5 5 One of Python's nicest features is its interactive interpreter. This allows
6 6 very fast testing of ideas without the overhead of creating test files as is
7 7 typical in most programming languages. However, the interpreter supplied with
8 8 the standard Python distribution is fairly primitive (and IDLE isn't really
9 9 much better).
10 10
11 11 IPython tries to:
12 12
13 13 i - provide an efficient environment for interactive work in Python
14 14 programming. It tries to address what we see as shortcomings of the standard
15 15 Python prompt, and adds many features to make interactive work much more
16 16 efficient.
17 17
18 18 ii - offer a flexible framework so that it can be used as the base
19 19 environment for other projects and problems where Python can be the
20 20 underlying language. Specifically scientific environments like Mathematica,
21 21 IDL and Mathcad inspired its design, but similar ideas can be useful in many
22 22 fields. Python is a fabulous language for implementing this kind of system
23 23 (due to its dynamic and introspective features), and with suitable libraries
24 24 entire systems could be built leveraging Python's power.
25 25
26 26 iii - serve as an embeddable, ready to go interpreter for your own programs.
27 27
28 IPython requires Python 2.3 or newer.
29
30 $Id: __init__.py 2399 2007-05-26 10:23:10Z vivainio $"""
28 IPython requires Python 2.4 or newer.
29 """
31 30
32 31 #*****************************************************************************
33 32 # Copyright (C) 2001-2006 Fernando Perez. <fperez@colorado.edu>
34 33 #
35 34 # Distributed under the terms of the BSD License. The full license is in
36 35 # the file COPYING, distributed as part of this software.
37 36 #*****************************************************************************
38 37
39 38 # Enforce proper version requirements
40 39 import sys
41 40
42 41 if sys.version[0:3] < '2.4':
43 42 raise ImportError('Python Version 2.4 or above is required for IPython.')
44 43
45 44 # Make it easy to import extensions - they are always directly on pythonpath.
46 45 # Therefore, non-IPython modules can be added to Extensions directory
47 46 import os
48 47 sys.path.append(os.path.dirname(__file__) + "/Extensions")
49 48
50 49 # Define what gets imported with a 'from IPython import *'
51 50 __all__ = ['ipapi','generics','ipstruct','Release','Shell']
52 51
53 52 # Load __all__ in IPython namespace so that a simple 'import IPython' gives
54 53 # access to them via IPython.<name>
55 54 glob,loc = globals(),locals()
56 55 for name in __all__:
57 56 #print 'Importing: ',name # dbg
58 57 __import__(name,glob,loc,[])
59 58
60 59 import Shell
61 60
62 61 # Release data
63 62 from IPython import Release # do it explicitly so pydoc can see it - pydoc bug
64 63 __author__ = '%s <%s>\n%s <%s>\n%s <%s>' % \
65 64 ( Release.authors['Fernando'] + Release.authors['Janko'] + \
66 65 Release.authors['Nathan'] )
67 66 __license__ = Release.license
68 67 __version__ = Release.version
69 68 __revision__ = Release.revision
70 69
71 70 # Namespace cleanup
72 71 del name,glob,loc
@@ -1,496 +1,490 b''
1 1 # -*- coding: utf-8 -*-
2 2 """Manage background (threaded) jobs conveniently from an interactive shell.
3 3
4 4 This module provides a BackgroundJobManager class. This is the main class
5 5 meant for public usage, it implements an object which can create and manage
6 6 new background jobs.
7 7
8 8 It also provides the actual job classes managed by these BackgroundJobManager
9 9 objects, see their docstrings below.
10 10
11 11
12 12 This system was inspired by discussions with B. Granger and the
13 13 BackgroundCommand class described in the book Python Scripting for
14 14 Computational Science, by H. P. Langtangen:
15 15
16 16 http://folk.uio.no/hpl/scripting
17 17
18 18 (although ultimately no code from this text was used, as IPython's system is a
19 19 separate implementation).
20
21 $Id: background_jobs.py 994 2006-01-08 08:29:44Z fperez $
22 20 """
23 21
24 22 #*****************************************************************************
25 23 # Copyright (C) 2005-2006 Fernando Perez <fperez@colorado.edu>
26 24 #
27 25 # Distributed under the terms of the BSD License. The full license is in
28 26 # the file COPYING, distributed as part of this software.
29 27 #*****************************************************************************
30 28
31 from IPython import Release
32 __author__ = '%s <%s>' % Release.authors['Fernando']
33 __license__ = Release.license
34
35 29 # Code begins
36 30 import sys
37 31 import threading
38 32
39 33 from IPython.ultraTB import AutoFormattedTB
40 34 from IPython.genutils import warn,error
41 35
42 36 class BackgroundJobManager:
43 37 """Class to manage a pool of backgrounded threaded jobs.
44 38
45 39 Below, we assume that 'jobs' is a BackgroundJobManager instance.
46 40
47 41 Usage summary (see the method docstrings for details):
48 42
49 43 jobs.new(...) -> start a new job
50 44
51 45 jobs() or jobs.status() -> print status summary of all jobs
52 46
53 47 jobs[N] -> returns job number N.
54 48
55 49 foo = jobs[N].result -> assign to variable foo the result of job N
56 50
57 51 jobs[N].traceback() -> print the traceback of dead job N
58 52
59 53 jobs.remove(N) -> remove (finished) job N
60 54
61 55 jobs.flush_finished() -> remove all finished jobs
62 56
63 57 As a convenience feature, BackgroundJobManager instances provide the
64 58 utility result and traceback methods which retrieve the corresponding
65 59 information from the jobs list:
66 60
67 61 jobs.result(N) <--> jobs[N].result
68 62 jobs.traceback(N) <--> jobs[N].traceback()
69 63
70 64 While this appears minor, it allows you to use tab completion
71 65 interactively on the job manager instance.
72 66
73 67 In interactive mode, IPython provides the magic fuction %bg for quick
74 68 creation of backgrounded expression-based jobs. Type bg? for details."""
75 69
76 70 def __init__(self):
77 71 # Lists for job management
78 72 self.jobs_run = []
79 73 self.jobs_comp = []
80 74 self.jobs_dead = []
81 75 # A dict of all jobs, so users can easily access any of them
82 76 self.jobs_all = {}
83 77 # For reporting
84 78 self._comp_report = []
85 79 self._dead_report = []
86 80 # Store status codes locally for fast lookups
87 81 self._s_created = BackgroundJobBase.stat_created_c
88 82 self._s_running = BackgroundJobBase.stat_running_c
89 83 self._s_completed = BackgroundJobBase.stat_completed_c
90 84 self._s_dead = BackgroundJobBase.stat_dead_c
91 85
92 86 def new(self,func_or_exp,*args,**kwargs):
93 87 """Add a new background job and start it in a separate thread.
94 88
95 89 There are two types of jobs which can be created:
96 90
97 91 1. Jobs based on expressions which can be passed to an eval() call.
98 92 The expression must be given as a string. For example:
99 93
100 94 job_manager.new('myfunc(x,y,z=1)'[,glob[,loc]])
101 95
102 96 The given expression is passed to eval(), along with the optional
103 97 global/local dicts provided. If no dicts are given, they are
104 98 extracted automatically from the caller's frame.
105 99
106 100 A Python statement is NOT a valid eval() expression. Basically, you
107 101 can only use as an eval() argument something which can go on the right
108 102 of an '=' sign and be assigned to a variable.
109 103
110 104 For example,"print 'hello'" is not valid, but '2+3' is.
111 105
112 106 2. Jobs given a function object, optionally passing additional
113 107 positional arguments:
114 108
115 109 job_manager.new(myfunc,x,y)
116 110
117 111 The function is called with the given arguments.
118 112
119 113 If you need to pass keyword arguments to your function, you must
120 114 supply them as a dict named kw:
121 115
122 116 job_manager.new(myfunc,x,y,kw=dict(z=1))
123 117
124 118 The reason for this assymmetry is that the new() method needs to
125 119 maintain access to its own keywords, and this prevents name collisions
126 120 between arguments to new() and arguments to your own functions.
127 121
128 122 In both cases, the result is stored in the job.result field of the
129 123 background job object.
130 124
131 125
132 126 Notes and caveats:
133 127
134 128 1. All threads running share the same standard output. Thus, if your
135 129 background jobs generate output, it will come out on top of whatever
136 130 you are currently writing. For this reason, background jobs are best
137 131 used with silent functions which simply return their output.
138 132
139 133 2. Threads also all work within the same global namespace, and this
140 134 system does not lock interactive variables. So if you send job to the
141 135 background which operates on a mutable object for a long time, and
142 136 start modifying that same mutable object interactively (or in another
143 137 backgrounded job), all sorts of bizarre behaviour will occur.
144 138
145 139 3. If a background job is spending a lot of time inside a C extension
146 140 module which does not release the Python Global Interpreter Lock
147 141 (GIL), this will block the IPython prompt. This is simply because the
148 142 Python interpreter can only switch between threads at Python
149 143 bytecodes. While the execution is inside C code, the interpreter must
150 144 simply wait unless the extension module releases the GIL.
151 145
152 146 4. There is no way, due to limitations in the Python threads library,
153 147 to kill a thread once it has started."""
154 148
155 149 if callable(func_or_exp):
156 150 kw = kwargs.get('kw',{})
157 151 job = BackgroundJobFunc(func_or_exp,*args,**kw)
158 152 elif isinstance(func_or_exp,basestring):
159 153 if not args:
160 154 frame = sys._getframe(1)
161 155 glob, loc = frame.f_globals, frame.f_locals
162 156 elif len(args)==1:
163 157 glob = loc = args[0]
164 158 elif len(args)==2:
165 159 glob,loc = args
166 160 else:
167 161 raise ValueError,\
168 162 'Expression jobs take at most 2 args (globals,locals)'
169 163 job = BackgroundJobExpr(func_or_exp,glob,loc)
170 164 else:
171 165 raise
172 166 jkeys = self.jobs_all.keys()
173 167 if jkeys:
174 168 job.num = max(jkeys)+1
175 169 else:
176 170 job.num = 0
177 171 self.jobs_run.append(job)
178 172 self.jobs_all[job.num] = job
179 173 print 'Starting job # %s in a separate thread.' % job.num
180 174 job.start()
181 175 return job
182 176
183 177 def __getitem__(self,key):
184 178 return self.jobs_all[key]
185 179
186 180 def __call__(self):
187 181 """An alias to self.status(),
188 182
189 183 This allows you to simply call a job manager instance much like the
190 184 Unix jobs shell command."""
191 185
192 186 return self.status()
193 187
194 188 def _update_status(self):
195 189 """Update the status of the job lists.
196 190
197 191 This method moves finished jobs to one of two lists:
198 192 - self.jobs_comp: jobs which completed successfully
199 193 - self.jobs_dead: jobs which finished but died.
200 194
201 195 It also copies those jobs to corresponding _report lists. These lists
202 196 are used to report jobs completed/dead since the last update, and are
203 197 then cleared by the reporting function after each call."""
204 198
205 199 run,comp,dead = self._s_running,self._s_completed,self._s_dead
206 200 jobs_run = self.jobs_run
207 201 for num in range(len(jobs_run)):
208 202 job = jobs_run[num]
209 203 stat = job.stat_code
210 204 if stat == run:
211 205 continue
212 206 elif stat == comp:
213 207 self.jobs_comp.append(job)
214 208 self._comp_report.append(job)
215 209 jobs_run[num] = False
216 210 elif stat == dead:
217 211 self.jobs_dead.append(job)
218 212 self._dead_report.append(job)
219 213 jobs_run[num] = False
220 214 self.jobs_run = filter(None,self.jobs_run)
221 215
222 216 def _group_report(self,group,name):
223 217 """Report summary for a given job group.
224 218
225 219 Return True if the group had any elements."""
226 220
227 221 if group:
228 222 print '%s jobs:' % name
229 223 for job in group:
230 224 print '%s : %s' % (job.num,job)
231 225 print
232 226 return True
233 227
234 228 def _group_flush(self,group,name):
235 229 """Flush a given job group
236 230
237 231 Return True if the group had any elements."""
238 232
239 233 njobs = len(group)
240 234 if njobs:
241 235 plural = {1:''}.setdefault(njobs,'s')
242 236 print 'Flushing %s %s job%s.' % (njobs,name,plural)
243 237 group[:] = []
244 238 return True
245 239
246 240 def _status_new(self):
247 241 """Print the status of newly finished jobs.
248 242
249 243 Return True if any new jobs are reported.
250 244
251 245 This call resets its own state every time, so it only reports jobs
252 246 which have finished since the last time it was called."""
253 247
254 248 self._update_status()
255 249 new_comp = self._group_report(self._comp_report,'Completed')
256 250 new_dead = self._group_report(self._dead_report,
257 251 'Dead, call job.traceback() for details')
258 252 self._comp_report[:] = []
259 253 self._dead_report[:] = []
260 254 return new_comp or new_dead
261 255
262 256 def status(self,verbose=0):
263 257 """Print a status of all jobs currently being managed."""
264 258
265 259 self._update_status()
266 260 self._group_report(self.jobs_run,'Running')
267 261 self._group_report(self.jobs_comp,'Completed')
268 262 self._group_report(self.jobs_dead,'Dead')
269 263 # Also flush the report queues
270 264 self._comp_report[:] = []
271 265 self._dead_report[:] = []
272 266
273 267 def remove(self,num):
274 268 """Remove a finished (completed or dead) job."""
275 269
276 270 try:
277 271 job = self.jobs_all[num]
278 272 except KeyError:
279 273 error('Job #%s not found' % num)
280 274 else:
281 275 stat_code = job.stat_code
282 276 if stat_code == self._s_running:
283 277 error('Job #%s is still running, it can not be removed.' % num)
284 278 return
285 279 elif stat_code == self._s_completed:
286 280 self.jobs_comp.remove(job)
287 281 elif stat_code == self._s_dead:
288 282 self.jobs_dead.remove(job)
289 283
290 284 def flush_finished(self):
291 285 """Flush all jobs finished (completed and dead) from lists.
292 286
293 287 Running jobs are never flushed.
294 288
295 289 It first calls _status_new(), to update info. If any jobs have
296 290 completed since the last _status_new() call, the flush operation
297 291 aborts."""
298 292
299 293 if self._status_new():
300 294 error('New jobs completed since last '\
301 295 '_status_new(), aborting flush.')
302 296 return
303 297
304 298 # Remove the finished jobs from the master dict
305 299 jobs_all = self.jobs_all
306 300 for job in self.jobs_comp+self.jobs_dead:
307 301 del(jobs_all[job.num])
308 302
309 303 # Now flush these lists completely
310 304 fl_comp = self._group_flush(self.jobs_comp,'Completed')
311 305 fl_dead = self._group_flush(self.jobs_dead,'Dead')
312 306 if not (fl_comp or fl_dead):
313 307 print 'No jobs to flush.'
314 308
315 309 def result(self,num):
316 310 """result(N) -> return the result of job N."""
317 311 try:
318 312 return self.jobs_all[num].result
319 313 except KeyError:
320 314 error('Job #%s not found' % num)
321 315
322 316 def traceback(self,num):
323 317 try:
324 318 self.jobs_all[num].traceback()
325 319 except KeyError:
326 320 error('Job #%s not found' % num)
327 321
328 322
329 323 class BackgroundJobBase(threading.Thread):
330 324 """Base class to build BackgroundJob classes.
331 325
332 326 The derived classes must implement:
333 327
334 328 - Their own __init__, since the one here raises NotImplementedError. The
335 329 derived constructor must call self._init() at the end, to provide common
336 330 initialization.
337 331
338 332 - A strform attribute used in calls to __str__.
339 333
340 334 - A call() method, which will make the actual execution call and must
341 335 return a value to be held in the 'result' field of the job object."""
342 336
343 337 # Class constants for status, in string and as numerical codes (when
344 338 # updating jobs lists, we don't want to do string comparisons). This will
345 339 # be done at every user prompt, so it has to be as fast as possible
346 340 stat_created = 'Created'; stat_created_c = 0
347 341 stat_running = 'Running'; stat_running_c = 1
348 342 stat_completed = 'Completed'; stat_completed_c = 2
349 343 stat_dead = 'Dead (Exception), call job.traceback() for details'
350 344 stat_dead_c = -1
351 345
352 346 def __init__(self):
353 347 raise NotImplementedError, \
354 348 "This class can not be instantiated directly."
355 349
356 350 def _init(self):
357 351 """Common initialization for all BackgroundJob objects"""
358 352
359 353 for attr in ['call','strform']:
360 354 assert hasattr(self,attr), "Missing attribute <%s>" % attr
361 355
362 356 # The num tag can be set by an external job manager
363 357 self.num = None
364 358
365 359 self.status = BackgroundJobBase.stat_created
366 360 self.stat_code = BackgroundJobBase.stat_created_c
367 361 self.finished = False
368 362 self.result = '<BackgroundJob has not completed>'
369 363 # reuse the ipython traceback handler if we can get to it, otherwise
370 364 # make a new one
371 365 try:
372 366 self._make_tb = __IPYTHON__.InteractiveTB.text
373 367 except:
374 368 self._make_tb = AutoFormattedTB(mode = 'Context',
375 369 color_scheme='NoColor',
376 370 tb_offset = 1).text
377 371 # Hold a formatted traceback if one is generated.
378 372 self._tb = None
379 373
380 374 threading.Thread.__init__(self)
381 375
382 376 def __str__(self):
383 377 return self.strform
384 378
385 379 def __repr__(self):
386 380 return '<BackgroundJob: %s>' % self.strform
387 381
388 382 def traceback(self):
389 383 print self._tb
390 384
391 385 def run(self):
392 386 try:
393 387 self.status = BackgroundJobBase.stat_running
394 388 self.stat_code = BackgroundJobBase.stat_running_c
395 389 self.result = self.call()
396 390 except:
397 391 self.status = BackgroundJobBase.stat_dead
398 392 self.stat_code = BackgroundJobBase.stat_dead_c
399 393 self.finished = None
400 394 self.result = ('<BackgroundJob died, call job.traceback() for details>')
401 395 self._tb = self._make_tb()
402 396 else:
403 397 self.status = BackgroundJobBase.stat_completed
404 398 self.stat_code = BackgroundJobBase.stat_completed_c
405 399 self.finished = True
406 400
407 401 class BackgroundJobExpr(BackgroundJobBase):
408 402 """Evaluate an expression as a background job (uses a separate thread)."""
409 403
410 404 def __init__(self,expression,glob=None,loc=None):
411 405 """Create a new job from a string which can be fed to eval().
412 406
413 407 global/locals dicts can be provided, which will be passed to the eval
414 408 call."""
415 409
416 410 # fail immediately if the given expression can't be compiled
417 411 self.code = compile(expression,'<BackgroundJob compilation>','eval')
418 412
419 413 if glob is None:
420 414 glob = {}
421 415 if loc is None:
422 416 loc = {}
423 417
424 418 self.expression = self.strform = expression
425 419 self.glob = glob
426 420 self.loc = loc
427 421 self._init()
428 422
429 423 def call(self):
430 424 return eval(self.code,self.glob,self.loc)
431 425
432 426 class BackgroundJobFunc(BackgroundJobBase):
433 427 """Run a function call as a background job (uses a separate thread)."""
434 428
435 429 def __init__(self,func,*args,**kwargs):
436 430 """Create a new job from a callable object.
437 431
438 432 Any positional arguments and keyword args given to this constructor
439 433 after the initial callable are passed directly to it."""
440 434
441 435 assert callable(func),'first argument must be callable'
442 436
443 437 if args is None:
444 438 args = []
445 439 if kwargs is None:
446 440 kwargs = {}
447 441
448 442 self.func = func
449 443 self.args = args
450 444 self.kwargs = kwargs
451 445 # The string form will only include the function passed, because
452 446 # generating string representations of the arguments is a potentially
453 447 # _very_ expensive operation (e.g. with large arrays).
454 448 self.strform = str(func)
455 449 self._init()
456 450
457 451 def call(self):
458 452 return self.func(*self.args,**self.kwargs)
459 453
460 454
461 455 if __name__=='__main__':
462 456
463 457 import time
464 458
465 459 def sleepfunc(interval=2,*a,**kw):
466 460 args = dict(interval=interval,
467 461 args=a,
468 462 kwargs=kw)
469 463 time.sleep(interval)
470 464 return args
471 465
472 466 def diefunc(interval=2,*a,**kw):
473 467 time.sleep(interval)
474 468 die
475 469
476 470 def printfunc(interval=1,reps=5):
477 471 for n in range(reps):
478 472 time.sleep(interval)
479 473 print 'In the background...'
480 474
481 475 jobs = BackgroundJobManager()
482 476 # first job will have # 0
483 477 jobs.new(sleepfunc,4)
484 478 jobs.new(sleepfunc,kw={'reps':2})
485 479 # This makes a job which will die
486 480 jobs.new(diefunc,1)
487 481 jobs.new('printfunc(1,3)')
488 482
489 483 # after a while, you can get the traceback of a dead job. Run the line
490 484 # below again interactively until it prints a traceback (check the status
491 485 # of the job):
492 486 print jobs[1].status
493 487 jobs[1].traceback()
494 488
495 489 # Run this line again until the printed result changes
496 490 print "The result of job #0 is:",jobs[0].result
@@ -1,189 +1,182 b''
1 1 # -*- coding: utf-8 -*-
2 2 """
3 3 A module to change reload() so that it acts recursively.
4 4 To enable it type:
5 5 >>> import __builtin__, deep_reload
6 6 >>> __builtin__.reload = deep_reload.reload
7 7
8 8 You can then disable it with:
9 9 >>> __builtin__.reload = deep_reload.original_reload
10 10
11 11 Alternatively, you can add a dreload builtin alongside normal reload with:
12 12 >>> __builtin__.dreload = deep_reload.reload
13 13
14 14 This code is almost entirely based on knee.py from the standard library.
15
16 $Id: deep_reload.py 958 2005-12-27 23:17:51Z fperez $"""
15 """
17 16
18 17 #*****************************************************************************
19 18 # Copyright (C) 2001 Nathaniel Gray <n8gray@caltech.edu>
20 19 #
21 20 # Distributed under the terms of the BSD License. The full license is in
22 21 # the file COPYING, distributed as part of this software.
23 22 #*****************************************************************************
24 23
25 from IPython import Release # do it explicitly so pydoc can see it - pydoc bug
26 __author__ = '%s <%s>' % Release.authors['Nathan']
27 __license__ = Release.license
28 __version__ = "0.5"
29 __date__ = "21 August 2001"
30
31 24 import __builtin__
32 25 import imp
33 26 import sys
34 27
35 28 # Replacement for __import__()
36 29 def deep_import_hook(name, globals=None, locals=None, fromlist=None, level=-1):
37 30 # For now level is ignored, it's just there to prevent crash
38 31 # with from __future__ import absolute_import
39 32 parent = determine_parent(globals)
40 33 q, tail = find_head_package(parent, name)
41 34 m = load_tail(q, tail)
42 35 if not fromlist:
43 36 return q
44 37 if hasattr(m, "__path__"):
45 38 ensure_fromlist(m, fromlist)
46 39 return m
47 40
48 41 def determine_parent(globals):
49 42 if not globals or not globals.has_key("__name__"):
50 43 return None
51 44 pname = globals['__name__']
52 45 if globals.has_key("__path__"):
53 46 parent = sys.modules[pname]
54 47 assert globals is parent.__dict__
55 48 return parent
56 49 if '.' in pname:
57 50 i = pname.rfind('.')
58 51 pname = pname[:i]
59 52 parent = sys.modules[pname]
60 53 assert parent.__name__ == pname
61 54 return parent
62 55 return None
63 56
64 57 def find_head_package(parent, name):
65 58 # Import the first
66 59 if '.' in name:
67 60 # 'some.nested.package' -> head = 'some', tail = 'nested.package'
68 61 i = name.find('.')
69 62 head = name[:i]
70 63 tail = name[i+1:]
71 64 else:
72 65 # 'packagename' -> head = 'packagename', tail = ''
73 66 head = name
74 67 tail = ""
75 68 if parent:
76 69 # If this is a subpackage then qname = parent's name + head
77 70 qname = "%s.%s" % (parent.__name__, head)
78 71 else:
79 72 qname = head
80 73 q = import_module(head, qname, parent)
81 74 if q: return q, tail
82 75 if parent:
83 76 qname = head
84 77 parent = None
85 78 q = import_module(head, qname, parent)
86 79 if q: return q, tail
87 80 raise ImportError, "No module named " + qname
88 81
89 82 def load_tail(q, tail):
90 83 m = q
91 84 while tail:
92 85 i = tail.find('.')
93 86 if i < 0: i = len(tail)
94 87 head, tail = tail[:i], tail[i+1:]
95 88
96 89 # fperez: fix dotted.name reloading failures by changing:
97 90 #mname = "%s.%s" % (m.__name__, head)
98 91 # to:
99 92 mname = m.__name__
100 93 # This needs more testing!!! (I don't understand this module too well)
101 94
102 95 #print '** head,tail=|%s|->|%s|, mname=|%s|' % (head,tail,mname) # dbg
103 96 m = import_module(head, mname, m)
104 97 if not m:
105 98 raise ImportError, "No module named " + mname
106 99 return m
107 100
108 101 def ensure_fromlist(m, fromlist, recursive=0):
109 102 for sub in fromlist:
110 103 if sub == "*":
111 104 if not recursive:
112 105 try:
113 106 all = m.__all__
114 107 except AttributeError:
115 108 pass
116 109 else:
117 110 ensure_fromlist(m, all, 1)
118 111 continue
119 112 if sub != "*" and not hasattr(m, sub):
120 113 subname = "%s.%s" % (m.__name__, sub)
121 114 submod = import_module(sub, subname, m)
122 115 if not submod:
123 116 raise ImportError, "No module named " + subname
124 117
125 118 # Need to keep track of what we've already reloaded to prevent cyclic evil
126 119 found_now = {}
127 120
128 121 def import_module(partname, fqname, parent):
129 122 global found_now
130 123 if found_now.has_key(fqname):
131 124 try:
132 125 return sys.modules[fqname]
133 126 except KeyError:
134 127 pass
135 128
136 129 print 'Reloading', fqname #, sys.excepthook is sys.__excepthook__, \
137 130 #sys.displayhook is sys.__displayhook__
138 131
139 132 found_now[fqname] = 1
140 133 try:
141 134 fp, pathname, stuff = imp.find_module(partname,
142 135 parent and parent.__path__)
143 136 except ImportError:
144 137 return None
145 138
146 139 try:
147 140 m = imp.load_module(fqname, fp, pathname, stuff)
148 141 finally:
149 142 if fp: fp.close()
150 143
151 144 if parent:
152 145 setattr(parent, partname, m)
153 146
154 147 return m
155 148
156 149 def deep_reload_hook(module):
157 150 name = module.__name__
158 151 if '.' not in name:
159 152 return import_module(name, name, None)
160 153 i = name.rfind('.')
161 154 pname = name[:i]
162 155 parent = sys.modules[pname]
163 156 return import_module(name[i+1:], name, parent)
164 157
165 158 # Save the original hooks
166 159 original_reload = __builtin__.reload
167 160
168 161 # Replacement for reload()
169 162 def reload(module, exclude=['sys', '__builtin__', '__main__']):
170 163 """Recursively reload all modules used in the given module. Optionally
171 164 takes a list of modules to exclude from reloading. The default exclude
172 165 list contains sys, __main__, and __builtin__, to prevent, e.g., resetting
173 166 display, exception, and io hooks.
174 167 """
175 168 global found_now
176 169 for i in exclude:
177 170 found_now[i] = 1
178 171 original_import = __builtin__.__import__
179 172 __builtin__.__import__ = deep_import_hook
180 173 try:
181 174 ret = deep_reload_hook(module)
182 175 finally:
183 176 __builtin__.__import__ = original_import
184 177 found_now = {}
185 178 return ret
186 179
187 180 # Uncomment the following to automatically activate deep reloading whenever
188 181 # this module is imported
189 182 #__builtin__.reload = reload
@@ -1,143 +1,137 b''
1 1 # -*- coding: utf-8 -*-
2 2 """
3 3 Color schemes for exception handling code in IPython.
4
5 $Id: Prompts.py 638 2005-07-18 03:01:41Z fperez $"""
4 """
6 5
7 6 #*****************************************************************************
8 7 # Copyright (C) 2005-2006 Fernando Perez <fperez@colorado.edu>
9 8 #
10 9 # Distributed under the terms of the BSD License. The full license is in
11 10 # the file COPYING, distributed as part of this software.
12 11 #*****************************************************************************
13 12
14 from IPython import Release
15 __author__ = '%s <%s>' % Release.authors['Fernando']
16 __license__ = Release.license
17 __version__ = Release.version
18
19 13 #****************************************************************************
20 14 # Required modules
21 15 from IPython.ColorANSI import ColorSchemeTable, TermColors, ColorScheme
22 16
23 17 def exception_colors():
24 18 """Return a color table with fields for exception reporting.
25 19
26 20 The table is an instance of ColorSchemeTable with schemes added for
27 21 'Linux', 'LightBG' and 'NoColor' and fields for exception handling filled
28 22 in.
29 23
30 24 Examples:
31 25
32 26 >>> ec = exception_colors()
33 27 >>> ec.active_scheme_name
34 28 ''
35 29 >>> print ec.active_colors
36 30 None
37 31
38 32 Now we activate a color scheme:
39 33 >>> ec.set_active_scheme('NoColor')
40 34 >>> ec.active_scheme_name
41 35 'NoColor'
42 36 >>> ec.active_colors.keys()
43 37 ['em', 'caret', '__allownew', 'name', 'val', 'vName', 'Normal', 'normalEm',
44 38 'filename', 'linenoEm', 'excName', 'lineno', 'valEm', 'filenameEm',
45 39 'nameEm', 'line', 'topline']
46 40 """
47 41
48 42 ex_colors = ColorSchemeTable()
49 43
50 44 # Populate it with color schemes
51 45 C = TermColors # shorthand and local lookup
52 46 ex_colors.add_scheme(ColorScheme(
53 47 'NoColor',
54 48 # The color to be used for the top line
55 49 topline = C.NoColor,
56 50
57 51 # The colors to be used in the traceback
58 52 filename = C.NoColor,
59 53 lineno = C.NoColor,
60 54 name = C.NoColor,
61 55 vName = C.NoColor,
62 56 val = C.NoColor,
63 57 em = C.NoColor,
64 58
65 59 # Emphasized colors for the last frame of the traceback
66 60 normalEm = C.NoColor,
67 61 filenameEm = C.NoColor,
68 62 linenoEm = C.NoColor,
69 63 nameEm = C.NoColor,
70 64 valEm = C.NoColor,
71 65
72 66 # Colors for printing the exception
73 67 excName = C.NoColor,
74 68 line = C.NoColor,
75 69 caret = C.NoColor,
76 70 Normal = C.NoColor
77 71 ))
78 72
79 73 # make some schemes as instances so we can copy them for modification easily
80 74 ex_colors.add_scheme(ColorScheme(
81 75 'Linux',
82 76 # The color to be used for the top line
83 77 topline = C.LightRed,
84 78
85 79 # The colors to be used in the traceback
86 80 filename = C.Green,
87 81 lineno = C.Green,
88 82 name = C.Purple,
89 83 vName = C.Cyan,
90 84 val = C.Green,
91 85 em = C.LightCyan,
92 86
93 87 # Emphasized colors for the last frame of the traceback
94 88 normalEm = C.LightCyan,
95 89 filenameEm = C.LightGreen,
96 90 linenoEm = C.LightGreen,
97 91 nameEm = C.LightPurple,
98 92 valEm = C.LightBlue,
99 93
100 94 # Colors for printing the exception
101 95 excName = C.LightRed,
102 96 line = C.Yellow,
103 97 caret = C.White,
104 98 Normal = C.Normal
105 99 ))
106 100
107 101 # For light backgrounds, swap dark/light colors
108 102 ex_colors.add_scheme(ColorScheme(
109 103 'LightBG',
110 104 # The color to be used for the top line
111 105 topline = C.Red,
112 106
113 107 # The colors to be used in the traceback
114 108 filename = C.LightGreen,
115 109 lineno = C.LightGreen,
116 110 name = C.LightPurple,
117 111 vName = C.Cyan,
118 112 val = C.LightGreen,
119 113 em = C.Cyan,
120 114
121 115 # Emphasized colors for the last frame of the traceback
122 116 normalEm = C.Cyan,
123 117 filenameEm = C.Green,
124 118 linenoEm = C.Green,
125 119 nameEm = C.Purple,
126 120 valEm = C.Blue,
127 121
128 122 # Colors for printing the exception
129 123 excName = C.Red,
130 124 #line = C.Brown, # brown often is displayed as yellow
131 125 line = C.Red,
132 126 caret = C.Normal,
133 127 Normal = C.Normal
134 128 ))
135 129
136 130 return ex_colors
137 131
138 132
139 133 # For backwards compatibility, keep around a single global object. Note that
140 134 # this should NOT be used, the factory function should be used instead, since
141 135 # these objects are stateful and it's very easy to get strange bugs if any code
142 136 # modifies the module-level object's state.
143 137 ExceptionColors = exception_colors()
@@ -1,278 +1,276 b''
1 1 # -*- coding: utf-8 -*-
2 2 """String interpolation for Python (by Ka-Ping Yee, 14 Feb 2000).
3 3
4 4 This module lets you quickly and conveniently interpolate values into
5 5 strings (in the flavour of Perl or Tcl, but with less extraneous
6 6 punctuation). You get a bit more power than in the other languages,
7 7 because this module allows subscripting, slicing, function calls,
8 8 attribute lookup, or arbitrary expressions. Variables and expressions
9 9 are evaluated in the namespace of the caller.
10 10
11 11 The itpl() function returns the result of interpolating a string, and
12 12 printpl() prints out an interpolated string. Here are some examples:
13 13
14 14 from Itpl import printpl
15 15 printpl("Here is a $string.")
16 16 printpl("Here is a $module.member.")
17 17 printpl("Here is an $object.member.")
18 18 printpl("Here is a $functioncall(with, arguments).")
19 19 printpl("Here is an ${arbitrary + expression}.")
20 20 printpl("Here is an $array[3] member.")
21 21 printpl("Here is a $dictionary['member'].")
22 22
23 23 The filter() function filters a file object so that output through it
24 24 is interpolated. This lets you produce the illusion that Python knows
25 25 how to do interpolation:
26 26
27 27 import Itpl
28 28 sys.stdout = Itpl.filter()
29 29 f = "fancy"
30 print "Isn't this $f?"
30 print "Is this not $f?"
31 31 print "Standard output has been replaced with a $sys.stdout object."
32 32 sys.stdout = Itpl.unfilter()
33 33 print "Okay, back $to $normal."
34 34
35 35 Under the hood, the Itpl class represents a string that knows how to
36 36 interpolate values. An instance of the class parses the string once
37 37 upon initialization; the evaluation and substitution can then be done
38 38 each time the instance is evaluated with str(instance). For example:
39 39
40 40 from Itpl import Itpl
41 41 s = Itpl("Here is $foo.")
42 42 foo = 5
43 43 print str(s)
44 44 foo = "bar"
45 45 print str(s)
46
47 $Id: Itpl.py 2305 2007-05-04 05:34:42Z bgranger $
48 """ # ' -> close an open quote for stupid emacs
46 """
49 47
50 48 #*****************************************************************************
51 49 #
52 50 # Copyright (c) 2001 Ka-Ping Yee <ping@lfw.org>
53 51 #
54 52 #
55 53 # Published under the terms of the MIT license, hereby reproduced:
56 54 #
57 55 # Permission is hereby granted, free of charge, to any person obtaining a copy
58 56 # of this software and associated documentation files (the "Software"), to
59 57 # deal in the Software without restriction, including without limitation the
60 58 # rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
61 59 # sell copies of the Software, and to permit persons to whom the Software is
62 60 # furnished to do so, subject to the following conditions:
63 61 #
64 62 # The above copyright notice and this permission notice shall be included in
65 63 # all copies or substantial portions of the Software.
66 64 #
67 65 # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
68 66 # IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
69 67 # FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
70 68 # AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
71 69 # LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
72 70 # FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
73 71 # IN THE SOFTWARE.
74 72 #
75 73 #*****************************************************************************
76 74
77 75 __author__ = 'Ka-Ping Yee <ping@lfw.org>'
78 76 __license__ = 'MIT'
79 77
80 78 import string
81 79 import sys
82 80 from tokenize import tokenprog
83 81 from types import StringType
84 82
85 83 class ItplError(ValueError):
86 84 def __init__(self, text, pos):
87 85 self.text = text
88 86 self.pos = pos
89 87 def __str__(self):
90 88 return "unfinished expression in %s at char %d" % (
91 89 repr(self.text), self.pos)
92 90
93 91 def matchorfail(text, pos):
94 92 match = tokenprog.match(text, pos)
95 93 if match is None:
96 94 raise ItplError(text, pos)
97 95 return match, match.end()
98 96
99 97 class Itpl:
100 98 """Class representing a string with interpolation abilities.
101 99
102 100 Upon creation, an instance works out what parts of the format
103 101 string are literal and what parts need to be evaluated. The
104 102 evaluation and substitution happens in the namespace of the
105 103 caller when str(instance) is called."""
106 104
107 105 def __init__(self, format,codec='utf_8',encoding_errors='backslashreplace'):
108 106 """The single mandatory argument to this constructor is a format
109 107 string.
110 108
111 109 The format string is parsed according to the following rules:
112 110
113 111 1. A dollar sign and a name, possibly followed by any of:
114 112 - an open-paren, and anything up to the matching paren
115 113 - an open-bracket, and anything up to the matching bracket
116 114 - a period and a name
117 115 any number of times, is evaluated as a Python expression.
118 116
119 117 2. A dollar sign immediately followed by an open-brace, and
120 118 anything up to the matching close-brace, is evaluated as
121 119 a Python expression.
122 120
123 121 3. Outside of the expressions described in the above two rules,
124 122 two dollar signs in a row give you one literal dollar sign.
125 123
126 124 Optional arguments:
127 125
128 126 - codec('utf_8'): a string containing the name of a valid Python
129 127 codec.
130 128
131 129 - encoding_errors('backslashreplace'): a string with a valid error handling
132 130 policy. See the codecs module documentation for details.
133 131
134 132 These are used to encode the format string if a call to str() fails on
135 133 the expanded result."""
136 134
137 135 if not isinstance(format,basestring):
138 136 raise TypeError, "needs string initializer"
139 137 self.format = format
140 138 self.codec = codec
141 139 self.encoding_errors = encoding_errors
142 140
143 141 namechars = "abcdefghijklmnopqrstuvwxyz" \
144 142 "ABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789_";
145 143 chunks = []
146 144 pos = 0
147 145
148 146 while 1:
149 147 dollar = string.find(format, "$", pos)
150 148 if dollar < 0: break
151 149 nextchar = format[dollar+1]
152 150
153 151 if nextchar == "{":
154 152 chunks.append((0, format[pos:dollar]))
155 153 pos, level = dollar+2, 1
156 154 while level:
157 155 match, pos = matchorfail(format, pos)
158 156 tstart, tend = match.regs[3]
159 157 token = format[tstart:tend]
160 158 if token == "{": level = level+1
161 159 elif token == "}": level = level-1
162 160 chunks.append((1, format[dollar+2:pos-1]))
163 161
164 162 elif nextchar in namechars:
165 163 chunks.append((0, format[pos:dollar]))
166 164 match, pos = matchorfail(format, dollar+1)
167 165 while pos < len(format):
168 166 if format[pos] == "." and \
169 167 pos+1 < len(format) and format[pos+1] in namechars:
170 168 match, pos = matchorfail(format, pos+1)
171 169 elif format[pos] in "([":
172 170 pos, level = pos+1, 1
173 171 while level:
174 172 match, pos = matchorfail(format, pos)
175 173 tstart, tend = match.regs[3]
176 174 token = format[tstart:tend]
177 175 if token[0] in "([": level = level+1
178 176 elif token[0] in ")]": level = level-1
179 177 else: break
180 178 chunks.append((1, format[dollar+1:pos]))
181 179
182 180 else:
183 181 chunks.append((0, format[pos:dollar+1]))
184 182 pos = dollar + 1 + (nextchar == "$")
185 183
186 184 if pos < len(format): chunks.append((0, format[pos:]))
187 185 self.chunks = chunks
188 186
189 187 def __repr__(self):
190 188 return "<Itpl %s >" % repr(self.format)
191 189
192 190 def _str(self,glob,loc):
193 191 """Evaluate to a string in the given globals/locals.
194 192
195 193 The final output is built by calling str(), but if this fails, the
196 194 result is encoded with the instance's codec and error handling policy,
197 195 via a call to out.encode(self.codec,self.encoding_errors)"""
198 196 result = []
199 197 app = result.append
200 198 for live, chunk in self.chunks:
201 199 if live: app(str(eval(chunk,glob,loc)))
202 200 else: app(chunk)
203 201 out = ''.join(result)
204 202 try:
205 203 return str(out)
206 204 except UnicodeError:
207 205 return out.encode(self.codec,self.encoding_errors)
208 206
209 207 def __str__(self):
210 208 """Evaluate and substitute the appropriate parts of the string."""
211 209
212 210 # We need to skip enough frames to get to the actual caller outside of
213 211 # Itpl.
214 212 frame = sys._getframe(1)
215 213 while frame.f_globals["__name__"] == __name__: frame = frame.f_back
216 214 loc, glob = frame.f_locals, frame.f_globals
217 215
218 216 return self._str(glob,loc)
219 217
220 218 class ItplNS(Itpl):
221 219 """Class representing a string with interpolation abilities.
222 220
223 221 This inherits from Itpl, but at creation time a namespace is provided
224 222 where the evaluation will occur. The interpolation becomes a bit more
225 223 efficient, as no traceback needs to be extracte. It also allows the
226 224 caller to supply a different namespace for the interpolation to occur than
227 225 its own."""
228 226
229 227 def __init__(self, format,globals,locals=None,
230 228 codec='utf_8',encoding_errors='backslashreplace'):
231 229 """ItplNS(format,globals[,locals]) -> interpolating string instance.
232 230
233 231 This constructor, besides a format string, takes a globals dictionary
234 232 and optionally a locals (which defaults to globals if not provided).
235 233
236 234 For further details, see the Itpl constructor."""
237 235
238 236 if locals is None:
239 237 locals = globals
240 238 self.globals = globals
241 239 self.locals = locals
242 240 Itpl.__init__(self,format,codec,encoding_errors)
243 241
244 242 def __str__(self):
245 243 """Evaluate and substitute the appropriate parts of the string."""
246 244 return self._str(self.globals,self.locals)
247 245
248 246 def __repr__(self):
249 247 return "<ItplNS %s >" % repr(self.format)
250 248
251 249 # utilities for fast printing
252 250 def itpl(text): return str(Itpl(text))
253 251 def printpl(text): print itpl(text)
254 252 # versions with namespace
255 253 def itplns(text,globals,locals=None): return str(ItplNS(text,globals,locals))
256 254 def printplns(text,globals,locals=None): print itplns(text,globals,locals)
257 255
258 256 class ItplFile:
259 257 """A file object that filters each write() through an interpolator."""
260 258 def __init__(self, file): self.file = file
261 259 def __repr__(self): return "<interpolated " + repr(self.file) + ">"
262 260 def __getattr__(self, attr): return getattr(self.file, attr)
263 261 def write(self, text): self.file.write(str(Itpl(text)))
264 262
265 263 def filter(file=sys.stdout):
266 264 """Return an ItplFile that filters writes to the given file object.
267 265
268 266 'file = filter(file)' replaces 'file' with a filtered object that
269 267 has a write() method. When called with no argument, this creates
270 268 a filter to sys.stdout."""
271 269 return ItplFile(file)
272 270
273 271 def unfilter(ifile=None):
274 272 """Return the original file that corresponds to the given ItplFile.
275 273
276 274 'file = unfilter(file)' undoes the effect of 'file = filter(file)'.
277 275 'sys.stdout = unfilter()' undoes the effect of 'sys.stdout = filter()'."""
278 276 return ifile and ifile.file or sys.stdout.file
1 NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
General Comments 0
You need to be logged in to leave comments. Login now