diff --git a/CHANGES b/CHANGES index b6922d253967f71e48dd415615da2db9ec609289..2031ea2c40458906b3c6f7e74d75a9fb843039a9 100644 --- a/CHANGES +++ b/CHANGES @@ -1,4 +1,6 @@ 0.2.3 +- added support for Jython 2.5. + - cache module now uses Beaker's clsmap to get at container classes, so cache types such as "ext:google", "ext:sqla", etc. are available. diff --git a/lib/mako/_ast_util.py b/lib/mako/_ast_util.py index 728eef881971f2fe27f3a43f4470abd06c106200..968084b55f88098eec28080dbd37982a140adab1 100644 --- a/lib/mako/_ast_util.py +++ b/lib/mako/_ast_util.py @@ -25,8 +25,37 @@ :copyright: Copyright 2008 by Armin Ronacher. :license: Python License. """ +import sys from _ast import * +if sys.platform.startswith('java'): + import array + + ast_list = array.ArrayType + get_symbol_key = lambda op: op + + def get_class_name(t): + result = t.__class__.__name__ + if result in ("org.python.antlr.ast.expr_contextType", + "org.python.antlr.ast.boolopType", + "org.python.antlr.ast.unaryopType", + "org.python.antlr.ast.cmpopType", + "org.python.antlr.ast.operatorType"): + result = str(t) + else: + result = result.split(".")[-1] + if result.endswith("Type"): + result = result[:-4] + if result == "Unicode": + # XXX: likely unecessary now + result = "Str" + return result + +else: + ast_list = list + get_symbol_key = type + get_class_name = lambda node: node.__class__.__name__ + BOOLOP_SYMBOLS = { And: 'and', @@ -109,7 +138,7 @@ def dump(node): return '%s(%s)' % (node.__class__.__name__, ', '.join('%s=%s' % (a, _format(b)) for a, b in iter_fields(node))) - elif isinstance(node, list): + elif isinstance(node, ast_list): return '[%s]' % ', '.join(_format(x) for x in node) return repr(node) if not isinstance(node, AST): @@ -190,7 +219,7 @@ def iter_child_nodes(node): for name, field in iter_fields(node): if isinstance(field, AST): yield field - elif isinstance(field, list): + elif isinstance(field, ast_list): for item in field: if isinstance(item, AST): yield item @@ -262,7 +291,7 @@ class NodeVisitor(object): exists for this node. In that case the generic visit function is used instead. """ - method = 'visit_' + node.__class__.__name__ + method = 'visit_' + get_class_name(node) return getattr(self, method, None) def visit(self, node): @@ -275,7 +304,7 @@ class NodeVisitor(object): def generic_visit(self, node): """Called if no explicit visitor function exists for a node.""" for field, value in iter_fields(node): - if isinstance(value, list): + if isinstance(value, ast_list): for item in value: if isinstance(item, AST): self.visit(item) @@ -321,7 +350,7 @@ class NodeTransformer(NodeVisitor): def generic_visit(self, node): for field, old_value in iter_fields(node): old_value = getattr(node, field, None) - if isinstance(old_value, list): + if isinstance(old_value, ast_list): new_values = [] for value in old_value: if isinstance(value, AST): @@ -422,7 +451,7 @@ class SourceGenerator(NodeVisitor): def visit_AugAssign(self, node): self.newline() self.visit(node.target) - self.write(BINOP_SYMBOLS[type(node.op)] + '=') + self.write(BINOP_SYMBOLS[get_symbol_key(node.op)] + '=') self.visit(node.value) def visit_ImportFrom(self, node): @@ -698,7 +727,7 @@ class SourceGenerator(NodeVisitor): def visit_BinOp(self, node): self.write('(') self.visit(node.left) - self.write(' %s ' % BINOP_SYMBOLS[type(node.op)]) + self.write(' %s ' % BINOP_SYMBOLS[get_symbol_key(node.op)]) self.visit(node.right) self.write(')') @@ -706,7 +735,7 @@ class SourceGenerator(NodeVisitor): self.write('(') for idx, value in enumerate(node.values): if idx: - self.write(' %s ' % BOOLOP_SYMBOLS[type(node.op)]) + self.write(' %s ' % BOOLOP_SYMBOLS[get_symbol_key(node.op)]) self.visit(value) self.write(')') @@ -714,13 +743,13 @@ class SourceGenerator(NodeVisitor): self.write('(') self.visit(node.left) for op, right in zip(node.ops, node.comparators): - self.write(' %s ' % CMPOP_SYMBOLS[type(op)]) + self.write(' %s ' % CMPOP_SYMBOLS[get_symbol_key(op)]) self.visit(right) self.write(')') def visit_UnaryOp(self, node): self.write('(') - op = UNARYOP_SYMBOLS[type(node.op)] + op = UNARYOP_SYMBOLS[get_symbol_key(node.op)] self.write(op) if op == 'not': self.write(' ') diff --git a/lib/mako/pyparser.py b/lib/mako/pyparser.py index 644afda94b428952da98f0924014ecb6a7340c09..cc9c04e2e7fd8b3f4f8ea9cc4b23e80fa3852077 100644 --- a/lib/mako/pyparser.py +++ b/lib/mako/pyparser.py @@ -17,13 +17,14 @@ from mako import exceptions, util # words that cannot be assigned to (notably smaller than the total keys in __builtins__) reserved = util.Set(['True', 'False', 'None']) -new_ast = sys.version_info > (2, 5) +jython = sys.platform.startswith('java') -if new_ast: +try: import _ast util.restore__ast(_ast) import _ast_util -else: +except ImportError: + _ast = None from compiler import parse as compiler_parse from compiler import visitor @@ -31,7 +32,7 @@ else: def parse(code, mode='exec', **exception_kwargs): """Parse an expression into AST""" try: - if new_ast: + if _ast: return _ast_util.parse(code, '<unknown>', mode) else: return compiler_parse(code, mode) @@ -39,7 +40,7 @@ def parse(code, mode='exec', **exception_kwargs): raise exceptions.SyntaxException("(%s) %s (%s)" % (e.__class__.__name__, str(e), repr(code[0:50])), **exception_kwargs) -if new_ast: +if _ast: class FindIdentifiers(_ast_util.NodeVisitor): def __init__(self, listener, **exception_kwargs): self.in_function = False @@ -90,7 +91,10 @@ if new_ast: for statement in node.orelse: self.visit(statement) def visit_Name(self, node): - if isinstance(node.ctx, _ast.Store): + if jython: + if node.ctx == _ast.Store: + self._add_declared(node.id) + elif isinstance(node.ctx, _ast.Store): self._add_declared(node.id) if node.id not in reserved and node.id not in self.listener.declared_identifiers and node.id not in self.local_ident_stack: self.listener.undeclared_identifiers.add(node.id)