Skip to content

Commit 3901925

Browse files
committed
Allow adding dynamic parameters to every Context
1 parent 4a758f5 commit 3901925

3 files changed

Lines changed: 30 additions & 3 deletions

File tree

CHANGES.rst

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -31,6 +31,7 @@ Unreleased
3131
- When generating a command's name from a decorated function's name, the
3232
suffixes ``_command``, ``_cmd``, ``_group``, and ``_grp`` are removed.
3333
:issue:`2322`
34+
- Add ``dynamic_params`` property to ``Context``. :pr:`2784`
3435

3536

3637
Version 8.1.8

src/click/core.py

Lines changed: 15 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -226,6 +226,11 @@ class Context:
226226
value is not set, it defaults to the value from the parent
227227
context. ``Command.show_default`` overrides this default for the
228228
specific command.
229+
:param dynamic_params: A list of :class:`Parameter` objects that the
230+
attached command will use.
231+
232+
.. versionchanged:: 8.2
233+
Added the ``dynamic_params`` parameter.
229234
230235
.. versionchanged:: 8.2
231236
The ``protected_args`` attribute is deprecated and will be removed in
@@ -278,6 +283,7 @@ def __init__(
278283
token_normalize_func: t.Callable[[str], str] | None = None,
279284
color: bool | None = None,
280285
show_default: bool | None = None,
286+
dynamic_params: list[Parameter] | None = None,
281287
) -> None:
282288
#: the parent context or `None` if none exists.
283289
self.parent = parent
@@ -425,6 +431,12 @@ def __init__(
425431
#: Show option default values when formatting help text.
426432
self.show_default: bool | None = show_default
427433

434+
if dynamic_params is None:
435+
dynamic_params = []
436+
437+
#: Allow for dynamic parameters.
438+
self.dynamic_params: list[Parameter] = dynamic_params
439+
428440
self._close_callbacks: list[t.Callable[[], t.Any]] = []
429441
self._depth = 0
430442
self._parameter_source: dict[str, ParameterSource] = {}
@@ -951,11 +963,11 @@ def get_usage(self, ctx: Context) -> str:
951963
return formatter.getvalue().rstrip("\n")
952964

953965
def get_params(self, ctx: Context) -> list[Parameter]:
954-
rv = self.params
955-
help_option = self.get_help_option(ctx)
966+
rv = [*self.params, *ctx.dynamic_params]
956967

968+
help_option = self.get_help_option(ctx)
957969
if help_option is not None:
958-
rv = [*rv, help_option]
970+
rv.append(help_option)
959971

960972
return rv
961973

tests/test_commands.py

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -409,3 +409,17 @@ def cli():
409409
assert rv.exit_code == 1
410410
assert isinstance(rv.exception.__cause__, exc)
411411
assert rv.exception.__cause__.args == ("catch me!",)
412+
413+
414+
def test_dynamic_params(runner):
415+
def callback(ctx, p, v):
416+
ctx.dynamic_params.append(click.Option([f"--{v}"]))
417+
return v
418+
419+
@click.command()
420+
@click.option("--dyn", required=True, is_eager=True, callback=callback)
421+
def command(dyn, **kwargs):
422+
assert dyn in kwargs
423+
assert kwargs[dyn] == "bar"
424+
425+
runner.invoke(command, ["--dyn", "foo", "--foo", "bar"])

0 commit comments

Comments
 (0)