Source code for GLXShell.libs.argparse

# https://gist.github.com/fonic/fe6cade2e1b9eaf3401cc732f48aeebd
import sys

try:
    from ucollections import namedtuple
except ImportError:
    from collections import namedtuple


[docs]class WithCmdArgParser: def __init__(self, parser): self.parser = parser def __call__(self, func): if not self.parser: self.parser = func(None, None, None, True) def wrapped_function(*args, **kwargs): try: return func(*args, parsed=self.parser.parse_args(args[1].split()), **kwargs) except SystemExit: return return wrapped_function
[docs]class Namespace: pass
class _ArgError(BaseException): pass class _Arg: def __init__(self, names, dest, action, nargs, const, default, type, help): self.names = names self.dest = dest self.action = action self.nargs = nargs self.const = const self.default = default self.type = type self.help = help def parse(self, optname, eq_arg, args): # parse args for this arg if self.action == "store" or self.action == "append": if self.nargs is None: if eq_arg is not None: ret = eq_arg elif args: ret = args.pop(0) else: raise _ArgError("expecting value for %s" % optname) return self.type(ret) elif self.nargs == "?": if eq_arg is not None: ret = eq_arg elif args: ret = args.pop(0) else: return self.default return self.type(ret) else: if self.nargs == "*": n = -1 elif self.nargs == "+": if not args: raise _ArgError("expecting value for %s" % optname) n = -1 else: n = int(self.nargs) ret = [] stop_at_opt = True while args and n != 0: if stop_at_opt and args[0].startswith("-") and args[0] != "-": if args[0] == "--": stop_at_opt = False args.pop(0) else: break else: ret.append(args.pop(0)) n -= 1 if n > 0: raise _ArgError("expecting value for %s" % optname) return ret elif self.action == "store_const": return self.const else: assert False def _dest_from_optnames(opt_names): dest = opt_names[0] for name in opt_names: if name.startswith("--"): dest = name break return dest.lstrip("-").replace("-", "_")
[docs]class ArgumentParser: def __init__(self, *, prog=None, description="", add_help=None): self.prog = prog self.description = description self.opt = [] self.pos = [] if add_help: self.add_argument("-h", "--help", help="show this help message and exit")
[docs] def add_argument(self, *args, **kwargs): action = kwargs.get("action", "store") if action == "store_true": action = "store_const" const = True default = kwargs.get("default", False) elif action == "store_false": action = "store_const" const = False default = kwargs.get("default", True) elif action == "append": const = None default = kwargs.get("default", []) else: const = kwargs.get("const", None) default = kwargs.get("default", None) if args and args[0].startswith("-"): list = self.opt dest = kwargs.get("dest") if dest is None: dest = _dest_from_optnames(args) else: list = self.pos dest = kwargs.get("dest") if dest is None: dest = args[0] if not args: args = [dest] list.append( _Arg(args, dest, action, kwargs.get("nargs", None), const, default, kwargs.get("type", str), kwargs.get("help", "")))
[docs] @staticmethod def error(msg): sys.stderr.write("error: %s\n" % msg) sys.exit(2)
[docs] def parse_args(self, args=None, namespace=None): return self._parse_args_impl(args, namespace, False)
[docs] def parse_known_args(self, args=None, namespace=None): return self._parse_args_impl(args, namespace, True)
def _parse_args_impl(self, args, namespace, return_unknown): if args is None: args = sys.argv[1:] else: args = args[:] if namespace is None: namespace = Namespace() try: return self._parse_args(args, namespace, return_unknown) except _ArgError as e: self.print_usage() self.error(str(e)) def _parse_args(self, args, argholder, return_unknown): # add optional args with defaults for opt in self.opt: setattr(argholder, opt.dest, opt.default) # deal with unknown arguments, if needed unknown = [] def consume_unknown(): while args and not args[0].startswith("-"): unknown.append(args.pop(0)) # parse all args parsed_pos = False while args or not parsed_pos: if args and args[0].startswith("-") and args[0] != "-" and args[0] != "--": # optional arg a = args.pop(0) if a in ("-h", "--help"): self.print_help() sys.exit(0) eq_arg = None if a.startswith("--") and "=" in a: a, eq_arg = a.split("=", 1) found = False for i, opt in enumerate(self.opt): if a in opt.names: val = opt.parse(a, eq_arg, args) if opt.action == "append": getattr(argholder, opt.dest).append(val) else: setattr(argholder, opt.dest, val) found = True break if not found: if return_unknown: unknown.append(a) consume_unknown() else: raise _ArgError("unknown option %s" % a) else: # positional arg if parsed_pos: if return_unknown: unknown = unknown + args break else: raise _ArgError("extra args: %s" % " ".join(args)) for pos in self.pos: setattr(argholder, pos.dest, pos.parse(pos.names[0], None, args)) parsed_pos = True if return_unknown: consume_unknown() return (argholder, unknown) if return_unknown else argholder
[docs] def format_usage(self): sys.stdout.write("Usage: %s" % (self.prog or sys.argv[0])) def render_arg(arg): if arg.action == "store": return " %s" % arg.dest else: return "" for opt in self.opt: sys.stdout.write(" [%s]" % ', '.join(opt.names)) for pos in self.pos: sys.stdout.write(render_arg(pos)) sys.stdout.write("\n")
[docs] def format_help(self): sys.stdout.write("Usage: %s" % (self.prog or sys.argv[0])) def render_arg(arg): if arg.action == "store": return " %s" % arg.dest else: return "" for opt in self.opt: sys.stdout.write(" [%s]" % ', '.join(opt.names)) for pos in self.pos: sys.stdout.write(render_arg(pos)) sys.stdout.write("\n\n") if self.description: sys.stdout.write("%s\n" % self.description) if self.pos: sys.stdout.write("\nPositional arguments:\n") for pos in self.pos: sys.stdout.write(" %-16s%s\n" % (pos.names[0], pos.help)) if self.opt: sys.stdout.write("\nOptional arguments:\n") for opt in self.opt: sys.stdout.write(" %-16s%s\n" % (', '.join(opt.names), opt.help))
[docs] def print_usage(self, file=None): self.format_usage()
[docs] def print_help(self, file=None): self.format_help()
# class ArgumentParser: # def __init__(self, **kwargs): # self.program = {key: kwargs[key] for key in kwargs} # self.positionals = [] # self.options = [] # if "add_help" in self.program and self.program['add_help'] is True: # self.add_argument("-h", "--help", help="show this help message and exit") # # def add_argument(self, *args, **kwargs): # argument = {key: kwargs[key] for key in kwargs} # # # Positional: argument with only one name not starting with '-' provided as # # positional argument to method -or- no name and only a 'dest=' argument # # if no default was supplied, use the parser-level default # # argument["action"] = kwargs.get("action", "store") # if argument["action"] == "store_true": # argument["action"] = "store_const" # argument["const"] = True # argument["default"] = kwargs.get("default", False) # elif argument["action"] == "store_false": # argument["action"] = "store_const" # argument["const"] = False # argument["default"] = kwargs.get("default", True) # else: # argument["const"] = kwargs.get("const", None) # argument["default"] = kwargs.get("default", None) # # if args and args[0].startswith("-"): # # argument["list"] = self.options # argument["dest"] = kwargs.get("dest") # if argument["dest"] is None: # argument["dest"] = args[0] # for name in args: # if name.startswith("--"): # argument["dest"] = name # break # argument["dest"] = argument["dest"].lstrip("-").replace("-", "_") # argument["name"] = argument["dest"] # else: # # argument["list"] = self.positionals # argument["dest"] = kwargs.get("dest") # if argument["dest"] is None: # argument["dest"] = args[0] # if not args: # # argument["dest"] = [argument["dest"]] # argument["name"] = argument["dest"] # # if len(args) == 0 or ( # len(args) == 1 and isinstance(args[0], str) and not args[0].startswith("-") # ): # if (len(args) > 0): # argument["name"] = args[0] # else: # argument["name"] = argument["dest"] # self.positionals.append(argument) # return # # # Option: argument with one or more flags starting with '-' provided as # # positional arguments to method # argument["flags"] = [item for item in args] # argument["nargs"] = kwargs.get("nargs", None) # self.options.append(argument) # # @staticmethod # def _parse(data, args): # if 'action' in data and data['action'] == "store": # if 'nargs' in data and data['nargs'] is None: # if args: # arg_val = args.pop(0) # else: # raise _ArgError("expecting value for %s" % data['name']) # elif 'nargs' in data and data['nargs'] == "?": # if args: # arg_val = args.pop(0) # else: # arg_val = data['default'] # else: # if 'nargs' in data and data['nargs'] == "*": # n = -1 # elif 'nargs' in data and data['nargs'] == "+": # if not args: # raise _ArgError("expecting value for %s" % data['name']) # n = -1 # else: # if 'nargs' in data: # n = int(data['nargs']) # else: # n = -1 # ret = [] # stop_at_opt = True # while args and n != 0: # if stop_at_opt and args[0].startswith("-") and args[0] != "-": # if args[0] == "--": # stop_at_opt = False # args.pop(0) # else: # break # else: # ret.append(args.pop(0)) # n -= 1 # if n > 0: # raise _ArgError("expecting value for %s" % data['name']) # arg_val = ret # elif 'action' in data and data['action'] == "store_const": # arg_val = data['const'] # else: # assert False # # return arg_val # # def parse_args(self, args=None): # # if args is None: # args = sys.argv[1:] # else: # args = args[:] # try: # return self._parse_args(args, False) # except _ArgError as e: # self.error(e) # # def _parse_args(self, args, return_unknown): # # add optional args with defaults # arg_dest = [] # arg_vals = [] # for opt in self.options: # arg_dest.append(opt['dest']) # arg_vals.append(opt['default']) # # # deal with unknown arguments, if needed # unknown = [] # # def consume_unknown(): # while args and not args[0].startswith("-"): # unknown.append(args.pop(0)) # # # parse all args # parsed_pos = False # while args or not parsed_pos: # if args and args[0].startswith("-") and args[0] != "-" and args[0] != "--": # # optional arg # a = args.pop(0) # if a in ("-h", "--help"): # self.print_help() # sys.exit(0) # found = False # count = 0 # for opt in self.options: # # if a in opt['flags']: # arg_vals[count] = self._parse(opt, args) # found = True # break # count += 1 # if not found: # if return_unknown: # unknown.append(a) # consume_unknown() # else: # raise _ArgError("unknown option %s" % a) # else: # # positional arg # if parsed_pos: # if return_unknown: # unknown = unknown + args # break # else: # raise _ArgError("extra args: %s" % " ".join(args)) # for pos in self.positionals: # arg_dest.append(pos['dest']) # arg_vals.append(self._parse(pos, args)) # # parsed_pos = True # if return_unknown: # consume_unknown() # # # build and return named tuple with arg values # values = namedtuple("args", arg_dest)(*arg_vals) # if return_unknown: # return values, unknown # else: # return values # # def format_usage(self): # # # Use user-defined usage message # if "usage" in self.program: # if self.program['usage'] == "" or str.isspace(self.program['usage']): # return "Usage: No usage information available" # return "Usage: %s" % self.program['usage'] # # # Use user-defined programme name # if 'prog' in self.program and not self.program['prog'] == "" and not str.isspace(self.program['prog']): # prog_text = self.program['prog'] # else: # prog_text = sys.argv[0] # # # Prepare output # output = [ # "Usage:", # prog_text # ] # # # argument # argument_list = [] # for option in self.options: # flags = str.join("|", option["flags"]) # argument_list.append( # "[%s]" % flags # if ( # "action" in option # and ( # option["action"] == "store_true" # or option["action"] == "store_false" # ) # ) # else "[%s %s]" % (flags, option["metavar"]) # if ("metavar" in option) # else "[%s]" % flags # if ("dest" in option) # else "[%s]" % flags # ) # for positional in self.positionals: # argument_list.append( # "%s" % positional["metavar"] # if ("metavar" in positional) # else "%s" % positional["name"] # ) # output.append(str.join(" ", argument_list)) # # return str.join(" ", output) # # def format_help(self): # # Add usage message to output # output = [self.format_usage()] # # # Add description to output if present # if ( # "description" in self.program # and self.program["description"] != "" # and not str.isspace(self.program["description"]) # ): # output.append("") # output.append(self.program["description"]) # # # Ad left key # for positional in self.positionals: # positional["left"] = ( # positional["metavar"] # if ("metavar" in positional) # else positional["name"] # ) # # for option in self.options: # if "action" in option and ( # option["action"] == "store_true" or option["action"] == "store_false" # ): # option["left"] = str.join(", ", option["flags"]) # else: # option["left"] = str.join( # ", ", # [ # "%s %s" % (item, option["metavar"]) # if ("metavar" in option) # else "%s" % item # if ("dest" in option) # else item # for item in option["flags"] # ], # ) # # # Determine determine max string lengths for left part # left_max_len = 0 # for argument in self.positionals + self.options: # left_max_len = max(left_max_len, len(argument["left"])) # # # Output format # outtmp = " %-" + str(left_max_len) + "s %s" # # # Add positional arguments to output # if len(self.positionals) > 0: # output.append("") # output.append("Positionals:") # for positional in self.positionals: # output.append(outtmp % (positional["left"], positional["help"])) # # # Add option arguments to output # if len(self.options) > 0: # output.append("") # output.append("Options:") # for option in self.options: # output.append(outtmp % (option["left"], option["help"])) # # # Add epilog to output if present # if ( # "epilog" in self.program # and self.program["epilog"] != "" # and not str.isspace(self.program["epilog"]) # ): # output.append("") # output.append(self.program["epilog"]) # # # Return output as single string # return str.join("\n", output) # # def print_usage(self, file=None): # if file is None: # file = sys.stdout # file.write("%s\n" % self.format_usage()) # # def print_help(self, file=None): # if file is None: # file = sys.stdout # file.write("%s\n" % self.format_help()) # # def error(self, message): # sys.stderr.write("%s\n" % self.format_usage()) # sys.stderr.write("Error: %s\n" % message) # sys.exit(2)