From e812e8e9630ff423e2cfd4c116a34724315567b8 Mon Sep 17 00:00:00 2001 From: Jakub Trllo Date: Wed, 6 Mar 2024 11:01:26 +0100 Subject: [PATCH] tools use version entity --- .../ayon_core/tools/loader/models/actions.py | 143 +++++++----------- .../tools/loader/models/site_sync.py | 6 +- .../tools/loader/ui/products_delegates.py | 6 +- .../tools/push_to_project/control.py | 29 ++-- .../tools/push_to_project/models/integrate.py | 131 +++++++++------- client/ayon_core/tools/utils/lib.py | 10 +- 6 files changed, 161 insertions(+), 164 deletions(-) diff --git a/client/ayon_core/tools/loader/models/actions.py b/client/ayon_core/tools/loader/models/actions.py index d5da2ca80e..0a1c5b6080 100644 --- a/client/ayon_core/tools/loader/models/actions.py +++ b/client/ayon_core/tools/loader/models/actions.py @@ -7,10 +7,7 @@ import uuid import ayon_api -from ayon_core.client import ( - get_versions, - get_representations, -) +from ayon_core.client import get_representations from ayon_core.pipeline.load import ( discover_loader_plugins, ProductLoaderPlugin, @@ -34,12 +31,12 @@ class LoaderActionsModel: This is probably only part of models that requires to use codebase from 'ayon_core.client' because of backwards compatibility with loaders logic - which are expecting mongo documents. + which are expecting entities. TODOs: Deprecate 'qargparse' usage in loaders and implement conversion of 'ActionItem' to data (and 'from_data'). - Use controller to get entities (documents) -> possible only when + Use controller to get entities -> possible only when loaders are able to handle AYON vs. OpenPype logic. Add missing site sync logic, and if possible remove it from loaders. Implement loader actions to replace load plugins. @@ -367,39 +364,6 @@ class LoaderActionsModel: return action_item.order, action_item.label - def _get_version_docs(self, project_name, version_ids): - """Get version documents for given version ids. - - This function also handles hero versions and copies data from - source version to it. - - Todos: - Remove this function when this is completely rewritten to - use AYON calls. - """ - - version_docs = list(get_versions( - project_name, version_ids=version_ids, hero=True - )) - hero_versions_by_src_id = collections.defaultdict(list) - src_hero_version = set() - for version_doc in version_docs: - if version_doc["type"] != "hero": - continue - version_id = "" - src_hero_version.add(version_id) - hero_versions_by_src_id[version_id].append(version_doc) - - src_versions = [] - if src_hero_version: - src_versions = get_versions(project_name, version_ids=version_ids) - for src_version in src_versions: - src_version_id = src_version["_id"] - for hero_version in hero_versions_by_src_id[src_version_id]: - hero_version["data"] = copy.deepcopy(src_version["data"]) - - return version_docs - def _contexts_for_versions(self, project_name, version_ids): """Get contexts for given version ids. @@ -408,7 +372,7 @@ class LoaderActionsModel: given versions. This method is very similar to '_contexts_for_representations' but the - queries of documents are called in a different order. + queries of entities are called in a different order. Args: project_name (str): Project name. @@ -425,16 +389,18 @@ class LoaderActionsModel: if not project_name and not version_ids: return version_context_by_id, repre_context_by_id - version_docs = self._get_version_docs(project_name, version_ids) - version_docs_by_id = {} - version_docs_by_product_id = collections.defaultdict(list) - for version_doc in version_docs: - version_id = version_doc["_id"] - product_id = version_doc["parent"] - version_docs_by_id[version_id] = version_doc - version_docs_by_product_id[product_id].append(version_doc) + version_entities = ayon_api.get_versions( + project_name, version_ids=version_ids + ) + version_entities_by_id = {} + version_entities_by_product_id = collections.defaultdict(list) + for version_entity in version_entities: + version_id = version_entity["id"] + product_id = version_entity["productId"] + version_entities_by_id[version_id] = version_entity + version_entities_by_product_id[product_id].append(version_entity) - _product_ids = set(version_docs_by_product_id.keys()) + _product_ids = set(version_entities_by_product_id.keys()) _product_entities = ayon_api.get_products( project_name, product_ids=_product_ids ) @@ -448,9 +414,9 @@ class LoaderActionsModel: project_entity = ayon_api.get_project(project_name) - for version_doc in version_docs: - version_id = version_doc["_id"] - product_id = version_doc["parent"] + for version_entity in version_entities_by_id: + version_id = version_entity["id"] + product_id = version_entity["productId"] product_entity = product_entities_by_id[product_id] folder_id = product_entity["folderId"] folder_entity = folder_entities_by_id[folder_id] @@ -458,15 +424,15 @@ class LoaderActionsModel: "project": project_entity, "folder": folder_entity, "product": product_entity, - "version": version_doc, + "version": version_entity, } repre_docs = get_representations( project_name, version_ids=version_ids) for repre_doc in repre_docs: version_id = repre_doc["parent"] - version_doc = version_docs_by_id[version_id] - product_id = version_doc["parent"] + version_entity = version_entities_by_id[version_id] + product_id = version_entity["productId"] product_entity = product_entities_by_id[product_id] folder_id = product_entity["folderId"] folder_entity = folder_entities_by_id[folder_id] @@ -475,7 +441,7 @@ class LoaderActionsModel: "project": project_entity, "folder": folder_entity, "product": product_entity, - "version": version_doc, + "version": version_entity, "representation": repre_doc, } @@ -489,7 +455,7 @@ class LoaderActionsModel: given versions. This method is very similar to '_contexts_for_versions' but the - queries of documents are called in a different order. + queries of entities are called in a different order. Args: project_name (str): Project name. @@ -509,12 +475,14 @@ class LoaderActionsModel: project_name, representation_ids=repre_ids )) version_ids = {r["parent"] for r in repre_docs} - version_docs = self._get_version_docs(project_name, version_ids) - version_docs_by_id = { - v["_id"]: v for v in version_docs + version_entities = ayon_api.get_versions( + project_name, version_ids=version_ids + ) + version_entities_by_id = { + v["id"]: v for v in version_entities } - product_ids = {v["parent"] for v in version_docs_by_id.values()} + product_ids = {v["productId"] for v in version_entities_by_id.values()} product_entities = ayon_api.get_products( project_name, product_ids=product_ids ) @@ -543,8 +511,8 @@ class LoaderActionsModel: for repre_doc in repre_docs: version_id = repre_doc["parent"] - version_doc = version_docs_by_id[version_id] - product_id = version_doc["parent"] + version_entity = version_entities_by_id[version_id] + product_id = version_entity["productId"] product_entity = product_entities_by_id[product_id] folder_id = product_entity["folderId"] folder_entity = folder_entities_by_id[folder_id] @@ -553,7 +521,7 @@ class LoaderActionsModel: "project": project_entity, "folder": folder_entity, "product": product_entity, - "version": version_doc, + "version": version_entity, "representation": repre_doc, } return product_context_by_id, repre_context_by_id @@ -667,8 +635,10 @@ class LoaderActionsModel: project_entity = ayon_api.get_project(project_name) - version_docs = self._get_version_docs(project_name, version_ids) - product_ids = {v["parent"] for v in version_docs} + version_entities = list(ayon_api.get_versions( + project_name, version_ids=version_ids + )) + product_ids = {v["productId"] for v in version_entities} product_entities = ayon_api.get_products( project_name, product_ids=product_ids ) @@ -679,8 +649,8 @@ class LoaderActionsModel: ) folder_entities_by_id = {f["id"]: f for f in folder_entities} product_contexts = [] - for version_doc in version_docs: - product_id = version_doc["parent"] + for version_entity in version_entities: + product_id = version_entity["productId"] product_entity = product_entities_by_id[product_id] folder_id = product_entity["folderId"] folder_entity = folder_entities_by_id[folder_id] @@ -688,7 +658,7 @@ class LoaderActionsModel: "project": project_entity, "folder": folder_entity, "product": product_entity, - "version": version_doc, + "version": version_entity, }) return self._load_products_by_loader( @@ -706,7 +676,7 @@ class LoaderActionsModel: This triggers 'load' method of 'LoaderPlugin' for given representation ids. For that are prepared contexts for each representation, with - all parent documents. + all parent entities. Args: loader (LoaderPlugin): Loader plugin to use. @@ -720,9 +690,13 @@ class LoaderActionsModel: project_name, representation_ids=representation_ids )) version_ids = {r["parent"] for r in repre_docs} - version_docs = self._get_version_docs(project_name, version_ids) - version_docs_by_id = {v["_id"]: v for v in version_docs} - product_ids = {v["parent"] for v in version_docs_by_id.values()} + version_entities = ayon_api.get_versions( + project_name, version_ids=version_ids + ) + version_entities_by_id = {v["id"]: v for v in version_entities} + product_ids = { + v["productId"] for v in version_entities_by_id.values() + } product_entities = ayon_api.get_products( project_name, product_ids=product_ids ) @@ -735,8 +709,8 @@ class LoaderActionsModel: repre_contexts = [] for repre_doc in repre_docs: version_id = repre_doc["parent"] - version_doc = version_docs_by_id[version_id] - product_id = version_doc["parent"] + version_entity = version_entities_by_id[version_id] + product_id = version_entity["productId"] product_entity = product_entities_by_id[product_id] folder_id = product_entity["folderId"] folder_entity = folder_entities_by_id[folder_id] @@ -744,7 +718,7 @@ class LoaderActionsModel: "project": project_entity, "folder": folder_entity, "product": product_entity, - "version": version_doc, + "version": version_entity, "representation": repre_doc, }) @@ -758,18 +732,17 @@ class LoaderActionsModel: Args: loader (LoaderPlugin): Loader plugin to use. repre_contexts (list[dict]): Full info about selected - representations, containing repre, version, product, folder and - project documents. + representations, containing repre, version, product, folder + and project entities. options (dict): Data from options. """ error_info = [] for repre_context in repre_contexts: - version_doc = repre_context["version"] - if version_doc["type"] == "hero_version": - version_name = "Hero" - else: - version_name = version_doc.get("name") + version_entity = repre_context["version"] + version = version_entity["version"] + if version < 0: + version = "Hero" try: load_with_repre_context( loader, @@ -784,7 +757,7 @@ class LoaderActionsModel: None, repre_context["representation"]["name"], repre_context["product"]["name"], - version_name + version )) except Exception as exc: @@ -800,7 +773,7 @@ class LoaderActionsModel: formatted_traceback, repre_context["representation"]["name"], repre_context["product"]["name"], - version_name + version )) return error_info diff --git a/client/ayon_core/tools/loader/models/site_sync.py b/client/ayon_core/tools/loader/models/site_sync.py index 2a6f1558ad..ff30a3e6fa 100644 --- a/client/ayon_core/tools/loader/models/site_sync.py +++ b/client/ayon_core/tools/loader/models/site_sync.py @@ -1,8 +1,10 @@ import collections from ayon_core.lib import Logger -from ayon_core.client.entities import get_representations -from ayon_core.client import get_linked_representation_id +from ayon_core.client import ( + get_representations, + get_linked_representation_id, +) from ayon_core.addon import AddonsManager from ayon_core.tools.ayon_utils.models import NestedCacheItem from ayon_core.tools.loader.abstract import ActionItem diff --git a/client/ayon_core/tools/loader/ui/products_delegates.py b/client/ayon_core/tools/loader/ui/products_delegates.py index 53d35c2bb7..12ed1165ae 100644 --- a/client/ayon_core/tools/loader/ui/products_delegates.py +++ b/client/ayon_core/tools/loader/ui/products_delegates.py @@ -50,9 +50,7 @@ class VersionComboBox(QtWidgets.QComboBox): item = self._items_by_id.get(version_id) if item is None: - label = format_version( - abs(version_item.version), version_item.is_hero - ) + label = format_version(version_item.version) item = QtGui.QStandardItem(label) item.setData(version_id, QtCore.Qt.UserRole) self._items_by_id[version_id] = item @@ -85,7 +83,7 @@ class VersionDelegate(QtWidgets.QStyledItemDelegate): def displayText(self, value, locale): if not isinstance(value, numbers.Integral): return "N/A" - return format_version(abs(value), value < 0) + return format_version(value) def paint(self, painter, option, index): fg_color = index.data(QtCore.Qt.ForegroundRole) diff --git a/client/ayon_core/tools/push_to_project/control.py b/client/ayon_core/tools/push_to_project/control.py index 1bc03d2285..e74bc8c210 100644 --- a/client/ayon_core/tools/push_to_project/control.py +++ b/client/ayon_core/tools/push_to_project/control.py @@ -2,10 +2,7 @@ import threading import ayon_api -from ayon_core.client import ( - get_version_by_id, - get_representations, -) +from ayon_core.client import get_representations from ayon_core.settings import get_project_settings from ayon_core.lib import prepare_template_data from ayon_core.lib.events import QueuedEventSystem @@ -35,7 +32,7 @@ class PushToContextController: self._src_folder_entity = None self._src_folder_task_entities = {} self._src_product_entity = None - self._src_version_doc = None + self._src_version_entity = None self._src_label = None self._submission_enabled = False @@ -75,13 +72,15 @@ class PushToContextController: folder_entity = None task_entities = {} product_entity = None - version_doc = None + version_entity = None if project_name and version_id: - version_doc = get_version_by_id(project_name, version_id) + version_entity = ayon_api.get_version_by_id( + project_name, version_id + ) - if version_doc: + if version_entity: product_entity = ayon_api.get_product_by_id( - project_name, version_doc["parent"] + project_name, version_entity["productId"] ) if product_entity: @@ -100,14 +99,14 @@ class PushToContextController: self._src_folder_entity = folder_entity self._src_folder_task_entities = task_entities self._src_product_entity = product_entity - self._src_version_doc = version_doc + self._src_version_entity = version_entity 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) - comment = version_doc["data"].get("comment") + comment = version_entity["attrib"].get("comment") if comment: self._user_values.set_comment(comment) @@ -218,12 +217,12 @@ class PushToContextController: folder_path = folder_entity["path"] product_entity = self._src_product_entity - version_doc = self._src_version_doc + version_entity = self._src_version_entity return "Source: {}{}/{}/v{:0>3}".format( self._src_project_name, folder_path, product_entity["name"], - version_doc["name"] + version_entity["version"] ) def _get_task_info_from_repre_docs(self, task_entities, repre_docs): @@ -256,10 +255,10 @@ class PushToContextController: def _get_src_variant(self): project_name = self._src_project_name - version_doc = self._src_version_doc + version_entity = self._src_version_entity task_entities = self._src_folder_task_entities repre_docs = get_representations( - project_name, version_ids=[version_doc["_id"]] + project_name, version_ids=[version_entity["id"]] ) task_name, task_type = self._get_task_info_from_repre_docs( task_entities, repre_docs 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 3fe5fa5ea1..91b9a65a8c 100644 --- a/client/ayon_core/tools/push_to_project/models/integrate.py +++ b/client/ayon_core/tools/push_to_project/models/integrate.py @@ -1,7 +1,6 @@ import os import re import copy -import socket import itertools import datetime import sys @@ -10,24 +9,15 @@ import uuid import ayon_api -from ayon_core.client import ( - get_version_by_id, - get_last_version_by_subset_id, - get_version_by_name, - get_representations, -) +from ayon_core.client import get_representations from ayon_core.client.operations import ( OperationsSession, - new_version_doc, new_representation_doc, - prepare_version_update_data, prepare_representation_update_data, ) from ayon_core.addon import AddonsManager from ayon_core.lib import ( StringTemplate, - get_ayon_username, - get_formatted_current_time, source_hash, ) @@ -445,7 +435,7 @@ class ProjectPushItemProcess: self._src_folder_entity = None self._src_product_entity = None - self._src_version_doc = None + self._src_version_entity = None self._src_repre_items = None self._project_entity = None @@ -453,7 +443,7 @@ class ProjectPushItemProcess: self._folder_entity = None self._task_info = None self._product_entity = None - self._version_doc = None + self._version_entity = None self._product_type = None self._product_name = None @@ -570,16 +560,20 @@ class ProjectPushItemProcess: self._log_debug(f"Project '{src_project_name}' found") - version_doc = get_version_by_id(src_project_name, src_version_id) - if not version_doc: + version_entity = ayon_api.get_version_by_id( + src_project_name, src_version_id + ) + if not version_entity: self._status.set_failed(( f"Source version with id \"{src_version_id}\"" f" was not found in project \"{src_project_name}\"" )) raise PushToProjectError(self._status.fail_reason) - product_id = version_doc["parent"] - product_entity = ayon_api.get_product_by_id(src_project_name, product_id) + product_id = version_entity["productId"] + product_entity = ayon_api.get_product_by_id( + src_project_name, product_id + ) if not product_entity: self._status.set_failed(( f"Could find product with id \"{product_id}\"" @@ -621,7 +615,7 @@ class ProjectPushItemProcess: self._src_folder_entity = folder_entity self._src_product_entity = product_entity - self._src_version_doc = version_doc + self._src_version_entity = version_entity self._src_repre_items = repre_items def _fill_destination_project(self): @@ -882,27 +876,42 @@ class ProjectPushItemProcess: project_name = self._item.dst_project_name version = self._item.dst_version - src_version_doc = self._src_version_doc + src_version_entity = self._src_version_entity product_entity = self._product_entity product_id = product_entity["id"] - src_data = src_version_doc["data"] product_type = product_entity["productType"] + src_attrib = src_version_entity["attrib"] + + dst_attrib = {} + for key in { + "productType", + "productTypes", + "families", + "fps", + "pixelAspect", + "clipIn", + "clipOut", + "frameStart", + "frameEnd", + "handleStart", + "handleEnd", + "resolutionWidth", + "resolutionHeight", + "colorSpace", + "source", + "comment", + "description", + "intent", + }: + if key in src_attrib: + dst_attrib[key] = src_attrib[key] - version_data = { - "families": [product_type], - "fps": src_data.get("fps"), - "source": src_data.get("source"), - "machine": socket.gethostname(), - "comment": self._item.comment or "", - "author": get_ayon_username(), - "time": get_formatted_current_time(), - } if version is None: - last_version_doc = get_last_version_by_subset_id( + last_version_entity = ayon_api.get_last_version_by_product_id( project_name, product_id ) - if last_version_doc: - version = int(last_version_doc["name"]) + 1 + if last_version_entity: + version = int(last_version_entity["version"]) + 1 else: version = get_versioning_start( project_name, @@ -913,34 +922,50 @@ class ProjectPushItemProcess: product_name=product_entity["name"] ) - existing_version_doc = get_version_by_name( + existing_version_entity = ayon_api.get_version_by_name( project_name, version, product_id ) # Update existing version - if existing_version_doc: - version_doc = new_version_doc( - version, product_id, version_data, existing_version_doc["_id"] + if existing_version_entity: + ayon_api.patch( + "projects/{}/versions/{}".format( + project_name, existing_version_entity["id"] + ), + **{"attrib": dst_attrib} ) - update_data = prepare_version_update_data( - existing_version_doc, version_doc + version_entity = ayon_api.get_version_by_id( + project_name, existing_version_entity["id"] ) - if update_data: - self._operations.update_entity( - project_name, - "version", - existing_version_doc["_id"], - update_data - ) - self._version_doc = version_doc + # TODO use operations + # self._operations.update_entity( + # project_name, + # "version", + # existing_version_entity["id"], + # update_data + # ) + self._version_entity = version_entity return - version_doc = new_version_doc( - version, product_id, version_data + response = ayon_api.post( + "projects/{}/versions/{}".format( + project_name, existing_version_entity["id"] + ), + **{ + "version": version, + "productId": product_id, + "attrib": dst_attrib, + } ) - self._operations.create_entity(project_name, "version", version_doc) + version_entity = ayon_api.get_version_by_id( + project_name, response.data["id"] + ) + # TODO use operations + # self._operations.create_entity( + # project_name, "version", version_entity + # ) - self._version_doc = version_doc + self._version_entity = version_entity def _integrate_representations(self): try: @@ -951,8 +976,8 @@ class ProjectPushItemProcess: raise def _real_integrate_representations(self): - version_doc = self._version_doc - version_id = version_doc["_id"] + version_entity = self._version_entity + version_id = version_entity["id"] existing_repres = get_representations( self._item.dst_project_name, version_ids=[version_id] @@ -976,7 +1001,7 @@ class ProjectPushItemProcess: "name": self._product_name, "type": self._product_type, }, - "version": version_doc["name"] + "version": version_entity["version"] }) path_template = anatomy.templates[template_name]["path"].replace( diff --git a/client/ayon_core/tools/utils/lib.py b/client/ayon_core/tools/utils/lib.py index 2e70f27da5..741fc1f335 100644 --- a/client/ayon_core/tools/utils/lib.py +++ b/client/ayon_core/tools/utils/lib.py @@ -120,12 +120,12 @@ def paint_image_with_color(image, color): return pixmap -def format_version(value, hero_version=False): +def format_version(value): """Formats integer to displayable version name""" - label = "v{0:03d}".format(value) - if not hero_version: - return label - return "[{}]".format(label) + label = "v{0:03d}".format(abs(value)) + if value < 0: + return "[{}]".format(label) + return label @contextlib.contextmanager