From 8f1ff9e31b07f7a46c21f59bb4ff1d20669126f6 Mon Sep 17 00:00:00 2001 From: Milan Kolar Date: Thu, 31 Oct 2019 20:07:03 +0100 Subject: [PATCH 01/12] update changelog and version --- pype/__init__.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pype/__init__.py b/pype/__init__.py index c2311dd528..91b72d7de5 100644 --- a/pype/__init__.py +++ b/pype/__init__.py @@ -9,7 +9,7 @@ from pypeapp import config import logging log = logging.getLogger(__name__) -__version__ = "2.1.0" +__version__ = "2.3.0" PACKAGE_DIR = os.path.dirname(__file__) PLUGINS_DIR = os.path.join(PACKAGE_DIR, "plugins") From 2c6b451485e3324846b386bbcd8d7c3eda70011d Mon Sep 17 00:00:00 2001 From: Milan Kolar Date: Thu, 31 Oct 2019 20:15:13 +0100 Subject: [PATCH 02/12] update chagnelog --- changelog.md | 38 ++++++++++++++++++++++++++++++++++++++ 1 file changed, 38 insertions(+) diff --git a/changelog.md b/changelog.md index 46cceb9fdc..c49ad56561 100644 --- a/changelog.md +++ b/changelog.md @@ -1,6 +1,44 @@ # Pype changelog # Welcome to pype changelog +## 2.3.0 ## +_release date: 1 Oct 2019_ + +**new**: +- _(maya)_ support for yeti rigs and yeti caches +- _(maya)_ validator for comparing arbitrary attributes against ftrack +- _(pype)_ burnins can now show current date and time +- _(muster)_ pools can now be set in render globals in maya +- _(pype)_ Rest API has been implemented in beta stage +- _(nuke)_ LUT loader has been added +- _(pype)_ rudimentary user module has been added as preparation for user management +- _(pype)_ a simple logging GUI has been added to pype tray +- _(nuke)_ nuke can now bake input process into mov +- _(maya)_ imported models now have selection handle displayed by defaulting +- _(avalon)_ it's is now possible to load multiple assets at once using loader + +**changed**: +- _(ftrack)_ event server now runs two paraller processes and is able to keep queue of events to process. +- _(nuke)_ task name is now added to all rendered subsets +- _(pype)_ adding more families to standalone publisher +- _(pype)_ standalone publisher now uses pyblish-lite +- _(pype)_ standalone publisher can now create review quicktimes +- _(ftrack)_ queries to ftrack were sped up +- _(ftrack)_ multiple ftrack action have been deprecated +- _(avalon)_ avalon upstream has been updated to 5.5.0 +- _(nukestudio)_ published transforms can now be animated +- + +**fix**: +- _(maya)_ fps popup button didn't work in some cases +- _(maya)_ geometry instances and references in maya were losing shader assignments +- _(muster)_ muster rendering templates were not working correctly +- _(maya)_ arnold tx texture conversion wasn't respecting colorspace set by the artist +- _(pype)_ problems with avalon db sync +- _(maya)_ ftrack was rounding FPS making it inconsistent +- _(pype)_ wrong icon names in Creator +- _(avalon)_ updated to + ## 2.2.0 ## _release date: 8 Sept 2019_ From 00b497cc21e9eff8a4976ecb173cdf3ff945eff0 Mon Sep 17 00:00:00 2001 From: Milan Kolar Date: Thu, 31 Oct 2019 20:16:16 +0100 Subject: [PATCH 03/12] update changelog --- changelog.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/changelog.md b/changelog.md index c49ad56561..ebf07db125 100644 --- a/changelog.md +++ b/changelog.md @@ -37,7 +37,7 @@ _release date: 1 Oct 2019_ - _(pype)_ problems with avalon db sync - _(maya)_ ftrack was rounding FPS making it inconsistent - _(pype)_ wrong icon names in Creator -- _(avalon)_ updated to +- _(maya)_ scene inventory wasn't showing anything if representation was removed from database after it's been loaded to the scene ## 2.2.0 ## _release date: 8 Sept 2019_ From c009f661e6f389fac532a9a794a95ff3f79a92f1 Mon Sep 17 00:00:00 2001 From: Jana Mizikova Date: Fri, 1 Nov 2019 17:06:35 +0100 Subject: [PATCH 04/12] fix(nks): thumbnails, build workfile with preview mov - thumbnail for clip is taken from middle of duration --- pype/nuke/lib.py | 4 +++- pype/plugins/nukestudio/publish/collect_plates.py | 6 ++++-- pype/plugins/nukestudio/publish/collect_reviews.py | 11 ++++++++--- 3 files changed, 15 insertions(+), 6 deletions(-) diff --git a/pype/nuke/lib.py b/pype/nuke/lib.py index f182088457..cd809bf640 100644 --- a/pype/nuke/lib.py +++ b/pype/nuke/lib.py @@ -927,7 +927,7 @@ class BuildWorkfile(WorkfileSettings): def process(self, regex_filter=None, version=None, - representations=["exr", "dpx", "lutJson"]): + representations=["exr", "dpx", "lutJson", "mov", "preview"]): """ A short description. @@ -984,6 +984,8 @@ class BuildWorkfile(WorkfileSettings): version=version, representations=representations) + log.info("__ subsets: `{}`".format(subsets)) + nodes_backdrop = list() for name, subset in subsets.items(): diff --git a/pype/plugins/nukestudio/publish/collect_plates.py b/pype/plugins/nukestudio/publish/collect_plates.py index 2ebbfde551..f9eb126772 100644 --- a/pype/plugins/nukestudio/publish/collect_plates.py +++ b/pype/plugins/nukestudio/publish/collect_plates.py @@ -196,12 +196,14 @@ class CollectPlatesData(api.InstancePlugin): thumb_file = head + ".png" thumb_path = os.path.join(staging_dir, thumb_file) + thumb_frame = instance.data["sourceIn"] + ((instance.data["sourceOut"] - instance.data["sourceIn"])/2) - thumbnail = item.thumbnail(instance.data["sourceIn"]).save( + thumbnail = item.thumbnail(thumb_frame).save( thumb_path, format='png' ) - self.log.debug("__ thumbnail: {}".format(thumbnail)) + self.log.debug("__ sourceIn: `{}`".format(instance.data["sourceIn"])) + self.log.debug("__ thumbnail: `{}`, frame: `{}`".format(thumbnail, thumb_frame)) thumb_representation = { 'files': thumb_file, diff --git a/pype/plugins/nukestudio/publish/collect_reviews.py b/pype/plugins/nukestudio/publish/collect_reviews.py index 9fab0f0741..f9032b2ca4 100644 --- a/pype/plugins/nukestudio/publish/collect_reviews.py +++ b/pype/plugins/nukestudio/publish/collect_reviews.py @@ -106,7 +106,6 @@ class CollectReviews(api.InstancePlugin): def create_thumbnail(self, instance): item = instance.data["item"] - source_in = instance.data["sourceIn"] source_path = instance.data["sourcePath"] source_file = os.path.basename(source_path) @@ -119,11 +118,17 @@ class CollectReviews(api.InstancePlugin): thumb_file = head + ".png" thumb_path = os.path.join(staging_dir, thumb_file) self.log.debug("__ thumb_path: {}".format(thumb_path)) - self.log.debug("__ source_in: {}".format(source_in)) - thumbnail = item.thumbnail(source_in).save( + + thumb_frame = instance.data["sourceIn"] + ((instance.data["sourceOut"] - instance.data["sourceIn"])/2) + + thumbnail = item.thumbnail(thumb_frame).save( thumb_path, format='png' ) + + self.log.debug("__ sourceIn: `{}`".format(instance.data["sourceIn"])) + self.log.debug("__ thumbnail: `{}`, frame: `{}`".format(thumbnail, thumb_frame)) + self.log.debug("__ thumbnail: {}".format(thumbnail)) thumb_representation = { From 66544273fd08fc22aedc4267b5716d0dbb8abd23 Mon Sep 17 00:00:00 2001 From: Ondrej Samohel Date: Fri, 1 Nov 2019 19:06:00 +0100 Subject: [PATCH 05/12] connect shapes to loaded Yeti Rig --- pype/plugins/maya/load/load_yeti_rig.py | 52 +++++++++++++++++++++++-- 1 file changed, 49 insertions(+), 3 deletions(-) diff --git a/pype/plugins/maya/load/load_yeti_rig.py b/pype/plugins/maya/load/load_yeti_rig.py index eb75ff6bdc..a3e03e8a6c 100644 --- a/pype/plugins/maya/load/load_yeti_rig.py +++ b/pype/plugins/maya/load/load_yeti_rig.py @@ -1,9 +1,17 @@ -import pype.maya.plugin import os +from collections import defaultdict + from pypeapp import config +import pype.maya.plugin +from pype.maya import lib class YetiRigLoader(pype.maya.plugin.ReferenceLoader): + """ + This loader will load Yeti rig. You can select something in scene and if it + has same ID as mesh published with rig, their shapes will be linked + together. + """ families = ["yetiRig"] representations = ["ma"] @@ -18,6 +26,32 @@ class YetiRigLoader(pype.maya.plugin.ReferenceLoader): import maya.cmds as cmds from avalon import maya + # get roots of selected hierarchies + selected_roots = [] + for sel in cmds.ls(sl=True, long=True): + selected_roots.append(sel.split("|")[1]) + + # get all objects under those roots + selected_hierarchy = [] + for root in selected_roots: + selected_hierarchy.append(cmds.listRelatives( + root, + allDescendents=True) or []) + + # flatten the list and filter only shapes + shapes_flat = [] + for root in selected_hierarchy: + shapes = cmds.ls(root, long=True, type="mesh") or [] + for shape in shapes: + shapes_flat.append(shape) + + # create dictionary of cbId and shape nodes + scene_lookup = defaultdict(list) + for node in shapes_flat: + cb_id = lib.get_id(node) + scene_lookup[cb_id] = node + + # load rig with maya.maintained_selection(): nodes = cmds.file(self.fname, namespace=namespace, @@ -26,6 +60,20 @@ class YetiRigLoader(pype.maya.plugin.ReferenceLoader): groupReference=True, groupName="{}:{}".format(namespace, name)) + # for every shape node we've just loaded find matching shape by its + # cbId in selection. If found outMesh of scene shape will connect to + # inMesh of loaded shape. + for destination_node in nodes: + source_node = scene_lookup[lib.get_id(destination_node)] + if source_node: + self.log.info("found: {}".format(source_node)) + self.log.info( + "creating connection to {}".format(destination_node)) + + cmds.connectAttr("{}.outMesh".format(source_node), + "{}.inMesh".format(destination_node), + force=True) + groupName = "{}:{}".format(namespace, name) presets = config.get_presets(project=os.environ['AVALON_PROJECT']) @@ -38,6 +86,4 @@ class YetiRigLoader(pype.maya.plugin.ReferenceLoader): c[0], c[1], c[2]) self[:] = nodes - self.log.info("Yeti Rig Connection Manager will be available soon") - return nodes From 95655d005693f37cd0590803751c54c830f557a0 Mon Sep 17 00:00:00 2001 From: Ondrej Samohel Date: Mon, 4 Nov 2019 16:04:54 +0100 Subject: [PATCH 06/12] added texture extraction to yeti rig extractor --- pype/plugins/maya/publish/extract_yeti_rig.py | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/pype/plugins/maya/publish/extract_yeti_rig.py b/pype/plugins/maya/publish/extract_yeti_rig.py index b575c07cf4..892bc0bea6 100644 --- a/pype/plugins/maya/publish/extract_yeti_rig.py +++ b/pype/plugins/maya/publish/extract_yeti_rig.py @@ -126,6 +126,18 @@ class ExtractYetiRig(pype.api.Extractor): with open(settings_path, "w") as fp: json.dump(settings, fp, ensure_ascii=False) + # add textures to transfers + if 'transfers' not in instance.data: + instance.data['transfers'] = [] + + for resource in instance.data.get('resources', []): + for file in resource['files']: + src = file + dst = os.path.join(image_search_path, os.path.basename(file)) + instance.data['transfers'].append([src, dst]) + + self.log.info("adding transfer {} -> {}". format(src, dst)) + # Ensure the imageSearchPath is being remapped to the publish folder attr_value = {"%s.imageSearchPath" % n: str(image_search_path) for n in yeti_nodes} From 26454a752b506a5fffd698cee612164c8ac67feb Mon Sep 17 00:00:00 2001 From: iLLiCiTiT Date: Tue, 5 Nov 2019 10:23:49 +0100 Subject: [PATCH 07/12] fixed not crashing event thumbnail updates if thumbnail is not happening on task --- pype/ftrack/events/event_thumbnail_updates.py | 25 ++++++++++++------- 1 file changed, 16 insertions(+), 9 deletions(-) diff --git a/pype/ftrack/events/event_thumbnail_updates.py b/pype/ftrack/events/event_thumbnail_updates.py index ae6f8adb5e..65c81f6545 100644 --- a/pype/ftrack/events/event_thumbnail_updates.py +++ b/pype/ftrack/events/event_thumbnail_updates.py @@ -20,7 +20,8 @@ class ThumbnailEvents(BaseEvent): if parent.get('thumbnail') and not task.get('thumbnail'): task['thumbnail'] = parent['thumbnail'] self.log.info('>>> Updated thumbnail on [ %s/%s ]'.format( - parent['name'], task['name'])) + parent['name'], task['name'] + )) # Update task thumbnail from published version # if (entity['entityType'] == 'assetversion' and @@ -32,18 +33,24 @@ class ThumbnailEvents(BaseEvent): version = session.get('AssetVersion', entity['entityId']) thumbnail = version.get('thumbnail') - task = version['task'] - if thumbnail: - task['thumbnail'] = thumbnail - task['parent']['thumbnail'] = thumbnail - self.log.info('>>> Updating thumbnail for task and shot\ - [ {} ]'.format(task['name'])) + parent = version['asset']['parent'] + task = version['task'] + parent['thumbnail_id'] = version['thumbnail_id'] + if parent.entity_type.lower() == "project": + name = parent["full_name"] + else: + name = parent["name"] + msg = '>>> Updating thumbnail for shot [ {} ]'.format(name) + + if task: + task['thumbnail_id'] = asset_version['thumbnail_id'] + msg += " and task [ {} ]".format(task["name"])) + + self.log.info(msg) session.commit() - pass - def register(session, plugins_presets): '''Register plugin. Called when used as an plugin.''' From b3dbf0f228131b3ffaae6208123feee7cf2c62bf Mon Sep 17 00:00:00 2001 From: iLLiCiTiT Date: Tue, 5 Nov 2019 10:29:02 +0100 Subject: [PATCH 08/12] variable name fix --- pype/ftrack/events/event_thumbnail_updates.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pype/ftrack/events/event_thumbnail_updates.py b/pype/ftrack/events/event_thumbnail_updates.py index 65c81f6545..620d1a5b72 100644 --- a/pype/ftrack/events/event_thumbnail_updates.py +++ b/pype/ftrack/events/event_thumbnail_updates.py @@ -44,7 +44,7 @@ class ThumbnailEvents(BaseEvent): msg = '>>> Updating thumbnail for shot [ {} ]'.format(name) if task: - task['thumbnail_id'] = asset_version['thumbnail_id'] + task['thumbnail_id'] = version['thumbnail_id'] msg += " and task [ {} ]".format(task["name"])) self.log.info(msg) From b22f7536caa25754d0f82aeb080287ff8f9d5bfa Mon Sep 17 00:00:00 2001 From: iLLiCiTiT Date: Tue, 5 Nov 2019 18:27:09 +0100 Subject: [PATCH 09/12] moved pymel.core imports to process parts of actions to not slow down discover --- pype/plugins/maya/load/load_ass.py | 2 +- pype/plugins/maya/load/load_gpucache.py | 1 - pype/plugins/maya/load/load_image_plane.py | 4 ++-- pype/plugins/maya/load/load_reference.py | 5 ++--- 4 files changed, 5 insertions(+), 7 deletions(-) diff --git a/pype/plugins/maya/load/load_ass.py b/pype/plugins/maya/load/load_ass.py index 979d4b5767..2960e4403e 100644 --- a/pype/plugins/maya/load/load_ass.py +++ b/pype/plugins/maya/load/load_ass.py @@ -1,7 +1,6 @@ from avalon import api import pype.maya.plugin import os -import pymel.core as pm from pypeapp import config @@ -70,6 +69,7 @@ class AssProxyLoader(pype.maya.plugin.ReferenceLoader): import os from maya import cmds + import pymel.core as pm node = container["objectName"] diff --git a/pype/plugins/maya/load/load_gpucache.py b/pype/plugins/maya/load/load_gpucache.py index b98ca8b7f4..9e7938777e 100644 --- a/pype/plugins/maya/load/load_gpucache.py +++ b/pype/plugins/maya/load/load_gpucache.py @@ -2,7 +2,6 @@ from avalon import api import pype.maya.plugin import os from pypeapp import config -import pymel.core as pm reload(config) diff --git a/pype/plugins/maya/load/load_image_plane.py b/pype/plugins/maya/load/load_image_plane.py index e2d94ac82e..e95ea6cd8f 100644 --- a/pype/plugins/maya/load/load_image_plane.py +++ b/pype/plugins/maya/load/load_image_plane.py @@ -1,5 +1,3 @@ -import pymel.core as pc - from avalon import api from Qt import QtWidgets @@ -14,6 +12,8 @@ class ImagePlaneLoader(api.Loader): color = "orange" def load(self, context, name, namespace, data): + import pymel.core as pc + new_nodes = [] image_plane_depth = 1000 diff --git a/pype/plugins/maya/load/load_reference.py b/pype/plugins/maya/load/load_reference.py index a754c3be98..55db019cf4 100644 --- a/pype/plugins/maya/load/load_reference.py +++ b/pype/plugins/maya/load/load_reference.py @@ -1,8 +1,6 @@ - import pype.maya.plugin import os from pypeapp import config -import pymel.core as pm reload(config) import pype.maya.plugin reload(pype.maya.plugin) @@ -20,9 +18,10 @@ class ReferenceLoader(pype.maya.plugin.ReferenceLoader): color = "orange" def process_reference(self, context, name, namespace, data): - import maya.cmds as cmds from avalon import maya + import pymel.core as pm + try: family = context["representation"]["context"]["family"] From 9d32095c3a161a06f74c4f52235cb600e9628f02 Mon Sep 17 00:00:00 2001 From: Milan Kolar Date: Wed, 6 Nov 2019 10:38:18 +0100 Subject: [PATCH 10/12] update changelog --- changelog.md | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/changelog.md b/changelog.md index ebf07db125..bdee041615 100644 --- a/changelog.md +++ b/changelog.md @@ -2,7 +2,7 @@ Welcome to pype changelog ## 2.3.0 ## -_release date: 1 Oct 2019_ +_release date: 6 Oct 2019_ **new**: - _(maya)_ support for yeti rigs and yeti caches @@ -16,9 +16,10 @@ _release date: 1 Oct 2019_ - _(nuke)_ nuke can now bake input process into mov - _(maya)_ imported models now have selection handle displayed by defaulting - _(avalon)_ it's is now possible to load multiple assets at once using loader +- _(maya)_ added ability to automatically connect yeti rig to a mesh upon loading **changed**: -- _(ftrack)_ event server now runs two paraller processes and is able to keep queue of events to process. +- _(ftrack)_ event server now runs two parallel processes and is able to keep queue of events to process. - _(nuke)_ task name is now added to all rendered subsets - _(pype)_ adding more families to standalone publisher - _(pype)_ standalone publisher now uses pyblish-lite @@ -38,6 +39,8 @@ _release date: 1 Oct 2019_ - _(maya)_ ftrack was rounding FPS making it inconsistent - _(pype)_ wrong icon names in Creator - _(maya)_ scene inventory wasn't showing anything if representation was removed from database after it's been loaded to the scene +- _(nukestudio)_ multiple bugs squashed +- _(loader)_ loader was taking long time to show all the loading action when first launcher in maya ## 2.2.0 ## _release date: 8 Sept 2019_ From dd967d87aa207e3a69669d81cf8a335e0e0e6392 Mon Sep 17 00:00:00 2001 From: Jakub Jezek Date: Wed, 6 Nov 2019 14:06:06 +0100 Subject: [PATCH 11/12] fix(ftrack): signals for linux --- pype/ftrack/events/event_sync_to_avalon.py | 2 ++ pype/ftrack/ftrack_server/event_server_cli.py | 6 ++++-- pype/ftrack/ftrack_server/sub_event_processor.py | 5 +++-- pype/ftrack/ftrack_server/sub_event_storer.py | 5 +++-- pype/ftrack/ftrack_server/sub_legacy_server.py | 5 +++-- 5 files changed, 15 insertions(+), 8 deletions(-) diff --git a/pype/ftrack/events/event_sync_to_avalon.py b/pype/ftrack/events/event_sync_to_avalon.py index a25866be65..3fe65bca11 100644 --- a/pype/ftrack/events/event_sync_to_avalon.py +++ b/pype/ftrack/events/event_sync_to_avalon.py @@ -101,6 +101,8 @@ class Sync_to_Avalon(BaseEvent): avalon_project = result['project'] except Exception as e: + session.reset() # reset session to clear it + message = str(e) title = 'Hey You! Unknown Error has been raised! (*look below*)' ftrack_message = ( diff --git a/pype/ftrack/ftrack_server/event_server_cli.py b/pype/ftrack/ftrack_server/event_server_cli.py index ec7cac9d6a..751d91ad4b 100644 --- a/pype/ftrack/ftrack_server/event_server_cli.py +++ b/pype/ftrack/ftrack_server/event_server_cli.py @@ -533,7 +533,9 @@ if __name__ == "__main__": signal.signal(signal.SIGINT, signal_handler) signal.signal(signal.SIGTERM, signal_handler) - if hasattr(signal, "SIGKILL"): - signal.signal(signal.SIGKILL, signal_handler) + try: + signal.signal(signal.SIGKILL, signal_handler) + except OSError: + pass sys.exit(main(sys.argv)) diff --git a/pype/ftrack/ftrack_server/sub_event_processor.py b/pype/ftrack/ftrack_server/sub_event_processor.py index 9444fe3ff0..4772c1e85e 100644 --- a/pype/ftrack/ftrack_server/sub_event_processor.py +++ b/pype/ftrack/ftrack_server/sub_event_processor.py @@ -47,7 +47,8 @@ if __name__ == "__main__": signal.signal(signal.SIGINT, signal_handler) signal.signal(signal.SIGTERM, signal_handler) - if hasattr(signal, "SIGKILL"): + try: signal.signal(signal.SIGKILL, signal_handler) - + except OSError: + pass sys.exit(main(sys.argv)) diff --git a/pype/ftrack/ftrack_server/sub_event_storer.py b/pype/ftrack/ftrack_server/sub_event_storer.py index 6e30fb99e2..a49561cfaf 100644 --- a/pype/ftrack/ftrack_server/sub_event_storer.py +++ b/pype/ftrack/ftrack_server/sub_event_storer.py @@ -112,7 +112,8 @@ if __name__ == "__main__": signal.signal(signal.SIGINT, signal_handler) signal.signal(signal.SIGTERM, signal_handler) - if hasattr(signal, "SIGKILL"): + try: signal.signal(signal.SIGKILL, signal_handler) - + except OSError: + pass sys.exit(main(sys.argv)) diff --git a/pype/ftrack/ftrack_server/sub_legacy_server.py b/pype/ftrack/ftrack_server/sub_legacy_server.py index c162b1abe1..01b1563db5 100644 --- a/pype/ftrack/ftrack_server/sub_legacy_server.py +++ b/pype/ftrack/ftrack_server/sub_legacy_server.py @@ -94,7 +94,8 @@ if __name__ == "__main__": signal.signal(signal.SIGINT, signal_handler) signal.signal(signal.SIGTERM, signal_handler) - if hasattr(signal, "SIGKILL"): + try: signal.signal(signal.SIGKILL, signal_handler) - + except OSError: + pass sys.exit(main(sys.argv)) From a6daff37ee5c4eaf6ad6230b6b61204b62d16fe9 Mon Sep 17 00:00:00 2001 From: Jakub Jezek Date: Wed, 6 Nov 2019 14:20:39 +0100 Subject: [PATCH 12/12] fix(ftrack): thumbnail event syntax error --- pype/ftrack/events/event_thumbnail_updates.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pype/ftrack/events/event_thumbnail_updates.py b/pype/ftrack/events/event_thumbnail_updates.py index 620d1a5b72..a74aad6bd9 100644 --- a/pype/ftrack/events/event_thumbnail_updates.py +++ b/pype/ftrack/events/event_thumbnail_updates.py @@ -45,7 +45,7 @@ class ThumbnailEvents(BaseEvent): if task: task['thumbnail_id'] = version['thumbnail_id'] - msg += " and task [ {} ]".format(task["name"])) + msg += " and task [ {} ]".format(task["name"]) self.log.info(msg)