Skip to content

Commit 5124f54

Browse files
DanielNoordcdce8p
andauthored
Refactor and typing of OutputLine (#5060)
Co-authored-by: Marc Mueller <[email protected]>
1 parent 9dc186f commit 5124f54

File tree

2 files changed

+55
-37
lines changed

2 files changed

+55
-37
lines changed

pylint/testutils/output_line.py

+41-24
Original file line numberDiff line numberDiff line change
@@ -2,10 +2,13 @@
22
# For details: https://github.com/PyCQA/pylint/blob/main/LICENSE
33

44
import collections
5-
from typing import Any, NamedTuple
5+
from typing import Any, NamedTuple, Optional, Sequence, Tuple, Union
6+
7+
from astroid import nodes
68

7-
from pylint import interfaces
89
from pylint.constants import PY38_PLUS
10+
from pylint.interfaces import HIGH, UNDEFINED, Confidence
11+
from pylint.message.message import Message
912
from pylint.testutils.constants import UPDATE_OPTION
1013

1114

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

19-
def __new__(cls, msg_id, line=None, node=None, args=None, confidence=None):
22+
def __new__(
23+
cls,
24+
msg_id: str,
25+
line: Optional[int] = None,
26+
node: Optional[nodes.NodeNG] = None,
27+
args: Any = None,
28+
confidence: Optional[Confidence] = None,
29+
) -> "MessageTest":
2030
return tuple.__new__(cls, (msg_id, line, node, args, confidence))
2131

22-
def __eq__(self, other):
32+
def __eq__(self, other: object) -> bool:
2333
if isinstance(other, MessageTest):
2434
if self.confidence and other.confidence:
2535
return super().__eq__(other)
26-
return self[:-1] == other[:-1]
36+
return tuple(self[:-1]) == tuple(other[:-1])
2737
return NotImplemented # pragma: no cover
2838

2939

3040
class MalformedOutputLineException(Exception):
31-
def __init__(self, row, exception):
41+
def __init__(
42+
self,
43+
row: Union[Sequence[str], str],
44+
exception: Exception,
45+
) -> None:
3246
example = "msg-symbolic-name:42:27:MyClass.my_function:The message"
3347
other_example = "msg-symbolic-name:7:42::The message"
3448
expected = [
@@ -62,39 +76,42 @@ def __init__(self, row, exception):
6276
class OutputLine(NamedTuple):
6377
symbol: str
6478
lineno: int
65-
column: str
66-
object: Any
79+
column: int
80+
object: str
6781
msg: str
68-
confidence: interfaces.Confidence
82+
confidence: str
6983

7084
@classmethod
71-
def from_msg(cls, msg):
72-
column = cls.get_column(msg.column)
85+
def from_msg(cls, msg: Message) -> "OutputLine":
86+
column = cls._get_column(msg.column)
7387
return cls(
7488
msg.symbol,
7589
msg.line,
7690
column,
7791
msg.obj or "",
7892
msg.msg.replace("\r\n", "\n"),
79-
msg.confidence.name
80-
if msg.confidence != interfaces.UNDEFINED
81-
else interfaces.HIGH.name,
93+
msg.confidence.name if msg.confidence != UNDEFINED else HIGH.name,
8294
)
8395

84-
@classmethod
85-
def get_column(cls, column):
96+
@staticmethod
97+
def _get_column(column: str) -> int:
8698
if not PY38_PLUS:
87-
return "" # pragma: no cover
88-
return str(column)
99+
# We check the column only for the new better ast parser introduced in python 3.8
100+
return 0 # pragma: no cover
101+
return int(column)
89102

90103
@classmethod
91-
def from_csv(cls, row):
104+
def from_csv(cls, row: Union[Sequence[str], str]) -> "OutputLine":
92105
try:
93-
confidence = row[5] if len(row) == 6 else interfaces.HIGH.name
94-
column = cls.get_column(row[2])
95-
return cls(row[0], int(row[1]), column, row[3], row[4], confidence)
106+
if isinstance(row, Sequence):
107+
column = cls._get_column(row[2])
108+
if len(row) == 5:
109+
return cls(row[0], int(row[1]), column, row[3], row[4], HIGH.name)
110+
if len(row) == 6:
111+
return cls(row[0], int(row[1]), column, row[3], row[4], row[5])
112+
raise IndexError
96113
except Exception as e:
97114
raise MalformedOutputLineException(row, e) from e
98115

99-
def to_csv(self):
100-
return tuple(self)
116+
def to_csv(self) -> Tuple[str, str, str, str, str, str]:
117+
return tuple(str(i) for i in self) # type: ignore # pylint: disable=not-an-iterable

tests/testutils/test_output_line.py

+14-13
Original file line numberDiff line numberDiff line change
@@ -3,14 +3,15 @@
33

44
# pylint: disable=redefined-outer-name
55

6-
from typing import Callable, List, Optional
6+
from typing import Callable, Optional
77

88
import pytest
99

1010
from pylint.constants import PY38_PLUS
1111
from pylint.interfaces import HIGH, INFERENCE, Confidence
1212
from pylint.message import Message
1313
from pylint.testutils.output_line import MalformedOutputLineException, OutputLine
14+
from pylint.typing import MessageLocationTuple
1415

1516

1617
@pytest.fixture()
@@ -19,14 +20,14 @@ def inner(confidence: Confidence = HIGH) -> Message:
1920
return Message(
2021
symbol="missing-docstring",
2122
msg_id="C0123",
22-
location=[ # type: ignore
23+
location=MessageLocationTuple(
2324
"abspath",
2425
"path",
2526
"module",
2627
"obj",
27-
"line",
28-
"column",
29-
],
28+
1,
29+
2,
30+
),
3031
msg="msg",
3132
confidence=confidence,
3233
)
@@ -37,11 +38,11 @@ def inner(confidence: Confidence = HIGH) -> Message:
3738
def test_output_line() -> None:
3839
output_line = OutputLine(
3940
symbol="missing-docstring",
40-
lineno=0,
41-
column="0",
41+
lineno=1,
42+
column=2,
4243
object="",
4344
msg="Missing docstring's bad.",
44-
confidence=HIGH,
45+
confidence=HIGH.name,
4546
)
4647
assert output_line.symbol == "missing-docstring"
4748

@@ -56,10 +57,10 @@ def test_output_line_from_message(message: Callable) -> None:
5657
def test_output_line_to_csv(confidence: Confidence, message: Callable) -> None:
5758
output_line = OutputLine.from_msg(message(confidence))
5859
csv = output_line.to_csv()
59-
expected_column = "column" if PY38_PLUS else ""
60+
expected_column = "2" if PY38_PLUS else "0"
6061
assert csv == (
6162
"missing-docstring",
62-
"line",
63+
"1",
6364
expected_column,
6465
"obj",
6566
"msg",
@@ -84,10 +85,10 @@ def test_output_line_from_csv_error() -> None:
8485
"confidence,expected_confidence", [[None, "HIGH"], ["INFERENCE", "INFERENCE"]]
8586
)
8687
def test_output_line_from_csv(
87-
confidence: Optional[str], expected_confidence: Confidence
88+
confidence: Optional[str], expected_confidence: str
8889
) -> None:
8990
if confidence:
90-
proper_csv: List[str] = [
91+
proper_csv = [
9192
"missing-docstring",
9293
"1",
9394
"2",
@@ -98,7 +99,7 @@ def test_output_line_from_csv(
9899
else:
99100
proper_csv = ["missing-docstring", "1", "2", "obj", "msg"]
100101
output_line = OutputLine.from_csv(proper_csv)
101-
expected_column = "2" if PY38_PLUS else ""
102+
expected_column = 2 if PY38_PLUS else 0
102103
assert output_line == OutputLine(
103104
symbol="missing-docstring",
104105
lineno=1,

0 commit comments

Comments
 (0)