Skip to content

Commit c35de2b

Browse files
committed
Define _CommandFunc to represent either a Bound or Ubound command function to make some types less restrictive
1 parent 5163c2d commit c35de2b

1 file changed

Lines changed: 18 additions & 10 deletions

File tree

‎cmd2/annotated.py‎

Lines changed: 18 additions & 10 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,
@@ -312,12 +313,16 @@ def do_build(self, target: str, common: CommonArgs):
312313
BoundCommandFunc,
313314
CmdOrSetT,
314315
UnboundChoicesProvider,
316+
UnboundCommandFunc,
315317
UnboundCompleter,
316318
)
317319

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

323+
# Parser construction works with a command method before or after descriptor binding.
324+
_CommandFunc: TypeAlias = BoundCommandFunc | UnboundCommandFunc[Any, ...]
325+
321326

322327
class Cmd2ParserKwargs(TypedDict, total=False):
323328
"""Forwarded ctor kwargs for [`Cmd2ArgumentParser`][cmd2.argparse_utils.Cmd2ArgumentParser] (PEP 692 ``Unpack``).
@@ -2119,7 +2124,7 @@ def _link_mutex_group_membership(
21192124
by_name[name].mutex_group_indices.append(index)
21202125

21212126

2122-
def _resolve_func_hints(func: BoundCommandFunc, *, 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]:
21232128
"""Resolve the type hints for the parameters that become arguments.
21242129
21252130
The bound first parameter (self/cls), the injected ``skip_params``, and the ``return`` annotation
@@ -2297,7 +2302,7 @@ def _block_field_dest(spec: _BlockSpec, field_name: str) -> str:
22972302
return _shared_field_dest(spec.dc_type, field_name) if spec.shared else field_name
22982303

22992304

2300-
def _dataclass_blocks(func: BoundCommandFunc, *, skip_params: frozenset[str] = _SKIP_PARAMS) -> dict[str, _BlockSpec]:
2305+
def _dataclass_blocks(func: _CommandFunc, *, skip_params: frozenset[str] = _SKIP_PARAMS) -> dict[str, _BlockSpec]:
23012306
"""Map each dataclass-block parameter name to its :class:`_BlockSpec`.
23022307
23032308
Used by the runtime handler to reconstruct the dataclass instance from the parsed namespace. A
@@ -2321,7 +2326,7 @@ def _dataclass_blocks(func: BoundCommandFunc, *, skip_params: frozenset[str] = _
23212326

23222327

23232328
def _lazy_block_resolver(
2324-
func: BoundCommandFunc,
2329+
func: _CommandFunc,
23252330
*,
23262331
base_accepted: set[str],
23272332
skip_params: frozenset[str],
@@ -2378,7 +2383,7 @@ def _reconstruct_dataclass_blocks(func_kwargs: dict[str, Any], blocks: dict[str,
23782383

23792384

23802385
def _resolve_parameters(
2381-
func: BoundCommandFunc,
2386+
func: _CommandFunc,
23822387
*,
23832388
skip_params: frozenset[str] = _SKIP_PARAMS,
23842389
base_command: bool = False,
@@ -2722,7 +2727,7 @@ def _docstring_first_paragraph(doc: str | None) -> str | None:
27222727

27232728

27242729
def build_parser_from_function(
2725-
func: BoundCommandFunc,
2730+
func: _CommandFunc,
27262731
*,
27272732
skip_params: frozenset[str] = _SKIP_PARAMS,
27282733
groups: tuple[Group, ...] | None = None,
@@ -2797,7 +2802,7 @@ def build_parser_from_function(
27972802
return parser
27982803

27992804

2800-
def _derive_subcommand_name(func: BoundCommandFunc, subcommand_to: str) -> str:
2805+
def _derive_subcommand_name(func: _CommandFunc, subcommand_to: str) -> str:
28012806
"""Derive the subcommand name from the function name and validate the naming convention.
28022807
28032808
``subcommand_to='team member'`` + ``func.__name__='team_member_add'`` -> ``'add'``.
@@ -2833,7 +2838,7 @@ class _ParserBuildOptions:
28332838

28342839

28352840
def _make_parser_builder(
2836-
func: BoundCommandFunc,
2841+
func: _CommandFunc,
28372842
*,
28382843
skip_params: frozenset[str],
28392844
base_command: bool,
@@ -2872,12 +2877,12 @@ def parser_builder() -> Cmd2ArgumentParser:
28722877

28732878

28742879
def _build_subcommand_handler(
2875-
func: BoundCommandFunc,
2880+
func: _CommandFunc,
28762881
subcommand_to: str,
28772882
*,
28782883
base_command: bool = False,
28792884
options: _ParserBuildOptions,
2880-
) -> tuple[BoundCommandFunc, str, Callable[[], Cmd2ArgumentParser]]:
2885+
) -> tuple[_CommandFunc, str, Callable[[], Cmd2ArgumentParser]]:
28812886
"""Build a subcommand's parser and a handler that unpacks the Namespace into typed kwargs.
28822887
28832888
:param func: the subcommand handler function
@@ -2923,9 +2928,12 @@ def handler(self_arg: Any, ns: Any) -> Any:
29232928
_CommandParams = ParamSpec("_CommandParams")
29242929

29252930

2926-
class _AnnotatedCommand(BoundCommandFunc, Protocol[_CommandParams]):
2931+
class _AnnotatedCommand(Protocol[_CommandParams]):
29272932
"""A callable command method with the metadata used by ``with_annotated``."""
29282933

2934+
__name__: str
2935+
__qualname__: str
2936+
29292937
def __call__(self, *args: _CommandParams.args, **kwargs: _CommandParams.kwargs) -> bool | None: ...
29302938

29312939

0 commit comments

Comments
 (0)