Galaxie Shell 0.2.6 documentation


Navigation:   | Index   | Search   | Top   | Up   |
Table of Content: |

© Copyright 2020-2024, Galaxie Shell Team.

Top » Module code » glxshell.lib.argparse.argparse

Source code for glxshell.lib.argparse.argparse

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

from glxshell.lib.textwrap import indent
from glxshell.lib.textwrap import wrap
from glxshell.lib.argparse.utility_description import UtilityDescription
from glxshell.lib.utils import get_bold_text

OPTIONAL = "?"
ZERO_OR_MORE = "*"
ONE_OR_MORE = "+"
PARSER = "A..."
REMAINDER = "..."


[docs] class WrapperCmdLineArgParser: def __init__(self, parser): """Init decorator with an argparse parser to be used in parsing cmd-line options""" self.parser = parser def __call__(self, func): """Decorate 'func' to parse 'line' and pass options to decorated function""" if not self.parser: self.parser = func(None, None, None, True) def wrapped_function(*args): line = args[1].split() try: parsed = self.parser.parse_args(line) except SystemExit: return None return func(*args, parsed) return wrapped_function
[docs] class Namespace: pass
class _ArgError(BaseException): pass class _Arg: def __init__(self, names, dest, action, nargs, const, default, arg_type, arg_help): self.names = names self.dest = dest self.action = action self.nargs = nargs self.const = const self.default = default self.type = arg_type self.help = arg_help def parse(self, optname, eq_arg, args): # parse args for this arg if self.action in {'store', 'append'}: if self.nargs is None: if eq_arg: return self.type(eq_arg) if args: return self.type(args.pop(0)) raise _ArgError("expecting value for %s" % optname) if self.nargs == OPTIONAL: if eq_arg: return self.type(eq_arg) if args: return self.type(args.pop(0)) return self.default # Else ret = [] if self.nargs == ZERO_OR_MORE: n = -1 elif self.nargs == ONE_OR_MORE: if not args: raise _ArgError("expecting value for %s" % optname) n = -1 elif self.nargs == REMAINDER: n = 0 while args: ret.append(args.pop(0)) else: n = int(self.nargs) 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 if self.action == "store_const": return self.const 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(UtilityDescription): def __init__(self, **kwargs): UtilityDescription.__init__(self) self.columns = 79 add_help = kwargs.get("add_help", False) self.name = kwargs.get("name", None) self.synopsis = kwargs.get("synopsis", None) self.description = kwargs.get("description", None) self.options = kwargs.get("options", None) self.operands = kwargs.get("operands", None) self.stdin = kwargs.get("stdin", None) self.input_files = kwargs.get("input_files", None) self.environment_variables = kwargs.get("environment_variables", None) self.asynchronous_events = kwargs.get("asynchronous_events", None) self.stdout = kwargs.get("stdout", None) self.stderr = kwargs.get("stderr", None) self.output_files = kwargs.get("output_files", None) self.extended_description = kwargs.get("extended_description", None) self.exit_status = kwargs.get("exit_status", None) self.consequences_of_errors = kwargs.get("consequences_of_errors", None) self.application_usage = kwargs.get("application_usage", None) self.examples = kwargs.get("examples", None) self.rationale = kwargs.get("rationale", None) self.future_directions = kwargs.get("future_directions", None) self.see_also = kwargs.get("see_also", None) self.change_history = kwargs.get("change_history", None) self.opt = [] self.pos = [] if add_help: self.add_argument("-h", "--help", dest="help", action="store_true", 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("-"): args_list = self.opt dest = kwargs.get("dest") if dest is None: dest = _dest_from_optnames(args) else: args_list = self.pos dest = kwargs.get("dest") if dest is None: dest = args[0] if not args: args = [dest] args_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)) return None def _parse_args(self, args, arg_holder, return_unknown): # add optional args with defaults for opt in self.opt: setattr(arg_holder, 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) # optional deal with cumulative arguments (ex: -lah) if "--" not in a and len(a) > 2: index_focus = 0 for letter in a.replace("-", ""): args.insert(index_focus, "-%s" % letter) index_focus += 1 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 _, opt in enumerate(self.opt): if a in opt.names: val = opt.parse(a, eq_arg, args) if opt.action == "append": getattr(arg_holder, opt.dest).append(val) else: setattr(arg_holder, 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 raise _ArgError("extra args: %s" % " ".join(args)) for pos in self.pos: setattr(arg_holder, pos.dest, pos.parse(pos.names[0], None, args)) parsed_pos = True if return_unknown: consume_unknown() return (arg_holder, unknown) if return_unknown else arg_holder
[docs] @staticmethod def render_arg(arg): if arg.action == "store": if arg.nargs == ONE_OR_MORE: return " %s..." % arg.dest if arg.nargs == ZERO_OR_MORE: return " [%s...]" % arg.dest if arg.nargs == OPTIONAL: return " [%s]" % arg.dest return " %s" % arg.dest return ""
[docs] def format_usage(self): if self.synopsis: for usage in self.synopsis: if usage == self.synopsis[0]: sys.stdout.write("Usage: %s\n" % usage) else: sys.stdout.write(" %s\n" % usage) else: if self.name: sys.stdout.write("Usage: %s" % self.name.split()[0]) else: sys.stdout.write("Usage: %s" % sys.argv[0]) for opt in self.opt: sys.stdout.write(" [%s]" % ", ".join(opt.names)) for pos in self.pos: sys.stdout.write(self.render_arg(pos)) sys.stdout.write("\n") if self.pos is None: pass
[docs] def format_help(self, columns): if columns is None: self.columns = 79 else: self.columns = columns if self.name: application_name = self.name.split()[0] else: application_name = sys.argv[0] self._format_help_name() self._format_help_synopsis(application_name) self._format_help_description() self._format_help_operands() self._format_help_options() self._format_exit_status()
def _format_help_name(self): if self.name: sys.stdout.write("%s\n" % get_bold_text("NAME")) for line in wrap(self.name, self.columns, replace_whitespace=False): sys.stdout.write("%s\n" % indent(line, " ")) def _format_help_synopsis(self, application_name): sys.stdout.write("\n%s\n" % get_bold_text("SYNOPSIS")) if self.synopsis: for synopsis_variation in self.synopsis: for line in wrap(synopsis_variation, self.columns, replace_whitespace=False): sys.stdout.write( "%s\n" % indent( line.replace(application_name, get_bold_text(application_name)), " ") ) else: if self.name: sys.stdout.write(" %s" % get_bold_text(self.name.split()[0])) else: sys.stdout.write(" %s" % get_bold_text(sys.argv[0])) for opt in self.opt: sys.stdout.write(" [%s]" % ", ".join(opt.names)) for pos in self.pos: sys.stdout.write(self.render_arg(pos)) sys.stdout.write("\n") def _format_help_description(self): if self.description: sys.stdout.write("\n%s\n" % get_bold_text("DESCRIPTION")) for line in wrap(self.description, self.columns, replace_whitespace=False): sys.stdout.write("%s\n" % indent(line, " ")) def _format_help_operands(self): if self.pos: sys.stdout.write("\n%s\n" % get_bold_text("OPERANDS")) max_size = max(len(x.names[0]) for x in self.pos) for pos in self.pos: the_name = pos.names[0] pos.help = pos.help[0].upper() + pos.help[1:] the_help = wrap(pos.help, self.columns - max_size - 4) sys.stdout.write(indent(get_bold_text(the_name), " ")) for help_line in the_help: if help_line == the_help[0]: sys.stdout.write(indent(help_line, " " * int(max_size - len(the_name) + 2))) sys.stdout.write("\n") else: sys.stdout.write(indent(help_line, " " * int(max_size + 4))) sys.stdout.write("\n") def _format_help_options(self): if self.opt: sys.stdout.write("\n%s\n" % get_bold_text("OPTIONS")) max_size = max(len(", ".join(x.names)) for x in self.opt) for opt in self.opt: the_name = ", ".join(opt.names) opt.help = opt.help[0].upper() + opt.help[1:] the_help = wrap(opt.help, self.columns - max_size - 4) sys.stdout.write(indent(get_bold_text(the_name), " ")) for help_line in the_help: if help_line == the_help[0]: sys.stdout.write(indent(help_line, " " * int(max_size - len(the_name) + 2))) sys.stdout.write("\n") else: sys.stdout.write(indent(help_line, " " * int(max_size + 4))) sys.stdout.write("\n") def _format_exit_status(self): if self.exit_status: sys.stdout.write("\n%s\n" % get_bold_text("EXIT STATUS")) max_size = max(len(exit_code) for exit_code, description in self.exit_status.items()) for exit_code, description in self.exit_status.items(): sys.stdout.write(indent(get_bold_text(exit_code), " ")) if description: the_help = wrap(description, self.columns - 4) for help_line in the_help: if help_line == the_help[0]: sys.stdout.write(indent(help_line, " " * int(max_size - len(exit_code) + 2))) sys.stdout.write("\n") else: sys.stdout.write(indent(help_line, " " * int(max_size + 4))) sys.stdout.write("\n") else: sys.stdout.write("\n")
[docs] def print_usage(self): self.format_usage()
[docs] def print_help(self, columns=None): self.format_help(columns=columns)
[docs] class FileType: """Factory for creating file object types Instances of FileType are typically passed as type= arguments to the ArgumentParser add_argument() method. Keyword Arguments: - mode -- A string indicating how the file is to be opened. Accepts the same values as the builtin open() function. - bufsize -- The file's desired buffer size. Accepts the same values as the builtin open() function. - encoding -- The file's encoding. Accepts the same values as the builtin open() function. - errors -- A string indicating how encoding and decoding errors are to be handled. Accepts the same value as the builtin open() function. """ def __init__(self, mode="r", bufsize=-1, encoding=None, errors=None): self._mode = mode self._bufsize = bufsize self._encoding = encoding self._errors = errors def __call__(self, string): # the special argument "-" means sys.std{in,out} if string == "-": if "r" in self._mode: return sys.stdin if "w" in self._mode: return sys.stdout raise ValueError('argument "-" with mode %r' % self._mode) # all other arguments are used as file names try: return open(string, self._mode, self._bufsize, self._encoding, self._errors) except OSError as e: args = {"filename": string, "error": e} message = "can't open '%(filename)s': %(error)s" raise TypeError(message % args) from e def __repr__(self): args = self._mode, self._bufsize kwargs = [("encoding", self._encoding), ("errors", self._errors)] args_str = ", ".join( [repr(arg) for arg in args if arg != -1] + ["%s=%r" % (kw, arg) for kw, arg in kwargs if arg is not None] ) return "%s(%s)" % (type(self).__name__, args_str)

Top » Module code » glxshell.lib.argparse.argparse

© Copyright 2020-2024, Galaxie Shell Team.
This page is licensed under the Creative Commons Attribution-NonCommercial-ShareAlike 4.0 International Public License (CC BY-NC-SA 4.0).
Examples, recipes, and other code in the documentation are additionally licensed under the Zero Clause BSD License.
See History and License for more information.

Last updated on None.
Created using Sphinx 8.0.2.