Mercurial > repos > guerler > springsuite
comparison planemo/lib/python3.7/site-packages/jinja2/environment.py @ 1:56ad4e20f292 draft
"planemo upload commit 6eee67778febed82ddd413c3ca40b3183a3898f1"
author | guerler |
---|---|
date | Fri, 31 Jul 2020 00:32:28 -0400 |
parents | |
children |
comparison
equal
deleted
inserted
replaced
0:d30785e31577 | 1:56ad4e20f292 |
---|---|
1 # -*- coding: utf-8 -*- | |
2 """Classes for managing templates and their runtime and compile time | |
3 options. | |
4 """ | |
5 import os | |
6 import sys | |
7 import weakref | |
8 from functools import partial | |
9 from functools import reduce | |
10 | |
11 from markupsafe import Markup | |
12 | |
13 from . import nodes | |
14 from ._compat import encode_filename | |
15 from ._compat import implements_iterator | |
16 from ._compat import implements_to_string | |
17 from ._compat import iteritems | |
18 from ._compat import PY2 | |
19 from ._compat import PYPY | |
20 from ._compat import reraise | |
21 from ._compat import string_types | |
22 from ._compat import text_type | |
23 from .compiler import CodeGenerator | |
24 from .compiler import generate | |
25 from .defaults import BLOCK_END_STRING | |
26 from .defaults import BLOCK_START_STRING | |
27 from .defaults import COMMENT_END_STRING | |
28 from .defaults import COMMENT_START_STRING | |
29 from .defaults import DEFAULT_FILTERS | |
30 from .defaults import DEFAULT_NAMESPACE | |
31 from .defaults import DEFAULT_POLICIES | |
32 from .defaults import DEFAULT_TESTS | |
33 from .defaults import KEEP_TRAILING_NEWLINE | |
34 from .defaults import LINE_COMMENT_PREFIX | |
35 from .defaults import LINE_STATEMENT_PREFIX | |
36 from .defaults import LSTRIP_BLOCKS | |
37 from .defaults import NEWLINE_SEQUENCE | |
38 from .defaults import TRIM_BLOCKS | |
39 from .defaults import VARIABLE_END_STRING | |
40 from .defaults import VARIABLE_START_STRING | |
41 from .exceptions import TemplateNotFound | |
42 from .exceptions import TemplateRuntimeError | |
43 from .exceptions import TemplatesNotFound | |
44 from .exceptions import TemplateSyntaxError | |
45 from .exceptions import UndefinedError | |
46 from .lexer import get_lexer | |
47 from .lexer import TokenStream | |
48 from .nodes import EvalContext | |
49 from .parser import Parser | |
50 from .runtime import Context | |
51 from .runtime import new_context | |
52 from .runtime import Undefined | |
53 from .utils import concat | |
54 from .utils import consume | |
55 from .utils import have_async_gen | |
56 from .utils import import_string | |
57 from .utils import internalcode | |
58 from .utils import LRUCache | |
59 from .utils import missing | |
60 | |
61 # for direct template usage we have up to ten living environments | |
62 _spontaneous_environments = LRUCache(10) | |
63 | |
64 | |
65 def get_spontaneous_environment(cls, *args): | |
66 """Return a new spontaneous environment. A spontaneous environment | |
67 is used for templates created directly rather than through an | |
68 existing environment. | |
69 | |
70 :param cls: Environment class to create. | |
71 :param args: Positional arguments passed to environment. | |
72 """ | |
73 key = (cls, args) | |
74 | |
75 try: | |
76 return _spontaneous_environments[key] | |
77 except KeyError: | |
78 _spontaneous_environments[key] = env = cls(*args) | |
79 env.shared = True | |
80 return env | |
81 | |
82 | |
83 def create_cache(size): | |
84 """Return the cache class for the given size.""" | |
85 if size == 0: | |
86 return None | |
87 if size < 0: | |
88 return {} | |
89 return LRUCache(size) | |
90 | |
91 | |
92 def copy_cache(cache): | |
93 """Create an empty copy of the given cache.""" | |
94 if cache is None: | |
95 return None | |
96 elif type(cache) is dict: | |
97 return {} | |
98 return LRUCache(cache.capacity) | |
99 | |
100 | |
101 def load_extensions(environment, extensions): | |
102 """Load the extensions from the list and bind it to the environment. | |
103 Returns a dict of instantiated environments. | |
104 """ | |
105 result = {} | |
106 for extension in extensions: | |
107 if isinstance(extension, string_types): | |
108 extension = import_string(extension) | |
109 result[extension.identifier] = extension(environment) | |
110 return result | |
111 | |
112 | |
113 def fail_for_missing_callable(string, name): | |
114 msg = string % name | |
115 if isinstance(name, Undefined): | |
116 try: | |
117 name._fail_with_undefined_error() | |
118 except Exception as e: | |
119 msg = "%s (%s; did you forget to quote the callable name?)" % (msg, e) | |
120 raise TemplateRuntimeError(msg) | |
121 | |
122 | |
123 def _environment_sanity_check(environment): | |
124 """Perform a sanity check on the environment.""" | |
125 assert issubclass( | |
126 environment.undefined, Undefined | |
127 ), "undefined must be a subclass of undefined because filters depend on it." | |
128 assert ( | |
129 environment.block_start_string | |
130 != environment.variable_start_string | |
131 != environment.comment_start_string | |
132 ), "block, variable and comment start strings must be different" | |
133 assert environment.newline_sequence in ( | |
134 "\r", | |
135 "\r\n", | |
136 "\n", | |
137 ), "newline_sequence set to unknown line ending string." | |
138 return environment | |
139 | |
140 | |
141 class Environment(object): | |
142 r"""The core component of Jinja is the `Environment`. It contains | |
143 important shared variables like configuration, filters, tests, | |
144 globals and others. Instances of this class may be modified if | |
145 they are not shared and if no template was loaded so far. | |
146 Modifications on environments after the first template was loaded | |
147 will lead to surprising effects and undefined behavior. | |
148 | |
149 Here are the possible initialization parameters: | |
150 | |
151 `block_start_string` | |
152 The string marking the beginning of a block. Defaults to ``'{%'``. | |
153 | |
154 `block_end_string` | |
155 The string marking the end of a block. Defaults to ``'%}'``. | |
156 | |
157 `variable_start_string` | |
158 The string marking the beginning of a print statement. | |
159 Defaults to ``'{{'``. | |
160 | |
161 `variable_end_string` | |
162 The string marking the end of a print statement. Defaults to | |
163 ``'}}'``. | |
164 | |
165 `comment_start_string` | |
166 The string marking the beginning of a comment. Defaults to ``'{#'``. | |
167 | |
168 `comment_end_string` | |
169 The string marking the end of a comment. Defaults to ``'#}'``. | |
170 | |
171 `line_statement_prefix` | |
172 If given and a string, this will be used as prefix for line based | |
173 statements. See also :ref:`line-statements`. | |
174 | |
175 `line_comment_prefix` | |
176 If given and a string, this will be used as prefix for line based | |
177 comments. See also :ref:`line-statements`. | |
178 | |
179 .. versionadded:: 2.2 | |
180 | |
181 `trim_blocks` | |
182 If this is set to ``True`` the first newline after a block is | |
183 removed (block, not variable tag!). Defaults to `False`. | |
184 | |
185 `lstrip_blocks` | |
186 If this is set to ``True`` leading spaces and tabs are stripped | |
187 from the start of a line to a block. Defaults to `False`. | |
188 | |
189 `newline_sequence` | |
190 The sequence that starts a newline. Must be one of ``'\r'``, | |
191 ``'\n'`` or ``'\r\n'``. The default is ``'\n'`` which is a | |
192 useful default for Linux and OS X systems as well as web | |
193 applications. | |
194 | |
195 `keep_trailing_newline` | |
196 Preserve the trailing newline when rendering templates. | |
197 The default is ``False``, which causes a single newline, | |
198 if present, to be stripped from the end of the template. | |
199 | |
200 .. versionadded:: 2.7 | |
201 | |
202 `extensions` | |
203 List of Jinja extensions to use. This can either be import paths | |
204 as strings or extension classes. For more information have a | |
205 look at :ref:`the extensions documentation <jinja-extensions>`. | |
206 | |
207 `optimized` | |
208 should the optimizer be enabled? Default is ``True``. | |
209 | |
210 `undefined` | |
211 :class:`Undefined` or a subclass of it that is used to represent | |
212 undefined values in the template. | |
213 | |
214 `finalize` | |
215 A callable that can be used to process the result of a variable | |
216 expression before it is output. For example one can convert | |
217 ``None`` implicitly into an empty string here. | |
218 | |
219 `autoescape` | |
220 If set to ``True`` the XML/HTML autoescaping feature is enabled by | |
221 default. For more details about autoescaping see | |
222 :class:`~markupsafe.Markup`. As of Jinja 2.4 this can also | |
223 be a callable that is passed the template name and has to | |
224 return ``True`` or ``False`` depending on autoescape should be | |
225 enabled by default. | |
226 | |
227 .. versionchanged:: 2.4 | |
228 `autoescape` can now be a function | |
229 | |
230 `loader` | |
231 The template loader for this environment. | |
232 | |
233 `cache_size` | |
234 The size of the cache. Per default this is ``400`` which means | |
235 that if more than 400 templates are loaded the loader will clean | |
236 out the least recently used template. If the cache size is set to | |
237 ``0`` templates are recompiled all the time, if the cache size is | |
238 ``-1`` the cache will not be cleaned. | |
239 | |
240 .. versionchanged:: 2.8 | |
241 The cache size was increased to 400 from a low 50. | |
242 | |
243 `auto_reload` | |
244 Some loaders load templates from locations where the template | |
245 sources may change (ie: file system or database). If | |
246 ``auto_reload`` is set to ``True`` (default) every time a template is | |
247 requested the loader checks if the source changed and if yes, it | |
248 will reload the template. For higher performance it's possible to | |
249 disable that. | |
250 | |
251 `bytecode_cache` | |
252 If set to a bytecode cache object, this object will provide a | |
253 cache for the internal Jinja bytecode so that templates don't | |
254 have to be parsed if they were not changed. | |
255 | |
256 See :ref:`bytecode-cache` for more information. | |
257 | |
258 `enable_async` | |
259 If set to true this enables async template execution which allows | |
260 you to take advantage of newer Python features. This requires | |
261 Python 3.6 or later. | |
262 """ | |
263 | |
264 #: if this environment is sandboxed. Modifying this variable won't make | |
265 #: the environment sandboxed though. For a real sandboxed environment | |
266 #: have a look at jinja2.sandbox. This flag alone controls the code | |
267 #: generation by the compiler. | |
268 sandboxed = False | |
269 | |
270 #: True if the environment is just an overlay | |
271 overlayed = False | |
272 | |
273 #: the environment this environment is linked to if it is an overlay | |
274 linked_to = None | |
275 | |
276 #: shared environments have this set to `True`. A shared environment | |
277 #: must not be modified | |
278 shared = False | |
279 | |
280 #: the class that is used for code generation. See | |
281 #: :class:`~jinja2.compiler.CodeGenerator` for more information. | |
282 code_generator_class = CodeGenerator | |
283 | |
284 #: the context class thatis used for templates. See | |
285 #: :class:`~jinja2.runtime.Context` for more information. | |
286 context_class = Context | |
287 | |
288 def __init__( | |
289 self, | |
290 block_start_string=BLOCK_START_STRING, | |
291 block_end_string=BLOCK_END_STRING, | |
292 variable_start_string=VARIABLE_START_STRING, | |
293 variable_end_string=VARIABLE_END_STRING, | |
294 comment_start_string=COMMENT_START_STRING, | |
295 comment_end_string=COMMENT_END_STRING, | |
296 line_statement_prefix=LINE_STATEMENT_PREFIX, | |
297 line_comment_prefix=LINE_COMMENT_PREFIX, | |
298 trim_blocks=TRIM_BLOCKS, | |
299 lstrip_blocks=LSTRIP_BLOCKS, | |
300 newline_sequence=NEWLINE_SEQUENCE, | |
301 keep_trailing_newline=KEEP_TRAILING_NEWLINE, | |
302 extensions=(), | |
303 optimized=True, | |
304 undefined=Undefined, | |
305 finalize=None, | |
306 autoescape=False, | |
307 loader=None, | |
308 cache_size=400, | |
309 auto_reload=True, | |
310 bytecode_cache=None, | |
311 enable_async=False, | |
312 ): | |
313 # !!Important notice!! | |
314 # The constructor accepts quite a few arguments that should be | |
315 # passed by keyword rather than position. However it's important to | |
316 # not change the order of arguments because it's used at least | |
317 # internally in those cases: | |
318 # - spontaneous environments (i18n extension and Template) | |
319 # - unittests | |
320 # If parameter changes are required only add parameters at the end | |
321 # and don't change the arguments (or the defaults!) of the arguments | |
322 # existing already. | |
323 | |
324 # lexer / parser information | |
325 self.block_start_string = block_start_string | |
326 self.block_end_string = block_end_string | |
327 self.variable_start_string = variable_start_string | |
328 self.variable_end_string = variable_end_string | |
329 self.comment_start_string = comment_start_string | |
330 self.comment_end_string = comment_end_string | |
331 self.line_statement_prefix = line_statement_prefix | |
332 self.line_comment_prefix = line_comment_prefix | |
333 self.trim_blocks = trim_blocks | |
334 self.lstrip_blocks = lstrip_blocks | |
335 self.newline_sequence = newline_sequence | |
336 self.keep_trailing_newline = keep_trailing_newline | |
337 | |
338 # runtime information | |
339 self.undefined = undefined | |
340 self.optimized = optimized | |
341 self.finalize = finalize | |
342 self.autoescape = autoescape | |
343 | |
344 # defaults | |
345 self.filters = DEFAULT_FILTERS.copy() | |
346 self.tests = DEFAULT_TESTS.copy() | |
347 self.globals = DEFAULT_NAMESPACE.copy() | |
348 | |
349 # set the loader provided | |
350 self.loader = loader | |
351 self.cache = create_cache(cache_size) | |
352 self.bytecode_cache = bytecode_cache | |
353 self.auto_reload = auto_reload | |
354 | |
355 # configurable policies | |
356 self.policies = DEFAULT_POLICIES.copy() | |
357 | |
358 # load extensions | |
359 self.extensions = load_extensions(self, extensions) | |
360 | |
361 self.enable_async = enable_async | |
362 self.is_async = self.enable_async and have_async_gen | |
363 if self.is_async: | |
364 # runs patch_all() to enable async support | |
365 from . import asyncsupport # noqa: F401 | |
366 | |
367 _environment_sanity_check(self) | |
368 | |
369 def add_extension(self, extension): | |
370 """Adds an extension after the environment was created. | |
371 | |
372 .. versionadded:: 2.5 | |
373 """ | |
374 self.extensions.update(load_extensions(self, [extension])) | |
375 | |
376 def extend(self, **attributes): | |
377 """Add the items to the instance of the environment if they do not exist | |
378 yet. This is used by :ref:`extensions <writing-extensions>` to register | |
379 callbacks and configuration values without breaking inheritance. | |
380 """ | |
381 for key, value in iteritems(attributes): | |
382 if not hasattr(self, key): | |
383 setattr(self, key, value) | |
384 | |
385 def overlay( | |
386 self, | |
387 block_start_string=missing, | |
388 block_end_string=missing, | |
389 variable_start_string=missing, | |
390 variable_end_string=missing, | |
391 comment_start_string=missing, | |
392 comment_end_string=missing, | |
393 line_statement_prefix=missing, | |
394 line_comment_prefix=missing, | |
395 trim_blocks=missing, | |
396 lstrip_blocks=missing, | |
397 extensions=missing, | |
398 optimized=missing, | |
399 undefined=missing, | |
400 finalize=missing, | |
401 autoescape=missing, | |
402 loader=missing, | |
403 cache_size=missing, | |
404 auto_reload=missing, | |
405 bytecode_cache=missing, | |
406 ): | |
407 """Create a new overlay environment that shares all the data with the | |
408 current environment except for cache and the overridden attributes. | |
409 Extensions cannot be removed for an overlayed environment. An overlayed | |
410 environment automatically gets all the extensions of the environment it | |
411 is linked to plus optional extra extensions. | |
412 | |
413 Creating overlays should happen after the initial environment was set | |
414 up completely. Not all attributes are truly linked, some are just | |
415 copied over so modifications on the original environment may not shine | |
416 through. | |
417 """ | |
418 args = dict(locals()) | |
419 del args["self"], args["cache_size"], args["extensions"] | |
420 | |
421 rv = object.__new__(self.__class__) | |
422 rv.__dict__.update(self.__dict__) | |
423 rv.overlayed = True | |
424 rv.linked_to = self | |
425 | |
426 for key, value in iteritems(args): | |
427 if value is not missing: | |
428 setattr(rv, key, value) | |
429 | |
430 if cache_size is not missing: | |
431 rv.cache = create_cache(cache_size) | |
432 else: | |
433 rv.cache = copy_cache(self.cache) | |
434 | |
435 rv.extensions = {} | |
436 for key, value in iteritems(self.extensions): | |
437 rv.extensions[key] = value.bind(rv) | |
438 if extensions is not missing: | |
439 rv.extensions.update(load_extensions(rv, extensions)) | |
440 | |
441 return _environment_sanity_check(rv) | |
442 | |
443 lexer = property(get_lexer, doc="The lexer for this environment.") | |
444 | |
445 def iter_extensions(self): | |
446 """Iterates over the extensions by priority.""" | |
447 return iter(sorted(self.extensions.values(), key=lambda x: x.priority)) | |
448 | |
449 def getitem(self, obj, argument): | |
450 """Get an item or attribute of an object but prefer the item.""" | |
451 try: | |
452 return obj[argument] | |
453 except (AttributeError, TypeError, LookupError): | |
454 if isinstance(argument, string_types): | |
455 try: | |
456 attr = str(argument) | |
457 except Exception: | |
458 pass | |
459 else: | |
460 try: | |
461 return getattr(obj, attr) | |
462 except AttributeError: | |
463 pass | |
464 return self.undefined(obj=obj, name=argument) | |
465 | |
466 def getattr(self, obj, attribute): | |
467 """Get an item or attribute of an object but prefer the attribute. | |
468 Unlike :meth:`getitem` the attribute *must* be a bytestring. | |
469 """ | |
470 try: | |
471 return getattr(obj, attribute) | |
472 except AttributeError: | |
473 pass | |
474 try: | |
475 return obj[attribute] | |
476 except (TypeError, LookupError, AttributeError): | |
477 return self.undefined(obj=obj, name=attribute) | |
478 | |
479 def call_filter( | |
480 self, name, value, args=None, kwargs=None, context=None, eval_ctx=None | |
481 ): | |
482 """Invokes a filter on a value the same way the compiler does it. | |
483 | |
484 Note that on Python 3 this might return a coroutine in case the | |
485 filter is running from an environment in async mode and the filter | |
486 supports async execution. It's your responsibility to await this | |
487 if needed. | |
488 | |
489 .. versionadded:: 2.7 | |
490 """ | |
491 func = self.filters.get(name) | |
492 if func is None: | |
493 fail_for_missing_callable("no filter named %r", name) | |
494 args = [value] + list(args or ()) | |
495 if getattr(func, "contextfilter", False) is True: | |
496 if context is None: | |
497 raise TemplateRuntimeError( | |
498 "Attempted to invoke context filter without context" | |
499 ) | |
500 args.insert(0, context) | |
501 elif getattr(func, "evalcontextfilter", False) is True: | |
502 if eval_ctx is None: | |
503 if context is not None: | |
504 eval_ctx = context.eval_ctx | |
505 else: | |
506 eval_ctx = EvalContext(self) | |
507 args.insert(0, eval_ctx) | |
508 elif getattr(func, "environmentfilter", False) is True: | |
509 args.insert(0, self) | |
510 return func(*args, **(kwargs or {})) | |
511 | |
512 def call_test(self, name, value, args=None, kwargs=None): | |
513 """Invokes a test on a value the same way the compiler does it. | |
514 | |
515 .. versionadded:: 2.7 | |
516 """ | |
517 func = self.tests.get(name) | |
518 if func is None: | |
519 fail_for_missing_callable("no test named %r", name) | |
520 return func(value, *(args or ()), **(kwargs or {})) | |
521 | |
522 @internalcode | |
523 def parse(self, source, name=None, filename=None): | |
524 """Parse the sourcecode and return the abstract syntax tree. This | |
525 tree of nodes is used by the compiler to convert the template into | |
526 executable source- or bytecode. This is useful for debugging or to | |
527 extract information from templates. | |
528 | |
529 If you are :ref:`developing Jinja extensions <writing-extensions>` | |
530 this gives you a good overview of the node tree generated. | |
531 """ | |
532 try: | |
533 return self._parse(source, name, filename) | |
534 except TemplateSyntaxError: | |
535 self.handle_exception(source=source) | |
536 | |
537 def _parse(self, source, name, filename): | |
538 """Internal parsing function used by `parse` and `compile`.""" | |
539 return Parser(self, source, name, encode_filename(filename)).parse() | |
540 | |
541 def lex(self, source, name=None, filename=None): | |
542 """Lex the given sourcecode and return a generator that yields | |
543 tokens as tuples in the form ``(lineno, token_type, value)``. | |
544 This can be useful for :ref:`extension development <writing-extensions>` | |
545 and debugging templates. | |
546 | |
547 This does not perform preprocessing. If you want the preprocessing | |
548 of the extensions to be applied you have to filter source through | |
549 the :meth:`preprocess` method. | |
550 """ | |
551 source = text_type(source) | |
552 try: | |
553 return self.lexer.tokeniter(source, name, filename) | |
554 except TemplateSyntaxError: | |
555 self.handle_exception(source=source) | |
556 | |
557 def preprocess(self, source, name=None, filename=None): | |
558 """Preprocesses the source with all extensions. This is automatically | |
559 called for all parsing and compiling methods but *not* for :meth:`lex` | |
560 because there you usually only want the actual source tokenized. | |
561 """ | |
562 return reduce( | |
563 lambda s, e: e.preprocess(s, name, filename), | |
564 self.iter_extensions(), | |
565 text_type(source), | |
566 ) | |
567 | |
568 def _tokenize(self, source, name, filename=None, state=None): | |
569 """Called by the parser to do the preprocessing and filtering | |
570 for all the extensions. Returns a :class:`~jinja2.lexer.TokenStream`. | |
571 """ | |
572 source = self.preprocess(source, name, filename) | |
573 stream = self.lexer.tokenize(source, name, filename, state) | |
574 for ext in self.iter_extensions(): | |
575 stream = ext.filter_stream(stream) | |
576 if not isinstance(stream, TokenStream): | |
577 stream = TokenStream(stream, name, filename) | |
578 return stream | |
579 | |
580 def _generate(self, source, name, filename, defer_init=False): | |
581 """Internal hook that can be overridden to hook a different generate | |
582 method in. | |
583 | |
584 .. versionadded:: 2.5 | |
585 """ | |
586 return generate( | |
587 source, | |
588 self, | |
589 name, | |
590 filename, | |
591 defer_init=defer_init, | |
592 optimized=self.optimized, | |
593 ) | |
594 | |
595 def _compile(self, source, filename): | |
596 """Internal hook that can be overridden to hook a different compile | |
597 method in. | |
598 | |
599 .. versionadded:: 2.5 | |
600 """ | |
601 return compile(source, filename, "exec") | |
602 | |
603 @internalcode | |
604 def compile(self, source, name=None, filename=None, raw=False, defer_init=False): | |
605 """Compile a node or template source code. The `name` parameter is | |
606 the load name of the template after it was joined using | |
607 :meth:`join_path` if necessary, not the filename on the file system. | |
608 the `filename` parameter is the estimated filename of the template on | |
609 the file system. If the template came from a database or memory this | |
610 can be omitted. | |
611 | |
612 The return value of this method is a python code object. If the `raw` | |
613 parameter is `True` the return value will be a string with python | |
614 code equivalent to the bytecode returned otherwise. This method is | |
615 mainly used internally. | |
616 | |
617 `defer_init` is use internally to aid the module code generator. This | |
618 causes the generated code to be able to import without the global | |
619 environment variable to be set. | |
620 | |
621 .. versionadded:: 2.4 | |
622 `defer_init` parameter added. | |
623 """ | |
624 source_hint = None | |
625 try: | |
626 if isinstance(source, string_types): | |
627 source_hint = source | |
628 source = self._parse(source, name, filename) | |
629 source = self._generate(source, name, filename, defer_init=defer_init) | |
630 if raw: | |
631 return source | |
632 if filename is None: | |
633 filename = "<template>" | |
634 else: | |
635 filename = encode_filename(filename) | |
636 return self._compile(source, filename) | |
637 except TemplateSyntaxError: | |
638 self.handle_exception(source=source_hint) | |
639 | |
640 def compile_expression(self, source, undefined_to_none=True): | |
641 """A handy helper method that returns a callable that accepts keyword | |
642 arguments that appear as variables in the expression. If called it | |
643 returns the result of the expression. | |
644 | |
645 This is useful if applications want to use the same rules as Jinja | |
646 in template "configuration files" or similar situations. | |
647 | |
648 Example usage: | |
649 | |
650 >>> env = Environment() | |
651 >>> expr = env.compile_expression('foo == 42') | |
652 >>> expr(foo=23) | |
653 False | |
654 >>> expr(foo=42) | |
655 True | |
656 | |
657 Per default the return value is converted to `None` if the | |
658 expression returns an undefined value. This can be changed | |
659 by setting `undefined_to_none` to `False`. | |
660 | |
661 >>> env.compile_expression('var')() is None | |
662 True | |
663 >>> env.compile_expression('var', undefined_to_none=False)() | |
664 Undefined | |
665 | |
666 .. versionadded:: 2.1 | |
667 """ | |
668 parser = Parser(self, source, state="variable") | |
669 try: | |
670 expr = parser.parse_expression() | |
671 if not parser.stream.eos: | |
672 raise TemplateSyntaxError( | |
673 "chunk after expression", parser.stream.current.lineno, None, None | |
674 ) | |
675 expr.set_environment(self) | |
676 except TemplateSyntaxError: | |
677 if sys.exc_info() is not None: | |
678 self.handle_exception(source=source) | |
679 | |
680 body = [nodes.Assign(nodes.Name("result", "store"), expr, lineno=1)] | |
681 template = self.from_string(nodes.Template(body, lineno=1)) | |
682 return TemplateExpression(template, undefined_to_none) | |
683 | |
684 def compile_templates( | |
685 self, | |
686 target, | |
687 extensions=None, | |
688 filter_func=None, | |
689 zip="deflated", | |
690 log_function=None, | |
691 ignore_errors=True, | |
692 py_compile=False, | |
693 ): | |
694 """Finds all the templates the loader can find, compiles them | |
695 and stores them in `target`. If `zip` is `None`, instead of in a | |
696 zipfile, the templates will be stored in a directory. | |
697 By default a deflate zip algorithm is used. To switch to | |
698 the stored algorithm, `zip` can be set to ``'stored'``. | |
699 | |
700 `extensions` and `filter_func` are passed to :meth:`list_templates`. | |
701 Each template returned will be compiled to the target folder or | |
702 zipfile. | |
703 | |
704 By default template compilation errors are ignored. In case a | |
705 log function is provided, errors are logged. If you want template | |
706 syntax errors to abort the compilation you can set `ignore_errors` | |
707 to `False` and you will get an exception on syntax errors. | |
708 | |
709 If `py_compile` is set to `True` .pyc files will be written to the | |
710 target instead of standard .py files. This flag does not do anything | |
711 on pypy and Python 3 where pyc files are not picked up by itself and | |
712 don't give much benefit. | |
713 | |
714 .. versionadded:: 2.4 | |
715 """ | |
716 from .loaders import ModuleLoader | |
717 | |
718 if log_function is None: | |
719 | |
720 def log_function(x): | |
721 pass | |
722 | |
723 if py_compile: | |
724 if not PY2 or PYPY: | |
725 import warnings | |
726 | |
727 warnings.warn( | |
728 "'py_compile=True' has no effect on PyPy or Python" | |
729 " 3 and will be removed in version 3.0", | |
730 DeprecationWarning, | |
731 stacklevel=2, | |
732 ) | |
733 py_compile = False | |
734 else: | |
735 import imp | |
736 import marshal | |
737 | |
738 py_header = imp.get_magic() + u"\xff\xff\xff\xff".encode("iso-8859-15") | |
739 | |
740 # Python 3.3 added a source filesize to the header | |
741 if sys.version_info >= (3, 3): | |
742 py_header += u"\x00\x00\x00\x00".encode("iso-8859-15") | |
743 | |
744 def write_file(filename, data): | |
745 if zip: | |
746 info = ZipInfo(filename) | |
747 info.external_attr = 0o755 << 16 | |
748 zip_file.writestr(info, data) | |
749 else: | |
750 if isinstance(data, text_type): | |
751 data = data.encode("utf8") | |
752 | |
753 with open(os.path.join(target, filename), "wb") as f: | |
754 f.write(data) | |
755 | |
756 if zip is not None: | |
757 from zipfile import ZipFile, ZipInfo, ZIP_DEFLATED, ZIP_STORED | |
758 | |
759 zip_file = ZipFile( | |
760 target, "w", dict(deflated=ZIP_DEFLATED, stored=ZIP_STORED)[zip] | |
761 ) | |
762 log_function('Compiling into Zip archive "%s"' % target) | |
763 else: | |
764 if not os.path.isdir(target): | |
765 os.makedirs(target) | |
766 log_function('Compiling into folder "%s"' % target) | |
767 | |
768 try: | |
769 for name in self.list_templates(extensions, filter_func): | |
770 source, filename, _ = self.loader.get_source(self, name) | |
771 try: | |
772 code = self.compile(source, name, filename, True, True) | |
773 except TemplateSyntaxError as e: | |
774 if not ignore_errors: | |
775 raise | |
776 log_function('Could not compile "%s": %s' % (name, e)) | |
777 continue | |
778 | |
779 filename = ModuleLoader.get_module_filename(name) | |
780 | |
781 if py_compile: | |
782 c = self._compile(code, encode_filename(filename)) | |
783 write_file(filename + "c", py_header + marshal.dumps(c)) | |
784 log_function('Byte-compiled "%s" as %s' % (name, filename + "c")) | |
785 else: | |
786 write_file(filename, code) | |
787 log_function('Compiled "%s" as %s' % (name, filename)) | |
788 finally: | |
789 if zip: | |
790 zip_file.close() | |
791 | |
792 log_function("Finished compiling templates") | |
793 | |
794 def list_templates(self, extensions=None, filter_func=None): | |
795 """Returns a list of templates for this environment. This requires | |
796 that the loader supports the loader's | |
797 :meth:`~BaseLoader.list_templates` method. | |
798 | |
799 If there are other files in the template folder besides the | |
800 actual templates, the returned list can be filtered. There are two | |
801 ways: either `extensions` is set to a list of file extensions for | |
802 templates, or a `filter_func` can be provided which is a callable that | |
803 is passed a template name and should return `True` if it should end up | |
804 in the result list. | |
805 | |
806 If the loader does not support that, a :exc:`TypeError` is raised. | |
807 | |
808 .. versionadded:: 2.4 | |
809 """ | |
810 names = self.loader.list_templates() | |
811 | |
812 if extensions is not None: | |
813 if filter_func is not None: | |
814 raise TypeError( | |
815 "either extensions or filter_func can be passed, but not both" | |
816 ) | |
817 | |
818 def filter_func(x): | |
819 return "." in x and x.rsplit(".", 1)[1] in extensions | |
820 | |
821 if filter_func is not None: | |
822 names = [name for name in names if filter_func(name)] | |
823 | |
824 return names | |
825 | |
826 def handle_exception(self, source=None): | |
827 """Exception handling helper. This is used internally to either raise | |
828 rewritten exceptions or return a rendered traceback for the template. | |
829 """ | |
830 from .debug import rewrite_traceback_stack | |
831 | |
832 reraise(*rewrite_traceback_stack(source=source)) | |
833 | |
834 def join_path(self, template, parent): | |
835 """Join a template with the parent. By default all the lookups are | |
836 relative to the loader root so this method returns the `template` | |
837 parameter unchanged, but if the paths should be relative to the | |
838 parent template, this function can be used to calculate the real | |
839 template name. | |
840 | |
841 Subclasses may override this method and implement template path | |
842 joining here. | |
843 """ | |
844 return template | |
845 | |
846 @internalcode | |
847 def _load_template(self, name, globals): | |
848 if self.loader is None: | |
849 raise TypeError("no loader for this environment specified") | |
850 cache_key = (weakref.ref(self.loader), name) | |
851 if self.cache is not None: | |
852 template = self.cache.get(cache_key) | |
853 if template is not None and ( | |
854 not self.auto_reload or template.is_up_to_date | |
855 ): | |
856 return template | |
857 template = self.loader.load(self, name, globals) | |
858 if self.cache is not None: | |
859 self.cache[cache_key] = template | |
860 return template | |
861 | |
862 @internalcode | |
863 def get_template(self, name, parent=None, globals=None): | |
864 """Load a template from the loader. If a loader is configured this | |
865 method asks the loader for the template and returns a :class:`Template`. | |
866 If the `parent` parameter is not `None`, :meth:`join_path` is called | |
867 to get the real template name before loading. | |
868 | |
869 The `globals` parameter can be used to provide template wide globals. | |
870 These variables are available in the context at render time. | |
871 | |
872 If the template does not exist a :exc:`TemplateNotFound` exception is | |
873 raised. | |
874 | |
875 .. versionchanged:: 2.4 | |
876 If `name` is a :class:`Template` object it is returned from the | |
877 function unchanged. | |
878 """ | |
879 if isinstance(name, Template): | |
880 return name | |
881 if parent is not None: | |
882 name = self.join_path(name, parent) | |
883 return self._load_template(name, self.make_globals(globals)) | |
884 | |
885 @internalcode | |
886 def select_template(self, names, parent=None, globals=None): | |
887 """Works like :meth:`get_template` but tries a number of templates | |
888 before it fails. If it cannot find any of the templates, it will | |
889 raise a :exc:`TemplatesNotFound` exception. | |
890 | |
891 .. versionchanged:: 2.11 | |
892 If names is :class:`Undefined`, an :exc:`UndefinedError` is | |
893 raised instead. If no templates were found and names | |
894 contains :class:`Undefined`, the message is more helpful. | |
895 | |
896 .. versionchanged:: 2.4 | |
897 If `names` contains a :class:`Template` object it is returned | |
898 from the function unchanged. | |
899 | |
900 .. versionadded:: 2.3 | |
901 """ | |
902 if isinstance(names, Undefined): | |
903 names._fail_with_undefined_error() | |
904 | |
905 if not names: | |
906 raise TemplatesNotFound( | |
907 message=u"Tried to select from an empty list " u"of templates." | |
908 ) | |
909 globals = self.make_globals(globals) | |
910 for name in names: | |
911 if isinstance(name, Template): | |
912 return name | |
913 if parent is not None: | |
914 name = self.join_path(name, parent) | |
915 try: | |
916 return self._load_template(name, globals) | |
917 except (TemplateNotFound, UndefinedError): | |
918 pass | |
919 raise TemplatesNotFound(names) | |
920 | |
921 @internalcode | |
922 def get_or_select_template(self, template_name_or_list, parent=None, globals=None): | |
923 """Does a typecheck and dispatches to :meth:`select_template` | |
924 if an iterable of template names is given, otherwise to | |
925 :meth:`get_template`. | |
926 | |
927 .. versionadded:: 2.3 | |
928 """ | |
929 if isinstance(template_name_or_list, (string_types, Undefined)): | |
930 return self.get_template(template_name_or_list, parent, globals) | |
931 elif isinstance(template_name_or_list, Template): | |
932 return template_name_or_list | |
933 return self.select_template(template_name_or_list, parent, globals) | |
934 | |
935 def from_string(self, source, globals=None, template_class=None): | |
936 """Load a template from a string. This parses the source given and | |
937 returns a :class:`Template` object. | |
938 """ | |
939 globals = self.make_globals(globals) | |
940 cls = template_class or self.template_class | |
941 return cls.from_code(self, self.compile(source), globals, None) | |
942 | |
943 def make_globals(self, d): | |
944 """Return a dict for the globals.""" | |
945 if not d: | |
946 return self.globals | |
947 return dict(self.globals, **d) | |
948 | |
949 | |
950 class Template(object): | |
951 """The central template object. This class represents a compiled template | |
952 and is used to evaluate it. | |
953 | |
954 Normally the template object is generated from an :class:`Environment` but | |
955 it also has a constructor that makes it possible to create a template | |
956 instance directly using the constructor. It takes the same arguments as | |
957 the environment constructor but it's not possible to specify a loader. | |
958 | |
959 Every template object has a few methods and members that are guaranteed | |
960 to exist. However it's important that a template object should be | |
961 considered immutable. Modifications on the object are not supported. | |
962 | |
963 Template objects created from the constructor rather than an environment | |
964 do have an `environment` attribute that points to a temporary environment | |
965 that is probably shared with other templates created with the constructor | |
966 and compatible settings. | |
967 | |
968 >>> template = Template('Hello {{ name }}!') | |
969 >>> template.render(name='John Doe') == u'Hello John Doe!' | |
970 True | |
971 >>> stream = template.stream(name='John Doe') | |
972 >>> next(stream) == u'Hello John Doe!' | |
973 True | |
974 >>> next(stream) | |
975 Traceback (most recent call last): | |
976 ... | |
977 StopIteration | |
978 """ | |
979 | |
980 #: Type of environment to create when creating a template directly | |
981 #: rather than through an existing environment. | |
982 environment_class = Environment | |
983 | |
984 def __new__( | |
985 cls, | |
986 source, | |
987 block_start_string=BLOCK_START_STRING, | |
988 block_end_string=BLOCK_END_STRING, | |
989 variable_start_string=VARIABLE_START_STRING, | |
990 variable_end_string=VARIABLE_END_STRING, | |
991 comment_start_string=COMMENT_START_STRING, | |
992 comment_end_string=COMMENT_END_STRING, | |
993 line_statement_prefix=LINE_STATEMENT_PREFIX, | |
994 line_comment_prefix=LINE_COMMENT_PREFIX, | |
995 trim_blocks=TRIM_BLOCKS, | |
996 lstrip_blocks=LSTRIP_BLOCKS, | |
997 newline_sequence=NEWLINE_SEQUENCE, | |
998 keep_trailing_newline=KEEP_TRAILING_NEWLINE, | |
999 extensions=(), | |
1000 optimized=True, | |
1001 undefined=Undefined, | |
1002 finalize=None, | |
1003 autoescape=False, | |
1004 enable_async=False, | |
1005 ): | |
1006 env = get_spontaneous_environment( | |
1007 cls.environment_class, | |
1008 block_start_string, | |
1009 block_end_string, | |
1010 variable_start_string, | |
1011 variable_end_string, | |
1012 comment_start_string, | |
1013 comment_end_string, | |
1014 line_statement_prefix, | |
1015 line_comment_prefix, | |
1016 trim_blocks, | |
1017 lstrip_blocks, | |
1018 newline_sequence, | |
1019 keep_trailing_newline, | |
1020 frozenset(extensions), | |
1021 optimized, | |
1022 undefined, | |
1023 finalize, | |
1024 autoescape, | |
1025 None, | |
1026 0, | |
1027 False, | |
1028 None, | |
1029 enable_async, | |
1030 ) | |
1031 return env.from_string(source, template_class=cls) | |
1032 | |
1033 @classmethod | |
1034 def from_code(cls, environment, code, globals, uptodate=None): | |
1035 """Creates a template object from compiled code and the globals. This | |
1036 is used by the loaders and environment to create a template object. | |
1037 """ | |
1038 namespace = {"environment": environment, "__file__": code.co_filename} | |
1039 exec(code, namespace) | |
1040 rv = cls._from_namespace(environment, namespace, globals) | |
1041 rv._uptodate = uptodate | |
1042 return rv | |
1043 | |
1044 @classmethod | |
1045 def from_module_dict(cls, environment, module_dict, globals): | |
1046 """Creates a template object from a module. This is used by the | |
1047 module loader to create a template object. | |
1048 | |
1049 .. versionadded:: 2.4 | |
1050 """ | |
1051 return cls._from_namespace(environment, module_dict, globals) | |
1052 | |
1053 @classmethod | |
1054 def _from_namespace(cls, environment, namespace, globals): | |
1055 t = object.__new__(cls) | |
1056 t.environment = environment | |
1057 t.globals = globals | |
1058 t.name = namespace["name"] | |
1059 t.filename = namespace["__file__"] | |
1060 t.blocks = namespace["blocks"] | |
1061 | |
1062 # render function and module | |
1063 t.root_render_func = namespace["root"] | |
1064 t._module = None | |
1065 | |
1066 # debug and loader helpers | |
1067 t._debug_info = namespace["debug_info"] | |
1068 t._uptodate = None | |
1069 | |
1070 # store the reference | |
1071 namespace["environment"] = environment | |
1072 namespace["__jinja_template__"] = t | |
1073 | |
1074 return t | |
1075 | |
1076 def render(self, *args, **kwargs): | |
1077 """This method accepts the same arguments as the `dict` constructor: | |
1078 A dict, a dict subclass or some keyword arguments. If no arguments | |
1079 are given the context will be empty. These two calls do the same:: | |
1080 | |
1081 template.render(knights='that say nih') | |
1082 template.render({'knights': 'that say nih'}) | |
1083 | |
1084 This will return the rendered template as unicode string. | |
1085 """ | |
1086 vars = dict(*args, **kwargs) | |
1087 try: | |
1088 return concat(self.root_render_func(self.new_context(vars))) | |
1089 except Exception: | |
1090 self.environment.handle_exception() | |
1091 | |
1092 def render_async(self, *args, **kwargs): | |
1093 """This works similar to :meth:`render` but returns a coroutine | |
1094 that when awaited returns the entire rendered template string. This | |
1095 requires the async feature to be enabled. | |
1096 | |
1097 Example usage:: | |
1098 | |
1099 await template.render_async(knights='that say nih; asynchronously') | |
1100 """ | |
1101 # see asyncsupport for the actual implementation | |
1102 raise NotImplementedError( | |
1103 "This feature is not available for this version of Python" | |
1104 ) | |
1105 | |
1106 def stream(self, *args, **kwargs): | |
1107 """Works exactly like :meth:`generate` but returns a | |
1108 :class:`TemplateStream`. | |
1109 """ | |
1110 return TemplateStream(self.generate(*args, **kwargs)) | |
1111 | |
1112 def generate(self, *args, **kwargs): | |
1113 """For very large templates it can be useful to not render the whole | |
1114 template at once but evaluate each statement after another and yield | |
1115 piece for piece. This method basically does exactly that and returns | |
1116 a generator that yields one item after another as unicode strings. | |
1117 | |
1118 It accepts the same arguments as :meth:`render`. | |
1119 """ | |
1120 vars = dict(*args, **kwargs) | |
1121 try: | |
1122 for event in self.root_render_func(self.new_context(vars)): | |
1123 yield event | |
1124 except Exception: | |
1125 yield self.environment.handle_exception() | |
1126 | |
1127 def generate_async(self, *args, **kwargs): | |
1128 """An async version of :meth:`generate`. Works very similarly but | |
1129 returns an async iterator instead. | |
1130 """ | |
1131 # see asyncsupport for the actual implementation | |
1132 raise NotImplementedError( | |
1133 "This feature is not available for this version of Python" | |
1134 ) | |
1135 | |
1136 def new_context(self, vars=None, shared=False, locals=None): | |
1137 """Create a new :class:`Context` for this template. The vars | |
1138 provided will be passed to the template. Per default the globals | |
1139 are added to the context. If shared is set to `True` the data | |
1140 is passed as is to the context without adding the globals. | |
1141 | |
1142 `locals` can be a dict of local variables for internal usage. | |
1143 """ | |
1144 return new_context( | |
1145 self.environment, self.name, self.blocks, vars, shared, self.globals, locals | |
1146 ) | |
1147 | |
1148 def make_module(self, vars=None, shared=False, locals=None): | |
1149 """This method works like the :attr:`module` attribute when called | |
1150 without arguments but it will evaluate the template on every call | |
1151 rather than caching it. It's also possible to provide | |
1152 a dict which is then used as context. The arguments are the same | |
1153 as for the :meth:`new_context` method. | |
1154 """ | |
1155 return TemplateModule(self, self.new_context(vars, shared, locals)) | |
1156 | |
1157 def make_module_async(self, vars=None, shared=False, locals=None): | |
1158 """As template module creation can invoke template code for | |
1159 asynchronous executions this method must be used instead of the | |
1160 normal :meth:`make_module` one. Likewise the module attribute | |
1161 becomes unavailable in async mode. | |
1162 """ | |
1163 # see asyncsupport for the actual implementation | |
1164 raise NotImplementedError( | |
1165 "This feature is not available for this version of Python" | |
1166 ) | |
1167 | |
1168 @internalcode | |
1169 def _get_default_module(self): | |
1170 if self._module is not None: | |
1171 return self._module | |
1172 self._module = rv = self.make_module() | |
1173 return rv | |
1174 | |
1175 @property | |
1176 def module(self): | |
1177 """The template as module. This is used for imports in the | |
1178 template runtime but is also useful if one wants to access | |
1179 exported template variables from the Python layer: | |
1180 | |
1181 >>> t = Template('{% macro foo() %}42{% endmacro %}23') | |
1182 >>> str(t.module) | |
1183 '23' | |
1184 >>> t.module.foo() == u'42' | |
1185 True | |
1186 | |
1187 This attribute is not available if async mode is enabled. | |
1188 """ | |
1189 return self._get_default_module() | |
1190 | |
1191 def get_corresponding_lineno(self, lineno): | |
1192 """Return the source line number of a line number in the | |
1193 generated bytecode as they are not in sync. | |
1194 """ | |
1195 for template_line, code_line in reversed(self.debug_info): | |
1196 if code_line <= lineno: | |
1197 return template_line | |
1198 return 1 | |
1199 | |
1200 @property | |
1201 def is_up_to_date(self): | |
1202 """If this variable is `False` there is a newer version available.""" | |
1203 if self._uptodate is None: | |
1204 return True | |
1205 return self._uptodate() | |
1206 | |
1207 @property | |
1208 def debug_info(self): | |
1209 """The debug info mapping.""" | |
1210 if self._debug_info: | |
1211 return [tuple(map(int, x.split("="))) for x in self._debug_info.split("&")] | |
1212 return [] | |
1213 | |
1214 def __repr__(self): | |
1215 if self.name is None: | |
1216 name = "memory:%x" % id(self) | |
1217 else: | |
1218 name = repr(self.name) | |
1219 return "<%s %s>" % (self.__class__.__name__, name) | |
1220 | |
1221 | |
1222 @implements_to_string | |
1223 class TemplateModule(object): | |
1224 """Represents an imported template. All the exported names of the | |
1225 template are available as attributes on this object. Additionally | |
1226 converting it into an unicode- or bytestrings renders the contents. | |
1227 """ | |
1228 | |
1229 def __init__(self, template, context, body_stream=None): | |
1230 if body_stream is None: | |
1231 if context.environment.is_async: | |
1232 raise RuntimeError( | |
1233 "Async mode requires a body stream " | |
1234 "to be passed to a template module. Use " | |
1235 "the async methods of the API you are " | |
1236 "using." | |
1237 ) | |
1238 body_stream = list(template.root_render_func(context)) | |
1239 self._body_stream = body_stream | |
1240 self.__dict__.update(context.get_exported()) | |
1241 self.__name__ = template.name | |
1242 | |
1243 def __html__(self): | |
1244 return Markup(concat(self._body_stream)) | |
1245 | |
1246 def __str__(self): | |
1247 return concat(self._body_stream) | |
1248 | |
1249 def __repr__(self): | |
1250 if self.__name__ is None: | |
1251 name = "memory:%x" % id(self) | |
1252 else: | |
1253 name = repr(self.__name__) | |
1254 return "<%s %s>" % (self.__class__.__name__, name) | |
1255 | |
1256 | |
1257 class TemplateExpression(object): | |
1258 """The :meth:`jinja2.Environment.compile_expression` method returns an | |
1259 instance of this object. It encapsulates the expression-like access | |
1260 to the template with an expression it wraps. | |
1261 """ | |
1262 | |
1263 def __init__(self, template, undefined_to_none): | |
1264 self._template = template | |
1265 self._undefined_to_none = undefined_to_none | |
1266 | |
1267 def __call__(self, *args, **kwargs): | |
1268 context = self._template.new_context(dict(*args, **kwargs)) | |
1269 consume(self._template.root_render_func(context)) | |
1270 rv = context.vars["result"] | |
1271 if self._undefined_to_none and isinstance(rv, Undefined): | |
1272 rv = None | |
1273 return rv | |
1274 | |
1275 | |
1276 @implements_iterator | |
1277 class TemplateStream(object): | |
1278 """A template stream works pretty much like an ordinary python generator | |
1279 but it can buffer multiple items to reduce the number of total iterations. | |
1280 Per default the output is unbuffered which means that for every unbuffered | |
1281 instruction in the template one unicode string is yielded. | |
1282 | |
1283 If buffering is enabled with a buffer size of 5, five items are combined | |
1284 into a new unicode string. This is mainly useful if you are streaming | |
1285 big templates to a client via WSGI which flushes after each iteration. | |
1286 """ | |
1287 | |
1288 def __init__(self, gen): | |
1289 self._gen = gen | |
1290 self.disable_buffering() | |
1291 | |
1292 def dump(self, fp, encoding=None, errors="strict"): | |
1293 """Dump the complete stream into a file or file-like object. | |
1294 Per default unicode strings are written, if you want to encode | |
1295 before writing specify an `encoding`. | |
1296 | |
1297 Example usage:: | |
1298 | |
1299 Template('Hello {{ name }}!').stream(name='foo').dump('hello.html') | |
1300 """ | |
1301 close = False | |
1302 if isinstance(fp, string_types): | |
1303 if encoding is None: | |
1304 encoding = "utf-8" | |
1305 fp = open(fp, "wb") | |
1306 close = True | |
1307 try: | |
1308 if encoding is not None: | |
1309 iterable = (x.encode(encoding, errors) for x in self) | |
1310 else: | |
1311 iterable = self | |
1312 if hasattr(fp, "writelines"): | |
1313 fp.writelines(iterable) | |
1314 else: | |
1315 for item in iterable: | |
1316 fp.write(item) | |
1317 finally: | |
1318 if close: | |
1319 fp.close() | |
1320 | |
1321 def disable_buffering(self): | |
1322 """Disable the output buffering.""" | |
1323 self._next = partial(next, self._gen) | |
1324 self.buffered = False | |
1325 | |
1326 def _buffered_generator(self, size): | |
1327 buf = [] | |
1328 c_size = 0 | |
1329 push = buf.append | |
1330 | |
1331 while 1: | |
1332 try: | |
1333 while c_size < size: | |
1334 c = next(self._gen) | |
1335 push(c) | |
1336 if c: | |
1337 c_size += 1 | |
1338 except StopIteration: | |
1339 if not c_size: | |
1340 return | |
1341 yield concat(buf) | |
1342 del buf[:] | |
1343 c_size = 0 | |
1344 | |
1345 def enable_buffering(self, size=5): | |
1346 """Enable buffering. Buffer `size` items before yielding them.""" | |
1347 if size <= 1: | |
1348 raise ValueError("buffer size too small") | |
1349 | |
1350 self.buffered = True | |
1351 self._next = partial(next, self._buffered_generator(size)) | |
1352 | |
1353 def __iter__(self): | |
1354 return self | |
1355 | |
1356 def __next__(self): | |
1357 return self._next() | |
1358 | |
1359 | |
1360 # hook in default template class. if anyone reads this comment: ignore that | |
1361 # it's possible to use custom templates ;-) | |
1362 Environment.template_class = Template |