text.py 5.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155
  1. # Copyright (c) 2003-2007 Sylvain Thenault (thenault@gmail.com).
  2. # Copyright (c) 2003-2012 LOGILAB S.A. (Paris, FRANCE).
  3. # This program is free software; you can redistribute it and/or modify it under
  4. # the terms of the GNU General Public License as published by the Free Software
  5. # Foundation; either version 2 of the License, or (at your option) any later
  6. # version.
  7. #
  8. # This program is distributed in the hope that it will be useful, but WITHOUT
  9. # ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
  10. # FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
  11. #
  12. # You should have received a copy of the GNU General Public License along with
  13. # this program; if not, write to the Free Software Foundation, Inc.,
  14. # 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
  15. """Plain text reporters:
  16. :text: the default one grouping messages by module
  17. :parseable:
  18. standard parseable output with full module path on each message (for
  19. editor integration)
  20. :colorized: an ANSI colorized text reporter
  21. """
  22. import os
  23. import sys
  24. from logilab.common.ureports import TextWriter
  25. from logilab.common.textutils import colorize_ansi
  26. from pylint.interfaces import IReporter
  27. from pylint.reporters import BaseReporter
  28. TITLE_UNDERLINES = ['', '=', '-', '.']
  29. class TextReporter(BaseReporter):
  30. """reports messages and layouts in plain text
  31. """
  32. __implements__ = IReporter
  33. extension = 'txt'
  34. def __init__(self, output=sys.stdout):
  35. BaseReporter.__init__(self, output)
  36. self._modules = {}
  37. def add_message(self, msg_id, location, msg):
  38. """manage message of different type and in the context of path"""
  39. module, obj, line, col_offset = location[1:]
  40. if module not in self._modules:
  41. if module:
  42. self.writeln('************* Module %s' % module)
  43. self._modules[module] = 1
  44. else:
  45. self.writeln('************* %s' % module)
  46. if obj:
  47. obj = ':%s' % obj
  48. if self.include_ids:
  49. sigle = msg_id
  50. else:
  51. sigle = msg_id[0]
  52. self.writeln('%s:%3s,%s%s: %s' % (sigle, line, col_offset, obj, msg))
  53. def _display(self, layout):
  54. """launch layouts display"""
  55. print >> self.out
  56. TextWriter().format(layout, self.out)
  57. class ParseableTextReporter(TextReporter):
  58. """a reporter very similar to TextReporter, but display messages in a form
  59. recognized by most text editors :
  60. <filename>:<linenum>:<msg>
  61. """
  62. line_format = '%(path)s:%(line)s: [%(sigle)s%(obj)s] %(msg)s'
  63. def __init__(self, output=sys.stdout, relative=True):
  64. TextReporter.__init__(self, output)
  65. if relative:
  66. self._prefix = os.getcwd() + os.sep
  67. else:
  68. self._prefix = ''
  69. def add_message(self, msg_id, location, msg):
  70. """manage message of different type and in the context of path"""
  71. path, _, obj, line, _ = location
  72. if obj:
  73. obj = ', %s' % obj
  74. if self.include_ids:
  75. sigle = msg_id
  76. else:
  77. sigle = msg_id[0]
  78. if self._prefix:
  79. path = path.replace(self._prefix, '')
  80. self.writeln(self.line_format % locals())
  81. class VSTextReporter(ParseableTextReporter):
  82. """Visual studio text reporter"""
  83. line_format = '%(path)s(%(line)s): [%(sigle)s%(obj)s] %(msg)s'
  84. class ColorizedTextReporter(TextReporter):
  85. """Simple TextReporter that colorizes text output"""
  86. COLOR_MAPPING = {
  87. "I" : ("green", None),
  88. 'C' : (None, "bold"),
  89. 'R' : ("magenta", "bold, italic"),
  90. 'W' : ("blue", None),
  91. 'E' : ("red", "bold"),
  92. 'F' : ("red", "bold, underline"),
  93. 'S' : ("yellow", "inverse"), # S stands for module Separator
  94. }
  95. def __init__(self, output=sys.stdout, color_mapping = None):
  96. TextReporter.__init__(self, output)
  97. self.color_mapping = color_mapping or \
  98. dict(ColorizedTextReporter.COLOR_MAPPING)
  99. def _get_decoration(self, msg_id):
  100. """Returns the tuple color, style associated with msg_id as defined
  101. in self.color_mapping
  102. """
  103. try:
  104. return self.color_mapping[msg_id[0]]
  105. except KeyError:
  106. return None, None
  107. def add_message(self, msg_id, location, msg):
  108. """manage message of different types, and colorize output
  109. using ansi escape codes
  110. """
  111. module, obj, line, _ = location[1:]
  112. if module not in self._modules:
  113. color, style = self._get_decoration('S')
  114. if module:
  115. modsep = colorize_ansi('************* Module %s' % module,
  116. color, style)
  117. else:
  118. modsep = colorize_ansi('************* %s' % module,
  119. color, style)
  120. self.writeln(modsep)
  121. self._modules[module] = 1
  122. if obj:
  123. obj = ':%s' % obj
  124. if self.include_ids:
  125. sigle = msg_id
  126. else:
  127. sigle = msg_id[0]
  128. color, style = self._get_decoration(sigle)
  129. msg = colorize_ansi(msg, color, style)
  130. sigle = colorize_ansi(sigle, color, style)
  131. self.writeln('%s:%3s%s: %s' % (sigle, line, obj, msg))