PageRenderTime 54ms CodeModel.GetById 25ms RepoModel.GetById 0ms app.codeStats 0ms

/qpy/compile_jython.py

https://bitbucket.org/pfw/durusworks
Python | 220 lines | 214 code | 2 blank | 4 comment | 3 complexity | 39113e7aeb274e2566e8ea54d6601c3c MD5 | raw file
  1. """
  2. open/DurusWorks/qpy/compile_jython.py
  3. """
  4. from java.io import ByteArrayInputStream
  5. from java.io import ByteArrayOutputStream
  6. from org.python.antlr import AST
  7. from org.python.compiler import Module
  8. from org.python.core import imp
  9. from org.python.core import ParserFacade, CompileMode, CompilerFlags
  10. from os.path import splitext
  11. from pprint import pprint
  12. from qpy.translate import translate_tokens
  13. from _ast import astlist
  14. import py_compile
  15. import re
  16. import symbol
  17. import sys
  18. import sys
  19. import token
  20. import __builtin__ as builtins
  21. def get_parse_tree(source, source_name=None):
  22. if source_name is None:
  23. mode = 'eval'
  24. else:
  25. mode = 'exec'
  26. node = ParserFacade.parse(
  27. ByteArrayInputStream(source),
  28. getattr(CompileMode, mode),
  29. source_name or '',
  30. CompilerFlags())
  31. return node
  32. def tree(node):
  33. if isinstance(node, AST):
  34. result = [node.__class__.__name__]
  35. result.append(
  36. [(name, tree(getattr(node, name))) for name in node._fields])
  37. result.append(
  38. [(name, tree(getattr(node, name))) for name in node._attributes])
  39. if hasattr(node, '__iter__'):
  40. for child in node:
  41. result.append((type(child), tree(child)))
  42. return result
  43. if node is None:
  44. return None
  45. if type(node) in (str, int, float):
  46. return node
  47. if hasattr(node, '__iter__'):
  48. return [node.__class__.__name__] + [tree(x) for x in node]
  49. else:
  50. return (type(node), node)
  51. def ptree(node):
  52. pprint(tree(node))
  53. def children(node):
  54. if isinstance(node, AST):
  55. result = []
  56. for name in node._fields:
  57. if name == 'ctx':
  58. continue
  59. value = getattr(node, name)
  60. if get_node_type(node) == 'List' or isinstance(value, astlist):
  61. #print name, value
  62. #ptree(value)
  63. for x in value:
  64. result.append(x)
  65. else:
  66. result.append(value)
  67. return result
  68. if hasattr(node, '__iter__'):
  69. return list(node)
  70. else:
  71. return []
  72. def get_node_type(node):
  73. return node.__class__.__name__
  74. class Transform (object):
  75. def __init__(self, tree):
  76. self.tree = tree
  77. self.template_type_stack = [None]
  78. self.traverse_node(self.tree)
  79. self.line_number = 1
  80. self.rationalize_line_numbers(self.tree)
  81. def rationalize_line_numbers(self, node):
  82. if hasattr(node, 'lineno'):
  83. if not node.lineno or node.lineno < self.line_number:
  84. node.lineno = self.line_number
  85. else:
  86. self.line_number = node.lineno
  87. for n in children(node):
  88. self.rationalize_line_numbers(n)
  89. def traverse_node(self, node):
  90. node_type = get_node_type(node)
  91. #print node_type, node, children(node)
  92. if node_type == 'FunctionDef':
  93. function_name = node.name
  94. if function_name.endswith('__xml_template__'):
  95. self.template_type_stack.append('xml')
  96. elif function_name.endswith('__str_template__'):
  97. self.template_type_stack.append('str')
  98. else:
  99. self.template_type_stack.append(None)
  100. # Quote literals in xml templates first.
  101. for child in children(node):
  102. if self.template_type_stack[-1] == 'xml' and 'Str' == get_node_type(child):
  103. if node_type in ('Expr', 'Attribute') and child is node.value:
  104. xml_quote_call = get_parse_tree('_qpy_xml("X")').body
  105. xml_quote_call.args[0] = child
  106. node.value = xml_quote_call
  107. elif node_type == 'BinOp' and child is node.left:
  108. xml_quote_call = get_parse_tree('_qpy_xml("X")').body
  109. xml_quote_call.args[0] = child
  110. node.left = xml_quote_call
  111. elif node_type == 'BinOp' and child is node.right:
  112. xml_quote_call = get_parse_tree('_qpy_xml("X")').body
  113. xml_quote_call.args[0] = child
  114. node.right = xml_quote_call
  115. elif node_type == 'Call':
  116. for j, arg in enumerate(node.args):
  117. if get_node_type(arg) == 'Str':
  118. xml_quote_call = get_parse_tree('_qpy_xml("X")').body
  119. xml_quote_call.args[0] = arg
  120. node.args[j] = xml_quote_call
  121. elif node_type == 'BinOp':
  122. for j, arg in enumerate(node.args):
  123. if get_node_type(arg) == 'Str':
  124. xml_quote_call = get_parse_tree('_qpy_xml("X")').body
  125. xml_quote_call.args[0] = arg
  126. node.args[j] = xml_quote_call
  127. elif node_type == 'Dict':
  128. for j, arg in enumerate(node.keys):
  129. if get_node_type(arg) == 'Str':
  130. xml_quote_call = get_parse_tree('_qpy_xml("X")').body
  131. xml_quote_call.args[0] = arg
  132. node.keys[j] = xml_quote_call
  133. for j, arg in enumerate(node.values):
  134. if get_node_type(arg) == 'Str':
  135. xml_quote_call = get_parse_tree('_qpy_xml("X")').body
  136. xml_quote_call.args[0] = arg
  137. node.values[j] = xml_quote_call
  138. elif node_type in ('List', 'Tuple'):
  139. for j, arg in enumerate(node.elts):
  140. if get_node_type(arg) == 'Str':
  141. xml_quote_call = get_parse_tree('_qpy_xml("X")').body
  142. xml_quote_call.args[0] = arg
  143. node.elts[j] = xml_quote_call
  144. else:
  145. print type(node)
  146. ptree(node)
  147. assert 0
  148. self.traverse_node(child)
  149. if node_type == 'Module':
  150. for index, child in enumerate(children(node)):
  151. child_type = get_node_type(child)
  152. if index == 0 and child_type == 'Expr' and get_node_type(child.value) == 'Str':
  153. continue
  154. if child_type == 'ImportFrom' and child.module == '__future__':
  155. continue
  156. module_start = get_parse_tree(
  157. 'from qpy.quoted import join_xml as _qpy_join_xml, '
  158. 'join_str as _qpy_join_str, xml as _qpy_xml', 'fake').body[0]
  159. node.body.insert(index, module_start)
  160. break
  161. elif self.template_type_stack[-1] is None:
  162. pass # We're not in a template, so we're done.
  163. elif node_type == 'Expr':
  164. # Wrap this expression statement in a qpy_append call.
  165. new_expr = get_parse_tree('qpy_append(X)', 'fake').body[0]
  166. new_expr.value.args[0] = node.value
  167. node.value = new_expr.value
  168. elif node_type == "FunctionDef":
  169. node.name = node.name[:-16]
  170. template_start = get_parse_tree('qpy_accumulation=[];qpy_append=qpy_accumulation.append', 'fake').body
  171. node.body.insert(0, template_start[0])
  172. node.body.insert(1, template_start[1])
  173. if self.template_type_stack[-1] == 'xml':
  174. template_end = get_parse_tree('return _qpy_join_xml(qpy_accumulation)', 'fake').body[0]
  175. else:
  176. template_end = get_parse_tree('return _qpy_join_str(qpy_accumulation)', 'fake').body[0]
  177. node.body.append(template_end)
  178. if node_type == 'FunctionDef':
  179. self.template_type_stack.pop()
  180. def get_result(self):
  181. return self.tree
  182. PYC = "$py.class"
  183. def get_code(source, source_name):
  184. translated_source = translate_tokens(source)
  185. node = get_parse_tree(translated_source, source_name)
  186. transformed = Transform(node).get_result()
  187. code = ByteArrayOutputStream()
  188. transformed = node
  189. Module.compile(transformed, code, source_name +"$py", source_name, True, False, None, imp.NO_MTIME)
  190. return code
  191. def compile(source_name):
  192. source = open(source_name).read()
  193. code = get_code(source, source_name)
  194. class_file_name = splitext(source_name)[0] + PYC
  195. class_file = open(class_file_name, 'wb')
  196. class_file.write(code.toByteArray())
  197. class_file.close()
  198. if __name__ == '__main__':
  199. import qpy.__main__