From a34274d1222acde0ab9a1abbb043071f57e3108c Mon Sep 17 00:00:00 2001 From: Stefan Appelhoff Date: Thu, 7 Dec 2023 16:08:59 +0100 Subject: [PATCH] Move project config to pyproject.toml, remove BINDER support (#1202) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * move project config to pyproject.toml * remove BINDER support * do not repeat deps in opt deps * organize opt dep subgroups more DRY * need defusedxml for some BrainVision ops * Reformat pyproject.toml with Even better TOML extension https://marketplace.visualstudio.com/items?itemName=tamasfe.even-better-toml * defusedxml only for doc, not proj * ignore .ruff_cache --------- Co-authored-by: Richard Höchenberger --- .circleci/config.yml | 18 ++-- .github/workflows/unit_tests.yml | 12 +-- .gitignore | 1 + CONTRIBUTING.md | 14 +-- MANIFEST.in | 2 +- Makefile | 2 +- doc/conf.py | 23 ---- doc/install.rst | 1 - doc/requirements.txt | 12 --- examples/README.rst | 2 - pyproject.toml | 175 ++++++++++++++++++++++++++++++- setup.cfg | 74 ------------- setup.py | 27 ----- test_requirements.txt | 18 ---- 14 files changed, 189 insertions(+), 192 deletions(-) delete mode 100644 doc/requirements.txt delete mode 100644 setup.py delete mode 100644 test_requirements.txt diff --git a/.circleci/config.yml b/.circleci/config.yml index a67878688..7b249d293 100644 --- a/.circleci/config.yml +++ b/.circleci/config.yml @@ -24,12 +24,12 @@ jobs: # restore cache from last build. Unless __init__.py has changed since then - restore_cache: keys: - - data-cache-5-{{ checksum "./mne_bids/__init__.py" }} + - data-cache-0-{{ checksum "./mne_bids/__init__.py" }} # Also restore pip cache to speed up installations - restore_cache: keys: - - pip-cache-1-{{ checksum "./test_requirements.txt" }}-{{ checksum "./doc/requirements.txt" }} + - pip-cache-0-{{ checksum "./pyproject.toml" }} - run: name: Setup Python3 environment @@ -41,10 +41,8 @@ jobs: name: Install Python packages command: | python -m pip install --upgrade --progress-bar off pip - python -m pip install --upgrade --progress-bar off -r test_requirements.txt - python -m pip install --upgrade --progress-bar off -r doc/requirements.txt python -m pip install --upgrade https://github.com/mne-tools/mne-python/archive/refs/heads/main.zip - python -m pip install -e . + python -m pip install -e .[test,doc] - run: name: Build the documentation @@ -62,13 +60,13 @@ jobs: # Store the data cache - save_cache: - key: data-cache-5-{{ checksum "./mne_bids/__init__.py" }} + key: data-cache-0-{{ checksum "./mne_bids/__init__.py" }} paths: - ~/mne_data # Store pip cache - save_cache: - key: pip-cache-1-{{ checksum "./test_requirements.txt" }}-{{ checksum "./doc/requirements.txt" }} + key: pip-cache-0-{{ checksum "./pyproject.toml" }} paths: - ~/.cache/pip @@ -112,7 +110,7 @@ jobs: - restore_cache: keys: - - pip-cache-1-{{ checksum "./test_requirements.txt" }}-{{ checksum "./doc/requirements.txt" }} + - pip-cache-0-{{ checksum "./pyproject.toml" }} - run: name: Setup Python3 environment @@ -124,10 +122,8 @@ jobs: name: Install Python packages command: | python -m pip install --upgrade --progress-bar off pip - python -m pip install --upgrade --progress-bar off -r test_requirements.txt - python -m pip install --upgrade --progress-bar off -r doc/requirements.txt python -m pip install --upgrade https://github.com/mne-tools/mne-python/archive/refs/heads/main.zip - python -m pip install -e . + python -m pip install -e .[test,doc] - run: name: Check links diff --git a/.github/workflows/unit_tests.yml b/.github/workflows/unit_tests.yml index ba13791c9..ea27b17b1 100644 --- a/.github/workflows/unit_tests.yml +++ b/.github/workflows/unit_tests.yml @@ -9,9 +9,6 @@ on: branches: ['**'] pull_request: branches: ['**'] - create: - branches: [main] - tags: ['**'] schedule: - cron: "0 4 * * *" @@ -32,7 +29,7 @@ jobs: - uses: actions/cache@v3 with: path: ${{ env.pythonLocation }} - key: style-0-${{ env.pythonLocation }}-${{ hashFiles('setup.cfg') }}-${{ hashFiles('test_requirements.txt') }} + key: style-0-${{ env.pythonLocation }}-${{ hashFiles('pyproject.toml') }} - name: Install dependencies run: | python -m pip install --upgrade pip @@ -60,7 +57,7 @@ jobs: - uses: actions/cache@v3 with: path: ${{ env.pythonLocation }} - key: build-2-${{ env.pythonLocation }}-${{ hashFiles('setup.cfg') }}-${{ hashFiles('test_requirements.txt') }} + key: build-0-${{ env.pythonLocation }}-${{ hashFiles('pyproject.toml') }} - name: Install dependencies run: | @@ -177,12 +174,13 @@ jobs: uses: actions/cache@v3 with: path: ${{ env.pythonLocation }} - key: test-1-${{ env.pythonLocation }}-${{ env.os }}-${{ hashFiles('setup.cfg') }}-${{ hashFiles('test_requirements.txt') }} + key: test-0-${{ env.pythonLocation }}-${{ env.os }}-${{ hashFiles('pyproject.toml') }} - name: Install Python dependencies using pip + # This would be nicer once this feature is implemented: https://github.com/pypa/pip/issues/11440 run: | python -m pip install --upgrade pip - python -m pip install --upgrade -r test_requirements.txt + python -m pip install -e .[test] - name: Install MNE (stable) if: matrix.mne-version == 'mne-stable' diff --git a/.gitignore b/.gitignore index 395fbd700..b8d24ce2e 100644 --- a/.gitignore +++ b/.gitignore @@ -6,6 +6,7 @@ build coverage *.xml .venv +.ruff_cache # Sphinx documentation doc/_build/ diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index 875fea757..2099cca54 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -53,24 +53,13 @@ Then, `git clone` your fork and install it in "editable" mode. ```Shell git clone https://github.com//mne-bids cd ./mne-bids -pip install -e .[full] +pip install -e .[dev] git config --local blame.ignoreRevsFile .git-blame-ignore-revs ``` The last command is needed for `git diff` to work properly. You should now have both the `mne` and `mne-bids` development versions available in your Python environment. -### Install additional Python packages required for development - -Navigate to the root of the `mne-bids` repository and call: - -```Shell -pip install -r test_requirements.txt -pip install -r doc/requirements.txt -``` - -This will install several packages for running tests and building the documentation for `mne-bids`. - ### Install the BIDS validator For a complete development setup of `mne-bids`, it is necessary to install the @@ -137,7 +126,6 @@ We suggest installing our git pre-commit hooks to automatically run style checks before a commit is created: ```Shell -pip install pre-commit pre-commit install ``` diff --git a/MANIFEST.in b/MANIFEST.in index 188f5408d..8c5aba9e4 100644 --- a/MANIFEST.in +++ b/MANIFEST.in @@ -29,5 +29,5 @@ exclude Makefile exclude CONTRIBUTING.md exclude *.yml exclude .mailmap -exclude test_requirements.txt exclude .gitignore +exclude .pre-commit-config.yaml diff --git a/Makefile b/Makefile index c3deb90f9..ebf9ab0e1 100755 --- a/Makefile +++ b/Makefile @@ -32,7 +32,7 @@ test: --doctest-modules \ --cov=mne_bids mne_bids/tests/ mne_bids/commands/tests/ \ --cov-report=xml \ - --cov-config=setup.cfg \ + --cov-config=pyproject.toml \ --verbose \ --ignore mne-python \ --ignore examples diff --git a/doc/conf.py b/doc/conf.py index e1b003df8..3bf2f4e76 100644 --- a/doc/conf.py +++ b/doc/conf.py @@ -172,17 +172,6 @@ } intersphinx_timeout = 5 -# Resolve binder filepath_prefix. From the docs: -# "A prefix to append to the filepath in the Binder links. You should use this -# if you will store your built documentation in a sub-folder of a repository, -# instead of in the root." -# we will store dev docs in a `dev` subdirectory and all other docs in a -# directory "v" + version_str. E.g., "v0.3" -if "dev" in version: - filepath_prefix = "dev" -else: - filepath_prefix = "v{}".format(version) - sphinx_gallery_conf = { "doc_module": "mne_bids", "reference_url": { @@ -193,16 +182,4 @@ "within_subsection_order": ExampleTitleSortKey, "gallery_dirs": "auto_examples", "filename_pattern": "^((?!sgskip).)*$", - "binder": { - # Required keys - "org": "mne-tools", - "repo": "mne-bids", - "branch": "gh-pages", # noqa: E501 Can be any branch, tag, or commit hash. Use a branch that hosts your docs. - "binderhub_url": "https://mybinder.org", # noqa: E501 Any URL of a binderhub deployment. Must be full URL (e.g. https://mybinder.org). - "filepath_prefix": filepath_prefix, # noqa: E501 A prefix to prepend to any filepaths in Binder links. - "dependencies": [ - "../test_requirements.txt", - "./requirements.txt", - ], - }, } diff --git a/doc/install.rst b/doc/install.rst index a433819d8..90d2e22b1 100644 --- a/doc/install.rst +++ b/doc/install.rst @@ -27,7 +27,6 @@ Optional: * ``EDFlib-Python`` (>=1.0.6, for writing EDF data with ``mne`` versions <1.7) * ``edfio`` (>=0.2.1, for writing EDF data) - We recommend installing ``mne-bids`` into an isolated Python environment, for example created via ``conda`` (may be obtained through `miniconda `_). diff --git a/doc/requirements.txt b/doc/requirements.txt deleted file mode 100644 index ec8f884a2..000000000 --- a/doc/requirements.txt +++ /dev/null @@ -1,12 +0,0 @@ -nilearn -sphinx -sphinx_gallery -sphinx-copybutton -pydata-sphinx-theme -numpydoc -matplotlib -pillow -pandas -https://github.com/mne-tools/mne-nirs/archive/refs/heads/main.zip -seaborn -openneuro-py diff --git a/examples/README.rst b/examples/README.rst index 79c74ee84..8456cf64e 100644 --- a/examples/README.rst +++ b/examples/README.rst @@ -2,7 +2,5 @@ Examples -------- The following examples demonstrate some common use-cases of MNE-BIDS. -Each example has a badge called "Binder" at the end. By clicking on that badge, -you can interactively run the examples in your browser. The examples are loosely ordered from basic to more advanced use cases. diff --git a/pyproject.toml b/pyproject.toml index a2ea6d3be..60f33f355 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -1,3 +1,110 @@ +[build-system] +requires = ["setuptools", "wheel"] +build-backend = "setuptools.build_meta" + +[project] +name = "mne-bids" +description = "MNE-BIDS: Organizing MEG, EEG, and iEEG data according to the BIDS specification and facilitating their analysis with MNE-Python" +dynamic = ["version"] +authors = [{ name = "MNE-BIDS Developers" }] +maintainers = [ + { name = "Stefan Appelhoff", email = "stefan.appelhoff@mailbox.org" }, +] +license = { text = "BSD-3-Clause" } +readme = { file = "README.md", content-type = "text/markdown" } +requires-python = ">=3.9" +keywords = [ + "meg", + "eeg", + "ieeg", + "bids", + "brain imaging data structure", + "neuroscience", + "neuroimaging", +] +classifiers = [ + "Topic :: Scientific/Engineering", + "Intended Audience :: Science/Research", + "Intended Audience :: Developers", + "License :: OSI Approved", + "Topic :: Software Development", + "Topic :: Scientific/Engineering", + "Operating System :: Microsoft :: Windows", + "Operating System :: POSIX :: Linux", + "Operating System :: MacOS", + "Programming Language :: Python", + "Programming Language :: Python :: 3.9", + "Programming Language :: Python :: 3.10", + "Programming Language :: Python :: 3.11", + "Programming Language :: Python :: 3.12", +] +scripts = { mne_bids = "mne_bids.commands.run:main" } +dependencies = ["mne>=1.5", "numpy>=1.21.2", "scipy>=1.7.1"] +[project.optional-dependencies] +# Variants with dependencies that will get installed on top of those listed unter +# project.dependencies + +# Dependencies for using all mne_bids features +full = [ + "nibabel >= 3.2.1", + "pybv >= 0.7.5", + "eeglabio >= 0.0.2", + "pymatreader >= 0.0.30", + "matplotlib >= 3.5.0", + "pandas >= 1.3.2", + "EDFlib-Python >= 1.0.6", # drop once mne <1.7 is no longer supported + "edfio >= 0.2.1", +] + +# Dependencies for running the test infrastructure +test = [ + "mne_bids[full]", + "pytest", + "pytest-cov", + "pytest-sugar", + "check-manifest", + "pydocstyle", + "flake8", + "black", +] + +# Dependencies for building the documentation +doc = [ + "nilearn", + "sphinx", + "sphinx_gallery", + "sphinx-copybutton", + "pydata-sphinx-theme", + "numpydoc", + "matplotlib", + "pillow", + "pandas", + "mne-nirs @ https://github.com/mne-tools/mne-nirs/archive/refs/heads/main.zip", + "seaborn", + "openneuro-py", + "defusedxml", # for reading BrainVision montages: `examples/convert_eeg_to_bids.py` +] + +# Dependencies for developer installations +dev = ["mne_bids[test,doc,full]", "pre-commit"] + +[project.urls] +"Homepage" = "https://mne.tools/mne-bids" +"Download" = "https://pypi.org/project/mne-bids/#files" +"Bug Tracker" = "https://github.com/mne-tools/mne-bids/issues/" +"Documentation" = "https://mne.tools/mne-bids" +"Forum" = "https://mne.discourse.group/" +"Source Code" = "https://github.com/mne-tools/mne-bids" + +[tool.setuptools.packages.find] +where = ["."] +include = ["mne_bids"] +exclude = ["tests"] +namespaces = false + +[tool.setuptools.dynamic] +version = { attr = "mne_bids.__version__" } + [tool.ruff] select = ["E", "F", "W", "D"] exclude = ["__init__.py"] @@ -8,5 +115,69 @@ convention = "numpy" [tool.black] exclude = "(dist/)|(build/)|(.*\\.ipynb)" -[tool.check-manifest] -ignore = [".pre-commit-config.yaml"] +[tool.coverage.run] +omit = ["*tests*"] + +[tool.coverage.report] +# Regexes for lines to exclude from consideration +exclude_lines = ["pragma: no cover", "if 0:", "if __name__ == .__main__.:"] + +[tool.isort] +skip_glob = "*/*" + +[tool.pydocstyle] +convention = "pep257" +match_dir = "^(?!\\.|doc|examples).*$" +add-ignore = ["D100", "D104", "D107", "D413"] +add-select = [ + "D214", + "D215", + "D404", + "D405", + "D406", + "D407", + "D408", + "D409", + "D410", + "D411", +] +ignore-decorators = "property" + +[tool.flake8] +max-line-length = 88 +exclude = "__init__.py" +ignore = ["I101", "I100", "I201"] +extend-ignore = ["W503", "E203"] +per-file-ignores = [ + "mne_bids/commands/tests/test_*.py:E402", + "mne_bids/tests/test_*.py:E402", +] + +[tool.pytest] +addopts = """--durations=20 -ra --junit-xml=junit-results.xml --tb=short + --ignore=doc --ignore=examples --ignore=mne_bids/tests/data""" +filterwarnings = [ + "error", + "ignore:Estimation of line frequency only supports.*:RuntimeWarning", + "ignore:There are channels without locations (n/a)*:RuntimeWarning", + "ignore:Did not find any electrodes.tsv.*:RuntimeWarning", + "ignore:Did not find any coordsystem.json.*:RuntimeWarning", + "ignore:Did not find any events.tsv.*:RuntimeWarning", + "ignore:No events found or provided.*:RuntimeWarning", + "ignore:Participants file not found for.*:RuntimeWarning", + "ignore:Converting to FIF for anonymization:RuntimeWarning", + "ignore:Converting to BV for anonymization:RuntimeWarning", + "ignore:Converting data files to BrainVision format:RuntimeWarning", + "ignore:Writing of electrodes.tsv is not supported for datatype.*:RuntimeWarning", + "ignore:numpy.ufunc size changed.*:RuntimeWarning", + "ignore:tostring\\(\\) is deprecated.*:DeprecationWarning", + "ignore:MEG ref channel RMSP did not.*:RuntimeWarning", + "ignore:`product` is deprecated as of NumPy.*:DeprecationWarning", + # Python 3.10+ and NumPy 1.22 (and maybe also newer NumPy versions?) + "ignore:.*distutils\\.sysconfig module is deprecated.*:DeprecationWarning", + # numba with NumPy dev + "ignore:`np.MachAr` is deprecated.*:DeprecationWarning", + # old MNE _fake_click + "ignore:The .*_event function was deprecated in Matplotlib.*:", + "ignore:datetime\\.datetime\\.utcfromtimestamp.* is deprecated and scheduled for removal in a future version.*:DeprecationWarning", +] diff --git a/setup.cfg b/setup.cfg index 8971178c2..f4781fc8a 100644 --- a/setup.cfg +++ b/setup.cfg @@ -1,60 +1,3 @@ -[metadata] -name = mne-bids -url = https://github.com/mne-tools/mne-bids -author = mne-bids developers -maintainer = Stefan Appelhoff -maintainer_email = stefan.appelhoff@mailbox.org -description = MNE-BIDS: Organizing MEG, EEG, and iEEG data according to the BIDS specification and facilitating their analysis with MNE-Python -keywords = meg, eeg, ieeg, bids, brain imaging data structure, neuroscience, neuroimaging -long_description = file: README.md -long_description_content_type = text/markdown; charset=UTF-8 -license = BSD-3-Clause -license_files = LICENSE -platforms = any -classifiers = - Topic :: Scientific/Engineering - Intended Audience :: Science/Research - Intended Audience :: Developers - License :: OSI Approved - Topic :: Software Development - Topic :: Scientific/Engineering - Operating System :: Microsoft :: Windows - Operating System :: POSIX :: Linux - Operating System :: MacOS - Programming Language :: Python - Programming Language :: Python :: 3.9 - Programming Language :: Python :: 3.10 - Programming Language :: Python :: 3.11 - Programming Language :: Python :: 3.12 -project_urls = - Documentation = https://mne.tools/mne-bids - Bug Reports = https://github.com/mne-tools/mne-bids/issues - Source = https://github.com/mne-tools/mne-bids - -[options] -python_requires = ~= 3.9 -install_requires = - mne >= 1.5 - numpy >= 1.21.2 - scipy >= 1.7.1 -packages = find: -include_package_data = True - -[options.extras_require] -full = - nibabel >= 3.2.1 - pybv >= 0.7.5 - eeglabio >= 0.0.2 - pymatreader >= 0.0.30 - matplotlib >= 3.5.0 - pandas >= 1.3.2 - EDFlib-Python >= 1.0.6 # drop once mne <1.7 is no longer supported - edfio >= 0.2.1 - -[options.entry_points] -console_scripts = - mne_bids = mne_bids.commands.run:main - [flake8] max-line-length = 88 exclude = __init__.py @@ -99,20 +42,3 @@ match_dir = ^(?!\.|doc|examples).*$ add-ignore = D100,D104,D107,D413 add-select = D214,D215,D404,D405,D406,D407,D408,D409,D410,D411 ignore-decorators = property - -[coverage:run] -omit = - # Do not include test script in coverage report - *tests* - -[coverage:report] -# Regexes for lines to exclude from consideration -exclude_lines = - # Have to re-enable the standard pragma - pragma: no cover - - # Don't complain if non-runnable code isn't run: - if __name__ == .__main__.: - -[isort] -skip_glob = */* diff --git a/setup.py b/setup.py deleted file mode 100644 index 9d8038fff..000000000 --- a/setup.py +++ /dev/null @@ -1,27 +0,0 @@ -"""Setup MNE-BIDS.""" -import os -import sys - -from setuptools import setup - -# Give setuptools a hint to complain if it's too old a version -SETUP_REQUIRES = ["setuptools >= 46.4.0"] -# This enables setuptools to install wheel on-the-fly -SETUP_REQUIRES += ["wheel"] if "bdist_wheel" in sys.argv else [] - -version = None -with open(os.path.join("mne_bids", "__init__.py"), "r") as fid: - for line in fid: - line = line.strip() - if line.startswith("__version__ = "): - version = line.split(" = ")[1].split("#")[0].strip('"') - break -if version is None: - raise RuntimeError("Could not determine version") - - -if __name__ == "__main__": - setup( - version=version, - setup_requires=SETUP_REQUIRES, - ) diff --git a/test_requirements.txt b/test_requirements.txt deleted file mode 100644 index 759c2abf5..000000000 --- a/test_requirements.txt +++ /dev/null @@ -1,18 +0,0 @@ -mne>=1.5 -numpy>=1.21.2 -scipy>=1.7.1 -nibabel>=3.2.1 -pybv>=0.7.5 -eeglabio>=0.0.2 -pymatreader>=0.0.30 -matplotlib>=3.5.0 -pandas>=1.3.2 -EDFlib-Python>=1.0.6 # drop once mne <1.7 is no longer supported -edfio >= 0.2.1 -pytest -pytest-cov -pytest-sugar -check-manifest -pydocstyle -flake8 -black