Coverage for C:\Repos\ekr-pylint\pylint\constants.py: 82%
61 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 os
8import pathlib
9import platform
10import sys
11from datetime import datetime
12from typing import NamedTuple
14import astroid
15import platformdirs
17from pylint.__pkginfo__ import __version__
18from pylint.typing import MessageTypesFullName
20PY38_PLUS = sys.version_info[:2] >= (3, 8)
21PY39_PLUS = sys.version_info[:2] >= (3, 9)
23IS_PYPY = platform.python_implementation() == "PyPy"
25PY_EXTS = (".py", ".pyc", ".pyo", ".pyw", ".so", ".dll")
27MSG_STATE_CONFIDENCE = 2
28_MSG_ORDER = "EWRCIF"
29MSG_STATE_SCOPE_CONFIG = 0
30MSG_STATE_SCOPE_MODULE = 1
32# The line/node distinction does not apply to fatal errors and reports.
33_SCOPE_EXEMPT = "FR"
35MSG_TYPES: dict[str, MessageTypesFullName] = {
36 "I": "info",
37 "C": "convention",
38 "R": "refactor",
39 "W": "warning",
40 "E": "error",
41 "F": "fatal",
42}
43MSG_TYPES_LONG: dict[str, str] = {v: k for k, v in MSG_TYPES.items()}
45MSG_TYPES_STATUS = {"I": 0, "C": 16, "R": 8, "W": 4, "E": 2, "F": 1}
47# You probably don't want to change the MAIN_CHECKER_NAME
48# This would affect rcfile generation and retro-compatibility
49# on all project using [MAIN] in their rcfile.
50MAIN_CHECKER_NAME = "main"
52USER_HOME = os.path.expanduser("~")
53# TODO: 3.0: Remove in 3.0 with all the surrounding code
54OLD_DEFAULT_PYLINT_HOME = ".pylint.d"
55DEFAULT_PYLINT_HOME = platformdirs.user_cache_dir("pylint")
58class WarningScope:
59 LINE = "line-based-msg"
60 NODE = "node-based-msg"
63full_version = f"""pylint {__version__}
64astroid {astroid.__version__}
65Python {sys.version}"""
67HUMAN_READABLE_TYPES = {
68 "file": "file",
69 "module": "module",
70 "const": "constant",
71 "class": "class",
72 "function": "function",
73 "method": "method",
74 "attr": "attribute",
75 "argument": "argument",
76 "variable": "variable",
77 "class_attribute": "class attribute",
78 "class_const": "class constant",
79 "inlinevar": "inline iteration",
80 "typevar": "type variable",
81}
84class DeletedMessage(NamedTuple):
85 msgid: str
86 symbol: str
87 old_names: list[tuple[str, str]] = []
90DELETED_MSGID_PREFIXES: list[int] = []
92DELETED_MESSAGES = [
93 # Everything until the next comment is from the
94 # PY3K+ checker, see https://github.com/PyCQA/pylint/pull/4942
95 DeletedMessage("W1601", "apply-builtin"),
96 DeletedMessage("E1601", "print-statement"),
97 DeletedMessage("E1602", "parameter-unpacking"),
98 DeletedMessage(
99 "E1603", "unpacking-in-except", [("W0712", "old-unpacking-in-except")]
100 ),
101 DeletedMessage("E1604", "old-raise-syntax", [("W0121", "old-old-raise-syntax")]),
102 DeletedMessage("E1605", "backtick", [("W0333", "old-backtick")]),
103 DeletedMessage("E1609", "import-star-module-level"),
104 DeletedMessage("W1601", "apply-builtin"),
105 DeletedMessage("W1602", "basestring-builtin"),
106 DeletedMessage("W1603", "buffer-builtin"),
107 DeletedMessage("W1604", "cmp-builtin"),
108 DeletedMessage("W1605", "coerce-builtin"),
109 DeletedMessage("W1606", "execfile-builtin"),
110 DeletedMessage("W1607", "file-builtin"),
111 DeletedMessage("W1608", "long-builtin"),
112 DeletedMessage("W1609", "raw_input-builtin"),
113 DeletedMessage("W1610", "reduce-builtin"),
114 DeletedMessage("W1611", "standarderror-builtin"),
115 DeletedMessage("W1612", "unicode-builtin"),
116 DeletedMessage("W1613", "xrange-builtin"),
117 DeletedMessage("W1614", "coerce-method"),
118 DeletedMessage("W1615", "delslice-method"),
119 DeletedMessage("W1616", "getslice-method"),
120 DeletedMessage("W1617", "setslice-method"),
121 DeletedMessage("W1618", "no-absolute-import"),
122 DeletedMessage("W1619", "old-division"),
123 DeletedMessage("W1620", "dict-iter-method"),
124 DeletedMessage("W1621", "dict-view-method"),
125 DeletedMessage("W1622", "next-method-called"),
126 DeletedMessage("W1623", "metaclass-assignment"),
127 DeletedMessage(
128 "W1624", "indexing-exception", [("W0713", "old-indexing-exception")]
129 ),
130 DeletedMessage("W1625", "raising-string", [("W0701", "old-raising-string")]),
131 DeletedMessage("W1626", "reload-builtin"),
132 DeletedMessage("W1627", "oct-method"),
133 DeletedMessage("W1628", "hex-method"),
134 DeletedMessage("W1629", "nonzero-method"),
135 DeletedMessage("W1630", "cmp-method"),
136 DeletedMessage("W1632", "input-builtin"),
137 DeletedMessage("W1633", "round-builtin"),
138 DeletedMessage("W1634", "intern-builtin"),
139 DeletedMessage("W1635", "unichr-builtin"),
140 DeletedMessage(
141 "W1636", "map-builtin-not-iterating", [("W1631", "implicit-map-evaluation")]
142 ),
143 DeletedMessage("W1637", "zip-builtin-not-iterating"),
144 DeletedMessage("W1638", "range-builtin-not-iterating"),
145 DeletedMessage("W1639", "filter-builtin-not-iterating"),
146 DeletedMessage("W1640", "using-cmp-argument"),
147 DeletedMessage("W1642", "div-method"),
148 DeletedMessage("W1643", "idiv-method"),
149 DeletedMessage("W1644", "rdiv-method"),
150 DeletedMessage("W1645", "exception-message-attribute"),
151 DeletedMessage("W1646", "invalid-str-codec"),
152 DeletedMessage("W1647", "sys-max-int"),
153 DeletedMessage("W1648", "bad-python3-import"),
154 DeletedMessage("W1649", "deprecated-string-function"),
155 DeletedMessage("W1650", "deprecated-str-translate-call"),
156 DeletedMessage("W1651", "deprecated-itertools-function"),
157 DeletedMessage("W1652", "deprecated-types-field"),
158 DeletedMessage("W1653", "next-method-defined"),
159 DeletedMessage("W1654", "dict-items-not-iterating"),
160 DeletedMessage("W1655", "dict-keys-not-iterating"),
161 DeletedMessage("W1656", "dict-values-not-iterating"),
162 DeletedMessage("W1657", "deprecated-operator-function"),
163 DeletedMessage("W1658", "deprecated-urllib-function"),
164 DeletedMessage("W1659", "xreadlines-attribute"),
165 DeletedMessage("W1660", "deprecated-sys-function"),
166 DeletedMessage("W1661", "exception-escape"),
167 DeletedMessage("W1662", "comprehension-escape"),
168 # https://github.com/PyCQA/pylint/pull/3578
169 DeletedMessage("W0312", "mixed-indentation"),
170 # https://github.com/PyCQA/pylint/pull/3577
171 DeletedMessage(
172 "C0326",
173 "bad-whitespace",
174 [
175 ("C0323", "no-space-after-operator"),
176 ("C0324", "no-space-after-comma"),
177 ("C0322", "no-space-before-operator"),
178 ],
179 ),
180 # https://github.com/PyCQA/pylint/pull/3571
181 DeletedMessage("C0330", "bad-continuation"),
182 # No PR
183 DeletedMessage("R0921", "abstract-class-not-used"),
184 # https://github.com/PyCQA/pylint/pull/3577
185 DeletedMessage("C0326", "bad-whitespace"),
186 # Pylint 1.4.3
187 DeletedMessage("W0142", "star-args"),
188 # https://github.com/PyCQA/pylint/issues/2409
189 DeletedMessage("W0232", "no-init"),
190 # https://github.com/PyCQA/pylint/pull/6421
191 DeletedMessage("W0111", "assign-to-new-keyword"),
192]
195# ignore some messages when emitting useless-suppression:
196# - cyclic-import: can show false positives due to incomplete context
197# - deprecated-{module, argument, class, method, decorator}:
198# can cause false positives for multi-interpreter projects
199# when linting with an interpreter on a lower python version
200INCOMPATIBLE_WITH_USELESS_SUPPRESSION = frozenset(
201 [
202 "R0401", # cyclic-import
203 "W0402", # deprecated-module
204 "W1505", # deprecated-method
205 "W1511", # deprecated-argument
206 "W1512", # deprecated-class
207 "W1513", # deprecated-decorator
208 "R0801", # duplicate-code
209 ]
210)
213TYPING_TYPE_CHECKS_GUARDS = frozenset({"typing.TYPE_CHECKING", "TYPE_CHECKING"})
216def _warn_about_old_home(pylint_home: pathlib.Path) -> None:
217 """Warn users about the old pylint home being deprecated.
219 The spam prevention mechanism is due to pylint being used in parallel by
220 pre-commit, and the message being spammy in this context
221 Also if you work with an old version of pylint that recreates the
222 old pylint home, you can get the old message for a long time.
223 """
224 prefix_spam_prevention = "pylint_warned_about_old_cache_already"
225 spam_prevention_file = pathlib.Path(pylint_home) / datetime.now().strftime(
226 prefix_spam_prevention + "_%Y-%m-%d.temp"
227 )
228 old_home = pathlib.Path(USER_HOME) / OLD_DEFAULT_PYLINT_HOME
230 if old_home.exists() and not spam_prevention_file.exists():
231 print(
232 f"PYLINTHOME is now '{pylint_home}' but obsolescent '{old_home}' is found; "
233 "you can safely remove the latter",
234 file=sys.stderr,
235 )
237 # Remove old spam prevention file
238 if pylint_home.exists():
239 for filename in pylint_home.iterdir():
240 if prefix_spam_prevention in str(filename):
241 try:
242 os.remove(pylint_home / filename)
243 except OSError: # pragma: no cover
244 pass
246 # Create spam prevention file for today
247 try:
248 pylint_home.mkdir(parents=True, exist_ok=True)
249 with open(spam_prevention_file, "w", encoding="utf8") as f:
250 f.write("")
251 except Exception as exc: # pragma: no cover # pylint: disable=broad-except
252 print(
253 "Can't write the file that was supposed to "
254 f"prevent 'pylint.d' deprecation spam in {pylint_home} because of {exc}."
255 )
258def _get_pylint_home() -> str:
259 """Return the pylint home."""
260 if "PYLINTHOME" in os.environ:
261 return os.environ["PYLINTHOME"]
263 _warn_about_old_home(pathlib.Path(DEFAULT_PYLINT_HOME))
265 return DEFAULT_PYLINT_HOME
268PYLINT_HOME = _get_pylint_home()