From 8375b93262fe779e11931880b0d2471c9adfdcba Mon Sep 17 00:00:00 2001 From: Jakub Trllo <43494761+iLLiCiTiT@users.noreply.github.com> Date: Wed, 29 Oct 2025 14:51:15 +0100 Subject: [PATCH 1/4] added functions to create thumbnail from stream --- ayon_api/__init__.py | 4 ++ ayon_api/_api.py | 52 +++++++++++++++++++++ ayon_api/_api_helpers/base.py | 11 +++++ ayon_api/_api_helpers/thumbnails.py | 72 +++++++++++++++++++++++++++++ 4 files changed, 139 insertions(+) diff --git a/ayon_api/__init__.py b/ayon_api/__init__.py index 7cf0825f1..b28083a66 100644 --- a/ayon_api/__init__.py +++ b/ayon_api/__init__.py @@ -271,7 +271,9 @@ get_version_thumbnail, get_workfile_thumbnail, create_thumbnail, + create_thumbnail_with_stream, update_thumbnail, + update_thumbnail_from_stream, ) @@ -546,5 +548,7 @@ "get_version_thumbnail", "get_workfile_thumbnail", "create_thumbnail", + "create_thumbnail_with_stream", "update_thumbnail", + "update_thumbnail_from_stream", ) diff --git a/ayon_api/_api.py b/ayon_api/_api.py index 0d93e03e0..b24a715c8 100644 --- a/ayon_api/_api.py +++ b/ayon_api/_api.py @@ -7726,6 +7726,34 @@ def create_thumbnail( ) +def create_thumbnail_with_stream( + project_name: str, + stream: StreamType, + thumbnail_id: Optional[str] = None, +) -> str: + """Create new thumbnail on server from passed path. + + Args: + project_name (str): Project where the thumbnail will be created + and can be used. + stream (StreamType): Thumbnail content stream. + thumbnail_id (Optional[str]): Prepared if of thumbnail. + + Returns: + str: Created thumbnail id. + + Raises: + ValueError: When thumbnail source cannot be processed. + + """ + con = get_server_api_connection() + return con.create_thumbnail_with_stream( + project_name=project_name, + stream=stream, + thumbnail_id=thumbnail_id, + ) + + def update_thumbnail( project_name: str, thumbnail_id: str, @@ -7751,3 +7779,27 @@ def update_thumbnail( thumbnail_id=thumbnail_id, src_filepath=src_filepath, ) + + +def update_thumbnail_from_stream( + project_name: str, + thumbnail_id: str, + stream: StreamType, +) -> None: + """Change thumbnail content by id. + + Update can be also used to create new thumbnail. + + Args: + project_name (str): Project where the thumbnail will be created + and can be used. + thumbnail_id (str): Thumbnail id to update. + stream (StreamType): Thumbnail content stream. + + """ + con = get_server_api_connection() + return con.update_thumbnail_from_stream( + project_name=project_name, + thumbnail_id=thumbnail_id, + stream=stream, + ) diff --git a/ayon_api/_api_helpers/base.py b/ayon_api/_api_helpers/base.py index 3e7499506..4d2d2e00c 100644 --- a/ayon_api/_api_helpers/base.py +++ b/ayon_api/_api_helpers/base.py @@ -13,6 +13,7 @@ AnyEntityDict, ServerVersion, ProjectDict, + StreamType, ) _PLACEHOLDER = object() @@ -84,6 +85,16 @@ def upload_file( ) -> requests.Response: raise NotImplementedError() + def upload_file_from_stream( + self, + endpoint: str, + stream: StreamType, + progress: Optional[TransferProgress] = None, + request_type: Optional[RequestType] = None, + **kwargs + ) -> requests.Response: + raise NotImplementedError() + def download_file( self, endpoint: str, diff --git a/ayon_api/_api_helpers/thumbnails.py b/ayon_api/_api_helpers/thumbnails.py index e4b1c56d1..2a0e12684 100644 --- a/ayon_api/_api_helpers/thumbnails.py +++ b/ayon_api/_api_helpers/thumbnails.py @@ -5,6 +5,7 @@ from typing import Optional from ayon_api.utils import ( + get_media_mime_type_for_stream, get_media_mime_type, ThumbnailContent, RequestTypes, @@ -259,6 +260,48 @@ def create_thumbnail( response.raise_for_status() return response.json()["id"] + def create_thumbnail_with_stream( + self, + project_name: str, + stream: StreamType, + thumbnail_id: Optional[str] = None, + ) -> str: + """Create new thumbnail on server from passed path. + + Args: + project_name (str): Project where the thumbnail will be created + and can be used. + stream (StreamType): Thumbnail content stream. + thumbnail_id (Optional[str]): Prepared if of thumbnail. + + Returns: + str: Created thumbnail id. + + Raises: + ValueError: When thumbnail source cannot be processed. + + """ + if not os.path.exists(src_filepath): + raise ValueError("Entered filepath does not exist.") + + if thumbnail_id: + self.update_thumbnail_from_stream( + project_name, + thumbnail_id, + stream + ) + return thumbnail_id + + mime_type = get_media_mime_type_for_stream(stream) + response = self.upload_file_from_stream( + f"projects/{project_name}/thumbnails", + stream, + request_type=RequestTypes.post, + headers={"Content-Type": mime_type}, + ) + response.raise_for_status() + return response.json()["id"] + def update_thumbnail( self, project_name: str, thumbnail_id: str, src_filepath: str ) -> None: @@ -288,6 +331,35 @@ def update_thumbnail( ) response.raise_for_status() + def update_thumbnail_from_stream( + self, + project_name: str, + thumbnail_id: str, + stream: StreamType, + ) -> None: + """Change thumbnail content by id. + + Update can be also used to create new thumbnail. + + Args: + project_name (str): Project where the thumbnail will be created + and can be used. + thumbnail_id (str): Thumbnail id to update. + stream (StreamType): Thumbnail content stream. + + """ + if not os.path.exists(src_filepath): + raise ValueError("Entered filepath does not exist.") + + mime_type = get_media_mime_type_for_stream(src_filepath) + response = self.upload_file_from_stream( + f"projects/{project_name}/thumbnails/{thumbnail_id}", + stream, + request_type=RequestTypes.put, + headers={"Content-Type": mime_type}, + ) + response.raise_for_status() + def _prepare_thumbnail_content( self, project_name: str, From e9254ceb1233681691d20b230a5bc98309eba22f Mon Sep 17 00:00:00 2001 From: Jakub Trllo <43494761+iLLiCiTiT@users.noreply.github.com> Date: Wed, 29 Oct 2025 15:14:03 +0100 Subject: [PATCH 2/4] fix copy pasted code --- ayon_api/_api_helpers/thumbnails.py | 12 +++--------- 1 file changed, 3 insertions(+), 9 deletions(-) diff --git a/ayon_api/_api_helpers/thumbnails.py b/ayon_api/_api_helpers/thumbnails.py index 2a0e12684..6a0e69c8c 100644 --- a/ayon_api/_api_helpers/thumbnails.py +++ b/ayon_api/_api_helpers/thumbnails.py @@ -266,7 +266,7 @@ def create_thumbnail_with_stream( stream: StreamType, thumbnail_id: Optional[str] = None, ) -> str: - """Create new thumbnail on server from passed path. + """Create new thumbnail on server from byte stream. Args: project_name (str): Project where the thumbnail will be created @@ -278,12 +278,9 @@ def create_thumbnail_with_stream( str: Created thumbnail id. Raises: - ValueError: When thumbnail source cannot be processed. + ValueError: When a thumbnail source cannot be processed. """ - if not os.path.exists(src_filepath): - raise ValueError("Entered filepath does not exist.") - if thumbnail_id: self.update_thumbnail_from_stream( project_name, @@ -348,10 +345,7 @@ def update_thumbnail_from_stream( stream (StreamType): Thumbnail content stream. """ - if not os.path.exists(src_filepath): - raise ValueError("Entered filepath does not exist.") - - mime_type = get_media_mime_type_for_stream(src_filepath) + mime_type = get_media_mime_type_for_stream(stream) response = self.upload_file_from_stream( f"projects/{project_name}/thumbnails/{thumbnail_id}", stream, From 48f9f50f3b55f83a46735867284ffc33b942baf0 Mon Sep 17 00:00:00 2001 From: Jakub Trllo <43494761+iLLiCiTiT@users.noreply.github.com> Date: Wed, 29 Oct 2025 15:15:08 +0100 Subject: [PATCH 3/4] add missing import --- ayon_api/_api_helpers/thumbnails.py | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/ayon_api/_api_helpers/thumbnails.py b/ayon_api/_api_helpers/thumbnails.py index 6a0e69c8c..577536e28 100644 --- a/ayon_api/_api_helpers/thumbnails.py +++ b/ayon_api/_api_helpers/thumbnails.py @@ -2,6 +2,7 @@ import os import warnings +import typing from typing import Optional from ayon_api.utils import ( @@ -14,6 +15,9 @@ from .base import BaseServerAPI +if typing.TYPE_CHECKING: + from .typing import StreamType + class ThumbnailsAPI(BaseServerAPI): def get_thumbnail_by_id( From c8c136e49f7fd722a32140d79e53f8304d53cd50 Mon Sep 17 00:00:00 2001 From: Jakub Trllo <43494761+iLLiCiTiT@users.noreply.github.com> Date: Wed, 29 Oct 2025 15:15:20 +0100 Subject: [PATCH 4/4] update public api --- ayon_api/_api.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/ayon_api/_api.py b/ayon_api/_api.py index b24a715c8..be6b21d9c 100644 --- a/ayon_api/_api.py +++ b/ayon_api/_api.py @@ -7731,7 +7731,7 @@ def create_thumbnail_with_stream( stream: StreamType, thumbnail_id: Optional[str] = None, ) -> str: - """Create new thumbnail on server from passed path. + """Create new thumbnail on server from byte stream. Args: project_name (str): Project where the thumbnail will be created @@ -7743,7 +7743,7 @@ def create_thumbnail_with_stream( str: Created thumbnail id. Raises: - ValueError: When thumbnail source cannot be processed. + ValueError: When a thumbnail source cannot be processed. """ con = get_server_api_connection()