# mako/runtime.py
# Copyright (C) 2006-2015 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

"""provides runtime services for templates, including Context,
Namespace, and various helper functions."""

from mako import exceptions, util, compat
from mako.compat import compat_builtins
import sys


class Context(object):

    """Provides runtime namespace, output buffer, and various
    callstacks for templates.

    See :ref:`runtime_toplevel` for detail on the usage of
    :class:`.Context`.

     """

    def __init__(self, buffer, **data):
        self._buffer_stack = [buffer]

        self._data = data

        self._kwargs = data.copy()
        self._with_template = None
        self._outputting_as_unicode = None
        self.namespaces = {}

        # "capture" function which proxies to the
        # generic "capture" function
        self._data['capture'] = compat.partial(capture, self)

        # "caller" stack used by def calls with content
        self.caller_stack = self._data['caller'] = CallerStack()

    def _set_with_template(self, t):
        self._with_template = t
        illegal_names = t.reserved_names.intersection(self._data)
        if illegal_names:
            raise exceptions.NameConflictError(
                "Reserved words passed to render(): %s" %
                ", ".join(illegal_names))

    @property
    def lookup(self):
        """Return the :class:`.TemplateLookup` associated
        with this :class:`.Context`.

        """
        return self._with_template.lookup

    @property
    def kwargs(self):
        """Return the dictionary of top level keyword arguments associated
        with this :class:`.Context`.

        This dictionary only includes the top-level arguments passed to
        :meth:`.Template.render`.  It does not include names produced within
        the template execution such as local variable names or special names
        such as ``self``, ``next``, etc.

        The purpose of this dictionary is primarily for the case that
        a :class:`.Template` accepts arguments via its ``<%page>`` tag,
        which are normally expected to be passed via :meth:`.Template.render`,
        except the template is being called in an inheritance context,
        using the ``body()`` method.   :attr:`.Context.kwargs` can then be
        used to propagate these arguments to the inheriting template::

            ${next.body(**context.kwargs)}

        """
        return self._kwargs.copy()

    def push_caller(self, caller):
        """Push a ``caller`` callable onto the callstack for
        this :class:`.Context`."""

        self.caller_stack.append(caller)

    def pop_caller(self):
        """Pop a ``caller`` callable onto the callstack for this
        :class:`.Context`."""

        del self.caller_stack[-1]

    def keys(self):
        """Return a list of all names established in this :class:`.Context`."""

        return list(self._data.keys())

    def __getitem__(self, key):
        if key in self._data:
            return self._data[key]
        else:
            return compat_builtins.__dict__[key]

    def _push_writer(self):
        """push a capturing buffer onto this Context and return
        the new writer function."""

        buf = util.FastEncodingBuffer()
        self._buffer_stack.append(buf)
        return buf.write

    def _pop_buffer_and_writer(self):
        """pop the most recent capturing buffer from this Context
        and return the current writer after the pop.

        """

        buf = self._buffer_stack.pop()
        return buf, self._buffer_stack[-1].write

    def _push_buffer(self):
        """push a capturing buffer onto this Context."""

        self._push_writer()

    def _pop_buffer(self):
        """pop the most recent capturing buffer from this Context."""

        return self._buffer_stack.pop()

    def get(self, key, default=None):
        """Return a value from this :class:`.Context`."""

        return self._data.get(key, compat_builtins.__dict__.get(key, default))

    def write(self, string):
        """Write a string to this :class:`.Context` object's
        underlying output buffer."""

        self._buffer_stack[-1].write(string)

    def writer(self):
        """Return the current writer function."""

        return self._buffer_stack[-1].write

    def _copy(self):
        c = Context.__new__(Context)
        c._buffer_stack = self._buffer_stack
        c._data = self._data.copy()
        c._kwargs = self._kwargs
        c._with_template = self._with_template
        c._outputting_as_unicode = self._outputting_as_unicode
        c.namespaces = self.namespaces
        c.caller_stack = self.caller_stack
        return c

    def _locals(self, d):
        """Create a new :class:`.Context` with a copy of this
        :class:`.Context`'s current state,
        updated with the given dictionary.

        The :attr:`.Context.kwargs` collection remains
        unaffected.


        """

        if not d:
            return self
        c = self._copy()
        c._data.update(d)
        return c

    def _clean_inheritance_tokens(self):
        """create a new copy of this :class:`.Context`. with
        tokens related to inheritance state removed."""

        c = self._copy()
        x = c._data
        x.pop('self', None)
        x.pop('parent', None)
        x.pop('next', None)
        return c


class CallerStack(list):

    def __init__(self):
        self.nextcaller = None

    def __nonzero__(self):
        return self.__bool__()

    def __bool__(self):
        return len(self) and self._get_caller() and True or False

    def _get_caller(self):
        # this method can be removed once
        # codegen MAGIC_NUMBER moves past 7
        return self[-1]

    def __getattr__(self, key):
        return getattr(self._get_caller(), key)

    def _push_frame(self):
        frame = self.nextcaller or None
        self.append(frame)
        self.nextcaller = None
        return frame

    def _pop_frame(self):
        self.nextcaller = self.pop()


class Undefined(object):

    """Represents an undefined value in a template.

    All template modules have a constant value
    ``UNDEFINED`` present which is an instance of this
    object.

    """

    def __str__(self):
        raise NameError("Undefined")

    def __nonzero__(self):
        return self.__bool__()

    def __bool__(self):
        return False

UNDEFINED = Undefined()
STOP_RENDERING = ""


class LoopStack(object):

    """a stack for LoopContexts that implements the context manager protocol
    to automatically pop off the top of the stack on context exit
    """

    def __init__(self):
        self.stack = []

    def _enter(self, iterable):
        self._push(iterable)
        return self._top

    def _exit(self):
        self._pop()
        return self._top

    @property
    def _top(self):
        if self.stack:
            return self.stack[-1]
        else:
            return self

    def _pop(self):
        return self.stack.pop()

    def _push(self, iterable):
        new = LoopContext(iterable)
        if self.stack:
            new.parent = self.stack[-1]
        return self.stack.append(new)

    def __getattr__(self, key):
        raise exceptions.RuntimeException("No loop context is established")

    def __iter__(self):
        return iter(self._top)


class LoopContext(object):

    """A magic loop variable.
    Automatically accessible in any ``% for`` block.

    See the section :ref:`loop_context` for usage
    notes.

    :attr:`parent` -> :class:`.LoopContext` or ``None``
        The parent loop, if one exists.
    :attr:`index` -> `int`
        The 0-based iteration count.
    :attr:`reverse_index` -> `int`
        The number of iterations remaining.
    :attr:`first` -> `bool`
        ``True`` on the first iteration, ``False`` otherwise.
    :attr:`last` -> `bool`
        ``True`` on the last iteration, ``False`` otherwise.
    :attr:`even` -> `bool`
        ``True`` when ``index`` is even.
    :attr:`odd` -> `bool`
        ``True`` when ``index`` is odd.
    """

    def __init__(self, iterable):
        self._iterable = iterable
        self.index = 0
        self.parent = None

    def __iter__(self):
        for i in self._iterable:
            yield i
            self.index += 1

    @util.memoized_instancemethod
    def __len__(self):
        return len(self._iterable)

    @property
    def reverse_index(self):
        return len(self) - self.index - 1

    @property
    def first(self):
        return self.index == 0

    @property
    def last(self):
        return self.index == len(self) - 1

    @property
    def even(self):
        return not self.odd

    @property
    def odd(self):
        return bool(self.index % 2)

    def cycle(self, *values):
        """Cycle through values as the loop progresses.
        """
        if not values:
            raise ValueError("You must provide values to cycle through")
        return values[self.index % len(values)]


class _NSAttr(object):

    def __init__(self, parent):
        self.__parent = parent

    def __getattr__(self, key):
        ns = self.__parent
        while ns:
            if hasattr(ns.module, key):
                return getattr(ns.module, key)
            else:
                ns = ns.inherits
        raise AttributeError(key)


class Namespace(object):

    """Provides access to collections of rendering methods, which
      can be local, from other templates, or from imported modules.

      To access a particular rendering method referenced by a
      :class:`.Namespace`, use plain attribute access:

      .. sourcecode:: mako

        ${some_namespace.foo(x, y, z)}

      :class:`.Namespace` also contains several built-in attributes
      described here.

      """

    def __init__(self, name, context,
                 callables=None, inherits=None,
                 populate_self=True, calling_uri=None):
        self.name = name
        self.context = context
        self.inherits = inherits
        if callables is not None:
            self.callables = dict([(c.__name__, c) for c in callables])

    callables = ()

    module = None
    """The Python module referenced by this :class:`.Namespace`.

    If the namespace references a :class:`.Template`, then
    this module is the equivalent of ``template.module``,
    i.e. the generated module for the template.

    """

    template = None
    """The :class:`.Template` object referenced by this
        :class:`.Namespace`, if any.

    """

    context = None
    """The :class:`.Context` object for this :class:`.Namespace`.

    Namespaces are often created with copies of contexts that
    contain slightly different data, particularly in inheritance
    scenarios. Using the :class:`.Context` off of a :class:`.Namespace` one
    can traverse an entire chain of templates that inherit from
    one-another.

    """

    filename = None
    """The path of the filesystem file used for this
    :class:`.Namespace`'s module or template.

    If this is a pure module-based
    :class:`.Namespace`, this evaluates to ``module.__file__``. If a
    template-based namespace, it evaluates to the original
    template file location.

    """

    uri = None
    """The URI for this :class:`.Namespace`'s template.

    I.e. whatever was sent to :meth:`.TemplateLookup.get_template()`.

    This is the equivalent of :attr:`.Template.uri`.

    """

    _templateuri = None

    @util.memoized_property
    def attr(self):
        """Access module level attributes by name.

        This accessor allows templates to supply "scalar"
        attributes which are particularly handy in inheritance
        relationships.

        .. seealso::

            :ref:`inheritance_attr`

            :ref:`namespace_attr_for_includes`

        """
        return _NSAttr(self)

    def get_namespace(self, uri):
        """Return a :class:`.Namespace` corresponding to the given ``uri``.

        If the given ``uri`` is a relative URI (i.e. it does not
        contain a leading slash ``/``), the ``uri`` is adjusted to
        be relative to the ``uri`` of the namespace itself. This
        method is therefore mostly useful off of the built-in
        ``local`` namespace, described in :ref:`namespace_local`.

        In
        most cases, a template wouldn't need this function, and
        should instead use the ``<%namespace>`` tag to load
        namespaces. However, since all ``<%namespace>`` tags are
        evaluated before the body of a template ever runs,
        this method can be used to locate namespaces using
        expressions that were generated within the body code of
        the template, or to conditionally use a particular
        namespace.

        """
        key = (self, uri)
        if key in self.context.namespaces:
            return self.context.namespaces[key]
        else:
            ns = TemplateNamespace(uri, self.context._copy(),
                                   templateuri=uri,
                                   calling_uri=self._templateuri)
            self.context.namespaces[key] = ns
            return ns

    def get_template(self, uri):
        """Return a :class:`.Template` from the given ``uri``.

        The ``uri`` resolution is relative to the ``uri`` of this
        :class:`.Namespace` object's :class:`.Template`.

        """
        return _lookup_template(self.context, uri, self._templateuri)

    def get_cached(self, key, **kwargs):
        """Return a value from the :class:`.Cache` referenced by this
        :class:`.Namespace` object's :class:`.Template`.

        The advantage to this method versus direct access to the
        :class:`.Cache` is that the configuration parameters
        declared in ``<%page>`` take effect here, thereby calling
        up the same configured backend as that configured
        by ``<%page>``.

        """

        return self.cache.get(key, **kwargs)

    @property
    def cache(self):
        """Return the :class:`.Cache` object referenced
        by this :class:`.Namespace` object's
        :class:`.Template`.

        """
        return self.template.cache

    def include_file(self, uri, **kwargs):
        """Include a file at the given ``uri``."""

        _include_file(self.context, uri, self._templateuri, **kwargs)

    def _populate(self, d, l):
        for ident in l:
            if ident == '*':
                for (k, v) in self._get_star():
                    d[k] = v
            else:
                d[ident] = getattr(self, ident)

    def _get_star(self):
        if self.callables:
            for key in self.callables:
                yield (key, self.callables[key])

    def __getattr__(self, key):
        if key in self.callables:
            val = self.callables[key]
        elif self.inherits:
            val = getattr(self.inherits, key)
        else:
            raise AttributeError(
                "Namespace '%s' has no member '%s'" %
                (self.name, key))
        setattr(self, key, val)
        return val


class TemplateNamespace(Namespace):

    """A :class:`.Namespace` specific to a :class:`.Template` instance."""

    def __init__(self, name, context, template=None, templateuri=None,
                 callables=None, inherits=None,
                 populate_self=True, calling_uri=None):
        self.name = name
        self.context = context
        self.inherits = inherits
        if callables is not None:
            self.callables = dict([(c.__name__, c) for c in callables])

        if templateuri is not None:
            self.template = _lookup_template(context, templateuri,
                                             calling_uri)
            self._templateuri = self.template.module._template_uri
        elif template is not None:
            self.template = template
            self._templateuri = template.module._template_uri
        else:
            raise TypeError("'template' argument is required.")

        if populate_self:
            lclcallable, lclcontext = \
                _populate_self_namespace(context, self.template,
                                         self_ns=self)

    @property
    def module(self):
        """The Python module referenced by this :class:`.Namespace`.

        If the namespace references a :class:`.Template`, then
        this module is the equivalent of ``template.module``,
        i.e. the generated module for the template.

        """
        return self.template.module

    @property
    def filename(self):
        """The path of the filesystem file used for this
        :class:`.Namespace`'s module or template.
        """
        return self.template.filename

    @property
    def uri(self):
        """The URI for this :class:`.Namespace`'s template.

        I.e. whatever was sent to :meth:`.TemplateLookup.get_template()`.

        This is the equivalent of :attr:`.Template.uri`.

        """
        return self.template.uri

    def _get_star(self):
        if self.callables:
            for key in self.callables:
                yield (key, self.callables[key])

        def get(key):
            callable_ = self.template._get_def_callable(key)
            return compat.partial(callable_, self.context)
        for k in self.template.module._exports:
            yield (k, get(k))

    def __getattr__(self, key):
        if key in self.callables:
            val = self.callables[key]
        elif self.template.has_def(key):
            callable_ = self.template._get_def_callable(key)
            val = compat.partial(callable_, self.context)
        elif self.inherits:
            val = getattr(self.inherits, key)

        else:
            raise AttributeError(
                "Namespace '%s' has no member '%s'" %
                (self.name, key))
        setattr(self, key, val)
        return val


class ModuleNamespace(Namespace):

    """A :class:`.Namespace` specific to a Python module instance."""

    def __init__(self, name, context, module,
                 callables=None, inherits=None,
                 populate_self=True, calling_uri=None):
        self.name = name
        self.context = context
        self.inherits = inherits
        if callables is not None:
            self.callables = dict([(c.__name__, c) for c in callables])

        mod = __import__(module)
        for token in module.split('.')[1:]:
            mod = getattr(mod, token)
        self.module = mod

    @property
    def filename(self):
        """The path of the filesystem file used for this
        :class:`.Namespace`'s module or template.
        """
        return self.module.__file__

    def _get_star(self):
        if self.callables:
            for key in self.callables:
                yield (key, self.callables[key])
        for key in dir(self.module):
            if key[0] != '_':
                callable_ = getattr(self.module, key)
                if compat.callable(callable_):
                    yield key, compat.partial(callable_, self.context)

    def __getattr__(self, key):
        if key in self.callables:
            val = self.callables[key]
        elif hasattr(self.module, key):
            callable_ = getattr(self.module, key)
            val = compat.partial(callable_, self.context)
        elif self.inherits:
            val = getattr(self.inherits, key)
        else:
            raise AttributeError(
                "Namespace '%s' has no member '%s'" %
                (self.name, key))
        setattr(self, key, val)
        return val


def supports_caller(func):
    """Apply a caller_stack compatibility decorator to a plain
    Python function.

    See the example in :ref:`namespaces_python_modules`.

    """

    def wrap_stackframe(context, *args, **kwargs):
        context.caller_stack._push_frame()
        try:
            return func(context, *args, **kwargs)
        finally:
            context.caller_stack._pop_frame()
    return wrap_stackframe


def capture(context, callable_, *args, **kwargs):
    """Execute the given template def, capturing the output into
    a buffer.

    See the example in :ref:`namespaces_python_modules`.

    """

    if not compat.callable(callable_):
        raise exceptions.RuntimeException(
            "capture() function expects a callable as "
            "its argument (i.e. capture(func, *args, **kwargs))"
        )
    context._push_buffer()
    try:
        callable_(*args, **kwargs)
    finally:
        buf = context._pop_buffer()
    return buf.getvalue()


def _decorate_toplevel(fn):
    def decorate_render(render_fn):
        def go(context, *args, **kw):
            def y(*args, **kw):
                return render_fn(context, *args, **kw)
            try:
                y.__name__ = render_fn.__name__[7:]
            except TypeError:
                # < Python 2.4
                pass
            return fn(y)(context, *args, **kw)
        return go
    return decorate_render


def _decorate_inline(context, fn):
    def decorate_render(render_fn):
        dec = fn(render_fn)

        def go(*args, **kw):
            return dec(context, *args, **kw)
        return go
    return decorate_render


def _include_file(context, uri, calling_uri, **kwargs):
    """locate the template from the given uri and include it in
    the current output."""

    template = _lookup_template(context, uri, calling_uri)
    (callable_, ctx) = _populate_self_namespace(
        context._clean_inheritance_tokens(),
        template)
    callable_(ctx, **_kwargs_for_include(callable_, context._data, **kwargs))


def _inherit_from(context, uri, calling_uri):
    """called by the _inherit method in template modules to set
    up the inheritance chain at the start of a template's
    execution."""

    if uri is None:
        return None
    template = _lookup_template(context, uri, calling_uri)
    self_ns = context['self']
    ih = self_ns
    while ih.inherits is not None:
        ih = ih.inherits
    lclcontext = context._locals({'next': ih})
    ih.inherits = TemplateNamespace("self:%s" % template.uri,
                                    lclcontext,
                                    template=template,
                                    populate_self=False)
    context._data['parent'] = lclcontext._data['local'] = ih.inherits
    callable_ = getattr(template.module, '_mako_inherit', None)
    if callable_ is not None:
        ret = callable_(template, lclcontext)
        if ret:
            return ret

    gen_ns = getattr(template.module, '_mako_generate_namespaces', None)
    if gen_ns is not None:
        gen_ns(context)
    return (template.callable_, lclcontext)


def _lookup_template(context, uri, relativeto):
    lookup = context._with_template.lookup
    if lookup is None:
        raise exceptions.TemplateLookupException(
            "Template '%s' has no TemplateLookup associated" %
            context._with_template.uri)
    uri = lookup.adjust_uri(uri, relativeto)
    try:
        return lookup.get_template(uri)
    except exceptions.TopLevelLookupException:
        raise exceptions.TemplateLookupException(str(compat.exception_as()))


def _populate_self_namespace(context, template, self_ns=None):
    if self_ns is None:
        self_ns = TemplateNamespace('self:%s' % template.uri,
                                    context, template=template,
                                    populate_self=False)
    context._data['self'] = context._data['local'] = self_ns
    if hasattr(template.module, '_mako_inherit'):
        ret = template.module._mako_inherit(template, context)
        if ret:
            return ret
    return (template.callable_, context)


def _render(template, callable_, args, data, as_unicode=False):
    """create a Context and return the string
    output of the given template and template callable."""

    if as_unicode:
        buf = util.FastEncodingBuffer(as_unicode=True)
    elif template.bytestring_passthrough:
        buf = compat.StringIO()
    else:
        buf = util.FastEncodingBuffer(
            as_unicode=as_unicode,
            encoding=template.output_encoding,
            errors=template.encoding_errors)
    context = Context(buf, **data)
    context._outputting_as_unicode = as_unicode
    context._set_with_template(template)

    _render_context(template, callable_, context, *args,
                    **_kwargs_for_callable(callable_, data))
    return context._pop_buffer().getvalue()


def _kwargs_for_callable(callable_, data):
    argspec = compat.inspect_func_args(callable_)
    # for normal pages, **pageargs is usually present
    if argspec[2]:
        return data

    # for rendering defs from the top level, figure out the args
    namedargs = argspec[0] + [v for v in argspec[1:3] if v is not None]
    kwargs = {}
    for arg in namedargs:
        if arg != 'context' and arg in data and arg not in kwargs:
            kwargs[arg] = data[arg]
    return kwargs


def _kwargs_for_include(callable_, data, **kwargs):
    argspec = compat.inspect_func_args(callable_)
    namedargs = argspec[0] + [v for v in argspec[1:3] if v is not None]
    for arg in namedargs:
        if arg != 'context' and arg in data and arg not in kwargs:
            kwargs[arg] = data[arg]
    return kwargs


def _render_context(tmpl, callable_, context, *args, **kwargs):
    import mako.template as template
    # create polymorphic 'self' namespace for this
    # template with possibly updated context
    if not isinstance(tmpl, template.DefTemplate):
        # if main render method, call from the base of the inheritance stack
        (inherit, lclcontext) = _populate_self_namespace(context, tmpl)
        _exec_template(inherit, lclcontext, args=args, kwargs=kwargs)
    else:
        # otherwise, call the actual rendering method specified
        (inherit, lclcontext) = _populate_self_namespace(context, tmpl.parent)
        _exec_template(callable_, context, args=args, kwargs=kwargs)


def _exec_template(callable_, context, args=None, kwargs=None):
    """execute a rendering callable given the callable, a
    Context, and optional explicit arguments

    the contextual Template will be located if it exists, and
    the error handling options specified on that Template will
    be interpreted here.
    """
    template = context._with_template
    if template is not None and \
            (template.format_exceptions or template.error_handler):
        try:
            callable_(context, *args, **kwargs)
        except Exception:
            _render_error(template, context, compat.exception_as())
        except:
            e = sys.exc_info()[0]
            _render_error(template, context, e)
    else:
        callable_(context, *args, **kwargs)


def _render_error(template, context, error):
    if template.error_handler:
        result = template.error_handler(context, error)
        if not result:
            compat.reraise(*sys.exc_info())
    else:
        error_template = exceptions.html_error_template()
        if context._outputting_as_unicode:
            context._buffer_stack[:] = [
                util.FastEncodingBuffer(as_unicode=True)]
        else:
            context._buffer_stack[:] = [util.FastEncodingBuffer(
                error_template.output_encoding,
                error_template.encoding_errors)]

        context._set_with_template(error_template)
        error_template.render_context(context, error=error)
