Repository: nipy/nipy

Issue:
numpy : No module named 'numpy.testing.decorators'
for recent version of numpy (1.18.1)

```
Python 3.7.6 (default, Jan  8 2020, 19:59:22) 
Type 'copyright', 'credits' or 'license' for more information
IPython 7.12.0 -- An enhanced Interactive Python. Type '?' for help.

In [1]: from nipy.algorithms.segmentation import brain_segmentation             
---------------------------------------------------------------------------
ModuleNotFoundError                       Traceback (most recent call last)
<ipython-input-1-5dd8704fa93a> in <module>
----> 1 from nipy.algorithms.segmentation import brain_segmentation

~/miniconda3/envs/conda37/lib/python3.7/site-packages/nipy/__init__.py in <module>
     10                    __version__)
     11 
---> 12 from nipy.testing import Tester
     13 test = Tester().test
     14 bench = Tester().bench

~/miniconda3/envs/conda37/lib/python3.7/site-packages/nipy/testing/__init__.py in <module>
     42 bench = Tester().bench
     43 
---> 44 from . import decorators as dec
     45 
     46 # Allow failed import of nose if not now running tests

~/miniconda3/envs/conda37/lib/python3.7/site-packages/nipy/testing/decorators.py in <module>
      9 from __future__ import absolute_import
     10 
---> 11 from numpy.testing.decorators import *
     12 
     13 from nipy.utils import templates, example_data, DataError

ModuleNotFoundError: No module named 'numpy.testing.decorators'
```


Discussion:

Patch:
diff --git a/.appveyor.yml b/.appveyor.yml
index cf72da45..15cb7438 100644
--- a/.appveyor.yml
+++ b/.appveyor.yml
@@ -10,12 +10,12 @@ environment:
     - PYTHON: C:\Python27-x64
       # Doctest fail from the long Ls, as in (1L, 2L) != (1, 2)
       EXTRA_FLAGS: "--without-doctest"
-    - PYTHON: C:\Python34
-    - PYTHON: C:\Python34-x64
-    - PYTHON: C:\Python35
-    - PYTHON: C:\Python35-x64
     - PYTHON: C:\Python36
     - PYTHON: C:\Python36-x64
+    - PYTHON: C:\Python37
+    - PYTHON: C:\Python37-x64
+    - PYTHON: C:\Python38
+    - PYTHON: C:\Python38-x64
 
 install:
   # Prepend newly installed Python to the PATH of this build (this cannot be
@@ -29,7 +29,7 @@ install:
   - echo "C:\Program Files\Microsoft SDKs\Windows\v7.1\Bin\SetEnv.cmd" /x64 > "C:\Program Files (x86)\Microsoft Visual Studio 10.0\VC\bin\amd64/vcvars64.bat"
 
   # Install the dependencies of the project.
-  - pip install numpy Cython nose nibabel sympy scipy
+  - pip install numpy Cython nose nibabel "sympy<1.6" scipy
   # Pin wheel to 0.26 to avoid Windows ABI tag for built wheel
   - pip install wheel==0.26
   # install
diff --git a/.travis.yml b/.travis.yml
index 0b7fd22d..ea3283d2 100644
--- a/.travis.yml
+++ b/.travis.yml
@@ -14,7 +14,7 @@ cache:
 
 env:
   global:
-    - DEPENDS="numpy scipy sympy matplotlib nibabel"
+    - DEPENDS="numpy scipy sympy<1.6 matplotlib nibabel"
     - EXTRA_WHEELS="https://5cf40426d9f06eb7461d-6fe47d9331aba7cd62fc36c7196769e4.ssl.cf2.rackcdn.com"
     - PRE_WHEELS="https://7933911d6844c6c53a7d-47bd50c35cd79bd838daf386af554a83.ssl.cf2.rackcdn.com"
     - EXTRA_PIP_FLAGS="--find-links=$EXTRA_WHEELS"
@@ -22,9 +22,9 @@ env:
     - INSTALL_TYPE="pip"
 
 python:
-    - 3.4
-    - 3.5
     - 3.6
+    - 3.7
+    - 3.8
 
 matrix:
   include:
@@ -38,7 +38,7 @@ matrix:
         - PRE_DEPENDS="numpy==1.6.0"
         - DEPENDS="scipy==0.9.0 sympy==0.7.0 nibabel==1.2.0"
     # Test compiling against external lapack
-    - python: 3.4
+    - python: 3.6
       env:
         - NIPY_EXTERNAL_LAPACK=1
       addons:
@@ -59,17 +59,17 @@ matrix:
         - INSTALL_TYPE=requirements
         - DEPENDS=
     # test 3.5 against pre-release builds of everything
-    - python: 3.5
+    - python: 3.6
       env:
         - EXTRA_PIP_FLAGS="$PRE_PIP_FLAGS"
     # test python setup.py install
-    - python: 3.5
+    - python: 3.6
       env:
         - INSTALL_TYPE=setup
-    - python: 3.5
+    - python: 3.6
       env:
         - INSTALL_TYPE="pip_e"
-    - python: 3.5
+    - python: 3.6
       env:
         - DOC_BUILD=1
       addons:
@@ -94,7 +94,9 @@ before_install:
     - if [ -n "$PRE_DEPENDS" ]; then
       pip install $EXTRA_PIP_FLAGS $PRE_DEPENDS;
       fi
-    - pip install $EXTRA_PIP_FLAGS $DEPENDS
+    - if [ -n "$DEPENDS" ]; then
+      pip install $EXTRA_PIP_FLAGS $DEPENDS;
+      fi
     - if [ "${COVERAGE}" == "1" ]; then
       pip install coverage;
       pip install coveralls codecov;
diff --git a/doc-requirements.txt b/doc-requirements.txt
index 8040e1fc..2bc87948 100644
--- a/doc-requirements.txt
+++ b/doc-requirements.txt
@@ -1,8 +1,8 @@
 # Requirements for building docs
 # Check these dependencies against doc/conf.py
 -r dev-requirements.txt
-sphinx>=1.0
-numpydoc
+sphinx>=1.0,<3.0
+numpydoc==0.8.0
 matplotlib
 texext
 ipython
diff --git a/nipy/algorithms/statistics/formula/formulae.py b/nipy/algorithms/statistics/formula/formulae.py
index e1cfdba5..ed2e5896 100644
--- a/nipy/algorithms/statistics/formula/formulae.py
+++ b/nipy/algorithms/statistics/formula/formulae.py
@@ -267,10 +267,10 @@ class FactorTerm(Term):
             return sympy.Symbol.__mul__(self, other)
 
 
-class Beta(sympy.symbol.Dummy):
+class Beta(sympy.Dummy):
     ''' A symbol tied to a Term `term` '''
     def __new__(cls, name, term):
-        new = sympy.symbol.Dummy.__new__(cls, name)
+        new = sympy.Dummy.__new__(cls, name)
         new._term = term
         return new
 
diff --git a/nipy/algorithms/statistics/rft.py b/nipy/algorithms/statistics/rft.py
index 286b38a8..b214ea78 100644
--- a/nipy/algorithms/statistics/rft.py
+++ b/nipy/algorithms/statistics/rft.py
@@ -20,7 +20,10 @@ import numpy as np
 from numpy.linalg import pinv
 
 from scipy import stats
-from scipy.misc import factorial
+try:
+    from scipy.misc import factorial
+except ImportError:
+    from scipy.special import factorial
 from scipy.special import gamma, gammaln, beta, hermitenorm
 
 # Legacy repr printing from numpy.
diff --git a/nipy/info.py b/nipy/info.py
index e93c00d0..78363858 100644
--- a/nipy/info.py
+++ b/nipy/info.py
@@ -170,7 +170,7 @@ MINOR               = _version_minor
 MICRO               = _version_micro
 ISRELEASE           = _version_extra == ''
 VERSION             = __version__
-REQUIRES            = ["numpy", "scipy", "sympy", "nibabel"]
+REQUIRES            = ["numpy", "scipy", "sympy(<1.6)", "nibabel"]
 STATUS              = 'beta'
 
 # Versions and locations of optional data packages
diff --git a/requirements.txt b/requirements.txt
index 61e7e728..e2219b04 100644
--- a/requirements.txt
+++ b/requirements.txt
@@ -1,5 +1,5 @@
 # See nipy/info.py for requirement definitions
 numpy>=1.6.0
 scipy>=0.9.0
-sympy>=0.7.0
+sympy>=0.7.0,<1.6
 nibabel>=1.2.0


Test patch:
diff --git a/nipy/algorithms/clustering/tests/test_vmm.py b/nipy/algorithms/clustering/tests/test_vmm.py
index 1223808f..8c80d2a7 100644
--- a/nipy/algorithms/clustering/tests/test_vmm.py
+++ b/nipy/algorithms/clustering/tests/test_vmm.py
@@ -13,7 +13,11 @@ from ..von_mises_fisher_mixture import (VonMisesMixture,
                                         select_vmm_cv)
 
 from nose.tools import assert_true, assert_equal
-from numpy.testing import decorators
+try:
+    from numpy.testing import decorators
+except ImportError:
+    from numpy.testing import dec
+    decorators = dec
 
 from nibabel.optpkg import optional_package
 
diff --git a/nipy/algorithms/diagnostics/tests/test_screen.py b/nipy/algorithms/diagnostics/tests/test_screen.py
index f9e43682..89b9cf25 100644
--- a/nipy/algorithms/diagnostics/tests/test_screen.py
+++ b/nipy/algorithms/diagnostics/tests/test_screen.py
@@ -23,7 +23,13 @@ from nibabel.tmpdirs import InTemporaryDirectory
 from nose.tools import (assert_true, assert_false, assert_equal, assert_raises)
 
 from numpy.testing import (assert_array_equal, assert_array_almost_equal,
-                           assert_almost_equal, decorators)
+                           assert_almost_equal)
+
+try:
+    from numpy.testing import decorators
+except ImportError:
+    from numpy.testing import dec
+    decorators = dec
 
 from nipy.testing import funcfile
 from nipy.testing.decorators import needs_mpl_agg
diff --git a/nipy/algorithms/statistics/tests/test_rft.py b/nipy/algorithms/statistics/tests/test_rft.py
index d2fa1970..2d432d34 100644
--- a/nipy/algorithms/statistics/tests/test_rft.py
+++ b/nipy/algorithms/statistics/tests/test_rft.py
@@ -6,7 +6,10 @@ import numpy as np
 
 from scipy.special import gammaln, hermitenorm
 import scipy.stats
-from scipy.misc import factorial
+try:
+    from scipy.misc import factorial
+except ImportError:
+    from scipy.special import factorial
 
 from .. import rft
 
diff --git a/nipy/fixes/numpy/testing/nosetester.py b/nipy/fixes/numpy/testing/nosetester.py
index 4be245db..355ab0d5 100644
--- a/nipy/fixes/numpy/testing/nosetester.py
+++ b/nipy/fixes/numpy/testing/nosetester.py
@@ -21,7 +21,7 @@ def get_package_name(filepath):
 
     Examples
     --------
-    >>> np.testing.nosetester.get_package_name('nonsense')
+    >>> get_package_name('nonsense')
     'numpy'
 
     """
diff --git a/nipy/labs/group/permutation_test.py b/nipy/labs/group/permutation_test.py
index 24492594..9035de90 100644
--- a/nipy/labs/group/permutation_test.py
+++ b/nipy/labs/group/permutation_test.py
@@ -6,7 +6,10 @@ from __future__ import print_function, absolute_import
 
 # Third-party imports
 import numpy as np
-import scipy.misc as sm
+try:
+    from scipy.misc import comb
+except ImportError:
+    from scipy.special import comb
 import warnings
 
 # Our own imports
@@ -374,7 +377,7 @@ class permutation_test(object):
         elif self.nsamples == 2:
             n1,p = self.data1.shape[self.axis], self.data1.shape[1-self.axis]
             n2 = self.data2.shape[self.axis]
-            max_nperms = sm.comb(n1+n2,n1,exact=1)
+            max_nperms = comb(n1+n2,n1,exact=1)
             data = np.concatenate((self.data1,self.data2), self.axis)
             if self.vardata1 is not None:
                 vardata = np.concatenate((self.vardata1,self.vardata2), self.axis)
diff --git a/nipy/labs/viz_tools/test/test_activation_maps.py b/nipy/labs/viz_tools/test/test_activation_maps.py
index 069cc7b0..915a5e03 100644
--- a/nipy/labs/viz_tools/test/test_activation_maps.py
+++ b/nipy/labs/viz_tools/test/test_activation_maps.py
@@ -10,7 +10,7 @@ from nipy.testing.decorators import skipif
 try:
     import matplotlib as mp
     # Make really sure that we don't try to open an Xserver connection.
-    mp.use('svg', warn=False)
+    mp.use('svg')
     import pylab as pl
     pl.switch_backend('svg')
 except ImportError:
@@ -28,7 +28,7 @@ from ..anat_cache import mni_sform, _AnatCache
 
 def test_demo_plot_map():
     # This is only a smoke test
-    mp.use('svg', warn=False)
+    mp.use('svg')
     import pylab as pl
     pl.switch_backend('svg')
     demo_plot_map()
@@ -38,7 +38,7 @@ def test_demo_plot_map():
 
 def test_plot_anat():
     # This is only a smoke test
-    mp.use('svg', warn=False)
+    mp.use('svg')
     import pylab as pl
     pl.switch_backend('svg')
     data = np.zeros((20, 20, 20))
@@ -85,7 +85,7 @@ def test_plot_map_empty():
     # Test that things don't crash when we give a map with nothing above
     # threshold
     # This is only a smoke test
-    mp.use('svg', warn=False)
+    mp.use('svg')
     import pylab as pl
     pl.switch_backend('svg')
     data = np.zeros((20, 20, 20))
diff --git a/nipy/labs/viz_tools/test/test_cm.py b/nipy/labs/viz_tools/test/test_cm.py
index 9c4c4349..203df3e7 100644
--- a/nipy/labs/viz_tools/test/test_cm.py
+++ b/nipy/labs/viz_tools/test/test_cm.py
@@ -8,7 +8,7 @@ from nose import SkipTest
 try:
     import matplotlib as mp
     # Make really sure that we don't try to open an Xserver connection.
-    mp.use('svg', warn=False)
+    mp.use('svg')
     import pylab as pl
     pl.switch_backend('svg')
 except ImportError:
@@ -19,14 +19,14 @@ from ..cm import dim_cmap, replace_inside
 
 def test_dim_cmap():
     # This is only a smoke test
-    mp.use('svg', warn=False)
+    mp.use('svg')
     import pylab as pl
     dim_cmap(pl.cm.jet)
 
 
 def test_replace_inside():
     # This is only a smoke test
-    mp.use('svg', warn=False)
+    mp.use('svg')
     import pylab as pl
     pl.switch_backend('svg')
     replace_inside(pl.cm.jet, pl.cm.hsv, .2, .8)
diff --git a/nipy/labs/viz_tools/test/test_slicers.py b/nipy/labs/viz_tools/test/test_slicers.py
index 80df02dd..33bcffc3 100644
--- a/nipy/labs/viz_tools/test/test_slicers.py
+++ b/nipy/labs/viz_tools/test/test_slicers.py
@@ -7,7 +7,7 @@ import nose
 try:
     import matplotlib as mp
     # Make really sure that we don't try to open an Xserver connection.
-    mp.use('svg', warn=False)
+    mp.use('svg')
     import pylab as pl
     pl.switch_backend('svg')
 except ImportError:
@@ -25,7 +25,7 @@ def test_demo_ortho_slicer():
     # conditioned on presence of MNI templated
     if not find_mni_template():
         raise nose.SkipTest("MNI Template is absent for the smoke test")
-    mp.use('svg', warn=False)
+    mp.use('svg')
     import pylab as pl
     pl.switch_backend('svg')
     demo_ortho_slicer()
diff --git a/nipy/modalities/fmri/tests/test_aliases.py b/nipy/modalities/fmri/tests/test_aliases.py
index 9e593234..38b35cdf 100644
--- a/nipy/modalities/fmri/tests/test_aliases.py
+++ b/nipy/modalities/fmri/tests/test_aliases.py
@@ -44,7 +44,7 @@ def test_implemented_function():
     func = sympy.Function('myfunc')
     assert_false(hasattr(func, '_imp_'))
     f = implemented_function(func, lambda x: 2*x)
-    assert_true(hasattr(func, '_imp_'))
+    assert_true(hasattr(f, '_imp_'))
 
 
 def test_lambdify():
diff --git a/nipy/testing/__init__.py b/nipy/testing/__init__.py
index c044b6ac..96bb82d5 100644
--- a/nipy/testing/__init__.py
+++ b/nipy/testing/__init__.py
@@ -36,6 +36,13 @@ funcfile = os.path.join(basedir, 'functional.nii.gz')
 anatfile = os.path.join(basedir, 'anatomical.nii.gz')
 
 from numpy.testing import *
+# Re import decorators/dec depending on numpy's version
+try:
+    from numpy.testing import decorators
+except ImportError:
+    from numpy.testing import dec
+    decorators = dec
+
 # Overwrites numpy.testing.Tester
 from .nosetester import NipyNoseTester as Tester
 test = Tester().test
diff --git a/nipy/testing/decorators.py b/nipy/testing/decorators.py
index 5d8be8b4..addb3570 100644
--- a/nipy/testing/decorators.py
+++ b/nipy/testing/decorators.py
@@ -8,7 +8,10 @@ dependency on nose.
 from __future__ import print_function
 from __future__ import absolute_import
 
-from numpy.testing.decorators import *
+try:
+    from numpy.testing.decorators import *
+except ImportError:
+    from numpy.testing._private.decorators import *
 
 from nipy.utils import templates, example_data, DataError
 
@@ -124,7 +127,7 @@ def needs_mpl_agg(func):
     import matplotlib.pyplot as plt
     from nose.tools import make_decorator
     def agg_func(*args, **kwargs):
-        matplotlib.use('agg', warn=False)
+        matplotlib.use('agg')
         plt.switch_backend('agg')
         return func(*args, **kwargs)
     return make_decorator(func)(agg_func)
diff --git a/nipy/tests/test_scripts.py b/nipy/tests/test_scripts.py
index cd96d870..cea7becc 100644
--- a/nipy/tests/test_scripts.py
+++ b/nipy/tests/test_scripts.py
@@ -19,7 +19,13 @@ from nipy.core.api import rollimg
 from nose.tools import assert_true, assert_false, assert_equal, assert_raises
 
 from ..testing import funcfile
-from numpy.testing import decorators, assert_almost_equal
+from numpy.testing import assert_almost_equal
+
+try:
+    from numpy.testing import decorators
+except ImportError:
+    from numpy.testing import dec
+    decorators = dec
 
 from nipy.testing.decorators import make_label_dec