Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(203)

Side by Side Diff: third_party/jinja2/compiler.py

Issue 2316103002: binding: Updates Jinja2 from 2.7.1 to 2.8. (Closed)
Patch Set: Created 4 years, 3 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
« no previous file with comments | « third_party/jinja2/bccache.py ('k') | third_party/jinja2/debug.py » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 # -*- coding: utf-8 -*- 1 # -*- coding: utf-8 -*-
2 """ 2 """
3 jinja2.compiler 3 jinja2.compiler
4 ~~~~~~~~~~~~~~~ 4 ~~~~~~~~~~~~~~~
5 5
6 Compiles nodes into python code. 6 Compiles nodes into python code.
7 7
8 :copyright: (c) 2010 by the Jinja Team. 8 :copyright: (c) 2010 by the Jinja Team.
9 :license: BSD, see LICENSE for more details. 9 :license: BSD, see LICENSE for more details.
10 """ 10 """
11 from itertools import chain 11 from itertools import chain
12 from copy import deepcopy 12 from copy import deepcopy
13 from keyword import iskeyword as is_python_keyword 13 from keyword import iskeyword as is_python_keyword
14 from jinja2 import nodes 14 from jinja2 import nodes
15 from jinja2.nodes import EvalContext 15 from jinja2.nodes import EvalContext
16 from jinja2.visitor import NodeVisitor 16 from jinja2.visitor import NodeVisitor
17 from jinja2.exceptions import TemplateAssertionError 17 from jinja2.exceptions import TemplateAssertionError
18 from jinja2.utils import Markup, concat, escape 18 from jinja2.utils import Markup, concat, escape
19 from jinja2._compat import range_type, next, text_type, string_types, \ 19 from jinja2._compat import range_type, text_type, string_types, \
20 iteritems, NativeStringIO, imap 20 iteritems, NativeStringIO, imap
21 21
22 22
23 operators = { 23 operators = {
24 'eq': '==', 24 'eq': '==',
25 'ne': '!=', 25 'ne': '!=',
26 'gt': '>', 26 'gt': '>',
27 'gteq': '>=', 27 'gteq': '>=',
28 'lt': '<', 28 'lt': '<',
29 'lteq': '<=', 29 'lteq': '<=',
(...skipping 20 matching lines...) Expand all
50 # no closure is on the function 50 # no closure is on the function
51 unoptimize_before_dead_code = bool( 51 unoptimize_before_dead_code = bool(
52 getattr(unoptimize_before_dead_code(), '__closure__', None)) 52 getattr(unoptimize_before_dead_code(), '__closure__', None))
53 53
54 54
55 def generate(node, environment, name, filename, stream=None, 55 def generate(node, environment, name, filename, stream=None,
56 defer_init=False): 56 defer_init=False):
57 """Generate the python source for a node tree.""" 57 """Generate the python source for a node tree."""
58 if not isinstance(node, nodes.Template): 58 if not isinstance(node, nodes.Template):
59 raise TypeError('Can\'t compile non template nodes') 59 raise TypeError('Can\'t compile non template nodes')
60 generator = CodeGenerator(environment, name, filename, stream, defer_init) 60 generator = environment.code_generator_class(environment, name, filename,
61 stream, defer_init)
61 generator.visit(node) 62 generator.visit(node)
62 if stream is None: 63 if stream is None:
63 return generator.stream.getvalue() 64 return generator.stream.getvalue()
64 65
65 66
66 def has_safe_repr(value): 67 def has_safe_repr(value):
67 """Does the node have a safe representation?""" 68 """Does the node have a safe representation?"""
68 if value is None or value is NotImplemented or value is Ellipsis: 69 if value is None or value is NotImplemented or value is Ellipsis:
69 return True 70 return True
70 if isinstance(value, (bool, int, float, complex, range_type, 71 if isinstance(value, (bool, int, float, complex, range_type,
(...skipping 269 matching lines...) Expand 10 before | Expand all | Expand 10 after
340 is visited as part of the outer scope. 341 is visited as part of the outer scope.
341 """ 342 """
342 self.visit(node.iter) 343 self.visit(node.iter)
343 344
344 def visit_CallBlock(self, node): 345 def visit_CallBlock(self, node):
345 self.visit(node.call) 346 self.visit(node.call)
346 347
347 def visit_FilterBlock(self, node): 348 def visit_FilterBlock(self, node):
348 self.visit(node.filter) 349 self.visit(node.filter)
349 350
351 def visit_AssignBlock(self, node):
352 """Stop visiting at block assigns."""
353
350 def visit_Scope(self, node): 354 def visit_Scope(self, node):
351 """Stop visiting at scopes.""" 355 """Stop visiting at scopes."""
352 356
353 def visit_Block(self, node): 357 def visit_Block(self, node):
354 """Stop visiting at blocks.""" 358 """Stop visiting at blocks."""
355 359
356 360
357 class CompilerExit(Exception): 361 class CompilerExit(Exception):
358 """Raised if the compiler encountered a situation where it just 362 """Raised if the compiler encountered a situation where it just
359 doesn't make sense to further process the code. Any block that 363 doesn't make sense to further process the code. Any block that
(...skipping 848 matching lines...) Expand 10 before | Expand all | Expand 10 after
1208 def visit_ExprStmt(self, node, frame): 1212 def visit_ExprStmt(self, node, frame):
1209 self.newline(node) 1213 self.newline(node)
1210 self.visit(node.node, frame) 1214 self.visit(node.node, frame)
1211 1215
1212 def visit_Output(self, node, frame): 1216 def visit_Output(self, node, frame):
1213 # if we have a known extends statement, we don't output anything 1217 # if we have a known extends statement, we don't output anything
1214 # if we are in a require_output_check section 1218 # if we are in a require_output_check section
1215 if self.has_known_extends and frame.require_output_check: 1219 if self.has_known_extends and frame.require_output_check:
1216 return 1220 return
1217 1221
1222 allow_constant_finalize = True
1218 if self.environment.finalize: 1223 if self.environment.finalize:
1219 finalize = lambda x: text_type(self.environment.finalize(x)) 1224 func = self.environment.finalize
1225 if getattr(func, 'contextfunction', False) or \
1226 getattr(func, 'evalcontextfunction', False):
1227 allow_constant_finalize = False
1228 elif getattr(func, 'environmentfunction', False):
1229 finalize = lambda x: text_type(
1230 self.environment.finalize(self.environment, x))
1231 else:
1232 finalize = lambda x: text_type(self.environment.finalize(x))
1220 else: 1233 else:
1221 finalize = text_type 1234 finalize = text_type
1222 1235
1223 # if we are inside a frame that requires output checking, we do so 1236 # if we are inside a frame that requires output checking, we do so
1224 outdent_later = False 1237 outdent_later = False
1225 if frame.require_output_check: 1238 if frame.require_output_check:
1226 self.writeline('if parent_template is None:') 1239 self.writeline('if parent_template is None:')
1227 self.indent() 1240 self.indent()
1228 outdent_later = True 1241 outdent_later = True
1229 1242
1230 # try to evaluate as many chunks as possible into a static 1243 # try to evaluate as many chunks as possible into a static
1231 # string at compile time. 1244 # string at compile time.
1232 body = [] 1245 body = []
1233 for child in node.nodes: 1246 for child in node.nodes:
1234 try: 1247 try:
1248 if not allow_constant_finalize:
1249 raise nodes.Impossible()
1235 const = child.as_const(frame.eval_ctx) 1250 const = child.as_const(frame.eval_ctx)
1236 except nodes.Impossible: 1251 except nodes.Impossible:
1237 body.append(child) 1252 body.append(child)
1238 continue 1253 continue
1239 # the frame can't be volatile here, becaus otherwise the 1254 # the frame can't be volatile here, becaus otherwise the
1240 # as_const() function would raise an Impossible exception 1255 # as_const() function would raise an Impossible exception
1241 # at that point. 1256 # at that point.
1242 try: 1257 try:
1243 if frame.eval_ctx.autoescape: 1258 if frame.eval_ctx.autoescape:
1244 if hasattr(const, '__html__'): 1259 if hasattr(const, '__html__'):
(...skipping 35 matching lines...) Expand 10 before | Expand all | Expand 10 after
1280 close = 1 1295 close = 1
1281 if frame.eval_ctx.volatile: 1296 if frame.eval_ctx.volatile:
1282 self.write('(context.eval_ctx.autoescape and' 1297 self.write('(context.eval_ctx.autoescape and'
1283 ' escape or to_string)(') 1298 ' escape or to_string)(')
1284 elif frame.eval_ctx.autoescape: 1299 elif frame.eval_ctx.autoescape:
1285 self.write('escape(') 1300 self.write('escape(')
1286 else: 1301 else:
1287 self.write('to_string(') 1302 self.write('to_string(')
1288 if self.environment.finalize is not None: 1303 if self.environment.finalize is not None:
1289 self.write('environment.finalize(') 1304 self.write('environment.finalize(')
1305 if getattr(self.environment.finalize,
1306 "contextfunction", False):
1307 self.write('context, ')
1290 close += 1 1308 close += 1
1291 self.visit(item, frame) 1309 self.visit(item, frame)
1292 self.write(')' * close) 1310 self.write(')' * close)
1293 if frame.buffer is not None: 1311 if frame.buffer is not None:
1294 self.write(', ') 1312 self.write(', ')
1295 if frame.buffer is not None: 1313 if frame.buffer is not None:
1296 # close the open parentheses 1314 # close the open parentheses
1297 self.outdent() 1315 self.outdent()
1298 self.writeline(len(body) == 1 and ')' or '))') 1316 self.writeline(len(body) == 1 and ')' or '))')
1299 1317
1300 # otherwise we create a format string as this is faster in that case 1318 # otherwise we create a format string as this is faster in that case
1301 else: 1319 else:
1302 format = [] 1320 format = []
1303 arguments = [] 1321 arguments = []
1304 for item in body: 1322 for item in body:
1305 if isinstance(item, list): 1323 if isinstance(item, list):
1306 format.append(concat(item).replace('%', '%%')) 1324 format.append(concat(item).replace('%', '%%'))
1307 else: 1325 else:
1308 format.append('%s') 1326 format.append('%s')
1309 arguments.append(item) 1327 arguments.append(item)
1310 self.writeline('yield ') 1328 self.writeline('yield ')
1311 self.write(repr(concat(format)) + ' % (') 1329 self.write(repr(concat(format)) + ' % (')
1312 idx = -1
1313 self.indent() 1330 self.indent()
1314 for argument in arguments: 1331 for argument in arguments:
1315 self.newline(argument) 1332 self.newline(argument)
1316 close = 0 1333 close = 0
1317 if frame.eval_ctx.volatile: 1334 if frame.eval_ctx.volatile:
1318 self.write('(context.eval_ctx.autoescape and' 1335 self.write('(context.eval_ctx.autoescape and'
1319 ' escape or to_string)(') 1336 ' escape or to_string)(')
1320 close += 1 1337 close += 1
1321 elif frame.eval_ctx.autoescape: 1338 elif frame.eval_ctx.autoescape:
1322 self.write('escape(') 1339 self.write('escape(')
1323 close += 1 1340 close += 1
1324 if self.environment.finalize is not None: 1341 if self.environment.finalize is not None:
1325 self.write('environment.finalize(') 1342 self.write('environment.finalize(')
1343 if getattr(self.environment.finalize,
1344 'contextfunction', False):
1345 self.write('context, ')
1346 elif getattr(self.environment.finalize,
1347 'evalcontextfunction', False):
1348 self.write('context.eval_ctx, ')
1349 elif getattr(self.environment.finalize,
1350 'environmentfunction', False):
1351 self.write('environment, ')
1326 close += 1 1352 close += 1
1327 self.visit(argument, frame) 1353 self.visit(argument, frame)
1328 self.write(')' * close + ', ') 1354 self.write(')' * close + ', ')
1329 self.outdent() 1355 self.outdent()
1330 self.writeline(')') 1356 self.writeline(')')
1331 1357
1332 if outdent_later: 1358 if outdent_later:
1333 self.outdent() 1359 self.outdent()
1334 1360
1335 def visit_Assign(self, node, frame): 1361 def make_assignment_frame(self, frame):
1336 self.newline(node)
1337 # toplevel assignments however go into the local namespace and 1362 # toplevel assignments however go into the local namespace and
1338 # the current template's context. We create a copy of the frame 1363 # the current template's context. We create a copy of the frame
1339 # here and add a set so that the Name visitor can add the assigned 1364 # here and add a set so that the Name visitor can add the assigned
1340 # names here. 1365 # names here.
1341 if frame.toplevel: 1366 if not frame.toplevel:
1342 assignment_frame = frame.copy() 1367 return frame
1343 assignment_frame.toplevel_assignments = set() 1368 assignment_frame = frame.copy()
1369 assignment_frame.toplevel_assignments = set()
1370 return assignment_frame
1371
1372 def export_assigned_vars(self, frame, assignment_frame):
1373 if not frame.toplevel:
1374 return
1375 public_names = [x for x in assignment_frame.toplevel_assignments
1376 if not x.startswith('_')]
1377 if len(assignment_frame.toplevel_assignments) == 1:
1378 name = next(iter(assignment_frame.toplevel_assignments))
1379 self.writeline('context.vars[%r] = l_%s' % (name, name))
1344 else: 1380 else:
1345 assignment_frame = frame 1381 self.writeline('context.vars.update({')
1382 for idx, name in enumerate(assignment_frame.toplevel_assignments):
1383 if idx:
1384 self.write(', ')
1385 self.write('%r: l_%s' % (name, name))
1386 self.write('})')
1387 if public_names:
1388 if len(public_names) == 1:
1389 self.writeline('context.exported_vars.add(%r)' %
1390 public_names[0])
1391 else:
1392 self.writeline('context.exported_vars.update((%s))' %
1393 ', '.join(imap(repr, public_names)))
1394
1395 def visit_Assign(self, node, frame):
1396 self.newline(node)
1397 assignment_frame = self.make_assignment_frame(frame)
1346 self.visit(node.target, assignment_frame) 1398 self.visit(node.target, assignment_frame)
1347 self.write(' = ') 1399 self.write(' = ')
1348 self.visit(node.node, frame) 1400 self.visit(node.node, frame)
1401 self.export_assigned_vars(frame, assignment_frame)
1349 1402
1350 # make sure toplevel assignments are added to the context. 1403 def visit_AssignBlock(self, node, frame):
1351 if frame.toplevel: 1404 block_frame = frame.inner()
1352 public_names = [x for x in assignment_frame.toplevel_assignments 1405 block_frame.inspect(node.body)
1353 if not x.startswith('_')] 1406 aliases = self.push_scope(block_frame)
1354 if len(assignment_frame.toplevel_assignments) == 1: 1407 self.pull_locals(block_frame)
1355 name = next(iter(assignment_frame.toplevel_assignments)) 1408 self.buffer(block_frame)
1356 self.writeline('context.vars[%r] = l_%s' % (name, name)) 1409 self.blockvisit(node.body, block_frame)
1357 else: 1410 self.pop_scope(aliases, block_frame)
1358 self.writeline('context.vars.update({') 1411
1359 for idx, name in enumerate(assignment_frame.toplevel_assignments ): 1412 assignment_frame = self.make_assignment_frame(frame)
1360 if idx: 1413 self.newline(node)
1361 self.write(', ') 1414 self.visit(node.target, assignment_frame)
1362 self.write('%r: l_%s' % (name, name)) 1415 self.write(' = concat(%s)' % block_frame.buffer)
1363 self.write('})') 1416 self.export_assigned_vars(frame, assignment_frame)
1364 if public_names:
1365 if len(public_names) == 1:
1366 self.writeline('context.exported_vars.add(%r)' %
1367 public_names[0])
1368 else:
1369 self.writeline('context.exported_vars.update((%s))' %
1370 ', '.join(imap(repr, public_names)))
1371 1417
1372 # -- Expression Visitors 1418 # -- Expression Visitors
1373 1419
1374 def visit_Name(self, node, frame): 1420 def visit_Name(self, node, frame):
1375 if node.ctx == 'store' and frame.toplevel: 1421 if node.ctx == 'store' and frame.toplevel:
1376 frame.toplevel_assignments.add(node.name) 1422 frame.toplevel_assignments.add(node.name)
1377 self.write('l_' + node.name) 1423 self.write('l_' + node.name)
1378 frame.assigned_names.add(node.name) 1424 frame.assigned_names.add(node.name)
1379 1425
1380 def visit_Const(self, node, frame): 1426 def visit_Const(self, node, frame):
(...skipping 250 matching lines...) Expand 10 before | Expand all | Expand 10 after
1631 1677
1632 def visit_ScopedEvalContextModifier(self, node, frame): 1678 def visit_ScopedEvalContextModifier(self, node, frame):
1633 old_ctx_name = self.temporary_identifier() 1679 old_ctx_name = self.temporary_identifier()
1634 safed_ctx = frame.eval_ctx.save() 1680 safed_ctx = frame.eval_ctx.save()
1635 self.writeline('%s = context.eval_ctx.save()' % old_ctx_name) 1681 self.writeline('%s = context.eval_ctx.save()' % old_ctx_name)
1636 self.visit_EvalContextModifier(node, frame) 1682 self.visit_EvalContextModifier(node, frame)
1637 for child in node.body: 1683 for child in node.body:
1638 self.visit(child, frame) 1684 self.visit(child, frame)
1639 frame.eval_ctx.revert(safed_ctx) 1685 frame.eval_ctx.revert(safed_ctx)
1640 self.writeline('context.eval_ctx.revert(%s)' % old_ctx_name) 1686 self.writeline('context.eval_ctx.revert(%s)' % old_ctx_name)
OLDNEW
« no previous file with comments | « third_party/jinja2/bccache.py ('k') | third_party/jinja2/debug.py » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698