Skip to content

Commit 30783e3

Browse files
Options that expect a file should accept lists of files too
The rationale is that these options readily accept multiple files from the command line, because they can be specified multiple times. However, duplicate option keys are invalid in an INI config file. The alternative is to accept multiple values for each occurrence of an option key.
1 parent 6774b1a commit 30783e3

File tree

2 files changed

+40
-25
lines changed

2 files changed

+40
-25
lines changed

codespell_lib/_codespell.py

Lines changed: 38 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -339,10 +339,9 @@ def parse_options(
339339
"-D",
340340
"--dictionary",
341341
action="append",
342-
help="custom dictionary file that contains spelling "
343-
"corrections. If this flag is not specified or "
344-
'equals "-" then the default dictionary is used. '
345-
"This option can be specified multiple times.",
342+
help="comma-separated list of custom dictionary files that "
343+
"contain spelling corrections. If this flag is not specified "
344+
'or equals "-" then the default dictionary is used.',
346345
)
347346
builtin_opts = "\n- ".join(
348347
[""] + [f"{d[0]!r} {d[1]}" for d in _builtin_dictionaries]
@@ -372,26 +371,26 @@ def parse_options(
372371
"-I",
373372
"--ignore-words",
374373
action="append",
375-
metavar="FILE",
376-
help="file that contains words that will be ignored "
377-
"by codespell. File must contain 1 word per line."
378-
" Words are case sensitive based on how they are "
379-
"written in the dictionary file",
374+
metavar="FILES",
375+
help="comma-separated list of files that contain "
376+
"words to be ignored by codespell. Files must contain "
377+
"1 word per line. Words are case sensitive based on "
378+
"how they are written in the dictionary file.",
380379
)
381380
parser.add_argument(
382381
"-L",
383382
"--ignore-words-list",
384383
action="append",
385384
metavar="WORDS",
386-
help="comma separated list of words to be ignored "
385+
help="comma-separated list of words to be ignored "
387386
"by codespell. Words are case sensitive based on "
388-
"how they are written in the dictionary file",
387+
"how they are written in the dictionary file.",
389388
)
390389
parser.add_argument(
391390
"--uri-ignore-words-list",
392391
action="append",
393392
metavar="WORDS",
394-
help="comma separated list of words to be ignored "
393+
help="comma-separated list of words to be ignored "
395394
"by codespell in URIs and emails only. Words are "
396395
"case sensitive based on how they are written in "
397396
'the dictionary file. If set to "*", all '
@@ -443,11 +442,13 @@ def parse_options(
443442
parser.add_argument(
444443
"-x",
445444
"--exclude-file",
445+
action="append",
446446
type=str,
447-
metavar="FILE",
448-
help="ignore whole lines that match those "
449-
"in the file FILE. The lines in FILE "
450-
"should match the to-be-excluded lines exactly",
447+
metavar="FILES",
448+
help="ignore whole lines that match those in "
449+
"the comma-separated list of files EXCLUDE. "
450+
"The lines in these files should match the "
451+
"to-be-excluded lines exactly",
451452
)
452453

453454
parser.add_argument(
@@ -984,6 +985,22 @@ def parse_file(
984985
return bad_count
985986

986987

988+
def flatten_comma_separated_arguments(
989+
arguments: List[str],
990+
) -> List[str]:
991+
"""
992+
>>> flatten_comma_separated_arguments([])
993+
[]
994+
>>> flatten_comma_separated_arguments(None)
995+
None
996+
>>> flatten_comma_separated_arguments(["a,b,c", "d", "e"])
997+
['a', 'b', 'c', 'd', 'e']
998+
"""
999+
if arguments:
1000+
arguments = [item for argument in arguments for item in argument.split(",")]
1001+
return arguments
1002+
1003+
9871004
def _script_main() -> int:
9881005
"""Wrap to main() for setuptools."""
9891006
return main(*sys.argv[1:])
@@ -1028,8 +1045,8 @@ def main(*args: str) -> int:
10281045
else:
10291046
ignore_word_regex = None
10301047

1031-
ignore_words_files = options.ignore_words or []
10321048
ignore_words = parse_ignore_words_option(options.ignore_words_list)
1049+
ignore_words_files = flatten_comma_separated_arguments(options.ignore_words) or []
10331050
for ignore_words_file in ignore_words_files:
10341051
if not os.path.isfile(ignore_words_file):
10351052
print(
@@ -1052,10 +1069,7 @@ def main(*args: str) -> int:
10521069
return EX_USAGE
10531070
uri_ignore_words = parse_ignore_words_option(options.uri_ignore_words_list)
10541071

1055-
if options.dictionary:
1056-
dictionaries = options.dictionary
1057-
else:
1058-
dictionaries = ["-"]
1072+
dictionaries = flatten_comma_separated_arguments(options.dictionary) or ["-"]
10591073
use_dictionaries = []
10601074
for dictionary in dictionaries:
10611075
if dictionary == "-":
@@ -1118,8 +1132,9 @@ def main(*args: str) -> int:
11181132
context = (context_before, context_after)
11191133

11201134
exclude_lines: Set[str] = set()
1121-
if options.exclude_file:
1122-
build_exclude_hashes(options.exclude_file, exclude_lines)
1135+
exclude_files = flatten_comma_separated_arguments(options.exclude_file) or []
1136+
for exclude_file in exclude_files:
1137+
build_exclude_hashes(exclude_file, exclude_lines)
11231138

11241139
file_opener = FileOpener(options.hard_encoding_detection, options.quiet_level)
11251140

pyproject.toml

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -141,6 +141,6 @@ max-complexity = 45
141141
[tool.ruff.pylint]
142142
allow-magic-value-types = ["bytes", "int", "str",]
143143
max-args = 12
144-
max-branches = 48
144+
max-branches = 46
145145
max-returns = 10
146-
max-statements = 111
146+
max-statements = 108

0 commit comments

Comments
 (0)