log.py 5.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180
  1. # vim: set fileencoding=utf-8 :
  2. #
  3. # (C) 2010 Guido Guenther <agx@sigxcpu.org>
  4. # This program is free software; you can redistribute it and/or modify
  5. # it under the terms of the GNU General Public License as published by
  6. # the Free Software Foundation; either version 2 of the License, or
  7. # (at your option) any later version.
  8. #
  9. # This program is distributed in the hope that it will be useful,
  10. # but WITHOUT ANY WARRANTY; without even the implied warranty of
  11. # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  12. # GNU General Public License for more details.
  13. #
  14. # You should have received a copy of the GNU General Public License
  15. # along with this program; if not, please see
  16. # <http://www.gnu.org/licenses/>
  17. #
  18. """Simple colored logging classes"""
  19. import os
  20. import sys
  21. import logging
  22. from logging import (DEBUG, INFO, WARNING, ERROR, CRITICAL, getLogger)
  23. import gbp.tristate
  24. COLORS = dict([('none', 0)] + list(zip(['black', 'red', 'green', 'yellow', 'blue',
  25. 'magenta', 'cyan', 'white'], range(30, 38))))
  26. DEFAULT_COLOR_SCHEME = {DEBUG: COLORS['green'],
  27. INFO: COLORS['green'],
  28. WARNING: COLORS['red'],
  29. ERROR: COLORS['red'],
  30. CRITICAL: COLORS['red']}
  31. class GbpFilter(object):
  32. """Filter for enabling selective output"""
  33. def __init__(self, levels):
  34. self._levels = levels
  35. def filter(self, record):
  36. """Do we show the record"""
  37. if record.levelno in self._levels:
  38. return True
  39. return False
  40. class GbpStreamHandler(logging.StreamHandler):
  41. """Special stream handler for enabling colored output"""
  42. COLOR_SEQ = "\033[%dm"
  43. OFF_SEQ = "\033[0m"
  44. def __init__(self, stream=None, color='auto'):
  45. super(GbpStreamHandler, self).__init__(stream)
  46. self._color = gbp.tristate.Tristate(color)
  47. self._color_scheme = DEFAULT_COLOR_SCHEME.copy()
  48. msg_fmt = "%(color)s%(name)s:%(levelname)s: %(message)s%(coloroff)s"
  49. self.setFormatter(logging.Formatter(fmt=msg_fmt))
  50. def set_color(self, color):
  51. """Set/unset colorized output"""
  52. self._color = gbp.tristate.Tristate(color)
  53. def set_color_scheme(self, color_scheme={}):
  54. """Set logging colors"""
  55. self._color_scheme = DEFAULT_COLOR_SCHEME.copy()
  56. self._color_scheme.update(color_scheme)
  57. def set_format(self, fmt):
  58. """Set logging format"""
  59. self.setFormatter(logging.Formatter(fmt=fmt))
  60. def _use_color(self):
  61. """Check if to print in color or not"""
  62. if self._color.is_on():
  63. return True
  64. elif self._color.is_auto() and hasattr(self.stream, 'isatty'):
  65. in_emacs = (os.getenv("EMACS") and
  66. os.getenv("INSIDE_EMACS", "").endswith(",comint"))
  67. return self.stream.isatty() and not in_emacs
  68. return False
  69. def format(self, record):
  70. """Colorizing formatter"""
  71. record.color = record.coloroff = ""
  72. if self._use_color():
  73. record.color = self.COLOR_SEQ % self._color_scheme[record.levelno]
  74. record.coloroff = self.OFF_SEQ
  75. record.levelname = record.levelname.lower()
  76. return super(GbpStreamHandler, self).format(record)
  77. class GbpLogger(logging.Logger):
  78. """Logger class for git-buildpackage"""
  79. def __init__(self, name, color='auto', *args, **kwargs):
  80. super(GbpLogger, self).__init__(name, *args, **kwargs)
  81. self._default_handlers = [GbpStreamHandler(sys.stdout, color),
  82. GbpStreamHandler(sys.stderr, color)]
  83. self._default_handlers[0].addFilter(GbpFilter([DEBUG, INFO]))
  84. self._default_handlers[1].addFilter(GbpFilter([WARNING, ERROR,
  85. CRITICAL]))
  86. for hdlr in self._default_handlers:
  87. self.addHandler(hdlr)
  88. def set_color(self, color):
  89. """Set/unset colorized output of the default handlers"""
  90. for hdlr in self._default_handlers:
  91. hdlr.set_color(color)
  92. def set_color_scheme(self, color_scheme={}):
  93. """Set the color scheme of the default handlers"""
  94. for hdlr in self._default_handlers:
  95. hdlr.set_color_scheme(color_scheme)
  96. def set_format(self, fmt):
  97. """Set the format of the default handlers"""
  98. for hdlr in self._default_handlers:
  99. hdlr.set_format(fmt)
  100. def err(msg):
  101. """Logs a message with level ERROR on the GBP logger"""
  102. LOGGER.error(msg)
  103. def error(msg):
  104. err(msg)
  105. def warn(msg):
  106. """Logs a message with level WARNING on the GBP logger"""
  107. LOGGER.warning(msg)
  108. def warning(msg):
  109. warn(msg)
  110. def info(msg):
  111. """Logs a message with level INFO on the GBP logger"""
  112. LOGGER.info(msg)
  113. def debug(msg):
  114. """Logs a message with level DEBUG on the GBP logger"""
  115. LOGGER.debug(msg)
  116. def _parse_color_scheme(color_scheme=""):
  117. """Set logging colors"""
  118. scheme = {}
  119. colors = color_scheme.split(':')
  120. levels = (DEBUG, INFO, WARNING, ERROR)
  121. if color_scheme and len(colors) != len(levels):
  122. raise ValueError("Number color fields in color scheme not %d'"
  123. % len(levels))
  124. for field, color in enumerate(colors):
  125. level = levels[field]
  126. try:
  127. scheme[level] = int(color)
  128. except ValueError:
  129. try:
  130. scheme[level] = COLORS[color.lower()]
  131. except KeyError: pass
  132. return scheme
  133. def setup(color, verbose, color_scheme=""):
  134. """Basic logger setup"""
  135. LOGGER.set_color(color)
  136. LOGGER.set_color_scheme(_parse_color_scheme(color_scheme))
  137. if verbose:
  138. LOGGER.setLevel(DEBUG)
  139. else:
  140. LOGGER.setLevel(INFO)
  141. # Initialize the module
  142. logging.setLoggerClass(GbpLogger)
  143. LOGGER = getLogger("gbp")