[build-system]
build-backend = "hatchling.build"
requires = ["hatch-vcs", "hatchling"]
[project]
authors = [
{email = "alexandre.gramfort@inria.fr", name = "Alexandre Gramfort"},
]
classifiers = [
"Intended Audience :: Developers",
"Intended Audience :: Science/Research",
"License :: OSI Approved",
"Operating System :: MacOS",
"Operating System :: Microsoft :: Windows",
"Operating System :: POSIX",
"Operating System :: Unix",
"Programming Language :: Python :: 3",
"Programming Language :: Python",
"Topic :: Scientific/Engineering",
"Topic :: Software Development",
]
dependencies = [
"decorator",
"jinja2",
"lazy_loader >= 0.3",
"matplotlib >= 3.7", # 2023/02/13
"numpy >= 1.25,<3", # 2023/06/17
"packaging",
"pooch >= 1.5",
"scipy >= 1.11", # 2023/06/25
"tqdm",
]
description = "MNE-Python project for MEG and EEG data analysis."
dynamic = ["version"]
keywords = [
"brain",
"ECoG",
"EEG",
"fNIRS",
"MEG",
"neuroimaging",
"neuroscience",
]
license = {text = "BSD-3-Clause"}
maintainers = [{email = "dan@mccloy.info", name = "Dan McCloy"}]
name = "mne"
readme = {content-type = "text/x-rst", file = "README.rst"}
requires-python = ">= 3.10"
scripts = {mne = "mne.commands.utils:main"}
[project.optional-dependencies]
# Leave this one here for backward-compat
data = []
dev = ["mne[doc,test]", "rcssmin"]
# Dependencies for building the documentation
doc = [
"graphviz",
"intersphinx_registry >= 0.2405.27",
"ipython != 8.7.0", # also in "full-no-qt" and "test"
"memory_profiler",
"mne-bids",
"mne-connectivity",
"mne-gui-addons",
"neo",
"numpydoc",
"openneuro-py",
"psutil",
"pydata_sphinx_theme >= 0.15.2",
"pygments >= 2.13",
"pytest",
"pyxdf",
"pyzmq != 24.0.0",
"seaborn != 0.11.2",
"selenium >= 4.27.1",
"sphinx >= 6",
"sphinx-design",
"sphinx-gallery >= 0.16",
"sphinx_copybutton",
"sphinxcontrib-bibtex >= 2.5",
"sphinxcontrib-towncrier >=0.5.0a0",
"sphinxcontrib-youtube",
]
full = ["mne[full-no-qt]", "PyQt6 != 6.6.0", "PyQt6-Qt6 != 6.6.0, != 6.7.0"]
# Dependencies for full MNE-Python functionality (other than raw/epochs export)
# We first define a variant without any Qt bindings. The "complete" variant, mne[full],
# makes an opinionated choice and installs PyQt6.
# We also offter two more variants: mne[full-qt6] (which is equivalent to mne[full]),
# and mne[full-pyside6], which will install PySide6 instead of PyQt6.
full-no-qt = [
"antio >= 0.5.0",
"darkdetect",
"defusedxml",
"dipy",
"edfio >= 0.2.1",
"eeglabio",
"h5py",
"imageio >= 2.6.1",
"imageio-ffmpeg >= 0.4.1",
"ipyevents",
"ipympl",
"ipython != 8.7.0", # for notebook backend; also in "doc" and "test"
"ipywidgets",
"joblib",
"jupyter",
"mffpy >= 0.5.7",
"mne-qt-browser",
"mne[hdf5]",
"neo",
"nibabel",
"nilearn",
"numba",
"openmeeg >= 2.5.5",
"pandas >= 2.0", # 2023/04/03
"pillow", # for `Brain.save_image` and `mne.Report`
"pyarrow", # only needed to avoid a deprecation warning in pandas
"pybv",
"pyobjc-framework-Cocoa >= 5.2.0; platform_system == 'Darwin'",
"python-picard",
"pyvista >= 0.32, != 0.35.2, != 0.38.0, != 0.38.1, != 0.38.2, != 0.38.3, != 0.38.4, != 0.38.5, != 0.38.6, != 0.42.0",
"pyvistaqt >= 0.4",
"qdarkstyle != 3.2.2",
"qtpy",
"scikit-learn",
"sip",
"snirf",
"statsmodels",
"threadpoolctl",
"traitlets",
"trame",
"trame-vtk",
"trame-vuetify",
"vtk >= 9.2",
"xlrd",
]
full-pyqt6 = ["mne[full]"]
full-pyside6 = ["mne[full-no-qt]", "PySide6 != 6.7.0, != 6.8.0, != 6.8.0.1"]
# Dependencies for MNE-Python functions that use HDF5 I/O
hdf5 = ["h5io >= 0.2.4", "pymatreader"]
# Dependencies for running the test infrastructure
test = [
"codespell",
"ipython != 8.7.0", # for testing notebook backend; also in "full-no-qt" and "doc"
"mypy",
"numpydoc",
"pre-commit",
"pytest >= 8.0",
"pytest-cov",
"pytest-qt",
"pytest-timeout",
"ruff",
"toml-sort",
"tomli; python_version<'3.11'",
"twine",
"vulture",
"wheel",
]
# Dependencies for being able to run additional tests (rare/CIs/advanced devs)
# Changes here should be reflected in the mne/utils/config.py dev dependencies section
test_extra = [
"edfio >= 0.2.1",
"eeglabio",
"imageio >= 2.6.1",
"imageio-ffmpeg >= 0.4.1",
"jupyter_client",
"mne-bids",
"mne[test]",
"nbclient",
"nbformat",
"neo",
"nitime",
"pybv",
"snirf",
"sphinx-gallery",
"statsmodels",
]
[project.urls]
"Bug Tracker" = "https://github.com/mne-tools/mne-python/issues/"
Documentation = "https://mne.tools/"
Download = "https://pypi.org/project/mne/#files"
Forum = "https://mne.discourse.group/"
Homepage = "https://mne.tools/"
"Source Code" = "https://github.com/mne-tools/mne-python/"
[tool.bandit.assert_used]
skips = ["*/test_*.py"] # assert statements are good practice with pytest
[tool.changelog-bot]
[tool.changelog-bot.towncrier_changelog]
changelog_skip_label = "no-changelog-entry-needed"
enabled = true
verify_pr_number = true
[tool.codespell]
builtin = "clear,rare,informal,names,usage"
ignore-words = "ignore_words.txt"
skip = "doc/references.bib"
[tool.hatch.build]
exclude = [
"/*.toml",
"/*.txt",
"/*.yaml",
"/*.yml",
"/.*",
"/CITATION.cff",
"/codemeta.json",
"/CONTRIBUTING.md",
"/doc",
"/examples",
"/ignore_words.txt",
"/logo",
"/Makefile",
"/mne/**/tests",
"/tools",
"/tutorials",
] # tracked by git, but we don't want to ship those files
[tool.hatch.version]
raw-options = {version_scheme = "release-branch-semver"}
source = "vcs"
[tool.mypy]
# Avoid the conflict between mne/__init__.py and mne/__init__.pyi by ignoring the former
exclude = '^mne/(beamformer|channels|commands|datasets|decoding|export|forward|gui|html_templates|inverse_sparse|io|minimum_norm|preprocessing|report|simulation|source_space|stats|time_frequency|utils|viz)?/?__init__\.py$'
ignore_errors = true
modules = ["mne"]
scripts_are_modules = true
strict = false
[[tool.mypy.overrides]]
ignore_missing_imports = true
module = ['scipy.*']
[[tool.mypy.overrides]]
# Ignore "attr-defined" until we fix stuff like:
# - BunchConstNamed: '"BunchConstNamed" has no attribute "FIFFB_EVOKED"'
# - Missing __all__: 'Module "mne.io.snirf" does not explicitly export attribute "read_raw_snirf"'
# Ignore "no-untyped-call" until we fix stuff like:
# - 'Call to untyped function "end_block" in typed context'
# Ignore "no-untyped-def" until we fix stuff like:
# - 'Function is missing a type annotation'
# Ignore "misc" until we fix stuff like:
# - 'Cannot determine type of "_projector" in base class "ProjMixin"'
# Ignore "assignment" until we fix stuff like:
# - 'Incompatible types in assignment (expression has type "tuple[str, ...]", variable has type "str")'
# Ignore "operator" until we fix stuff like:
# - Unsupported operand types for - ("None" and "int")
disable_error_code = [
'assignment',
'attr-defined',
'misc',
'no-untyped-call',
'no-untyped-def',
'operator',
]
ignore_errors = false
module = ['mne.annotations', 'mne.epochs', 'mne.evoked', 'mne.io']
[tool.pytest.ini_options]
# -r f (failed), E (error), s (skipped), x (xfail), X (xpassed), w (warnings)
# don't put in xfail for pytest 8.0+ because then it prints the tracebacks,
# which look like real errors
addopts = """--durations=20 --doctest-modules -rfEXs --cov-report= --tb=short \
--cov-branch --doctest-ignore-import-errors --junit-xml=junit-results.xml \
--ignore=doc --ignore=logo --ignore=examples --ignore=tutorials \
--ignore=mne/gui/_*.py --ignore=mne/icons --ignore=tools \
--ignore=mne/report/js_and_css \
--color=yes --capture=sys"""
[tool.rstcheck]
ignore_directives = [
"autoclass",
"autofunction",
"automodule",
"autosummary",
"bibliography",
"card",
"cssclass",
"currentmodule",
"dropdown",
"footbibliography",
"glossary",
"graphviz",
"grid",
"highlight",
"minigallery",
"related-software",
"rst-class",
"tab-set",
"tabularcolumns",
"toctree",
"towncrier-draft-entries",
]
ignore_messages = "^.*(Unknown target name|Undefined substitution referenced)[^`]*$"
ignore_roles = [
"attr",
"bdg-info-line",
"bdg-primary-line",
"class",
"doc",
"eq",
"exc",
"file",
"footcite",
"footcite:t",
"func",
"gh",
"kbd",
"meth",
"mod",
"newcontrib",
"py:mod",
"ref",
"samp",
"term",
]
report_level = "WARNING"
[tool.ruff]
exclude = ["__init__.py", "constants.py", "resources.py"]
[tool.ruff.lint]
ignore = [
"D100", # Missing docstring in public module
"D104", # Missing docstring in public package
"D413", # Missing blank line after last section
]
select = ["A", "B006", "D", "E", "F", "I", "UP", "UP031", "W"]
[tool.ruff.lint.per-file-ignores]
"examples/*/*.py" = [
"D205", # 1 blank line required between summary line and description
"D400", # First line should end with a period
]
"examples/preprocessing/eeg_bridging.py" = [
"E501", # line too long
]
"mne/__init__.pyi" = [
"A004", # Import *** is shadowing a Python builtin
]
"mne/datasets/*/*.py" = [
"D103", # Missing docstring in public function
]
"mne/decoding/tests/test_*.py" = [
"E402", # Module level import not at top of file
]
"mne/utils/tests/test_docs.py" = [
"D101", # Missing docstring in public class
"D410", # Missing blank line after section
"D411", # Missing blank line before section
"D414", # Section has no content
]
"tutorials/*/*.py" = [
"D400", # First line should end with a period
]
"tutorials/time-freq/10_spectrum_class.py" = [
"E501", # line too long
]
[tool.ruff.lint.pydocstyle]
convention = "numpy"
ignore-decorators = [
"mne.utils.copy_doc",
"mne.utils.copy_function_doc_to_method_doc",
"mne.utils.deprecated",
"property",
"setter",
]
[tool.tomlsort]
all = true
ignore_case = true
spaces_before_inline_comment = 2
trailing_comma_inline_array = true
[tool.towncrier]
directory = "doc/changes/devel/"
filename = "doc/changes/devel.rst"
issue_format = "`#{issue} <https://github.com/mne-tools/mne-python/pull/{issue}>`__"
package = "mne"
title_format = "{version} ({project_date})"
[[tool.towncrier.type]]
directory = "notable"
name = "Notable changes"
showcontent = true
[[tool.towncrier.type]]
directory = "dependency"
name = "Dependencies"
showcontent = true
[[tool.towncrier.type]]
directory = "bugfix"
name = "Bugfixes"
showcontent = true
[[tool.towncrier.type]]
directory = "apichange"
name = "API changes by deprecation"
showcontent = true
[[tool.towncrier.type]]
directory = "newfeature"
name = "New features"
showcontent = true
[[tool.towncrier.type]]
directory = "other"
name = "Other changes"
showcontent = true
[tool.vulture]
exclude = [
'conftest.py',
'constants.py',
'mne/viz/backends/_abstract.py',
'mne/viz/backends/_notebook.py',
'mne/viz/backends/_qt.py',
]
ignore_decorators = ['@observe']
min_confidence = 60
paths = ['mne', 'tools/vulture_allowlist.py']
verbose = false