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