From 10da5885cd8611354f0c903622a33124dcda4ac4 Mon Sep 17 00:00:00 2001 From: Jacob Danell Date: Thu, 9 Mar 2023 21:13:42 +0100 Subject: [PATCH 01/23] Get the settings up and running --- .../defaults/project_settings/kitsu.json | 6 ++++- .../projects_schema/schema_project_kitsu.json | 26 ++++++++++++++++++- 2 files changed, 30 insertions(+), 2 deletions(-) diff --git a/openpype/settings/defaults/project_settings/kitsu.json b/openpype/settings/defaults/project_settings/kitsu.json index 95b3da04ae..280895f1b9 100644 --- a/openpype/settings/defaults/project_settings/kitsu.json +++ b/openpype/settings/defaults/project_settings/kitsu.json @@ -8,6 +8,10 @@ "IntegrateKitsuNote": { "set_status_note": false, "note_status_shortname": "wfa" + }, + "CustomCommentTemplate": { + "enabled": false, + "comment_template": "{comment}\n\n| | |\n|--|--|\n| version| `{version}` |\n| family | `{family}` |\n| name | `{name}` |" } } -} +} \ No newline at end of file diff --git a/openpype/settings/entities/schemas/projects_schema/schema_project_kitsu.json b/openpype/settings/entities/schemas/projects_schema/schema_project_kitsu.json index fb47670e74..255190c396 100644 --- a/openpype/settings/entities/schemas/projects_schema/schema_project_kitsu.json +++ b/openpype/settings/entities/schemas/projects_schema/schema_project_kitsu.json @@ -54,8 +54,32 @@ "label": "Note shortname" } ] + }, + { + "type": "dict", + "collapsible": true, + "checkbox_key": "enabled", + "key": "CustomCommentTemplate", + "label": "Custom Comment Template", + "children": [ + { + "type": "boolean", + "key": "enabled", + "label": "Enabled" + }, + { + "type": "label", + "label": "Kitsu supports markdown and here you can create a custom comment template.
You can use data from your instance's anatomy." + }, + { + "key": "comment_template", + "type": "text", + "multiline": true, + "label": "Custom comment" + } + ] } ] } ] -} +} \ No newline at end of file From e2771abfb48d255288a708407b305241f4601737 Mon Sep 17 00:00:00 2001 From: Jacob Danell Date: Fri, 10 Mar 2023 23:07:13 +0100 Subject: [PATCH 02/23] Move CustomCommentTemplate to within IntegrateKitsuNote --- .../defaults/project_settings/kitsu.json | 10 ++--- .../projects_schema/schema_project_kitsu.json | 44 +++++++++---------- 2 files changed, 27 insertions(+), 27 deletions(-) diff --git a/openpype/settings/defaults/project_settings/kitsu.json b/openpype/settings/defaults/project_settings/kitsu.json index 280895f1b9..f8a98d1a0b 100644 --- a/openpype/settings/defaults/project_settings/kitsu.json +++ b/openpype/settings/defaults/project_settings/kitsu.json @@ -7,11 +7,11 @@ "publish": { "IntegrateKitsuNote": { "set_status_note": false, - "note_status_shortname": "wfa" - }, - "CustomCommentTemplate": { - "enabled": false, - "comment_template": "{comment}\n\n| | |\n|--|--|\n| version| `{version}` |\n| family | `{family}` |\n| name | `{name}` |" + "note_status_shortname": "wfa", + "CustomCommentTemplate": { + "enabled": false, + "comment_template": "{comment}\n\n| | |\n|--|--|\n| version| `{version}` |\n| family | `{family}` |\n| name | `{name}` |" + } } } } \ No newline at end of file diff --git a/openpype/settings/entities/schemas/projects_schema/schema_project_kitsu.json b/openpype/settings/entities/schemas/projects_schema/schema_project_kitsu.json index 255190c396..25f75c8280 100644 --- a/openpype/settings/entities/schemas/projects_schema/schema_project_kitsu.json +++ b/openpype/settings/entities/schemas/projects_schema/schema_project_kitsu.json @@ -52,30 +52,30 @@ "type": "text", "key": "note_status_shortname", "label": "Note shortname" - } - ] - }, - { - "type": "dict", - "collapsible": true, - "checkbox_key": "enabled", - "key": "CustomCommentTemplate", - "label": "Custom Comment Template", - "children": [ - { - "type": "boolean", - "key": "enabled", - "label": "Enabled" }, { - "type": "label", - "label": "Kitsu supports markdown and here you can create a custom comment template.
You can use data from your instance's anatomy." - }, - { - "key": "comment_template", - "type": "text", - "multiline": true, - "label": "Custom comment" + "type": "dict", + "collapsible": true, + "checkbox_key": "enabled", + "key": "CustomCommentTemplate", + "label": "Custom Comment Template", + "children": [ + { + "type": "boolean", + "key": "enabled", + "label": "Enabled" + }, + { + "type": "label", + "label": "Kitsu supports markdown and here you can create a custom comment template.
You can use data from your instance's anatomy." + }, + { + "key": "comment_template", + "type": "text", + "multiline": true, + "label": "Custom comment" + } + ] } ] } From 7c1789faabea2380ab3001e32876d2747cf55f28 Mon Sep 17 00:00:00 2001 From: Jacob Danell Date: Fri, 10 Mar 2023 23:07:41 +0100 Subject: [PATCH 03/23] Add custom message functionally --- .../plugins/publish/integrate_kitsu_note.py | 36 +++++++++++++++++-- 1 file changed, 34 insertions(+), 2 deletions(-) diff --git a/openpype/modules/kitsu/plugins/publish/integrate_kitsu_note.py b/openpype/modules/kitsu/plugins/publish/integrate_kitsu_note.py index 6702cbe7aa..b1743ca828 100644 --- a/openpype/modules/kitsu/plugins/publish/integrate_kitsu_note.py +++ b/openpype/modules/kitsu/plugins/publish/integrate_kitsu_note.py @@ -1,6 +1,7 @@ # -*- coding: utf-8 -*- import gazu import pyblish.api +import re class IntegrateKitsuNote(pyblish.api.ContextPlugin): @@ -9,17 +10,39 @@ class IntegrateKitsuNote(pyblish.api.ContextPlugin): order = pyblish.api.IntegratorOrder label = "Kitsu Note and Status" families = ["render", "kitsu"] + + # status settings set_status_note = False note_status_shortname = "wfa" + # comment settings + CustomCommentTemplate = {} + CustomCommentTemplate["enabled"] = False + CustomCommentTemplate["comment_template"] = "{comment}" + + def safe_format(self, msg, **kwargs): + def replace_missing(match): + value = kwargs.get(match.group(1), None) + if value is None: + self.log.warning( + "Key `{}` was not found in instance.data " + "and will be rendered as `` in the comment".format( + match.group(1) + ) + ) + return "" + else: + return str(value) + + pattern = r"\{([^}]*)\}" + return re.sub(pattern, replace_missing, msg) + def process(self, context): # Get comment text body publish_comment = context.data.get("comment") if not publish_comment: self.log.info("Comment is not set.") - self.log.debug("Comment is `{}`".format(publish_comment)) - for instance in context: kitsu_task = instance.data.get("kitsu_task") if kitsu_task is None: @@ -42,6 +65,15 @@ class IntegrateKitsuNote(pyblish.api.ContextPlugin): "changed!".format(self.note_status_shortname) ) + # If custom comment, create it + if self.CustomCommentTemplate["enabled"]: + publish_comment = self.safe_format( + self.CustomCommentTemplate["comment_template"], + **instance.data, + ) + + self.log.debug("Comment is `{}`".format(publish_comment)) + # Add comment to kitsu task task_id = kitsu_task["id"] self.log.debug("Add new note in taks id {}".format(task_id)) From a797d78d451eb953bd5c4a2018712ade3e645c2a Mon Sep 17 00:00:00 2001 From: Jacob Danell Date: Fri, 10 Mar 2023 23:19:31 +0100 Subject: [PATCH 04/23] Added a check so only renders gets published to Kitsu --- .../modules/kitsu/plugins/publish/integrate_kitsu_note.py | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/openpype/modules/kitsu/plugins/publish/integrate_kitsu_note.py b/openpype/modules/kitsu/plugins/publish/integrate_kitsu_note.py index b1743ca828..44134dec6d 100644 --- a/openpype/modules/kitsu/plugins/publish/integrate_kitsu_note.py +++ b/openpype/modules/kitsu/plugins/publish/integrate_kitsu_note.py @@ -44,6 +44,10 @@ class IntegrateKitsuNote(pyblish.api.ContextPlugin): self.log.info("Comment is not set.") for instance in context: + # Check if instance is a render by checking its family + if "render" not in instance.data["family"]: + continue + kitsu_task = instance.data.get("kitsu_task") if kitsu_task is None: continue From 1093c519add9baae3276e01aa28e1a1d46cab0c8 Mon Sep 17 00:00:00 2001 From: Jacob Danell Date: Fri, 10 Mar 2023 23:27:47 +0100 Subject: [PATCH 05/23] Change the label to explain more correct what it does --- .../schemas/projects_schema/schema_project_kitsu.json | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/openpype/settings/entities/schemas/projects_schema/schema_project_kitsu.json b/openpype/settings/entities/schemas/projects_schema/schema_project_kitsu.json index 25f75c8280..1a7747b3dc 100644 --- a/openpype/settings/entities/schemas/projects_schema/schema_project_kitsu.json +++ b/openpype/settings/entities/schemas/projects_schema/schema_project_kitsu.json @@ -46,12 +46,12 @@ { "type": "boolean", "key": "set_status_note", - "label": "Set status on note" + "label": "Set status with note" }, { "type": "text", "key": "note_status_shortname", - "label": "Note shortname" + "label": "Status shortname" }, { "type": "dict", From 24a22e964a4de4481c9896eca2ebc5ebf75adabd Mon Sep 17 00:00:00 2001 From: Jakub Jezek Date: Mon, 13 Mar 2023 16:27:33 +0100 Subject: [PATCH 06/23] Nuke: fix families mixing up with old way. --- .../deadline/plugins/publish/submit_nuke_deadline.py | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/openpype/modules/deadline/plugins/publish/submit_nuke_deadline.py b/openpype/modules/deadline/plugins/publish/submit_nuke_deadline.py index aff34c7e4a..9abe8dec8b 100644 --- a/openpype/modules/deadline/plugins/publish/submit_nuke_deadline.py +++ b/openpype/modules/deadline/plugins/publish/submit_nuke_deadline.py @@ -32,7 +32,7 @@ class NukeSubmitDeadline(pyblish.api.InstancePlugin, label = "Submit Nuke to Deadline" order = pyblish.api.IntegratorOrder + 0.1 hosts = ["nuke"] - families = ["render", "prerender.farm"] + families = ["render", "prerender"] optional = True targets = ["local"] @@ -80,6 +80,9 @@ class NukeSubmitDeadline(pyblish.api.InstancePlugin, ] def process(self, instance): + if not instance.data.get("farm"): + return + instance.data["attributeValues"] = self.get_attr_values_from_data( instance.data) @@ -168,10 +171,10 @@ class NukeSubmitDeadline(pyblish.api.InstancePlugin, resp.json()["_id"]) # redefinition of families - if "render.farm" in families: + if "render" in family: instance.data['family'] = 'write' families.insert(0, "render2d") - elif "prerender.farm" in families: + elif "prerender" in family: instance.data['family'] = 'write' families.insert(0, "prerender") instance.data["families"] = families From 1e458d6d1d67b2eb88c0d6e649fd80f7192f08ce Mon Sep 17 00:00:00 2001 From: Jakub Jezek Date: Tue, 14 Mar 2023 14:44:29 +0100 Subject: [PATCH 07/23] global and nuke: farm publishing workflow fixes --- openpype/hosts/nuke/plugins/publish/extract_review_data.py | 2 +- .../hosts/nuke/plugins/publish/extract_review_data_lut.py | 7 ++++++- .../hosts/nuke/plugins/publish/extract_review_data_mov.py | 5 +---- openpype/hosts/nuke/plugins/publish/extract_thumbnail.py | 2 +- .../deadline/plugins/publish/submit_nuke_deadline.py | 5 +++-- .../modules/deadline/plugins/publish/submit_publish_job.py | 4 ++++ .../deadline/plugins/publish/validate_deadline_pools.py | 4 ++++ 7 files changed, 20 insertions(+), 9 deletions(-) diff --git a/openpype/hosts/nuke/plugins/publish/extract_review_data.py b/openpype/hosts/nuke/plugins/publish/extract_review_data.py index dee8248295..c221af40fb 100644 --- a/openpype/hosts/nuke/plugins/publish/extract_review_data.py +++ b/openpype/hosts/nuke/plugins/publish/extract_review_data.py @@ -25,7 +25,7 @@ class ExtractReviewData(publish.Extractor): # review can be removed since `ProcessSubmittedJobOnFarm` will create # reviewable representation if needed if ( - "render.farm" in instance.data["families"] + instance.data.get("farm") and "review" in instance.data["families"] ): instance.data["families"].remove("review") diff --git a/openpype/hosts/nuke/plugins/publish/extract_review_data_lut.py b/openpype/hosts/nuke/plugins/publish/extract_review_data_lut.py index 67779e9599..e4b7b155cd 100644 --- a/openpype/hosts/nuke/plugins/publish/extract_review_data_lut.py +++ b/openpype/hosts/nuke/plugins/publish/extract_review_data_lut.py @@ -49,7 +49,12 @@ class ExtractReviewDataLut(publish.Extractor): exporter.stagingDir, exporter.file).replace("\\", "/") instance.data["representations"] += data["representations"] - if "render.farm" in families: + # review can be removed since `ProcessSubmittedJobOnFarm` will create + # reviewable representation if needed + if ( + instance.data.get("farm") + and "review" in instance.data["families"] + ): instance.data["families"].remove("review") self.log.debug( diff --git a/openpype/hosts/nuke/plugins/publish/extract_review_data_mov.py b/openpype/hosts/nuke/plugins/publish/extract_review_data_mov.py index 3fcfc2a4b5..956d1a54a3 100644 --- a/openpype/hosts/nuke/plugins/publish/extract_review_data_mov.py +++ b/openpype/hosts/nuke/plugins/publish/extract_review_data_mov.py @@ -105,10 +105,7 @@ class ExtractReviewDataMov(publish.Extractor): self, instance, o_name, o_data["extension"], multiple_presets) - if ( - "render.farm" in families or - "prerender.farm" in families - ): + if instance.data.get("farm"): if "review" in instance.data["families"]: instance.data["families"].remove("review") diff --git a/openpype/hosts/nuke/plugins/publish/extract_thumbnail.py b/openpype/hosts/nuke/plugins/publish/extract_thumbnail.py index a1a0e241c0..f391ca1e7c 100644 --- a/openpype/hosts/nuke/plugins/publish/extract_thumbnail.py +++ b/openpype/hosts/nuke/plugins/publish/extract_thumbnail.py @@ -31,7 +31,7 @@ class ExtractThumbnail(publish.Extractor): def process(self, instance): - if "render.farm" in instance.data["families"]: + if instance.data.get("farm"): return with napi.maintained_selection(): diff --git a/openpype/modules/deadline/plugins/publish/submit_nuke_deadline.py b/openpype/modules/deadline/plugins/publish/submit_nuke_deadline.py index 9abe8dec8b..cc069cf51a 100644 --- a/openpype/modules/deadline/plugins/publish/submit_nuke_deadline.py +++ b/openpype/modules/deadline/plugins/publish/submit_nuke_deadline.py @@ -81,6 +81,7 @@ class NukeSubmitDeadline(pyblish.api.InstancePlugin, def process(self, instance): if not instance.data.get("farm"): + self.log.info("Skipping local instance.") return instance.data["attributeValues"] = self.get_attr_values_from_data( @@ -171,10 +172,10 @@ class NukeSubmitDeadline(pyblish.api.InstancePlugin, resp.json()["_id"]) # redefinition of families - if "render" in family: + if "render" in instance.data["family"]: instance.data['family'] = 'write' families.insert(0, "render2d") - elif "prerender" in family: + elif "prerender" in instance.data["family"]: instance.data['family'] = 'write' families.insert(0, "prerender") instance.data["families"] = families diff --git a/openpype/modules/deadline/plugins/publish/submit_publish_job.py b/openpype/modules/deadline/plugins/publish/submit_publish_job.py index 53c09ad22f..0d0698c21f 100644 --- a/openpype/modules/deadline/plugins/publish/submit_publish_job.py +++ b/openpype/modules/deadline/plugins/publish/submit_publish_job.py @@ -756,6 +756,10 @@ class ProcessSubmittedJobOnFarm(pyblish.api.InstancePlugin): instance (pyblish.api.Instance): Instance data. """ + if not instance.data.get("farm"): + self.log.info("Skipping local instance.") + return + data = instance.data.copy() context = instance.context self.context = context diff --git a/openpype/modules/deadline/plugins/publish/validate_deadline_pools.py b/openpype/modules/deadline/plugins/publish/validate_deadline_pools.py index 78eed17c98..05afa5080d 100644 --- a/openpype/modules/deadline/plugins/publish/validate_deadline_pools.py +++ b/openpype/modules/deadline/plugins/publish/validate_deadline_pools.py @@ -21,6 +21,10 @@ class ValidateDeadlinePools(OptionalPyblishPluginMixin, optional = True def process(self, instance): + if not instance.data.get("farm"): + self.log.info("Skipping local instance.") + return + # get default deadline webservice url from deadline module deadline_url = instance.context.data["defaultDeadline"] self.log.info("deadline_url::{}".format(deadline_url)) From 383ce7ccb6f20453ef2aa40d81b2af4ae5856eba Mon Sep 17 00:00:00 2001 From: Jacob Danell Date: Tue, 14 Mar 2023 18:32:18 +0100 Subject: [PATCH 08/23] Change variable name to snake_case --- .../kitsu/plugins/publish/integrate_kitsu_note.py | 12 +++++++----- 1 file changed, 7 insertions(+), 5 deletions(-) diff --git a/openpype/modules/kitsu/plugins/publish/integrate_kitsu_note.py b/openpype/modules/kitsu/plugins/publish/integrate_kitsu_note.py index 44134dec6d..debbfdf98e 100644 --- a/openpype/modules/kitsu/plugins/publish/integrate_kitsu_note.py +++ b/openpype/modules/kitsu/plugins/publish/integrate_kitsu_note.py @@ -16,9 +16,11 @@ class IntegrateKitsuNote(pyblish.api.ContextPlugin): note_status_shortname = "wfa" # comment settings - CustomCommentTemplate = {} - CustomCommentTemplate["enabled"] = False - CustomCommentTemplate["comment_template"] = "{comment}" + custom_comment_template = {} + custom_comment_template = { + "enabled": False, + "comment_template": "{comment}", + } def safe_format(self, msg, **kwargs): def replace_missing(match): @@ -70,9 +72,9 @@ class IntegrateKitsuNote(pyblish.api.ContextPlugin): ) # If custom comment, create it - if self.CustomCommentTemplate["enabled"]: + if self.custom_comment_template["enabled"]: publish_comment = self.safe_format( - self.CustomCommentTemplate["comment_template"], + self.custom_comment_template["comment_template"], **instance.data, ) From c53e5b2302b9916360bf3e3a2f38e550596f64d8 Mon Sep 17 00:00:00 2001 From: Jacob Danell Date: Tue, 14 Mar 2023 18:32:41 +0100 Subject: [PATCH 09/23] Added docstring --- openpype/modules/kitsu/plugins/publish/integrate_kitsu_note.py | 2 ++ 1 file changed, 2 insertions(+) diff --git a/openpype/modules/kitsu/plugins/publish/integrate_kitsu_note.py b/openpype/modules/kitsu/plugins/publish/integrate_kitsu_note.py index debbfdf98e..a4b229d236 100644 --- a/openpype/modules/kitsu/plugins/publish/integrate_kitsu_note.py +++ b/openpype/modules/kitsu/plugins/publish/integrate_kitsu_note.py @@ -23,6 +23,8 @@ class IntegrateKitsuNote(pyblish.api.ContextPlugin): } def safe_format(self, msg, **kwargs): + """If key is not found in kwargs, set None instead""" + def replace_missing(match): value = kwargs.get(match.group(1), None) if value is None: From a789b135aed5d1dabdbee3b3ae14904a95b34428 Mon Sep 17 00:00:00 2001 From: Jacob Danell Date: Tue, 14 Mar 2023 18:33:00 +0100 Subject: [PATCH 10/23] Changed the instance check from render to review --- .../modules/kitsu/plugins/publish/integrate_kitsu_note.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/openpype/modules/kitsu/plugins/publish/integrate_kitsu_note.py b/openpype/modules/kitsu/plugins/publish/integrate_kitsu_note.py index a4b229d236..2e1e656cee 100644 --- a/openpype/modules/kitsu/plugins/publish/integrate_kitsu_note.py +++ b/openpype/modules/kitsu/plugins/publish/integrate_kitsu_note.py @@ -48,8 +48,8 @@ class IntegrateKitsuNote(pyblish.api.ContextPlugin): self.log.info("Comment is not set.") for instance in context: - # Check if instance is a render by checking its family - if "render" not in instance.data["family"]: + # Check if instance is a review by checking its family + if "review" not in instance.data["family"]: continue kitsu_task = instance.data.get("kitsu_task") From b3816ae876ff35d6187e43357d2580e46bafe2ae Mon Sep 17 00:00:00 2001 From: Jacob Danell Date: Wed, 15 Mar 2023 17:05:00 +0100 Subject: [PATCH 11/23] Fixed key check towards kwargs --- .../kitsu/plugins/publish/integrate_kitsu_note.py | 11 ++++------- 1 file changed, 4 insertions(+), 7 deletions(-) diff --git a/openpype/modules/kitsu/plugins/publish/integrate_kitsu_note.py b/openpype/modules/kitsu/plugins/publish/integrate_kitsu_note.py index 2e1e656cee..d4282ab048 100644 --- a/openpype/modules/kitsu/plugins/publish/integrate_kitsu_note.py +++ b/openpype/modules/kitsu/plugins/publish/integrate_kitsu_note.py @@ -16,7 +16,6 @@ class IntegrateKitsuNote(pyblish.api.ContextPlugin): note_status_shortname = "wfa" # comment settings - custom_comment_template = {} custom_comment_template = { "enabled": False, "comment_template": "{comment}", @@ -26,17 +25,15 @@ class IntegrateKitsuNote(pyblish.api.ContextPlugin): """If key is not found in kwargs, set None instead""" def replace_missing(match): - value = kwargs.get(match.group(1), None) - if value is None: + key = match.group(1) + if key not in kwargs: self.log.warning( "Key `{}` was not found in instance.data " - "and will be rendered as `` in the comment".format( - match.group(1) - ) + "and will be rendered as `` in the comment".format(key) ) return "" else: - return str(value) + return str(kwargs[key]) pattern = r"\{([^}]*)\}" return re.sub(pattern, replace_missing, msg) From a30887bb746ebba4756329cefb36eb4fa77d0db7 Mon Sep 17 00:00:00 2001 From: Jacob Danell Date: Wed, 15 Mar 2023 17:05:34 +0100 Subject: [PATCH 12/23] Change name from CamelCase to snake_case --- openpype/settings/defaults/project_settings/kitsu.json | 2 +- .../schemas/projects_schema/schema_project_kitsu.json | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/openpype/settings/defaults/project_settings/kitsu.json b/openpype/settings/defaults/project_settings/kitsu.json index f8a98d1a0b..738bd95e38 100644 --- a/openpype/settings/defaults/project_settings/kitsu.json +++ b/openpype/settings/defaults/project_settings/kitsu.json @@ -8,7 +8,7 @@ "IntegrateKitsuNote": { "set_status_note": false, "note_status_shortname": "wfa", - "CustomCommentTemplate": { + "custom_comment_template": { "enabled": false, "comment_template": "{comment}\n\n| | |\n|--|--|\n| version| `{version}` |\n| family | `{family}` |\n| name | `{name}` |" } diff --git a/openpype/settings/entities/schemas/projects_schema/schema_project_kitsu.json b/openpype/settings/entities/schemas/projects_schema/schema_project_kitsu.json index 1a7747b3dc..fc421c20f5 100644 --- a/openpype/settings/entities/schemas/projects_schema/schema_project_kitsu.json +++ b/openpype/settings/entities/schemas/projects_schema/schema_project_kitsu.json @@ -57,7 +57,7 @@ "type": "dict", "collapsible": true, "checkbox_key": "enabled", - "key": "CustomCommentTemplate", + "key": "custom_comment_template", "label": "Custom Comment Template", "children": [ { @@ -67,7 +67,7 @@ }, { "type": "label", - "label": "Kitsu supports markdown and here you can create a custom comment template.
You can use data from your instance's anatomy." + "label": "Kitsu supports markdown and here you can create a custom comment template.
You can use data from your publishing instance's data." }, { "key": "comment_template", From 8449c2131d49354b581e8db495b1b36b64f1a89f Mon Sep 17 00:00:00 2001 From: Petr Kalis Date: Wed, 15 Mar 2023 18:28:55 +0100 Subject: [PATCH 13/23] Extended Nuke testing classes with representation details --- .../nuke/test_deadline_publish_in_nuke.py | 18 +++++++++++ .../hosts/nuke/test_publish_in_nuke.py | 31 +++++++++++++++---- 2 files changed, 43 insertions(+), 6 deletions(-) diff --git a/tests/integration/hosts/nuke/test_deadline_publish_in_nuke.py b/tests/integration/hosts/nuke/test_deadline_publish_in_nuke.py index cd9cbb94f8..a4026f195b 100644 --- a/tests/integration/hosts/nuke/test_deadline_publish_in_nuke.py +++ b/tests/integration/hosts/nuke/test_deadline_publish_in_nuke.py @@ -71,12 +71,30 @@ class TestDeadlinePublishInNuke(NukeDeadlinePublishTestClass): failures.append( DBAssert.count_of_types(dbcon, "representation", 4)) + additional_args = {"context.subset": "workfileTest_task", + "context.ext": "nk"} + failures.append( + DBAssert.count_of_types(dbcon, "representation", 1, + additional_args=additional_args)) + additional_args = {"context.subset": "renderTest_taskMain", "context.ext": "exr"} failures.append( DBAssert.count_of_types(dbcon, "representation", 1, additional_args=additional_args)) + additional_args = {"context.subset": "renderTest_taskMain", + "name": "thumbnail"} + failures.append( + DBAssert.count_of_types(dbcon, "representation", 1, + additional_args=additional_args)) + + additional_args = {"context.subset": "renderTest_taskMain", + "name": "h264_mov"} + failures.append( + DBAssert.count_of_types(dbcon, "representation", 1, + additional_args=additional_args)) + assert not any(failures) diff --git a/tests/integration/hosts/nuke/test_publish_in_nuke.py b/tests/integration/hosts/nuke/test_publish_in_nuke.py index f84f13fa20..a4026f195b 100644 --- a/tests/integration/hosts/nuke/test_publish_in_nuke.py +++ b/tests/integration/hosts/nuke/test_publish_in_nuke.py @@ -1,12 +1,12 @@ import logging from tests.lib.assert_classes import DBAssert -from tests.integration.hosts.nuke.lib import NukeLocalPublishTestClass +from tests.integration.hosts.nuke.lib import NukeDeadlinePublishTestClass log = logging.getLogger("test_publish_in_nuke") -class TestPublishInNuke(NukeLocalPublishTestClass): +class TestDeadlinePublishInNuke(NukeDeadlinePublishTestClass): """Basic test case for publishing in Nuke Uses generic TestCase to prepare fixtures for test data, testing DBs, @@ -15,7 +15,7 @@ class TestPublishInNuke(NukeLocalPublishTestClass): !!! It expects modified path in WriteNode, use '[python {nuke.script_directory()}]' instead of regular root - dir (eg. instead of `c:/projects/test_project/test_asset/test_task`). + dir (eg. instead of `c:/projects`). Access file path by selecting WriteNode group, CTRL+Enter, update file input !!! @@ -36,12 +36,13 @@ class TestPublishInNuke(NukeLocalPublishTestClass): """ # https://drive.google.com/file/d/1SUurHj2aiQ21ZIMJfGVBI2KjR8kIjBGI/view?usp=sharing # noqa: E501 TEST_FILES = [ - ("1SUurHj2aiQ21ZIMJfGVBI2KjR8kIjBGI", "test_Nuke_publish.zip", "") + ("1SeWprClKhWMv2xVC9AcnekIJFExxnp_b", + "test_nuke_deadline_publish.zip", "") ] APP_GROUP = "nuke" - TIMEOUT = 50 # publish timeout + TIMEOUT = 180 # publish timeout # could be overwritten by command line arguments # keep empty to locate latest installed variant or explicit @@ -70,14 +71,32 @@ class TestPublishInNuke(NukeLocalPublishTestClass): failures.append( DBAssert.count_of_types(dbcon, "representation", 4)) + additional_args = {"context.subset": "workfileTest_task", + "context.ext": "nk"} + failures.append( + DBAssert.count_of_types(dbcon, "representation", 1, + additional_args=additional_args)) + additional_args = {"context.subset": "renderTest_taskMain", "context.ext": "exr"} failures.append( DBAssert.count_of_types(dbcon, "representation", 1, additional_args=additional_args)) + additional_args = {"context.subset": "renderTest_taskMain", + "name": "thumbnail"} + failures.append( + DBAssert.count_of_types(dbcon, "representation", 1, + additional_args=additional_args)) + + additional_args = {"context.subset": "renderTest_taskMain", + "name": "h264_mov"} + failures.append( + DBAssert.count_of_types(dbcon, "representation", 1, + additional_args=additional_args)) + assert not any(failures) if __name__ == "__main__": - test_case = TestPublishInNuke() + test_case = TestDeadlinePublishInNuke() From ce22b665b4b1ce1216f84156c09074cb6436545a Mon Sep 17 00:00:00 2001 From: Jacob Danell Date: Thu, 16 Mar 2023 10:39:47 +0100 Subject: [PATCH 14/23] Fixed comments in code --- .../kitsu/plugins/publish/integrate_kitsu_note.py | 13 ++++++++----- 1 file changed, 8 insertions(+), 5 deletions(-) diff --git a/openpype/modules/kitsu/plugins/publish/integrate_kitsu_note.py b/openpype/modules/kitsu/plugins/publish/integrate_kitsu_note.py index d4282ab048..69b456426f 100644 --- a/openpype/modules/kitsu/plugins/publish/integrate_kitsu_note.py +++ b/openpype/modules/kitsu/plugins/publish/integrate_kitsu_note.py @@ -22,21 +22,24 @@ class IntegrateKitsuNote(pyblish.api.ContextPlugin): } def safe_format(self, msg, **kwargs): - """If key is not found in kwargs, set None instead""" + """Pars the msg thourgh a custom format code. + It makes sure non existing keys gets None returned instead of error + """ - def replace_missing(match): + def replace_missing_key(match): + """If key is not found in kwargs, set None instead""" key = match.group(1) if key not in kwargs: self.log.warning( - "Key `{}` was not found in instance.data " - "and will be rendered as `` in the comment".format(key) + "Key '{}' was not found in instance.data " + "and will be rendered as '' in the comment".format(key) ) return "" else: return str(kwargs[key]) pattern = r"\{([^}]*)\}" - return re.sub(pattern, replace_missing, msg) + return re.sub(pattern, replace_missing_key, msg) def process(self, context): # Get comment text body From adc648616f2eebe7780a81de5882bf95e805ddf9 Mon Sep 17 00:00:00 2001 From: Jacob Danell Date: Thu, 16 Mar 2023 10:40:03 +0100 Subject: [PATCH 15/23] Look for review in families instead of family --- openpype/modules/kitsu/plugins/publish/integrate_kitsu_note.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/openpype/modules/kitsu/plugins/publish/integrate_kitsu_note.py b/openpype/modules/kitsu/plugins/publish/integrate_kitsu_note.py index 69b456426f..3ad53a1f12 100644 --- a/openpype/modules/kitsu/plugins/publish/integrate_kitsu_note.py +++ b/openpype/modules/kitsu/plugins/publish/integrate_kitsu_note.py @@ -49,7 +49,7 @@ class IntegrateKitsuNote(pyblish.api.ContextPlugin): for instance in context: # Check if instance is a review by checking its family - if "review" not in instance.data["family"]: + if "review" not in instance.data["families"]: continue kitsu_task = instance.data.get("kitsu_task") From f70eac116d1978a337c8adc912413ab5a12bd842 Mon Sep 17 00:00:00 2001 From: Jacob Danell Date: Thu, 16 Mar 2023 17:11:16 +0100 Subject: [PATCH 16/23] Made the format function more logical --- .../plugins/publish/integrate_kitsu_note.py | 25 +++++++++---------- 1 file changed, 12 insertions(+), 13 deletions(-) diff --git a/openpype/modules/kitsu/plugins/publish/integrate_kitsu_note.py b/openpype/modules/kitsu/plugins/publish/integrate_kitsu_note.py index 3ad53a1f12..b0063282d0 100644 --- a/openpype/modules/kitsu/plugins/publish/integrate_kitsu_note.py +++ b/openpype/modules/kitsu/plugins/publish/integrate_kitsu_note.py @@ -21,25 +21,27 @@ class IntegrateKitsuNote(pyblish.api.ContextPlugin): "comment_template": "{comment}", } - def safe_format(self, msg, **kwargs): - """Pars the msg thourgh a custom format code. - It makes sure non existing keys gets None returned instead of error - """ + def format_publish_comment(self, instance): + """Format the instance's publish comment + Formats `instance.data` against the custom template. + """ + def replace_missing_key(match): """If key is not found in kwargs, set None instead""" key = match.group(1) - if key not in kwargs: + if key not in instance.data: self.log.warning( - "Key '{}' was not found in instance.data " - "and will be rendered as '' in the comment".format(key) + "Key "{}" was not found in instance.data " + "and will be rendered as "" in the comment".format(key) ) return "" else: - return str(kwargs[key]) + return str(instance.data[key]) + template = self.custom_comment_template["comment_template"] pattern = r"\{([^}]*)\}" - return re.sub(pattern, replace_missing_key, msg) + return re.sub(pattern, replace_missing_key, template) def process(self, context): # Get comment text body @@ -75,10 +77,7 @@ class IntegrateKitsuNote(pyblish.api.ContextPlugin): # If custom comment, create it if self.custom_comment_template["enabled"]: - publish_comment = self.safe_format( - self.custom_comment_template["comment_template"], - **instance.data, - ) + publish_comment = self.format_publish_comment(instance) self.log.debug("Comment is `{}`".format(publish_comment)) From 5a7bf785f72d4dacbf9283ee362f447991db2de8 Mon Sep 17 00:00:00 2001 From: Jacob Danell Date: Thu, 16 Mar 2023 17:13:17 +0100 Subject: [PATCH 17/23] Fixed hound comments --- .../modules/kitsu/plugins/publish/integrate_kitsu_note.py | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/openpype/modules/kitsu/plugins/publish/integrate_kitsu_note.py b/openpype/modules/kitsu/plugins/publish/integrate_kitsu_note.py index b0063282d0..a5a58c8462 100644 --- a/openpype/modules/kitsu/plugins/publish/integrate_kitsu_note.py +++ b/openpype/modules/kitsu/plugins/publish/integrate_kitsu_note.py @@ -26,14 +26,15 @@ class IntegrateKitsuNote(pyblish.api.ContextPlugin): Formats `instance.data` against the custom template. """ - + def replace_missing_key(match): """If key is not found in kwargs, set None instead""" key = match.group(1) if key not in instance.data: self.log.warning( - "Key "{}" was not found in instance.data " - "and will be rendered as "" in the comment".format(key) + "Key '{}' was not found in instance.data " + "and will be rendered as " + " in the comment".format(key) ) return "" else: From c86e8e1d6ea0ae292fe414d5c499451884b230e1 Mon Sep 17 00:00:00 2001 From: Jacob Danell Date: Fri, 17 Mar 2023 16:22:01 +0100 Subject: [PATCH 18/23] Added empty line in the end VSC removed it automatically before. --- openpype/settings/defaults/project_settings/kitsu.json | 2 +- .../entities/schemas/projects_schema/schema_project_kitsu.json | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/openpype/settings/defaults/project_settings/kitsu.json b/openpype/settings/defaults/project_settings/kitsu.json index 738bd95e38..11c138e8e5 100644 --- a/openpype/settings/defaults/project_settings/kitsu.json +++ b/openpype/settings/defaults/project_settings/kitsu.json @@ -14,4 +14,4 @@ } } } -} \ No newline at end of file +} diff --git a/openpype/settings/entities/schemas/projects_schema/schema_project_kitsu.json b/openpype/settings/entities/schemas/projects_schema/schema_project_kitsu.json index fc421c20f5..7ceb979d6f 100644 --- a/openpype/settings/entities/schemas/projects_schema/schema_project_kitsu.json +++ b/openpype/settings/entities/schemas/projects_schema/schema_project_kitsu.json @@ -82,4 +82,4 @@ ] } ] -} \ No newline at end of file +} From 8a91e4aaa07dc10ae0d0c373749af103e284e5a7 Mon Sep 17 00:00:00 2001 From: Jacob Danell Date: Fri, 17 Mar 2023 16:22:28 +0100 Subject: [PATCH 19/23] Fixed comment --- .../modules/kitsu/plugins/publish/integrate_kitsu_note.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/openpype/modules/kitsu/plugins/publish/integrate_kitsu_note.py b/openpype/modules/kitsu/plugins/publish/integrate_kitsu_note.py index a5a58c8462..67702578c5 100644 --- a/openpype/modules/kitsu/plugins/publish/integrate_kitsu_note.py +++ b/openpype/modules/kitsu/plugins/publish/integrate_kitsu_note.py @@ -33,8 +33,8 @@ class IntegrateKitsuNote(pyblish.api.ContextPlugin): if key not in instance.data: self.log.warning( "Key '{}' was not found in instance.data " - "and will be rendered as " - " in the comment".format(key) + "and will be rendered as an empty string " + "in the comment".format(key) ) return "" else: From 94ba8151e72b6d069d8a72fb74477a6ad0f7739c Mon Sep 17 00:00:00 2001 From: Jacob Danell Date: Fri, 17 Mar 2023 16:23:13 +0100 Subject: [PATCH 20/23] Read the comment from the instance instead from the context --- .../kitsu/plugins/publish/integrate_kitsu_note.py | 13 ++++++------- 1 file changed, 6 insertions(+), 7 deletions(-) diff --git a/openpype/modules/kitsu/plugins/publish/integrate_kitsu_note.py b/openpype/modules/kitsu/plugins/publish/integrate_kitsu_note.py index 67702578c5..cf36bbc4fe 100644 --- a/openpype/modules/kitsu/plugins/publish/integrate_kitsu_note.py +++ b/openpype/modules/kitsu/plugins/publish/integrate_kitsu_note.py @@ -45,11 +45,6 @@ class IntegrateKitsuNote(pyblish.api.ContextPlugin): return re.sub(pattern, replace_missing_key, template) def process(self, context): - # Get comment text body - publish_comment = context.data.get("comment") - if not publish_comment: - self.log.info("Comment is not set.") - for instance in context: # Check if instance is a review by checking its family if "review" not in instance.data["families"]: @@ -76,11 +71,15 @@ class IntegrateKitsuNote(pyblish.api.ContextPlugin): "changed!".format(self.note_status_shortname) ) - # If custom comment, create it + # Get comment text body + publish_comment = instance.data.get("comment") if self.custom_comment_template["enabled"]: publish_comment = self.format_publish_comment(instance) - self.log.debug("Comment is `{}`".format(publish_comment)) + if not publish_comment: + self.log.info("Comment is not set.") + else: + self.log.debug("Comment is `{}`".format(publish_comment)) # Add comment to kitsu task task_id = kitsu_task["id"] From 4506a2f3ef3e7fe7b7002d89266fdb8dfb6ce8da Mon Sep 17 00:00:00 2001 From: Petr Kalis Date: Mon, 20 Mar 2023 13:41:17 +0100 Subject: [PATCH 21/23] Fix broken Nuke local test Accidentally used DL version --- tests/integration/hosts/nuke/test_publish_in_nuke.py | 11 +++++------ 1 file changed, 5 insertions(+), 6 deletions(-) diff --git a/tests/integration/hosts/nuke/test_publish_in_nuke.py b/tests/integration/hosts/nuke/test_publish_in_nuke.py index a4026f195b..bfd84e4fd5 100644 --- a/tests/integration/hosts/nuke/test_publish_in_nuke.py +++ b/tests/integration/hosts/nuke/test_publish_in_nuke.py @@ -1,12 +1,12 @@ import logging from tests.lib.assert_classes import DBAssert -from tests.integration.hosts.nuke.lib import NukeDeadlinePublishTestClass +from tests.integration.hosts.nuke.lib import NukeLocalPublishTestClass log = logging.getLogger("test_publish_in_nuke") -class TestDeadlinePublishInNuke(NukeDeadlinePublishTestClass): +class TestPublishInNuke(NukeLocalPublishTestClass): """Basic test case for publishing in Nuke Uses generic TestCase to prepare fixtures for test data, testing DBs, @@ -36,13 +36,12 @@ class TestDeadlinePublishInNuke(NukeDeadlinePublishTestClass): """ # https://drive.google.com/file/d/1SUurHj2aiQ21ZIMJfGVBI2KjR8kIjBGI/view?usp=sharing # noqa: E501 TEST_FILES = [ - ("1SeWprClKhWMv2xVC9AcnekIJFExxnp_b", - "test_nuke_deadline_publish.zip", "") + ("1SUurHj2aiQ21ZIMJfGVBI2KjR8kIjBGI", "test_Nuke_publish.zip", "") ] APP_GROUP = "nuke" - TIMEOUT = 180 # publish timeout + TIMEOUT = 50 # publish timeout # could be overwritten by command line arguments # keep empty to locate latest installed variant or explicit @@ -99,4 +98,4 @@ class TestDeadlinePublishInNuke(NukeDeadlinePublishTestClass): if __name__ == "__main__": - test_case = TestDeadlinePublishInNuke() + test_case = TestPublishInNuke() From 71a28cb76048d0fa057f2ec6ede62fe84fe54587 Mon Sep 17 00:00:00 2001 From: Roy Nieterau Date: Tue, 21 Mar 2023 10:09:36 +0100 Subject: [PATCH 22/23] Scene inventory: Fix code errors when "not found" entries are found (#4594) * Avoid VersionDelegate error if version value is not set, e.g. for NOT FOUND instances * Ignore items without `representation` data * Add not found items per container into the model like regular containers * Do not provide set version + remove options for NOT FOUND items --- openpype/tools/sceneinventory/model.py | 16 ++++++++-------- openpype/tools/sceneinventory/view.py | 7 +++++++ openpype/tools/utils/delegates.py | 8 +++++--- 3 files changed, 20 insertions(+), 11 deletions(-) diff --git a/openpype/tools/sceneinventory/model.py b/openpype/tools/sceneinventory/model.py index 680dfd5a51..63d2945145 100644 --- a/openpype/tools/sceneinventory/model.py +++ b/openpype/tools/sceneinventory/model.py @@ -327,7 +327,7 @@ class InventoryModel(TreeModel): project_name, repre_id ) if not representation: - not_found["representation"].append(group_items) + not_found["representation"].extend(group_items) not_found_ids.append(repre_id) continue @@ -335,7 +335,7 @@ class InventoryModel(TreeModel): project_name, representation["parent"] ) if not version: - not_found["version"].append(group_items) + not_found["version"].extend(group_items) not_found_ids.append(repre_id) continue @@ -348,13 +348,13 @@ class InventoryModel(TreeModel): subset = get_subset_by_id(project_name, version["parent"]) if not subset: - not_found["subset"].append(group_items) + not_found["subset"].extend(group_items) not_found_ids.append(repre_id) continue asset = get_asset_by_id(project_name, subset["parent"]) if not asset: - not_found["asset"].append(group_items) + not_found["asset"].extend(group_items) not_found_ids.append(repre_id) continue @@ -380,11 +380,11 @@ class InventoryModel(TreeModel): self.add_child(group_node, parent=parent) - for _group_items in group_items: + for item in group_items: item_node = Item() - item_node["Name"] = ", ".join( - [item["objectName"] for item in _group_items] - ) + item_node.update(item) + item_node["Name"] = item.get("objectName", "NO NAME") + item_node["isNotFound"] = True self.add_child(item_node, parent=group_node) for repre_id, group_dict in sorted(grouped.items()): diff --git a/openpype/tools/sceneinventory/view.py b/openpype/tools/sceneinventory/view.py index a04171e429..3279be6094 100644 --- a/openpype/tools/sceneinventory/view.py +++ b/openpype/tools/sceneinventory/view.py @@ -80,9 +80,16 @@ class SceneInventoryView(QtWidgets.QTreeView): self.setStyleSheet("QTreeView {}") def _build_item_menu_for_selection(self, items, menu): + + # Exclude items that are "NOT FOUND" since setting versions, updating + # and removal won't work for those items. + items = [item for item in items if not item.get("isNotFound")] + if not items: return + # An item might not have a representation, for example when an item + # is listed as "NOT FOUND" repre_ids = { item["representation"] for item in items diff --git a/openpype/tools/utils/delegates.py b/openpype/tools/utils/delegates.py index d76284afb1..fa69113ef1 100644 --- a/openpype/tools/utils/delegates.py +++ b/openpype/tools/utils/delegates.py @@ -30,9 +30,11 @@ class VersionDelegate(QtWidgets.QStyledItemDelegate): def displayText(self, value, locale): if isinstance(value, HeroVersionType): return lib.format_version(value, True) - assert isinstance(value, numbers.Integral), ( - "Version is not integer. \"{}\" {}".format(value, str(type(value))) - ) + if not isinstance(value, numbers.Integral): + # For cases where no version is resolved like NOT FOUND cases + # where a representation might not exist in current database + return + return lib.format_version(value) def paint(self, painter, option, index): From a0c599203e992b8aea3f7898ce040362e3c11032 Mon Sep 17 00:00:00 2001 From: Petr Kalis Date: Tue, 21 Mar 2023 10:42:06 +0100 Subject: [PATCH 23/23] Global: add tags field to thumbnail representation (#4660) * Fix add tags field to thumbnail representation Co-authored-by: Jakub Trllo <43494761+iLLiCiTiT@users.noreply.github.com> --- .../plugins/publish/preintegrate_thumbnail_representation.py | 2 ++ 1 file changed, 2 insertions(+) diff --git a/openpype/plugins/publish/preintegrate_thumbnail_representation.py b/openpype/plugins/publish/preintegrate_thumbnail_representation.py index b88ccee9dc..1c95b82c97 100644 --- a/openpype/plugins/publish/preintegrate_thumbnail_representation.py +++ b/openpype/plugins/publish/preintegrate_thumbnail_representation.py @@ -60,6 +60,8 @@ class PreIntegrateThumbnails(pyblish.api.InstancePlugin): if not found_profile: return + thumbnail_repre.setdefault("tags", []) + if not found_profile["integrate_thumbnail"]: if "delete" not in thumbnail_repre["tags"]: thumbnail_repre["tags"].append("delete")