summaryrefslogtreecommitdiff
path: root/mako/template.py
diff options
context:
space:
mode:
Diffstat (limited to 'mako/template.py')
-rw-r--r--mako/template.py352
1 files changed, 191 insertions, 161 deletions
diff --git a/mako/template.py b/mako/template.py
index 329632c..89d2105 100644
--- a/mako/template.py
+++ b/mako/template.py
@@ -7,8 +7,6 @@
"""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
@@ -18,6 +16,14 @@ import tempfile
import types
import weakref
+from mako import cache
+from mako import codegen
+from mako import compat
+from mako import exceptions
+from mako import runtime
+from mako import util
+from mako.lexer import Lexer
+
class Template(object):
@@ -230,41 +236,43 @@ class Template(object):
lexer_cls = Lexer
- 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,
- lexer_cls=None,
- include_error_handler=None):
+ 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,
+ lexer_cls=None,
+ include_error_handler=None,
+ ):
if uri:
- self.module_id = re.sub(r'\W', "_", uri)
+ self.module_id = re.sub(r"\W", "_", uri)
self.uri = uri
elif filename:
- self.module_id = re.sub(r'\W', "_", 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
@@ -278,9 +286,10 @@ class Template(object):
u_norm = os.path.normpath(u_norm)
if u_norm.startswith(".."):
raise exceptions.TemplateLookupException(
- "Template uri \"%s\" is invalid - "
+ 'Template uri "%s" is invalid - '
"it cannot be relative outside "
- "of the root path." % self.uri)
+ "of the root path." % self.uri
+ )
self.input_encoding = input_encoding
self.output_encoding = output_encoding
@@ -293,17 +302,18 @@ class Template(object):
if compat.py3k and disable_unicode:
raise exceptions.UnsupportedError(
- "Mako for Python 3 does not "
- "support disabling Unicode")
+ "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.")
+ "None when disable_unicode is used."
+ )
if default_filters is None:
if compat.py3k or self.disable_unicode:
- self.default_filters = ['str']
+ self.default_filters = ["str"]
else:
- self.default_filters = ['unicode']
+ self.default_filters = ["unicode"]
else:
self.default_filters = default_filters
self.buffer_filters = buffer_filters
@@ -329,8 +339,7 @@ class Template(object):
elif module_directory is not None:
path = os.path.abspath(
os.path.join(
- os.path.normpath(module_directory),
- u_norm + ".py"
+ os.path.normpath(module_directory), u_norm + ".py"
)
)
else:
@@ -338,7 +347,8 @@ class Template(object):
module = self._compile_from_file(path, filename)
else:
raise exceptions.RuntimeException(
- "Template requires text or filename")
+ "Template requires text or filename"
+ )
self.module = module
self.filename = filename
@@ -351,8 +361,12 @@ class Template(object):
self.module_directory = module_directory
self._setup_cache_args(
- cache_impl, cache_enabled, cache_args,
- cache_type, cache_dir, cache_url
+ cache_impl,
+ cache_enabled,
+ cache_args,
+ cache_type,
+ cache_dir,
+ cache_url,
)
@util.memoized_property
@@ -360,11 +374,17 @@ class Template(object):
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):
+ 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:
@@ -374,35 +394,31 @@ class Template(object):
# transfer deprecated cache_* args
if cache_type:
- self.cache_args['type'] = cache_type
+ self.cache_args["type"] = cache_type
if cache_dir:
- self.cache_args['dir'] = cache_dir
+ self.cache_args["dir"] = cache_dir
if cache_url:
- self.cache_args['url'] = 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:
+ 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)
+ self, data, filename, path, self.module_writer
+ )
module = compat.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)
+ self, data, filename, path, self.module_writer
+ )
module = compat.load_module(self.module_id, path)
del sys.modules[self.module_id]
ModuleInfo(module, path, self, filename, None, None)
@@ -410,10 +426,7 @@ class Template(object):
# template filename and no module directory, compile code
# in memory
data = util.read_file(filename)
- code, module = _compile_text(
- self,
- data,
- filename)
+ code, module = _compile_text(self, data, filename)
self._source = None
self._code = code
ModuleInfo(module, None, self, filename, code, None)
@@ -437,15 +450,15 @@ class Template(object):
@property
def cache_dir(self):
- return self.cache_args['dir']
+ return self.cache_args["dir"]
@property
def cache_url(self):
- return self.cache_args['url']
+ return self.cache_args["url"]
@property
def cache_type(self):
- return self.cache_args['type']
+ return self.cache_args["type"]
def render(self, *args, **data):
"""Render the output of this template as a string.
@@ -464,11 +477,9 @@ class Template(object):
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)
+ 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.
@@ -476,13 +487,9 @@ class Template(object):
The data is written to the context's buffer.
"""
- if getattr(context, '_with_template', None) is None:
+ if getattr(context, "_with_template", None) is None:
context._set_with_template(self)
- runtime._render_context(self,
- self.callable_,
- context,
- *args,
- **kwargs)
+ runtime._render_context(self, self.callable_, context, *args, **kwargs)
def has_def(self, name):
return hasattr(self.module, "render_%s" % name)
@@ -498,7 +505,7 @@ class Template(object):
.. versionadded:: 1.0.4
"""
- return [i[7:] for i in dir(self.module) if i[:7] == 'render_']
+ return [i[7:] for i in dir(self.module) if i[:7] == "render_"]
def _get_def_callable(self, name):
return getattr(self.module, "render_%s" % name)
@@ -526,28 +533,30 @@ class ModuleTemplate(Template):
"""
- 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,
- include_error_handler=None,
- ):
- self.module_id = re.sub(r'\W', "_", module._template_uri)
+ 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,
+ include_error_handler=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
@@ -558,21 +567,24 @@ class ModuleTemplate(Template):
if compat.py3k and disable_unicode:
raise exceptions.UnsupportedError(
- "Mako for Python 3 does not "
- "support disabling Unicode")
+ "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.")
+ "None when disable_unicode is used."
+ )
self.module = module
self.filename = template_filename
- ModuleInfo(module,
- module_filename,
- self,
- template_filename,
- module_source,
- template_source)
+ ModuleInfo(
+ module,
+ module_filename,
+ self,
+ template_filename,
+ module_source,
+ template_source,
+ )
self.callable_ = self.module.render_body
self.format_exceptions = format_exceptions
@@ -580,8 +592,12 @@ class ModuleTemplate(Template):
self.include_error_handler = include_error_handler
self.lookup = lookup
self._setup_cache_args(
- cache_impl, cache_enabled, cache_args,
- cache_type, cache_dir, cache_url
+ cache_impl,
+ cache_enabled,
+ cache_args,
+ cache_type,
+ cache_dir,
+ cache_url,
)
@@ -614,15 +630,18 @@ class ModuleInfo(object):
source code based on a module's identifier.
"""
+
_modules = weakref.WeakValueDictionary()
- def __init__(self,
- module,
- module_filename,
- template,
- template_filename,
- module_source,
- template_source):
+ 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
@@ -635,15 +654,15 @@ class ModuleInfo(object):
@classmethod
def get_module_source_metadata(cls, module_source, full_line_map=False):
source_map = re.search(
- r"__M_BEGIN_METADATA(.+?)__M_END_METADATA",
- module_source, re.S).group(1)
+ r"__M_BEGIN_METADATA(.+?)__M_END_METADATA", module_source, re.S
+ ).group(1)
source_map = compat.json.loads(source_map)
- source_map['line_map'] = dict(
- (int(k), int(v))
- for k, v in source_map['line_map'].items())
+ source_map["line_map"] = dict(
+ (int(k), int(v)) for k, v in source_map["line_map"].items()
+ )
if full_line_map:
- f_line_map = source_map['full_line_map'] = []
- line_map = source_map['line_map']
+ f_line_map = source_map["full_line_map"] = []
+ line_map = source_map["line_map"]
curr_templ_line = 1
for mod_line in range(1, max(line_map)):
@@ -662,10 +681,12 @@ class ModuleInfo(object):
@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):
+ if self.module._source_encoding and not isinstance(
+ self.template_source, compat.text_type
+ ):
return self.template_source.decode(
- self.module._source_encoding)
+ self.module._source_encoding
+ )
else:
return self.template_source
else:
@@ -677,38 +698,46 @@ class ModuleInfo(object):
def _compile(template, text, filename, generate_magic_comment):
- lexer = template.lexer_cls(text,
- filename,
- disable_unicode=template.disable_unicode,
- input_encoding=template.input_encoding,
- preprocessor=template.preprocessor)
+ lexer = template.lexer_cls(
+ 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)
+ 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)
+ 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')
+ code = compile(source, cid, "exec")
# this exec() works for 2.4->3.3.
exec(code, module.__dict__, module.__dict__)
@@ -716,11 +745,12 @@ def _compile_text(template, text, filename):
def _compile_module_file(template, text, filename, outputpath, module_writer):
- source, lexer = _compile(template, text, filename,
- generate_magic_comment=True)
+ source, lexer = _compile(
+ template, text, filename, generate_magic_comment=True
+ )
if isinstance(source, compat.text_type):
- source = source.encode(lexer.encoding or 'ascii')
+ source = source.encode(lexer.encoding or "ascii")
if module_writer:
module_writer(source, outputpath)
@@ -737,9 +767,9 @@ def _compile_module_file(template, text, filename, outputpath, module_writer):
def _get_module_info_from_callable(callable_):
if compat.py3k:
- return _get_module_info(callable_.__globals__['__name__'])
+ return _get_module_info(callable_.__globals__["__name__"])
else:
- return _get_module_info(callable_.func_globals['__name__'])
+ return _get_module_info(callable_.func_globals["__name__"])
def _get_module_info(filename):