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