Skip to content

Commit

Permalink
Add pre-commit configuration (#2459)
Browse files Browse the repository at this point in the history
  • Loading branch information
mdeweerd authored Dec 9, 2022
1 parent c965f08 commit f010d35
Show file tree
Hide file tree
Showing 8 changed files with 241 additions and 36 deletions.
6 changes: 6 additions & 0 deletions .github/workflows/codespell-private.yml
Original file line number Diff line number Diff line change
Expand Up @@ -63,6 +63,12 @@ jobs:
flake8-annotation:
runs-on: ubuntu-latest
steps:
- name: Setup python
uses: actions/setup-python@v4
with:
python-version: 3.x
- uses: actions/checkout@v3
- name: Install codespell dependencies
run: pip install -e ".[dev]"
- name: Flake8 with annotations
uses: TrueBrain/actions-flake8@v2
111 changes: 111 additions & 0 deletions .pre-commit-config.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,111 @@
---
files: ^(.*\.(py|json|md|sh|yaml|cfg|txt))$
exclude: ^(\.[^/]*cache/.*)$
repos:
- repo: https://github.com/executablebooks/mdformat
# Do this before other tools "fixing" the line endings
rev: 0.7.16
hooks:
- id: mdformat
name: Format Markdown
entry: mdformat # Executable to run, with fixed options
language: python
types: [markdown]
args: [--wrap, '75', --number]
additional_dependencies:
- mdformat-toc
- mdformat-beautysh
# -mdformat-shfmt
# -mdformat-tables
- mdformat-config
- mdformat-black
- mdformat-web
- mdformat-gfm
- repo: https://github.com/asottile/pyupgrade
rev: v3.3.1
hooks:
- id: pyupgrade
args: [--py37-plus]
- repo: https://github.com/pre-commit/pre-commit-hooks
rev: v4.4.0
hooks:
- id: no-commit-to-branch
args: [--branch, main]
- id: check-yaml
args: [--unsafe]
- id: debug-statements
- id: end-of-file-fixer
- id: trailing-whitespace
- id: check-json
- id: mixed-line-ending
- id: check-builtin-literals
- id: check-ast
- id: check-merge-conflict
- id: check-executables-have-shebangs
- id: check-shebang-scripts-are-executable
- id: check-docstring-first
- id: fix-byte-order-marker
- id: check-case-conflict
- id: check-toml
- repo: https://github.com/adrienverge/yamllint.git
rev: v1.28.0
hooks:
- id: yamllint
args:
- --no-warnings
- -d
- '{extends: relaxed, rules: {line-length: {max: 90}}}'
- repo: https://github.com/psf/black
rev: 22.10.0
hooks:
- id: black
- repo: https://github.com/Lucas-C/pre-commit-hooks-bandit
rev: v1.0.6
hooks:
- id: python-bandit-vulnerability-check
- repo: https://github.com/PyCQA/autoflake
rev: v2.0.0
hooks:
- id: autoflake
- repo: https://github.com/PyCQA/flake8
rev: 6.0.0
hooks:
- id: flake8
additional_dependencies:
- flake8-pyproject>=1.2.2
- flake8-bugbear>=22.7.1
- flake8-comprehensions>=3.10.0
- flake8-2020>=1.7.0
- mccabe>=0.7.0
- pycodestyle>=2.9.1
- pyflakes>=2.5.0
- repo: https://github.com/PyCQA/isort
rev: 5.10.1
hooks:
- id: isort
- repo: https://github.com/codespell-project/codespell
rev: v2.2.2
hooks:
- id: codespell
args: [--toml, pyproject-codespell.precommit-toml]
additional_dependencies:
- tomli
- repo: https://github.com/pre-commit/mirrors-pylint
rev: v3.0.0a5
hooks:
- id: pylint
additional_dependencies:
- chardet
- pytest
- repo: https://github.com/pre-commit/mirrors-mypy
rev: v0.991
hooks:
- id: mypy
args: [--no-warn-unused-ignores, --config-file, pyproject.toml, --disable-error-code,
import]
additional_dependencies:
- chardet
- pytest
- pytest-cov
- pytest-dependency
- types-chardet
1 change: 1 addition & 0 deletions MANIFEST.in
Original file line number Diff line number Diff line change
Expand Up @@ -9,3 +9,4 @@ exclude .git-blame-ignore-revs
exclude example example/* snap snap/* tools tools/*
exclude Makefile
exclude codespell.1.include
exclude pyproject-codespell.precommit-toml
40 changes: 22 additions & 18 deletions codespell_lib/_codespell.py
Original file line number Diff line number Diff line change
Expand Up @@ -352,7 +352,7 @@ def parse_options(
"This option can be specified multiple times.",
)
builtin_opts = "\n- ".join(
[""] + ["%r %s" % (d[0], d[1]) for d in _builtin_dictionaries]
[""] + [f"{d[0]!r} {d[1]}" for d in _builtin_dictionaries]
)
parser.add_argument(
"--builtin",
Expand Down Expand Up @@ -693,7 +693,7 @@ def ask_for_word_fix(
r = ""
fixword = fix_case(wrongword, misspelling.data)
while not r:
print("%s\t%s ==> %s (Y/n) " % (line, wrongword, fixword), end="")
print(f"{line}\t{wrongword} ==> {fixword} (Y/n) ", end="")
r = sys.stdin.readline().strip().upper()
if not r:
r = "Y"
Expand Down Expand Up @@ -743,7 +743,7 @@ def print_context(
# context = (context_before, context_after)
for i in range(index - context[0], index + context[1] + 1):
if 0 <= i < len(lines):
print("%s %s" % (">" if i == index else ":", lines[i].rstrip()))
print("{} {}".format(">" if i == index else ":", lines[i].rstrip()))


def extract_words(
Expand Down Expand Up @@ -806,14 +806,14 @@ def parse_file(
if summary and fix:
summary.update(lword)

cfilename = "%s%s%s" % (colors.FILE, filename, colors.DISABLE)
cwrongword = "%s%s%s" % (colors.WWORD, word, colors.DISABLE)
crightword = "%s%s%s" % (colors.FWORD, fixword, colors.DISABLE)
cfilename = f"{colors.FILE}{filename}{colors.DISABLE}"
cwrongword = f"{colors.WWORD}{word}{colors.DISABLE}"
crightword = f"{colors.FWORD}{fixword}{colors.DISABLE}"

if misspellings[lword].reason:
if options.quiet_level & QuietLevels.DISABLED_FIXES:
continue
creason = " | %s%s%s" % (
creason = " | {}{}{}".format(
colors.FILE,
misspellings[lword].reason,
colors.DISABLE,
Expand Down Expand Up @@ -843,7 +843,7 @@ def parse_file(
try:
text = is_text_file(filename)
except PermissionError as e:
print("WARNING: %s: %s" % (e.strerror, filename), file=sys.stderr)
print(f"WARNING: {e.strerror}: {filename}", file=sys.stderr)
return bad_count
except OSError:
return bad_count
Expand Down Expand Up @@ -917,16 +917,16 @@ def parse_file(
):
continue

cfilename = "%s%s%s" % (colors.FILE, filename, colors.DISABLE)
cfilename = f"{colors.FILE}{filename}{colors.DISABLE}"
cline = "%s%d%s" % (colors.FILE, i + 1, colors.DISABLE)
cwrongword = "%s%s%s" % (colors.WWORD, word, colors.DISABLE)
crightword = "%s%s%s" % (colors.FWORD, fixword, colors.DISABLE)
cwrongword = f"{colors.WWORD}{word}{colors.DISABLE}"
crightword = f"{colors.FWORD}{fixword}{colors.DISABLE}"

if misspellings[lword].reason:
if options.quiet_level & QuietLevels.DISABLED_FIXES:
continue

creason = " | %s%s%s" % (
creason = " | {}{}{}".format(
colors.FILE,
misspellings[lword].reason,
colors.DISABLE,
Expand Down Expand Up @@ -976,7 +976,7 @@ def parse_file(
else:
if not options.quiet_level & QuietLevels.FIXES:
print(
"%sFIXED:%s %s" % (colors.FWORD, colors.DISABLE, filename),
f"{colors.FWORD}FIXED:{colors.DISABLE} {filename}",
file=sys.stderr,
)
with open(filename, "w", encoding=encoding, newline="") as f:
Expand Down Expand Up @@ -1010,7 +1010,7 @@ def main(*args: str) -> int:
try:
word_regex = re.compile(word_regex)
except re.error as err:
print('ERROR: invalid --regex "%s" (%s)' % (word_regex, err), file=sys.stderr)
print(f'ERROR: invalid --regex "{word_regex}" ({err})', file=sys.stderr)
parser.print_help()
return EX_USAGE

Expand All @@ -1019,7 +1019,9 @@ def main(*args: str) -> int:
ignore_word_regex = re.compile(options.ignore_regex)
except re.error as err:
print(
'ERROR: invalid --ignore-regex "%s" (%s)' % (options.ignore_regex, err),
'ERROR: invalid --ignore-regex "{}" ({})'.format(
options.ignore_regex, err
),
file=sys.stderr,
)
parser.print_help()
Expand All @@ -1044,7 +1046,8 @@ def main(*args: str) -> int:
uri_regex = re.compile(uri_regex)
except re.error as err:
print(
'ERROR: invalid --uri-regex "%s" (%s)' % (uri_regex, err), file=sys.stderr
f'ERROR: invalid --uri-regex "{uri_regex}" ({err})',
file=sys.stderr,
)
parser.print_help()
return EX_USAGE
Expand All @@ -1063,12 +1066,13 @@ def main(*args: str) -> int:
for builtin in _builtin_dictionaries:
if builtin[0] == u:
use_dictionaries.append(
os.path.join(_data_root, "dictionary%s.txt" % (builtin[2],))
os.path.join(_data_root, f"dictionary{builtin[2]}.txt")
)
break
else:
print(
"ERROR: Unknown builtin dictionary: %s" % (u,), file=sys.stderr
f"ERROR: Unknown builtin dictionary: {u}",
file=sys.stderr,
)
parser.print_help()
return EX_USAGE
Expand Down
47 changes: 32 additions & 15 deletions codespell_lib/tests/test_dictionary.py
Original file line number Diff line number Diff line change
Expand Up @@ -89,14 +89,14 @@ def _check_aspell(
spellers[lang].check(phrase.encode(spellers[lang].ConfigKeys()["encoding"][1]))
for lang in languages
)
end = "be in aspell dictionaries (%s) for dictionary %s" % (
end = "be in aspell dictionaries ({}) for dictionary {}".format(
", ".join(languages),
fname,
)
if in_aspell: # should be an error in aspell
assert this_in_aspell, "%s should %s" % (msg, end)
assert this_in_aspell, f"{msg} should {end}"
else: # shouldn't be
assert not this_in_aspell, "%s should not %s" % (msg, end)
assert not this_in_aspell, f"{msg} should not {end}"


whitespace = re.compile(r"\s")
Expand All @@ -118,15 +118,18 @@ def _check_err_rep(
) -> None:
assert whitespace.search(err) is None, "error %r has whitespace" % err
assert "," not in err, "error %r has a comma" % err
assert len(rep) > 0, "error %s: correction %r must be non-empty" % (err, rep)
assert len(rep) > 0, f"error {err}: correction {rep!r} must be non-empty"
assert not start_whitespace.match(
rep
), "error %s: correction %r cannot start with whitespace" % (err, rep)
_check_aspell(err, "error %r" % (err,), in_aspell[0], fname, languages[0])
prefix = "error %s: correction %r" % (err, rep)
), f"error {err}: correction {rep!r} cannot start with whitespace"
_check_aspell(err, f"error {err!r}", in_aspell[0], fname, languages[0])
prefix = f"error {err}: correction {rep!r}"
for (regex, msg) in [
(start_comma, "%s starts with a comma"),
(whitespace_comma, "%s contains a whitespace character followed by a comma"),
(
whitespace_comma,
"%s contains a whitespace character followed by a comma",
),
(
comma_whitespaces,
"%s contains a comma followed by multiple whitespace characters",
Expand All @@ -144,9 +147,13 @@ def _check_err_rep(
reps = [r.strip() for r in rep.split(",")]
reps = [r for r in reps if len(r)]
for r in reps:
assert err != r.lower(), "error %r corrects to itself amongst others" % (err,)
assert err != r.lower(), f"error {err!r} corrects to itself amongst others"
_check_aspell(
r, "error %s: correction %r" % (err, r), in_aspell[1], fname, languages[1]
r,
f"error {err}: correction {r!r}",
in_aspell[1],
fname,
languages[1],
)

# aspell dictionary is case sensitive, so pass the original case into there
Expand Down Expand Up @@ -180,7 +187,11 @@ def test_error_checking(err: str, rep: str, match: str) -> None:
"""Test that our error checking works."""
with pytest.raises(AssertionError, match=match):
_check_err_rep(
err, rep, (None, None), "dummy", (supported_languages, supported_languages)
err,
rep,
(None, None),
"dummy",
(supported_languages, supported_languages),
)


Expand All @@ -205,7 +216,13 @@ def test_error_checking(err: str, rep: str, match: str) -> None:
("a", "bar back", None, False, "should not be in aspell"),
("a", "bar back Wednesday", None, False, "should not be in aspell"),
# Second multi-word, both parts
("a", "bar back, abcdef uvwxyz, bar,", None, True, "should be in aspell"),
(
"a",
"bar back, abcdef uvwxyz, bar,",
None,
True,
"should be in aspell",
),
(
"a",
"abcdef uvwxyz, bar back, ghijkl,",
Expand Down Expand Up @@ -263,7 +280,7 @@ def test_dictionary_looping(
for line in fid:
err, rep = line.split("->")
err = err.lower()
assert err not in this_err_dict, "error %r already exists in %s" % (
assert err not in this_err_dict, "error {!r} already exists in {}".format(
err,
short_fname,
)
Expand All @@ -286,7 +303,7 @@ def test_dictionary_looping(
for err in this_err_dict:
assert (
err not in other_err_dict
), "error %r in dictionary %s already exists in dictionary %s" % (
), "error {!r} in dictionary {} already exists in dictionary {}".format(
err,
short_fname,
other_fname,
Expand All @@ -297,7 +314,7 @@ def test_dictionary_looping(
for err in this_err_dict:
assert (
err not in other_err_dict
), "error %r in dictionary %s already exists in dictionary %s" % (
), "error {!r} in dictionary {} already exists in dictionary {}".format(
err,
short_fname,
other_fname,
Expand Down
7 changes: 7 additions & 0 deletions pyproject-codespell.precommit-toml
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
[tool.codespell]
#builtin = ["clear","rare","informal","usage","code","names"]
builtin = "clear,rare,informal,usage,code,names"
#ignore-words-list = ["uint"]
ignore-words-list = "uint"
#skip=[ "./.*","codespell_lib/data/*","codespell_lib/tests/*"]
skip="./.*,codespell_lib/data/*,codespell_lib/tests/*"
Loading

0 comments on commit f010d35

Please sign in to comment.