From 5bfc060979bb82d2d3829dd7428a57ce43313695 Mon Sep 17 00:00:00 2001 From: Sebastiaan Huber Date: Wed, 8 Mar 2023 13:36:02 +0100 Subject: [PATCH] `verdi config list`: Do not except if no profiles are defined The command should work if no profiles exist, in which case it should simply list the global values, however, it was excepting since it assumed that `ctx.obj.profile` would be set. This is set by the `ProfileParamType` which is used by the `--profile` option, but this is not called if no profiles are defined. To create a regression test, the `empty_config` fixture is used. However, since this fixture works in memory, the `use_subprocess=False` switch has to be used for `run_cli_command`. This by default would populate the `ctx.obj.profile` object. This is normally done by the `--profile` option, but this is not hit when using `click.CliRunner`. This would nullify the test, as it would always pass, even without the fix. To solve this issue, a new argument `initialize_ctx_obj` is added to the `run_cli_command` fixture. If set to `False`, the `ctx.obj` is not initialized. By using this new argument, the regression test properly failed before the test, but passes after the fix. --- aiida/cmdline/commands/cmd_config.py | 2 +- tests/cmdline/commands/test_config.py | 8 ++++++++ tests/conftest.py | 20 +++++++++++++++----- 3 files changed, 24 insertions(+), 6 deletions(-) diff --git a/aiida/cmdline/commands/cmd_config.py b/aiida/cmdline/commands/cmd_config.py index 9a19ce94a9..6e010e4625 100644 --- a/aiida/cmdline/commands/cmd_config.py +++ b/aiida/cmdline/commands/cmd_config.py @@ -40,7 +40,7 @@ def verdi_config_list(ctx, prefix, description: bool): from aiida.manage.configuration import Config, Profile config: Config = ctx.obj.config - profile: Profile = ctx.obj.profile + profile: Profile = ctx.obj.get('profile', None) if not profile: echo.echo_warning('no profiles configured: run `verdi setup` to create one') diff --git a/tests/cmdline/commands/test_config.py b/tests/cmdline/commands/test_config.py index b27f5e9982..9292f01fda 100644 --- a/tests/cmdline/commands/test_config.py +++ b/tests/cmdline/commands/test_config.py @@ -8,10 +8,18 @@ # For further information please visit http://www.aiida.net # ########################################################################### """Tests for ``verdi config``.""" +import pytest + from aiida import get_profile from aiida.cmdline.commands import cmd_verdi +@pytest.mark.usefixtures('empty_config') +def test_config_list_no_profile(run_cli_command): + """Test the `verdi config list` command when no profile is present in the config, it should not except.""" + run_cli_command(cmd_verdi.verdi, ['config', 'list'], initialize_ctx_obj=False) + + def test_config_set_option_no_profile(run_cli_command, empty_config): """Test the `verdi config set` command when no profile is present in the config.""" config = empty_config diff --git a/tests/conftest.py b/tests/conftest.py index 466908a124..3281face0b 100644 --- a/tests/conftest.py +++ b/tests/conftest.py @@ -488,6 +488,7 @@ def factory( raises: bool = False, use_subprocess: bool = False, suppress_warnings: bool = False, + initialize_ctx_obj: bool = True, **kwargs ) -> CliResult: """Run the command and check the result. @@ -513,6 +514,12 @@ def factory( on the output is very strict. By running in a sub process, any warnings that are emitted by the code will be shown since they have not already been hit as would be the case when running the test through the test runner in this interpreter. + :param initialize_ctx_obj: Boolean, if ``True``, the custom ``obj`` attribute of the ``ctx`` is initialized when + ``use_subprocess == False``. When invoking the ``verdi`` command from the command line (and when running + tests with ``use_subprocess == True``), this is done by the ``VerdiContext``, but when using the test runner + in this interpreter, the object has to be initialized manually and passed to the test runner. In certain + cases, however, this initialization should not be done, to simulate for example the absence of a loaded + profile. :returns: Instance of ``CliResult``. :raises AssertionError: If ``raises == True`` and the command didn't except, or if ``raises == True`` and the the command did except. @@ -523,7 +530,7 @@ def factory( if use_subprocess: result = run_cli_command_subprocess(command, parameters, user_input, aiida_profile.name, suppress_warnings) else: - result = run_cli_command_runner(command, parameters, user_input, kwargs) + result = run_cli_command_runner(command, parameters, user_input, initialize_ctx_obj, kwargs) if raises: assert result.exception is not None, result.output @@ -574,16 +581,19 @@ def run_cli_command_subprocess(command, parameters, user_input, profile_name, su return result -def run_cli_command_runner(command, parameters, user_input, kwargs): +def run_cli_command_runner(command, parameters, user_input, initialize_ctx_obj, kwargs): """Run CLI command through ``click.testing.CliRunner``.""" from click.testing import CliRunner from aiida.cmdline.commands.cmd_verdi import VerdiCommandGroup from aiida.common import AttributeDict - config = get_config() - profile = get_profile() - obj = AttributeDict({'config': config, 'profile': profile}) + if initialize_ctx_obj: + config = get_config() + profile = get_profile() + obj = AttributeDict({'config': config, 'profile': profile}) + else: + obj = None # We need to apply the ``VERBOSITY`` option. When invoked through the command line, this is done by the logic of the # ``VerdiCommandGroup``, but when testing commands, the command is retrieved directly from the module which