Skip to content

Commit

Permalink
Refactor and typing of OutputLine (#5060)
Browse files Browse the repository at this point in the history
Co-authored-by: Marc Mueller <30130371+cdce8p@users.noreply.github.com>
  • Loading branch information
DanielNoord and cdce8p authored Sep 23, 2021
1 parent 9dc186f commit 5124f54
Show file tree
Hide file tree
Showing 2 changed files with 55 additions and 37 deletions.
65 changes: 41 additions & 24 deletions pylint/testutils/output_line.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,10 +2,13 @@
# For details: https://github.com/PyCQA/pylint/blob/main/LICENSE

import collections
from typing import Any, NamedTuple
from typing import Any, NamedTuple, Optional, Sequence, Tuple, Union

from astroid import nodes

from pylint import interfaces
from pylint.constants import PY38_PLUS
from pylint.interfaces import HIGH, UNDEFINED, Confidence
from pylint.message.message import Message
from pylint.testutils.constants import UPDATE_OPTION


Expand All @@ -16,19 +19,30 @@ class MessageTest(
):
"""Used to test messages produced by pylint. Class name cannot start with Test as pytest doesn't allow constructors in test classes."""

def __new__(cls, msg_id, line=None, node=None, args=None, confidence=None):
def __new__(
cls,
msg_id: str,
line: Optional[int] = None,
node: Optional[nodes.NodeNG] = None,
args: Any = None,
confidence: Optional[Confidence] = None,
) -> "MessageTest":
return tuple.__new__(cls, (msg_id, line, node, args, confidence))

def __eq__(self, other):
def __eq__(self, other: object) -> bool:
if isinstance(other, MessageTest):
if self.confidence and other.confidence:
return super().__eq__(other)
return self[:-1] == other[:-1]
return tuple(self[:-1]) == tuple(other[:-1])
return NotImplemented # pragma: no cover


class MalformedOutputLineException(Exception):
def __init__(self, row, exception):
def __init__(
self,
row: Union[Sequence[str], str],
exception: Exception,
) -> None:
example = "msg-symbolic-name:42:27:MyClass.my_function:The message"
other_example = "msg-symbolic-name:7:42::The message"
expected = [
Expand Down Expand Up @@ -62,39 +76,42 @@ def __init__(self, row, exception):
class OutputLine(NamedTuple):
symbol: str
lineno: int
column: str
object: Any
column: int
object: str
msg: str
confidence: interfaces.Confidence
confidence: str

@classmethod
def from_msg(cls, msg):
column = cls.get_column(msg.column)
def from_msg(cls, msg: Message) -> "OutputLine":
column = cls._get_column(msg.column)
return cls(
msg.symbol,
msg.line,
column,
msg.obj or "",
msg.msg.replace("\r\n", "\n"),
msg.confidence.name
if msg.confidence != interfaces.UNDEFINED
else interfaces.HIGH.name,
msg.confidence.name if msg.confidence != UNDEFINED else HIGH.name,
)

@classmethod
def get_column(cls, column):
@staticmethod
def _get_column(column: str) -> int:
if not PY38_PLUS:
return "" # pragma: no cover
return str(column)
# We check the column only for the new better ast parser introduced in python 3.8
return 0 # pragma: no cover
return int(column)

@classmethod
def from_csv(cls, row):
def from_csv(cls, row: Union[Sequence[str], str]) -> "OutputLine":
try:
confidence = row[5] if len(row) == 6 else interfaces.HIGH.name
column = cls.get_column(row[2])
return cls(row[0], int(row[1]), column, row[3], row[4], confidence)
if isinstance(row, Sequence):
column = cls._get_column(row[2])
if len(row) == 5:
return cls(row[0], int(row[1]), column, row[3], row[4], HIGH.name)
if len(row) == 6:
return cls(row[0], int(row[1]), column, row[3], row[4], row[5])
raise IndexError
except Exception as e:
raise MalformedOutputLineException(row, e) from e

def to_csv(self):
return tuple(self)
def to_csv(self) -> Tuple[str, str, str, str, str, str]:
return tuple(str(i) for i in self) # type: ignore # pylint: disable=not-an-iterable
27 changes: 14 additions & 13 deletions tests/testutils/test_output_line.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,14 +3,15 @@

# pylint: disable=redefined-outer-name

from typing import Callable, List, Optional
from typing import Callable, Optional

import pytest

from pylint.constants import PY38_PLUS
from pylint.interfaces import HIGH, INFERENCE, Confidence
from pylint.message import Message
from pylint.testutils.output_line import MalformedOutputLineException, OutputLine
from pylint.typing import MessageLocationTuple


@pytest.fixture()
Expand All @@ -19,14 +20,14 @@ def inner(confidence: Confidence = HIGH) -> Message:
return Message(
symbol="missing-docstring",
msg_id="C0123",
location=[ # type: ignore
location=MessageLocationTuple(
"abspath",
"path",
"module",
"obj",
"line",
"column",
],
1,
2,
),
msg="msg",
confidence=confidence,
)
Expand All @@ -37,11 +38,11 @@ def inner(confidence: Confidence = HIGH) -> Message:
def test_output_line() -> None:
output_line = OutputLine(
symbol="missing-docstring",
lineno=0,
column="0",
lineno=1,
column=2,
object="",
msg="Missing docstring's bad.",
confidence=HIGH,
confidence=HIGH.name,
)
assert output_line.symbol == "missing-docstring"

Expand All @@ -56,10 +57,10 @@ def test_output_line_from_message(message: Callable) -> None:
def test_output_line_to_csv(confidence: Confidence, message: Callable) -> None:
output_line = OutputLine.from_msg(message(confidence))
csv = output_line.to_csv()
expected_column = "column" if PY38_PLUS else ""
expected_column = "2" if PY38_PLUS else "0"
assert csv == (
"missing-docstring",
"line",
"1",
expected_column,
"obj",
"msg",
Expand All @@ -84,10 +85,10 @@ def test_output_line_from_csv_error() -> None:
"confidence,expected_confidence", [[None, "HIGH"], ["INFERENCE", "INFERENCE"]]
)
def test_output_line_from_csv(
confidence: Optional[str], expected_confidence: Confidence
confidence: Optional[str], expected_confidence: str
) -> None:
if confidence:
proper_csv: List[str] = [
proper_csv = [
"missing-docstring",
"1",
"2",
Expand All @@ -98,7 +99,7 @@ def test_output_line_from_csv(
else:
proper_csv = ["missing-docstring", "1", "2", "obj", "msg"]
output_line = OutputLine.from_csv(proper_csv)
expected_column = "2" if PY38_PLUS else ""
expected_column = 2 if PY38_PLUS else 0
assert output_line == OutputLine(
symbol="missing-docstring",
lineno=1,
Expand Down

0 comments on commit 5124f54

Please sign in to comment.