What is the proper way to handle plugins and families?


#1

Let’s consider such situation:
I’ve got some plugins for validating rig, eg. ValidateJointOrients, ValidateNames and ValidateJointsHierarchy. They’re operating on instances with “rig” family.
But after some time the new kind of the rig appeared that do not need the joints hierarchy to be validated (#1). So I’m collecting it as “rig_new_type” and I’m adding this family to families of two other plugins.
Later some newer rig appears and needs all plugins and one more, ValidateState or something (#2) , so I’m creating this new plugin that targets only new family, and adding one more new family to the other tests.

This works, but it does not seem to be a good way, updating families in every plugin that has to be loaded for every new type of publishing.

I know, that the suggested method for managing plugins is to place them in many specific directories and register paths to them when needed (Task specific plugins) so I can register those paths before launching the Pyblish, but I’d just like the user to be able to e.g. open the new scene with different type of rig click refresh in pyblish and publish and while using this option it is not possible.

-The possibility of assigning multiple families to the instance would help with #2 .
-The possibility of activating/deactivating plugins by some other plugin during collection seemed as a workaround that would work with both #1 and #2, that’s why I was asking about it
-To solve #2 I can also create one more instance, create a standard rig and a new rig_new_new :wink: instance that would trigger only additional plugin, but:

  • It could be disabled by the user and the rig would be published without using plugins that it require
  • It would look like two rigs will be published, because there would be two items on the list f instances
  • Some system of hierarchy of families would also work, and I do like this idea, like a famil name “rig.new_tech” would mean rig #1. This is simillar to multiple families of an instance in fact
  • I can also check the rig type, by a filepath or a attributes of the rig, env, or sth, during execution of those plugins, but it seams like a dirty way and plugins that did nothing would be listed as “green”, passed.

So I’d like to ask what is a proper way to deal with such situations. I’d like to mention, that I’m still reading the documentation, discussions and learning pyblish, so this may be a stupid question


#2

Hi @p4vv37,

Great question!

One way of thinking about this problem I think is hierarchical. That is, you have a generic “rig” family, that does things relevant to all rigs. And then a “specificRig” family, for specific things.

For example.

from pyblish import api


# This applies to both rigs in general, but also specific rigs.
class ValidateGenericThings(api.InstancePlugin):
  families = ["rig", "specificRig"]
  order = api.ValidatorOrder

  def process(self, instance):
    assert "out_SEL" in instance, (
      "'%s' didn't have an out_SEL" % instance.data["name"])


# This only applies to specific rigs
class ValidateSpecificThings(api.InstancePlugin):
  families = ["specificRig"]
  order = api.ValidatorOrder

  def process(self, instance):
    assert "specificData" in instance.data, (
      "The specific rig didn't have a 'specificData' member")


class CollectSomeRigs(api.ContextPlugin):
  order = api.CollectorOrder

  def process(self, context):
    rig1 = context.create_instance("GenericRig", family="rig")
    rig2 = context.create_instance("SpecificRig", family="specificRig")

    rig1.append("out_SEL")
    rig2.append("out_SEL")
    rig2.data["specificData"] = True

api.register_plugin(ValidateGenericThings)
api.register_plugin(ValidateSpecificThings)
api.register_plugin(CollectSomeRigs)

from pyblish import util
util.publish()

Notice how instances of family rig is processed by only one of the plug-ins, whereas a specificRig is processed by both.

You can copy/paste this in your Maya Script Editor and run it.

Does this solve your problem?


#3

Hey @p4vv37 :slight_smile:

You can definitely assign multiple families to an instance. This is a newer workflow that is becoming more common:

instance.data["families"] = ["rig", "no_hierarchy", "specialFamily"]

With multiple families also comes maybe a wish for different matching algorithms; https://api.pyblish.com/pages/Plugin.match.html


#4

Thank You both for reply,

@marcus - I’ve mentioned this possibility, yes, it solves the probem, but i thought that there are better ways and that updating plugins this way may not be very convenient

@tokejepsen - I’ll read more about matching but I guess, that multiple families do solve my problem. I thought, that there’s only a “family” argument in instances, not “families”, I should have checked this better before asking

I’ll check it out in action, :grinning: Thanks again.


#5

As about matching algorithms: is plugins_by_families in logic.py of pyblish_base supporting it properly?


#6

Seems like it might be missing from the convenience method :worried:


#7

Ok, I’ve tried to fix this


#8

Hey @p4vv37, how has it gone? Did you find a suitable solution?

I think you might be able to get away with using multiple families, without an alternative algorithm. The default one might be enough.

If you’re having trouble, I can try and put together an example for you.


#9

I’ve accomplished what I wanted with just multiple families, so thanks for support, my problems are no more :slight_smile:


#10

That’s great to hear! :slight_smile:


#11

The convenience function plugins_by_families has been updated in 1.4.4. Thanks @p4vv37!