Skip to content

Use type hinting generics In standard collections #1377

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 1 commit into from
Nov 10, 2024
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
4 changes: 1 addition & 3 deletions cmd2/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -11,8 +11,6 @@
# package is not installed
pass

from typing import List

from . import plugin
from .ansi import (
Bg,
Expand Down Expand Up @@ -64,7 +62,7 @@
categorize,
)

__all__: List[str] = [
__all__: list[str] = [
'COMMAND_NAME',
'DEFAULT_SHORTCUTS',
# ANSI Exports
Expand Down
9 changes: 4 additions & 5 deletions cmd2/ansi.py
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,6 @@
from typing import (
IO,
Any,
List,
Optional,
cast,
)
Expand Down Expand Up @@ -992,11 +991,11 @@ def style(
:raises: TypeError if bg isn't None or a subclass of BgColor
:return: the stylized string
"""
# List of strings that add style
additions: List[AnsiSequence] = []
# list of strings that add style
additions: list[AnsiSequence] = []

# List of strings that remove style
removals: List[AnsiSequence] = []
# list of strings that remove style
removals: list[AnsiSequence] = []

# Process the style settings
if fg is not None:
Expand Down
40 changes: 19 additions & 21 deletions cmd2/argparse_completer.py
Original file line number Diff line number Diff line change
Expand Up @@ -14,8 +14,6 @@
)
from typing import (
TYPE_CHECKING,
Dict,
List,
Optional,
Type,
Union,
Expand Down Expand Up @@ -172,7 +170,7 @@ class ArgparseCompleter:
"""Automatic command line tab completion based on argparse parameters"""

def __init__(
self, parser: argparse.ArgumentParser, cmd2_app: 'Cmd', *, parent_tokens: Optional[Dict[str, List[str]]] = None
self, parser: argparse.ArgumentParser, cmd2_app: 'Cmd', *, parent_tokens: Optional[dict[str, list[str]]] = None
) -> None:
"""
Create an ArgparseCompleter
Expand Down Expand Up @@ -213,8 +211,8 @@ def __init__(
self._subcommand_action = action

def complete(
self, text: str, line: str, begidx: int, endidx: int, tokens: List[str], *, cmd_set: Optional[CommandSet] = None
) -> List[str]:
self, text: str, line: str, begidx: int, endidx: int, tokens: list[str], *, cmd_set: Optional[CommandSet] = None
) -> list[str]:
"""
Complete text using argparse metadata

Expand Down Expand Up @@ -245,13 +243,13 @@ def complete(
flag_arg_state: Optional[_ArgumentState] = None

# Non-reusable flags that we've parsed
matched_flags: List[str] = []
matched_flags: list[str] = []

# Keeps track of arguments we've seen and any tokens they consumed
consumed_arg_values: Dict[str, List[str]] = dict() # dict(arg_name -> List[tokens])
consumed_arg_values: dict[str, list[str]] = dict() # dict(arg_name -> l[tokens])

# Completed mutually exclusive groups
completed_mutex_groups: Dict[argparse._MutuallyExclusiveGroup, argparse.Action] = dict()
completed_mutex_groups: dict[argparse._MutuallyExclusiveGroup, argparse.Action] = dict()

def consume_argument(arg_state: _ArgumentState) -> None:
"""Consuming token as an argument"""
Expand Down Expand Up @@ -507,7 +505,7 @@ def update_mutex_groups(arg_action: argparse.Action) -> None:

return completion_results

def _complete_flags(self, text: str, line: str, begidx: int, endidx: int, matched_flags: List[str]) -> List[str]:
def _complete_flags(self, text: str, line: str, begidx: int, endidx: int, matched_flags: list[str]) -> list[str]:
"""Tab completion routine for a parsers unused flags"""

# Build a list of flags that can be tab completed
Expand All @@ -524,7 +522,7 @@ def _complete_flags(self, text: str, line: str, begidx: int, endidx: int, matche
matches = self._cmd2_app.basic_complete(text, line, begidx, endidx, match_against)

# Build a dictionary linking actions with their matched flag names
matched_actions: Dict[argparse.Action, List[str]] = dict()
matched_actions: dict[argparse.Action, list[str]] = dict()
for flag in matches:
action = self._flag_to_action[flag]
matched_actions.setdefault(action, [])
Expand All @@ -541,14 +539,14 @@ def _complete_flags(self, text: str, line: str, begidx: int, endidx: int, matche

return matches

def _format_completions(self, arg_state: _ArgumentState, completions: Union[List[str], List[CompletionItem]]) -> List[str]:
def _format_completions(self, arg_state: _ArgumentState, completions: Union[list[str], list[CompletionItem]]) -> list[str]:
"""Format CompletionItems into hint table"""

# Nothing to do if we don't have at least 2 completions which are all CompletionItems
if len(completions) < 2 or not all(isinstance(c, CompletionItem) for c in completions):
return cast(List[str], completions)
return cast(list[str], completions)

completion_items = cast(List[CompletionItem], completions)
completion_items = cast(list[CompletionItem], completions)

# Check if the data being completed have a numerical type
all_nums = all(isinstance(c.orig_value, numbers.Number) for c in completion_items)
Expand Down Expand Up @@ -616,17 +614,17 @@ def _format_completions(self, arg_state: _ArgumentState, completions: Union[List
self._cmd2_app.formatted_completions = hint_table.generate_table(table_data, row_spacing=0)

# Return sorted list of completions
return cast(List[str], completions)
return cast(list[str], completions)

def complete_subcommand_help(self, text: str, line: str, begidx: int, endidx: int, tokens: List[str]) -> List[str]:
def complete_subcommand_help(self, text: str, line: str, begidx: int, endidx: int, tokens: list[str]) -> list[str]:
"""
Supports cmd2's help command in the completion of subcommand names
:param text: the string prefix we are attempting to match (all matches must begin with it)
:param line: the current input line with leading whitespace removed
:param begidx: the beginning index of the prefix text
:param endidx: the ending index of the prefix text
:param tokens: arguments passed to command/subcommand
:return: List of subcommand completions
:return: list of subcommand completions
"""
# If our parser has subcommands, we must examine the tokens and check if they are subcommands
# If so, we will let the subcommand's parser handle the rest of the tokens via another ArgparseCompleter.
Expand All @@ -645,7 +643,7 @@ def complete_subcommand_help(self, text: str, line: str, begidx: int, endidx: in
break
return []

def format_help(self, tokens: List[str]) -> str:
def format_help(self, tokens: list[str]) -> str:
"""
Supports cmd2's help command in the retrieval of help text
:param tokens: arguments passed to help command
Expand All @@ -672,17 +670,17 @@ def _complete_arg(
begidx: int,
endidx: int,
arg_state: _ArgumentState,
consumed_arg_values: Dict[str, List[str]],
consumed_arg_values: dict[str, list[str]],
*,
cmd_set: Optional[CommandSet] = None,
) -> List[str]:
) -> list[str]:
"""
Tab completion routine for an argparse argument
:return: list of completions
:raises: CompletionError if the completer or choices function this calls raises one
"""
# Check if the arg provides choices to the user
arg_choices: Union[List[str], ChoicesCallable]
arg_choices: Union[list[str], ChoicesCallable]
if arg_state.action.choices is not None:
arg_choices = list(arg_state.action.choices)
if not arg_choices:
Expand Down Expand Up @@ -739,7 +737,7 @@ def _complete_arg(
# Otherwise use basic_complete on the choices
else:
# Check if the choices come from a function
completion_items: List[str] = []
completion_items: list[str] = []
if isinstance(arg_choices, ChoicesCallable):
if not arg_choices.is_completer:
choices_func = arg_choices.choices_provider
Expand Down
48 changes: 22 additions & 26 deletions cmd2/argparse_custom.py
Original file line number Diff line number Diff line change
Expand Up @@ -250,15 +250,11 @@ def my_completer(self, text, line, begidx, endidx, arg_tokens)
TYPE_CHECKING,
Any,
Callable,
Dict,
Iterable,
List,
NoReturn,
Optional,
Protocol,
Sequence,
Set,
Tuple,
Type,
Union,
cast,
Expand Down Expand Up @@ -350,7 +346,7 @@ class ChoicesProviderFuncBase(Protocol):
Function that returns a list of choices in support of tab completion
"""

def __call__(self) -> List[str]: ... # pragma: no cover
def __call__(self) -> list[str]: ... # pragma: no cover


@runtime_checkable
Expand All @@ -359,7 +355,7 @@ class ChoicesProviderFuncWithTokens(Protocol):
Function that returns a list of choices in support of tab completion and accepts a dictionary of prior arguments.
"""

def __call__(self, *, arg_tokens: Dict[str, List[str]] = {}) -> List[str]: ... # pragma: no cover
def __call__(self, *, arg_tokens: dict[str, list[str]] = {}) -> list[str]: ... # pragma: no cover


ChoicesProviderFunc = Union[ChoicesProviderFuncBase, ChoicesProviderFuncWithTokens]
Expand All @@ -377,7 +373,7 @@ def __call__(
line: str,
begidx: int,
endidx: int,
) -> List[str]: ... # pragma: no cover
) -> list[str]: ... # pragma: no cover


@runtime_checkable
Expand All @@ -394,8 +390,8 @@ def __call__(
begidx: int,
endidx: int,
*,
arg_tokens: Dict[str, List[str]] = {},
) -> List[str]: ... # pragma: no cover
arg_tokens: dict[str, list[str]] = {},
) -> list[str]: ... # pragma: no cover


CompleterFunc = Union[CompleterFuncBase, CompleterFuncWithTokens]
Expand Down Expand Up @@ -598,7 +594,7 @@ def _action_set_descriptive_header(self: argparse.Action, descriptive_header: Op
############################################################################################################
# Patch argparse.Action with accessors for nargs_range attribute
############################################################################################################
def _action_get_nargs_range(self: argparse.Action) -> Optional[Tuple[int, Union[int, float]]]:
def _action_get_nargs_range(self: argparse.Action) -> Optional[tuple[int, Union[int, float]]]:
"""
Get the nargs_range attribute of an argparse Action.

Expand All @@ -609,13 +605,13 @@ def _action_get_nargs_range(self: argparse.Action) -> Optional[Tuple[int, Union[
:param self: argparse Action being queried
:return: The value of nargs_range or None if attribute does not exist
"""
return cast(Optional[Tuple[int, Union[int, float]]], getattr(self, ATTR_NARGS_RANGE, None))
return cast(Optional[tuple[int, Union[int, float]]], getattr(self, ATTR_NARGS_RANGE, None))


setattr(argparse.Action, 'get_nargs_range', _action_get_nargs_range)


def _action_set_nargs_range(self: argparse.Action, nargs_range: Optional[Tuple[int, Union[int, float]]]) -> None:
def _action_set_nargs_range(self: argparse.Action, nargs_range: Optional[tuple[int, Union[int, float]]]) -> None:
"""
Set the nargs_range attribute of an argparse Action.

Expand Down Expand Up @@ -673,7 +669,7 @@ def _action_set_suppress_tab_hint(self: argparse.Action, suppress_tab_hint: bool
# Allow developers to add custom action attributes
############################################################################################################

CUSTOM_ACTION_ATTRIBS: Set[str] = set()
CUSTOM_ACTION_ATTRIBS: set[str] = set()
_CUSTOM_ATTRIB_PFX = '_attr_'


Expand Down Expand Up @@ -746,7 +742,7 @@ def _action_set_custom_parameter(self: argparse.Action, value: Any) -> None:
def _add_argument_wrapper(
self: argparse._ActionsContainer,
*args: Any,
nargs: Union[int, str, Tuple[int], Tuple[int, int], Tuple[int, float], None] = None,
nargs: Union[int, str, tuple[int], tuple[int, int], tuple[int, float], None] = None,
choices_provider: Optional[ChoicesProviderFunc] = None,
completer: Optional[CompleterFunc] = None,
suppress_tab_hint: bool = False,
Expand Down Expand Up @@ -797,7 +793,7 @@ def _add_argument_wrapper(
nargs_range = None

if nargs is not None:
nargs_adjusted: Union[int, str, Tuple[int], Tuple[int, int], Tuple[int, float], None]
nargs_adjusted: Union[int, str, tuple[int], tuple[int, int], tuple[int, float], None]
# Check if nargs was given as a range
if isinstance(nargs, tuple):
# Handle 1-item tuple by setting max to INFINITY
Expand Down Expand Up @@ -847,7 +843,7 @@ def _add_argument_wrapper(
kwargs['nargs'] = nargs_adjusted

# Extract registered custom keyword arguments
custom_attribs: Dict[str, Any] = {}
custom_attribs: dict[str, Any] = {}
for keyword, value in kwargs.items():
if keyword in CUSTOM_ACTION_ATTRIBS:
custom_attribs[keyword] = value
Expand Down Expand Up @@ -1124,9 +1120,9 @@ def _format_usage(
# End cmd2 customization

# helper for wrapping lines
def get_lines(parts: List[str], indent: str, prefix: Optional[str] = None) -> List[str]:
lines: List[str] = []
line: List[str] = []
def get_lines(parts: list[str], indent: str, prefix: Optional[str] = None) -> list[str]:
lines: list[str] = []
line: list[str] = []
if prefix is not None:
line_len = len(prefix) - 1
else:
Expand Down Expand Up @@ -1188,7 +1184,7 @@ def _format_action_invocation(self, action: argparse.Action) -> str:
return metavar

else:
parts: List[str] = []
parts: list[str] = []

# if the Optional doesn't take a value, format is:
# -s, --long
Expand All @@ -1209,8 +1205,8 @@ def _format_action_invocation(self, action: argparse.Action) -> str:
def _determine_metavar(
self,
action: argparse.Action,
default_metavar: Union[str, Tuple[str, ...]],
) -> Union[str, Tuple[str, ...]]:
default_metavar: Union[str, tuple[str, ...]],
) -> Union[str, tuple[str, ...]]:
"""Custom method to determine what to use as the metavar value of an action"""
if action.metavar is not None:
result = action.metavar
Expand All @@ -1226,19 +1222,19 @@ def _determine_metavar(
def _metavar_formatter(
self,
action: argparse.Action,
default_metavar: Union[str, Tuple[str, ...]],
) -> Callable[[int], Tuple[str, ...]]:
default_metavar: Union[str, tuple[str, ...]],
) -> Callable[[int], tuple[str, ...]]:
metavar = self._determine_metavar(action, default_metavar)

def format(tuple_size: int) -> Tuple[str, ...]:
def format(tuple_size: int) -> tuple[str, ...]:
if isinstance(metavar, tuple):
return metavar
else:
return (metavar,) * tuple_size

return format

def _format_args(self, action: argparse.Action, default_metavar: Union[str, Tuple[str, ...]]) -> str:
def _format_args(self, action: argparse.Action, default_metavar: Union[str, tuple[str, ...]]) -> str:
"""Customized to handle ranged nargs and make other output less verbose"""
metavar = self._determine_metavar(action, default_metavar)
metavar_formatter = self._metavar_formatter(action, default_metavar)
Expand Down
Loading
Loading