metaflow/exception.py (115 lines of code) (raw):
import sys
import traceback
# worker processes that exit with this exit code are not retried
METAFLOW_EXIT_DISALLOW_RETRY = 202
# worker processes that exit with this code should be retried (if retry counts left)
METAFLOW_EXIT_ALLOW_RETRY = 203
class MetaflowExceptionWrapper(Exception):
def __init__(self, exc=None):
if exc is not None:
self.exception = str(exc)
self.type = "%s.%s" % (exc.__class__.__module__, exc.__class__.__name__)
if sys.exc_info()[0] is None:
self.stacktrace = None
else:
self.stacktrace = traceback.format_exc()
# Base Exception defines its own __reduce__ and __setstate__
# which don't work nicely with derived exceptions. We override
# the magic methods related to pickle to get desired behavior.
def __reduce__(self):
return MetaflowExceptionWrapper, (None,), self.__dict__
def __getstate__(self):
return self.__dict__
def __setstate__(self, state):
self.__dict__ = state
def __repr__(self):
return str(self)
def __str__(self):
if self.stacktrace:
return self.stacktrace
else:
return "[no stacktrace]\n%s: %s" % (self.type, self.exception)
class MetaflowException(Exception):
headline = "Flow failed"
def __init__(self, msg="", lineno=None, source_file=None):
self.message = msg
self.line_no = lineno
self.source_file = source_file
super(MetaflowException, self).__init__()
def __str__(self):
prefix = ""
if self.source_file:
prefix = "%s:" % self.source_file
if self.line_no:
prefix = "line %d:" % self.line_no
prefix = "%s: " % prefix if prefix else ""
return "%s%s" % (prefix, self.message)
class ParameterFieldFailed(MetaflowException):
headline = "Parameter field failed"
def __init__(self, name, field):
exc = traceback.format_exc()
msg = (
"When evaluating the field *%s* for the Parameter *%s*, "
"the following exception occurred:\n\n%s" % (field, name, exc)
)
super(ParameterFieldFailed, self).__init__(msg)
class ParameterFieldTypeMismatch(MetaflowException):
headline = "Parameter field with a mismatching type"
def __init__(self, msg):
super(ParameterFieldTypeMismatch, self).__init__(msg)
class ExternalCommandFailed(MetaflowException):
headline = "External command failed"
def __init__(self, msg):
super(ExternalCommandFailed, self).__init__(msg)
class MetaflowNotFound(MetaflowException):
headline = "Object not found"
class MetaflowNamespaceMismatch(MetaflowException):
headline = "Object not in the current namespace"
def __init__(self, namespace):
msg = "Object not in namespace '%s'" % namespace
super(MetaflowNamespaceMismatch, self).__init__(msg)
class MetaflowInvalidPathspec(MetaflowException):
headline = "Invalid pathspec"
def __init__(self, msg):
super(MetaflowInvalidPathspec, self).__init__(msg)
class MetaflowInternalError(MetaflowException):
headline = "Internal error"
class MetaflowTaggingError(MetaflowException):
headline = "Tagging error"
class MetaflowUnknownUser(MetaflowException):
headline = "Unknown user"
def __init__(self):
msg = (
"Metaflow could not determine your user name based on "
"environment variables ($USERNAME etc.)"
)
super(MetaflowUnknownUser, self).__init__(msg)
class InvalidDecoratorAttribute(MetaflowException):
headline = "Unknown decorator attribute"
def __init__(self, deconame, attr, defaults):
msg = (
"Decorator '{deco}' does not support the attribute '{attr}'. "
"These attributes are supported: {defaults}.".format(
deco=deconame, attr=attr, defaults=", ".join(defaults)
)
)
super(InvalidDecoratorAttribute, self).__init__(msg)
class CommandException(MetaflowException):
headline = "Invalid command"
class MetaflowDataMissing(MetaflowException):
headline = "Data missing"
class UnhandledInMergeArtifactsException(MetaflowException):
headline = "Unhandled artifacts in merge"
def __init__(self, msg, unhandled):
super(UnhandledInMergeArtifactsException, self).__init__(msg)
self.artifact_names = unhandled
class MissingInMergeArtifactsException(MetaflowException):
headline = "Missing artifacts in merge"
def __init__(self, msg, unhandled):
super(MissingInMergeArtifactsException, self).__init__(msg)
self.artifact_names = unhandled
# Import any exceptions defined by a Metaflow extensions packages
try:
from metaflow.extension_support import get_modules, multiload_globals
multiload_globals(get_modules("exceptions"), globals())
finally:
# Erase all temporary names to avoid leaking things
for _n in ["get_modules", "multiload_globals"]:
try:
del globals()[_n]
except KeyError:
pass
del globals()["_n"]