You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

logging.py 3.2 KiB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130
  1. from __future__ import absolute_import
  2. import contextlib
  3. import logging
  4. import logging.handlers
  5. import os
  6. try:
  7. import threading
  8. except ImportError:
  9. import dummy_threading as threading
  10. from pip.compat import WINDOWS
  11. from pip.utils import ensure_dir
  12. try:
  13. from pip._vendor import colorama
  14. # Lots of different errors can come from this, including SystemError and
  15. # ImportError.
  16. except Exception:
  17. colorama = None
  18. _log_state = threading.local()
  19. _log_state.indentation = 0
  20. @contextlib.contextmanager
  21. def indent_log(num=2):
  22. """
  23. A context manager which will cause the log output to be indented for any
  24. log messages emited inside it.
  25. """
  26. _log_state.indentation += num
  27. try:
  28. yield
  29. finally:
  30. _log_state.indentation -= num
  31. def get_indentation():
  32. return _log_state.indentation
  33. class IndentingFormatter(logging.Formatter):
  34. def format(self, record):
  35. """
  36. Calls the standard formatter, but will indent all of the log messages
  37. by our current indentation level.
  38. """
  39. formatted = logging.Formatter.format(self, record)
  40. formatted = "".join([
  41. (" " * get_indentation()) + line
  42. for line in formatted.splitlines(True)
  43. ])
  44. return formatted
  45. def _color_wrap(*colors):
  46. def wrapped(inp):
  47. return "".join(list(colors) + [inp, colorama.Style.RESET_ALL])
  48. return wrapped
  49. class ColorizedStreamHandler(logging.StreamHandler):
  50. # Don't build up a list of colors if we don't have colorama
  51. if colorama:
  52. COLORS = [
  53. # This needs to be in order from highest logging level to lowest.
  54. (logging.ERROR, _color_wrap(colorama.Fore.RED)),
  55. (logging.WARNING, _color_wrap(colorama.Fore.YELLOW)),
  56. ]
  57. else:
  58. COLORS = []
  59. def __init__(self, stream=None):
  60. logging.StreamHandler.__init__(self, stream)
  61. if WINDOWS and colorama:
  62. self.stream = colorama.AnsiToWin32(self.stream)
  63. def should_color(self):
  64. # Don't colorize things if we do not have colorama
  65. if not colorama:
  66. return False
  67. real_stream = (
  68. self.stream if not isinstance(self.stream, colorama.AnsiToWin32)
  69. else self.stream.wrapped
  70. )
  71. # If the stream is a tty we should color it
  72. if hasattr(real_stream, "isatty") and real_stream.isatty():
  73. return True
  74. # If we have an ASNI term we should color it
  75. if os.environ.get("TERM") == "ANSI":
  76. return True
  77. # If anything else we should not color it
  78. return False
  79. def format(self, record):
  80. msg = logging.StreamHandler.format(self, record)
  81. if self.should_color():
  82. for level, color in self.COLORS:
  83. if record.levelno >= level:
  84. msg = color(msg)
  85. break
  86. return msg
  87. class BetterRotatingFileHandler(logging.handlers.RotatingFileHandler):
  88. def _open(self):
  89. ensure_dir(os.path.dirname(self.baseFilename))
  90. return logging.handlers.RotatingFileHandler._open(self)
  91. class MaxLevelFilter(logging.Filter):
  92. def __init__(self, level):
  93. self.level = level
  94. def filter(self, record):
  95. return record.levelno < self.level