Skip to content
Open
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
4 changes: 3 additions & 1 deletion codespell_lib/_codespell.py
Original file line number Diff line number Diff line change
Expand Up @@ -896,7 +896,9 @@ def _ignore_word_sub(
ignore_word_regex: Optional[Pattern[str]],
) -> str:
if ignore_word_regex:
text = ignore_word_regex.sub(" ", text)
# Pad to the match length: callers match against this text but index
# back into the original, so the substitution must not move offsets.
text = ignore_word_regex.sub(lambda m: " " * (m.end() - m.start()), text)
return text


Expand Down
22 changes: 22 additions & 0 deletions codespell_lib/tests/test_basic.py
Original file line number Diff line number Diff line change
Expand Up @@ -1054,6 +1054,28 @@ def test_ignore_regex_option(
assert cs.main(fname, r"--ignore-regex=\bdonn\b") == 1


def test_ignore_regex_does_not_shift_offsets(
tmp_path: Path,
capsys: pytest.CaptureFixture[str],
) -> None:
"""A non-overlapping --ignore-regex must not affect other checks.

Matches are found in the ignore-substituted text but indexed against the
original line, so the substitution has to preserve offsets.
"""
# The escape-sequence check reads the character before the match.
fname = tmp_path / "esc.txt"
fname.write_text("var = 'IGNOREME \\nwe are here'\n")
assert cs.main(fname) == 0
assert cs.main(fname, "--ignore-regex=IGNOREME") == 0

# The "[sic]" check matches the line from the end of the match.
fname = tmp_path / "sic.txt"
fname.write_text("IGNOREME padding wrod [sic]\n")
assert cs.main(fname, "--ignore-sic") == 0
assert cs.main(fname, "--ignore-sic", "--ignore-regex=IGNOREME") == 0


def test_ignore_multiline_regex_option(
tmp_path: Path,
capsys: pytest.CaptureFixture[str],
Expand Down