3737
3838# If it's not available on PyPI, add it to this dict:
3939MANUAL_PACKAGES = {
40- # TODO: These packages are not pip-installable as of 2024/07/17 , so we have to
40+ # TODO: These packages are not pip-installable as of 2025/11/19 , so we have to
4141 # manually populate them -- should open issues on their package repos.
4242 "best-python" : {
4343 "Home-page" : "https://github.com/multifunkim/best-python" ,
5454 # This package does not provide wheels, so don't force CircleCI to build it.
5555 # If it eventually provides binary wheels we could add it to
5656 # `tools/circleci_dependencies.sh` and remove from here.
57+ # https://github.com/Eelbrain/Eelbrain/issues/130
5758 "eelbrain" : {
5859 "Home-page" : "https://eelbrain.readthedocs.io/en/stable/" ,
5960 "Summary" : "Open-source Python toolkit for MEG and EEG data analysis." ,
6061 },
61- # mne-kit-gui requires mayavi (ugh)
62- "mne-kit-gui" : {
63- "Home-page" : "https://github.com/mne-tools/mne-kit-gui" ,
64- "Summary" : "A module for KIT MEG coregistration." ,
65- },
66- # fsleyes requires wxpython, which needs to build
67- "fsleyes" : {
68- "Home-page" : "https://fsl.fmrib.ox.ac.uk/fsl/fslwiki/FSLeyes" ,
69- "Summary" : "FSLeyes is the FSL image viewer." ,
70- },
71- # dcm2niix must be built from source
72- "dcm2niix" : {
73- "Home-page" : "https://github.com/rordenlab/dcm2niix" ,
74- "Summary" : "DICOM to NIfTI converter" ,
75- },
7662 # TODO: these do not set a valid homepage or documentation page on PyPI
7763 "python-picard" : { # https://github.com/mind-inria/picard/issues/60
7864 "Home-page" : "https://github.com/mind-inria/picard" ,
7965 "Summary" : "Preconditioned ICA for Real Data" ,
8066 },
81- "eeg_positions" : {
82- "Home-page" : "https://eeg-positions.readthedocs.io" ,
83- "Summary" : "Compute and plot standard EEG electrode positions." ,
84- },
85- "mne-faster" : {
86- "Home-page" : "https://github.com/wmvanvliet/mne-faster" ,
87- "Summary" : "MNE-FASTER: automatic bad channel/epoch/component detection." , # noqa: E501
88- },
8967 "mne-features" : {
9068 "Home-page" : "https://mne.tools/mne-features" ,
9169 "Summary" : "MNE-Features software for extracting features from multivariate time series" , # noqa: E501
9270 },
93- "mne-rsa" : {
94- "Home-page" : "https://users.aalto.fi/~vanvlm1/mne-rsa" ,
95- "Summary" : "Code for performing Representational Similarity Analysis on MNE-Python data structures." , # noqa: E501
96- },
9771 "mffpy" : {
9872 "Home-page" : "https://github.com/BEL-Public/mffpy" ,
9973 "Summary" : "Reader and Writer for Philips' MFF file format." ,
10074 },
101- "emd" : {
102- "Home-page" : "https://emd.readthedocs.io/en/stable" ,
103- "Summary" : "Empirical Mode Decomposition in Python." ,
104- },
105- # Needs a release with homepage set properly
106- "meegkit" : {
107- "Home-page" : "https://nbara.github.io/python-meegkit" ,
108- "Summary" : "Denoising tools for M/EEG processing." ,
109- },
11075 # not on PyPI
11176 "conpy" : {
11277 "Home-page" : "https://github.com/aaltoimaginglanguage/conpy" ,
11378 "Summary" : "Functions and classes for performing connectivity analysis on MEG data." , # noqa: E501
11479 },
11580}
11681
117- REQUIRE_METADATA = os .getenv ("MNE_REQUIRE_RELATED_SOFTWARE_INSTALLED" , "false" ).lower ()
118- REQUIRE_METADATA = REQUIRE_METADATA in ("true" , "1" )
82+ REQUIRE_INSTALLED = os .getenv ("MNE_REQUIRE_RELATED_SOFTWARE_INSTALLED" , "false" ).lower ()
83+ REQUIRE_INSTALLED = REQUIRE_INSTALLED in ("true" , "1" )
84+ REQUIRE_METADATA = REQUIRE_INSTALLED
11985
12086# These packages pip-install with a different name than the package name
12187RENAMES = {
@@ -201,7 +167,7 @@ def _get_packages() -> dict[str, str]:
201167 if "Home-page" in md :
202168 url = md ["Home-page" ]
203169 else :
204- for prefix in ("homepage" , "documentation" ):
170+ for prefix in ("homepage" , "documentation" , "user documentation" ):
205171 for key , val in md .items ():
206172 if key == "Project-URL" and val .lower ().startswith (
207173 f"{ prefix } , "
@@ -217,6 +183,12 @@ def _get_packages() -> dict[str, str]:
217183 continue
218184 out [package ]["url" ] = url
219185 out [package ]["description" ] = md ["Summary" ].replace ("\n " , "" )
186+ if not REQUIRE_INSTALLED :
187+ reasons = [
188+ reason
189+ for reason in reasons
190+ if "not found, needs to be installed" not in reason
191+ ]
220192 reason_str = "\n " .join (reasons )
221193 if reason_str and REQUIRE_METADATA :
222194 raise ExtensionError (
@@ -263,6 +235,9 @@ def setup(app):
263235
264236
265237if __name__ == "__main__" : # pragma: no cover
238+ # running `python doc/sphinxext/related_software.py` for testing
239+ # require metadata for any installed packages (for debugging)
240+ REQUIRE_METADATA = True
266241 items = list (RelatedSoftwareDirective .run (None )[0 ].children )
267242 print (f"Got { len (items )} related software packages:" )
268243 for item in items :
0 commit comments