Coverage for /pythoncovmergedfiles/medio/medio/usr/local/lib/python3.8/site-packages/jinja2/environment.py: 49%

595 statements  

« prev     ^ index     » next       coverage.py v7.3.1, created at 2023-09-25 06:15 +0000

1"""Classes for managing templates and their runtime and compile time 

2options. 

3""" 

4import os 

5import typing 

6import typing as t 

7import weakref 

8from collections import ChainMap 

9from functools import lru_cache 

10from functools import partial 

11from functools import reduce 

12from types import CodeType 

13 

14from markupsafe import Markup 

15 

16from . import nodes 

17from .compiler import CodeGenerator 

18from .compiler import generate 

19from .defaults import BLOCK_END_STRING 

20from .defaults import BLOCK_START_STRING 

21from .defaults import COMMENT_END_STRING 

22from .defaults import COMMENT_START_STRING 

23from .defaults import DEFAULT_FILTERS 

24from .defaults import DEFAULT_NAMESPACE 

25from .defaults import DEFAULT_POLICIES 

26from .defaults import DEFAULT_TESTS 

27from .defaults import KEEP_TRAILING_NEWLINE 

28from .defaults import LINE_COMMENT_PREFIX 

29from .defaults import LINE_STATEMENT_PREFIX 

30from .defaults import LSTRIP_BLOCKS 

31from .defaults import NEWLINE_SEQUENCE 

32from .defaults import TRIM_BLOCKS 

33from .defaults import VARIABLE_END_STRING 

34from .defaults import VARIABLE_START_STRING 

35from .exceptions import TemplateNotFound 

36from .exceptions import TemplateRuntimeError 

37from .exceptions import TemplatesNotFound 

38from .exceptions import TemplateSyntaxError 

39from .exceptions import UndefinedError 

40from .lexer import get_lexer 

41from .lexer import Lexer 

42from .lexer import TokenStream 

43from .nodes import EvalContext 

44from .parser import Parser 

45from .runtime import Context 

46from .runtime import new_context 

47from .runtime import Undefined 

48from .utils import _PassArg 

49from .utils import concat 

50from .utils import consume 

51from .utils import import_string 

52from .utils import internalcode 

53from .utils import LRUCache 

54from .utils import missing 

55 

56if t.TYPE_CHECKING: 

57 import typing_extensions as te 

58 from .bccache import BytecodeCache 

59 from .ext import Extension 

60 from .loaders import BaseLoader 

61 

62_env_bound = t.TypeVar("_env_bound", bound="Environment") 

63 

64 

65# for direct template usage we have up to ten living environments 

66@lru_cache(maxsize=10) 

67def get_spontaneous_environment(cls: t.Type[_env_bound], *args: t.Any) -> _env_bound: 

68 """Return a new spontaneous environment. A spontaneous environment 

69 is used for templates created directly rather than through an 

70 existing environment. 

71 

72 :param cls: Environment class to create. 

73 :param args: Positional arguments passed to environment. 

74 """ 

75 env = cls(*args) 

76 env.shared = True 

77 return env 

78 

79 

80def create_cache( 

81 size: int, 

82) -> t.Optional[t.MutableMapping[t.Tuple["weakref.ref[BaseLoader]", str], "Template"]]: 

83 """Return the cache class for the given size.""" 

84 if size == 0: 

85 return None 

86 

87 if size < 0: 

88 return {} 

89 

90 return LRUCache(size) # type: ignore 

91 

92 

93def copy_cache( 

94 cache: t.Optional[ 

95 t.MutableMapping[t.Tuple["weakref.ref[BaseLoader]", str], "Template"] 

96 ], 

97) -> t.Optional[t.MutableMapping[t.Tuple["weakref.ref[BaseLoader]", str], "Template"]]: 

98 """Create an empty copy of the given cache.""" 

99 if cache is None: 

100 return None 

101 

102 if type(cache) is dict: 

103 return {} 

104 

105 return LRUCache(cache.capacity) # type: ignore 

106 

107 

108def load_extensions( 

109 environment: "Environment", 

110 extensions: t.Sequence[t.Union[str, t.Type["Extension"]]], 

111) -> t.Dict[str, "Extension"]: 

112 """Load the extensions from the list and bind it to the environment. 

113 Returns a dict of instantiated extensions. 

114 """ 

115 result = {} 

116 

117 for extension in extensions: 

118 if isinstance(extension, str): 

119 extension = t.cast(t.Type["Extension"], import_string(extension)) 

120 

121 result[extension.identifier] = extension(environment) 

122 

123 return result 

124 

125 

126def _environment_config_check(environment: "Environment") -> "Environment": 

127 """Perform a sanity check on the environment.""" 

128 assert issubclass( 

129 environment.undefined, Undefined 

130 ), "'undefined' must be a subclass of 'jinja2.Undefined'." 

131 assert ( 

132 environment.block_start_string 

133 != environment.variable_start_string 

134 != environment.comment_start_string 

135 ), "block, variable and comment start strings must be different." 

136 assert environment.newline_sequence in { 

137 "\r", 

138 "\r\n", 

139 "\n", 

140 }, "'newline_sequence' must be one of '\\n', '\\r\\n', or '\\r'." 

141 return environment 

142 

143 

144class Environment: 

145 r"""The core component of Jinja is the `Environment`. It contains 

146 important shared variables like configuration, filters, tests, 

147 globals and others. Instances of this class may be modified if 

148 they are not shared and if no template was loaded so far. 

149 Modifications on environments after the first template was loaded 

150 will lead to surprising effects and undefined behavior. 

151 

152 Here are the possible initialization parameters: 

153 

154 `block_start_string` 

155 The string marking the beginning of a block. Defaults to ``'{%'``. 

156 

157 `block_end_string` 

158 The string marking the end of a block. Defaults to ``'%}'``. 

159 

160 `variable_start_string` 

161 The string marking the beginning of a print statement. 

162 Defaults to ``'{{'``. 

163 

164 `variable_end_string` 

165 The string marking the end of a print statement. Defaults to 

166 ``'}}'``. 

167 

168 `comment_start_string` 

169 The string marking the beginning of a comment. Defaults to ``'{#'``. 

170 

171 `comment_end_string` 

172 The string marking the end of a comment. Defaults to ``'#}'``. 

173 

174 `line_statement_prefix` 

175 If given and a string, this will be used as prefix for line based 

176 statements. See also :ref:`line-statements`. 

177 

178 `line_comment_prefix` 

179 If given and a string, this will be used as prefix for line based 

180 comments. See also :ref:`line-statements`. 

181 

182 .. versionadded:: 2.2 

183 

184 `trim_blocks` 

185 If this is set to ``True`` the first newline after a block is 

186 removed (block, not variable tag!). Defaults to `False`. 

187 

188 `lstrip_blocks` 

189 If this is set to ``True`` leading spaces and tabs are stripped 

190 from the start of a line to a block. Defaults to `False`. 

191 

192 `newline_sequence` 

193 The sequence that starts a newline. Must be one of ``'\r'``, 

194 ``'\n'`` or ``'\r\n'``. The default is ``'\n'`` which is a 

195 useful default for Linux and OS X systems as well as web 

196 applications. 

197 

198 `keep_trailing_newline` 

199 Preserve the trailing newline when rendering templates. 

200 The default is ``False``, which causes a single newline, 

201 if present, to be stripped from the end of the template. 

202 

203 .. versionadded:: 2.7 

204 

205 `extensions` 

206 List of Jinja extensions to use. This can either be import paths 

207 as strings or extension classes. For more information have a 

208 look at :ref:`the extensions documentation <jinja-extensions>`. 

209 

210 `optimized` 

211 should the optimizer be enabled? Default is ``True``. 

212 

213 `undefined` 

214 :class:`Undefined` or a subclass of it that is used to represent 

215 undefined values in the template. 

216 

217 `finalize` 

218 A callable that can be used to process the result of a variable 

219 expression before it is output. For example one can convert 

220 ``None`` implicitly into an empty string here. 

221 

222 `autoescape` 

223 If set to ``True`` the XML/HTML autoescaping feature is enabled by 

224 default. For more details about autoescaping see 

225 :class:`~markupsafe.Markup`. As of Jinja 2.4 this can also 

226 be a callable that is passed the template name and has to 

227 return ``True`` or ``False`` depending on autoescape should be 

228 enabled by default. 

229 

230 .. versionchanged:: 2.4 

231 `autoescape` can now be a function 

232 

233 `loader` 

234 The template loader for this environment. 

235 

236 `cache_size` 

237 The size of the cache. Per default this is ``400`` which means 

238 that if more than 400 templates are loaded the loader will clean 

239 out the least recently used template. If the cache size is set to 

240 ``0`` templates are recompiled all the time, if the cache size is 

241 ``-1`` the cache will not be cleaned. 

242 

243 .. versionchanged:: 2.8 

244 The cache size was increased to 400 from a low 50. 

245 

246 `auto_reload` 

247 Some loaders load templates from locations where the template 

248 sources may change (ie: file system or database). If 

249 ``auto_reload`` is set to ``True`` (default) every time a template is 

250 requested the loader checks if the source changed and if yes, it 

251 will reload the template. For higher performance it's possible to 

252 disable that. 

253 

254 `bytecode_cache` 

255 If set to a bytecode cache object, this object will provide a 

256 cache for the internal Jinja bytecode so that templates don't 

257 have to be parsed if they were not changed. 

258 

259 See :ref:`bytecode-cache` for more information. 

260 

261 `enable_async` 

262 If set to true this enables async template execution which 

263 allows using async functions and generators. 

264 """ 

265 

266 #: if this environment is sandboxed. Modifying this variable won't make 

267 #: the environment sandboxed though. For a real sandboxed environment 

268 #: have a look at jinja2.sandbox. This flag alone controls the code 

269 #: generation by the compiler. 

270 sandboxed = False 

271 

272 #: True if the environment is just an overlay 

273 overlayed = False 

274 

275 #: the environment this environment is linked to if it is an overlay 

276 linked_to: t.Optional["Environment"] = None 

277 

278 #: shared environments have this set to `True`. A shared environment 

279 #: must not be modified 

280 shared = False 

281 

282 #: the class that is used for code generation. See 

283 #: :class:`~jinja2.compiler.CodeGenerator` for more information. 

284 code_generator_class: t.Type["CodeGenerator"] = CodeGenerator 

285 

286 concat = "".join 

287 

288 #: the context class that is used for templates. See 

289 #: :class:`~jinja2.runtime.Context` for more information. 

290 context_class: t.Type[Context] = Context 

291 

292 template_class: t.Type["Template"] 

293 

294 def __init__( 

295 self, 

296 block_start_string: str = BLOCK_START_STRING, 

297 block_end_string: str = BLOCK_END_STRING, 

298 variable_start_string: str = VARIABLE_START_STRING, 

299 variable_end_string: str = VARIABLE_END_STRING, 

300 comment_start_string: str = COMMENT_START_STRING, 

301 comment_end_string: str = COMMENT_END_STRING, 

302 line_statement_prefix: t.Optional[str] = LINE_STATEMENT_PREFIX, 

303 line_comment_prefix: t.Optional[str] = LINE_COMMENT_PREFIX, 

304 trim_blocks: bool = TRIM_BLOCKS, 

305 lstrip_blocks: bool = LSTRIP_BLOCKS, 

306 newline_sequence: "te.Literal['\\n', '\\r\\n', '\\r']" = NEWLINE_SEQUENCE, 

307 keep_trailing_newline: bool = KEEP_TRAILING_NEWLINE, 

308 extensions: t.Sequence[t.Union[str, t.Type["Extension"]]] = (), 

309 optimized: bool = True, 

310 undefined: t.Type[Undefined] = Undefined, 

311 finalize: t.Optional[t.Callable[..., t.Any]] = None, 

312 autoescape: t.Union[bool, t.Callable[[t.Optional[str]], bool]] = False, 

313 loader: t.Optional["BaseLoader"] = None, 

314 cache_size: int = 400, 

315 auto_reload: bool = True, 

316 bytecode_cache: t.Optional["BytecodeCache"] = None, 

317 enable_async: bool = False, 

318 ): 

319 # !!Important notice!! 

320 # The constructor accepts quite a few arguments that should be 

321 # passed by keyword rather than position. However it's important to 

322 # not change the order of arguments because it's used at least 

323 # internally in those cases: 

324 # - spontaneous environments (i18n extension and Template) 

325 # - unittests 

326 # If parameter changes are required only add parameters at the end 

327 # and don't change the arguments (or the defaults!) of the arguments 

328 # existing already. 

329 

330 # lexer / parser information 

331 self.block_start_string = block_start_string 

332 self.block_end_string = block_end_string 

333 self.variable_start_string = variable_start_string 

334 self.variable_end_string = variable_end_string 

335 self.comment_start_string = comment_start_string 

336 self.comment_end_string = comment_end_string 

337 self.line_statement_prefix = line_statement_prefix 

338 self.line_comment_prefix = line_comment_prefix 

339 self.trim_blocks = trim_blocks 

340 self.lstrip_blocks = lstrip_blocks 

341 self.newline_sequence = newline_sequence 

342 self.keep_trailing_newline = keep_trailing_newline 

343 

344 # runtime information 

345 self.undefined: t.Type[Undefined] = undefined 

346 self.optimized = optimized 

347 self.finalize = finalize 

348 self.autoescape = autoescape 

349 

350 # defaults 

351 self.filters = DEFAULT_FILTERS.copy() 

352 self.tests = DEFAULT_TESTS.copy() 

353 self.globals = DEFAULT_NAMESPACE.copy() 

354 

355 # set the loader provided 

356 self.loader = loader 

357 self.cache = create_cache(cache_size) 

358 self.bytecode_cache = bytecode_cache 

359 self.auto_reload = auto_reload 

360 

361 # configurable policies 

362 self.policies = DEFAULT_POLICIES.copy() 

363 

364 # load extensions 

365 self.extensions = load_extensions(self, extensions) 

366 

367 self.is_async = enable_async 

368 _environment_config_check(self) 

369 

370 def add_extension(self, extension: t.Union[str, t.Type["Extension"]]) -> None: 

371 """Adds an extension after the environment was created. 

372 

373 .. versionadded:: 2.5 

374 """ 

375 self.extensions.update(load_extensions(self, [extension])) 

376 

377 def extend(self, **attributes: t.Any) -> None: 

378 """Add the items to the instance of the environment if they do not exist 

379 yet. This is used by :ref:`extensions <writing-extensions>` to register 

380 callbacks and configuration values without breaking inheritance. 

381 """ 

382 for key, value in attributes.items(): 

383 if not hasattr(self, key): 

384 setattr(self, key, value) 

385 

386 def overlay( 

387 self, 

388 block_start_string: str = missing, 

389 block_end_string: str = missing, 

390 variable_start_string: str = missing, 

391 variable_end_string: str = missing, 

392 comment_start_string: str = missing, 

393 comment_end_string: str = missing, 

394 line_statement_prefix: t.Optional[str] = missing, 

395 line_comment_prefix: t.Optional[str] = missing, 

396 trim_blocks: bool = missing, 

397 lstrip_blocks: bool = missing, 

398 newline_sequence: "te.Literal['\\n', '\\r\\n', '\\r']" = missing, 

399 keep_trailing_newline: bool = missing, 

400 extensions: t.Sequence[t.Union[str, t.Type["Extension"]]] = missing, 

401 optimized: bool = missing, 

402 undefined: t.Type[Undefined] = missing, 

403 finalize: t.Optional[t.Callable[..., t.Any]] = missing, 

404 autoescape: t.Union[bool, t.Callable[[t.Optional[str]], bool]] = missing, 

405 loader: t.Optional["BaseLoader"] = missing, 

406 cache_size: int = missing, 

407 auto_reload: bool = missing, 

408 bytecode_cache: t.Optional["BytecodeCache"] = missing, 

409 enable_async: bool = False, 

410 ) -> "Environment": 

411 """Create a new overlay environment that shares all the data with the 

412 current environment except for cache and the overridden attributes. 

413 Extensions cannot be removed for an overlayed environment. An overlayed 

414 environment automatically gets all the extensions of the environment it 

415 is linked to plus optional extra extensions. 

416 

417 Creating overlays should happen after the initial environment was set 

418 up completely. Not all attributes are truly linked, some are just 

419 copied over so modifications on the original environment may not shine 

420 through. 

421 

422 .. versionchanged:: 3.1.2 

423 Added the ``newline_sequence``,, ``keep_trailing_newline``, 

424 and ``enable_async`` parameters to match ``__init__``. 

425 """ 

426 args = dict(locals()) 

427 del args["self"], args["cache_size"], args["extensions"], args["enable_async"] 

428 

429 rv = object.__new__(self.__class__) 

430 rv.__dict__.update(self.__dict__) 

431 rv.overlayed = True 

432 rv.linked_to = self 

433 

434 for key, value in args.items(): 

435 if value is not missing: 

436 setattr(rv, key, value) 

437 

438 if cache_size is not missing: 

439 rv.cache = create_cache(cache_size) 

440 else: 

441 rv.cache = copy_cache(self.cache) 

442 

443 rv.extensions = {} 

444 for key, value in self.extensions.items(): 

445 rv.extensions[key] = value.bind(rv) 

446 if extensions is not missing: 

447 rv.extensions.update(load_extensions(rv, extensions)) 

448 

449 if enable_async is not missing: 

450 rv.is_async = enable_async 

451 

452 return _environment_config_check(rv) 

453 

454 @property 

455 def lexer(self) -> Lexer: 

456 """The lexer for this environment.""" 

457 return get_lexer(self) 

458 

459 def iter_extensions(self) -> t.Iterator["Extension"]: 

460 """Iterates over the extensions by priority.""" 

461 return iter(sorted(self.extensions.values(), key=lambda x: x.priority)) 

462 

463 def getitem( 

464 self, obj: t.Any, argument: t.Union[str, t.Any] 

465 ) -> t.Union[t.Any, Undefined]: 

466 """Get an item or attribute of an object but prefer the item.""" 

467 try: 

468 return obj[argument] 

469 except (AttributeError, TypeError, LookupError): 

470 if isinstance(argument, str): 

471 try: 

472 attr = str(argument) 

473 except Exception: 

474 pass 

475 else: 

476 try: 

477 return getattr(obj, attr) 

478 except AttributeError: 

479 pass 

480 return self.undefined(obj=obj, name=argument) 

481 

482 def getattr(self, obj: t.Any, attribute: str) -> t.Any: 

483 """Get an item or attribute of an object but prefer the attribute. 

484 Unlike :meth:`getitem` the attribute *must* be a string. 

485 """ 

486 try: 

487 return getattr(obj, attribute) 

488 except AttributeError: 

489 pass 

490 try: 

491 return obj[attribute] 

492 except (TypeError, LookupError, AttributeError): 

493 return self.undefined(obj=obj, name=attribute) 

494 

495 def _filter_test_common( 

496 self, 

497 name: t.Union[str, Undefined], 

498 value: t.Any, 

499 args: t.Optional[t.Sequence[t.Any]], 

500 kwargs: t.Optional[t.Mapping[str, t.Any]], 

501 context: t.Optional[Context], 

502 eval_ctx: t.Optional[EvalContext], 

503 is_filter: bool, 

504 ) -> t.Any: 

505 if is_filter: 

506 env_map = self.filters 

507 type_name = "filter" 

508 else: 

509 env_map = self.tests 

510 type_name = "test" 

511 

512 func = env_map.get(name) # type: ignore 

513 

514 if func is None: 

515 msg = f"No {type_name} named {name!r}." 

516 

517 if isinstance(name, Undefined): 

518 try: 

519 name._fail_with_undefined_error() 

520 except Exception as e: 

521 msg = f"{msg} ({e}; did you forget to quote the callable name?)" 

522 

523 raise TemplateRuntimeError(msg) 

524 

525 args = [value, *(args if args is not None else ())] 

526 kwargs = kwargs if kwargs is not None else {} 

527 pass_arg = _PassArg.from_obj(func) 

528 

529 if pass_arg is _PassArg.context: 

530 if context is None: 

531 raise TemplateRuntimeError( 

532 f"Attempted to invoke a context {type_name} without context." 

533 ) 

534 

535 args.insert(0, context) 

536 elif pass_arg is _PassArg.eval_context: 

537 if eval_ctx is None: 

538 if context is not None: 

539 eval_ctx = context.eval_ctx 

540 else: 

541 eval_ctx = EvalContext(self) 

542 

543 args.insert(0, eval_ctx) 

544 elif pass_arg is _PassArg.environment: 

545 args.insert(0, self) 

546 

547 return func(*args, **kwargs) 

548 

549 def call_filter( 

550 self, 

551 name: str, 

552 value: t.Any, 

553 args: t.Optional[t.Sequence[t.Any]] = None, 

554 kwargs: t.Optional[t.Mapping[str, t.Any]] = None, 

555 context: t.Optional[Context] = None, 

556 eval_ctx: t.Optional[EvalContext] = None, 

557 ) -> t.Any: 

558 """Invoke a filter on a value the same way the compiler does. 

559 

560 This might return a coroutine if the filter is running from an 

561 environment in async mode and the filter supports async 

562 execution. It's your responsibility to await this if needed. 

563 

564 .. versionadded:: 2.7 

565 """ 

566 return self._filter_test_common( 

567 name, value, args, kwargs, context, eval_ctx, True 

568 ) 

569 

570 def call_test( 

571 self, 

572 name: str, 

573 value: t.Any, 

574 args: t.Optional[t.Sequence[t.Any]] = None, 

575 kwargs: t.Optional[t.Mapping[str, t.Any]] = None, 

576 context: t.Optional[Context] = None, 

577 eval_ctx: t.Optional[EvalContext] = None, 

578 ) -> t.Any: 

579 """Invoke a test on a value the same way the compiler does. 

580 

581 This might return a coroutine if the test is running from an 

582 environment in async mode and the test supports async execution. 

583 It's your responsibility to await this if needed. 

584 

585 .. versionchanged:: 3.0 

586 Tests support ``@pass_context``, etc. decorators. Added 

587 the ``context`` and ``eval_ctx`` parameters. 

588 

589 .. versionadded:: 2.7 

590 """ 

591 return self._filter_test_common( 

592 name, value, args, kwargs, context, eval_ctx, False 

593 ) 

594 

595 @internalcode 

596 def parse( 

597 self, 

598 source: str, 

599 name: t.Optional[str] = None, 

600 filename: t.Optional[str] = None, 

601 ) -> nodes.Template: 

602 """Parse the sourcecode and return the abstract syntax tree. This 

603 tree of nodes is used by the compiler to convert the template into 

604 executable source- or bytecode. This is useful for debugging or to 

605 extract information from templates. 

606 

607 If you are :ref:`developing Jinja extensions <writing-extensions>` 

608 this gives you a good overview of the node tree generated. 

609 """ 

610 try: 

611 return self._parse(source, name, filename) 

612 except TemplateSyntaxError: 

613 self.handle_exception(source=source) 

614 

615 def _parse( 

616 self, source: str, name: t.Optional[str], filename: t.Optional[str] 

617 ) -> nodes.Template: 

618 """Internal parsing function used by `parse` and `compile`.""" 

619 return Parser(self, source, name, filename).parse() 

620 

621 def lex( 

622 self, 

623 source: str, 

624 name: t.Optional[str] = None, 

625 filename: t.Optional[str] = None, 

626 ) -> t.Iterator[t.Tuple[int, str, str]]: 

627 """Lex the given sourcecode and return a generator that yields 

628 tokens as tuples in the form ``(lineno, token_type, value)``. 

629 This can be useful for :ref:`extension development <writing-extensions>` 

630 and debugging templates. 

631 

632 This does not perform preprocessing. If you want the preprocessing 

633 of the extensions to be applied you have to filter source through 

634 the :meth:`preprocess` method. 

635 """ 

636 source = str(source) 

637 try: 

638 return self.lexer.tokeniter(source, name, filename) 

639 except TemplateSyntaxError: 

640 self.handle_exception(source=source) 

641 

642 def preprocess( 

643 self, 

644 source: str, 

645 name: t.Optional[str] = None, 

646 filename: t.Optional[str] = None, 

647 ) -> str: 

648 """Preprocesses the source with all extensions. This is automatically 

649 called for all parsing and compiling methods but *not* for :meth:`lex` 

650 because there you usually only want the actual source tokenized. 

651 """ 

652 return reduce( 

653 lambda s, e: e.preprocess(s, name, filename), 

654 self.iter_extensions(), 

655 str(source), 

656 ) 

657 

658 def _tokenize( 

659 self, 

660 source: str, 

661 name: t.Optional[str], 

662 filename: t.Optional[str] = None, 

663 state: t.Optional[str] = None, 

664 ) -> TokenStream: 

665 """Called by the parser to do the preprocessing and filtering 

666 for all the extensions. Returns a :class:`~jinja2.lexer.TokenStream`. 

667 """ 

668 source = self.preprocess(source, name, filename) 

669 stream = self.lexer.tokenize(source, name, filename, state) 

670 

671 for ext in self.iter_extensions(): 

672 stream = ext.filter_stream(stream) # type: ignore 

673 

674 if not isinstance(stream, TokenStream): 

675 stream = TokenStream(stream, name, filename) # type: ignore 

676 

677 return stream 

678 

679 def _generate( 

680 self, 

681 source: nodes.Template, 

682 name: t.Optional[str], 

683 filename: t.Optional[str], 

684 defer_init: bool = False, 

685 ) -> str: 

686 """Internal hook that can be overridden to hook a different generate 

687 method in. 

688 

689 .. versionadded:: 2.5 

690 """ 

691 return generate( # type: ignore 

692 source, 

693 self, 

694 name, 

695 filename, 

696 defer_init=defer_init, 

697 optimized=self.optimized, 

698 ) 

699 

700 def _compile(self, source: str, filename: str) -> CodeType: 

701 """Internal hook that can be overridden to hook a different compile 

702 method in. 

703 

704 .. versionadded:: 2.5 

705 """ 

706 return compile(source, filename, "exec") 

707 

708 @typing.overload 

709 def compile( # type: ignore 

710 self, 

711 source: t.Union[str, nodes.Template], 

712 name: t.Optional[str] = None, 

713 filename: t.Optional[str] = None, 

714 raw: "te.Literal[False]" = False, 

715 defer_init: bool = False, 

716 ) -> CodeType: 

717 ... 

718 

719 @typing.overload 

720 def compile( 

721 self, 

722 source: t.Union[str, nodes.Template], 

723 name: t.Optional[str] = None, 

724 filename: t.Optional[str] = None, 

725 raw: "te.Literal[True]" = ..., 

726 defer_init: bool = False, 

727 ) -> str: 

728 ... 

729 

730 @internalcode 

731 def compile( 

732 self, 

733 source: t.Union[str, nodes.Template], 

734 name: t.Optional[str] = None, 

735 filename: t.Optional[str] = None, 

736 raw: bool = False, 

737 defer_init: bool = False, 

738 ) -> t.Union[str, CodeType]: 

739 """Compile a node or template source code. The `name` parameter is 

740 the load name of the template after it was joined using 

741 :meth:`join_path` if necessary, not the filename on the file system. 

742 the `filename` parameter is the estimated filename of the template on 

743 the file system. If the template came from a database or memory this 

744 can be omitted. 

745 

746 The return value of this method is a python code object. If the `raw` 

747 parameter is `True` the return value will be a string with python 

748 code equivalent to the bytecode returned otherwise. This method is 

749 mainly used internally. 

750 

751 `defer_init` is use internally to aid the module code generator. This 

752 causes the generated code to be able to import without the global 

753 environment variable to be set. 

754 

755 .. versionadded:: 2.4 

756 `defer_init` parameter added. 

757 """ 

758 source_hint = None 

759 try: 

760 if isinstance(source, str): 

761 source_hint = source 

762 source = self._parse(source, name, filename) 

763 source = self._generate(source, name, filename, defer_init=defer_init) 

764 if raw: 

765 return source 

766 if filename is None: 

767 filename = "<template>" 

768 return self._compile(source, filename) 

769 except TemplateSyntaxError: 

770 self.handle_exception(source=source_hint) 

771 

772 def compile_expression( 

773 self, source: str, undefined_to_none: bool = True 

774 ) -> "TemplateExpression": 

775 """A handy helper method that returns a callable that accepts keyword 

776 arguments that appear as variables in the expression. If called it 

777 returns the result of the expression. 

778 

779 This is useful if applications want to use the same rules as Jinja 

780 in template "configuration files" or similar situations. 

781 

782 Example usage: 

783 

784 >>> env = Environment() 

785 >>> expr = env.compile_expression('foo == 42') 

786 >>> expr(foo=23) 

787 False 

788 >>> expr(foo=42) 

789 True 

790 

791 Per default the return value is converted to `None` if the 

792 expression returns an undefined value. This can be changed 

793 by setting `undefined_to_none` to `False`. 

794 

795 >>> env.compile_expression('var')() is None 

796 True 

797 >>> env.compile_expression('var', undefined_to_none=False)() 

798 Undefined 

799 

800 .. versionadded:: 2.1 

801 """ 

802 parser = Parser(self, source, state="variable") 

803 try: 

804 expr = parser.parse_expression() 

805 if not parser.stream.eos: 

806 raise TemplateSyntaxError( 

807 "chunk after expression", parser.stream.current.lineno, None, None 

808 ) 

809 expr.set_environment(self) 

810 except TemplateSyntaxError: 

811 self.handle_exception(source=source) 

812 

813 body = [nodes.Assign(nodes.Name("result", "store"), expr, lineno=1)] 

814 template = self.from_string(nodes.Template(body, lineno=1)) 

815 return TemplateExpression(template, undefined_to_none) 

816 

817 def compile_templates( 

818 self, 

819 target: t.Union[str, "os.PathLike[str]"], 

820 extensions: t.Optional[t.Collection[str]] = None, 

821 filter_func: t.Optional[t.Callable[[str], bool]] = None, 

822 zip: t.Optional[str] = "deflated", 

823 log_function: t.Optional[t.Callable[[str], None]] = None, 

824 ignore_errors: bool = True, 

825 ) -> None: 

826 """Finds all the templates the loader can find, compiles them 

827 and stores them in `target`. If `zip` is `None`, instead of in a 

828 zipfile, the templates will be stored in a directory. 

829 By default a deflate zip algorithm is used. To switch to 

830 the stored algorithm, `zip` can be set to ``'stored'``. 

831 

832 `extensions` and `filter_func` are passed to :meth:`list_templates`. 

833 Each template returned will be compiled to the target folder or 

834 zipfile. 

835 

836 By default template compilation errors are ignored. In case a 

837 log function is provided, errors are logged. If you want template 

838 syntax errors to abort the compilation you can set `ignore_errors` 

839 to `False` and you will get an exception on syntax errors. 

840 

841 .. versionadded:: 2.4 

842 """ 

843 from .loaders import ModuleLoader 

844 

845 if log_function is None: 

846 

847 def log_function(x: str) -> None: 

848 pass 

849 

850 assert log_function is not None 

851 assert self.loader is not None, "No loader configured." 

852 

853 def write_file(filename: str, data: str) -> None: 

854 if zip: 

855 info = ZipInfo(filename) 

856 info.external_attr = 0o755 << 16 

857 zip_file.writestr(info, data) 

858 else: 

859 with open(os.path.join(target, filename), "wb") as f: 

860 f.write(data.encode("utf8")) 

861 

862 if zip is not None: 

863 from zipfile import ZipFile, ZipInfo, ZIP_DEFLATED, ZIP_STORED 

864 

865 zip_file = ZipFile( 

866 target, "w", dict(deflated=ZIP_DEFLATED, stored=ZIP_STORED)[zip] 

867 ) 

868 log_function(f"Compiling into Zip archive {target!r}") 

869 else: 

870 if not os.path.isdir(target): 

871 os.makedirs(target) 

872 log_function(f"Compiling into folder {target!r}") 

873 

874 try: 

875 for name in self.list_templates(extensions, filter_func): 

876 source, filename, _ = self.loader.get_source(self, name) 

877 try: 

878 code = self.compile(source, name, filename, True, True) 

879 except TemplateSyntaxError as e: 

880 if not ignore_errors: 

881 raise 

882 log_function(f'Could not compile "{name}": {e}') 

883 continue 

884 

885 filename = ModuleLoader.get_module_filename(name) 

886 

887 write_file(filename, code) 

888 log_function(f'Compiled "{name}" as {filename}') 

889 finally: 

890 if zip: 

891 zip_file.close() 

892 

893 log_function("Finished compiling templates") 

894 

895 def list_templates( 

896 self, 

897 extensions: t.Optional[t.Collection[str]] = None, 

898 filter_func: t.Optional[t.Callable[[str], bool]] = None, 

899 ) -> t.List[str]: 

900 """Returns a list of templates for this environment. This requires 

901 that the loader supports the loader's 

902 :meth:`~BaseLoader.list_templates` method. 

903 

904 If there are other files in the template folder besides the 

905 actual templates, the returned list can be filtered. There are two 

906 ways: either `extensions` is set to a list of file extensions for 

907 templates, or a `filter_func` can be provided which is a callable that 

908 is passed a template name and should return `True` if it should end up 

909 in the result list. 

910 

911 If the loader does not support that, a :exc:`TypeError` is raised. 

912 

913 .. versionadded:: 2.4 

914 """ 

915 assert self.loader is not None, "No loader configured." 

916 names = self.loader.list_templates() 

917 

918 if extensions is not None: 

919 if filter_func is not None: 

920 raise TypeError( 

921 "either extensions or filter_func can be passed, but not both" 

922 ) 

923 

924 def filter_func(x: str) -> bool: 

925 return "." in x and x.rsplit(".", 1)[1] in extensions 

926 

927 if filter_func is not None: 

928 names = [name for name in names if filter_func(name)] 

929 

930 return names 

931 

932 def handle_exception(self, source: t.Optional[str] = None) -> "te.NoReturn": 

933 """Exception handling helper. This is used internally to either raise 

934 rewritten exceptions or return a rendered traceback for the template. 

935 """ 

936 from .debug import rewrite_traceback_stack 

937 

938 raise rewrite_traceback_stack(source=source) 

939 

940 def join_path(self, template: str, parent: str) -> str: 

941 """Join a template with the parent. By default all the lookups are 

942 relative to the loader root so this method returns the `template` 

943 parameter unchanged, but if the paths should be relative to the 

944 parent template, this function can be used to calculate the real 

945 template name. 

946 

947 Subclasses may override this method and implement template path 

948 joining here. 

949 """ 

950 return template 

951 

952 @internalcode 

953 def _load_template( 

954 self, name: str, globals: t.Optional[t.MutableMapping[str, t.Any]] 

955 ) -> "Template": 

956 if self.loader is None: 

957 raise TypeError("no loader for this environment specified") 

958 cache_key = (weakref.ref(self.loader), name) 

959 if self.cache is not None: 

960 template = self.cache.get(cache_key) 

961 if template is not None and ( 

962 not self.auto_reload or template.is_up_to_date 

963 ): 

964 # template.globals is a ChainMap, modifying it will only 

965 # affect the template, not the environment globals. 

966 if globals: 

967 template.globals.update(globals) 

968 

969 return template 

970 

971 template = self.loader.load(self, name, self.make_globals(globals)) 

972 

973 if self.cache is not None: 

974 self.cache[cache_key] = template 

975 return template 

976 

977 @internalcode 

978 def get_template( 

979 self, 

980 name: t.Union[str, "Template"], 

981 parent: t.Optional[str] = None, 

982 globals: t.Optional[t.MutableMapping[str, t.Any]] = None, 

983 ) -> "Template": 

984 """Load a template by name with :attr:`loader` and return a 

985 :class:`Template`. If the template does not exist a 

986 :exc:`TemplateNotFound` exception is raised. 

987 

988 :param name: Name of the template to load. When loading 

989 templates from the filesystem, "/" is used as the path 

990 separator, even on Windows. 

991 :param parent: The name of the parent template importing this 

992 template. :meth:`join_path` can be used to implement name 

993 transformations with this. 

994 :param globals: Extend the environment :attr:`globals` with 

995 these extra variables available for all renders of this 

996 template. If the template has already been loaded and 

997 cached, its globals are updated with any new items. 

998 

999 .. versionchanged:: 3.0 

1000 If a template is loaded from cache, ``globals`` will update 

1001 the template's globals instead of ignoring the new values. 

1002 

1003 .. versionchanged:: 2.4 

1004 If ``name`` is a :class:`Template` object it is returned 

1005 unchanged. 

1006 """ 

1007 if isinstance(name, Template): 

1008 return name 

1009 if parent is not None: 

1010 name = self.join_path(name, parent) 

1011 

1012 return self._load_template(name, globals) 

1013 

1014 @internalcode 

1015 def select_template( 

1016 self, 

1017 names: t.Iterable[t.Union[str, "Template"]], 

1018 parent: t.Optional[str] = None, 

1019 globals: t.Optional[t.MutableMapping[str, t.Any]] = None, 

1020 ) -> "Template": 

1021 """Like :meth:`get_template`, but tries loading multiple names. 

1022 If none of the names can be loaded a :exc:`TemplatesNotFound` 

1023 exception is raised. 

1024 

1025 :param names: List of template names to try loading in order. 

1026 :param parent: The name of the parent template importing this 

1027 template. :meth:`join_path` can be used to implement name 

1028 transformations with this. 

1029 :param globals: Extend the environment :attr:`globals` with 

1030 these extra variables available for all renders of this 

1031 template. If the template has already been loaded and 

1032 cached, its globals are updated with any new items. 

1033 

1034 .. versionchanged:: 3.0 

1035 If a template is loaded from cache, ``globals`` will update 

1036 the template's globals instead of ignoring the new values. 

1037 

1038 .. versionchanged:: 2.11 

1039 If ``names`` is :class:`Undefined`, an :exc:`UndefinedError` 

1040 is raised instead. If no templates were found and ``names`` 

1041 contains :class:`Undefined`, the message is more helpful. 

1042 

1043 .. versionchanged:: 2.4 

1044 If ``names`` contains a :class:`Template` object it is 

1045 returned unchanged. 

1046 

1047 .. versionadded:: 2.3 

1048 """ 

1049 if isinstance(names, Undefined): 

1050 names._fail_with_undefined_error() 

1051 

1052 if not names: 

1053 raise TemplatesNotFound( 

1054 message="Tried to select from an empty list of templates." 

1055 ) 

1056 

1057 for name in names: 

1058 if isinstance(name, Template): 

1059 return name 

1060 if parent is not None: 

1061 name = self.join_path(name, parent) 

1062 try: 

1063 return self._load_template(name, globals) 

1064 except (TemplateNotFound, UndefinedError): 

1065 pass 

1066 raise TemplatesNotFound(names) # type: ignore 

1067 

1068 @internalcode 

1069 def get_or_select_template( 

1070 self, 

1071 template_name_or_list: t.Union[ 

1072 str, "Template", t.List[t.Union[str, "Template"]] 

1073 ], 

1074 parent: t.Optional[str] = None, 

1075 globals: t.Optional[t.MutableMapping[str, t.Any]] = None, 

1076 ) -> "Template": 

1077 """Use :meth:`select_template` if an iterable of template names 

1078 is given, or :meth:`get_template` if one name is given. 

1079 

1080 .. versionadded:: 2.3 

1081 """ 

1082 if isinstance(template_name_or_list, (str, Undefined)): 

1083 return self.get_template(template_name_or_list, parent, globals) 

1084 elif isinstance(template_name_or_list, Template): 

1085 return template_name_or_list 

1086 return self.select_template(template_name_or_list, parent, globals) 

1087 

1088 def from_string( 

1089 self, 

1090 source: t.Union[str, nodes.Template], 

1091 globals: t.Optional[t.MutableMapping[str, t.Any]] = None, 

1092 template_class: t.Optional[t.Type["Template"]] = None, 

1093 ) -> "Template": 

1094 """Load a template from a source string without using 

1095 :attr:`loader`. 

1096 

1097 :param source: Jinja source to compile into a template. 

1098 :param globals: Extend the environment :attr:`globals` with 

1099 these extra variables available for all renders of this 

1100 template. If the template has already been loaded and 

1101 cached, its globals are updated with any new items. 

1102 :param template_class: Return an instance of this 

1103 :class:`Template` class. 

1104 """ 

1105 gs = self.make_globals(globals) 

1106 cls = template_class or self.template_class 

1107 return cls.from_code(self, self.compile(source), gs, None) 

1108 

1109 def make_globals( 

1110 self, d: t.Optional[t.MutableMapping[str, t.Any]] 

1111 ) -> t.MutableMapping[str, t.Any]: 

1112 """Make the globals map for a template. Any given template 

1113 globals overlay the environment :attr:`globals`. 

1114 

1115 Returns a :class:`collections.ChainMap`. This allows any changes 

1116 to a template's globals to only affect that template, while 

1117 changes to the environment's globals are still reflected. 

1118 However, avoid modifying any globals after a template is loaded. 

1119 

1120 :param d: Dict of template-specific globals. 

1121 

1122 .. versionchanged:: 3.0 

1123 Use :class:`collections.ChainMap` to always prevent mutating 

1124 environment globals. 

1125 """ 

1126 if d is None: 

1127 d = {} 

1128 

1129 return ChainMap(d, self.globals) 

1130 

1131 

1132class Template: 

1133 """A compiled template that can be rendered. 

1134 

1135 Use the methods on :class:`Environment` to create or load templates. 

1136 The environment is used to configure how templates are compiled and 

1137 behave. 

1138 

1139 It is also possible to create a template object directly. This is 

1140 not usually recommended. The constructor takes most of the same 

1141 arguments as :class:`Environment`. All templates created with the 

1142 same environment arguments share the same ephemeral ``Environment`` 

1143 instance behind the scenes. 

1144 

1145 A template object should be considered immutable. Modifications on 

1146 the object are not supported. 

1147 """ 

1148 

1149 #: Type of environment to create when creating a template directly 

1150 #: rather than through an existing environment. 

1151 environment_class: t.Type[Environment] = Environment 

1152 

1153 environment: Environment 

1154 globals: t.MutableMapping[str, t.Any] 

1155 name: t.Optional[str] 

1156 filename: t.Optional[str] 

1157 blocks: t.Dict[str, t.Callable[[Context], t.Iterator[str]]] 

1158 root_render_func: t.Callable[[Context], t.Iterator[str]] 

1159 _module: t.Optional["TemplateModule"] 

1160 _debug_info: str 

1161 _uptodate: t.Optional[t.Callable[[], bool]] 

1162 

1163 def __new__( 

1164 cls, 

1165 source: t.Union[str, nodes.Template], 

1166 block_start_string: str = BLOCK_START_STRING, 

1167 block_end_string: str = BLOCK_END_STRING, 

1168 variable_start_string: str = VARIABLE_START_STRING, 

1169 variable_end_string: str = VARIABLE_END_STRING, 

1170 comment_start_string: str = COMMENT_START_STRING, 

1171 comment_end_string: str = COMMENT_END_STRING, 

1172 line_statement_prefix: t.Optional[str] = LINE_STATEMENT_PREFIX, 

1173 line_comment_prefix: t.Optional[str] = LINE_COMMENT_PREFIX, 

1174 trim_blocks: bool = TRIM_BLOCKS, 

1175 lstrip_blocks: bool = LSTRIP_BLOCKS, 

1176 newline_sequence: "te.Literal['\\n', '\\r\\n', '\\r']" = NEWLINE_SEQUENCE, 

1177 keep_trailing_newline: bool = KEEP_TRAILING_NEWLINE, 

1178 extensions: t.Sequence[t.Union[str, t.Type["Extension"]]] = (), 

1179 optimized: bool = True, 

1180 undefined: t.Type[Undefined] = Undefined, 

1181 finalize: t.Optional[t.Callable[..., t.Any]] = None, 

1182 autoescape: t.Union[bool, t.Callable[[t.Optional[str]], bool]] = False, 

1183 enable_async: bool = False, 

1184 ) -> t.Any: # it returns a `Template`, but this breaks the sphinx build... 

1185 env = get_spontaneous_environment( 

1186 cls.environment_class, # type: ignore 

1187 block_start_string, 

1188 block_end_string, 

1189 variable_start_string, 

1190 variable_end_string, 

1191 comment_start_string, 

1192 comment_end_string, 

1193 line_statement_prefix, 

1194 line_comment_prefix, 

1195 trim_blocks, 

1196 lstrip_blocks, 

1197 newline_sequence, 

1198 keep_trailing_newline, 

1199 frozenset(extensions), 

1200 optimized, 

1201 undefined, # type: ignore 

1202 finalize, 

1203 autoescape, 

1204 None, 

1205 0, 

1206 False, 

1207 None, 

1208 enable_async, 

1209 ) 

1210 return env.from_string(source, template_class=cls) 

1211 

1212 @classmethod 

1213 def from_code( 

1214 cls, 

1215 environment: Environment, 

1216 code: CodeType, 

1217 globals: t.MutableMapping[str, t.Any], 

1218 uptodate: t.Optional[t.Callable[[], bool]] = None, 

1219 ) -> "Template": 

1220 """Creates a template object from compiled code and the globals. This 

1221 is used by the loaders and environment to create a template object. 

1222 """ 

1223 namespace = {"environment": environment, "__file__": code.co_filename} 

1224 exec(code, namespace) 

1225 rv = cls._from_namespace(environment, namespace, globals) 

1226 rv._uptodate = uptodate 

1227 return rv 

1228 

1229 @classmethod 

1230 def from_module_dict( 

1231 cls, 

1232 environment: Environment, 

1233 module_dict: t.MutableMapping[str, t.Any], 

1234 globals: t.MutableMapping[str, t.Any], 

1235 ) -> "Template": 

1236 """Creates a template object from a module. This is used by the 

1237 module loader to create a template object. 

1238 

1239 .. versionadded:: 2.4 

1240 """ 

1241 return cls._from_namespace(environment, module_dict, globals) 

1242 

1243 @classmethod 

1244 def _from_namespace( 

1245 cls, 

1246 environment: Environment, 

1247 namespace: t.MutableMapping[str, t.Any], 

1248 globals: t.MutableMapping[str, t.Any], 

1249 ) -> "Template": 

1250 t: "Template" = object.__new__(cls) 

1251 t.environment = environment 

1252 t.globals = globals 

1253 t.name = namespace["name"] 

1254 t.filename = namespace["__file__"] 

1255 t.blocks = namespace["blocks"] 

1256 

1257 # render function and module 

1258 t.root_render_func = namespace["root"] 

1259 t._module = None 

1260 

1261 # debug and loader helpers 

1262 t._debug_info = namespace["debug_info"] 

1263 t._uptodate = None 

1264 

1265 # store the reference 

1266 namespace["environment"] = environment 

1267 namespace["__jinja_template__"] = t 

1268 

1269 return t 

1270 

1271 def render(self, *args: t.Any, **kwargs: t.Any) -> str: 

1272 """This method accepts the same arguments as the `dict` constructor: 

1273 A dict, a dict subclass or some keyword arguments. If no arguments 

1274 are given the context will be empty. These two calls do the same:: 

1275 

1276 template.render(knights='that say nih') 

1277 template.render({'knights': 'that say nih'}) 

1278 

1279 This will return the rendered template as a string. 

1280 """ 

1281 if self.environment.is_async: 

1282 import asyncio 

1283 

1284 close = False 

1285 

1286 try: 

1287 loop = asyncio.get_running_loop() 

1288 except RuntimeError: 

1289 loop = asyncio.new_event_loop() 

1290 close = True 

1291 

1292 try: 

1293 return loop.run_until_complete(self.render_async(*args, **kwargs)) 

1294 finally: 

1295 if close: 

1296 loop.close() 

1297 

1298 ctx = self.new_context(dict(*args, **kwargs)) 

1299 

1300 try: 

1301 return self.environment.concat(self.root_render_func(ctx)) # type: ignore 

1302 except Exception: 

1303 self.environment.handle_exception() 

1304 

1305 async def render_async(self, *args: t.Any, **kwargs: t.Any) -> str: 

1306 """This works similar to :meth:`render` but returns a coroutine 

1307 that when awaited returns the entire rendered template string. This 

1308 requires the async feature to be enabled. 

1309 

1310 Example usage:: 

1311 

1312 await template.render_async(knights='that say nih; asynchronously') 

1313 """ 

1314 if not self.environment.is_async: 

1315 raise RuntimeError( 

1316 "The environment was not created with async mode enabled." 

1317 ) 

1318 

1319 ctx = self.new_context(dict(*args, **kwargs)) 

1320 

1321 try: 

1322 return self.environment.concat( # type: ignore 

1323 [n async for n in self.root_render_func(ctx)] # type: ignore 

1324 ) 

1325 except Exception: 

1326 return self.environment.handle_exception() 

1327 

1328 def stream(self, *args: t.Any, **kwargs: t.Any) -> "TemplateStream": 

1329 """Works exactly like :meth:`generate` but returns a 

1330 :class:`TemplateStream`. 

1331 """ 

1332 return TemplateStream(self.generate(*args, **kwargs)) 

1333 

1334 def generate(self, *args: t.Any, **kwargs: t.Any) -> t.Iterator[str]: 

1335 """For very large templates it can be useful to not render the whole 

1336 template at once but evaluate each statement after another and yield 

1337 piece for piece. This method basically does exactly that and returns 

1338 a generator that yields one item after another as strings. 

1339 

1340 It accepts the same arguments as :meth:`render`. 

1341 """ 

1342 if self.environment.is_async: 

1343 import asyncio 

1344 

1345 async def to_list() -> t.List[str]: 

1346 return [x async for x in self.generate_async(*args, **kwargs)] 

1347 

1348 yield from asyncio.run(to_list()) 

1349 return 

1350 

1351 ctx = self.new_context(dict(*args, **kwargs)) 

1352 

1353 try: 

1354 yield from self.root_render_func(ctx) 

1355 except Exception: 

1356 yield self.environment.handle_exception() 

1357 

1358 async def generate_async( 

1359 self, *args: t.Any, **kwargs: t.Any 

1360 ) -> t.AsyncIterator[str]: 

1361 """An async version of :meth:`generate`. Works very similarly but 

1362 returns an async iterator instead. 

1363 """ 

1364 if not self.environment.is_async: 

1365 raise RuntimeError( 

1366 "The environment was not created with async mode enabled." 

1367 ) 

1368 

1369 ctx = self.new_context(dict(*args, **kwargs)) 

1370 

1371 try: 

1372 async for event in self.root_render_func(ctx): # type: ignore 

1373 yield event 

1374 except Exception: 

1375 yield self.environment.handle_exception() 

1376 

1377 def new_context( 

1378 self, 

1379 vars: t.Optional[t.Dict[str, t.Any]] = None, 

1380 shared: bool = False, 

1381 locals: t.Optional[t.Mapping[str, t.Any]] = None, 

1382 ) -> Context: 

1383 """Create a new :class:`Context` for this template. The vars 

1384 provided will be passed to the template. Per default the globals 

1385 are added to the context. If shared is set to `True` the data 

1386 is passed as is to the context without adding the globals. 

1387 

1388 `locals` can be a dict of local variables for internal usage. 

1389 """ 

1390 return new_context( 

1391 self.environment, self.name, self.blocks, vars, shared, self.globals, locals 

1392 ) 

1393 

1394 def make_module( 

1395 self, 

1396 vars: t.Optional[t.Dict[str, t.Any]] = None, 

1397 shared: bool = False, 

1398 locals: t.Optional[t.Mapping[str, t.Any]] = None, 

1399 ) -> "TemplateModule": 

1400 """This method works like the :attr:`module` attribute when called 

1401 without arguments but it will evaluate the template on every call 

1402 rather than caching it. It's also possible to provide 

1403 a dict which is then used as context. The arguments are the same 

1404 as for the :meth:`new_context` method. 

1405 """ 

1406 ctx = self.new_context(vars, shared, locals) 

1407 return TemplateModule(self, ctx) 

1408 

1409 async def make_module_async( 

1410 self, 

1411 vars: t.Optional[t.Dict[str, t.Any]] = None, 

1412 shared: bool = False, 

1413 locals: t.Optional[t.Mapping[str, t.Any]] = None, 

1414 ) -> "TemplateModule": 

1415 """As template module creation can invoke template code for 

1416 asynchronous executions this method must be used instead of the 

1417 normal :meth:`make_module` one. Likewise the module attribute 

1418 becomes unavailable in async mode. 

1419 """ 

1420 ctx = self.new_context(vars, shared, locals) 

1421 return TemplateModule( 

1422 self, ctx, [x async for x in self.root_render_func(ctx)] # type: ignore 

1423 ) 

1424 

1425 @internalcode 

1426 def _get_default_module(self, ctx: t.Optional[Context] = None) -> "TemplateModule": 

1427 """If a context is passed in, this means that the template was 

1428 imported. Imported templates have access to the current 

1429 template's globals by default, but they can only be accessed via 

1430 the context during runtime. 

1431 

1432 If there are new globals, we need to create a new module because 

1433 the cached module is already rendered and will not have access 

1434 to globals from the current context. This new module is not 

1435 cached because the template can be imported elsewhere, and it 

1436 should have access to only the current template's globals. 

1437 """ 

1438 if self.environment.is_async: 

1439 raise RuntimeError("Module is not available in async mode.") 

1440 

1441 if ctx is not None: 

1442 keys = ctx.globals_keys - self.globals.keys() 

1443 

1444 if keys: 

1445 return self.make_module({k: ctx.parent[k] for k in keys}) 

1446 

1447 if self._module is None: 

1448 self._module = self.make_module() 

1449 

1450 return self._module 

1451 

1452 async def _get_default_module_async( 

1453 self, ctx: t.Optional[Context] = None 

1454 ) -> "TemplateModule": 

1455 if ctx is not None: 

1456 keys = ctx.globals_keys - self.globals.keys() 

1457 

1458 if keys: 

1459 return await self.make_module_async({k: ctx.parent[k] for k in keys}) 

1460 

1461 if self._module is None: 

1462 self._module = await self.make_module_async() 

1463 

1464 return self._module 

1465 

1466 @property 

1467 def module(self) -> "TemplateModule": 

1468 """The template as module. This is used for imports in the 

1469 template runtime but is also useful if one wants to access 

1470 exported template variables from the Python layer: 

1471 

1472 >>> t = Template('{% macro foo() %}42{% endmacro %}23') 

1473 >>> str(t.module) 

1474 '23' 

1475 >>> t.module.foo() == u'42' 

1476 True 

1477 

1478 This attribute is not available if async mode is enabled. 

1479 """ 

1480 return self._get_default_module() 

1481 

1482 def get_corresponding_lineno(self, lineno: int) -> int: 

1483 """Return the source line number of a line number in the 

1484 generated bytecode as they are not in sync. 

1485 """ 

1486 for template_line, code_line in reversed(self.debug_info): 

1487 if code_line <= lineno: 

1488 return template_line 

1489 return 1 

1490 

1491 @property 

1492 def is_up_to_date(self) -> bool: 

1493 """If this variable is `False` there is a newer version available.""" 

1494 if self._uptodate is None: 

1495 return True 

1496 return self._uptodate() 

1497 

1498 @property 

1499 def debug_info(self) -> t.List[t.Tuple[int, int]]: 

1500 """The debug info mapping.""" 

1501 if self._debug_info: 

1502 return [ 

1503 tuple(map(int, x.split("="))) # type: ignore 

1504 for x in self._debug_info.split("&") 

1505 ] 

1506 

1507 return [] 

1508 

1509 def __repr__(self) -> str: 

1510 if self.name is None: 

1511 name = f"memory:{id(self):x}" 

1512 else: 

1513 name = repr(self.name) 

1514 return f"<{type(self).__name__} {name}>" 

1515 

1516 

1517class TemplateModule: 

1518 """Represents an imported template. All the exported names of the 

1519 template are available as attributes on this object. Additionally 

1520 converting it into a string renders the contents. 

1521 """ 

1522 

1523 def __init__( 

1524 self, 

1525 template: Template, 

1526 context: Context, 

1527 body_stream: t.Optional[t.Iterable[str]] = None, 

1528 ) -> None: 

1529 if body_stream is None: 

1530 if context.environment.is_async: 

1531 raise RuntimeError( 

1532 "Async mode requires a body stream to be passed to" 

1533 " a template module. Use the async methods of the" 

1534 " API you are using." 

1535 ) 

1536 

1537 body_stream = list(template.root_render_func(context)) 

1538 

1539 self._body_stream = body_stream 

1540 self.__dict__.update(context.get_exported()) 

1541 self.__name__ = template.name 

1542 

1543 def __html__(self) -> Markup: 

1544 return Markup(concat(self._body_stream)) 

1545 

1546 def __str__(self) -> str: 

1547 return concat(self._body_stream) 

1548 

1549 def __repr__(self) -> str: 

1550 if self.__name__ is None: 

1551 name = f"memory:{id(self):x}" 

1552 else: 

1553 name = repr(self.__name__) 

1554 return f"<{type(self).__name__} {name}>" 

1555 

1556 

1557class TemplateExpression: 

1558 """The :meth:`jinja2.Environment.compile_expression` method returns an 

1559 instance of this object. It encapsulates the expression-like access 

1560 to the template with an expression it wraps. 

1561 """ 

1562 

1563 def __init__(self, template: Template, undefined_to_none: bool) -> None: 

1564 self._template = template 

1565 self._undefined_to_none = undefined_to_none 

1566 

1567 def __call__(self, *args: t.Any, **kwargs: t.Any) -> t.Optional[t.Any]: 

1568 context = self._template.new_context(dict(*args, **kwargs)) 

1569 consume(self._template.root_render_func(context)) 

1570 rv = context.vars["result"] 

1571 if self._undefined_to_none and isinstance(rv, Undefined): 

1572 rv = None 

1573 return rv 

1574 

1575 

1576class TemplateStream: 

1577 """A template stream works pretty much like an ordinary python generator 

1578 but it can buffer multiple items to reduce the number of total iterations. 

1579 Per default the output is unbuffered which means that for every unbuffered 

1580 instruction in the template one string is yielded. 

1581 

1582 If buffering is enabled with a buffer size of 5, five items are combined 

1583 into a new string. This is mainly useful if you are streaming 

1584 big templates to a client via WSGI which flushes after each iteration. 

1585 """ 

1586 

1587 def __init__(self, gen: t.Iterator[str]) -> None: 

1588 self._gen = gen 

1589 self.disable_buffering() 

1590 

1591 def dump( 

1592 self, 

1593 fp: t.Union[str, t.IO[t.Any]], 

1594 encoding: t.Optional[str] = None, 

1595 errors: t.Optional[str] = "strict", 

1596 ) -> None: 

1597 """Dump the complete stream into a file or file-like object. 

1598 Per default strings are written, if you want to encode 

1599 before writing specify an `encoding`. 

1600 

1601 Example usage:: 

1602 

1603 Template('Hello {{ name }}!').stream(name='foo').dump('hello.html') 

1604 """ 

1605 close = False 

1606 

1607 if isinstance(fp, str): 

1608 if encoding is None: 

1609 encoding = "utf-8" 

1610 

1611 fp = open(fp, "wb") 

1612 close = True 

1613 try: 

1614 if encoding is not None: 

1615 iterable = (x.encode(encoding, errors) for x in self) # type: ignore 

1616 else: 

1617 iterable = self # type: ignore 

1618 

1619 if hasattr(fp, "writelines"): 

1620 fp.writelines(iterable) 

1621 else: 

1622 for item in iterable: 

1623 fp.write(item) 

1624 finally: 

1625 if close: 

1626 fp.close() 

1627 

1628 def disable_buffering(self) -> None: 

1629 """Disable the output buffering.""" 

1630 self._next = partial(next, self._gen) 

1631 self.buffered = False 

1632 

1633 def _buffered_generator(self, size: int) -> t.Iterator[str]: 

1634 buf: t.List[str] = [] 

1635 c_size = 0 

1636 push = buf.append 

1637 

1638 while True: 

1639 try: 

1640 while c_size < size: 

1641 c = next(self._gen) 

1642 push(c) 

1643 if c: 

1644 c_size += 1 

1645 except StopIteration: 

1646 if not c_size: 

1647 return 

1648 yield concat(buf) 

1649 del buf[:] 

1650 c_size = 0 

1651 

1652 def enable_buffering(self, size: int = 5) -> None: 

1653 """Enable buffering. Buffer `size` items before yielding them.""" 

1654 if size <= 1: 

1655 raise ValueError("buffer size too small") 

1656 

1657 self.buffered = True 

1658 self._next = partial(next, self._buffered_generator(size)) 

1659 

1660 def __iter__(self) -> "TemplateStream": 

1661 return self 

1662 

1663 def __next__(self) -> str: 

1664 return self._next() # type: ignore 

1665 

1666 

1667# hook in default template class. if anyone reads this comment: ignore that 

1668# it's possible to use custom templates ;-) 

1669Environment.template_class = Template