Skip to content

Commit f9b4ee0

Browse files
committed
WIP: Typing changes left
2 parents 6f24105 + 70af2e7 commit f9b4ee0

File tree

13 files changed

+186
-100
lines changed

13 files changed

+186
-100
lines changed

pylint/checkers/similar.py

Lines changed: 5 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -49,10 +49,11 @@
4949
import sys
5050
from collections import defaultdict
5151
from getopt import getopt
52-
from io import BufferedIOBase, BufferedReader, BytesIO
52+
from io import BufferedReader, BytesIO
5353
from itertools import chain, groupby
5454
from typing import (
5555
Any,
56+
Callable,
5657
Dict,
5758
FrozenSet,
5859
Generator,
@@ -379,12 +380,10 @@ def append_stream(
379380
self, streamid: str, stream: STREAM_TYPES, encoding: Optional[str] = None
380381
) -> None:
381382
"""append a file to search for similarities"""
382-
if isinstance(stream, BufferedIOBase):
383-
if encoding is None:
384-
raise ValueError
385-
readlines = decoding_stream(stream, encoding).readlines
383+
if encoding is None:
384+
readlines: Union[Callable[..., Union[str, bytes]], Any] = stream.readlines
386385
else:
387-
readlines = stream.readlines # type: ignore # hint parameter is incorrectly typed as non-optional
386+
readlines = decoding_stream(stream, encoding).readlines
388387
try:
389388
self.linesets.append(
390389
LineSet(

pylint/reporters/base_reporter.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -21,7 +21,7 @@ class BaseReporter:
2121

2222
extension = ""
2323

24-
def __init__(self, output=None):
24+
def __init__(self, output=None) -> None:
2525
self.linter = None
2626
self.section = 0
2727
self.out = None
@@ -39,7 +39,7 @@ def set_output(self, output=None):
3939
"""set output stream"""
4040
self.out = output or sys.stdout
4141

42-
def writeln(self, string=""):
42+
def writeln(self, string: str = "") -> None:
4343
"""write a line in the output buffer"""
4444
print(string, file=self.out)
4545

pylint/reporters/text.py

Lines changed: 16 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -26,12 +26,14 @@
2626
import os
2727
import sys
2828
import warnings
29-
from typing import TYPE_CHECKING, Optional
29+
from typing import TYPE_CHECKING, Optional, Set
3030

3131
from pylint import utils
3232
from pylint.interfaces import IReporter
33+
from pylint.lint.pylinter import PyLinter
3334
from pylint.message import Message
3435
from pylint.reporters import BaseReporter
36+
from pylint.reporters.ureports.nodes import Section
3537
from pylint.reporters.ureports.text_writer import TextWriter
3638

3739
if TYPE_CHECKING:
@@ -64,7 +66,7 @@
6466
}
6567

6668

67-
def _get_ansi_code(color=None, style=None):
69+
def _get_ansi_code(color: Optional[str] = None, style: Optional[str] = None) -> str:
6870
"""return ansi escape code corresponding to color and style
6971
7072
:type color: str or None
@@ -98,7 +100,7 @@ def _get_ansi_code(color=None, style=None):
98100
return ""
99101

100102

101-
def colorize_ansi(msg, color=None, style=None):
103+
def colorize_ansi(msg: str, color: str = None, style: Optional[str] = None) -> str:
102104
"""colorize message by wrapping it with ansi escape codes
103105
104106
:type msg: str or unicode
@@ -136,15 +138,15 @@ class TextReporter(BaseReporter):
136138
extension = "txt"
137139
line_format = "{path}:{line}:{column}: {msg_id}: {msg} ({symbol})"
138140

139-
def __init__(self, output=None):
141+
def __init__(self, output: Optional[StringIO] = None) -> None:
140142
BaseReporter.__init__(self, output)
141-
self._modules = set()
143+
self._modules: Set[str] = set()
142144
self._template = self.line_format
143145

144146
def on_set_current_module(self, module: str, filepath: Optional[str]) -> None:
145147
self._template = str(self.linter.config.msg_template or self._template)
146148

147-
def write_message(self, msg):
149+
def write_message(self, msg: Message) -> None:
148150
"""Convenience method to write a formatted message with class default template"""
149151
self.writeln(msg.format(self._template))
150152

@@ -174,7 +176,7 @@ class ParseableTextReporter(TextReporter):
174176
name = "parseable"
175177
line_format = "{path}:{line}: [{msg_id}({symbol}), {obj}] {msg}"
176178

177-
def __init__(self, output=None):
179+
def __init__(self, output: Optional[Any] = None) -> None:
178180
warnings.warn(
179181
f"{self.name} output format is deprecated. This is equivalent to --msg-template={self.line_format}",
180182
DeprecationWarning,
@@ -203,7 +205,9 @@ class ColorizedTextReporter(TextReporter):
203205
"S": ("yellow", "inverse"), # S stands for module Separator
204206
}
205207

206-
def __init__(self, output=None, color_mapping=None):
208+
def __init__(
209+
self, output: Optional[StringIO] = None, color_mapping: Optional[Any] = None
210+
) -> None:
207211
TextReporter.__init__(self, output)
208212
self.color_mapping = color_mapping or dict(ColorizedTextReporter.COLOR_MAPPING)
209213
ansi_terms = ["xterm-16color", "xterm-256color"]
@@ -214,7 +218,9 @@ def __init__(self, output=None, color_mapping=None):
214218

215219
self.out = colorama.AnsiToWin32(self.out)
216220

217-
def _get_decoration(self, msg_id):
221+
def _get_decoration(
222+
self, msg_id: str
223+
) -> Union[Tuple[None, None], Tuple[str, Optional[str]]]:
218224
"""Returns the tuple color, style associated with msg_id as defined
219225
in self.color_mapping
220226
"""
@@ -248,7 +254,7 @@ def handle_message(self, msg: Message) -> None:
248254
self.write_message(msg)
249255

250256

251-
def register(linter):
257+
def register(linter: PyLinter) -> None:
252258
"""Register the reporter classes with the linter."""
253259
linter.register_reporter(TextReporter)
254260
linter.register_reporter(ParseableTextReporter)

pylint/testutils/checker_test_case.py

Lines changed: 9 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -2,34 +2,37 @@
22
# For details: https://github.com/PyCQA/pylint/blob/main/LICENSE
33

44
import contextlib
5-
from typing import Dict, Optional, Type
5+
from typing import Dict, Iterator, Type
6+
7+
from astroid.nodes import Module
68

79
from pylint.testutils.global_test_linter import linter
10+
from pylint.testutils.output_line import Message
811
from pylint.testutils.unittest_linter import UnittestLinter
912
from pylint.utils import ASTWalker
1013

1114

1215
class CheckerTestCase:
1316
"""A base testcase class for unit testing individual checker classes."""
1417

15-
CHECKER_CLASS: Optional[Type] = None
18+
CHECKER_CLASS: Type
1619
CONFIG: Dict = {}
1720

18-
def setup_method(self):
21+
def setup_method(self) -> None:
1922
self.linter = UnittestLinter()
2023
self.checker = self.CHECKER_CLASS(self.linter) # pylint: disable=not-callable
2124
for key, value in self.CONFIG.items():
2225
setattr(self.checker.config, key, value)
2326
self.checker.open()
2427

2528
@contextlib.contextmanager
26-
def assertNoMessages(self):
29+
def assertNoMessages(self) -> Iterator[None]:
2730
"""Assert that no messages are added by the given method."""
2831
with self.assertAddsMessages():
2932
yield
3033

3134
@contextlib.contextmanager
32-
def assertAddsMessages(self, *messages):
35+
def assertAddsMessages(self, *messages: Message) -> Iterator[None]:
3336
"""Assert that exactly the given method adds the given messages.
3437
3538
The list of messages must exactly match *all* the messages added by the
@@ -47,7 +50,7 @@ def assertAddsMessages(self, *messages):
4750
)
4851
assert got == list(messages), msg
4952

50-
def walk(self, node):
53+
def walk(self, node: Module) -> None:
5154
"""recursive walk on the given node"""
5255
walker = ASTWalker(linter)
5356
walker.add_checker(self.checker)

pylint/testutils/lint_module_test.py

Lines changed: 16 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@
77
import sys
88
from collections import Counter
99
from io import StringIO, TextIOWrapper
10-
from typing import TYPE_CHECKING, Dict, List, Optional, Tuple
10+
from typing import TYPE_CHECKING, Dict, List, Optional, TextIO, Tuple, Union
1111

1212
import pytest
1313
from _pytest.config import Config
@@ -53,7 +53,7 @@ def __init__(self, test_file: FunctionalTestFile, config: Optional[Config] = Non
5353
self._test_file = test_file
5454
self._config = config
5555

56-
def setUp(self):
56+
def setUp(self) -> None:
5757
if self._should_be_skipped_due_to_version():
5858
pytest.skip(
5959
f"Test cannot run with Python {sys.version.split(' ', maxsplit=1)[0]}."
@@ -78,10 +78,10 @@ def setUp(self):
7878
if sys.platform.lower() in platforms:
7979
pytest.skip(f"Test cannot run on platform {sys.platform!r}")
8080

81-
def runTest(self):
81+
def runTest(self) -> None:
8282
self._runTest()
8383

84-
def _should_be_skipped_due_to_version(self):
84+
def _should_be_skipped_due_to_version(self) -> bool:
8585
return (
8686
sys.version_info < self._test_file.options["min_pyver"]
8787
or sys.version_info > self._test_file.options["max_pyver"]
@@ -141,21 +141,21 @@ def multiset_difference(
141141
return missing, unexpected
142142

143143
# pylint: disable=consider-using-with
144-
def _open_expected_file(self):
144+
def _open_expected_file(self) -> Union[StringIO, TextIOWrapper, TextIO]:
145145
try:
146146
return open(self._test_file.expected_output, encoding="utf-8")
147147
except FileNotFoundError:
148148
return StringIO("")
149149

150150
# pylint: disable=consider-using-with
151-
def _open_source_file(self):
151+
def _open_source_file(self) -> TextIO:
152152
if self._test_file.base == "invalid_encoded_data":
153153
return open(self._test_file.source, encoding="utf-8")
154154
if "latin1" in self._test_file.base:
155155
return open(self._test_file.source, encoding="latin1")
156156
return open(self._test_file.source, encoding="utf8")
157157

158-
def _get_expected(self):
158+
def _get_expected(self) -> Tuple[Counter, List[OutputLine]]:
159159
with self._open_source_file() as f:
160160
expected_msgs = self.get_expected_messages(f)
161161
if not expected_msgs:
@@ -166,10 +166,10 @@ def _get_expected(self):
166166
]
167167
return expected_msgs, expected_output_lines
168168

169-
def _get_actual(self):
169+
def _get_actual(self) -> Tuple[Counter, List[OutputLine]]:
170170
messages = self._linter.reporter.messages
171171
messages.sort(key=lambda m: (m.line, m.symbol, m.msg))
172-
received_msgs = Counter()
172+
received_msgs: Counter = Counter()
173173
received_output_lines = []
174174
for msg in messages:
175175
assert (
@@ -179,7 +179,7 @@ def _get_actual(self):
179179
received_output_lines.append(OutputLine.from_msg(msg))
180180
return received_msgs, received_output_lines
181181

182-
def _runTest(self):
182+
def _runTest(self) -> None:
183183
__tracebackhide__ = True # pylint: disable=unused-variable
184184
modules_to_check = [self._test_file.source]
185185
self._linter.check(modules_to_check)
@@ -234,7 +234,12 @@ def error_msg_for_unequal_output(self, expected_lines, received_lines) -> str:
234234
error_msg += f"{line}\n"
235235
return error_msg
236236

237-
def _check_output_text(self, _, expected_output, actual_output):
237+
def _check_output_text(
238+
self,
239+
_: Counter,
240+
expected_output: List[OutputLine],
241+
actual_output: List[OutputLine],
242+
) -> None:
238243
"""This is a function because we want to be able to update the text in LintModuleOutputUpdate"""
239244
assert expected_output == actual_output, self.error_msg_for_unequal_output(
240245
expected_output, actual_output

pylint/testutils/output_line.py

Lines changed: 25 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -2,10 +2,11 @@
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 List, NamedTuple, Tuple, Union
66

77
from pylint import interfaces
88
from pylint.constants import PY38_PLUS
9+
from pylint.message.message import Message as pylint_Message
910
from pylint.testutils.constants import UPDATE_OPTION
1011

1112

@@ -15,16 +16,20 @@ class Message(
1516
def __new__(cls, msg_id, line=None, node=None, args=None, confidence=None):
1617
return tuple.__new__(cls, (msg_id, line, node, args, confidence))
1718

18-
def __eq__(self, other):
19+
def __eq__(self, other: Union[object, "Message"]) -> bool:
1920
if isinstance(other, Message):
2021
if self.confidence and other.confidence:
2122
return super().__eq__(other)
22-
return self[:-1] == other[:-1]
23+
return self[:-1] == other[:-1] # type: ignore
2324
return NotImplemented # pragma: no cover
2425

2526

2627
class MalformedOutputLineException(Exception):
27-
def __init__(self, row, exception):
28+
def __init__(
29+
self,
30+
row: Union[List[str], Tuple[str, str, str, str, str], str],
31+
exception: ValueError,
32+
) -> None:
2833
example = "msg-symbolic-name:42:27:MyClass.my_function:The message"
2934
other_example = "msg-symbolic-name:7:42::The message"
3035
expected = [
@@ -59,12 +64,12 @@ class OutputLine(NamedTuple):
5964
symbol: str
6065
lineno: int
6166
column: str
62-
object: Any
67+
object: str
6368
msg: str
64-
confidence: interfaces.Confidence
69+
confidence: Union[interfaces.Confidence, str]
6570

6671
@classmethod
67-
def from_msg(cls, msg):
72+
def from_msg(cls, msg: pylint_Message) -> "OutputLine":
6873
column = cls.get_column(msg.column)
6974
return cls(
7075
msg.symbol,
@@ -78,19 +83,26 @@ def from_msg(cls, msg):
7883
)
7984

8085
@classmethod
81-
def get_column(cls, column):
86+
def get_column(cls, column: Union[int, str]) -> str:
8287
if not PY38_PLUS:
8388
return "" # pragma: no cover
8489
return str(column)
8590

8691
@classmethod
87-
def from_csv(cls, row):
92+
def from_csv(
93+
cls, row: Union[List[str], Tuple[str, str, str, str, str], str]
94+
) -> "OutputLine":
8895
try:
89-
confidence = row[5] if len(row) == 6 else interfaces.HIGH.name
96+
if len(row) == 6:
97+
confidence = row[5] # type: ignore # mypy does not recognize that this cannot fail
98+
else:
99+
confidence = interfaces.HIGH.name
90100
column = cls.get_column(row[2])
91101
return cls(row[0], int(row[1]), column, row[3], row[4], confidence)
92102
except Exception as e:
93-
raise MalformedOutputLineException(row, e) from e
103+
if isinstance(e, ValueError):
104+
raise MalformedOutputLineException(row, e) from e
105+
raise
94106

95-
def to_csv(self):
96-
return tuple(self)
107+
def to_csv(self) -> "OutputLine":
108+
return self

pylint/testutils/reporter_for_tests.py

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -23,7 +23,7 @@ def __init__(
2323
): # pylint: disable=super-init-not-called # See https://github.com/PyCQA/pylint/issues/4941
2424
self.reset()
2525

26-
def reset(self):
26+
def reset(self) -> None:
2727
self.message_ids: Dict = {}
2828
self.out = StringIO()
2929
self.path_strip_prefix: str = getcwd() + sep
@@ -45,11 +45,12 @@ def handle_message(self, msg: Message) -> None:
4545
str_message = str_message.replace("\r\n", "\n")
4646
self.messages.append(f"{sigle}:{line:>3}{obj}: {str_message}")
4747

48-
def finalize(self):
48+
def finalize(self) -> str:
4949
self.messages.sort()
5050
for msg in self.messages:
5151
print(msg, file=self.out)
52-
result = self.out.getvalue()
52+
if isinstance(self.out, StringIO):
53+
result = self.out.getvalue()
5354
self.reset()
5455
return result
5556

0 commit comments

Comments
 (0)