summaryrefslogtreecommitdiff
path: root/pylint
diff options
context:
space:
mode:
authorDaniƫl van Noord <13665637+DanielNoord@users.noreply.github.com>2022-04-18 17:36:07 +0200
committerGitHub <noreply@github.com>2022-04-18 17:36:07 +0200
commite5dfec0127e342eac8bdb46b1ecd8483b39c6049 (patch)
treea06e91a10482a0b1842dba5bd2180e986ee0dae9 /pylint
parentaf4bcf86a24465690197f487f062596f3bf25eba (diff)
downloadpylint-git-e5dfec0127e342eac8bdb46b1ecd8483b39c6049.tar.gz
Make ``Message`` a ``dataclass`` (#6381)
Diffstat (limited to 'pylint')
-rw-r--r--pylint/lint/parallel.py28
-rw-r--r--pylint/message/message.py108
-rw-r--r--pylint/reporters/text.py18
-rw-r--r--pylint/testutils/output_line.py2
4 files changed, 68 insertions, 88 deletions
diff --git a/pylint/lint/parallel.py b/pylint/lint/parallel.py
index 7f160e328..98a2af5be 100644
--- a/pylint/lint/parallel.py
+++ b/pylint/lint/parallel.py
@@ -16,7 +16,7 @@ import dill
from pylint import reporters
from pylint.lint.utils import _patch_sys_path
from pylint.message import Message
-from pylint.typing import FileItem, MessageLocationTuple
+from pylint.typing import FileItem
from pylint.utils import LinterStats, merge_stats
try:
@@ -32,18 +32,6 @@ if TYPE_CHECKING:
_worker_linter = None
-def _get_new_args(message):
- location = (
- message.abspath,
- message.path,
- message.module,
- message.obj,
- message.line,
- message.column,
- )
- return (message.msg_id, message.symbol, location, message.msg, message.confidence)
-
-
def _worker_initialize(
linter: bytes, arguments: None | str | Sequence[str] = None
) -> None:
@@ -67,7 +55,14 @@ def _worker_initialize(
def _worker_check_single_file(
file_item: FileItem,
) -> tuple[
- int, Any, str, Any, list[tuple[Any, ...]], LinterStats, Any, defaultdict[Any, list]
+ int,
+ Any,
+ str,
+ Any,
+ list[Message],
+ LinterStats,
+ Any,
+ defaultdict[Any, list],
]:
if not _worker_linter:
raise Exception("Worker linter not yet initialised")
@@ -80,7 +75,7 @@ def _worker_check_single_file(
except AttributeError:
continue
mapreduce_data[checker.name].append(data)
- msgs = [_get_new_args(m) for m in _worker_linter.reporter.messages]
+ msgs = _worker_linter.reporter.messages
_worker_linter.reporter.reset()
if _worker_linter.current_name is None:
warnings.warn(
@@ -162,9 +157,6 @@ def check_parallel(
linter.file_state.base_name = base_name
linter.set_current_module(module, file_path)
for msg in messages:
- msg = Message(
- msg[0], msg[1], MessageLocationTuple(*msg[2]), msg[3], msg[4]
- )
linter.reporter.handle_message(msg)
all_stats.append(stats)
all_mapreduce_data[worker_idx].append(mapreduce_data)
diff --git a/pylint/message/message.py b/pylint/message/message.py
index 67f787572..4efa3f124 100644
--- a/pylint/message/message.py
+++ b/pylint/message/message.py
@@ -4,85 +4,71 @@
from __future__ import annotations
-import collections
-from typing import overload
+from dataclasses import asdict, dataclass
from warnings import warn
from pylint.constants import MSG_TYPES
-from pylint.interfaces import Confidence
+from pylint.interfaces import UNDEFINED, Confidence
from pylint.typing import MessageLocationTuple
-_MsgBase = collections.namedtuple(
- "_MsgBase",
- [
- "msg_id",
- "symbol",
- "msg",
- "C",
- "category",
- "confidence",
- "abspath",
- "path",
- "module",
- "obj",
- "line",
- "column",
- "end_line",
- "end_column",
- ],
-)
-
-class Message(_MsgBase):
+@dataclass(unsafe_hash=True)
+class Message: # pylint: disable=too-many-instance-attributes
"""This class represent a message to be issued by the reporters."""
- @overload
- def __new__(
- cls,
- msg_id: str,
- symbol: str,
- location: MessageLocationTuple,
- msg: str,
- confidence: Confidence | None,
- ) -> Message:
- ...
-
- @overload
- def __new__(
- cls,
- msg_id: str,
- symbol: str,
- location: tuple[str, str, str, str, int, int],
- msg: str,
- confidence: Confidence | None,
- ) -> Message:
- # Remove for pylint 3.0
- ...
+ msg_id: str
+ symbol: str
+ msg: str
+ C: str
+ category: str
+ confidence: Confidence
+ abspath: str
+ path: str
+ module: str
+ obj: str
+ line: int
+ column: int
+ end_line: int | None
+ end_column: int | None
- def __new__(
- cls,
+ def __init__(
+ self,
msg_id: str,
symbol: str,
location: tuple[str, str, str, str, int, int] | MessageLocationTuple,
msg: str,
confidence: Confidence | None,
- ) -> Message:
+ ) -> None:
if not isinstance(location, MessageLocationTuple):
warn(
"In pylint 3.0, Messages will only accept a MessageLocationTuple as location parameter",
DeprecationWarning,
)
- location = location + (None, None) # type: ignore[assignment] # Temporary fix until deprecation
- return _MsgBase.__new__(
- cls,
- msg_id,
- symbol,
- msg,
- msg_id[0],
- MSG_TYPES[msg_id[0]],
- confidence,
- *location,
- )
+ location = MessageLocationTuple(
+ location[0],
+ location[1],
+ location[2],
+ location[3],
+ location[4],
+ location[5],
+ None,
+ None,
+ )
+
+ self.msg_id = msg_id
+ self.symbol = symbol
+ self.msg = msg
+ self.C = msg_id[0]
+ self.category = MSG_TYPES[msg_id[0]]
+ self.confidence = confidence or UNDEFINED
+ self.abspath = location.abspath
+ self.path = location.path
+ self.module = location.module
+ self.obj = location.obj
+ self.line = location.line
+ self.column = location.column
+ self.end_line = location.end_line
+ self.end_column = location.end_column
def format(self, template: str) -> str:
"""Format the message according to the given template.
@@ -90,4 +76,4 @@ class Message(_MsgBase):
The template format is the one of the format method :
cf. https://docs.python.org/2/library/string.html#formatstrings
"""
- return template.format(**self._asdict())
+ return template.format(**asdict(self))
diff --git a/pylint/reporters/text.py b/pylint/reporters/text.py
index 347f4d6d2..009582fa0 100644
--- a/pylint/reporters/text.py
+++ b/pylint/reporters/text.py
@@ -14,6 +14,7 @@ import os
import re
import sys
import warnings
+from dataclasses import asdict, fields
from typing import TYPE_CHECKING, Dict, NamedTuple, Optional, TextIO, cast, overload
from pylint.interfaces import IReporter
@@ -66,6 +67,9 @@ ANSI_COLORS = {
"white": "37",
}
+MESSAGE_FIELDS = {i.name for i in fields(Message)}
+"""All fields of the Message class."""
+
def _get_ansi_code(msg_style: MessageStyle) -> str:
"""Return ansi escape code corresponding to color and style.
@@ -176,7 +180,7 @@ class TextReporter(BaseReporter):
# 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:
+ 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?"
@@ -186,7 +190,7 @@ class TextReporter(BaseReporter):
def write_message(self, msg: Message) -> None:
"""Convenience method to write a formatted message with class default template."""
- self_dict = msg._asdict()
+ self_dict = asdict(msg)
for key in ("end_line", "end_column"):
self_dict[key] = self_dict[key] or ""
@@ -316,12 +320,10 @@ class ColorizedTextReporter(TextReporter):
self._modules.add(msg.module)
msg_style = self._get_decoration(msg.C)
- msg = msg._replace(
- **{
- attr: colorize_ansi(getattr(msg, attr), msg_style)
- for attr in ("msg", "symbol", "category", "C")
- }
- )
+ msg.msg = colorize_ansi(msg.msg, msg_style)
+ msg.symbol = colorize_ansi(msg.symbol, msg_style)
+ msg.category = colorize_ansi(msg.category, msg_style)
+ msg.C = colorize_ansi(msg.C, msg_style)
self.write_message(msg)
diff --git a/pylint/testutils/output_line.py b/pylint/testutils/output_line.py
index 4cde92d4f..14d172725 100644
--- a/pylint/testutils/output_line.py
+++ b/pylint/testutils/output_line.py
@@ -99,7 +99,7 @@ class OutputLine(NamedTuple):
)
@staticmethod
- def _get_column(column: str) -> int:
+ def _get_column(column: str | int) -> int:
"""Handle column numbers except for python < 3.8.
The ast parser in those versions doesn't return them.