Upstream version 9.38.198.0
[platform/framework/web/crosswalk.git] / src / third_party / cython / src / Cython / Build / Cythonize.py
1 #!/usr/bin/env python
2
3 import os
4 import shutil
5 import tempfile
6
7 from distutils.core import setup
8 from Cython.Build.Dependencies import cythonize, extended_iglob
9 from Cython.Utils import is_package_dir
10 from Cython.Compiler import Options
11
12 try:
13     import multiprocessing
14     parallel_compiles = int(multiprocessing.cpu_count() * 1.5)
15 except ImportError:
16     multiprocessing = None
17     parallel_compiles = 0
18
19
20 class _FakePool(object):
21     def map_async(self, func, args):
22         from itertools import imap
23         for _ in imap(func, args):
24             pass
25
26     def close(self): pass
27     def terminate(self): pass
28     def join(self): pass
29
30
31 def parse_directives(option, name, value, parser):
32     dest = option.dest
33     old_directives = dict(getattr(parser.values, dest,
34                                   Options.directive_defaults))
35     directives = Options.parse_directive_list(
36         value, relaxed_bool=True, current_settings=old_directives)
37     setattr(parser.values, dest, directives)
38
39
40 def parse_options(option, name, value, parser):
41     dest = option.dest
42     options = dict(getattr(parser.values, dest, {}))
43     for opt in value.split(','):
44         if '=' in opt:
45             n, v = opt.split('=', 1)
46             v = v.lower() not in ('false', 'f', '0', 'no')
47         else:
48             n, v = opt, True
49         options[n] = v
50     setattr(parser.values, dest, options)
51
52
53 def find_package_base(path):
54     base_dir, package_path = os.path.split(path)
55     while os.path.isfile(os.path.join(base_dir, '__init__.py')):
56         base_dir, parent = os.path.split(base_dir)
57         package_path = '%s/%s' % (parent, package_path)
58     return base_dir, package_path
59
60
61 def cython_compile(path_pattern, options):
62     pool = None
63     paths = map(os.path.abspath, extended_iglob(path_pattern))
64     try:
65         for path in paths:
66             if options.build_inplace:
67                 base_dir = path
68                 while not os.path.isdir(base_dir) or is_package_dir(base_dir):
69                     base_dir = os.path.dirname(base_dir)
70             else:
71                 base_dir = None
72
73             if os.path.isdir(path):
74                 # recursively compiling a package
75                 paths = [os.path.join(path, '**', '*.%s' % ext)
76                          for ext in ('py', 'pyx')]
77             else:
78                 # assume it's a file(-like thing)
79                 paths = [path]
80
81             ext_modules = cythonize(
82                 paths,
83                 nthreads=options.parallel,
84                 exclude_failures=options.keep_going,
85                 exclude=options.excludes,
86                 compiler_directives=options.directives,
87                 force=options.force,
88                 quiet=options.quiet,
89                 **options.options)
90
91             if ext_modules and options.build:
92                 if len(ext_modules) > 1 and options.parallel > 1:
93                     if pool is None:
94                         try:
95                             pool = multiprocessing.Pool(options.parallel)
96                         except OSError:
97                             pool = _FakePool()
98                     pool.map_async(run_distutils, [
99                         (base_dir, [ext]) for ext in ext_modules])
100                 else:
101                     run_distutils((base_dir, ext_modules))
102     except:
103         if pool is not None:
104             pool.terminate()
105         raise
106     else:
107         if pool is not None:
108             pool.close()
109             pool.join()
110
111
112 def run_distutils(args):
113     base_dir, ext_modules = args
114     script_args = ['build_ext', '-i']
115     cwd = os.getcwd()
116     temp_dir = None
117     try:
118         if base_dir:
119             os.chdir(base_dir)
120             temp_dir = tempfile.mkdtemp(dir=base_dir)
121             script_args.extend(['--build-temp', temp_dir])
122         setup(
123             script_name='setup.py',
124             script_args=script_args,
125             ext_modules=ext_modules,
126         )
127     finally:
128         if base_dir:
129             os.chdir(cwd)
130             if temp_dir and os.path.isdir(temp_dir):
131                 shutil.rmtree(temp_dir)
132
133
134 def parse_args(args):
135     from optparse import OptionParser
136     parser = OptionParser(usage='%prog [options] [sources and packages]+')
137
138     parser.add_option('-X', '--directive', metavar='NAME=VALUE,...', dest='directives',
139                       type=str, action='callback', callback=parse_directives, default={},
140                       help='set a compiler directive')
141     parser.add_option('-s', '--option', metavar='NAME=VALUE', dest='options',
142                       type=str, action='callback', callback=parse_options, default={},
143                       help='set a cythonize option')
144     parser.add_option('-3', dest='python3_mode', action='store_true',
145                       help='use Python 3 syntax mode by default')
146
147     parser.add_option('-x', '--exclude', metavar='PATTERN', dest='excludes',
148                       action='append', default=[],
149                       help='exclude certain file patterns from the compilation')
150
151     parser.add_option('-b', '--build', dest='build', action='store_true',
152                       help='build extension modules using distutils')
153     parser.add_option('-i', '--inplace', dest='build_inplace', action='store_true',
154                       help='build extension modules in place using distutils (implies -b)')
155     parser.add_option('-j', '--parallel', dest='parallel', metavar='N',
156                       type=int, default=parallel_compiles,
157                       help=('run builds in N parallel jobs (default: %d)' %
158                             parallel_compiles or 1))
159     parser.add_option('-f', '--force', dest='force', action='store_true',
160                       help='force recompilation')
161     parser.add_option('-q', '--quiet', dest='quiet', action='store_true',
162                       help='be less verbose during compilation')
163
164     parser.add_option('--lenient', dest='lenient', action='store_true',
165                       help='increase Python compatibility by ignoring some compile time errors')
166     parser.add_option('-k', '--keep-going', dest='keep_going', action='store_true',
167                       help='compile as much as possible, ignore compilation failures')
168
169     options, args = parser.parse_args(args)
170     if not args:
171         parser.error("no source files provided")
172     if options.build_inplace:
173         options.build = True
174     if multiprocessing is None:
175         options.parallel = 0
176     if options.python3_mode:
177         options.options['language_level'] = 3
178     return options, args
179
180
181 def main(args=None):
182     options, paths = parse_args(args)
183
184     if options.lenient:
185         # increase Python compatibility by ignoring compile time errors
186         Options.error_on_unknown_names = False
187         Options.error_on_uninitialized = False
188
189     for path in paths:
190         cython_compile(path, options)
191
192
193 if __name__ == '__main__':
194     main()