#!/usr/bin/python
# Copyright 2016 The Chromium Authors. All rights reserved.
# Use of this source code is governed by a BSD-style license that can be
# found in the LICENSE file.

"""
 Converts a given ASCII proto into a binary resource.

"""

import abc
import imp
import optparse
import os
import re
import subprocess
import sys
import traceback


class GoogleProtobufModuleImporter:
  """A custom module importer for importing google.protobuf.

  See PEP #302 (https://www.python.org/dev/peps/pep-0302/) for full information
  on the Importer Protocol.
  """

  def __init__(self, paths):
    """Creates a loader that searches |paths| for google.protobuf modules."""
    self._paths = paths

  def _fullname_to_filepath(self, fullname):
    """Converts a full module name to a corresponding path to a .py file.

    e.g. google.protobuf.text_format -> pyproto/google/protobuf/text_format.py
    """
    for path in self._paths:
      filepath = os.path.join(path, fullname.replace('.', os.sep) + '.py')
      if os.path.isfile(filepath):
        return filepath
    return None

  def _module_exists(self, fullname):
    return self._fullname_to_filepath(fullname) is not None

  def find_module(self, fullname, path=None):
    """Returns a loader module for the google.protobuf module in pyproto."""
    if (fullname.startswith('google.protobuf.')
        and self._module_exists(fullname)):
      # Per PEP #302, this will result in self.load_module getting used
      # to load |fullname|.
      return self

    # Per PEP #302, if the module cannot be loaded, then return None.
    return None

  def load_module(self, fullname):
    """Loads the module specified by |fullname| and returns the module."""
    if fullname in sys.modules:
      # Per PEP #302, if |fullname| is in sys.modules, it must be returned.
      return sys.modules[fullname]

    if (not fullname.startswith('google.protobuf.') or
        not self._module_exists(fullname)):
      # Per PEP #302, raise ImportError if the requested module/package
      # cannot be loaded. This should never get reached for this simple loader,
      # but is included for completeness.
      raise ImportError(fullname)

    filepath = self._fullname_to_filepath(fullname)
    return imp.load_source(fullname, filepath)

class BinaryProtoGenerator:

  # If the script is run in a virtualenv
  # (https://virtualenv.pypa.io/en/stable/), then no google.protobuf library
  # should be brought in from site-packages. Passing -S into the interpreter in
  # a virtualenv actually destroys the ability to import standard library
  # functions like optparse, so this script should not be wrapped if we're in a
  # virtualenv.
  def _IsInVirtualEnv(self):
    # This is the way used by pip and other software to detect virtualenv.
    return hasattr(sys, 'real_prefix')

  def _ImportProtoModules(self, paths):
    """Import the protobuf modules we need. |paths| is list of import paths"""
    for path in paths:
      # Put the path to our proto libraries in front, so that we don't use
      # system protobuf.
      sys.path.insert(1, path)

    if self._IsInVirtualEnv():
      # Add a custom module loader. When run in a virtualenv that has
      # google.protobuf installed, the site-package was getting searched first
      # despite that pyproto/ is at the start of the sys.path. The module
      # loaders in the meta_path precede all other imports (including even
      # builtins), which allows the proper google.protobuf from pyproto to be
      # found.
      sys.meta_path.append(GoogleProtobufModuleImporter(paths))

    import google.protobuf.text_format as text_format
    globals()['text_format'] = text_format
    self.ImportProtoModule()

  def _GenerateBinaryProtos(self, opts):
    """ Read the ASCII proto and generate one or more binary protos. """
    # Read the ASCII
    with open(opts.infile, 'r') as ifile:
      ascii_pb_str = ifile.read()

    # Parse it into a structured PB
    full_pb = self.EmptyProtoInstance()
    text_format.Merge(ascii_pb_str, full_pb)

    self.ValidatePb(opts, full_pb);
    self.ProcessPb(opts, full_pb)

  @abc.abstractmethod
  def ImportProtoModule(self):
    """ Import the proto module to be used by the generator. """
    pass

  @abc.abstractmethod
  def EmptyProtoInstance(self):
    """ Returns an empty proto instance to be filled by the generator."""
    pass

  @abc.abstractmethod
  def ValidatePb(self, opts, pb):
    """ Validate the basic values of the protobuf.  The
        file_type_policies_unittest.cc will also validate it by platform,
        but this will catch errors earlier.
    """
    pass

  @abc.abstractmethod
  def ProcessPb(self, opts, pb):
    """ Process the parsed prototobuf. """
    pass

  def AddCommandLineOptions(self, parser):
    """ Allows subclasses to add any options the command line parser. """
    pass

  def AddExtraCommandLineArgsForVirtualEnvRun(self, opts, command):
    """ Allows subclasses to add any extra command line arguments when running
        this under a virtualenv."""
    pass

  def VerifyArgs(self, opts):
    """ Allows subclasses to check command line parameters before running. """
    return True

  def Run(self):
    parser = optparse.OptionParser()
    # TODO(crbug.com/614082): Remove this once the bug is fixed.
    parser.add_option('-w', '--wrap', action="store_true", default=False,
                      help='Wrap this script in another python '
                      'execution to disable site-packages.  This is a '
                      'fix for http://crbug.com/605592')

    parser.add_option('-i', '--infile',
                      help='The ASCII proto file to read.')
    parser.add_option('-d', '--outdir',
                      help='Directory underwhich binary file(s) will be ' +
                           'written')
    parser.add_option('-o', '--outbasename',
                      help='Basename of the binary file to write to.')
    parser.add_option('-p', '--path', action="append",
                      help='Repeat this as needed.  Directory(s) containing ' +
                      'the your_proto_definition_pb2.py and ' +
                      'google.protobuf.text_format modules')
    self.AddCommandLineOptions(parser)

    (opts, args) = parser.parse_args()
    if opts.infile is None or opts.outdir is None or opts.outbasename is None:
      parser.print_help()
      return 1

    if opts.wrap and not self._IsInVirtualEnv():
      # Run this script again with different args to the interpreter to suppress
      # the inclusion of libraries, like google.protobuf, from site-packages,
      # which is checked before sys.path when resolving imports. We want to
      # specifically import the libraries injected into the sys.path in
      # ImportProtoModules().
      command = [sys.executable, '-S', '-s', sys.argv[0]]
      command += ['-i', opts.infile]
      command += ['-d', opts.outdir]
      command += ['-o', opts.outbasename]
      for path in opts.path:
        command += ['-p', path]

      self.AddExtraCommandLineArgsForVirtualEnvRun(opts, command);
      sys.exit(subprocess.call(command))

    self._ImportProtoModules(opts.path)

    if not self.VerifyArgs(opts):
      print "Wrong arguments"
      return 1

    try:
      self._GenerateBinaryProtos(opts)
    except Exception as e:
      print "ERROR: Failed to render binary version of %s:\n  %s\n%s" % (
          opts.infile, str(e), traceback.format_exc())
      return 1
