366 lines
11 KiB
TOML
366 lines
11 KiB
TOML
[build-system]
|
|
# Note for maintainers: this numpy constraint is specific to wheels for PyPI. See:
|
|
# https://numpy.org/doc/stable/dev/depending_on_numpy.html#numpy-2-abi-handling
|
|
requires = [
|
|
"scikit-build-core>=0.10.0",
|
|
"setuptools-scm>=8.0",
|
|
"numpy>=2.0",
|
|
"packaging>20.9",
|
|
"nanobind>=2.0.0",
|
|
]
|
|
build-backend = "scikit_build_core.build"
|
|
|
|
[project]
|
|
name = "shap"
|
|
description = "A unified approach to explain the output of any machine learning model."
|
|
readme = "README.md"
|
|
license = {text = "MIT License"}
|
|
authors = [
|
|
{name = "Scott Lundberg", email = "slund1@cs.washington.edu"},
|
|
]
|
|
requires-python = ">=3.12"
|
|
dependencies = [
|
|
'numpy>=2',
|
|
'scipy',
|
|
'scikit-learn',
|
|
'pandas',
|
|
'tqdm>=4.27.0',
|
|
'packaging>20.9',
|
|
'slicer==0.0.8',
|
|
'numba<0.63; sys_platform == "darwin" and platform_machine == "x86_64"', # numba 0.63+ dropped macOS x86_64 wheels, see numba/numba#10187
|
|
'numba; sys_platform != "darwin" or platform_machine != "x86_64"',
|
|
'llvmlite<0.46; sys_platform == "darwin" and platform_machine == "x86_64"', # llvmlite 0.46+ dropped macOS x86_64 wheels, see numba/numba#10187
|
|
'llvmlite; sys_platform != "darwin" or platform_machine != "x86_64"',
|
|
'cloudpickle',
|
|
]
|
|
classifiers = [
|
|
"Operating System :: Microsoft :: Windows",
|
|
"Operating System :: POSIX",
|
|
"Operating System :: Unix",
|
|
"Operating System :: MacOS",
|
|
"Programming Language :: Python :: 3.12",
|
|
"Programming Language :: Python :: 3.13",
|
|
"Programming Language :: Python :: 3.14",
|
|
"Intended Audience :: Information Technology",
|
|
"Intended Audience :: Science/Research",
|
|
"Topic :: Scientific/Engineering",
|
|
"Topic :: Scientific/Engineering :: Artificial Intelligence",
|
|
"Development Status :: 5 - Production/Stable",
|
|
"License :: OSI Approved :: MIT License",
|
|
]
|
|
dynamic = ["version"]
|
|
|
|
|
|
[dependency-groups]
|
|
plots = ["matplotlib", "ipython"]
|
|
download-datasets = [
|
|
# Dependencies needed to download datasets for testing
|
|
# scikit-learn is already in core dependencies, but listed here for clarity
|
|
"scikit-learn",
|
|
]
|
|
docs = [
|
|
{include-group = "plots"},
|
|
"numpydoc",
|
|
"sphinx_rtd_theme",
|
|
"sphinx",
|
|
"nbsphinx",
|
|
"sphinx_github_changelog",
|
|
"myst-parser",
|
|
"requests",
|
|
"ipywidgets", # For tqdm in notebooks
|
|
]
|
|
test-core = [
|
|
"pytest",
|
|
"pytest-mpl",
|
|
"pytest-cov",
|
|
"mypy",
|
|
"pre-commit",
|
|
"ruff",
|
|
]
|
|
test = [
|
|
{include-group = "test-core"},
|
|
"xgboost",
|
|
"lightgbm",
|
|
'catboost; python_version < "3.14"', # TODO: pending 3.14 support
|
|
'gpboost==1.6.3.1; python_version < "3.14"', # TODO: pending 3.14 support, see GH #4210
|
|
"ngboost",
|
|
"pyspark",
|
|
"pyod",
|
|
"transformers < 4.54.0", # TODO: fix once tests pass for 4.54.0
|
|
"tf-keras",
|
|
"protobuf", # See GH #3046
|
|
'torch<=2.11.0; python_version < "3.14"', # TODO: pending 3.14 support, see GH #5016
|
|
'torchvision; python_version < "3.14"', # TODO: pending 3.14 support
|
|
'tensorflow; python_version < "3.14"', # TODO: pending 3.14 support
|
|
"sentencepiece",
|
|
"opencv-python",
|
|
# Constraint to prevent the combination of tf<2.15 and numpy>=2.0.
|
|
# See GH #3707, #3768, 3922
|
|
"numpy>=2.0",
|
|
"causalml>=0.15.5",
|
|
# causalml imports private sklearn.ensemble._forest internals (DOUBLE, DTYPE, MAX_INT)
|
|
# that were removed in scikit-learn 1.9. See https://github.com/uber/causalml/issues/926
|
|
"scikit-learn<1.9",
|
|
"selenium", # needed to test the javascript based plots
|
|
]
|
|
nbtest = [
|
|
"jupyter",
|
|
"nbconvert",
|
|
"nbformat",
|
|
"nlp",
|
|
"transformers",
|
|
"datasets",
|
|
"keras",
|
|
"nbtest-plugin",
|
|
"nbtest-gen",
|
|
"nbtest-lab-extension"
|
|
]
|
|
|
|
[project.urls]
|
|
Repository = 'http://github.com/shap/shap'
|
|
Documentation = 'https://shap.readthedocs.io/en/latest/index.html'
|
|
"Release Notes" = 'https://shap.readthedocs.io/en/latest/release_notes.html'
|
|
|
|
[tool.uv]
|
|
cache-keys = [
|
|
{ file = "shap/cext/*.cc" },
|
|
{ file = "shap/cext/*.cu" },
|
|
{ file = "shap/cext/*.h" },
|
|
{ file = "shap/cutils/*.cpp" },
|
|
{ file = "shap/cutils/*.h" },
|
|
{ file = "CMakeLists.txt" },
|
|
]
|
|
|
|
[tool.mypy]
|
|
check_untyped_defs = true
|
|
disallow_untyped_calls = false
|
|
disallow_untyped_defs = false
|
|
disallow_incomplete_defs = false
|
|
exclude = ["shap/benchmark/*", "tests/benchmark/*", "shap/_cutils.pyi"]
|
|
|
|
# NOTE: numpy.typing.mypy_plugin is deprecated in NumPy 2.3+ and will be removed in a future release
|
|
# plugins = ["numpy.typing.mypy_plugin"]
|
|
|
|
[[tool.mypy.overrides]]
|
|
# Disable some checks from certain shap modules
|
|
# TODO: get these passing!
|
|
# NOTE: Modules with added type hints have been removed from this list
|
|
module = [
|
|
# "shap.explainers._additive", # NOW TYPE CHECKED - type hints added
|
|
"shap.explainers._deep.deep_pytorch",
|
|
"shap.explainers._deep.deep_tf",
|
|
# "shap.explainers._exact", # NOW TYPE CHECKED - type hints added
|
|
# "shap.explainers._explainer", # NOW TYPE CHECKED - type hints added
|
|
# "shap.explainers._gradient", # NOW TYPE CHECKED - type hints added
|
|
# "shap.explainers._kernel", # NOW TYPE CHECKED - type hints added
|
|
# "shap.explainers._linear", # NOW TYPE CHECKED - type hints added
|
|
# "shap.explainers._partition", # NOW TYPE CHECKED - type hints added
|
|
# "shap.explainers._permutation", # NOW TYPE CHECKED - type hints added
|
|
# "shap.explainers._sampling", # NOW TYPE CHECKED - type hints added
|
|
# "shap.explainers._tree", # NOW TYPE CHECKED - type hints added
|
|
# "shap.explainers._coalition", # NOW TYPE CHECKED - type hints added
|
|
# "shap.explainers.other._random", # NOW TYPE CHECKED - type hints added
|
|
"shap.explainers.pytree",
|
|
"shap.explainers.tf_utils",
|
|
# "shap.maskers._composite", # NOW TYPE CHECKED - type hints added
|
|
# "shap.maskers._fixed", # NOW TYPE CHECKED - type hints added
|
|
"shap.maskers._image",
|
|
# "shap.maskers._masker", # NOW TYPE CHECKED - type hints added
|
|
"shap.maskers._tabular",
|
|
"shap.maskers._text",
|
|
"shap.plots._benchmark",
|
|
"shap.plots._force_matplotlib",
|
|
"shap.plots._force",
|
|
"shap.plots._text",
|
|
"shap.plots._waterfall",
|
|
]
|
|
check_untyped_defs = false
|
|
|
|
[[tool.mypy.overrides]]
|
|
# Ignore missing types for 3rd party libraries
|
|
module = [
|
|
"catboost.*",
|
|
"cloudpickle",
|
|
"cv2",
|
|
"IPython.*",
|
|
"lightgbm.*",
|
|
"lime.*",
|
|
"numba",
|
|
"pandas",
|
|
"pyod.*",
|
|
"pyspark.*",
|
|
"scipy.*",
|
|
"sklearn.*",
|
|
"slicer",
|
|
"tensorflow.*",
|
|
"transformers.*",
|
|
"torch.*",
|
|
"tqdm.*",
|
|
"xgboost.*",
|
|
"causalml.*",
|
|
"selenium.*",
|
|
]
|
|
ignore_missing_imports = true
|
|
|
|
[tool.setuptools_scm]
|
|
version_file = "shap/_version.py"
|
|
# Use "no-local-version" so dev releases are compatibile with PyPI
|
|
local_scheme = "no-local-version"
|
|
|
|
[tool.scikit-build]
|
|
# List of packages to include in the wheel
|
|
wheel.packages = [
|
|
'shap',
|
|
'shap.cext',
|
|
'shap.explainers',
|
|
'shap.explainers.other',
|
|
'shap.explainers._deep',
|
|
'shap.plots',
|
|
'shap.plots.colors',
|
|
'shap.plots.resources',
|
|
'shap.benchmark',
|
|
'shap.maskers',
|
|
'shap.utils',
|
|
'shap.actions',
|
|
'shap.models',
|
|
]
|
|
|
|
metadata.version.provider = "scikit_build_core.metadata.setuptools_scm"
|
|
sdist.include = ["shap/_version.py"]
|
|
sdist.exclude = ["docs/", "notebooks/", ".claude/", "appveyor/"]
|
|
|
|
# Protect the configuration against future changes in scikit-build-core
|
|
minimum-version = "build-system.requires"
|
|
|
|
# Setuptools-style build caching in a local directory
|
|
build-dir = "build/{wheel_tag}"
|
|
|
|
# Exclude C/C++/CUDA source files from the wheel (compiled .so is sufficient)
|
|
wheel.exclude = ["**/*.cc", "**/*.cpp", "**/*.h", "**/*.cu"]
|
|
|
|
# Build stable ABI wheels for CPython 3.12+
|
|
wheel.py-api = "cp312"
|
|
|
|
|
|
[tool.pytest.ini_options]
|
|
addopts = "--mpl -m 'not xslow'"
|
|
mpl-default-style = "default"
|
|
testpaths = ["tests"]
|
|
filterwarnings = [
|
|
# Ignore warnings that are entirely from 3rd party libs outside our control
|
|
"ignore:.*distutils Version classes are deprecated.*:DeprecationWarning:.*pandas.*",
|
|
"ignore:.*typing.io is deprecated.*:DeprecationWarning:.*pyspark.*",
|
|
"ignore:.*is_datetime64tz_dtype is deprecated.*:DeprecationWarning:.*pyspark.*",
|
|
"ignore:.*'force_all_finite' was renamed to 'ensure_all_finite' in 1.6.*:FutureWarning:.*sklearn.*",
|
|
]
|
|
markers = ["xslow: mark test as extremely slow (not run unless explicitly requested)"]
|
|
|
|
[tool.ruff]
|
|
# Careful: when running on pre-commit, ruff's "include" and "exclude" config
|
|
# options are ignored! So, instead of "exclude", use the "per-file-ignores"
|
|
# config to always disable linting for specific files.
|
|
include = ["*.py", "*.pyi", "**/pyproject.toml", "*.ipynb"]
|
|
extend-exclude = ["**/tree_shap_paper/**", "docs/user_studies/*"]
|
|
line-length = 120
|
|
|
|
[tool.ruff.lint]
|
|
select = [
|
|
"F", # pyflakes
|
|
"I", # isort
|
|
"ISC", # string literal concatenation.
|
|
"UP", # pyupgrade
|
|
"E", # pycodestyle
|
|
"W", # warning
|
|
"D", # pydocstyle
|
|
"NPY", # Numpy
|
|
"SIM101", # flake8-simplify
|
|
"FA", # future annotations
|
|
"TCH", # Move type only imports to type-checking condition.
|
|
# D417 # undocumented parameter. FIXME: get this passing
|
|
]
|
|
ignore = [
|
|
# Recommended rules to disable when using ruff formatter:
|
|
# https://docs.astral.sh/ruff/formatter/#conflicting-lint-rules
|
|
"D206",
|
|
"D300",
|
|
"E111",
|
|
"E114",
|
|
"E117",
|
|
"E501",
|
|
"W191",
|
|
|
|
# pydocstyle issues not yet fixed
|
|
"D100", # Missing docstring in public module
|
|
"D101", # Missing docstring in public class
|
|
"D102", # Missing docstring in public method
|
|
"D103", # Missing docstring in public function
|
|
"D104", # Missing docstring in public package
|
|
"D105", # Missing docstring in magic method
|
|
"D205", # 1 blank line required between summary line and description
|
|
"D400", # First line should end with a period
|
|
"D401", # First line of docstring should be in imperative mood: "A basic partial dependence plot function."
|
|
"D404", # First word of the docstring should not be "This"
|
|
"NPY002", # Allow numpy RandomState objects in tests
|
|
]
|
|
|
|
[tool.ruff.lint.pydocstyle]
|
|
convention = "numpy"
|
|
|
|
[tool.ruff.lint.per-file-ignores]
|
|
# Don't apply linting/formatting to vendored code
|
|
"shap/explainers/other/_maple.py" = ["ALL"]
|
|
|
|
# Ignore notebooks in user_studies, which are not maintained
|
|
"docs/user_studies/*.ipynb" = ["ALL"]
|
|
|
|
# Ignore SHAP Paper, as it is an unmaintained record of a published paper
|
|
"notebooks/tabular_examples/tree_based_models/tree_shap_paper/*" = ["ALL"]
|
|
|
|
# Disable some unwanted rules on Jupyter notebooks
|
|
"*.ipynb" = ["D", "E703", "E402"] # Allow trailing semicolons, allow imports not at top
|
|
|
|
# Ignore pycodestyle in tests
|
|
"tests/*py" = ["D"]
|
|
|
|
[tool.coverage.run]
|
|
source_pkgs = ["shap"]
|
|
omit = ["shap/benchmark/*"]
|
|
|
|
[tool.coverage.paths]
|
|
combine = ["shap", "*/site-packages/shap"]
|
|
|
|
[tool.cibuildwheel]
|
|
# TODO: Should we use uv as build frontend for faster builds?
|
|
# build-frontend = "uv"
|
|
|
|
# Restrict the set of builds to mirror the wheels available in scipy. See #3028
|
|
# skip cp314-macosx_x86_64 due to lack of numba and llvmlite support
|
|
# skip *t (free-threaded builds) since dependencies like llvmlite don't support it yet
|
|
skip = [
|
|
"cp314-macosx_x86_64",
|
|
"cp314t-manylinux_x86_64",
|
|
"cp314t-macosx_x86_64",
|
|
"cp314t-win_amd64",
|
|
]
|
|
build-verbosity = 2
|
|
# Change import-mode to ensure we test against installed package, not local project
|
|
test-command = "pytest -v {project}/tests --import-mode=append"
|
|
test-groups = ["test-core", "plots"]
|
|
# skip tests on *-musllinux*" since llvmlite and numba do not provide musllinux wheels
|
|
test-skip = "*-musllinux*"
|
|
|
|
[tool.cibuildwheel.linux]
|
|
archs = ["x86_64", "aarch64"]
|
|
|
|
[tool.cibuildwheel.windows]
|
|
# TODO: Should we support Windows ARM64 too?
|
|
archs = ["AMD64"]
|
|
|
|
[tool.cibuildwheel.macos]
|
|
# TODO: Should we build universal2 wheels for macOS to reduce wheel count?
|
|
archs = ["x86_64", "arm64"]
|
|
|
|
[tool.cibuildwheel.macos.environment]
|
|
# Needed for C++17 support
|
|
MACOSX_DEPLOYMENT_TARGET = "10.13"
|