Repository URL to install this package:
|
Version:
1.1.3 ▾
|
scikit-learn
/
setup.py
|
|---|
#! /usr/bin/env python
#
# Copyright (C) 2007-2009 Cournapeau David <cournape@gmail.com>
# 2010 Fabian Pedregosa <fabian.pedregosa@inria.fr>
# License: 3-clause BSD
import sys
import os
import platform
import shutil
# We need to import setuptools before because it monkey-patches distutils
import setuptools # noqa
from distutils.command.clean import clean as Clean
from distutils.command.sdist import sdist
import traceback
import importlib
try:
import builtins
except ImportError:
# Python 2 compat: just to be able to declare that Python >=3.8 is needed.
import __builtin__ as builtins
# This is a bit (!) hackish: we are setting a global variable so that the
# main sklearn __init__ can detect if it is being loaded by the setup
# routine, to avoid attempting to load components that aren't built yet:
# the numpy distutils extensions that are used by scikit-learn to
# recursively build the compiled extensions in sub-packages is based on the
# Python import machinery.
builtins.__SKLEARN_SETUP__ = True
DISTNAME = "scikit-learn"
DESCRIPTION = "A set of python modules for machine learning and data mining"
with open("README.rst") as f:
LONG_DESCRIPTION = f.read()
MAINTAINER = "Andreas Mueller"
MAINTAINER_EMAIL = "amueller@ais.uni-bonn.de"
URL = "http://scikit-learn.org"
DOWNLOAD_URL = "https://pypi.org/project/scikit-learn/#files"
LICENSE = "new BSD"
PROJECT_URLS = {
"Bug Tracker": "https://github.com/scikit-learn/scikit-learn/issues",
"Documentation": "https://scikit-learn.org/stable/documentation.html",
"Source Code": "https://github.com/scikit-learn/scikit-learn",
}
# We can actually import a restricted version of sklearn that
# does not need the compiled code
import sklearn # noqa
import sklearn._min_dependencies as min_deps # noqa
from sklearn.externals._packaging.version import parse as parse_version # noqa
VERSION = sklearn.__version__
# For some commands, use setuptools
SETUPTOOLS_COMMANDS = {
"develop",
"release",
"bdist_egg",
"bdist_rpm",
"bdist_wininst",
"install_egg_info",
"build_sphinx",
"egg_info",
"easy_install",
"upload",
"bdist_wheel",
"--single-version-externally-managed",
}
if SETUPTOOLS_COMMANDS.intersection(sys.argv):
extra_setuptools_args = dict(
zip_safe=False, # the package can run out of an .egg file
include_package_data=True,
extras_require={
key: min_deps.tag_to_packages[key]
for key in ["examples", "docs", "tests", "benchmark"]
},
)
else:
extra_setuptools_args = dict()
# Custom clean command to remove build artifacts
class CleanCommand(Clean):
description = "Remove build artifacts from the source tree"
def run(self):
Clean.run(self)
# Remove c files if we are not within a sdist package
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:
print("Will remove generated .c files")
if os.path.exists("build"):
shutil.rmtree("build")
for dirpath, dirnames, filenames in os.walk("sklearn"):
for filename in filenames:
if any(
filename.endswith(suffix)
for suffix in (".so", ".pyd", ".dll", ".pyc")
):
os.unlink(os.path.join(dirpath, filename))
continue
extension = os.path.splitext(filename)[1]
if remove_c_files and extension in [".c", ".cpp"]:
pyx_file = str.replace(filename, extension, ".pyx")
if os.path.exists(os.path.join(dirpath, pyx_file)):
os.unlink(os.path.join(dirpath, filename))
for dirname in dirnames:
if dirname == "__pycache__":
shutil.rmtree(os.path.join(dirpath, dirname))
cmdclass = {"clean": CleanCommand, "sdist": sdist}
# Custom build_ext command to set OpenMP compile flags depending on os and
# compiler. Also makes it possible to set the parallelism level via
# and environment variable (useful for the wheel building CI).
# build_ext has to be imported after setuptools
try:
from numpy.distutils.command.build_ext import build_ext # noqa
class build_ext_subclass(build_ext):
def finalize_options(self):
super().finalize_options()
if self.parallel is None:
# Do not override self.parallel if already defined by
# command-line flag (--parallel or -j)
parallel = os.environ.get("SKLEARN_BUILD_PARALLEL")
if parallel:
self.parallel = int(parallel)
if self.parallel:
print("setting parallel=%d " % self.parallel)
def build_extensions(self):
from sklearn._build_utils.openmp_helpers import get_openmp_flag
if sklearn._OPENMP_SUPPORTED:
openmp_flag = get_openmp_flag(self.compiler)
for e in self.extensions:
e.extra_compile_args += openmp_flag
e.extra_link_args += openmp_flag
build_ext.build_extensions(self)
cmdclass["build_ext"] = build_ext_subclass
except ImportError:
# Numpy should not be a dependency just to be able to introspect
# that python 3.8 is required.
pass
def configuration(parent_package="", top_path=None):
if os.path.exists("MANIFEST"):
os.remove("MANIFEST")
from numpy.distutils.misc_util import Configuration
from sklearn._build_utils import _check_cython_version
config = Configuration(None, parent_package, top_path)
# Avoid useless msg:
# "Ignoring attempt to set 'name' (from ... "
config.set_options(
ignore_setup_xxx_py=True,
assume_default_configuration=True,
delegate_options_to_subpackages=True,
quiet=True,
)
# Cython is required by config.add_subpackage for templated extensions
# that need the tempita sub-submodule. So check that we have the correct
# version of Cython so as to be able to raise a more informative error
# message from the start if it's not the case.
_check_cython_version()
config.add_subpackage("sklearn")
return config
def check_package_status(package, min_version):
"""
Returns a dictionary containing a boolean specifying whether given package
is up-to-date, along with the version string (empty string if
not installed).
"""
package_status = {}
try:
module = importlib.import_module(package)
package_version = module.__version__
package_status["up_to_date"] = parse_version(package_version) >= parse_version(
min_version
)
package_status["version"] = package_version
except ImportError:
traceback.print_exc()
package_status["up_to_date"] = False
package_status["version"] = ""
req_str = "scikit-learn requires {} >= {}.\n".format(package, min_version)
instructions = (
"Installation instructions are available on the "
"scikit-learn website: "
"http://scikit-learn.org/stable/install.html\n"
)
if package_status["up_to_date"] is False:
if package_status["version"]:
raise ImportError(
"Your installation of {} {} is out-of-date.\n{}{}".format(
package, package_status["version"], req_str, instructions
)
)
else:
raise ImportError(
"{} is not installed.\n{}{}".format(package, req_str, instructions)
)
def setup_package():
# TODO: Require Python 3.8 for PyPy when PyPy3.8 is ready
# https://github.com/conda-forge/conda-forge-pinning-feedstock/issues/2089
if platform.python_implementation() == "PyPy":
python_requires = ">=3.7"
required_python_version = (3, 7)
else:
python_requires = ">=3.8"
required_python_version = (3, 8)
metadata = dict(
name=DISTNAME,
maintainer=MAINTAINER,
maintainer_email=MAINTAINER_EMAIL,
description=DESCRIPTION,
license=LICENSE,
url=URL,
download_url=DOWNLOAD_URL,
project_urls=PROJECT_URLS,
version=VERSION,
long_description=LONG_DESCRIPTION,
classifiers=[
"Intended Audience :: Science/Research",
"Intended Audience :: Developers",
"License :: OSI Approved :: BSD License",
"Programming Language :: C",
"Programming Language :: Python",
"Topic :: Software Development",
"Topic :: Scientific/Engineering",
"Development Status :: 5 - Production/Stable",
"Operating System :: Microsoft :: Windows",
"Operating System :: POSIX",
"Operating System :: Unix",
"Operating System :: MacOS",
"Programming Language :: Python :: 3",
"Programming Language :: Python :: 3.8",
"Programming Language :: Python :: 3.9",
"Programming Language :: Python :: 3.10",
"Programming Language :: Python :: 3.11",
"Programming Language :: Python :: Implementation :: CPython",
"Programming Language :: Python :: Implementation :: PyPy",
],
cmdclass=cmdclass,
python_requires=python_requires,
install_requires=min_deps.tag_to_packages["install"],
package_data={"": ["*.pxd"]},
**extra_setuptools_args,
)
commands = [arg for arg in sys.argv[1:] if not arg.startswith("-")]
if all(
command in ("egg_info", "dist_info", "clean", "check") for command in commands
):
# These actions are required to succeed without Numpy for example when
# pip is used to install Scikit-learn when Numpy is not yet present in
# the system.
# These commands use setup from setuptools
from setuptools import setup
metadata["version"] = VERSION
metadata["packages"] = ["sklearn"]
else:
if sys.version_info < required_python_version:
required_version = "%d.%d" % required_python_version
raise RuntimeError(
"Scikit-learn requires Python %s or later. The current"
" Python version is %s installed in %s."
% (required_version, platform.python_version(), sys.executable)
)
check_package_status("numpy", min_deps.NUMPY_MIN_VERSION)
check_package_status("scipy", min_deps.SCIPY_MIN_VERSION)
# These commands require the setup from numpy.distutils because they
# may use numpy.distutils compiler classes.
from numpy.distutils.core import setup
# Monkeypatches CCompiler.spawn to prevent random wheel build errors on Windows
# The build errors on Windows was because msvccompiler spawn was not threadsafe
# This fixed can be removed when we build with numpy >= 1.22.2 on Windows.
# https://github.com/pypa/distutils/issues/5
# https://github.com/scikit-learn/scikit-learn/issues/22310
# https://github.com/numpy/numpy/pull/20640
from numpy.distutils.ccompiler import replace_method
from distutils.ccompiler import CCompiler
from sklearn.externals._numpy_compiler_patch import CCompiler_spawn
replace_method(CCompiler, "spawn", CCompiler_spawn)
metadata["configuration"] = configuration
setup(**metadata)
if __name__ == "__main__":
setup_package()