"""quixote.errors

Exception classes used by Quixote
"""

class PublishError (Exception):
    """PublishError exceptions are raised due to some problem with the
    data provided by the client and are raised during the publishing
    process.  Quixote will abort the current request and return an error
    to the client.  The error returned to the client is controlled by the
    format method.

    The formatting done by the Quixote versions of these exceptions is
    very simple.  Applications will probably wish to raise application
    specific subclasses which do more sophisticated formatting.
    """

    def format (self, request):
        """format(request : HTTPRequest) -> string

        Called by Quixote to return a response to the user.
        """
        return None                     # use default formatting


class TraversalError (PublishError):
    """
    Raised when a client attempts to access a resource that does not
    exist or is otherwise unavailable to them (eg. a Python function
    not listed in its module's _q_exports list).

    public_msg should be a user-readable message that reveals no
    inner workings of your application; it will always be shown.  If
    not supplied, an innocuous default ("Resource not found") will be
    shown.

    private_msg will only be shown if the config option
    SECURE_ERRORS is false; Quixote uses this to give you more
    detail about why a resource was not found -- eg. Python module
    couldn't be imported, name exists but not in _q_exports, etc.
    You might want to use it for similar, application-specific
    information.  (SECURE_ERRORS should always be true in a
    production environment, since these details about the inner
    workings of your application could conceivably be useful to
    attackers.)

    path should be the path to the requested resource; if not
    supplied, the current request object will be fetched and its
    get_path() method called.
    """

    # XXX it should be possible to make publish raise an application
    # specific subclass of this exception

    def __init__ (self, public_msg = "Resource not found",
                  private_msg=None, path=None):
        if private_msg is None: private_msg = public_msg
        if path is None:
            import quixote
            path = quixote.get_request().get_path()

        self.public_msg = public_msg
        self.private_msg = private_msg
        self.path = path

    def __str__ (self):
        if self.private_msg:
            return "%s: %s" % (self.path, self.private_msg)
        else:
            return self.path


class QueryError (PublishError):
    """Should be raised if bad data was provided in the query part of a
    URL or in the content of a POST request.  What constitutes bad data is
    solely application dependent (eg: letters in a form field when the
    application expects a number).

    The formatting done by this exception is very simple.  Applications
    will probably wish to raise subclasses which do more sophisticated
    formatting.
    """

    def __init__ (self, msg=None):
        self.msg = msg or "Invalid query"

    def __str__ (self):
        return self.msg


class AccessError (PublishError):
    """Should be raised raised if the client does not have access to the
    requested resource.  Usually applications will raise this error from
    an _q_access method.
    """

    def __init__ (self, msg=None):
        self.msg = msg or "Access denied"
    
    def __str__ (self):
        return self.msg


class SessionError (PublishError):
    """Raised when a session cookie has an invalid session ID.  This
    could be either a broken/malicious client or an expired session.
    """

    def __init__ (self, msg=None, session_id=None):
        self.msg = msg or "Expired or invalid session ID"
        self.session_id = session_id

    def __str__ (self):
        if self.session_id is None:
            return self.msg
        else:
            return "%s: %s" % (self.msg, self.session_id)
