From 41ae635622ba6e53a71ad76f83b1a4f53c0a13bc Mon Sep 17 00:00:00 2001 From: BartoszCki Date: Wed, 26 Feb 2020 17:27:07 +0100 Subject: [PATCH] Overvrite yaml options in terminal --- gradient/cli/common.py | 18 +++++++++++---- tests/functional/test_experiments.py | 34 ++++++++++++++++++++++++++++ 2 files changed, 48 insertions(+), 4 deletions(-) diff --git a/gradient/cli/common.py b/gradient/cli/common.py index fabc1340..6b1cf3a2 100644 --- a/gradient/cli/common.py +++ b/gradient/cli/common.py @@ -67,7 +67,7 @@ def get_option_name(options_strings): class ReadValueFromConfigFile(click.Parameter): def handle_parse_result(self, ctx, opts, args): config_file = ctx.params.get(OPTIONS_FILE_PARAMETER_NAME) - if config_file: + if self.should_read_value_from_file(opts, args, config_file): with open(config_file) as f: config_data = yaml.load(f, Loader=yaml.FullLoader) option_name = get_option_name(self.opts) @@ -89,8 +89,15 @@ def handle_parse_result(self, ctx, opts, args): opts[self.name] = value - return super(ReadValueFromConfigFile, self).handle_parse_result( + rv = super(ReadValueFromConfigFile, self).handle_parse_result( ctx, opts, args) + return rv + + def should_read_value_from_file(self, opts, args, config_file): + """ + :rtype: bool + """ + raise NotImplementedError class ColorExtrasInCommandHelpMixin(object): @@ -127,11 +134,13 @@ def _color_str(self, s): class GradientArgument(ColorExtrasInCommandHelpMixin, ReadValueFromConfigFile, click.Argument): - pass + def should_read_value_from_file(self, opts, args, config_file): + return opts.get(self.name) in (None, ()) and config_file class GradientOption(ColorExtrasInCommandHelpMixin, ReadValueFromConfigFile, click.Option): - pass + def should_read_value_from_file(self, opts, args, config_file): + return self.name not in opts and config_file api_key_option = click.option( @@ -207,6 +216,7 @@ def options_file(f): click.option( "--" + OPTIONS_FILE_OPTION_NAME, OPTIONS_FILE_PARAMETER_NAME, + is_eager=True, help="Path to YAML file with predefined options", type=click.Path(exists=True, resolve_path=True) ), diff --git a/tests/functional/test_experiments.py b/tests/functional/test_experiments.py index a380014b..8edddecf 100644 --- a/tests/functional/test_experiments.py +++ b/tests/functional/test_experiments.py @@ -1,3 +1,4 @@ +import copy import os import shutil import tempfile @@ -98,6 +99,11 @@ class TestExperimentsCreateSingleNode(object): "experiments", "create", "singlenode", "--optionsFile", # path added in test, ] + FULL_OPTIONS_COMMAND_WITH_OPTIONS_FILE_AND_SOME_VALUES_OVERWRITTEN_IN_LINE = [ + "experiments", "create", "singlenode", + "--name", "some_other_name", + "--optionsFile", # path added in test, + ] BASIC_OPTIONS_REQUEST = { "projectHandle": u"testHandle", "container": u"testContainer", @@ -173,6 +179,29 @@ def test_should_read_options_from_config_file( data=None) assert result.exit_code == 0, result.exc_info + @mock.patch("gradient.api_sdk.clients.http_client.requests.post") + def test_should_read_options_from_config_file_and_overwrite_options_with_values_provided_in_terminal( + self, post_patched, create_single_node_experiment_config_path): + post_patched.return_value = MockResponse(self.RESPONSE_JSON_200) + request_json = copy.deepcopy(self.FULL_OPTIONS_REQUEST) + request_json["name"] = "some_other_name" + request_json["projectHandle"] = "some_other_project_id" + + command = self.FULL_OPTIONS_COMMAND_WITH_OPTIONS_FILE_AND_SOME_VALUES_OVERWRITTEN_IN_LINE[:] + command = command[:] + [create_single_node_experiment_config_path, "--projectId", "some_other_project_id"] + + runner = CliRunner() + result = runner.invoke(cli.cli, command) + + assert self.EXPECTED_STDOUT in result.output, result.exc_info + post_patched.assert_called_once_with(self.URL_V2, + headers=EXPECTED_HEADERS_WITH_CHANGED_API_KEY, + json=request_json, + params=None, + files=None, + data=None) + assert result.exit_code == 0, result.exc_info + @mock.patch("gradient.api_sdk.clients.http_client.requests.post") def test_should_send_proper_data_and_print_message_when_create_experiment_was_run_with_full_options(self, post_patched): @@ -953,6 +982,11 @@ class TestExperimentsCreateAndStartSingleNode(TestExperimentsCreateSingleNode): "experiments", "run", "singlenode", "--optionsFile", # path added in test, ] + FULL_OPTIONS_COMMAND_WITH_OPTIONS_FILE_AND_SOME_VALUES_OVERWRITTEN_IN_LINE = [ + "experiments", "run", "singlenode", + "--name", "some_other_name", + "--optionsFile", # path added in test, + ] EXPECTED_STDOUT = "New experiment created and started with ID: sadkfhlskdjh\n"