X-Git-Url: http://git.tremily.us/?a=blobdiff_plain;f=setup.py;h=cb4f996dd241e9fb0d60e1f2702a9e105a82ec4e;hb=dafd5e0e29ac340f8f35e7a119b90ba60a2cc002;hp=da55aa931072a92ab208229f870023a538870102;hpb=5cc0a44b2bb99b85349c9b5f937b036c1b4ddb47;p=cython.git diff --git a/setup.py b/setup.py index da55aa93..cb4f996d 100644 --- a/setup.py +++ b/setup.py @@ -3,21 +3,6 @@ from distutils.sysconfig import get_python_lib import os, os.path import sys -if 'sdist' in sys.argv: - # Record the current revision in .hgrev - import subprocess # os.popen is cleaner but depricated - changset = subprocess.Popen("hg log --rev tip | grep changeset", - shell=True, - stdout=subprocess.PIPE).stdout.read() - rev = changset.split(':')[-1].strip() - hgrev = open('.hgrev', 'w') - hgrev.write(rev) - hgrev.close() - -compiler_dir = os.path.join(get_python_lib(prefix=''), 'Cython/Compiler') -if sys.platform == "win32": - compiler_dir = compiler_dir[len(sys.prefix)+1:] - if sys.platform == "darwin": # Don't create resource files on OS X tar. os.environ['COPY_EXTENDED_ATTRIBUTES_DISABLE'] = 'true' @@ -30,6 +15,16 @@ def add_command_class(name, cls): cmdclasses[name] = cls setup_args['cmdclass'] = cmdclasses +from distutils.command.sdist import sdist as sdist_orig +class sdist(sdist_orig): + def run(self): + self.force_manifest = 1 + if (sys.platform != "win32" and + os.path.isdir('.git')): + assert os.system("git show-ref -s HEAD > .gitrev") == 0 + sdist_orig.run(self) +add_command_class('sdist', sdist) + if sys.version_info[0] >= 3: import lib2to3.refactor from distutils.command.build_py \ @@ -41,28 +36,43 @@ if sys.version_info[0] >= 3: build_py.fixer_names = fixers add_command_class("build_py", build_py) +pxd_include_dirs = [ + directory for directory, dirs, files in os.walk('Cython/Includes') + if '__init__.pyx' in files or '__init__.pxd' in files + or directory == 'Cython/Includes' or directory == 'Cython/Includes/Deprecated'] + +pxd_include_patterns = [ + p+'/*.pxd' for p in pxd_include_dirs ] + [ + p+'/*.pyx' for p in pxd_include_dirs ] if sys.version_info < (2,4): + install_base_dir = get_python_lib(prefix='') import glob - cython_dir = os.path.join(get_python_lib(prefix=''), 'Cython') - compiler_dir = os.path.join(cython_dir, 'Compiler') + patterns = pxd_include_patterns + [ + 'Cython/Plex/*.pxd', + 'Cython/Compiler/*.pxd', + 'Cython/Runtime/*.pyx' + ] setup_args['data_files'] = [ - (cython_dir, [ f for pattern in - ['Cython/Includes/*.pxd', - 'Cython/Plex/*.pxd', - 'Cython/Compiler/*.pxd', - 'Cython/Runtime/*.pyx'] - for f in glob.glob(pattern) ])] + (os.path.dirname(os.path.join(install_base_dir, pattern)), + [ f for f in glob.glob(pattern) ]) + for pattern in patterns + ] else: - setup_args['package_data'] = {'Cython' : ['Includes/*.pxd', - 'Plex/*.pxd', - 'Compiler/*.pxd', - 'Runtime/*.pyx']} + setup_args['package_data'] = { + 'Cython.Plex' : ['*.pxd'], + 'Cython.Compiler' : ['*.pxd'], + 'Cython.Runtime' : ['*.pyx', '*.pxd'], + 'Cython' : [ p[7:] for p in pxd_include_patterns ], + } -# This dict is used for passing extra arguments that are setuptools +# This dict is used for passing extra arguments that are setuptools # specific to setup setuptools_extra_args = {} +# tells whether to include cygdb (the script and the Cython.Debugger package +include_debugger = sys.version_info[:2] > (2, 5) + if 'setuptools' in sys.modules: setuptools_extra_args['zip_safe'] = False setuptools_extra_args['entry_points'] = { @@ -74,18 +84,37 @@ if 'setuptools' in sys.modules: else: if os.name == "posix": scripts = ["bin/cython"] + if include_debugger: + scripts.append('bin/cygdb') else: scripts = ["cython.py"] + if include_debugger: + scripts.append('cygdb.py') -def compile_cython_modules(): +def compile_cython_modules(profile=False, compile_more=False, cython_with_refnanny=False): source_root = os.path.abspath(os.path.dirname(__file__)) compiled_modules = ["Cython.Plex.Scanners", + "Cython.Plex.Actions", + "Cython.Compiler.Lexicon", "Cython.Compiler.Scanning", "Cython.Compiler.Parsing", "Cython.Compiler.Visitor", - "Cython.Runtime.refnanny"] - extensions = [] + "Cython.Compiler.Code", + "Cython.Runtime.refnanny",] + if compile_more: + compiled_modules.extend([ + "Cython.Compiler.ParseTreeTransforms", + "Cython.Compiler.Nodes", + "Cython.Compiler.ExprNodes", + "Cython.Compiler.ModuleNode", + "Cython.Compiler.Optimize", + ]) + + defines = [] + if cython_with_refnanny: + defines.append(('CYTHON_REFNANNY', '1')) + extensions = [] if sys.version_info[0] >= 3: from Cython.Distutils import build_ext as build_ext_orig for module in compiled_modules: @@ -94,20 +123,40 @@ def compile_cython_modules(): pyx_source_file = source_file + ".py" else: pyx_source_file = source_file + ".pyx" + dep_files = [] + if os.path.exists(source_file + '.pxd'): + dep_files.append(source_file + '.pxd') + if '.refnanny' in module: + defines_for_module = [] + else: + defines_for_module = defines extensions.append( - Extension(module, sources = [pyx_source_file]) + Extension(module, sources = [pyx_source_file], + define_macros = defines_for_module, + depends = dep_files) ) class build_ext(build_ext_orig): + # we must keep the original modules alive to make sure + # their code keeps working when we remove them from + # sys.modules + dead_modules = [] + def build_extensions(self): # add path where 2to3 installed the transformed sources # and make sure Python (re-)imports them from there already_imported = [ module for module in sys.modules if module == 'Cython' or module.startswith('Cython.') ] + keep_alive = self.dead_modules.append for module in already_imported: + keep_alive(sys.modules[module]) del sys.modules[module] sys.path.insert(0, os.path.join(source_root, self.build_lib)) + if profile: + from Cython.Compiler.Options import directive_defaults + directive_defaults['profile'] = True + print("Enabled profiling for the Cython binary modules") build_ext_orig.build_extensions(self) setup_args['ext_modules'] = extensions @@ -124,6 +173,10 @@ def compile_cython_modules(): print("Compilation of '%s' failed" % ext.sources[0]) from Cython.Compiler.Main import compile from Cython import Utils + if profile: + from Cython.Compiler.Options import directive_defaults + directive_defaults['profile'] = True + print("Enabled profiling for the Cython binary modules") source_root = os.path.dirname(__file__) for module in compiled_modules: source_file = os.path.join(source_root, *module.split('.')) @@ -132,15 +185,35 @@ def compile_cython_modules(): else: pyx_source_file = source_file + ".pyx" c_source_file = source_file + ".c" - if not os.path.exists(c_source_file) or \ - Utils.file_newer_than(pyx_source_file, - Utils.modification_time(c_source_file)): + source_is_newer = False + if not os.path.exists(c_source_file): + source_is_newer = True + else: + c_last_modified = Utils.modification_time(c_source_file) + if Utils.file_newer_than(pyx_source_file, c_last_modified): + source_is_newer = True + else: + pxd_source_file = source_file + ".pxd" + if os.path.exists(pxd_source_file) and Utils.file_newer_than(pxd_source_file, c_last_modified): + source_is_newer = True + if source_is_newer: print("Compiling module %s ..." % module) result = compile(pyx_source_file) c_source_file = result.c_file if c_source_file: + # Py2 distutils can't handle unicode file paths + if isinstance(c_source_file, unicode): + filename_encoding = sys.getfilesystemencoding() + if filename_encoding is None: + filename_encoding = sys.getdefaultencoding() + c_source_file = c_source_file.encode(filename_encoding) + if '.refnanny' in module: + defines_for_module = [] + else: + defines_for_module = defines extensions.append( - Extension(module, sources = [c_source_file]) + Extension(module, sources = [c_source_file], + define_macros = defines_for_module) ) else: print("Compilation failed") @@ -148,24 +221,66 @@ def compile_cython_modules(): setup_args['ext_modules'] = extensions add_command_class("build_ext", build_ext) except Exception: - print("ERROR: %s" % sys.exc_info()[1]) - print("Extension module compilation failed, using plain Python implementation") + print(''' +ERROR: %s + +Extension module compilation failed, looks like Cython cannot run +properly on this system. To work around this, pass the option +"--no-cython-compile". This will install a pure Python version of +Cython without compiling its own sources. +''' % sys.exc_info()[1]) + raise + +cython_profile = '--cython-profile' in sys.argv +if cython_profile: + sys.argv.remove('--cython-profile') + +try: + sys.argv.remove("--cython-compile-all") + cython_compile_more = True +except ValueError: + cython_compile_more = False + +try: + sys.argv.remove("--cython-with-refnanny") + cython_with_refnanny = True +except ValueError: + cython_with_refnanny = False try: sys.argv.remove("--no-cython-compile") except ValueError: - compile_cython_modules() + compile_cython_modules(cython_profile, cython_compile_more, cython_with_refnanny) setup_args.update(setuptools_extra_args) -from Cython.Compiler.Version import version +from Cython import __version__ as version + +packages = [ + 'Cython', + 'Cython.Build', + 'Cython.Compiler', + 'Cython.Runtime', + 'Cython.Distutils', + 'Cython.Plex', + 'Cython.Tests', + 'Cython.Build.Tests', + 'Cython.Compiler.Tests', +] + +if include_debugger: + packages.append('Cython.Debugger') + packages.append('Cython.Debugger.Tests') + # it's enough to do this for Py2.5+: + setup_args['package_data']['Cython.Debugger.Tests'] = ['codefile', 'cfuncs.c'] + setup( name = 'Cython', version = version, url = 'http://www.cython.org', - author = 'Greg Ewing, Robert Bradshaw, Stefan Behnel, Dag Seljebotn, et al.', - author_email = 'cython-dev@codespeak.net', + author = 'Robert Bradshaw, Stefan Behnel, Dag Seljebotn, Greg Ewing, et al.', + author_email = 'cython-devel@python.org', description = "The Cython compiler for writing C extensions for the Python language.", long_description = """\ The Cython language makes writing C extensions for the Python language as @@ -200,16 +315,7 @@ setup( ], scripts = scripts, - packages=[ - 'Cython', - 'Cython.Compiler', - 'Cython.Runtime', - 'Cython.Distutils', - 'Cython.Plex', - - 'Cython.Tests', - 'Cython.Compiler.Tests', - ], + packages=packages, # pyximport py_modules = ["pyximport/__init__",