1 # -*- coding: utf-8 -*-
6 Provides a class that holds runtime and parsing time options.
8 :copyright: 2007 by Armin Ronacher.
9 :license: BSD, see LICENSE for more details.
12 from jinja.lexer import Lexer
13 from jinja.parser import Parser
14 from jinja.loaders import LoaderWrapper
15 from jinja.datastructure import Undefined, Markup, Context, FakeTranslator
16 from jinja.utils import escape, collect_translations, get_attribute
17 from jinja.exceptions import FilterNotFound, TestNotFound, \
18 SecurityException, TemplateSyntaxError
19 from jinja.defaults import DEFAULT_FILTERS, DEFAULT_TESTS, DEFAULT_NAMESPACE
22 class Environment(object):
24 The jinja environment.
28 block_start_string='{%',
29 block_end_string='%}',
30 variable_start_string='{{',
31 variable_end_string='}}',
32 comment_start_string='{#',
33 comment_end_string='#}',
37 template_charset='utf-8',
43 context_class=Context):
45 # lexer / parser information
46 self.block_start_string = block_start_string
47 self.block_end_string = block_end_string
48 self.variable_start_string = variable_start_string
49 self.variable_end_string = variable_end_string
50 self.comment_start_string = comment_start_string
51 self.comment_end_string = comment_end_string
52 self.trim_blocks = trim_blocks
55 self.template_charset = template_charset
56 self.charset = charset
58 self.filters = filters is None and DEFAULT_FILTERS.copy() or filters
59 self.tests = tests is None and DEFAULT_TESTS.copy() or tests
60 self.default_filters = default_filters or []
61 self.context_class = context_class
64 self.globals = namespace is None and DEFAULT_NAMESPACE.copy() \
67 # jinja 1.0 compatibility
69 self.default_filters.append(('escape', (True,)))
70 self.globals['Markup'] = Markup
73 self.lexer = Lexer(self)
75 def loader(self, value):
77 Get or set the template loader.
79 self._loader = LoaderWrapper(self, value)
80 loader = property(lambda s: s._loader, loader, loader.__doc__)
82 def parse(self, source, filename=None):
83 """Function that creates a new parser and parses the source."""
84 parser = Parser(self, source, filename)
87 def from_string(self, source):
88 """Load a template from a string."""
89 from jinja.parser import Parser
90 from jinja.translators.python import PythonTranslator
92 rv = PythonTranslator.process(self, Parser(self, source).parse())
93 except TemplateSyntaxError, e:
94 # if errors occour raise a better traceback
95 from jinja.utils import raise_syntax_error
96 __traceback_hide__ = True
97 raise_syntax_error(e, self, source)
99 # everything went well. attach the source and return it
100 # attach the source for debugging
104 def get_template(self, filename):
105 """Load a template from a filename. Only works
106 if a proper loader is set."""
107 return self._loader.load(filename)
109 def to_unicode(self, value):
111 Convert a value to unicode with the rules defined on the environment.
113 if value in (None, Undefined):
115 elif isinstance(value, unicode):
119 return unicode(value)
121 return str(value).decode(self.charset, 'ignore')
123 def get_translator(self, context):
125 Return the translator for i18n.
127 A translator is an object that provides the two functions
128 ``gettext(string)`` and ``ngettext(singular, plural, n)``. Note
129 that both of them have to return unicode!
131 return FakeTranslator()
133 def get_translations(self, name):
135 Load template `name` and return all translatable strings (note that
136 that it really just returns the strings form this template, not from
137 the parent or any included templates!)
139 return collect_translations(self.loader.parse(name))
141 def apply_filters(self, value, context, filters):
143 Apply a list of filters on the variable.
146 if key in context.cache:
147 func = context.cache[key]
149 filtername, args = key
150 if filtername not in self.filters:
151 raise FilterNotFound(filtername)
152 context.cache[key] = func = self.filters[filtername](*args)
153 value = func(self, context, value)
156 def perform_test(self, context, testname, args, value, invert):
158 Perform a test on a variable.
160 key = (testname, args)
161 if key in context.cache:
162 func = context.cache[key]
164 if testname not in self.tests:
165 raise TestNotFound(testname)
166 context.cache[key] = func = self.tests[testname](*args)
167 rv = func(self, context, value)
172 def get_attribute(self, obj, name):
174 Get one attribute from an object.
178 except (TypeError, KeyError, IndexError):
180 return get_attribute(obj, name)
181 except (AttributeError, SecurityException):
185 def get_attributes(self, obj, attributes):
187 Get some attributes from an object. If attributes is an
188 empty sequence the object is returned as it.
190 get = self.get_attribute
191 for name in attributes:
195 def call_function(self, f, context, args, kwargs, dyn_args, dyn_kwargs):
197 Function call helper. Called for all functions that are passed
200 if dyn_args is not None:
201 args += tuple(dyn_args)
202 elif dyn_kwargs is not None:
203 kwargs.update(dyn_kwargs)
204 if getattr(f, 'jinja_unsafe_call', False) or \
205 getattr(f, 'alters_data', False):
207 if getattr(f, 'jinja_context_callable', False):
208 args = (self, context) + args
209 return f(*args, **kwargs)
211 def call_function_simple(self, f, context):
213 Function call without arguments. Because of the smaller signature and
214 fewer logic here we have a bit of redundant code.
216 if getattr(f, 'jinja_unsafe_call', False) or \
217 getattr(f, 'alters_data', False):
219 if getattr(f, 'jinja_context_callable', False):
220 return f(self, context)
223 def finish_var(self, value, ctx):
225 As long as no write_var function is passed to the template
226 evaluator the source generated by the python translator will
227 call this function for all variables.
229 if value is Undefined or value is None:
231 val = self.to_unicode(value)
232 if self.default_filters:
233 val = self.apply_filters(val, ctx, self.default_filters)