diff --git a/client/ayon_core/pipeline/traits/content.py b/client/ayon_core/pipeline/traits/content.py index 3f08cc2214..47a7e208bd 100644 --- a/client/ayon_core/pipeline/traits/content.py +++ b/client/ayon_core/pipeline/traits/content.py @@ -55,7 +55,7 @@ class LocatableContent(TraitBase): location: str = Field(..., title="Location") is_templated: Optional[bool] = Field(None, title="Is Templated") -class FileLocation(LocatableContent): +class FileLocation(TraitBase): """FileLocation trait model. This model represents a file path. It is a specialization of the @@ -75,10 +75,11 @@ class FileLocation(LocatableContent): name: ClassVar[str] = "FileLocation" description: ClassVar[str] = "FileLocation Trait Model" id: ClassVar[str] = "ayon.content.FileLocation.v1" - file_path: Path = Field(..., title="File Path", alias="location") - file_size: int = Field(None, title="File Size") + file_path: Path = Field(..., title="File Path") + file_size: Optional[int] = Field(None, title="File Size") file_hash: Optional[str] = Field(None, title="File Hash") + class RootlessLocation(TraitBase): """RootlessLocation trait model. diff --git a/client/ayon_core/pipeline/traits/lifecycle.py b/client/ayon_core/pipeline/traits/lifecycle.py index fed620da9b..39fe04e3cb 100644 --- a/client/ayon_core/pipeline/traits/lifecycle.py +++ b/client/ayon_core/pipeline/traits/lifecycle.py @@ -1,7 +1,6 @@ """Lifecycle traits.""" from typing import ClassVar -from . import Representation from .trait import TraitBase @@ -21,7 +20,7 @@ class Transient(TraitBase): description: ClassVar[str] = "Transient Trait Model" id: ClassVar[str] = "ayon.lifecycle.Transient.v1" - def validate(self, representation: Representation) -> bool: + def validate(self, representation) -> bool: # noqa: ANN001 """Validate representation is not Persistent. Args: @@ -50,7 +49,7 @@ class Persistent(TraitBase): description: ClassVar[str] = "Persistent Trait Model" id: ClassVar[str] = "ayon.lifecycle.Persistent.v1" - def validate(self, representation: Representation) -> bool: + def validate(self, representation) -> bool: # noqa: ANN001 """Validate representation is not Transient. Args: diff --git a/client/ayon_core/pipeline/traits/trait.py b/client/ayon_core/pipeline/traits/trait.py index b97ec08cc6..6c37f40a45 100644 --- a/client/ayon_core/pipeline/traits/trait.py +++ b/client/ayon_core/pipeline/traits/trait.py @@ -6,7 +6,7 @@ import re import sys import uuid from abc import ABC, abstractmethod -from functools import cached_property, lru_cache +from functools import lru_cache from typing import ClassVar, Optional, Type, Union import pydantic.alias_generators @@ -65,20 +65,6 @@ class TraitBase(ABC, BaseModel): """Abstract attribute for description.""" ... - @property - @cached_property - def version(self) -> Union[int, None]: - # sourcery skip: use-named-expression - """Get trait version from ID. - - This assumes Trait ID ends with `.v{version}`. If not, it will - return None. - - """ - version_regex = r"v(\d+)$" - match = re.search(version_regex, self.id) - return int(match[1]) if match else None - def validate(self, representation: Representation) -> bool: """Validate the trait. @@ -95,6 +81,19 @@ class TraitBase(ABC, BaseModel): """ return True + @classmethod + def get_version(cls) -> Optional[int]: + # sourcery skip: use-named-expression + """Get trait version from ID. + + This assumes Trait ID ends with `.v{version}`. If not, it will + return None. + + """ + version_regex = r"v(\d+)$" + match = re.search(version_regex, str(cls.id)) + return int(match[1]) if match else None + class Representation: """Representation of products. diff --git a/tests/client/ayon_core/pipeline/traits/test_traits.py b/tests/client/ayon_core/pipeline/traits/test_traits.py index 8a48d6eef8..43d8301e00 100644 --- a/tests/client/ayon_core/pipeline/traits/test_traits.py +++ b/tests/client/ayon_core/pipeline/traits/test_traits.py @@ -72,7 +72,8 @@ def test_representation_errors(representation: Representation) -> None: def test_representation_traits(representation: Representation) -> None: """Test setting and getting traits.""" - assert representation.get_trait_by_id("ayon.2d.PixelBased").version == 1 + assert representation.get_trait_by_id( + "ayon.2d.PixelBased").get_version() == 1 assert len(representation) == len(REPRESENTATION_DATA) assert representation.get_trait_by_id(FileLocation.id) @@ -234,7 +235,7 @@ def test_bundles() -> None: def test_get_version_from_id() -> None: """Test getting version from trait ID.""" - assert Image().version == 1 + assert Image().get_version() == 1 class TestOverscan(Overscan): id = "ayon.2d.Overscan.v2" @@ -244,12 +245,12 @@ def test_get_version_from_id() -> None: right=0, top=0, bottom=0 - ).version == 2 + ).get_version() == 2 class TestMimeType(MimeType): id = "ayon.content.MimeType" - assert TestMimeType(mime_type="foo/bar").version is None + assert TestMimeType(mime_type="foo/bar").get_version() is None def test_from_dict() -> None: