Repository: pallets/click (python)

Issue:
argument with nargs=-1 and envvar ignores values from command line
Since click 8.0, the value(s) provided on the command line for a nargs=-1 argument are ignored if the argument has `envvar` set.

Example:

```python
#!/usr/bin/env python
import click

@click.command()
@click.argument("foo", nargs=-1, envvar="FOO")
def cli(foo):
    click.echo(foo)

if __name__ == "__main__":
    cli()
```

```
$ ./clickbug arg1 arg2
()
```


When arguments are passed on the command line, the `foo` value remains empty. Removing the `envvar` option makes it work again. Values from the environment variable are picked up, though. Reverting to `click<8` also fixes the problem.

The cause of the bug is possibly [here](https://github.com/pallets/click/commit/3d3ea9c64420fd8978a41ce8b4db3ac2d245849c#diff-948f9e0cc733616a6b18aa152ac6703e819fec61dd752d1efa40e5736c3bdce7): The incoming `value` (which at this point still contains the correct arguments) is overwritten with `None` if `nargs` is -1 and the argument has an envvar set.

Environment:

- Python version: 3.8.5
- Click version: 8.0.0


Pull request description:
argument with nargs=-1 and envvar prefers command line value
Resubmitting #1906 with some cleanup, cc @MarcSchmitzer. Rebased to 8.0.x, updated test with value from envvar, updated changelog and comment.

If an `Argument` has `nargs=-1` and `envvar` set, it was ignoring command line values and always trying the env var. Now it only does that if no command line values were given (empty tuple).

<!--
Link to relevant issues or previous PRs, one per line. Use "fixes" to
automatically close an issue.
-->

- fixes #1903

<!--
Ensure each step in CONTRIBUTING.rst is complete by adding an "x" to
each box below.

If only docs were changed, these aren't relevant and can be removed.
-->

Checklist:

- [x] Add tests that demonstrate the correct behavior of the change. Tests should fail without the change.
- [x] Add an entry in `CHANGES.rst` summarizing the change and linking to the issue.
- [x] Run `pre-commit` hooks and fix any issues.
- [x] Run `pytest` and `tox`, no tests failed.


Patch:
diff --git a/CHANGES.rst b/CHANGES.rst
index 1058fab..0b24de0 100644
--- a/CHANGES.rst
+++ b/CHANGES.rst
@@ -14,6 +14,8 @@ Unreleased
     :issue:`1892`
 -   The ``importlib_metadata`` backport package is installed on Python <
     3.8. :issue:`1889`
+-   Arguments with ``nargs=-1`` only use env var value if no command
+    line values are given. :issue:`1903`
 
 
 Version 8.0.0
diff --git a/src/click/parser.py b/src/click/parser.py
index c713a24..7d995f7 100644
--- a/src/click/parser.py
+++ b/src/click/parser.py
@@ -233,7 +233,9 @@ class Argument:
                     )
                 )
 
-        if self.nargs == -1 and self.obj.envvar is not None:
+        if self.nargs == -1 and self.obj.envvar is not None and value == ():
+            # Replace empty tuple with None so that a value from the
+            # environment may be tried.
             value = None
 
         state.opts[self.dest] = value  # type: ignore


Test patch:
diff --git a/tests/test_arguments.py b/tests/test_arguments.py
index 2045f6f..f4d7afd 100644
--- a/tests/test_arguments.py
+++ b/tests/test_arguments.py
@@ -194,6 +194,19 @@ def test_nargs_envvar(runner, nargs, value, expect):
         assert result.return_value == expect
 
 
+def test_nargs_envvar_only_if_values_empty(runner):
+    @click.command()
+    @click.argument("arg", envvar="X", nargs=-1)
+    def cli(arg):
+        return arg
+
+    result = runner.invoke(cli, ["a", "b"], standalone_mode=False)
+    assert result.return_value == ("a", "b")
+
+    result = runner.invoke(cli, env={"X": "a"}, standalone_mode=False)
+    assert result.return_value == ("a",)
+
+
 def test_empty_nargs(runner):
     @click.command()
     @click.argument("arg", nargs=-1)