From 41fbfe5e4591fa3da2f2bb887e82d8b88f72e8e5 Mon Sep 17 00:00:00 2001 From: Dimitri Papadopoulos <3234522+DimitriPapadopoulos@users.noreply.github.com> Date: Fri, 10 Sep 2021 11:18:39 +0200 Subject: [PATCH] Interpret --skip arguments as relative paths 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. --- .github/workflows/codespell-private.yml | 2 +- .github/workflows/codespell.yml | 2 +- README.rst | 8 ++-- codespell_lib/_codespell.py | 49 ++++++++++++++++++------- 4 files changed, 41 insertions(+), 20 deletions(-) diff --git a/.github/workflows/codespell-private.yml b/.github/workflows/codespell-private.yml index 7b3f299cd13..2f7e364005d 100644 --- a/.github/workflows/codespell-private.yml +++ b/.github/workflows/codespell-private.yml @@ -33,7 +33,7 @@ jobs: - run: python setup.py install - run: codespell --help - run: make check - - 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/*" + - 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/*" # this file has an error - run: "! codespell codespell_lib/tests/test_basic.py" - run: codecov diff --git a/.github/workflows/codespell.yml b/.github/workflows/codespell.yml index e3a064a1fb2..5f3a954c4c7 100644 --- a/.github/workflows/codespell.yml +++ b/.github/workflows/codespell.yml @@ -13,4 +13,4 @@ jobs: with: check_filenames: true # When using this Action in other repos, the --skip option below can be removed - skip: ./.git,./codespell_lib/data,./example/code.c,test_basic.py,*.pyc,README.rst + skip: .git,codespell_lib/data,example/code.c,test_basic.py,*.pyc,README.rst diff --git a/README.rst b/README.rst index dab29a8834a..02cdeed7198 100644 --- a/README.rst +++ b/README.rst @@ -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. :: @@ -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. diff --git a/codespell_lib/_codespell.py b/codespell_lib/_codespell.py index 259af286aa2..8d700354828 100755 --- a/codespell_lib/_codespell.py +++ b/codespell_lib/_codespell.py @@ -95,12 +95,14 @@ class QuietLevels(object): class GlobMatch(object): def __init__(self, pattern): if pattern: - # We remove trailing path separators from each pattern - # because shell completion might add a trailing separator - # '/' after directory names - self.pattern_list = [p.rstrip(os.path.sep) - # Pattern might be a list of comma-separated patterns - for p in ','.join(pattern).split(',')] + self.pattern_list = [ + # We remove trailing path separators from each pattern + # because shell completion might add a trailing separator + # '/' after directory names + p.rstrip(os.path.sep) + # Pattern might be a list of comma-separated patterns + for p in ','.join(pattern).split(',') + ] else: self.pattern_list = None @@ -428,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('.') @@ -877,29 +883,44 @@ def main(*args): 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 "as is" and relative 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 directories + if is_hidden(root, options.check_hidden): continue + + # files for file_ in files: # ignore hidden files in directories 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 "as is" and relative 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,