extension.erp5.PythonScriptParserUtility.py 2.77 KB
Newer Older
Yusei Tahara's avatar
Yusei Tahara committed
1 2 3 4 5 6 7 8 9 10 11 12 13
import compiler
import compiler.ast
import compiler.visitor


class Visitor(compiler.visitor.ASTVisitor):

  def __init__(self, func_name):
    self.func_name = func_name
    compiler.visitor.ASTVisitor.__init__(self)
    self.result = []

  def visitCallFunc(self, node, *args):
Yusei Tahara's avatar
Yusei Tahara committed
14 15 16 17 18 19
    if ((isinstance(node.node, compiler.ast.Name) and
         node.node.name==self.func_name)
        or
        (isinstance(node.node, compiler.ast.Getattr) and
         node.node.attrname==self.func_name)
        ):
Yusei Tahara's avatar
Yusei Tahara committed
20 21 22 23 24 25 26 27
      arg = node.args[0]
      value = None
      if isinstance(arg, compiler.ast.Const):
        value = arg.value
      elif isinstance(arg, compiler.ast.Add):
        value = concatenate_add_const_value(arg)
      if value is not None:
        self.result.append(value)
Yusei Tahara's avatar
Yusei Tahara committed
28 29
    for child_node in node.args:
      self.preorder(child_node, self)
Yusei Tahara's avatar
Yusei Tahara committed
30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55


def concatenate_add_const_value(node):
  def iterate(nodes):
    if not nodes:
      return ''
    node = nodes[0]
    if isinstance(node, compiler.ast.Const):
      return node.value + iterate(nodes[1:])
    elif isinstance(node, compiler.ast.Add):
      if getattr(node, 'nodes', None):
        children_nodes = node.nodes
      else:
        children_nodes = (node.left, node.right)
      return iterate(children_nodes)+iterate(nodes[1:])
    elif isinstance(node, compiler.ast.Mod):
      # we can't handle Mod node statically.
      pass
  return iterate((node,))


def getFunctionFirstArgumentValue(func_name, source):
  ast = compiler.parse(source)
  visitor = Visitor(func_name)
  compiler.walk(ast, visitor)
  return visitor.result
Yusei Tahara's avatar
Yusei Tahara committed
56 57 58 59 60 61 62 63 64 65 66


#
# Collect translation message from products
#
import os.path
import Products.ERP5
def findMessageListFromPythonInProduct(function_name_list):
  product_dir = os.path.dirname(Products.ERP5.__path__[0])
  erp5_product_list = ('CMFActivity', 'CMFCategory',
                       'ERP5', 'ERP5Banking', 'ERP5Catalog', 'ERP5Configurator',
67
                       'ERP5Form', 'ERP5OOo', 'ERP5Security', 'ERP5VCS',
Yusei Tahara's avatar
Yusei Tahara committed
68 69
                       'ERP5SyncML', 'ERP5Type', 'ERP5Wizard', 'ERP5Workflow',
                       'HBTreeFolder2', 'MailTemplates', 'TimerService',
70
                       'ZMySQLDA', 'ZSQLCatalog',
Yusei Tahara's avatar
Yusei Tahara committed
71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86
                       )
  result = []
  def findStaticMessage(file_path):
    source = open(file_path).read()
    for func_name in function_name_list:
      call_func_name = '%s(' % func_name
      if call_func_name in source:
        for m in getFunctionFirstArgumentValue(func_name, source):
          result.append((m, file_path))
  def visit(arg, dirname, filename_list):
    for filename in filename_list:
      if filename.endswith('.py'):
        findStaticMessage(os.path.join(dirname, filename))
  for product_name in erp5_product_list:
    os.path.walk(os.path.join(product_dir, product_name), visit, None)
  return result