.. :data:: DDEBUG = 5
Very verbose debugging level
+Defines several logs:
+
+`log`
+ main log, initially a duplicated fd 2 (stderr)
+`userlog`
+ public progress log, initially a duplicated fd 1 (stdout)
+`testlog`
+ per-test log, initially no handler, to be directed to file like `{TEST}.log`
+
+.. note:: Currently, the logs and fd's get never closed.
+.. warning:: `Loggers.open_eval_log` changes global fd's 1 and 2 by default.
"""
-import sys, os
-import logging
-from logging import Logger, StreamHandler, Formatter
-
-logging.addLevelName(5,'DDEBUG')
-
-
-class Loggers(Logger):
- """Defines several logs:
-
- `self`
- root log, which sends messages to `eval` and `test` logs
- `self.eval`
- main log, initially a duplicated fd 2 (stderr)
- `self.user`
- public progress log, initially a duplicated fd 1 (stdout)
- `self.test`
- per-test log, initially no handler, to be directed to file like `{TEST}.log`
-
- .. note:: Currently, the logs and fd's get never closed.
- .. warning:: `Loggers.open_eval_log` changes global fd's 1 and 2 by default.
- """
- def __init__(self):
- "Initialize loggers as described in class description."
- Logger.__init__(self, '')
- # Duplicate the fd's
- self.orig_stdout_fd = os.dup(1)
- self.orig_stdout_file = os.fdopen(self.orig_stdout_fd, 'w', 0)
- self.orig_stderr_fd = os.dup(2)
- self.orig_stderr_file = os.fdopen(self.orig_stderr_fd, 'w', 0)
- # Eval main logger
- self.eval = Logger('eval')
- self.eval.addHandler(StreamHandler(self.orig_stderr_file))
- # per-test logger
- self.test = Logger('test')
- self.test_handler = None
- self.test_file = None
- # user progress logger
- self.user = Logger('user')
- self.user.addHandler(StreamHandler(self.orig_stdout_file))
-
- self.addHandler(self.test)
- self.addHandler(self.eval)
- self.debug('Logging initialized.')
+# Global logs to be imported by every module
+
+__all__ = ['log', 'userlog', 'testlog', 'pipelog' ]
+
+log = None
+userlog = None
+testlog = None
+pipelog = None
+
+orig_stdout_fd = None
+orig_stdout_file = None
+orig_stderr_fd = None
+orig_stderr_file = None
+testlog_file = None
+
+import logging, sys
+
+def __init__():
+ """Very basic loggers setup to stderr."""
+
+ global orig_stdout_fd, orig_stdout_file, orig_stderr_fd, orig_stderr_file
+ global log, userlog,
+
+ orig_stdout_fd = os.dup(1)
+ orig_stdout_file = os.fdopen(orig_stdout_fd, 'w', 0)
+ orig_stderr_fd = os.dup(2)
+ orig_stderr_file = os.fdopen(orig_stderr_fd, 'w', 0)
+
+ log = logging.getLogger('mainlog')
+ log.addHandler(StreamHandler(orig_stderr_file))
+
+ userlog = logging.getLogger('userlog')
+ userlog.addHandler(StreamHandler(orig_stdout_file))
- def open_user_log(self, filename, level=logging.INFO):
+ testlog = log
+ pipelog = log
+
+ logging.addLevelName(5,'DDEBUG')
+
+ log.debug('Logging initialized.')
+
+
+def open_user_log(filename, level=logging.INFO):
"""Open user (progress) logfile. Leaves logging to stdout active."""
h = StreamHandler(open(filename, 'w', 0))
h.setFormatter(Formatter('%(message)s'))
- self.user.setLevel(level)
- self.user.addHandler(h)
- self.user.debug('Logging started')
+ userlog.setLevel(level)
+ userlog.addHandler(h)
+
+ log.debug('User logging to %r started', filename)
- def open_eval_log(self, filename, level, redirect_fds = True):
+def open_eval_log(filename, redirect_fds = True):
"""Open main logfile.
- Leaves logging to stderr active. If told to, redirects fd's 1 and 2 to this file.
- Sets level of both `self.eval` and `self`."""
- self.eval_file = open(filename, 'w', 0)
- self.eval_handler = StreamHandler(self.eval_file)
- self.eval_handler.setFormatter(Formatter('%(asctime)s [%(levelno)s] %(message)s'))
- self.eval.addHandler(self.eval_handler)
+ Leaves logging to stderr active. If told to, redirects fd's 1 and 2 to this file."""
+
+ eval_file = open(filename, 'w', 0)
+ h = StreamHandler(self.eval_file)
+ h.setFormatter(Formatter('%(asctime)s [%(levelno)s] %(message)s'))
+ log.addHandler(h)
+ log.debug('Opened eval logfile %r')
+
if redirect_fds:
- os.dup2(self.eval_file.fileno(), 1)
- os.dup2(self.eval_file.fileno(), 2)
- self.eval.setLevel(level)
- self.setLevel(level)
- self.eval.debug('Logging started')
-
-
- def open_test_log(self, filename, level):
- """Open per-test log file, like "{TEST}.log". Also set handler level to `level`."""
- self.debug('Opening per-test log %s' % filename)
- if self.test_handler:
- self.close_test_log()
- self.test_file = open(filename, 'w')
- self.test_handler = StreamHandler(self.test_file)
- self.test.addHandler(self.test_handler)
- self.test.setLevel(level)
- self.test_handler.setFormatter(Formatter('%(asctime)s [%(levelno)s] %(message)s'))
- self.test.debug('Logging started')
-
- def close_test_log(self):
- """Close per-test logfile, leaving only the null handler."""
- if self.test_handler:
- self.test.info('Closing test logfile')
- self.test.removeHandler(self.test_handler)
- self.test_handler = None
- self.test_file.close()
-
- def ddebug(self, msg, *args, **kwargs):
- """Log with priority 5 (normal DEBUG is 10)"""
- self.log(5, msg, *args, **kwargs)
+ os.dup2(eval_file.fileno(), 1)
+ os.dup2(eval_file.fileno(), 2)
+ log.debug('Redirected fds 1,2 -> eval logfile')
+
+
+def open_test_log(filename, level):
+ """Open per-test log file, usually "{TEST}.log", set its level."""
+
+ log.debug('Opening per-test log %r', filename)
+
+ global testlog, testlog_file
+ assert testlog_file is None
+
+ testlog = logging.getLogger('testlog')
+ testlog.setLevel(level)
+ for h in testlog.handlers:
+ testlog.removeHandler(h)
+
+ testlog_file = open(filename, 'w')
+ h = StreamHandler(self.testlog_file)
+ h.setFormatter(Formatter('%(asctime)s [%(levelno)s] %(message)s'))
+ testlog.addHandler(h)
+
+ testlog.debug('Logging started')
+
+def close_test_log():
+ """Close per-test logfile, set `testlog` to `log`."""
+ assert testlog_file is not None
+ testlog_file.close()
+ testlog = log