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 |
+ |