fix function declarations inside of 'with' blocks
[cython.git] / setup.py
1 from distutils.core import setup, Extension
2 from distutils.sysconfig import get_python_lib
3 import os, os.path
4 import sys
5
6 if sys.platform == "darwin":
7     # Don't create resource files on OS X tar.
8     os.environ['COPY_EXTENDED_ATTRIBUTES_DISABLE'] = 'true'
9     os.environ['COPYFILE_DISABLE'] = 'true'
10
11 setup_args = {}
12
13 def add_command_class(name, cls):
14     cmdclasses = setup_args.get('cmdclass', {})
15     cmdclasses[name] = cls
16     setup_args['cmdclass'] = cmdclasses
17
18 from distutils.command.sdist import sdist as sdist_orig
19 class sdist(sdist_orig):
20     def run(self):
21         self.force_manifest = 1
22         if (sys.platform != "win32" and 
23             os.path.isdir('.git')):
24             assert os.system("git show-ref -s HEAD > .gitrev") == 0
25         sdist_orig.run(self)
26 add_command_class('sdist', sdist)
27
28 if sys.version_info[0] >= 3:
29     import lib2to3.refactor
30     from distutils.command.build_py \
31          import build_py_2to3 as build_py
32     # need to convert sources to Py3 on installation
33     fixers = [ fix for fix in lib2to3.refactor.get_fixers_from_package("lib2to3.fixes")
34                if fix.split('fix_')[-1] not in ('next',)
35                ]
36     build_py.fixer_names = fixers
37     add_command_class("build_py", build_py)
38
39 pxd_include_dirs = [
40     directory for directory, dirs, files in os.walk('Cython/Includes')
41     if '__init__.pyx' in files or '__init__.pxd' in files
42     or directory == 'Cython/Includes' or directory == 'Cython/Includes/Deprecated']
43
44 pxd_include_patterns = [
45     p+'/*.pxd' for p in pxd_include_dirs ] + [
46     p+'/*.pyx' for p in pxd_include_dirs ]
47
48 if sys.version_info < (2,4):
49     install_base_dir = get_python_lib(prefix='')
50     import glob
51     patterns = pxd_include_patterns + [
52         'Cython/Plex/*.pxd',
53         'Cython/Compiler/*.pxd',
54         'Cython/Runtime/*.pyx'
55         ]
56     setup_args['data_files'] = [
57         (os.path.dirname(os.path.join(install_base_dir, pattern)),
58          [ f for f in glob.glob(pattern) ])
59         for pattern in patterns
60         ]
61 else:
62     setup_args['package_data'] = {
63         'Cython.Plex'     : ['*.pxd'],
64         'Cython.Compiler' : ['*.pxd'],
65         'Cython.Runtime'  : ['*.pyx', '*.pxd'],
66         'Cython'          : [ p[7:] for p in pxd_include_patterns ],
67         }
68
69 # This dict is used for passing extra arguments that are setuptools
70 # specific to setup
71 setuptools_extra_args = {}
72
73 # tells whether to include cygdb (the script and the Cython.Debugger package
74 include_debugger = sys.version_info[:2] > (2, 5)
75
76 if 'setuptools' in sys.modules:
77     setuptools_extra_args['zip_safe'] = False
78     setuptools_extra_args['entry_points'] = {
79         'console_scripts': [
80             'cython = Cython.Compiler.Main:setuptools_main',
81         ]
82     }
83     scripts = []
84 else:
85     if os.name == "posix":
86         scripts = ["bin/cython"]
87         if include_debugger:
88             scripts.append('bin/cygdb')
89     else:
90         scripts = ["cython.py"]
91         if include_debugger:
92             scripts.append('cygdb.py')
93
94 def compile_cython_modules(profile=False, compile_more=False, cython_with_refnanny=False):
95     source_root = os.path.abspath(os.path.dirname(__file__))
96     compiled_modules = ["Cython.Plex.Scanners",
97                         "Cython.Plex.Actions",
98                         "Cython.Compiler.Lexicon",
99                         "Cython.Compiler.Scanning",
100                         "Cython.Compiler.Parsing",
101                         "Cython.Compiler.Visitor",
102                         "Cython.Compiler.Code",
103                         "Cython.Runtime.refnanny",]
104     if compile_more:
105         compiled_modules.extend([
106             "Cython.Compiler.ParseTreeTransforms",
107             "Cython.Compiler.Nodes",
108             "Cython.Compiler.ExprNodes",
109             "Cython.Compiler.ModuleNode",
110             "Cython.Compiler.Optimize",
111             ])
112
113     defines = []
114     if cython_with_refnanny:
115         defines.append(('CYTHON_REFNANNY', '1'))
116
117     extensions = []
118     if sys.version_info[0] >= 3:
119         from Cython.Distutils import build_ext as build_ext_orig
120         for module in compiled_modules:
121             source_file = os.path.join(source_root, *module.split('.'))
122             if os.path.exists(source_file + ".py"):
123                 pyx_source_file = source_file + ".py"
124             else:
125                 pyx_source_file = source_file + ".pyx"
126             dep_files = []
127             if os.path.exists(source_file + '.pxd'):
128                 dep_files.append(source_file + '.pxd')
129             if '.refnanny' in module:
130                 defines_for_module = []
131             else:
132                 defines_for_module = defines
133             extensions.append(
134                 Extension(module, sources = [pyx_source_file],
135                           define_macros = defines_for_module,
136                           depends = dep_files)
137                 )
138
139         class build_ext(build_ext_orig):
140             # we must keep the original modules alive to make sure
141             # their code keeps working when we remove them from
142             # sys.modules
143             dead_modules = []
144
145             def build_extensions(self):
146                 # add path where 2to3 installed the transformed sources
147                 # and make sure Python (re-)imports them from there
148                 already_imported = [ module for module in sys.modules
149                                      if module == 'Cython' or module.startswith('Cython.') ]
150                 keep_alive = self.dead_modules.append
151                 for module in already_imported:
152                     keep_alive(sys.modules[module])
153                     del sys.modules[module]
154                 sys.path.insert(0, os.path.join(source_root, self.build_lib))
155
156                 if profile:
157                     from Cython.Compiler.Options import directive_defaults
158                     directive_defaults['profile'] = True
159                     print("Enabled profiling for the Cython binary modules")
160                 build_ext_orig.build_extensions(self)
161
162         setup_args['ext_modules'] = extensions
163         add_command_class("build_ext", build_ext)
164
165     else: # Python 2.x
166         from distutils.command.build_ext import build_ext as build_ext_orig
167         try:
168             class build_ext(build_ext_orig):
169                 def build_extension(self, ext, *args, **kargs):
170                     try:
171                         build_ext_orig.build_extension(self, ext, *args, **kargs)
172                     except StandardError:
173                         print("Compilation of '%s' failed" % ext.sources[0])
174             from Cython.Compiler.Main import compile
175             from Cython import Utils
176             if profile:
177                 from Cython.Compiler.Options import directive_defaults
178                 directive_defaults['profile'] = True
179                 print("Enabled profiling for the Cython binary modules")
180             source_root = os.path.dirname(__file__)
181             for module in compiled_modules:
182                 source_file = os.path.join(source_root, *module.split('.'))
183                 if os.path.exists(source_file + ".py"):
184                     pyx_source_file = source_file + ".py"
185                 else:
186                     pyx_source_file = source_file + ".pyx"
187                 c_source_file = source_file + ".c"
188                 source_is_newer = False
189                 if not os.path.exists(c_source_file):
190                     source_is_newer = True
191                 else:
192                     c_last_modified = Utils.modification_time(c_source_file)
193                     if Utils.file_newer_than(pyx_source_file, c_last_modified):
194                         source_is_newer = True
195                     else:
196                         pxd_source_file = source_file + ".pxd"
197                         if os.path.exists(pxd_source_file) and Utils.file_newer_than(pxd_source_file, c_last_modified):
198                             source_is_newer = True
199                 if source_is_newer:
200                     print("Compiling module %s ..." % module)
201                     result = compile(pyx_source_file)
202                     c_source_file = result.c_file
203                 if c_source_file:
204                     # Py2 distutils can't handle unicode file paths
205                     if isinstance(c_source_file, unicode):
206                         filename_encoding = sys.getfilesystemencoding()
207                         if filename_encoding is None:
208                             filename_encoding = sys.getdefaultencoding()
209                         c_source_file = c_source_file.encode(filename_encoding)
210                     if '.refnanny' in module:
211                         defines_for_module = []
212                     else:
213                         defines_for_module = defines
214                     extensions.append(
215                         Extension(module, sources = [c_source_file],
216                                   define_macros = defines_for_module)
217                         )
218                 else:
219                     print("Compilation failed")
220             if extensions:
221                 setup_args['ext_modules'] = extensions
222                 add_command_class("build_ext", build_ext)
223         except Exception:
224             print('''
225 ERROR: %s
226
227 Extension module compilation failed, looks like Cython cannot run
228 properly on this system.  To work around this, pass the option
229 "--no-cython-compile".  This will install a pure Python version of
230 Cython without compiling its own sources.
231 ''' % sys.exc_info()[1])
232             raise
233
234 cython_profile = '--cython-profile' in sys.argv
235 if cython_profile:
236     sys.argv.remove('--cython-profile')
237
238 try:
239     sys.argv.remove("--cython-compile-all")
240     cython_compile_more = True
241 except ValueError:
242     cython_compile_more = False
243
244 try:
245     sys.argv.remove("--cython-with-refnanny")
246     cython_with_refnanny = True
247 except ValueError:
248     cython_with_refnanny = False
249
250 try:
251     sys.argv.remove("--no-cython-compile")
252 except ValueError:
253     compile_cython_modules(cython_profile, cython_compile_more, cython_with_refnanny)
254
255 setup_args.update(setuptools_extra_args)
256
257 from Cython import __version__ as version
258
259 packages = [
260     'Cython',
261     'Cython.Build',
262     'Cython.Compiler',
263     'Cython.Runtime',
264     'Cython.Distutils',
265     'Cython.Plex',
266     'Cython.Tests',
267     'Cython.Build.Tests',
268     'Cython.Compiler.Tests',
269 ]
270
271 if include_debugger:
272     packages.append('Cython.Debugger')
273     packages.append('Cython.Debugger.Tests')
274     # it's enough to do this for Py2.5+:
275     setup_args['package_data']['Cython.Debugger.Tests'] = ['codefile', 'cfuncs.c']
276
277
278 setup(
279   name = 'Cython',
280   version = version,
281   url = 'http://www.cython.org',
282   author = 'Robert Bradshaw, Stefan Behnel, Dag Seljebotn, Greg Ewing, et al.',
283   author_email = 'cython-devel@python.org',
284   description = "The Cython compiler for writing C extensions for the Python language.",
285   long_description = """\
286   The Cython language makes writing C extensions for the Python language as
287   easy as Python itself.  Cython is a source code translator based on the
288   well-known Pyrex_, but supports more cutting edge functionality and
289   optimizations.
290
291   The Cython language is very close to the Python language (and most Python
292   code is also valid Cython code), but Cython additionally supports calling C
293   functions and declaring C types on variables and class attributes. This
294   allows the compiler to generate very efficient C code from Cython code.
295
296   This makes Cython the ideal language for writing glue code for external C
297   libraries, and for fast C modules that speed up the execution of Python
298   code.
299
300   .. _Pyrex: http://www.cosc.canterbury.ac.nz/greg.ewing/python/Pyrex/
301   """,
302   classifiers = [
303     "Development Status :: 5 - Production/Stable",
304     "Intended Audience :: Developers",
305     "License :: OSI Approved :: Apache Software License",
306     "Operating System :: OS Independent",
307     "Programming Language :: Python",
308     "Programming Language :: Python :: 2",
309     "Programming Language :: Python :: 3",
310     "Programming Language :: C",
311     "Programming Language :: Cython",
312     "Topic :: Software Development :: Code Generators",
313     "Topic :: Software Development :: Compilers",
314     "Topic :: Software Development :: Libraries :: Python Modules"
315   ],
316
317   scripts = scripts,
318   packages=packages,
319
320   # pyximport
321   py_modules = ["pyximport/__init__",
322                 "pyximport/pyximport",
323                 "pyximport/pyxbuild",
324
325                 "cython"],
326
327   **setup_args
328   )