From 21914c24d66c82a521220e843b060644bd866aac Mon Sep 17 00:00:00 2001 From: murphy Date: Wed, 23 Feb 2022 11:40:01 +0100 Subject: [PATCH 1/5] Documentation: fixed broken links - fixed wrong .md link - fixed outdated link to deadline docs --- website/docs/module_deadline.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/website/docs/module_deadline.md b/website/docs/module_deadline.md index 88332fd748..3b3221bcb0 100644 --- a/website/docs/module_deadline.md +++ b/website/docs/module_deadline.md @@ -12,11 +12,11 @@ import TabItem from '@theme/TabItem'; For [AWS Thinkbox Deadline](https://www.awsthinkbox.com/deadline) support you need to set a few things up in both OpenPype and Deadline itself -1. Deploy OpenPype executable to all nodes of Deadline farm. See [Install & Run](admin_use) +1. Deploy OpenPype executable to all nodes of Deadline farm. See [Install & Run](admin_use.md) 2. Enable Deadline module it in the [settings](admin_settings_system.md#deadline) -3. Set up *Deadline Web API service*. For more details on how to do it, see [here](https://docs.thinkboxsoftware.com/products/deadline/10.0/1_User%20Manual/manual/web-service.html). +3. Set up *Deadline Web API service*. For more details on how to do it, see [here](https://docs.thinkboxsoftware.com/products/deadline/10.1/1_User%20Manual/manual/web-service.html). 4. Point OpenPype to your deadline webservice URL in the [settings](admin_settings_system.md#deadline) From 2da1f5e1e46f35e7d0f8383b537247ff403844d9 Mon Sep 17 00:00:00 2001 From: Jakub Trllo Date: Wed, 23 Feb 2022 11:47:02 +0100 Subject: [PATCH 2/5] Uset task ids from asset versions before tasks are removed --- .../action_delete_asset.py | 24 ++++++++++++--- .../default_modules/ftrack/lib/avalon_sync.py | 30 ++++++++++++++++--- 2 files changed, 46 insertions(+), 8 deletions(-) diff --git a/openpype/modules/default_modules/ftrack/event_handlers_user/action_delete_asset.py b/openpype/modules/default_modules/ftrack/event_handlers_user/action_delete_asset.py index 676dd80e93..94385a36c5 100644 --- a/openpype/modules/default_modules/ftrack/event_handlers_user/action_delete_asset.py +++ b/openpype/modules/default_modules/ftrack/event_handlers_user/action_delete_asset.py @@ -3,8 +3,9 @@ import uuid from datetime import datetime from bson.objectid import ObjectId -from openpype_modules.ftrack.lib import BaseAction, statics_icon from avalon.api import AvalonMongoDB +from openpype_modules.ftrack.lib import BaseAction, statics_icon +from openpype_modules.ftrack.lib.avalon_sync import create_chunks class DeleteAssetSubset(BaseAction): @@ -554,8 +555,8 @@ class DeleteAssetSubset(BaseAction): ftrack_proc_txt, ", ".join(ftrack_ids_to_delete) )) - entities_by_link_len = ( - self._filter_entities_to_delete(ftrack_ids_to_delete, session) + entities_by_link_len = self._prepare_entities_before_delete( + ftrack_ids_to_delete, session ) for link_len in sorted(entities_by_link_len.keys(), reverse=True): for entity in entities_by_link_len[link_len]: @@ -609,7 +610,7 @@ class DeleteAssetSubset(BaseAction): return self.report_handle(report_messages, project_name, event) - def _filter_entities_to_delete(self, ftrack_ids_to_delete, session): + def _prepare_entities_before_delete(self, ftrack_ids_to_delete, session): """Filter children entities to avoid CircularDependencyError.""" joined_ids_to_delete = ", ".join( ["\"{}\"".format(id) for id in ftrack_ids_to_delete] @@ -638,6 +639,21 @@ class DeleteAssetSubset(BaseAction): parent_ids_to_delete.append(entity["id"]) to_delete_entities.append(entity) + # Unset 'task_id' from AssetVersion entities + # - when task is deleted the asset version is not marked for deletion + task_ids = set( + entity["id"] + for entity in to_delete_entities + if entity.entity_type.lower() == "task" + ) + for chunk in create_chunks(task_ids): + asset_versions = session.query(( + "select id, task_id from AssetVersion where task_id in ({})" + ).format(self.join_query_keys(chunk))).all() + for asset_version in asset_versions: + asset_version["task_id"] = None + session.commit() + entities_by_link_len = collections.defaultdict(list) for entity in to_delete_entities: entities_by_link_len[len(entity["link"])].append(entity) diff --git a/openpype/modules/default_modules/ftrack/lib/avalon_sync.py b/openpype/modules/default_modules/ftrack/lib/avalon_sync.py index 06e8784287..db7c592c9b 100644 --- a/openpype/modules/default_modules/ftrack/lib/avalon_sync.py +++ b/openpype/modules/default_modules/ftrack/lib/avalon_sync.py @@ -33,6 +33,30 @@ CURRENT_DOC_SCHEMAS = { } +def create_chunks(iterable, chunk_size=None): + """Separate iterable into multiple chunks by size. + + Args: + iterable(list|tuple|set): Object that will be separated into chunks. + chunk_size(int): Size of one chunk. Default value is 200. + + Returns: + list: Chunked items. + """ + chunks = [] + if not iterable: + return chunks + + tupled_iterable = tuple(iterable) + iterable_size = len(tupled_iterable) + if chunk_size is None: + chunk_size = 200 + + for idx in range(0, iterable_size, chunk_size): + chunks.append(tupled_iterable[idx:idx + chunk_size]) + return chunks + + def check_regex(name, entity_type, in_schema=None, schema_patterns=None): schema_name = "asset-3.0" if in_schema: @@ -1147,10 +1171,8 @@ class SyncEntitiesFactory: ids_len = len(tupled_ids) chunk_size = int(5000 / ids_len) all_links = [] - for idx in range(0, ids_len, chunk_size): - entity_ids_joined = join_query_keys( - tupled_ids[idx:idx + chunk_size] - ) + for chunk in create_chunks(ftrack_ids, chunk_size): + entity_ids_joined = join_query_keys(chunk) all_links.extend(self.session.query(( "select from_id, to_id from" From 160d3cb12dd5f15f82f329f8e9d724abcdf94f92 Mon Sep 17 00:00:00 2001 From: Jakub Jezek Date: Wed, 23 Feb 2022 15:51:43 +0100 Subject: [PATCH 3/5] resolve: fixing fusion module loading --- openpype/hosts/resolve/api/utils.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/openpype/hosts/resolve/api/utils.py b/openpype/hosts/resolve/api/utils.py index 3dee17cb01..9b3762f328 100644 --- a/openpype/hosts/resolve/api/utils.py +++ b/openpype/hosts/resolve/api/utils.py @@ -70,9 +70,9 @@ def get_resolve_module(): sys.exit() # assign global var and return bmdvr = bmd.scriptapp("Resolve") - # bmdvf = bmd.scriptapp("Fusion") + bmdvf = bmd.scriptapp("Fusion") resolve.api.bmdvr = bmdvr - resolve.api.bmdvf = bmdvr.Fusion() + resolve.api.bmdvf = bmdvf log.info(("Assigning resolve module to " f"`pype.hosts.resolve.api.bmdvr`: {resolve.api.bmdvr}")) log.info(("Assigning resolve module to " From fc4b7e45737afb8b26907e0f21c6e587ab819756 Mon Sep 17 00:00:00 2001 From: Jakub Trllo Date: Wed, 23 Feb 2022 16:12:54 +0100 Subject: [PATCH 4/5] set context environments even for non host applications --- openpype/hooks/pre_global_host_data.py | 11 ++--------- openpype/lib/applications.py | 4 +++- 2 files changed, 5 insertions(+), 10 deletions(-) diff --git a/openpype/hooks/pre_global_host_data.py b/openpype/hooks/pre_global_host_data.py index bae967e25f..9b82e36171 100644 --- a/openpype/hooks/pre_global_host_data.py +++ b/openpype/hooks/pre_global_host_data.py @@ -14,14 +14,6 @@ class GlobalHostDataHook(PreLaunchHook): def execute(self): """Prepare global objects to `data` that will be used for sure.""" - if not self.application.is_host: - self.log.info( - "Skipped hook {}. Application is not marked as host.".format( - self.__class__.__name__ - ) - ) - return - self.prepare_global_data() if not self.data.get("asset_doc"): @@ -49,7 +41,8 @@ class GlobalHostDataHook(PreLaunchHook): "log": self.log }) - prepare_host_environments(temp_data, self.launch_context.env_group) + if app.is_host: + prepare_host_environments(temp_data, self.launch_context.env_group) prepare_context_environments(temp_data) temp_data.pop("log") diff --git a/openpype/lib/applications.py b/openpype/lib/applications.py index 393c83e9be..30e671cfad 100644 --- a/openpype/lib/applications.py +++ b/openpype/lib/applications.py @@ -1508,10 +1508,12 @@ def prepare_context_environments(data, env_group=None): "AVALON_PROJECT": project_doc["name"], "AVALON_ASSET": asset_doc["name"], "AVALON_TASK": task_name, - "AVALON_APP": app.host_name, "AVALON_APP_NAME": app.full_name, "AVALON_WORKDIR": workdir } + if app.is_host: + context_env["AVALON_APP"]: app.host_name + log.debug( "Context environments set:\n{}".format( json.dumps(context_env, indent=4) From 040688ca62904847225b9ea8b0c108b28cab9fb2 Mon Sep 17 00:00:00 2001 From: Jakub Trllo Date: Thu, 24 Feb 2022 09:55:42 +0100 Subject: [PATCH 5/5] fixed app and context data fill --- openpype/hooks/pre_global_host_data.py | 5 ++-- openpype/lib/__init__.py | 4 +-- openpype/lib/applications.py | 38 ++++++++++++++------------ 3 files changed, 24 insertions(+), 23 deletions(-) diff --git a/openpype/hooks/pre_global_host_data.py b/openpype/hooks/pre_global_host_data.py index 9b82e36171..4c85a511ed 100644 --- a/openpype/hooks/pre_global_host_data.py +++ b/openpype/hooks/pre_global_host_data.py @@ -2,7 +2,7 @@ from openpype.api import Anatomy from openpype.lib import ( PreLaunchHook, EnvironmentPrepData, - prepare_host_environments, + prepare_app_environments, prepare_context_environments ) @@ -41,8 +41,7 @@ class GlobalHostDataHook(PreLaunchHook): "log": self.log }) - if app.is_host: - prepare_host_environments(temp_data, self.launch_context.env_group) + prepare_app_environments(temp_data, self.launch_context.env_group) prepare_context_environments(temp_data) temp_data.pop("log") diff --git a/openpype/lib/__init__.py b/openpype/lib/__init__.py index ebe7648ad7..f79c03ed57 100644 --- a/openpype/lib/__init__.py +++ b/openpype/lib/__init__.py @@ -130,7 +130,7 @@ from .applications import ( PostLaunchHook, EnvironmentPrepData, - prepare_host_environments, + prepare_app_environments, prepare_context_environments, get_app_environments_for_context, apply_project_environments_value @@ -261,7 +261,7 @@ __all__ = [ "PreLaunchHook", "PostLaunchHook", "EnvironmentPrepData", - "prepare_host_environments", + "prepare_app_environments", "prepare_context_environments", "get_app_environments_for_context", "apply_project_environments_value", diff --git a/openpype/lib/applications.py b/openpype/lib/applications.py index 30e671cfad..0b51a6629c 100644 --- a/openpype/lib/applications.py +++ b/openpype/lib/applications.py @@ -1295,7 +1295,7 @@ def get_app_environments_for_context( "env": env }) - prepare_host_environments(data, env_group) + prepare_app_environments(data, env_group) prepare_context_environments(data, env_group) # Discard avalon connection @@ -1316,7 +1316,7 @@ def _merge_env(env, current_env): return result -def prepare_host_environments(data, env_group=None, implementation_envs=True): +def prepare_app_environments(data, env_group=None, implementation_envs=True): """Modify launch environments based on launched app and context. Args: @@ -1474,6 +1474,22 @@ def prepare_context_environments(data, env_group=None): ) app = data["app"] + context_env = { + "AVALON_PROJECT": project_doc["name"], + "AVALON_ASSET": asset_doc["name"], + "AVALON_TASK": task_name, + "AVALON_APP_NAME": app.full_name + } + + log.debug( + "Context environments set:\n{}".format( + json.dumps(context_env, indent=4) + ) + ) + data["env"].update(context_env) + if not app.is_host: + return + workdir_data = get_workdir_data( project_doc, asset_doc, task_name, app.host_name ) @@ -1504,22 +1520,8 @@ def prepare_context_environments(data, env_group=None): "Couldn't create workdir because: {}".format(str(exc)) ) - context_env = { - "AVALON_PROJECT": project_doc["name"], - "AVALON_ASSET": asset_doc["name"], - "AVALON_TASK": task_name, - "AVALON_APP_NAME": app.full_name, - "AVALON_WORKDIR": workdir - } - if app.is_host: - context_env["AVALON_APP"]: app.host_name - - log.debug( - "Context environments set:\n{}".format( - json.dumps(context_env, indent=4) - ) - ) - data["env"].update(context_env) + data["env"]["AVALON_APP"] = app.host_name + data["env"]["AVALON_WORKDIR"] = workdir _prepare_last_workfile(data, workdir)