From 535559adbd7d5549d1d123e8c7f9a9e602f0cc3f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?R=C3=A9my=20Greinhofer?= Date: Sat, 14 Oct 2017 15:33:15 -0500 Subject: [PATCH] Fix variable precedence This patch fixes the variable precedence in order to have the default values read last: 1. Values from CLI 2. Values from the environment 3. Default values Tests were added accordingly. Drive-by: * Update `.gitignore` file * Update `tox.ini` to skip missing environments Fixes: #873 --- .gitignore | 1 + click/core.py | 5 +++-- tests/test_commands.py | 48 ++++++++++++++++++++++++++++++++++++++++++ tox.ini | 1 + 4 files changed, 53 insertions(+), 2 deletions(-) diff --git a/.gitignore b/.gitignore index ed66c157b..fe562f26a 100644 --- a/.gitignore +++ b/.gitignore @@ -8,6 +8,7 @@ dist build docs/_build click.egg-info +venv/ .tox .cache .ropeproject diff --git a/click/core.py b/click/core.py index a8962bec3..9498850f1 100644 --- a/click/core.py +++ b/click/core.py @@ -1328,12 +1328,13 @@ def get_default(self, ctx): def add_to_parser(self, parser, ctx): pass + def consume_value(self, ctx, opts): value = opts.get(self.name) - if value is None: - value = ctx.lookup_default(self.name) if value is None: value = self.value_from_envvar(ctx) + if value is None: + value = ctx.lookup_default(self.name) return value def type_cast_value(self, ctx, value): diff --git a/tests/test_commands.py b/tests/test_commands.py index e900c431f..e8a95351b 100644 --- a/tests/test_commands.py +++ b/tests/test_commands.py @@ -1,6 +1,8 @@ # -*- coding: utf-8 -*- import re + import click +import pytest def test_other_command_invoke(runner): @@ -267,3 +269,49 @@ def foo_bar(): result = runner.invoke(cli, ['foo-bar']) assert not result.exception assert result.output.splitlines() == ['foo-bar'] + + +def test_environment_variables(runner): + @click.group() + def cli(): + pass + + @cli.command() + @click.option('--name', envvar='CLICK_NAME') + def foo(name): + click.echo(name) + + result = runner.invoke(cli, ['foo'], env={'CLICK_NAME': 'environment'}) + + assert not result.exception + assert result.output == 'environment\n' + + +# Ensures the variables are read in the following order: +# 1. CLI +# 2. Environment +# 3. Defaults +variable_precedence_testdata = [ + (['foo', '--name=cli'], {'CLICK_NAME': 'environment'}, 'cli\n'), + (['foo'], {'CLICK_NAME': 'environment'}, 'environment\n'), + (['foo'], None, 'defaults\n'), +] + + +@pytest.mark.parametrize("command,environment,expected", + variable_precedence_testdata) +def test_variable_precendence_00(runner, command, environment, expected): + @click.group() + def cli(): + pass + + @cli.command() + @click.option('--name', envvar='CLICK_NAME') + def foo(name): + click.echo(name) + + defaults = {'foo': {'name': 'defaults'}} + result = runner.invoke(cli, command, default_map=defaults, env=environment) + + assert not result.exception + assert result.output == expected diff --git a/tox.ini b/tox.ini index af7bf986b..ef4a70366 100644 --- a/tox.ini +++ b/tox.ini @@ -1,5 +1,6 @@ [tox] envlist = py27,py34,py35,py36,pypy +skip_missing_interpreters = true [testenv] passenv = LANG