From a2def7be0eb779470fc9453eb9bf9983f7e3e6ba Mon Sep 17 00:00:00 2001 From: Jakub Trllo Date: Mon, 4 Mar 2024 17:41:43 +0100 Subject: [PATCH] modified push to project --- .../tools/push_to_project/control.py | 60 +++--- .../tools/push_to_project/models/integrate.py | 187 +++++++++--------- .../tools/push_to_project/ui/window.py | 8 +- 3 files changed, 134 insertions(+), 121 deletions(-) diff --git a/client/ayon_core/tools/push_to_project/control.py b/client/ayon_core/tools/push_to_project/control.py index 3b6bd85028..1e1434c27e 100644 --- a/client/ayon_core/tools/push_to_project/control.py +++ b/client/ayon_core/tools/push_to_project/control.py @@ -1,7 +1,8 @@ import threading +import ayon_api + from ayon_core.client import ( - get_asset_by_id, get_subset_by_id, get_version_by_id, get_representations, @@ -32,7 +33,8 @@ class PushToContextController: self._src_project_name = None self._src_version_id = None - self._src_asset_doc = None + self._src_folder_entity = None + self._src_folder_task_entities = {} self._src_subset_doc = None self._src_version_doc = None self._src_label = None @@ -71,7 +73,8 @@ class PushToContextController: self._src_project_name = project_name self._src_version_id = version_id self._src_label = None - asset_doc = None + folder_entity = None + task_entities = {} subset_doc = None version_doc = None if project_name and version_id: @@ -81,13 +84,24 @@ class PushToContextController: subset_doc = get_subset_by_id(project_name, version_doc["parent"]) if subset_doc: - asset_doc = get_asset_by_id(project_name, subset_doc["parent"]) + folder_entity = ayon_api.get_folder_by_id( + project_name, subset_doc["parent"] + ) - self._src_asset_doc = asset_doc + if folder_entity: + task_entities = { + task_entity["name"]: task_entity + for task_entity in ayon_api.get_tasks( + project_name, folder_ids=[folder_entity["id"]] + ) + } + + self._src_folder_entity = folder_entity + self._src_folder_task_entities = task_entities self._src_subset_doc = subset_doc self._src_version_doc = version_doc - if asset_doc: - self._user_values.set_new_folder_name(asset_doc["name"]) + if folder_entity: + self._user_values.set_new_folder_name(folder_entity["name"]) variant = self._get_src_variant() if variant: self._user_values.set_variant(variant) @@ -197,39 +211,35 @@ class PushToContextController: if not self._src_project_name or not self._src_version_id: return "Source is not defined" - asset_doc = self._src_asset_doc - if not asset_doc: + folder_entity = self._src_folder_entity + if not folder_entity: return "Source is invalid" - folder_path_parts = list(asset_doc["data"]["parents"]) - folder_path_parts.append(asset_doc["name"]) - folder_path = "/".join(folder_path_parts) + folder_path = folder_entity["path"] subset_doc = self._src_subset_doc version_doc = self._src_version_doc - return "Source: {}/{}/{}/v{:0>3}".format( + return "Source: {}{}/{}/v{:0>3}".format( self._src_project_name, folder_path, subset_doc["name"], version_doc["name"] ) - def _get_task_info_from_repre_docs(self, asset_doc, repre_docs): - asset_tasks = asset_doc["data"].get("tasks") or {} + def _get_task_info_from_repre_docs(self, task_entities, repre_docs): found_comb = [] for repre_doc in repre_docs: context = repre_doc["context"] - task_info = context.get("task") - if task_info is None: + repre_task_name = context.get("task") + if repre_task_name is None: continue + if isinstance(repre_task_name, dict): + repre_task_name = repre_task_name.get("name") + task_name = None task_type = None - if isinstance(task_info, str): - task_name = task_info - asset_task_info = asset_tasks.get(task_info) or {} - task_type = asset_task_info.get("type") - - elif isinstance(task_info, dict): + if repre_task_name: + task_info = task_entities.get(repre_task_name) or {} task_name = task_info.get("name") task_type = task_info.get("type") @@ -246,12 +256,12 @@ class PushToContextController: def _get_src_variant(self): project_name = self._src_project_name version_doc = self._src_version_doc - asset_doc = self._src_asset_doc + task_entities = self._src_folder_task_entities repre_docs = get_representations( project_name, version_ids=[version_doc["_id"]] ) task_name, task_type = self._get_task_info_from_repre_docs( - asset_doc, repre_docs + task_entities, repre_docs ) project_settings = get_project_settings(project_name) diff --git a/client/ayon_core/tools/push_to_project/models/integrate.py b/client/ayon_core/tools/push_to_project/models/integrate.py index d0b26d1c03..0c37055a2b 100644 --- a/client/ayon_core/tools/push_to_project/models/integrate.py +++ b/client/ayon_core/tools/push_to_project/models/integrate.py @@ -11,8 +11,6 @@ import uuid import ayon_api from ayon_core.client import ( - get_assets, - get_asset_by_id, get_subset_by_id, get_subset_by_name, get_version_by_id, @@ -22,7 +20,6 @@ from ayon_core.client import ( ) from ayon_core.client.operations import ( OperationsSession, - new_asset_document, new_subset_document, new_version_doc, new_representation_doc, @@ -449,15 +446,14 @@ class ProjectPushItemProcess: self._model = model self._item = item - self._src_asset_doc = None + self._src_folder_entity = None self._src_subset_doc = None self._src_version_doc = None self._src_repre_items = None self._project_entity = None self._anatomy = None - self._asset_doc = None - self._created_asset_doc = None + self._folder_entity = None self._task_info = None self._subset_doc = None self._version_doc = None @@ -493,8 +489,8 @@ class ProjectPushItemProcess: self._log_info("Source entities were found") self._fill_destination_project() self._log_info("Destination project was found") - self._fill_or_create_destination_asset() - self._log_info("Destination asset was determined") + self._fill_or_create_destination_folder() + self._log_info("Destination folder was determined") self._determine_product_type() self._determine_publish_template_name() self._determine_product_name() @@ -594,11 +590,13 @@ class ProjectPushItemProcess: )) raise PushToProjectError(self._status.fail_reason) - asset_id = subset_doc["parent"] - asset_doc = get_asset_by_id(src_project_name, asset_id) - if not asset_doc: + folder_id = subset_doc["parent"] + folder_entity = ayon_api.get_folder_by_id( + src_project_name, folder_id, own_attributes=True + ) + if not folder_entity: self._status.set_failed(( - f"Could find asset with id \"{asset_id}\"" + f"Could find folder with id \"{folder_id}\"" f" in project \"{src_project_name}\"" )) raise PushToProjectError(self._status.fail_reason) @@ -624,7 +622,7 @@ class ProjectPushItemProcess: ) raise PushToProjectError(self._status.fail_reason) - self._src_asset_doc = asset_doc + self._src_folder_entity = folder_entity self._src_subset_doc = subset_doc self._src_version_doc = version_doc self._src_repre_items = repre_items @@ -652,50 +650,37 @@ class ProjectPushItemProcess: self._item.dst_project_name ) - def _create_asset( + def _create_folder( self, - src_asset_doc, + src_folder_entity, project_entity, - parent_asset_doc, - asset_name + parent_folder_entity, + folder_name ): parent_id = None - parents = [] - tools = [] - if parent_asset_doc: - parent_id = parent_asset_doc["_id"] - parents = list(parent_asset_doc["data"]["parents"]) - parents.append(parent_asset_doc["name"]) - _tools = parent_asset_doc["data"].get("tools_env") - if _tools: - tools = list(_tools) + if parent_folder_entity: + parent_id = parent_folder_entity["id"] - asset_name_low = asset_name.lower() - other_asset_docs = get_assets( + folder_name_low = folder_name.lower() + other_folder_entities = ayon_api.get_folders( project_entity["name"], - fields=["_id", "name", "data.visualParent"] + parent_ids=[parent_id], + fields={"id", "name"} ) - for other_asset_doc in other_asset_docs: - other_name = other_asset_doc["name"] - other_parent_id = other_asset_doc["data"].get("visualParent") - if other_name.lower() != asset_name_low: + for other_folder_entity in other_folder_entities: + other_name = other_folder_entity["name"] + if other_name.lower() != folder_name_low: continue - if other_parent_id != parent_id: - self._status.set_failed(( - f"Asset with name \"{other_name}\" already" - " exists in different hierarchy." - )) - raise PushToProjectError(self._status.fail_reason) - self._log_debug(( - f"Found already existing asset with name \"{other_name}\"" - f" which match requested name \"{asset_name}\"" + f"Found already existing folder with name \"{other_name}\"" + f" which match requested name \"{folder_name}\"" )) - return get_asset_by_id( - project_entity["name"], other_asset_doc["_id"] + return ayon_api.get_folder_by_id( + project_entity["name"], other_folder_entity["id"] ) + # TODO should we hard pass attribute values? data_keys = ( "clipIn", "clipOut", @@ -708,87 +693,105 @@ class ProjectPushItemProcess: "fps", "pixelAspect", ) - asset_data = { - "visualParent": parent_id, - "parents": parents, - "tasks": {}, - "tools_env": tools + new_folder_attrib = {} + src_attrib = src_folder_entity["attrib"] + for attr_name, attr_value in src_attrib.items(): + if attr_name in data_keys: + new_folder_attrib[attr_name] = attr_value + + new_folder_name = ayon_api.slugify_string(folder_name) + folder_label = None + if new_folder_name != folder_name: + folder_label = folder_name + fodler_create_data = { + "name": folder_name, + # TODO use different folder type? + "folderType": "Folder", } - src_asset_data = src_asset_doc["data"] - for key in data_keys: - if key in src_asset_data: - asset_data[key] = src_asset_data[key] + if parent_id: + fodler_create_data["parentId"] = parent_id - asset_doc = new_asset_document( - asset_name, - project_entity["name"], - parent_id, - parents, - data=asset_data + if folder_label: + fodler_create_data["label"] = folder_label + + if new_folder_attrib: + fodler_create_data["attrib"] = new_folder_attrib + + project_name = project_entity["name"] + response = ayon_api.post( + f"projects/{project_name}/folders", + **fodler_create_data ) - self._operations.create_entity( - project_entity["name"], - asset_doc["type"], - asset_doc + new_folder_entity = ayon_api.get_folder_by_id( + project_name, response.data["id"] ) + # TODO use operations + # self._operations.create_entity( + # project_entity["name"], + # "folder", + # fodler_create_data + # ) self._log_info( - f"Creating new asset with name \"{asset_name}\"" + f"Creating new folder with name \"{folder_name}\"" ) - self._created_asset_doc = asset_doc - return asset_doc + return new_folder_entity - def _fill_or_create_destination_asset(self): + def _fill_or_create_destination_folder(self): dst_project_name = self._item.dst_project_name dst_folder_id = self._item.dst_folder_id dst_task_name = self._item.dst_task_name + dst_task_name_low = dst_task_name.lower() new_folder_name = self._item.new_folder_name if not dst_folder_id and not new_folder_name: self._status.set_failed( - "Push item does not have defined destination asset" + "Push item does not have defined destination folder" ) raise PushToProjectError(self._status.fail_reason) - # Get asset document - parent_asset_doc = None + # Get folder entity + parent_folder_entity = None if dst_folder_id: - parent_asset_doc = get_asset_by_id( + parent_folder_entity = ayon_api.get_folder_by_id( self._item.dst_project_name, self._item.dst_folder_id ) - if not parent_asset_doc: + if not parent_folder_entity: self._status.set_failed( - f"Could find asset with id \"{dst_folder_id}\"" + f"Could find folder with id \"{dst_folder_id}\"" f" in project \"{dst_project_name}\"" ) raise PushToProjectError(self._status.fail_reason) if not new_folder_name: - asset_doc = parent_asset_doc + folder_entity = parent_folder_entity else: - asset_doc = self._create_asset( - self._src_asset_doc, + folder_entity = self._create_folder( + self._src_folder_entity, self._project_entity, - parent_asset_doc, + parent_folder_entity, new_folder_name ) - self._asset_doc = asset_doc + self._folder_entity = folder_entity if not dst_task_name: self._task_info = {} return - asset_path_parts = list(asset_doc["data"]["parents"]) - asset_path_parts.append(asset_doc["name"]) - asset_path = "/".join(asset_path_parts) - asset_tasks = asset_doc.get("data", {}).get("tasks") or {} - task_info = asset_tasks.get(dst_task_name) + folder_path = folder_entity["path"] + folder_tasks = { + task_entity["name"].lower(): task_entity + for task_entity in ayon_api.get_tasks( + dst_project_name, folder_ids=[folder_entity["id"]] + ) + } + task_info = folder_tasks.get(dst_task_name_low) if not task_info: self._status.set_failed( f"Could find task with name \"{dst_task_name}\"" - f" on asset \"{asset_path}\"" + f" on folder \"{folder_path}\"" f" in project \"{dst_project_name}\"" ) raise PushToProjectError(self._status.fail_reason) - # Create copy of task info to avoid changing data in asset document + # Create copy of task info to avoid changing data in task entity task_info = copy.deepcopy(task_info) task_info["name"] = dst_task_name # Fill rest of task information based on task type @@ -836,12 +839,12 @@ class ProjectPushItemProcess: def _determine_product_name(self): product_type = self._product_type - asset_doc = self._asset_doc + folder_entity = self._folder_entity task_info = self._task_info product_name = get_product_name( self._item.dst_project_name, - asset_doc, - task_info.get("name"), + folder_entity, + task_info, self.host_name, product_type, self._item.variant, @@ -854,10 +857,10 @@ class ProjectPushItemProcess: def _make_sure_subset_exists(self): project_name = self._item.dst_project_name - asset_id = self._asset_doc["_id"] + folder_id = self._folder_entity["id"] product_name = self._product_name product_type = self._product_type - subset_doc = get_subset_by_name(project_name, product_name, asset_id) + subset_doc = get_subset_by_name(project_name, product_name, folder_id) if subset_doc: self._subset_doc = subset_doc return subset_doc @@ -866,7 +869,7 @@ class ProjectPushItemProcess: "families": [product_type] } subset_doc = new_subset_document( - product_name, product_type, asset_id, data + product_name, product_type, folder_id, data ) self._operations.create_entity(project_name, "subset", subset_doc) self._subset_doc = subset_doc @@ -961,7 +964,7 @@ class ProjectPushItemProcess: anatomy = self._anatomy formatting_data = get_template_data( self._project_entity, - self._asset_doc, + self._folder_entity, self._task_info.get("name"), self.host_name ) diff --git a/client/ayon_core/tools/push_to_project/ui/window.py b/client/ayon_core/tools/push_to_project/ui/window.py index 4d39075dc3..bc2fc6bf96 100644 --- a/client/ayon_core/tools/push_to_project/ui/window.py +++ b/client/ayon_core/tools/push_to_project/ui/window.py @@ -158,7 +158,7 @@ class PushToContextSelectWindow(QtWidgets.QWidget): main_thread_timer.timeout.connect(self._on_main_thread_timer) show_timer.timeout.connect(self._on_show_timer) user_input_changed_timer.timeout.connect(self._on_user_input_timer) - folder_name_input.textChanged.connect(self._on_new_asset_change) + folder_name_input.textChanged.connect(self._on_new_folder_change) variant_input.textChanged.connect(self._on_variant_change) comment_input.textChanged.connect(self._on_comment_change) @@ -169,7 +169,7 @@ class PushToContextSelectWindow(QtWidgets.QWidget): controller.register_event_callback( "new_folder_name.changed", - self._on_controller_new_asset_change + self._on_controller_new_folder_change ) controller.register_event_callback( "variant.changed", self._on_controller_variant_change @@ -291,7 +291,7 @@ class PushToContextSelectWindow(QtWidgets.QWidget): self.refresh() - def _on_new_asset_change(self, text): + def _on_new_folder_change(self, text): self._new_folder_name_input_text = text self._user_input_changed_timer.start() @@ -319,7 +319,7 @@ class PushToContextSelectWindow(QtWidgets.QWidget): self._comment_input_text = None self._controller.set_user_value_comment(comment) - def _on_controller_new_asset_change(self, event): + def _on_controller_new_folder_change(self, event): folder_name = event["new_folder_name"] if ( self._new_folder_name_input_text is None