def test_func_transform(self): options = CompilationOptions(default_options, ctypes=True) context = options.create_context() t = self.run_pipeline([NormalizeTree(self), ExternDefTransform(context)], u"""\ cdef extern from "stdio.h": int printf(char *, int *)\ """) print self.codeToString(t) self.assertEquals(self.codeToString(t), """\ with (cython.ctypes_extern)('stdio.h'): printf = (cython.ctypes_func)('printf','c',ctypes.c_int,ctypes.POINTER(ctypes.c_char),ctypes.POINTER(ctypes.c_int))\ """)
def extract(path, **kwargs): name = os.path.splitext(os.path.relpath(path))[0].replace('/', '.') options = CompilationOptions() options.include_path.append('include') options.language_level = 2 options.compiler_directives = dict( c_string_type='str', c_string_encoding='ascii', ) context = options.create_context() tree = parse_from_strings(name, open(path).read().decode('utf8'), context, **kwargs) extractor = Visitor({'file': path}) extractor.visit(tree) return extractor.events
def extract(path, **kwargs): name = os.path.splitext(os.path.relpath(path))[0].replace("/", ".") options = CompilationOptions() options.include_path.append("include") options.language_level = 2 options.compiler_directives = dict(c_string_type="str", c_string_encoding="ascii") context = options.create_context() tree = parse_from_strings( name, open(path).read(), context, level="module_pxd" if path.endswith(".pxd") else None, **kwargs) extractor = Visitor({"file": path}) extractor.visit(tree) return extractor.events
def cythonize(module_list, exclude=[], nthreads=0, aliases=None, quiet=False, force=False, exclude_failures=False, **options): """ Compile a set of source modules into C/C++ files and return a list of distutils Extension objects for them. As module list, pass either a glob pattern, a list of glob patterns or a list of Extension objects. The latter allows you to configure the extensions separately through the normal distutils options. When using glob patterns, you can exclude certain module names explicitly by passing them into the 'exclude' option. For parallel compilation, set the 'nthreads' option to the number of concurrent builds. For a broad 'try to compile' mode that ignores compilation failures and simply excludes the failed extensions, pass 'exclude_failures=True'. Note that this only really makes sense for compiling .py files which can also be used without compilation. Additional compilation options can be passed as keyword arguments. """ if 'include_path' not in options: options['include_path'] = ['.'] if 'common_utility_include_dir' in options: if options.get('cache'): raise NotImplementedError("common_utility_include_dir does not yet work with caching") if not os.path.exists(options['common_utility_include_dir']): os.makedirs(options['common_utility_include_dir']) c_options = CompilationOptions(**options) cpp_options = CompilationOptions(**options); cpp_options.cplus = True ctx = c_options.create_context() options = c_options module_list = create_extension_list( module_list, exclude=exclude, ctx=ctx, quiet=quiet, exclude_failures=exclude_failures, aliases=aliases) deps = create_dependency_tree(ctx, quiet=quiet) build_dir = getattr(options, 'build_dir', None) modules_by_cfile = {} to_compile = [] for m in module_list: if build_dir: root = os.path.realpath(os.path.abspath(find_root_package_dir(m.sources[0]))) def copy_to_build_dir(filepath, root=root): filepath_abs = os.path.realpath(os.path.abspath(filepath)) if os.path.isabs(filepath): filepath = filepath_abs if filepath_abs.startswith(root): mod_dir = os.path.join(build_dir, os.path.dirname(_relpath(filepath, root))) if not os.path.isdir(mod_dir): os.makedirs(mod_dir) shutil.copy(filepath, mod_dir) for dep in m.depends: copy_to_build_dir(dep) new_sources = [] for source in m.sources: base, ext = os.path.splitext(source) if ext in ('.pyx', '.py'): if m.language == 'c++': c_file = base + '.cpp' options = cpp_options else: c_file = base + '.c' options = c_options # setup for out of place build directory if enabled if build_dir: c_file = os.path.join(build_dir, c_file) dir = os.path.dirname(c_file) if not os.path.isdir(dir): os.makedirs(dir) if os.path.exists(c_file): c_timestamp = os.path.getmtime(c_file) else: c_timestamp = -1 # Priority goes first to modified files, second to direct # dependents, and finally to indirect dependents. if c_timestamp < deps.timestamp(source): dep_timestamp, dep = deps.timestamp(source), source priority = 0 else: dep_timestamp, dep = deps.newest_dependency(source) priority = 2 - (dep in deps.immediate_dependencies(source)) if force or c_timestamp < dep_timestamp: if not quiet: if source == dep: print("Compiling %s because it changed." % source) else: print("Compiling %s because it depends on %s." % (source, dep)) if not force and hasattr(options, 'cache'): extra = m.language fingerprint = deps.transitive_fingerprint(source, extra) else: fingerprint = None to_compile.append((priority, source, c_file, fingerprint, quiet, options, not exclude_failures)) new_sources.append(c_file) if c_file not in modules_by_cfile: modules_by_cfile[c_file] = [m] else: modules_by_cfile[c_file].append(m) else: new_sources.append(source) if build_dir: copy_to_build_dir(source) m.sources = new_sources if hasattr(options, 'cache'): if not os.path.exists(options.cache): os.makedirs(options.cache) to_compile.sort() if nthreads: # Requires multiprocessing (or Python >= 2.6) try: import multiprocessing pool = multiprocessing.Pool(nthreads) except (ImportError, OSError): print("multiprocessing required for parallel cythonization") nthreads = 0 else: try: pool.map(cythonize_one_helper, to_compile) finally: pool.close() if not nthreads: for args in to_compile: cythonize_one(*args[1:]) if exclude_failures: failed_modules = set() for c_file, modules in modules_by_cfile.iteritems(): if not os.path.exists(c_file): failed_modules.update(modules) elif os.path.getsize(c_file) < 200: f = io_open(c_file, 'r', encoding='iso8859-1') try: if f.read(len('#error ')) == '#error ': # dead compilation result failed_modules.update(modules) finally: f.close() if failed_modules: for module in failed_modules: module_list.remove(module) print("Failed compilations: %s" % ', '.join(sorted([ module.name for module in failed_modules]))) if hasattr(options, 'cache'): cleanup_cache(options.cache, getattr(options, 'cache_size', 1024 * 1024 * 100)) # cythonize() is often followed by the (non-Python-buffered) # compiler output, flush now to avoid interleaving output. sys.stdout.flush() return module_list
def cythonize(module_list, exclude=[], nthreads=0, aliases=None, quiet=False, force=False, exclude_failures=False, **options): """ Compile a set of source modules into C/C++ files and return a list of distutils Extension objects for them. As module list, pass either a glob pattern, a list of glob patterns or a list of Extension objects. The latter allows you to configure the extensions separately through the normal distutils options. When using glob patterns, you can exclude certain module names explicitly by passing them into the 'exclude' option. For parallel compilation, set the 'nthreads' option to the number of concurrent builds. For a broad 'try to compile' mode that ignores compilation failures and simply excludes the failed extensions, pass 'exclude_failures=True'. Note that this only really makes sense for compiling .py files which can also be used without compilation. Additional compilation options can be passed as keyword arguments. """ if 'include_path' not in options: options['include_path'] = ['.'] if 'common_utility_include_dir' in options: if options.get('cache'): raise NotImplementedError, "common_utility_include_dir does not yet work with caching" if not os.path.exists(options['common_utility_include_dir']): os.makedirs(options['common_utility_include_dir']) c_options = CompilationOptions(**options) cpp_options = CompilationOptions(**options) cpp_options.cplus = True ctx = c_options.create_context() options = c_options module_list = create_extension_list(module_list, exclude=exclude, ctx=ctx, quiet=quiet, exclude_failures=exclude_failures, aliases=aliases) deps = create_dependency_tree(ctx, quiet=quiet) build_dir = getattr(options, 'build_dir', None) modules_by_cfile = {} to_compile = [] for m in module_list: if build_dir: root = os.path.realpath( os.path.abspath(find_root_package_dir(m.sources[0]))) def copy_to_build_dir(filepath, root=root): filepath_abs = os.path.realpath(os.path.abspath(filepath)) if os.path.isabs(filepath): filepath = filepath_abs if filepath_abs.startswith(root): mod_dir = os.path.join( build_dir, os.path.dirname(_relpath(filepath, root))) if not os.path.isdir(mod_dir): os.makedirs(mod_dir) shutil.copy(filepath, mod_dir) for dep in m.depends: copy_to_build_dir(dep) new_sources = [] for source in m.sources: base, ext = os.path.splitext(source) if ext in ('.pyx', '.py'): if m.language == 'c++': c_file = base + '.cpp' options = cpp_options else: c_file = base + '.c' options = c_options # setup for out of place build directory if enabled if build_dir: c_file = os.path.join(build_dir, c_file) dir = os.path.dirname(c_file) if not os.path.isdir(dir): os.makedirs(dir) if os.path.exists(c_file): c_timestamp = os.path.getmtime(c_file) else: c_timestamp = -1 # Priority goes first to modified files, second to direct # dependents, and finally to indirect dependents. if c_timestamp < deps.timestamp(source): dep_timestamp, dep = deps.timestamp(source), source priority = 0 else: dep_timestamp, dep = deps.newest_dependency(source) priority = 2 - (dep in deps.immediate_dependencies(source)) if force or c_timestamp < dep_timestamp: if not quiet: if source == dep: print("Compiling %s because it changed." % source) else: print("Compiling %s because it depends on %s." % (source, dep)) if not force and hasattr(options, 'cache'): extra = m.language fingerprint = deps.transitive_fingerprint( source, extra) else: fingerprint = None to_compile.append((priority, source, c_file, fingerprint, quiet, options, not exclude_failures)) new_sources.append(c_file) if c_file not in modules_by_cfile: modules_by_cfile[c_file] = [m] else: modules_by_cfile[c_file].append(m) else: new_sources.append(source) if build_dir: copy_to_build_dir(source) m.sources = new_sources if hasattr(options, 'cache'): if not os.path.exists(options.cache): os.makedirs(options.cache) to_compile.sort() if nthreads: # Requires multiprocessing (or Python >= 2.6) try: import multiprocessing pool = multiprocessing.Pool(nthreads) except (ImportError, OSError): print("multiprocessing required for parallel cythonization") nthreads = 0 else: pool.map(cythonize_one_helper, to_compile) if not nthreads: for args in to_compile: cythonize_one(*args[1:]) if exclude_failures: failed_modules = set() for c_file, modules in modules_by_cfile.iteritems(): if not os.path.exists(c_file): failed_modules.update(modules) elif os.path.getsize(c_file) < 200: f = io_open(c_file, 'r', encoding='iso8859-1') try: if f.read(len('#error ')) == '#error ': # dead compilation result failed_modules.update(modules) finally: f.close() if failed_modules: for module in failed_modules: module_list.remove(module) print("Failed compilations: %s" % ', '.join(sorted([module.name for module in failed_modules]))) if hasattr(options, 'cache'): cleanup_cache(options.cache, getattr(options, 'cache_size', 1024 * 1024 * 100)) # cythonize() is often followed by the (non-Python-buffered) # compiler output, flush now to avoid interleaving output. sys.stdout.flush() return module_list
def cythonize(module_list, exclude=[], nthreads=0, aliases=None, quiet=False, **options): if 'include_path' not in options: options['include_path'] = ['.'] c_options = CompilationOptions(**options) cpp_options = CompilationOptions(**options); cpp_options.cplus = True ctx = c_options.create_context() module_list = create_extension_list( module_list, exclude=exclude, ctx=ctx, aliases=aliases) deps = create_dependency_tree(ctx) to_compile = [] for m in module_list: new_sources = [] for source in m.sources: base, ext = os.path.splitext(source) if ext in ('.pyx', '.py'): if m.language == 'c++': c_file = base + '.cpp' options = cpp_options else: c_file = base + '.c' options = c_options if os.path.exists(c_file): c_timestamp = os.path.getmtime(c_file) else: c_timestamp = -1 # Priority goes first to modified files, second to direct # dependents, and finally to indirect dependents. if c_timestamp < deps.timestamp(source): dep_timestamp, dep = deps.timestamp(source), source priority = 0 else: dep_timestamp, dep = deps.newest_dependency(source) priority = 2 - (dep in deps.immediate_dependencies(source)) if c_timestamp < dep_timestamp: if not quiet: if source == dep: print("Compiling %s because it changed." % source) else: print("Compiling %s because it depends on %s." % (source, dep)) to_compile.append((priority, source, c_file, options)) new_sources.append(c_file) else: new_sources.append(source) m.sources = new_sources to_compile.sort() if nthreads: # Requires multiprocessing (or Python >= 2.6) try: import multiprocessing pool = multiprocessing.Pool(nthreads) pool.map(cythonize_one_helper, to_compile) except ImportError: print("multiprocessing required for parallel cythonization") nthreads = 0 if not nthreads: for priority, pyx_file, c_file, options in to_compile: cythonize_one(pyx_file, c_file, options) return module_list
from Cython.Compiler.Main import compile_single, CompilationOptions from Cython.Compiler.TreeFragment import parse_from_strings from Cython.Compiler.Visitor import TreeVisitor from Cython.Compiler import Nodes from Cython.Compiler.AutoDocTransforms import EmbedSignature options = CompilationOptions() options.include_path.append('include') options.language_level = 2 options.compiler_directives = dict( c_string_type='str', c_string_encoding='ascii', ) ctx = options.create_context() tree = parse_from_strings('include.libavutil.avutil', open('scratchpad/test.pxd').read().decode('utf8'), ctx) class Visitor(TreeVisitor): def __init__(self, state=None): super(Visitor, self).__init__() self.state = dict(state or {}) self.events = [] def record_event(self, node, **kw): state = self.state.copy() state.update(**kw) state['pos'] = node.pos
def cythonize(module_list, exclude=[], nthreads=0, aliases=None, quiet=False, force=False, **options): if 'include_path' not in options: options['include_path'] = ['.'] c_options = CompilationOptions(**options) cpp_options = CompilationOptions(**options) cpp_options.cplus = True ctx = c_options.create_context() module_list = create_extension_list(module_list, exclude=exclude, ctx=ctx, aliases=aliases) deps = create_dependency_tree(ctx) to_compile = [] for m in module_list: new_sources = [] for source in m.sources: base, ext = os.path.splitext(source) if ext in ('.pyx', '.py'): if m.language == 'c++': c_file = base + '.cpp' options = cpp_options else: c_file = base + '.c' options = c_options if os.path.exists(c_file): c_timestamp = os.path.getmtime(c_file) else: c_timestamp = -1 # Priority goes first to modified files, second to direct # dependents, and finally to indirect dependents. if c_timestamp < deps.timestamp(source): dep_timestamp, dep = deps.timestamp(source), source priority = 0 else: dep_timestamp, dep = deps.newest_dependency(source) priority = 2 - (dep in deps.immediate_dependencies(source)) if force or c_timestamp < dep_timestamp: if not quiet: if source == dep: print("Compiling %s because it changed." % source) else: print("Compiling %s because it depends on %s." % (source, dep)) to_compile.append((priority, source, c_file, options)) new_sources.append(c_file) else: new_sources.append(source) m.sources = new_sources to_compile.sort() if nthreads: # Requires multiprocessing (or Python >= 2.6) try: import multiprocessing pool = multiprocessing.Pool(nthreads) pool.map(cythonize_one_helper, to_compile) except ImportError: print("multiprocessing required for parallel cythonization") nthreads = 0 if not nthreads: for priority, pyx_file, c_file, options in to_compile: cythonize_one(pyx_file, c_file, quiet, options) return module_list
def cythonize(module_list, exclude=[], nthreads=0, aliases=None, quiet=False, force=False, exclude_failures=False, **options): """ Compile a set of source modules into C/C++ files and return a list of distutils Extension objects for them. As module list, pass either a glob pattern, a list of glob patterns or a list of Extension objects. The latter allows you to configure the extensions separately through the normal distutils options. When using glob patterns, you can exclude certain module names explicitly by passing them into the 'exclude' option. For parallel compilation, set the 'nthreads' option to the number of concurrent builds. For a broad 'try to compile' mode that ignores compilation failures and simply excludes the failed extensions, pass 'exclude_failures=True'. Note that this only really makes sense for compiling .py files which can also be used without compilation. Additional compilation options can be passed as keyword arguments. """ if 'include_path' not in options: options['include_path'] = ['.'] c_options = CompilationOptions(**options) cpp_options = CompilationOptions(**options) cpp_options.cplus = True ctx = c_options.create_context() module_list = create_extension_list(module_list, exclude=exclude, ctx=ctx, quiet=quiet, exclude_failures=exclude_failures, aliases=aliases) deps = create_dependency_tree(ctx, quiet=quiet) modules_by_cfile = {} to_compile = [] for m in module_list: new_sources = [] for source in m.sources: base, ext = os.path.splitext(source) if ext in ('.pyx', '.py'): if m.language == 'c++': c_file = base + '.cpp' options = cpp_options else: c_file = base + '.c' options = c_options if os.path.exists(c_file): c_timestamp = os.path.getmtime(c_file) else: c_timestamp = -1 # Priority goes first to modified files, second to direct # dependents, and finally to indirect dependents. if c_timestamp < deps.timestamp(source): dep_timestamp, dep = deps.timestamp(source), source priority = 0 else: dep_timestamp, dep = deps.newest_dependency(source) priority = 2 - (dep in deps.immediate_dependencies(source)) if force or c_timestamp < dep_timestamp: if not quiet: if source == dep: print("Compiling %s because it changed." % source) else: print("Compiling %s because it depends on %s." % (source, dep)) if not force and hasattr(options, 'cache'): extra = m.language fingerprint = deps.transitive_fingerprint( source, extra) else: fingerprint = None to_compile.append((priority, source, c_file, fingerprint, quiet, options, not exclude_failures)) new_sources.append(c_file) if c_file not in modules_by_cfile: modules_by_cfile[c_file] = [m] else: modules_by_cfile[c_file].append(m) else: new_sources.append(source) m.sources = new_sources if hasattr(options, 'cache'): if not os.path.exists(options.cache): os.mkdir(options.cache) to_compile.sort() if nthreads: # Requires multiprocessing (or Python >= 2.6) try: import multiprocessing pool = multiprocessing.Pool(nthreads) pool.map(cythonize_one_helper, to_compile) except ImportError: print("multiprocessing required for parallel cythonization") nthreads = 0 if not nthreads: for args in to_compile: cythonize_one(*args[1:]) if exclude_failures: failed_modules = set() for c_file, modules in modules_by_cfile.iteritems(): if not os.path.exists(c_file): failed_modules.update(modules) for module in failed_modules: module_list.remove(module) if hasattr(options, 'cache'): cleanup_cache(options.cache, getattr(options, 'cache_size', 1024 * 1024 * 100)) # cythonize() is often followed by the (non-Python-buffered) # compiler output, flush now to avoid interleaving output. sys.stdout.flush() return module_list
from Cython.Compiler.Main import compile_single, CompilationOptions from Cython.Compiler.TreeFragment import parse_from_strings from Cython.Compiler.Visitor import TreeVisitor from Cython.Compiler import Nodes from Cython.Compiler.AutoDocTransforms import EmbedSignature options = CompilationOptions() options.include_path.append('include') options.language_level = 2 options.compiler_directives = dict( c_string_type='str', c_string_encoding='ascii', ) ctx = options.create_context() tree = parse_from_strings('include.libavutil.avutil', open('scratchpad/test.pxd').read().decode('utf8'), ctx) class Visitor(TreeVisitor): def __init__(self, state=None): super(Visitor, self).__init__() self.state = dict(state or {}) self.events = [] def record_event(self, node, **kw): state = self.state.copy() state.update(**kw) state['pos'] = node.pos state['end_pos'] = node.end_pos() self.events.append(state)
def cythonize(module_list, exclude=[], nthreads=0, aliases=None, quiet=False, force=False, exclude_failures=False, **options): """ Compile a set of source modules into C/C++ files and return a list of distutils Extension objects for them. As module list, pass either a glob pattern, a list of glob patterns or a list of Extension objects. The latter allows you to configure the extensions separately through the normal distutils options. When using glob patterns, you can exclude certain module names explicitly by passing them into the 'exclude' option. For parallel compilation, set the 'nthreads' option to the number of concurrent builds. For a broad 'try to compile' mode that ignores compilation failures and simply excludes the failed extensions, pass 'exclude_failures=True'. Note that this only really makes sense for compiling .py files which can also be used without compilation. Additional compilation options can be passed as keyword arguments. """ if 'include_path' not in options: options['include_path'] = ['.'] c_options = CompilationOptions(**options) cpp_options = CompilationOptions(**options); cpp_options.cplus = True ctx = c_options.create_context() module_list = create_extension_list( module_list, exclude=exclude, ctx=ctx, quiet=quiet, exclude_failures=exclude_failures, aliases=aliases) deps = create_dependency_tree(ctx, quiet=quiet) modules_by_cfile = {} to_compile = [] for m in module_list: new_sources = [] for source in m.sources: base, ext = os.path.splitext(source) if ext in ('.pyx', '.py'): if m.language == 'c++': c_file = base + '.cpp' options = cpp_options else: c_file = base + '.c' options = c_options if os.path.exists(c_file): c_timestamp = os.path.getmtime(c_file) else: c_timestamp = -1 # Priority goes first to modified files, second to direct # dependents, and finally to indirect dependents. if c_timestamp < deps.timestamp(source): dep_timestamp, dep = deps.timestamp(source), source priority = 0 else: dep_timestamp, dep = deps.newest_dependency(source) priority = 2 - (dep in deps.immediate_dependencies(source)) if force or c_timestamp < dep_timestamp: if not quiet: if source == dep: print("Compiling %s because it changed." % source) else: print("Compiling %s because it depends on %s." % (source, dep)) if not force and hasattr(options, 'cache'): extra = m.language fingerprint = deps.transitive_fingerprint(source, extra) else: fingerprint = None to_compile.append((priority, source, c_file, fingerprint, quiet, options, not exclude_failures)) new_sources.append(c_file) if c_file not in modules_by_cfile: modules_by_cfile[c_file] = [m] else: modules_by_cfile[c_file].append(m) else: new_sources.append(source) m.sources = new_sources if hasattr(options, 'cache'): if not os.path.exists(options.cache): os.mkdir(options.cache) to_compile.sort() if nthreads: # Requires multiprocessing (or Python >= 2.6) try: import multiprocessing pool = multiprocessing.Pool(nthreads) pool.map(cythonize_one_helper, to_compile) except ImportError: print("multiprocessing required for parallel cythonization") nthreads = 0 if not nthreads: for args in to_compile: cythonize_one(*args[1:]) if exclude_failures: failed_modules = set() for c_file, modules in modules_by_cfile.iteritems(): if not os.path.exists(c_file): failed_modules.update(modules) for module in failed_modules: module_list.remove(module) if hasattr(options, 'cache'): cleanup_cache(options.cache, getattr(options, 'cache_size', 1024 * 1024 * 100)) return module_list