Skip to content

Commit

Permalink
Implement inline ignores (#2400)
Browse files Browse the repository at this point in the history
Co-authored-by: Peter Newman <peternewman@users.noreply.github.com>
  • Loading branch information
kaste and peternewman committed Mar 10, 2024
1 parent 3ae34b5 commit 8fa1baa
Show file tree
Hide file tree
Showing 4 changed files with 74 additions and 3 deletions.
2 changes: 1 addition & 1 deletion .github/workflows/codespell-private.yml
Original file line number Diff line number Diff line change
Expand Up @@ -54,7 +54,7 @@ jobs:
# tomli should not be required for the next two steps (and make sure it's not)
- run: pip uninstall -yq tomli
if: ${{ matrix.no-toml == 'no-toml' }}
- run: codespell --check-filenames --skip="./.git/*,*.pyc,./codespell_lib/tests/test_basic.py,./codespell_lib/data/*,./example/code.c,./build/lib/codespell_lib/tests/test_basic.py,./build/lib/codespell_lib/data/*,README.rst,*.egg-info/*,pyproject-codespell.precommit-toml,./.mypy_cache"
- run: codespell --check-filenames --skip="./.git/*,./.pytest_cache/*,./junit-results.xml,*.pyc,./codespell_lib/tests/test_basic.py,./codespell_lib/data/*,./example/code.c,./build/lib/codespell_lib/tests/test_basic.py,./build/lib/codespell_lib/data/*,README.rst,*.egg-info/*,pyproject-codespell.precommit-toml,./.mypy_cache"
# this file has an error
- run: "! codespell codespell_lib/tests/test_basic.py"

Expand Down
12 changes: 11 additions & 1 deletion codespell_lib/_codespell.py
Original file line number Diff line number Diff line change
Expand Up @@ -55,6 +55,7 @@
# Pass all misspellings through this translation table to generate
# alternative misspellings and fixes.
alt_chars = (("'", "’"),) # noqa: RUF001
inline_ignore_regex = re.compile(r"[^\w\s]\s?codespell:ignore\b(\s+(?P<words>[\w,]*))?")
USAGE = """
\t%prog [OPTIONS] [file1 file2 ... fileN]
"""
Expand Down Expand Up @@ -974,6 +975,15 @@ def parse_file(
if line.rstrip() in exclude_lines:
continue

extra_words_to_ignore = set()
match = inline_ignore_regex.search(line)
if match:
extra_words_to_ignore = set(
filter(None, (match.group("words") or "").split(","))
)
if not extra_words_to_ignore:
continue

fixed_words = set()
asked_for = set()

Expand All @@ -998,7 +1008,7 @@ def parse_file(
if word in ignore_words_cased:
continue
lword = word.lower()
if lword in misspellings:
if lword in misspellings and lword not in extra_words_to_ignore:
# Sometimes we find a 'misspelling' which is actually a valid word
# preceded by a string escape sequence. Ignore such cases as
# they're usually false alarms; see issue #17 among others.
Expand Down
61 changes: 61 additions & 0 deletions codespell_lib/tests/test_basic.py
Original file line number Diff line number Diff line change
Expand Up @@ -391,6 +391,67 @@ def test_ignore_word_list(
assert cs.main("-Labandonned,someword", "-Labilty", tmp_path) == 1


@pytest.mark.parametrize(
("content", "expected_error_count"),
[
# recommended form
("abandonned abondon abilty # codespell:ignore abondon", 2),
("abandonned abondon abilty // codespell:ignore abondon,abilty", 1),
(
"abandonned abondon abilty /* codespell:ignore abandonned,abondon,abilty",
0,
),
# ignore unused ignore
("abandonned abondon abilty # codespell:ignore nomenklatur", 3),
# wildcard form
("abandonned abondon abilty # codespell:ignore ", 0),
("abandonned abondon abilty # codespell:ignore", 0),
("abandonned abondon abilty # codespell:ignore\n", 0),
("abandonned abondon abilty # codespell:ignore\r\n", 0),
("abandonned abondon abilty # codespell:ignore # noqa: E501\n", 0),
("abandonned abondon abilty # codespell:ignore # noqa: E501\n", 0),
("abandonned abondon abilty # codespell:ignore# noqa: E501\n", 0),
("abandonned abondon abilty # codespell:ignore, noqa: E501\n", 0),
("abandonned abondon abilty #codespell:ignore\n", 0),
# ignore these for safety
("abandonned abondon abilty # codespell:ignorenoqa: E501\n", 3),
("abandonned abondon abilty codespell:ignore\n", 3),
("abandonned abondon abilty codespell:ignore\n", 3),
# ignore these as they aren't valid
("abandonned abondon abilty # codespell:igore\n", 4),
# showcase different comment markers
("abandonned abondon abilty ' codespell:ignore\n", 0),
('abandonned abondon abilty " codespell:ignore\n', 0),
("abandonned abondon abilty ;; codespell:ignore\n", 0),
("abandonned abondon abilty /* codespell:ignore */\n", 0),
# prose examples
(
"You could also use line based igore ( codespell:ignore ) to igore ",
0,
),
("You could also use line based igore (codespell:ignore) to igore ", 0),
(
"You could also use line based igore (codespell:ignore igore) to igore ",
0,
),
(
"You could also use line based igore (codespell:ignore igare) to igore ",
2,
),
],
)
def test_inline_ignores(
tmpdir: pytest.TempPathFactory,
capsys: pytest.CaptureFixture[str],
content: str,
expected_error_count: int,
) -> None:
d = str(tmpdir)
with open(op.join(d, "bad.txt"), "w") as f:
f.write(content)
assert cs.main(d) == expected_error_count


def test_custom_regex(
tmp_path: Path,
capsys: pytest.CaptureFixture[str],
Expand Down
2 changes: 1 addition & 1 deletion pyproject.toml
Original file line number Diff line number Diff line change
Expand Up @@ -171,4 +171,4 @@ allow-magic-value-types = ["bytes", "int", "str",]
max-args = 13
max-branches = 49
max-returns = 11
max-statements = 113
max-statements = 119

0 comments on commit 8fa1baa

Please sign in to comment.