@@ -254,17 +254,11 @@ def get(self, command_method: CommandFunc) -> Optional[argparse.ArgumentParser]:
254
254
command = command_method .__name__ [len (COMMAND_FUNC_PREFIX ) :]
255
255
256
256
parser_builder = getattr (command_method , constants .CMD_ATTR_ARGPARSER , None )
257
- parent = self ._cmd .find_commandset_for_command (command ) or self ._cmd
258
- parser = self ._cmd ._build_parser (parent , parser_builder )
259
- if parser is None :
257
+ if parser_builder is None :
260
258
return None
261
259
262
- # argparser defaults the program name to sys.argv[0], but we want it to be the name of our command
263
- from .decorators import (
264
- _set_parser_prog ,
265
- )
266
-
267
- _set_parser_prog (parser , command )
260
+ parent = self ._cmd .find_commandset_for_command (command ) or self ._cmd
261
+ parser = self ._cmd ._build_parser (parent , parser_builder , command )
268
262
269
263
# If the description has not been set, then use the method docstring if one exists
270
264
if parser .description is None and hasattr (command_method , '__wrapped__' ) and command_method .__wrapped__ .__doc__ :
@@ -758,24 +752,39 @@ def register_command_set(self, cmdset: CommandSet) -> None:
758
752
def _build_parser (
759
753
self ,
760
754
parent : CommandParent ,
761
- parser_builder : Optional [
762
- Union [
763
- argparse .ArgumentParser ,
764
- Callable [[], argparse .ArgumentParser ],
765
- StaticArgParseBuilder ,
766
- ClassArgParseBuilder ,
767
- ]
755
+ parser_builder : Union [
756
+ argparse .ArgumentParser ,
757
+ Callable [[], argparse .ArgumentParser ],
758
+ StaticArgParseBuilder ,
759
+ ClassArgParseBuilder ,
768
760
],
769
- ) -> Optional [argparse .ArgumentParser ]:
770
- parser : Optional [argparse .ArgumentParser ] = None
761
+ prog : str ,
762
+ ) -> argparse .ArgumentParser :
763
+ """Build argument parser for a command/subcommand.
764
+
765
+ :param parent: CommandParent object which owns the parser
766
+ :param parser_builder: method used to build the parser
767
+ :param prog: prog value to set in new parser
768
+ :return: new parser
769
+ :raises TypeError: if parser_builder is invalid type
770
+ """
771
771
if isinstance (parser_builder , staticmethod ):
772
772
parser = parser_builder .__func__ ()
773
773
elif isinstance (parser_builder , classmethod ):
774
- parser = parser_builder .__func__ (parent if not None else self ) # type: ignore[arg-type]
774
+ parser = parser_builder .__func__ (parent . __class__ )
775
775
elif callable (parser_builder ):
776
776
parser = parser_builder ()
777
777
elif isinstance (parser_builder , argparse .ArgumentParser ):
778
778
parser = copy .deepcopy (parser_builder )
779
+ else :
780
+ raise TypeError (f"Invalid type for parser_builder: { type (parser_builder )} " )
781
+
782
+ from .decorators import (
783
+ _set_parser_prog ,
784
+ )
785
+
786
+ _set_parser_prog (parser , prog )
787
+
779
788
return parser
780
789
781
790
def _install_command_function (self , command_func_name : str , command_method : CommandFunc , context : str = '' ) -> None :
@@ -963,12 +972,7 @@ def find_subcommand(action: argparse.ArgumentParser, subcmd_names: list[str]) ->
963
972
964
973
target_parser = find_subcommand (command_parser , subcommand_names )
965
974
966
- subcmd_parser = cast (argparse .ArgumentParser , self ._build_parser (cmdset , subcmd_parser_builder ))
967
- from .decorators import (
968
- _set_parser_prog ,
969
- )
970
-
971
- _set_parser_prog (subcmd_parser , f'{ command_name } { subcommand_name } ' )
975
+ subcmd_parser = self ._build_parser (cmdset , subcmd_parser_builder , f'{ command_name } { subcommand_name } ' )
972
976
if subcmd_parser .description is None and method .__doc__ :
973
977
subcmd_parser .description = strip_doc_annotations (method .__doc__ )
974
978
0 commit comments