[wontfix] Derived plug-in won't load packages from original plug-ins file

Description

When inheriting a Plug-in from another one it seems that any packages the original loaded in its file (e.g. import os) don’t work anymore. As such any calls the plug-in made to those packages will not work and tell you a None type doesn’t have that method.

Reproducable?

Not entirely sure if this is always easily reproducable. But in my case I’m doing something fairly simple. I have pyblish_magenta on my PYTHONPATH and loaded. From this package I inherit from the Alembic extractor in my own package. Upon loading both my plug-in overrides the original one, but it doesn’t process correctly.

from pyblish_magenta.plugins.pipeline import extract_alembic


class ExtractAlembic(extract_alembic.ExtractAlembic):
    """This has been overridden"""

    @property
    def default_options(self):
        # Must import again, because the reference to the module disappears
        # once the plug-in has been loaded and is about to run this property..
        from pyblish_magenta.plugins.pipeline import extract_alembic
        options = extract_alembic.ExtractAlembic.default_options.fget(self)

        # Include Colorbleed user-defined attributes
        options["attrPrefix"] = "cb"

        return options

Note that the “re importing there” is actually something that was a leftover from @marcus working on it. Funnily enough the comment is descriptive but doesn’t seem to fix this particular problem. I remember trying it also without that comment (not sure if that actually made a difference, will try again later today)

This comment by @marcus does give some direction to the issue that it’s likely related to how Pyblish loads a plug-in.

Other than the above I also tried just putting the imports of the original file at the top of this file, that also didn’t work.

Any idea on how to work around this?

I’ve seen this before, an immediate solution would be not to inherit plug-ins, but to copy and modify.

A longer lasting solution is still not inherit, but to instead not store business logic or library functions in plug-ins. Instead, make it actual Python module/package functionality that common plug-ins import and use.

import shared

class ExtractAlembic(pyblish.api.InstancePlugin):
  def process(self, instance):
    shared.my_function()

The inheritance mechanism simply isn’t well supported today, it is due to how Pyblish is guarding against plug-ins not remaining in memory between runs - such that you can update a plug-in on disk or in memory, and be guaranteed that it is updated the next time you run. Technically what is happening is that the superclass you inherit from is removed from memory once the inheritance is complete; brutally breaking the inherited class.

It’s possible both are achievable, in which case the discover() function would be a good place to start looking, but for now I would suggest finding another way to share functionality.

1 Like

Thanks for the clarification. It’s not an immediate problem at this moment since there’s other ways to tackle this, like you mentioned. It felt odd that it didn’t work as I remembered being mentioned somewhere that inheritance is a way for this in Pyblish.

In this particular case I could also have a Collector running last that adds that particular data to the instance. This also means I can use the same more abstract Extractor from Magenta. Plus the fact that I can define what families need that particular data and have others that don’t. Also Validators could then find that data on the instance and even validate.

Hey BigRoy, are by any chance running an api.discover() between when the execution of starts, before that plugin is processed?

plugin_A() # anything, collect, another validator
plugin_B() # perhaps in this plugin api.discover() is triggered directly or indirectly
plugin_C() # will lose access to its imports

So in the studio we have a scenario that a contextplugin will create an instance and Collect, Validate, etc on it.
But since since we are not passing in any plugins, it discovers() and that will make plugin_C lose access to its imports.

I hope I have conveyed the scenario correctly. I just wished to confirm with anyone who may have encountered this issue.

EDIT: Damn, I am sorry to bring up such an old post, I did not realize at the time. I do not know if it is better etiquette to start a new one and reference this or what.