comparison genshi/template/eval.py @ 902:09cc3627654c experimental-inline

Sync `experimental/inline` branch with [source:trunk@1126].
author cmlenz
date Fri, 23 Apr 2010 21:08:26 +0000
parents de82830f8816
children 95d62e239f60
comparison
equal deleted inserted replaced
830:de82830f8816 902:09cc3627654c
1 # -*- coding: utf-8 -*- 1 # -*- coding: utf-8 -*-
2 # 2 #
3 # Copyright (C) 2006-2008 Edgewall Software 3 # Copyright (C) 2006-2010 Edgewall Software
4 # All rights reserved. 4 # All rights reserved.
5 # 5 #
6 # This software is licensed as described in the file COPYING, which 6 # This software is licensed as described in the file COPYING, which
7 # you should have received as part of this distribution. The terms 7 # you should have received as part of this distribution. The terms
8 # are also available at http://genshi.edgewall.org/wiki/License. 8 # are also available at http://genshi.edgewall.org/wiki/License.
118 118
119 def __ne__(self, other): 119 def __ne__(self, other):
120 return not self == other 120 return not self == other
121 121
122 def __repr__(self): 122 def __repr__(self):
123 return '%s(%r)' % (self.__class__.__name__, self.source) 123 return '%s(%r)' % (type(self).__name__, self.source)
124 124
125 125
126 class Expression(Code): 126 class Expression(Code):
127 """Evaluates Python expressions used in templates. 127 """Evaluates Python expressions used in templates.
128 128
227 >>> foo = Undefined('foo') 227 >>> foo = Undefined('foo')
228 >>> bool(foo) 228 >>> bool(foo)
229 False 229 False
230 >>> list(foo) 230 >>> list(foo)
231 [] 231 []
232 >>> print foo 232 >>> print(foo)
233 undefined 233 undefined
234 234
235 However, calling an undefined variable, or trying to access an attribute 235 However, calling an undefined variable, or trying to access an attribute
236 of that variable, will raise an exception that includes the name used to 236 of that variable, will raise an exception that includes the name used to
237 reference that undefined variable. 237 reference that undefined variable.
264 264
265 def __nonzero__(self): 265 def __nonzero__(self):
266 return False 266 return False
267 267
268 def __repr__(self): 268 def __repr__(self):
269 return '<%s %r>' % (self.__class__.__name__, self._name) 269 return '<%s %r>' % (type(self).__name__, self._name)
270 270
271 def __str__(self): 271 def __str__(self):
272 return 'undefined' 272 return 'undefined'
273 273
274 def _die(self, *args, **kwargs): 274 def _die(self, *args, **kwargs):
275 """Raise an `UndefinedError`.""" 275 """Raise an `UndefinedError`."""
276 __traceback_hide__ = True 276 __traceback_hide__ = True
277 raise UndefinedError(self._name, self._owner) 277 raise UndefinedError(self._name, self._owner)
278 __call__ = __getattr__ = __getitem__ = _die 278 __call__ = __getattr__ = __getitem__ = _die
279
280 # Hack around some behavior introduced in Python 2.6.2
281 # http://genshi.edgewall.org/ticket/324
282 __length_hint__ = None
279 283
280 284
281 class LookupBase(object): 285 class LookupBase(object):
282 """Abstract base class for variable lookup implementations.""" 286 """Abstract base class for variable lookup implementations."""
283 287
493 names.add(node.id) 497 names.add(node.id)
494 elif isinstance(node, _ast.alias): 498 elif isinstance(node, _ast.alias):
495 names.add(node.asname or node.name) 499 names.add(node.asname or node.name)
496 elif isinstance(node, _ast.Tuple): 500 elif isinstance(node, _ast.Tuple):
497 for elt in node.elts: 501 for elt in node.elts:
498 _process(node) 502 _process(elt)
499 if hasattr(node, 'args'): 503 if hasattr(node, 'args'):
500 for arg in node.args: 504 for arg in node.args:
501 _process(arg) 505 _process(arg)
502 if hasattr(node, 'vararg'): 506 if hasattr(node, 'vararg'):
503 names.add(node.vararg) 507 names.add(node.vararg)
556 self.locals.pop() 560 self.locals.pop()
557 561
558 # GeneratorExp(expr elt, comprehension* generators) 562 # GeneratorExp(expr elt, comprehension* generators)
559 def visit_GeneratorExp(self, node): 563 def visit_GeneratorExp(self, node):
560 gens = [] 564 gens = []
561 # need to visit them in inverse order 565 for generator in node.generators:
562 for generator in node.generators[::-1]:
563 # comprehension = (expr target, expr iter, expr* ifs) 566 # comprehension = (expr target, expr iter, expr* ifs)
564 self.locals.append(set()) 567 self.locals.append(set())
565 gen = _new(_ast.comprehension, self.visit(generator.target), 568 gen = _new(_ast.comprehension, self.visit(generator.target),
566 self.visit(generator.iter), 569 self.visit(generator.iter),
567 [self.visit(if_) for if_ in generator.ifs]) 570 [self.visit(if_) for if_ in generator.ifs])
568 gens.append(gen) 571 gens.append(gen)
569 gens.reverse()
570 572
571 # use node.__class__ to make it reusable as ListComp 573 # use node.__class__ to make it reusable as ListComp
572 ret = _new(node.__class__, self.visit(node.elt), gens) 574 ret = _new(node.__class__, self.visit(node.elt), gens)
573 #delete inserted locals 575 #delete inserted locals
574 del self.locals[-len(node.generators):] 576 del self.locals[-len(node.generators):]
Copyright (C) 2012-2017 Edgewall Software