##// END OF EJS Templates
Major cleanups and changes, see changelog/changeset for full details.
fperez -
Show More
@@ -2,12 +2,12 b''
2 """
2 """
3 Logger class for IPython's logging facilities.
3 Logger class for IPython's logging facilities.
4
4
5 $Id: Logger.py 958 2005-12-27 23:17:51Z fperez $
5 $Id: Logger.py 966 2005-12-29 08:34:07Z fperez $
6 """
6 """
7
7
8 #*****************************************************************************
8 #*****************************************************************************
9 # Copyright (C) 2001 Janko Hauser <jhauser@zscout.de> and
9 # Copyright (C) 2001 Janko Hauser <jhauser@zscout.de> and
10 # Copyright (C) 2001-2004 Fernando Perez <fperez@colorado.edu>
10 # Copyright (C) 2001-2005 Fernando Perez <fperez@colorado.edu>
11 #
11 #
12 # 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
13 # the file COPYING, distributed as part of this software.
13 # the file COPYING, distributed as part of this software.
@@ -24,61 +24,96 b' __license__ = Release.license'
24 # Python standard modules
24 # Python standard modules
25 import glob
25 import glob
26 import os
26 import os
27 import sys
27 import time
28
29 # Homebrewed
30 from IPython.genutils import *
31
28
32 #****************************************************************************
29 #****************************************************************************
33 # FIXME: The logger class shouldn't be a mixin, it throws too many things into
30 # FIXME: This class isn't a mixin anymore, but it still needs attributes from
34 # the InteractiveShell namespace. Rather make it a standalone tool, and create
31 # ipython and does input cache management. Finish cleanup later...
35 # a Logger instance in InteractiveShell that uses it. Doing this will require
32
36 # tracking down a *lot* of nasty uses of the Logger attributes in
33 class Logger(object):
37 # InteractiveShell, but will clean up things quite a bit.
34 """A Logfile class with different policies for file creation"""
38
35
39 class Logger:
36 def __init__(self,shell,logfname='Logger.log',loghead='',logmode='over'):
40 """A Logfile Mixin class with different policies for file creation"""
37
41
42 # FIXME: once this isn't a mixin, log_ns should just be 'namespace', since the
43 # names won't collide anymore.
44 def __init__(self,log_ns):
45 self._i00,self._i,self._ii,self._iii = '','','',''
38 self._i00,self._i,self._ii,self._iii = '','','',''
46 self.do_full_cache = 0 # FIXME. There's also a do_full.. in OutputCache
47 self.log_ns = log_ns
48 # defaults
49 self.LOGMODE = 'backup'
50 self.defname = 'logfile'
51
52 def create_log(self,header='',fname='',defname='.Logger.log'):
53 """Generate a new log-file with a default header"""
54 if fname:
55 self.LOG = fname
56
39
57 if self.LOG:
40 # this is the full ipython instance, we need some attributes from it
58 self.logfname = self.LOG
41 # which won't exist until later. What a mess, clean up later...
59 else:
42 self.shell = shell
60 self.logfname = defname
43
44 self.logfname = logfname
45 self.loghead = loghead
46 self.logmode = logmode
47 self.logfile = None
48
49 # whether to also log output
50 self.log_output = False
51
52 # whether to put timestamps before each log entry
53 self.timestamp = False
54
55 # activity control flags
56 self.log_active = False
57
58 # logmode is a validated property
59 def _set_mode(self,mode):
60 if mode not in ['append','backup','global','over','rotate']:
61 raise ValueError,'invalid log mode %s given' % mode
62 self._logmode = mode
63
64 def _get_mode(self):
65 return self._logmode
66
67 logmode = property(_get_mode,_set_mode)
68
69 def logstart(self,logfname=None,loghead=None,logmode=None,
70 log_output=False,timestamp=False):
71 """Generate a new log-file with a default header.
72
73 Raises RuntimeError if the log has already been started"""
74
75 if self.logfile is not None:
76 raise RuntimeError('Log file is already active: %s' %
77 self.logfname)
61
78
62 if self.LOGMODE == 'over':
79 self.log_active = True
63 if os.path.isfile(self.logfname):
80
64 os.remove(self.logfname)
81 # The three parameters can override constructor defaults
65 self.logfile = open(self.logfname,'w')
82 if logfname: self.logfname = logfname
66 if self.LOGMODE == 'backup':
83 if loghead: self.loghead = loghead
67 if os.path.isfile(self.logfname):
84 if logmode: self.logmode = logmode
85 self.timestamp = timestamp
86 self.log_output = log_output
87
88 # init depending on the log mode requested
89 isfile = os.path.isfile
90 logmode = self.logmode
91
92 if logmode == 'append':
93 self.logfile = open(self.logfname,'a')
94
95 elif logmode == 'backup':
96 if isfile(self.logfname):
68 backup_logname = self.logfname+'~'
97 backup_logname = self.logfname+'~'
69 # Manually remove any old backup, since os.rename may fail
98 # Manually remove any old backup, since os.rename may fail
70 # under Windows.
99 # under Windows.
71 if os.path.isfile(backup_logname):
100 if isfile(backup_logname):
72 os.remove(backup_logname)
101 os.remove(backup_logname)
73 os.rename(self.logfname,backup_logname)
102 os.rename(self.logfname,backup_logname)
74 self.logfile = open(self.logfname,'w')
103 self.logfile = open(self.logfname,'w')
75 elif self.LOGMODE == 'global':
104
76 self.logfname = os.path.join(self.home_dir, self.defname)
105 elif logmode == 'global':
106 self.logfname = os.path.join(self.shell.home_dir,self.logfname)
77 self.logfile = open(self.logfname, 'a')
107 self.logfile = open(self.logfname, 'a')
78 self.LOG = self.logfname
108
79 elif self.LOGMODE == 'rotate':
109 elif logmode == 'over':
80 if os.path.isfile(self.logfname):
110 if isfile(self.logfname):
81 if os.path.isfile(self.logfname+'.001~'):
111 os.remove(self.logfname)
112 self.logfile = open(self.logfname,'w')
113
114 elif logmode == 'rotate':
115 if isfile(self.logfname):
116 if isfile(self.logfname+'.001~'):
82 old = glob.glob(self.logfname+'.*~')
117 old = glob.glob(self.logfname+'.*~')
83 old.sort()
118 old.sort()
84 old.reverse()
119 old.reverse()
@@ -88,71 +123,56 b' class Logger:'
88 os.rename(f, root+'.'+`num`.zfill(3)+'~')
123 os.rename(f, root+'.'+`num`.zfill(3)+'~')
89 os.rename(self.logfname, self.logfname+'.001~')
124 os.rename(self.logfname, self.logfname+'.001~')
90 self.logfile = open(self.logfname,'w')
125 self.logfile = open(self.logfname,'w')
91 elif self.LOGMODE == 'append':
92 self.logfile = open(self.logfname,'a')
93
126
94 if self.LOGMODE != 'append':
127 if logmode != 'append':
95 self.logfile.write(header)
128 self.logfile.write(self.loghead)
96 self.logfile.flush()
97
129
98 def logstart(self, header='',parameter_s = ''):
130 self.logfile.flush()
99 if not hasattr(self, 'LOG'):
100 logfname = self.LOG or parameter_s or './'+self.defname
101 self.create_log(header,logfname)
102 elif parameter_s and hasattr(self,'logfname') and \
103 parameter_s != self.logfname:
104 self.close_log()
105 self.create_log(header,parameter_s)
106
107 self._dolog = 1
108
131
109 def switch_log(self,val):
132 def switch_log(self,val):
110 """Switch logging on/off. val should be ONLY 0 or 1."""
133 """Switch logging on/off. val should be ONLY a boolean."""
111
134
112 if not val in [0,1]:
135 if val not in [False,True,0,1]:
113 raise ValueError, \
136 raise ValueError, \
114 'Call switch_log ONLY with 0 or 1 as argument, not with:',val
137 'Call switch_log ONLY with a boolean argument, not with:',val
115
138
116 label = {0:'OFF',1:'ON'}
139 label = {0:'OFF',1:'ON',False:'OFF',True:'ON'}
117
140
118 try:
141 if self.logfile is None:
119 _ = self.logfile
120 except AttributeError:
121 print """
142 print """
122 Logging hasn't been started yet (use %logstart for that).
143 Logging hasn't been started yet (use logstart for that).
123
144
124 %logon/%logoff are for temporarily starting and stopping logging for a logfile
145 %logon/%logoff are for temporarily starting and stopping logging for a logfile
125 which already exists. But you must first start the logging process with
146 which already exists. But you must first start the logging process with
126 %logstart (optionally giving a logfile name)."""
147 %logstart (optionally giving a logfile name)."""
127
148
128 else:
149 else:
129 if self._dolog == val:
150 if self.log_active == val:
130 print 'Logging is already',label[val]
151 print 'Logging is already',label[val]
131 else:
152 else:
132 print 'Switching logging',label[val]
153 print 'Switching logging',label[val]
133 self._dolog = 1 - self._dolog
154 self.log_active = not self.log_active
155 self.log_active_out = self.log_active
134
156
135 def logstate(self):
157 def logstate(self):
136 """Print a status message about the logger."""
158 """Print a status message about the logger."""
137 try:
159 if self.logfile is None:
138 logfile = self.logfname
139 except:
140 print 'Logging has not been activated.'
160 print 'Logging has not been activated.'
141 else:
161 else:
142 state = self._dolog and 'active' or 'temporarily suspended'
162 state = self.log_active and 'active' or 'temporarily suspended'
143 print """
163 print 'Filename :',self.logfname
144 File:\t%s
164 print 'Mode :',self.logmode
145 Mode:\t%s
165 print 'Output logging:',self.log_output
146 State:\t%s """ % (logfile,self.LOGMODE,state)
166 print 'Timestamping :',self.timestamp
167 print 'State :',state
147
168
148
149 def log(self, line,continuation=None):
169 def log(self, line,continuation=None):
150 """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*."""
151
171
152 # update the auto _i tables
172 # update the auto _i tables
153 #print '***logging line',line # dbg
173 #print '***logging line',line # dbg
154 #print '***cache_count', self.outputcache.prompt_count # dbg
174 #print '***cache_count', self.shell.outputcache.prompt_count # dbg
155 input_hist = self.log_ns['_ih']
175 input_hist = self.shell.user_ns['_ih']
156 if not continuation and line:
176 if not continuation and line:
157 self._iii = self._ii
177 self._iii = self._ii
158 self._ii = self._i
178 self._ii = self._i
@@ -164,24 +184,38 b' State:\\t%s """ % (logfile,self.LOGMODE,state)'
164
184
165 # hackish access to top-level namespace to create _i1,_i2... dynamically
185 # hackish access to top-level namespace to create _i1,_i2... dynamically
166 to_main = {'_i':self._i,'_ii':self._ii,'_iii':self._iii}
186 to_main = {'_i':self._i,'_ii':self._ii,'_iii':self._iii}
167 if self.do_full_cache:
187 if self.shell.outputcache.do_full_cache:
168 in_num = self.outputcache.prompt_count
188 in_num = self.shell.outputcache.prompt_count
169 # add blank lines if the input cache fell out of sync. This can happen
189 # add blank lines if the input cache fell out of sync. This can
170 # for embedded instances which get killed via C-D and then get resumed.
190 # happen for embedded instances which get killed via C-D and then
191 # get resumed.
171 while in_num >= len(input_hist):
192 while in_num >= len(input_hist):
172 input_hist.append('\n')
193 input_hist.append('\n')
173 new_i = '_i%s' % in_num
194 new_i = '_i%s' % in_num
174 if continuation:
195 if continuation:
175 self._i00 = '%s%s\n' % (self.log_ns[new_i],line)
196 self._i00 = '%s%s\n' % (self.shell.user_ns[new_i],line)
176 input_hist[in_num] = self._i00
197 input_hist[in_num] = self._i00
177 to_main[new_i] = self._i00
198 to_main[new_i] = self._i00
178 self.log_ns.update(to_main)
199 self.shell.user_ns.update(to_main)
179
200 self.log_write(line)
180 if self._dolog and line:
201
181 self.logfile.write(line+'\n')
202 def log_write(self,data,kind='input'):
203 """Write data to the log file, if active"""
204
205 if self.log_active and data:
206 write = self.logfile.write
207 if kind=='input':
208 if self.timestamp:
209 write(time.strftime('# %a, %d %b %Y %H:%M:%S\n',
210 time.localtime()))
211 write('%s\n' % data)
212 elif kind=='output' and self.log_output:
213 odata = '\n'.join(['#[Out]# %s' % s
214 for s in data.split('\n')])
215 write('%s\n' % odata)
182 self.logfile.flush()
216 self.logfile.flush()
183
217
184 def close_log(self):
218 def close_log(self):
185 if hasattr(self, 'logfile'):
219 self.logfile.close()
186 self.logfile.close()
220 self.logfile = None
187 self.logfname = ''
221 self.logfname = ''
@@ -1,7 +1,7 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 965 2005-12-28 23:23:09Z fperez $"""
4 $Id: Magic.py 966 2005-12-29 08:34:07Z fperez $"""
5
5
6 #*****************************************************************************
6 #*****************************************************************************
7 # Copyright (C) 2001 Janko Hauser <jhauser@zscout.de> and
7 # Copyright (C) 2001 Janko Hauser <jhauser@zscout.de> and
@@ -48,33 +48,8 b' from IPython.PyColorize import Parser'
48 from IPython.Struct import Struct
48 from IPython.Struct import Struct
49 from IPython.genutils import *
49 from IPython.genutils import *
50
50
51 # Globals to be set later by Magic constructor
52 MAGIC_PREFIX = ''
53 MAGIC_ESCAPE = ''
54
55 #***************************************************************************
51 #***************************************************************************
56 # Utility functions
52 # Utility functions
57 def magic2python(cmd):
58 """Convert a command string of magic syntax to valid Python code."""
59
60 if cmd.startswith('#'+MAGIC_ESCAPE) or \
61 cmd.startswith(MAGIC_ESCAPE):
62 if cmd[0]=='#':
63 cmd = cmd[1:]
64 # we need to return the proper line end later
65 if cmd[-1] == '\n':
66 endl = '\n'
67 else:
68 endl = ''
69 try:
70 func,args = cmd[1:].split(' ',1)
71 except:
72 func,args = cmd[1:].rstrip(),''
73 args = args.replace('"','\\"').replace("'","\\'").rstrip()
74 return '%s%s ("%s")%s' % (MAGIC_PREFIX,func,args,endl)
75 else:
76 return cmd
77
78 def on_off(tag):
53 def on_off(tag):
79 """Return an ON/OFF string for a 1/0 input. Simple utility function."""
54 """Return an ON/OFF string for a 1/0 input. Simple utility function."""
80 return ['OFF','ON'][tag]
55 return ['OFF','ON'][tag]
@@ -82,22 +57,15 b' def on_off(tag):'
82
57
83 #****************************************************************************
58 #****************************************************************************
84 # Utility classes
59 # Utility classes
85 class Macro:
60 class Macro(list):
86 """Simple class to store the value of macros as strings.
61 """Simple class to store the value of macros as strings.
87
62
88 This allows us to later exec them by checking when something is an
63 This allows us to later exec them by checking when something is an
89 instance of this class."""
64 instance of this class."""
90
91 def __init__(self,cmds):
92 """Build a macro from a list of commands."""
93
65
94 # Since the list may include multi-line entries, first make sure that
66 def __init__(self,data):
95 # they've been all broken up before passing it to magic2python
67 list.__init__(self,data)
96 cmdlist = map(magic2python,''.join(cmds).split('\n'))
68 self.value = ''.join(data)
97 self.value = '\n'.join(cmdlist)
98
99 def __str__(self):
100 return self.value
101
69
102 #***************************************************************************
70 #***************************************************************************
103 # Main class implementing Magic functionality
71 # Main class implementing Magic functionality
@@ -120,21 +88,18 b' class Magic:'
120 # some utility functions
88 # some utility functions
121
89
122 def __init__(self,shell):
90 def __init__(self,shell):
123 # XXX This is hackish, clean up later to avoid these messy globals
124 global MAGIC_PREFIX, MAGIC_ESCAPE
125
91
126 self.options_table = {}
92 self.options_table = {}
127 MAGIC_PREFIX = shell.name+'.magic_'
128 MAGIC_ESCAPE = shell.ESC_MAGIC
129 if profile is None:
93 if profile is None:
130 self.magic_prun = self.profile_missing_notice
94 self.magic_prun = self.profile_missing_notice
95 self.shell = shell
131
96
132 def profile_missing_notice(self, *args, **kwargs):
97 def profile_missing_notice(self, *args, **kwargs):
133 error("""\
98 error("""\
134 The profile module could not be found. If you are a Debian user,
99 The profile module could not be found. If you are a Debian user,
135 it has been removed from the standard Debian package because of its non-free
100 it has been removed from the standard Debian package because of its non-free
136 license. To use profiling, please install"python2.3-profiler" from non-free.""")
101 license. To use profiling, please install"python2.3-profiler" from non-free.""")
137
102
138 def default_option(self,fn,optstr):
103 def default_option(self,fn,optstr):
139 """Make an entry in the options_table for fn, with value optstr"""
104 """Make an entry in the options_table for fn, with value optstr"""
140
105
@@ -168,10 +133,6 b' license. To use profiling, please install"python2.3-profiler" from non-free.""")'
168 out.sort()
133 out.sort()
169 return out
134 return out
170
135
171 def set_shell(self,shell):
172 self.shell = shell
173 self.alias_table = shell.alias_table
174
175 def extract_input_slices(self,slices):
136 def extract_input_slices(self,slices):
176 """Return as a string a set of input history slices.
137 """Return as a string a set of input history slices.
177
138
@@ -496,17 +457,17 b' Currently the magic system has the following functions:\\n"""'
496
457
497 This feature is only available if numbered prompts are in use."""
458 This feature is only available if numbered prompts are in use."""
498
459
499 if not self.do_full_cache:
460 if not self.shell.outputcache.do_full_cache:
500 print 'This feature is only available if numbered prompts are in use.'
461 print 'This feature is only available if numbered prompts are in use.'
501 return
462 return
502 opts,args = self.parse_options(parameter_s,'n',mode='list')
463 opts,args = self.parse_options(parameter_s,'n',mode='list')
503
464
504 default_length = 40
465 default_length = 40
505 if len(args) == 0:
466 if len(args) == 0:
506 final = self.outputcache.prompt_count
467 final = self.shell.outputcache.prompt_count
507 init = max(1,final-default_length)
468 init = max(1,final-default_length)
508 elif len(args) == 1:
469 elif len(args) == 1:
509 final = self.outputcache.prompt_count
470 final = self.shell.outputcache.prompt_count
510 init = max(1,final-int(args[0]))
471 init = max(1,final-int(args[0]))
511 elif len(args) == 2:
472 elif len(args) == 2:
512 init,final = map(int,args)
473 init,final = map(int,args)
@@ -562,11 +523,8 b' Currently the magic system has the following functions:\\n"""'
562 if input != 'ipmagic("r")\n' and \
523 if input != 'ipmagic("r")\n' and \
563 (input.startswith(start) or input.startswith(start_magic)):
524 (input.startswith(start) or input.startswith(start_magic)):
564 #print 'match',`input` # dbg
525 #print 'match',`input` # dbg
565 if input.startswith(esc_magic):
566 input = magic2python(input)
567 #print 'modified',`input` # dbg
568 print 'Executing:',input,
526 print 'Executing:',input,
569 exec input in self.shell.user_ns
527 self.shell.runlines(input)
570 return
528 return
571 print 'No previous input matching `%s` found.' % start
529 print 'No previous input matching `%s` found.' % start
572
530
@@ -788,8 +746,8 b' Currently the magic system has the following functions:\\n"""'
788 typelist = parameter_s.split()
746 typelist = parameter_s.split()
789 for i in self.shell.user_ns.keys():
747 for i in self.shell.user_ns.keys():
790 if not (i.startswith('_') or i.startswith('_i')) \
748 if not (i.startswith('_') or i.startswith('_i')) \
791 and not (self.internal_ns.has_key(i) or
749 and not (self.shell.internal_ns.has_key(i) or
792 self.user_config_ns.has_key(i)):
750 self.shell.user_config_ns.has_key(i)):
793 if typelist:
751 if typelist:
794 if type(user_ns[i]).__name__ in typelist:
752 if type(user_ns[i]).__name__ in typelist:
795 out.append(i)
753 out.append(i)
@@ -946,9 +904,9 b' Currently the magic system has the following functions:\\n"""'
946 def magic_logstart(self,parameter_s=''):
904 def magic_logstart(self,parameter_s=''):
947 """Start logging anywhere in a session.
905 """Start logging anywhere in a session.
948
906
949 %logstart [log_name [log_mode]]
907 %logstart [-o|-t] [log_name [log_mode]]
950
908
951 If no name is given, it defaults to a file named 'ipython.log' in your
909 If no name is given, it defaults to a file named 'ipython_log.py' in your
952 current directory, in 'rotate' mode (see below).
910 current directory, in 'rotate' mode (see below).
953
911
954 '%logstart name' saves to file 'name' in 'backup' mode. It saves your
912 '%logstart name' saves to file 'name' in 'backup' mode. It saves your
@@ -956,67 +914,86 b' Currently the magic system has the following functions:\\n"""'
956
914
957 %logstart takes a second optional parameter: logging mode. This can be one
915 %logstart takes a second optional parameter: logging mode. This can be one
958 of (note that the modes are given unquoted):\\
916 of (note that the modes are given unquoted):\\
959 over: overwrite existing log.\\
960 backup: rename (if exists) to name~ and start name.\\
961 append: well, that says it.\\
917 append: well, that says it.\\
918 backup: rename (if exists) to name~ and start name.\\
919 global: single logfile in your home dir, appended to.\\
920 over : overwrite existing log.\\
962 rotate: create rotating logs name.1~, name.2~, etc.
921 rotate: create rotating logs name.1~, name.2~, etc.
963 """
964
922
965 #FIXME. This function should all be moved to the Logger class.
923 Options:
924
925 -o: log also IPython's output. In this mode, all commands which
926 generate an Out[NN] prompt are recorded to the logfile, right after
927 their corresponding input line. The output lines are always
928 prepended with a #[Out]# marker, so that the log remains valid
929 Python code.
930
931 -t: put timestamps before each input line logged (these are put in
932 comments)."""
966
933
967 valid_modes = qw('over backup append rotate')
934 opts,par = self.parse_options(parameter_s,'ot')
968 if self.LOG:
935 log_output = 'o' in opts
969 print 'Logging is already in place. Logfile:',self.LOG
936 timestamp = 't' in opts
970 return
971
937
972 par = parameter_s.strip()
938 rc = self.shell.rc
973 if not par:
939 logger = self.shell.logger
974 logname = self.LOGDEF
940
975 logmode = 'rotate' # use rotate for the auto-generated logs
941 # if no args are given, the defaults set in the logger constructor by
976 else:
942 # ipytohn remain valid
943 if par:
977 try:
944 try:
978 logname,logmode = par.split()
945 logfname,logmode = par.split()
979 except:
946 except:
980 try:
947 logfname = par
981 logname = par
948 logmode = 'backup'
982 logmode = 'backup'
949 else:
983 except:
950 logfname = logger.logfname
984 warn('Usage: %log [log_name [log_mode]]')
951 logmode = logger.logmode
985 return
952 # put logfname into rc struct as if it had been called on the command
986 if not logmode in valid_modes:
953 # line, so it ends up saved in the log header Save it in case we need
987 warn('Logging NOT activated.\n'
954 # to restore it...
988 'Usage: %log [log_name [log_mode]]\n'
955 old_logfile = rc.opts.get('logfile','')
989 'Valid modes: '+str(valid_modes))
956 if logfname:
990 return
957 logfname = os.path.expanduser(logfname)
991
958 rc.opts.logfile = logfname
992 # If we made it this far, I think we're ok:
959 loghead = self.shell.loghead_tpl % (rc.opts,rc.args)
993 print 'Activating auto-logging.'
994 print 'Current session state plus future input saved to:',logname
995 print 'Logging mode: ',logmode
996 # put logname into rc struct as if it had been called on the command line,
997 # so it ends up saved in the log header
998 # Save it in case we need to restore it...
999 old_logfile = self.shell.rc.opts.get('logfile','')
1000 logname = os.path.expanduser(logname)
1001 self.shell.rc.opts.logfile = logname
1002 self.LOGMODE = logmode # FIXME: this should be set through a function.
1003 try:
960 try:
1004 header = str(self.LOGHEAD)
961 started = logger.logstart(logfname,loghead,logmode,
1005 self.create_log(header,logname)
962 log_output,timestamp)
1006 self.logstart(header,logname)
1007 except:
963 except:
1008 self.LOG = '' # we are NOT logging, something went wrong
964 rc.opts.logfile = old_logfile
1009 self.shell.rc.opts.logfile = old_logfile
965 warn("Couldn't start log: %s" % sys.exc_info()[1])
1010 warn("Couldn't start log: "+str(sys.exc_info()[1]))
966 else:
1011 else: # log input history up to this point
967 # log input history up to this point, optionally interleaving
1012 self.logfile.write(self.shell.user_ns['_ih'][1:])
968 # output if requested
1013 self.logfile.flush()
969
1014
970 if timestamp:
971 # disable timestamping for the previous history, since we've
972 # lost those already (no time machine here).
973 logger.timestamp = False
974 if log_output:
975 log_write = logger.log_write
976 input_hist = self.shell.input_hist
977 output_hist = self.shell.output_hist
978 for n in range(1,len(input_hist)-1):
979 log_write(input_hist[n].rstrip())
980 if n in output_hist:
981 log_write(repr(output_hist[n]),'output')
982 else:
983 logger.log_write(self.shell.input_hist[1:])
984 if timestamp:
985 # re-enable timestamping
986 logger.timestamp = True
987
988 print ('Activating auto-logging. '
989 'Current session state plus future input saved.')
990 logger.logstate()
991
1015 def magic_logoff(self,parameter_s=''):
992 def magic_logoff(self,parameter_s=''):
1016 """Temporarily stop logging.
993 """Temporarily stop logging.
1017
994
1018 You must have previously started logging."""
995 You must have previously started logging."""
1019 self.switch_log(0)
996 self.shell.logger.switch_log(0)
1020
997
1021 def magic_logon(self,parameter_s=''):
998 def magic_logon(self,parameter_s=''):
1022 """Restart logging.
999 """Restart logging.
@@ -1026,12 +1003,12 b' Currently the magic system has the following functions:\\n"""'
1026 must use the %logstart function, which allows you to specify an
1003 must use the %logstart function, which allows you to specify an
1027 optional log filename."""
1004 optional log filename."""
1028
1005
1029 self.switch_log(1)
1006 self.shell.logger.switch_log(1)
1030
1007
1031 def magic_logstate(self,parameter_s=''):
1008 def magic_logstate(self,parameter_s=''):
1032 """Print the status of the logging system."""
1009 """Print the status of the logging system."""
1033
1010
1034 self.logstate()
1011 self.shell.logger.logstate()
1035
1012
1036 def magic_pdb(self, parameter_s=''):
1013 def magic_pdb(self, parameter_s=''):
1037 """Control the calling of the pdb interactive debugger.
1014 """Control the calling of the pdb interactive debugger.
@@ -1047,24 +1024,18 b' Currently the magic system has the following functions:\\n"""'
1047
1024
1048 if par:
1025 if par:
1049 try:
1026 try:
1050 pdb = {'off':0,'0':0,'on':1,'1':1}[par]
1027 new_pdb = {'off':0,'0':0,'on':1,'1':1}[par]
1051 except KeyError:
1028 except KeyError:
1052 print 'Incorrect argument. Use on/1, off/0, or nothing for a toggle.'
1029 print ('Incorrect argument. Use on/1, off/0, '
1030 'or nothing for a toggle.')
1053 return
1031 return
1054 else:
1055 self.shell.InteractiveTB.call_pdb = pdb
1056 else:
1032 else:
1033 # toggle
1057 new_pdb = not self.shell.InteractiveTB.call_pdb
1034 new_pdb = not self.shell.InteractiveTB.call_pdb
1058 self.shell.InteractiveTB.call_pdb = new_pdb
1059 if self.shell.isthreaded:
1060 try:
1061 self.sys_excepthook.call_pdb = new_pdb
1062 except:
1063 warn('Failed to activate pdb for threaded exception handler')
1064
1065 print 'Automatic pdb calling has been turned',on_off(new_pdb)
1066
1067
1035
1036 # set on the shell
1037 self.shell.call_pdb = new_pdb
1038 print 'Automatic pdb calling has been turned',on_off(new_pdb)
1068
1039
1069 def magic_prun(self, parameter_s ='',user_mode=1,
1040 def magic_prun(self, parameter_s ='',user_mode=1,
1070 opts=None,arg_lst=None,prog_ns=None):
1041 opts=None,arg_lst=None,prog_ns=None):
@@ -1606,12 +1577,12 b' Currently the magic system has the following functions:\\n"""'
1606 args = parameter_s.split()
1577 args = parameter_s.split()
1607 name,ranges = args[0], args[1:]
1578 name,ranges = args[0], args[1:]
1608 #print 'rng',ranges # dbg
1579 #print 'rng',ranges # dbg
1609 cmds = self.extract_input_slices(ranges)
1580 lines = self.extract_input_slices(ranges)
1610 macro = Macro(cmds)
1581 macro = Macro(lines)
1611 self.shell.user_ns.update({name:macro})
1582 self.shell.user_ns.update({name:macro})
1612 print 'Macro `%s` created. To execute, type its name (without quotes).' % name
1583 print 'Macro `%s` created. To execute, type its name (without quotes).' % name
1613 print 'Macro contents:'
1584 print 'Macro contents:'
1614 print str(macro).rstrip(),
1585 print macro
1615
1586
1616 def magic_save(self,parameter_s = ''):
1587 def magic_save(self,parameter_s = ''):
1617 """Save a set of lines to a given filename.
1588 """Save a set of lines to a given filename.
@@ -1906,17 +1877,18 b' Currently the magic system has the following functions:\\n"""'
1906 warn('Error changing %s exception modes.\n%s' %
1877 warn('Error changing %s exception modes.\n%s' %
1907 (name,sys.exc_info()[1]))
1878 (name,sys.exc_info()[1]))
1908
1879
1880 shell = self.shell
1909 new_mode = parameter_s.strip().capitalize()
1881 new_mode = parameter_s.strip().capitalize()
1910 try:
1882 try:
1911 self.InteractiveTB.set_mode(mode=new_mode)
1883 shell.InteractiveTB.set_mode(mode=new_mode)
1912 print 'Exception reporting mode:',self.InteractiveTB.mode
1884 print 'Exception reporting mode:',shell.InteractiveTB.mode
1913 except:
1885 except:
1914 xmode_switch_err('user')
1886 xmode_switch_err('user')
1915
1887
1916 # threaded shells use a special handler in sys.excepthook
1888 # threaded shells use a special handler in sys.excepthook
1917 if self.isthreaded:
1889 if shell.isthreaded:
1918 try:
1890 try:
1919 self.shell.sys_excepthook.set_mode(mode=new_mode)
1891 shell.sys_excepthook.set_mode(mode=new_mode)
1920 except:
1892 except:
1921 xmode_switch_err('threaded')
1893 xmode_switch_err('threaded')
1922
1894
@@ -1961,37 +1933,39 b' http://starship.python.net/crew/theller/ctypes'
1961 Defaulting color scheme to 'NoColor'"""
1933 Defaulting color scheme to 'NoColor'"""
1962 new_scheme = 'NoColor'
1934 new_scheme = 'NoColor'
1963 warn(msg)
1935 warn(msg)
1936 # local shortcut
1937 shell = self.shell
1964
1938
1965 # Set prompt colors
1939 # Set prompt colors
1966 try:
1940 try:
1967 self.shell.outputcache.set_colors(new_scheme)
1941 shell.outputcache.set_colors(new_scheme)
1968 except:
1942 except:
1969 color_switch_err('prompt')
1943 color_switch_err('prompt')
1970 else:
1944 else:
1971 self.shell.rc.colors = \
1945 shell.rc.colors = \
1972 self.shell.outputcache.color_table.active_scheme_name
1946 shell.outputcache.color_table.active_scheme_name
1973 # Set exception colors
1947 # Set exception colors
1974 try:
1948 try:
1975 self.shell.InteractiveTB.set_colors(scheme = new_scheme)
1949 shell.InteractiveTB.set_colors(scheme = new_scheme)
1976 self.shell.SyntaxTB.set_colors(scheme = new_scheme)
1950 shell.SyntaxTB.set_colors(scheme = new_scheme)
1977 except:
1951 except:
1978 color_switch_err('exception')
1952 color_switch_err('exception')
1979
1953
1980 # threaded shells use a verbose traceback in sys.excepthook
1954 # threaded shells use a verbose traceback in sys.excepthook
1981 if self.isthreaded:
1955 if shell.isthreaded:
1982 try:
1956 try:
1983 self.shell.sys_excepthook.set_colors(scheme=new_scheme)
1957 shell.sys_excepthook.set_colors(scheme=new_scheme)
1984 except:
1958 except:
1985 color_switch_err('system exception handler')
1959 color_switch_err('system exception handler')
1986
1960
1987 # Set info (for 'object?') colors
1961 # Set info (for 'object?') colors
1988 if self.shell.rc.color_info:
1962 if shell.rc.color_info:
1989 try:
1963 try:
1990 self.shell.inspector.set_active_scheme(new_scheme)
1964 shell.inspector.set_active_scheme(new_scheme)
1991 except:
1965 except:
1992 color_switch_err('object inspector')
1966 color_switch_err('object inspector')
1993 else:
1967 else:
1994 self.shell.inspector.set_active_scheme('NoColor')
1968 shell.inspector.set_active_scheme('NoColor')
1995
1969
1996 def magic_color_info(self,parameter_s = ''):
1970 def magic_color_info(self,parameter_s = ''):
1997 """Toggle color_info.
1971 """Toggle color_info.
@@ -2284,7 +2258,7 b' Defaulting color scheme to \'NoColor\'"""'
2284 else:
2258 else:
2285 self.shell.user_ns['_dh'].append(os.getcwd())
2259 self.shell.user_ns['_dh'].append(os.getcwd())
2286 else:
2260 else:
2287 os.chdir(self.home_dir)
2261 os.chdir(self.shell.home_dir)
2288 self.shell.user_ns['_dh'].append(os.getcwd())
2262 self.shell.user_ns['_dh'].append(os.getcwd())
2289 if not 'q' in opts:
2263 if not 'q' in opts:
2290 print self.shell.user_ns['_dh'][-1]
2264 print self.shell.user_ns['_dh'][-1]
@@ -2323,7 +2297,6 b' Defaulting color scheme to \'NoColor\'"""'
2323 def magic_env(self, parameter_s=''):
2297 def magic_env(self, parameter_s=''):
2324 """List environment variables."""
2298 """List environment variables."""
2325
2299
2326 # environ is an instance of UserDict
2327 return os.environ.data
2300 return os.environ.data
2328
2301
2329 def magic_pushd(self, parameter_s=''):
2302 def magic_pushd(self, parameter_s=''):
@@ -2335,11 +2308,12 b' Defaulting color scheme to \'NoColor\'"""'
2335 %pushd with no arguments does a %pushd to your home directory.
2308 %pushd with no arguments does a %pushd to your home directory.
2336 """
2309 """
2337 if parameter_s == '': parameter_s = '~'
2310 if parameter_s == '': parameter_s = '~'
2338 if len(self.dir_stack)>0 and os.path.expanduser(parameter_s) != \
2311 dir_s = self.shell.dir_stack
2339 os.path.expanduser(self.dir_stack[0]):
2312 if len(dir_s)>0 and os.path.expanduser(parameter_s) != \
2313 os.path.expanduser(self.shell.dir_stack[0]):
2340 try:
2314 try:
2341 self.magic_cd(parameter_s)
2315 self.magic_cd(parameter_s)
2342 self.dir_stack.insert(0,os.getcwd().replace(self.home_dir,'~'))
2316 dir_s.insert(0,os.getcwd().replace(self.home_dir,'~'))
2343 self.magic_dirs()
2317 self.magic_dirs()
2344 except:
2318 except:
2345 print 'Invalid directory'
2319 print 'Invalid directory'
@@ -2349,18 +2323,18 b' Defaulting color scheme to \'NoColor\'"""'
2349 def magic_popd(self, parameter_s=''):
2323 def magic_popd(self, parameter_s=''):
2350 """Change to directory popped off the top of the stack.
2324 """Change to directory popped off the top of the stack.
2351 """
2325 """
2352 if len (self.dir_stack) > 1:
2326 if len (self.shell.dir_stack) > 1:
2353 self.dir_stack.pop(0)
2327 self.shell.dir_stack.pop(0)
2354 self.magic_cd(self.dir_stack[0])
2328 self.magic_cd(self.shell.dir_stack[0])
2355 print self.dir_stack[0]
2329 print self.shell.dir_stack[0]
2356 else:
2330 else:
2357 print "You can't remove the starting directory from the stack:",\
2331 print "You can't remove the starting directory from the stack:",\
2358 self.dir_stack
2332 self.shell.dir_stack
2359
2333
2360 def magic_dirs(self, parameter_s=''):
2334 def magic_dirs(self, parameter_s=''):
2361 """Return the current directory stack."""
2335 """Return the current directory stack."""
2362
2336
2363 return self.dir_stack[:]
2337 return self.shell.dir_stack[:]
2364
2338
2365 def magic_sc(self, parameter_s=''):
2339 def magic_sc(self, parameter_s=''):
2366 """Shell capture - execute a shell command and capture its output.
2340 """Shell capture - execute a shell command and capture its output.
@@ -2605,7 +2579,7 b' Defaulting color scheme to \'NoColor\'"""'
2605 bkms[args[0]] = os.getcwd()
2579 bkms[args[0]] = os.getcwd()
2606 elif len(args)==2:
2580 elif len(args)==2:
2607 bkms[args[0]] = args[1]
2581 bkms[args[0]] = args[1]
2608 self.persist['bookmarks'] = bkms
2582 self.shell.persist['bookmarks'] = bkms
2609
2583
2610 def magic_pycat(self, parameter_s=''):
2584 def magic_pycat(self, parameter_s=''):
2611 """Show a syntax-highlighted file through a pager.
2585 """Show a syntax-highlighted file through a pager.
@@ -2,7 +2,7 b''
2 """
2 """
3 Classes for handling input/output prompts.
3 Classes for handling input/output prompts.
4
4
5 $Id: Prompts.py 960 2005-12-28 06:51:01Z fperez $"""
5 $Id: Prompts.py 966 2005-12-29 08:34:07Z fperez $"""
6
6
7 #*****************************************************************************
7 #*****************************************************************************
8 # Copyright (C) 2001-2004 Fernando Perez <fperez@colorado.edu>
8 # Copyright (C) 2001-2004 Fernando Perez <fperez@colorado.edu>
@@ -392,10 +392,10 b' class CachedOutput:'
392 Initialize with initial and final values for cache counter (this defines
392 Initialize with initial and final values for cache counter (this defines
393 the maximum size of the cache."""
393 the maximum size of the cache."""
394
394
395 def __init__(self,cache_size,Pprint,colors='NoColor',input_sep='\n',
395 def __init__(self,shell,cache_size,Pprint,
396 output_sep='\n',output_sep2='',user_ns={},
396 colors='NoColor',input_sep='\n',
397 ps1 = None, ps2 = None,ps_out = None,
397 output_sep='\n',output_sep2='',
398 input_hist = None,pad_left=True):
398 ps1 = None, ps2 = None,ps_out = None,pad_left=True):
399
399
400 cache_size_min = 20
400 cache_size_min = 20
401 if cache_size <= 0:
401 if cache_size <= 0:
@@ -413,9 +413,12 b' class CachedOutput:'
413 self.input_sep = input_sep
413 self.input_sep = input_sep
414
414
415 # we need a reference to the user-level namespace
415 # we need a reference to the user-level namespace
416 self.user_ns = user_ns
416 self.shell = shell
417 self.user_ns = shell.user_ns
417 # and to the user's input
418 # and to the user's input
418 self.input_hist = input_hist
419 self.input_hist = shell.input_hist
420 # and to the user's logger, for logging output
421 self.logger = shell.logger
419
422
420 # Set input prompt strings and colors
423 # Set input prompt strings and colors
421 if cache_size == 0:
424 if cache_size == 0:
@@ -509,11 +512,13 b' class CachedOutput:'
509 print 'Executing Macro...'
512 print 'Executing Macro...'
510 # in case the macro takes a long time to execute
513 # in case the macro takes a long time to execute
511 Term.cout.flush()
514 Term.cout.flush()
512 exec arg.value in self.user_ns
515 self.shell.runlines(arg.value)
513 return None
516 return None
514
517
515 # and now call a possibly user-defined print mechanism
518 # and now call a possibly user-defined print mechanism
516 self.display(arg)
519 self.display(arg)
520 if self.logger.log_output:
521 self.logger.log_write(repr(arg),'output')
517 cout_write(self.output_sep2)
522 cout_write(self.output_sep2)
518 Term.cout.flush()
523 Term.cout.flush()
519
524
@@ -6,7 +6,7 b' Requires Python 2.1 or newer.'
6
6
7 This file contains all the classes and helper functions specific to IPython.
7 This file contains all the classes and helper functions specific to IPython.
8
8
9 $Id: iplib.py 965 2005-12-28 23:23:09Z fperez $
9 $Id: iplib.py 966 2005-12-29 08:34:07Z fperez $
10 """
10 """
11
11
12 #*****************************************************************************
12 #*****************************************************************************
@@ -67,7 +67,8 b' from IPython.ColorANSI import ColorScheme,ColorSchemeTable # too long names'
67 from IPython.FakeModule import FakeModule
67 from IPython.FakeModule import FakeModule
68 from IPython.Itpl import Itpl,itpl,printpl,ItplNS,itplns
68 from IPython.Itpl import Itpl,itpl,printpl,ItplNS,itplns
69 from IPython.Logger import Logger
69 from IPython.Logger import Logger
70 from IPython.Magic import Magic,magic2python
70 from IPython.Magic import Magic
71 from IPython.Prompts import CachedOutput
71 from IPython.Struct import Struct
72 from IPython.Struct import Struct
72 from IPython.background_jobs import BackgroundJobManager
73 from IPython.background_jobs import BackgroundJobManager
73 from IPython.usage import cmd_line_usage,interactive_usage
74 from IPython.usage import cmd_line_usage,interactive_usage
@@ -229,7 +230,27 b' class SyntaxTB(ultraTB.ListTB):'
229
230
230 #****************************************************************************
231 #****************************************************************************
231 # Main IPython class
232 # Main IPython class
232 class InteractiveShell(Logger, Magic):
233
234 # FIXME: the Magic class is a mixin for now, and will unfortunately remain so
235 # until a full rewrite is made. I've cleaned all cross-class uses of
236 # attributes and methods, but too much user code out there relies on the
237 # equlity %foo == __IP.magic_foo, so I can't actually remove the mixin usage.
238 #
239 # But at least now, all the pieces have been separated and we could, in
240 # principle, stop using the mixin. This will ease the transition to the
241 # chainsaw branch.
242
243 # For reference, the following is the list of 'self.foo' uses in the Magic
244 # class as of 2005-12-28. These are names we CAN'T use in the main ipython
245 # class, to prevent clashes.
246
247 # ['self.__class__', 'self.__dict__', 'self._inspect', 'self._ofind',
248 # 'self.arg_err', 'self.extract_input', 'self.format_', 'self.lsmagic',
249 # 'self.magic_', 'self.options_table', 'self.parse', 'self.shell',
250 # 'self.value']
251
252
253 class InteractiveShell(Magic):
233 """An enhanced console for Python."""
254 """An enhanced console for Python."""
234
255
235 # class attribute to indicate whether the class supports threads or not.
256 # class attribute to indicate whether the class supports threads or not.
@@ -305,7 +326,6 b' class InteractiveShell(Logger, Magic):'
305 # Von: Alex Martelli <aleaxit@yahoo.com>
326 # Von: Alex Martelli <aleaxit@yahoo.com>
306 # Datum: Freitag 01 Oktober 2004 04:45:34 nachmittags/abends
327 # Datum: Freitag 01 Oktober 2004 04:45:34 nachmittags/abends
307 # Gruppen: comp.lang.python
328 # Gruppen: comp.lang.python
308 # Referenzen: 1
309
329
310 # Michael Hohn <hohn@hooknose.lbl.gov> wrote:
330 # Michael Hohn <hohn@hooknose.lbl.gov> wrote:
311 # > >>> print type(builtin_check.get_global_binding('__builtins__'))
331 # > >>> print type(builtin_check.get_global_binding('__builtins__'))
@@ -432,22 +452,17 b' class InteractiveShell(Logger, Magic):'
432 self.ESC_PAREN = '/'
452 self.ESC_PAREN = '/'
433
453
434 # And their associated handlers
454 # And their associated handlers
435 self.esc_handlers = {self.ESC_PAREN:self.handle_auto,
455 self.esc_handlers = {self.ESC_PAREN : self.handle_auto,
436 self.ESC_QUOTE:self.handle_auto,
456 self.ESC_QUOTE : self.handle_auto,
437 self.ESC_QUOTE2:self.handle_auto,
457 self.ESC_QUOTE2 : self.handle_auto,
438 self.ESC_MAGIC:self.handle_magic,
458 self.ESC_MAGIC : self.handle_magic,
439 self.ESC_HELP:self.handle_help,
459 self.ESC_HELP : self.handle_help,
440 self.ESC_SHELL:self.handle_shell_escape,
460 self.ESC_SHELL : self.handle_shell_escape,
441 }
461 }
442
462
443 # class initializations
463 # class initializations
444 Logger.__init__(self,log_ns = self.user_ns)
445 Magic.__init__(self,self)
464 Magic.__init__(self,self)
446
465
447 # an ugly hack to get a pointer to the shell, so I can start writing
448 # magic code via this pointer instead of the current mixin salad.
449 Magic.set_shell(self,self)
450
451 # Python source parser/formatter for syntax highlighting
466 # Python source parser/formatter for syntax highlighting
452 pyformat = PyColorize.Parser().format
467 pyformat = PyColorize.Parser().format
453 self.pycolorize = lambda src: pyformat(src,'str',self.rc['colors'])
468 self.pycolorize = lambda src: pyformat(src,'str',self.rc['colors'])
@@ -488,6 +503,16 b' class InteractiveShell(Logger, Magic):'
488 # Keep track of readline usage (later set by init_readline)
503 # Keep track of readline usage (later set by init_readline)
489 self.has_readline = False
504 self.has_readline = False
490
505
506 # template for logfile headers. It gets resolved at runtime by the
507 # logstart method.
508 self.loghead_tpl = \
509 """#log# Automatic Logger file. *** THIS MUST BE THE FIRST LINE ***
510 #log# DO NOT CHANGE THIS LINE OR THE TWO BELOW
511 #log# opts = %s
512 #log# args = %s
513 #log# It is safe to make manual edits below here.
514 #log#-----------------------------------------------------------------------
515 """
491 # for pushd/popd management
516 # for pushd/popd management
492 try:
517 try:
493 self.home_dir = get_home_dir()
518 self.home_dir = get_home_dir()
@@ -550,19 +575,6 b' class InteractiveShell(Logger, Magic):'
550 # keep track of where we started running (mainly for crash post-mortem)
575 # keep track of where we started running (mainly for crash post-mortem)
551 self.starting_dir = os.getcwd()
576 self.starting_dir = os.getcwd()
552
577
553 # Attributes for Logger mixin class, make defaults here
554 self._dolog = False
555 self.LOG = ''
556 self.LOGDEF = '.InteractiveShell.log'
557 self.LOGMODE = 'over'
558 self.LOGHEAD = Itpl(
559 """#log# Automatic Logger file. *** THIS MUST BE THE FIRST LINE ***
560 #log# DO NOT CHANGE THIS LINE OR THE TWO BELOW
561 #log# opts = $self.rc.opts
562 #log# args = $self.rc.args
563 #log# It is safe to make manual edits below here.
564 #log#-----------------------------------------------------------------------
565 """)
566 # Various switches which can be set
578 # Various switches which can be set
567 self.CACHELENGTH = 5000 # this is cheap, it's just text
579 self.CACHELENGTH = 5000 # this is cheap, it's just text
568 self.BANNER = "Python %(version)s on %(platform)s\n" % sys.__dict__
580 self.BANNER = "Python %(version)s on %(platform)s\n" % sys.__dict__
@@ -655,10 +667,42 b' class InteractiveShell(Logger, Magic):'
655 if rc.readline:
667 if rc.readline:
656 self.init_readline()
668 self.init_readline()
657
669
670 # log system
671 self.logger = Logger(self,logfname='ipython_log.py',logmode='rotate')
672 # local shortcut, this is used a LOT
673 self.log = self.logger.log
674
675 # Initialize cache, set in/out prompts and printing system
676 self.outputcache = CachedOutput(self,
677 rc.cache_size,
678 rc.pprint,
679 input_sep = rc.separate_in,
680 output_sep = rc.separate_out,
681 output_sep2 = rc.separate_out2,
682 ps1 = rc.prompt_in1,
683 ps2 = rc.prompt_in2,
684 ps_out = rc.prompt_out,
685 pad_left = rc.prompts_pad_left)
686
687 # user may have over-ridden the default print hook:
688 try:
689 self.outputcache.__class__.display = self.hooks.display
690 except AttributeError:
691 pass
692
693 # I don't like assigning globally to sys, because it means when embedding
694 # instances, each embedded instance overrides the previous choice. But
695 # sys.displayhook seems to be called internally by exec, so I don't see a
696 # way around it.
697 sys.displayhook = self.outputcache
698
658 # Set user colors (don't do it in the constructor above so that it
699 # Set user colors (don't do it in the constructor above so that it
659 # doesn't crash if colors option is invalid)
700 # doesn't crash if colors option is invalid)
660 self.magic_colors(rc.colors)
701 self.magic_colors(rc.colors)
661
702
703 # Set calling of pdb on exceptions
704 self.call_pdb = rc.pdb
705
662 # Load user aliases
706 # Load user aliases
663 for alias in rc.alias:
707 for alias in rc.alias:
664 self.magic_alias(alias)
708 self.magic_alias(alias)
@@ -742,6 +786,28 b' class InteractiveShell(Logger, Magic):'
742 self.Completer.__class__)
786 self.Completer.__class__)
743 self.Completer.matchers.insert(pos,newcomp)
787 self.Completer.matchers.insert(pos,newcomp)
744
788
789 def _get_call_pdb(self):
790 return self._call_pdb
791
792 def _set_call_pdb(self,val):
793
794 if val not in (0,1,False,True):
795 raise ValueError,'new call_pdb value must be boolean'
796
797 # store value in instance
798 self._call_pdb = val
799
800 # notify the actual exception handlers
801 self.InteractiveTB.call_pdb = val
802 if self.isthreaded:
803 try:
804 self.sys_excepthook.call_pdb = val
805 except:
806 warn('Failed to activate pdb for threaded exception handler')
807
808 call_pdb = property(_get_call_pdb,_set_call_pdb,None,
809 'Control auto-activation of pdb at exceptions')
810
745 def complete(self,text):
811 def complete(self,text):
746 """Return a sorted list of all possible completions on text.
812 """Return a sorted list of all possible completions on text.
747
813
@@ -1907,10 +1973,10 b' want to merge them back into the new files.""" % locals()'
1907 kw.setdefault('quiet',1)
1973 kw.setdefault('quiet',1)
1908 kw.setdefault('exit_ignore',0)
1974 kw.setdefault('exit_ignore',0)
1909 first = xfile.readline()
1975 first = xfile.readline()
1910 _LOGHEAD = str(self.LOGHEAD).split('\n',1)[0].strip()
1976 loghead = str(self.loghead_tpl).split('\n',1)[0].strip()
1911 xfile.close()
1977 xfile.close()
1912 # line by line execution
1978 # line by line execution
1913 if first.startswith(_LOGHEAD) or kw['islog']:
1979 if first.startswith(loghead) or kw['islog']:
1914 print 'Loading log file <%s> one line at a time...' % fname
1980 print 'Loading log file <%s> one line at a time...' % fname
1915 if kw['quiet']:
1981 if kw['quiet']:
1916 stdout_save = sys.stdout
1982 stdout_save = sys.stdout
@@ -1942,9 +2008,6 b' want to merge them back into the new files.""" % locals()'
1942 # don't re-insert logger status info into cache
2008 # don't re-insert logger status info into cache
1943 if line.startswith('#log#'):
2009 if line.startswith('#log#'):
1944 continue
2010 continue
1945 elif line.startswith('#%s'% self.ESC_MAGIC):
1946 self.update_cache(line[1:])
1947 line = magic2python(line)
1948 elif line.startswith('#!'):
2011 elif line.startswith('#!'):
1949 self.update_cache(line[1:])
2012 self.update_cache(line[1:])
1950 else:
2013 else:
@@ -6,7 +6,7 b' Requires Python 2.1 or better.'
6
6
7 This file contains the main make_IPython() starter function.
7 This file contains the main make_IPython() starter function.
8
8
9 $Id: ipmaker.py 965 2005-12-28 23:23:09Z fperez $"""
9 $Id: ipmaker.py 966 2005-12-29 08:34:07Z fperez $"""
10
10
11 #*****************************************************************************
11 #*****************************************************************************
12 # Copyright (C) 2001-2004 Fernando Perez. <fperez@colorado.edu>
12 # Copyright (C) 2001-2004 Fernando Perez. <fperez@colorado.edu>
@@ -51,7 +51,6 b' from IPython.OutputTrap import OutputTrap'
51 from IPython.ConfigLoader import ConfigLoader
51 from IPython.ConfigLoader import ConfigLoader
52 from IPython.iplib import InteractiveShell,qw_lol,import_fail_info
52 from IPython.iplib import InteractiveShell,qw_lol,import_fail_info
53 from IPython.usage import cmd_line_usage,interactive_usage
53 from IPython.usage import cmd_line_usage,interactive_usage
54 from IPython.Prompts import CachedOutput
55 from IPython.genutils import *
54 from IPython.genutils import *
56
55
57 #-----------------------------------------------------------------------------
56 #-----------------------------------------------------------------------------
@@ -322,9 +321,6 b" object? -> Details about 'object'. ?object also works, ?? prints more."
322 mutex_opts(opts,[qw('log logfile'),qw('rcfile profile'),
321 mutex_opts(opts,[qw('log logfile'),qw('rcfile profile'),
323 qw('classic profile'),qw('classic rcfile')])
322 qw('classic profile'),qw('classic rcfile')])
324
323
325 # default logfilename used when -log is called.
326 IP.LOGDEF = 'ipython.log'
327
328 #---------------------------------------------------------------------------
324 #---------------------------------------------------------------------------
329 # Log replay
325 # Log replay
330
326
@@ -681,37 +677,7 b" object? -> Details about 'object'. ?object also works, ?? prints more."
681 # paged:
677 # paged:
682 num_lines_bot = IP_rc.separate_in.count('\n')+1
678 num_lines_bot = IP_rc.separate_in.count('\n')+1
683 IP_rc.screen_length = IP_rc.screen_length - num_lines_bot
679 IP_rc.screen_length = IP_rc.screen_length - num_lines_bot
684 # Initialize cache, set in/out prompts and printing system
685 IP.outputcache = CachedOutput(IP_rc.cache_size,
686 IP_rc.pprint,
687 input_sep = IP_rc.separate_in,
688 output_sep = IP_rc.separate_out,
689 output_sep2 = IP_rc.separate_out2,
690 ps1 = IP_rc.prompt_in1,
691 ps2 = IP_rc.prompt_in2,
692 ps_out = IP_rc.prompt_out,
693 user_ns = IP.user_ns,
694 input_hist = IP.input_hist,
695 pad_left = IP_rc.prompts_pad_left)
696
697 # user may have over-ridden the default print hook:
698 try:
699 IP.outputcache.__class__.display = IP.hooks.display
700 except AttributeError:
701 pass
702
680
703 # Set calling of pdb on exceptions
704 IP.InteractiveTB.call_pdb = IP_rc.pdb
705
706 # I don't like assigning globally to sys, because it means when embedding
707 # instances, each embedded instance overrides the previous choice. But
708 # sys.displayhook seems to be called internally by exec, so I don't see a
709 # way around it.
710 sys.displayhook = IP.outputcache
711
712 # we need to know globally if we're caching i/o or not
713 IP.do_full_cache = IP.outputcache.do_full_cache
714
715 # configure startup banner
681 # configure startup banner
716 if IP_rc.c: # regular python doesn't print the banner with -c
682 if IP_rc.c: # regular python doesn't print the banner with -c
717 IP_rc.banner = 0
683 IP_rc.banner = 0
@@ -6,7 +6,7 b''
6 # the file COPYING, distributed as part of this software.
6 # the file COPYING, distributed as part of this software.
7 #*****************************************************************************
7 #*****************************************************************************
8
8
9 # $Id: usage.py 960 2005-12-28 06:51:01Z fperez $
9 # $Id: usage.py 966 2005-12-29 08:34:07Z fperez $
10
10
11 from IPython import Release
11 from IPython import Release
12 __author__ = '%s <%s>' % Release.authors['Fernando']
12 __author__ = '%s <%s>' % Release.authors['Fernando']
@@ -236,14 +236,14 b' REGULAR OPTIONS'
236 This can also be specified through the environment variable
236 This can also be specified through the environment variable
237 IPYTHONDIR.
237 IPYTHONDIR.
238
238
239 -log|l Generate a log file of all input. The file is named ipython.log
239 -log|l Generate a log file of all input. The file is named
240 in your current directory (which prevents logs from multiple
240 ipython_log.py in your current directory (which prevents logs
241 IPython sessions from trampling each other). You can use this to
241 from multiple IPython sessions from trampling each other). You
242 later restore a session by loading your logfile as a file to be
242 can use this to later restore a session by loading your logfile
243 executed with option -logplay (see below).
243 as a file to be executed with option -logplay (see below).
244
244
245 -logfile|lf
245 -logfile|lf
246 Specifu the name of your logfile.
246 Specify the name of your logfile.
247
247
248 -logplay|lp
248 -logplay|lp
249 Replay a previous log. For restoring a session as close as pos-
249 Replay a previous log. For restoring a session as close as pos-
@@ -1,3 +1,31 b''
1 2005-12-29 Fernando Perez <Fernando.Perez@colorado.edu>
2
3 * IPython/Magic.py (Macro): simplified Macro class to just
4 subclass list. We've had only 2.2 compatibility for a very long
5 time, yet I was still avoiding subclassing the builtin types. No
6 more (I'm also starting to use properties, though I won't shift to
7 2.3-specific features quite yet).
8
9 * IPython/iplib.py (InteractiveShell.post_config_initialization):
10 changed the default logfile name from 'ipython.log' to
11 'ipython_log.py'. These logs are real python files, and now that
12 we have much better multiline support, people are more likely to
13 want to use them as such. Might as well name them correctly.
14
15 * IPython/Magic.py: substantial cleanup. While we can't stop
16 using magics as mixins, due to the existing customizations 'out
17 there' which rely on the mixin naming conventions, at least I
18 cleaned out all cross-class name usage. So once we are OK with
19 breaking compatibility, the two systems can be separated.
20
21 * IPython/Logger.py: major cleanup. This one is NOT a mixin
22 anymore, and the class is a fair bit less hideous as well. New
23 features were also introduced: timestamping of input, and logging
24 of output results. These are user-visible with the -t and -o
25 options to %logstart. Closes
26 http://www.scipy.net/roundup/ipython/issue11 and a request by
27 William Stein (SAGE developer - http://modular.ucsd.edu/sage).
28
1 2005-12-28 Fernando Perez <Fernando.Perez@colorado.edu>
29 2005-12-28 Fernando Perez <Fernando.Perez@colorado.edu>
2
30
3 * IPython/iplib.py (handle_shell_escape): add Ville's patch to
31 * IPython/iplib.py (handle_shell_escape): add Ville's patch to
@@ -205,14 +205,13 b' The name of your IPython configuration directory IPYTHONDIR. This can'
205 also be specified through the environment variable IPYTHONDIR.
205 also be specified through the environment variable IPYTHONDIR.
206 .TP
206 .TP
207 .B \-log|l
207 .B \-log|l
208 Generate a log file of all input. The file is named ipython.log in
208 Generate a log file of all input. The file is named ipython_log.py in your
209 your current directory (which prevents logs from multiple IPython
209 current directory (which prevents logs from multiple IPython sessions from
210 sessions from trampling each other). You can use this to later restore
210 trampling each other). You can use this to later restore a session by loading
211 a session by loading your logfile as a file to be executed with option
211 your logfile as a file to be executed with option -logplay (see below).
212 -logplay (see below).
213 .TP
212 .TP
214 .B \-logfile|lf
213 .B \-logfile|lf
215 Specifu the name of your logfile.
214 Specify the name of your logfile.
216 .TP
215 .TP
217 .B \-logplay|lp
216 .B \-logplay|lp
218 Replay a previous log. For restoring a session as close as possible to
217 Replay a previous log. For restoring a session as close as possible to
@@ -2957,11 +2957,12 b' IPYTHONDIR'
2957 \family default
2957 \family default
2958 \series default
2958 \series default
2959 : generate a log file of all input.
2959 : generate a log file of all input.
2960 Defaults to
2960 The file is named
2961 \family typewriter
2961 \family typewriter
2962 $IPYTHONDIR/log
2962 ipython_log.py
2963 \family default
2963 \family default
2964 .
2964 in your current directory (which prevents logs from multiple IPython sessions
2965 from trampling each other).
2965 You can use this to later restore a session by loading your logfile as
2966 You can use this to later restore a session by loading your logfile as
2966 a file to be executed with option
2967 a file to be executed with option
2967 \family typewriter
2968 \family typewriter
General Comments 0
You need to be logged in to leave comments. Login now