From ff2516e219b5eff574e2ba12c13aff1d9033814c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?F=C3=A9lix=20David?= Date: Wed, 18 Jan 2023 16:47:53 +0100 Subject: [PATCH 01/12] Feature: Keep synced hero representations up-to-date. Fix #4331 --- .../plugins/publish/integrate_hero_version.py | 19 +++++++++++++++++++ 1 file changed, 19 insertions(+) diff --git a/openpype/plugins/publish/integrate_hero_version.py b/openpype/plugins/publish/integrate_hero_version.py index 5f4d284740..c162c83976 100644 --- a/openpype/plugins/publish/integrate_hero_version.py +++ b/openpype/plugins/publish/integrate_hero_version.py @@ -386,6 +386,25 @@ class IntegrateHeroVersion(pyblish.api.InstancePlugin): repre["_id"] = old_repre["_id"] update_data = prepare_representation_update_data( old_repre, repre) + + # Keep previously synchronized sites up-to-date + # by comparing old and new sites and adding old sites + # if missing in new ones + old_repre_files_sites = [ + f.get("sites", []) for f in old_repre.get("files", []) + ] + for i, file in enumerate(repre.get("files", [])): + repre_sites_names = { + s["name"] for s in file.get("sites", []) + } + for site in old_repre_files_sites[i]: + if site["name"] not in repre_sites_names: + # Pop the date to tag for sync + site.pop("created_dt") + file["sites"].append(site) + + update_data["files"][i] = file + op_session.update_entity( project_name, old_repre["type"], From 5476217f6ed17b44cf4fdd02849429ef10774c1c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?F=C3=A9lix=20David?= Date: Wed, 18 Jan 2023 16:59:53 +0100 Subject: [PATCH 02/12] linting --- openpype/plugins/publish/integrate_hero_version.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/openpype/plugins/publish/integrate_hero_version.py b/openpype/plugins/publish/integrate_hero_version.py index c162c83976..427256c137 100644 --- a/openpype/plugins/publish/integrate_hero_version.py +++ b/openpype/plugins/publish/integrate_hero_version.py @@ -404,7 +404,7 @@ class IntegrateHeroVersion(pyblish.api.InstancePlugin): file["sites"].append(site) update_data["files"][i] = file - + op_session.update_entity( project_name, old_repre["type"], From 977d4263cb52e12517d655391f3aec7b6c95b897 Mon Sep 17 00:00:00 2001 From: Petr Kalis Date: Fri, 20 Jan 2023 19:39:52 +0100 Subject: [PATCH 03/12] Fix - addSite loader handles hero version If adding site to representation presence of hero version is checked, if found hero version is marked to be donwloaded too. --- openpype/plugins/load/add_site.py | 57 +++++++++++++++++++++++++++---- 1 file changed, 50 insertions(+), 7 deletions(-) diff --git a/openpype/plugins/load/add_site.py b/openpype/plugins/load/add_site.py index ac931e41db..64567b746a 100644 --- a/openpype/plugins/load/add_site.py +++ b/openpype/plugins/load/add_site.py @@ -2,6 +2,12 @@ from openpype.client import get_linked_representation_id from openpype.modules import ModulesManager from openpype.pipeline import load from openpype.modules.sync_server.utils import SiteAlreadyPresentError +from openpype.client.entities import ( + get_hero_version_by_subset_id, + get_representation_by_id, + get_version_by_id, + get_representation_by_name +) class AddSyncSite(load.LoaderPlugin): @@ -34,15 +40,20 @@ class AddSyncSite(load.LoaderPlugin): return self._sync_server def load(self, context, name=None, namespace=None, data=None): - self.log.info("Adding {} to representation: {}".format( - data["site_name"], data["_id"])) + # self.log wont propagate + print("Adding {} to representation: {}".format( + data["site_name"], data["_id"])) family = context["representation"]["context"]["family"] project_name = data["project_name"] repre_id = data["_id"] site_name = data["site_name"] - self.sync_server.add_site(project_name, repre_id, site_name, - force=True) + representation_ids = self._add_hero_representation_ids(project_name, + repre_id) + + for repre_id in representation_ids: + self.sync_server.add_site(project_name, repre_id, site_name, + force=True) if family == "workfile": links = get_linked_representation_id( @@ -52,9 +63,12 @@ class AddSyncSite(load.LoaderPlugin): ) for link_repre_id in links: try: - self.sync_server.add_site(project_name, link_repre_id, - site_name, - force=False) + representation_ids = self._add_hero_representation_ids( + project_name, link_repre_id) + for repre_id in representation_ids: + self.sync_server.add_site(project_name, repre_id, + site_name, + force=False) except SiteAlreadyPresentError: # do not add/reset working site for references self.log.debug("Site present", exc_info=True) @@ -64,3 +78,32 @@ class AddSyncSite(load.LoaderPlugin): def filepath_from_context(self, context): """No real file loading""" return "" + + def _add_hero_representation_ids(self, project_name, repre_id): + """Find hero version if exists for repre_id. + + Returns: + (list): at least [repre_id] if no hero version found + """ + representation_ids = [repre_id] + + repre_doc = get_representation_by_id( + project_name, repre_id, fields=["_id", "parent", "name"] + ) + + version_doc = get_version_by_id(project_name, repre_doc["parent"]) + if version_doc["type"] != "hero_version": + hero_version = get_hero_version_by_subset_id( + project_name, version_doc["parent"], + fields=["_id", "version_id"] + ) + if (hero_version and + hero_version["version_id"] == version_doc["_id"]): + hero_repre_doc = get_representation_by_name( + project_name, + repre_doc["name"], + hero_version["_id"] + ) + representation_ids.append(hero_repre_doc["_id"]) + + return representation_ids From 7787ee26992ad805a957656f8ca8555349789ec1 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?F=C3=A9lix=20David?= Date: Wed, 25 Jan 2023 13:09:34 +0100 Subject: [PATCH 04/12] fix pop created_dt --- openpype/plugins/publish/integrate_hero_version.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/openpype/plugins/publish/integrate_hero_version.py b/openpype/plugins/publish/integrate_hero_version.py index 427256c137..1a4f4bacfd 100644 --- a/openpype/plugins/publish/integrate_hero_version.py +++ b/openpype/plugins/publish/integrate_hero_version.py @@ -400,7 +400,7 @@ class IntegrateHeroVersion(pyblish.api.InstancePlugin): for site in old_repre_files_sites[i]: if site["name"] not in repre_sites_names: # Pop the date to tag for sync - site.pop("created_dt") + site.pop("created_dt", None) file["sites"].append(site) update_data["files"][i] = file From b5ccd03ebd9ece448b3308d827a4ff50db245198 Mon Sep 17 00:00:00 2001 From: Petr Kalis Date: Wed, 25 Jan 2023 18:25:04 +0100 Subject: [PATCH 05/12] Fix - handle inputLinks and hero version Hero version doesn't store inputLinks, but with changes in comparing it should work. --- openpype/client/entity_links.py | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/openpype/client/entity_links.py b/openpype/client/entity_links.py index e42ac58aff..b74b4ce7f6 100644 --- a/openpype/client/entity_links.py +++ b/openpype/client/entity_links.py @@ -164,7 +164,6 @@ def get_linked_representation_id( # Recursive graph lookup for inputs {"$graphLookup": graph_lookup} ] - conn = get_project_connection(project_name) result = conn.aggregate(query_pipeline) referenced_version_ids = _process_referenced_pipeline_result( @@ -213,7 +212,7 @@ def _process_referenced_pipeline_result(result, link_type): for output in sorted(outputs_recursive, key=lambda o: o["depth"]): output_links = output.get("data", {}).get("inputLinks") - if not output_links: + if not output_links and output["type"] != "hero_version": continue # Leaf @@ -232,6 +231,9 @@ def _process_referenced_pipeline_result(result, link_type): def _filter_input_links(input_links, link_type, correctly_linked_ids): + if not input_links: # to handle hero versions + return + for input_link in input_links: if link_type and input_link["type"] != link_type: continue From 60c6a61779b132e90233a7b3ca83068a5e4a56f8 Mon Sep 17 00:00:00 2001 From: Petr Kalis Date: Wed, 25 Jan 2023 18:27:08 +0100 Subject: [PATCH 06/12] Fix - added docstring --- openpype/plugins/load/add_site.py | 3 +++ 1 file changed, 3 insertions(+) diff --git a/openpype/plugins/load/add_site.py b/openpype/plugins/load/add_site.py index 64567b746a..860e0ef15e 100644 --- a/openpype/plugins/load/add_site.py +++ b/openpype/plugins/load/add_site.py @@ -82,6 +82,9 @@ class AddSyncSite(load.LoaderPlugin): def _add_hero_representation_ids(self, project_name, repre_id): """Find hero version if exists for repre_id. + Args: + project_name (str) + repre_id (ObjectId) Returns: (list): at least [repre_id] if no hero version found """ From 7cb976a01da3255db84109a716bc03f62ce02f42 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?F=C3=A9lix=20David?= Date: Fri, 27 Jan 2023 15:33:07 +0100 Subject: [PATCH 07/12] Fix: import workfile all families --- openpype/hosts/blender/plugins/load/import_workfile.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/openpype/hosts/blender/plugins/load/import_workfile.py b/openpype/hosts/blender/plugins/load/import_workfile.py index 618fb83e31..bbdf1c7ea0 100644 --- a/openpype/hosts/blender/plugins/load/import_workfile.py +++ b/openpype/hosts/blender/plugins/load/import_workfile.py @@ -44,7 +44,7 @@ class AppendBlendLoader(plugin.AssetLoader): """ representations = ["blend"] - families = ["*"] + families = ["workfile"] label = "Append Workfile" order = 9 @@ -68,7 +68,7 @@ class ImportBlendLoader(plugin.AssetLoader): """ representations = ["blend"] - families = ["*"] + families = ["workfile"] label = "Import Workfile" order = 9 From 6894e17bbc9881b847a3a141574d336441b35f84 Mon Sep 17 00:00:00 2001 From: Petr Kalis Date: Wed, 8 Feb 2023 16:18:45 +0100 Subject: [PATCH 08/12] Refactor - use values from context if available Remove unnecessary keys from data --- openpype/plugins/load/add_site.py | 33 +++++++++++++++++++++++-------- openpype/tools/loader/widgets.py | 16 +++++++-------- 2 files changed, 32 insertions(+), 17 deletions(-) diff --git a/openpype/plugins/load/add_site.py b/openpype/plugins/load/add_site.py index 860e0ef15e..f0c9887b66 100644 --- a/openpype/plugins/load/add_site.py +++ b/openpype/plugins/load/add_site.py @@ -40,16 +40,29 @@ class AddSyncSite(load.LoaderPlugin): return self._sync_server def load(self, context, name=None, namespace=None, data=None): + """"Adds site skeleton information on representation_id + + Looks for loaded containers for workfile, adds them site skeleton too + (eg. they should be downloaded too). + Handles hero versions (for representation_id and referenced subsets) + Args: + context (dict): + name (str): + namespace (str): + data (dict): expects {"site_name": SITE_NAME_TO_ADD} + """ # self.log wont propagate print("Adding {} to representation: {}".format( data["site_name"], data["_id"])) - family = context["representation"]["context"]["family"] - project_name = data["project_name"] - repre_id = data["_id"] + project_name = context["project"]["name"] + repre_doc = context["representation"] + family = repre_doc["context"]["family"] + repre_id = [repre_doc["_id"]] site_name = data["site_name"] representation_ids = self._add_hero_representation_ids(project_name, - repre_id) + repre_id, + repre_doc) for repre_id in representation_ids: self.sync_server.add_site(project_name, repre_id, site_name, @@ -79,20 +92,24 @@ class AddSyncSite(load.LoaderPlugin): """No real file loading""" return "" - def _add_hero_representation_ids(self, project_name, repre_id): + def _add_hero_representation_ids(self, project_name, repre_id, + repre_doc=None): """Find hero version if exists for repre_id. Args: project_name (str) repre_id (ObjectId) + repre_doc (dict): repre document for 'repre_id', might be collected + previously Returns: (list): at least [repre_id] if no hero version found """ representation_ids = [repre_id] - repre_doc = get_representation_by_id( - project_name, repre_id, fields=["_id", "parent", "name"] - ) + if not repre_doc: + repre_doc = get_representation_by_id( + project_name, repre_id, fields=["_id", "parent", "name"] + ) version_doc = get_version_by_id(project_name, repre_doc["parent"]) if version_doc["type"] != "hero_version": diff --git a/openpype/tools/loader/widgets.py b/openpype/tools/loader/widgets.py index faef6c8a26..dbf2feb624 100644 --- a/openpype/tools/loader/widgets.py +++ b/openpype/tools/loader/widgets.py @@ -1468,23 +1468,21 @@ class RepresentationWidget(QtWidgets.QWidget): repre_ids = [] data_by_repre_id = {} selected_side = action_representation.get("selected_side") + site_name = "{}_site_name".format(selected_side) is_sync_loader = tools_lib.is_sync_loader(loader) for item in items: - item_id = item.get("_id") - repre_ids.append(item_id) + repre_id = item["_id"] + repre_ids.append(repre_id) if not is_sync_loader: continue - site_name = "{}_site_name".format(selected_side) data_site_name = item.get(site_name) if not data_site_name: continue - data_by_repre_id[item_id] = { - "_id": item_id, - "site_name": data_site_name, - "project_name": self.dbcon.active_project() + data_by_repre_id[repre_id] = { + "site_name": data_site_name } repre_contexts = get_repres_contexts(repre_ids, self.dbcon) @@ -1574,8 +1572,8 @@ def _load_representations_by_loader(loader, repre_contexts, version_name = version_doc.get("name") try: if data_by_repre_id: - _id = repre_context["representation"]["_id"] - data = data_by_repre_id.get(_id) + repre_id = repre_context["representation"]["_id"] + data = data_by_repre_id.get(repre_id) options.update(data) load_with_repre_context( loader, From d9877ae62323cea4099e9c01f2e47caffa4f5d4d Mon Sep 17 00:00:00 2001 From: Petr Kalis Date: Wed, 8 Feb 2023 16:54:20 +0100 Subject: [PATCH 09/12] Refactor - remove explict handling of hero version If representation_id should be added(downloaded) it shouldn't download hero version if downloaded repre is actually latest, eg hero version. They files are completely separate. Hero version should be downloaded explicitly in Loader. --- openpype/plugins/load/add_site.py | 31 +++++++++---------------------- 1 file changed, 9 insertions(+), 22 deletions(-) diff --git a/openpype/plugins/load/add_site.py b/openpype/plugins/load/add_site.py index f0c9887b66..98a390fb30 100644 --- a/openpype/plugins/load/add_site.py +++ b/openpype/plugins/load/add_site.py @@ -44,7 +44,6 @@ class AddSyncSite(load.LoaderPlugin): Looks for loaded containers for workfile, adds them site skeleton too (eg. they should be downloaded too). - Handles hero versions (for representation_id and referenced subsets) Args: context (dict): name (str): @@ -60,13 +59,8 @@ class AddSyncSite(load.LoaderPlugin): repre_id = [repre_doc["_id"]] site_name = data["site_name"] - representation_ids = self._add_hero_representation_ids(project_name, - repre_id, - repre_doc) - - for repre_id in representation_ids: - self.sync_server.add_site(project_name, repre_id, site_name, - force=True) + self.sync_server.add_site(project_name, repre_id, site_name, + force=True) if family == "workfile": links = get_linked_representation_id( @@ -76,12 +70,9 @@ class AddSyncSite(load.LoaderPlugin): ) for link_repre_id in links: try: - representation_ids = self._add_hero_representation_ids( - project_name, link_repre_id) - for repre_id in representation_ids: - self.sync_server.add_site(project_name, repre_id, - site_name, - force=False) + self.sync_server.add_site(project_name, link_repre_id, + site_name, + force=False) except SiteAlreadyPresentError: # do not add/reset working site for references self.log.debug("Site present", exc_info=True) @@ -92,24 +83,20 @@ class AddSyncSite(load.LoaderPlugin): """No real file loading""" return "" - def _add_hero_representation_ids(self, project_name, repre_id, - repre_doc=None): + def _add_hero_representation_ids(self, project_name, repre_id): """Find hero version if exists for repre_id. Args: project_name (str) repre_id (ObjectId) - repre_doc (dict): repre document for 'repre_id', might be collected - previously Returns: (list): at least [repre_id] if no hero version found """ representation_ids = [repre_id] - if not repre_doc: - repre_doc = get_representation_by_id( - project_name, repre_id, fields=["_id", "parent", "name"] - ) + repre_doc = get_representation_by_id( + project_name, repre_id, fields=["_id", "parent", "name"] + ) version_doc = get_version_by_id(project_name, repre_doc["parent"]) if version_doc["type"] != "hero_version": From 4edf16cad6e9b3cab480c57068783af57d0ccd69 Mon Sep 17 00:00:00 2001 From: Petr Kalis Date: Wed, 8 Feb 2023 17:26:48 +0100 Subject: [PATCH 10/12] Fix - updated usage of correct variables --- openpype/plugins/load/add_site.py | 8 +++++--- openpype/plugins/load/remove_site.py | 22 +++++++++++++++------- 2 files changed, 20 insertions(+), 10 deletions(-) diff --git a/openpype/plugins/load/add_site.py b/openpype/plugins/load/add_site.py index 98a390fb30..38c27f9079 100644 --- a/openpype/plugins/load/add_site.py +++ b/openpype/plugins/load/add_site.py @@ -51,13 +51,13 @@ class AddSyncSite(load.LoaderPlugin): data (dict): expects {"site_name": SITE_NAME_TO_ADD} """ # self.log wont propagate - print("Adding {} to representation: {}".format( - data["site_name"], data["_id"])) project_name = context["project"]["name"] repre_doc = context["representation"] family = repre_doc["context"]["family"] - repre_id = [repre_doc["_id"]] + repre_id = repre_doc["_id"] site_name = data["site_name"] + print("Adding {} to representation: {}".format( + data["site_name"], repre_id)) self.sync_server.add_site(project_name, repre_id, site_name, force=True) @@ -70,6 +70,8 @@ class AddSyncSite(load.LoaderPlugin): ) for link_repre_id in links: try: + print("Adding {} to linked representation: {}".format( + data["site_name"], link_repre_id)) self.sync_server.add_site(project_name, link_repre_id, site_name, force=False) diff --git a/openpype/plugins/load/remove_site.py b/openpype/plugins/load/remove_site.py index c5f442b2f5..bea8b1b346 100644 --- a/openpype/plugins/load/remove_site.py +++ b/openpype/plugins/load/remove_site.py @@ -3,7 +3,10 @@ from openpype.pipeline import load class RemoveSyncSite(load.LoaderPlugin): - """Remove sync site and its files on representation""" + """Remove sync site and its files on representation. + + Removes files only on local site! + """ representations = ["*"] families = ["*"] @@ -24,13 +27,18 @@ class RemoveSyncSite(load.LoaderPlugin): return self._sync_server def load(self, context, name=None, namespace=None, data=None): - self.log.info("Removing {} on representation: {}".format( - data["site_name"], data["_id"])) - self.sync_server.remove_site(data["project_name"], - data["_id"], - data["site_name"], + project_name = context["project"]["name"] + repre_doc = context["representation"] + repre_id = repre_doc["_id"] + site_name = data["site_name"] + + print("Removing {} on representation: {}".format(site_name, repre_id)) + + self.sync_server.remove_site(project_name, + repre_id, + site_name, True) - self.log.debug("Site added.") + self.log.debug("Site removed.") def filepath_from_context(self, context): """No real file loading""" From b16af10670181630de0fb1bc700877f46dbfa18d Mon Sep 17 00:00:00 2001 From: Petr Kalis Date: Thu, 9 Feb 2023 16:27:34 +0100 Subject: [PATCH 11/12] Removed obsolete method and imports Fixed in get_linked_representation_id instead --- openpype/plugins/load/add_site.py | 38 ------------------------------- 1 file changed, 38 deletions(-) diff --git a/openpype/plugins/load/add_site.py b/openpype/plugins/load/add_site.py index 38c27f9079..e31f746f51 100644 --- a/openpype/plugins/load/add_site.py +++ b/openpype/plugins/load/add_site.py @@ -2,12 +2,6 @@ from openpype.client import get_linked_representation_id from openpype.modules import ModulesManager from openpype.pipeline import load from openpype.modules.sync_server.utils import SiteAlreadyPresentError -from openpype.client.entities import ( - get_hero_version_by_subset_id, - get_representation_by_id, - get_version_by_id, - get_representation_by_name -) class AddSyncSite(load.LoaderPlugin): @@ -84,35 +78,3 @@ class AddSyncSite(load.LoaderPlugin): def filepath_from_context(self, context): """No real file loading""" return "" - - def _add_hero_representation_ids(self, project_name, repre_id): - """Find hero version if exists for repre_id. - - Args: - project_name (str) - repre_id (ObjectId) - Returns: - (list): at least [repre_id] if no hero version found - """ - representation_ids = [repre_id] - - repre_doc = get_representation_by_id( - project_name, repre_id, fields=["_id", "parent", "name"] - ) - - version_doc = get_version_by_id(project_name, repre_doc["parent"]) - if version_doc["type"] != "hero_version": - hero_version = get_hero_version_by_subset_id( - project_name, version_doc["parent"], - fields=["_id", "version_id"] - ) - if (hero_version and - hero_version["version_id"] == version_doc["_id"]): - hero_repre_doc = get_representation_by_name( - project_name, - repre_doc["name"], - hero_version["_id"] - ) - representation_ids.append(hero_repre_doc["_id"]) - - return representation_ids From 4c98fe735f7151dbd5ba9d5c59879d0cd47f886b Mon Sep 17 00:00:00 2001 From: Ynbot Date: Sat, 11 Feb 2023 03:27:14 +0000 Subject: [PATCH 12/12] [Automated] Bump version --- openpype/version.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/openpype/version.py b/openpype/version.py index 61339fb3dd..8dfd638414 100644 --- a/openpype/version.py +++ b/openpype/version.py @@ -1,3 +1,3 @@ # -*- coding: utf-8 -*- """Package declaring Pype version.""" -__version__ = "3.15.1-nightly.4" +__version__ = "3.15.1-nightly.5"