Skip to content

Pre and post loader hooks #1222

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged

Conversation

kalisp
Copy link
Member

@kalisp kalisp commented Apr 3, 2025

Changelog Description

This PR introduces new concept of Pre/Post Loader Hooks which could be used by to enhance or modify loading processes without need of modifying official loaders.

The idea is for custom addons to be able to implement their own PrePostLoaderHookPlugin which would be triggered before/after Loader action.

Method to be implemented in PrePostLoaderHookPlugin:

  • pre_load
  • post_load
  • pre_update
  • post_update
  • pre_remove
  • post_remove

The function signature (arguments) to each of the pre/post methods matches the regular LoadPlugin except that post_* methods take an additional result argument which receives the output of the LoadPlugin method call, like simplified:

pre_load()
result = load()
post_load(x, y, z, result=result)

Additional info

Each addon must register its folder with pre/post hooks like this:

    register_loader_hook_plugin_path(loader_hook_dir)

I am testing it with this dummy custom addon which shows hooks for "CopyFile", "FileLoader", "LoadImage" Loaders.
my_custom_addon-1.0.0.zip (outdated example files)

Register example hook to just print all the hook methods

from ayon_core.pipeline.load.plugins import LoaderHookPlugin
from ayon_core.pipeline.load import register_loader_hook_plugin


class LoadHookTest(LoaderHookPlugin):
    @classmethod
    def is_compatible(cls, Loader) -> bool:
        return True

    def pre_load(self, context, name=None, namespace=None, data=None, plugin=None):
        self.log.info("pre_loadaa")

    def post_load(self, context, name=None, namespace=None, data=None, plugin=None, result=None):
        self.log.info("post_load")

    def pre_update(self, container, context, plugin=None):
        self.log.info("pre_update")

    def post_update(self, container, context, plugin=None, result=None):
        self.log.info("post_update")

    def pre_remove(self, container, plugin=None):
        self.log.info("pre_remove")

    def post_remove(self, container, plugin=None, result=None):
        self.log.info("post_remove")
		
		
register_loader_hook_plugin(LoadHookTest)

Or when targeting specific loaders and e.g. writing to a file on disk on each hook call:

from ayon_core.pipeline.load import get_loader_identifier
from ayon_core.pipeline.load.plugins import LoaderHookPlugin


class PrePostCopyFile(LoaderHookPlugin):
    """Example of hook which would be run before and after CopyFile.load()"""
    @classmethod
    def is_compatible(cls, Loader) -> bool:
        identifier = get_loader_identifier(Loader)
        return identifier in {"CopyFile", "FileLoader", "LoadImage"}

    def pre_load(self, context, name=None, namespace=None, data=None, plugin=None):
        self._write("pre_load")

    def post_load(self, context, name=None, namespace=None, data=None, plugin=None, result=None):
        self._write("post_load")

    def pre_update(self, container, context, plugin=None):
        self._write("pre_update")

    def post_update(self, container, context, plugin=None, result=None):
        self._write("post_update")

    def pre_remove(self, container, plugin=None):
        self._write("pre_remove")

    def post_remove(self, container, plugin=None, result=None):
        self._write("post_remove")

    def _write(self, value):
        with open("c:/projects/pre_post_load.txt", "a") as fp:
            fp.write(f"{value}\n")

Testing notes:

  1. update copy_file_hook.py in my_custom_addon however you feel fit for your testing
  2. follow this step

@kalisp kalisp self-assigned this Apr 3, 2025
@ynbot
Copy link
Contributor

ynbot commented Apr 3, 2025

@ynbot ynbot added type: feature Adding something new and exciting to the product size/S labels Apr 3, 2025
@kalisp kalisp linked an issue Apr 3, 2025 that may be closed by this pull request
@ynbot ynbot moved this to Review In Progress in PR reviewing Apr 3, 2025
@BigRoy
Copy link
Collaborator

BigRoy commented Apr 3, 2025

I wonder if new hook plug-ins here make more sense than just an EventSystem 😕 Seems somewhat overkill here.

@kalisp
Copy link
Member Author

kalisp commented Apr 4, 2025

I wonder if new hook plug-ins here make more sense than just an EventSystem 😕 Seems somewhat overkill here.

Had the same question, but they should be blocking, I dont think you can achieve that with events.

@BigRoy
Copy link
Collaborator

BigRoy commented Apr 4, 2025

I wonder if new hook plug-ins here make more sense than just an EventSystem 😕 Seems somewhat overkill here.

Had the same question, but they should be blocking, I dont think you can achieve that with events.

The Event system in AYON is blocking by default, right @iLLiCiTiT ?

@kalisp kalisp requested review from antirotor and iLLiCiTiT April 7, 2025 08:22
We still support older Maya
Plugin is required so it makes sense to bump it up to first position and pass it before args
@kalisp kalisp requested a review from antirotor June 19, 2025 09:19
@kalisp
Copy link
Member Author

kalisp commented Jun 19, 2025

Reordered arguments in pre_, post_ methods.

@kalisp kalisp requested review from BigRoy and iLLiCiTiT June 19, 2025 09:20
):
pass

@abstractmethod
Copy link
Member

@iLLiCiTiT iLLiCiTiT Jun 19, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

One more question, is there a reason that it is required to implement all the methods? I would just remove the abstractmethod except is_compatible which is really required.

Copy link
Member Author

@kalisp kalisp Jun 19, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I feel it forces developer to actually think about (mostly) update process, which might be a bit hidden.

Copy link
Member

@iLLiCiTiT iLLiCiTiT Jun 19, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

But if I want to implement only pre methods then I also have to implement all post methods too, just keep them empty.

@github-project-automation github-project-automation bot moved this from Review In Progress to Merge Requested in PR reviewing Jun 19, 2025
@iLLiCiTiT
Copy link
Member

It is mergable, from my point of view the abstract methods are unnecessary, but I won't be the one who will use it.

@kalisp kalisp merged commit b61d368 into develop Jun 19, 2025
2 checks passed
@kalisp kalisp deleted the feature/AY-2218_Plugin-hooks-Loader-and-Scene-Inventory branch June 19, 2025 10:42
@github-project-automation github-project-automation bot moved this from Merge Requested to Done in PR reviewing Jun 19, 2025
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
size/S sponsored This is directly sponsored by a client or community member type: feature Adding something new and exciting to the product
Projects
Archived in project
Development

Successfully merging this pull request may close these issues.

AY-2218_Plugin hooks - Loader and Scene Inventory
5 participants