Skip to content
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

Create & Publish: Attribute definitions per instance #860

Closed

Conversation

iLLiCiTiT
Copy link
Member

@iLLiCiTiT iLLiCiTiT commented Aug 30, 2024

Changelog Description

Create plugins and publish plugins can define attribute definitions per instance. Publish context plugins can also define attributes for instances and instance plugins can define attributes for context.

Additional info

THIS IS NOT FINAL PR

This PR is primarily created to review my current state of work, it might not be merged at the end. Following PR should add option to change instance attributes after creation using callbacks, which might mean that some of the methods will probably change to suit the usecase, which would again mean breaking backwards compatibility.

Testing notes:

Existing plugins should work exactly the same as before this PR.
With changes in this PR it is possible to define different attribute definitions per instance, for create plugin and for publish plugin.
One example could be that an instance have enumerator but with different values, e.g. based on scene location.

I've had some testing scenario, but I'm certain I don't have what might be useful.

@ynbot
Copy link
Contributor

ynbot commented Aug 30, 2024

Task linked: AY-5552 Publisher attr defs per instance

@iLLiCiTiT iLLiCiTiT requested a review from BigRoy August 30, 2024 15:51
@ynbot ynbot added size/S type: enhancement Improvement of existing functionality or minor addition labels Aug 30, 2024
Comment on lines 366 to 376
def _create_instance(
self, product_type: str, product_name: str, data: Dict[str, Any]
) -> CreatedInstance:
instance = CreatedInstance(
product_type,
product_name,
data,
creator=self,
)
self._add_instance_to_context(instance)
return instance
Copy link
Collaborator

Choose a reason for hiding this comment

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

Why is this needed?

Copy link
Member Author

@iLLiCiTiT iLLiCiTiT Sep 3, 2024

Choose a reason for hiding this comment

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

Just helper method for creators. Not needed, but you don't have to import CreatedInstance and call _add_instance_to_context manually to create one.

client/ayon_core/pipeline/publish/publish_plugins.py Outdated Show resolved Hide resolved
Comment on lines +567 to +575
def get_attr_defs_for_instance(self, instance):
"""Get attribute definitions for an instance.

Args:
instance (CreatedInstance): Instance for which to get
attribute definitions.

"""
return self.get_instance_attr_defs()
Copy link
Collaborator

Choose a reason for hiding this comment

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

So - how dynamic is this? Like, from the CreatedInstance to what data in it are we allowed to respond to make the returned attribute definitions unique? E.g. technically we can now differentiate attribute defs based on "other attributes" on the instance - however I wonder whether that's intended 'feature'?

  • Can we rely on doing something different based on e.g. folder path or task? If so, what happens if someone without resets confirms a target folder path change from within the UI? Does it refresh?
  • Can we rely on doing something differently based on e.g. families on the instance if it has it?
  • Can we rely on doing something based off of other attributes on the instance from other plug-ins, I suppose not? Since it'd only update on reset?

Copy link
Member Author

@iLLiCiTiT iLLiCiTiT Sep 3, 2024

Choose a reason for hiding this comment

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

Can we rely on doing something differently based on e.g. families on the instance if it has it?

Yes, but if I may request, please do not use families for it if possible. We can discuss each individual use-case (not here).

Why: In case of USD, you probably should be adding families based on the definitions, instead of showing definitions based on families? Meaning, you can add "isUsdInstance": True on instance data to know if is related to USD or not (please take this as very very basic example).

Can we rely on doing something different based on e.g. folder path or task? If so, what happens if someone without resets confirms a target folder path change from within the UI? Does it refresh?

Can we rely on doing something based off of other attributes on the instance from other plug-ins, I suppose not? Since it'd only update on reset?

Both question have same answer. Right now it collects definitions only when instance is created or collected (on create and on reset). For "real time update" we need callbacks. Future PR mentioned in description, which I think might require change of the methods or create context api.

Copy link
Collaborator

@BigRoy BigRoy Sep 3, 2024

Choose a reason for hiding this comment

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

Why: In case of USD, you probably should be adding families based on the definitions, instead of showing definitions based on families? Meaning, you can add "isUsdInstance": True on instance data to know if is related to USD or not (please take this as very very basic example).

I see, but preferably we work towards something similar to families (like standardizes like that, alsmost like "tags") but for the instance's features instead instead of resulting in TONS and TONS of isUsdInstance=True and isFbxInstance=True. Stepping away from pyblish terminology like families, yes! But just doing for example targetProductTypes = {"fbx", "usd"} or whatever name we come up seems like something we can standardize way better. Or maybe better yet, have a dedicated attribute for that on the instance. E.g. being able to do something like:

if instance.supports("usd"):
    # bla

Likely overlaps tons with @antirotor work with OpenAssetIO but that's a can of worms I'm afraid to touch. :)


Both question have same answer. Right now it collects definitions only when instance is created or collected (on create and on reset). For "real time update" we need callbacks. Future PR mentioned in description, which I think might require change of the methods or create context api.

👍

Copy link
Member Author

@iLLiCiTiT iLLiCiTiT Sep 3, 2024

Choose a reason for hiding this comment

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

Because I don't know the context, I can't react. Only from what you wrote I have 10 following questions that will raise another questions. Maybe with full context I would agree, but at this moment I don't.

It is possible to do anything, we should just discuss what would be the ideal approach, to make it clear from data flow.

Like I've said (wrote) we can discuss that out of this PR, as it is not directly related, and it requires more minds.

@BigRoy
Copy link
Collaborator

BigRoy commented Sep 5, 2024

So I have some use cases for this that I'd like to implement soon - as a means to testing this PR, but there's one big worry that I have: performance. @iLLiCiTiT

Let me explain the use cases:

  • For Maya instances (and a client ticket) I'd like to set the default frame range for an instance to the target folder entity or task entity's frame range instead of the scene's frame range. As such, I'd now need to query the folder/task entity for each of the instances, in this method. Which would result in many queries, per instance. Is there some sort of shared cache I could abuse? Or for this case, should the instances provide access to the folder and task entities on the CreatedInstance itself?
  • For Maya Review instances I'd like to set the review resolution width/height to a default, also based off the target folder or task.
  • For Deadline instances I'd like to collect the pools to make them enums instead of raw string attributes and the same goes for "machine list" where it can be an enum of the available Workers, etc. - this would need to be based off of the "deadline url" set on the instance because I believe that can be defined per instance -- although I have no idea what defines that URL?

Having the defaults update related to the instance for attributes may also make #153 and #146 more sensible to implement.
What are your thoughts?

@BigRoy
Copy link
Collaborator

BigRoy commented Sep 5, 2024

Calling instance.data_to_store() on the CreatedInstance in get_attr_defs_for_instance() raises:

//   File "E:\dev\ayon-core\client\ayon_core\pipeline\create\context.py", line 1037, in reset_instances
//     creator.collect_instances()
//   File "E:\dev\ayon-maya\client\ayon_maya\api\plugin.py", line 293, in collect_instances
//     return self._default_collect_instances()
//   File "E:\dev\ayon-maya\client\ayon_maya\api\plugin.py", line 234, in _default_collect_instances
//     created_instance = CreatedInstance.from_existing(node_data, self)
//   File "E:\dev\ayon-core\client\ayon_core\pipeline\create\structures.py", line 716, in from_existing
//     return cls(
//   File "E:\dev\ayon-core\client\ayon_core\pipeline\create\structures.py", line 479, in __init__
//     creator_attr_defs = creator.get_attr_defs_for_instance(self)
//   File "E:\dev\ayon-maya\client\ayon_maya\plugins\create\create_review.py", line 100, in get_attr_defs_for_instance
//     print(instance.data_to_store())
//   File "E:\dev\ayon-core\client\ayon_core\pipeline\create\structures.py", line 689, in data_to_store
//     output["creator_attributes"] = self.creator_attributes.data_to_store()
//   File "E:\dev\ayon-core\client\ayon_core\pipeline\create\structures.py", line 654, in creator_attributes
//     return self._data["creator_attributes"]

If I try to get the folder path or task name for the instance, I can't find it?

print(instance.items())
# odict_items([('id', 'pyblish.avalon.instance'), ('productType', 'review'), ('productName', 'reviewMain'), ('active', True), ('creator_identifier', 'io.openpype.creators.maya.review'), ('variant', '')])

Also, variant is an empty value?

@MustafaJafar MustafaJafar self-requested a review September 9, 2024 08:38
…er-instance

# Conflicts:
#	client/ayon_core/pipeline/create/structures.py
@iLLiCiTiT
Copy link
Member Author

Calling instance.data_to_store() on the CreatedInstance in get_attr_defs_for_instance() raises:

Should be fixed, but I would recommend to not use data_to_store there, rather get only values you need...

Copy link
Contributor

@MustafaJafar MustafaJafar left a comment

Choose a reason for hiding this comment

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

Hey,
I tested this PR against ynput/ayon-houdini#2
I applied the following modification to these lines: renamed the method + add the if condition.

    def get_attr_defs_for_instance(self, instance):
        """get instance attribute definitions.

        Attributes defined in this method are exposed in
            publish tab in the publisher UI.
        """

        if instance["productType"] != "render":
            return []

and it I was able to change the attr defs per instances.
My code skips adding review and render target parameters for non render products.

non render product render product
image image

tbh, I find it hard to furtherly test this PR.

@iLLiCiTiT
Copy link
Member Author

I find it hard to furtherly test this PR.

I don't know if there is anything else to test?

@MustafaJafar
Copy link
Contributor

I find it hard to furtherly test this PR.

I don't know if there is anything else to test?

I meant it's hard for me to test it with other creator plugins. maybe because I'm not yet familiar with the enhancement in this PR.

@iLLiCiTiT
Copy link
Member Author

Closing in favor of #935

@iLLiCiTiT iLLiCiTiT closed this Oct 3, 2024
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
size/S type: enhancement Improvement of existing functionality or minor addition
Projects
Archived in project
Development

Successfully merging this pull request may close these issues.

4 participants