22
33import argparse
44from argparse import ArgumentParser , Namespace
5+ from gettext import gettext as _
56import os
67from typing import TYPE_CHECKING , Any , override
78
89if TYPE_CHECKING :
910 from collections .abc import Callable , Sequence
1011
1112
13+ class ArgumentHelpFormatter (argparse .RawTextHelpFormatter ):
14+ """Custom argument formatter.
15+
16+ Appends environment variable and default value to help.
17+ """
18+
19+ def _get_help_string (self , action : argparse .Action ) -> str | None :
20+ _help = action .help
21+ if _help is None :
22+ _help = ""
23+
24+ if isinstance (action , EnvDefault ):
25+ # append type
26+ t = action .type
27+ if t is not None :
28+ if (
29+ hasattr (t , "__annotations__" )
30+ and t .__annotations__ .get ("return" , None ) is not None
31+ ):
32+ _help += f"\n (type: { t .__annotations__ .get ('return' , None )} )"
33+ elif hasattr (t , "__name__" ):
34+ _help += f"\n (type: { t .__name__ } )"
35+
36+ if "%(default)" not in _help and action .default is not argparse .SUPPRESS :
37+ defaulting_nargs = [argparse .OPTIONAL , argparse .ZERO_OR_MORE ]
38+ if action .option_strings or action .nargs in defaulting_nargs :
39+ # append default value
40+ _help += _ ("\n (default: %(default)s)" )
41+ # append environment variable
42+ _help += f"\n (environment variable: { action .envvar } )"
43+ # whitespace from each line
44+ return "\n " .join ([m .lstrip () for m in _help .split ("\n " )])
45+
46+
1247class EnvDefault (argparse .Action ):
1348 def __init__ (
1449 self ,
@@ -17,6 +52,7 @@ def __init__(
1752 default : str | None = None ,
1853 ** kwargs : dict [str , Any ],
1954 ) -> None :
55+ self .envvar = envvar
2056 if os .environ .get (envvar ):
2157 default = os .environ [envvar ]
2258 if required and default :
0 commit comments