Skip to content

Commit

Permalink
Merge pull request #1705: Add help text to clarify extend actions
Browse files Browse the repository at this point in the history
  • Loading branch information
victorlin authored Jan 7, 2025
2 parents a57d50c + 3d71c25 commit f758ced
Show file tree
Hide file tree
Showing 3 changed files with 34 additions and 9 deletions.
2 changes: 2 additions & 0 deletions CHANGES.md
Original file line number Diff line number Diff line change
Expand Up @@ -10,9 +10,11 @@

* ancestral, refine: Explicitly specify how the root and ambiguous states are handled during sequence reconstruction and mutation counting. [#1690][] (@rneher)
* titers: Fix type errors in code associated with cross-validation of models. [#1688][] (@huddlej)
* Add help text to clarify difference in behavior between options that override defaults (e.g. `--metadata-delimiters`) vs. options that extend existing defaults (e.g. `--expected-date-formats`). [#1705][] (@victorlin)

[#1688]: https://github.com/nextstrain/augur/pull/1688
[#1690]: https://github.com/nextstrain/augur/pull/1690
[#1705]: https://github.com/nextstrain/augur/pull/1705

## 27.0.0 (9 December 2024)

Expand Down
38 changes: 30 additions & 8 deletions augur/argparse_.py
Original file line number Diff line number Diff line change
@@ -1,25 +1,47 @@
"""
Custom helpers for the argparse standard library.
"""
from argparse import Action, ArgumentDefaultsHelpFormatter, ArgumentParser, _ArgumentGroup
from argparse import Action, ArgumentParser, _ArgumentGroup, HelpFormatter, SUPPRESS, OPTIONAL, ZERO_OR_MORE, _ExtendAction
from typing import Union
from .types import ValidationMode


# Include this in an argument help string to suppress the automatic appending
# of the default value by argparse.ArgumentDefaultsHelpFormatter. This works
# because the automatic appending is conditional on the presence of %(default),
# so we include it but then format it as a zero-length string .0s. 🙃
# of the default value by CustomHelpFormatter. This works because the
# automatic appending is conditional on the presence of %(default), so we
# include it but then format it as a zero-length string .0s. 🙃
#
# Another solution would be to add an extra attribute to the argument (the
# argparse.Action instance) and then subclass ArgumentDefaultsHelpFormatter to
# condition on that new attribute, but that seems more brittle.
# argparse.Action instance) and then modify CustomHelpFormatter to condition
# on that new attribute, but that seems more brittle.
#
# Copied from the Nextstrain CLI repo
# Initially copied from the Nextstrain CLI repo
# https://github.com/nextstrain/cli/blob/017c53805e8317951327d24c04184615cc400b09/nextstrain/cli/argparse.py#L13-L21
SKIP_AUTO_DEFAULT_IN_HELP = "%(default).0s"


class CustomHelpFormatter(HelpFormatter):
"""Customize help text.
Initially copied from argparse.ArgumentDefaultsHelpFormatter.
"""
def _get_help_string(self, action: Action):
help = action.help

if action.default is not None and action.default != []:
if isinstance(action, ExtendOverwriteDefault):
help += ' Specified values will override the default list.'
if isinstance(action, _ExtendAction):
help += ' Specified values will extend the default list.'

if '%(default)' not in action.help:
if action.default is not SUPPRESS:
defaulting_nargs = [OPTIONAL, ZERO_OR_MORE]
if action.option_strings or action.nargs in defaulting_nargs:
help += ' (default: %(default)s)'
return help


def add_default_command(parser):
"""
Sets the default command to run when none is provided.
Expand Down Expand Up @@ -61,7 +83,7 @@ def add_command_subparsers(subparsers, commands, command_attribute='__command__'

# Use the same formatting class for every command for consistency.
# Set here to avoid repeating it in every command's register_parser().
subparser.formatter_class = ArgumentDefaultsHelpFormatter
subparser.formatter_class = CustomHelpFormatter

if not subparser.description and command.__doc__:
subparser.description = command.__doc__
Expand Down
3 changes: 2 additions & 1 deletion docs/conf.py
Original file line number Diff line number Diff line change
Expand Up @@ -132,9 +132,10 @@ def prose_list(items):
("py:class", "json.decoder.JSONDecodeError"),
("py:class", "json.encoder.JSONEncoder"),

# This class can't be referenced.
# These classes can't be referenced.
# <https://github.com/python/cpython/issues/101503>
("py:class", "argparse._SubParsersAction"),
("py:class", "argparse.HelpFormatter"),
]

# -- Cross-project references ------------------------------------------------
Expand Down

0 comments on commit f758ced

Please sign in to comment.