Source code for ymp.exceptions
"""Exceptions raised by YMP"""
import textwrap
from inspect import stack
from typing import Optional
from click import ClickException, echo
[docs]class YmpException(Exception):
"""Base class of all YMP Exceptions"""
[docs]class YmpNoStackException(YmpException, ClickException):
"""Exception that does not lead to stack trace on CLI
Inheriting from ClickException makes ``click`` print only the
``self.msg`` value of the exception, rather than allowing Python
to print a full stack trace.
This is useful for exceptions indicating usage or configuration
errors. We use this, instead of `click.UsageError` and friends so
that the exceptions can be caught and handled explicitly where
needed.
Note that click will call the ``show`` method on this object to
print the exception. The default implementation from click will
just prefix the ``msg`` with ``Error:``.
FIXME: This does not work if the exception is raised from within
the snakemake workflow as snakemake.snakemake catches and
reformats exceptions.
"""
[docs]class YmpUsageError(YmpNoStackException):
pass
[docs]class YmpSystemError(YmpNoStackException):
"""Indicates problem running YMP with available system software"""
[docs]class YmpRuleError(YmpNoStackException):
"""Indicates an error in the rules files
This could e.g. be a Stage or Environment defined twice.
Args:
obj: The object causing the exception. Must have ``lineno``
and ``filename`` as these will be shown as part of the error
message on the command line.
msg: The message to display
"""
def __init__(self, obj: object, msg: str) -> None:
self.obj = obj
self.stack = stack()
super().__init__(msg)
[docs] def show(self) -> None:
echo('Error in line %i of %s:\n%s' % (
getattr(self.obj, "lineno", -1),
getattr(self.obj, "filename", "<NOT FOUND>"),
self.format_message()
), err=True)
for fi in self.stack:
if not fi.filename.endswith(".py"):
echo(f" included from {fi.filename}:{fi.lineno}")
[docs]class YmpConfigError(YmpNoStackException):
"""Indicates an error in the ymp.yml config files
Args:
obj: Subtree of config causing error
msg: The message to display
key: Key indicating part of ``obj`` causing error
exc: Upstream exception causing error
"""
def __init__(self, obj: object, msg: str, key: Optional[object]=None,
exc: Optional[Exception]=None) -> None:
self.obj = obj
self.stack = stack()
self.exc = exc
super().__init__(msg)
[docs]class YmpStageError(YmpNoStackException):
"""Indicates an error in the requested stage stack
"""
def __init__(self, msg: str) -> None:
super().__init__(textwrap.dedent(msg))
[docs] def show(self) -> None:
echo(self.format_message(), err=True)
[docs]class YmpWorkflowError(YmpNoStackException):
"""Indicates an error during workflow execution
E.g. failures to expand dynamic variables
"""