Skip to content

Commit 04215ad

Browse files
Eli FinePierre-Sassoulas
Eli Fine
authored andcommitted
skipping spellcheck for code flanked in backticks
1 parent 525f24b commit 04215ad

File tree

3 files changed

+72
-34
lines changed

3 files changed

+72
-34
lines changed

ChangeLog

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -67,6 +67,14 @@ Release date: Undefined
6767

6868
* Don't show ``DuplicateBasesError`` for attribute access
6969

70+
* Allow code flanked in backticks to be skipped by spellchecker
71+
72+
Closes #4319
73+
74+
* Allow Python tool directives (for black, flake8, zimports, isort, mypy, bandit, pycharm) at beginning of comments to be skipped by spellchecker
75+
76+
Closes #4320
77+
7078

7179
What's New in Pylint 2.7.4?
7280
===========================
@@ -302,7 +310,7 @@ Release date: 2021-02-21
302310

303311
Close #2738
304312

305-
* Fix ``duplicate-code`` false positive when lines only contain whitespace and non-alphanumeric characters (e.g. parentheses, bracket, comman, etc.)
313+
* Fix ``duplicate-code`` false positive when lines only contain whitespace and non-alphanumeric characters (e.g. parentheses, bracket, comma, etc.)
306314

307315
* Improve lint message for ``singleton-comparison`` with bools
308316

pylint/checkers/spelling.py

Lines changed: 23 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -103,7 +103,7 @@ def _skip(self, word):
103103

104104
class RegExFilter(Filter):
105105
r"""Parent class for filters using regular expressions.
106-
This filter skips any words the match the expression assigned to the class attribute `_pattern`
106+
This filter skips any words the match the expression assigned to the class attribute ``_pattern``
107107
108108
"""
109109
_pattern: Pattern[str]
@@ -176,6 +176,24 @@ def _next(self):
176176
raise StopIteration()
177177

178178

179+
CODE_FLANKED_IN_BACKTICK_REGEX = re.compile(r"(\s|^)(`{1,2})([^`]+)(\2)([^`]|$)")
180+
181+
182+
def _strip_code_flanked_in_backticks(line: str) -> str:
183+
"""Alter line so code flanked in backticks is ignored.
184+
185+
Pyenchant automatically strips backticks when parsing tokens, so this cannot be done at the individual filter level.
186+
187+
"""
188+
189+
def replace_code_but_leave_surrounding_characters(match_obj) -> str:
190+
return match_obj.group(1) + match_obj.group(5)
191+
192+
return CODE_FLANKED_IN_BACKTICK_REGEX.sub(
193+
replace_code_but_leave_surrounding_characters, line
194+
)
195+
196+
179197
class SpellingChecker(BaseTokenChecker):
180198
"""Check spelling in comments and docstrings"""
181199

@@ -323,13 +341,17 @@ def _check_spelling(self, msgid, line, line_num):
323341
"noqa",
324342
"nosec",
325343
"isort:skip",
344+
"mypy:",
326345
):
327346
if line.startswith(" " + iter_directive):
328347
line = line[(len(iter_directive) + 1) :]
329348
break
330349
starts_with_comment = True
331350
else:
332351
starts_with_comment = False
352+
353+
line = _strip_code_flanked_in_backticks(line)
354+
333355
for word, word_start_at in self.tokenizer(line.strip()):
334356
word_start_at += initial_space
335357
lower_cased_word = word.casefold()

tests/checkers/unittest_spelling.py

Lines changed: 40 additions & 32 deletions
Original file line numberDiff line numberDiff line change
@@ -37,7 +37,9 @@
3737
pass
3838

3939

40-
class TestSpellingChecker(CheckerTestCase):
40+
class TestSpellingChecker(
41+
CheckerTestCase
42+
): # pylint:disable=too-many-public-methods # This is a test case class, not sure why it would be relevant to have this pylint rule enforced for test case classes
4143
CHECKER_CLASS = spelling.SpellingChecker
4244

4345
skip_on_missing_package_or_dict = pytest.mark.skipif(
@@ -303,37 +305,6 @@ def test_skip_sphinx_directives_2(self):
303305
):
304306
self.checker.visit_classdef(stmt)
305307

306-
# @skip_on_missing_package_or_dict
307-
# # @set_config(spelling_dict=spell_dict)
308-
# @pytest.mark.parametrize(
309-
# "num_files,num_jobs,num_checkers",
310-
# [
311-
# (1, 2, 1),
312-
# (1, 2, 2),
313-
# (1, 2, 3),
314-
# (2, 2, 1),
315-
# (2, 2, 2),
316-
# (2, 2, 3),
317-
# (3, 2, 1),
318-
# (3, 2, 2),
319-
# (3, 2, 3),
320-
# (3, 1, 1),
321-
# (3, 1, 2),
322-
# (3, 1, 3),
323-
# (3, 5, 1),
324-
# (3, 5, 2),
325-
# (3, 5, 3),
326-
# (10, 2, 1),
327-
# (10, 2, 2),
328-
# (10, 2, 3),
329-
# (2, 10, 1),
330-
# (2, 10, 2),
331-
# (2, 10, 3),
332-
# ],
333-
# )
334-
# def test_compare_workers_to_single_proc(self, num_files, num_jobs, num_checkers):
335-
# assert True
336-
337308
@skip_on_missing_package_or_dict
338309
@set_config(spelling_dict=spell_dict)
339310
@pytest.mark.parametrize(
@@ -351,6 +322,7 @@ def test_skip_sphinx_directives_2(self):
351322
("noqa", ":", "flake8 / zimports directive"),
352323
("nosec", "", "bandit directive"),
353324
("isort", ":skip", "isort directive"),
325+
("mypy", ":", "mypy directive"),
354326
),
355327
)
356328
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
@@ -371,6 +343,42 @@ def test_skip_tool_directives_at_beginning_of_comments_but_still_raise_error_if_
371343
):
372344
self.checker.process_tokens(_tokenize_str(full_comment))
373345

346+
@skip_on_missing_package_or_dict
347+
@set_config(spelling_dict=spell_dict)
348+
def test_skip_code_flanked_in_double_backticks(self):
349+
full_comment = "# The function ``.qsize()`` .qsize()"
350+
with self.assertAddsMessages(
351+
Message(
352+
"wrong-spelling-in-comment",
353+
line=1,
354+
args=(
355+
"qsize",
356+
full_comment,
357+
" ^^^^^",
358+
self._get_msg_suggestions("qsize"),
359+
),
360+
)
361+
):
362+
self.checker.process_tokens(_tokenize_str(full_comment))
363+
364+
@skip_on_missing_package_or_dict
365+
@set_config(spelling_dict=spell_dict)
366+
def test_skip_code_flanked_in_single_backticks(self):
367+
full_comment = "# The function `.qsize()` .qsize()"
368+
with self.assertAddsMessages(
369+
Message(
370+
"wrong-spelling-in-comment",
371+
line=1,
372+
args=(
373+
"qsize",
374+
full_comment,
375+
" ^^^^^",
376+
self._get_msg_suggestions("qsize"),
377+
),
378+
)
379+
):
380+
self.checker.process_tokens(_tokenize_str(full_comment))
381+
374382
@skip_on_missing_package_or_dict
375383
@set_config(spelling_dict=spell_dict)
376384
def test_handle_words_joined_by_forward_slash(self):

0 commit comments

Comments
 (0)