##// 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 # -*- coding: utf-8 -*-
1 # -*- coding: utf-8 -*-
2 """Tools for coloring text in ANSI terminals.
2 """Tools for coloring text in ANSI terminals.
3
3 """
4 $Id: ColorANSI.py 2167 2007-03-21 06:57:50Z fperez $"""
5
4
6 #*****************************************************************************
5 #*****************************************************************************
7 # Copyright (C) 2002-2006 Fernando Perez. <fperez@colorado.edu>
6 # Copyright (C) 2002-2006 Fernando Perez. <fperez@colorado.edu>
8 #
7 #
9 # Distributed under the terms of the BSD License. The full license is in
8 # Distributed under the terms of the BSD License. The full license is in
10 # the file COPYING, distributed as part of this software.
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 __all__ = ['TermColors','InputTermColors','ColorScheme','ColorSchemeTable']
12 __all__ = ['TermColors','InputTermColors','ColorScheme','ColorSchemeTable']
18
13
19 import os
14 import os
20
15
21 from IPython.ipstruct import Struct
16 from IPython.ipstruct import Struct
22
17
23 def make_color_table(in_class):
18 def make_color_table(in_class):
24 """Build a set of color attributes in a class.
19 """Build a set of color attributes in a class.
25
20
26 Helper function for building the *TermColors classes."""
21 Helper function for building the *TermColors classes."""
27
22
28 color_templates = (
23 color_templates = (
29 # Dark colors
24 # Dark colors
30 ("Black" , "0;30"),
25 ("Black" , "0;30"),
31 ("Red" , "0;31"),
26 ("Red" , "0;31"),
32 ("Green" , "0;32"),
27 ("Green" , "0;32"),
33 ("Brown" , "0;33"),
28 ("Brown" , "0;33"),
34 ("Blue" , "0;34"),
29 ("Blue" , "0;34"),
35 ("Purple" , "0;35"),
30 ("Purple" , "0;35"),
36 ("Cyan" , "0;36"),
31 ("Cyan" , "0;36"),
37 ("LightGray" , "0;37"),
32 ("LightGray" , "0;37"),
38 # Light colors
33 # Light colors
39 ("DarkGray" , "1;30"),
34 ("DarkGray" , "1;30"),
40 ("LightRed" , "1;31"),
35 ("LightRed" , "1;31"),
41 ("LightGreen" , "1;32"),
36 ("LightGreen" , "1;32"),
42 ("Yellow" , "1;33"),
37 ("Yellow" , "1;33"),
43 ("LightBlue" , "1;34"),
38 ("LightBlue" , "1;34"),
44 ("LightPurple" , "1;35"),
39 ("LightPurple" , "1;35"),
45 ("LightCyan" , "1;36"),
40 ("LightCyan" , "1;36"),
46 ("White" , "1;37"),
41 ("White" , "1;37"),
47 # Blinking colors. Probably should not be used in anything serious.
42 # Blinking colors. Probably should not be used in anything serious.
48 ("BlinkBlack" , "5;30"),
43 ("BlinkBlack" , "5;30"),
49 ("BlinkRed" , "5;31"),
44 ("BlinkRed" , "5;31"),
50 ("BlinkGreen" , "5;32"),
45 ("BlinkGreen" , "5;32"),
51 ("BlinkYellow" , "5;33"),
46 ("BlinkYellow" , "5;33"),
52 ("BlinkBlue" , "5;34"),
47 ("BlinkBlue" , "5;34"),
53 ("BlinkPurple" , "5;35"),
48 ("BlinkPurple" , "5;35"),
54 ("BlinkCyan" , "5;36"),
49 ("BlinkCyan" , "5;36"),
55 ("BlinkLightGray", "5;37"),
50 ("BlinkLightGray", "5;37"),
56 )
51 )
57
52
58 for name,value in color_templates:
53 for name,value in color_templates:
59 setattr(in_class,name,in_class._base % value)
54 setattr(in_class,name,in_class._base % value)
60
55
61 class TermColors:
56 class TermColors:
62 """Color escape sequences.
57 """Color escape sequences.
63
58
64 This class defines the escape sequences for all the standard (ANSI?)
59 This class defines the escape sequences for all the standard (ANSI?)
65 colors in terminals. Also defines a NoColor escape which is just the null
60 colors in terminals. Also defines a NoColor escape which is just the null
66 string, suitable for defining 'dummy' color schemes in terminals which get
61 string, suitable for defining 'dummy' color schemes in terminals which get
67 confused by color escapes.
62 confused by color escapes.
68
63
69 This class should be used as a mixin for building color schemes."""
64 This class should be used as a mixin for building color schemes."""
70
65
71 NoColor = '' # for color schemes in color-less terminals.
66 NoColor = '' # for color schemes in color-less terminals.
72 Normal = '\033[0m' # Reset normal coloring
67 Normal = '\033[0m' # Reset normal coloring
73 _base = '\033[%sm' # Template for all other colors
68 _base = '\033[%sm' # Template for all other colors
74
69
75 # Build the actual color table as a set of class attributes:
70 # Build the actual color table as a set of class attributes:
76 make_color_table(TermColors)
71 make_color_table(TermColors)
77
72
78 class InputTermColors:
73 class InputTermColors:
79 """Color escape sequences for input prompts.
74 """Color escape sequences for input prompts.
80
75
81 This class is similar to TermColors, but the escapes are wrapped in \001
76 This class is similar to TermColors, but the escapes are wrapped in \001
82 and \002 so that readline can properly know the length of each line and
77 and \002 so that readline can properly know the length of each line and
83 can wrap lines accordingly. Use this class for any colored text which
78 can wrap lines accordingly. Use this class for any colored text which
84 needs to be used in input prompts, such as in calls to raw_input().
79 needs to be used in input prompts, such as in calls to raw_input().
85
80
86 This class defines the escape sequences for all the standard (ANSI?)
81 This class defines the escape sequences for all the standard (ANSI?)
87 colors in terminals. Also defines a NoColor escape which is just the null
82 colors in terminals. Also defines a NoColor escape which is just the null
88 string, suitable for defining 'dummy' color schemes in terminals which get
83 string, suitable for defining 'dummy' color schemes in terminals which get
89 confused by color escapes.
84 confused by color escapes.
90
85
91 This class should be used as a mixin for building color schemes."""
86 This class should be used as a mixin for building color schemes."""
92
87
93 NoColor = '' # for color schemes in color-less terminals.
88 NoColor = '' # for color schemes in color-less terminals.
94
89
95 if os.name == 'nt' and os.environ.get('TERM','dumb') == 'emacs':
90 if os.name == 'nt' and os.environ.get('TERM','dumb') == 'emacs':
96 # (X)emacs on W32 gets confused with \001 and \002 so we remove them
91 # (X)emacs on W32 gets confused with \001 and \002 so we remove them
97 Normal = '\033[0m' # Reset normal coloring
92 Normal = '\033[0m' # Reset normal coloring
98 _base = '\033[%sm' # Template for all other colors
93 _base = '\033[%sm' # Template for all other colors
99 else:
94 else:
100 Normal = '\001\033[0m\002' # Reset normal coloring
95 Normal = '\001\033[0m\002' # Reset normal coloring
101 _base = '\001\033[%sm\002' # Template for all other colors
96 _base = '\001\033[%sm\002' # Template for all other colors
102
97
103 # Build the actual color table as a set of class attributes:
98 # Build the actual color table as a set of class attributes:
104 make_color_table(InputTermColors)
99 make_color_table(InputTermColors)
105
100
106 class ColorScheme:
101 class ColorScheme:
107 """Generic color scheme class. Just a name and a Struct."""
102 """Generic color scheme class. Just a name and a Struct."""
108 def __init__(self,__scheme_name_,colordict=None,**colormap):
103 def __init__(self,__scheme_name_,colordict=None,**colormap):
109 self.name = __scheme_name_
104 self.name = __scheme_name_
110 if colordict is None:
105 if colordict is None:
111 self.colors = Struct(**colormap)
106 self.colors = Struct(**colormap)
112 else:
107 else:
113 self.colors = Struct(colordict)
108 self.colors = Struct(colordict)
114
109
115 def copy(self,name=None):
110 def copy(self,name=None):
116 """Return a full copy of the object, optionally renaming it."""
111 """Return a full copy of the object, optionally renaming it."""
117 if name is None:
112 if name is None:
118 name = self.name
113 name = self.name
119 return ColorScheme(name,self.colors.__dict__)
114 return ColorScheme(name,self.colors.__dict__)
120
115
121 class ColorSchemeTable(dict):
116 class ColorSchemeTable(dict):
122 """General class to handle tables of color schemes.
117 """General class to handle tables of color schemes.
123
118
124 It's basically a dict of color schemes with a couple of shorthand
119 It's basically a dict of color schemes with a couple of shorthand
125 attributes and some convenient methods.
120 attributes and some convenient methods.
126
121
127 active_scheme_name -> obvious
122 active_scheme_name -> obvious
128 active_colors -> actual color table of the active scheme"""
123 active_colors -> actual color table of the active scheme"""
129
124
130 def __init__(self,scheme_list=None,default_scheme=''):
125 def __init__(self,scheme_list=None,default_scheme=''):
131 """Create a table of color schemes.
126 """Create a table of color schemes.
132
127
133 The table can be created empty and manually filled or it can be
128 The table can be created empty and manually filled or it can be
134 created with a list of valid color schemes AND the specification for
129 created with a list of valid color schemes AND the specification for
135 the default active scheme.
130 the default active scheme.
136 """
131 """
137
132
138 # create object attributes to be set later
133 # create object attributes to be set later
139 self.active_scheme_name = ''
134 self.active_scheme_name = ''
140 self.active_colors = None
135 self.active_colors = None
141
136
142 if scheme_list:
137 if scheme_list:
143 if default_scheme == '':
138 if default_scheme == '':
144 raise ValueError,'you must specify the default color scheme'
139 raise ValueError,'you must specify the default color scheme'
145 for scheme in scheme_list:
140 for scheme in scheme_list:
146 self.add_scheme(scheme)
141 self.add_scheme(scheme)
147 self.set_active_scheme(default_scheme)
142 self.set_active_scheme(default_scheme)
148
143
149 def copy(self):
144 def copy(self):
150 """Return full copy of object"""
145 """Return full copy of object"""
151 return ColorSchemeTable(self.values(),self.active_scheme_name)
146 return ColorSchemeTable(self.values(),self.active_scheme_name)
152
147
153 def add_scheme(self,new_scheme):
148 def add_scheme(self,new_scheme):
154 """Add a new color scheme to the table."""
149 """Add a new color scheme to the table."""
155 if not isinstance(new_scheme,ColorScheme):
150 if not isinstance(new_scheme,ColorScheme):
156 raise ValueError,'ColorSchemeTable only accepts ColorScheme instances'
151 raise ValueError,'ColorSchemeTable only accepts ColorScheme instances'
157 self[new_scheme.name] = new_scheme
152 self[new_scheme.name] = new_scheme
158
153
159 def set_active_scheme(self,scheme,case_sensitive=0):
154 def set_active_scheme(self,scheme,case_sensitive=0):
160 """Set the currently active scheme.
155 """Set the currently active scheme.
161
156
162 Names are by default compared in a case-insensitive way, but this can
157 Names are by default compared in a case-insensitive way, but this can
163 be changed by setting the parameter case_sensitive to true."""
158 be changed by setting the parameter case_sensitive to true."""
164
159
165 scheme_names = self.keys()
160 scheme_names = self.keys()
166 if case_sensitive:
161 if case_sensitive:
167 valid_schemes = scheme_names
162 valid_schemes = scheme_names
168 scheme_test = scheme
163 scheme_test = scheme
169 else:
164 else:
170 valid_schemes = [s.lower() for s in scheme_names]
165 valid_schemes = [s.lower() for s in scheme_names]
171 scheme_test = scheme.lower()
166 scheme_test = scheme.lower()
172 try:
167 try:
173 scheme_idx = valid_schemes.index(scheme_test)
168 scheme_idx = valid_schemes.index(scheme_test)
174 except ValueError:
169 except ValueError:
175 raise ValueError,'Unrecognized color scheme: ' + scheme + \
170 raise ValueError,'Unrecognized color scheme: ' + scheme + \
176 '\nValid schemes: '+str(scheme_names).replace("'', ",'')
171 '\nValid schemes: '+str(scheme_names).replace("'', ",'')
177 else:
172 else:
178 active = scheme_names[scheme_idx]
173 active = scheme_names[scheme_idx]
179 self.active_scheme_name = active
174 self.active_scheme_name = active
180 self.active_colors = self[active].colors
175 self.active_colors = self[active].colors
181 # Now allow using '' as an index for the current active scheme
176 # Now allow using '' as an index for the current active scheme
182 self[''] = self[active]
177 self[''] = self[active]
@@ -1,116 +1,111 b''
1 # -*- coding: utf-8 -*-
1 # -*- coding: utf-8 -*-
2 """Configuration loader
2 """Configuration loader
3
3 """
4 $Id: ConfigLoader.py 1005 2006-01-12 08:39:26Z fperez $"""
5
4
6 #*****************************************************************************
5 #*****************************************************************************
7 # Copyright (C) 2001-2006 Fernando Perez. <fperez@colorado.edu>
6 # Copyright (C) 2001-2006 Fernando Perez. <fperez@colorado.edu>
8 #
7 #
9 # Distributed under the terms of the BSD License. The full license is in
8 # Distributed under the terms of the BSD License. The full license is in
10 # the file COPYING, distributed as part of this software.
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 import exceptions
12 import exceptions
18 import os
13 import os
19 from pprint import pprint
14 from pprint import pprint
20
15
21 from IPython import ultraTB
16 from IPython import ultraTB
22 from IPython.ipstruct import Struct
17 from IPython.ipstruct import Struct
23 from IPython.genutils import *
18 from IPython.genutils import *
24
19
25 class ConfigLoaderError(exceptions.Exception):
20 class ConfigLoaderError(exceptions.Exception):
26 """Exception for ConfigLoader class."""
21 """Exception for ConfigLoader class."""
27
22
28 def __init__(self,args=None):
23 def __init__(self,args=None):
29 self.args = args
24 self.args = args
30
25
31 class ConfigLoader:
26 class ConfigLoader:
32
27
33 """Configuration file loader capable of handling recursive inclusions and
28 """Configuration file loader capable of handling recursive inclusions and
34 with parametrized conflict resolution for multiply found keys."""
29 with parametrized conflict resolution for multiply found keys."""
35
30
36 def __init__(self,conflict=None,field_sep=None,reclimit=15):
31 def __init__(self,conflict=None,field_sep=None,reclimit=15):
37
32
38 """The reclimit parameter controls the number of recursive
33 """The reclimit parameter controls the number of recursive
39 configuration file inclusions. This way we can stop early on (before
34 configuration file inclusions. This way we can stop early on (before
40 python's own recursion limit is hit) if there is a circular
35 python's own recursion limit is hit) if there is a circular
41 inclusion.
36 inclusion.
42
37
43 - conflict: dictionary for conflict resolutions (see Struct.merge())
38 - conflict: dictionary for conflict resolutions (see Struct.merge())
44
39
45 """
40 """
46 self.conflict = conflict
41 self.conflict = conflict
47 self.field_sep = field_sep
42 self.field_sep = field_sep
48 self.reset(reclimit)
43 self.reset(reclimit)
49
44
50 def reset(self,reclimit=15):
45 def reset(self,reclimit=15):
51 self.reclimit = reclimit
46 self.reclimit = reclimit
52 self.recdepth = 0
47 self.recdepth = 0
53 self.included = []
48 self.included = []
54
49
55 def load(self,fname,convert=None,recurse_key='',incpath = '.',**kw):
50 def load(self,fname,convert=None,recurse_key='',incpath = '.',**kw):
56 """Load a configuration file, return the resulting Struct.
51 """Load a configuration file, return the resulting Struct.
57
52
58 Call: load_config(fname,convert=None,conflict=None,recurse_key='')
53 Call: load_config(fname,convert=None,conflict=None,recurse_key='')
59
54
60 - fname: file to load from.
55 - fname: file to load from.
61 - convert: dictionary of type conversions (see read_dict())
56 - convert: dictionary of type conversions (see read_dict())
62 - recurse_key: keyword in dictionary to trigger recursive file
57 - recurse_key: keyword in dictionary to trigger recursive file
63 inclusions.
58 inclusions.
64 """
59 """
65
60
66 if self.recdepth > self.reclimit:
61 if self.recdepth > self.reclimit:
67 raise ConfigLoaderError, 'maximum recursive inclusion of rcfiles '+\
62 raise ConfigLoaderError, 'maximum recursive inclusion of rcfiles '+\
68 'exceeded: ' + `self.recdepth` + \
63 'exceeded: ' + `self.recdepth` + \
69 '.\nMaybe you have a circular chain of inclusions?'
64 '.\nMaybe you have a circular chain of inclusions?'
70 self.recdepth += 1
65 self.recdepth += 1
71 fname = filefind(fname,incpath)
66 fname = filefind(fname,incpath)
72 data = Struct()
67 data = Struct()
73 # avoid including the same file more than once
68 # avoid including the same file more than once
74 if fname in self.included:
69 if fname in self.included:
75 return data
70 return data
76 Xinfo = ultraTB.AutoFormattedTB(color_scheme='NoColor')
71 Xinfo = ultraTB.AutoFormattedTB(color_scheme='NoColor')
77 if convert==None and recurse_key : convert = {qwflat:recurse_key}
72 if convert==None and recurse_key : convert = {qwflat:recurse_key}
78 # for production, change warn to 0:
73 # for production, change warn to 0:
79 data.merge(read_dict(fname,convert,fs=self.field_sep,strip=1,
74 data.merge(read_dict(fname,convert,fs=self.field_sep,strip=1,
80 warn=0,no_empty=0,**kw))
75 warn=0,no_empty=0,**kw))
81 # keep track of successfully loaded files
76 # keep track of successfully loaded files
82 self.included.append(fname)
77 self.included.append(fname)
83 if recurse_key in data:
78 if recurse_key in data:
84 for incfilename in data[recurse_key]:
79 for incfilename in data[recurse_key]:
85 found=0
80 found=0
86 try:
81 try:
87 incfile = filefind(incfilename,incpath)
82 incfile = filefind(incfilename,incpath)
88 except IOError:
83 except IOError:
89 if os.name in ['nt','dos']:
84 if os.name in ['nt','dos']:
90 try:
85 try:
91 # Try again with '.ini' extension
86 # Try again with '.ini' extension
92 incfilename += '.ini'
87 incfilename += '.ini'
93 incfile = filefind(incfilename,incpath)
88 incfile = filefind(incfilename,incpath)
94 except IOError:
89 except IOError:
95 found = 0
90 found = 0
96 else:
91 else:
97 found = 1
92 found = 1
98 else:
93 else:
99 found = 0
94 found = 0
100 else:
95 else:
101 found = 1
96 found = 1
102 if found:
97 if found:
103 try:
98 try:
104 data.merge(self.load(incfile,convert,recurse_key,
99 data.merge(self.load(incfile,convert,recurse_key,
105 incpath,**kw),
100 incpath,**kw),
106 self.conflict)
101 self.conflict)
107 except:
102 except:
108 Xinfo()
103 Xinfo()
109 warn('Problem loading included file: '+
104 warn('Problem loading included file: '+
110 `incfilename` + '. Ignoring it...')
105 `incfilename` + '. Ignoring it...')
111 else:
106 else:
112 warn('File `%s` not found. Included by %s' % (incfilename,fname))
107 warn('File `%s` not found. Included by %s' % (incfilename,fname))
113
108
114 return data
109 return data
115
110
116 # end ConfigLoader
111 # end ConfigLoader
@@ -1,228 +1,227 b''
1 # -*- coding: utf-8 -*-
1 # -*- coding: utf-8 -*-
2 """sys.excepthook for IPython itself, leaves a detailed report on disk.
2 """sys.excepthook for IPython itself, leaves a detailed report on disk.
3
3 """
4 $Id: CrashHandler.py 2908 2007-12-30 21:07:46Z vivainio $"""
5
4
6 #*****************************************************************************
5 #*****************************************************************************
7 # Copyright (C) 2001-2006 Fernando Perez. <fperez@colorado.edu>
6 # Copyright (C) 2001-2006 Fernando Perez. <fperez@colorado.edu>
8 #
7 #
9 # Distributed under the terms of the BSD License. The full license is in
8 # Distributed under the terms of the BSD License. The full license is in
10 # the file COPYING, distributed as part of this software.
9 # the file COPYING, distributed as part of this software.
11 #*****************************************************************************
10 #*****************************************************************************
12
11
13 from IPython import Release
12 from IPython import Release
14 __author__ = '%s <%s>' % Release.authors['Fernando']
13 __author__ = '%s <%s>' % Release.authors['Fernando']
15 __license__ = Release.license
14 __license__ = Release.license
16 __version__ = Release.version
15 __version__ = Release.version
17
16
18 #****************************************************************************
17 #****************************************************************************
19 # Required modules
18 # Required modules
20
19
21 # From the standard library
20 # From the standard library
22 import os
21 import os
23 import sys
22 import sys
24 from pprint import pprint,pformat
23 from pprint import pprint,pformat
25
24
26 # Homebrewed
25 # Homebrewed
27 from IPython.Itpl import Itpl,itpl,printpl
26 from IPython.Itpl import Itpl,itpl,printpl
28 from IPython.ColorANSI import ColorScheme,ColorSchemeTable # too long names
27 from IPython.ColorANSI import ColorScheme,ColorSchemeTable # too long names
29 from IPython import ultraTB
28 from IPython import ultraTB
30 from IPython.genutils import *
29 from IPython.genutils import *
31
30
32 #****************************************************************************
31 #****************************************************************************
33 class CrashHandler:
32 class CrashHandler:
34 """Customizable crash handlers for IPython-based systems.
33 """Customizable crash handlers for IPython-based systems.
35
34
36 Instances of this class provide a __call__ method which can be used as a
35 Instances of this class provide a __call__ method which can be used as a
37 sys.excepthook, i.e., the __call__ signature is:
36 sys.excepthook, i.e., the __call__ signature is:
38
37
39 def __call__(self,etype, evalue, etb)
38 def __call__(self,etype, evalue, etb)
40
39
41 """
40 """
42
41
43 def __init__(self,IP,app_name,contact_name,contact_email,
42 def __init__(self,IP,app_name,contact_name,contact_email,
44 bug_tracker,crash_report_fname,
43 bug_tracker,crash_report_fname,
45 show_crash_traceback=True):
44 show_crash_traceback=True):
46 """New crash handler.
45 """New crash handler.
47
46
48 Inputs:
47 Inputs:
49
48
50 - IP: a running IPython instance, which will be queried at crash time
49 - IP: a running IPython instance, which will be queried at crash time
51 for internal information.
50 for internal information.
52
51
53 - app_name: a string containing the name of your application.
52 - app_name: a string containing the name of your application.
54
53
55 - contact_name: a string with the name of the person to contact.
54 - contact_name: a string with the name of the person to contact.
56
55
57 - contact_email: a string with the email address of the contact.
56 - contact_email: a string with the email address of the contact.
58
57
59 - bug_tracker: a string with the URL for your project's bug tracker.
58 - bug_tracker: a string with the URL for your project's bug tracker.
60
59
61 - crash_report_fname: a string with the filename for the crash report
60 - crash_report_fname: a string with the filename for the crash report
62 to be saved in. These reports are left in the ipython user directory
61 to be saved in. These reports are left in the ipython user directory
63 as determined by the running IPython instance.
62 as determined by the running IPython instance.
64
63
65 Optional inputs:
64 Optional inputs:
66
65
67 - show_crash_traceback(True): if false, don't print the crash
66 - show_crash_traceback(True): if false, don't print the crash
68 traceback on stderr, only generate the on-disk report
67 traceback on stderr, only generate the on-disk report
69
68
70
69
71 Non-argument instance attributes:
70 Non-argument instance attributes:
72
71
73 These instances contain some non-argument attributes which allow for
72 These instances contain some non-argument attributes which allow for
74 further customization of the crash handler's behavior. Please see the
73 further customization of the crash handler's behavior. Please see the
75 source for further details.
74 source for further details.
76 """
75 """
77
76
78 # apply args into instance
77 # apply args into instance
79 self.IP = IP # IPython instance
78 self.IP = IP # IPython instance
80 self.app_name = app_name
79 self.app_name = app_name
81 self.contact_name = contact_name
80 self.contact_name = contact_name
82 self.contact_email = contact_email
81 self.contact_email = contact_email
83 self.bug_tracker = bug_tracker
82 self.bug_tracker = bug_tracker
84 self.crash_report_fname = crash_report_fname
83 self.crash_report_fname = crash_report_fname
85 self.show_crash_traceback = show_crash_traceback
84 self.show_crash_traceback = show_crash_traceback
86
85
87 # Hardcoded defaults, which can be overridden either by subclasses or
86 # Hardcoded defaults, which can be overridden either by subclasses or
88 # at runtime for the instance.
87 # at runtime for the instance.
89
88
90 # Template for the user message. Subclasses which completely override
89 # Template for the user message. Subclasses which completely override
91 # this, or user apps, can modify it to suit their tastes. It gets
90 # this, or user apps, can modify it to suit their tastes. It gets
92 # expanded using itpl, so calls of the kind $self.foo are valid.
91 # expanded using itpl, so calls of the kind $self.foo are valid.
93 self.user_message_template = """
92 self.user_message_template = """
94 Oops, $self.app_name crashed. We do our best to make it stable, but...
93 Oops, $self.app_name crashed. We do our best to make it stable, but...
95
94
96 A crash report was automatically generated with the following information:
95 A crash report was automatically generated with the following information:
97 - A verbatim copy of the crash traceback.
96 - A verbatim copy of the crash traceback.
98 - A copy of your input history during this session.
97 - A copy of your input history during this session.
99 - Data on your current $self.app_name configuration.
98 - Data on your current $self.app_name configuration.
100
99
101 It was left in the file named:
100 It was left in the file named:
102 \t'$self.crash_report_fname'
101 \t'$self.crash_report_fname'
103 If you can email this file to the developers, the information in it will help
102 If you can email this file to the developers, the information in it will help
104 them in understanding and correcting the problem.
103 them in understanding and correcting the problem.
105
104
106 You can mail it to: $self.contact_name at $self.contact_email
105 You can mail it to: $self.contact_name at $self.contact_email
107 with the subject '$self.app_name Crash Report'.
106 with the subject '$self.app_name Crash Report'.
108
107
109 If you want to do it now, the following command will work (under Unix):
108 If you want to do it now, the following command will work (under Unix):
110 mail -s '$self.app_name Crash Report' $self.contact_email < $self.crash_report_fname
109 mail -s '$self.app_name Crash Report' $self.contact_email < $self.crash_report_fname
111
110
112 To ensure accurate tracking of this issue, please file a report about it at:
111 To ensure accurate tracking of this issue, please file a report about it at:
113 $self.bug_tracker
112 $self.bug_tracker
114 """
113 """
115
114
116 def __call__(self,etype, evalue, etb):
115 def __call__(self,etype, evalue, etb):
117 """Handle an exception, call for compatible with sys.excepthook"""
116 """Handle an exception, call for compatible with sys.excepthook"""
118
117
119 # Report tracebacks shouldn't use color in general (safer for users)
118 # Report tracebacks shouldn't use color in general (safer for users)
120 color_scheme = 'NoColor'
119 color_scheme = 'NoColor'
121
120
122 # Use this ONLY for developer debugging (keep commented out for release)
121 # Use this ONLY for developer debugging (keep commented out for release)
123 #color_scheme = 'Linux' # dbg
122 #color_scheme = 'Linux' # dbg
124
123
125 try:
124 try:
126 rptdir = self.IP.rc.ipythondir
125 rptdir = self.IP.rc.ipythondir
127 except:
126 except:
128 rptdir = os.getcwd()
127 rptdir = os.getcwd()
129 if not os.path.isdir(rptdir):
128 if not os.path.isdir(rptdir):
130 rptdir = os.getcwd()
129 rptdir = os.getcwd()
131 report_name = os.path.join(rptdir,self.crash_report_fname)
130 report_name = os.path.join(rptdir,self.crash_report_fname)
132 # write the report filename into the instance dict so it can get
131 # write the report filename into the instance dict so it can get
133 # properly expanded out in the user message template
132 # properly expanded out in the user message template
134 self.crash_report_fname = report_name
133 self.crash_report_fname = report_name
135 TBhandler = ultraTB.VerboseTB(color_scheme=color_scheme,
134 TBhandler = ultraTB.VerboseTB(color_scheme=color_scheme,
136 long_header=1)
135 long_header=1)
137 traceback = TBhandler.text(etype,evalue,etb,context=31)
136 traceback = TBhandler.text(etype,evalue,etb,context=31)
138
137
139 # print traceback to screen
138 # print traceback to screen
140 if self.show_crash_traceback:
139 if self.show_crash_traceback:
141 print >> sys.stderr, traceback
140 print >> sys.stderr, traceback
142
141
143 # and generate a complete report on disk
142 # and generate a complete report on disk
144 try:
143 try:
145 report = open(report_name,'w')
144 report = open(report_name,'w')
146 except:
145 except:
147 print >> sys.stderr, 'Could not create crash report on disk.'
146 print >> sys.stderr, 'Could not create crash report on disk.'
148 return
147 return
149
148
150 # Inform user on stderr of what happened
149 # Inform user on stderr of what happened
151 msg = itpl('\n'+'*'*70+'\n'+self.user_message_template)
150 msg = itpl('\n'+'*'*70+'\n'+self.user_message_template)
152 print >> sys.stderr, msg
151 print >> sys.stderr, msg
153
152
154 # Construct report on disk
153 # Construct report on disk
155 report.write(self.make_report(traceback))
154 report.write(self.make_report(traceback))
156 report.close()
155 report.close()
157 raw_input("Press enter to exit:")
156 raw_input("Press enter to exit:")
158
157
159 def make_report(self,traceback):
158 def make_report(self,traceback):
160 """Return a string containing a crash report."""
159 """Return a string containing a crash report."""
161
160
162 sec_sep = '\n\n'+'*'*75+'\n\n'
161 sec_sep = '\n\n'+'*'*75+'\n\n'
163
162
164 report = []
163 report = []
165 rpt_add = report.append
164 rpt_add = report.append
166
165
167 rpt_add('*'*75+'\n\n'+'IPython post-mortem report\n\n')
166 rpt_add('*'*75+'\n\n'+'IPython post-mortem report\n\n')
168 rpt_add('IPython version: %s \n\n' % Release.version)
167 rpt_add('IPython version: %s \n\n' % Release.version)
169 rpt_add('SVN revision : %s \n\n' % Release.revision)
168 rpt_add('SVN revision : %s \n\n' % Release.revision)
170 rpt_add('Platform info : os.name -> %s, sys.platform -> %s' %
169 rpt_add('Platform info : os.name -> %s, sys.platform -> %s' %
171 (os.name,sys.platform) )
170 (os.name,sys.platform) )
172 rpt_add(sec_sep+'Current user configuration structure:\n\n')
171 rpt_add(sec_sep+'Current user configuration structure:\n\n')
173 rpt_add(pformat(self.IP.rc.dict()))
172 rpt_add(pformat(self.IP.rc.dict()))
174 rpt_add(sec_sep+'Crash traceback:\n\n' + traceback)
173 rpt_add(sec_sep+'Crash traceback:\n\n' + traceback)
175 try:
174 try:
176 rpt_add(sec_sep+"History of session input:")
175 rpt_add(sec_sep+"History of session input:")
177 for line in self.IP.user_ns['_ih']:
176 for line in self.IP.user_ns['_ih']:
178 rpt_add(line)
177 rpt_add(line)
179 rpt_add('\n*** Last line of input (may not be in above history):\n')
178 rpt_add('\n*** Last line of input (may not be in above history):\n')
180 rpt_add(self.IP._last_input_line+'\n')
179 rpt_add(self.IP._last_input_line+'\n')
181 except:
180 except:
182 pass
181 pass
183
182
184 return ''.join(report)
183 return ''.join(report)
185
184
186 class IPythonCrashHandler(CrashHandler):
185 class IPythonCrashHandler(CrashHandler):
187 """sys.excepthook for IPython itself, leaves a detailed report on disk."""
186 """sys.excepthook for IPython itself, leaves a detailed report on disk."""
188
187
189 def __init__(self,IP):
188 def __init__(self,IP):
190
189
191 # Set here which of the IPython authors should be listed as contact
190 # Set here which of the IPython authors should be listed as contact
192 AUTHOR_CONTACT = 'Ville'
191 AUTHOR_CONTACT = 'Ville'
193
192
194 # Set argument defaults
193 # Set argument defaults
195 app_name = 'IPython'
194 app_name = 'IPython'
196 bug_tracker = 'http://projects.scipy.org/ipython/ipython/report'
195 bug_tracker = 'http://projects.scipy.org/ipython/ipython/report'
197 contact_name,contact_email = Release.authors[AUTHOR_CONTACT][:2]
196 contact_name,contact_email = Release.authors[AUTHOR_CONTACT][:2]
198 crash_report_fname = 'IPython_crash_report.txt'
197 crash_report_fname = 'IPython_crash_report.txt'
199 # Call parent constructor
198 # Call parent constructor
200 CrashHandler.__init__(self,IP,app_name,contact_name,contact_email,
199 CrashHandler.__init__(self,IP,app_name,contact_name,contact_email,
201 bug_tracker,crash_report_fname)
200 bug_tracker,crash_report_fname)
202
201
203 def make_report(self,traceback):
202 def make_report(self,traceback):
204 """Return a string containing a crash report."""
203 """Return a string containing a crash report."""
205
204
206 sec_sep = '\n\n'+'*'*75+'\n\n'
205 sec_sep = '\n\n'+'*'*75+'\n\n'
207
206
208 report = []
207 report = []
209 rpt_add = report.append
208 rpt_add = report.append
210
209
211 rpt_add('*'*75+'\n\n'+'IPython post-mortem report\n\n')
210 rpt_add('*'*75+'\n\n'+'IPython post-mortem report\n\n')
212 rpt_add('IPython version: %s \n\n' % Release.version)
211 rpt_add('IPython version: %s \n\n' % Release.version)
213 rpt_add('SVN revision : %s \n\n' % Release.revision)
212 rpt_add('SVN revision : %s \n\n' % Release.revision)
214 rpt_add('Platform info : os.name -> %s, sys.platform -> %s' %
213 rpt_add('Platform info : os.name -> %s, sys.platform -> %s' %
215 (os.name,sys.platform) )
214 (os.name,sys.platform) )
216 rpt_add(sec_sep+'Current user configuration structure:\n\n')
215 rpt_add(sec_sep+'Current user configuration structure:\n\n')
217 rpt_add(pformat(self.IP.rc.dict()))
216 rpt_add(pformat(self.IP.rc.dict()))
218 rpt_add(sec_sep+'Crash traceback:\n\n' + traceback)
217 rpt_add(sec_sep+'Crash traceback:\n\n' + traceback)
219 try:
218 try:
220 rpt_add(sec_sep+"History of session input:")
219 rpt_add(sec_sep+"History of session input:")
221 for line in self.IP.user_ns['_ih']:
220 for line in self.IP.user_ns['_ih']:
222 rpt_add(line)
221 rpt_add(line)
223 rpt_add('\n*** Last line of input (may not be in above history):\n')
222 rpt_add('\n*** Last line of input (may not be in above history):\n')
224 rpt_add(self.IP._last_input_line+'\n')
223 rpt_add(self.IP._last_input_line+'\n')
225 except:
224 except:
226 pass
225 pass
227
226
228 return ''.join(report)
227 return ''.join(report)
@@ -1,693 +1,690 b''
1 # -*- coding: utf-8 -*-
1 # -*- coding: utf-8 -*-
2 """DPyGetOpt -- Demiurge Python GetOptions Module
2 """DPyGetOpt -- Demiurge Python GetOptions Module
3
3
4 $Id: DPyGetOpt.py 2872 2007-11-25 17:58:05Z fperez $
5
6 This module is modeled after perl's Getopt::Long module-- which
4 This module is modeled after perl's Getopt::Long module-- which
7 is, in turn, modeled after GNU's extended getopt() function.
5 is, in turn, modeled after GNU's extended getopt() function.
8
6
9 Upon instantiation, the option specification should be a sequence
7 Upon instantiation, the option specification should be a sequence
10 (list) of option definitions.
8 (list) of option definitions.
11
9
12 Options that take no arguments should simply contain the name of
10 Options that take no arguments should simply contain the name of
13 the option. If a ! is post-pended, the option can be negated by
11 the option. If a ! is post-pended, the option can be negated by
14 prepending 'no'; ie 'debug!' specifies that -debug and -nodebug
12 prepending 'no'; ie 'debug!' specifies that -debug and -nodebug
15 should be accepted.
13 should be accepted.
16
14
17 Mandatory arguments to options are specified using a postpended
15 Mandatory arguments to options are specified using a postpended
18 '=' + a type specifier. '=s' specifies a mandatory string
16 '=' + a type specifier. '=s' specifies a mandatory string
19 argument, '=i' specifies a mandatory integer argument, and '=f'
17 argument, '=i' specifies a mandatory integer argument, and '=f'
20 specifies a mandatory real number. In all cases, the '=' can be
18 specifies a mandatory real number. In all cases, the '=' can be
21 substituted with ':' to specify that the argument is optional.
19 substituted with ':' to specify that the argument is optional.
22
20
23 Dashes '-' in option names are allowed.
21 Dashes '-' in option names are allowed.
24
22
25 If an option has the character '@' postpended (after the
23 If an option has the character '@' postpended (after the
26 argumentation specification), it can appear multiple times within
24 argumentation specification), it can appear multiple times within
27 each argument list that is processed. The results will be stored
25 each argument list that is processed. The results will be stored
28 in a list.
26 in a list.
29
27
30 The option name can actually be a list of names separated by '|'
28 The option name can actually be a list of names separated by '|'
31 characters; ie-- 'foo|bar|baz=f@' specifies that all -foo, -bar,
29 characters; ie-- 'foo|bar|baz=f@' specifies that all -foo, -bar,
32 and -baz options that appear on within the parsed argument list
30 and -baz options that appear on within the parsed argument list
33 must have a real number argument and that the accumulated list
31 must have a real number argument and that the accumulated list
34 of values will be available under the name 'foo'
32 of values will be available under the name 'foo'
35
33 """
36 $Id: DPyGetOpt.py 2872 2007-11-25 17:58:05Z fperez $"""
37
34
38 #*****************************************************************************
35 #*****************************************************************************
39 #
36 #
40 # Copyright (c) 2001 Bill Bumgarner <bbum@friday.com>
37 # Copyright (c) 2001 Bill Bumgarner <bbum@friday.com>
41 #
38 #
42 #
39 #
43 # Published under the terms of the MIT license, hereby reproduced:
40 # Published under the terms of the MIT license, hereby reproduced:
44 #
41 #
45 # Permission is hereby granted, free of charge, to any person obtaining a copy
42 # Permission is hereby granted, free of charge, to any person obtaining a copy
46 # of this software and associated documentation files (the "Software"), to
43 # of this software and associated documentation files (the "Software"), to
47 # deal in the Software without restriction, including without limitation the
44 # deal in the Software without restriction, including without limitation the
48 # rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
45 # rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
49 # sell copies of the Software, and to permit persons to whom the Software is
46 # sell copies of the Software, and to permit persons to whom the Software is
50 # furnished to do so, subject to the following conditions:
47 # furnished to do so, subject to the following conditions:
51 #
48 #
52 # The above copyright notice and this permission notice shall be included in
49 # The above copyright notice and this permission notice shall be included in
53 # all copies or substantial portions of the Software.
50 # all copies or substantial portions of the Software.
54 #
51 #
55 # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
52 # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
56 # IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
53 # IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
57 # FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
54 # FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
58 # AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
55 # AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
59 # LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
56 # LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
60 # FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
57 # FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
61 # IN THE SOFTWARE.
58 # IN THE SOFTWARE.
62 #
59 #
63 #*****************************************************************************
60 #*****************************************************************************
64
61
65 __author__ = 'Bill Bumgarner <bbum@friday.com>'
62 __author__ = 'Bill Bumgarner <bbum@friday.com>'
66 __license__ = 'MIT'
63 __license__ = 'MIT'
67 __version__ = '1.2'
64 __version__ = '1.2'
68
65
69 # Modified to use re instead of regex and regsub modules.
66 # Modified to use re instead of regex and regsub modules.
70 # 2001/5/7, Jonathan Hogg <jonathan@onegoodidea.com>
67 # 2001/5/7, Jonathan Hogg <jonathan@onegoodidea.com>
71
68
72 import re
69 import re
73 import string
70 import string
74 import sys
71 import sys
75 import types
72 import types
76
73
77 class Error(Exception):
74 class Error(Exception):
78 """Base class for exceptions in the DPyGetOpt module."""
75 """Base class for exceptions in the DPyGetOpt module."""
79
76
80 class ArgumentError(Error):
77 class ArgumentError(Error):
81 """Exception indicating an error in the arguments passed to
78 """Exception indicating an error in the arguments passed to
82 DPyGetOpt.processArguments."""
79 DPyGetOpt.processArguments."""
83
80
84 class SpecificationError(Error):
81 class SpecificationError(Error):
85 """Exception indicating an error with an option specification."""
82 """Exception indicating an error with an option specification."""
86
83
87 class TerminationError(Error):
84 class TerminationError(Error):
88 """Exception indicating an error with an option processing terminator."""
85 """Exception indicating an error with an option processing terminator."""
89
86
90 specificationExpr = re.compile('(?P<required>.)(?P<type>.)(?P<multi>@?)')
87 specificationExpr = re.compile('(?P<required>.)(?P<type>.)(?P<multi>@?)')
91
88
92 ArgRequired = 'Requires an Argument'
89 ArgRequired = 'Requires an Argument'
93 ArgOptional = 'Argument Optional'
90 ArgOptional = 'Argument Optional'
94
91
95 # The types modules is not used for these identifiers because there
92 # The types modules is not used for these identifiers because there
96 # is no identifier for 'boolean' or 'generic'
93 # is no identifier for 'boolean' or 'generic'
97 StringArgType = 'String Argument Type'
94 StringArgType = 'String Argument Type'
98 IntegerArgType = 'Integer Argument Type'
95 IntegerArgType = 'Integer Argument Type'
99 RealArgType = 'Real Argument Type'
96 RealArgType = 'Real Argument Type'
100 BooleanArgType = 'Boolean Argument Type'
97 BooleanArgType = 'Boolean Argument Type'
101 GenericArgType = 'Generic Argument Type'
98 GenericArgType = 'Generic Argument Type'
102
99
103 # dictionary of conversion functions-- boolean and generic options
100 # dictionary of conversion functions-- boolean and generic options
104 # do not accept arguments and do not need conversion functions;
101 # do not accept arguments and do not need conversion functions;
105 # the identity function is used purely for convenience.
102 # the identity function is used purely for convenience.
106 ConversionFunctions = {
103 ConversionFunctions = {
107 StringArgType : lambda x: x,
104 StringArgType : lambda x: x,
108 IntegerArgType : string.atoi,
105 IntegerArgType : string.atoi,
109 RealArgType : string.atof,
106 RealArgType : string.atof,
110 BooleanArgType : lambda x: x,
107 BooleanArgType : lambda x: x,
111 GenericArgType : lambda x: x,
108 GenericArgType : lambda x: x,
112 }
109 }
113
110
114 class DPyGetOpt:
111 class DPyGetOpt:
115
112
116 def __init__(self, spec = None, terminators = ['--']):
113 def __init__(self, spec = None, terminators = ['--']):
117 """
114 """
118 Declare and intialize instance variables
115 Declare and intialize instance variables
119
116
120 Yes, declaration is not necessary... but one of the things
117 Yes, declaration is not necessary... but one of the things
121 I sorely miss from C/Obj-C is the concept of having an
118 I sorely miss from C/Obj-C is the concept of having an
122 interface definition that clearly declares all instance
119 interface definition that clearly declares all instance
123 variables and methods without providing any implementation
120 variables and methods without providing any implementation
124 details. it is a useful reference!
121 details. it is a useful reference!
125
122
126 all instance variables are initialized to 0/Null/None of
123 all instance variables are initialized to 0/Null/None of
127 the appropriate type-- not even the default value...
124 the appropriate type-- not even the default value...
128 """
125 """
129
126
130 # sys.stderr.write(string.join(spec) + "\n")
127 # sys.stderr.write(string.join(spec) + "\n")
131
128
132 self.allowAbbreviations = 1 # boolean, 1 if abbreviations will
129 self.allowAbbreviations = 1 # boolean, 1 if abbreviations will
133 # be expanded
130 # be expanded
134 self.freeValues = [] # list, contains free values
131 self.freeValues = [] # list, contains free values
135 self.ignoreCase = 0 # boolean, YES if ignoring case
132 self.ignoreCase = 0 # boolean, YES if ignoring case
136 self.needsParse = 0 # boolean, YES if need to reparse parameter spec
133 self.needsParse = 0 # boolean, YES if need to reparse parameter spec
137 self.optionNames = {} # dict, all option names-- value is index of tuple
134 self.optionNames = {} # dict, all option names-- value is index of tuple
138 self.optionStartExpr = None # regexp defining the start of an option (ie; '-', '--')
135 self.optionStartExpr = None # regexp defining the start of an option (ie; '-', '--')
139 self.optionTuples = [] # list o' tuples containing defn of options AND aliases
136 self.optionTuples = [] # list o' tuples containing defn of options AND aliases
140 self.optionValues = {} # dict, option names (after alias expansion) -> option value(s)
137 self.optionValues = {} # dict, option names (after alias expansion) -> option value(s)
141 self.orderMixed = 0 # boolean, YES if options can be mixed with args
138 self.orderMixed = 0 # boolean, YES if options can be mixed with args
142 self.posixCompliance = 0 # boolean, YES indicates posix like behaviour
139 self.posixCompliance = 0 # boolean, YES indicates posix like behaviour
143 self.spec = [] # list, raw specs (in case it must be reparsed)
140 self.spec = [] # list, raw specs (in case it must be reparsed)
144 self.terminators = terminators # list, strings that terminate argument processing
141 self.terminators = terminators # list, strings that terminate argument processing
145 self.termValues = [] # list, values after terminator
142 self.termValues = [] # list, values after terminator
146 self.terminator = None # full name of terminator that ended
143 self.terminator = None # full name of terminator that ended
147 # option processing
144 # option processing
148
145
149 # set up defaults
146 # set up defaults
150 self.setPosixCompliance()
147 self.setPosixCompliance()
151 self.setIgnoreCase()
148 self.setIgnoreCase()
152 self.setAllowAbbreviations()
149 self.setAllowAbbreviations()
153
150
154 # parse spec-- if present
151 # parse spec-- if present
155 if spec:
152 if spec:
156 self.parseConfiguration(spec)
153 self.parseConfiguration(spec)
157
154
158 def setPosixCompliance(self, aFlag = 0):
155 def setPosixCompliance(self, aFlag = 0):
159 """
156 """
160 Enables and disables posix compliance.
157 Enables and disables posix compliance.
161
158
162 When enabled, '+' can be used as an option prefix and free
159 When enabled, '+' can be used as an option prefix and free
163 values can be mixed with options.
160 values can be mixed with options.
164 """
161 """
165 self.posixCompliance = aFlag
162 self.posixCompliance = aFlag
166 self.needsParse = 1
163 self.needsParse = 1
167
164
168 if self.posixCompliance:
165 if self.posixCompliance:
169 self.optionStartExpr = re.compile('(--|-)(?P<option>[A-Za-z0-9_-]+)(?P<arg>=.*)?')
166 self.optionStartExpr = re.compile('(--|-)(?P<option>[A-Za-z0-9_-]+)(?P<arg>=.*)?')
170 self.orderMixed = 0
167 self.orderMixed = 0
171 else:
168 else:
172 self.optionStartExpr = re.compile('(--|-|\+)(?P<option>[A-Za-z0-9_-]+)(?P<arg>=.*)?')
169 self.optionStartExpr = re.compile('(--|-|\+)(?P<option>[A-Za-z0-9_-]+)(?P<arg>=.*)?')
173 self.orderMixed = 1
170 self.orderMixed = 1
174
171
175 def isPosixCompliant(self):
172 def isPosixCompliant(self):
176 """
173 """
177 Returns the value of the posix compliance flag.
174 Returns the value of the posix compliance flag.
178 """
175 """
179 return self.posixCompliance
176 return self.posixCompliance
180
177
181 def setIgnoreCase(self, aFlag = 1):
178 def setIgnoreCase(self, aFlag = 1):
182 """
179 """
183 Enables and disables ignoring case during option processing.
180 Enables and disables ignoring case during option processing.
184 """
181 """
185 self.needsParse = 1
182 self.needsParse = 1
186 self.ignoreCase = aFlag
183 self.ignoreCase = aFlag
187
184
188 def ignoreCase(self):
185 def ignoreCase(self):
189 """
186 """
190 Returns 1 if the option processor will ignore case when
187 Returns 1 if the option processor will ignore case when
191 processing options.
188 processing options.
192 """
189 """
193 return self.ignoreCase
190 return self.ignoreCase
194
191
195 def setAllowAbbreviations(self, aFlag = 1):
192 def setAllowAbbreviations(self, aFlag = 1):
196 """
193 """
197 Enables and disables the expansion of abbreviations during
194 Enables and disables the expansion of abbreviations during
198 option processing.
195 option processing.
199 """
196 """
200 self.allowAbbreviations = aFlag
197 self.allowAbbreviations = aFlag
201
198
202 def willAllowAbbreviations(self):
199 def willAllowAbbreviations(self):
203 """
200 """
204 Returns 1 if abbreviated options will be automatically
201 Returns 1 if abbreviated options will be automatically
205 expanded to the non-abbreviated form (instead of causing an
202 expanded to the non-abbreviated form (instead of causing an
206 unrecognized option error).
203 unrecognized option error).
207 """
204 """
208 return self.allowAbbreviations
205 return self.allowAbbreviations
209
206
210 def addTerminator(self, newTerm):
207 def addTerminator(self, newTerm):
211 """
208 """
212 Adds newTerm as terminator of option processing.
209 Adds newTerm as terminator of option processing.
213
210
214 Whenever the option processor encounters one of the terminators
211 Whenever the option processor encounters one of the terminators
215 during option processing, the processing of options terminates
212 during option processing, the processing of options terminates
216 immediately, all remaining options are stored in the termValues
213 immediately, all remaining options are stored in the termValues
217 instance variable and the full name of the terminator is stored
214 instance variable and the full name of the terminator is stored
218 in the terminator instance variable.
215 in the terminator instance variable.
219 """
216 """
220 self.terminators = self.terminators + [newTerm]
217 self.terminators = self.terminators + [newTerm]
221
218
222 def _addOption(self, oTuple):
219 def _addOption(self, oTuple):
223 """
220 """
224 Adds the option described by oTuple (name, (type, mode,
221 Adds the option described by oTuple (name, (type, mode,
225 default), alias) to optionTuples. Adds index keyed under name
222 default), alias) to optionTuples. Adds index keyed under name
226 to optionNames. Raises SpecificationError if name already in
223 to optionNames. Raises SpecificationError if name already in
227 optionNames
224 optionNames
228 """
225 """
229 (name, (type, mode, default, multi), realName) = oTuple
226 (name, (type, mode, default, multi), realName) = oTuple
230
227
231 # verify name and add to option names dictionary
228 # verify name and add to option names dictionary
232 if self.optionNames.has_key(name):
229 if self.optionNames.has_key(name):
233 if realName:
230 if realName:
234 raise SpecificationError('Alias \'' + name + '\' for \'' +
231 raise SpecificationError('Alias \'' + name + '\' for \'' +
235 realName +
232 realName +
236 '\' already used for another option or alias.')
233 '\' already used for another option or alias.')
237 else:
234 else:
238 raise SpecificationError('Option named \'' + name +
235 raise SpecificationError('Option named \'' + name +
239 '\' specified more than once. Specification: '
236 '\' specified more than once. Specification: '
240 + option)
237 + option)
241
238
242 # validated. add to optionNames
239 # validated. add to optionNames
243 self.optionNames[name] = self.tupleIndex
240 self.optionNames[name] = self.tupleIndex
244 self.tupleIndex = self.tupleIndex + 1
241 self.tupleIndex = self.tupleIndex + 1
245
242
246 # add to optionTuples
243 # add to optionTuples
247 self.optionTuples = self.optionTuples + [oTuple]
244 self.optionTuples = self.optionTuples + [oTuple]
248
245
249 # if type is boolean, add negation
246 # if type is boolean, add negation
250 if type == BooleanArgType:
247 if type == BooleanArgType:
251 alias = 'no' + name
248 alias = 'no' + name
252 specTuple = (type, mode, 0, multi)
249 specTuple = (type, mode, 0, multi)
253 oTuple = (alias, specTuple, name)
250 oTuple = (alias, specTuple, name)
254
251
255 # verify name and add to option names dictionary
252 # verify name and add to option names dictionary
256 if self.optionNames.has_key(alias):
253 if self.optionNames.has_key(alias):
257 if realName:
254 if realName:
258 raise SpecificationError('Negated alias \'' + name +
255 raise SpecificationError('Negated alias \'' + name +
259 '\' for \'' + realName +
256 '\' for \'' + realName +
260 '\' already used for another option or alias.')
257 '\' already used for another option or alias.')
261 else:
258 else:
262 raise SpecificationError('Negated option named \'' + name +
259 raise SpecificationError('Negated option named \'' + name +
263 '\' specified more than once. Specification: '
260 '\' specified more than once. Specification: '
264 + option)
261 + option)
265
262
266 # validated. add to optionNames
263 # validated. add to optionNames
267 self.optionNames[alias] = self.tupleIndex
264 self.optionNames[alias] = self.tupleIndex
268 self.tupleIndex = self.tupleIndex + 1
265 self.tupleIndex = self.tupleIndex + 1
269
266
270 # add to optionTuples
267 # add to optionTuples
271 self.optionTuples = self.optionTuples + [oTuple]
268 self.optionTuples = self.optionTuples + [oTuple]
272
269
273 def addOptionConfigurationTuple(self, oTuple):
270 def addOptionConfigurationTuple(self, oTuple):
274 (name, argSpec, realName) = oTuple
271 (name, argSpec, realName) = oTuple
275 if self.ignoreCase:
272 if self.ignoreCase:
276 name = string.lower(name)
273 name = string.lower(name)
277 if realName:
274 if realName:
278 realName = string.lower(realName)
275 realName = string.lower(realName)
279 else:
276 else:
280 realName = name
277 realName = name
281
278
282 oTuple = (name, argSpec, realName)
279 oTuple = (name, argSpec, realName)
283
280
284 # add option
281 # add option
285 self._addOption(oTuple)
282 self._addOption(oTuple)
286
283
287 def addOptionConfigurationTuples(self, oTuple):
284 def addOptionConfigurationTuples(self, oTuple):
288 if type(oTuple) is ListType:
285 if type(oTuple) is ListType:
289 for t in oTuple:
286 for t in oTuple:
290 self.addOptionConfigurationTuple(t)
287 self.addOptionConfigurationTuple(t)
291 else:
288 else:
292 self.addOptionConfigurationTuple(oTuple)
289 self.addOptionConfigurationTuple(oTuple)
293
290
294 def parseConfiguration(self, spec):
291 def parseConfiguration(self, spec):
295 # destroy previous stored information + store raw spec
292 # destroy previous stored information + store raw spec
296 self.spec = spec
293 self.spec = spec
297 self.optionTuples = []
294 self.optionTuples = []
298 self.optionNames = {}
295 self.optionNames = {}
299 self.tupleIndex = 0
296 self.tupleIndex = 0
300
297
301 tupleIndex = 0
298 tupleIndex = 0
302
299
303 # create some regex's for parsing each spec
300 # create some regex's for parsing each spec
304 splitExpr = \
301 splitExpr = \
305 re.compile('(?P<names>\w+[-A-Za-z0-9|]*)?(?P<spec>!|[=:][infs]@?)?')
302 re.compile('(?P<names>\w+[-A-Za-z0-9|]*)?(?P<spec>!|[=:][infs]@?)?')
306 for option in spec:
303 for option in spec:
307 # push to lower case (does not negatively affect
304 # push to lower case (does not negatively affect
308 # specification)
305 # specification)
309 if self.ignoreCase:
306 if self.ignoreCase:
310 option = string.lower(option)
307 option = string.lower(option)
311
308
312 # break into names, specification
309 # break into names, specification
313 match = splitExpr.match(option)
310 match = splitExpr.match(option)
314 if match is None:
311 if match is None:
315 raise SpecificationError('Invalid specification {' + option +
312 raise SpecificationError('Invalid specification {' + option +
316 '}')
313 '}')
317
314
318 names = match.group('names')
315 names = match.group('names')
319 specification = match.group('spec')
316 specification = match.group('spec')
320
317
321 # break name into name, aliases
318 # break name into name, aliases
322 nlist = string.split(names, '|')
319 nlist = string.split(names, '|')
323
320
324 # get name
321 # get name
325 name = nlist[0]
322 name = nlist[0]
326 aliases = nlist[1:]
323 aliases = nlist[1:]
327
324
328 # specificationExpr = regex.symcomp('\(<required>.\)\(<type>.\)\(<multi>@?\)')
325 # specificationExpr = regex.symcomp('\(<required>.\)\(<type>.\)\(<multi>@?\)')
329 if not specification:
326 if not specification:
330 #spec tuple is ('type', 'arg mode', 'default value', 'multiple')
327 #spec tuple is ('type', 'arg mode', 'default value', 'multiple')
331 argType = GenericArgType
328 argType = GenericArgType
332 argMode = None
329 argMode = None
333 argDefault = 1
330 argDefault = 1
334 argMultiple = 0
331 argMultiple = 0
335 elif specification == '!':
332 elif specification == '!':
336 argType = BooleanArgType
333 argType = BooleanArgType
337 argMode = None
334 argMode = None
338 argDefault = 1
335 argDefault = 1
339 argMultiple = 0
336 argMultiple = 0
340 else:
337 else:
341 # parse
338 # parse
342 match = specificationExpr.match(specification)
339 match = specificationExpr.match(specification)
343 if match is None:
340 if match is None:
344 # failed to parse, die
341 # failed to parse, die
345 raise SpecificationError('Invalid configuration for option \''
342 raise SpecificationError('Invalid configuration for option \''
346 + option + '\'')
343 + option + '\'')
347
344
348 # determine mode
345 # determine mode
349 required = match.group('required')
346 required = match.group('required')
350 if required == '=':
347 if required == '=':
351 argMode = ArgRequired
348 argMode = ArgRequired
352 elif required == ':':
349 elif required == ':':
353 argMode = ArgOptional
350 argMode = ArgOptional
354 else:
351 else:
355 raise SpecificationError('Unknown requirement configuration \''
352 raise SpecificationError('Unknown requirement configuration \''
356 + required + '\'')
353 + required + '\'')
357
354
358 # determine type
355 # determine type
359 type = match.group('type')
356 type = match.group('type')
360 if type == 's':
357 if type == 's':
361 argType = StringArgType
358 argType = StringArgType
362 argDefault = ''
359 argDefault = ''
363 elif type == 'i':
360 elif type == 'i':
364 argType = IntegerArgType
361 argType = IntegerArgType
365 argDefault = 1
362 argDefault = 1
366 elif type == 'f' or type == 'n':
363 elif type == 'f' or type == 'n':
367 argType = RealArgType
364 argType = RealArgType
368 argDefault = 1
365 argDefault = 1
369 else:
366 else:
370 raise SpecificationError('Unknown type specifier \'' +
367 raise SpecificationError('Unknown type specifier \'' +
371 type + '\'')
368 type + '\'')
372
369
373 # determine quantity
370 # determine quantity
374 if match.group('multi') == '@':
371 if match.group('multi') == '@':
375 argMultiple = 1
372 argMultiple = 1
376 else:
373 else:
377 argMultiple = 0
374 argMultiple = 0
378 ## end else (of not specification)
375 ## end else (of not specification)
379
376
380 # construct specification tuple
377 # construct specification tuple
381 specTuple = (argType, argMode, argDefault, argMultiple)
378 specTuple = (argType, argMode, argDefault, argMultiple)
382
379
383 # add the option-- option tuple is (name, specTuple, real name)
380 # add the option-- option tuple is (name, specTuple, real name)
384 oTuple = (name, specTuple, name)
381 oTuple = (name, specTuple, name)
385 self._addOption(oTuple)
382 self._addOption(oTuple)
386
383
387 for alias in aliases:
384 for alias in aliases:
388 # drop to all lower (if configured to do so)
385 # drop to all lower (if configured to do so)
389 if self.ignoreCase:
386 if self.ignoreCase:
390 alias = string.lower(alias)
387 alias = string.lower(alias)
391 # create configuration tuple
388 # create configuration tuple
392 oTuple = (alias, specTuple, name)
389 oTuple = (alias, specTuple, name)
393 # add
390 # add
394 self._addOption(oTuple)
391 self._addOption(oTuple)
395
392
396 # successfully parsed....
393 # successfully parsed....
397 self.needsParse = 0
394 self.needsParse = 0
398
395
399 def _getArgTuple(self, argName):
396 def _getArgTuple(self, argName):
400 """
397 """
401 Returns a list containing all the specification tuples that
398 Returns a list containing all the specification tuples that
402 match argName. If none match, None is returned. If one
399 match argName. If none match, None is returned. If one
403 matches, a list with one tuple is returned. If more than one
400 matches, a list with one tuple is returned. If more than one
404 match, a list containing all the tuples that matched is
401 match, a list containing all the tuples that matched is
405 returned.
402 returned.
406
403
407 In other words, this function does not pass judgement upon the
404 In other words, this function does not pass judgement upon the
408 validity of multiple matches.
405 validity of multiple matches.
409 """
406 """
410 # is it in the optionNames dict?
407 # is it in the optionNames dict?
411
408
412 try:
409 try:
413 # sys.stderr.write(argName + string.join(self.optionNames.keys()) + "\n")
410 # sys.stderr.write(argName + string.join(self.optionNames.keys()) + "\n")
414
411
415 # yes, get index
412 # yes, get index
416 tupleIndex = self.optionNames[argName]
413 tupleIndex = self.optionNames[argName]
417 # and return tuple as element of list
414 # and return tuple as element of list
418 return [self.optionTuples[tupleIndex]]
415 return [self.optionTuples[tupleIndex]]
419 except KeyError:
416 except KeyError:
420 # are abbreviations allowed?
417 # are abbreviations allowed?
421 if not self.allowAbbreviations:
418 if not self.allowAbbreviations:
422 # No! terefore, this cannot be valid argument-- nothing found
419 # No! terefore, this cannot be valid argument-- nothing found
423 return None
420 return None
424
421
425 # argName might be an abbreviation (and, abbreviations must
422 # argName might be an abbreviation (and, abbreviations must
426 # be allowed... or this would not have been reached!)
423 # be allowed... or this would not have been reached!)
427
424
428 # create regex for argName
425 # create regex for argName
429 argExpr = re.compile('^' + argName)
426 argExpr = re.compile('^' + argName)
430
427
431 tuples = filter(lambda x, argExpr=argExpr: argExpr.search(x[0]) is not None,
428 tuples = filter(lambda x, argExpr=argExpr: argExpr.search(x[0]) is not None,
432 self.optionTuples)
429 self.optionTuples)
433
430
434 if not len(tuples):
431 if not len(tuples):
435 return None
432 return None
436 else:
433 else:
437 return tuples
434 return tuples
438
435
439 def _isTerminator(self, optionName):
436 def _isTerminator(self, optionName):
440 """
437 """
441 Returns the full name of the terminator if optionName is a valid
438 Returns the full name of the terminator if optionName is a valid
442 terminator. If it is, sets self.terminator to the full name of
439 terminator. If it is, sets self.terminator to the full name of
443 the terminator.
440 the terminator.
444
441
445 If more than one terminator matched, raises a TerminationError with a
442 If more than one terminator matched, raises a TerminationError with a
446 string describing the ambiguity.
443 string describing the ambiguity.
447 """
444 """
448
445
449 # sys.stderr.write(optionName + "\n")
446 # sys.stderr.write(optionName + "\n")
450 # sys.stderr.write(repr(self.terminators))
447 # sys.stderr.write(repr(self.terminators))
451
448
452 if optionName in self.terminators:
449 if optionName in self.terminators:
453 self.terminator = optionName
450 self.terminator = optionName
454 elif not self.allowAbbreviations:
451 elif not self.allowAbbreviations:
455 return None
452 return None
456
453
457 # regex thing in bogus
454 # regex thing in bogus
458 # termExpr = regex.compile('^' + optionName)
455 # termExpr = regex.compile('^' + optionName)
459
456
460 terms = filter(lambda x, on=optionName: string.find(x,on) == 0, self.terminators)
457 terms = filter(lambda x, on=optionName: string.find(x,on) == 0, self.terminators)
461
458
462 if not len(terms):
459 if not len(terms):
463 return None
460 return None
464 elif len(terms) > 1:
461 elif len(terms) > 1:
465 raise TerminationError('Ambiguous terminator \'' + optionName +
462 raise TerminationError('Ambiguous terminator \'' + optionName +
466 '\' matches ' + repr(terms))
463 '\' matches ' + repr(terms))
467
464
468 self.terminator = terms[0]
465 self.terminator = terms[0]
469 return self.terminator
466 return self.terminator
470
467
471 def processArguments(self, args = None):
468 def processArguments(self, args = None):
472 """
469 """
473 Processes args, a list of arguments (including options).
470 Processes args, a list of arguments (including options).
474
471
475 If args is the same as sys.argv, automatically trims the first
472 If args is the same as sys.argv, automatically trims the first
476 argument (the executable name/path).
473 argument (the executable name/path).
477
474
478 If an exception is not raised, the argument list was parsed
475 If an exception is not raised, the argument list was parsed
479 correctly.
476 correctly.
480
477
481 Upon successful completion, the freeValues instance variable
478 Upon successful completion, the freeValues instance variable
482 will contain all the arguments that were not associated with an
479 will contain all the arguments that were not associated with an
483 option in the order they were encountered. optionValues is a
480 option in the order they were encountered. optionValues is a
484 dictionary containing the value of each option-- the method
481 dictionary containing the value of each option-- the method
485 valueForOption() can be used to query this dictionary.
482 valueForOption() can be used to query this dictionary.
486 terminator will contain the argument encountered that terminated
483 terminator will contain the argument encountered that terminated
487 option processing (or None, if a terminator was never
484 option processing (or None, if a terminator was never
488 encountered) and termValues will contain all of the options that
485 encountered) and termValues will contain all of the options that
489 appeared after the Terminator (or an empty list).
486 appeared after the Terminator (or an empty list).
490 """
487 """
491
488
492 if hasattr(sys, "argv") and args == sys.argv:
489 if hasattr(sys, "argv") and args == sys.argv:
493 args = sys.argv[1:]
490 args = sys.argv[1:]
494
491
495 max = len(args) # maximum index + 1
492 max = len(args) # maximum index + 1
496 self.freeValues = [] # array to hold return values
493 self.freeValues = [] # array to hold return values
497 self.optionValues= {}
494 self.optionValues= {}
498 index = 0 # initial index
495 index = 0 # initial index
499 self.terminator = None
496 self.terminator = None
500 self.termValues = []
497 self.termValues = []
501
498
502 while index < max:
499 while index < max:
503 # obtain argument
500 # obtain argument
504 arg = args[index]
501 arg = args[index]
505 # increment index -- REMEMBER; it is NOW incremented
502 # increment index -- REMEMBER; it is NOW incremented
506 index = index + 1
503 index = index + 1
507
504
508 # terminate immediately if option terminator encountered
505 # terminate immediately if option terminator encountered
509 if self._isTerminator(arg):
506 if self._isTerminator(arg):
510 self.freeValues = self.freeValues + args[index:]
507 self.freeValues = self.freeValues + args[index:]
511 self.termValues = args[index:]
508 self.termValues = args[index:]
512 return
509 return
513
510
514 # is this possibly an option?
511 # is this possibly an option?
515 match = self.optionStartExpr.match(arg)
512 match = self.optionStartExpr.match(arg)
516 if match is None:
513 if match is None:
517 # not an option-- add to freeValues
514 # not an option-- add to freeValues
518 self.freeValues = self.freeValues + [arg]
515 self.freeValues = self.freeValues + [arg]
519 if not self.orderMixed:
516 if not self.orderMixed:
520 # mixing not allowed; add rest of args as freeValues
517 # mixing not allowed; add rest of args as freeValues
521 self.freeValues = self.freeValues + args[index:]
518 self.freeValues = self.freeValues + args[index:]
522 # return to caller
519 # return to caller
523 return
520 return
524 else:
521 else:
525 continue
522 continue
526
523
527 # grab name
524 # grab name
528 optName = match.group('option')
525 optName = match.group('option')
529
526
530 # obtain next argument-- index has already been incremented
527 # obtain next argument-- index has already been incremented
531 nextArg = match.group('arg')
528 nextArg = match.group('arg')
532 if nextArg:
529 if nextArg:
533 nextArg = nextArg[1:]
530 nextArg = nextArg[1:]
534 index = index - 1 # put it back
531 index = index - 1 # put it back
535 else:
532 else:
536 try:
533 try:
537 nextArg = args[index]
534 nextArg = args[index]
538 except:
535 except:
539 nextArg = None
536 nextArg = None
540
537
541 # transpose to lower case, if necessary
538 # transpose to lower case, if necessary
542 if self.ignoreCase:
539 if self.ignoreCase:
543 optName = string.lower(optName)
540 optName = string.lower(optName)
544
541
545 # obtain defining tuple
542 # obtain defining tuple
546 tuples = self._getArgTuple(optName)
543 tuples = self._getArgTuple(optName)
547
544
548 if tuples == None:
545 if tuples == None:
549 raise ArgumentError('Illegal option \'' + arg + '\'')
546 raise ArgumentError('Illegal option \'' + arg + '\'')
550 elif len(tuples) > 1:
547 elif len(tuples) > 1:
551 raise ArgumentError('Ambiguous option \'' + arg +
548 raise ArgumentError('Ambiguous option \'' + arg +
552 '\'; matches ' +
549 '\'; matches ' +
553 repr(map(lambda x: x[0], tuples)))
550 repr(map(lambda x: x[0], tuples)))
554 else:
551 else:
555 config = tuples[0]
552 config = tuples[0]
556
553
557 # config is now set to the configuration tuple for the
554 # config is now set to the configuration tuple for the
558 # argument
555 # argument
559 (fullName, spec, realName) = config
556 (fullName, spec, realName) = config
560 (optType, optMode, optDefault, optMultiple) = spec
557 (optType, optMode, optDefault, optMultiple) = spec
561
558
562 # if opt mode required, but nextArg is none, raise an error
559 # if opt mode required, but nextArg is none, raise an error
563 if (optMode == ArgRequired):
560 if (optMode == ArgRequired):
564 if (not nextArg) or self._isTerminator(nextArg):
561 if (not nextArg) or self._isTerminator(nextArg):
565 # print nextArg
562 # print nextArg
566 raise ArgumentError('Option \'' + arg +
563 raise ArgumentError('Option \'' + arg +
567 '\' requires an argument of type ' +
564 '\' requires an argument of type ' +
568 optType)
565 optType)
569
566
570 if (not optMode == None) and nextArg and (not self._isTerminator(nextArg)):
567 if (not optMode == None) and nextArg and (not self._isTerminator(nextArg)):
571 # nextArg defined, option configured to possibly consume arg
568 # nextArg defined, option configured to possibly consume arg
572 try:
569 try:
573 # grab conversion function-- the try is more for internal diagnostics
570 # grab conversion function-- the try is more for internal diagnostics
574 func = ConversionFunctions[optType]
571 func = ConversionFunctions[optType]
575 try:
572 try:
576 optionValue = func(nextArg)
573 optionValue = func(nextArg)
577 index = index + 1
574 index = index + 1
578 except:
575 except:
579 # only raise conversion error if REQUIRED to consume argument
576 # only raise conversion error if REQUIRED to consume argument
580 if optMode == ArgRequired:
577 if optMode == ArgRequired:
581 raise ArgumentError('Invalid argument to option \''
578 raise ArgumentError('Invalid argument to option \''
582 + arg + '\'; should be \'' +
579 + arg + '\'; should be \'' +
583 optType + '\'')
580 optType + '\'')
584 else:
581 else:
585 optionValue = optDefault
582 optionValue = optDefault
586 except ArgumentError:
583 except ArgumentError:
587 raise
584 raise
588 except:
585 except:
589 raise ArgumentError('(' + arg +
586 raise ArgumentError('(' + arg +
590 ') Conversion function for \'' +
587 ') Conversion function for \'' +
591 optType + '\' not found.')
588 optType + '\' not found.')
592 else:
589 else:
593 optionValue = optDefault
590 optionValue = optDefault
594
591
595 # add value to options dictionary
592 # add value to options dictionary
596 if optMultiple:
593 if optMultiple:
597 # can be multiple values
594 # can be multiple values
598 try:
595 try:
599 # try to append element
596 # try to append element
600 self.optionValues[realName] = self.optionValues[realName] + [optionValue]
597 self.optionValues[realName] = self.optionValues[realName] + [optionValue]
601 except:
598 except:
602 # failed-- must not exist; add it
599 # failed-- must not exist; add it
603 self.optionValues[realName] = [optionValue]
600 self.optionValues[realName] = [optionValue]
604 else:
601 else:
605 # only one value per
602 # only one value per
606 if self.isPosixCompliant and self.optionValues.has_key(realName):
603 if self.isPosixCompliant and self.optionValues.has_key(realName):
607 raise ArgumentError('Argument \'' + arg +
604 raise ArgumentError('Argument \'' + arg +
608 '\' occurs multiple times.')
605 '\' occurs multiple times.')
609
606
610 self.optionValues[realName] = optionValue
607 self.optionValues[realName] = optionValue
611
608
612 def valueForOption(self, optionName, defaultValue = None):
609 def valueForOption(self, optionName, defaultValue = None):
613 """
610 """
614 Return the value associated with optionName. If optionName was
611 Return the value associated with optionName. If optionName was
615 not encountered during parsing of the arguments, returns the
612 not encountered during parsing of the arguments, returns the
616 defaultValue (which defaults to None).
613 defaultValue (which defaults to None).
617 """
614 """
618 try:
615 try:
619 optionValue = self.optionValues[optionName]
616 optionValue = self.optionValues[optionName]
620 except:
617 except:
621 optionValue = defaultValue
618 optionValue = defaultValue
622
619
623 return optionValue
620 return optionValue
624
621
625 ##
622 ##
626 ## test/example section
623 ## test/example section
627 ##
624 ##
628 test_error = 'Test Run Amok!'
625 test_error = 'Test Run Amok!'
629 def _test():
626 def _test():
630 """
627 """
631 A relatively complete test suite.
628 A relatively complete test suite.
632 """
629 """
633 try:
630 try:
634 DPyGetOpt(['foo', 'bar=s', 'foo'])
631 DPyGetOpt(['foo', 'bar=s', 'foo'])
635 except Error, exc:
632 except Error, exc:
636 print 'EXCEPTION (should be \'foo\' already used..): %s' % exc
633 print 'EXCEPTION (should be \'foo\' already used..): %s' % exc
637
634
638 try:
635 try:
639 DPyGetOpt(['foo|bar|apple=s@', 'baz|apple!'])
636 DPyGetOpt(['foo|bar|apple=s@', 'baz|apple!'])
640 except Error, exc:
637 except Error, exc:
641 print 'EXCEPTION (should be duplicate alias/name error): %s' % exc
638 print 'EXCEPTION (should be duplicate alias/name error): %s' % exc
642
639
643 x = DPyGetOpt(['apple|atlas=i@', 'application|executable=f@'])
640 x = DPyGetOpt(['apple|atlas=i@', 'application|executable=f@'])
644 try:
641 try:
645 x.processArguments(['-app', '29.3'])
642 x.processArguments(['-app', '29.3'])
646 except Error, exc:
643 except Error, exc:
647 print 'EXCEPTION (should be ambiguous argument): %s' % exc
644 print 'EXCEPTION (should be ambiguous argument): %s' % exc
648
645
649 x = DPyGetOpt(['foo'], ['antigravity', 'antithesis'])
646 x = DPyGetOpt(['foo'], ['antigravity', 'antithesis'])
650 try:
647 try:
651 x.processArguments(['-foo', 'anti'])
648 x.processArguments(['-foo', 'anti'])
652 except Error, exc:
649 except Error, exc:
653 print 'EXCEPTION (should be ambiguous terminator): %s' % exc
650 print 'EXCEPTION (should be ambiguous terminator): %s' % exc
654
651
655 profile = ['plain-option',
652 profile = ['plain-option',
656 'boolean-option!',
653 'boolean-option!',
657 'list-of-integers=i@',
654 'list-of-integers=i@',
658 'list-real-option|list-real-alias|list-real-pseudonym=f@',
655 'list-real-option|list-real-alias|list-real-pseudonym=f@',
659 'optional-string-option:s',
656 'optional-string-option:s',
660 'abbreviated-string-list=s@']
657 'abbreviated-string-list=s@']
661
658
662 terminators = ['terminator']
659 terminators = ['terminator']
663
660
664 args = ['-plain-option',
661 args = ['-plain-option',
665 '+noboolean-option',
662 '+noboolean-option',
666 '--list-of-integers', '1',
663 '--list-of-integers', '1',
667 '+list-of-integers', '2',
664 '+list-of-integers', '2',
668 '-list-of-integers', '3',
665 '-list-of-integers', '3',
669 'freeargone',
666 'freeargone',
670 '-list-real-option', '1.1',
667 '-list-real-option', '1.1',
671 '+list-real-alias', '1.2',
668 '+list-real-alias', '1.2',
672 '--list-real-pseudonym', '1.3',
669 '--list-real-pseudonym', '1.3',
673 'freeargtwo',
670 'freeargtwo',
674 '-abbreviated-string-list', 'String1',
671 '-abbreviated-string-list', 'String1',
675 '--abbreviated-s', 'String2',
672 '--abbreviated-s', 'String2',
676 '-abbrev', 'String3',
673 '-abbrev', 'String3',
677 '-a', 'String4',
674 '-a', 'String4',
678 '-optional-string-option',
675 '-optional-string-option',
679 'term',
676 'term',
680 'next option should look like an invalid arg',
677 'next option should look like an invalid arg',
681 '-a']
678 '-a']
682
679
683
680
684 print 'Using profile: ' + repr(profile)
681 print 'Using profile: ' + repr(profile)
685 print 'With terminator: ' + repr(terminators)
682 print 'With terminator: ' + repr(terminators)
686 print 'Processing arguments: ' + repr(args)
683 print 'Processing arguments: ' + repr(args)
687
684
688 go = DPyGetOpt(profile, terminators)
685 go = DPyGetOpt(profile, terminators)
689 go.processArguments(args)
686 go.processArguments(args)
690
687
691 print 'Options (and values): ' + repr(go.optionValues)
688 print 'Options (and values): ' + repr(go.optionValues)
692 print 'free args: ' + repr(go.freeValues)
689 print 'free args: ' + repr(go.freeValues)
693 print 'term args: ' + repr(go.termValues)
690 print 'term args: ' + repr(go.termValues)
@@ -1,528 +1,522 b''
1 # -*- coding: utf-8 -*-
1 # -*- coding: utf-8 -*-
2 """
2 """
3 Pdb debugger class.
3 Pdb debugger class.
4
4
5 Modified from the standard pdb.Pdb class to avoid including readline, so that
5 Modified from the standard pdb.Pdb class to avoid including readline, so that
6 the command line completion of other programs which include this isn't
6 the command line completion of other programs which include this isn't
7 damaged.
7 damaged.
8
8
9 In the future, this class will be expanded with improvements over the standard
9 In the future, this class will be expanded with improvements over the standard
10 pdb.
10 pdb.
11
11
12 The code in this file is mainly lifted out of cmd.py in Python 2.2, with minor
12 The code in this file is mainly lifted out of cmd.py in Python 2.2, with minor
13 changes. Licensing should therefore be under the standard Python terms. For
13 changes. Licensing should therefore be under the standard Python terms. For
14 details on the PSF (Python Software Foundation) standard license, see:
14 details on the PSF (Python Software Foundation) standard license, see:
15
15
16 http://www.python.org/2.2.3/license.html
16 http://www.python.org/2.2.3/license.html"""
17
18 $Id: Debugger.py 2913 2007-12-31 12:42:14Z vivainio $"""
19
17
20 #*****************************************************************************
18 #*****************************************************************************
21 #
19 #
22 # This file is licensed under the PSF license.
20 # This file is licensed under the PSF license.
23 #
21 #
24 # Copyright (C) 2001 Python Software Foundation, www.python.org
22 # Copyright (C) 2001 Python Software Foundation, www.python.org
25 # Copyright (C) 2005-2006 Fernando Perez. <fperez@colorado.edu>
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 import bdb
28 import bdb
35 import cmd
29 import cmd
36 import linecache
30 import linecache
37 import os
31 import os
38 import sys
32 import sys
39
33
40 from IPython import PyColorize, ColorANSI, ipapi
34 from IPython import PyColorize, ColorANSI, ipapi
41 from IPython.genutils import Term
35 from IPython.genutils import Term
42 from IPython.excolors import exception_colors
36 from IPython.excolors import exception_colors
43
37
44 # See if we can use pydb.
38 # See if we can use pydb.
45 has_pydb = False
39 has_pydb = False
46 prompt = 'ipdb> '
40 prompt = 'ipdb> '
47 #We have to check this directly from sys.argv, config struct not yet available
41 #We have to check this directly from sys.argv, config struct not yet available
48 if '-pydb' in sys.argv:
42 if '-pydb' in sys.argv:
49 try:
43 try:
50 import pydb
44 import pydb
51 if hasattr(pydb.pydb, "runl") and pydb.version>'1.17':
45 if hasattr(pydb.pydb, "runl") and pydb.version>'1.17':
52 # Version 1.17 is broken, and that's what ships with Ubuntu Edgy, so we
46 # Version 1.17 is broken, and that's what ships with Ubuntu Edgy, so we
53 # better protect against it.
47 # better protect against it.
54 has_pydb = True
48 has_pydb = True
55 except ImportError:
49 except ImportError:
56 print "Pydb (http://bashdb.sourceforge.net/pydb/) does not seem to be available"
50 print "Pydb (http://bashdb.sourceforge.net/pydb/) does not seem to be available"
57
51
58 if has_pydb:
52 if has_pydb:
59 from pydb import Pdb as OldPdb
53 from pydb import Pdb as OldPdb
60 #print "Using pydb for %run -d and post-mortem" #dbg
54 #print "Using pydb for %run -d and post-mortem" #dbg
61 prompt = 'ipydb> '
55 prompt = 'ipydb> '
62 else:
56 else:
63 from pdb import Pdb as OldPdb
57 from pdb import Pdb as OldPdb
64
58
65 # Allow the set_trace code to operate outside of an ipython instance, even if
59 # Allow the set_trace code to operate outside of an ipython instance, even if
66 # it does so with some limitations. The rest of this support is implemented in
60 # it does so with some limitations. The rest of this support is implemented in
67 # the Tracer constructor.
61 # the Tracer constructor.
68 def BdbQuit_excepthook(et,ev,tb):
62 def BdbQuit_excepthook(et,ev,tb):
69 if et==bdb.BdbQuit:
63 if et==bdb.BdbQuit:
70 print 'Exiting Debugger.'
64 print 'Exiting Debugger.'
71 else:
65 else:
72 BdbQuit_excepthook.excepthook_ori(et,ev,tb)
66 BdbQuit_excepthook.excepthook_ori(et,ev,tb)
73
67
74 def BdbQuit_IPython_excepthook(self,et,ev,tb):
68 def BdbQuit_IPython_excepthook(self,et,ev,tb):
75 print 'Exiting Debugger.'
69 print 'Exiting Debugger.'
76
70
77 class Tracer(object):
71 class Tracer(object):
78 """Class for local debugging, similar to pdb.set_trace.
72 """Class for local debugging, similar to pdb.set_trace.
79
73
80 Instances of this class, when called, behave like pdb.set_trace, but
74 Instances of this class, when called, behave like pdb.set_trace, but
81 providing IPython's enhanced capabilities.
75 providing IPython's enhanced capabilities.
82
76
83 This is implemented as a class which must be initialized in your own code
77 This is implemented as a class which must be initialized in your own code
84 and not as a standalone function because we need to detect at runtime
78 and not as a standalone function because we need to detect at runtime
85 whether IPython is already active or not. That detection is done in the
79 whether IPython is already active or not. That detection is done in the
86 constructor, ensuring that this code plays nicely with a running IPython,
80 constructor, ensuring that this code plays nicely with a running IPython,
87 while functioning acceptably (though with limitations) if outside of it.
81 while functioning acceptably (though with limitations) if outside of it.
88 """
82 """
89
83
90 def __init__(self,colors=None):
84 def __init__(self,colors=None):
91 """Create a local debugger instance.
85 """Create a local debugger instance.
92
86
93 :Parameters:
87 :Parameters:
94
88
95 - `colors` (None): a string containing the name of the color scheme to
89 - `colors` (None): a string containing the name of the color scheme to
96 use, it must be one of IPython's valid color schemes. If not given, the
90 use, it must be one of IPython's valid color schemes. If not given, the
97 function will default to the current IPython scheme when running inside
91 function will default to the current IPython scheme when running inside
98 IPython, and to 'NoColor' otherwise.
92 IPython, and to 'NoColor' otherwise.
99
93
100 Usage example:
94 Usage example:
101
95
102 from IPython.Debugger import Tracer; debug_here = Tracer()
96 from IPython.Debugger import Tracer; debug_here = Tracer()
103
97
104 ... later in your code
98 ... later in your code
105 debug_here() # -> will open up the debugger at that point.
99 debug_here() # -> will open up the debugger at that point.
106
100
107 Once the debugger activates, you can use all of its regular commands to
101 Once the debugger activates, you can use all of its regular commands to
108 step through code, set breakpoints, etc. See the pdb documentation
102 step through code, set breakpoints, etc. See the pdb documentation
109 from the Python standard library for usage details.
103 from the Python standard library for usage details.
110 """
104 """
111
105
112 global __IPYTHON__
106 global __IPYTHON__
113 try:
107 try:
114 __IPYTHON__
108 __IPYTHON__
115 except NameError:
109 except NameError:
116 # Outside of ipython, we set our own exception hook manually
110 # Outside of ipython, we set our own exception hook manually
117 __IPYTHON__ = ipapi.get(True,False)
111 __IPYTHON__ = ipapi.get(True,False)
118 BdbQuit_excepthook.excepthook_ori = sys.excepthook
112 BdbQuit_excepthook.excepthook_ori = sys.excepthook
119 sys.excepthook = BdbQuit_excepthook
113 sys.excepthook = BdbQuit_excepthook
120 def_colors = 'NoColor'
114 def_colors = 'NoColor'
121 try:
115 try:
122 # Limited tab completion support
116 # Limited tab completion support
123 import rlcompleter,readline
117 import rlcompleter,readline
124 readline.parse_and_bind('tab: complete')
118 readline.parse_and_bind('tab: complete')
125 except ImportError:
119 except ImportError:
126 pass
120 pass
127 else:
121 else:
128 # In ipython, we use its custom exception handler mechanism
122 # In ipython, we use its custom exception handler mechanism
129 ip = ipapi.get()
123 ip = ipapi.get()
130 def_colors = ip.options.colors
124 def_colors = ip.options.colors
131 ip.set_custom_exc((bdb.BdbQuit,),BdbQuit_IPython_excepthook)
125 ip.set_custom_exc((bdb.BdbQuit,),BdbQuit_IPython_excepthook)
132
126
133 if colors is None:
127 if colors is None:
134 colors = def_colors
128 colors = def_colors
135 self.debugger = Pdb(colors)
129 self.debugger = Pdb(colors)
136
130
137 def __call__(self):
131 def __call__(self):
138 """Starts an interactive debugger at the point where called.
132 """Starts an interactive debugger at the point where called.
139
133
140 This is similar to the pdb.set_trace() function from the std lib, but
134 This is similar to the pdb.set_trace() function from the std lib, but
141 using IPython's enhanced debugger."""
135 using IPython's enhanced debugger."""
142
136
143 self.debugger.set_trace(sys._getframe().f_back)
137 self.debugger.set_trace(sys._getframe().f_back)
144
138
145 def decorate_fn_with_doc(new_fn, old_fn, additional_text=""):
139 def decorate_fn_with_doc(new_fn, old_fn, additional_text=""):
146 """Make new_fn have old_fn's doc string. This is particularly useful
140 """Make new_fn have old_fn's doc string. This is particularly useful
147 for the do_... commands that hook into the help system.
141 for the do_... commands that hook into the help system.
148 Adapted from from a comp.lang.python posting
142 Adapted from from a comp.lang.python posting
149 by Duncan Booth."""
143 by Duncan Booth."""
150 def wrapper(*args, **kw):
144 def wrapper(*args, **kw):
151 return new_fn(*args, **kw)
145 return new_fn(*args, **kw)
152 if old_fn.__doc__:
146 if old_fn.__doc__:
153 wrapper.__doc__ = old_fn.__doc__ + additional_text
147 wrapper.__doc__ = old_fn.__doc__ + additional_text
154 return wrapper
148 return wrapper
155
149
156 def _file_lines(fname):
150 def _file_lines(fname):
157 """Return the contents of a named file as a list of lines.
151 """Return the contents of a named file as a list of lines.
158
152
159 This function never raises an IOError exception: if the file can't be
153 This function never raises an IOError exception: if the file can't be
160 read, it simply returns an empty list."""
154 read, it simply returns an empty list."""
161
155
162 try:
156 try:
163 outfile = open(fname)
157 outfile = open(fname)
164 except IOError:
158 except IOError:
165 return []
159 return []
166 else:
160 else:
167 out = outfile.readlines()
161 out = outfile.readlines()
168 outfile.close()
162 outfile.close()
169 return out
163 return out
170
164
171 class Pdb(OldPdb):
165 class Pdb(OldPdb):
172 """Modified Pdb class, does not load readline."""
166 """Modified Pdb class, does not load readline."""
173
167
174 if sys.version[:3] >= '2.5' or has_pydb:
168 if sys.version[:3] >= '2.5' or has_pydb:
175 def __init__(self,color_scheme='NoColor',completekey=None,
169 def __init__(self,color_scheme='NoColor',completekey=None,
176 stdin=None, stdout=None):
170 stdin=None, stdout=None):
177
171
178 # Parent constructor:
172 # Parent constructor:
179 if has_pydb and completekey is None:
173 if has_pydb and completekey is None:
180 OldPdb.__init__(self,stdin=stdin,stdout=Term.cout)
174 OldPdb.__init__(self,stdin=stdin,stdout=Term.cout)
181 else:
175 else:
182 OldPdb.__init__(self,completekey,stdin,stdout)
176 OldPdb.__init__(self,completekey,stdin,stdout)
183
177
184 self.prompt = prompt # The default prompt is '(Pdb)'
178 self.prompt = prompt # The default prompt is '(Pdb)'
185
179
186 # IPython changes...
180 # IPython changes...
187 self.is_pydb = has_pydb
181 self.is_pydb = has_pydb
188
182
189 if self.is_pydb:
183 if self.is_pydb:
190
184
191 # iplib.py's ipalias seems to want pdb's checkline
185 # iplib.py's ipalias seems to want pdb's checkline
192 # which located in pydb.fn
186 # which located in pydb.fn
193 import pydb.fns
187 import pydb.fns
194 self.checkline = lambda filename, lineno: \
188 self.checkline = lambda filename, lineno: \
195 pydb.fns.checkline(self, filename, lineno)
189 pydb.fns.checkline(self, filename, lineno)
196
190
197 self.curframe = None
191 self.curframe = None
198 self.do_restart = self.new_do_restart
192 self.do_restart = self.new_do_restart
199
193
200 self.old_all_completions = __IPYTHON__.Completer.all_completions
194 self.old_all_completions = __IPYTHON__.Completer.all_completions
201 __IPYTHON__.Completer.all_completions=self.all_completions
195 __IPYTHON__.Completer.all_completions=self.all_completions
202
196
203 self.do_list = decorate_fn_with_doc(self.list_command_pydb,
197 self.do_list = decorate_fn_with_doc(self.list_command_pydb,
204 OldPdb.do_list)
198 OldPdb.do_list)
205 self.do_l = self.do_list
199 self.do_l = self.do_list
206 self.do_frame = decorate_fn_with_doc(self.new_do_frame,
200 self.do_frame = decorate_fn_with_doc(self.new_do_frame,
207 OldPdb.do_frame)
201 OldPdb.do_frame)
208
202
209 self.aliases = {}
203 self.aliases = {}
210
204
211 # Create color table: we copy the default one from the traceback
205 # Create color table: we copy the default one from the traceback
212 # module and add a few attributes needed for debugging
206 # module and add a few attributes needed for debugging
213 self.color_scheme_table = exception_colors()
207 self.color_scheme_table = exception_colors()
214
208
215 # shorthands
209 # shorthands
216 C = ColorANSI.TermColors
210 C = ColorANSI.TermColors
217 cst = self.color_scheme_table
211 cst = self.color_scheme_table
218
212
219 cst['NoColor'].colors.breakpoint_enabled = C.NoColor
213 cst['NoColor'].colors.breakpoint_enabled = C.NoColor
220 cst['NoColor'].colors.breakpoint_disabled = C.NoColor
214 cst['NoColor'].colors.breakpoint_disabled = C.NoColor
221
215
222 cst['Linux'].colors.breakpoint_enabled = C.LightRed
216 cst['Linux'].colors.breakpoint_enabled = C.LightRed
223 cst['Linux'].colors.breakpoint_disabled = C.Red
217 cst['Linux'].colors.breakpoint_disabled = C.Red
224
218
225 cst['LightBG'].colors.breakpoint_enabled = C.LightRed
219 cst['LightBG'].colors.breakpoint_enabled = C.LightRed
226 cst['LightBG'].colors.breakpoint_disabled = C.Red
220 cst['LightBG'].colors.breakpoint_disabled = C.Red
227
221
228 self.set_colors(color_scheme)
222 self.set_colors(color_scheme)
229
223
230 # Add a python parser so we can syntax highlight source while
224 # Add a python parser so we can syntax highlight source while
231 # debugging.
225 # debugging.
232 self.parser = PyColorize.Parser()
226 self.parser = PyColorize.Parser()
233
227
234
228
235 else:
229 else:
236 # Ugly hack: for Python 2.3-2.4, we can't call the parent constructor,
230 # Ugly hack: for Python 2.3-2.4, we can't call the parent constructor,
237 # because it binds readline and breaks tab-completion. This means we
231 # because it binds readline and breaks tab-completion. This means we
238 # have to COPY the constructor here.
232 # have to COPY the constructor here.
239 def __init__(self,color_scheme='NoColor'):
233 def __init__(self,color_scheme='NoColor'):
240 bdb.Bdb.__init__(self)
234 bdb.Bdb.__init__(self)
241 cmd.Cmd.__init__(self,completekey=None) # don't load readline
235 cmd.Cmd.__init__(self,completekey=None) # don't load readline
242 self.prompt = 'ipdb> ' # The default prompt is '(Pdb)'
236 self.prompt = 'ipdb> ' # The default prompt is '(Pdb)'
243 self.aliases = {}
237 self.aliases = {}
244
238
245 # These two lines are part of the py2.4 constructor, let's put them
239 # These two lines are part of the py2.4 constructor, let's put them
246 # unconditionally here as they won't cause any problems in 2.3.
240 # unconditionally here as they won't cause any problems in 2.3.
247 self.mainpyfile = ''
241 self.mainpyfile = ''
248 self._wait_for_mainpyfile = 0
242 self._wait_for_mainpyfile = 0
249
243
250 # Read $HOME/.pdbrc and ./.pdbrc
244 # Read $HOME/.pdbrc and ./.pdbrc
251 try:
245 try:
252 self.rcLines = _file_lines(os.path.join(os.environ['HOME'],
246 self.rcLines = _file_lines(os.path.join(os.environ['HOME'],
253 ".pdbrc"))
247 ".pdbrc"))
254 except KeyError:
248 except KeyError:
255 self.rcLines = []
249 self.rcLines = []
256 self.rcLines.extend(_file_lines(".pdbrc"))
250 self.rcLines.extend(_file_lines(".pdbrc"))
257
251
258 # Create color table: we copy the default one from the traceback
252 # Create color table: we copy the default one from the traceback
259 # module and add a few attributes needed for debugging
253 # module and add a few attributes needed for debugging
260 self.color_scheme_table = exception_colors()
254 self.color_scheme_table = exception_colors()
261
255
262 # shorthands
256 # shorthands
263 C = ColorANSI.TermColors
257 C = ColorANSI.TermColors
264 cst = self.color_scheme_table
258 cst = self.color_scheme_table
265
259
266 cst['NoColor'].colors.breakpoint_enabled = C.NoColor
260 cst['NoColor'].colors.breakpoint_enabled = C.NoColor
267 cst['NoColor'].colors.breakpoint_disabled = C.NoColor
261 cst['NoColor'].colors.breakpoint_disabled = C.NoColor
268
262
269 cst['Linux'].colors.breakpoint_enabled = C.LightRed
263 cst['Linux'].colors.breakpoint_enabled = C.LightRed
270 cst['Linux'].colors.breakpoint_disabled = C.Red
264 cst['Linux'].colors.breakpoint_disabled = C.Red
271
265
272 cst['LightBG'].colors.breakpoint_enabled = C.LightRed
266 cst['LightBG'].colors.breakpoint_enabled = C.LightRed
273 cst['LightBG'].colors.breakpoint_disabled = C.Red
267 cst['LightBG'].colors.breakpoint_disabled = C.Red
274
268
275 self.set_colors(color_scheme)
269 self.set_colors(color_scheme)
276
270
277 # Add a python parser so we can syntax highlight source while
271 # Add a python parser so we can syntax highlight source while
278 # debugging.
272 # debugging.
279 self.parser = PyColorize.Parser()
273 self.parser = PyColorize.Parser()
280
274
281 def set_colors(self, scheme):
275 def set_colors(self, scheme):
282 """Shorthand access to the color table scheme selector method."""
276 """Shorthand access to the color table scheme selector method."""
283 self.color_scheme_table.set_active_scheme(scheme)
277 self.color_scheme_table.set_active_scheme(scheme)
284
278
285 def interaction(self, frame, traceback):
279 def interaction(self, frame, traceback):
286 __IPYTHON__.set_completer_frame(frame)
280 __IPYTHON__.set_completer_frame(frame)
287 OldPdb.interaction(self, frame, traceback)
281 OldPdb.interaction(self, frame, traceback)
288
282
289 def new_do_up(self, arg):
283 def new_do_up(self, arg):
290 OldPdb.do_up(self, arg)
284 OldPdb.do_up(self, arg)
291 __IPYTHON__.set_completer_frame(self.curframe)
285 __IPYTHON__.set_completer_frame(self.curframe)
292 do_u = do_up = decorate_fn_with_doc(new_do_up, OldPdb.do_up)
286 do_u = do_up = decorate_fn_with_doc(new_do_up, OldPdb.do_up)
293
287
294 def new_do_down(self, arg):
288 def new_do_down(self, arg):
295 OldPdb.do_down(self, arg)
289 OldPdb.do_down(self, arg)
296 __IPYTHON__.set_completer_frame(self.curframe)
290 __IPYTHON__.set_completer_frame(self.curframe)
297
291
298 do_d = do_down = decorate_fn_with_doc(new_do_down, OldPdb.do_down)
292 do_d = do_down = decorate_fn_with_doc(new_do_down, OldPdb.do_down)
299
293
300 def new_do_frame(self, arg):
294 def new_do_frame(self, arg):
301 OldPdb.do_frame(self, arg)
295 OldPdb.do_frame(self, arg)
302 __IPYTHON__.set_completer_frame(self.curframe)
296 __IPYTHON__.set_completer_frame(self.curframe)
303
297
304 def new_do_quit(self, arg):
298 def new_do_quit(self, arg):
305
299
306 if hasattr(self, 'old_all_completions'):
300 if hasattr(self, 'old_all_completions'):
307 __IPYTHON__.Completer.all_completions=self.old_all_completions
301 __IPYTHON__.Completer.all_completions=self.old_all_completions
308
302
309
303
310 return OldPdb.do_quit(self, arg)
304 return OldPdb.do_quit(self, arg)
311
305
312 do_q = do_quit = decorate_fn_with_doc(new_do_quit, OldPdb.do_quit)
306 do_q = do_quit = decorate_fn_with_doc(new_do_quit, OldPdb.do_quit)
313
307
314 def new_do_restart(self, arg):
308 def new_do_restart(self, arg):
315 """Restart command. In the context of ipython this is exactly the same
309 """Restart command. In the context of ipython this is exactly the same
316 thing as 'quit'."""
310 thing as 'quit'."""
317 self.msg("Restart doesn't make sense here. Using 'quit' instead.")
311 self.msg("Restart doesn't make sense here. Using 'quit' instead.")
318 return self.do_quit(arg)
312 return self.do_quit(arg)
319
313
320 def postloop(self):
314 def postloop(self):
321 __IPYTHON__.set_completer_frame(None)
315 __IPYTHON__.set_completer_frame(None)
322
316
323 def print_stack_trace(self):
317 def print_stack_trace(self):
324 try:
318 try:
325 for frame_lineno in self.stack:
319 for frame_lineno in self.stack:
326 self.print_stack_entry(frame_lineno, context = 5)
320 self.print_stack_entry(frame_lineno, context = 5)
327 except KeyboardInterrupt:
321 except KeyboardInterrupt:
328 pass
322 pass
329
323
330 def print_stack_entry(self,frame_lineno,prompt_prefix='\n-> ',
324 def print_stack_entry(self,frame_lineno,prompt_prefix='\n-> ',
331 context = 3):
325 context = 3):
332 #frame, lineno = frame_lineno
326 #frame, lineno = frame_lineno
333 print >>Term.cout, self.format_stack_entry(frame_lineno, '', context)
327 print >>Term.cout, self.format_stack_entry(frame_lineno, '', context)
334
328
335 # vds: >>
329 # vds: >>
336 frame, lineno = frame_lineno
330 frame, lineno = frame_lineno
337 filename = frame.f_code.co_filename
331 filename = frame.f_code.co_filename
338 __IPYTHON__.hooks.synchronize_with_editor(filename, lineno, 0)
332 __IPYTHON__.hooks.synchronize_with_editor(filename, lineno, 0)
339 # vds: <<
333 # vds: <<
340
334
341 def format_stack_entry(self, frame_lineno, lprefix=': ', context = 3):
335 def format_stack_entry(self, frame_lineno, lprefix=': ', context = 3):
342 import linecache, repr
336 import linecache, repr
343
337
344 ret = []
338 ret = []
345
339
346 Colors = self.color_scheme_table.active_colors
340 Colors = self.color_scheme_table.active_colors
347 ColorsNormal = Colors.Normal
341 ColorsNormal = Colors.Normal
348 tpl_link = '%s%%s%s' % (Colors.filenameEm, ColorsNormal)
342 tpl_link = '%s%%s%s' % (Colors.filenameEm, ColorsNormal)
349 tpl_call = '%s%%s%s%%s%s' % (Colors.vName, Colors.valEm, ColorsNormal)
343 tpl_call = '%s%%s%s%%s%s' % (Colors.vName, Colors.valEm, ColorsNormal)
350 tpl_line = '%%s%s%%s %s%%s' % (Colors.lineno, ColorsNormal)
344 tpl_line = '%%s%s%%s %s%%s' % (Colors.lineno, ColorsNormal)
351 tpl_line_em = '%%s%s%%s %s%%s%s' % (Colors.linenoEm, Colors.line,
345 tpl_line_em = '%%s%s%%s %s%%s%s' % (Colors.linenoEm, Colors.line,
352 ColorsNormal)
346 ColorsNormal)
353
347
354 frame, lineno = frame_lineno
348 frame, lineno = frame_lineno
355
349
356 return_value = ''
350 return_value = ''
357 if '__return__' in frame.f_locals:
351 if '__return__' in frame.f_locals:
358 rv = frame.f_locals['__return__']
352 rv = frame.f_locals['__return__']
359 #return_value += '->'
353 #return_value += '->'
360 return_value += repr.repr(rv) + '\n'
354 return_value += repr.repr(rv) + '\n'
361 ret.append(return_value)
355 ret.append(return_value)
362
356
363 #s = filename + '(' + `lineno` + ')'
357 #s = filename + '(' + `lineno` + ')'
364 filename = self.canonic(frame.f_code.co_filename)
358 filename = self.canonic(frame.f_code.co_filename)
365 link = tpl_link % filename
359 link = tpl_link % filename
366
360
367 if frame.f_code.co_name:
361 if frame.f_code.co_name:
368 func = frame.f_code.co_name
362 func = frame.f_code.co_name
369 else:
363 else:
370 func = "<lambda>"
364 func = "<lambda>"
371
365
372 call = ''
366 call = ''
373 if func != '?':
367 if func != '?':
374 if '__args__' in frame.f_locals:
368 if '__args__' in frame.f_locals:
375 args = repr.repr(frame.f_locals['__args__'])
369 args = repr.repr(frame.f_locals['__args__'])
376 else:
370 else:
377 args = '()'
371 args = '()'
378 call = tpl_call % (func, args)
372 call = tpl_call % (func, args)
379
373
380 # The level info should be generated in the same format pdb uses, to
374 # The level info should be generated in the same format pdb uses, to
381 # avoid breaking the pdbtrack functionality of python-mode in *emacs.
375 # avoid breaking the pdbtrack functionality of python-mode in *emacs.
382 if frame is self.curframe:
376 if frame is self.curframe:
383 ret.append('> ')
377 ret.append('> ')
384 else:
378 else:
385 ret.append(' ')
379 ret.append(' ')
386 ret.append('%s(%s)%s\n' % (link,lineno,call))
380 ret.append('%s(%s)%s\n' % (link,lineno,call))
387
381
388 start = lineno - 1 - context//2
382 start = lineno - 1 - context//2
389 lines = linecache.getlines(filename)
383 lines = linecache.getlines(filename)
390 start = max(start, 0)
384 start = max(start, 0)
391 start = min(start, len(lines) - context)
385 start = min(start, len(lines) - context)
392 lines = lines[start : start + context]
386 lines = lines[start : start + context]
393
387
394 for i,line in enumerate(lines):
388 for i,line in enumerate(lines):
395 show_arrow = (start + 1 + i == lineno)
389 show_arrow = (start + 1 + i == lineno)
396 linetpl = (frame is self.curframe or show_arrow) \
390 linetpl = (frame is self.curframe or show_arrow) \
397 and tpl_line_em \
391 and tpl_line_em \
398 or tpl_line
392 or tpl_line
399 ret.append(self.__format_line(linetpl, filename,
393 ret.append(self.__format_line(linetpl, filename,
400 start + 1 + i, line,
394 start + 1 + i, line,
401 arrow = show_arrow) )
395 arrow = show_arrow) )
402
396
403 return ''.join(ret)
397 return ''.join(ret)
404
398
405 def __format_line(self, tpl_line, filename, lineno, line, arrow = False):
399 def __format_line(self, tpl_line, filename, lineno, line, arrow = False):
406 bp_mark = ""
400 bp_mark = ""
407 bp_mark_color = ""
401 bp_mark_color = ""
408
402
409 scheme = self.color_scheme_table.active_scheme_name
403 scheme = self.color_scheme_table.active_scheme_name
410 new_line, err = self.parser.format2(line, 'str', scheme)
404 new_line, err = self.parser.format2(line, 'str', scheme)
411 if not err: line = new_line
405 if not err: line = new_line
412
406
413 bp = None
407 bp = None
414 if lineno in self.get_file_breaks(filename):
408 if lineno in self.get_file_breaks(filename):
415 bps = self.get_breaks(filename, lineno)
409 bps = self.get_breaks(filename, lineno)
416 bp = bps[-1]
410 bp = bps[-1]
417
411
418 if bp:
412 if bp:
419 Colors = self.color_scheme_table.active_colors
413 Colors = self.color_scheme_table.active_colors
420 bp_mark = str(bp.number)
414 bp_mark = str(bp.number)
421 bp_mark_color = Colors.breakpoint_enabled
415 bp_mark_color = Colors.breakpoint_enabled
422 if not bp.enabled:
416 if not bp.enabled:
423 bp_mark_color = Colors.breakpoint_disabled
417 bp_mark_color = Colors.breakpoint_disabled
424
418
425 numbers_width = 7
419 numbers_width = 7
426 if arrow:
420 if arrow:
427 # This is the line with the error
421 # This is the line with the error
428 pad = numbers_width - len(str(lineno)) - len(bp_mark)
422 pad = numbers_width - len(str(lineno)) - len(bp_mark)
429 if pad >= 3:
423 if pad >= 3:
430 marker = '-'*(pad-3) + '-> '
424 marker = '-'*(pad-3) + '-> '
431 elif pad == 2:
425 elif pad == 2:
432 marker = '> '
426 marker = '> '
433 elif pad == 1:
427 elif pad == 1:
434 marker = '>'
428 marker = '>'
435 else:
429 else:
436 marker = ''
430 marker = ''
437 num = '%s%s' % (marker, str(lineno))
431 num = '%s%s' % (marker, str(lineno))
438 line = tpl_line % (bp_mark_color + bp_mark, num, line)
432 line = tpl_line % (bp_mark_color + bp_mark, num, line)
439 else:
433 else:
440 num = '%*s' % (numbers_width - len(bp_mark), str(lineno))
434 num = '%*s' % (numbers_width - len(bp_mark), str(lineno))
441 line = tpl_line % (bp_mark_color + bp_mark, num, line)
435 line = tpl_line % (bp_mark_color + bp_mark, num, line)
442
436
443 return line
437 return line
444
438
445 def list_command_pydb(self, arg):
439 def list_command_pydb(self, arg):
446 """List command to use if we have a newer pydb installed"""
440 """List command to use if we have a newer pydb installed"""
447 filename, first, last = OldPdb.parse_list_cmd(self, arg)
441 filename, first, last = OldPdb.parse_list_cmd(self, arg)
448 if filename is not None:
442 if filename is not None:
449 self.print_list_lines(filename, first, last)
443 self.print_list_lines(filename, first, last)
450
444
451 def print_list_lines(self, filename, first, last):
445 def print_list_lines(self, filename, first, last):
452 """The printing (as opposed to the parsing part of a 'list'
446 """The printing (as opposed to the parsing part of a 'list'
453 command."""
447 command."""
454 try:
448 try:
455 Colors = self.color_scheme_table.active_colors
449 Colors = self.color_scheme_table.active_colors
456 ColorsNormal = Colors.Normal
450 ColorsNormal = Colors.Normal
457 tpl_line = '%%s%s%%s %s%%s' % (Colors.lineno, ColorsNormal)
451 tpl_line = '%%s%s%%s %s%%s' % (Colors.lineno, ColorsNormal)
458 tpl_line_em = '%%s%s%%s %s%%s%s' % (Colors.linenoEm, Colors.line, ColorsNormal)
452 tpl_line_em = '%%s%s%%s %s%%s%s' % (Colors.linenoEm, Colors.line, ColorsNormal)
459 src = []
453 src = []
460 for lineno in range(first, last+1):
454 for lineno in range(first, last+1):
461 line = linecache.getline(filename, lineno)
455 line = linecache.getline(filename, lineno)
462 if not line:
456 if not line:
463 break
457 break
464
458
465 if lineno == self.curframe.f_lineno:
459 if lineno == self.curframe.f_lineno:
466 line = self.__format_line(tpl_line_em, filename, lineno, line, arrow = True)
460 line = self.__format_line(tpl_line_em, filename, lineno, line, arrow = True)
467 else:
461 else:
468 line = self.__format_line(tpl_line, filename, lineno, line, arrow = False)
462 line = self.__format_line(tpl_line, filename, lineno, line, arrow = False)
469
463
470 src.append(line)
464 src.append(line)
471 self.lineno = lineno
465 self.lineno = lineno
472
466
473 print >>Term.cout, ''.join(src)
467 print >>Term.cout, ''.join(src)
474
468
475 except KeyboardInterrupt:
469 except KeyboardInterrupt:
476 pass
470 pass
477
471
478 def do_list(self, arg):
472 def do_list(self, arg):
479 self.lastcmd = 'list'
473 self.lastcmd = 'list'
480 last = None
474 last = None
481 if arg:
475 if arg:
482 try:
476 try:
483 x = eval(arg, {}, {})
477 x = eval(arg, {}, {})
484 if type(x) == type(()):
478 if type(x) == type(()):
485 first, last = x
479 first, last = x
486 first = int(first)
480 first = int(first)
487 last = int(last)
481 last = int(last)
488 if last < first:
482 if last < first:
489 # Assume it's a count
483 # Assume it's a count
490 last = first + last
484 last = first + last
491 else:
485 else:
492 first = max(1, int(x) - 5)
486 first = max(1, int(x) - 5)
493 except:
487 except:
494 print '*** Error in argument:', `arg`
488 print '*** Error in argument:', `arg`
495 return
489 return
496 elif self.lineno is None:
490 elif self.lineno is None:
497 first = max(1, self.curframe.f_lineno - 5)
491 first = max(1, self.curframe.f_lineno - 5)
498 else:
492 else:
499 first = self.lineno + 1
493 first = self.lineno + 1
500 if last is None:
494 if last is None:
501 last = first + 10
495 last = first + 10
502 self.print_list_lines(self.curframe.f_code.co_filename, first, last)
496 self.print_list_lines(self.curframe.f_code.co_filename, first, last)
503
497
504 # vds: >>
498 # vds: >>
505 lineno = first
499 lineno = first
506 filename = self.curframe.f_code.co_filename
500 filename = self.curframe.f_code.co_filename
507 __IPYTHON__.hooks.synchronize_with_editor(filename, lineno, 0)
501 __IPYTHON__.hooks.synchronize_with_editor(filename, lineno, 0)
508 # vds: <<
502 # vds: <<
509
503
510 do_l = do_list
504 do_l = do_list
511
505
512 def do_pdef(self, arg):
506 def do_pdef(self, arg):
513 """The debugger interface to magic_pdef"""
507 """The debugger interface to magic_pdef"""
514 namespaces = [('Locals', self.curframe.f_locals),
508 namespaces = [('Locals', self.curframe.f_locals),
515 ('Globals', self.curframe.f_globals)]
509 ('Globals', self.curframe.f_globals)]
516 __IPYTHON__.magic_pdef(arg, namespaces=namespaces)
510 __IPYTHON__.magic_pdef(arg, namespaces=namespaces)
517
511
518 def do_pdoc(self, arg):
512 def do_pdoc(self, arg):
519 """The debugger interface to magic_pdoc"""
513 """The debugger interface to magic_pdoc"""
520 namespaces = [('Locals', self.curframe.f_locals),
514 namespaces = [('Locals', self.curframe.f_locals),
521 ('Globals', self.curframe.f_globals)]
515 ('Globals', self.curframe.f_globals)]
522 __IPYTHON__.magic_pdoc(arg, namespaces=namespaces)
516 __IPYTHON__.magic_pdoc(arg, namespaces=namespaces)
523
517
524 def do_pinfo(self, arg):
518 def do_pinfo(self, arg):
525 """The debugger equivalant of ?obj"""
519 """The debugger equivalant of ?obj"""
526 namespaces = [('Locals', self.curframe.f_locals),
520 namespaces = [('Locals', self.curframe.f_locals),
527 ('Globals', self.curframe.f_globals)]
521 ('Globals', self.curframe.f_globals)]
528 __IPYTHON__.magic_pinfo("pinfo %s" % arg, namespaces=namespaces)
522 __IPYTHON__.magic_pinfo("pinfo %s" % arg, namespaces=namespaces)
@@ -1,259 +1,253 b''
1 # -*- coding: utf-8 -*-
1 # -*- coding: utf-8 -*-
2 """Modified input prompt for executing files.
2 """Modified input prompt for executing files.
3
3
4 We define a special input line filter to allow typing lines which begin with
4 We define a special input line filter to allow typing lines which begin with
5 '~', '/' or '.'. If one of those strings is encountered, it is automatically
5 '~', '/' or '.'. If one of those strings is encountered, it is automatically
6 executed.
6 executed.
7
7 """
8 $Id: InterpreterExec.py 2724 2007-09-07 08:05:38Z fperez $"""
9
8
10 #*****************************************************************************
9 #*****************************************************************************
11 # Copyright (C) 2004 W.J. van der Laan <gnufnork@hetdigitalegat.nl>
10 # Copyright (C) 2004 W.J. van der Laan <gnufnork@hetdigitalegat.nl>
12 # Copyright (C) 2004-2006 Fernando Perez <fperez@colorado.edu>
11 # Copyright (C) 2004-2006 Fernando Perez <fperez@colorado.edu>
13 #
12 #
14 # Distributed under the terms of the BSD License. The full license is in
13 # Distributed under the terms of the BSD License. The full license is in
15 # the file COPYING, distributed as part of this software.
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 # TODO: deprecated
17 # TODO: deprecated
24 def prefilter_shell(self,line,continuation):
18 def prefilter_shell(self,line,continuation):
25 """Alternate prefilter, modified for shell-like functionality.
19 """Alternate prefilter, modified for shell-like functionality.
26
20
27 - Execute all lines beginning with '~', '/' or '.'
21 - Execute all lines beginning with '~', '/' or '.'
28 - $var=cmd <=> %sc var=cmd
22 - $var=cmd <=> %sc var=cmd
29 - $$var=cmd <=> %sc -l var=cmd
23 - $$var=cmd <=> %sc -l var=cmd
30 """
24 """
31
25
32 if line:
26 if line:
33 l0 = line[0]
27 l0 = line[0]
34 if l0 in '~/.':
28 if l0 in '~/.':
35 return self._prefilter("!%s"%line,continuation)
29 return self._prefilter("!%s"%line,continuation)
36 elif l0=='$':
30 elif l0=='$':
37 lrest = line[1:]
31 lrest = line[1:]
38 if lrest.startswith('$'):
32 if lrest.startswith('$'):
39 # $$var=cmd <=> %sc -l var=cmd
33 # $$var=cmd <=> %sc -l var=cmd
40 return self._prefilter("%ssc -l %s" % (self.ESC_MAGIC,lrest[1:]),
34 return self._prefilter("%ssc -l %s" % (self.ESC_MAGIC,lrest[1:]),
41 continuation)
35 continuation)
42 else:
36 else:
43 # $var=cmd <=> %sc var=cmd
37 # $var=cmd <=> %sc var=cmd
44 return self._prefilter("%ssc %s" % (self.ESC_MAGIC,lrest),
38 return self._prefilter("%ssc %s" % (self.ESC_MAGIC,lrest),
45 continuation)
39 continuation)
46 else:
40 else:
47 return self._prefilter(line,continuation)
41 return self._prefilter(line,continuation)
48 else:
42 else:
49 return self._prefilter(line,continuation)
43 return self._prefilter(line,continuation)
50
44
51 # Rebind this to be the new IPython prefilter:
45 # Rebind this to be the new IPython prefilter:
52 from IPython.iplib import InteractiveShell
46 from IPython.iplib import InteractiveShell
53 InteractiveShell.prefilter = prefilter_shell
47 InteractiveShell.prefilter = prefilter_shell
54 # Clean up the namespace.
48 # Clean up the namespace.
55 del InteractiveShell,prefilter_shell
49 del InteractiveShell,prefilter_shell
56
50
57 # Provide pysh and further shell-oriented services
51 # Provide pysh and further shell-oriented services
58 import os,sys,shutil
52 import os,sys,shutil
59 from IPython.genutils import system,shell,getoutput,getoutputerror
53 from IPython.genutils import system,shell,getoutput,getoutputerror
60
54
61 # Short aliases for getting shell output as a string and a list
55 # Short aliases for getting shell output as a string and a list
62 sout = getoutput
56 sout = getoutput
63 lout = lambda cmd: getoutput(cmd,split=1)
57 lout = lambda cmd: getoutput(cmd,split=1)
64
58
65 # Empty function, meant as a docstring holder so help(pysh) works.
59 # Empty function, meant as a docstring holder so help(pysh) works.
66 def pysh():
60 def pysh():
67 """Pysh is a set of modules and extensions to IPython which make shell-like
61 """Pysh is a set of modules and extensions to IPython which make shell-like
68 usage with Python syntax more convenient. Keep in mind that pysh is NOT a
62 usage with Python syntax more convenient. Keep in mind that pysh is NOT a
69 full-blown shell, so don't try to make it your /etc/passwd entry!
63 full-blown shell, so don't try to make it your /etc/passwd entry!
70
64
71 In particular, it has no job control, so if you type Ctrl-Z (under Unix),
65 In particular, it has no job control, so if you type Ctrl-Z (under Unix),
72 you'll suspend pysh itself, not the process you just started.
66 you'll suspend pysh itself, not the process you just started.
73
67
74 Since pysh is really nothing but a customized IPython, you should
68 Since pysh is really nothing but a customized IPython, you should
75 familiarize yourself with IPython's features. This brief help mainly
69 familiarize yourself with IPython's features. This brief help mainly
76 documents areas in which pysh differs from the normal IPython.
70 documents areas in which pysh differs from the normal IPython.
77
71
78 ALIASES
72 ALIASES
79 -------
73 -------
80 All of your $PATH has been loaded as IPython aliases, so you should be
74 All of your $PATH has been loaded as IPython aliases, so you should be
81 able to type any normal system command and have it executed. See %alias?
75 able to type any normal system command and have it executed. See %alias?
82 and %unalias? for details on the alias facilities.
76 and %unalias? for details on the alias facilities.
83
77
84 SPECIAL SYNTAX
78 SPECIAL SYNTAX
85 --------------
79 --------------
86 Any lines which begin with '~', '/' and '.' will be executed as shell
80 Any lines which begin with '~', '/' and '.' will be executed as shell
87 commands instead of as Python code. The special escapes below are also
81 commands instead of as Python code. The special escapes below are also
88 recognized. !cmd is valid in single or multi-line input, all others are
82 recognized. !cmd is valid in single or multi-line input, all others are
89 only valid in single-line input:
83 only valid in single-line input:
90
84
91 !cmd - pass 'cmd' directly to the shell
85 !cmd - pass 'cmd' directly to the shell
92 !!cmd - execute 'cmd' and return output as a list (split on '\\n')
86 !!cmd - execute 'cmd' and return output as a list (split on '\\n')
93 $var=cmd - capture output of cmd into var, as a string
87 $var=cmd - capture output of cmd into var, as a string
94 $$var=cmd - capture output of cmd into var, as a list (split on '\\n')
88 $$var=cmd - capture output of cmd into var, as a list (split on '\\n')
95
89
96 The $/$$ syntaxes make Python variables from system output, which you can
90 The $/$$ syntaxes make Python variables from system output, which you can
97 later use for further scripting. The converse is also possible: when
91 later use for further scripting. The converse is also possible: when
98 executing an alias or calling to the system via !/!!, you can expand any
92 executing an alias or calling to the system via !/!!, you can expand any
99 python variable or expression by prepending it with $. Full details of
93 python variable or expression by prepending it with $. Full details of
100 the allowed syntax can be found in Python's PEP 215.
94 the allowed syntax can be found in Python's PEP 215.
101
95
102 A few brief examples will illustrate these:
96 A few brief examples will illustrate these:
103
97
104 fperez[~/test]|3> !ls *s.py
98 fperez[~/test]|3> !ls *s.py
105 scopes.py strings.py
99 scopes.py strings.py
106
100
107 ls is an internal alias, so there's no need to use !:
101 ls is an internal alias, so there's no need to use !:
108 fperez[~/test]|4> ls *s.py
102 fperez[~/test]|4> ls *s.py
109 scopes.py* strings.py
103 scopes.py* strings.py
110
104
111 !!ls will return the output into a Python variable:
105 !!ls will return the output into a Python variable:
112 fperez[~/test]|5> !!ls *s.py
106 fperez[~/test]|5> !!ls *s.py
113 <5> ['scopes.py', 'strings.py']
107 <5> ['scopes.py', 'strings.py']
114 fperez[~/test]|6> print _5
108 fperez[~/test]|6> print _5
115 ['scopes.py', 'strings.py']
109 ['scopes.py', 'strings.py']
116
110
117 $ and $$ allow direct capture to named variables:
111 $ and $$ allow direct capture to named variables:
118 fperez[~/test]|7> $astr = ls *s.py
112 fperez[~/test]|7> $astr = ls *s.py
119 fperez[~/test]|8> astr
113 fperez[~/test]|8> astr
120 <8> 'scopes.py\\nstrings.py'
114 <8> 'scopes.py\\nstrings.py'
121
115
122 fperez[~/test]|9> $$alist = ls *s.py
116 fperez[~/test]|9> $$alist = ls *s.py
123 fperez[~/test]|10> alist
117 fperez[~/test]|10> alist
124 <10> ['scopes.py', 'strings.py']
118 <10> ['scopes.py', 'strings.py']
125
119
126 alist is now a normal python list you can loop over. Using $ will expand
120 alist is now a normal python list you can loop over. Using $ will expand
127 back the python values when alias calls are made:
121 back the python values when alias calls are made:
128 fperez[~/test]|11> for f in alist:
122 fperez[~/test]|11> for f in alist:
129 |..> print 'file',f,
123 |..> print 'file',f,
130 |..> wc -l $f
124 |..> wc -l $f
131 |..>
125 |..>
132 file scopes.py 13 scopes.py
126 file scopes.py 13 scopes.py
133 file strings.py 4 strings.py
127 file strings.py 4 strings.py
134
128
135 Note that you may need to protect your variables with braces if you want
129 Note that you may need to protect your variables with braces if you want
136 to append strings to their names. To copy all files in alist to .bak
130 to append strings to their names. To copy all files in alist to .bak
137 extensions, you must use:
131 extensions, you must use:
138 fperez[~/test]|12> for f in alist:
132 fperez[~/test]|12> for f in alist:
139 |..> cp $f ${f}.bak
133 |..> cp $f ${f}.bak
140
134
141 If you try using $f.bak, you'll get an AttributeError exception saying
135 If you try using $f.bak, you'll get an AttributeError exception saying
142 that your string object doesn't have a .bak attribute. This is because
136 that your string object doesn't have a .bak attribute. This is because
143 the $ expansion mechanism allows you to expand full Python expressions:
137 the $ expansion mechanism allows you to expand full Python expressions:
144 fperez[~/test]|13> echo "sys.platform is: $sys.platform"
138 fperez[~/test]|13> echo "sys.platform is: $sys.platform"
145 sys.platform is: linux2
139 sys.platform is: linux2
146
140
147 IPython's input history handling is still active, which allows you to
141 IPython's input history handling is still active, which allows you to
148 rerun a single block of multi-line input by simply using exec:
142 rerun a single block of multi-line input by simply using exec:
149 fperez[~/test]|14> $$alist = ls *.eps
143 fperez[~/test]|14> $$alist = ls *.eps
150 fperez[~/test]|15> exec _i11
144 fperez[~/test]|15> exec _i11
151 file image2.eps 921 image2.eps
145 file image2.eps 921 image2.eps
152 file image.eps 921 image.eps
146 file image.eps 921 image.eps
153
147
154 While these are new special-case syntaxes, they are designed to allow very
148 While these are new special-case syntaxes, they are designed to allow very
155 efficient use of the shell with minimal typing. At an interactive shell
149 efficient use of the shell with minimal typing. At an interactive shell
156 prompt, conciseness of expression wins over readability.
150 prompt, conciseness of expression wins over readability.
157
151
158 USEFUL FUNCTIONS AND MODULES
152 USEFUL FUNCTIONS AND MODULES
159 ----------------------------
153 ----------------------------
160 The os, sys and shutil modules from the Python standard library are
154 The os, sys and shutil modules from the Python standard library are
161 automatically loaded. Some additional functions, useful for shell usage,
155 automatically loaded. Some additional functions, useful for shell usage,
162 are listed below. You can request more help about them with '?'.
156 are listed below. You can request more help about them with '?'.
163
157
164 shell - execute a command in the underlying system shell
158 shell - execute a command in the underlying system shell
165 system - like shell(), but return the exit status of the command
159 system - like shell(), but return the exit status of the command
166 sout - capture the output of a command as a string
160 sout - capture the output of a command as a string
167 lout - capture the output of a command as a list (split on '\\n')
161 lout - capture the output of a command as a list (split on '\\n')
168 getoutputerror - capture (output,error) of a shell command
162 getoutputerror - capture (output,error) of a shell command
169
163
170 sout/lout are the functional equivalents of $/$$. They are provided to
164 sout/lout are the functional equivalents of $/$$. They are provided to
171 allow you to capture system output in the middle of true python code,
165 allow you to capture system output in the middle of true python code,
172 function definitions, etc (where $ and $$ are invalid).
166 function definitions, etc (where $ and $$ are invalid).
173
167
174 DIRECTORY MANAGEMENT
168 DIRECTORY MANAGEMENT
175 --------------------
169 --------------------
176 Since each command passed by pysh to the underlying system is executed in
170 Since each command passed by pysh to the underlying system is executed in
177 a subshell which exits immediately, you can NOT use !cd to navigate the
171 a subshell which exits immediately, you can NOT use !cd to navigate the
178 filesystem.
172 filesystem.
179
173
180 Pysh provides its own builtin '%cd' magic command to move in the
174 Pysh provides its own builtin '%cd' magic command to move in the
181 filesystem (the % is not required with automagic on). It also maintains a
175 filesystem (the % is not required with automagic on). It also maintains a
182 list of visited directories (use %dhist to see it) and allows direct
176 list of visited directories (use %dhist to see it) and allows direct
183 switching to any of them. Type 'cd?' for more details.
177 switching to any of them. Type 'cd?' for more details.
184
178
185 %pushd, %popd and %dirs are provided for directory stack handling.
179 %pushd, %popd and %dirs are provided for directory stack handling.
186
180
187 PROMPT CUSTOMIZATION
181 PROMPT CUSTOMIZATION
188 --------------------
182 --------------------
189
183
190 The supplied ipythonrc-pysh profile comes with an example of a very
184 The supplied ipythonrc-pysh profile comes with an example of a very
191 colored and detailed prompt, mainly to serve as an illustration. The
185 colored and detailed prompt, mainly to serve as an illustration. The
192 valid escape sequences, besides color names, are:
186 valid escape sequences, besides color names, are:
193
187
194 \\# - Prompt number.
188 \\# - Prompt number.
195 \\D - Dots, as many as there are digits in \\# (so they align).
189 \\D - Dots, as many as there are digits in \\# (so they align).
196 \\w - Current working directory (cwd).
190 \\w - Current working directory (cwd).
197 \\W - Basename of current working directory.
191 \\W - Basename of current working directory.
198 \\XN - Where N=0..5. N terms of the cwd, with $HOME written as ~.
192 \\XN - Where N=0..5. N terms of the cwd, with $HOME written as ~.
199 \\YN - Where N=0..5. Like XN, but if ~ is term N+1 it's also shown.
193 \\YN - Where N=0..5. Like XN, but if ~ is term N+1 it's also shown.
200 \\u - Username.
194 \\u - Username.
201 \\H - Full hostname.
195 \\H - Full hostname.
202 \\h - Hostname up to first '.'
196 \\h - Hostname up to first '.'
203 \\$ - Root symbol ($ or #).
197 \\$ - Root symbol ($ or #).
204 \\t - Current time, in H:M:S format.
198 \\t - Current time, in H:M:S format.
205 \\v - IPython release version.
199 \\v - IPython release version.
206 \\n - Newline.
200 \\n - Newline.
207 \\r - Carriage return.
201 \\r - Carriage return.
208 \\\\ - An explicitly escaped '\\'.
202 \\\\ - An explicitly escaped '\\'.
209
203
210 You can configure your prompt colors using any ANSI color escape. Each
204 You can configure your prompt colors using any ANSI color escape. Each
211 color escape sets the color for any subsequent text, until another escape
205 color escape sets the color for any subsequent text, until another escape
212 comes in and changes things. The valid color escapes are:
206 comes in and changes things. The valid color escapes are:
213
207
214 \\C_Black
208 \\C_Black
215 \\C_Blue
209 \\C_Blue
216 \\C_Brown
210 \\C_Brown
217 \\C_Cyan
211 \\C_Cyan
218 \\C_DarkGray
212 \\C_DarkGray
219 \\C_Green
213 \\C_Green
220 \\C_LightBlue
214 \\C_LightBlue
221 \\C_LightCyan
215 \\C_LightCyan
222 \\C_LightGray
216 \\C_LightGray
223 \\C_LightGreen
217 \\C_LightGreen
224 \\C_LightPurple
218 \\C_LightPurple
225 \\C_LightRed
219 \\C_LightRed
226 \\C_Purple
220 \\C_Purple
227 \\C_Red
221 \\C_Red
228 \\C_White
222 \\C_White
229 \\C_Yellow
223 \\C_Yellow
230 \\C_Normal - Stop coloring, defaults to your terminal settings.
224 \\C_Normal - Stop coloring, defaults to your terminal settings.
231 """
225 """
232 pass
226 pass
233
227
234 # Configure a few things. Much of this is fairly hackish, since IPython
228 # Configure a few things. Much of this is fairly hackish, since IPython
235 # doesn't really expose a clean API for it. Be careful if you start making
229 # doesn't really expose a clean API for it. Be careful if you start making
236 # many modifications here.
230 # many modifications here.
237
231
238
232
239 # Set the 'cd' command to quiet mode, a more shell-like behavior
233 # Set the 'cd' command to quiet mode, a more shell-like behavior
240 __IPYTHON__.default_option('cd','-q')
234 __IPYTHON__.default_option('cd','-q')
241
235
242 # This is redundant, ipy_user_conf.py will determine this
236 # This is redundant, ipy_user_conf.py will determine this
243 # Load all of $PATH as aliases
237 # Load all of $PATH as aliases
244 __IPYTHON__.magic_rehashx()
238 __IPYTHON__.magic_rehashx()
245
239
246 # Remove %sc,%sx if present as aliases
240 # Remove %sc,%sx if present as aliases
247 __IPYTHON__.magic_unalias('sc')
241 __IPYTHON__.magic_unalias('sc')
248 __IPYTHON__.magic_unalias('sx')
242 __IPYTHON__.magic_unalias('sx')
249
243
250 # We need different criteria for line-splitting, so that aliases such as
244 # We need different criteria for line-splitting, so that aliases such as
251 # 'gnome-terminal' are interpreted as a single alias instead of variable
245 # 'gnome-terminal' are interpreted as a single alias instead of variable
252 # 'gnome' minus variable 'terminal'.
246 # 'gnome' minus variable 'terminal'.
253 import re
247 import re
254 __IPYTHON__.line_split = re.compile(r'^([\s*,;/])'
248 __IPYTHON__.line_split = re.compile(r'^([\s*,;/])'
255 r'([\?\w\.\-\+]+\w*\s*)'
249 r'([\?\w\.\-\+]+\w*\s*)'
256 r'(\(?.*$)')
250 r'(\(?.*$)')
257
251
258 # Namespace cleanup
252 # Namespace cleanup
259 del re
253 del re
@@ -1,66 +1,63 b''
1 # -*- coding: utf-8 -*-
1 # -*- coding: utf-8 -*-
2 """ IPython extension: new prefilters for output grabbing
2 """ IPython extension: new prefilters for output grabbing
3
3
4 Provides
4 Provides
5
5
6 var = %magic blah blah
6 var = %magic blah blah
7
7
8 var = !ls
8 var = !ls
9
10 $Id: genutils.py 1077 2006-01-24 18:15:27Z vivainio $
11
12 """
9 """
13
10
14 import IPython.ipapi
11 import IPython.ipapi
15 from IPython.genutils import *
12 from IPython.genutils import *
16
13
17 ip = IPython.ipapi.get()
14 ip = IPython.ipapi.get()
18
15
19 import re
16 import re
20
17
21 def hnd_magic(line,mo):
18 def hnd_magic(line,mo):
22 """ Handle a = %mymagic blah blah """
19 """ Handle a = %mymagic blah blah """
23 #cmd = genutils.make_quoted_expr(mo.group('syscmd'))
20 #cmd = genutils.make_quoted_expr(mo.group('syscmd'))
24 #mag = 'ipmagic
21 #mag = 'ipmagic
25 #return "%s = %s"
22 #return "%s = %s"
26 var = mo.group('varname')
23 var = mo.group('varname')
27 cmd = mo.group('cmd')
24 cmd = mo.group('cmd')
28 expr = make_quoted_expr(cmd)
25 expr = make_quoted_expr(cmd)
29 return itpl('$var = _ip.magic($expr)')
26 return itpl('$var = _ip.magic($expr)')
30
27
31 def hnd_syscmd(line,mo):
28 def hnd_syscmd(line,mo):
32 """ Handle a = !ls """
29 """ Handle a = !ls """
33 #cmd = genutils.make_quoted_expr(mo.group('syscmd'))
30 #cmd = genutils.make_quoted_expr(mo.group('syscmd'))
34 #mag = 'ipmagic
31 #mag = 'ipmagic
35 #return "%s = %s"
32 #return "%s = %s"
36 var = mo.group('varname')
33 var = mo.group('varname')
37 cmd = mo.group('cmd')
34 cmd = mo.group('cmd')
38 expr = make_quoted_expr(itpl("sc -l =$cmd"))
35 expr = make_quoted_expr(itpl("sc -l =$cmd"))
39 return itpl('$var = _ip.magic($expr)')
36 return itpl('$var = _ip.magic($expr)')
40
37
41 def install_re_handler(pat, hnd):
38 def install_re_handler(pat, hnd):
42 ip.meta.re_prefilters.append((re.compile(pat), hnd))
39 ip.meta.re_prefilters.append((re.compile(pat), hnd))
43
40
44 def init_handlers():
41 def init_handlers():
45
42
46 ip.meta.re_prefilters = []
43 ip.meta.re_prefilters = []
47
44
48 install_re_handler('(?P<varname>[\w\.]+)\s*=\s*%(?P<cmd>.*)',
45 install_re_handler('(?P<varname>[\w\.]+)\s*=\s*%(?P<cmd>.*)',
49 hnd_magic
46 hnd_magic
50 )
47 )
51
48
52 install_re_handler('(?P<varname>[\w\.]+)\s*=\s*!(?P<cmd>.*)',
49 install_re_handler('(?P<varname>[\w\.]+)\s*=\s*!(?P<cmd>.*)',
53 hnd_syscmd
50 hnd_syscmd
54 )
51 )
55
52
56 init_handlers()
53 init_handlers()
57
54
58 def regex_prefilter_f(self,line):
55 def regex_prefilter_f(self,line):
59 for pat, handler in ip.meta.re_prefilters:
56 for pat, handler in ip.meta.re_prefilters:
60 mo = pat.match(line)
57 mo = pat.match(line)
61 if mo:
58 if mo:
62 return handler(line,mo)
59 return handler(line,mo)
63
60
64 raise IPython.ipapi.TryNext
61 raise IPython.ipapi.TryNext
65
62
66 ip.set_hook('input_prefilter', regex_prefilter_f)
63 ip.set_hook('input_prefilter', regex_prefilter_f)
@@ -1,184 +1,182 b''
1 # -*- coding: utf-8 -*-
1 # -*- coding: utf-8 -*-
2 """
2 """
3 %store magic for lightweight persistence.
3 %store magic for lightweight persistence.
4
4
5 Stores variables, aliases etc. in PickleShare database.
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 import IPython.ipapi
8 import IPython.ipapi
11 from IPython.ipapi import UsageError
9 from IPython.ipapi import UsageError
12 ip = IPython.ipapi.get()
10 ip = IPython.ipapi.get()
13
11
14 import pickleshare
12 import pickleshare
15
13
16 import inspect,pickle,os,sys,textwrap
14 import inspect,pickle,os,sys,textwrap
17 from IPython.FakeModule import FakeModule
15 from IPython.FakeModule import FakeModule
18
16
19 def restore_aliases(self):
17 def restore_aliases(self):
20 ip = self.getapi()
18 ip = self.getapi()
21 staliases = ip.db.get('stored_aliases', {})
19 staliases = ip.db.get('stored_aliases', {})
22 for k,v in staliases.items():
20 for k,v in staliases.items():
23 #print "restore alias",k,v # dbg
21 #print "restore alias",k,v # dbg
24 #self.alias_table[k] = v
22 #self.alias_table[k] = v
25 ip.defalias(k,v)
23 ip.defalias(k,v)
26
24
27
25
28 def refresh_variables(ip):
26 def refresh_variables(ip):
29 db = ip.db
27 db = ip.db
30 for key in db.keys('autorestore/*'):
28 for key in db.keys('autorestore/*'):
31 # strip autorestore
29 # strip autorestore
32 justkey = os.path.basename(key)
30 justkey = os.path.basename(key)
33 try:
31 try:
34 obj = db[key]
32 obj = db[key]
35 except KeyError:
33 except KeyError:
36 print "Unable to restore variable '%s', ignoring (use %%store -d to forget!)" % justkey
34 print "Unable to restore variable '%s', ignoring (use %%store -d to forget!)" % justkey
37 print "The error was:",sys.exc_info()[0]
35 print "The error was:",sys.exc_info()[0]
38 else:
36 else:
39 #print "restored",justkey,"=",obj #dbg
37 #print "restored",justkey,"=",obj #dbg
40 ip.user_ns[justkey] = obj
38 ip.user_ns[justkey] = obj
41
39
42
40
43 def restore_dhist(ip):
41 def restore_dhist(ip):
44 db = ip.db
42 db = ip.db
45 ip.user_ns['_dh'] = db.get('dhist',[])
43 ip.user_ns['_dh'] = db.get('dhist',[])
46
44
47 def restore_data(self):
45 def restore_data(self):
48 ip = self.getapi()
46 ip = self.getapi()
49 refresh_variables(ip)
47 refresh_variables(ip)
50 restore_aliases(self)
48 restore_aliases(self)
51 restore_dhist(self)
49 restore_dhist(self)
52 raise IPython.ipapi.TryNext
50 raise IPython.ipapi.TryNext
53
51
54 ip.set_hook('late_startup_hook', restore_data)
52 ip.set_hook('late_startup_hook', restore_data)
55
53
56 def magic_store(self, parameter_s=''):
54 def magic_store(self, parameter_s=''):
57 """Lightweight persistence for python variables.
55 """Lightweight persistence for python variables.
58
56
59 Example:
57 Example:
60
58
61 ville@badger[~]|1> A = ['hello',10,'world']\\
59 ville@badger[~]|1> A = ['hello',10,'world']\\
62 ville@badger[~]|2> %store A\\
60 ville@badger[~]|2> %store A\\
63 ville@badger[~]|3> Exit
61 ville@badger[~]|3> Exit
64
62
65 (IPython session is closed and started again...)
63 (IPython session is closed and started again...)
66
64
67 ville@badger:~$ ipython -p pysh\\
65 ville@badger:~$ ipython -p pysh\\
68 ville@badger[~]|1> print A
66 ville@badger[~]|1> print A
69
67
70 ['hello', 10, 'world']
68 ['hello', 10, 'world']
71
69
72 Usage:
70 Usage:
73
71
74 %store - Show list of all variables and their current values\\
72 %store - Show list of all variables and their current values\\
75 %store <var> - Store the *current* value of the variable to disk\\
73 %store <var> - Store the *current* value of the variable to disk\\
76 %store -d <var> - Remove the variable and its value from storage\\
74 %store -d <var> - Remove the variable and its value from storage\\
77 %store -z - Remove all variables from storage\\
75 %store -z - Remove all variables from storage\\
78 %store -r - Refresh all variables from store (delete current vals)\\
76 %store -r - Refresh all variables from store (delete current vals)\\
79 %store foo >a.txt - Store value of foo to new file a.txt\\
77 %store foo >a.txt - Store value of foo to new file a.txt\\
80 %store foo >>a.txt - Append value of foo to file a.txt\\
78 %store foo >>a.txt - Append value of foo to file a.txt\\
81
79
82 It should be noted that if you change the value of a variable, you
80 It should be noted that if you change the value of a variable, you
83 need to %store it again if you want to persist the new value.
81 need to %store it again if you want to persist the new value.
84
82
85 Note also that the variables will need to be pickleable; most basic
83 Note also that the variables will need to be pickleable; most basic
86 python types can be safely %stored.
84 python types can be safely %stored.
87
85
88 Also aliases can be %store'd across sessions.
86 Also aliases can be %store'd across sessions.
89 """
87 """
90
88
91 opts,argsl = self.parse_options(parameter_s,'drz',mode='string')
89 opts,argsl = self.parse_options(parameter_s,'drz',mode='string')
92 args = argsl.split(None,1)
90 args = argsl.split(None,1)
93 ip = self.getapi()
91 ip = self.getapi()
94 db = ip.db
92 db = ip.db
95 # delete
93 # delete
96 if opts.has_key('d'):
94 if opts.has_key('d'):
97 try:
95 try:
98 todel = args[0]
96 todel = args[0]
99 except IndexError:
97 except IndexError:
100 raise UsageError('You must provide the variable to forget')
98 raise UsageError('You must provide the variable to forget')
101 else:
99 else:
102 try:
100 try:
103 del db['autorestore/' + todel]
101 del db['autorestore/' + todel]
104 except:
102 except:
105 raise UsageError("Can't delete variable '%s'" % todel)
103 raise UsageError("Can't delete variable '%s'" % todel)
106 # reset
104 # reset
107 elif opts.has_key('z'):
105 elif opts.has_key('z'):
108 for k in db.keys('autorestore/*'):
106 for k in db.keys('autorestore/*'):
109 del db[k]
107 del db[k]
110
108
111 elif opts.has_key('r'):
109 elif opts.has_key('r'):
112 refresh_variables(ip)
110 refresh_variables(ip)
113
111
114
112
115 # run without arguments -> list variables & values
113 # run without arguments -> list variables & values
116 elif not args:
114 elif not args:
117 vars = self.db.keys('autorestore/*')
115 vars = self.db.keys('autorestore/*')
118 vars.sort()
116 vars.sort()
119 if vars:
117 if vars:
120 size = max(map(len,vars))
118 size = max(map(len,vars))
121 else:
119 else:
122 size = 0
120 size = 0
123
121
124 print 'Stored variables and their in-db values:'
122 print 'Stored variables and their in-db values:'
125 fmt = '%-'+str(size)+'s -> %s'
123 fmt = '%-'+str(size)+'s -> %s'
126 get = db.get
124 get = db.get
127 for var in vars:
125 for var in vars:
128 justkey = os.path.basename(var)
126 justkey = os.path.basename(var)
129 # print 30 first characters from every var
127 # print 30 first characters from every var
130 print fmt % (justkey,repr(get(var,'<unavailable>'))[:50])
128 print fmt % (justkey,repr(get(var,'<unavailable>'))[:50])
131
129
132 # default action - store the variable
130 # default action - store the variable
133 else:
131 else:
134 # %store foo >file.txt or >>file.txt
132 # %store foo >file.txt or >>file.txt
135 if len(args) > 1 and args[1].startswith('>'):
133 if len(args) > 1 and args[1].startswith('>'):
136 fnam = os.path.expanduser(args[1].lstrip('>').lstrip())
134 fnam = os.path.expanduser(args[1].lstrip('>').lstrip())
137 if args[1].startswith('>>'):
135 if args[1].startswith('>>'):
138 fil = open(fnam,'a')
136 fil = open(fnam,'a')
139 else:
137 else:
140 fil = open(fnam,'w')
138 fil = open(fnam,'w')
141 obj = ip.ev(args[0])
139 obj = ip.ev(args[0])
142 print "Writing '%s' (%s) to file '%s'." % (args[0],
140 print "Writing '%s' (%s) to file '%s'." % (args[0],
143 obj.__class__.__name__, fnam)
141 obj.__class__.__name__, fnam)
144
142
145
143
146 if not isinstance (obj,basestring):
144 if not isinstance (obj,basestring):
147 from pprint import pprint
145 from pprint import pprint
148 pprint(obj,fil)
146 pprint(obj,fil)
149 else:
147 else:
150 fil.write(obj)
148 fil.write(obj)
151 if not obj.endswith('\n'):
149 if not obj.endswith('\n'):
152 fil.write('\n')
150 fil.write('\n')
153
151
154 fil.close()
152 fil.close()
155 return
153 return
156
154
157 # %store foo
155 # %store foo
158 try:
156 try:
159 obj = ip.user_ns[args[0]]
157 obj = ip.user_ns[args[0]]
160 except KeyError:
158 except KeyError:
161 # it might be an alias
159 # it might be an alias
162 if args[0] in self.alias_table:
160 if args[0] in self.alias_table:
163 staliases = db.get('stored_aliases',{})
161 staliases = db.get('stored_aliases',{})
164 staliases[ args[0] ] = self.alias_table[ args[0] ]
162 staliases[ args[0] ] = self.alias_table[ args[0] ]
165 db['stored_aliases'] = staliases
163 db['stored_aliases'] = staliases
166 print "Alias stored:", args[0], self.alias_table[ args[0] ]
164 print "Alias stored:", args[0], self.alias_table[ args[0] ]
167 return
165 return
168 else:
166 else:
169 raise UsageError("Unknown variable '%s'" % args[0])
167 raise UsageError("Unknown variable '%s'" % args[0])
170
168
171 else:
169 else:
172 if isinstance(inspect.getmodule(obj), FakeModule):
170 if isinstance(inspect.getmodule(obj), FakeModule):
173 print textwrap.dedent("""\
171 print textwrap.dedent("""\
174 Warning:%s is %s
172 Warning:%s is %s
175 Proper storage of interactively declared classes (or instances
173 Proper storage of interactively declared classes (or instances
176 of those classes) is not possible! Only instances
174 of those classes) is not possible! Only instances
177 of classes in real modules on file system can be %%store'd.
175 of classes in real modules on file system can be %%store'd.
178 """ % (args[0], obj) )
176 """ % (args[0], obj) )
179 return
177 return
180 #pickled = pickle.dumps(obj)
178 #pickled = pickle.dumps(obj)
181 self.db[ 'autorestore/' + args[0] ] = obj
179 self.db[ 'autorestore/' + args[0] ] = obj
182 print "Stored '%s' (%s)" % (args[0], obj.__class__.__name__)
180 print "Stored '%s' (%s)" % (args[0], obj.__class__.__name__)
183
181
184 ip.expose_magic('store',magic_store)
182 ip.expose_magic('store',magic_store)
@@ -1,43 +1,42 b''
1 # -*- coding: utf-8 -*-
1 # -*- coding: utf-8 -*-
2 """
2 """
3 Class which mimics a module.
3 Class which mimics a module.
4
4
5 Needed to allow pickle to correctly resolve namespaces during IPython
5 Needed to allow pickle to correctly resolve namespaces during IPython
6 sessions.
6 sessions.
7
7 """
8 $Id: FakeModule.py 2754 2007-09-09 10:16:59Z fperez $"""
9
8
10 #*****************************************************************************
9 #*****************************************************************************
11 # Copyright (C) 2002-2004 Fernando Perez. <fperez@colorado.edu>
10 # Copyright (C) 2002-2004 Fernando Perez. <fperez@colorado.edu>
12 #
11 #
13 # Distributed under the terms of the BSD License. The full license is in
12 # Distributed under the terms of the BSD License. The full license is in
14 # the file COPYING, distributed as part of this software.
13 # the file COPYING, distributed as part of this software.
15 #*****************************************************************************
14 #*****************************************************************************
16
15
17 import types
16 import types
18
17
19 class FakeModule(types.ModuleType):
18 class FakeModule(types.ModuleType):
20 """Simple class with attribute access to fake a module.
19 """Simple class with attribute access to fake a module.
21
20
22 This is not meant to replace a module, but to allow inserting a fake
21 This is not meant to replace a module, but to allow inserting a fake
23 module in sys.modules so that systems which rely on run-time module
22 module in sys.modules so that systems which rely on run-time module
24 importing (like shelve and pickle) work correctly in interactive IPython
23 importing (like shelve and pickle) work correctly in interactive IPython
25 sessions.
24 sessions.
26
25
27 Do NOT use this code for anything other than this IPython private hack."""
26 Do NOT use this code for anything other than this IPython private hack."""
28
27
29 def __init__(self,adict=None):
28 def __init__(self,adict=None):
30
29
31 # tmp to force __dict__ instance creation, else self.__dict__ fails
30 # tmp to force __dict__ instance creation, else self.__dict__ fails
32 self.__iptmp = None
31 self.__iptmp = None
33
32
34 # It seems pydoc (and perhaps others) needs any module instance to
33 # It seems pydoc (and perhaps others) needs any module instance to
35 # implement a __nonzero__ method, so we add it if missing:
34 # implement a __nonzero__ method, so we add it if missing:
36 self.__dict__.setdefault('__nonzero__',lambda : True)
35 self.__dict__.setdefault('__nonzero__',lambda : True)
37 self.__dict__.setdefault('__file__',__file__)
36 self.__dict__.setdefault('__file__',__file__)
38
37
39 # cleanup our temp trick
38 # cleanup our temp trick
40 del self.__iptmp
39 del self.__iptmp
41
40
42 if adict is not None:
41 if adict is not None:
43 self.__dict__.update(adict)
42 self.__dict__.update(adict)
@@ -1,666 +1,665 b''
1 # -*- coding: utf-8 -*-
1 # -*- coding: utf-8 -*-
2 """Improved replacement for the Gnuplot.Gnuplot class.
2 """Improved replacement for the Gnuplot.Gnuplot class.
3
3
4 This module imports Gnuplot and replaces some of its functionality with
4 This module imports Gnuplot and replaces some of its functionality with
5 improved versions. They add better handling of arrays for plotting and more
5 improved versions. They add better handling of arrays for plotting and more
6 convenient PostScript generation, plus some fixes for hardcopy().
6 convenient PostScript generation, plus some fixes for hardcopy().
7
7
8 It also adds a convenient plot2 method for plotting dictionaries and
8 It also adds a convenient plot2 method for plotting dictionaries and
9 lists/tuples of arrays.
9 lists/tuples of arrays.
10
10
11 This module is meant to be used as a drop-in replacement to the original
11 This module is meant to be used as a drop-in replacement to the original
12 Gnuplot, so it should be safe to do:
12 Gnuplot, so it should be safe to do:
13
13
14 import IPython.Gnuplot2 as Gnuplot
14 import IPython.Gnuplot2 as Gnuplot
15
15 """
16 $Id: Gnuplot2.py 1210 2006-03-13 01:19:31Z fperez $"""
17
16
18 import cStringIO
17 import cStringIO
19 import os
18 import os
20 import string
19 import string
21 import sys
20 import sys
22 import tempfile
21 import tempfile
23 import time
22 import time
24 import types
23 import types
25
24
26 import Gnuplot as Gnuplot_ori
25 import Gnuplot as Gnuplot_ori
27 import Numeric
26 import Numeric
28
27
29 from IPython.genutils import popkey,xsys
28 from IPython.genutils import popkey,xsys
30
29
31 # needed by hardcopy():
30 # needed by hardcopy():
32 gp = Gnuplot_ori.gp
31 gp = Gnuplot_ori.gp
33
32
34 # Patch for Gnuplot.py 1.6 compatibility.
33 # Patch for Gnuplot.py 1.6 compatibility.
35 # Thanks to Hayden Callow <h.callow@elec.canterbury.ac.nz>
34 # Thanks to Hayden Callow <h.callow@elec.canterbury.ac.nz>
36 try:
35 try:
37 OptionException = Gnuplot_ori.PlotItems.OptionException
36 OptionException = Gnuplot_ori.PlotItems.OptionException
38 except AttributeError:
37 except AttributeError:
39 OptionException = Gnuplot_ori.Errors.OptionError
38 OptionException = Gnuplot_ori.Errors.OptionError
40
39
41 # exhibit a similar interface to Gnuplot so it can be somewhat drop-in
40 # exhibit a similar interface to Gnuplot so it can be somewhat drop-in
42 Data = Gnuplot_ori.Data
41 Data = Gnuplot_ori.Data
43 Func = Gnuplot_ori.Func
42 Func = Gnuplot_ori.Func
44 GridData = Gnuplot_ori.GridData
43 GridData = Gnuplot_ori.GridData
45 PlotItem = Gnuplot_ori.PlotItem
44 PlotItem = Gnuplot_ori.PlotItem
46 PlotItems = Gnuplot_ori.PlotItems
45 PlotItems = Gnuplot_ori.PlotItems
47
46
48 # Modify some of Gnuplot's functions with improved versions (or bugfixed, in
47 # Modify some of Gnuplot's functions with improved versions (or bugfixed, in
49 # hardcopy's case). In order to preserve the docstrings at runtime, I've
48 # hardcopy's case). In order to preserve the docstrings at runtime, I've
50 # copied them from the original code.
49 # copied them from the original code.
51
50
52 # After some significant changes in v 1.7 of Gnuplot.py, we need to do a bit
51 # After some significant changes in v 1.7 of Gnuplot.py, we need to do a bit
53 # of version checking.
52 # of version checking.
54
53
55 if Gnuplot_ori.__version__ <= '1.6':
54 if Gnuplot_ori.__version__ <= '1.6':
56 _BaseFileItem = PlotItems.File
55 _BaseFileItem = PlotItems.File
57 _BaseTempFileItem = PlotItems.TempFile
56 _BaseTempFileItem = PlotItems.TempFile
58
57
59 # Fix the File class to add the 'index' option for Gnuplot versions < 1.7
58 # Fix the File class to add the 'index' option for Gnuplot versions < 1.7
60 class File(_BaseFileItem):
59 class File(_BaseFileItem):
61
60
62 _option_list = _BaseFileItem._option_list.copy()
61 _option_list = _BaseFileItem._option_list.copy()
63 _option_list.update({
62 _option_list.update({
64 'index' : lambda self, index: self.set_option_index(index),
63 'index' : lambda self, index: self.set_option_index(index),
65 })
64 })
66
65
67 # A new initializer is needed b/c we want to add a modified
66 # A new initializer is needed b/c we want to add a modified
68 # _option_sequence list which includes 'index' in the right place.
67 # _option_sequence list which includes 'index' in the right place.
69 def __init__(self,*args,**kw):
68 def __init__(self,*args,**kw):
70 self._option_sequence = ['binary', 'index', 'using', 'smooth', 'axes',
69 self._option_sequence = ['binary', 'index', 'using', 'smooth', 'axes',
71 'title', 'with']
70 'title', 'with']
72
71
73 _BaseFileItem.__init__(self,*args,**kw)
72 _BaseFileItem.__init__(self,*args,**kw)
74
73
75 # Let's fix the constructor docstring
74 # Let's fix the constructor docstring
76 __newdoc = \
75 __newdoc = \
77 """Additional Keyword arguments added by IPython:
76 """Additional Keyword arguments added by IPython:
78
77
79 'index=<int>' -- similar to the `index` keyword in Gnuplot.
78 'index=<int>' -- similar to the `index` keyword in Gnuplot.
80 This allows only some of the datasets in a file to be
79 This allows only some of the datasets in a file to be
81 plotted. Datasets within a file are assumed to be separated
80 plotted. Datasets within a file are assumed to be separated
82 by _pairs_ of blank lines, and the first one is numbered as
81 by _pairs_ of blank lines, and the first one is numbered as
83 0 (similar to C/Python usage)."""
82 0 (similar to C/Python usage)."""
84 __init__.__doc__ = PlotItems.File.__init__.__doc__ + __newdoc
83 __init__.__doc__ = PlotItems.File.__init__.__doc__ + __newdoc
85
84
86 def set_option_index(self, index):
85 def set_option_index(self, index):
87 if index is None:
86 if index is None:
88 self.clear_option('index')
87 self.clear_option('index')
89 elif type(index) in [type(''), type(1)]:
88 elif type(index) in [type(''), type(1)]:
90 self._options['index'] = (index, 'index %s' % index)
89 self._options['index'] = (index, 'index %s' % index)
91 elif type(index) is type(()):
90 elif type(index) is type(()):
92 self._options['index'] = (index,'index %s' %
91 self._options['index'] = (index,'index %s' %
93 string.join(map(repr, index), ':'))
92 string.join(map(repr, index), ':'))
94 else:
93 else:
95 raise OptionException('index=%s' % (index,))
94 raise OptionException('index=%s' % (index,))
96
95
97 # We need a FileClass with a different name from 'File', which is a
96 # We need a FileClass with a different name from 'File', which is a
98 # factory function in 1.7, so that our String class can subclass FileClass
97 # factory function in 1.7, so that our String class can subclass FileClass
99 # in any version.
98 # in any version.
100 _FileClass = File
99 _FileClass = File
101
100
102 elif Gnuplot_ori.__version__ =='1.7':
101 elif Gnuplot_ori.__version__ =='1.7':
103 _FileClass = _BaseFileItem = PlotItems._FileItem
102 _FileClass = _BaseFileItem = PlotItems._FileItem
104 _BaseTempFileItem = PlotItems._TempFileItem
103 _BaseTempFileItem = PlotItems._TempFileItem
105 File = PlotItems.File
104 File = PlotItems.File
106
105
107 else: # changes in the newer version (svn as of March'06)
106 else: # changes in the newer version (svn as of March'06)
108 _FileClass = _BaseFileItem = PlotItems._FileItem
107 _FileClass = _BaseFileItem = PlotItems._FileItem
109 _BaseTempFileItem = PlotItems._NewFileItem
108 _BaseTempFileItem = PlotItems._NewFileItem
110 File = PlotItems.File
109 File = PlotItems.File
111
110
112
111
113 # Now, we can add our generic code which is version independent
112 # Now, we can add our generic code which is version independent
114
113
115 # First some useful utilities
114 # First some useful utilities
116 def eps_fix_bbox(fname):
115 def eps_fix_bbox(fname):
117 """Fix the bounding box of an eps file by running ps2eps on it.
116 """Fix the bounding box of an eps file by running ps2eps on it.
118
117
119 If its name ends in .eps, the original file is removed.
118 If its name ends in .eps, the original file is removed.
120
119
121 This is particularly useful for plots made by Gnuplot with square aspect
120 This is particularly useful for plots made by Gnuplot with square aspect
122 ratio: there is a bug in Gnuplot which makes it generate a bounding box
121 ratio: there is a bug in Gnuplot which makes it generate a bounding box
123 which is far wider than the actual plot.
122 which is far wider than the actual plot.
124
123
125 This function assumes that ps2eps is installed in your system."""
124 This function assumes that ps2eps is installed in your system."""
126
125
127 # note: ps2ps and eps2eps do NOT work, ONLY ps2eps works correctly. The
126 # note: ps2ps and eps2eps do NOT work, ONLY ps2eps works correctly. The
128 # others make output with bitmapped fonts, which looks horrible.
127 # others make output with bitmapped fonts, which looks horrible.
129 print 'Fixing eps file: <%s>' % fname
128 print 'Fixing eps file: <%s>' % fname
130 xsys('ps2eps -f -q -l %s' % fname)
129 xsys('ps2eps -f -q -l %s' % fname)
131 if fname.endswith('.eps'):
130 if fname.endswith('.eps'):
132 os.rename(fname+'.eps',fname)
131 os.rename(fname+'.eps',fname)
133
132
134 def is_list1d(x,containers = [types.ListType,types.TupleType]):
133 def is_list1d(x,containers = [types.ListType,types.TupleType]):
135 """Returns true if x appears to be a 1d list/tuple/array.
134 """Returns true if x appears to be a 1d list/tuple/array.
136
135
137 The heuristics are: identify Numeric arrays, or lists/tuples whose first
136 The heuristics are: identify Numeric arrays, or lists/tuples whose first
138 element is not itself a list/tuple. This way zipped lists should work like
137 element is not itself a list/tuple. This way zipped lists should work like
139 the original Gnuplot. There's no inexpensive way to know if a list doesn't
138 the original Gnuplot. There's no inexpensive way to know if a list doesn't
140 have a composite object after its first element, so that kind of input
139 have a composite object after its first element, so that kind of input
141 will produce an error. But it should work well in most cases.
140 will produce an error. But it should work well in most cases.
142 """
141 """
143 x_type = type(x)
142 x_type = type(x)
144
143
145 return x_type == Numeric.ArrayType and len(x.shape)==1 or \
144 return x_type == Numeric.ArrayType and len(x.shape)==1 or \
146 (x_type in containers and
145 (x_type in containers and
147 type(x[0]) not in containers + [Numeric.ArrayType])
146 type(x[0]) not in containers + [Numeric.ArrayType])
148
147
149 def zip_items(items,titles=None):
148 def zip_items(items,titles=None):
150 """zip together neighboring 1-d arrays, and zip standalone ones
149 """zip together neighboring 1-d arrays, and zip standalone ones
151 with their index. Leave other plot items alone."""
150 with their index. Leave other plot items alone."""
152
151
153 class StandaloneItem(Exception): pass
152 class StandaloneItem(Exception): pass
154
153
155 def get_titles(titles):
154 def get_titles(titles):
156 """Return the next title and the input titles array.
155 """Return the next title and the input titles array.
157
156
158 The input array may be changed to None when no titles are left to
157 The input array may be changed to None when no titles are left to
159 prevent extra unnecessary calls to this function."""
158 prevent extra unnecessary calls to this function."""
160
159
161 try:
160 try:
162 title = titles[tit_ct[0]] # tit_ct[0] is in zip_items'scope
161 title = titles[tit_ct[0]] # tit_ct[0] is in zip_items'scope
163 except IndexError:
162 except IndexError:
164 titles = None # so we don't enter again
163 titles = None # so we don't enter again
165 title = None
164 title = None
166 else:
165 else:
167 tit_ct[0] += 1
166 tit_ct[0] += 1
168 return title,titles
167 return title,titles
169
168
170 new_items = []
169 new_items = []
171
170
172 if titles:
171 if titles:
173 # Initialize counter. It was put in a list as a hack to allow the
172 # Initialize counter. It was put in a list as a hack to allow the
174 # nested get_titles to modify it without raising a NameError.
173 # nested get_titles to modify it without raising a NameError.
175 tit_ct = [0]
174 tit_ct = [0]
176
175
177 n = 0 # this loop needs to be done by hand
176 n = 0 # this loop needs to be done by hand
178 while n < len(items):
177 while n < len(items):
179 item = items[n]
178 item = items[n]
180 try:
179 try:
181 if is_list1d(item):
180 if is_list1d(item):
182 if n==len(items)-1: # last in list
181 if n==len(items)-1: # last in list
183 raise StandaloneItem
182 raise StandaloneItem
184 else: # check the next item and zip together if needed
183 else: # check the next item and zip together if needed
185 next_item = items[n+1]
184 next_item = items[n+1]
186 if next_item is None:
185 if next_item is None:
187 n += 1
186 n += 1
188 raise StandaloneItem
187 raise StandaloneItem
189 elif is_list1d(next_item):
188 elif is_list1d(next_item):
190 # this would be best done with an iterator
189 # this would be best done with an iterator
191 if titles:
190 if titles:
192 title,titles = get_titles(titles)
191 title,titles = get_titles(titles)
193 else:
192 else:
194 title = None
193 title = None
195 new_items.append(Data(zip(item,next_item),
194 new_items.append(Data(zip(item,next_item),
196 title=title))
195 title=title))
197 n += 1 # avoid double-inclusion of next item
196 n += 1 # avoid double-inclusion of next item
198 else: # can't zip with next, zip with own index list
197 else: # can't zip with next, zip with own index list
199 raise StandaloneItem
198 raise StandaloneItem
200 else: # not 1-d array
199 else: # not 1-d array
201 new_items.append(item)
200 new_items.append(item)
202 except StandaloneItem:
201 except StandaloneItem:
203 if titles:
202 if titles:
204 title,titles = get_titles(titles)
203 title,titles = get_titles(titles)
205 else:
204 else:
206 title = None
205 title = None
207 new_items.append(Data(zip(range(len(item)),item),title=title))
206 new_items.append(Data(zip(range(len(item)),item),title=title))
208 except AttributeError:
207 except AttributeError:
209 new_items.append(item)
208 new_items.append(item)
210 n+=1
209 n+=1
211
210
212 return new_items
211 return new_items
213
212
214 # And some classes with enhanced functionality.
213 # And some classes with enhanced functionality.
215 class String(_FileClass):
214 class String(_FileClass):
216 """Make a PlotItem from data in a string with the same format as a File.
215 """Make a PlotItem from data in a string with the same format as a File.
217
216
218 This allows writing data directly inside python scripts using the exact
217 This allows writing data directly inside python scripts using the exact
219 same format and manipulation options which would be used for external
218 same format and manipulation options which would be used for external
220 files."""
219 files."""
221
220
222 def __init__(self, data_str, **keyw):
221 def __init__(self, data_str, **keyw):
223 """Construct a String object.
222 """Construct a String object.
224
223
225 <data_str> is a string formatted exactly like a valid Gnuplot data
224 <data_str> is a string formatted exactly like a valid Gnuplot data
226 file would be. All options from the File constructor are valid here.
225 file would be. All options from the File constructor are valid here.
227
226
228 Warning: when used for interactive plotting in scripts which exit
227 Warning: when used for interactive plotting in scripts which exit
229 immediately, you may get an error because the temporary file used to
228 immediately, you may get an error because the temporary file used to
230 hold the string data was deleted before Gnuplot had a chance to see
229 hold the string data was deleted before Gnuplot had a chance to see
231 it. You can work around this problem by putting a raw_input() call at
230 it. You can work around this problem by putting a raw_input() call at
232 the end of the script.
231 the end of the script.
233
232
234 This problem does not appear when generating PostScript output, only
233 This problem does not appear when generating PostScript output, only
235 with Gnuplot windows."""
234 with Gnuplot windows."""
236
235
237 self.tmpfile = _BaseTempFileItem()
236 self.tmpfile = _BaseTempFileItem()
238 tmpfile = file(self.tmpfile.filename,'w')
237 tmpfile = file(self.tmpfile.filename,'w')
239 tmpfile.write(data_str)
238 tmpfile.write(data_str)
240 _BaseFileItem.__init__(self,self.tmpfile,**keyw)
239 _BaseFileItem.__init__(self,self.tmpfile,**keyw)
241
240
242
241
243 class Gnuplot(Gnuplot_ori.Gnuplot):
242 class Gnuplot(Gnuplot_ori.Gnuplot):
244 """Improved Gnuplot class.
243 """Improved Gnuplot class.
245
244
246 Enhancements: better plot,replot and hardcopy methods. New methods for
245 Enhancements: better plot,replot and hardcopy methods. New methods for
247 quick range setting.
246 quick range setting.
248 """
247 """
249
248
250 def xrange(self,min='*',max='*'):
249 def xrange(self,min='*',max='*'):
251 """Set xrange. If min/max is omitted, it is set to '*' (auto).
250 """Set xrange. If min/max is omitted, it is set to '*' (auto).
252
251
253 Note that this is different from the regular Gnuplot behavior, where
252 Note that this is different from the regular Gnuplot behavior, where
254 an unspecified limit means no change. Here any unspecified limit is
253 an unspecified limit means no change. Here any unspecified limit is
255 set to autoscaling, allowing these functions to be used for full
254 set to autoscaling, allowing these functions to be used for full
256 autoscaling when called with no arguments.
255 autoscaling when called with no arguments.
257
256
258 To preserve one limit's current value while changing the other, an
257 To preserve one limit's current value while changing the other, an
259 explicit '' argument must be given as the limit to be kept.
258 explicit '' argument must be given as the limit to be kept.
260
259
261 Similar functions exist for [y{2}z{2}rtuv]range."""
260 Similar functions exist for [y{2}z{2}rtuv]range."""
262
261
263 self('set xrange [%s:%s]' % (min,max))
262 self('set xrange [%s:%s]' % (min,max))
264
263
265 def yrange(self,min='*',max='*'):
264 def yrange(self,min='*',max='*'):
266 self('set yrange [%s:%s]' % (min,max))
265 self('set yrange [%s:%s]' % (min,max))
267
266
268 def zrange(self,min='*',max='*'):
267 def zrange(self,min='*',max='*'):
269 self('set zrange [%s:%s]' % (min,max))
268 self('set zrange [%s:%s]' % (min,max))
270
269
271 def x2range(self,min='*',max='*'):
270 def x2range(self,min='*',max='*'):
272 self('set xrange [%s:%s]' % (min,max))
271 self('set xrange [%s:%s]' % (min,max))
273
272
274 def y2range(self,min='*',max='*'):
273 def y2range(self,min='*',max='*'):
275 self('set yrange [%s:%s]' % (min,max))
274 self('set yrange [%s:%s]' % (min,max))
276
275
277 def z2range(self,min='*',max='*'):
276 def z2range(self,min='*',max='*'):
278 self('set zrange [%s:%s]' % (min,max))
277 self('set zrange [%s:%s]' % (min,max))
279
278
280 def rrange(self,min='*',max='*'):
279 def rrange(self,min='*',max='*'):
281 self('set rrange [%s:%s]' % (min,max))
280 self('set rrange [%s:%s]' % (min,max))
282
281
283 def trange(self,min='*',max='*'):
282 def trange(self,min='*',max='*'):
284 self('set trange [%s:%s]' % (min,max))
283 self('set trange [%s:%s]' % (min,max))
285
284
286 def urange(self,min='*',max='*'):
285 def urange(self,min='*',max='*'):
287 self('set urange [%s:%s]' % (min,max))
286 self('set urange [%s:%s]' % (min,max))
288
287
289 def vrange(self,min='*',max='*'):
288 def vrange(self,min='*',max='*'):
290 self('set vrange [%s:%s]' % (min,max))
289 self('set vrange [%s:%s]' % (min,max))
291
290
292 def set_ps(self,option):
291 def set_ps(self,option):
293 """Set an option for the PostScript terminal and reset default term."""
292 """Set an option for the PostScript terminal and reset default term."""
294
293
295 self('set terminal postscript %s ' % option)
294 self('set terminal postscript %s ' % option)
296 self('set terminal %s' % gp.GnuplotOpts.default_term)
295 self('set terminal %s' % gp.GnuplotOpts.default_term)
297
296
298 def __plot_ps(self, plot_method,*items, **keyw):
297 def __plot_ps(self, plot_method,*items, **keyw):
299 """Wrapper for plot/splot/replot, with processing of hardcopy options.
298 """Wrapper for plot/splot/replot, with processing of hardcopy options.
300
299
301 For internal use only."""
300 For internal use only."""
302
301
303 # Filter out PostScript options which will crash the normal plot/replot
302 # Filter out PostScript options which will crash the normal plot/replot
304 psargs = {'filename':None,
303 psargs = {'filename':None,
305 'mode':None,
304 'mode':None,
306 'eps':None,
305 'eps':None,
307 'enhanced':None,
306 'enhanced':None,
308 'color':None,
307 'color':None,
309 'solid':None,
308 'solid':None,
310 'duplexing':None,
309 'duplexing':None,
311 'fontname':None,
310 'fontname':None,
312 'fontsize':None,
311 'fontsize':None,
313 'debug':0 }
312 'debug':0 }
314
313
315 for k in psargs.keys():
314 for k in psargs.keys():
316 if keyw.has_key(k):
315 if keyw.has_key(k):
317 psargs[k] = keyw[k]
316 psargs[k] = keyw[k]
318 del keyw[k]
317 del keyw[k]
319
318
320 # Filter out other options the original plot doesn't know
319 # Filter out other options the original plot doesn't know
321 hardcopy = popkey(keyw,'hardcopy',psargs['filename'] is not None)
320 hardcopy = popkey(keyw,'hardcopy',psargs['filename'] is not None)
322 titles = popkey(keyw,'titles',0)
321 titles = popkey(keyw,'titles',0)
323
322
324 # the filename keyword should control hardcopy generation, this is an
323 # the filename keyword should control hardcopy generation, this is an
325 # override switch only which needs to be explicitly set to zero
324 # override switch only which needs to be explicitly set to zero
326 if hardcopy:
325 if hardcopy:
327 if psargs['filename'] is None:
326 if psargs['filename'] is None:
328 raise ValueError, \
327 raise ValueError, \
329 'If you request hardcopy, you must give a filename.'
328 'If you request hardcopy, you must give a filename.'
330
329
331 # set null output so nothing goes to screen. hardcopy() restores output
330 # set null output so nothing goes to screen. hardcopy() restores output
332 self('set term dumb')
331 self('set term dumb')
333 # I don't know how to prevent screen output in Windows
332 # I don't know how to prevent screen output in Windows
334 if os.name == 'posix':
333 if os.name == 'posix':
335 self('set output "/dev/null"')
334 self('set output "/dev/null"')
336
335
337 new_items = zip_items(items,titles)
336 new_items = zip_items(items,titles)
338 # plot_method is either plot or replot from the original Gnuplot class:
337 # plot_method is either plot or replot from the original Gnuplot class:
339 plot_method(self,*new_items,**keyw)
338 plot_method(self,*new_items,**keyw)
340
339
341 # Do hardcopy if requested
340 # Do hardcopy if requested
342 if hardcopy:
341 if hardcopy:
343 if psargs['filename'].endswith('.eps'):
342 if psargs['filename'].endswith('.eps'):
344 psargs['eps'] = 1
343 psargs['eps'] = 1
345 self.hardcopy(**psargs)
344 self.hardcopy(**psargs)
346
345
347 def plot(self, *items, **keyw):
346 def plot(self, *items, **keyw):
348 """Draw a new plot.
347 """Draw a new plot.
349
348
350 Clear the current plot and create a new 2-d plot containing
349 Clear the current plot and create a new 2-d plot containing
351 the specified items. Each arguments should be of the
350 the specified items. Each arguments should be of the
352 following types:
351 following types:
353
352
354 'PlotItem' (e.g., 'Data', 'File', 'Func') -- This is the most
353 'PlotItem' (e.g., 'Data', 'File', 'Func') -- This is the most
355 flexible way to call plot because the PlotItems can
354 flexible way to call plot because the PlotItems can
356 contain suboptions. Moreover, PlotItems can be saved to
355 contain suboptions. Moreover, PlotItems can be saved to
357 variables so that their lifetime is longer than one plot
356 variables so that their lifetime is longer than one plot
358 command; thus they can be replotted with minimal overhead.
357 command; thus they can be replotted with minimal overhead.
359
358
360 'string' (e.g., 'sin(x)') -- The string is interpreted as
359 'string' (e.g., 'sin(x)') -- The string is interpreted as
361 'Func(string)' (a function that is computed by gnuplot).
360 'Func(string)' (a function that is computed by gnuplot).
362
361
363 Anything else -- The object, which should be convertible to an
362 Anything else -- The object, which should be convertible to an
364 array, is passed to the 'Data' constructor, and thus
363 array, is passed to the 'Data' constructor, and thus
365 plotted as data. If the conversion fails, an exception is
364 plotted as data. If the conversion fails, an exception is
366 raised.
365 raised.
367
366
368
367
369 This is a modified version of plot(). Compared to the original in
368 This is a modified version of plot(). Compared to the original in
370 Gnuplot.py, this version has several enhancements, listed below.
369 Gnuplot.py, this version has several enhancements, listed below.
371
370
372
371
373 Modifications to the input arguments
372 Modifications to the input arguments
374 ------------------------------------
373 ------------------------------------
375
374
376 (1-d array means Numeric array, list or tuple):
375 (1-d array means Numeric array, list or tuple):
377
376
378 (i) Any 1-d array which is NOT followed by another 1-d array, is
377 (i) Any 1-d array which is NOT followed by another 1-d array, is
379 automatically zipped with range(len(array_1d)). Typing g.plot(y) will
378 automatically zipped with range(len(array_1d)). Typing g.plot(y) will
380 plot y against its indices.
379 plot y against its indices.
381
380
382 (ii) If two 1-d arrays are contiguous in the argument list, they are
381 (ii) If two 1-d arrays are contiguous in the argument list, they are
383 automatically zipped together. So g.plot(x,y) plots y vs. x, and
382 automatically zipped together. So g.plot(x,y) plots y vs. x, and
384 g.plot(x1,y1,x2,y2) plots y1 vs. x1 and y2 vs. x2.
383 g.plot(x1,y1,x2,y2) plots y1 vs. x1 and y2 vs. x2.
385
384
386 (iii) Any 1-d array which is followed by None is automatically zipped
385 (iii) Any 1-d array which is followed by None is automatically zipped
387 with range(len(array_1d)). In this form, typing g.plot(y1,None,y2)
386 with range(len(array_1d)). In this form, typing g.plot(y1,None,y2)
388 will plot both y1 and y2 against their respective indices (and NOT
387 will plot both y1 and y2 against their respective indices (and NOT
389 versus one another). The None prevents zipping y1 and y2 together, and
388 versus one another). The None prevents zipping y1 and y2 together, and
390 since y2 is unpaired it is automatically zipped to its indices by (i)
389 since y2 is unpaired it is automatically zipped to its indices by (i)
391
390
392 (iv) Any other arguments which don't match these cases are left alone and
391 (iv) Any other arguments which don't match these cases are left alone and
393 passed to the code below.
392 passed to the code below.
394
393
395 For lists or tuples, the heuristics used to determine whether they are
394 For lists or tuples, the heuristics used to determine whether they are
396 in fact 1-d is fairly simplistic: their first element is checked, and
395 in fact 1-d is fairly simplistic: their first element is checked, and
397 if it is not a list or tuple itself, it is assumed that the whole
396 if it is not a list or tuple itself, it is assumed that the whole
398 object is one-dimensional.
397 object is one-dimensional.
399
398
400 An additional optional keyword 'titles' has been added: it must be a
399 An additional optional keyword 'titles' has been added: it must be a
401 list of strings to be used as labels for the individual plots which
400 list of strings to be used as labels for the individual plots which
402 are NOT PlotItem objects (since those objects carry their own labels
401 are NOT PlotItem objects (since those objects carry their own labels
403 within).
402 within).
404
403
405
404
406 PostScript generation
405 PostScript generation
407 ---------------------
406 ---------------------
408
407
409 This version of plot() also handles automatically the production of
408 This version of plot() also handles automatically the production of
410 PostScript output. The main options are (given as keyword arguments):
409 PostScript output. The main options are (given as keyword arguments):
411
410
412 - filename: a string, typically ending in .eps. If given, the plot is
411 - filename: a string, typically ending in .eps. If given, the plot is
413 sent to this file in PostScript format.
412 sent to this file in PostScript format.
414
413
415 - hardcopy: this can be set to 0 to override 'filename'. It does not
414 - hardcopy: this can be set to 0 to override 'filename'. It does not
416 need to be given to produce PostScript, its purpose is to allow
415 need to be given to produce PostScript, its purpose is to allow
417 switching PostScript output off globally in scripts without having to
416 switching PostScript output off globally in scripts without having to
418 manually change 'filename' values in multiple calls.
417 manually change 'filename' values in multiple calls.
419
418
420 All other keywords accepted by Gnuplot.hardcopy() are transparently
419 All other keywords accepted by Gnuplot.hardcopy() are transparently
421 passed, and safely ignored if output is sent to the screen instead of
420 passed, and safely ignored if output is sent to the screen instead of
422 PostScript.
421 PostScript.
423
422
424 For example:
423 For example:
425
424
426 In [1]: x=frange(0,2*pi,npts=100)
425 In [1]: x=frange(0,2*pi,npts=100)
427
426
428 Generate a plot in file 'sin.eps':
427 Generate a plot in file 'sin.eps':
429
428
430 In [2]: plot(x,sin(x),filename = 'sin.eps')
429 In [2]: plot(x,sin(x),filename = 'sin.eps')
431
430
432 Plot to screen instead, without having to change the filename:
431 Plot to screen instead, without having to change the filename:
433
432
434 In [3]: plot(x,sin(x),filename = 'sin.eps',hardcopy=0)
433 In [3]: plot(x,sin(x),filename = 'sin.eps',hardcopy=0)
435
434
436 Pass the 'color=0' option to hardcopy for monochrome output:
435 Pass the 'color=0' option to hardcopy for monochrome output:
437
436
438 In [4]: plot(x,sin(x),filename = 'sin.eps',color=0)
437 In [4]: plot(x,sin(x),filename = 'sin.eps',color=0)
439
438
440 PostScript generation through plot() is useful mainly for scripting
439 PostScript generation through plot() is useful mainly for scripting
441 uses where you are not interested in interactive plotting. For
440 uses where you are not interested in interactive plotting. For
442 interactive use, the hardcopy() function is typically more convenient:
441 interactive use, the hardcopy() function is typically more convenient:
443
442
444 In [5]: plot(x,sin(x))
443 In [5]: plot(x,sin(x))
445
444
446 In [6]: hardcopy('sin.eps') """
445 In [6]: hardcopy('sin.eps') """
447
446
448 self.__plot_ps(Gnuplot_ori.Gnuplot.plot,*items,**keyw)
447 self.__plot_ps(Gnuplot_ori.Gnuplot.plot,*items,**keyw)
449
448
450 def plot2(self,arg,**kw):
449 def plot2(self,arg,**kw):
451 """Plot the entries of a dictionary or a list/tuple of arrays.
450 """Plot the entries of a dictionary or a list/tuple of arrays.
452
451
453 This simple utility calls plot() with a list of Gnuplot.Data objects
452 This simple utility calls plot() with a list of Gnuplot.Data objects
454 constructed either from the values of the input dictionary, or the entries
453 constructed either from the values of the input dictionary, or the entries
455 in it if it is a tuple or list. Each item gets labeled with the key/index
454 in it if it is a tuple or list. Each item gets labeled with the key/index
456 in the Gnuplot legend.
455 in the Gnuplot legend.
457
456
458 Each item is plotted by zipping it with a list of its indices.
457 Each item is plotted by zipping it with a list of its indices.
459
458
460 Any keywords are passed directly to plot()."""
459 Any keywords are passed directly to plot()."""
461
460
462 if hasattr(arg,'keys'):
461 if hasattr(arg,'keys'):
463 keys = arg.keys()
462 keys = arg.keys()
464 keys.sort()
463 keys.sort()
465 else:
464 else:
466 keys = range(len(arg))
465 keys = range(len(arg))
467
466
468 pitems = [Data(zip(range(len(arg[k])),arg[k]),title=`k`) for k in keys]
467 pitems = [Data(zip(range(len(arg[k])),arg[k]),title=`k`) for k in keys]
469 self.plot(*pitems,**kw)
468 self.plot(*pitems,**kw)
470
469
471 def splot(self, *items, **keyw):
470 def splot(self, *items, **keyw):
472 """Draw a new three-dimensional plot.
471 """Draw a new three-dimensional plot.
473
472
474 Clear the current plot and create a new 3-d plot containing
473 Clear the current plot and create a new 3-d plot containing
475 the specified items. Arguments can be of the following types:
474 the specified items. Arguments can be of the following types:
476
475
477 'PlotItem' (e.g., 'Data', 'File', 'Func', 'GridData' ) -- This
476 'PlotItem' (e.g., 'Data', 'File', 'Func', 'GridData' ) -- This
478 is the most flexible way to call plot because the
477 is the most flexible way to call plot because the
479 PlotItems can contain suboptions. Moreover, PlotItems can
478 PlotItems can contain suboptions. Moreover, PlotItems can
480 be saved to variables so that their lifetime is longer
479 be saved to variables so that their lifetime is longer
481 than one plot command--thus they can be replotted with
480 than one plot command--thus they can be replotted with
482 minimal overhead.
481 minimal overhead.
483
482
484 'string' (e.g., 'sin(x*y)') -- The string is interpreted as a
483 'string' (e.g., 'sin(x*y)') -- The string is interpreted as a
485 'Func()' (a function that is computed by gnuplot).
484 'Func()' (a function that is computed by gnuplot).
486
485
487 Anything else -- The object is converted to a Data() item, and
486 Anything else -- The object is converted to a Data() item, and
488 thus plotted as data. Note that each data point should
487 thus plotted as data. Note that each data point should
489 normally have at least three values associated with it
488 normally have at least three values associated with it
490 (i.e., x, y, and z). If the conversion fails, an
489 (i.e., x, y, and z). If the conversion fails, an
491 exception is raised.
490 exception is raised.
492
491
493 This is a modified version of splot(). Compared to the original in
492 This is a modified version of splot(). Compared to the original in
494 Gnuplot.py, this version has several enhancements, listed in the
493 Gnuplot.py, this version has several enhancements, listed in the
495 plot() documentation.
494 plot() documentation.
496 """
495 """
497
496
498 self.__plot_ps(Gnuplot_ori.Gnuplot.splot,*items,**keyw)
497 self.__plot_ps(Gnuplot_ori.Gnuplot.splot,*items,**keyw)
499
498
500 def replot(self, *items, **keyw):
499 def replot(self, *items, **keyw):
501 """Replot the data, possibly adding new 'PlotItem's.
500 """Replot the data, possibly adding new 'PlotItem's.
502
501
503 Replot the existing graph, using the items in the current
502 Replot the existing graph, using the items in the current
504 itemlist. If arguments are specified, they are interpreted as
503 itemlist. If arguments are specified, they are interpreted as
505 additional items to be plotted alongside the existing items on
504 additional items to be plotted alongside the existing items on
506 the same graph. See 'plot' for details.
505 the same graph. See 'plot' for details.
507
506
508 If you want to replot to a postscript file, you MUST give the
507 If you want to replot to a postscript file, you MUST give the
509 'filename' keyword argument in each call to replot. The Gnuplot python
508 'filename' keyword argument in each call to replot. The Gnuplot python
510 interface has no way of knowing that your previous call to
509 interface has no way of knowing that your previous call to
511 Gnuplot.plot() was meant for PostScript output."""
510 Gnuplot.plot() was meant for PostScript output."""
512
511
513 self.__plot_ps(Gnuplot_ori.Gnuplot.replot,*items,**keyw)
512 self.__plot_ps(Gnuplot_ori.Gnuplot.replot,*items,**keyw)
514
513
515 # The original hardcopy has a bug. See fix at the end. The rest of the code
514 # The original hardcopy has a bug. See fix at the end. The rest of the code
516 # was lifted verbatim from the original, so that people using IPython get the
515 # was lifted verbatim from the original, so that people using IPython get the
517 # benefits without having to manually patch Gnuplot.py
516 # benefits without having to manually patch Gnuplot.py
518 def hardcopy(self, filename=None,
517 def hardcopy(self, filename=None,
519 mode=None,
518 mode=None,
520 eps=None,
519 eps=None,
521 enhanced=None,
520 enhanced=None,
522 color=None,
521 color=None,
523 solid=None,
522 solid=None,
524 duplexing=None,
523 duplexing=None,
525 fontname=None,
524 fontname=None,
526 fontsize=None,
525 fontsize=None,
527 debug = 0,
526 debug = 0,
528 ):
527 ):
529 """Create a hardcopy of the current plot.
528 """Create a hardcopy of the current plot.
530
529
531 Create a postscript hardcopy of the current plot to the
530 Create a postscript hardcopy of the current plot to the
532 default printer (if configured) or to the specified filename.
531 default printer (if configured) or to the specified filename.
533
532
534 Note that gnuplot remembers the postscript suboptions across
533 Note that gnuplot remembers the postscript suboptions across
535 terminal changes. Therefore if you set, for example, color=1
534 terminal changes. Therefore if you set, for example, color=1
536 for one hardcopy then the next hardcopy will also be color
535 for one hardcopy then the next hardcopy will also be color
537 unless you explicitly choose color=0. Alternately you can
536 unless you explicitly choose color=0. Alternately you can
538 force all of the options to their defaults by setting
537 force all of the options to their defaults by setting
539 mode='default'. I consider this to be a bug in gnuplot.
538 mode='default'. I consider this to be a bug in gnuplot.
540
539
541 Keyword arguments:
540 Keyword arguments:
542
541
543 'filename=<string>' -- if a filename is specified, save the
542 'filename=<string>' -- if a filename is specified, save the
544 output in that file; otherwise print it immediately
543 output in that file; otherwise print it immediately
545 using the 'default_lpr' configuration option. If the
544 using the 'default_lpr' configuration option. If the
546 filename ends in '.eps', EPS mode is automatically
545 filename ends in '.eps', EPS mode is automatically
547 selected (like manually specifying eps=1 or mode='eps').
546 selected (like manually specifying eps=1 or mode='eps').
548
547
549 'mode=<string>' -- set the postscript submode ('landscape',
548 'mode=<string>' -- set the postscript submode ('landscape',
550 'portrait', 'eps', or 'default'). The default is
549 'portrait', 'eps', or 'default'). The default is
551 to leave this option unspecified.
550 to leave this option unspecified.
552
551
553 'eps=<bool>' -- shorthand for 'mode="eps"'; asks gnuplot to
552 'eps=<bool>' -- shorthand for 'mode="eps"'; asks gnuplot to
554 generate encapsulated postscript.
553 generate encapsulated postscript.
555
554
556 'enhanced=<bool>' -- if set (the default), then generate
555 'enhanced=<bool>' -- if set (the default), then generate
557 enhanced postscript, which allows extra features like
556 enhanced postscript, which allows extra features like
558 font-switching, superscripts, and subscripts in axis
557 font-switching, superscripts, and subscripts in axis
559 labels. (Some old gnuplot versions do not support
558 labels. (Some old gnuplot versions do not support
560 enhanced postscript; if this is the case set
559 enhanced postscript; if this is the case set
561 gp.GnuplotOpts.prefer_enhanced_postscript=None.)
560 gp.GnuplotOpts.prefer_enhanced_postscript=None.)
562
561
563 'color=<bool>' -- if set, create a plot with color. Default
562 'color=<bool>' -- if set, create a plot with color. Default
564 is to leave this option unchanged.
563 is to leave this option unchanged.
565
564
566 'solid=<bool>' -- if set, force lines to be solid (i.e., not
565 'solid=<bool>' -- if set, force lines to be solid (i.e., not
567 dashed).
566 dashed).
568
567
569 'duplexing=<string>' -- set duplexing option ('defaultplex',
568 'duplexing=<string>' -- set duplexing option ('defaultplex',
570 'simplex', or 'duplex'). Only request double-sided
569 'simplex', or 'duplex'). Only request double-sided
571 printing if your printer can handle it. Actually this
570 printing if your printer can handle it. Actually this
572 option is probably meaningless since hardcopy() can only
571 option is probably meaningless since hardcopy() can only
573 print a single plot at a time.
572 print a single plot at a time.
574
573
575 'fontname=<string>' -- set the default font to <string>,
574 'fontname=<string>' -- set the default font to <string>,
576 which must be a valid postscript font. The default is
575 which must be a valid postscript font. The default is
577 to leave this option unspecified.
576 to leave this option unspecified.
578
577
579 'fontsize=<double>' -- set the default font size, in
578 'fontsize=<double>' -- set the default font size, in
580 postscript points.
579 postscript points.
581
580
582 'debug=<bool>' -- print extra debugging information (useful if
581 'debug=<bool>' -- print extra debugging information (useful if
583 your PostScript files are misteriously not being created).
582 your PostScript files are misteriously not being created).
584 """
583 """
585
584
586 if filename is None:
585 if filename is None:
587 assert gp.GnuplotOpts.default_lpr is not None, \
586 assert gp.GnuplotOpts.default_lpr is not None, \
588 OptionException('default_lpr is not set, so you can only '
587 OptionException('default_lpr is not set, so you can only '
589 'print to a file.')
588 'print to a file.')
590 filename = gp.GnuplotOpts.default_lpr
589 filename = gp.GnuplotOpts.default_lpr
591 lpr_output = 1
590 lpr_output = 1
592 else:
591 else:
593 if filename.endswith('.eps'):
592 if filename.endswith('.eps'):
594 eps = 1
593 eps = 1
595 lpr_output = 0
594 lpr_output = 0
596
595
597 # Be careful processing the options. If the user didn't
596 # Be careful processing the options. If the user didn't
598 # request an option explicitly, do not specify it on the 'set
597 # request an option explicitly, do not specify it on the 'set
599 # terminal' line (don't even specify the default value for the
598 # terminal' line (don't even specify the default value for the
600 # option). This is to avoid confusing older versions of
599 # option). This is to avoid confusing older versions of
601 # gnuplot that do not support all of these options. The
600 # gnuplot that do not support all of these options. The
602 # exception is 'enhanced', which is just too useful to have to
601 # exception is 'enhanced', which is just too useful to have to
603 # specify each time!
602 # specify each time!
604
603
605 setterm = ['set', 'terminal', 'postscript']
604 setterm = ['set', 'terminal', 'postscript']
606 if eps:
605 if eps:
607 assert mode is None or mode=='eps', \
606 assert mode is None or mode=='eps', \
608 OptionException('eps option and mode are incompatible')
607 OptionException('eps option and mode are incompatible')
609 setterm.append('eps')
608 setterm.append('eps')
610 else:
609 else:
611 if mode is not None:
610 if mode is not None:
612 assert mode in ['landscape', 'portrait', 'eps', 'default'], \
611 assert mode in ['landscape', 'portrait', 'eps', 'default'], \
613 OptionException('illegal mode "%s"' % mode)
612 OptionException('illegal mode "%s"' % mode)
614 setterm.append(mode)
613 setterm.append(mode)
615 if enhanced is None:
614 if enhanced is None:
616 enhanced = gp.GnuplotOpts.prefer_enhanced_postscript
615 enhanced = gp.GnuplotOpts.prefer_enhanced_postscript
617 if enhanced is not None:
616 if enhanced is not None:
618 if enhanced: setterm.append('enhanced')
617 if enhanced: setterm.append('enhanced')
619 else: setterm.append('noenhanced')
618 else: setterm.append('noenhanced')
620 if color is not None:
619 if color is not None:
621 if color: setterm.append('color')
620 if color: setterm.append('color')
622 else: setterm.append('monochrome')
621 else: setterm.append('monochrome')
623 if solid is not None:
622 if solid is not None:
624 if solid: setterm.append('solid')
623 if solid: setterm.append('solid')
625 else: setterm.append('dashed')
624 else: setterm.append('dashed')
626 if duplexing is not None:
625 if duplexing is not None:
627 assert duplexing in ['defaultplex', 'simplex', 'duplex'], \
626 assert duplexing in ['defaultplex', 'simplex', 'duplex'], \
628 OptionException('illegal duplexing mode "%s"' % duplexing)
627 OptionException('illegal duplexing mode "%s"' % duplexing)
629 setterm.append(duplexing)
628 setterm.append(duplexing)
630 if fontname is not None:
629 if fontname is not None:
631 setterm.append('"%s"' % fontname)
630 setterm.append('"%s"' % fontname)
632 if fontsize is not None:
631 if fontsize is not None:
633 setterm.append('%s' % fontsize)
632 setterm.append('%s' % fontsize)
634
633
635 self(string.join(setterm))
634 self(string.join(setterm))
636 self.set_string('output', filename)
635 self.set_string('output', filename)
637 # replot the current figure (to the printer):
636 # replot the current figure (to the printer):
638 self.refresh()
637 self.refresh()
639
638
640 # fperez. Ugly kludge: often for some reason the file is NOT created
639 # fperez. Ugly kludge: often for some reason the file is NOT created
641 # and we must reissue the creation commands. I have no idea why!
640 # and we must reissue the creation commands. I have no idea why!
642 if not lpr_output:
641 if not lpr_output:
643 #print 'Hardcopy <%s>' % filename # dbg
642 #print 'Hardcopy <%s>' % filename # dbg
644 maxtries = 20
643 maxtries = 20
645 delay = 0.1 # delay (in seconds) between print attempts
644 delay = 0.1 # delay (in seconds) between print attempts
646 for i in range(maxtries):
645 for i in range(maxtries):
647 time.sleep(0.05) # safety, very small delay
646 time.sleep(0.05) # safety, very small delay
648 if os.path.isfile(filename):
647 if os.path.isfile(filename):
649 if debug:
648 if debug:
650 print 'Hardcopy to file <%s> success at attempt #%s.' \
649 print 'Hardcopy to file <%s> success at attempt #%s.' \
651 % (filename,i+1)
650 % (filename,i+1)
652 break
651 break
653 time.sleep(delay)
652 time.sleep(delay)
654 # try again, issue all commands just in case
653 # try again, issue all commands just in case
655 self(string.join(setterm))
654 self(string.join(setterm))
656 self.set_string('output', filename)
655 self.set_string('output', filename)
657 self.refresh()
656 self.refresh()
658 if not os.path.isfile(filename):
657 if not os.path.isfile(filename):
659 print >> sys.stderr,'ERROR: Tried %s times and failed to '\
658 print >> sys.stderr,'ERROR: Tried %s times and failed to '\
660 'create hardcopy file `%s`' % (maxtries,filename)
659 'create hardcopy file `%s`' % (maxtries,filename)
661
660
662 # reset the terminal to its `default' setting:
661 # reset the terminal to its `default' setting:
663 self('set terminal %s' % gp.GnuplotOpts.default_term)
662 self('set terminal %s' % gp.GnuplotOpts.default_term)
664 self.set_string('output')
663 self.set_string('output')
665
664
666 #********************** End of file <Gnuplot2.py> ************************
665 #********************** End of file <Gnuplot2.py> ************************
@@ -1,148 +1,147 b''
1 # -*- coding: utf-8 -*-
1 # -*- coding: utf-8 -*-
2 """Interactive functions and magic functions for Gnuplot usage.
2 """Interactive functions and magic functions for Gnuplot usage.
3
3
4 This requires the Gnuplot.py module for interfacing python with Gnuplot, which
4 This requires the Gnuplot.py module for interfacing python with Gnuplot, which
5 can be downloaded from:
5 can be downloaded from:
6
6
7 http://gnuplot-py.sourceforge.net/
7 http://gnuplot-py.sourceforge.net/
8
8
9 See gphelp() below for details on the services offered by this module.
9 See gphelp() below for details on the services offered by this module.
10
10
11 Inspired by a suggestion/request from Arnd Baecker.
11 Inspired by a suggestion/request from Arnd Baecker.
12
12 """
13 $Id: GnuplotInteractive.py 389 2004-10-09 07:59:30Z fperez $"""
14
13
15 __all__ = ['Gnuplot','gp','gp_new','plot','plot2','splot','replot',
14 __all__ = ['Gnuplot','gp','gp_new','plot','plot2','splot','replot',
16 'hardcopy','gpdata','gpfile','gpstring','gpfunc','gpgrid',
15 'hardcopy','gpdata','gpfile','gpstring','gpfunc','gpgrid',
17 'gphelp']
16 'gphelp']
18
17
19 import IPython.GnuplotRuntime as GRun
18 import IPython.GnuplotRuntime as GRun
20 from IPython.genutils import page,warn
19 from IPython.genutils import page,warn
21
20
22 # Set global names for interactive use
21 # Set global names for interactive use
23 Gnuplot = GRun.Gnuplot
22 Gnuplot = GRun.Gnuplot
24 gp_new = GRun.gp_new
23 gp_new = GRun.gp_new
25 gp = GRun.gp
24 gp = GRun.gp
26 plot = gp.plot
25 plot = gp.plot
27 plot2 = gp.plot2
26 plot2 = gp.plot2
28 splot = gp.splot
27 splot = gp.splot
29 replot = gp.replot
28 replot = gp.replot
30 hardcopy = gp.hardcopy
29 hardcopy = gp.hardcopy
31
30
32 # Accessors for the main plot object constructors:
31 # Accessors for the main plot object constructors:
33 gpdata = Gnuplot.Data
32 gpdata = Gnuplot.Data
34 gpfile = Gnuplot.File
33 gpfile = Gnuplot.File
35 gpstring = Gnuplot.String
34 gpstring = Gnuplot.String
36 gpfunc = Gnuplot.Func
35 gpfunc = Gnuplot.Func
37 gpgrid = Gnuplot.GridData
36 gpgrid = Gnuplot.GridData
38
37
39 def gphelp():
38 def gphelp():
40 """Print information about the Gnuplot facilities in IPython."""
39 """Print information about the Gnuplot facilities in IPython."""
41
40
42 page("""
41 page("""
43 IPython provides an interface to access the Gnuplot scientific plotting
42 IPython provides an interface to access the Gnuplot scientific plotting
44 system, in an environment similar to that of Mathematica or Matlab.
43 system, in an environment similar to that of Mathematica or Matlab.
45
44
46 New top-level global objects
45 New top-level global objects
47 ----------------------------
46 ----------------------------
48
47
49 Please see their respective docstrings for further details.
48 Please see their respective docstrings for further details.
50
49
51 - gp: a running Gnuplot instance. You can access its methods as
50 - gp: a running Gnuplot instance. You can access its methods as
52 gp.<method>. gp(`a string`) will execute the given string as if it had been
51 gp.<method>. gp(`a string`) will execute the given string as if it had been
53 typed in an interactive gnuplot window.
52 typed in an interactive gnuplot window.
54
53
55 - plot, splot, replot and hardcopy: aliases to the methods of the same name in
54 - plot, splot, replot and hardcopy: aliases to the methods of the same name in
56 the global running Gnuplot instance gp. These allow you to simply type:
55 the global running Gnuplot instance gp. These allow you to simply type:
57
56
58 In [1]: plot(x,sin(x),title='Sin(x)') # assuming x is a Numeric array
57 In [1]: plot(x,sin(x),title='Sin(x)') # assuming x is a Numeric array
59
58
60 and obtain a plot of sin(x) vs x with the title 'Sin(x)'.
59 and obtain a plot of sin(x) vs x with the title 'Sin(x)'.
61
60
62 - gp_new: a function which returns a new Gnuplot instance. This can be used to
61 - gp_new: a function which returns a new Gnuplot instance. This can be used to
63 have multiple Gnuplot instances running in your session to compare different
62 have multiple Gnuplot instances running in your session to compare different
64 plots, each in a separate window.
63 plots, each in a separate window.
65
64
66 - Gnuplot: alias to the Gnuplot2 module, an improved drop-in replacement for
65 - Gnuplot: alias to the Gnuplot2 module, an improved drop-in replacement for
67 the original Gnuplot.py. Gnuplot2 needs Gnuplot but redefines several of its
66 the original Gnuplot.py. Gnuplot2 needs Gnuplot but redefines several of its
68 functions with improved versions (Gnuplot2 comes with IPython).
67 functions with improved versions (Gnuplot2 comes with IPython).
69
68
70 - gpdata, gpfile, gpstring, gpfunc, gpgrid: aliases to Gnuplot.Data,
69 - gpdata, gpfile, gpstring, gpfunc, gpgrid: aliases to Gnuplot.Data,
71 Gnuplot.File, Gnuplot.String, Gnuplot.Func and Gnuplot.GridData
70 Gnuplot.File, Gnuplot.String, Gnuplot.Func and Gnuplot.GridData
72 respectively. These functions create objects which can then be passed to the
71 respectively. These functions create objects which can then be passed to the
73 plotting commands. See the Gnuplot.py documentation for details.
72 plotting commands. See the Gnuplot.py documentation for details.
74
73
75 Keep in mind that all commands passed to a Gnuplot instance are executed in
74 Keep in mind that all commands passed to a Gnuplot instance are executed in
76 the Gnuplot namespace, where no Python variables exist. For example, for
75 the Gnuplot namespace, where no Python variables exist. For example, for
77 plotting sin(x) vs x as above, typing
76 plotting sin(x) vs x as above, typing
78
77
79 In [2]: gp('plot x,sin(x)')
78 In [2]: gp('plot x,sin(x)')
80
79
81 would not work. Instead, you would get the plot of BOTH the functions 'x' and
80 would not work. Instead, you would get the plot of BOTH the functions 'x' and
82 'sin(x)', since Gnuplot doesn't know about the 'x' Python array. The plot()
81 'sin(x)', since Gnuplot doesn't know about the 'x' Python array. The plot()
83 method lives in python and does know about these variables.
82 method lives in python and does know about these variables.
84
83
85
84
86 New magic functions
85 New magic functions
87 -------------------
86 -------------------
88
87
89 %gpc: pass one command to Gnuplot and execute it or open a Gnuplot shell where
88 %gpc: pass one command to Gnuplot and execute it or open a Gnuplot shell where
90 each line of input is executed.
89 each line of input is executed.
91
90
92 %gp_set_default: reset the value of IPython's global Gnuplot instance.""")
91 %gp_set_default: reset the value of IPython's global Gnuplot instance.""")
93
92
94 # Code below is all for IPython use
93 # Code below is all for IPython use
95 # Define the magic functions for communicating with the above gnuplot instance.
94 # Define the magic functions for communicating with the above gnuplot instance.
96 def magic_gpc(self,parameter_s=''):
95 def magic_gpc(self,parameter_s=''):
97 """Execute a gnuplot command or open a gnuplot shell.
96 """Execute a gnuplot command or open a gnuplot shell.
98
97
99 Usage (omit the % if automagic is on). There are two ways to use it:
98 Usage (omit the % if automagic is on). There are two ways to use it:
100
99
101 1) %gpc 'command' -> passes 'command' directly to the gnuplot instance.
100 1) %gpc 'command' -> passes 'command' directly to the gnuplot instance.
102
101
103 2) %gpc -> will open up a prompt (gnuplot>>>) which takes input like the
102 2) %gpc -> will open up a prompt (gnuplot>>>) which takes input like the
104 standard gnuplot interactive prompt. If you need to type a multi-line
103 standard gnuplot interactive prompt. If you need to type a multi-line
105 command, use \\ at the end of each intermediate line.
104 command, use \\ at the end of each intermediate line.
106
105
107 Upon exiting of the gnuplot sub-shell, you return to your IPython
106 Upon exiting of the gnuplot sub-shell, you return to your IPython
108 session (the gnuplot sub-shell can be invoked as many times as needed).
107 session (the gnuplot sub-shell can be invoked as many times as needed).
109 """
108 """
110
109
111 if parameter_s.strip():
110 if parameter_s.strip():
112 self.shell.gnuplot(parameter_s)
111 self.shell.gnuplot(parameter_s)
113 else:
112 else:
114 self.shell.gnuplot.interact()
113 self.shell.gnuplot.interact()
115
114
116 def magic_gp_set_default(self,parameter_s=''):
115 def magic_gp_set_default(self,parameter_s=''):
117 """Set the default gnuplot instance accessed by the %gp magic function.
116 """Set the default gnuplot instance accessed by the %gp magic function.
118
117
119 %gp_set_default name
118 %gp_set_default name
120
119
121 Call with the name of the new instance at the command line. If you want to
120 Call with the name of the new instance at the command line. If you want to
122 set this instance in your own code (using an embedded IPython, for
121 set this instance in your own code (using an embedded IPython, for
123 example), simply set the variable __IPYTHON__.gnuplot to your own gnuplot
122 example), simply set the variable __IPYTHON__.gnuplot to your own gnuplot
124 instance object."""
123 instance object."""
125
124
126 gname = parameter_s.strip()
125 gname = parameter_s.strip()
127 G = eval(gname,self.shell.user_ns)
126 G = eval(gname,self.shell.user_ns)
128 self.shell.gnuplot = G
127 self.shell.gnuplot = G
129 self.shell.user_ns.update({'plot':G.plot,'splot':G.splot,'plot2':G.plot2,
128 self.shell.user_ns.update({'plot':G.plot,'splot':G.splot,'plot2':G.plot2,
130 'replot':G.replot,'hardcopy':G.hardcopy})
129 'replot':G.replot,'hardcopy':G.hardcopy})
131
130
132 try:
131 try:
133 __IPYTHON__
132 __IPYTHON__
134 except NameError:
133 except NameError:
135 pass
134 pass
136 else:
135 else:
137 # make the global Gnuplot instance known to IPython
136 # make the global Gnuplot instance known to IPython
138 __IPYTHON__.gnuplot = GRun.gp
137 __IPYTHON__.gnuplot = GRun.gp
139 __IPYTHON__.gnuplot.shell_first_time = 1
138 __IPYTHON__.gnuplot.shell_first_time = 1
140
139
141 print """*** Type `gphelp` for help on the Gnuplot integration features."""
140 print """*** Type `gphelp` for help on the Gnuplot integration features."""
142
141
143 # Add the new magic functions to the class dict
142 # Add the new magic functions to the class dict
144 from IPython.iplib import InteractiveShell
143 from IPython.iplib import InteractiveShell
145 InteractiveShell.magic_gpc = magic_gpc
144 InteractiveShell.magic_gpc = magic_gpc
146 InteractiveShell.magic_gp_set_default = magic_gp_set_default
145 InteractiveShell.magic_gp_set_default = magic_gp_set_default
147
146
148 #********************** End of file <GnuplotInteractive.py> *******************
147 #********************** End of file <GnuplotInteractive.py> *******************
@@ -1,147 +1,146 b''
1 # -*- coding: utf-8 -*-
1 # -*- coding: utf-8 -*-
2 """Basic Gnuplot functionality for inclusion in other code.
2 """Basic Gnuplot functionality for inclusion in other code.
3
3
4 This module creates a running Gnuplot instance called 'gp' and builds other
4 This module creates a running Gnuplot instance called 'gp' and builds other
5 convenient globals for quick use in running scripts. It is intended to allow
5 convenient globals for quick use in running scripts. It is intended to allow
6 you to script plotting tasks in Python with a minimum of effort. A typical
6 you to script plotting tasks in Python with a minimum of effort. A typical
7 usage would be:
7 usage would be:
8
8
9 import IPython.GnuplotRuntime as GP # or some other short name
9 import IPython.GnuplotRuntime as GP # or some other short name
10 GP.gp.plot(GP.File('your_data.dat'))
10 GP.gp.plot(GP.File('your_data.dat'))
11
11
12
12
13 This module exposes the following objects:
13 This module exposes the following objects:
14
14
15 - gp: a running Gnuplot instance. You can access its methods as
15 - gp: a running Gnuplot instance. You can access its methods as
16 gp.<method>. gp(`a string`) will execute the given string as if it had been
16 gp.<method>. gp(`a string`) will execute the given string as if it had been
17 typed in an interactive gnuplot window.
17 typed in an interactive gnuplot window.
18
18
19 - gp_new: a function which returns a new Gnuplot instance. This can be used to
19 - gp_new: a function which returns a new Gnuplot instance. This can be used to
20 have multiple Gnuplot instances running in your session to compare different
20 have multiple Gnuplot instances running in your session to compare different
21 plots.
21 plots.
22
22
23 - Gnuplot: alias to the Gnuplot2 module, an improved drop-in replacement for
23 - Gnuplot: alias to the Gnuplot2 module, an improved drop-in replacement for
24 the original Gnuplot.py. Gnuplot2 needs Gnuplot but redefines several of its
24 the original Gnuplot.py. Gnuplot2 needs Gnuplot but redefines several of its
25 functions with improved versions (Gnuplot2 comes with IPython).
25 functions with improved versions (Gnuplot2 comes with IPython).
26
26
27 - Data: alias to Gnuplot.Data, makes a PlotItem from array data.
27 - Data: alias to Gnuplot.Data, makes a PlotItem from array data.
28
28
29 - File: alias to Gnuplot.File, makes a PlotItem from a file.
29 - File: alias to Gnuplot.File, makes a PlotItem from a file.
30
30
31 - String: alias to Gnuplot.String, makes a PlotItem from a string formatted
31 - String: alias to Gnuplot.String, makes a PlotItem from a string formatted
32 exactly like a file for Gnuplot.File would be.
32 exactly like a file for Gnuplot.File would be.
33
33
34 - Func: alias to Gnuplot.Func, makes a PlotItem from a function string.
34 - Func: alias to Gnuplot.Func, makes a PlotItem from a function string.
35
35
36 - GridData: alias to Gnuplot.GridData, makes a PlotItem from grid data.
36 - GridData: alias to Gnuplot.GridData, makes a PlotItem from grid data.
37
37
38 - pm3d_config: a string with Gnuplot commands to set up the pm3d mode for
38 - pm3d_config: a string with Gnuplot commands to set up the pm3d mode for
39 surface plotting. You can activate it simply by calling gp(pm3d_config).
39 surface plotting. You can activate it simply by calling gp(pm3d_config).
40
40
41 - eps_fix_bbox: A Unix-only function to fix eps files with bad bounding boxes
41 - eps_fix_bbox: A Unix-only function to fix eps files with bad bounding boxes
42 (which Gnuplot generates when the plot size is set to square).
42 (which Gnuplot generates when the plot size is set to square).
43
43
44 This requires the Gnuplot.py module for interfacing Python with Gnuplot, which
44 This requires the Gnuplot.py module for interfacing Python with Gnuplot, which
45 can be downloaded from:
45 can be downloaded from:
46
46
47 http://gnuplot-py.sourceforge.net/
47 http://gnuplot-py.sourceforge.net/
48
48
49 Inspired by a suggestion/request from Arnd Baecker.
49 Inspired by a suggestion/request from Arnd Baecker.
50
50 """
51 $Id: GnuplotRuntime.py 389 2004-10-09 07:59:30Z fperez $"""
52
51
53 __all__ = ['Gnuplot','gp','gp_new','Data','File','Func','GridData',
52 __all__ = ['Gnuplot','gp','gp_new','Data','File','Func','GridData',
54 'pm3d_config','eps_fix_bbox']
53 'pm3d_config','eps_fix_bbox']
55
54
56 import os,tempfile,sys
55 import os,tempfile,sys
57 from IPython.genutils import getoutput
56 from IPython.genutils import getoutput
58
57
59 #---------------------------------------------------------------------------
58 #---------------------------------------------------------------------------
60 # Notes on mouse support for Gnuplot.py
59 # Notes on mouse support for Gnuplot.py
61
60
62 # If you do not have a mouse-enabled gnuplot, set gnuplot_mouse to 0. If you
61 # If you do not have a mouse-enabled gnuplot, set gnuplot_mouse to 0. If you
63 # use gnuplot, you should really grab a recent, mouse enabled copy. It is an
62 # use gnuplot, you should really grab a recent, mouse enabled copy. It is an
64 # extremely useful feature. Mouse support is official as of gnuplot 4.0,
63 # extremely useful feature. Mouse support is official as of gnuplot 4.0,
65 # released in April 2004.
64 # released in April 2004.
66
65
67 # For the mouse features to work correctly, you MUST set your Gnuplot.py
66 # For the mouse features to work correctly, you MUST set your Gnuplot.py
68 # module to use temporary files instead of 'inline data' for data
67 # module to use temporary files instead of 'inline data' for data
69 # communication. Note that this is the default, so unless you've manually
68 # communication. Note that this is the default, so unless you've manually
70 # fiddled with it you should be ok. If you need to make changes, in the
69 # fiddled with it you should be ok. If you need to make changes, in the
71 # Gnuplot module directory, loook for the gp_unix.py file and make sure the
70 # Gnuplot module directory, loook for the gp_unix.py file and make sure the
72 # prefer_inline_data variable is set to 0. If you set it to 1 Gnuplot.py will
71 # prefer_inline_data variable is set to 0. If you set it to 1 Gnuplot.py will
73 # try to pass the data to gnuplot via standard input, which completely
72 # try to pass the data to gnuplot via standard input, which completely
74 # confuses the mouse control system (even though it may be a bit faster than
73 # confuses the mouse control system (even though it may be a bit faster than
75 # using temp files).
74 # using temp files).
76
75
77 # As of Gnuplot.py v1.7, a new option was added to use FIFOs (pipes). This
76 # As of Gnuplot.py v1.7, a new option was added to use FIFOs (pipes). This
78 # mechanism, while fast, also breaks the mouse system. You must therefore set
77 # mechanism, while fast, also breaks the mouse system. You must therefore set
79 # the variable prefer_fifo_data to 0 in gp_unix.py.
78 # the variable prefer_fifo_data to 0 in gp_unix.py.
80
79
81 tmpname = tempfile.mktemp()
80 tmpname = tempfile.mktemp()
82 open(tmpname,'w').write('set mouse')
81 open(tmpname,'w').write('set mouse')
83 gnu_out = getoutput('gnuplot '+ tmpname)
82 gnu_out = getoutput('gnuplot '+ tmpname)
84 os.unlink(tmpname)
83 os.unlink(tmpname)
85 if gnu_out: # Gnuplot won't print anything if it has mouse support
84 if gnu_out: # Gnuplot won't print anything if it has mouse support
86 print "*** Your version of Gnuplot appears not to have mouse support."
85 print "*** Your version of Gnuplot appears not to have mouse support."
87 gnuplot_mouse = 0
86 gnuplot_mouse = 0
88 else:
87 else:
89 gnuplot_mouse = 1
88 gnuplot_mouse = 1
90 del tmpname,gnu_out
89 del tmpname,gnu_out
91
90
92 # Default state for persistence of new gnuplot instances
91 # Default state for persistence of new gnuplot instances
93 if os.name in ['nt','dos'] or sys.platform == 'cygwin':
92 if os.name in ['nt','dos'] or sys.platform == 'cygwin':
94 gnuplot_persist = 0
93 gnuplot_persist = 0
95 else:
94 else:
96 gnuplot_persist = 1
95 gnuplot_persist = 1
97
96
98 import IPython.Gnuplot2 as Gnuplot
97 import IPython.Gnuplot2 as Gnuplot
99
98
100 class NotGiven: pass
99 class NotGiven: pass
101
100
102 def gp_new(mouse=NotGiven,persist=NotGiven):
101 def gp_new(mouse=NotGiven,persist=NotGiven):
103 """Return a new Gnuplot instance.
102 """Return a new Gnuplot instance.
104
103
105 The instance returned uses the improved methods defined in Gnuplot2.
104 The instance returned uses the improved methods defined in Gnuplot2.
106
105
107 Options (boolean):
106 Options (boolean):
108
107
109 - mouse: if unspecified, the module global gnuplot_mouse is used.
108 - mouse: if unspecified, the module global gnuplot_mouse is used.
110
109
111 - persist: if unspecified, the module global gnuplot_persist is used."""
110 - persist: if unspecified, the module global gnuplot_persist is used."""
112
111
113 if mouse is NotGiven:
112 if mouse is NotGiven:
114 mouse = gnuplot_mouse
113 mouse = gnuplot_mouse
115 if persist is NotGiven:
114 if persist is NotGiven:
116 persist = gnuplot_persist
115 persist = gnuplot_persist
117 g = Gnuplot.Gnuplot(persist=persist)
116 g = Gnuplot.Gnuplot(persist=persist)
118 if mouse:
117 if mouse:
119 g('set mouse')
118 g('set mouse')
120 return g
119 return g
121
120
122 # Global-level names.
121 # Global-level names.
123
122
124 # A global Gnuplot instance for interactive use:
123 # A global Gnuplot instance for interactive use:
125 gp = gp_new()
124 gp = gp_new()
126
125
127 # Accessors for the main plot object constructors:
126 # Accessors for the main plot object constructors:
128 Data = Gnuplot.Data
127 Data = Gnuplot.Data
129 File = Gnuplot.File
128 File = Gnuplot.File
130 Func = Gnuplot.Func
129 Func = Gnuplot.Func
131 String = Gnuplot.String
130 String = Gnuplot.String
132 GridData = Gnuplot.GridData
131 GridData = Gnuplot.GridData
133
132
134 # A Unix-only function to fix eps files with bad bounding boxes (which Gnuplot
133 # A Unix-only function to fix eps files with bad bounding boxes (which Gnuplot
135 # generates when the plot size is set to square):
134 # generates when the plot size is set to square):
136 eps_fix_bbox = Gnuplot.eps_fix_bbox
135 eps_fix_bbox = Gnuplot.eps_fix_bbox
137
136
138 # String for configuring pm3d. Simply call g(pm3d_config) to execute it. pm3d
137 # String for configuring pm3d. Simply call g(pm3d_config) to execute it. pm3d
139 # is a very nice mode for plotting colormaps on surfaces. Modify the defaults
138 # is a very nice mode for plotting colormaps on surfaces. Modify the defaults
140 # below to suit your taste.
139 # below to suit your taste.
141 pm3d_config = """
140 pm3d_config = """
142 set pm3d solid
141 set pm3d solid
143 set hidden3d
142 set hidden3d
144 unset surface
143 unset surface
145 set isosamples 50
144 set isosamples 50
146 """
145 """
147 #******************** End of file <GnuplotRuntime.py> ******************
146 #******************** End of file <GnuplotRuntime.py> ******************
@@ -1,292 +1,290 b''
1 # -*- coding: utf-8 -*-
1 # -*- coding: utf-8 -*-
2 """String interpolation for Python (by Ka-Ping Yee, 14 Feb 2000).
2 """String interpolation for Python (by Ka-Ping Yee, 14 Feb 2000).
3
3
4 This module lets you quickly and conveniently interpolate values into
4 This module lets you quickly and conveniently interpolate values into
5 strings (in the flavour of Perl or Tcl, but with less extraneous
5 strings (in the flavour of Perl or Tcl, but with less extraneous
6 punctuation). You get a bit more power than in the other languages,
6 punctuation). You get a bit more power than in the other languages,
7 because this module allows subscripting, slicing, function calls,
7 because this module allows subscripting, slicing, function calls,
8 attribute lookup, or arbitrary expressions. Variables and expressions
8 attribute lookup, or arbitrary expressions. Variables and expressions
9 are evaluated in the namespace of the caller.
9 are evaluated in the namespace of the caller.
10
10
11 The itpl() function returns the result of interpolating a string, and
11 The itpl() function returns the result of interpolating a string, and
12 printpl() prints out an interpolated string. Here are some examples:
12 printpl() prints out an interpolated string. Here are some examples:
13
13
14 from Itpl import printpl
14 from Itpl import printpl
15 printpl("Here is a $string.")
15 printpl("Here is a $string.")
16 printpl("Here is a $module.member.")
16 printpl("Here is a $module.member.")
17 printpl("Here is an $object.member.")
17 printpl("Here is an $object.member.")
18 printpl("Here is a $functioncall(with, arguments).")
18 printpl("Here is a $functioncall(with, arguments).")
19 printpl("Here is an ${arbitrary + expression}.")
19 printpl("Here is an ${arbitrary + expression}.")
20 printpl("Here is an $array[3] member.")
20 printpl("Here is an $array[3] member.")
21 printpl("Here is a $dictionary['member'].")
21 printpl("Here is a $dictionary['member'].")
22
22
23 The filter() function filters a file object so that output through it
23 The filter() function filters a file object so that output through it
24 is interpolated. This lets you produce the illusion that Python knows
24 is interpolated. This lets you produce the illusion that Python knows
25 how to do interpolation:
25 how to do interpolation:
26
26
27 import Itpl
27 import Itpl
28 sys.stdout = Itpl.filter()
28 sys.stdout = Itpl.filter()
29 f = "fancy"
29 f = "fancy"
30 print "Isn't this $f?"
30 print "Is this not $f?"
31 print "Standard output has been replaced with a $sys.stdout object."
31 print "Standard output has been replaced with a $sys.stdout object."
32 sys.stdout = Itpl.unfilter()
32 sys.stdout = Itpl.unfilter()
33 print "Okay, back $to $normal."
33 print "Okay, back $to $normal."
34
34
35 Under the hood, the Itpl class represents a string that knows how to
35 Under the hood, the Itpl class represents a string that knows how to
36 interpolate values. An instance of the class parses the string once
36 interpolate values. An instance of the class parses the string once
37 upon initialization; the evaluation and substitution can then be done
37 upon initialization; the evaluation and substitution can then be done
38 each time the instance is evaluated with str(instance). For example:
38 each time the instance is evaluated with str(instance). For example:
39
39
40 from Itpl import Itpl
40 from Itpl import Itpl
41 s = Itpl("Here is $foo.")
41 s = Itpl("Here is $foo.")
42 foo = 5
42 foo = 5
43 print str(s)
43 print str(s)
44 foo = "bar"
44 foo = "bar"
45 print str(s)
45 print str(s)
46
46 """
47 $Id: Itpl.py 2918 2007-12-31 14:34:47Z vivainio $
48 """ # ' -> close an open quote for stupid emacs
49
47
50 #*****************************************************************************
48 #*****************************************************************************
51 #
49 #
52 # Copyright (c) 2001 Ka-Ping Yee <ping@lfw.org>
50 # Copyright (c) 2001 Ka-Ping Yee <ping@lfw.org>
53 #
51 #
54 #
52 #
55 # Published under the terms of the MIT license, hereby reproduced:
53 # Published under the terms of the MIT license, hereby reproduced:
56 #
54 #
57 # Permission is hereby granted, free of charge, to any person obtaining a copy
55 # Permission is hereby granted, free of charge, to any person obtaining a copy
58 # of this software and associated documentation files (the "Software"), to
56 # of this software and associated documentation files (the "Software"), to
59 # deal in the Software without restriction, including without limitation the
57 # deal in the Software without restriction, including without limitation the
60 # rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
58 # rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
61 # sell copies of the Software, and to permit persons to whom the Software is
59 # sell copies of the Software, and to permit persons to whom the Software is
62 # furnished to do so, subject to the following conditions:
60 # furnished to do so, subject to the following conditions:
63 #
61 #
64 # The above copyright notice and this permission notice shall be included in
62 # The above copyright notice and this permission notice shall be included in
65 # all copies or substantial portions of the Software.
63 # all copies or substantial portions of the Software.
66 #
64 #
67 # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
65 # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
68 # IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
66 # IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
69 # FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
67 # FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
70 # AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
68 # AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
71 # LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
69 # LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
72 # FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
70 # FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
73 # IN THE SOFTWARE.
71 # IN THE SOFTWARE.
74 #
72 #
75 #*****************************************************************************
73 #*****************************************************************************
76
74
77 __author__ = 'Ka-Ping Yee <ping@lfw.org>'
75 __author__ = 'Ka-Ping Yee <ping@lfw.org>'
78 __license__ = 'MIT'
76 __license__ = 'MIT'
79
77
80 import string
78 import string
81 import sys
79 import sys
82 from tokenize import tokenprog
80 from tokenize import tokenprog
83 from types import StringType
81 from types import StringType
84
82
85 class ItplError(ValueError):
83 class ItplError(ValueError):
86 def __init__(self, text, pos):
84 def __init__(self, text, pos):
87 self.text = text
85 self.text = text
88 self.pos = pos
86 self.pos = pos
89 def __str__(self):
87 def __str__(self):
90 return "unfinished expression in %s at char %d" % (
88 return "unfinished expression in %s at char %d" % (
91 repr(self.text), self.pos)
89 repr(self.text), self.pos)
92
90
93 def matchorfail(text, pos):
91 def matchorfail(text, pos):
94 match = tokenprog.match(text, pos)
92 match = tokenprog.match(text, pos)
95 if match is None:
93 if match is None:
96 raise ItplError(text, pos)
94 raise ItplError(text, pos)
97
95
98 return match, match.end()
96 return match, match.end()
99
97
100 try:
98 try:
101 itpl_encoding = sys.stdin.encoding or 'ascii'
99 itpl_encoding = sys.stdin.encoding or 'ascii'
102 except AttributeError:
100 except AttributeError:
103 itpl_encoding = 'ascii'
101 itpl_encoding = 'ascii'
104
102
105
103
106
104
107 class Itpl:
105 class Itpl:
108 """Class representing a string with interpolation abilities.
106 """Class representing a string with interpolation abilities.
109
107
110 Upon creation, an instance works out what parts of the format
108 Upon creation, an instance works out what parts of the format
111 string are literal and what parts need to be evaluated. The
109 string are literal and what parts need to be evaluated. The
112 evaluation and substitution happens in the namespace of the
110 evaluation and substitution happens in the namespace of the
113 caller when str(instance) is called."""
111 caller when str(instance) is called."""
114
112
115 def __init__(self, format,codec=itpl_encoding,encoding_errors='backslashreplace'):
113 def __init__(self, format,codec=itpl_encoding,encoding_errors='backslashreplace'):
116 """The single mandatory argument to this constructor is a format
114 """The single mandatory argument to this constructor is a format
117 string.
115 string.
118
116
119 The format string is parsed according to the following rules:
117 The format string is parsed according to the following rules:
120
118
121 1. A dollar sign and a name, possibly followed by any of:
119 1. A dollar sign and a name, possibly followed by any of:
122 - an open-paren, and anything up to the matching paren
120 - an open-paren, and anything up to the matching paren
123 - an open-bracket, and anything up to the matching bracket
121 - an open-bracket, and anything up to the matching bracket
124 - a period and a name
122 - a period and a name
125 any number of times, is evaluated as a Python expression.
123 any number of times, is evaluated as a Python expression.
126
124
127 2. A dollar sign immediately followed by an open-brace, and
125 2. A dollar sign immediately followed by an open-brace, and
128 anything up to the matching close-brace, is evaluated as
126 anything up to the matching close-brace, is evaluated as
129 a Python expression.
127 a Python expression.
130
128
131 3. Outside of the expressions described in the above two rules,
129 3. Outside of the expressions described in the above two rules,
132 two dollar signs in a row give you one literal dollar sign.
130 two dollar signs in a row give you one literal dollar sign.
133
131
134 Optional arguments:
132 Optional arguments:
135
133
136 - codec('utf_8'): a string containing the name of a valid Python
134 - codec('utf_8'): a string containing the name of a valid Python
137 codec.
135 codec.
138
136
139 - encoding_errors('backslashreplace'): a string with a valid error handling
137 - encoding_errors('backslashreplace'): a string with a valid error handling
140 policy. See the codecs module documentation for details.
138 policy. See the codecs module documentation for details.
141
139
142 These are used to encode the format string if a call to str() fails on
140 These are used to encode the format string if a call to str() fails on
143 the expanded result."""
141 the expanded result."""
144
142
145 if not isinstance(format,basestring):
143 if not isinstance(format,basestring):
146 raise TypeError, "needs string initializer"
144 raise TypeError, "needs string initializer"
147 self.format = format
145 self.format = format
148 self.codec = codec
146 self.codec = codec
149 self.encoding_errors = encoding_errors
147 self.encoding_errors = encoding_errors
150
148
151 namechars = "abcdefghijklmnopqrstuvwxyz" \
149 namechars = "abcdefghijklmnopqrstuvwxyz" \
152 "ABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789_";
150 "ABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789_";
153 chunks = []
151 chunks = []
154 pos = 0
152 pos = 0
155
153
156 while 1:
154 while 1:
157 dollar = string.find(format, "$", pos)
155 dollar = string.find(format, "$", pos)
158 if dollar < 0: break
156 if dollar < 0: break
159 nextchar = format[dollar+1]
157 nextchar = format[dollar+1]
160
158
161 if nextchar == "{":
159 if nextchar == "{":
162 chunks.append((0, format[pos:dollar]))
160 chunks.append((0, format[pos:dollar]))
163 pos, level = dollar+2, 1
161 pos, level = dollar+2, 1
164 while level:
162 while level:
165 match, pos = matchorfail(format, pos)
163 match, pos = matchorfail(format, pos)
166 tstart, tend = match.regs[3]
164 tstart, tend = match.regs[3]
167 token = format[tstart:tend]
165 token = format[tstart:tend]
168 if token == "{": level = level+1
166 if token == "{": level = level+1
169 elif token == "}": level = level-1
167 elif token == "}": level = level-1
170 chunks.append((1, format[dollar+2:pos-1]))
168 chunks.append((1, format[dollar+2:pos-1]))
171
169
172 elif nextchar in namechars:
170 elif nextchar in namechars:
173 chunks.append((0, format[pos:dollar]))
171 chunks.append((0, format[pos:dollar]))
174 match, pos = matchorfail(format, dollar+1)
172 match, pos = matchorfail(format, dollar+1)
175 while pos < len(format):
173 while pos < len(format):
176 if format[pos] == "." and \
174 if format[pos] == "." and \
177 pos+1 < len(format) and format[pos+1] in namechars:
175 pos+1 < len(format) and format[pos+1] in namechars:
178 match, pos = matchorfail(format, pos+1)
176 match, pos = matchorfail(format, pos+1)
179 elif format[pos] in "([":
177 elif format[pos] in "([":
180 pos, level = pos+1, 1
178 pos, level = pos+1, 1
181 while level:
179 while level:
182 match, pos = matchorfail(format, pos)
180 match, pos = matchorfail(format, pos)
183 tstart, tend = match.regs[3]
181 tstart, tend = match.regs[3]
184 token = format[tstart:tend]
182 token = format[tstart:tend]
185 if token[0] in "([": level = level+1
183 if token[0] in "([": level = level+1
186 elif token[0] in ")]": level = level-1
184 elif token[0] in ")]": level = level-1
187 else: break
185 else: break
188 chunks.append((1, format[dollar+1:pos]))
186 chunks.append((1, format[dollar+1:pos]))
189
187
190 else:
188 else:
191 chunks.append((0, format[pos:dollar+1]))
189 chunks.append((0, format[pos:dollar+1]))
192 pos = dollar + 1 + (nextchar == "$")
190 pos = dollar + 1 + (nextchar == "$")
193
191
194 if pos < len(format): chunks.append((0, format[pos:]))
192 if pos < len(format): chunks.append((0, format[pos:]))
195 self.chunks = chunks
193 self.chunks = chunks
196
194
197 def __repr__(self):
195 def __repr__(self):
198 return "<Itpl %s >" % repr(self.format)
196 return "<Itpl %s >" % repr(self.format)
199
197
200 def _str(self,glob,loc):
198 def _str(self,glob,loc):
201 """Evaluate to a string in the given globals/locals.
199 """Evaluate to a string in the given globals/locals.
202
200
203 The final output is built by calling str(), but if this fails, the
201 The final output is built by calling str(), but if this fails, the
204 result is encoded with the instance's codec and error handling policy,
202 result is encoded with the instance's codec and error handling policy,
205 via a call to out.encode(self.codec,self.encoding_errors)"""
203 via a call to out.encode(self.codec,self.encoding_errors)"""
206 result = []
204 result = []
207 app = result.append
205 app = result.append
208 for live, chunk in self.chunks:
206 for live, chunk in self.chunks:
209 if live:
207 if live:
210 val = eval(chunk,glob,loc)
208 val = eval(chunk,glob,loc)
211 try:
209 try:
212 app(str(val))
210 app(str(val))
213 except UnicodeEncodeError:
211 except UnicodeEncodeError:
214 app(unicode(val))
212 app(unicode(val))
215
213
216 else: app(chunk)
214 else: app(chunk)
217 out = ''.join(result)
215 out = ''.join(result)
218 try:
216 try:
219 return str(out)
217 return str(out)
220 except UnicodeError:
218 except UnicodeError:
221 return out.encode(self.codec,self.encoding_errors)
219 return out.encode(self.codec,self.encoding_errors)
222
220
223 def __str__(self):
221 def __str__(self):
224 """Evaluate and substitute the appropriate parts of the string."""
222 """Evaluate and substitute the appropriate parts of the string."""
225
223
226 # We need to skip enough frames to get to the actual caller outside of
224 # We need to skip enough frames to get to the actual caller outside of
227 # Itpl.
225 # Itpl.
228 frame = sys._getframe(1)
226 frame = sys._getframe(1)
229 while frame.f_globals["__name__"] == __name__: frame = frame.f_back
227 while frame.f_globals["__name__"] == __name__: frame = frame.f_back
230 loc, glob = frame.f_locals, frame.f_globals
228 loc, glob = frame.f_locals, frame.f_globals
231
229
232 return self._str(glob,loc)
230 return self._str(glob,loc)
233
231
234 class ItplNS(Itpl):
232 class ItplNS(Itpl):
235 """Class representing a string with interpolation abilities.
233 """Class representing a string with interpolation abilities.
236
234
237 This inherits from Itpl, but at creation time a namespace is provided
235 This inherits from Itpl, but at creation time a namespace is provided
238 where the evaluation will occur. The interpolation becomes a bit more
236 where the evaluation will occur. The interpolation becomes a bit more
239 efficient, as no traceback needs to be extracte. It also allows the
237 efficient, as no traceback needs to be extracte. It also allows the
240 caller to supply a different namespace for the interpolation to occur than
238 caller to supply a different namespace for the interpolation to occur than
241 its own."""
239 its own."""
242
240
243 def __init__(self, format,globals,locals=None,
241 def __init__(self, format,globals,locals=None,
244 codec='utf_8',encoding_errors='backslashreplace'):
242 codec='utf_8',encoding_errors='backslashreplace'):
245 """ItplNS(format,globals[,locals]) -> interpolating string instance.
243 """ItplNS(format,globals[,locals]) -> interpolating string instance.
246
244
247 This constructor, besides a format string, takes a globals dictionary
245 This constructor, besides a format string, takes a globals dictionary
248 and optionally a locals (which defaults to globals if not provided).
246 and optionally a locals (which defaults to globals if not provided).
249
247
250 For further details, see the Itpl constructor."""
248 For further details, see the Itpl constructor."""
251
249
252 if locals is None:
250 if locals is None:
253 locals = globals
251 locals = globals
254 self.globals = globals
252 self.globals = globals
255 self.locals = locals
253 self.locals = locals
256 Itpl.__init__(self,format,codec,encoding_errors)
254 Itpl.__init__(self,format,codec,encoding_errors)
257
255
258 def __str__(self):
256 def __str__(self):
259 """Evaluate and substitute the appropriate parts of the string."""
257 """Evaluate and substitute the appropriate parts of the string."""
260 return self._str(self.globals,self.locals)
258 return self._str(self.globals,self.locals)
261
259
262 def __repr__(self):
260 def __repr__(self):
263 return "<ItplNS %s >" % repr(self.format)
261 return "<ItplNS %s >" % repr(self.format)
264
262
265 # utilities for fast printing
263 # utilities for fast printing
266 def itpl(text): return str(Itpl(text))
264 def itpl(text): return str(Itpl(text))
267 def printpl(text): print itpl(text)
265 def printpl(text): print itpl(text)
268 # versions with namespace
266 # versions with namespace
269 def itplns(text,globals,locals=None): return str(ItplNS(text,globals,locals))
267 def itplns(text,globals,locals=None): return str(ItplNS(text,globals,locals))
270 def printplns(text,globals,locals=None): print itplns(text,globals,locals)
268 def printplns(text,globals,locals=None): print itplns(text,globals,locals)
271
269
272 class ItplFile:
270 class ItplFile:
273 """A file object that filters each write() through an interpolator."""
271 """A file object that filters each write() through an interpolator."""
274 def __init__(self, file): self.file = file
272 def __init__(self, file): self.file = file
275 def __repr__(self): return "<interpolated " + repr(self.file) + ">"
273 def __repr__(self): return "<interpolated " + repr(self.file) + ">"
276 def __getattr__(self, attr): return getattr(self.file, attr)
274 def __getattr__(self, attr): return getattr(self.file, attr)
277 def write(self, text): self.file.write(str(Itpl(text)))
275 def write(self, text): self.file.write(str(Itpl(text)))
278
276
279 def filter(file=sys.stdout):
277 def filter(file=sys.stdout):
280 """Return an ItplFile that filters writes to the given file object.
278 """Return an ItplFile that filters writes to the given file object.
281
279
282 'file = filter(file)' replaces 'file' with a filtered object that
280 'file = filter(file)' replaces 'file' with a filtered object that
283 has a write() method. When called with no argument, this creates
281 has a write() method. When called with no argument, this creates
284 a filter to sys.stdout."""
282 a filter to sys.stdout."""
285 return ItplFile(file)
283 return ItplFile(file)
286
284
287 def unfilter(ifile=None):
285 def unfilter(ifile=None):
288 """Return the original file that corresponds to the given ItplFile.
286 """Return the original file that corresponds to the given ItplFile.
289
287
290 'file = unfilter(file)' undoes the effect of 'file = filter(file)'.
288 'file = unfilter(file)' undoes the effect of 'file = filter(file)'.
291 'sys.stdout = unfilter()' undoes the effect of 'sys.stdout = filter()'."""
289 'sys.stdout = unfilter()' undoes the effect of 'sys.stdout = filter()'."""
292 return ifile and ifile.file or sys.stdout.file
290 return ifile and ifile.file or sys.stdout.file
@@ -1,270 +1,263 b''
1 # -*- coding: utf-8 -*-
1 # -*- coding: utf-8 -*-
2 """
2 """
3 Logger class for IPython's logging facilities.
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 # Copyright (C) 2001 Janko Hauser <jhauser@zscout.de> and
7 # Copyright (C) 2001 Janko Hauser <jhauser@zscout.de> and
10 # Copyright (C) 2001-2006 Fernando Perez <fperez@colorado.edu>
8 # Copyright (C) 2001-2006 Fernando Perez <fperez@colorado.edu>
11 #
9 #
12 # Distributed under the terms of the BSD License. The full license is in
10 # Distributed under the terms of the BSD License. The full license is in
13 # the file COPYING, distributed as part of this software.
11 # the file COPYING, distributed as part of this software.
14 #*****************************************************************************
12 #*****************************************************************************
15
13
16 #****************************************************************************
14 #****************************************************************************
17 # Modules and globals
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 # Python standard modules
17 # Python standard modules
25 import glob
18 import glob
26 import os
19 import os
27 import time
20 import time
28
21
29 #****************************************************************************
22 #****************************************************************************
30 # FIXME: This class isn't a mixin anymore, but it still needs attributes from
23 # FIXME: This class isn't a mixin anymore, but it still needs attributes from
31 # ipython and does input cache management. Finish cleanup later...
24 # ipython and does input cache management. Finish cleanup later...
32
25
33 class Logger(object):
26 class Logger(object):
34 """A Logfile class with different policies for file creation"""
27 """A Logfile class with different policies for file creation"""
35
28
36 def __init__(self,shell,logfname='Logger.log',loghead='',logmode='over'):
29 def __init__(self,shell,logfname='Logger.log',loghead='',logmode='over'):
37
30
38 self._i00,self._i,self._ii,self._iii = '','','',''
31 self._i00,self._i,self._ii,self._iii = '','','',''
39
32
40 # this is the full ipython instance, we need some attributes from it
33 # this is the full ipython instance, we need some attributes from it
41 # which won't exist until later. What a mess, clean up later...
34 # which won't exist until later. What a mess, clean up later...
42 self.shell = shell
35 self.shell = shell
43
36
44 self.logfname = logfname
37 self.logfname = logfname
45 self.loghead = loghead
38 self.loghead = loghead
46 self.logmode = logmode
39 self.logmode = logmode
47 self.logfile = None
40 self.logfile = None
48
41
49 # Whether to log raw or processed input
42 # Whether to log raw or processed input
50 self.log_raw_input = False
43 self.log_raw_input = False
51
44
52 # whether to also log output
45 # whether to also log output
53 self.log_output = False
46 self.log_output = False
54
47
55 # whether to put timestamps before each log entry
48 # whether to put timestamps before each log entry
56 self.timestamp = False
49 self.timestamp = False
57
50
58 # activity control flags
51 # activity control flags
59 self.log_active = False
52 self.log_active = False
60
53
61 # logmode is a validated property
54 # logmode is a validated property
62 def _set_mode(self,mode):
55 def _set_mode(self,mode):
63 if mode not in ['append','backup','global','over','rotate']:
56 if mode not in ['append','backup','global','over','rotate']:
64 raise ValueError,'invalid log mode %s given' % mode
57 raise ValueError,'invalid log mode %s given' % mode
65 self._logmode = mode
58 self._logmode = mode
66
59
67 def _get_mode(self):
60 def _get_mode(self):
68 return self._logmode
61 return self._logmode
69
62
70 logmode = property(_get_mode,_set_mode)
63 logmode = property(_get_mode,_set_mode)
71
64
72 def logstart(self,logfname=None,loghead=None,logmode=None,
65 def logstart(self,logfname=None,loghead=None,logmode=None,
73 log_output=False,timestamp=False,log_raw_input=False):
66 log_output=False,timestamp=False,log_raw_input=False):
74 """Generate a new log-file with a default header.
67 """Generate a new log-file with a default header.
75
68
76 Raises RuntimeError if the log has already been started"""
69 Raises RuntimeError if the log has already been started"""
77
70
78 if self.logfile is not None:
71 if self.logfile is not None:
79 raise RuntimeError('Log file is already active: %s' %
72 raise RuntimeError('Log file is already active: %s' %
80 self.logfname)
73 self.logfname)
81
74
82 self.log_active = True
75 self.log_active = True
83
76
84 # The parameters can override constructor defaults
77 # The parameters can override constructor defaults
85 if logfname is not None: self.logfname = logfname
78 if logfname is not None: self.logfname = logfname
86 if loghead is not None: self.loghead = loghead
79 if loghead is not None: self.loghead = loghead
87 if logmode is not None: self.logmode = logmode
80 if logmode is not None: self.logmode = logmode
88
81
89 # Parameters not part of the constructor
82 # Parameters not part of the constructor
90 self.timestamp = timestamp
83 self.timestamp = timestamp
91 self.log_output = log_output
84 self.log_output = log_output
92 self.log_raw_input = log_raw_input
85 self.log_raw_input = log_raw_input
93
86
94 # init depending on the log mode requested
87 # init depending on the log mode requested
95 isfile = os.path.isfile
88 isfile = os.path.isfile
96 logmode = self.logmode
89 logmode = self.logmode
97
90
98 if logmode == 'append':
91 if logmode == 'append':
99 self.logfile = open(self.logfname,'a')
92 self.logfile = open(self.logfname,'a')
100
93
101 elif logmode == 'backup':
94 elif logmode == 'backup':
102 if isfile(self.logfname):
95 if isfile(self.logfname):
103 backup_logname = self.logfname+'~'
96 backup_logname = self.logfname+'~'
104 # Manually remove any old backup, since os.rename may fail
97 # Manually remove any old backup, since os.rename may fail
105 # under Windows.
98 # under Windows.
106 if isfile(backup_logname):
99 if isfile(backup_logname):
107 os.remove(backup_logname)
100 os.remove(backup_logname)
108 os.rename(self.logfname,backup_logname)
101 os.rename(self.logfname,backup_logname)
109 self.logfile = open(self.logfname,'w')
102 self.logfile = open(self.logfname,'w')
110
103
111 elif logmode == 'global':
104 elif logmode == 'global':
112 self.logfname = os.path.join(self.shell.home_dir,self.logfname)
105 self.logfname = os.path.join(self.shell.home_dir,self.logfname)
113 self.logfile = open(self.logfname, 'a')
106 self.logfile = open(self.logfname, 'a')
114
107
115 elif logmode == 'over':
108 elif logmode == 'over':
116 if isfile(self.logfname):
109 if isfile(self.logfname):
117 os.remove(self.logfname)
110 os.remove(self.logfname)
118 self.logfile = open(self.logfname,'w')
111 self.logfile = open(self.logfname,'w')
119
112
120 elif logmode == 'rotate':
113 elif logmode == 'rotate':
121 if isfile(self.logfname):
114 if isfile(self.logfname):
122 if isfile(self.logfname+'.001~'):
115 if isfile(self.logfname+'.001~'):
123 old = glob.glob(self.logfname+'.*~')
116 old = glob.glob(self.logfname+'.*~')
124 old.sort()
117 old.sort()
125 old.reverse()
118 old.reverse()
126 for f in old:
119 for f in old:
127 root, ext = os.path.splitext(f)
120 root, ext = os.path.splitext(f)
128 num = int(ext[1:-1])+1
121 num = int(ext[1:-1])+1
129 os.rename(f, root+'.'+`num`.zfill(3)+'~')
122 os.rename(f, root+'.'+`num`.zfill(3)+'~')
130 os.rename(self.logfname, self.logfname+'.001~')
123 os.rename(self.logfname, self.logfname+'.001~')
131 self.logfile = open(self.logfname,'w')
124 self.logfile = open(self.logfname,'w')
132
125
133 if logmode != 'append':
126 if logmode != 'append':
134 self.logfile.write(self.loghead)
127 self.logfile.write(self.loghead)
135
128
136 self.logfile.flush()
129 self.logfile.flush()
137
130
138 def switch_log(self,val):
131 def switch_log(self,val):
139 """Switch logging on/off. val should be ONLY a boolean."""
132 """Switch logging on/off. val should be ONLY a boolean."""
140
133
141 if val not in [False,True,0,1]:
134 if val not in [False,True,0,1]:
142 raise ValueError, \
135 raise ValueError, \
143 'Call switch_log ONLY with a boolean argument, not with:',val
136 'Call switch_log ONLY with a boolean argument, not with:',val
144
137
145 label = {0:'OFF',1:'ON',False:'OFF',True:'ON'}
138 label = {0:'OFF',1:'ON',False:'OFF',True:'ON'}
146
139
147 if self.logfile is None:
140 if self.logfile is None:
148 print """
141 print """
149 Logging hasn't been started yet (use logstart for that).
142 Logging hasn't been started yet (use logstart for that).
150
143
151 %logon/%logoff are for temporarily starting and stopping logging for a logfile
144 %logon/%logoff are for temporarily starting and stopping logging for a logfile
152 which already exists. But you must first start the logging process with
145 which already exists. But you must first start the logging process with
153 %logstart (optionally giving a logfile name)."""
146 %logstart (optionally giving a logfile name)."""
154
147
155 else:
148 else:
156 if self.log_active == val:
149 if self.log_active == val:
157 print 'Logging is already',label[val]
150 print 'Logging is already',label[val]
158 else:
151 else:
159 print 'Switching logging',label[val]
152 print 'Switching logging',label[val]
160 self.log_active = not self.log_active
153 self.log_active = not self.log_active
161 self.log_active_out = self.log_active
154 self.log_active_out = self.log_active
162
155
163 def logstate(self):
156 def logstate(self):
164 """Print a status message about the logger."""
157 """Print a status message about the logger."""
165 if self.logfile is None:
158 if self.logfile is None:
166 print 'Logging has not been activated.'
159 print 'Logging has not been activated.'
167 else:
160 else:
168 state = self.log_active and 'active' or 'temporarily suspended'
161 state = self.log_active and 'active' or 'temporarily suspended'
169 print 'Filename :',self.logfname
162 print 'Filename :',self.logfname
170 print 'Mode :',self.logmode
163 print 'Mode :',self.logmode
171 print 'Output logging :',self.log_output
164 print 'Output logging :',self.log_output
172 print 'Raw input log :',self.log_raw_input
165 print 'Raw input log :',self.log_raw_input
173 print 'Timestamping :',self.timestamp
166 print 'Timestamping :',self.timestamp
174 print 'State :',state
167 print 'State :',state
175
168
176 def log(self,line_ori,line_mod,continuation=None):
169 def log(self,line_ori,line_mod,continuation=None):
177 """Write the line to a log and create input cache variables _i*.
170 """Write the line to a log and create input cache variables _i*.
178
171
179 Inputs:
172 Inputs:
180
173
181 - line_ori: unmodified input line from the user. This is not
174 - line_ori: unmodified input line from the user. This is not
182 necessarily valid Python.
175 necessarily valid Python.
183
176
184 - line_mod: possibly modified input, such as the transformations made
177 - line_mod: possibly modified input, such as the transformations made
185 by input prefilters or input handlers of various kinds. This should
178 by input prefilters or input handlers of various kinds. This should
186 always be valid Python.
179 always be valid Python.
187
180
188 - continuation: if True, indicates this is part of multi-line input."""
181 - continuation: if True, indicates this is part of multi-line input."""
189
182
190 # update the auto _i tables
183 # update the auto _i tables
191 #print '***logging line',line_mod # dbg
184 #print '***logging line',line_mod # dbg
192 #print '***cache_count', self.shell.outputcache.prompt_count # dbg
185 #print '***cache_count', self.shell.outputcache.prompt_count # dbg
193 try:
186 try:
194 input_hist = self.shell.user_ns['_ih']
187 input_hist = self.shell.user_ns['_ih']
195 except:
188 except:
196 #print 'userns:',self.shell.user_ns.keys() # dbg
189 #print 'userns:',self.shell.user_ns.keys() # dbg
197 return
190 return
198
191
199 out_cache = self.shell.outputcache
192 out_cache = self.shell.outputcache
200
193
201 # add blank lines if the input cache fell out of sync.
194 # add blank lines if the input cache fell out of sync.
202 if out_cache.do_full_cache and \
195 if out_cache.do_full_cache and \
203 out_cache.prompt_count +1 > len(input_hist):
196 out_cache.prompt_count +1 > len(input_hist):
204 input_hist.extend(['\n'] * (out_cache.prompt_count - len(input_hist)))
197 input_hist.extend(['\n'] * (out_cache.prompt_count - len(input_hist)))
205
198
206 if not continuation and line_mod:
199 if not continuation and line_mod:
207 self._iii = self._ii
200 self._iii = self._ii
208 self._ii = self._i
201 self._ii = self._i
209 self._i = self._i00
202 self._i = self._i00
210 # put back the final \n of every input line
203 # put back the final \n of every input line
211 self._i00 = line_mod+'\n'
204 self._i00 = line_mod+'\n'
212 #print 'Logging input:<%s>' % line_mod # dbg
205 #print 'Logging input:<%s>' % line_mod # dbg
213 input_hist.append(self._i00)
206 input_hist.append(self._i00)
214 #print '---[%s]' % (len(input_hist)-1,) # dbg
207 #print '---[%s]' % (len(input_hist)-1,) # dbg
215
208
216 # hackish access to top-level namespace to create _i1,_i2... dynamically
209 # hackish access to top-level namespace to create _i1,_i2... dynamically
217 to_main = {'_i':self._i,'_ii':self._ii,'_iii':self._iii}
210 to_main = {'_i':self._i,'_ii':self._ii,'_iii':self._iii}
218 if self.shell.outputcache.do_full_cache:
211 if self.shell.outputcache.do_full_cache:
219 in_num = self.shell.outputcache.prompt_count
212 in_num = self.shell.outputcache.prompt_count
220
213
221 # but if the opposite is true (a macro can produce multiple inputs
214 # but if the opposite is true (a macro can produce multiple inputs
222 # with no output display called), then bring the output counter in
215 # with no output display called), then bring the output counter in
223 # sync:
216 # sync:
224 last_num = len(input_hist)-1
217 last_num = len(input_hist)-1
225 if in_num != last_num:
218 if in_num != last_num:
226 in_num = self.shell.outputcache.prompt_count = last_num
219 in_num = self.shell.outputcache.prompt_count = last_num
227 new_i = '_i%s' % in_num
220 new_i = '_i%s' % in_num
228 if continuation:
221 if continuation:
229 self._i00 = '%s%s\n' % (self.shell.user_ns[new_i],line_mod)
222 self._i00 = '%s%s\n' % (self.shell.user_ns[new_i],line_mod)
230 input_hist[in_num] = self._i00
223 input_hist[in_num] = self._i00
231 to_main[new_i] = self._i00
224 to_main[new_i] = self._i00
232 self.shell.user_ns.update(to_main)
225 self.shell.user_ns.update(to_main)
233
226
234 # Write the log line, but decide which one according to the
227 # Write the log line, but decide which one according to the
235 # log_raw_input flag, set when the log is started.
228 # log_raw_input flag, set when the log is started.
236 if self.log_raw_input:
229 if self.log_raw_input:
237 self.log_write(line_ori)
230 self.log_write(line_ori)
238 else:
231 else:
239 self.log_write(line_mod)
232 self.log_write(line_mod)
240
233
241 def log_write(self,data,kind='input'):
234 def log_write(self,data,kind='input'):
242 """Write data to the log file, if active"""
235 """Write data to the log file, if active"""
243
236
244 #print 'data: %r' % data # dbg
237 #print 'data: %r' % data # dbg
245 if self.log_active and data:
238 if self.log_active and data:
246 write = self.logfile.write
239 write = self.logfile.write
247 if kind=='input':
240 if kind=='input':
248 if self.timestamp:
241 if self.timestamp:
249 write(time.strftime('# %a, %d %b %Y %H:%M:%S\n',
242 write(time.strftime('# %a, %d %b %Y %H:%M:%S\n',
250 time.localtime()))
243 time.localtime()))
251 write('%s\n' % data)
244 write('%s\n' % data)
252 elif kind=='output' and self.log_output:
245 elif kind=='output' and self.log_output:
253 odata = '\n'.join(['#[Out]# %s' % s
246 odata = '\n'.join(['#[Out]# %s' % s
254 for s in data.split('\n')])
247 for s in data.split('\n')])
255 write('%s\n' % odata)
248 write('%s\n' % odata)
256 self.logfile.flush()
249 self.logfile.flush()
257
250
258 def logstop(self):
251 def logstop(self):
259 """Fully stop logging and close log file.
252 """Fully stop logging and close log file.
260
253
261 In order to start logging again, a new logstart() call needs to be
254 In order to start logging again, a new logstart() call needs to be
262 made, possibly (though not necessarily) with a new filename, mode and
255 made, possibly (though not necessarily) with a new filename, mode and
263 other options."""
256 other options."""
264
257
265 self.logfile.close()
258 self.logfile.close()
266 self.logfile = None
259 self.logfile = None
267 self.log_active = False
260 self.log_active = False
268
261
269 # For backwards compatibility, in case anyone was using this.
262 # For backwards compatibility, in case anyone was using this.
270 close_log = logstop
263 close_log = logstop
@@ -1,3416 +1,3415 b''
1 # -*- coding: utf-8 -*-
1 # -*- coding: utf-8 -*-
2 """Magic functions for InteractiveShell.
2 """Magic functions for InteractiveShell.
3
3 """
4 $Id: Magic.py 2996 2008-01-30 06:31:39Z fperez $"""
5
4
6 #*****************************************************************************
5 #*****************************************************************************
7 # Copyright (C) 2001 Janko Hauser <jhauser@zscout.de> and
6 # Copyright (C) 2001 Janko Hauser <jhauser@zscout.de> and
8 # Copyright (C) 2001-2006 Fernando Perez <fperez@colorado.edu>
7 # Copyright (C) 2001-2006 Fernando Perez <fperez@colorado.edu>
9 #
8 #
10 # Distributed under the terms of the BSD License. The full license is in
9 # Distributed under the terms of the BSD License. The full license is in
11 # the file COPYING, distributed as part of this software.
10 # the file COPYING, distributed as part of this software.
12 #*****************************************************************************
11 #*****************************************************************************
13
12
14 #****************************************************************************
13 #****************************************************************************
15 # Modules and globals
14 # Modules and globals
16
15
17 from IPython import Release
16 from IPython import Release
18 __author__ = '%s <%s>\n%s <%s>' % \
17 __author__ = '%s <%s>\n%s <%s>' % \
19 ( Release.authors['Janko'] + Release.authors['Fernando'] )
18 ( Release.authors['Janko'] + Release.authors['Fernando'] )
20 __license__ = Release.license
19 __license__ = Release.license
21
20
22 # Python standard modules
21 # Python standard modules
23 import __builtin__
22 import __builtin__
24 import bdb
23 import bdb
25 import inspect
24 import inspect
26 import os
25 import os
27 import pdb
26 import pdb
28 import pydoc
27 import pydoc
29 import sys
28 import sys
30 import re
29 import re
31 import tempfile
30 import tempfile
32 import time
31 import time
33 import cPickle as pickle
32 import cPickle as pickle
34 import textwrap
33 import textwrap
35 from cStringIO import StringIO
34 from cStringIO import StringIO
36 from getopt import getopt,GetoptError
35 from getopt import getopt,GetoptError
37 from pprint import pprint, pformat
36 from pprint import pprint, pformat
38 from sets import Set
37 from sets import Set
39
38
40 # cProfile was added in Python2.5
39 # cProfile was added in Python2.5
41 try:
40 try:
42 import cProfile as profile
41 import cProfile as profile
43 import pstats
42 import pstats
44 except ImportError:
43 except ImportError:
45 # profile isn't bundled by default in Debian for license reasons
44 # profile isn't bundled by default in Debian for license reasons
46 try:
45 try:
47 import profile,pstats
46 import profile,pstats
48 except ImportError:
47 except ImportError:
49 profile = pstats = None
48 profile = pstats = None
50
49
51 # Homebrewed
50 # Homebrewed
52 import IPython
51 import IPython
53 from IPython import Debugger, OInspect, wildcard
52 from IPython import Debugger, OInspect, wildcard
54 from IPython.FakeModule import FakeModule
53 from IPython.FakeModule import FakeModule
55 from IPython.Itpl import Itpl, itpl, printpl,itplns
54 from IPython.Itpl import Itpl, itpl, printpl,itplns
56 from IPython.PyColorize import Parser
55 from IPython.PyColorize import Parser
57 from IPython.ipstruct import Struct
56 from IPython.ipstruct import Struct
58 from IPython.macro import Macro
57 from IPython.macro import Macro
59 from IPython.genutils import *
58 from IPython.genutils import *
60 from IPython import platutils
59 from IPython import platutils
61 import IPython.generics
60 import IPython.generics
62 import IPython.ipapi
61 import IPython.ipapi
63 from IPython.ipapi import UsageError
62 from IPython.ipapi import UsageError
64 from IPython.testing import decorators as testdec
63 from IPython.testing import decorators as testdec
65
64
66 #***************************************************************************
65 #***************************************************************************
67 # Utility functions
66 # Utility functions
68 def on_off(tag):
67 def on_off(tag):
69 """Return an ON/OFF string for a 1/0 input. Simple utility function."""
68 """Return an ON/OFF string for a 1/0 input. Simple utility function."""
70 return ['OFF','ON'][tag]
69 return ['OFF','ON'][tag]
71
70
72 class Bunch: pass
71 class Bunch: pass
73
72
74 def compress_dhist(dh):
73 def compress_dhist(dh):
75 head, tail = dh[:-10], dh[-10:]
74 head, tail = dh[:-10], dh[-10:]
76
75
77 newhead = []
76 newhead = []
78 done = Set()
77 done = Set()
79 for h in head:
78 for h in head:
80 if h in done:
79 if h in done:
81 continue
80 continue
82 newhead.append(h)
81 newhead.append(h)
83 done.add(h)
82 done.add(h)
84
83
85 return newhead + tail
84 return newhead + tail
86
85
87
86
88 #***************************************************************************
87 #***************************************************************************
89 # Main class implementing Magic functionality
88 # Main class implementing Magic functionality
90 class Magic:
89 class Magic:
91 """Magic functions for InteractiveShell.
90 """Magic functions for InteractiveShell.
92
91
93 Shell functions which can be reached as %function_name. All magic
92 Shell functions which can be reached as %function_name. All magic
94 functions should accept a string, which they can parse for their own
93 functions should accept a string, which they can parse for their own
95 needs. This can make some functions easier to type, eg `%cd ../`
94 needs. This can make some functions easier to type, eg `%cd ../`
96 vs. `%cd("../")`
95 vs. `%cd("../")`
97
96
98 ALL definitions MUST begin with the prefix magic_. The user won't need it
97 ALL definitions MUST begin with the prefix magic_. The user won't need it
99 at the command line, but it is is needed in the definition. """
98 at the command line, but it is is needed in the definition. """
100
99
101 # class globals
100 # class globals
102 auto_status = ['Automagic is OFF, % prefix IS needed for magic functions.',
101 auto_status = ['Automagic is OFF, % prefix IS needed for magic functions.',
103 'Automagic is ON, % prefix NOT needed for magic functions.']
102 'Automagic is ON, % prefix NOT needed for magic functions.']
104
103
105 #......................................................................
104 #......................................................................
106 # some utility functions
105 # some utility functions
107
106
108 def __init__(self,shell):
107 def __init__(self,shell):
109
108
110 self.options_table = {}
109 self.options_table = {}
111 if profile is None:
110 if profile is None:
112 self.magic_prun = self.profile_missing_notice
111 self.magic_prun = self.profile_missing_notice
113 self.shell = shell
112 self.shell = shell
114
113
115 # namespace for holding state we may need
114 # namespace for holding state we may need
116 self._magic_state = Bunch()
115 self._magic_state = Bunch()
117
116
118 def profile_missing_notice(self, *args, **kwargs):
117 def profile_missing_notice(self, *args, **kwargs):
119 error("""\
118 error("""\
120 The profile module could not be found. It has been removed from the standard
119 The profile module could not be found. It has been removed from the standard
121 python packages because of its non-free license. To use profiling, install the
120 python packages because of its non-free license. To use profiling, install the
122 python-profiler package from non-free.""")
121 python-profiler package from non-free.""")
123
122
124 def default_option(self,fn,optstr):
123 def default_option(self,fn,optstr):
125 """Make an entry in the options_table for fn, with value optstr"""
124 """Make an entry in the options_table for fn, with value optstr"""
126
125
127 if fn not in self.lsmagic():
126 if fn not in self.lsmagic():
128 error("%s is not a magic function" % fn)
127 error("%s is not a magic function" % fn)
129 self.options_table[fn] = optstr
128 self.options_table[fn] = optstr
130
129
131 def lsmagic(self):
130 def lsmagic(self):
132 """Return a list of currently available magic functions.
131 """Return a list of currently available magic functions.
133
132
134 Gives a list of the bare names after mangling (['ls','cd', ...], not
133 Gives a list of the bare names after mangling (['ls','cd', ...], not
135 ['magic_ls','magic_cd',...]"""
134 ['magic_ls','magic_cd',...]"""
136
135
137 # FIXME. This needs a cleanup, in the way the magics list is built.
136 # FIXME. This needs a cleanup, in the way the magics list is built.
138
137
139 # magics in class definition
138 # magics in class definition
140 class_magic = lambda fn: fn.startswith('magic_') and \
139 class_magic = lambda fn: fn.startswith('magic_') and \
141 callable(Magic.__dict__[fn])
140 callable(Magic.__dict__[fn])
142 # in instance namespace (run-time user additions)
141 # in instance namespace (run-time user additions)
143 inst_magic = lambda fn: fn.startswith('magic_') and \
142 inst_magic = lambda fn: fn.startswith('magic_') and \
144 callable(self.__dict__[fn])
143 callable(self.__dict__[fn])
145 # and bound magics by user (so they can access self):
144 # and bound magics by user (so they can access self):
146 inst_bound_magic = lambda fn: fn.startswith('magic_') and \
145 inst_bound_magic = lambda fn: fn.startswith('magic_') and \
147 callable(self.__class__.__dict__[fn])
146 callable(self.__class__.__dict__[fn])
148 magics = filter(class_magic,Magic.__dict__.keys()) + \
147 magics = filter(class_magic,Magic.__dict__.keys()) + \
149 filter(inst_magic,self.__dict__.keys()) + \
148 filter(inst_magic,self.__dict__.keys()) + \
150 filter(inst_bound_magic,self.__class__.__dict__.keys())
149 filter(inst_bound_magic,self.__class__.__dict__.keys())
151 out = []
150 out = []
152 for fn in Set(magics):
151 for fn in Set(magics):
153 out.append(fn.replace('magic_','',1))
152 out.append(fn.replace('magic_','',1))
154 out.sort()
153 out.sort()
155 return out
154 return out
156
155
157 def extract_input_slices(self,slices,raw=False):
156 def extract_input_slices(self,slices,raw=False):
158 """Return as a string a set of input history slices.
157 """Return as a string a set of input history slices.
159
158
160 Inputs:
159 Inputs:
161
160
162 - slices: the set of slices is given as a list of strings (like
161 - slices: the set of slices is given as a list of strings (like
163 ['1','4:8','9'], since this function is for use by magic functions
162 ['1','4:8','9'], since this function is for use by magic functions
164 which get their arguments as strings.
163 which get their arguments as strings.
165
164
166 Optional inputs:
165 Optional inputs:
167
166
168 - raw(False): by default, the processed input is used. If this is
167 - raw(False): by default, the processed input is used. If this is
169 true, the raw input history is used instead.
168 true, the raw input history is used instead.
170
169
171 Note that slices can be called with two notations:
170 Note that slices can be called with two notations:
172
171
173 N:M -> standard python form, means including items N...(M-1).
172 N:M -> standard python form, means including items N...(M-1).
174
173
175 N-M -> include items N..M (closed endpoint)."""
174 N-M -> include items N..M (closed endpoint)."""
176
175
177 if raw:
176 if raw:
178 hist = self.shell.input_hist_raw
177 hist = self.shell.input_hist_raw
179 else:
178 else:
180 hist = self.shell.input_hist
179 hist = self.shell.input_hist
181
180
182 cmds = []
181 cmds = []
183 for chunk in slices:
182 for chunk in slices:
184 if ':' in chunk:
183 if ':' in chunk:
185 ini,fin = map(int,chunk.split(':'))
184 ini,fin = map(int,chunk.split(':'))
186 elif '-' in chunk:
185 elif '-' in chunk:
187 ini,fin = map(int,chunk.split('-'))
186 ini,fin = map(int,chunk.split('-'))
188 fin += 1
187 fin += 1
189 else:
188 else:
190 ini = int(chunk)
189 ini = int(chunk)
191 fin = ini+1
190 fin = ini+1
192 cmds.append(hist[ini:fin])
191 cmds.append(hist[ini:fin])
193 return cmds
192 return cmds
194
193
195 def _ofind(self, oname, namespaces=None):
194 def _ofind(self, oname, namespaces=None):
196 """Find an object in the available namespaces.
195 """Find an object in the available namespaces.
197
196
198 self._ofind(oname) -> dict with keys: found,obj,ospace,ismagic
197 self._ofind(oname) -> dict with keys: found,obj,ospace,ismagic
199
198
200 Has special code to detect magic functions.
199 Has special code to detect magic functions.
201 """
200 """
202
201
203 oname = oname.strip()
202 oname = oname.strip()
204
203
205 alias_ns = None
204 alias_ns = None
206 if namespaces is None:
205 if namespaces is None:
207 # Namespaces to search in:
206 # Namespaces to search in:
208 # Put them in a list. The order is important so that we
207 # Put them in a list. The order is important so that we
209 # find things in the same order that Python finds them.
208 # find things in the same order that Python finds them.
210 namespaces = [ ('Interactive', self.shell.user_ns),
209 namespaces = [ ('Interactive', self.shell.user_ns),
211 ('IPython internal', self.shell.internal_ns),
210 ('IPython internal', self.shell.internal_ns),
212 ('Python builtin', __builtin__.__dict__),
211 ('Python builtin', __builtin__.__dict__),
213 ('Alias', self.shell.alias_table),
212 ('Alias', self.shell.alias_table),
214 ]
213 ]
215 alias_ns = self.shell.alias_table
214 alias_ns = self.shell.alias_table
216
215
217 # initialize results to 'null'
216 # initialize results to 'null'
218 found = 0; obj = None; ospace = None; ds = None;
217 found = 0; obj = None; ospace = None; ds = None;
219 ismagic = 0; isalias = 0; parent = None
218 ismagic = 0; isalias = 0; parent = None
220
219
221 # Look for the given name by splitting it in parts. If the head is
220 # Look for the given name by splitting it in parts. If the head is
222 # found, then we look for all the remaining parts as members, and only
221 # found, then we look for all the remaining parts as members, and only
223 # declare success if we can find them all.
222 # declare success if we can find them all.
224 oname_parts = oname.split('.')
223 oname_parts = oname.split('.')
225 oname_head, oname_rest = oname_parts[0],oname_parts[1:]
224 oname_head, oname_rest = oname_parts[0],oname_parts[1:]
226 for nsname,ns in namespaces:
225 for nsname,ns in namespaces:
227 try:
226 try:
228 obj = ns[oname_head]
227 obj = ns[oname_head]
229 except KeyError:
228 except KeyError:
230 continue
229 continue
231 else:
230 else:
232 #print 'oname_rest:', oname_rest # dbg
231 #print 'oname_rest:', oname_rest # dbg
233 for part in oname_rest:
232 for part in oname_rest:
234 try:
233 try:
235 parent = obj
234 parent = obj
236 obj = getattr(obj,part)
235 obj = getattr(obj,part)
237 except:
236 except:
238 # Blanket except b/c some badly implemented objects
237 # Blanket except b/c some badly implemented objects
239 # allow __getattr__ to raise exceptions other than
238 # allow __getattr__ to raise exceptions other than
240 # AttributeError, which then crashes IPython.
239 # AttributeError, which then crashes IPython.
241 break
240 break
242 else:
241 else:
243 # If we finish the for loop (no break), we got all members
242 # If we finish the for loop (no break), we got all members
244 found = 1
243 found = 1
245 ospace = nsname
244 ospace = nsname
246 if ns == alias_ns:
245 if ns == alias_ns:
247 isalias = 1
246 isalias = 1
248 break # namespace loop
247 break # namespace loop
249
248
250 # Try to see if it's magic
249 # Try to see if it's magic
251 if not found:
250 if not found:
252 if oname.startswith(self.shell.ESC_MAGIC):
251 if oname.startswith(self.shell.ESC_MAGIC):
253 oname = oname[1:]
252 oname = oname[1:]
254 obj = getattr(self,'magic_'+oname,None)
253 obj = getattr(self,'magic_'+oname,None)
255 if obj is not None:
254 if obj is not None:
256 found = 1
255 found = 1
257 ospace = 'IPython internal'
256 ospace = 'IPython internal'
258 ismagic = 1
257 ismagic = 1
259
258
260 # Last try: special-case some literals like '', [], {}, etc:
259 # Last try: special-case some literals like '', [], {}, etc:
261 if not found and oname_head in ["''",'""','[]','{}','()']:
260 if not found and oname_head in ["''",'""','[]','{}','()']:
262 obj = eval(oname_head)
261 obj = eval(oname_head)
263 found = 1
262 found = 1
264 ospace = 'Interactive'
263 ospace = 'Interactive'
265
264
266 return {'found':found, 'obj':obj, 'namespace':ospace,
265 return {'found':found, 'obj':obj, 'namespace':ospace,
267 'ismagic':ismagic, 'isalias':isalias, 'parent':parent}
266 'ismagic':ismagic, 'isalias':isalias, 'parent':parent}
268
267
269 def arg_err(self,func):
268 def arg_err(self,func):
270 """Print docstring if incorrect arguments were passed"""
269 """Print docstring if incorrect arguments were passed"""
271 print 'Error in arguments:'
270 print 'Error in arguments:'
272 print OInspect.getdoc(func)
271 print OInspect.getdoc(func)
273
272
274 def format_latex(self,strng):
273 def format_latex(self,strng):
275 """Format a string for latex inclusion."""
274 """Format a string for latex inclusion."""
276
275
277 # Characters that need to be escaped for latex:
276 # Characters that need to be escaped for latex:
278 escape_re = re.compile(r'(%|_|\$|#|&)',re.MULTILINE)
277 escape_re = re.compile(r'(%|_|\$|#|&)',re.MULTILINE)
279 # Magic command names as headers:
278 # Magic command names as headers:
280 cmd_name_re = re.compile(r'^(%s.*?):' % self.shell.ESC_MAGIC,
279 cmd_name_re = re.compile(r'^(%s.*?):' % self.shell.ESC_MAGIC,
281 re.MULTILINE)
280 re.MULTILINE)
282 # Magic commands
281 # Magic commands
283 cmd_re = re.compile(r'(?P<cmd>%s.+?\b)(?!\}\}:)' % self.shell.ESC_MAGIC,
282 cmd_re = re.compile(r'(?P<cmd>%s.+?\b)(?!\}\}:)' % self.shell.ESC_MAGIC,
284 re.MULTILINE)
283 re.MULTILINE)
285 # Paragraph continue
284 # Paragraph continue
286 par_re = re.compile(r'\\$',re.MULTILINE)
285 par_re = re.compile(r'\\$',re.MULTILINE)
287
286
288 # The "\n" symbol
287 # The "\n" symbol
289 newline_re = re.compile(r'\\n')
288 newline_re = re.compile(r'\\n')
290
289
291 # Now build the string for output:
290 # Now build the string for output:
292 #strng = cmd_name_re.sub(r'\n\\texttt{\\textsl{\\large \1}}:',strng)
291 #strng = cmd_name_re.sub(r'\n\\texttt{\\textsl{\\large \1}}:',strng)
293 strng = cmd_name_re.sub(r'\n\\bigskip\n\\texttt{\\textbf{ \1}}:',
292 strng = cmd_name_re.sub(r'\n\\bigskip\n\\texttt{\\textbf{ \1}}:',
294 strng)
293 strng)
295 strng = cmd_re.sub(r'\\texttt{\g<cmd>}',strng)
294 strng = cmd_re.sub(r'\\texttt{\g<cmd>}',strng)
296 strng = par_re.sub(r'\\\\',strng)
295 strng = par_re.sub(r'\\\\',strng)
297 strng = escape_re.sub(r'\\\1',strng)
296 strng = escape_re.sub(r'\\\1',strng)
298 strng = newline_re.sub(r'\\textbackslash{}n',strng)
297 strng = newline_re.sub(r'\\textbackslash{}n',strng)
299 return strng
298 return strng
300
299
301 def format_screen(self,strng):
300 def format_screen(self,strng):
302 """Format a string for screen printing.
301 """Format a string for screen printing.
303
302
304 This removes some latex-type format codes."""
303 This removes some latex-type format codes."""
305 # Paragraph continue
304 # Paragraph continue
306 par_re = re.compile(r'\\$',re.MULTILINE)
305 par_re = re.compile(r'\\$',re.MULTILINE)
307 strng = par_re.sub('',strng)
306 strng = par_re.sub('',strng)
308 return strng
307 return strng
309
308
310 def parse_options(self,arg_str,opt_str,*long_opts,**kw):
309 def parse_options(self,arg_str,opt_str,*long_opts,**kw):
311 """Parse options passed to an argument string.
310 """Parse options passed to an argument string.
312
311
313 The interface is similar to that of getopt(), but it returns back a
312 The interface is similar to that of getopt(), but it returns back a
314 Struct with the options as keys and the stripped argument string still
313 Struct with the options as keys and the stripped argument string still
315 as a string.
314 as a string.
316
315
317 arg_str is quoted as a true sys.argv vector by using shlex.split.
316 arg_str is quoted as a true sys.argv vector by using shlex.split.
318 This allows us to easily expand variables, glob files, quote
317 This allows us to easily expand variables, glob files, quote
319 arguments, etc.
318 arguments, etc.
320
319
321 Options:
320 Options:
322 -mode: default 'string'. If given as 'list', the argument string is
321 -mode: default 'string'. If given as 'list', the argument string is
323 returned as a list (split on whitespace) instead of a string.
322 returned as a list (split on whitespace) instead of a string.
324
323
325 -list_all: put all option values in lists. Normally only options
324 -list_all: put all option values in lists. Normally only options
326 appearing more than once are put in a list.
325 appearing more than once are put in a list.
327
326
328 -posix (True): whether to split the input line in POSIX mode or not,
327 -posix (True): whether to split the input line in POSIX mode or not,
329 as per the conventions outlined in the shlex module from the
328 as per the conventions outlined in the shlex module from the
330 standard library."""
329 standard library."""
331
330
332 # inject default options at the beginning of the input line
331 # inject default options at the beginning of the input line
333 caller = sys._getframe(1).f_code.co_name.replace('magic_','')
332 caller = sys._getframe(1).f_code.co_name.replace('magic_','')
334 arg_str = '%s %s' % (self.options_table.get(caller,''),arg_str)
333 arg_str = '%s %s' % (self.options_table.get(caller,''),arg_str)
335
334
336 mode = kw.get('mode','string')
335 mode = kw.get('mode','string')
337 if mode not in ['string','list']:
336 if mode not in ['string','list']:
338 raise ValueError,'incorrect mode given: %s' % mode
337 raise ValueError,'incorrect mode given: %s' % mode
339 # Get options
338 # Get options
340 list_all = kw.get('list_all',0)
339 list_all = kw.get('list_all',0)
341 posix = kw.get('posix',True)
340 posix = kw.get('posix',True)
342
341
343 # Check if we have more than one argument to warrant extra processing:
342 # Check if we have more than one argument to warrant extra processing:
344 odict = {} # Dictionary with options
343 odict = {} # Dictionary with options
345 args = arg_str.split()
344 args = arg_str.split()
346 if len(args) >= 1:
345 if len(args) >= 1:
347 # If the list of inputs only has 0 or 1 thing in it, there's no
346 # If the list of inputs only has 0 or 1 thing in it, there's no
348 # need to look for options
347 # need to look for options
349 argv = arg_split(arg_str,posix)
348 argv = arg_split(arg_str,posix)
350 # Do regular option processing
349 # Do regular option processing
351 try:
350 try:
352 opts,args = getopt(argv,opt_str,*long_opts)
351 opts,args = getopt(argv,opt_str,*long_opts)
353 except GetoptError,e:
352 except GetoptError,e:
354 raise UsageError('%s ( allowed: "%s" %s)' % (e.msg,opt_str,
353 raise UsageError('%s ( allowed: "%s" %s)' % (e.msg,opt_str,
355 " ".join(long_opts)))
354 " ".join(long_opts)))
356 for o,a in opts:
355 for o,a in opts:
357 if o.startswith('--'):
356 if o.startswith('--'):
358 o = o[2:]
357 o = o[2:]
359 else:
358 else:
360 o = o[1:]
359 o = o[1:]
361 try:
360 try:
362 odict[o].append(a)
361 odict[o].append(a)
363 except AttributeError:
362 except AttributeError:
364 odict[o] = [odict[o],a]
363 odict[o] = [odict[o],a]
365 except KeyError:
364 except KeyError:
366 if list_all:
365 if list_all:
367 odict[o] = [a]
366 odict[o] = [a]
368 else:
367 else:
369 odict[o] = a
368 odict[o] = a
370
369
371 # Prepare opts,args for return
370 # Prepare opts,args for return
372 opts = Struct(odict)
371 opts = Struct(odict)
373 if mode == 'string':
372 if mode == 'string':
374 args = ' '.join(args)
373 args = ' '.join(args)
375
374
376 return opts,args
375 return opts,args
377
376
378 #......................................................................
377 #......................................................................
379 # And now the actual magic functions
378 # And now the actual magic functions
380
379
381 # Functions for IPython shell work (vars,funcs, config, etc)
380 # Functions for IPython shell work (vars,funcs, config, etc)
382 def magic_lsmagic(self, parameter_s = ''):
381 def magic_lsmagic(self, parameter_s = ''):
383 """List currently available magic functions."""
382 """List currently available magic functions."""
384 mesc = self.shell.ESC_MAGIC
383 mesc = self.shell.ESC_MAGIC
385 print 'Available magic functions:\n'+mesc+\
384 print 'Available magic functions:\n'+mesc+\
386 (' '+mesc).join(self.lsmagic())
385 (' '+mesc).join(self.lsmagic())
387 print '\n' + Magic.auto_status[self.shell.rc.automagic]
386 print '\n' + Magic.auto_status[self.shell.rc.automagic]
388 return None
387 return None
389
388
390 def magic_magic(self, parameter_s = ''):
389 def magic_magic(self, parameter_s = ''):
391 """Print information about the magic function system.
390 """Print information about the magic function system.
392
391
393 Supported formats: -latex, -brief, -rest
392 Supported formats: -latex, -brief, -rest
394 """
393 """
395
394
396 mode = ''
395 mode = ''
397 try:
396 try:
398 if parameter_s.split()[0] == '-latex':
397 if parameter_s.split()[0] == '-latex':
399 mode = 'latex'
398 mode = 'latex'
400 if parameter_s.split()[0] == '-brief':
399 if parameter_s.split()[0] == '-brief':
401 mode = 'brief'
400 mode = 'brief'
402 if parameter_s.split()[0] == '-rest':
401 if parameter_s.split()[0] == '-rest':
403 mode = 'rest'
402 mode = 'rest'
404 rest_docs = []
403 rest_docs = []
405 except:
404 except:
406 pass
405 pass
407
406
408 magic_docs = []
407 magic_docs = []
409 for fname in self.lsmagic():
408 for fname in self.lsmagic():
410 mname = 'magic_' + fname
409 mname = 'magic_' + fname
411 for space in (Magic,self,self.__class__):
410 for space in (Magic,self,self.__class__):
412 try:
411 try:
413 fn = space.__dict__[mname]
412 fn = space.__dict__[mname]
414 except KeyError:
413 except KeyError:
415 pass
414 pass
416 else:
415 else:
417 break
416 break
418 if mode == 'brief':
417 if mode == 'brief':
419 # only first line
418 # only first line
420 if fn.__doc__:
419 if fn.__doc__:
421 fndoc = fn.__doc__.split('\n',1)[0]
420 fndoc = fn.__doc__.split('\n',1)[0]
422 else:
421 else:
423 fndoc = 'No documentation'
422 fndoc = 'No documentation'
424 else:
423 else:
425 fndoc = fn.__doc__.rstrip()
424 fndoc = fn.__doc__.rstrip()
426
425
427 if mode == 'rest':
426 if mode == 'rest':
428 rest_docs.append('**%s%s**::\n\n\t%s\n\n' %(self.shell.ESC_MAGIC,
427 rest_docs.append('**%s%s**::\n\n\t%s\n\n' %(self.shell.ESC_MAGIC,
429 fname,fndoc))
428 fname,fndoc))
430
429
431 else:
430 else:
432 magic_docs.append('%s%s:\n\t%s\n' %(self.shell.ESC_MAGIC,
431 magic_docs.append('%s%s:\n\t%s\n' %(self.shell.ESC_MAGIC,
433 fname,fndoc))
432 fname,fndoc))
434
433
435 magic_docs = ''.join(magic_docs)
434 magic_docs = ''.join(magic_docs)
436
435
437 if mode == 'rest':
436 if mode == 'rest':
438 return "".join(rest_docs)
437 return "".join(rest_docs)
439
438
440 if mode == 'latex':
439 if mode == 'latex':
441 print self.format_latex(magic_docs)
440 print self.format_latex(magic_docs)
442 return
441 return
443 else:
442 else:
444 magic_docs = self.format_screen(magic_docs)
443 magic_docs = self.format_screen(magic_docs)
445 if mode == 'brief':
444 if mode == 'brief':
446 return magic_docs
445 return magic_docs
447
446
448 outmsg = """
447 outmsg = """
449 IPython's 'magic' functions
448 IPython's 'magic' functions
450 ===========================
449 ===========================
451
450
452 The magic function system provides a series of functions which allow you to
451 The magic function system provides a series of functions which allow you to
453 control the behavior of IPython itself, plus a lot of system-type
452 control the behavior of IPython itself, plus a lot of system-type
454 features. All these functions are prefixed with a % character, but parameters
453 features. All these functions are prefixed with a % character, but parameters
455 are given without parentheses or quotes.
454 are given without parentheses or quotes.
456
455
457 NOTE: If you have 'automagic' enabled (via the command line option or with the
456 NOTE: If you have 'automagic' enabled (via the command line option or with the
458 %automagic function), you don't need to type in the % explicitly. By default,
457 %automagic function), you don't need to type in the % explicitly. By default,
459 IPython ships with automagic on, so you should only rarely need the % escape.
458 IPython ships with automagic on, so you should only rarely need the % escape.
460
459
461 Example: typing '%cd mydir' (without the quotes) changes you working directory
460 Example: typing '%cd mydir' (without the quotes) changes you working directory
462 to 'mydir', if it exists.
461 to 'mydir', if it exists.
463
462
464 You can define your own magic functions to extend the system. See the supplied
463 You can define your own magic functions to extend the system. See the supplied
465 ipythonrc and example-magic.py files for details (in your ipython
464 ipythonrc and example-magic.py files for details (in your ipython
466 configuration directory, typically $HOME/.ipython/).
465 configuration directory, typically $HOME/.ipython/).
467
466
468 You can also define your own aliased names for magic functions. In your
467 You can also define your own aliased names for magic functions. In your
469 ipythonrc file, placing a line like:
468 ipythonrc file, placing a line like:
470
469
471 execute __IPYTHON__.magic_pf = __IPYTHON__.magic_profile
470 execute __IPYTHON__.magic_pf = __IPYTHON__.magic_profile
472
471
473 will define %pf as a new name for %profile.
472 will define %pf as a new name for %profile.
474
473
475 You can also call magics in code using the ipmagic() function, which IPython
474 You can also call magics in code using the ipmagic() function, which IPython
476 automatically adds to the builtin namespace. Type 'ipmagic?' for details.
475 automatically adds to the builtin namespace. Type 'ipmagic?' for details.
477
476
478 For a list of the available magic functions, use %lsmagic. For a description
477 For a list of the available magic functions, use %lsmagic. For a description
479 of any of them, type %magic_name?, e.g. '%cd?'.
478 of any of them, type %magic_name?, e.g. '%cd?'.
480
479
481 Currently the magic system has the following functions:\n"""
480 Currently the magic system has the following functions:\n"""
482
481
483 mesc = self.shell.ESC_MAGIC
482 mesc = self.shell.ESC_MAGIC
484 outmsg = ("%s\n%s\n\nSummary of magic functions (from %slsmagic):"
483 outmsg = ("%s\n%s\n\nSummary of magic functions (from %slsmagic):"
485 "\n\n%s%s\n\n%s" % (outmsg,
484 "\n\n%s%s\n\n%s" % (outmsg,
486 magic_docs,mesc,mesc,
485 magic_docs,mesc,mesc,
487 (' '+mesc).join(self.lsmagic()),
486 (' '+mesc).join(self.lsmagic()),
488 Magic.auto_status[self.shell.rc.automagic] ) )
487 Magic.auto_status[self.shell.rc.automagic] ) )
489
488
490 page(outmsg,screen_lines=self.shell.rc.screen_length)
489 page(outmsg,screen_lines=self.shell.rc.screen_length)
491
490
492
491
493 def magic_autoindent(self, parameter_s = ''):
492 def magic_autoindent(self, parameter_s = ''):
494 """Toggle autoindent on/off (if available)."""
493 """Toggle autoindent on/off (if available)."""
495
494
496 self.shell.set_autoindent()
495 self.shell.set_autoindent()
497 print "Automatic indentation is:",['OFF','ON'][self.shell.autoindent]
496 print "Automatic indentation is:",['OFF','ON'][self.shell.autoindent]
498
497
499
498
500 def magic_automagic(self, parameter_s = ''):
499 def magic_automagic(self, parameter_s = ''):
501 """Make magic functions callable without having to type the initial %.
500 """Make magic functions callable without having to type the initial %.
502
501
503 Without argumentsl toggles on/off (when off, you must call it as
502 Without argumentsl toggles on/off (when off, you must call it as
504 %automagic, of course). With arguments it sets the value, and you can
503 %automagic, of course). With arguments it sets the value, and you can
505 use any of (case insensitive):
504 use any of (case insensitive):
506
505
507 - on,1,True: to activate
506 - on,1,True: to activate
508
507
509 - off,0,False: to deactivate.
508 - off,0,False: to deactivate.
510
509
511 Note that magic functions have lowest priority, so if there's a
510 Note that magic functions have lowest priority, so if there's a
512 variable whose name collides with that of a magic fn, automagic won't
511 variable whose name collides with that of a magic fn, automagic won't
513 work for that function (you get the variable instead). However, if you
512 work for that function (you get the variable instead). However, if you
514 delete the variable (del var), the previously shadowed magic function
513 delete the variable (del var), the previously shadowed magic function
515 becomes visible to automagic again."""
514 becomes visible to automagic again."""
516
515
517 rc = self.shell.rc
516 rc = self.shell.rc
518 arg = parameter_s.lower()
517 arg = parameter_s.lower()
519 if parameter_s in ('on','1','true'):
518 if parameter_s in ('on','1','true'):
520 rc.automagic = True
519 rc.automagic = True
521 elif parameter_s in ('off','0','false'):
520 elif parameter_s in ('off','0','false'):
522 rc.automagic = False
521 rc.automagic = False
523 else:
522 else:
524 rc.automagic = not rc.automagic
523 rc.automagic = not rc.automagic
525 print '\n' + Magic.auto_status[rc.automagic]
524 print '\n' + Magic.auto_status[rc.automagic]
526
525
527 @testdec.skip_doctest
526 @testdec.skip_doctest
528 def magic_autocall(self, parameter_s = ''):
527 def magic_autocall(self, parameter_s = ''):
529 """Make functions callable without having to type parentheses.
528 """Make functions callable without having to type parentheses.
530
529
531 Usage:
530 Usage:
532
531
533 %autocall [mode]
532 %autocall [mode]
534
533
535 The mode can be one of: 0->Off, 1->Smart, 2->Full. If not given, the
534 The mode can be one of: 0->Off, 1->Smart, 2->Full. If not given, the
536 value is toggled on and off (remembering the previous state).
535 value is toggled on and off (remembering the previous state).
537
536
538 In more detail, these values mean:
537 In more detail, these values mean:
539
538
540 0 -> fully disabled
539 0 -> fully disabled
541
540
542 1 -> active, but do not apply if there are no arguments on the line.
541 1 -> active, but do not apply if there are no arguments on the line.
543
542
544 In this mode, you get:
543 In this mode, you get:
545
544
546 In [1]: callable
545 In [1]: callable
547 Out[1]: <built-in function callable>
546 Out[1]: <built-in function callable>
548
547
549 In [2]: callable 'hello'
548 In [2]: callable 'hello'
550 ------> callable('hello')
549 ------> callable('hello')
551 Out[2]: False
550 Out[2]: False
552
551
553 2 -> Active always. Even if no arguments are present, the callable
552 2 -> Active always. Even if no arguments are present, the callable
554 object is called:
553 object is called:
555
554
556 In [2]: float
555 In [2]: float
557 ------> float()
556 ------> float()
558 Out[2]: 0.0
557 Out[2]: 0.0
559
558
560 Note that even with autocall off, you can still use '/' at the start of
559 Note that even with autocall off, you can still use '/' at the start of
561 a line to treat the first argument on the command line as a function
560 a line to treat the first argument on the command line as a function
562 and add parentheses to it:
561 and add parentheses to it:
563
562
564 In [8]: /str 43
563 In [8]: /str 43
565 ------> str(43)
564 ------> str(43)
566 Out[8]: '43'
565 Out[8]: '43'
567
566
568 # all-random (note for auto-testing)
567 # all-random (note for auto-testing)
569 """
568 """
570
569
571 rc = self.shell.rc
570 rc = self.shell.rc
572
571
573 if parameter_s:
572 if parameter_s:
574 arg = int(parameter_s)
573 arg = int(parameter_s)
575 else:
574 else:
576 arg = 'toggle'
575 arg = 'toggle'
577
576
578 if not arg in (0,1,2,'toggle'):
577 if not arg in (0,1,2,'toggle'):
579 error('Valid modes: (0->Off, 1->Smart, 2->Full')
578 error('Valid modes: (0->Off, 1->Smart, 2->Full')
580 return
579 return
581
580
582 if arg in (0,1,2):
581 if arg in (0,1,2):
583 rc.autocall = arg
582 rc.autocall = arg
584 else: # toggle
583 else: # toggle
585 if rc.autocall:
584 if rc.autocall:
586 self._magic_state.autocall_save = rc.autocall
585 self._magic_state.autocall_save = rc.autocall
587 rc.autocall = 0
586 rc.autocall = 0
588 else:
587 else:
589 try:
588 try:
590 rc.autocall = self._magic_state.autocall_save
589 rc.autocall = self._magic_state.autocall_save
591 except AttributeError:
590 except AttributeError:
592 rc.autocall = self._magic_state.autocall_save = 1
591 rc.autocall = self._magic_state.autocall_save = 1
593
592
594 print "Automatic calling is:",['OFF','Smart','Full'][rc.autocall]
593 print "Automatic calling is:",['OFF','Smart','Full'][rc.autocall]
595
594
596 def magic_system_verbose(self, parameter_s = ''):
595 def magic_system_verbose(self, parameter_s = ''):
597 """Set verbose printing of system calls.
596 """Set verbose printing of system calls.
598
597
599 If called without an argument, act as a toggle"""
598 If called without an argument, act as a toggle"""
600
599
601 if parameter_s:
600 if parameter_s:
602 val = bool(eval(parameter_s))
601 val = bool(eval(parameter_s))
603 else:
602 else:
604 val = None
603 val = None
605
604
606 self.shell.rc_set_toggle('system_verbose',val)
605 self.shell.rc_set_toggle('system_verbose',val)
607 print "System verbose printing is:",\
606 print "System verbose printing is:",\
608 ['OFF','ON'][self.shell.rc.system_verbose]
607 ['OFF','ON'][self.shell.rc.system_verbose]
609
608
610
609
611 def magic_page(self, parameter_s=''):
610 def magic_page(self, parameter_s=''):
612 """Pretty print the object and display it through a pager.
611 """Pretty print the object and display it through a pager.
613
612
614 %page [options] OBJECT
613 %page [options] OBJECT
615
614
616 If no object is given, use _ (last output).
615 If no object is given, use _ (last output).
617
616
618 Options:
617 Options:
619
618
620 -r: page str(object), don't pretty-print it."""
619 -r: page str(object), don't pretty-print it."""
621
620
622 # After a function contributed by Olivier Aubert, slightly modified.
621 # After a function contributed by Olivier Aubert, slightly modified.
623
622
624 # Process options/args
623 # Process options/args
625 opts,args = self.parse_options(parameter_s,'r')
624 opts,args = self.parse_options(parameter_s,'r')
626 raw = 'r' in opts
625 raw = 'r' in opts
627
626
628 oname = args and args or '_'
627 oname = args and args or '_'
629 info = self._ofind(oname)
628 info = self._ofind(oname)
630 if info['found']:
629 if info['found']:
631 txt = (raw and str or pformat)( info['obj'] )
630 txt = (raw and str or pformat)( info['obj'] )
632 page(txt)
631 page(txt)
633 else:
632 else:
634 print 'Object `%s` not found' % oname
633 print 'Object `%s` not found' % oname
635
634
636 def magic_profile(self, parameter_s=''):
635 def magic_profile(self, parameter_s=''):
637 """Print your currently active IPyhton profile."""
636 """Print your currently active IPyhton profile."""
638 if self.shell.rc.profile:
637 if self.shell.rc.profile:
639 printpl('Current IPython profile: $self.shell.rc.profile.')
638 printpl('Current IPython profile: $self.shell.rc.profile.')
640 else:
639 else:
641 print 'No profile active.'
640 print 'No profile active.'
642
641
643 def magic_pinfo(self, parameter_s='', namespaces=None):
642 def magic_pinfo(self, parameter_s='', namespaces=None):
644 """Provide detailed information about an object.
643 """Provide detailed information about an object.
645
644
646 '%pinfo object' is just a synonym for object? or ?object."""
645 '%pinfo object' is just a synonym for object? or ?object."""
647
646
648 #print 'pinfo par: <%s>' % parameter_s # dbg
647 #print 'pinfo par: <%s>' % parameter_s # dbg
649
648
650
649
651 # detail_level: 0 -> obj? , 1 -> obj??
650 # detail_level: 0 -> obj? , 1 -> obj??
652 detail_level = 0
651 detail_level = 0
653 # We need to detect if we got called as 'pinfo pinfo foo', which can
652 # We need to detect if we got called as 'pinfo pinfo foo', which can
654 # happen if the user types 'pinfo foo?' at the cmd line.
653 # happen if the user types 'pinfo foo?' at the cmd line.
655 pinfo,qmark1,oname,qmark2 = \
654 pinfo,qmark1,oname,qmark2 = \
656 re.match('(pinfo )?(\?*)(.*?)(\??$)',parameter_s).groups()
655 re.match('(pinfo )?(\?*)(.*?)(\??$)',parameter_s).groups()
657 if pinfo or qmark1 or qmark2:
656 if pinfo or qmark1 or qmark2:
658 detail_level = 1
657 detail_level = 1
659 if "*" in oname:
658 if "*" in oname:
660 self.magic_psearch(oname)
659 self.magic_psearch(oname)
661 else:
660 else:
662 self._inspect('pinfo', oname, detail_level=detail_level,
661 self._inspect('pinfo', oname, detail_level=detail_level,
663 namespaces=namespaces)
662 namespaces=namespaces)
664
663
665 def magic_pdef(self, parameter_s='', namespaces=None):
664 def magic_pdef(self, parameter_s='', namespaces=None):
666 """Print the definition header for any callable object.
665 """Print the definition header for any callable object.
667
666
668 If the object is a class, print the constructor information."""
667 If the object is a class, print the constructor information."""
669 self._inspect('pdef',parameter_s, namespaces)
668 self._inspect('pdef',parameter_s, namespaces)
670
669
671 def magic_pdoc(self, parameter_s='', namespaces=None):
670 def magic_pdoc(self, parameter_s='', namespaces=None):
672 """Print the docstring for an object.
671 """Print the docstring for an object.
673
672
674 If the given object is a class, it will print both the class and the
673 If the given object is a class, it will print both the class and the
675 constructor docstrings."""
674 constructor docstrings."""
676 self._inspect('pdoc',parameter_s, namespaces)
675 self._inspect('pdoc',parameter_s, namespaces)
677
676
678 def magic_psource(self, parameter_s='', namespaces=None):
677 def magic_psource(self, parameter_s='', namespaces=None):
679 """Print (or run through pager) the source code for an object."""
678 """Print (or run through pager) the source code for an object."""
680 self._inspect('psource',parameter_s, namespaces)
679 self._inspect('psource',parameter_s, namespaces)
681
680
682 def magic_pfile(self, parameter_s=''):
681 def magic_pfile(self, parameter_s=''):
683 """Print (or run through pager) the file where an object is defined.
682 """Print (or run through pager) the file where an object is defined.
684
683
685 The file opens at the line where the object definition begins. IPython
684 The file opens at the line where the object definition begins. IPython
686 will honor the environment variable PAGER if set, and otherwise will
685 will honor the environment variable PAGER if set, and otherwise will
687 do its best to print the file in a convenient form.
686 do its best to print the file in a convenient form.
688
687
689 If the given argument is not an object currently defined, IPython will
688 If the given argument is not an object currently defined, IPython will
690 try to interpret it as a filename (automatically adding a .py extension
689 try to interpret it as a filename (automatically adding a .py extension
691 if needed). You can thus use %pfile as a syntax highlighting code
690 if needed). You can thus use %pfile as a syntax highlighting code
692 viewer."""
691 viewer."""
693
692
694 # first interpret argument as an object name
693 # first interpret argument as an object name
695 out = self._inspect('pfile',parameter_s)
694 out = self._inspect('pfile',parameter_s)
696 # if not, try the input as a filename
695 # if not, try the input as a filename
697 if out == 'not found':
696 if out == 'not found':
698 try:
697 try:
699 filename = get_py_filename(parameter_s)
698 filename = get_py_filename(parameter_s)
700 except IOError,msg:
699 except IOError,msg:
701 print msg
700 print msg
702 return
701 return
703 page(self.shell.inspector.format(file(filename).read()))
702 page(self.shell.inspector.format(file(filename).read()))
704
703
705 def _inspect(self,meth,oname,namespaces=None,**kw):
704 def _inspect(self,meth,oname,namespaces=None,**kw):
706 """Generic interface to the inspector system.
705 """Generic interface to the inspector system.
707
706
708 This function is meant to be called by pdef, pdoc & friends."""
707 This function is meant to be called by pdef, pdoc & friends."""
709
708
710 #oname = oname.strip()
709 #oname = oname.strip()
711 #print '1- oname: <%r>' % oname # dbg
710 #print '1- oname: <%r>' % oname # dbg
712 try:
711 try:
713 oname = oname.strip().encode('ascii')
712 oname = oname.strip().encode('ascii')
714 #print '2- oname: <%r>' % oname # dbg
713 #print '2- oname: <%r>' % oname # dbg
715 except UnicodeEncodeError:
714 except UnicodeEncodeError:
716 print 'Python identifiers can only contain ascii characters.'
715 print 'Python identifiers can only contain ascii characters.'
717 return 'not found'
716 return 'not found'
718
717
719 info = Struct(self._ofind(oname, namespaces))
718 info = Struct(self._ofind(oname, namespaces))
720
719
721 if info.found:
720 if info.found:
722 try:
721 try:
723 IPython.generics.inspect_object(info.obj)
722 IPython.generics.inspect_object(info.obj)
724 return
723 return
725 except IPython.ipapi.TryNext:
724 except IPython.ipapi.TryNext:
726 pass
725 pass
727 # Get the docstring of the class property if it exists.
726 # Get the docstring of the class property if it exists.
728 path = oname.split('.')
727 path = oname.split('.')
729 root = '.'.join(path[:-1])
728 root = '.'.join(path[:-1])
730 if info.parent is not None:
729 if info.parent is not None:
731 try:
730 try:
732 target = getattr(info.parent, '__class__')
731 target = getattr(info.parent, '__class__')
733 # The object belongs to a class instance.
732 # The object belongs to a class instance.
734 try:
733 try:
735 target = getattr(target, path[-1])
734 target = getattr(target, path[-1])
736 # The class defines the object.
735 # The class defines the object.
737 if isinstance(target, property):
736 if isinstance(target, property):
738 oname = root + '.__class__.' + path[-1]
737 oname = root + '.__class__.' + path[-1]
739 info = Struct(self._ofind(oname))
738 info = Struct(self._ofind(oname))
740 except AttributeError: pass
739 except AttributeError: pass
741 except AttributeError: pass
740 except AttributeError: pass
742
741
743 pmethod = getattr(self.shell.inspector,meth)
742 pmethod = getattr(self.shell.inspector,meth)
744 formatter = info.ismagic and self.format_screen or None
743 formatter = info.ismagic and self.format_screen or None
745 if meth == 'pdoc':
744 if meth == 'pdoc':
746 pmethod(info.obj,oname,formatter)
745 pmethod(info.obj,oname,formatter)
747 elif meth == 'pinfo':
746 elif meth == 'pinfo':
748 pmethod(info.obj,oname,formatter,info,**kw)
747 pmethod(info.obj,oname,formatter,info,**kw)
749 else:
748 else:
750 pmethod(info.obj,oname)
749 pmethod(info.obj,oname)
751 else:
750 else:
752 print 'Object `%s` not found.' % oname
751 print 'Object `%s` not found.' % oname
753 return 'not found' # so callers can take other action
752 return 'not found' # so callers can take other action
754
753
755 def magic_psearch(self, parameter_s=''):
754 def magic_psearch(self, parameter_s=''):
756 """Search for object in namespaces by wildcard.
755 """Search for object in namespaces by wildcard.
757
756
758 %psearch [options] PATTERN [OBJECT TYPE]
757 %psearch [options] PATTERN [OBJECT TYPE]
759
758
760 Note: ? can be used as a synonym for %psearch, at the beginning or at
759 Note: ? can be used as a synonym for %psearch, at the beginning or at
761 the end: both a*? and ?a* are equivalent to '%psearch a*'. Still, the
760 the end: both a*? and ?a* are equivalent to '%psearch a*'. Still, the
762 rest of the command line must be unchanged (options come first), so
761 rest of the command line must be unchanged (options come first), so
763 for example the following forms are equivalent
762 for example the following forms are equivalent
764
763
765 %psearch -i a* function
764 %psearch -i a* function
766 -i a* function?
765 -i a* function?
767 ?-i a* function
766 ?-i a* function
768
767
769 Arguments:
768 Arguments:
770
769
771 PATTERN
770 PATTERN
772
771
773 where PATTERN is a string containing * as a wildcard similar to its
772 where PATTERN is a string containing * as a wildcard similar to its
774 use in a shell. The pattern is matched in all namespaces on the
773 use in a shell. The pattern is matched in all namespaces on the
775 search path. By default objects starting with a single _ are not
774 search path. By default objects starting with a single _ are not
776 matched, many IPython generated objects have a single
775 matched, many IPython generated objects have a single
777 underscore. The default is case insensitive matching. Matching is
776 underscore. The default is case insensitive matching. Matching is
778 also done on the attributes of objects and not only on the objects
777 also done on the attributes of objects and not only on the objects
779 in a module.
778 in a module.
780
779
781 [OBJECT TYPE]
780 [OBJECT TYPE]
782
781
783 Is the name of a python type from the types module. The name is
782 Is the name of a python type from the types module. The name is
784 given in lowercase without the ending type, ex. StringType is
783 given in lowercase without the ending type, ex. StringType is
785 written string. By adding a type here only objects matching the
784 written string. By adding a type here only objects matching the
786 given type are matched. Using all here makes the pattern match all
785 given type are matched. Using all here makes the pattern match all
787 types (this is the default).
786 types (this is the default).
788
787
789 Options:
788 Options:
790
789
791 -a: makes the pattern match even objects whose names start with a
790 -a: makes the pattern match even objects whose names start with a
792 single underscore. These names are normally ommitted from the
791 single underscore. These names are normally ommitted from the
793 search.
792 search.
794
793
795 -i/-c: make the pattern case insensitive/sensitive. If neither of
794 -i/-c: make the pattern case insensitive/sensitive. If neither of
796 these options is given, the default is read from your ipythonrc
795 these options is given, the default is read from your ipythonrc
797 file. The option name which sets this value is
796 file. The option name which sets this value is
798 'wildcards_case_sensitive'. If this option is not specified in your
797 'wildcards_case_sensitive'. If this option is not specified in your
799 ipythonrc file, IPython's internal default is to do a case sensitive
798 ipythonrc file, IPython's internal default is to do a case sensitive
800 search.
799 search.
801
800
802 -e/-s NAMESPACE: exclude/search a given namespace. The pattern you
801 -e/-s NAMESPACE: exclude/search a given namespace. The pattern you
803 specifiy can be searched in any of the following namespaces:
802 specifiy can be searched in any of the following namespaces:
804 'builtin', 'user', 'user_global','internal', 'alias', where
803 'builtin', 'user', 'user_global','internal', 'alias', where
805 'builtin' and 'user' are the search defaults. Note that you should
804 'builtin' and 'user' are the search defaults. Note that you should
806 not use quotes when specifying namespaces.
805 not use quotes when specifying namespaces.
807
806
808 'Builtin' contains the python module builtin, 'user' contains all
807 'Builtin' contains the python module builtin, 'user' contains all
809 user data, 'alias' only contain the shell aliases and no python
808 user data, 'alias' only contain the shell aliases and no python
810 objects, 'internal' contains objects used by IPython. The
809 objects, 'internal' contains objects used by IPython. The
811 'user_global' namespace is only used by embedded IPython instances,
810 'user_global' namespace is only used by embedded IPython instances,
812 and it contains module-level globals. You can add namespaces to the
811 and it contains module-level globals. You can add namespaces to the
813 search with -s or exclude them with -e (these options can be given
812 search with -s or exclude them with -e (these options can be given
814 more than once).
813 more than once).
815
814
816 Examples:
815 Examples:
817
816
818 %psearch a* -> objects beginning with an a
817 %psearch a* -> objects beginning with an a
819 %psearch -e builtin a* -> objects NOT in the builtin space starting in a
818 %psearch -e builtin a* -> objects NOT in the builtin space starting in a
820 %psearch a* function -> all functions beginning with an a
819 %psearch a* function -> all functions beginning with an a
821 %psearch re.e* -> objects beginning with an e in module re
820 %psearch re.e* -> objects beginning with an e in module re
822 %psearch r*.e* -> objects that start with e in modules starting in r
821 %psearch r*.e* -> objects that start with e in modules starting in r
823 %psearch r*.* string -> all strings in modules beginning with r
822 %psearch r*.* string -> all strings in modules beginning with r
824
823
825 Case sensitve search:
824 Case sensitve search:
826
825
827 %psearch -c a* list all object beginning with lower case a
826 %psearch -c a* list all object beginning with lower case a
828
827
829 Show objects beginning with a single _:
828 Show objects beginning with a single _:
830
829
831 %psearch -a _* list objects beginning with a single underscore"""
830 %psearch -a _* list objects beginning with a single underscore"""
832 try:
831 try:
833 parameter_s = parameter_s.encode('ascii')
832 parameter_s = parameter_s.encode('ascii')
834 except UnicodeEncodeError:
833 except UnicodeEncodeError:
835 print 'Python identifiers can only contain ascii characters.'
834 print 'Python identifiers can only contain ascii characters.'
836 return
835 return
837
836
838 # default namespaces to be searched
837 # default namespaces to be searched
839 def_search = ['user','builtin']
838 def_search = ['user','builtin']
840
839
841 # Process options/args
840 # Process options/args
842 opts,args = self.parse_options(parameter_s,'cias:e:',list_all=True)
841 opts,args = self.parse_options(parameter_s,'cias:e:',list_all=True)
843 opt = opts.get
842 opt = opts.get
844 shell = self.shell
843 shell = self.shell
845 psearch = shell.inspector.psearch
844 psearch = shell.inspector.psearch
846
845
847 # select case options
846 # select case options
848 if opts.has_key('i'):
847 if opts.has_key('i'):
849 ignore_case = True
848 ignore_case = True
850 elif opts.has_key('c'):
849 elif opts.has_key('c'):
851 ignore_case = False
850 ignore_case = False
852 else:
851 else:
853 ignore_case = not shell.rc.wildcards_case_sensitive
852 ignore_case = not shell.rc.wildcards_case_sensitive
854
853
855 # Build list of namespaces to search from user options
854 # Build list of namespaces to search from user options
856 def_search.extend(opt('s',[]))
855 def_search.extend(opt('s',[]))
857 ns_exclude = ns_exclude=opt('e',[])
856 ns_exclude = ns_exclude=opt('e',[])
858 ns_search = [nm for nm in def_search if nm not in ns_exclude]
857 ns_search = [nm for nm in def_search if nm not in ns_exclude]
859
858
860 # Call the actual search
859 # Call the actual search
861 try:
860 try:
862 psearch(args,shell.ns_table,ns_search,
861 psearch(args,shell.ns_table,ns_search,
863 show_all=opt('a'),ignore_case=ignore_case)
862 show_all=opt('a'),ignore_case=ignore_case)
864 except:
863 except:
865 shell.showtraceback()
864 shell.showtraceback()
866
865
867 def magic_who_ls(self, parameter_s=''):
866 def magic_who_ls(self, parameter_s=''):
868 """Return a sorted list of all interactive variables.
867 """Return a sorted list of all interactive variables.
869
868
870 If arguments are given, only variables of types matching these
869 If arguments are given, only variables of types matching these
871 arguments are returned."""
870 arguments are returned."""
872
871
873 user_ns = self.shell.user_ns
872 user_ns = self.shell.user_ns
874 internal_ns = self.shell.internal_ns
873 internal_ns = self.shell.internal_ns
875 user_config_ns = self.shell.user_config_ns
874 user_config_ns = self.shell.user_config_ns
876 out = []
875 out = []
877 typelist = parameter_s.split()
876 typelist = parameter_s.split()
878
877
879 for i in user_ns:
878 for i in user_ns:
880 if not (i.startswith('_') or i.startswith('_i')) \
879 if not (i.startswith('_') or i.startswith('_i')) \
881 and not (i in internal_ns or i in user_config_ns):
880 and not (i in internal_ns or i in user_config_ns):
882 if typelist:
881 if typelist:
883 if type(user_ns[i]).__name__ in typelist:
882 if type(user_ns[i]).__name__ in typelist:
884 out.append(i)
883 out.append(i)
885 else:
884 else:
886 out.append(i)
885 out.append(i)
887 out.sort()
886 out.sort()
888 return out
887 return out
889
888
890 def magic_who(self, parameter_s=''):
889 def magic_who(self, parameter_s=''):
891 """Print all interactive variables, with some minimal formatting.
890 """Print all interactive variables, with some minimal formatting.
892
891
893 If any arguments are given, only variables whose type matches one of
892 If any arguments are given, only variables whose type matches one of
894 these are printed. For example:
893 these are printed. For example:
895
894
896 %who function str
895 %who function str
897
896
898 will only list functions and strings, excluding all other types of
897 will only list functions and strings, excluding all other types of
899 variables. To find the proper type names, simply use type(var) at a
898 variables. To find the proper type names, simply use type(var) at a
900 command line to see how python prints type names. For example:
899 command line to see how python prints type names. For example:
901
900
902 In [1]: type('hello')\\
901 In [1]: type('hello')\\
903 Out[1]: <type 'str'>
902 Out[1]: <type 'str'>
904
903
905 indicates that the type name for strings is 'str'.
904 indicates that the type name for strings is 'str'.
906
905
907 %who always excludes executed names loaded through your configuration
906 %who always excludes executed names loaded through your configuration
908 file and things which are internal to IPython.
907 file and things which are internal to IPython.
909
908
910 This is deliberate, as typically you may load many modules and the
909 This is deliberate, as typically you may load many modules and the
911 purpose of %who is to show you only what you've manually defined."""
910 purpose of %who is to show you only what you've manually defined."""
912
911
913 varlist = self.magic_who_ls(parameter_s)
912 varlist = self.magic_who_ls(parameter_s)
914 if not varlist:
913 if not varlist:
915 if parameter_s:
914 if parameter_s:
916 print 'No variables match your requested type.'
915 print 'No variables match your requested type.'
917 else:
916 else:
918 print 'Interactive namespace is empty.'
917 print 'Interactive namespace is empty.'
919 return
918 return
920
919
921 # if we have variables, move on...
920 # if we have variables, move on...
922 count = 0
921 count = 0
923 for i in varlist:
922 for i in varlist:
924 print i+'\t',
923 print i+'\t',
925 count += 1
924 count += 1
926 if count > 8:
925 if count > 8:
927 count = 0
926 count = 0
928 print
927 print
929 print
928 print
930
929
931 def magic_whos(self, parameter_s=''):
930 def magic_whos(self, parameter_s=''):
932 """Like %who, but gives some extra information about each variable.
931 """Like %who, but gives some extra information about each variable.
933
932
934 The same type filtering of %who can be applied here.
933 The same type filtering of %who can be applied here.
935
934
936 For all variables, the type is printed. Additionally it prints:
935 For all variables, the type is printed. Additionally it prints:
937
936
938 - For {},[],(): their length.
937 - For {},[],(): their length.
939
938
940 - For numpy and Numeric arrays, a summary with shape, number of
939 - For numpy and Numeric arrays, a summary with shape, number of
941 elements, typecode and size in memory.
940 elements, typecode and size in memory.
942
941
943 - Everything else: a string representation, snipping their middle if
942 - Everything else: a string representation, snipping their middle if
944 too long."""
943 too long."""
945
944
946 varnames = self.magic_who_ls(parameter_s)
945 varnames = self.magic_who_ls(parameter_s)
947 if not varnames:
946 if not varnames:
948 if parameter_s:
947 if parameter_s:
949 print 'No variables match your requested type.'
948 print 'No variables match your requested type.'
950 else:
949 else:
951 print 'Interactive namespace is empty.'
950 print 'Interactive namespace is empty.'
952 return
951 return
953
952
954 # if we have variables, move on...
953 # if we have variables, move on...
955
954
956 # for these types, show len() instead of data:
955 # for these types, show len() instead of data:
957 seq_types = [types.DictType,types.ListType,types.TupleType]
956 seq_types = [types.DictType,types.ListType,types.TupleType]
958
957
959 # for numpy/Numeric arrays, display summary info
958 # for numpy/Numeric arrays, display summary info
960 try:
959 try:
961 import numpy
960 import numpy
962 except ImportError:
961 except ImportError:
963 ndarray_type = None
962 ndarray_type = None
964 else:
963 else:
965 ndarray_type = numpy.ndarray.__name__
964 ndarray_type = numpy.ndarray.__name__
966 try:
965 try:
967 import Numeric
966 import Numeric
968 except ImportError:
967 except ImportError:
969 array_type = None
968 array_type = None
970 else:
969 else:
971 array_type = Numeric.ArrayType.__name__
970 array_type = Numeric.ArrayType.__name__
972
971
973 # Find all variable names and types so we can figure out column sizes
972 # Find all variable names and types so we can figure out column sizes
974 def get_vars(i):
973 def get_vars(i):
975 return self.shell.user_ns[i]
974 return self.shell.user_ns[i]
976
975
977 # some types are well known and can be shorter
976 # some types are well known and can be shorter
978 abbrevs = {'IPython.macro.Macro' : 'Macro'}
977 abbrevs = {'IPython.macro.Macro' : 'Macro'}
979 def type_name(v):
978 def type_name(v):
980 tn = type(v).__name__
979 tn = type(v).__name__
981 return abbrevs.get(tn,tn)
980 return abbrevs.get(tn,tn)
982
981
983 varlist = map(get_vars,varnames)
982 varlist = map(get_vars,varnames)
984
983
985 typelist = []
984 typelist = []
986 for vv in varlist:
985 for vv in varlist:
987 tt = type_name(vv)
986 tt = type_name(vv)
988
987
989 if tt=='instance':
988 if tt=='instance':
990 typelist.append( abbrevs.get(str(vv.__class__),
989 typelist.append( abbrevs.get(str(vv.__class__),
991 str(vv.__class__)))
990 str(vv.__class__)))
992 else:
991 else:
993 typelist.append(tt)
992 typelist.append(tt)
994
993
995 # column labels and # of spaces as separator
994 # column labels and # of spaces as separator
996 varlabel = 'Variable'
995 varlabel = 'Variable'
997 typelabel = 'Type'
996 typelabel = 'Type'
998 datalabel = 'Data/Info'
997 datalabel = 'Data/Info'
999 colsep = 3
998 colsep = 3
1000 # variable format strings
999 # variable format strings
1001 vformat = "$vname.ljust(varwidth)$vtype.ljust(typewidth)"
1000 vformat = "$vname.ljust(varwidth)$vtype.ljust(typewidth)"
1002 vfmt_short = '$vstr[:25]<...>$vstr[-25:]'
1001 vfmt_short = '$vstr[:25]<...>$vstr[-25:]'
1003 aformat = "%s: %s elems, type `%s`, %s bytes"
1002 aformat = "%s: %s elems, type `%s`, %s bytes"
1004 # find the size of the columns to format the output nicely
1003 # find the size of the columns to format the output nicely
1005 varwidth = max(max(map(len,varnames)), len(varlabel)) + colsep
1004 varwidth = max(max(map(len,varnames)), len(varlabel)) + colsep
1006 typewidth = max(max(map(len,typelist)), len(typelabel)) + colsep
1005 typewidth = max(max(map(len,typelist)), len(typelabel)) + colsep
1007 # table header
1006 # table header
1008 print varlabel.ljust(varwidth) + typelabel.ljust(typewidth) + \
1007 print varlabel.ljust(varwidth) + typelabel.ljust(typewidth) + \
1009 ' '+datalabel+'\n' + '-'*(varwidth+typewidth+len(datalabel)+1)
1008 ' '+datalabel+'\n' + '-'*(varwidth+typewidth+len(datalabel)+1)
1010 # and the table itself
1009 # and the table itself
1011 kb = 1024
1010 kb = 1024
1012 Mb = 1048576 # kb**2
1011 Mb = 1048576 # kb**2
1013 for vname,var,vtype in zip(varnames,varlist,typelist):
1012 for vname,var,vtype in zip(varnames,varlist,typelist):
1014 print itpl(vformat),
1013 print itpl(vformat),
1015 if vtype in seq_types:
1014 if vtype in seq_types:
1016 print len(var)
1015 print len(var)
1017 elif vtype in [array_type,ndarray_type]:
1016 elif vtype in [array_type,ndarray_type]:
1018 vshape = str(var.shape).replace(',','').replace(' ','x')[1:-1]
1017 vshape = str(var.shape).replace(',','').replace(' ','x')[1:-1]
1019 if vtype==ndarray_type:
1018 if vtype==ndarray_type:
1020 # numpy
1019 # numpy
1021 vsize = var.size
1020 vsize = var.size
1022 vbytes = vsize*var.itemsize
1021 vbytes = vsize*var.itemsize
1023 vdtype = var.dtype
1022 vdtype = var.dtype
1024 else:
1023 else:
1025 # Numeric
1024 # Numeric
1026 vsize = Numeric.size(var)
1025 vsize = Numeric.size(var)
1027 vbytes = vsize*var.itemsize()
1026 vbytes = vsize*var.itemsize()
1028 vdtype = var.typecode()
1027 vdtype = var.typecode()
1029
1028
1030 if vbytes < 100000:
1029 if vbytes < 100000:
1031 print aformat % (vshape,vsize,vdtype,vbytes)
1030 print aformat % (vshape,vsize,vdtype,vbytes)
1032 else:
1031 else:
1033 print aformat % (vshape,vsize,vdtype,vbytes),
1032 print aformat % (vshape,vsize,vdtype,vbytes),
1034 if vbytes < Mb:
1033 if vbytes < Mb:
1035 print '(%s kb)' % (vbytes/kb,)
1034 print '(%s kb)' % (vbytes/kb,)
1036 else:
1035 else:
1037 print '(%s Mb)' % (vbytes/Mb,)
1036 print '(%s Mb)' % (vbytes/Mb,)
1038 else:
1037 else:
1039 try:
1038 try:
1040 vstr = str(var)
1039 vstr = str(var)
1041 except UnicodeEncodeError:
1040 except UnicodeEncodeError:
1042 vstr = unicode(var).encode(sys.getdefaultencoding(),
1041 vstr = unicode(var).encode(sys.getdefaultencoding(),
1043 'backslashreplace')
1042 'backslashreplace')
1044 vstr = vstr.replace('\n','\\n')
1043 vstr = vstr.replace('\n','\\n')
1045 if len(vstr) < 50:
1044 if len(vstr) < 50:
1046 print vstr
1045 print vstr
1047 else:
1046 else:
1048 printpl(vfmt_short)
1047 printpl(vfmt_short)
1049
1048
1050 def magic_reset(self, parameter_s=''):
1049 def magic_reset(self, parameter_s=''):
1051 """Resets the namespace by removing all names defined by the user.
1050 """Resets the namespace by removing all names defined by the user.
1052
1051
1053 Input/Output history are left around in case you need them."""
1052 Input/Output history are left around in case you need them."""
1054
1053
1055 ans = self.shell.ask_yes_no(
1054 ans = self.shell.ask_yes_no(
1056 "Once deleted, variables cannot be recovered. Proceed (y/[n])? ")
1055 "Once deleted, variables cannot be recovered. Proceed (y/[n])? ")
1057 if not ans:
1056 if not ans:
1058 print 'Nothing done.'
1057 print 'Nothing done.'
1059 return
1058 return
1060 user_ns = self.shell.user_ns
1059 user_ns = self.shell.user_ns
1061 for i in self.magic_who_ls():
1060 for i in self.magic_who_ls():
1062 del(user_ns[i])
1061 del(user_ns[i])
1063
1062
1064 # Also flush the private list of module references kept for script
1063 # Also flush the private list of module references kept for script
1065 # execution protection
1064 # execution protection
1066 self.shell._user_main_modules[:] = []
1065 self.shell._user_main_modules[:] = []
1067
1066
1068 def magic_logstart(self,parameter_s=''):
1067 def magic_logstart(self,parameter_s=''):
1069 """Start logging anywhere in a session.
1068 """Start logging anywhere in a session.
1070
1069
1071 %logstart [-o|-r|-t] [log_name [log_mode]]
1070 %logstart [-o|-r|-t] [log_name [log_mode]]
1072
1071
1073 If no name is given, it defaults to a file named 'ipython_log.py' in your
1072 If no name is given, it defaults to a file named 'ipython_log.py' in your
1074 current directory, in 'rotate' mode (see below).
1073 current directory, in 'rotate' mode (see below).
1075
1074
1076 '%logstart name' saves to file 'name' in 'backup' mode. It saves your
1075 '%logstart name' saves to file 'name' in 'backup' mode. It saves your
1077 history up to that point and then continues logging.
1076 history up to that point and then continues logging.
1078
1077
1079 %logstart takes a second optional parameter: logging mode. This can be one
1078 %logstart takes a second optional parameter: logging mode. This can be one
1080 of (note that the modes are given unquoted):\\
1079 of (note that the modes are given unquoted):\\
1081 append: well, that says it.\\
1080 append: well, that says it.\\
1082 backup: rename (if exists) to name~ and start name.\\
1081 backup: rename (if exists) to name~ and start name.\\
1083 global: single logfile in your home dir, appended to.\\
1082 global: single logfile in your home dir, appended to.\\
1084 over : overwrite existing log.\\
1083 over : overwrite existing log.\\
1085 rotate: create rotating logs name.1~, name.2~, etc.
1084 rotate: create rotating logs name.1~, name.2~, etc.
1086
1085
1087 Options:
1086 Options:
1088
1087
1089 -o: log also IPython's output. In this mode, all commands which
1088 -o: log also IPython's output. In this mode, all commands which
1090 generate an Out[NN] prompt are recorded to the logfile, right after
1089 generate an Out[NN] prompt are recorded to the logfile, right after
1091 their corresponding input line. The output lines are always
1090 their corresponding input line. The output lines are always
1092 prepended with a '#[Out]# ' marker, so that the log remains valid
1091 prepended with a '#[Out]# ' marker, so that the log remains valid
1093 Python code.
1092 Python code.
1094
1093
1095 Since this marker is always the same, filtering only the output from
1094 Since this marker is always the same, filtering only the output from
1096 a log is very easy, using for example a simple awk call:
1095 a log is very easy, using for example a simple awk call:
1097
1096
1098 awk -F'#\\[Out\\]# ' '{if($2) {print $2}}' ipython_log.py
1097 awk -F'#\\[Out\\]# ' '{if($2) {print $2}}' ipython_log.py
1099
1098
1100 -r: log 'raw' input. Normally, IPython's logs contain the processed
1099 -r: log 'raw' input. Normally, IPython's logs contain the processed
1101 input, so that user lines are logged in their final form, converted
1100 input, so that user lines are logged in their final form, converted
1102 into valid Python. For example, %Exit is logged as
1101 into valid Python. For example, %Exit is logged as
1103 '_ip.magic("Exit"). If the -r flag is given, all input is logged
1102 '_ip.magic("Exit"). If the -r flag is given, all input is logged
1104 exactly as typed, with no transformations applied.
1103 exactly as typed, with no transformations applied.
1105
1104
1106 -t: put timestamps before each input line logged (these are put in
1105 -t: put timestamps before each input line logged (these are put in
1107 comments)."""
1106 comments)."""
1108
1107
1109 opts,par = self.parse_options(parameter_s,'ort')
1108 opts,par = self.parse_options(parameter_s,'ort')
1110 log_output = 'o' in opts
1109 log_output = 'o' in opts
1111 log_raw_input = 'r' in opts
1110 log_raw_input = 'r' in opts
1112 timestamp = 't' in opts
1111 timestamp = 't' in opts
1113
1112
1114 rc = self.shell.rc
1113 rc = self.shell.rc
1115 logger = self.shell.logger
1114 logger = self.shell.logger
1116
1115
1117 # if no args are given, the defaults set in the logger constructor by
1116 # if no args are given, the defaults set in the logger constructor by
1118 # ipytohn remain valid
1117 # ipytohn remain valid
1119 if par:
1118 if par:
1120 try:
1119 try:
1121 logfname,logmode = par.split()
1120 logfname,logmode = par.split()
1122 except:
1121 except:
1123 logfname = par
1122 logfname = par
1124 logmode = 'backup'
1123 logmode = 'backup'
1125 else:
1124 else:
1126 logfname = logger.logfname
1125 logfname = logger.logfname
1127 logmode = logger.logmode
1126 logmode = logger.logmode
1128 # put logfname into rc struct as if it had been called on the command
1127 # put logfname into rc struct as if it had been called on the command
1129 # line, so it ends up saved in the log header Save it in case we need
1128 # line, so it ends up saved in the log header Save it in case we need
1130 # to restore it...
1129 # to restore it...
1131 old_logfile = rc.opts.get('logfile','')
1130 old_logfile = rc.opts.get('logfile','')
1132 if logfname:
1131 if logfname:
1133 logfname = os.path.expanduser(logfname)
1132 logfname = os.path.expanduser(logfname)
1134 rc.opts.logfile = logfname
1133 rc.opts.logfile = logfname
1135 loghead = self.shell.loghead_tpl % (rc.opts,rc.args)
1134 loghead = self.shell.loghead_tpl % (rc.opts,rc.args)
1136 try:
1135 try:
1137 started = logger.logstart(logfname,loghead,logmode,
1136 started = logger.logstart(logfname,loghead,logmode,
1138 log_output,timestamp,log_raw_input)
1137 log_output,timestamp,log_raw_input)
1139 except:
1138 except:
1140 rc.opts.logfile = old_logfile
1139 rc.opts.logfile = old_logfile
1141 warn("Couldn't start log: %s" % sys.exc_info()[1])
1140 warn("Couldn't start log: %s" % sys.exc_info()[1])
1142 else:
1141 else:
1143 # log input history up to this point, optionally interleaving
1142 # log input history up to this point, optionally interleaving
1144 # output if requested
1143 # output if requested
1145
1144
1146 if timestamp:
1145 if timestamp:
1147 # disable timestamping for the previous history, since we've
1146 # disable timestamping for the previous history, since we've
1148 # lost those already (no time machine here).
1147 # lost those already (no time machine here).
1149 logger.timestamp = False
1148 logger.timestamp = False
1150
1149
1151 if log_raw_input:
1150 if log_raw_input:
1152 input_hist = self.shell.input_hist_raw
1151 input_hist = self.shell.input_hist_raw
1153 else:
1152 else:
1154 input_hist = self.shell.input_hist
1153 input_hist = self.shell.input_hist
1155
1154
1156 if log_output:
1155 if log_output:
1157 log_write = logger.log_write
1156 log_write = logger.log_write
1158 output_hist = self.shell.output_hist
1157 output_hist = self.shell.output_hist
1159 for n in range(1,len(input_hist)-1):
1158 for n in range(1,len(input_hist)-1):
1160 log_write(input_hist[n].rstrip())
1159 log_write(input_hist[n].rstrip())
1161 if n in output_hist:
1160 if n in output_hist:
1162 log_write(repr(output_hist[n]),'output')
1161 log_write(repr(output_hist[n]),'output')
1163 else:
1162 else:
1164 logger.log_write(input_hist[1:])
1163 logger.log_write(input_hist[1:])
1165 if timestamp:
1164 if timestamp:
1166 # re-enable timestamping
1165 # re-enable timestamping
1167 logger.timestamp = True
1166 logger.timestamp = True
1168
1167
1169 print ('Activating auto-logging. '
1168 print ('Activating auto-logging. '
1170 'Current session state plus future input saved.')
1169 'Current session state plus future input saved.')
1171 logger.logstate()
1170 logger.logstate()
1172
1171
1173 def magic_logstop(self,parameter_s=''):
1172 def magic_logstop(self,parameter_s=''):
1174 """Fully stop logging and close log file.
1173 """Fully stop logging and close log file.
1175
1174
1176 In order to start logging again, a new %logstart call needs to be made,
1175 In order to start logging again, a new %logstart call needs to be made,
1177 possibly (though not necessarily) with a new filename, mode and other
1176 possibly (though not necessarily) with a new filename, mode and other
1178 options."""
1177 options."""
1179 self.logger.logstop()
1178 self.logger.logstop()
1180
1179
1181 def magic_logoff(self,parameter_s=''):
1180 def magic_logoff(self,parameter_s=''):
1182 """Temporarily stop logging.
1181 """Temporarily stop logging.
1183
1182
1184 You must have previously started logging."""
1183 You must have previously started logging."""
1185 self.shell.logger.switch_log(0)
1184 self.shell.logger.switch_log(0)
1186
1185
1187 def magic_logon(self,parameter_s=''):
1186 def magic_logon(self,parameter_s=''):
1188 """Restart logging.
1187 """Restart logging.
1189
1188
1190 This function is for restarting logging which you've temporarily
1189 This function is for restarting logging which you've temporarily
1191 stopped with %logoff. For starting logging for the first time, you
1190 stopped with %logoff. For starting logging for the first time, you
1192 must use the %logstart function, which allows you to specify an
1191 must use the %logstart function, which allows you to specify an
1193 optional log filename."""
1192 optional log filename."""
1194
1193
1195 self.shell.logger.switch_log(1)
1194 self.shell.logger.switch_log(1)
1196
1195
1197 def magic_logstate(self,parameter_s=''):
1196 def magic_logstate(self,parameter_s=''):
1198 """Print the status of the logging system."""
1197 """Print the status of the logging system."""
1199
1198
1200 self.shell.logger.logstate()
1199 self.shell.logger.logstate()
1201
1200
1202 def magic_pdb(self, parameter_s=''):
1201 def magic_pdb(self, parameter_s=''):
1203 """Control the automatic calling of the pdb interactive debugger.
1202 """Control the automatic calling of the pdb interactive debugger.
1204
1203
1205 Call as '%pdb on', '%pdb 1', '%pdb off' or '%pdb 0'. If called without
1204 Call as '%pdb on', '%pdb 1', '%pdb off' or '%pdb 0'. If called without
1206 argument it works as a toggle.
1205 argument it works as a toggle.
1207
1206
1208 When an exception is triggered, IPython can optionally call the
1207 When an exception is triggered, IPython can optionally call the
1209 interactive pdb debugger after the traceback printout. %pdb toggles
1208 interactive pdb debugger after the traceback printout. %pdb toggles
1210 this feature on and off.
1209 this feature on and off.
1211
1210
1212 The initial state of this feature is set in your ipythonrc
1211 The initial state of this feature is set in your ipythonrc
1213 configuration file (the variable is called 'pdb').
1212 configuration file (the variable is called 'pdb').
1214
1213
1215 If you want to just activate the debugger AFTER an exception has fired,
1214 If you want to just activate the debugger AFTER an exception has fired,
1216 without having to type '%pdb on' and rerunning your code, you can use
1215 without having to type '%pdb on' and rerunning your code, you can use
1217 the %debug magic."""
1216 the %debug magic."""
1218
1217
1219 par = parameter_s.strip().lower()
1218 par = parameter_s.strip().lower()
1220
1219
1221 if par:
1220 if par:
1222 try:
1221 try:
1223 new_pdb = {'off':0,'0':0,'on':1,'1':1}[par]
1222 new_pdb = {'off':0,'0':0,'on':1,'1':1}[par]
1224 except KeyError:
1223 except KeyError:
1225 print ('Incorrect argument. Use on/1, off/0, '
1224 print ('Incorrect argument. Use on/1, off/0, '
1226 'or nothing for a toggle.')
1225 'or nothing for a toggle.')
1227 return
1226 return
1228 else:
1227 else:
1229 # toggle
1228 # toggle
1230 new_pdb = not self.shell.call_pdb
1229 new_pdb = not self.shell.call_pdb
1231
1230
1232 # set on the shell
1231 # set on the shell
1233 self.shell.call_pdb = new_pdb
1232 self.shell.call_pdb = new_pdb
1234 print 'Automatic pdb calling has been turned',on_off(new_pdb)
1233 print 'Automatic pdb calling has been turned',on_off(new_pdb)
1235
1234
1236 def magic_debug(self, parameter_s=''):
1235 def magic_debug(self, parameter_s=''):
1237 """Activate the interactive debugger in post-mortem mode.
1236 """Activate the interactive debugger in post-mortem mode.
1238
1237
1239 If an exception has just occurred, this lets you inspect its stack
1238 If an exception has just occurred, this lets you inspect its stack
1240 frames interactively. Note that this will always work only on the last
1239 frames interactively. Note that this will always work only on the last
1241 traceback that occurred, so you must call this quickly after an
1240 traceback that occurred, so you must call this quickly after an
1242 exception that you wish to inspect has fired, because if another one
1241 exception that you wish to inspect has fired, because if another one
1243 occurs, it clobbers the previous one.
1242 occurs, it clobbers the previous one.
1244
1243
1245 If you want IPython to automatically do this on every exception, see
1244 If you want IPython to automatically do this on every exception, see
1246 the %pdb magic for more details.
1245 the %pdb magic for more details.
1247 """
1246 """
1248
1247
1249 self.shell.debugger(force=True)
1248 self.shell.debugger(force=True)
1250
1249
1251 @testdec.skip_doctest
1250 @testdec.skip_doctest
1252 def magic_prun(self, parameter_s ='',user_mode=1,
1251 def magic_prun(self, parameter_s ='',user_mode=1,
1253 opts=None,arg_lst=None,prog_ns=None):
1252 opts=None,arg_lst=None,prog_ns=None):
1254
1253
1255 """Run a statement through the python code profiler.
1254 """Run a statement through the python code profiler.
1256
1255
1257 Usage:
1256 Usage:
1258 %prun [options] statement
1257 %prun [options] statement
1259
1258
1260 The given statement (which doesn't require quote marks) is run via the
1259 The given statement (which doesn't require quote marks) is run via the
1261 python profiler in a manner similar to the profile.run() function.
1260 python profiler in a manner similar to the profile.run() function.
1262 Namespaces are internally managed to work correctly; profile.run
1261 Namespaces are internally managed to work correctly; profile.run
1263 cannot be used in IPython because it makes certain assumptions about
1262 cannot be used in IPython because it makes certain assumptions about
1264 namespaces which do not hold under IPython.
1263 namespaces which do not hold under IPython.
1265
1264
1266 Options:
1265 Options:
1267
1266
1268 -l <limit>: you can place restrictions on what or how much of the
1267 -l <limit>: you can place restrictions on what or how much of the
1269 profile gets printed. The limit value can be:
1268 profile gets printed. The limit value can be:
1270
1269
1271 * A string: only information for function names containing this string
1270 * A string: only information for function names containing this string
1272 is printed.
1271 is printed.
1273
1272
1274 * An integer: only these many lines are printed.
1273 * An integer: only these many lines are printed.
1275
1274
1276 * A float (between 0 and 1): this fraction of the report is printed
1275 * A float (between 0 and 1): this fraction of the report is printed
1277 (for example, use a limit of 0.4 to see the topmost 40% only).
1276 (for example, use a limit of 0.4 to see the topmost 40% only).
1278
1277
1279 You can combine several limits with repeated use of the option. For
1278 You can combine several limits with repeated use of the option. For
1280 example, '-l __init__ -l 5' will print only the topmost 5 lines of
1279 example, '-l __init__ -l 5' will print only the topmost 5 lines of
1281 information about class constructors.
1280 information about class constructors.
1282
1281
1283 -r: return the pstats.Stats object generated by the profiling. This
1282 -r: return the pstats.Stats object generated by the profiling. This
1284 object has all the information about the profile in it, and you can
1283 object has all the information about the profile in it, and you can
1285 later use it for further analysis or in other functions.
1284 later use it for further analysis or in other functions.
1286
1285
1287 -s <key>: sort profile by given key. You can provide more than one key
1286 -s <key>: sort profile by given key. You can provide more than one key
1288 by using the option several times: '-s key1 -s key2 -s key3...'. The
1287 by using the option several times: '-s key1 -s key2 -s key3...'. The
1289 default sorting key is 'time'.
1288 default sorting key is 'time'.
1290
1289
1291 The following is copied verbatim from the profile documentation
1290 The following is copied verbatim from the profile documentation
1292 referenced below:
1291 referenced below:
1293
1292
1294 When more than one key is provided, additional keys are used as
1293 When more than one key is provided, additional keys are used as
1295 secondary criteria when the there is equality in all keys selected
1294 secondary criteria when the there is equality in all keys selected
1296 before them.
1295 before them.
1297
1296
1298 Abbreviations can be used for any key names, as long as the
1297 Abbreviations can be used for any key names, as long as the
1299 abbreviation is unambiguous. The following are the keys currently
1298 abbreviation is unambiguous. The following are the keys currently
1300 defined:
1299 defined:
1301
1300
1302 Valid Arg Meaning
1301 Valid Arg Meaning
1303 "calls" call count
1302 "calls" call count
1304 "cumulative" cumulative time
1303 "cumulative" cumulative time
1305 "file" file name
1304 "file" file name
1306 "module" file name
1305 "module" file name
1307 "pcalls" primitive call count
1306 "pcalls" primitive call count
1308 "line" line number
1307 "line" line number
1309 "name" function name
1308 "name" function name
1310 "nfl" name/file/line
1309 "nfl" name/file/line
1311 "stdname" standard name
1310 "stdname" standard name
1312 "time" internal time
1311 "time" internal time
1313
1312
1314 Note that all sorts on statistics are in descending order (placing
1313 Note that all sorts on statistics are in descending order (placing
1315 most time consuming items first), where as name, file, and line number
1314 most time consuming items first), where as name, file, and line number
1316 searches are in ascending order (i.e., alphabetical). The subtle
1315 searches are in ascending order (i.e., alphabetical). The subtle
1317 distinction between "nfl" and "stdname" is that the standard name is a
1316 distinction between "nfl" and "stdname" is that the standard name is a
1318 sort of the name as printed, which means that the embedded line
1317 sort of the name as printed, which means that the embedded line
1319 numbers get compared in an odd way. For example, lines 3, 20, and 40
1318 numbers get compared in an odd way. For example, lines 3, 20, and 40
1320 would (if the file names were the same) appear in the string order
1319 would (if the file names were the same) appear in the string order
1321 "20" "3" and "40". In contrast, "nfl" does a numeric compare of the
1320 "20" "3" and "40". In contrast, "nfl" does a numeric compare of the
1322 line numbers. In fact, sort_stats("nfl") is the same as
1321 line numbers. In fact, sort_stats("nfl") is the same as
1323 sort_stats("name", "file", "line").
1322 sort_stats("name", "file", "line").
1324
1323
1325 -T <filename>: save profile results as shown on screen to a text
1324 -T <filename>: save profile results as shown on screen to a text
1326 file. The profile is still shown on screen.
1325 file. The profile is still shown on screen.
1327
1326
1328 -D <filename>: save (via dump_stats) profile statistics to given
1327 -D <filename>: save (via dump_stats) profile statistics to given
1329 filename. This data is in a format understod by the pstats module, and
1328 filename. This data is in a format understod by the pstats module, and
1330 is generated by a call to the dump_stats() method of profile
1329 is generated by a call to the dump_stats() method of profile
1331 objects. The profile is still shown on screen.
1330 objects. The profile is still shown on screen.
1332
1331
1333 If you want to run complete programs under the profiler's control, use
1332 If you want to run complete programs under the profiler's control, use
1334 '%run -p [prof_opts] filename.py [args to program]' where prof_opts
1333 '%run -p [prof_opts] filename.py [args to program]' where prof_opts
1335 contains profiler specific options as described here.
1334 contains profiler specific options as described here.
1336
1335
1337 You can read the complete documentation for the profile module with::
1336 You can read the complete documentation for the profile module with::
1338
1337
1339 In [1]: import profile; profile.help()
1338 In [1]: import profile; profile.help()
1340 """
1339 """
1341
1340
1342 opts_def = Struct(D=[''],l=[],s=['time'],T=[''])
1341 opts_def = Struct(D=[''],l=[],s=['time'],T=[''])
1343 # protect user quote marks
1342 # protect user quote marks
1344 parameter_s = parameter_s.replace('"',r'\"').replace("'",r"\'")
1343 parameter_s = parameter_s.replace('"',r'\"').replace("'",r"\'")
1345
1344
1346 if user_mode: # regular user call
1345 if user_mode: # regular user call
1347 opts,arg_str = self.parse_options(parameter_s,'D:l:rs:T:',
1346 opts,arg_str = self.parse_options(parameter_s,'D:l:rs:T:',
1348 list_all=1)
1347 list_all=1)
1349 namespace = self.shell.user_ns
1348 namespace = self.shell.user_ns
1350 else: # called to run a program by %run -p
1349 else: # called to run a program by %run -p
1351 try:
1350 try:
1352 filename = get_py_filename(arg_lst[0])
1351 filename = get_py_filename(arg_lst[0])
1353 except IOError,msg:
1352 except IOError,msg:
1354 error(msg)
1353 error(msg)
1355 return
1354 return
1356
1355
1357 arg_str = 'execfile(filename,prog_ns)'
1356 arg_str = 'execfile(filename,prog_ns)'
1358 namespace = locals()
1357 namespace = locals()
1359
1358
1360 opts.merge(opts_def)
1359 opts.merge(opts_def)
1361
1360
1362 prof = profile.Profile()
1361 prof = profile.Profile()
1363 try:
1362 try:
1364 prof = prof.runctx(arg_str,namespace,namespace)
1363 prof = prof.runctx(arg_str,namespace,namespace)
1365 sys_exit = ''
1364 sys_exit = ''
1366 except SystemExit:
1365 except SystemExit:
1367 sys_exit = """*** SystemExit exception caught in code being profiled."""
1366 sys_exit = """*** SystemExit exception caught in code being profiled."""
1368
1367
1369 stats = pstats.Stats(prof).strip_dirs().sort_stats(*opts.s)
1368 stats = pstats.Stats(prof).strip_dirs().sort_stats(*opts.s)
1370
1369
1371 lims = opts.l
1370 lims = opts.l
1372 if lims:
1371 if lims:
1373 lims = [] # rebuild lims with ints/floats/strings
1372 lims = [] # rebuild lims with ints/floats/strings
1374 for lim in opts.l:
1373 for lim in opts.l:
1375 try:
1374 try:
1376 lims.append(int(lim))
1375 lims.append(int(lim))
1377 except ValueError:
1376 except ValueError:
1378 try:
1377 try:
1379 lims.append(float(lim))
1378 lims.append(float(lim))
1380 except ValueError:
1379 except ValueError:
1381 lims.append(lim)
1380 lims.append(lim)
1382
1381
1383 # Trap output.
1382 # Trap output.
1384 stdout_trap = StringIO()
1383 stdout_trap = StringIO()
1385
1384
1386 if hasattr(stats,'stream'):
1385 if hasattr(stats,'stream'):
1387 # In newer versions of python, the stats object has a 'stream'
1386 # In newer versions of python, the stats object has a 'stream'
1388 # attribute to write into.
1387 # attribute to write into.
1389 stats.stream = stdout_trap
1388 stats.stream = stdout_trap
1390 stats.print_stats(*lims)
1389 stats.print_stats(*lims)
1391 else:
1390 else:
1392 # For older versions, we manually redirect stdout during printing
1391 # For older versions, we manually redirect stdout during printing
1393 sys_stdout = sys.stdout
1392 sys_stdout = sys.stdout
1394 try:
1393 try:
1395 sys.stdout = stdout_trap
1394 sys.stdout = stdout_trap
1396 stats.print_stats(*lims)
1395 stats.print_stats(*lims)
1397 finally:
1396 finally:
1398 sys.stdout = sys_stdout
1397 sys.stdout = sys_stdout
1399
1398
1400 output = stdout_trap.getvalue()
1399 output = stdout_trap.getvalue()
1401 output = output.rstrip()
1400 output = output.rstrip()
1402
1401
1403 page(output,screen_lines=self.shell.rc.screen_length)
1402 page(output,screen_lines=self.shell.rc.screen_length)
1404 print sys_exit,
1403 print sys_exit,
1405
1404
1406 dump_file = opts.D[0]
1405 dump_file = opts.D[0]
1407 text_file = opts.T[0]
1406 text_file = opts.T[0]
1408 if dump_file:
1407 if dump_file:
1409 prof.dump_stats(dump_file)
1408 prof.dump_stats(dump_file)
1410 print '\n*** Profile stats marshalled to file',\
1409 print '\n*** Profile stats marshalled to file',\
1411 `dump_file`+'.',sys_exit
1410 `dump_file`+'.',sys_exit
1412 if text_file:
1411 if text_file:
1413 pfile = file(text_file,'w')
1412 pfile = file(text_file,'w')
1414 pfile.write(output)
1413 pfile.write(output)
1415 pfile.close()
1414 pfile.close()
1416 print '\n*** Profile printout saved to text file',\
1415 print '\n*** Profile printout saved to text file',\
1417 `text_file`+'.',sys_exit
1416 `text_file`+'.',sys_exit
1418
1417
1419 if opts.has_key('r'):
1418 if opts.has_key('r'):
1420 return stats
1419 return stats
1421 else:
1420 else:
1422 return None
1421 return None
1423
1422
1424 @testdec.skip_doctest
1423 @testdec.skip_doctest
1425 def magic_run(self, parameter_s ='',runner=None,
1424 def magic_run(self, parameter_s ='',runner=None,
1426 file_finder=get_py_filename):
1425 file_finder=get_py_filename):
1427 """Run the named file inside IPython as a program.
1426 """Run the named file inside IPython as a program.
1428
1427
1429 Usage:\\
1428 Usage:\\
1430 %run [-n -i -t [-N<N>] -d [-b<N>] -p [profile options]] file [args]
1429 %run [-n -i -t [-N<N>] -d [-b<N>] -p [profile options]] file [args]
1431
1430
1432 Parameters after the filename are passed as command-line arguments to
1431 Parameters after the filename are passed as command-line arguments to
1433 the program (put in sys.argv). Then, control returns to IPython's
1432 the program (put in sys.argv). Then, control returns to IPython's
1434 prompt.
1433 prompt.
1435
1434
1436 This is similar to running at a system prompt:\\
1435 This is similar to running at a system prompt:\\
1437 $ python file args\\
1436 $ python file args\\
1438 but with the advantage of giving you IPython's tracebacks, and of
1437 but with the advantage of giving you IPython's tracebacks, and of
1439 loading all variables into your interactive namespace for further use
1438 loading all variables into your interactive namespace for further use
1440 (unless -p is used, see below).
1439 (unless -p is used, see below).
1441
1440
1442 The file is executed in a namespace initially consisting only of
1441 The file is executed in a namespace initially consisting only of
1443 __name__=='__main__' and sys.argv constructed as indicated. It thus
1442 __name__=='__main__' and sys.argv constructed as indicated. It thus
1444 sees its environment as if it were being run as a stand-alone program
1443 sees its environment as if it were being run as a stand-alone program
1445 (except for sharing global objects such as previously imported
1444 (except for sharing global objects such as previously imported
1446 modules). But after execution, the IPython interactive namespace gets
1445 modules). But after execution, the IPython interactive namespace gets
1447 updated with all variables defined in the program (except for __name__
1446 updated with all variables defined in the program (except for __name__
1448 and sys.argv). This allows for very convenient loading of code for
1447 and sys.argv). This allows for very convenient loading of code for
1449 interactive work, while giving each program a 'clean sheet' to run in.
1448 interactive work, while giving each program a 'clean sheet' to run in.
1450
1449
1451 Options:
1450 Options:
1452
1451
1453 -n: __name__ is NOT set to '__main__', but to the running file's name
1452 -n: __name__ is NOT set to '__main__', but to the running file's name
1454 without extension (as python does under import). This allows running
1453 without extension (as python does under import). This allows running
1455 scripts and reloading the definitions in them without calling code
1454 scripts and reloading the definitions in them without calling code
1456 protected by an ' if __name__ == "__main__" ' clause.
1455 protected by an ' if __name__ == "__main__" ' clause.
1457
1456
1458 -i: run the file in IPython's namespace instead of an empty one. This
1457 -i: run the file in IPython's namespace instead of an empty one. This
1459 is useful if you are experimenting with code written in a text editor
1458 is useful if you are experimenting with code written in a text editor
1460 which depends on variables defined interactively.
1459 which depends on variables defined interactively.
1461
1460
1462 -e: ignore sys.exit() calls or SystemExit exceptions in the script
1461 -e: ignore sys.exit() calls or SystemExit exceptions in the script
1463 being run. This is particularly useful if IPython is being used to
1462 being run. This is particularly useful if IPython is being used to
1464 run unittests, which always exit with a sys.exit() call. In such
1463 run unittests, which always exit with a sys.exit() call. In such
1465 cases you are interested in the output of the test results, not in
1464 cases you are interested in the output of the test results, not in
1466 seeing a traceback of the unittest module.
1465 seeing a traceback of the unittest module.
1467
1466
1468 -t: print timing information at the end of the run. IPython will give
1467 -t: print timing information at the end of the run. IPython will give
1469 you an estimated CPU time consumption for your script, which under
1468 you an estimated CPU time consumption for your script, which under
1470 Unix uses the resource module to avoid the wraparound problems of
1469 Unix uses the resource module to avoid the wraparound problems of
1471 time.clock(). Under Unix, an estimate of time spent on system tasks
1470 time.clock(). Under Unix, an estimate of time spent on system tasks
1472 is also given (for Windows platforms this is reported as 0.0).
1471 is also given (for Windows platforms this is reported as 0.0).
1473
1472
1474 If -t is given, an additional -N<N> option can be given, where <N>
1473 If -t is given, an additional -N<N> option can be given, where <N>
1475 must be an integer indicating how many times you want the script to
1474 must be an integer indicating how many times you want the script to
1476 run. The final timing report will include total and per run results.
1475 run. The final timing report will include total and per run results.
1477
1476
1478 For example (testing the script uniq_stable.py):
1477 For example (testing the script uniq_stable.py):
1479
1478
1480 In [1]: run -t uniq_stable
1479 In [1]: run -t uniq_stable
1481
1480
1482 IPython CPU timings (estimated):\\
1481 IPython CPU timings (estimated):\\
1483 User : 0.19597 s.\\
1482 User : 0.19597 s.\\
1484 System: 0.0 s.\\
1483 System: 0.0 s.\\
1485
1484
1486 In [2]: run -t -N5 uniq_stable
1485 In [2]: run -t -N5 uniq_stable
1487
1486
1488 IPython CPU timings (estimated):\\
1487 IPython CPU timings (estimated):\\
1489 Total runs performed: 5\\
1488 Total runs performed: 5\\
1490 Times : Total Per run\\
1489 Times : Total Per run\\
1491 User : 0.910862 s, 0.1821724 s.\\
1490 User : 0.910862 s, 0.1821724 s.\\
1492 System: 0.0 s, 0.0 s.
1491 System: 0.0 s, 0.0 s.
1493
1492
1494 -d: run your program under the control of pdb, the Python debugger.
1493 -d: run your program under the control of pdb, the Python debugger.
1495 This allows you to execute your program step by step, watch variables,
1494 This allows you to execute your program step by step, watch variables,
1496 etc. Internally, what IPython does is similar to calling:
1495 etc. Internally, what IPython does is similar to calling:
1497
1496
1498 pdb.run('execfile("YOURFILENAME")')
1497 pdb.run('execfile("YOURFILENAME")')
1499
1498
1500 with a breakpoint set on line 1 of your file. You can change the line
1499 with a breakpoint set on line 1 of your file. You can change the line
1501 number for this automatic breakpoint to be <N> by using the -bN option
1500 number for this automatic breakpoint to be <N> by using the -bN option
1502 (where N must be an integer). For example:
1501 (where N must be an integer). For example:
1503
1502
1504 %run -d -b40 myscript
1503 %run -d -b40 myscript
1505
1504
1506 will set the first breakpoint at line 40 in myscript.py. Note that
1505 will set the first breakpoint at line 40 in myscript.py. Note that
1507 the first breakpoint must be set on a line which actually does
1506 the first breakpoint must be set on a line which actually does
1508 something (not a comment or docstring) for it to stop execution.
1507 something (not a comment or docstring) for it to stop execution.
1509
1508
1510 When the pdb debugger starts, you will see a (Pdb) prompt. You must
1509 When the pdb debugger starts, you will see a (Pdb) prompt. You must
1511 first enter 'c' (without qoutes) to start execution up to the first
1510 first enter 'c' (without qoutes) to start execution up to the first
1512 breakpoint.
1511 breakpoint.
1513
1512
1514 Entering 'help' gives information about the use of the debugger. You
1513 Entering 'help' gives information about the use of the debugger. You
1515 can easily see pdb's full documentation with "import pdb;pdb.help()"
1514 can easily see pdb's full documentation with "import pdb;pdb.help()"
1516 at a prompt.
1515 at a prompt.
1517
1516
1518 -p: run program under the control of the Python profiler module (which
1517 -p: run program under the control of the Python profiler module (which
1519 prints a detailed report of execution times, function calls, etc).
1518 prints a detailed report of execution times, function calls, etc).
1520
1519
1521 You can pass other options after -p which affect the behavior of the
1520 You can pass other options after -p which affect the behavior of the
1522 profiler itself. See the docs for %prun for details.
1521 profiler itself. See the docs for %prun for details.
1523
1522
1524 In this mode, the program's variables do NOT propagate back to the
1523 In this mode, the program's variables do NOT propagate back to the
1525 IPython interactive namespace (because they remain in the namespace
1524 IPython interactive namespace (because they remain in the namespace
1526 where the profiler executes them).
1525 where the profiler executes them).
1527
1526
1528 Internally this triggers a call to %prun, see its documentation for
1527 Internally this triggers a call to %prun, see its documentation for
1529 details on the options available specifically for profiling.
1528 details on the options available specifically for profiling.
1530
1529
1531 There is one special usage for which the text above doesn't apply:
1530 There is one special usage for which the text above doesn't apply:
1532 if the filename ends with .ipy, the file is run as ipython script,
1531 if the filename ends with .ipy, the file is run as ipython script,
1533 just as if the commands were written on IPython prompt.
1532 just as if the commands were written on IPython prompt.
1534 """
1533 """
1535
1534
1536 # get arguments and set sys.argv for program to be run.
1535 # get arguments and set sys.argv for program to be run.
1537 opts,arg_lst = self.parse_options(parameter_s,'nidtN:b:pD:l:rs:T:e',
1536 opts,arg_lst = self.parse_options(parameter_s,'nidtN:b:pD:l:rs:T:e',
1538 mode='list',list_all=1)
1537 mode='list',list_all=1)
1539
1538
1540 try:
1539 try:
1541 filename = file_finder(arg_lst[0])
1540 filename = file_finder(arg_lst[0])
1542 except IndexError:
1541 except IndexError:
1543 warn('you must provide at least a filename.')
1542 warn('you must provide at least a filename.')
1544 print '\n%run:\n',OInspect.getdoc(self.magic_run)
1543 print '\n%run:\n',OInspect.getdoc(self.magic_run)
1545 return
1544 return
1546 except IOError,msg:
1545 except IOError,msg:
1547 error(msg)
1546 error(msg)
1548 return
1547 return
1549
1548
1550 if filename.lower().endswith('.ipy'):
1549 if filename.lower().endswith('.ipy'):
1551 self.api.runlines(open(filename).read())
1550 self.api.runlines(open(filename).read())
1552 return
1551 return
1553
1552
1554 # Control the response to exit() calls made by the script being run
1553 # Control the response to exit() calls made by the script being run
1555 exit_ignore = opts.has_key('e')
1554 exit_ignore = opts.has_key('e')
1556
1555
1557 # Make sure that the running script gets a proper sys.argv as if it
1556 # Make sure that the running script gets a proper sys.argv as if it
1558 # were run from a system shell.
1557 # were run from a system shell.
1559 save_argv = sys.argv # save it for later restoring
1558 save_argv = sys.argv # save it for later restoring
1560 sys.argv = [filename]+ arg_lst[1:] # put in the proper filename
1559 sys.argv = [filename]+ arg_lst[1:] # put in the proper filename
1561
1560
1562 if opts.has_key('i'):
1561 if opts.has_key('i'):
1563 # Run in user's interactive namespace
1562 # Run in user's interactive namespace
1564 prog_ns = self.shell.user_ns
1563 prog_ns = self.shell.user_ns
1565 __name__save = self.shell.user_ns['__name__']
1564 __name__save = self.shell.user_ns['__name__']
1566 prog_ns['__name__'] = '__main__'
1565 prog_ns['__name__'] = '__main__'
1567 main_mod = FakeModule(prog_ns)
1566 main_mod = FakeModule(prog_ns)
1568 else:
1567 else:
1569 # Run in a fresh, empty namespace
1568 # Run in a fresh, empty namespace
1570 if opts.has_key('n'):
1569 if opts.has_key('n'):
1571 name = os.path.splitext(os.path.basename(filename))[0]
1570 name = os.path.splitext(os.path.basename(filename))[0]
1572 else:
1571 else:
1573 name = '__main__'
1572 name = '__main__'
1574 main_mod = FakeModule()
1573 main_mod = FakeModule()
1575 prog_ns = main_mod.__dict__
1574 prog_ns = main_mod.__dict__
1576 prog_ns['__name__'] = name
1575 prog_ns['__name__'] = name
1577
1576
1578 # The shell MUST hold a reference to main_mod so after %run exits,
1577 # The shell MUST hold a reference to main_mod so after %run exits,
1579 # the python deletion mechanism doesn't zero it out (leaving
1578 # the python deletion mechanism doesn't zero it out (leaving
1580 # dangling references)
1579 # dangling references)
1581
1580
1582 # XXX - the note above was written without further detail, but this
1581 # XXX - the note above was written without further detail, but this
1583 # code actually causes problems. By holding references to the
1582 # code actually causes problems. By holding references to the
1584 # namespace where every script is executed, we effectively disable
1583 # namespace where every script is executed, we effectively disable
1585 # just about all possible variable cleanup. In particular,
1584 # just about all possible variable cleanup. In particular,
1586 # generator expressions and other variables that point to open
1585 # generator expressions and other variables that point to open
1587 # files are kept alive, and as a user session lives on, it may run
1586 # files are kept alive, and as a user session lives on, it may run
1588 # out of available file descriptors. Such a bug has already been
1587 # out of available file descriptors. Such a bug has already been
1589 # reported by JD Hunter. I'm disabling this for now, but we need
1588 # reported by JD Hunter. I'm disabling this for now, but we need
1590 # to clarify exactly (and add tests) what from main_mod needs to be
1589 # to clarify exactly (and add tests) what from main_mod needs to be
1591 # kept alive and what is save to remove... In fact, see note
1590 # kept alive and what is save to remove... In fact, see note
1592 # below, where we append main_mod to sys.modules and then delete it
1591 # below, where we append main_mod to sys.modules and then delete it
1593 # again. The final cleanup is rendered moot by this reference kept
1592 # again. The final cleanup is rendered moot by this reference kept
1594 # in _user_main_modules(), so we really need to look into this.
1593 # in _user_main_modules(), so we really need to look into this.
1595
1594
1596 self.shell._user_main_modules.append(main_mod)
1595 self.shell._user_main_modules.append(main_mod)
1597
1596
1598 # /XXX
1597 # /XXX
1599
1598
1600 # Since '%run foo' emulates 'python foo.py' at the cmd line, we must
1599 # Since '%run foo' emulates 'python foo.py' at the cmd line, we must
1601 # set the __file__ global in the script's namespace
1600 # set the __file__ global in the script's namespace
1602 prog_ns['__file__'] = filename
1601 prog_ns['__file__'] = filename
1603
1602
1604 # pickle fix. See iplib for an explanation. But we need to make sure
1603 # pickle fix. See iplib for an explanation. But we need to make sure
1605 # that, if we overwrite __main__, we replace it at the end
1604 # that, if we overwrite __main__, we replace it at the end
1606 main_mod_name = prog_ns['__name__']
1605 main_mod_name = prog_ns['__name__']
1607
1606
1608 if main_mod_name == '__main__':
1607 if main_mod_name == '__main__':
1609 restore_main = sys.modules['__main__']
1608 restore_main = sys.modules['__main__']
1610 else:
1609 else:
1611 restore_main = False
1610 restore_main = False
1612
1611
1613 # This needs to be undone at the end to prevent holding references to
1612 # This needs to be undone at the end to prevent holding references to
1614 # every single object ever created.
1613 # every single object ever created.
1615 sys.modules[main_mod_name] = main_mod
1614 sys.modules[main_mod_name] = main_mod
1616
1615
1617 stats = None
1616 stats = None
1618 try:
1617 try:
1619 self.shell.savehist()
1618 self.shell.savehist()
1620
1619
1621 if opts.has_key('p'):
1620 if opts.has_key('p'):
1622 stats = self.magic_prun('',0,opts,arg_lst,prog_ns)
1621 stats = self.magic_prun('',0,opts,arg_lst,prog_ns)
1623 else:
1622 else:
1624 if opts.has_key('d'):
1623 if opts.has_key('d'):
1625 deb = Debugger.Pdb(self.shell.rc.colors)
1624 deb = Debugger.Pdb(self.shell.rc.colors)
1626 # reset Breakpoint state, which is moronically kept
1625 # reset Breakpoint state, which is moronically kept
1627 # in a class
1626 # in a class
1628 bdb.Breakpoint.next = 1
1627 bdb.Breakpoint.next = 1
1629 bdb.Breakpoint.bplist = {}
1628 bdb.Breakpoint.bplist = {}
1630 bdb.Breakpoint.bpbynumber = [None]
1629 bdb.Breakpoint.bpbynumber = [None]
1631 # Set an initial breakpoint to stop execution
1630 # Set an initial breakpoint to stop execution
1632 maxtries = 10
1631 maxtries = 10
1633 bp = int(opts.get('b',[1])[0])
1632 bp = int(opts.get('b',[1])[0])
1634 checkline = deb.checkline(filename,bp)
1633 checkline = deb.checkline(filename,bp)
1635 if not checkline:
1634 if not checkline:
1636 for bp in range(bp+1,bp+maxtries+1):
1635 for bp in range(bp+1,bp+maxtries+1):
1637 if deb.checkline(filename,bp):
1636 if deb.checkline(filename,bp):
1638 break
1637 break
1639 else:
1638 else:
1640 msg = ("\nI failed to find a valid line to set "
1639 msg = ("\nI failed to find a valid line to set "
1641 "a breakpoint\n"
1640 "a breakpoint\n"
1642 "after trying up to line: %s.\n"
1641 "after trying up to line: %s.\n"
1643 "Please set a valid breakpoint manually "
1642 "Please set a valid breakpoint manually "
1644 "with the -b option." % bp)
1643 "with the -b option." % bp)
1645 error(msg)
1644 error(msg)
1646 return
1645 return
1647 # if we find a good linenumber, set the breakpoint
1646 # if we find a good linenumber, set the breakpoint
1648 deb.do_break('%s:%s' % (filename,bp))
1647 deb.do_break('%s:%s' % (filename,bp))
1649 # Start file run
1648 # Start file run
1650 print "NOTE: Enter 'c' at the",
1649 print "NOTE: Enter 'c' at the",
1651 print "%s prompt to start your script." % deb.prompt
1650 print "%s prompt to start your script." % deb.prompt
1652 try:
1651 try:
1653 deb.run('execfile("%s")' % filename,prog_ns)
1652 deb.run('execfile("%s")' % filename,prog_ns)
1654
1653
1655 except:
1654 except:
1656 etype, value, tb = sys.exc_info()
1655 etype, value, tb = sys.exc_info()
1657 # Skip three frames in the traceback: the %run one,
1656 # Skip three frames in the traceback: the %run one,
1658 # one inside bdb.py, and the command-line typed by the
1657 # one inside bdb.py, and the command-line typed by the
1659 # user (run by exec in pdb itself).
1658 # user (run by exec in pdb itself).
1660 self.shell.InteractiveTB(etype,value,tb,tb_offset=3)
1659 self.shell.InteractiveTB(etype,value,tb,tb_offset=3)
1661 else:
1660 else:
1662 if runner is None:
1661 if runner is None:
1663 runner = self.shell.safe_execfile
1662 runner = self.shell.safe_execfile
1664 if opts.has_key('t'):
1663 if opts.has_key('t'):
1665 # timed execution
1664 # timed execution
1666 try:
1665 try:
1667 nruns = int(opts['N'][0])
1666 nruns = int(opts['N'][0])
1668 if nruns < 1:
1667 if nruns < 1:
1669 error('Number of runs must be >=1')
1668 error('Number of runs must be >=1')
1670 return
1669 return
1671 except (KeyError):
1670 except (KeyError):
1672 nruns = 1
1671 nruns = 1
1673 if nruns == 1:
1672 if nruns == 1:
1674 t0 = clock2()
1673 t0 = clock2()
1675 runner(filename,prog_ns,prog_ns,
1674 runner(filename,prog_ns,prog_ns,
1676 exit_ignore=exit_ignore)
1675 exit_ignore=exit_ignore)
1677 t1 = clock2()
1676 t1 = clock2()
1678 t_usr = t1[0]-t0[0]
1677 t_usr = t1[0]-t0[0]
1679 t_sys = t1[1]-t1[1]
1678 t_sys = t1[1]-t1[1]
1680 print "\nIPython CPU timings (estimated):"
1679 print "\nIPython CPU timings (estimated):"
1681 print " User : %10s s." % t_usr
1680 print " User : %10s s." % t_usr
1682 print " System: %10s s." % t_sys
1681 print " System: %10s s." % t_sys
1683 else:
1682 else:
1684 runs = range(nruns)
1683 runs = range(nruns)
1685 t0 = clock2()
1684 t0 = clock2()
1686 for nr in runs:
1685 for nr in runs:
1687 runner(filename,prog_ns,prog_ns,
1686 runner(filename,prog_ns,prog_ns,
1688 exit_ignore=exit_ignore)
1687 exit_ignore=exit_ignore)
1689 t1 = clock2()
1688 t1 = clock2()
1690 t_usr = t1[0]-t0[0]
1689 t_usr = t1[0]-t0[0]
1691 t_sys = t1[1]-t1[1]
1690 t_sys = t1[1]-t1[1]
1692 print "\nIPython CPU timings (estimated):"
1691 print "\nIPython CPU timings (estimated):"
1693 print "Total runs performed:",nruns
1692 print "Total runs performed:",nruns
1694 print " Times : %10s %10s" % ('Total','Per run')
1693 print " Times : %10s %10s" % ('Total','Per run')
1695 print " User : %10s s, %10s s." % (t_usr,t_usr/nruns)
1694 print " User : %10s s, %10s s." % (t_usr,t_usr/nruns)
1696 print " System: %10s s, %10s s." % (t_sys,t_sys/nruns)
1695 print " System: %10s s, %10s s." % (t_sys,t_sys/nruns)
1697
1696
1698 else:
1697 else:
1699 # regular execution
1698 # regular execution
1700 runner(filename,prog_ns,prog_ns,exit_ignore=exit_ignore)
1699 runner(filename,prog_ns,prog_ns,exit_ignore=exit_ignore)
1701 if opts.has_key('i'):
1700 if opts.has_key('i'):
1702 self.shell.user_ns['__name__'] = __name__save
1701 self.shell.user_ns['__name__'] = __name__save
1703 else:
1702 else:
1704 # update IPython interactive namespace
1703 # update IPython interactive namespace
1705 del prog_ns['__name__']
1704 del prog_ns['__name__']
1706 self.shell.user_ns.update(prog_ns)
1705 self.shell.user_ns.update(prog_ns)
1707 finally:
1706 finally:
1708 # Ensure key global structures are restored
1707 # Ensure key global structures are restored
1709 sys.argv = save_argv
1708 sys.argv = save_argv
1710 if restore_main:
1709 if restore_main:
1711 sys.modules['__main__'] = restore_main
1710 sys.modules['__main__'] = restore_main
1712 else:
1711 else:
1713 # Remove from sys.modules the reference to main_mod we'd
1712 # Remove from sys.modules the reference to main_mod we'd
1714 # added. Otherwise it will trap references to objects
1713 # added. Otherwise it will trap references to objects
1715 # contained therein.
1714 # contained therein.
1716 del sys.modules[main_mod_name]
1715 del sys.modules[main_mod_name]
1717 self.shell.reloadhist()
1716 self.shell.reloadhist()
1718
1717
1719 return stats
1718 return stats
1720
1719
1721 def magic_runlog(self, parameter_s =''):
1720 def magic_runlog(self, parameter_s =''):
1722 """Run files as logs.
1721 """Run files as logs.
1723
1722
1724 Usage:\\
1723 Usage:\\
1725 %runlog file1 file2 ...
1724 %runlog file1 file2 ...
1726
1725
1727 Run the named files (treating them as log files) in sequence inside
1726 Run the named files (treating them as log files) in sequence inside
1728 the interpreter, and return to the prompt. This is much slower than
1727 the interpreter, and return to the prompt. This is much slower than
1729 %run because each line is executed in a try/except block, but it
1728 %run because each line is executed in a try/except block, but it
1730 allows running files with syntax errors in them.
1729 allows running files with syntax errors in them.
1731
1730
1732 Normally IPython will guess when a file is one of its own logfiles, so
1731 Normally IPython will guess when a file is one of its own logfiles, so
1733 you can typically use %run even for logs. This shorthand allows you to
1732 you can typically use %run even for logs. This shorthand allows you to
1734 force any file to be treated as a log file."""
1733 force any file to be treated as a log file."""
1735
1734
1736 for f in parameter_s.split():
1735 for f in parameter_s.split():
1737 self.shell.safe_execfile(f,self.shell.user_ns,
1736 self.shell.safe_execfile(f,self.shell.user_ns,
1738 self.shell.user_ns,islog=1)
1737 self.shell.user_ns,islog=1)
1739
1738
1740 @testdec.skip_doctest
1739 @testdec.skip_doctest
1741 def magic_timeit(self, parameter_s =''):
1740 def magic_timeit(self, parameter_s =''):
1742 """Time execution of a Python statement or expression
1741 """Time execution of a Python statement or expression
1743
1742
1744 Usage:\\
1743 Usage:\\
1745 %timeit [-n<N> -r<R> [-t|-c]] statement
1744 %timeit [-n<N> -r<R> [-t|-c]] statement
1746
1745
1747 Time execution of a Python statement or expression using the timeit
1746 Time execution of a Python statement or expression using the timeit
1748 module.
1747 module.
1749
1748
1750 Options:
1749 Options:
1751 -n<N>: execute the given statement <N> times in a loop. If this value
1750 -n<N>: execute the given statement <N> times in a loop. If this value
1752 is not given, a fitting value is chosen.
1751 is not given, a fitting value is chosen.
1753
1752
1754 -r<R>: repeat the loop iteration <R> times and take the best result.
1753 -r<R>: repeat the loop iteration <R> times and take the best result.
1755 Default: 3
1754 Default: 3
1756
1755
1757 -t: use time.time to measure the time, which is the default on Unix.
1756 -t: use time.time to measure the time, which is the default on Unix.
1758 This function measures wall time.
1757 This function measures wall time.
1759
1758
1760 -c: use time.clock to measure the time, which is the default on
1759 -c: use time.clock to measure the time, which is the default on
1761 Windows and measures wall time. On Unix, resource.getrusage is used
1760 Windows and measures wall time. On Unix, resource.getrusage is used
1762 instead and returns the CPU user time.
1761 instead and returns the CPU user time.
1763
1762
1764 -p<P>: use a precision of <P> digits to display the timing result.
1763 -p<P>: use a precision of <P> digits to display the timing result.
1765 Default: 3
1764 Default: 3
1766
1765
1767
1766
1768 Examples:
1767 Examples:
1769
1768
1770 In [1]: %timeit pass
1769 In [1]: %timeit pass
1771 10000000 loops, best of 3: 53.3 ns per loop
1770 10000000 loops, best of 3: 53.3 ns per loop
1772
1771
1773 In [2]: u = None
1772 In [2]: u = None
1774
1773
1775 In [3]: %timeit u is None
1774 In [3]: %timeit u is None
1776 10000000 loops, best of 3: 184 ns per loop
1775 10000000 loops, best of 3: 184 ns per loop
1777
1776
1778 In [4]: %timeit -r 4 u == None
1777 In [4]: %timeit -r 4 u == None
1779 1000000 loops, best of 4: 242 ns per loop
1778 1000000 loops, best of 4: 242 ns per loop
1780
1779
1781 In [5]: import time
1780 In [5]: import time
1782
1781
1783 In [6]: %timeit -n1 time.sleep(2)
1782 In [6]: %timeit -n1 time.sleep(2)
1784 1 loops, best of 3: 2 s per loop
1783 1 loops, best of 3: 2 s per loop
1785
1784
1786
1785
1787 The times reported by %timeit will be slightly higher than those
1786 The times reported by %timeit will be slightly higher than those
1788 reported by the timeit.py script when variables are accessed. This is
1787 reported by the timeit.py script when variables are accessed. This is
1789 due to the fact that %timeit executes the statement in the namespace
1788 due to the fact that %timeit executes the statement in the namespace
1790 of the shell, compared with timeit.py, which uses a single setup
1789 of the shell, compared with timeit.py, which uses a single setup
1791 statement to import function or create variables. Generally, the bias
1790 statement to import function or create variables. Generally, the bias
1792 does not matter as long as results from timeit.py are not mixed with
1791 does not matter as long as results from timeit.py are not mixed with
1793 those from %timeit."""
1792 those from %timeit."""
1794
1793
1795 import timeit
1794 import timeit
1796 import math
1795 import math
1797
1796
1798 units = [u"s", u"ms", u"\xb5s", u"ns"]
1797 units = [u"s", u"ms", u"\xb5s", u"ns"]
1799 scaling = [1, 1e3, 1e6, 1e9]
1798 scaling = [1, 1e3, 1e6, 1e9]
1800
1799
1801 opts, stmt = self.parse_options(parameter_s,'n:r:tcp:',
1800 opts, stmt = self.parse_options(parameter_s,'n:r:tcp:',
1802 posix=False)
1801 posix=False)
1803 if stmt == "":
1802 if stmt == "":
1804 return
1803 return
1805 timefunc = timeit.default_timer
1804 timefunc = timeit.default_timer
1806 number = int(getattr(opts, "n", 0))
1805 number = int(getattr(opts, "n", 0))
1807 repeat = int(getattr(opts, "r", timeit.default_repeat))
1806 repeat = int(getattr(opts, "r", timeit.default_repeat))
1808 precision = int(getattr(opts, "p", 3))
1807 precision = int(getattr(opts, "p", 3))
1809 if hasattr(opts, "t"):
1808 if hasattr(opts, "t"):
1810 timefunc = time.time
1809 timefunc = time.time
1811 if hasattr(opts, "c"):
1810 if hasattr(opts, "c"):
1812 timefunc = clock
1811 timefunc = clock
1813
1812
1814 timer = timeit.Timer(timer=timefunc)
1813 timer = timeit.Timer(timer=timefunc)
1815 # this code has tight coupling to the inner workings of timeit.Timer,
1814 # this code has tight coupling to the inner workings of timeit.Timer,
1816 # but is there a better way to achieve that the code stmt has access
1815 # but is there a better way to achieve that the code stmt has access
1817 # to the shell namespace?
1816 # to the shell namespace?
1818
1817
1819 src = timeit.template % {'stmt': timeit.reindent(stmt, 8),
1818 src = timeit.template % {'stmt': timeit.reindent(stmt, 8),
1820 'setup': "pass"}
1819 'setup': "pass"}
1821 # Track compilation time so it can be reported if too long
1820 # Track compilation time so it can be reported if too long
1822 # Minimum time above which compilation time will be reported
1821 # Minimum time above which compilation time will be reported
1823 tc_min = 0.1
1822 tc_min = 0.1
1824
1823
1825 t0 = clock()
1824 t0 = clock()
1826 code = compile(src, "<magic-timeit>", "exec")
1825 code = compile(src, "<magic-timeit>", "exec")
1827 tc = clock()-t0
1826 tc = clock()-t0
1828
1827
1829 ns = {}
1828 ns = {}
1830 exec code in self.shell.user_ns, ns
1829 exec code in self.shell.user_ns, ns
1831 timer.inner = ns["inner"]
1830 timer.inner = ns["inner"]
1832
1831
1833 if number == 0:
1832 if number == 0:
1834 # determine number so that 0.2 <= total time < 2.0
1833 # determine number so that 0.2 <= total time < 2.0
1835 number = 1
1834 number = 1
1836 for i in range(1, 10):
1835 for i in range(1, 10):
1837 number *= 10
1836 number *= 10
1838 if timer.timeit(number) >= 0.2:
1837 if timer.timeit(number) >= 0.2:
1839 break
1838 break
1840
1839
1841 best = min(timer.repeat(repeat, number)) / number
1840 best = min(timer.repeat(repeat, number)) / number
1842
1841
1843 if best > 0.0:
1842 if best > 0.0:
1844 order = min(-int(math.floor(math.log10(best)) // 3), 3)
1843 order = min(-int(math.floor(math.log10(best)) // 3), 3)
1845 else:
1844 else:
1846 order = 3
1845 order = 3
1847 print u"%d loops, best of %d: %.*g %s per loop" % (number, repeat,
1846 print u"%d loops, best of %d: %.*g %s per loop" % (number, repeat,
1848 precision,
1847 precision,
1849 best * scaling[order],
1848 best * scaling[order],
1850 units[order])
1849 units[order])
1851 if tc > tc_min:
1850 if tc > tc_min:
1852 print "Compiler time: %.2f s" % tc
1851 print "Compiler time: %.2f s" % tc
1853
1852
1854 @testdec.skip_doctest
1853 @testdec.skip_doctest
1855 def magic_time(self,parameter_s = ''):
1854 def magic_time(self,parameter_s = ''):
1856 """Time execution of a Python statement or expression.
1855 """Time execution of a Python statement or expression.
1857
1856
1858 The CPU and wall clock times are printed, and the value of the
1857 The CPU and wall clock times are printed, and the value of the
1859 expression (if any) is returned. Note that under Win32, system time
1858 expression (if any) is returned. Note that under Win32, system time
1860 is always reported as 0, since it can not be measured.
1859 is always reported as 0, since it can not be measured.
1861
1860
1862 This function provides very basic timing functionality. In Python
1861 This function provides very basic timing functionality. In Python
1863 2.3, the timeit module offers more control and sophistication, so this
1862 2.3, the timeit module offers more control and sophistication, so this
1864 could be rewritten to use it (patches welcome).
1863 could be rewritten to use it (patches welcome).
1865
1864
1866 Some examples:
1865 Some examples:
1867
1866
1868 In [1]: time 2**128
1867 In [1]: time 2**128
1869 CPU times: user 0.00 s, sys: 0.00 s, total: 0.00 s
1868 CPU times: user 0.00 s, sys: 0.00 s, total: 0.00 s
1870 Wall time: 0.00
1869 Wall time: 0.00
1871 Out[1]: 340282366920938463463374607431768211456L
1870 Out[1]: 340282366920938463463374607431768211456L
1872
1871
1873 In [2]: n = 1000000
1872 In [2]: n = 1000000
1874
1873
1875 In [3]: time sum(range(n))
1874 In [3]: time sum(range(n))
1876 CPU times: user 1.20 s, sys: 0.05 s, total: 1.25 s
1875 CPU times: user 1.20 s, sys: 0.05 s, total: 1.25 s
1877 Wall time: 1.37
1876 Wall time: 1.37
1878 Out[3]: 499999500000L
1877 Out[3]: 499999500000L
1879
1878
1880 In [4]: time print 'hello world'
1879 In [4]: time print 'hello world'
1881 hello world
1880 hello world
1882 CPU times: user 0.00 s, sys: 0.00 s, total: 0.00 s
1881 CPU times: user 0.00 s, sys: 0.00 s, total: 0.00 s
1883 Wall time: 0.00
1882 Wall time: 0.00
1884
1883
1885 Note that the time needed by Python to compile the given expression
1884 Note that the time needed by Python to compile the given expression
1886 will be reported if it is more than 0.1s. In this example, the
1885 will be reported if it is more than 0.1s. In this example, the
1887 actual exponentiation is done by Python at compilation time, so while
1886 actual exponentiation is done by Python at compilation time, so while
1888 the expression can take a noticeable amount of time to compute, that
1887 the expression can take a noticeable amount of time to compute, that
1889 time is purely due to the compilation:
1888 time is purely due to the compilation:
1890
1889
1891 In [5]: time 3**9999;
1890 In [5]: time 3**9999;
1892 CPU times: user 0.00 s, sys: 0.00 s, total: 0.00 s
1891 CPU times: user 0.00 s, sys: 0.00 s, total: 0.00 s
1893 Wall time: 0.00 s
1892 Wall time: 0.00 s
1894
1893
1895 In [6]: time 3**999999;
1894 In [6]: time 3**999999;
1896 CPU times: user 0.00 s, sys: 0.00 s, total: 0.00 s
1895 CPU times: user 0.00 s, sys: 0.00 s, total: 0.00 s
1897 Wall time: 0.00 s
1896 Wall time: 0.00 s
1898 Compiler : 0.78 s
1897 Compiler : 0.78 s
1899 """
1898 """
1900
1899
1901 # fail immediately if the given expression can't be compiled
1900 # fail immediately if the given expression can't be compiled
1902
1901
1903 expr = self.shell.prefilter(parameter_s,False)
1902 expr = self.shell.prefilter(parameter_s,False)
1904
1903
1905 # Minimum time above which compilation time will be reported
1904 # Minimum time above which compilation time will be reported
1906 tc_min = 0.1
1905 tc_min = 0.1
1907
1906
1908 try:
1907 try:
1909 mode = 'eval'
1908 mode = 'eval'
1910 t0 = clock()
1909 t0 = clock()
1911 code = compile(expr,'<timed eval>',mode)
1910 code = compile(expr,'<timed eval>',mode)
1912 tc = clock()-t0
1911 tc = clock()-t0
1913 except SyntaxError:
1912 except SyntaxError:
1914 mode = 'exec'
1913 mode = 'exec'
1915 t0 = clock()
1914 t0 = clock()
1916 code = compile(expr,'<timed exec>',mode)
1915 code = compile(expr,'<timed exec>',mode)
1917 tc = clock()-t0
1916 tc = clock()-t0
1918 # skew measurement as little as possible
1917 # skew measurement as little as possible
1919 glob = self.shell.user_ns
1918 glob = self.shell.user_ns
1920 clk = clock2
1919 clk = clock2
1921 wtime = time.time
1920 wtime = time.time
1922 # time execution
1921 # time execution
1923 wall_st = wtime()
1922 wall_st = wtime()
1924 if mode=='eval':
1923 if mode=='eval':
1925 st = clk()
1924 st = clk()
1926 out = eval(code,glob)
1925 out = eval(code,glob)
1927 end = clk()
1926 end = clk()
1928 else:
1927 else:
1929 st = clk()
1928 st = clk()
1930 exec code in glob
1929 exec code in glob
1931 end = clk()
1930 end = clk()
1932 out = None
1931 out = None
1933 wall_end = wtime()
1932 wall_end = wtime()
1934 # Compute actual times and report
1933 # Compute actual times and report
1935 wall_time = wall_end-wall_st
1934 wall_time = wall_end-wall_st
1936 cpu_user = end[0]-st[0]
1935 cpu_user = end[0]-st[0]
1937 cpu_sys = end[1]-st[1]
1936 cpu_sys = end[1]-st[1]
1938 cpu_tot = cpu_user+cpu_sys
1937 cpu_tot = cpu_user+cpu_sys
1939 print "CPU times: user %.2f s, sys: %.2f s, total: %.2f s" % \
1938 print "CPU times: user %.2f s, sys: %.2f s, total: %.2f s" % \
1940 (cpu_user,cpu_sys,cpu_tot)
1939 (cpu_user,cpu_sys,cpu_tot)
1941 print "Wall time: %.2f s" % wall_time
1940 print "Wall time: %.2f s" % wall_time
1942 if tc > tc_min:
1941 if tc > tc_min:
1943 print "Compiler : %.2f s" % tc
1942 print "Compiler : %.2f s" % tc
1944 return out
1943 return out
1945
1944
1946 @testdec.skip_doctest
1945 @testdec.skip_doctest
1947 def magic_macro(self,parameter_s = ''):
1946 def magic_macro(self,parameter_s = ''):
1948 """Define a set of input lines as a macro for future re-execution.
1947 """Define a set of input lines as a macro for future re-execution.
1949
1948
1950 Usage:\\
1949 Usage:\\
1951 %macro [options] name n1-n2 n3-n4 ... n5 .. n6 ...
1950 %macro [options] name n1-n2 n3-n4 ... n5 .. n6 ...
1952
1951
1953 Options:
1952 Options:
1954
1953
1955 -r: use 'raw' input. By default, the 'processed' history is used,
1954 -r: use 'raw' input. By default, the 'processed' history is used,
1956 so that magics are loaded in their transformed version to valid
1955 so that magics are loaded in their transformed version to valid
1957 Python. If this option is given, the raw input as typed as the
1956 Python. If this option is given, the raw input as typed as the
1958 command line is used instead.
1957 command line is used instead.
1959
1958
1960 This will define a global variable called `name` which is a string
1959 This will define a global variable called `name` which is a string
1961 made of joining the slices and lines you specify (n1,n2,... numbers
1960 made of joining the slices and lines you specify (n1,n2,... numbers
1962 above) from your input history into a single string. This variable
1961 above) from your input history into a single string. This variable
1963 acts like an automatic function which re-executes those lines as if
1962 acts like an automatic function which re-executes those lines as if
1964 you had typed them. You just type 'name' at the prompt and the code
1963 you had typed them. You just type 'name' at the prompt and the code
1965 executes.
1964 executes.
1966
1965
1967 The notation for indicating number ranges is: n1-n2 means 'use line
1966 The notation for indicating number ranges is: n1-n2 means 'use line
1968 numbers n1,...n2' (the endpoint is included). That is, '5-7' means
1967 numbers n1,...n2' (the endpoint is included). That is, '5-7' means
1969 using the lines numbered 5,6 and 7.
1968 using the lines numbered 5,6 and 7.
1970
1969
1971 Note: as a 'hidden' feature, you can also use traditional python slice
1970 Note: as a 'hidden' feature, you can also use traditional python slice
1972 notation, where N:M means numbers N through M-1.
1971 notation, where N:M means numbers N through M-1.
1973
1972
1974 For example, if your history contains (%hist prints it):
1973 For example, if your history contains (%hist prints it):
1975
1974
1976 44: x=1
1975 44: x=1
1977 45: y=3
1976 45: y=3
1978 46: z=x+y
1977 46: z=x+y
1979 47: print x
1978 47: print x
1980 48: a=5
1979 48: a=5
1981 49: print 'x',x,'y',y
1980 49: print 'x',x,'y',y
1982
1981
1983 you can create a macro with lines 44 through 47 (included) and line 49
1982 you can create a macro with lines 44 through 47 (included) and line 49
1984 called my_macro with:
1983 called my_macro with:
1985
1984
1986 In [55]: %macro my_macro 44-47 49
1985 In [55]: %macro my_macro 44-47 49
1987
1986
1988 Now, typing `my_macro` (without quotes) will re-execute all this code
1987 Now, typing `my_macro` (without quotes) will re-execute all this code
1989 in one pass.
1988 in one pass.
1990
1989
1991 You don't need to give the line-numbers in order, and any given line
1990 You don't need to give the line-numbers in order, and any given line
1992 number can appear multiple times. You can assemble macros with any
1991 number can appear multiple times. You can assemble macros with any
1993 lines from your input history in any order.
1992 lines from your input history in any order.
1994
1993
1995 The macro is a simple object which holds its value in an attribute,
1994 The macro is a simple object which holds its value in an attribute,
1996 but IPython's display system checks for macros and executes them as
1995 but IPython's display system checks for macros and executes them as
1997 code instead of printing them when you type their name.
1996 code instead of printing them when you type their name.
1998
1997
1999 You can view a macro's contents by explicitly printing it with:
1998 You can view a macro's contents by explicitly printing it with:
2000
1999
2001 'print macro_name'.
2000 'print macro_name'.
2002
2001
2003 For one-off cases which DON'T contain magic function calls in them you
2002 For one-off cases which DON'T contain magic function calls in them you
2004 can obtain similar results by explicitly executing slices from your
2003 can obtain similar results by explicitly executing slices from your
2005 input history with:
2004 input history with:
2006
2005
2007 In [60]: exec In[44:48]+In[49]"""
2006 In [60]: exec In[44:48]+In[49]"""
2008
2007
2009 opts,args = self.parse_options(parameter_s,'r',mode='list')
2008 opts,args = self.parse_options(parameter_s,'r',mode='list')
2010 if not args:
2009 if not args:
2011 macs = [k for k,v in self.shell.user_ns.items() if isinstance(v, Macro)]
2010 macs = [k for k,v in self.shell.user_ns.items() if isinstance(v, Macro)]
2012 macs.sort()
2011 macs.sort()
2013 return macs
2012 return macs
2014 if len(args) == 1:
2013 if len(args) == 1:
2015 raise UsageError(
2014 raise UsageError(
2016 "%macro insufficient args; usage '%macro name n1-n2 n3-4...")
2015 "%macro insufficient args; usage '%macro name n1-n2 n3-4...")
2017 name,ranges = args[0], args[1:]
2016 name,ranges = args[0], args[1:]
2018
2017
2019 #print 'rng',ranges # dbg
2018 #print 'rng',ranges # dbg
2020 lines = self.extract_input_slices(ranges,opts.has_key('r'))
2019 lines = self.extract_input_slices(ranges,opts.has_key('r'))
2021 macro = Macro(lines)
2020 macro = Macro(lines)
2022 self.shell.user_ns.update({name:macro})
2021 self.shell.user_ns.update({name:macro})
2023 print 'Macro `%s` created. To execute, type its name (without quotes).' % name
2022 print 'Macro `%s` created. To execute, type its name (without quotes).' % name
2024 print 'Macro contents:'
2023 print 'Macro contents:'
2025 print macro,
2024 print macro,
2026
2025
2027 def magic_save(self,parameter_s = ''):
2026 def magic_save(self,parameter_s = ''):
2028 """Save a set of lines to a given filename.
2027 """Save a set of lines to a given filename.
2029
2028
2030 Usage:\\
2029 Usage:\\
2031 %save [options] filename n1-n2 n3-n4 ... n5 .. n6 ...
2030 %save [options] filename n1-n2 n3-n4 ... n5 .. n6 ...
2032
2031
2033 Options:
2032 Options:
2034
2033
2035 -r: use 'raw' input. By default, the 'processed' history is used,
2034 -r: use 'raw' input. By default, the 'processed' history is used,
2036 so that magics are loaded in their transformed version to valid
2035 so that magics are loaded in their transformed version to valid
2037 Python. If this option is given, the raw input as typed as the
2036 Python. If this option is given, the raw input as typed as the
2038 command line is used instead.
2037 command line is used instead.
2039
2038
2040 This function uses the same syntax as %macro for line extraction, but
2039 This function uses the same syntax as %macro for line extraction, but
2041 instead of creating a macro it saves the resulting string to the
2040 instead of creating a macro it saves the resulting string to the
2042 filename you specify.
2041 filename you specify.
2043
2042
2044 It adds a '.py' extension to the file if you don't do so yourself, and
2043 It adds a '.py' extension to the file if you don't do so yourself, and
2045 it asks for confirmation before overwriting existing files."""
2044 it asks for confirmation before overwriting existing files."""
2046
2045
2047 opts,args = self.parse_options(parameter_s,'r',mode='list')
2046 opts,args = self.parse_options(parameter_s,'r',mode='list')
2048 fname,ranges = args[0], args[1:]
2047 fname,ranges = args[0], args[1:]
2049 if not fname.endswith('.py'):
2048 if not fname.endswith('.py'):
2050 fname += '.py'
2049 fname += '.py'
2051 if os.path.isfile(fname):
2050 if os.path.isfile(fname):
2052 ans = raw_input('File `%s` exists. Overwrite (y/[N])? ' % fname)
2051 ans = raw_input('File `%s` exists. Overwrite (y/[N])? ' % fname)
2053 if ans.lower() not in ['y','yes']:
2052 if ans.lower() not in ['y','yes']:
2054 print 'Operation cancelled.'
2053 print 'Operation cancelled.'
2055 return
2054 return
2056 cmds = ''.join(self.extract_input_slices(ranges,opts.has_key('r')))
2055 cmds = ''.join(self.extract_input_slices(ranges,opts.has_key('r')))
2057 f = file(fname,'w')
2056 f = file(fname,'w')
2058 f.write(cmds)
2057 f.write(cmds)
2059 f.close()
2058 f.close()
2060 print 'The following commands were written to file `%s`:' % fname
2059 print 'The following commands were written to file `%s`:' % fname
2061 print cmds
2060 print cmds
2062
2061
2063 def _edit_macro(self,mname,macro):
2062 def _edit_macro(self,mname,macro):
2064 """open an editor with the macro data in a file"""
2063 """open an editor with the macro data in a file"""
2065 filename = self.shell.mktempfile(macro.value)
2064 filename = self.shell.mktempfile(macro.value)
2066 self.shell.hooks.editor(filename)
2065 self.shell.hooks.editor(filename)
2067
2066
2068 # and make a new macro object, to replace the old one
2067 # and make a new macro object, to replace the old one
2069 mfile = open(filename)
2068 mfile = open(filename)
2070 mvalue = mfile.read()
2069 mvalue = mfile.read()
2071 mfile.close()
2070 mfile.close()
2072 self.shell.user_ns[mname] = Macro(mvalue)
2071 self.shell.user_ns[mname] = Macro(mvalue)
2073
2072
2074 def magic_ed(self,parameter_s=''):
2073 def magic_ed(self,parameter_s=''):
2075 """Alias to %edit."""
2074 """Alias to %edit."""
2076 return self.magic_edit(parameter_s)
2075 return self.magic_edit(parameter_s)
2077
2076
2078 @testdec.skip_doctest
2077 @testdec.skip_doctest
2079 def magic_edit(self,parameter_s='',last_call=['','']):
2078 def magic_edit(self,parameter_s='',last_call=['','']):
2080 """Bring up an editor and execute the resulting code.
2079 """Bring up an editor and execute the resulting code.
2081
2080
2082 Usage:
2081 Usage:
2083 %edit [options] [args]
2082 %edit [options] [args]
2084
2083
2085 %edit runs IPython's editor hook. The default version of this hook is
2084 %edit runs IPython's editor hook. The default version of this hook is
2086 set to call the __IPYTHON__.rc.editor command. This is read from your
2085 set to call the __IPYTHON__.rc.editor command. This is read from your
2087 environment variable $EDITOR. If this isn't found, it will default to
2086 environment variable $EDITOR. If this isn't found, it will default to
2088 vi under Linux/Unix and to notepad under Windows. See the end of this
2087 vi under Linux/Unix and to notepad under Windows. See the end of this
2089 docstring for how to change the editor hook.
2088 docstring for how to change the editor hook.
2090
2089
2091 You can also set the value of this editor via the command line option
2090 You can also set the value of this editor via the command line option
2092 '-editor' or in your ipythonrc file. This is useful if you wish to use
2091 '-editor' or in your ipythonrc file. This is useful if you wish to use
2093 specifically for IPython an editor different from your typical default
2092 specifically for IPython an editor different from your typical default
2094 (and for Windows users who typically don't set environment variables).
2093 (and for Windows users who typically don't set environment variables).
2095
2094
2096 This command allows you to conveniently edit multi-line code right in
2095 This command allows you to conveniently edit multi-line code right in
2097 your IPython session.
2096 your IPython session.
2098
2097
2099 If called without arguments, %edit opens up an empty editor with a
2098 If called without arguments, %edit opens up an empty editor with a
2100 temporary file and will execute the contents of this file when you
2099 temporary file and will execute the contents of this file when you
2101 close it (don't forget to save it!).
2100 close it (don't forget to save it!).
2102
2101
2103
2102
2104 Options:
2103 Options:
2105
2104
2106 -n <number>: open the editor at a specified line number. By default,
2105 -n <number>: open the editor at a specified line number. By default,
2107 the IPython editor hook uses the unix syntax 'editor +N filename', but
2106 the IPython editor hook uses the unix syntax 'editor +N filename', but
2108 you can configure this by providing your own modified hook if your
2107 you can configure this by providing your own modified hook if your
2109 favorite editor supports line-number specifications with a different
2108 favorite editor supports line-number specifications with a different
2110 syntax.
2109 syntax.
2111
2110
2112 -p: this will call the editor with the same data as the previous time
2111 -p: this will call the editor with the same data as the previous time
2113 it was used, regardless of how long ago (in your current session) it
2112 it was used, regardless of how long ago (in your current session) it
2114 was.
2113 was.
2115
2114
2116 -r: use 'raw' input. This option only applies to input taken from the
2115 -r: use 'raw' input. This option only applies to input taken from the
2117 user's history. By default, the 'processed' history is used, so that
2116 user's history. By default, the 'processed' history is used, so that
2118 magics are loaded in their transformed version to valid Python. If
2117 magics are loaded in their transformed version to valid Python. If
2119 this option is given, the raw input as typed as the command line is
2118 this option is given, the raw input as typed as the command line is
2120 used instead. When you exit the editor, it will be executed by
2119 used instead. When you exit the editor, it will be executed by
2121 IPython's own processor.
2120 IPython's own processor.
2122
2121
2123 -x: do not execute the edited code immediately upon exit. This is
2122 -x: do not execute the edited code immediately upon exit. This is
2124 mainly useful if you are editing programs which need to be called with
2123 mainly useful if you are editing programs which need to be called with
2125 command line arguments, which you can then do using %run.
2124 command line arguments, which you can then do using %run.
2126
2125
2127
2126
2128 Arguments:
2127 Arguments:
2129
2128
2130 If arguments are given, the following possibilites exist:
2129 If arguments are given, the following possibilites exist:
2131
2130
2132 - The arguments are numbers or pairs of colon-separated numbers (like
2131 - The arguments are numbers or pairs of colon-separated numbers (like
2133 1 4:8 9). These are interpreted as lines of previous input to be
2132 1 4:8 9). These are interpreted as lines of previous input to be
2134 loaded into the editor. The syntax is the same of the %macro command.
2133 loaded into the editor. The syntax is the same of the %macro command.
2135
2134
2136 - If the argument doesn't start with a number, it is evaluated as a
2135 - If the argument doesn't start with a number, it is evaluated as a
2137 variable and its contents loaded into the editor. You can thus edit
2136 variable and its contents loaded into the editor. You can thus edit
2138 any string which contains python code (including the result of
2137 any string which contains python code (including the result of
2139 previous edits).
2138 previous edits).
2140
2139
2141 - If the argument is the name of an object (other than a string),
2140 - If the argument is the name of an object (other than a string),
2142 IPython will try to locate the file where it was defined and open the
2141 IPython will try to locate the file where it was defined and open the
2143 editor at the point where it is defined. You can use `%edit function`
2142 editor at the point where it is defined. You can use `%edit function`
2144 to load an editor exactly at the point where 'function' is defined,
2143 to load an editor exactly at the point where 'function' is defined,
2145 edit it and have the file be executed automatically.
2144 edit it and have the file be executed automatically.
2146
2145
2147 If the object is a macro (see %macro for details), this opens up your
2146 If the object is a macro (see %macro for details), this opens up your
2148 specified editor with a temporary file containing the macro's data.
2147 specified editor with a temporary file containing the macro's data.
2149 Upon exit, the macro is reloaded with the contents of the file.
2148 Upon exit, the macro is reloaded with the contents of the file.
2150
2149
2151 Note: opening at an exact line is only supported under Unix, and some
2150 Note: opening at an exact line is only supported under Unix, and some
2152 editors (like kedit and gedit up to Gnome 2.8) do not understand the
2151 editors (like kedit and gedit up to Gnome 2.8) do not understand the
2153 '+NUMBER' parameter necessary for this feature. Good editors like
2152 '+NUMBER' parameter necessary for this feature. Good editors like
2154 (X)Emacs, vi, jed, pico and joe all do.
2153 (X)Emacs, vi, jed, pico and joe all do.
2155
2154
2156 - If the argument is not found as a variable, IPython will look for a
2155 - If the argument is not found as a variable, IPython will look for a
2157 file with that name (adding .py if necessary) and load it into the
2156 file with that name (adding .py if necessary) and load it into the
2158 editor. It will execute its contents with execfile() when you exit,
2157 editor. It will execute its contents with execfile() when you exit,
2159 loading any code in the file into your interactive namespace.
2158 loading any code in the file into your interactive namespace.
2160
2159
2161 After executing your code, %edit will return as output the code you
2160 After executing your code, %edit will return as output the code you
2162 typed in the editor (except when it was an existing file). This way
2161 typed in the editor (except when it was an existing file). This way
2163 you can reload the code in further invocations of %edit as a variable,
2162 you can reload the code in further invocations of %edit as a variable,
2164 via _<NUMBER> or Out[<NUMBER>], where <NUMBER> is the prompt number of
2163 via _<NUMBER> or Out[<NUMBER>], where <NUMBER> is the prompt number of
2165 the output.
2164 the output.
2166
2165
2167 Note that %edit is also available through the alias %ed.
2166 Note that %edit is also available through the alias %ed.
2168
2167
2169 This is an example of creating a simple function inside the editor and
2168 This is an example of creating a simple function inside the editor and
2170 then modifying it. First, start up the editor:
2169 then modifying it. First, start up the editor:
2171
2170
2172 In [1]: ed
2171 In [1]: ed
2173 Editing... done. Executing edited code...
2172 Editing... done. Executing edited code...
2174 Out[1]: 'def foo():n print "foo() was defined in an editing session"n'
2173 Out[1]: 'def foo():n print "foo() was defined in an editing session"n'
2175
2174
2176 We can then call the function foo():
2175 We can then call the function foo():
2177
2176
2178 In [2]: foo()
2177 In [2]: foo()
2179 foo() was defined in an editing session
2178 foo() was defined in an editing session
2180
2179
2181 Now we edit foo. IPython automatically loads the editor with the
2180 Now we edit foo. IPython automatically loads the editor with the
2182 (temporary) file where foo() was previously defined:
2181 (temporary) file where foo() was previously defined:
2183
2182
2184 In [3]: ed foo
2183 In [3]: ed foo
2185 Editing... done. Executing edited code...
2184 Editing... done. Executing edited code...
2186
2185
2187 And if we call foo() again we get the modified version:
2186 And if we call foo() again we get the modified version:
2188
2187
2189 In [4]: foo()
2188 In [4]: foo()
2190 foo() has now been changed!
2189 foo() has now been changed!
2191
2190
2192 Here is an example of how to edit a code snippet successive
2191 Here is an example of how to edit a code snippet successive
2193 times. First we call the editor:
2192 times. First we call the editor:
2194
2193
2195 In [5]: ed
2194 In [5]: ed
2196 Editing... done. Executing edited code...
2195 Editing... done. Executing edited code...
2197 hello
2196 hello
2198 Out[5]: "print 'hello'n"
2197 Out[5]: "print 'hello'n"
2199
2198
2200 Now we call it again with the previous output (stored in _):
2199 Now we call it again with the previous output (stored in _):
2201
2200
2202 In [6]: ed _
2201 In [6]: ed _
2203 Editing... done. Executing edited code...
2202 Editing... done. Executing edited code...
2204 hello world
2203 hello world
2205 Out[6]: "print 'hello world'n"
2204 Out[6]: "print 'hello world'n"
2206
2205
2207 Now we call it with the output #8 (stored in _8, also as Out[8]):
2206 Now we call it with the output #8 (stored in _8, also as Out[8]):
2208
2207
2209 In [7]: ed _8
2208 In [7]: ed _8
2210 Editing... done. Executing edited code...
2209 Editing... done. Executing edited code...
2211 hello again
2210 hello again
2212 Out[7]: "print 'hello again'n"
2211 Out[7]: "print 'hello again'n"
2213
2212
2214
2213
2215 Changing the default editor hook:
2214 Changing the default editor hook:
2216
2215
2217 If you wish to write your own editor hook, you can put it in a
2216 If you wish to write your own editor hook, you can put it in a
2218 configuration file which you load at startup time. The default hook
2217 configuration file which you load at startup time. The default hook
2219 is defined in the IPython.hooks module, and you can use that as a
2218 is defined in the IPython.hooks module, and you can use that as a
2220 starting example for further modifications. That file also has
2219 starting example for further modifications. That file also has
2221 general instructions on how to set a new hook for use once you've
2220 general instructions on how to set a new hook for use once you've
2222 defined it."""
2221 defined it."""
2223
2222
2224 # FIXME: This function has become a convoluted mess. It needs a
2223 # FIXME: This function has become a convoluted mess. It needs a
2225 # ground-up rewrite with clean, simple logic.
2224 # ground-up rewrite with clean, simple logic.
2226
2225
2227 def make_filename(arg):
2226 def make_filename(arg):
2228 "Make a filename from the given args"
2227 "Make a filename from the given args"
2229 try:
2228 try:
2230 filename = get_py_filename(arg)
2229 filename = get_py_filename(arg)
2231 except IOError:
2230 except IOError:
2232 if args.endswith('.py'):
2231 if args.endswith('.py'):
2233 filename = arg
2232 filename = arg
2234 else:
2233 else:
2235 filename = None
2234 filename = None
2236 return filename
2235 return filename
2237
2236
2238 # custom exceptions
2237 # custom exceptions
2239 class DataIsObject(Exception): pass
2238 class DataIsObject(Exception): pass
2240
2239
2241 opts,args = self.parse_options(parameter_s,'prxn:')
2240 opts,args = self.parse_options(parameter_s,'prxn:')
2242 # Set a few locals from the options for convenience:
2241 # Set a few locals from the options for convenience:
2243 opts_p = opts.has_key('p')
2242 opts_p = opts.has_key('p')
2244 opts_r = opts.has_key('r')
2243 opts_r = opts.has_key('r')
2245
2244
2246 # Default line number value
2245 # Default line number value
2247 lineno = opts.get('n',None)
2246 lineno = opts.get('n',None)
2248
2247
2249 if opts_p:
2248 if opts_p:
2250 args = '_%s' % last_call[0]
2249 args = '_%s' % last_call[0]
2251 if not self.shell.user_ns.has_key(args):
2250 if not self.shell.user_ns.has_key(args):
2252 args = last_call[1]
2251 args = last_call[1]
2253
2252
2254 # use last_call to remember the state of the previous call, but don't
2253 # use last_call to remember the state of the previous call, but don't
2255 # let it be clobbered by successive '-p' calls.
2254 # let it be clobbered by successive '-p' calls.
2256 try:
2255 try:
2257 last_call[0] = self.shell.outputcache.prompt_count
2256 last_call[0] = self.shell.outputcache.prompt_count
2258 if not opts_p:
2257 if not opts_p:
2259 last_call[1] = parameter_s
2258 last_call[1] = parameter_s
2260 except:
2259 except:
2261 pass
2260 pass
2262
2261
2263 # by default this is done with temp files, except when the given
2262 # by default this is done with temp files, except when the given
2264 # arg is a filename
2263 # arg is a filename
2265 use_temp = 1
2264 use_temp = 1
2266
2265
2267 if re.match(r'\d',args):
2266 if re.match(r'\d',args):
2268 # Mode where user specifies ranges of lines, like in %macro.
2267 # Mode where user specifies ranges of lines, like in %macro.
2269 # This means that you can't edit files whose names begin with
2268 # This means that you can't edit files whose names begin with
2270 # numbers this way. Tough.
2269 # numbers this way. Tough.
2271 ranges = args.split()
2270 ranges = args.split()
2272 data = ''.join(self.extract_input_slices(ranges,opts_r))
2271 data = ''.join(self.extract_input_slices(ranges,opts_r))
2273 elif args.endswith('.py'):
2272 elif args.endswith('.py'):
2274 filename = make_filename(args)
2273 filename = make_filename(args)
2275 data = ''
2274 data = ''
2276 use_temp = 0
2275 use_temp = 0
2277 elif args:
2276 elif args:
2278 try:
2277 try:
2279 # Load the parameter given as a variable. If not a string,
2278 # Load the parameter given as a variable. If not a string,
2280 # process it as an object instead (below)
2279 # process it as an object instead (below)
2281
2280
2282 #print '*** args',args,'type',type(args) # dbg
2281 #print '*** args',args,'type',type(args) # dbg
2283 data = eval(args,self.shell.user_ns)
2282 data = eval(args,self.shell.user_ns)
2284 if not type(data) in StringTypes:
2283 if not type(data) in StringTypes:
2285 raise DataIsObject
2284 raise DataIsObject
2286
2285
2287 except (NameError,SyntaxError):
2286 except (NameError,SyntaxError):
2288 # given argument is not a variable, try as a filename
2287 # given argument is not a variable, try as a filename
2289 filename = make_filename(args)
2288 filename = make_filename(args)
2290 if filename is None:
2289 if filename is None:
2291 warn("Argument given (%s) can't be found as a variable "
2290 warn("Argument given (%s) can't be found as a variable "
2292 "or as a filename." % args)
2291 "or as a filename." % args)
2293 return
2292 return
2294
2293
2295 data = ''
2294 data = ''
2296 use_temp = 0
2295 use_temp = 0
2297 except DataIsObject:
2296 except DataIsObject:
2298
2297
2299 # macros have a special edit function
2298 # macros have a special edit function
2300 if isinstance(data,Macro):
2299 if isinstance(data,Macro):
2301 self._edit_macro(args,data)
2300 self._edit_macro(args,data)
2302 return
2301 return
2303
2302
2304 # For objects, try to edit the file where they are defined
2303 # For objects, try to edit the file where they are defined
2305 try:
2304 try:
2306 filename = inspect.getabsfile(data)
2305 filename = inspect.getabsfile(data)
2307 if 'fakemodule' in filename.lower() and inspect.isclass(data):
2306 if 'fakemodule' in filename.lower() and inspect.isclass(data):
2308 # class created by %edit? Try to find source
2307 # class created by %edit? Try to find source
2309 # by looking for method definitions instead, the
2308 # by looking for method definitions instead, the
2310 # __module__ in those classes is FakeModule.
2309 # __module__ in those classes is FakeModule.
2311 attrs = [getattr(data, aname) for aname in dir(data)]
2310 attrs = [getattr(data, aname) for aname in dir(data)]
2312 for attr in attrs:
2311 for attr in attrs:
2313 if not inspect.ismethod(attr):
2312 if not inspect.ismethod(attr):
2314 continue
2313 continue
2315 filename = inspect.getabsfile(attr)
2314 filename = inspect.getabsfile(attr)
2316 if filename and 'fakemodule' not in filename.lower():
2315 if filename and 'fakemodule' not in filename.lower():
2317 # change the attribute to be the edit target instead
2316 # change the attribute to be the edit target instead
2318 data = attr
2317 data = attr
2319 break
2318 break
2320
2319
2321 datafile = 1
2320 datafile = 1
2322 except TypeError:
2321 except TypeError:
2323 filename = make_filename(args)
2322 filename = make_filename(args)
2324 datafile = 1
2323 datafile = 1
2325 warn('Could not find file where `%s` is defined.\n'
2324 warn('Could not find file where `%s` is defined.\n'
2326 'Opening a file named `%s`' % (args,filename))
2325 'Opening a file named `%s`' % (args,filename))
2327 # Now, make sure we can actually read the source (if it was in
2326 # Now, make sure we can actually read the source (if it was in
2328 # a temp file it's gone by now).
2327 # a temp file it's gone by now).
2329 if datafile:
2328 if datafile:
2330 try:
2329 try:
2331 if lineno is None:
2330 if lineno is None:
2332 lineno = inspect.getsourcelines(data)[1]
2331 lineno = inspect.getsourcelines(data)[1]
2333 except IOError:
2332 except IOError:
2334 filename = make_filename(args)
2333 filename = make_filename(args)
2335 if filename is None:
2334 if filename is None:
2336 warn('The file `%s` where `%s` was defined cannot '
2335 warn('The file `%s` where `%s` was defined cannot '
2337 'be read.' % (filename,data))
2336 'be read.' % (filename,data))
2338 return
2337 return
2339 use_temp = 0
2338 use_temp = 0
2340 else:
2339 else:
2341 data = ''
2340 data = ''
2342
2341
2343 if use_temp:
2342 if use_temp:
2344 filename = self.shell.mktempfile(data)
2343 filename = self.shell.mktempfile(data)
2345 print 'IPython will make a temporary file named:',filename
2344 print 'IPython will make a temporary file named:',filename
2346
2345
2347 # do actual editing here
2346 # do actual editing here
2348 print 'Editing...',
2347 print 'Editing...',
2349 sys.stdout.flush()
2348 sys.stdout.flush()
2350 self.shell.hooks.editor(filename,lineno)
2349 self.shell.hooks.editor(filename,lineno)
2351
2350
2352 # XXX TODO: should this be generalized for all string vars?
2351 # XXX TODO: should this be generalized for all string vars?
2353 # For now, this is special-cased to blocks created by cpaste
2352 # For now, this is special-cased to blocks created by cpaste
2354 if args.strip() == 'pasted_block':
2353 if args.strip() == 'pasted_block':
2355 self.shell.user_ns['pasted_block'] = file_read(filename)
2354 self.shell.user_ns['pasted_block'] = file_read(filename)
2356
2355
2357 if opts.has_key('x'): # -x prevents actual execution
2356 if opts.has_key('x'): # -x prevents actual execution
2358 print
2357 print
2359 else:
2358 else:
2360 print 'done. Executing edited code...'
2359 print 'done. Executing edited code...'
2361 if opts_r:
2360 if opts_r:
2362 self.shell.runlines(file_read(filename))
2361 self.shell.runlines(file_read(filename))
2363 else:
2362 else:
2364 self.shell.safe_execfile(filename,self.shell.user_ns,
2363 self.shell.safe_execfile(filename,self.shell.user_ns,
2365 self.shell.user_ns)
2364 self.shell.user_ns)
2366
2365
2367
2366
2368 if use_temp:
2367 if use_temp:
2369 try:
2368 try:
2370 return open(filename).read()
2369 return open(filename).read()
2371 except IOError,msg:
2370 except IOError,msg:
2372 if msg.filename == filename:
2371 if msg.filename == filename:
2373 warn('File not found. Did you forget to save?')
2372 warn('File not found. Did you forget to save?')
2374 return
2373 return
2375 else:
2374 else:
2376 self.shell.showtraceback()
2375 self.shell.showtraceback()
2377
2376
2378 def magic_xmode(self,parameter_s = ''):
2377 def magic_xmode(self,parameter_s = ''):
2379 """Switch modes for the exception handlers.
2378 """Switch modes for the exception handlers.
2380
2379
2381 Valid modes: Plain, Context and Verbose.
2380 Valid modes: Plain, Context and Verbose.
2382
2381
2383 If called without arguments, acts as a toggle."""
2382 If called without arguments, acts as a toggle."""
2384
2383
2385 def xmode_switch_err(name):
2384 def xmode_switch_err(name):
2386 warn('Error changing %s exception modes.\n%s' %
2385 warn('Error changing %s exception modes.\n%s' %
2387 (name,sys.exc_info()[1]))
2386 (name,sys.exc_info()[1]))
2388
2387
2389 shell = self.shell
2388 shell = self.shell
2390 new_mode = parameter_s.strip().capitalize()
2389 new_mode = parameter_s.strip().capitalize()
2391 try:
2390 try:
2392 shell.InteractiveTB.set_mode(mode=new_mode)
2391 shell.InteractiveTB.set_mode(mode=new_mode)
2393 print 'Exception reporting mode:',shell.InteractiveTB.mode
2392 print 'Exception reporting mode:',shell.InteractiveTB.mode
2394 except:
2393 except:
2395 xmode_switch_err('user')
2394 xmode_switch_err('user')
2396
2395
2397 # threaded shells use a special handler in sys.excepthook
2396 # threaded shells use a special handler in sys.excepthook
2398 if shell.isthreaded:
2397 if shell.isthreaded:
2399 try:
2398 try:
2400 shell.sys_excepthook.set_mode(mode=new_mode)
2399 shell.sys_excepthook.set_mode(mode=new_mode)
2401 except:
2400 except:
2402 xmode_switch_err('threaded')
2401 xmode_switch_err('threaded')
2403
2402
2404 def magic_colors(self,parameter_s = ''):
2403 def magic_colors(self,parameter_s = ''):
2405 """Switch color scheme for prompts, info system and exception handlers.
2404 """Switch color scheme for prompts, info system and exception handlers.
2406
2405
2407 Currently implemented schemes: NoColor, Linux, LightBG.
2406 Currently implemented schemes: NoColor, Linux, LightBG.
2408
2407
2409 Color scheme names are not case-sensitive."""
2408 Color scheme names are not case-sensitive."""
2410
2409
2411 def color_switch_err(name):
2410 def color_switch_err(name):
2412 warn('Error changing %s color schemes.\n%s' %
2411 warn('Error changing %s color schemes.\n%s' %
2413 (name,sys.exc_info()[1]))
2412 (name,sys.exc_info()[1]))
2414
2413
2415
2414
2416 new_scheme = parameter_s.strip()
2415 new_scheme = parameter_s.strip()
2417 if not new_scheme:
2416 if not new_scheme:
2418 raise UsageError(
2417 raise UsageError(
2419 "%colors: you must specify a color scheme. See '%colors?'")
2418 "%colors: you must specify a color scheme. See '%colors?'")
2420 return
2419 return
2421 # local shortcut
2420 # local shortcut
2422 shell = self.shell
2421 shell = self.shell
2423
2422
2424 import IPython.rlineimpl as readline
2423 import IPython.rlineimpl as readline
2425
2424
2426 if not readline.have_readline and sys.platform == "win32":
2425 if not readline.have_readline and sys.platform == "win32":
2427 msg = """\
2426 msg = """\
2428 Proper color support under MS Windows requires the pyreadline library.
2427 Proper color support under MS Windows requires the pyreadline library.
2429 You can find it at:
2428 You can find it at:
2430 http://ipython.scipy.org/moin/PyReadline/Intro
2429 http://ipython.scipy.org/moin/PyReadline/Intro
2431 Gary's readline needs the ctypes module, from:
2430 Gary's readline needs the ctypes module, from:
2432 http://starship.python.net/crew/theller/ctypes
2431 http://starship.python.net/crew/theller/ctypes
2433 (Note that ctypes is already part of Python versions 2.5 and newer).
2432 (Note that ctypes is already part of Python versions 2.5 and newer).
2434
2433
2435 Defaulting color scheme to 'NoColor'"""
2434 Defaulting color scheme to 'NoColor'"""
2436 new_scheme = 'NoColor'
2435 new_scheme = 'NoColor'
2437 warn(msg)
2436 warn(msg)
2438
2437
2439 # readline option is 0
2438 # readline option is 0
2440 if not shell.has_readline:
2439 if not shell.has_readline:
2441 new_scheme = 'NoColor'
2440 new_scheme = 'NoColor'
2442
2441
2443 # Set prompt colors
2442 # Set prompt colors
2444 try:
2443 try:
2445 shell.outputcache.set_colors(new_scheme)
2444 shell.outputcache.set_colors(new_scheme)
2446 except:
2445 except:
2447 color_switch_err('prompt')
2446 color_switch_err('prompt')
2448 else:
2447 else:
2449 shell.rc.colors = \
2448 shell.rc.colors = \
2450 shell.outputcache.color_table.active_scheme_name
2449 shell.outputcache.color_table.active_scheme_name
2451 # Set exception colors
2450 # Set exception colors
2452 try:
2451 try:
2453 shell.InteractiveTB.set_colors(scheme = new_scheme)
2452 shell.InteractiveTB.set_colors(scheme = new_scheme)
2454 shell.SyntaxTB.set_colors(scheme = new_scheme)
2453 shell.SyntaxTB.set_colors(scheme = new_scheme)
2455 except:
2454 except:
2456 color_switch_err('exception')
2455 color_switch_err('exception')
2457
2456
2458 # threaded shells use a verbose traceback in sys.excepthook
2457 # threaded shells use a verbose traceback in sys.excepthook
2459 if shell.isthreaded:
2458 if shell.isthreaded:
2460 try:
2459 try:
2461 shell.sys_excepthook.set_colors(scheme=new_scheme)
2460 shell.sys_excepthook.set_colors(scheme=new_scheme)
2462 except:
2461 except:
2463 color_switch_err('system exception handler')
2462 color_switch_err('system exception handler')
2464
2463
2465 # Set info (for 'object?') colors
2464 # Set info (for 'object?') colors
2466 if shell.rc.color_info:
2465 if shell.rc.color_info:
2467 try:
2466 try:
2468 shell.inspector.set_active_scheme(new_scheme)
2467 shell.inspector.set_active_scheme(new_scheme)
2469 except:
2468 except:
2470 color_switch_err('object inspector')
2469 color_switch_err('object inspector')
2471 else:
2470 else:
2472 shell.inspector.set_active_scheme('NoColor')
2471 shell.inspector.set_active_scheme('NoColor')
2473
2472
2474 def magic_color_info(self,parameter_s = ''):
2473 def magic_color_info(self,parameter_s = ''):
2475 """Toggle color_info.
2474 """Toggle color_info.
2476
2475
2477 The color_info configuration parameter controls whether colors are
2476 The color_info configuration parameter controls whether colors are
2478 used for displaying object details (by things like %psource, %pfile or
2477 used for displaying object details (by things like %psource, %pfile or
2479 the '?' system). This function toggles this value with each call.
2478 the '?' system). This function toggles this value with each call.
2480
2479
2481 Note that unless you have a fairly recent pager (less works better
2480 Note that unless you have a fairly recent pager (less works better
2482 than more) in your system, using colored object information displays
2481 than more) in your system, using colored object information displays
2483 will not work properly. Test it and see."""
2482 will not work properly. Test it and see."""
2484
2483
2485 self.shell.rc.color_info = 1 - self.shell.rc.color_info
2484 self.shell.rc.color_info = 1 - self.shell.rc.color_info
2486 self.magic_colors(self.shell.rc.colors)
2485 self.magic_colors(self.shell.rc.colors)
2487 print 'Object introspection functions have now coloring:',
2486 print 'Object introspection functions have now coloring:',
2488 print ['OFF','ON'][self.shell.rc.color_info]
2487 print ['OFF','ON'][self.shell.rc.color_info]
2489
2488
2490 def magic_Pprint(self, parameter_s=''):
2489 def magic_Pprint(self, parameter_s=''):
2491 """Toggle pretty printing on/off."""
2490 """Toggle pretty printing on/off."""
2492
2491
2493 self.shell.rc.pprint = 1 - self.shell.rc.pprint
2492 self.shell.rc.pprint = 1 - self.shell.rc.pprint
2494 print 'Pretty printing has been turned', \
2493 print 'Pretty printing has been turned', \
2495 ['OFF','ON'][self.shell.rc.pprint]
2494 ['OFF','ON'][self.shell.rc.pprint]
2496
2495
2497 def magic_exit(self, parameter_s=''):
2496 def magic_exit(self, parameter_s=''):
2498 """Exit IPython, confirming if configured to do so.
2497 """Exit IPython, confirming if configured to do so.
2499
2498
2500 You can configure whether IPython asks for confirmation upon exit by
2499 You can configure whether IPython asks for confirmation upon exit by
2501 setting the confirm_exit flag in the ipythonrc file."""
2500 setting the confirm_exit flag in the ipythonrc file."""
2502
2501
2503 self.shell.exit()
2502 self.shell.exit()
2504
2503
2505 def magic_quit(self, parameter_s=''):
2504 def magic_quit(self, parameter_s=''):
2506 """Exit IPython, confirming if configured to do so (like %exit)"""
2505 """Exit IPython, confirming if configured to do so (like %exit)"""
2507
2506
2508 self.shell.exit()
2507 self.shell.exit()
2509
2508
2510 def magic_Exit(self, parameter_s=''):
2509 def magic_Exit(self, parameter_s=''):
2511 """Exit IPython without confirmation."""
2510 """Exit IPython without confirmation."""
2512
2511
2513 self.shell.ask_exit()
2512 self.shell.ask_exit()
2514
2513
2515 #......................................................................
2514 #......................................................................
2516 # Functions to implement unix shell-type things
2515 # Functions to implement unix shell-type things
2517
2516
2518 @testdec.skip_doctest
2517 @testdec.skip_doctest
2519 def magic_alias(self, parameter_s = ''):
2518 def magic_alias(self, parameter_s = ''):
2520 """Define an alias for a system command.
2519 """Define an alias for a system command.
2521
2520
2522 '%alias alias_name cmd' defines 'alias_name' as an alias for 'cmd'
2521 '%alias alias_name cmd' defines 'alias_name' as an alias for 'cmd'
2523
2522
2524 Then, typing 'alias_name params' will execute the system command 'cmd
2523 Then, typing 'alias_name params' will execute the system command 'cmd
2525 params' (from your underlying operating system).
2524 params' (from your underlying operating system).
2526
2525
2527 Aliases have lower precedence than magic functions and Python normal
2526 Aliases have lower precedence than magic functions and Python normal
2528 variables, so if 'foo' is both a Python variable and an alias, the
2527 variables, so if 'foo' is both a Python variable and an alias, the
2529 alias can not be executed until 'del foo' removes the Python variable.
2528 alias can not be executed until 'del foo' removes the Python variable.
2530
2529
2531 You can use the %l specifier in an alias definition to represent the
2530 You can use the %l specifier in an alias definition to represent the
2532 whole line when the alias is called. For example:
2531 whole line when the alias is called. For example:
2533
2532
2534 In [2]: alias all echo "Input in brackets: <%l>"
2533 In [2]: alias all echo "Input in brackets: <%l>"
2535 In [3]: all hello world
2534 In [3]: all hello world
2536 Input in brackets: <hello world>
2535 Input in brackets: <hello world>
2537
2536
2538 You can also define aliases with parameters using %s specifiers (one
2537 You can also define aliases with parameters using %s specifiers (one
2539 per parameter):
2538 per parameter):
2540
2539
2541 In [1]: alias parts echo first %s second %s
2540 In [1]: alias parts echo first %s second %s
2542 In [2]: %parts A B
2541 In [2]: %parts A B
2543 first A second B
2542 first A second B
2544 In [3]: %parts A
2543 In [3]: %parts A
2545 Incorrect number of arguments: 2 expected.
2544 Incorrect number of arguments: 2 expected.
2546 parts is an alias to: 'echo first %s second %s'
2545 parts is an alias to: 'echo first %s second %s'
2547
2546
2548 Note that %l and %s are mutually exclusive. You can only use one or
2547 Note that %l and %s are mutually exclusive. You can only use one or
2549 the other in your aliases.
2548 the other in your aliases.
2550
2549
2551 Aliases expand Python variables just like system calls using ! or !!
2550 Aliases expand Python variables just like system calls using ! or !!
2552 do: all expressions prefixed with '$' get expanded. For details of
2551 do: all expressions prefixed with '$' get expanded. For details of
2553 the semantic rules, see PEP-215:
2552 the semantic rules, see PEP-215:
2554 http://www.python.org/peps/pep-0215.html. This is the library used by
2553 http://www.python.org/peps/pep-0215.html. This is the library used by
2555 IPython for variable expansion. If you want to access a true shell
2554 IPython for variable expansion. If you want to access a true shell
2556 variable, an extra $ is necessary to prevent its expansion by IPython:
2555 variable, an extra $ is necessary to prevent its expansion by IPython:
2557
2556
2558 In [6]: alias show echo
2557 In [6]: alias show echo
2559 In [7]: PATH='A Python string'
2558 In [7]: PATH='A Python string'
2560 In [8]: show $PATH
2559 In [8]: show $PATH
2561 A Python string
2560 A Python string
2562 In [9]: show $$PATH
2561 In [9]: show $$PATH
2563 /usr/local/lf9560/bin:/usr/local/intel/compiler70/ia32/bin:...
2562 /usr/local/lf9560/bin:/usr/local/intel/compiler70/ia32/bin:...
2564
2563
2565 You can use the alias facility to acess all of $PATH. See the %rehash
2564 You can use the alias facility to acess all of $PATH. See the %rehash
2566 and %rehashx functions, which automatically create aliases for the
2565 and %rehashx functions, which automatically create aliases for the
2567 contents of your $PATH.
2566 contents of your $PATH.
2568
2567
2569 If called with no parameters, %alias prints the current alias table."""
2568 If called with no parameters, %alias prints the current alias table."""
2570
2569
2571 par = parameter_s.strip()
2570 par = parameter_s.strip()
2572 if not par:
2571 if not par:
2573 stored = self.db.get('stored_aliases', {} )
2572 stored = self.db.get('stored_aliases', {} )
2574 atab = self.shell.alias_table
2573 atab = self.shell.alias_table
2575 aliases = atab.keys()
2574 aliases = atab.keys()
2576 aliases.sort()
2575 aliases.sort()
2577 res = []
2576 res = []
2578 showlast = []
2577 showlast = []
2579 for alias in aliases:
2578 for alias in aliases:
2580 special = False
2579 special = False
2581 try:
2580 try:
2582 tgt = atab[alias][1]
2581 tgt = atab[alias][1]
2583 except (TypeError, AttributeError):
2582 except (TypeError, AttributeError):
2584 # unsubscriptable? probably a callable
2583 # unsubscriptable? probably a callable
2585 tgt = atab[alias]
2584 tgt = atab[alias]
2586 special = True
2585 special = True
2587 # 'interesting' aliases
2586 # 'interesting' aliases
2588 if (alias in stored or
2587 if (alias in stored or
2589 special or
2588 special or
2590 alias.lower() != os.path.splitext(tgt)[0].lower() or
2589 alias.lower() != os.path.splitext(tgt)[0].lower() or
2591 ' ' in tgt):
2590 ' ' in tgt):
2592 showlast.append((alias, tgt))
2591 showlast.append((alias, tgt))
2593 else:
2592 else:
2594 res.append((alias, tgt ))
2593 res.append((alias, tgt ))
2595
2594
2596 # show most interesting aliases last
2595 # show most interesting aliases last
2597 res.extend(showlast)
2596 res.extend(showlast)
2598 print "Total number of aliases:",len(aliases)
2597 print "Total number of aliases:",len(aliases)
2599 return res
2598 return res
2600 try:
2599 try:
2601 alias,cmd = par.split(None,1)
2600 alias,cmd = par.split(None,1)
2602 except:
2601 except:
2603 print OInspect.getdoc(self.magic_alias)
2602 print OInspect.getdoc(self.magic_alias)
2604 else:
2603 else:
2605 nargs = cmd.count('%s')
2604 nargs = cmd.count('%s')
2606 if nargs>0 and cmd.find('%l')>=0:
2605 if nargs>0 and cmd.find('%l')>=0:
2607 error('The %s and %l specifiers are mutually exclusive '
2606 error('The %s and %l specifiers are mutually exclusive '
2608 'in alias definitions.')
2607 'in alias definitions.')
2609 else: # all looks OK
2608 else: # all looks OK
2610 self.shell.alias_table[alias] = (nargs,cmd)
2609 self.shell.alias_table[alias] = (nargs,cmd)
2611 self.shell.alias_table_validate(verbose=0)
2610 self.shell.alias_table_validate(verbose=0)
2612 # end magic_alias
2611 # end magic_alias
2613
2612
2614 def magic_unalias(self, parameter_s = ''):
2613 def magic_unalias(self, parameter_s = ''):
2615 """Remove an alias"""
2614 """Remove an alias"""
2616
2615
2617 aname = parameter_s.strip()
2616 aname = parameter_s.strip()
2618 if aname in self.shell.alias_table:
2617 if aname in self.shell.alias_table:
2619 del self.shell.alias_table[aname]
2618 del self.shell.alias_table[aname]
2620 stored = self.db.get('stored_aliases', {} )
2619 stored = self.db.get('stored_aliases', {} )
2621 if aname in stored:
2620 if aname in stored:
2622 print "Removing %stored alias",aname
2621 print "Removing %stored alias",aname
2623 del stored[aname]
2622 del stored[aname]
2624 self.db['stored_aliases'] = stored
2623 self.db['stored_aliases'] = stored
2625
2624
2626
2625
2627 def magic_rehashx(self, parameter_s = ''):
2626 def magic_rehashx(self, parameter_s = ''):
2628 """Update the alias table with all executable files in $PATH.
2627 """Update the alias table with all executable files in $PATH.
2629
2628
2630 This version explicitly checks that every entry in $PATH is a file
2629 This version explicitly checks that every entry in $PATH is a file
2631 with execute access (os.X_OK), so it is much slower than %rehash.
2630 with execute access (os.X_OK), so it is much slower than %rehash.
2632
2631
2633 Under Windows, it checks executability as a match agains a
2632 Under Windows, it checks executability as a match agains a
2634 '|'-separated string of extensions, stored in the IPython config
2633 '|'-separated string of extensions, stored in the IPython config
2635 variable win_exec_ext. This defaults to 'exe|com|bat'.
2634 variable win_exec_ext. This defaults to 'exe|com|bat'.
2636
2635
2637 This function also resets the root module cache of module completer,
2636 This function also resets the root module cache of module completer,
2638 used on slow filesystems.
2637 used on slow filesystems.
2639 """
2638 """
2640
2639
2641
2640
2642 ip = self.api
2641 ip = self.api
2643
2642
2644 # for the benefit of module completer in ipy_completers.py
2643 # for the benefit of module completer in ipy_completers.py
2645 del ip.db['rootmodules']
2644 del ip.db['rootmodules']
2646
2645
2647 path = [os.path.abspath(os.path.expanduser(p)) for p in
2646 path = [os.path.abspath(os.path.expanduser(p)) for p in
2648 os.environ.get('PATH','').split(os.pathsep)]
2647 os.environ.get('PATH','').split(os.pathsep)]
2649 path = filter(os.path.isdir,path)
2648 path = filter(os.path.isdir,path)
2650
2649
2651 alias_table = self.shell.alias_table
2650 alias_table = self.shell.alias_table
2652 syscmdlist = []
2651 syscmdlist = []
2653 if os.name == 'posix':
2652 if os.name == 'posix':
2654 isexec = lambda fname:os.path.isfile(fname) and \
2653 isexec = lambda fname:os.path.isfile(fname) and \
2655 os.access(fname,os.X_OK)
2654 os.access(fname,os.X_OK)
2656 else:
2655 else:
2657
2656
2658 try:
2657 try:
2659 winext = os.environ['pathext'].replace(';','|').replace('.','')
2658 winext = os.environ['pathext'].replace(';','|').replace('.','')
2660 except KeyError:
2659 except KeyError:
2661 winext = 'exe|com|bat|py'
2660 winext = 'exe|com|bat|py'
2662 if 'py' not in winext:
2661 if 'py' not in winext:
2663 winext += '|py'
2662 winext += '|py'
2664 execre = re.compile(r'(.*)\.(%s)$' % winext,re.IGNORECASE)
2663 execre = re.compile(r'(.*)\.(%s)$' % winext,re.IGNORECASE)
2665 isexec = lambda fname:os.path.isfile(fname) and execre.match(fname)
2664 isexec = lambda fname:os.path.isfile(fname) and execre.match(fname)
2666 savedir = os.getcwd()
2665 savedir = os.getcwd()
2667 try:
2666 try:
2668 # write the whole loop for posix/Windows so we don't have an if in
2667 # write the whole loop for posix/Windows so we don't have an if in
2669 # the innermost part
2668 # the innermost part
2670 if os.name == 'posix':
2669 if os.name == 'posix':
2671 for pdir in path:
2670 for pdir in path:
2672 os.chdir(pdir)
2671 os.chdir(pdir)
2673 for ff in os.listdir(pdir):
2672 for ff in os.listdir(pdir):
2674 if isexec(ff) and ff not in self.shell.no_alias:
2673 if isexec(ff) and ff not in self.shell.no_alias:
2675 # each entry in the alias table must be (N,name),
2674 # each entry in the alias table must be (N,name),
2676 # where N is the number of positional arguments of the
2675 # where N is the number of positional arguments of the
2677 # alias.
2676 # alias.
2678 # Dots will be removed from alias names, since ipython
2677 # Dots will be removed from alias names, since ipython
2679 # assumes names with dots to be python code
2678 # assumes names with dots to be python code
2680 alias_table[ff.replace('.','')] = (0,ff)
2679 alias_table[ff.replace('.','')] = (0,ff)
2681 syscmdlist.append(ff)
2680 syscmdlist.append(ff)
2682 else:
2681 else:
2683 for pdir in path:
2682 for pdir in path:
2684 os.chdir(pdir)
2683 os.chdir(pdir)
2685 for ff in os.listdir(pdir):
2684 for ff in os.listdir(pdir):
2686 base, ext = os.path.splitext(ff)
2685 base, ext = os.path.splitext(ff)
2687 if isexec(ff) and base.lower() not in self.shell.no_alias:
2686 if isexec(ff) and base.lower() not in self.shell.no_alias:
2688 if ext.lower() == '.exe':
2687 if ext.lower() == '.exe':
2689 ff = base
2688 ff = base
2690 alias_table[base.lower().replace('.','')] = (0,ff)
2689 alias_table[base.lower().replace('.','')] = (0,ff)
2691 syscmdlist.append(ff)
2690 syscmdlist.append(ff)
2692 # Make sure the alias table doesn't contain keywords or builtins
2691 # Make sure the alias table doesn't contain keywords or builtins
2693 self.shell.alias_table_validate()
2692 self.shell.alias_table_validate()
2694 # Call again init_auto_alias() so we get 'rm -i' and other
2693 # Call again init_auto_alias() so we get 'rm -i' and other
2695 # modified aliases since %rehashx will probably clobber them
2694 # modified aliases since %rehashx will probably clobber them
2696
2695
2697 # no, we don't want them. if %rehashx clobbers them, good,
2696 # no, we don't want them. if %rehashx clobbers them, good,
2698 # we'll probably get better versions
2697 # we'll probably get better versions
2699 # self.shell.init_auto_alias()
2698 # self.shell.init_auto_alias()
2700 db = ip.db
2699 db = ip.db
2701 db['syscmdlist'] = syscmdlist
2700 db['syscmdlist'] = syscmdlist
2702 finally:
2701 finally:
2703 os.chdir(savedir)
2702 os.chdir(savedir)
2704
2703
2705 def magic_pwd(self, parameter_s = ''):
2704 def magic_pwd(self, parameter_s = ''):
2706 """Return the current working directory path."""
2705 """Return the current working directory path."""
2707 return os.getcwd()
2706 return os.getcwd()
2708
2707
2709 def magic_cd(self, parameter_s=''):
2708 def magic_cd(self, parameter_s=''):
2710 """Change the current working directory.
2709 """Change the current working directory.
2711
2710
2712 This command automatically maintains an internal list of directories
2711 This command automatically maintains an internal list of directories
2713 you visit during your IPython session, in the variable _dh. The
2712 you visit during your IPython session, in the variable _dh. The
2714 command %dhist shows this history nicely formatted. You can also
2713 command %dhist shows this history nicely formatted. You can also
2715 do 'cd -<tab>' to see directory history conveniently.
2714 do 'cd -<tab>' to see directory history conveniently.
2716
2715
2717 Usage:
2716 Usage:
2718
2717
2719 cd 'dir': changes to directory 'dir'.
2718 cd 'dir': changes to directory 'dir'.
2720
2719
2721 cd -: changes to the last visited directory.
2720 cd -: changes to the last visited directory.
2722
2721
2723 cd -<n>: changes to the n-th directory in the directory history.
2722 cd -<n>: changes to the n-th directory in the directory history.
2724
2723
2725 cd --foo: change to directory that matches 'foo' in history
2724 cd --foo: change to directory that matches 'foo' in history
2726
2725
2727 cd -b <bookmark_name>: jump to a bookmark set by %bookmark
2726 cd -b <bookmark_name>: jump to a bookmark set by %bookmark
2728 (note: cd <bookmark_name> is enough if there is no
2727 (note: cd <bookmark_name> is enough if there is no
2729 directory <bookmark_name>, but a bookmark with the name exists.)
2728 directory <bookmark_name>, but a bookmark with the name exists.)
2730 'cd -b <tab>' allows you to tab-complete bookmark names.
2729 'cd -b <tab>' allows you to tab-complete bookmark names.
2731
2730
2732 Options:
2731 Options:
2733
2732
2734 -q: quiet. Do not print the working directory after the cd command is
2733 -q: quiet. Do not print the working directory after the cd command is
2735 executed. By default IPython's cd command does print this directory,
2734 executed. By default IPython's cd command does print this directory,
2736 since the default prompts do not display path information.
2735 since the default prompts do not display path information.
2737
2736
2738 Note that !cd doesn't work for this purpose because the shell where
2737 Note that !cd doesn't work for this purpose because the shell where
2739 !command runs is immediately discarded after executing 'command'."""
2738 !command runs is immediately discarded after executing 'command'."""
2740
2739
2741 parameter_s = parameter_s.strip()
2740 parameter_s = parameter_s.strip()
2742 #bkms = self.shell.persist.get("bookmarks",{})
2741 #bkms = self.shell.persist.get("bookmarks",{})
2743
2742
2744 oldcwd = os.getcwd()
2743 oldcwd = os.getcwd()
2745 numcd = re.match(r'(-)(\d+)$',parameter_s)
2744 numcd = re.match(r'(-)(\d+)$',parameter_s)
2746 # jump in directory history by number
2745 # jump in directory history by number
2747 if numcd:
2746 if numcd:
2748 nn = int(numcd.group(2))
2747 nn = int(numcd.group(2))
2749 try:
2748 try:
2750 ps = self.shell.user_ns['_dh'][nn]
2749 ps = self.shell.user_ns['_dh'][nn]
2751 except IndexError:
2750 except IndexError:
2752 print 'The requested directory does not exist in history.'
2751 print 'The requested directory does not exist in history.'
2753 return
2752 return
2754 else:
2753 else:
2755 opts = {}
2754 opts = {}
2756 elif parameter_s.startswith('--'):
2755 elif parameter_s.startswith('--'):
2757 ps = None
2756 ps = None
2758 fallback = None
2757 fallback = None
2759 pat = parameter_s[2:]
2758 pat = parameter_s[2:]
2760 dh = self.shell.user_ns['_dh']
2759 dh = self.shell.user_ns['_dh']
2761 # first search only by basename (last component)
2760 # first search only by basename (last component)
2762 for ent in reversed(dh):
2761 for ent in reversed(dh):
2763 if pat in os.path.basename(ent) and os.path.isdir(ent):
2762 if pat in os.path.basename(ent) and os.path.isdir(ent):
2764 ps = ent
2763 ps = ent
2765 break
2764 break
2766
2765
2767 if fallback is None and pat in ent and os.path.isdir(ent):
2766 if fallback is None and pat in ent and os.path.isdir(ent):
2768 fallback = ent
2767 fallback = ent
2769
2768
2770 # if we have no last part match, pick the first full path match
2769 # if we have no last part match, pick the first full path match
2771 if ps is None:
2770 if ps is None:
2772 ps = fallback
2771 ps = fallback
2773
2772
2774 if ps is None:
2773 if ps is None:
2775 print "No matching entry in directory history"
2774 print "No matching entry in directory history"
2776 return
2775 return
2777 else:
2776 else:
2778 opts = {}
2777 opts = {}
2779
2778
2780
2779
2781 else:
2780 else:
2782 #turn all non-space-escaping backslashes to slashes,
2781 #turn all non-space-escaping backslashes to slashes,
2783 # for c:\windows\directory\names\
2782 # for c:\windows\directory\names\
2784 parameter_s = re.sub(r'\\(?! )','/', parameter_s)
2783 parameter_s = re.sub(r'\\(?! )','/', parameter_s)
2785 opts,ps = self.parse_options(parameter_s,'qb',mode='string')
2784 opts,ps = self.parse_options(parameter_s,'qb',mode='string')
2786 # jump to previous
2785 # jump to previous
2787 if ps == '-':
2786 if ps == '-':
2788 try:
2787 try:
2789 ps = self.shell.user_ns['_dh'][-2]
2788 ps = self.shell.user_ns['_dh'][-2]
2790 except IndexError:
2789 except IndexError:
2791 raise UsageError('%cd -: No previous directory to change to.')
2790 raise UsageError('%cd -: No previous directory to change to.')
2792 # jump to bookmark if needed
2791 # jump to bookmark if needed
2793 else:
2792 else:
2794 if not os.path.isdir(ps) or opts.has_key('b'):
2793 if not os.path.isdir(ps) or opts.has_key('b'):
2795 bkms = self.db.get('bookmarks', {})
2794 bkms = self.db.get('bookmarks', {})
2796
2795
2797 if bkms.has_key(ps):
2796 if bkms.has_key(ps):
2798 target = bkms[ps]
2797 target = bkms[ps]
2799 print '(bookmark:%s) -> %s' % (ps,target)
2798 print '(bookmark:%s) -> %s' % (ps,target)
2800 ps = target
2799 ps = target
2801 else:
2800 else:
2802 if opts.has_key('b'):
2801 if opts.has_key('b'):
2803 raise UsageError("Bookmark '%s' not found. "
2802 raise UsageError("Bookmark '%s' not found. "
2804 "Use '%%bookmark -l' to see your bookmarks." % ps)
2803 "Use '%%bookmark -l' to see your bookmarks." % ps)
2805
2804
2806 # at this point ps should point to the target dir
2805 # at this point ps should point to the target dir
2807 if ps:
2806 if ps:
2808 try:
2807 try:
2809 os.chdir(os.path.expanduser(ps))
2808 os.chdir(os.path.expanduser(ps))
2810 if self.shell.rc.term_title:
2809 if self.shell.rc.term_title:
2811 #print 'set term title:',self.shell.rc.term_title # dbg
2810 #print 'set term title:',self.shell.rc.term_title # dbg
2812 platutils.set_term_title('IPy ' + abbrev_cwd())
2811 platutils.set_term_title('IPy ' + abbrev_cwd())
2813 except OSError:
2812 except OSError:
2814 print sys.exc_info()[1]
2813 print sys.exc_info()[1]
2815 else:
2814 else:
2816 cwd = os.getcwd()
2815 cwd = os.getcwd()
2817 dhist = self.shell.user_ns['_dh']
2816 dhist = self.shell.user_ns['_dh']
2818 if oldcwd != cwd:
2817 if oldcwd != cwd:
2819 dhist.append(cwd)
2818 dhist.append(cwd)
2820 self.db['dhist'] = compress_dhist(dhist)[-100:]
2819 self.db['dhist'] = compress_dhist(dhist)[-100:]
2821
2820
2822 else:
2821 else:
2823 os.chdir(self.shell.home_dir)
2822 os.chdir(self.shell.home_dir)
2824 if self.shell.rc.term_title:
2823 if self.shell.rc.term_title:
2825 platutils.set_term_title("IPy ~")
2824 platutils.set_term_title("IPy ~")
2826 cwd = os.getcwd()
2825 cwd = os.getcwd()
2827 dhist = self.shell.user_ns['_dh']
2826 dhist = self.shell.user_ns['_dh']
2828
2827
2829 if oldcwd != cwd:
2828 if oldcwd != cwd:
2830 dhist.append(cwd)
2829 dhist.append(cwd)
2831 self.db['dhist'] = compress_dhist(dhist)[-100:]
2830 self.db['dhist'] = compress_dhist(dhist)[-100:]
2832 if not 'q' in opts and self.shell.user_ns['_dh']:
2831 if not 'q' in opts and self.shell.user_ns['_dh']:
2833 print self.shell.user_ns['_dh'][-1]
2832 print self.shell.user_ns['_dh'][-1]
2834
2833
2835
2834
2836 def magic_env(self, parameter_s=''):
2835 def magic_env(self, parameter_s=''):
2837 """List environment variables."""
2836 """List environment variables."""
2838
2837
2839 return os.environ.data
2838 return os.environ.data
2840
2839
2841 def magic_pushd(self, parameter_s=''):
2840 def magic_pushd(self, parameter_s=''):
2842 """Place the current dir on stack and change directory.
2841 """Place the current dir on stack and change directory.
2843
2842
2844 Usage:\\
2843 Usage:\\
2845 %pushd ['dirname']
2844 %pushd ['dirname']
2846 """
2845 """
2847
2846
2848 dir_s = self.shell.dir_stack
2847 dir_s = self.shell.dir_stack
2849 tgt = os.path.expanduser(parameter_s)
2848 tgt = os.path.expanduser(parameter_s)
2850 cwd = os.getcwd().replace(self.home_dir,'~')
2849 cwd = os.getcwd().replace(self.home_dir,'~')
2851 if tgt:
2850 if tgt:
2852 self.magic_cd(parameter_s)
2851 self.magic_cd(parameter_s)
2853 dir_s.insert(0,cwd)
2852 dir_s.insert(0,cwd)
2854 return self.magic_dirs()
2853 return self.magic_dirs()
2855
2854
2856 def magic_popd(self, parameter_s=''):
2855 def magic_popd(self, parameter_s=''):
2857 """Change to directory popped off the top of the stack.
2856 """Change to directory popped off the top of the stack.
2858 """
2857 """
2859 if not self.shell.dir_stack:
2858 if not self.shell.dir_stack:
2860 raise UsageError("%popd on empty stack")
2859 raise UsageError("%popd on empty stack")
2861 top = self.shell.dir_stack.pop(0)
2860 top = self.shell.dir_stack.pop(0)
2862 self.magic_cd(top)
2861 self.magic_cd(top)
2863 print "popd ->",top
2862 print "popd ->",top
2864
2863
2865 def magic_dirs(self, parameter_s=''):
2864 def magic_dirs(self, parameter_s=''):
2866 """Return the current directory stack."""
2865 """Return the current directory stack."""
2867
2866
2868 return self.shell.dir_stack
2867 return self.shell.dir_stack
2869
2868
2870 def magic_dhist(self, parameter_s=''):
2869 def magic_dhist(self, parameter_s=''):
2871 """Print your history of visited directories.
2870 """Print your history of visited directories.
2872
2871
2873 %dhist -> print full history\\
2872 %dhist -> print full history\\
2874 %dhist n -> print last n entries only\\
2873 %dhist n -> print last n entries only\\
2875 %dhist n1 n2 -> print entries between n1 and n2 (n1 not included)\\
2874 %dhist n1 n2 -> print entries between n1 and n2 (n1 not included)\\
2876
2875
2877 This history is automatically maintained by the %cd command, and
2876 This history is automatically maintained by the %cd command, and
2878 always available as the global list variable _dh. You can use %cd -<n>
2877 always available as the global list variable _dh. You can use %cd -<n>
2879 to go to directory number <n>.
2878 to go to directory number <n>.
2880
2879
2881 Note that most of time, you should view directory history by entering
2880 Note that most of time, you should view directory history by entering
2882 cd -<TAB>.
2881 cd -<TAB>.
2883
2882
2884 """
2883 """
2885
2884
2886 dh = self.shell.user_ns['_dh']
2885 dh = self.shell.user_ns['_dh']
2887 if parameter_s:
2886 if parameter_s:
2888 try:
2887 try:
2889 args = map(int,parameter_s.split())
2888 args = map(int,parameter_s.split())
2890 except:
2889 except:
2891 self.arg_err(Magic.magic_dhist)
2890 self.arg_err(Magic.magic_dhist)
2892 return
2891 return
2893 if len(args) == 1:
2892 if len(args) == 1:
2894 ini,fin = max(len(dh)-(args[0]),0),len(dh)
2893 ini,fin = max(len(dh)-(args[0]),0),len(dh)
2895 elif len(args) == 2:
2894 elif len(args) == 2:
2896 ini,fin = args
2895 ini,fin = args
2897 else:
2896 else:
2898 self.arg_err(Magic.magic_dhist)
2897 self.arg_err(Magic.magic_dhist)
2899 return
2898 return
2900 else:
2899 else:
2901 ini,fin = 0,len(dh)
2900 ini,fin = 0,len(dh)
2902 nlprint(dh,
2901 nlprint(dh,
2903 header = 'Directory history (kept in _dh)',
2902 header = 'Directory history (kept in _dh)',
2904 start=ini,stop=fin)
2903 start=ini,stop=fin)
2905
2904
2906 @testdec.skip_doctest
2905 @testdec.skip_doctest
2907 def magic_sc(self, parameter_s=''):
2906 def magic_sc(self, parameter_s=''):
2908 """Shell capture - execute a shell command and capture its output.
2907 """Shell capture - execute a shell command and capture its output.
2909
2908
2910 DEPRECATED. Suboptimal, retained for backwards compatibility.
2909 DEPRECATED. Suboptimal, retained for backwards compatibility.
2911
2910
2912 You should use the form 'var = !command' instead. Example:
2911 You should use the form 'var = !command' instead. Example:
2913
2912
2914 "%sc -l myfiles = ls ~" should now be written as
2913 "%sc -l myfiles = ls ~" should now be written as
2915
2914
2916 "myfiles = !ls ~"
2915 "myfiles = !ls ~"
2917
2916
2918 myfiles.s, myfiles.l and myfiles.n still apply as documented
2917 myfiles.s, myfiles.l and myfiles.n still apply as documented
2919 below.
2918 below.
2920
2919
2921 --
2920 --
2922 %sc [options] varname=command
2921 %sc [options] varname=command
2923
2922
2924 IPython will run the given command using commands.getoutput(), and
2923 IPython will run the given command using commands.getoutput(), and
2925 will then update the user's interactive namespace with a variable
2924 will then update the user's interactive namespace with a variable
2926 called varname, containing the value of the call. Your command can
2925 called varname, containing the value of the call. Your command can
2927 contain shell wildcards, pipes, etc.
2926 contain shell wildcards, pipes, etc.
2928
2927
2929 The '=' sign in the syntax is mandatory, and the variable name you
2928 The '=' sign in the syntax is mandatory, and the variable name you
2930 supply must follow Python's standard conventions for valid names.
2929 supply must follow Python's standard conventions for valid names.
2931
2930
2932 (A special format without variable name exists for internal use)
2931 (A special format without variable name exists for internal use)
2933
2932
2934 Options:
2933 Options:
2935
2934
2936 -l: list output. Split the output on newlines into a list before
2935 -l: list output. Split the output on newlines into a list before
2937 assigning it to the given variable. By default the output is stored
2936 assigning it to the given variable. By default the output is stored
2938 as a single string.
2937 as a single string.
2939
2938
2940 -v: verbose. Print the contents of the variable.
2939 -v: verbose. Print the contents of the variable.
2941
2940
2942 In most cases you should not need to split as a list, because the
2941 In most cases you should not need to split as a list, because the
2943 returned value is a special type of string which can automatically
2942 returned value is a special type of string which can automatically
2944 provide its contents either as a list (split on newlines) or as a
2943 provide its contents either as a list (split on newlines) or as a
2945 space-separated string. These are convenient, respectively, either
2944 space-separated string. These are convenient, respectively, either
2946 for sequential processing or to be passed to a shell command.
2945 for sequential processing or to be passed to a shell command.
2947
2946
2948 For example:
2947 For example:
2949
2948
2950 # all-random
2949 # all-random
2951
2950
2952 # Capture into variable a
2951 # Capture into variable a
2953 In [1]: sc a=ls *py
2952 In [1]: sc a=ls *py
2954
2953
2955 # a is a string with embedded newlines
2954 # a is a string with embedded newlines
2956 In [2]: a
2955 In [2]: a
2957 Out[2]: 'setup.py\\nwin32_manual_post_install.py'
2956 Out[2]: 'setup.py\\nwin32_manual_post_install.py'
2958
2957
2959 # which can be seen as a list:
2958 # which can be seen as a list:
2960 In [3]: a.l
2959 In [3]: a.l
2961 Out[3]: ['setup.py', 'win32_manual_post_install.py']
2960 Out[3]: ['setup.py', 'win32_manual_post_install.py']
2962
2961
2963 # or as a whitespace-separated string:
2962 # or as a whitespace-separated string:
2964 In [4]: a.s
2963 In [4]: a.s
2965 Out[4]: 'setup.py win32_manual_post_install.py'
2964 Out[4]: 'setup.py win32_manual_post_install.py'
2966
2965
2967 # a.s is useful to pass as a single command line:
2966 # a.s is useful to pass as a single command line:
2968 In [5]: !wc -l $a.s
2967 In [5]: !wc -l $a.s
2969 146 setup.py
2968 146 setup.py
2970 130 win32_manual_post_install.py
2969 130 win32_manual_post_install.py
2971 276 total
2970 276 total
2972
2971
2973 # while the list form is useful to loop over:
2972 # while the list form is useful to loop over:
2974 In [6]: for f in a.l:
2973 In [6]: for f in a.l:
2975 ...: !wc -l $f
2974 ...: !wc -l $f
2976 ...:
2975 ...:
2977 146 setup.py
2976 146 setup.py
2978 130 win32_manual_post_install.py
2977 130 win32_manual_post_install.py
2979
2978
2980 Similiarly, the lists returned by the -l option are also special, in
2979 Similiarly, the lists returned by the -l option are also special, in
2981 the sense that you can equally invoke the .s attribute on them to
2980 the sense that you can equally invoke the .s attribute on them to
2982 automatically get a whitespace-separated string from their contents:
2981 automatically get a whitespace-separated string from their contents:
2983
2982
2984 In [7]: sc -l b=ls *py
2983 In [7]: sc -l b=ls *py
2985
2984
2986 In [8]: b
2985 In [8]: b
2987 Out[8]: ['setup.py', 'win32_manual_post_install.py']
2986 Out[8]: ['setup.py', 'win32_manual_post_install.py']
2988
2987
2989 In [9]: b.s
2988 In [9]: b.s
2990 Out[9]: 'setup.py win32_manual_post_install.py'
2989 Out[9]: 'setup.py win32_manual_post_install.py'
2991
2990
2992 In summary, both the lists and strings used for ouptut capture have
2991 In summary, both the lists and strings used for ouptut capture have
2993 the following special attributes:
2992 the following special attributes:
2994
2993
2995 .l (or .list) : value as list.
2994 .l (or .list) : value as list.
2996 .n (or .nlstr): value as newline-separated string.
2995 .n (or .nlstr): value as newline-separated string.
2997 .s (or .spstr): value as space-separated string.
2996 .s (or .spstr): value as space-separated string.
2998 """
2997 """
2999
2998
3000 opts,args = self.parse_options(parameter_s,'lv')
2999 opts,args = self.parse_options(parameter_s,'lv')
3001 # Try to get a variable name and command to run
3000 # Try to get a variable name and command to run
3002 try:
3001 try:
3003 # the variable name must be obtained from the parse_options
3002 # the variable name must be obtained from the parse_options
3004 # output, which uses shlex.split to strip options out.
3003 # output, which uses shlex.split to strip options out.
3005 var,_ = args.split('=',1)
3004 var,_ = args.split('=',1)
3006 var = var.strip()
3005 var = var.strip()
3007 # But the the command has to be extracted from the original input
3006 # But the the command has to be extracted from the original input
3008 # parameter_s, not on what parse_options returns, to avoid the
3007 # parameter_s, not on what parse_options returns, to avoid the
3009 # quote stripping which shlex.split performs on it.
3008 # quote stripping which shlex.split performs on it.
3010 _,cmd = parameter_s.split('=',1)
3009 _,cmd = parameter_s.split('=',1)
3011 except ValueError:
3010 except ValueError:
3012 var,cmd = '',''
3011 var,cmd = '',''
3013 # If all looks ok, proceed
3012 # If all looks ok, proceed
3014 out,err = self.shell.getoutputerror(cmd)
3013 out,err = self.shell.getoutputerror(cmd)
3015 if err:
3014 if err:
3016 print >> Term.cerr,err
3015 print >> Term.cerr,err
3017 if opts.has_key('l'):
3016 if opts.has_key('l'):
3018 out = SList(out.split('\n'))
3017 out = SList(out.split('\n'))
3019 else:
3018 else:
3020 out = LSString(out)
3019 out = LSString(out)
3021 if opts.has_key('v'):
3020 if opts.has_key('v'):
3022 print '%s ==\n%s' % (var,pformat(out))
3021 print '%s ==\n%s' % (var,pformat(out))
3023 if var:
3022 if var:
3024 self.shell.user_ns.update({var:out})
3023 self.shell.user_ns.update({var:out})
3025 else:
3024 else:
3026 return out
3025 return out
3027
3026
3028 def magic_sx(self, parameter_s=''):
3027 def magic_sx(self, parameter_s=''):
3029 """Shell execute - run a shell command and capture its output.
3028 """Shell execute - run a shell command and capture its output.
3030
3029
3031 %sx command
3030 %sx command
3032
3031
3033 IPython will run the given command using commands.getoutput(), and
3032 IPython will run the given command using commands.getoutput(), and
3034 return the result formatted as a list (split on '\\n'). Since the
3033 return the result formatted as a list (split on '\\n'). Since the
3035 output is _returned_, it will be stored in ipython's regular output
3034 output is _returned_, it will be stored in ipython's regular output
3036 cache Out[N] and in the '_N' automatic variables.
3035 cache Out[N] and in the '_N' automatic variables.
3037
3036
3038 Notes:
3037 Notes:
3039
3038
3040 1) If an input line begins with '!!', then %sx is automatically
3039 1) If an input line begins with '!!', then %sx is automatically
3041 invoked. That is, while:
3040 invoked. That is, while:
3042 !ls
3041 !ls
3043 causes ipython to simply issue system('ls'), typing
3042 causes ipython to simply issue system('ls'), typing
3044 !!ls
3043 !!ls
3045 is a shorthand equivalent to:
3044 is a shorthand equivalent to:
3046 %sx ls
3045 %sx ls
3047
3046
3048 2) %sx differs from %sc in that %sx automatically splits into a list,
3047 2) %sx differs from %sc in that %sx automatically splits into a list,
3049 like '%sc -l'. The reason for this is to make it as easy as possible
3048 like '%sc -l'. The reason for this is to make it as easy as possible
3050 to process line-oriented shell output via further python commands.
3049 to process line-oriented shell output via further python commands.
3051 %sc is meant to provide much finer control, but requires more
3050 %sc is meant to provide much finer control, but requires more
3052 typing.
3051 typing.
3053
3052
3054 3) Just like %sc -l, this is a list with special attributes:
3053 3) Just like %sc -l, this is a list with special attributes:
3055
3054
3056 .l (or .list) : value as list.
3055 .l (or .list) : value as list.
3057 .n (or .nlstr): value as newline-separated string.
3056 .n (or .nlstr): value as newline-separated string.
3058 .s (or .spstr): value as whitespace-separated string.
3057 .s (or .spstr): value as whitespace-separated string.
3059
3058
3060 This is very useful when trying to use such lists as arguments to
3059 This is very useful when trying to use such lists as arguments to
3061 system commands."""
3060 system commands."""
3062
3061
3063 if parameter_s:
3062 if parameter_s:
3064 out,err = self.shell.getoutputerror(parameter_s)
3063 out,err = self.shell.getoutputerror(parameter_s)
3065 if err:
3064 if err:
3066 print >> Term.cerr,err
3065 print >> Term.cerr,err
3067 return SList(out.split('\n'))
3066 return SList(out.split('\n'))
3068
3067
3069 def magic_bg(self, parameter_s=''):
3068 def magic_bg(self, parameter_s=''):
3070 """Run a job in the background, in a separate thread.
3069 """Run a job in the background, in a separate thread.
3071
3070
3072 For example,
3071 For example,
3073
3072
3074 %bg myfunc(x,y,z=1)
3073 %bg myfunc(x,y,z=1)
3075
3074
3076 will execute 'myfunc(x,y,z=1)' in a background thread. As soon as the
3075 will execute 'myfunc(x,y,z=1)' in a background thread. As soon as the
3077 execution starts, a message will be printed indicating the job
3076 execution starts, a message will be printed indicating the job
3078 number. If your job number is 5, you can use
3077 number. If your job number is 5, you can use
3079
3078
3080 myvar = jobs.result(5) or myvar = jobs[5].result
3079 myvar = jobs.result(5) or myvar = jobs[5].result
3081
3080
3082 to assign this result to variable 'myvar'.
3081 to assign this result to variable 'myvar'.
3083
3082
3084 IPython has a job manager, accessible via the 'jobs' object. You can
3083 IPython has a job manager, accessible via the 'jobs' object. You can
3085 type jobs? to get more information about it, and use jobs.<TAB> to see
3084 type jobs? to get more information about it, and use jobs.<TAB> to see
3086 its attributes. All attributes not starting with an underscore are
3085 its attributes. All attributes not starting with an underscore are
3087 meant for public use.
3086 meant for public use.
3088
3087
3089 In particular, look at the jobs.new() method, which is used to create
3088 In particular, look at the jobs.new() method, which is used to create
3090 new jobs. This magic %bg function is just a convenience wrapper
3089 new jobs. This magic %bg function is just a convenience wrapper
3091 around jobs.new(), for expression-based jobs. If you want to create a
3090 around jobs.new(), for expression-based jobs. If you want to create a
3092 new job with an explicit function object and arguments, you must call
3091 new job with an explicit function object and arguments, you must call
3093 jobs.new() directly.
3092 jobs.new() directly.
3094
3093
3095 The jobs.new docstring also describes in detail several important
3094 The jobs.new docstring also describes in detail several important
3096 caveats associated with a thread-based model for background job
3095 caveats associated with a thread-based model for background job
3097 execution. Type jobs.new? for details.
3096 execution. Type jobs.new? for details.
3098
3097
3099 You can check the status of all jobs with jobs.status().
3098 You can check the status of all jobs with jobs.status().
3100
3099
3101 The jobs variable is set by IPython into the Python builtin namespace.
3100 The jobs variable is set by IPython into the Python builtin namespace.
3102 If you ever declare a variable named 'jobs', you will shadow this
3101 If you ever declare a variable named 'jobs', you will shadow this
3103 name. You can either delete your global jobs variable to regain
3102 name. You can either delete your global jobs variable to regain
3104 access to the job manager, or make a new name and assign it manually
3103 access to the job manager, or make a new name and assign it manually
3105 to the manager (stored in IPython's namespace). For example, to
3104 to the manager (stored in IPython's namespace). For example, to
3106 assign the job manager to the Jobs name, use:
3105 assign the job manager to the Jobs name, use:
3107
3106
3108 Jobs = __builtins__.jobs"""
3107 Jobs = __builtins__.jobs"""
3109
3108
3110 self.shell.jobs.new(parameter_s,self.shell.user_ns)
3109 self.shell.jobs.new(parameter_s,self.shell.user_ns)
3111
3110
3112 def magic_r(self, parameter_s=''):
3111 def magic_r(self, parameter_s=''):
3113 """Repeat previous input.
3112 """Repeat previous input.
3114
3113
3115 Note: Consider using the more powerfull %rep instead!
3114 Note: Consider using the more powerfull %rep instead!
3116
3115
3117 If given an argument, repeats the previous command which starts with
3116 If given an argument, repeats the previous command which starts with
3118 the same string, otherwise it just repeats the previous input.
3117 the same string, otherwise it just repeats the previous input.
3119
3118
3120 Shell escaped commands (with ! as first character) are not recognized
3119 Shell escaped commands (with ! as first character) are not recognized
3121 by this system, only pure python code and magic commands.
3120 by this system, only pure python code and magic commands.
3122 """
3121 """
3123
3122
3124 start = parameter_s.strip()
3123 start = parameter_s.strip()
3125 esc_magic = self.shell.ESC_MAGIC
3124 esc_magic = self.shell.ESC_MAGIC
3126 # Identify magic commands even if automagic is on (which means
3125 # Identify magic commands even if automagic is on (which means
3127 # the in-memory version is different from that typed by the user).
3126 # the in-memory version is different from that typed by the user).
3128 if self.shell.rc.automagic:
3127 if self.shell.rc.automagic:
3129 start_magic = esc_magic+start
3128 start_magic = esc_magic+start
3130 else:
3129 else:
3131 start_magic = start
3130 start_magic = start
3132 # Look through the input history in reverse
3131 # Look through the input history in reverse
3133 for n in range(len(self.shell.input_hist)-2,0,-1):
3132 for n in range(len(self.shell.input_hist)-2,0,-1):
3134 input = self.shell.input_hist[n]
3133 input = self.shell.input_hist[n]
3135 # skip plain 'r' lines so we don't recurse to infinity
3134 # skip plain 'r' lines so we don't recurse to infinity
3136 if input != '_ip.magic("r")\n' and \
3135 if input != '_ip.magic("r")\n' and \
3137 (input.startswith(start) or input.startswith(start_magic)):
3136 (input.startswith(start) or input.startswith(start_magic)):
3138 #print 'match',`input` # dbg
3137 #print 'match',`input` # dbg
3139 print 'Executing:',input,
3138 print 'Executing:',input,
3140 self.shell.runlines(input)
3139 self.shell.runlines(input)
3141 return
3140 return
3142 print 'No previous input matching `%s` found.' % start
3141 print 'No previous input matching `%s` found.' % start
3143
3142
3144
3143
3145 def magic_bookmark(self, parameter_s=''):
3144 def magic_bookmark(self, parameter_s=''):
3146 """Manage IPython's bookmark system.
3145 """Manage IPython's bookmark system.
3147
3146
3148 %bookmark <name> - set bookmark to current dir
3147 %bookmark <name> - set bookmark to current dir
3149 %bookmark <name> <dir> - set bookmark to <dir>
3148 %bookmark <name> <dir> - set bookmark to <dir>
3150 %bookmark -l - list all bookmarks
3149 %bookmark -l - list all bookmarks
3151 %bookmark -d <name> - remove bookmark
3150 %bookmark -d <name> - remove bookmark
3152 %bookmark -r - remove all bookmarks
3151 %bookmark -r - remove all bookmarks
3153
3152
3154 You can later on access a bookmarked folder with:
3153 You can later on access a bookmarked folder with:
3155 %cd -b <name>
3154 %cd -b <name>
3156 or simply '%cd <name>' if there is no directory called <name> AND
3155 or simply '%cd <name>' if there is no directory called <name> AND
3157 there is such a bookmark defined.
3156 there is such a bookmark defined.
3158
3157
3159 Your bookmarks persist through IPython sessions, but they are
3158 Your bookmarks persist through IPython sessions, but they are
3160 associated with each profile."""
3159 associated with each profile."""
3161
3160
3162 opts,args = self.parse_options(parameter_s,'drl',mode='list')
3161 opts,args = self.parse_options(parameter_s,'drl',mode='list')
3163 if len(args) > 2:
3162 if len(args) > 2:
3164 raise UsageError("%bookmark: too many arguments")
3163 raise UsageError("%bookmark: too many arguments")
3165
3164
3166 bkms = self.db.get('bookmarks',{})
3165 bkms = self.db.get('bookmarks',{})
3167
3166
3168 if opts.has_key('d'):
3167 if opts.has_key('d'):
3169 try:
3168 try:
3170 todel = args[0]
3169 todel = args[0]
3171 except IndexError:
3170 except IndexError:
3172 raise UsageError(
3171 raise UsageError(
3173 "%bookmark -d: must provide a bookmark to delete")
3172 "%bookmark -d: must provide a bookmark to delete")
3174 else:
3173 else:
3175 try:
3174 try:
3176 del bkms[todel]
3175 del bkms[todel]
3177 except KeyError:
3176 except KeyError:
3178 raise UsageError(
3177 raise UsageError(
3179 "%%bookmark -d: Can't delete bookmark '%s'" % todel)
3178 "%%bookmark -d: Can't delete bookmark '%s'" % todel)
3180
3179
3181 elif opts.has_key('r'):
3180 elif opts.has_key('r'):
3182 bkms = {}
3181 bkms = {}
3183 elif opts.has_key('l'):
3182 elif opts.has_key('l'):
3184 bks = bkms.keys()
3183 bks = bkms.keys()
3185 bks.sort()
3184 bks.sort()
3186 if bks:
3185 if bks:
3187 size = max(map(len,bks))
3186 size = max(map(len,bks))
3188 else:
3187 else:
3189 size = 0
3188 size = 0
3190 fmt = '%-'+str(size)+'s -> %s'
3189 fmt = '%-'+str(size)+'s -> %s'
3191 print 'Current bookmarks:'
3190 print 'Current bookmarks:'
3192 for bk in bks:
3191 for bk in bks:
3193 print fmt % (bk,bkms[bk])
3192 print fmt % (bk,bkms[bk])
3194 else:
3193 else:
3195 if not args:
3194 if not args:
3196 raise UsageError("%bookmark: You must specify the bookmark name")
3195 raise UsageError("%bookmark: You must specify the bookmark name")
3197 elif len(args)==1:
3196 elif len(args)==1:
3198 bkms[args[0]] = os.getcwd()
3197 bkms[args[0]] = os.getcwd()
3199 elif len(args)==2:
3198 elif len(args)==2:
3200 bkms[args[0]] = args[1]
3199 bkms[args[0]] = args[1]
3201 self.db['bookmarks'] = bkms
3200 self.db['bookmarks'] = bkms
3202
3201
3203 def magic_pycat(self, parameter_s=''):
3202 def magic_pycat(self, parameter_s=''):
3204 """Show a syntax-highlighted file through a pager.
3203 """Show a syntax-highlighted file through a pager.
3205
3204
3206 This magic is similar to the cat utility, but it will assume the file
3205 This magic is similar to the cat utility, but it will assume the file
3207 to be Python source and will show it with syntax highlighting. """
3206 to be Python source and will show it with syntax highlighting. """
3208
3207
3209 try:
3208 try:
3210 filename = get_py_filename(parameter_s)
3209 filename = get_py_filename(parameter_s)
3211 cont = file_read(filename)
3210 cont = file_read(filename)
3212 except IOError:
3211 except IOError:
3213 try:
3212 try:
3214 cont = eval(parameter_s,self.user_ns)
3213 cont = eval(parameter_s,self.user_ns)
3215 except NameError:
3214 except NameError:
3216 cont = None
3215 cont = None
3217 if cont is None:
3216 if cont is None:
3218 print "Error: no such file or variable"
3217 print "Error: no such file or variable"
3219 return
3218 return
3220
3219
3221 page(self.shell.pycolorize(cont),
3220 page(self.shell.pycolorize(cont),
3222 screen_lines=self.shell.rc.screen_length)
3221 screen_lines=self.shell.rc.screen_length)
3223
3222
3224 def magic_cpaste(self, parameter_s=''):
3223 def magic_cpaste(self, parameter_s=''):
3225 """Allows you to paste & execute a pre-formatted code block from clipboard.
3224 """Allows you to paste & execute a pre-formatted code block from clipboard.
3226
3225
3227 You must terminate the block with '--' (two minus-signs) alone on the
3226 You must terminate the block with '--' (two minus-signs) alone on the
3228 line. You can also provide your own sentinel with '%paste -s %%' ('%%'
3227 line. You can also provide your own sentinel with '%paste -s %%' ('%%'
3229 is the new sentinel for this operation)
3228 is the new sentinel for this operation)
3230
3229
3231 The block is dedented prior to execution to enable execution of method
3230 The block is dedented prior to execution to enable execution of method
3232 definitions. '>' and '+' characters at the beginning of a line are
3231 definitions. '>' and '+' characters at the beginning of a line are
3233 ignored, to allow pasting directly from e-mails, diff files and
3232 ignored, to allow pasting directly from e-mails, diff files and
3234 doctests (the '...' continuation prompt is also stripped). The
3233 doctests (the '...' continuation prompt is also stripped). The
3235 executed block is also assigned to variable named 'pasted_block' for
3234 executed block is also assigned to variable named 'pasted_block' for
3236 later editing with '%edit pasted_block'.
3235 later editing with '%edit pasted_block'.
3237
3236
3238 You can also pass a variable name as an argument, e.g. '%cpaste foo'.
3237 You can also pass a variable name as an argument, e.g. '%cpaste foo'.
3239 This assigns the pasted block to variable 'foo' as string, without
3238 This assigns the pasted block to variable 'foo' as string, without
3240 dedenting or executing it (preceding >>> and + is still stripped)
3239 dedenting or executing it (preceding >>> and + is still stripped)
3241
3240
3242 '%cpaste -r' re-executes the block previously entered by cpaste.
3241 '%cpaste -r' re-executes the block previously entered by cpaste.
3243
3242
3244 Do not be alarmed by garbled output on Windows (it's a readline bug).
3243 Do not be alarmed by garbled output on Windows (it's a readline bug).
3245 Just press enter and type -- (and press enter again) and the block
3244 Just press enter and type -- (and press enter again) and the block
3246 will be what was just pasted.
3245 will be what was just pasted.
3247
3246
3248 IPython statements (magics, shell escapes) are not supported (yet).
3247 IPython statements (magics, shell escapes) are not supported (yet).
3249 """
3248 """
3250 opts,args = self.parse_options(parameter_s,'rs:',mode='string')
3249 opts,args = self.parse_options(parameter_s,'rs:',mode='string')
3251 par = args.strip()
3250 par = args.strip()
3252 if opts.has_key('r'):
3251 if opts.has_key('r'):
3253 b = self.user_ns.get('pasted_block', None)
3252 b = self.user_ns.get('pasted_block', None)
3254 if b is None:
3253 if b is None:
3255 raise UsageError('No previous pasted block available')
3254 raise UsageError('No previous pasted block available')
3256 print "Re-executing '%s...' (%d chars)"% (b.split('\n',1)[0], len(b))
3255 print "Re-executing '%s...' (%d chars)"% (b.split('\n',1)[0], len(b))
3257 exec b in self.user_ns
3256 exec b in self.user_ns
3258 return
3257 return
3259
3258
3260 sentinel = opts.get('s','--')
3259 sentinel = opts.get('s','--')
3261
3260
3262 # Regular expressions that declare text we strip from the input:
3261 # Regular expressions that declare text we strip from the input:
3263 strip_re = [r'^\s*In \[\d+\]:', # IPython input prompt
3262 strip_re = [r'^\s*In \[\d+\]:', # IPython input prompt
3264 r'^\s*(\s?>)+', # Python input prompt
3263 r'^\s*(\s?>)+', # Python input prompt
3265 r'^\s*\.{3,}', # Continuation prompts
3264 r'^\s*\.{3,}', # Continuation prompts
3266 r'^\++',
3265 r'^\++',
3267 ]
3266 ]
3268
3267
3269 strip_from_start = map(re.compile,strip_re)
3268 strip_from_start = map(re.compile,strip_re)
3270
3269
3271 from IPython import iplib
3270 from IPython import iplib
3272 lines = []
3271 lines = []
3273 print "Pasting code; enter '%s' alone on the line to stop." % sentinel
3272 print "Pasting code; enter '%s' alone on the line to stop." % sentinel
3274 while 1:
3273 while 1:
3275 l = iplib.raw_input_original(':')
3274 l = iplib.raw_input_original(':')
3276 if l ==sentinel:
3275 if l ==sentinel:
3277 break
3276 break
3278
3277
3279 for pat in strip_from_start:
3278 for pat in strip_from_start:
3280 l = pat.sub('',l)
3279 l = pat.sub('',l)
3281 lines.append(l)
3280 lines.append(l)
3282
3281
3283 block = "\n".join(lines) + '\n'
3282 block = "\n".join(lines) + '\n'
3284 #print "block:\n",block
3283 #print "block:\n",block
3285 if not par:
3284 if not par:
3286 b = textwrap.dedent(block)
3285 b = textwrap.dedent(block)
3287 self.user_ns['pasted_block'] = b
3286 self.user_ns['pasted_block'] = b
3288 exec b in self.user_ns
3287 exec b in self.user_ns
3289 else:
3288 else:
3290 self.user_ns[par] = SList(block.splitlines())
3289 self.user_ns[par] = SList(block.splitlines())
3291 print "Block assigned to '%s'" % par
3290 print "Block assigned to '%s'" % par
3292
3291
3293 def magic_quickref(self,arg):
3292 def magic_quickref(self,arg):
3294 """ Show a quick reference sheet """
3293 """ Show a quick reference sheet """
3295 import IPython.usage
3294 import IPython.usage
3296 qr = IPython.usage.quick_reference + self.magic_magic('-brief')
3295 qr = IPython.usage.quick_reference + self.magic_magic('-brief')
3297
3296
3298 page(qr)
3297 page(qr)
3299
3298
3300 def magic_upgrade(self,arg):
3299 def magic_upgrade(self,arg):
3301 """ Upgrade your IPython installation
3300 """ Upgrade your IPython installation
3302
3301
3303 This will copy the config files that don't yet exist in your
3302 This will copy the config files that don't yet exist in your
3304 ipython dir from the system config dir. Use this after upgrading
3303 ipython dir from the system config dir. Use this after upgrading
3305 IPython if you don't wish to delete your .ipython dir.
3304 IPython if you don't wish to delete your .ipython dir.
3306
3305
3307 Call with -nolegacy to get rid of ipythonrc* files (recommended for
3306 Call with -nolegacy to get rid of ipythonrc* files (recommended for
3308 new users)
3307 new users)
3309
3308
3310 """
3309 """
3311 ip = self.getapi()
3310 ip = self.getapi()
3312 ipinstallation = path(IPython.__file__).dirname()
3311 ipinstallation = path(IPython.__file__).dirname()
3313 upgrade_script = '%s "%s"' % (sys.executable,ipinstallation / 'upgrade_dir.py')
3312 upgrade_script = '%s "%s"' % (sys.executable,ipinstallation / 'upgrade_dir.py')
3314 src_config = ipinstallation / 'UserConfig'
3313 src_config = ipinstallation / 'UserConfig'
3315 userdir = path(ip.options.ipythondir)
3314 userdir = path(ip.options.ipythondir)
3316 cmd = '%s "%s" "%s"' % (upgrade_script, src_config, userdir)
3315 cmd = '%s "%s" "%s"' % (upgrade_script, src_config, userdir)
3317 print ">",cmd
3316 print ">",cmd
3318 shell(cmd)
3317 shell(cmd)
3319 if arg == '-nolegacy':
3318 if arg == '-nolegacy':
3320 legacy = userdir.files('ipythonrc*')
3319 legacy = userdir.files('ipythonrc*')
3321 print "Nuking legacy files:",legacy
3320 print "Nuking legacy files:",legacy
3322
3321
3323 [p.remove() for p in legacy]
3322 [p.remove() for p in legacy]
3324 suffix = (sys.platform == 'win32' and '.ini' or '')
3323 suffix = (sys.platform == 'win32' and '.ini' or '')
3325 (userdir / ('ipythonrc' + suffix)).write_text('# Empty, see ipy_user_conf.py\n')
3324 (userdir / ('ipythonrc' + suffix)).write_text('# Empty, see ipy_user_conf.py\n')
3326
3325
3327
3326
3328 def magic_doctest_mode(self,parameter_s=''):
3327 def magic_doctest_mode(self,parameter_s=''):
3329 """Toggle doctest mode on and off.
3328 """Toggle doctest mode on and off.
3330
3329
3331 This mode allows you to toggle the prompt behavior between normal
3330 This mode allows you to toggle the prompt behavior between normal
3332 IPython prompts and ones that are as similar to the default IPython
3331 IPython prompts and ones that are as similar to the default IPython
3333 interpreter as possible.
3332 interpreter as possible.
3334
3333
3335 It also supports the pasting of code snippets that have leading '>>>'
3334 It also supports the pasting of code snippets that have leading '>>>'
3336 and '...' prompts in them. This means that you can paste doctests from
3335 and '...' prompts in them. This means that you can paste doctests from
3337 files or docstrings (even if they have leading whitespace), and the
3336 files or docstrings (even if they have leading whitespace), and the
3338 code will execute correctly. You can then use '%history -tn' to see
3337 code will execute correctly. You can then use '%history -tn' to see
3339 the translated history without line numbers; this will give you the
3338 the translated history without line numbers; this will give you the
3340 input after removal of all the leading prompts and whitespace, which
3339 input after removal of all the leading prompts and whitespace, which
3341 can be pasted back into an editor.
3340 can be pasted back into an editor.
3342
3341
3343 With these features, you can switch into this mode easily whenever you
3342 With these features, you can switch into this mode easily whenever you
3344 need to do testing and changes to doctests, without having to leave
3343 need to do testing and changes to doctests, without having to leave
3345 your existing IPython session.
3344 your existing IPython session.
3346 """
3345 """
3347
3346
3348 # XXX - Fix this to have cleaner activate/deactivate calls.
3347 # XXX - Fix this to have cleaner activate/deactivate calls.
3349 from IPython.Extensions import InterpreterPasteInput as ipaste
3348 from IPython.Extensions import InterpreterPasteInput as ipaste
3350 from IPython.ipstruct import Struct
3349 from IPython.ipstruct import Struct
3351
3350
3352 # Shorthands
3351 # Shorthands
3353 shell = self.shell
3352 shell = self.shell
3354 oc = shell.outputcache
3353 oc = shell.outputcache
3355 rc = shell.rc
3354 rc = shell.rc
3356 meta = shell.meta
3355 meta = shell.meta
3357 # dstore is a data store kept in the instance metadata bag to track any
3356 # dstore is a data store kept in the instance metadata bag to track any
3358 # changes we make, so we can undo them later.
3357 # changes we make, so we can undo them later.
3359 dstore = meta.setdefault('doctest_mode',Struct())
3358 dstore = meta.setdefault('doctest_mode',Struct())
3360 save_dstore = dstore.setdefault
3359 save_dstore = dstore.setdefault
3361
3360
3362 # save a few values we'll need to recover later
3361 # save a few values we'll need to recover later
3363 mode = save_dstore('mode',False)
3362 mode = save_dstore('mode',False)
3364 save_dstore('rc_pprint',rc.pprint)
3363 save_dstore('rc_pprint',rc.pprint)
3365 save_dstore('xmode',shell.InteractiveTB.mode)
3364 save_dstore('xmode',shell.InteractiveTB.mode)
3366 save_dstore('rc_separate_out',rc.separate_out)
3365 save_dstore('rc_separate_out',rc.separate_out)
3367 save_dstore('rc_separate_out2',rc.separate_out2)
3366 save_dstore('rc_separate_out2',rc.separate_out2)
3368 save_dstore('rc_prompts_pad_left',rc.prompts_pad_left)
3367 save_dstore('rc_prompts_pad_left',rc.prompts_pad_left)
3369 save_dstore('rc_separate_in',rc.separate_in)
3368 save_dstore('rc_separate_in',rc.separate_in)
3370
3369
3371 if mode == False:
3370 if mode == False:
3372 # turn on
3371 # turn on
3373 ipaste.activate_prefilter()
3372 ipaste.activate_prefilter()
3374
3373
3375 oc.prompt1.p_template = '>>> '
3374 oc.prompt1.p_template = '>>> '
3376 oc.prompt2.p_template = '... '
3375 oc.prompt2.p_template = '... '
3377 oc.prompt_out.p_template = ''
3376 oc.prompt_out.p_template = ''
3378
3377
3379 # Prompt separators like plain python
3378 # Prompt separators like plain python
3380 oc.input_sep = oc.prompt1.sep = ''
3379 oc.input_sep = oc.prompt1.sep = ''
3381 oc.output_sep = ''
3380 oc.output_sep = ''
3382 oc.output_sep2 = ''
3381 oc.output_sep2 = ''
3383
3382
3384 oc.prompt1.pad_left = oc.prompt2.pad_left = \
3383 oc.prompt1.pad_left = oc.prompt2.pad_left = \
3385 oc.prompt_out.pad_left = False
3384 oc.prompt_out.pad_left = False
3386
3385
3387 rc.pprint = False
3386 rc.pprint = False
3388
3387
3389 shell.magic_xmode('Plain')
3388 shell.magic_xmode('Plain')
3390
3389
3391 else:
3390 else:
3392 # turn off
3391 # turn off
3393 ipaste.deactivate_prefilter()
3392 ipaste.deactivate_prefilter()
3394
3393
3395 oc.prompt1.p_template = rc.prompt_in1
3394 oc.prompt1.p_template = rc.prompt_in1
3396 oc.prompt2.p_template = rc.prompt_in2
3395 oc.prompt2.p_template = rc.prompt_in2
3397 oc.prompt_out.p_template = rc.prompt_out
3396 oc.prompt_out.p_template = rc.prompt_out
3398
3397
3399 oc.input_sep = oc.prompt1.sep = dstore.rc_separate_in
3398 oc.input_sep = oc.prompt1.sep = dstore.rc_separate_in
3400
3399
3401 oc.output_sep = dstore.rc_separate_out
3400 oc.output_sep = dstore.rc_separate_out
3402 oc.output_sep2 = dstore.rc_separate_out2
3401 oc.output_sep2 = dstore.rc_separate_out2
3403
3402
3404 oc.prompt1.pad_left = oc.prompt2.pad_left = \
3403 oc.prompt1.pad_left = oc.prompt2.pad_left = \
3405 oc.prompt_out.pad_left = dstore.rc_prompts_pad_left
3404 oc.prompt_out.pad_left = dstore.rc_prompts_pad_left
3406
3405
3407 rc.pprint = dstore.rc_pprint
3406 rc.pprint = dstore.rc_pprint
3408
3407
3409 shell.magic_xmode(dstore.xmode)
3408 shell.magic_xmode(dstore.xmode)
3410
3409
3411 # Store new mode and inform
3410 # Store new mode and inform
3412 dstore.mode = bool(1-int(mode))
3411 dstore.mode = bool(1-int(mode))
3413 print 'Doctest mode is:',
3412 print 'Doctest mode is:',
3414 print ['OFF','ON'][dstore.mode]
3413 print ['OFF','ON'][dstore.mode]
3415
3414
3416 # end Magic
3415 # end Magic
@@ -1,613 +1,607 b''
1 # -*- coding: utf-8 -*-
1 # -*- coding: utf-8 -*-
2 """Tools for inspecting Python objects.
2 """Tools for inspecting Python objects.
3
3
4 Uses syntax highlighting for presenting the various information elements.
4 Uses syntax highlighting for presenting the various information elements.
5
5
6 Similar in spirit to the inspect module, but all calls take a name argument to
6 Similar in spirit to the inspect module, but all calls take a name argument to
7 reference the name under which an object is being read.
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 # Copyright (C) 2001-2004 Fernando Perez <fperez@colorado.edu>
11 # Copyright (C) 2001-2004 Fernando Perez <fperez@colorado.edu>
14 #
12 #
15 # Distributed under the terms of the BSD License. The full license is in
13 # Distributed under the terms of the BSD License. The full license is in
16 # the file COPYING, distributed as part of this software.
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 __all__ = ['Inspector','InspectColors']
17 __all__ = ['Inspector','InspectColors']
24
18
25 # stdlib modules
19 # stdlib modules
26 import __builtin__
20 import __builtin__
27 import StringIO
21 import StringIO
28 import inspect
22 import inspect
29 import linecache
23 import linecache
30 import os
24 import os
31 import string
25 import string
32 import sys
26 import sys
33 import types
27 import types
34
28
35 # IPython's own
29 # IPython's own
36 from IPython import PyColorize
30 from IPython import PyColorize
37 from IPython.genutils import page,indent,Term
31 from IPython.genutils import page,indent,Term
38 from IPython.Itpl import itpl
32 from IPython.Itpl import itpl
39 from IPython.wildcard import list_namespace
33 from IPython.wildcard import list_namespace
40 from IPython.ColorANSI import *
34 from IPython.ColorANSI import *
41
35
42 #****************************************************************************
36 #****************************************************************************
43 # HACK!!! This is a crude fix for bugs in python 2.3's inspect module. We
37 # HACK!!! This is a crude fix for bugs in python 2.3's inspect module. We
44 # simply monkeypatch inspect with code copied from python 2.4.
38 # simply monkeypatch inspect with code copied from python 2.4.
45 if sys.version_info[:2] == (2,3):
39 if sys.version_info[:2] == (2,3):
46 from inspect import ismodule, getabsfile, modulesbyfile
40 from inspect import ismodule, getabsfile, modulesbyfile
47 def getmodule(object):
41 def getmodule(object):
48 """Return the module an object was defined in, or None if not found."""
42 """Return the module an object was defined in, or None if not found."""
49 if ismodule(object):
43 if ismodule(object):
50 return object
44 return object
51 if hasattr(object, '__module__'):
45 if hasattr(object, '__module__'):
52 return sys.modules.get(object.__module__)
46 return sys.modules.get(object.__module__)
53 try:
47 try:
54 file = getabsfile(object)
48 file = getabsfile(object)
55 except TypeError:
49 except TypeError:
56 return None
50 return None
57 if file in modulesbyfile:
51 if file in modulesbyfile:
58 return sys.modules.get(modulesbyfile[file])
52 return sys.modules.get(modulesbyfile[file])
59 for module in sys.modules.values():
53 for module in sys.modules.values():
60 if hasattr(module, '__file__'):
54 if hasattr(module, '__file__'):
61 modulesbyfile[
55 modulesbyfile[
62 os.path.realpath(
56 os.path.realpath(
63 getabsfile(module))] = module.__name__
57 getabsfile(module))] = module.__name__
64 if file in modulesbyfile:
58 if file in modulesbyfile:
65 return sys.modules.get(modulesbyfile[file])
59 return sys.modules.get(modulesbyfile[file])
66 main = sys.modules['__main__']
60 main = sys.modules['__main__']
67 if not hasattr(object, '__name__'):
61 if not hasattr(object, '__name__'):
68 return None
62 return None
69 if hasattr(main, object.__name__):
63 if hasattr(main, object.__name__):
70 mainobject = getattr(main, object.__name__)
64 mainobject = getattr(main, object.__name__)
71 if mainobject is object:
65 if mainobject is object:
72 return main
66 return main
73 builtin = sys.modules['__builtin__']
67 builtin = sys.modules['__builtin__']
74 if hasattr(builtin, object.__name__):
68 if hasattr(builtin, object.__name__):
75 builtinobject = getattr(builtin, object.__name__)
69 builtinobject = getattr(builtin, object.__name__)
76 if builtinobject is object:
70 if builtinobject is object:
77 return builtin
71 return builtin
78
72
79 inspect.getmodule = getmodule
73 inspect.getmodule = getmodule
80
74
81 #****************************************************************************
75 #****************************************************************************
82 # Builtin color schemes
76 # Builtin color schemes
83
77
84 Colors = TermColors # just a shorthand
78 Colors = TermColors # just a shorthand
85
79
86 # Build a few color schemes
80 # Build a few color schemes
87 NoColor = ColorScheme(
81 NoColor = ColorScheme(
88 'NoColor',{
82 'NoColor',{
89 'header' : Colors.NoColor,
83 'header' : Colors.NoColor,
90 'normal' : Colors.NoColor # color off (usu. Colors.Normal)
84 'normal' : Colors.NoColor # color off (usu. Colors.Normal)
91 } )
85 } )
92
86
93 LinuxColors = ColorScheme(
87 LinuxColors = ColorScheme(
94 'Linux',{
88 'Linux',{
95 'header' : Colors.LightRed,
89 'header' : Colors.LightRed,
96 'normal' : Colors.Normal # color off (usu. Colors.Normal)
90 'normal' : Colors.Normal # color off (usu. Colors.Normal)
97 } )
91 } )
98
92
99 LightBGColors = ColorScheme(
93 LightBGColors = ColorScheme(
100 'LightBG',{
94 'LightBG',{
101 'header' : Colors.Red,
95 'header' : Colors.Red,
102 'normal' : Colors.Normal # color off (usu. Colors.Normal)
96 'normal' : Colors.Normal # color off (usu. Colors.Normal)
103 } )
97 } )
104
98
105 # Build table of color schemes (needed by the parser)
99 # Build table of color schemes (needed by the parser)
106 InspectColors = ColorSchemeTable([NoColor,LinuxColors,LightBGColors],
100 InspectColors = ColorSchemeTable([NoColor,LinuxColors,LightBGColors],
107 'Linux')
101 'Linux')
108
102
109 #****************************************************************************
103 #****************************************************************************
110 # Auxiliary functions
104 # Auxiliary functions
111 def getdoc(obj):
105 def getdoc(obj):
112 """Stable wrapper around inspect.getdoc.
106 """Stable wrapper around inspect.getdoc.
113
107
114 This can't crash because of attribute problems.
108 This can't crash because of attribute problems.
115
109
116 It also attempts to call a getdoc() method on the given object. This
110 It also attempts to call a getdoc() method on the given object. This
117 allows objects which provide their docstrings via non-standard mechanisms
111 allows objects which provide their docstrings via non-standard mechanisms
118 (like Pyro proxies) to still be inspected by ipython's ? system."""
112 (like Pyro proxies) to still be inspected by ipython's ? system."""
119
113
120 ds = None # default return value
114 ds = None # default return value
121 try:
115 try:
122 ds = inspect.getdoc(obj)
116 ds = inspect.getdoc(obj)
123 except:
117 except:
124 # Harden against an inspect failure, which can occur with
118 # Harden against an inspect failure, which can occur with
125 # SWIG-wrapped extensions.
119 # SWIG-wrapped extensions.
126 pass
120 pass
127 # Allow objects to offer customized documentation via a getdoc method:
121 # Allow objects to offer customized documentation via a getdoc method:
128 try:
122 try:
129 ds2 = obj.getdoc()
123 ds2 = obj.getdoc()
130 except:
124 except:
131 pass
125 pass
132 else:
126 else:
133 # if we get extra info, we add it to the normal docstring.
127 # if we get extra info, we add it to the normal docstring.
134 if ds is None:
128 if ds is None:
135 ds = ds2
129 ds = ds2
136 else:
130 else:
137 ds = '%s\n%s' % (ds,ds2)
131 ds = '%s\n%s' % (ds,ds2)
138 return ds
132 return ds
139
133
140
134
141 def getsource(obj,is_binary=False):
135 def getsource(obj,is_binary=False):
142 """Wrapper around inspect.getsource.
136 """Wrapper around inspect.getsource.
143
137
144 This can be modified by other projects to provide customized source
138 This can be modified by other projects to provide customized source
145 extraction.
139 extraction.
146
140
147 Inputs:
141 Inputs:
148
142
149 - obj: an object whose source code we will attempt to extract.
143 - obj: an object whose source code we will attempt to extract.
150
144
151 Optional inputs:
145 Optional inputs:
152
146
153 - is_binary: whether the object is known to come from a binary source.
147 - is_binary: whether the object is known to come from a binary source.
154 This implementation will skip returning any output for binary objects, but
148 This implementation will skip returning any output for binary objects, but
155 custom extractors may know how to meaningfully process them."""
149 custom extractors may know how to meaningfully process them."""
156
150
157 if is_binary:
151 if is_binary:
158 return None
152 return None
159 else:
153 else:
160 try:
154 try:
161 src = inspect.getsource(obj)
155 src = inspect.getsource(obj)
162 except TypeError:
156 except TypeError:
163 if hasattr(obj,'__class__'):
157 if hasattr(obj,'__class__'):
164 src = inspect.getsource(obj.__class__)
158 src = inspect.getsource(obj.__class__)
165 return src
159 return src
166
160
167 def getargspec(obj):
161 def getargspec(obj):
168 """Get the names and default values of a function's arguments.
162 """Get the names and default values of a function's arguments.
169
163
170 A tuple of four things is returned: (args, varargs, varkw, defaults).
164 A tuple of four things is returned: (args, varargs, varkw, defaults).
171 'args' is a list of the argument names (it may contain nested lists).
165 'args' is a list of the argument names (it may contain nested lists).
172 'varargs' and 'varkw' are the names of the * and ** arguments or None.
166 'varargs' and 'varkw' are the names of the * and ** arguments or None.
173 'defaults' is an n-tuple of the default values of the last n arguments.
167 'defaults' is an n-tuple of the default values of the last n arguments.
174
168
175 Modified version of inspect.getargspec from the Python Standard
169 Modified version of inspect.getargspec from the Python Standard
176 Library."""
170 Library."""
177
171
178 if inspect.isfunction(obj):
172 if inspect.isfunction(obj):
179 func_obj = obj
173 func_obj = obj
180 elif inspect.ismethod(obj):
174 elif inspect.ismethod(obj):
181 func_obj = obj.im_func
175 func_obj = obj.im_func
182 else:
176 else:
183 raise TypeError, 'arg is not a Python function'
177 raise TypeError, 'arg is not a Python function'
184 args, varargs, varkw = inspect.getargs(func_obj.func_code)
178 args, varargs, varkw = inspect.getargs(func_obj.func_code)
185 return args, varargs, varkw, func_obj.func_defaults
179 return args, varargs, varkw, func_obj.func_defaults
186
180
187 #****************************************************************************
181 #****************************************************************************
188 # Class definitions
182 # Class definitions
189
183
190 class myStringIO(StringIO.StringIO):
184 class myStringIO(StringIO.StringIO):
191 """Adds a writeln method to normal StringIO."""
185 """Adds a writeln method to normal StringIO."""
192 def writeln(self,*arg,**kw):
186 def writeln(self,*arg,**kw):
193 """Does a write() and then a write('\n')"""
187 """Does a write() and then a write('\n')"""
194 self.write(*arg,**kw)
188 self.write(*arg,**kw)
195 self.write('\n')
189 self.write('\n')
196
190
197
191
198 class Inspector:
192 class Inspector:
199 def __init__(self,color_table,code_color_table,scheme,
193 def __init__(self,color_table,code_color_table,scheme,
200 str_detail_level=0):
194 str_detail_level=0):
201 self.color_table = color_table
195 self.color_table = color_table
202 self.parser = PyColorize.Parser(code_color_table,out='str')
196 self.parser = PyColorize.Parser(code_color_table,out='str')
203 self.format = self.parser.format
197 self.format = self.parser.format
204 self.str_detail_level = str_detail_level
198 self.str_detail_level = str_detail_level
205 self.set_active_scheme(scheme)
199 self.set_active_scheme(scheme)
206
200
207 def __getdef(self,obj,oname=''):
201 def __getdef(self,obj,oname=''):
208 """Return the definition header for any callable object.
202 """Return the definition header for any callable object.
209
203
210 If any exception is generated, None is returned instead and the
204 If any exception is generated, None is returned instead and the
211 exception is suppressed."""
205 exception is suppressed."""
212
206
213 try:
207 try:
214 return oname + inspect.formatargspec(*getargspec(obj))
208 return oname + inspect.formatargspec(*getargspec(obj))
215 except:
209 except:
216 return None
210 return None
217
211
218 def __head(self,h):
212 def __head(self,h):
219 """Return a header string with proper colors."""
213 """Return a header string with proper colors."""
220 return '%s%s%s' % (self.color_table.active_colors.header,h,
214 return '%s%s%s' % (self.color_table.active_colors.header,h,
221 self.color_table.active_colors.normal)
215 self.color_table.active_colors.normal)
222
216
223 def set_active_scheme(self,scheme):
217 def set_active_scheme(self,scheme):
224 self.color_table.set_active_scheme(scheme)
218 self.color_table.set_active_scheme(scheme)
225 self.parser.color_table.set_active_scheme(scheme)
219 self.parser.color_table.set_active_scheme(scheme)
226
220
227 def noinfo(self,msg,oname):
221 def noinfo(self,msg,oname):
228 """Generic message when no information is found."""
222 """Generic message when no information is found."""
229 print 'No %s found' % msg,
223 print 'No %s found' % msg,
230 if oname:
224 if oname:
231 print 'for %s' % oname
225 print 'for %s' % oname
232 else:
226 else:
233 print
227 print
234
228
235 def pdef(self,obj,oname=''):
229 def pdef(self,obj,oname=''):
236 """Print the definition header for any callable object.
230 """Print the definition header for any callable object.
237
231
238 If the object is a class, print the constructor information."""
232 If the object is a class, print the constructor information."""
239
233
240 if not callable(obj):
234 if not callable(obj):
241 print 'Object is not callable.'
235 print 'Object is not callable.'
242 return
236 return
243
237
244 header = ''
238 header = ''
245
239
246 if inspect.isclass(obj):
240 if inspect.isclass(obj):
247 header = self.__head('Class constructor information:\n')
241 header = self.__head('Class constructor information:\n')
248 obj = obj.__init__
242 obj = obj.__init__
249 elif type(obj) is types.InstanceType:
243 elif type(obj) is types.InstanceType:
250 obj = obj.__call__
244 obj = obj.__call__
251
245
252 output = self.__getdef(obj,oname)
246 output = self.__getdef(obj,oname)
253 if output is None:
247 if output is None:
254 self.noinfo('definition header',oname)
248 self.noinfo('definition header',oname)
255 else:
249 else:
256 print >>Term.cout, header,self.format(output),
250 print >>Term.cout, header,self.format(output),
257
251
258 def pdoc(self,obj,oname='',formatter = None):
252 def pdoc(self,obj,oname='',formatter = None):
259 """Print the docstring for any object.
253 """Print the docstring for any object.
260
254
261 Optional:
255 Optional:
262 -formatter: a function to run the docstring through for specially
256 -formatter: a function to run the docstring through for specially
263 formatted docstrings."""
257 formatted docstrings."""
264
258
265 head = self.__head # so that itpl can find it even if private
259 head = self.__head # so that itpl can find it even if private
266 ds = getdoc(obj)
260 ds = getdoc(obj)
267 if formatter:
261 if formatter:
268 ds = formatter(ds)
262 ds = formatter(ds)
269 if inspect.isclass(obj):
263 if inspect.isclass(obj):
270 init_ds = getdoc(obj.__init__)
264 init_ds = getdoc(obj.__init__)
271 output = itpl('$head("Class Docstring:")\n'
265 output = itpl('$head("Class Docstring:")\n'
272 '$indent(ds)\n'
266 '$indent(ds)\n'
273 '$head("Constructor Docstring"):\n'
267 '$head("Constructor Docstring"):\n'
274 '$indent(init_ds)')
268 '$indent(init_ds)')
275 elif (type(obj) is types.InstanceType or isinstance(obj,object)) \
269 elif (type(obj) is types.InstanceType or isinstance(obj,object)) \
276 and hasattr(obj,'__call__'):
270 and hasattr(obj,'__call__'):
277 call_ds = getdoc(obj.__call__)
271 call_ds = getdoc(obj.__call__)
278 if call_ds:
272 if call_ds:
279 output = itpl('$head("Class Docstring:")\n$indent(ds)\n'
273 output = itpl('$head("Class Docstring:")\n$indent(ds)\n'
280 '$head("Calling Docstring:")\n$indent(call_ds)')
274 '$head("Calling Docstring:")\n$indent(call_ds)')
281 else:
275 else:
282 output = ds
276 output = ds
283 else:
277 else:
284 output = ds
278 output = ds
285 if output is None:
279 if output is None:
286 self.noinfo('documentation',oname)
280 self.noinfo('documentation',oname)
287 return
281 return
288 page(output)
282 page(output)
289
283
290 def psource(self,obj,oname=''):
284 def psource(self,obj,oname=''):
291 """Print the source code for an object."""
285 """Print the source code for an object."""
292
286
293 # Flush the source cache because inspect can return out-of-date source
287 # Flush the source cache because inspect can return out-of-date source
294 linecache.checkcache()
288 linecache.checkcache()
295 try:
289 try:
296 src = getsource(obj)
290 src = getsource(obj)
297 except:
291 except:
298 self.noinfo('source',oname)
292 self.noinfo('source',oname)
299 else:
293 else:
300 page(self.format(src))
294 page(self.format(src))
301
295
302 def pfile(self,obj,oname=''):
296 def pfile(self,obj,oname=''):
303 """Show the whole file where an object was defined."""
297 """Show the whole file where an object was defined."""
304
298
305 try:
299 try:
306 try:
300 try:
307 lineno = inspect.getsourcelines(obj)[1]
301 lineno = inspect.getsourcelines(obj)[1]
308 except TypeError:
302 except TypeError:
309 # For instances, try the class object like getsource() does
303 # For instances, try the class object like getsource() does
310 if hasattr(obj,'__class__'):
304 if hasattr(obj,'__class__'):
311 lineno = inspect.getsourcelines(obj.__class__)[1]
305 lineno = inspect.getsourcelines(obj.__class__)[1]
312 # Adjust the inspected object so getabsfile() below works
306 # Adjust the inspected object so getabsfile() below works
313 obj = obj.__class__
307 obj = obj.__class__
314 except:
308 except:
315 self.noinfo('file',oname)
309 self.noinfo('file',oname)
316 return
310 return
317
311
318 # We only reach this point if object was successfully queried
312 # We only reach this point if object was successfully queried
319
313
320 # run contents of file through pager starting at line
314 # run contents of file through pager starting at line
321 # where the object is defined
315 # where the object is defined
322 ofile = inspect.getabsfile(obj)
316 ofile = inspect.getabsfile(obj)
323
317
324 if (ofile.endswith('.so') or ofile.endswith('.dll')):
318 if (ofile.endswith('.so') or ofile.endswith('.dll')):
325 print 'File %r is binary, not printing.' % ofile
319 print 'File %r is binary, not printing.' % ofile
326 elif not os.path.isfile(ofile):
320 elif not os.path.isfile(ofile):
327 print 'File %r does not exist, not printing.' % ofile
321 print 'File %r does not exist, not printing.' % ofile
328 else:
322 else:
329 # Print only text files, not extension binaries. Note that
323 # Print only text files, not extension binaries. Note that
330 # getsourcelines returns lineno with 1-offset and page() uses
324 # getsourcelines returns lineno with 1-offset and page() uses
331 # 0-offset, so we must adjust.
325 # 0-offset, so we must adjust.
332 page(self.format(open(ofile).read()),lineno-1)
326 page(self.format(open(ofile).read()),lineno-1)
333
327
334 def pinfo(self,obj,oname='',formatter=None,info=None,detail_level=0):
328 def pinfo(self,obj,oname='',formatter=None,info=None,detail_level=0):
335 """Show detailed information about an object.
329 """Show detailed information about an object.
336
330
337 Optional arguments:
331 Optional arguments:
338
332
339 - oname: name of the variable pointing to the object.
333 - oname: name of the variable pointing to the object.
340
334
341 - formatter: special formatter for docstrings (see pdoc)
335 - formatter: special formatter for docstrings (see pdoc)
342
336
343 - info: a structure with some information fields which may have been
337 - info: a structure with some information fields which may have been
344 precomputed already.
338 precomputed already.
345
339
346 - detail_level: if set to 1, more information is given.
340 - detail_level: if set to 1, more information is given.
347 """
341 """
348
342
349 obj_type = type(obj)
343 obj_type = type(obj)
350
344
351 header = self.__head
345 header = self.__head
352 if info is None:
346 if info is None:
353 ismagic = 0
347 ismagic = 0
354 isalias = 0
348 isalias = 0
355 ospace = ''
349 ospace = ''
356 else:
350 else:
357 ismagic = info.ismagic
351 ismagic = info.ismagic
358 isalias = info.isalias
352 isalias = info.isalias
359 ospace = info.namespace
353 ospace = info.namespace
360 # Get docstring, special-casing aliases:
354 # Get docstring, special-casing aliases:
361 if isalias:
355 if isalias:
362 if not callable(obj):
356 if not callable(obj):
363 try:
357 try:
364 ds = "Alias to the system command:\n %s" % obj[1]
358 ds = "Alias to the system command:\n %s" % obj[1]
365 except:
359 except:
366 ds = "Alias: " + str(obj)
360 ds = "Alias: " + str(obj)
367 else:
361 else:
368 ds = "Alias to " + str(obj)
362 ds = "Alias to " + str(obj)
369 if obj.__doc__:
363 if obj.__doc__:
370 ds += "\nDocstring:\n" + obj.__doc__
364 ds += "\nDocstring:\n" + obj.__doc__
371 else:
365 else:
372 ds = getdoc(obj)
366 ds = getdoc(obj)
373 if ds is None:
367 if ds is None:
374 ds = '<no docstring>'
368 ds = '<no docstring>'
375 if formatter is not None:
369 if formatter is not None:
376 ds = formatter(ds)
370 ds = formatter(ds)
377
371
378 # store output in a list which gets joined with \n at the end.
372 # store output in a list which gets joined with \n at the end.
379 out = myStringIO()
373 out = myStringIO()
380
374
381 string_max = 200 # max size of strings to show (snipped if longer)
375 string_max = 200 # max size of strings to show (snipped if longer)
382 shalf = int((string_max -5)/2)
376 shalf = int((string_max -5)/2)
383
377
384 if ismagic:
378 if ismagic:
385 obj_type_name = 'Magic function'
379 obj_type_name = 'Magic function'
386 elif isalias:
380 elif isalias:
387 obj_type_name = 'System alias'
381 obj_type_name = 'System alias'
388 else:
382 else:
389 obj_type_name = obj_type.__name__
383 obj_type_name = obj_type.__name__
390 out.writeln(header('Type:\t\t')+obj_type_name)
384 out.writeln(header('Type:\t\t')+obj_type_name)
391
385
392 try:
386 try:
393 bclass = obj.__class__
387 bclass = obj.__class__
394 out.writeln(header('Base Class:\t')+str(bclass))
388 out.writeln(header('Base Class:\t')+str(bclass))
395 except: pass
389 except: pass
396
390
397 # String form, but snip if too long in ? form (full in ??)
391 # String form, but snip if too long in ? form (full in ??)
398 if detail_level >= self.str_detail_level:
392 if detail_level >= self.str_detail_level:
399 try:
393 try:
400 ostr = str(obj)
394 ostr = str(obj)
401 str_head = 'String Form:'
395 str_head = 'String Form:'
402 if not detail_level and len(ostr)>string_max:
396 if not detail_level and len(ostr)>string_max:
403 ostr = ostr[:shalf] + ' <...> ' + ostr[-shalf:]
397 ostr = ostr[:shalf] + ' <...> ' + ostr[-shalf:]
404 ostr = ("\n" + " " * len(str_head.expandtabs())).\
398 ostr = ("\n" + " " * len(str_head.expandtabs())).\
405 join(map(string.strip,ostr.split("\n")))
399 join(map(string.strip,ostr.split("\n")))
406 if ostr.find('\n') > -1:
400 if ostr.find('\n') > -1:
407 # Print multi-line strings starting at the next line.
401 # Print multi-line strings starting at the next line.
408 str_sep = '\n'
402 str_sep = '\n'
409 else:
403 else:
410 str_sep = '\t'
404 str_sep = '\t'
411 out.writeln("%s%s%s" % (header(str_head),str_sep,ostr))
405 out.writeln("%s%s%s" % (header(str_head),str_sep,ostr))
412 except:
406 except:
413 pass
407 pass
414
408
415 if ospace:
409 if ospace:
416 out.writeln(header('Namespace:\t')+ospace)
410 out.writeln(header('Namespace:\t')+ospace)
417
411
418 # Length (for strings and lists)
412 # Length (for strings and lists)
419 try:
413 try:
420 length = str(len(obj))
414 length = str(len(obj))
421 out.writeln(header('Length:\t\t')+length)
415 out.writeln(header('Length:\t\t')+length)
422 except: pass
416 except: pass
423
417
424 # Filename where object was defined
418 # Filename where object was defined
425 binary_file = False
419 binary_file = False
426 try:
420 try:
427 try:
421 try:
428 fname = inspect.getabsfile(obj)
422 fname = inspect.getabsfile(obj)
429 except TypeError:
423 except TypeError:
430 # For an instance, the file that matters is where its class was
424 # For an instance, the file that matters is where its class was
431 # declared.
425 # declared.
432 if hasattr(obj,'__class__'):
426 if hasattr(obj,'__class__'):
433 fname = inspect.getabsfile(obj.__class__)
427 fname = inspect.getabsfile(obj.__class__)
434 if fname.endswith('<string>'):
428 if fname.endswith('<string>'):
435 fname = 'Dynamically generated function. No source code available.'
429 fname = 'Dynamically generated function. No source code available.'
436 if (fname.endswith('.so') or fname.endswith('.dll')):
430 if (fname.endswith('.so') or fname.endswith('.dll')):
437 binary_file = True
431 binary_file = True
438 out.writeln(header('File:\t\t')+fname)
432 out.writeln(header('File:\t\t')+fname)
439 except:
433 except:
440 # if anything goes wrong, we don't want to show source, so it's as
434 # if anything goes wrong, we don't want to show source, so it's as
441 # if the file was binary
435 # if the file was binary
442 binary_file = True
436 binary_file = True
443
437
444 # reconstruct the function definition and print it:
438 # reconstruct the function definition and print it:
445 defln = self.__getdef(obj,oname)
439 defln = self.__getdef(obj,oname)
446 if defln:
440 if defln:
447 out.write(header('Definition:\t')+self.format(defln))
441 out.write(header('Definition:\t')+self.format(defln))
448
442
449 # Docstrings only in detail 0 mode, since source contains them (we
443 # Docstrings only in detail 0 mode, since source contains them (we
450 # avoid repetitions). If source fails, we add them back, see below.
444 # avoid repetitions). If source fails, we add them back, see below.
451 if ds and detail_level == 0:
445 if ds and detail_level == 0:
452 out.writeln(header('Docstring:\n') + indent(ds))
446 out.writeln(header('Docstring:\n') + indent(ds))
453
447
454 # Original source code for any callable
448 # Original source code for any callable
455 if detail_level:
449 if detail_level:
456 # Flush the source cache because inspect can return out-of-date
450 # Flush the source cache because inspect can return out-of-date
457 # source
451 # source
458 linecache.checkcache()
452 linecache.checkcache()
459 source_success = False
453 source_success = False
460 try:
454 try:
461 try:
455 try:
462 src = getsource(obj,binary_file)
456 src = getsource(obj,binary_file)
463 except TypeError:
457 except TypeError:
464 if hasattr(obj,'__class__'):
458 if hasattr(obj,'__class__'):
465 src = getsource(obj.__class__,binary_file)
459 src = getsource(obj.__class__,binary_file)
466 if src is not None:
460 if src is not None:
467 source = self.format(src)
461 source = self.format(src)
468 out.write(header('Source:\n')+source.rstrip())
462 out.write(header('Source:\n')+source.rstrip())
469 source_success = True
463 source_success = True
470 except Exception, msg:
464 except Exception, msg:
471 pass
465 pass
472
466
473 if ds and not source_success:
467 if ds and not source_success:
474 out.writeln(header('Docstring [source file open failed]:\n')
468 out.writeln(header('Docstring [source file open failed]:\n')
475 + indent(ds))
469 + indent(ds))
476
470
477 # Constructor docstring for classes
471 # Constructor docstring for classes
478 if inspect.isclass(obj):
472 if inspect.isclass(obj):
479 # reconstruct the function definition and print it:
473 # reconstruct the function definition and print it:
480 try:
474 try:
481 obj_init = obj.__init__
475 obj_init = obj.__init__
482 except AttributeError:
476 except AttributeError:
483 init_def = init_ds = None
477 init_def = init_ds = None
484 else:
478 else:
485 init_def = self.__getdef(obj_init,oname)
479 init_def = self.__getdef(obj_init,oname)
486 init_ds = getdoc(obj_init)
480 init_ds = getdoc(obj_init)
487 # Skip Python's auto-generated docstrings
481 # Skip Python's auto-generated docstrings
488 if init_ds and \
482 if init_ds and \
489 init_ds.startswith('x.__init__(...) initializes'):
483 init_ds.startswith('x.__init__(...) initializes'):
490 init_ds = None
484 init_ds = None
491
485
492 if init_def or init_ds:
486 if init_def or init_ds:
493 out.writeln(header('\nConstructor information:'))
487 out.writeln(header('\nConstructor information:'))
494 if init_def:
488 if init_def:
495 out.write(header('Definition:\t')+ self.format(init_def))
489 out.write(header('Definition:\t')+ self.format(init_def))
496 if init_ds:
490 if init_ds:
497 out.writeln(header('Docstring:\n') + indent(init_ds))
491 out.writeln(header('Docstring:\n') + indent(init_ds))
498 # and class docstring for instances:
492 # and class docstring for instances:
499 elif obj_type is types.InstanceType or \
493 elif obj_type is types.InstanceType or \
500 isinstance(obj,object):
494 isinstance(obj,object):
501
495
502 # First, check whether the instance docstring is identical to the
496 # First, check whether the instance docstring is identical to the
503 # class one, and print it separately if they don't coincide. In
497 # class one, and print it separately if they don't coincide. In
504 # most cases they will, but it's nice to print all the info for
498 # most cases they will, but it's nice to print all the info for
505 # objects which use instance-customized docstrings.
499 # objects which use instance-customized docstrings.
506 if ds:
500 if ds:
507 try:
501 try:
508 cls = getattr(obj,'__class__')
502 cls = getattr(obj,'__class__')
509 except:
503 except:
510 class_ds = None
504 class_ds = None
511 else:
505 else:
512 class_ds = getdoc(cls)
506 class_ds = getdoc(cls)
513 # Skip Python's auto-generated docstrings
507 # Skip Python's auto-generated docstrings
514 if class_ds and \
508 if class_ds and \
515 (class_ds.startswith('function(code, globals[,') or \
509 (class_ds.startswith('function(code, globals[,') or \
516 class_ds.startswith('instancemethod(function, instance,') or \
510 class_ds.startswith('instancemethod(function, instance,') or \
517 class_ds.startswith('module(name[,') ):
511 class_ds.startswith('module(name[,') ):
518 class_ds = None
512 class_ds = None
519 if class_ds and ds != class_ds:
513 if class_ds and ds != class_ds:
520 out.writeln(header('Class Docstring:\n') +
514 out.writeln(header('Class Docstring:\n') +
521 indent(class_ds))
515 indent(class_ds))
522
516
523 # Next, try to show constructor docstrings
517 # Next, try to show constructor docstrings
524 try:
518 try:
525 init_ds = getdoc(obj.__init__)
519 init_ds = getdoc(obj.__init__)
526 # Skip Python's auto-generated docstrings
520 # Skip Python's auto-generated docstrings
527 if init_ds and \
521 if init_ds and \
528 init_ds.startswith('x.__init__(...) initializes'):
522 init_ds.startswith('x.__init__(...) initializes'):
529 init_ds = None
523 init_ds = None
530 except AttributeError:
524 except AttributeError:
531 init_ds = None
525 init_ds = None
532 if init_ds:
526 if init_ds:
533 out.writeln(header('Constructor Docstring:\n') +
527 out.writeln(header('Constructor Docstring:\n') +
534 indent(init_ds))
528 indent(init_ds))
535
529
536 # Call form docstring for callable instances
530 # Call form docstring for callable instances
537 if hasattr(obj,'__call__'):
531 if hasattr(obj,'__call__'):
538 #out.writeln(header('Callable:\t')+'Yes')
532 #out.writeln(header('Callable:\t')+'Yes')
539 call_def = self.__getdef(obj.__call__,oname)
533 call_def = self.__getdef(obj.__call__,oname)
540 #if call_def is None:
534 #if call_def is None:
541 # out.writeln(header('Call def:\t')+
535 # out.writeln(header('Call def:\t')+
542 # 'Calling definition not available.')
536 # 'Calling definition not available.')
543 if call_def is not None:
537 if call_def is not None:
544 out.writeln(header('Call def:\t')+self.format(call_def))
538 out.writeln(header('Call def:\t')+self.format(call_def))
545 call_ds = getdoc(obj.__call__)
539 call_ds = getdoc(obj.__call__)
546 # Skip Python's auto-generated docstrings
540 # Skip Python's auto-generated docstrings
547 if call_ds and call_ds.startswith('x.__call__(...) <==> x(...)'):
541 if call_ds and call_ds.startswith('x.__call__(...) <==> x(...)'):
548 call_ds = None
542 call_ds = None
549 if call_ds:
543 if call_ds:
550 out.writeln(header('Call docstring:\n') + indent(call_ds))
544 out.writeln(header('Call docstring:\n') + indent(call_ds))
551
545
552 # Finally send to printer/pager
546 # Finally send to printer/pager
553 output = out.getvalue()
547 output = out.getvalue()
554 if output:
548 if output:
555 page(output)
549 page(output)
556 # end pinfo
550 # end pinfo
557
551
558 def psearch(self,pattern,ns_table,ns_search=[],
552 def psearch(self,pattern,ns_table,ns_search=[],
559 ignore_case=False,show_all=False):
553 ignore_case=False,show_all=False):
560 """Search namespaces with wildcards for objects.
554 """Search namespaces with wildcards for objects.
561
555
562 Arguments:
556 Arguments:
563
557
564 - pattern: string containing shell-like wildcards to use in namespace
558 - pattern: string containing shell-like wildcards to use in namespace
565 searches and optionally a type specification to narrow the search to
559 searches and optionally a type specification to narrow the search to
566 objects of that type.
560 objects of that type.
567
561
568 - ns_table: dict of name->namespaces for search.
562 - ns_table: dict of name->namespaces for search.
569
563
570 Optional arguments:
564 Optional arguments:
571
565
572 - ns_search: list of namespace names to include in search.
566 - ns_search: list of namespace names to include in search.
573
567
574 - ignore_case(False): make the search case-insensitive.
568 - ignore_case(False): make the search case-insensitive.
575
569
576 - show_all(False): show all names, including those starting with
570 - show_all(False): show all names, including those starting with
577 underscores.
571 underscores.
578 """
572 """
579 #print 'ps pattern:<%r>' % pattern # dbg
573 #print 'ps pattern:<%r>' % pattern # dbg
580
574
581 # defaults
575 # defaults
582 type_pattern = 'all'
576 type_pattern = 'all'
583 filter = ''
577 filter = ''
584
578
585 cmds = pattern.split()
579 cmds = pattern.split()
586 len_cmds = len(cmds)
580 len_cmds = len(cmds)
587 if len_cmds == 1:
581 if len_cmds == 1:
588 # Only filter pattern given
582 # Only filter pattern given
589 filter = cmds[0]
583 filter = cmds[0]
590 elif len_cmds == 2:
584 elif len_cmds == 2:
591 # Both filter and type specified
585 # Both filter and type specified
592 filter,type_pattern = cmds
586 filter,type_pattern = cmds
593 else:
587 else:
594 raise ValueError('invalid argument string for psearch: <%s>' %
588 raise ValueError('invalid argument string for psearch: <%s>' %
595 pattern)
589 pattern)
596
590
597 # filter search namespaces
591 # filter search namespaces
598 for name in ns_search:
592 for name in ns_search:
599 if name not in ns_table:
593 if name not in ns_table:
600 raise ValueError('invalid namespace <%s>. Valid names: %s' %
594 raise ValueError('invalid namespace <%s>. Valid names: %s' %
601 (name,ns_table.keys()))
595 (name,ns_table.keys()))
602
596
603 #print 'type_pattern:',type_pattern # dbg
597 #print 'type_pattern:',type_pattern # dbg
604 search_result = []
598 search_result = []
605 for ns_name in ns_search:
599 for ns_name in ns_search:
606 ns = ns_table[ns_name]
600 ns = ns_table[ns_name]
607 tmp_res = list(list_namespace(ns,type_pattern,filter,
601 tmp_res = list(list_namespace(ns,type_pattern,filter,
608 ignore_case=ignore_case,
602 ignore_case=ignore_case,
609 show_all=show_all))
603 show_all=show_all))
610 search_result.extend(tmp_res)
604 search_result.extend(tmp_res)
611 search_result.sort()
605 search_result.sort()
612
606
613 page('\n'.join(search_result))
607 page('\n'.join(search_result))
@@ -1,263 +1,258 b''
1 # -*- coding: utf-8 -*-
1 # -*- coding: utf-8 -*-
2 """Class to trap stdout and stderr and log them separately.
2 """Class to trap stdout and stderr and log them separately.
3
3 """
4 $Id: OutputTrap.py 958 2005-12-27 23:17:51Z fperez $"""
5
4
6 #*****************************************************************************
5 #*****************************************************************************
7 # Copyright (C) 2001-2004 Fernando Perez <fperez@colorado.edu>
6 # Copyright (C) 2001-2004 Fernando Perez <fperez@colorado.edu>
8 #
7 #
9 # Distributed under the terms of the BSD License. The full license is in
8 # Distributed under the terms of the BSD License. The full license is in
10 # the file COPYING, distributed as part of this software.
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 import exceptions
12 import exceptions
18 import sys
13 import sys
19 from cStringIO import StringIO
14 from cStringIO import StringIO
20
15
21 class OutputTrapError(exceptions.Exception):
16 class OutputTrapError(exceptions.Exception):
22 """Exception for OutputTrap class."""
17 """Exception for OutputTrap class."""
23
18
24 def __init__(self,args=None):
19 def __init__(self,args=None):
25 exceptions.Exception.__init__(self)
20 exceptions.Exception.__init__(self)
26 self.args = args
21 self.args = args
27
22
28 class OutputTrap:
23 class OutputTrap:
29
24
30 """Class to trap standard output and standard error. They get logged in
25 """Class to trap standard output and standard error. They get logged in
31 StringIO objects which are available as <instance>.out and
26 StringIO objects which are available as <instance>.out and
32 <instance>.err. The class also offers summary methods which format this
27 <instance>.err. The class also offers summary methods which format this
33 data a bit.
28 data a bit.
34
29
35 A word of caution: because it blocks messages, using this class can make
30 A word of caution: because it blocks messages, using this class can make
36 debugging very tricky. If you are having bizarre problems silently, try
31 debugging very tricky. If you are having bizarre problems silently, try
37 turning your output traps off for a while. You can call the constructor
32 turning your output traps off for a while. You can call the constructor
38 with the parameter debug=1 for these cases. This turns actual trapping
33 with the parameter debug=1 for these cases. This turns actual trapping
39 off, but you can keep the rest of your code unchanged (this has already
34 off, but you can keep the rest of your code unchanged (this has already
40 been a life saver).
35 been a life saver).
41
36
42 Example:
37 Example:
43
38
44 # config: trapper with a line of dots as log separator (final '\\n' needed)
39 # config: trapper with a line of dots as log separator (final '\\n' needed)
45 config = OutputTrap('Config','Out ','Err ','.'*80+'\\n')
40 config = OutputTrap('Config','Out ','Err ','.'*80+'\\n')
46
41
47 # start trapping output
42 # start trapping output
48 config.trap_all()
43 config.trap_all()
49
44
50 # now all output is logged ...
45 # now all output is logged ...
51 # do stuff...
46 # do stuff...
52
47
53 # output back to normal:
48 # output back to normal:
54 config.release_all()
49 config.release_all()
55
50
56 # print all that got logged:
51 # print all that got logged:
57 print config.summary()
52 print config.summary()
58
53
59 # print individual raw data:
54 # print individual raw data:
60 print config.out.getvalue()
55 print config.out.getvalue()
61 print config.err.getvalue()
56 print config.err.getvalue()
62 """
57 """
63
58
64 def __init__(self,name='Generic Output Trap',
59 def __init__(self,name='Generic Output Trap',
65 out_head='Standard Output. ',err_head='Standard Error. ',
60 out_head='Standard Output. ',err_head='Standard Error. ',
66 sum_sep='\n',debug=0,trap_out=0,trap_err=0,
61 sum_sep='\n',debug=0,trap_out=0,trap_err=0,
67 quiet_out=0,quiet_err=0):
62 quiet_out=0,quiet_err=0):
68 self.name = name
63 self.name = name
69 self.out_head = out_head
64 self.out_head = out_head
70 self.err_head = err_head
65 self.err_head = err_head
71 self.sum_sep = sum_sep
66 self.sum_sep = sum_sep
72 self.out = StringIO()
67 self.out = StringIO()
73 self.err = StringIO()
68 self.err = StringIO()
74 self.out_save = None
69 self.out_save = None
75 self.err_save = None
70 self.err_save = None
76 self.debug = debug
71 self.debug = debug
77 self.quiet_out = quiet_out
72 self.quiet_out = quiet_out
78 self.quiet_err = quiet_err
73 self.quiet_err = quiet_err
79 if trap_out:
74 if trap_out:
80 self.trap_out()
75 self.trap_out()
81 if trap_err:
76 if trap_err:
82 self.trap_err()
77 self.trap_err()
83
78
84 def trap_out(self):
79 def trap_out(self):
85 """Trap and log stdout."""
80 """Trap and log stdout."""
86 if sys.stdout is self.out:
81 if sys.stdout is self.out:
87 raise OutputTrapError,'You are already trapping stdout.'
82 raise OutputTrapError,'You are already trapping stdout.'
88 if not self.debug:
83 if not self.debug:
89 self._out_save = sys.stdout
84 self._out_save = sys.stdout
90 sys.stdout = self.out
85 sys.stdout = self.out
91
86
92 def release_out(self):
87 def release_out(self):
93 """Release stdout."""
88 """Release stdout."""
94 if not self.debug:
89 if not self.debug:
95 if not sys.stdout is self.out:
90 if not sys.stdout is self.out:
96 raise OutputTrapError,'You are not trapping stdout.'
91 raise OutputTrapError,'You are not trapping stdout.'
97 sys.stdout = self._out_save
92 sys.stdout = self._out_save
98 self.out_save = None
93 self.out_save = None
99
94
100 def summary_out(self):
95 def summary_out(self):
101 """Return as a string the log from stdout."""
96 """Return as a string the log from stdout."""
102 out = self.out.getvalue()
97 out = self.out.getvalue()
103 if out:
98 if out:
104 if self.quiet_out:
99 if self.quiet_out:
105 return out
100 return out
106 else:
101 else:
107 return self.out_head + 'Log by '+ self.name + ':\n' + out
102 return self.out_head + 'Log by '+ self.name + ':\n' + out
108 else:
103 else:
109 return ''
104 return ''
110
105
111 def flush_out(self):
106 def flush_out(self):
112 """Flush the stdout log. All data held in the log is lost."""
107 """Flush the stdout log. All data held in the log is lost."""
113
108
114 self.out.close()
109 self.out.close()
115 self.out = StringIO()
110 self.out = StringIO()
116
111
117 def trap_err(self):
112 def trap_err(self):
118 """Trap and log stderr."""
113 """Trap and log stderr."""
119 if sys.stderr is self.err:
114 if sys.stderr is self.err:
120 raise OutputTrapError,'You are already trapping stderr.'
115 raise OutputTrapError,'You are already trapping stderr.'
121 if not self.debug:
116 if not self.debug:
122 self._err_save = sys.stderr
117 self._err_save = sys.stderr
123 sys.stderr = self.err
118 sys.stderr = self.err
124
119
125 def release_err(self):
120 def release_err(self):
126 """Release stderr."""
121 """Release stderr."""
127 if not self.debug:
122 if not self.debug:
128 if not sys.stderr is self.err:
123 if not sys.stderr is self.err:
129 raise OutputTrapError,'You are not trapping stderr.'
124 raise OutputTrapError,'You are not trapping stderr.'
130 sys.stderr = self._err_save
125 sys.stderr = self._err_save
131 self.err_save = None
126 self.err_save = None
132
127
133 def summary_err(self):
128 def summary_err(self):
134 """Return as a string the log from stderr."""
129 """Return as a string the log from stderr."""
135 err = self.err.getvalue()
130 err = self.err.getvalue()
136 if err:
131 if err:
137 if self.quiet_err:
132 if self.quiet_err:
138 return err
133 return err
139 else:
134 else:
140 return self.err_head + 'Log by '+ self.name + ':\n' + err
135 return self.err_head + 'Log by '+ self.name + ':\n' + err
141 else:
136 else:
142 return ''
137 return ''
143
138
144 def flush_err(self):
139 def flush_err(self):
145 """Flush the stdout log. All data held in the log is lost."""
140 """Flush the stdout log. All data held in the log is lost."""
146
141
147 self.err.close()
142 self.err.close()
148 self.err = StringIO()
143 self.err = StringIO()
149
144
150 def trap_all(self):
145 def trap_all(self):
151 """Trap and log both stdout and stderr.
146 """Trap and log both stdout and stderr.
152
147
153 Cacthes and discards OutputTrapError exceptions raised."""
148 Cacthes and discards OutputTrapError exceptions raised."""
154 try:
149 try:
155 self.trap_out()
150 self.trap_out()
156 except OutputTrapError:
151 except OutputTrapError:
157 pass
152 pass
158 try:
153 try:
159 self.trap_err()
154 self.trap_err()
160 except OutputTrapError:
155 except OutputTrapError:
161 pass
156 pass
162
157
163 def release_all(self):
158 def release_all(self):
164 """Release both stdout and stderr.
159 """Release both stdout and stderr.
165
160
166 Cacthes and discards OutputTrapError exceptions raised."""
161 Cacthes and discards OutputTrapError exceptions raised."""
167 try:
162 try:
168 self.release_out()
163 self.release_out()
169 except OutputTrapError:
164 except OutputTrapError:
170 pass
165 pass
171 try:
166 try:
172 self.release_err()
167 self.release_err()
173 except OutputTrapError:
168 except OutputTrapError:
174 pass
169 pass
175
170
176 def summary_all(self):
171 def summary_all(self):
177 """Return as a string the log from stdout and stderr, prepending a separator
172 """Return as a string the log from stdout and stderr, prepending a separator
178 to each (defined in __init__ as sum_sep)."""
173 to each (defined in __init__ as sum_sep)."""
179 sum = ''
174 sum = ''
180 sout = self.summary_out()
175 sout = self.summary_out()
181 if sout:
176 if sout:
182 sum += self.sum_sep + sout
177 sum += self.sum_sep + sout
183 serr = self.summary_err()
178 serr = self.summary_err()
184 if serr:
179 if serr:
185 sum += '\n'+self.sum_sep + serr
180 sum += '\n'+self.sum_sep + serr
186 return sum
181 return sum
187
182
188 def flush_all(self):
183 def flush_all(self):
189 """Flush stdout and stderr"""
184 """Flush stdout and stderr"""
190 self.flush_out()
185 self.flush_out()
191 self.flush_err()
186 self.flush_err()
192
187
193 # a few shorthands
188 # a few shorthands
194 trap = trap_all
189 trap = trap_all
195 release = release_all
190 release = release_all
196 summary = summary_all
191 summary = summary_all
197 flush = flush_all
192 flush = flush_all
198 # end OutputTrap
193 # end OutputTrap
199
194
200
195
201 #****************************************************************************
196 #****************************************************************************
202 # Module testing. Incomplete, I'm lazy...
197 # Module testing. Incomplete, I'm lazy...
203
198
204 def _test_all():
199 def _test_all():
205
200
206 """Module testing functions, activated when the module is called as a
201 """Module testing functions, activated when the module is called as a
207 script (not imported)."""
202 script (not imported)."""
208
203
209 # Put tests for this module in here.
204 # Put tests for this module in here.
210 # Define them as nested functions so they don't clobber the
205 # Define them as nested functions so they don't clobber the
211 # pydoc-generated docs
206 # pydoc-generated docs
212
207
213 def _test_():
208 def _test_():
214 name = ''
209 name = ''
215 print '#'*50+'\nRunning test for ' + name
210 print '#'*50+'\nRunning test for ' + name
216 # ...
211 # ...
217 print 'Finished test for '+ name +'\n'+'#'*50
212 print 'Finished test for '+ name +'\n'+'#'*50
218
213
219 def _test_OutputTrap():
214 def _test_OutputTrap():
220 trap = OutputTrap(name = 'Test Trap', sum_sep = '.'*50+'\n',
215 trap = OutputTrap(name = 'Test Trap', sum_sep = '.'*50+'\n',
221 out_head = 'SOut. ', err_head = 'SErr. ')
216 out_head = 'SOut. ', err_head = 'SErr. ')
222
217
223 name = 'OutputTrap class'
218 name = 'OutputTrap class'
224 print '#'*50+'\nRunning test for ' + name
219 print '#'*50+'\nRunning test for ' + name
225 print 'Trapping out'
220 print 'Trapping out'
226 trap.trap_out()
221 trap.trap_out()
227 print >>sys.stdout, '>>stdout. stdout is trapped.'
222 print >>sys.stdout, '>>stdout. stdout is trapped.'
228 print >>sys.stderr, '>>stderr. stdout is trapped.'
223 print >>sys.stderr, '>>stderr. stdout is trapped.'
229 trap.release_out()
224 trap.release_out()
230 print trap.summary_out()
225 print trap.summary_out()
231
226
232 print 'Trapping err'
227 print 'Trapping err'
233 trap.trap_err()
228 trap.trap_err()
234 print >>sys.stdout, '>>stdout. stderr is trapped.'
229 print >>sys.stdout, '>>stdout. stderr is trapped.'
235 print >>sys.stderr, '>>stderr. stderr is trapped.'
230 print >>sys.stderr, '>>stderr. stderr is trapped.'
236 trap.release_err()
231 trap.release_err()
237 print trap.summary_err()
232 print trap.summary_err()
238
233
239 print 'Trapping all (no flushing)'
234 print 'Trapping all (no flushing)'
240 trap.trap_all()
235 trap.trap_all()
241 print >>sys.stdout, '>>stdout. stdout/err is trapped.'
236 print >>sys.stdout, '>>stdout. stdout/err is trapped.'
242 print >>sys.stderr, '>>stderr. stdout/err is trapped.'
237 print >>sys.stderr, '>>stderr. stdout/err is trapped.'
243 trap.release_all()
238 trap.release_all()
244 print trap.summary_all()
239 print trap.summary_all()
245
240
246 print 'Trapping all (flushing first)'
241 print 'Trapping all (flushing first)'
247 trap.flush()
242 trap.flush()
248 trap.trap_all()
243 trap.trap_all()
249 print >>sys.stdout, '>>stdout. stdout/err is trapped.'
244 print >>sys.stdout, '>>stdout. stdout/err is trapped.'
250 print >>sys.stderr, '>>stderr. stdout/err is trapped.'
245 print >>sys.stderr, '>>stderr. stdout/err is trapped.'
251 trap.release_all()
246 trap.release_all()
252 print trap.summary_all()
247 print trap.summary_all()
253 print 'Finished test for '+ name +'\n'+'#'*50
248 print 'Finished test for '+ name +'\n'+'#'*50
254
249
255 # call the actual tests here:
250 # call the actual tests here:
256 _test_OutputTrap()
251 _test_OutputTrap()
257
252
258
253
259 if __name__=="__main__":
254 if __name__=="__main__":
260 # _test_all() # XXX BROKEN.
255 # _test_all() # XXX BROKEN.
261 pass
256 pass
262
257
263 #************************ end of file <OutputTrap.py> ************************
258 #************************ end of file <OutputTrap.py> ************************
@@ -1,625 +1,624 b''
1 # -*- coding: utf-8 -*-
1 # -*- coding: utf-8 -*-
2 """
2 """
3 Classes for handling input/output prompts.
3 Classes for handling input/output prompts.
4
4 """
5 $Id: Prompts.py 3026 2008-02-07 16:03:16Z vivainio $"""
6
5
7 #*****************************************************************************
6 #*****************************************************************************
8 # Copyright (C) 2001-2006 Fernando Perez <fperez@colorado.edu>
7 # Copyright (C) 2001-2006 Fernando Perez <fperez@colorado.edu>
9 #
8 #
10 # Distributed under the terms of the BSD License. The full license is in
9 # Distributed under the terms of the BSD License. The full license is in
11 # the file COPYING, distributed as part of this software.
10 # the file COPYING, distributed as part of this software.
12 #*****************************************************************************
11 #*****************************************************************************
13
12
14 from IPython import Release
13 from IPython import Release
15 __author__ = '%s <%s>' % Release.authors['Fernando']
14 __author__ = '%s <%s>' % Release.authors['Fernando']
16 __license__ = Release.license
15 __license__ = Release.license
17 __version__ = Release.version
16 __version__ = Release.version
18
17
19 #****************************************************************************
18 #****************************************************************************
20 # Required modules
19 # Required modules
21 import __builtin__
20 import __builtin__
22 import os
21 import os
23 import socket
22 import socket
24 import sys
23 import sys
25 import time
24 import time
26
25
27 # IPython's own
26 # IPython's own
28 from IPython import ColorANSI
27 from IPython import ColorANSI
29 from IPython.Itpl import ItplNS
28 from IPython.Itpl import ItplNS
30 from IPython.ipstruct import Struct
29 from IPython.ipstruct import Struct
31 from IPython.macro import Macro
30 from IPython.macro import Macro
32 from IPython.genutils import *
31 from IPython.genutils import *
33 from IPython.ipapi import TryNext
32 from IPython.ipapi import TryNext
34
33
35 #****************************************************************************
34 #****************************************************************************
36 #Color schemes for Prompts.
35 #Color schemes for Prompts.
37
36
38 PromptColors = ColorANSI.ColorSchemeTable()
37 PromptColors = ColorANSI.ColorSchemeTable()
39 InputColors = ColorANSI.InputTermColors # just a shorthand
38 InputColors = ColorANSI.InputTermColors # just a shorthand
40 Colors = ColorANSI.TermColors # just a shorthand
39 Colors = ColorANSI.TermColors # just a shorthand
41
40
42 PromptColors.add_scheme(ColorANSI.ColorScheme(
41 PromptColors.add_scheme(ColorANSI.ColorScheme(
43 'NoColor',
42 'NoColor',
44 in_prompt = InputColors.NoColor, # Input prompt
43 in_prompt = InputColors.NoColor, # Input prompt
45 in_number = InputColors.NoColor, # Input prompt number
44 in_number = InputColors.NoColor, # Input prompt number
46 in_prompt2 = InputColors.NoColor, # Continuation prompt
45 in_prompt2 = InputColors.NoColor, # Continuation prompt
47 in_normal = InputColors.NoColor, # color off (usu. Colors.Normal)
46 in_normal = InputColors.NoColor, # color off (usu. Colors.Normal)
48
47
49 out_prompt = Colors.NoColor, # Output prompt
48 out_prompt = Colors.NoColor, # Output prompt
50 out_number = Colors.NoColor, # Output prompt number
49 out_number = Colors.NoColor, # Output prompt number
51
50
52 normal = Colors.NoColor # color off (usu. Colors.Normal)
51 normal = Colors.NoColor # color off (usu. Colors.Normal)
53 ))
52 ))
54
53
55 # make some schemes as instances so we can copy them for modification easily:
54 # make some schemes as instances so we can copy them for modification easily:
56 __PColLinux = ColorANSI.ColorScheme(
55 __PColLinux = ColorANSI.ColorScheme(
57 'Linux',
56 'Linux',
58 in_prompt = InputColors.Green,
57 in_prompt = InputColors.Green,
59 in_number = InputColors.LightGreen,
58 in_number = InputColors.LightGreen,
60 in_prompt2 = InputColors.Green,
59 in_prompt2 = InputColors.Green,
61 in_normal = InputColors.Normal, # color off (usu. Colors.Normal)
60 in_normal = InputColors.Normal, # color off (usu. Colors.Normal)
62
61
63 out_prompt = Colors.Red,
62 out_prompt = Colors.Red,
64 out_number = Colors.LightRed,
63 out_number = Colors.LightRed,
65
64
66 normal = Colors.Normal
65 normal = Colors.Normal
67 )
66 )
68 # Don't forget to enter it into the table!
67 # Don't forget to enter it into the table!
69 PromptColors.add_scheme(__PColLinux)
68 PromptColors.add_scheme(__PColLinux)
70
69
71 # Slightly modified Linux for light backgrounds
70 # Slightly modified Linux for light backgrounds
72 __PColLightBG = __PColLinux.copy('LightBG')
71 __PColLightBG = __PColLinux.copy('LightBG')
73
72
74 __PColLightBG.colors.update(
73 __PColLightBG.colors.update(
75 in_prompt = InputColors.Blue,
74 in_prompt = InputColors.Blue,
76 in_number = InputColors.LightBlue,
75 in_number = InputColors.LightBlue,
77 in_prompt2 = InputColors.Blue
76 in_prompt2 = InputColors.Blue
78 )
77 )
79 PromptColors.add_scheme(__PColLightBG)
78 PromptColors.add_scheme(__PColLightBG)
80
79
81 del Colors,InputColors
80 del Colors,InputColors
82
81
83 #-----------------------------------------------------------------------------
82 #-----------------------------------------------------------------------------
84 def multiple_replace(dict, text):
83 def multiple_replace(dict, text):
85 """ Replace in 'text' all occurences of any key in the given
84 """ Replace in 'text' all occurences of any key in the given
86 dictionary by its corresponding value. Returns the new string."""
85 dictionary by its corresponding value. Returns the new string."""
87
86
88 # Function by Xavier Defrang, originally found at:
87 # Function by Xavier Defrang, originally found at:
89 # http://aspn.activestate.com/ASPN/Cookbook/Python/Recipe/81330
88 # http://aspn.activestate.com/ASPN/Cookbook/Python/Recipe/81330
90
89
91 # Create a regular expression from the dictionary keys
90 # Create a regular expression from the dictionary keys
92 regex = re.compile("(%s)" % "|".join(map(re.escape, dict.keys())))
91 regex = re.compile("(%s)" % "|".join(map(re.escape, dict.keys())))
93 # For each match, look-up corresponding value in dictionary
92 # For each match, look-up corresponding value in dictionary
94 return regex.sub(lambda mo: dict[mo.string[mo.start():mo.end()]], text)
93 return regex.sub(lambda mo: dict[mo.string[mo.start():mo.end()]], text)
95
94
96 #-----------------------------------------------------------------------------
95 #-----------------------------------------------------------------------------
97 # Special characters that can be used in prompt templates, mainly bash-like
96 # Special characters that can be used in prompt templates, mainly bash-like
98
97
99 # If $HOME isn't defined (Windows), make it an absurd string so that it can
98 # If $HOME isn't defined (Windows), make it an absurd string so that it can
100 # never be expanded out into '~'. Basically anything which can never be a
99 # never be expanded out into '~'. Basically anything which can never be a
101 # reasonable directory name will do, we just want the $HOME -> '~' operation
100 # reasonable directory name will do, we just want the $HOME -> '~' operation
102 # to become a no-op. We pre-compute $HOME here so it's not done on every
101 # to become a no-op. We pre-compute $HOME here so it's not done on every
103 # prompt call.
102 # prompt call.
104
103
105 # FIXME:
104 # FIXME:
106
105
107 # - This should be turned into a class which does proper namespace management,
106 # - This should be turned into a class which does proper namespace management,
108 # since the prompt specials need to be evaluated in a certain namespace.
107 # since the prompt specials need to be evaluated in a certain namespace.
109 # Currently it's just globals, which need to be managed manually by code
108 # Currently it's just globals, which need to be managed manually by code
110 # below.
109 # below.
111
110
112 # - I also need to split up the color schemes from the prompt specials
111 # - I also need to split up the color schemes from the prompt specials
113 # somehow. I don't have a clean design for that quite yet.
112 # somehow. I don't have a clean design for that quite yet.
114
113
115 HOME = os.environ.get("HOME","//////:::::ZZZZZ,,,~~~")
114 HOME = os.environ.get("HOME","//////:::::ZZZZZ,,,~~~")
116
115
117 # We precompute a few more strings here for the prompt_specials, which are
116 # We precompute a few more strings here for the prompt_specials, which are
118 # fixed once ipython starts. This reduces the runtime overhead of computing
117 # fixed once ipython starts. This reduces the runtime overhead of computing
119 # prompt strings.
118 # prompt strings.
120 USER = os.environ.get("USER")
119 USER = os.environ.get("USER")
121 HOSTNAME = socket.gethostname()
120 HOSTNAME = socket.gethostname()
122 HOSTNAME_SHORT = HOSTNAME.split(".")[0]
121 HOSTNAME_SHORT = HOSTNAME.split(".")[0]
123 ROOT_SYMBOL = "$#"[os.name=='nt' or os.getuid()==0]
122 ROOT_SYMBOL = "$#"[os.name=='nt' or os.getuid()==0]
124
123
125 prompt_specials_color = {
124 prompt_specials_color = {
126 # Prompt/history count
125 # Prompt/history count
127 '%n' : '${self.col_num}' '${self.cache.prompt_count}' '${self.col_p}',
126 '%n' : '${self.col_num}' '${self.cache.prompt_count}' '${self.col_p}',
128 r'\#': '${self.col_num}' '${self.cache.prompt_count}' '${self.col_p}',
127 r'\#': '${self.col_num}' '${self.cache.prompt_count}' '${self.col_p}',
129 # Just the prompt counter number, WITHOUT any coloring wrappers, so users
128 # Just the prompt counter number, WITHOUT any coloring wrappers, so users
130 # can get numbers displayed in whatever color they want.
129 # can get numbers displayed in whatever color they want.
131 r'\N': '${self.cache.prompt_count}',
130 r'\N': '${self.cache.prompt_count}',
132 # Prompt/history count, with the actual digits replaced by dots. Used
131 # Prompt/history count, with the actual digits replaced by dots. Used
133 # mainly in continuation prompts (prompt_in2)
132 # mainly in continuation prompts (prompt_in2)
134 r'\D': '${"."*len(str(self.cache.prompt_count))}',
133 r'\D': '${"."*len(str(self.cache.prompt_count))}',
135 # Current working directory
134 # Current working directory
136 r'\w': '${os.getcwd()}',
135 r'\w': '${os.getcwd()}',
137 # Current time
136 # Current time
138 r'\t' : '${time.strftime("%H:%M:%S")}',
137 r'\t' : '${time.strftime("%H:%M:%S")}',
139 # Basename of current working directory.
138 # Basename of current working directory.
140 # (use os.sep to make this portable across OSes)
139 # (use os.sep to make this portable across OSes)
141 r'\W' : '${os.getcwd().split("%s")[-1]}' % os.sep,
140 r'\W' : '${os.getcwd().split("%s")[-1]}' % os.sep,
142 # These X<N> are an extension to the normal bash prompts. They return
141 # These X<N> are an extension to the normal bash prompts. They return
143 # N terms of the path, after replacing $HOME with '~'
142 # N terms of the path, after replacing $HOME with '~'
144 r'\X0': '${os.getcwd().replace("%s","~")}' % HOME,
143 r'\X0': '${os.getcwd().replace("%s","~")}' % HOME,
145 r'\X1': '${self.cwd_filt(1)}',
144 r'\X1': '${self.cwd_filt(1)}',
146 r'\X2': '${self.cwd_filt(2)}',
145 r'\X2': '${self.cwd_filt(2)}',
147 r'\X3': '${self.cwd_filt(3)}',
146 r'\X3': '${self.cwd_filt(3)}',
148 r'\X4': '${self.cwd_filt(4)}',
147 r'\X4': '${self.cwd_filt(4)}',
149 r'\X5': '${self.cwd_filt(5)}',
148 r'\X5': '${self.cwd_filt(5)}',
150 # Y<N> are similar to X<N>, but they show '~' if it's the directory
149 # Y<N> are similar to X<N>, but they show '~' if it's the directory
151 # N+1 in the list. Somewhat like %cN in tcsh.
150 # N+1 in the list. Somewhat like %cN in tcsh.
152 r'\Y0': '${self.cwd_filt2(0)}',
151 r'\Y0': '${self.cwd_filt2(0)}',
153 r'\Y1': '${self.cwd_filt2(1)}',
152 r'\Y1': '${self.cwd_filt2(1)}',
154 r'\Y2': '${self.cwd_filt2(2)}',
153 r'\Y2': '${self.cwd_filt2(2)}',
155 r'\Y3': '${self.cwd_filt2(3)}',
154 r'\Y3': '${self.cwd_filt2(3)}',
156 r'\Y4': '${self.cwd_filt2(4)}',
155 r'\Y4': '${self.cwd_filt2(4)}',
157 r'\Y5': '${self.cwd_filt2(5)}',
156 r'\Y5': '${self.cwd_filt2(5)}',
158 # Hostname up to first .
157 # Hostname up to first .
159 r'\h': HOSTNAME_SHORT,
158 r'\h': HOSTNAME_SHORT,
160 # Full hostname
159 # Full hostname
161 r'\H': HOSTNAME,
160 r'\H': HOSTNAME,
162 # Username of current user
161 # Username of current user
163 r'\u': USER,
162 r'\u': USER,
164 # Escaped '\'
163 # Escaped '\'
165 '\\\\': '\\',
164 '\\\\': '\\',
166 # Newline
165 # Newline
167 r'\n': '\n',
166 r'\n': '\n',
168 # Carriage return
167 # Carriage return
169 r'\r': '\r',
168 r'\r': '\r',
170 # Release version
169 # Release version
171 r'\v': __version__,
170 r'\v': __version__,
172 # Root symbol ($ or #)
171 # Root symbol ($ or #)
173 r'\$': ROOT_SYMBOL,
172 r'\$': ROOT_SYMBOL,
174 }
173 }
175
174
176 # A copy of the prompt_specials dictionary but with all color escapes removed,
175 # A copy of the prompt_specials dictionary but with all color escapes removed,
177 # so we can correctly compute the prompt length for the auto_rewrite method.
176 # so we can correctly compute the prompt length for the auto_rewrite method.
178 prompt_specials_nocolor = prompt_specials_color.copy()
177 prompt_specials_nocolor = prompt_specials_color.copy()
179 prompt_specials_nocolor['%n'] = '${self.cache.prompt_count}'
178 prompt_specials_nocolor['%n'] = '${self.cache.prompt_count}'
180 prompt_specials_nocolor[r'\#'] = '${self.cache.prompt_count}'
179 prompt_specials_nocolor[r'\#'] = '${self.cache.prompt_count}'
181
180
182 # Add in all the InputTermColors color escapes as valid prompt characters.
181 # Add in all the InputTermColors color escapes as valid prompt characters.
183 # They all get added as \\C_COLORNAME, so that we don't have any conflicts
182 # They all get added as \\C_COLORNAME, so that we don't have any conflicts
184 # with a color name which may begin with a letter used by any other of the
183 # with a color name which may begin with a letter used by any other of the
185 # allowed specials. This of course means that \\C will never be allowed for
184 # allowed specials. This of course means that \\C will never be allowed for
186 # anything else.
185 # anything else.
187 input_colors = ColorANSI.InputTermColors
186 input_colors = ColorANSI.InputTermColors
188 for _color in dir(input_colors):
187 for _color in dir(input_colors):
189 if _color[0] != '_':
188 if _color[0] != '_':
190 c_name = r'\C_'+_color
189 c_name = r'\C_'+_color
191 prompt_specials_color[c_name] = getattr(input_colors,_color)
190 prompt_specials_color[c_name] = getattr(input_colors,_color)
192 prompt_specials_nocolor[c_name] = ''
191 prompt_specials_nocolor[c_name] = ''
193
192
194 # we default to no color for safety. Note that prompt_specials is a global
193 # we default to no color for safety. Note that prompt_specials is a global
195 # variable used by all prompt objects.
194 # variable used by all prompt objects.
196 prompt_specials = prompt_specials_nocolor
195 prompt_specials = prompt_specials_nocolor
197
196
198 #-----------------------------------------------------------------------------
197 #-----------------------------------------------------------------------------
199 def str_safe(arg):
198 def str_safe(arg):
200 """Convert to a string, without ever raising an exception.
199 """Convert to a string, without ever raising an exception.
201
200
202 If str(arg) fails, <ERROR: ... > is returned, where ... is the exception
201 If str(arg) fails, <ERROR: ... > is returned, where ... is the exception
203 error message."""
202 error message."""
204
203
205 try:
204 try:
206 out = str(arg)
205 out = str(arg)
207 except UnicodeError:
206 except UnicodeError:
208 try:
207 try:
209 out = arg.encode('utf_8','replace')
208 out = arg.encode('utf_8','replace')
210 except Exception,msg:
209 except Exception,msg:
211 # let's keep this little duplication here, so that the most common
210 # let's keep this little duplication here, so that the most common
212 # case doesn't suffer from a double try wrapping.
211 # case doesn't suffer from a double try wrapping.
213 out = '<ERROR: %s>' % msg
212 out = '<ERROR: %s>' % msg
214 except Exception,msg:
213 except Exception,msg:
215 out = '<ERROR: %s>' % msg
214 out = '<ERROR: %s>' % msg
216 return out
215 return out
217
216
218 class BasePrompt(object):
217 class BasePrompt(object):
219 """Interactive prompt similar to Mathematica's."""
218 """Interactive prompt similar to Mathematica's."""
220
219
221 def _get_p_template(self):
220 def _get_p_template(self):
222 return self._p_template
221 return self._p_template
223
222
224 def _set_p_template(self,val):
223 def _set_p_template(self,val):
225 self._p_template = val
224 self._p_template = val
226 self.set_p_str()
225 self.set_p_str()
227
226
228 p_template = property(_get_p_template,_set_p_template,
227 p_template = property(_get_p_template,_set_p_template,
229 doc='Template for prompt string creation')
228 doc='Template for prompt string creation')
230
229
231 def __init__(self,cache,sep,prompt,pad_left=False):
230 def __init__(self,cache,sep,prompt,pad_left=False):
232
231
233 # Hack: we access information about the primary prompt through the
232 # Hack: we access information about the primary prompt through the
234 # cache argument. We need this, because we want the secondary prompt
233 # cache argument. We need this, because we want the secondary prompt
235 # to be aligned with the primary one. Color table info is also shared
234 # to be aligned with the primary one. Color table info is also shared
236 # by all prompt classes through the cache. Nice OO spaghetti code!
235 # by all prompt classes through the cache. Nice OO spaghetti code!
237 self.cache = cache
236 self.cache = cache
238 self.sep = sep
237 self.sep = sep
239
238
240 # regexp to count the number of spaces at the end of a prompt
239 # regexp to count the number of spaces at the end of a prompt
241 # expression, useful for prompt auto-rewriting
240 # expression, useful for prompt auto-rewriting
242 self.rspace = re.compile(r'(\s*)$')
241 self.rspace = re.compile(r'(\s*)$')
243 # Flag to left-pad prompt strings to match the length of the primary
242 # Flag to left-pad prompt strings to match the length of the primary
244 # prompt
243 # prompt
245 self.pad_left = pad_left
244 self.pad_left = pad_left
246
245
247 # Set template to create each actual prompt (where numbers change).
246 # Set template to create each actual prompt (where numbers change).
248 # Use a property
247 # Use a property
249 self.p_template = prompt
248 self.p_template = prompt
250 self.set_p_str()
249 self.set_p_str()
251
250
252 def set_p_str(self):
251 def set_p_str(self):
253 """ Set the interpolating prompt strings.
252 """ Set the interpolating prompt strings.
254
253
255 This must be called every time the color settings change, because the
254 This must be called every time the color settings change, because the
256 prompt_specials global may have changed."""
255 prompt_specials global may have changed."""
257
256
258 import os,time # needed in locals for prompt string handling
257 import os,time # needed in locals for prompt string handling
259 loc = locals()
258 loc = locals()
260 try:
259 try:
261 self.p_str = ItplNS('%s%s%s' %
260 self.p_str = ItplNS('%s%s%s' %
262 ('${self.sep}${self.col_p}',
261 ('${self.sep}${self.col_p}',
263 multiple_replace(prompt_specials, self.p_template),
262 multiple_replace(prompt_specials, self.p_template),
264 '${self.col_norm}'),self.cache.user_ns,loc)
263 '${self.col_norm}'),self.cache.user_ns,loc)
265
264
266 self.p_str_nocolor = ItplNS(multiple_replace(prompt_specials_nocolor,
265 self.p_str_nocolor = ItplNS(multiple_replace(prompt_specials_nocolor,
267 self.p_template),
266 self.p_template),
268 self.cache.user_ns,loc)
267 self.cache.user_ns,loc)
269 except:
268 except:
270 print "Illegal prompt template (check $ usage!):",self.p_template
269 print "Illegal prompt template (check $ usage!):",self.p_template
271 self.p_str = self.p_template
270 self.p_str = self.p_template
272 self.p_str_nocolor = self.p_template
271 self.p_str_nocolor = self.p_template
273
272
274 def write(self,msg): # dbg
273 def write(self,msg): # dbg
275 sys.stdout.write(msg)
274 sys.stdout.write(msg)
276 return ''
275 return ''
277
276
278 def __str__(self):
277 def __str__(self):
279 """Return a string form of the prompt.
278 """Return a string form of the prompt.
280
279
281 This for is useful for continuation and output prompts, since it is
280 This for is useful for continuation and output prompts, since it is
282 left-padded to match lengths with the primary one (if the
281 left-padded to match lengths with the primary one (if the
283 self.pad_left attribute is set)."""
282 self.pad_left attribute is set)."""
284
283
285 out_str = str_safe(self.p_str)
284 out_str = str_safe(self.p_str)
286 if self.pad_left:
285 if self.pad_left:
287 # We must find the amount of padding required to match lengths,
286 # We must find the amount of padding required to match lengths,
288 # taking the color escapes (which are invisible on-screen) into
287 # taking the color escapes (which are invisible on-screen) into
289 # account.
288 # account.
290 esc_pad = len(out_str) - len(str_safe(self.p_str_nocolor))
289 esc_pad = len(out_str) - len(str_safe(self.p_str_nocolor))
291 format = '%%%ss' % (len(str(self.cache.last_prompt))+esc_pad)
290 format = '%%%ss' % (len(str(self.cache.last_prompt))+esc_pad)
292 return format % out_str
291 return format % out_str
293 else:
292 else:
294 return out_str
293 return out_str
295
294
296 # these path filters are put in as methods so that we can control the
295 # these path filters are put in as methods so that we can control the
297 # namespace where the prompt strings get evaluated
296 # namespace where the prompt strings get evaluated
298 def cwd_filt(self,depth):
297 def cwd_filt(self,depth):
299 """Return the last depth elements of the current working directory.
298 """Return the last depth elements of the current working directory.
300
299
301 $HOME is always replaced with '~'.
300 $HOME is always replaced with '~'.
302 If depth==0, the full path is returned."""
301 If depth==0, the full path is returned."""
303
302
304 cwd = os.getcwd().replace(HOME,"~")
303 cwd = os.getcwd().replace(HOME,"~")
305 out = os.sep.join(cwd.split(os.sep)[-depth:])
304 out = os.sep.join(cwd.split(os.sep)[-depth:])
306 if out:
305 if out:
307 return out
306 return out
308 else:
307 else:
309 return os.sep
308 return os.sep
310
309
311 def cwd_filt2(self,depth):
310 def cwd_filt2(self,depth):
312 """Return the last depth elements of the current working directory.
311 """Return the last depth elements of the current working directory.
313
312
314 $HOME is always replaced with '~'.
313 $HOME is always replaced with '~'.
315 If depth==0, the full path is returned."""
314 If depth==0, the full path is returned."""
316
315
317 full_cwd = os.getcwd()
316 full_cwd = os.getcwd()
318 cwd = full_cwd.replace(HOME,"~").split(os.sep)
317 cwd = full_cwd.replace(HOME,"~").split(os.sep)
319 if '~' in cwd and len(cwd) == depth+1:
318 if '~' in cwd and len(cwd) == depth+1:
320 depth += 1
319 depth += 1
321 drivepart = ''
320 drivepart = ''
322 if sys.platform == 'win32' and len(cwd) > depth:
321 if sys.platform == 'win32' and len(cwd) > depth:
323 drivepart = os.path.splitdrive(full_cwd)[0]
322 drivepart = os.path.splitdrive(full_cwd)[0]
324 out = drivepart + '/'.join(cwd[-depth:])
323 out = drivepart + '/'.join(cwd[-depth:])
325
324
326 if out:
325 if out:
327 return out
326 return out
328 else:
327 else:
329 return os.sep
328 return os.sep
330
329
331 def __nonzero__(self):
330 def __nonzero__(self):
332 """Implement boolean behavior.
331 """Implement boolean behavior.
333
332
334 Checks whether the p_str attribute is non-empty"""
333 Checks whether the p_str attribute is non-empty"""
335
334
336 return bool(self.p_template)
335 return bool(self.p_template)
337
336
338 class Prompt1(BasePrompt):
337 class Prompt1(BasePrompt):
339 """Input interactive prompt similar to Mathematica's."""
338 """Input interactive prompt similar to Mathematica's."""
340
339
341 def __init__(self,cache,sep='\n',prompt='In [\\#]: ',pad_left=True):
340 def __init__(self,cache,sep='\n',prompt='In [\\#]: ',pad_left=True):
342 BasePrompt.__init__(self,cache,sep,prompt,pad_left)
341 BasePrompt.__init__(self,cache,sep,prompt,pad_left)
343
342
344 def set_colors(self):
343 def set_colors(self):
345 self.set_p_str()
344 self.set_p_str()
346 Colors = self.cache.color_table.active_colors # shorthand
345 Colors = self.cache.color_table.active_colors # shorthand
347 self.col_p = Colors.in_prompt
346 self.col_p = Colors.in_prompt
348 self.col_num = Colors.in_number
347 self.col_num = Colors.in_number
349 self.col_norm = Colors.in_normal
348 self.col_norm = Colors.in_normal
350 # We need a non-input version of these escapes for the '--->'
349 # We need a non-input version of these escapes for the '--->'
351 # auto-call prompts used in the auto_rewrite() method.
350 # auto-call prompts used in the auto_rewrite() method.
352 self.col_p_ni = self.col_p.replace('\001','').replace('\002','')
351 self.col_p_ni = self.col_p.replace('\001','').replace('\002','')
353 self.col_norm_ni = Colors.normal
352 self.col_norm_ni = Colors.normal
354
353
355 def __str__(self):
354 def __str__(self):
356 self.cache.prompt_count += 1
355 self.cache.prompt_count += 1
357 self.cache.last_prompt = str_safe(self.p_str_nocolor).split('\n')[-1]
356 self.cache.last_prompt = str_safe(self.p_str_nocolor).split('\n')[-1]
358 return str_safe(self.p_str)
357 return str_safe(self.p_str)
359
358
360 def auto_rewrite(self):
359 def auto_rewrite(self):
361 """Print a string of the form '--->' which lines up with the previous
360 """Print a string of the form '--->' which lines up with the previous
362 input string. Useful for systems which re-write the user input when
361 input string. Useful for systems which re-write the user input when
363 handling automatically special syntaxes."""
362 handling automatically special syntaxes."""
364
363
365 curr = str(self.cache.last_prompt)
364 curr = str(self.cache.last_prompt)
366 nrspaces = len(self.rspace.search(curr).group())
365 nrspaces = len(self.rspace.search(curr).group())
367 return '%s%s>%s%s' % (self.col_p_ni,'-'*(len(curr)-nrspaces-1),
366 return '%s%s>%s%s' % (self.col_p_ni,'-'*(len(curr)-nrspaces-1),
368 ' '*nrspaces,self.col_norm_ni)
367 ' '*nrspaces,self.col_norm_ni)
369
368
370 class PromptOut(BasePrompt):
369 class PromptOut(BasePrompt):
371 """Output interactive prompt similar to Mathematica's."""
370 """Output interactive prompt similar to Mathematica's."""
372
371
373 def __init__(self,cache,sep='',prompt='Out[\\#]: ',pad_left=True):
372 def __init__(self,cache,sep='',prompt='Out[\\#]: ',pad_left=True):
374 BasePrompt.__init__(self,cache,sep,prompt,pad_left)
373 BasePrompt.__init__(self,cache,sep,prompt,pad_left)
375 if not self.p_template:
374 if not self.p_template:
376 self.__str__ = lambda: ''
375 self.__str__ = lambda: ''
377
376
378 def set_colors(self):
377 def set_colors(self):
379 self.set_p_str()
378 self.set_p_str()
380 Colors = self.cache.color_table.active_colors # shorthand
379 Colors = self.cache.color_table.active_colors # shorthand
381 self.col_p = Colors.out_prompt
380 self.col_p = Colors.out_prompt
382 self.col_num = Colors.out_number
381 self.col_num = Colors.out_number
383 self.col_norm = Colors.normal
382 self.col_norm = Colors.normal
384
383
385 class Prompt2(BasePrompt):
384 class Prompt2(BasePrompt):
386 """Interactive continuation prompt."""
385 """Interactive continuation prompt."""
387
386
388 def __init__(self,cache,prompt=' .\\D.: ',pad_left=True):
387 def __init__(self,cache,prompt=' .\\D.: ',pad_left=True):
389 self.cache = cache
388 self.cache = cache
390 self.p_template = prompt
389 self.p_template = prompt
391 self.pad_left = pad_left
390 self.pad_left = pad_left
392 self.set_p_str()
391 self.set_p_str()
393
392
394 def set_p_str(self):
393 def set_p_str(self):
395 import os,time # needed in locals for prompt string handling
394 import os,time # needed in locals for prompt string handling
396 loc = locals()
395 loc = locals()
397 self.p_str = ItplNS('%s%s%s' %
396 self.p_str = ItplNS('%s%s%s' %
398 ('${self.col_p2}',
397 ('${self.col_p2}',
399 multiple_replace(prompt_specials, self.p_template),
398 multiple_replace(prompt_specials, self.p_template),
400 '$self.col_norm'),
399 '$self.col_norm'),
401 self.cache.user_ns,loc)
400 self.cache.user_ns,loc)
402 self.p_str_nocolor = ItplNS(multiple_replace(prompt_specials_nocolor,
401 self.p_str_nocolor = ItplNS(multiple_replace(prompt_specials_nocolor,
403 self.p_template),
402 self.p_template),
404 self.cache.user_ns,loc)
403 self.cache.user_ns,loc)
405
404
406 def set_colors(self):
405 def set_colors(self):
407 self.set_p_str()
406 self.set_p_str()
408 Colors = self.cache.color_table.active_colors
407 Colors = self.cache.color_table.active_colors
409 self.col_p2 = Colors.in_prompt2
408 self.col_p2 = Colors.in_prompt2
410 self.col_norm = Colors.in_normal
409 self.col_norm = Colors.in_normal
411 # FIXME (2004-06-16) HACK: prevent crashes for users who haven't
410 # FIXME (2004-06-16) HACK: prevent crashes for users who haven't
412 # updated their prompt_in2 definitions. Remove eventually.
411 # updated their prompt_in2 definitions. Remove eventually.
413 self.col_p = Colors.out_prompt
412 self.col_p = Colors.out_prompt
414 self.col_num = Colors.out_number
413 self.col_num = Colors.out_number
415
414
416
415
417 #-----------------------------------------------------------------------------
416 #-----------------------------------------------------------------------------
418 class CachedOutput:
417 class CachedOutput:
419 """Class for printing output from calculations while keeping a cache of
418 """Class for printing output from calculations while keeping a cache of
420 reults. It dynamically creates global variables prefixed with _ which
419 reults. It dynamically creates global variables prefixed with _ which
421 contain these results.
420 contain these results.
422
421
423 Meant to be used as a sys.displayhook replacement, providing numbered
422 Meant to be used as a sys.displayhook replacement, providing numbered
424 prompts and cache services.
423 prompts and cache services.
425
424
426 Initialize with initial and final values for cache counter (this defines
425 Initialize with initial and final values for cache counter (this defines
427 the maximum size of the cache."""
426 the maximum size of the cache."""
428
427
429 def __init__(self,shell,cache_size,Pprint,
428 def __init__(self,shell,cache_size,Pprint,
430 colors='NoColor',input_sep='\n',
429 colors='NoColor',input_sep='\n',
431 output_sep='\n',output_sep2='',
430 output_sep='\n',output_sep2='',
432 ps1 = None, ps2 = None,ps_out = None,pad_left=True):
431 ps1 = None, ps2 = None,ps_out = None,pad_left=True):
433
432
434 cache_size_min = 3
433 cache_size_min = 3
435 if cache_size <= 0:
434 if cache_size <= 0:
436 self.do_full_cache = 0
435 self.do_full_cache = 0
437 cache_size = 0
436 cache_size = 0
438 elif cache_size < cache_size_min:
437 elif cache_size < cache_size_min:
439 self.do_full_cache = 0
438 self.do_full_cache = 0
440 cache_size = 0
439 cache_size = 0
441 warn('caching was disabled (min value for cache size is %s).' %
440 warn('caching was disabled (min value for cache size is %s).' %
442 cache_size_min,level=3)
441 cache_size_min,level=3)
443 else:
442 else:
444 self.do_full_cache = 1
443 self.do_full_cache = 1
445
444
446 self.cache_size = cache_size
445 self.cache_size = cache_size
447 self.input_sep = input_sep
446 self.input_sep = input_sep
448
447
449 # we need a reference to the user-level namespace
448 # we need a reference to the user-level namespace
450 self.shell = shell
449 self.shell = shell
451 self.user_ns = shell.user_ns
450 self.user_ns = shell.user_ns
452 # and to the user's input
451 # and to the user's input
453 self.input_hist = shell.input_hist
452 self.input_hist = shell.input_hist
454 # and to the user's logger, for logging output
453 # and to the user's logger, for logging output
455 self.logger = shell.logger
454 self.logger = shell.logger
456
455
457 # Set input prompt strings and colors
456 # Set input prompt strings and colors
458 if cache_size == 0:
457 if cache_size == 0:
459 if ps1.find('%n') > -1 or ps1.find(r'\#') > -1 \
458 if ps1.find('%n') > -1 or ps1.find(r'\#') > -1 \
460 or ps1.find(r'\N') > -1:
459 or ps1.find(r'\N') > -1:
461 ps1 = '>>> '
460 ps1 = '>>> '
462 if ps2.find('%n') > -1 or ps2.find(r'\#') > -1 \
461 if ps2.find('%n') > -1 or ps2.find(r'\#') > -1 \
463 or ps2.find(r'\N') > -1:
462 or ps2.find(r'\N') > -1:
464 ps2 = '... '
463 ps2 = '... '
465 self.ps1_str = self._set_prompt_str(ps1,'In [\\#]: ','>>> ')
464 self.ps1_str = self._set_prompt_str(ps1,'In [\\#]: ','>>> ')
466 self.ps2_str = self._set_prompt_str(ps2,' .\\D.: ','... ')
465 self.ps2_str = self._set_prompt_str(ps2,' .\\D.: ','... ')
467 self.ps_out_str = self._set_prompt_str(ps_out,'Out[\\#]: ','')
466 self.ps_out_str = self._set_prompt_str(ps_out,'Out[\\#]: ','')
468
467
469 self.color_table = PromptColors
468 self.color_table = PromptColors
470 self.prompt1 = Prompt1(self,sep=input_sep,prompt=self.ps1_str,
469 self.prompt1 = Prompt1(self,sep=input_sep,prompt=self.ps1_str,
471 pad_left=pad_left)
470 pad_left=pad_left)
472 self.prompt2 = Prompt2(self,prompt=self.ps2_str,pad_left=pad_left)
471 self.prompt2 = Prompt2(self,prompt=self.ps2_str,pad_left=pad_left)
473 self.prompt_out = PromptOut(self,sep='',prompt=self.ps_out_str,
472 self.prompt_out = PromptOut(self,sep='',prompt=self.ps_out_str,
474 pad_left=pad_left)
473 pad_left=pad_left)
475 self.set_colors(colors)
474 self.set_colors(colors)
476
475
477 # other more normal stuff
476 # other more normal stuff
478 # b/c each call to the In[] prompt raises it by 1, even the first.
477 # b/c each call to the In[] prompt raises it by 1, even the first.
479 self.prompt_count = 0
478 self.prompt_count = 0
480 # Store the last prompt string each time, we need it for aligning
479 # Store the last prompt string each time, we need it for aligning
481 # continuation and auto-rewrite prompts
480 # continuation and auto-rewrite prompts
482 self.last_prompt = ''
481 self.last_prompt = ''
483 self.Pprint = Pprint
482 self.Pprint = Pprint
484 self.output_sep = output_sep
483 self.output_sep = output_sep
485 self.output_sep2 = output_sep2
484 self.output_sep2 = output_sep2
486 self._,self.__,self.___ = '','',''
485 self._,self.__,self.___ = '','',''
487 self.pprint_types = map(type,[(),[],{}])
486 self.pprint_types = map(type,[(),[],{}])
488
487
489 # these are deliberately global:
488 # these are deliberately global:
490 to_user_ns = {'_':self._,'__':self.__,'___':self.___}
489 to_user_ns = {'_':self._,'__':self.__,'___':self.___}
491 self.user_ns.update(to_user_ns)
490 self.user_ns.update(to_user_ns)
492
491
493 def _set_prompt_str(self,p_str,cache_def,no_cache_def):
492 def _set_prompt_str(self,p_str,cache_def,no_cache_def):
494 if p_str is None:
493 if p_str is None:
495 if self.do_full_cache:
494 if self.do_full_cache:
496 return cache_def
495 return cache_def
497 else:
496 else:
498 return no_cache_def
497 return no_cache_def
499 else:
498 else:
500 return p_str
499 return p_str
501
500
502 def set_colors(self,colors):
501 def set_colors(self,colors):
503 """Set the active color scheme and configure colors for the three
502 """Set the active color scheme and configure colors for the three
504 prompt subsystems."""
503 prompt subsystems."""
505
504
506 # FIXME: the prompt_specials global should be gobbled inside this
505 # FIXME: the prompt_specials global should be gobbled inside this
507 # class instead. Do it when cleaning up the whole 3-prompt system.
506 # class instead. Do it when cleaning up the whole 3-prompt system.
508 global prompt_specials
507 global prompt_specials
509 if colors.lower()=='nocolor':
508 if colors.lower()=='nocolor':
510 prompt_specials = prompt_specials_nocolor
509 prompt_specials = prompt_specials_nocolor
511 else:
510 else:
512 prompt_specials = prompt_specials_color
511 prompt_specials = prompt_specials_color
513
512
514 self.color_table.set_active_scheme(colors)
513 self.color_table.set_active_scheme(colors)
515 self.prompt1.set_colors()
514 self.prompt1.set_colors()
516 self.prompt2.set_colors()
515 self.prompt2.set_colors()
517 self.prompt_out.set_colors()
516 self.prompt_out.set_colors()
518
517
519 def __call__(self,arg=None):
518 def __call__(self,arg=None):
520 """Printing with history cache management.
519 """Printing with history cache management.
521
520
522 This is invoked everytime the interpreter needs to print, and is
521 This is invoked everytime the interpreter needs to print, and is
523 activated by setting the variable sys.displayhook to it."""
522 activated by setting the variable sys.displayhook to it."""
524
523
525 # If something injected a '_' variable in __builtin__, delete
524 # If something injected a '_' variable in __builtin__, delete
526 # ipython's automatic one so we don't clobber that. gettext() in
525 # ipython's automatic one so we don't clobber that. gettext() in
527 # particular uses _, so we need to stay away from it.
526 # particular uses _, so we need to stay away from it.
528 if '_' in __builtin__.__dict__:
527 if '_' in __builtin__.__dict__:
529 try:
528 try:
530 del self.user_ns['_']
529 del self.user_ns['_']
531 except KeyError:
530 except KeyError:
532 pass
531 pass
533 if arg is not None:
532 if arg is not None:
534 cout_write = Term.cout.write # fast lookup
533 cout_write = Term.cout.write # fast lookup
535 # first handle the cache and counters
534 # first handle the cache and counters
536
535
537 # do not print output if input ends in ';'
536 # do not print output if input ends in ';'
538 try:
537 try:
539 if self.input_hist[self.prompt_count].endswith(';\n'):
538 if self.input_hist[self.prompt_count].endswith(';\n'):
540 return
539 return
541 except IndexError:
540 except IndexError:
542 # some uses of ipshellembed may fail here
541 # some uses of ipshellembed may fail here
543 pass
542 pass
544 # don't use print, puts an extra space
543 # don't use print, puts an extra space
545 cout_write(self.output_sep)
544 cout_write(self.output_sep)
546 outprompt = self.shell.hooks.generate_output_prompt()
545 outprompt = self.shell.hooks.generate_output_prompt()
547 if self.do_full_cache:
546 if self.do_full_cache:
548 cout_write(outprompt)
547 cout_write(outprompt)
549
548
550 # and now call a possibly user-defined print mechanism
549 # and now call a possibly user-defined print mechanism
551 manipulated_val = self.display(arg)
550 manipulated_val = self.display(arg)
552
551
553 # user display hooks can change the variable to be stored in
552 # user display hooks can change the variable to be stored in
554 # output history
553 # output history
555
554
556 if manipulated_val is not None:
555 if manipulated_val is not None:
557 arg = manipulated_val
556 arg = manipulated_val
558
557
559 # avoid recursive reference when displaying _oh/Out
558 # avoid recursive reference when displaying _oh/Out
560 if arg is not self.user_ns['_oh']:
559 if arg is not self.user_ns['_oh']:
561 self.update(arg)
560 self.update(arg)
562
561
563 if self.logger.log_output:
562 if self.logger.log_output:
564 self.logger.log_write(repr(arg),'output')
563 self.logger.log_write(repr(arg),'output')
565 cout_write(self.output_sep2)
564 cout_write(self.output_sep2)
566 Term.cout.flush()
565 Term.cout.flush()
567
566
568 def _display(self,arg):
567 def _display(self,arg):
569 """Default printer method, uses pprint.
568 """Default printer method, uses pprint.
570
569
571 Do ip.set_hook("result_display", my_displayhook) for custom result
570 Do ip.set_hook("result_display", my_displayhook) for custom result
572 display, e.g. when your own objects need special formatting.
571 display, e.g. when your own objects need special formatting.
573 """
572 """
574 try:
573 try:
575 return IPython.generics.result_display(arg)
574 return IPython.generics.result_display(arg)
576 except TryNext:
575 except TryNext:
577 return self.shell.hooks.result_display(arg)
576 return self.shell.hooks.result_display(arg)
578
577
579 # Assign the default display method:
578 # Assign the default display method:
580 display = _display
579 display = _display
581
580
582 def update(self,arg):
581 def update(self,arg):
583 #print '***cache_count', self.cache_count # dbg
582 #print '***cache_count', self.cache_count # dbg
584 if len(self.user_ns['_oh']) >= self.cache_size and self.do_full_cache:
583 if len(self.user_ns['_oh']) >= self.cache_size and self.do_full_cache:
585 warn('Output cache limit (currently '+
584 warn('Output cache limit (currently '+
586 `self.cache_size`+' entries) hit.\n'
585 `self.cache_size`+' entries) hit.\n'
587 'Flushing cache and resetting history counter...\n'
586 'Flushing cache and resetting history counter...\n'
588 'The only history variables available will be _,__,___ and _1\n'
587 'The only history variables available will be _,__,___ and _1\n'
589 'with the current result.')
588 'with the current result.')
590
589
591 self.flush()
590 self.flush()
592 # Don't overwrite '_' and friends if '_' is in __builtin__ (otherwise
591 # Don't overwrite '_' and friends if '_' is in __builtin__ (otherwise
593 # we cause buggy behavior for things like gettext).
592 # we cause buggy behavior for things like gettext).
594 if '_' not in __builtin__.__dict__:
593 if '_' not in __builtin__.__dict__:
595 self.___ = self.__
594 self.___ = self.__
596 self.__ = self._
595 self.__ = self._
597 self._ = arg
596 self._ = arg
598 self.user_ns.update({'_':self._,'__':self.__,'___':self.___})
597 self.user_ns.update({'_':self._,'__':self.__,'___':self.___})
599
598
600 # hackish access to top-level namespace to create _1,_2... dynamically
599 # hackish access to top-level namespace to create _1,_2... dynamically
601 to_main = {}
600 to_main = {}
602 if self.do_full_cache:
601 if self.do_full_cache:
603 new_result = '_'+`self.prompt_count`
602 new_result = '_'+`self.prompt_count`
604 to_main[new_result] = arg
603 to_main[new_result] = arg
605 self.user_ns.update(to_main)
604 self.user_ns.update(to_main)
606 self.user_ns['_oh'][self.prompt_count] = arg
605 self.user_ns['_oh'][self.prompt_count] = arg
607
606
608 def flush(self):
607 def flush(self):
609 if not self.do_full_cache:
608 if not self.do_full_cache:
610 raise ValueError,"You shouldn't have reached the cache flush "\
609 raise ValueError,"You shouldn't have reached the cache flush "\
611 "if full caching is not enabled!"
610 "if full caching is not enabled!"
612 # delete auto-generated vars from global namespace
611 # delete auto-generated vars from global namespace
613
612
614 for n in range(1,self.prompt_count + 1):
613 for n in range(1,self.prompt_count + 1):
615 key = '_'+`n`
614 key = '_'+`n`
616 try:
615 try:
617 del self.user_ns[key]
616 del self.user_ns[key]
618 except: pass
617 except: pass
619 self.user_ns['_oh'].clear()
618 self.user_ns['_oh'].clear()
620
619
621 if '_' not in __builtin__.__dict__:
620 if '_' not in __builtin__.__dict__:
622 self.user_ns.update({'_':None,'__':None, '___':None})
621 self.user_ns.update({'_':None,'__':None, '___':None})
623 import gc
622 import gc
624 gc.collect() # xxx needed?
623 gc.collect() # xxx needed?
625
624
@@ -1,301 +1,300 b''
1 # -*- coding: utf-8 -*-
1 # -*- coding: utf-8 -*-
2 """
2 """
3 Class and program to colorize python source code for ANSI terminals.
3 Class and program to colorize python source code for ANSI terminals.
4
4
5 Based on an HTML code highlighter by Jurgen Hermann found at:
5 Based on an HTML code highlighter by Jurgen Hermann found at:
6 http://aspn.activestate.com/ASPN/Cookbook/Python/Recipe/52298
6 http://aspn.activestate.com/ASPN/Cookbook/Python/Recipe/52298
7
7
8 Modifications by Fernando Perez (fperez@colorado.edu).
8 Modifications by Fernando Perez (fperez@colorado.edu).
9
9
10 Information on the original HTML highlighter follows:
10 Information on the original HTML highlighter follows:
11
11
12 MoinMoin - Python Source Parser
12 MoinMoin - Python Source Parser
13
13
14 Title: Colorize Python source using the built-in tokenizer
14 Title: Colorize Python source using the built-in tokenizer
15
15
16 Submitter: Jurgen Hermann
16 Submitter: Jurgen Hermann
17 Last Updated:2001/04/06
17 Last Updated:2001/04/06
18
18
19 Version no:1.2
19 Version no:1.2
20
20
21 Description:
21 Description:
22
22
23 This code is part of MoinMoin (http://moin.sourceforge.net/) and converts
23 This code is part of MoinMoin (http://moin.sourceforge.net/) and converts
24 Python source code to HTML markup, rendering comments, keywords,
24 Python source code to HTML markup, rendering comments, keywords,
25 operators, numeric and string literals in different colors.
25 operators, numeric and string literals in different colors.
26
26
27 It shows how to use the built-in keyword, token and tokenize modules to
27 It shows how to use the built-in keyword, token and tokenize modules to
28 scan Python source code and re-emit it with no changes to its original
28 scan Python source code and re-emit it with no changes to its original
29 formatting (which is the hard part).
29 formatting (which is the hard part).
30
30 """
31 $Id: PyColorize.py 2586 2007-08-06 19:30:09Z vivainio $"""
32
31
33 __all__ = ['ANSICodeColors','Parser']
32 __all__ = ['ANSICodeColors','Parser']
34
33
35 _scheme_default = 'Linux'
34 _scheme_default = 'Linux'
36
35
37 # Imports
36 # Imports
38 import cStringIO
37 import cStringIO
39 import keyword
38 import keyword
40 import os
39 import os
41 import optparse
40 import optparse
42 import string
41 import string
43 import sys
42 import sys
44 import token
43 import token
45 import tokenize
44 import tokenize
46
45
47 from IPython.ColorANSI import *
46 from IPython.ColorANSI import *
48
47
49 #############################################################################
48 #############################################################################
50 ### Python Source Parser (does Hilighting)
49 ### Python Source Parser (does Hilighting)
51 #############################################################################
50 #############################################################################
52
51
53 _KEYWORD = token.NT_OFFSET + 1
52 _KEYWORD = token.NT_OFFSET + 1
54 _TEXT = token.NT_OFFSET + 2
53 _TEXT = token.NT_OFFSET + 2
55
54
56 #****************************************************************************
55 #****************************************************************************
57 # Builtin color schemes
56 # Builtin color schemes
58
57
59 Colors = TermColors # just a shorthand
58 Colors = TermColors # just a shorthand
60
59
61 # Build a few color schemes
60 # Build a few color schemes
62 NoColor = ColorScheme(
61 NoColor = ColorScheme(
63 'NoColor',{
62 'NoColor',{
64 token.NUMBER : Colors.NoColor,
63 token.NUMBER : Colors.NoColor,
65 token.OP : Colors.NoColor,
64 token.OP : Colors.NoColor,
66 token.STRING : Colors.NoColor,
65 token.STRING : Colors.NoColor,
67 tokenize.COMMENT : Colors.NoColor,
66 tokenize.COMMENT : Colors.NoColor,
68 token.NAME : Colors.NoColor,
67 token.NAME : Colors.NoColor,
69 token.ERRORTOKEN : Colors.NoColor,
68 token.ERRORTOKEN : Colors.NoColor,
70
69
71 _KEYWORD : Colors.NoColor,
70 _KEYWORD : Colors.NoColor,
72 _TEXT : Colors.NoColor,
71 _TEXT : Colors.NoColor,
73
72
74 'normal' : Colors.NoColor # color off (usu. Colors.Normal)
73 'normal' : Colors.NoColor # color off (usu. Colors.Normal)
75 } )
74 } )
76
75
77 LinuxColors = ColorScheme(
76 LinuxColors = ColorScheme(
78 'Linux',{
77 'Linux',{
79 token.NUMBER : Colors.LightCyan,
78 token.NUMBER : Colors.LightCyan,
80 token.OP : Colors.Yellow,
79 token.OP : Colors.Yellow,
81 token.STRING : Colors.LightBlue,
80 token.STRING : Colors.LightBlue,
82 tokenize.COMMENT : Colors.LightRed,
81 tokenize.COMMENT : Colors.LightRed,
83 token.NAME : Colors.White,
82 token.NAME : Colors.White,
84 token.ERRORTOKEN : Colors.Red,
83 token.ERRORTOKEN : Colors.Red,
85
84
86 _KEYWORD : Colors.LightGreen,
85 _KEYWORD : Colors.LightGreen,
87 _TEXT : Colors.Yellow,
86 _TEXT : Colors.Yellow,
88
87
89 'normal' : Colors.Normal # color off (usu. Colors.Normal)
88 'normal' : Colors.Normal # color off (usu. Colors.Normal)
90 } )
89 } )
91
90
92 LightBGColors = ColorScheme(
91 LightBGColors = ColorScheme(
93 'LightBG',{
92 'LightBG',{
94 token.NUMBER : Colors.Cyan,
93 token.NUMBER : Colors.Cyan,
95 token.OP : Colors.Blue,
94 token.OP : Colors.Blue,
96 token.STRING : Colors.Blue,
95 token.STRING : Colors.Blue,
97 tokenize.COMMENT : Colors.Red,
96 tokenize.COMMENT : Colors.Red,
98 token.NAME : Colors.Black,
97 token.NAME : Colors.Black,
99 token.ERRORTOKEN : Colors.Red,
98 token.ERRORTOKEN : Colors.Red,
100
99
101 _KEYWORD : Colors.Green,
100 _KEYWORD : Colors.Green,
102 _TEXT : Colors.Blue,
101 _TEXT : Colors.Blue,
103
102
104 'normal' : Colors.Normal # color off (usu. Colors.Normal)
103 'normal' : Colors.Normal # color off (usu. Colors.Normal)
105 } )
104 } )
106
105
107 # Build table of color schemes (needed by the parser)
106 # Build table of color schemes (needed by the parser)
108 ANSICodeColors = ColorSchemeTable([NoColor,LinuxColors,LightBGColors],
107 ANSICodeColors = ColorSchemeTable([NoColor,LinuxColors,LightBGColors],
109 _scheme_default)
108 _scheme_default)
110
109
111 class Parser:
110 class Parser:
112 """ Format colored Python source.
111 """ Format colored Python source.
113 """
112 """
114
113
115 def __init__(self, color_table=None,out = sys.stdout):
114 def __init__(self, color_table=None,out = sys.stdout):
116 """ Create a parser with a specified color table and output channel.
115 """ Create a parser with a specified color table and output channel.
117
116
118 Call format() to process code.
117 Call format() to process code.
119 """
118 """
120 self.color_table = color_table and color_table or ANSICodeColors
119 self.color_table = color_table and color_table or ANSICodeColors
121 self.out = out
120 self.out = out
122
121
123 def format(self, raw, out = None, scheme = ''):
122 def format(self, raw, out = None, scheme = ''):
124 return self.format2(raw, out, scheme)[0]
123 return self.format2(raw, out, scheme)[0]
125
124
126 def format2(self, raw, out = None, scheme = ''):
125 def format2(self, raw, out = None, scheme = ''):
127 """ Parse and send the colored source.
126 """ Parse and send the colored source.
128
127
129 If out and scheme are not specified, the defaults (given to
128 If out and scheme are not specified, the defaults (given to
130 constructor) are used.
129 constructor) are used.
131
130
132 out should be a file-type object. Optionally, out can be given as the
131 out should be a file-type object. Optionally, out can be given as the
133 string 'str' and the parser will automatically return the output in a
132 string 'str' and the parser will automatically return the output in a
134 string."""
133 string."""
135
134
136 string_output = 0
135 string_output = 0
137 if out == 'str' or self.out == 'str' or \
136 if out == 'str' or self.out == 'str' or \
138 isinstance(self.out,cStringIO.OutputType):
137 isinstance(self.out,cStringIO.OutputType):
139 # XXX - I don't really like this state handling logic, but at this
138 # XXX - I don't really like this state handling logic, but at this
140 # point I don't want to make major changes, so adding the
139 # point I don't want to make major changes, so adding the
141 # isinstance() check is the simplest I can do to ensure correct
140 # isinstance() check is the simplest I can do to ensure correct
142 # behavior.
141 # behavior.
143 out_old = self.out
142 out_old = self.out
144 self.out = cStringIO.StringIO()
143 self.out = cStringIO.StringIO()
145 string_output = 1
144 string_output = 1
146 elif out is not None:
145 elif out is not None:
147 self.out = out
146 self.out = out
148
147
149 # Fast return of the unmodified input for NoColor scheme
148 # Fast return of the unmodified input for NoColor scheme
150 if scheme == 'NoColor':
149 if scheme == 'NoColor':
151 error = False
150 error = False
152 self.out.write(raw)
151 self.out.write(raw)
153 if string_output:
152 if string_output:
154 return raw,error
153 return raw,error
155 else:
154 else:
156 return None,error
155 return None,error
157
156
158 # local shorthands
157 # local shorthands
159 colors = self.color_table[scheme].colors
158 colors = self.color_table[scheme].colors
160 self.colors = colors # put in object so __call__ sees it
159 self.colors = colors # put in object so __call__ sees it
161
160
162 # Remove trailing whitespace and normalize tabs
161 # Remove trailing whitespace and normalize tabs
163 self.raw = raw.expandtabs().rstrip()
162 self.raw = raw.expandtabs().rstrip()
164
163
165 # store line offsets in self.lines
164 # store line offsets in self.lines
166 self.lines = [0, 0]
165 self.lines = [0, 0]
167 pos = 0
166 pos = 0
168 raw_find = self.raw.find
167 raw_find = self.raw.find
169 lines_append = self.lines.append
168 lines_append = self.lines.append
170 while 1:
169 while 1:
171 pos = raw_find('\n', pos) + 1
170 pos = raw_find('\n', pos) + 1
172 if not pos: break
171 if not pos: break
173 lines_append(pos)
172 lines_append(pos)
174 lines_append(len(self.raw))
173 lines_append(len(self.raw))
175
174
176 # parse the source and write it
175 # parse the source and write it
177 self.pos = 0
176 self.pos = 0
178 text = cStringIO.StringIO(self.raw)
177 text = cStringIO.StringIO(self.raw)
179
178
180 error = False
179 error = False
181 try:
180 try:
182 tokenize.tokenize(text.readline, self)
181 tokenize.tokenize(text.readline, self)
183 except tokenize.TokenError, ex:
182 except tokenize.TokenError, ex:
184 msg = ex[0]
183 msg = ex[0]
185 line = ex[1][0]
184 line = ex[1][0]
186 self.out.write("%s\n\n*** ERROR: %s%s%s\n" %
185 self.out.write("%s\n\n*** ERROR: %s%s%s\n" %
187 (colors[token.ERRORTOKEN],
186 (colors[token.ERRORTOKEN],
188 msg, self.raw[self.lines[line]:],
187 msg, self.raw[self.lines[line]:],
189 colors.normal)
188 colors.normal)
190 )
189 )
191 error = True
190 error = True
192 self.out.write(colors.normal+'\n')
191 self.out.write(colors.normal+'\n')
193 if string_output:
192 if string_output:
194 output = self.out.getvalue()
193 output = self.out.getvalue()
195 self.out = out_old
194 self.out = out_old
196 return (output, error)
195 return (output, error)
197 return (None, error)
196 return (None, error)
198
197
199 def __call__(self, toktype, toktext, (srow,scol), (erow,ecol), line):
198 def __call__(self, toktype, toktext, (srow,scol), (erow,ecol), line):
200 """ Token handler, with syntax highlighting."""
199 """ Token handler, with syntax highlighting."""
201
200
202 # local shorthands
201 # local shorthands
203 colors = self.colors
202 colors = self.colors
204 owrite = self.out.write
203 owrite = self.out.write
205
204
206 # line separator, so this works across platforms
205 # line separator, so this works across platforms
207 linesep = os.linesep
206 linesep = os.linesep
208
207
209 # calculate new positions
208 # calculate new positions
210 oldpos = self.pos
209 oldpos = self.pos
211 newpos = self.lines[srow] + scol
210 newpos = self.lines[srow] + scol
212 self.pos = newpos + len(toktext)
211 self.pos = newpos + len(toktext)
213
212
214 # handle newlines
213 # handle newlines
215 if toktype in [token.NEWLINE, tokenize.NL]:
214 if toktype in [token.NEWLINE, tokenize.NL]:
216 owrite(linesep)
215 owrite(linesep)
217 return
216 return
218
217
219 # send the original whitespace, if needed
218 # send the original whitespace, if needed
220 if newpos > oldpos:
219 if newpos > oldpos:
221 owrite(self.raw[oldpos:newpos])
220 owrite(self.raw[oldpos:newpos])
222
221
223 # skip indenting tokens
222 # skip indenting tokens
224 if toktype in [token.INDENT, token.DEDENT]:
223 if toktype in [token.INDENT, token.DEDENT]:
225 self.pos = newpos
224 self.pos = newpos
226 return
225 return
227
226
228 # map token type to a color group
227 # map token type to a color group
229 if token.LPAR <= toktype and toktype <= token.OP:
228 if token.LPAR <= toktype and toktype <= token.OP:
230 toktype = token.OP
229 toktype = token.OP
231 elif toktype == token.NAME and keyword.iskeyword(toktext):
230 elif toktype == token.NAME and keyword.iskeyword(toktext):
232 toktype = _KEYWORD
231 toktype = _KEYWORD
233 color = colors.get(toktype, colors[_TEXT])
232 color = colors.get(toktype, colors[_TEXT])
234
233
235 #print '<%s>' % toktext, # dbg
234 #print '<%s>' % toktext, # dbg
236
235
237 # Triple quoted strings must be handled carefully so that backtracking
236 # Triple quoted strings must be handled carefully so that backtracking
238 # in pagers works correctly. We need color terminators on _each_ line.
237 # in pagers works correctly. We need color terminators on _each_ line.
239 if linesep in toktext:
238 if linesep in toktext:
240 toktext = toktext.replace(linesep, '%s%s%s' %
239 toktext = toktext.replace(linesep, '%s%s%s' %
241 (colors.normal,linesep,color))
240 (colors.normal,linesep,color))
242
241
243 # send text
242 # send text
244 owrite('%s%s%s' % (color,toktext,colors.normal))
243 owrite('%s%s%s' % (color,toktext,colors.normal))
245
244
246 def main(argv=None):
245 def main(argv=None):
247 """Run as a command-line script: colorize a python file or stdin using ANSI
246 """Run as a command-line script: colorize a python file or stdin using ANSI
248 color escapes and print to stdout.
247 color escapes and print to stdout.
249
248
250 Inputs:
249 Inputs:
251
250
252 - argv(None): a list of strings like sys.argv[1:] giving the command-line
251 - argv(None): a list of strings like sys.argv[1:] giving the command-line
253 arguments. If None, use sys.argv[1:].
252 arguments. If None, use sys.argv[1:].
254 """
253 """
255
254
256 usage_msg = """%prog [options] [filename]
255 usage_msg = """%prog [options] [filename]
257
256
258 Colorize a python file or stdin using ANSI color escapes and print to stdout.
257 Colorize a python file or stdin using ANSI color escapes and print to stdout.
259 If no filename is given, or if filename is -, read standard input."""
258 If no filename is given, or if filename is -, read standard input."""
260
259
261 parser = optparse.OptionParser(usage=usage_msg)
260 parser = optparse.OptionParser(usage=usage_msg)
262 newopt = parser.add_option
261 newopt = parser.add_option
263 newopt('-s','--scheme',metavar='NAME',dest='scheme_name',action='store',
262 newopt('-s','--scheme',metavar='NAME',dest='scheme_name',action='store',
264 choices=['Linux','LightBG','NoColor'],default=_scheme_default,
263 choices=['Linux','LightBG','NoColor'],default=_scheme_default,
265 help="give the color scheme to use. Currently only 'Linux'\
264 help="give the color scheme to use. Currently only 'Linux'\
266 (default) and 'LightBG' and 'NoColor' are implemented (give without\
265 (default) and 'LightBG' and 'NoColor' are implemented (give without\
267 quotes)")
266 quotes)")
268
267
269 opts,args = parser.parse_args(argv)
268 opts,args = parser.parse_args(argv)
270
269
271 if len(args) > 1:
270 if len(args) > 1:
272 parser.error("you must give at most one filename.")
271 parser.error("you must give at most one filename.")
273
272
274 if len(args) == 0:
273 if len(args) == 0:
275 fname = '-' # no filename given; setup to read from stdin
274 fname = '-' # no filename given; setup to read from stdin
276 else:
275 else:
277 fname = args[0]
276 fname = args[0]
278
277
279 if fname == '-':
278 if fname == '-':
280 stream = sys.stdin
279 stream = sys.stdin
281 else:
280 else:
282 stream = file(fname)
281 stream = file(fname)
283
282
284 parser = Parser()
283 parser = Parser()
285
284
286 # we need nested try blocks because pre-2.5 python doesn't support unified
285 # we need nested try blocks because pre-2.5 python doesn't support unified
287 # try-except-finally
286 # try-except-finally
288 try:
287 try:
289 try:
288 try:
290 # write colorized version to stdout
289 # write colorized version to stdout
291 parser.format(stream.read(),scheme=opts.scheme_name)
290 parser.format(stream.read(),scheme=opts.scheme_name)
292 except IOError,msg:
291 except IOError,msg:
293 # if user reads through a pager and quits, don't print traceback
292 # if user reads through a pager and quits, don't print traceback
294 if msg.args != (32,'Broken pipe'):
293 if msg.args != (32,'Broken pipe'):
295 raise
294 raise
296 finally:
295 finally:
297 if stream is not sys.stdin:
296 if stream is not sys.stdin:
298 stream.close() # in case a non-handled exception happened above
297 stream.close() # in case a non-handled exception happened above
299
298
300 if __name__ == "__main__":
299 if __name__ == "__main__":
301 main()
300 main()
@@ -1,1238 +1,1233 b''
1 # -*- coding: utf-8 -*-
1 # -*- coding: utf-8 -*-
2 """IPython Shell classes.
2 """IPython Shell classes.
3
3
4 All the matplotlib support code was co-developed with John Hunter,
4 All the matplotlib support code was co-developed with John Hunter,
5 matplotlib's author.
5 matplotlib's author.
6
6 """
7 $Id: Shell.py 3024 2008-02-07 15:34:42Z darren.dale $"""
8
7
9 #*****************************************************************************
8 #*****************************************************************************
10 # Copyright (C) 2001-2006 Fernando Perez <fperez@colorado.edu>
9 # Copyright (C) 2001-2006 Fernando Perez <fperez@colorado.edu>
11 #
10 #
12 # Distributed under the terms of the BSD License. The full license is in
11 # Distributed under the terms of the BSD License. The full license is in
13 # the file COPYING, distributed as part of this software.
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 # Code begins
15 # Code begins
21 # Stdlib imports
16 # Stdlib imports
22 import __builtin__
17 import __builtin__
23 import __main__
18 import __main__
24 import Queue
19 import Queue
25 import inspect
20 import inspect
26 import os
21 import os
27 import sys
22 import sys
28 import thread
23 import thread
29 import threading
24 import threading
30 import time
25 import time
31
26
32 from signal import signal, SIGINT
27 from signal import signal, SIGINT
33
28
34 try:
29 try:
35 import ctypes
30 import ctypes
36 HAS_CTYPES = True
31 HAS_CTYPES = True
37 except ImportError:
32 except ImportError:
38 HAS_CTYPES = False
33 HAS_CTYPES = False
39
34
40 # IPython imports
35 # IPython imports
41 import IPython
36 import IPython
42 from IPython import ultraTB, ipapi
37 from IPython import ultraTB, ipapi
43 from IPython.Magic import Magic
38 from IPython.Magic import Magic
44 from IPython.genutils import Term,warn,error,flag_calls, ask_yes_no
39 from IPython.genutils import Term,warn,error,flag_calls, ask_yes_no
45 from IPython.iplib import InteractiveShell
40 from IPython.iplib import InteractiveShell
46 from IPython.ipmaker import make_IPython
41 from IPython.ipmaker import make_IPython
47 from IPython.ipstruct import Struct
42 from IPython.ipstruct import Struct
48 from IPython.testing import decorators as testdec
43 from IPython.testing import decorators as testdec
49
44
50 # Globals
45 # Globals
51 # global flag to pass around information about Ctrl-C without exceptions
46 # global flag to pass around information about Ctrl-C without exceptions
52 KBINT = False
47 KBINT = False
53
48
54 # global flag to turn on/off Tk support.
49 # global flag to turn on/off Tk support.
55 USE_TK = False
50 USE_TK = False
56
51
57 # ID for the main thread, used for cross-thread exceptions
52 # ID for the main thread, used for cross-thread exceptions
58 MAIN_THREAD_ID = thread.get_ident()
53 MAIN_THREAD_ID = thread.get_ident()
59
54
60 # Tag when runcode() is active, for exception handling
55 # Tag when runcode() is active, for exception handling
61 CODE_RUN = None
56 CODE_RUN = None
62
57
63 # Default timeout for waiting for multithreaded shells (in seconds)
58 # Default timeout for waiting for multithreaded shells (in seconds)
64 GUI_TIMEOUT = 10
59 GUI_TIMEOUT = 10
65
60
66 #-----------------------------------------------------------------------------
61 #-----------------------------------------------------------------------------
67 # This class is trivial now, but I want to have it in to publish a clean
62 # This class is trivial now, but I want to have it in to publish a clean
68 # interface. Later when the internals are reorganized, code that uses this
63 # interface. Later when the internals are reorganized, code that uses this
69 # shouldn't have to change.
64 # shouldn't have to change.
70
65
71 class IPShell:
66 class IPShell:
72 """Create an IPython instance."""
67 """Create an IPython instance."""
73
68
74 def __init__(self,argv=None,user_ns=None,user_global_ns=None,
69 def __init__(self,argv=None,user_ns=None,user_global_ns=None,
75 debug=1,shell_class=InteractiveShell):
70 debug=1,shell_class=InteractiveShell):
76 self.IP = make_IPython(argv,user_ns=user_ns,
71 self.IP = make_IPython(argv,user_ns=user_ns,
77 user_global_ns=user_global_ns,
72 user_global_ns=user_global_ns,
78 debug=debug,shell_class=shell_class)
73 debug=debug,shell_class=shell_class)
79
74
80 def mainloop(self,sys_exit=0,banner=None):
75 def mainloop(self,sys_exit=0,banner=None):
81 self.IP.mainloop(banner)
76 self.IP.mainloop(banner)
82 if sys_exit:
77 if sys_exit:
83 sys.exit()
78 sys.exit()
84
79
85 #-----------------------------------------------------------------------------
80 #-----------------------------------------------------------------------------
86 def kill_embedded(self,parameter_s=''):
81 def kill_embedded(self,parameter_s=''):
87 """%kill_embedded : deactivate for good the current embedded IPython.
82 """%kill_embedded : deactivate for good the current embedded IPython.
88
83
89 This function (after asking for confirmation) sets an internal flag so that
84 This function (after asking for confirmation) sets an internal flag so that
90 an embedded IPython will never activate again. This is useful to
85 an embedded IPython will never activate again. This is useful to
91 permanently disable a shell that is being called inside a loop: once you've
86 permanently disable a shell that is being called inside a loop: once you've
92 figured out what you needed from it, you may then kill it and the program
87 figured out what you needed from it, you may then kill it and the program
93 will then continue to run without the interactive shell interfering again.
88 will then continue to run without the interactive shell interfering again.
94 """
89 """
95
90
96 kill = ask_yes_no("Are you sure you want to kill this embedded instance "
91 kill = ask_yes_no("Are you sure you want to kill this embedded instance "
97 "(y/n)? [y/N] ",'n')
92 "(y/n)? [y/N] ",'n')
98 if kill:
93 if kill:
99 self.shell.embedded_active = False
94 self.shell.embedded_active = False
100 print "This embedded IPython will not reactivate anymore once you exit."
95 print "This embedded IPython will not reactivate anymore once you exit."
101
96
102 class IPShellEmbed:
97 class IPShellEmbed:
103 """Allow embedding an IPython shell into a running program.
98 """Allow embedding an IPython shell into a running program.
104
99
105 Instances of this class are callable, with the __call__ method being an
100 Instances of this class are callable, with the __call__ method being an
106 alias to the embed() method of an InteractiveShell instance.
101 alias to the embed() method of an InteractiveShell instance.
107
102
108 Usage (see also the example-embed.py file for a running example):
103 Usage (see also the example-embed.py file for a running example):
109
104
110 ipshell = IPShellEmbed([argv,banner,exit_msg,rc_override])
105 ipshell = IPShellEmbed([argv,banner,exit_msg,rc_override])
111
106
112 - argv: list containing valid command-line options for IPython, as they
107 - argv: list containing valid command-line options for IPython, as they
113 would appear in sys.argv[1:].
108 would appear in sys.argv[1:].
114
109
115 For example, the following command-line options:
110 For example, the following command-line options:
116
111
117 $ ipython -prompt_in1 'Input <\\#>' -colors LightBG
112 $ ipython -prompt_in1 'Input <\\#>' -colors LightBG
118
113
119 would be passed in the argv list as:
114 would be passed in the argv list as:
120
115
121 ['-prompt_in1','Input <\\#>','-colors','LightBG']
116 ['-prompt_in1','Input <\\#>','-colors','LightBG']
122
117
123 - banner: string which gets printed every time the interpreter starts.
118 - banner: string which gets printed every time the interpreter starts.
124
119
125 - exit_msg: string which gets printed every time the interpreter exits.
120 - exit_msg: string which gets printed every time the interpreter exits.
126
121
127 - rc_override: a dict or Struct of configuration options such as those
122 - rc_override: a dict or Struct of configuration options such as those
128 used by IPython. These options are read from your ~/.ipython/ipythonrc
123 used by IPython. These options are read from your ~/.ipython/ipythonrc
129 file when the Shell object is created. Passing an explicit rc_override
124 file when the Shell object is created. Passing an explicit rc_override
130 dict with any options you want allows you to override those values at
125 dict with any options you want allows you to override those values at
131 creation time without having to modify the file. This way you can create
126 creation time without having to modify the file. This way you can create
132 embeddable instances configured in any way you want without editing any
127 embeddable instances configured in any way you want without editing any
133 global files (thus keeping your interactive IPython configuration
128 global files (thus keeping your interactive IPython configuration
134 unchanged).
129 unchanged).
135
130
136 Then the ipshell instance can be called anywhere inside your code:
131 Then the ipshell instance can be called anywhere inside your code:
137
132
138 ipshell(header='') -> Opens up an IPython shell.
133 ipshell(header='') -> Opens up an IPython shell.
139
134
140 - header: string printed by the IPython shell upon startup. This can let
135 - header: string printed by the IPython shell upon startup. This can let
141 you know where in your code you are when dropping into the shell. Note
136 you know where in your code you are when dropping into the shell. Note
142 that 'banner' gets prepended to all calls, so header is used for
137 that 'banner' gets prepended to all calls, so header is used for
143 location-specific information.
138 location-specific information.
144
139
145 For more details, see the __call__ method below.
140 For more details, see the __call__ method below.
146
141
147 When the IPython shell is exited with Ctrl-D, normal program execution
142 When the IPython shell is exited with Ctrl-D, normal program execution
148 resumes.
143 resumes.
149
144
150 This functionality was inspired by a posting on comp.lang.python by cmkl
145 This functionality was inspired by a posting on comp.lang.python by cmkl
151 <cmkleffner@gmx.de> on Dec. 06/01 concerning similar uses of pyrepl, and
146 <cmkleffner@gmx.de> on Dec. 06/01 concerning similar uses of pyrepl, and
152 by the IDL stop/continue commands."""
147 by the IDL stop/continue commands."""
153
148
154 def __init__(self,argv=None,banner='',exit_msg=None,rc_override=None,
149 def __init__(self,argv=None,banner='',exit_msg=None,rc_override=None,
155 user_ns=None):
150 user_ns=None):
156 """Note that argv here is a string, NOT a list."""
151 """Note that argv here is a string, NOT a list."""
157 self.set_banner(banner)
152 self.set_banner(banner)
158 self.set_exit_msg(exit_msg)
153 self.set_exit_msg(exit_msg)
159 self.set_dummy_mode(0)
154 self.set_dummy_mode(0)
160
155
161 # sys.displayhook is a global, we need to save the user's original
156 # sys.displayhook is a global, we need to save the user's original
162 # Don't rely on __displayhook__, as the user may have changed that.
157 # Don't rely on __displayhook__, as the user may have changed that.
163 self.sys_displayhook_ori = sys.displayhook
158 self.sys_displayhook_ori = sys.displayhook
164
159
165 # save readline completer status
160 # save readline completer status
166 try:
161 try:
167 #print 'Save completer',sys.ipcompleter # dbg
162 #print 'Save completer',sys.ipcompleter # dbg
168 self.sys_ipcompleter_ori = sys.ipcompleter
163 self.sys_ipcompleter_ori = sys.ipcompleter
169 except:
164 except:
170 pass # not nested with IPython
165 pass # not nested with IPython
171
166
172 self.IP = make_IPython(argv,rc_override=rc_override,
167 self.IP = make_IPython(argv,rc_override=rc_override,
173 embedded=True,
168 embedded=True,
174 user_ns=user_ns)
169 user_ns=user_ns)
175
170
176 ip = ipapi.IPApi(self.IP)
171 ip = ipapi.IPApi(self.IP)
177 ip.expose_magic("kill_embedded",kill_embedded)
172 ip.expose_magic("kill_embedded",kill_embedded)
178
173
179 # copy our own displayhook also
174 # copy our own displayhook also
180 self.sys_displayhook_embed = sys.displayhook
175 self.sys_displayhook_embed = sys.displayhook
181 # and leave the system's display hook clean
176 # and leave the system's display hook clean
182 sys.displayhook = self.sys_displayhook_ori
177 sys.displayhook = self.sys_displayhook_ori
183 # don't use the ipython crash handler so that user exceptions aren't
178 # don't use the ipython crash handler so that user exceptions aren't
184 # trapped
179 # trapped
185 sys.excepthook = ultraTB.FormattedTB(color_scheme = self.IP.rc.colors,
180 sys.excepthook = ultraTB.FormattedTB(color_scheme = self.IP.rc.colors,
186 mode = self.IP.rc.xmode,
181 mode = self.IP.rc.xmode,
187 call_pdb = self.IP.rc.pdb)
182 call_pdb = self.IP.rc.pdb)
188 self.restore_system_completer()
183 self.restore_system_completer()
189
184
190 def restore_system_completer(self):
185 def restore_system_completer(self):
191 """Restores the readline completer which was in place.
186 """Restores the readline completer which was in place.
192
187
193 This allows embedded IPython within IPython not to disrupt the
188 This allows embedded IPython within IPython not to disrupt the
194 parent's completion.
189 parent's completion.
195 """
190 """
196
191
197 try:
192 try:
198 self.IP.readline.set_completer(self.sys_ipcompleter_ori)
193 self.IP.readline.set_completer(self.sys_ipcompleter_ori)
199 sys.ipcompleter = self.sys_ipcompleter_ori
194 sys.ipcompleter = self.sys_ipcompleter_ori
200 except:
195 except:
201 pass
196 pass
202
197
203 def __call__(self,header='',local_ns=None,global_ns=None,dummy=None):
198 def __call__(self,header='',local_ns=None,global_ns=None,dummy=None):
204 """Activate the interactive interpreter.
199 """Activate the interactive interpreter.
205
200
206 __call__(self,header='',local_ns=None,global_ns,dummy=None) -> Start
201 __call__(self,header='',local_ns=None,global_ns,dummy=None) -> Start
207 the interpreter shell with the given local and global namespaces, and
202 the interpreter shell with the given local and global namespaces, and
208 optionally print a header string at startup.
203 optionally print a header string at startup.
209
204
210 The shell can be globally activated/deactivated using the
205 The shell can be globally activated/deactivated using the
211 set/get_dummy_mode methods. This allows you to turn off a shell used
206 set/get_dummy_mode methods. This allows you to turn off a shell used
212 for debugging globally.
207 for debugging globally.
213
208
214 However, *each* time you call the shell you can override the current
209 However, *each* time you call the shell you can override the current
215 state of dummy_mode with the optional keyword parameter 'dummy'. For
210 state of dummy_mode with the optional keyword parameter 'dummy'. For
216 example, if you set dummy mode on with IPShell.set_dummy_mode(1), you
211 example, if you set dummy mode on with IPShell.set_dummy_mode(1), you
217 can still have a specific call work by making it as IPShell(dummy=0).
212 can still have a specific call work by making it as IPShell(dummy=0).
218
213
219 The optional keyword parameter dummy controls whether the call
214 The optional keyword parameter dummy controls whether the call
220 actually does anything. """
215 actually does anything. """
221
216
222 # If the user has turned it off, go away
217 # If the user has turned it off, go away
223 if not self.IP.embedded_active:
218 if not self.IP.embedded_active:
224 return
219 return
225
220
226 # Normal exits from interactive mode set this flag, so the shell can't
221 # Normal exits from interactive mode set this flag, so the shell can't
227 # re-enter (it checks this variable at the start of interactive mode).
222 # re-enter (it checks this variable at the start of interactive mode).
228 self.IP.exit_now = False
223 self.IP.exit_now = False
229
224
230 # Allow the dummy parameter to override the global __dummy_mode
225 # Allow the dummy parameter to override the global __dummy_mode
231 if dummy or (dummy != 0 and self.__dummy_mode):
226 if dummy or (dummy != 0 and self.__dummy_mode):
232 return
227 return
233
228
234 # Set global subsystems (display,completions) to our values
229 # Set global subsystems (display,completions) to our values
235 sys.displayhook = self.sys_displayhook_embed
230 sys.displayhook = self.sys_displayhook_embed
236 if self.IP.has_readline:
231 if self.IP.has_readline:
237 self.IP.set_completer()
232 self.IP.set_completer()
238
233
239 if self.banner and header:
234 if self.banner and header:
240 format = '%s\n%s\n'
235 format = '%s\n%s\n'
241 else:
236 else:
242 format = '%s%s\n'
237 format = '%s%s\n'
243 banner = format % (self.banner,header)
238 banner = format % (self.banner,header)
244
239
245 # Call the embedding code with a stack depth of 1 so it can skip over
240 # Call the embedding code with a stack depth of 1 so it can skip over
246 # our call and get the original caller's namespaces.
241 # our call and get the original caller's namespaces.
247 self.IP.embed_mainloop(banner,local_ns,global_ns,stack_depth=1)
242 self.IP.embed_mainloop(banner,local_ns,global_ns,stack_depth=1)
248
243
249 if self.exit_msg:
244 if self.exit_msg:
250 print self.exit_msg
245 print self.exit_msg
251
246
252 # Restore global systems (display, completion)
247 # Restore global systems (display, completion)
253 sys.displayhook = self.sys_displayhook_ori
248 sys.displayhook = self.sys_displayhook_ori
254 self.restore_system_completer()
249 self.restore_system_completer()
255
250
256 def set_dummy_mode(self,dummy):
251 def set_dummy_mode(self,dummy):
257 """Sets the embeddable shell's dummy mode parameter.
252 """Sets the embeddable shell's dummy mode parameter.
258
253
259 set_dummy_mode(dummy): dummy = 0 or 1.
254 set_dummy_mode(dummy): dummy = 0 or 1.
260
255
261 This parameter is persistent and makes calls to the embeddable shell
256 This parameter is persistent and makes calls to the embeddable shell
262 silently return without performing any action. This allows you to
257 silently return without performing any action. This allows you to
263 globally activate or deactivate a shell you're using with a single call.
258 globally activate or deactivate a shell you're using with a single call.
264
259
265 If you need to manually"""
260 If you need to manually"""
266
261
267 if dummy not in [0,1,False,True]:
262 if dummy not in [0,1,False,True]:
268 raise ValueError,'dummy parameter must be boolean'
263 raise ValueError,'dummy parameter must be boolean'
269 self.__dummy_mode = dummy
264 self.__dummy_mode = dummy
270
265
271 def get_dummy_mode(self):
266 def get_dummy_mode(self):
272 """Return the current value of the dummy mode parameter.
267 """Return the current value of the dummy mode parameter.
273 """
268 """
274 return self.__dummy_mode
269 return self.__dummy_mode
275
270
276 def set_banner(self,banner):
271 def set_banner(self,banner):
277 """Sets the global banner.
272 """Sets the global banner.
278
273
279 This banner gets prepended to every header printed when the shell
274 This banner gets prepended to every header printed when the shell
280 instance is called."""
275 instance is called."""
281
276
282 self.banner = banner
277 self.banner = banner
283
278
284 def set_exit_msg(self,exit_msg):
279 def set_exit_msg(self,exit_msg):
285 """Sets the global exit_msg.
280 """Sets the global exit_msg.
286
281
287 This exit message gets printed upon exiting every time the embedded
282 This exit message gets printed upon exiting every time the embedded
288 shell is called. It is None by default. """
283 shell is called. It is None by default. """
289
284
290 self.exit_msg = exit_msg
285 self.exit_msg = exit_msg
291
286
292 #-----------------------------------------------------------------------------
287 #-----------------------------------------------------------------------------
293 if HAS_CTYPES:
288 if HAS_CTYPES:
294 # Add async exception support. Trick taken from:
289 # Add async exception support. Trick taken from:
295 # http://sebulba.wikispaces.com/recipe+thread2
290 # http://sebulba.wikispaces.com/recipe+thread2
296 def _async_raise(tid, exctype):
291 def _async_raise(tid, exctype):
297 """raises the exception, performs cleanup if needed"""
292 """raises the exception, performs cleanup if needed"""
298 if not inspect.isclass(exctype):
293 if not inspect.isclass(exctype):
299 raise TypeError("Only types can be raised (not instances)")
294 raise TypeError("Only types can be raised (not instances)")
300 res = ctypes.pythonapi.PyThreadState_SetAsyncExc(tid,
295 res = ctypes.pythonapi.PyThreadState_SetAsyncExc(tid,
301 ctypes.py_object(exctype))
296 ctypes.py_object(exctype))
302 if res == 0:
297 if res == 0:
303 raise ValueError("invalid thread id")
298 raise ValueError("invalid thread id")
304 elif res != 1:
299 elif res != 1:
305 # """if it returns a number greater than one, you're in trouble,
300 # """if it returns a number greater than one, you're in trouble,
306 # and you should call it again with exc=NULL to revert the effect"""
301 # and you should call it again with exc=NULL to revert the effect"""
307 ctypes.pythonapi.PyThreadState_SetAsyncExc(tid, 0)
302 ctypes.pythonapi.PyThreadState_SetAsyncExc(tid, 0)
308 raise SystemError("PyThreadState_SetAsyncExc failed")
303 raise SystemError("PyThreadState_SetAsyncExc failed")
309
304
310 def sigint_handler (signum,stack_frame):
305 def sigint_handler (signum,stack_frame):
311 """Sigint handler for threaded apps.
306 """Sigint handler for threaded apps.
312
307
313 This is a horrible hack to pass information about SIGINT _without_
308 This is a horrible hack to pass information about SIGINT _without_
314 using exceptions, since I haven't been able to properly manage
309 using exceptions, since I haven't been able to properly manage
315 cross-thread exceptions in GTK/WX. In fact, I don't think it can be
310 cross-thread exceptions in GTK/WX. In fact, I don't think it can be
316 done (or at least that's my understanding from a c.l.py thread where
311 done (or at least that's my understanding from a c.l.py thread where
317 this was discussed)."""
312 this was discussed)."""
318
313
319 global KBINT
314 global KBINT
320
315
321 if CODE_RUN:
316 if CODE_RUN:
322 _async_raise(MAIN_THREAD_ID,KeyboardInterrupt)
317 _async_raise(MAIN_THREAD_ID,KeyboardInterrupt)
323 else:
318 else:
324 KBINT = True
319 KBINT = True
325 print '\nKeyboardInterrupt - Press <Enter> to continue.',
320 print '\nKeyboardInterrupt - Press <Enter> to continue.',
326 Term.cout.flush()
321 Term.cout.flush()
327
322
328 else:
323 else:
329 def sigint_handler (signum,stack_frame):
324 def sigint_handler (signum,stack_frame):
330 """Sigint handler for threaded apps.
325 """Sigint handler for threaded apps.
331
326
332 This is a horrible hack to pass information about SIGINT _without_
327 This is a horrible hack to pass information about SIGINT _without_
333 using exceptions, since I haven't been able to properly manage
328 using exceptions, since I haven't been able to properly manage
334 cross-thread exceptions in GTK/WX. In fact, I don't think it can be
329 cross-thread exceptions in GTK/WX. In fact, I don't think it can be
335 done (or at least that's my understanding from a c.l.py thread where
330 done (or at least that's my understanding from a c.l.py thread where
336 this was discussed)."""
331 this was discussed)."""
337
332
338 global KBINT
333 global KBINT
339
334
340 print '\nKeyboardInterrupt - Press <Enter> to continue.',
335 print '\nKeyboardInterrupt - Press <Enter> to continue.',
341 Term.cout.flush()
336 Term.cout.flush()
342 # Set global flag so that runsource can know that Ctrl-C was hit
337 # Set global flag so that runsource can know that Ctrl-C was hit
343 KBINT = True
338 KBINT = True
344
339
345
340
346 class MTInteractiveShell(InteractiveShell):
341 class MTInteractiveShell(InteractiveShell):
347 """Simple multi-threaded shell."""
342 """Simple multi-threaded shell."""
348
343
349 # Threading strategy taken from:
344 # Threading strategy taken from:
350 # http://aspn.activestate.com/ASPN/Cookbook/Python/Recipe/65109, by Brian
345 # http://aspn.activestate.com/ASPN/Cookbook/Python/Recipe/65109, by Brian
351 # McErlean and John Finlay. Modified with corrections by Antoon Pardon,
346 # McErlean and John Finlay. Modified with corrections by Antoon Pardon,
352 # from the pygtk mailing list, to avoid lockups with system calls.
347 # from the pygtk mailing list, to avoid lockups with system calls.
353
348
354 # class attribute to indicate whether the class supports threads or not.
349 # class attribute to indicate whether the class supports threads or not.
355 # Subclasses with thread support should override this as needed.
350 # Subclasses with thread support should override this as needed.
356 isthreaded = True
351 isthreaded = True
357
352
358 def __init__(self,name,usage=None,rc=Struct(opts=None,args=None),
353 def __init__(self,name,usage=None,rc=Struct(opts=None,args=None),
359 user_ns=None,user_global_ns=None,banner2='',
354 user_ns=None,user_global_ns=None,banner2='',
360 gui_timeout=GUI_TIMEOUT,**kw):
355 gui_timeout=GUI_TIMEOUT,**kw):
361 """Similar to the normal InteractiveShell, but with threading control"""
356 """Similar to the normal InteractiveShell, but with threading control"""
362
357
363 InteractiveShell.__init__(self,name,usage,rc,user_ns,
358 InteractiveShell.__init__(self,name,usage,rc,user_ns,
364 user_global_ns,banner2)
359 user_global_ns,banner2)
365
360
366 # Timeout we wait for GUI thread
361 # Timeout we wait for GUI thread
367 self.gui_timeout = gui_timeout
362 self.gui_timeout = gui_timeout
368
363
369 # A queue to hold the code to be executed.
364 # A queue to hold the code to be executed.
370 self.code_queue = Queue.Queue()
365 self.code_queue = Queue.Queue()
371
366
372 # Stuff to do at closing time
367 # Stuff to do at closing time
373 self._kill = None
368 self._kill = None
374 on_kill = kw.get('on_kill', [])
369 on_kill = kw.get('on_kill', [])
375 # Check that all things to kill are callable:
370 # Check that all things to kill are callable:
376 for t in on_kill:
371 for t in on_kill:
377 if not callable(t):
372 if not callable(t):
378 raise TypeError,'on_kill must be a list of callables'
373 raise TypeError,'on_kill must be a list of callables'
379 self.on_kill = on_kill
374 self.on_kill = on_kill
380 # thread identity of the "worker thread" (that may execute code directly)
375 # thread identity of the "worker thread" (that may execute code directly)
381 self.worker_ident = None
376 self.worker_ident = None
382
377
383 def runsource(self, source, filename="<input>", symbol="single"):
378 def runsource(self, source, filename="<input>", symbol="single"):
384 """Compile and run some source in the interpreter.
379 """Compile and run some source in the interpreter.
385
380
386 Modified version of code.py's runsource(), to handle threading issues.
381 Modified version of code.py's runsource(), to handle threading issues.
387 See the original for full docstring details."""
382 See the original for full docstring details."""
388
383
389 global KBINT
384 global KBINT
390
385
391 # If Ctrl-C was typed, we reset the flag and return right away
386 # If Ctrl-C was typed, we reset the flag and return right away
392 if KBINT:
387 if KBINT:
393 KBINT = False
388 KBINT = False
394 return False
389 return False
395
390
396 if self._kill:
391 if self._kill:
397 # can't queue new code if we are being killed
392 # can't queue new code if we are being killed
398 return True
393 return True
399
394
400 try:
395 try:
401 code = self.compile(source, filename, symbol)
396 code = self.compile(source, filename, symbol)
402 except (OverflowError, SyntaxError, ValueError):
397 except (OverflowError, SyntaxError, ValueError):
403 # Case 1
398 # Case 1
404 self.showsyntaxerror(filename)
399 self.showsyntaxerror(filename)
405 return False
400 return False
406
401
407 if code is None:
402 if code is None:
408 # Case 2
403 # Case 2
409 return True
404 return True
410
405
411 # shortcut - if we are in worker thread, or the worker thread is not
406 # shortcut - if we are in worker thread, or the worker thread is not
412 # running, execute directly (to allow recursion and prevent deadlock if
407 # running, execute directly (to allow recursion and prevent deadlock if
413 # code is run early in IPython construction)
408 # code is run early in IPython construction)
414
409
415 if (self.worker_ident is None
410 if (self.worker_ident is None
416 or self.worker_ident == thread.get_ident() ):
411 or self.worker_ident == thread.get_ident() ):
417 InteractiveShell.runcode(self,code)
412 InteractiveShell.runcode(self,code)
418 return
413 return
419
414
420 # Case 3
415 # Case 3
421 # Store code in queue, so the execution thread can handle it.
416 # Store code in queue, so the execution thread can handle it.
422
417
423 completed_ev, received_ev = threading.Event(), threading.Event()
418 completed_ev, received_ev = threading.Event(), threading.Event()
424
419
425 self.code_queue.put((code,completed_ev, received_ev))
420 self.code_queue.put((code,completed_ev, received_ev))
426 # first make sure the message was received, with timeout
421 # first make sure the message was received, with timeout
427 received_ev.wait(self.gui_timeout)
422 received_ev.wait(self.gui_timeout)
428 if not received_ev.isSet():
423 if not received_ev.isSet():
429 # the mainloop is dead, start executing code directly
424 # the mainloop is dead, start executing code directly
430 print "Warning: Timeout for mainloop thread exceeded"
425 print "Warning: Timeout for mainloop thread exceeded"
431 print "switching to nonthreaded mode (until mainloop wakes up again)"
426 print "switching to nonthreaded mode (until mainloop wakes up again)"
432 self.worker_ident = None
427 self.worker_ident = None
433 else:
428 else:
434 completed_ev.wait()
429 completed_ev.wait()
435 return False
430 return False
436
431
437 def runcode(self):
432 def runcode(self):
438 """Execute a code object.
433 """Execute a code object.
439
434
440 Multithreaded wrapper around IPython's runcode()."""
435 Multithreaded wrapper around IPython's runcode()."""
441
436
442 global CODE_RUN
437 global CODE_RUN
443
438
444 # we are in worker thread, stash out the id for runsource()
439 # we are in worker thread, stash out the id for runsource()
445 self.worker_ident = thread.get_ident()
440 self.worker_ident = thread.get_ident()
446
441
447 if self._kill:
442 if self._kill:
448 print >>Term.cout, 'Closing threads...',
443 print >>Term.cout, 'Closing threads...',
449 Term.cout.flush()
444 Term.cout.flush()
450 for tokill in self.on_kill:
445 for tokill in self.on_kill:
451 tokill()
446 tokill()
452 print >>Term.cout, 'Done.'
447 print >>Term.cout, 'Done.'
453 # allow kill() to return
448 # allow kill() to return
454 self._kill.set()
449 self._kill.set()
455 return True
450 return True
456
451
457 # Install sigint handler. We do it every time to ensure that if user
452 # Install sigint handler. We do it every time to ensure that if user
458 # code modifies it, we restore our own handling.
453 # code modifies it, we restore our own handling.
459 try:
454 try:
460 signal(SIGINT,sigint_handler)
455 signal(SIGINT,sigint_handler)
461 except SystemError:
456 except SystemError:
462 # This happens under Windows, which seems to have all sorts
457 # This happens under Windows, which seems to have all sorts
463 # of problems with signal handling. Oh well...
458 # of problems with signal handling. Oh well...
464 pass
459 pass
465
460
466 # Flush queue of pending code by calling the run methood of the parent
461 # Flush queue of pending code by calling the run methood of the parent
467 # class with all items which may be in the queue.
462 # class with all items which may be in the queue.
468 code_to_run = None
463 code_to_run = None
469 while 1:
464 while 1:
470 try:
465 try:
471 code_to_run, completed_ev, received_ev = self.code_queue.get_nowait()
466 code_to_run, completed_ev, received_ev = self.code_queue.get_nowait()
472 except Queue.Empty:
467 except Queue.Empty:
473 break
468 break
474 received_ev.set()
469 received_ev.set()
475
470
476 # Exceptions need to be raised differently depending on which
471 # Exceptions need to be raised differently depending on which
477 # thread is active. This convoluted try/except is only there to
472 # thread is active. This convoluted try/except is only there to
478 # protect against asynchronous exceptions, to ensure that a KBINT
473 # protect against asynchronous exceptions, to ensure that a KBINT
479 # at the wrong time doesn't deadlock everything. The global
474 # at the wrong time doesn't deadlock everything. The global
480 # CODE_TO_RUN is set to true/false as close as possible to the
475 # CODE_TO_RUN is set to true/false as close as possible to the
481 # runcode() call, so that the KBINT handler is correctly informed.
476 # runcode() call, so that the KBINT handler is correctly informed.
482 try:
477 try:
483 try:
478 try:
484 CODE_RUN = True
479 CODE_RUN = True
485 InteractiveShell.runcode(self,code_to_run)
480 InteractiveShell.runcode(self,code_to_run)
486 except KeyboardInterrupt:
481 except KeyboardInterrupt:
487 print "Keyboard interrupted in mainloop"
482 print "Keyboard interrupted in mainloop"
488 while not self.code_queue.empty():
483 while not self.code_queue.empty():
489 code, ev1,ev2 = self.code_queue.get_nowait()
484 code, ev1,ev2 = self.code_queue.get_nowait()
490 ev1.set()
485 ev1.set()
491 ev2.set()
486 ev2.set()
492 break
487 break
493 finally:
488 finally:
494 CODE_RUN = False
489 CODE_RUN = False
495 # allow runsource() return from wait
490 # allow runsource() return from wait
496 completed_ev.set()
491 completed_ev.set()
497
492
498
493
499 # This MUST return true for gtk threading to work
494 # This MUST return true for gtk threading to work
500 return True
495 return True
501
496
502 def kill(self):
497 def kill(self):
503 """Kill the thread, returning when it has been shut down."""
498 """Kill the thread, returning when it has been shut down."""
504 self._kill = threading.Event()
499 self._kill = threading.Event()
505 self._kill.wait()
500 self._kill.wait()
506
501
507 class MatplotlibShellBase:
502 class MatplotlibShellBase:
508 """Mixin class to provide the necessary modifications to regular IPython
503 """Mixin class to provide the necessary modifications to regular IPython
509 shell classes for matplotlib support.
504 shell classes for matplotlib support.
510
505
511 Given Python's MRO, this should be used as the FIRST class in the
506 Given Python's MRO, this should be used as the FIRST class in the
512 inheritance hierarchy, so that it overrides the relevant methods."""
507 inheritance hierarchy, so that it overrides the relevant methods."""
513
508
514 def _matplotlib_config(self,name,user_ns,user_global_ns=None):
509 def _matplotlib_config(self,name,user_ns,user_global_ns=None):
515 """Return items needed to setup the user's shell with matplotlib"""
510 """Return items needed to setup the user's shell with matplotlib"""
516
511
517 # Initialize matplotlib to interactive mode always
512 # Initialize matplotlib to interactive mode always
518 import matplotlib
513 import matplotlib
519 from matplotlib import backends
514 from matplotlib import backends
520 matplotlib.interactive(True)
515 matplotlib.interactive(True)
521
516
522 def use(arg):
517 def use(arg):
523 """IPython wrapper for matplotlib's backend switcher.
518 """IPython wrapper for matplotlib's backend switcher.
524
519
525 In interactive use, we can not allow switching to a different
520 In interactive use, we can not allow switching to a different
526 interactive backend, since thread conflicts will most likely crash
521 interactive backend, since thread conflicts will most likely crash
527 the python interpreter. This routine does a safety check first,
522 the python interpreter. This routine does a safety check first,
528 and refuses to perform a dangerous switch. It still allows
523 and refuses to perform a dangerous switch. It still allows
529 switching to non-interactive backends."""
524 switching to non-interactive backends."""
530
525
531 if arg in backends.interactive_bk and arg != self.mpl_backend:
526 if arg in backends.interactive_bk and arg != self.mpl_backend:
532 m=('invalid matplotlib backend switch.\n'
527 m=('invalid matplotlib backend switch.\n'
533 'This script attempted to switch to the interactive '
528 'This script attempted to switch to the interactive '
534 'backend: `%s`\n'
529 'backend: `%s`\n'
535 'Your current choice of interactive backend is: `%s`\n\n'
530 'Your current choice of interactive backend is: `%s`\n\n'
536 'Switching interactive matplotlib backends at runtime\n'
531 'Switching interactive matplotlib backends at runtime\n'
537 'would crash the python interpreter, '
532 'would crash the python interpreter, '
538 'and IPython has blocked it.\n\n'
533 'and IPython has blocked it.\n\n'
539 'You need to either change your choice of matplotlib backend\n'
534 'You need to either change your choice of matplotlib backend\n'
540 'by editing your .matplotlibrc file, or run this script as a \n'
535 'by editing your .matplotlibrc file, or run this script as a \n'
541 'standalone file from the command line, not using IPython.\n' %
536 'standalone file from the command line, not using IPython.\n' %
542 (arg,self.mpl_backend) )
537 (arg,self.mpl_backend) )
543 raise RuntimeError, m
538 raise RuntimeError, m
544 else:
539 else:
545 self.mpl_use(arg)
540 self.mpl_use(arg)
546 self.mpl_use._called = True
541 self.mpl_use._called = True
547
542
548 self.matplotlib = matplotlib
543 self.matplotlib = matplotlib
549 self.mpl_backend = matplotlib.rcParams['backend']
544 self.mpl_backend = matplotlib.rcParams['backend']
550
545
551 # we also need to block switching of interactive backends by use()
546 # we also need to block switching of interactive backends by use()
552 self.mpl_use = matplotlib.use
547 self.mpl_use = matplotlib.use
553 self.mpl_use._called = False
548 self.mpl_use._called = False
554 # overwrite the original matplotlib.use with our wrapper
549 # overwrite the original matplotlib.use with our wrapper
555 matplotlib.use = use
550 matplotlib.use = use
556
551
557 # This must be imported last in the matplotlib series, after
552 # This must be imported last in the matplotlib series, after
558 # backend/interactivity choices have been made
553 # backend/interactivity choices have been made
559 import matplotlib.pylab as pylab
554 import matplotlib.pylab as pylab
560 self.pylab = pylab
555 self.pylab = pylab
561
556
562 self.pylab.show._needmain = False
557 self.pylab.show._needmain = False
563 # We need to detect at runtime whether show() is called by the user.
558 # We need to detect at runtime whether show() is called by the user.
564 # For this, we wrap it into a decorator which adds a 'called' flag.
559 # For this, we wrap it into a decorator which adds a 'called' flag.
565 self.pylab.draw_if_interactive = flag_calls(self.pylab.draw_if_interactive)
560 self.pylab.draw_if_interactive = flag_calls(self.pylab.draw_if_interactive)
566
561
567 # Build a user namespace initialized with matplotlib/matlab features.
562 # Build a user namespace initialized with matplotlib/matlab features.
568 user_ns, user_global_ns = IPython.ipapi.make_user_namespaces(user_ns,
563 user_ns, user_global_ns = IPython.ipapi.make_user_namespaces(user_ns,
569 user_global_ns)
564 user_global_ns)
570
565
571 # Import numpy as np/pyplot as plt are conventions we're trying to
566 # Import numpy as np/pyplot as plt are conventions we're trying to
572 # somewhat standardize on. Making them available to users by default
567 # somewhat standardize on. Making them available to users by default
573 # will greatly help this.
568 # will greatly help this.
574 exec ("import numpy\n"
569 exec ("import numpy\n"
575 "import numpy as np\n"
570 "import numpy as np\n"
576 "import matplotlib\n"
571 "import matplotlib\n"
577 "import matplotlib.pylab as pylab\n"
572 "import matplotlib.pylab as pylab\n"
578 "try:\n"
573 "try:\n"
579 " import matplotlib.pyplot as plt\n"
574 " import matplotlib.pyplot as plt\n"
580 "except ImportError:\n"
575 "except ImportError:\n"
581 " pass\n"
576 " pass\n"
582 ) in user_ns
577 ) in user_ns
583
578
584 # Build matplotlib info banner
579 # Build matplotlib info banner
585 b="""
580 b="""
586 Welcome to pylab, a matplotlib-based Python environment.
581 Welcome to pylab, a matplotlib-based Python environment.
587 For more information, type 'help(pylab)'.
582 For more information, type 'help(pylab)'.
588 """
583 """
589 return user_ns,user_global_ns,b
584 return user_ns,user_global_ns,b
590
585
591 def mplot_exec(self,fname,*where,**kw):
586 def mplot_exec(self,fname,*where,**kw):
592 """Execute a matplotlib script.
587 """Execute a matplotlib script.
593
588
594 This is a call to execfile(), but wrapped in safeties to properly
589 This is a call to execfile(), but wrapped in safeties to properly
595 handle interactive rendering and backend switching."""
590 handle interactive rendering and backend switching."""
596
591
597 #print '*** Matplotlib runner ***' # dbg
592 #print '*** Matplotlib runner ***' # dbg
598 # turn off rendering until end of script
593 # turn off rendering until end of script
599 isInteractive = self.matplotlib.rcParams['interactive']
594 isInteractive = self.matplotlib.rcParams['interactive']
600 self.matplotlib.interactive(False)
595 self.matplotlib.interactive(False)
601 self.safe_execfile(fname,*where,**kw)
596 self.safe_execfile(fname,*where,**kw)
602 self.matplotlib.interactive(isInteractive)
597 self.matplotlib.interactive(isInteractive)
603 # make rendering call now, if the user tried to do it
598 # make rendering call now, if the user tried to do it
604 if self.pylab.draw_if_interactive.called:
599 if self.pylab.draw_if_interactive.called:
605 self.pylab.draw()
600 self.pylab.draw()
606 self.pylab.draw_if_interactive.called = False
601 self.pylab.draw_if_interactive.called = False
607
602
608 # if a backend switch was performed, reverse it now
603 # if a backend switch was performed, reverse it now
609 if self.mpl_use._called:
604 if self.mpl_use._called:
610 self.matplotlib.rcParams['backend'] = self.mpl_backend
605 self.matplotlib.rcParams['backend'] = self.mpl_backend
611
606
612 @testdec.skip_doctest
607 @testdec.skip_doctest
613 def magic_run(self,parameter_s=''):
608 def magic_run(self,parameter_s=''):
614 Magic.magic_run(self,parameter_s,runner=self.mplot_exec)
609 Magic.magic_run(self,parameter_s,runner=self.mplot_exec)
615
610
616 # Fix the docstring so users see the original as well
611 # Fix the docstring so users see the original as well
617 magic_run.__doc__ = "%s\n%s" % (Magic.magic_run.__doc__,
612 magic_run.__doc__ = "%s\n%s" % (Magic.magic_run.__doc__,
618 "\n *** Modified %run for Matplotlib,"
613 "\n *** Modified %run for Matplotlib,"
619 " with proper interactive handling ***")
614 " with proper interactive handling ***")
620
615
621 # Now we provide 2 versions of a matplotlib-aware IPython base shells, single
616 # Now we provide 2 versions of a matplotlib-aware IPython base shells, single
622 # and multithreaded. Note that these are meant for internal use, the IPShell*
617 # and multithreaded. Note that these are meant for internal use, the IPShell*
623 # classes below are the ones meant for public consumption.
618 # classes below are the ones meant for public consumption.
624
619
625 class MatplotlibShell(MatplotlibShellBase,InteractiveShell):
620 class MatplotlibShell(MatplotlibShellBase,InteractiveShell):
626 """Single-threaded shell with matplotlib support."""
621 """Single-threaded shell with matplotlib support."""
627
622
628 def __init__(self,name,usage=None,rc=Struct(opts=None,args=None),
623 def __init__(self,name,usage=None,rc=Struct(opts=None,args=None),
629 user_ns=None,user_global_ns=None,**kw):
624 user_ns=None,user_global_ns=None,**kw):
630 user_ns,user_global_ns,b2 = self._matplotlib_config(name,user_ns,user_global_ns)
625 user_ns,user_global_ns,b2 = self._matplotlib_config(name,user_ns,user_global_ns)
631 InteractiveShell.__init__(self,name,usage,rc,user_ns,user_global_ns,
626 InteractiveShell.__init__(self,name,usage,rc,user_ns,user_global_ns,
632 banner2=b2,**kw)
627 banner2=b2,**kw)
633
628
634 class MatplotlibMTShell(MatplotlibShellBase,MTInteractiveShell):
629 class MatplotlibMTShell(MatplotlibShellBase,MTInteractiveShell):
635 """Multi-threaded shell with matplotlib support."""
630 """Multi-threaded shell with matplotlib support."""
636
631
637 def __init__(self,name,usage=None,rc=Struct(opts=None,args=None),
632 def __init__(self,name,usage=None,rc=Struct(opts=None,args=None),
638 user_ns=None,user_global_ns=None, **kw):
633 user_ns=None,user_global_ns=None, **kw):
639 user_ns,user_global_ns,b2 = self._matplotlib_config(name,user_ns,user_global_ns)
634 user_ns,user_global_ns,b2 = self._matplotlib_config(name,user_ns,user_global_ns)
640 MTInteractiveShell.__init__(self,name,usage,rc,user_ns,user_global_ns,
635 MTInteractiveShell.__init__(self,name,usage,rc,user_ns,user_global_ns,
641 banner2=b2,**kw)
636 banner2=b2,**kw)
642
637
643 #-----------------------------------------------------------------------------
638 #-----------------------------------------------------------------------------
644 # Utility functions for the different GUI enabled IPShell* classes.
639 # Utility functions for the different GUI enabled IPShell* classes.
645
640
646 def get_tk():
641 def get_tk():
647 """Tries to import Tkinter and returns a withdrawn Tkinter root
642 """Tries to import Tkinter and returns a withdrawn Tkinter root
648 window. If Tkinter is already imported or not available, this
643 window. If Tkinter is already imported or not available, this
649 returns None. This function calls `hijack_tk` underneath.
644 returns None. This function calls `hijack_tk` underneath.
650 """
645 """
651 if not USE_TK or sys.modules.has_key('Tkinter'):
646 if not USE_TK or sys.modules.has_key('Tkinter'):
652 return None
647 return None
653 else:
648 else:
654 try:
649 try:
655 import Tkinter
650 import Tkinter
656 except ImportError:
651 except ImportError:
657 return None
652 return None
658 else:
653 else:
659 hijack_tk()
654 hijack_tk()
660 r = Tkinter.Tk()
655 r = Tkinter.Tk()
661 r.withdraw()
656 r.withdraw()
662 return r
657 return r
663
658
664 def hijack_tk():
659 def hijack_tk():
665 """Modifies Tkinter's mainloop with a dummy so when a module calls
660 """Modifies Tkinter's mainloop with a dummy so when a module calls
666 mainloop, it does not block.
661 mainloop, it does not block.
667
662
668 """
663 """
669 def misc_mainloop(self, n=0):
664 def misc_mainloop(self, n=0):
670 pass
665 pass
671 def tkinter_mainloop(n=0):
666 def tkinter_mainloop(n=0):
672 pass
667 pass
673
668
674 import Tkinter
669 import Tkinter
675 Tkinter.Misc.mainloop = misc_mainloop
670 Tkinter.Misc.mainloop = misc_mainloop
676 Tkinter.mainloop = tkinter_mainloop
671 Tkinter.mainloop = tkinter_mainloop
677
672
678 def update_tk(tk):
673 def update_tk(tk):
679 """Updates the Tkinter event loop. This is typically called from
674 """Updates the Tkinter event loop. This is typically called from
680 the respective WX or GTK mainloops.
675 the respective WX or GTK mainloops.
681 """
676 """
682 if tk:
677 if tk:
683 tk.update()
678 tk.update()
684
679
685 def hijack_wx():
680 def hijack_wx():
686 """Modifies wxPython's MainLoop with a dummy so user code does not
681 """Modifies wxPython's MainLoop with a dummy so user code does not
687 block IPython. The hijacked mainloop function is returned.
682 block IPython. The hijacked mainloop function is returned.
688 """
683 """
689 def dummy_mainloop(*args, **kw):
684 def dummy_mainloop(*args, **kw):
690 pass
685 pass
691
686
692 try:
687 try:
693 import wx
688 import wx
694 except ImportError:
689 except ImportError:
695 # For very old versions of WX
690 # For very old versions of WX
696 import wxPython as wx
691 import wxPython as wx
697
692
698 ver = wx.__version__
693 ver = wx.__version__
699 orig_mainloop = None
694 orig_mainloop = None
700 if ver[:3] >= '2.5':
695 if ver[:3] >= '2.5':
701 import wx
696 import wx
702 if hasattr(wx, '_core_'): core = getattr(wx, '_core_')
697 if hasattr(wx, '_core_'): core = getattr(wx, '_core_')
703 elif hasattr(wx, '_core'): core = getattr(wx, '_core')
698 elif hasattr(wx, '_core'): core = getattr(wx, '_core')
704 else: raise AttributeError('Could not find wx core module')
699 else: raise AttributeError('Could not find wx core module')
705 orig_mainloop = core.PyApp_MainLoop
700 orig_mainloop = core.PyApp_MainLoop
706 core.PyApp_MainLoop = dummy_mainloop
701 core.PyApp_MainLoop = dummy_mainloop
707 elif ver[:3] == '2.4':
702 elif ver[:3] == '2.4':
708 orig_mainloop = wx.wxc.wxPyApp_MainLoop
703 orig_mainloop = wx.wxc.wxPyApp_MainLoop
709 wx.wxc.wxPyApp_MainLoop = dummy_mainloop
704 wx.wxc.wxPyApp_MainLoop = dummy_mainloop
710 else:
705 else:
711 warn("Unable to find either wxPython version 2.4 or >= 2.5.")
706 warn("Unable to find either wxPython version 2.4 or >= 2.5.")
712 return orig_mainloop
707 return orig_mainloop
713
708
714 def hijack_gtk():
709 def hijack_gtk():
715 """Modifies pyGTK's mainloop with a dummy so user code does not
710 """Modifies pyGTK's mainloop with a dummy so user code does not
716 block IPython. This function returns the original `gtk.mainloop`
711 block IPython. This function returns the original `gtk.mainloop`
717 function that has been hijacked.
712 function that has been hijacked.
718 """
713 """
719 def dummy_mainloop(*args, **kw):
714 def dummy_mainloop(*args, **kw):
720 pass
715 pass
721 import gtk
716 import gtk
722 if gtk.pygtk_version >= (2,4,0): orig_mainloop = gtk.main
717 if gtk.pygtk_version >= (2,4,0): orig_mainloop = gtk.main
723 else: orig_mainloop = gtk.mainloop
718 else: orig_mainloop = gtk.mainloop
724 gtk.mainloop = dummy_mainloop
719 gtk.mainloop = dummy_mainloop
725 gtk.main = dummy_mainloop
720 gtk.main = dummy_mainloop
726 return orig_mainloop
721 return orig_mainloop
727
722
728 def hijack_qt():
723 def hijack_qt():
729 """Modifies PyQt's mainloop with a dummy so user code does not
724 """Modifies PyQt's mainloop with a dummy so user code does not
730 block IPython. This function returns the original
725 block IPython. This function returns the original
731 `qt.qApp.exec_loop` function that has been hijacked.
726 `qt.qApp.exec_loop` function that has been hijacked.
732 """
727 """
733 def dummy_mainloop(*args, **kw):
728 def dummy_mainloop(*args, **kw):
734 pass
729 pass
735 import qt
730 import qt
736 orig_mainloop = qt.qApp.exec_loop
731 orig_mainloop = qt.qApp.exec_loop
737 qt.qApp.exec_loop = dummy_mainloop
732 qt.qApp.exec_loop = dummy_mainloop
738 qt.QApplication.exec_loop = dummy_mainloop
733 qt.QApplication.exec_loop = dummy_mainloop
739 return orig_mainloop
734 return orig_mainloop
740
735
741 def hijack_qt4():
736 def hijack_qt4():
742 """Modifies PyQt4's mainloop with a dummy so user code does not
737 """Modifies PyQt4's mainloop with a dummy so user code does not
743 block IPython. This function returns the original
738 block IPython. This function returns the original
744 `QtGui.qApp.exec_` function that has been hijacked.
739 `QtGui.qApp.exec_` function that has been hijacked.
745 """
740 """
746 def dummy_mainloop(*args, **kw):
741 def dummy_mainloop(*args, **kw):
747 pass
742 pass
748 from PyQt4 import QtGui, QtCore
743 from PyQt4 import QtGui, QtCore
749 orig_mainloop = QtGui.qApp.exec_
744 orig_mainloop = QtGui.qApp.exec_
750 QtGui.qApp.exec_ = dummy_mainloop
745 QtGui.qApp.exec_ = dummy_mainloop
751 QtGui.QApplication.exec_ = dummy_mainloop
746 QtGui.QApplication.exec_ = dummy_mainloop
752 QtCore.QCoreApplication.exec_ = dummy_mainloop
747 QtCore.QCoreApplication.exec_ = dummy_mainloop
753 return orig_mainloop
748 return orig_mainloop
754
749
755 #-----------------------------------------------------------------------------
750 #-----------------------------------------------------------------------------
756 # The IPShell* classes below are the ones meant to be run by external code as
751 # The IPShell* classes below are the ones meant to be run by external code as
757 # IPython instances. Note that unless a specific threading strategy is
752 # IPython instances. Note that unless a specific threading strategy is
758 # desired, the factory function start() below should be used instead (it
753 # desired, the factory function start() below should be used instead (it
759 # selects the proper threaded class).
754 # selects the proper threaded class).
760
755
761 class IPThread(threading.Thread):
756 class IPThread(threading.Thread):
762 def run(self):
757 def run(self):
763 self.IP.mainloop(self._banner)
758 self.IP.mainloop(self._banner)
764 self.IP.kill()
759 self.IP.kill()
765
760
766 class IPShellGTK(IPThread):
761 class IPShellGTK(IPThread):
767 """Run a gtk mainloop() in a separate thread.
762 """Run a gtk mainloop() in a separate thread.
768
763
769 Python commands can be passed to the thread where they will be executed.
764 Python commands can be passed to the thread where they will be executed.
770 This is implemented by periodically checking for passed code using a
765 This is implemented by periodically checking for passed code using a
771 GTK timeout callback."""
766 GTK timeout callback."""
772
767
773 TIMEOUT = 100 # Millisecond interval between timeouts.
768 TIMEOUT = 100 # Millisecond interval between timeouts.
774
769
775 def __init__(self,argv=None,user_ns=None,user_global_ns=None,
770 def __init__(self,argv=None,user_ns=None,user_global_ns=None,
776 debug=1,shell_class=MTInteractiveShell):
771 debug=1,shell_class=MTInteractiveShell):
777
772
778 import gtk
773 import gtk
779
774
780 self.gtk = gtk
775 self.gtk = gtk
781 self.gtk_mainloop = hijack_gtk()
776 self.gtk_mainloop = hijack_gtk()
782
777
783 # Allows us to use both Tk and GTK.
778 # Allows us to use both Tk and GTK.
784 self.tk = get_tk()
779 self.tk = get_tk()
785
780
786 if gtk.pygtk_version >= (2,4,0): mainquit = self.gtk.main_quit
781 if gtk.pygtk_version >= (2,4,0): mainquit = self.gtk.main_quit
787 else: mainquit = self.gtk.mainquit
782 else: mainquit = self.gtk.mainquit
788
783
789 self.IP = make_IPython(argv,user_ns=user_ns,
784 self.IP = make_IPython(argv,user_ns=user_ns,
790 user_global_ns=user_global_ns,
785 user_global_ns=user_global_ns,
791 debug=debug,
786 debug=debug,
792 shell_class=shell_class,
787 shell_class=shell_class,
793 on_kill=[mainquit])
788 on_kill=[mainquit])
794
789
795 # HACK: slot for banner in self; it will be passed to the mainloop
790 # HACK: slot for banner in self; it will be passed to the mainloop
796 # method only and .run() needs it. The actual value will be set by
791 # method only and .run() needs it. The actual value will be set by
797 # .mainloop().
792 # .mainloop().
798 self._banner = None
793 self._banner = None
799
794
800 threading.Thread.__init__(self)
795 threading.Thread.__init__(self)
801
796
802 def mainloop(self,sys_exit=0,banner=None):
797 def mainloop(self,sys_exit=0,banner=None):
803
798
804 self._banner = banner
799 self._banner = banner
805
800
806 if self.gtk.pygtk_version >= (2,4,0):
801 if self.gtk.pygtk_version >= (2,4,0):
807 import gobject
802 import gobject
808 gobject.idle_add(self.on_timer)
803 gobject.idle_add(self.on_timer)
809 else:
804 else:
810 self.gtk.idle_add(self.on_timer)
805 self.gtk.idle_add(self.on_timer)
811
806
812 if sys.platform != 'win32':
807 if sys.platform != 'win32':
813 try:
808 try:
814 if self.gtk.gtk_version[0] >= 2:
809 if self.gtk.gtk_version[0] >= 2:
815 self.gtk.gdk.threads_init()
810 self.gtk.gdk.threads_init()
816 except AttributeError:
811 except AttributeError:
817 pass
812 pass
818 except RuntimeError:
813 except RuntimeError:
819 error('Your pyGTK likely has not been compiled with '
814 error('Your pyGTK likely has not been compiled with '
820 'threading support.\n'
815 'threading support.\n'
821 'The exception printout is below.\n'
816 'The exception printout is below.\n'
822 'You can either rebuild pyGTK with threads, or '
817 'You can either rebuild pyGTK with threads, or '
823 'try using \n'
818 'try using \n'
824 'matplotlib with a different backend (like Tk or WX).\n'
819 'matplotlib with a different backend (like Tk or WX).\n'
825 'Note that matplotlib will most likely not work in its '
820 'Note that matplotlib will most likely not work in its '
826 'current state!')
821 'current state!')
827 self.IP.InteractiveTB()
822 self.IP.InteractiveTB()
828
823
829 self.start()
824 self.start()
830 self.gtk.gdk.threads_enter()
825 self.gtk.gdk.threads_enter()
831 self.gtk_mainloop()
826 self.gtk_mainloop()
832 self.gtk.gdk.threads_leave()
827 self.gtk.gdk.threads_leave()
833 self.join()
828 self.join()
834
829
835 def on_timer(self):
830 def on_timer(self):
836 """Called when GTK is idle.
831 """Called when GTK is idle.
837
832
838 Must return True always, otherwise GTK stops calling it"""
833 Must return True always, otherwise GTK stops calling it"""
839
834
840 update_tk(self.tk)
835 update_tk(self.tk)
841 self.IP.runcode()
836 self.IP.runcode()
842 time.sleep(0.01)
837 time.sleep(0.01)
843 return True
838 return True
844
839
845
840
846 class IPShellWX(IPThread):
841 class IPShellWX(IPThread):
847 """Run a wx mainloop() in a separate thread.
842 """Run a wx mainloop() in a separate thread.
848
843
849 Python commands can be passed to the thread where they will be executed.
844 Python commands can be passed to the thread where they will be executed.
850 This is implemented by periodically checking for passed code using a
845 This is implemented by periodically checking for passed code using a
851 GTK timeout callback."""
846 GTK timeout callback."""
852
847
853 TIMEOUT = 100 # Millisecond interval between timeouts.
848 TIMEOUT = 100 # Millisecond interval between timeouts.
854
849
855 def __init__(self,argv=None,user_ns=None,user_global_ns=None,
850 def __init__(self,argv=None,user_ns=None,user_global_ns=None,
856 debug=1,shell_class=MTInteractiveShell):
851 debug=1,shell_class=MTInteractiveShell):
857
852
858 self.IP = make_IPython(argv,user_ns=user_ns,
853 self.IP = make_IPython(argv,user_ns=user_ns,
859 user_global_ns=user_global_ns,
854 user_global_ns=user_global_ns,
860 debug=debug,
855 debug=debug,
861 shell_class=shell_class,
856 shell_class=shell_class,
862 on_kill=[self.wxexit])
857 on_kill=[self.wxexit])
863
858
864 wantedwxversion=self.IP.rc.wxversion
859 wantedwxversion=self.IP.rc.wxversion
865 if wantedwxversion!="0":
860 if wantedwxversion!="0":
866 try:
861 try:
867 import wxversion
862 import wxversion
868 except ImportError:
863 except ImportError:
869 error('The wxversion module is needed for WX version selection')
864 error('The wxversion module is needed for WX version selection')
870 else:
865 else:
871 try:
866 try:
872 wxversion.select(wantedwxversion)
867 wxversion.select(wantedwxversion)
873 except:
868 except:
874 self.IP.InteractiveTB()
869 self.IP.InteractiveTB()
875 error('Requested wxPython version %s could not be loaded' %
870 error('Requested wxPython version %s could not be loaded' %
876 wantedwxversion)
871 wantedwxversion)
877
872
878 import wx
873 import wx
879
874
880 threading.Thread.__init__(self)
875 threading.Thread.__init__(self)
881 self.wx = wx
876 self.wx = wx
882 self.wx_mainloop = hijack_wx()
877 self.wx_mainloop = hijack_wx()
883
878
884 # Allows us to use both Tk and GTK.
879 # Allows us to use both Tk and GTK.
885 self.tk = get_tk()
880 self.tk = get_tk()
886
881
887 # HACK: slot for banner in self; it will be passed to the mainloop
882 # HACK: slot for banner in self; it will be passed to the mainloop
888 # method only and .run() needs it. The actual value will be set by
883 # method only and .run() needs it. The actual value will be set by
889 # .mainloop().
884 # .mainloop().
890 self._banner = None
885 self._banner = None
891
886
892 self.app = None
887 self.app = None
893
888
894 def wxexit(self, *args):
889 def wxexit(self, *args):
895 if self.app is not None:
890 if self.app is not None:
896 self.app.agent.timer.Stop()
891 self.app.agent.timer.Stop()
897 self.app.ExitMainLoop()
892 self.app.ExitMainLoop()
898
893
899 def mainloop(self,sys_exit=0,banner=None):
894 def mainloop(self,sys_exit=0,banner=None):
900
895
901 self._banner = banner
896 self._banner = banner
902
897
903 self.start()
898 self.start()
904
899
905 class TimerAgent(self.wx.MiniFrame):
900 class TimerAgent(self.wx.MiniFrame):
906 wx = self.wx
901 wx = self.wx
907 IP = self.IP
902 IP = self.IP
908 tk = self.tk
903 tk = self.tk
909 def __init__(self, parent, interval):
904 def __init__(self, parent, interval):
910 style = self.wx.DEFAULT_FRAME_STYLE | self.wx.TINY_CAPTION_HORIZ
905 style = self.wx.DEFAULT_FRAME_STYLE | self.wx.TINY_CAPTION_HORIZ
911 self.wx.MiniFrame.__init__(self, parent, -1, ' ', pos=(200, 200),
906 self.wx.MiniFrame.__init__(self, parent, -1, ' ', pos=(200, 200),
912 size=(100, 100),style=style)
907 size=(100, 100),style=style)
913 self.Show(False)
908 self.Show(False)
914 self.interval = interval
909 self.interval = interval
915 self.timerId = self.wx.NewId()
910 self.timerId = self.wx.NewId()
916
911
917 def StartWork(self):
912 def StartWork(self):
918 self.timer = self.wx.Timer(self, self.timerId)
913 self.timer = self.wx.Timer(self, self.timerId)
919 self.wx.EVT_TIMER(self, self.timerId, self.OnTimer)
914 self.wx.EVT_TIMER(self, self.timerId, self.OnTimer)
920 self.timer.Start(self.interval)
915 self.timer.Start(self.interval)
921
916
922 def OnTimer(self, event):
917 def OnTimer(self, event):
923 update_tk(self.tk)
918 update_tk(self.tk)
924 self.IP.runcode()
919 self.IP.runcode()
925
920
926 class App(self.wx.App):
921 class App(self.wx.App):
927 wx = self.wx
922 wx = self.wx
928 TIMEOUT = self.TIMEOUT
923 TIMEOUT = self.TIMEOUT
929 def OnInit(self):
924 def OnInit(self):
930 'Create the main window and insert the custom frame'
925 'Create the main window and insert the custom frame'
931 self.agent = TimerAgent(None, self.TIMEOUT)
926 self.agent = TimerAgent(None, self.TIMEOUT)
932 self.agent.Show(False)
927 self.agent.Show(False)
933 self.agent.StartWork()
928 self.agent.StartWork()
934 return True
929 return True
935
930
936 self.app = App(redirect=False)
931 self.app = App(redirect=False)
937 self.wx_mainloop(self.app)
932 self.wx_mainloop(self.app)
938 self.join()
933 self.join()
939
934
940
935
941 class IPShellQt(IPThread):
936 class IPShellQt(IPThread):
942 """Run a Qt event loop in a separate thread.
937 """Run a Qt event loop in a separate thread.
943
938
944 Python commands can be passed to the thread where they will be executed.
939 Python commands can be passed to the thread where they will be executed.
945 This is implemented by periodically checking for passed code using a
940 This is implemented by periodically checking for passed code using a
946 Qt timer / slot."""
941 Qt timer / slot."""
947
942
948 TIMEOUT = 100 # Millisecond interval between timeouts.
943 TIMEOUT = 100 # Millisecond interval between timeouts.
949
944
950 def __init__(self, argv=None, user_ns=None, user_global_ns=None,
945 def __init__(self, argv=None, user_ns=None, user_global_ns=None,
951 debug=0, shell_class=MTInteractiveShell):
946 debug=0, shell_class=MTInteractiveShell):
952
947
953 import qt
948 import qt
954
949
955 self.exec_loop = hijack_qt()
950 self.exec_loop = hijack_qt()
956
951
957 # Allows us to use both Tk and QT.
952 # Allows us to use both Tk and QT.
958 self.tk = get_tk()
953 self.tk = get_tk()
959
954
960 self.IP = make_IPython(argv,
955 self.IP = make_IPython(argv,
961 user_ns=user_ns,
956 user_ns=user_ns,
962 user_global_ns=user_global_ns,
957 user_global_ns=user_global_ns,
963 debug=debug,
958 debug=debug,
964 shell_class=shell_class,
959 shell_class=shell_class,
965 on_kill=[qt.qApp.exit])
960 on_kill=[qt.qApp.exit])
966
961
967 # HACK: slot for banner in self; it will be passed to the mainloop
962 # HACK: slot for banner in self; it will be passed to the mainloop
968 # method only and .run() needs it. The actual value will be set by
963 # method only and .run() needs it. The actual value will be set by
969 # .mainloop().
964 # .mainloop().
970 self._banner = None
965 self._banner = None
971
966
972 threading.Thread.__init__(self)
967 threading.Thread.__init__(self)
973
968
974 def mainloop(self, sys_exit=0, banner=None):
969 def mainloop(self, sys_exit=0, banner=None):
975
970
976 import qt
971 import qt
977
972
978 self._banner = banner
973 self._banner = banner
979
974
980 if qt.QApplication.startingUp():
975 if qt.QApplication.startingUp():
981 a = qt.QApplication(sys.argv)
976 a = qt.QApplication(sys.argv)
982
977
983 self.timer = qt.QTimer()
978 self.timer = qt.QTimer()
984 qt.QObject.connect(self.timer,
979 qt.QObject.connect(self.timer,
985 qt.SIGNAL('timeout()'),
980 qt.SIGNAL('timeout()'),
986 self.on_timer)
981 self.on_timer)
987
982
988 self.start()
983 self.start()
989 self.timer.start(self.TIMEOUT, True)
984 self.timer.start(self.TIMEOUT, True)
990 while True:
985 while True:
991 if self.IP._kill: break
986 if self.IP._kill: break
992 self.exec_loop()
987 self.exec_loop()
993 self.join()
988 self.join()
994
989
995 def on_timer(self):
990 def on_timer(self):
996 update_tk(self.tk)
991 update_tk(self.tk)
997 result = self.IP.runcode()
992 result = self.IP.runcode()
998 self.timer.start(self.TIMEOUT, True)
993 self.timer.start(self.TIMEOUT, True)
999 return result
994 return result
1000
995
1001
996
1002 class IPShellQt4(IPThread):
997 class IPShellQt4(IPThread):
1003 """Run a Qt event loop in a separate thread.
998 """Run a Qt event loop in a separate thread.
1004
999
1005 Python commands can be passed to the thread where they will be executed.
1000 Python commands can be passed to the thread where they will be executed.
1006 This is implemented by periodically checking for passed code using a
1001 This is implemented by periodically checking for passed code using a
1007 Qt timer / slot."""
1002 Qt timer / slot."""
1008
1003
1009 TIMEOUT = 100 # Millisecond interval between timeouts.
1004 TIMEOUT = 100 # Millisecond interval between timeouts.
1010
1005
1011 def __init__(self, argv=None, user_ns=None, user_global_ns=None,
1006 def __init__(self, argv=None, user_ns=None, user_global_ns=None,
1012 debug=0, shell_class=MTInteractiveShell):
1007 debug=0, shell_class=MTInteractiveShell):
1013
1008
1014 from PyQt4 import QtCore, QtGui
1009 from PyQt4 import QtCore, QtGui
1015
1010
1016 try:
1011 try:
1017 # present in PyQt4-4.2.1 or later
1012 # present in PyQt4-4.2.1 or later
1018 QtCore.pyqtRemoveInputHook()
1013 QtCore.pyqtRemoveInputHook()
1019 except AttributeError:
1014 except AttributeError:
1020 pass
1015 pass
1021
1016
1022 if QtCore.PYQT_VERSION_STR == '4.3':
1017 if QtCore.PYQT_VERSION_STR == '4.3':
1023 warn('''PyQt4 version 4.3 detected.
1018 warn('''PyQt4 version 4.3 detected.
1024 If you experience repeated threading warnings, please update PyQt4.
1019 If you experience repeated threading warnings, please update PyQt4.
1025 ''')
1020 ''')
1026
1021
1027 self.exec_ = hijack_qt4()
1022 self.exec_ = hijack_qt4()
1028
1023
1029 # Allows us to use both Tk and QT.
1024 # Allows us to use both Tk and QT.
1030 self.tk = get_tk()
1025 self.tk = get_tk()
1031
1026
1032 self.IP = make_IPython(argv,
1027 self.IP = make_IPython(argv,
1033 user_ns=user_ns,
1028 user_ns=user_ns,
1034 user_global_ns=user_global_ns,
1029 user_global_ns=user_global_ns,
1035 debug=debug,
1030 debug=debug,
1036 shell_class=shell_class,
1031 shell_class=shell_class,
1037 on_kill=[QtGui.qApp.exit])
1032 on_kill=[QtGui.qApp.exit])
1038
1033
1039 # HACK: slot for banner in self; it will be passed to the mainloop
1034 # HACK: slot for banner in self; it will be passed to the mainloop
1040 # method only and .run() needs it. The actual value will be set by
1035 # method only and .run() needs it. The actual value will be set by
1041 # .mainloop().
1036 # .mainloop().
1042 self._banner = None
1037 self._banner = None
1043
1038
1044 threading.Thread.__init__(self)
1039 threading.Thread.__init__(self)
1045
1040
1046 def mainloop(self, sys_exit=0, banner=None):
1041 def mainloop(self, sys_exit=0, banner=None):
1047
1042
1048 from PyQt4 import QtCore, QtGui
1043 from PyQt4 import QtCore, QtGui
1049
1044
1050 self._banner = banner
1045 self._banner = banner
1051
1046
1052 if QtGui.QApplication.startingUp():
1047 if QtGui.QApplication.startingUp():
1053 a = QtGui.QApplication(sys.argv)
1048 a = QtGui.QApplication(sys.argv)
1054
1049
1055 self.timer = QtCore.QTimer()
1050 self.timer = QtCore.QTimer()
1056 QtCore.QObject.connect(self.timer,
1051 QtCore.QObject.connect(self.timer,
1057 QtCore.SIGNAL('timeout()'),
1052 QtCore.SIGNAL('timeout()'),
1058 self.on_timer)
1053 self.on_timer)
1059
1054
1060 self.start()
1055 self.start()
1061 self.timer.start(self.TIMEOUT)
1056 self.timer.start(self.TIMEOUT)
1062 while True:
1057 while True:
1063 if self.IP._kill: break
1058 if self.IP._kill: break
1064 self.exec_()
1059 self.exec_()
1065 self.join()
1060 self.join()
1066
1061
1067 def on_timer(self):
1062 def on_timer(self):
1068 update_tk(self.tk)
1063 update_tk(self.tk)
1069 result = self.IP.runcode()
1064 result = self.IP.runcode()
1070 self.timer.start(self.TIMEOUT)
1065 self.timer.start(self.TIMEOUT)
1071 return result
1066 return result
1072
1067
1073
1068
1074 # A set of matplotlib public IPython shell classes, for single-threaded (Tk*
1069 # A set of matplotlib public IPython shell classes, for single-threaded (Tk*
1075 # and FLTK*) and multithreaded (GTK*, WX* and Qt*) backends to use.
1070 # and FLTK*) and multithreaded (GTK*, WX* and Qt*) backends to use.
1076 def _load_pylab(user_ns):
1071 def _load_pylab(user_ns):
1077 """Allow users to disable pulling all of pylab into the top-level
1072 """Allow users to disable pulling all of pylab into the top-level
1078 namespace.
1073 namespace.
1079
1074
1080 This little utility must be called AFTER the actual ipython instance is
1075 This little utility must be called AFTER the actual ipython instance is
1081 running, since only then will the options file have been fully parsed."""
1076 running, since only then will the options file have been fully parsed."""
1082
1077
1083 ip = IPython.ipapi.get()
1078 ip = IPython.ipapi.get()
1084 if ip.options.pylab_import_all:
1079 if ip.options.pylab_import_all:
1085 ip.ex("from matplotlib.pylab import *")
1080 ip.ex("from matplotlib.pylab import *")
1086 ip.IP.user_config_ns.update(ip.user_ns)
1081 ip.IP.user_config_ns.update(ip.user_ns)
1087
1082
1088
1083
1089 class IPShellMatplotlib(IPShell):
1084 class IPShellMatplotlib(IPShell):
1090 """Subclass IPShell with MatplotlibShell as the internal shell.
1085 """Subclass IPShell with MatplotlibShell as the internal shell.
1091
1086
1092 Single-threaded class, meant for the Tk* and FLTK* backends.
1087 Single-threaded class, meant for the Tk* and FLTK* backends.
1093
1088
1094 Having this on a separate class simplifies the external driver code."""
1089 Having this on a separate class simplifies the external driver code."""
1095
1090
1096 def __init__(self,argv=None,user_ns=None,user_global_ns=None,debug=1):
1091 def __init__(self,argv=None,user_ns=None,user_global_ns=None,debug=1):
1097 IPShell.__init__(self,argv,user_ns,user_global_ns,debug,
1092 IPShell.__init__(self,argv,user_ns,user_global_ns,debug,
1098 shell_class=MatplotlibShell)
1093 shell_class=MatplotlibShell)
1099 _load_pylab(self.IP.user_ns)
1094 _load_pylab(self.IP.user_ns)
1100
1095
1101 class IPShellMatplotlibGTK(IPShellGTK):
1096 class IPShellMatplotlibGTK(IPShellGTK):
1102 """Subclass IPShellGTK with MatplotlibMTShell as the internal shell.
1097 """Subclass IPShellGTK with MatplotlibMTShell as the internal shell.
1103
1098
1104 Multi-threaded class, meant for the GTK* backends."""
1099 Multi-threaded class, meant for the GTK* backends."""
1105
1100
1106 def __init__(self,argv=None,user_ns=None,user_global_ns=None,debug=1):
1101 def __init__(self,argv=None,user_ns=None,user_global_ns=None,debug=1):
1107 IPShellGTK.__init__(self,argv,user_ns,user_global_ns,debug,
1102 IPShellGTK.__init__(self,argv,user_ns,user_global_ns,debug,
1108 shell_class=MatplotlibMTShell)
1103 shell_class=MatplotlibMTShell)
1109 _load_pylab(self.IP.user_ns)
1104 _load_pylab(self.IP.user_ns)
1110
1105
1111 class IPShellMatplotlibWX(IPShellWX):
1106 class IPShellMatplotlibWX(IPShellWX):
1112 """Subclass IPShellWX with MatplotlibMTShell as the internal shell.
1107 """Subclass IPShellWX with MatplotlibMTShell as the internal shell.
1113
1108
1114 Multi-threaded class, meant for the WX* backends."""
1109 Multi-threaded class, meant for the WX* backends."""
1115
1110
1116 def __init__(self,argv=None,user_ns=None,user_global_ns=None,debug=1):
1111 def __init__(self,argv=None,user_ns=None,user_global_ns=None,debug=1):
1117 IPShellWX.__init__(self,argv,user_ns,user_global_ns,debug,
1112 IPShellWX.__init__(self,argv,user_ns,user_global_ns,debug,
1118 shell_class=MatplotlibMTShell)
1113 shell_class=MatplotlibMTShell)
1119 _load_pylab(self.IP.user_ns)
1114 _load_pylab(self.IP.user_ns)
1120
1115
1121 class IPShellMatplotlibQt(IPShellQt):
1116 class IPShellMatplotlibQt(IPShellQt):
1122 """Subclass IPShellQt with MatplotlibMTShell as the internal shell.
1117 """Subclass IPShellQt with MatplotlibMTShell as the internal shell.
1123
1118
1124 Multi-threaded class, meant for the Qt* backends."""
1119 Multi-threaded class, meant for the Qt* backends."""
1125
1120
1126 def __init__(self,argv=None,user_ns=None,user_global_ns=None,debug=1):
1121 def __init__(self,argv=None,user_ns=None,user_global_ns=None,debug=1):
1127 IPShellQt.__init__(self,argv,user_ns,user_global_ns,debug,
1122 IPShellQt.__init__(self,argv,user_ns,user_global_ns,debug,
1128 shell_class=MatplotlibMTShell)
1123 shell_class=MatplotlibMTShell)
1129 _load_pylab(self.IP.user_ns)
1124 _load_pylab(self.IP.user_ns)
1130
1125
1131 class IPShellMatplotlibQt4(IPShellQt4):
1126 class IPShellMatplotlibQt4(IPShellQt4):
1132 """Subclass IPShellQt4 with MatplotlibMTShell as the internal shell.
1127 """Subclass IPShellQt4 with MatplotlibMTShell as the internal shell.
1133
1128
1134 Multi-threaded class, meant for the Qt4* backends."""
1129 Multi-threaded class, meant for the Qt4* backends."""
1135
1130
1136 def __init__(self,argv=None,user_ns=None,user_global_ns=None,debug=1):
1131 def __init__(self,argv=None,user_ns=None,user_global_ns=None,debug=1):
1137 IPShellQt4.__init__(self,argv,user_ns,user_global_ns,debug,
1132 IPShellQt4.__init__(self,argv,user_ns,user_global_ns,debug,
1138 shell_class=MatplotlibMTShell)
1133 shell_class=MatplotlibMTShell)
1139 _load_pylab(self.IP.user_ns)
1134 _load_pylab(self.IP.user_ns)
1140
1135
1141 #-----------------------------------------------------------------------------
1136 #-----------------------------------------------------------------------------
1142 # Factory functions to actually start the proper thread-aware shell
1137 # Factory functions to actually start the proper thread-aware shell
1143
1138
1144 def _select_shell(argv):
1139 def _select_shell(argv):
1145 """Select a shell from the given argv vector.
1140 """Select a shell from the given argv vector.
1146
1141
1147 This function implements the threading selection policy, allowing runtime
1142 This function implements the threading selection policy, allowing runtime
1148 control of the threading mode, both for general users and for matplotlib.
1143 control of the threading mode, both for general users and for matplotlib.
1149
1144
1150 Return:
1145 Return:
1151 Shell class to be instantiated for runtime operation.
1146 Shell class to be instantiated for runtime operation.
1152 """
1147 """
1153
1148
1154 global USE_TK
1149 global USE_TK
1155
1150
1156 mpl_shell = {'gthread' : IPShellMatplotlibGTK,
1151 mpl_shell = {'gthread' : IPShellMatplotlibGTK,
1157 'wthread' : IPShellMatplotlibWX,
1152 'wthread' : IPShellMatplotlibWX,
1158 'qthread' : IPShellMatplotlibQt,
1153 'qthread' : IPShellMatplotlibQt,
1159 'q4thread' : IPShellMatplotlibQt4,
1154 'q4thread' : IPShellMatplotlibQt4,
1160 'tkthread' : IPShellMatplotlib, # Tk is built-in
1155 'tkthread' : IPShellMatplotlib, # Tk is built-in
1161 }
1156 }
1162
1157
1163 th_shell = {'gthread' : IPShellGTK,
1158 th_shell = {'gthread' : IPShellGTK,
1164 'wthread' : IPShellWX,
1159 'wthread' : IPShellWX,
1165 'qthread' : IPShellQt,
1160 'qthread' : IPShellQt,
1166 'q4thread' : IPShellQt4,
1161 'q4thread' : IPShellQt4,
1167 'tkthread' : IPShell, # Tk is built-in
1162 'tkthread' : IPShell, # Tk is built-in
1168 }
1163 }
1169
1164
1170 backends = {'gthread' : 'GTKAgg',
1165 backends = {'gthread' : 'GTKAgg',
1171 'wthread' : 'WXAgg',
1166 'wthread' : 'WXAgg',
1172 'qthread' : 'QtAgg',
1167 'qthread' : 'QtAgg',
1173 'q4thread' :'Qt4Agg',
1168 'q4thread' :'Qt4Agg',
1174 'tkthread' :'TkAgg',
1169 'tkthread' :'TkAgg',
1175 }
1170 }
1176
1171
1177 all_opts = set(['tk','pylab','gthread','qthread','q4thread','wthread',
1172 all_opts = set(['tk','pylab','gthread','qthread','q4thread','wthread',
1178 'tkthread'])
1173 'tkthread'])
1179 user_opts = set([s.replace('-','') for s in argv[:3]])
1174 user_opts = set([s.replace('-','') for s in argv[:3]])
1180 special_opts = user_opts & all_opts
1175 special_opts = user_opts & all_opts
1181
1176
1182 if 'tk' in special_opts:
1177 if 'tk' in special_opts:
1183 USE_TK = True
1178 USE_TK = True
1184 special_opts.remove('tk')
1179 special_opts.remove('tk')
1185
1180
1186 if 'pylab' in special_opts:
1181 if 'pylab' in special_opts:
1187
1182
1188 try:
1183 try:
1189 import matplotlib
1184 import matplotlib
1190 except ImportError:
1185 except ImportError:
1191 error('matplotlib could NOT be imported! Starting normal IPython.')
1186 error('matplotlib could NOT be imported! Starting normal IPython.')
1192 return IPShell
1187 return IPShell
1193
1188
1194 special_opts.remove('pylab')
1189 special_opts.remove('pylab')
1195 # If there's any option left, it means the user wants to force the
1190 # If there's any option left, it means the user wants to force the
1196 # threading backend, else it's auto-selected from the rc file
1191 # threading backend, else it's auto-selected from the rc file
1197 if special_opts:
1192 if special_opts:
1198 th_mode = special_opts.pop()
1193 th_mode = special_opts.pop()
1199 matplotlib.rcParams['backend'] = backends[th_mode]
1194 matplotlib.rcParams['backend'] = backends[th_mode]
1200 else:
1195 else:
1201 backend = matplotlib.rcParams['backend']
1196 backend = matplotlib.rcParams['backend']
1202 if backend.startswith('GTK'):
1197 if backend.startswith('GTK'):
1203 th_mode = 'gthread'
1198 th_mode = 'gthread'
1204 elif backend.startswith('WX'):
1199 elif backend.startswith('WX'):
1205 th_mode = 'wthread'
1200 th_mode = 'wthread'
1206 elif backend.startswith('Qt4'):
1201 elif backend.startswith('Qt4'):
1207 th_mode = 'q4thread'
1202 th_mode = 'q4thread'
1208 elif backend.startswith('Qt'):
1203 elif backend.startswith('Qt'):
1209 th_mode = 'qthread'
1204 th_mode = 'qthread'
1210 else:
1205 else:
1211 # Any other backend, use plain Tk
1206 # Any other backend, use plain Tk
1212 th_mode = 'tkthread'
1207 th_mode = 'tkthread'
1213
1208
1214 return mpl_shell[th_mode]
1209 return mpl_shell[th_mode]
1215 else:
1210 else:
1216 # No pylab requested, just plain threads
1211 # No pylab requested, just plain threads
1217 try:
1212 try:
1218 th_mode = special_opts.pop()
1213 th_mode = special_opts.pop()
1219 except KeyError:
1214 except KeyError:
1220 th_mode = 'tkthread'
1215 th_mode = 'tkthread'
1221 return th_shell[th_mode]
1216 return th_shell[th_mode]
1222
1217
1223
1218
1224 # This is the one which should be called by external code.
1219 # This is the one which should be called by external code.
1225 def start(user_ns = None):
1220 def start(user_ns = None):
1226 """Return a running shell instance, dealing with threading options.
1221 """Return a running shell instance, dealing with threading options.
1227
1222
1228 This is a factory function which will instantiate the proper IPython shell
1223 This is a factory function which will instantiate the proper IPython shell
1229 based on the user's threading choice. Such a selector is needed because
1224 based on the user's threading choice. Such a selector is needed because
1230 different GUI toolkits require different thread handling details."""
1225 different GUI toolkits require different thread handling details."""
1231
1226
1232 shell = _select_shell(sys.argv)
1227 shell = _select_shell(sys.argv)
1233 return shell(user_ns = user_ns)
1228 return shell(user_ns = user_ns)
1234
1229
1235 # Some aliases for backwards compatibility
1230 # Some aliases for backwards compatibility
1236 IPythonShell = IPShell
1231 IPythonShell = IPShell
1237 IPythonShellEmbed = IPShellEmbed
1232 IPythonShellEmbed = IPShellEmbed
1238 #************************ End of file <Shell.py> ***************************
1233 #************************ End of file <Shell.py> ***************************
@@ -1,72 +1,71 b''
1 # -*- coding: utf-8 -*-
1 # -*- coding: utf-8 -*-
2 """
2 """
3 IPython -- An enhanced Interactive Python
3 IPython -- An enhanced Interactive Python
4
4
5 One of Python's nicest features is its interactive interpreter. This allows
5 One of Python's nicest features is its interactive interpreter. This allows
6 very fast testing of ideas without the overhead of creating test files as is
6 very fast testing of ideas without the overhead of creating test files as is
7 typical in most programming languages. However, the interpreter supplied with
7 typical in most programming languages. However, the interpreter supplied with
8 the standard Python distribution is fairly primitive (and IDLE isn't really
8 the standard Python distribution is fairly primitive (and IDLE isn't really
9 much better).
9 much better).
10
10
11 IPython tries to:
11 IPython tries to:
12
12
13 i - provide an efficient environment for interactive work in Python
13 i - provide an efficient environment for interactive work in Python
14 programming. It tries to address what we see as shortcomings of the standard
14 programming. It tries to address what we see as shortcomings of the standard
15 Python prompt, and adds many features to make interactive work much more
15 Python prompt, and adds many features to make interactive work much more
16 efficient.
16 efficient.
17
17
18 ii - offer a flexible framework so that it can be used as the base
18 ii - offer a flexible framework so that it can be used as the base
19 environment for other projects and problems where Python can be the
19 environment for other projects and problems where Python can be the
20 underlying language. Specifically scientific environments like Mathematica,
20 underlying language. Specifically scientific environments like Mathematica,
21 IDL and Mathcad inspired its design, but similar ideas can be useful in many
21 IDL and Mathcad inspired its design, but similar ideas can be useful in many
22 fields. Python is a fabulous language for implementing this kind of system
22 fields. Python is a fabulous language for implementing this kind of system
23 (due to its dynamic and introspective features), and with suitable libraries
23 (due to its dynamic and introspective features), and with suitable libraries
24 entire systems could be built leveraging Python's power.
24 entire systems could be built leveraging Python's power.
25
25
26 iii - serve as an embeddable, ready to go interpreter for your own programs.
26 iii - serve as an embeddable, ready to go interpreter for your own programs.
27
27
28 IPython requires Python 2.3 or newer.
28 IPython requires Python 2.4 or newer.
29
29 """
30 $Id: __init__.py 2399 2007-05-26 10:23:10Z vivainio $"""
31
30
32 #*****************************************************************************
31 #*****************************************************************************
33 # Copyright (C) 2001-2006 Fernando Perez. <fperez@colorado.edu>
32 # Copyright (C) 2001-2006 Fernando Perez. <fperez@colorado.edu>
34 #
33 #
35 # Distributed under the terms of the BSD License. The full license is in
34 # Distributed under the terms of the BSD License. The full license is in
36 # the file COPYING, distributed as part of this software.
35 # the file COPYING, distributed as part of this software.
37 #*****************************************************************************
36 #*****************************************************************************
38
37
39 # Enforce proper version requirements
38 # Enforce proper version requirements
40 import sys
39 import sys
41
40
42 if sys.version[0:3] < '2.4':
41 if sys.version[0:3] < '2.4':
43 raise ImportError('Python Version 2.4 or above is required for IPython.')
42 raise ImportError('Python Version 2.4 or above is required for IPython.')
44
43
45 # Make it easy to import extensions - they are always directly on pythonpath.
44 # Make it easy to import extensions - they are always directly on pythonpath.
46 # Therefore, non-IPython modules can be added to Extensions directory
45 # Therefore, non-IPython modules can be added to Extensions directory
47 import os
46 import os
48 sys.path.append(os.path.dirname(__file__) + "/Extensions")
47 sys.path.append(os.path.dirname(__file__) + "/Extensions")
49
48
50 # Define what gets imported with a 'from IPython import *'
49 # Define what gets imported with a 'from IPython import *'
51 __all__ = ['ipapi','generics','ipstruct','Release','Shell']
50 __all__ = ['ipapi','generics','ipstruct','Release','Shell']
52
51
53 # Load __all__ in IPython namespace so that a simple 'import IPython' gives
52 # Load __all__ in IPython namespace so that a simple 'import IPython' gives
54 # access to them via IPython.<name>
53 # access to them via IPython.<name>
55 glob,loc = globals(),locals()
54 glob,loc = globals(),locals()
56 for name in __all__:
55 for name in __all__:
57 #print 'Importing: ',name # dbg
56 #print 'Importing: ',name # dbg
58 __import__(name,glob,loc,[])
57 __import__(name,glob,loc,[])
59
58
60 import Shell
59 import Shell
61
60
62 # Release data
61 # Release data
63 from IPython import Release # do it explicitly so pydoc can see it - pydoc bug
62 from IPython import Release # do it explicitly so pydoc can see it - pydoc bug
64 __author__ = '%s <%s>\n%s <%s>\n%s <%s>' % \
63 __author__ = '%s <%s>\n%s <%s>\n%s <%s>' % \
65 ( Release.authors['Fernando'] + Release.authors['Janko'] + \
64 ( Release.authors['Fernando'] + Release.authors['Janko'] + \
66 Release.authors['Nathan'] )
65 Release.authors['Nathan'] )
67 __license__ = Release.license
66 __license__ = Release.license
68 __version__ = Release.version
67 __version__ = Release.version
69 __revision__ = Release.revision
68 __revision__ = Release.revision
70
69
71 # Namespace cleanup
70 # Namespace cleanup
72 del name,glob,loc
71 del name,glob,loc
@@ -1,496 +1,490 b''
1 # -*- coding: utf-8 -*-
1 # -*- coding: utf-8 -*-
2 """Manage background (threaded) jobs conveniently from an interactive shell.
2 """Manage background (threaded) jobs conveniently from an interactive shell.
3
3
4 This module provides a BackgroundJobManager class. This is the main class
4 This module provides a BackgroundJobManager class. This is the main class
5 meant for public usage, it implements an object which can create and manage
5 meant for public usage, it implements an object which can create and manage
6 new background jobs.
6 new background jobs.
7
7
8 It also provides the actual job classes managed by these BackgroundJobManager
8 It also provides the actual job classes managed by these BackgroundJobManager
9 objects, see their docstrings below.
9 objects, see their docstrings below.
10
10
11
11
12 This system was inspired by discussions with B. Granger and the
12 This system was inspired by discussions with B. Granger and the
13 BackgroundCommand class described in the book Python Scripting for
13 BackgroundCommand class described in the book Python Scripting for
14 Computational Science, by H. P. Langtangen:
14 Computational Science, by H. P. Langtangen:
15
15
16 http://folk.uio.no/hpl/scripting
16 http://folk.uio.no/hpl/scripting
17
17
18 (although ultimately no code from this text was used, as IPython's system is a
18 (although ultimately no code from this text was used, as IPython's system is a
19 separate implementation).
19 separate implementation).
20
21 $Id: background_jobs.py 994 2006-01-08 08:29:44Z fperez $
22 """
20 """
23
21
24 #*****************************************************************************
22 #*****************************************************************************
25 # Copyright (C) 2005-2006 Fernando Perez <fperez@colorado.edu>
23 # Copyright (C) 2005-2006 Fernando Perez <fperez@colorado.edu>
26 #
24 #
27 # Distributed under the terms of the BSD License. The full license is in
25 # Distributed under the terms of the BSD License. The full license is in
28 # the file COPYING, distributed as part of this software.
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 # Code begins
29 # Code begins
36 import sys
30 import sys
37 import threading
31 import threading
38
32
39 from IPython.ultraTB import AutoFormattedTB
33 from IPython.ultraTB import AutoFormattedTB
40 from IPython.genutils import warn,error
34 from IPython.genutils import warn,error
41
35
42 class BackgroundJobManager:
36 class BackgroundJobManager:
43 """Class to manage a pool of backgrounded threaded jobs.
37 """Class to manage a pool of backgrounded threaded jobs.
44
38
45 Below, we assume that 'jobs' is a BackgroundJobManager instance.
39 Below, we assume that 'jobs' is a BackgroundJobManager instance.
46
40
47 Usage summary (see the method docstrings for details):
41 Usage summary (see the method docstrings for details):
48
42
49 jobs.new(...) -> start a new job
43 jobs.new(...) -> start a new job
50
44
51 jobs() or jobs.status() -> print status summary of all jobs
45 jobs() or jobs.status() -> print status summary of all jobs
52
46
53 jobs[N] -> returns job number N.
47 jobs[N] -> returns job number N.
54
48
55 foo = jobs[N].result -> assign to variable foo the result of job N
49 foo = jobs[N].result -> assign to variable foo the result of job N
56
50
57 jobs[N].traceback() -> print the traceback of dead job N
51 jobs[N].traceback() -> print the traceback of dead job N
58
52
59 jobs.remove(N) -> remove (finished) job N
53 jobs.remove(N) -> remove (finished) job N
60
54
61 jobs.flush_finished() -> remove all finished jobs
55 jobs.flush_finished() -> remove all finished jobs
62
56
63 As a convenience feature, BackgroundJobManager instances provide the
57 As a convenience feature, BackgroundJobManager instances provide the
64 utility result and traceback methods which retrieve the corresponding
58 utility result and traceback methods which retrieve the corresponding
65 information from the jobs list:
59 information from the jobs list:
66
60
67 jobs.result(N) <--> jobs[N].result
61 jobs.result(N) <--> jobs[N].result
68 jobs.traceback(N) <--> jobs[N].traceback()
62 jobs.traceback(N) <--> jobs[N].traceback()
69
63
70 While this appears minor, it allows you to use tab completion
64 While this appears minor, it allows you to use tab completion
71 interactively on the job manager instance.
65 interactively on the job manager instance.
72
66
73 In interactive mode, IPython provides the magic fuction %bg for quick
67 In interactive mode, IPython provides the magic fuction %bg for quick
74 creation of backgrounded expression-based jobs. Type bg? for details."""
68 creation of backgrounded expression-based jobs. Type bg? for details."""
75
69
76 def __init__(self):
70 def __init__(self):
77 # Lists for job management
71 # Lists for job management
78 self.jobs_run = []
72 self.jobs_run = []
79 self.jobs_comp = []
73 self.jobs_comp = []
80 self.jobs_dead = []
74 self.jobs_dead = []
81 # A dict of all jobs, so users can easily access any of them
75 # A dict of all jobs, so users can easily access any of them
82 self.jobs_all = {}
76 self.jobs_all = {}
83 # For reporting
77 # For reporting
84 self._comp_report = []
78 self._comp_report = []
85 self._dead_report = []
79 self._dead_report = []
86 # Store status codes locally for fast lookups
80 # Store status codes locally for fast lookups
87 self._s_created = BackgroundJobBase.stat_created_c
81 self._s_created = BackgroundJobBase.stat_created_c
88 self._s_running = BackgroundJobBase.stat_running_c
82 self._s_running = BackgroundJobBase.stat_running_c
89 self._s_completed = BackgroundJobBase.stat_completed_c
83 self._s_completed = BackgroundJobBase.stat_completed_c
90 self._s_dead = BackgroundJobBase.stat_dead_c
84 self._s_dead = BackgroundJobBase.stat_dead_c
91
85
92 def new(self,func_or_exp,*args,**kwargs):
86 def new(self,func_or_exp,*args,**kwargs):
93 """Add a new background job and start it in a separate thread.
87 """Add a new background job and start it in a separate thread.
94
88
95 There are two types of jobs which can be created:
89 There are two types of jobs which can be created:
96
90
97 1. Jobs based on expressions which can be passed to an eval() call.
91 1. Jobs based on expressions which can be passed to an eval() call.
98 The expression must be given as a string. For example:
92 The expression must be given as a string. For example:
99
93
100 job_manager.new('myfunc(x,y,z=1)'[,glob[,loc]])
94 job_manager.new('myfunc(x,y,z=1)'[,glob[,loc]])
101
95
102 The given expression is passed to eval(), along with the optional
96 The given expression is passed to eval(), along with the optional
103 global/local dicts provided. If no dicts are given, they are
97 global/local dicts provided. If no dicts are given, they are
104 extracted automatically from the caller's frame.
98 extracted automatically from the caller's frame.
105
99
106 A Python statement is NOT a valid eval() expression. Basically, you
100 A Python statement is NOT a valid eval() expression. Basically, you
107 can only use as an eval() argument something which can go on the right
101 can only use as an eval() argument something which can go on the right
108 of an '=' sign and be assigned to a variable.
102 of an '=' sign and be assigned to a variable.
109
103
110 For example,"print 'hello'" is not valid, but '2+3' is.
104 For example,"print 'hello'" is not valid, but '2+3' is.
111
105
112 2. Jobs given a function object, optionally passing additional
106 2. Jobs given a function object, optionally passing additional
113 positional arguments:
107 positional arguments:
114
108
115 job_manager.new(myfunc,x,y)
109 job_manager.new(myfunc,x,y)
116
110
117 The function is called with the given arguments.
111 The function is called with the given arguments.
118
112
119 If you need to pass keyword arguments to your function, you must
113 If you need to pass keyword arguments to your function, you must
120 supply them as a dict named kw:
114 supply them as a dict named kw:
121
115
122 job_manager.new(myfunc,x,y,kw=dict(z=1))
116 job_manager.new(myfunc,x,y,kw=dict(z=1))
123
117
124 The reason for this assymmetry is that the new() method needs to
118 The reason for this assymmetry is that the new() method needs to
125 maintain access to its own keywords, and this prevents name collisions
119 maintain access to its own keywords, and this prevents name collisions
126 between arguments to new() and arguments to your own functions.
120 between arguments to new() and arguments to your own functions.
127
121
128 In both cases, the result is stored in the job.result field of the
122 In both cases, the result is stored in the job.result field of the
129 background job object.
123 background job object.
130
124
131
125
132 Notes and caveats:
126 Notes and caveats:
133
127
134 1. All threads running share the same standard output. Thus, if your
128 1. All threads running share the same standard output. Thus, if your
135 background jobs generate output, it will come out on top of whatever
129 background jobs generate output, it will come out on top of whatever
136 you are currently writing. For this reason, background jobs are best
130 you are currently writing. For this reason, background jobs are best
137 used with silent functions which simply return their output.
131 used with silent functions which simply return their output.
138
132
139 2. Threads also all work within the same global namespace, and this
133 2. Threads also all work within the same global namespace, and this
140 system does not lock interactive variables. So if you send job to the
134 system does not lock interactive variables. So if you send job to the
141 background which operates on a mutable object for a long time, and
135 background which operates on a mutable object for a long time, and
142 start modifying that same mutable object interactively (or in another
136 start modifying that same mutable object interactively (or in another
143 backgrounded job), all sorts of bizarre behaviour will occur.
137 backgrounded job), all sorts of bizarre behaviour will occur.
144
138
145 3. If a background job is spending a lot of time inside a C extension
139 3. If a background job is spending a lot of time inside a C extension
146 module which does not release the Python Global Interpreter Lock
140 module which does not release the Python Global Interpreter Lock
147 (GIL), this will block the IPython prompt. This is simply because the
141 (GIL), this will block the IPython prompt. This is simply because the
148 Python interpreter can only switch between threads at Python
142 Python interpreter can only switch between threads at Python
149 bytecodes. While the execution is inside C code, the interpreter must
143 bytecodes. While the execution is inside C code, the interpreter must
150 simply wait unless the extension module releases the GIL.
144 simply wait unless the extension module releases the GIL.
151
145
152 4. There is no way, due to limitations in the Python threads library,
146 4. There is no way, due to limitations in the Python threads library,
153 to kill a thread once it has started."""
147 to kill a thread once it has started."""
154
148
155 if callable(func_or_exp):
149 if callable(func_or_exp):
156 kw = kwargs.get('kw',{})
150 kw = kwargs.get('kw',{})
157 job = BackgroundJobFunc(func_or_exp,*args,**kw)
151 job = BackgroundJobFunc(func_or_exp,*args,**kw)
158 elif isinstance(func_or_exp,basestring):
152 elif isinstance(func_or_exp,basestring):
159 if not args:
153 if not args:
160 frame = sys._getframe(1)
154 frame = sys._getframe(1)
161 glob, loc = frame.f_globals, frame.f_locals
155 glob, loc = frame.f_globals, frame.f_locals
162 elif len(args)==1:
156 elif len(args)==1:
163 glob = loc = args[0]
157 glob = loc = args[0]
164 elif len(args)==2:
158 elif len(args)==2:
165 glob,loc = args
159 glob,loc = args
166 else:
160 else:
167 raise ValueError,\
161 raise ValueError,\
168 'Expression jobs take at most 2 args (globals,locals)'
162 'Expression jobs take at most 2 args (globals,locals)'
169 job = BackgroundJobExpr(func_or_exp,glob,loc)
163 job = BackgroundJobExpr(func_or_exp,glob,loc)
170 else:
164 else:
171 raise
165 raise
172 jkeys = self.jobs_all.keys()
166 jkeys = self.jobs_all.keys()
173 if jkeys:
167 if jkeys:
174 job.num = max(jkeys)+1
168 job.num = max(jkeys)+1
175 else:
169 else:
176 job.num = 0
170 job.num = 0
177 self.jobs_run.append(job)
171 self.jobs_run.append(job)
178 self.jobs_all[job.num] = job
172 self.jobs_all[job.num] = job
179 print 'Starting job # %s in a separate thread.' % job.num
173 print 'Starting job # %s in a separate thread.' % job.num
180 job.start()
174 job.start()
181 return job
175 return job
182
176
183 def __getitem__(self,key):
177 def __getitem__(self,key):
184 return self.jobs_all[key]
178 return self.jobs_all[key]
185
179
186 def __call__(self):
180 def __call__(self):
187 """An alias to self.status(),
181 """An alias to self.status(),
188
182
189 This allows you to simply call a job manager instance much like the
183 This allows you to simply call a job manager instance much like the
190 Unix jobs shell command."""
184 Unix jobs shell command."""
191
185
192 return self.status()
186 return self.status()
193
187
194 def _update_status(self):
188 def _update_status(self):
195 """Update the status of the job lists.
189 """Update the status of the job lists.
196
190
197 This method moves finished jobs to one of two lists:
191 This method moves finished jobs to one of two lists:
198 - self.jobs_comp: jobs which completed successfully
192 - self.jobs_comp: jobs which completed successfully
199 - self.jobs_dead: jobs which finished but died.
193 - self.jobs_dead: jobs which finished but died.
200
194
201 It also copies those jobs to corresponding _report lists. These lists
195 It also copies those jobs to corresponding _report lists. These lists
202 are used to report jobs completed/dead since the last update, and are
196 are used to report jobs completed/dead since the last update, and are
203 then cleared by the reporting function after each call."""
197 then cleared by the reporting function after each call."""
204
198
205 run,comp,dead = self._s_running,self._s_completed,self._s_dead
199 run,comp,dead = self._s_running,self._s_completed,self._s_dead
206 jobs_run = self.jobs_run
200 jobs_run = self.jobs_run
207 for num in range(len(jobs_run)):
201 for num in range(len(jobs_run)):
208 job = jobs_run[num]
202 job = jobs_run[num]
209 stat = job.stat_code
203 stat = job.stat_code
210 if stat == run:
204 if stat == run:
211 continue
205 continue
212 elif stat == comp:
206 elif stat == comp:
213 self.jobs_comp.append(job)
207 self.jobs_comp.append(job)
214 self._comp_report.append(job)
208 self._comp_report.append(job)
215 jobs_run[num] = False
209 jobs_run[num] = False
216 elif stat == dead:
210 elif stat == dead:
217 self.jobs_dead.append(job)
211 self.jobs_dead.append(job)
218 self._dead_report.append(job)
212 self._dead_report.append(job)
219 jobs_run[num] = False
213 jobs_run[num] = False
220 self.jobs_run = filter(None,self.jobs_run)
214 self.jobs_run = filter(None,self.jobs_run)
221
215
222 def _group_report(self,group,name):
216 def _group_report(self,group,name):
223 """Report summary for a given job group.
217 """Report summary for a given job group.
224
218
225 Return True if the group had any elements."""
219 Return True if the group had any elements."""
226
220
227 if group:
221 if group:
228 print '%s jobs:' % name
222 print '%s jobs:' % name
229 for job in group:
223 for job in group:
230 print '%s : %s' % (job.num,job)
224 print '%s : %s' % (job.num,job)
231 print
225 print
232 return True
226 return True
233
227
234 def _group_flush(self,group,name):
228 def _group_flush(self,group,name):
235 """Flush a given job group
229 """Flush a given job group
236
230
237 Return True if the group had any elements."""
231 Return True if the group had any elements."""
238
232
239 njobs = len(group)
233 njobs = len(group)
240 if njobs:
234 if njobs:
241 plural = {1:''}.setdefault(njobs,'s')
235 plural = {1:''}.setdefault(njobs,'s')
242 print 'Flushing %s %s job%s.' % (njobs,name,plural)
236 print 'Flushing %s %s job%s.' % (njobs,name,plural)
243 group[:] = []
237 group[:] = []
244 return True
238 return True
245
239
246 def _status_new(self):
240 def _status_new(self):
247 """Print the status of newly finished jobs.
241 """Print the status of newly finished jobs.
248
242
249 Return True if any new jobs are reported.
243 Return True if any new jobs are reported.
250
244
251 This call resets its own state every time, so it only reports jobs
245 This call resets its own state every time, so it only reports jobs
252 which have finished since the last time it was called."""
246 which have finished since the last time it was called."""
253
247
254 self._update_status()
248 self._update_status()
255 new_comp = self._group_report(self._comp_report,'Completed')
249 new_comp = self._group_report(self._comp_report,'Completed')
256 new_dead = self._group_report(self._dead_report,
250 new_dead = self._group_report(self._dead_report,
257 'Dead, call job.traceback() for details')
251 'Dead, call job.traceback() for details')
258 self._comp_report[:] = []
252 self._comp_report[:] = []
259 self._dead_report[:] = []
253 self._dead_report[:] = []
260 return new_comp or new_dead
254 return new_comp or new_dead
261
255
262 def status(self,verbose=0):
256 def status(self,verbose=0):
263 """Print a status of all jobs currently being managed."""
257 """Print a status of all jobs currently being managed."""
264
258
265 self._update_status()
259 self._update_status()
266 self._group_report(self.jobs_run,'Running')
260 self._group_report(self.jobs_run,'Running')
267 self._group_report(self.jobs_comp,'Completed')
261 self._group_report(self.jobs_comp,'Completed')
268 self._group_report(self.jobs_dead,'Dead')
262 self._group_report(self.jobs_dead,'Dead')
269 # Also flush the report queues
263 # Also flush the report queues
270 self._comp_report[:] = []
264 self._comp_report[:] = []
271 self._dead_report[:] = []
265 self._dead_report[:] = []
272
266
273 def remove(self,num):
267 def remove(self,num):
274 """Remove a finished (completed or dead) job."""
268 """Remove a finished (completed or dead) job."""
275
269
276 try:
270 try:
277 job = self.jobs_all[num]
271 job = self.jobs_all[num]
278 except KeyError:
272 except KeyError:
279 error('Job #%s not found' % num)
273 error('Job #%s not found' % num)
280 else:
274 else:
281 stat_code = job.stat_code
275 stat_code = job.stat_code
282 if stat_code == self._s_running:
276 if stat_code == self._s_running:
283 error('Job #%s is still running, it can not be removed.' % num)
277 error('Job #%s is still running, it can not be removed.' % num)
284 return
278 return
285 elif stat_code == self._s_completed:
279 elif stat_code == self._s_completed:
286 self.jobs_comp.remove(job)
280 self.jobs_comp.remove(job)
287 elif stat_code == self._s_dead:
281 elif stat_code == self._s_dead:
288 self.jobs_dead.remove(job)
282 self.jobs_dead.remove(job)
289
283
290 def flush_finished(self):
284 def flush_finished(self):
291 """Flush all jobs finished (completed and dead) from lists.
285 """Flush all jobs finished (completed and dead) from lists.
292
286
293 Running jobs are never flushed.
287 Running jobs are never flushed.
294
288
295 It first calls _status_new(), to update info. If any jobs have
289 It first calls _status_new(), to update info. If any jobs have
296 completed since the last _status_new() call, the flush operation
290 completed since the last _status_new() call, the flush operation
297 aborts."""
291 aborts."""
298
292
299 if self._status_new():
293 if self._status_new():
300 error('New jobs completed since last '\
294 error('New jobs completed since last '\
301 '_status_new(), aborting flush.')
295 '_status_new(), aborting flush.')
302 return
296 return
303
297
304 # Remove the finished jobs from the master dict
298 # Remove the finished jobs from the master dict
305 jobs_all = self.jobs_all
299 jobs_all = self.jobs_all
306 for job in self.jobs_comp+self.jobs_dead:
300 for job in self.jobs_comp+self.jobs_dead:
307 del(jobs_all[job.num])
301 del(jobs_all[job.num])
308
302
309 # Now flush these lists completely
303 # Now flush these lists completely
310 fl_comp = self._group_flush(self.jobs_comp,'Completed')
304 fl_comp = self._group_flush(self.jobs_comp,'Completed')
311 fl_dead = self._group_flush(self.jobs_dead,'Dead')
305 fl_dead = self._group_flush(self.jobs_dead,'Dead')
312 if not (fl_comp or fl_dead):
306 if not (fl_comp or fl_dead):
313 print 'No jobs to flush.'
307 print 'No jobs to flush.'
314
308
315 def result(self,num):
309 def result(self,num):
316 """result(N) -> return the result of job N."""
310 """result(N) -> return the result of job N."""
317 try:
311 try:
318 return self.jobs_all[num].result
312 return self.jobs_all[num].result
319 except KeyError:
313 except KeyError:
320 error('Job #%s not found' % num)
314 error('Job #%s not found' % num)
321
315
322 def traceback(self,num):
316 def traceback(self,num):
323 try:
317 try:
324 self.jobs_all[num].traceback()
318 self.jobs_all[num].traceback()
325 except KeyError:
319 except KeyError:
326 error('Job #%s not found' % num)
320 error('Job #%s not found' % num)
327
321
328
322
329 class BackgroundJobBase(threading.Thread):
323 class BackgroundJobBase(threading.Thread):
330 """Base class to build BackgroundJob classes.
324 """Base class to build BackgroundJob classes.
331
325
332 The derived classes must implement:
326 The derived classes must implement:
333
327
334 - Their own __init__, since the one here raises NotImplementedError. The
328 - Their own __init__, since the one here raises NotImplementedError. The
335 derived constructor must call self._init() at the end, to provide common
329 derived constructor must call self._init() at the end, to provide common
336 initialization.
330 initialization.
337
331
338 - A strform attribute used in calls to __str__.
332 - A strform attribute used in calls to __str__.
339
333
340 - A call() method, which will make the actual execution call and must
334 - A call() method, which will make the actual execution call and must
341 return a value to be held in the 'result' field of the job object."""
335 return a value to be held in the 'result' field of the job object."""
342
336
343 # Class constants for status, in string and as numerical codes (when
337 # Class constants for status, in string and as numerical codes (when
344 # updating jobs lists, we don't want to do string comparisons). This will
338 # updating jobs lists, we don't want to do string comparisons). This will
345 # be done at every user prompt, so it has to be as fast as possible
339 # be done at every user prompt, so it has to be as fast as possible
346 stat_created = 'Created'; stat_created_c = 0
340 stat_created = 'Created'; stat_created_c = 0
347 stat_running = 'Running'; stat_running_c = 1
341 stat_running = 'Running'; stat_running_c = 1
348 stat_completed = 'Completed'; stat_completed_c = 2
342 stat_completed = 'Completed'; stat_completed_c = 2
349 stat_dead = 'Dead (Exception), call job.traceback() for details'
343 stat_dead = 'Dead (Exception), call job.traceback() for details'
350 stat_dead_c = -1
344 stat_dead_c = -1
351
345
352 def __init__(self):
346 def __init__(self):
353 raise NotImplementedError, \
347 raise NotImplementedError, \
354 "This class can not be instantiated directly."
348 "This class can not be instantiated directly."
355
349
356 def _init(self):
350 def _init(self):
357 """Common initialization for all BackgroundJob objects"""
351 """Common initialization for all BackgroundJob objects"""
358
352
359 for attr in ['call','strform']:
353 for attr in ['call','strform']:
360 assert hasattr(self,attr), "Missing attribute <%s>" % attr
354 assert hasattr(self,attr), "Missing attribute <%s>" % attr
361
355
362 # The num tag can be set by an external job manager
356 # The num tag can be set by an external job manager
363 self.num = None
357 self.num = None
364
358
365 self.status = BackgroundJobBase.stat_created
359 self.status = BackgroundJobBase.stat_created
366 self.stat_code = BackgroundJobBase.stat_created_c
360 self.stat_code = BackgroundJobBase.stat_created_c
367 self.finished = False
361 self.finished = False
368 self.result = '<BackgroundJob has not completed>'
362 self.result = '<BackgroundJob has not completed>'
369 # reuse the ipython traceback handler if we can get to it, otherwise
363 # reuse the ipython traceback handler if we can get to it, otherwise
370 # make a new one
364 # make a new one
371 try:
365 try:
372 self._make_tb = __IPYTHON__.InteractiveTB.text
366 self._make_tb = __IPYTHON__.InteractiveTB.text
373 except:
367 except:
374 self._make_tb = AutoFormattedTB(mode = 'Context',
368 self._make_tb = AutoFormattedTB(mode = 'Context',
375 color_scheme='NoColor',
369 color_scheme='NoColor',
376 tb_offset = 1).text
370 tb_offset = 1).text
377 # Hold a formatted traceback if one is generated.
371 # Hold a formatted traceback if one is generated.
378 self._tb = None
372 self._tb = None
379
373
380 threading.Thread.__init__(self)
374 threading.Thread.__init__(self)
381
375
382 def __str__(self):
376 def __str__(self):
383 return self.strform
377 return self.strform
384
378
385 def __repr__(self):
379 def __repr__(self):
386 return '<BackgroundJob: %s>' % self.strform
380 return '<BackgroundJob: %s>' % self.strform
387
381
388 def traceback(self):
382 def traceback(self):
389 print self._tb
383 print self._tb
390
384
391 def run(self):
385 def run(self):
392 try:
386 try:
393 self.status = BackgroundJobBase.stat_running
387 self.status = BackgroundJobBase.stat_running
394 self.stat_code = BackgroundJobBase.stat_running_c
388 self.stat_code = BackgroundJobBase.stat_running_c
395 self.result = self.call()
389 self.result = self.call()
396 except:
390 except:
397 self.status = BackgroundJobBase.stat_dead
391 self.status = BackgroundJobBase.stat_dead
398 self.stat_code = BackgroundJobBase.stat_dead_c
392 self.stat_code = BackgroundJobBase.stat_dead_c
399 self.finished = None
393 self.finished = None
400 self.result = ('<BackgroundJob died, call job.traceback() for details>')
394 self.result = ('<BackgroundJob died, call job.traceback() for details>')
401 self._tb = self._make_tb()
395 self._tb = self._make_tb()
402 else:
396 else:
403 self.status = BackgroundJobBase.stat_completed
397 self.status = BackgroundJobBase.stat_completed
404 self.stat_code = BackgroundJobBase.stat_completed_c
398 self.stat_code = BackgroundJobBase.stat_completed_c
405 self.finished = True
399 self.finished = True
406
400
407 class BackgroundJobExpr(BackgroundJobBase):
401 class BackgroundJobExpr(BackgroundJobBase):
408 """Evaluate an expression as a background job (uses a separate thread)."""
402 """Evaluate an expression as a background job (uses a separate thread)."""
409
403
410 def __init__(self,expression,glob=None,loc=None):
404 def __init__(self,expression,glob=None,loc=None):
411 """Create a new job from a string which can be fed to eval().
405 """Create a new job from a string which can be fed to eval().
412
406
413 global/locals dicts can be provided, which will be passed to the eval
407 global/locals dicts can be provided, which will be passed to the eval
414 call."""
408 call."""
415
409
416 # fail immediately if the given expression can't be compiled
410 # fail immediately if the given expression can't be compiled
417 self.code = compile(expression,'<BackgroundJob compilation>','eval')
411 self.code = compile(expression,'<BackgroundJob compilation>','eval')
418
412
419 if glob is None:
413 if glob is None:
420 glob = {}
414 glob = {}
421 if loc is None:
415 if loc is None:
422 loc = {}
416 loc = {}
423
417
424 self.expression = self.strform = expression
418 self.expression = self.strform = expression
425 self.glob = glob
419 self.glob = glob
426 self.loc = loc
420 self.loc = loc
427 self._init()
421 self._init()
428
422
429 def call(self):
423 def call(self):
430 return eval(self.code,self.glob,self.loc)
424 return eval(self.code,self.glob,self.loc)
431
425
432 class BackgroundJobFunc(BackgroundJobBase):
426 class BackgroundJobFunc(BackgroundJobBase):
433 """Run a function call as a background job (uses a separate thread)."""
427 """Run a function call as a background job (uses a separate thread)."""
434
428
435 def __init__(self,func,*args,**kwargs):
429 def __init__(self,func,*args,**kwargs):
436 """Create a new job from a callable object.
430 """Create a new job from a callable object.
437
431
438 Any positional arguments and keyword args given to this constructor
432 Any positional arguments and keyword args given to this constructor
439 after the initial callable are passed directly to it."""
433 after the initial callable are passed directly to it."""
440
434
441 assert callable(func),'first argument must be callable'
435 assert callable(func),'first argument must be callable'
442
436
443 if args is None:
437 if args is None:
444 args = []
438 args = []
445 if kwargs is None:
439 if kwargs is None:
446 kwargs = {}
440 kwargs = {}
447
441
448 self.func = func
442 self.func = func
449 self.args = args
443 self.args = args
450 self.kwargs = kwargs
444 self.kwargs = kwargs
451 # The string form will only include the function passed, because
445 # The string form will only include the function passed, because
452 # generating string representations of the arguments is a potentially
446 # generating string representations of the arguments is a potentially
453 # _very_ expensive operation (e.g. with large arrays).
447 # _very_ expensive operation (e.g. with large arrays).
454 self.strform = str(func)
448 self.strform = str(func)
455 self._init()
449 self._init()
456
450
457 def call(self):
451 def call(self):
458 return self.func(*self.args,**self.kwargs)
452 return self.func(*self.args,**self.kwargs)
459
453
460
454
461 if __name__=='__main__':
455 if __name__=='__main__':
462
456
463 import time
457 import time
464
458
465 def sleepfunc(interval=2,*a,**kw):
459 def sleepfunc(interval=2,*a,**kw):
466 args = dict(interval=interval,
460 args = dict(interval=interval,
467 args=a,
461 args=a,
468 kwargs=kw)
462 kwargs=kw)
469 time.sleep(interval)
463 time.sleep(interval)
470 return args
464 return args
471
465
472 def diefunc(interval=2,*a,**kw):
466 def diefunc(interval=2,*a,**kw):
473 time.sleep(interval)
467 time.sleep(interval)
474 die
468 die
475
469
476 def printfunc(interval=1,reps=5):
470 def printfunc(interval=1,reps=5):
477 for n in range(reps):
471 for n in range(reps):
478 time.sleep(interval)
472 time.sleep(interval)
479 print 'In the background...'
473 print 'In the background...'
480
474
481 jobs = BackgroundJobManager()
475 jobs = BackgroundJobManager()
482 # first job will have # 0
476 # first job will have # 0
483 jobs.new(sleepfunc,4)
477 jobs.new(sleepfunc,4)
484 jobs.new(sleepfunc,kw={'reps':2})
478 jobs.new(sleepfunc,kw={'reps':2})
485 # This makes a job which will die
479 # This makes a job which will die
486 jobs.new(diefunc,1)
480 jobs.new(diefunc,1)
487 jobs.new('printfunc(1,3)')
481 jobs.new('printfunc(1,3)')
488
482
489 # after a while, you can get the traceback of a dead job. Run the line
483 # after a while, you can get the traceback of a dead job. Run the line
490 # below again interactively until it prints a traceback (check the status
484 # below again interactively until it prints a traceback (check the status
491 # of the job):
485 # of the job):
492 print jobs[1].status
486 print jobs[1].status
493 jobs[1].traceback()
487 jobs[1].traceback()
494
488
495 # Run this line again until the printed result changes
489 # Run this line again until the printed result changes
496 print "The result of job #0 is:",jobs[0].result
490 print "The result of job #0 is:",jobs[0].result
@@ -1,189 +1,182 b''
1 # -*- coding: utf-8 -*-
1 # -*- coding: utf-8 -*-
2 """
2 """
3 A module to change reload() so that it acts recursively.
3 A module to change reload() so that it acts recursively.
4 To enable it type:
4 To enable it type:
5 >>> import __builtin__, deep_reload
5 >>> import __builtin__, deep_reload
6 >>> __builtin__.reload = deep_reload.reload
6 >>> __builtin__.reload = deep_reload.reload
7
7
8 You can then disable it with:
8 You can then disable it with:
9 >>> __builtin__.reload = deep_reload.original_reload
9 >>> __builtin__.reload = deep_reload.original_reload
10
10
11 Alternatively, you can add a dreload builtin alongside normal reload with:
11 Alternatively, you can add a dreload builtin alongside normal reload with:
12 >>> __builtin__.dreload = deep_reload.reload
12 >>> __builtin__.dreload = deep_reload.reload
13
13
14 This code is almost entirely based on knee.py from the standard library.
14 This code is almost entirely based on knee.py from the standard library.
15
15 """
16 $Id: deep_reload.py 958 2005-12-27 23:17:51Z fperez $"""
17
16
18 #*****************************************************************************
17 #*****************************************************************************
19 # Copyright (C) 2001 Nathaniel Gray <n8gray@caltech.edu>
18 # Copyright (C) 2001 Nathaniel Gray <n8gray@caltech.edu>
20 #
19 #
21 # Distributed under the terms of the BSD License. The full license is in
20 # Distributed under the terms of the BSD License. The full license is in
22 # the file COPYING, distributed as part of this software.
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 import __builtin__
24 import __builtin__
32 import imp
25 import imp
33 import sys
26 import sys
34
27
35 # Replacement for __import__()
28 # Replacement for __import__()
36 def deep_import_hook(name, globals=None, locals=None, fromlist=None, level=-1):
29 def deep_import_hook(name, globals=None, locals=None, fromlist=None, level=-1):
37 # For now level is ignored, it's just there to prevent crash
30 # For now level is ignored, it's just there to prevent crash
38 # with from __future__ import absolute_import
31 # with from __future__ import absolute_import
39 parent = determine_parent(globals)
32 parent = determine_parent(globals)
40 q, tail = find_head_package(parent, name)
33 q, tail = find_head_package(parent, name)
41 m = load_tail(q, tail)
34 m = load_tail(q, tail)
42 if not fromlist:
35 if not fromlist:
43 return q
36 return q
44 if hasattr(m, "__path__"):
37 if hasattr(m, "__path__"):
45 ensure_fromlist(m, fromlist)
38 ensure_fromlist(m, fromlist)
46 return m
39 return m
47
40
48 def determine_parent(globals):
41 def determine_parent(globals):
49 if not globals or not globals.has_key("__name__"):
42 if not globals or not globals.has_key("__name__"):
50 return None
43 return None
51 pname = globals['__name__']
44 pname = globals['__name__']
52 if globals.has_key("__path__"):
45 if globals.has_key("__path__"):
53 parent = sys.modules[pname]
46 parent = sys.modules[pname]
54 assert globals is parent.__dict__
47 assert globals is parent.__dict__
55 return parent
48 return parent
56 if '.' in pname:
49 if '.' in pname:
57 i = pname.rfind('.')
50 i = pname.rfind('.')
58 pname = pname[:i]
51 pname = pname[:i]
59 parent = sys.modules[pname]
52 parent = sys.modules[pname]
60 assert parent.__name__ == pname
53 assert parent.__name__ == pname
61 return parent
54 return parent
62 return None
55 return None
63
56
64 def find_head_package(parent, name):
57 def find_head_package(parent, name):
65 # Import the first
58 # Import the first
66 if '.' in name:
59 if '.' in name:
67 # 'some.nested.package' -> head = 'some', tail = 'nested.package'
60 # 'some.nested.package' -> head = 'some', tail = 'nested.package'
68 i = name.find('.')
61 i = name.find('.')
69 head = name[:i]
62 head = name[:i]
70 tail = name[i+1:]
63 tail = name[i+1:]
71 else:
64 else:
72 # 'packagename' -> head = 'packagename', tail = ''
65 # 'packagename' -> head = 'packagename', tail = ''
73 head = name
66 head = name
74 tail = ""
67 tail = ""
75 if parent:
68 if parent:
76 # If this is a subpackage then qname = parent's name + head
69 # If this is a subpackage then qname = parent's name + head
77 qname = "%s.%s" % (parent.__name__, head)
70 qname = "%s.%s" % (parent.__name__, head)
78 else:
71 else:
79 qname = head
72 qname = head
80 q = import_module(head, qname, parent)
73 q = import_module(head, qname, parent)
81 if q: return q, tail
74 if q: return q, tail
82 if parent:
75 if parent:
83 qname = head
76 qname = head
84 parent = None
77 parent = None
85 q = import_module(head, qname, parent)
78 q = import_module(head, qname, parent)
86 if q: return q, tail
79 if q: return q, tail
87 raise ImportError, "No module named " + qname
80 raise ImportError, "No module named " + qname
88
81
89 def load_tail(q, tail):
82 def load_tail(q, tail):
90 m = q
83 m = q
91 while tail:
84 while tail:
92 i = tail.find('.')
85 i = tail.find('.')
93 if i < 0: i = len(tail)
86 if i < 0: i = len(tail)
94 head, tail = tail[:i], tail[i+1:]
87 head, tail = tail[:i], tail[i+1:]
95
88
96 # fperez: fix dotted.name reloading failures by changing:
89 # fperez: fix dotted.name reloading failures by changing:
97 #mname = "%s.%s" % (m.__name__, head)
90 #mname = "%s.%s" % (m.__name__, head)
98 # to:
91 # to:
99 mname = m.__name__
92 mname = m.__name__
100 # This needs more testing!!! (I don't understand this module too well)
93 # This needs more testing!!! (I don't understand this module too well)
101
94
102 #print '** head,tail=|%s|->|%s|, mname=|%s|' % (head,tail,mname) # dbg
95 #print '** head,tail=|%s|->|%s|, mname=|%s|' % (head,tail,mname) # dbg
103 m = import_module(head, mname, m)
96 m = import_module(head, mname, m)
104 if not m:
97 if not m:
105 raise ImportError, "No module named " + mname
98 raise ImportError, "No module named " + mname
106 return m
99 return m
107
100
108 def ensure_fromlist(m, fromlist, recursive=0):
101 def ensure_fromlist(m, fromlist, recursive=0):
109 for sub in fromlist:
102 for sub in fromlist:
110 if sub == "*":
103 if sub == "*":
111 if not recursive:
104 if not recursive:
112 try:
105 try:
113 all = m.__all__
106 all = m.__all__
114 except AttributeError:
107 except AttributeError:
115 pass
108 pass
116 else:
109 else:
117 ensure_fromlist(m, all, 1)
110 ensure_fromlist(m, all, 1)
118 continue
111 continue
119 if sub != "*" and not hasattr(m, sub):
112 if sub != "*" and not hasattr(m, sub):
120 subname = "%s.%s" % (m.__name__, sub)
113 subname = "%s.%s" % (m.__name__, sub)
121 submod = import_module(sub, subname, m)
114 submod = import_module(sub, subname, m)
122 if not submod:
115 if not submod:
123 raise ImportError, "No module named " + subname
116 raise ImportError, "No module named " + subname
124
117
125 # Need to keep track of what we've already reloaded to prevent cyclic evil
118 # Need to keep track of what we've already reloaded to prevent cyclic evil
126 found_now = {}
119 found_now = {}
127
120
128 def import_module(partname, fqname, parent):
121 def import_module(partname, fqname, parent):
129 global found_now
122 global found_now
130 if found_now.has_key(fqname):
123 if found_now.has_key(fqname):
131 try:
124 try:
132 return sys.modules[fqname]
125 return sys.modules[fqname]
133 except KeyError:
126 except KeyError:
134 pass
127 pass
135
128
136 print 'Reloading', fqname #, sys.excepthook is sys.__excepthook__, \
129 print 'Reloading', fqname #, sys.excepthook is sys.__excepthook__, \
137 #sys.displayhook is sys.__displayhook__
130 #sys.displayhook is sys.__displayhook__
138
131
139 found_now[fqname] = 1
132 found_now[fqname] = 1
140 try:
133 try:
141 fp, pathname, stuff = imp.find_module(partname,
134 fp, pathname, stuff = imp.find_module(partname,
142 parent and parent.__path__)
135 parent and parent.__path__)
143 except ImportError:
136 except ImportError:
144 return None
137 return None
145
138
146 try:
139 try:
147 m = imp.load_module(fqname, fp, pathname, stuff)
140 m = imp.load_module(fqname, fp, pathname, stuff)
148 finally:
141 finally:
149 if fp: fp.close()
142 if fp: fp.close()
150
143
151 if parent:
144 if parent:
152 setattr(parent, partname, m)
145 setattr(parent, partname, m)
153
146
154 return m
147 return m
155
148
156 def deep_reload_hook(module):
149 def deep_reload_hook(module):
157 name = module.__name__
150 name = module.__name__
158 if '.' not in name:
151 if '.' not in name:
159 return import_module(name, name, None)
152 return import_module(name, name, None)
160 i = name.rfind('.')
153 i = name.rfind('.')
161 pname = name[:i]
154 pname = name[:i]
162 parent = sys.modules[pname]
155 parent = sys.modules[pname]
163 return import_module(name[i+1:], name, parent)
156 return import_module(name[i+1:], name, parent)
164
157
165 # Save the original hooks
158 # Save the original hooks
166 original_reload = __builtin__.reload
159 original_reload = __builtin__.reload
167
160
168 # Replacement for reload()
161 # Replacement for reload()
169 def reload(module, exclude=['sys', '__builtin__', '__main__']):
162 def reload(module, exclude=['sys', '__builtin__', '__main__']):
170 """Recursively reload all modules used in the given module. Optionally
163 """Recursively reload all modules used in the given module. Optionally
171 takes a list of modules to exclude from reloading. The default exclude
164 takes a list of modules to exclude from reloading. The default exclude
172 list contains sys, __main__, and __builtin__, to prevent, e.g., resetting
165 list contains sys, __main__, and __builtin__, to prevent, e.g., resetting
173 display, exception, and io hooks.
166 display, exception, and io hooks.
174 """
167 """
175 global found_now
168 global found_now
176 for i in exclude:
169 for i in exclude:
177 found_now[i] = 1
170 found_now[i] = 1
178 original_import = __builtin__.__import__
171 original_import = __builtin__.__import__
179 __builtin__.__import__ = deep_import_hook
172 __builtin__.__import__ = deep_import_hook
180 try:
173 try:
181 ret = deep_reload_hook(module)
174 ret = deep_reload_hook(module)
182 finally:
175 finally:
183 __builtin__.__import__ = original_import
176 __builtin__.__import__ = original_import
184 found_now = {}
177 found_now = {}
185 return ret
178 return ret
186
179
187 # Uncomment the following to automatically activate deep reloading whenever
180 # Uncomment the following to automatically activate deep reloading whenever
188 # this module is imported
181 # this module is imported
189 #__builtin__.reload = reload
182 #__builtin__.reload = reload
@@ -1,143 +1,137 b''
1 # -*- coding: utf-8 -*-
1 # -*- coding: utf-8 -*-
2 """
2 """
3 Color schemes for exception handling code in IPython.
3 Color schemes for exception handling code in IPython.
4
4 """
5 $Id: Prompts.py 638 2005-07-18 03:01:41Z fperez $"""
6
5
7 #*****************************************************************************
6 #*****************************************************************************
8 # Copyright (C) 2005-2006 Fernando Perez <fperez@colorado.edu>
7 # Copyright (C) 2005-2006 Fernando Perez <fperez@colorado.edu>
9 #
8 #
10 # Distributed under the terms of the BSD License. The full license is in
9 # Distributed under the terms of the BSD License. The full license is in
11 # the file COPYING, distributed as part of this software.
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 # Required modules
14 # Required modules
21 from IPython.ColorANSI import ColorSchemeTable, TermColors, ColorScheme
15 from IPython.ColorANSI import ColorSchemeTable, TermColors, ColorScheme
22
16
23 def exception_colors():
17 def exception_colors():
24 """Return a color table with fields for exception reporting.
18 """Return a color table with fields for exception reporting.
25
19
26 The table is an instance of ColorSchemeTable with schemes added for
20 The table is an instance of ColorSchemeTable with schemes added for
27 'Linux', 'LightBG' and 'NoColor' and fields for exception handling filled
21 'Linux', 'LightBG' and 'NoColor' and fields for exception handling filled
28 in.
22 in.
29
23
30 Examples:
24 Examples:
31
25
32 >>> ec = exception_colors()
26 >>> ec = exception_colors()
33 >>> ec.active_scheme_name
27 >>> ec.active_scheme_name
34 ''
28 ''
35 >>> print ec.active_colors
29 >>> print ec.active_colors
36 None
30 None
37
31
38 Now we activate a color scheme:
32 Now we activate a color scheme:
39 >>> ec.set_active_scheme('NoColor')
33 >>> ec.set_active_scheme('NoColor')
40 >>> ec.active_scheme_name
34 >>> ec.active_scheme_name
41 'NoColor'
35 'NoColor'
42 >>> ec.active_colors.keys()
36 >>> ec.active_colors.keys()
43 ['em', 'caret', '__allownew', 'name', 'val', 'vName', 'Normal', 'normalEm',
37 ['em', 'caret', '__allownew', 'name', 'val', 'vName', 'Normal', 'normalEm',
44 'filename', 'linenoEm', 'excName', 'lineno', 'valEm', 'filenameEm',
38 'filename', 'linenoEm', 'excName', 'lineno', 'valEm', 'filenameEm',
45 'nameEm', 'line', 'topline']
39 'nameEm', 'line', 'topline']
46 """
40 """
47
41
48 ex_colors = ColorSchemeTable()
42 ex_colors = ColorSchemeTable()
49
43
50 # Populate it with color schemes
44 # Populate it with color schemes
51 C = TermColors # shorthand and local lookup
45 C = TermColors # shorthand and local lookup
52 ex_colors.add_scheme(ColorScheme(
46 ex_colors.add_scheme(ColorScheme(
53 'NoColor',
47 'NoColor',
54 # The color to be used for the top line
48 # The color to be used for the top line
55 topline = C.NoColor,
49 topline = C.NoColor,
56
50
57 # The colors to be used in the traceback
51 # The colors to be used in the traceback
58 filename = C.NoColor,
52 filename = C.NoColor,
59 lineno = C.NoColor,
53 lineno = C.NoColor,
60 name = C.NoColor,
54 name = C.NoColor,
61 vName = C.NoColor,
55 vName = C.NoColor,
62 val = C.NoColor,
56 val = C.NoColor,
63 em = C.NoColor,
57 em = C.NoColor,
64
58
65 # Emphasized colors for the last frame of the traceback
59 # Emphasized colors for the last frame of the traceback
66 normalEm = C.NoColor,
60 normalEm = C.NoColor,
67 filenameEm = C.NoColor,
61 filenameEm = C.NoColor,
68 linenoEm = C.NoColor,
62 linenoEm = C.NoColor,
69 nameEm = C.NoColor,
63 nameEm = C.NoColor,
70 valEm = C.NoColor,
64 valEm = C.NoColor,
71
65
72 # Colors for printing the exception
66 # Colors for printing the exception
73 excName = C.NoColor,
67 excName = C.NoColor,
74 line = C.NoColor,
68 line = C.NoColor,
75 caret = C.NoColor,
69 caret = C.NoColor,
76 Normal = C.NoColor
70 Normal = C.NoColor
77 ))
71 ))
78
72
79 # make some schemes as instances so we can copy them for modification easily
73 # make some schemes as instances so we can copy them for modification easily
80 ex_colors.add_scheme(ColorScheme(
74 ex_colors.add_scheme(ColorScheme(
81 'Linux',
75 'Linux',
82 # The color to be used for the top line
76 # The color to be used for the top line
83 topline = C.LightRed,
77 topline = C.LightRed,
84
78
85 # The colors to be used in the traceback
79 # The colors to be used in the traceback
86 filename = C.Green,
80 filename = C.Green,
87 lineno = C.Green,
81 lineno = C.Green,
88 name = C.Purple,
82 name = C.Purple,
89 vName = C.Cyan,
83 vName = C.Cyan,
90 val = C.Green,
84 val = C.Green,
91 em = C.LightCyan,
85 em = C.LightCyan,
92
86
93 # Emphasized colors for the last frame of the traceback
87 # Emphasized colors for the last frame of the traceback
94 normalEm = C.LightCyan,
88 normalEm = C.LightCyan,
95 filenameEm = C.LightGreen,
89 filenameEm = C.LightGreen,
96 linenoEm = C.LightGreen,
90 linenoEm = C.LightGreen,
97 nameEm = C.LightPurple,
91 nameEm = C.LightPurple,
98 valEm = C.LightBlue,
92 valEm = C.LightBlue,
99
93
100 # Colors for printing the exception
94 # Colors for printing the exception
101 excName = C.LightRed,
95 excName = C.LightRed,
102 line = C.Yellow,
96 line = C.Yellow,
103 caret = C.White,
97 caret = C.White,
104 Normal = C.Normal
98 Normal = C.Normal
105 ))
99 ))
106
100
107 # For light backgrounds, swap dark/light colors
101 # For light backgrounds, swap dark/light colors
108 ex_colors.add_scheme(ColorScheme(
102 ex_colors.add_scheme(ColorScheme(
109 'LightBG',
103 'LightBG',
110 # The color to be used for the top line
104 # The color to be used for the top line
111 topline = C.Red,
105 topline = C.Red,
112
106
113 # The colors to be used in the traceback
107 # The colors to be used in the traceback
114 filename = C.LightGreen,
108 filename = C.LightGreen,
115 lineno = C.LightGreen,
109 lineno = C.LightGreen,
116 name = C.LightPurple,
110 name = C.LightPurple,
117 vName = C.Cyan,
111 vName = C.Cyan,
118 val = C.LightGreen,
112 val = C.LightGreen,
119 em = C.Cyan,
113 em = C.Cyan,
120
114
121 # Emphasized colors for the last frame of the traceback
115 # Emphasized colors for the last frame of the traceback
122 normalEm = C.Cyan,
116 normalEm = C.Cyan,
123 filenameEm = C.Green,
117 filenameEm = C.Green,
124 linenoEm = C.Green,
118 linenoEm = C.Green,
125 nameEm = C.Purple,
119 nameEm = C.Purple,
126 valEm = C.Blue,
120 valEm = C.Blue,
127
121
128 # Colors for printing the exception
122 # Colors for printing the exception
129 excName = C.Red,
123 excName = C.Red,
130 #line = C.Brown, # brown often is displayed as yellow
124 #line = C.Brown, # brown often is displayed as yellow
131 line = C.Red,
125 line = C.Red,
132 caret = C.Normal,
126 caret = C.Normal,
133 Normal = C.Normal
127 Normal = C.Normal
134 ))
128 ))
135
129
136 return ex_colors
130 return ex_colors
137
131
138
132
139 # For backwards compatibility, keep around a single global object. Note that
133 # For backwards compatibility, keep around a single global object. Note that
140 # this should NOT be used, the factory function should be used instead, since
134 # this should NOT be used, the factory function should be used instead, since
141 # these objects are stateful and it's very easy to get strange bugs if any code
135 # these objects are stateful and it's very easy to get strange bugs if any code
142 # modifies the module-level object's state.
136 # modifies the module-level object's state.
143 ExceptionColors = exception_colors()
137 ExceptionColors = exception_colors()
@@ -1,278 +1,276 b''
1 # -*- coding: utf-8 -*-
1 # -*- coding: utf-8 -*-
2 """String interpolation for Python (by Ka-Ping Yee, 14 Feb 2000).
2 """String interpolation for Python (by Ka-Ping Yee, 14 Feb 2000).
3
3
4 This module lets you quickly and conveniently interpolate values into
4 This module lets you quickly and conveniently interpolate values into
5 strings (in the flavour of Perl or Tcl, but with less extraneous
5 strings (in the flavour of Perl or Tcl, but with less extraneous
6 punctuation). You get a bit more power than in the other languages,
6 punctuation). You get a bit more power than in the other languages,
7 because this module allows subscripting, slicing, function calls,
7 because this module allows subscripting, slicing, function calls,
8 attribute lookup, or arbitrary expressions. Variables and expressions
8 attribute lookup, or arbitrary expressions. Variables and expressions
9 are evaluated in the namespace of the caller.
9 are evaluated in the namespace of the caller.
10
10
11 The itpl() function returns the result of interpolating a string, and
11 The itpl() function returns the result of interpolating a string, and
12 printpl() prints out an interpolated string. Here are some examples:
12 printpl() prints out an interpolated string. Here are some examples:
13
13
14 from Itpl import printpl
14 from Itpl import printpl
15 printpl("Here is a $string.")
15 printpl("Here is a $string.")
16 printpl("Here is a $module.member.")
16 printpl("Here is a $module.member.")
17 printpl("Here is an $object.member.")
17 printpl("Here is an $object.member.")
18 printpl("Here is a $functioncall(with, arguments).")
18 printpl("Here is a $functioncall(with, arguments).")
19 printpl("Here is an ${arbitrary + expression}.")
19 printpl("Here is an ${arbitrary + expression}.")
20 printpl("Here is an $array[3] member.")
20 printpl("Here is an $array[3] member.")
21 printpl("Here is a $dictionary['member'].")
21 printpl("Here is a $dictionary['member'].")
22
22
23 The filter() function filters a file object so that output through it
23 The filter() function filters a file object so that output through it
24 is interpolated. This lets you produce the illusion that Python knows
24 is interpolated. This lets you produce the illusion that Python knows
25 how to do interpolation:
25 how to do interpolation:
26
26
27 import Itpl
27 import Itpl
28 sys.stdout = Itpl.filter()
28 sys.stdout = Itpl.filter()
29 f = "fancy"
29 f = "fancy"
30 print "Isn't this $f?"
30 print "Is this not $f?"
31 print "Standard output has been replaced with a $sys.stdout object."
31 print "Standard output has been replaced with a $sys.stdout object."
32 sys.stdout = Itpl.unfilter()
32 sys.stdout = Itpl.unfilter()
33 print "Okay, back $to $normal."
33 print "Okay, back $to $normal."
34
34
35 Under the hood, the Itpl class represents a string that knows how to
35 Under the hood, the Itpl class represents a string that knows how to
36 interpolate values. An instance of the class parses the string once
36 interpolate values. An instance of the class parses the string once
37 upon initialization; the evaluation and substitution can then be done
37 upon initialization; the evaluation and substitution can then be done
38 each time the instance is evaluated with str(instance). For example:
38 each time the instance is evaluated with str(instance). For example:
39
39
40 from Itpl import Itpl
40 from Itpl import Itpl
41 s = Itpl("Here is $foo.")
41 s = Itpl("Here is $foo.")
42 foo = 5
42 foo = 5
43 print str(s)
43 print str(s)
44 foo = "bar"
44 foo = "bar"
45 print str(s)
45 print str(s)
46
46 """
47 $Id: Itpl.py 2305 2007-05-04 05:34:42Z bgranger $
48 """ # ' -> close an open quote for stupid emacs
49
47
50 #*****************************************************************************
48 #*****************************************************************************
51 #
49 #
52 # Copyright (c) 2001 Ka-Ping Yee <ping@lfw.org>
50 # Copyright (c) 2001 Ka-Ping Yee <ping@lfw.org>
53 #
51 #
54 #
52 #
55 # Published under the terms of the MIT license, hereby reproduced:
53 # Published under the terms of the MIT license, hereby reproduced:
56 #
54 #
57 # Permission is hereby granted, free of charge, to any person obtaining a copy
55 # Permission is hereby granted, free of charge, to any person obtaining a copy
58 # of this software and associated documentation files (the "Software"), to
56 # of this software and associated documentation files (the "Software"), to
59 # deal in the Software without restriction, including without limitation the
57 # deal in the Software without restriction, including without limitation the
60 # rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
58 # rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
61 # sell copies of the Software, and to permit persons to whom the Software is
59 # sell copies of the Software, and to permit persons to whom the Software is
62 # furnished to do so, subject to the following conditions:
60 # furnished to do so, subject to the following conditions:
63 #
61 #
64 # The above copyright notice and this permission notice shall be included in
62 # The above copyright notice and this permission notice shall be included in
65 # all copies or substantial portions of the Software.
63 # all copies or substantial portions of the Software.
66 #
64 #
67 # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
65 # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
68 # IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
66 # IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
69 # FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
67 # FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
70 # AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
68 # AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
71 # LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
69 # LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
72 # FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
70 # FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
73 # IN THE SOFTWARE.
71 # IN THE SOFTWARE.
74 #
72 #
75 #*****************************************************************************
73 #*****************************************************************************
76
74
77 __author__ = 'Ka-Ping Yee <ping@lfw.org>'
75 __author__ = 'Ka-Ping Yee <ping@lfw.org>'
78 __license__ = 'MIT'
76 __license__ = 'MIT'
79
77
80 import string
78 import string
81 import sys
79 import sys
82 from tokenize import tokenprog
80 from tokenize import tokenprog
83 from types import StringType
81 from types import StringType
84
82
85 class ItplError(ValueError):
83 class ItplError(ValueError):
86 def __init__(self, text, pos):
84 def __init__(self, text, pos):
87 self.text = text
85 self.text = text
88 self.pos = pos
86 self.pos = pos
89 def __str__(self):
87 def __str__(self):
90 return "unfinished expression in %s at char %d" % (
88 return "unfinished expression in %s at char %d" % (
91 repr(self.text), self.pos)
89 repr(self.text), self.pos)
92
90
93 def matchorfail(text, pos):
91 def matchorfail(text, pos):
94 match = tokenprog.match(text, pos)
92 match = tokenprog.match(text, pos)
95 if match is None:
93 if match is None:
96 raise ItplError(text, pos)
94 raise ItplError(text, pos)
97 return match, match.end()
95 return match, match.end()
98
96
99 class Itpl:
97 class Itpl:
100 """Class representing a string with interpolation abilities.
98 """Class representing a string with interpolation abilities.
101
99
102 Upon creation, an instance works out what parts of the format
100 Upon creation, an instance works out what parts of the format
103 string are literal and what parts need to be evaluated. The
101 string are literal and what parts need to be evaluated. The
104 evaluation and substitution happens in the namespace of the
102 evaluation and substitution happens in the namespace of the
105 caller when str(instance) is called."""
103 caller when str(instance) is called."""
106
104
107 def __init__(self, format,codec='utf_8',encoding_errors='backslashreplace'):
105 def __init__(self, format,codec='utf_8',encoding_errors='backslashreplace'):
108 """The single mandatory argument to this constructor is a format
106 """The single mandatory argument to this constructor is a format
109 string.
107 string.
110
108
111 The format string is parsed according to the following rules:
109 The format string is parsed according to the following rules:
112
110
113 1. A dollar sign and a name, possibly followed by any of:
111 1. A dollar sign and a name, possibly followed by any of:
114 - an open-paren, and anything up to the matching paren
112 - an open-paren, and anything up to the matching paren
115 - an open-bracket, and anything up to the matching bracket
113 - an open-bracket, and anything up to the matching bracket
116 - a period and a name
114 - a period and a name
117 any number of times, is evaluated as a Python expression.
115 any number of times, is evaluated as a Python expression.
118
116
119 2. A dollar sign immediately followed by an open-brace, and
117 2. A dollar sign immediately followed by an open-brace, and
120 anything up to the matching close-brace, is evaluated as
118 anything up to the matching close-brace, is evaluated as
121 a Python expression.
119 a Python expression.
122
120
123 3. Outside of the expressions described in the above two rules,
121 3. Outside of the expressions described in the above two rules,
124 two dollar signs in a row give you one literal dollar sign.
122 two dollar signs in a row give you one literal dollar sign.
125
123
126 Optional arguments:
124 Optional arguments:
127
125
128 - codec('utf_8'): a string containing the name of a valid Python
126 - codec('utf_8'): a string containing the name of a valid Python
129 codec.
127 codec.
130
128
131 - encoding_errors('backslashreplace'): a string with a valid error handling
129 - encoding_errors('backslashreplace'): a string with a valid error handling
132 policy. See the codecs module documentation for details.
130 policy. See the codecs module documentation for details.
133
131
134 These are used to encode the format string if a call to str() fails on
132 These are used to encode the format string if a call to str() fails on
135 the expanded result."""
133 the expanded result."""
136
134
137 if not isinstance(format,basestring):
135 if not isinstance(format,basestring):
138 raise TypeError, "needs string initializer"
136 raise TypeError, "needs string initializer"
139 self.format = format
137 self.format = format
140 self.codec = codec
138 self.codec = codec
141 self.encoding_errors = encoding_errors
139 self.encoding_errors = encoding_errors
142
140
143 namechars = "abcdefghijklmnopqrstuvwxyz" \
141 namechars = "abcdefghijklmnopqrstuvwxyz" \
144 "ABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789_";
142 "ABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789_";
145 chunks = []
143 chunks = []
146 pos = 0
144 pos = 0
147
145
148 while 1:
146 while 1:
149 dollar = string.find(format, "$", pos)
147 dollar = string.find(format, "$", pos)
150 if dollar < 0: break
148 if dollar < 0: break
151 nextchar = format[dollar+1]
149 nextchar = format[dollar+1]
152
150
153 if nextchar == "{":
151 if nextchar == "{":
154 chunks.append((0, format[pos:dollar]))
152 chunks.append((0, format[pos:dollar]))
155 pos, level = dollar+2, 1
153 pos, level = dollar+2, 1
156 while level:
154 while level:
157 match, pos = matchorfail(format, pos)
155 match, pos = matchorfail(format, pos)
158 tstart, tend = match.regs[3]
156 tstart, tend = match.regs[3]
159 token = format[tstart:tend]
157 token = format[tstart:tend]
160 if token == "{": level = level+1
158 if token == "{": level = level+1
161 elif token == "}": level = level-1
159 elif token == "}": level = level-1
162 chunks.append((1, format[dollar+2:pos-1]))
160 chunks.append((1, format[dollar+2:pos-1]))
163
161
164 elif nextchar in namechars:
162 elif nextchar in namechars:
165 chunks.append((0, format[pos:dollar]))
163 chunks.append((0, format[pos:dollar]))
166 match, pos = matchorfail(format, dollar+1)
164 match, pos = matchorfail(format, dollar+1)
167 while pos < len(format):
165 while pos < len(format):
168 if format[pos] == "." and \
166 if format[pos] == "." and \
169 pos+1 < len(format) and format[pos+1] in namechars:
167 pos+1 < len(format) and format[pos+1] in namechars:
170 match, pos = matchorfail(format, pos+1)
168 match, pos = matchorfail(format, pos+1)
171 elif format[pos] in "([":
169 elif format[pos] in "([":
172 pos, level = pos+1, 1
170 pos, level = pos+1, 1
173 while level:
171 while level:
174 match, pos = matchorfail(format, pos)
172 match, pos = matchorfail(format, pos)
175 tstart, tend = match.regs[3]
173 tstart, tend = match.regs[3]
176 token = format[tstart:tend]
174 token = format[tstart:tend]
177 if token[0] in "([": level = level+1
175 if token[0] in "([": level = level+1
178 elif token[0] in ")]": level = level-1
176 elif token[0] in ")]": level = level-1
179 else: break
177 else: break
180 chunks.append((1, format[dollar+1:pos]))
178 chunks.append((1, format[dollar+1:pos]))
181
179
182 else:
180 else:
183 chunks.append((0, format[pos:dollar+1]))
181 chunks.append((0, format[pos:dollar+1]))
184 pos = dollar + 1 + (nextchar == "$")
182 pos = dollar + 1 + (nextchar == "$")
185
183
186 if pos < len(format): chunks.append((0, format[pos:]))
184 if pos < len(format): chunks.append((0, format[pos:]))
187 self.chunks = chunks
185 self.chunks = chunks
188
186
189 def __repr__(self):
187 def __repr__(self):
190 return "<Itpl %s >" % repr(self.format)
188 return "<Itpl %s >" % repr(self.format)
191
189
192 def _str(self,glob,loc):
190 def _str(self,glob,loc):
193 """Evaluate to a string in the given globals/locals.
191 """Evaluate to a string in the given globals/locals.
194
192
195 The final output is built by calling str(), but if this fails, the
193 The final output is built by calling str(), but if this fails, the
196 result is encoded with the instance's codec and error handling policy,
194 result is encoded with the instance's codec and error handling policy,
197 via a call to out.encode(self.codec,self.encoding_errors)"""
195 via a call to out.encode(self.codec,self.encoding_errors)"""
198 result = []
196 result = []
199 app = result.append
197 app = result.append
200 for live, chunk in self.chunks:
198 for live, chunk in self.chunks:
201 if live: app(str(eval(chunk,glob,loc)))
199 if live: app(str(eval(chunk,glob,loc)))
202 else: app(chunk)
200 else: app(chunk)
203 out = ''.join(result)
201 out = ''.join(result)
204 try:
202 try:
205 return str(out)
203 return str(out)
206 except UnicodeError:
204 except UnicodeError:
207 return out.encode(self.codec,self.encoding_errors)
205 return out.encode(self.codec,self.encoding_errors)
208
206
209 def __str__(self):
207 def __str__(self):
210 """Evaluate and substitute the appropriate parts of the string."""
208 """Evaluate and substitute the appropriate parts of the string."""
211
209
212 # We need to skip enough frames to get to the actual caller outside of
210 # We need to skip enough frames to get to the actual caller outside of
213 # Itpl.
211 # Itpl.
214 frame = sys._getframe(1)
212 frame = sys._getframe(1)
215 while frame.f_globals["__name__"] == __name__: frame = frame.f_back
213 while frame.f_globals["__name__"] == __name__: frame = frame.f_back
216 loc, glob = frame.f_locals, frame.f_globals
214 loc, glob = frame.f_locals, frame.f_globals
217
215
218 return self._str(glob,loc)
216 return self._str(glob,loc)
219
217
220 class ItplNS(Itpl):
218 class ItplNS(Itpl):
221 """Class representing a string with interpolation abilities.
219 """Class representing a string with interpolation abilities.
222
220
223 This inherits from Itpl, but at creation time a namespace is provided
221 This inherits from Itpl, but at creation time a namespace is provided
224 where the evaluation will occur. The interpolation becomes a bit more
222 where the evaluation will occur. The interpolation becomes a bit more
225 efficient, as no traceback needs to be extracte. It also allows the
223 efficient, as no traceback needs to be extracte. It also allows the
226 caller to supply a different namespace for the interpolation to occur than
224 caller to supply a different namespace for the interpolation to occur than
227 its own."""
225 its own."""
228
226
229 def __init__(self, format,globals,locals=None,
227 def __init__(self, format,globals,locals=None,
230 codec='utf_8',encoding_errors='backslashreplace'):
228 codec='utf_8',encoding_errors='backslashreplace'):
231 """ItplNS(format,globals[,locals]) -> interpolating string instance.
229 """ItplNS(format,globals[,locals]) -> interpolating string instance.
232
230
233 This constructor, besides a format string, takes a globals dictionary
231 This constructor, besides a format string, takes a globals dictionary
234 and optionally a locals (which defaults to globals if not provided).
232 and optionally a locals (which defaults to globals if not provided).
235
233
236 For further details, see the Itpl constructor."""
234 For further details, see the Itpl constructor."""
237
235
238 if locals is None:
236 if locals is None:
239 locals = globals
237 locals = globals
240 self.globals = globals
238 self.globals = globals
241 self.locals = locals
239 self.locals = locals
242 Itpl.__init__(self,format,codec,encoding_errors)
240 Itpl.__init__(self,format,codec,encoding_errors)
243
241
244 def __str__(self):
242 def __str__(self):
245 """Evaluate and substitute the appropriate parts of the string."""
243 """Evaluate and substitute the appropriate parts of the string."""
246 return self._str(self.globals,self.locals)
244 return self._str(self.globals,self.locals)
247
245
248 def __repr__(self):
246 def __repr__(self):
249 return "<ItplNS %s >" % repr(self.format)
247 return "<ItplNS %s >" % repr(self.format)
250
248
251 # utilities for fast printing
249 # utilities for fast printing
252 def itpl(text): return str(Itpl(text))
250 def itpl(text): return str(Itpl(text))
253 def printpl(text): print itpl(text)
251 def printpl(text): print itpl(text)
254 # versions with namespace
252 # versions with namespace
255 def itplns(text,globals,locals=None): return str(ItplNS(text,globals,locals))
253 def itplns(text,globals,locals=None): return str(ItplNS(text,globals,locals))
256 def printplns(text,globals,locals=None): print itplns(text,globals,locals)
254 def printplns(text,globals,locals=None): print itplns(text,globals,locals)
257
255
258 class ItplFile:
256 class ItplFile:
259 """A file object that filters each write() through an interpolator."""
257 """A file object that filters each write() through an interpolator."""
260 def __init__(self, file): self.file = file
258 def __init__(self, file): self.file = file
261 def __repr__(self): return "<interpolated " + repr(self.file) + ">"
259 def __repr__(self): return "<interpolated " + repr(self.file) + ">"
262 def __getattr__(self, attr): return getattr(self.file, attr)
260 def __getattr__(self, attr): return getattr(self.file, attr)
263 def write(self, text): self.file.write(str(Itpl(text)))
261 def write(self, text): self.file.write(str(Itpl(text)))
264
262
265 def filter(file=sys.stdout):
263 def filter(file=sys.stdout):
266 """Return an ItplFile that filters writes to the given file object.
264 """Return an ItplFile that filters writes to the given file object.
267
265
268 'file = filter(file)' replaces 'file' with a filtered object that
266 'file = filter(file)' replaces 'file' with a filtered object that
269 has a write() method. When called with no argument, this creates
267 has a write() method. When called with no argument, this creates
270 a filter to sys.stdout."""
268 a filter to sys.stdout."""
271 return ItplFile(file)
269 return ItplFile(file)
272
270
273 def unfilter(ifile=None):
271 def unfilter(ifile=None):
274 """Return the original file that corresponds to the given ItplFile.
272 """Return the original file that corresponds to the given ItplFile.
275
273
276 'file = unfilter(file)' undoes the effect of 'file = filter(file)'.
274 'file = unfilter(file)' undoes the effect of 'file = filter(file)'.
277 'sys.stdout = unfilter()' undoes the effect of 'sys.stdout = filter()'."""
275 'sys.stdout = unfilter()' undoes the effect of 'sys.stdout = filter()'."""
278 return ifile and ifile.file or sys.stdout.file
276 return ifile and ifile.file or sys.stdout.file
1 NO CONTENT: modified file
NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
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