diff --git a/.travis.yml b/.travis.yml index 97bf881f3b6fc..b0331941e2a1e 100644 --- a/.travis.yml +++ b/.travis.yml @@ -86,6 +86,7 @@ matrix: - JOB_NAME: "36" - TEST_ARGS="--skip-slow --skip-network" - PANDAS_TESTING_MODE="deprecate" + - CONDA_FORGE=true addons: apt: packages: diff --git a/ci/install_travis.sh b/ci/install_travis.sh index b337f6e443be2..12202b4ceee70 100755 --- a/ci/install_travis.sh +++ b/ci/install_travis.sh @@ -53,14 +53,17 @@ conda config --set ssl_verify false || exit 1 conda config --set always_yes true --set changeps1 false || exit 1 conda update -q conda +echo "[add channels]" # add the pandas channel to take priority # to add extra packages -echo "[add channels]" conda config --add channels pandas || exit 1 conda config --remove channels defaults || exit 1 conda config --add channels defaults || exit 1 -conda install anaconda-client +if [ "$CONDA_FORGE" ]; then + # add conda-forge channel as priority + conda config --add channels conda-forge || exit 1 +fi # Useful for debugging any issues with conda conda info -a || exit 1 diff --git a/ci/requirements-3.6.run b/ci/requirements-3.6.run index 9a6c1c7edbc5e..41c9680ce1b7e 100644 --- a/ci/requirements-3.6.run +++ b/ci/requirements-3.6.run @@ -14,6 +14,7 @@ html5lib jinja2 sqlalchemy pymysql +feather-format # psycopg2 (not avail on defaults ATM) beautifulsoup4 s3fs diff --git a/ci/requirements-3.6.sh b/ci/requirements-3.6.sh deleted file mode 100644 index 7d88ede751ec8..0000000000000 --- a/ci/requirements-3.6.sh +++ /dev/null @@ -1,7 +0,0 @@ -#!/bin/bash - -source activate pandas - -echo "install 36" - -conda install -n pandas -c conda-forge feather-format diff --git a/pandas/tests/frame/test_missing.py b/pandas/tests/frame/test_missing.py index 80ea01d3a05aa..923ed2e7c3444 100644 --- a/pandas/tests/frame/test_missing.py +++ b/pandas/tests/frame/test_missing.py @@ -548,7 +548,8 @@ def test_interp_nan_idx(self): df.interpolate(method='values') def test_interp_various(self): - tm._skip_if_no_scipy() + tm.skip_if_no_package('scipy', max_version='0.19.0') + 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') diff --git a/pandas/tests/frame/test_rank.py b/pandas/tests/frame/test_rank.py index 151a89888c329..b115218d76958 100644 --- a/pandas/tests/frame/test_rank.py +++ b/pandas/tests/frame/test_rank.py @@ -193,7 +193,8 @@ def test_rank_axis(self): tm.assert_frame_equal(df.rank(axis=1), df.rank(axis='columns')) def test_rank_methods_frame(self): - tm.skip_if_no_package('scipy', '0.13', 'scipy.stats.rankdata') + tm.skip_if_no_package('scipy', min_version='0.13', + app='scipy.stats.rankdata') import scipy from scipy.stats import rankdata diff --git a/pandas/tests/series/test_missing.py b/pandas/tests/series/test_missing.py index 87cfcf32229b4..9e997da517bf6 100644 --- a/pandas/tests/series/test_missing.py +++ b/pandas/tests/series/test_missing.py @@ -827,7 +827,8 @@ def test_interp_quad(self): assert_series_equal(result, expected) def test_interp_scipy_basic(self): - tm._skip_if_no_scipy() + tm.skip_if_no_package('scipy', max_version='0.19.0') + s = Series([1, 3, np.nan, 12, np.nan, 25]) # slinear expected = Series([1., 3., 7.5, 12., 18.5, 25.]) @@ -1027,8 +1028,8 @@ def test_spline(self): def test_spline_extrapolate(self): tm.skip_if_no_package( - 'scipy', '0.15', - 'setting ext on scipy.interpolate.UnivariateSpline') + '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.]) diff --git a/pandas/tests/series/test_rank.py b/pandas/tests/series/test_rank.py index 99257b343310f..f47eae3adc3ae 100644 --- a/pandas/tests/series/test_rank.py +++ b/pandas/tests/series/test_rank.py @@ -246,7 +246,8 @@ def _check(s, expected, method='average'): _check(series, results[method], method=method) def test_rank_methods_series(self): - tm.skip_if_no_package('scipy', '0.13', 'scipy.stats.rankdata') + tm.skip_if_no_package('scipy', min_version='0.13', + app='scipy.stats.rankdata') import scipy from scipy.stats import rankdata diff --git a/pandas/tests/sparse/test_frame.py b/pandas/tests/sparse/test_frame.py index 4cd5a643ce4be..c0c678c184ee8 100644 --- a/pandas/tests/sparse/test_frame.py +++ b/pandas/tests/sparse/test_frame.py @@ -1129,10 +1129,10 @@ def test_isnotnull(self): @pytest.mark.parametrize('index', [None, list('ab')]) # noqa: F811 @pytest.mark.parametrize('columns', [None, list('cd')]) @pytest.mark.parametrize('fill_value', [None, 0, np.nan]) -@pytest.mark.parametrize('dtype', [object, bool, int, float, np.uint16]) +@pytest.mark.parametrize('dtype', [bool, int, float, np.uint16]) def test_from_to_scipy(spmatrix, index, columns, fill_value, dtype): # GH 4343 - tm._skip_if_no_scipy() + tm.skip_if_no_package('scipy') # Make one ndarray and from it one sparse matrix, both to be used for # constructing frames and comparing results @@ -1180,6 +1180,51 @@ def test_from_to_scipy(spmatrix, index, columns, fill_value, dtype): tm.assert_equal(sdf.to_coo().dtype, np.object_) +@pytest.mark.parametrize('fill_value', [None, 0, np.nan]) # noqa: F811 +def test_from_to_scipy_object(spmatrix, fill_value): + # GH 4343 + dtype = object + columns = list('cd') + index = list('ab') + tm.skip_if_no_package('scipy', max_version='0.19.0') + + # Make one ndarray and from it one sparse matrix, both to be used for + # constructing frames and comparing results + arr = np.eye(2, dtype=dtype) + try: + spm = spmatrix(arr) + assert spm.dtype == arr.dtype + except (TypeError, AssertionError): + # If conversion to sparse fails for this spmatrix type and arr.dtype, + # then the combination is not currently supported in NumPy, so we + # can just skip testing it thoroughly + return + + sdf = pd.SparseDataFrame(spm, index=index, columns=columns, + default_fill_value=fill_value) + + # Expected result construction is kind of tricky for all + # dtype-fill_value combinations; easiest to cast to something generic + # and except later on + rarr = arr.astype(object) + rarr[arr == 0] = np.nan + expected = pd.SparseDataFrame(rarr, index=index, columns=columns).fillna( + fill_value if fill_value is not None else np.nan) + + # Assert frame is as expected + sdf_obj = sdf.astype(object) + tm.assert_sp_frame_equal(sdf_obj, expected) + tm.assert_frame_equal(sdf_obj.to_dense(), expected.to_dense()) + + # Assert spmatrices equal + tm.assert_equal(dict(sdf.to_coo().todok()), dict(spm.todok())) + + # Ensure dtype is preserved if possible + res_dtype = object + tm.assert_contains_all(sdf.dtypes, {np.dtype(res_dtype)}) + tm.assert_equal(sdf.to_coo().dtype, res_dtype) + + class TestSparseDataFrameArithmetic(tm.TestCase): def test_numeric_op_scalar(self): diff --git a/pandas/tests/test_nanops.py b/pandas/tests/test_nanops.py index 937c20d009b6b..75a7555d58ca5 100644 --- a/pandas/tests/test_nanops.py +++ b/pandas/tests/test_nanops.py @@ -5,7 +5,7 @@ import warnings import numpy as np -from pandas import Series, isnull +from pandas import Series, isnull, _np_version_under1p9 from pandas.types.common import is_integer_dtype import pandas.core.nanops as nanops import pandas.util.testing as tm @@ -338,8 +338,7 @@ def test_nanmean_overflow(self): # is now consistent with numpy # numpy < 1.9.0 is not computing this correctly - from distutils.version import LooseVersion - if LooseVersion(np.__version__) >= '1.9.0': + if not _np_version_under1p9: for a in [2 ** 55, -2 ** 55, 20150515061816532]: s = Series(a, index=range(500), dtype=np.int64) result = s.mean() @@ -388,8 +387,7 @@ def test_nanstd(self): allow_tdelta=True, allow_obj='convert') def test_nansem(self): - tm.skip_if_no_package('scipy.stats') - tm._skip_if_scipy_0_17() + tm.skip_if_no_package('scipy', min_version='0.17.0') from scipy.stats import sem self.check_funs_ddof(nanops.nansem, sem, allow_complex=False, allow_str=False, allow_date=False, @@ -448,16 +446,14 @@ def _skew_kurt_wrap(self, values, axis=None, func=None): return result def test_nanskew(self): - tm.skip_if_no_package('scipy.stats') - tm._skip_if_scipy_0_17() + tm.skip_if_no_package('scipy', min_version='0.17.0') from scipy.stats import skew func = partial(self._skew_kurt_wrap, func=skew) self.check_funs(nanops.nanskew, func, allow_complex=False, allow_str=False, allow_date=False, allow_tdelta=False) def test_nankurt(self): - tm.skip_if_no_package('scipy.stats') - tm._skip_if_scipy_0_17() + tm.skip_if_no_package('scipy', min_version='0.17.0') from scipy.stats import kurtosis func1 = partial(kurtosis, fisher=True) func = partial(self._skew_kurt_wrap, func=func1) diff --git a/pandas/tests/test_window.py b/pandas/tests/test_window.py index 3f2973a9834ca..b7164d31b2a5e 100644 --- a/pandas/tests/test_window.py +++ b/pandas/tests/test_window.py @@ -905,7 +905,7 @@ def test_cmov_window_na_min_periods(self): def test_cmov_window_regular(self): # GH 8238 - tm._skip_if_no_scipy() + tm.skip_if_no_package('scipy', max_version='0.19.0') win_types = ['triang', 'blackman', 'hamming', 'bartlett', 'bohman', 'blackmanharris', 'nuttall', 'barthann'] @@ -938,7 +938,7 @@ def test_cmov_window_regular(self): def test_cmov_window_regular_linear_range(self): # GH 8238 - tm._skip_if_no_scipy() + tm.skip_if_no_package('scipy', max_version='0.19.0') win_types = ['triang', 'blackman', 'hamming', 'bartlett', 'bohman', 'blackmanharris', 'nuttall', 'barthann'] @@ -955,7 +955,7 @@ def test_cmov_window_regular_linear_range(self): def test_cmov_window_regular_missing_data(self): # GH 8238 - tm._skip_if_no_scipy() + tm.skip_if_no_package('scipy', max_version='0.19.0') win_types = ['triang', 'blackman', 'hamming', 'bartlett', 'bohman', 'blackmanharris', 'nuttall', 'barthann'] @@ -988,7 +988,7 @@ def test_cmov_window_regular_missing_data(self): def test_cmov_window_special(self): # GH 8238 - tm._skip_if_no_scipy() + tm.skip_if_no_package('scipy', max_version='0.19.0') win_types = ['kaiser', 'gaussian', 'general_gaussian', 'slepian'] kwds = [{'beta': 1.}, {'std': 1.}, {'power': 2., @@ -1015,7 +1015,7 @@ def test_cmov_window_special(self): def test_cmov_window_special_linear_range(self): # GH 8238 - tm._skip_if_no_scipy() + tm.skip_if_no_package('scipy', max_version='0.19.0') win_types = ['kaiser', 'gaussian', 'general_gaussian', 'slepian'] kwds = [{'beta': 1.}, {'std': 1.}, {'power': 2., diff --git a/pandas/util/testing.py b/pandas/util/testing.py index 74ff480a9c198..529ecef3e2d6a 100644 --- a/pandas/util/testing.py +++ b/pandas/util/testing.py @@ -304,14 +304,6 @@ def _skip_if_no_scipy(): pytest.skip('scipy.sparse missing') -def _skip_if_scipy_0_17(): - import scipy - v = scipy.__version__ - if v >= LooseVersion("0.17.0"): - import pytest - pytest.skip("scipy 0.17") - - def _check_if_lzma(): try: return compat.import_lzma() @@ -2020,15 +2012,18 @@ def __init__(self, *args, **kwargs): # Dependency checks. Copied this from Nipy/Nipype (Copyright of # respective developers, license: BSD-3) -def package_check(pkg_name, version=None, app='pandas', checker=LooseVersion): - """Check that the minimal version of the required package is installed. +def package_check(pkg_name, min_version=None, max_version=None, app='pandas', + checker=LooseVersion): + """Check that the min/max version of the required package is installed. Parameters ---------- pkg_name : string Name of the required package. - version : string, optional + min_version : string, optional Minimal version number for required package. + max_version : string, optional + Max version number for required package. app : string, optional Application that is performing the check. For instance, the name of the tutorial being executed that depends on specific @@ -2040,7 +2035,6 @@ def package_check(pkg_name, version=None, app='pandas', checker=LooseVersion): Examples -------- package_check('numpy', '1.3') - package_check('networkx', '1.0', 'tutorial1') """ @@ -2049,8 +2043,10 @@ def package_check(pkg_name, version=None, app='pandas', checker=LooseVersion): msg = '%s requires %s' % (app, pkg_name) else: msg = 'module requires %s' % pkg_name - if version: - msg += ' with version >= %s' % (version,) + if min_version: + msg += ' with version >= %s' % (min_version,) + if max_version: + msg += ' with version < %s' % (max_version,) try: mod = __import__(pkg_name) except ImportError: @@ -2059,7 +2055,9 @@ def package_check(pkg_name, version=None, app='pandas', checker=LooseVersion): have_version = mod.__version__ except AttributeError: pytest.skip('Cannot find version for %s' % pkg_name) - if version and checker(have_version) < checker(version): + if min_version and checker(have_version) < checker(min_version): + pytest.skip(msg) + if max_version and checker(have_version) >= checker(max_version): pytest.skip(msg)