# HG changeset patch # User cmlenz # Date 1159348747 0 # Node ID 63bdd030c49ff6a38b4eb15b0dccc3cecad74acf # Parent eb0a369ebef6f1fce0fefd0e82606dfe0577aa35 * Better approach for absolute template paths in exceptions than what was checked in in [333]. Also, errors from `TextTemplate`s now also have absolute file paths. * A bit of cleanup in `genshi.eval`. diff --git a/genshi/eval.py b/genshi/eval.py --- a/genshi/eval.py +++ b/genshi/eval.py @@ -91,7 +91,8 @@ retval = eval(self.code, {'data': data, '_lookup_name': _lookup_name, '_lookup_attr': _lookup_attr, - '_lookup_item': _lookup_item}) + '_lookup_item': _lookup_item}, + {'data': data}) if not nocall and type(retval) is not Undefined and callable(retval): retval = retval() return retval @@ -295,17 +296,33 @@ visitAssName = visitAssTuple = _visitDefault visitConst = visitName = _visitDefault - def visitKeyword(self, node, *args, **kwargs): - node.expr = self.visit(node.expr, *args, **kwargs) - return node - def visitDict(self, node, *args, **kwargs): node.items = [(self.visit(k, *args, **kwargs), self.visit(v, *args, **kwargs)) for k, v in node.items] return node - def visitTuple(self, node, *args, **kwargs): - node.nodes = [self.visit(n, *args, **kwargs) for n in node.nodes] + def visitGenExpr(self, node, *args, **kwargs): + node.code = self.visit(node.code, *args, **kwargs) + node.filename = '' # workaround for bug in pycodegen + return node + + def visitGenExprFor(self, node, *args, **kwargs): + node.assign = self.visit(node.assign, *args, **kwargs) + node.iter = self.visit(node.iter, *args, **kwargs) + node.ifs = [self.visit(x, *args, **kwargs) for x in node.ifs] + return node + + def visitGenExprIf(self, node, *args, **kwargs): + node.test = self.visit(node.test, *args, **kwargs) + return node + + def visitGenExprInner(self, node, *args, **kwargs): + node.expr = self.visit(node.expr, *args, **kwargs) + node.quals = [self.visit(x, *args, **kwargs) for x in node.quals] + return node + + def visitKeyword(self, node, *args, **kwargs): + node.expr = self.visit(node.expr, *args, **kwargs) return node def visitList(self, node, *args, **kwargs): @@ -327,26 +344,6 @@ node.test = self.visit(node.test, *args, **kwargs) return node - def visitGenExpr(self, node, *args, **kwargs): - node.code = self.visit(node.code, *args, **kwargs) - node.filename = '' # workaround for bug in pycodegen - return node - - def visitGenExprFor(self, node, *args, **kwargs): - node.assign = self.visit(node.assign, *args, **kwargs) - node.iter = self.visit(node.iter, *args, **kwargs) - node.ifs = [self.visit(x, *args, **kwargs) for x in node.ifs] - return node - - def visitGenExprIf(self, node, *args, **kwargs): - node.test = self.visit(node.test, locals_=True, *args, **kwargs) - return node - - def visitGenExprInner(self, node, *args, **kwargs): - node.expr = self.visit(node.expr, locals_=True, *args, **kwargs) - node.quals = [self.visit(x, *args, **kwargs) for x in node.quals] - return node - def visitSlice(self, node, *args, **kwargs): node.expr = self.visit(node.expr, locals_=True, *args, **kwargs) if node.lower is not None: @@ -359,6 +356,10 @@ node.nodes = [self.visit(x, *args, **kwargs) for x in node.nodes] return node + def visitTuple(self, node, *args, **kwargs): + node.nodes = [self.visit(n, *args, **kwargs) for n in node.nodes] + return node + class ExpressionASTTransformer(ASTTransformer): """Concrete AST transformer that implements the AST transformations needed @@ -370,6 +371,15 @@ return ast.Const(node.value.decode('utf-8')) return node + def visitGenExprIf(self, node, *args, **kwargs): + node.test = self.visit(node.test, locals_=True) + return node + + def visitGenExprInner(self, node, *args, **kwargs): + node.expr = self.visit(node.expr, locals_=True) + node.quals = [self.visit(x) for x in node.quals] + return node + def visitGetattr(self, node, locals_=False): return ast.CallFunc(ast.Name('_lookup_attr'), [ ast.Name('data'), self.visit(node.expr, locals_=locals_), diff --git a/genshi/template.py b/genshi/template.py --- a/genshi/template.py +++ b/genshi/template.py @@ -108,7 +108,7 @@ self._match_templates = [] def __repr__(self): - return repr(self.frames) + return repr(list(self.frames)) def __setitem__(self, key, value): """Set a variable in the current scope.""" @@ -965,7 +965,7 @@ ns_prefix = {} depth = 0 - for kind, data, pos in XMLParser(self.source, filename=self.filename): + for kind, data, pos in XMLParser(self.source, filename=self.filepath): if kind is START_NS: # Strip out the namespace declaration for template directives @@ -992,7 +992,7 @@ if cls is None: raise BadDirectiveError(tag.localname, pos[0], pos[1]) value = attrib.get(getattr(cls, 'ATTRIBUTE', None), '') - directives.append(cls(value, self.filepath, pos[1], pos[2])) + directives.append(cls(value, *pos)) strip = True new_attrib = [] @@ -1002,12 +1002,10 @@ if cls is None: raise BadDirectiveError(name.localname, pos[0], pos[1]) - directives.append(cls(value, self.filepath, pos[1], - pos[2])) + directives.append(cls(value, *pos)) else: if value: - value = list(self._interpolate(value, self.filepath, - pos[1], pos[2])) + value = list(self._interpolate(value, *pos)) if len(value) == 1 and value[0][0] is TEXT: value = value[0][1] else: @@ -1038,8 +1036,7 @@ pos)] elif kind is TEXT: - for kind, data, pos in self._interpolate(data, self.filepath, - pos[1], pos[2]): + for kind, data, pos in self._interpolate(data, *pos): stream.append((kind, data, pos)) elif kind is COMMENT: @@ -1174,7 +1171,7 @@ start, end = mo.span() if start > offset: text = source[offset:start] - for kind, data, pos in self._interpolate(text, self.filename, + for kind, data, pos in self._interpolate(text, self.filepath, lineno, 0): stream.append((kind, data, pos)) lineno += len(text.splitlines()) @@ -1193,12 +1190,12 @@ directive, start_offset = dirmap.pop(depth) substream = stream[start_offset:] stream[start_offset:] = [(SUB, ([directive], substream), - (self.filename, lineno, 0))] + (self.filepath, lineno, 0))] elif command != '#': cls = self._dir_by_name.get(command) if cls is None: raise BadDirectiveError(command) - directive = cls(value, self.filename, lineno, 0) + directive = cls(value, self.filepath, lineno, 0) dirmap[depth] = (directive, len(stream)) depth += 1 @@ -1206,7 +1203,7 @@ if offset < len(source): text = source[offset:].replace('\\#', '#') - for kind, data, pos in self._interpolate(text, self.filename, + for kind, data, pos in self._interpolate(text, self.filepath, lineno, 0): stream.append((kind, data, pos)) diff --git a/genshi/tests/eval.py b/genshi/tests/eval.py --- a/genshi/tests/eval.py +++ b/genshi/tests/eval.py @@ -9,7 +9,7 @@ # # This software consists of voluntary contributions made by many # individuals. For the exact contribution history, see the revision -# history and logs, available at hhttp://genshi.edgewall.org/log/. +# history and logs, available at http://genshi.edgewall.org/log/. import doctest import sys