Repository: pallets/click (python)

Issue:
group return value is ignored
Calling a command defined as `@click.group()` with `standalone_mode=False` does not propagate the return value as expected.

For instance:
```python
import click
import sys

@click.group(invoke_without_command=True)
@click.option("-l", "--local-configuration", type=str)
def main(local_configuration):
    print('Inside main')
    return 1

if __name__ == '__main__':
    print(main(sys.argv[1:], standalone_mode=False))
```

```
$ python test.py
Inside main
None
```

It does work when the command is defined with `@click.command()`, hence I suppose this is a bug.

Environment:

- Python version: 3.7.5
- Click version: 8.0.3

Pull request description:
group without command passes return value to result callback
A non-chained group invoked without a subcommand will pass its return value to its result callback, instead of `None`.

fixes #2124 

Patch:
diff --git a/CHANGES.rst b/CHANGES.rst
index 8662316..0a9661a 100644
--- a/CHANGES.rst
+++ b/CHANGES.rst
@@ -45,6 +45,9 @@ Version 8.1.0
     :issue:`2131`.
 -   ``@command`` decorator is annotated as returning the correct type if
     a ``cls`` argument is used. :issue:`2211`
+-   A ``Group`` with ``invoke_without_command=True`` and ``chain=False``
+    will invoke its result callback with the group function's return
+    value. :issue:`2124`
 
 
 Version 8.0.4
diff --git a/src/click/core.py b/src/click/core.py
index 9ba738b..263a5ff 100644
--- a/src/click/core.py
+++ b/src/click/core.py
@@ -1626,11 +1626,11 @@ class MultiCommand(Command):
         if not ctx.protected_args:
             if self.invoke_without_command:
                 # No subcommand was invoked, so the result callback is
-                # invoked with None for regular groups, or an empty list
-                # for chained groups.
+                # invoked with the group return value for regular
+                # groups, or an empty list for chained groups.
                 with ctx:
-                    super().invoke(ctx)
-                    return _process_result([] if self.chain else None)
+                    rv = super().invoke(ctx)
+                    return _process_result([] if self.chain else rv)
             ctx.fail(_("Missing command."))
 
         # Fetch args back out


Test patch:
diff --git a/tests/test_chain.py b/tests/test_chain.py
index 3431009..6b2eae3 100644
--- a/tests/test_chain.py
+++ b/tests/test_chain.py
@@ -85,20 +85,20 @@ def test_chaining_with_options(runner):
     assert result.output.splitlines() == ["bdist called 1", "sdist called 2"]
 
 
-@pytest.mark.parametrize(("chain", "expect"), [(False, "None"), (True, "[]")])
+@pytest.mark.parametrize(("chain", "expect"), [(False, "1"), (True, "[]")])
 def test_no_command_result_callback(runner, chain, expect):
     """When a group has ``invoke_without_command=True``, the result
     callback is always invoked. A regular group invokes it with
-    ``None``, a chained group with ``[]``.
+    its return value, a chained group with ``[]``.
     """
 
     @click.group(invoke_without_command=True, chain=chain)
     def cli():
-        pass
+        return 1
 
     @cli.result_callback()
     def process_result(result):
-        click.echo(str(result), nl=False)
+        click.echo(result, nl=False)
 
     result = runner.invoke(cli, [])
     assert result.output == expect