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
Draft
Show file tree
Hide file tree
Changes from 22 commits
Commits
Show all changes
76 commits
Select commit Hold shift + click to select a range
5118c3c
Merge remote-tracking branch 'origin/develop' into feature/909-define…
antirotor Oct 8, 2024
b9774e4
:wrench: WIP on feature/909-define-basic-trait-type-using-dataclasses
antirotor Oct 8, 2024
88a4aa1
:recycle: tweak ruff linting
antirotor Oct 9, 2024
092325e
:art: implement `TraitsData`
antirotor Oct 9, 2024
3981a2e
:alembic: add tests
antirotor Oct 10, 2024
6d07307
:recycle: refactor `TraitsData` to `Representation`
antirotor Oct 10, 2024
43edcb8
:alembic: add dependencies necessary to run tests
antirotor Oct 10, 2024
e0a6e17
:recycle: add traits and refactor api
antirotor Oct 14, 2024
9b3e1ce
:alembic: fix tests
antirotor Oct 14, 2024
c0cf227
Merge remote-tracking branch 'origin/develop' into feature/909-define…
antirotor Oct 16, 2024
de4d5b9
Auto stash before merge of "feature/909-define-basic-trait-type-using…
antirotor Oct 16, 2024
03dcc37
:art: add some more traits
antirotor Oct 16, 2024
2b572ae
:art: introduce name and id for representation
antirotor Oct 16, 2024
4e0f9b4
:wrench: WIP on the integrator
antirotor Oct 17, 2024
a299f8e
:bug: fix test fixture
antirotor Oct 17, 2024
4bd5706
:recycle: make some properties optional
antirotor Oct 17, 2024
913a188
Merge branch 'feature/909-define-basic-trait-type-using-dataclasses' …
antirotor Oct 17, 2024
4b3469c
:wrench: adding project based test
antirotor Oct 21, 2024
664d839
:art: added id and name to representation
antirotor Oct 25, 2024
edefade
:art: added id and name to representation
antirotor Oct 25, 2024
37ebb8a
Merge remote-tracking branch 'origin/develop' into feature/909-define…
antirotor Oct 25, 2024
c559d5b
Merge remote-tracking branch 'origin/feature/909-define-basic-trait-t…
antirotor Oct 25, 2024
282edd9
Update client/ayon_core/pipeline/traits/time.py
antirotor Oct 31, 2024
8698c81
:burn: remove unnecessary init files
antirotor Nov 4, 2024
ba3497b
Merge remote-tracking branch 'origin/feature/909-define-basic-trait-t…
antirotor Nov 4, 2024
ba49b65
:fire: remove integrator from this branch
antirotor Nov 4, 2024
b0bd488
:recycle: add traits and docstrings
antirotor Nov 4, 2024
2b05c52
Merge branch 'develop' into feature/909-define-basic-trait-type-using…
antirotor Nov 4, 2024
fbeef7f
:dog: run ruff action only on changed files
antirotor Nov 5, 2024
eb04f24
Merge remote-tracking branch 'origin/feature/909-define-basic-trait-t…
antirotor Nov 5, 2024
9e7dac2
:recycle: switch ruff to official GH action
antirotor Nov 5, 2024
deae44d
:recycle: fix tests and trait version
antirotor Nov 6, 2024
4d31c5e
:fire: remove FrameRanged field aliases
antirotor Nov 6, 2024
b9e430e
:recycle: make fields optional, fps data type
antirotor Nov 8, 2024
db5d997
:art: add `get_versionless_id()` helper (and test)
antirotor Nov 8, 2024
e4377e8
:recycle: raise exception if trait not found instead of returning None
antirotor Nov 8, 2024
d228527
:art: add file locations
antirotor Nov 11, 2024
f589cb9
:recycle: change validations
antirotor Nov 12, 2024
b64e034
:recycle: refactor to remove circular imports
antirotor Nov 12, 2024
794160f
:dog: fix ruff issues
antirotor Nov 13, 2024
fc30b85
:dog: remove unused import
antirotor Nov 13, 2024
13e5642
:art: add get padding from files
antirotor Nov 22, 2024
dc26079
:bug: handle `ABCMeta.__issubclass__()` bug?
antirotor Nov 26, 2024
97fe8ac
:art: handle frame specs
antirotor Nov 26, 2024
32d82e4
:art: add persistent property to trait
antirotor Nov 29, 2024
60f10fe
:art: add dict-like behavior to Representation
antirotor Nov 29, 2024
265b181
:recycle: simplify equality check and validation
antirotor Nov 29, 2024
5e0509c
:art: enhance range validations
antirotor Nov 29, 2024
799b0bc
:alembic: split test to more files
antirotor Nov 29, 2024
90d8df8
:dog: add missing docstring
antirotor Nov 30, 2024
4948cdd
:art: FileLocations only with Sequence or Bundle
antirotor Nov 30, 2024
c9d4716
:art: add `UDIM` to `FileLocations` relationships
antirotor Nov 30, 2024
5c8d111
:dog: fix indent
antirotor Nov 30, 2024
cf3242b
:fire: revert the assumption that `FileLocations relates to `Bundles`
antirotor Nov 30, 2024
f416976
:recycle: expose trait validation error
antirotor Dec 1, 2024
595a354
:art: add helpers for getting files
antirotor Dec 1, 2024
cc543fb
:bug: return Path instead of FileLocation
antirotor Dec 1, 2024
cf195c4
:recycle: refactor to return `FileLocation` again
antirotor Dec 1, 2024
5748c15
:art: udims as a list
antirotor Dec 1, 2024
0d98ff4
:bug: compile regex
antirotor Dec 1, 2024
891a065
:art: add helper function
antirotor Dec 1, 2024
828c522
:bug: fix typo
antirotor Dec 3, 2024
e83541a
:art: add Variant trait
antirotor Dec 3, 2024
da95746
:memo: add readme for traits
antirotor Dec 4, 2024
718cad7
:bug: fix PGPSigned trait name
antirotor Dec 4, 2024
5ab0f82
:art: add traits addon interface
antirotor Dec 9, 2024
b51273a
:art: add original location traits and fix some typos
antirotor Dec 10, 2024
83dfd76
:bug: fix validation
antirotor Dec 10, 2024
6d9c73d
:bug: small fixes
antirotor Dec 11, 2024
b0238cb
:bug: fix regex named group for frame list
antirotor Dec 12, 2024
a08ed70
:recycle: fix mypy errors
antirotor Dec 20, 2024
5d31e66
merge develop
antirotor Dec 22, 2024
a4dbb31
:bug: fix mypy errors
antirotor Dec 22, 2024
6ffe6af
Merge remote-tracking branch 'origin/develop' into feature/909-define…
antirotor Jan 22, 2025
e44901e
:sparkles: add SourceApplication trait
antirotor Jan 22, 2025
8662e42
Merge remote-tracking branch 'origin/feature/909-define-basic-trait-t…
antirotor Jan 22, 2025
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
60 changes: 60 additions & 0 deletions client/ayon_core/pipeline/traits/__init__.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,60 @@
"""Trait classes for the pipeline."""
from .content import (
Bundle,
Compressed,
FileLocation,
MimeType,
RootlessLocation,
)
from .lifecycle import Persistent, Transient
from .meta import Tagged, TemplatePath
from .three_dimensional import Spatial
from .time import Clip, GapPolicy, Sequence, SMPTETimecode
from .trait import Representation, TraitBase
from .two_dimensional import (
UDIM,
Deep,
Image,
Overscan,
PixelBased,
Planar,
)

__all__ = [
# base
"Representation",
"TraitBase",

# content
"Bundle",
"Compressed",
"FileLocation",
"MimeType",
"RootlessLocation",

# life cycle
"Persistent",
"Transient",

# meta
"Tagged",
"TemplatePath",

# two-dimensional
"Compressed",
"Deep",
"Image",
"Overscan",
"PixelBased",
"Planar",
"UDIM",

# three-dimensional
"Spatial",

# time
"Clip",
"GapPolicy",
"Sequence",
"SMPTETimecode",
]
135 changes: 135 additions & 0 deletions client/ayon_core/pipeline/traits/content.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,135 @@
"""Content traits for the pipeline."""
from __future__ import annotations

# TCH003 is there because Path in TYPECHECKING will fail in tests
from pathlib import Path # noqa: TCH003
from typing import ClassVar, Optional

from pydantic import Field

from .trait import Representation, TraitBase


class MimeType(TraitBase):
"""MimeType trait model.

This model represents a mime type trait.

Attributes:
name (str): Trait name.
description (str): Trait description.
id (str): id should be namespaced trait name with version
mime_type (str): Mime type.

"""

name: ClassVar[str] = "MimeType"
description: ClassVar[str] = "MimeType Trait Model"
id: ClassVar[str] = "ayon.content.MimeType.v1"
mime_type: str = Field(..., title="Mime Type")

class FileLocation(TraitBase):
"""FileLocation trait model.

This model represents a file location trait.

Attributes:
name (str): Trait name.
description (str): Trait description.
id (str): id should be namespaced trait name with version
file_path (str): File path.
file_size (int): File size in bytes.
file_hash (str): File hash.

"""

name: ClassVar[str] = "FileLocation"
description: ClassVar[str] = "FileLocation Trait Model"
id: ClassVar[str] = "ayon.content.FileLocation.v1"
file_path: Path = Field(..., title="File Path")
file_size: int = Field(..., title="File Size")
file_hash: Optional[str] = Field(None, title="File Hash")

class RootlessLocation(TraitBase):
"""RootlessLocation trait model.

This model represents a rootless location trait.

Attributes:
name (str): Trait name.
description (str): Trait description.
id (str): id should be namespaced trait name with version
rootless_path (str): Rootless path.

"""

name: ClassVar[str] = "RootlessLocation"
description: ClassVar[str] = "RootlessLocation Trait Model"
id: ClassVar[str] = "ayon.content.RootlessLocation.v1"
rootless_path: str = Field(..., title="File Path")


class Compressed(TraitBase):
"""Compressed trait model.

This model represents a compressed trait.

Attributes:
name (str): Trait name.
description (str): Trait description.
id (str): id should be namespaced trait name with version
compression_type (str): Compression type.

"""

name: ClassVar[str] = "Compressed"
description: ClassVar[str] = "Compressed Trait"
id: ClassVar[str] = "ayon.content.Compressed.v1"
compression_type: str = Field(..., title="Compression Type")


class Bundle(TraitBase):
"""Bundle trait model.

This model list of independent Representation traits
that are bundled together. This is useful for representing
a collection of representations that are part of a single
entity.

Attributes:
name (str): Trait name.
description (str): Trait description.
id (str): id should be namespaced trait name with version
items (list[list[TraitBase]]): List of representations.

"""

name: ClassVar[str] = "Bundle"
description: ClassVar[str] = "Bundle Trait"
id: ClassVar[str] = "ayon.content.Bundle.v1"
items: list[list[TraitBase]] = Field(
..., title="Bundles of traits")

def to_representation(self) -> Representation:
"""Convert to a representation."""
return Representation(traits=self.items)


class Fragment(TraitBase):
"""Fragment trait model.

This model represents a fragment trait. A fragment is a part of
a larger entity that is represented by a representation.

Attributes:
name (str): Trait name.
description (str): Trait description.
id (str): id should be namespaced trait name with version
parent (str): Parent representation id.

"""

name: ClassVar[str] = "Fragment"
description: ClassVar[str] = "Fragment Trait"
id: ClassVar[str] = "ayon.content.Fragment.v1"
parent: str = Field(..., title="Parent Representation Id")
37 changes: 37 additions & 0 deletions client/ayon_core/pipeline/traits/lifecycle.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
"""Lifecycle traits."""
from typing import ClassVar

from .trait import TraitBase


class Transient(TraitBase):
"""Transient trait model.

This model represents a transient trait.

Attributes:
name (str): Trait name.
description (str): Trait description.
id (str): id should be namespaced trait name with version
tags (List[str]): Tags.
"""

name: ClassVar[str] = "Transient"
description: ClassVar[str] = "Transient Trait Model"
id: ClassVar[str] = "ayon.lifecycle.Transient.v1"


class Persistent(TraitBase):
"""Persistent trait model.

This model represents a persistent trait.

Attributes:
name (str): Trait name.
description (str): Trait description.
id (str): id should be namespaced trait name with version
"""
antirotor marked this conversation as resolved.
Show resolved Hide resolved

name: ClassVar[str] = "Persistent"
description: ClassVar[str] = "Persistent Trait Model"
id: ClassVar[str] = "ayon.lifecycle.Persistent.v1"
44 changes: 44 additions & 0 deletions client/ayon_core/pipeline/traits/meta.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
"""Metadata traits."""
from typing import ClassVar, List

from pydantic import Field

from .trait import TraitBase


class Tagged(TraitBase):
"""Tagged trait model.

This model represents a tagged trait.

Attributes:
name (str): Trait name.
description (str): Trait description.
id (str): id should be namespaced trait name with version
tags (List[str]): Tags.
"""

name: ClassVar[str] = "Tagged"
description: ClassVar[str] = "Tagged Trait Model"
id: ClassVar[str] = "ayon.meta.Tagged.v1"
tags: List[str] = Field(..., title="Tags")


class TemplatePath(TraitBase):
"""TemplatePath trait model.

This model represents a template path with formatting data.

Attributes:
name (str): Trait name.
description (str): Trait description.
id (str): id should be namespaced trait name with version
template_path (str): Template path.
data (dict[str]): Formatting data.
"""

name: ClassVar[str] = "TemplatePath"
description: ClassVar[str] = "Template Path Trait Model"
id: ClassVar[str] = "ayon.meta.TemplatePath.v1"
template: str = Field(..., title="Template Path")
data: dict = Field(..., title="Formatting Data")
23 changes: 23 additions & 0 deletions client/ayon_core/pipeline/traits/three_dimensional.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
"""Two-dimensional image traits."""
from typing import ClassVar

from pydantic import Field

from .trait import TraitBase


class Spatial(TraitBase):
"""Spatial trait model.

Attributes:
up_axis (str): Up axis.
handedness (str): Handedness.
meters_per_unit (float): Meters per unit.

"""
id: ClassVar[str] = "ayon.3d.Spatial.v1"
name: ClassVar[str] = "Spatial"
description: ClassVar[str] = "Spatial trait model."
up_axis: str = Field(..., title="Up axis")
handedness: str = Field(..., title="Handedness")
meters_per_unit: float = Field(..., title="Meters per unit")
86 changes: 86 additions & 0 deletions client/ayon_core/pipeline/traits/time.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,86 @@
"""Temporal (time related) traits."""
from __future__ import annotations

from enum import Enum, auto
from typing import ClassVar, Optional

from pydantic import Field

from .trait import TraitBase


class GapPolicy(Enum):
"""Gap policy enumeration.

Attributes:
forbidden (int): Gaps are forbidden.
missing (int): Gaps are interpreted as missing frames.
hold (int): Gaps are interpreted as hold frames (last existing frames).
black (int): Gaps are interpreted as black frames.
"""
forbidden = auto()
missing = auto()
hold = auto()
black = auto()

antirotor marked this conversation as resolved.
Show resolved Hide resolved
class Clip(TraitBase):
"""Clip trait model.

Model representing a clip trait.

Attributes:
name (str): Trait name.
description (str): Trait description.
id (str): id should be namespaced trait name with version
frame_start (int): Frame start.
frame_end (int): Frame end.
frame_start_handle (int): Frame start handle.
frame_end_handle (int): Frame end handle.

"""
name: ClassVar[str] = "Clip"
description: ClassVar[str] = "Clip Trait"
id: ClassVar[str] = "ayon.time.Clip.v1"
frame_start: int = Field(..., title="Frame Start")
frame_end: int = Field(..., title="Frame End")
frame_start_handle: Optional[int] = Field(0, title="Frame Start Handle")
frame_end_handle: Optional[int] = Field(0, title="Frame End Handle")

class Sequence(Clip):
"""Sequence trait model.

This model represents a sequence trait. Based on the Clip trait,
adding handling for steps, gaps policy and frame padding.

Attributes:
name (str): Trait name.
description (str): Trait description.
id (str): id should be namespaced trait name with version
step (int): Frame step.
gaps_policy (GapPolicy): Gaps policy - how to handle gaps in
sequence.
frame_padding (int): Frame padding.
frame_regex (str): Frame regex - regular expression to match
frame numbers.
frame_list (str): Frame list specification of frames. This takes
string like "1-10,20-30,40-50" etc.

"""
name: ClassVar[str] = "Sequence"
description: ClassVar[str] = "Sequence Trait Model"
id: ClassVar[str] = "ayon.time.Sequence.v1"
step: Optional[int] = Field(1, title="Step")
gaps_policy: GapPolicy = Field(
GapPolicy.forbidden, title="Gaps Policy")
frame_padding: int = Field(..., title="Frame Padding")
frame_regex: str = Field(..., title="Frame Regex")
frame_list: Optional[str] = Field(None, title="Frame List")


# Do we need one for drop and non-drop frame?
class SMPTETimecode(TraitBase):
"""Timecode trait model."""
name: ClassVar[str] = "Timecode"
description: ClassVar[str] = "SMPTE Timecode Trait"
id: ClassVar[str] = "ayon.time.SMPTETimecode.v1"
timecode: str = Field(..., title="SMPTE Timecode HH:MM:SS:FF")
Loading
Loading