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

Representation defined by traits #979

Draft
wants to merge 76 commits into
base: develop
Choose a base branch
from

Conversation

antirotor
Copy link
Member

@antirotor antirotor commented Oct 31, 2024

Changelog Description

Introducing new way of defining representations. Developer friendly, flexible yet strictly typed, easy to extend using Traits as building blocks defining what representation IS.

Additional info

New representation is holder for traits. Each trait define some properties and together with other traits describes the representation. Traits can be anything- their purpose is to help publisher, loader (and basically any other systems) to clearly identify data needed for processing. Like file system path, or frame per second, or resolution. Those properties are grouped together to logical block - frame range specific, resolution specific, etc.

This PR is introducing several new features:

TraitBase - this is Pydantic based model for all Traits. It defines abstract properties like id, name, description that needs to be in all Traits.

Note

Every Trait can re-implement validate() method. The one in TraitBase always returns True. Representation is passed to that method so every Trait can validate against all other Trait present in representation.

Representation - this is "container" of sorts to hold all Traits. It holds representationname and id. And lot of "helper" methods to work with Traits:

  • methods to check if Trait exists in the Representation
  • methods to add and remove Traits
  • methods to get Traits
  • method to return whole Representation serialized as Python dict
  • method to reconstruct Representation from the dict

Most of them can run on bulk of Traits and you can access Traits by their class or by their Id. More on that below.

There is also mechanism for upgrading and versioning Traits.

Traits

There are some pre-defined Traits that should come with ayon-core to provide "common language". They are all based on TraitBase and are grouped to logical chunks or namespaces - content, lifecycle, meta, three_dimensional, time, two_dimensional. Their complete list can be found in the code and is obviously subject to change based on the need.

Practical examples

So how to work with traits and representations? To define traits (for example in Collector plugin or in Extractor plugin:

from ayon_core.pipeline.traits import (
	FileLocation,
	Image,,
	MimeType,
    PixelBased,
	Representation
)

# define traits
file_location = FileLocation(
    file_path=Path("/path/to/file.jpg"),
)

pixel_based = PixelBased(
	display_window_width=1920,
    display_window_height=1080,
    pixel_aspect_ratio=1.0 
)

# create representation itself

representation = Representation(
    name="Image test",
	traits=[file_location, Image(), pixel_based])

# add additional traits
mime_type = MimeType(mime_type="image/jpeg")
representation.add_trait(mime_type)

# remove trait
representation.remove_trait(MimeType)

if representation.contains_trait(PixelBased):
	print(f"width: {representation.get_trait(PixelBased).display_window_width)}")

You can work with Traits using classes, but you can also utilize their ids. That is useful when working with representation that was serialized into "plain' dictionary:

# some pseudo-function to get representation as dict
representation = Representation.from_dict(get_representation_dict(...))

# get trait by its id
# note: the use of version in the ID. You can test if trait is present in representation, or if trait of specific version is present.
if representation.contains_trait_by_id("ayon.content.FileLocation"):
	print(f"path: {representation.get_trait_by_id("ayon.content.FileLocation.v1")

# serialize back to dict
representation.traits_as_dict()

There is also feature of version upgrade on Traits. Whenever you want to de-serialize data that are using older version of trait, upgrade() method on newer trait definition is called to reconstruct new version (downgrading isn't possible). So, you can have serialized trait like so (type trait without properties):

{
		ayon.2d.Image.v1: {}
}

But your current runtime has Image trait ayon.2d.Image.v2 that is also adding property foo.

Whenever you run representation.get_trait_by_id("ayon.2d.Image") without version specifier, it can try to find out the latest Trait definition available and if it differs - v1 != v2 it tries to call upgrade() method on the latest trait.

Warning

🔧 DESCRIPTION IN PROGRESS

added few helper methods to query/set/remove bunch of traits at once
…into feature/911-new-traits-based-integrator
note that this needs `pytest-ayon` dependency to run that will be added in subsequent commits
also added versionless trait id processing and trait validation
also added versionless trait id processing and trait validation
…ype-using-dataclasses' into feature/909-define-basic-trait-type-using-dataclasses
@antirotor antirotor added type: feature Adding something new and exciting to the product tests PR contains new unit or integration test or improves the existing ones labels Oct 31, 2024
@antirotor antirotor self-assigned this Oct 31, 2024
@antirotor antirotor linked an issue Oct 31, 2024 that may be closed by this pull request
@ynbot ynbot added the size/XXL label Oct 31, 2024
FrameRanged: FrameRanged trait.

"""
col = assemble([path.as_posix() for path in paths])[0][0]
Copy link
Collaborator

Choose a reason for hiding this comment

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

This will error on:

  • File paths that do not have a sequence identifier
  • File paths that only contain a single frame

Because both won'tbe detected as collections but as remainder

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
size/XXL tests PR contains new unit or integration test or improves the existing ones type: feature Adding something new and exciting to the product
Projects
Status: Review In Progress
Development

Successfully merging this pull request may close these issues.

Define basic trait type using dataclasses
4 participants