diff --git a/pandas/tests/dtypes/test_common.py b/pandas/tests/dtypes/test_common.py index e0be34b14a97d..2146704fea95f 100644 --- a/pandas/tests/dtypes/test_common.py +++ b/pandas/tests/dtypes/test_common.py @@ -9,6 +9,7 @@ import pandas.core.dtypes.common as com import pandas.util.testing as tm +import pandas.util._test_decorators as td class TestPandasDtype(object): @@ -132,21 +133,22 @@ def test_is_object(): assert not com.is_object_dtype([1, 2, 3]) -def test_is_sparse(): +@pytest.mark.parametrize("check_scipy", [ + False, pytest.param(True, marks=td.skip_if_no_scipy) +]) +def test_is_sparse(check_scipy): assert com.is_sparse(pd.SparseArray([1, 2, 3])) assert com.is_sparse(pd.SparseSeries([1, 2, 3])) assert not com.is_sparse(np.array([1, 2, 3])) - # This test will only skip if the previous assertions - # pass AND scipy is not installed. - sparse = pytest.importorskip("scipy.sparse") - assert not com.is_sparse(sparse.bsr_matrix([1, 2, 3])) + if check_scipy: + import scipy.sparse + assert not com.is_sparse(scipy.sparse.bsr_matrix([1, 2, 3])) +@td.skip_if_no_scipy def test_is_scipy_sparse(): - tm._skip_if_no_scipy() - from scipy.sparse import bsr_matrix assert com.is_scipy_sparse(bsr_matrix([1, 2, 3])) @@ -501,7 +503,10 @@ def test_is_bool_dtype(): assert com.is_bool_dtype(pd.Index([True, False])) -def test_is_extension_type(): +@pytest.mark.parametrize("check_scipy", [ + False, pytest.param(True, marks=td.skip_if_no_scipy) +]) +def test_is_extension_type(check_scipy): assert not com.is_extension_type([1, 2, 3]) assert not com.is_extension_type(np.array([1, 2, 3])) assert not com.is_extension_type(pd.DatetimeIndex([1, 2, 3])) @@ -517,10 +522,9 @@ def test_is_extension_type(): s = pd.Series([], dtype=dtype) assert com.is_extension_type(s) - # This test will only skip if the previous assertions - # pass AND scipy is not installed. - sparse = pytest.importorskip("scipy.sparse") - assert not com.is_extension_type(sparse.bsr_matrix([1, 2, 3])) + if check_scipy: + import scipy.sparse + assert not com.is_extension_type(scipy.sparse.bsr_matrix([1, 2, 3])) def test_is_complex_dtype(): diff --git a/pandas/tests/dtypes/test_inference.py b/pandas/tests/dtypes/test_inference.py index 577f4238c2328..e8bdd2a551a34 100644 --- a/pandas/tests/dtypes/test_inference.py +++ b/pandas/tests/dtypes/test_inference.py @@ -37,6 +37,7 @@ _ensure_int32, _ensure_categorical) from pandas.util import testing as tm +import pandas.util._test_decorators as td @pytest.fixture(params=[True, False], ids=str) @@ -1190,8 +1191,8 @@ def test_nan_to_nat_conversions(): assert (s[8].value == np.datetime64('NaT').astype(np.int64)) +@td.skip_if_no_scipy def test_is_scipy_sparse(spmatrix): # noqa: F811 - tm._skip_if_no_scipy() assert is_scipy_sparse(spmatrix([[0, 1]])) assert not is_scipy_sparse(np.array([1])) diff --git a/pandas/tests/frame/test_analytics.py b/pandas/tests/frame/test_analytics.py index 7014929db4c2d..17d711f937bf7 100644 --- a/pandas/tests/frame/test_analytics.py +++ b/pandas/tests/frame/test_analytics.py @@ -22,6 +22,7 @@ import pandas.io.formats.printing as printing import pandas.util.testing as tm +import pandas.util._test_decorators as td from pandas.tests.frame.common import TestData @@ -30,22 +31,22 @@ class TestDataFrameAnalytics(TestData): # ---------------------------------------------------------------------= # Correlation and covariance + @td.skip_if_no_scipy def test_corr_pearson(self): - tm._skip_if_no_scipy() self.frame['A'][:5] = nan self.frame['B'][5:10] = nan self._check_method('pearson') + @td.skip_if_no_scipy def test_corr_kendall(self): - tm._skip_if_no_scipy() self.frame['A'][:5] = nan self.frame['B'][5:10] = nan self._check_method('kendall') + @td.skip_if_no_scipy def test_corr_spearman(self): - tm._skip_if_no_scipy() self.frame['A'][:5] = nan self.frame['B'][5:10] = nan @@ -62,8 +63,8 @@ def _check_method(self, method='pearson', check_minp=False): expected.loc['A', 'B'] = expected.loc['B', 'A'] = nan tm.assert_frame_equal(result, expected) + @td.skip_if_no_scipy def test_corr_non_numeric(self): - tm._skip_if_no_scipy() self.frame['A'][:5] = nan self.frame['B'][5:10] = nan @@ -72,9 +73,8 @@ def test_corr_non_numeric(self): expected = self.mixed_frame.loc[:, ['A', 'B', 'C', 'D']].corr() tm.assert_frame_equal(result, expected) + @td.skip_if_no_scipy def test_corr_nooverlap(self): - tm._skip_if_no_scipy() - # nothing in common for meth in ['pearson', 'kendall', 'spearman']: df = DataFrame({'A': [1, 1.5, 1, np.nan, np.nan, np.nan], @@ -88,9 +88,8 @@ def test_corr_nooverlap(self): assert rs.loc['B', 'B'] == 1 assert isna(rs.loc['C', 'C']) + @td.skip_if_no_scipy def test_corr_constant(self): - tm._skip_if_no_scipy() - # constant --> all NA for meth in ['pearson', 'spearman']: @@ -106,9 +105,8 @@ def test_corr_int(self): df3.cov() df3.corr() + @td.skip_if_no_scipy def test_corr_int_and_boolean(self): - tm._skip_if_no_scipy() - # when dtypes of pandas series are different # then ndarray will have dtype=object, # so it need to be properly handled @@ -719,8 +717,8 @@ def test_sem(self): result = nanops.nansem(arr, axis=0) assert not (result < 0).any() + @td.skip_if_no_scipy def test_skew(self): - tm._skip_if_no_scipy() from scipy.stats import skew def alt(x): @@ -730,9 +728,8 @@ def alt(x): self._check_stat_op('skew', alt) + @td.skip_if_no_scipy def test_kurt(self): - tm._skip_if_no_scipy() - from scipy.stats import kurtosis def alt(x): diff --git a/pandas/tests/frame/test_missing.py b/pandas/tests/frame/test_missing.py index 7e8869cbdeefb..2e4e8b9582cf6 100644 --- a/pandas/tests/frame/test_missing.py +++ b/pandas/tests/frame/test_missing.py @@ -16,6 +16,7 @@ from pandas.util.testing import assert_series_equal, assert_frame_equal import pandas.util.testing as tm +import pandas.util._test_decorators as td from pandas.tests.frame.common import TestData, _check_mixed_float @@ -646,9 +647,8 @@ def test_interp_nan_idx(self): with pytest.raises(NotImplementedError): df.interpolate(method='values') + @td.skip_if_no_scipy def test_interp_various(self): - tm._skip_if_no_scipy() - df = DataFrame({'A': [1, 2, np.nan, 4, 5, np.nan, 7], 'C': [1, 2, 3, 5, 8, 13, 21]}) df = df.set_index('C') @@ -695,8 +695,8 @@ def test_interp_various(self): expected.A.loc[13] = 5 assert_frame_equal(result, expected, check_dtype=False) + @td.skip_if_no_scipy def test_interp_alt_scipy(self): - tm._skip_if_no_scipy() df = DataFrame({'A': [1, 2, np.nan, 4, 5, np.nan, 7], 'C': [1, 2, 3, 5, 8, 13, 21]}) result = df.interpolate(method='barycentric') @@ -739,8 +739,6 @@ def test_interp_rowwise(self): expected[4] = expected[4].astype(np.float64) assert_frame_equal(result, expected) - # scipy route - tm._skip_if_no_scipy() result = df.interpolate(axis=1, method='values') assert_frame_equal(result, expected) @@ -753,7 +751,10 @@ def test_rowwise_alt(self): 1: [1, 2, 3, 4, 3, 2, 1, 0, -1]}) df.interpolate(axis=0) - def test_interp_leading_nans(self): + @pytest.mark.parametrize("check_scipy", [ + False, pytest.param(True, marks=td.skip_if_no_scipy) + ]) + def test_interp_leading_nans(self, check_scipy): df = DataFrame({"A": [np.nan, np.nan, .5, .25, 0], "B": [np.nan, -3, -3.5, np.nan, -4]}) result = df.interpolate() @@ -761,9 +762,9 @@ def test_interp_leading_nans(self): expected['B'].loc[3] = -3.75 assert_frame_equal(result, expected) - tm._skip_if_no_scipy() - result = df.interpolate(method='polynomial', order=1) - assert_frame_equal(result, expected) + if check_scipy: + result = df.interpolate(method='polynomial', order=1) + assert_frame_equal(result, expected) def test_interp_raise_on_only_mixed(self): df = DataFrame({'A': [1, 2, np.nan, 4], diff --git a/pandas/tests/plotting/test_datetimelike.py b/pandas/tests/plotting/test_datetimelike.py index e87c67a682d46..7f9ae7b8bb1da 100644 --- a/pandas/tests/plotting/test_datetimelike.py +++ b/pandas/tests/plotting/test_datetimelike.py @@ -643,10 +643,10 @@ def test_secondary_y_ts(self): assert ax.get_yaxis().get_visible() @pytest.mark.slow + @td.skip_if_no_scipy def test_secondary_kde(self): if not self.mpl_ge_1_5_0: pytest.skip("mpl is not supported") - tm._skip_if_no_scipy() _skip_if_no_scipy_gaussian_kde() ser = Series(np.random.randn(10)) diff --git a/pandas/tests/plotting/test_deprecated.py b/pandas/tests/plotting/test_deprecated.py index d2f8e13a2444b..2c2d371921d2f 100644 --- a/pandas/tests/plotting/test_deprecated.py +++ b/pandas/tests/plotting/test_deprecated.py @@ -24,9 +24,8 @@ class TestDeprecatedNameSpace(TestPlotBase): @pytest.mark.slow + @td.skip_if_no_scipy def test_scatter_plot_legacy(self): - tm._skip_if_no_scipy() - df = pd.DataFrame(randn(100, 2)) with tm.assert_produces_warning(FutureWarning): diff --git a/pandas/tests/plotting/test_frame.py b/pandas/tests/plotting/test_frame.py index 3b3f6666340b8..d61b0a40380f3 100644 --- a/pandas/tests/plotting/test_frame.py +++ b/pandas/tests/plotting/test_frame.py @@ -1398,8 +1398,8 @@ def test_boxplot_subplots_return_type(self): check_ax_title=False) @pytest.mark.slow + @td.skip_if_no_scipy def test_kde_df(self): - tm._skip_if_no_scipy() _skip_if_no_scipy_gaussian_kde() if not self.mpl_ge_1_5_0: pytest.skip("mpl is not supported") @@ -1422,8 +1422,8 @@ def test_kde_df(self): self._check_ax_scales(axes, yaxis='log') @pytest.mark.slow + @td.skip_if_no_scipy def test_kde_missing_vals(self): - tm._skip_if_no_scipy() _skip_if_no_scipy_gaussian_kde() if not self.mpl_ge_1_5_0: pytest.skip("mpl is not supported") @@ -1949,8 +1949,8 @@ def test_hist_colors(self): tm.close() @pytest.mark.slow + @td.skip_if_no_scipy def test_kde_colors(self): - tm._skip_if_no_scipy() _skip_if_no_scipy_gaussian_kde() if not self.mpl_ge_1_5_0: pytest.skip("mpl is not supported") @@ -1974,8 +1974,8 @@ def test_kde_colors(self): self._check_colors(ax.get_lines(), linecolors=rgba_colors) @pytest.mark.slow + @td.skip_if_no_scipy def test_kde_colors_and_styles_subplots(self): - tm._skip_if_no_scipy() _skip_if_no_scipy_gaussian_kde() if not self.mpl_ge_1_5_0: pytest.skip("mpl is not supported") diff --git a/pandas/tests/plotting/test_misc.py b/pandas/tests/plotting/test_misc.py index 1753bc6387d33..bb590d5232b62 100644 --- a/pandas/tests/plotting/test_misc.py +++ b/pandas/tests/plotting/test_misc.py @@ -52,8 +52,8 @@ def test_bootstrap_plot(self): @td.skip_if_no_mpl class TestDataFramePlots(TestPlotBase): + @td.skip_if_no_scipy def test_scatter_matrix_axis(self): - tm._skip_if_no_scipy() scatter_matrix = plotting.scatter_matrix with tm.RNGContext(42): diff --git a/pandas/tests/plotting/test_series.py b/pandas/tests/plotting/test_series.py index 6dd7e1e9882b2..2458fc0dc992c 100644 --- a/pandas/tests/plotting/test_series.py +++ b/pandas/tests/plotting/test_series.py @@ -589,6 +589,7 @@ def test_plot_fails_with_dupe_color_and_style(self): x.plot(style='k--', color='k', ax=ax) @pytest.mark.slow + @td.skip_if_no_scipy def test_hist_kde(self): if not self.mpl_ge_1_5_0: pytest.skip("mpl is not supported") @@ -602,7 +603,6 @@ def test_hist_kde(self): ylabels = ax.get_yticklabels() self._check_text_labels(ylabels, [''] * len(ylabels)) - tm._skip_if_no_scipy() _skip_if_no_scipy_gaussian_kde() _check_plot_works(self.ts.plot.kde) _check_plot_works(self.ts.plot.density) @@ -615,8 +615,8 @@ def test_hist_kde(self): self._check_text_labels(ylabels, [''] * len(ylabels)) @pytest.mark.slow + @td.skip_if_no_scipy def test_kde_kwargs(self): - tm._skip_if_no_scipy() _skip_if_no_scipy_gaussian_kde() if not self.mpl_ge_1_5_0: pytest.skip("mpl is not supported") @@ -633,8 +633,8 @@ def test_kde_kwargs(self): self._check_text_labels(ax.yaxis.get_label(), 'Density') @pytest.mark.slow + @td.skip_if_no_scipy def test_kde_missing_vals(self): - tm._skip_if_no_scipy() _skip_if_no_scipy_gaussian_kde() if not self.mpl_ge_1_5_0: pytest.skip("mpl is not supported") @@ -665,6 +665,7 @@ def test_hist_kwargs(self): tm.close() @pytest.mark.slow + @td.skip_if_no_scipy def test_hist_kde_color(self): if not self.mpl_ge_1_5_0: pytest.skip("mpl is not supported") @@ -675,7 +676,6 @@ def test_hist_kde_color(self): assert len(ax.patches) == 10 self._check_colors(ax.patches, facecolors=['b'] * 10) - tm._skip_if_no_scipy() _skip_if_no_scipy_gaussian_kde() _, ax = self.plt.subplots() ax = self.ts.plot.kde(logy=True, color='r', ax=ax) diff --git a/pandas/tests/series/test_analytics.py b/pandas/tests/series/test_analytics.py index 289b5c01c1263..b206d84c0d6f8 100644 --- a/pandas/tests/series/test_analytics.py +++ b/pandas/tests/series/test_analytics.py @@ -23,6 +23,7 @@ from pandas.util.testing import (assert_series_equal, assert_almost_equal, assert_frame_equal, assert_index_equal) import pandas.util.testing as tm +import pandas.util._test_decorators as td from .common import TestData @@ -282,9 +283,8 @@ def test_sem(self): result = s.sem(ddof=1) assert isna(result) + @td.skip_if_no_scipy def test_skew(self): - tm._skip_if_no_scipy() - from scipy.stats import skew alt = lambda x: skew(x, bias=False) self._check_stat_op('skew', alt) @@ -302,9 +302,8 @@ def test_skew(self): assert 0 == s.skew() assert (df.skew() == 0).all() + @td.skip_if_no_scipy def test_kurt(self): - tm._skip_if_no_scipy() - from scipy.stats import kurtosis alt = lambda x: kurtosis(x, bias=False) self._check_stat_op('kurt', alt) @@ -708,9 +707,8 @@ def test_modulo(self): expected = Series([nan, 0.0]) assert_series_equal(result, expected) + @td.skip_if_no_scipy def test_corr(self): - tm._skip_if_no_scipy() - import scipy.stats as stats # full overlap @@ -739,9 +737,8 @@ def test_corr(self): expected, _ = stats.pearsonr(A, B) tm.assert_almost_equal(result, expected) + @td.skip_if_no_scipy def test_corr_rank(self): - tm._skip_if_no_scipy() - import scipy import scipy.stats as stats diff --git a/pandas/tests/series/test_missing.py b/pandas/tests/series/test_missing.py index b23dc37016b69..04fdebad6165b 100644 --- a/pandas/tests/series/test_missing.py +++ b/pandas/tests/series/test_missing.py @@ -19,6 +19,7 @@ from pandas.core.series import remove_na from pandas.util.testing import assert_series_equal, assert_frame_equal import pandas.util.testing as tm +import pandas.util._test_decorators as td from .common import TestData @@ -853,8 +854,8 @@ def test_interpolate(self): non_ts[0] = np.NaN pytest.raises(ValueError, non_ts.interpolate, method='time') + @td.skip_if_no_scipy def test_interpolate_pchip(self): - tm._skip_if_no_scipy() _skip_if_no_pchip() ser = Series(np.sort(np.random.uniform(size=100))) @@ -866,8 +867,8 @@ def test_interpolate_pchip(self): # does not blow up, GH5977 interp_s[49:51] + @td.skip_if_no_scipy def test_interpolate_akima(self): - tm._skip_if_no_scipy() _skip_if_no_akima() ser = Series([10, 11, 12, 13]) @@ -881,9 +882,8 @@ def test_interpolate_akima(self): interp_s = ser.reindex(new_index).interpolate(method='akima') assert_series_equal(interp_s[1:3], expected) + @td.skip_if_no_scipy def test_interpolate_piecewise_polynomial(self): - tm._skip_if_no_scipy() - ser = Series([10, 11, 12, 13]) expected = Series([11.00, 11.25, 11.50, 11.75, @@ -896,9 +896,8 @@ def test_interpolate_piecewise_polynomial(self): method='piecewise_polynomial') assert_series_equal(interp_s[1:3], expected) + @td.skip_if_no_scipy def test_interpolate_from_derivatives(self): - tm._skip_if_no_scipy() - ser = Series([10, 11, 12, 13]) expected = Series([11.00, 11.25, 11.50, 11.75, @@ -911,19 +910,17 @@ def test_interpolate_from_derivatives(self): method='from_derivatives') assert_series_equal(interp_s[1:3], expected) - def test_interpolate_corners(self): - s = Series([np.nan, np.nan]) - assert_series_equal(s.interpolate(), s) - - s = Series([]).interpolate() - assert_series_equal(s.interpolate(), s) - - tm._skip_if_no_scipy() + @pytest.mark.parametrize("kwargs", [ + {}, + pytest.param({'method': 'polynomial', 'order': 1}, + marks=td.skip_if_no_scipy) + ]) + def test_interpolate_corners(self, kwargs): s = Series([np.nan, np.nan]) - assert_series_equal(s.interpolate(method='polynomial', order=1), s) + assert_series_equal(s.interpolate(**kwargs), s) s = Series([]).interpolate() - assert_series_equal(s.interpolate(method='polynomial', order=1), s) + assert_series_equal(s.interpolate(**kwargs), s) def test_interpolate_index_values(self): s = Series(np.nan, index=np.sort(np.random.rand(30))) @@ -953,17 +950,17 @@ def test_interpolate_non_ts(self): with pytest.raises(ValueError): s.interpolate(method='time') - # New interpolation tests - def test_nan_interpolate(self): + @pytest.mark.parametrize("kwargs", [ + {}, + pytest.param({'method': 'polynomial', 'order': 1}, + marks=td.skip_if_no_scipy) + ]) + def test_nan_interpolate(self, kwargs): s = Series([0, 1, np.nan, 3]) - result = s.interpolate() + result = s.interpolate(**kwargs) expected = Series([0., 1., 2., 3.]) assert_series_equal(result, expected) - tm._skip_if_no_scipy() - result = s.interpolate(method='polynomial', order=1) - assert_series_equal(result, expected) - def test_nan_irregular_index(self): s = Series([1, 2, np.nan, 4], index=[1, 3, 5, 9]) result = s.interpolate() @@ -976,16 +973,15 @@ def test_nan_str_index(self): expected = Series([0., 1., 2., 2.], index=list('abcd')) assert_series_equal(result, expected) + @td.skip_if_no_scipy def test_interp_quad(self): - tm._skip_if_no_scipy() sq = Series([1, 4, np.nan, 16], index=[1, 2, 3, 4]) result = sq.interpolate(method='quadratic') expected = Series([1., 4., 9., 16.], index=[1, 2, 3, 4]) assert_series_equal(result, expected) + @td.skip_if_no_scipy def test_interp_scipy_basic(self): - tm._skip_if_no_scipy() - s = Series([1, 3, np.nan, 12, np.nan, 25]) # slinear expected = Series([1., 3., 7.5, 12., 18.5, 25.]) @@ -1147,9 +1143,8 @@ def test_interp_limit_before_ends(self): limit_direction='both') assert_series_equal(result, expected) + @td.skip_if_no_scipy def test_interp_all_good(self): - # scipy - tm._skip_if_no_scipy() s = Series([1, 2, 3]) result = s.interpolate(method='polynomial', order=1) assert_series_equal(result, s) @@ -1158,7 +1153,11 @@ def test_interp_all_good(self): result = s.interpolate() assert_series_equal(result, s) - def test_interp_multiIndex(self): + @pytest.mark.parametrize("check_scipy", [ + False, + pytest.param(True, marks=td.skip_if_no_scipy) + ]) + def test_interp_multiIndex(self, check_scipy): idx = MultiIndex.from_tuples([(0, 'a'), (1, 'b'), (2, 'c')]) s = Series([1, 2, np.nan], index=idx) @@ -1167,18 +1166,18 @@ def test_interp_multiIndex(self): result = s.interpolate() assert_series_equal(result, expected) - tm._skip_if_no_scipy() - with pytest.raises(ValueError): - s.interpolate(method='polynomial', order=1) + if check_scipy: + with pytest.raises(ValueError): + s.interpolate(method='polynomial', order=1) + @td.skip_if_no_scipy def test_interp_nonmono_raise(self): - tm._skip_if_no_scipy() s = Series([1, np.nan, 3], index=[0, 2, 1]) with pytest.raises(ValueError): s.interpolate(method='krogh') + @td.skip_if_no_scipy def test_interp_datetime64(self): - tm._skip_if_no_scipy() df = Series([1, np.nan, 3], index=date_range('1/1/2000', periods=3)) result = df.interpolate(method='nearest') expected = Series([1., 1., 3.], @@ -1192,25 +1191,22 @@ def test_interp_limit_no_nans(self): expected = s assert_series_equal(result, expected) - def test_no_order(self): - tm._skip_if_no_scipy() + @td.skip_if_no_scipy + @pytest.mark.parametrize("method", ['polynomial', 'spline']) + def test_no_order(self, method): s = Series([0, 1, np.nan, 3]) with pytest.raises(ValueError): - s.interpolate(method='polynomial') - with pytest.raises(ValueError): - s.interpolate(method='spline') + s.interpolate(method=method) + @td.skip_if_no_scipy def test_spline(self): - tm._skip_if_no_scipy() s = Series([1, 2, np.nan, 4, 5, np.nan, 7]) result = s.interpolate(method='spline', order=1) expected = Series([1., 2., 3., 4., 5., 6., 7.]) assert_series_equal(result, expected) + @td.skip_if_no('scipy', min_version='0.15') def test_spline_extrapolate(self): - tm.skip_if_no_package( - 'scipy', min_version='0.15', - app='setting ext on scipy.interpolate.UnivariateSpline') s = Series([1, 2, 3, 4, np.nan, 6, np.nan]) result3 = s.interpolate(method='spline', order=1, ext=3) expected3 = Series([1., 2., 3., 4., 5., 6., 6.]) @@ -1220,25 +1216,23 @@ def test_spline_extrapolate(self): expected1 = Series([1., 2., 3., 4., 5., 6., 7.]) assert_series_equal(result1, expected1) + @td.skip_if_no_scipy def test_spline_smooth(self): - tm._skip_if_no_scipy() s = Series([1, 2, np.nan, 4, 5.1, np.nan, 7]) assert (s.interpolate(method='spline', order=3, s=0)[5] != s.interpolate(method='spline', order=3)[5]) + @td.skip_if_no_scipy def test_spline_interpolation(self): - tm._skip_if_no_scipy() - s = Series(np.arange(10) ** 2) s[np.random.randint(0, 9, 3)] = np.nan result1 = s.interpolate(method='spline', order=1) expected1 = s.interpolate(method='spline', order=1) assert_series_equal(result1, expected1) + @td.skip_if_no_scipy def test_spline_error(self): # see gh-10633 - tm._skip_if_no_scipy() - s = pd.Series(np.arange(10) ** 2) s[np.random.randint(0, 9, 3)] = np.nan with pytest.raises(ValueError): diff --git a/pandas/tests/sparse/test_series.py b/pandas/tests/sparse/test_series.py index 1dc1c7f1575cc..7deeedacd1b23 100644 --- a/pandas/tests/sparse/test_series.py +++ b/pandas/tests/sparse/test_series.py @@ -13,6 +13,7 @@ isna, compat, _np_version_under1p12) from pandas.tseries.offsets import BDay import pandas.util.testing as tm +import pandas.util._test_decorators as td from pandas.compat import range from pandas.core.reshape.util import cartesian_product @@ -997,11 +998,11 @@ def test_round_trip_preserve_multiindex_names(self): check_names=True) +@td.skip_if_no_scipy class TestSparseSeriesScipyInteraction(object): # Issue 8048: add SparseSeries coo methods def setup_method(self, method): - tm._skip_if_no_scipy() import scipy.sparse # SparseSeries inputs used in tests, the tests rely on the order self.sparse_series = [] @@ -1108,7 +1109,6 @@ def test_from_coo_nodense_index(self): def test_from_coo_long_repr(self): # GH 13114 # test it doesn't raise error. Formatting is tested in test_format - tm._skip_if_no_scipy() import scipy.sparse sparse = SparseSeries.from_coo(scipy.sparse.rand(350, 18)) diff --git a/pandas/tests/test_algos.py b/pandas/tests/test_algos.py index 7ef77e4c78e10..d7fc5033bab90 100644 --- a/pandas/tests/test_algos.py +++ b/pandas/tests/test_algos.py @@ -19,6 +19,7 @@ import pandas.core.algorithms as algos from pandas.core.common import _asarray_tuplesafe import pandas.util.testing as tm +import pandas.util._test_decorators as td from pandas.core.dtypes.dtypes import CategoricalDtype as CDT from pandas.compat.numpy import np_array_datetime64_compat from pandas.util.testing import assert_almost_equal @@ -1109,8 +1110,8 @@ def test_unique_label_indices(): class TestRank(object): + @td.skip_if_no_scipy def test_scipy_compat(self): - tm._skip_if_no_scipy() from scipy.stats import rankdata def _check(arr): diff --git a/pandas/tests/test_panel.py b/pandas/tests/test_panel.py index f51bf0c4e476a..040c3adbcaf93 100644 --- a/pandas/tests/test_panel.py +++ b/pandas/tests/test_panel.py @@ -26,6 +26,7 @@ makeCustomDataframe as mkdf) import pandas.core.panel as panelm import pandas.util.testing as tm +import pandas.util._test_decorators as td def make_test_panel(): @@ -104,11 +105,9 @@ def test_min(self): def test_max(self): self._check_stat_op('max', np.max) + @td.skip_if_no_scipy def test_skew(self): - try: - from scipy.stats import skew - except ImportError: - pytest.skip("no scipy.stats.skew") + from scipy.stats import skew def this_skew(x): if len(x) < 3: diff --git a/pandas/tests/test_panel4d.py b/pandas/tests/test_panel4d.py index c42bedebe2f23..b064e3c7012bc 100644 --- a/pandas/tests/test_panel4d.py +++ b/pandas/tests/test_panel4d.py @@ -16,6 +16,7 @@ from pandas.util.testing import (assert_frame_equal, assert_series_equal, assert_almost_equal) import pandas.util.testing as tm +import pandas.util._test_decorators as td def add_nans(panel4d): @@ -59,11 +60,9 @@ def test_min(self): def test_max(self): self._check_stat_op('max', np.max) + @td.skip_if_no_scipy def test_skew(self): - try: - from scipy.stats import skew - except ImportError: - pytest.skip("no scipy.stats.skew") + from scipy.stats import skew def this_skew(x): if len(x) < 3: diff --git a/pandas/tests/test_window.py b/pandas/tests/test_window.py index 661c7dfcc50fc..bee925823eebe 100644 --- a/pandas/tests/test_window.py +++ b/pandas/tests/test_window.py @@ -17,6 +17,7 @@ from pandas.core.base import SpecificationError from pandas.errors import UnsupportedFunctionCall import pandas.util.testing as tm +import pandas.util._test_decorators as td from pandas.compat import range, zip, PY3 N, K = 100, 10 @@ -251,9 +252,8 @@ def test_count_nonnumeric_types(self): expected = df.notna().astype(float) tm.assert_frame_equal(result, expected) + @td.skip_if_no_scipy def test_window_with_args(self): - tm._skip_if_no_scipy() - # make sure that we are aggregating window functions correctly with arg r = Series(np.random.randn(100)).rolling(window=10, min_periods=1, win_type='gaussian') @@ -289,9 +289,9 @@ class TestWindow(Base): def setup_method(self, method): self._create_data() + @td.skip_if_no_scipy def test_constructor(self): # GH 12669 - tm._skip_if_no_scipy() for o in [self.series, self.frame]: c = o.rolling @@ -367,9 +367,9 @@ def test_constructor(self): with pytest.raises(ValueError): c(window=2, min_periods=1, center=w) + @td.skip_if_no_scipy def test_constructor_with_win_type(self): # GH 13383 - tm._skip_if_no_scipy() for o in [self.series, self.frame]: c = o.rolling c(0, win_type='boxcar') @@ -839,10 +839,9 @@ def test_rolling_count(self): def test_rolling_mean(self): self._check_moment_func(mom.rolling_mean, np.mean, name='mean') + @td.skip_if_no_scipy def test_cmov_mean(self): # GH 8238 - tm._skip_if_no_scipy() - vals = np.array([6.95, 15.21, 4.72, 9.12, 13.81, 13.49, 16.68, 9.48, 10.63, 14.48]) xp = np.array([np.nan, np.nan, 9.962, 11.27, 11.564, 12.516, 12.818, @@ -856,10 +855,9 @@ def test_cmov_mean(self): rs = Series(vals).rolling(5, center=True).mean() tm.assert_series_equal(xp, rs) + @td.skip_if_no_scipy def test_cmov_window(self): # GH 8238 - tm._skip_if_no_scipy() - vals = np.array([6.95, 15.21, 4.72, 9.12, 13.81, 13.49, 16.68, 9.48, 10.63, 14.48]) xp = np.array([np.nan, np.nan, 9.962, 11.27, 11.564, 12.516, 12.818, @@ -873,10 +871,9 @@ def test_cmov_window(self): rs = Series(vals).rolling(5, win_type='boxcar', center=True).mean() tm.assert_series_equal(xp, rs) + @td.skip_if_no_scipy def test_cmov_window_corner(self): # GH 8238 - tm._skip_if_no_scipy() - # all nan vals = np.empty(10, dtype=float) vals.fill(np.nan) @@ -897,10 +894,9 @@ def test_cmov_window_corner(self): assert np.isnan(rs).all() assert len(rs) == 5 + @td.skip_if_no_scipy def test_cmov_window_frame(self): # Gh 8238 - tm._skip_if_no_scipy() - vals = np.array([[12.18, 3.64], [10.18, 9.16], [13.24, 14.61], [4.51, 8.11], [6.15, 11.44], [9.14, 6.21], [11.31, 10.67], [2.94, 6.51], [9.42, 8.39], [12.44, @@ -929,9 +925,8 @@ def test_cmov_window_frame(self): rs = DataFrame(vals).rolling(5, win_type='boxcar', center=True).sum() tm.assert_frame_equal(DataFrame(xp), rs) + @td.skip_if_no_scipy def test_cmov_window_na_min_periods(self): - tm._skip_if_no_scipy() - # min_periods vals = Series(np.random.randn(10)) vals[4] = np.nan @@ -942,10 +937,9 @@ def test_cmov_window_na_min_periods(self): center=True).mean() tm.assert_series_equal(xp, rs) + @td.skip_if_no_scipy def test_cmov_window_regular(self): # GH 8238 - tm._skip_if_no_scipy() - win_types = ['triang', 'blackman', 'hamming', 'bartlett', 'bohman', 'blackmanharris', 'nuttall', 'barthann'] @@ -975,10 +969,9 @@ def test_cmov_window_regular(self): rs = Series(vals).rolling(5, win_type=wt, center=True).mean() tm.assert_series_equal(xp, rs) + @td.skip_if_no_scipy def test_cmov_window_regular_linear_range(self): # GH 8238 - tm._skip_if_no_scipy() - win_types = ['triang', 'blackman', 'hamming', 'bartlett', 'bohman', 'blackmanharris', 'nuttall', 'barthann'] @@ -992,10 +985,9 @@ def test_cmov_window_regular_linear_range(self): rs = Series(vals).rolling(5, win_type=wt, center=True).mean() tm.assert_series_equal(xp, rs) + @td.skip_if_no_scipy def test_cmov_window_regular_missing_data(self): # GH 8238 - tm._skip_if_no_scipy() - win_types = ['triang', 'blackman', 'hamming', 'bartlett', 'bohman', 'blackmanharris', 'nuttall', 'barthann'] @@ -1025,10 +1017,9 @@ def test_cmov_window_regular_missing_data(self): rs = Series(vals).rolling(5, win_type=wt, min_periods=3).mean() tm.assert_series_equal(xp, rs) + @td.skip_if_no_scipy def test_cmov_window_special(self): # GH 8238 - tm._skip_if_no_scipy() - win_types = ['kaiser', 'gaussian', 'general_gaussian', 'slepian'] kwds = [{'beta': 1.}, {'std': 1.}, {'power': 2., 'width': 2.}, {'width': 0.5}] @@ -1052,10 +1043,9 @@ def test_cmov_window_special(self): rs = Series(vals).rolling(5, win_type=wt, center=True).mean(**k) tm.assert_series_equal(xp, rs) + @td.skip_if_no_scipy def test_cmov_window_special_linear_range(self): # GH 8238 - tm._skip_if_no_scipy() - win_types = ['kaiser', 'gaussian', 'general_gaussian', 'slepian'] kwds = [{'beta': 1.}, {'std': 1.}, {'power': 2., 'width': 2.}, {'width': 0.5}] @@ -1259,19 +1249,15 @@ def test_rolling_var(self): self._check_moment_func(mom.rolling_var, lambda x: np.var(x, ddof=0), name='var', ddof=0) + @td.skip_if_no_scipy def test_rolling_skew(self): - try: - from scipy.stats import skew - except ImportError: - pytest.skip('no scipy') + from scipy.stats import skew self._check_moment_func(mom.rolling_skew, lambda x: skew(x, bias=False), name='skew') + @td.skip_if_no_scipy def test_rolling_kurt(self): - try: - from scipy.stats import kurtosis - except ImportError: - pytest.skip('no scipy') + from scipy.stats import kurtosis self._check_moment_func(mom.rolling_kurt, lambda x: kurtosis(x, bias=False), name='kurt') diff --git a/pandas/util/_test_decorators.py b/pandas/util/_test_decorators.py index 0b2d50d06a66c..95a9a8fed42f7 100644 --- a/pandas/util/_test_decorators.py +++ b/pandas/util/_test_decorators.py @@ -94,6 +94,11 @@ def _skip_if_not_us_locale(): return True +def _skip_if_no_scipy(): + return not (safe_import('scipy.stats') and safe_import('scipy.sparse') and + safe_import('scipy.interpolate')) + + def skip_if_no(package, min_version=None): """ Generic function to help skip test functions when required packages are not @@ -119,9 +124,11 @@ def skip_if_no(package, min_version=None): The decorated function wrapped within a pytest ``skip_if`` mark """ def decorated_func(func): + msg = "Could not import '{}'".format(package) + if min_version: + msg += " satisfying a min_version of {}".format(min_version) return pytest.mark.skipif( - not safe_import(package, min_version=min_version), - reason="Could not import '{}'".format(package) + not safe_import(package, min_version=min_version), reason=msg )(func) return decorated_func @@ -144,3 +151,5 @@ def decorated_func(func): reason="Specific locale is set " "{lang}".format( lang=locale.getlocale()[0])) +skip_if_no_scipy = pytest.mark.skipif(_skip_if_no_scipy(), + reason="Missing SciPy requirement")