Enhancement: More descriptive error messages for Loaders (#5227)

* More descriptive error messages for Loaders

* Restructure error reporting
This commit is contained in:
Roy Nieterau 2023-07-03 13:42:00 +02:00 committed by GitHub
parent 88e9716839
commit fe58cb3c7c
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
3 changed files with 52 additions and 13 deletions

View file

@ -4,6 +4,8 @@ from .utils import (
LoadError, LoadError,
IncompatibleLoaderError, IncompatibleLoaderError,
InvalidRepresentationContext, InvalidRepresentationContext,
LoaderSwitchNotImplementedError,
LoaderNotFoundError,
get_repres_contexts, get_repres_contexts,
get_contexts_for_repre_docs, get_contexts_for_repre_docs,
@ -55,6 +57,8 @@ __all__ = (
"LoadError", "LoadError",
"IncompatibleLoaderError", "IncompatibleLoaderError",
"InvalidRepresentationContext", "InvalidRepresentationContext",
"LoaderSwitchNotImplementedError",
"LoaderNotFoundError",
"get_repres_contexts", "get_repres_contexts",
"get_contexts_for_repre_docs", "get_contexts_for_repre_docs",

View file

@ -79,6 +79,16 @@ class InvalidRepresentationContext(ValueError):
pass pass
class LoaderSwitchNotImplementedError(NotImplementedError):
"""Error when `switch` is used with Loader that has no implementation."""
pass
class LoaderNotFoundError(RuntimeError):
"""Error when Loader plugin for a loader name is not found."""
pass
def get_repres_contexts(representation_ids, dbcon=None): def get_repres_contexts(representation_ids, dbcon=None):
"""Return parenthood context for representation. """Return parenthood context for representation.
@ -432,7 +442,10 @@ def remove_container(container):
Loader = _get_container_loader(container) Loader = _get_container_loader(container)
if not Loader: if not Loader:
raise RuntimeError("Can't remove container. See log for details.") raise LoaderNotFoundError(
"Can't remove container because loader '{}' was not found."
.format(container.get("loader"))
)
loader = Loader(get_representation_context(container["representation"])) loader = Loader(get_representation_context(container["representation"]))
return loader.remove(container) return loader.remove(container)
@ -480,7 +493,10 @@ def update_container(container, version=-1):
# Run update on the Loader for this container # Run update on the Loader for this container
Loader = _get_container_loader(container) Loader = _get_container_loader(container)
if not Loader: if not Loader:
raise RuntimeError("Can't update container. See log for details.") raise LoaderNotFoundError(
"Can't update container because loader '{}' was not found."
.format(container.get("loader"))
)
loader = Loader(get_representation_context(container["representation"])) loader = Loader(get_representation_context(container["representation"]))
return loader.update(container, new_representation) return loader.update(container, new_representation)
@ -502,15 +518,18 @@ def switch_container(container, representation, loader_plugin=None):
loader_plugin = _get_container_loader(container) loader_plugin = _get_container_loader(container)
if not loader_plugin: if not loader_plugin:
raise RuntimeError("Can't switch container. See log for details.") raise LoaderNotFoundError(
"Can't switch container because loader '{}' was not found."
.format(container.get("loader"))
)
if not hasattr(loader_plugin, "switch"): if not hasattr(loader_plugin, "switch"):
# Backwards compatibility (classes without switch support # Backwards compatibility (classes without switch support
# might be better to just have "switch" raise NotImplementedError # might be better to just have "switch" raise NotImplementedError
# on the base class of Loader\ # on the base class of Loader\
raise RuntimeError("Loader '{}' does not support 'switch'".format( raise LoaderSwitchNotImplementedError(
loader_plugin.label "Loader {} does not support 'switch'".format(loader_plugin.label)
)) )
# Get the new representation to switch to # Get the new representation to switch to
project_name = legacy_io.active_project() project_name = legacy_io.active_project()
@ -520,7 +539,11 @@ def switch_container(container, representation, loader_plugin=None):
new_context = get_representation_context(new_representation) new_context = get_representation_context(new_representation)
if not is_compatible_loader(loader_plugin, new_context): if not is_compatible_loader(loader_plugin, new_context):
raise AssertionError("Must be compatible Loader") raise IncompatibleLoaderError(
"Loader {} is incompatible with {}".format(
loader_plugin.__name__, new_context["subset"]["name"]
)
)
loader = loader_plugin(new_context) loader = loader_plugin(new_context)

View file

@ -19,6 +19,9 @@ from openpype.pipeline.load import (
switch_container, switch_container,
get_repres_contexts, get_repres_contexts,
loaders_from_repre_context, loaders_from_repre_context,
LoaderSwitchNotImplementedError,
IncompatibleLoaderError,
LoaderNotFoundError
) )
from .widgets import ( from .widgets import (
@ -1298,19 +1301,28 @@ class SwitchAssetDialog(QtWidgets.QDialog):
else: else:
repre_doc = repres_by_name[container_repre_name] repre_doc = repres_by_name[container_repre_name]
error = None
try: try:
switch_container(container, repre_doc, loader) switch_container(container, repre_doc, loader)
except (
LoaderSwitchNotImplementedError,
IncompatibleLoaderError,
LoaderNotFoundError,
) as exc:
error = str(exc)
except Exception: except Exception:
msg = ( error = (
"Switch asset failed. "
"Search console log for more details."
)
if error is not None:
log.warning((
"Couldn't switch asset." "Couldn't switch asset."
"See traceback for more information." "See traceback for more information."
) ), exc_info=True)
log.warning(msg, exc_info=True)
dialog = QtWidgets.QMessageBox(self) dialog = QtWidgets.QMessageBox(self)
dialog.setWindowTitle("Switch asset failed") dialog.setWindowTitle("Switch asset failed")
dialog.setText( dialog.setText(error)
"Switch asset failed. Search console log for more details"
)
dialog.exec_() dialog.exec_()
self.switched.emit() self.switched.emit()