Todo list¶

This page lists every pending item of the project. It collects the {todo} admonitions of the documentation pages and of the docstrings that autodoc renders. Each entry links back to where it is written, next to the code or the prose it acts on.

Many items wait on an upstream release: the ticket named in an item is what closes it.

Todo

Regroup the bug report helpers of kdeldycke/mail-deduplicate and kdeldycke/meta-package-manager in Click Extra, so every CLI built on it invites a report the same way:

Each project then keeps only the content of its own reports: the mail fingerprint, the override table.

(The original entry is located in /home/runner/work/click-extra/click-extra/docs/version.md, line 599.)

Todo

Drop the (target)= case from the cross-page caveat above once the myst-parser floor of the sphinx extra passes the release carrying executablebooks/MyST-Parser#1158, which resolves a link to a label on another page. That fix closes executablebooks/MyST-Parser#1151, and no release carries it yet.

(The original entry is located in /home/runner/work/click-extra/click-extra/docs/sphinx.md, line 1021.)

Todo

Drop CLOUP_METADATA_PROBE_VERSION from tests/test_commands.py once this package’s cloup floor is above 4.0.0. That release is the last to import importlib.metadata at module scope, which janluke/cloup#242 removes. The startup ballast list then names importlib.metadata and email unconditionally.

(The original entry is located in /home/runner/work/click-extra/click-extra/click_extra/__init__.py:docstring of click_extra, line 8.)

Todo

Delete _DEPRECATED_CLICK_EXPORTS, the loop dropping its bindings and its branch in __getattr__ once the Click floor reaches 9.0, which removes the five names it forwards.

(The original entry is located in /home/runner/work/click-extra/click-extra/click_extra/__init__.py:docstring of click_extra, line 18.)

Todo

Delete click_extra/blocks.py, the deprecated alias of click_extra.markdown.blocks, and its tests in tests/test_blocks.py in 11.0.0: its warnings announce that release.

(The original entry is located in /home/runner/work/click-extra/click-extra/click_extra/__init__.py:docstring of click_extra, line 25.)

Todo

Delete _tile_runs, _TILE_RUN and _TILE_RE from click_extra/capture/svg.py in 11.0.0, with the __getattr__ serving them as tile_runs, TILE_RUN and _TILING_RE, and their tests in tests/test_screenshots.py: its warnings announce that release.

(The original entry is located in /home/runner/work/click-extra/click-extra/click_extra/__init__.py:docstring of click_extra, line 32.)

Todo

Delete click_extra/sphinx/tabs.py, its setup call in click_extra/sphinx/__init__.py, tests/sphinx/test_sphinx_tabs.py, its NON_META_KEYS entry in tests/test_context.py and the vertical tab-sets section of docs/sphinx.md in 11.0.0: its warnings announce that release. Move its entry in docs/upstream.md to the upstreamed section.

(The original entry is located in /home/runner/work/click-extra/click-extra/click_extra/__init__.py:docstring of click_extra, line 40.)

Todo

Propose addition of meta keyword upstream to Click.

(The original entry is located in /home/runner/work/click-extra/click-extra/click_extra/commands.py:docstring of click_extra.commands.Context, line 20.)

Todo

Delete the human_readable_name override and _CLICK_HAS_PARAMETER_SPEC once this package’s Click floor reaches 8.6.0. From that release on, Click names a parameter by Parameter.spec, added by pallets/click#3877: a deprecation notice then names the option by its longest-prefixed flag.

(The original entry is located in /home/runner/work/click-extra/click-extra/click_extra/parameters.py:docstring of click_extra.parameters.Option, line 6.)

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 a live CLI needs: landing it retires the replay behind the --params table and the configuration dump. The click-extra wrap --params path keeps this constant and its replay, because Click never parses the foreign CLI it renders.

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.)

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

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

Stop turning a RuntimeError of the wait in _wait_result() back into the KeyboardInterrupt it replaced, once python/cpython#118433 is fixed in every free-threaded Python Click Extra supports.

(The original entry is located in /home/runner/work/click-extra/click-extra/click_extra/jobs.py:docstring of click_extra.jobs, line 8.)

Todo

Let the -v/-q counter reach beyond the LogLevel range, where it clamps at DEBUG and CRITICAL:

  • a TRACE pseudo-level below LogLevel.DEBUG (numeric value 5, mirroring logging.DEBUG - 5) so repeated -v can surface finer-grained tracing past DEBUG;

  • a SILENT pseudo-level above LogLevel.CRITICAL (any value above logging.CRITICAL) so repeated -q can suppress every record, including LogLevel.CRITICAL.

Both require extending LogLevel, which ripples into the --verbosity EnumChoice, the Formatter level-name color lookup and the level-ordering tests.

(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

Remove once the minimum supported Python is 3.15: its UTF-8 mode, on by default (PEP 686), makes the standard streams speak UTF-8 unless the environment asks otherwise.

(The original entry is located in /home/runner/work/click-extra/click-extra/click_extra/output.py:docstring of click_extra.output.force_unicode_output, line 17.)

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/param_tools.py:docstring of click_extra.param_tools.canonical_param_name, line 29.)

Todo

Drop the github patch of _setup_tabulate once a python-tabulate release ships astanin/python-tabulate#410: github then marks column alignment in its separator row, as pipe does.

(The original entry is located in /home/runner/work/click-extra/click-extra/click_extra/table.py:docstring of click_extra.table, line 3.)

Todo

Delete _pad_gfm_separator once a python-tabulate release ships astanin/python-tabulate#426: the separator rows of pipe and github then carry the padding mdformat writes.

(The original entry is located in /home/runner/work/click-extra/click-extra/click_extra/table.py:docstring of click_extra.table, line 10.)

Todo

Import NestedReferences from the root of extra_platforms, in place of the private extra_platforms._types._TNestedReferences, once extra-platforms 15.0.0 ships on PyPI and the floor of that dependency moves to >=15. extra-platforms 16.0.0 removes the private alias.

(The original entry is located in /home/runner/work/click-extra/click-extra/click_extra/test_suite.py:docstring of click_extra.test_suite, line 22.)

Todo

pallets/click#3896 adds a context_settings parameter to click.testing.CliRunner.invoke(). It sets the context color without the Command.main() patch in invoke().

On a Click release that carries it, this constant also catches context_settings, and the patch sends it to Context, which rejects it. On such a release, keep context_settings out of the collision set and pass force_color through it. Drop this constant and the patch once the Click floor of this package reaches that release.

(The original entry is located in /home/runner/work/click-extra/click-extra/click_extra/testing.py:docstring of click_extra.testing.INVOKE_ARGS, line 7.)

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 click_extra.markdown package with its MyST converters and marker-region primitives, and the ones 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

Collapse ContentOffsetMixin.abs_content_offset of click_extra.sphinx._base onto its rST branch (content_offset verbatim) once a myst-parser release carries the open rework #1175, which makes content_offset document-relative.

(The original entry is located in /home/runner/work/click-extra/click-extra/click_extra/sphinx/click.py:docstring of click_extra.sphinx.click, line 23.)

Todo

Delete TerminatedEchoingStdin and this override once the Click floor reaches the release that ships pallets/click#3878, targeted at 8.6.0: CliRunner(echo_stdin=True) then echoes the EOT byte as ^D itself.

(The original entry is located in /home/runner/work/click-extra/click-extra/click_extra/sphinx/click_runner.py:docstring of click_extra.sphinx.click_runner.ClickRunner.isolation, line 3.)

Todo

Re-scope this module once myst-parser parses an {eval-rst} block into the page’s own document, which executablebooks/MyST-Parser#1212 asks for in its item 3, and the sphinx extra’s myst-parser floor passes that release. The hook then only serves the python:render-* directives, which can point their nodes at the page where they parse them, and the module can go.

(The original entry is located in /home/runner/work/click-extra/click-extra/click_extra/sphinx/doctrees.py:docstring of click_extra.sphinx.doctrees, line 19.)

Todo

Contribute this upstream as a Sphinx config value, on sphinx-doc/sphinx#7949, which asks for the same feature and has waited for a design since 2020.

Sphinx already holds both halves. sphinx.util.logging.is_suppressed_warning is the matching this module reuses, and the exit status --fail-on-warning sets is the outcome. A config value read where sphinx.util.logging.WarningSuppressor already counts each warning would replace this module.

Should it land, keep this module as a shim for the Sphinx releases that predate it, then drop it once click-extra’s Sphinx floor moves past them.

(The original entry is located in /home/runner/work/click-extra/click-extra/click_extra/sphinx/fail_on_warnings.py:docstring of click_extra.sphinx.fail_on_warnings, line 20.)

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 helpers this module needed (todo_identity(), is_reexport() and the comparison of the objects behind two labels) 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 32.)

Todo

Delete this module once sphinx-doc/sphinx#14675 is fixed and the sphinx extra’s floor passes the release that carries the fix.

(The original entry is located in /home/runner/work/click-extra/click-extra/click_extra/sphinx/viewcode.py:docstring of click_extra.sphinx.viewcode, line 17.)

Todo

Convert a directive whose body holds a fence to a longer outer fence, instead of leaving it in reST: the build-time extension click_extra.sphinx.myst_docstrings reads fences of any length.

(The original entry is located in /home/runner/work/click-extra/click-extra/click_extra/markdown/myst.py:docstring of click_extra.markdown.myst.convert_directives, line 20.)

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/capture/recording.py:docstring of click_extra.capture.recording, line 20.)

Todo

Close the click-extra-side gaps the sections below identify:

  • a @persistent_option decorator (or a persistent=True kwarg 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.params during shell completion, so a completion callback can depend on parameter values already typed on the command line;

  • native NushellComplete and PowerShellComplete classes, for users without the carapace binary the Carapace spec needs;

  • a @completion_option bundling 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 185.)

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.)