Coverage for C:\Repos\ekr-pylint\pylint\message\message_definition.py: 24%
74 statements
« prev ^ index » next coverage.py v6.4, created at 2022-05-24 10:21 -0500
« prev ^ index » next coverage.py v6.4, created at 2022-05-24 10:21 -0500
1# Licensed under the GPL: https://www.gnu.org/licenses/old-licenses/gpl-2.0.html
2# For details: https://github.com/PyCQA/pylint/blob/main/LICENSE
3# Copyright (c) https://github.com/PyCQA/pylint/blob/main/CONTRIBUTORS.txt
5from __future__ import annotations
7import sys
8from typing import TYPE_CHECKING, Any
10from astroid import nodes
12from pylint.constants import _SCOPE_EXEMPT, MSG_TYPES, WarningScope
13from pylint.exceptions import InvalidMessageError
14from pylint.utils import normalize_text
16if TYPE_CHECKING:
17 from pylint.checkers import BaseChecker
20class MessageDefinition:
21 def __init__(
22 self,
23 checker: BaseChecker,
24 msgid: str,
25 msg: str,
26 description: str,
27 symbol: str,
28 scope: str,
29 minversion: tuple[int, int] | None = None,
30 maxversion: tuple[int, int] | None = None,
31 old_names: list[tuple[str, str]] | None = None,
32 ) -> None:
33 self.checker_name = checker.name
34 self.check_msgid(msgid)
35 self.msgid = msgid
36 self.symbol = symbol
37 self.msg = msg
38 self.description = description
39 self.scope = scope
40 self.minversion = minversion
41 self.maxversion = maxversion
42 self.old_names: list[tuple[str, str]] = []
43 if old_names:
44 for old_msgid, old_symbol in old_names:
45 self.check_msgid(old_msgid)
46 self.old_names.append(
47 (old_msgid, old_symbol),
48 )
50 @staticmethod
51 def check_msgid(msgid: str) -> None:
52 if len(msgid) != 5:
53 raise InvalidMessageError(f"Invalid message id {msgid!r}")
54 if msgid[0] not in MSG_TYPES:
55 raise InvalidMessageError(f"Bad message type {msgid[0]} in {msgid!r}")
57 def __eq__(self, other: Any) -> bool:
58 return (
59 isinstance(other, MessageDefinition)
60 and self.msgid == other.msgid
61 and self.symbol == other.symbol
62 )
64 def __repr__(self) -> str:
65 return f"MessageDefinition:{self.symbol} ({self.msgid})"
67 def __str__(self) -> str:
68 return f"{repr(self)}:\n{self.msg} {self.description}"
70 def may_be_emitted(self) -> bool:
71 """Return True if message may be emitted using the current interpreter."""
72 if self.minversion is not None and self.minversion > sys.version_info:
73 return False
74 if self.maxversion is not None and self.maxversion <= sys.version_info:
75 return False
76 return True
78 def format_help(self, checkerref: bool = False) -> str:
79 """Return the help string for the given message id."""
80 desc = self.description
81 if checkerref:
82 desc += f" This message belongs to the {self.checker_name} checker."
83 title = self.msg
84 if self.minversion or self.maxversion:
85 restr = []
86 if self.minversion:
87 restr.append(f"< {'.'.join(str(n) for n in self.minversion)}")
88 if self.maxversion:
89 restr.append(f">= {'.'.join(str(n) for n in self.maxversion)}")
90 restriction = " or ".join(restr)
91 if checkerref:
92 desc += f" It can't be emitted when using Python {restriction}."
93 else:
94 desc += (
95 f" This message can't be emitted when using Python {restriction}."
96 )
97 msg_help = normalize_text(" ".join(desc.split()), indent=" ")
98 message_id = f"{self.symbol} ({self.msgid})"
99 if title != "%s":
100 title = title.splitlines()[0]
101 return f":{message_id}: *{title.rstrip(' ')}*\n{msg_help}"
102 return f":{message_id}:\n{msg_help}"
104 def check_message_definition(
105 self, line: int | None, node: nodes.NodeNG | None
106 ) -> None:
107 """Check MessageDefinition for possible errors."""
108 if self.msgid[0] not in _SCOPE_EXEMPT:
109 # Fatal messages and reports are special, the node/scope distinction
110 # does not apply to them.
111 if self.scope == WarningScope.LINE:
112 if line is None:
113 raise InvalidMessageError(
114 f"Message {self.msgid} must provide line, got None"
115 )
116 if node is not None:
117 raise InvalidMessageError(
118 f"Message {self.msgid} must only provide line, "
119 f"got line={line}, node={node}"
120 )
121 elif self.scope == WarningScope.NODE:
122 # Node-based warnings may provide an override line.
123 if node is None:
124 raise InvalidMessageError(
125 f"Message {self.msgid} must provide Node, got None"
126 )