From 361d21eff6afb403781e92fa32fc6588af0a9257 Mon Sep 17 00:00:00 2001 From: MustafaJafar Date: Sun, 31 Dec 2023 14:20:37 +0200 Subject: [PATCH 01/92] =?UTF-8?q?=F0=9F=93=B8=20allow=20taking=20snapshoot?= =?UTF-8?q?s=20from=20houdini?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- openpype/hosts/houdini/api/lib.py | 70 +++++++++++++++++++++++++++++++ 1 file changed, 70 insertions(+) diff --git a/openpype/hosts/houdini/api/lib.py b/openpype/hosts/houdini/api/lib.py index edd50f10c1..7b09d2baf2 100644 --- a/openpype/hosts/houdini/api/lib.py +++ b/openpype/hosts/houdini/api/lib.py @@ -1054,3 +1054,73 @@ def add_self_publish_button(node): template = node.parmTemplateGroup() template.insertBefore((0,), button_parm) node.setParmTemplateGroup(template) + + +def getSceneViewer(): + """ + return an instance of a visible viewport. + There may be many, some could be closed, any visible are current + """ + panes = hou.ui.paneTabs() + panes = [x for x in panes if x.type() == hou.paneTabType.SceneViewer] + panes = sorted(panes, key=lambda x: x.isCurrentTab()) + if panes: + return panes[-1] + else: + return None + + +def sceneview_snapshoot( + filename="$HIP/thumbnails/$HIPNAME.$F4.jpg", + fstart=None, + fend=None + ): + """ + It takes snapshoot of your scene view fot the given frame range. + So, it's capable of generating snapshoots image sequence. + It works in different Houdini context e.g. Objects, Solaris + + Example: + from openpype.hosts.houdini.api import lib + lib.sceneview_snapshoot() + + Notes: + .png output will render poorly, so use .jpg. + + How it works: + Get the current sceneviewer (may be more than one or hidden) + and screengrab the perspective viewport to a file in the + publish location to be picked up with the publish. + + Credits: + https://www.sidefx.com/forum/topic/42808/?page=1#post-354796 + + Args: + filename (str): filename with the desired full path. + fstart (int): the frame at which snapshooting starts + fend (int): the frame at which snapshooting ends + """ + + try: + + if fstart is None: + fstart = hou.frame() + if fend is None: + fend = fstart = hou.frame() + + sceneview = getSceneViewer() + if not sceneview: + log.debug("No SceneViewers detected.") + return + viewport = sceneview.curViewport() + + # this will open an mplay window to show the result + flip_settings = sceneview.flipbookSettings().stash() + flip_settings.frameRange( (fstart, fend) ) + flip_settings.output(filename) + flip_settings.outputToMPlay(False) + sceneview.flipbook(viewport, flip_settings) + log.debug("A snap of sceneview has been saved to: {}".format(filename)) + + except Exception as e: + log.debug(e) From 5658b109259a55a93edbb30f2e0c7f35c64a6201 Mon Sep 17 00:00:00 2001 From: MustafaJafar Date: Sun, 31 Dec 2023 14:31:31 +0200 Subject: [PATCH 02/92] =?UTF-8?q?=F0=9F=90=BE=20Resolve=20Hound?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- openpype/hosts/houdini/api/lib.py | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/openpype/hosts/houdini/api/lib.py b/openpype/hosts/houdini/api/lib.py index 7b09d2baf2..1b172595c8 100644 --- a/openpype/hosts/houdini/api/lib.py +++ b/openpype/hosts/houdini/api/lib.py @@ -1073,8 +1073,7 @@ def getSceneViewer(): def sceneview_snapshoot( filename="$HIP/thumbnails/$HIPNAME.$F4.jpg", fstart=None, - fend=None - ): + fend=None): """ It takes snapshoot of your scene view fot the given frame range. So, it's capable of generating snapshoots image sequence. @@ -1116,7 +1115,7 @@ def sceneview_snapshoot( # this will open an mplay window to show the result flip_settings = sceneview.flipbookSettings().stash() - flip_settings.frameRange( (fstart, fend) ) + flip_settings.frameRange((fstart, fend)) flip_settings.output(filename) flip_settings.outputToMPlay(False) sceneview.flipbook(viewport, flip_settings) From ab61e755e99773d3f4997c4fcbf27250e47d8262 Mon Sep 17 00:00:00 2001 From: MustafaJafar Date: Wed, 3 Jan 2024 17:22:52 +0200 Subject: [PATCH 03/92] =?UTF-8?q?=F0=9F=93=9D=20Kuba's=20and=20Big=20Roy's?= =?UTF-8?q?=20comments?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- openpype/hosts/houdini/api/lib.py | 59 +++++++++++++++---------------- 1 file changed, 29 insertions(+), 30 deletions(-) diff --git a/openpype/hosts/houdini/api/lib.py b/openpype/hosts/houdini/api/lib.py index 1b172595c8..db9955694d 100644 --- a/openpype/hosts/houdini/api/lib.py +++ b/openpype/hosts/houdini/api/lib.py @@ -1056,7 +1056,7 @@ def add_self_publish_button(node): node.setParmTemplateGroup(template) -def getSceneViewer(): +def get_scene_viewer(): """ return an instance of a visible viewport. There may be many, some could be closed, any visible are current @@ -1066,12 +1066,13 @@ def getSceneViewer(): panes = sorted(panes, key=lambda x: x.isCurrentTab()) if panes: return panes[-1] - else: - return None + + return None -def sceneview_snapshoot( - filename="$HIP/thumbnails/$HIPNAME.$F4.jpg", +def sceneview_snapshot( + sceneview, + filepath="$HIP/thumbnails/$HIPNAME.$F4.jpg", fstart=None, fend=None): """ @@ -1081,7 +1082,8 @@ def sceneview_snapshoot( Example: from openpype.hosts.houdini.api import lib - lib.sceneview_snapshoot() + sceneview = hou.ui.paneTabOfType(hou.paneTabType.SceneViewer) + lib.sceneview_snapshot(sceneview) Notes: .png output will render poorly, so use .jpg. @@ -1095,31 +1097,28 @@ def sceneview_snapshoot( https://www.sidefx.com/forum/topic/42808/?page=1#post-354796 Args: - filename (str): filename with the desired full path. - fstart (int): the frame at which snapshooting starts - fend (int): the frame at which snapshooting ends + sceneview (hou.SceneViewer): The scene view pane from which you want + to take a snapshot. + filepath (str): thumbnail filepath. + fstart (int): the frame at which snapshot starts + fend (int): the frame at which snapshot ends """ - try: + if fstart is None: + fstart = hou.frame() + if fend is None: + fend = fstart - if fstart is None: - fstart = hou.frame() - if fend is None: - fend = fstart = hou.frame() + if not isinstance(sceneview, hou.SceneViewer): + log.debug("Wrong Input. {} is not of type hou.SceneViewer." + .format(sceneview)) + return + viewport = sceneview.curViewport() - sceneview = getSceneViewer() - if not sceneview: - log.debug("No SceneViewers detected.") - return - viewport = sceneview.curViewport() - - # this will open an mplay window to show the result - flip_settings = sceneview.flipbookSettings().stash() - flip_settings.frameRange((fstart, fend)) - flip_settings.output(filename) - flip_settings.outputToMPlay(False) - sceneview.flipbook(viewport, flip_settings) - log.debug("A snap of sceneview has been saved to: {}".format(filename)) - - except Exception as e: - log.debug(e) + # this will open an mplay window to show the result + flip_settings = sceneview.flipbookSettings().stash() + flip_settings.frameRange((fstart, fend)) + flip_settings.output(filepath) + flip_settings.outputToMPlay(False) + sceneview.flipbook(viewport, flip_settings) + log.debug("A snap of sceneview has been saved to: {}".format(filepath)) From a27c7bf8fd99effd8374075b07e1f036467964a4 Mon Sep 17 00:00:00 2001 From: MustafaJafar Date: Wed, 3 Jan 2024 17:40:49 +0200 Subject: [PATCH 04/92] =?UTF-8?q?=E2=9C=8F=EF=B8=8F=20=20fix=20typo?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- openpype/hosts/houdini/api/lib.py | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/openpype/hosts/houdini/api/lib.py b/openpype/hosts/houdini/api/lib.py index db9955694d..7e07bce2d1 100644 --- a/openpype/hosts/houdini/api/lib.py +++ b/openpype/hosts/houdini/api/lib.py @@ -1076,8 +1076,8 @@ def sceneview_snapshot( fstart=None, fend=None): """ - It takes snapshoot of your scene view fot the given frame range. - So, it's capable of generating snapshoots image sequence. + It takes snapshot of your scene view fot the given frame range. + So, it's capable of generating snapshots image sequence. It works in different Houdini context e.g. Objects, Solaris Example: @@ -1121,4 +1121,4 @@ def sceneview_snapshot( flip_settings.output(filepath) flip_settings.outputToMPlay(False) sceneview.flipbook(viewport, flip_settings) - log.debug("A snap of sceneview has been saved to: {}".format(filepath)) + log.debug("A snapshot of sceneview has been saved to: {}".format(filepath)) From b6a432d39363e00894ecb0f3fc4a95586d6d14c8 Mon Sep 17 00:00:00 2001 From: MustafaJafar Date: Wed, 3 Jan 2024 21:50:48 +0200 Subject: [PATCH 05/92] =?UTF-8?q?=F0=9F=96=BC=EF=B8=8F=20=20Extract=20acti?= =?UTF-8?q?ve=20view=20as=20thumbnail?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../publish/extract_active_view_thumbnail.py | 58 +++++++++++++++++++ 1 file changed, 58 insertions(+) create mode 100644 openpype/hosts/houdini/plugins/publish/extract_active_view_thumbnail.py diff --git a/openpype/hosts/houdini/plugins/publish/extract_active_view_thumbnail.py b/openpype/hosts/houdini/plugins/publish/extract_active_view_thumbnail.py new file mode 100644 index 0000000000..40b0dac02e --- /dev/null +++ b/openpype/hosts/houdini/plugins/publish/extract_active_view_thumbnail.py @@ -0,0 +1,58 @@ +import os + +import pyblish.api + +from openpype.pipeline import publish, registered_host +from openpype.hosts.houdini.api import lib +from openpype.hosts.houdini.api.pipeline import IS_HEADLESS + +import hou + + +class ExtractActiveViewThumbnail(publish.Extractor): + """Set instance thumbnail to a screengrab of current active viewport. + + This makes it so that if an instance does not have a thumbnail set yet that + it will get a thumbnail of the currently active view at the time of + publishing as a fallback. + + """ + order = pyblish.api.ExtractorOrder + 0.49 + label = "Extract Active View Thumbnail" + families = ["workfile"] + hosts = ["houdini"] + + def process(self, instance): + if IS_HEADLESS: + self.log.debug( + "Skip extraction of active view thumbnail, due to being in" + "headless mode." + ) + return + + thumbnail = instance.data.get("thumbnailPath") + self.log.debug(thumbnail) + if not thumbnail: + view_thumbnail = self.get_view_thumbnail(instance) + if not view_thumbnail: + return + + self.log.debug("Setting instance thumbnail path to: {}".format( + view_thumbnail + )) + instance.data["thumbnailPath"] = view_thumbnail + + def get_view_thumbnail(self, instance): + + host = registered_host() + current_filepath = host.get_current_workfile() + if not current_filepath: + self.log.error("No current workfile path. Thumbnail generation skipped") + return + + thumbnail_path = "{}_thumbnail.jpg".format( + current_filepath.rsplit('.', 1)[0]) + sceneview = lib.get_scene_viewer() + lib.sceneview_snapshot(sceneview, thumbnail_path) + + return thumbnail_path From 08ccdfcea8593776f6898b659bf5c3d606b89770 Mon Sep 17 00:00:00 2001 From: MustafaJafar Date: Wed, 3 Jan 2024 21:52:33 +0200 Subject: [PATCH 06/92] =?UTF-8?q?=F0=9F=A6=B4=20Resolve=20Hound?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../plugins/publish/extract_active_view_thumbnail.py | 7 ++----- 1 file changed, 2 insertions(+), 5 deletions(-) diff --git a/openpype/hosts/houdini/plugins/publish/extract_active_view_thumbnail.py b/openpype/hosts/houdini/plugins/publish/extract_active_view_thumbnail.py index 40b0dac02e..b326f6918d 100644 --- a/openpype/hosts/houdini/plugins/publish/extract_active_view_thumbnail.py +++ b/openpype/hosts/houdini/plugins/publish/extract_active_view_thumbnail.py @@ -1,13 +1,9 @@ -import os - import pyblish.api from openpype.pipeline import publish, registered_host from openpype.hosts.houdini.api import lib from openpype.hosts.houdini.api.pipeline import IS_HEADLESS -import hou - class ExtractActiveViewThumbnail(publish.Extractor): """Set instance thumbnail to a screengrab of current active viewport. @@ -47,7 +43,8 @@ class ExtractActiveViewThumbnail(publish.Extractor): host = registered_host() current_filepath = host.get_current_workfile() if not current_filepath: - self.log.error("No current workfile path. Thumbnail generation skipped") + self.log.error("No current workfile path. " + "Thumbnail generation skipped") return thumbnail_path = "{}_thumbnail.jpg".format( From 0e7efc5da979d3cfdaa12cdfa31b926569ff2ea0 Mon Sep 17 00:00:00 2001 From: MustafaJafar Date: Thu, 4 Jan 2024 18:56:59 +0200 Subject: [PATCH 07/92] Kuba's comments - Better Code --- openpype/hosts/houdini/api/lib.py | 18 +++++++++--------- .../publish/extract_active_view_thumbnail.py | 17 ++++++----------- 2 files changed, 15 insertions(+), 20 deletions(-) diff --git a/openpype/hosts/houdini/api/lib.py b/openpype/hosts/houdini/api/lib.py index 7e07bce2d1..318de5f538 100644 --- a/openpype/hosts/houdini/api/lib.py +++ b/openpype/hosts/houdini/api/lib.py @@ -1073,8 +1073,8 @@ def get_scene_viewer(): def sceneview_snapshot( sceneview, filepath="$HIP/thumbnails/$HIPNAME.$F4.jpg", - fstart=None, - fend=None): + frame_start=None, + frame_end=None): """ It takes snapshot of your scene view fot the given frame range. So, it's capable of generating snapshots image sequence. @@ -1100,14 +1100,14 @@ def sceneview_snapshot( sceneview (hou.SceneViewer): The scene view pane from which you want to take a snapshot. filepath (str): thumbnail filepath. - fstart (int): the frame at which snapshot starts - fend (int): the frame at which snapshot ends + frame_start (int): the frame at which snapshot starts + frame_end (int): the frame at which snapshot ends """ - if fstart is None: - fstart = hou.frame() - if fend is None: - fend = fstart + if frame_start is None: + frame_start = hou.frame() + if frame_end is None: + frame_end = frame_start if not isinstance(sceneview, hou.SceneViewer): log.debug("Wrong Input. {} is not of type hou.SceneViewer." @@ -1117,7 +1117,7 @@ def sceneview_snapshot( # this will open an mplay window to show the result flip_settings = sceneview.flipbookSettings().stash() - flip_settings.frameRange((fstart, fend)) + flip_settings.frameRange((frame_start, frame_end)) flip_settings.output(filepath) flip_settings.outputToMPlay(False) sceneview.flipbook(viewport, flip_settings) diff --git a/openpype/hosts/houdini/plugins/publish/extract_active_view_thumbnail.py b/openpype/hosts/houdini/plugins/publish/extract_active_view_thumbnail.py index b326f6918d..82976bdf83 100644 --- a/openpype/hosts/houdini/plugins/publish/extract_active_view_thumbnail.py +++ b/openpype/hosts/houdini/plugins/publish/extract_active_view_thumbnail.py @@ -1,6 +1,6 @@ import pyblish.api - -from openpype.pipeline import publish, registered_host +import tempfile +from openpype.pipeline import publish from openpype.hosts.houdini.api import lib from openpype.hosts.houdini.api.pipeline import IS_HEADLESS @@ -27,7 +27,6 @@ class ExtractActiveViewThumbnail(publish.Extractor): return thumbnail = instance.data.get("thumbnailPath") - self.log.debug(thumbnail) if not thumbnail: view_thumbnail = self.get_view_thumbnail(instance) if not view_thumbnail: @@ -40,15 +39,11 @@ class ExtractActiveViewThumbnail(publish.Extractor): def get_view_thumbnail(self, instance): - host = registered_host() - current_filepath = host.get_current_workfile() - if not current_filepath: - self.log.error("No current workfile path. " - "Thumbnail generation skipped") - return + with tempfile.NamedTemporaryFile("w", suffix=".jpg") as tmp: + thumbnail_path = tmp.name + + instance.context.data["cleanupFullPaths"].append(thumbnail_path) - thumbnail_path = "{}_thumbnail.jpg".format( - current_filepath.rsplit('.', 1)[0]) sceneview = lib.get_scene_viewer() lib.sceneview_snapshot(sceneview, thumbnail_path) From 435cd9cce1e6a95fd5074aef1282866b8c126ef8 Mon Sep 17 00:00:00 2001 From: MustafaJafar Date: Fri, 5 Jan 2024 17:04:36 +0200 Subject: [PATCH 08/92] =?UTF-8?q?=E2=9E=96=20Remove=20unnecessary=20commen?= =?UTF-8?q?t?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- openpype/hosts/houdini/api/lib.py | 1 - 1 file changed, 1 deletion(-) diff --git a/openpype/hosts/houdini/api/lib.py b/openpype/hosts/houdini/api/lib.py index 318de5f538..bd15b8b83d 100644 --- a/openpype/hosts/houdini/api/lib.py +++ b/openpype/hosts/houdini/api/lib.py @@ -1115,7 +1115,6 @@ def sceneview_snapshot( return viewport = sceneview.curViewport() - # this will open an mplay window to show the result flip_settings = sceneview.flipbookSettings().stash() flip_settings.frameRange((frame_start, frame_end)) flip_settings.output(filepath) From 3ffb6db49fe161e1790c039142bc2236b492265a Mon Sep 17 00:00:00 2001 From: MustafaJafar Date: Tue, 9 Jan 2024 10:01:38 +0200 Subject: [PATCH 09/92] =?UTF-8?q?=F0=9F=93=9D=20Stick=20to=20Google=20doc?= =?UTF-8?q?=20string=20style?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- openpype/hosts/houdini/api/lib.py | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/openpype/hosts/houdini/api/lib.py b/openpype/hosts/houdini/api/lib.py index bd15b8b83d..33b74ca6b9 100644 --- a/openpype/hosts/houdini/api/lib.py +++ b/openpype/hosts/houdini/api/lib.py @@ -1058,7 +1058,8 @@ def add_self_publish_button(node): def get_scene_viewer(): """ - return an instance of a visible viewport. + Return an instance of a visible viewport. + There may be many, some could be closed, any visible are current """ panes = hou.ui.paneTabs() @@ -1075,8 +1076,9 @@ def sceneview_snapshot( filepath="$HIP/thumbnails/$HIPNAME.$F4.jpg", frame_start=None, frame_end=None): - """ - It takes snapshot of your scene view fot the given frame range. + """Take a snapshot of your scene view. + + It takes snapshot of your scene view for the given frame range. So, it's capable of generating snapshots image sequence. It works in different Houdini context e.g. Objects, Solaris From 62020ca29d2ec75b7e545fbf3d1a0b835dd86e98 Mon Sep 17 00:00:00 2001 From: MustafaJafar Date: Mon, 4 Mar 2024 15:46:28 +0200 Subject: [PATCH 10/92] update 'sceneview_snapshot' docstring --- client/ayon_core/hosts/houdini/api/lib.py | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/client/ayon_core/hosts/houdini/api/lib.py b/client/ayon_core/hosts/houdini/api/lib.py index b9a92fab0c..3cab61ff26 100644 --- a/client/ayon_core/hosts/houdini/api/lib.py +++ b/client/ayon_core/hosts/houdini/api/lib.py @@ -1083,9 +1083,11 @@ def sceneview_snapshot( It works in different Houdini context e.g. Objects, Solaris Example: - from openpype.hosts.houdini.api import lib - sceneview = hou.ui.paneTabOfType(hou.paneTabType.SceneViewer) - lib.sceneview_snapshot(sceneview) + This is how the function can be used:: + + from ayon_core.hosts.houdini.api import lib + sceneview = hou.ui.paneTabOfType(hou.paneTabType.SceneViewer) + lib.sceneview_snapshot(sceneview) Notes: .png output will render poorly, so use .jpg. From ab6d89c8c29c0dd883cbece387f8a9f872a3aaa3 Mon Sep 17 00:00:00 2001 From: MustafaJafar Date: Mon, 4 Mar 2024 16:01:08 +0200 Subject: [PATCH 11/92] wrap lib.sceneview_snapshot() into tempfile.NamedTemporaryFile --- .../plugins/publish/extract_active_view_thumbnail.py | 8 +++----- 1 file changed, 3 insertions(+), 5 deletions(-) diff --git a/client/ayon_core/hosts/houdini/plugins/publish/extract_active_view_thumbnail.py b/client/ayon_core/hosts/houdini/plugins/publish/extract_active_view_thumbnail.py index 27c4493f44..392201e865 100644 --- a/client/ayon_core/hosts/houdini/plugins/publish/extract_active_view_thumbnail.py +++ b/client/ayon_core/hosts/houdini/plugins/publish/extract_active_view_thumbnail.py @@ -39,12 +39,10 @@ class ExtractActiveViewThumbnail(publish.Extractor): def get_view_thumbnail(self, instance): - with tempfile.NamedTemporaryFile("w", suffix=".jpg") as tmp: + sceneview = lib.get_scene_viewer() + with tempfile.NamedTemporaryFile("w", suffix=".jpg", delete=False) as tmp: + lib.sceneview_snapshot(sceneview, tmp.name) thumbnail_path = tmp.name instance.context.data["cleanupFullPaths"].append(thumbnail_path) - - sceneview = lib.get_scene_viewer() - lib.sceneview_snapshot(sceneview, thumbnail_path) - return thumbnail_path From 8320ab7b5138fdc57f352e708738cbce0f40c424 Mon Sep 17 00:00:00 2001 From: MustafaJafar Date: Mon, 4 Mar 2024 16:46:34 +0200 Subject: [PATCH 12/92] Houdini: add a warning if no sceneview was found --- .../houdini/plugins/publish/extract_active_view_thumbnail.py | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/client/ayon_core/hosts/houdini/plugins/publish/extract_active_view_thumbnail.py b/client/ayon_core/hosts/houdini/plugins/publish/extract_active_view_thumbnail.py index 392201e865..1be8cb7440 100644 --- a/client/ayon_core/hosts/houdini/plugins/publish/extract_active_view_thumbnail.py +++ b/client/ayon_core/hosts/houdini/plugins/publish/extract_active_view_thumbnail.py @@ -40,6 +40,11 @@ class ExtractActiveViewThumbnail(publish.Extractor): def get_view_thumbnail(self, instance): sceneview = lib.get_scene_viewer() + if sceneview is None: + self.log.warning("Skipping Extract Active View Thumbnail" + " because no scene view was detected.") + return + with tempfile.NamedTemporaryFile("w", suffix=".jpg", delete=False) as tmp: lib.sceneview_snapshot(sceneview, tmp.name) thumbnail_path = tmp.name From a58766962356fb4d50a6219fa361c0bbb5ec9806 Mon Sep 17 00:00:00 2001 From: Roy Nieterau Date: Wed, 27 Mar 2024 00:56:11 +0100 Subject: [PATCH 13/92] Actually report the duplicated creator class --- client/ayon_core/pipeline/create/context.py | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/client/ayon_core/pipeline/create/context.py b/client/ayon_core/pipeline/create/context.py index 8c6a7f1bb6..2a779370e9 100644 --- a/client/ayon_core/pipeline/create/context.py +++ b/client/ayon_core/pipeline/create/context.py @@ -1790,10 +1790,10 @@ class CreateContext: creator_identifier = creator_class.identifier if creator_identifier in creators: - self.log.warning(( - "Duplicated Creator identifier. " - "Using first and skipping following" - )) + self.log.warning( + "Duplicated Creator identifier. Using first and " + "skipping following: {}".format(str(creator_class)) + ) continue # Filter by host name From 07cc3bba0b61fbb4a7d8260dddd43690de2d2f0b Mon Sep 17 00:00:00 2001 From: Roy Nieterau Date: Wed, 27 Mar 2024 11:09:28 +0100 Subject: [PATCH 14/92] Include identifier in warning log --- client/ayon_core/pipeline/create/context.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/client/ayon_core/pipeline/create/context.py b/client/ayon_core/pipeline/create/context.py index 2a779370e9..bf007a8461 100644 --- a/client/ayon_core/pipeline/create/context.py +++ b/client/ayon_core/pipeline/create/context.py @@ -1791,8 +1791,8 @@ class CreateContext: creator_identifier = creator_class.identifier if creator_identifier in creators: self.log.warning( - "Duplicated Creator identifier. Using first and " - "skipping following: {}".format(str(creator_class)) + "Duplicate Creator identifier: '%s'. Using first Creator " + "and skipping: %s", creator_identifier, creator_class ) continue From 1c97c78a173aa3540587c2a4f2bf34d93d8e5ae6 Mon Sep 17 00:00:00 2001 From: Roy Nieterau Date: Wed, 27 Mar 2024 15:15:03 +0100 Subject: [PATCH 15/92] Report the asset names of the other ids that were found --- .../publish/validate_node_ids_related.py | 27 ++++++++++++++++--- 1 file changed, 24 insertions(+), 3 deletions(-) diff --git a/client/ayon_core/hosts/maya/plugins/publish/validate_node_ids_related.py b/client/ayon_core/hosts/maya/plugins/publish/validate_node_ids_related.py index 992988dc7d..be52dedd61 100644 --- a/client/ayon_core/hosts/maya/plugins/publish/validate_node_ids_related.py +++ b/client/ayon_core/hosts/maya/plugins/publish/validate_node_ids_related.py @@ -1,9 +1,11 @@ +from collections import defaultdict import pyblish.api import ayon_core.hosts.maya.api.action from ayon_core.hosts.maya.api import lib from ayon_core.pipeline.publish import ( OptionalPyblishPluginMixin, PublishValidationError, ValidatePipelineOrder) +from ayon_api import get_folders class ValidateNodeIDsRelated(pyblish.api.InstancePlugin, @@ -48,12 +50,12 @@ class ValidateNodeIDsRelated(pyblish.api.InstancePlugin, @classmethod def get_invalid(cls, instance): """Return the member nodes that are invalid""" - invalid = list() - folder_id = instance.data["folderEntity"]["id"] - # We do want to check the referenced nodes as we it might be + # We do want to check the referenced nodes as it might be # part of the end product + invalid = list() + nodes_by_other_folder_ids = defaultdict(set) for node in instance: _id = lib.get_id(node) if not _id: @@ -62,5 +64,24 @@ class ValidateNodeIDsRelated(pyblish.api.InstancePlugin, node_folder_id = _id.split(":", 1)[0] if node_folder_id != folder_id: invalid.append(node) + nodes_by_other_folder_ids[node_folder_id].add(node) + + # Log what other assets were found. + if nodes_by_other_folder_ids: + project_name = instance.context.data["projectName"] + other_folder_ids = set(nodes_by_other_folder_ids.keys()) + folder_entities = get_folders(project_name=project_name, + folder_ids=other_folder_ids, + fields=["name"]) + if folder_entities: + # Log names of other assets detected + # We disregard logging nodes/ids for asset ids where no asset + # was found in the database because ValidateNodeIdsInDatabase + # takes care of that. + folder_names = {entity["name"] for entity in folder_entities} + cls.log.error( + "Found nodes related to other assets: {}" + .format(", ".join(sorted(folder_names))) + ) return invalid From 6cfa9a164680855bbbc651ff5a925532ddbb44bc Mon Sep 17 00:00:00 2001 From: Roy Nieterau Date: Wed, 27 Mar 2024 15:18:23 +0100 Subject: [PATCH 16/92] Report using the folder paths --- .../hosts/maya/plugins/publish/validate_node_ids_related.py | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/client/ayon_core/hosts/maya/plugins/publish/validate_node_ids_related.py b/client/ayon_core/hosts/maya/plugins/publish/validate_node_ids_related.py index be52dedd61..f8337ed6f0 100644 --- a/client/ayon_core/hosts/maya/plugins/publish/validate_node_ids_related.py +++ b/client/ayon_core/hosts/maya/plugins/publish/validate_node_ids_related.py @@ -72,16 +72,16 @@ class ValidateNodeIDsRelated(pyblish.api.InstancePlugin, other_folder_ids = set(nodes_by_other_folder_ids.keys()) folder_entities = get_folders(project_name=project_name, folder_ids=other_folder_ids, - fields=["name"]) + fields=["path"]) if folder_entities: # Log names of other assets detected # We disregard logging nodes/ids for asset ids where no asset # was found in the database because ValidateNodeIdsInDatabase # takes care of that. - folder_names = {entity["name"] for entity in folder_entities} + folder_paths = {entity["path"] for entity in folder_entities} cls.log.error( "Found nodes related to other assets: {}" - .format(", ".join(sorted(folder_names))) + .format(", ".join(sorted(folder_paths))) ) return invalid From 4dd44b08b78f3a803c0e738841067096a5cea943 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ond=C5=99ej=20Samohel?= Date: Wed, 27 Mar 2024 17:19:52 +0100 Subject: [PATCH 17/92] :art: add support for Maya 2025 some changes to support PySide6 there --- client/ayon_core/hosts/maya/addon.py | 8 ++++---- .../maya/vendor/python}/capture.py | 6 +----- pyproject.toml | 2 +- .../applications/server/applications.json | 20 +++++++++++++++++++ server_addon/applications/server/version.py | 2 +- 5 files changed, 27 insertions(+), 11 deletions(-) rename client/ayon_core/{vendor/python/common => hosts/maya/vendor/python}/capture.py (99%) diff --git a/client/ayon_core/hosts/maya/addon.py b/client/ayon_core/hosts/maya/addon.py index c68aa4c911..1ad0fcf4cf 100644 --- a/client/ayon_core/hosts/maya/addon.py +++ b/client/ayon_core/hosts/maya/addon.py @@ -22,15 +22,15 @@ class MayaAddon(AYONAddon, IHostAddon): if norm_path not in new_python_paths: new_python_paths.append(norm_path) + # add vendor path + new_python_paths.append( + os.path.join(MAYA_ROOT_DIR, "vendor", "python") + ) env["PYTHONPATH"] = os.pathsep.join(new_python_paths) # Set default environments envs = { "AYON_LOG_NO_COLORS": "1", - # For python module 'qtpy' - "QT_API": "PySide2", - # For python module 'Qt' - "QT_PREFERRED_BINDING": "PySide2" } for key, value in envs.items(): env[key] = value diff --git a/client/ayon_core/vendor/python/common/capture.py b/client/ayon_core/hosts/maya/vendor/python/capture.py similarity index 99% rename from client/ayon_core/vendor/python/common/capture.py rename to client/ayon_core/hosts/maya/vendor/python/capture.py index 224699f916..7a3be38f56 100644 --- a/client/ayon_core/vendor/python/common/capture.py +++ b/client/ayon_core/hosts/maya/vendor/python/capture.py @@ -12,11 +12,7 @@ import logging from maya import cmds from maya import mel -try: - from PySide2 import QtGui, QtWidgets -except ImportError: - from PySide import QtGui - QtWidgets = QtGui +from qtpy import QtGui, QtWidgets version_info = (2, 3, 0) diff --git a/pyproject.toml b/pyproject.toml index ee124ddc2d..ec38b746dd 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -92,7 +92,7 @@ line-ending = "auto" [tool.codespell] # Ignore words that are not in the dictionary. -ignore-words-list = "ayon,ynput" +ignore-words-list = "ayon,ynput,developpement" skip = "./.*,./package/*,*/vendor/*,*/unreal/integration/*,*/aftereffects/api/extension/js/libs/*" count = true quiet-level = 3 diff --git a/server_addon/applications/server/applications.json b/server_addon/applications/server/applications.json index 85bf6f1dda..e4b72fdff9 100644 --- a/server_addon/applications/server/applications.json +++ b/server_addon/applications/server/applications.json @@ -7,6 +7,26 @@ "host_name": "maya", "environment": "{\n \"MAYA_DISABLE_CLIC_IPM\": \"Yes\",\n \"MAYA_DISABLE_CIP\": \"Yes\",\n \"MAYA_DISABLE_CER\": \"Yes\",\n \"PYMEL_SKIP_MEL_INIT\": \"Yes\",\n \"LC_ALL\": \"C\"\n}\n", "variants": [ + { + "name": "2025", + "label": "2025", + "executables": { + "windows": [ + "C:\\Program Files\\Autodesk\\Maya2025\\bin\\maya.exe" + ], + "darwin": ["/Applications/Autodesk/maya2025/Maya.app"], + "linux": [ + "/usr/autodesk/maya2025/bin/maya" + ] + }, + "arguments": { + "windows": [], + "darwin": [], + "linux": [] + }, + "environment": "{\n \"MAYA_VERSION\": \"2025\"\n}", + "use_python_2": false + }, { "name": "2024", "label": "2024", diff --git a/server_addon/applications/server/version.py b/server_addon/applications/server/version.py index 9cb17e7976..c11f861afb 100644 --- a/server_addon/applications/server/version.py +++ b/server_addon/applications/server/version.py @@ -1 +1 @@ -__version__ = "0.1.8" +__version__ = "0.1.9" From bbbea73a8d21a3d99465d54071ea1ac9a4ad14c0 Mon Sep 17 00:00:00 2001 From: Roy Nieterau Date: Thu, 28 Mar 2024 15:36:55 +0100 Subject: [PATCH 18/92] Optimize collect inputs by caching scene containers once --- .../houdini/plugins/publish/collect_inputs.py | 78 ++++++++++++------- 1 file changed, 48 insertions(+), 30 deletions(-) diff --git a/client/ayon_core/hosts/houdini/plugins/publish/collect_inputs.py b/client/ayon_core/hosts/houdini/plugins/publish/collect_inputs.py index 7d7fabb315..3523acee06 100644 --- a/client/ayon_core/hosts/houdini/plugins/publish/collect_inputs.py +++ b/client/ayon_core/hosts/houdini/plugins/publish/collect_inputs.py @@ -1,9 +1,21 @@ +from collections import deque + import pyblish.api from ayon_core.pipeline import registered_host -def collect_input_containers(nodes): +def get_container_members(container): + node = container["node"] + # Usually the loaded containers don't have any complex references + # and the contained children should be all we need. So we disregard + # checking for .references() on the nodes. + members = set(node.allSubChildren()) + members.add(node) # include the node itself + return members + + +def collect_input_containers(containers, nodes): """Collect containers that contain any of the node in `nodes`. This will return any loaded Avalon container that contains at least one of @@ -11,30 +23,13 @@ def collect_input_containers(nodes): there are member nodes of that container. Returns: - list: Input avalon containers + list: Loaded containers that contain the `nodes` """ - - # Lookup by node ids - lookup = frozenset(nodes) - - containers = [] - host = registered_host() - for container in host.ls(): - - node = container["node"] - - # Usually the loaded containers don't have any complex references - # and the contained children should be all we need. So we disregard - # checking for .references() on the nodes. - members = set(node.allSubChildren()) - members.add(node) # include the node itself - - # If there's an intersection - if not lookup.isdisjoint(members): - containers.append(container) - - return containers + # Assume the containers have collected their cached '_members' data + # in the collector. + return [container for container in containers + if any(node in container["_members"] for node in nodes)] def iter_upstream(node): @@ -54,7 +49,7 @@ def iter_upstream(node): ) # Initialize process queue with the node's ancestors itself - queue = list(upstream) + queue = deque(upstream) collected = set(upstream) # Traverse upstream references for all nodes and yield them as we @@ -72,6 +67,10 @@ def iter_upstream(node): # Include the references' ancestors that have not been collected yet. for reference in references: + if reference in collected: + # Might have been collected in previous iteration + continue + ancestors = reference.inputAncestors( include_ref_inputs=True, follow_subnets=True ) @@ -108,13 +107,32 @@ class CollectUpstreamInputs(pyblish.api.InstancePlugin): ) return - # Collect all upstream parents - nodes = list(iter_upstream(output)) - nodes.append(output) + # For large scenes the querying of "host.ls()" can be relatively slow + # e.g. up to a second. Many instances calling it easily slows this + # down. As such, we cache it so we trigger it only once. + # todo: Instead of hidden cache make "CollectContainers" plug-in + cache_key = "__cache_containers" + scene_containers = instance.context.data.get(cache_key, None) + if scene_containers is None: + # Query the scenes' containers if there's no cache yet + host = registered_host() + scene_containers = list(host.ls()) + for container in scene_containers: + # Embed the members into the container dictionary + container_members = set(get_container_members(container)) + container["_members"] = container_members + instance.context.data["__cache_containers"] = scene_containers - # Collect containers for the given set of nodes - containers = collect_input_containers(nodes) + inputs = [] + if scene_containers: + # Collect all upstream parents + nodes = list(iter_upstream(output)) + nodes.append(output) + + # Collect containers for the given set of nodes + containers = collect_input_containers(scene_containers, nodes) + + inputs = [c["representation"] for c in containers] - inputs = [c["representation"] for c in containers] instance.data["inputRepresentations"] = inputs self.log.debug("Collected inputs: %s" % inputs) From 81e6d1dd896be17a1916139de8e7d40203a37b92 Mon Sep 17 00:00:00 2001 From: Roy Nieterau Date: Fri, 29 Mar 2024 13:20:48 +0100 Subject: [PATCH 19/92] Do not error if there are references that maya considers invalid, instead ignore them --- client/ayon_core/hosts/maya/api/lib.py | 34 +++++++++++++++++++++++++- 1 file changed, 33 insertions(+), 1 deletion(-) diff --git a/client/ayon_core/hosts/maya/api/lib.py b/client/ayon_core/hosts/maya/api/lib.py index b18d3a0c33..4541197ab5 100644 --- a/client/ayon_core/hosts/maya/api/lib.py +++ b/client/ayon_core/hosts/maya/api/lib.py @@ -1832,6 +1832,29 @@ def apply_attributes(attributes, nodes_by_id): set_attribute(attr, value, node) +def is_valid_reference_node(reference_node): + """Return whether Maya considers the reference node a valid reference. + + Maya might report an error when using `maya.cmds.referenceQuery`: + Reference node 'reference_node' is not associated with a reference file. + + Note that this does *not* check whether the reference node points to an + existing file. Instead it only returns whether maya considers it valid + and thus is not an unassociated reference node + + Arguments: + reference_node (str): Reference node name + + Returns: + bool: Whether reference node is a valid reference + + """ + sel = OpenMaya.MSelectionList() + sel.add(reference_node) + depend_node = sel.getDependNode(0) + return OpenMaya.MFnReference(depend_node).isValidReference() + + def get_container_members(container): """Returns the members of a container. This includes the nodes from any loaded references in the container. @@ -1857,7 +1880,16 @@ def get_container_members(container): if ref.rsplit(":", 1)[-1].startswith("_UNKNOWN_REF_NODE_"): continue - reference_members = cmds.referenceQuery(ref, nodes=True, dagPath=True) + try: + reference_members = cmds.referenceQuery(ref, + nodes=True, + dagPath=True) + except RuntimeError: + # Ignore reference nodes that are not associated with a + # referenced file on which `referenceQuery` command fails + if not is_valid_reference_node(ref): + continue + raise reference_members = cmds.ls(reference_members, long=True, objectsOnly=True) From 71bb5552f38ea72e1bab07f41281cc3e595070ae Mon Sep 17 00:00:00 2001 From: MustafaJafar Date: Tue, 2 Apr 2024 12:30:33 +0200 Subject: [PATCH 20/92] BigRoy's comments - Better doc strings --- client/ayon_core/hosts/houdini/api/lib.py | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/client/ayon_core/hosts/houdini/api/lib.py b/client/ayon_core/hosts/houdini/api/lib.py index dfdca62b61..111b230252 100644 --- a/client/ayon_core/hosts/houdini/api/lib.py +++ b/client/ayon_core/hosts/houdini/api/lib.py @@ -1003,6 +1003,9 @@ def get_scene_viewer(): Return an instance of a visible viewport. There may be many, some could be closed, any visible are current + + Returns: + Optional[hou.SceneViewer]: A scene viewer, if any. """ panes = hou.ui.paneTabs() panes = [x for x in panes if x.type() == hou.paneTabType.SceneViewer] @@ -1045,7 +1048,9 @@ def sceneview_snapshot( Args: sceneview (hou.SceneViewer): The scene view pane from which you want to take a snapshot. - filepath (str): thumbnail filepath. + filepath (str): thumbnail filepath. it expects `$F4` token + when frame_end is bigger than frame_star other wise + each frame will override its predecessor. frame_start (int): the frame at which snapshot starts frame_end (int): the frame at which snapshot ends """ From f543e560011a6bae6346e9a611ec1cc102fbb690 Mon Sep 17 00:00:00 2001 From: MustafaJafar Date: Tue, 2 Apr 2024 12:36:22 +0200 Subject: [PATCH 21/92] BigRoy's comment - Better logic --- .../publish/extract_active_view_thumbnail.py | 22 ++++++++++--------- 1 file changed, 12 insertions(+), 10 deletions(-) diff --git a/client/ayon_core/hosts/houdini/plugins/publish/extract_active_view_thumbnail.py b/client/ayon_core/hosts/houdini/plugins/publish/extract_active_view_thumbnail.py index 1be8cb7440..aedcb1da02 100644 --- a/client/ayon_core/hosts/houdini/plugins/publish/extract_active_view_thumbnail.py +++ b/client/ayon_core/hosts/houdini/plugins/publish/extract_active_view_thumbnail.py @@ -27,22 +27,24 @@ class ExtractActiveViewThumbnail(publish.Extractor): return thumbnail = instance.data.get("thumbnailPath") - if not thumbnail: - view_thumbnail = self.get_view_thumbnail(instance) - if not view_thumbnail: - return + if thumbnail: + # A thumbnail was already set for this instance + return - self.log.debug("Setting instance thumbnail path to: {}".format( - view_thumbnail - )) - instance.data["thumbnailPath"] = view_thumbnail + view_thumbnail = self.get_view_thumbnail(instance) + if not view_thumbnail: + return + self.log.debug("Setting instance thumbnail path to: {}" + .format(view_thumbnail) + ) + instance.data["thumbnailPath"] = view_thumbnail def get_view_thumbnail(self, instance): sceneview = lib.get_scene_viewer() if sceneview is None: - self.log.warning("Skipping Extract Active View Thumbnail" - " because no scene view was detected.") + self.log.debug("Skipping Extract Active View Thumbnail" + " because no scene view was detected.") return with tempfile.NamedTemporaryFile("w", suffix=".jpg", delete=False) as tmp: From d68664b20b22dbf9051d78ec19ac4653e3f97b0d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ond=C5=99ej=20Samohel?= Date: Tue, 2 Apr 2024 14:21:12 +0200 Subject: [PATCH 22/92] :bug: fix compatibility with Qt6 --- client/ayon_core/hosts/maya/vendor/python/capture.py | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/client/ayon_core/hosts/maya/vendor/python/capture.py b/client/ayon_core/hosts/maya/vendor/python/capture.py index 7a3be38f56..4ccfdb35f3 100644 --- a/client/ayon_core/hosts/maya/vendor/python/capture.py +++ b/client/ayon_core/hosts/maya/vendor/python/capture.py @@ -869,7 +869,11 @@ def _get_screen_size(): if _in_standalone(): return [0, 0] - rect = QtWidgets.QDesktopWidget().screenGeometry(-1) + try: + rect = QtWidgets.QDesktopWidget().screenGeometry(-1) + except AttributeError: + # in Qt6 it is a different call + rect = QtWidgets.QApplication.primaryScreen().availableGeometry() return [rect.width(), rect.height()] From ba9350e945e05c9b5af2315fb0e39c339a8e05c4 Mon Sep 17 00:00:00 2001 From: Roy Nieterau Date: Fri, 5 Apr 2024 12:00:27 +0200 Subject: [PATCH 23/92] Update client/ayon_core/hosts/houdini/plugins/publish/collect_inputs.py Co-authored-by: Kayla Man <64118225+moonyuet@users.noreply.github.com> --- .../ayon_core/hosts/houdini/plugins/publish/collect_inputs.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/client/ayon_core/hosts/houdini/plugins/publish/collect_inputs.py b/client/ayon_core/hosts/houdini/plugins/publish/collect_inputs.py index 3523acee06..6cf6bbf430 100644 --- a/client/ayon_core/hosts/houdini/plugins/publish/collect_inputs.py +++ b/client/ayon_core/hosts/houdini/plugins/publish/collect_inputs.py @@ -121,7 +121,7 @@ class CollectUpstreamInputs(pyblish.api.InstancePlugin): # Embed the members into the container dictionary container_members = set(get_container_members(container)) container["_members"] = container_members - instance.context.data["__cache_containers"] = scene_containers + instance.context.data[cache_key] = scene_containers inputs = [] if scene_containers: From 825add6c2cf51be99b8a1454e357f1ca7acfa891 Mon Sep 17 00:00:00 2001 From: Roy Nieterau Date: Tue, 9 Apr 2024 10:26:40 +0200 Subject: [PATCH 24/92] Fix support for non-unique top group names --- .../hosts/maya/plugins/publish/validate_model_content.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/client/ayon_core/hosts/maya/plugins/publish/validate_model_content.py b/client/ayon_core/hosts/maya/plugins/publish/validate_model_content.py index 1001bee91f..bbc644c3db 100644 --- a/client/ayon_core/hosts/maya/plugins/publish/validate_model_content.py +++ b/client/ayon_core/hosts/maya/plugins/publish/validate_model_content.py @@ -79,7 +79,7 @@ class ValidateModelContent(pyblish.api.InstancePlugin, return [instance.data["instance_node"]] # Ensure single top group - top_parents = {x.split("|", 2)[1] for x in content_instance} + top_parents = {"|" + x.split("|", 2)[1] for x in content_instance} if cls.validate_top_group and len(top_parents) != 1: cls.log.error( "A model instance must have exactly one top group. " From 17e7c9ff00aebb94f5198a9dcf30407f41a5f301 Mon Sep 17 00:00:00 2001 From: Jakub Trllo <43494761+iLLiCiTiT@users.noreply.github.com> Date: Tue, 9 Apr 2024 17:23:45 +0200 Subject: [PATCH 25/92] change 'representations' attribute on loader plugin to 'set' --- client/ayon_core/pipeline/load/plugins.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/client/ayon_core/pipeline/load/plugins.py b/client/ayon_core/pipeline/load/plugins.py index 064af4ddc1..3f47ec421e 100644 --- a/client/ayon_core/pipeline/load/plugins.py +++ b/client/ayon_core/pipeline/load/plugins.py @@ -24,7 +24,7 @@ class LoaderPlugin(list): """ product_types = set() - representations = [] + representations = set() extensions = {"*"} order = 0 is_multiple_contexts_compatible = False From 43b4be851ede5043729446de171d30b0fd717640 Mon Sep 17 00:00:00 2001 From: Jakub Trllo <43494761+iLLiCiTiT@users.noreply.github.com> Date: Tue, 9 Apr 2024 17:26:28 +0200 Subject: [PATCH 26/92] use 'set' for 'representations' attribute --- .../hosts/aftereffects/plugins/load/load_background.py | 2 +- .../ayon_core/hosts/aftereffects/plugins/load/load_file.py | 2 +- .../ayon_core/hosts/blender/plugins/load/import_workfile.py | 4 ++-- client/ayon_core/hosts/blender/plugins/load/load_abc.py | 2 +- client/ayon_core/hosts/blender/plugins/load/load_action.py | 2 +- .../ayon_core/hosts/blender/plugins/load/load_animation.py | 2 +- client/ayon_core/hosts/blender/plugins/load/load_audio.py | 2 +- client/ayon_core/hosts/blender/plugins/load/load_blend.py | 2 +- .../ayon_core/hosts/blender/plugins/load/load_blendscene.py | 2 +- .../ayon_core/hosts/blender/plugins/load/load_camera_abc.py | 2 +- .../ayon_core/hosts/blender/plugins/load/load_camera_fbx.py | 2 +- client/ayon_core/hosts/blender/plugins/load/load_fbx.py | 2 +- .../hosts/blender/plugins/load/load_layout_json.py | 2 +- client/ayon_core/hosts/blender/plugins/load/load_look.py | 2 +- client/ayon_core/hosts/flame/plugins/load/load_clip.py | 2 +- .../ayon_core/hosts/flame/plugins/load/load_clip_batch.py | 2 +- client/ayon_core/hosts/fusion/plugins/load/actions.py | 4 ++-- client/ayon_core/hosts/fusion/plugins/load/load_alembic.py | 2 +- client/ayon_core/hosts/fusion/plugins/load/load_fbx.py | 2 +- client/ayon_core/hosts/fusion/plugins/load/load_sequence.py | 2 +- client/ayon_core/hosts/fusion/plugins/load/load_usd.py | 2 +- client/ayon_core/hosts/fusion/plugins/load/load_workfile.py | 2 +- client/ayon_core/hosts/harmony/api/README.md | 2 +- client/ayon_core/hosts/harmony/plugins/load/load_audio.py | 2 +- .../ayon_core/hosts/harmony/plugins/load/load_background.py | 2 +- .../hosts/harmony/plugins/load/load_imagesequence.py | 2 +- client/ayon_core/hosts/harmony/plugins/load/load_palette.py | 2 +- .../ayon_core/hosts/harmony/plugins/load/load_template.py | 2 +- .../hosts/harmony/plugins/load/load_template_workfile.py | 4 ++-- client/ayon_core/hosts/hiero/plugins/load/load_clip.py | 2 +- client/ayon_core/hosts/hiero/plugins/load/load_effects.py | 2 +- client/ayon_core/hosts/houdini/plugins/load/actions.py | 4 ++-- client/ayon_core/hosts/houdini/plugins/load/load_alembic.py | 2 +- .../hosts/houdini/plugins/load/load_alembic_archive.py | 2 +- client/ayon_core/hosts/houdini/plugins/load/load_ass.py | 2 +- client/ayon_core/hosts/houdini/plugins/load/load_bgeo.py | 4 ++-- client/ayon_core/hosts/houdini/plugins/load/load_camera.py | 2 +- client/ayon_core/hosts/houdini/plugins/load/load_fbx.py | 2 +- .../ayon_core/hosts/houdini/plugins/load/load_filepath.py | 2 +- client/ayon_core/hosts/houdini/plugins/load/load_hda.py | 2 +- client/ayon_core/hosts/houdini/plugins/load/load_image.py | 2 +- .../hosts/houdini/plugins/load/load_redshift_proxy.py | 2 +- .../ayon_core/hosts/houdini/plugins/load/load_usd_layer.py | 2 +- .../hosts/houdini/plugins/load/load_usd_reference.py | 2 +- client/ayon_core/hosts/houdini/plugins/load/load_usd_sop.py | 2 +- client/ayon_core/hosts/houdini/plugins/load/load_vdb.py | 2 +- client/ayon_core/hosts/houdini/plugins/load/show_usdview.py | 2 +- client/ayon_core/hosts/max/plugins/load/load_camera_fbx.py | 2 +- client/ayon_core/hosts/max/plugins/load/load_max_scene.py | 2 +- client/ayon_core/hosts/max/plugins/load/load_model.py | 2 +- client/ayon_core/hosts/max/plugins/load/load_model_fbx.py | 2 +- client/ayon_core/hosts/max/plugins/load/load_model_obj.py | 2 +- client/ayon_core/hosts/max/plugins/load/load_model_usd.py | 2 +- client/ayon_core/hosts/max/plugins/load/load_pointcache.py | 2 +- .../hosts/max/plugins/load/load_pointcache_ornatrix.py | 2 +- client/ayon_core/hosts/max/plugins/load/load_pointcloud.py | 2 +- .../ayon_core/hosts/max/plugins/load/load_redshift_proxy.py | 2 +- client/ayon_core/hosts/max/plugins/load/load_tycache.py | 2 +- client/ayon_core/hosts/maya/plugins/load/_load_animation.py | 4 ++-- client/ayon_core/hosts/maya/plugins/load/actions.py | 6 +++--- .../hosts/maya/plugins/load/load_arnold_standin.py | 2 +- client/ayon_core/hosts/maya/plugins/load/load_assembly.py | 2 +- client/ayon_core/hosts/maya/plugins/load/load_audio.py | 2 +- client/ayon_core/hosts/maya/plugins/load/load_gpucache.py | 2 +- client/ayon_core/hosts/maya/plugins/load/load_image.py | 2 +- .../ayon_core/hosts/maya/plugins/load/load_image_plane.py | 4 ++-- client/ayon_core/hosts/maya/plugins/load/load_look.py | 2 +- client/ayon_core/hosts/maya/plugins/load/load_matchmove.py | 2 +- client/ayon_core/hosts/maya/plugins/load/load_maya_usd.py | 2 +- .../hosts/maya/plugins/load/load_multiverse_usd.py | 2 +- .../hosts/maya/plugins/load/load_multiverse_usd_over.py | 2 +- .../hosts/maya/plugins/load/load_redshift_proxy.py | 2 +- client/ayon_core/hosts/maya/plugins/load/load_reference.py | 4 ++-- .../ayon_core/hosts/maya/plugins/load/load_rendersetup.py | 2 +- .../ayon_core/hosts/maya/plugins/load/load_vdb_to_arnold.py | 2 +- .../hosts/maya/plugins/load/load_vdb_to_redshift.py | 2 +- .../ayon_core/hosts/maya/plugins/load/load_vdb_to_vray.py | 2 +- client/ayon_core/hosts/maya/plugins/load/load_vrayproxy.py | 2 +- client/ayon_core/hosts/maya/plugins/load/load_vrayscene.py | 2 +- client/ayon_core/hosts/maya/plugins/load/load_xgen.py | 2 +- client/ayon_core/hosts/maya/plugins/load/load_yeti_cache.py | 2 +- client/ayon_core/hosts/maya/plugins/load/load_yeti_rig.py | 2 +- client/ayon_core/hosts/nuke/plugins/load/actions.py | 4 ++-- client/ayon_core/hosts/nuke/plugins/load/load_backdrop.py | 2 +- client/ayon_core/hosts/nuke/plugins/load/load_camera_abc.py | 2 +- client/ayon_core/hosts/nuke/plugins/load/load_clip.py | 2 +- client/ayon_core/hosts/nuke/plugins/load/load_effects.py | 2 +- client/ayon_core/hosts/nuke/plugins/load/load_effects_ip.py | 2 +- client/ayon_core/hosts/nuke/plugins/load/load_gizmo.py | 2 +- client/ayon_core/hosts/nuke/plugins/load/load_gizmo_ip.py | 2 +- client/ayon_core/hosts/nuke/plugins/load/load_image.py | 2 +- client/ayon_core/hosts/nuke/plugins/load/load_matchmove.py | 2 +- client/ayon_core/hosts/nuke/plugins/load/load_model.py | 2 +- client/ayon_core/hosts/nuke/plugins/load/load_ociolook.py | 2 +- .../hosts/nuke/plugins/load/load_script_precomp.py | 2 +- client/ayon_core/hosts/photoshop/api/README.md | 2 +- client/ayon_core/hosts/photoshop/plugins/load/load_image.py | 2 +- .../photoshop/plugins/load/load_image_from_sequence.py | 2 +- .../hosts/photoshop/plugins/load/load_reference.py | 2 +- client/ayon_core/hosts/resolve/plugins/load/load_clip.py | 2 +- .../hosts/substancepainter/plugins/load/load_mesh.py | 2 +- client/ayon_core/hosts/tvpaint/plugins/load/load_image.py | 2 +- .../hosts/tvpaint/plugins/load/load_reference_image.py | 2 +- client/ayon_core/hosts/tvpaint/plugins/load/load_sound.py | 2 +- .../ayon_core/hosts/tvpaint/plugins/load/load_workfile.py | 2 +- .../hosts/unreal/plugins/load/load_alembic_animation.py | 2 +- .../ayon_core/hosts/unreal/plugins/load/load_animation.py | 2 +- client/ayon_core/hosts/unreal/plugins/load/load_camera.py | 2 +- .../hosts/unreal/plugins/load/load_geometrycache_abc.py | 2 +- client/ayon_core/hosts/unreal/plugins/load/load_layout.py | 2 +- .../hosts/unreal/plugins/load/load_layout_existing.py | 2 +- .../hosts/unreal/plugins/load/load_skeletalmesh_abc.py | 2 +- .../hosts/unreal/plugins/load/load_skeletalmesh_fbx.py | 2 +- .../hosts/unreal/plugins/load/load_staticmesh_abc.py | 2 +- .../hosts/unreal/plugins/load/load_staticmesh_fbx.py | 2 +- client/ayon_core/hosts/unreal/plugins/load/load_uasset.py | 4 ++-- .../ayon_core/hosts/unreal/plugins/load/load_yeticache.py | 2 +- client/ayon_core/plugins/load/copy_file.py | 2 +- client/ayon_core/plugins/load/copy_file_path.py | 2 +- client/ayon_core/plugins/load/delete_old_versions.py | 2 +- client/ayon_core/plugins/load/delivery.py | 2 +- client/ayon_core/plugins/load/open_file.py | 2 +- client/ayon_core/plugins/load/push_to_library.py | 2 +- 123 files changed, 135 insertions(+), 135 deletions(-) diff --git a/client/ayon_core/hosts/aftereffects/plugins/load/load_background.py b/client/ayon_core/hosts/aftereffects/plugins/load/load_background.py index 7c9bd2fcfd..5685011d5f 100644 --- a/client/ayon_core/hosts/aftereffects/plugins/load/load_background.py +++ b/client/ayon_core/hosts/aftereffects/plugins/load/load_background.py @@ -21,7 +21,7 @@ class BackgroundLoader(api.AfterEffectsLoader): """ label = "Load JSON Background" product_types = {"background"} - representations = ["json"] + representations = {"json"} def load(self, context, name=None, namespace=None, data=None): stub = self.get_stub() diff --git a/client/ayon_core/hosts/aftereffects/plugins/load/load_file.py b/client/ayon_core/hosts/aftereffects/plugins/load/load_file.py index 79e791af7b..4b81201722 100644 --- a/client/ayon_core/hosts/aftereffects/plugins/load/load_file.py +++ b/client/ayon_core/hosts/aftereffects/plugins/load/load_file.py @@ -20,7 +20,7 @@ class FileLoader(api.AfterEffectsLoader): "review", "audio", } - representations = ["*"] + representations = {"*"} def load(self, context, name=None, namespace=None, data=None): stub = self.get_stub() diff --git a/client/ayon_core/hosts/blender/plugins/load/import_workfile.py b/client/ayon_core/hosts/blender/plugins/load/import_workfile.py index 3aa73a5143..d2e58c7752 100644 --- a/client/ayon_core/hosts/blender/plugins/load/import_workfile.py +++ b/client/ayon_core/hosts/blender/plugins/load/import_workfile.py @@ -43,7 +43,7 @@ class AppendBlendLoader(plugin.AssetLoader): so you could also use it as a new base. """ - representations = ["blend"] + representations = {"blend"} product_types = {"workfile"} label = "Append Workfile" @@ -68,7 +68,7 @@ class ImportBlendLoader(plugin.AssetLoader): so you could also use it as a new base. """ - representations = ["blend"] + representations = {"blend"} product_types = {"workfile"} label = "Import Workfile" diff --git a/client/ayon_core/hosts/blender/plugins/load/load_abc.py b/client/ayon_core/hosts/blender/plugins/load/load_abc.py index 938ae6106b..c074b5ed13 100644 --- a/client/ayon_core/hosts/blender/plugins/load/load_abc.py +++ b/client/ayon_core/hosts/blender/plugins/load/load_abc.py @@ -27,7 +27,7 @@ class CacheModelLoader(plugin.AssetLoader): At least for now it only supports Alembic files. """ product_types = {"model", "pointcache", "animation"} - representations = ["abc"] + representations = {"abc"} label = "Load Alembic" icon = "code-fork" diff --git a/client/ayon_core/hosts/blender/plugins/load/load_action.py b/client/ayon_core/hosts/blender/plugins/load/load_action.py index 4161f8bff3..8135df042a 100644 --- a/client/ayon_core/hosts/blender/plugins/load/load_action.py +++ b/client/ayon_core/hosts/blender/plugins/load/load_action.py @@ -25,7 +25,7 @@ class BlendActionLoader(plugin.AssetLoader): """ product_types = {"action"} - representations = ["blend"] + representations = {"blend"} label = "Link Action" icon = "code-fork" diff --git a/client/ayon_core/hosts/blender/plugins/load/load_animation.py b/client/ayon_core/hosts/blender/plugins/load/load_animation.py index effb91c48c..c9f3b33a6f 100644 --- a/client/ayon_core/hosts/blender/plugins/load/load_animation.py +++ b/client/ayon_core/hosts/blender/plugins/load/load_animation.py @@ -17,7 +17,7 @@ class BlendAnimationLoader(plugin.AssetLoader): """ product_types = {"animation"} - representations = ["blend"] + representations = {"blend"} label = "Link Animation" icon = "code-fork" diff --git a/client/ayon_core/hosts/blender/plugins/load/load_audio.py b/client/ayon_core/hosts/blender/plugins/load/load_audio.py index db83c4bca2..3d2f412e2b 100644 --- a/client/ayon_core/hosts/blender/plugins/load/load_audio.py +++ b/client/ayon_core/hosts/blender/plugins/load/load_audio.py @@ -21,7 +21,7 @@ class AudioLoader(plugin.AssetLoader): """Load audio in Blender.""" product_types = {"audio"} - representations = ["wav"] + representations = {"wav"} label = "Load Audio" icon = "volume-up" diff --git a/client/ayon_core/hosts/blender/plugins/load/load_blend.py b/client/ayon_core/hosts/blender/plugins/load/load_blend.py index 1984193a30..f9377d615c 100644 --- a/client/ayon_core/hosts/blender/plugins/load/load_blend.py +++ b/client/ayon_core/hosts/blender/plugins/load/load_blend.py @@ -21,7 +21,7 @@ class BlendLoader(plugin.AssetLoader): """Load assets from a .blend file.""" product_types = {"model", "rig", "layout", "camera"} - representations = ["blend"] + representations = {"blend"} label = "Append Blend" icon = "code-fork" diff --git a/client/ayon_core/hosts/blender/plugins/load/load_blendscene.py b/client/ayon_core/hosts/blender/plugins/load/load_blendscene.py index 627941752f..f91d828d83 100644 --- a/client/ayon_core/hosts/blender/plugins/load/load_blendscene.py +++ b/client/ayon_core/hosts/blender/plugins/load/load_blendscene.py @@ -19,7 +19,7 @@ class BlendSceneLoader(plugin.AssetLoader): """Load assets from a .blend file.""" product_types = {"blendScene"} - representations = ["blend"] + representations = {"blend"} label = "Append Blend" icon = "code-fork" diff --git a/client/ayon_core/hosts/blender/plugins/load/load_camera_abc.py b/client/ayon_core/hosts/blender/plugins/load/load_camera_abc.py index e677fc3e58..6178578081 100644 --- a/client/ayon_core/hosts/blender/plugins/load/load_camera_abc.py +++ b/client/ayon_core/hosts/blender/plugins/load/load_camera_abc.py @@ -24,7 +24,7 @@ class AbcCameraLoader(plugin.AssetLoader): """ product_types = {"camera"} - representations = ["abc"] + representations = {"abc"} label = "Load Camera (ABC)" icon = "code-fork" diff --git a/client/ayon_core/hosts/blender/plugins/load/load_camera_fbx.py b/client/ayon_core/hosts/blender/plugins/load/load_camera_fbx.py index 14d61a6395..a510d42850 100644 --- a/client/ayon_core/hosts/blender/plugins/load/load_camera_fbx.py +++ b/client/ayon_core/hosts/blender/plugins/load/load_camera_fbx.py @@ -24,7 +24,7 @@ class FbxCameraLoader(plugin.AssetLoader): """ product_types = {"camera"} - representations = ["fbx"] + representations = {"fbx"} label = "Load Camera (FBX)" icon = "code-fork" diff --git a/client/ayon_core/hosts/blender/plugins/load/load_fbx.py b/client/ayon_core/hosts/blender/plugins/load/load_fbx.py index 0042482284..e323d49dea 100644 --- a/client/ayon_core/hosts/blender/plugins/load/load_fbx.py +++ b/client/ayon_core/hosts/blender/plugins/load/load_fbx.py @@ -24,7 +24,7 @@ class FbxModelLoader(plugin.AssetLoader): """ product_types = {"model", "rig"} - representations = ["fbx"] + representations = {"fbx"} label = "Load FBX" icon = "code-fork" diff --git a/client/ayon_core/hosts/blender/plugins/load/load_layout_json.py b/client/ayon_core/hosts/blender/plugins/load/load_layout_json.py index 7a3da1882e..bea997108b 100644 --- a/client/ayon_core/hosts/blender/plugins/load/load_layout_json.py +++ b/client/ayon_core/hosts/blender/plugins/load/load_layout_json.py @@ -27,7 +27,7 @@ class JsonLayoutLoader(plugin.AssetLoader): """Load layout published from Unreal.""" product_types = {"layout"} - representations = ["json"] + representations = {"json"} label = "Load Layout" icon = "code-fork" diff --git a/client/ayon_core/hosts/blender/plugins/load/load_look.py b/client/ayon_core/hosts/blender/plugins/load/load_look.py index ce677a8471..75401f94ec 100644 --- a/client/ayon_core/hosts/blender/plugins/load/load_look.py +++ b/client/ayon_core/hosts/blender/plugins/load/load_look.py @@ -24,7 +24,7 @@ class BlendLookLoader(plugin.AssetLoader): """ product_types = {"look"} - representations = ["json"] + representations = {"json"} label = "Load Look" icon = "code-fork" diff --git a/client/ayon_core/hosts/flame/plugins/load/load_clip.py b/client/ayon_core/hosts/flame/plugins/load/load_clip.py index f528caeb29..40ab9c038b 100644 --- a/client/ayon_core/hosts/flame/plugins/load/load_clip.py +++ b/client/ayon_core/hosts/flame/plugins/load/load_clip.py @@ -18,7 +18,7 @@ class LoadClip(opfapi.ClipLoader): """ product_types = {"render2d", "source", "plate", "render", "review"} - representations = ["*"] + representations = {"*"} extensions = set( ext.lstrip(".") for ext in IMAGE_EXTENSIONS.union(VIDEO_EXTENSIONS) ) diff --git a/client/ayon_core/hosts/flame/plugins/load/load_clip_batch.py b/client/ayon_core/hosts/flame/plugins/load/load_clip_batch.py index 9bdd467d63..1b23a8b465 100644 --- a/client/ayon_core/hosts/flame/plugins/load/load_clip_batch.py +++ b/client/ayon_core/hosts/flame/plugins/load/load_clip_batch.py @@ -17,7 +17,7 @@ class LoadClipBatch(opfapi.ClipLoader): """ product_types = {"render2d", "source", "plate", "render", "review"} - representations = ["*"] + representations = {"*"} extensions = set( ext.lstrip(".") for ext in IMAGE_EXTENSIONS.union(VIDEO_EXTENSIONS) ) diff --git a/client/ayon_core/hosts/fusion/plugins/load/actions.py b/client/ayon_core/hosts/fusion/plugins/load/actions.py index 9600479680..95400ea41c 100644 --- a/client/ayon_core/hosts/fusion/plugins/load/actions.py +++ b/client/ayon_core/hosts/fusion/plugins/load/actions.py @@ -17,7 +17,7 @@ class FusionSetFrameRangeLoader(load.LoaderPlugin): "pointcache", "render", } - representations = ["*"] + representations = {"*"} extensions = {"*"} label = "Set frame range" @@ -54,7 +54,7 @@ class FusionSetFrameRangeWithHandlesLoader(load.LoaderPlugin): "pointcache", "render", } - representations = ["*"] + representations = {"*"} label = "Set frame range (with handles)" order = 12 diff --git a/client/ayon_core/hosts/fusion/plugins/load/load_alembic.py b/client/ayon_core/hosts/fusion/plugins/load/load_alembic.py index ae2175964d..312362caca 100644 --- a/client/ayon_core/hosts/fusion/plugins/load/load_alembic.py +++ b/client/ayon_core/hosts/fusion/plugins/load/load_alembic.py @@ -13,7 +13,7 @@ class FusionLoadAlembicMesh(load.LoaderPlugin): """Load Alembic mesh into Fusion""" product_types = {"pointcache", "model"} - representations = ["*"] + representations = {"*"} extensions = {"abc"} label = "Load alembic mesh" diff --git a/client/ayon_core/hosts/fusion/plugins/load/load_fbx.py b/client/ayon_core/hosts/fusion/plugins/load/load_fbx.py index 68b7cdacd1..a84e7e0914 100644 --- a/client/ayon_core/hosts/fusion/plugins/load/load_fbx.py +++ b/client/ayon_core/hosts/fusion/plugins/load/load_fbx.py @@ -13,7 +13,7 @@ class FusionLoadFBXMesh(load.LoaderPlugin): """Load FBX mesh into Fusion""" product_types = {"*"} - representations = ["*"] + representations = {"*"} extensions = { "3ds", "amc", diff --git a/client/ayon_core/hosts/fusion/plugins/load/load_sequence.py b/client/ayon_core/hosts/fusion/plugins/load/load_sequence.py index f0a8233377..7c70b54e48 100644 --- a/client/ayon_core/hosts/fusion/plugins/load/load_sequence.py +++ b/client/ayon_core/hosts/fusion/plugins/load/load_sequence.py @@ -137,7 +137,7 @@ class FusionLoadSequence(load.LoaderPlugin): "image", "online", } - representations = ["*"] + representations = {"*"} extensions = set( ext.lstrip(".") for ext in IMAGE_EXTENSIONS.union(VIDEO_EXTENSIONS) ) diff --git a/client/ayon_core/hosts/fusion/plugins/load/load_usd.py b/client/ayon_core/hosts/fusion/plugins/load/load_usd.py index 2f8eeb4c66..309b0c094c 100644 --- a/client/ayon_core/hosts/fusion/plugins/load/load_usd.py +++ b/client/ayon_core/hosts/fusion/plugins/load/load_usd.py @@ -17,7 +17,7 @@ class FusionLoadUSD(load.LoaderPlugin): """ product_types = {"*"} - representations = ["*"] + representations = {"*"} extensions = {"usd", "usda", "usdz"} label = "Load USD" diff --git a/client/ayon_core/hosts/fusion/plugins/load/load_workfile.py b/client/ayon_core/hosts/fusion/plugins/load/load_workfile.py index fd2fa7c08b..818fbcb187 100644 --- a/client/ayon_core/hosts/fusion/plugins/load/load_workfile.py +++ b/client/ayon_core/hosts/fusion/plugins/load/load_workfile.py @@ -15,7 +15,7 @@ class FusionLoadWorkfile(load.LoaderPlugin): """Load the content of a workfile into Fusion""" product_types = {"workfile"} - representations = ["*"] + representations = {"*"} extensions = {"comp"} label = "Load Workfile" diff --git a/client/ayon_core/hosts/harmony/api/README.md b/client/ayon_core/hosts/harmony/api/README.md index 7ac185638a..b8d1dbc100 100644 --- a/client/ayon_core/hosts/harmony/api/README.md +++ b/client/ayon_core/hosts/harmony/api/README.md @@ -590,7 +590,7 @@ class ImageSequenceLoader(load.LoaderPlugin): "reference", "review", } - representations = ["*"] + representations = {"*"} extensions = {"jpeg", "png", "jpg"} def load(self, context, name=None, namespace=None, data=None): diff --git a/client/ayon_core/hosts/harmony/plugins/load/load_audio.py b/client/ayon_core/hosts/harmony/plugins/load/load_audio.py index 00f3ac77ec..d23f3ed034 100644 --- a/client/ayon_core/hosts/harmony/plugins/load/load_audio.py +++ b/client/ayon_core/hosts/harmony/plugins/load/load_audio.py @@ -36,7 +36,7 @@ class ImportAudioLoader(load.LoaderPlugin): """Import audio.""" product_types = {"shot", "audio"} - representations = ["wav"] + representations = {"wav"} label = "Import Audio" def load(self, context, name=None, namespace=None, data=None): diff --git a/client/ayon_core/hosts/harmony/plugins/load/load_background.py b/client/ayon_core/hosts/harmony/plugins/load/load_background.py index 74bc5a4fd8..dad6ac2f22 100644 --- a/client/ayon_core/hosts/harmony/plugins/load/load_background.py +++ b/client/ayon_core/hosts/harmony/plugins/load/load_background.py @@ -234,7 +234,7 @@ class BackgroundLoader(load.LoaderPlugin): Stores the imported asset in a container named after the asset. """ product_types = {"background"} - representations = ["json"] + representations = {"json"} def load(self, context, name=None, namespace=None, data=None): diff --git a/client/ayon_core/hosts/harmony/plugins/load/load_imagesequence.py b/client/ayon_core/hosts/harmony/plugins/load/load_imagesequence.py index bf4b87a03e..f81ebca9af 100644 --- a/client/ayon_core/hosts/harmony/plugins/load/load_imagesequence.py +++ b/client/ayon_core/hosts/harmony/plugins/load/load_imagesequence.py @@ -28,7 +28,7 @@ class ImageSequenceLoader(load.LoaderPlugin): "reference", "review", } - representations = ["*"] + representations = {"*"} extensions = {"jpeg", "png", "jpg"} def load(self, context, name=None, namespace=None, data=None): diff --git a/client/ayon_core/hosts/harmony/plugins/load/load_palette.py b/client/ayon_core/hosts/harmony/plugins/load/load_palette.py index d5fbeb323b..24f4b4e8d4 100644 --- a/client/ayon_core/hosts/harmony/plugins/load/load_palette.py +++ b/client/ayon_core/hosts/harmony/plugins/load/load_palette.py @@ -12,7 +12,7 @@ class ImportPaletteLoader(load.LoaderPlugin): """Import palettes.""" product_types = {"palette", "harmony.palette"} - representations = ["plt"] + representations = {"plt"} label = "Import Palette" def load(self, context, name=None, namespace=None, data=None): diff --git a/client/ayon_core/hosts/harmony/plugins/load/load_template.py b/client/ayon_core/hosts/harmony/plugins/load/load_template.py index 48064f2b75..96dadb0375 100644 --- a/client/ayon_core/hosts/harmony/plugins/load/load_template.py +++ b/client/ayon_core/hosts/harmony/plugins/load/load_template.py @@ -24,7 +24,7 @@ class TemplateLoader(load.LoaderPlugin): """ product_types = {"template", "workfile"} - representations = ["*"] + representations = {"*"} label = "Load Template" icon = "gift" diff --git a/client/ayon_core/hosts/harmony/plugins/load/load_template_workfile.py b/client/ayon_core/hosts/harmony/plugins/load/load_template_workfile.py index c7132ce373..fa5ffe5105 100644 --- a/client/ayon_core/hosts/harmony/plugins/load/load_template_workfile.py +++ b/client/ayon_core/hosts/harmony/plugins/load/load_template_workfile.py @@ -14,7 +14,7 @@ class ImportTemplateLoader(load.LoaderPlugin): """Import templates.""" product_types = {"harmony.template", "workfile"} - representations = ["*"] + representations = {"*"} label = "Import Template" def load(self, context, name=None, namespace=None, data=None): @@ -61,5 +61,5 @@ class ImportWorkfileLoader(ImportTemplateLoader): """Import workfiles.""" product_types = {"workfile"} - representations = ["zip"] + representations = {"zip"} label = "Import Workfile" diff --git a/client/ayon_core/hosts/hiero/plugins/load/load_clip.py b/client/ayon_core/hosts/hiero/plugins/load/load_clip.py index 72d7e03a9a..715e8c508e 100644 --- a/client/ayon_core/hosts/hiero/plugins/load/load_clip.py +++ b/client/ayon_core/hosts/hiero/plugins/load/load_clip.py @@ -16,7 +16,7 @@ class LoadClip(phiero.SequenceLoader): """ product_types = {"render2d", "source", "plate", "render", "review"} - representations = ["*"] + representations = {"*"} extensions = set( ext.lstrip(".") for ext in IMAGE_EXTENSIONS.union(VIDEO_EXTENSIONS) ) diff --git a/client/ayon_core/hosts/hiero/plugins/load/load_effects.py b/client/ayon_core/hosts/hiero/plugins/load/load_effects.py index fd6b8ed694..92aa2de325 100644 --- a/client/ayon_core/hosts/hiero/plugins/load/load_effects.py +++ b/client/ayon_core/hosts/hiero/plugins/load/load_effects.py @@ -15,7 +15,7 @@ class LoadEffects(load.LoaderPlugin): """Loading colorspace soft effect exported from nukestudio""" product_types = {"effect"} - representations = ["*"] + representations = {"*"} extension = {"json"} label = "Load Effects" diff --git a/client/ayon_core/hosts/houdini/plugins/load/actions.py b/client/ayon_core/hosts/houdini/plugins/load/actions.py index fbd89ab9c2..3e9cc35504 100644 --- a/client/ayon_core/hosts/houdini/plugins/load/actions.py +++ b/client/ayon_core/hosts/houdini/plugins/load/actions.py @@ -15,7 +15,7 @@ class SetFrameRangeLoader(load.LoaderPlugin): "vdbcache", "usd", } - representations = ["abc", "vdb", "usd"] + representations = {"abc", "vdb", "usd"} label = "Set frame range" order = 11 @@ -52,7 +52,7 @@ class SetFrameRangeWithHandlesLoader(load.LoaderPlugin): "vdbcache", "usd", } - representations = ["abc", "vdb", "usd"] + representations = {"abc", "vdb", "usd"} label = "Set frame range (with handles)" order = 12 diff --git a/client/ayon_core/hosts/houdini/plugins/load/load_alembic.py b/client/ayon_core/hosts/houdini/plugins/load/load_alembic.py index 37657cbdff..1bb9043cd0 100644 --- a/client/ayon_core/hosts/houdini/plugins/load/load_alembic.py +++ b/client/ayon_core/hosts/houdini/plugins/load/load_alembic.py @@ -11,7 +11,7 @@ class AbcLoader(load.LoaderPlugin): product_types = {"model", "animation", "pointcache", "gpuCache"} label = "Load Alembic" - representations = ["*"] + representations = {"*"} extensions = {"abc"} order = -10 icon = "code-fork" diff --git a/client/ayon_core/hosts/houdini/plugins/load/load_alembic_archive.py b/client/ayon_core/hosts/houdini/plugins/load/load_alembic_archive.py index 39928fd952..a231bd9993 100644 --- a/client/ayon_core/hosts/houdini/plugins/load/load_alembic_archive.py +++ b/client/ayon_core/hosts/houdini/plugins/load/load_alembic_archive.py @@ -11,7 +11,7 @@ class AbcArchiveLoader(load.LoaderPlugin): product_types = {"model", "animation", "pointcache", "gpuCache"} label = "Load Alembic as Archive" - representations = ["*"] + representations = {"*"} extensions = {"abc"} order = -5 icon = "code-fork" diff --git a/client/ayon_core/hosts/houdini/plugins/load/load_ass.py b/client/ayon_core/hosts/houdini/plugins/load/load_ass.py index fd0e8f4604..6e0922e305 100644 --- a/client/ayon_core/hosts/houdini/plugins/load/load_ass.py +++ b/client/ayon_core/hosts/houdini/plugins/load/load_ass.py @@ -13,7 +13,7 @@ class AssLoader(load.LoaderPlugin): product_types = {"ass"} label = "Load Arnold Procedural" - representations = ["ass"] + representations = {"ass"} order = -10 icon = "code-fork" color = "orange" diff --git a/client/ayon_core/hosts/houdini/plugins/load/load_bgeo.py b/client/ayon_core/hosts/houdini/plugins/load/load_bgeo.py index fd8071c0de..a318b71963 100644 --- a/client/ayon_core/hosts/houdini/plugins/load/load_bgeo.py +++ b/client/ayon_core/hosts/houdini/plugins/load/load_bgeo.py @@ -14,9 +14,9 @@ class BgeoLoader(load.LoaderPlugin): label = "Load bgeo" product_types = {"model", "pointcache", "bgeo"} - representations = [ + representations = { "bgeo", "bgeosc", "bgeogz", - "bgeo.sc", "bgeo.gz", "bgeo.lzma", "bgeo.bz2"] + "bgeo.sc", "bgeo.gz", "bgeo.lzma", "bgeo.bz2"} order = -10 icon = "code-fork" color = "orange" diff --git a/client/ayon_core/hosts/houdini/plugins/load/load_camera.py b/client/ayon_core/hosts/houdini/plugins/load/load_camera.py index 7cb4542d0c..b7912f88f1 100644 --- a/client/ayon_core/hosts/houdini/plugins/load/load_camera.py +++ b/client/ayon_core/hosts/houdini/plugins/load/load_camera.py @@ -89,7 +89,7 @@ class CameraLoader(load.LoaderPlugin): product_types = {"camera"} label = "Load Camera (abc)" - representations = ["abc"] + representations = {"abc"} order = -10 icon = "code-fork" diff --git a/client/ayon_core/hosts/houdini/plugins/load/load_fbx.py b/client/ayon_core/hosts/houdini/plugins/load/load_fbx.py index a0c5e0c934..398019a3bd 100644 --- a/client/ayon_core/hosts/houdini/plugins/load/load_fbx.py +++ b/client/ayon_core/hosts/houdini/plugins/load/load_fbx.py @@ -17,7 +17,7 @@ class FbxLoader(load.LoaderPlugin): order = -10 product_types = {"*"} - representations = ["*"] + representations = {"*"} extensions = {"fbx"} def load(self, context, name=None, namespace=None, data=None): diff --git a/client/ayon_core/hosts/houdini/plugins/load/load_filepath.py b/client/ayon_core/hosts/houdini/plugins/load/load_filepath.py index f107190f96..d189a027fd 100644 --- a/client/ayon_core/hosts/houdini/plugins/load/load_filepath.py +++ b/client/ayon_core/hosts/houdini/plugins/load/load_filepath.py @@ -22,7 +22,7 @@ class FilePathLoader(load.LoaderPlugin): icon = "link" color = "white" product_types = {"*"} - representations = ["*"] + representations = {"*"} def load(self, context, name=None, namespace=None, data=None): diff --git a/client/ayon_core/hosts/houdini/plugins/load/load_hda.py b/client/ayon_core/hosts/houdini/plugins/load/load_hda.py index df77783a34..10fc03be03 100644 --- a/client/ayon_core/hosts/houdini/plugins/load/load_hda.py +++ b/client/ayon_core/hosts/houdini/plugins/load/load_hda.py @@ -12,7 +12,7 @@ class HdaLoader(load.LoaderPlugin): product_types = {"hda"} label = "Load Hda" - representations = ["hda"] + representations = {"hda"} order = -10 icon = "code-fork" color = "orange" diff --git a/client/ayon_core/hosts/houdini/plugins/load/load_image.py b/client/ayon_core/hosts/houdini/plugins/load/load_image.py index 0429b1c3fe..dfbd3c11eb 100644 --- a/client/ayon_core/hosts/houdini/plugins/load/load_image.py +++ b/client/ayon_core/hosts/houdini/plugins/load/load_image.py @@ -54,7 +54,7 @@ class ImageLoader(load.LoaderPlugin): "online", } label = "Load Image (COP2)" - representations = ["*"] + representations = {"*"} order = -10 icon = "code-fork" diff --git a/client/ayon_core/hosts/houdini/plugins/load/load_redshift_proxy.py b/client/ayon_core/hosts/houdini/plugins/load/load_redshift_proxy.py index a6556619fc..f09856a970 100644 --- a/client/ayon_core/hosts/houdini/plugins/load/load_redshift_proxy.py +++ b/client/ayon_core/hosts/houdini/plugins/load/load_redshift_proxy.py @@ -15,7 +15,7 @@ class RedshiftProxyLoader(load.LoaderPlugin): product_types = {"redshiftproxy"} label = "Load Redshift Proxy" - representations = ["rs"] + representations = {"rs"} order = -10 icon = "code-fork" color = "orange" diff --git a/client/ayon_core/hosts/houdini/plugins/load/load_usd_layer.py b/client/ayon_core/hosts/houdini/plugins/load/load_usd_layer.py index 19950e2c98..4e6954c531 100644 --- a/client/ayon_core/hosts/houdini/plugins/load/load_usd_layer.py +++ b/client/ayon_core/hosts/houdini/plugins/load/load_usd_layer.py @@ -14,7 +14,7 @@ class USDSublayerLoader(load.LoaderPlugin): "usdCamera", } label = "Sublayer USD" - representations = ["usd", "usda", "usdlc", "usdnc", "abc"] + representations = {"usd", "usda", "usdlc", "usdnc", "abc"} order = 1 icon = "code-fork" diff --git a/client/ayon_core/hosts/houdini/plugins/load/load_usd_reference.py b/client/ayon_core/hosts/houdini/plugins/load/load_usd_reference.py index 25f98c7c7c..7e82a6abd0 100644 --- a/client/ayon_core/hosts/houdini/plugins/load/load_usd_reference.py +++ b/client/ayon_core/hosts/houdini/plugins/load/load_usd_reference.py @@ -14,7 +14,7 @@ class USDReferenceLoader(load.LoaderPlugin): "usdCamera", } label = "Reference USD" - representations = ["usd", "usda", "usdlc", "usdnc", "abc"] + representations = {"usd", "usda", "usdlc", "usdnc", "abc"} order = -8 icon = "code-fork" diff --git a/client/ayon_core/hosts/houdini/plugins/load/load_usd_sop.py b/client/ayon_core/hosts/houdini/plugins/load/load_usd_sop.py index 5b7e022e73..506f6140bf 100644 --- a/client/ayon_core/hosts/houdini/plugins/load/load_usd_sop.py +++ b/client/ayon_core/hosts/houdini/plugins/load/load_usd_sop.py @@ -9,7 +9,7 @@ class SopUsdImportLoader(load.LoaderPlugin): label = "Load USD to SOPs" product_types = {"*"} - representations = ["usd"] + representations = {"usd"} order = -6 icon = "code-fork" color = "orange" diff --git a/client/ayon_core/hosts/houdini/plugins/load/load_vdb.py b/client/ayon_core/hosts/houdini/plugins/load/load_vdb.py index d9808020d7..0008f0d5f8 100644 --- a/client/ayon_core/hosts/houdini/plugins/load/load_vdb.py +++ b/client/ayon_core/hosts/houdini/plugins/load/load_vdb.py @@ -13,7 +13,7 @@ class VdbLoader(load.LoaderPlugin): product_types = {"vdbcache"} label = "Load VDB" - representations = ["vdb"] + representations = {"vdb"} order = -10 icon = "code-fork" color = "orange" diff --git a/client/ayon_core/hosts/houdini/plugins/load/show_usdview.py b/client/ayon_core/hosts/houdini/plugins/load/show_usdview.py index 9506d9dd0c..0158a6b963 100644 --- a/client/ayon_core/hosts/houdini/plugins/load/show_usdview.py +++ b/client/ayon_core/hosts/houdini/plugins/load/show_usdview.py @@ -10,7 +10,7 @@ class ShowInUsdview(load.LoaderPlugin): """Open USD file in usdview""" label = "Show in usdview" - representations = ["*"] + representations = {"*"} product_types = {"*"} extensions = {"usd", "usda", "usdlc", "usdnc", "abc"} order = 15 diff --git a/client/ayon_core/hosts/max/plugins/load/load_camera_fbx.py b/client/ayon_core/hosts/max/plugins/load/load_camera_fbx.py index e1de6b98f9..6f1e9988c5 100644 --- a/client/ayon_core/hosts/max/plugins/load/load_camera_fbx.py +++ b/client/ayon_core/hosts/max/plugins/load/load_camera_fbx.py @@ -19,7 +19,7 @@ class FbxLoader(load.LoaderPlugin): """Fbx Loader.""" product_types = {"camera"} - representations = ["fbx"] + representations = {"fbx"} order = -9 icon = "code-fork" color = "white" diff --git a/client/ayon_core/hosts/max/plugins/load/load_max_scene.py b/client/ayon_core/hosts/max/plugins/load/load_max_scene.py index 1c2c5317cc..4f982dd5ba 100644 --- a/client/ayon_core/hosts/max/plugins/load/load_max_scene.py +++ b/client/ayon_core/hosts/max/plugins/load/load_max_scene.py @@ -78,7 +78,7 @@ class MaxSceneLoader(load.LoaderPlugin): "model", } - representations = ["max"] + representations = {"max"} order = -8 icon = "code-fork" color = "green" diff --git a/client/ayon_core/hosts/max/plugins/load/load_model.py b/client/ayon_core/hosts/max/plugins/load/load_model.py index 00e675d69c..1070fce2bd 100644 --- a/client/ayon_core/hosts/max/plugins/load/load_model.py +++ b/client/ayon_core/hosts/max/plugins/load/load_model.py @@ -16,7 +16,7 @@ class ModelAbcLoader(load.LoaderPlugin): product_types = {"model"} label = "Load Model with Alembic" - representations = ["abc"] + representations = {"abc"} order = -10 icon = "code-fork" color = "orange" diff --git a/client/ayon_core/hosts/max/plugins/load/load_model_fbx.py b/client/ayon_core/hosts/max/plugins/load/load_model_fbx.py index 4b87c60de0..82cad71c3e 100644 --- a/client/ayon_core/hosts/max/plugins/load/load_model_fbx.py +++ b/client/ayon_core/hosts/max/plugins/load/load_model_fbx.py @@ -18,7 +18,7 @@ class FbxModelLoader(load.LoaderPlugin): """Fbx Model Loader.""" product_types = {"model"} - representations = ["fbx"] + representations = {"fbx"} order = -9 icon = "code-fork" color = "white" diff --git a/client/ayon_core/hosts/max/plugins/load/load_model_obj.py b/client/ayon_core/hosts/max/plugins/load/load_model_obj.py index 2330dbfc24..38f2cdf43c 100644 --- a/client/ayon_core/hosts/max/plugins/load/load_model_obj.py +++ b/client/ayon_core/hosts/max/plugins/load/load_model_obj.py @@ -20,7 +20,7 @@ class ObjLoader(load.LoaderPlugin): """Obj Loader.""" product_types = {"model"} - representations = ["obj"] + representations = {"obj"} order = -9 icon = "code-fork" color = "white" diff --git a/client/ayon_core/hosts/max/plugins/load/load_model_usd.py b/client/ayon_core/hosts/max/plugins/load/load_model_usd.py index bde23e119e..2b946eb2aa 100644 --- a/client/ayon_core/hosts/max/plugins/load/load_model_usd.py +++ b/client/ayon_core/hosts/max/plugins/load/load_model_usd.py @@ -24,7 +24,7 @@ class ModelUSDLoader(load.LoaderPlugin): product_types = {"model"} label = "Load Model(USD)" - representations = ["usda"] + representations = {"usda"} order = -10 icon = "code-fork" color = "orange" diff --git a/client/ayon_core/hosts/max/plugins/load/load_pointcache.py b/client/ayon_core/hosts/max/plugins/load/load_pointcache.py index 7f515ac6a5..0743b3bb34 100644 --- a/client/ayon_core/hosts/max/plugins/load/load_pointcache.py +++ b/client/ayon_core/hosts/max/plugins/load/load_pointcache.py @@ -20,7 +20,7 @@ class AbcLoader(load.LoaderPlugin): product_types = {"camera", "animation", "pointcache"} label = "Load Alembic" - representations = ["abc"] + representations = {"abc"} order = -10 icon = "code-fork" color = "orange" diff --git a/client/ayon_core/hosts/max/plugins/load/load_pointcache_ornatrix.py b/client/ayon_core/hosts/max/plugins/load/load_pointcache_ornatrix.py index 31d3f02ec0..2efb7c7f62 100644 --- a/client/ayon_core/hosts/max/plugins/load/load_pointcache_ornatrix.py +++ b/client/ayon_core/hosts/max/plugins/load/load_pointcache_ornatrix.py @@ -23,7 +23,7 @@ class OxAbcLoader(load.LoaderPlugin): product_types = {"camera", "animation", "pointcache"} label = "Load Alembic with Ornatrix" - representations = ["abc"] + representations = {"abc"} order = -10 icon = "code-fork" color = "orange" diff --git a/client/ayon_core/hosts/max/plugins/load/load_pointcloud.py b/client/ayon_core/hosts/max/plugins/load/load_pointcloud.py index c0000c7a79..0e79882fc5 100644 --- a/client/ayon_core/hosts/max/plugins/load/load_pointcloud.py +++ b/client/ayon_core/hosts/max/plugins/load/load_pointcloud.py @@ -18,7 +18,7 @@ class PointCloudLoader(load.LoaderPlugin): """Point Cloud Loader.""" product_types = {"pointcloud"} - representations = ["prt"] + representations = {"prt"} order = -8 icon = "code-fork" color = "green" diff --git a/client/ayon_core/hosts/max/plugins/load/load_redshift_proxy.py b/client/ayon_core/hosts/max/plugins/load/load_redshift_proxy.py index ff6811bd1b..22d42390d9 100644 --- a/client/ayon_core/hosts/max/plugins/load/load_redshift_proxy.py +++ b/client/ayon_core/hosts/max/plugins/load/load_redshift_proxy.py @@ -24,7 +24,7 @@ class RedshiftProxyLoader(load.LoaderPlugin): label = "Load Redshift Proxy" product_types = {"redshiftproxy"} - representations = ["rs"] + representations = {"rs"} order = -9 icon = "code-fork" color = "white" diff --git a/client/ayon_core/hosts/max/plugins/load/load_tycache.py b/client/ayon_core/hosts/max/plugins/load/load_tycache.py index 0244e4e6fc..7a5296d933 100644 --- a/client/ayon_core/hosts/max/plugins/load/load_tycache.py +++ b/client/ayon_core/hosts/max/plugins/load/load_tycache.py @@ -17,7 +17,7 @@ class TyCacheLoader(load.LoaderPlugin): """TyCache Loader.""" product_types = {"tycache"} - representations = ["tyc"] + representations = {"tyc"} order = -8 icon = "code-fork" color = "green" diff --git a/client/ayon_core/hosts/maya/plugins/load/_load_animation.py b/client/ayon_core/hosts/maya/plugins/load/_load_animation.py index 884bdd7538..393f6b0115 100644 --- a/client/ayon_core/hosts/maya/plugins/load/_load_animation.py +++ b/client/ayon_core/hosts/maya/plugins/load/_load_animation.py @@ -51,7 +51,7 @@ class AbcLoader(ayon_core.hosts.maya.api.plugin.ReferenceLoader): "camera", "pointcache", } - representations = ["abc"] + representations = {"abc"} label = "Reference animation" order = -10 @@ -81,7 +81,7 @@ class FbxLoader(ayon_core.hosts.maya.api.plugin.ReferenceLoader): "animation", "camera", } - representations = ["fbx"] + representations = {"fbx"} label = "Reference animation" order = -10 diff --git a/client/ayon_core/hosts/maya/plugins/load/actions.py b/client/ayon_core/hosts/maya/plugins/load/actions.py index a98fe97692..3e21d600ac 100644 --- a/client/ayon_core/hosts/maya/plugins/load/actions.py +++ b/client/ayon_core/hosts/maya/plugins/load/actions.py @@ -19,7 +19,7 @@ class SetFrameRangeLoader(load.LoaderPlugin): "proxyAbc", "pointcache", } - representations = ["abc"] + representations = {"abc"} label = "Set frame range" order = 11 @@ -54,7 +54,7 @@ class SetFrameRangeWithHandlesLoader(load.LoaderPlugin): "proxyAbc", "pointcache", } - representations = ["abc"] + representations = {"abc"} label = "Set frame range (with handles)" order = 12 @@ -94,7 +94,7 @@ class ImportMayaLoader(ayon_core.hosts.maya.api.plugin.Loader): so you could also use it as a new base. """ - representations = ["ma", "mb", "obj"] + representations = {"ma", "mb", "obj"} product_types = { "model", "pointcache", diff --git a/client/ayon_core/hosts/maya/plugins/load/load_arnold_standin.py b/client/ayon_core/hosts/maya/plugins/load/load_arnold_standin.py index 7170c30422..4b7d2f42ab 100644 --- a/client/ayon_core/hosts/maya/plugins/load/load_arnold_standin.py +++ b/client/ayon_core/hosts/maya/plugins/load/load_arnold_standin.py @@ -31,7 +31,7 @@ class ArnoldStandinLoader(load.LoaderPlugin): product_types = { "ass", "animation", "model", "proxyAbc", "pointcache", "usd" } - representations = ["ass", "abc", "usda", "usdc", "usd"] + representations = {"ass", "abc", "usda", "usdc", "usd"} label = "Load as Arnold standin" order = -5 diff --git a/client/ayon_core/hosts/maya/plugins/load/load_assembly.py b/client/ayon_core/hosts/maya/plugins/load/load_assembly.py index a0cbf91905..0fcbc6bd07 100644 --- a/client/ayon_core/hosts/maya/plugins/load/load_assembly.py +++ b/client/ayon_core/hosts/maya/plugins/load/load_assembly.py @@ -13,7 +13,7 @@ from ayon_core.hosts.maya.api import setdress class AssemblyLoader(load.LoaderPlugin): product_types = {"assembly"} - representations = ["json"] + representations = {"json"} label = "Load Set Dress" order = -9 diff --git a/client/ayon_core/hosts/maya/plugins/load/load_audio.py b/client/ayon_core/hosts/maya/plugins/load/load_audio.py index 0a40993fcd..228189f1a1 100644 --- a/client/ayon_core/hosts/maya/plugins/load/load_audio.py +++ b/client/ayon_core/hosts/maya/plugins/load/load_audio.py @@ -13,7 +13,7 @@ class AudioLoader(load.LoaderPlugin): product_types = {"audio"} label = "Load audio" - representations = ["wav"] + representations = {"wav"} icon = "volume-up" color = "orange" diff --git a/client/ayon_core/hosts/maya/plugins/load/load_gpucache.py b/client/ayon_core/hosts/maya/plugins/load/load_gpucache.py index 9689282ae9..9832d2d657 100644 --- a/client/ayon_core/hosts/maya/plugins/load/load_gpucache.py +++ b/client/ayon_core/hosts/maya/plugins/load/load_gpucache.py @@ -14,7 +14,7 @@ class GpuCacheLoader(load.LoaderPlugin): """Load Alembic as gpuCache""" product_types = {"model", "animation", "proxyAbc", "pointcache"} - representations = ["abc", "gpu_cache"] + representations = {"abc", "gpu_cache"} label = "Load Gpu Cache" order = -5 diff --git a/client/ayon_core/hosts/maya/plugins/load/load_image.py b/client/ayon_core/hosts/maya/plugins/load/load_image.py index 3641655d49..5b0858ce70 100644 --- a/client/ayon_core/hosts/maya/plugins/load/load_image.py +++ b/client/ayon_core/hosts/maya/plugins/load/load_image.py @@ -93,7 +93,7 @@ class FileNodeLoader(load.LoaderPlugin): product_types = {"image", "plate", "render"} label = "Load file node" - representations = ["exr", "tif", "png", "jpg"] + representations = {"exr", "tif", "png", "jpg"} icon = "image" color = "orange" order = 2 diff --git a/client/ayon_core/hosts/maya/plugins/load/load_image_plane.py b/client/ayon_core/hosts/maya/plugins/load/load_image_plane.py index b298d5b892..15c7654c52 100644 --- a/client/ayon_core/hosts/maya/plugins/load/load_image_plane.py +++ b/client/ayon_core/hosts/maya/plugins/load/load_image_plane.py @@ -89,7 +89,7 @@ class ImagePlaneLoader(load.LoaderPlugin): product_types = {"image", "plate", "render"} label = "Load imagePlane" - representations = ["mov", "exr", "preview", "png", "jpg"] + representations = {"mov", "exr", "preview", "png", "jpg"} icon = "image" color = "orange" @@ -171,7 +171,7 @@ class ImagePlaneLoader(load.LoaderPlugin): plug = "{}.{}".format(image_plane_shape, attr) cmds.setAttr(plug, value) - movie_representations = ["mov", "preview"] + movie_representations = {"mov", "preview"} if context["representation"]["name"] in movie_representations: cmds.setAttr(image_plane_shape + ".type", 2) diff --git a/client/ayon_core/hosts/maya/plugins/load/load_look.py b/client/ayon_core/hosts/maya/plugins/load/load_look.py index f126a1df26..af0e000dd2 100644 --- a/client/ayon_core/hosts/maya/plugins/load/load_look.py +++ b/client/ayon_core/hosts/maya/plugins/load/load_look.py @@ -18,7 +18,7 @@ class LookLoader(ayon_core.hosts.maya.api.plugin.ReferenceLoader): """Specific loader for lookdev""" product_types = {"look"} - representations = ["ma"] + representations = {"ma"} label = "Reference look" order = -10 diff --git a/client/ayon_core/hosts/maya/plugins/load/load_matchmove.py b/client/ayon_core/hosts/maya/plugins/load/load_matchmove.py index 05da173bb7..b19b14b1aa 100644 --- a/client/ayon_core/hosts/maya/plugins/load/load_matchmove.py +++ b/client/ayon_core/hosts/maya/plugins/load/load_matchmove.py @@ -9,7 +9,7 @@ class MatchmoveLoader(load.LoaderPlugin): """ product_types = {"matchmove"} - representations = ["py", "mel"] + representations = {"py", "mel"} defaults = ["Camera", "Object", "Mocap"] label = "Run matchmove script" diff --git a/client/ayon_core/hosts/maya/plugins/load/load_maya_usd.py b/client/ayon_core/hosts/maya/plugins/load/load_maya_usd.py index cd73c26de1..628a25e574 100644 --- a/client/ayon_core/hosts/maya/plugins/load/load_maya_usd.py +++ b/client/ayon_core/hosts/maya/plugins/load/load_maya_usd.py @@ -17,7 +17,7 @@ class MayaUsdLoader(load.LoaderPlugin): """Read USD data in a Maya USD Proxy""" product_types = {"model", "usd", "pointcache", "animation"} - representations = ["usd", "usda", "usdc", "usdz", "abc"] + representations = {"usd", "usda", "usdc", "usdz", "abc"} label = "Load USD to Maya Proxy" order = -1 diff --git a/client/ayon_core/hosts/maya/plugins/load/load_multiverse_usd.py b/client/ayon_core/hosts/maya/plugins/load/load_multiverse_usd.py index 984d14dff3..f32c76481d 100644 --- a/client/ayon_core/hosts/maya/plugins/load/load_multiverse_usd.py +++ b/client/ayon_core/hosts/maya/plugins/load/load_multiverse_usd.py @@ -28,7 +28,7 @@ class MultiverseUsdLoader(load.LoaderPlugin): "pointcache", "animation", } - representations = ["usd", "usda", "usdc", "usdz", "abc"] + representations = {"usd", "usda", "usdc", "usdz", "abc"} label = "Load USD to Multiverse" order = -10 diff --git a/client/ayon_core/hosts/maya/plugins/load/load_multiverse_usd_over.py b/client/ayon_core/hosts/maya/plugins/load/load_multiverse_usd_over.py index dc5bc6ec1c..b23fa48f07 100644 --- a/client/ayon_core/hosts/maya/plugins/load/load_multiverse_usd_over.py +++ b/client/ayon_core/hosts/maya/plugins/load/load_multiverse_usd_over.py @@ -20,7 +20,7 @@ class MultiverseUsdOverLoader(load.LoaderPlugin): """Reference file""" product_types = {"mvUsdOverride"} - representations = ["usda", "usd", "udsz"] + representations = {"usda", "usd", "udsz"} label = "Load Usd Override into Compound" order = -10 diff --git a/client/ayon_core/hosts/maya/plugins/load/load_redshift_proxy.py b/client/ayon_core/hosts/maya/plugins/load/load_redshift_proxy.py index 0f91d9048a..7760d4081c 100644 --- a/client/ayon_core/hosts/maya/plugins/load/load_redshift_proxy.py +++ b/client/ayon_core/hosts/maya/plugins/load/load_redshift_proxy.py @@ -23,7 +23,7 @@ class RedshiftProxyLoader(load.LoaderPlugin): """Load Redshift proxy""" product_types = {"redshiftproxy"} - representations = ["rs"] + representations = {"rs"} label = "Import Redshift Proxy" order = -10 diff --git a/client/ayon_core/hosts/maya/plugins/load/load_reference.py b/client/ayon_core/hosts/maya/plugins/load/load_reference.py index de18b2b0ec..847591bd11 100644 --- a/client/ayon_core/hosts/maya/plugins/load/load_reference.py +++ b/client/ayon_core/hosts/maya/plugins/load/load_reference.py @@ -107,7 +107,7 @@ class ReferenceLoader(plugin.ReferenceLoader): "matchmove", } - representations = ["ma", "abc", "fbx", "mb"] + representations = {"ma", "abc", "fbx", "mb"} label = "Reference" order = -10 @@ -269,7 +269,7 @@ class MayaUSDReferenceLoader(ReferenceLoader): label = "Reference Maya USD" product_types = {"usd"} - representations = ["usd"] + representations = {"usd"} extensions = {"usd", "usda", "usdc"} options = ReferenceLoader.options + [ diff --git a/client/ayon_core/hosts/maya/plugins/load/load_rendersetup.py b/client/ayon_core/hosts/maya/plugins/load/load_rendersetup.py index 7096f86e35..d5685b2c4c 100644 --- a/client/ayon_core/hosts/maya/plugins/load/load_rendersetup.py +++ b/client/ayon_core/hosts/maya/plugins/load/load_rendersetup.py @@ -52,7 +52,7 @@ class RenderSetupLoader(load.LoaderPlugin): """Load json preset for RenderSetup overwriting current one.""" product_types = {"rendersetup"} - representations = ["json"] + representations = {"json"} defaults = ['Main'] label = "Load RenderSetup template" diff --git a/client/ayon_core/hosts/maya/plugins/load/load_vdb_to_arnold.py b/client/ayon_core/hosts/maya/plugins/load/load_vdb_to_arnold.py index 0780a7b3e7..5b0c78fd6f 100644 --- a/client/ayon_core/hosts/maya/plugins/load/load_vdb_to_arnold.py +++ b/client/ayon_core/hosts/maya/plugins/load/load_vdb_to_arnold.py @@ -13,7 +13,7 @@ class LoadVDBtoArnold(load.LoaderPlugin): """Load OpenVDB for Arnold in aiVolume""" product_types = {"vdbcache"} - representations = ["vdb"] + representations = {"vdb"} label = "Load VDB to Arnold" icon = "cloud" diff --git a/client/ayon_core/hosts/maya/plugins/load/load_vdb_to_redshift.py b/client/ayon_core/hosts/maya/plugins/load/load_vdb_to_redshift.py index 3fa490f405..e345a7bf6f 100644 --- a/client/ayon_core/hosts/maya/plugins/load/load_vdb_to_redshift.py +++ b/client/ayon_core/hosts/maya/plugins/load/load_vdb_to_redshift.py @@ -19,7 +19,7 @@ class LoadVDBtoRedShift(load.LoaderPlugin): """ product_types = {"vdbcache"} - representations = ["vdb"] + representations = {"vdb"} label = "Load VDB to RedShift" icon = "cloud" diff --git a/client/ayon_core/hosts/maya/plugins/load/load_vdb_to_vray.py b/client/ayon_core/hosts/maya/plugins/load/load_vdb_to_vray.py index 7b87c21f38..d6d1c948b0 100644 --- a/client/ayon_core/hosts/maya/plugins/load/load_vdb_to_vray.py +++ b/client/ayon_core/hosts/maya/plugins/load/load_vdb_to_vray.py @@ -78,7 +78,7 @@ class LoadVDBtoVRay(load.LoaderPlugin): """Load OpenVDB in a V-Ray Volume Grid""" product_types = {"vdbcache"} - representations = ["vdb"] + representations = {"vdb"} label = "Load VDB to VRay" icon = "cloud" diff --git a/client/ayon_core/hosts/maya/plugins/load/load_vrayproxy.py b/client/ayon_core/hosts/maya/plugins/load/load_vrayproxy.py index 895a4a4127..14d645021c 100644 --- a/client/ayon_core/hosts/maya/plugins/load/load_vrayproxy.py +++ b/client/ayon_core/hosts/maya/plugins/load/load_vrayproxy.py @@ -28,7 +28,7 @@ class VRayProxyLoader(load.LoaderPlugin): """Load VRay Proxy with Alembic or VrayMesh.""" product_types = {"vrayproxy", "model", "pointcache", "animation"} - representations = ["vrmesh", "abc"] + representations = {"vrmesh", "abc"} label = "Import VRay Proxy" order = -10 diff --git a/client/ayon_core/hosts/maya/plugins/load/load_vrayscene.py b/client/ayon_core/hosts/maya/plugins/load/load_vrayscene.py index 36a25e2af1..ea3215da97 100644 --- a/client/ayon_core/hosts/maya/plugins/load/load_vrayscene.py +++ b/client/ayon_core/hosts/maya/plugins/load/load_vrayscene.py @@ -18,7 +18,7 @@ class VRaySceneLoader(load.LoaderPlugin): """Load Vray scene""" product_types = {"vrayscene_layer"} - representations = ["vrscene"] + representations = {"vrscene"} label = "Import VRay Scene" order = -10 diff --git a/client/ayon_core/hosts/maya/plugins/load/load_xgen.py b/client/ayon_core/hosts/maya/plugins/load/load_xgen.py index 880efd82e1..e2664439b0 100644 --- a/client/ayon_core/hosts/maya/plugins/load/load_xgen.py +++ b/client/ayon_core/hosts/maya/plugins/load/load_xgen.py @@ -21,7 +21,7 @@ class XgenLoader(ayon_core.hosts.maya.api.plugin.ReferenceLoader): """Load Xgen as reference""" product_types = {"xgen"} - representations = ["ma", "mb"] + representations = {"ma", "mb"} label = "Reference Xgen" icon = "code-fork" diff --git a/client/ayon_core/hosts/maya/plugins/load/load_yeti_cache.py b/client/ayon_core/hosts/maya/plugins/load/load_yeti_cache.py index a5cd04b0f4..caea6b7a72 100644 --- a/client/ayon_core/hosts/maya/plugins/load/load_yeti_cache.py +++ b/client/ayon_core/hosts/maya/plugins/load/load_yeti_cache.py @@ -37,7 +37,7 @@ class YetiCacheLoader(load.LoaderPlugin): """Load Yeti Cache with one or more Yeti nodes""" product_types = {"yeticache", "yetiRig"} - representations = ["fur"] + representations = {"fur"} label = "Load Yeti Cache" order = -9 diff --git a/client/ayon_core/hosts/maya/plugins/load/load_yeti_rig.py b/client/ayon_core/hosts/maya/plugins/load/load_yeti_rig.py index 74e33c5866..bf9525bae3 100644 --- a/client/ayon_core/hosts/maya/plugins/load/load_yeti_rig.py +++ b/client/ayon_core/hosts/maya/plugins/load/load_yeti_rig.py @@ -8,7 +8,7 @@ class YetiRigLoader(plugin.ReferenceLoader): """This loader will load Yeti rig.""" product_types = {"yetiRig"} - representations = ["ma"] + representations = {"ma"} label = "Load Yeti Rig" order = -9 diff --git a/client/ayon_core/hosts/nuke/plugins/load/actions.py b/client/ayon_core/hosts/nuke/plugins/load/actions.py index a1b3697ef1..53cb03087b 100644 --- a/client/ayon_core/hosts/nuke/plugins/load/actions.py +++ b/client/ayon_core/hosts/nuke/plugins/load/actions.py @@ -19,7 +19,7 @@ class SetFrameRangeLoader(load.LoaderPlugin): "yeticache", "pointcache", } - representations = ["*"] + representations = {"*"} extensions = {"*"} label = "Set frame range" @@ -53,7 +53,7 @@ class SetFrameRangeWithHandlesLoader(load.LoaderPlugin): "yeticache", "pointcache", } - representations = ["*"] + representations = {"*"} label = "Set frame range (with handles)" order = 12 diff --git a/client/ayon_core/hosts/nuke/plugins/load/load_backdrop.py b/client/ayon_core/hosts/nuke/plugins/load/load_backdrop.py index e48dbf5e2f..7d823919dc 100644 --- a/client/ayon_core/hosts/nuke/plugins/load/load_backdrop.py +++ b/client/ayon_core/hosts/nuke/plugins/load/load_backdrop.py @@ -22,7 +22,7 @@ class LoadBackdropNodes(load.LoaderPlugin): """Loading Published Backdrop nodes (workfile, nukenodes)""" product_types = {"workfile", "nukenodes"} - representations = ["*"] + representations = {"*"} extensions = {"nk"} label = "Import Nuke Nodes" diff --git a/client/ayon_core/hosts/nuke/plugins/load/load_camera_abc.py b/client/ayon_core/hosts/nuke/plugins/load/load_camera_abc.py index 70b736b1c8..14c54c3adc 100644 --- a/client/ayon_core/hosts/nuke/plugins/load/load_camera_abc.py +++ b/client/ayon_core/hosts/nuke/plugins/load/load_camera_abc.py @@ -21,7 +21,7 @@ class AlembicCameraLoader(load.LoaderPlugin): """ product_types = {"camera"} - representations = ["*"] + representations = {"*"} extensions = {"abc"} label = "Load Alembic Camera" diff --git a/client/ayon_core/hosts/nuke/plugins/load/load_clip.py b/client/ayon_core/hosts/nuke/plugins/load/load_clip.py index 062a5295ed..df8f2ab018 100644 --- a/client/ayon_core/hosts/nuke/plugins/load/load_clip.py +++ b/client/ayon_core/hosts/nuke/plugins/load/load_clip.py @@ -42,7 +42,7 @@ class LoadClip(plugin.NukeLoader): "prerender", "review", } - representations = ["*"] + representations = {"*"} extensions = set( ext.lstrip(".") for ext in IMAGE_EXTENSIONS.union(VIDEO_EXTENSIONS) ) diff --git a/client/ayon_core/hosts/nuke/plugins/load/load_effects.py b/client/ayon_core/hosts/nuke/plugins/load/load_effects.py index f17b179d1b..a87c81295a 100644 --- a/client/ayon_core/hosts/nuke/plugins/load/load_effects.py +++ b/client/ayon_core/hosts/nuke/plugins/load/load_effects.py @@ -19,7 +19,7 @@ class LoadEffects(load.LoaderPlugin): """Loading colorspace soft effect exported from nukestudio""" product_types = {"effect"} - representations = ["*"] + representations = {"*"} extensions = {"json"} label = "Load Effects - nodes" diff --git a/client/ayon_core/hosts/nuke/plugins/load/load_effects_ip.py b/client/ayon_core/hosts/nuke/plugins/load/load_effects_ip.py index 6b58977a95..8fa1347598 100644 --- a/client/ayon_core/hosts/nuke/plugins/load/load_effects_ip.py +++ b/client/ayon_core/hosts/nuke/plugins/load/load_effects_ip.py @@ -20,7 +20,7 @@ class LoadEffectsInputProcess(load.LoaderPlugin): """Loading colorspace soft effect exported from nukestudio""" product_types = {"effect"} - representations = ["*"] + representations = {"*"} extensions = {"json"} label = "Load Effects - Input Process" diff --git a/client/ayon_core/hosts/nuke/plugins/load/load_gizmo.py b/client/ayon_core/hosts/nuke/plugins/load/load_gizmo.py index 6709648ffb..95f85bacfc 100644 --- a/client/ayon_core/hosts/nuke/plugins/load/load_gizmo.py +++ b/client/ayon_core/hosts/nuke/plugins/load/load_gizmo.py @@ -22,7 +22,7 @@ class LoadGizmo(load.LoaderPlugin): """Loading nuke Gizmo""" product_types = {"gizmo"} - representations = ["*"] + representations = {"*"} extensions = {"nk"} label = "Load Gizmo" diff --git a/client/ayon_core/hosts/nuke/plugins/load/load_gizmo_ip.py b/client/ayon_core/hosts/nuke/plugins/load/load_gizmo_ip.py index 3017fa5fc9..3112e27811 100644 --- a/client/ayon_core/hosts/nuke/plugins/load/load_gizmo_ip.py +++ b/client/ayon_core/hosts/nuke/plugins/load/load_gizmo_ip.py @@ -24,7 +24,7 @@ class LoadGizmoInputProcess(load.LoaderPlugin): """Loading colorspace soft effect exported from nukestudio""" product_types = {"gizmo"} - representations = ["*"] + representations = {"*"} extensions = {"nk"} label = "Load Gizmo - Input Process" diff --git a/client/ayon_core/hosts/nuke/plugins/load/load_image.py b/client/ayon_core/hosts/nuke/plugins/load/load_image.py index 9d3f9ceea0..d825b621fc 100644 --- a/client/ayon_core/hosts/nuke/plugins/load/load_image.py +++ b/client/ayon_core/hosts/nuke/plugins/load/load_image.py @@ -32,7 +32,7 @@ class LoadImage(load.LoaderPlugin): "review", "image", } - representations = ["*"] + representations = {"*"} extensions = set( ext.lstrip(".") for ext in IMAGE_EXTENSIONS ) diff --git a/client/ayon_core/hosts/nuke/plugins/load/load_matchmove.py b/client/ayon_core/hosts/nuke/plugins/load/load_matchmove.py index 73c21376b4..beebd0458f 100644 --- a/client/ayon_core/hosts/nuke/plugins/load/load_matchmove.py +++ b/client/ayon_core/hosts/nuke/plugins/load/load_matchmove.py @@ -8,7 +8,7 @@ class MatchmoveLoader(load.LoaderPlugin): """ product_types = {"matchmove"} - representations = ["*"] + representations = {"*"} extensions = {"py"} defaults = ["Camera", "Object"] diff --git a/client/ayon_core/hosts/nuke/plugins/load/load_model.py b/client/ayon_core/hosts/nuke/plugins/load/load_model.py index 971c36b6cf..0326e0a4fc 100644 --- a/client/ayon_core/hosts/nuke/plugins/load/load_model.py +++ b/client/ayon_core/hosts/nuke/plugins/load/load_model.py @@ -19,7 +19,7 @@ class AlembicModelLoader(load.LoaderPlugin): """ product_types = {"model", "pointcache", "animation"} - representations = ["*"] + representations = {"*"} extensions = {"abc"} label = "Load Alembic" diff --git a/client/ayon_core/hosts/nuke/plugins/load/load_ociolook.py b/client/ayon_core/hosts/nuke/plugins/load/load_ociolook.py index 82addcdfc0..c369030b65 100644 --- a/client/ayon_core/hosts/nuke/plugins/load/load_ociolook.py +++ b/client/ayon_core/hosts/nuke/plugins/load/load_ociolook.py @@ -21,7 +21,7 @@ class LoadOcioLookNodes(load.LoaderPlugin): """Loading Ocio look to the nuke.Node graph""" product_types = {"ociolook"} - representations = ["*"] + representations = {"*"} extensions = {"json"} label = "Load OcioLook [nodes]" diff --git a/client/ayon_core/hosts/nuke/plugins/load/load_script_precomp.py b/client/ayon_core/hosts/nuke/plugins/load/load_script_precomp.py index ccc4164355..3e554f9d3b 100644 --- a/client/ayon_core/hosts/nuke/plugins/load/load_script_precomp.py +++ b/client/ayon_core/hosts/nuke/plugins/load/load_script_precomp.py @@ -17,7 +17,7 @@ class LinkAsGroup(load.LoaderPlugin): """Copy the published file to be pasted at the desired location""" product_types = {"workfile", "nukenodes"} - representations = ["*"] + representations = {"*"} extensions = {"nk"} label = "Load Precomp" diff --git a/client/ayon_core/hosts/photoshop/api/README.md b/client/ayon_core/hosts/photoshop/api/README.md index c936c1ec1f..b391131a42 100644 --- a/client/ayon_core/hosts/photoshop/api/README.md +++ b/client/ayon_core/hosts/photoshop/api/README.md @@ -207,7 +207,7 @@ class ImageLoader(load.LoaderPlugin): """ families = ["image"] - representations = ["*"] + representations = {"*"} def load(self, context, name=None, namespace=None, data=None): path = self.filepath_from_context(context) diff --git a/client/ayon_core/hosts/photoshop/plugins/load/load_image.py b/client/ayon_core/hosts/photoshop/plugins/load/load_image.py index 72df2706b5..d71067615e 100644 --- a/client/ayon_core/hosts/photoshop/plugins/load/load_image.py +++ b/client/ayon_core/hosts/photoshop/plugins/load/load_image.py @@ -12,7 +12,7 @@ class ImageLoader(photoshop.PhotoshopLoader): """ product_types = {"image", "render"} - representations = ["*"] + representations = {"*"} def load(self, context, name=None, namespace=None, data=None): stub = self.get_stub() diff --git a/client/ayon_core/hosts/photoshop/plugins/load/load_image_from_sequence.py b/client/ayon_core/hosts/photoshop/plugins/load/load_image_from_sequence.py index 73e8c3683c..dd14543f3e 100644 --- a/client/ayon_core/hosts/photoshop/plugins/load/load_image_from_sequence.py +++ b/client/ayon_core/hosts/photoshop/plugins/load/load_image_from_sequence.py @@ -25,7 +25,7 @@ class ImageFromSequenceLoader(photoshop.PhotoshopLoader): """ product_types = {"render"} - representations = ["*"] + representations = {"*"} options = [] def load(self, context, name=None, namespace=None, data=None): diff --git a/client/ayon_core/hosts/photoshop/plugins/load/load_reference.py b/client/ayon_core/hosts/photoshop/plugins/load/load_reference.py index 7cd34690f7..b563faff82 100644 --- a/client/ayon_core/hosts/photoshop/plugins/load/load_reference.py +++ b/client/ayon_core/hosts/photoshop/plugins/load/load_reference.py @@ -15,7 +15,7 @@ class ReferenceLoader(photoshop.PhotoshopLoader): """ product_types = {"image", "render"} - representations = ["*"] + representations = {"*"} def load(self, context, name=None, namespace=None, data=None): stub = self.get_stub() diff --git a/client/ayon_core/hosts/resolve/plugins/load/load_clip.py b/client/ayon_core/hosts/resolve/plugins/load/load_clip.py index c7bced5e8e..2ce1c43957 100644 --- a/client/ayon_core/hosts/resolve/plugins/load/load_clip.py +++ b/client/ayon_core/hosts/resolve/plugins/load/load_clip.py @@ -20,7 +20,7 @@ class LoadClip(plugin.TimelineItemLoader): product_types = {"render2d", "source", "plate", "render", "review"} - representations = ["*"] + representations = {"*"} extensions = set( ext.lstrip(".") for ext in IMAGE_EXTENSIONS.union(VIDEO_EXTENSIONS) ) diff --git a/client/ayon_core/hosts/substancepainter/plugins/load/load_mesh.py b/client/ayon_core/hosts/substancepainter/plugins/load/load_mesh.py index d940d7b05c..01cb65dd5c 100644 --- a/client/ayon_core/hosts/substancepainter/plugins/load/load_mesh.py +++ b/client/ayon_core/hosts/substancepainter/plugins/load/load_mesh.py @@ -18,7 +18,7 @@ class SubstanceLoadProjectMesh(load.LoaderPlugin): """Load mesh for project""" product_types = {"*"} - representations = ["abc", "fbx", "obj", "gltf", "usd", "usda", "usdc"] + representations = {"abc", "fbx", "obj", "gltf", "usd", "usda", "usdc"} label = "Load mesh" order = -10 diff --git a/client/ayon_core/hosts/tvpaint/plugins/load/load_image.py b/client/ayon_core/hosts/tvpaint/plugins/load/load_image.py index e954b72f12..aad8f92d26 100644 --- a/client/ayon_core/hosts/tvpaint/plugins/load/load_image.py +++ b/client/ayon_core/hosts/tvpaint/plugins/load/load_image.py @@ -7,7 +7,7 @@ class ImportImage(plugin.Loader): """Load image or image sequence to TVPaint as new layer.""" product_types = {"render", "image", "background", "plate", "review"} - representations = ["*"] + representations = {"*"} label = "Import Image" order = 1 diff --git a/client/ayon_core/hosts/tvpaint/plugins/load/load_reference_image.py b/client/ayon_core/hosts/tvpaint/plugins/load/load_reference_image.py index ec671b0cb1..a7fcb9f4a4 100644 --- a/client/ayon_core/hosts/tvpaint/plugins/load/load_reference_image.py +++ b/client/ayon_core/hosts/tvpaint/plugins/load/load_reference_image.py @@ -18,7 +18,7 @@ class LoadImage(plugin.Loader): """Load image or image sequence to TVPaint as new layer.""" product_types = {"render", "image", "background", "plate", "review"} - representations = ["*"] + representations = {"*"} label = "Load Image" order = 1 diff --git a/client/ayon_core/hosts/tvpaint/plugins/load/load_sound.py b/client/ayon_core/hosts/tvpaint/plugins/load/load_sound.py index d8c6a7a430..7e8c8022d6 100644 --- a/client/ayon_core/hosts/tvpaint/plugins/load/load_sound.py +++ b/client/ayon_core/hosts/tvpaint/plugins/load/load_sound.py @@ -23,7 +23,7 @@ class ImportSound(plugin.Loader): """ product_types = {"audio", "review", "plate"} - representations = ["*"] + representations = {"*"} label = "Import Sound" order = 1 diff --git a/client/ayon_core/hosts/tvpaint/plugins/load/load_workfile.py b/client/ayon_core/hosts/tvpaint/plugins/load/load_workfile.py index 8663dac997..407671e14d 100644 --- a/client/ayon_core/hosts/tvpaint/plugins/load/load_workfile.py +++ b/client/ayon_core/hosts/tvpaint/plugins/load/load_workfile.py @@ -25,7 +25,7 @@ class LoadWorkfile(plugin.Loader): """Load workfile.""" product_types = {"workfile"} - representations = ["tvpp"] + representations = {"tvpp"} label = "Load Workfile" diff --git a/client/ayon_core/hosts/unreal/plugins/load/load_alembic_animation.py b/client/ayon_core/hosts/unreal/plugins/load/load_alembic_animation.py index 64d684939c..a12f4f41b4 100644 --- a/client/ayon_core/hosts/unreal/plugins/load/load_alembic_animation.py +++ b/client/ayon_core/hosts/unreal/plugins/load/load_alembic_animation.py @@ -16,7 +16,7 @@ class AnimationAlembicLoader(plugin.Loader): product_types = {"animation"} label = "Import Alembic Animation" - representations = ["abc"] + representations = {"abc"} icon = "cube" color = "orange" diff --git a/client/ayon_core/hosts/unreal/plugins/load/load_animation.py b/client/ayon_core/hosts/unreal/plugins/load/load_animation.py index 59b9f66b78..f6a612ce53 100644 --- a/client/ayon_core/hosts/unreal/plugins/load/load_animation.py +++ b/client/ayon_core/hosts/unreal/plugins/load/load_animation.py @@ -22,7 +22,7 @@ class AnimationFBXLoader(plugin.Loader): product_types = {"animation"} label = "Import FBX Animation" - representations = ["fbx"] + representations = {"fbx"} icon = "cube" color = "orange" diff --git a/client/ayon_core/hosts/unreal/plugins/load/load_camera.py b/client/ayon_core/hosts/unreal/plugins/load/load_camera.py index 285834c911..681c83c6a1 100644 --- a/client/ayon_core/hosts/unreal/plugins/load/load_camera.py +++ b/client/ayon_core/hosts/unreal/plugins/load/load_camera.py @@ -30,7 +30,7 @@ class CameraLoader(plugin.Loader): product_types = {"camera"} label = "Load Camera" - representations = ["fbx"] + representations = {"fbx"} icon = "cube" color = "orange" diff --git a/client/ayon_core/hosts/unreal/plugins/load/load_geometrycache_abc.py b/client/ayon_core/hosts/unreal/plugins/load/load_geometrycache_abc.py index 44c308069b..ae7d41192a 100644 --- a/client/ayon_core/hosts/unreal/plugins/load/load_geometrycache_abc.py +++ b/client/ayon_core/hosts/unreal/plugins/load/load_geometrycache_abc.py @@ -21,7 +21,7 @@ class PointCacheAlembicLoader(plugin.Loader): product_types = {"model", "pointcache"} label = "Import Alembic Point Cache" - representations = ["abc"] + representations = {"abc"} icon = "cube" color = "orange" diff --git a/client/ayon_core/hosts/unreal/plugins/load/load_layout.py b/client/ayon_core/hosts/unreal/plugins/load/load_layout.py index b0f09ee8b0..49d95c6459 100644 --- a/client/ayon_core/hosts/unreal/plugins/load/load_layout.py +++ b/client/ayon_core/hosts/unreal/plugins/load/load_layout.py @@ -41,7 +41,7 @@ class LayoutLoader(plugin.Loader): """Load Layout from a JSON file""" product_types = {"layout"} - representations = ["json"] + representations = {"json"} label = "Load Layout" icon = "code-fork" diff --git a/client/ayon_core/hosts/unreal/plugins/load/load_layout_existing.py b/client/ayon_core/hosts/unreal/plugins/load/load_layout_existing.py index 56e36f6185..f9d438367b 100644 --- a/client/ayon_core/hosts/unreal/plugins/load/load_layout_existing.py +++ b/client/ayon_core/hosts/unreal/plugins/load/load_layout_existing.py @@ -22,7 +22,7 @@ class ExistingLayoutLoader(plugin.Loader): """ product_types = {"layout"} - representations = ["json"] + representations = {"json"} label = "Load Layout on Existing Scene" icon = "code-fork" diff --git a/client/ayon_core/hosts/unreal/plugins/load/load_skeletalmesh_abc.py b/client/ayon_core/hosts/unreal/plugins/load/load_skeletalmesh_abc.py index 64b1810080..dfc5d58708 100644 --- a/client/ayon_core/hosts/unreal/plugins/load/load_skeletalmesh_abc.py +++ b/client/ayon_core/hosts/unreal/plugins/load/load_skeletalmesh_abc.py @@ -20,7 +20,7 @@ class SkeletalMeshAlembicLoader(plugin.Loader): product_types = {"pointcache", "skeletalMesh"} label = "Import Alembic Skeletal Mesh" - representations = ["abc"] + representations = {"abc"} icon = "cube" color = "orange" diff --git a/client/ayon_core/hosts/unreal/plugins/load/load_skeletalmesh_fbx.py b/client/ayon_core/hosts/unreal/plugins/load/load_skeletalmesh_fbx.py index f61f0dbc3f..513404ab98 100644 --- a/client/ayon_core/hosts/unreal/plugins/load/load_skeletalmesh_fbx.py +++ b/client/ayon_core/hosts/unreal/plugins/load/load_skeletalmesh_fbx.py @@ -20,7 +20,7 @@ class SkeletalMeshFBXLoader(plugin.Loader): product_types = {"rig", "skeletalMesh"} label = "Import FBX Skeletal Mesh" - representations = ["fbx"] + representations = {"fbx"} icon = "cube" color = "orange" diff --git a/client/ayon_core/hosts/unreal/plugins/load/load_staticmesh_abc.py b/client/ayon_core/hosts/unreal/plugins/load/load_staticmesh_abc.py index 256cb9e8bc..0bf6ce9eaa 100644 --- a/client/ayon_core/hosts/unreal/plugins/load/load_staticmesh_abc.py +++ b/client/ayon_core/hosts/unreal/plugins/load/load_staticmesh_abc.py @@ -20,7 +20,7 @@ class StaticMeshAlembicLoader(plugin.Loader): product_types = {"model", "staticMesh"} label = "Import Alembic Static Mesh" - representations = ["abc"] + representations = {"abc"} icon = "cube" color = "orange" diff --git a/client/ayon_core/hosts/unreal/plugins/load/load_staticmesh_fbx.py b/client/ayon_core/hosts/unreal/plugins/load/load_staticmesh_fbx.py index 0ec4b1b4f8..b7bb57ac23 100644 --- a/client/ayon_core/hosts/unreal/plugins/load/load_staticmesh_fbx.py +++ b/client/ayon_core/hosts/unreal/plugins/load/load_staticmesh_fbx.py @@ -20,7 +20,7 @@ class StaticMeshFBXLoader(plugin.Loader): product_types = {"model", "staticMesh"} label = "Import FBX Static Mesh" - representations = ["fbx"] + representations = {"fbx"} icon = "cube" color = "orange" diff --git a/client/ayon_core/hosts/unreal/plugins/load/load_uasset.py b/client/ayon_core/hosts/unreal/plugins/load/load_uasset.py index 89ef357c89..63f23ecc11 100644 --- a/client/ayon_core/hosts/unreal/plugins/load/load_uasset.py +++ b/client/ayon_core/hosts/unreal/plugins/load/load_uasset.py @@ -17,7 +17,7 @@ class UAssetLoader(plugin.Loader): product_types = {"uasset"} label = "Load UAsset" - representations = ["uasset"] + representations = {"uasset"} icon = "cube" color = "orange" @@ -166,6 +166,6 @@ class UMapLoader(UAssetLoader): product_types = {"uasset"} label = "Load Level" - representations = ["umap"] + representations = {"umap"} extension = "umap" diff --git a/client/ayon_core/hosts/unreal/plugins/load/load_yeticache.py b/client/ayon_core/hosts/unreal/plugins/load/load_yeticache.py index 21715a24c6..708fc83745 100644 --- a/client/ayon_core/hosts/unreal/plugins/load/load_yeticache.py +++ b/client/ayon_core/hosts/unreal/plugins/load/load_yeticache.py @@ -17,7 +17,7 @@ class YetiLoader(plugin.Loader): product_types = {"yeticacheUE"} label = "Import Yeti" - representations = ["abc"] + representations = {"abc"} icon = "pagelines" color = "orange" diff --git a/client/ayon_core/plugins/load/copy_file.py b/client/ayon_core/plugins/load/copy_file.py index 5e6daa866b..08dad03be3 100644 --- a/client/ayon_core/plugins/load/copy_file.py +++ b/client/ayon_core/plugins/load/copy_file.py @@ -5,7 +5,7 @@ from ayon_core.pipeline import load class CopyFile(load.LoaderPlugin): """Copy the published file to be pasted at the desired location""" - representations = ["*"] + representations = {"*"} product_types = {"*"} label = "Copy File" diff --git a/client/ayon_core/plugins/load/copy_file_path.py b/client/ayon_core/plugins/load/copy_file_path.py index ecde3bc55f..fdf31b5e02 100644 --- a/client/ayon_core/plugins/load/copy_file_path.py +++ b/client/ayon_core/plugins/load/copy_file_path.py @@ -5,7 +5,7 @@ from ayon_core.pipeline import load class CopyFilePath(load.LoaderPlugin): """Copy published file path to clipboard""" - representations = ["*"] + representations = {"*"} product_types = {"*"} label = "Copy File Path" diff --git a/client/ayon_core/plugins/load/delete_old_versions.py b/client/ayon_core/plugins/load/delete_old_versions.py index 04873d8b5c..8e04fd9827 100644 --- a/client/ayon_core/plugins/load/delete_old_versions.py +++ b/client/ayon_core/plugins/load/delete_old_versions.py @@ -26,7 +26,7 @@ # is_multiple_contexts_compatible = True # sequence_splitter = "__sequence_splitter__" # -# representations = ["*"] +# representations = {"*"} # product_types = {"*"} # tool_names = ["library_loader"] # diff --git a/client/ayon_core/plugins/load/delivery.py b/client/ayon_core/plugins/load/delivery.py index cd358846ea..c7954a18b2 100644 --- a/client/ayon_core/plugins/load/delivery.py +++ b/client/ayon_core/plugins/load/delivery.py @@ -28,7 +28,7 @@ class Delivery(load.ProductLoaderPlugin): is_multiple_contexts_compatible = True sequence_splitter = "__sequence_splitter__" - representations = ["*"] + representations = {"*"} product_types = {"*"} tool_names = ["library_loader"] diff --git a/client/ayon_core/plugins/load/open_file.py b/client/ayon_core/plugins/load/open_file.py index fc57708cd6..3b5fbbc0c9 100644 --- a/client/ayon_core/plugins/load/open_file.py +++ b/client/ayon_core/plugins/load/open_file.py @@ -19,7 +19,7 @@ class OpenFile(load.LoaderPlugin): """Open Image Sequence or Video with system default""" product_types = {"render2d"} - representations = ["*"] + representations = {"*"} label = "Open" order = -10 diff --git a/client/ayon_core/plugins/load/push_to_library.py b/client/ayon_core/plugins/load/push_to_library.py index 02d834bc95..981028d734 100644 --- a/client/ayon_core/plugins/load/push_to_library.py +++ b/client/ayon_core/plugins/load/push_to_library.py @@ -11,7 +11,7 @@ class PushToLibraryProject(load.ProductLoaderPlugin): is_multiple_contexts_compatible = True - representations = ["*"] + representations = {"*"} product_types = {"*"} label = "Push to Library project" From 84f8a61cc64d85f71441bf253a45042ec67efc4e Mon Sep 17 00:00:00 2001 From: Jakub Trllo <43494761+iLLiCiTiT@users.noreply.github.com> Date: Tue, 9 Apr 2024 17:28:49 +0200 Subject: [PATCH 27/92] add docstring --- client/ayon_core/pipeline/load/plugins.py | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/client/ayon_core/pipeline/load/plugins.py b/client/ayon_core/pipeline/load/plugins.py index 3f47ec421e..2475800cbb 100644 --- a/client/ayon_core/pipeline/load/plugins.py +++ b/client/ayon_core/pipeline/load/plugins.py @@ -162,6 +162,15 @@ class LoaderPlugin(list): @classmethod def get_representations(cls): + """Representation names with which is plugin compatible. + + Empty set makes the plugin incompatible with any representation. To + allow compatibility with all representations use '{"*"}'. + + Returns: + set[str]: Names with which is plugin compatible. + + """ return cls.representations @classmethod From 3c73c1762740d7385f951b39195abe719ea96134 Mon Sep 17 00:00:00 2001 From: Jakub Trllo <43494761+iLLiCiTiT@users.noreply.github.com> Date: Wed, 10 Apr 2024 11:03:05 +0200 Subject: [PATCH 28/92] removed unused imports in settings --- server_addon/maya/server/settings/loaders.py | 2 +- server_addon/maya/server/settings/publish_playblast.py | 2 +- server_addon/tvpaint/server/settings/publish_plugins.py | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/server_addon/maya/server/settings/loaders.py b/server_addon/maya/server/settings/loaders.py index 4e949f616a..f59711b1e6 100644 --- a/server_addon/maya/server/settings/loaders.py +++ b/server_addon/maya/server/settings/loaders.py @@ -1,5 +1,5 @@ from ayon_server.settings import BaseSettingsModel, SettingsField -from ayon_server.types import ColorRGB_float, ColorRGBA_uint8 +from ayon_server.types import ColorRGBA_uint8 class LoaderEnabledModel(BaseSettingsModel): diff --git a/server_addon/maya/server/settings/publish_playblast.py b/server_addon/maya/server/settings/publish_playblast.py index 39f48bacbe..d513a43e99 100644 --- a/server_addon/maya/server/settings/publish_playblast.py +++ b/server_addon/maya/server/settings/publish_playblast.py @@ -6,7 +6,7 @@ from ayon_server.settings import ( ensure_unique_names, task_types_enum, ) -from ayon_server.types import ColorRGBA_uint8, ColorRGB_float +from ayon_server.types import ColorRGBA_uint8 def hardware_falloff_enum(): diff --git a/server_addon/tvpaint/server/settings/publish_plugins.py b/server_addon/tvpaint/server/settings/publish_plugins.py index 0d978e5714..db1c7bd11a 100644 --- a/server_addon/tvpaint/server/settings/publish_plugins.py +++ b/server_addon/tvpaint/server/settings/publish_plugins.py @@ -1,5 +1,5 @@ from ayon_server.settings import BaseSettingsModel, SettingsField -from ayon_server.types import ColorRGBA_uint8, ColorRGB_uint8 +from ayon_server.types import ColorRGBA_uint8 class CollectRenderInstancesModel(BaseSettingsModel): From 640bbaadec212d35c8a68335361395034ac22cbf Mon Sep 17 00:00:00 2001 From: Jakub Trllo <43494761+iLLiCiTiT@users.noreply.github.com> Date: Wed, 10 Apr 2024 11:04:48 +0200 Subject: [PATCH 29/92] remove unused import in ayon core --- .../publish/validate_look_default_shaders_connections.py | 1 - client/ayon_core/hosts/nuke/api/plugin.py | 2 +- .../plugins/publish/create_publish_royalrender_job.py | 1 - client/ayon_core/pipeline/anatomy/templates.py | 1 - client/ayon_core/pipeline/context_tools.py | 2 -- client/ayon_core/pipeline/schema/__init__.py | 1 - client/ayon_core/plugins/actions/open_file_explorer.py | 2 -- 7 files changed, 1 insertion(+), 9 deletions(-) diff --git a/client/ayon_core/hosts/maya/plugins/publish/validate_look_default_shaders_connections.py b/client/ayon_core/hosts/maya/plugins/publish/validate_look_default_shaders_connections.py index d8a9222c36..cfd4156124 100644 --- a/client/ayon_core/hosts/maya/plugins/publish/validate_look_default_shaders_connections.py +++ b/client/ayon_core/hosts/maya/plugins/publish/validate_look_default_shaders_connections.py @@ -2,7 +2,6 @@ from maya import cmds import pyblish.api from ayon_core.pipeline.publish import ( - ValidateContentsOrder, RepairContextAction, PublishValidationError ) diff --git a/client/ayon_core/hosts/nuke/api/plugin.py b/client/ayon_core/hosts/nuke/api/plugin.py index 6aa098c558..5b97fab0c2 100644 --- a/client/ayon_core/hosts/nuke/api/plugin.py +++ b/client/ayon_core/hosts/nuke/api/plugin.py @@ -5,7 +5,7 @@ import sys import six import random import string -from collections import OrderedDict, defaultdict +from collections import defaultdict from ayon_core.settings import get_current_project_settings from ayon_core.lib import ( diff --git a/client/ayon_core/modules/royalrender/plugins/publish/create_publish_royalrender_job.py b/client/ayon_core/modules/royalrender/plugins/publish/create_publish_royalrender_job.py index f3287b7638..51500f84f5 100644 --- a/client/ayon_core/modules/royalrender/plugins/publish/create_publish_royalrender_job.py +++ b/client/ayon_core/modules/royalrender/plugins/publish/create_publish_royalrender_job.py @@ -3,7 +3,6 @@ import os import attr import json -import re import pyblish.api diff --git a/client/ayon_core/pipeline/anatomy/templates.py b/client/ayon_core/pipeline/anatomy/templates.py index 46cad385f0..d89b70719e 100644 --- a/client/ayon_core/pipeline/anatomy/templates.py +++ b/client/ayon_core/pipeline/anatomy/templates.py @@ -14,7 +14,6 @@ from .exceptions import ( TemplateMissingKey, AnatomyTemplateUnsolved, ) -from .roots import RootItem _PLACEHOLDER = object() diff --git a/client/ayon_core/pipeline/context_tools.py b/client/ayon_core/pipeline/context_tools.py index e9151bcd1f..33567d7280 100644 --- a/client/ayon_core/pipeline/context_tools.py +++ b/client/ayon_core/pipeline/context_tools.py @@ -1,7 +1,6 @@ """Core pipeline functionality""" import os -import types import logging import platform import uuid @@ -21,7 +20,6 @@ from .anatomy import Anatomy from .template_data import get_template_data_with_names from .workfile import ( get_workdir, - get_workfile_template_key, get_custom_workfile_template_by_string_context, ) from . import ( diff --git a/client/ayon_core/pipeline/schema/__init__.py b/client/ayon_core/pipeline/schema/__init__.py index 67cf120b59..db98a6d080 100644 --- a/client/ayon_core/pipeline/schema/__init__.py +++ b/client/ayon_core/pipeline/schema/__init__.py @@ -13,7 +13,6 @@ Resources: """ import os -import re import json import logging diff --git a/client/ayon_core/plugins/actions/open_file_explorer.py b/client/ayon_core/plugins/actions/open_file_explorer.py index 6a456c75c1..50a3107444 100644 --- a/client/ayon_core/plugins/actions/open_file_explorer.py +++ b/client/ayon_core/plugins/actions/open_file_explorer.py @@ -3,8 +3,6 @@ import platform import subprocess from string import Formatter -import ayon_api - from ayon_core.pipeline import ( Anatomy, LauncherAction, From 75bb2b7a46b13e619b853a2a6b1b7ae7969b9619 Mon Sep 17 00:00:00 2001 From: Jakub Trllo <43494761+iLLiCiTiT@users.noreply.github.com> Date: Wed, 10 Apr 2024 11:09:12 +0200 Subject: [PATCH 30/92] remove python 2 compatible type hint in houdini this is because ruff does not use this type hinting --- .../hosts/houdini/plugins/create/create_alembic_camera.py | 4 ++-- .../hosts/houdini/plugins/create/create_arnold_ass.py | 2 +- .../hosts/houdini/plugins/create/create_arnold_rop.py | 2 +- client/ayon_core/hosts/houdini/plugins/create/create_bgeo.py | 4 ++-- .../hosts/houdini/plugins/create/create_composite.py | 4 ++-- client/ayon_core/hosts/houdini/plugins/create/create_hda.py | 2 +- .../hosts/houdini/plugins/create/create_karma_rop.py | 3 +-- .../hosts/houdini/plugins/create/create_mantra_ifd.py | 3 +-- .../hosts/houdini/plugins/create/create_mantra_rop.py | 3 +-- client/ayon_core/hosts/houdini/plugins/create/create_usd.py | 3 +-- .../hosts/houdini/plugins/create/create_usdrender.py | 3 +-- .../hosts/houdini/plugins/create/create_vbd_cache.py | 3 +-- .../ayon_core/hosts/houdini/plugins/create/create_vray_rop.py | 4 ++-- .../hosts/houdini/plugins/publish/increment_current_file.py | 3 +-- 14 files changed, 18 insertions(+), 25 deletions(-) diff --git a/client/ayon_core/hosts/houdini/plugins/create/create_alembic_camera.py b/client/ayon_core/hosts/houdini/plugins/create/create_alembic_camera.py index b61b4cbd46..0ab5e2794e 100644 --- a/client/ayon_core/hosts/houdini/plugins/create/create_alembic_camera.py +++ b/client/ayon_core/hosts/houdini/plugins/create/create_alembic_camera.py @@ -1,7 +1,7 @@ # -*- coding: utf-8 -*- """Creator plugin for creating alembic camera products.""" from ayon_core.hosts.houdini.api import plugin -from ayon_core.pipeline import CreatedInstance, CreatorError +from ayon_core.pipeline import CreatorError import hou @@ -23,7 +23,7 @@ class CreateAlembicCamera(plugin.HoudiniCreator): instance = super(CreateAlembicCamera, self).create( product_name, instance_data, - pre_create_data) # type: CreatedInstance + pre_create_data) instance_node = hou.node(instance.get("instance_node")) parms = { diff --git a/client/ayon_core/hosts/houdini/plugins/create/create_arnold_ass.py b/client/ayon_core/hosts/houdini/plugins/create/create_arnold_ass.py index 6d992f136a..be5604c01c 100644 --- a/client/ayon_core/hosts/houdini/plugins/create/create_arnold_ass.py +++ b/client/ayon_core/hosts/houdini/plugins/create/create_arnold_ass.py @@ -29,7 +29,7 @@ class CreateArnoldAss(plugin.HoudiniCreator): instance = super(CreateArnoldAss, self).create( product_name, instance_data, - pre_create_data) # type: plugin.CreatedInstance + pre_create_data) instance_node = hou.node(instance.get("instance_node")) diff --git a/client/ayon_core/hosts/houdini/plugins/create/create_arnold_rop.py b/client/ayon_core/hosts/houdini/plugins/create/create_arnold_rop.py index b7c5910a4f..f65b54a452 100644 --- a/client/ayon_core/hosts/houdini/plugins/create/create_arnold_rop.py +++ b/client/ayon_core/hosts/houdini/plugins/create/create_arnold_rop.py @@ -31,7 +31,7 @@ class CreateArnoldRop(plugin.HoudiniCreator): instance = super(CreateArnoldRop, self).create( product_name, instance_data, - pre_create_data) # type: plugin.CreatedInstance + pre_create_data) instance_node = hou.node(instance.get("instance_node")) diff --git a/client/ayon_core/hosts/houdini/plugins/create/create_bgeo.py b/client/ayon_core/hosts/houdini/plugins/create/create_bgeo.py index 92c89c71cb..3749598b1d 100644 --- a/client/ayon_core/hosts/houdini/plugins/create/create_bgeo.py +++ b/client/ayon_core/hosts/houdini/plugins/create/create_bgeo.py @@ -1,7 +1,7 @@ # -*- coding: utf-8 -*- """Creator plugin for creating pointcache bgeo files.""" from ayon_core.hosts.houdini.api import plugin -from ayon_core.pipeline import CreatedInstance, CreatorError +from ayon_core.pipeline import CreatorError import hou from ayon_core.lib import EnumDef, BoolDef @@ -25,7 +25,7 @@ class CreateBGEO(plugin.HoudiniCreator): instance = super(CreateBGEO, self).create( product_name, instance_data, - pre_create_data) # type: CreatedInstance + pre_create_data) instance_node = hou.node(instance.get("instance_node")) diff --git a/client/ayon_core/hosts/houdini/plugins/create/create_composite.py b/client/ayon_core/hosts/houdini/plugins/create/create_composite.py index a1104e5093..a25faf0e8e 100644 --- a/client/ayon_core/hosts/houdini/plugins/create/create_composite.py +++ b/client/ayon_core/hosts/houdini/plugins/create/create_composite.py @@ -1,7 +1,7 @@ # -*- coding: utf-8 -*- """Creator plugin for creating composite sequences.""" from ayon_core.hosts.houdini.api import plugin -from ayon_core.pipeline import CreatedInstance, CreatorError +from ayon_core.pipeline import CreatorError import hou @@ -25,7 +25,7 @@ class CreateCompositeSequence(plugin.HoudiniCreator): instance = super(CreateCompositeSequence, self).create( product_name, instance_data, - pre_create_data) # type: CreatedInstance + pre_create_data) instance_node = hou.node(instance.get("instance_node")) filepath = "{}{}".format( diff --git a/client/ayon_core/hosts/houdini/plugins/create/create_hda.py b/client/ayon_core/hosts/houdini/plugins/create/create_hda.py index b307293dc8..d399aa5e15 100644 --- a/client/ayon_core/hosts/houdini/plugins/create/create_hda.py +++ b/client/ayon_core/hosts/houdini/plugins/create/create_hda.py @@ -78,7 +78,7 @@ class CreateHDA(plugin.HoudiniCreator): instance = super(CreateHDA, self).create( product_name, instance_data, - pre_create_data) # type: plugin.CreatedInstance + pre_create_data) return instance diff --git a/client/ayon_core/hosts/houdini/plugins/create/create_karma_rop.py b/client/ayon_core/hosts/houdini/plugins/create/create_karma_rop.py index 9eb9d80cd3..e91ddbc0ac 100644 --- a/client/ayon_core/hosts/houdini/plugins/create/create_karma_rop.py +++ b/client/ayon_core/hosts/houdini/plugins/create/create_karma_rop.py @@ -1,7 +1,6 @@ # -*- coding: utf-8 -*- """Creator plugin to create Karma ROP.""" from ayon_core.hosts.houdini.api import plugin -from ayon_core.pipeline import CreatedInstance from ayon_core.lib import BoolDef, EnumDef, NumberDef @@ -25,7 +24,7 @@ class CreateKarmaROP(plugin.HoudiniCreator): instance = super(CreateKarmaROP, self).create( product_name, instance_data, - pre_create_data) # type: CreatedInstance + pre_create_data) instance_node = hou.node(instance.get("instance_node")) diff --git a/client/ayon_core/hosts/houdini/plugins/create/create_mantra_ifd.py b/client/ayon_core/hosts/houdini/plugins/create/create_mantra_ifd.py index bb10f3893c..e0cf035c35 100644 --- a/client/ayon_core/hosts/houdini/plugins/create/create_mantra_ifd.py +++ b/client/ayon_core/hosts/houdini/plugins/create/create_mantra_ifd.py @@ -1,7 +1,6 @@ # -*- coding: utf-8 -*- """Creator plugin for creating pointcache alembics.""" from ayon_core.hosts.houdini.api import plugin -from ayon_core.pipeline import CreatedInstance from ayon_core.lib import BoolDef @@ -22,7 +21,7 @@ class CreateMantraIFD(plugin.HoudiniCreator): instance = super(CreateMantraIFD, self).create( product_name, instance_data, - pre_create_data) # type: CreatedInstance + pre_create_data) instance_node = hou.node(instance.get("instance_node")) diff --git a/client/ayon_core/hosts/houdini/plugins/create/create_mantra_rop.py b/client/ayon_core/hosts/houdini/plugins/create/create_mantra_rop.py index f15f49f463..64ecf428e9 100644 --- a/client/ayon_core/hosts/houdini/plugins/create/create_mantra_rop.py +++ b/client/ayon_core/hosts/houdini/plugins/create/create_mantra_rop.py @@ -1,7 +1,6 @@ # -*- coding: utf-8 -*- """Creator plugin to create Mantra ROP.""" from ayon_core.hosts.houdini.api import plugin -from ayon_core.pipeline import CreatedInstance from ayon_core.lib import EnumDef, BoolDef @@ -28,7 +27,7 @@ class CreateMantraROP(plugin.HoudiniCreator): instance = super(CreateMantraROP, self).create( product_name, instance_data, - pre_create_data) # type: CreatedInstance + pre_create_data) instance_node = hou.node(instance.get("instance_node")) diff --git a/client/ayon_core/hosts/houdini/plugins/create/create_usd.py b/client/ayon_core/hosts/houdini/plugins/create/create_usd.py index ee05639368..700f7eefd6 100644 --- a/client/ayon_core/hosts/houdini/plugins/create/create_usd.py +++ b/client/ayon_core/hosts/houdini/plugins/create/create_usd.py @@ -1,7 +1,6 @@ # -*- coding: utf-8 -*- """Creator plugin for creating USDs.""" from ayon_core.hosts.houdini.api import plugin -from ayon_core.pipeline import CreatedInstance import hou @@ -22,7 +21,7 @@ class CreateUSD(plugin.HoudiniCreator): instance = super(CreateUSD, self).create( product_name, instance_data, - pre_create_data) # type: CreatedInstance + pre_create_data) instance_node = hou.node(instance.get("instance_node")) diff --git a/client/ayon_core/hosts/houdini/plugins/create/create_usdrender.py b/client/ayon_core/hosts/houdini/plugins/create/create_usdrender.py index 0a5c8896a8..36197e349e 100644 --- a/client/ayon_core/hosts/houdini/plugins/create/create_usdrender.py +++ b/client/ayon_core/hosts/houdini/plugins/create/create_usdrender.py @@ -1,7 +1,6 @@ # -*- coding: utf-8 -*- """Creator plugin for creating USD renders.""" from ayon_core.hosts.houdini.api import plugin -from ayon_core.pipeline import CreatedInstance class CreateUSDRender(plugin.HoudiniCreator): @@ -23,7 +22,7 @@ class CreateUSDRender(plugin.HoudiniCreator): instance = super(CreateUSDRender, self).create( product_name, instance_data, - pre_create_data) # type: CreatedInstance + pre_create_data) instance_node = hou.node(instance.get("instance_node")) diff --git a/client/ayon_core/hosts/houdini/plugins/create/create_vbd_cache.py b/client/ayon_core/hosts/houdini/plugins/create/create_vbd_cache.py index 9ac7ebdff7..c34cd2b4b5 100644 --- a/client/ayon_core/hosts/houdini/plugins/create/create_vbd_cache.py +++ b/client/ayon_core/hosts/houdini/plugins/create/create_vbd_cache.py @@ -1,7 +1,6 @@ # -*- coding: utf-8 -*- """Creator plugin for creating VDB Caches.""" from ayon_core.hosts.houdini.api import plugin -from ayon_core.pipeline import CreatedInstance from ayon_core.lib import BoolDef import hou @@ -26,7 +25,7 @@ class CreateVDBCache(plugin.HoudiniCreator): instance = super(CreateVDBCache, self).create( product_name, instance_data, - pre_create_data) # type: CreatedInstance + pre_create_data) instance_node = hou.node(instance.get("instance_node")) file_path = "{}{}".format( diff --git a/client/ayon_core/hosts/houdini/plugins/create/create_vray_rop.py b/client/ayon_core/hosts/houdini/plugins/create/create_vray_rop.py index 6b2396bffb..5ed9e848a7 100644 --- a/client/ayon_core/hosts/houdini/plugins/create/create_vray_rop.py +++ b/client/ayon_core/hosts/houdini/plugins/create/create_vray_rop.py @@ -3,7 +3,7 @@ import hou from ayon_core.hosts.houdini.api import plugin -from ayon_core.pipeline import CreatedInstance, CreatorError +from ayon_core.pipeline import CreatorError from ayon_core.lib import EnumDef, BoolDef @@ -31,7 +31,7 @@ class CreateVrayROP(plugin.HoudiniCreator): instance = super(CreateVrayROP, self).create( product_name, instance_data, - pre_create_data) # type: CreatedInstance + pre_create_data) instance_node = hou.node(instance.get("instance_node")) diff --git a/client/ayon_core/hosts/houdini/plugins/publish/increment_current_file.py b/client/ayon_core/hosts/houdini/plugins/publish/increment_current_file.py index 73145b211a..fe8fa25f10 100644 --- a/client/ayon_core/hosts/houdini/plugins/publish/increment_current_file.py +++ b/client/ayon_core/hosts/houdini/plugins/publish/increment_current_file.py @@ -3,7 +3,6 @@ import pyblish.api from ayon_core.lib import version_up from ayon_core.pipeline import registered_host from ayon_core.pipeline.publish import get_errored_plugins_from_context -from ayon_core.hosts.houdini.api import HoudiniHost from ayon_core.pipeline.publish import KnownPublishError @@ -39,7 +38,7 @@ class IncrementCurrentFile(pyblish.api.ContextPlugin): ) # Filename must not have changed since collecting - host = registered_host() # type: HoudiniHost + host = registered_host() current_file = host.current_file() if context.data["currentFile"] != current_file: raise KnownPublishError( From 22a845b8170a3022ff05493ffef2d726b4e62f9f Mon Sep 17 00:00:00 2001 From: Jakub Trllo <43494761+iLLiCiTiT@users.noreply.github.com> Date: Wed, 10 Apr 2024 11:09:53 +0200 Subject: [PATCH 31/92] remove python 2 compatible type hint in maya this is because ruff does not use this type hinting --- client/ayon_core/hosts/maya/api/fbx.py | 3 --- 1 file changed, 3 deletions(-) diff --git a/client/ayon_core/hosts/maya/api/fbx.py b/client/ayon_core/hosts/maya/api/fbx.py index 97e95d2ec4..939da4011b 100644 --- a/client/ayon_core/hosts/maya/api/fbx.py +++ b/client/ayon_core/hosts/maya/api/fbx.py @@ -2,8 +2,6 @@ """Tools to work with FBX.""" import logging -from pyblish.api import Instance - from maya import cmds # noqa import maya.mel as mel # noqa from ayon_core.hosts.maya.api.lib import maintained_selection @@ -146,7 +144,6 @@ class FBXExtractor: return options def set_options_from_instance(self, instance): - # type: (Instance) -> None """Sets FBX export options from data in the instance. Args: From 8a49a5533d09fb16665f0b7d7f6dcaaaa1445d35 Mon Sep 17 00:00:00 2001 From: Jakub Trllo <43494761+iLLiCiTiT@users.noreply.github.com> Date: Wed, 10 Apr 2024 11:10:49 +0200 Subject: [PATCH 32/92] modify RR imports in api.py added noqa F401 for ruff which does not use python 2 type hinting --- client/ayon_core/modules/royalrender/api.py | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/client/ayon_core/modules/royalrender/api.py b/client/ayon_core/modules/royalrender/api.py index cd72014a42..a69f88c43c 100644 --- a/client/ayon_core/modules/royalrender/api.py +++ b/client/ayon_core/modules/royalrender/api.py @@ -1,13 +1,14 @@ # -*- coding: utf-8 -*- """Wrapper around Royal Render API.""" -import sys import os +import sys -from ayon_core.lib.local_settings import AYONSettingsRegistry -from ayon_core.lib import Logger, run_subprocess -from .rr_job import RRJob, SubmitFile, SubmitterParameter +from ayon_core.lib import Logger, run_subprocess, AYONSettingsRegistry from ayon_core.lib.vendor_bin_utils import find_tool_in_custom_paths +from .rr_job import SubmitFile +from .rr_job import RRjob, SubmitterParameter # noqa F401 + class Api: From c89eb16689e1d1beebae112a19ee0ca7d08b2089 Mon Sep 17 00:00:00 2001 From: Jakub Trllo <43494761+iLLiCiTiT@users.noreply.github.com> Date: Wed, 10 Apr 2024 11:11:25 +0200 Subject: [PATCH 33/92] remove python 2 compatible type hint in pyblish functions this is because ruff does not use this type hinting --- client/ayon_core/pipeline/farm/pyblish_functions.py | 12 ++++-------- 1 file changed, 4 insertions(+), 8 deletions(-) diff --git a/client/ayon_core/pipeline/farm/pyblish_functions.py b/client/ayon_core/pipeline/farm/pyblish_functions.py index dadf2cbe1a..37003cbd88 100644 --- a/client/ayon_core/pipeline/farm/pyblish_functions.py +++ b/client/ayon_core/pipeline/farm/pyblish_functions.py @@ -6,13 +6,11 @@ from copy import deepcopy import attr import ayon_api -import pyblish.api import clique from ayon_core.pipeline import ( get_current_project_name, get_representation_path, - Anatomy, ) from ayon_core.lib import Logger from ayon_core.pipeline.publish import KnownPublishError @@ -137,7 +135,7 @@ def get_transferable_representations(instance): list of dicts: List of transferable representations. """ - anatomy = instance.context.data["anatomy"] # type: Anatomy + anatomy = instance.context.data["anatomy"] to_transfer = [] for representation in instance.data.get("representations", []): @@ -166,7 +164,6 @@ def get_transferable_representations(instance): def create_skeleton_instance( instance, families_transfer=None, instance_transfer=None): - # type: (pyblish.api.Instance, list, dict) -> dict """Create skeleton instance from original instance data. This will create dictionary containing skeleton @@ -191,7 +188,7 @@ def create_skeleton_instance( context = instance.context data = instance.data.copy() - anatomy = instance.context.data["anatomy"] # type: Anatomy + anatomy = instance.context.data["anatomy"] # get time related data from instance (or context) time_data = get_time_data_from_instance_or_context(instance) @@ -751,7 +748,6 @@ def get_resources(project_name, version_entity, extension=None): def create_skeleton_instance_cache(instance): - # type: (pyblish.api.Instance, list, dict) -> dict """Create skeleton instance from original instance data. This will create dictionary containing skeleton @@ -771,7 +767,7 @@ def create_skeleton_instance_cache(instance): context = instance.context data = instance.data.copy() - anatomy = instance.context.data["anatomy"] # type: Anatomy + anatomy = instance.context.data["anatomy"] # get time related data from instance (or context) time_data = get_time_data_from_instance_or_context(instance) @@ -1005,7 +1001,7 @@ def copy_extend_frames(instance, representation): start = instance.data.get("frameStart") end = instance.data.get("frameEnd") project_name = instance.context.data["project"] - anatomy = instance.context.data["anatomy"] # type: Anatomy + anatomy = instance.context.data["anatomy"] folder_entity = ayon_api.get_folder_by_path( project_name, instance.data.get("folderPath") From 87f4336aca4f01d6f212e489d424449f6b987bdf Mon Sep 17 00:00:00 2001 From: Jakub Trllo <43494761+iLLiCiTiT@users.noreply.github.com> Date: Wed, 10 Apr 2024 11:11:47 +0200 Subject: [PATCH 34/92] fix typehint import in deadline settings --- server_addon/deadline/server/settings/main.py | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/server_addon/deadline/server/settings/main.py b/server_addon/deadline/server/settings/main.py index 9537d6d550..83c7567c0d 100644 --- a/server_addon/deadline/server/settings/main.py +++ b/server_addon/deadline/server/settings/main.py @@ -1,3 +1,4 @@ +from typing import TYPE_CHECKING from pydantic import validator from ayon_server.settings import ( @@ -5,6 +6,8 @@ from ayon_server.settings import ( SettingsField, ensure_unique_names, ) +if TYPE_CHECKING: + from ayon_server.addons import BaseServerAddon from .publish_plugins import ( PublishPluginsModel, @@ -19,7 +22,7 @@ class ServerListSubmodel(BaseSettingsModel): async def defined_deadline_ws_name_enum_resolver( - addon: "BaseServerAddon", + addon: BaseServerAddon, settings_variant: str = "production", project_name: str | None = None, ) -> list[str]: From 0bf6be0fc42a600d37341ecf901e49a2b8888001 Mon Sep 17 00:00:00 2001 From: Jakub Trllo <43494761+iLLiCiTiT@users.noreply.github.com> Date: Wed, 10 Apr 2024 11:12:36 +0200 Subject: [PATCH 35/92] better import in fusion --- client/ayon_core/hosts/fusion/api/lib.py | 9 +++------ 1 file changed, 3 insertions(+), 6 deletions(-) diff --git a/client/ayon_core/hosts/fusion/api/lib.py b/client/ayon_core/hosts/fusion/api/lib.py index 03a1eeeb65..08722463e1 100644 --- a/client/ayon_core/hosts/fusion/api/lib.py +++ b/client/ayon_core/hosts/fusion/api/lib.py @@ -3,8 +3,8 @@ import sys import re import contextlib -from ayon_core.lib import Logger - +from ayon_core.lib import Logger, BoolDef, UILabelDef +from ayon_core.style import load_stylesheet from ayon_core.pipeline import registered_host from ayon_core.pipeline.create import CreateContext from ayon_core.pipeline.context_tools import get_current_folder_entity @@ -181,7 +181,6 @@ def validate_comp_prefs(comp=None, force_repair=False): from . import menu from ayon_core.tools.utils import SimplePopup - from ayon_core.style import load_stylesheet dialog = SimplePopup(parent=menu.menu) dialog.setWindowTitle("Fusion comp has invalid configuration") @@ -340,9 +339,7 @@ def prompt_reset_context(): from ayon_core.tools.attribute_defs.dialog import ( AttributeDefinitionsDialog ) - from ayon_core.style import load_stylesheet - from ayon_core.lib import BoolDef, UILabelDef - from qtpy import QtWidgets, QtCore + from qtpy import QtCore definitions = [ UILabelDef( From 1a1826dbbf10a13cd87858d7affa07b8769cf72f Mon Sep 17 00:00:00 2001 From: Jakub Trllo <43494761+iLLiCiTiT@users.noreply.github.com> Date: Wed, 10 Apr 2024 11:18:28 +0200 Subject: [PATCH 36/92] fix filename formatting in workflie load plugin --- client/ayon_core/hosts/tvpaint/plugins/load/load_workfile.py | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/client/ayon_core/hosts/tvpaint/plugins/load/load_workfile.py b/client/ayon_core/hosts/tvpaint/plugins/load/load_workfile.py index 8663dac997..2ad81cabcd 100644 --- a/client/ayon_core/hosts/tvpaint/plugins/load/load_workfile.py +++ b/client/ayon_core/hosts/tvpaint/plugins/load/load_workfile.py @@ -1,6 +1,5 @@ import os -from ayon_core.lib import StringTemplate from ayon_core.pipeline import ( registered_host, get_current_context, @@ -111,8 +110,6 @@ class LoadWorkfile(plugin.Loader): data["version"] = version - filename = StringTemplate.format_strict_template( - file_template, data - ) + filename = work_template["file"].format_strict(data) path = os.path.join(work_root, filename) host.save_workfile(path) From e69ac72a7520352d03424de0e2ed1a57304116bf Mon Sep 17 00:00:00 2001 From: Jakub Trllo <43494761+iLLiCiTiT@users.noreply.github.com> Date: Wed, 10 Apr 2024 11:19:08 +0200 Subject: [PATCH 37/92] fix used variable in blender load layout plugin --- client/ayon_core/hosts/blender/plugins/load/load_layout_json.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/client/ayon_core/hosts/blender/plugins/load/load_layout_json.py b/client/ayon_core/hosts/blender/plugins/load/load_layout_json.py index 7a3da1882e..f5d3aed084 100644 --- a/client/ayon_core/hosts/blender/plugins/load/load_layout_json.py +++ b/client/ayon_core/hosts/blender/plugins/load/load_layout_json.py @@ -167,7 +167,7 @@ class JsonLayoutLoader(plugin.AssetLoader): asset_group.empty_display_type = 'SINGLE_ARROW' avalon_container.objects.link(asset_group) - self._process(libpath, asset, asset_group, None) + self._process(libpath, asset_name, asset_group, None) bpy.context.scene.collection.objects.link(asset_group) From 09e1779586f5cee1c12af1702b3c5cb07dd9c03d Mon Sep 17 00:00:00 2001 From: Jakub Trllo <43494761+iLLiCiTiT@users.noreply.github.com> Date: Wed, 10 Apr 2024 11:19:43 +0200 Subject: [PATCH 38/92] use correct variable for product name --- .../hosts/hiero/plugins/publish/precollect_instances.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/client/ayon_core/hosts/hiero/plugins/publish/precollect_instances.py b/client/ayon_core/hosts/hiero/plugins/publish/precollect_instances.py index 67e1f18cbf..17a5e00bfd 100644 --- a/client/ayon_core/hosts/hiero/plugins/publish/precollect_instances.py +++ b/client/ayon_core/hosts/hiero/plugins/publish/precollect_instances.py @@ -293,7 +293,7 @@ class PrecollectInstances(pyblish.api.ContextPlugin): label += " {}".format(product_name) data.update({ - "name": "{}_{}".format(folder_path, subset), + "name": "{}_{}".format(folder_path, product_name), "label": label, "productName": product_name, "productType": product_type, From 978604f34c1d393502635b2ef92d03800740e986 Mon Sep 17 00:00:00 2001 From: Jakub Trllo <43494761+iLLiCiTiT@users.noreply.github.com> Date: Wed, 10 Apr 2024 11:20:07 +0200 Subject: [PATCH 39/92] remove duplicated code --- .../hosts/hiero/plugins/publish/precollect_instances.py | 4 ---- 1 file changed, 4 deletions(-) diff --git a/client/ayon_core/hosts/hiero/plugins/publish/precollect_instances.py b/client/ayon_core/hosts/hiero/plugins/publish/precollect_instances.py index 17a5e00bfd..b7a508f0b5 100644 --- a/client/ayon_core/hosts/hiero/plugins/publish/precollect_instances.py +++ b/client/ayon_core/hosts/hiero/plugins/publish/precollect_instances.py @@ -92,10 +92,6 @@ class PrecollectInstances(pyblish.api.ContextPlugin): folder_path, folder_name = self._get_folder_data(tag_data) - product_name = tag_data.get("productName") - if product_name is None: - product_name = tag_data["subset"] - families = [str(f) for f in tag_data["families"]] # TODO: remove backward compatibility From a782d4bc1982e063b30d1795a17c09d4f594dd32 Mon Sep 17 00:00:00 2001 From: Jakub Trllo <43494761+iLLiCiTiT@users.noreply.github.com> Date: Wed, 10 Apr 2024 11:24:16 +0200 Subject: [PATCH 40/92] added constants to __all__ --- .../ayon_core/addons/applications/ayon_applications/__init__.py | 1 + client/ayon_core/hosts/unreal/api/__init__.py | 2 ++ 2 files changed, 3 insertions(+) diff --git a/client/ayon_core/addons/applications/ayon_applications/__init__.py b/client/ayon_core/addons/applications/ayon_applications/__init__.py index b4a50279ab..c9b72f9914 100644 --- a/client/ayon_core/addons/applications/ayon_applications/__init__.py +++ b/client/ayon_core/addons/applications/ayon_applications/__init__.py @@ -31,6 +31,7 @@ from .addon import ApplicationsAddon __all__ = ( + "APPLICATIONS_ADDON_ROOT", "DEFAULT_ENV_SUBGROUP", "PLATFORM_NAMES", diff --git a/client/ayon_core/hosts/unreal/api/__init__.py b/client/ayon_core/hosts/unreal/api/__init__.py index ac6a91eae9..defad8b3c9 100644 --- a/client/ayon_core/hosts/unreal/api/__init__.py +++ b/client/ayon_core/hosts/unreal/api/__init__.py @@ -30,6 +30,8 @@ from .pipeline import ( __all__ = [ "install", "uninstall", + "UnrealActorCreator", + "UnrealAssetCreator", "Loader", "ls", "publish", From ebfcd364cd51876339d7e99498fd77b506fdb5ba Mon Sep 17 00:00:00 2001 From: Jakub Trllo <43494761+iLLiCiTiT@users.noreply.github.com> Date: Wed, 10 Apr 2024 11:24:33 +0200 Subject: [PATCH 41/92] don't use single char variable --- .../ayon_core/tools/utils/color_widgets/color_inputs.py | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/client/ayon_core/tools/utils/color_widgets/color_inputs.py b/client/ayon_core/tools/utils/color_widgets/color_inputs.py index 9c8e7b92e8..795b80fc1e 100644 --- a/client/ayon_core/tools/utils/color_widgets/color_inputs.py +++ b/client/ayon_core/tools/utils/color_widgets/color_inputs.py @@ -562,11 +562,11 @@ class HSLInputs(QtWidgets.QWidget): return self._block_changes = True - h, s, l, _ = self.color.getHsl() + hue, sat, lum, _ = self.color.getHsl() - self.input_hue.setValue(h) - self.input_sat.setValue(s) - self.input_light.setValue(l) + self.input_hue.setValue(hue) + self.input_sat.setValue(sat) + self.input_light.setValue(lum) self._block_changes = False From d1243d74e34ff18e2f5baec764a53ec0b88d4e93 Mon Sep 17 00:00:00 2001 From: Jakub Trllo <43494761+iLLiCiTiT@users.noreply.github.com> Date: Wed, 10 Apr 2024 11:24:41 +0200 Subject: [PATCH 42/92] define function instead of lambda --- client/ayon_core/tools/utils/widgets.py | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/client/ayon_core/tools/utils/widgets.py b/client/ayon_core/tools/utils/widgets.py index 1d4f85246f..21cab5d682 100644 --- a/client/ayon_core/tools/utils/widgets.py +++ b/client/ayon_core/tools/utils/widgets.py @@ -578,7 +578,8 @@ class OptionalAction(QtWidgets.QWidgetAction): def set_option_tip(self, options): sep = "\n\n" if not options or not isinstance(options[0], AbstractAttrDef): - mak = (lambda opt: opt["name"] + " :\n " + opt["help"]) + def mak(opt): + return opt["name"] + " :\n " + opt["help"] self.option_tip = sep.join(mak(opt) for opt in options) return From 9cb8b3b84ca1cfc7be8aecb54852ccb55fd7ae2c Mon Sep 17 00:00:00 2001 From: Jakub Trllo <43494761+iLLiCiTiT@users.noreply.github.com> Date: Wed, 10 Apr 2024 11:24:55 +0200 Subject: [PATCH 43/92] comment out example implementation --- client/ayon_core/tools/publisher/control_qt.py | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/client/ayon_core/tools/publisher/control_qt.py b/client/ayon_core/tools/publisher/control_qt.py index ee08899cac..bef3a5af3b 100644 --- a/client/ayon_core/tools/publisher/control_qt.py +++ b/client/ayon_core/tools/publisher/control_qt.py @@ -343,8 +343,9 @@ class QtRemotePublishController(BasePublisherController): @abstractmethod def _send_instance_changes_to_client(self): - instance_changes = self._get_instance_changes_for_client() - # Implement to send 'instance_changes' value to client + # TODO Implement to send 'instance_changes' value to client + # instance_changes = self._get_instance_changes_for_client() + pass @abstractmethod def save_changes(self): From 2f9834ba3bbb68828a01851ea99599b3d6ca1719 Mon Sep 17 00:00:00 2001 From: Jakub Trllo <43494761+iLLiCiTiT@users.noreply.github.com> Date: Wed, 10 Apr 2024 11:25:05 +0200 Subject: [PATCH 44/92] removed duplicated methods in slates --- client/ayon_core/scripts/slates/slate_base/base.py | 14 -------------- 1 file changed, 14 deletions(-) diff --git a/client/ayon_core/scripts/slates/slate_base/base.py b/client/ayon_core/scripts/slates/slate_base/base.py index 35ef46769c..e1648c916a 100644 --- a/client/ayon_core/scripts/slates/slate_base/base.py +++ b/client/ayon_core/scripts/slates/slate_base/base.py @@ -82,20 +82,6 @@ class BaseObj: def main_style(self): return load_default_style() - def height(self): - raise NotImplementedError( - "Attribute `height` is not implemented for <{}>".format( - self.__clas__.__name__ - ) - ) - - def width(self): - raise NotImplementedError( - "Attribute `width` is not implemented for <{}>".format( - self.__clas__.__name__ - ) - ) - def collect_data(self): return None From 40c41f82ece7331020a185166d1437a16045b3c9 Mon Sep 17 00:00:00 2001 From: Jakub Trllo <43494761+iLLiCiTiT@users.noreply.github.com> Date: Wed, 10 Apr 2024 11:25:18 +0200 Subject: [PATCH 45/92] ignore unused import in loader action --- client/ayon_core/modules/loader_action.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/client/ayon_core/modules/loader_action.py b/client/ayon_core/modules/loader_action.py index a0cc417b66..1e45db05dc 100644 --- a/client/ayon_core/modules/loader_action.py +++ b/client/ayon_core/modules/loader_action.py @@ -13,7 +13,7 @@ class LoaderAddon(AYONAddon, ITrayAddon): # Add library tool self._loader_imported = False try: - from ayon_core.tools.loader.ui import LoaderWindow + from ayon_core.tools.loader.ui import LoaderWindow # noqa F401 self._loader_imported = True except Exception: From 55b60fc7e224fb1d27c24d31482ed94939899eec Mon Sep 17 00:00:00 2001 From: Jakub Trllo <43494761+iLLiCiTiT@users.noreply.github.com> Date: Wed, 10 Apr 2024 11:25:33 +0200 Subject: [PATCH 46/92] do not store output to unused variable --- .../hosts/traypublisher/plugins/create/create_editorial.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/client/ayon_core/hosts/traypublisher/plugins/create/create_editorial.py b/client/ayon_core/hosts/traypublisher/plugins/create/create_editorial.py index 843729786c..4057aee9a6 100644 --- a/client/ayon_core/hosts/traypublisher/plugins/create/create_editorial.py +++ b/client/ayon_core/hosts/traypublisher/plugins/create/create_editorial.py @@ -402,7 +402,7 @@ or updating already created. Publishing will create OTIO file. ): continue - instance = self._make_product_instance( + self._make_product_instance( otio_clip, product_type_preset, deepcopy(base_instance_data), From 7c994ee1f0d0c87784d40e0f3b1f1ef157ff51cd Mon Sep 17 00:00:00 2001 From: Jakub Trllo <43494761+iLLiCiTiT@users.noreply.github.com> Date: Wed, 10 Apr 2024 11:25:45 +0200 Subject: [PATCH 47/92] ignore unused variable in tray --- client/ayon_core/tools/tray/tray.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/client/ayon_core/tools/tray/tray.py b/client/ayon_core/tools/tray/tray.py index 3c6c529be8..957518afe4 100644 --- a/client/ayon_core/tools/tray/tray.py +++ b/client/ayon_core/tools/tray/tray.py @@ -552,7 +552,7 @@ class TrayStarter(QtCore.QObject): def main(): app = get_ayon_qt_app() - starter = TrayStarter(app) + starter = TrayStarter(app) # noqa F841 if not is_running_from_build() and os.name == "nt": import ctypes From 400e30f160b1190889cc61b712286cc45f95939c Mon Sep 17 00:00:00 2001 From: Jakub Trllo <43494761+iLLiCiTiT@users.noreply.github.com> Date: Wed, 10 Apr 2024 11:29:02 +0200 Subject: [PATCH 48/92] fix variable used in anatomy to work with site sync --- client/ayon_core/pipeline/anatomy/anatomy.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/client/ayon_core/pipeline/anatomy/anatomy.py b/client/ayon_core/pipeline/anatomy/anatomy.py index 73dd215233..2aa8eeddbc 100644 --- a/client/ayon_core/pipeline/anatomy/anatomy.py +++ b/client/ayon_core/pipeline/anatomy/anatomy.py @@ -549,7 +549,7 @@ class Anatomy(BaseAnatomy): ) else: # Ask sync server to get roots overrides - roots_overrides = sitesync.get_site_root_overrides( + roots_overrides = sitesync_addon.get_site_root_overrides( project_name, site_name ) site_cache.update_data(roots_overrides) From eb5258012f5f30306e4afb36bcfdec8a366e595e Mon Sep 17 00:00:00 2001 From: Jakub Trllo <43494761+iLLiCiTiT@users.noreply.github.com> Date: Wed, 10 Apr 2024 11:34:30 +0200 Subject: [PATCH 49/92] added list of files to exclude from linting --- pyproject.toml | 14 ++++++++++++++ 1 file changed, 14 insertions(+) diff --git a/pyproject.toml b/pyproject.toml index 3c9ff4ea0a..29733983e8 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -77,6 +77,20 @@ unfixable = [] # Allow unused variables when underscore-prefixed. dummy-variable-rgx = "^(_+|(_+[a-zA-Z0-9_]*[a-zA-Z0-9]+?))$" +exclude = [ + "client/ayon_core/hosts/unreal/integration/*", + "client/ayon_core/hosts/aftereffects/api/extension/js/libs/*", + "client/ayon_core/hosts/hiero/api/startup/*", + "client/ayon_core/modules/deadline/repository/custom/plugins/CelAction/*", + "client/ayon_core/modules/deadline/repository/custom/plugins/HarmonyAYON/*", + "client/ayon_core/modules/click_wrap.py", + "client/ayon_core/scripts/slates/__init__.py" +] + +[tool.ruff.lint.per-file-ignores] +"client/ayon_core/lib/__init__.py" = ["E402"] +"client/ayon_core/hosts/max/startup/startup.py" = ["E402"] + [tool.ruff.format] # Like Black, use double quotes for strings. quote-style = "double" From 6366998d57b1914e1552923edc8ad9ef97fdc2b3 Mon Sep 17 00:00:00 2001 From: Jakub Trllo <43494761+iLLiCiTiT@users.noreply.github.com> Date: Wed, 10 Apr 2024 12:02:12 +0200 Subject: [PATCH 50/92] change order to match imports order Co-authored-by: Roy Nieterau --- client/ayon_core/hosts/unreal/api/__init__.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/client/ayon_core/hosts/unreal/api/__init__.py b/client/ayon_core/hosts/unreal/api/__init__.py index defad8b3c9..7e7f839f27 100644 --- a/client/ayon_core/hosts/unreal/api/__init__.py +++ b/client/ayon_core/hosts/unreal/api/__init__.py @@ -28,11 +28,11 @@ from .pipeline import ( ) __all__ = [ - "install", - "uninstall", "UnrealActorCreator", "UnrealAssetCreator", "Loader", + "install", + "uninstall", "ls", "publish", "containerise", From acdafb0a90563ffe4056beeda6ede5bbff33306b Mon Sep 17 00:00:00 2001 From: Jakub Trllo <43494761+iLLiCiTiT@users.noreply.github.com> Date: Wed, 10 Apr 2024 13:50:53 +0200 Subject: [PATCH 51/92] removed unused 'win32api' import --- client/ayon_core/hosts/blender/hooks/pre_pyside_install.py | 1 - client/ayon_core/hosts/fusion/hooks/pre_pyside_install.py | 1 - 2 files changed, 2 deletions(-) diff --git a/client/ayon_core/hosts/blender/hooks/pre_pyside_install.py b/client/ayon_core/hosts/blender/hooks/pre_pyside_install.py index 8f46eea0de..de397d6542 100644 --- a/client/ayon_core/hosts/blender/hooks/pre_pyside_install.py +++ b/client/ayon_core/hosts/blender/hooks/pre_pyside_install.py @@ -139,7 +139,6 @@ class InstallPySideToBlender(PreLaunchHook): administration rights. """ try: - import win32api import win32con import win32process import win32event diff --git a/client/ayon_core/hosts/fusion/hooks/pre_pyside_install.py b/client/ayon_core/hosts/fusion/hooks/pre_pyside_install.py index ab12078c43..4678d5bac7 100644 --- a/client/ayon_core/hosts/fusion/hooks/pre_pyside_install.py +++ b/client/ayon_core/hosts/fusion/hooks/pre_pyside_install.py @@ -85,7 +85,6 @@ class InstallPySideToFusion(PreLaunchHook): administration rights. """ try: - import win32api import win32con import win32process import win32event From ca704a81266975a3026c90d1a76f44bf43e1e6c8 Mon Sep 17 00:00:00 2001 From: Jakub Trllo <43494761+iLLiCiTiT@users.noreply.github.com> Date: Wed, 10 Apr 2024 14:19:25 +0200 Subject: [PATCH 52/92] define qt binding based on blender version --- .../hosts/blender/hooks/pre_pyside_install.py | 11 +++++++++-- 1 file changed, 9 insertions(+), 2 deletions(-) diff --git a/client/ayon_core/hosts/blender/hooks/pre_pyside_install.py b/client/ayon_core/hosts/blender/hooks/pre_pyside_install.py index 8f46eea0de..b0ace518c9 100644 --- a/client/ayon_core/hosts/blender/hooks/pre_pyside_install.py +++ b/client/ayon_core/hosts/blender/hooks/pre_pyside_install.py @@ -31,7 +31,7 @@ class InstallPySideToBlender(PreLaunchHook): def inner_execute(self): # Get blender's python directory - version_regex = re.compile(r"^[2-4]\.[0-9]+$") + version_regex = re.compile(r"^([2-4])\.[0-9]+$") platform = system().lower() executable = self.launch_context.executable.executable_path @@ -42,7 +42,8 @@ class InstallPySideToBlender(PreLaunchHook): if os.path.basename(executable).lower() != expected_executable: self.log.info(( f"Executable does not lead to {expected_executable} file." - "Can't determine blender's python to check/install PySide2." + "Can't determine blender's python to check/install" + " Qt binding." )) return @@ -73,6 +74,12 @@ class InstallPySideToBlender(PreLaunchHook): return version_subfolder = version_subfolders[0] + before_blender_4 = False + if int(version_regex.match(version_subfolder).group(1)) < 4: + before_blender_4 = True + # Blender 4 has Python 3.11 which does not support 'PySide2' + # QUESTION could we always install PySide6? + qt_binding = "PySide2" if before_blender_4 else "PySide6" python_dir = os.path.join(versions_dir, version_subfolder, "python") python_lib = os.path.join(python_dir, "lib") From ff6d207d442d4b9e3e8a447e00092511225b55d6 Mon Sep 17 00:00:00 2001 From: Jakub Trllo <43494761+iLLiCiTiT@users.noreply.github.com> Date: Wed, 10 Apr 2024 14:21:31 +0200 Subject: [PATCH 53/92] use the qt binding to be installed --- .../hosts/blender/hooks/pre_pyside_install.py | 36 ++++++++++++------- 1 file changed, 24 insertions(+), 12 deletions(-) diff --git a/client/ayon_core/hosts/blender/hooks/pre_pyside_install.py b/client/ayon_core/hosts/blender/hooks/pre_pyside_install.py index b0ace518c9..694080a324 100644 --- a/client/ayon_core/hosts/blender/hooks/pre_pyside_install.py +++ b/client/ayon_core/hosts/blender/hooks/pre_pyside_install.py @@ -123,22 +123,30 @@ class InstallPySideToBlender(PreLaunchHook): return # Check if PySide2 is installed and skip if yes - if self.is_pyside_installed(python_executable): + if self.is_pyside_installed(python_executable, qt_binding): self.log.debug("Blender has already installed PySide2.") return # Install PySide2 in blender's python if platform == "windows": - result = self.install_pyside_windows(python_executable) + result = self.install_pyside_windows( + python_executable, qt_binding + ) else: - result = self.install_pyside(python_executable) + result = self.install_pyside( + python_executable, qt_binding + ) if result: - self.log.info("Successfully installed PySide2 module to blender.") + self.log.info( + f"Successfully installed {qt_binding} module to blender." + ) else: - self.log.warning("Failed to install PySide2 module to blender.") + self.log.warning( + f"Failed to install {qt_binding} module to blender." + ) - def install_pyside_windows(self, python_executable): + def install_pyside_windows(self, python_executable, qt_binding): """Install PySide2 python module to blender's python. Installation requires administration rights that's why it is required @@ -162,7 +170,7 @@ class InstallPySideToBlender(PreLaunchHook): # - use "-m pip" as module pip to install PySide2 and argument # "--ignore-installed" is to force install module to blender's # site-packages and make sure it is binary compatible - parameters = "-m pip install --ignore-installed PySide2" + parameters = f"-m pip install --ignore-installed {qt_binding}" # Execute command and ask for administrator's rights process_info = ShellExecuteEx( @@ -180,20 +188,22 @@ class InstallPySideToBlender(PreLaunchHook): except pywintypes.error: pass - def install_pyside(self, python_executable): + def install_pyside(self, python_executable, qt_binding): """Install PySide2 python module to blender's python.""" try: # Parameters - # - use "-m pip" as module pip to install PySide2 and argument + # - use "-m pip" as module pip to install qt binding and argument # "--ignore-installed" is to force install module to blender's # site-packages and make sure it is binary compatible + # TODO find out if blender 4.x on linux/darwin does install + # qt binding to correct place. args = [ python_executable, "-m", "pip", "install", "--ignore-installed", - "PySide2", + qt_binding, ] process = subprocess.Popen( args, stdout=subprocess.PIPE, universal_newlines=True @@ -210,13 +220,15 @@ class InstallPySideToBlender(PreLaunchHook): except subprocess.SubprocessError: pass - def is_pyside_installed(self, python_executable): + def is_pyside_installed(self, python_executable, qt_binding): """Check if PySide2 module is in blender's pip list. Check that PySide2 is installed directly in blender's site-packages. It is possible that it is installed in user's site-packages but that may be incompatible with blender's python. """ + + qt_binding_low = qt_binding.lower() # Get pip list from blender's python executable args = [python_executable, "-m", "pip", "list"] process = subprocess.Popen(args, stdout=subprocess.PIPE) @@ -233,6 +245,6 @@ class InstallPySideToBlender(PreLaunchHook): if not line: continue package_name = line[0:package_len].strip() - if package_name.lower() == "pyside2": + if package_name.lower() == qt_binding_low: return True return False From 99160a8832652cba7fa552f2c6f6881281345f7b Mon Sep 17 00:00:00 2001 From: Jakub Trllo <43494761+iLLiCiTiT@users.noreply.github.com> Date: Wed, 10 Apr 2024 14:22:15 +0200 Subject: [PATCH 54/92] fix installation of qt binding for newer blender --- .../hosts/blender/hooks/pre_pyside_install.py | 30 +++++++++++++++++-- 1 file changed, 27 insertions(+), 3 deletions(-) diff --git a/client/ayon_core/hosts/blender/hooks/pre_pyside_install.py b/client/ayon_core/hosts/blender/hooks/pre_pyside_install.py index 694080a324..e03856c2e5 100644 --- a/client/ayon_core/hosts/blender/hooks/pre_pyside_install.py +++ b/client/ayon_core/hosts/blender/hooks/pre_pyside_install.py @@ -130,7 +130,7 @@ class InstallPySideToBlender(PreLaunchHook): # Install PySide2 in blender's python if platform == "windows": result = self.install_pyside_windows( - python_executable, qt_binding + python_executable, qt_binding, before_blender_4 ) else: result = self.install_pyside( @@ -146,7 +146,9 @@ class InstallPySideToBlender(PreLaunchHook): f"Failed to install {qt_binding} module to blender." ) - def install_pyside_windows(self, python_executable, qt_binding): + def install_pyside_windows( + self, python_executable, qt_binding, before_blender_4 + ): """Install PySide2 python module to blender's python. Installation requires administration rights that's why it is required @@ -170,7 +172,29 @@ class InstallPySideToBlender(PreLaunchHook): # - use "-m pip" as module pip to install PySide2 and argument # "--ignore-installed" is to force install module to blender's # site-packages and make sure it is binary compatible - parameters = f"-m pip install --ignore-installed {qt_binding}" + fake_exe = "fake.exe" + site_packages_prefix = os.path.dirname( + os.path.dirname(python_executable) + ) + args = [ + fake_exe, + "-m", + "pip", + "install", + "--ignore-installed", + qt_binding, + ] + if not before_blender_4: + # Define prefix for site package + # Python in blender 4.x is installing packages in AppData and + # not in blender's directory. + args.extend(["--prefix", site_packages_prefix]) + + parameters = ( + subprocess.list2cmdline(args) + .lstrip(fake_exe) + .lstrip(" ") + ) # Execute command and ask for administrator's rights process_info = ShellExecuteEx( From 066e18afe7fb784c0473b8837a9791f2a486bd7e Mon Sep 17 00:00:00 2001 From: Jakub Trllo <43494761+iLLiCiTiT@users.noreply.github.com> Date: Wed, 10 Apr 2024 14:22:24 +0200 Subject: [PATCH 55/92] do not set 'QT_PREFERRED_BINDING' for subprocess --- client/ayon_core/hosts/blender/addon.py | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/client/ayon_core/hosts/blender/addon.py b/client/ayon_core/hosts/blender/addon.py index b7484de243..6a4b325365 100644 --- a/client/ayon_core/hosts/blender/addon.py +++ b/client/ayon_core/hosts/blender/addon.py @@ -55,8 +55,7 @@ class BlenderAddon(AYONAddon, IHostAddon): ) # Define Qt binding if not defined - if not env.get("QT_PREFERRED_BINDING"): - env["QT_PREFERRED_BINDING"] = "PySide2" + env.pop("QT_PREFERRED_BINDING", None) def get_launch_hook_paths(self, app): if app.host_name != self.host_name: From 43a95bed75c8748673d3092260415ec93af0664d Mon Sep 17 00:00:00 2001 From: Jakub Trllo <43494761+iLLiCiTiT@users.noreply.github.com> Date: Wed, 10 Apr 2024 16:00:52 +0200 Subject: [PATCH 56/92] move client code of applications addon next to server codebase --- .../applications/client}/ayon_applications/__init__.py | 0 .../applications/client}/ayon_applications/addon.py | 0 .../applications/client}/ayon_applications/constants.py | 0 .../applications/client}/ayon_applications/defs.py | 0 .../applications/client}/ayon_applications/exceptions.py | 0 .../applications/client}/ayon_applications/hooks.py | 0 .../applications/client}/ayon_applications/manager.py | 0 .../client}/ayon_applications/plugins/publish/collect_app_name.py | 0 .../applications/client}/ayon_applications/utils.py | 0 9 files changed, 0 insertions(+), 0 deletions(-) rename {client/ayon_core/addons/applications => server_addon/applications/client}/ayon_applications/__init__.py (100%) rename {client/ayon_core/addons/applications => server_addon/applications/client}/ayon_applications/addon.py (100%) rename {client/ayon_core/addons/applications => server_addon/applications/client}/ayon_applications/constants.py (100%) rename {client/ayon_core/addons/applications => server_addon/applications/client}/ayon_applications/defs.py (100%) rename {client/ayon_core/addons/applications => server_addon/applications/client}/ayon_applications/exceptions.py (100%) rename {client/ayon_core/addons/applications => server_addon/applications/client}/ayon_applications/hooks.py (100%) rename {client/ayon_core/addons/applications => server_addon/applications/client}/ayon_applications/manager.py (100%) rename {client/ayon_core/addons/applications => server_addon/applications/client}/ayon_applications/plugins/publish/collect_app_name.py (100%) rename {client/ayon_core/addons/applications => server_addon/applications/client}/ayon_applications/utils.py (100%) diff --git a/client/ayon_core/addons/applications/ayon_applications/__init__.py b/server_addon/applications/client/ayon_applications/__init__.py similarity index 100% rename from client/ayon_core/addons/applications/ayon_applications/__init__.py rename to server_addon/applications/client/ayon_applications/__init__.py diff --git a/client/ayon_core/addons/applications/ayon_applications/addon.py b/server_addon/applications/client/ayon_applications/addon.py similarity index 100% rename from client/ayon_core/addons/applications/ayon_applications/addon.py rename to server_addon/applications/client/ayon_applications/addon.py diff --git a/client/ayon_core/addons/applications/ayon_applications/constants.py b/server_addon/applications/client/ayon_applications/constants.py similarity index 100% rename from client/ayon_core/addons/applications/ayon_applications/constants.py rename to server_addon/applications/client/ayon_applications/constants.py diff --git a/client/ayon_core/addons/applications/ayon_applications/defs.py b/server_addon/applications/client/ayon_applications/defs.py similarity index 100% rename from client/ayon_core/addons/applications/ayon_applications/defs.py rename to server_addon/applications/client/ayon_applications/defs.py diff --git a/client/ayon_core/addons/applications/ayon_applications/exceptions.py b/server_addon/applications/client/ayon_applications/exceptions.py similarity index 100% rename from client/ayon_core/addons/applications/ayon_applications/exceptions.py rename to server_addon/applications/client/ayon_applications/exceptions.py diff --git a/client/ayon_core/addons/applications/ayon_applications/hooks.py b/server_addon/applications/client/ayon_applications/hooks.py similarity index 100% rename from client/ayon_core/addons/applications/ayon_applications/hooks.py rename to server_addon/applications/client/ayon_applications/hooks.py diff --git a/client/ayon_core/addons/applications/ayon_applications/manager.py b/server_addon/applications/client/ayon_applications/manager.py similarity index 100% rename from client/ayon_core/addons/applications/ayon_applications/manager.py rename to server_addon/applications/client/ayon_applications/manager.py diff --git a/client/ayon_core/addons/applications/ayon_applications/plugins/publish/collect_app_name.py b/server_addon/applications/client/ayon_applications/plugins/publish/collect_app_name.py similarity index 100% rename from client/ayon_core/addons/applications/ayon_applications/plugins/publish/collect_app_name.py rename to server_addon/applications/client/ayon_applications/plugins/publish/collect_app_name.py diff --git a/client/ayon_core/addons/applications/ayon_applications/utils.py b/server_addon/applications/client/ayon_applications/utils.py similarity index 100% rename from client/ayon_core/addons/applications/ayon_applications/utils.py rename to server_addon/applications/client/ayon_applications/utils.py From a17381dcaea7e16c369bdecc2baf37f8bb04dcbd Mon Sep 17 00:00:00 2001 From: Jakub Trllo <43494761+iLLiCiTiT@users.noreply.github.com> Date: Wed, 10 Apr 2024 16:27:17 +0200 Subject: [PATCH 57/92] create ayon addons script can handle client code --- server_addon/create_ayon_addons.py | 46 ++++++++++++++++++++++++++++++ 1 file changed, 46 insertions(+) diff --git a/server_addon/create_ayon_addons.py b/server_addon/create_ayon_addons.py index c2686199be..fb6b46da88 100644 --- a/server_addon/create_ayon_addons.py +++ b/server_addon/create_ayon_addons.py @@ -44,6 +44,11 @@ version = "{addon_version}" plugin_for = ["ayon_server"] """ +CLIENT_VERSION_CONTENT = '''# -*- coding: utf-8 -*- +"""Package declaring AYON core addon version.""" +__version__ = "{}" +''' + class ZipFileLongPaths(zipfile.ZipFile): """Allows longer paths in zip files. @@ -175,6 +180,45 @@ def create_addon_zip( shutil.rmtree(str(output_dir / addon_name)) +def prepare_client_code( + addon_dir: Path, + addon_output_dir: Path, + addon_version: str +): + client_dir = addon_dir / "client" + if not client_dir.exists(): + return + + # Prepare private dir in output + private_dir = addon_output_dir / "private" + private_dir.mkdir(parents=True, exist_ok=True) + + # Copy pyproject toml if available + pyproject_toml = client_dir / "pyproject.toml" + if pyproject_toml.exists(): + shutil.copy(pyproject_toml, private_dir) + + for subpath in client_dir.iterdir(): + if subpath.name == "pyproject.toml": + continue + + if subpath.is_file(): + continue + + # Update version.py with server version if 'version.py' is available + version_path = subpath / "version.py" + if version_path.exists(): + with open(version_path, "w") as stream: + stream.write(CLIENT_VERSION_CONTENT.format(addon_version)) + + zip_filepath = private_dir / "client.zip" + with ZipFileLongPaths(zip_filepath, "w", zipfile.ZIP_DEFLATED) as zipf: + # Add client code content to zip + for path, sub_path in find_files_in_subdir(str(subpath)): + sub_path = os.path.join(subpath.name, sub_path) + zipf.write(path, sub_path) + + def create_addon_package( addon_dir: Path, output_dir: Path, @@ -205,6 +249,8 @@ def create_addon_package( server_dir, addon_output_dir / "server", dirs_exist_ok=True ) + prepare_client_code(addon_dir, addon_output_dir, addon_version) + if create_zip: create_addon_zip( output_dir, addon_dir.name, addon_version, keep_source From d498eb8e42ac83d3aa0bcc130227986a4e7fbced Mon Sep 17 00:00:00 2001 From: Jakub Trllo <43494761+iLLiCiTiT@users.noreply.github.com> Date: Wed, 10 Apr 2024 16:42:38 +0200 Subject: [PATCH 58/92] create pakcage.py only if is not available --- server_addon/create_ayon_addons.py | 46 +++++++++++++++++++++++------- 1 file changed, 36 insertions(+), 10 deletions(-) diff --git a/server_addon/create_ayon_addons.py b/server_addon/create_ayon_addons.py index fb6b46da88..2501faebe3 100644 --- a/server_addon/create_ayon_addons.py +++ b/server_addon/create_ayon_addons.py @@ -4,6 +4,8 @@ import re import shutil import argparse import zipfile +import types +import importlib import platform import collections from pathlib import Path @@ -219,13 +221,34 @@ def prepare_client_code( zipf.write(path, sub_path) +def import_filepath(path: Path, module_name: Optional[str] = None): + if not module_name: + module_name = os.path.splitext(path.name)[0] + + module = types.ModuleType(module_name) + module.__file__ = path + + # Use loader so module has full specs + module_loader = importlib.machinery.SourceFileLoader( + module_name, path + ) + module_loader.exec_module(module) + return module + + def create_addon_package( addon_dir: Path, output_dir: Path, create_zip: bool, keep_source: bool, ): - addon_version = get_addon_version(addon_dir) + src_package_py = addon_dir / "package.py" + package = None + if src_package_py.exists(): + package = import_filepath(src_package_py) + addon_version = package.version + else: + addon_version = get_addon_version(addon_dir) addon_output_dir = output_dir / addon_dir.name / addon_version if addon_output_dir.exists(): @@ -233,16 +256,19 @@ def create_addon_package( addon_output_dir.mkdir(parents=True) # Copy server content - package_py = addon_output_dir / "package.py" - addon_name = addon_dir.name - if addon_name == "royal_render": - addon_name = "royalrender" - package_py_content = PACKAGE_PY_TEMPLATE.format( - addon_name=addon_name, addon_version=addon_version - ) + dst_package_py = addon_output_dir / "package.py" + if package is not None: + shutil.copy(src_package_py, dst_package_py) + else: + addon_name = addon_dir.name + if addon_name == "royal_render": + addon_name = "royalrender" + package_py_content = PACKAGE_PY_TEMPLATE.format( + addon_name=addon_name, addon_version=addon_version + ) - with open(package_py, "w+") as pkg_py: - pkg_py.write(package_py_content) + with open(dst_package_py, "w+") as pkg_py: + pkg_py.write(package_py_content) server_dir = addon_dir / "server" shutil.copytree( From 10ba857abdebd6390ee1d406a36b97ad01be0057 Mon Sep 17 00:00:00 2001 From: Jakub Trllo <43494761+iLLiCiTiT@users.noreply.github.com> Date: Wed, 10 Apr 2024 16:42:49 +0200 Subject: [PATCH 59/92] applications addon has package.py --- server_addon/applications/package.py | 3 +++ server_addon/applications/server/__init__.py | 4 ---- server_addon/applications/server/version.py | 1 - 3 files changed, 3 insertions(+), 5 deletions(-) create mode 100644 server_addon/applications/package.py delete mode 100644 server_addon/applications/server/version.py diff --git a/server_addon/applications/package.py b/server_addon/applications/package.py new file mode 100644 index 0000000000..0380222a53 --- /dev/null +++ b/server_addon/applications/package.py @@ -0,0 +1,3 @@ +name = "applications" +title = "Applications" +version = "0.1.9" diff --git a/server_addon/applications/server/__init__.py b/server_addon/applications/server/__init__.py index 2668589cbe..d85678b77b 100644 --- a/server_addon/applications/server/__init__.py +++ b/server_addon/applications/server/__init__.py @@ -6,7 +6,6 @@ from ayon_server.addons import BaseServerAddon, AddonLibrary from ayon_server.entities.core import attribute_library from ayon_server.lib.postgres import Postgres -from .version import __version__ from .settings import ApplicationsAddonSettings, DEFAULT_VALUES try: @@ -87,9 +86,6 @@ def get_enum_items_from_groups(groups): class ApplicationsAddon(BaseServerAddon): - name = "applications" - title = "Applications" - version = __version__ settings_model = ApplicationsAddonSettings async def get_default_settings(self): diff --git a/server_addon/applications/server/version.py b/server_addon/applications/server/version.py deleted file mode 100644 index c11f861afb..0000000000 --- a/server_addon/applications/server/version.py +++ /dev/null @@ -1 +0,0 @@ -__version__ = "0.1.9" From cad45cee4c00ea92bfcda92687fda52f4eb1e29b Mon Sep 17 00:00:00 2001 From: Jakub Trllo <43494761+iLLiCiTiT@users.noreply.github.com> Date: Wed, 10 Apr 2024 17:37:52 +0200 Subject: [PATCH 60/92] check for correct first argument --- client/ayon_core/cli.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/client/ayon_core/cli.py b/client/ayon_core/cli.py index 80fbb57340..bd47dc1aac 100644 --- a/client/ayon_core/cli.py +++ b/client/ayon_core/cli.py @@ -176,9 +176,9 @@ def run(script): # future versions might remove it. first_arg = sys.argv[0] if is_running_from_build(): - comp_path = os.path.join(os.environ["AYON_ROOT"], "start.py") - else: comp_path = os.getenv("AYON_EXECUTABLE") + else: + comp_path = os.path.join(os.environ["AYON_ROOT"], "start.py") # Compare paths and remove first argument if it is the same as AYON if Path(first_arg).resolve() == Path(comp_path).resolve(): sys.argv.pop(0) From 409c8ef88510cf2dc7f726c242adeac7918e08c5 Mon Sep 17 00:00:00 2001 From: Jakub Trllo <43494761+iLLiCiTiT@users.noreply.github.com> Date: Wed, 10 Apr 2024 18:29:24 +0200 Subject: [PATCH 61/92] bump applications addon version to '0.2.0' --- server_addon/applications/package.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/server_addon/applications/package.py b/server_addon/applications/package.py index 0380222a53..ce312ed662 100644 --- a/server_addon/applications/package.py +++ b/server_addon/applications/package.py @@ -1,3 +1,3 @@ name = "applications" title = "Applications" -version = "0.1.9" +version = "0.2.0" From ad7b558d186bcd5c27cef35c93c0f1e383ceadfc Mon Sep 17 00:00:00 2001 From: Jakub Trllo <43494761+iLLiCiTiT@users.noreply.github.com> Date: Wed, 10 Apr 2024 18:29:58 +0200 Subject: [PATCH 62/92] removed logic loading addons from 'addons' dir --- client/ayon_core/addon/base.py | 57 ---------------------------------- 1 file changed, 57 deletions(-) diff --git a/client/ayon_core/addon/base.py b/client/ayon_core/addon/base.py index 6ef838652e..8d0465db35 100644 --- a/client/ayon_core/addon/base.py +++ b/client/ayon_core/addon/base.py @@ -336,66 +336,9 @@ def _load_ayon_addons(openpype_modules, modules_key, log): return addons_to_skip_in_core -def _load_ayon_core_addons_dir( - ignore_addon_names, openpype_modules, modules_key, log -): - addons_dir = os.path.join(AYON_CORE_ROOT, "addons") - if not os.path.exists(addons_dir): - return - - imported_modules = [] - - # Make sure that addons which already have client code are not loaded - # from core again, with older code - filtered_paths = [] - for name in os.listdir(addons_dir): - if name in ignore_addon_names: - continue - path = os.path.join(addons_dir, name) - if os.path.isdir(path): - filtered_paths.append(path) - - for path in filtered_paths: - while path in sys.path: - sys.path.remove(path) - sys.path.insert(0, path) - - for name in os.listdir(path): - fullpath = os.path.join(path, name) - if os.path.isfile(fullpath): - basename, ext = os.path.splitext(name) - if ext != ".py": - continue - else: - basename = name - try: - module = __import__(basename, fromlist=("",)) - for attr_name in dir(module): - attr = getattr(module, attr_name) - if ( - inspect.isclass(attr) - and issubclass(attr, AYONAddon) - ): - new_import_str = "{}.{}".format(modules_key, basename) - sys.modules[new_import_str] = module - setattr(openpype_modules, basename, module) - imported_modules.append(module) - break - - except Exception: - log.error( - "Failed to import addon '{}'.".format(fullpath), - exc_info=True - ) - return imported_modules - - def _load_addons_in_core( ignore_addon_names, openpype_modules, modules_key, log ): - _load_ayon_core_addons_dir( - ignore_addon_names, openpype_modules, modules_key, log - ) # Add current directory at first place # - has small differences in import logic hosts_dir = os.path.join(AYON_CORE_ROOT, "hosts") From 4fa9cab65bc7a159ca1581340c89c9e9400f2bf1 Mon Sep 17 00:00:00 2001 From: Jakub Trllo <43494761+iLLiCiTiT@users.noreply.github.com> Date: Wed, 10 Apr 2024 18:32:23 +0200 Subject: [PATCH 63/92] implemented milestone versions so we can log that addon version is too old to be compatible with ayon core --- client/ayon_core/addon/base.py | 56 ++++++++++++++++++++++++++++++++++ 1 file changed, 56 insertions(+) diff --git a/client/ayon_core/addon/base.py b/client/ayon_core/addon/base.py index 8d0465db35..3d028dba07 100644 --- a/client/ayon_core/addon/base.py +++ b/client/ayon_core/addon/base.py @@ -15,6 +15,7 @@ from abc import ABCMeta, abstractmethod import six import appdirs import ayon_api +from semver import VersionInfo from ayon_core import AYON_CORE_ROOT from ayon_core.lib import Logger, is_dev_mode_enabled @@ -46,6 +47,11 @@ IGNORED_HOSTS_IN_AYON = { } IGNORED_MODULES_IN_AYON = set() +# When addon was moved from ayon-core codebase +# - this is used to log the missing addon +MOVED_ADDON_MILESTONE_VERSIONS = { + "applications": VersionInfo(2, 0, 0), +} # Inherit from `object` for Python 2 hosts class _ModuleClass(object): @@ -192,6 +198,45 @@ def _get_ayon_addons_information(bundle_info): return output +def _handle_moved_addons(addon_name, milestone_version, log): + """Log message that addon version is not compatible with current core. + + The function can return path to addon client code, but that can happen + only if ayon-core is used from code (for development), but still + logs a warning. + + Args: + addon_name (str): Addon name. + milestone_version (str): Milestone addon version. + log (logging.Logger): Logger object. + + Returns: + Union[str, None]: Addon dir or None. + """ + # Handle addons which were moved out of ayon-core + # - Try to fix it by loading it directly from server addons dir in + # ayon-core repository. But that will work only if ayon-core is + # used from code. + addon_dir = os.path.join( + os.path.dirname(os.path.dirname(AYON_CORE_ROOT)), + "server_addon", + addon_name, + "client", + ) + if not os.path.exists(addon_dir): + log.error(( + "Addon '{}' is not be available." + " Please update applications addon to '{}' or higher." + ).format(addon_name, milestone_version)) + return None + + log.warning(( + "Please update '{}' addon to '{}' or higher." + " Using client code from ayon-core repository." + ).format(addon_name, milestone_version)) + return addon_dir + + def _load_ayon_addons(openpype_modules, modules_key, log): """Load AYON addons based on information from server. @@ -249,6 +294,7 @@ def _load_ayon_addons(openpype_modules, modules_key, log): use_dev_path = dev_addon_info.get("enabled", False) addon_dir = None + milestone_version = MOVED_ADDON_MILESTONE_VERSIONS.get(addon_name) if use_dev_path: addon_dir = dev_addon_info["path"] if not addon_dir or not os.path.exists(addon_dir): @@ -257,6 +303,16 @@ def _load_ayon_addons(openpype_modules, modules_key, log): ).format(addon_name, addon_version, addon_dir)) continue + elif ( + milestone_version is not None + and VersionInfo.parse(addon_version) < milestone_version + ): + addon_dir = _handle_moved_addons( + addon_name, milestone_version, log + ) + if not addon_dir: + continue + elif addons_dir_exists: folder_name = "{}_{}".format(addon_name, addon_version) addon_dir = os.path.join(addons_dir, folder_name) From 1d459d2be26ff4b73e13f1e64c89bdb5a050877a Mon Sep 17 00:00:00 2001 From: iLLiCiTiT Date: Wed, 10 Apr 2024 22:43:21 +0200 Subject: [PATCH 64/92] modified products model to get versions information once --- .../tools/loader/ui/products_model.py | 65 ++++++++++++++++--- 1 file changed, 56 insertions(+), 9 deletions(-) diff --git a/client/ayon_core/tools/loader/ui/products_model.py b/client/ayon_core/tools/loader/ui/products_model.py index 41342ba0df..b465679c3b 100644 --- a/client/ayon_core/tools/loader/ui/products_model.py +++ b/client/ayon_core/tools/loader/ui/products_model.py @@ -284,7 +284,13 @@ class ProductsModel(QtGui.QStandardItemModel): model_item.setData(label, QtCore.Qt.DisplayRole) return model_item - def _set_version_data_to_product_item(self, model_item, version_item): + def _set_version_data_to_product_item( + self, + model_item, + version_item, + repre_count_by_version_id=None, + sync_availability_by_version_id=None, + ): """ Args: @@ -292,6 +298,10 @@ class ProductsModel(QtGui.QStandardItemModel): from version item. version_item (VersionItem): Item from entities model with information about version. + repre_count_by_version_id (Optional[str, int]): Mapping of + representation count by version id. + sync_availability_by_version_id (Optional[str, Tuple[int, int]]): + Mapping of sync availability by version id. """ model_item.setData(version_item.version_id, VERSION_ID_ROLE) @@ -312,12 +322,20 @@ class ProductsModel(QtGui.QStandardItemModel): # TODO call site sync methods for all versions at once project_name = self._last_project_name version_id = version_item.version_id - repre_count = self._controller.get_versions_representation_count( - project_name, [version_id] - )[version_id] - active, remote = self._controller.get_version_sync_availability( - project_name, [version_id] - )[version_id] + if repre_count_by_version_id is None: + repre_count_by_version_id = ( + self._controller.get_versions_representation_count( + project_name, [version_id] + ) + ) + if sync_availability_by_version_id is None: + sync_availability_by_version_id = ( + self._controller.get_version_sync_availability( + project_name, [version_id] + ) + ) + repre_count = repre_count_by_version_id[version_id] + active, remote = sync_availability_by_version_id[version_id] model_item.setData(repre_count, REPRESENTATIONS_COUNT_ROLE) model_item.setData(active, SYNC_ACTIVE_SITE_AVAILABILITY) @@ -327,7 +345,9 @@ class ProductsModel(QtGui.QStandardItemModel): self, product_item, active_site_icon, - remote_site_icon + remote_site_icon, + repre_count_by_version_id, + sync_availability_by_version_id, ): model_item = self._items_by_id.get(product_item.product_id) versions = list(product_item.version_items.values()) @@ -357,7 +377,12 @@ class ProductsModel(QtGui.QStandardItemModel): model_item.setData(active_site_icon, ACTIVE_SITE_ICON_ROLE) model_item.setData(remote_site_icon, REMOTE_SITE_ICON_ROLE) - self._set_version_data_to_product_item(model_item, last_version) + self._set_version_data_to_product_item( + model_item, + last_version, + repre_count_by_version_id, + sync_availability_by_version_id, + ) return model_item def get_last_project_name(self): @@ -387,6 +412,24 @@ class ProductsModel(QtGui.QStandardItemModel): product_item.product_id: product_item for product_item in product_items } + last_version_id_by_product_id = {} + for product_item in product_items: + versions = list(product_item.version_items.values()) + versions.sort() + last_version = versions[-1] + last_version_id_by_product_id[product_item.product_id] = ( + last_version.version_id + ) + + version_ids = set(last_version_id_by_product_id.values()) + repre_count_by_version_id = self._controller.get_versions_representation_count( + project_name, version_ids + ) + sync_availability_by_version_id = ( + self._controller.get_version_sync_availability( + project_name, version_ids + ) + ) # Prepare product groups product_name_matches_by_group = collections.defaultdict(dict) @@ -443,6 +486,8 @@ class ProductsModel(QtGui.QStandardItemModel): product_item, active_site_icon, remote_site_icon, + repre_count_by_version_id, + sync_availability_by_version_id, ) new_items.append(item) @@ -463,6 +508,8 @@ class ProductsModel(QtGui.QStandardItemModel): product_item, active_site_icon, remote_site_icon, + repre_count_by_version_id, + sync_availability_by_version_id, ) new_merged_items.append(item) merged_product_types.add(product_item.product_type) From 93d0e28a639814d752317ad8d06d3b76d4a17cf7 Mon Sep 17 00:00:00 2001 From: Jakub Trllo <43494761+iLLiCiTiT@users.noreply.github.com> Date: Thu, 11 Apr 2024 10:10:55 +0200 Subject: [PATCH 65/92] make sure path is string --- server_addon/create_ayon_addons.py | 2 ++ 1 file changed, 2 insertions(+) diff --git a/server_addon/create_ayon_addons.py b/server_addon/create_ayon_addons.py index 2501faebe3..bfd601af07 100644 --- a/server_addon/create_ayon_addons.py +++ b/server_addon/create_ayon_addons.py @@ -225,6 +225,8 @@ def import_filepath(path: Path, module_name: Optional[str] = None): if not module_name: module_name = os.path.splitext(path.name)[0] + # Convert to string + path = str(path) module = types.ModuleType(module_name) module.__file__ = path From 065906a5ab69274f04aefdc140dc3b9a540d0254 Mon Sep 17 00:00:00 2001 From: Roy Nieterau Date: Thu, 11 Apr 2024 12:16:45 +0200 Subject: [PATCH 66/92] Fix 'reference node is not associated with a reference file' errors --- client/ayon_core/hosts/maya/api/lib.py | 19 +++++++++++++------ 1 file changed, 13 insertions(+), 6 deletions(-) diff --git a/client/ayon_core/hosts/maya/api/lib.py b/client/ayon_core/hosts/maya/api/lib.py index 2c6017148a..321bcbc0b5 100644 --- a/client/ayon_core/hosts/maya/api/lib.py +++ b/client/ayon_core/hosts/maya/api/lib.py @@ -4270,6 +4270,9 @@ def get_reference_node(members, log=None): if ref.rsplit(":", 1)[-1].startswith("_UNKNOWN_REF_NODE_"): continue + if not is_valid_reference_node(ref): + continue + references.add(ref) assert references, "No reference node found in container" @@ -4300,15 +4303,19 @@ def get_reference_node_parents(ref): list: The upstream parent reference nodes. """ - parent = cmds.referenceQuery(ref, - referenceNode=True, - parent=True) + def _get_parent(reference_node): + """Return parent reference node, but ignore invalid reference nodes""" + if not is_valid_reference_node(reference_node): + return + return cmds.referenceQuery(reference_node, + referenceNode=True, + parent=True) + + parent = _get_parent(ref) parents = [] while parent: parents.append(parent) - parent = cmds.referenceQuery(parent, - referenceNode=True, - parent=True) + parent = _get_parent(parent) return parents From f9a0b7a1ec62f42d9a96ed2524671e792195849f Mon Sep 17 00:00:00 2001 From: Roy Nieterau Date: Thu, 11 Apr 2024 12:58:47 +0200 Subject: [PATCH 67/92] Replace instances while preserving their `instance.id` and instance.data[`instance_id`] --- .../plugins/publish/collect_render.py | 11 ++---- .../fusion/plugins/publish/collect_render.py | 16 +++----- .../publish/abstract_collect_render.py | 15 +++++++- client/ayon_core/pipeline/publish/lib.py | 38 +++++++++++++++++++ 4 files changed, 60 insertions(+), 20 deletions(-) diff --git a/client/ayon_core/hosts/aftereffects/plugins/publish/collect_render.py b/client/ayon_core/hosts/aftereffects/plugins/publish/collect_render.py index 4134e9d593..46616a2d93 100644 --- a/client/ayon_core/hosts/aftereffects/plugins/publish/collect_render.py +++ b/client/ayon_core/hosts/aftereffects/plugins/publish/collect_render.py @@ -41,7 +41,6 @@ class CollectAERender(publish.AbstractCollectRender): def get_instances(self, context): instances = [] - instances_to_remove = [] app_version = CollectAERender.get_stub().get_app_version() app_version = app_version[0:4] @@ -117,7 +116,10 @@ class CollectAERender(publish.AbstractCollectRender): fps=fps, app_version=app_version, publish_attributes=inst.data.get("publish_attributes", {}), - file_names=[item.file_name for item in render_q] + file_names=[item.file_name for item in render_q], + + # The source instance this render instance replaces + source_instance=inst ) comp = compositions_by_id.get(comp_id) @@ -144,11 +146,6 @@ class CollectAERender(publish.AbstractCollectRender): # to skip ExtractReview locally instance.families.remove("review") - instances.append(instance) - instances_to_remove.append(inst) - - for instance in instances_to_remove: - context.remove(instance) return instances def get_expected_files(self, render_instance): diff --git a/client/ayon_core/hosts/fusion/plugins/publish/collect_render.py b/client/ayon_core/hosts/fusion/plugins/publish/collect_render.py index 36102d02cb..521a47675a 100644 --- a/client/ayon_core/hosts/fusion/plugins/publish/collect_render.py +++ b/client/ayon_core/hosts/fusion/plugins/publish/collect_render.py @@ -37,14 +37,13 @@ class CollectFusionRender( aspect_x = comp_frame_format_prefs["AspectX"] aspect_y = comp_frame_format_prefs["AspectY"] - instances = [] - instances_to_remove = [] current_file = context.data["currentFile"] version = context.data["version"] project_entity = context.data["projectEntity"] + instances = [] for inst in context: if not inst.data.get("active", True): continue @@ -91,7 +90,10 @@ class CollectFusionRender( frameStep=1, fps=comp_frame_format_prefs.get("Rate"), app_version=comp.GetApp().Version, - publish_attributes=inst.data.get("publish_attributes", {}) + publish_attributes=inst.data.get("publish_attributes", {}), + + # The source instance this render instance replaces + source_instance=inst ) render_target = inst.data["creator_attributes"]["render_target"] @@ -114,14 +116,6 @@ class CollectFusionRender( # to skip ExtractReview locally instance.families.remove("review") - # add new instance to the list and remove the original - # instance since it is not needed anymore - instances.append(instance) - instances_to_remove.append(inst) - - for instance in instances_to_remove: - context.remove(instance) - return instances def post_collecting_action(self): diff --git a/client/ayon_core/pipeline/publish/abstract_collect_render.py b/client/ayon_core/pipeline/publish/abstract_collect_render.py index 745632ca0a..1b482b1d5f 100644 --- a/client/ayon_core/pipeline/publish/abstract_collect_render.py +++ b/client/ayon_core/pipeline/publish/abstract_collect_render.py @@ -12,6 +12,7 @@ import six import pyblish.api from .publish_plugins import AbstractMetaContextPlugin +from .lib import replace_instance_in_context @attr.s @@ -81,6 +82,9 @@ class RenderInstance(object): outputDir = attr.ib(default=None) context = attr.ib(default=None) + # The source instance this render instance should replace in the context + source_instance = attr.ib(default=None, type=pyblish.api.Instance) + @frameStart.validator def check_frame_start(self, _, value): """Validate if frame start is not larger then end.""" @@ -214,8 +218,15 @@ class AbstractCollectRender(pyblish.api.ContextPlugin): data = self.add_additional_data(data) render_instance_dict = attr.asdict(render_instance) - instance = context.create_instance(render_instance.name) - instance.data["label"] = render_instance.label + instance = pyblish.api.Instance(render_instance.name, + parent=context) + if render_instance.source_instance: + replace_instance_in_context(context, + render_instance.source_instance, + instance) + else: + context.append(instance) + instance.data.update(render_instance_dict) instance.data.update(data) diff --git a/client/ayon_core/pipeline/publish/lib.py b/client/ayon_core/pipeline/publish/lib.py index 8d3644637b..63fb0feb0a 100644 --- a/client/ayon_core/pipeline/publish/lib.py +++ b/client/ayon_core/pipeline/publish/lib.py @@ -934,3 +934,41 @@ def get_publish_instance_families(instance): families.discard(family) output.extend(families) return output + + +def replace_instance_in_context( + context: pyblish.api.Context, + source_instance: pyblish.api.Instance, + destination_instance: pyblish.api.Instance +): + """Replace source instance with the destination instance. + + This transfers the instance's IDs so that the new instance acts exactly + as if it was the source instance the whole time. This is required for + the publisher to correctly detect and transfer the logs relevant for the + instance. + + Returns: + bool: Whether the source instance was replaced or the destination + instance was only added because source instance did not exist + in the context. + + """ + + # Transfer the pyblish.api.Instance id + destination_instance._id = source_instance.id + + # Transfer the `instance_id` of the new publisher's instances + key = "instance_id" + if key in source_instance.data: + destination_instance.data[key] = source_instance.data[key] + + # Replace the instance at the same index in the context + for i, instance in enumerate(context): + if source_instance is instance: + context[i] = destination_instance + return True + + # Source was not found + context.append(destination_instance) + return False From 56fd07a7848a4cb0c3ee5d16d60d84e39c4333e5 Mon Sep 17 00:00:00 2001 From: Roy Nieterau Date: Thu, 11 Apr 2024 13:14:24 +0200 Subject: [PATCH 68/92] Fix replacement --- client/ayon_core/pipeline/publish/abstract_collect_render.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/client/ayon_core/pipeline/publish/abstract_collect_render.py b/client/ayon_core/pipeline/publish/abstract_collect_render.py index 1b482b1d5f..01c2ed7537 100644 --- a/client/ayon_core/pipeline/publish/abstract_collect_render.py +++ b/client/ayon_core/pipeline/publish/abstract_collect_render.py @@ -220,7 +220,7 @@ class AbstractCollectRender(pyblish.api.ContextPlugin): instance = pyblish.api.Instance(render_instance.name, parent=context) - if render_instance.source_instance: + if render_instance.source_instance is not None: replace_instance_in_context(context, render_instance.source_instance, instance) From 6e812e00796c8f0a2cf3eedf5d5d00196d3984d2 Mon Sep 17 00:00:00 2001 From: Roy Nieterau Date: Thu, 11 Apr 2024 13:23:00 +0200 Subject: [PATCH 69/92] Fix replacement, and do not add new instance in context twice --- .../pipeline/publish/abstract_collect_render.py | 15 ++++++++------- 1 file changed, 8 insertions(+), 7 deletions(-) diff --git a/client/ayon_core/pipeline/publish/abstract_collect_render.py b/client/ayon_core/pipeline/publish/abstract_collect_render.py index 01c2ed7537..096f1c406e 100644 --- a/client/ayon_core/pipeline/publish/abstract_collect_render.py +++ b/client/ayon_core/pipeline/publish/abstract_collect_render.py @@ -218,14 +218,15 @@ class AbstractCollectRender(pyblish.api.ContextPlugin): data = self.add_additional_data(data) render_instance_dict = attr.asdict(render_instance) - instance = pyblish.api.Instance(render_instance.name, - parent=context) + instance = context.create_instance(render_instance.name) if render_instance.source_instance is not None: - replace_instance_in_context(context, - render_instance.source_instance, - instance) - else: - context.append(instance) + # remove the new instance, because we want to insert it + # at the position of the original instance + context.pop() + replace_instance_in_context( + context, + source_instance=render_instance.source_instance, + destination_instance=instance) instance.data.update(render_instance_dict) instance.data.update(data) From 5b85cc9ec3cafbe632eba90975acb0d4bde43c29 Mon Sep 17 00:00:00 2001 From: Roy Nieterau Date: Thu, 11 Apr 2024 13:23:41 +0200 Subject: [PATCH 70/92] Tweak comment --- client/ayon_core/pipeline/publish/abstract_collect_render.py | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/client/ayon_core/pipeline/publish/abstract_collect_render.py b/client/ayon_core/pipeline/publish/abstract_collect_render.py index 096f1c406e..a9d5b38ada 100644 --- a/client/ayon_core/pipeline/publish/abstract_collect_render.py +++ b/client/ayon_core/pipeline/publish/abstract_collect_render.py @@ -221,7 +221,8 @@ class AbstractCollectRender(pyblish.api.ContextPlugin): instance = context.create_instance(render_instance.name) if render_instance.source_instance is not None: # remove the new instance, because we want to insert it - # at the position of the original instance + # at the position of the original instance to replace the + # source instance in the context completely context.pop() replace_instance_in_context( context, From b3d9dabd62bd98455529ae4fa564c3e6de87379c Mon Sep 17 00:00:00 2001 From: Roy Nieterau Date: Thu, 11 Apr 2024 13:24:08 +0200 Subject: [PATCH 71/92] Fix returning the instances --- client/ayon_core/hosts/fusion/plugins/publish/collect_render.py | 2 ++ 1 file changed, 2 insertions(+) diff --git a/client/ayon_core/hosts/fusion/plugins/publish/collect_render.py b/client/ayon_core/hosts/fusion/plugins/publish/collect_render.py index 521a47675a..7a2844d5db 100644 --- a/client/ayon_core/hosts/fusion/plugins/publish/collect_render.py +++ b/client/ayon_core/hosts/fusion/plugins/publish/collect_render.py @@ -116,6 +116,8 @@ class CollectFusionRender( # to skip ExtractReview locally instance.families.remove("review") + instances.append(instance) + return instances def post_collecting_action(self): From 708fd64c793f41cb423ff7a139072e8f78d73abd Mon Sep 17 00:00:00 2001 From: Roy Nieterau Date: Thu, 11 Apr 2024 13:29:35 +0200 Subject: [PATCH 72/92] Fix instances - I need more coffee today --- .../hosts/aftereffects/plugins/publish/collect_render.py | 2 ++ 1 file changed, 2 insertions(+) diff --git a/client/ayon_core/hosts/aftereffects/plugins/publish/collect_render.py b/client/ayon_core/hosts/aftereffects/plugins/publish/collect_render.py index 46616a2d93..c28042b6ae 100644 --- a/client/ayon_core/hosts/aftereffects/plugins/publish/collect_render.py +++ b/client/ayon_core/hosts/aftereffects/plugins/publish/collect_render.py @@ -146,6 +146,8 @@ class CollectAERender(publish.AbstractCollectRender): # to skip ExtractReview locally instance.families.remove("review") + instances.append(instance) + return instances def get_expected_files(self, render_instance): From bcfd43b9f5b906f0bece12fc5667bf0bb0f5b45a Mon Sep 17 00:00:00 2001 From: Kayla Man Date: Thu, 11 Apr 2024 20:28:11 +0800 Subject: [PATCH 73/92] add 8k options into texture creator --- .../hosts/substancepainter/plugins/create/create_textures.py | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/client/ayon_core/hosts/substancepainter/plugins/create/create_textures.py b/client/ayon_core/hosts/substancepainter/plugins/create/create_textures.py index f204ff7728..f46afadb5a 100644 --- a/client/ayon_core/hosts/substancepainter/plugins/create/create_textures.py +++ b/client/ayon_core/hosts/substancepainter/plugins/create/create_textures.py @@ -144,7 +144,8 @@ class CreateTextures(Creator): 9: "512", 10: "1024", 11: "2048", - 12: "4096" + 12: "4096", + 13: "8192" }, default=None, label="Size"), From 19c655e1532236418b55d07fcb3b44386b8324a5 Mon Sep 17 00:00:00 2001 From: Roy Nieterau Date: Thu, 11 Apr 2024 14:38:28 +0200 Subject: [PATCH 74/92] Update client/ayon_core/pipeline/publish/lib.py Co-authored-by: Jakub Trllo <43494761+iLLiCiTiT@users.noreply.github.com> --- client/ayon_core/pipeline/publish/lib.py | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/client/ayon_core/pipeline/publish/lib.py b/client/ayon_core/pipeline/publish/lib.py index 63fb0feb0a..87d01e5b97 100644 --- a/client/ayon_core/pipeline/publish/lib.py +++ b/client/ayon_core/pipeline/publish/lib.py @@ -937,9 +937,9 @@ def get_publish_instance_families(instance): def replace_instance_in_context( - context: pyblish.api.Context, - source_instance: pyblish.api.Instance, - destination_instance: pyblish.api.Instance + context: pyblish.api.Context, + source_instance: pyblish.api.Instance, + destination_instance: pyblish.api.Instance ): """Replace source instance with the destination instance. From e1bd0ccf540f341905a11862b8b65ce03a94272a Mon Sep 17 00:00:00 2001 From: Roy Nieterau Date: Thu, 11 Apr 2024 14:38:33 +0200 Subject: [PATCH 75/92] Update client/ayon_core/pipeline/publish/lib.py Co-authored-by: Jakub Trllo <43494761+iLLiCiTiT@users.noreply.github.com> --- client/ayon_core/pipeline/publish/lib.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/client/ayon_core/pipeline/publish/lib.py b/client/ayon_core/pipeline/publish/lib.py index 87d01e5b97..2b97feebb3 100644 --- a/client/ayon_core/pipeline/publish/lib.py +++ b/client/ayon_core/pipeline/publish/lib.py @@ -964,9 +964,9 @@ def replace_instance_in_context( destination_instance.data[key] = source_instance.data[key] # Replace the instance at the same index in the context - for i, instance in enumerate(context): + for idx, instance in enumerate(context): if source_instance is instance: - context[i] = destination_instance + context[idx] = destination_instance return True # Source was not found From 25a54cbdca35380195a5998f3b2f34f4561a8c66 Mon Sep 17 00:00:00 2001 From: Roy Nieterau Date: Thu, 11 Apr 2024 14:38:38 +0200 Subject: [PATCH 76/92] Update client/ayon_core/pipeline/publish/lib.py Co-authored-by: Jakub Trllo <43494761+iLLiCiTiT@users.noreply.github.com> --- client/ayon_core/pipeline/publish/lib.py | 1 - 1 file changed, 1 deletion(-) diff --git a/client/ayon_core/pipeline/publish/lib.py b/client/ayon_core/pipeline/publish/lib.py index 2b97feebb3..ebdaca5518 100644 --- a/client/ayon_core/pipeline/publish/lib.py +++ b/client/ayon_core/pipeline/publish/lib.py @@ -954,7 +954,6 @@ def replace_instance_in_context( in the context. """ - # Transfer the pyblish.api.Instance id destination_instance._id = source_instance.id From e3cfb6800707eb906135feae6bf5c835b7ecccc6 Mon Sep 17 00:00:00 2001 From: Jakub Trllo <43494761+iLLiCiTiT@users.noreply.github.com> Date: Thu, 11 Apr 2024 14:42:08 +0200 Subject: [PATCH 77/92] convert only string values in prepare data --- client/ayon_core/lib/plugin_tools.py | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/client/ayon_core/lib/plugin_tools.py b/client/ayon_core/lib/plugin_tools.py index 5ad4da88b9..654bc7ac4a 100644 --- a/client/ayon_core/lib/plugin_tools.py +++ b/client/ayon_core/lib/plugin_tools.py @@ -94,8 +94,12 @@ def prepare_template_data(fill_pairs): output = {} for item in valid_items: keys, value = item - upper_value = value.upper() - capitalized_value = _capitalize_value(value) + # Convert only string values + if isinstance(value, str): + upper_value = value.upper() + capitalized_value = _capitalize_value(value) + else: + upper_value = capitalized_value = value first_key = keys.pop(0) if not keys: From d0b622ffc0fcbfe3c35d213b328702e51acc0aae Mon Sep 17 00:00:00 2001 From: Roy Nieterau Date: Thu, 11 Apr 2024 15:18:11 +0200 Subject: [PATCH 78/92] Improve validations for meshes without any faces/geometry Easiest reproducable: `maya.cmds.createNode("mesh")` --- .../maya/plugins/publish/validate_mesh_ngons.py | 5 +++++ .../plugins/publish/validate_mesh_uv_set_map1.py | 15 +++++++++++++-- 2 files changed, 18 insertions(+), 2 deletions(-) diff --git a/client/ayon_core/hosts/maya/plugins/publish/validate_mesh_ngons.py b/client/ayon_core/hosts/maya/plugins/publish/validate_mesh_ngons.py index d1d7e49fa4..58d015e962 100644 --- a/client/ayon_core/hosts/maya/plugins/publish/validate_mesh_ngons.py +++ b/client/ayon_core/hosts/maya/plugins/publish/validate_mesh_ngons.py @@ -45,6 +45,11 @@ class ValidateMeshNgons(pyblish.api.InstancePlugin, # Get all faces faces = ['{0}.f[*]'.format(node) for node in meshes] + # Skip meshes that for some reason have no faces, e.g. empty meshes + faces = cmds.ls(faces) + if not faces: + return [] + # Filter to n-sided polygon faces (ngons) invalid = lib.polyConstraint(faces, t=0x0008, # type=face diff --git a/client/ayon_core/hosts/maya/plugins/publish/validate_mesh_uv_set_map1.py b/client/ayon_core/hosts/maya/plugins/publish/validate_mesh_uv_set_map1.py index a139b65169..71503f42ee 100644 --- a/client/ayon_core/hosts/maya/plugins/publish/validate_mesh_uv_set_map1.py +++ b/client/ayon_core/hosts/maya/plugins/publish/validate_mesh_uv_set_map1.py @@ -29,8 +29,8 @@ class ValidateMeshUVSetMap1(pyblish.api.InstancePlugin, actions = [ayon_core.hosts.maya.api.action.SelectInvalidAction, RepairAction] - @staticmethod - def get_invalid(instance): + @classmethod + def get_invalid(cls, instance): meshes = cmds.ls(instance, type='mesh', long=True) @@ -40,6 +40,11 @@ class ValidateMeshUVSetMap1(pyblish.api.InstancePlugin, # Get existing mapping of uv sets by index indices = cmds.polyUVSet(mesh, query=True, allUVSetsIndices=True) maps = cmds.polyUVSet(mesh, query=True, allUVSets=True) + if not indices or not maps: + cls.log.warning("Mesh has no UV set: %s", mesh) + invalid.append(mesh) + continue + mapping = dict(zip(indices, maps)) # Get the uv set at index zero. @@ -68,6 +73,12 @@ class ValidateMeshUVSetMap1(pyblish.api.InstancePlugin, # Get existing mapping of uv sets by index indices = cmds.polyUVSet(mesh, query=True, allUVSetsIndices=True) maps = cmds.polyUVSet(mesh, query=True, allUVSets=True) + if not indices or not maps: + # No UV set exist at all, create a `map1` uv set + # This may fail silently if the mesh has no geometry at all + cmds.polyUVSet(mesh, create=True, uvSet="map1") + continue + mapping = dict(zip(indices, maps)) # Ensure there is no uv set named map1 to avoid From 3c8efc0a75cb6dd3c6af2836299048b870918a8c Mon Sep 17 00:00:00 2001 From: Jakub Trllo <43494761+iLLiCiTiT@users.noreply.github.com> Date: Thu, 11 Apr 2024 15:37:10 +0200 Subject: [PATCH 79/92] define explicit version of pyside6 --- .../hosts/blender/hooks/pre_pyside_install.py | 32 ++++++++++++++++--- 1 file changed, 27 insertions(+), 5 deletions(-) diff --git a/client/ayon_core/hosts/blender/hooks/pre_pyside_install.py b/client/ayon_core/hosts/blender/hooks/pre_pyside_install.py index e03856c2e5..a64c767582 100644 --- a/client/ayon_core/hosts/blender/hooks/pre_pyside_install.py +++ b/client/ayon_core/hosts/blender/hooks/pre_pyside_install.py @@ -80,6 +80,9 @@ class InstallPySideToBlender(PreLaunchHook): # Blender 4 has Python 3.11 which does not support 'PySide2' # QUESTION could we always install PySide6? qt_binding = "PySide2" if before_blender_4 else "PySide6" + # Use PySide6 6.6.3 because 6.7.0 had a bug + # - 'QTextEdit' can't be added to 'QBoxLayout' + qt_binding_version = None if before_blender_4 else "6.6.3" python_dir = os.path.join(versions_dir, version_subfolder, "python") python_lib = os.path.join(python_dir, "lib") @@ -130,11 +133,16 @@ class InstallPySideToBlender(PreLaunchHook): # Install PySide2 in blender's python if platform == "windows": result = self.install_pyside_windows( - python_executable, qt_binding, before_blender_4 + python_executable, + qt_binding, + qt_binding_version, + before_blender_4, ) else: result = self.install_pyside( - python_executable, qt_binding + python_executable, + qt_binding, + qt_binding_version, ) if result: @@ -147,7 +155,11 @@ class InstallPySideToBlender(PreLaunchHook): ) def install_pyside_windows( - self, python_executable, qt_binding, before_blender_4 + self, + python_executable, + qt_binding, + qt_binding_version, + before_blender_4, ): """Install PySide2 python module to blender's python. @@ -167,6 +179,9 @@ class InstallPySideToBlender(PreLaunchHook): self.log.warning("Couldn't import \"pywin32\" modules") return + if qt_binding_version: + qt_binding = f"{qt_binding}=={qt_binding_version}" + try: # Parameters # - use "-m pip" as module pip to install PySide2 and argument @@ -212,8 +227,15 @@ class InstallPySideToBlender(PreLaunchHook): except pywintypes.error: pass - def install_pyside(self, python_executable, qt_binding): - """Install PySide2 python module to blender's python.""" + def install_pyside( + self, + python_executable, + qt_binding, + qt_binding_version, + ): + """Install Qt binding python module to blender's python.""" + if qt_binding_version: + qt_binding = f"{qt_binding}=={qt_binding_version}" try: # Parameters # - use "-m pip" as module pip to install qt binding and argument From dfc52029d6718287a642dcff81a5298c76ac8576 Mon Sep 17 00:00:00 2001 From: Roy Nieterau Date: Thu, 11 Apr 2024 16:03:34 +0200 Subject: [PATCH 80/92] Improve validation report: better node list and add description for the report --- .../publish/validate_mesh_uv_set_map1.py | 30 ++++++++++++++++++- 1 file changed, 29 insertions(+), 1 deletion(-) diff --git a/client/ayon_core/hosts/maya/plugins/publish/validate_mesh_uv_set_map1.py b/client/ayon_core/hosts/maya/plugins/publish/validate_mesh_uv_set_map1.py index 71503f42ee..305a58d78e 100644 --- a/client/ayon_core/hosts/maya/plugins/publish/validate_mesh_uv_set_map1.py +++ b/client/ayon_core/hosts/maya/plugins/publish/validate_mesh_uv_set_map1.py @@ -1,3 +1,5 @@ +import inspect + from maya import cmds import pyblish.api @@ -61,8 +63,14 @@ class ValidateMeshUVSetMap1(pyblish.api.InstancePlugin, invalid = self.get_invalid(instance) if invalid: + + invalid_list = "\n".join(f"- {node}" for node in invalid) + raise PublishValidationError( - "Meshes found without 'map1' UV set: {0}".format(invalid)) + "Meshes found without 'map1' UV set:\n" + "{0}".format(invalid_list), + description=self.get_description() + ) @classmethod def repair(cls, instance): @@ -108,3 +116,23 @@ class ValidateMeshUVSetMap1(pyblish.api.InstancePlugin, rename=True, uvSet=original, newUVSet="map1") + + @staticmethod + def get_description(): + return inspect.cleandoc("""### Mesh found without map1 uv set + + A mesh must have a default UV set named `map1` to adhere to the default + mesh behavior of Maya meshes. + + There may be meshes that: + - Have no UV set + - Have no `map1` uv set but are using a different name + - Have a `map1` uv set, but it's not the default (first index) + + + #### Repair + + Using repair will try to make the first UV set the `map1` uv set. If it + does not exist yet it will be created or renames the current first + UV set to `map1`. + """) From 9690748d993dc2384013fc3a6714cd82e7000435 Mon Sep 17 00:00:00 2001 From: Roy Nieterau Date: Thu, 11 Apr 2024 16:24:40 +0200 Subject: [PATCH 81/92] Do not return `bool` --- client/ayon_core/pipeline/publish/lib.py | 8 +------- 1 file changed, 1 insertion(+), 7 deletions(-) diff --git a/client/ayon_core/pipeline/publish/lib.py b/client/ayon_core/pipeline/publish/lib.py index ebdaca5518..4cf2c4cb83 100644 --- a/client/ayon_core/pipeline/publish/lib.py +++ b/client/ayon_core/pipeline/publish/lib.py @@ -948,11 +948,6 @@ def replace_instance_in_context( the publisher to correctly detect and transfer the logs relevant for the instance. - Returns: - bool: Whether the source instance was replaced or the destination - instance was only added because source instance did not exist - in the context. - """ # Transfer the pyblish.api.Instance id destination_instance._id = source_instance.id @@ -966,8 +961,7 @@ def replace_instance_in_context( for idx, instance in enumerate(context): if source_instance is instance: context[idx] = destination_instance - return True + return # Source was not found context.append(destination_instance) - return False From 5ad7103f5777f70d244bde459cbf7b98b880f1d9 Mon Sep 17 00:00:00 2001 From: Roy Nieterau Date: Thu, 11 Apr 2024 16:25:34 +0200 Subject: [PATCH 82/92] Raise error if source not found in context --- 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 4cf2c4cb83..bf733a8620 100644 --- a/client/ayon_core/pipeline/publish/lib.py +++ b/client/ayon_core/pipeline/publish/lib.py @@ -963,5 +963,6 @@ def replace_instance_in_context( context[idx] = destination_instance return - # Source was not found - context.append(destination_instance) + raise ValueError( + f"Source instance {source_instance} not found in context." + ) From 79abe05637823693cc9cea73823f1adf8f6359f7 Mon Sep 17 00:00:00 2001 From: Roy Nieterau Date: Thu, 11 Apr 2024 17:03:42 +0200 Subject: [PATCH 83/92] Fix message formatting --- .../hosts/maya/plugins/publish/validate_scene_set_workspace.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/client/ayon_core/hosts/maya/plugins/publish/validate_scene_set_workspace.py b/client/ayon_core/hosts/maya/plugins/publish/validate_scene_set_workspace.py index 6e68cf5d14..c7d5de2050 100644 --- a/client/ayon_core/hosts/maya/plugins/publish/validate_scene_set_workspace.py +++ b/client/ayon_core/hosts/maya/plugins/publish/validate_scene_set_workspace.py @@ -46,6 +46,6 @@ class ValidateSceneSetWorkspace(pyblish.api.ContextPlugin): raise PublishValidationError( "Maya workspace is not set correctly.\n\n" f"Current workfile `{scene_name}` is not inside the " - "current Maya project root directory `{root_dir}`.\n\n" + f"current Maya project root directory `{root_dir}`.\n\n" "Please use Workfile app to re-save." ) From 129d5d6b0ed2cbcb1ab673f2e315dc65bfd7471a Mon Sep 17 00:00:00 2001 From: Roy Nieterau Date: Thu, 11 Apr 2024 17:11:39 +0200 Subject: [PATCH 84/92] Do not create a new instance, just update the existing instance --- .../publish/abstract_collect_render.py | 13 ++----- client/ayon_core/pipeline/publish/lib.py | 34 +------------------ 2 files changed, 4 insertions(+), 43 deletions(-) diff --git a/client/ayon_core/pipeline/publish/abstract_collect_render.py b/client/ayon_core/pipeline/publish/abstract_collect_render.py index a9d5b38ada..d344433d53 100644 --- a/client/ayon_core/pipeline/publish/abstract_collect_render.py +++ b/client/ayon_core/pipeline/publish/abstract_collect_render.py @@ -12,7 +12,6 @@ import six import pyblish.api from .publish_plugins import AbstractMetaContextPlugin -from .lib import replace_instance_in_context @attr.s @@ -218,16 +217,10 @@ class AbstractCollectRender(pyblish.api.ContextPlugin): data = self.add_additional_data(data) render_instance_dict = attr.asdict(render_instance) - instance = context.create_instance(render_instance.name) if render_instance.source_instance is not None: - # remove the new instance, because we want to insert it - # at the position of the original instance to replace the - # source instance in the context completely - context.pop() - replace_instance_in_context( - context, - source_instance=render_instance.source_instance, - destination_instance=instance) + instance = render_instance.source_instance + else: + instance = context.create_instance(render_instance.name) instance.data.update(render_instance_dict) instance.data.update(data) diff --git a/client/ayon_core/pipeline/publish/lib.py b/client/ayon_core/pipeline/publish/lib.py index bf733a8620..0be72b459a 100644 --- a/client/ayon_core/pipeline/publish/lib.py +++ b/client/ayon_core/pipeline/publish/lib.py @@ -933,36 +933,4 @@ def get_publish_instance_families(instance): output.append(family) families.discard(family) output.extend(families) - return output - - -def replace_instance_in_context( - context: pyblish.api.Context, - source_instance: pyblish.api.Instance, - destination_instance: pyblish.api.Instance -): - """Replace source instance with the destination instance. - - This transfers the instance's IDs so that the new instance acts exactly - as if it was the source instance the whole time. This is required for - the publisher to correctly detect and transfer the logs relevant for the - instance. - - """ - # Transfer the pyblish.api.Instance id - destination_instance._id = source_instance.id - - # Transfer the `instance_id` of the new publisher's instances - key = "instance_id" - if key in source_instance.data: - destination_instance.data[key] = source_instance.data[key] - - # Replace the instance at the same index in the context - for idx, instance in enumerate(context): - if source_instance is instance: - context[idx] = destination_instance - return - - raise ValueError( - f"Source instance {source_instance} not found in context." - ) + return output \ No newline at end of file From 5f507ff85438654e42891f54daf12a327d87993e Mon Sep 17 00:00:00 2001 From: Roy Nieterau Date: Thu, 11 Apr 2024 17:12:45 +0200 Subject: [PATCH 85/92] Update comment --- client/ayon_core/pipeline/publish/abstract_collect_render.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/client/ayon_core/pipeline/publish/abstract_collect_render.py b/client/ayon_core/pipeline/publish/abstract_collect_render.py index d344433d53..2e56adf66e 100644 --- a/client/ayon_core/pipeline/publish/abstract_collect_render.py +++ b/client/ayon_core/pipeline/publish/abstract_collect_render.py @@ -81,7 +81,7 @@ class RenderInstance(object): outputDir = attr.ib(default=None) context = attr.ib(default=None) - # The source instance this render instance should replace in the context + # The source instance the data of this render instance should merge into source_instance = attr.ib(default=None, type=pyblish.api.Instance) @frameStart.validator From c9dc848b70592088594c8254e256f446101548c5 Mon Sep 17 00:00:00 2001 From: Roy Nieterau Date: Thu, 11 Apr 2024 17:15:42 +0200 Subject: [PATCH 86/92] Cosmetics --- client/ayon_core/pipeline/publish/lib.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/client/ayon_core/pipeline/publish/lib.py b/client/ayon_core/pipeline/publish/lib.py index 0be72b459a..8d3644637b 100644 --- a/client/ayon_core/pipeline/publish/lib.py +++ b/client/ayon_core/pipeline/publish/lib.py @@ -933,4 +933,4 @@ def get_publish_instance_families(instance): output.append(family) families.discard(family) output.extend(families) - return output \ No newline at end of file + return output From c538ed58efd1c35849455822c089dc53b2ca8731 Mon Sep 17 00:00:00 2001 From: Roy Nieterau Date: Thu, 11 Apr 2024 17:26:15 +0200 Subject: [PATCH 87/92] Do not merge `source_instance` into the instance --- .../ayon_core/pipeline/publish/abstract_collect_render.py | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/client/ayon_core/pipeline/publish/abstract_collect_render.py b/client/ayon_core/pipeline/publish/abstract_collect_render.py index 2e56adf66e..c50dc16380 100644 --- a/client/ayon_core/pipeline/publish/abstract_collect_render.py +++ b/client/ayon_core/pipeline/publish/abstract_collect_render.py @@ -217,9 +217,9 @@ class AbstractCollectRender(pyblish.api.ContextPlugin): data = self.add_additional_data(data) render_instance_dict = attr.asdict(render_instance) - if render_instance.source_instance is not None: - instance = render_instance.source_instance - else: + # Merge into source instance if provided, otherwise create instance + instance = render_instance_dict.pop("source_instance", None) + if instance is None: instance = context.create_instance(render_instance.name) instance.data.update(render_instance_dict) From cc42c4d5a89978a3ca3be622dc28bbab0e85902f Mon Sep 17 00:00:00 2001 From: Petr Kalis Date: Thu, 11 Apr 2024 17:52:38 +0200 Subject: [PATCH 88/92] Fix - use differently named variable Original `instance` variable might shadow wanted `render-like` instance if wrong order of instances get processed. --- .../deadline/plugins/publish/submit_fusion_deadline.py | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/client/ayon_core/modules/deadline/plugins/publish/submit_fusion_deadline.py b/client/ayon_core/modules/deadline/plugins/publish/submit_fusion_deadline.py index bfb65708e6..e3a4cd8030 100644 --- a/client/ayon_core/modules/deadline/plugins/publish/submit_fusion_deadline.py +++ b/client/ayon_core/modules/deadline/plugins/publish/submit_fusion_deadline.py @@ -103,17 +103,17 @@ class FusionSubmitDeadline( # Collect all saver instances in context that are to be rendered saver_instances = [] - for instance in context: - if instance.data["productType"] != "render": + for inst in context: + if inst.data["productType"] != "render": # Allow only saver family instances continue - if not instance.data.get("publish", True): + if not inst.data.get("publish", True): # Skip inactive instances continue - self.log.debug(instance.data["name"]) - saver_instances.append(instance) + self.log.debug(inst.data["name"]) + saver_instances.append(inst) if not saver_instances: raise RuntimeError("No instances found for Deadline submission") From 6a08003ca7975dc2a72d7e66577a21303dc71362 Mon Sep 17 00:00:00 2001 From: Roy Nieterau Date: Thu, 11 Apr 2024 18:06:27 +0200 Subject: [PATCH 89/92] Preserve image plane size on attaching - fix #411 --- .../hosts/maya/plugins/publish/extract_camera_mayaScene.py | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/client/ayon_core/hosts/maya/plugins/publish/extract_camera_mayaScene.py b/client/ayon_core/hosts/maya/plugins/publish/extract_camera_mayaScene.py index c4af2914cd..cb3951ec0c 100644 --- a/client/ayon_core/hosts/maya/plugins/publish/extract_camera_mayaScene.py +++ b/client/ayon_core/hosts/maya/plugins/publish/extract_camera_mayaScene.py @@ -299,4 +299,10 @@ def transfer_image_planes(source_cameras, target_cameras, def _attach_image_plane(camera, image_plane): cmds.imagePlane(image_plane, edit=True, detach=True) + + # Attaching to a camera resets it to identity size, so we counter that + size_x = cmds.getAttr(f"{image_plane}.sizeX") + size_y = cmds.getAttr(f"{image_plane}.sizeY") cmds.imagePlane(image_plane, edit=True, camera=camera) + cmds.setAttr(f"{image_plane}.sizeX", size_x) + cmds.setAttr(f"{image_plane}.sizeY", size_y) From 5adfd62e9a025bbced343c121ef9982160a95887 Mon Sep 17 00:00:00 2001 From: Toke Stuart Jepsen Date: Thu, 11 Apr 2024 21:20:53 +0100 Subject: [PATCH 90/92] Porting --- .../pipeline/farm/pyblish_functions.py | 25 ++++++++++++++++--- 1 file changed, 21 insertions(+), 4 deletions(-) diff --git a/client/ayon_core/pipeline/farm/pyblish_functions.py b/client/ayon_core/pipeline/farm/pyblish_functions.py index 37003cbd88..eb6f8569d9 100644 --- a/client/ayon_core/pipeline/farm/pyblish_functions.py +++ b/client/ayon_core/pipeline/farm/pyblish_functions.py @@ -617,15 +617,32 @@ def _create_instances_for_aov(instance, skeleton, aov_filter, additional_data, aov_patterns = aov_filter preview = match_aov_pattern(app, aov_patterns, render_file_name) - # toggle preview on if multipart is on - if instance.data.get("multipartExr"): - log.debug("Adding preview tag because its multipartExr") - preview = True new_instance = deepcopy(skeleton) new_instance["productName"] = product_name new_instance["productGroup"] = group_name + # toggle preview on if multipart is on + # Because we cant query the multipartExr data member of each AOV we'll + # need to have hardcoded rule of excluding any renders with + # "cryptomatte" in the file name from being a multipart EXR. This issue + # happens with Redshift that forces Cryptomatte renders to be separate + # files even when the rest of the AOVs are merged into a single EXR. + # There might be an edge case where the main instance has cryptomatte + # in the name even though it's a multipart EXR. + if instance.data.get("renderer") == "redshift": + if ( + instance.data.get("multipartExr") and + "cryptomatte" not in render_file_name.lower() + ): + log.debug("Adding preview tag because it's multipartExr") + preview = True + else: + new_instance["multipartExr"] = False + elif instance.data.get("multipartExr"): + log.debug("Adding preview tag because its multipartExr") + preview = True + # explicitly disable review by user preview = preview and not do_not_add_review if preview: From 0a2a1105df3f1ced13e460bc9c4a46e6e6d7a5aa Mon Sep 17 00:00:00 2001 From: Roy Nieterau Date: Fri, 12 Apr 2024 14:45:57 +0200 Subject: [PATCH 91/92] Ignore invalid uuids in query to AYON API --- .../publish/validate_node_ids_related.py | 18 ++++++++++++++++++ 1 file changed, 18 insertions(+) diff --git a/client/ayon_core/hosts/maya/plugins/publish/validate_node_ids_related.py b/client/ayon_core/hosts/maya/plugins/publish/validate_node_ids_related.py index f8337ed6f0..2930f6f7f6 100644 --- a/client/ayon_core/hosts/maya/plugins/publish/validate_node_ids_related.py +++ b/client/ayon_core/hosts/maya/plugins/publish/validate_node_ids_related.py @@ -1,3 +1,4 @@ +import uuid from collections import defaultdict import pyblish.api @@ -8,6 +9,15 @@ from ayon_core.pipeline.publish import ( from ayon_api import get_folders +def is_valid_uuid(value) -> bool: + """Return whether value is a valid UUID""" + try: + uuid.UUID(value) + except ValueError: + return False + return True + + class ValidateNodeIDsRelated(pyblish.api.InstancePlugin, OptionalPyblishPluginMixin): """Validate nodes have a related Colorbleed Id to the @@ -70,6 +80,14 @@ class ValidateNodeIDsRelated(pyblish.api.InstancePlugin, if nodes_by_other_folder_ids: project_name = instance.context.data["projectName"] other_folder_ids = set(nodes_by_other_folder_ids.keys()) + + # Remove folder ids that are not valid UUID identifiers, these + # may be legacy OpenPype ids + other_folder_ids = {folder_id for folder_id in other_folder_ids + if is_valid_uuid(folder_id)} + if not other_folder_ids: + return invalid + folder_entities = get_folders(project_name=project_name, folder_ids=other_folder_ids, fields=["path"]) From 8984788bc35d24ec819803cf06c643f420867da9 Mon Sep 17 00:00:00 2001 From: Roy Nieterau Date: Fri, 12 Apr 2024 15:29:45 +0200 Subject: [PATCH 92/92] Improve validation report --- .../publish/validate_node_ids_related.py | 37 ++++++++++++++----- 1 file changed, 27 insertions(+), 10 deletions(-) diff --git a/client/ayon_core/hosts/maya/plugins/publish/validate_node_ids_related.py b/client/ayon_core/hosts/maya/plugins/publish/validate_node_ids_related.py index 2930f6f7f6..17eb58f421 100644 --- a/client/ayon_core/hosts/maya/plugins/publish/validate_node_ids_related.py +++ b/client/ayon_core/hosts/maya/plugins/publish/validate_node_ids_related.py @@ -1,3 +1,4 @@ +import inspect import uuid from collections import defaultdict import pyblish.api @@ -20,10 +21,7 @@ def is_valid_uuid(value) -> bool: class ValidateNodeIDsRelated(pyblish.api.InstancePlugin, OptionalPyblishPluginMixin): - """Validate nodes have a related Colorbleed Id to the - instance.data[folderPath] - - """ + """Validate nodes have a related `cbId` to the instance.data[folderPath]""" order = ValidatePipelineOrder label = 'Node Ids Related (ID)' @@ -51,11 +49,14 @@ class ValidateNodeIDsRelated(pyblish.api.InstancePlugin, # Ensure all nodes have a cbId invalid = self.get_invalid(instance) if invalid: + + invalid_list = "\n".join(f"- {node}" for node in sorted(invalid)) + raise PublishValidationError(( - "Nodes IDs found that are not related to folder '{}' : {}" - ).format( - instance.data["folderPath"], invalid - )) + "Nodes IDs found that are not related to folder '{}':\n{}" + ).format(instance.data["folderPath"], invalid_list), + description=self.get_description() + ) @classmethod def get_invalid(cls, instance): @@ -98,8 +99,24 @@ class ValidateNodeIDsRelated(pyblish.api.InstancePlugin, # takes care of that. folder_paths = {entity["path"] for entity in folder_entities} cls.log.error( - "Found nodes related to other assets: {}" - .format(", ".join(sorted(folder_paths))) + "Found nodes related to other folders:\n{}".format( + "\n".join(f"- {path}" for path in sorted(folder_paths)) + ) ) return invalid + + @staticmethod + def get_description(): + return inspect.cleandoc("""### Node IDs must match folder id + + The node ids must match the folder entity id you are publishing to. + + Usually these mismatch occurs if you are re-using nodes from another + folder or project. + + #### How to repair? + + The repair action will regenerate new ids for + the invalid nodes to match the instance's folder. + """)