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+ t = action .type
26+ if t is not None :
27+ if (
28+ hasattr (t , "__annotations__" )
29+ and t .__annotations__ .get ("return" , None ) is not None
30+ ):
31+ _help += f"\n (type: { t .__annotations__ .get ('return' , None )} )"
32+ elif hasattr (t , "__name__" ):
33+ _help += f"\n (type: { t .__name__ } )"
34+
35+ if "%(default)" not in _help :
36+ if 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+ _help += _ ("\n (default: %(default)s)" )
40+ _help += f"\n (environment variable: { action .envvar } )"
41+
42+ return "\n " .join ([m .lstrip () for m in _help .split ("\n " )])
43+
44+
1245class EnvDefault (argparse .Action ):
1346 def __init__ (
1447 self ,
@@ -17,6 +50,7 @@ def __init__(
1750 default : str | None = None ,
1851 ** kwargs : dict [str , Any ],
1952 ) -> None :
53+ self .envvar = envvar
2054 if os .environ .get (envvar ):
2155 default = os .environ [envvar ]
2256 if required and default :
0 commit comments