mne-tools / mne-python

MNE: Magnetoencephalography (MEG) and Electroencephalography (EEG) in Python
https://mne.tools
BSD 3-Clause "New" or "Revised" License
2.72k stars 1.32k forks source link

`mne` depends on `setuptools` without declaring it as a dependecy, which can break build backends other than `setuptools` #11448

Closed aplzr closed 1 year ago

aplzr commented 1 year ago

Description of the problem

Without declaring setuptools as a dependency, mne imports pkg_resources, which is a part of setuptools, in at least one place:

File "/tmp/pip-build-env-t3o1ln7x/normal/lib/python3.9/site-packages/mne/datasets/eegbci/eegbci.py", line 8, in <module>
          import pkg_resources

In my case this leads to the following problem: I have written a package that depends on mne and that I package with flit, i.e. my package is fully independent of setuptools. When I try to install my package (with the flit_core build backend instead of setuptools) I get the following error:

pip install .[test]
Processing /home/pzr
  Installing build dependencies ... done
  Getting requirements to build wheel ... done
  Installing backend dependencies ... done
  Preparing metadata (pyproject.toml) ... error
  error: subprocess-exited-with-error

  × Preparing metadata (pyproject.toml) did not run successfully.
  │ exit code: 1
  ╰─> [38 lines of output]
      Unexpected names under [project]: requires_python
      [pyhelpers] SSL verification check: SSL verification failed.
      [pyhelpers] Adding FhG certificate bundle to the certificate store.
      [pyhelpers] Checking again: SSL verification works, continuing.
      Traceback (most recent call last):
        File "/usr/local/lib/python3.9/site-packages/pip/_vendor/pep517/in_process/_in_process.py", line 363, in <module>
          main()
        File "/usr/local/lib/python3.9/site-packages/pip/_vendor/pep517/in_process/_in_process.py", line 345, in main
          json_out['return_val'] = hook(**hook_input['kwargs'])
        File "/usr/local/lib/python3.9/site-packages/pip/_vendor/pep517/in_process/_in_process.py", line 164, in prepare_metadata_for_build_wheel
          return hook(metadata_directory, config_settings)
        File "/tmp/pip-build-env-t3o1ln7x/overlay/lib/python3.9/site-packages/flit_core/buildapi.py", line 49, in prepare_metadata_for_build_wheel
          metadata = make_metadata(module, ini_info)
        File "/tmp/pip-build-env-t3o1ln7x/overlay/lib/python3.9/site-packages/flit_core/common.py", line 410, in make_metadata
          md_dict.update(get_info_from_module(module, ini_info.dynamic_metadata))
        File "/tmp/pip-build-env-t3o1ln7x/overlay/lib/python3.9/site-packages/flit_core/common.py", line 207, in get_info_from_module
          docstring, version = get_docstring_and_version_via_import(target)
        File "/tmp/pip-build-env-t3o1ln7x/overlay/lib/python3.9/site-packages/flit_core/common.py", line 180, in get_docstring_and_version_via_import
          spec.loader.exec_module(m)
        File "<frozen importlib._bootstrap_external>", line 850, in exec_module
        File "<frozen importlib._bootstrap>", line 228, in _call_with_frames_removed
        File "/home/pzr/src/pyhelpers/__init__.py", line 3, in <module>
          from . import constants, fileio, neuro, plotting, sigproc, string
        File "/home/pzr/src/pyhelpers/sigproc/__init__.py", line 1, in <module>
          from . import eeg
        File "/home/pzr/src/pyhelpers/sigproc/eeg/__init__.py", line 1, in <module>
          from ._eeg import (create_eeg_raw_array, drop_channels, filter_eeg,
        File "/home/pzr/src/pyhelpers/sigproc/eeg/_eeg.py", line 4, in <module>
          from mne import create_info
        File "/tmp/pip-build-env-t3o1ln7x/normal/lib/python3.9/site-packages/mne/__init__.py", line 111, in <module>
          from . import datasets
        File "/tmp/pip-build-env-t3o1ln7x/normal/lib/python3.9/site-packages/mne/datasets/__init__.py", line 10, in <module>
          from . import eegbci
        File "/tmp/pip-build-env-t3o1ln7x/normal/lib/python3.9/site-packages/mne/datasets/eegbci/__init__.py", line 3, in <module>
          from .eegbci import data_path, load_data, standardize
        File "/tmp/pip-build-env-t3o1ln7x/normal/lib/python3.9/site-packages/mne/datasets/eegbci/eegbci.py", line 8, in <module>
          import pkg_resources
      ModuleNotFoundError: No module named 'pkg_resources'
      [end of output]

The problem is solved by declaring setuptools as a dependency in my own package, which I would prefer not having to do for obvious reasons. I understand that setuptools has been the de-facto standard for many years and that one could just assume that pretty much every package will be installed in an environment where it is present. But lately a lot of people have been moving away from setuptools, so if you depend on it I think you should explicitly declare it as a dependency in mne.

Steps to reproduce

Write a package with a build backend other than setuptools and have it depend on mne.

Link to data

No response

Expected results

Package can be installed with build backend other than setuptools.

Actual results

Package can't be installed.

Additional information

(This is on a Gitlab runner, so not sure how helpful this is)

Platform:         Linux-3.10.0-1160.15.2.el7.x86_64-x86_64-with-glibc2.31
Python:           3.9.16 (main, Jan 23 2023, 23:35:25)  [GCC 10.2.1 20210110]
Executable:       /usr/local/bin/python
CPU:              : 20 cores
Memory:           Unavailable (requires "psutil" package)
mne:              1.3.0
numpy:            1.24.1 {unknown linalg bindings (threadpoolctl module not found: No module named 'threadpoolctl')}
scipy:            1.10.0
matplotlib:       3.6.3 {backend=agg}

sklearn:          Not found
numba:            Not found
nibabel:          Not found
nilearn:          Not found
dipy:             Not found
openmeeg:         Not found
cupy:             Not found
pandas:           Not found
pyvista:          Not found
pyvistaqt:        Not found
ipyvtklink:       Not found
vtk:              Not found
qtpy:             Not found
ipympl:           Not found
pyqtgraph:        Not found
pooch:            v1.6.0

mne_bids:         Not found
mne_nirs:         Not found
mne_features:     Not found
mne_qt_browser:   Not found
mne_connectivity: Not found
mne_icalabel:     Not found
welcome[bot] commented 1 year ago

Hello! 👋 Thanks for opening your first issue here! ❤️ We will try to get back to you soon. 🚴🏽‍♂️

cbrnr commented 1 year ago

I think we should try to replace setuptools.pkg_resources with importlib.resources (which is part of the standard library) (as recommended here). Would that resolve your issue?

aplzr commented 1 year ago

I think it should, as it's part of the standard library. I just checked, there's only one additional place where pkg_resources is imported (https://github.com/mne-tools/mne-python/blob/main/mne/utils/misc.py#L443), so it should be a fairly easy thing to fix (assuming there are no other parts of setuptools that are used somewhere in mne).

I have no experience with Github pull requests (we're using Gitlab at my company) but I'm happy to read up on it and give it a try.

drammock commented 1 year ago

I have no experience with Github pull requests (we're using Gitlab at my company) but I'm happy to read up on it and give it a try.

please go for it!

aplzr commented 1 year ago

While trying to set up my local environment according to https://mne.tools/stable/install/contributing.html I ran into a problem when installing the doc requirements. Not sure if this is relevant in the context of this issue (I will ignore this for the moment), but thought I'd mention it.

 pzr@ols122 ~\development\mne-python main  ❯ python -m pip install -r .\requirements_doc.txt
Collecting https://github.com/numpy/numpydoc/archive/main.zip (from -r .\requirements_doc.txt (line 3))
  Downloading https://github.com/numpy/numpydoc/archive/main.zip
     | 86.9 kB 174.9 kB/s 0:00:00
  Preparing metadata (setup.py) ... done
Collecting https://github.com/pydata/pydata-sphinx-theme/archive/f367a58af33be362351686f1e207ea099f8e529e.zip (from -r .\requirements_doc.txt (line 4))
  Downloading https://github.com/pydata/pydata-sphinx-theme/archive/f367a58af33be362351686f1e207ea099f8e529e.zip
     / 3.4 MB 584.2 kB/s 0:00:05
  Installing build dependencies ... done
  Getting requirements to build wheel ... done
  Preparing metadata (pyproject.toml) ... error
  error: subprocess-exited-with-error

  × Preparing metadata (pyproject.toml) did not run successfully.
  │ exit code: 1
  ╰─> [16 lines of output]
      Traceback (most recent call last):
        File "C:\Users\pzr\development\venv\mne-bugfix-38\lib\site-packages\pip\_vendor\pyproject_hooks\_in_process\_in_process.py", line 353, in <module>
          main()
        File "C:\Users\pzr\development\venv\mne-bugfix-38\lib\site-packages\pip\_vendor\pyproject_hooks\_in_process\_in_process.py", line 335, in main
          json_out['return_val'] = hook(**hook_input['kwargs'])
        File "C:\Users\pzr\development\venv\mne-bugfix-38\lib\site-packages\pip\_vendor\pyproject_hooks\_in_process\_in_process.py", line 149, in prepare_metadata_for_build_wheel
          return hook(metadata_directory, config_settings)
        File "C:\Users\pzr\AppData\Local\Temp\pip-build-env-el1y8v1d\overlay\Lib\site-packages\sphinx_theme_builder\__init__.py", line 80, in prepare_metadata_for_build_wheel
          return _generate_metadata(project, destination=Path(metadata_directory))
        File "C:\Users\pzr\AppData\Local\Temp\pip-build-env-el1y8v1d\overlay\Lib\site-packages\sphinx_theme_builder\_internal\distributions.py", line 132, in generate_metadata
          (dist_info / "METADATA").write_text(project.get_metadata_file_contents())
        File "C:\Users\pzr\AppData\Local\Programs\Python\Python38\lib\pathlib.py", line 1256, in write_text
          return f.write(data)
        File "C:\Users\pzr\AppData\Local\Programs\Python\Python38\lib\encodings\cp1252.py", line 19, in encode
          return codecs.charmap_encode(input,self.errors,encoding_table)[0]
      UnicodeEncodeError: 'charmap' codec can't encode character '\U0001f4da' in position 4769: character maps to <undefined>
      [end of output]
drammock commented 1 year ago

Exporting the environment variable PYTHONUTF8=1 before install should fix this. Windows doesn't like the fact that there are emoji in the README of our website theme

aplzr commented 1 year ago

That worked, thanks!