Skip to content

Commit

Permalink
Add linting test to ensure use of ExtendOverwriteDefault for nargs=*/+
Browse files Browse the repository at this point in the history
  • Loading branch information
tsibley committed Jan 8, 2025
1 parent b367af3 commit 8f6f145
Show file tree
Hide file tree
Showing 3 changed files with 62 additions and 7 deletions.
13 changes: 8 additions & 5 deletions LICENSE.nextstrain-cli
Original file line number Diff line number Diff line change
@@ -1,8 +1,11 @@
This license applies to the original copy of resource functions from the
Nextstrain CLI project into this project, incorporated in
"augur/data/__init__.py". Any subsequent modifications to this project's copy of
those functions are licensed under the license of this project, not of
Nextstrain CLI.
This license applies to the original copy of functions from the Nextstrain CLI
project into this project, namely

- resource functions incorporated as "augur/data/__init__.py"
- walk_commands() function incorporated into "augur/argparse_.py"

Any subsequent modifications to this project's copy of these functions are
licensed under the license of this project, not of Nextstrain CLI.

MIT License

Expand Down
30 changes: 28 additions & 2 deletions augur/argparse_.py
Original file line number Diff line number Diff line change
@@ -1,8 +1,9 @@
"""
Custom helpers for the argparse standard library.
"""
from argparse import Action, ArgumentParser, _ArgumentGroup, HelpFormatter, SUPPRESS, OPTIONAL, ZERO_OR_MORE, _ExtendAction
from typing import Union
from argparse import Action, ArgumentParser, _ArgumentGroup, HelpFormatter, SUPPRESS, OPTIONAL, ZERO_OR_MORE, _ExtendAction, _SubParsersAction
from itertools import chain
from typing import Iterable, Optional, Tuple, Union
from .types import ValidationMode


Expand Down Expand Up @@ -148,3 +149,28 @@ def add_validation_arguments(parser: Union[ArgumentParser, _ArgumentGroup]):
action="store_const",
const=ValidationMode.SKIP,
help="Skip validation of input/output files, equivalent to --validation-mode=skip. Use at your own risk!")


# Originally copied from nextstrain/cli/argparse.py in the Nextstrain CLI project¹.
#
# ¹ <https://github.com/nextstrain/cli/blob/4a00d7100eff811eab6df34db73c7f6d4196e22b/nextstrain/cli/argparse.py#L252-L271>
def walk_commands(parser: ArgumentParser, command: Optional[Tuple[str, ...]] = None) -> Iterable[Tuple[Tuple[str, ...], ArgumentParser]]:
if command is None:
command = (parser.prog,)

yield command, parser

subparsers = chain.from_iterable(
action.choices.items()
for action in parser._actions
if isinstance(action, _SubParsersAction))

visited = set()

for subname, subparser in subparsers:
if subparser in visited:
continue

visited.add(subparser)

yield from walk_commands(subparser, (*command, subname))
26 changes: 26 additions & 0 deletions tests/test_argparse_linting.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
# Originally based on tests/help.py from the Nextstrain CLI project.¹
#
# ¹ <https://github.com/nextstrain/cli/blob/4a00d7100eff811eab6df34db73c7f6d4196e22b/tests/help.py>
import pytest
from argparse import ArgumentParser
from typing import List, Tuple

from augur import make_parser
from augur.argparse_ import walk_commands, ExtendOverwriteDefault


# Walking commands is slow, so do it only once and use it for all tests in this
# file (though currently n=1).
commands = list(walk_commands(make_parser()))


# Ensure we always use ExtendOverwriteDefault for options that take a variable
# number of arguments. See <https://github.com/nextstrain/augur/pull/1709>.
@pytest.mark.parametrize("action", [
pytest.param(action, id = " ".join(command) + " " + "/".join(action.option_strings))
for command, parser in commands
for action in parser._actions
if action.nargs in {"+", "*"}
])
def test_ExtendOverwriteDefault(action):
assert isinstance(action, ExtendOverwriteDefault)

0 comments on commit 8f6f145

Please sign in to comment.