From 04a2f08fea82ce4f546f673d4859f6a6116712ae Mon Sep 17 00:00:00 2001 From: Petr Kalis Date: Thu, 3 Apr 2025 18:05:54 +0200 Subject: [PATCH 01/25] Added new Pre and Post Loader Hooks Added functions to register/deregister them. --- client/ayon_core/pipeline/__init__.py | 24 ++++++++ client/ayon_core/pipeline/load/__init__.py | 24 ++++++++ client/ayon_core/pipeline/load/plugins.py | 66 ++++++++++++++++++++++ 3 files changed, 114 insertions(+) diff --git a/client/ayon_core/pipeline/__init__.py b/client/ayon_core/pipeline/__init__.py index 41bcd0dbd1..c6903f1b8e 100644 --- a/client/ayon_core/pipeline/__init__.py +++ b/client/ayon_core/pipeline/__init__.py @@ -42,6 +42,18 @@ register_loader_plugin_path, deregister_loader_plugin, + discover_loader_pre_hook_plugin, + register_loader_pre_hook_plugin, + deregister_loader_pre_hook_plugin, + register_loader_pre_hook_plugin_path, + deregister_loader_pre_hook_plugin_path, + + discover_loader_post_hook_plugin, + register_loader_post_hook_plugin, + deregister_loader_post_hook_plugin, + register_loader_post_hook_plugin_path, + deregister_loader_post_hook_plugin_path, + load_container, remove_container, update_container, @@ -160,6 +172,18 @@ "register_loader_plugin_path", "deregister_loader_plugin", + "discover_loader_pre_hook_plugin", + "register_loader_pre_hook_plugin", + "deregister_loader_pre_hook_plugin", + "register_loader_pre_hook_plugin_path", + "deregister_loader_pre_hook_plugin_path", + + "discover_loader_post_hook_plugin", + "register_loader_post_hook_plugin", + "deregister_loader_post_hook_plugin", + "register_loader_post_hook_plugin_path", + "deregister_loader_post_hook_plugin_path", + "load_container", "remove_container", "update_container", diff --git a/client/ayon_core/pipeline/load/__init__.py b/client/ayon_core/pipeline/load/__init__.py index bdc5ece620..fdbcaec1b9 100644 --- a/client/ayon_core/pipeline/load/__init__.py +++ b/client/ayon_core/pipeline/load/__init__.py @@ -49,6 +49,18 @@ deregister_loader_plugin_path, register_loader_plugin_path, deregister_loader_plugin, + + discover_loader_pre_hook_plugin, + register_loader_pre_hook_plugin, + deregister_loader_pre_hook_plugin, + register_loader_pre_hook_plugin_path, + deregister_loader_pre_hook_plugin_path, + + discover_loader_post_hook_plugin, + register_loader_post_hook_plugin, + deregister_loader_post_hook_plugin, + register_loader_post_hook_plugin_path, + deregister_loader_post_hook_plugin_path, ) @@ -103,4 +115,16 @@ "deregister_loader_plugin_path", "register_loader_plugin_path", "deregister_loader_plugin", + + "discover_loader_pre_hook_plugin", + "register_loader_pre_hook_plugin", + "deregister_loader_pre_hook_plugin", + "register_loader_pre_hook_plugin_path", + "deregister_loader_pre_hook_plugin_path", + + "discover_loader_post_hook_plugin", + "register_loader_post_hook_plugin", + "deregister_loader_post_hook_plugin", + "register_loader_post_hook_plugin_path", + "deregister_loader_post_hook_plugin_path", ) diff --git a/client/ayon_core/pipeline/load/plugins.py b/client/ayon_core/pipeline/load/plugins.py index b601914acd..553e88c2f7 100644 --- a/client/ayon_core/pipeline/load/plugins.py +++ b/client/ayon_core/pipeline/load/plugins.py @@ -1,5 +1,6 @@ import os import logging +from typing import ClassVar from ayon_core.settings import get_project_settings from ayon_core.pipeline.plugin_discover import ( @@ -264,6 +265,30 @@ class ProductLoaderPlugin(LoaderPlugin): """ +class PreLoadHookPlugin: + """Plugin that should be run before any Loaders in 'loaders' + + Should be used as non-invasive method to enrich core loading process. + Any external studio might want to modify loaded data before or afte + they are loaded without need to override existing core plugins. + """ + loaders: ClassVar[set[str]] + + def process(self, context, name=None, namespace=None, options=None): + pass + +class PostLoadHookPlugin: + """Plugin that should be run after any Loaders in 'loaders' + + Should be used as non-invasive method to enrich core loading process. + Any external studio might want to modify loaded data before or afte + they are loaded without need to override existing core plugins. + loaders: ClassVar[set[str]] + """ + def process(self, context, name=None, namespace=None, options=None): + pass + + def discover_loader_plugins(project_name=None): from ayon_core.lib import Logger from ayon_core.pipeline import get_current_project_name @@ -300,3 +325,44 @@ def deregister_loader_plugin_path(path): def register_loader_plugin_path(path): return register_plugin_path(LoaderPlugin, path) + + +def discover_loader_pre_hook_plugin(project_name=None): + plugins = discover(PreLoadHookPlugin) + return plugins + +def register_loader_pre_hook_plugin(plugin): + return register_plugin(PreLoadHookPlugin, plugin) + + +def deregister_loader_pre_hook_plugin(plugin): + deregister_plugin(PreLoadHookPlugin, plugin) + + +def register_loader_pre_hook_plugin_path(path): + return register_plugin_path(PreLoadHookPlugin, path) + + +def deregister_loader_pre_hook_plugin_path(path): + deregister_plugin_path(PreLoadHookPlugin, path) + + +def discover_loader_post_hook_plugin(): + plugins = discover(PostLoadHookPlugin) + return plugins + + +def register_loader_post_hook_plugin(plugin): + return register_plugin(PostLoadHookPlugin, plugin) + + +def deregister_loader_post_hook_plugin(plugin): + deregister_plugin(PostLoadHookPlugin, plugin) + + +def register_loader_post_hook_plugin_path(path): + return register_plugin_path(PostLoadHookPlugin, path) + + +def deregister_loader_post_hook_plugin_path(path): + deregister_plugin_path(PostLoadHookPlugin, path) From 7ec99b3715e800643a373eb20ccc9df7301ca2ec Mon Sep 17 00:00:00 2001 From: Petr Kalis Date: Thu, 3 Apr 2025 18:06:31 +0200 Subject: [PATCH 02/25] Initial implementation of pre/post loader hooks --- .../ayon_core/tools/loader/models/actions.py | 110 ++++++++++++++++-- 1 file changed, 101 insertions(+), 9 deletions(-) diff --git a/client/ayon_core/tools/loader/models/actions.py b/client/ayon_core/tools/loader/models/actions.py index cfe91cadab..c188bf1609 100644 --- a/client/ayon_core/tools/loader/models/actions.py +++ b/client/ayon_core/tools/loader/models/actions.py @@ -9,6 +9,7 @@ from ayon_core.lib import NestedCacheItem from ayon_core.pipeline.load import ( discover_loader_plugins, + discover_loader_pre_hook_plugin, ProductLoaderPlugin, filter_repre_contexts_by_loader, get_loader_identifier, @@ -17,6 +18,8 @@ load_with_product_contexts, LoadError, IncompatibleLoaderError, + get_loaders_by_name + ) from ayon_core.tools.loader.abstract import ActionItem @@ -50,6 +53,8 @@ def __init__(self, controller): levels=1, lifetime=self.loaders_cache_lifetime) self._repre_loaders = NestedCacheItem( levels=1, lifetime=self.loaders_cache_lifetime) + self._hook_loaders_by_identifier = NestedCacheItem( + levels=1, lifetime=self.loaders_cache_lifetime) def reset(self): """Reset the model with all cached items.""" @@ -58,6 +63,7 @@ def reset(self): self._loaders_by_identifier.reset() self._product_loaders.reset() self._repre_loaders.reset() + self._hook_loaders_by_identifier.reset() def get_versions_action_items(self, project_name, version_ids): """Get action items for given version ids. @@ -143,12 +149,14 @@ def trigger_action_item( ACTIONS_MODEL_SENDER, ) loader = self._get_loader_by_identifier(project_name, identifier) + hooks = self._get_hook_loaders_by_identifier(project_name, identifier) if representation_ids is not None: error_info = self._trigger_representation_loader( loader, options, project_name, representation_ids, + hooks ) elif version_ids is not None: error_info = self._trigger_version_loader( @@ -156,6 +164,7 @@ def trigger_action_item( options, project_name, version_ids, + hooks ) else: raise NotImplementedError( @@ -307,22 +316,40 @@ def _get_loaders(self, project_name): we want to show loaders for? Returns: - tuple[list[ProductLoaderPlugin], list[LoaderPlugin]]: Discovered - loader plugins. + tuple( + list[ProductLoaderPlugin], + list[LoaderPlugin], + ): Discovered loader plugins. """ loaders_by_identifier_c = self._loaders_by_identifier[project_name] product_loaders_c = self._product_loaders[project_name] repre_loaders_c = self._repre_loaders[project_name] + hook_loaders_by_identifier_c = self._hook_loaders_by_identifier[project_name] if loaders_by_identifier_c.is_valid: - return product_loaders_c.get_data(), repre_loaders_c.get_data() + return ( + product_loaders_c.get_data(), + repre_loaders_c.get_data(), + hook_loaders_by_identifier_c.get_data() + ) # Get all representation->loader combinations available for the # index under the cursor, so we can list the user the options. available_loaders = self._filter_loaders_by_tool_name( project_name, discover_loader_plugins(project_name) ) - + hook_loaders_by_identifier = {} + pre_load_hook_plugins = discover_loader_pre_hook_plugin(project_name) + loaders_by_name = get_loaders_by_name() + for hook_plugin in pre_load_hook_plugins: + for load_plugin_name in hook_plugin.loaders: + load_plugin = loaders_by_name.get(load_plugin_name) + if not load_plugin: + continue + if not load_plugin.enabled: + continue + identifier = get_loader_identifier(load_plugin) + hook_loaders_by_identifier.setdefault(identifier, {}).setdefault("pre", []).append(hook_plugin) repre_loaders = [] product_loaders = [] loaders_by_identifier = {} @@ -340,6 +367,8 @@ def _get_loaders(self, project_name): loaders_by_identifier_c.update_data(loaders_by_identifier) product_loaders_c.update_data(product_loaders) repre_loaders_c.update_data(repre_loaders) + hook_loaders_by_identifier_c.update_data(hook_loaders_by_identifier) + return product_loaders, repre_loaders def _get_loader_by_identifier(self, project_name, identifier): @@ -349,6 +378,13 @@ def _get_loader_by_identifier(self, project_name, identifier): loaders_by_identifier = loaders_by_identifier_c.get_data() return loaders_by_identifier.get(identifier) + def _get_hook_loaders_by_identifier(self, project_name, identifier): + if not self._hook_loaders_by_identifier[project_name].is_valid: + self._get_loaders(project_name) + hook_loaders_by_identifier_c = self._hook_loaders_by_identifier[project_name] + hook_loaders_by_identifier_c = hook_loaders_by_identifier_c.get_data() + return hook_loaders_by_identifier_c.get(identifier) + def _actions_sorter(self, action_item): """Sort the Loaders by their order and then their name. @@ -606,6 +642,7 @@ def _trigger_version_loader( options, project_name, version_ids, + hooks=None ): """Trigger version loader. @@ -655,7 +692,7 @@ def _trigger_version_loader( }) return self._load_products_by_loader( - loader, product_contexts, options + loader, product_contexts, options, hooks=hooks ) def _trigger_representation_loader( @@ -664,6 +701,7 @@ def _trigger_representation_loader( options, project_name, representation_ids, + hooks ): """Trigger representation loader. @@ -716,10 +754,16 @@ def _trigger_representation_loader( }) return self._load_representations_by_loader( - loader, repre_contexts, options + loader, repre_contexts, options, hooks ) - def _load_representations_by_loader(self, loader, repre_contexts, options): + def _load_representations_by_loader( + self, + loader, + repre_contexts, + options, + hooks=None + ): """Loops through list of repre_contexts and loads them with one loader Args: @@ -737,12 +781,26 @@ def _load_representations_by_loader(self, loader, repre_contexts, options): if version < 0: version = "Hero" try: + for hook_plugin in hooks.get("pre", []): + hook_plugin.process( + loader, + repre_context, + options=options + ) + load_with_repre_context( loader, repre_context, options=options ) + for hook_plugin in hooks.get("post", []): + hook_plugin.process( + loader, + repre_context, + options=options + ) + except IncompatibleLoaderError as exc: print(exc) error_info.append(( @@ -770,7 +828,13 @@ def _load_representations_by_loader(self, loader, repre_contexts, options): )) return error_info - def _load_products_by_loader(self, loader, version_contexts, options): + def _load_products_by_loader( + self, + loader, + version_contexts, + options, + hooks=None + ): """Triggers load with ProductLoader type of loaders. Warning: @@ -791,12 +855,26 @@ def _load_products_by_loader(self, loader, version_contexts, options): product_name = context.get("product", {}).get("name") or "N/A" product_names.append(product_name) try: + for hook_plugin in hooks.get("pre", []): + hook_plugin.process( + loader, + version_contexts, + options=options + ) + load_with_product_contexts( loader, version_contexts, - options=options + options=options, ) + for hook_plugin in hooks.get("post", []): + hook_plugin.process( + loader, + version_contexts, + options=options + ) + except Exception as exc: formatted_traceback = None if not isinstance(exc, LoadError): @@ -817,12 +895,26 @@ def _load_products_by_loader(self, loader, version_contexts, options): version_context.get("product", {}).get("name") or "N/A" ) try: + for hook_plugin in hooks.get("pre", []): + hook_plugin.process( + loader, + version_contexts, + options=options + ) + load_with_product_context( loader, version_context, options=options ) + for hook_plugin in hooks.get("post", []): + hook_plugin.process( + loader, + version_context, + options=options + ) + except Exception as exc: formatted_traceback = None if not isinstance(exc, LoadError): From e76691ea6e62473a923e9ae576d161a418f5e288 Mon Sep 17 00:00:00 2001 From: Petr Kalis Date: Fri, 4 Apr 2025 15:39:32 +0200 Subject: [PATCH 03/25] Moved usage of hooks out of UI actions to utils It is assumed that utils could be used in some kind 'load API', `actions` are tightly bound to UI loading. --- client/ayon_core/pipeline/load/utils.py | 74 +++++++++++++++++-- .../ayon_core/tools/loader/models/actions.py | 49 ++---------- 2 files changed, 72 insertions(+), 51 deletions(-) diff --git a/client/ayon_core/pipeline/load/utils.py b/client/ayon_core/pipeline/load/utils.py index de8e1676e7..d280aa3407 100644 --- a/client/ayon_core/pipeline/load/utils.py +++ b/client/ayon_core/pipeline/load/utils.py @@ -288,7 +288,13 @@ def get_representation_context(project_name, representation): def load_with_repre_context( - Loader, repre_context, namespace=None, name=None, options=None, **kwargs + Loader, + repre_context, + namespace=None, + name=None, + options=None, + hooks=None, + **kwargs ): # Ensure the Loader is compatible for the representation @@ -322,11 +328,24 @@ def load_with_repre_context( # Deprecated - to be removed in OpenPype 3.16.6 or 3.17.0. loader._fname = get_representation_path_from_context(repre_context) - return loader.load(repre_context, name, namespace, options) + return _load_context( + Loader, + repre_context, + name, + namespace, + options, + hooks + ) def load_with_product_context( - Loader, product_context, namespace=None, name=None, options=None, **kwargs + Loader, + product_context, + namespace=None, + name=None, + options=None, + hooks=None, + **kwargs ): # Ensure options is a dictionary when no explicit options provided @@ -344,12 +363,24 @@ def load_with_product_context( Loader.__name__, product_context["folder"]["path"] ) ) - - return Loader().load(product_context, name, namespace, options) + return _load_context( + Loader, + product_context, + name, + namespace, + options, + hooks + ) def load_with_product_contexts( - Loader, product_contexts, namespace=None, name=None, options=None, **kwargs + Loader, + product_contexts, + namespace=None, + name=None, + options=None, + hooks=None, + **kwargs ): # Ensure options is a dictionary when no explicit options provided @@ -371,8 +402,37 @@ def load_with_product_contexts( Loader.__name__, joined_product_names ) ) + return _load_context( + Loader, + product_contexts, + name, + namespace, + options, + hooks + ) + + +def _load_context(Loader, contexts, hooks, name, namespace, options): + """Helper function to wrap hooks around generic load function. - return Loader().load(product_contexts, name, namespace, options) + Only dynamic part is different context(s) to be loaded. + """ + for hook_plugin in hooks.get("pre", []): + hook_plugin.process( + contexts, + name, + namespace, + options, + ) + load_return = Loader().load(contexts, name, namespace, options) + for hook_plugin in hooks.get("post", []): + hook_plugin.process( + contexts, + name, + namespace, + options, + ) + return load_return def load_container( diff --git a/client/ayon_core/tools/loader/models/actions.py b/client/ayon_core/tools/loader/models/actions.py index c188bf1609..7151dbdaec 100644 --- a/client/ayon_core/tools/loader/models/actions.py +++ b/client/ayon_core/tools/loader/models/actions.py @@ -781,26 +781,14 @@ def _load_representations_by_loader( if version < 0: version = "Hero" try: - for hook_plugin in hooks.get("pre", []): - hook_plugin.process( - loader, - repre_context, - options=options - ) load_with_repre_context( loader, repre_context, - options=options + options=options, + hooks=hooks ) - for hook_plugin in hooks.get("post", []): - hook_plugin.process( - loader, - repre_context, - options=options - ) - except IncompatibleLoaderError as exc: print(exc) error_info.append(( @@ -855,26 +843,12 @@ def _load_products_by_loader( product_name = context.get("product", {}).get("name") or "N/A" product_names.append(product_name) try: - for hook_plugin in hooks.get("pre", []): - hook_plugin.process( - loader, - version_contexts, - options=options - ) - load_with_product_contexts( loader, version_contexts, options=options, + hooks=hooks ) - - for hook_plugin in hooks.get("post", []): - hook_plugin.process( - loader, - version_contexts, - options=options - ) - except Exception as exc: formatted_traceback = None if not isinstance(exc, LoadError): @@ -895,26 +869,13 @@ def _load_products_by_loader( version_context.get("product", {}).get("name") or "N/A" ) try: - for hook_plugin in hooks.get("pre", []): - hook_plugin.process( - loader, - version_contexts, - options=options - ) - load_with_product_context( loader, version_context, - options=options + options=options, + hooks=hooks ) - for hook_plugin in hooks.get("post", []): - hook_plugin.process( - loader, - version_context, - options=options - ) - except Exception as exc: formatted_traceback = None if not isinstance(exc, LoadError): From f10564ffb83dce99bd623aa10b5cb622f6d9ffa5 Mon Sep 17 00:00:00 2001 From: Petr Kalis Date: Fri, 4 Apr 2025 16:25:59 +0200 Subject: [PATCH 04/25] Removed unnecessary functions --- client/ayon_core/pipeline/load/__init__.py | 4 ---- client/ayon_core/pipeline/load/plugins.py | 9 --------- 2 files changed, 13 deletions(-) diff --git a/client/ayon_core/pipeline/load/__init__.py b/client/ayon_core/pipeline/load/__init__.py index fdbcaec1b9..7f9734f94e 100644 --- a/client/ayon_core/pipeline/load/__init__.py +++ b/client/ayon_core/pipeline/load/__init__.py @@ -50,13 +50,11 @@ register_loader_plugin_path, deregister_loader_plugin, - discover_loader_pre_hook_plugin, register_loader_pre_hook_plugin, deregister_loader_pre_hook_plugin, register_loader_pre_hook_plugin_path, deregister_loader_pre_hook_plugin_path, - discover_loader_post_hook_plugin, register_loader_post_hook_plugin, deregister_loader_post_hook_plugin, register_loader_post_hook_plugin_path, @@ -116,13 +114,11 @@ "register_loader_plugin_path", "deregister_loader_plugin", - "discover_loader_pre_hook_plugin", "register_loader_pre_hook_plugin", "deregister_loader_pre_hook_plugin", "register_loader_pre_hook_plugin_path", "deregister_loader_pre_hook_plugin_path", - "discover_loader_post_hook_plugin", "register_loader_post_hook_plugin", "deregister_loader_post_hook_plugin", "register_loader_post_hook_plugin_path", diff --git a/client/ayon_core/pipeline/load/plugins.py b/client/ayon_core/pipeline/load/plugins.py index 553e88c2f7..6b1591221a 100644 --- a/client/ayon_core/pipeline/load/plugins.py +++ b/client/ayon_core/pipeline/load/plugins.py @@ -327,10 +327,6 @@ def register_loader_plugin_path(path): return register_plugin_path(LoaderPlugin, path) -def discover_loader_pre_hook_plugin(project_name=None): - plugins = discover(PreLoadHookPlugin) - return plugins - def register_loader_pre_hook_plugin(plugin): return register_plugin(PreLoadHookPlugin, plugin) @@ -347,11 +343,6 @@ def deregister_loader_pre_hook_plugin_path(path): deregister_plugin_path(PreLoadHookPlugin, path) -def discover_loader_post_hook_plugin(): - plugins = discover(PostLoadHookPlugin) - return plugins - - def register_loader_post_hook_plugin(plugin): return register_plugin(PostLoadHookPlugin, plugin) From 92600726b3e9e08a5f3f7f7d63d3919cf436b011 Mon Sep 17 00:00:00 2001 From: Petr Kalis Date: Fri, 4 Apr 2025 16:27:50 +0200 Subject: [PATCH 05/25] Extracted get_hook_loaders_by_identifier to utils --- client/ayon_core/pipeline/load/__init__.py | 2 ++ client/ayon_core/pipeline/load/utils.py | 32 +++++++++++++++++++ .../ayon_core/tools/loader/models/actions.py | 16 ++-------- 3 files changed, 37 insertions(+), 13 deletions(-) diff --git a/client/ayon_core/pipeline/load/__init__.py b/client/ayon_core/pipeline/load/__init__.py index 7f9734f94e..eaba8cd78d 100644 --- a/client/ayon_core/pipeline/load/__init__.py +++ b/client/ayon_core/pipeline/load/__init__.py @@ -24,6 +24,7 @@ get_loader_identifier, get_loaders_by_name, + get_hook_loaders_by_identifier, get_representation_path_from_context, get_representation_path, @@ -89,6 +90,7 @@ "get_loader_identifier", "get_loaders_by_name", + "get_hook_loaders_by_identifier", "get_representation_path_from_context", "get_representation_path", diff --git a/client/ayon_core/pipeline/load/utils.py b/client/ayon_core/pipeline/load/utils.py index d280aa3407..9d3635a186 100644 --- a/client/ayon_core/pipeline/load/utils.py +++ b/client/ayon_core/pipeline/load/utils.py @@ -16,6 +16,7 @@ ) from ayon_core.pipeline import ( Anatomy, + discover ) log = logging.getLogger(__name__) @@ -1149,3 +1150,34 @@ def filter_containers(containers, project_name): uptodate_containers.append(container) return output + + +def get_hook_loaders_by_identifier(): + """Discovers pre/post hooks for loader plugins. + + Returns: + (dict) {"LoaderName": {"pre": ["PreLoader1"], "post":["PreLoader2]} + """ + # beware of circular imports! + from .plugins import PreLoadHookPlugin, PostLoadHookPlugin + hook_loaders_by_identifier = {} + _get_hook_loaders(hook_loaders_by_identifier, PreLoadHookPlugin, "pre") + _get_hook_loaders(hook_loaders_by_identifier, PostLoadHookPlugin, "post") + return hook_loaders_by_identifier + + +def _get_hook_loaders(hook_loaders_by_identifier, loader_plugin, loader_type): + load_hook_plugins = discover(loader_plugin) + loaders_by_name = get_loaders_by_name() + for hook_plugin in load_hook_plugins: + for load_plugin_name in hook_plugin.loaders: + load_plugin = loaders_by_name.get(load_plugin_name) + if not load_plugin: + continue + if not load_plugin.enabled: + continue + identifier = get_loader_identifier(load_plugin) + (hook_loaders_by_identifier.setdefault(identifier, {}) + .setdefault(loader_type, []).append( + hook_plugin) + ) diff --git a/client/ayon_core/tools/loader/models/actions.py b/client/ayon_core/tools/loader/models/actions.py index 7151dbdaec..71bd0c1289 100644 --- a/client/ayon_core/tools/loader/models/actions.py +++ b/client/ayon_core/tools/loader/models/actions.py @@ -18,7 +18,8 @@ load_with_product_contexts, LoadError, IncompatibleLoaderError, - get_loaders_by_name + get_loaders_by_name, + get_hook_loaders_by_identifier ) from ayon_core.tools.loader.abstract import ActionItem @@ -338,18 +339,7 @@ def _get_loaders(self, project_name): available_loaders = self._filter_loaders_by_tool_name( project_name, discover_loader_plugins(project_name) ) - hook_loaders_by_identifier = {} - pre_load_hook_plugins = discover_loader_pre_hook_plugin(project_name) - loaders_by_name = get_loaders_by_name() - for hook_plugin in pre_load_hook_plugins: - for load_plugin_name in hook_plugin.loaders: - load_plugin = loaders_by_name.get(load_plugin_name) - if not load_plugin: - continue - if not load_plugin.enabled: - continue - identifier = get_loader_identifier(load_plugin) - hook_loaders_by_identifier.setdefault(identifier, {}).setdefault("pre", []).append(hook_plugin) + hook_loaders_by_identifier = get_hook_loaders_by_identifier() repre_loaders = [] product_loaders = [] loaders_by_identifier = {} From 969358d37a73abcbaf09df63137260b089a732df Mon Sep 17 00:00:00 2001 From: Petr Kalis Date: Fri, 4 Apr 2025 16:30:38 +0200 Subject: [PATCH 06/25] Removed missed unnecessary functions --- client/ayon_core/pipeline/__init__.py | 4 ---- client/ayon_core/tools/loader/models/actions.py | 1 - 2 files changed, 5 deletions(-) diff --git a/client/ayon_core/pipeline/__init__.py b/client/ayon_core/pipeline/__init__.py index c6903f1b8e..beb5fa5ac2 100644 --- a/client/ayon_core/pipeline/__init__.py +++ b/client/ayon_core/pipeline/__init__.py @@ -42,13 +42,11 @@ register_loader_plugin_path, deregister_loader_plugin, - discover_loader_pre_hook_plugin, register_loader_pre_hook_plugin, deregister_loader_pre_hook_plugin, register_loader_pre_hook_plugin_path, deregister_loader_pre_hook_plugin_path, - discover_loader_post_hook_plugin, register_loader_post_hook_plugin, deregister_loader_post_hook_plugin, register_loader_post_hook_plugin_path, @@ -172,13 +170,11 @@ "register_loader_plugin_path", "deregister_loader_plugin", - "discover_loader_pre_hook_plugin", "register_loader_pre_hook_plugin", "deregister_loader_pre_hook_plugin", "register_loader_pre_hook_plugin_path", "deregister_loader_pre_hook_plugin_path", - "discover_loader_post_hook_plugin", "register_loader_post_hook_plugin", "deregister_loader_post_hook_plugin", "register_loader_post_hook_plugin_path", diff --git a/client/ayon_core/tools/loader/models/actions.py b/client/ayon_core/tools/loader/models/actions.py index 71bd0c1289..07195f4b05 100644 --- a/client/ayon_core/tools/loader/models/actions.py +++ b/client/ayon_core/tools/loader/models/actions.py @@ -9,7 +9,6 @@ from ayon_core.lib import NestedCacheItem from ayon_core.pipeline.load import ( discover_loader_plugins, - discover_loader_pre_hook_plugin, ProductLoaderPlugin, filter_repre_contexts_by_loader, get_loader_identifier, From 42d869973c40ae8508d620fc904ce29ea5909e10 Mon Sep 17 00:00:00 2001 From: Petr Kalis Date: Fri, 4 Apr 2025 16:42:23 +0200 Subject: [PATCH 07/25] Fixed circular import --- client/ayon_core/pipeline/load/utils.py | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/client/ayon_core/pipeline/load/utils.py b/client/ayon_core/pipeline/load/utils.py index 9d3635a186..910ffb2eac 100644 --- a/client/ayon_core/pipeline/load/utils.py +++ b/client/ayon_core/pipeline/load/utils.py @@ -16,7 +16,6 @@ ) from ayon_core.pipeline import ( Anatomy, - discover ) log = logging.getLogger(__name__) @@ -413,7 +412,7 @@ def load_with_product_contexts( ) -def _load_context(Loader, contexts, hooks, name, namespace, options): +def _load_context(Loader, contexts, name, namespace, options, hooks): """Helper function to wrap hooks around generic load function. Only dynamic part is different context(s) to be loaded. @@ -1160,6 +1159,7 @@ def get_hook_loaders_by_identifier(): """ # beware of circular imports! from .plugins import PreLoadHookPlugin, PostLoadHookPlugin + hook_loaders_by_identifier = {} _get_hook_loaders(hook_loaders_by_identifier, PreLoadHookPlugin, "pre") _get_hook_loaders(hook_loaders_by_identifier, PostLoadHookPlugin, "post") @@ -1167,6 +1167,8 @@ def get_hook_loaders_by_identifier(): def _get_hook_loaders(hook_loaders_by_identifier, loader_plugin, loader_type): + from ..plugin_discover import discover + load_hook_plugins = discover(loader_plugin) loaders_by_name = get_loaders_by_name() for hook_plugin in load_hook_plugins: From 3961f8a5e2282834d6852d49192527365d0e8b8c Mon Sep 17 00:00:00 2001 From: Petr Kalis Date: Fri, 4 Apr 2025 17:07:53 +0200 Subject: [PATCH 08/25] Added get_hook_loaders_by_identifier to pipeline API --- client/ayon_core/pipeline/__init__.py | 3 +++ 1 file changed, 3 insertions(+) diff --git a/client/ayon_core/pipeline/__init__.py b/client/ayon_core/pipeline/__init__.py index beb5fa5ac2..0a805b16dc 100644 --- a/client/ayon_core/pipeline/__init__.py +++ b/client/ayon_core/pipeline/__init__.py @@ -61,6 +61,7 @@ get_representation_path, get_representation_context, get_repres_contexts, + get_hook_loaders_by_identifier ) from .publish import ( @@ -240,6 +241,8 @@ "register_workfile_build_plugin_path", "deregister_workfile_build_plugin_path", + "get_hook_loaders_by_identifier", + # Backwards compatible function names "install", "uninstall", From a963f8c137896ec326695c01fdefa509cde9d510 Mon Sep 17 00:00:00 2001 From: Petr Kalis Date: Fri, 4 Apr 2025 17:08:13 +0200 Subject: [PATCH 09/25] Added get_hook_loaders_by_identifier SceneInventory controller --- client/ayon_core/tools/sceneinventory/control.py | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/client/ayon_core/tools/sceneinventory/control.py b/client/ayon_core/tools/sceneinventory/control.py index 60d9bc77a9..acbd67b14d 100644 --- a/client/ayon_core/tools/sceneinventory/control.py +++ b/client/ayon_core/tools/sceneinventory/control.py @@ -5,6 +5,7 @@ from ayon_core.pipeline import ( registered_host, get_current_context, + get_hook_loaders_by_identifier ) from ayon_core.tools.common_models import HierarchyModel, ProjectsModel @@ -35,6 +36,8 @@ def __init__(self, host=None): self._projects_model = ProjectsModel(self) self._event_system = self._create_event_system() + self._hooks_by_identifier = get_hook_loaders_by_identifier() + def get_host(self) -> HostBase: return self._host @@ -115,6 +118,10 @@ def get_version_items(self, project_name, product_ids): return self._containers_model.get_version_items( project_name, product_ids) + def get_hook_loaders_by_identifier(self): + """Returns lists of pre|post hooks per Loader identifier.""" + return self._hooks_by_identifier + # Site Sync methods def is_sitesync_enabled(self): return self._sitesync_model.is_sitesync_enabled() From 761ef4b4af343496c42a2236b373069210b0758f Mon Sep 17 00:00:00 2001 From: Petr Kalis Date: Fri, 4 Apr 2025 17:08:33 +0200 Subject: [PATCH 10/25] Added update methods for Loader Hooks --- client/ayon_core/pipeline/load/plugins.py | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/client/ayon_core/pipeline/load/plugins.py b/client/ayon_core/pipeline/load/plugins.py index 6b1591221a..af38cf4c45 100644 --- a/client/ayon_core/pipeline/load/plugins.py +++ b/client/ayon_core/pipeline/load/plugins.py @@ -277,6 +277,10 @@ class PreLoadHookPlugin: def process(self, context, name=None, namespace=None, options=None): pass + def update(self, container, context): + pass + + class PostLoadHookPlugin: """Plugin that should be run after any Loaders in 'loaders' @@ -288,6 +292,9 @@ class PostLoadHookPlugin: def process(self, context, name=None, namespace=None, options=None): pass + def update(self, container, context): + pass + def discover_loader_plugins(project_name=None): from ayon_core.lib import Logger From f44b81a7e58c645481b9653378ece6a72f09f154 Mon Sep 17 00:00:00 2001 From: Petr Kalis Date: Fri, 4 Apr 2025 17:09:06 +0200 Subject: [PATCH 11/25] Pass hook_loaders_by_id in SceneInventory view --- client/ayon_core/tools/sceneinventory/view.py | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/client/ayon_core/tools/sceneinventory/view.py b/client/ayon_core/tools/sceneinventory/view.py index bb95e37d4e..75d3d9a680 100644 --- a/client/ayon_core/tools/sceneinventory/view.py +++ b/client/ayon_core/tools/sceneinventory/view.py @@ -1100,11 +1100,16 @@ def _update_containers(self, item_ids, versions): containers_by_id = self._controller.get_containers_by_item_ids( item_ids ) + hook_loaders_by_id = self._controller.get_hook_loaders_by_identifier() try: for item_id, item_version in zip(item_ids, versions): container = containers_by_id[item_id] try: - update_container(container, item_version) + update_container( + container, + item_version, + hook_loaders_by_id + ) except AssertionError: log.warning("Update failed", exc_info=True) self._show_version_error_dialog( From a5c10767fd3352aa2c7772d16b0e04d094b198fd Mon Sep 17 00:00:00 2001 From: Petr Kalis Date: Fri, 4 Apr 2025 17:09:32 +0200 Subject: [PATCH 12/25] Added loader hooks to update_container --- client/ayon_core/pipeline/load/utils.py | 17 +++++++++++++++-- 1 file changed, 15 insertions(+), 2 deletions(-) diff --git a/client/ayon_core/pipeline/load/utils.py b/client/ayon_core/pipeline/load/utils.py index 910ffb2eac..abef1bc500 100644 --- a/client/ayon_core/pipeline/load/utils.py +++ b/client/ayon_core/pipeline/load/utils.py @@ -520,7 +520,7 @@ def remove_container(container): return Loader().remove(container) -def update_container(container, version=-1): +def update_container(container, version=-1, hooks_by_identifier=None): """Update a container""" from ayon_core.pipeline import get_current_project_name @@ -616,7 +616,20 @@ def update_container(container, version=-1): if not path or not os.path.exists(path): raise ValueError("Path {} doesn't exist".format(path)) - return Loader().update(container, context) + loader_identifier = get_loader_identifier(Loader) + hooks = hooks_by_identifier.get(loader_identifier, {}) + for hook_plugin in hooks.get("pre", []): + hook_plugin.update( + context, + container + ) + update_return = Loader().update(container, context) + for hook_plugin in hooks.get("post", []): + hook_plugin.update( + context, + container + ) + return update_return def switch_container(container, representation, loader_plugin=None): From 82ae29dc12ce92ee748b9c19feab40dc80c4b877 Mon Sep 17 00:00:00 2001 From: Petr Kalis Date: Fri, 4 Apr 2025 17:10:47 +0200 Subject: [PATCH 13/25] Lazy initialization of get_hook_loaders_by_identifier --- client/ayon_core/tools/sceneinventory/control.py | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/client/ayon_core/tools/sceneinventory/control.py b/client/ayon_core/tools/sceneinventory/control.py index acbd67b14d..e6fb459129 100644 --- a/client/ayon_core/tools/sceneinventory/control.py +++ b/client/ayon_core/tools/sceneinventory/control.py @@ -36,7 +36,7 @@ def __init__(self, host=None): self._projects_model = ProjectsModel(self) self._event_system = self._create_event_system() - self._hooks_by_identifier = get_hook_loaders_by_identifier() + self._hooks_by_identifier = None def get_host(self) -> HostBase: return self._host @@ -120,6 +120,8 @@ def get_version_items(self, project_name, product_ids): def get_hook_loaders_by_identifier(self): """Returns lists of pre|post hooks per Loader identifier.""" + if self._hooks_by_identifier is None: + self._hooks_by_identifier = get_hook_loaders_by_identifier() return self._hooks_by_identifier # Site Sync methods From f609d2f5c44e2caf18b7f512e207b2eb6aeab856 Mon Sep 17 00:00:00 2001 From: Petr Kalis Date: Fri, 4 Apr 2025 17:19:24 +0200 Subject: [PATCH 14/25] Added switch methods to Loader Hooks --- client/ayon_core/pipeline/load/plugins.py | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/client/ayon_core/pipeline/load/plugins.py b/client/ayon_core/pipeline/load/plugins.py index af38cf4c45..e930f034ce 100644 --- a/client/ayon_core/pipeline/load/plugins.py +++ b/client/ayon_core/pipeline/load/plugins.py @@ -280,6 +280,9 @@ def process(self, context, name=None, namespace=None, options=None): def update(self, container, context): pass + def switch(self, container, context): + pass + class PostLoadHookPlugin: """Plugin that should be run after any Loaders in 'loaders' @@ -295,6 +298,9 @@ def process(self, context, name=None, namespace=None, options=None): def update(self, container, context): pass + def switch(self, container, context): + pass + def discover_loader_plugins(project_name=None): from ayon_core.lib import Logger From 3a2d831ca632fdbfc93bf2789bdc7501424d5262 Mon Sep 17 00:00:00 2001 From: Petr Kalis Date: Fri, 4 Apr 2025 17:20:09 +0200 Subject: [PATCH 15/25] Added Loader Hooks to switch_container --- client/ayon_core/pipeline/load/utils.py | 27 ++++++++++++++++--- .../sceneinventory/switch_dialog/dialog.py | 8 +++++- 2 files changed, 31 insertions(+), 4 deletions(-) diff --git a/client/ayon_core/pipeline/load/utils.py b/client/ayon_core/pipeline/load/utils.py index abef1bc500..94e7ad53a6 100644 --- a/client/ayon_core/pipeline/load/utils.py +++ b/client/ayon_core/pipeline/load/utils.py @@ -632,15 +632,22 @@ def update_container(container, version=-1, hooks_by_identifier=None): return update_return -def switch_container(container, representation, loader_plugin=None): +def switch_container( + container, + representation, + loader_plugin=None, + hooks_by_identifier=None +): """Switch a container to representation Args: container (dict): container information representation (dict): representation entity + loader_plugin (LoaderPlugin) + hooks_by_identifier (dict): {"pre": [PreHookPlugin1], "post":[]} Returns: - function call + return from function call """ from ayon_core.pipeline import get_current_project_name @@ -679,7 +686,21 @@ def switch_container(container, representation, loader_plugin=None): loader = loader_plugin(context) - return loader.switch(container, context) + loader_identifier = get_loader_identifier(loader) + hooks = hooks_by_identifier.get(loader_identifier, {}) + for hook_plugin in hooks.get("pre", []): + hook_plugin.switch( + context, + container + ) + switch_return = loader.switch(container, context) + for hook_plugin in hooks.get("post", []): + hook_plugin.switch( + context, + container + ) + + return switch_return def _fix_representation_context_compatibility(repre_context): diff --git a/client/ayon_core/tools/sceneinventory/switch_dialog/dialog.py b/client/ayon_core/tools/sceneinventory/switch_dialog/dialog.py index a6d88ed44a..c878cad079 100644 --- a/client/ayon_core/tools/sceneinventory/switch_dialog/dialog.py +++ b/client/ayon_core/tools/sceneinventory/switch_dialog/dialog.py @@ -1339,8 +1339,14 @@ def _switch_container( repre_entity = repres_by_name[container_repre_name] error = None + hook_loaders_by_id = self._controller.get_hook_loaders_by_identifier() try: - switch_container(container, repre_entity, loader) + switch_container( + container, + repre_entity, + loader, + hook_loaders_by_id + ) except ( LoaderSwitchNotImplementedError, IncompatibleLoaderError, From 0070edb34b7ff68d79d3bb50593c478c1ab39774 Mon Sep 17 00:00:00 2001 From: Petr Kalis Date: Mon, 7 Apr 2025 09:56:37 +0200 Subject: [PATCH 16/25] Updated docstrings --- client/ayon_core/tools/sceneinventory/control.py | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/client/ayon_core/tools/sceneinventory/control.py b/client/ayon_core/tools/sceneinventory/control.py index e6fb459129..c4e59699c3 100644 --- a/client/ayon_core/tools/sceneinventory/control.py +++ b/client/ayon_core/tools/sceneinventory/control.py @@ -119,7 +119,11 @@ def get_version_items(self, project_name, product_ids): project_name, product_ids) def get_hook_loaders_by_identifier(self): - """Returns lists of pre|post hooks per Loader identifier.""" + """Returns lists of pre|post hooks per Loader identifier. + + Returns: + (dict) {"LoaderName": {"pre": ["PreLoader1"], "post":["PreLoader2]} + """ if self._hooks_by_identifier is None: self._hooks_by_identifier = get_hook_loaders_by_identifier() return self._hooks_by_identifier From 310174fd1a0fba4b0713475bc89e28385fe18e0e Mon Sep 17 00:00:00 2001 From: Petr Kalis Date: Mon, 7 Apr 2025 10:18:19 +0200 Subject: [PATCH 17/25] Fix calling hook --- client/ayon_core/pipeline/load/utils.py | 30 ++++++++++++------------- 1 file changed, 15 insertions(+), 15 deletions(-) diff --git a/client/ayon_core/pipeline/load/utils.py b/client/ayon_core/pipeline/load/utils.py index 94e7ad53a6..d251dff06f 100644 --- a/client/ayon_core/pipeline/load/utils.py +++ b/client/ayon_core/pipeline/load/utils.py @@ -417,16 +417,16 @@ def _load_context(Loader, contexts, name, namespace, options, hooks): Only dynamic part is different context(s) to be loaded. """ - for hook_plugin in hooks.get("pre", []): - hook_plugin.process( + for hook_plugin_cls in hooks.get("pre", []): + hook_plugin_cls().process( contexts, name, namespace, options, ) load_return = Loader().load(contexts, name, namespace, options) - for hook_plugin in hooks.get("post", []): - hook_plugin.process( + for hook_plugin_cls in hooks.get("post", []): + hook_plugin_cls().process( contexts, name, namespace, @@ -618,14 +618,14 @@ def update_container(container, version=-1, hooks_by_identifier=None): loader_identifier = get_loader_identifier(Loader) hooks = hooks_by_identifier.get(loader_identifier, {}) - for hook_plugin in hooks.get("pre", []): - hook_plugin.update( + for hook_plugin_cls in hooks.get("pre", []): + hook_plugin_cls().update( context, container ) update_return = Loader().update(container, context) - for hook_plugin in hooks.get("post", []): - hook_plugin.update( + for hook_plugin_cls in hooks.get("post", []): + hook_plugin_cls().update( context, container ) @@ -688,14 +688,14 @@ def switch_container( loader_identifier = get_loader_identifier(loader) hooks = hooks_by_identifier.get(loader_identifier, {}) - for hook_plugin in hooks.get("pre", []): - hook_plugin.switch( + for hook_plugin_cls in hooks.get("pre", []): + hook_plugin_cls().switch( context, container ) switch_return = loader.switch(container, context) - for hook_plugin in hooks.get("post", []): - hook_plugin.switch( + for hook_plugin_cls in hooks.get("post", []): + hook_plugin_cls().switch( context, container ) @@ -1205,8 +1205,8 @@ def _get_hook_loaders(hook_loaders_by_identifier, loader_plugin, loader_type): load_hook_plugins = discover(loader_plugin) loaders_by_name = get_loaders_by_name() - for hook_plugin in load_hook_plugins: - for load_plugin_name in hook_plugin.loaders: + for hook_plugin_cls in load_hook_plugins: + for load_plugin_name in hook_plugin_cls.loaders: load_plugin = loaders_by_name.get(load_plugin_name) if not load_plugin: continue @@ -1215,5 +1215,5 @@ def _get_hook_loaders(hook_loaders_by_identifier, loader_plugin, loader_type): identifier = get_loader_identifier(load_plugin) (hook_loaders_by_identifier.setdefault(identifier, {}) .setdefault(loader_type, []).append( - hook_plugin) + hook_plugin_cls) ) From a0002774301c859b5b6906dc630500e117fed32f Mon Sep 17 00:00:00 2001 From: Petr Kalis Date: Mon, 7 Apr 2025 10:57:58 +0200 Subject: [PATCH 18/25] Update naming Co-authored-by: Jakub Trllo <43494761+iLLiCiTiT@users.noreply.github.com> --- client/ayon_core/pipeline/load/plugins.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/client/ayon_core/pipeline/load/plugins.py b/client/ayon_core/pipeline/load/plugins.py index e930f034ce..9f9c6c223f 100644 --- a/client/ayon_core/pipeline/load/plugins.py +++ b/client/ayon_core/pipeline/load/plugins.py @@ -284,7 +284,7 @@ def switch(self, container, context): pass -class PostLoadHookPlugin: +class PostLoaderHookPlugin: """Plugin that should be run after any Loaders in 'loaders' Should be used as non-invasive method to enrich core loading process. From d11a8d2731c2e22abf8da7c45103690b6b660535 Mon Sep 17 00:00:00 2001 From: Petr Kalis Date: Mon, 7 Apr 2025 10:58:07 +0200 Subject: [PATCH 19/25] Update naming Co-authored-by: Jakub Trllo <43494761+iLLiCiTiT@users.noreply.github.com> --- client/ayon_core/pipeline/load/plugins.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/client/ayon_core/pipeline/load/plugins.py b/client/ayon_core/pipeline/load/plugins.py index 9f9c6c223f..40a5eeb1a8 100644 --- a/client/ayon_core/pipeline/load/plugins.py +++ b/client/ayon_core/pipeline/load/plugins.py @@ -265,7 +265,7 @@ class ProductLoaderPlugin(LoaderPlugin): """ -class PreLoadHookPlugin: +class PreLoaderHookPlugin: """Plugin that should be run before any Loaders in 'loaders' Should be used as non-invasive method to enrich core loading process. From 70cf7fe5d41d282a23c8e974479ef32112d0081a Mon Sep 17 00:00:00 2001 From: Petr Kalis Date: Mon, 7 Apr 2025 10:58:25 +0200 Subject: [PATCH 20/25] Import annotations Co-authored-by: Jakub Trllo <43494761+iLLiCiTiT@users.noreply.github.com> --- client/ayon_core/pipeline/load/plugins.py | 1 + 1 file changed, 1 insertion(+) diff --git a/client/ayon_core/pipeline/load/plugins.py b/client/ayon_core/pipeline/load/plugins.py index 40a5eeb1a8..4ac1b3076d 100644 --- a/client/ayon_core/pipeline/load/plugins.py +++ b/client/ayon_core/pipeline/load/plugins.py @@ -1,3 +1,4 @@ +from __future__ import annotations import os import logging from typing import ClassVar From 44fc6f75ab1352cc8106543d612cbea64db0d03d Mon Sep 17 00:00:00 2001 From: Petr Kalis Date: Tue, 8 Apr 2025 10:40:52 +0200 Subject: [PATCH 21/25] Typo --- client/ayon_core/pipeline/load/plugins.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/client/ayon_core/pipeline/load/plugins.py b/client/ayon_core/pipeline/load/plugins.py index e930f034ce..4a503d6f1e 100644 --- a/client/ayon_core/pipeline/load/plugins.py +++ b/client/ayon_core/pipeline/load/plugins.py @@ -269,7 +269,7 @@ class PreLoadHookPlugin: """Plugin that should be run before any Loaders in 'loaders' Should be used as non-invasive method to enrich core loading process. - Any external studio might want to modify loaded data before or afte + Any external studio might want to modify loaded data before or after they are loaded without need to override existing core plugins. """ loaders: ClassVar[set[str]] @@ -288,7 +288,7 @@ class PostLoadHookPlugin: """Plugin that should be run after any Loaders in 'loaders' Should be used as non-invasive method to enrich core loading process. - Any external studio might want to modify loaded data before or afte + Any external studio might want to modify loaded data before or after they are loaded without need to override existing core plugins. loaders: ClassVar[set[str]] """ From 2fe9381471c619c2bff46ea0dfb50d4d5f8dc9ce Mon Sep 17 00:00:00 2001 From: Petr Kalis Date: Tue, 8 Apr 2025 10:44:21 +0200 Subject: [PATCH 22/25] Added loaded container to Post process arguments --- client/ayon_core/pipeline/load/plugins.py | 9 ++++++++- client/ayon_core/pipeline/load/utils.py | 1 + 2 files changed, 9 insertions(+), 1 deletion(-) diff --git a/client/ayon_core/pipeline/load/plugins.py b/client/ayon_core/pipeline/load/plugins.py index 4a503d6f1e..1719ee8c07 100644 --- a/client/ayon_core/pipeline/load/plugins.py +++ b/client/ayon_core/pipeline/load/plugins.py @@ -292,7 +292,14 @@ class PostLoadHookPlugin: they are loaded without need to override existing core plugins. loaders: ClassVar[set[str]] """ - def process(self, context, name=None, namespace=None, options=None): + def process( + self, + container, + context, + name=None, + namespace=None, + options=None + ): pass def update(self, container, context): diff --git a/client/ayon_core/pipeline/load/utils.py b/client/ayon_core/pipeline/load/utils.py index d251dff06f..471d93bb63 100644 --- a/client/ayon_core/pipeline/load/utils.py +++ b/client/ayon_core/pipeline/load/utils.py @@ -427,6 +427,7 @@ def _load_context(Loader, contexts, name, namespace, options, hooks): load_return = Loader().load(contexts, name, namespace, options) for hook_plugin_cls in hooks.get("post", []): hook_plugin_cls().process( + load_return, contexts, name, namespace, From fb1879a645e6f16f0bb9dd81349b3cd052b7d91c Mon Sep 17 00:00:00 2001 From: Petr Kalis Date: Tue, 8 Apr 2025 10:46:11 +0200 Subject: [PATCH 23/25] Updated names --- client/ayon_core/pipeline/load/utils.py | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/client/ayon_core/pipeline/load/utils.py b/client/ayon_core/pipeline/load/utils.py index 471d93bb63..718316a4c2 100644 --- a/client/ayon_core/pipeline/load/utils.py +++ b/client/ayon_core/pipeline/load/utils.py @@ -424,16 +424,16 @@ def _load_context(Loader, contexts, name, namespace, options, hooks): namespace, options, ) - load_return = Loader().load(contexts, name, namespace, options) + loaded_container = Loader().load(contexts, name, namespace, options) for hook_plugin_cls in hooks.get("post", []): hook_plugin_cls().process( - load_return, + loaded_container, contexts, name, namespace, options, ) - return load_return + return loaded_container def load_container( @@ -624,13 +624,13 @@ def update_container(container, version=-1, hooks_by_identifier=None): context, container ) - update_return = Loader().update(container, context) + updated_container = Loader().update(container, context) for hook_plugin_cls in hooks.get("post", []): hook_plugin_cls().update( context, container ) - return update_return + return updated_container def switch_container( @@ -694,14 +694,14 @@ def switch_container( context, container ) - switch_return = loader.switch(container, context) + switched_container = loader.switch(container, context) for hook_plugin_cls in hooks.get("post", []): hook_plugin_cls().switch( context, container ) - return switch_return + return switched_container def _fix_representation_context_compatibility(repre_context): From 1e5f5446a77d5b0872a02498d31b4925a9c7cefa Mon Sep 17 00:00:00 2001 From: Petr Kalis Date: Tue, 8 Apr 2025 10:49:04 +0200 Subject: [PATCH 24/25] Renamed loaders to more descriptive --- client/ayon_core/pipeline/load/plugins.py | 5 +++-- client/ayon_core/pipeline/load/utils.py | 2 +- 2 files changed, 4 insertions(+), 3 deletions(-) diff --git a/client/ayon_core/pipeline/load/plugins.py b/client/ayon_core/pipeline/load/plugins.py index 1719ee8c07..26363a40d9 100644 --- a/client/ayon_core/pipeline/load/plugins.py +++ b/client/ayon_core/pipeline/load/plugins.py @@ -272,7 +272,7 @@ class PreLoadHookPlugin: Any external studio might want to modify loaded data before or after they are loaded without need to override existing core plugins. """ - loaders: ClassVar[set[str]] + loader_identifiers: ClassVar[set[str]] def process(self, context, name=None, namespace=None, options=None): pass @@ -290,8 +290,9 @@ class PostLoadHookPlugin: Should be used as non-invasive method to enrich core loading process. Any external studio might want to modify loaded data before or after they are loaded without need to override existing core plugins. - loaders: ClassVar[set[str]] """ + loader_identifiers: ClassVar[set[str]] + def process( self, container, diff --git a/client/ayon_core/pipeline/load/utils.py b/client/ayon_core/pipeline/load/utils.py index 718316a4c2..c61d743d05 100644 --- a/client/ayon_core/pipeline/load/utils.py +++ b/client/ayon_core/pipeline/load/utils.py @@ -1207,7 +1207,7 @@ def _get_hook_loaders(hook_loaders_by_identifier, loader_plugin, loader_type): load_hook_plugins = discover(loader_plugin) loaders_by_name = get_loaders_by_name() for hook_plugin_cls in load_hook_plugins: - for load_plugin_name in hook_plugin_cls.loaders: + for load_plugin_name in hook_plugin_cls.loader_identifiers: load_plugin = loaders_by_name.get(load_plugin_name) if not load_plugin: continue From 8c90fac2b5568cd1e5f38417216d062eab1254bc Mon Sep 17 00:00:00 2001 From: Petr Kalis Date: Tue, 8 Apr 2025 12:36:21 +0200 Subject: [PATCH 25/25] Fix renamed class names --- client/ayon_core/pipeline/load/plugins.py | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/client/ayon_core/pipeline/load/plugins.py b/client/ayon_core/pipeline/load/plugins.py index 02efe5b43a..d069508bfa 100644 --- a/client/ayon_core/pipeline/load/plugins.py +++ b/client/ayon_core/pipeline/load/plugins.py @@ -350,32 +350,32 @@ def register_loader_plugin_path(path): def register_loader_pre_hook_plugin(plugin): - return register_plugin(PreLoadHookPlugin, plugin) + return register_plugin(PreLoaderHookPlugin, plugin) def deregister_loader_pre_hook_plugin(plugin): - deregister_plugin(PreLoadHookPlugin, plugin) + deregister_plugin(PreLoaderHookPlugin, plugin) def register_loader_pre_hook_plugin_path(path): - return register_plugin_path(PreLoadHookPlugin, path) + return register_plugin_path(PreLoaderHookPlugin, path) def deregister_loader_pre_hook_plugin_path(path): - deregister_plugin_path(PreLoadHookPlugin, path) + deregister_plugin_path(PreLoaderHookPlugin, path) def register_loader_post_hook_plugin(plugin): - return register_plugin(PostLoadHookPlugin, plugin) + return register_plugin(PostLoaderHookPlugin, plugin) def deregister_loader_post_hook_plugin(plugin): - deregister_plugin(PostLoadHookPlugin, plugin) + deregister_plugin(PostLoaderHookPlugin, plugin) def register_loader_post_hook_plugin_path(path): - return register_plugin_path(PostLoadHookPlugin, path) + return register_plugin_path(PostLoaderHookPlugin, path) def deregister_loader_post_hook_plugin_path(path): - deregister_plugin_path(PostLoadHookPlugin, path) + deregister_plugin_path(PostLoaderHookPlugin, path)