1#!/usr/bin/env python 2try: 3 from setuptools import setup, Extension 4except ImportError: 5 from distutils.core import setup, Extension 6import os 7import stat 8import subprocess 9import textwrap 10import sys 11 12import platform 13is_cpython = platform.python_implementation() == 'CPython' 14 15# this specifies which versions of python we support, pip >= 9 knows to skip 16# versions of packages which are not compatible with the running python 17PYTHON_REQUIRES = '>=2.6, !=3.0.*, !=3.1.*, !=3.2.*' 18 19if sys.platform == "darwin": 20 # Don't create resource files on OS X tar. 21 os.environ['COPY_EXTENDED_ATTRIBUTES_DISABLE'] = 'true' 22 os.environ['COPYFILE_DISABLE'] = 'true' 23 24setup_args = {} 25 26def add_command_class(name, cls): 27 cmdclasses = setup_args.get('cmdclass', {}) 28 cmdclasses[name] = cls 29 setup_args['cmdclass'] = cmdclasses 30 31from distutils.command.sdist import sdist as sdist_orig 32class sdist(sdist_orig): 33 def run(self): 34 self.force_manifest = 1 35 if (sys.platform != "win32" and 36 os.path.isdir('.git')): 37 assert os.system("git rev-parse --verify HEAD > .gitrev") == 0 38 sdist_orig.run(self) 39add_command_class('sdist', sdist) 40 41pxd_include_dirs = [ 42 directory for directory, dirs, files 43 in os.walk(os.path.join('Cython', 'Includes')) 44 if '__init__.pyx' in files or '__init__.pxd' in files 45 or directory == os.path.join('Cython', 'Includes') 46 or directory == os.path.join('Cython', 'Includes', 'Deprecated')] 47 48pxd_include_patterns = [ 49 p+'/*.pxd' for p in pxd_include_dirs ] + [ 50 p+'/*.pyx' for p in pxd_include_dirs ] 51 52setup_args['package_data'] = { 53 'Cython.Plex' : ['*.pxd'], 54 'Cython.Compiler' : ['*.pxd'], 55 'Cython.Runtime' : ['*.pyx', '*.pxd'], 56 'Cython.Utility' : ['*.pyx', '*.pxd', '*.c', '*.h', '*.cpp'], 57 'Cython' : [ p[7:] for p in pxd_include_patterns ], 58 'Cython.Debugger.Tests': ['codefile', 'cfuncs.c'], 59} 60 61# This dict is used for passing extra arguments that are setuptools 62# specific to setup 63setuptools_extra_args = {} 64 65if 'setuptools' in sys.modules: 66 setuptools_extra_args['python_requires'] = PYTHON_REQUIRES 67 setuptools_extra_args['zip_safe'] = False 68 setuptools_extra_args['entry_points'] = { 69 'console_scripts': [ 70 'cython = Cython.Compiler.Main:setuptools_main', 71 'cythonize = Cython.Build.Cythonize:main', 72 'cygdb = Cython.Debugger.Cygdb:main', 73 ] 74 } 75 scripts = [] 76else: 77 if os.name == "posix": 78 scripts = ["bin/cython", "bin/cythonize", "bin/cygdb"] 79 else: 80 scripts = ["cython.py", "cythonize.py", "cygdb.py"] 81 82 83def compile_cython_modules(profile=False, compile_more=False, cython_with_refnanny=False): 84 source_root = os.path.abspath(os.path.dirname(__file__)) 85 compiled_modules = [ 86 "Cython.Plex.Scanners", 87 "Cython.Plex.Actions", 88 "Cython.Compiler.Scanning", 89 "Cython.Compiler.Visitor", 90 "Cython.Compiler.FlowControl", 91 "Cython.Runtime.refnanny", 92 "Cython.Compiler.FusedNode", 93 "Cython.Tempita._tempita", 94 ] 95 if compile_more: 96 compiled_modules.extend([ 97 "Cython.StringIOTree", 98 "Cython.Compiler.Code", 99 "Cython.Compiler.Lexicon", 100 "Cython.Compiler.Parsing", 101 "Cython.Compiler.Pythran", 102 "Cython.Build.Dependencies", 103 "Cython.Compiler.ParseTreeTransforms", 104 "Cython.Compiler.Nodes", 105 "Cython.Compiler.ExprNodes", 106 "Cython.Compiler.ModuleNode", 107 "Cython.Compiler.Optimize", 108 ]) 109 110 from distutils.spawn import find_executable 111 from distutils.sysconfig import get_python_inc 112 pgen = find_executable( 113 'pgen', os.pathsep.join([os.environ['PATH'], os.path.join(get_python_inc(), '..', 'Parser')])) 114 if not pgen: 115 sys.stderr.write("Unable to find pgen, not compiling formal grammar.\n") 116 else: 117 parser_dir = os.path.join(os.path.dirname(__file__), 'Cython', 'Parser') 118 grammar = os.path.join(parser_dir, 'Grammar') 119 subprocess.check_call([ 120 pgen, 121 os.path.join(grammar), 122 os.path.join(parser_dir, 'graminit.h'), 123 os.path.join(parser_dir, 'graminit.c'), 124 ]) 125 cst_pyx = os.path.join(parser_dir, 'ConcreteSyntaxTree.pyx') 126 if os.stat(grammar)[stat.ST_MTIME] > os.stat(cst_pyx)[stat.ST_MTIME]: 127 mtime = os.stat(grammar)[stat.ST_MTIME] 128 os.utime(cst_pyx, (mtime, mtime)) 129 compiled_modules.extend([ 130 "Cython.Parser.ConcreteSyntaxTree", 131 ]) 132 133 defines = [] 134 if cython_with_refnanny: 135 defines.append(('CYTHON_REFNANNY', '1')) 136 137 extensions = [] 138 for module in compiled_modules: 139 source_file = os.path.join(source_root, *module.split('.')) 140 if os.path.exists(source_file + ".py"): 141 pyx_source_file = source_file + ".py" 142 else: 143 pyx_source_file = source_file + ".pyx" 144 dep_files = [] 145 if os.path.exists(source_file + '.pxd'): 146 dep_files.append(source_file + '.pxd') 147 if '.refnanny' in module: 148 defines_for_module = [] 149 else: 150 defines_for_module = defines 151 extensions.append(Extension( 152 module, sources=[pyx_source_file], 153 define_macros=defines_for_module, 154 depends=dep_files)) 155 # XXX hack around setuptools quirk for '*.pyx' sources 156 extensions[-1].sources[0] = pyx_source_file 157 158 from Cython.Distutils.build_ext import new_build_ext 159 from Cython.Compiler.Options import get_directive_defaults 160 get_directive_defaults()['language_level'] = 2 161 if profile: 162 get_directive_defaults()['profile'] = True 163 sys.stderr.write("Enabled profiling for the Cython binary modules\n") 164 165 # not using cythonize() directly to let distutils decide whether building extensions was requested 166 add_command_class("build_ext", new_build_ext) 167 setup_args['ext_modules'] = extensions 168 169 170cython_profile = '--cython-profile' in sys.argv 171if cython_profile: 172 sys.argv.remove('--cython-profile') 173 174try: 175 sys.argv.remove("--cython-compile-all") 176 cython_compile_more = True 177except ValueError: 178 cython_compile_more = False 179 180try: 181 sys.argv.remove("--cython-with-refnanny") 182 cython_with_refnanny = True 183except ValueError: 184 cython_with_refnanny = False 185 186try: 187 sys.argv.remove("--no-cython-compile") 188 compile_cython_itself = False 189except ValueError: 190 compile_cython_itself = True 191 192if compile_cython_itself and (is_cpython or cython_compile_more): 193 compile_cython_modules(cython_profile, cython_compile_more, cython_with_refnanny) 194 195setup_args.update(setuptools_extra_args) 196 197from Cython import __version__ as version 198 199 200def dev_status(): 201 if 'b' in version or 'c' in version: 202 # 1b1, 1beta1, 2rc1, ... 203 return 'Development Status :: 4 - Beta' 204 elif 'a' in version: 205 # 1a1, 1alpha1, ... 206 return 'Development Status :: 3 - Alpha' 207 else: 208 return 'Development Status :: 5 - Production/Stable' 209 210 211packages = [ 212 'Cython', 213 'Cython.Build', 214 'Cython.Compiler', 215 'Cython.Runtime', 216 'Cython.Distutils', 217 'Cython.Debugger', 218 'Cython.Debugger.Tests', 219 'Cython.Plex', 220 'Cython.Tests', 221 'Cython.Build.Tests', 222 'Cython.Compiler.Tests', 223 'Cython.Utility', 224 'Cython.Tempita', 225 'pyximport', 226] 227 228setup( 229 name='Cython', 230 version=version, 231 url='http://cython.org/', 232 author='Robert Bradshaw, Stefan Behnel, Dag Seljebotn, Greg Ewing, et al.', 233 author_email='cython-devel@python.org', 234 description="The Cython compiler for writing C extensions for the Python language.", 235 long_description=textwrap.dedent("""\ 236 The Cython language makes writing C extensions for the Python language as 237 easy as Python itself. Cython is a source code translator based on Pyrex_, 238 but supports more cutting edge functionality and optimizations. 239 240 The Cython language is a superset of the Python language (almost all Python 241 code is also valid Cython code), but Cython additionally supports optional 242 static typing to natively call C functions, operate with C++ classes and 243 declare fast C types on variables and class attributes. This allows the 244 compiler to generate very efficient C code from Cython code. 245 246 This makes Cython the ideal language for writing glue code for external 247 C/C++ libraries, and for fast C modules that speed up the execution of 248 Python code. 249 250 Note that for one-time builds, e.g. for CI/testing, on platforms that are not 251 covered by one of the wheel packages provided on PyPI *and* the pure Python wheel 252 that we provide is not used, it is substantially faster than a full source build 253 to install an uncompiled (slower) version of Cython with:: 254 255 pip install Cython --install-option="--no-cython-compile" 256 257 .. _Pyrex: http://www.cosc.canterbury.ac.nz/greg.ewing/python/Pyrex/ 258 """), 259 license='Apache', 260 classifiers=[ 261 dev_status(), 262 "Intended Audience :: Developers", 263 "License :: OSI Approved :: Apache Software License", 264 "Operating System :: OS Independent", 265 "Programming Language :: Python", 266 "Programming Language :: Python :: 2", 267 "Programming Language :: Python :: 2.6", 268 "Programming Language :: Python :: 2.7", 269 "Programming Language :: Python :: 3", 270 "Programming Language :: Python :: 3.4", 271 "Programming Language :: Python :: 3.5", 272 "Programming Language :: Python :: 3.6", 273 "Programming Language :: Python :: 3.7", 274 "Programming Language :: Python :: 3.8", 275 "Programming Language :: Python :: 3.9", 276 "Programming Language :: Python :: Implementation :: CPython", 277 "Programming Language :: Python :: Implementation :: PyPy", 278 "Programming Language :: C", 279 "Programming Language :: Cython", 280 "Topic :: Software Development :: Code Generators", 281 "Topic :: Software Development :: Compilers", 282 "Topic :: Software Development :: Libraries :: Python Modules" 283 ], 284 285 scripts=scripts, 286 packages=packages, 287 py_modules=["cython"], 288 **setup_args 289) 290