Skip to content

Commit 2b22e91

Browse files
chore: clean up docs (#1671)
Updating docs as some of the links and rendering are broken.
1 parent 5765bb4 commit 2b22e91

5 files changed

Lines changed: 69 additions & 44 deletions

File tree

cmd2/annotated.py

Lines changed: 24 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,12 @@
11
"""Build argparse parsers from type-annotated function signatures.
22
3-
.. warning:: Experimental
3+
!!! warning "Experimental"
44
5-
This module is experimental and its behavior may change in future releases.
5+
This module is experimental and its behavior may change in future releases.
66
7-
The :func:`with_annotated` decorator inspects a command function's type hints and
8-
default values to build a ``Cmd2ArgumentParser``. :class:`Argument` and
9-
:class:`Option` metadata classes give finer per-parameter control via
7+
The [`with_annotated`][cmd2.annotated.with_annotated] decorator inspects a command function's type hints and
8+
default values to build a ``Cmd2ArgumentParser``. [`Argument`][cmd2.annotated.Argument] and
9+
[`Option`][cmd2.annotated.Option] metadata classes give finer per-parameter control via
1010
``typing.Annotated``.
1111
1212
Parameters without defaults become positional arguments; parameters with defaults
@@ -18,7 +18,7 @@
1818
flag (``dry_run`` -> ``--dry-run``); pass an explicit ``Option("--my_flag")`` to opt out.
1919
Positional-only parameters (before ``/``) and ``**kwargs`` raise ``TypeError``. The parameter
2020
names ``dest`` and ``subcommand`` are reserved; ``cmd2_statement`` receives the parsed
21-
``Statement`` and (with ``base_command=True``) ``cmd2_handler`` receives the subcommand handler::
21+
``Statement`` and (with ``base_command=True``) ``cmd2_handler`` receives the subcommand handler:
2222
2323
class MyApp(cmd2.Cmd):
2424
@cmd2.with_annotated
@@ -27,8 +27,8 @@ def do_greet(self, name: str, count: int = 1, loud: bool = False):
2727
msg = f"Hello {name}"
2828
self.poutput(msg.upper() if loud else msg)
2929
30-
Use ``Annotated`` with :class:`Argument` or :class:`Option` for finer
31-
control over individual parameters::
30+
Use ``Annotated`` with [`Argument`][cmd2.annotated.Argument] or [`Option`][cmd2.annotated.Option] for finer
31+
control over individual parameters:
3232
3333
from typing import Annotated
3434
@@ -84,7 +84,7 @@ def do_paint(
8484
converted ``VALUE``); the ``const`` is stored verbatim and must match the declared type.
8585
``const`` is validated against the declared type and is rejected on a positional ``Argument`` (argparse
8686
ignores it there)
87-
- a custom :class:`argparse.Action` subclass -- passed straight through to ``add_argument``.
87+
- a custom `argparse.Action` subclass -- passed straight through to ``add_argument``.
8888
The user's class owns storage, so the collection-casting wrapper is dropped and the action-specific
8989
type/const/collection-shape constraints are skipped. The type-inferred converter, default, and
9090
``required`` are still applied; the action receives them like any hand-built ``add_argument`` call.
@@ -106,20 +106,20 @@ def do_paint(
106106
parameter, which maps to it -- a raw ``help`` would silently shadow it), and -- on ``Argument`` only
107107
-- ``action`` / ``required`` (which have no meaning on a positional). Every other ``add_argument``
108108
parameter, including those registered via
109-
:func:`~cmd2.argparse_utils.register_argparse_argument_parameter`, passes through unchanged.
109+
[`register_argparse_argument_parameter`][cmd2.argparse_utils.register_argparse_argument_parameter], passes through unchanged.
110110
111111
A ``default`` may be supplied either as the function-signature default (``param: T = v``) or as
112112
``Argument(default=v)`` / ``Option(default=v)`` -- the two forms are equivalent. Specifying both at
113113
once raises ``TypeError`` (the value would have two sources of truth), and ``argparse.SUPPRESS`` is
114114
rejected as a default from either source because it would remove the keyword argument the function
115115
expects.
116116
117-
Parser-level customization is forwarded to :class:`~cmd2.Cmd2ArgumentParser`'s constructor via PEP
117+
Parser-level customization is forwarded to [`Cmd2ArgumentParser`][cmd2.argparse_utils.Cmd2ArgumentParser]'s constructor via PEP
118118
692 ``**parser_kwargs: Unpack[Cmd2ParserKwargs]``. Anything the parser ctor accepts -- ``description``,
119119
``epilog``, ``prog``, ``usage``, ``parents``, ``argument_default``, ``prefix_chars``,
120120
``fromfile_prefix_chars``, ``conflict_handler``, ``add_help``, ``allow_abbrev``, ``exit_on_error``,
121121
``formatter_class``, ``ap_completer_type``, and on Python >= 3.14 ``suggest_on_error`` / ``color`` --
122-
flows straight through; the :class:`Cmd2ParserKwargs` ``TypedDict`` is the single source of truth
122+
flows straight through; the [`Cmd2ParserKwargs`][cmd2.annotated.Cmd2ParserKwargs] ``TypedDict`` is the single source of truth
123123
and gives type-checkers/IDEs autocomplete on the decorator's call site. ``parser_class`` stays as
124124
its own explicit kwarg because it selects the class itself, not a value passed to it. Two
125125
behaviors layer on top of the raw passthrough: if ``description`` is omitted, the first paragraph
@@ -218,7 +218,7 @@ def do_paint(
218218

219219

220220
class Cmd2ParserKwargs(TypedDict, total=False):
221-
"""Forwarded ctor kwargs for :class:`~cmd2.Cmd2ArgumentParser` (PEP 692 ``Unpack``).
221+
"""Forwarded ctor kwargs for [`Cmd2ArgumentParser`][cmd2.argparse_utils.Cmd2ArgumentParser] (PEP 692 ``Unpack``).
222222
223223
Single source of truth mirroring the parser's ``__init__``: add a field here to expose a new
224224
ctor kwarg on the decorator's call site. All optional (``total=False``); ``suggest_on_error``
@@ -302,7 +302,7 @@ def __init__(
302302
``default`` mirrors the signature default (``Option(default=v)`` == ``... = v``); supplying
303303
both, or ``argparse.SUPPRESS``, is rejected. ``extra_kwargs`` forwards any other
304304
``add_argument`` parameter (incl. those from
305-
:func:`~cmd2.argparse_utils.register_argparse_argument_parameter`) straight through.
305+
[`register_argparse_argument_parameter`][cmd2.argparse_utils.register_argparse_argument_parameter]) straight through.
306306
"""
307307
reserved = self._RESERVED_EXTRA_KWARGS & extra_kwargs.keys()
308308
if reserved:
@@ -362,7 +362,7 @@ def __init__(
362362
363363
``action`` is a supported string action (``store_true``/``store_false``/``count``/
364364
``append``/``extend``/``store_const``/``append_const``) or a custom
365-
:class:`argparse.Action` subclass (passed through; it owns storage, so the inferred
365+
`argparse.Action` subclass (passed through; it owns storage, so the inferred
366366
action and the action-specific constraints are skipped).
367367
"""
368368
super().__init__(**kwargs)
@@ -1940,16 +1940,16 @@ def build_parser_from_function(
19401940
) -> Cmd2ArgumentParser:
19411941
"""Inspect a function's signature and build a ``Cmd2ArgumentParser``.
19421942
1943-
The lower-level entry point behind :func:`with_annotated`. ``parser_kwargs`` is forwarded to
1944-
the parser ctor (see :class:`Cmd2ParserKwargs`); when ``description`` is omitted, the first
1943+
The lower-level entry point behind [`with_annotated`][cmd2.annotated.with_annotated]. ``parser_kwargs`` is forwarded to
1944+
the parser ctor (see [`Cmd2ParserKwargs`][cmd2.annotated.Cmd2ParserKwargs]); when ``description`` is omitted, the first
19451945
paragraph of ``func.__doc__`` is used.
19461946
19471947
:param func: the command function to inspect
19481948
:param skip_params: parameter names to exclude from the parser
1949-
:param groups: :class:`Group` instances assigning parameters to argument groups
1950-
:param mutually_exclusive_groups: :class:`Group` instances of mutually exclusive parameters
1949+
:param groups: [`Group`][cmd2.annotated.Group] instances assigning parameters to argument groups
1950+
:param mutually_exclusive_groups: [`Group`][cmd2.annotated.Group] instances of mutually exclusive parameters
19511951
:param parser_class: custom parser class (defaults to the configured default)
1952-
:param parser_kwargs: forwarded :class:`Cmd2ParserKwargs`
1952+
:param parser_kwargs: forwarded [`Cmd2ParserKwargs`][cmd2.annotated.Cmd2ParserKwargs]
19531953
:return: a fully configured ``Cmd2ArgumentParser``
19541954
"""
19551955
parser_cls = parser_class or DEFAULT_ARGUMENT_PARSER
@@ -2175,14 +2175,15 @@ def with_annotated(
21752175
:param help: subcommand help text (only with ``subcommand_to``)
21762176
:param aliases: alternative subcommand names (only with ``subcommand_to``)
21772177
:param deprecated: mark the subcommand deprecated in ``--help`` (only with ``subcommand_to``)
2178-
:param groups: :class:`Group` instances assigning parameters to titled argument groups
2179-
:param mutually_exclusive_groups: :class:`Group` instances of mutually exclusive parameters
2178+
:param groups: [`Group`][cmd2.annotated.Group] instances assigning parameters to titled argument groups
2179+
:param mutually_exclusive_groups: [`Group`][cmd2.annotated.Group] instances of mutually exclusive parameters
21802180
:param parser_class: custom parser class (defaults to the configured default)
21812181
:param subcommand_required: whether a subcommand must be supplied (``base_command`` only)
21822182
:param subcommand_metavar: metavar for the subcommands group (``base_command`` only)
21832183
:param subcommand_title: title for the subcommands ``--help`` section (``base_command`` only)
21842184
:param subcommand_description: description for that section (``base_command`` only)
2185-
:param parser_kwargs: any :class:`~cmd2.Cmd2ArgumentParser` ctor kwarg (see :class:`Cmd2ParserKwargs`).
2185+
:param parser_kwargs: any [`Cmd2ArgumentParser`][cmd2.argparse_utils.Cmd2ArgumentParser] ctor kwarg
2186+
(see [`Cmd2ParserKwargs`][cmd2.annotated.Cmd2ParserKwargs]).
21862187
``description`` defaults to the docstring's first paragraph when omitted;
21872188
``prog`` is rejected with ``subcommand_to`` (cmd2 rewrites it from the parent).
21882189
"""

docs/api/annotated.md

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
# cmd2.annotated
2+
3+
::: cmd2.annotated

docs/features/annotated.md

Lines changed: 40 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -155,21 +155,31 @@ Both `Argument` and `Option` accept the same cmd2-specific fields as `add_argume
155155
`Option` additionally accepts `action`, `required`, and positional `*names` for custom flag strings
156156
(e.g. `Option("--color", "-c")`).
157157

158+
### Actions
159+
158160
When an `Option(action=...)` uses a zero-argument argparse action that takes no value from the
159161
command line (`count`, `store_true`, `store_false`, `store_const`, `append_const`),
160-
`@with_annotated` removes the value-oriented metadata inferred from the type before calling
161-
`add_argument()`: the `type` converter, the static `choices`, and any inferred tab-completer (such
162-
as the path completer for `Path`) or `choices_provider`. This matches argparse behavior (which
163-
rejects a completer on a value-less action) and avoids parser-construction errors such as combining
164-
`action='count'` with `type=int`. Actions that do consume values (`append` / `extend` on a
165-
`list[T]`, or a plain value option) keep the inferred converter and completer. `action='help'` and
166-
`action='version'` are not supported.
162+
`@with_annotated` strips the value-oriented metadata it inferred from the type before calling
163+
`add_argument()`:
164+
165+
- the `type` converter,
166+
- the static `choices`, and
167+
- any inferred tab-completer (such as the path completer for `Path`) or `choices_provider`.
168+
169+
This matches argparse behavior (which rejects a completer on a value-less action) and avoids
170+
parser-construction errors such as combining `action='count'` with `type=int`. Actions that _do_
171+
consume values (`append` / `extend` on a `list[T]`, or a plain value option) keep the inferred
172+
converter and completer.
167173

168174
Pairing `const` with an explicit `nargs` on a scalar `Option` selects argparse's optional-value
169175
idiom instead of `store_const`. `Annotated[str | None, Option("--log", nargs='?', const="CONSOLE")]`
170-
keeps the `store` action and the inferred `type` converter, so the flag is three-way: absent yields
171-
the default, a bare `--log` yields the `const`, and `--log VALUE` yields the converted `VALUE`. The
172-
`const` is stored verbatim (it is not run through the converter), so it must already match the
176+
keeps the `store` action and the inferred `type` converter, so the flag is three-way:
177+
178+
- absent yields the default,
179+
- a bare `--log` yields the `const`, and
180+
- `--log VALUE` yields the converted `VALUE`.
181+
182+
The `const` is stored verbatim (it is not run through the converter), so it must already match the
173183
declared type. Without an explicit `nargs`, `const` alone still infers the value-less `store_const`
174184
(present yields the `const`, and supplying a value is an error).
175185

@@ -192,6 +202,8 @@ def do_shout(self, name: Annotated[str, Option("--name", action=UpperAction)] =
192202
`action='help'` and `action='version'` are not supported by `@with_annotated`; use `@with_argparser`
193203
if you need them.
194204

205+
### Reserved keyword arguments
206+
195207
`Argument()` and `Option()` refuse a handful of `add_argument()` kwargs that the decorator derives
196208
from the function signature itself, so misusing them surfaces as a clear `TypeError` instead of a
197209
silent override. The refused kwargs are:
@@ -204,6 +216,8 @@ silent override. The refused kwargs are:
204216
Every other `add_argument()` parameter passes through, including any custom parameter registered via
205217
[register_argparse_argument_parameter][cmd2.argparse_utils.register_argparse_argument_parameter].
206218

219+
### Defaults
220+
207221
A `default` may be supplied either through the function signature or as a metadata kwarg. The two
208222
forms are equivalent:
209223

@@ -223,6 +237,8 @@ Parser-construction kwargs such as `add_help`, `prefix_chars`, `fromfile_prefix_
223237
`argument_default`, `conflict_handler`, and `allow_abbrev` are not exposed by `@with_annotated`. Set
224238
them on a custom `parser_class` subclass and pass it via `parser_class=`.
225239

240+
### Choices and enums
241+
226242
When a user-supplied `choices_provider` or `completer` is given for an inferred `Enum` or `Literal`,
227243
the inferred static `choices` list is dropped so completion is driven by the provider or completer.
228244
The inferred `type` converter is preserved, so parsed values still coerce to the declared type
@@ -268,17 +284,10 @@ list the values.
268284
- `groups` -- `Group` instances assigning parameter names to argument groups
269285
- `mutually_exclusive_groups` -- `Group` instances of mutually exclusive parameters
270286
- `parser_class` -- a custom parser class (defaults to the configured default)
271-
- `**parser_kwargs` -- every other parser-construction kwarg accepted by `Cmd2ArgumentParser` is
272-
forwarded through PEP 692
273-
[`Unpack`][typing.Unpack][`[Cmd2ParserKwargs]`][cmd2.annotated.Cmd2ParserKwargs]: `description`,
274-
`epilog`, `prog`, `usage`, `parents`, `argument_default`, `prefix_chars`, `fromfile_prefix_chars`,
275-
`conflict_handler`, `add_help`, `allow_abbrev`, `exit_on_error`, `formatter_class`,
276-
`ap_completer_type`, and on Python ≥ 3.14 `suggest_on_error` / `color`. Two behaviors layer on
277-
top of the raw passthrough:
278-
- `description` -- when omitted, the first paragraph of the function's docstring (up to the
279-
first blank line) is used; pass an explicit value to override.
280-
- `prog` -- rejected when `subcommand_to` is set; cmd2's subcommand machinery rewrites `prog`
281-
from the parent command hierarchy and any value here would be silently overwritten.
287+
- `**parser_kwargs` -- every other `Cmd2ArgumentParser` constructor kwarg, forwarded through PEP 692
288+
[`Unpack[Cmd2ParserKwargs]`][cmd2.annotated.Cmd2ParserKwargs]. See
289+
[Parser customization](#parser-customization) below for the full list and the `description` /
290+
`prog` special cases.
282291

283292
```py
284293
@with_annotated(with_unknown_args=True)
@@ -296,6 +305,16 @@ the forwarded kwargs and gives type-checkers/IDEs autocomplete on the decorator'
296305
a new ctor kwarg to `Cmd2ArgumentParser` only needs a matching field on `Cmd2ParserKwargs`, and the
297306
annotated decorator picks it up automatically.
298307

308+
The forwarded kwargs are `description`, `epilog`, `prog`, `usage`, `parents`, `argument_default`,
309+
`prefix_chars`, `fromfile_prefix_chars`, `conflict_handler`, `add_help`, `allow_abbrev`,
310+
`exit_on_error`, `formatter_class`, `ap_completer_type`, and on Python ≥ 3.14 `suggest_on_error` /
311+
`color`. Two of them layer extra behavior on top of the raw passthrough:
312+
313+
- `description` -- when omitted, it is filled from the function's docstring (detailed below); pass
314+
an explicit value to override.
315+
- `prog` -- rejected when `subcommand_to` is set; cmd2's subcommand machinery rewrites `prog` from
316+
the parent command hierarchy, so any value here would be silently overwritten.
317+
299318
`parser_class` stays as its own explicit kwarg because it selects the class itself rather than a
300319
value passed to it. Argument groups are declared with [Group][cmd2.annotated.Group]; pass `title`
301320
and `description` for a titled help section (omit them for an untitled group):

docs/features/index.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@
33
<div class="grid cards" markdown>
44
<!--intro-start-->
55
- [Argument Processing](argument_processing.md)
6+
- [Annotated Argument Processing](annotated.md)
67
- [Async Commands](async_commands.md)
78
- [Builtin Commands](builtin_commands.md)
89
- [Clipboard Integration](clipboard.md)

mkdocs.yml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -196,6 +196,7 @@ nav:
196196
- API Reference:
197197
- api/index.md
198198
- api/cmd.md
199+
- api/annotated.md
199200
- api/argparse_completer.md
200201
- api/argparse_utils.md
201202
- api/clipboard.md

0 commit comments

Comments
 (0)