Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
82 changes: 41 additions & 41 deletions cmd2/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -65,56 +65,56 @@
)

__all__: list[str] = [ # noqa: RUF022
'COMMAND_NAME',
'DEFAULT_SHORTCUTS',
"COMMAND_NAME",
"DEFAULT_SHORTCUTS",
# Argparse Exports
'Cmd2ArgumentParser',
'register_argparse_argument_parameter',
'set_default_ap_completer_type',
'set_default_argument_parser_type',
"Cmd2ArgumentParser",
"register_argparse_argument_parameter",
"set_default_ap_completer_type",
"set_default_argument_parser_type",
# Cmd2
'Cmd',
'CommandResult',
'CommandSet',
'Statement',
"Cmd",
"CommandResult",
"CommandSet",
"Statement",
# Colors
'Color',
"Color",
# Completion
'Choices',
'CompletionItem',
'Completions',
"Choices",
"CompletionItem",
"Completions",
# Decorators
'with_argument_list',
'with_argparser',
'with_category',
'as_subcommand_to',
"with_argument_list",
"with_argparser",
"with_category",
"as_subcommand_to",
# Exceptions
'Cmd2ArgparseError',
'CommandSetRegistrationError',
'CompletionError',
'PassThroughException',
'SkipPostcommandHooks',
"Cmd2ArgparseError",
"CommandSetRegistrationError",
"CompletionError",
"PassThroughException",
"SkipPostcommandHooks",
# modules
'plugin',
'rich_utils',
'string_utils',
"plugin",
"rich_utils",
"string_utils",
# Rich Utils
'ArgumentDefaultsCmd2HelpFormatter',
'Cmd2HelpFormatter',
'get_theme',
'MetavarTypeCmd2HelpFormatter',
'RawDescriptionCmd2HelpFormatter',
'RawTextCmd2HelpFormatter',
'RichPrintKwargs',
'set_theme',
'TextGroup',
"ArgumentDefaultsCmd2HelpFormatter",
"Cmd2HelpFormatter",
"get_theme",
"MetavarTypeCmd2HelpFormatter",
"RawDescriptionCmd2HelpFormatter",
"RawTextCmd2HelpFormatter",
"RichPrintKwargs",
"set_theme",
"TextGroup",
# String Utils
'stylize',
"stylize",
# Styles,
'Cmd2Style',
"Cmd2Style",
# Utilities
'categorize',
'CustomCompletionSettings',
'Settable',
'set_default_str_sort_key',
"categorize",
"CustomCompletionSettings",
"Settable",
"set_default_str_sort_key",
]
30 changes: 15 additions & 15 deletions cmd2/argparse_completer.py
Original file line number Diff line number Diff line change
Expand Up @@ -46,15 +46,15 @@

# Name of the choice/completer function argument that, if present, will be passed a dictionary of
# command line tokens up through the token being completed mapped to their argparse destination name.
ARG_TOKENS = 'arg_tokens'
ARG_TOKENS = "arg_tokens"


def _build_hint(parser: Cmd2ArgumentParser, arg_action: argparse.Action) -> str:
"""Build completion hint for a given argument."""
# Check if hinting is disabled for this argument
suppress_hint = arg_action.get_suppress_tab_hint() # type: ignore[attr-defined]
if suppress_hint or arg_action.help == argparse.SUPPRESS:
return ''
return ""

# Use the parser's help formatter to display just this action's help text
formatter = parser._get_formatter()
Expand Down Expand Up @@ -90,7 +90,7 @@ def _looks_like_flag(token: str, parser: Cmd2ArgumentParser) -> bool:
return False

# Flags can't have a space
return ' ' not in token
return " " not in token


class _ArgumentState:
Expand Down Expand Up @@ -133,8 +133,8 @@ def __init__(self, flag_arg_state: _ArgumentState) -> None:

:param flag_arg_state: information about the unfinished flag action.
"""
arg = f'{argparse._get_action_name(flag_arg_state.action)}'
err = f'{build_range_error(flag_arg_state.min, flag_arg_state.max)}'
arg = f"{argparse._get_action_name(flag_arg_state.action)}"
err = f"{build_range_error(flag_arg_state.min, flag_arg_state.max)}"
error = f"Error: argument {arg}: {err} ({flag_arg_state.count} entered)"
super().__init__(error)

Expand All @@ -158,7 +158,7 @@ class ArgparseCompleter:
def __init__(
self,
parser: Cmd2ArgumentParser,
cmd2_app: 'Cmd',
cmd2_app: "Cmd",
*,
parent_tokens: Mapping[str, MutableSequence[str]] | None = None,
) -> None:
Expand Down Expand Up @@ -269,14 +269,14 @@ def consume_argument(arg_state: _ArgumentState, arg_token: str) -> None:

# If we're in a flag REMAINDER arg, force all future tokens to go to that until a double dash is hit
if flag_arg_state is not None and flag_arg_state.is_remainder:
if token == '--': # noqa: S105
if token == "--": # noqa: S105
flag_arg_state = None
else:
consume_argument(flag_arg_state, token)
continue

# Handle '--' which tells argparse all remaining arguments are non-flags
if token == '--' and not skip_remaining_flags: # noqa: S105
if token == "--" and not skip_remaining_flags: # noqa: S105
# Check if there is an unfinished flag
if (
flag_arg_state is not None
Expand Down Expand Up @@ -437,8 +437,8 @@ def _update_mutex_groups(
if arg_action == completer_action:
return

arg_str = f'{argparse._get_action_name(arg_action)}'
completer_str = f'{argparse._get_action_name(completer_action)}'
arg_str = f"{argparse._get_action_name(arg_action)}"
completer_str = f"{argparse._get_action_name(completer_action)}"
error = f"Error: argument {arg_str}: not allowed with argument {completer_str}"
raise CompletionError(error)

Expand Down Expand Up @@ -566,18 +566,18 @@ def _complete_flags(self, text: str, line: str, begidx: int, endidx: int, used_f
# For completion suggestions, group matched flags by action
items: list[CompletionItem] = []
for action, option_strings in matched_actions.items():
flag_text = ', '.join(option_strings)
flag_text = ", ".join(option_strings)

# Mark optional flags with brackets
if not action.required:
flag_text = '[' + flag_text + ']'
flag_text = "[" + flag_text + "]"

# Use the first option string as the completion result for this action
items.append(
CompletionItem(
option_strings[0],
display=flag_text,
display_meta=action.help or '',
display_meta=action.help or "",
)
)

Expand Down Expand Up @@ -720,10 +720,10 @@ def _choices_to_items(self, arg_state: _ArgumentState) -> list[CompletionItem]:
for action in arg_state.action._choices_actions:
if action.dest in arg_state.action.choices:
subparser = arg_state.action.choices[action.dest]
parser_help[subparser] = action.help or ''
parser_help[subparser] = action.help or ""

return [
CompletionItem(name, display_meta=parser_help.get(subparser, ''))
CompletionItem(name, display_meta=parser_help.get(subparser, ""))
for name, subparser in arg_state.action.choices.items()
]

Expand Down
64 changes: 32 additions & 32 deletions cmd2/argparse_utils.py
Original file line number Diff line number Diff line change
Expand Up @@ -262,10 +262,10 @@ def build_range_error(range_min: int, range_max: float) -> str:
err_msg = "expected "

if range_max == constants.INFINITY:
plural = '' if range_min == 1 else 's'
plural = "" if range_min == 1 else "s"
err_msg += f"at least {range_min}"
else:
plural = '' if range_max == 1 else 's'
plural = "" if range_max == 1 else "s"
if range_min == range_max:
err_msg += f"{range_min}"
else:
Expand Down Expand Up @@ -309,8 +309,8 @@ def register_argparse_argument_parameter(
raise KeyError(f"'{param_name}' conflicts with an existing attribute on argparse.Action")

# Check if accessors already exist (e.g., from manual patching or previous registration)
getter_name = f'get_{param_name}'
setter_name = f'set_{param_name}'
getter_name = f"get_{param_name}"
setter_name = f"set_{param_name}"
if hasattr(argparse.Action, getter_name) or hasattr(argparse.Action, setter_name):
raise KeyError(f"Accessor methods for '{param_name}' already exist on argparse.Action")

Expand Down Expand Up @@ -355,11 +355,11 @@ def _validate_completion_callable(self: argparse.Action, value: Any) -> Any:

# Add new attributes to argparse.Action.
# See _ActionsContainer_add_argument() for details on these attributes.
register_argparse_argument_parameter('choices_provider', validator=_validate_completion_callable)
register_argparse_argument_parameter('completer', validator=_validate_completion_callable)
register_argparse_argument_parameter('table_columns')
register_argparse_argument_parameter('nargs_range')
register_argparse_argument_parameter('suppress_tab_hint')
register_argparse_argument_parameter("choices_provider", validator=_validate_completion_callable)
register_argparse_argument_parameter("completer", validator=_validate_completion_callable)
register_argparse_argument_parameter("table_columns")
register_argparse_argument_parameter("nargs_range")
register_argparse_argument_parameter("suppress_tab_hint")


############################################################################################################
Expand Down Expand Up @@ -431,11 +431,11 @@ def _ActionsContainer_add_argument( # noqa: N802
or not isinstance(nargs[0], int)
or not (isinstance(nargs[1], int) or nargs[1] == constants.INFINITY)
):
raise ValueError('Ranged values for nargs must be a tuple of 1 or 2 integers')
raise ValueError("Ranged values for nargs must be a tuple of 1 or 2 integers")
if nargs[0] >= nargs[1]:
raise ValueError('Invalid nargs range. The first value must be less than the second')
raise ValueError("Invalid nargs range. The first value must be less than the second")
if nargs[0] < 0:
raise ValueError('Negative numbers are invalid for nargs range')
raise ValueError("Negative numbers are invalid for nargs range")

# Save the nargs tuple as our range setting
nargs_range = nargs
Expand Down Expand Up @@ -465,7 +465,7 @@ def _ActionsContainer_add_argument( # noqa: N802
nargs_adjusted = nargs

# Add the argparse-recognized version of nargs to kwargs
kwargs['nargs'] = nargs_adjusted
kwargs["nargs"] = nargs_adjusted

# Extract registered custom keyword arguments
custom_attribs = {keyword: value for keyword, value in kwargs.items() if keyword in _CUSTOM_ACTION_ATTRIBS}
Expand All @@ -484,7 +484,7 @@ def _ActionsContainer_add_argument( # noqa: N802

# Set other registered custom attributes
for keyword, value in custom_attribs.items():
attr_setter = getattr(new_arg, f'set_{keyword}', None)
attr_setter = getattr(new_arg, f"set_{keyword}", None)
if attr_setter is not None:
attr_setter(value)

Expand All @@ -506,17 +506,17 @@ def __init__(
epilog: RenderableType | None = None,
parents: Sequence[argparse.ArgumentParser] = (),
formatter_class: type[Cmd2HelpFormatter] = Cmd2HelpFormatter,
prefix_chars: str = '-',
prefix_chars: str = "-",
fromfile_prefix_chars: str | None = None,
argument_default: str | None = None,
conflict_handler: str = 'error',
conflict_handler: str = "error",
add_help: bool = True,
allow_abbrev: bool = True,
exit_on_error: bool = True,
suggest_on_error: bool = False,
color: bool = False,
*,
ap_completer_type: type['ArgparseCompleter'] | None = None,
ap_completer_type: type["ArgparseCompleter"] | None = None,
) -> None:
"""Initialize the Cmd2ArgumentParser instance.

Expand Down Expand Up @@ -651,7 +651,7 @@ def update_prog(self, prog: str) -> None:
subcmd_parser.update_prog(subcmd_prog)
updated_parsers.add(subcmd_parser)

def _find_parser(self, subcommand_path: Iterable[str]) -> 'Cmd2ArgumentParser':
def _find_parser(self, subcommand_path: Iterable[str]) -> "Cmd2ArgumentParser":
"""Find a parser in the hierarchy based on a sequence of subcommand names.

:param subcommand_path: sequence of subcommand names leading to the target parser
Expand All @@ -670,7 +670,7 @@ def attach_subcommand(
self,
subcommand_path: Iterable[str],
subcommand: str,
subcommand_parser: 'Cmd2ArgumentParser',
subcommand_parser: "Cmd2ArgumentParser",
**add_parser_kwargs: Any,
) -> None:
"""Attach a parser as a subcommand to a command at the specified path.
Expand Down Expand Up @@ -719,7 +719,7 @@ def attach_subcommand(
for alias in add_parser_kwargs.get("aliases", ()):
subparsers_action._name_parser_map[alias] = subcommand_parser

def detach_subcommand(self, subcommand_path: Iterable[str], subcommand: str) -> 'Cmd2ArgumentParser':
def detach_subcommand(self, subcommand_path: Iterable[str], subcommand: str) -> "Cmd2ArgumentParser":
"""Detach a subcommand from a command at the specified path.

:param subcommand_path: sequence of subcommand names leading to the parser hosting the
Expand Down Expand Up @@ -753,13 +753,13 @@ def detach_subcommand(self, subcommand_path: Iterable[str], subcommand: str) ->

def error(self, message: str) -> NoReturn:
"""Override that applies custom formatting to the error message."""
lines = message.split('\n')
formatted_message = ''
lines = message.split("\n")
formatted_message = ""
for linum, line in enumerate(lines):
if linum == 0:
formatted_message = 'Error: ' + line
formatted_message = "Error: " + line
else:
formatted_message += '\n ' + line
formatted_message += "\n " + line

self.print_usage(sys.stderr)

Expand All @@ -769,27 +769,27 @@ def error(self, message: str) -> NoReturn:
console.print(formatted_message, style=Cmd2Style.ERROR)
formatted_message = f"{capture.get()}"

self.exit(2, f'{formatted_message}\n')
self.exit(2, f"{formatted_message}\n")

def _get_formatter(self, **kwargs: Any) -> Cmd2HelpFormatter:
"""Override with customizations for Cmd2HelpFormatter."""
return cast(Cmd2HelpFormatter, super()._get_formatter(**kwargs))

def format_help(self) -> str:
"""Override to add a newline."""
return super().format_help() + '\n'
return super().format_help() + "\n"

def _get_nargs_pattern(self, action: argparse.Action) -> str:
"""Override to support nargs ranges."""
nargs_range = action.get_nargs_range() # type: ignore[attr-defined]
if nargs_range:
range_max = '' if nargs_range[1] == constants.INFINITY else nargs_range[1]
nargs_pattern = f'(-*A{{{nargs_range[0]},{range_max}}}-*)'
range_max = "" if nargs_range[1] == constants.INFINITY else nargs_range[1]
nargs_pattern = f"(-*A{{{nargs_range[0]},{range_max}}}-*)"

# if this is an optional action, -- is not allowed
if action.option_strings:
nargs_pattern = nargs_pattern.replace('-*', '')
nargs_pattern = nargs_pattern.replace('-', '')
nargs_pattern = nargs_pattern.replace("-*", "")
nargs_pattern = nargs_pattern.replace("-", "")
return nargs_pattern

return super()._get_nargs_pattern(action)
Expand Down Expand Up @@ -823,8 +823,8 @@ def _check_value(self, action: argparse.Action, value: Any) -> None:
if action.choices is not None and value not in action.choices:
# If any choice is a CompletionItem, then display its value property.
choices = [c.value if isinstance(c, CompletionItem) else c for c in action.choices]
args = {'value': value, 'choices': ', '.join(map(repr, choices))}
msg = _('invalid choice: %(value)r (choose from %(choices)s)')
args = {"value": value, "choices": ", ".join(map(repr, choices))}
msg = _("invalid choice: %(value)r (choose from %(choices)s)")
raise ArgumentError(action, msg % args)


Expand Down
Loading
Loading