blob: 417a03539e09b83a0c59f5da895a888474d300a8 [file] [log] [blame]
Armin Ronacher07bc6842008-03-31 14:18:49 +02001# -*- coding: utf-8 -*-
2"""
Armin Ronacher82b3f3d2008-03-31 20:01:08 +02003 jinja2.environment
4 ~~~~~~~~~~~~~~~~~~
Armin Ronacher07bc6842008-03-31 14:18:49 +02005
6 Provides a class that holds runtime and parsing time options.
7
8 :copyright: 2007 by Armin Ronacher.
9 :license: BSD, see LICENSE for more details.
10"""
Armin Ronacher82b3f3d2008-03-31 20:01:08 +020011from jinja2.lexer import Lexer
12from jinja2.parser import Parser
Armin Ronacherbcb7c532008-04-11 16:30:34 +020013from jinja2.optimizer import optimize
14from jinja2.compiler import generate
Armin Ronacher82b3f3d2008-03-31 20:01:08 +020015from jinja2.defaults import DEFAULT_FILTERS, DEFAULT_TESTS, DEFAULT_NAMESPACE
Armin Ronacher07bc6842008-03-31 14:18:49 +020016
17
18class Environment(object):
Armin Ronacher8edbe492008-04-10 20:43:43 +020019 """The Jinja environment.
Armin Ronacher07bc6842008-03-31 14:18:49 +020020
21 The core component of Jinja is the `Environment`. It contains
22 important shared variables like configuration, filters, tests,
23 globals and others.
24 """
25
26 def __init__(self,
27 block_start_string='{%',
28 block_end_string='%}',
29 variable_start_string='{{',
30 variable_end_string='}}',
31 comment_start_string='{#',
32 comment_end_string='#}',
33 trim_blocks=False,
Armin Ronacherbcb7c532008-04-11 16:30:34 +020034 template_charset='utf-8',
35 loader=None):
Armin Ronacher8edbe492008-04-10 20:43:43 +020036 """Here the possible initialization parameters:
Armin Ronacher07bc6842008-03-31 14:18:49 +020037
38 ========================= ============================================
39 `block_start_string` the string marking the begin of a block.
40 this defaults to ``'{%'``.
41 `block_end_string` the string marking the end of a block.
42 defaults to ``'%}'``.
43 `variable_start_string` the string marking the begin of a print
44 statement. defaults to ``'{{'``.
45 `comment_start_string` the string marking the begin of a
46 comment. defaults to ``'{#'``.
47 `comment_end_string` the string marking the end of a comment.
48 defaults to ``'#}'``.
49 `trim_blocks` If this is set to ``True`` the first newline
50 after a block is removed (block, not
51 variable tag!). Defaults to ``False``.
Armin Ronacher82b3f3d2008-03-31 20:01:08 +020052 `template_charset` the charset of the templates.
Armin Ronacherbcb7c532008-04-11 16:30:34 +020053 `loader` the loader which should be used.
Armin Ronacher07bc6842008-03-31 14:18:49 +020054 ========================= ============================================
55 """
56
57 # lexer / parser information
58 self.block_start_string = block_start_string
59 self.block_end_string = block_end_string
60 self.variable_start_string = variable_start_string
61 self.variable_end_string = variable_end_string
62 self.comment_start_string = comment_start_string
63 self.comment_end_string = comment_end_string
64 self.trim_blocks = trim_blocks
Armin Ronacher07bc6842008-03-31 14:18:49 +020065 self.template_charset = template_charset
Armin Ronacher07bc6842008-03-31 14:18:49 +020066
67 # defaults
68 self.filters = DEFAULT_FILTERS.copy()
69 self.tests = DEFAULT_TESTS.copy()
70 self.globals = DEFAULT_NAMESPACE.copy()
71
Armin Ronacher8edbe492008-04-10 20:43:43 +020072 # if no finalize function/method exists we default to unicode. The
73 # compiler check if the finalize attribute *is* unicode, if yes no
74 # finalizaion is written where it can be avoided.
75 if not hasattr(self, 'finalize'):
76 self.finalize = unicode
Armin Ronacher4dfc9752008-04-09 15:03:29 +020077
Armin Ronacherbcb7c532008-04-11 16:30:34 +020078 # set the loader provided
79 self.loader = loader
80
Armin Ronacher07bc6842008-03-31 14:18:49 +020081 # create lexer
82 self.lexer = Lexer(self)
83
Armin Ronacher07bc6842008-03-31 14:18:49 +020084 def parse(self, source, filename=None):
Armin Ronacher8edbe492008-04-10 20:43:43 +020085 """Parse the sourcecode and return the abstract syntax tree. This tree
86 of nodes is used by the compiler to convert the template into
Armin Ronacher07bc6842008-03-31 14:18:49 +020087 executable source- or bytecode.
Armin Ronacher07bc6842008-03-31 14:18:49 +020088 """
89 parser = Parser(self, source, filename)
90 return parser.parse()
91
92 def lex(self, source, filename=None):
Armin Ronacher8edbe492008-04-10 20:43:43 +020093 """Lex the given sourcecode and return a generator that yields tokens.
Armin Ronacher07bc6842008-03-31 14:18:49 +020094 The stream returned is not usable for Jinja but can be used if
95 Jinja templates should be processed by other tools (for example
96 syntax highlighting etc)
97
98 The tuples are returned in the form ``(lineno, token, value)``.
99 """
100 return self.lexer.tokeniter(source, filename)
Armin Ronacherbcb7c532008-04-11 16:30:34 +0200101
102 def compile(self, source, filename=None, raw=False):
103 """Compile a node or source."""
104 if isinstance(source, basestring):
105 source = self.parse(source, filename)
106 node = optimize(source, self)
Armin Ronacher46f5f982008-04-11 16:40:09 +0200107 source = generate(node, self, filename)
Armin Ronacherbcb7c532008-04-11 16:30:34 +0200108 if raw:
109 return source
110 if isinstance(filename, unicode):
111 filename = filename.encode('utf-8')
112 return compile(source, filename, 'exec')
113
114 def join_path(self, template, parent):
115 """Join a template with the parent. By default all the lookups are
116 relative to the loader root, but if the paths should be relative this
117 function can be used to calculate the real filename."""
118 return template
119
120 def get_template(self, name, parent=None):
121 """Load a template."""
122 if self.loader is None:
123 raise TypeError('no loader for this environment specified')
124 if parent is not None:
125 name = self.join_path(name, parent)
126 return self.loader.load(self, name)
127
Armin Ronacher46f5f982008-04-11 16:40:09 +0200128 def from_string(self, source, filename='<string>'):
129 """Load a template from a string."""
130 return Template(self, self.compile(source, filename))
131
Armin Ronacherbcb7c532008-04-11 16:30:34 +0200132
133class Template(object):
134 """Represents a template."""
135
136 def __init__(self, environment, code):
137 namespace = {'environment': environment}
138 exec code in namespace
139 self.environment = environment
Armin Ronacherd4c64f72008-04-11 17:15:29 +0200140 self.name = namespace['filename']
Armin Ronacherbcb7c532008-04-11 16:30:34 +0200141 self.root_render_func = namespace['root']
142 self.blocks = namespace['blocks']
143
144 def render(self, *args, **kwargs):
145 return u''.join(self.stream(*args, **kwargs))
146
147 def stream(self, *args, **kwargs):
Armin Ronacher449167d2008-04-11 17:55:05 +0200148 return self.root_render_func(dict(*args, **kwargs))