nodes.py (16353B)
1 #Embedded file name: C:\BuildAgent\work\20d73f1b24eed06e\eve\release\V24.01\carbon\common\lib\jinja2\nodes.py 2 import operator 3 from itertools import chain, izip 4 from collections import deque 5 from jinja2.utils import Markup, MethodType, FunctionType 6 _context_function_types = (FunctionType, MethodType) 7 _binop_to_func = {'*': operator.mul, 8 '/': operator.truediv, 9 '//': operator.floordiv, 10 '**': operator.pow, 11 '%': operator.mod, 12 '+': operator.add, 13 '-': operator.sub} 14 _uaop_to_func = {'not': operator.not_, 15 '+': operator.pos, 16 '-': operator.neg} 17 _cmpop_to_func = {'eq': operator.eq, 18 'ne': operator.ne, 19 'gt': operator.gt, 20 'gteq': operator.ge, 21 'lt': operator.lt, 22 'lteq': operator.le, 23 'in': lambda a, b: a in b, 24 'notin': lambda a, b: a not in b} 25 26 class Impossible(Exception): 27 pass 28 29 30 class NodeType(type): 31 32 def __new__(cls, name, bases, d): 33 for attr in ('fields', 'attributes'): 34 storage = [] 35 storage.extend(getattr(bases[0], attr, ())) 36 storage.extend(d.get(attr, ())) 37 d[attr] = tuple(storage) 38 39 d.setdefault('abstract', False) 40 return type.__new__(cls, name, bases, d) 41 42 43 class EvalContext(object): 44 45 def __init__(self, environment, template_name = None): 46 self.environment = environment 47 if callable(environment.autoescape): 48 self.autoescape = environment.autoescape(template_name) 49 else: 50 self.autoescape = environment.autoescape 51 self.volatile = False 52 53 def save(self): 54 return self.__dict__.copy() 55 56 def revert(self, old): 57 self.__dict__.clear() 58 self.__dict__.update(old) 59 60 61 def get_eval_context(node, ctx): 62 if ctx is None: 63 if node.environment is None: 64 raise RuntimeError('if no eval context is passed, the node must have an attached environment.') 65 return EvalContext(node.environment) 66 return ctx 67 68 69 class Node(object): 70 __metaclass__ = NodeType 71 fields = () 72 attributes = ('lineno', 'environment') 73 abstract = True 74 75 def __init__(self, *fields, **attributes): 76 if self.abstract: 77 raise TypeError('abstract nodes are not instanciable') 78 if fields: 79 if len(fields) != len(self.fields): 80 if not self.fields: 81 raise TypeError('%r takes 0 arguments' % self.__class__.__name__) 82 raise TypeError('%r takes 0 or %d argument%s' % (self.__class__.__name__, len(self.fields), len(self.fields) != 1 and 's' or '')) 83 for name, arg in izip(self.fields, fields): 84 setattr(self, name, arg) 85 86 for attr in self.attributes: 87 setattr(self, attr, attributes.pop(attr, None)) 88 89 if attributes: 90 raise TypeError('unknown attribute %r' % iter(attributes).next()) 91 92 def iter_fields(self, exclude = None, only = None): 93 for name in self.fields: 94 if exclude is only is None or exclude is not None and name not in exclude or only is not None and name in only: 95 try: 96 yield (name, getattr(self, name)) 97 except AttributeError: 98 pass 99 100 def iter_child_nodes(self, exclude = None, only = None): 101 for field, item in self.iter_fields(exclude, only): 102 if isinstance(item, list): 103 for n in item: 104 if isinstance(n, Node): 105 yield n 106 107 elif isinstance(item, Node): 108 yield item 109 110 def find(self, node_type): 111 for result in self.find_all(node_type): 112 return result 113 114 def find_all(self, node_type): 115 for child in self.iter_child_nodes(): 116 if isinstance(child, node_type): 117 yield child 118 for result in child.find_all(node_type): 119 yield result 120 121 def set_ctx(self, ctx): 122 todo = deque([self]) 123 while todo: 124 node = todo.popleft() 125 if 'ctx' in node.fields: 126 node.ctx = ctx 127 todo.extend(node.iter_child_nodes()) 128 129 return self 130 131 def set_lineno(self, lineno, override = False): 132 todo = deque([self]) 133 while todo: 134 node = todo.popleft() 135 if 'lineno' in node.attributes: 136 if node.lineno is None or override: 137 node.lineno = lineno 138 todo.extend(node.iter_child_nodes()) 139 140 return self 141 142 def set_environment(self, environment): 143 todo = deque([self]) 144 while todo: 145 node = todo.popleft() 146 node.environment = environment 147 todo.extend(node.iter_child_nodes()) 148 149 return self 150 151 def __eq__(self, other): 152 return type(self) is type(other) and tuple(self.iter_fields()) == tuple(other.iter_fields()) 153 154 def __ne__(self, other): 155 return not self.__eq__(other) 156 157 def __repr__(self): 158 return '%s(%s)' % (self.__class__.__name__, ', '.join(('%s=%r' % (arg, getattr(self, arg, None)) for arg in self.fields))) 159 160 161 class Stmt(Node): 162 abstract = True 163 164 165 class Helper(Node): 166 abstract = True 167 168 169 class Template(Node): 170 fields = ('body',) 171 172 173 class Output(Stmt): 174 fields = ('nodes',) 175 176 177 class Extends(Stmt): 178 fields = ('template',) 179 180 181 class For(Stmt): 182 fields = ('target', 'iter', 'body', 'else_', 'test', 'recursive') 183 184 185 class If(Stmt): 186 fields = ('test', 'body', 'else_') 187 188 189 class Macro(Stmt): 190 fields = ('name', 'args', 'defaults', 'body') 191 192 193 class CallBlock(Stmt): 194 fields = ('call', 'args', 'defaults', 'body') 195 196 197 class FilterBlock(Stmt): 198 fields = ('body', 'filter') 199 200 201 class Block(Stmt): 202 fields = ('name', 'body', 'scoped') 203 204 205 class Include(Stmt): 206 fields = ('template', 'with_context', 'ignore_missing') 207 208 209 class Import(Stmt): 210 fields = ('template', 'target', 'with_context') 211 212 213 class FromImport(Stmt): 214 fields = ('template', 'names', 'with_context') 215 216 217 class ExprStmt(Stmt): 218 fields = ('node',) 219 220 221 class Assign(Stmt): 222 fields = ('target', 'node') 223 224 225 class Expr(Node): 226 abstract = True 227 228 def as_const(self, eval_ctx = None): 229 raise Impossible() 230 231 def can_assign(self): 232 return False 233 234 235 class BinExpr(Expr): 236 fields = ('left', 'right') 237 operator = None 238 abstract = True 239 240 def as_const(self, eval_ctx = None): 241 eval_ctx = get_eval_context(self, eval_ctx) 242 if self.environment.sandboxed and self.operator in self.environment.intercepted_binops: 243 raise Impossible() 244 f = _binop_to_func[self.operator] 245 try: 246 return f(self.left.as_const(eval_ctx), self.right.as_const(eval_ctx)) 247 except Exception: 248 raise Impossible() 249 250 251 class UnaryExpr(Expr): 252 fields = ('node',) 253 operator = None 254 abstract = True 255 256 def as_const(self, eval_ctx = None): 257 eval_ctx = get_eval_context(self, eval_ctx) 258 if self.environment.sandboxed and self.operator in self.environment.intercepted_unops: 259 raise Impossible() 260 f = _uaop_to_func[self.operator] 261 try: 262 return f(self.node.as_const(eval_ctx)) 263 except Exception: 264 raise Impossible() 265 266 267 class Name(Expr): 268 fields = ('name', 'ctx') 269 270 def can_assign(self): 271 return self.name not in ('true', 'false', 'none', 'True', 'False', 'None') 272 273 274 class Literal(Expr): 275 abstract = True 276 277 278 class Const(Literal): 279 fields = ('value',) 280 281 def as_const(self, eval_ctx = None): 282 return self.value 283 284 @classmethod 285 def from_untrusted(cls, value, lineno = None, environment = None): 286 from compiler import has_safe_repr 287 if not has_safe_repr(value): 288 raise Impossible() 289 return cls(value, lineno=lineno, environment=environment) 290 291 292 class TemplateData(Literal): 293 fields = ('data',) 294 295 def as_const(self, eval_ctx = None): 296 eval_ctx = get_eval_context(self, eval_ctx) 297 if eval_ctx.volatile: 298 raise Impossible() 299 if eval_ctx.autoescape: 300 return Markup(self.data) 301 return self.data 302 303 304 class Tuple(Literal): 305 fields = ('items', 'ctx') 306 307 def as_const(self, eval_ctx = None): 308 eval_ctx = get_eval_context(self, eval_ctx) 309 return tuple((x.as_const(eval_ctx) for x in self.items)) 310 311 def can_assign(self): 312 for item in self.items: 313 if not item.can_assign(): 314 return False 315 316 return True 317 318 319 class List(Literal): 320 fields = ('items',) 321 322 def as_const(self, eval_ctx = None): 323 eval_ctx = get_eval_context(self, eval_ctx) 324 return [ x.as_const(eval_ctx) for x in self.items ] 325 326 327 class Dict(Literal): 328 fields = ('items',) 329 330 def as_const(self, eval_ctx = None): 331 eval_ctx = get_eval_context(self, eval_ctx) 332 return dict((x.as_const(eval_ctx) for x in self.items)) 333 334 335 class Pair(Helper): 336 fields = ('key', 'value') 337 338 def as_const(self, eval_ctx = None): 339 eval_ctx = get_eval_context(self, eval_ctx) 340 return (self.key.as_const(eval_ctx), self.value.as_const(eval_ctx)) 341 342 343 class Keyword(Helper): 344 fields = ('key', 'value') 345 346 def as_const(self, eval_ctx = None): 347 eval_ctx = get_eval_context(self, eval_ctx) 348 return (self.key, self.value.as_const(eval_ctx)) 349 350 351 class CondExpr(Expr): 352 fields = ('test', 'expr1', 'expr2') 353 354 def as_const(self, eval_ctx = None): 355 eval_ctx = get_eval_context(self, eval_ctx) 356 if self.test.as_const(eval_ctx): 357 return self.expr1.as_const(eval_ctx) 358 if self.expr2 is None: 359 raise Impossible() 360 return self.expr2.as_const(eval_ctx) 361 362 363 class Filter(Expr): 364 fields = ('node', 'name', 'args', 'kwargs', 'dyn_args', 'dyn_kwargs') 365 366 def as_const(self, eval_ctx = None): 367 eval_ctx = get_eval_context(self, eval_ctx) 368 if eval_ctx.volatile or self.node is None: 369 raise Impossible() 370 filter_ = self.environment.filters.get(self.name) 371 if filter_ is None or getattr(filter_, 'contextfilter', False): 372 raise Impossible() 373 obj = self.node.as_const(eval_ctx) 374 args = [ x.as_const(eval_ctx) for x in self.args ] 375 if getattr(filter_, 'evalcontextfilter', False): 376 args.insert(0, eval_ctx) 377 elif getattr(filter_, 'environmentfilter', False): 378 args.insert(0, self.environment) 379 kwargs = dict((x.as_const(eval_ctx) for x in self.kwargs)) 380 if self.dyn_args is not None: 381 try: 382 args.extend(self.dyn_args.as_const(eval_ctx)) 383 except Exception: 384 raise Impossible() 385 386 if self.dyn_kwargs is not None: 387 try: 388 kwargs.update(self.dyn_kwargs.as_const(eval_ctx)) 389 except Exception: 390 raise Impossible() 391 392 try: 393 return filter_(obj, *args, **kwargs) 394 except Exception: 395 raise Impossible() 396 397 398 class Test(Expr): 399 fields = ('node', 'name', 'args', 'kwargs', 'dyn_args', 'dyn_kwargs') 400 401 402 class Call(Expr): 403 fields = ('node', 'args', 'kwargs', 'dyn_args', 'dyn_kwargs') 404 405 def as_const(self, eval_ctx = None): 406 eval_ctx = get_eval_context(self, eval_ctx) 407 if eval_ctx.volatile: 408 raise Impossible() 409 obj = self.node.as_const(eval_ctx) 410 args = [ x.as_const(eval_ctx) for x in self.args ] 411 if isinstance(obj, _context_function_types): 412 if getattr(obj, 'contextfunction', False): 413 raise Impossible() 414 elif getattr(obj, 'evalcontextfunction', False): 415 args.insert(0, eval_ctx) 416 elif getattr(obj, 'environmentfunction', False): 417 args.insert(0, self.environment) 418 kwargs = dict((x.as_const(eval_ctx) for x in self.kwargs)) 419 if self.dyn_args is not None: 420 try: 421 args.extend(self.dyn_args.as_const(eval_ctx)) 422 except Exception: 423 raise Impossible() 424 425 if self.dyn_kwargs is not None: 426 try: 427 kwargs.update(self.dyn_kwargs.as_const(eval_ctx)) 428 except Exception: 429 raise Impossible() 430 431 try: 432 return obj(*args, **kwargs) 433 except Exception: 434 raise Impossible() 435 436 437 class Getitem(Expr): 438 fields = ('node', 'arg', 'ctx') 439 440 def as_const(self, eval_ctx = None): 441 eval_ctx = get_eval_context(self, eval_ctx) 442 if self.ctx != 'load': 443 raise Impossible() 444 try: 445 return self.environment.getitem(self.node.as_const(eval_ctx), self.arg.as_const(eval_ctx)) 446 except Exception: 447 raise Impossible() 448 449 def can_assign(self): 450 return False 451 452 453 class Getattr(Expr): 454 fields = ('node', 'attr', 'ctx') 455 456 def as_const(self, eval_ctx = None): 457 if self.ctx != 'load': 458 raise Impossible() 459 try: 460 eval_ctx = get_eval_context(self, eval_ctx) 461 return self.environment.getattr(self.node.as_const(eval_ctx), self.attr) 462 except Exception: 463 raise Impossible() 464 465 def can_assign(self): 466 return False 467 468 469 class Slice(Expr): 470 fields = ('start', 'stop', 'step') 471 472 def as_const(self, eval_ctx = None): 473 eval_ctx = get_eval_context(self, eval_ctx) 474 475 def const(obj): 476 if obj is None: 477 return 478 return obj.as_const(eval_ctx) 479 480 return slice(const(self.start), const(self.stop), const(self.step)) 481 482 483 class Concat(Expr): 484 fields = ('nodes',) 485 486 def as_const(self, eval_ctx = None): 487 eval_ctx = get_eval_context(self, eval_ctx) 488 return ''.join((unicode(x.as_const(eval_ctx)) for x in self.nodes)) 489 490 491 class Compare(Expr): 492 fields = ('expr', 'ops') 493 494 def as_const(self, eval_ctx = None): 495 eval_ctx = get_eval_context(self, eval_ctx) 496 result = value = self.expr.as_const(eval_ctx) 497 try: 498 for op in self.ops: 499 new_value = op.expr.as_const(eval_ctx) 500 result = _cmpop_to_func[op.op](value, new_value) 501 value = new_value 502 503 except Exception: 504 raise Impossible() 505 506 return result 507 508 509 class Operand(Helper): 510 fields = ('op', 'expr') 511 512 513 class Mul(BinExpr): 514 operator = '*' 515 516 517 class Div(BinExpr): 518 operator = '/' 519 520 521 class FloorDiv(BinExpr): 522 operator = '//' 523 524 525 class Add(BinExpr): 526 operator = '+' 527 528 529 class Sub(BinExpr): 530 operator = '-' 531 532 533 class Mod(BinExpr): 534 operator = '%' 535 536 537 class Pow(BinExpr): 538 operator = '**' 539 540 541 class And(BinExpr): 542 operator = 'and' 543 544 def as_const(self, eval_ctx = None): 545 eval_ctx = get_eval_context(self, eval_ctx) 546 return self.left.as_const(eval_ctx) and self.right.as_const(eval_ctx) 547 548 549 class Or(BinExpr): 550 operator = 'or' 551 552 def as_const(self, eval_ctx = None): 553 eval_ctx = get_eval_context(self, eval_ctx) 554 return self.left.as_const(eval_ctx) or self.right.as_const(eval_ctx) 555 556 557 class Not(UnaryExpr): 558 operator = 'not' 559 560 561 class Neg(UnaryExpr): 562 operator = '-' 563 564 565 class Pos(UnaryExpr): 566 operator = '+' 567 568 569 class EnvironmentAttribute(Expr): 570 fields = ('name',) 571 572 573 class ExtensionAttribute(Expr): 574 fields = ('identifier', 'name') 575 576 577 class ImportedName(Expr): 578 fields = ('importname',) 579 580 581 class InternalName(Expr): 582 fields = ('name',) 583 584 def __init__(self): 585 raise TypeError("Can't create internal names. Use the `free_identifier` method on a parser.") 586 587 588 class MarkSafe(Expr): 589 fields = ('expr',) 590 591 def as_const(self, eval_ctx = None): 592 eval_ctx = get_eval_context(self, eval_ctx) 593 return Markup(self.expr.as_const(eval_ctx)) 594 595 596 class MarkSafeIfAutoescape(Expr): 597 fields = ('expr',) 598 599 def as_const(self, eval_ctx = None): 600 eval_ctx = get_eval_context(self, eval_ctx) 601 if eval_ctx.volatile: 602 raise Impossible() 603 expr = self.expr.as_const(eval_ctx) 604 if eval_ctx.autoescape: 605 return Markup(expr) 606 return expr 607 608 609 class ContextReference(Expr): 610 pass 611 612 613 class Continue(Stmt): 614 pass 615 616 617 class Break(Stmt): 618 pass 619 620 621 class Scope(Stmt): 622 fields = ('body',) 623 624 625 class EvalContextModifier(Stmt): 626 fields = ('options',) 627 628 629 class ScopedEvalContextModifier(EvalContextModifier): 630 fields = ('body',) 631 632 633 def _failing_new(*args, **kwargs): 634 raise TypeError("can't create custom node types") 635 636 637 NodeType.__new__ = staticmethod(_failing_new) 638 del _failing_new