##// END OF EJS Templates
Merge branch 'master' of github.com:ipython/ipython into trunk
Merge branch 'master' of github.com:ipython/ipython into trunk

File last commit:

r3086:2523ba07
r3237:f0963426 merge
Show More
logger.py
215 lines | 7.6 KiB | text/x-python | PythonLexer
Fernando Perez
Remove all direct shell access from logger....
r3086 """Logger class for IPython's logging facilities.
fperez
Reorganized the directory for ipython/ to have its own dir, which is a bit...
r0 """
#*****************************************************************************
# Copyright (C) 2001 Janko Hauser <jhauser@zscout.de> and
fperez
Small fix in ultraTB, and fix autocall....
r88 # Copyright (C) 2001-2006 Fernando Perez <fperez@colorado.edu>
fperez
Reorganized the directory for ipython/ to have its own dir, which is a bit...
r0 #
# Distributed under the terms of the BSD License. The full license is in
# the file COPYING, distributed as part of this software.
#*****************************************************************************
#****************************************************************************
# Modules and globals
# Python standard modules
fperez
Cosmetic cleanups: put all imports in a single line, and sort them...
r52 import glob
import os
fperez
Major cleanups and changes, see changelog/changeset for full details.
r60 import time
fperez
Reorganized the directory for ipython/ to have its own dir, which is a bit...
r0
#****************************************************************************
fperez
Major cleanups and changes, see changelog/changeset for full details.
r60 # FIXME: This class isn't a mixin anymore, but it still needs attributes from
# ipython and does input cache management. Finish cleanup later...
class Logger(object):
"""A Logfile class with different policies for file creation"""
Fernando Perez
Remove all direct shell access from logger....
r3086 def __init__(self, home_dir, logfname='Logger.log', loghead='',
logmode='over'):
fperez
Reorganized the directory for ipython/ to have its own dir, which is a bit...
r0
fperez
Major cleanups and changes, see changelog/changeset for full details.
r60 # this is the full ipython instance, we need some attributes from it
# which won't exist until later. What a mess, clean up later...
Fernando Perez
Remove all direct shell access from logger....
r3086 self.home_dir = home_dir
fperez
Major cleanups and changes, see changelog/changeset for full details.
r60
self.logfname = logfname
self.loghead = loghead
self.logmode = logmode
self.logfile = None
fperez
Add -r option to %logstart, to log 'raw' input instead of the processed one....
r305 # Whether to log raw or processed input
self.log_raw_input = False
fperez
Major cleanups and changes, see changelog/changeset for full details.
r60 # whether to also log output
self.log_output = False
# whether to put timestamps before each log entry
self.timestamp = False
# activity control flags
self.log_active = False
# logmode is a validated property
def _set_mode(self,mode):
if mode not in ['append','backup','global','over','rotate']:
raise ValueError,'invalid log mode %s given' % mode
self._logmode = mode
def _get_mode(self):
return self._logmode
logmode = property(_get_mode,_set_mode)
def logstart(self,logfname=None,loghead=None,logmode=None,
fperez
Add -r option to %logstart, to log 'raw' input instead of the processed one....
r305 log_output=False,timestamp=False,log_raw_input=False):
fperez
Major cleanups and changes, see changelog/changeset for full details.
r60 """Generate a new log-file with a default header.
Raises RuntimeError if the log has already been started"""
if self.logfile is not None:
raise RuntimeError('Log file is already active: %s' %
self.logfname)
fperez
Reorganized the directory for ipython/ to have its own dir, which is a bit...
r0
fperez
Major cleanups and changes, see changelog/changeset for full details.
r60 self.log_active = True
fperez
Add -r option to %logstart, to log 'raw' input instead of the processed one....
r305 # The parameters can override constructor defaults
if logfname is not None: self.logfname = logfname
if loghead is not None: self.loghead = loghead
if logmode is not None: self.logmode = logmode
# Parameters not part of the constructor
fperez
Major cleanups and changes, see changelog/changeset for full details.
r60 self.timestamp = timestamp
self.log_output = log_output
fperez
Add -r option to %logstart, to log 'raw' input instead of the processed one....
r305 self.log_raw_input = log_raw_input
fperez
Major cleanups and changes, see changelog/changeset for full details.
r60
# init depending on the log mode requested
isfile = os.path.isfile
logmode = self.logmode
if logmode == 'append':
self.logfile = open(self.logfname,'a')
elif logmode == 'backup':
if isfile(self.logfname):
fperez
Reorganized the directory for ipython/ to have its own dir, which is a bit...
r0 backup_logname = self.logfname+'~'
# Manually remove any old backup, since os.rename may fail
# under Windows.
fperez
Major cleanups and changes, see changelog/changeset for full details.
r60 if isfile(backup_logname):
fperez
Reorganized the directory for ipython/ to have its own dir, which is a bit...
r0 os.remove(backup_logname)
os.rename(self.logfname,backup_logname)
self.logfile = open(self.logfname,'w')
fperez
Major cleanups and changes, see changelog/changeset for full details.
r60
elif logmode == 'global':
Fernando Perez
Remove all direct shell access from logger....
r3086 self.logfname = os.path.join(self.home_dir,self.logfname)
fperez
Reorganized the directory for ipython/ to have its own dir, which is a bit...
r0 self.logfile = open(self.logfname, 'a')
fperez
Major cleanups and changes, see changelog/changeset for full details.
r60
elif logmode == 'over':
if isfile(self.logfname):
os.remove(self.logfname)
self.logfile = open(self.logfname,'w')
elif logmode == 'rotate':
if isfile(self.logfname):
if isfile(self.logfname+'.001~'):
fperez
Reorganized the directory for ipython/ to have its own dir, which is a bit...
r0 old = glob.glob(self.logfname+'.*~')
old.sort()
old.reverse()
for f in old:
root, ext = os.path.splitext(f)
num = int(ext[1:-1])+1
os.rename(f, root+'.'+`num`.zfill(3)+'~')
os.rename(self.logfname, self.logfname+'.001~')
self.logfile = open(self.logfname,'w')
fperez
Major cleanups and changes, see changelog/changeset for full details.
r60 if logmode != 'append':
self.logfile.write(self.loghead)
fperez
Reorganized the directory for ipython/ to have its own dir, which is a bit...
r0
fperez
Major cleanups and changes, see changelog/changeset for full details.
r60 self.logfile.flush()
fperez
Reorganized the directory for ipython/ to have its own dir, which is a bit...
r0
def switch_log(self,val):
fperez
Major cleanups and changes, see changelog/changeset for full details.
r60 """Switch logging on/off. val should be ONLY a boolean."""
fperez
Reorganized the directory for ipython/ to have its own dir, which is a bit...
r0
fperez
Major cleanups and changes, see changelog/changeset for full details.
r60 if val not in [False,True,0,1]:
fperez
Reorganized the directory for ipython/ to have its own dir, which is a bit...
r0 raise ValueError, \
fperez
Major cleanups and changes, see changelog/changeset for full details.
r60 'Call switch_log ONLY with a boolean argument, not with:',val
fperez
Reorganized the directory for ipython/ to have its own dir, which is a bit...
r0
fperez
Major cleanups and changes, see changelog/changeset for full details.
r60 label = {0:'OFF',1:'ON',False:'OFF',True:'ON'}
fperez
Reorganized the directory for ipython/ to have its own dir, which is a bit...
r0
fperez
Major cleanups and changes, see changelog/changeset for full details.
r60 if self.logfile is None:
fperez
Reorganized the directory for ipython/ to have its own dir, which is a bit...
r0 print """
fperez
Major cleanups and changes, see changelog/changeset for full details.
r60 Logging hasn't been started yet (use logstart for that).
fperez
Reorganized the directory for ipython/ to have its own dir, which is a bit...
r0
%logon/%logoff are for temporarily starting and stopping logging for a logfile
which already exists. But you must first start the logging process with
%logstart (optionally giving a logfile name)."""
else:
fperez
Major cleanups and changes, see changelog/changeset for full details.
r60 if self.log_active == val:
fperez
Reorganized the directory for ipython/ to have its own dir, which is a bit...
r0 print 'Logging is already',label[val]
else:
print 'Switching logging',label[val]
fperez
Major cleanups and changes, see changelog/changeset for full details.
r60 self.log_active = not self.log_active
self.log_active_out = self.log_active
fperez
Reorganized the directory for ipython/ to have its own dir, which is a bit...
r0
def logstate(self):
"""Print a status message about the logger."""
fperez
Major cleanups and changes, see changelog/changeset for full details.
r60 if self.logfile is None:
fperez
Reorganized the directory for ipython/ to have its own dir, which is a bit...
r0 print 'Logging has not been activated.'
else:
fperez
Major cleanups and changes, see changelog/changeset for full details.
r60 state = self.log_active and 'active' or 'temporarily suspended'
fperez
doc fixes to logging
r68 print 'Filename :',self.logfname
print 'Mode :',self.logmode
print 'Output logging :',self.log_output
fperez
Minor fix to diagnostics, forgot to list raw input.
r306 print 'Raw input log :',self.log_raw_input
fperez
doc fixes to logging
r68 print 'Timestamping :',self.timestamp
print 'State :',state
fperez
Reorganized the directory for ipython/ to have its own dir, which is a bit...
r0
Fernando Perez
Remove all direct shell access from logger....
r3086 def log(self, line_mod, line_ori):
"""Write the sources to a log.
fperez
Add -r option to %logstart, to log 'raw' input instead of the processed one....
r305
Inputs:
- line_mod: possibly modified input, such as the transformations made
by input prefilters or input handlers of various kinds. This should
always be valid Python.
Fernando Perez
Remove all direct shell access from logger....
r3086 - line_ori: unmodified input line from the user. This is not
necessarily valid Python.
"""
fperez
Add -r option to %logstart, to log 'raw' input instead of the processed one....
r305
# Write the log line, but decide which one according to the
# log_raw_input flag, set when the log is started.
if self.log_raw_input:
self.log_write(line_ori)
else:
self.log_write(line_mod)
fperez
Major cleanups and changes, see changelog/changeset for full details.
r60
Fernando Perez
Remove all direct shell access from logger....
r3086 def log_write(self, data, kind='input'):
fperez
Major cleanups and changes, see changelog/changeset for full details.
r60 """Write data to the log file, if active"""
vivainio
Merged 1071-1076 from banches/0.7.1
r145 #print 'data: %r' % data # dbg
fperez
Major cleanups and changes, see changelog/changeset for full details.
r60 if self.log_active and data:
write = self.logfile.write
if kind=='input':
if self.timestamp:
write(time.strftime('# %a, %d %b %Y %H:%M:%S\n',
time.localtime()))
Fernando Perez
Remove all direct shell access from logger....
r3086 write(data)
fperez
Major cleanups and changes, see changelog/changeset for full details.
r60 elif kind=='output' and self.log_output:
odata = '\n'.join(['#[Out]# %s' % s
Fernando Perez
Remove all direct shell access from logger....
r3086 for s in data.splitlines()])
fperez
Major cleanups and changes, see changelog/changeset for full details.
r60 write('%s\n' % odata)
fperez
Reorganized the directory for ipython/ to have its own dir, which is a bit...
r0 self.logfile.flush()
fperez
- Add %logstop functionality to fully stop logger after turning it on....
r895 def logstop(self):
"""Fully stop logging and close log file.
In order to start logging again, a new logstart() call needs to be
made, possibly (though not necessarily) with a new filename, mode and
other options."""
fperez
Major cleanups and changes, see changelog/changeset for full details.
r60 self.logfile.close()
self.logfile = None
fperez
- Add %logstop functionality to fully stop logger after turning it on....
r895 self.log_active = False
# For backwards compatibility, in case anyone was using this.
close_log = logstop