summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorEli Fine <ubuntu@ip-172-31-89-59.ec2.internal>2021-04-09 13:39:58 +0000
committerPierre Sassoulas <pierre.sassoulas@gmail.com>2021-04-10 08:36:29 +0200
commit525f24b2f9301a09f1a1c8ef8a5b18417dbe5226 (patch)
tree2aab9dfb3edbfa74637576dd3cbc6b48c75652d4
parentd0591ba2a097312c41d544e4269eda5b809c47a0 (diff)
downloadpylint-git-525f24b2f9301a09f1a1c8ef8a5b18417dbe5226.tar.gz
skipping spellcheck for tool directives in comments
-rw-r--r--pylint/checkers/spelling.py43
-rw-r--r--pylint/testutils/decorator.py6
-rw-r--r--tests/checkers/unittest_spelling.py68
3 files changed, 103 insertions, 14 deletions
diff --git a/pylint/checkers/spelling.py b/pylint/checkers/spelling.py
index 95b46cda2..dca7da3b5 100644
--- a/pylint/checkers/spelling.py
+++ b/pylint/checkers/spelling.py
@@ -17,6 +17,7 @@
# Copyright (c) 2020 Ganden Schaffner <gschaffner@pm.me>
# Copyright (c) 2020 hippo91 <guillaume.peillex@gmail.com>
# Copyright (c) 2020 Damien Baty <damien.baty@polyconseil.fr>
+# Copyright (c) 2021 Eli Fine <ejfine@gmail.com>
# Licensed under the GPL: https://www.gnu.org/licenses/old-licenses/gpl-2.0.html
# For details: https://github.com/PyCQA/pylint/blob/master/COPYING
@@ -26,6 +27,7 @@
import os
import re
import tokenize
+from typing import Pattern
from pylint.checkers import BaseTokenChecker
from pylint.checkers.utils import check_messages
@@ -79,7 +81,7 @@ else:
instr = " To make it work, install the 'python-enchant' package."
-class WordsWithDigigtsFilter(Filter):
+class WordsWithDigitsFilter(Filter):
"""Skips words with digits."""
def _skip(self, word):
@@ -99,7 +101,18 @@ class WordsWithUnderscores(Filter):
return "_" in word
-class CamelCasedWord(Filter):
+class RegExFilter(Filter):
+ r"""Parent class for filters using regular expressions.
+ This filter skips any words the match the expression assigned to the class attribute `_pattern`
+
+ """
+ _pattern: Pattern[str]
+
+ def _skip(self, word) -> bool:
+ return bool(self._pattern.match(word))
+
+
+class CamelCasedWord(RegExFilter):
r"""Filter skipping over camelCasedWords.
This filter skips any words matching the following regular expression:
@@ -109,11 +122,8 @@ class CamelCasedWord(Filter):
"""
_pattern = re.compile(r"^([a-z]+([\d]|[A-Z])(?:\w+)?)")
- def _skip(self, word):
- return bool(self._pattern.match(word))
-
-class SphinxDirectives(Filter):
+class SphinxDirectives(RegExFilter):
r"""Filter skipping over Sphinx Directives.
This filter skips any words matching the following regular expression:
@@ -124,11 +134,8 @@ class SphinxDirectives(Filter):
# The final ` in the pattern is optional because enchant strips it out
_pattern = re.compile(r"^(:([a-z]+)){1,2}:`([^`]+)(`)?")
- def _skip(self, word):
- return bool(self._pattern.match(word))
-
-class ForwardSlashChunkder(Chunker):
+class ForwardSlashChunker(Chunker):
"""
This chunker allows splitting words like 'before/after' into 'before' and 'after'
"""
@@ -283,15 +290,16 @@ class SpellingChecker(BaseTokenChecker):
self.tokenizer = get_tokenizer(
dict_name,
- chunkers=[ForwardSlashChunkder],
+ chunkers=[ForwardSlashChunker],
filters=[
EmailFilter,
URLFilter,
WikiWordFilter,
- WordsWithDigigtsFilter,
+ WordsWithDigitsFilter,
WordsWithUnderscores,
CamelCasedWord,
SphinxDirectives,
+ # BlackDirectives
],
)
self.initialized = True
@@ -308,6 +316,17 @@ class SpellingChecker(BaseTokenChecker):
initial_space = 0
if line.strip().startswith("#") and "docstring" not in msgid:
line = line.strip()[1:]
+ for iter_directive in (
+ "fmt: on",
+ "fmt: off",
+ "noqa:",
+ "noqa",
+ "nosec",
+ "isort:skip",
+ ):
+ if line.startswith(" " + iter_directive):
+ line = line[(len(iter_directive) + 1) :]
+ break
starts_with_comment = True
else:
starts_with_comment = False
diff --git a/pylint/testutils/decorator.py b/pylint/testutils/decorator.py
index 3b70867cb..3fb5f190a 100644
--- a/pylint/testutils/decorator.py
+++ b/pylint/testutils/decorator.py
@@ -11,13 +11,15 @@ def set_config(**kwargs):
def _wrapper(fun):
@functools.wraps(fun)
- def _forward(self):
+ def _forward(self, *args, **test_function_kwargs):
for key, value in kwargs.items():
setattr(self.checker.config, key, value)
if isinstance(self, CheckerTestCase):
# reopen checker in case, it may be interested in configuration change
self.checker.open()
- fun(self)
+ fun(
+ self, *args, **test_function_kwargs
+ ) # Passing the args and kwargs back to the test function itself allows this decorator to be used on parametrized test cases
return _forward
diff --git a/tests/checkers/unittest_spelling.py b/tests/checkers/unittest_spelling.py
index c14062d2d..dec6b19ee 100644
--- a/tests/checkers/unittest_spelling.py
+++ b/tests/checkers/unittest_spelling.py
@@ -303,6 +303,74 @@ class TestSpellingChecker(CheckerTestCase):
):
self.checker.visit_classdef(stmt)
+ # @skip_on_missing_package_or_dict
+ # # @set_config(spelling_dict=spell_dict)
+ # @pytest.mark.parametrize(
+ # "num_files,num_jobs,num_checkers",
+ # [
+ # (1, 2, 1),
+ # (1, 2, 2),
+ # (1, 2, 3),
+ # (2, 2, 1),
+ # (2, 2, 2),
+ # (2, 2, 3),
+ # (3, 2, 1),
+ # (3, 2, 2),
+ # (3, 2, 3),
+ # (3, 1, 1),
+ # (3, 1, 2),
+ # (3, 1, 3),
+ # (3, 5, 1),
+ # (3, 5, 2),
+ # (3, 5, 3),
+ # (10, 2, 1),
+ # (10, 2, 2),
+ # (10, 2, 3),
+ # (2, 10, 1),
+ # (2, 10, 2),
+ # (2, 10, 3),
+ # ],
+ # )
+ # def test_compare_workers_to_single_proc(self, num_files, num_jobs, num_checkers):
+ # assert True
+
+ @skip_on_missing_package_or_dict
+ @set_config(spelling_dict=spell_dict)
+ @pytest.mark.parametrize(
+ ",".join(
+ (
+ "misspelled_portion_of_directive",
+ "second_portion_of_directive",
+ "description",
+ )
+ ),
+ (
+ ("fmt", ": on", "black directive to turn on formatting"),
+ ("fmt", ": off", "black directive to turn off formatting"),
+ ("noqa", "", "pycharm directive"),
+ ("noqa", ":", "flake8 / zimports directive"),
+ ("nosec", "", "bandit directive"),
+ ("isort", ":skip", "isort directive"),
+ ),
+ )
+ def test_skip_tool_directives_at_beginning_of_comments_but_still_raise_error_if_directive_appears_later_in_comment( # pylint:disable=unused-argument # Having the extra description parameter allows the description to show up in the pytest output as part of the test name when running parametrized tests
+ self, misspelled_portion_of_directive, second_portion_of_directive, description
+ ):
+ full_comment = f"# {misspelled_portion_of_directive}{second_portion_of_directive} {misspelled_portion_of_directive}"
+ with self.assertAddsMessages(
+ Message(
+ "wrong-spelling-in-comment",
+ line=1,
+ args=(
+ misspelled_portion_of_directive,
+ full_comment,
+ f" {'^'*len(misspelled_portion_of_directive)}",
+ self._get_msg_suggestions(misspelled_portion_of_directive),
+ ),
+ )
+ ):
+ self.checker.process_tokens(_tokenize_str(full_comment))
+
@skip_on_missing_package_or_dict
@set_config(spelling_dict=spell_dict)
def test_handle_words_joined_by_forward_slash(self):