w000t. first template
[jinja2.git] / jinja2 / environment.py
1 # -*- coding: utf-8 -*-
2 """
3     jinja2.environment
4     ~~~~~~~~~~~~~~~~~~
5
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 """
11 from jinja2.lexer import Lexer
12 from jinja2.parser import Parser
13 from jinja2.optimizer import optimize
14 from jinja2.compiler import generate
15 from jinja2.defaults import DEFAULT_FILTERS, DEFAULT_TESTS, DEFAULT_NAMESPACE
16
17
18 class Environment(object):
19     """The Jinja environment.
20
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,
34                  template_charset='utf-8',
35                  loader=None):
36         """Here the possible initialization parameters:
37
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``.
52         `template_charset`        the charset of the templates.
53         `loader`                  the loader which should be used.
54         ========================= ============================================
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
65         self.template_charset = template_charset
66
67         # defaults
68         self.filters = DEFAULT_FILTERS.copy()
69         self.tests = DEFAULT_TESTS.copy()
70         self.globals = DEFAULT_NAMESPACE.copy()
71
72         # 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
77
78         # set the loader provided
79         self.loader = loader
80
81         # create lexer
82         self.lexer = Lexer(self)
83
84     def parse(self, source, filename=None):
85         """Parse the sourcecode and return the abstract syntax tree. This tree
86         of nodes is used by the compiler to convert the template into
87         executable source- or bytecode.
88         """
89         parser = Parser(self, source, filename)
90         return parser.parse()
91
92     def lex(self, source, filename=None):
93         """Lex the given sourcecode and return a generator that yields tokens.
94         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)
101
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)
107         source = generate(node, self, filename)
108         if raw:
109             return source
110         print source
111         if isinstance(filename, unicode):
112             filename = filename.encode('utf-8')
113         return compile(source, filename, 'exec')
114
115     def join_path(self, template, parent):
116         """Join a template with the parent.  By default all the lookups are
117         relative to the loader root, but if the paths should be relative this
118         function can be used to calculate the real filename."""
119         return template
120
121     def get_template(self, name, parent=None):
122         """Load a template."""
123         if self.loader is None:
124             raise TypeError('no loader for this environment specified')
125         if parent is not None:
126             name = self.join_path(name, parent)
127         return self.loader.load(self, name)
128
129     def from_string(self, source, filename='<string>'):
130         """Load a template from a string."""
131         return Template(self, self.compile(source, filename))
132
133
134 class Template(object):
135     """Represents a template."""
136
137     def __init__(self, environment, code):
138         namespace = {'environment': environment}
139         exec code in namespace
140         self.environment = environment
141         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):
148         context = dict(*args, **kwargs)
149         return self.root_render_func(context)