[project]
name = "jax-sklearn"
version = "0.1.0"
description = "JAX-accelerated machine learning library with scikit-learn compatibility"
readme = "README.md"
maintainers = [
    {name = "XLearn developers", email="xlearn@python.org"},
]
dependencies = [
  "numpy>=1.22.0",
  "scipy>=1.8.0",
  "joblib>=1.2.0",
  "threadpoolctl>=3.1.0",
  "jax>=0.4.20",
  "jaxlib>=0.4.20",
]
requires-python = ">=3.10"
license = "BSD-3-Clause"
license-files = ["COPYING"]
classifiers=[
  "Intended Audience :: Science/Research",
  "Intended Audience :: Developers",
  "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.10",
  "Programming Language :: Python :: 3.11",
  "Programming Language :: Python :: 3.12",
  "Programming Language :: Python :: 3.13",
  "Programming Language :: Python :: Implementation :: CPython",
]

[project.urls]
homepage = "https://jax-sklearn.org"
source = "https://github.com/chenxingqiang/jax-sklearn"
download = "https://pypi.org/project/jax-sklearn/#files"
tracker = "https://github.com/chenxingqiang/jax-sklearn/issues"
"release notes" = "https://jax-sklearn.org/stable/whats_new"

[project.optional-dependencies]
build = ["numpy>=1.22.0", "scipy>=1.8.0", "cython>=3.0.10", "meson-python>=0.17.1"]
install = ["numpy>=1.22.0", "scipy>=1.8.0", "joblib>=1.2.0", "threadpoolctl>=3.1.0", "jax>=0.4.20", "jaxlib>=0.4.20"]
jax = ["jax>=0.4.20", "jaxlib>=0.4.20"]
jax-cpu = ["jax[cpu]>=0.4.20"]
jax-gpu = ["jax[gpu]>=0.4.20"]
benchmark = ["matplotlib>=3.5.0", "pandas>=1.4.0", "memory_profiler>=0.57.0"]
docs = [
    "matplotlib>=3.5.0",
    "scikit-image>=0.19.0",
    "pandas>=1.4.0",
    "seaborn>=0.9.0",
    "memory_profiler>=0.57.0",
    "sphinx>=7.3.7",
    "sphinx-copybutton>=0.5.2",
    "sphinx-gallery>=0.17.1",
    "numpydoc>=1.2.0",
    "Pillow>=8.4.0",
    "pooch>=1.6.0",
    "sphinx-prompt>=1.4.0",
    "sphinxext-opengraph>=0.9.1",
    "plotly>=5.14.0",
    "polars>=0.20.30",
    "sphinx-design>=0.5.0",
    "sphinx-design>=0.6.0",
    "sphinxcontrib-sass>=0.3.4",
    "pydata-sphinx-theme>=0.15.3",
    "sphinx-remove-toctrees>=1.0.0.post1",
    "towncrier>=24.8.0",
]
examples = [
    "matplotlib>=3.5.0",
    "scikit-image>=0.19.0",
    "pandas>=1.4.0",
    "seaborn>=0.9.0",
    "pooch>=1.6.0",
    "plotly>=5.14.0",
]
tests = [
    "matplotlib>=3.5.0",
    "scikit-image>=0.19.0",
    "pandas>=1.4.0",
    "pytest>=7.1.2",
    "pytest-cov>=2.9.0",
    "ruff>=0.11.7",
    "mypy>=1.15",
    "pyamg>=4.2.1",
    "polars>=0.20.30",
    "pyarrow>=12.0.0",
    "numpydoc>=1.2.0",
    "pooch>=1.6.0",
]
maintenance = ["conda-lock==3.0.1"]

[build-system]
build-backend = "mesonpy"
# Minimum requirements for the build system to execute.
requires = [
    "meson-python>=0.16.0,<0.19.0",
    "Cython>=3.0.10,<3.2.0",
    "numpy>=2,<2.3.0",
    "scipy>=1.8.0,<1.16.0",
]

[tool.pytest.ini_options]
doctest_optionflags = "NORMALIZE_WHITESPACE ELLIPSIS"
testpaths = "xlearn"
addopts = [
    "--disable-pytest-warnings",
    "--color=yes",
    "--import-mode=importlib",
]

[tool.ruff]
line-length = 88
exclude=[
    ".eggs",
    ".git",
    ".mypy_cache",
    ".vscode",
    "__pycache__",
    "build",
    "dist",
    "xlearn/externals",
    "doc/_build",
    "doc/auto_examples",
    "asv_benchmarks/env",
    "asv_benchmarks/html",
    "asv_benchmarks/results",
    "asv_benchmarks/benchmarks/cache",
]

[tool.ruff.lint]
# This enables us to use CPY001: copyright header check
preview = true
# This enables us to use the explicit preview rules that we want only
explicit-preview-rules = true
# all rules can be found here: https://docs.astral.sh/ruff/rules/
extend-select = ["E501", "W", "I", "CPY001", "PGH", "RUF"]
ignore=[
    # do not assign a lambda expression, use a def
    "E731",
    # do not use variables named 'l', 'O', or 'I'
    "E741",
    # E721 gives many false positives.
    # Use `is` and `is not` for type comparisons, or `isinstance()` for
    # isinstance checks
    "E721",
    # We don't care much about F841.
    # Local variable ... is assigned to but never used
    "F841",
    # some RUF rules trigger too many changes
    "RUF002",
    "RUF003",
    "RUF005",
    "RUF012",
    "RUF015",
    "RUF021",
    # https://docs.astral.sh/ruff/formatter/#conflicting-lint-rules
    "W191",
    "E111",
    "E114",
    "E117",
    "D206",
    "D300",
    "Q000",
    "Q001",
    "Q002",
    "Q003",
    "COM812",
    "COM819",
]

[tool.ruff.lint.flake8-copyright]
notice-rgx = "\\#\\ Authors:\\ The\\ scikit\\-learn\\ developers\\\r?\\\n\\#\\ SPDX\\-License\\-Identifier:\\ BSD\\-3\\-Clause"

[tool.ruff.lint.per-file-ignores]
# It's fine not to put the import at the top of the file in the examples
# folder.
"examples/*"=["E402"]
"doc/conf.py"=["E402"]
"**/tests/*"=["CPY001"]
"asv_benchmarks/*"=["CPY001"]
"benchmarks/*"=["CPY001"]
"doc/*"=["CPY001"]
"build_tools/*"=["CPY001"]
"xlearn/_build_utils/*"=["CPY001"]
"maint_tools/*"=["CPY001"]
".spin/*"=["CPY001"]
".github/*"=["CPY001"]
# __doc__ is too long (>4096 chars) and therefore false positive on copyright check
"examples/model_selection/plot_precision_recall.py"=["CPY001"]
"examples/svm/plot_rbf_parameters.py"=["CPY001"]
# __all__ has un-imported names
"xlearn/__init__.py"=["F822"]
"xlearn/utils/_metadata_requests.py"=["CPY001"]

[tool.mypy]
ignore_missing_imports = true
allow_redefinition = true
exclude = "^xlearn/externals"

[[tool.mypy.overrides]]
module = ["joblib.*", "xlearn.externals.*"]
follow_imports = "skip"

[tool.cython-lint]
# Ignore the same error codes as ruff
# + E501 (line too long) because keeping it < 88 in cython
# often makes code less readable.
ignore = [
    # multiple spaces/tab after comma
    'E24',
    # line too long
    'E501',
    # do not assign a lambda expression, use a def
    'E731',
    # do not use variables named 'l', 'O', or 'I'
    'E741',
    # line break before binary operator
    'W503',
    # line break after binary operator
    'W504',
]
# Exclude files are generated from tempita templates
exclude= '''
(
    asv_benchmarks/
  | xlearn/_loss/_loss.pyx
  | xlearn/linear_model/_sag_fast.pyx
  | xlearn/linear_model/_sgd_fast.pyx
  | xlearn/utils/_seq_dataset.pyx
  | xlearn/utils/_seq_dataset.pxd
  | xlearn/utils/_weight_vector.pyx
  | xlearn/utils/_weight_vector.pxd
  | xlearn/metrics/_dist_metrics.pyx
  | xlearn/metrics/_dist_metrics.pxd
  | xlearn/metrics/_pairwise_distances_reduction/_argkmin.pxd
  | xlearn/metrics/_pairwise_distances_reduction/_argkmin.pyx
  | xlearn/metrics/_pairwise_distances_reduction/_argkmin_classmode.pyx
  | xlearn/metrics/_pairwise_distances_reduction/_base.pxd
  | xlearn/metrics/_pairwise_distances_reduction/_base.pyx
  | xlearn/metrics/_pairwise_distances_reduction/_datasets_pair.pxd
  | xlearn/metrics/_pairwise_distances_reduction/_datasets_pair.pyx
  | xlearn/metrics/_pairwise_distances_reduction/_middle_term_computer.pxd
  | xlearn/metrics/_pairwise_distances_reduction/_middle_term_computer.pyx
  | xlearn/metrics/_pairwise_distances_reduction/_radius_neighbors.pxd
  | xlearn/metrics/_pairwise_distances_reduction/_radius_neighbors.pyx
)
'''

[tool.check-sdist]
# These settings should match .gitattributes
sdist-only = []
git-only = [".*", "asv_benchmarks", "azure-pipelines.yml", "benchmarks", "build_tools", "maint_tools"]
default-ignore = false

[tool.spin]
package = "xlearn"  # name of your package

[tool.spin.commands]
"Build" = [
  "spin.cmds.pip.install",
  "spin.cmds.meson.test",
  ".spin/cmds.py:clean",
]
"Documentation" = [
  "spin.cmds.meson.docs"
]

[tool.changelog-bot]
    [tool.changelog-bot.towncrier_changelog]
        enabled = true
        verify_pr_number = true
        changelog_noop_label = "No Changelog Needed"
        whatsnew_pattern = 'doc/whatsnew/upcoming_changes/[^/]+/\d+\.[^.]+\.rst'

[tool.codespell]
skip = ["./.git", "*.svg", "./.mypy_cache", "./xlearn/feature_extraction/_stop_words.py", "./xlearn/feature_extraction/tests/test_text.py", "./build_tools/wheels/LICENSE_windows.txt", "./doc/_build", "./doc/auto_examples", "./doc/modules/generated"]
ignore-words = "build_tools/codespell_ignore_words.txt"

[tool.towncrier]
    package = "xlearn"
    filename = "doc/whats_new/v1.7.rst"
    single_file = true
    directory = "doc/whats_new/upcoming_changes"
    issue_format = ":pr:`{issue}`"
    template = "doc/whats_new/upcoming_changes/towncrier_template.rst.jinja2"
    all_bullets = false

    [[tool.towncrier.type]]
        directory = "major-feature"
        name = "|MajorFeature|"
        showcontent = true

    [[tool.towncrier.type]]
        directory = "feature"
        name = "|Feature|"
        showcontent = true

    [[tool.towncrier.type]]
        directory = "efficiency"
        name = "|Efficiency|"
        showcontent = true

    [[tool.towncrier.type]]
        directory = "enhancement"
        name = "|Enhancement|"
        showcontent = true

    [[tool.towncrier.type]]
        directory = "fix"
        name = "|Fix|"
        showcontent = true

    [[tool.towncrier.type]]
        directory = "api"
        name = "|API|"
        showcontent = true

    [[tool.towncrier.type]]
        directory = "other"
        name = ""
        showcontent = true

    [[tool.towncrier.section]]
        name = "Security"
        path = "security"

    [[tool.towncrier.section]]
        name = "Changed models"
        path = "changed-models"

    [[tool.towncrier.section]]
        name = "Changes impacting many modules"
        path = "many-modules"

    [[tool.towncrier.section]]
        name = "Support for Array API"
        path = "array-api"

    [[tool.towncrier.section]]
        name = "Metadata routing"
        path = "metadata-routing"

    [[tool.towncrier.section]]
        name = "custom-top-level"
        path = "custom-top-level"

    [[tool.towncrier.section]]
        name = ":mod:`xlearn.base`"
        path = "xlearn.base"

    [[tool.towncrier.section]]
        name = ":mod:`xlearn.calibration`"
        path = "xlearn.calibration"

    [[tool.towncrier.section]]
        name = ":mod:`xlearn.cluster`"
        path = "xlearn.cluster"

    [[tool.towncrier.section]]
        name = ":mod:`xlearn.compose`"
        path = "xlearn.compose"

    [[tool.towncrier.section]]
        name = ":mod:`xlearn.covariance`"
        path = "xlearn.covariance"

    [[tool.towncrier.section]]
        name = ":mod:`xlearn.cross_decomposition`"
        path = "xlearn.cross_decomposition"

    [[tool.towncrier.section]]
        name = ":mod:`xlearn.datasets`"
        path = "xlearn.datasets"

    [[tool.towncrier.section]]
        name = ":mod:`xlearn.decomposition`"
        path = "xlearn.decomposition"

    [[tool.towncrier.section]]
        name = ":mod:`xlearn.discriminant_analysis`"
        path = "xlearn.discriminant_analysis"

    [[tool.towncrier.section]]
        name = ":mod:`xlearn.dummy`"
        path = "xlearn.dummy"

    [[tool.towncrier.section]]
        name = ":mod:`xlearn.ensemble`"
        path = "xlearn.ensemble"

    [[tool.towncrier.section]]
        name = ":mod:`xlearn.exceptions`"
        path = "xlearn.exceptions"

    [[tool.towncrier.section]]
        name = ":mod:`xlearn.feature_extraction`"
        path = "xlearn.feature_extraction"

    [[tool.towncrier.section]]
        name = ":mod:`xlearn.feature_selection`"
        path = "xlearn.feature_selection"

    [[tool.towncrier.section]]
        name = ":mod:`xlearn.frozen`"
        path = "xlearn.frozen"

    [[tool.towncrier.section]]
        name = ":mod:`xlearn.gaussian_process`"
        path = "xlearn.gaussian_process"

    [[tool.towncrier.section]]
        name = ":mod:`xlearn.impute`"
        path = "xlearn.impute"

    [[tool.towncrier.section]]
        name = ":mod:`xlearn.inspection`"
        path = "xlearn.inspection"

    [[tool.towncrier.section]]
        name = ":mod:`xlearn.isotonic`"
        path = "xlearn.isotonic"

    [[tool.towncrier.section]]
        name = ":mod:`xlearn.kernel_approximation`"
        path = "xlearn.kernel_approximation"

    [[tool.towncrier.section]]
        name = ":mod:`xlearn.kernel_ridge`"
        path = "xlearn.kernel_ridge"

    [[tool.towncrier.section]]
        name = ":mod:`xlearn.linear_model`"
        path = "xlearn.linear_model"

    [[tool.towncrier.section]]
        name = ":mod:`xlearn.manifold`"
        path = "xlearn.manifold"

    [[tool.towncrier.section]]
        name = ":mod:`xlearn.metrics`"
        path = "xlearn.metrics"

    [[tool.towncrier.section]]
        name = ":mod:`xlearn.mixture`"
        path = "xlearn.mixture"

    [[tool.towncrier.section]]
        name = ":mod:`xlearn.model_selection`"
        path = "xlearn.model_selection"

    [[tool.towncrier.section]]
        name = ":mod:`xlearn.multiclass`"
        path = "xlearn.multiclass"

    [[tool.towncrier.section]]
        name = ":mod:`xlearn.multioutput`"
        path = "xlearn.multioutput"

    [[tool.towncrier.section]]
        name = ":mod:`xlearn.naive_bayes`"
        path = "xlearn.naive_bayes"

    [[tool.towncrier.section]]
        name = ":mod:`xlearn.neighbors`"
        path = "xlearn.neighbors"

    [[tool.towncrier.section]]
        name = ":mod:`xlearn.neural_network`"
        path = "xlearn.neural_network"

    [[tool.towncrier.section]]
        name = ":mod:`xlearn.pipeline`"
        path = "xlearn.pipeline"

    [[tool.towncrier.section]]
        name = ":mod:`xlearn.preprocessing`"
        path = "xlearn.preprocessing"

    [[tool.towncrier.section]]
        name = ":mod:`xlearn.random_projection`"
        path = "xlearn.random_projection"

    [[tool.towncrier.section]]
        name = ":mod:`xlearn.semi_supervised`"
        path = "xlearn.semi_supervised"

    [[tool.towncrier.section]]
        name = ":mod:`xlearn.svm`"
        path = "xlearn.svm"

    [[tool.towncrier.section]]
        name = ":mod:`xlearn.tree`"
        path = "xlearn.tree"

    [[tool.towncrier.section]]
        name = ":mod:`xlearn.utils`"
        path = "xlearn.utils"
