diff --git a/.travis.yml b/.travis.yml index 1f517d188ce6ee3ff91b2f2f08ea5dc4e043b81b..5677901f66695ec1e7b6845836912e967493e5cb 100644 --- a/.travis.yml +++ b/.travis.yml @@ -6,13 +6,7 @@ language: python # Pre-install packages for the ubuntu distribution cache: apt: true - # We use three different cache directory - # to work around a Travis bug with multi-platform cache directories: - - $HOME/sklearn_build_ubuntu - - $HOME/sklearn_build_oldest - - $HOME/sklearn_build_latest - - $HOME/sklearn_build_numpy_dev - $HOME/.cache/pip - $HOME/download addons: @@ -33,21 +27,19 @@ env: # This environment tests that scikit-learn can be built against # versions of numpy, scipy with ATLAS that comes with Ubuntu Precise 12.04 - DISTRIB="ubuntu" PYTHON_VERSION="2.7" CYTHON_VERSION="0.23.4" - CACHED_BUILD_DIR="$HOME/sklearn_build_ubuntu" COVERAGE=true + COVERAGE=true # This environment tests the oldest supported anaconda env - DISTRIB="conda" PYTHON_VERSION="2.6" INSTALL_MKL="false" - NUMPY_VERSION="1.6.2" SCIPY_VERSION="0.11.0" CYTHON_VERSION="0.21" - CACHED_BUILD_DIR="$HOME/sklearn_build_oldest" + NUMPY_VERSION="1.6.2" SCIPY_VERSION="0.11.0" CYTHON_VERSION="0.23" # This environment tests the newest supported anaconda env # It also runs tests requiring Pandas. - DISTRIB="conda" PYTHON_VERSION="3.5" INSTALL_MKL="true" NUMPY_VERSION="1.10.4" SCIPY_VERSION="0.17.0" PANDAS_VERSION="0.18.0" - CYTHON_VERSION="0.23.4" CACHED_BUILD_DIR="$HOME/sklearn_build_latest" + CYTHON_VERSION="0.23.4" # flake8 linting on diff wrt common ancestor with upstream/master - RUN_FLAKE8="true" SKIP_TESTS="true" DISTRIB="conda" PYTHON_VERSION="3.5" INSTALL_MKL="true" NUMPY_VERSION="1.10.4" SCIPY_VERSION="0.17.0" CYTHON_VERSION="0.23.4" - CACHED_BUILD_DIR="$HOME/dummy" matrix: @@ -66,7 +58,6 @@ matrix: # the before_install step with and addons/apt/packages declaration. - python: 3.5 env: DISTRIB="scipy-dev-wheels" - CACHED_BUILD_DIR="$HOME/sklearn_build_numpy_dev" sudo: True before_install: sudo apt-get install -yqq libatlas3gf-base libatlas-dev diff --git a/build_tools/cythonize.py b/build_tools/cythonize.py deleted file mode 100755 index b01da58231db51e1a76dfad5acd43ad33505166f..0000000000000000000000000000000000000000 --- a/build_tools/cythonize.py +++ /dev/null @@ -1,198 +0,0 @@ -#!/usr/bin/env python -""" cythonize - -Cythonize pyx files into C files as needed. - -Usage: cythonize [root_dir] - -Default [root_dir] is 'sklearn'. - -Checks pyx files to see if they have been changed relative to their -corresponding C files. If they have, then runs cython on these files to -recreate the C files. - -The script detects changes in the pyx/pxd files using checksums -[or hashes] stored in a database file - -Simple script to invoke Cython on all .pyx -files; while waiting for a proper build system. Uses file hashes to -figure out if rebuild is needed. - -It is called by ./setup.py sdist so that sdist package can be installed without -cython - -Originally written by Dag Sverre Seljebotn, and adapted from statsmodel 0.6.1 -(Modified BSD 3-clause) - -We copied it for scikit-learn. - -Note: this script does not check any of the dependent C libraries; it only -operates on the Cython .pyx files or their corresponding Cython header (.pxd) -files. -""" -# Author: Arthur Mensch <arthur.mensch@inria.fr> -# Author: Raghav R V <rvraghav93@gmail.com> -# -# License: BSD 3 clause - -from __future__ import division, print_function, absolute_import - -import os -import re -import sys -import hashlib -import subprocess - -HASH_FILE = 'cythonize.dat' -DEFAULT_ROOT = 'sklearn' - -# WindowsError is not defined on unix systems -try: - WindowsError -except NameError: - WindowsError = None - - -def cythonize(cython_file, gen_file): - try: - from Cython.Compiler.Version import version as cython_version - from distutils.version import LooseVersion - if LooseVersion(cython_version) < LooseVersion('0.21'): - raise Exception('Building scikit-learn requires Cython >= 0.21') - - except ImportError: - pass - - flags = ['--fast-fail'] - if gen_file.endswith('.cpp'): - flags += ['--cplus'] - - try: - try: - rc = subprocess.call(['cython'] + - flags + ["-o", gen_file, cython_file]) - if rc != 0: - raise Exception('Cythonizing %s failed' % cython_file) - except OSError: - # There are ways of installing Cython that don't result in a cython - # executable on the path, see scipy issue gh-2397. - rc = subprocess.call([sys.executable, '-c', - 'import sys; from Cython.Compiler.Main ' - 'import setuptools_main as main;' - ' sys.exit(main())'] + flags + - ["-o", gen_file, cython_file]) - if rc != 0: - raise Exception('Cythonizing %s failed' % cython_file) - except OSError: - raise OSError('Cython needs to be installed') - - -def load_hashes(filename): - """Load the hashes dict from the hashfile""" - # { filename : (sha1 of header if available or 'NA', - # sha1 of input, - # sha1 of output) } - - hashes = {} - try: - with open(filename, 'r') as cython_hash_file: - for hash_record in cython_hash_file: - (filename, header_hash, - cython_hash, gen_file_hash) = hash_record.split() - hashes[filename] = (header_hash, cython_hash, gen_file_hash) - except (KeyError, ValueError, AttributeError, IOError): - hashes = {} - return hashes - - -def save_hashes(hashes, filename): - """Save the hashes dict to the hashfile""" - with open(filename, 'w') as cython_hash_file: - for key, value in hashes.items(): - cython_hash_file.write("%s %s %s %s\n" - % (key, value[0], value[1], value[2])) - - -def sha1_of_file(filename): - h = hashlib.sha1() - with open(filename, "rb") as f: - h.update(f.read()) - return h.hexdigest() - - -def clean_path(path): - """Clean the path""" - path = path.replace(os.sep, '/') - if path.startswith('./'): - path = path[2:] - return path - - -def get_hash_tuple(header_path, cython_path, gen_file_path): - """Get the hashes from the given files""" - - header_hash = (sha1_of_file(header_path) - if os.path.exists(header_path) else 'NA') - from_hash = sha1_of_file(cython_path) - to_hash = (sha1_of_file(gen_file_path) - if os.path.exists(gen_file_path) else 'NA') - - return header_hash, from_hash, to_hash - - -def cythonize_if_unchanged(path, cython_file, gen_file, hashes): - full_cython_path = os.path.join(path, cython_file) - full_header_path = full_cython_path.replace('.pyx', '.pxd') - full_gen_file_path = os.path.join(path, gen_file) - - current_hash = get_hash_tuple(full_header_path, full_cython_path, - full_gen_file_path) - - if current_hash == hashes.get(clean_path(full_cython_path)): - print('%s has not changed' % full_cython_path) - return - - print('Processing %s' % full_cython_path) - cythonize(full_cython_path, full_gen_file_path) - - # changed target file, recompute hash - current_hash = get_hash_tuple(full_header_path, full_cython_path, - full_gen_file_path) - - # Update the hashes dict with the new hash - hashes[clean_path(full_cython_path)] = current_hash - - -def check_and_cythonize(root_dir): - print(root_dir) - hashes = load_hashes(HASH_FILE) - - for cur_dir, dirs, files in os.walk(root_dir): - for filename in files: - if filename.endswith('.pyx'): - gen_file_ext = '.c' - # Cython files with libcpp imports should be compiled to cpp - with open(os.path.join(cur_dir, filename), 'rb') as f: - data = f.read() - m = re.search(b"libcpp", data, re.I | re.M) - if m: - gen_file_ext = ".cpp" - cython_file = filename - gen_file = filename.replace('.pyx', gen_file_ext) - cythonize_if_unchanged(cur_dir, cython_file, gen_file, hashes) - - # Save hashes once per module. This prevents cythonizing prev. - # files again when debugging broken code in a single file - save_hashes(hashes, HASH_FILE) - - -def main(root_dir=DEFAULT_ROOT): - check_and_cythonize(root_dir) - - -if __name__ == '__main__': - try: - root_dir_arg = sys.argv[1] - except IndexError: - root_dir_arg = DEFAULT_ROOT - main(root_dir_arg) diff --git a/build_tools/travis/install.sh b/build_tools/travis/install.sh index bfd39bc58a69a8949afb12994cb71e76c85672bd..def59e35f1d7c9a38be3c6aa1fd0f5861d12a0f8 100755 --- a/build_tools/travis/install.sh +++ b/build_tools/travis/install.sh @@ -53,17 +53,23 @@ if [[ "$DISTRIB" == "conda" ]]; then if [[ "$INSTALL_MKL" == "true" ]]; then conda create -n testenv --yes python=$PYTHON_VERSION pip nose \ numpy=$NUMPY_VERSION scipy=$SCIPY_VERSION numpy scipy \ - cython=$CYTHON_VERSION libgfortran mkl flake8 \ + libgfortran mkl flake8 \ ${PANDAS_VERSION+pandas=$PANDAS_VERSION} else conda create -n testenv --yes python=$PYTHON_VERSION pip nose \ - numpy=$NUMPY_VERSION scipy=$SCIPY_VERSION cython=$CYTHON_VERSION \ + numpy=$NUMPY_VERSION scipy=$SCIPY_VERSION \ libgfortran nomkl \ ${PANDAS_VERSION+pandas=$PANDAS_VERSION} fi source activate testenv + # Temporary work around for Python 2.6 because cython >= 0.23 is + # required for building scikit-learn but python 2.6 and cython + # 0.23 are not compatible in conda. Remove the next line and + # install cython via conda when Python 2.6 support is removed. + pip install cython==$CYTHON_VERSION + # Install nose-timer via pip pip install nose-timer @@ -101,15 +107,6 @@ fi if [[ "$SKIP_TESTS" == "true" ]]; then echo "No need to build scikit-learn when not running the tests" else - if [ ! -d "$CACHED_BUILD_DIR" ]; then - mkdir -p $CACHED_BUILD_DIR - fi - - rsync -av --exclude '.git/' --exclude='testvenv/' \ - $TRAVIS_BUILD_DIR $CACHED_BUILD_DIR - - cd $CACHED_BUILD_DIR/scikit-learn - # Build scikit-learn in the install.sh script to collapse the verbose # build output in the travis output when it succeeds. python --version diff --git a/build_tools/travis/test_script.sh b/build_tools/travis/test_script.sh index d40fd2e91752a97dffd2872d8a1a54cc4cae55d5..3e9bb9978161dd979462e33693fcb5ff68367cf2 100755 --- a/build_tools/travis/test_script.sh +++ b/build_tools/travis/test_script.sh @@ -39,11 +39,8 @@ run_tests() { nosetests -s --with-timer --timer-top-n 20 sklearn fi - # Is directory still empty ? - ls -ltra - # Test doc - cd $CACHED_BUILD_DIR/scikit-learn + cd $OLDPWD make test-doc test-sphinxext } diff --git a/setup.py b/setup.py index 1a50d3b61806249a43e0f35a376572ffa8266223..1a10d70f3ba5d0d2b097b0dafe5d43f4478e54b1 100755 --- a/setup.py +++ b/setup.py @@ -84,9 +84,6 @@ class CleanCommand(Clean): cwd = os.path.abspath(os.path.dirname(__file__)) remove_c_files = not os.path.exists(os.path.join(cwd, 'PKG-INFO')) if remove_c_files: - cython_hash_file = os.path.join(cwd, 'cythonize.dat') - if os.path.exists(cython_hash_file): - os.unlink(cython_hash_file) print('Will remove generated .c files') if os.path.exists('build'): shutil.rmtree('build') @@ -181,18 +178,6 @@ def get_numpy_status(): return numpy_status -def generate_cython(): - cwd = os.path.abspath(os.path.dirname(__file__)) - print("Cythonizing sources") - p = subprocess.call([sys.executable, os.path.join(cwd, - 'build_tools', - 'cythonize.py'), - 'sklearn'], - cwd=cwd) - if p != 0: - raise RuntimeError("Running cythonize failed!") - - def setup_package(): metadata = dict(name=DISTNAME, maintainer=MAINTAINER, @@ -230,7 +215,7 @@ def setup_package(): 'egg_info', '--version', 'clean'))): - # For these actions, NumPy is not required, nor Cythonization + # For these actions, NumPy is not required # # They are required to succeed without Numpy for example when # pip is used to install Scikit-learn when Numpy is not yet present in @@ -278,26 +263,6 @@ def setup_package(): metadata['configuration'] = configuration - if len(sys.argv) >= 2 and sys.argv[1] not in 'config': - # Cythonize if needed - - print('Generating cython files') - cwd = os.path.abspath(os.path.dirname(__file__)) - if not os.path.exists(os.path.join(cwd, 'PKG-INFO')): - # Generate Cython sources, unless building from source release - generate_cython() - - # Clean left-over .so file - for dirpath, dirnames, filenames in os.walk( - os.path.join(cwd, 'sklearn')): - for filename in filenames: - extension = os.path.splitext(filename)[1] - if extension in (".so", ".pyd", ".dll"): - pyx_file = str.replace(filename, extension, '.pyx') - print(pyx_file) - if not os.path.exists(os.path.join(dirpath, pyx_file)): - os.unlink(os.path.join(dirpath, filename)) - setup(**metadata) diff --git a/sklearn/__check_build/setup.py b/sklearn/__check_build/setup.py index c9a76db2b5cd776cffdc7e599fd043c2ac453faa..b8c30d9c83dffd8776cd2b6c75919921805c93b3 100644 --- a/sklearn/__check_build/setup.py +++ b/sklearn/__check_build/setup.py @@ -8,7 +8,7 @@ def configuration(parent_package='', top_path=None): from numpy.distutils.misc_util import Configuration config = Configuration('__check_build', parent_package, top_path) config.add_extension('_check_build', - sources=['_check_build.c'], + sources=['_check_build.pyx'], include_dirs=[numpy.get_include()]) return config diff --git a/sklearn/_build_utils/__init__.py b/sklearn/_build_utils/__init__.py index 85049f749262176a67c83557792c4e7cebd2cd85..0ed4968a1aa38727ff2fec63d79ef8d1b29fc37c 100644 --- a/sklearn/_build_utils/__init__.py +++ b/sklearn/_build_utils/__init__.py @@ -6,10 +6,15 @@ Utilities useful during the build. from __future__ import division, print_function, absolute_import -DEFAULT_ROOT = 'sklearn' +import os + +from distutils.version import LooseVersion from numpy.distutils.system_info import get_info +DEFAULT_ROOT = 'sklearn' +CYTHON_MIN_VERSION = '0.23' + def get_blas_info(): def atlas_not_found(blas_info_): @@ -33,3 +38,47 @@ def get_blas_info(): cblas_libs = blas_info.pop('libraries', []) return cblas_libs, blas_info + + +def build_from_c_and_cpp_files(extensions): + """Modify the extensions to build from the .c and .cpp files. + + This is useful for releases, this way cython is not required to + run python setup.py install. + """ + for extension in extensions: + sources = [] + for sfile in extension.sources: + path, ext = os.path.splitext(sfile) + if ext in ('.pyx', '.py'): + if extension.language == 'c++': + ext = '.cpp' + else: + ext = '.c' + sfile = path + ext + sources.append(sfile) + extension.sources = sources + + +def maybe_cythonize_extensions(top_path, config): + """Tweaks for building extensions between release and development mode.""" + is_release = os.path.exists(os.path.join(top_path, 'PKG-INFO')) + + if is_release: + build_from_c_and_cpp_files(config.ext_modules) + else: + message = ('Please install cython with a version >= {0} in order ' + 'to build a scikit-learn development version.').format( + CYTHON_MIN_VERSION) + try: + import Cython + if LooseVersion(Cython.__version__) < CYTHON_MIN_VERSION: + message += ' Your version of Cython was {0}.'.format( + Cython.__version__) + raise ValueError(message) + from Cython.Build import cythonize + except ImportError as exc: + exc.args += (message,) + raise + + config.ext_modules = cythonize(config.ext_modules) diff --git a/sklearn/cluster/setup.py b/sklearn/cluster/setup.py index 672983c7aa9ed5a681d3578f6a459ae8f1b44953..99c4dcd6177b06d86724ffe4cc69abc04d2e2049 100644 --- a/sklearn/cluster/setup.py +++ b/sklearn/cluster/setup.py @@ -20,30 +20,30 @@ def configuration(parent_package='', top_path=None): config = Configuration('cluster', parent_package, top_path) config.add_extension('_dbscan_inner', - sources=['_dbscan_inner.cpp'], + sources=['_dbscan_inner.pyx'], include_dirs=[numpy.get_include()], language="c++") config.add_extension('_hierarchical', - sources=['_hierarchical.cpp'], + sources=['_hierarchical.pyx'], language="c++", include_dirs=[numpy.get_include()], libraries=libraries) config.add_extension('_k_means_elkan', - sources=['_k_means_elkan.c'], + sources=['_k_means_elkan.pyx'], include_dirs=[numpy.get_include()], libraries=libraries) - config.add_extension( - '_k_means', - libraries=cblas_libs, - sources=['_k_means.c'], - include_dirs=[join('..', 'src', 'cblas'), - numpy.get_include(), - blas_info.pop('include_dirs', [])], - extra_compile_args=blas_info.pop('extra_compile_args', []), - **blas_info - ) + config.add_extension('_k_means', + libraries=cblas_libs, + sources=['_k_means.pyx'], + include_dirs=[join('..', 'src', 'cblas'), + numpy.get_include(), + blas_info.pop('include_dirs', [])], + extra_compile_args=blas_info.pop( + 'extra_compile_args', []), + **blas_info + ) config.add_subpackage('tests') diff --git a/sklearn/datasets/setup.py b/sklearn/datasets/setup.py index 78327e8b3ffa0b3f728fa96fec4244c40400ec03..a1def76c1bfcec53171688532dc440437bad9cb3 100644 --- a/sklearn/datasets/setup.py +++ b/sklearn/datasets/setup.py @@ -11,7 +11,7 @@ def configuration(parent_package='', top_path=None): config.add_data_dir('images') config.add_data_dir(os.path.join('tests', 'data')) config.add_extension('_svmlight_format', - sources=['_svmlight_format.c'], + sources=['_svmlight_format.pyx'], include_dirs=[numpy.get_include()]) config.add_subpackage('tests') return config diff --git a/sklearn/decomposition/setup.py b/sklearn/decomposition/setup.py index ffa523d2fe7143a98b135d15913272ad6ee665f7..dc57808ddc621f65ae6d17079d94515394eefd67 100644 --- a/sklearn/decomposition/setup.py +++ b/sklearn/decomposition/setup.py @@ -11,12 +11,12 @@ def configuration(parent_package="", top_path=None): libraries.append('m') config.add_extension("_online_lda", - sources=["_online_lda.c"], + sources=["_online_lda.pyx"], include_dirs=[numpy.get_include()], libraries=libraries) config.add_extension('cdnmf_fast', - sources=['cdnmf_fast.c'], + sources=['cdnmf_fast.pyx'], include_dirs=[numpy.get_include()], libraries=libraries) diff --git a/sklearn/ensemble/setup.py b/sklearn/ensemble/setup.py index 59c01f81f6530dc13e96b14cc62680c019bc9d37..34fb63b906d0a389c22035763735d80f70302bd9 100644 --- a/sklearn/ensemble/setup.py +++ b/sklearn/ensemble/setup.py @@ -5,7 +5,7 @@ from numpy.distutils.misc_util import Configuration def configuration(parent_package="", top_path=None): config = Configuration("ensemble", parent_package, top_path) config.add_extension("_gradient_boosting", - sources=["_gradient_boosting.c"], + sources=["_gradient_boosting.pyx"], include_dirs=[numpy.get_include()]) config.add_subpackage("tests") diff --git a/sklearn/feature_extraction/setup.py b/sklearn/feature_extraction/setup.py index 075cac470bf7a68d499aa9639b712c1ed2922b47..7b71dfdcc83d7c1626686f940eef82a645f0da25 100644 --- a/sklearn/feature_extraction/setup.py +++ b/sklearn/feature_extraction/setup.py @@ -11,7 +11,7 @@ def configuration(parent_package='', top_path=None): libraries.append('m') config.add_extension('_hashing', - sources=['_hashing.c'], + sources=['_hashing.pyx'], include_dirs=[numpy.get_include()], libraries=libraries) config.add_subpackage("tests") diff --git a/sklearn/linear_model/setup.py b/sklearn/linear_model/setup.py index 4f8ab23cac77d8c595bf339f08918bfc6ed32936..9c3822b8e7561eb6d3a9799f871afae23d6708cf 100644 --- a/sklearn/linear_model/setup.py +++ b/sklearn/linear_model/setup.py @@ -16,7 +16,7 @@ def configuration(parent_package='', top_path=None): if os.name == 'posix': cblas_libs.append('m') - config.add_extension('cd_fast', sources=['cd_fast.c'], + config.add_extension('cd_fast', sources=['cd_fast.pyx'], libraries=cblas_libs, include_dirs=[join('..', 'src', 'cblas'), numpy.get_include(), @@ -25,7 +25,7 @@ def configuration(parent_package='', top_path=None): []), **blas_info) config.add_extension('sgd_fast', - sources=['sgd_fast.c'], + sources=['sgd_fast.pyx'], include_dirs=[join('..', 'src', 'cblas'), numpy.get_include(), blas_info.pop('include_dirs', [])], @@ -35,7 +35,7 @@ def configuration(parent_package='', top_path=None): **blas_info) config.add_extension('sag_fast', - sources=['sag_fast.c'], + sources=['sag_fast.pyx'], include_dirs=numpy.get_include()) # add other directories diff --git a/sklearn/manifold/setup.py b/sklearn/manifold/setup.py index d1b6ebf9e0adc2cbcf631388a08998e4ee393b06..a2562cd3c02d8e036bc9d61affcfe6f5bde809d7 100644 --- a/sklearn/manifold/setup.py +++ b/sklearn/manifold/setup.py @@ -12,7 +12,7 @@ def configuration(parent_package="", top_path=None): if os.name == 'posix': libraries.append('m') config.add_extension("_utils", - sources=["_utils.c"], + sources=["_utils.pyx"], include_dirs=[numpy.get_include()], libraries=libraries, extra_compile_args=["-O3"]) @@ -21,7 +21,7 @@ def configuration(parent_package="", top_path=None): eca.append("-O4") config.add_extension("_barnes_hut_tsne", libraries=cblas_libs, - sources=["_barnes_hut_tsne.c"], + sources=["_barnes_hut_tsne.pyx"], include_dirs=[join('..', 'src', 'cblas'), numpy.get_include(), blas_info.pop('include_dirs', [])], diff --git a/sklearn/metrics/cluster/setup.py b/sklearn/metrics/cluster/setup.py index 22debe88fe6ff5c8e3f99b05f62275e162008f0a..910cc829a10faa5ab69dc227ed29a23727ea4d56 100644 --- a/sklearn/metrics/cluster/setup.py +++ b/sklearn/metrics/cluster/setup.py @@ -10,7 +10,7 @@ def configuration(parent_package="", top_path=None): if os.name == 'posix': libraries.append('m') config.add_extension("expected_mutual_info_fast", - sources=["expected_mutual_info_fast.c"], + sources=["expected_mutual_info_fast.pyx"], include_dirs=[numpy.get_include()], libraries=libraries) diff --git a/sklearn/metrics/setup.py b/sklearn/metrics/setup.py index 7e2f4e6ae41bb117b32aea478582e0e6e951b68b..946016e3df814ae5df64b4a30ef3735b3512ffd5 100644 --- a/sklearn/metrics/setup.py +++ b/sklearn/metrics/setup.py @@ -15,7 +15,7 @@ def configuration(parent_package="", top_path=None): cblas_libs.append('m') config.add_extension("pairwise_fast", - sources=["pairwise_fast.c"], + sources=["pairwise_fast.pyx"], include_dirs=[os.path.join('..', 'src', 'cblas'), numpy.get_include(), blas_info.pop('include_dirs', [])], diff --git a/sklearn/neighbors/setup.py b/sklearn/neighbors/setup.py index 575b4fce66eedbae3222062ae6b067ea0986e5cb..1180b8c365dfbc68835505ecc556a851862b72f6 100644 --- a/sklearn/neighbors/setup.py +++ b/sklearn/neighbors/setup.py @@ -11,24 +11,24 @@ def configuration(parent_package='', top_path=None): libraries.append('m') config.add_extension('ball_tree', - sources=['ball_tree.c'], + sources=['ball_tree.pyx'], include_dirs=[numpy.get_include()], libraries=libraries) config.add_extension('kd_tree', - sources=['kd_tree.c'], + sources=['kd_tree.pyx'], include_dirs=[numpy.get_include()], libraries=libraries) config.add_extension('dist_metrics', - sources=['dist_metrics.c'], + sources=['dist_metrics.pyx'], include_dirs=[numpy.get_include(), os.path.join(numpy.get_include(), 'numpy')], libraries=libraries) config.add_extension('typedefs', - sources=['typedefs.c'], + sources=['typedefs.pyx'], include_dirs=[numpy.get_include()], libraries=libraries) diff --git a/sklearn/setup.py b/sklearn/setup.py index 5166785159861fcb6e59d07cf807fbb4417b03ec..8adbbd9d49132938a6672d518021ae415c46eeba 100644 --- a/sklearn/setup.py +++ b/sklearn/setup.py @@ -2,6 +2,8 @@ import os from os.path import join import warnings +from sklearn._build_utils import maybe_cythonize_extensions + def configuration(parent_package='', top_path=None): from numpy.distutils.misc_util import Configuration @@ -55,12 +57,11 @@ def configuration(parent_package='', top_path=None): config.add_subpackage('svm') # add cython extension module for isotonic regression - config.add_extension( - '_isotonic', - sources=['_isotonic.c'], - include_dirs=[numpy.get_include()], - libraries=libraries, - ) + config.add_extension('_isotonic', + sources=['_isotonic.pyx'], + include_dirs=[numpy.get_include()], + libraries=libraries, + ) # some libs needs cblas, fortran-compiled BLAS will not be sufficient blas_info = get_info('blas_opt', 0) @@ -78,6 +79,8 @@ def configuration(parent_package='', top_path=None): # add the test directory config.add_subpackage('tests') + maybe_cythonize_extensions(top_path, config) + return config if __name__ == '__main__': diff --git a/sklearn/svm/setup.py b/sklearn/svm/setup.py index 711e868b11eb43befcac47de0eea84acf7e9d6db..399b1a841eb77f9e6defaa556deb6928803cb1e1 100644 --- a/sklearn/svm/setup.py +++ b/sklearn/svm/setup.py @@ -24,7 +24,7 @@ def configuration(parent_package='', top_path=None): extra_link_args=['-lstdc++'], ) - libsvm_sources = ['libsvm.c'] + libsvm_sources = ['libsvm.pyx'] libsvm_depends = [join('src', 'libsvm', 'libsvm_helper.c'), join('src', 'libsvm', 'libsvm_template.cpp'), join('src', 'libsvm', 'svm.cpp'), @@ -38,12 +38,12 @@ def configuration(parent_package='', top_path=None): depends=libsvm_depends, ) - ### liblinear module + # liblinear module cblas_libs, blas_info = get_blas_info() if os.name == 'posix': cblas_libs.append('m') - liblinear_sources = ['liblinear.c', + liblinear_sources = ['liblinear.pyx', join('src', 'liblinear', '*.cpp')] liblinear_depends = [join('src', 'liblinear', '*.h'), @@ -61,10 +61,10 @@ def configuration(parent_package='', top_path=None): # extra_compile_args=['-O0 -fno-inline'], ** blas_info) - ## end liblinear module + # end liblinear module # this should go *after* libsvm-skl - libsvm_sparse_sources = ['libsvm_sparse.c'] + libsvm_sparse_sources = ['libsvm_sparse.pyx'] config.add_extension('libsvm_sparse', libraries=['libsvm-skl'], sources=libsvm_sparse_sources, include_dirs=[numpy.get_include(), diff --git a/sklearn/tree/setup.py b/sklearn/tree/setup.py index 94f61ef8250f4d66c46d09f31fd1904e26205432..079ae9d8690755f4a69aebe1bfb27bdf3b4bac1d 100644 --- a/sklearn/tree/setup.py +++ b/sklearn/tree/setup.py @@ -10,22 +10,22 @@ def configuration(parent_package="", top_path=None): if os.name == 'posix': libraries.append('m') config.add_extension("_tree", - sources=["_tree.c"], + sources=["_tree.pyx"], include_dirs=[numpy.get_include()], libraries=libraries, extra_compile_args=["-O3"]) config.add_extension("_splitter", - sources=["_splitter.c"], + sources=["_splitter.pyx"], include_dirs=[numpy.get_include()], libraries=libraries, extra_compile_args=["-O3"]) config.add_extension("_criterion", - sources=["_criterion.c"], + sources=["_criterion.pyx"], include_dirs=[numpy.get_include()], libraries=libraries, extra_compile_args=["-O3"]) config.add_extension("_utils", - sources=["_utils.c"], + sources=["_utils.pyx"], include_dirs=[numpy.get_include()], libraries=libraries, extra_compile_args=["-O3"]) diff --git a/sklearn/utils/setup.py b/sklearn/utils/setup.py index ad1e3bef814d0ab3a79ab0ce9dcdd42cb446ca43..9590692b0dff0119bdd3b13aed0e35f18575c5a8 100644 --- a/sklearn/utils/setup.py +++ b/sklearn/utils/setup.py @@ -22,11 +22,11 @@ def configuration(parent_package='', top_path=None): libraries.append('m') cblas_libs.append('m') - config.add_extension('sparsefuncs_fast', sources=['sparsefuncs_fast.c'], + config.add_extension('sparsefuncs_fast', sources=['sparsefuncs_fast.pyx'], libraries=libraries) config.add_extension('arrayfuncs', - sources=['arrayfuncs.c'], + sources=['arrayfuncs.pyx'], depends=[join('src', 'cholesky_delete.h')], libraries=cblas_libs, include_dirs=cblas_includes, @@ -34,43 +34,43 @@ def configuration(parent_package='', top_path=None): **blas_info ) - config.add_extension( - 'murmurhash', - sources=['murmurhash.c', join('src', 'MurmurHash3.cpp')], - include_dirs=['src']) + config.add_extension('murmurhash', + sources=['murmurhash.pyx', join( + 'src', 'MurmurHash3.cpp')], + include_dirs=['src']) config.add_extension('lgamma', - sources=['lgamma.c', join('src', 'gamma.c')], + sources=['lgamma.pyx', join('src', 'gamma.c')], include_dirs=['src'], libraries=libraries) config.add_extension('graph_shortest_path', - sources=['graph_shortest_path.c'], + sources=['graph_shortest_path.pyx'], include_dirs=[numpy.get_include()]) config.add_extension('fast_dict', - sources=['fast_dict.cpp'], + sources=['fast_dict.pyx'], language="c++", include_dirs=[numpy.get_include()], libraries=libraries) config.add_extension('seq_dataset', - sources=['seq_dataset.c'], + sources=['seq_dataset.pyx'], include_dirs=[numpy.get_include()]) config.add_extension('weight_vector', - sources=['weight_vector.c'], + sources=['weight_vector.pyx'], include_dirs=cblas_includes, libraries=cblas_libs, **blas_info) config.add_extension("_random", - sources=["_random.c"], + sources=["_random.pyx"], include_dirs=[numpy.get_include()], libraries=libraries) config.add_extension("_logistic_sigmoid", - sources=["_logistic_sigmoid.c"], + sources=["_logistic_sigmoid.pyx"], include_dirs=[numpy.get_include()], libraries=libraries) diff --git a/sklearn/utils/sparsetools/setup.py b/sklearn/utils/sparsetools/setup.py index 9a6082341fced0a1880e60accfb65245962ac5ff..7b5bc33edd1518d9cb7bb4a07fd5a74917264d88 100644 --- a/sklearn/utils/sparsetools/setup.py +++ b/sklearn/utils/sparsetools/setup.py @@ -7,15 +7,11 @@ def configuration(parent_package='', top_path=None): config = Configuration('sparsetools', parent_package, top_path) config.add_extension('_traversal', - sources=['_traversal.c'], - include_dirs=[numpy.get_include()], - #libraries=libraries - ) + sources=['_traversal.pyx'], + include_dirs=[numpy.get_include()]) config.add_extension('_graph_tools', - sources=['_graph_tools.c'], - include_dirs=[numpy.get_include()], - #libraries=libraries - ) + sources=['_graph_tools.pyx'], + include_dirs=[numpy.get_include()]) config.add_subpackage('tests')