text: """Logger class for IPython's logging facilities.
  """
  
  #*****************************************************************************
  #       Copyright (C) 2001 Janko Hauser <jhauser@zscout.de> and
  #       Copyright (C) 2001-2006 Fernando Perez <fperez@colorado.edu>
  #
  #  Distributed under the terms of the BSD License.  The full license is in
  #  the file COPYING, distributed as part of this software.
  #*****************************************************************************
  
  #****************************************************************************
  # Modules and globals
  
  # Python standard modules
  import glob
  import io
  import os
  import time
  
  from IPython.utils.py3compat import str_to_unicode
  
  #****************************************************************************
  # 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"""
  
      def __init__(self, home_dir, logfname='Logger.log', loghead='',
                   logmode='over'):
  
          # this is the full ipython instance, we need some attributes from it
          # which won't exist until later. What a mess, clean up later...
          self.home_dir = home_dir
  
          self.logfname = logfname
          self.loghead = loghead
          self.logmode = logmode
          self.logfile = None
  
          # Whether to log raw or processed input
          self.log_raw_input = False
  
          # 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,
                   log_output=False, timestamp=False, log_raw_input=False):
          """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)
  
          # 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
          self.timestamp = timestamp
          self.log_output = log_output
          self.log_raw_input = log_raw_input
  
          # init depending on the log mode requested
          isfile = os.path.isfile
          logmode = self.logmode
  
          if logmode == 'append':
              self.logfile = io.open(self.logfname, 'a', encoding='utf-8')
  
          elif logmode == 'backup':
              if isfile(self.logfname):
                  backup_logname = self.logfname+'~'
                  # Manually remove any old backup, since os.rename may fail
                  # under Windows.
                  if isfile(backup_logname):
                      os.remove(backup_logname)
                  os.rename(self.logfname,backup_logname)
              self.logfile = io.open(self.logfname, 'w', encoding='utf-8')
  
          elif logmode == 'global':
              self.logfname = os.path.join(self.home_dir,self.logfname)
              self.logfile = io.open(self.logfname, 'a', encoding='utf-8')
  
          elif logmode == 'over':
              if isfile(self.logfname):
                  os.remove(self.logfname)
              self.logfile = io.open(self.logfname,'w', encoding='utf-8')
  
          elif logmode == 'rotate':
              if isfile(self.logfname):
                  if isfile(self.logfname+'.001~'):
                      old = glob.glob(self.logfname+'.*~')
                      old.sort()
                      old.reverse()
                      for f in old:
                          root, ext = os.path.splitext(f)
                          num = int(ext[1:-1])+1
                          os.rename(f, root+'.'+repr(num).zfill(3)+'~')
                  os.rename(self.logfname, self.logfname+'.001~')
              self.logfile = io.open(self.logfname, 'w', encoding='utf-8')
  
          if logmode != 'append':
              self.logfile.write(self.loghead)
  
          self.logfile.flush()
          self.log_active = True
  
      def switch_log(self,val):
          """Switch logging on/off. val should be ONLY a boolean."""
  
          if val not in [False,True,0,1]:
              raise ValueError('Call switch_log ONLY with a boolean argument, not with:').with_traceback(val)
  
          label = {0:'OFF',1:'ON',False:'OFF',True:'ON'}
  
          if self.logfile is None:
              print("""
  Logging hasn't been started yet (use logstart for that).
  
  %logon/%logoff are for temporarily starting and stopping logging for a logfile
  which already exists. But you must first start the logging process with
  %logstart (optionally giving a logfile name).""")
  
          else:
              if self.log_active == val:
                  print('Logging is already',label[val])
              else:
                  print('Switching logging',label[val])
                  self.log_active = not self.log_active
                  self.log_active_out = self.log_active
  
      def logstate(self):
          """Print a status message about the logger."""
          if self.logfile is None:
              print('Logging has not been activated.')
          else:
              state = self.log_active and 'active' or 'temporarily suspended'
              print('Filename       :',self.logfname)
              print('Mode           :',self.logmode)
              print('Output logging :',self.log_output)
              print('Raw input log  :',self.log_raw_input)
              print('Timestamping   :',self.timestamp)
              print('State          :',state)
  
      def log(self, line_mod, line_ori):
          """Write the sources to a log.
  
          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.
  
          - line_ori: unmodified input line from the user.  This is not
          necessarily valid Python.
          """
  
          # 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)
  
      def log_write(self, data, kind='input'):
          """Write data to the log file, if active"""
  
          #print 'data: %r' % data # dbg
          if self.log_active and data:
              write = self.logfile.write
              if kind=='input':
                  if self.timestamp:
                      write(str_to_unicode(time.strftime('# %a, %d %b %Y %H:%M:%S\n',
                                          time.localtime())))
                  write(data)
              elif kind=='output' and self.log_output:
                  odata = '\n'.join(['#[Out]# %s' % s
                                     for s in data.splitlines()])
                  write('%s\n' % odata)
              self.logfile.flush()
  
      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."""
  
          if self.logfile is not None:
              self.logfile.close()
              self.logfile = None
          else:
              print("Logging hadn't been started.")
          self.log_active = False
  
      # For backwards compatibility, in case anyone was using this.
      close_log = logstop
  