| Index: third_party/cython/src/pyximport/pyxbuild.py
|
| diff --git a/third_party/cython/src/pyximport/pyxbuild.py b/third_party/cython/src/pyximport/pyxbuild.py
|
| new file mode 100644
|
| index 0000000000000000000000000000000000000000..82401cdbc921dff5733d90aa42065d624811ce11
|
| --- /dev/null
|
| +++ b/third_party/cython/src/pyximport/pyxbuild.py
|
| @@ -0,0 +1,161 @@
|
| +"""Build a Pyrex file from .pyx source to .so loadable module using
|
| +the installed distutils infrastructure. Call:
|
| +
|
| +out_fname = pyx_to_dll("foo.pyx")
|
| +"""
|
| +import os
|
| +import sys
|
| +
|
| +from distutils.dist import Distribution
|
| +from distutils.errors import DistutilsArgError, DistutilsError, CCompilerError
|
| +from distutils.extension import Extension
|
| +from distutils.util import grok_environment_error
|
| +try:
|
| + from Cython.Distutils import build_ext
|
| + HAS_CYTHON = True
|
| +except ImportError:
|
| + HAS_CYTHON = False
|
| +
|
| +DEBUG = 0
|
| +
|
| +_reloads={}
|
| +
|
| +def pyx_to_dll(filename, ext = None, force_rebuild = 0,
|
| + build_in_temp=False, pyxbuild_dir=None, setup_args={},
|
| + reload_support=False, inplace=False):
|
| + """Compile a PYX file to a DLL and return the name of the generated .so
|
| + or .dll ."""
|
| + assert os.path.exists(filename), "Could not find %s" % os.path.abspath(filename)
|
| +
|
| + path, name = os.path.split(os.path.abspath(filename))
|
| +
|
| + if not ext:
|
| + modname, extension = os.path.splitext(name)
|
| + assert extension in (".pyx", ".py"), extension
|
| + if not HAS_CYTHON:
|
| + filename = filename[:-len(extension)] + '.c'
|
| + ext = Extension(name=modname, sources=[filename])
|
| +
|
| + if not pyxbuild_dir:
|
| + pyxbuild_dir = os.path.join(path, "_pyxbld")
|
| +
|
| + package_base_dir = path
|
| + for package_name in ext.name.split('.')[-2::-1]:
|
| + package_base_dir, pname = os.path.split(package_base_dir)
|
| + if pname != package_name:
|
| + # something is wrong - package path doesn't match file path
|
| + package_base_dir = None
|
| + break
|
| +
|
| + script_args=setup_args.get("script_args",[])
|
| + if DEBUG or "--verbose" in script_args:
|
| + quiet = "--verbose"
|
| + else:
|
| + quiet = "--quiet"
|
| + args = [quiet, "build_ext"]
|
| + if force_rebuild:
|
| + args.append("--force")
|
| + if inplace and package_base_dir:
|
| + args.extend(['--build-lib', package_base_dir])
|
| + if ext.name == '__init__' or ext.name.endswith('.__init__'):
|
| + # package => provide __path__ early
|
| + if not hasattr(ext, 'cython_directives'):
|
| + ext.cython_directives = {'set_initial_path' : 'SOURCEFILE'}
|
| + elif 'set_initial_path' not in ext.cython_directives:
|
| + ext.cython_directives['set_initial_path'] = 'SOURCEFILE'
|
| +
|
| + if HAS_CYTHON and build_in_temp:
|
| + args.append("--pyrex-c-in-temp")
|
| + sargs = setup_args.copy()
|
| + sargs.update(
|
| + {"script_name": None,
|
| + "script_args": args + script_args} )
|
| + dist = Distribution(sargs)
|
| + if not dist.ext_modules:
|
| + dist.ext_modules = []
|
| + dist.ext_modules.append(ext)
|
| + if HAS_CYTHON:
|
| + dist.cmdclass = {'build_ext': build_ext}
|
| + build = dist.get_command_obj('build')
|
| + build.build_base = pyxbuild_dir
|
| +
|
| + config_files = dist.find_config_files()
|
| + try: config_files.remove('setup.cfg')
|
| + except ValueError: pass
|
| + dist.parse_config_files(config_files)
|
| +
|
| + cfgfiles = dist.find_config_files()
|
| + try: cfgfiles.remove('setup.cfg')
|
| + except ValueError: pass
|
| + dist.parse_config_files(cfgfiles)
|
| + try:
|
| + ok = dist.parse_command_line()
|
| + except DistutilsArgError:
|
| + raise
|
| +
|
| + if DEBUG:
|
| + print("options (after parsing command line):")
|
| + dist.dump_option_dicts()
|
| + assert ok
|
| +
|
| +
|
| + try:
|
| + obj_build_ext = dist.get_command_obj("build_ext")
|
| + dist.run_commands()
|
| + so_path = obj_build_ext.get_outputs()[0]
|
| + if obj_build_ext.inplace:
|
| + # Python distutils get_outputs()[ returns a wrong so_path
|
| + # when --inplace ; see http://bugs.python.org/issue5977
|
| + # workaround:
|
| + so_path = os.path.join(os.path.dirname(filename),
|
| + os.path.basename(so_path))
|
| + if reload_support:
|
| + org_path = so_path
|
| + timestamp = os.path.getmtime(org_path)
|
| + global _reloads
|
| + last_timestamp, last_path, count = _reloads.get(org_path, (None,None,0) )
|
| + if last_timestamp == timestamp:
|
| + so_path = last_path
|
| + else:
|
| + basename = os.path.basename(org_path)
|
| + while count < 100:
|
| + count += 1
|
| + r_path = os.path.join(obj_build_ext.build_lib,
|
| + basename + '.reload%s'%count)
|
| + try:
|
| + import shutil # late import / reload_support is: debugging
|
| + try:
|
| + # Try to unlink first --- if the .so file
|
| + # is mmapped by another process,
|
| + # overwriting its contents corrupts the
|
| + # loaded image (on Linux) and crashes the
|
| + # other process. On Windows, unlinking an
|
| + # open file just fails.
|
| + if os.path.isfile(r_path):
|
| + os.unlink(r_path)
|
| + except OSError:
|
| + continue
|
| + shutil.copy2(org_path, r_path)
|
| + so_path = r_path
|
| + except IOError:
|
| + continue
|
| + break
|
| + else:
|
| + # used up all 100 slots
|
| + raise ImportError("reload count for %s reached maximum"%org_path)
|
| + _reloads[org_path]=(timestamp, so_path, count)
|
| + return so_path
|
| + except KeyboardInterrupt:
|
| + sys.exit(1)
|
| + except (IOError, os.error):
|
| + exc = sys.exc_info()[1]
|
| + error = grok_environment_error(exc)
|
| +
|
| + if DEBUG:
|
| + sys.stderr.write(error + "\n")
|
| + raise
|
| +
|
| +if __name__=="__main__":
|
| + pyx_to_dll("dummy.pyx")
|
| + import test
|
| +
|
|
|