text: #!/usr/bin/env python
  # Copyright (C) 2011, Kees Bos <cornelis.bos@gmail.com>
  #
  # Licensed under the Apache License, Version 2.0 (the "License");
  # you may not use this file except in compliance with the License.
  # You may obtain a copy of the License at
  #
  #     http://www.apache.org/licenses/LICENSE-2.0
  #
  # Unless required by applicable law or agreed to in writing, software
  # distributed under the License is distributed on an "AS IS" BASIS,
  # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  # See the License for the specific language governing permissions and
  # limitations under the License.
  
  """Create imports for gwt to import from pyjamas instead of gwt"""
  
  import sys
  import os
  import compiler
  from compiler import ast
  
  
  class CreateImports(object):
      verbosity = 1
  
      def __init__(self, srcFile, dstFile, base_directory='.'):
          self.import_names = []
          self.import_lines = []
          self.srcFile = srcFile
          self.dstFile = dstFile
          parent, module = os.path.split(srcFile)
          self.srcModule = parent.split(os.sep)
          base_depth = len(base_directory.split(os.sep))
          self.srcModule = self.srcModule[base_depth:]
          if module.lower().endswith(".py"):
              module = module[:-3]
          if module != '__init__':
              self.srcModule.append(module)
  
      def log(self, logname, msg, lineno):
          if lineno is None:
              lineno = ''
          else:
              lineno = "(%s) " % lineno
          if self.srcFile:
              if lineno:
                  file = self.srcFile
              else:
                  file = '%s ' % self.srcFile
          else:
              file = ''
          sys.stderr.write("%(file)s%(lineno)s%(logname)s: %(msg)s\n" % locals())
  
      def error(self, msg, lineno=None):
          self.log('ERROR', msg, lineno)
  
      def warning(self, msg, lineno=None):
          self.log('WARNING', msg, lineno)
  
      def getImportNames(self, srcFile=None, import_names=None):
          savedSrcFile = self.srcFile
          if srcFile is None:
              srcFile = self.srcFile
          else:
              self.srcFile = srcFile
          if import_names is None:
              import_names = self.import_names
          skip = False
          try:
              nodes = compiler.parseFile(srcFile).getChildNodes()[0]
          except SyntaxError, e:
              self.warning("Skipping. Syntax error: %s" % e)
              skip = True
          except:
              exc = sys.exc_info()
              self.error("Parse error %s" % (exc, ))
              raise
          if not skip:
              dict_import_names = dict([(k, True) for k in import_names])
              for node in nodes:
                  ast_name = node.__class__.__name__
                  method = getattr(self, "ast%s" % ast_name, None)
                  if method is not None:
                      method(dict_import_names, node)
                  elif self.verbosity:
                      self.warning('Skipping %s' % ast_name, node.lineno)
              import_names[:] = dict_import_names.keys()
              import_names.sort()
              self.srcFile = savedSrcFile
          return import_names
  
      def addNames(self, import_names, node_names):
          for names in node_names:
              if isinstance(names, basestring):
                  name = names
              elif names[1] is None:
                  name = names[0]
              else:
                  name = names[1]
              import_names[name] = True
  
      def astImport(self, import_names, node):
          self.addNames(import_names, node.names)
  
      def astFrom(self, import_names, node):
          if not node.modname in [
              '__pyjamas__',
              '__javascript__',
          ]:
              self.addNames(import_names, node.names)
  
      def astAssign(self, import_names, node):
          for node in node.nodes:
              if node.flags == 'OP_ASSIGN':
                  import_names[node.name] = True
              else:
                  self.warning("Ignoring Assign %s" % node.flags, node.lineno)
  
      def astAssName(self, import_names, node):
          if node.flags == 'OP_DELETE':
              if node.name in import_names:
                  del(import_names[node.name])
          else:
              self.warning("Ignoring AssName %s" % node.flags, node.lineno)
  
      def astClass(self, import_names, node):
          import_names[node.name] = True
  
      def astFunction(self, import_names, node):
          import_names[node.name] = True
  
      def astGlobal(self, import_names, node):
          self.addNames(import_names, node.names)
  
      # Now all the completely ignored asts
      def astTryExcept(self, import_names, node):
          pass
  
      def astIf(self, import_names, node):
          pass
  
      def astPrintnl(self, import_names, node):
          pass
  
      def astDiscard(self, import_names, node):
          pass
  
      def createImportLines(self, base=None, import_names=None):
          if base is None:
              base = '.'.join(self.srcModule)
          if import_names is None:
              import_names = self.import_names
          lines = []
          lines.append('from %s import (' % base)
          for name in import_names:
              lines.append('    %s,' % name)
          lines.append(')')
          self.import_lines[:] = lines
          return lines
  
      def createDestination(self, dstFile=None, import_lines=None):
          if dstFile is None:
              dstFile = self.dstFile
          if import_lines is None:
              import_lines = self.import_lines
          try:
              oldData = open(dstFile, 'r').readlines()
          except IOError, e:
              if e[0] == 2: # No such file or directory
                  oldData = []
              else:
                  raise
          newData = []
          if len(import_lines) > 2:
              for line in import_lines:
                  newData.append("%s\n" % line)
          skip = False
          for line in oldData:
              sline = line.rstrip()
              if skip:
                  if sline == ')':
                      skip = False
                  continue
              if sline == import_lines[0]:
                  skip = True
                  continue
              newData.append(line)
          newData = "".join(newData)
          open(dstFile, 'w').write(newData)
  
  if __name__== '__main__':
      from optparse import OptionParser
      parser = OptionParser()
      parser.add_option(
          "--gwt",
          dest="gwt",
          default=False,
          action="store_true",
          help="Add all gwt imports to pyjamas",
      )
      parser.add_option(
          "--base-directory",
          dest="base_directory",
          default='.',
          help="Directory to search for files",
      )
      options, args = parser.parse_args()
      if options.gwt and len(args) > 0:
          raise ValueError("--gwt and arguments are mutually exclusive")
      if not options.gwt and len(args) == 0:
          raise ValueError("Missing src and dst file or --gwt")
      if not options.gwt:
          if len(args) != 2:
              raise ValueError("Too many arguments")
          srcFile = os.path.join(dirname, sys.argv[1])
          dstFile = os.path.join(dirname, sys.argv[2])
          ci = CreateImports(
              srcFile,
              dstFile,
              base_directory=options.base_directory,
          )
          ci.getImportNames()
          ci.createImportLines()
          ci.createDestination()
      else:
          gwtbase = os.path.join(options.base_directory, "gwt")
          pyjsbase = os.path.join(options.base_directory, "pyjamas")
          for dirname, subdirs, files in os.walk(gwtbase):
              if 'platform' in subdirs:
                  subdirs.remove('platform')
              for f in files:
                  if not f.lower().endswith(".py"):
                      continue
                  srcFile = os.path.join(dirname, f)
                  dstFile = srcFile.replace(gwtbase, pyjsbase)
                  ci = CreateImports(
                      srcFile,
                      dstFile,
                      base_directory=options.base_directory,
                  )
                  ci.getImportNames()
                  ci.createImportLines()
                  ci.createDestination()
  