diff --git a/ayon_api/__init__.py b/ayon_api/__init__.py index a41fee778..7cf0825f1 100644 --- a/ayon_api/__init__.py +++ b/ayon_api/__init__.py @@ -222,11 +222,17 @@ create_representation, update_representation, delete_representation, + get_workfile_entities, + get_workfile_entity, + get_workfile_entity_by_id, + create_workfile_entity, + update_workfile_entity, + delete_workfile_entity, get_workfiles_info, get_workfile_info, get_workfile_info_by_id, - delete_workfile_info, update_workfile_info, + delete_workfile_info, get_full_link_type_name, get_link_types, get_link_type, @@ -491,11 +497,17 @@ "create_representation", "update_representation", "delete_representation", + "get_workfile_entities", + "get_workfile_entity", + "get_workfile_entity_by_id", + "create_workfile_entity", + "update_workfile_entity", + "delete_workfile_entity", "get_workfiles_info", "get_workfile_info", "get_workfile_info_by_id", - "delete_workfile_info", "update_workfile_info", + "delete_workfile_info", "get_full_link_type_name", "get_link_types", "get_link_type", diff --git a/ayon_api/_api.py b/ayon_api/_api.py index b6a101f1c..0d93e03e0 100644 --- a/ayon_api/_api.py +++ b/ayon_api/_api.py @@ -6157,8 +6157,9 @@ def delete_representation( ) -def get_workfiles_info( +def get_workfile_entities( project_name: str, + *, workfile_ids: Optional[Iterable[str]] = None, task_ids: Optional[Iterable[str]] = None, paths: Optional[Iterable[str]] = None, @@ -6167,7 +6168,6 @@ def get_workfiles_info( tags: Optional[Iterable[str]] = None, has_links: Optional[str] = None, fields: Optional[Iterable[str]] = None, - own_attributes=_PLACEHOLDER, ) -> Generator[WorkfileInfoDict, None, None]: """Workfile info entities by passed filters. @@ -6186,8 +6186,6 @@ def get_workfiles_info( fields (Optional[Iterable[str]]): Fields to be queried for representation. All possible fields are returned if 'None' is passed. - own_attributes (Optional[bool]): DEPRECATED: Not supported for - workfiles. Returns: Generator[WorkfileInfoDict, None, None]: Queried workfile info @@ -6195,7 +6193,7 @@ def get_workfiles_info( """ con = get_server_api_connection() - return con.get_workfiles_info( + return con.get_workfile_entities( project_name=project_name, workfile_ids=workfile_ids, task_ids=task_ids, @@ -6205,16 +6203,15 @@ def get_workfiles_info( tags=tags, has_links=has_links, fields=fields, - own_attributes=own_attributes, ) -def get_workfile_info( +def get_workfile_entity( project_name: str, task_id: str, path: str, + *, fields: Optional[Iterable[str]] = None, - own_attributes=_PLACEHOLDER, ) -> Optional[WorkfileInfoDict]: """Workfile info entity by task id and workfile path. @@ -6225,28 +6222,25 @@ def get_workfile_info( fields (Optional[Iterable[str]]): Fields to be queried for representation. All possible fields are returned if 'None' is passed. - own_attributes (Optional[bool]): DEPRECATED: Not supported for - workfiles. Returns: Optional[WorkfileInfoDict]: Workfile info entity or None. """ con = get_server_api_connection() - return con.get_workfile_info( + return con.get_workfile_entity( project_name=project_name, task_id=task_id, path=path, fields=fields, - own_attributes=own_attributes, ) -def get_workfile_info_by_id( +def get_workfile_entity_by_id( project_name: str, workfile_id: str, + *, fields: Optional[Iterable[str]] = None, - own_attributes=_PLACEHOLDER, ) -> Optional[WorkfileInfoDict]: """Workfile info entity by id. @@ -6256,23 +6250,119 @@ def get_workfile_info_by_id( fields (Optional[Iterable[str]]): Fields to be queried for representation. All possible fields are returned if 'None' is passed. - own_attributes (Optional[bool]): DEPRECATED: Not supported for - workfiles. Returns: Optional[WorkfileInfoDict]: Workfile info entity or None. """ con = get_server_api_connection() - return con.get_workfile_info_by_id( + return con.get_workfile_entity_by_id( project_name=project_name, workfile_id=workfile_id, fields=fields, - own_attributes=own_attributes, ) -def delete_workfile_info( +def create_workfile_entity( + project_name: str, + path: str, + task_id: str, + *, + thumbnail_id: Optional[str] = None, + attrib: Optional[dict[str, Any]] = None, + data: Optional[dict[str, Any]] = None, + tags: Optional[list[str]] = None, + status: Optional[str] = None, + active: Optional[bool] = None, + workfile_id: Optional[str] = None, +) -> str: + """Create new workfile. + + Args: + project_name (str): Project name. + path (str): Representation name. + task_id (str): Parent task id. + thumbnail_id (Optional[str]): Thumbnail id. + attrib (Optional[dict[str, Any]]): Representation attributes. + data (Optional[dict[str, Any]]): Representation data. + tags (Optional[Iterable[str]]): Representation tags. + status (Optional[str]): Representation status. + active (Optional[bool]): Representation active state. + workfile_id (Optional[str]): Workfile info id. If not + passed new id is generated. + + Returns: + str: Workfile info id. + + """ + con = get_server_api_connection() + return con.create_workfile_entity( + project_name=project_name, + path=path, + task_id=task_id, + thumbnail_id=thumbnail_id, + attrib=attrib, + data=data, + tags=tags, + status=status, + active=active, + workfile_id=workfile_id, + ) + + +def update_workfile_entity( + project_name: str, + workfile_id: str, + *, + path: Optional[str] = None, + task_id: Optional[str] = None, + attrib: Optional[dict[str, Any]] = None, + data: Optional[dict[str, Any]] = None, + tags: Optional[Iterable[str]] = None, + status: Optional[str] = None, + active: Optional[bool] = None, + thumbnail_id: Optional[str] = NOT_SET, + created_by: Optional[str] = None, + updated_by: Optional[str] = None, +) -> None: + """Update workfile entity on server. + + Update of ``attrib`` does change only passed attributes. If you want + to unset value, use ``None``. + + Args: + project_name (str): Project name. + workfile_id (str): Workfile id. + path (Optional[str]): New rootless workfile path.. + task_id (Optional[str]): New parent task id. + attrib (Optional[dict[str, Any]]): New attributes. + data (Optional[dict[str, Any]]): New data. + tags (Optional[Iterable[str]]): New tags. + status (Optional[str]): New status. + active (Optional[bool]): New active state. + thumbnail_id (Optional[str]): New thumbnail id. + created_by (Optional[str]): New created by username. + updated_by (Optional[str]): New updated by username. + + """ + con = get_server_api_connection() + return con.update_workfile_entity( + project_name=project_name, + workfile_id=workfile_id, + path=path, + task_id=task_id, + attrib=attrib, + data=data, + tags=tags, + status=status, + active=active, + thumbnail_id=thumbnail_id, + created_by=created_by, + updated_by=updated_by, + ) + + +def delete_workfile_entity( project_name: str, workfile_id: str, ) -> None: @@ -6284,12 +6374,127 @@ def delete_workfile_info( """ con = get_server_api_connection() - return con.delete_workfile_info( + return con.delete_workfile_entity( project_name=project_name, workfile_id=workfile_id, ) +def get_workfiles_info( + project_name: str, + workfile_ids: Optional[Iterable[str]] = None, + task_ids: Optional[Iterable[str]] = None, + paths: Optional[Iterable[str]] = None, + path_regex: Optional[str] = None, + statuses: Optional[Iterable[str]] = None, + tags: Optional[Iterable[str]] = None, + has_links: Optional[str] = None, + fields: Optional[Iterable[str]] = None, + own_attributes=_PLACEHOLDER, +) -> Generator[WorkfileInfoDict, None, None]: + """DEPRECATED Workfile info entities by passed filters. + + Args: + project_name (str): Project under which the entity is located. + workfile_ids (Optional[Iterable[str]]): Workfile ids. + task_ids (Optional[Iterable[str]]): Task ids. + paths (Optional[Iterable[str]]): Rootless workfiles paths. + path_regex (Optional[str]): Regex filter for workfile path. + statuses (Optional[Iterable[str]]): Workfile info statuses used + for filtering. + tags (Optional[Iterable[str]]): Workfile info tags used + for filtering. + has_links (Optional[Literal[IN, OUT, ANY]]): Filter + representations with IN/OUT/ANY links. + fields (Optional[Iterable[str]]): Fields to be queried for + representation. All possible fields are returned if 'None' is + passed. + own_attributes (Optional[bool]): DEPRECATED: Not supported for + workfiles. + + Returns: + Generator[WorkfileInfoDict, None, None]: Queried workfile info + entites. + + """ + con = get_server_api_connection() + return con.get_workfiles_info( + project_name=project_name, + workfile_ids=workfile_ids, + task_ids=task_ids, + paths=paths, + path_regex=path_regex, + statuses=statuses, + tags=tags, + has_links=has_links, + fields=fields, + own_attributes=own_attributes, + ) + + +def get_workfile_info( + project_name: str, + task_id: str, + path: str, + fields: Optional[Iterable[str]] = None, + own_attributes=_PLACEHOLDER, +) -> Optional[WorkfileInfoDict]: + """DEPRECATED Workfile info entity by task id and workfile path. + + Args: + project_name (str): Project under which the entity is located. + task_id (str): Task id. + path (str): Rootless workfile path. + fields (Optional[Iterable[str]]): Fields to be queried for + representation. All possible fields are returned if 'None' is + passed. + own_attributes (Optional[bool]): DEPRECATED: Not supported for + workfiles. + + Returns: + Optional[WorkfileInfoDict]: Workfile info entity or None. + + """ + con = get_server_api_connection() + return con.get_workfile_info( + project_name=project_name, + task_id=task_id, + path=path, + fields=fields, + own_attributes=own_attributes, + ) + + +def get_workfile_info_by_id( + project_name: str, + workfile_id: str, + fields: Optional[Iterable[str]] = None, + own_attributes=_PLACEHOLDER, +) -> Optional[WorkfileInfoDict]: + """DEPRECATED Workfile info entity by id. + + Args: + project_name (str): Project under which the entity is located. + workfile_id (str): Workfile info id. + fields (Optional[Iterable[str]]): Fields to be queried for + representation. All possible fields are returned if 'None' is + passed. + own_attributes (Optional[bool]): DEPRECATED: Not supported for + workfiles. + + Returns: + Optional[WorkfileInfoDict]: Workfile info entity or None. + + """ + con = get_server_api_connection() + return con.get_workfile_info_by_id( + project_name=project_name, + workfile_id=workfile_id, + fields=fields, + own_attributes=own_attributes, + ) + + def update_workfile_info( project_name: str, workfile_id: str, @@ -6304,7 +6509,7 @@ def update_workfile_info( created_by: Optional[str] = None, updated_by: Optional[str] = None, ) -> None: - """Update workfile entity on server. + """DEPRECATED Update workfile entity on server. Update of ``attrib`` does change only passed attributes. If you want to unset value, use ``None``. @@ -6341,6 +6546,24 @@ def update_workfile_info( ) +def delete_workfile_info( + project_name: str, + workfile_id: str, +) -> None: + """DEPRECATED Delete workfile entity on server. + + Args: + project_name (str): Project name. + workfile_id (str): Workfile id to delete. + + """ + con = get_server_api_connection() + return con.delete_workfile_info( + project_name=project_name, + workfile_id=workfile_id, + ) + + def get_full_link_type_name( link_type_name: str, input_type: str, diff --git a/ayon_api/_api_helpers/base.py b/ayon_api/_api_helpers/base.py index f49b10a9b..3e7499506 100644 --- a/ayon_api/_api_helpers/base.py +++ b/ayon_api/_api_helpers/base.py @@ -109,6 +109,11 @@ def get_project( ) -> Optional[ProjectDict]: raise NotImplementedError() + def get_user( + self, username: Optional[str] = None + ) -> Optional[dict[str, Any]]: + raise NotImplementedError() + def _prepare_fields( self, entity_type: str, diff --git a/ayon_api/_api_helpers/workfiles.py b/ayon_api/_api_helpers/workfiles.py index 8b2efb90f..a0e35b9a8 100644 --- a/ayon_api/_api_helpers/workfiles.py +++ b/ayon_api/_api_helpers/workfiles.py @@ -5,7 +5,8 @@ from typing import Optional, Iterable, Generator, Any from ayon_api.graphql_queries import workfiles_info_graphql_query -from ayon_api.utils import NOT_SET +from ayon_api.utils import NOT_SET, create_entity_id + from .base import BaseServerAPI, _PLACEHOLDER if typing.TYPE_CHECKING: @@ -13,9 +14,10 @@ class WorkfilesAPI(BaseServerAPI): - def get_workfiles_info( + def get_workfile_entities( self, project_name: str, + *, workfile_ids: Optional[Iterable[str]] = None, task_ids: Optional[Iterable[str]] =None, paths: Optional[Iterable[str]] =None, @@ -24,7 +26,6 @@ def get_workfiles_info( tags: Optional[Iterable[str]] = None, has_links: Optional[str]=None, fields: Optional[Iterable[str]] = None, - own_attributes=_PLACEHOLDER, ) -> Generator[WorkfileInfoDict, None, None]: """Workfile info entities by passed filters. @@ -43,8 +44,6 @@ def get_workfiles_info( fields (Optional[Iterable[str]]): Fields to be queried for representation. All possible fields are returned if 'None' is passed. - own_attributes (Optional[bool]): DEPRECATED: Not supported for - workfiles. Returns: Generator[WorkfileInfoDict, None, None]: Queried workfile info @@ -94,16 +93,6 @@ def get_workfiles_info( fields = set(fields) self._prepare_fields("workfile", fields) - if own_attributes is not _PLACEHOLDER: - warnings.warn( - ( - "'own_attributes' is not supported for workfiles. The" - " argument will be removed form function signature in" - " future (apx. version 1.0.10 or 1.1.0)." - ), - DeprecationWarning - ) - query = workfiles_info_graphql_query(fields) for attr, filter_value in filters.items(): @@ -114,13 +103,13 @@ def get_workfiles_info( self._convert_entity_data(workfile_info) yield workfile_info - def get_workfile_info( + def get_workfile_entity( self, project_name: str, task_id: str, path: str, + *, fields: Optional[Iterable[str]] = None, - own_attributes=_PLACEHOLDER, ) -> Optional[WorkfileInfoDict]: """Workfile info entity by task id and workfile path. @@ -131,8 +120,6 @@ def get_workfile_info( fields (Optional[Iterable[str]]): Fields to be queried for representation. All possible fields are returned if 'None' is passed. - own_attributes (Optional[bool]): DEPRECATED: Not supported for - workfiles. Returns: Optional[WorkfileInfoDict]: Workfile info entity or None. @@ -141,22 +128,21 @@ def get_workfile_info( if not task_id or not path: return None - for workfile_info in self.get_workfiles_info( + for workfile_info in self.get_workfile_entities( project_name, task_ids=[task_id], paths=[path], fields=fields, - own_attributes=own_attributes ): return workfile_info return None - def get_workfile_info_by_id( + def get_workfile_entity_by_id( self, project_name: str, workfile_id: str, + *, fields: Optional[Iterable[str]] = None, - own_attributes=_PLACEHOLDER, ) -> Optional[WorkfileInfoDict]: """Workfile info entity by id. @@ -166,8 +152,6 @@ def get_workfile_info_by_id( fields (Optional[Iterable[str]]): Fields to be queried for representation. All possible fields are returned if 'None' is passed. - own_attributes (Optional[bool]): DEPRECATED: Not supported for - workfiles. Returns: Optional[WorkfileInfoDict]: Workfile info entity or None. @@ -176,36 +160,85 @@ def get_workfile_info_by_id( if not workfile_id: return None - for workfile_info in self.get_workfiles_info( + for workfile_info in self.get_workfile_entities( project_name, workfile_ids=[workfile_id], fields=fields, - own_attributes=own_attributes ): return workfile_info return None - def delete_workfile_info( + def create_workfile_entity( self, project_name: str, - workfile_id: str, - ) -> None: - """Delete workfile entity on server. + path: str, + task_id: str, + *, + thumbnail_id: Optional[str] = None, + attrib: Optional[dict[str, Any]] = None, + data: Optional[dict[str, Any]] = None, + tags: Optional[list[str]] = None, + status: Optional[str] = None, + active: Optional[bool] = None, + workfile_id: Optional[str] = None, + ) -> str: + """Create new workfile. Args: project_name (str): Project name. - workfile_id (str): Workfile id to delete. + path (str): Representation name. + task_id (str): Parent task id. + thumbnail_id (Optional[str]): Thumbnail id. + attrib (Optional[dict[str, Any]]): Representation attributes. + data (Optional[dict[str, Any]]): Representation data. + tags (Optional[Iterable[str]]): Representation tags. + status (Optional[str]): Representation status. + active (Optional[bool]): Representation active state. + workfile_id (Optional[str]): Workfile info id. If not + passed new id is generated. + + Returns: + str: Workfile info id. """ - response = self.delete( - f"projects/{project_name}/workfiles/{workfile_id}" + if workfile_id is None: + workfile_id = create_entity_id() + + create_data = { + "id": workfile_id, + "path": path, + "taskId": task_id, + } + for key, value in ( + ("thumbnailId", thumbnail_id), + ("attrib", attrib), + ("data", data), + ("tags", tags), + ("status", status), + ("active", active), + ): + if value is not None: + create_data[key] = value + + major, minor, patch, _, _ = self.get_server_version_tuple() + if (major, minor, patch) < (1, 1, 3): + user = self.get_user() + username = user["name"] + create_data["createdBy"] = username + create_data["updatedBy"] = username + + response = self.post( + f"projects/{project_name}/workfiles", + **create_data ) response.raise_for_status() + return workfile_id - def update_workfile_info( + def update_workfile_entity( self, project_name: str, workfile_id: str, + *, path: Optional[str] = None, task_id: Optional[str] = None, attrib: Optional[dict[str, Any]] = None, @@ -263,3 +296,226 @@ def update_workfile_info( **update_data ) response.raise_for_status() + + def delete_workfile_entity( + self, + project_name: str, + workfile_id: str, + ) -> None: + """Delete workfile entity on server. + + Args: + project_name (str): Project name. + workfile_id (str): Workfile id to delete. + + """ + response = self.delete( + f"projects/{project_name}/workfiles/{workfile_id}" + ) + response.raise_for_status() + + # --- DEPRECATED --- + def get_workfiles_info( + self, + project_name: str, + workfile_ids: Optional[Iterable[str]] = None, + task_ids: Optional[Iterable[str]] =None, + paths: Optional[Iterable[str]] =None, + path_regex: Optional[str] = None, + statuses: Optional[Iterable[str]] = None, + tags: Optional[Iterable[str]] = None, + has_links: Optional[str]=None, + fields: Optional[Iterable[str]] = None, + own_attributes=_PLACEHOLDER, + ) -> Generator[WorkfileInfoDict, None, None]: + """DEPRECATED Workfile info entities by passed filters. + + Args: + project_name (str): Project under which the entity is located. + workfile_ids (Optional[Iterable[str]]): Workfile ids. + task_ids (Optional[Iterable[str]]): Task ids. + paths (Optional[Iterable[str]]): Rootless workfiles paths. + path_regex (Optional[str]): Regex filter for workfile path. + statuses (Optional[Iterable[str]]): Workfile info statuses used + for filtering. + tags (Optional[Iterable[str]]): Workfile info tags used + for filtering. + has_links (Optional[Literal[IN, OUT, ANY]]): Filter + representations with IN/OUT/ANY links. + fields (Optional[Iterable[str]]): Fields to be queried for + representation. All possible fields are returned if 'None' is + passed. + own_attributes (Optional[bool]): DEPRECATED: Not supported for + workfiles. + + Returns: + Generator[WorkfileInfoDict, None, None]: Queried workfile info + entites. + + """ + if own_attributes is not _PLACEHOLDER: + warnings.warn( + ( + "'own_attributes' is not supported for workfiles. The" + " argument will be removed form function signature in" + " future (apx. version 1.0.10 or 1.1.0)." + ), + DeprecationWarning, + stacklevel=2, + ) + + return self.get_workfile_entities( + project_name, + workfile_ids=workfile_ids, + task_ids=task_ids, + paths=paths, + path_regex=path_regex, + statuses=statuses, + tags=tags, + has_links=has_links, + fields=fields, + ) + + def get_workfile_info( + self, + project_name: str, + task_id: str, + path: str, + fields: Optional[Iterable[str]] = None, + own_attributes=_PLACEHOLDER, + ) -> Optional[WorkfileInfoDict]: + """DEPRECATED Workfile info entity by task id and workfile path. + + Args: + project_name (str): Project under which the entity is located. + task_id (str): Task id. + path (str): Rootless workfile path. + fields (Optional[Iterable[str]]): Fields to be queried for + representation. All possible fields are returned if 'None' is + passed. + own_attributes (Optional[bool]): DEPRECATED: Not supported for + workfiles. + + Returns: + Optional[WorkfileInfoDict]: Workfile info entity or None. + + """ + if own_attributes is not _PLACEHOLDER: + warnings.warn( + ( + "'own_attributes' is not supported for workfiles. The" + " argument will be removed form function signature in" + " future (apx. version 1.0.10 or 1.1.0)." + ), + DeprecationWarning, + stacklevel=2, + ) + + return self.get_workfile_entity( + project_name, task_id, path,fields=fields + ) + + def get_workfile_info_by_id( + self, + project_name: str, + workfile_id: str, + fields: Optional[Iterable[str]] = None, + own_attributes=_PLACEHOLDER, + ) -> Optional[WorkfileInfoDict]: + """DEPRECATED Workfile info entity by id. + + Args: + project_name (str): Project under which the entity is located. + workfile_id (str): Workfile info id. + fields (Optional[Iterable[str]]): Fields to be queried for + representation. All possible fields are returned if 'None' is + passed. + own_attributes (Optional[bool]): DEPRECATED: Not supported for + workfiles. + + Returns: + Optional[WorkfileInfoDict]: Workfile info entity or None. + + """ + if own_attributes is not _PLACEHOLDER: + warnings.warn( + ( + "'own_attributes' is not supported for workfiles. The" + " argument will be removed form function signature in" + " future (apx. version 1.0.10 or 1.1.0)." + ), + DeprecationWarning, + stacklevel=2, + ) + return self.get_workfile_entity_by_id( + project_name, + workfile_id, + fields=fields, + ) + + def update_workfile_info( + self, + project_name: str, + workfile_id: str, + path: Optional[str] = None, + task_id: Optional[str] = None, + attrib: Optional[dict[str, Any]] = None, + data: Optional[dict[str, Any]] = None, + tags: Optional[Iterable[str]] = None, + status: Optional[str] = None, + active: Optional[bool] = None, + thumbnail_id: Optional[str] = NOT_SET, + created_by: Optional[str] = None, + updated_by: Optional[str] = None, + ) -> None: + """DEPRECATED Update workfile entity on server. + + Update of ``attrib`` does change only passed attributes. If you want + to unset value, use ``None``. + + Args: + project_name (str): Project name. + workfile_id (str): Workfile id. + path (Optional[str]): New rootless workfile path.. + task_id (Optional[str]): New parent task id. + attrib (Optional[dict[str, Any]]): New attributes. + data (Optional[dict[str, Any]]): New data. + tags (Optional[Iterable[str]]): New tags. + status (Optional[str]): New status. + active (Optional[bool]): New active state. + thumbnail_id (Optional[str]): New thumbnail id. + created_by (Optional[str]): New created by username. + updated_by (Optional[str]): New updated by username. + + """ + return self.update_workfile_entity( + project_name, + workfile_id, + path=path, + task_id=task_id, + attrib=attrib, + data=data, + tags=tags, + status=status, + active=active, + thumbnail_id=thumbnail_id, + created_by=created_by, + updated_by=updated_by, + ) + + def delete_workfile_info( + self, + project_name: str, + workfile_id: str, + ) -> None: + """DEPRECATED Delete workfile entity on server. + + Args: + project_name (str): Project name. + workfile_id (str): Workfile id to delete. + + """ + return self.delete_workfile_entity( + project_name, + workfile_id, + )