pyblish / pyblish-base

Pyblish base library - see https://github.com/pyblish/pyblish for details.
Other
127 stars 59 forks source link

Variable family-matching algorithms #305

Closed mottosso closed 8 years ago

mottosso commented 8 years ago

This enables the use of multiple families of an instance to be associated with a plug-in, only when said families are a subset of the families supported by a plug-in.

That's a mouth full!

All algorithms

Algorithm Description
Intersection Include instances that match any supported family of plug-in (default)
Subset Include instances that match all supported families of a plug-in
Exact Include instances that include only supported families of a plug-in


Example

Let's see an example.

from pyblish import api

class GenericPlugin(api.InstancePlugin):

  # Support both models and rigs
  families = ["model", "rig"]

  def process(self, instance):
    # Applies to both models and rigs
    assert "parent_GRP" in instance

class SpecificPlugin(api.InstancePlugin):

  # Support models, but only low-poly models
  families = ["model", "low"]
  match = api.Subset

  def process(self, instance):
    # Applies to only low-poly models
    assert instance.data["polyCount"] < 500

In this example, SpecificPlugin is associated to instances whose family(ies) are a subset of the supported families model and low. If the instance does not have at least both of these, it is not a match.

This is different from GenericPlugin, where only one of the families of an instance need to match any of the supported families of a plug-in.

The match parameter then is a matching algorithm, as provided by standard set functionality.

# 1. Include on any match
assert set(["a", "b"]).intersection(["b", "c"])

# 2. Include on all match
assert set(["a", "b"]).issubset(["a", "b", "c"])

# 3. Include on exact match (note order is independent)
assert set(["a", "b"]) == set(["b", "a"])

The default value for this parameter is api.Intersection to preserve backwards compatibility. The last possible value is api.Exact which means an instance only matches when families of both instance and plug-ins match exactly.

class EdgeCasePlugin(api.InstancePlugin):
  families = ["model", "low", "level21"]
  match = api.Exact

  def process(self, instance):
    assert "specialMember" in instance

See [test_logic.py]() for complete examples.

tokejepsen commented 8 years ago

It all looks good, but I was wondering why you limited the algorithms to Intersection, Subset and Exact?

mottosso commented 8 years ago

but I was wondering why you limited the algorithms to Intersection, Subset and Exact?

I didn't think of it that way, what other algorithms would you like to see? Are you looking to provide your own?

tokejepsen commented 8 years ago

I didn't think of it that way, what other algorithms would you like to see? Are you looking to provide your own?

Yeah, if you wanted to match by something else than the families data member. For example for pyblish-ftrack its expected for required data members to be present. We are currently working around that by returning early, but the plugin is still run which might be confusing for other users.

mottosso commented 8 years ago

Aha, ok. I think that'd be a good topic for a separate feature request. It'd be an entirely new feature, so we'll need to narrow down use-cases and consequences. Off the top of my head, I might worry about every collection of plug-ins defining their own algorithm, making external plug-ins that much less usable, understandable and interchangeable.

Does this feature request at least fulfil the initial requirement from the forums?

tokejepsen commented 8 years ago

Does this feature request at least fulfil the initial requirement from for forums?

It does indeed:-)