Skip to content

Commit

Permalink
Update reporters to (allow) use of end_line and end_column (#…
Browse files Browse the repository at this point in the history
…5372)

* Update reporters to (allow) use end_line and end_column

Co-authored-by: Marc Mueller <30130371+cdce8p@users.noreply.github.com>
Co-authored-by: Pierre Sassoulas <pierre.sassoulas@gmail.com>
  • Loading branch information
3 people committed Nov 24, 2021
1 parent 5e9d20d commit 7c3533c
Show file tree
Hide file tree
Showing 5 changed files with 111 additions and 2 deletions.
5 changes: 5 additions & 0 deletions ChangeLog
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,11 @@ Release date: TBA

Closes #4982

* Add ability to add ``end_line`` and ``end_column`` to the ``--msg-template`` option.
With the standard ``TextReporter`` this will add the line and column number of the
end of a node to the output of Pylint. If these numbers are unknown, they are represented
by an empty string.

* Introduced primer tests and a configuration tests framework. The helper classes available in
``pylint/testutil/`` are still unstable and might be modified in the near future.

Expand Down
7 changes: 7 additions & 0 deletions doc/user_guide/output.rst
Original file line number Diff line number Diff line change
Expand Up @@ -58,6 +58,10 @@ line
line number
column
column number
end_line
line number of the end of the node
end_column
column number of the end of the node
module
module name
obj
Expand Down Expand Up @@ -94,6 +98,9 @@ A few other examples:
The ``--msg-template`` option can only be combined with text-based reporters (``--output-format`` either unspecified or one of: parseable, colorized or msvs).
If both ``--output-format`` and ``--msg-template`` are specified, the ``--msg-template`` option will take precedence over the default line format defined by the reporter class.

If ``end_line`` or ``end_column`` are ``None``, they will be represented as an empty string
by the default ``TextReporter``.

.. _Python new format syntax: https://docs.python.org/2/library/string.html#formatstrings

Source code analysis section
Expand Down
5 changes: 5 additions & 0 deletions doc/whatsnew/2.12.rst
Original file line number Diff line number Diff line change
Expand Up @@ -205,6 +205,11 @@ Other Changes

Partially closes #5321

* Add ability to add ``end_line`` and ``end_column`` to the ``--msg-template`` option.
With the standard ``TextReporter`` this will add the line and column number of the
end of a node to the output of Pylint. If these numbers are unknown, they are represented
by an empty string.

* Introduced primer tests and a configuration tests framework. The helper classes available in
``pylint/testutil/`` are still unstable and might be modified in the near future.

Expand Down
30 changes: 28 additions & 2 deletions pylint/reporters/text.py
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@
:colorized: an ANSI colorized text reporter
"""
import os
import re
import sys
import warnings
from typing import (
Expand Down Expand Up @@ -183,13 +184,38 @@ def __init__(self, output: Optional[TextIO] = None) -> None:
super().__init__(output)
self._modules: Set[str] = set()
self._template = self.line_format
self._fixed_template = self.line_format
"""The output format template with any unrecognized arguments removed"""

def on_set_current_module(self, module: str, filepath: Optional[str]) -> None:
self._template = str(self.linter.config.msg_template or self._template)
"""Set the format template to be used and check for unrecognized arguments."""
template = str(self.linter.config.msg_template or self._template)

# Return early if the template is the same as the previous one
if template == self._template:
return

# Set template to the currently selected template
self._template = template

# Check to see if all parameters in the template are attributes of the Message
arguments = re.findall(r"\{(.+?)(:.*)?\}", template)
for argument in arguments:
if argument[0] not in Message._fields:
warnings.warn(
f"Don't recognize the argument '{argument[0]}' in the --msg-template. "
"Are you sure it is supported on the current version of pylint?"
)
template = re.sub(r"\{" + argument[0] + r"(:.*?)?\}", "", template)
self._fixed_template = template

def write_message(self, msg: Message) -> None:
"""Convenience method to write a formatted message with class default template"""
self.writeln(msg.format(self._template))
self_dict = msg._asdict()
for key in ("end_line", "end_column"):
self_dict[key] = self_dict[key] or ""

self.writeln(self._fixed_template.format(**self_dict))

def handle_message(self, msg: Message) -> None:
"""manage message of different type and in the context of path"""
Expand Down
66 changes: 66 additions & 0 deletions tests/unittest_reporting.py
Original file line number Diff line number Diff line change
Expand Up @@ -57,6 +57,72 @@ def test_template_option(linter):
assert output.getvalue() == "************* Module 0123\nC0301:001\nC0301:002\n"


def test_template_option_default(linter) -> None:
"""Test the default msg-template setting"""
output = StringIO()
linter.reporter.out = output
linter.open()
linter.set_current_module("my_module")
linter.add_message("C0301", line=1, args=(1, 2))
linter.add_message("line-too-long", line=2, args=(3, 4))

out_lines = output.getvalue().split("\n")
assert out_lines[1] == "my_module:1:0: C0301: Line too long (1/2) (line-too-long)"
assert out_lines[2] == "my_module:2:0: C0301: Line too long (3/4) (line-too-long)"


def test_template_option_end_line(linter) -> None:
"""Test the msg-template option with end_line and end_column"""
output = StringIO()
linter.reporter.out = output
linter.set_option(
"msg-template",
"{path}:{line}:{column}:{end_line}:{end_column}: {msg_id}: {msg} ({symbol})",
)
linter.open()
linter.set_current_module("my_mod")
linter.add_message("C0301", line=1, args=(1, 2))
linter.add_message(
"line-too-long", line=2, end_lineno=2, end_col_offset=4, args=(3, 4)
)

out_lines = output.getvalue().split("\n")
assert out_lines[1] == "my_mod:1:0::: C0301: Line too long (1/2) (line-too-long)"
assert out_lines[2] == "my_mod:2:0:2:4: C0301: Line too long (3/4) (line-too-long)"


def test_template_option_non_exisiting(linter) -> None:
"""Test the msg-template option with a non exisiting options.
This makes sure that this option remains backwards compatible as new
parameters do not break on previous versions"""
output = StringIO()
linter.reporter.out = output
linter.set_option(
"msg-template",
"{path}:{line}:{a_new_option}:({a_second_new_option:03d})",
)
linter.open()
with pytest.warns(UserWarning) as records:
linter.set_current_module("my_mod")
assert len(records) == 2
assert (
"Don't recognize the argument 'a_new_option'" in records[0].message.args[0]
)
assert (
"Don't recognize the argument 'a_second_new_option'"
in records[1].message.args[0]
)

linter.add_message("C0301", line=1, args=(1, 2))
linter.add_message(
"line-too-long", line=2, end_lineno=2, end_col_offset=4, args=(3, 4)
)

out_lines = output.getvalue().split("\n")
assert out_lines[1] == "my_mod:1::()"
assert out_lines[2] == "my_mod:2::()"


def test_deprecation_set_output(recwarn):
"""TODO remove in 3.0"""
reporter = BaseReporter()
Expand Down

0 comments on commit 7c3533c

Please sign in to comment.