From 4d31caad676fee2a5faf9baf19bc5da390b56d4e Mon Sep 17 00:00:00 2001 From: Toke Jepsen Date: Tue, 23 Jul 2019 14:47:22 +0100 Subject: [PATCH 01/13] Multiple paths and environment inheritance. - PYPE_MODULE_ROOT and PYPE_PYTHON_EXE had multiple paths. - The environment was not inherited, so need to explicitly pass it onwards. --- pype/plugins/global/publish/extract_burnin.py | 44 +++++++++++++++---- 1 file changed, 36 insertions(+), 8 deletions(-) diff --git a/pype/plugins/global/publish/extract_burnin.py b/pype/plugins/global/publish/extract_burnin.py index 5f16cc91f2..57db1f6c31 100644 --- a/pype/plugins/global/publish/extract_burnin.py +++ b/pype/plugins/global/publish/extract_burnin.py @@ -61,19 +61,47 @@ class ExtractBurnin(pype.api.Extractor): self.log.debug("__ burnin_data2: {}".format(burnin_data)) json_data = json.dumps(burnin_data) - scriptpath = os.path.normpath(os.path.join(os.environ['PYPE_MODULE_ROOT'], - "pype", - "scripts", - "otio_burnin.py")) + + # Get script path. + module_path = os.environ['PYPE_MODULE_ROOT'] + + # There can be multiple paths in PYPE_MODULE_ROOT, in which case + # we just take first one. + if os.pathsep in module_path: + module_path = module_path.split(os.pathsep)[0] + + scriptpath = os.path.normpath( + os.path.join( + module_path, + "pype", + "scripts", + "otio_burnin.py" + ) + ) self.log.debug("__ scriptpath: {}".format(scriptpath)) - self.log.debug("__ EXE: {}".format(os.getenv("PYPE_PYTHON_EXE"))) + + # Get executable. + executable = os.getenv("PYPE_PYTHON_EXE") + + # There can be multiple paths in PYPE_PYTHON_EXE, in which case + # we just take first one. + if os.pathsep in executable: + executable = executable.split(os.pathsep)[0] + + self.log.debug("__ EXE: {}".format(executable)) + + self.log.debug(json.dumps(os.environ, indent=4)) try: - p = subprocess.Popen( - [os.getenv("PYPE_PYTHON_EXE"), scriptpath, json_data] - ) + args = [executable, scriptpath, json_data] + self.log.debug("Executing: {}".format(args)) + + # Explicitly passing the environment, because there are cases + # where enviroment is not inherited. + p = subprocess.Popen(args, env=os.environ) p.wait() + if not os.path.isfile(full_burnin_path): raise RuntimeError("File not existing: {}".format(full_burnin_path)) except Exception as e: From 1eacfd9c61c4051df3591c7fd6808ba4f45f9cf9 Mon Sep 17 00:00:00 2001 From: Toke Jepsen Date: Tue, 23 Jul 2019 21:46:52 +0100 Subject: [PATCH 02/13] Remove redundant debug logging. --- pype/plugins/global/publish/extract_burnin.py | 2 -- 1 file changed, 2 deletions(-) diff --git a/pype/plugins/global/publish/extract_burnin.py b/pype/plugins/global/publish/extract_burnin.py index 57db1f6c31..87ff925a0a 100644 --- a/pype/plugins/global/publish/extract_burnin.py +++ b/pype/plugins/global/publish/extract_burnin.py @@ -91,8 +91,6 @@ class ExtractBurnin(pype.api.Extractor): self.log.debug("__ EXE: {}".format(executable)) - self.log.debug(json.dumps(os.environ, indent=4)) - try: args = [executable, scriptpath, json_data] self.log.debug("Executing: {}".format(args)) From 3ba5478d0f4c61ccdd51daafc6d347c9ba00446f Mon Sep 17 00:00:00 2001 From: Toke Jepsen Date: Wed, 24 Jul 2019 23:17:52 +0100 Subject: [PATCH 03/13] Validate Maya render output folder to not be scene dependent. --- pype/plugins/maya/publish/validate_rendersettings.py | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/pype/plugins/maya/publish/validate_rendersettings.py b/pype/plugins/maya/publish/validate_rendersettings.py index a41fe7b5f2..952c028bbf 100644 --- a/pype/plugins/maya/publish/validate_rendersettings.py +++ b/pype/plugins/maya/publish/validate_rendersettings.py @@ -9,9 +9,9 @@ class ValidateRenderSettings(pyblish.api.InstancePlugin): """Validates the global render settings * File Name Prefix must be as followed: - * vray: // - * arnold: // - * default: // + * vray: maya// + * arnold: maya// + * default: maya// * Frame Padding must be: * default: 4 @@ -34,8 +34,8 @@ class ValidateRenderSettings(pyblish.api.InstancePlugin): actions = [pype.api.RepairAction] DEFAULT_PADDING = 4 - RENDERER_PREFIX = {"vray": "//"} - DEFAULT_PREFIX = "//_" + RENDERER_PREFIX = {"vray": "maya//"} + DEFAULT_PREFIX = "maya//_" def process(self, instance): From dd944d0dda65a7d8c787b28308be46d8eb1f2916 Mon Sep 17 00:00:00 2001 From: Toke Jepsen Date: Wed, 24 Jul 2019 23:20:31 +0100 Subject: [PATCH 04/13] Create write nodes with no version in the output path. --- pype/nuke/lib.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pype/nuke/lib.py b/pype/nuke/lib.py index 6a57704fff..bb8131b849 100644 --- a/pype/nuke/lib.py +++ b/pype/nuke/lib.py @@ -191,7 +191,7 @@ def create_write_node(name, data): # build file path to workfiles fpath = str(anatomy_filled["work"]["folder"]).replace("\\", "/") - fpath = '{work}/renders/v{version}/{subset}.{frame}.{ext}'.format( + fpath = '{work}/renders/nuke/{subset}/{subset}.{frame}.{ext}'.format( work=fpath, version=data["version"], subset=data["subset"], frame=data["frame"], ext=data["nuke_dataflow_writes"]["file_type"]) From 8d41902b1a8a480d71e4ec56afee7326991c9313 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ond=C5=99ej=20Samohel?= Date: Fri, 26 Jul 2019 14:00:30 +0200 Subject: [PATCH 05/13] feat: deleting rendered frames from working area after publishing --- .../global/publish/collect_filesequences.py | 11 +++++--- pype/plugins/global/publish/integrate_new.py | 25 ++++++++++++++++--- 2 files changed, 28 insertions(+), 8 deletions(-) diff --git a/pype/plugins/global/publish/collect_filesequences.py b/pype/plugins/global/publish/collect_filesequences.py index ed48404a98..8b87068a09 100644 --- a/pype/plugins/global/publish/collect_filesequences.py +++ b/pype/plugins/global/publish/collect_filesequences.py @@ -160,10 +160,13 @@ class CollectRenderedFrames(pyblish.api.ContextPlugin): # Get family from the data families = data.get("families", ["render"]) - assert isinstance(families, (list, tuple)), "Must be iterable" - assert families, "Must have at least a single family" - families.append("ftrack") - families.append("review") + if "render" not in families: + families.append("render") + if "ftrack" not in families: + families.append("ftrack") + if "review" not in families: + families.append("review") + for collection in collections: instance = context.create_instance(str(collection)) self.log.info("Collection: %s" % list(collection)) diff --git a/pype/plugins/global/publish/integrate_new.py b/pype/plugins/global/publish/integrate_new.py index 0d077ca65e..3070a1f759 100644 --- a/pype/plugins/global/publish/integrate_new.py +++ b/pype/plugins/global/publish/integrate_new.py @@ -403,19 +403,36 @@ class IntegrateAssetNew(pyblish.api.InstancePlugin): self.log.info("Registered {} items".format(len(representations))) def integrate(self, instance): - """Move the files + """ Move the files. If files are in render family, they will be + deleted after copy. - Through `instance.data["transfers"]` + Through `instance.data["transfers"]` - Args: - instance: the instance to integrate + Args: + instance: the instance to integrate """ transfers = instance.data.get("transfers", list()) + current_families = instance.data.get("families", list()) + instance_family = instance.data.get("family", None) + dirnames = [] + for src, dest in transfers: if os.path.normpath(src) != os.path.normpath(dest): self.copy_file(src, dest) + if instance_family == 'render' or 'render' in current_families: + os.remove(src) + dirnames.append(os.path.dirname(src)) + + # make unique set + cleanup_dirs = set(dirnames) + for dir in cleanup_dirs: + try: + os.rmdir(dir) + except OSError: + # directory is not empty, skipping + continue # Produce hardlinked copies # Note: hardlink can only be produced between two files on the same From 62ce7fad853188a3727899db2bdaf368a4321b8c Mon Sep 17 00:00:00 2001 From: Toke Jepsen Date: Sat, 27 Jul 2019 12:36:53 +0100 Subject: [PATCH 06/13] Account for host name in work file path. --- pype/nuke/lib.py | 15 ++++++++++--- .../maya/publish/validate_rendersettings.py | 22 ++++++++++++++++--- 2 files changed, 31 insertions(+), 6 deletions(-) diff --git a/pype/nuke/lib.py b/pype/nuke/lib.py index bb8131b849..37d3f9eb40 100644 --- a/pype/nuke/lib.py +++ b/pype/nuke/lib.py @@ -191,10 +191,19 @@ def create_write_node(name, data): # build file path to workfiles fpath = str(anatomy_filled["work"]["folder"]).replace("\\", "/") - fpath = '{work}/renders/nuke/{subset}/{subset}.{frame}.{ext}'.format( - work=fpath, version=data["version"], subset=data["subset"], + pattern = "{work}/renders/nuke/{subset}/{subset}.{frame}.{ext}" + # Workfile paths can be configured to have host name in file path. + # In this case we want to avoid duplicate folder names. + if "nuke" in fpath.lower(): + pattern = pattern.replace("nuke/", "") + + fpath = pattern.format( + work=fpath, + version=data["version"], + subset=data["subset"], frame=data["frame"], - ext=data["nuke_dataflow_writes"]["file_type"]) + ext=data["nuke_dataflow_writes"]["file_type"] + ) # create directory if not os.path.isdir(os.path.dirname(fpath)): diff --git a/pype/plugins/maya/publish/validate_rendersettings.py b/pype/plugins/maya/publish/validate_rendersettings.py index 952c028bbf..f4798e6dbe 100644 --- a/pype/plugins/maya/publish/validate_rendersettings.py +++ b/pype/plugins/maya/publish/validate_rendersettings.py @@ -1,4 +1,7 @@ +import os + import maya.cmds as cmds +import pymel.core as pm import pyblish.api import pype.api @@ -66,8 +69,8 @@ class ValidateRenderSettings(pyblish.api.InstancePlugin): cls.log.error("Animation needs to be enabled. Use the same " "frame for start and end to render single frame") - fname_prefix = cls.RENDERER_PREFIX.get(renderer, - cls.DEFAULT_PREFIX) + fname_prefix = cls.get_prefix(cls, renderer) + if prefix != fname_prefix: invalid = True cls.log.error("Wrong file name prefix: %s (expected: %s)" @@ -80,6 +83,19 @@ class ValidateRenderSettings(pyblish.api.InstancePlugin): return invalid + @classmethod + def get_prefix(cls, renderer): + prefix = cls.RENDERER_PREFIX.get(renderer, cls.DEFAULT_PREFIX) + output_path = os.path.join( + pm.workspace.getcwd(), pm.workspace.fileRules["images"] + ) + # Workfile paths can be configured to have host name in file path. + # In this case we want to avoid duplicate folder names. + if "maya" in output_path.lower(): + prefix = prefix.replace("maya/", "") + + return prefix + @classmethod def repair(cls, instance): @@ -94,7 +110,7 @@ class ValidateRenderSettings(pyblish.api.InstancePlugin): node = render_attrs["node"] prefix_attr = render_attrs["prefix"] - fname_prefix = cls.RENDERER_PREFIX.get(renderer, cls.DEFAULT_PREFIX) + fname_prefix = cls.get_prefix(cls, renderer) cmds.setAttr("{}.{}".format(node, prefix_attr), fname_prefix, type="string") From d5c76a4c10366e969113168e2eb6e1639024ea39 Mon Sep 17 00:00:00 2001 From: Toke Jepsen Date: Mon, 29 Jul 2019 09:15:03 +0100 Subject: [PATCH 07/13] Fix hardcoded deadline submission. --- .../maya/publish/submit_maya_deadline.py | 17 ++++++++++++++--- 1 file changed, 14 insertions(+), 3 deletions(-) diff --git a/pype/plugins/maya/publish/submit_maya_deadline.py b/pype/plugins/maya/publish/submit_maya_deadline.py index b7a4a835fa..6264609fdf 100644 --- a/pype/plugins/maya/publish/submit_maya_deadline.py +++ b/pype/plugins/maya/publish/submit_maya_deadline.py @@ -51,7 +51,7 @@ def get_renderer_variables(renderlayer=None): # returns an index number. filename_base = os.path.basename(filename_0) extension = os.path.splitext(filename_base)[-1].strip(".") - filename_prefix = "//" + filename_prefix = cmds.getAttr("defaultRenderGlobals.imageFilePrefix") return {"ext": extension, "filename_prefix": filename_prefix, @@ -77,8 +77,19 @@ def preview_fname(folder, scene, layer, padding, ext): """ - # Following hardcoded "/_/" - output = "{scene}/{layer}/{layer}.{number}.{ext}".format( + fileprefix = cmds.getAttr("defaultRenderGlobals.imageFilePrefix") + output = fileprefix + ".{number}.{ext}" + # RenderPass is currently hardcoded to "beauty" because its not important + # for the deadline submission, but we will need something to replace + # "". + mapping = { + "": "{scene}", + "": "{layer}", + "RenderPass": "beauty" + } + for key, value in mapping.items(): + output = output.replace(key, value) + output = output.format( scene=scene, layer=layer, number="#" * padding, From c77578be01393413f83ab64c1591ede60852caab Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ond=C5=99ej=20Samohel?= Date: Mon, 29 Jul 2019 11:37:24 +0200 Subject: [PATCH 08/13] moved render cleanup code to cleanup instance plugin --- pype/plugins/global/publish/cleanup.py | 28 ++++++++++++++++++-- pype/plugins/global/publish/integrate_new.py | 22 --------------- 2 files changed, 26 insertions(+), 24 deletions(-) diff --git a/pype/plugins/global/publish/cleanup.py b/pype/plugins/global/publish/cleanup.py index f31477faca..34123b31cf 100644 --- a/pype/plugins/global/publish/cleanup.py +++ b/pype/plugins/global/publish/cleanup.py @@ -3,11 +3,33 @@ import shutil import pyblish.api +def clean_renders(instance): + transfers = instance.data.get("transfers", list()) + + current_families = instance.data.get("families", list()) + instance_family = instance.data.get("family", None) + dirnames = [] + + for src, dest in transfers: + if os.path.normpath(src) != os.path.normpath(dest): + if instance_family == 'render' or 'render' in current_families: + os.remove(src) + dirnames.append(os.path.dirname(src)) + + # make unique set + cleanup_dirs = set(dirnames) + for dir in cleanup_dirs: + try: + os.rmdir(dir) + except OSError: + # directory is not empty, skipping + continue + + class CleanUp(pyblish.api.InstancePlugin): """Cleans up the staging directory after a successful publish. - The removal will only happen for staging directories which are inside the - temporary folder, otherwise the folder is ignored. + This will also clean published renders and delete their parent directories. """ @@ -36,3 +58,5 @@ class CleanUp(pyblish.api.InstancePlugin): self.log.info("Removing temporary folder ...") shutil.rmtree(staging_dir) + self.log.info("Cleaning renders ...") + clean_renders(instance) diff --git a/pype/plugins/global/publish/integrate_new.py b/pype/plugins/global/publish/integrate_new.py index 3070a1f759..bca12dc62e 100644 --- a/pype/plugins/global/publish/integrate_new.py +++ b/pype/plugins/global/publish/integrate_new.py @@ -412,28 +412,6 @@ class IntegrateAssetNew(pyblish.api.InstancePlugin): instance: the instance to integrate """ - transfers = instance.data.get("transfers", list()) - - current_families = instance.data.get("families", list()) - instance_family = instance.data.get("family", None) - dirnames = [] - - for src, dest in transfers: - if os.path.normpath(src) != os.path.normpath(dest): - self.copy_file(src, dest) - if instance_family == 'render' or 'render' in current_families: - os.remove(src) - dirnames.append(os.path.dirname(src)) - - # make unique set - cleanup_dirs = set(dirnames) - for dir in cleanup_dirs: - try: - os.rmdir(dir) - except OSError: - # directory is not empty, skipping - continue - # Produce hardlinked copies # Note: hardlink can only be produced between two files on the same # server/disk and editing one of the two will edit both files at once. From 31f709b2a455620d48d0c2044b8adad0f5c7d80c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ond=C5=99ej=20Samohel?= Date: Mon, 29 Jul 2019 11:39:24 +0200 Subject: [PATCH 09/13] fixed docstring in integrate --- pype/plugins/global/publish/integrate_new.py | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/pype/plugins/global/publish/integrate_new.py b/pype/plugins/global/publish/integrate_new.py index bca12dc62e..acb5555ba9 100644 --- a/pype/plugins/global/publish/integrate_new.py +++ b/pype/plugins/global/publish/integrate_new.py @@ -403,8 +403,7 @@ class IntegrateAssetNew(pyblish.api.InstancePlugin): self.log.info("Registered {} items".format(len(representations))) def integrate(self, instance): - """ Move the files. If files are in render family, they will be - deleted after copy. + """ Move the files. Through `instance.data["transfers"]` From 659f46e3173dc0d6f57abfb753c5ba4975835f48 Mon Sep 17 00:00:00 2001 From: Toke Jepsen Date: Mon, 29 Jul 2019 11:33:08 +0100 Subject: [PATCH 10/13] Enforce environment by passing to subprocess. --- pype/scripts/publish_filesequence.py | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/pype/scripts/publish_filesequence.py b/pype/scripts/publish_filesequence.py index 705a21c8c2..25ed4135c3 100644 --- a/pype/scripts/publish_filesequence.py +++ b/pype/scripts/publish_filesequence.py @@ -58,7 +58,9 @@ def __main__(): ] print("Pype command: {}".format(" ".join(args))) - exit_code = subprocess.call(args, shell=True) + # Forcing forwaring the environment because environment inheritance does + # not always work. + exit_code = subprocess.call(args, env=os.environ) if exit_code != 0: raise ValueError("Publishing failed.") From e742693fd73cb1e91b0d595eaba6298a19bfa4e2 Mon Sep 17 00:00:00 2001 From: Toke Jepsen Date: Mon, 29 Jul 2019 11:35:21 +0100 Subject: [PATCH 11/13] Only submit to muster when environment is setup. --- pype/plugins/maya/publish/submit_maya_muster.py | 11 +++++++++-- 1 file changed, 9 insertions(+), 2 deletions(-) diff --git a/pype/plugins/maya/publish/submit_maya_muster.py b/pype/plugins/maya/publish/submit_maya_muster.py index 3aae2e55ea..f4f3f3fe14 100644 --- a/pype/plugins/maya/publish/submit_maya_muster.py +++ b/pype/plugins/maya/publish/submit_maya_muster.py @@ -250,8 +250,15 @@ class MayaSubmitMuster(pyblish.api.InstancePlugin): render publish job and submit job to farm. """ # setup muster environment - self.MUSTER_REST_URL = os.environ.get("MUSTER_REST_URL", - "https://localhost:9891") + self.MUSTER_REST_URL = os.environ.get("MUSTER_REST_URL") + + if self.MUSTER_REST_URL is None: + self.log.debug( + "\"MUSTER_REST_URL\" is not found. Skipping " + "\"{}\".".format(instance) + ) + return + self._load_credentials() self._authenticate() self._get_templates() From f8f9c4f085ccd5463095d548a3f7ee85eafb997c Mon Sep 17 00:00:00 2001 From: Toke Jepsen Date: Mon, 29 Jul 2019 15:51:43 +0100 Subject: [PATCH 12/13] Fix get_prefix and workspace root. --- pype/plugins/maya/publish/validate_rendersettings.py | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/pype/plugins/maya/publish/validate_rendersettings.py b/pype/plugins/maya/publish/validate_rendersettings.py index f4798e6dbe..0d983b9cf1 100644 --- a/pype/plugins/maya/publish/validate_rendersettings.py +++ b/pype/plugins/maya/publish/validate_rendersettings.py @@ -1,6 +1,6 @@ import os -import maya.cmds as cmds +from maya import cmds, mel import pymel.core as pm import pyblish.api @@ -69,7 +69,7 @@ class ValidateRenderSettings(pyblish.api.InstancePlugin): cls.log.error("Animation needs to be enabled. Use the same " "frame for start and end to render single frame") - fname_prefix = cls.get_prefix(cls, renderer) + fname_prefix = cls.get_prefix(renderer) if prefix != fname_prefix: invalid = True @@ -86,8 +86,10 @@ class ValidateRenderSettings(pyblish.api.InstancePlugin): @classmethod def get_prefix(cls, renderer): prefix = cls.RENDERER_PREFIX.get(renderer, cls.DEFAULT_PREFIX) + # maya.cmds and pymel.core return only default project directory and + # not the current one but only default. output_path = os.path.join( - pm.workspace.getcwd(), pm.workspace.fileRules["images"] + mel.eval("workspace -q -rd;"), pm.workspace.fileRules["images"] ) # Workfile paths can be configured to have host name in file path. # In this case we want to avoid duplicate folder names. @@ -110,7 +112,7 @@ class ValidateRenderSettings(pyblish.api.InstancePlugin): node = render_attrs["node"] prefix_attr = render_attrs["prefix"] - fname_prefix = cls.get_prefix(cls, renderer) + fname_prefix = cls.get_prefix(renderer) cmds.setAttr("{}.{}".format(node, prefix_attr), fname_prefix, type="string") From 02526f156d7b3e2bf10a669736d980ced29b53fc Mon Sep 17 00:00:00 2001 From: Jakub Jezek Date: Wed, 31 Jul 2019 01:05:14 +0200 Subject: [PATCH 13/13] fix(nuke): fixing update function in loader to better work with avalon.nuke.lib:ls_img_sequence --- pype/plugins/nuke/load/load_mov.py | 6 ++---- pype/plugins/nuke/load/load_sequence.py | 6 +++--- 2 files changed, 5 insertions(+), 7 deletions(-) diff --git a/pype/plugins/nuke/load/load_mov.py b/pype/plugins/nuke/load/load_mov.py index f74c31d232..cd45c77906 100644 --- a/pype/plugins/nuke/load/load_mov.py +++ b/pype/plugins/nuke/load/load_mov.py @@ -182,7 +182,6 @@ class LoadMov(api.Loader): """ from avalon.nuke import ( - ls_img_sequence, update_container ) @@ -190,8 +189,7 @@ class LoadMov(api.Loader): # TODO: prepare also for other Read img/geo/camera assert node.Class() == "Read", "Must be Read" - root = api.get_representation_path(representation) - file = ls_img_sequence(os.path.dirname(root), one=True) + file = api.get_representation_path(representation) # Get start frame from version data version = io.find_one({ @@ -238,7 +236,7 @@ class LoadMov(api.Loader): # Update the loader's path whilst preserving some values with preserve_trim(node): node["file"].setValue(file["path"]) - log.info("__ node['file']: {}".format(node["file"])) + log.info("__ node['file']: {}".format(node["file"].value())) # Set the global in to the start frame of the sequence loader_shift(node, first, relative=True) diff --git a/pype/plugins/nuke/load/load_sequence.py b/pype/plugins/nuke/load/load_sequence.py index fd733f7c87..b2affb3563 100644 --- a/pype/plugins/nuke/load/load_sequence.py +++ b/pype/plugins/nuke/load/load_sequence.py @@ -179,8 +179,8 @@ class LoadSequence(api.Loader): # TODO: prepare also for other Read img/geo/camera assert node.Class() == "Read", "Must be Read" - root = api.get_representation_path(representation) - file = ls_img_sequence(os.path.dirname(root), one=True) + path = api.get_representation_path(representation) + file = ls_img_sequence(path) # Get start frame from version data version = io.find_one({ @@ -222,7 +222,7 @@ class LoadSequence(api.Loader): # Update the loader's path whilst preserving some values with preserve_trim(node): node["file"].setValue(file["path"]) - log.info("__ node['file']: {}".format(node["file"])) + log.info("__ node['file']: {}".format(node["file"].value())) # Set the global in to the start frame of the sequence loader_shift(node, first, relative=True)