From b7687ed4e6b7b970ebd91da91c06c5d22f1cfa59 Mon Sep 17 00:00:00 2001 From: farrizabalaga Date: Tue, 4 Jun 2024 23:54:15 +0200 Subject: [PATCH 1/7] Initial support to update versions through entity hub --- ayon_api/entity_hub.py | 22 ++++++++++++++++++++-- 1 file changed, 20 insertions(+), 2 deletions(-) diff --git a/ayon_api/entity_hub.py b/ayon_api/entity_hub.py index e3d936956..4630aa37e 100644 --- a/ayon_api/entity_hub.py +++ b/ayon_api/entity_hub.py @@ -222,9 +222,18 @@ def get_or_query_entity_by_id(self, entity_id, entity_types): fields=self._get_task_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=False + # setting it to True errors out with + # GraphQl query Failed: Cannot query field 'ownAttrib' on type 'VersionNode'. Did you mean 'attrib'? + ) else: raise ValueError( - "Unknonwn entity type \"{}\"".format(entity_type) + "Unknown entity type \"{}\"".format(entity_type) ) if entity_data: @@ -241,6 +250,10 @@ def get_or_query_entity_by_id(self, entity_id, entity_types): elif entity_type == "task": return self.add_task(entity_data) + # TODO: ? + # elif entity_type == "version": + # return self.add_version(entity_data) + return None @property @@ -611,7 +624,12 @@ def _get_task_fields(self): return set( self._connection.get_default_fields_for_type("task") ) - + + def _get_version_fields(self): + return set( + self._connection.get_default_fields_for_type("version") + ) + def query_entities_from_server(self): """Query whole project at once.""" project_entity = self.fill_project_from_server() From 7c90f0b34a554978c340c7f93ea7e32a09a9f27a Mon Sep 17 00:00:00 2001 From: farrizabalaga Date: Tue, 4 Jun 2024 23:57:01 +0200 Subject: [PATCH 2/7] Remove changes from feature/task_assignees branch --- ayon_api/entity_hub.py | 36 ------------------------------------ 1 file changed, 36 deletions(-) diff --git a/ayon_api/entity_hub.py b/ayon_api/entity_hub.py index 4630aa37e..4641b6c7c 100644 --- a/ayon_api/entity_hub.py +++ b/ayon_api/entity_hub.py @@ -2811,7 +2811,6 @@ def __init__( *args, label=None, tags=None, - assignees=None, status=UNKNOWN_VALUE, **kwargs ): @@ -2821,23 +2820,16 @@ def __init__( 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() @@ -2847,7 +2839,6 @@ def lock(self): 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 @@ -2911,26 +2902,6 @@ def set_tags(self, tags): tags = property(get_tags, set_tags) - def get_assignees(self): - """Folder assignees. - - Returns: - list[str]: Folder assignees. - - """ - return self._assignees - - def set_assignees(self, assignees): - """Change assignees. - - Args: - assignees (Iterable[str]): assignees. - - """ - self._assignees = list(assignees) - - assignees = property(get_assignees, set_assignees) - def add_child(self, child): raise ValueError("Task does not support to add children") @@ -2950,9 +2921,6 @@ def changes(self): 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 @@ -2967,7 +2935,6 @@ def from_entity_data(cls, task, entity_hub): label=task["label"], status=task["status"], tags=task["tags"], - assignees=task["assignees"], parent_id=task["folderId"], name=task["name"], data=task.get("data"), @@ -3004,9 +2971,6 @@ def to_create_body_data(self): if self.tags: output["tags"] = self.tags - if self.assignees: - output["assignees"] = self.assignees - if ( self._entity_hub.allow_data_changes and self._data is not UNKNOWN_VALUE From 7e7ae670aae5c5434879725c0d210d1693eed3cc Mon Sep 17 00:00:00 2001 From: farrizabalaga Date: Wed, 5 Jun 2024 19:47:05 +0200 Subject: [PATCH 3/7] Add VersionEntity so we can update its status --- ayon_api/entity_hub.py | 180 ++++++++++++++++++++++++++++++++++++++++- 1 file changed, 176 insertions(+), 4 deletions(-) diff --git a/ayon_api/entity_hub.py b/ayon_api/entity_hub.py index 4641b6c7c..26443fb93 100644 --- a/ayon_api/entity_hub.py +++ b/ayon_api/entity_hub.py @@ -250,9 +250,8 @@ def get_or_query_entity_by_id(self, entity_id, entity_types): elif entity_type == "task": return self.add_task(entity_data) - # TODO: ? - # elif entity_type == "version": - # return self.add_version(entity_data) + elif entity_type == "version": + return self.add_version(entity_data) return None @@ -353,6 +352,20 @@ def add_task(self, task): self.add_entity(task_entity) return task_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. @@ -624,7 +637,7 @@ def _get_task_fields(self): return set( self._connection.get_default_fields_for_type("task") ) - + def _get_version_fields(self): return set( self._connection.get_default_fields_for_type("version") @@ -2492,6 +2505,7 @@ def from_entity_data(cls, project, entity_hub): folder_types=project["folderTypes"], task_types=project["taskTypes"], name=project["name"], + statuses=project["statuses"], attribs=project["ownAttrib"], data=project["data"], active=project["active"], @@ -2989,3 +3003,161 @@ def _get_label_value(self): if not label or self._name == label: return None return label + +class VersionEntity(BaseEntity): + """Entity representing a version on AYON server. + + Args: + 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. + 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_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'. + """ + + entity_type = "version" + parent_entity_types = ["product"] + + def __init__( + self, + *args, + tags=None, + assignees=None, + status=UNKNOWN_VALUE, + **kwargs + ): + super(VersionEntity, self).__init__(*args, **kwargs) + + if tags is None: + tags = [] + else: + tags = list(tags) + + if assignees is None: + assignees = [] + else: + assignees = list(assignees) + + self._status = status + self._tags = tags + + self._orig_status = status + self._orig_tags = copy.deepcopy(tags) + + def lock(self): + super(VersionEntity, self).lock() + self._orig_status = self._status + self._orig_tags = copy.deepcopy(self._tags) + + def get_status(self): + """Version status. + + Returns: + Union[str, UNKNOWN_VALUE]: Version status or 'UNKNOWN_VALUE'. + + """ + return self._status + + def set_status(self, status_name): + """Set Version 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." + ) + self._status = status_name + + status = property(get_status, set_status) + + def get_tags(self): + """Version tags. + + Returns: + list[str]: Version 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) + + @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_status != self._status: + changes["status"] = self._status + + if self._orig_tags != self._tags: + changes["tags"] = self._tags + + return changes + + @classmethod + def from_entity_data(cls, version, entity_hub): + return cls( + entity_id=version["id"], + status=version["status"], + tags=version["tags"], + parent_id=version["productId"], + name=version["name"], + data=version.get("data"), + attribs=version["attrib"], + active=version["active"], + 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 'parent_id'") + + output = { + "name": self.name, + "productId": self.parent_id, + "attrib": self.attribs.to_dict(), + } + + attrib = self.attribs.to_dict() + if attrib: + output["attrib"] = attrib + + if self.active is not UNKNOWN_VALUE: + output["active"] = self.active + + if self.status is not UNKNOWN_VALUE: + output["status"] = self.status + + 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 From 49792ac5802c8fdea1670f24c74359c2555ae1ed Mon Sep 17 00:00:00 2001 From: farrizabalaga Date: Wed, 5 Jun 2024 19:50:38 +0200 Subject: [PATCH 4/7] Remove assignees kwarg from version --- ayon_api/entity_hub.py | 6 ------ 1 file changed, 6 deletions(-) diff --git a/ayon_api/entity_hub.py b/ayon_api/entity_hub.py index 26443fb93..45f37e77b 100644 --- a/ayon_api/entity_hub.py +++ b/ayon_api/entity_hub.py @@ -3029,7 +3029,6 @@ def __init__( self, *args, tags=None, - assignees=None, status=UNKNOWN_VALUE, **kwargs ): @@ -3039,11 +3038,6 @@ def __init__( tags = [] else: tags = list(tags) - - if assignees is None: - assignees = [] - else: - assignees = list(assignees) self._status = status self._tags = tags From 993207d575f9f8916132b6f6d5eb52e0196e0a94 Mon Sep 17 00:00:00 2001 From: farrizabalaga Date: Wed, 5 Jun 2024 19:51:37 +0200 Subject: [PATCH 5/7] Add extra whitespace between classes --- ayon_api/entity_hub.py | 1 + 1 file changed, 1 insertion(+) diff --git a/ayon_api/entity_hub.py b/ayon_api/entity_hub.py index 45f37e77b..f9e1354a5 100644 --- a/ayon_api/entity_hub.py +++ b/ayon_api/entity_hub.py @@ -3004,6 +3004,7 @@ def _get_label_value(self): return None return label + class VersionEntity(BaseEntity): """Entity representing a version on AYON server. From 50e75cdfe634ab773ecf31cd44b9986a0a8b18c0 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Fabi=C3=A0=20Serra=20Arrizabalaga?= Date: Thu, 6 Jun 2024 15:45:32 +0200 Subject: [PATCH 6/7] Add task_id to version entity --- ayon_api/entity_hub.py | 38 ++++++++++++++++++++++++++++++++++++-- 1 file changed, 36 insertions(+), 2 deletions(-) diff --git a/ayon_api/entity_hub.py b/ayon_api/entity_hub.py index f9e1354a5..312c67ef9 100644 --- a/ayon_api/entity_hub.py +++ b/ayon_api/entity_hub.py @@ -3017,6 +3017,9 @@ class VersionEntity(BaseEntity): data (Dict[str, Any]): Entity data (custom data). thumbnail_id (Union[str, None]): Id of entity's thumbnail. active (bool): Is entity active. + task_id (str): Id of task assigned to version. + status (ProjectStatus): Status to set to version. + tags (Iterable[str]): Tags to add to version. entity_hub (EntityHub): Object of entity hub which created object of the entity. created (Optional[bool]): Entity is new. When 'None' is passed the @@ -3029,8 +3032,9 @@ class VersionEntity(BaseEntity): def __init__( self, *args, - tags=None, + task_id=None, status=UNKNOWN_VALUE, + tags=None, **kwargs ): super(VersionEntity, self).__init__(*args, **kwargs) @@ -3040,17 +3044,40 @@ def __init__( else: tags = list(tags) + self._task_id = task_id self._status = status self._tags = tags + self._orig_task_id = task_id self._orig_status = status self._orig_tags = copy.deepcopy(tags) def lock(self): super(VersionEntity, self).lock() + self._orig_task_id = self._task_id self._orig_status = self._status self._orig_tags = copy.deepcopy(self._tags) + def get_task_id(self): + """Task id. + + Returns: + str: Id of task assigned to version. + + """ + return self._task_id + + def set_task_id(self, task_id): + """Set task id. + + Args: + task_id (str): Id of task to assign to version. + + """ + self._task_id = task_id + + task_id = property(get_task_id, set_task_id) + def get_status(self): """Version status. @@ -3103,7 +3130,10 @@ def changes(self): if self._orig_parent_id != self._parent_id: changes["folderId"] = self._parent_id - + + if self._orig_task_id != self._task_id: + changes["task_id"] = self._task_id + if self._orig_status != self._status: changes["status"] = self._status @@ -3116,6 +3146,7 @@ def changes(self): def from_entity_data(cls, version, entity_hub): return cls( entity_id=version["id"], + task_id=version["task_id"], status=version["status"], tags=version["tags"], parent_id=version["productId"], @@ -3144,6 +3175,9 @@ def to_create_body_data(self): if self.active is not UNKNOWN_VALUE: output["active"] = self.active + if self.task_id is not UNKNOWN_VALUE: + output["task_id"] = self.task_id + if self.status is not UNKNOWN_VALUE: output["status"] = self.status From 87fe7612f4a134d0ecd668cbadc861a46a383496 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Fabi=C3=A0=20Serra=20Arrizabalaga?= Date: Thu, 6 Jun 2024 18:44:01 +0200 Subject: [PATCH 7/7] Revert reverted commit in the history for task assignees --- ayon_api/entity_hub.py | 16 ++++++++++++++++ 1 file changed, 16 insertions(+) diff --git a/ayon_api/entity_hub.py b/ayon_api/entity_hub.py index b4ca4ba61..7914cbd32 100644 --- a/ayon_api/entity_hub.py +++ b/ayon_api/entity_hub.py @@ -2823,6 +2823,7 @@ def __init__( *args, label=None, tags=None, + assignees=None, status=UNKNOWN_VALUE, **kwargs ): @@ -2832,16 +2833,23 @@ def __init__( 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() @@ -2851,6 +2859,7 @@ def lock(self): 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 @@ -2953,6 +2962,9 @@ def changes(self): 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 @@ -2967,6 +2979,7 @@ def from_entity_data(cls, task, entity_hub): label=task["label"], status=task["status"], tags=task["tags"], + assignees=task["assignees"], parent_id=task["folderId"], name=task["name"], data=task.get("data"), @@ -3003,6 +3016,9 @@ def to_create_body_data(self): if self.tags: output["tags"] = self.tags + if self.assignees: + output["assignees"] = self.assignees + if ( self._entity_hub.allow_data_changes and self._data is not UNKNOWN_VALUE