import os, sys
from distutils import util
from distutils.command import install
from distutils.core import DEBUG

class Install(install.install):

    command_name = 'install'

    user_options = [
        # Byte-compilation options -- see install_lib.py for details, as
        # these are duplicated from there (but only install_lib does
        # anything with them).
        ('compile', 'c', "compile .py to .pyc [default]"),
        ('no-compile', None, "don't compile .py files"),
        ('optimize=', 'O',
         "also compile with optimization: -O1 for \"python -O\", "
         "-O2 for \"python -OO\", and -O0 to disable [default: -O0]"),

        # Miscellaneous control options
        ('force', 'f',
         "force installation (overwrite any existing files)"),
        ('skip-build', None,
         "skip rebuilding everything (for testing/debugging)"),

        ('with-docs', None, 'enable documentation build'),
        ('without-docs', None, 'disable documentation build [default]'),
        ]

    boolean_options = ['compile', 'force', 'skip-build', 'with-docs']

    negative_opt = {'no-compile' : 'compile',
                    'without-docs' : 'with-docs'}

    def initialize_options(self):
        self.install_lib = '$pythonlibdir'
        self.install_scripts = '$bindir'
        self.install_data = '$datadir'
        self.install_sysconf = '$sysconfdir'
        self.install_localstate = '$localstatedir'
        self.install_docs = '$docdir'
        self.install_tests = '$libdir'
        self.install_l10n = '$localedir'

        self.compile = None
        self.optimize = None

        # This sets the installation base (used by bdist commands)
        self.root = None

        # 'force' forces installation, even if target files are not
        # out-of-date.  'skip_build' skips running the "build" command,
        # handy if you know it's not necessary.  'warn_dir' (which is *not*
        # a user option, it's just there so the bdist_* commands can turn
        # it off) determines whether we warn about installing to a
        # directory not in sys.path.
        self.force = 0
        self.skip_build = 0
        self.warn_dir = 1

        # These are only here as a conduit from the 'build' command to the
        # 'install_*' commands that do the real work.  ('build_base' isn't
        # actually used anywhere, but it might be useful in future.)  They
        # are not user options, because if the user told the install
        # command where the build directory is, that wouldn't affect the
        # build command.
        self.build_base = None
        self.build_lib = None

        self.with_docs = None
        return

    def finalize_options(self):
        # Find out the build directories, ie. where to install from.
        self.set_undefined_options('build',
                                   ('build_base', 'build_base'),
                                   ('build_lib', 'build_lib'),
                                   ('with_docs', 'with_docs'))

        # Expand configuration variables, tilde, etc. in the installation
        # directories.
        config = self.get_finalized_command('config')
        config_vars = config.get_config_vars()

        for attr in ('install_lib',
                     'install_scripts',
                     'install_data',
                     'install_sysconf',
                     'install_localstate',
                     'install_docs',
                     'install_tests',
                     'install_l10n'):
            value = getattr(self, attr)
            value = util.convert_path(value)
            value = util.subst_vars(value, config_vars)
            if self.root is not None:
                value = util.change_root(self.root, value)
            setattr(self, attr, value)
        return

    def run(self):
        # Obviously have to build before we can install
        if not self.skip_build:
            self.run_command('build')

        # Run all sub-commands (at least those that need to be run)
        for cmd_name in self.get_sub_commands():
            self.run_command(cmd_name)

        sys_path = map(os.path.normpath, sys.path)
        sys_path = map(os.path.normcase, sys_path)
        libdir = os.path.normcase(os.path.normpath(self.install_lib))
        # FIXME: In a new interpreter, sys.path might include the
        # newly created libdir, in which case the warning here will
        # be bogus. This happens with Python 2.4 on Windows, which
        # does not have a site-packages dir until we create one
        # during the 4Suite install.
        if self.warn_dir and (libdir not in sys_path):
            self.warn(("modules installed to %r, which is not in "
                       "Python's module search path (sys.path) -- "
                       "you'll have to change the search path yourself") %
                      self.install_lib)
        return

    def get_source_files(self):
        files = []
        for cmd_name in self.get_sub_commands():
            cmd = self.get_finalized_command(cmd_name)
            files.extend(cmd.get_inputs())
        return files

    # -- Predicates for sub-command list -------------------------------

    def has_sysconf(self):
        return self.distribution.has_sysconf()

    def has_localstate(self):
        return self.distribution.has_localstate()

    def has_docs(self):
        return self.with_docs and self.distribution.has_docs()

    def has_tests(self):
        return self.distribution.has_tests()

    def has_l10n(self):
        return self.distribution.has_l10n()

    # a list of commands this command might have to run to do its work.
    sub_commands = install.install.sub_commands + [
        ('install_sysconf', has_sysconf),
        ('install_localstate', has_localstate),
        ('install_docs', has_docs),
        ('install_tests', has_tests),
        ('install_l10n', has_l10n),
        ]
