# mako/exceptions.py
# Copyright (C) 2006-2014 the Mako authors and contributors <see AUTHORS file>
#
# This module is part of Mako and is released under
# the MIT License: http://www.opensource.org/licenses/mit-license.php

"""exception classes"""

import traceback
import sys
from mako import util, compat

class MakoException(Exception):
    pass

class RuntimeException(MakoException):
    pass

def _format_filepos(lineno, pos, filename):
    if filename is None:
        return " at line: %d char: %d" % (lineno, pos)
    else:
        return " in file '%s' at line: %d char: %d" % (filename, lineno, pos)


class CompileException(MakoException):
    def __init__(self, message, source, lineno, pos, filename):
        MakoException.__init__(self,
                              message + _format_filepos(lineno, pos, filename))
        self.lineno = lineno
        self.pos = pos
        self.filename = filename
        self.source = source

class SyntaxException(MakoException):
    def __init__(self, message, source, lineno, pos, filename):
        MakoException.__init__(self,
                              message + _format_filepos(lineno, pos, filename))
        self.lineno = lineno
        self.pos = pos
        self.filename = filename
        self.source = source

class UnsupportedError(MakoException):
    """raised when a retired feature is used."""

class NameConflictError(MakoException):
    """raised when a reserved word is used inappropriately"""

class TemplateLookupException(MakoException):
    pass

class TopLevelLookupException(TemplateLookupException):
    pass

class RichTraceback(object):
    """Pull the current exception from the ``sys`` traceback and extracts
    Mako-specific template information.

    See the usage examples in :ref:`handling_exceptions`.

    """
    def __init__(self, error=None, traceback=None):
        self.source, self.lineno = "", 0

        if error is None or traceback is None:
            t, value, tback = sys.exc_info()

        if error is None:
            error = value or t

        if traceback is None:
            traceback = tback

        self.error = error
        self.records = self._init(traceback)

        if isinstance(self.error, (CompileException, SyntaxException)):
            self.source = self.error.source
            self.lineno = self.error.lineno
            self._has_source = True

        self._init_message()

    @property
    def errorname(self):
        return compat.exception_name(self.error)

    def _init_message(self):
        """Find a unicode representation of self.error"""
        try:
            self.message = compat.text_type(self.error)
        except UnicodeError:
            try:
                self.message = str(self.error)
            except UnicodeEncodeError:
                # Fallback to args as neither unicode nor
                # str(Exception(u'\xe6')) work in Python < 2.6
                self.message = self.error.args[0]
        if not isinstance(self.message, compat.text_type):
            self.message = compat.text_type(self.message, 'ascii', 'replace')

    def _get_reformatted_records(self, records):
        for rec in records:
            if rec[6] is not None:
                yield (rec[4], rec[5], rec[2], rec[6])
            else:
                yield tuple(rec[0:4])

    @property
    def traceback(self):
        """Return a list of 4-tuple traceback records (i.e. normal python
        format) with template-corresponding lines remapped to the originating
        template.

        """
        return list(self._get_reformatted_records(self.records))

    @property
    def reverse_records(self):
        return reversed(self.records)

    @property
    def reverse_traceback(self):
        """Return the same data as traceback, except in reverse order.
        """

        return list(self._get_reformatted_records(self.reverse_records))

    def _init(self, trcback):
        """format a traceback from sys.exc_info() into 7-item tuples,
        containing the regular four traceback tuple items, plus the original
        template filename, the line number adjusted relative to the template
        source, and code line from that line number of the template."""

        import mako.template
        mods = {}
        rawrecords = traceback.extract_tb(trcback)
        new_trcback = []
        for filename, lineno, function, line in rawrecords:
            if not line:
                line = ''
            try:
                (line_map, template_lines) = mods[filename]
            except KeyError:
                try:
                    info = mako.template._get_module_info(filename)
                    module_source = info.code
                    template_source = info.source
                    template_filename = info.template_filename or filename
                except KeyError:
                    # A normal .py file (not a Template)
                    if not compat.py3k:
                        try:
                            fp = open(filename, 'rb')
                            encoding = util.parse_encoding(fp)
                            fp.close()
                        except IOError:
                            encoding = None
                        if encoding:
                            line = line.decode(encoding)
                        else:
                            line = line.decode('ascii', 'replace')
                    new_trcback.append((filename, lineno, function, line,
                                            None, None, None, None))
                    continue

                template_ln = 1

                source_map = mako.template.ModuleInfo.\
                                get_module_source_metadata(
                                    module_source, full_line_map=True)
                line_map = source_map['full_line_map']

                template_lines = [line for line in
                                    template_source.split("\n")]
                mods[filename] = (line_map, template_lines)

            template_ln = line_map[lineno - 1]

            if template_ln <= len(template_lines):
                template_line = template_lines[template_ln - 1]
            else:
                template_line = None
            new_trcback.append((filename, lineno, function,
                                line, template_filename, template_ln,
                                template_line, template_source))
        if not self.source:
            for l in range(len(new_trcback) - 1, 0, -1):
                if new_trcback[l][5]:
                    self.source = new_trcback[l][7]
                    self.lineno = new_trcback[l][5]
                    break
            else:
                if new_trcback:
                    try:
                        # A normal .py file (not a Template)
                        fp = open(new_trcback[-1][0], 'rb')
                        encoding = util.parse_encoding(fp)
                        fp.seek(0)
                        self.source = fp.read()
                        fp.close()
                        if encoding:
                            self.source = self.source.decode(encoding)
                    except IOError:
                        self.source = ''
                    self.lineno = new_trcback[-1][1]
        return new_trcback


def text_error_template(lookup=None):
    """Provides a template that renders a stack trace in a similar format to
    the Python interpreter, substituting source template filenames, line
    numbers and code for that of the originating source template, as
    applicable.

    """
    import mako.template
    return mako.template.Template(r"""
<%page args="error=None, traceback=None"/>
<%!
    from mako.exceptions import RichTraceback
%>\
<%
    tback = RichTraceback(error=error, traceback=traceback)
%>\
Traceback (most recent call last):
% for (filename, lineno, function, line) in tback.traceback:
  File "${filename}", line ${lineno}, in ${function or '?'}
    ${line | trim}
% endfor
${tback.errorname}: ${tback.message}
""")


def _install_pygments():
    global syntax_highlight, pygments_html_formatter
    from mako.ext.pygmentplugin import syntax_highlight,\
            pygments_html_formatter

def _install_fallback():
    global syntax_highlight, pygments_html_formatter
    from mako.filters import html_escape
    pygments_html_formatter = None
    def syntax_highlight(filename='', language=None):
        return html_escape

def _install_highlighting():
    try:
        _install_pygments()
    except ImportError:
        _install_fallback()
_install_highlighting()

def html_error_template():
    """Provides a template that renders a stack trace in an HTML format,
    providing an excerpt of code as well as substituting source template
    filenames, line numbers and code for that of the originating source
    template, as applicable.

    The template's default ``encoding_errors`` value is
    ``'htmlentityreplace'``. The template has two options. With the
    ``full`` option disabled, only a section of an HTML document is
    returned. With the ``css`` option disabled, the default stylesheet
    won't be included.

    """
    import mako.template
    return mako.template.Template(r"""
<%!
    from mako.exceptions import RichTraceback, syntax_highlight,\
            pygments_html_formatter
%>
<%page args="full=True, css=True, error=None, traceback=None"/>
% if full:
<html>
<head>
    <title>Mako Runtime Error</title>
% endif
% if css:
    <style>
        body { font-family:verdana; margin:10px 30px 10px 30px;}
        .stacktrace { margin:5px 5px 5px 5px; }
        .highlight { padding:0px 10px 0px 10px; background-color:#9F9FDF; }
        .nonhighlight { padding:0px; background-color:#DFDFDF; }
        .sample { padding:10px; margin:10px 10px 10px 10px;
                  font-family:monospace; }
        .sampleline { padding:0px 10px 0px 10px; }
        .sourceline { margin:5px 5px 10px 5px; font-family:monospace;}
        .location { font-size:80%; }
        .highlight { white-space:pre; }
        .sampleline { white-space:pre; }

    % if pygments_html_formatter:
        ${pygments_html_formatter.get_style_defs()}
        .linenos { min-width: 2.5em; text-align: right; }
        pre { margin: 0; }
        .syntax-highlighted { padding: 0 10px; }
        .syntax-highlightedtable { border-spacing: 1px; }
        .nonhighlight { border-top: 1px solid #DFDFDF;
                        border-bottom: 1px solid #DFDFDF; }
        .stacktrace .nonhighlight { margin: 5px 15px 10px; }
        .sourceline { margin: 0 0; font-family:monospace; }
        .code { background-color: #F8F8F8; width: 100%; }
        .error .code { background-color: #FFBDBD; }
        .error .syntax-highlighted { background-color: #FFBDBD; }
    % endif

    </style>
% endif
% if full:
</head>
<body>
% endif

<h2>Error !</h2>
<%
    tback = RichTraceback(error=error, traceback=traceback)
    src = tback.source
    line = tback.lineno
    if src:
        lines = src.split('\n')
    else:
        lines = None
%>
<h3>${tback.errorname}: ${tback.message|h}</h3>

% if lines:
    <div class="sample">
    <div class="nonhighlight">
% for index in range(max(0, line-4),min(len(lines), line+5)):
    <%
       if pygments_html_formatter:
           pygments_html_formatter.linenostart = index + 1
    %>
    % if index + 1 == line:
    <%
       if pygments_html_formatter:
           old_cssclass = pygments_html_formatter.cssclass
           pygments_html_formatter.cssclass = 'error ' + old_cssclass
    %>
        ${lines[index] | syntax_highlight(language='mako')}
    <%
       if pygments_html_formatter:
           pygments_html_formatter.cssclass = old_cssclass
    %>
    % else:
        ${lines[index] | syntax_highlight(language='mako')}
    % endif
% endfor
    </div>
    </div>
% endif

<div class="stacktrace">
% for (filename, lineno, function, line) in tback.reverse_traceback:
    <div class="location">${filename}, line ${lineno}:</div>
    <div class="nonhighlight">
    <%
       if pygments_html_formatter:
           pygments_html_formatter.linenostart = lineno
    %>
      <div class="sourceline">${line | syntax_highlight(filename)}</div>
    </div>
% endfor
</div>

% if full:
</body>
</html>
% endif
""", output_encoding=sys.getdefaultencoding(),
        encoding_errors='htmlentityreplace')
