Skip to content

Commit

Permalink
Interpret --skip arguments as relative paths
Browse files Browse the repository at this point in the history
The --skip arguments are interpreted as paths relative to the
directories to check (the "file" arguments passed to codespell),
in addition to being interpreted "as is".

The benefit is that "codespell ." and "codespell $PWD" behave
the same, you just pass relative paths to --skip. No more adding
"./" to directory patterns.
  • Loading branch information
DimitriPapadopoulos committed Sep 27, 2021
1 parent 51aca06 commit 5b0023f
Show file tree
Hide file tree
Showing 3 changed files with 69 additions and 17 deletions.
8 changes: 4 additions & 4 deletions README.rst
Original file line number Diff line number Diff line change
Expand Up @@ -57,12 +57,12 @@ Comma-separated list of files to skip. It accepts globs as well. Examples:

* to skip .eps & .txt files, invoke ``codespell --skip="*.eps,*.txt"``

* to skip directories, invoke ``codespell --skip="./src/3rd-Party,./src/Test"``
* to skip directories, invoke ``codespell --skip="src/3rd-Party,src/Test"``


Useful commands::

codespell -d -q 3 --skip="*.po,*.ts,./src/3rdParty,./src/Test"
codespell -d -q 3 --skip="*.po,*.ts,src/3rdParty,src/Test"

List all typos found except translation files and some directories.
Display them without terminal colors and with a quiet level of 3. ::
Expand Down Expand Up @@ -95,13 +95,13 @@ containing an entry named ``[codespell]``. Each command line argument can
be specified in this file (without the preceding dashes), for example::

[codespell]
skip = *.po,*.ts,./src/3rdParty,./src/Test
skip = *.po,*.ts,src/3rdParty,src/Test
count =
quiet-level = 3

This is equivalent to running::

codespell --quiet-level 3 --count --skip "*.po,*.ts,./src/3rdParty,./src/Test"
codespell --quiet-level 3 --count --skip "*.po,*.ts,src/3rdParty,src/Test"

Any options specified in the command line will *override* options from the
config file.
Expand Down
40 changes: 30 additions & 10 deletions codespell_lib/_codespell.py
Original file line number Diff line number Diff line change
Expand Up @@ -430,6 +430,10 @@ def parse_options(args):
# Re-parse command line options to override config.
options = parser.parse_args(list(args), namespace=options)

# Add a phony option than can be changed into a real option when we
# are ready to deprecate old patterns (./foo/bar instead of foo/bar)
options.deprecated = True

if not options.files:
options.files.append('.')

Expand Down Expand Up @@ -873,35 +877,51 @@ def main(*args):

bad_count = 0
for filename in options.files:
# ignore hidden files
# ignore hidden file or directory
if is_hidden(filename, options.check_hidden):
continue

if os.path.isdir(filename):
for root, dirs, files in os.walk(filename):
if glob_match.match(root): # skip (absolute) directories
rel_root = os.path.relpath(root, filename)
# skip matching relative and "as is" directory paths
if (
glob_match.match(rel_root)
or glob_match.match(root) and options.deprecated
):
del dirs[:]
continue
if is_hidden(root, options.check_hidden): # dir itself hidden

# ignore hidden directory
if is_hidden(root, options.check_hidden):
continue

# files
for file_ in files:
# ignore hidden files in directories
# ignore hidden files
if is_hidden(file_, options.check_hidden):
continue
if glob_match.match(file_): # skip files
# skip base file name
if glob_match.match(file_):
continue
fname = os.path.join(root, file_)
if glob_match.match(fname): # skip paths
abs_path = os.path.join(root, file_)
rel_path = os.path.join(rel_root, file_)
# skip matching relative and "as is" file paths
if (
glob_match.match(rel_path)
or glob_match.match(abs_path) and options.deprecated
):
continue

bad_count += parse_file(
fname, colors, summary, misspellings, exclude_lines,
abs_path, colors, summary, misspellings, exclude_lines,
file_opener, word_regex, ignore_word_regex, uri_regex,
uri_ignore_words, context, options)

# skip (relative) directories
# skip base directory name
dirs[:] = [dir_ for dir_ in dirs if not glob_match.match(dir_)]

elif not glob_match.match(filename): # skip files
elif not glob_match.match(filename): # skip file
bad_count += parse_file(
filename, colors, summary, misspellings, exclude_lines,
file_opener, word_regex, ignore_word_regex, uri_regex,
Expand Down
38 changes: 35 additions & 3 deletions codespell_lib/tests/test_basic.py
Original file line number Diff line number Diff line change
Expand Up @@ -287,7 +287,19 @@ def test_encoding(tmpdir, capsys):


def test_ignore(tmpdir, capsys):
"""Test ignoring of files and directories."""
"""Test ignoring of files and directories.
Test the following file hierarchy:
tmpdir
├── good.txt
├── bad.txt
├── ignoredir
│   └── subdir
│    └── bad.txt
└── bad.js
"""
d = str(tmpdir)
goodtxt = op.join(d, 'good.txt')
with open(goodtxt, 'w') as f:
Expand All @@ -298,19 +310,39 @@ def test_ignore(tmpdir, capsys):
f.write('abandonned')
assert cs.main(d) == 1
assert cs.main('--skip=bad*', d) == 0
assert cs.main('--skip=*bad*', d) == 0
assert cs.main('--skip=bad.txt', d) == 0
assert cs.main('--skip=./bad.txt', d) == 0 # deprecated
subdir = op.join(d, 'ignoredir')
os.mkdir(subdir)
subdir = op.join(subdir, 'subdir')
os.mkdir(subdir)
with open(op.join(subdir, 'bad.txt'), 'w') as f:
f.write('abandonned')
assert cs.main(d) == 2
assert cs.main('--skip=bad*', d) == 0
assert cs.main('--skip=*ignoredir*', d) == 1
assert cs.main('--skip=*gnore*', d) == 1
assert cs.main('--skip=ignoredir*', d) == 1
assert cs.main('--skip=ignoredir', d) == 1
assert cs.main('--skip=*ignoredir/bad*', d) == 1
assert cs.main('--skip=ignoredir/', d) == 1
assert cs.main('--skip=./ignoredir', d) == 1 # deprecated
assert cs.main('--skip=*ignoredir/subdir*', d) == 1
assert cs.main('--skip=*gnoredir/subdi*', d) == 1
assert cs.main('--skip=ignoredir/subdir', d) == 1
assert cs.main('--skip=ignoredir/subdir/', d) == 1
assert cs.main('--skip=./ignoredir/subdir/', d) == 1 # deprecated
assert cs.main('--skip=*ignoredir/subdir/bad*', d) == 1
assert cs.main('--skip=ignoredir/subdir/bad.txt', d) == 1
assert cs.main('--skip=./ignoredir/subdir/bad.txt', d) == 1 # deprecated
assert cs.main('--skip=*subdir*', d) == 1
assert cs.main('--skip=*ubd*', d) == 1
assert cs.main('--skip=subdir', d) == 1
assert cs.main('--skip=*subdir/bad*', d) == 1
assert cs.main('--skip=subdir/bad*', d) == 2
badjs = op.join(d, 'bad.js')
copyfile(badtxt, badjs)
assert cs.main('--skip=*.js', goodtxt, badtxt, badjs) == 1
assert cs.main('--skip=*.js', goodtxt, badtxt, badjs) == 2


def test_check_filename(tmpdir, capsys):
Expand Down

0 comments on commit 5b0023f

Please sign in to comment.