Source code for core.log

#!/usr/bin/env python
# -*- coding: utf-8 -*-
"""Logging module."""

import sys
import traceback

_log = None

# Logging levels
INFO = 2

[docs]class Log(object): """Logging class.""" def __init__(self): """Constructor for Log. Sets the maximum logging level to INFO.""" self.max_level = INFO self.output_err = False self.output_out = False self.level_stack = [] self.lines = [] self.prefixes = []
[docs] def push_level(self, level): """Temporarily changes the logging level to <level>. Call pop_level to restore the previous level.""" self.level_stack.append(level) self.set_level(level)
[docs] def pop_level(self): """Restores the previous logging level, if the level stack is not empty.""" try: self.max_level = self.level_stack.pop() except IndexError: self.e('Tried to pop logging level, but stack empty', stack=True)
[docs] def set_level(self, level): """Sets the maximum logging level to <level>.""" self.max_level = level
[docs] def push_prefix(self, prefix): """Adds a prefix to future log messages. Old prefixes will appear before new prefixes.""" self.prefixes.append(prefix)
[docs] def pop_prefix(self): """Removes the most recently added prefix from future log messages.""" try: self.prefixes.pop() except IndexError: self.e('Tried to pop logging prefix, but stack empty', stack=True)
def __get_prefixes(self): """Returns a string containing the prefixes for this log message.""" if not self.prefixes: return '' return ': '.join(self.prefixes + [''])
[docs] def log(self, log_level, message, *args, **kwargs): """Logs a message if the current logging level includes messages at level <log_level>. Args: log_level: the level to log the message at. If less than the current logging level, nothing will happen. message: the message to log. *args: Used to format the message with the ``%`` operator. stack: if True, logs a stack trace. If sys.excinfo contains an exception, this will be formatted and logged instead. """ if log_level < self.max_level: return p = self.__get_level_string(log_level) + self.__get_prefixes() self.__write(p + str(message) % args + "\n") if kwargs.get('stack', False): ex = sys.exc_info() if ex[2]: for line in traceback.format_exception(*ex): self.__write(line) else: for line in traceback.format_stack(): self.__write(line)
@staticmethod def __get_level_string(level): """Returns a prefix corresponding to the given logging level.""" return ["VERBOSE", "DEBUG", "INFO", "WARNING", "ERROR"][level] + ": "
[docs] def d(self, message, *args, **kwargs): """Writes a DEBUG message to the log. See `Log.log` for details.""" return self.log(DEBUG, message, *args, **kwargs)
[docs] def e(self, message, *args, **kwargs): """Writes an ERROR message to the log. See `Log.log` for details.""" return self.log(ERROR, message, *args, **kwargs)
[docs] def i(self, message, *args, **kwargs): """Writes a INFO message to the log. See `Log.log` for details.""" return self.log(INFO, message, *args, **kwargs)
[docs] def v(self, message, *args, **kwargs): """Writes a VERBOSE message to the log. See `Log.log` for details.""" return self.log(VERBOSE, message, *args, **kwargs)
[docs] def w(self, message, *args, **kwargs): """Writes a WARNING message to the log. See `Log.log` for details.""" return self.log(WARNING, message, *args, **kwargs)
[docs] def get_lines(self): """Returns all logged lines.""" return self.lines
def __write(self, text): """Writes a line of text to the log.""" if self.output_err: sys.stderr.write(text) if self.output_out: sys.stdout.write(text) self.lines.append(text)
[docs]def get(): """Returns the default Log instance.""" return _log
# prepare the default instance _log = Log() # Output to error log on the default instance _log.output_err = True # expose the methods targeting the default instance on the module itself push_level = _log.push_level pop_level = _log.pop_level set_level = _log.set_level log = _log.log debug = d = _log.d error = e = _log.e info = i = _log.i verbose = v = _log.v warning = w = _log.w get_lines = _log.get_lines push_prefix = _log.push_prefix pop_prefix = _log.pop_prefix