diff --git a/server_addon/houdini/client/ayon_houdini/api/plugin.py b/server_addon/houdini/client/ayon_houdini/api/plugin.py index 9c6bba925a..0e2308e948 100644 --- a/server_addon/houdini/client/ayon_houdini/api/plugin.py +++ b/server_addon/houdini/client/ayon_houdini/api/plugin.py @@ -1,5 +1,6 @@ # -*- coding: utf-8 -*- """Houdini specific Avalon/Pyblish plugin definitions.""" +import os import sys from abc import ( ABCMeta @@ -392,3 +393,22 @@ class HoudiniExtractorPlugin(publish.Extractor): hosts = ["houdini"] settings_category = SETTINGS_CATEGORY + + def validate_expected_frames(self, instance, staging_dir): + """ + Validate all expected files in `instance.data["frames"]` exist in + the staging directory. + """ + filenames = instance.data["frames"] + if isinstance(filenames, str): + # Single frame + filenames = [filenames] + + missing_filenames = [] + for filename in filenames: + path = os.path.join(staging_dir, filename) + if not os.path.isfile(path): + missing_filenames.append(filename) + if missing_filenames: + raise RuntimeError(f"Missing frames: {missing_filenames}") + diff --git a/server_addon/houdini/client/ayon_houdini/plugins/publish/extract_alembic.py b/server_addon/houdini/client/ayon_houdini/plugins/publish/extract_alembic.py index e82f07284a..07216a491c 100644 --- a/server_addon/houdini/client/ayon_houdini/plugins/publish/extract_alembic.py +++ b/server_addon/houdini/client/ayon_houdini/plugins/publish/extract_alembic.py @@ -26,15 +26,8 @@ class ExtractAlembic(plugin.HoudiniExtractorPlugin): staging_dir = os.path.dirname(output) instance.data["stagingDir"] = staging_dir - if instance.data.get("frames"): - # list of files - files = instance.data["frames"] - else: - # single file - files = os.path.basename(output) - # We run the render - self.log.info("Writing alembic '%s' to '%s'" % (files, + self.log.info("Writing alembic '%s' to '%s'" % (output, staging_dir)) render_rop(ropnode) @@ -45,7 +38,7 @@ class ExtractAlembic(plugin.HoudiniExtractorPlugin): representation = { 'name': 'abc', 'ext': 'abc', - 'files': files, + 'files': instance.data["frames"], "stagingDir": staging_dir, } instance.data["representations"].append(representation) diff --git a/server_addon/houdini/client/ayon_houdini/plugins/publish/extract_ass.py b/server_addon/houdini/client/ayon_houdini/plugins/publish/extract_ass.py index a796bbf4b3..befa6d0d49 100644 --- a/server_addon/houdini/client/ayon_houdini/plugins/publish/extract_ass.py +++ b/server_addon/houdini/client/ayon_houdini/plugins/publish/extract_ass.py @@ -35,16 +35,7 @@ class ExtractAss(plugin.HoudiniExtractorPlugin): # Unfortunately user interrupting the extraction does not raise an # error and thus still continues to the integrator. To capture that # we make sure all files exist - files = instance.data["frames"] - missing = [] - for file_name in files: - full_path = os.path.normpath(os.path.join(staging_dir, file_name)) - if not os.path.exists(full_path): - missing.append(full_path) - - if missing: - raise RuntimeError("Failed to complete Arnold ass extraction. " - "Missing output files: {}".format(missing)) + self.validate_expected_frames(instance, staging_dir) if "representations" not in instance.data: instance.data["representations"] = [] @@ -55,7 +46,7 @@ class ExtractAss(plugin.HoudiniExtractorPlugin): representation = { 'name': 'ass', 'ext': ext, - "files": files, + "files": instance.data["frames"], "stagingDir": staging_dir, "frameStart": instance.data["frameStartHandle"], "frameEnd": instance.data["frameEndHandle"], diff --git a/server_addon/houdini/client/ayon_houdini/plugins/publish/extract_bgeo.py b/server_addon/houdini/client/ayon_houdini/plugins/publish/extract_bgeo.py index ab8837065d..180812ab87 100644 --- a/server_addon/houdini/client/ayon_houdini/plugins/publish/extract_bgeo.py +++ b/server_addon/houdini/client/ayon_houdini/plugins/publish/extract_bgeo.py @@ -19,8 +19,8 @@ class ExtractBGEO(plugin.HoudiniExtractorPlugin): ropnode = hou.node(instance.data["instance_node"]) # Get the filename from the filename parameter - output = ropnode.evalParm("sopoutput") - staging_dir, file_name = os.path.split(output) + sop_output = ropnode.evalParm("sopoutput") + staging_dir, file_name = os.path.split(sop_output) instance.data["stagingDir"] = staging_dir # We run the render @@ -30,10 +30,8 @@ class ExtractBGEO(plugin.HoudiniExtractorPlugin): # write files lib.render_rop(ropnode) - output = instance.data["frames"] - _, ext = lib.splitext( - output[0], allowed_multidot_extensions=[ + sop_output, allowed_multidot_extensions=[ ".ass.gz", ".bgeo.sc", ".bgeo.gz", ".bgeo.lzma", ".bgeo.bz2"]) @@ -43,7 +41,7 @@ class ExtractBGEO(plugin.HoudiniExtractorPlugin): representation = { "name": "bgeo", "ext": ext.lstrip("."), - "files": output, + "files": instance.data["frames"], "stagingDir": staging_dir, "frameStart": instance.data["frameStartHandle"], "frameEnd": instance.data["frameEndHandle"] diff --git a/server_addon/houdini/client/ayon_houdini/plugins/publish/extract_composite.py b/server_addon/houdini/client/ayon_houdini/plugins/publish/extract_composite.py index cab462aef6..84f03e5d1c 100644 --- a/server_addon/houdini/client/ayon_houdini/plugins/publish/extract_composite.py +++ b/server_addon/houdini/client/ayon_houdini/plugins/publish/extract_composite.py @@ -20,17 +20,16 @@ class ExtractComposite(plugin.HoudiniExtractorPlugin, # Get the filename from the copoutput parameter # `.evalParm(parameter)` will make sure all tokens are resolved - output = ropnode.evalParm("copoutput") - staging_dir = os.path.dirname(output) + cop_output = ropnode.evalParm("copoutput") + staging_dir, file_name = os.path.split(cop_output) instance.data["stagingDir"] = staging_dir - file_name = os.path.basename(output) self.log.info("Writing comp '%s' to '%s'" % (file_name, staging_dir)) render_rop(ropnode) output = instance.data["frames"] - _, ext = splitext(output[0], []) + _, ext = splitext(file_name, []) ext = ext.lstrip(".") if "representations" not in instance.data: diff --git a/server_addon/houdini/client/ayon_houdini/plugins/publish/extract_mantra_ifd.py b/server_addon/houdini/client/ayon_houdini/plugins/publish/extract_mantra_ifd.py index b424f2e452..f0f402fa64 100644 --- a/server_addon/houdini/client/ayon_houdini/plugins/publish/extract_mantra_ifd.py +++ b/server_addon/houdini/client/ayon_houdini/plugins/publish/extract_mantra_ifd.py @@ -23,17 +23,7 @@ class ExtractMantraIFD(plugin.HoudiniExtractorPlugin): staging_dir = os.path.dirname(output) instance.data["stagingDir"] = staging_dir - files = instance.data["frames"] - missing_frames = [ - frame - for frame in instance.data["frames"] - if not os.path.exists( - os.path.normpath(os.path.join(staging_dir, frame))) - ] - if missing_frames: - raise RuntimeError("Failed to complete Mantra ifd extraction. " - "Missing output files: {}".format( - missing_frames)) + self.validate_expected_frames(instance, staging_dir) if "representations" not in instance.data: instance.data["representations"] = [] @@ -41,7 +31,7 @@ class ExtractMantraIFD(plugin.HoudiniExtractorPlugin): representation = { 'name': 'ifd', 'ext': 'ifd', - 'files': files, + 'files': instance.data["frames"], "stagingDir": staging_dir, "frameStart": instance.data["frameStart"], "frameEnd": instance.data["frameEnd"], diff --git a/server_addon/houdini/client/ayon_houdini/plugins/publish/extract_opengl.py b/server_addon/houdini/client/ayon_houdini/plugins/publish/extract_opengl.py index bee1bf871f..934f98a9f3 100644 --- a/server_addon/houdini/client/ayon_houdini/plugins/publish/extract_opengl.py +++ b/server_addon/houdini/client/ayon_houdini/plugins/publish/extract_opengl.py @@ -38,8 +38,6 @@ class ExtractOpenGL(plugin.HoudiniExtractorPlugin, render_rop(ropnode) - output = instance.data["frames"] - tags = ["review"] if not instance.data.get("keepImages"): tags.append("delete") @@ -47,7 +45,7 @@ class ExtractOpenGL(plugin.HoudiniExtractorPlugin, representation = { "name": instance.data["imageFormat"], "ext": instance.data["imageFormat"], - "files": output, + "files": instance.data["frames"], "stagingDir": staging_dir, "frameStart": instance.data["frameStartHandle"], "frameEnd": instance.data["frameEndHandle"], diff --git a/server_addon/houdini/client/ayon_houdini/plugins/publish/extract_redshift_proxy.py b/server_addon/houdini/client/ayon_houdini/plugins/publish/extract_redshift_proxy.py index 3e8a79df00..8c3cdd5ef9 100644 --- a/server_addon/houdini/client/ayon_houdini/plugins/publish/extract_redshift_proxy.py +++ b/server_addon/houdini/client/ayon_houdini/plugins/publish/extract_redshift_proxy.py @@ -32,15 +32,13 @@ class ExtractRedshiftProxy(plugin.HoudiniExtractorPlugin): render_rop(ropnode) - output = instance.data["frames"] - if "representations" not in instance.data: instance.data["representations"] = [] representation = { "name": "rs", "ext": "rs", - "files": output, + "files": instance.data["frames"], "stagingDir": staging_dir, } diff --git a/server_addon/houdini/client/ayon_houdini/plugins/publish/extract_vdb_cache.py b/server_addon/houdini/client/ayon_houdini/plugins/publish/extract_vdb_cache.py index a944d81e9b..8f0c070ff1 100644 --- a/server_addon/houdini/client/ayon_houdini/plugins/publish/extract_vdb_cache.py +++ b/server_addon/houdini/client/ayon_houdini/plugins/publish/extract_vdb_cache.py @@ -30,15 +30,13 @@ class ExtractVDBCache(plugin.HoudiniExtractorPlugin): render_rop(ropnode) - output = instance.data["frames"] - if "representations" not in instance.data: instance.data["representations"] = [] representation = { "name": "vdb", "ext": "vdb", - "files": output, + "files": instance.data["frames"], "stagingDir": staging_dir, "frameStart": instance.data["frameStartHandle"], "frameEnd": instance.data["frameEndHandle"],