diff options
Diffstat (limited to 'Lib/argparse.py')
-rw-r--r-- | Lib/argparse.py | 128 |
1 files changed, 59 insertions, 69 deletions
diff --git a/Lib/argparse.py b/Lib/argparse.py index c0dcd0bbff0..83258cf3e0f 100644 --- a/Lib/argparse.py +++ b/Lib/argparse.py @@ -167,7 +167,6 @@ class HelpFormatter(object): indent_increment=2, max_help_position=24, width=None, - prefix_chars='-', color=False, ): # default setting for width @@ -176,16 +175,7 @@ class HelpFormatter(object): width = shutil.get_terminal_size().columns width -= 2 - from _colorize import ANSIColors, NoColors, can_colorize, decolor - - if color and can_colorize(): - self._ansi = ANSIColors() - self._decolor = decolor - else: - self._ansi = NoColors - self._decolor = lambda text: text - - self._prefix_chars = prefix_chars + self._set_color(color) self._prog = prog self._indent_increment = indent_increment self._max_help_position = min(max_help_position, @@ -202,9 +192,20 @@ class HelpFormatter(object): self._whitespace_matcher = _re.compile(r'\s+', _re.ASCII) self._long_break_matcher = _re.compile(r'\n\n\n+') + def _set_color(self, color): + from _colorize import can_colorize, decolor, get_theme + + if color and can_colorize(): + self._theme = get_theme(force_color=True).argparse + self._decolor = decolor + else: + self._theme = get_theme(force_no_color=True).argparse + self._decolor = lambda text: text + # =============================== # Section and indentation methods # =============================== + def _indent(self): self._current_indent += self._indent_increment self._level += 1 @@ -237,14 +238,12 @@ class HelpFormatter(object): # add the heading if the section was non-empty if self.heading is not SUPPRESS and self.heading is not None: - bold_blue = self.formatter._ansi.BOLD_BLUE - reset = self.formatter._ansi.RESET - current_indent = self.formatter._current_indent heading_text = _('%(heading)s:') % dict(heading=self.heading) + t = self.formatter._theme heading = ( f'{" " * current_indent}' - f'{bold_blue}{heading_text}{reset}\n' + f'{t.heading}{heading_text}{t.reset}\n' ) else: heading = '' @@ -258,6 +257,7 @@ class HelpFormatter(object): # ======================== # Message building methods # ======================== + def start_section(self, heading): self._indent() section = self._Section(self, self._current_section, heading) @@ -301,6 +301,7 @@ class HelpFormatter(object): # ======================= # Help-formatting methods # ======================= + def format_help(self): help = self._root_section.format_help() if help: @@ -314,10 +315,7 @@ class HelpFormatter(object): if part and part is not SUPPRESS]) def _format_usage(self, usage, actions, groups, prefix): - bold_blue = self._ansi.BOLD_BLUE - bold_magenta = self._ansi.BOLD_MAGENTA - magenta = self._ansi.MAGENTA - reset = self._ansi.RESET + t = self._theme if prefix is None: prefix = _('usage: ') @@ -325,15 +323,15 @@ class HelpFormatter(object): # if usage is specified, use that if usage is not None: usage = ( - magenta + t.prog_extra + usage - % {"prog": f"{bold_magenta}{self._prog}{reset}{magenta}"} - + reset + % {"prog": f"{t.prog}{self._prog}{t.reset}{t.prog_extra}"} + + t.reset ) # if no optionals or positionals are available, usage is just prog elif usage is None and not actions: - usage = f"{bold_magenta}{self._prog}{reset}" + usage = f"{t.prog}{self._prog}{t.reset}" # if optionals and positionals are available, calculate usage elif usage is None: @@ -411,23 +409,16 @@ class HelpFormatter(object): usage = '\n'.join(lines) usage = usage.removeprefix(prog) - usage = f"{bold_magenta}{prog}{reset}{usage}" + usage = f"{t.prog}{prog}{t.reset}{usage}" # prefix with 'usage:' - return f'{bold_blue}{prefix}{reset}{usage}\n\n' + return f'{t.usage}{prefix}{t.reset}{usage}\n\n' def _format_actions_usage(self, actions, groups): return ' '.join(self._get_actions_usage_parts(actions, groups)) def _is_long_option(self, string): - return len(string) >= 2 and string[1] in self._prefix_chars - - def _is_short_option(self, string): - return ( - not self._is_long_option(string) - and len(string) >= 1 - and string[0] in self._prefix_chars - ) + return len(string) > 2 def _get_actions_usage_parts(self, actions, groups): # find group indices and identify actions in groups @@ -452,10 +443,7 @@ class HelpFormatter(object): # collect all actions format strings parts = [] - cyan = self._ansi.CYAN - green = self._ansi.GREEN - yellow = self._ansi.YELLOW - reset = self._ansi.RESET + t = self._theme for action in actions: # suppressed arguments are marked with None @@ -465,7 +453,11 @@ class HelpFormatter(object): # produce all arg strings elif not action.option_strings: default = self._get_default_metavar_for_positional(action) - part = green + self._format_args(action, default) + reset + part = ( + t.summary_action + + self._format_args(action, default) + + t.reset + ) # if it's in a group, strip the outer [] if action in group_actions: @@ -475,26 +467,26 @@ class HelpFormatter(object): # produce the first way to invoke the option in brackets else: option_string = action.option_strings[0] + if self._is_long_option(option_string): + option_color = t.summary_long_option + else: + option_color = t.summary_short_option # if the Optional doesn't take a value, format is: # -s or --long if action.nargs == 0: part = action.format_usage() - if self._is_long_option(part): - part = f"{cyan}{part}{reset}" - elif self._is_short_option(part): - part = f"{green}{part}{reset}" + part = f"{option_color}{part}{t.reset}" # if the Optional takes a value, format is: # -s ARGS or --long ARGS else: default = self._get_default_metavar_for_optional(action) args_string = self._format_args(action, default) - if self._is_long_option(option_string): - option_string = f"{cyan}{option_string}" - elif self._is_short_option(option_string): - option_string = f"{green}{option_string}" - part = f"{option_string} {yellow}{args_string}{reset}" + part = ( + f"{option_color}{option_string} " + f"{t.summary_label}{args_string}{t.reset}" + ) # make it look optional if it's not required or in a group if not action.required and action not in group_actions: @@ -590,17 +582,14 @@ class HelpFormatter(object): return self._join_parts(parts) def _format_action_invocation(self, action): - bold_green = self._ansi.BOLD_GREEN - bold_cyan = self._ansi.BOLD_CYAN - bold_yellow = self._ansi.BOLD_YELLOW - reset = self._ansi.RESET + t = self._theme if not action.option_strings: default = self._get_default_metavar_for_positional(action) return ( - bold_green + t.action + ' '.join(self._metavar_formatter(action, default)(1)) - + reset + + t.reset ) else: @@ -609,11 +598,9 @@ class HelpFormatter(object): parts = [] for s in strings: if self._is_long_option(s): - parts.append(f"{bold_cyan}{s}{reset}") - elif self._is_short_option(s): - parts.append(f"{bold_green}{s}{reset}") + parts.append(f"{t.long_option}{s}{t.reset}") else: - parts.append(s) + parts.append(f"{t.short_option}{s}{t.reset}") return parts # if the Optional doesn't take a value, format is: @@ -628,7 +615,7 @@ class HelpFormatter(object): default = self._get_default_metavar_for_optional(action) option_strings = color_option_strings(action.option_strings) args_string = ( - f"{bold_yellow}{self._format_args(action, default)}{reset}" + f"{t.label}{self._format_args(action, default)}{t.reset}" ) return ', '.join(option_strings) + ' ' + args_string @@ -1483,6 +1470,7 @@ class _ActionsContainer(object): # ==================== # Registration methods # ==================== + def register(self, registry_name, value, object): registry = self._registries.setdefault(registry_name, {}) registry[value] = object @@ -1493,6 +1481,7 @@ class _ActionsContainer(object): # ================================== # Namespace default accessor methods # ================================== + def set_defaults(self, **kwargs): self._defaults.update(kwargs) @@ -1512,6 +1501,7 @@ class _ActionsContainer(object): # ======================= # Adding argument actions # ======================= + def add_argument(self, *args, **kwargs): """ add_argument(dest, ..., name=value, ...) @@ -1544,7 +1534,7 @@ class _ActionsContainer(object): action_name = kwargs.get('action') action_class = self._pop_action_class(kwargs) if not callable(action_class): - raise ValueError('unknown action {action_class!r}') + raise ValueError(f'unknown action {action_class!r}') action = action_class(**kwargs) # raise an error if action for positional argument does not @@ -1937,6 +1927,7 @@ class ArgumentParser(_AttributeHolder, _ActionsContainer): # ======================= # Pretty __repr__ methods # ======================= + def _get_kwargs(self): names = [ 'prog', @@ -1951,6 +1942,7 @@ class ArgumentParser(_AttributeHolder, _ActionsContainer): # ================================== # Optional/Positional adding methods # ================================== + def add_subparsers(self, **kwargs): if self._subparsers is not None: raise ValueError('cannot have multiple subparser arguments') @@ -2004,6 +1996,7 @@ class ArgumentParser(_AttributeHolder, _ActionsContainer): # ===================================== # Command line argument parsing methods # ===================================== + def parse_args(self, args=None, namespace=None): args, argv = self.parse_known_args(args, namespace) if argv: @@ -2598,6 +2591,7 @@ class ArgumentParser(_AttributeHolder, _ActionsContainer): # ======================== # Value conversion methods # ======================== + def _get_values(self, action, arg_strings): # optional argument produces a default when not present if not arg_strings and action.nargs == OPTIONAL: @@ -2697,6 +2691,7 @@ class ArgumentParser(_AttributeHolder, _ActionsContainer): # ======================= # Help-formatting methods # ======================= + def format_usage(self): formatter = self._get_formatter() formatter.add_usage(self.usage, self._actions, @@ -2727,20 +2722,14 @@ class ArgumentParser(_AttributeHolder, _ActionsContainer): return formatter.format_help() def _get_formatter(self): - if isinstance(self.formatter_class, type) and issubclass( - self.formatter_class, HelpFormatter - ): - return self.formatter_class( - prog=self.prog, - prefix_chars=self.prefix_chars, - color=self.color, - ) - else: - return self.formatter_class(prog=self.prog) + formatter = self.formatter_class(prog=self.prog) + formatter._set_color(self.color) + return formatter # ===================== # Help-printing methods # ===================== + def print_usage(self, file=None): if file is None: file = _sys.stdout @@ -2762,6 +2751,7 @@ class ArgumentParser(_AttributeHolder, _ActionsContainer): # =============== # Exiting methods # =============== + def exit(self, status=0, message=None): if message: self._print_message(message, _sys.stderr) |