Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Support # noqa: ... pragmas #3221

Closed
wants to merge 1 commit into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 5 additions & 0 deletions ChangeLog
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,11 @@ Release date: TBA

* Allow parallel linting when run under Prospector

* ``# noqa: ...` pragmas are now supported as an alternative to
``# pylint: disable=...``.

Closes #2493


What's New in Pylint 2.4.3?
===========================
Expand Down
14 changes: 14 additions & 0 deletions doc/user_guide/message-control.rst
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
.. _messages-control:

Messages control
================

Expand Down Expand Up @@ -25,6 +27,18 @@ For all of these controls, ``pylint`` accepts the following values:

* All the checks with ``all``

.. note::

``pylint`` also supports using the ``# noqa: ...`` pragma
as an alternative to ``# pylint: disable=...``.
Note that other linters may not be able to parse pragmas that use
symbolic messages.
Therefore is it recommended to use numerical IDs inside ``# noqa`` pragmas
when using ``pylint`` with another linter.
Disabling ``use-symbolic-message-instead`` may be needed in this case.

Bare ``# noqa`` pragmas without a list of messages to disable is not supported.


Block disables
--------------
Expand Down
6 changes: 6 additions & 0 deletions doc/whatsnew/2.5.rst
Original file line number Diff line number Diff line change
Expand Up @@ -32,3 +32,9 @@ Other Changes
These files can also be passed in on the command line.

* Mutable ``collections.*`` are now flagged as dangerous defaults.

* ``# noqa: ...` pragmas are now supported as an alternative to
``# pylint: disable=...``.
See :ref:`messages-control` for detailed usage.

Closes #2493
1 change: 1 addition & 0 deletions pylint/constants.py
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@
# so that an option can be continued with the reasons
# why it is active or disabled.
OPTION_RGX = re.compile(r"\s*#.*\bpylint:\s*([^;#]+)[;#]{0,1}")
NOQA_RGX = re.compile(r"# noqa:[\s]?([^;#]+)[;#]{0,1}", re.IGNORECASE)

PY_EXTS = (".py", ".pyc", ".pyo", ".pyw", ".so", ".dll")

Expand Down
37 changes: 30 additions & 7 deletions pylint/lint.py
Original file line number Diff line number Diff line change
Expand Up @@ -68,6 +68,7 @@
import traceback
import warnings
from io import TextIOWrapper
from typing import List

import astroid
from astroid import modutils
Expand All @@ -76,7 +77,7 @@

from pylint import __pkginfo__, checkers, config, exceptions, interfaces, reporters
from pylint.__pkginfo__ import version
from pylint.constants import MAIN_CHECKER_NAME, MSG_TYPES, OPTION_RGX
from pylint.constants import MAIN_CHECKER_NAME, MSG_TYPES, NOQA_RGX, OPTION_RGX
from pylint.message import Message, MessageDefinitionStore, MessagesHandlerMixIn
from pylint.reporters.ureports import nodes as report_nodes
from pylint.utils import ASTWalker, FileState, utils
Expand Down Expand Up @@ -806,6 +807,14 @@ def process_tokens(self, tokens):

if tok_type != tokenize.COMMENT:
continue

# If we did not see a newline between the previous line and now,
# we saw a backslash so treat the two lines as one.
line_nos = [start[0]]
if not saw_newline:
line_nos.append(start[0] - 1)
self._process_noqa(content, line_nos)

match = OPTION_RGX.search(content)
if match is None:
continue
Expand Down Expand Up @@ -846,7 +855,7 @@ def process_tokens(self, tokens):
for msgid in utils._splitstrip(value):
# Add the line where a control pragma was encountered.
if opt in control_pragmas:
self._pragma_lineno[msgid] = start[0]
self._pragma_lineno[msgid] = line_nos[-1]

try:
if (opt, msgid) == ("disable", "all"):
Expand All @@ -858,16 +867,30 @@ def process_tokens(self, tokens):
self.add_message("file-ignored", line=start[0])
self._ignore_file = True
return
# If we did not see a newline between the previous line and now,
# we saw a backslash so treat the two lines as one.
if not saw_newline:
meth(msgid, "module", start[0] - 1)
meth(msgid, "module", start[0])

for line_no in line_nos:
meth(msgid, "module", line_no)
except exceptions.UnknownMessageError:
self.add_message("bad-option-value", args=msgid, line=start[0])
else:
self.add_message("unrecognized-inline-option", args=opt, line=start[0])

def _process_noqa(self, content: str, line_nos: List[int]) -> None:
"""Find and process any supported noqa pragmas.

:param content: The comment to parse (including the leading "#").
:param line_nos: The line numbers of the lines that the pragma affects.
"""
match = NOQA_RGX.search(content)
if not match:
return

for msgid in utils._splitstrip(match.group(1)):
for line_no in line_nos:
self._pragma_lineno[msgid] = line_no
# Ignore unknown messages because this message may not be ours
self.disable(msgid, "module", line_no, ignore_unknown=True)

# code checking methods ###################################################

def get_checkers(self):
Expand Down
13 changes: 13 additions & 0 deletions tests/functional/n/noqa_pragma.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
"""Test that a noqa pragma has an effect."""
# pylint: disable=too-few-public-methods

class Foo:
"""block-disable test"""

def meth3(self):
"""test one line disabling"""
print(self.bla) # noqa: E1101

print(self.bla) # noqa: no-member

self.thing = self.bla # noqa: E1101, attribute-defined-outside-init
6 changes: 6 additions & 0 deletions tests/functional/p/pragma_after_backslash.py
Original file line number Diff line number Diff line change
Expand Up @@ -8,3 +8,9 @@ def meth3(self):
"""test one line disabling"""
print(self.bla) \
# pylint: disable=E1101

print(self.bla \
+ self.bla) # pylint: disable=E1101

print(self.bla) \
# noqa: E1101