import os, sys
from distutils.command import build_py
from distutils.dep_util import newer
from distutils.errors import DistutilsExecError

class BuildPy(build_py.build_py):

    command_name = 'build_py'
    
    def finalize_options(self):
        build_py.build_py.finalize_options(self)

        self.config_filename = None
        if self.distribution.config_module:
            parts = self.distribution.config_module.split('.')
            self.config_filename = os.path.join(self.build_lib, *parts) + '.py'
        return

    def run(self):
        if sys.version < '2.3':
            if self.py_modules:
                self.build_modules()
            if self.packages:
                self.build_packages()
            self.byte_compile(self.get_outputs(include_bytecode=0))
        else:
            build_py.build_py.run(self)

        config = self.get_finalized_command('config')
        if (not self.dry_run and
            (self.config_filename and
             (self.force or
              newer(config.cache_filename, self.config_filename)))):
            # Create the configuration filename
            config.write_config_vars(self.config_filename)
        return

    def get_outputs(self, include_bytecode=1):
        outputs = build_py.build_py.get_outputs(self, include_bytecode)
        if self.config_filename:
            outputs.append(self.config_filename)
        return outputs

    def copy_file(self, src, dest, *args, **kwds):
        """
        Overridden to validate Python sources before copying them.
        """
        if src[-3:] == '.py':
            try:
                f = open(src, 'U')
            except:
                f = open(src, 'r')
                codestring = f.read()
                codestring = codestring.replace("\r\n", "\n")
                codestring = codestring.replace("\r", "\n")
            else:
                codestring = f.read()
            f.close()
            if codestring and codestring[-1] != '\n':
                codestring = codestring + '\n'
            try:
                compile(codestring, src, 'exec')
            except SyntaxError, detail:
                msg, (filename, lineno, offset, line) = detail
                if not filename: filename = src
                L = ['Syntax error in file "%s", line %d: %s' % (filename,
                                                                 lineno, msg)]
                if line is not None:
                    i = 0
                    while i < len(line) and line[i].isspace():
                        i = i+1
                    L.append('    %s' % line.strip())
                    if offset is not None:
                        s = '    '
                        for c in line[i:offset-1]:
                            if c.isspace():
                                s = s + c
                            else:
                                s = s + ' '
                        L.append('%s^' % s)
                raise DistutilsExecError('\n'.join(L))

        return build_py.build_py.copy_file(self, src, dest, *args, **kwds)
