blob: 9228985babf23db2d8b4e122690f3ea2ca8001e3 [file] [log] [blame]
#
# -*- coding: utf-8 -*-
#
# This file is part of reclass (http://github.com/madduck/reclass)
#
# Copyright © 2007–14 martin f. krafft <madduck@madduck.net>
# Released under the terms of the Artistic Licence 2.0
#
import posix, sys
import traceback
from reclass.defaults import PARAMETER_INTERPOLATION_SENTINELS
class ReclassException(Exception):
def __init__(self, rc=posix.EX_SOFTWARE, msg=None):
super(ReclassException, self).__init__()
self._rc = rc
self._msg = msg
self._traceback = traceback.format_exc()
message = property(lambda self: self._get_message())
rc = property(lambda self: self._rc)
def __str__(self):
return self.message + '\n' + super(ReclassException, self).__str__()
def _get_message(self):
if self._msg:
return self._msg
else:
return 'No error message provided.'
def exit_with_message(self, out=sys.stderr):
print >>out, self.message
if self._traceback:
print >>out, self._traceback
sys.exit(self.rc)
class PermissionError(ReclassException):
def __init__(self, msg, rc=posix.EX_NOPERM):
super(PermissionError, self).__init__(rc=rc, msg=msg)
class InvocationError(ReclassException):
def __init__(self, msg, rc=posix.EX_USAGE):
super(InvocationError, self).__init__(rc=rc, msg=msg)
class ConfigError(ReclassException):
def __init__(self, msg, rc=posix.EX_CONFIG):
super(ConfigError, self).__init__(rc=rc, msg=msg)
class DuplicateUriError(ConfigError):
def __init__(self, nodes_uri, classes_uri):
super(DuplicateUriError, self).__init__(msg=None)
self._nodes_uri = nodes_uri
self._classes_uri = classes_uri
def _get_message(self):
return "The inventory URIs must not be the same " \
"for nodes and classes: {0}".format(self._nodes_uri)
class UriOverlapError(ConfigError):
def __init__(self, nodes_uri, classes_uri):
super(UriOverlapError, self).__init__(msg=None)
self._nodes_uri = nodes_uri
self._classes_uri = classes_uri
def _get_message(self):
msg = "The URIs for the nodes and classes inventories must not " \
"overlap, but {0} and {1} do."
return msg.format(self._nodes_uri, self._classes_uri)
class NotFoundError(ReclassException):
def __init__(self, msg, rc=posix.EX_IOERR):
super(NotFoundError, self).__init__(rc=rc, msg=msg)
class NodeNotFound(NotFoundError):
def __init__(self, storage, nodename, uri):
super(NodeNotFound, self).__init__(msg=None)
self._storage = storage
self._name = nodename
self._uri = uri
def _get_message(self):
msg = "Node '{0}' not found under {1}://{2}"
return msg.format(self._name, self._storage, self._uri)
class ClassNotFound(NotFoundError):
def __init__(self, storage, classname, uri, nodename=None):
super(ClassNotFound, self).__init__(msg=None)
self._storage = storage
self._name = classname
self._uri = uri
self._nodename = nodename
def _get_message(self):
if self._nodename:
msg = "Class '{0}' (in ancestry of node '{1}') not found " \
"under {2}://{3}"
else:
msg = "Class '{0}' not found under {2}://{3}"
return msg.format(self._name, self._nodename, self._storage, self._uri)
def set_nodename(self, nodename):
self._nodename = nodename
class InterpolationError(ReclassException):
def __init__(self, msg, rc=posix.EX_DATAERR):
super(InterpolationError, self).__init__(rc=rc, msg=msg)
class UndefinedVariableError(InterpolationError):
def __init__(self, var, context=None):
super(UndefinedVariableError, self).__init__(msg=None)
self._var = var
self._context = context
var = property(lambda self: self._var)
context = property(lambda self: self._context)
def _get_message(self):
msg = "Cannot resolve " + self._var.join(PARAMETER_INTERPOLATION_SENTINELS)
if self._context:
msg += ' in the context of %s' % self._context
return msg
def set_context(self, context):
self._context = context
class IncompleteInterpolationError(InterpolationError):
def __init__(self, string, end_sentinel):
super(IncompleteInterpolationError, self).__init__(msg=None)
self._ref = string.join(PARAMETER_INTERPOLATION_SENTINELS)
self._end_sentinel = end_sentinel
def _get_message(self):
msg = "Missing '{0}' to end reference: {1}"
return msg.format(self._end_sentinel, self._ref)
class InfiniteRecursionError(InterpolationError):
def __init__(self, path, ref):
super(InfiniteRecursionError, self).__init__(msg=None)
self._path = path
self._ref = ref.join(PARAMETER_INTERPOLATION_SENTINELS)
def _get_message(self):
msg = "Infinite recursion while resolving {0} at {1}"
return msg.format(self._ref, self._path)
class MappingError(ReclassException):
def __init__(self, msg, rc=posix.EX_DATAERR):
super(MappingError, self).__init__(rc=rc, msg=msg)
class MappingFormatError(MappingError):
def __init__(self, msg):
super(MappingFormatError, self).__init__(msg)
class NameError(ReclassException):
def __init__(self, msg, rc=posix.EX_DATAERR):
super(NameError, self).__init__(rc=rc, msg=msg)
class InvalidClassnameError(NameError):
def __init__(self, invalid_character, classname):
super(InvalidClassnameError, self).__init__(msg=None)
self._char = invalid_character
self._classname = classname
def _get_message(self):
msg = "Invalid character '{0}' in class name '{1}'."
return msg.format(self._char, self._classname)
class DuplicateNodeNameError(NameError):
def __init__(self, storage, name, uri1, uri2):
super(DuplicateNodeNameError, self).__init__(msg=None)
self._storage = storage
self._name = name
self._uris = (uri1, uri2)
def _get_message(self):
msg = "{0}: Definition of node '{1}' in '{2}' collides with " \
"definition in '{3}'. Nodes can only be defined once " \
"per inventory."
return msg.format(self._storage, self._name, self._uris[1], self._uris[0])