From dd89d59234d77e92e19c44d03edd7ef64ab3c17c Mon Sep 17 00:00:00 2001 From: Gahyun Suh Date: Tue, 17 Oct 2023 02:46:28 +0000 Subject: [PATCH] feat: add conflict resolution option to configuration file Signed-off-by: Gahyun Suh --- src/deadline/client/cli/_common.py | 6 ++++++ src/deadline/client/cli/_groups/job_group.py | 14 ++++++-------- src/deadline/client/config/config_file.py | 7 ++++++- .../client/ui/dialogs/deadline_config_dialog.py | 10 ++++++++++ src/deadline/job_attachments/models.py | 1 + test/unit/deadline_client/cli/test_cli_config.py | 4 +++- 6 files changed, 32 insertions(+), 10 deletions(-) diff --git a/src/deadline/client/cli/_common.py b/src/deadline/client/cli/_common.py index 2a87dcd6..bbe7bd38 100644 --- a/src/deadline/client/cli/_common.py +++ b/src/deadline/client/cli/_common.py @@ -103,6 +103,12 @@ def _apply_cli_options_to_config( auto_accept = args.pop("yes", None) if auto_accept: config_file.set_setting("settings.auto_accept", "true", config=config) + + conflict_resolution = args.pop("conflict_resolution", None) + if conflict_resolution: + config_file.set_setting( + "settings.conflict_resolution", conflict_resolution, config=config + ) else: # Remove the standard option names from the args list for name in ["profile", "farm_id", "queue_id", "job_id"]: diff --git a/src/deadline/client/cli/_groups/job_group.py b/src/deadline/client/cli/_groups/job_group.py index 4d0d32d6..f0dfe696 100644 --- a/src/deadline/client/cli/_groups/job_group.py +++ b/src/deadline/client/cli/_groups/job_group.py @@ -221,7 +221,6 @@ def _download_job_output( job_id: str, step_id: Optional[str], task_id: Optional[str], - conflict_resolution: Optional[str] = None, is_json_format: bool = False, ): """ @@ -232,6 +231,7 @@ def _download_job_output( auto_accept = config_file.str2bool( config_file.get_setting("settings.auto_accept", config=config) ) + conflict_resolution = config_file.get_setting("settings.conflict_resolution", config=config) job = deadline.get_job(farmId=farm_id, queueId=queue_id, jobId=job_id) @@ -330,10 +330,10 @@ def _download_job_output( ) output_paths_by_root = job_output_downloader.get_output_paths_by_root() - # If the conflict resolution option was not provided as a command option, auto-accept is false, - # and if there are any conflicting files in local, prompt users to select a resolution method. + # If the conflict resolution option was not specified, auto-accept is false, and + # if there are any conflicting files in local, prompt users to select a resolution method. # (skip, overwrite, or make a copy.) - if conflict_resolution: + if conflict_resolution != FileConflictResolution.NOT_SELECTED.name: file_conflict_resolution = FileConflictResolution[conflict_resolution] elif auto_accept: file_conflict_resolution = FileConflictResolution.CREATE_COPY @@ -565,7 +565,7 @@ def _is_path_in_windows_format(path_str: str) -> bool: "parsed/consumed by custom scripts.", ) @_handle_error -def job_download_output(step_id, task_id, conflict_resolution, output, **args): +def job_download_output(step_id, task_id, output, **args): """ Download the output attached to an Amazon Deadline Cloud Job. """ @@ -582,9 +582,7 @@ def job_download_output(step_id, task_id, conflict_resolution, output, **args): is_json_format = True if output == "json" else False try: - _download_job_output( - config, farm_id, queue_id, job_id, step_id, task_id, conflict_resolution, is_json_format - ) + _download_job_output(config, farm_id, queue_id, job_id, step_id, task_id, is_json_format) except Exception as e: if is_json_format: error_one_liner = str(e).replace("\n", ". ") diff --git a/src/deadline/client/config/config_file.py b/src/deadline/client/config/config_file.py index c37fa8db..3f104f5f 100644 --- a/src/deadline/client/config/config_file.py +++ b/src/deadline/client/config/config_file.py @@ -21,7 +21,8 @@ from pathlib import Path from typing import Any, Dict, List, Optional -import boto3 # type: ignore[import] +import boto3 +from deadline.job_attachments.models import FileConflictResolution from ..exceptions import DeadlineOperationError import re @@ -98,6 +99,10 @@ "settings.auto_accept": { "default": "false", }, + "settings.conflict_resolution": { + "default": FileConflictResolution.NOT_SELECTED.name, + "description": "How to handle duplicate files when downloading (if a file with the same path/name already exists.)", + }, "settings.log_level": { "default": "WARNING", "description": "The logging level to use in the CLI and GUIs.", diff --git a/src/deadline/client/ui/dialogs/deadline_config_dialog.py b/src/deadline/client/ui/dialogs/deadline_config_dialog.py index 4b0f15b2..c3db63cf 100644 --- a/src/deadline/client/ui/dialogs/deadline_config_dialog.py +++ b/src/deadline/client/ui/dialogs/deadline_config_dialog.py @@ -18,6 +18,7 @@ import boto3 # type: ignore[import] from botocore.exceptions import ProfileNotFound # type: ignore[import] +from deadline.job_attachments.models import FileConflictResolution from PySide2.QtCore import QSize, Qt, Signal from PySide2.QtWidgets import ( # pylint: disable=import-error; type: ignore QCheckBox, @@ -276,6 +277,15 @@ def _build_general_settings_ui(self, group, layout): group, layout, "settings.auto_accept", "Auto Accept Confirmation Prompts" ) + self._conflict_resolution_options = [option.name for option in FileConflictResolution] + self.conflict_resolution_box = self._init_combobox_setting( + group, + layout, + "settings.conflict_resolution", + "Conflict Resolution Option", + self._conflict_resolution_options, + ) + self._log_levels = ["ERROR", "WARNING", "INFO", "DEBUG"] self.log_level_box = self._init_combobox_setting( group, diff --git a/src/deadline/job_attachments/models.py b/src/deadline/job_attachments/models.py index 881123e4..50b948d0 100644 --- a/src/deadline/job_attachments/models.py +++ b/src/deadline/job_attachments/models.py @@ -276,6 +276,7 @@ class FileSystemLocationType(str, Enum): class FileConflictResolution(Enum): + NOT_SELECTED = 0 SKIP = 1 OVERWRITE = 2 CREATE_COPY = 3 diff --git a/test/unit/deadline_client/cli/test_cli_config.py b/test/unit/deadline_client/cli/test_cli_config.py index d64887c7..729e981e 100644 --- a/test/unit/deadline_client/cli/test_cli_config.py +++ b/test/unit/deadline_client/cli/test_cli_config.py @@ -35,7 +35,7 @@ def test_cli_config_show_defaults(fresh_deadline_config): assert fresh_deadline_config in result.output # Assert the expected number of settings - assert len(settings.keys()) == 13 + assert len(settings.keys()) == 14 for setting_name in settings.keys(): assert setting_name in result.output @@ -98,6 +98,7 @@ def test_cli_config_show_modified_config(fresh_deadline_config): config.set_setting("defaults.queue_id", "queue-389348u234jhk34") config.set_setting("defaults.job_id", "job-239u40234jkl234nkl23") config.set_setting("settings.auto_accept", "False") + config.set_setting("settings.conflict_resolution", "CREATE_COPY") config.set_setting("defaults.job_attachments_file_system", "VIRTUAL") config.set_setting("settings.log_level", "DEBUG") config.set_setting("telemetry.opt_out", "True") @@ -119,6 +120,7 @@ def test_cli_config_show_modified_config(fresh_deadline_config): assert "farm-82934h23k4j23kjh" in result.output assert "queue-389348u234jhk34" in result.output assert "job-239u40234jkl234nkl23" in result.output + assert "settings.conflict_resolution:\n CREATE_COPY" in result.output assert "settings.log_level:\n DEBUG" in result.output assert "user-id-123abc-456def" in result.output # It shouldn't say anywhere that there is a default setting