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

Enhancement: Callbacks and groups with Publisher attributes #133

Open
2 tasks done
antirotor opened this issue Feb 28, 2024 · 5 comments · May be fixed by #935
Open
2 tasks done

Enhancement: Callbacks and groups with Publisher attributes #133

antirotor opened this issue Feb 28, 2024 · 5 comments · May be fixed by #935
Assignees
Labels
backlog added into backlog type: enhancement Improvement of existing functionality or minor addition

Comments

@antirotor
Copy link
Member

antirotor commented Feb 28, 2024

Is there an existing issue for this?

  • I have searched the existing issues.

Please describe the feature you have in mind and explain what the current shortcomings are?

In publisher, both creator and publish plugins can define attributes that can be set to control specifics of the publishing process. Right now, all those attributes are basically standalone without having any connection to others.

We need to define relationship between individual attributes, so changing value of one can affect the whole group (or other groups, or other controls).

How would you imagine the implementation of the feature?

Since attributes are defined in individual plugins there are few things that needs to be implemented to overcome this:

  • attribute identifier: to be able to reference one attribute from somewhere else
  • callbacks: ability for plugin to define custom callback to be called when some attribute state is changed (connected to event system). Those callbacks should be able to report back to UI - for example to report invalid state.
  • labeling: show what controls belongs together, either plugin-wise, or logical group related

Are there any labels you wish to add?

  • I have added the relevant labels to the enhancement request.

Describe alternatives you've considered:

No response

Additional context:

Rreferences

ynput/ayon-workgroups#4

[cuID:AY-2420]

@antirotor antirotor added the type: enhancement Improvement of existing functionality or minor addition label Feb 28, 2024
@jakubjezek001 jakubjezek001 added the backlog added into backlog label Feb 28, 2024
@antirotor
Copy link
Member Author

So, based on our discussion with @BigRoy and @iLLiCiTiT , this is example mockup code that might be solution:

import subprocess
from ayon_core.lib import EnumDef, BoolDef, TextDef, ButtonDef
from  ayon_core.pipeline.create import CreateContext
import pyblish.api


class ExamplePlugin(pyblish.api.InstancePlugin):
    """Example plugin for demonstration purposes.
    
    Attributes:
        id (str): Unique identifier for this plugin.
            It is using reverse domain name notation.
    
    """

    @classmethod
    def get_attribute_defs(cls):
        """Get the attribute definitions for this plugin.
        
        Every attribute can be uniquely identified by its id. To get it's value,
        you need also instance itself.
        """
        return [
            BoolDef(
                "groupEnabled",  # io.ayon.publish.examplePlugin.attributes.groupEnabled
                label="Group Enabled",
                default=True,
            ),
            EnumDef("groupEnum",  # io.ayon.publish.examplePlugin.attributes.groupEnum
                    label="Enum Example",
                    items=["Foo", "Bar", "Baz"],
                    default="Foo"),
            TextDef("groupText",  # io.ayon.publish.examplePlugin.attributes.groupText
                    label="Text Example",
                    default="Hello World"),
            ButtonDef("groupButton",  # io.ayon.publish.examplePlugin.attributes.groupButton
                    label="Button Example")
        ]
    
    @classmethod
    def register_attribute_callback(cls, create_context):
        """Register attribute callbacks for this plugin.

        These callbacks are called when the value of the attribute changes.
        """
        # register callback should take either list of attribute ids or a single attribute id
        create_context.register_callback(
            ["io.ayon.publish.examplePlugin.attributes.groupEnabled"], cls.on_attribute_changed)
        create_context.register_callback("io.ayon.publish.examplePlugin.attributes.groupButton", cls.on_button_pressed)


    @classmethod
    def on_attribute_changed(cls, create_context: CreateContext, changes: list):
        """Callback for when the attribute changes.
        
        Args:
            create_context (CreateContext): The create context.
            changes (list): List of changes that happened.
                This should be a list of tuples where the first element is instance id,
                the second one is original value, the third one is new value.

        """
        enabled_attr = create_context.get_attribute_by_id("io.ayon.publish.examplePlugin.attributes.groupEnabled")
        group_attrs = create_context.get_attribute_by_group("io.ayon.publish.examplePlugin.attributes")
        if enabled_attr.value:
            print("Group is enabled")
            group_attrs["groupEnum"] = "Bar"
            group_attrs["groupText"] = "Hello Bar Enabled"
        else:
            print("Group is disabled")
            group_attrs["groupEnum"].set_disabled(True)
            group_attrs["groupText"].set_disabled(True)


    @classmethod
    def on_button_pressed(cls, create_context: CreateContext, changes: list):
        print("Button Pressed")
        output = subprocess.check_output(["ls", "-l"])
        instance_ids = []
        for instance in create_context.get_instances():
            if instance.family == "exampleFamily":
                instance_ids.append(instance.id)
        try:
            create_context.set_instance_attribute(instance_ids, "groupText", output)
        except AttributeError:
            # instance does not have the attribute
            pass

there are some mixed approaches together, but main idea is event based system where every plugin could express it's interest in changes of certain attribute values. Create context would then execute callback whenever attribute value changes and pass itself and information about changes to the callback. Callback will then decide what to do.

Pros

  • Flexible way where every plugin can decide what to do with changes
  • Tt can solve some issues where certain attribute definition can't be shown because we don't know all instances beforehand

Cons

  • There might be conflicting callbacks defined plugins (should we allow of forbid?)
  • It might be really slow

Notes
Maybe changes can be passed as object with some helper methods to access instance, check types, etc.

This is just a quick summary, lets elaborate more on this (and other ways) here

@bradenjennings
Copy link
Contributor

I quickly prototyped something in the following PR. This is without any guidance. So its a very rudimentary solution.

This was done before you posted your code example above

Comparing develop...enhancement/AY-2614_publisher_display_overridden_vs_default_values · ynput/ayon-core (github.com)

@bradenjennings
Copy link
Contributor

bradenjennings commented Mar 5, 2024

I had a look at your code @antirotor.

and I'm not sure how I would implement something like this especially in regards to signals. I'm not assigned to the ticket yet.

perhaps this one is better handled by someone more experienced.

@antirotor
Copy link
Member Author

I quickly prototyped something in the following PR. This is without any guidance. So its a very rudimentary solution.

This was done before you posted your code example above

Comparing develop...enhancement/AY-2614_publisher_display_overridden_vs_default_values · ynput/ayon-core (github.com)

This is not directly connected with your PR - this is mostly about ability to define custom logic in individual plugins that has access to all defined attributes within the system. Default values are definitely touching this, but are not the main topic.

@bradenjennings
Copy link
Contributor

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
backlog added into backlog type: enhancement Improvement of existing functionality or minor addition
Projects
None yet
Development

Successfully merging a pull request may close this issue.

4 participants