# mako/template.py
# Copyright (C) 2006-2012 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 the Template class, a facade for parsing, generating and executing
template strings, as well as template runtime operations."""

from mako.lexer import Lexer
from mako import runtime, util, exceptions, codegen, cache, compat
import os
import re
import shutil
import stat
import sys
import tempfile
import types
import weakref


class Template(object):
    """Represents a compiled template.

    :class:`.Template` includes a reference to the original
    template source (via the :attr:`.source` attribute)
    as well as the source code of the
    generated Python module (i.e. the :attr:`.code` attribute),
    as well as a reference to an actual Python module.

    :class:`.Template` is constructed using either a literal string
    representing the template text, or a filename representing a filesystem
    path to a source file.

    :param text: textual template source.  This argument is mutually
     exclusive versus the ``filename`` parameter.

    :param filename: filename of the source template.  This argument is
     mutually exclusive versus the ``text`` parameter.

    :param buffer_filters: string list of filters to be applied
     to the output of ``%def``\ s which are buffered, cached, or otherwise
     filtered, after all filters
     defined with the ``%def`` itself have been applied. Allows the
     creation of default expression filters that let the output
     of return-valued ``%def``\ s "opt out" of that filtering via
     passing special attributes or objects.

    :param bytestring_passthrough: When ``True``, and ``output_encoding`` is
     set to ``None``, and :meth:`.Template.render` is used to render,
     the `StringIO` or `cStringIO` buffer will be used instead of the
     default "fast" buffer.   This allows raw bytestrings in the
     output stream, such as in expressions, to pass straight
     through to the buffer.  This flag is forced
     to ``True`` if ``disable_unicode`` is also configured.

     .. versionadded:: 0.4
        Added to provide the same behavior as that of the previous series.

    :param cache_args: Dictionary of cache configuration arguments that
     will be passed to the :class:`.CacheImpl`.   See :ref:`caching_toplevel`.

    :param cache_dir:

     .. deprecated:: 0.6
        Use the ``'dir'`` argument in the ``cache_args`` dictionary.
        See :ref:`caching_toplevel`.

    :param cache_enabled: Boolean flag which enables caching of this
     template.  See :ref:`caching_toplevel`.

    :param cache_impl: String name of a :class:`.CacheImpl` caching
     implementation to use.   Defaults to ``'beaker'``.

    :param cache_type:

     .. deprecated:: 0.6
        Use the ``'type'`` argument in the ``cache_args`` dictionary.
        See :ref:`caching_toplevel`.

    :param cache_url:

     .. deprecated:: 0.6
        Use the ``'url'`` argument in the ``cache_args`` dictionary.
        See :ref:`caching_toplevel`.

    :param default_filters: List of string filter names that will
     be applied to all expressions.  See :ref:`filtering_default_filters`.

    :param disable_unicode: Disables all awareness of Python Unicode
     objects.  See :ref:`unicode_disabled`.

    :param enable_loop: When ``True``, enable the ``loop`` context variable.
     This can be set to ``False`` to support templates that may
     be making usage of the name "``loop``".   Individual templates can
     re-enable the "loop" context by placing the directive
     ``enable_loop="True"`` inside the ``<%page>`` tag -- see
     :ref:`migrating_loop`.

    :param encoding_errors: Error parameter passed to ``encode()`` when
     string encoding is performed. See :ref:`usage_unicode`.

    :param error_handler: Python callable which is called whenever
     compile or runtime exceptions occur. The callable is passed
     the current context as well as the exception. If the
     callable returns ``True``, the exception is considered to
     be handled, else it is re-raised after the function
     completes. Is used to provide custom error-rendering
     functions.

    :param format_exceptions: if ``True``, exceptions which occur during
     the render phase of this template will be caught and
     formatted into an HTML error page, which then becomes the
     rendered result of the :meth:`.render` call. Otherwise,
     runtime exceptions are propagated outwards.

    :param imports: String list of Python statements, typically individual
     "import" lines, which will be placed into the module level
     preamble of all generated Python modules. See the example
     in :ref:`filtering_default_filters`.

    :param future_imports: String list of names to import from `__future__`.
     These will be concatenated into a comma-separated string and inserted
     into the beginning of the template, e.g. ``futures_imports=['FOO',
     'BAR']`` results in ``from __future__ import FOO, BAR``.  If you're
     interested in using features like the new division operator, you must
     use future_imports to convey that to the renderer, as otherwise the
     import will not appear as the first executed statement in the generated
     code and will therefore not have the desired effect.

    :param input_encoding: Encoding of the template's source code.  Can
     be used in lieu of the coding comment. See
     :ref:`usage_unicode` as well as :ref:`unicode_toplevel` for
     details on source encoding.

    :param lookup: a :class:`.TemplateLookup` instance that will be used
     for all file lookups via the ``<%namespace>``,
     ``<%include>``, and ``<%inherit>`` tags. See
     :ref:`usage_templatelookup`.

    :param module_directory: Filesystem location where generated
     Python module files will be placed.

    :param module_filename: Overrides the filename of the generated
     Python module file. For advanced usage only.

    :param module_writer: A callable which overrides how the Python
     module is written entirely.  The callable is passed the
     encoded source content of the module and the destination
     path to be written to.   The default behavior of module writing
     uses a tempfile in conjunction with a file move in order
     to make the operation atomic.   So a user-defined module
     writing function that mimics the default behavior would be:

     .. sourcecode:: python

         import tempfile
         import os
         import shutil

         def module_writer(source, outputpath):
             (dest, name) = \\
                 tempfile.mkstemp(
                     dir=os.path.dirname(outputpath)
                 )

             os.write(dest, source)
             os.close(dest)
             shutil.move(name, outputpath)

         from mako.template import Template
         mytemplate = Template(
                         file="index.html",
                         module_directory="/path/to/modules",
                         module_writer=module_writer
                     )

     The function is provided for unusual configurations where
     certain platform-specific permissions or other special
     steps are needed.

    :param output_encoding: The encoding to use when :meth:`.render`
     is called.
     See :ref:`usage_unicode` as well as :ref:`unicode_toplevel`.

    :param preprocessor: Python callable which will be passed
     the full template source before it is parsed. The return
     result of the callable will be used as the template source
     code.

    :param strict_undefined: Replaces the automatic usage of
     ``UNDEFINED`` for any undeclared variables not located in
     the :class:`.Context` with an immediate raise of
     ``NameError``. The advantage is immediate reporting of
     missing variables which include the name.

     .. versionadded:: 0.3.6

    :param uri: string URI or other identifier for this template.
     If not provided, the ``uri`` is generated from the filesystem
     path, or from the in-memory identity of a non-file-based
     template. The primary usage of the ``uri`` is to provide a key
     within :class:`.TemplateLookup`, as well as to generate the
     file path of the generated Python module file, if
     ``module_directory`` is specified.

    """

    def __init__(self,
                    text=None,
                    filename=None,
                    uri=None,
                    format_exceptions=False,
                    error_handler=None,
                    lookup=None,
                    output_encoding=None,
                    encoding_errors='strict',
                    module_directory=None,
                    cache_args=None,
                    cache_impl='beaker',
                    cache_enabled=True,
                    cache_type=None,
                    cache_dir=None,
                    cache_url=None,
                    module_filename=None,
                    input_encoding=None,
                    disable_unicode=False,
                    module_writer=None,
                    bytestring_passthrough=False,
                    default_filters=None,
                    buffer_filters=(),
                    strict_undefined=False,
                    imports=None,
                    future_imports=None,
                    enable_loop=True,
                    preprocessor=None):
        if uri:
            self.module_id = re.sub(r'\W', "_", uri)
            self.uri = uri
        elif filename:
            self.module_id = re.sub(r'\W', "_", filename)
            drive, path = os.path.splitdrive(filename)
            path = os.path.normpath(path).replace(os.path.sep, "/")
            self.uri = path
        else:
            self.module_id = "memory:" + hex(id(self))
            self.uri = self.module_id

        u_norm = self.uri
        if u_norm.startswith("/"):
            u_norm = u_norm[1:]
        u_norm = os.path.normpath(u_norm)
        if u_norm.startswith(".."):
            raise exceptions.TemplateLookupException(
                    "Template uri \"%s\" is invalid - "
                    "it cannot be relative outside "
                    "of the root path." % self.uri)

        self.input_encoding = input_encoding
        self.output_encoding = output_encoding
        self.encoding_errors = encoding_errors
        self.disable_unicode = disable_unicode
        self.bytestring_passthrough = bytestring_passthrough or disable_unicode
        self.enable_loop = enable_loop
        self.strict_undefined = strict_undefined
        self.module_writer = module_writer

        if compat.py3k and disable_unicode:
            raise exceptions.UnsupportedError(
                                    "Mako for Python 3 does not "
                                    "support disabling Unicode")
        elif output_encoding and disable_unicode:
            raise exceptions.UnsupportedError(
                                    "output_encoding must be set to "
                                    "None when disable_unicode is used.")
        if default_filters is None:
            if compat.py3k or self.disable_unicode:
                self.default_filters = ['str']
            else:
                self.default_filters = ['unicode']
        else:
            self.default_filters = default_filters
        self.buffer_filters = buffer_filters

        self.imports = imports
        self.future_imports = future_imports
        self.preprocessor = preprocessor

        # if plain text, compile code in memory only
        if text is not None:
            (code, module) = _compile_text(self, text, filename)
            self._code = code
            self._source = text
            ModuleInfo(module, None, self, filename, code, text)
        elif filename is not None:
            # if template filename and a module directory, load
            # a filesystem-based module file, generating if needed
            if module_filename is not None:
                path = module_filename
            elif module_directory is not None:
                path = os.path.abspath(
                        os.path.join(
                            os.path.normpath(module_directory),
                            u_norm + ".py"
                            )
                        )
            else:
                path = None
            module = self._compile_from_file(path, filename)
        else:
            raise exceptions.RuntimeException(
                                "Template requires text or filename")

        self.module = module
        self.filename = filename
        self.callable_ = self.module.render_body
        self.format_exceptions = format_exceptions
        self.error_handler = error_handler
        self.lookup = lookup

        self.module_directory = module_directory

        self._setup_cache_args(
            cache_impl, cache_enabled, cache_args,
            cache_type, cache_dir, cache_url
        )


    @util.memoized_property
    def reserved_names(self):
        if self.enable_loop:
            return codegen.RESERVED_NAMES
        else:
            return codegen.RESERVED_NAMES.difference(['loop'])

    def _setup_cache_args(self,
                cache_impl, cache_enabled, cache_args,
                cache_type, cache_dir, cache_url):
        self.cache_impl = cache_impl
        self.cache_enabled = cache_enabled
        if cache_args:
            self.cache_args = cache_args
        else:
            self.cache_args = {}

        # transfer deprecated cache_* args
        if cache_type:
            self.cache_args['type'] = cache_type
        if cache_dir:
            self.cache_args['dir'] = cache_dir
        if cache_url:
            self.cache_args['url'] = cache_url

    def _compile_from_file(self, path, filename):
        if path is not None:
            util.verify_directory(os.path.dirname(path))
            filemtime = os.stat(filename)[stat.ST_MTIME]
            if not os.path.exists(path) or \
                        os.stat(path)[stat.ST_MTIME] < filemtime:
                data = util.read_file(filename)
                _compile_module_file(
                            self,
                            data,
                            filename,
                            path,
                            self.module_writer)
            module = util.load_module(self.module_id, path)
            del sys.modules[self.module_id]
            if module._magic_number != codegen.MAGIC_NUMBER:
                data = util.read_file(filename)
                _compile_module_file(
                            self,
                            data,
                            filename,
                            path,
                            self.module_writer)
                module = util.load_module(self.module_id, path)
                del sys.modules[self.module_id]
            ModuleInfo(module, path, self, filename, None, None)
        else:
            # template filename and no module directory, compile code
            # in memory
            data = util.read_file(filename)
            code, module = _compile_text(
                                self,
                                data,
                                filename)
            self._source = None
            self._code = code
            ModuleInfo(module, None, self, filename, code, None)
        return module

    @property
    def source(self):
        """Return the template source code for this :class:`.Template`."""

        return _get_module_info_from_callable(self.callable_).source

    @property
    def code(self):
        """Return the module source code for this :class:`.Template`."""

        return _get_module_info_from_callable(self.callable_).code

    @util.memoized_property
    def cache(self):
        return cache.Cache(self)

    @property
    def cache_dir(self):
        return self.cache_args['dir']
    @property
    def cache_url(self):
        return self.cache_args['url']
    @property
    def cache_type(self):
        return self.cache_args['type']

    def render(self, *args, **data):
        """Render the output of this template as a string.

        If the template specifies an output encoding, the string
        will be encoded accordingly, else the output is raw (raw
        output uses `cStringIO` and can't handle multibyte
        characters). A :class:`.Context` object is created corresponding
        to the given data. Arguments that are explicitly declared
        by this template's internal rendering method are also
        pulled from the given ``*args``, ``**data`` members.

        """
        return runtime._render(self, self.callable_, args, data)

    def render_unicode(self, *args, **data):
        """Render the output of this template as a unicode object."""

        return runtime._render(self,
                                self.callable_,
                                args,
                                data,
                                as_unicode=True)

    def render_context(self, context, *args, **kwargs):
        """Render this :class:`.Template` with the given context.

        The data is written to the context's buffer.

        """
        if getattr(context, '_with_template', None) is None:
            context._set_with_template(self)
        runtime._render_context(self,
                                self.callable_,
                                context,
                                *args,
                                **kwargs)

    def has_def(self, name):
        return hasattr(self.module, "render_%s" % name)

    def get_def(self, name):
        """Return a def of this template as a :class:`.DefTemplate`."""

        return DefTemplate(self, getattr(self.module, "render_%s" % name))

    def _get_def_callable(self, name):
        return getattr(self.module, "render_%s" % name)

    @property
    def last_modified(self):
        return self.module._modified_time

class ModuleTemplate(Template):
    """A Template which is constructed given an existing Python module.

        e.g.::

        t = Template("this is a template")
        f = file("mymodule.py", "w")
        f.write(t.code)
        f.close()

        import mymodule

        t = ModuleTemplate(mymodule)
        print t.render()

    """

    def __init__(self, module,
                        module_filename=None,
                        template=None,
                        template_filename=None,
                        module_source=None,
                        template_source=None,
                        output_encoding=None,
                        encoding_errors='strict',
                        disable_unicode=False,
                        bytestring_passthrough=False,
                        format_exceptions=False,
                        error_handler=None,
                        lookup=None,
                        cache_args=None,
                        cache_impl='beaker',
                        cache_enabled=True,
                        cache_type=None,
                        cache_dir=None,
                        cache_url=None,
    ):
        self.module_id = re.sub(r'\W', "_", module._template_uri)
        self.uri = module._template_uri
        self.input_encoding = module._source_encoding
        self.output_encoding = output_encoding
        self.encoding_errors = encoding_errors
        self.disable_unicode = disable_unicode
        self.bytestring_passthrough = bytestring_passthrough or disable_unicode
        self.enable_loop = module._enable_loop

        if compat.py3k and disable_unicode:
            raise exceptions.UnsupportedError(
                                    "Mako for Python 3 does not "
                                    "support disabling Unicode")
        elif output_encoding and disable_unicode:
            raise exceptions.UnsupportedError(
                                    "output_encoding must be set to "
                                    "None when disable_unicode is used.")

        self.module = module
        self.filename = template_filename
        ModuleInfo(module,
                        module_filename,
                        self,
                        template_filename,
                        module_source,
                        template_source)

        self.callable_ = self.module.render_body
        self.format_exceptions = format_exceptions
        self.error_handler = error_handler
        self.lookup = lookup
        self._setup_cache_args(
            cache_impl, cache_enabled, cache_args,
            cache_type, cache_dir, cache_url
        )

class DefTemplate(Template):
    """A :class:`.Template` which represents a callable def in a parent
    template."""

    def __init__(self, parent, callable_):
        self.parent = parent
        self.callable_ = callable_
        self.output_encoding = parent.output_encoding
        self.module = parent.module
        self.encoding_errors = parent.encoding_errors
        self.format_exceptions = parent.format_exceptions
        self.error_handler = parent.error_handler
        self.enable_loop = parent.enable_loop
        self.lookup = parent.lookup
        self.bytestring_passthrough = parent.bytestring_passthrough

    def get_def(self, name):
        return self.parent.get_def(name)

class ModuleInfo(object):
    """Stores information about a module currently loaded into
    memory, provides reverse lookups of template source, module
    source code based on a module's identifier.

     """
    _modules = weakref.WeakValueDictionary()

    def __init__(self,
                    module,
                    module_filename,
                    template,
                    template_filename,
                    module_source,
                    template_source):
        self.module = module
        self.module_filename = module_filename
        self.template_filename = template_filename
        self.module_source = module_source
        self.template_source = template_source
        self._modules[module.__name__] = template._mmarker = self
        if module_filename:
            self._modules[module_filename] = self

    @property
    def code(self):
        if self.module_source is not None:
            return self.module_source
        else:
            return util.read_file(self.module_filename)

    @property
    def source(self):
        if self.template_source is not None:
            if self.module._source_encoding and \
                    not isinstance(self.template_source, compat.text_type):
                return self.template_source.decode(
                                self.module._source_encoding)
            else:
                return self.template_source
        else:
            data = util.read_file(self.template_filename)
            if self.module._source_encoding:
                return data.decode(self.module._source_encoding)
            else:
                return data

def _compile(template, text, filename, generate_magic_comment):
    lexer = Lexer(text,
                    filename,
                    disable_unicode=template.disable_unicode,
                    input_encoding=template.input_encoding,
                    preprocessor=template.preprocessor)
    node = lexer.parse()
    source = codegen.compile(node,
                            template.uri,
                            filename,
                            default_filters=template.default_filters,
                            buffer_filters=template.buffer_filters,
                            imports=template.imports,
                            future_imports=template.future_imports,
                            source_encoding=lexer.encoding,
                            generate_magic_comment=generate_magic_comment,
                            disable_unicode=template.disable_unicode,
                            strict_undefined=template.strict_undefined,
                            enable_loop=template.enable_loop,
                            reserved_names=template.reserved_names)
    return source, lexer

def _compile_text(template, text, filename):
    identifier = template.module_id
    source, lexer = _compile(template, text, filename,
                        generate_magic_comment=template.disable_unicode)

    cid = identifier
    if not compat.py3k and isinstance(cid, compat.text_type):
        cid = cid.encode()
    module = types.ModuleType(cid)
    code = compile(source, cid, 'exec')

    # this exec() works for 2.4->3.3.
    exec(code, module.__dict__, module.__dict__)
    return (source, module)

def _compile_module_file(template, text, filename, outputpath, module_writer):
    source, lexer = _compile(template, text, filename,
                        generate_magic_comment=True)

    if isinstance(source, compat.text_type):
        source = source.encode(lexer.encoding or 'ascii')

    if module_writer:
        module_writer(source, outputpath)
    else:
        # make tempfiles in the same location as the ultimate
        # location.   this ensures they're on the same filesystem,
        # avoiding synchronization issues.
        (dest, name) = tempfile.mkstemp(dir=os.path.dirname(outputpath))

        os.write(dest, source)
        os.close(dest)
        shutil.move(name, outputpath)

def _get_module_info_from_callable(callable_):
    if compat.py3k:
        return _get_module_info(callable_.__globals__['__name__'])
    else:
        return _get_module_info(callable_.func_globals['__name__'])

def _get_module_info(filename):
    return ModuleInfo._modules[filename]

