import argparse import sys class CustomArgumentParser(argparse.ArgumentParser): CLI_ACTION_DISCOVER = "discover" CLI_ACTION_SEND = "send" def __init__(self, argv=None, **kwargs): super().__init__(**kwargs) self.argv = argv if argv is not None else sys.argv[1:] subparsers = self.add_subparsers(dest='cli_action', help="Available actions") subparsers._parser_class = self.create_subparser # Use a factory method for subparsers parser_discover = subparsers.add_parser(self.CLI_ACTION_DISCOVER, help="Discover Apple VDM's based on the given arguments") parser_discover.add_argument("-d", "--device", help="Acroname Device Serial Number", type=self.auto_int, metavar='', default=0) parser_discover.add_argument("-p", "--port", help="Port to execute VDM on.", required=True, type=int, metavar='') parser_discover.add_argument("-a", "--action", help="The Action to be included in the VDM", type=self.auto_int, metavar='', default=None) parser_discover.add_argument("-s", "--sop", help="SOP Selection: SOP`Debug(3), SOP``Debug(4)", required=False, type=int, metavar='', choices={3,4}, default=4) #SOP'Debug parser_send = subparsers.add_parser(self.CLI_ACTION_SEND, help="Sends the resulting Apple DFU VDM") parser_send.add_argument("-d", "--device", help="Acroname Device Serial Number", type=self.auto_int, metavar='', default=0) parser_send.add_argument("-p", "--port", help="Port to execute VDM on.", required=True, type=int, metavar='') parser_send.add_argument("-a", "--action", help="The Action to be included in the VDM", required=True, type=self.auto_int, metavar='') parser_send.add_argument("-r", "--action_argument", help="The Action to be included in the VDM", required=True, type=self.auto_int, metavar='') parser_send.add_argument("-s", "--sop", help="SOP Selection: SOP`Debug(3), SOP``Debug(4)", required=False, type=int, metavar='', choices={3,4}, default=4) #SOP'Debug parser_send.add_argument("-x", "--send", help="Actually send the vdm", action='store_true') self.parsed_args = self.parse_args(self.argv[1:]) #Ensure the user provided a subparser argument (discovered, send) self.cli_action = self.parsed_args.cli_action if self.cli_action is None: self.print_help() sys.exit(255) self.action = self.parsed_args.action self.port = self.parsed_args.port self.sn = self.parsed_args.device self.sop = self.parsed_args.sop if self.CLI_ACTION_SEND == self.cli_action: self.action_argument= self.parsed_args.action_argument self.send = self.parsed_args.send def create_subparser(self, **kwargs): return argparse.ArgumentParser(**kwargs) def print_example_usage(self): EXAMPLE_USAGE = [ \ (""), \ ("Example Usage:"), \ (" \"%s discover -p 5\" - Discovers all Actions and Action Arguments" % (self.argv[0])), \ (" \"%s discover -p 5 -d 0xBEEFFEED\" - Discovers all Actions and Action Arguments for the specified device" % (self.argv[0])), \ (" \"%s discover -p 5 -a 0x106\" - Discovers Action Arguments for the provided action" % (self.argv[0])), \ (""), \ (" Note: Action (-a) and Action Arguments (-r) are not verified before sending."), \ (" \"%s send -p 5 -a 0x0106 -r 0x8001\" - Constructs an Apple DFU VDM, but does not send it." % (self.argv[0])), \ (" \"%s send -p 5 -a 0x0106 -r 0x8001 -x\" - Constructs an Apple DFU VDM and Sends it" % (self.argv[0])), \ ] for usage in EXAMPLE_USAGE: print(usage) def print_help(self): super().print_help() self.print_example_usage() @staticmethod def auto_int(x): # Automatically detect the base (hex if prefixed with '0x', decimal otherwise) return int(x, 0)