Adding new stuff
This commit is contained in:
parent
39ee792ad4
commit
a410da0e04
722 changed files with 331 additions and 189 deletions
|
|
@ -1,133 +0,0 @@
|
|||
# Copyright (c) 2003-2013 LOGILAB S.A. (Paris, FRANCE).
|
||||
# This program is free software; you can redistribute it and/or modify it under
|
||||
# the terms of the GNU General Public License as published by the Free Software
|
||||
# Foundation; either version 2 of the License, or (at your option) any later
|
||||
# version.
|
||||
#
|
||||
# This program is distributed in the hope that it will be useful, but WITHOUT
|
||||
# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
|
||||
# FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
|
||||
#
|
||||
# You should have received a copy of the GNU General Public License along with
|
||||
# this program; if not, write to the Free Software Foundation, Inc.,
|
||||
# 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
||||
"""utilities methods and classes for reporters"""
|
||||
from __future__ import print_function
|
||||
|
||||
import sys
|
||||
import locale
|
||||
import os
|
||||
|
||||
|
||||
from pylint import utils
|
||||
|
||||
CMPS = ['=', '-', '+']
|
||||
|
||||
# py3k has no more cmp builtin
|
||||
if sys.version_info >= (3, 0):
|
||||
def cmp(a, b): # pylint: disable=redefined-builtin
|
||||
return (a > b) - (a < b)
|
||||
|
||||
def diff_string(old, new):
|
||||
"""given a old and new int value, return a string representing the
|
||||
difference
|
||||
"""
|
||||
diff = abs(old - new)
|
||||
diff_str = "%s%s" % (CMPS[cmp(old, new)], diff and ('%.2f' % diff) or '')
|
||||
return diff_str
|
||||
|
||||
|
||||
class BaseReporter(object):
|
||||
"""base class for reporters
|
||||
|
||||
symbols: show short symbolic names for messages.
|
||||
"""
|
||||
|
||||
extension = ''
|
||||
|
||||
def __init__(self, output=None):
|
||||
self.linter = None
|
||||
# self.include_ids = None # Deprecated
|
||||
# self.symbols = None # Deprecated
|
||||
self.section = 0
|
||||
self.out = None
|
||||
self.out_encoding = None
|
||||
self.encode = None
|
||||
self.set_output(output)
|
||||
# Build the path prefix to strip to get relative paths
|
||||
self.path_strip_prefix = os.getcwd() + os.sep
|
||||
|
||||
def handle_message(self, msg):
|
||||
"""Handle a new message triggered on the current file.
|
||||
|
||||
Invokes the legacy add_message API by default."""
|
||||
self.add_message(
|
||||
msg.msg_id, (msg.abspath, msg.module, msg.obj, msg.line, msg.column),
|
||||
msg.msg)
|
||||
|
||||
def add_message(self, msg_id, location, msg):
|
||||
"""Deprecated, do not use."""
|
||||
raise NotImplementedError
|
||||
|
||||
def set_output(self, output=None):
|
||||
"""set output stream"""
|
||||
self.out = output or sys.stdout
|
||||
# py3k streams handle their encoding :
|
||||
if sys.version_info >= (3, 0):
|
||||
self.encode = lambda x: x
|
||||
return
|
||||
|
||||
def encode(string):
|
||||
if not isinstance(string, unicode):
|
||||
return string
|
||||
encoding = (getattr(self.out, 'encoding', None) or
|
||||
locale.getdefaultlocale()[1] or
|
||||
sys.getdefaultencoding())
|
||||
# errors=replace, we don't want to crash when attempting to show
|
||||
# source code line that can't be encoded with the current locale
|
||||
# settings
|
||||
return string.encode(encoding, 'replace')
|
||||
self.encode = encode
|
||||
|
||||
def writeln(self, string=''):
|
||||
"""write a line in the output buffer"""
|
||||
print(self.encode(string), file=self.out)
|
||||
|
||||
def display_results(self, layout):
|
||||
"""display results encapsulated in the layout tree"""
|
||||
self.section = 0
|
||||
if hasattr(layout, 'report_id'):
|
||||
layout.children[0].children[0].data += ' (%s)' % layout.report_id
|
||||
self._display(layout)
|
||||
|
||||
def _display(self, layout):
|
||||
"""display the layout"""
|
||||
raise NotImplementedError()
|
||||
|
||||
# Event callbacks
|
||||
|
||||
def on_set_current_module(self, module, filepath):
|
||||
"""starting analyzis of a module"""
|
||||
pass
|
||||
|
||||
def on_close(self, stats, previous_stats):
|
||||
"""global end of analyzis"""
|
||||
pass
|
||||
|
||||
|
||||
class CollectingReporter(BaseReporter):
|
||||
"""collects messages"""
|
||||
|
||||
name = 'collector'
|
||||
|
||||
def __init__(self):
|
||||
BaseReporter.__init__(self)
|
||||
self.messages = []
|
||||
|
||||
def handle_message(self, msg):
|
||||
self.messages.append(msg)
|
||||
|
||||
|
||||
def initialize(linter):
|
||||
"""initialize linter with reporters in this package """
|
||||
utils.register_plugins(linter, __path__[0])
|
||||
Binary file not shown.
|
|
@ -1,27 +0,0 @@
|
|||
""" reporter used by gui.py """
|
||||
|
||||
import sys
|
||||
|
||||
from pylint.interfaces import IReporter
|
||||
from pylint.reporters import BaseReporter
|
||||
from logilab.common.ureports import TextWriter
|
||||
|
||||
|
||||
class GUIReporter(BaseReporter):
|
||||
"""saves messages"""
|
||||
|
||||
__implements__ = IReporter
|
||||
extension = ''
|
||||
|
||||
def __init__(self, gui, output=sys.stdout):
|
||||
"""init"""
|
||||
BaseReporter.__init__(self, output)
|
||||
self.gui = gui
|
||||
|
||||
def handle_message(self, msg):
|
||||
"""manage message of different type and in the context of path"""
|
||||
self.gui.msg_queue.put(msg)
|
||||
|
||||
def _display(self, layout):
|
||||
"""launch layouts display"""
|
||||
TextWriter().format(layout, self.out)
|
||||
|
|
@ -1,101 +0,0 @@
|
|||
# Copyright (c) 2003-2013 LOGILAB S.A. (Paris, FRANCE).
|
||||
# This program is free software; you can redistribute it and/or modify it under
|
||||
# the terms of the GNU General Public License as published by the Free Software
|
||||
# Foundation; either version 2 of the License, or (at your option) any later
|
||||
# version.
|
||||
#
|
||||
# This program is distributed in the hope that it will be useful, but WITHOUT
|
||||
# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
|
||||
# FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
|
||||
#
|
||||
# You should have received a copy of the GNU General Public License along with
|
||||
# this program; if not, write to the Free Software Foundation, Inc.,
|
||||
# 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
||||
"""HTML reporter"""
|
||||
|
||||
import itertools
|
||||
import string
|
||||
import sys
|
||||
|
||||
from logilab.common.ureports import HTMLWriter, Section, Table
|
||||
|
||||
from pylint.interfaces import IReporter
|
||||
from pylint.reporters import BaseReporter
|
||||
|
||||
|
||||
class HTMLReporter(BaseReporter):
|
||||
"""report messages and layouts in HTML"""
|
||||
|
||||
__implements__ = IReporter
|
||||
name = 'html'
|
||||
extension = 'html'
|
||||
|
||||
def __init__(self, output=sys.stdout):
|
||||
BaseReporter.__init__(self, output)
|
||||
self.msgs = []
|
||||
# Add placeholders for title and parsed messages
|
||||
self.header = None
|
||||
self.msgargs = []
|
||||
|
||||
@staticmethod
|
||||
def _parse_msg_template(msg_template):
|
||||
formatter = string.Formatter()
|
||||
parsed = formatter.parse(msg_template)
|
||||
for item in parsed:
|
||||
if item[1]:
|
||||
yield item[1]
|
||||
|
||||
def _parse_template(self):
|
||||
"""Helper function to parse the message template"""
|
||||
self.header = []
|
||||
if self.linter.config.msg_template:
|
||||
msg_template = self.linter.config.msg_template
|
||||
else:
|
||||
msg_template = '{category}{module}{obj}{line}{column}{msg}'
|
||||
|
||||
_header, _msgs = itertools.tee(self._parse_msg_template(msg_template))
|
||||
self.header = list(_header)
|
||||
self.msgargs = list(_msgs)
|
||||
|
||||
def handle_message(self, msg):
|
||||
"""manage message of different type and in the context of path"""
|
||||
|
||||
# It would be better to do this in init, but currently we do not
|
||||
# have access to the linter (as it is setup in lint.set_reporter()
|
||||
# Therefore we try to parse just the once.
|
||||
if self.header is None:
|
||||
self._parse_template()
|
||||
|
||||
# We want to add the lines given by the template
|
||||
self.msgs += [str(getattr(msg, field)) for field in self.msgargs]
|
||||
|
||||
def set_output(self, output=None):
|
||||
"""set output stream
|
||||
|
||||
messages buffered for old output is processed first"""
|
||||
if self.out and self.msgs:
|
||||
self._display(Section())
|
||||
BaseReporter.set_output(self, output)
|
||||
|
||||
def _display(self, layout):
|
||||
"""launch layouts display
|
||||
|
||||
overridden from BaseReporter to add insert the messages section
|
||||
(in add_message, message is not displayed, just collected so it
|
||||
can be displayed in an html table)
|
||||
"""
|
||||
if self.msgs:
|
||||
# add stored messages to the layout
|
||||
msgs = self.header
|
||||
cols = len(self.header)
|
||||
msgs += self.msgs
|
||||
sect = Section('Messages')
|
||||
layout.append(sect)
|
||||
sect.append(Table(cols=cols, children=msgs, rheaders=1))
|
||||
self.msgs = []
|
||||
HTMLWriter().format(layout, self.out)
|
||||
|
||||
|
||||
def register(linter):
|
||||
"""Register the reporter classes with the linter."""
|
||||
linter.register_reporter(HTMLReporter)
|
||||
|
|
@ -1,58 +0,0 @@
|
|||
# Copyright (c) 2003-2014 LOGILAB S.A. (Paris, FRANCE).
|
||||
# This program is free software; you can redistribute it and/or modify it under
|
||||
# the terms of the GNU General Public License as published by the Free Software
|
||||
# Foundation; either version 2 of the License, or (at your option) any later
|
||||
# version.
|
||||
#
|
||||
# This program is distributed in the hope that it will be useful, but WITHOUT
|
||||
# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
|
||||
# FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
|
||||
#
|
||||
# You should have received a copy of the GNU General Public License along with
|
||||
# this program; if not, write to the Free Software Foundation, Inc.,
|
||||
# 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
||||
"""JSON reporter"""
|
||||
from __future__ import absolute_import, print_function
|
||||
|
||||
import json
|
||||
import sys
|
||||
from cgi import escape
|
||||
|
||||
from pylint.interfaces import IReporter
|
||||
from pylint.reporters import BaseReporter
|
||||
|
||||
|
||||
class JSONReporter(BaseReporter):
|
||||
"""Report messages and layouts in JSON."""
|
||||
|
||||
__implements__ = IReporter
|
||||
name = 'json'
|
||||
extension = 'json'
|
||||
|
||||
def __init__(self, output=sys.stdout):
|
||||
BaseReporter.__init__(self, output)
|
||||
self.messages = []
|
||||
|
||||
def handle_message(self, message):
|
||||
"""Manage message of different type and in the context of path."""
|
||||
|
||||
self.messages.append({
|
||||
'type': message.category,
|
||||
'module': message.module,
|
||||
'obj': message.obj,
|
||||
'line': message.line,
|
||||
'column': message.column,
|
||||
'path': message.path,
|
||||
'symbol': message.symbol,
|
||||
'message': escape(message.msg or ''),
|
||||
})
|
||||
|
||||
def _display(self, layout):
|
||||
"""Launch layouts display"""
|
||||
if self.messages:
|
||||
print(json.dumps(self.messages, indent=4), file=self.out)
|
||||
|
||||
|
||||
def register(linter):
|
||||
"""Register the reporter classes with the linter."""
|
||||
linter.register_reporter(JSONReporter)
|
||||
|
|
@ -1,146 +0,0 @@
|
|||
# Copyright (c) 2003-2013 LOGILAB S.A. (Paris, FRANCE).
|
||||
# This program is free software; you can redistribute it and/or modify it under
|
||||
# the terms of the GNU General Public License as published by the Free Software
|
||||
# Foundation; either version 2 of the License, or (at your option) any later
|
||||
# version.
|
||||
#
|
||||
# This program is distributed in the hope that it will be useful, but WITHOUT
|
||||
# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
|
||||
# FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
|
||||
#
|
||||
# You should have received a copy of the GNU General Public License along with
|
||||
# this program; if not, write to the Free Software Foundation, Inc.,
|
||||
# 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
||||
"""Plain text reporters:
|
||||
|
||||
:text: the default one grouping messages by module
|
||||
:colorized: an ANSI colorized text reporter
|
||||
"""
|
||||
from __future__ import print_function
|
||||
|
||||
import warnings
|
||||
|
||||
from logilab.common.ureports import TextWriter
|
||||
from logilab.common.textutils import colorize_ansi
|
||||
|
||||
from pylint.interfaces import IReporter
|
||||
from pylint.reporters import BaseReporter
|
||||
import six
|
||||
|
||||
TITLE_UNDERLINES = ['', '=', '-', '.']
|
||||
|
||||
|
||||
class TextReporter(BaseReporter):
|
||||
"""reports messages and layouts in plain text"""
|
||||
|
||||
__implements__ = IReporter
|
||||
name = 'text'
|
||||
extension = 'txt'
|
||||
line_format = '{C}:{line:3d},{column:2d}: {msg} ({symbol})'
|
||||
|
||||
def __init__(self, output=None):
|
||||
BaseReporter.__init__(self, output)
|
||||
self._modules = set()
|
||||
self._template = None
|
||||
|
||||
def on_set_current_module(self, module, filepath):
|
||||
self._template = six.text_type(self.linter.config.msg_template or self.line_format)
|
||||
|
||||
def write_message(self, msg):
|
||||
"""Convenience method to write a formated message with class default template"""
|
||||
self.writeln(msg.format(self._template))
|
||||
|
||||
def handle_message(self, msg):
|
||||
"""manage message of different type and in the context of path"""
|
||||
if msg.module not in self._modules:
|
||||
if msg.module:
|
||||
self.writeln('************* Module %s' % msg.module)
|
||||
self._modules.add(msg.module)
|
||||
else:
|
||||
self.writeln('************* ')
|
||||
self.write_message(msg)
|
||||
|
||||
def _display(self, layout):
|
||||
"""launch layouts display"""
|
||||
print(file=self.out)
|
||||
TextWriter().format(layout, self.out)
|
||||
|
||||
|
||||
class ParseableTextReporter(TextReporter):
|
||||
"""a reporter very similar to TextReporter, but display messages in a form
|
||||
recognized by most text editors :
|
||||
|
||||
<filename>:<linenum>:<msg>
|
||||
"""
|
||||
name = 'parseable'
|
||||
line_format = '{path}:{line}: [{msg_id}({symbol}), {obj}] {msg}'
|
||||
|
||||
def __init__(self, output=None):
|
||||
warnings.warn('%s output format is deprecated. This is equivalent '
|
||||
'to --msg-template=%s' % (self.name, self.line_format),
|
||||
DeprecationWarning)
|
||||
TextReporter.__init__(self, output)
|
||||
|
||||
|
||||
class VSTextReporter(ParseableTextReporter):
|
||||
"""Visual studio text reporter"""
|
||||
name = 'msvs'
|
||||
line_format = '{path}({line}): [{msg_id}({symbol}){obj}] {msg}'
|
||||
|
||||
|
||||
class ColorizedTextReporter(TextReporter):
|
||||
"""Simple TextReporter that colorizes text output"""
|
||||
|
||||
name = 'colorized'
|
||||
COLOR_MAPPING = {
|
||||
"I" : ("green", None),
|
||||
'C' : (None, "bold"),
|
||||
'R' : ("magenta", "bold, italic"),
|
||||
'W' : ("blue", None),
|
||||
'E' : ("red", "bold"),
|
||||
'F' : ("red", "bold, underline"),
|
||||
'S' : ("yellow", "inverse"), # S stands for module Separator
|
||||
}
|
||||
|
||||
def __init__(self, output=None, color_mapping=None):
|
||||
TextReporter.__init__(self, output)
|
||||
self.color_mapping = color_mapping or \
|
||||
dict(ColorizedTextReporter.COLOR_MAPPING)
|
||||
|
||||
def _get_decoration(self, msg_id):
|
||||
"""Returns the tuple color, style associated with msg_id as defined
|
||||
in self.color_mapping
|
||||
"""
|
||||
try:
|
||||
return self.color_mapping[msg_id[0]]
|
||||
except KeyError:
|
||||
return None, None
|
||||
|
||||
def handle_message(self, msg):
|
||||
"""manage message of different types, and colorize output
|
||||
using ansi escape codes
|
||||
"""
|
||||
if msg.module not in self._modules:
|
||||
color, style = self._get_decoration('S')
|
||||
if msg.module:
|
||||
modsep = colorize_ansi('************* Module %s' % msg.module,
|
||||
color, style)
|
||||
else:
|
||||
modsep = colorize_ansi('************* %s' % msg.module,
|
||||
color, style)
|
||||
self.writeln(modsep)
|
||||
self._modules.add(msg.module)
|
||||
color, style = self._get_decoration(msg.C)
|
||||
|
||||
msg = msg._replace(
|
||||
**{attr: colorize_ansi(getattr(msg, attr), color, style)
|
||||
for attr in ('msg', 'symbol', 'category', 'C')})
|
||||
self.write_message(msg)
|
||||
|
||||
|
||||
def register(linter):
|
||||
"""Register the reporter classes with the linter."""
|
||||
linter.register_reporter(TextReporter)
|
||||
linter.register_reporter(ParseableTextReporter)
|
||||
linter.register_reporter(VSTextReporter)
|
||||
linter.register_reporter(ColorizedTextReporter)
|
||||
Loading…
Add table
Add a link
Reference in a new issue