Skip to content

Commit e6790c3

Browse files
chore: minor clean up
1 parent 5727076 commit e6790c3

1 file changed

Lines changed: 21 additions & 8 deletions

File tree

cmd2/annotated.py

Lines changed: 21 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -458,7 +458,7 @@ def _resolve_tuple(_tp: Any, args: tuple[Any, ...], *, has_default: bool = False
458458
first = args[0]
459459
if not all(a == first for a in args[1:]):
460460
raise TypeError(
461-
f"tuple[{', '.join(a.__name__ if hasattr(a, '__name__') else str(a) for a in args)}] "
461+
f"tuple[{', '.join(_type_name(a) for a in args)}] "
462462
f"has mixed element types which is not currently supported because argparse "
463463
f"can only apply a single type= converter per argument. "
464464
f"Use tuple[T, T] (same type) or tuple[T, ...] instead."
@@ -505,6 +505,22 @@ def _resolve_enum(tp: Any, _args: tuple[Any, ...], **_ctx: Any) -> dict[str, Any
505505
}
506506

507507

508+
# -- Helpers ------------------------------------------------------------------
509+
510+
511+
def _type_name(tp: Any) -> str:
512+
"""Best-effort type name for diagnostic messages."""
513+
return tp.__name__ if hasattr(tp, "__name__") else str(tp)
514+
515+
516+
def _nargs_yields_list(nargs: Any) -> bool:
517+
"""Return ``True`` when an argparse ``nargs`` value produces a list at parse time.
518+
519+
``nargs=1`` is included: argparse returns ``[value]``, not the bare value.
520+
"""
521+
return nargs in ("*", "+") or (isinstance(nargs, int) and nargs >= 1)
522+
523+
508524
def _resolve_type(
509525
tp: type,
510526
*,
@@ -553,22 +569,19 @@ def _resolve_type(
553569
if metadata:
554570
kwargs.update(metadata.to_kwargs())
555571

556-
type_repr = tp.__name__ if hasattr(tp, "__name__") else str(tp)
557572
nargs_val = kwargs.get("nargs")
558573

559574
# A fixed-arity type (e.g. ``tuple[T, T]``) declares its own nargs;
560575
# user metadata cannot override it to a different value.
561576
if isinstance(resolver_nargs, int) and nargs_val != resolver_nargs:
562577
raise TypeError(
563-
f"nargs={nargs_val!r} conflicts with the fixed arity of '{type_repr}' (expected nargs={resolver_nargs})."
578+
f"nargs={nargs_val!r} conflicts with the fixed arity of '{_type_name(tp)}' (expected nargs={resolver_nargs})."
564579
)
565580

566581
# nargs that produces a list of values requires a collection annotation.
567-
# Catches mistakes like ``Annotated[str, Argument(nargs=2)]`` where the
568-
# parameter is typed as a scalar but argparse will hand back a list.
569-
if not kwargs.get("is_collection") and (nargs_val in ("*", "+") or (isinstance(nargs_val, int) and nargs_val >= 1)):
582+
if not kwargs.get("is_collection") and _nargs_yields_list(nargs_val):
570583
raise TypeError(
571-
f"nargs={nargs_val!r} produces a list of values, but the annotation '{type_repr}' is not a collection type. "
584+
f"nargs={nargs_val!r} produces a list of values, but the annotation '{_type_name(tp)}' is not a collection type. "
572585
f"Use list[T], tuple[T, ...], or set[T] (optionally with | None) to match."
573586
)
574587

@@ -613,7 +626,7 @@ def _unwrap_optional(tp: type) -> tuple[type, bool]:
613626
f"Unexpected single-element Union without None: Union[{non_none[0]}]. "
614627
f"Use the type directly instead of wrapping in Union."
615628
)
616-
type_names = " | ".join(a.__name__ if hasattr(a, "__name__") else str(a) for a in non_none)
629+
type_names = " | ".join(_type_name(a) for a in non_none)
617630
raise TypeError(f"Union type {type_names} is ambiguous for auto-resolution.")
618631
return tp, False
619632

0 commit comments

Comments
 (0)