Skip to content

Commit 2c94add

Browse files
committed
Removed redundant _NamedCallable protocol class from cmd2/annotated.py
Changes include: 1. Removed _NamedCallable: Deleted the redundant protocol class definition of _NamedCallable from cmd2/annotated.py. 2. Imported type protocols: Imported BoundCommandFunc and UnboundCommandFunc from cmd2/types.py, and TypeAlias from typing. 3. Defined unified _CommandFunc alias: Formed a private, unified type alias _CommandFunc = BoundCommandFunc | UnboundCommandFunc[CmdOrSetT, [argparse.Namespace]]. 4. Updated function signatures: Replaced all annotations that previously used _NamedCallable in cmd2/annotated.py with _CommandFunc.
1 parent d5a0a1a commit 2c94add

2 files changed

Lines changed: 18 additions & 18 deletions

File tree

‎CHANGELOG.md‎

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -4,8 +4,9 @@
44
- Converted `BoundCommandFunc` and `UnboundCommandFunc` TypeAliases in `types.py` to Protocol
55
classes for stricter type checking on `cmd2` command method references
66
- Experimental features
7-
- Defined `_NamedCallable` protocol class in `annotated.py` to implement some stricter type
8-
checking on function references
7+
- Defined private, unified type alias `_CommandFunc` in `annotated.py` basead on
8+
`BoundCommandFunc` and `UnboundCommandFunc` to get the benefit of stricter type checking here
9+
as well
910

1011
## 4.2.2 (August 25, 2026)
1112

‎cmd2/annotated.py‎

Lines changed: 15 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -284,6 +284,7 @@ def do_build(self, target: str, common: CommonArgs):
284284
NamedTuple,
285285
ParamSpec,
286286
Protocol,
287+
TypeAlias,
287288
TypedDict,
288289
TypeGuard,
289290
TypeVar,
@@ -309,20 +310,18 @@ def do_build(self, target: str, common: CommonArgs):
309310
from .exceptions import Cmd2ArgparseError
310311
from .rich_utils import Cmd2HelpFormatter, HelpContent
311312
from .types import (
313+
BoundCommandFunc,
312314
CmdOrSetT,
313315
UnboundChoicesProvider,
316+
UnboundCommandFunc,
314317
UnboundCompleter,
315318
)
316319

317320
#: ``nargs`` values accepted by cmd2's patched ``add_argument`` (incl. ranged tuples).
318321
_NargsValue = int | str | tuple[int] | tuple[int, int] | tuple[int, float]
319322

320323

321-
class _NamedCallable(Protocol):
322-
__name__: str
323-
__qualname__: str
324-
325-
def __call__(self, *args: Any, **kwargs: Any) -> Any: ...
324+
_CommandFunc: TypeAlias = BoundCommandFunc | UnboundCommandFunc[CmdOrSetT, [argparse.Namespace]]
326325

327326

328327
class Cmd2ParserKwargs(TypedDict, total=False):
@@ -2125,7 +2124,7 @@ def _link_mutex_group_membership(
21252124
by_name[name].mutex_group_indices.append(index)
21262125

21272126

2128-
def _resolve_func_hints(func: _NamedCallable, *, skip_params: frozenset[str] = _SKIP_PARAMS) -> dict[str, Any]:
2127+
def _resolve_func_hints(func: _CommandFunc, *, skip_params: frozenset[str] = _SKIP_PARAMS) -> dict[str, Any]:
21292128
"""Resolve the type hints for the parameters that become arguments.
21302129
21312130
The bound first parameter (self/cls), the injected ``skip_params``, and the ``return`` annotation
@@ -2303,7 +2302,7 @@ def _block_field_dest(spec: _BlockSpec, field_name: str) -> str:
23032302
return _shared_field_dest(spec.dc_type, field_name) if spec.shared else field_name
23042303

23052304

2306-
def _dataclass_blocks(func: _NamedCallable, *, skip_params: frozenset[str] = _SKIP_PARAMS) -> dict[str, _BlockSpec]:
2305+
def _dataclass_blocks(func: _CommandFunc, *, skip_params: frozenset[str] = _SKIP_PARAMS) -> dict[str, _BlockSpec]:
23072306
"""Map each dataclass-block parameter name to its :class:`_BlockSpec`.
23082307
23092308
Used by the runtime handler to reconstruct the dataclass instance from the parsed namespace. A
@@ -2327,7 +2326,7 @@ def _dataclass_blocks(func: _NamedCallable, *, skip_params: frozenset[str] = _SK
23272326

23282327

23292328
def _lazy_block_resolver(
2330-
func: _NamedCallable,
2329+
func: _CommandFunc,
23312330
*,
23322331
base_accepted: set[str],
23332332
skip_params: frozenset[str],
@@ -2384,7 +2383,7 @@ def _reconstruct_dataclass_blocks(func_kwargs: dict[str, Any], blocks: dict[str,
23842383

23852384

23862385
def _resolve_parameters(
2387-
func: _NamedCallable,
2386+
func: _CommandFunc,
23882387
*,
23892388
skip_params: frozenset[str] = _SKIP_PARAMS,
23902389
base_command: bool = False,
@@ -2728,7 +2727,7 @@ def _docstring_first_paragraph(doc: str | None) -> str | None:
27282727

27292728

27302729
def build_parser_from_function(
2731-
func: _NamedCallable,
2730+
func: _CommandFunc,
27322731
*,
27332732
skip_params: frozenset[str] = _SKIP_PARAMS,
27342733
groups: tuple[Group, ...] | None = None,
@@ -2803,7 +2802,7 @@ def build_parser_from_function(
28032802
return parser
28042803

28052804

2806-
def _derive_subcommand_name(func: _NamedCallable, subcommand_to: str) -> str:
2805+
def _derive_subcommand_name(func: _CommandFunc, subcommand_to: str) -> str:
28072806
"""Derive the subcommand name from the function name and validate the naming convention.
28082807
28092808
``subcommand_to='team member'`` + ``func.__name__='team_member_add'`` -> ``'add'``.
@@ -2839,7 +2838,7 @@ class _ParserBuildOptions:
28392838

28402839

28412840
def _make_parser_builder(
2842-
func: _NamedCallable,
2841+
func: _CommandFunc,
28432842
*,
28442843
skip_params: frozenset[str],
28452844
base_command: bool,
@@ -2878,12 +2877,12 @@ def parser_builder() -> Cmd2ArgumentParser:
28782877

28792878

28802879
def _build_subcommand_handler(
2881-
func: _NamedCallable,
2880+
func: _CommandFunc,
28822881
subcommand_to: str,
28832882
*,
28842883
base_command: bool = False,
28852884
options: _ParserBuildOptions,
2886-
) -> tuple[_NamedCallable, str, Callable[[], Cmd2ArgumentParser]]:
2885+
) -> tuple[_CommandFunc, str, Callable[[], Cmd2ArgumentParser]]:
28872886
"""Build a subcommand's parser and a handler that unpacks the Namespace into typed kwargs.
28882887
28892888
:param func: the subcommand handler function
@@ -2964,7 +2963,7 @@ def with_annotated(
29642963

29652964

29662965
def with_annotated(
2967-
func: _NamedCallable | None = None,
2966+
func: _CommandFunc | None = None,
29682967
*,
29692968
ns_provider: Callable[..., argparse.Namespace] | None = None,
29702969
preserve_quotes: bool = False,
@@ -3043,7 +3042,7 @@ def with_annotated(
30433042
subcommand_description=subcommand_description,
30443043
)
30453044

3046-
def decorator(fn: _NamedCallable) -> _NamedCallable:
3045+
def decorator(fn: _CommandFunc) -> _CommandFunc:
30473046
if with_unknown_args:
30483047
unknown_param = inspect.signature(fn).parameters.get("_unknown")
30493048
if unknown_param is None:

0 commit comments

Comments
 (0)