Todo-list¶
Todo
Close the click-extra-side gaps the sections below identify:
a
@persistent_optiondecorator (or apersistent=Truekwarg on@option) registering an option on a group and injecting it into every subcommand at decoration time, covering the inherited-flags family Click has consistently declined;populate
ctx.paramsduring shell completion, so a completion callback can depend on parameter values already typed on the command line;native
NushellCompleteandPowerShellCompleteclasses, for users without thecarapacebinary the Carapace spec needs;a
@completion_optionbundling multi-shell detection and auto-install, matching Typer’s--install-completion.
(The original entry is located in /home/runner/work/click-extra/click-extra/docs/benchmark.md, line 71.)
Todo
Mark a required flag group once
carapace-sh/carapace-spec#437 ships a Command key for cobra’s
MarkFlagsOneRequired. It closes two gaps at once: a required boolean pair
(--foo / --no-foo) reaches the spec unmarked, since ! marks one flag at a
time and either spelling satisfies Click; and Cloup’s RequireAtLeast
constraint is dropped for want of anywhere to put it.
(The original entry is located in /home/runner/work/click-extra/click-extra/click_extra/carapace.py:docstring of click_extra.carapace, line 36.)
Todo
Propose addition of meta keyword upstream to Click.
(The original entry is located in /home/runner/work/click-extra/click-extra/click_extra/context.py:docstring of click_extra.context.Context, line 20.)
Todo
Re-scope this override once cloup ships the fix for
janluke/cloup#225.
Cloup’s own with_() collects its arguments from a fixed locals(),
so it rejects every slot this subclass adds. That reason expires with
the fix; what stays is returning the same instance when a style is
unchanged, and the message naming an unrecognized argument. The same
issue also fixes dark() and light(), shadowed below.
(The original entry is located in /home/runner/work/click-extra/click-extra/click_extra/theme.py:docstring of click_extra.theme.HelpTheme.with_, line 5.)
Todo
Delete this method and light(), along with _from_cloup(),
once cloup ships the fix for
janluke/cloup#225.
Cloup declares both as static methods naming HelpTheme in their
return expression, so the inherited ones hand back a bare
cloup.HelpTheme carrying none of the slots below.
(The original entry is located in /home/runner/work/click-extra/click-extra/click_extra/theme.py:docstring of click_extra.theme.HelpTheme.dark, line 6.)
Todo
Re-scope __eq__() and __hash__() once cloup ships the fix for
janluke/cloup#224. Cloup
declares its lazy _style_kwargs cache without compare=False, so a
cloup.Style stops comparing equal to its twin, and hash() raises
TypeError, from its first call onwards. Both methods stay after that fix,
for the cross-class comparison against cloup.Style the generated ones
refuse: only their cache rationale expires.
(The original entry is located in /home/runner/work/click-extra/click-extra/click_extra/styling.py:docstring of click_extra.styling.Style, line 7.)
Todo
Drop the # type: ignore[assignment] on the fg and bg re-declarations
below once cloup widens its own annotations. It types both Optional[str],
while click.style takes int | tuple[int, int, int] | str | None, so
covering a palette index and an RGB tuple here reads as an incompatible
override. Asked upstream at
janluke/cloup#222.
(The original entry is located in /home/runner/work/click-extra/click-extra/click_extra/styling.py:docstring of click_extra.styling.Style, line 18.)
Todo
Support case-folding, so we can have the Straße string matching the
Strasse content.
This could be tricky as it messes with string length and characters index, which our logic relies on.
Danger
Danger
Roundtrip through lower-casing/upper-casing is a can of worms, because some characters change length when their case is changed:
(The original entry is located in /home/runner/work/click-extra/click-extra/click_extra/highlight.py:docstring of click_extra.highlight.highlight, line 6.)
Todo
Let the -v/-q counter reach beyond the current LogLevel range, as
sketched by the -vvvv (trace) and -q (silence everything) notes that used
to live on _VerbosityOption:
a
TRACEpseudo-level belowLogLevel.DEBUG(numeric value5, mirroringlogging.DEBUG - 5) so repeated-vcan surface finer-grained tracing pastDEBUG;a
SILENTpseudo-level aboveLogLevel.CRITICAL(any value abovelogging.CRITICAL) so repeated-qcan suppress every record, includingLogLevel.CRITICAL.
Both require extending LogLevel, which ripples into the --verbosity
EnumChoice, the Formatter level-name color
lookup and the level-ordering tests. They are intentionally left out of the
symmetric-counter change that introduced -q, where the counter simply clamps
at DEBUG/CRITICAL.
(The original entry is located in /home/runner/work/click-extra/click-extra/click_extra/logging.py:docstring of click_extra.logging, line 3.)
Todo
Drop click_extra._utils.memoize_enums() and both its call sites, here and in
click_extra.version.VersionOption.__deepcopy__(), once this package’s
Click floor reaches the release carrying
pallets/click#3805. That pull
request gives Sentinel its own __copy__, __deepcopy__ and __reduce_ex__,
so a member survives a copy unaided and the memo seeding buys nothing. It is
slated for Click 8.5.1, against a floor of 8.4.1 here.
(The original entry is located in /home/runner/work/click-extra/click-extra/click_extra/multicall.py:docstring of click_extra.multicall, line 73.)
Todo
Upstream pallets/click#3827
asks whether Option should keep the case of an identifier declaration,
as it does today, or fold it the way Argument already does. Should Click
fold both, no parameter can be named Foo_Bar any more: drop the caution
above, and with it the ambiguity branch of _merge_into_template in
click_extra.config.schema, which exists only to tell two such names
apart.
(The original entry is located in /home/runner/work/click-extra/click-extra/click_extra/parameters.py:docstring of click_extra.parameters.canonical_param_name, line 29.)
Todo
Upstream pallets/click#3821
splits the spec half of Option.get_help_record() into its own
get_help_spec() method, which returns it even for hidden options.
Once a Click release ships it, drop the monkey-patching below and call
that method directly.
(The original entry is located in /home/runner/work/click-extra/click-extra/click_extra/parameters.py:docstring of click_extra.parameters.get_param_spec, line 10.)
Todo
Read a full-screen program through pyte behind an optional extra, should picturing one ever be asked for. The screen below would stay the default, so the common case keeps costing no dependency.
(The original entry is located in /home/runner/work/click-extra/click-extra/click_extra/recording.py:docstring of click_extra.recording, line 20.)
Todo
Split the documentation stack into a standalone extra-docs project, should it
keep growing away from the CLI framework hosting it. It would take this package,
click_extra.pygments, click_extra.mkdocs, the MyST converters in
click_extra.myst_converter and click_extra.rst_to_myst, and the
marker-region primitives repomatic keeps in its own docs/docs_update.py. The
open question is the click:source and click:run directives: they invoke a
Click CLI, so either they stay here, or extra-docs depends on click-extra.
(The original entry is located in /home/runner/work/click-extra/click-extra/click_extra/sphinx/__init__.py:docstring of click_extra.sphinx, line 9.)
Todo
Remove this module entirely once click-extra drops Python 3.10. myst-parser
5.0 requires Python 3.11, and that is what holds the test dependency group at
myst-parser>=4, resolved to 4.0.1 below Python 3.11 and to 5.1.0 above it;
the docs group already sits at >=5.1.
Moving that floor is not enough on its own, because none of this repository’s
floors reaches a consumer: nothing declares myst-parser, so a project still on
myst-parser 4.x would lose its alert rendering with no error to show for it.
Declare myst-parser>=5.1 in the sphinx extra in the same change, then delete
this module, the setup-time version gate
(click_extra.sphinx.MYST_NATIVE_ALERTS_VERSION) and the optional
myst_parser import it reads, the log message pointing projects at the upstream
extension, and the MYST_HAS_NATIVE_ALERTS switch the Sphinx test suite
branches on.
(The original entry is located in /home/runner/work/click-extra/click-extra/click_extra/sphinx/alerts.py:docstring of click_extra.sphinx.alerts, line 16.)
Todo
Retire the MyST content_offset workaround once the pinned myst-parser
floor rises past the release carrying the fix:
delete
_myst_content_offset_inflation()and this constant, and collapseClickDirective.abs_content_offsetonto its rST branch (content_offsetverbatim);drop the
directive.contentfallback inclick_extra.sphinx._base.directive_source(), which stays offblock_textonly because that attribute is body-only inmyst-parser <= 5.1.0(#1164 is merged but unreleased). A releasedblock_textanchors a robust line-number computation and retires the workaround from both sides.
The single-trailing-blank-line case documented on
_myst_content_offset_inflation() stays off by one until then, and no
local fix can reach it: the round-trip consumes that line without a trace.
(The original entry is located in /home/runner/work/click-extra/click-extra/click_extra/sphinx/click.py:docstring of click_extra.sphinx.click.MYST_CONTENT_OFFSET_INFLATED_MAX, line 16.)
Todo
Declare TerminatedEchoingStdin instead of rewriting the
__class__ of the instance Click already built. That needs Click to
make EchoingStdin overridable: an echo_stdin_class attribute on
click.testing.CliRunner, say, that isolation() instantiates
rather than hard-coding. Worth proposing upstream.
(The original entry is located in /home/runner/work/click-extra/click-extra/click_extra/sphinx/click.py:docstring of click_extra.sphinx.click.ClickRunner.isolation, line 3.)
Todo
Propose the deduplication upstream, as a sphinx.ext.todo feature rather
than a third-party hook.
The repetition is a property of how autodoc renders a docstring, not of how
a project writes one, so every autodoc project documenting a module twice
hits it and none of them can fix it in their own source: :no-index: reads
like the cure and is not.
sphinx.ext.todo.TodoListProcessor already flattens the whole domain
in one place, which is where a todo_deduplicate config value would apply;
the two helpers this module needed (todo_identity() and
is_reexport()) are the whole of the logic.
Should it land, keep this module as a shim for the Sphinx releases below that floor, then drop it once the floor moves past them.
(The original entry is located in /home/runner/work/click-extra/click-extra/click_extra/sphinx/todos.py:docstring of click_extra.sphinx.todos, line 28.)
Todo
Open a narrowly-scoped Click issue and PR for a public
click.Context accessor returning a parameter’s resolved
(value, ParameterSource) after parsing, without re-firing eager callbacks.
That is the forward resolution --params actually consumes, and landing it
retires the re-parse this constant exists to feed.
Reference pallets/click#1279
as related, not as home: it asks for the inverse direction (reconstructing a
normalized argv from a Context), was scoped with about a dozen normalization
rules, flagged underdefined, and has stalled since 2023. Tracked in
docs/upstream.md under “Normalized arguments”; the developer note below
records why the cheaper alternatives do not work.
(The original entry is located in /home/runner/work/click-extra/click-extra/click_extra/context.py:docstring of click_extra.context.RAW_ARGS, line 9.)