diff --git a/client/ayon_core/pipeline/traits/time.py b/client/ayon_core/pipeline/traits/time.py index 751eef3fb5..7a614e1a94 100644 --- a/client/ayon_core/pipeline/traits/time.py +++ b/client/ayon_core/pipeline/traits/time.py @@ -2,12 +2,16 @@ from __future__ import annotations from enum import Enum, auto -from typing import ClassVar, Optional +from typing import TYPE_CHECKING, ClassVar, Optional, Union from pydantic import Field from .trait import TraitBase +if TYPE_CHECKING: + from decimal import Decimal + from fractions import Fraction + class GapPolicy(Enum): """Gap policy enumeration. @@ -45,7 +49,7 @@ class FrameRanged(TraitBase): frame_end (int): Frame end. frame_in (int): Frame in. frame_out (int): Frame out. - frames_per_second (int): Frames per second. + frames_per_second (float, Fraction, Decimal): Frames per second. step (int): Step. """ @@ -56,9 +60,9 @@ class FrameRanged(TraitBase): ..., title="Start Frame") frame_end: int = Field( ..., title="Frame Start") - frame_in: int = Field(..., title="In Frame") - frame_out: int = Field(..., title="Out Frame") - frames_per_second: int = Field( + frame_in: Optional[int] = Field(None, title="In Frame") + frame_out: Optional[int] = Field(None, title="Out Frame") + frames_per_second: Union[float, Fraction, Decimal] = Field( ..., title="Frames Per Second") step: Optional[int] = Field(1, title="Step") diff --git a/client/ayon_core/pipeline/traits/trait.py b/client/ayon_core/pipeline/traits/trait.py index 6c37f40a45..22e7fc6d64 100644 --- a/client/ayon_core/pipeline/traits/trait.py +++ b/client/ayon_core/pipeline/traits/trait.py @@ -94,6 +94,16 @@ class TraitBase(ABC, BaseModel): match = re.search(version_regex, str(cls.id)) return int(match[1]) if match else None + @classmethod + def get_versionless_id(cls) -> str: + """Get trait ID without version. + + Returns: + str: Trait ID without version. + + """ + return re.sub(r"\.v\d+$", "", str(cls.id)) + class Representation: """Representation of products. @@ -416,6 +426,9 @@ class Representation: bool: True if the representations are equal, False otherwise. """ + if self.representation_id != other.representation_id: + return False + if not isinstance(other, Representation): return False diff --git a/tests/client/ayon_core/pipeline/traits/test_traits.py b/tests/client/ayon_core/pipeline/traits/test_traits.py index 43d8301e00..8a6e210b78 100644 --- a/tests/client/ayon_core/pipeline/traits/test_traits.py +++ b/tests/client/ayon_core/pipeline/traits/test_traits.py @@ -252,6 +252,26 @@ def test_get_version_from_id() -> None: assert TestMimeType(mime_type="foo/bar").get_version() is None +def test_get_versionless_id() -> None: + """Test getting versionless trait ID.""" + assert Image().get_versionless_id() == "ayon.2d.Image" + + class TestOverscan(Overscan): + id = "ayon.2d.Overscan.v2" + + assert TestOverscan( + left=0, + right=0, + top=0, + bottom=0 + ).get_versionless_id() == "ayon.2d.Overscan" + + class TestMimeType(MimeType): + id = "ayon.content.MimeType" + + assert TestMimeType(mime_type="foo/bar").get_versionless_id() == \ + "ayon.content.MimeType" + def test_from_dict() -> None: """Test creating representation from dictionary."""