Source code for aiida.cmdline.params.options.test_conditional

# -*- coding: utf-8 -*-
###########################################################################
# Copyright (c), The AiiDA team. All rights reserved.                     #
# This file is part of the AiiDA code.                                    #
#                                                                         #
# The code is hosted on GitHub at https://github.com/aiidateam/aiida_core #
# For further information on the license, see the LICENSE.txt file        #
# For further information please visit http://www.aiida.net               #
###########################################################################
"""Unit tests for the ConditionalOption."""
from __future__ import division
from __future__ import print_function
from __future__ import absolute_import

import unittest

import click
from click.testing import CliRunner

from .conditional import ConditionalOption


[docs]class ConditionalOptionTest(unittest.TestCase): """Unit tests for ConditionalOption."""
[docs] @classmethod def setUpClass(cls): cls.runner = CliRunner()
[docs] def simple_cmd(self, pname, required_fn=lambda ctx: ctx.params.get('on'), **kwargs): """ returns a command with two options: * an option created from the args and kwargs * --opt, ConditionalOption with required_fn from kwargs """ # pylint: disable=no-self-use @click.command() @click.option(pname, **kwargs) @click.option('--opt', required_fn=required_fn, cls=ConditionalOption) def cmd(on, opt): """dummy command for testing""" # pylint: disable=unused-argument, invalid-name click.echo(opt) return cmd
[docs] def test_switch_off(self): """ scenario: switch --on/--off detrmines if option opt is required action: invoke with no options behaviour: flag is off by default -> command runs without complaining """ cmd = self.simple_cmd('--on/--off') runner = CliRunner() result = runner.invoke(cmd, []) self.assertIsNone(result.exception)
[docs] def test_switch_on(self): """ scenario: switch --on/--off detrmines if option opt is required action: invoke with --on behaviour: fails with Missin option message """ cmd = self.simple_cmd('--on/--off') runner = CliRunner() result = runner.invoke(cmd, ['--on']) self.assertIsNotNone(result.exception) self.assertIn('Error: Missing option "--opt".', result.output)
[docs] def test_flag_off(self): """ scenario: flag "--on" detrmines if option opt is required action: invoke without options behaviour: command runs without complaining """ cmd = self.simple_cmd('--on', is_flag=True) runner = CliRunner() result = runner.invoke(cmd, []) self.assertIsNone(result.exception)
[docs] def test_flag_on(self): """ scenario: flag "--on" detrmines if option opt is required action: invoke with --on behaviour: fails with Missing option message """ cmd = self.simple_cmd('--on', is_flag=True) runner = CliRunner() result = runner.invoke(cmd, ['--on']) self.assertIsNotNone(result.exception) self.assertIn('Error: Missing option "--opt".', result.output)
[docs] def setup_multi_non_eager(self): """ scenario a-or-b: * flag a_or_b (--a/--b) * opt-a required if a_or_b == True * opt-b required if a_or_b == False """ # pylint: disable=no-self-use @click.command() @click.option('--a/--b', 'a_or_b') @click.option('--opt-a', required_fn=lambda c: c.params.get('a_or_b'), cls=ConditionalOption) @click.option('--opt-b', required_fn=lambda c: not c.params.get('a_or_b'), cls=ConditionalOption) def cmd(a_or_b, opt_a, opt_b): """test command for scenario a-or-b""" # pylint: disable=unused-argument click.echo('{} / {}'.format(opt_a, opt_b)) runner = CliRunner() return runner, cmd
[docs] def test_aa(self): """ scenario = a-or-b action: require a, give a (+ reversed order) behaviour: command runs """ runner, cmd = self.setup_multi_non_eager() result = runner.invoke(cmd, ['--a', '--opt-a=Bla']) self.assertIsNone(result.exception) self.assertEqual(result.output, 'Bla / None\n') result_rev = runner.invoke(cmd, ['--opt-a=Bla', '--a']) self.assertIsNone(result_rev.exception) self.assertEqual(result_rev.output, 'Bla / None\n')
[docs] def test_ab(self): """ scenario = a-or-b action: require a, give b (+ reversed order) behaviour: fail, Missing option """ runner, cmd = self.setup_multi_non_eager() result = runner.invoke(cmd, ['--a', '--opt-b=Bla']) self.assertIsNotNone(result.exception) self.assertIn('Error: Missing option "--opt-a".', result.output) result_rev = runner.invoke(cmd, ['--opt-b=Bla', '--a']) self.assertIsNotNone(result_rev.exception) self.assertIn('Error: Missing option "--opt-a".', result_rev.output)
[docs] def test_ba(self): """ scenario = a-or-b action: require b, give a (+ reversed order) behaviour: fail, Missing option """ runner, cmd = self.setup_multi_non_eager() result = runner.invoke(cmd, ['--b', '--opt-a=Bla']) self.assertIsNotNone(result.exception) self.assertIn('Error: Missing option "--opt-b".', result.output) result_rev = runner.invoke(cmd, ['--opt-a=Bla', '--b']) self.assertIsNotNone(result_rev.exception) self.assertIn('Error: Missing option "--opt-b".', result_rev.output)
[docs] @staticmethod def user_callback(_ctx, param, value): """ Testing callback that does not accept 42 and transforms a missing value to -1 """ if not value: return -1 if value != 42: raise click.BadParameter('invalid', param=param) return value
[docs] @staticmethod def setup_flag_cond(**kwargs): """Set up a command with a flag and a customizable option that depends on it.""" @click.command() @click.option('--flag', is_flag=True) @click.option('--opt-a', required_fn=lambda c: c.params.get('flag'), cls=ConditionalOption, **kwargs) def cmd(flag, opt_a): """ A command with a flag and customizable options that dependon it """ # pylint: disable=unused-argument click.echo('{}'.format(opt_a)) return cmd
[docs] def test_default(self): """Test that the default still gets passed.""" cmd = self.setup_flag_cond(default='default') result_noflag = self.runner.invoke(cmd) self.assertIsNone(result_noflag.exception) self.assertEqual('default\n', result_noflag.output) result_flag = self.runner.invoke(cmd, ['--flag']) self.assertIsNone(result_flag.exception) self.assertEqual('default\n', result_flag.output)
[docs] def test_callback(self): """Test that the callback still gets called.""" cmd = self.setup_flag_cond(default=23, type=int, callback=self.user_callback) result_noflag = self.runner.invoke(cmd) self.assertIsNotNone(result_noflag.exception) result_flag = self.runner.invoke(cmd, ['--flag']) self.assertIsNotNone(result_flag.exception)
[docs] def test_prompt_callback(self): """Test that the callback gets called on prompt results.""" cmd = self.setup_flag_cond(prompt='A', default=23, type=int, callback=self.user_callback) result_noflag = self.runner.invoke(cmd, input='\n') self.assertIsNotNone(result_noflag.exception) self.assertIn('A [23]: \n', result_noflag.output) self.assertIn('Invalid', result_noflag.output) result_flag = self.runner.invoke(cmd, ['--flag'], input='\n') self.assertIsNotNone(result_flag.exception) self.assertIn('A [23]: \n', result_flag.output) self.assertIn('Invalid', result_flag.output)
[docs] def test_required(self): """Test that required_fn overrides required if it evaluates to False.""" cmd = self.setup_flag_cond(required=True) result_noflag = self.runner.invoke(cmd) self.assertIsNone(result_noflag.exception) result_flag = self.runner.invoke(cmd, ['--flag']) self.assertIsNotNone(result_flag.exception)