"""
A utility to build a Python extension module from C, wrapping distutils.
"""
import py

# set to true for automatic re-compilation of extensions
AUTOREGEN = False 

#  XXX we should distutils in a subprocess, because it messes up the
#      environment and who knows what else.  Currently we just save
#      and restore os.environ.

def make_module_from_c(cfile):
    import os, sys, imp
    from distutils.core import setup
    from distutils.extension import Extension
    debug = 0

    #try:
    #    from distutils.log import set_threshold
    #    set_threshold(10000)
    #except ImportError:
    #    print "ERROR IMPORTING"
    #    pass

    dirpath = cfile.dirpath()
    modname = cfile.purebasename

    # find the expected extension of the compiled C module
    for ext, mode, filetype in imp.get_suffixes():
        if filetype == imp.C_EXTENSION:
            break
    else:
        raise ImportError, "cannot find the file name suffix of C ext modules"
    lib = dirpath.join(modname+ext)

    # XXX argl! we need better "build"-locations alltogether!
    if lib.check() and AUTOREGEN and lib.stat().mtime < cfile.stat().mtime:
        try:
            lib.remove()
        except EnvironmentError:
            pass # XXX we just use the existing version, bah

    if not lib.check():
        c = py.io.StdCaptureFD()
        try:
            try:
                saved_environ = os.environ.items()
                try:
                    lastdir = dirpath.chdir()
                    try:
                        setup(
                          name = "pylibmodules",
                          ext_modules=[
                                Extension(modname, [str(cfile)])
                          ],
                          script_name = 'setup.py',
                          script_args = ['-q', 'build_ext', '--inplace']
                          #script_args = ['build_ext', '--inplace']
                        )
                    finally:
                        lastdir.chdir()
                finally:
                    for key, value in saved_environ:
                        if os.environ.get(key) != value:
                            os.environ[key] = value
            finally:
                foutput, foutput = c.done()
        except KeyboardInterrupt:
            raise
        except SystemExit, e:
            raise RuntimeError("cannot compile %s: %s\n%s" % (cfile, e,
                                                          foutput.read()))
    # XXX do we need to do some check on fout/ferr?
    # XXX not a nice way to import a module
    if debug:
        print "inserting path to sys.path", dirpath
    sys.path.insert(0, str(dirpath))
    if debug:
        print "import %(modname)s as testmodule" % locals()
    exec py.code.compile("import %(modname)s as testmodule" % locals())
    try:
        sys.path.remove(str(dirpath))
    except ValueError:
        pass

    return testmodule
