Repository: nipy/nipype

Issue:
Is pybids a mandatory dependency? 
### Summary

Hi all, 

I am packaging the newest `nipype` version and using the test function `pytest -v --doctest-modules nipype`. I have everything in `requirements.txt` installed and everything seems great in this new release. However, I am getting **1** failed test and it's in the BIDS functionality (which I have not chosen to include on my system at this time).  *Is `pybids` an optional dependency or a mandatory one?* If mandatory I will install it, if optional should the test be skipped? 

Thanks!

### Actual behavior

the test output is: 

```
========================================= FAILURES ==========================================
______________________ [doctest] nipype.interfaces.io.BIDSDataGrabber _______________________
2893 BIDS datagrabber module that wraps around pybids to allow arbitrary
2894     querying of BIDS datasets.
2895 
2896     Examples
2897     --------
2898     By default, the BIDSDataGrabber fetches anatomical and functional images
2899     from a project, and makes BIDS entities (e.g. subject) available for
2900     filtering outputs.
2901 
2902     >>> bg = BIDSDataGrabber()
UNEXPECTED EXCEPTION: ModuleNotFoundError("No module named 'bids'")
Traceback (most recent call last):
  File "/usr/lib/python3.8/doctest.py", line 1336, in __run
    exec(compile(example.source, filename, "single",
  File "<doctest nipype.interfaces.io.BIDSDataGrabber[0]>", line 1, in <module>
  File "/mnt/4e43a4f6-7402-4881-bcf5-d280e54cc385/AUR/aur/python-nipype/src/nipype-1.5.0/nipype/interfaces/io.py", line 2951, in __init__
    from bids import layout as bidslayout
ModuleNotFoundError: No module named 'bids'
```

### Expected behavior

I would expect the BIDS related tests to be skipped if pybids, bids-validator, etc. are not installed. 

### Script/Workflow details

here is the full test summary if you are interested: 

<details><summary>test results</summary>
<p>

```
========================================= FAILURES ==========================================
______________________ [doctest] nipype.interfaces.io.BIDSDataGrabber _______________________
2893 BIDS datagrabber module that wraps around pybids to allow arbitrary
2894     querying of BIDS datasets.
2895 
2896     Examples
2897     --------
2898     By default, the BIDSDataGrabber fetches anatomical and functional images
2899     from a project, and makes BIDS entities (e.g. subject) available for
2900     filtering outputs.
2901 
2902     >>> bg = BIDSDataGrabber()
UNEXPECTED EXCEPTION: ModuleNotFoundError("No module named 'bids'")
Traceback (most recent call last):
  File "/usr/lib/python3.8/doctest.py", line 1336, in __run
    exec(compile(example.source, filename, "single",
  File "<doctest nipype.interfaces.io.BIDSDataGrabber[0]>", line 1, in <module>
  File "/mnt/4e43a4f6-7402-4881-bcf5-d280e54cc385/AUR/aur/python-nipype/src/nipype-1.5.0/nipype/interfaces/io.py", line 2951, in __init__
    from bids import layout as bidslayout
ModuleNotFoundError: No module named 'bids'
/mnt/4e43a4f6-7402-4881-bcf5-d280e54cc385/AUR/aur/python-nipype/src/nipype-1.5.0/nipype/interfaces/io.py:2902: UnexpectedException
----------------------------------- Captured stdout call ------------------------------------
200604-11:31:33,297 nipype.interface WARNING:
	 Unable to import ['bids']; BIDSDataGrabber interface may fail to run
------------------------------------- Captured log call -------------------------------------
WARNING  nipype.interface:core.py:1069 Unable to import ['bids']; BIDSDataGrabber interface may fail to run
===================================== warnings summary ======================================
/usr/lib/python3.8/site-packages/dipy/viz/__init__.py:21
  /usr/lib/python3.8/site-packages/dipy/viz/__init__.py:21: UserWarning: You do not have FURY installed. Some visualization functions might not work for you. For installation instructions, please visit: https://fury.gl/
    warnings.warn(

/usr/lib/python3.8/site-packages/dipy/stats/__init__.py:7
  /usr/lib/python3.8/site-packages/dipy/stats/__init__.py:7: UserWarning: The `dipy.stats` module is still under heavy development and functionality, as well as the API is likely to change in future versions of the software
    warnings.warn(w_string)

nipype/interfaces/mrtrix/convert.py:6
  /mnt/4e43a4f6-7402-4881-bcf5-d280e54cc385/AUR/aur/python-nipype/src/nipype-1.5.0/nipype/interfaces/mrtrix/convert.py:6: DeprecationWarning: The trackvis interface has been deprecated and will be removed in v4.0; please use the 'nibabel.streamlines' interface.
    import nibabel.trackvis as trk

nipype/pipeline/engine/tests/test_nodes.py:319
  /mnt/4e43a4f6-7402-4881-bcf5-d280e54cc385/AUR/aur/python-nipype/src/nipype-1.5.0/nipype/pipeline/engine/tests/test_nodes.py:319: PytestUnknownMarkWarning: Unknown pytest.mark.timeout - is this a typo?  You can register custom marks to avoid this warning - for details, see https://docs.pytest.org/en/latest/mark.html
    @pytest.mark.timeout(30)

nipype/pipeline/plugins/tests/test_oar.py:33
  /mnt/4e43a4f6-7402-4881-bcf5-d280e54cc385/AUR/aur/python-nipype/src/nipype-1.5.0/nipype/pipeline/plugins/tests/test_oar.py:33: PytestUnknownMarkWarning: Unknown pytest.mark.timeout - is this a typo?  You can register custom marks to avoid this warning - for details, see https://docs.pytest.org/en/latest/mark.html
    @pytest.mark.timeout(60)

nipype/pipeline/plugins/tests/test_pbs.py:33
  /mnt/4e43a4f6-7402-4881-bcf5-d280e54cc385/AUR/aur/python-nipype/src/nipype-1.5.0/nipype/pipeline/plugins/tests/test_pbs.py:33: PytestUnknownMarkWarning: Unknown pytest.mark.timeout - is this a typo?  You can register custom marks to avoid this warning - for details, see https://docs.pytest.org/en/latest/mark.html
    @pytest.mark.timeout(60)

/usr/lib/python3.8/site-packages/sphinxcontrib/napoleon/docstring.py:16
  /usr/lib/python3.8/site-packages/sphinxcontrib/napoleon/docstring.py:16: DeprecationWarning: Using or importing the ABCs from 'collections' instead of from 'collections.abc' is deprecated since Python 3.3, and in 3.9 it will stop working
    from collections import Callable

nipype/utils/tests/test_provenance.py:18
  /mnt/4e43a4f6-7402-4881-bcf5-d280e54cc385/AUR/aur/python-nipype/src/nipype-1.5.0/nipype/utils/tests/test_provenance.py:18: PytestUnknownMarkWarning: Unknown pytest.mark.timeout - is this a typo?  You can register custom marks to avoid this warning - for details, see https://docs.pytest.org/en/latest/mark.html
    @pytest.mark.timeout(60)

nipype/utils/tests/test_provenance.py:31
  /mnt/4e43a4f6-7402-4881-bcf5-d280e54cc385/AUR/aur/python-nipype/src/nipype-1.5.0/nipype/utils/tests/test_provenance.py:31: PytestUnknownMarkWarning: Unknown pytest.mark.timeout - is this a typo?  You can register custom marks to avoid this warning - for details, see https://docs.pytest.org/en/latest/mark.html
    @pytest.mark.timeout(60)

nipype/workflows/__init__.py:28
  /mnt/4e43a4f6-7402-4881-bcf5-d280e54cc385/AUR/aur/python-nipype/src/nipype-1.5.0/nipype/workflows/__init__.py:28: UserWarning: Nipype 1 workflows have been moved to the niflow-nipype1-workflows package. pip install niflow-nipype1-workflows to continue using them.
    warnings.warn(" ".join(_msg))

algorithms/tests/test_CompCor.py::TestCompCor::test_tcompcor_asymmetric_dim
  /mnt/4e43a4f6-7402-4881-bcf5-d280e54cc385/AUR/aur/python-nipype/src/nipype-1.5.0/nipype/algorithms/confounds.py:1438: RuntimeWarning: invalid value encountered in true_divide
    variance_explained = (s ** 2) / np.sum(s ** 2)

interfaces/fsl/dti.py::nipype.interfaces.fsl.dti.ProbTrackX
interfaces/fsl/dti.py::nipype.interfaces.fsl.dti.ProbTrackX2
  /mnt/4e43a4f6-7402-4881-bcf5-d280e54cc385/AUR/aur/python-nipype/src/nipype-1.5.0/nipype/interfaces/fsl/dti.py:816: DeprecationWarning: Deprecated: Please use create_bedpostx_pipeline instead
    warnings.warn(

interfaces/fsl/epi.py::nipype.interfaces.fsl.epi.EPIDeWarp
  /mnt/4e43a4f6-7402-4881-bcf5-d280e54cc385/AUR/aur/python-nipype/src/nipype-1.5.0/nipype/interfaces/fsl/epi.py:1417: DeprecationWarning: Deprecated: Please use niflow.nipype1.workflows.dmri.preprocess.epi.sdc_fmb instead
    warnings.warn(

interfaces/fsl/epi.py::nipype.interfaces.fsl.epi.EddyCorrect
interfaces/fsl/tests/test_epi.py::test_eddy_correct2
interfaces/fsl/tests/test_epi.py::test_eddy_correct2
  /mnt/4e43a4f6-7402-4881-bcf5-d280e54cc385/AUR/aur/python-nipype/src/nipype-1.5.0/nipype/interfaces/fsl/epi.py:1523: DeprecationWarning: Deprecated: Please use nipype.interfaces.fsl.epi.Eddy instead
    warnings.warn(

interfaces/nipy/utils.py::nipype.interfaces.nipy.utils.Similarity
  /mnt/4e43a4f6-7402-4881-bcf5-d280e54cc385/AUR/aur/python-nipype/src/nipype-1.5.0/nipype/interfaces/nipy/utils.py:59: DeprecationWarning: This interface is deprecated since 0.10.0. Please use nipype.algorithms.metrics.Similarity
    warnings.warn(

interfaces/tests/test_nilearn.py::TestSignalExtraction::test_signal_extract_no_shared
  /usr/lib/python3.8/site-packages/nilearn/_utils/niimg.py:168: DeprecationWarning: Using or importing the ABCs from 'collections' instead of from 'collections.abc' is deprecated since Python 3.3, and in 3.9 it will stop working
    if isinstance(niimgs, collections.Iterable):

interfaces/tests/test_nilearn.py::TestSignalExtraction::test_signal_extract_no_shared
interfaces/tests/test_nilearn.py::TestSignalExtraction::test_signal_extr_global_no_shared
interfaces/tests/test_nilearn.py::TestSignalExtraction::test_signal_extr_global_no_shared
interfaces/tests/test_nilearn.py::TestSignalExtraction::test_signal_extr_4d_global_no_shared
interfaces/tests/test_nilearn.py::TestSignalExtraction::test_signal_extr_traits_valid
  /usr/lib/python3.8/site-packages/nilearn/_utils/cache_mixin.py:226: DeprecationWarning: The 'cachedir' attribute has been deprecated in version 0.12 and will be removed in version 0.14.
  Use os.path.join(memory.location, 'joblib') attribute instead.
    if (memory.cachedir is None and memory_level is not None

interfaces/tests/test_nilearn.py::TestSignalExtraction::test_signal_extr_equiv_4d_no_shared
interfaces/tests/test_nilearn.py::TestSignalExtraction::test_signal_extr_4d_no_shared
interfaces/tests/test_nilearn.py::TestSignalExtraction::test_signal_extr_4d_global_no_shared
interfaces/tests/test_nilearn.py::TestSignalExtraction::test_signal_extr_shared
interfaces/tests/test_nilearn.py::TestSignalExtraction::test_signal_extr_shared
interfaces/tests/test_nilearn.py::TestSignalExtraction::test_signal_extr_shared
  /usr/lib/python3.8/site-packages/nilearn/_utils/cache_mixin.py:295: DeprecationWarning: The 'cachedir' attribute has been deprecated in version 0.12 and will be removed in version 0.14.
  Use os.path.join(memory.location, 'joblib') attribute instead.
    if self.memory_level == 0 and self.memory.cachedir is not None:

utils/tests/test_misc.py::test_rgetcwd
  /mnt/4e43a4f6-7402-4881-bcf5-d280e54cc385/AUR/aur/python-nipype/src/nipype-1.5.0/nipype/utils/misc.py:368: UserWarning: Current folder does not exist, replacing with "/tmp/pytest-of-mri/pytest-1/test_rgetcwd0" instead.
    warn('Current folder does not exist, replacing with "%s" instead.' % cwd)

-- Docs: https://docs.pytest.org/en/latest/warnings.html
================================== short test summary info ==================================
FAILED nipype/interfaces/io.py::nipype.interfaces.io.BIDSDataGrabber
====== 1 failed, 2809 passed, 73 skipped, 5 xfailed, 31 warnings in 153.19s (0:02:33) =======

```

</p>
</details>

### Platform details:

(have not yet installed 1.5.0) 

```
200604-11:38:58,673 nipype.utils INFO:
	 Running nipype version 1.4.2 (latest: 1.5.0)
{'commit_hash': '%h',
 'commit_source': 'archive substitution',
 'networkx_version': '2.4',
 'nibabel_version': '3.1.0',
 'nipype_version': '1.4.2',
 'numpy_version': '1.18.3',
 'pkg_path': '/usr/lib/python3.8/site-packages/nipype',
 'scipy_version': '1.4.1',
 'sys_executable': '/usr/bin/python',
 'sys_platform': 'linux',
 'sys_version': '3.8.3 (default, May 17 2020, 18:15:42) \n[GCC 10.1.0]',
 'traits_version': '6.0.0'}

```

### Execution environment

Choose one
- My python environment outside container



Discussion:
No. We should condition those tests on whether it's available.
Oh, it's the doctest. The regular tests are conditioned.

Resolving patch:
diff --git a/nipype/conftest.py b/nipype/conftest.py
--- a/nipype/conftest.py
+++ b/nipype/conftest.py
@@ -17,6 +17,7 @@
 def add_np(doctest_namespace):
     doctest_namespace["np"] = numpy
     doctest_namespace["os"] = os
+    doctest_namespace["pytest"] = pytest
     doctest_namespace["datadir"] = data_dir
 
 
diff --git a/nipype/interfaces/io.py b/nipype/interfaces/io.py
--- a/nipype/interfaces/io.py
+++ b/nipype/interfaces/io.py
@@ -2895,6 +2895,14 @@ class BIDSDataGrabber(LibraryBaseInterface, IOBase):
 
     Examples
     --------
+
+    .. setup::
+
+        >>> try:
+        ...     import bids
+        ... except ImportError:
+        ...     pytest.skip()
+
     By default, the BIDSDataGrabber fetches anatomical and functional images
     from a project, and makes BIDS entities (e.g. subject) available for
     filtering outputs.


Test patch: