diff --git a/client/ayon_houdini/plugins/publish/collect_render_products.py b/client/ayon_houdini/plugins/publish/collect_render_products.py index 7223f1ffe9..2fb5ce8c8a 100644 --- a/client/ayon_houdini/plugins/publish/collect_render_products.py +++ b/client/ayon_houdini/plugins/publish/collect_render_products.py @@ -6,6 +6,7 @@ import pyblish.api +from ayon_core.pipeline import PublishError from ayon_houdini.api import plugin from ayon_houdini.api.usd import ( get_usd_render_rop_rendersettings @@ -107,10 +108,10 @@ def replace(match): filename = os.path.join(dirname, filename_base) filename = filename.replace("\\", "/") - assert "#" in filename, ( - "Couldn't resolve render product name " - "with frame number: %s" % name - ) + if "#" not in filename: + raise PublishError( + f"Couldn't resolve render product name with frame number: {name}" + ) filenames.append(filename) diff --git a/client/ayon_houdini/plugins/publish/collect_usd_layers.py b/client/ayon_houdini/plugins/publish/collect_usd_layers.py index 1073322468..82990fbec6 100644 --- a/client/ayon_houdini/plugins/publish/collect_usd_layers.py +++ b/client/ayon_houdini/plugins/publish/collect_usd_layers.py @@ -4,6 +4,7 @@ import pyblish.api +from ayon_core.pipeline import KnownPublishError from ayon_core.pipeline.create import get_product_name from ayon_houdini.api import plugin import ayon_houdini.api.usd as usdlib @@ -27,8 +28,7 @@ def copy_instance_data(instance_src, instance_dest, attr): in the source instance's data. Raises: - KeyError: If the key does not exist on the source instance. - AssertionError: If a parent key already exists on the destination + KnownPublishError: If a parent key already exists on the destination instance but is not of the correct type (= is not a dict) """ @@ -43,7 +43,8 @@ def copy_instance_data(instance_src, instance_dest, attr): src_value = src_data[key] if i != len(key): dest_data = dest_data.setdefault(key, {}) - assert isinstance(dest_data, dict), "Destination must be a dict" + if not isinstance(dest_data, dict): + raise KnownPublishError("Destination must be a dict") src_data = src_value else: # Last iteration - assign the value diff --git a/client/ayon_houdini/plugins/publish/extract_render.py b/client/ayon_houdini/plugins/publish/extract_render.py index 5004ae53e9..affd779cd2 100644 --- a/client/ayon_houdini/plugins/publish/extract_render.py +++ b/client/ayon_houdini/plugins/publish/extract_render.py @@ -3,6 +3,7 @@ import pyblish.api +from ayon_core.pipeline import PublishError from ayon_houdini.api import plugin @@ -75,13 +76,14 @@ def process(self, instance): all_frames.extend(value) # Check missing frames. # Frames won't exist if user cancels the render. - missing_frames = [ + missing_frames = "\n\n - ".join( frame for frame in all_frames if not os.path.exists(frame) - ] + ) if missing_frames: - # TODO: Use user friendly error reporting. - raise RuntimeError("Failed to complete render extraction. " - "Missing output files: {}".format( - missing_frames)) + raise PublishError( + "Failed to complete render extraction.\n" + "Please render any missing output files.", + detail=f"Missing output files: \n\n - {missing_frames}" + ) diff --git a/client/ayon_houdini/plugins/publish/extract_rop.py b/client/ayon_houdini/plugins/publish/extract_rop.py index 7e5c5798cd..65578d3216 100644 --- a/client/ayon_houdini/plugins/publish/extract_rop.py +++ b/client/ayon_houdini/plugins/publish/extract_rop.py @@ -1,7 +1,7 @@ import os import pyblish.api -from ayon_core.pipeline import publish +from ayon_core.pipeline import publish, PublishError from ayon_houdini.api import plugin from ayon_houdini.api.lib import splitext @@ -68,12 +68,16 @@ def validate_expected_frames(self, instance: pyblish.api.Instance): # Single frame filenames = [filenames] - missing_filenames = [ + missing_filenames = "\n\n - ".join( filename for filename in filenames if not os.path.isfile(os.path.join(staging_dir, filename)) - ] + ) if missing_filenames: - raise RuntimeError(f"Missing frames: {missing_filenames}") + raise PublishError( + "Failed to complete render extraction.\n" + "Please render any missing output files.", + detail=f"Missing output files: \n\n - {missing_filenames}" + ) def update_representation_data(self, instance: pyblish.api.Instance, diff --git a/client/ayon_houdini/plugins/publish/extract_usd.py b/client/ayon_houdini/plugins/publish/extract_usd.py index 90fd085b21..1b3cf9dd88 100644 --- a/client/ayon_houdini/plugins/publish/extract_usd.py +++ b/client/ayon_houdini/plugins/publish/extract_usd.py @@ -3,6 +3,7 @@ import pyblish.api +from ayon_core.pipeline import KnownPublisherError, PublishError from ayon_core.pipeline.entity_uri import construct_ayon_entity_uri from ayon_core.pipeline.publish.lib import get_instance_expected_output_path from ayon_houdini.api import plugin @@ -47,7 +48,8 @@ def process(self, instance): with remap_paths(ropnode, mapping): render_rop(ropnode) - assert os.path.exists(output), "Output does not exist: %s" % output + if not os.path.exists(output): + PublishError(f"Output does not exist: {output}") if "representations" not in instance.data: instance.data["representations"] = [] @@ -135,5 +137,6 @@ def get_source_paths( # Single file return [os.path.join(staging, files)] - raise TypeError(f"Unsupported type for representation files: {files} " - "(supports list or str)") + raise KnownPublisherError( + f"Unsupported type for representation files: {files} (supports list or str)" + ) diff --git a/client/ayon_houdini/plugins/publish/increment_current_file.py b/client/ayon_houdini/plugins/publish/increment_current_file.py index 878500f605..bcafe6eaee 100644 --- a/client/ayon_houdini/plugins/publish/increment_current_file.py +++ b/client/ayon_houdini/plugins/publish/increment_current_file.py @@ -1,7 +1,7 @@ import pyblish.api from ayon_core.lib import version_up -from ayon_core.pipeline import registered_host +from ayon_core.pipeline import registered_host, PublishError from ayon_core.pipeline.publish import ( get_errored_plugins_from_context, KnownPublishError @@ -46,8 +46,10 @@ def process(self, context): host = registered_host() current_file = host.current_file() if context.data["currentFile"] != current_file: - raise KnownPublishError( - "Collected filename mismatches from current scene name." + raise PublishError( + f"Collected filename '{context.data['currentFile']}'" + f" mismatches from current scene name '{current_file}'." + "Save the file and republish. Don't change the file during publishing." ) new_filepath = version_up(current_file) diff --git a/client/ayon_houdini/plugins/publish/save_scene.py b/client/ayon_houdini/plugins/publish/save_scene.py index e0734da5d1..e61f9d4d19 100644 --- a/client/ayon_houdini/plugins/publish/save_scene.py +++ b/client/ayon_houdini/plugins/publish/save_scene.py @@ -1,6 +1,7 @@ +import inspect import pyblish.api -from ayon_core.pipeline import registered_host +from ayon_core.pipeline import registered_host, PublishError from ayon_houdini.api import plugin @@ -16,12 +17,23 @@ def process(self, context): # Filename must not have changed since collecting host = registered_host() current_file = host.get_current_workfile() - assert context.data['currentFile'] == current_file, ( - "Collected filename from current scene name." - ) - + if context.data['currentFile'] != current_file: + raise PublishError( + f"Collected filename '{context.data['currentFile']}' differs" + f" from current scene name '{current_file}'.", + description=self.get_error_description() + ) if host.workfile_has_unsaved_changes(): self.log.info("Saving current file: {}".format(current_file)) host.save_workfile(current_file) else: self.log.debug("No unsaved changes, skipping file save..") + + + def get_error_description(self): + return inspect.cleandoc( + """### Scene File Name Change During Publishing + This error occurs when you validate the scene and then save it as a new file manually, or if you open a new file and continue publishing. + Please reset the publisher and publish without changing the scene file midway. + """ + ) \ No newline at end of file diff --git a/client/ayon_houdini/plugins/publish/validate_frame_token.py b/client/ayon_houdini/plugins/publish/validate_frame_token.py index 46c02ba6f2..04974710d1 100644 --- a/client/ayon_houdini/plugins/publish/validate_frame_token.py +++ b/client/ayon_houdini/plugins/publish/validate_frame_token.py @@ -2,6 +2,7 @@ import pyblish.api +from ayon_core.pipeline import PublishValidationError from ayon_houdini.api import lib, plugin @@ -31,7 +32,7 @@ def process(self, instance): invalid = self.get_invalid(instance) if invalid: - raise RuntimeError( + raise PublishValidationError( "Output settings do no match for '%s'" % instance ) @@ -42,11 +43,11 @@ def get_invalid(cls, instance): # Check trange parm, 0 means Render Current Frame frame_range = node.evalParm("trange") if frame_range == 0: - return [] + return output_parm = lib.get_output_parameter(node) unexpanded_str = output_parm.unexpandedString() if "$F" not in unexpanded_str: cls.log.error("No frame token found in '%s'" % node.path()) - return [instance] + return [node]