From edc451c916c4776dcea216e6362d56b1e1bde330 Mon Sep 17 00:00:00 2001 From: MustafaJafar Date: Tue, 15 Apr 2025 18:24:19 +0200 Subject: [PATCH 01/59] add optional `aov` key to render template profile name --- server/settings/tools.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/server/settings/tools.py b/server/settings/tools.py index 32c72e7a98..ed23cee69c 100644 --- a/server/settings/tools.py +++ b/server/settings/tools.py @@ -414,7 +414,7 @@ DEFAULT_TOOLS_VALUES = { "hosts": [], "task_types": [], "tasks": [], - "template": "{product[type]}{Task[name]}{Variant}" + "template": "{product[type]}{Task[name]}{Variant}<_{Aov}>" }, { "product_types": [ From d23269b654b86443f482d33ce52b315b2fb0c2ff Mon Sep 17 00:00:00 2001 From: Jakub Trllo <43494761+iLLiCiTiT@users.noreply.github.com> Date: Fri, 3 Oct 2025 17:06:26 +0200 Subject: [PATCH 02/59] override '_drawtext' in ffmpeg burnins --- client/ayon_core/scripts/otio_burnin.py | 35 +++++++++++++++++++++++++ 1 file changed, 35 insertions(+) diff --git a/client/ayon_core/scripts/otio_burnin.py b/client/ayon_core/scripts/otio_burnin.py index 77eeecaff6..47bc5dd444 100644 --- a/client/ayon_core/scripts/otio_burnin.py +++ b/client/ayon_core/scripts/otio_burnin.py @@ -7,6 +7,8 @@ import tempfile from string import Formatter import opentimelineio_contrib.adapters.ffmpeg_burnins as ffmpeg_burnins +from PIL import ImageFont + from ayon_core.lib import ( get_ffmpeg_tool_args, get_ffmpeg_codec_args, @@ -36,6 +38,39 @@ TIMECODE_KEY = "{timecode}" SOURCE_TIMECODE_KEY = "{source_timecode}" +def _drawtext(align, resolution, text, options): + """ + :rtype: {'x': int, 'y': int} + """ + x_pos = "0" + if align in (ffmpeg_burnins.TOP_CENTERED, ffmpeg_burnins.BOTTOM_CENTERED): + x_pos = "w/2-tw/2" + + elif align in (ffmpeg_burnins.TOP_RIGHT, ffmpeg_burnins.BOTTOM_RIGHT): + ifont = ImageFont.truetype(options["font"], options["font_size"]) + if hasattr(ifont, "getbox"): + left, top, right, bottom = ifont.getbbox(text) + box_size = right - left, bottom - top + else: + box_size = ifont.getsize(text) + x_pos = resolution[0] - (box_size[0] + options["x_offset"]) + elif align in (ffmpeg_burnins.TOP_LEFT, ffmpeg_burnins.BOTTOM_LEFT): + x_pos = options["x_offset"] + + if align in ( + ffmpeg_burnins.TOP_CENTERED, + ffmpeg_burnins.TOP_RIGHT, + ffmpeg_burnins.TOP_LEFT + ): + y_pos = "%d" % options["y_offset"] + else: + y_pos = "h-text_h-%d" % (options["y_offset"]) + return {"x": x_pos, "y": y_pos} + + +ffmpeg_burnins._drawtext = _drawtext + + def _get_ffprobe_data(source): """Reimplemented from otio burnins to be able use full path to ffprobe :param str source: source media file From 7c0aef98dceebf5e66dd9e8babc2c6f07b3ec68c Mon Sep 17 00:00:00 2001 From: Ynbot Date: Mon, 6 Oct 2025 12:01:06 +0000 Subject: [PATCH 03/59] [Automated] Add generated package files from main --- client/ayon_core/version.py | 2 +- package.py | 2 +- pyproject.toml | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/client/ayon_core/version.py b/client/ayon_core/version.py index c7a72e0b43..6643698ce6 100644 --- a/client/ayon_core/version.py +++ b/client/ayon_core/version.py @@ -1,3 +1,3 @@ # -*- coding: utf-8 -*- """Package declaring AYON addon 'core' version.""" -__version__ = "1.6.1+dev" +__version__ = "1.6.2" diff --git a/package.py b/package.py index f6853d8816..d45d387dd1 100644 --- a/package.py +++ b/package.py @@ -1,6 +1,6 @@ name = "core" title = "Core" -version = "1.6.1+dev" +version = "1.6.2" client_dir = "ayon_core" diff --git a/pyproject.toml b/pyproject.toml index 18f2047a92..e2ee09e66c 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -5,7 +5,7 @@ [tool.poetry] name = "ayon-core" -version = "1.6.1+dev" +version = "1.6.2" description = "" authors = ["Ynput Team "] readme = "README.md" From 67539297ae287f7f3b569cfe692582e4c7799dda Mon Sep 17 00:00:00 2001 From: Ynbot Date: Mon, 6 Oct 2025 12:01:45 +0000 Subject: [PATCH 04/59] [Automated] Update version in package.py for develop --- client/ayon_core/version.py | 2 +- package.py | 2 +- pyproject.toml | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/client/ayon_core/version.py b/client/ayon_core/version.py index 6643698ce6..0cea28a13d 100644 --- a/client/ayon_core/version.py +++ b/client/ayon_core/version.py @@ -1,3 +1,3 @@ # -*- coding: utf-8 -*- """Package declaring AYON addon 'core' version.""" -__version__ = "1.6.2" +__version__ = "1.6.2+dev" diff --git a/package.py b/package.py index d45d387dd1..115c0dadd8 100644 --- a/package.py +++ b/package.py @@ -1,6 +1,6 @@ name = "core" title = "Core" -version = "1.6.2" +version = "1.6.2+dev" client_dir = "ayon_core" diff --git a/pyproject.toml b/pyproject.toml index e2ee09e66c..e32d3d2d85 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -5,7 +5,7 @@ [tool.poetry] name = "ayon-core" -version = "1.6.2" +version = "1.6.2+dev" description = "" authors = ["Ynput Team "] readme = "README.md" From 2a32d56bc44d33b6130c0d1cacc88ae5514016ff Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" Date: Mon, 6 Oct 2025 12:02:42 +0000 Subject: [PATCH 05/59] chore(): update bug report / version --- .github/ISSUE_TEMPLATE/bug_report.yml | 1 + 1 file changed, 1 insertion(+) diff --git a/.github/ISSUE_TEMPLATE/bug_report.yml b/.github/ISSUE_TEMPLATE/bug_report.yml index 6b75179e7b..e1e5e053c0 100644 --- a/.github/ISSUE_TEMPLATE/bug_report.yml +++ b/.github/ISSUE_TEMPLATE/bug_report.yml @@ -35,6 +35,7 @@ body: label: Version description: What version are you running? Look to AYON Tray options: + - 1.6.2 - 1.6.1 - 1.6.0 - 1.5.3 From 6643fdca07b3333e5d25241a46ba434cd28c71cb Mon Sep 17 00:00:00 2001 From: Jakub Trllo <43494761+iLLiCiTiT@users.noreply.github.com> Date: Mon, 6 Oct 2025 17:12:43 +0200 Subject: [PATCH 06/59] fix import of otio burnins --- client/ayon_core/scripts/otio_burnin.py | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/client/ayon_core/scripts/otio_burnin.py b/client/ayon_core/scripts/otio_burnin.py index 77eeecaff6..a4e8848e10 100644 --- a/client/ayon_core/scripts/otio_burnin.py +++ b/client/ayon_core/scripts/otio_burnin.py @@ -6,7 +6,10 @@ import json import tempfile from string import Formatter -import opentimelineio_contrib.adapters.ffmpeg_burnins as ffmpeg_burnins +try: + from otio_burnins_adapter import ffmpeg_burnins +except ImportError: + import opentimelineio_contrib.adapters.ffmpeg_burnins as ffmpeg_burnins from ayon_core.lib import ( get_ffmpeg_tool_args, get_ffmpeg_codec_args, From 434b7bd7b2fce428d20b1788d94369e3a1662e84 Mon Sep 17 00:00:00 2001 From: Ynbot Date: Mon, 6 Oct 2025 16:24:54 +0000 Subject: [PATCH 07/59] [Automated] Add generated package files from main --- client/ayon_core/version.py | 2 +- package.py | 2 +- pyproject.toml | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/client/ayon_core/version.py b/client/ayon_core/version.py index 0cea28a13d..61df8e2e7d 100644 --- a/client/ayon_core/version.py +++ b/client/ayon_core/version.py @@ -1,3 +1,3 @@ # -*- coding: utf-8 -*- """Package declaring AYON addon 'core' version.""" -__version__ = "1.6.2+dev" +__version__ = "1.6.3" diff --git a/package.py b/package.py index 115c0dadd8..c201fa3541 100644 --- a/package.py +++ b/package.py @@ -1,6 +1,6 @@ name = "core" title = "Core" -version = "1.6.2+dev" +version = "1.6.3" client_dir = "ayon_core" diff --git a/pyproject.toml b/pyproject.toml index e32d3d2d85..14d44c4048 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -5,7 +5,7 @@ [tool.poetry] name = "ayon-core" -version = "1.6.2+dev" +version = "1.6.3" description = "" authors = ["Ynput Team "] readme = "README.md" From faccabc64cfd25385a8b4c8025ebc5860fb0fd6f Mon Sep 17 00:00:00 2001 From: Ynbot Date: Mon, 6 Oct 2025 16:25:31 +0000 Subject: [PATCH 08/59] [Automated] Update version in package.py for develop --- client/ayon_core/version.py | 2 +- package.py | 2 +- pyproject.toml | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/client/ayon_core/version.py b/client/ayon_core/version.py index 61df8e2e7d..cb43cd72c3 100644 --- a/client/ayon_core/version.py +++ b/client/ayon_core/version.py @@ -1,3 +1,3 @@ # -*- coding: utf-8 -*- """Package declaring AYON addon 'core' version.""" -__version__ = "1.6.3" +__version__ = "1.6.3+dev" diff --git a/package.py b/package.py index c201fa3541..5101503403 100644 --- a/package.py +++ b/package.py @@ -1,6 +1,6 @@ name = "core" title = "Core" -version = "1.6.3" +version = "1.6.3+dev" client_dir = "ayon_core" diff --git a/pyproject.toml b/pyproject.toml index 14d44c4048..cde88e0941 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -5,7 +5,7 @@ [tool.poetry] name = "ayon-core" -version = "1.6.3" +version = "1.6.3+dev" description = "" authors = ["Ynput Team "] readme = "README.md" From 201da3b5d1c0ceea369ec3c6484ee20ea9db3571 Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" Date: Mon, 6 Oct 2025 16:26:24 +0000 Subject: [PATCH 09/59] chore(): update bug report / version --- .github/ISSUE_TEMPLATE/bug_report.yml | 1 + 1 file changed, 1 insertion(+) diff --git a/.github/ISSUE_TEMPLATE/bug_report.yml b/.github/ISSUE_TEMPLATE/bug_report.yml index e1e5e053c0..e84522395d 100644 --- a/.github/ISSUE_TEMPLATE/bug_report.yml +++ b/.github/ISSUE_TEMPLATE/bug_report.yml @@ -35,6 +35,7 @@ body: label: Version description: What version are you running? Look to AYON Tray options: + - 1.6.3 - 1.6.2 - 1.6.1 - 1.6.0 From 243436918c8816f1a4e537f5a572f70494ecf39e Mon Sep 17 00:00:00 2001 From: Jakub Trllo <43494761+iLLiCiTiT@users.noreply.github.com> Date: Tue, 7 Oct 2025 17:14:34 +0200 Subject: [PATCH 10/59] revert otio to use older version --- client/pyproject.toml | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/client/pyproject.toml b/client/pyproject.toml index 5acfdf439d..6416d9b8e1 100644 --- a/client/pyproject.toml +++ b/client/pyproject.toml @@ -15,8 +15,7 @@ qtawesome = "0.7.3" [ayon.runtimeDependencies] aiohttp-middlewares = "^2.0.0" Click = "^8" -OpenTimelineIO = "0.17.0" -otio-burnins-adapter = "1.0.0" +OpenTimelineIO = "0.16.0" opencolorio = "^2.3.2,<2.4.0" Pillow = "9.5.0" websocket-client = ">=0.40.0,<2" From 6069471eff8703bee8e87c39dc13c8a5a8a4c160 Mon Sep 17 00:00:00 2001 From: Jakub Trllo <43494761+iLLiCiTiT@users.noreply.github.com> Date: Wed, 8 Oct 2025 11:38:20 +0200 Subject: [PATCH 11/59] use better method name --- client/ayon_core/plugins/publish/extract_thumbnail.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/client/ayon_core/plugins/publish/extract_thumbnail.py b/client/ayon_core/plugins/publish/extract_thumbnail.py index 943f169b1c..b5d2d8a82e 100644 --- a/client/ayon_core/plugins/publish/extract_thumbnail.py +++ b/client/ayon_core/plugins/publish/extract_thumbnail.py @@ -219,7 +219,7 @@ class ExtractThumbnail(pyblish.api.InstancePlugin): ) # If the input can read by OIIO then use OIIO method for # conversion otherwise use ffmpeg - repre_thumb_created = self._create_thumbnail_oiio( + repre_thumb_created = self._create_colorspace_thumbnail( full_input_path, full_output_path, colorspace_data @@ -382,7 +382,7 @@ class ExtractThumbnail(pyblish.api.InstancePlugin): return ext in IMAGE_EXTENSIONS or ext in VIDEO_EXTENSIONS - def _create_thumbnail_oiio( + def _create_colorspace_thumbnail( self, src_path, dst_path, From 0232e4641a69cd69f004a3dbb968c5008aebd927 Mon Sep 17 00:00:00 2001 From: Jakub Trllo <43494761+iLLiCiTiT@users.noreply.github.com> Date: Wed, 8 Oct 2025 11:38:37 +0200 Subject: [PATCH 12/59] remove irrelevant log --- client/ayon_core/plugins/publish/extract_thumbnail.py | 6 ------ 1 file changed, 6 deletions(-) diff --git a/client/ayon_core/plugins/publish/extract_thumbnail.py b/client/ayon_core/plugins/publish/extract_thumbnail.py index b5d2d8a82e..e796e35ae2 100644 --- a/client/ayon_core/plugins/publish/extract_thumbnail.py +++ b/client/ayon_core/plugins/publish/extract_thumbnail.py @@ -229,12 +229,6 @@ class ExtractThumbnail(pyblish.api.InstancePlugin): # oiiotool isn't available or representation is not having # colorspace data if not repre_thumb_created: - if oiio_supported: - self.log.debug( - "Converting with FFMPEG because input" - " can't be read by OIIO." - ) - repre_thumb_created = self._create_thumbnail_ffmpeg( full_input_path, full_output_path ) From c0ac022cf78c54f646e2f51d4b194653f7747158 Mon Sep 17 00:00:00 2001 From: Jakub Trllo <43494761+iLLiCiTiT@users.noreply.github.com> Date: Wed, 8 Oct 2025 11:38:48 +0200 Subject: [PATCH 13/59] fallback to oiio if ffmpeg conversion fails --- .../plugins/publish/extract_thumbnail.py | 45 ++++++++++++++++++- 1 file changed, 43 insertions(+), 2 deletions(-) diff --git a/client/ayon_core/plugins/publish/extract_thumbnail.py b/client/ayon_core/plugins/publish/extract_thumbnail.py index e796e35ae2..316d7a4ed9 100644 --- a/client/ayon_core/plugins/publish/extract_thumbnail.py +++ b/client/ayon_core/plugins/publish/extract_thumbnail.py @@ -6,6 +6,7 @@ import re import pyblish.api from ayon_core.lib import ( + get_oiio_tool_args, get_ffmpeg_tool_args, get_ffprobe_data, @@ -210,6 +211,12 @@ class ExtractThumbnail(pyblish.api.InstancePlugin): full_output_path = os.path.join(dst_staging, jpeg_file) colorspace_data = repre.get("colorspaceData") + # NOTE We should find out what is happening here. Why don't we + # use oiiotool all the time if it is available? Only possible + # reason might be that video files should be converted using + # ffmpeg, but other then that, we should use oiio all the time. + # - We should also probably get rid of the ffmpeg settings... + # only use OIIO if it is supported and representation has # colorspace data if oiio_supported and colorspace_data: @@ -234,6 +241,11 @@ class ExtractThumbnail(pyblish.api.InstancePlugin): ) # Skip representation and try next one if wasn't created + if not repre_thumb_created and oiio_supported: + repre_thumb_created = self._create_thumbnail_oiio( + full_input_path, full_output_path + ) + if not repre_thumb_created: continue @@ -449,9 +461,38 @@ class ExtractThumbnail(pyblish.api.InstancePlugin): return True + def _create_thumbnail_oiio(self, src_path, dst_path): + self.log.debug(f"Extracting thumbnail with OIIO: {dst_path}") + + try: + resolution_arg = self._get_resolution_arg("oiiotool", src_path) + except RuntimeError: + return False + + oiio_cmd = get_oiio_tool_args( + "oiiotool", + "-a", src_path, + "--ch", "R,G,B", + ) + oiio_cmd.extend(resolution_arg) + oiio_cmd.extend(("-o", dst_path)) + self.log.debug("Running: {}".format(" ".join(oiio_cmd))) + try: + run_subprocess(oiio_cmd, logger=self.log) + return True + except Exception: + self.log.warning( + "Failed to create thumbnail using oiiotool", + exc_info=True + ) + return False + def _create_thumbnail_ffmpeg(self, src_path, dst_path): - self.log.debug("Extracting thumbnail with FFMPEG: {}".format(dst_path)) - resolution_arg = self._get_resolution_arg("ffmpeg", src_path) + try: + resolution_arg = self._get_resolution_arg("ffmpeg", src_path) + except RuntimeError: + return False + ffmpeg_path_args = get_ffmpeg_tool_args("ffmpeg") ffmpeg_args = self.ffmpeg_args or {} From bb850e9bdcdf5c4a4fa3b2909d043b0533f3a1ed Mon Sep 17 00:00:00 2001 From: Jakub Trllo <43494761+iLLiCiTiT@users.noreply.github.com> Date: Wed, 8 Oct 2025 11:59:14 +0200 Subject: [PATCH 14/59] use review channels to create the thumbnail --- .../plugins/publish/extract_thumbnail.py | 16 +++++++++++++--- 1 file changed, 13 insertions(+), 3 deletions(-) diff --git a/client/ayon_core/plugins/publish/extract_thumbnail.py b/client/ayon_core/plugins/publish/extract_thumbnail.py index 316d7a4ed9..4553c1de86 100644 --- a/client/ayon_core/plugins/publish/extract_thumbnail.py +++ b/client/ayon_core/plugins/publish/extract_thumbnail.py @@ -16,7 +16,11 @@ from ayon_core.lib import ( path_to_subprocess_arg, run_subprocess, ) -from ayon_core.lib.transcoding import oiio_color_convert +from ayon_core.lib.transcoding import ( + oiio_color_convert, + get_oiio_input_and_channel_args, + get_oiio_info_for_input, +) from ayon_core.lib.transcoding import VIDEO_EXTENSIONS, IMAGE_EXTENSIONS @@ -469,10 +473,16 @@ class ExtractThumbnail(pyblish.api.InstancePlugin): except RuntimeError: return False + input_info = get_oiio_info_for_input(src_path, logger=self.log) + input_arg, channels_arg = get_oiio_input_and_channel_args(input_info) oiio_cmd = get_oiio_tool_args( "oiiotool", - "-a", src_path, - "--ch", "R,G,B", + input_arg, src_path, + # Tell oiiotool which channels should be put to top stack + # (and output) + "--ch", channels_arg, + # Use first subimage + "--subimage", "0" ) oiio_cmd.extend(resolution_arg) oiio_cmd.extend(("-o", dst_path)) From 455db40985044760b38014b442d5643ee4a58138 Mon Sep 17 00:00:00 2001 From: Jakub Trllo <43494761+iLLiCiTiT@users.noreply.github.com> Date: Wed, 8 Oct 2025 11:59:29 +0200 Subject: [PATCH 15/59] allow 'rgba' layer name to be used if is available --- client/ayon_core/lib/transcoding.py | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/client/ayon_core/lib/transcoding.py b/client/ayon_core/lib/transcoding.py index 75f0c8bc4d..77f383f7a8 100644 --- a/client/ayon_core/lib/transcoding.py +++ b/client/ayon_core/lib/transcoding.py @@ -420,12 +420,16 @@ def get_review_info_by_layer_name(channel_names): channel = last_part[0].upper() rgba_by_layer_name[layer_name][channel] = channel_name - # Put empty layer to the beginning of the list + # Put empty layer or 'rgba' to the beginning of the list # - if input has R, G, B, A channels they should be used for review if "" in layer_names_order: layer_names_order.remove("") layer_names_order.insert(0, "") + elif "rgba" in layer_names_order: + layer_names_order.remove("rgba") + layer_names_order.insert(0, "rgba") + output = [] for layer_name in layer_names_order: rgba_layer_info = rgba_by_layer_name[layer_name] From 0f7176c2d20d7a5460d5da9bb62eecd287945acb Mon Sep 17 00:00:00 2001 From: Jakub Trllo <43494761+iLLiCiTiT@users.noreply.github.com> Date: Wed, 8 Oct 2025 12:03:56 +0200 Subject: [PATCH 16/59] avoid duplicated code --- client/ayon_core/lib/transcoding.py | 13 ++++++------- 1 file changed, 6 insertions(+), 7 deletions(-) diff --git a/client/ayon_core/lib/transcoding.py b/client/ayon_core/lib/transcoding.py index 77f383f7a8..127bd3bac4 100644 --- a/client/ayon_core/lib/transcoding.py +++ b/client/ayon_core/lib/transcoding.py @@ -422,13 +422,12 @@ def get_review_info_by_layer_name(channel_names): # Put empty layer or 'rgba' to the beginning of the list # - if input has R, G, B, A channels they should be used for review - if "" in layer_names_order: - layer_names_order.remove("") - layer_names_order.insert(0, "") - - elif "rgba" in layer_names_order: - layer_names_order.remove("rgba") - layer_names_order.insert(0, "rgba") + # NOTE They are iterated in reversed order because they're inserted to + # the beginning of 'layer_names_order' -> last added will be first. + for name in reversed(["", "rgba"]): + if name in layer_names_order: + layer_names_order.remove(name) + layer_names_order.insert(0, name) output = [] for layer_name in layer_names_order: From 257a20c263886f8d4b16b48ae0f826c851ecf4a0 Mon Sep 17 00:00:00 2001 From: Jakub Trllo <43494761+iLLiCiTiT@users.noreply.github.com> Date: Wed, 8 Oct 2025 12:29:53 +0200 Subject: [PATCH 17/59] grammar fix Co-authored-by: Roy Nieterau --- client/ayon_core/plugins/publish/extract_thumbnail.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/client/ayon_core/plugins/publish/extract_thumbnail.py b/client/ayon_core/plugins/publish/extract_thumbnail.py index 4553c1de86..79876f7974 100644 --- a/client/ayon_core/plugins/publish/extract_thumbnail.py +++ b/client/ayon_core/plugins/publish/extract_thumbnail.py @@ -244,7 +244,7 @@ class ExtractThumbnail(pyblish.api.InstancePlugin): full_input_path, full_output_path ) - # Skip representation and try next one if wasn't created + # Skip representation and try next one if wasn't created if not repre_thumb_created and oiio_supported: repre_thumb_created = self._create_thumbnail_oiio( full_input_path, full_output_path From b508c3ffbb8364009c058cfcaa24e0c235bed928 Mon Sep 17 00:00:00 2001 From: Jakub Trllo <43494761+iLLiCiTiT@users.noreply.github.com> Date: Wed, 8 Oct 2025 14:09:20 +0200 Subject: [PATCH 18/59] add warning logs if thumbnail creation fails --- client/ayon_core/plugins/publish/extract_thumbnail.py | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/client/ayon_core/plugins/publish/extract_thumbnail.py b/client/ayon_core/plugins/publish/extract_thumbnail.py index 79876f7974..b5885178d0 100644 --- a/client/ayon_core/plugins/publish/extract_thumbnail.py +++ b/client/ayon_core/plugins/publish/extract_thumbnail.py @@ -471,6 +471,9 @@ class ExtractThumbnail(pyblish.api.InstancePlugin): try: resolution_arg = self._get_resolution_arg("oiiotool", src_path) except RuntimeError: + self.log.warning( + "Failed to create thumbnail using oiio", exc_info=True + ) return False input_info = get_oiio_info_for_input(src_path, logger=self.log) @@ -501,6 +504,9 @@ class ExtractThumbnail(pyblish.api.InstancePlugin): try: resolution_arg = self._get_resolution_arg("ffmpeg", src_path) except RuntimeError: + self.log.warning( + "Failed to create thumbnail using ffmpeg", exc_info=True + ) return False ffmpeg_path_args = get_ffmpeg_tool_args("ffmpeg") From e6db46d0e43ffa95d1485d6559eb81f71c2487dd Mon Sep 17 00:00:00 2001 From: Ynbot Date: Wed, 8 Oct 2025 13:32:34 +0000 Subject: [PATCH 19/59] [Automated] Add generated package files from main --- client/ayon_core/version.py | 2 +- package.py | 2 +- pyproject.toml | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/client/ayon_core/version.py b/client/ayon_core/version.py index cb43cd72c3..89f69f50e1 100644 --- a/client/ayon_core/version.py +++ b/client/ayon_core/version.py @@ -1,3 +1,3 @@ # -*- coding: utf-8 -*- """Package declaring AYON addon 'core' version.""" -__version__ = "1.6.3+dev" +__version__ = "1.6.4" diff --git a/package.py b/package.py index 5101503403..f001460889 100644 --- a/package.py +++ b/package.py @@ -1,6 +1,6 @@ name = "core" title = "Core" -version = "1.6.3+dev" +version = "1.6.4" client_dir = "ayon_core" diff --git a/pyproject.toml b/pyproject.toml index cde88e0941..2473ecc9fd 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -5,7 +5,7 @@ [tool.poetry] name = "ayon-core" -version = "1.6.3+dev" +version = "1.6.4" description = "" authors = ["Ynput Team "] readme = "README.md" From 6c44eca710288ec481b1a30540b699cd65ba15d3 Mon Sep 17 00:00:00 2001 From: Ynbot Date: Wed, 8 Oct 2025 13:33:10 +0000 Subject: [PATCH 20/59] [Automated] Update version in package.py for develop --- client/ayon_core/version.py | 2 +- package.py | 2 +- pyproject.toml | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/client/ayon_core/version.py b/client/ayon_core/version.py index 89f69f50e1..bbced6b641 100644 --- a/client/ayon_core/version.py +++ b/client/ayon_core/version.py @@ -1,3 +1,3 @@ # -*- coding: utf-8 -*- """Package declaring AYON addon 'core' version.""" -__version__ = "1.6.4" +__version__ = "1.6.4+dev" diff --git a/package.py b/package.py index f001460889..114f7d12ef 100644 --- a/package.py +++ b/package.py @@ -1,6 +1,6 @@ name = "core" title = "Core" -version = "1.6.4" +version = "1.6.4+dev" client_dir = "ayon_core" diff --git a/pyproject.toml b/pyproject.toml index 2473ecc9fd..44c6a9d73c 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -5,7 +5,7 @@ [tool.poetry] name = "ayon-core" -version = "1.6.4" +version = "1.6.4+dev" description = "" authors = ["Ynput Team "] readme = "README.md" From 5631e07174d06f0e63668955fbd08f4acd8342ea Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" Date: Wed, 8 Oct 2025 13:34:09 +0000 Subject: [PATCH 21/59] chore(): update bug report / version --- .github/ISSUE_TEMPLATE/bug_report.yml | 1 + 1 file changed, 1 insertion(+) diff --git a/.github/ISSUE_TEMPLATE/bug_report.yml b/.github/ISSUE_TEMPLATE/bug_report.yml index e84522395d..27ed2217dd 100644 --- a/.github/ISSUE_TEMPLATE/bug_report.yml +++ b/.github/ISSUE_TEMPLATE/bug_report.yml @@ -35,6 +35,7 @@ body: label: Version description: What version are you running? Look to AYON Tray options: + - 1.6.4 - 1.6.3 - 1.6.2 - 1.6.1 From e98e3a1d99c7d67f2b88e2b981bb9b5d5df70696 Mon Sep 17 00:00:00 2001 From: Vahan Sosoyan Date: Thu, 9 Oct 2025 18:16:17 +0400 Subject: [PATCH 22/59] Fix typo --- client/ayon_core/scripts/otio_burnin.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/client/ayon_core/scripts/otio_burnin.py b/client/ayon_core/scripts/otio_burnin.py index 737faa7fe4..bd94225979 100644 --- a/client/ayon_core/scripts/otio_burnin.py +++ b/client/ayon_core/scripts/otio_burnin.py @@ -51,7 +51,7 @@ def _drawtext(align, resolution, text, options): elif align in (ffmpeg_burnins.TOP_RIGHT, ffmpeg_burnins.BOTTOM_RIGHT): ifont = ImageFont.truetype(options["font"], options["font_size"]) - if hasattr(ifont, "getbox"): + if hasattr(ifont, "getbbox"): left, top, right, bottom = ifont.getbbox(text) box_size = right - left, bottom - top else: From afb0b082fd847c2e160f13798a00c0dfb0a608b9 Mon Sep 17 00:00:00 2001 From: Jakub Trllo <43494761+iLLiCiTiT@users.noreply.github.com> Date: Fri, 10 Oct 2025 13:29:35 +0200 Subject: [PATCH 23/59] just set minimum size --- client/ayon_core/tools/utils/dialogs.py | 16 +++++----------- 1 file changed, 5 insertions(+), 11 deletions(-) diff --git a/client/ayon_core/tools/utils/dialogs.py b/client/ayon_core/tools/utils/dialogs.py index 5dd0ddd54e..e6df68c168 100644 --- a/client/ayon_core/tools/utils/dialogs.py +++ b/client/ayon_core/tools/utils/dialogs.py @@ -49,8 +49,6 @@ class ScrollMessageBox(QtWidgets.QDialog): self.setWindowFlags(QtCore.Qt.WindowTitleHint) - layout = QtWidgets.QVBoxLayout(self) - scroll_widget = QtWidgets.QScrollArea(self) scroll_widget.setWidgetResizable(True) content_widget = QtWidgets.QWidget(self) @@ -63,14 +61,8 @@ class ScrollMessageBox(QtWidgets.QDialog): content_layout.addWidget(label_widget) message_len = max(message_len, len(message)) - # guess size of scrollable area - # WARNING: 'desktop' method probably won't work in PySide6 - desktop = QtWidgets.QApplication.desktop() - max_width = desktop.availableGeometry().width() - scroll_widget.setMinimumWidth( - min(max_width, message_len * 6) - ) - layout.addWidget(scroll_widget) + # Set minimum width + scroll_widget.setMinimumWidth(360) buttons = QtWidgets.QDialogButtonBox.Ok if cancelable: @@ -86,7 +78,9 @@ class ScrollMessageBox(QtWidgets.QDialog): btn.clicked.connect(self._on_copy_click) btn_box.addButton(btn, QtWidgets.QDialogButtonBox.NoRole) - layout.addWidget(btn_box) + main_layout = QtWidgets.QVBoxLayout(self) + main_layout.addWidget(scroll_widget, 1) + main_layout.addWidget(btn_box, 0) def _on_copy_click(self): clipboard = QtWidgets.QApplication.clipboard() From abcb4fe3e42270bc30082f3ce138948f1852922a Mon Sep 17 00:00:00 2001 From: Jakub Trllo <43494761+iLLiCiTiT@users.noreply.github.com> Date: Fri, 10 Oct 2025 13:29:42 +0200 Subject: [PATCH 24/59] use py3 super --- client/ayon_core/tools/utils/dialogs.py | 10 ++++------ 1 file changed, 4 insertions(+), 6 deletions(-) diff --git a/client/ayon_core/tools/utils/dialogs.py b/client/ayon_core/tools/utils/dialogs.py index e6df68c168..6dc3cf1d8b 100644 --- a/client/ayon_core/tools/utils/dialogs.py +++ b/client/ayon_core/tools/utils/dialogs.py @@ -41,7 +41,7 @@ class ScrollMessageBox(QtWidgets.QDialog): """ def __init__(self, icon, title, messages, cancelable=False): - super(ScrollMessageBox, self).__init__() + super().__init__() self.setWindowTitle(title) self.icon = icon @@ -98,7 +98,7 @@ class SimplePopup(QtWidgets.QDialog): on_clicked = QtCore.Signal() def __init__(self, parent=None, *args, **kwargs): - super(SimplePopup, self).__init__(parent=parent, *args, **kwargs) + super().__init__(parent=parent, *args, **kwargs) # Set default title self.setWindowTitle("Popup") @@ -155,7 +155,7 @@ class SimplePopup(QtWidgets.QDialog): geo = self._calculate_window_geometry() self.setGeometry(geo) - return super(SimplePopup, self).showEvent(event) + return super().showEvent(event) def _on_clicked(self): """Callback for when the 'show' button is clicked. @@ -222,9 +222,7 @@ class PopupUpdateKeys(SimplePopup): on_clicked_state = QtCore.Signal(bool) def __init__(self, parent=None, *args, **kwargs): - super(PopupUpdateKeys, self).__init__( - parent=parent, *args, **kwargs - ) + super().__init__(parent=parent, *args, **kwargs) layout = self.layout() From b7822123289e789776c91b19a0a69b4fa3757a5c Mon Sep 17 00:00:00 2001 From: Petr Kalis Date: Fri, 10 Oct 2025 16:04:20 +0200 Subject: [PATCH 25/59] Extracted gap filling from last version --- client/ayon_core/lib/plugin_tools.py | 97 +++++++++++++++++++ .../plugins/publish/extract_review.py | 91 +---------------- 2 files changed, 99 insertions(+), 89 deletions(-) diff --git a/client/ayon_core/lib/plugin_tools.py b/client/ayon_core/lib/plugin_tools.py index 654bc7ac4a..1bc5824b86 100644 --- a/client/ayon_core/lib/plugin_tools.py +++ b/client/ayon_core/lib/plugin_tools.py @@ -4,6 +4,15 @@ import os import logging import re import collections +from typing import Optional, Any, Tuple +import clique +import speedcopy + +import ayon_api +import pyblish.api + +from ayon_api import get_last_version_by_product_name, get_representations + log = logging.getLogger(__name__) @@ -151,3 +160,91 @@ def source_hash(filepath, *args): time = str(os.path.getmtime(filepath)) size = str(os.path.getsize(filepath)) return "|".join([file_name, time, size] + list(args)).replace(".", ",") + + +def fill_sequence_gaps_with_previous( + collection: str, + staging_dir: str, + instance: pyblish.plugin.Instance, + current_repre_name: str, + start_frame: int, + end_frame: int +) -> Tuple[dict[str, Any], Optional[dict[int, str]]]: + """Tries to replace missing frames from ones from last version""" + used_version_entity, repre_file_paths = _get_last_version_files( + instance, current_repre_name + ) + if repre_file_paths is None: + # issues in getting last version files + return (None, None) + + prev_collection = clique.assemble( + repre_file_paths, + patterns=[clique.PATTERNS["frames"]], + minimum_items=1 + )[0][0] + prev_col_format = prev_collection.format("{head}{padding}{tail}") + + added_files = {} + anatomy = instance.context.data["anatomy"] + col_format = collection.format("{head}{padding}{tail}") + for frame in range(start_frame, end_frame + 1): + if frame in collection.indexes: + continue + hole_fpath = os.path.join(staging_dir, col_format % frame) + + previous_version_path = prev_col_format % frame + previous_version_path = anatomy.fill_root(previous_version_path) + if not os.path.exists(previous_version_path): + log.warning( + "Missing frame should be replaced from " + f"'{previous_version_path}' but that doesn't exist. " + "Falling back to filling from currently last rendered." + ) + return (None, None) + + log.warning( + f"Replacing missing '{hole_fpath}' with " + f"'{previous_version_path}'" + ) + speedcopy.copyfile(previous_version_path, hole_fpath) + added_files[frame] = hole_fpath + + return (used_version_entity, added_files) + + +def _get_last_version_files( + instance: pyblish.plugin.Instance, + current_repre_name: str, +): + product_name = instance.data["productName"] + project_name = instance.data["projectEntity"]["name"] + folder_entity = instance.data["folderEntity"] + + version_entity = get_last_version_by_product_name( + project_name, + product_name, + folder_entity["id"], + fields={"id"} + ) + + if not version_entity: + return (None, None) + + matching_repres = get_representations( + project_name, + version_ids=[version_entity["id"]], + representation_names=[current_repre_name], + fields={"files"} + ) + + if not matching_repres: + return None + matching_repre = list(matching_repres)[0] + + repre_file_paths = [ + file_info["path"] + for file_info in matching_repre["files"] + ] + + return (version_entity, repre_file_paths) diff --git a/client/ayon_core/plugins/publish/extract_review.py b/client/ayon_core/plugins/publish/extract_review.py index 04e534054e..535f8ab6cf 100644 --- a/client/ayon_core/plugins/publish/extract_review.py +++ b/client/ayon_core/plugins/publish/extract_review.py @@ -13,14 +13,13 @@ import clique import speedcopy import pyblish.api -from ayon_api import get_last_version_by_product_name, get_representations - from ayon_core.lib import ( get_ffmpeg_tool_args, filter_profiles, path_to_subprocess_arg, run_subprocess, ) +from ayon_core.lib.plugin_tools import fill_sequence_gaps_with_previous from ayon_core.lib.transcoding import ( IMAGE_EXTENSIONS, get_ffprobe_streams, @@ -511,7 +510,7 @@ class ExtractReview(pyblish.api.InstancePlugin): temp_data=temp_data ) elif fill_missing_frames == "previous_version": - new_frame_files = self.fill_sequence_gaps_with_previous( + _, new_frame_files = fill_sequence_gaps_with_previous( collection=collection, staging_dir=new_repre["stagingDir"], instance=instance, @@ -1050,92 +1049,6 @@ class ExtractReview(pyblish.api.InstancePlugin): return all_args - def fill_sequence_gaps_with_previous( - self, - collection: str, - staging_dir: str, - instance: pyblish.plugin.Instance, - current_repre_name: str, - start_frame: int, - end_frame: int - ) -> Optional[dict[int, str]]: - """Tries to replace missing frames from ones from last version""" - repre_file_paths = self._get_last_version_files( - instance, current_repre_name) - if repre_file_paths is None: - # issues in getting last version files, falling back - return None - - prev_collection = clique.assemble( - repre_file_paths, - patterns=[clique.PATTERNS["frames"]], - minimum_items=1 - )[0][0] - prev_col_format = prev_collection.format("{head}{padding}{tail}") - - added_files = {} - anatomy = instance.context.data["anatomy"] - col_format = collection.format("{head}{padding}{tail}") - for frame in range(start_frame, end_frame + 1): - if frame in collection.indexes: - continue - hole_fpath = os.path.join(staging_dir, col_format % frame) - - previous_version_path = prev_col_format % frame - previous_version_path = anatomy.fill_root(previous_version_path) - if not os.path.exists(previous_version_path): - self.log.warning( - "Missing frame should be replaced from " - f"'{previous_version_path}' but that doesn't exist. " - "Falling back to filling from currently last rendered." - ) - return None - - self.log.warning( - f"Replacing missing '{hole_fpath}' with " - f"'{previous_version_path}'" - ) - speedcopy.copyfile(previous_version_path, hole_fpath) - added_files[frame] = hole_fpath - - return added_files - - def _get_last_version_files( - self, - instance: pyblish.plugin.Instance, - current_repre_name: str, - ): - product_name = instance.data["productName"] - project_name = instance.data["projectEntity"]["name"] - folder_entity = instance.data["folderEntity"] - - version_entity = get_last_version_by_product_name( - project_name, - product_name, - folder_entity["id"], - fields={"id"} - ) - if not version_entity: - return None - - matching_repres = get_representations( - project_name, - version_ids=[version_entity["id"]], - representation_names=[current_repre_name], - fields={"files"} - ) - - if not matching_repres: - return None - matching_repre = list(matching_repres)[0] - - repre_file_paths = [ - file_info["path"] - for file_info in matching_repre["files"] - ] - - return repre_file_paths - def fill_sequence_gaps_with_blanks( self, collection: str, From a7209e68f0b0142d138f18e88656470354f8ad0b Mon Sep 17 00:00:00 2001 From: Petr Kalis Date: Fri, 10 Oct 2025 16:05:04 +0200 Subject: [PATCH 26/59] Push through reuseLastVersion value to deadline metadata --- client/ayon_core/pipeline/farm/pyblish_functions.py | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/client/ayon_core/pipeline/farm/pyblish_functions.py b/client/ayon_core/pipeline/farm/pyblish_functions.py index 0d8e70f9d2..4e9f9ed601 100644 --- a/client/ayon_core/pipeline/farm/pyblish_functions.py +++ b/client/ayon_core/pipeline/farm/pyblish_functions.py @@ -249,7 +249,8 @@ def create_skeleton_instance( # map inputVersions `ObjectId` -> `str` so json supports it "inputVersions": list(map(str, data.get("inputVersions", []))), "colorspace": data.get("colorspace"), - "hasExplicitFrames": data.get("hasExplicitFrames") + "hasExplicitFrames": data.get("hasExplicitFrames") or False, + "reuseLastVersion": data.get("reuseLastVersion") or False } if data.get("renderlayer"): From 3a0ba21117d53fc8120f29a6c5a90f7da3df6e9c Mon Sep 17 00:00:00 2001 From: Petr Kalis Date: Fri, 10 Oct 2025 16:17:31 +0200 Subject: [PATCH 27/59] Return attrib for frameStart query --- client/ayon_core/lib/plugin_tools.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/client/ayon_core/lib/plugin_tools.py b/client/ayon_core/lib/plugin_tools.py index 1bc5824b86..1ee8f673e0 100644 --- a/client/ayon_core/lib/plugin_tools.py +++ b/client/ayon_core/lib/plugin_tools.py @@ -225,7 +225,7 @@ def _get_last_version_files( project_name, product_name, folder_entity["id"], - fields={"id"} + fields={"id", "attrib"} ) if not version_entity: From 98d8417c737ba5faaecab2dd5adfb78c4300af35 Mon Sep 17 00:00:00 2001 From: Petr Kalis Date: Fri, 10 Oct 2025 16:36:44 +0200 Subject: [PATCH 28/59] Removed confusing message --- client/ayon_core/lib/plugin_tools.py | 1 - 1 file changed, 1 deletion(-) diff --git a/client/ayon_core/lib/plugin_tools.py b/client/ayon_core/lib/plugin_tools.py index 1ee8f673e0..ec7668bdbf 100644 --- a/client/ayon_core/lib/plugin_tools.py +++ b/client/ayon_core/lib/plugin_tools.py @@ -199,7 +199,6 @@ def fill_sequence_gaps_with_previous( log.warning( "Missing frame should be replaced from " f"'{previous_version_path}' but that doesn't exist. " - "Falling back to filling from currently last rendered." ) return (None, None) From 29baac0d306969973226f7e20a20682a6e86b8b4 Mon Sep 17 00:00:00 2001 From: Petr Kalis Date: Fri, 10 Oct 2025 16:38:43 +0200 Subject: [PATCH 29/59] Moved message where it makes sense --- client/ayon_core/plugins/publish/extract_review.py | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/client/ayon_core/plugins/publish/extract_review.py b/client/ayon_core/plugins/publish/extract_review.py index 535f8ab6cf..fac68a511a 100644 --- a/client/ayon_core/plugins/publish/extract_review.py +++ b/client/ayon_core/plugins/publish/extract_review.py @@ -520,6 +520,10 @@ class ExtractReview(pyblish.api.InstancePlugin): ) # fallback to original workflow if new_frame_files is None: + self.log.warning( + "Falling back to filling from currently " + "last rendered." + ) new_frame_files = ( self.fill_sequence_gaps_from_existing( collection=collection, From c046588ea8e6a1caf9d610ae6569bda3e3cd4e6d Mon Sep 17 00:00:00 2001 From: Petr Kalis Date: Fri, 10 Oct 2025 16:40:38 +0200 Subject: [PATCH 30/59] Ruff --- client/ayon_core/lib/plugin_tools.py | 1 - 1 file changed, 1 deletion(-) diff --git a/client/ayon_core/lib/plugin_tools.py b/client/ayon_core/lib/plugin_tools.py index ec7668bdbf..117083a9c9 100644 --- a/client/ayon_core/lib/plugin_tools.py +++ b/client/ayon_core/lib/plugin_tools.py @@ -8,7 +8,6 @@ from typing import Optional, Any, Tuple import clique import speedcopy -import ayon_api import pyblish.api from ayon_api import get_last_version_by_product_name, get_representations From ef0af72632b74170f1bf7b381dac093b234f4f9b Mon Sep 17 00:00:00 2001 From: Petr Kalis Date: Mon, 13 Oct 2025 13:33:12 +0200 Subject: [PATCH 31/59] Updated typin Co-authored-by: Jakub Trllo <43494761+iLLiCiTiT@users.noreply.github.com> --- client/ayon_core/lib/plugin_tools.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/client/ayon_core/lib/plugin_tools.py b/client/ayon_core/lib/plugin_tools.py index 117083a9c9..122d61c726 100644 --- a/client/ayon_core/lib/plugin_tools.py +++ b/client/ayon_core/lib/plugin_tools.py @@ -168,7 +168,7 @@ def fill_sequence_gaps_with_previous( current_repre_name: str, start_frame: int, end_frame: int -) -> Tuple[dict[str, Any], Optional[dict[int, str]]]: +) -> tuple[Optional[dict[str, Any]], Optional[dict[int, str]]]: """Tries to replace missing frames from ones from last version""" used_version_entity, repre_file_paths = _get_last_version_files( instance, current_repre_name From 951ea6286b1babfef3ab46e28fa88d8a574e1273 Mon Sep 17 00:00:00 2001 From: Petr Kalis Date: Mon, 13 Oct 2025 13:33:32 +0200 Subject: [PATCH 32/59] Removed unneeded import Co-authored-by: Jakub Trllo <43494761+iLLiCiTiT@users.noreply.github.com> --- client/ayon_core/lib/plugin_tools.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/client/ayon_core/lib/plugin_tools.py b/client/ayon_core/lib/plugin_tools.py index 122d61c726..3931e98777 100644 --- a/client/ayon_core/lib/plugin_tools.py +++ b/client/ayon_core/lib/plugin_tools.py @@ -4,7 +4,7 @@ import os import logging import re import collections -from typing import Optional, Any, Tuple +from typing import Optional, Any import clique import speedcopy From afe863e36b0d86b60676b226badc7e23e88cac73 Mon Sep 17 00:00:00 2001 From: Petr Kalis Date: Mon, 13 Oct 2025 13:34:07 +0200 Subject: [PATCH 33/59] Removed unnecessary parentheses Co-authored-by: Jakub Trllo <43494761+iLLiCiTiT@users.noreply.github.com> --- client/ayon_core/lib/plugin_tools.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/client/ayon_core/lib/plugin_tools.py b/client/ayon_core/lib/plugin_tools.py index 3931e98777..eff66fecfe 100644 --- a/client/ayon_core/lib/plugin_tools.py +++ b/client/ayon_core/lib/plugin_tools.py @@ -227,7 +227,7 @@ def _get_last_version_files( ) if not version_entity: - return (None, None) + return None, None matching_repres = get_representations( project_name, From 9a0f4b72e3e7fe2220202c4236fa848314bd89cb Mon Sep 17 00:00:00 2001 From: Petr Kalis Date: Mon, 13 Oct 2025 13:34:53 +0200 Subject: [PATCH 34/59] Formatting change Co-authored-by: Jakub Trllo <43494761+iLLiCiTiT@users.noreply.github.com> --- client/ayon_core/pipeline/farm/pyblish_functions.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/client/ayon_core/pipeline/farm/pyblish_functions.py b/client/ayon_core/pipeline/farm/pyblish_functions.py index 4e9f9ed601..a5053844b9 100644 --- a/client/ayon_core/pipeline/farm/pyblish_functions.py +++ b/client/ayon_core/pipeline/farm/pyblish_functions.py @@ -249,8 +249,8 @@ def create_skeleton_instance( # map inputVersions `ObjectId` -> `str` so json supports it "inputVersions": list(map(str, data.get("inputVersions", []))), "colorspace": data.get("colorspace"), - "hasExplicitFrames": data.get("hasExplicitFrames") or False, - "reuseLastVersion": data.get("reuseLastVersion") or False + "hasExplicitFrames": data.get("hasExplicitFrames", False), + "reuseLastVersion": data.get("reuseLastVersion", False), } if data.get("renderlayer"): From c3de53ae5e85a367487dc7a9d0cda3ab699589e7 Mon Sep 17 00:00:00 2001 From: Petr Kalis Date: Mon, 13 Oct 2025 13:35:09 +0200 Subject: [PATCH 35/59] Removed import Co-authored-by: Jakub Trllo <43494761+iLLiCiTiT@users.noreply.github.com> --- client/ayon_core/lib/plugin_tools.py | 2 -- 1 file changed, 2 deletions(-) diff --git a/client/ayon_core/lib/plugin_tools.py b/client/ayon_core/lib/plugin_tools.py index eff66fecfe..3b39567207 100644 --- a/client/ayon_core/lib/plugin_tools.py +++ b/client/ayon_core/lib/plugin_tools.py @@ -8,8 +8,6 @@ from typing import Optional, Any import clique import speedcopy -import pyblish.api - from ayon_api import get_last_version_by_product_name, get_representations From 1f88b90cbabbcaaaa53392a9c1ad40a3e9ceddd0 Mon Sep 17 00:00:00 2001 From: Petr Kalis Date: Mon, 13 Oct 2025 13:35:28 +0200 Subject: [PATCH 36/59] Added return type Co-authored-by: Jakub Trllo <43494761+iLLiCiTiT@users.noreply.github.com> --- client/ayon_core/lib/plugin_tools.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/client/ayon_core/lib/plugin_tools.py b/client/ayon_core/lib/plugin_tools.py index 3b39567207..dc371a9ed1 100644 --- a/client/ayon_core/lib/plugin_tools.py +++ b/client/ayon_core/lib/plugin_tools.py @@ -212,7 +212,7 @@ def fill_sequence_gaps_with_previous( def _get_last_version_files( instance: pyblish.plugin.Instance, current_repre_name: str, -): +) -> tuple[Optional[dict[str, Any], Optional[list[str]]]: product_name = instance.data["productName"] project_name = instance.data["projectEntity"]["name"] folder_entity = instance.data["folderEntity"] From 1da4abc9bd87aefed1fadd2cb5a219c9c86a56fc Mon Sep 17 00:00:00 2001 From: Petr Kalis Date: Mon, 13 Oct 2025 13:35:46 +0200 Subject: [PATCH 37/59] Fixed return Co-authored-by: Jakub Trllo <43494761+iLLiCiTiT@users.noreply.github.com> --- client/ayon_core/lib/plugin_tools.py | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/client/ayon_core/lib/plugin_tools.py b/client/ayon_core/lib/plugin_tools.py index dc371a9ed1..676d3e43b5 100644 --- a/client/ayon_core/lib/plugin_tools.py +++ b/client/ayon_core/lib/plugin_tools.py @@ -234,9 +234,10 @@ def _get_last_version_files( fields={"files"} ) - if not matching_repres: - return None - matching_repre = list(matching_repres)[0] + matching_repre = next(matching_repres, None) + if not matching_repre: + return None, None + repre_file_paths = [ file_info["path"] From bd4381fe9b22ede0b70bbb4b0343c9e19caa3d73 Mon Sep 17 00:00:00 2001 From: Petr Kalis Date: Mon, 13 Oct 2025 13:45:24 +0200 Subject: [PATCH 38/59] Moved fill_sequence_gaps_with_previous --- client/ayon_core/lib/plugin_tools.py | 96 ------------------------ client/ayon_core/pipeline/publish/lib.py | 95 ++++++++++++++++++++++- 2 files changed, 94 insertions(+), 97 deletions(-) diff --git a/client/ayon_core/lib/plugin_tools.py b/client/ayon_core/lib/plugin_tools.py index 676d3e43b5..b19fe1e200 100644 --- a/client/ayon_core/lib/plugin_tools.py +++ b/client/ayon_core/lib/plugin_tools.py @@ -1,17 +1,9 @@ # -*- coding: utf-8 -*- """AYON plugin tools.""" import os -import logging import re import collections -from typing import Optional, Any -import clique -import speedcopy -from ayon_api import get_last_version_by_product_name, get_representations - - -log = logging.getLogger(__name__) CAPITALIZE_REGEX = re.compile(r"[a-zA-Z0-9]") @@ -157,91 +149,3 @@ def source_hash(filepath, *args): time = str(os.path.getmtime(filepath)) size = str(os.path.getsize(filepath)) return "|".join([file_name, time, size] + list(args)).replace(".", ",") - - -def fill_sequence_gaps_with_previous( - collection: str, - staging_dir: str, - instance: pyblish.plugin.Instance, - current_repre_name: str, - start_frame: int, - end_frame: int -) -> tuple[Optional[dict[str, Any]], Optional[dict[int, str]]]: - """Tries to replace missing frames from ones from last version""" - used_version_entity, repre_file_paths = _get_last_version_files( - instance, current_repre_name - ) - if repre_file_paths is None: - # issues in getting last version files - return (None, None) - - prev_collection = clique.assemble( - repre_file_paths, - patterns=[clique.PATTERNS["frames"]], - minimum_items=1 - )[0][0] - prev_col_format = prev_collection.format("{head}{padding}{tail}") - - added_files = {} - anatomy = instance.context.data["anatomy"] - col_format = collection.format("{head}{padding}{tail}") - for frame in range(start_frame, end_frame + 1): - if frame in collection.indexes: - continue - hole_fpath = os.path.join(staging_dir, col_format % frame) - - previous_version_path = prev_col_format % frame - previous_version_path = anatomy.fill_root(previous_version_path) - if not os.path.exists(previous_version_path): - log.warning( - "Missing frame should be replaced from " - f"'{previous_version_path}' but that doesn't exist. " - ) - return (None, None) - - log.warning( - f"Replacing missing '{hole_fpath}' with " - f"'{previous_version_path}'" - ) - speedcopy.copyfile(previous_version_path, hole_fpath) - added_files[frame] = hole_fpath - - return (used_version_entity, added_files) - - -def _get_last_version_files( - instance: pyblish.plugin.Instance, - current_repre_name: str, -) -> tuple[Optional[dict[str, Any], Optional[list[str]]]: - product_name = instance.data["productName"] - project_name = instance.data["projectEntity"]["name"] - folder_entity = instance.data["folderEntity"] - - version_entity = get_last_version_by_product_name( - project_name, - product_name, - folder_entity["id"], - fields={"id", "attrib"} - ) - - if not version_entity: - return None, None - - matching_repres = get_representations( - project_name, - version_ids=[version_entity["id"]], - representation_names=[current_repre_name], - fields={"files"} - ) - - matching_repre = next(matching_repres, None) - if not matching_repre: - return None, None - - - repre_file_paths = [ - file_info["path"] - for file_info in matching_repre["files"] - ] - - return (version_entity, repre_file_paths) diff --git a/client/ayon_core/pipeline/publish/lib.py b/client/ayon_core/pipeline/publish/lib.py index 3b82d961f8..4d555ae48b 100644 --- a/client/ayon_core/pipeline/publish/lib.py +++ b/client/ayon_core/pipeline/publish/lib.py @@ -7,7 +7,10 @@ import copy import warnings import hashlib import xml.etree.ElementTree -from typing import TYPE_CHECKING, Optional, Union, List +from typing import TYPE_CHECKING, Optional, Union, List, Any +import clique +import speedcopy +import logging import ayon_api import pyblish.util @@ -27,6 +30,7 @@ from .constants import ( DEFAULT_PUBLISH_TEMPLATE, DEFAULT_HERO_PUBLISH_TEMPLATE, ) +from ayon_api import get_last_version_by_product_name, get_representations if TYPE_CHECKING: from ayon_core.pipeline.traits import Representation @@ -34,6 +38,8 @@ if TYPE_CHECKING: TRAIT_INSTANCE_KEY: str = "representations_with_traits" +log = logging.getLogger(__name__) + def get_template_name_profiles( project_name, project_settings=None, logger=None @@ -1143,3 +1149,90 @@ def get_trait_representations( """ return instance.data.get(TRAIT_INSTANCE_KEY, []) + + +def fill_sequence_gaps_with_previous( + collection: str, + staging_dir: str, + instance: pyblish.plugin.Instance, + current_repre_name: str, + start_frame: int, + end_frame: int +) -> tuple[Optional[dict[str, Any]], Optional[dict[int, str]]]: + """Tries to replace missing frames from ones from last version""" + used_version_entity, repre_file_paths = _get_last_version_files( + instance, current_repre_name + ) + if repre_file_paths is None: + # issues in getting last version files + return (None, None) + + prev_collection = clique.assemble( + repre_file_paths, + patterns=[clique.PATTERNS["frames"]], + minimum_items=1 + )[0][0] + prev_col_format = prev_collection.format("{head}{padding}{tail}") + + added_files = {} + anatomy = instance.context.data["anatomy"] + col_format = collection.format("{head}{padding}{tail}") + for frame in range(start_frame, end_frame + 1): + if frame in collection.indexes: + continue + hole_fpath = os.path.join(staging_dir, col_format % frame) + + previous_version_path = prev_col_format % frame + previous_version_path = anatomy.fill_root(previous_version_path) + if not os.path.exists(previous_version_path): + log.warning( + "Missing frame should be replaced from " + f"'{previous_version_path}' but that doesn't exist. " + ) + return (None, None) + + log.warning( + f"Replacing missing '{hole_fpath}' with " + f"'{previous_version_path}'" + ) + speedcopy.copyfile(previous_version_path, hole_fpath) + added_files[frame] = hole_fpath + + return (used_version_entity, added_files) + + +def _get_last_version_files( + instance: pyblish.plugin.Instance, + current_repre_name: str, +) -> tuple[Optional[dict[str, Any]], Optional[list[str]]]: + product_name = instance.data["productName"] + project_name = instance.data["projectEntity"]["name"] + folder_entity = instance.data["folderEntity"] + + version_entity = get_last_version_by_product_name( + project_name, + product_name, + folder_entity["id"], + fields={"id", "attrib"} + ) + + if not version_entity: + return None, None + + matching_repres = get_representations( + project_name, + version_ids=[version_entity["id"]], + representation_names=[current_repre_name], + fields={"files"} + ) + + matching_repre = next(matching_repres, None) + if not matching_repre: + return None, None + + repre_file_paths = [ + file_info["path"] + for file_info in matching_repre["files"] + ] + + return (version_entity, repre_file_paths) From 949cfc75a61b5a1c14eeec40d9153e56c7da4331 Mon Sep 17 00:00:00 2001 From: Petr Kalis Date: Mon, 13 Oct 2025 13:47:14 +0200 Subject: [PATCH 39/59] Renamed fill_sequence_gaps_with_previous --- client/ayon_core/pipeline/publish/lib.py | 2 +- client/ayon_core/plugins/publish/extract_review.py | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/client/ayon_core/pipeline/publish/lib.py b/client/ayon_core/pipeline/publish/lib.py index 4d555ae48b..657a57226d 100644 --- a/client/ayon_core/pipeline/publish/lib.py +++ b/client/ayon_core/pipeline/publish/lib.py @@ -1151,7 +1151,7 @@ def get_trait_representations( return instance.data.get(TRAIT_INSTANCE_KEY, []) -def fill_sequence_gaps_with_previous( +def fill_sequence_gaps_with_previous_version( collection: str, staging_dir: str, instance: pyblish.plugin.Instance, diff --git a/client/ayon_core/plugins/publish/extract_review.py b/client/ayon_core/plugins/publish/extract_review.py index fac68a511a..fe0e7d4e3b 100644 --- a/client/ayon_core/plugins/publish/extract_review.py +++ b/client/ayon_core/plugins/publish/extract_review.py @@ -19,7 +19,7 @@ from ayon_core.lib import ( path_to_subprocess_arg, run_subprocess, ) -from ayon_core.lib.plugin_tools import fill_sequence_gaps_with_previous +from ayon_core.pipeline.publish.lib import fill_sequence_gaps_with_previous_version from ayon_core.lib.transcoding import ( IMAGE_EXTENSIONS, get_ffprobe_streams, @@ -510,7 +510,7 @@ class ExtractReview(pyblish.api.InstancePlugin): temp_data=temp_data ) elif fill_missing_frames == "previous_version": - _, new_frame_files = fill_sequence_gaps_with_previous( + _, new_frame_files = fill_sequence_gaps_with_previous_version( collection=collection, staging_dir=new_repre["stagingDir"], instance=instance, From f3300a67e42dac2698ca2a153f1e2cd220f88a85 Mon Sep 17 00:00:00 2001 From: Petr Kalis Date: Mon, 13 Oct 2025 15:51:35 +0200 Subject: [PATCH 40/59] Formatting change Co-authored-by: Jakub Trllo <43494761+iLLiCiTiT@users.noreply.github.com> --- client/ayon_core/plugins/publish/extract_review.py | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/client/ayon_core/plugins/publish/extract_review.py b/client/ayon_core/plugins/publish/extract_review.py index fe0e7d4e3b..89926d2235 100644 --- a/client/ayon_core/plugins/publish/extract_review.py +++ b/client/ayon_core/plugins/publish/extract_review.py @@ -19,7 +19,9 @@ from ayon_core.lib import ( path_to_subprocess_arg, run_subprocess, ) -from ayon_core.pipeline.publish.lib import fill_sequence_gaps_with_previous_version +from ayon_core.pipeline.publish.lib import ( + fill_sequence_gaps_with_previous_version, +) from ayon_core.lib.transcoding import ( IMAGE_EXTENSIONS, get_ffprobe_streams, From 0dc8bbe0a651f5c9a783163b7b43e2239f4005b3 Mon Sep 17 00:00:00 2001 From: Petr Kalis Date: Tue, 14 Oct 2025 14:13:50 +0200 Subject: [PATCH 41/59] Reorder imports Co-authored-by: Jakub Trllo <43494761+iLLiCiTiT@users.noreply.github.com> --- client/ayon_core/pipeline/publish/lib.py | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/client/ayon_core/pipeline/publish/lib.py b/client/ayon_core/pipeline/publish/lib.py index 657a57226d..96ab76f963 100644 --- a/client/ayon_core/pipeline/publish/lib.py +++ b/client/ayon_core/pipeline/publish/lib.py @@ -7,12 +7,13 @@ import copy import warnings import hashlib import xml.etree.ElementTree +import logging from typing import TYPE_CHECKING, Optional, Union, List, Any + import clique import speedcopy -import logging - import ayon_api +from ayon_api import get_last_version_by_product_name, get_representations import pyblish.util import pyblish.plugin import pyblish.api From 0d96e40d4075695c47905fbbf69268793388eaeb Mon Sep 17 00:00:00 2001 From: Petr Kalis Date: Tue, 14 Oct 2025 15:14:07 +0200 Subject: [PATCH 42/59] Ruff --- client/ayon_core/plugins/publish/extract_review.py | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/client/ayon_core/plugins/publish/extract_review.py b/client/ayon_core/plugins/publish/extract_review.py index fe0e7d4e3b..8a46b93060 100644 --- a/client/ayon_core/plugins/publish/extract_review.py +++ b/client/ayon_core/plugins/publish/extract_review.py @@ -507,10 +507,10 @@ class ExtractReview(pyblish.api.InstancePlugin): resolution_width=temp_data.resolution_width, resolution_height=temp_data.resolution_height, extension=temp_data.input_ext, - temp_data=temp_data + temp_data=temp_data, ) elif fill_missing_frames == "previous_version": - _, new_frame_files = fill_sequence_gaps_with_previous_version( + fill_output = fill_sequence_gaps_with_previous_version( collection=collection, staging_dir=new_repre["stagingDir"], instance=instance, @@ -518,6 +518,7 @@ class ExtractReview(pyblish.api.InstancePlugin): start_frame=temp_data.frame_start, end_frame=temp_data.frame_end, ) + _, new_frame_files = fill_output # fallback to original workflow if new_frame_files is None: self.log.warning( From bb1fed3dbc59eb5f226656c8b934323fa7373c3c Mon Sep 17 00:00:00 2001 From: Petr Kalis Date: Tue, 14 Oct 2025 15:16:49 +0200 Subject: [PATCH 43/59] Ruff --- client/ayon_core/pipeline/publish/lib.py | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/client/ayon_core/pipeline/publish/lib.py b/client/ayon_core/pipeline/publish/lib.py index 657a57226d..7152ec78fa 100644 --- a/client/ayon_core/pipeline/publish/lib.py +++ b/client/ayon_core/pipeline/publish/lib.py @@ -12,11 +12,15 @@ import clique import speedcopy import logging -import ayon_api import pyblish.util import pyblish.plugin import pyblish.api +from ayon_api import ( + get_server_api_connection, + get_representations, + get_last_version_by_product_name +) from ayon_core.lib import ( import_filepath, Logger, @@ -30,7 +34,6 @@ from .constants import ( DEFAULT_PUBLISH_TEMPLATE, DEFAULT_HERO_PUBLISH_TEMPLATE, ) -from ayon_api import get_last_version_by_product_name, get_representations if TYPE_CHECKING: from ayon_core.pipeline.traits import Representation @@ -1036,7 +1039,7 @@ def main_cli_publish( # NOTE: ayon-python-api does not have public api function to find # out if is used service user. So we need to have try > except # block. - con = ayon_api.get_server_api_connection() + con = get_server_api_connection() try: con.set_default_service_username(username) except ValueError: From 0aaac3e0d5769718960f362e1391fa7d7406e568 Mon Sep 17 00:00:00 2001 From: Jakub Jezek Date: Thu, 16 Oct 2025 10:38:12 +0200 Subject: [PATCH 44/59] Updates review extraction process. Refactors review extraction to remove Ftrack-specific elements. - Removes redundant data related to frame starts in Ftrack. - Simplifies review representation. - Streamlines the audio input processing. --- client/ayon_core/plugins/publish/extract_review.py | 12 +----------- 1 file changed, 1 insertion(+), 11 deletions(-) diff --git a/client/ayon_core/plugins/publish/extract_review.py b/client/ayon_core/plugins/publish/extract_review.py index 04e534054e..25c4c817ff 100644 --- a/client/ayon_core/plugins/publish/extract_review.py +++ b/client/ayon_core/plugins/publish/extract_review.py @@ -130,7 +130,7 @@ def frame_to_timecode(frame: int, fps: float) -> str: class ExtractReview(pyblish.api.InstancePlugin): - """Extracting Review mov file for Ftrack + """Extracting Reviewable medias Compulsory attribute of representation is tags list with "review", otherwise the representation is ignored. @@ -612,8 +612,6 @@ class ExtractReview(pyblish.api.InstancePlugin): "name": "{}_{}".format(output_name, output_ext), "outputName": output_name, "outputDef": output_def, - "frameStartFtrack": temp_data.output_frame_start, - "frameEndFtrack": temp_data.output_frame_end, "ffmpeg_cmd": subprcs_cmd }) @@ -1384,15 +1382,7 @@ class ExtractReview(pyblish.api.InstancePlugin): return audio_in_args, audio_filters, audio_out_args for audio in audio_inputs: - # NOTE modified, always was expected "frameStartFtrack" which is - # STRANGE?!!! There should be different key, right? - # TODO use different frame start! offset_seconds = 0 - frame_start_ftrack = instance.data.get("frameStartFtrack") - if frame_start_ftrack is not None: - offset_frames = frame_start_ftrack - audio["offset"] - offset_seconds = offset_frames / temp_data.fps - if offset_seconds > 0: audio_in_args.append( "-ss {}".format(offset_seconds) From 16d5fe45fc1ad21c6a9a548ffcdef528badd2fb7 Mon Sep 17 00:00:00 2001 From: Jakub Trllo <43494761+iLLiCiTiT@users.noreply.github.com> Date: Thu, 16 Oct 2025 12:44:35 +0200 Subject: [PATCH 45/59] use settings summary to resolve which addon versions are used --- client/ayon_core/addon/base.py | 81 ++++++++++++++++++---------------- 1 file changed, 43 insertions(+), 38 deletions(-) diff --git a/client/ayon_core/addon/base.py b/client/ayon_core/addon/base.py index 1d1562f543..9207bb74c0 100644 --- a/client/ayon_core/addon/base.py +++ b/client/ayon_core/addon/base.py @@ -2,7 +2,6 @@ """Base class for AYON addons.""" from __future__ import annotations -import copy import os import sys import time @@ -13,6 +12,7 @@ import collections import warnings from uuid import uuid4 from abc import ABC, abstractmethod +from urllib.parse import urlencode from types import ModuleType import typing from typing import Optional, Any, Union @@ -136,39 +136,47 @@ def load_addons(force: bool = False) -> None: time.sleep(0.1) -def _get_ayon_bundle_data() -> Optional[dict[str, Any]]: +def _get_ayon_bundle_data() -> tuple[ + dict[str, Any], Optional[dict[str, Any]] +]: studio_bundle_name = os.environ.get("AYON_STUDIO_BUNDLE_NAME") project_bundle_name = os.getenv("AYON_BUNDLE_NAME") bundles = ayon_api.get_bundles()["bundles"] - project_bundle = next( + studio_bundle = next( ( bundle for bundle in bundles - if bundle["name"] == project_bundle_name + if bundle["name"] == studio_bundle_name ), None ) - studio_bundle = None - if studio_bundle_name and project_bundle_name != studio_bundle_name: - studio_bundle = next( + + if studio_bundle is None: + raise RuntimeError(f"Failed to find bundle '{studio_bundle_name}'.") + + project_bundle = None + if project_bundle_name and project_bundle_name != studio_bundle_name: + project_bundle = next( ( bundle for bundle in bundles - if bundle["name"] == studio_bundle_name + if bundle["name"] == project_bundle_name ), None ) - if project_bundle and studio_bundle: - addons = copy.deepcopy(studio_bundle["addons"]) - addons.update(project_bundle["addons"]) - project_bundle["addons"] = addons - return project_bundle + if project_bundle is None: + raise RuntimeError( + f"Failed to find project bundle '{project_bundle_name}'." + ) + + return studio_bundle, project_bundle def _get_ayon_addons_information( - bundle_info: dict[str, Any] -) -> list[dict[str, Any]]: + studio_bundle: dict[str, Any], + project_bundle: Optional[dict[str, Any]], +) -> dict[str, str]: """Receive information about addons to use from server. Todos: @@ -181,22 +189,20 @@ def _get_ayon_addons_information( list[dict[str, Any]]: List of addon information to use. """ - output = [] - bundle_addons = bundle_info["addons"] - addons = ayon_api.get_addons_info()["addons"] - for addon in addons: - name = addon["name"] - versions = addon.get("versions") - addon_version = bundle_addons.get(name) - if addon_version is None or not versions: - continue - version = versions.get(addon_version) - if version: - version = copy.deepcopy(version) - version["name"] = name - version["version"] = addon_version - output.append(version) - return output + key_values = { + "summary": "true", + "bundle_name": studio_bundle["name"], + } + if project_bundle: + key_values["project_bundle_name"] = project_bundle["name"] + + query = urlencode(key_values) + + response = ayon_api.get(f"settings?{query}") + return { + addon["name"]: addon["version"] + for addon in response.data["addons"] + } def _load_ayon_addons(log: logging.Logger) -> list[ModuleType]: @@ -214,8 +220,8 @@ def _load_ayon_addons(log: logging.Logger) -> list[ModuleType]: """ all_addon_modules = [] - bundle_info = _get_ayon_bundle_data() - addons_info = _get_ayon_addons_information(bundle_info) + studio_bundle, project_bundle = _get_ayon_bundle_data() + addons_info = _get_ayon_addons_information(studio_bundle, project_bundle) if not addons_info: return all_addon_modules @@ -227,17 +233,16 @@ def _load_ayon_addons(log: logging.Logger) -> list[ModuleType]: dev_addons_info = {} if dev_mode_enabled: # Get dev addons info only when dev mode is enabled - dev_addons_info = bundle_info.get("addonDevelopment", dev_addons_info) + dev_addons_info = studio_bundle.get( + "addonDevelopment", dev_addons_info + ) addons_dir_exists = os.path.exists(addons_dir) if not addons_dir_exists: log.warning( f"Addons directory does not exists. Path \"{addons_dir}\"") - for addon_info in addons_info: - addon_name = addon_info["name"] - addon_version = addon_info["version"] - + for addon_name, addon_version in addons_info.items(): # core addon does not have any addon object if addon_name == "core": continue From e356630f4d94428828f14898a70ecc3c70619b8c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ond=C5=99ej=20Samohel?= Date: Thu, 16 Oct 2025 17:19:41 +0200 Subject: [PATCH 46/59] =?UTF-8?q?=F0=9F=AA=B2=20get=20the=20correct=20temp?= =?UTF-8?q?late=20for=20resources?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../plugins/publish/collect_resources_path.py | 25 +++++++++++++------ 1 file changed, 18 insertions(+), 7 deletions(-) diff --git a/client/ayon_core/plugins/publish/collect_resources_path.py b/client/ayon_core/plugins/publish/collect_resources_path.py index 2e5b296228..e410303a2a 100644 --- a/client/ayon_core/plugins/publish/collect_resources_path.py +++ b/client/ayon_core/plugins/publish/collect_resources_path.py @@ -13,6 +13,9 @@ import copy import pyblish.api +from ayon_core.pipeline.publish import get_publish_template_name +from ayon_core.pipeline.context_tools import get_current_host_name + class CollectResourcesPath(pyblish.api.InstancePlugin): """Generate directory path where the files and resources will be stored. @@ -77,16 +80,24 @@ class CollectResourcesPath(pyblish.api.InstancePlugin): # This is for cases of Deprecated anatomy without `folder` # TODO remove when all clients have solved this issue - template_data.update({ - "frame": "FRAME_TEMP", - "representation": "TEMP" - }) + template_data.update({"frame": "FRAME_TEMP", "representation": "TEMP"}) - publish_templates = anatomy.get_template_item( - "publish", "default", "directory" + + template_name = get_publish_template_name( + project_name=template_data["project"]["name"], + host_name=get_current_host_name(), + product_type=template_data["product"]["type"], + task_name=template_data["product"]["name"], + task_type=template_data["product"]["type"], + project_settings=instance.context.data["project_settings"], + logger=self.log, ) + + publish_template = anatomy.get_template_item( + "publish", template_name, "directory") + publish_folder = os.path.normpath( - publish_templates.format_strict(template_data) + publish_template.format_strict(template_data) ) resources_folder = os.path.join(publish_folder, "resources") From 68e19f4184dd9835df1dda49417da2bd8118a64f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ond=C5=99ej=20Samohel?= Date: Thu, 16 Oct 2025 18:55:04 +0200 Subject: [PATCH 47/59] =?UTF-8?q?=F0=9F=90=95=20fix=20linting=20issues?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- client/ayon_core/plugins/publish/collect_resources_path.py | 1 - 1 file changed, 1 deletion(-) diff --git a/client/ayon_core/plugins/publish/collect_resources_path.py b/client/ayon_core/plugins/publish/collect_resources_path.py index e410303a2a..11e378ce52 100644 --- a/client/ayon_core/plugins/publish/collect_resources_path.py +++ b/client/ayon_core/plugins/publish/collect_resources_path.py @@ -82,7 +82,6 @@ class CollectResourcesPath(pyblish.api.InstancePlugin): # TODO remove when all clients have solved this issue template_data.update({"frame": "FRAME_TEMP", "representation": "TEMP"}) - template_name = get_publish_template_name( project_name=template_data["project"]["name"], host_name=get_current_host_name(), From d99075fed6e2186326aa8eb772b9480c8490a00f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ond=C5=99ej=20Samohel?= Date: Fri, 17 Oct 2025 11:39:42 +0200 Subject: [PATCH 48/59] =?UTF-8?q?=E2=99=BB=EF=B8=8Fuse=20collected=20data?= =?UTF-8?q?=20instead?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- client/ayon_core/plugins/publish/collect_resources_path.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/client/ayon_core/plugins/publish/collect_resources_path.py b/client/ayon_core/plugins/publish/collect_resources_path.py index 11e378ce52..2ef3ffe61d 100644 --- a/client/ayon_core/plugins/publish/collect_resources_path.py +++ b/client/ayon_core/plugins/publish/collect_resources_path.py @@ -84,7 +84,7 @@ class CollectResourcesPath(pyblish.api.InstancePlugin): template_name = get_publish_template_name( project_name=template_data["project"]["name"], - host_name=get_current_host_name(), + host_name=instance.context.data["hostName"], product_type=template_data["product"]["type"], task_name=template_data["product"]["name"], task_type=template_data["product"]["type"], From fd5a5a2142437d264d404456ff990951876ff69d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ond=C5=99ej=20Samohel?= Date: Fri, 17 Oct 2025 11:40:18 +0200 Subject: [PATCH 49/59] =?UTF-8?q?=E2=99=BB=EF=B8=8F=20and=20remove=20unnec?= =?UTF-8?q?essary=20import?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- client/ayon_core/plugins/publish/collect_resources_path.py | 1 - 1 file changed, 1 deletion(-) diff --git a/client/ayon_core/plugins/publish/collect_resources_path.py b/client/ayon_core/plugins/publish/collect_resources_path.py index 2ef3ffe61d..fc8d3d15cd 100644 --- a/client/ayon_core/plugins/publish/collect_resources_path.py +++ b/client/ayon_core/plugins/publish/collect_resources_path.py @@ -14,7 +14,6 @@ import copy import pyblish.api from ayon_core.pipeline.publish import get_publish_template_name -from ayon_core.pipeline.context_tools import get_current_host_name class CollectResourcesPath(pyblish.api.InstancePlugin): From fe7adf36e689b4fcc87544d91f3987f6ad63e929 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ond=C5=99ej=20Samohel?= Date: Fri, 17 Oct 2025 11:44:33 +0200 Subject: [PATCH 50/59] =?UTF-8?q?=F0=9F=AA=B2=20fix=20task=20and=20product?= =?UTF-8?q?=20type?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../plugins/publish/collect_resources_path.py | 12 +++++++++--- 1 file changed, 9 insertions(+), 3 deletions(-) diff --git a/client/ayon_core/plugins/publish/collect_resources_path.py b/client/ayon_core/plugins/publish/collect_resources_path.py index fc8d3d15cd..30fe5c0c80 100644 --- a/client/ayon_core/plugins/publish/collect_resources_path.py +++ b/client/ayon_core/plugins/publish/collect_resources_path.py @@ -81,12 +81,18 @@ class CollectResourcesPath(pyblish.api.InstancePlugin): # TODO remove when all clients have solved this issue template_data.update({"frame": "FRAME_TEMP", "representation": "TEMP"}) + task_name = task_type = None + task_entity = instance.data.get("taskEntity") + if task_entity: + task_name = task_entity.name + task_type = task_entity.type + template_name = get_publish_template_name( project_name=template_data["project"]["name"], host_name=instance.context.data["hostName"], - product_type=template_data["product"]["type"], - task_name=template_data["product"]["name"], - task_type=template_data["product"]["type"], + product_type=instance.data["productType"], + task_name=task_name, + task_type=task_type, project_settings=instance.context.data["project_settings"], logger=self.log, ) From c49d92c30668df40a620218fce2c8991973d1d51 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ond=C5=99ej=20Samohel?= Date: Fri, 17 Oct 2025 11:46:48 +0200 Subject: [PATCH 51/59] =?UTF-8?q?=F0=9F=A6=97=20fix=20data=20access?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- client/ayon_core/plugins/publish/collect_resources_path.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/client/ayon_core/plugins/publish/collect_resources_path.py b/client/ayon_core/plugins/publish/collect_resources_path.py index 30fe5c0c80..927e358ea7 100644 --- a/client/ayon_core/plugins/publish/collect_resources_path.py +++ b/client/ayon_core/plugins/publish/collect_resources_path.py @@ -84,8 +84,8 @@ class CollectResourcesPath(pyblish.api.InstancePlugin): task_name = task_type = None task_entity = instance.data.get("taskEntity") if task_entity: - task_name = task_entity.name - task_type = task_entity.type + task_name = task_entity["name"] + task_type = task_entity["task_type"] template_name = get_publish_template_name( project_name=template_data["project"]["name"], From df8459bbabf81d26c6b15d47dce3a66eb22c7de5 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ond=C5=99ej=20Samohel?= Date: Fri, 17 Oct 2025 11:47:57 +0200 Subject: [PATCH 52/59] =?UTF-8?q?=F0=9F=A6=97=20fix=20key=20name?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- client/ayon_core/plugins/publish/collect_resources_path.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/client/ayon_core/plugins/publish/collect_resources_path.py b/client/ayon_core/plugins/publish/collect_resources_path.py index 927e358ea7..07cae07a3f 100644 --- a/client/ayon_core/plugins/publish/collect_resources_path.py +++ b/client/ayon_core/plugins/publish/collect_resources_path.py @@ -85,7 +85,7 @@ class CollectResourcesPath(pyblish.api.InstancePlugin): task_entity = instance.data.get("taskEntity") if task_entity: task_name = task_entity["name"] - task_type = task_entity["task_type"] + task_type = task_entity["taskType"] template_name = get_publish_template_name( project_name=template_data["project"]["name"], From 34594f7ee4deddcf7cb58efab05311b8c66d14b0 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ond=C5=99ej=20Samohel?= <33513211+antirotor@users.noreply.github.com> Date: Fri, 17 Oct 2025 14:12:58 +0200 Subject: [PATCH 53/59] Apply suggestion from @iLLiCiTiT Co-authored-by: Jakub Trllo <43494761+iLLiCiTiT@users.noreply.github.com> --- client/ayon_core/plugins/publish/collect_resources_path.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/client/ayon_core/plugins/publish/collect_resources_path.py b/client/ayon_core/plugins/publish/collect_resources_path.py index 07cae07a3f..704c69a6ab 100644 --- a/client/ayon_core/plugins/publish/collect_resources_path.py +++ b/client/ayon_core/plugins/publish/collect_resources_path.py @@ -88,7 +88,7 @@ class CollectResourcesPath(pyblish.api.InstancePlugin): task_type = task_entity["taskType"] template_name = get_publish_template_name( - project_name=template_data["project"]["name"], + project_name=instance.context.data["projectName"], host_name=instance.context.data["hostName"], product_type=instance.data["productType"], task_name=task_name, From 99a9541f27cf6c26117cae17b6129be20d5397c5 Mon Sep 17 00:00:00 2001 From: Petr Kalis Date: Mon, 20 Oct 2025 14:55:03 +0200 Subject: [PATCH 54/59] Ruff --- client/ayon_core/plugins/publish/extract_review.py | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/client/ayon_core/plugins/publish/extract_review.py b/client/ayon_core/plugins/publish/extract_review.py index 8a46b93060..0111d02cb3 100644 --- a/client/ayon_core/plugins/publish/extract_review.py +++ b/client/ayon_core/plugins/publish/extract_review.py @@ -19,7 +19,9 @@ from ayon_core.lib import ( path_to_subprocess_arg, run_subprocess, ) -from ayon_core.pipeline.publish.lib import fill_sequence_gaps_with_previous_version +from ayon_core.pipeline.publish.lib import ( + fill_sequence_gaps_with_previous_version +) from ayon_core.lib.transcoding import ( IMAGE_EXTENSIONS, get_ffprobe_streams, From 1487c30f06655e43757650160a151c2b38951002 Mon Sep 17 00:00:00 2001 From: MustafaJafar Date: Mon, 20 Oct 2025 20:27:40 +0300 Subject: [PATCH 55/59] Revert changes in `pyproject.toml` from #1215 --- pyproject.toml | 11 ----------- 1 file changed, 11 deletions(-) diff --git a/pyproject.toml b/pyproject.toml index 44c6a9d73c..be3e82cc67 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -27,17 +27,6 @@ codespell = "^2.2.6" semver = "^3.0.2" mypy = "^1.14.0" mock = "^5.0.0" -tomlkit = "^0.13.2" -requests = "^2.32.3" -mkdocs-material = "^9.6.7" -mkdocs-autoapi = "^0.4.0" -mkdocstrings-python = "^1.16.2" -mkdocs-minify-plugin = "^0.8.0" -markdown-checklist = "^0.4.4" -mdx-gh-links = "^0.4" -pymdown-extensions = "^10.14.3" -mike = "^2.1.3" -mkdocstrings-shell = "^1.0.2" nxtools = "^1.6" [tool.poetry.group.test.dependencies] From 5b8d92fb9c6528d0fdb8f81ae81045f9c38979e9 Mon Sep 17 00:00:00 2001 From: Ynbot Date: Tue, 21 Oct 2025 08:31:10 +0000 Subject: [PATCH 56/59] [Automated] Add generated package files from main --- client/ayon_core/version.py | 2 +- package.py | 2 +- pyproject.toml | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/client/ayon_core/version.py b/client/ayon_core/version.py index bbced6b641..bbe6ee01a8 100644 --- a/client/ayon_core/version.py +++ b/client/ayon_core/version.py @@ -1,3 +1,3 @@ # -*- coding: utf-8 -*- """Package declaring AYON addon 'core' version.""" -__version__ = "1.6.4+dev" +__version__ = "1.6.5" diff --git a/package.py b/package.py index 114f7d12ef..4a2cd6d568 100644 --- a/package.py +++ b/package.py @@ -1,6 +1,6 @@ name = "core" title = "Core" -version = "1.6.4+dev" +version = "1.6.5" client_dir = "ayon_core" diff --git a/pyproject.toml b/pyproject.toml index be3e82cc67..d603c9dc04 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -5,7 +5,7 @@ [tool.poetry] name = "ayon-core" -version = "1.6.4+dev" +version = "1.6.5" description = "" authors = ["Ynput Team "] readme = "README.md" From fc5199c70f8712697874a2c52af89461c8eb5024 Mon Sep 17 00:00:00 2001 From: Ynbot Date: Tue, 21 Oct 2025 08:31:51 +0000 Subject: [PATCH 57/59] [Automated] Update version in package.py for develop --- client/ayon_core/version.py | 2 +- package.py | 2 +- pyproject.toml | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/client/ayon_core/version.py b/client/ayon_core/version.py index bbe6ee01a8..d3b3454fd1 100644 --- a/client/ayon_core/version.py +++ b/client/ayon_core/version.py @@ -1,3 +1,3 @@ # -*- coding: utf-8 -*- """Package declaring AYON addon 'core' version.""" -__version__ = "1.6.5" +__version__ = "1.6.5+dev" diff --git a/package.py b/package.py index 4a2cd6d568..2889039502 100644 --- a/package.py +++ b/package.py @@ -1,6 +1,6 @@ name = "core" title = "Core" -version = "1.6.5" +version = "1.6.5+dev" client_dir = "ayon_core" diff --git a/pyproject.toml b/pyproject.toml index d603c9dc04..f43846ec2b 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -5,7 +5,7 @@ [tool.poetry] name = "ayon-core" -version = "1.6.5" +version = "1.6.5+dev" description = "" authors = ["Ynput Team "] readme = "README.md" From afee12cd7ad8b6623e338ee6f9fd579a77aaffea Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" Date: Tue, 21 Oct 2025 08:33:00 +0000 Subject: [PATCH 58/59] chore(): update bug report / version --- .github/ISSUE_TEMPLATE/bug_report.yml | 1 + 1 file changed, 1 insertion(+) diff --git a/.github/ISSUE_TEMPLATE/bug_report.yml b/.github/ISSUE_TEMPLATE/bug_report.yml index 27ed2217dd..646a2dd1ee 100644 --- a/.github/ISSUE_TEMPLATE/bug_report.yml +++ b/.github/ISSUE_TEMPLATE/bug_report.yml @@ -35,6 +35,7 @@ body: label: Version description: What version are you running? Look to AYON Tray options: + - 1.6.5 - 1.6.4 - 1.6.3 - 1.6.2 From 363e338a613331750036d8691ac3c3252f3fa3ba Mon Sep 17 00:00:00 2001 From: Jakub Trllo <43494761+iLLiCiTiT@users.noreply.github.com> Date: Tue, 21 Oct 2025 15:01:47 +0200 Subject: [PATCH 59/59] pass studio bundle name to farm --- client/ayon_core/plugins/publish/collect_farm_env_variables.py | 1 + 1 file changed, 1 insertion(+) diff --git a/client/ayon_core/plugins/publish/collect_farm_env_variables.py b/client/ayon_core/plugins/publish/collect_farm_env_variables.py index 39c421381d..d35f02b9df 100644 --- a/client/ayon_core/plugins/publish/collect_farm_env_variables.py +++ b/client/ayon_core/plugins/publish/collect_farm_env_variables.py @@ -32,6 +32,7 @@ class CollectCoreJobEnvVars(pyblish.api.ContextPlugin): for key in [ "AYON_BUNDLE_NAME", + "AYON_STUDIO_BUNDLE_NAME", "AYON_USE_STAGING", "AYON_IN_TESTS", # NOTE Not sure why workdir is needed?