@@ -254,17 +254,11 @@ def get(self, command_method: CommandFunc) -> Optional[argparse.ArgumentParser]:
254254 command = command_method .__name__ [len (COMMAND_FUNC_PREFIX ) :]
255255
256256 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 :
260258 return None
261259
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 )
268262
269263 # If the description has not been set, then use the method docstring if one exists
270264 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:
758752 def _build_parser (
759753 self ,
760754 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 ,
768760 ],
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+ """
771771 if isinstance (parser_builder , staticmethod ):
772772 parser = parser_builder .__func__ ()
773773 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__ )
775775 elif callable (parser_builder ):
776776 parser = parser_builder ()
777777 elif isinstance (parser_builder , argparse .ArgumentParser ):
778778 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+
779788 return parser
780789
781790 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]) ->
963972
964973 target_parser = find_subcommand (command_parser , subcommand_names )
965974
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 } ' )
972976 if subcmd_parser .description is None and method .__doc__ :
973977 subcmd_parser .description = strip_doc_annotations (method .__doc__ )
974978
0 commit comments