From 7b763f74fb3ff903932ae0495ec88a2a6fe36be5 Mon Sep 17 00:00:00 2001 From: IamCathal Date: Mon, 6 Jul 2020 16:47:51 +0100 Subject: [PATCH] Add result callback invocation for subcommands --- CHANGES.rst | 1 + src/click/core.py | 16 ++++------------ tests/test_chain.py | 17 +++++++++++++++++ 3 files changed, 22 insertions(+), 12 deletions(-) diff --git a/CHANGES.rst b/CHANGES.rst index cd40f7891..e6d198234 100644 --- a/CHANGES.rst +++ b/CHANGES.rst @@ -28,6 +28,7 @@ Unreleased matched name. This makes behavior such as help text and ``Context.invoked_subcommand`` consistent when using patterns like ``AliasedGroup``. :issue:`1422` +- Add result callback invocation for subcommands. :issue:`1178` Version 7.1.2 diff --git a/src/click/core.py b/src/click/core.py index 22f742001..60458f8da 100644 --- a/src/click/core.py +++ b/src/click/core.py @@ -1170,7 +1170,7 @@ def format_options(self, ctx, formatter): self.format_commands(ctx, formatter) def resultcallback(self, replace=False): - """Adds a result callback to the chain command. By default if a + """Adds a result callback to the a command. By default if a result callback is already registered this will chain them but this can be disabled with the `replace` parameter. The result callback is invoked with the return value of the subcommand @@ -1258,15 +1258,10 @@ def _process_result(value): return value if not ctx.protected_args: - # If we are invoked without command the chain flag controls - # how this happens. If we are not in chain mode, the return - # value here is the return value of the command. - # If however we are in chain mode, the return value is the - # return value of the result processor invoked with an empty - # list (which means that no subcommand actually was executed). + # The return value is the return value of the result processor + # invoked with an empty list (which means that no subcommand + # was actually executed). if self.invoke_without_command: - if not self.chain: - return Command.invoke(self, ctx) with ctx: Command.invoke(self, ctx) return _process_result([]) @@ -1277,9 +1272,6 @@ def _process_result(value): ctx.args = [] ctx.protected_args = [] - # If we're not in chain mode, we only allow the invocation of a - # single command but we also inform the current context about the - # name of the command to invoke. if not self.chain: # Make sure the context is entered so we do not clean up # resources until the result processor has worked. diff --git a/tests/test_chain.py b/tests/test_chain.py index 046277909..7f840d803 100644 --- a/tests/test_chain.py +++ b/tests/test_chain.py @@ -88,6 +88,23 @@ def bdist(format): assert result.output.splitlines() == ["bdist called 1", "sdist called 2"] +def test_resultcallback(runner): + @click.group(invoke_without_command=True) + def cli(): + pass + + @cli.command() + def sub(): + return "Sub" + + @cli.resultcallback() + def process_result(result): + print("Subcommands invoked:", result) + + result = runner.invoke(cli, []) + assert result.output == "Subcommands invoked: []\n" + + def test_chaining_with_arguments(runner): @click.group(chain=True) def cli():