Mercurial > genshi > genshi-test
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):] |