From 852a913f468b5baf40776f91b30518b90e5baa46 Mon Sep 17 00:00:00 2001 From: Jakub Trllo <43494761+iLLiCiTiT@users.noreply.github.com> Date: Mon, 21 Oct 2024 18:40:23 +0200 Subject: [PATCH 01/33] use explicit arguments in entity init --- ayon_api/entity_hub.py | 69 ++++++++++++++++++++++++++++++++++++------ 1 file changed, 60 insertions(+), 9 deletions(-) diff --git a/ayon_api/entity_hub.py b/ayon_api/entity_hub.py index 8989c0b05..df06c4b32 100644 --- a/ayon_api/entity_hub.py +++ b/ayon_api/entity_hub.py @@ -2417,10 +2417,27 @@ def __init__( folder_types, task_types, statuses, - *args, - **kwargs, + entity_id=None, + parent_id=UNKNOWN_VALUE, + name=UNKNOWN_VALUE, + attribs=UNKNOWN_VALUE, + data=UNKNOWN_VALUE, + thumbnail_id=UNKNOWN_VALUE, + active=UNKNOWN_VALUE, + entity_hub=None, + created=None, ): - super().__init__(*args, **kwargs) + super().__init__( + entity_id, + parent_id, + name, + attribs, + data, + thumbnail_id, + active, + entity_hub, + created + ) self._project_code = project_code self._library_project = library @@ -2580,14 +2597,31 @@ class FolderEntity(BaseEntity): def __init__( self, folder_type, - *args, + entity_id=None, + parent_id=UNKNOWN_VALUE, + name=UNKNOWN_VALUE, + attribs=UNKNOWN_VALUE, + data=UNKNOWN_VALUE, + thumbnail_id=UNKNOWN_VALUE, + active=UNKNOWN_VALUE, + entity_hub=None, + created=None, label=None, path=None, tags=None, status=UNKNOWN_VALUE, - **kwargs ): - super(FolderEntity, self).__init__(*args, **kwargs) + super().__init__( + entity_id, + parent_id, + name, + attribs, + data, + thumbnail_id, + active, + entity_hub, + created, + ) # Autofill project as parent of folder if is not yet set # - this can be guessed only if folder was just created if self.created and self._parent_id is UNKNOWN_VALUE: @@ -2861,14 +2895,31 @@ class TaskEntity(BaseEntity): def __init__( self, task_type, - *args, + entity_id=None, + parent_id=UNKNOWN_VALUE, + name=UNKNOWN_VALUE, + attribs=UNKNOWN_VALUE, + data=UNKNOWN_VALUE, + thumbnail_id=UNKNOWN_VALUE, + active=UNKNOWN_VALUE, + entity_hub=None, + created=None, label=None, tags=None, assignees=None, status=UNKNOWN_VALUE, - **kwargs ): - super(TaskEntity, self).__init__(*args, **kwargs) + super().__init__( + entity_id, + parent_id, + name, + attribs, + data, + thumbnail_id, + active, + entity_hub, + created, + ) if tags is None: tags = [] From e29f38faaf55b0b9b2b217ed16712ed09b866ccb Mon Sep 17 00:00:00 2001 From: Jakub Trllo <43494761+iLLiCiTiT@users.noreply.github.com> Date: Fri, 25 Oct 2024 17:30:38 +0200 Subject: [PATCH 02/33] delegated common attributes to base entity --- ayon_api/entity_hub.py | 524 +++++++++++++++++++++-------------------- 1 file changed, 269 insertions(+), 255 deletions(-) diff --git a/ayon_api/entity_hub.py b/ayon_api/entity_hub.py index df06c4b32..9ecea77a9 100644 --- a/ayon_api/entity_hub.py +++ b/ayon_api/entity_hub.py @@ -928,7 +928,7 @@ class Attributes(object): Args: attrib_keys (Iterable[str]): Keys that are available in attribs of the entity. - values (Union[None, Dict[str, Any]]): Values of attributes. + values (Optional[Dict[str, Any]]): Values of attributes. """ @@ -1114,32 +1114,40 @@ class BaseEntity(ABC): entity are set as "current data" on server. Args: - entity_id (Union[str, None]): Id of the entity. New id is created if + entity_id (Optional[str]): Entity id. New id is created if not passed. - parent_id (Union[str, None]): Id of parent entity. - name (str): Name of entity. - attribs (Dict[str, Any]): Attribute values. - data (Dict[str, Any]): Entity data (custom data). - thumbnail_id (Union[str, None]): Id of entity's thumbnail. - active (bool): Is entity active. + parent_id (Optional[str]): Parent entity id. + attribs (Optional[Dict[str, Any]]): Attribute values. + data (Optional[Dict[str, Any]]): Entity data (custom data). + thumbnail_id (Optional[str]): Thumbnail id. + active (Optional[bool]): Is entity active. entity_hub (EntityHub): Object of entity hub which created object of the entity. created (Optional[bool]): Entity is new. When 'None' is passed the value is defined based on value of 'entity_id'. """ + _supports_name = False + _supports_label = False + _supports_status = False + _supports_tags = False + _supports_thumbnail = False def __init__( self, - entity_id=None, - parent_id=UNKNOWN_VALUE, - name=UNKNOWN_VALUE, - attribs=UNKNOWN_VALUE, - data=UNKNOWN_VALUE, - thumbnail_id=UNKNOWN_VALUE, - active=UNKNOWN_VALUE, - entity_hub=None, - created=None + entity_id: Optional[str] = None, + parent_id: Optional[Union[str, _CustomNone]] = UNKNOWN_VALUE, + attribs: Optional[Dict[str, Any]] = UNKNOWN_VALUE, + data: Optional[Dict[str, Any]] = UNKNOWN_VALUE, + active: Optional[bool] = UNKNOWN_VALUE, + created: Optional[bool] = None, + entity_hub: EntityHub = None, + # Optional arguments + name=None, + label=None, + status: Optional[str] = UNKNOWN_VALUE, + tags: Optional[List[str]] = None, + thumbnail_id: Optional[str] = UNKNOWN_VALUE, ): if entity_hub is None: raise ValueError("Missing required kwarg 'entity_hub'") @@ -1164,15 +1172,18 @@ def __init__( if not created and parent_id is UNKNOWN_VALUE: raise ValueError("Existing entity is missing parent id.") + if tags is None: + tags = [] + else: + tags = list(tags) + # These are public without any validation at this moment # may change in future (e.g. name will have regex validation) self._entity_id = entity_id self._parent_id = parent_id - self._name = name self.active = active self._created = created - self._thumbnail_id = thumbnail_id self._attribs = Attributes( self._get_attributes_for_type(self.entity_type), attribs @@ -1181,9 +1192,20 @@ def __init__( self._children_ids = children_ids self._orig_parent_id = parent_id + self._orig_active = active + + # Optional only if supported by entity type + self._name = name + self._label = label + self._status = status + self._tags = copy.deepcopy(tags) + self._thumbnail_id = thumbnail_id + self._orig_name = name + self._orig_label = label + self._orig_status = status + self._orig_tags = copy.deepcopy(tags) self._orig_thumbnail_id = thumbnail_id - self._orig_active = active self._immutable_for_hierarchy_cache = None @@ -1380,9 +1402,6 @@ def _get_default_changes(self): """ changes = {} - if self._orig_name != self._name: - changes["name"] = self._name - if ( self._entity_hub.allow_data_changes and self._data is not UNKNOWN_VALUE @@ -1400,6 +1419,20 @@ def _get_default_changes(self): attrib_changes = self.attribs.changes if attrib_changes: changes["attrib"] = attrib_changes + + if self._supports_name and self._orig_name != self._name: + changes["name"] = self._name + + if self._supports_label: + label = self._get_label_value() + if label != self._orig_label: + changes["label"] = label + + if self._supports_status and self._orig_status != self._status: + changes["status"] = self._status + + if self._supports_tags and self._orig_tags != self._tags: + changes["tags"] = self._tags return changes def _get_attributes_for_type(self, entity_type): @@ -1417,6 +1450,15 @@ def lock(self): self._immutable_for_hierarchy_cache = None self._created = False + if self._supports_label: + self._orig_label = self._get_label_value() + if self._supports_status: + self._orig_status = self._status + if self._supports_tags: + self._orig_tags = copy.deepcopy(self._tags) + if self._supports_thumbnail: + self._orig_thumbnail_id = self._thumbnail_id + def _get_entity_by_id(self, entity_id): return self._entity_hub.get_entity_by_id(entity_id) @@ -1432,7 +1474,7 @@ def get_parent_id(self): """Parent entity id. Returns: - Union[str, None]: Id of parent entity or none if is not set. + Optional[str]: Parent entity id or none if is not set. """ return self._parent_id @@ -1441,7 +1483,7 @@ def set_parent_id(self, parent_id): """Change parent by id. Args: - parent_id (Union[str, None]): Id of new parent for entity. + parent_id (Optional[str]): Id of new parent for entity. Raises: ValueError: If parent was not found by id. @@ -1461,7 +1503,7 @@ def get_parent(self, allow_query=True): """Parent entity. Returns: - Union[BaseEntity, None]: Parent object. + Optional[BaseEntity]: Parent object. """ parent = self._entity_hub.get_entity_by_id(self._parent_id) @@ -1575,7 +1617,7 @@ def get_thumbnail_id(self): """Thumbnail id of entity. Returns: - Union[str, None]: Id of parent entity or none if is not set. + Optional[str]: Thumbnail id or none if is not set. """ return self._thumbnail_id @@ -1584,7 +1626,7 @@ def set_thumbnail_id(self, thumbnail_id): """Change thumbnail id. Args: - thumbnail_id (Union[str, None]): Id of thumbnail for entity. + thumbnail_id (Union[str, None]): Thumbnail id for entity. """ self._thumbnail_id = thumbnail_id @@ -1610,6 +1652,139 @@ def fill_children_ids(self, children_ids): """ self._children_ids = set(children_ids) + def get_name(self): + if not self._supports_name: + raise NotImplementedError( + f"Name is not supported for '{self.entity_type}'." + ) + return self._name + + name = property(get_name) + + def get_label(self) -> Optional[str]: + if not self._supports_label: + raise NotImplementedError( + f"Label is not supported for '{self.entity_type}'." + ) + return self._label + + def set_label(self, label: Optional[str]): + if not self._supports_label: + raise NotImplementedError( + f"Label is not supported for '{self.entity_type}'." + ) + self._label = label + + def _get_label_value(self): + """Get label value that will be used for operations. + + Returns: + Optional[str]: Label value. + + """ + label = self._label + if not label or self._name == label: + return None + return label + + label = property(get_label, set_label) + + def get_thumbnail_id(self): + """Thumbnail id of entity. + + Returns: + Optional[str]: Thumbnail id or none if is not set. + + """ + if not self._supports_thumbnail: + raise NotImplementedError( + f"Thumbnail is not supported for '{self.entity_type}'." + ) + return self._thumbnail_id + + def set_thumbnail_id(self, thumbnail_id): + """Change thumbnail id. + + Args: + thumbnail_id (Union[str, None]): Thumbnail id for entity. + + """ + if not self._supports_thumbnail: + raise NotImplementedError( + f"Thumbnail is not supported for '{self.entity_type}'." + ) + self._thumbnail_id = thumbnail_id + + thumbnail_id = property(get_thumbnail_id, set_thumbnail_id) + + def get_status(self) -> Union[str, UNKNOWN_VALUE]: + """Folder status. + + Returns: + Union[str, UNKNOWN_VALUE]: Folder status or 'UNKNOWN_VALUE'. + + """ + if not self._supports_status: + raise NotImplementedError( + f"Status is not supported for '{self.entity_type}'." + ) + return self._status + + def set_status(self, status_name: str): + """Set folder status. + + Args: + status_name (str): Status name. + + """ + if not self._supports_status: + raise NotImplementedError( + f"Status is not supported for '{self.entity_type}'." + ) + project_entity = self._entity_hub.project_entity + status = project_entity.get_status_by_slugified_name(status_name) + if status is None: + raise ValueError( + f"Status {status_name} is not available on project." + ) + + if not status.is_available_for_entity_type(self.entity_type): + raise ValueError( + f"Status {status_name} is not available for folder." + ) + + self._status = status_name + + status = property(get_status, set_status) + + def get_tags(self): + """Task tags. + + Returns: + list[str]: Task tags. + + """ + if not self._supports_tags: + raise NotImplementedError( + f"Tags are not supported for '{self.entity_type}'." + ) + return self._tags + + def set_tags(self, tags): + """Change tags. + + Args: + tags (Iterable[str]): Tags. + + """ + if not self._supports_tags: + raise NotImplementedError( + f"Tags are not supported for '{self.entity_type}'." + ) + self._tags = list(tags) + + tags = property(get_tags, set_tags) + class ProjectStatus: """Project status class. @@ -2402,8 +2577,9 @@ class ProjectEntity(BaseEntity): the entity. created (Optional[bool]): Entity is new. When 'None' is passed the value is defined based on value of 'entity_id'. - """ + """ + _supports_name = True entity_type = "project" parent_entity_types = [] # TODO These are hardcoded but maybe should be used from server??? @@ -2428,15 +2604,15 @@ def __init__( created=None, ): super().__init__( - entity_id, - parent_id, - name, - attribs, - data, - thumbnail_id, - active, - entity_hub, - created + entity_id=name, + parent_id=PROJECT_PARENT_ID, + attribs=attribs, + data=data, + active=active, + created=False, + entity_hub=entity_hub, + name=name, + thumbnail_id=thumbnail_id, ) self._project_code = project_code @@ -2458,6 +2634,11 @@ def _prepare_entity_id(self, entity_id): entity_id, self.project_name)) return entity_id + def set_name(self, name): + if self._name == name: + return + raise ValueError("It is not allowed to change project name.") + def get_parent(self, *args, **kwargs): return None @@ -2590,6 +2771,11 @@ class FolderEntity(BaseEntity): created (Optional[bool]): Entity is new. When 'None' is passed the value is defined based on value of 'entity_id'. """ + _supports_name = True + _supports_label = True + _supports_tags = True + _supports_status = True + _supports_thumbnail = True entity_type = "folder" parent_entity_types = ["folder", "project"] @@ -2612,108 +2798,40 @@ def __init__( status=UNKNOWN_VALUE, ): super().__init__( - entity_id, - parent_id, - name, - attribs, - data, - thumbnail_id, - active, - entity_hub, - created, + entity_id=entity_id, + parent_id=parent_id, + attribs=attribs, + data=data, + active=active, + created=created, + entity_hub=entity_hub, + name=name, + label=label, + tags=tags, + status=status, + thumbnail_id=thumbnail_id, ) # Autofill project as parent of folder if is not yet set # - this can be guessed only if folder was just created if self.created and self._parent_id is UNKNOWN_VALUE: self._parent_id = self.project_name - if tags is None: - tags = [] - else: - tags = list(tags) - self._folder_type = folder_type - self._label = label - self._tags = copy.deepcopy(tags) - self._status = status self._orig_folder_type = folder_type - self._orig_label = label - self._orig_status = status - self._orig_tags = copy.deepcopy(tags) # Know if folder has any products # - is used to know if folder allows hierarchy changes self._has_published_content = False self._path = path - def get_folder_type(self): + def get_folder_type(self) -> str: return self._folder_type - def set_folder_type(self, folder_type): + def set_folder_type(self, folder_type: str): self._folder_type = folder_type folder_type = property(get_folder_type, set_folder_type) - def get_label(self): - return self._label - - def set_label(self, label): - self._label = label - - label = property(get_label, set_label) - - def get_status(self): - """Folder status. - - Returns: - Union[str, UNKNOWN_VALUE]: Folder status or 'UNKNOWN_VALUE'. - - """ - return self._status - - def set_status(self, status_name): - """Set folder status. - - Args: - status_name (str): Status name. - - """ - project_entity = self._entity_hub.project_entity - status = project_entity.get_status_by_slugified_name(status_name) - if status is None: - raise ValueError( - f"Status {status_name} is not available on project." - ) - - if not status.is_available_for_entity_type("folder"): - raise ValueError( - f"Status {status_name} is not available for folder." - ) - - self._status = status_name - - status = property(get_status, set_status) - - def get_tags(self): - """Folder tags. - - Returns: - list[str]: Folder tags. - - """ - return self._tags - - def set_tags(self, tags): - """Change tags. - - Args: - tags (Iterable[str]): Tags. - - """ - self._tags = list(tags) - - tags = property(get_tags, set_tags) - def get_path(self, dynamic_value=True): if not dynamic_value: return self._path @@ -2758,16 +2876,12 @@ def _immutable_for_hierarchy(self): return None def lock(self): - super(FolderEntity, self).lock() - self._orig_label = self._get_label_value() + super().lock() self._orig_folder_type = self._folder_type - self._orig_status = self._status - self._orig_tags = copy.deepcopy(self._tags) @property def changes(self): changes = self._get_default_changes() - if self._orig_parent_id != self._parent_id: parent_id = self._parent_id if parent_id == self.project_name: @@ -2777,15 +2891,6 @@ def changes(self): if self._orig_folder_type != self._folder_type: changes["folderType"] = self._folder_type - if self._orig_status != self._status: - changes["status"] = self._status - - if self._orig_tags != self._tags: - changes["tags"] = self._tags - - label = self._get_label_value() - if label != self._orig_label: - changes["label"] = label return changes @@ -2855,29 +2960,17 @@ def to_create_body_data(self): output["data"] = self._data.get_new_entity_value() return output - def _get_label_value(self): - """Get label value that will be used for operations. - - Returns: - Union[str, None]: Label value. - - """ - label = self._label - if not label or self._name == label: - return None - return label - class TaskEntity(BaseEntity): """Entity representing a task on AYON server. Args: + name (str): Name of entity. task_type (str): Type of task. Task type must be available in config of project task types. entity_id (Union[str, None]): Id of the entity. New id is created if not passed. parent_id (Union[str, None]): Id of parent entity. - name (str): Name of entity. label (Optional[str]): Task label. attribs (Dict[str, Any]): Attribute values. data (Dict[str, Any]): Entity data (custom data). @@ -2887,8 +2980,13 @@ class TaskEntity(BaseEntity): the entity. created (Optional[bool]): Entity is new. When 'None' is passed the value is defined based on value of 'entity_id'. + status (Optional[str]): Task status. """ - + _supports_name = True + _supports_label = True + _supports_tags = True + _supports_status = True + _supports_thumbnail = True entity_type = "task" parent_entity_types = ["folder"] @@ -2910,116 +3008,52 @@ def __init__( status=UNKNOWN_VALUE, ): super().__init__( - entity_id, - parent_id, - name, - attribs, - data, - thumbnail_id, - active, - entity_hub, - created, + entity_id=entity_id, + parent_id=parent_id, + attribs=attribs, + data=data, + active=active, + created=created, + entity_hub=entity_hub, + name=name, + label=label, + tags=tags, + status=status, + thumbnail_id=thumbnail_id, ) - - if tags is None: - tags = [] - else: - tags = list(tags) - if assignees is None: assignees = [] else: assignees = list(assignees) self._task_type = task_type - self._label = label - self._status = status - self._tags = tags self._assignees = assignees self._orig_task_type = task_type - self._orig_label = label - self._orig_status = status - self._orig_tags = copy.deepcopy(tags) self._orig_assignees = copy.deepcopy(assignees) self._children_ids = set() def lock(self): - super(TaskEntity, self).lock() - self._orig_label = self._get_label_value() + super().lock() self._orig_task_type = self._task_type - self._orig_status = self._status - self._orig_tags = copy.deepcopy(self._tags) self._orig_assignees = copy.deepcopy(self._assignees) - def get_task_type(self): - return self._task_type - - def set_task_type(self, task_type): - self._task_type = task_type - - task_type = property(get_task_type, set_task_type) - - def get_label(self): - return self._label - - def set_label(self, label): - self._label = label - - label = property(get_label, set_label) - - def get_status(self): - """Task status. - - Returns: - Union[str, UNKNOWN_VALUE]: Task status or 'UNKNOWN_VALUE'. - - """ - return self._status - - def set_status(self, status_name): - """Set Task status. - - Args: - status_name (str): Status name. - - """ - project_entity = self._entity_hub.project_entity - status = project_entity.get_status_by_slugified_name(status_name) - if status is None: - raise ValueError( - f"Status {status_name} is not available on project." - ) - - if not status.is_available_for_entity_type("task"): - raise ValueError( - f"Status {status_name} is not available for task." - ) - - self._status = status_name - - status = property(get_status, set_status) - - def get_tags(self): - """Task tags. - - Returns: - list[str]: Task tags. + def get_folder_id(self): + return self._parent_id - """ - return self._tags + def set_folder_id(self, folder_id): + self.set_parent_id(folder_id) - def set_tags(self, tags): - """Change tags. + folder_id = property(get_folder_id, set_folder_id) - Args: - tags (Iterable[str]): Tags. + def get_task_type(self) -> str: + return self._task_type - """ - self._tags = list(tags) + def set_task_type(self, task_type: str): + self._task_type = task_type - tags = property(get_tags, set_tags) + task_type = property(get_task_type, set_task_type) def get_assignees(self): """Task assignees. @@ -3054,19 +3088,9 @@ def changes(self): if self._orig_task_type != self._task_type: changes["taskType"] = self._task_type - if self._orig_status != self._status: - changes["status"] = self._status - - if self._orig_tags != self._tags: - changes["tags"] = self._tags - if self._orig_assignees != self._assignees: changes["assignees"] = self._assignees - label = self._get_label_value() - if label != self._orig_label: - changes["label"] = label - return changes @classmethod @@ -3124,14 +3148,4 @@ def to_create_body_data(self): output["data"] = self._data.get_new_entity_value() return output - def _get_label_value(self): - """Get label value that will be used for operations. - - Returns: - Union[str, None]: Label value. - """ - label = self._label - if not label or self._name == label: - return None - return label From e43b27f5e539f47705f6e62d389874418d7556d6 Mon Sep 17 00:00:00 2001 From: Jakub Trllo <43494761+iLLiCiTiT@users.noreply.github.com> Date: Fri, 25 Oct 2024 17:32:52 +0200 Subject: [PATCH 03/33] use 'fetch' over 'query' --- ayon_api/entity_hub.py | 89 +++++++++++++++++++++++++++++------------- 1 file changed, 61 insertions(+), 28 deletions(-) diff --git a/ayon_api/entity_hub.py b/ayon_api/entity_hub.py index 9ecea77a9..1451a7195 100644 --- a/ayon_api/entity_hub.py +++ b/ayon_api/entity_hub.py @@ -1,8 +1,10 @@ import re import copy import collections +import warnings from abc import ABC, abstractmethod import typing +from typing import Optional, Union, Iterable, Dict, List, Set, Any from ._api import get_server_api_connection from .utils import create_entity_id, convert_entity_id, slugify_string @@ -146,7 +148,7 @@ def get_attributes_for_type(self, entity_type): """ return self._connection.get_attributes_for_type(entity_type) - def get_entity_by_id(self, entity_id): + def get_entity_by_id(self, entity_id: str) -> Optional["BaseEntity"]: """Receive entity by its id without entity type. The entity must be already existing in cached objects. @@ -155,44 +157,55 @@ def get_entity_by_id(self, entity_id): entity_id (str): Id of entity. Returns: - Union[BaseEntity, None]: Entity object or None. + Optional[BaseEntity]: Entity object or None. """ return self._entities_by_id.get(entity_id) - def get_folder_by_id(self, entity_id, allow_query=True): + def get_folder_by_id( + self, + entity_id: str, + allow_fetch: Optional[bool] = True, + ) -> Optional["FolderEntity"]: """Get folder entity by id. Args: - entity_id (str): Id of folder entity. - allow_query (bool): Try to query entity from server if is not + entity_id (str): Folder entity id. + allow_fetch (bool): Try to query entity from server if is not available in cache. Returns: - Union[FolderEntity, None]: Object of folder or 'None'. + Optional[FolderEntity]: Folder entity object. """ - if allow_query: - return self.get_or_query_entity_by_id(entity_id, ["folder"]) + if allow_fetch: + return self.get_or_fetch_entity_by_id(entity_id, ["folder"]) return self._entities_by_id.get(entity_id) - def get_task_by_id(self, entity_id, allow_query=True): + def get_task_by_id( + self, + entity_id: str, + allow_fetch: Optional[bool] = True, + ) -> Optional["TaskEntity"]: """Get task entity by id. Args: entity_id (str): Id of task entity. - allow_query (bool): Try to query entity from server if is not + allow_fetch (bool): Try to query entity from server if is not available in cache. Returns: - Union[TaskEntity, None]: Object of folder or 'None'. + Optional[TaskEntity]: Task entity object or None. """ - if allow_query: - return self.get_or_query_entity_by_id(entity_id, ["task"]) + if allow_fetch: + return self.get_or_fetch_entity_by_id(entity_id, ["task"]) return self._entities_by_id.get(entity_id) - - def get_or_query_entity_by_id(self, entity_id, entity_types): + def get_or_fetch_entity_by_id( + self, + entity_id: str, + entity_types: List["EntityType"], + ): """Get or query entity based on it's id and possible entity types. This is a helper function when entity id is known but entity type may @@ -249,6 +262,18 @@ def get_or_query_entity_by_id(self, entity_id, entity_types): return None + def get_or_query_entity_by_id( + self, + entity_id: str, + entity_types: List["EntityType"], + ): + warnings.warn( + "Method 'get_or_query_entity_by_id' is deprecated. " + "Please use 'get_or_fetch_entity_by_id' instead.", + DeprecationWarning + ) + return self.get_or_fetch_entity_by_id(entity_id, entity_types) + @property def entities(self): """Iterator over available entities. @@ -463,7 +488,7 @@ def set_entity_parent(self, entity_id, parent_id, orig_parent_id=_NOT_SET): parent.add_child(entity_id) self.reset_immutable_for_hierarchy_cache(parent_id) - def _query_entity_children(self, entity): + def _fetch_entity_children(self, entity): folder_fields = self._get_folder_fields() task_fields = self._get_task_fields() tasks = [] @@ -518,15 +543,15 @@ def _query_entity_children(self, entity): entity.fill_children_ids(children_ids) - def get_entity_children(self, entity, allow_query=True): - children_ids = entity.get_children_ids(allow_query=False) + def get_entity_children(self, entity, allow_fetch=True): + children_ids = entity.get_children_ids(allow_fetch=False) if children_ids is not UNKNOWN_VALUE: return entity.get_children() - if children_ids is UNKNOWN_VALUE and not allow_query: + if children_ids is UNKNOWN_VALUE and not allow_fetch: return UNKNOWN_VALUE - self._query_entity_children(entity) + self._fetch_entity_children(entity) return entity.get_children() @@ -614,7 +639,7 @@ def _get_task_fields(self): self._connection.get_default_fields_for_type("task") ) - def query_entities_from_server(self): + def fetch_hierarchy_entities(self): """Query whole project at once.""" project_entity = self.fill_project_from_server() @@ -670,6 +695,14 @@ def query_entities_from_server(self): entity = lock_queue.popleft() entity.lock() + def query_entities_from_server(self): + warnings.warn( + "Method 'query_entities_from_server' is deprecated." + " Please use 'fetch_hierarchy_entities' instead.", + DeprecationWarning + ) + return self.fetch_hierarchy_entities() + def lock(self): if self._project_entity is None: return @@ -1499,7 +1532,7 @@ def set_parent_id(self, parent_id): parent_id = property(get_parent_id, set_parent_id) - def get_parent(self, allow_query=True): + def get_parent(self, allow_fetch=True): """Parent entity. Returns: @@ -1510,13 +1543,13 @@ def get_parent(self, allow_query=True): if parent is not None: return parent - if not allow_query: + if not allow_fetch: return self._parent_id if self._parent_id is UNKNOWN_VALUE: return self._parent_id - return self._entity_hub.get_or_query_entity_by_id( + return self._entity_hub.get_or_fetch_entity_by_id( self._parent_id, self.parent_entity_types ) @@ -1537,7 +1570,7 @@ def set_parent(self, parent): parent = property(get_parent, set_parent) - def get_children_ids(self, allow_query=True): + def get_children_ids(self, allow_fetch=True): """Access to children objects. Todos: @@ -1551,14 +1584,14 @@ def get_children_ids(self, allow_query=True): """ if self._children_ids is UNKNOWN_VALUE: - if not allow_query: + if not allow_fetch: return self._children_ids self._entity_hub.get_entity_children(self, True) return set(self._children_ids) children_ids = property(get_children_ids) - def get_children(self, allow_query=True): + def get_children(self, allow_fetch=True): """Access to children objects. Returns: @@ -1566,7 +1599,7 @@ def get_children(self, allow_query=True): """ if self._children_ids is UNKNOWN_VALUE: - if not allow_query: + if not allow_fetch: return self._children_ids return self._entity_hub.get_entity_children(self, True) From 9452e3768a99e29e6a949ffcf1b3cdf967449430 Mon Sep 17 00:00:00 2001 From: Jakub Trllo <43494761+iLLiCiTiT@users.noreply.github.com> Date: Fri, 25 Oct 2024 17:36:44 +0200 Subject: [PATCH 04/33] added some typehints --- ayon_api/entity_hub.py | 69 ++++++++++++++++++++++-------------------- 1 file changed, 37 insertions(+), 32 deletions(-) diff --git a/ayon_api/entity_hub.py b/ayon_api/entity_hub.py index 1451a7195..2c308fc8b 100644 --- a/ayon_api/entity_hub.py +++ b/ayon_api/entity_hub.py @@ -129,7 +129,7 @@ def project_entity(self): self.fill_project_from_server() return self._project_entity - def get_attributes_for_type(self, entity_type): + def get_attributes_for_type(self, entity_type: "EntityType"): """Get attributes available for a type. Attributes are based on entity types. @@ -321,14 +321,14 @@ def add_new_task(self, *args, created=True, **kwargs): Args: task_type (str): Type of task. Task type must be available in config of project folder types. - entity_id (Union[str, None]): Id of the entity. New id is created + entity_id (Optional[str]): Id of the entity. New id is created if not passed. - parent_id (Union[str, None]): Id of parent entity. + parent_id (Optional[str]): Id of parent entity. name (str): Name of entity. label (Optional[str]): Folder label. attribs (Dict[str, Any]): Attribute values. data (Dict[str, Any]): Entity data (custom data). - thumbnail_id (Union[str, None]): Id of entity's thumbnail. + thumbnail_id (Optional[str]): Id of entity's thumbnail. active (bool): Is entity active. created (Optional[bool]): Entity is new. When 'None' is passed the value is defined based on value of 'entity_id'. @@ -565,7 +565,7 @@ def delete_entity(self, entity): parent.remove_child(entity.id) def reset_immutable_for_hierarchy_cache( - self, entity_id, bottom_to_top=True + self, entity_id: Optional[str], bottom_to_top: Optional[bool] = True ): if bottom_to_top is None or entity_id is None: return @@ -574,16 +574,20 @@ def reset_immutable_for_hierarchy_cache( reset_queue.append(entity_id) if bottom_to_top: while reset_queue: - entity_id = reset_queue.popleft() - entity = self.get_entity_by_id(entity_id) + entity_id: str = reset_queue.popleft() + entity: Optional["BaseEntity"] = self.get_entity_by_id( + entity_id + ) if entity is None: continue entity.reset_immutable_for_hierarchy_cache(None) reset_queue.append(entity.parent_id) else: while reset_queue: - entity_id = reset_queue.popleft() - entity = self.get_entity_by_id(entity_id) + entity_id: str = reset_queue.popleft() + entity: Optional["BaseEntity"] = self.get_entity_by_id( + entity_id + ) if entity is None: continue entity.reset_immutable_for_hierarchy_cache(None) @@ -625,7 +629,7 @@ def fill_project_from_server(self): self.add_entity(self._project_entity) return self._project_entity - def _get_folder_fields(self): + def _get_folder_fields(self) -> Set[str]: folder_fields = set( self._connection.get_default_fields_for_type("folder") ) @@ -634,7 +638,7 @@ def _get_folder_fields(self): folder_fields.add("data") return folder_fields - def _get_task_fields(self): + def _get_task_fields(self) -> Set[str]: return set( self._connection.get_default_fields_for_type("task") ) @@ -1251,14 +1255,14 @@ def __getitem__(self, item): def __setitem__(self, item, value): return setattr(self, item, value) - def _prepare_entity_id(self, entity_id): + def _prepare_entity_id(self, entity_id: Any) -> str: entity_id = convert_entity_id(entity_id) if entity_id is None: entity_id = create_entity_id() return entity_id @property - def id(self): + def id(self) -> str: """Access to entity id under which is entity available on server. Returns: @@ -1268,7 +1272,7 @@ def id(self): return self._entity_id @property - def removed(self): + def removed(self) -> bool: return self._parent_id is None @property @@ -1300,7 +1304,7 @@ def data(self): return self._data @property - def project_name(self): + def project_name(self) -> str: """Quick access to project from entity hub. Returns: @@ -1311,8 +1315,8 @@ def project_name(self): @property @abstractmethod - def entity_type(self): - """Entity type coresponding to server. + def entity_type(self) -> "EntityType": + """Entity type corresponding to server. Returns: EntityType: Entity type. @@ -1322,22 +1326,22 @@ def entity_type(self): @property @abstractmethod - def parent_entity_types(self): - """Entity type coresponding to server. + def parent_entity_types(self) -> List[str]: + """Entity type corresponding to server. Returns: - Iterable[str]: Possible entity types of parent. + List[str]: Possible entity types of parent. """ pass @property @abstractmethod - def changes(self): + def changes(self) -> Optional[Dict[str, Any]]: """Receive entity changes. Returns: - Union[Dict[str, Any], None]: All values that have changed on + Optional[Dict[str, Any]]: All values that have changed on entity. New entity must return None. """ @@ -1345,7 +1349,9 @@ def changes(self): @classmethod @abstractmethod - def from_entity_data(cls, entity_data, entity_hub): + def from_entity_data( + cls, entity_data: Dict[str, Any], entity_hub: EntityHub + ) -> "BaseEntity": """Create entity based on queried data from server. Args: @@ -1359,7 +1365,7 @@ def from_entity_data(cls, entity_data, entity_hub): pass @abstractmethod - def to_create_body_data(self): + def to_create_body_data(self) -> Dict[str, Any]: """Convert object of entity to data for server on creation. Returns: @@ -1369,7 +1375,7 @@ def to_create_body_data(self): pass @property - def immutable_for_hierarchy(self): + def immutable_for_hierarchy(self) -> bool: """Entity is immutable for hierarchy changes. Hierarchy changes can be considered as change of name or parents. @@ -1402,17 +1408,19 @@ def _immutable_for_hierarchy(self): which is used in property 'immutable_for_hierarchy'. Returns: - Union[bool, None]: Bool to explicitly telling if is immutable or + Optional[bool]: Bool to explicitly telling if is immutable or not otherwise None. """ return None @property - def has_cached_immutable_hierarchy(self): + def has_cached_immutable_hierarchy(self) -> bool: return self._immutable_for_hierarchy_cache is not None - def reset_immutable_for_hierarchy_cache(self, bottom_to_top=True): + def reset_immutable_for_hierarchy_cache( + self, bottom_to_top: Optional[bool] = True + ): """Clear cache of immutable hierarchy property. This is used when entity changed parent or a child was added. @@ -2598,11 +2606,8 @@ class ProjectEntity(BaseEntity): library (bool): Is project library project. folder_types (list[dict[str, Any]]): Folder types definition. task_types (list[dict[str, Any]]): Task types definition. - entity_id (Optional[str]): Id of the entity. New id is created if - not passed. - parent_id (Union[str, None]): Id of parent entity. name (str): Name of entity. - attribs (Dict[str, Any]): Attribute values. + attribs (Optional[Dict[str, Any]]): Attribute values. data (Dict[str, Any]): Entity data (custom data). thumbnail_id (Union[str, None]): Id of entity's thumbnail. active (bool): Is entity active. From 41ddf872547f9080d361e7502f65dc128ef0d732 Mon Sep 17 00:00:00 2001 From: Jakub Trllo <43494761+iLLiCiTiT@users.noreply.github.com> Date: Fri, 25 Oct 2024 17:37:31 +0200 Subject: [PATCH 05/33] simplified ProjectEntity arguments --- ayon_api/entity_hub.py | 37 ++++++++++++++----------------------- 1 file changed, 14 insertions(+), 23 deletions(-) diff --git a/ayon_api/entity_hub.py b/ayon_api/entity_hub.py index 2c308fc8b..f1651f929 100644 --- a/ayon_api/entity_hub.py +++ b/ayon_api/entity_hub.py @@ -2602,19 +2602,17 @@ class ProjectEntity(BaseEntity): """Entity representing project on AYON server. Args: + name (str): Name of entity. project_code (str): Project code. library (bool): Is project library project. folder_types (list[dict[str, Any]]): Folder types definition. task_types (list[dict[str, Any]]): Task types definition. - name (str): Name of entity. + statuses: (list[dict[str, Any]]): Statuses definition. attribs (Optional[Dict[str, Any]]): Attribute values. data (Dict[str, Any]): Entity data (custom data). - thumbnail_id (Union[str, None]): Id of entity's thumbnail. active (bool): Is entity active. entity_hub (EntityHub): Object of entity hub which created object of the entity. - created (Optional[bool]): Entity is new. When 'None' is passed the - value is defined based on value of 'entity_id'. """ _supports_name = True @@ -2626,20 +2624,16 @@ class ProjectEntity(BaseEntity): def __init__( self, - project_code, - library, - folder_types, - task_types, - statuses, - entity_id=None, - parent_id=UNKNOWN_VALUE, - name=UNKNOWN_VALUE, - attribs=UNKNOWN_VALUE, - data=UNKNOWN_VALUE, - thumbnail_id=UNKNOWN_VALUE, - active=UNKNOWN_VALUE, - entity_hub=None, - created=None, + name: str, + project_code: str, + library: bool, + folder_types: List[Dict[str, Any]], + task_types: List[Dict[str, Any]], + statuses: List[Dict[str, Any]], + attribs: Optional[Dict[str, Any]] = UNKNOWN_VALUE, + data: Optional[Dict[str, Any]] = UNKNOWN_VALUE, + active: Optional[bool] = UNKNOWN_VALUE, + entity_hub: EntityHub = None, ): super().__init__( entity_id=name, @@ -2650,7 +2644,6 @@ def __init__( created=False, entity_hub=entity_hub, name=name, - thumbnail_id=thumbnail_id, ) self._project_code = project_code @@ -2765,16 +2758,14 @@ def changes(self): return changes @classmethod - def from_entity_data(cls, project, entity_hub): + def from_entity_data(cls, project, entity_hub) -> "ProjectEntity": return cls( + project["name"], project["code"], - parent_id=PROJECT_PARENT_ID, - entity_id=project["name"], library=project["library"], folder_types=project["folderTypes"], task_types=project["taskTypes"], statuses=project["statuses"], - name=project["name"], attribs=project["ownAttrib"], data=project["data"], active=project["active"], From 98e9db24812d19225e059b51d6eabb9453e1d580 Mon Sep 17 00:00:00 2001 From: Jakub Trllo <43494761+iLLiCiTiT@users.noreply.github.com> Date: Fri, 25 Oct 2024 17:44:09 +0200 Subject: [PATCH 06/33] better arguments order for folder entity --- ayon_api/entity_hub.py | 97 +++++++++++++++++++++++++++--------------- 1 file changed, 63 insertions(+), 34 deletions(-) diff --git a/ayon_api/entity_hub.py b/ayon_api/entity_hub.py index f1651f929..a3ccc4f6a 100644 --- a/ayon_api/entity_hub.py +++ b/ayon_api/entity_hub.py @@ -285,23 +285,39 @@ def entities(self): for entity in self._entities_by_id.values(): yield entity - def add_new_folder(self, *args, created=True, **kwargs): + def add_new_folder( + self, + name: str, + folder_type: str, + label: Optional[str] = None, + parent_id: Optional[str] = UNKNOWN_VALUE, + attribs: Optional[Dict[str, Any]] = UNKNOWN_VALUE, + data: Optional[Dict[str, Any]] = UNKNOWN_VALUE, + path: Optional[str] = None, + status: Optional[str] = UNKNOWN_VALUE, + thumbnail_id: Optional[str] = UNKNOWN_VALUE, + active: bool = UNKNOWN_VALUE, + entity_id: Optional[str] = None, + created: Optional[bool] = None, + tags: Optional[List[str]] = None, + ): """Create folder object and add it to entity hub. Args: + name (str): Name of entity. folder_type (str): Type of folder. Folder type must be available in config of project folder types. - entity_id (Union[str, None]): Id of the entity. New id is created - if not passed. - parent_id (Union[str, None]): Id of parent entity. - name (str): Name of entity. label (Optional[str]): Folder label. - path (Optional[str]): Folder path. Path consist of all parent names - with slash('/') used as separator. + parent_id (Union[str, None]): Id of parent entity. attribs (Dict[str, Any]): Attribute values. data (Dict[str, Any]): Entity data (custom data). + path (Optional[str]): Folder path. Path consist of all parent names + with slash('/') used as separator. + status (Optional[str]): Folder status. thumbnail_id (Union[str, None]): Id of entity's thumbnail. active (bool): Is entity active. + entity_id (Union[str, None]): Id of the entity. New id is created if + not passed. created (Optional[bool]): Entity is new. When 'None' is passed the value is defined based on value of 'entity_id'. @@ -310,7 +326,20 @@ def add_new_folder(self, *args, created=True, **kwargs): """ folder_entity = FolderEntity( - *args, **kwargs, created=created, entity_hub=self + name=name, + folder_type=folder_type, + label=label, + parent_id=parent_id, + attribs=attribs, + data=data, + path=path, + status=status, + thumbnail_id=thumbnail_id, + active=active, + entity_id=entity_id, + created=created, + tags=tags, + entity_hub=self ) self.add_entity(folder_entity) return folder_entity @@ -2782,23 +2811,24 @@ class FolderEntity(BaseEntity): """Entity representing a folder on AYON server. Args: + name (str): Name of entity. folder_type (str): Type of folder. Folder type must be available in config of project folder types. - entity_id (Union[str, None]): Id of the entity. New id is created if - not passed. + label (Optional[str]): Folder label. parent_id (Union[str, None]): Id of parent entity. - name (str): Name of entity. attribs (Dict[str, Any]): Attribute values. data (Dict[str, Any]): Entity data (custom data). - thumbnail_id (Union[str, None]): Id of entity's thumbnail. - active (bool): Is entity active. - label (Optional[str]): Folder label. path (Optional[str]): Folder path. Path consist of all parent names with slash('/') used as separator. - entity_hub (EntityHub): Object of entity hub which created object of - the entity. + status (Optional[str]): Folder status. + thumbnail_id (Union[str, None]): Id of entity's thumbnail. + active (bool): Is entity active. + entity_id (Union[str, None]): Id of the entity. New id is created if + not passed. created (Optional[bool]): Entity is new. When 'None' is passed the value is defined based on value of 'entity_id'. + entity_hub (EntityHub): Object of entity hub which created object of + the entity. """ _supports_name = True _supports_label = True @@ -2811,20 +2841,20 @@ class FolderEntity(BaseEntity): def __init__( self, - folder_type, - entity_id=None, - parent_id=UNKNOWN_VALUE, - name=UNKNOWN_VALUE, - attribs=UNKNOWN_VALUE, - data=UNKNOWN_VALUE, - thumbnail_id=UNKNOWN_VALUE, - active=UNKNOWN_VALUE, - entity_hub=None, - created=None, - label=None, - path=None, - tags=None, - status=UNKNOWN_VALUE, + name: str, + folder_type: str, + label: Optional[str] = None, + parent_id: Optional[str] = UNKNOWN_VALUE, + attribs: Optional[Dict[str, Any]] = UNKNOWN_VALUE, + data: Optional[Dict[str, Any]] = UNKNOWN_VALUE, + path: Optional[str] = None, + status: Optional[str] = UNKNOWN_VALUE, + thumbnail_id: Optional[str] = UNKNOWN_VALUE, + active: bool = UNKNOWN_VALUE, + entity_id: Optional[str] = None, + created: Optional[bool] = None, + tags: Optional[List[str]] = None, + entity_hub: EntityHub = None, ): super().__init__( entity_id=entity_id, @@ -2920,23 +2950,22 @@ def changes(self): if self._orig_folder_type != self._folder_type: changes["folderType"] = self._folder_type - return changes @classmethod - def from_entity_data(cls, folder, entity_hub): + def from_entity_data(cls, folder, entity_hub) -> "FolderEntity": parent_id = folder["parentId"] if parent_id is None: parent_id = entity_hub.project_entity.id return cls( - folder["folderType"], + name=folder["name"], + folder_type=folder["folderType"], label=folder["label"], path=folder["path"], status=folder["status"], tags=folder["tags"], entity_id=folder["id"], parent_id=parent_id, - name=folder["name"], data=folder.get("data"), attribs=folder["ownAttrib"], active=folder["active"], From f59f8788199406eebae395571725d90ef746d172 Mon Sep 17 00:00:00 2001 From: Jakub Trllo <43494761+iLLiCiTiT@users.noreply.github.com> Date: Fri, 25 Oct 2024 17:48:01 +0200 Subject: [PATCH 07/33] even better args order --- ayon_api/entity_hub.py | 39 +++++++++++++++++++++------------------ 1 file changed, 21 insertions(+), 18 deletions(-) diff --git a/ayon_api/entity_hub.py b/ayon_api/entity_hub.py index a3ccc4f6a..8a0de641f 100644 --- a/ayon_api/entity_hub.py +++ b/ayon_api/entity_hub.py @@ -289,17 +289,17 @@ def add_new_folder( self, name: str, folder_type: str, - label: Optional[str] = None, parent_id: Optional[str] = UNKNOWN_VALUE, - attribs: Optional[Dict[str, Any]] = UNKNOWN_VALUE, - data: Optional[Dict[str, Any]] = UNKNOWN_VALUE, + label: Optional[str] = None, path: Optional[str] = None, status: Optional[str] = UNKNOWN_VALUE, + tags: Optional[List[str]] = None, + attribs: Optional[Dict[str, Any]] = UNKNOWN_VALUE, + data: Optional[Dict[str, Any]] = UNKNOWN_VALUE, thumbnail_id: Optional[str] = UNKNOWN_VALUE, active: bool = UNKNOWN_VALUE, entity_id: Optional[str] = None, created: Optional[bool] = None, - tags: Optional[List[str]] = None, ): """Create folder object and add it to entity hub. @@ -307,13 +307,14 @@ def add_new_folder( name (str): Name of entity. folder_type (str): Type of folder. Folder type must be available in config of project folder types. - label (Optional[str]): Folder label. parent_id (Union[str, None]): Id of parent entity. - attribs (Dict[str, Any]): Attribute values. - data (Dict[str, Any]): Entity data (custom data). + label (Optional[str]): Folder label. path (Optional[str]): Folder path. Path consist of all parent names with slash('/') used as separator. status (Optional[str]): Folder status. + tags (Optional[List[str]]): Folder tags. + attribs (Dict[str, Any]): Attribute values. + data (Dict[str, Any]): Entity data (custom data). thumbnail_id (Union[str, None]): Id of entity's thumbnail. active (bool): Is entity active. entity_id (Union[str, None]): Id of the entity. New id is created if @@ -328,17 +329,17 @@ def add_new_folder( folder_entity = FolderEntity( name=name, folder_type=folder_type, - label=label, parent_id=parent_id, - attribs=attribs, - data=data, + label=label, path=path, status=status, + tags=tags, + attribs=attribs, + data=data, thumbnail_id=thumbnail_id, active=active, entity_id=entity_id, created=created, - tags=tags, entity_hub=self ) self.add_entity(folder_entity) @@ -2814,13 +2815,14 @@ class FolderEntity(BaseEntity): name (str): Name of entity. folder_type (str): Type of folder. Folder type must be available in config of project folder types. - label (Optional[str]): Folder label. parent_id (Union[str, None]): Id of parent entity. - attribs (Dict[str, Any]): Attribute values. - data (Dict[str, Any]): Entity data (custom data). + label (Optional[str]): Folder label. path (Optional[str]): Folder path. Path consist of all parent names with slash('/') used as separator. status (Optional[str]): Folder status. + tags (Optional[List[str]]): Folder tags. + attribs (Dict[str, Any]): Attribute values. + data (Dict[str, Any]): Entity data (custom data). thumbnail_id (Union[str, None]): Id of entity's thumbnail. active (bool): Is entity active. entity_id (Union[str, None]): Id of the entity. New id is created if @@ -2829,6 +2831,7 @@ class FolderEntity(BaseEntity): value is defined based on value of 'entity_id'. entity_hub (EntityHub): Object of entity hub which created object of the entity. + """ _supports_name = True _supports_label = True @@ -2843,17 +2846,17 @@ def __init__( self, name: str, folder_type: str, - label: Optional[str] = None, parent_id: Optional[str] = UNKNOWN_VALUE, - attribs: Optional[Dict[str, Any]] = UNKNOWN_VALUE, - data: Optional[Dict[str, Any]] = UNKNOWN_VALUE, + label: Optional[str] = None, path: Optional[str] = None, status: Optional[str] = UNKNOWN_VALUE, + tags: Optional[List[str]] = None, + attribs: Optional[Dict[str, Any]] = UNKNOWN_VALUE, + data: Optional[Dict[str, Any]] = UNKNOWN_VALUE, thumbnail_id: Optional[str] = UNKNOWN_VALUE, active: bool = UNKNOWN_VALUE, entity_id: Optional[str] = None, created: Optional[bool] = None, - tags: Optional[List[str]] = None, entity_hub: EntityHub = None, ): super().__init__( From 4679f6f50ef1044a7c7d7b41c1bf3a7fa9696134 Mon Sep 17 00:00:00 2001 From: Jakub Trllo <43494761+iLLiCiTiT@users.noreply.github.com> Date: Fri, 25 Oct 2024 17:54:26 +0200 Subject: [PATCH 08/33] match order of args in classmethod --- ayon_api/entity_hub.py | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/ayon_api/entity_hub.py b/ayon_api/entity_hub.py index 8a0de641f..dcda65f3a 100644 --- a/ayon_api/entity_hub.py +++ b/ayon_api/entity_hub.py @@ -2963,16 +2963,16 @@ def from_entity_data(cls, folder, entity_hub) -> "FolderEntity": return cls( name=folder["name"], folder_type=folder["folderType"], + parent_id=parent_id, label=folder["label"], path=folder["path"], status=folder["status"], tags=folder["tags"], - entity_id=folder["id"], - parent_id=parent_id, - data=folder.get("data"), attribs=folder["ownAttrib"], - active=folder["active"], + data=folder.get("data"), thumbnail_id=folder["thumbnailId"], + active=folder["active"], + entity_id=folder["id"], created=False, entity_hub=entity_hub ) From 6d7002b39ae245aa1d4eb3b7b175f8e9ab0b8fbb Mon Sep 17 00:00:00 2001 From: Jakub Trllo <43494761+iLLiCiTiT@users.noreply.github.com> Date: Fri, 25 Oct 2024 17:56:48 +0200 Subject: [PATCH 09/33] better order of arguments for task entity --- ayon_api/entity_hub.py | 117 ++++++++++++++++++++++++++--------------- 1 file changed, 76 insertions(+), 41 deletions(-) diff --git a/ayon_api/entity_hub.py b/ayon_api/entity_hub.py index dcda65f3a..edd52612d 100644 --- a/ayon_api/entity_hub.py +++ b/ayon_api/entity_hub.py @@ -345,21 +345,39 @@ def add_new_folder( self.add_entity(folder_entity) return folder_entity - def add_new_task(self, *args, created=True, **kwargs): + def add_new_task( + self, + name: str, + task_type: str, + parent_id: Optional[str] = UNKNOWN_VALUE, + label: Optional[str] = None, + status: Optional[str] = UNKNOWN_VALUE, + tags: Optional[Iterable[str]] = None, + attribs: Optional[Dict[str, Any]] = UNKNOWN_VALUE, + data: Optional[Dict[str, Any]] = UNKNOWN_VALUE, + assignees: Optional[Iterable[str]] = None, + thumbnail_id: Optional[str] = UNKNOWN_VALUE, + active: Optional[bool] = UNKNOWN_VALUE, + entity_id: Optional[str] = None, + created: Optional[bool] = None, + ): """Create folder object and add it to entity hub. Args: - task_type (str): Type of task. Task type must be available in - config of project folder types. - entity_id (Optional[str]): Id of the entity. New id is created - if not passed. - parent_id (Optional[str]): Id of parent entity. name (str): Name of entity. - label (Optional[str]): Folder label. + task_type (str): Type of task. Task type must be available in config + of project task types. + parent_id (Union[str, None]): Id of parent entity. + label (Optional[str]): Task label. + status (Optional[str]): Task status. + tags (Optional[Iterable[str]]): Folder tags. attribs (Dict[str, Any]): Attribute values. data (Dict[str, Any]): Entity data (custom data). - thumbnail_id (Optional[str]): Id of entity's thumbnail. + assignees (Optional[Iterable[str]]): User assignees to the task. + thumbnail_id (Union[str, None]): Id of entity's thumbnail. active (bool): Is entity active. + entity_id (Union[str, None]): Id of the entity. New id is created if + not passed. created (Optional[bool]): Entity is new. When 'None' is passed the value is defined based on value of 'entity_id'. @@ -368,7 +386,20 @@ def add_new_task(self, *args, created=True, **kwargs): """ task_entity = TaskEntity( - *args, **kwargs, created=created, entity_hub=self + name=name, + task_type=task_type, + parent_id=parent_id, + label=label, + status=status, + tags=tags, + attribs=attribs, + data=data, + assignees=assignees, + thumbnail_id=thumbnail_id, + active=active, + entity_id=entity_id, + created=created, + entity_hub=self, ) self.add_entity(task_entity) return task_entity @@ -3029,19 +3060,22 @@ class TaskEntity(BaseEntity): name (str): Name of entity. task_type (str): Type of task. Task type must be available in config of project task types. - entity_id (Union[str, None]): Id of the entity. New id is created if - not passed. parent_id (Union[str, None]): Id of parent entity. label (Optional[str]): Task label. + status (Optional[str]): Task status. + tags (Optional[Iterable[str]]): Folder tags. attribs (Dict[str, Any]): Attribute values. data (Dict[str, Any]): Entity data (custom data). + assignees (Optional[Iterable[str]]): User assignees to the task. thumbnail_id (Union[str, None]): Id of entity's thumbnail. active (bool): Is entity active. - entity_hub (EntityHub): Object of entity hub which created object of - the entity. + entity_id (Union[str, None]): Id of the entity. New id is created if + not passed. created (Optional[bool]): Entity is new. When 'None' is passed the value is defined based on value of 'entity_id'. - status (Optional[str]): Task status. + entity_hub (EntityHub): Object of entity hub which created object of + the entity. + """ _supports_name = True _supports_label = True @@ -3053,34 +3087,34 @@ class TaskEntity(BaseEntity): def __init__( self, - task_type, - entity_id=None, - parent_id=UNKNOWN_VALUE, - name=UNKNOWN_VALUE, - attribs=UNKNOWN_VALUE, - data=UNKNOWN_VALUE, - thumbnail_id=UNKNOWN_VALUE, - active=UNKNOWN_VALUE, - entity_hub=None, - created=None, - label=None, - tags=None, - assignees=None, - status=UNKNOWN_VALUE, + name: str, + task_type: str, + parent_id: Optional[str] = UNKNOWN_VALUE, + label: Optional[str] = None, + status: Optional[str] = UNKNOWN_VALUE, + tags: Optional[Iterable[str]] = None, + attribs: Optional[Dict[str, Any]] = UNKNOWN_VALUE, + data: Optional[Dict[str, Any]] = UNKNOWN_VALUE, + assignees: Optional[Iterable[str]] = None, + thumbnail_id: Optional[str] = UNKNOWN_VALUE, + active: Optional[bool] = UNKNOWN_VALUE, + entity_id: Optional[str] = None, + created: Optional[bool] = None, + entity_hub: EntityHub = None, ): super().__init__( - entity_id=entity_id, + name=name, parent_id=parent_id, + label=label, + status=status, + tags=tags, attribs=attribs, data=data, + thumbnail_id=thumbnail_id, active=active, + entity_id=entity_id, created=created, entity_hub=entity_hub, - name=name, - label=label, - tags=tags, - status=status, - thumbnail_id=thumbnail_id, ) if assignees is None: assignees = [] @@ -3155,19 +3189,20 @@ def changes(self): return changes @classmethod - def from_entity_data(cls, task, entity_hub): + def from_entity_data(cls, task, entity_hub) -> "TaskEntity": return cls( - task["taskType"], - entity_id=task["id"], + name=task["name"], + task_type=task["taskType"], + parent_id=task["folderId"], label=task["label"], status=task["status"], tags=task["tags"], - assignees=task["assignees"], - parent_id=task["folderId"], - name=task["name"], - data=task.get("data"), attribs=task["ownAttrib"], + data=task.get("data"), + assignees=task["assignees"], + thumbnail_id=task["thumbnailId"], active=task["active"], + entity_id=task["id"], created=False, entity_hub=entity_hub ) From fdc27eb016a0181dbbb3630b294ccc74169e2930 Mon Sep 17 00:00:00 2001 From: Jakub Trllo <43494761+iLLiCiTiT@users.noreply.github.com> Date: Fri, 25 Oct 2024 17:56:57 +0200 Subject: [PATCH 10/33] removed unused variable --- ayon_api/entity_hub.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/ayon_api/entity_hub.py b/ayon_api/entity_hub.py index edd52612d..e437f6c6b 100644 --- a/ayon_api/entity_hub.py +++ b/ayon_api/entity_hub.py @@ -61,7 +61,7 @@ def __init__( ): if not connection: connection = get_server_api_connection() - major, minor, patch, _, _ = connection.server_version_tuple + major, minor, _, _, _ = connection.server_version_tuple path_start_with_slash = True if (major, minor) < (0, 6): path_start_with_slash = False From 1984157642e6d3e3885cacd3a8595f164afeb089 Mon Sep 17 00:00:00 2001 From: Jakub Trllo <43494761+iLLiCiTiT@users.noreply.github.com> Date: Fri, 25 Oct 2024 18:23:36 +0200 Subject: [PATCH 11/33] use folder_id instead of parent_id --- ayon_api/entity_hub.py | 22 ++++++++++++++++------ 1 file changed, 16 insertions(+), 6 deletions(-) diff --git a/ayon_api/entity_hub.py b/ayon_api/entity_hub.py index e437f6c6b..ab4b73b47 100644 --- a/ayon_api/entity_hub.py +++ b/ayon_api/entity_hub.py @@ -349,7 +349,7 @@ def add_new_task( self, name: str, task_type: str, - parent_id: Optional[str] = UNKNOWN_VALUE, + folder_id: Optional[str] = UNKNOWN_VALUE, label: Optional[str] = None, status: Optional[str] = UNKNOWN_VALUE, tags: Optional[Iterable[str]] = None, @@ -360,6 +360,7 @@ def add_new_task( active: Optional[bool] = UNKNOWN_VALUE, entity_id: Optional[str] = None, created: Optional[bool] = None, + parent_id: Optional[str] = UNKNOWN_VALUE, ): """Create folder object and add it to entity hub. @@ -367,7 +368,7 @@ def add_new_task( name (str): Name of entity. task_type (str): Type of task. Task type must be available in config of project task types. - parent_id (Union[str, None]): Id of parent entity. + folder_id (Union[str, None]): Parent folder id. label (Optional[str]): Task label. status (Optional[str]): Task status. tags (Optional[Iterable[str]]): Folder tags. @@ -380,15 +381,24 @@ def add_new_task( not passed. created (Optional[bool]): Entity is new. When 'None' is passed the value is defined based on value of 'entity_id'. + parent_id (Union[str, None]): DEPRECATED Parent folder id. Returns: TaskEntity: Added task entity. """ + if parent_id is not UNKNOWN_VALUE: + warnings.warn( + "Used deprecated argument 'parent_id'." + " Use 'folder_id' instead.", + DeprecationWarning + ) + folder_id = parent_id + task_entity = TaskEntity( name=name, task_type=task_type, - parent_id=parent_id, + folder_id=folder_id, label=label, status=status, tags=tags, @@ -3089,7 +3099,7 @@ def __init__( self, name: str, task_type: str, - parent_id: Optional[str] = UNKNOWN_VALUE, + folder_id: Optional[str] = UNKNOWN_VALUE, label: Optional[str] = None, status: Optional[str] = UNKNOWN_VALUE, tags: Optional[Iterable[str]] = None, @@ -3104,7 +3114,7 @@ def __init__( ): super().__init__( name=name, - parent_id=parent_id, + parent_id=folder_id, label=label, status=status, tags=tags, @@ -3193,7 +3203,7 @@ def from_entity_data(cls, task, entity_hub) -> "TaskEntity": return cls( name=task["name"], task_type=task["taskType"], - parent_id=task["folderId"], + folder_id=task["folderId"], label=task["label"], status=task["status"], tags=task["tags"], From ad1f62927a6860a24e1b9e117397c80f768ba82d Mon Sep 17 00:00:00 2001 From: Jakub Trllo <43494761+iLLiCiTiT@users.noreply.github.com> Date: Fri, 25 Oct 2024 18:23:46 +0200 Subject: [PATCH 12/33] don't add attribs to data automatically --- ayon_api/entity_hub.py | 1 - 1 file changed, 1 deletion(-) diff --git a/ayon_api/entity_hub.py b/ayon_api/entity_hub.py index ab4b73b47..b9e457536 100644 --- a/ayon_api/entity_hub.py +++ b/ayon_api/entity_hub.py @@ -3225,7 +3225,6 @@ def to_create_body_data(self): "name": self.name, "taskType": self.task_type, "folderId": self.parent_id, - "attrib": self.attribs.to_dict(), } label = self._get_label_value() if label: From 71496fbb2d2959b55ccdb29bce68ab1b94035716 Mon Sep 17 00:00:00 2001 From: Jakub Trllo <43494761+iLLiCiTiT@users.noreply.github.com> Date: Fri, 25 Oct 2024 18:23:58 +0200 Subject: [PATCH 13/33] added product and version entity --- ayon_api/entity_hub.py | 234 +++++++++++++++++++++++++++++++++++++++++ 1 file changed, 234 insertions(+) diff --git a/ayon_api/entity_hub.py b/ayon_api/entity_hub.py index b9e457536..248b4d58e 100644 --- a/ayon_api/entity_hub.py +++ b/ayon_api/entity_hub.py @@ -3254,3 +3254,237 @@ def to_create_body_data(self): return output +class ProductEntity(BaseEntity): + _supports_name = True + _supports_tags = True + + def __init__( + self, + name: str, + product_type: str, + folder_id: Optional[Union[str, _CustomNone]] = UNKNOWN_VALUE, + tags: Optional[Iterable[str]] = None, + attribs: Optional[Dict[str, Any]] = UNKNOWN_VALUE, + data: Optional[Dict[str, Any]] = UNKNOWN_VALUE, + active: Optional[bool] = UNKNOWN_VALUE, + entity_id: Optional[str] = None, + created: Optional[bool] = None, + entity_hub: EntityHub = None, + ): + super().__init__( + name=name, + parent_id=folder_id, + tags=tags, + attribs=attribs, + data=data, + created=created, + entity_id=entity_id, + active=active, + entity_hub=entity_hub, + ) + self._product_type = product_type + + self._orig_product_type = product_type + + def get_folder_id(self): + return self._parent_id + + def set_folder_id(self, folder_id): + self.set_parent_id(folder_id) + + folder_id = property(get_folder_id, set_folder_id) + + def get_product_type(self): + return self._product_type + + def set_product_type(self, product_type): + self._product_type = product_type + + product_type = property(get_product_type, set_product_type) + + def lock(self): + super().lock() + self._orig_product_type = self._product_type + + @property + def changes(self): + changes = self._get_default_changes() + + if self._orig_parent_id != self._parent_id: + changes["folderId"] = self._parent_id + + if self._orig_product_type != self._product_type: + changes["productType"] = self._product_type + + return changes + + @classmethod + def from_entity_data(cls, product, entity_hub): + return cls( + name=product["name"], + product_type=product["productType"], + folder_id=product["folderId"], + tags=product["tags"], + attribs=product["ownAttrib"], + data=product.get("data"), + active=product["active"], + entity_id=product["id"], + created=False, + entity_hub=entity_hub + ) + + def to_create_body_data(self): + if self.parent_id is UNKNOWN_VALUE: + raise ValueError("Product does not have set 'folder_id'") + + output = { + "name": self.name, + "productType": self.product_type, + "folderId": self.parent_id, + } + + attrib = self.attribs.to_dict() + if attrib: + output["attrib"] = attrib + + if self.active is not UNKNOWN_VALUE: + output["active"] = self.active + + if self.tags: + output["tags"] = self.tags + + if ( + self._entity_hub.allow_data_changes + and self._data is not UNKNOWN_VALUE + ): + output["data"] = self._data.get_new_entity_value() + return output + + +class VersionEntity(BaseEntity): + _supports_tags = True + _supports_status = True + _supports_thumbnail = True + + def __init__( + self, + version: int, + product_id: Optional[Union[str, _CustomNone]] = UNKNOWN_VALUE, + task_id: Optional[Union[str, _CustomNone]] = UNKNOWN_VALUE, + status: Optional[str] = UNKNOWN_VALUE, + tags: Optional[Iterable[str]] = None, + attribs: Optional[Dict[str, Any]] = UNKNOWN_VALUE, + data: Optional[Dict[str, Any]] = UNKNOWN_VALUE, + thumbnail_id: Optional[str] = UNKNOWN_VALUE, + active: Optional[bool] = UNKNOWN_VALUE, + entity_id: Optional[str] = None, + created: Optional[bool] = None, + entity_hub: EntityHub = None, + ): + super().__init__( + parent_id=product_id, + status=status, + tags=tags, + attribs=attribs, + data=data, + thumbnail_id=thumbnail_id, + active=active, + entity_id=entity_id, + created=created, + entity_hub=entity_hub, + ) + self._version = version + self._task_id = task_id + + self._orig_version = version + self._orig_task_id = task_id + + def get_version(self): + return self._version + + def set_version(self, version): + self._version = version + + version = property(get_version, set_version) + + def get_product_id(self): + return self._parent_id + + def set_product_id(self, product_id): + self.set_parent_id(product_id) + + product_id = property(get_product_id, set_product_id) + + def get_task_id(self): + return self._task_id + + def set_task_id(self, task_id): + self._task_id = task_id + + task_id = property(get_task_id, set_task_id) + + def lock(self): + super().lock() + self._orig_version = self._version + self._orig_task_id = self._task_id + + @property + def changes(self): + changes = self._get_default_changes() + + if self._orig_parent_id != self._parent_id: + changes["productId"] = self._parent_id + + if self._orig_task_id != self._task_id: + changes["taskId"] = self._task_id + + return changes + + @classmethod + def from_entity_data(cls, version, entity_hub): + return cls( + version=version["version"], + product_id=version["productId"], + task_id=version["taskId"], + status=version["status"], + tags=version["tags"], + attribs=version["ownAttrib"], + data=version.get("data"), + thumbnail_id=version["thumbnailId"], + active=version["active"], + entity_id=version["id"], + created=False, + entity_hub=entity_hub + ) + + def to_create_body_data(self): + if self.parent_id is UNKNOWN_VALUE: + raise ValueError("Version does not have set 'product_id'") + + output = { + "version": self.version, + "productId": self.parent_id, + } + task_id = self.task_id + if task_id: + output["taskId"] = task_id + + attrib = self.attribs.to_dict() + if attrib: + output["attrib"] = attrib + + if self.active is not UNKNOWN_VALUE: + output["active"] = self.active + + if self.tags: + output["tags"] = self.tags + + if self.status: + output["status"] = self.status + + if ( + self._entity_hub.allow_data_changes + and self._data is not UNKNOWN_VALUE + ): + output["data"] = self._data.get_new_entity_value() + return output From 82c8835301ce5235f7a7fc5f28ae536dd43d5e98 Mon Sep 17 00:00:00 2001 From: Jakub Trllo <43494761+iLLiCiTiT@users.noreply.github.com> Date: Fri, 25 Oct 2024 18:25:13 +0200 Subject: [PATCH 14/33] implement remaining abstract properties --- ayon_api/entity_hub.py | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/ayon_api/entity_hub.py b/ayon_api/entity_hub.py index 248b4d58e..ca08722a0 100644 --- a/ayon_api/entity_hub.py +++ b/ayon_api/entity_hub.py @@ -3258,6 +3258,9 @@ class ProductEntity(BaseEntity): _supports_name = True _supports_tags = True + entity_type = "product" + parent_entity_types = ["folder"] + def __init__( self, name: str, @@ -3366,6 +3369,9 @@ class VersionEntity(BaseEntity): _supports_status = True _supports_thumbnail = True + entity_type = "version" + parent_entity_types = ["product"] + def __init__( self, version: int, From b4fc406adcbfab8cd4088f7b806bc2b78121f29c Mon Sep 17 00:00:00 2001 From: Jakub Trllo <43494761+iLLiCiTiT@users.noreply.github.com> Date: Fri, 25 Oct 2024 18:38:12 +0200 Subject: [PATCH 15/33] added few helper functions to get entities --- ayon_api/entity_hub.py | 69 ++++++++++++++++++++++++++++++++++++++++-- 1 file changed, 67 insertions(+), 2 deletions(-) diff --git a/ayon_api/entity_hub.py b/ayon_api/entity_hub.py index ca08722a0..52c36478c 100644 --- a/ayon_api/entity_hub.py +++ b/ayon_api/entity_hub.py @@ -171,7 +171,7 @@ def get_folder_by_id( Args: entity_id (str): Folder entity id. - allow_fetch (bool): Try to query entity from server if is not + allow_fetch (bool): Try to fetch entity from server if is not available in cache. Returns: @@ -191,7 +191,7 @@ def get_task_by_id( Args: entity_id (str): Id of task entity. - allow_fetch (bool): Try to query entity from server if is not + allow_fetch (bool): Try to fetch entity from server if is not available in cache. Returns: @@ -201,6 +201,47 @@ def get_task_by_id( if allow_fetch: return self.get_or_fetch_entity_by_id(entity_id, ["task"]) return self._entities_by_id.get(entity_id) + + def get_product_by_id( + self, + entity_id: str, + allow_fetch: Optional[bool] = True, + ) -> Optional["ProductEntity"]: + """Get product entity by id. + + Args: + entity_id (str): Product id. + allow_fetch (bool): Try to fetch entity from server if is not + available in cache. + + Returns: + Optional[ProductEntity]: Product entity object or None. + + """ + if allow_fetch: + return self.get_or_fetch_entity_by_id(entity_id, ["product"]) + return self._entities_by_id.get(entity_id) + + def get_version_by_id( + self, + entity_id: str, + allow_fetch: Optional[bool] = True, + ) -> Optional["VersionEntity"]: + """Get version entity by id. + + Args: + entity_id (str): Version id. + allow_fetch (bool): Try to fetch entity from server if is not + available in cache. + + Returns: + Optional[VersionEntity]: Version entity object or None. + + """ + if allow_fetch: + return self.get_or_fetch_entity_by_id(entity_id, ["version"]) + return self._entities_by_id.get(entity_id) + def get_or_fetch_entity_by_id( self, entity_id: str, @@ -241,6 +282,20 @@ def get_or_fetch_entity_by_id( fields=self._get_task_fields(), own_attributes=True ) + elif entity_type == "product": + entity_data = self._connection.get_product_by_id( + self.project_name, + entity_id, + fields=self._get_product_fields(), + own_attributes=True + ) + elif entity_type == "version": + entity_data = self._connection.get_version_by_id( + self.project_name, + entity_id, + fields=self._get_version_fields(), + own_attributes=True + ) else: raise ValueError( "Unknonwn entity type \"{}\"".format(entity_type) @@ -714,6 +769,16 @@ def _get_task_fields(self) -> Set[str]: self._connection.get_default_fields_for_type("task") ) + def _get_product_fields(self) -> Set[str]: + return set( + self._connection.get_default_fields_for_type("product") + ) + + def _get_version_fields(self) -> Set[str]: + return set( + self._connection.get_default_fields_for_type("version") + ) + def fetch_hierarchy_entities(self): """Query whole project at once.""" project_entity = self.fill_project_from_server() From ee1e01ea6165b72743079fb94949494dd9cd8727 Mon Sep 17 00:00:00 2001 From: Jakub Trllo <43494761+iLLiCiTiT@users.noreply.github.com> Date: Mon, 28 Oct 2024 16:07:27 +0100 Subject: [PATCH 16/33] fix ownAttrib on version --- ayon_api/entity_hub.py | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/ayon_api/entity_hub.py b/ayon_api/entity_hub.py index 52c36478c..d6bd9099a 100644 --- a/ayon_api/entity_hub.py +++ b/ayon_api/entity_hub.py @@ -294,7 +294,6 @@ def get_or_fetch_entity_by_id( self.project_name, entity_id, fields=self._get_version_fields(), - own_attributes=True ) else: raise ValueError( @@ -3519,7 +3518,7 @@ def from_entity_data(cls, version, entity_hub): task_id=version["taskId"], status=version["status"], tags=version["tags"], - attribs=version["ownAttrib"], + attribs=version["attrib"], data=version.get("data"), thumbnail_id=version["thumbnailId"], active=version["active"], From de8a1fb6405bb01140236343418126c6f380bca1 Mon Sep 17 00:00:00 2001 From: Jakub Trllo <43494761+iLLiCiTiT@users.noreply.github.com> Date: Mon, 28 Oct 2024 16:07:54 +0100 Subject: [PATCH 17/33] avoid crashes for entities without thumbnail id --- ayon_api/entity_hub.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/ayon_api/entity_hub.py b/ayon_api/entity_hub.py index d6bd9099a..c8b08fb2e 100644 --- a/ayon_api/entity_hub.py +++ b/ayon_api/entity_hub.py @@ -1618,7 +1618,7 @@ def lock(self): """Lock entity as 'saved' so all changes are discarded.""" self._orig_parent_id = self._parent_id self._orig_name = self._name - self._orig_thumbnail_id = self.thumbnail_id + self._orig_thumbnail_id = self._thumbnail_id if isinstance(self._data, EntityData): self._data.lock() self._attribs.lock() From f174b3e19020c6f9c33a56ef26b11fd52aecde09 Mon Sep 17 00:00:00 2001 From: Jakub Trllo <43494761+iLLiCiTiT@users.noreply.github.com> Date: Mon, 28 Oct 2024 16:08:15 +0100 Subject: [PATCH 18/33] fix docstring --- ayon_api/entity_hub.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/ayon_api/entity_hub.py b/ayon_api/entity_hub.py index c8b08fb2e..9ef6ad870 100644 --- a/ayon_api/entity_hub.py +++ b/ayon_api/entity_hub.py @@ -416,7 +416,7 @@ def add_new_task( created: Optional[bool] = None, parent_id: Optional[str] = UNKNOWN_VALUE, ): - """Create folder object and add it to entity hub. + """Create task object and add it to entity hub. Args: name (str): Name of entity. From 7c55604e4aa3395ffe9a430d15c70e6b90f5474e Mon Sep 17 00:00:00 2001 From: Jakub Trllo <43494761+iLLiCiTiT@users.noreply.github.com> Date: Mon, 28 Oct 2024 16:08:25 +0100 Subject: [PATCH 19/33] fix typehint --- ayon_api/entity_hub.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/ayon_api/entity_hub.py b/ayon_api/entity_hub.py index 9ef6ad870..10075f9d1 100644 --- a/ayon_api/entity_hub.py +++ b/ayon_api/entity_hub.py @@ -1893,7 +1893,7 @@ def set_thumbnail_id(self, thumbnail_id): thumbnail_id = property(get_thumbnail_id, set_thumbnail_id) - def get_status(self) -> Union[str, UNKNOWN_VALUE]: + def get_status(self) -> Union[str, _CustomNone]: """Folder status. Returns: From 6b48b9c9e7b5ae98cbc17b097fbf793b97a977ad Mon Sep 17 00:00:00 2001 From: Jakub Trllo <43494761+iLLiCiTiT@users.noreply.github.com> Date: Mon, 28 Oct 2024 16:10:13 +0100 Subject: [PATCH 20/33] added option to get product and version entities --- ayon_api/entity_hub.py | 34 ++++++++++++++++++++++++++++++++++ 1 file changed, 34 insertions(+) diff --git a/ayon_api/entity_hub.py b/ayon_api/entity_hub.py index 10075f9d1..010861fe8 100644 --- a/ayon_api/entity_hub.py +++ b/ayon_api/entity_hub.py @@ -314,6 +314,12 @@ def get_or_fetch_entity_by_id( elif entity_type == "task": return self.add_task(entity_data) + elif entity_type == "product": + return self.add_product(entity_data) + + elif entity_type == "version": + return self.add_version(entity_data) + return None def get_or_query_entity_by_id( @@ -496,6 +502,34 @@ def add_task(self, task): self.add_entity(task_entity) return task_entity + def add_product(self, product): + """Create version object and add it to entity hub. + + Args: + product (Dict[str, Any]): Version entity data. + + Returns: + ProductEntity: Added version entity. + + """ + product_entity = ProductEntity.from_entity_data(product, entity_hub=self) + self.add_entity(product_entity) + return product_entity + + def add_version(self, version): + """Create version object and add it to entity hub. + + Args: + version (Dict[str, Any]): Version entity data. + + Returns: + VersionEntity: Added version entity. + + """ + version_entity = VersionEntity.from_entity_data(version, entity_hub=self) + self.add_entity(version_entity) + return version_entity + def add_entity(self, entity): """Add entity to hub cache. From 8a56ed6cb421c386feee4318192282092392af8f Mon Sep 17 00:00:00 2001 From: Jakub Trllo <43494761+iLLiCiTiT@users.noreply.github.com> Date: Mon, 28 Oct 2024 16:10:28 +0100 Subject: [PATCH 21/33] added option to create new entities --- ayon_api/entity_hub.py | 98 ++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 98 insertions(+) diff --git a/ayon_api/entity_hub.py b/ayon_api/entity_hub.py index 010861fe8..dedb13929 100644 --- a/ayon_api/entity_hub.py +++ b/ayon_api/entity_hub.py @@ -474,6 +474,104 @@ def add_new_task( self.add_entity(task_entity) return task_entity + def add_new_product( + self, + name: str, + product_type: str, + folder_id: Optional[Union[str, _CustomNone]] = UNKNOWN_VALUE, + tags: Optional[Iterable[str]] = None, + attribs: Optional[Dict[str, Any]] = UNKNOWN_VALUE, + data: Optional[Dict[str, Any]] = UNKNOWN_VALUE, + active: Optional[bool] = UNKNOWN_VALUE, + entity_id: Optional[str] = None, + created: Optional[bool] = None, + ): + """Create task object and add it to entity hub. + + Args: + name (str): Name of entity. + product_type (str): Type of product. + folder_id (Union[str, None]): Parent folder id. + tags (Optional[Iterable[str]]): Folder tags. + attribs (Dict[str, Any]): Attribute values. + data (Dict[str, Any]): Entity data (custom data). + active (bool): Is entity active. + entity_id (Union[str, None]): Id of the entity. New id is created if + not passed. + created (Optional[bool]): Entity is new. When 'None' is passed the + value is defined based on value of 'entity_id'. + + Returns: + ProductEntity: Added product entity. + + """ + product_entity = ProductEntity( + name=name, + product_type=product_type, + folder_id=folder_id, + tags=tags, + attribs=attribs, + data=data, + active=active, + entity_id=entity_id, + created=created, + entity_hub=self, + ) + self.add_entity(product_entity) + return product_entity + + def add_new_version( + self, + version: int, + product_id: Optional[Union[str, _CustomNone]] = UNKNOWN_VALUE, + task_id: Optional[Union[str, _CustomNone]] = UNKNOWN_VALUE, + status: Optional[str] = UNKNOWN_VALUE, + tags: Optional[Iterable[str]] = None, + attribs: Optional[Dict[str, Any]] = UNKNOWN_VALUE, + data: Optional[Dict[str, Any]] = UNKNOWN_VALUE, + thumbnail_id: Optional[str] = UNKNOWN_VALUE, + active: Optional[bool] = UNKNOWN_VALUE, + entity_id: Optional[str] = None, + created: Optional[bool] = None, + ): + """Create task object and add it to entity hub. + + Args: + version (int): Version. + product_id (Union[str, None]): Parent product id. + task_id (Union[str, None]): Parent task id. + status (Optional[str]): Task status. + tags (Optional[Iterable[str]]): Folder tags. + attribs (Dict[str, Any]): Attribute values. + data (Dict[str, Any]): Entity data (custom data). + thumbnail_id (Union[str, None]): Id of entity's thumbnail. + active (bool): Is entity active. + entity_id (Union[str, None]): Id of the entity. New id is created if + not passed. + created (Optional[bool]): Entity is new. When 'None' is passed the + value is defined based on value of 'entity_id'. + + Returns: + VersionEntity: Added version entity. + + """ + version_entity = VersionEntity( + version=version, + product_id=product_id, + task_id=task_id, + status=status, + tags=tags, + attribs=attribs, + data=data, + thumbnail_id=thumbnail_id, + active=active, + entity_id=entity_id, + created=created, + entity_hub=self, + ) + self.add_entity(version_entity) + return version_entity + def add_folder(self, folder): """Create folder object and add it to entity hub. From abfcb2ce116135db23741967a70711acc814e8ac Mon Sep 17 00:00:00 2001 From: Jakub Trllo <43494761+iLLiCiTiT@users.noreply.github.com> Date: Mon, 28 Oct 2024 16:10:39 +0100 Subject: [PATCH 22/33] updated typehint literal --- ayon_api/entity_hub.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/ayon_api/entity_hub.py b/ayon_api/entity_hub.py index dedb13929..ad02a313a 100644 --- a/ayon_api/entity_hub.py +++ b/ayon_api/entity_hub.py @@ -13,7 +13,7 @@ from typing import Literal StatusState = Literal["not_started", "in_progress", "done", "blocked"] - EntityType = Literal["project", "folder", "task"] + EntityType = Literal["project", "folder", "task", "product", "version"] class _CustomNone(object): From 76b243f8d12589899cbf59e32e5c129fa759f78e Mon Sep 17 00:00:00 2001 From: Jakub Trllo <43494761+iLLiCiTiT@users.noreply.github.com> Date: Mon, 28 Oct 2024 16:13:00 +0100 Subject: [PATCH 23/33] Union is imported only for typehints --- ayon_api/entity_hub.py | 20 ++++++++++---------- 1 file changed, 10 insertions(+), 10 deletions(-) diff --git a/ayon_api/entity_hub.py b/ayon_api/entity_hub.py index ad02a313a..07795c22f 100644 --- a/ayon_api/entity_hub.py +++ b/ayon_api/entity_hub.py @@ -4,13 +4,13 @@ import warnings from abc import ABC, abstractmethod import typing -from typing import Optional, Union, Iterable, Dict, List, Set, Any +from typing import Optional, Iterable, Dict, List, Set, Any from ._api import get_server_api_connection from .utils import create_entity_id, convert_entity_id, slugify_string if typing.TYPE_CHECKING: - from typing import Literal + from typing import Literal, Union StatusState = Literal["not_started", "in_progress", "done", "blocked"] EntityType = Literal["project", "folder", "task", "product", "version"] @@ -478,7 +478,7 @@ def add_new_product( self, name: str, product_type: str, - folder_id: Optional[Union[str, _CustomNone]] = UNKNOWN_VALUE, + folder_id: Optional["Union[str, _CustomNone]"] = UNKNOWN_VALUE, tags: Optional[Iterable[str]] = None, attribs: Optional[Dict[str, Any]] = UNKNOWN_VALUE, data: Optional[Dict[str, Any]] = UNKNOWN_VALUE, @@ -523,8 +523,8 @@ def add_new_product( def add_new_version( self, version: int, - product_id: Optional[Union[str, _CustomNone]] = UNKNOWN_VALUE, - task_id: Optional[Union[str, _CustomNone]] = UNKNOWN_VALUE, + product_id: Optional["Union[str, _CustomNone]"] = UNKNOWN_VALUE, + task_id: Optional["Union[str, _CustomNone]"] = UNKNOWN_VALUE, status: Optional[str] = UNKNOWN_VALUE, tags: Optional[Iterable[str]] = None, attribs: Optional[Dict[str, Any]] = UNKNOWN_VALUE, @@ -1440,7 +1440,7 @@ class BaseEntity(ABC): def __init__( self, entity_id: Optional[str] = None, - parent_id: Optional[Union[str, _CustomNone]] = UNKNOWN_VALUE, + parent_id: Optional["Union[str, _CustomNone]"] = UNKNOWN_VALUE, attribs: Optional[Dict[str, Any]] = UNKNOWN_VALUE, data: Optional[Dict[str, Any]] = UNKNOWN_VALUE, active: Optional[bool] = UNKNOWN_VALUE, @@ -2025,7 +2025,7 @@ def set_thumbnail_id(self, thumbnail_id): thumbnail_id = property(get_thumbnail_id, set_thumbnail_id) - def get_status(self) -> Union[str, _CustomNone]: + def get_status(self) -> "Union[str, _CustomNone]": """Folder status. Returns: @@ -3461,7 +3461,7 @@ def __init__( self, name: str, product_type: str, - folder_id: Optional[Union[str, _CustomNone]] = UNKNOWN_VALUE, + folder_id: Optional["Union[str, _CustomNone]"] = UNKNOWN_VALUE, tags: Optional[Iterable[str]] = None, attribs: Optional[Dict[str, Any]] = UNKNOWN_VALUE, data: Optional[Dict[str, Any]] = UNKNOWN_VALUE, @@ -3571,8 +3571,8 @@ class VersionEntity(BaseEntity): def __init__( self, version: int, - product_id: Optional[Union[str, _CustomNone]] = UNKNOWN_VALUE, - task_id: Optional[Union[str, _CustomNone]] = UNKNOWN_VALUE, + product_id: Optional["Union[str, _CustomNone]"] = UNKNOWN_VALUE, + task_id: Optional["Union[str, _CustomNone]"] = UNKNOWN_VALUE, status: Optional[str] = UNKNOWN_VALUE, tags: Optional[Iterable[str]] = None, attribs: Optional[Dict[str, Any]] = UNKNOWN_VALUE, From 8a52679afa2ccafe405173a98d66e8757ca32d71 Mon Sep 17 00:00:00 2001 From: Jakub Trllo <43494761+iLLiCiTiT@users.noreply.github.com> Date: Mon, 28 Oct 2024 16:19:13 +0100 Subject: [PATCH 24/33] fix typo --- ayon_api/entity_hub.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/ayon_api/entity_hub.py b/ayon_api/entity_hub.py index 07795c22f..48d5d06e5 100644 --- a/ayon_api/entity_hub.py +++ b/ayon_api/entity_hub.py @@ -297,7 +297,7 @@ def get_or_fetch_entity_by_id( ) else: raise ValueError( - "Unknonwn entity type \"{}\"".format(entity_type) + "Unknown entity type \"{}\"".format(entity_type) ) if entity_data: From 80bdd7174aeccd67f32ab173b48043b77310bf5b Mon Sep 17 00:00:00 2001 From: Jakub Trllo <43494761+iLLiCiTiT@users.noreply.github.com> Date: Mon, 28 Oct 2024 18:07:10 +0100 Subject: [PATCH 25/33] keep folder and task type as first in arguments --- ayon_api/entity_hub.py | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/ayon_api/entity_hub.py b/ayon_api/entity_hub.py index 48d5d06e5..00a73082c 100644 --- a/ayon_api/entity_hub.py +++ b/ayon_api/entity_hub.py @@ -347,8 +347,10 @@ def entities(self): def add_new_folder( self, - name: str, + # TODO move 'folder_type' after 'name' + # - that will break backwards compatibility folder_type: str, + name: str, parent_id: Optional[str] = UNKNOWN_VALUE, label: Optional[str] = None, path: Optional[str] = None, @@ -407,8 +409,10 @@ def add_new_folder( def add_new_task( self, - name: str, + # TODO move 'folder_type' after 'name' + # - that will break backwards compatibility task_type: str, + name: str, folder_id: Optional[str] = UNKNOWN_VALUE, label: Optional[str] = None, status: Optional[str] = UNKNOWN_VALUE, From 61227c6db34b5ab29cb04a748e47db590dad41b8 Mon Sep 17 00:00:00 2001 From: Jakub Trllo <43494761+iLLiCiTiT@users.noreply.github.com> Date: Mon, 28 Oct 2024 18:13:33 +0100 Subject: [PATCH 26/33] fix linting issues --- ayon_api/entity_hub.py | 20 ++++++++++++-------- 1 file changed, 12 insertions(+), 8 deletions(-) diff --git a/ayon_api/entity_hub.py b/ayon_api/entity_hub.py index 00a73082c..751282227 100644 --- a/ayon_api/entity_hub.py +++ b/ayon_api/entity_hub.py @@ -379,7 +379,7 @@ def add_new_folder( data (Dict[str, Any]): Entity data (custom data). thumbnail_id (Union[str, None]): Id of entity's thumbnail. active (bool): Is entity active. - entity_id (Union[str, None]): Id of the entity. New id is created if + entity_id (Optional[str]): Id of the entity. New id is created if not passed. created (Optional[bool]): Entity is new. When 'None' is passed the value is defined based on value of 'entity_id'. @@ -430,8 +430,8 @@ def add_new_task( Args: name (str): Name of entity. - task_type (str): Type of task. Task type must be available in config - of project task types. + task_type (str): Type of task. Task type must be available in + config of project task types. folder_id (Union[str, None]): Parent folder id. label (Optional[str]): Task label. status (Optional[str]): Task status. @@ -441,7 +441,7 @@ def add_new_task( assignees (Optional[Iterable[str]]): User assignees to the task. thumbnail_id (Union[str, None]): Id of entity's thumbnail. active (bool): Is entity active. - entity_id (Union[str, None]): Id of the entity. New id is created if + entity_id (Optional[str]): Id of the entity. New id is created if not passed. created (Optional[bool]): Entity is new. When 'None' is passed the value is defined based on value of 'entity_id'. @@ -500,7 +500,7 @@ def add_new_product( attribs (Dict[str, Any]): Attribute values. data (Dict[str, Any]): Entity data (custom data). active (bool): Is entity active. - entity_id (Union[str, None]): Id of the entity. New id is created if + entity_id (Optional[str]): Id of the entity. New id is created if not passed. created (Optional[bool]): Entity is new. When 'None' is passed the value is defined based on value of 'entity_id'. @@ -550,7 +550,7 @@ def add_new_version( data (Dict[str, Any]): Entity data (custom data). thumbnail_id (Union[str, None]): Id of entity's thumbnail. active (bool): Is entity active. - entity_id (Union[str, None]): Id of the entity. New id is created if + entity_id (Optional[str]): Id of the entity. New id is created if not passed. created (Optional[bool]): Entity is new. When 'None' is passed the value is defined based on value of 'entity_id'. @@ -614,7 +614,9 @@ def add_product(self, product): ProductEntity: Added version entity. """ - product_entity = ProductEntity.from_entity_data(product, entity_hub=self) + product_entity = ProductEntity.from_entity_data( + product, entity_hub=self + ) self.add_entity(product_entity) return product_entity @@ -628,7 +630,9 @@ def add_version(self, version): VersionEntity: Added version entity. """ - version_entity = VersionEntity.from_entity_data(version, entity_hub=self) + version_entity = VersionEntity.from_entity_data( + version, entity_hub=self + ) self.add_entity(version_entity) return version_entity From ccaa28974288cf70092c9918d5026598b01b9e58 Mon Sep 17 00:00:00 2001 From: Jakub Trllo <43494761+iLLiCiTiT@users.noreply.github.com> Date: Mon, 28 Oct 2024 18:20:58 +0100 Subject: [PATCH 27/33] updated some docstrings --- ayon_api/entity_hub.py | 14 ++++++++------ 1 file changed, 8 insertions(+), 6 deletions(-) diff --git a/ayon_api/entity_hub.py b/ayon_api/entity_hub.py index 751282227..f0a01ef9e 100644 --- a/ayon_api/entity_hub.py +++ b/ayon_api/entity_hub.py @@ -43,14 +43,14 @@ class EntityHub(object): frequently. Todos: - Listen to server events about entity changes to be able update already - queried entities. + Listen to server events about entity changes to be able to update + already queried entities. Args: project_name (str): Name of project where changes will happen. connection (ServerAPI): Connection to server with logged user. allow_data_changes (bool): This option gives ability to change 'data' - key on entities. This is not recommended as 'data' may be use for + key on entities. This is not recommended as 'data' may be used for secure information and would also slow down server queries. Content of 'data' key can't be received only GraphQl. @@ -85,9 +85,11 @@ def __init__( def allow_data_changes(self): """Entity hub allows changes of 'data' key on entities. - Data are private and not all users may have access to them. Also to get - 'data' for entity is required to use REST api calls, which means to - query each entity on-by-one from server. + Data are private and not all users may have access to them. + + Older version of AYON server allowed to get 'data' for entity only + using REST api calls, which means to query each entity on-by-one + from server. Returns: bool: Data changes are allowed. From 7d4647c7be40cc554313f26049dcbc52b05a15ea Mon Sep 17 00:00:00 2001 From: Jakub Trllo <43494761+iLLiCiTiT@users.noreply.github.com> Date: Thu, 21 Nov 2024 17:32:16 +0100 Subject: [PATCH 28/33] fix ownAttrib for product --- ayon_api/entity_hub.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/ayon_api/entity_hub.py b/ayon_api/entity_hub.py index f0a01ef9e..857ed536f 100644 --- a/ayon_api/entity_hub.py +++ b/ayon_api/entity_hub.py @@ -3534,7 +3534,7 @@ def from_entity_data(cls, product, entity_hub): product_type=product["productType"], folder_id=product["folderId"], tags=product["tags"], - attribs=product["ownAttrib"], + attribs=product["attrib"], data=product.get("data"), active=product["active"], entity_id=product["id"], From 8d4d524a0060acf8950f9b57589ad051e5318eab Mon Sep 17 00:00:00 2001 From: Jakub Trllo <43494761+iLLiCiTiT@users.noreply.github.com> Date: Thu, 21 Nov 2024 17:33:18 +0100 Subject: [PATCH 29/33] removed 'own_attributes' from products getter --- ayon_api/entity_hub.py | 1 - 1 file changed, 1 deletion(-) diff --git a/ayon_api/entity_hub.py b/ayon_api/entity_hub.py index 857ed536f..7f366f2aa 100644 --- a/ayon_api/entity_hub.py +++ b/ayon_api/entity_hub.py @@ -289,7 +289,6 @@ def get_or_fetch_entity_by_id( self.project_name, entity_id, fields=self._get_product_fields(), - own_attributes=True ) elif entity_type == "version": entity_data = self._connection.get_version_by_id( From 7db794957593d9ed787c20fadb5d7c6fafbdddd0 Mon Sep 17 00:00:00 2001 From: Jakub Trllo <43494761+iLLiCiTiT@users.noreply.github.com> Date: Thu, 21 Nov 2024 17:33:47 +0100 Subject: [PATCH 30/33] swap arguments order --- ayon_api/entity_hub.py | 8 ++------ 1 file changed, 2 insertions(+), 6 deletions(-) diff --git a/ayon_api/entity_hub.py b/ayon_api/entity_hub.py index 7f366f2aa..c805546c9 100644 --- a/ayon_api/entity_hub.py +++ b/ayon_api/entity_hub.py @@ -348,10 +348,8 @@ def entities(self): def add_new_folder( self, - # TODO move 'folder_type' after 'name' - # - that will break backwards compatibility - folder_type: str, name: str, + folder_type: str, parent_id: Optional[str] = UNKNOWN_VALUE, label: Optional[str] = None, path: Optional[str] = None, @@ -410,10 +408,8 @@ def add_new_folder( def add_new_task( self, - # TODO move 'folder_type' after 'name' - # - that will break backwards compatibility - task_type: str, name: str, + task_type: str, folder_id: Optional[str] = UNKNOWN_VALUE, label: Optional[str] = None, status: Optional[str] = UNKNOWN_VALUE, From f25ef18058e463216c1b1f5496ac8a867a6e705d Mon Sep 17 00:00:00 2001 From: Jakub Trllo <43494761+iLLiCiTiT@users.noreply.github.com> Date: Fri, 22 Nov 2024 13:51:02 +0100 Subject: [PATCH 31/33] use correct default values for created --- ayon_api/entity_hub.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/ayon_api/entity_hub.py b/ayon_api/entity_hub.py index c805546c9..27f5e3ee0 100644 --- a/ayon_api/entity_hub.py +++ b/ayon_api/entity_hub.py @@ -360,7 +360,7 @@ def add_new_folder( thumbnail_id: Optional[str] = UNKNOWN_VALUE, active: bool = UNKNOWN_VALUE, entity_id: Optional[str] = None, - created: Optional[bool] = None, + created: Optional[bool] = True, ): """Create folder object and add it to entity hub. @@ -420,7 +420,7 @@ def add_new_task( thumbnail_id: Optional[str] = UNKNOWN_VALUE, active: Optional[bool] = UNKNOWN_VALUE, entity_id: Optional[str] = None, - created: Optional[bool] = None, + created: Optional[bool] = True, parent_id: Optional[str] = UNKNOWN_VALUE, ): """Create task object and add it to entity hub. From 59b1e14526151e6b5eff038d57ef8e1cb1f77a5b Mon Sep 17 00:00:00 2001 From: Jakub Trllo <43494761+iLLiCiTiT@users.noreply.github.com> Date: Fri, 22 Nov 2024 13:53:38 +0100 Subject: [PATCH 32/33] fix creted for product and version --- ayon_api/entity_hub.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/ayon_api/entity_hub.py b/ayon_api/entity_hub.py index 27f5e3ee0..e9a5197f5 100644 --- a/ayon_api/entity_hub.py +++ b/ayon_api/entity_hub.py @@ -485,7 +485,7 @@ def add_new_product( data: Optional[Dict[str, Any]] = UNKNOWN_VALUE, active: Optional[bool] = UNKNOWN_VALUE, entity_id: Optional[str] = None, - created: Optional[bool] = None, + created: Optional[bool] = True, ): """Create task object and add it to entity hub. @@ -533,7 +533,7 @@ def add_new_version( thumbnail_id: Optional[str] = UNKNOWN_VALUE, active: Optional[bool] = UNKNOWN_VALUE, entity_id: Optional[str] = None, - created: Optional[bool] = None, + created: Optional[bool] = True, ): """Create task object and add it to entity hub. From 55bdf37789bd1fb05ca718448a6fcde64b7f83cc Mon Sep 17 00:00:00 2001 From: Jakub Trllo <43494761+iLLiCiTiT@users.noreply.github.com> Date: Fri, 22 Nov 2024 13:59:58 +0100 Subject: [PATCH 33/33] add thumbnail id to task fields --- ayon_api/constants.py | 1 + 1 file changed, 1 insertion(+) diff --git a/ayon_api/constants.py b/ayon_api/constants.py index 594155706..346620c77 100644 --- a/ayon_api/constants.py +++ b/ayon_api/constants.py @@ -84,6 +84,7 @@ "taskType", "folderId", "active", + "thumbnailId", "assignees", "data", "status",