diff options
-rw-r--r-- | pylint/checkers/spelling.py | 43 | ||||
-rw-r--r-- | pylint/testutils/decorator.py | 6 | ||||
-rw-r--r-- | tests/checkers/unittest_spelling.py | 68 |
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): |