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