From bcaf944b63a80ae90e326c71080babfea132457b Mon Sep 17 00:00:00 2001 From: "H. Vetinari" Date: Mon, 25 Mar 2019 07:38:07 +0100 Subject: [PATCH 01/21] DEPS: bump numpy minimum to 1.13.3 --- README.md | 2 +- ci/azure/windows.yml | 2 +- ci/deps/azure-35-compat.yaml | 12 ++--- ci/deps/azure-36-locale.yaml | 8 +-- ci/deps/azure-36-locale_slow.yaml | 6 +-- ci/deps/azure-37-locale.yaml | 2 +- ci/deps/azure-37-numpydev.yaml | 2 +- ci/deps/azure-macos-35.yaml | 6 +-- ci/deps/azure-windows-36.yaml | 2 +- ci/deps/azure-windows-37.yaml | 2 +- ci/deps/travis-36-doc.yaml | 2 +- ci/deps/travis-36-locale.yaml | 4 +- ci/deps/travis-36-slow.yaml | 2 +- ci/deps/travis-36.yaml | 6 +-- ci/deps/travis-37.yaml | 2 +- doc/source/install.rst | 10 ++-- doc/source/whatsnew/v0.25.0.rst | 14 ++++- environment.yml | 4 +- pandas/_libs/tslibs/timestamps.pyx | 14 +---- pandas/compat/numpy/__init__.py | 8 ++- pandas/core/arrays/categorical.py | 7 --- pandas/core/arrays/numpy_.py | 16 +----- pandas/core/arrays/sparse.py | 4 +- pandas/core/computation/check.py | 2 +- pandas/core/groupby/generic.py | 5 +- pandas/plotting/_compat.py | 5 +- pandas/tests/arrays/test_numpy.py | 5 +- pandas/tests/plotting/common.py | 5 +- pandas/tests/plotting/test_datetimelike.py | 61 ++++++---------------- pandas/tests/plotting/test_frame.py | 8 +-- pandas/tests/plotting/test_hist_method.py | 25 +++------ pandas/tests/plotting/test_misc.py | 2 - pandas/tests/plotting/test_series.py | 5 +- pandas/tests/test_expressions.py | 5 +- pandas/tests/test_nanops.py | 18 +------ pandas/util/_test_decorators.py | 15 ------ requirements-dev.txt | 4 +- setup.py | 2 +- 38 files changed, 92 insertions(+), 212 deletions(-) diff --git a/README.md b/README.md index dcf39864e46e2..e8bfd28cc8208 100644 --- a/README.md +++ b/README.md @@ -164,7 +164,7 @@ pip install pandas ``` ## Dependencies -- [NumPy](https://www.numpy.org): 1.12.0 or higher +- [NumPy](https://www.numpy.org): 1.13.3 or higher - [python-dateutil](https://labix.org/python-dateutil): 2.5.0 or higher - [pytz](https://pythonhosted.org/pytz): 2015.4 or higher diff --git a/ci/azure/windows.yml b/ci/azure/windows.yml index cd5879bf55e4b..1e3390a7f8d9b 100644 --- a/ci/azure/windows.yml +++ b/ci/azure/windows.yml @@ -8,7 +8,7 @@ jobs: vmImage: ${{ parameters.vmImage }} strategy: matrix: - py36_np14: + py36_np15: ENV_FILE: ci/deps/azure-windows-36.yaml CONDA_PY: "36" diff --git a/ci/deps/azure-35-compat.yaml b/ci/deps/azure-35-compat.yaml index adae9bc761a42..3001bf47d0838 100644 --- a/ci/deps/azure-35-compat.yaml +++ b/ci/deps/azure-35-compat.yaml @@ -4,18 +4,18 @@ channels: - conda-forge dependencies: - beautifulsoup4==4.4.1 - - bottleneck=1.2.0 + - bottleneck=1.2.1 - cython=0.28.2 - hypothesis>=3.58.0 - jinja2=2.8 - - numexpr=2.6.1 - - numpy=1.12.0 + - numexpr=2.6.2 + - numpy=1.13.3 - openpyxl=2.4.0 - pytables=3.4.2 - python-dateutil=2.5.0 - - python=3.5* - - pytz=2015.4 - - scipy=0.18.1 + - python=3.5.* + - pytz=2013b + - scipy=0.19.0 - xlrd=1.0.0 - xlsxwriter=0.7.7 - xlwt=1.0.0 diff --git a/ci/deps/azure-36-locale.yaml b/ci/deps/azure-36-locale.yaml index c74d56443be5d..4209247cd6ce5 100644 --- a/ci/deps/azure-36-locale.yaml +++ b/ci/deps/azure-36-locale.yaml @@ -4,15 +4,15 @@ channels: - conda-forge dependencies: - beautifulsoup4==4.5.1 - - bottleneck=1.2.0 + - bottleneck=1.2.* - cython=0.28.2 - lxml - - matplotlib=2.0.0 - - numpy=1.12.0 + - matplotlib=2.2.2 + - numpy=1.14.* - openpyxl=2.4.0 - python-dateutil - python-blosc - - python=3.6 + - python=3.6.* - pytz=2016.10 - scipy - sqlalchemy=1.1.4 diff --git a/ci/deps/azure-36-locale_slow.yaml b/ci/deps/azure-36-locale_slow.yaml index 3f788e5ddcf39..fa2749017ec07 100644 --- a/ci/deps/azure-36-locale_slow.yaml +++ b/ci/deps/azure-36-locale_slow.yaml @@ -10,14 +10,14 @@ dependencies: - ipython - jinja2 - lxml - - matplotlib + - matplotlib=3.0.* - nomkl - numexpr - - numpy + - numpy=1.15.* - openpyxl - pytables - python-dateutil - - python=3.6* + - python=3.6.* - pytz - s3fs - scipy diff --git a/ci/deps/azure-37-locale.yaml b/ci/deps/azure-37-locale.yaml index 9d598cddce91a..71d69d0ab68c1 100644 --- a/ci/deps/azure-37-locale.yaml +++ b/ci/deps/azure-37-locale.yaml @@ -16,7 +16,7 @@ dependencies: - openpyxl - pytables - python-dateutil - - python=3.7* + - python=3.7.* - pytz - s3fs - scipy diff --git a/ci/deps/azure-37-numpydev.yaml b/ci/deps/azure-37-numpydev.yaml index e58c1f599279c..d940463e2768c 100644 --- a/ci/deps/azure-37-numpydev.yaml +++ b/ci/deps/azure-37-numpydev.yaml @@ -2,7 +2,7 @@ name: pandas-dev channels: - defaults dependencies: - - python=3.7* + - python=3.7.* - pytz - Cython>=0.28.2 # universal diff --git a/ci/deps/azure-macos-35.yaml b/ci/deps/azure-macos-35.yaml index 38625c6563753..591266348a5f1 100644 --- a/ci/deps/azure-macos-35.yaml +++ b/ci/deps/azure-macos-35.yaml @@ -8,14 +8,14 @@ dependencies: - html5lib - jinja2 - lxml - - matplotlib=2.2.0 + - matplotlib=2.2.3 - nomkl - numexpr - - numpy=1.12.0 + - numpy=1.13.3 - openpyxl - pyarrow - pytables - - python=3.5* + - python=3.5.* - pytz - xarray - xlrd diff --git a/ci/deps/azure-windows-36.yaml b/ci/deps/azure-windows-36.yaml index 5ce55a4cb4c0e..8661fc3ab65d2 100644 --- a/ci/deps/azure-windows-36.yaml +++ b/ci/deps/azure-windows-36.yaml @@ -9,7 +9,7 @@ dependencies: - fastparquet>=0.2.1 - matplotlib - numexpr - - numpy=1.14* + - numpy=1.15.* - openpyxl - parquet-cpp - pyarrow diff --git a/ci/deps/azure-windows-37.yaml b/ci/deps/azure-windows-37.yaml index 96ddc1d6293d8..5384e794d442a 100644 --- a/ci/deps/azure-windows-37.yaml +++ b/ci/deps/azure-windows-37.yaml @@ -9,7 +9,7 @@ dependencies: - html5lib - jinja2 - lxml - - matplotlib=3.0.1 + - matplotlib=2.2.* - numexpr - numpy=1.14.* - openpyxl diff --git a/ci/deps/travis-36-doc.yaml b/ci/deps/travis-36-doc.yaml index 8015f7bdc81c6..9d6cbd82fdc05 100644 --- a/ci/deps/travis-36-doc.yaml +++ b/ci/deps/travis-36-doc.yaml @@ -29,7 +29,7 @@ dependencies: - pytables - python-dateutil - python-snappy - - python=3.6* + - python=3.6.* - pytz - scipy - seaborn diff --git a/ci/deps/travis-36-locale.yaml b/ci/deps/travis-36-locale.yaml index fb0401958f05a..ba57bfb9bfe6f 100644 --- a/ci/deps/travis-36-locale.yaml +++ b/ci/deps/travis-36-locale.yaml @@ -9,7 +9,7 @@ dependencies: - ipython - jinja2 - lxml - - matplotlib + - matplotlib=3.0.1 - nomkl - numexpr - numpy @@ -18,7 +18,7 @@ dependencies: - pymysql=0.7.9 - pytables - python-dateutil - - python=3.6* + - python=3.6.* - pytz - s3fs - scipy diff --git a/ci/deps/travis-36-slow.yaml b/ci/deps/travis-36-slow.yaml index 46875d59411d9..365c78c02f4d4 100644 --- a/ci/deps/travis-36-slow.yaml +++ b/ci/deps/travis-36-slow.yaml @@ -16,7 +16,7 @@ dependencies: - pymysql - pytables - python-dateutil - - python=3.6* + - python=3.6.* - pytz - s3fs - scipy diff --git a/ci/deps/travis-36.yaml b/ci/deps/travis-36.yaml index 06fc0d76a3d16..763142bf438e7 100644 --- a/ci/deps/travis-36.yaml +++ b/ci/deps/travis-36.yaml @@ -11,17 +11,17 @@ dependencies: - gcsfs - geopandas - html5lib - - matplotlib + - matplotlib=3.0.0 - nomkl - numexpr - - numpy + - numpy=1.15.* - openpyxl - psycopg2 - pyarrow=0.9.0 - pymysql - pytables - python-snappy - - python=3.6.6 + - python=3.6.* - pytz - s3fs - scikit-learn diff --git a/ci/deps/travis-37.yaml b/ci/deps/travis-37.yaml index f71d29fe13378..3ddd08e640806 100644 --- a/ci/deps/travis-37.yaml +++ b/ci/deps/travis-37.yaml @@ -4,7 +4,7 @@ channels: - conda-forge - c3i_test dependencies: - - python=3.7 + - python=3.7.* - botocore>=1.11 - cython>=0.28.2 - numpy diff --git a/doc/source/install.rst b/doc/source/install.rst index 5df633e8dd984..a482fc6645439 100644 --- a/doc/source/install.rst +++ b/doc/source/install.rst @@ -224,7 +224,7 @@ Dependencies ------------ * `setuptools `__: 24.2.0 or higher -* `NumPy `__: 1.12.0 or higher +* `NumPy `__: 1.13.3 or higher * `python-dateutil `__: 2.5.0 or higher * `pytz `__: 2015.4 or higher @@ -235,11 +235,11 @@ Recommended Dependencies * `numexpr `__: for accelerating certain numerical operations. ``numexpr`` uses multiple cores as well as smart chunking and caching to achieve large speedups. - If installed, must be Version 2.6.1 or higher. + If installed, must be Version 2.6.2 or higher. * `bottleneck `__: for accelerating certain types of ``nan`` evaluations. ``bottleneck`` uses specialized cython routines to achieve large speedups. If installed, - must be Version 1.2.0 or higher. + must be Version 1.2.1 or higher. .. note:: @@ -254,7 +254,7 @@ Optional Dependencies * `Cython `__: Only necessary to build development version. Version 0.28.2 or higher. -* `SciPy `__: miscellaneous statistical functions, Version 0.18.1 or higher +* `SciPy `__: miscellaneous statistical functions, Version 0.19.0 or higher * `xarray `__: pandas like handling for > 2 dims. Version 0.7.0 or higher is recommended. * `PyTables `__: necessary for HDF5-based storage, Version 3.4.2 or higher * `pyarrow `__ (>= 0.9.0): necessary for feather-based storage. @@ -265,7 +265,7 @@ Optional Dependencies * `pymysql `__: for MySQL. * `SQLite `__: for SQLite, this is included in Python's standard library by default. -* `matplotlib `__: for plotting, Version 2.0.0 or higher. +* `matplotlib `__: for plotting, Version 2.2.2 or higher. * For Excel I/O: * `xlrd/xlwt `__: Excel reading (xlrd), version 1.0.0 or higher required, and writing (xlwt) diff --git a/doc/source/whatsnew/v0.25.0.rst b/doc/source/whatsnew/v0.25.0.rst index 58c07a14dec39..5befea2fd43a9 100644 --- a/doc/source/whatsnew/v0.25.0.rst +++ b/doc/source/whatsnew/v0.25.0.rst @@ -115,27 +115,37 @@ Increased minimum versions for dependencies ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ Due to dropping support for Python 2.7, a number of optional dependencies have updated minimum versions. -Independently, some minimum supported versions of dependencies were updated (:issue:`23519`, :issue:`24942`). +Independently, some minimum supported versions of dependencies were updated (:issue:`23519`, :issue:`24942`, :issue:`25554`, :issue:`25752`). If installed, we now require: +-----------------+-----------------+----------+ | Package | Minimum Version | Required | +=================+=================+==========+ +| numpy | 1.13.3 | X | ++-----------------+-----------------+----------+ | beautifulsoup4 | 4.4.1 | | +-----------------+-----------------+----------+ +| bottleneck | 1.2.1 | | ++-----------------+-----------------+----------+ +| matplotlib | 2.2.2 | | ++-----------------+-----------------+----------+ +| numexpr | 2.6.2 | | ++-----------------+-----------------+----------+ | openpyxl | 2.4.0 | | +-----------------+-----------------+----------+ | pymysql | 0.7.9 | | +-----------------+-----------------+----------+ | pytz | 2015.4 | | +-----------------+-----------------+----------+ +| scipy | 0.19.0 | | ++-----------------+-----------------+----------+ | sqlalchemy | 1.1.4 | | +-----------------+-----------------+----------+ | xlsxwriter | 0.7.7 | | +-----------------+-----------------+----------+ | xlwt | 1.0.0 | | +-----------------+-----------------+----------+ -| pytest (dev) | 4.0.2 | | +| pytest | 4.0.2 | (dev) | +-----------------+-----------------+----------+ .. _whatsnew_0250.api.other: diff --git a/environment.yml b/environment.yml index 41f013c52041c..01165c3050670 100644 --- a/environment.yml +++ b/environment.yml @@ -30,14 +30,14 @@ dependencies: - blosc - botocore>=1.11 - boto3 - - bottleneck>=1.2.0 + - bottleneck>=1.2.1 - fastparquet>=0.2.1 - html5lib - ipython>=5.6.0 - ipykernel - jinja2 - lxml - - matplotlib>=2.0.0 + - matplotlib>=2.2.2 - nbsphinx - numexpr>=2.6.8 - openpyxl diff --git a/pandas/_libs/tslibs/timestamps.pyx b/pandas/_libs/tslibs/timestamps.pyx index c4d47a3c2384a..ae15fb36169be 100644 --- a/pandas/_libs/tslibs/timestamps.pyx +++ b/pandas/_libs/tslibs/timestamps.pyx @@ -129,18 +129,6 @@ class RoundTo(object): return 4 -cdef inline _npdivmod(x1, x2): - """implement divmod for numpy < 1.13""" - return np.floor_divide(x1, x2), np.remainder(x1, x2) - - -try: - from numpy import divmod as npdivmod -except ImportError: - # numpy < 1.13 - npdivmod = _npdivmod - - cdef inline _floor_int64(values, unit): return values - np.remainder(values, unit) @@ -183,7 +171,7 @@ def round_nsint64(values, mode, freq): # for odd unit there is no need of a tie break if unit % 2: return _rounddown_int64(values, unit) - quotient, remainder = npdivmod(values, unit) + quotient, remainder = np.divmod(values, unit) mask = np.logical_or( remainder > (unit // 2), np.logical_and(remainder == (unit // 2), quotient % 2) diff --git a/pandas/compat/numpy/__init__.py b/pandas/compat/numpy/__init__.py index 6e9f768d8bd68..aed8fd2710e6f 100644 --- a/pandas/compat/numpy/__init__.py +++ b/pandas/compat/numpy/__init__.py @@ -9,18 +9,17 @@ # numpy versioning _np_version = np.__version__ _nlv = LooseVersion(_np_version) -_np_version_under1p13 = _nlv < LooseVersion('1.13') _np_version_under1p14 = _nlv < LooseVersion('1.14') _np_version_under1p15 = _nlv < LooseVersion('1.15') _np_version_under1p16 = _nlv < LooseVersion('1.16') _np_version_under1p17 = _nlv < LooseVersion('1.17') -if _nlv < '1.12': +if _nlv < '1.13.3': raise ImportError('this version of pandas is incompatible with ' - 'numpy < 1.12.0\n' + 'numpy < 1.13.3\n' 'your numpy version is {0}.\n' - 'Please upgrade numpy to >= 1.12.0 to use ' + 'Please upgrade numpy to >= 1.13.3 to use ' 'this pandas version'.format(_np_version)) @@ -64,7 +63,6 @@ def np_array_datetime64_compat(arr, *args, **kwargs): __all__ = ['np', - '_np_version_under1p13', '_np_version_under1p14', '_np_version_under1p15', '_np_version_under1p16', diff --git a/pandas/core/arrays/categorical.py b/pandas/core/arrays/categorical.py index 2a6cc6c742a52..ecb9000ff2f2c 100644 --- a/pandas/core/arrays/categorical.py +++ b/pandas/core/arrays/categorical.py @@ -101,13 +101,6 @@ def f(self, other): ret[na_mask] = False return ret - # Numpy < 1.13 may convert a scalar to a zerodim array during - # comparison operation when second arg has higher priority, e.g. - # - # cat[0] < cat - # - # With cat[0], for example, being ``np.int64(1)`` by the time it gets - # into this function would become ``np.array(1)``. if is_scalar(other): if other in self.categories: i = self.categories.get_loc(other) diff --git a/pandas/core/arrays/numpy_.py b/pandas/core/arrays/numpy_.py index 8e2ab586cacb6..b2c2e1f411e6f 100644 --- a/pandas/core/arrays/numpy_.py +++ b/pandas/core/arrays/numpy_.py @@ -1,6 +1,7 @@ import numbers import numpy as np +from numpy.lib.mixins import NDArrayOperatorsMixin from pandas._libs import lib from pandas.compat.numpy import function as nv @@ -82,20 +83,9 @@ def itemsize(self): return self._dtype.itemsize -# TODO(NumPy1.13): remove this -# Compat for NumPy 1.12, which doesn't provide NDArrayOperatorsMixin -# or __array_ufunc__, so those operations won't be available to people -# on older NumPys. -# # We would normally write this as bases=(...), then "class Foo(*bases): # but Python2 doesn't allow unpacking tuples in the class statement. # So, we fall back to "object", to avoid writing a metaclass. -try: - from numpy.lib.mixins import NDArrayOperatorsMixin -except ImportError: - NDArrayOperatorsMixin = object - - class PandasArray(ExtensionArray, ExtensionOpsMixin, NDArrayOperatorsMixin): """ A pandas ExtensionArray for NumPy data. @@ -111,10 +101,6 @@ class PandasArray(ExtensionArray, ExtensionOpsMixin, NDArrayOperatorsMixin): The NumPy ndarray to wrap. Must be 1-dimensional. copy : bool, default False Whether to copy `values`. - - Notes - ----- - Operations like ``+`` and applying ufuncs requires NumPy>=1.13. """ # If you're wondering why pd.Series(cls) doesn't put the array in an # ExtensionBlock, search for `ABCPandasArray`. We check for diff --git a/pandas/core/arrays/sparse.py b/pandas/core/arrays/sparse.py index 8a4422120b7a3..436305558f761 100644 --- a/pandas/core/arrays/sparse.py +++ b/pandas/core/arrays/sparse.py @@ -1848,9 +1848,7 @@ def make_sparse(arr, kind='block', fill_value=None, dtype=None, copy=False): if isna(fill_value): mask = notna(arr) else: - # For str arrays in NumPy 1.12.0, operator!= below isn't - # element-wise but just returns False if fill_value is not str, - # so cast to object comparison to be safe + # cast to object comparison to be safe if is_string_dtype(arr): arr = arr.astype(object) diff --git a/pandas/core/computation/check.py b/pandas/core/computation/check.py index da89bde56fe18..c9b68661fd596 100644 --- a/pandas/core/computation/check.py +++ b/pandas/core/computation/check.py @@ -2,7 +2,7 @@ import warnings _NUMEXPR_INSTALLED = False -_MIN_NUMEXPR_VERSION = "2.6.1" +_MIN_NUMEXPR_VERSION = "2.6.2" _NUMEXPR_VERSION = None try: diff --git a/pandas/core/groupby/generic.py b/pandas/core/groupby/generic.py index 0604689c6bb2b..a33c3eb2ed278 100644 --- a/pandas/core/groupby/generic.py +++ b/pandas/core/groupby/generic.py @@ -16,8 +16,7 @@ from pandas._libs import Timestamp, lib import pandas.compat as compat -from pandas.compat import lzip -from pandas.compat.numpy import _np_version_under1p13 +from pandas.compat import lzip, map from pandas.errors import AbstractMethodError from pandas.util._decorators import Appender, Substitution @@ -1218,7 +1217,7 @@ def count(self): mask = (ids != -1) & ~isna(val) ids = ensure_platform_int(ids) - minlength = ngroups or (None if _np_version_under1p13 else 0) + minlength = ngroups or 0 out = np.bincount(ids[mask], minlength=minlength) return Series(out, diff --git a/pandas/plotting/_compat.py b/pandas/plotting/_compat.py index 48900c088a125..02dba9a6a99f1 100644 --- a/pandas/plotting/_compat.py +++ b/pandas/plotting/_compat.py @@ -18,8 +18,5 @@ def inner(): return inner -_mpl_ge_2_0_1 = _mpl_version('2.0.1', operator.ge) -_mpl_ge_2_1_0 = _mpl_version('2.1.0', operator.ge) -_mpl_ge_2_2_0 = _mpl_version('2.2.0', operator.ge) -_mpl_ge_2_2_2 = _mpl_version('2.2.2', operator.ge) +_mpl_eq_2_2_2 = _mpl_version('2.2.2', operator.eq) _mpl_ge_3_0_0 = _mpl_version('3.0.0', operator.ge) diff --git a/pandas/tests/arrays/test_numpy.py b/pandas/tests/arrays/test_numpy.py index 9cf26dce15d0a..5e4f6e376c1d3 100644 --- a/pandas/tests/arrays/test_numpy.py +++ b/pandas/tests/arrays/test_numpy.py @@ -5,8 +5,6 @@ import numpy as np import pytest -import pandas.util._test_decorators as td - import pandas as pd from pandas.arrays import PandasArray from pandas.core.arrays.numpy_ import PandasDtype @@ -178,7 +176,7 @@ def test_validate_reduction_keyword_args(): # ---------------------------------------------------------------------------- # Ops -@td.skip_if_no("numpy", min_version="1.13.0") + def test_ufunc(): arr = PandasArray(np.array([-1.0, 0.0, 1.0])) result = np.abs(arr) @@ -193,7 +191,6 @@ def test_ufunc(): tm.assert_extension_array_equal(r2, e2) -@td.skip_if_no("numpy", min_version="1.13.0") def test_basic_binop(): # Just a basic smoke test. The EA interface tests exercise this # more thoroughly. diff --git a/pandas/tests/plotting/common.py b/pandas/tests/plotting/common.py index 9067a724289fe..5036856cd6c7b 100644 --- a/pandas/tests/plotting/common.py +++ b/pandas/tests/plotting/common.py @@ -53,10 +53,7 @@ def setup_method(self, method): import matplotlib as mpl mpl.rcdefaults() - self.mpl_ge_2_0_1 = plotting._compat._mpl_ge_2_0_1() - self.mpl_ge_2_1_0 = plotting._compat._mpl_ge_2_1_0() - self.mpl_ge_2_2_0 = plotting._compat._mpl_ge_2_2_0() - self.mpl_ge_2_2_2 = plotting._compat._mpl_ge_2_2_2() + self.mpl_eq_2_2_2 = plotting._compat._mpl_eq_2_2_2() self.mpl_ge_3_0_0 = plotting._compat._mpl_ge_3_0_0() self.bp_n_objects = 7 diff --git a/pandas/tests/plotting/test_datetimelike.py b/pandas/tests/plotting/test_datetimelike.py index b8bcf83d8631b..de64212d8a09e 100644 --- a/pandas/tests/plotting/test_datetimelike.py +++ b/pandas/tests/plotting/test_datetimelike.py @@ -406,11 +406,9 @@ def test_get_finder(self): def test_finder_daily(self): day_lst = [10, 40, 252, 400, 950, 2750, 10000] - if (self.mpl_ge_3_0_0 or not self.mpl_ge_2_0_1 - or (self.mpl_ge_2_1_0 and not self.mpl_ge_2_2_2)): - # 2.0.0, 2.2.0 (exactly) or >= 3.0.0 + if self.mpl_ge_3_0_0 or self.mpl_eq_2_2_2: xpl1 = xpl2 = [Period('1999-1-1', freq='B').ordinal] * len(day_lst) - else: # 2.0.1, 2.1.0, 2.2.2, 2.2.3 + else: # 2.2.3, 2.2.4 xpl1 = [7565, 7564, 7553, 7546, 7518, 7428, 7066] xpl2 = [7566, 7564, 7554, 7546, 7519, 7429, 7066] @@ -436,11 +434,9 @@ def test_finder_daily(self): def test_finder_quarterly(self): yrs = [3.5, 11] - if (self.mpl_ge_3_0_0 or not self.mpl_ge_2_0_1 - or (self.mpl_ge_2_1_0 and not self.mpl_ge_2_2_2)): - # 2.0.0, 2.2.0 (exactly) or >= 3.0.0 + if self.mpl_ge_3_0_0 or self.mpl_eq_2_2_2: xpl1 = xpl2 = [Period('1988Q1').ordinal] * len(yrs) - else: # 2.0.1, 2.1.0, 2.2.2, 2.2.3 + else: # 2.2.3, 2.2.4 xpl1 = [68, 68] xpl2 = [72, 68] @@ -466,11 +462,9 @@ def test_finder_quarterly(self): def test_finder_monthly(self): yrs = [1.15, 2.5, 4, 11] - if (self.mpl_ge_3_0_0 or not self.mpl_ge_2_0_1 - or (self.mpl_ge_2_1_0 and not self.mpl_ge_2_2_2)): - # 2.0.0, 2.2.0 (exactly) or >= 3.0.0 + if self.mpl_ge_3_0_0 or self.mpl_eq_2_2_2: xpl1 = xpl2 = [Period('Jan 1988').ordinal] * len(yrs) - else: # 2.0.1, 2.1.0, 2.2.2, 2.2.3 + else: # 2.2.3, 2.2.4 xpl1 = [216, 216, 204, 204] xpl2 = [216, 216, 216, 204] @@ -504,11 +498,9 @@ def test_finder_monthly_long(self): @pytest.mark.slow def test_finder_annual(self): - if (self.mpl_ge_3_0_0 or not self.mpl_ge_2_0_1 - or (self.mpl_ge_2_1_0 and not self.mpl_ge_2_2_2)): - # 2.0.0, 2.2.0 (exactly) or >= 3.0.0 + if self.mpl_ge_3_0_0 or self.mpl_eq_2_2_2: xp = [1987, 1988, 1990, 1990, 1995, 2020, 2070, 2170] - else: # 2.0.1, 2.1.0, 2.2.2, 2.2.3 + else: # 2.2.3, 2.2.4 xp = [1986, 1986, 1990, 1990, 1995, 2020, 1970, 1970] xp = [Period(x, freq='A').ordinal for x in xp] @@ -545,10 +537,7 @@ def test_finder_hourly(self): ser.plot(ax=ax) xaxis = ax.get_xaxis() rs = xaxis.get_majorticklocs()[0] - if self.mpl_ge_2_0_1: - xp = Period('1/1/1999', freq='H').ordinal - else: # 2.0.0 - xp = Period('1998-12-31 22:00', freq='H').ordinal + xp = Period('1/1/1999', freq='H').ordinal assert rs == xp @@ -563,9 +552,7 @@ def test_gaps(self): line = lines[0] data = line.get_xydata() - if (self.mpl_ge_3_0_0 or not self.mpl_ge_2_0_1 - or (self.mpl_ge_2_1_0 and not self.mpl_ge_2_2_2)): - # 2.0.0, 2.2.0 (exactly) or >= 3.0.0 + if self.mpl_ge_3_0_0 or self.mpl_eq_2_2_2: data = np.ma.MaskedArray(data, mask=isna(data), fill_value=np.nan) assert isinstance(data, np.ma.core.MaskedArray) @@ -584,9 +571,7 @@ def test_gaps(self): line = lines[0] data = line.get_xydata() - if (self.mpl_ge_3_0_0 or not self.mpl_ge_2_0_1 - or (self.mpl_ge_2_1_0 and not self.mpl_ge_2_2_2)): - # 2.0.0, 2.2.0 (exactly) or >= 3.0.0 + if self.mpl_ge_3_0_0 or self.mpl_eq_2_2_2: data = np.ma.MaskedArray(data, mask=isna(data), fill_value=np.nan) assert isinstance(data, np.ma.core.MaskedArray) @@ -604,9 +589,7 @@ def test_gaps(self): assert len(lines) == 1 line = lines[0] data = line.get_xydata() - if (self.mpl_ge_3_0_0 or not self.mpl_ge_2_0_1 - or (self.mpl_ge_2_1_0 and not self.mpl_ge_2_2_2)): - # 2.0.0, 2.2.0 (exactly) or >= 3.0.0 + if self.mpl_ge_3_0_0 or self.mpl_eq_2_2_2: data = np.ma.MaskedArray(data, mask=isna(data), fill_value=np.nan) assert isinstance(data, np.ma.core.MaskedArray) @@ -629,9 +612,7 @@ def test_gap_upsample(self): line = lines[0] data = line.get_xydata() - if (self.mpl_ge_3_0_0 or not self.mpl_ge_2_0_1 - or (self.mpl_ge_2_1_0 and not self.mpl_ge_2_2_2)): - # 2.0.0, 2.2.0 (exactly) or >= 3.0.0 + if self.mpl_ge_3_0_0 or self.mpl_eq_2_2_2: data = np.ma.MaskedArray(data, mask=isna(data), fill_value=np.nan) assert isinstance(data, np.ma.core.MaskedArray) @@ -1395,13 +1376,8 @@ def test_plot_outofbounds_datetime(self): def test_format_timedelta_ticks_narrow(self): - if self.mpl_ge_2_0_1: - expected_labels = (['00:00:00.0000000{:0>2d}'.format(i) - for i in range(10)]) - else: # 2.0.0 - expected_labels = [''] + [ - '00:00:00.00000000{:d}'.format(2 * i) - for i in range(5)] + [''] + expected_labels = (['00:00:00.0000000{:0>2d}'.format(i) + for i in range(10)]) rng = timedelta_range('0', periods=10, freq='ns') df = DataFrame(np.random.randn(len(rng), 3), rng) @@ -1416,7 +1392,6 @@ def test_format_timedelta_ticks_narrow(self): def test_format_timedelta_ticks_wide(self): expected_labels = [ - '', '00:00:00', '1 days 03:46:40', '2 days 07:33:20', @@ -1426,13 +1401,7 @@ def test_format_timedelta_ticks_wide(self): '6 days 22:40:00', '8 days 02:26:40', '9 days 06:13:20', - '' ] - if self.mpl_ge_2_2_0: - expected_labels = expected_labels[1:-1] - elif self.mpl_ge_2_0_1: - expected_labels = expected_labels[1:-1] - expected_labels[-1] = '' rng = timedelta_range('0', periods=10, freq='1 d') df = DataFrame(np.random.randn(len(rng), 3), rng) diff --git a/pandas/tests/plotting/test_frame.py b/pandas/tests/plotting/test_frame.py index 4c22c3245b788..c1c0a76744c5f 100644 --- a/pandas/tests/plotting/test_frame.py +++ b/pandas/tests/plotting/test_frame.py @@ -1563,11 +1563,7 @@ def test_hist_df(self): self._check_ticks_props(axes, xrot=40, yrot=0) tm.close() - if plotting._compat._mpl_ge_2_2_0(): - kwargs = {"density": True} - else: - kwargs = {"normed": True} - ax = series.plot.hist(cumulative=True, bins=4, **kwargs) + ax = series.plot.hist(cumulative=True, bins=4, density=True) # height of last bin (index 5) must be 1.0 rects = [x for x in ax.get_children() if isinstance(x, Rectangle)] tm.assert_almost_equal(rects[-1].get_height(), 1.0) @@ -2569,8 +2565,6 @@ def test_errorbar_asymmetrical(self): tm.close() - # This XPASSES when tested with mpl == 3.0.1 - @td.xfail_if_mpl_2_2 def test_table(self): df = DataFrame(np.random.rand(10, 3), index=list(string.ascii_letters[:10])) diff --git a/pandas/tests/plotting/test_hist_method.py b/pandas/tests/plotting/test_hist_method.py index 4f0bef52b5e15..c62ed21c2fb17 100644 --- a/pandas/tests/plotting/test_hist_method.py +++ b/pandas/tests/plotting/test_hist_method.py @@ -12,7 +12,6 @@ from pandas.tests.plotting.common import TestPlotBase, _check_plot_works import pandas.util.testing as tm -from pandas.plotting._compat import _mpl_ge_2_2_0 from pandas.plotting._core import grouped_hist @@ -193,12 +192,8 @@ def test_hist_df_legacy(self): ylabelsize=yf, yrot=yrot) tm.close() - # make sure kwargs to hist are handled - if _mpl_ge_2_2_0(): - kwargs = {"density": True} - else: - kwargs = {"normed": True} - ax = ser.hist(cumulative=True, bins=4, **kwargs) + + ax = ser.hist(cumulative=True, bins=4, density=True) # height of last bin (index 5) must be 1.0 rects = [x for x in ax.get_children() if isinstance(x, Rectangle)] tm.assert_almost_equal(rects[-1].get_height(), 1.0) @@ -248,12 +243,11 @@ def test_hist_layout(self): @pytest.mark.slow # GH 9351 def test_tight_layout(self): - if self.mpl_ge_2_0_1: - df = DataFrame(randn(100, 3)) - _check_plot_works(df.hist) - self.plt.tight_layout() + df = DataFrame(randn(100, 3)) + _check_plot_works(df.hist) + self.plt.tight_layout() - tm.close() + tm.close() @td.skip_if_no_mpl @@ -285,14 +279,9 @@ def test_grouped_hist_legacy(self): xf, yf = 20, 18 xrot, yrot = 30, 40 - if _mpl_ge_2_2_0(): - kwargs = {"density": True} - else: - kwargs = {"normed": True} - axes = grouped_hist(df.A, by=df.C, cumulative=True, bins=4, xlabelsize=xf, xrot=xrot, - ylabelsize=yf, yrot=yrot, **kwargs) + ylabelsize=yf, yrot=yrot, density=True) # height of last bin (index 5) must be 1.0 for ax in axes.ravel(): rects = [x for x in ax.get_children() if isinstance(x, Rectangle)] diff --git a/pandas/tests/plotting/test_misc.py b/pandas/tests/plotting/test_misc.py index 98248586f3d27..a184c024f4459 100644 --- a/pandas/tests/plotting/test_misc.py +++ b/pandas/tests/plotting/test_misc.py @@ -61,8 +61,6 @@ def test_bootstrap_plot(self): @td.skip_if_no_mpl class TestDataFramePlots(TestPlotBase): - # This XPASSES when tested with mpl == 3.0.1 - @td.xfail_if_mpl_2_2 @td.skip_if_no_scipy def test_scatter_matrix_axis(self): scatter_matrix = plotting.scatter_matrix diff --git a/pandas/tests/plotting/test_series.py b/pandas/tests/plotting/test_series.py index e384c578aa446..cac66a1d58ca4 100644 --- a/pandas/tests/plotting/test_series.py +++ b/pandas/tests/plotting/test_series.py @@ -783,12 +783,9 @@ def test_errorbar_plot(self): s.plot(yerr=np.arange(11)) s_err = ['zzz'] * 10 - # MPL > 2.0.0 will most likely use TypeError here - with pytest.raises((TypeError, ValueError)): + with pytest.raises(TypeError): s.plot(yerr=s_err) - # This XPASSES when tested with mpl == 3.0.1 - @td.xfail_if_mpl_2_2 def test_table(self): _check_plot_works(self.series.plot, table=True) _check_plot_works(self.series.plot, table=self.series) diff --git a/pandas/tests/test_expressions.py b/pandas/tests/test_expressions.py index 71116303c3900..786dceecc4145 100644 --- a/pandas/tests/test_expressions.py +++ b/pandas/tests/test_expressions.py @@ -8,7 +8,6 @@ from numpy.random import randn import pytest -from pandas import _np_version_under1p13 from pandas.core.api import DataFrame from pandas.core.computation import expressions as expr import pandas.util.testing as tm @@ -359,8 +358,8 @@ def test_bool_ops_warn_on_arithmetic(self): f = getattr(operator, name) fe = getattr(operator, sub_funcs[subs[op]]) - # >= 1.13.0 these are now TypeErrors - if op == '-' and not _np_version_under1p13: + if op == '-': + # raises TypeError continue with tm.use_numexpr(True, min_elements=5): diff --git a/pandas/tests/test_nanops.py b/pandas/tests/test_nanops.py index 25cd206769a82..78b2e0b03952c 100644 --- a/pandas/tests/test_nanops.py +++ b/pandas/tests/test_nanops.py @@ -7,7 +7,6 @@ import numpy as np import pytest -from pandas.compat.numpy import _np_version_under1p13 import pandas.util._test_decorators as td from pandas.core.dtypes.common import is_integer_dtype @@ -1019,6 +1018,8 @@ def test_use_bottleneck(): (np.nanmedian, 2.5), (np.min, 1), (np.max, 4), + (np.nanmin, 1), + (np.nanmax, 4) ]) def test_numpy_ops(numpy_op, expected): # GH8383 @@ -1026,21 +1027,6 @@ def test_numpy_ops(numpy_op, expected): assert result == expected -@pytest.mark.parametrize("numpy_op, expected", [ - (np.nanmin, 1), - (np.nanmax, 4), -]) -def test_numpy_ops_np_version_under1p13(numpy_op, expected): - # GH8383 - result = numpy_op(pd.Series([1, 2, 3, 4])) - if _np_version_under1p13: - # bug for numpy < 1.13, where result is a series, should be a scalar - with pytest.raises(ValueError): - assert result == expected - else: - assert result == expected - - @pytest.mark.parametrize("operation", [ nanops.nanany, nanops.nanall, diff --git a/pandas/util/_test_decorators.py b/pandas/util/_test_decorators.py index 0331661c3131f..9fd5fb77d662e 100644 --- a/pandas/util/_test_decorators.py +++ b/pandas/util/_test_decorators.py @@ -23,7 +23,6 @@ def test_foo(): For more information, refer to the ``pytest`` documentation on ``skipif``. """ -from distutils.version import LooseVersion import locale import pytest @@ -80,17 +79,6 @@ def _skip_if_no_mpl(): return True -def _skip_if_mpl_2_2(): - mod = safe_import("matplotlib") - - if mod: - v = mod.__version__ - if LooseVersion(v) > LooseVersion('2.1.2'): - return True - else: - mod.use("Agg", warn=False) - - def _skip_if_has_locale(): lang, _ = locale.getlocale() if lang is not None: @@ -157,9 +145,6 @@ def decorated_func(func): reason="NumPy 1.15 or greater required") skip_if_mpl = pytest.mark.skipif(not _skip_if_no_mpl(), reason="matplotlib is present") -xfail_if_mpl_2_2 = pytest.mark.xfail(_skip_if_mpl_2_2(), - reason="matplotlib 2.2", - strict=False) skip_if_32bit = pytest.mark.skipif(is_platform_32bit(), reason="skipping for 32 bit") skip_if_windows = pytest.mark.skipif(is_platform_windows(), diff --git a/requirements-dev.txt b/requirements-dev.txt index ccf2301dad66b..c9d91757bb7b2 100644 --- a/requirements-dev.txt +++ b/requirements-dev.txt @@ -19,14 +19,14 @@ beautifulsoup4>=4.2.1 blosc botocore>=1.11 boto3 -bottleneck>=1.2.0 +bottleneck>=1.2.1 fastparquet>=0.2.1 html5lib ipython>=5.6.0 ipykernel jinja2 lxml -matplotlib>=2.0.0 +matplotlib>=2.2.2 nbsphinx numexpr>=2.6.8 openpyxl diff --git a/setup.py b/setup.py index e5ef0d7bd3aea..1dca7fa77219f 100755 --- a/setup.py +++ b/setup.py @@ -30,7 +30,7 @@ def is_platform_mac(): return sys.platform == 'darwin' -min_numpy_ver = '1.12.0' +min_numpy_ver = '1.13.3' setuptools_kwargs = { 'install_requires': [ 'python-dateutil >= 2.5.0', From ca28cdbbadf46efe2d42238c7a304669f4af254c Mon Sep 17 00:00:00 2001 From: "H. Vetinari" Date: Mon, 25 Mar 2019 08:07:14 +0100 Subject: [PATCH 02/21] Fixes --- ci/deps/azure-35-compat.yaml | 2 +- pandas/core/groupby/generic.py | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/ci/deps/azure-35-compat.yaml b/ci/deps/azure-35-compat.yaml index 3001bf47d0838..e96b1f49c3110 100644 --- a/ci/deps/azure-35-compat.yaml +++ b/ci/deps/azure-35-compat.yaml @@ -14,7 +14,7 @@ dependencies: - pytables=3.4.2 - python-dateutil=2.5.0 - python=3.5.* - - pytz=2013b + - pytz=2015.4 - scipy=0.19.0 - xlrd=1.0.0 - xlsxwriter=0.7.7 diff --git a/pandas/core/groupby/generic.py b/pandas/core/groupby/generic.py index a33c3eb2ed278..3a676fc94dff8 100644 --- a/pandas/core/groupby/generic.py +++ b/pandas/core/groupby/generic.py @@ -16,7 +16,7 @@ from pandas._libs import Timestamp, lib import pandas.compat as compat -from pandas.compat import lzip, map +from pandas.compat import lzip from pandas.errors import AbstractMethodError from pandas.util._decorators import Appender, Substitution From 4830f49ac84d1de77cf6c30c07f9bc0ac98c92f2 Mon Sep 17 00:00:00 2001 From: "H. Vetinari" Date: Mon, 25 Mar 2019 08:28:19 +0100 Subject: [PATCH 03/21] Enforce higher bottleneck version --- pandas/core/nanops.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pandas/core/nanops.py b/pandas/core/nanops.py index 5e762325da192..cfc42d26c5471 100644 --- a/pandas/core/nanops.py +++ b/pandas/core/nanops.py @@ -23,7 +23,7 @@ import pandas.core.common as com _BOTTLENECK_INSTALLED = False -_MIN_BOTTLENECK_VERSION = '1.0.0' +_MIN_BOTTLENECK_VERSION = '1.2.1' try: import bottleneck as bn From 49e8a066160c5126737fbd9b63f84846db4da90f Mon Sep 17 00:00:00 2001 From: "H. Vetinari" Date: Mon, 25 Mar 2019 12:44:37 +0100 Subject: [PATCH 04/21] Shift mpl pin away from coverage job --- .travis.yml | 2 +- ci/deps/{travis-36.yaml => travis-36-cov.yaml} | 2 +- ci/deps/travis-36-slow.yaml | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) rename ci/deps/{travis-36.yaml => travis-36-cov.yaml} (96%) diff --git a/.travis.yml b/.travis.yml index f8302f4718ef2..529f1221899dc 100644 --- a/.travis.yml +++ b/.travis.yml @@ -41,7 +41,7 @@ matrix: - dist: trusty env: - - JOB="3.6, coverage" ENV_FILE="ci/deps/travis-36.yaml" PATTERN="((not slow and not network) or (single and db))" PANDAS_TESTING_MODE="deprecate" COVERAGE=true + - JOB="3.6, coverage" ENV_FILE="ci/deps/travis-36-cov.yaml" PATTERN="((not slow and not network) or (single and db))" PANDAS_TESTING_MODE="deprecate" COVERAGE=true # In allow_failures - dist: trusty diff --git a/ci/deps/travis-36.yaml b/ci/deps/travis-36-cov.yaml similarity index 96% rename from ci/deps/travis-36.yaml rename to ci/deps/travis-36-cov.yaml index 763142bf438e7..766ab9380298d 100644 --- a/ci/deps/travis-36.yaml +++ b/ci/deps/travis-36-cov.yaml @@ -11,7 +11,7 @@ dependencies: - gcsfs - geopandas - html5lib - - matplotlib=3.0.0 + - matplotlib - nomkl - numexpr - numpy=1.15.* diff --git a/ci/deps/travis-36-slow.yaml b/ci/deps/travis-36-slow.yaml index 365c78c02f4d4..e0a178c096b59 100644 --- a/ci/deps/travis-36-slow.yaml +++ b/ci/deps/travis-36-slow.yaml @@ -7,7 +7,7 @@ dependencies: - cython>=0.28.2 - html5lib - lxml - - matplotlib + - matplotlib=3.0.0 - numexpr - numpy - openpyxl From 01e2b06acd62fb7a3b607bc82914227e369143c7 Mon Sep 17 00:00:00 2001 From: "H. Vetinari" Date: Mon, 25 Mar 2019 20:07:56 +0100 Subject: [PATCH 05/21] Clean up scipy cruft --- pandas/core/missing.py | 10 ------ pandas/plotting/_core.py | 12 +------ pandas/tests/frame/test_missing.py | 34 ++++--------------- pandas/tests/frame/test_rank.py | 9 ++--- pandas/tests/plotting/common.py | 20 ----------- pandas/tests/plotting/test_datetimelike.py | 4 +-- pandas/tests/plotting/test_frame.py | 26 ++------------ pandas/tests/plotting/test_series.py | 21 ++---------- pandas/tests/series/test_analytics.py | 7 ---- pandas/tests/series/test_missing.py | 17 ++-------- pandas/tests/series/test_rank.py | 7 +--- .../tests/sparse/frame/test_to_from_scipy.py | 7 ++-- pandas/tests/test_nanops.py | 6 ++-- 13 files changed, 23 insertions(+), 157 deletions(-) diff --git a/pandas/core/missing.py b/pandas/core/missing.py index 6a6ab78ae3554..f029cc75c350a 100644 --- a/pandas/core/missing.py +++ b/pandas/core/missing.py @@ -1,7 +1,6 @@ """ Routines for filling missing data. """ -from distutils.version import LooseVersion import operator import numpy as np @@ -347,17 +346,8 @@ def _from_derivatives(xi, yi, x, order=None, der=0, extrapolate=False): y : scalar or array_like The result, of length R or length M or M by R. """ - import scipy from scipy import interpolate - if LooseVersion(scipy.__version__) < LooseVersion('0.18.0'): - try: - method = interpolate.piecewise_polynomial_interpolate - return method(xi, yi.reshape(-1, 1), x, - orders=order, der=der) - except AttributeError: - pass - # return the method for compat with scipy version & backwards compat method = interpolate.BPoly.from_derivatives m = method(xi, yi.reshape(-1, 1), diff --git a/pandas/plotting/_core.py b/pandas/plotting/_core.py index 358de30b6eb83..7a6409006f740 100644 --- a/pandas/plotting/_core.py +++ b/pandas/plotting/_core.py @@ -3,7 +3,6 @@ from __future__ import division from collections import namedtuple -from distutils.version import LooseVersion import re import warnings @@ -1476,18 +1475,9 @@ def _get_ind(self, y): def _plot(cls, ax, y, style=None, bw_method=None, ind=None, column_num=None, stacking_id=None, **kwds): from scipy.stats import gaussian_kde - from scipy import __version__ as spv y = remove_na_arraylike(y) - - if LooseVersion(spv) >= '0.11.0': - gkde = gaussian_kde(y, bw_method=bw_method) - else: - gkde = gaussian_kde(y) - if bw_method is not None: - msg = ('bw_method was added in Scipy 0.11.0.' + - ' Scipy version in use is {spv}.'.format(spv=spv)) - warnings.warn(msg) + gkde = gaussian_kde(y, bw_method=bw_method) y = gkde.evaluate(ind) lines = MPLPlot._plot(ax, ind, y, style=style, **kwds) diff --git a/pandas/tests/frame/test_missing.py b/pandas/tests/frame/test_missing.py index 1ac0d2e5c82d3..3c8e6740fcbd7 100644 --- a/pandas/tests/frame/test_missing.py +++ b/pandas/tests/frame/test_missing.py @@ -3,7 +3,6 @@ from __future__ import print_function import datetime -from distutils.version import LooseVersion import dateutil import numpy as np @@ -18,13 +17,6 @@ import pandas.util.testing as tm from pandas.util.testing import assert_frame_equal, assert_series_equal -try: - import scipy - _is_scipy_ge_0190 = (LooseVersion(scipy.__version__) >= - LooseVersion('0.19.0')) -except ImportError: - _is_scipy_ge_0190 = False - def _skip_if_no_pchip(): try: @@ -718,14 +710,8 @@ def test_interp_various(self): result = df.interpolate(method='cubic') # GH #15662. - # new cubic and quadratic interpolation algorithms from scipy 0.19.0. - # previously `splmake` was used. See scipy/scipy#6710 - if _is_scipy_ge_0190: - expected.A.loc[3] = 2.81547781 - expected.A.loc[13] = 5.52964175 - else: - expected.A.loc[3] = 2.81621174 - expected.A.loc[13] = 5.64146581 + expected.A.loc[3] = 2.81547781 + expected.A.loc[13] = 5.52964175 assert_frame_equal(result, expected) result = df.interpolate(method='nearest') @@ -734,12 +720,8 @@ def test_interp_various(self): assert_frame_equal(result, expected, check_dtype=False) result = df.interpolate(method='quadratic') - if _is_scipy_ge_0190: - expected.A.loc[3] = 2.82150771 - expected.A.loc[13] = 6.12648668 - else: - expected.A.loc[3] = 2.82533638 - expected.A.loc[13] = 6.02817974 + expected.A.loc[3] = 2.82150771 + expected.A.loc[13] = 6.12648668 assert_frame_equal(result, expected) result = df.interpolate(method='slinear') @@ -771,14 +753,10 @@ def test_interp_alt_scipy(self): assert_frame_equal(result, expectedk) _skip_if_no_pchip() - import scipy + result = df.interpolate(method='pchip') expected.loc[2, 'A'] = 3 - - if LooseVersion(scipy.__version__) >= LooseVersion('0.17.0'): - expected.loc[5, 'A'] = 6.0 - else: - expected.loc[5, 'A'] = 6.125 + expected.loc[5, 'A'] = 6.0 assert_frame_equal(result, expected) diff --git a/pandas/tests/frame/test_rank.py b/pandas/tests/frame/test_rank.py index 6bb9dea15d1ce..3af625323118c 100644 --- a/pandas/tests/frame/test_rank.py +++ b/pandas/tests/frame/test_rank.py @@ -1,6 +1,5 @@ # -*- coding: utf-8 -*- from datetime import datetime, timedelta -from distutils.version import LooseVersion import numpy as np import pytest @@ -209,7 +208,6 @@ def test_rank_axis(self): def test_rank_methods_frame(self): pytest.importorskip('scipy.stats.special') rankdata = pytest.importorskip('scipy.stats.rankdata') - import scipy xs = np.random.randint(0, 21, (100, 26)) xs = (xs - 10.0) / 10.0 @@ -225,11 +223,8 @@ def test_rank_methods_frame(self): rankdata, ax, vals, m if m != 'first' else 'ordinal') sprank = sprank.astype(np.float64) - expected = DataFrame(sprank, columns=cols) - - if (LooseVersion(scipy.__version__) >= - LooseVersion('0.17.0')): - expected = expected.astype('float64') + expected = DataFrame(sprank, + columns=cols).astype('float64') tm.assert_frame_equal(result, expected) @pytest.mark.parametrize('dtype', ['O', 'f8', 'i8']) diff --git a/pandas/tests/plotting/common.py b/pandas/tests/plotting/common.py index 5036856cd6c7b..8a1403615e7f1 100644 --- a/pandas/tests/plotting/common.py +++ b/pandas/tests/plotting/common.py @@ -6,7 +6,6 @@ import numpy as np from numpy import random -import pytest from pandas.compat import iteritems from pandas.util._decorators import cache_readonly @@ -28,23 +27,6 @@ """ -def _skip_if_no_scipy_gaussian_kde(): - try: - from scipy.stats import gaussian_kde # noqa - except ImportError: - pytest.skip("scipy version doesn't support gaussian_kde") - - -def _ok_for_gaussian_kde(kind): - if kind in ['kde', 'density']: - try: - from scipy.stats import gaussian_kde # noqa - except ImportError: - return False - - return True - - @td.skip_if_no_mpl class TestPlotBase(object): @@ -467,8 +449,6 @@ def is_grid_on(): spndx = 1 for kind in kinds: - if not _ok_for_gaussian_kde(kind): - continue self.plt.subplot(1, 4 * len(kinds), spndx) spndx += 1 diff --git a/pandas/tests/plotting/test_datetimelike.py b/pandas/tests/plotting/test_datetimelike.py index de64212d8a09e..fae00f2956fd6 100644 --- a/pandas/tests/plotting/test_datetimelike.py +++ b/pandas/tests/plotting/test_datetimelike.py @@ -14,8 +14,7 @@ from pandas.core.indexes.period import Period, PeriodIndex, period_range from pandas.core.indexes.timedeltas import timedelta_range from pandas.core.resample import DatetimeIndex -from pandas.tests.plotting.common import ( - TestPlotBase, _skip_if_no_scipy_gaussian_kde) +from pandas.tests.plotting.common import TestPlotBase import pandas.util.testing as tm from pandas.util.testing import assert_series_equal, ensure_clean @@ -679,7 +678,6 @@ def test_secondary_y_ts(self): @pytest.mark.slow @td.skip_if_no_scipy def test_secondary_kde(self): - _skip_if_no_scipy_gaussian_kde() ser = Series(np.random.randn(10)) fig, ax = self.plt.subplots() diff --git a/pandas/tests/plotting/test_frame.py b/pandas/tests/plotting/test_frame.py index c1c0a76744c5f..2482e40502094 100644 --- a/pandas/tests/plotting/test_frame.py +++ b/pandas/tests/plotting/test_frame.py @@ -19,9 +19,7 @@ from pandas import ( DataFrame, MultiIndex, PeriodIndex, Series, bdate_range, date_range) from pandas.core.arrays import integer_array -from pandas.tests.plotting.common import ( - TestPlotBase, _check_plot_works, _ok_for_gaussian_kde, - _skip_if_no_scipy_gaussian_kde) +from pandas.tests.plotting.common import TestPlotBase, _check_plot_works import pandas.util.testing as tm from pandas.io.formats.printing import pprint_thing @@ -1514,8 +1512,6 @@ def test_boxplot_subplots_return_type(self): @pytest.mark.slow @td.skip_if_no_scipy def test_kde_df(self): - _skip_if_no_scipy_gaussian_kde() - df = DataFrame(randn(100, 4)) ax = _check_plot_works(df.plot, kind='kde') expected = [pprint_thing(c) for c in df.columns] @@ -1536,8 +1532,6 @@ def test_kde_df(self): @pytest.mark.slow @td.skip_if_no_scipy def test_kde_missing_vals(self): - _skip_if_no_scipy_gaussian_kde() - df = DataFrame(np.random.uniform(size=(100, 4))) df.loc[0, 0] = np.nan _check_plot_works(df.plot, kind='kde') @@ -1703,8 +1697,6 @@ def test_df_legend_labels(self): df4 = DataFrame(rand(3, 3), columns=['j', 'k', 'l']) for kind in kinds: - if not _ok_for_gaussian_kde(kind): - continue ax = df.plot(kind=kind, legend=True) self._check_legend_labels(ax, labels=df.columns) @@ -1793,8 +1785,6 @@ def test_no_legend(self): df = DataFrame(rand(3, 3), columns=['a', 'b', 'c']) for kind in kinds: - if not _ok_for_gaussian_kde(kind): - continue ax = df.plot(kind=kind, legend=False) self._check_legend_labels(ax, visible=False) @@ -2040,8 +2030,6 @@ def test_hist_colors(self): @pytest.mark.slow @td.skip_if_no_scipy def test_kde_colors(self): - _skip_if_no_scipy_gaussian_kde() - from matplotlib import cm custom_colors = 'rgcby' @@ -2063,8 +2051,6 @@ def test_kde_colors(self): @pytest.mark.slow @td.skip_if_no_scipy def test_kde_colors_and_styles_subplots(self): - _skip_if_no_scipy_gaussian_kde() - from matplotlib import cm default_colors = self._unpack_cycler(self.plt.rcParams) @@ -2211,8 +2197,7 @@ def test_unordered_ts(self): def test_kind_both_ways(self): df = DataFrame({'x': [1, 2, 3]}) for kind in plotting._core._common_kinds: - if not _ok_for_gaussian_kde(kind): - continue + df.plot(kind=kind) getattr(df.plot, kind)() for kind in ['scatter', 'hexbin']: @@ -2222,8 +2207,6 @@ def test_kind_both_ways(self): def test_all_invalid_plot_data(self): df = DataFrame(list('abcd')) for kind in plotting._core._common_kinds: - if not _ok_for_gaussian_kde(kind): - continue msg = "no numeric data to plot" with pytest.raises(TypeError, match=msg): @@ -2235,8 +2218,6 @@ def test_partially_invalid_plot_data(self): df = DataFrame(randn(10, 2), dtype=object) df[np.random.rand(df.shape[0]) > 0.5] = 'a' for kind in plotting._core._common_kinds: - if not _ok_for_gaussian_kde(kind): - continue msg = "no numeric data to plot" with pytest.raises(TypeError, match=msg): @@ -2728,8 +2709,7 @@ def test_memory_leak(self): results = {} for kind in plotting._core._plot_klass.keys(): - if not _ok_for_gaussian_kde(kind): - continue + args = {} if kind in ['hexbin', 'scatter', 'pie']: df = self.hexbin_df diff --git a/pandas/tests/plotting/test_series.py b/pandas/tests/plotting/test_series.py index cac66a1d58ca4..a2250a8942e22 100644 --- a/pandas/tests/plotting/test_series.py +++ b/pandas/tests/plotting/test_series.py @@ -15,9 +15,7 @@ import pandas as pd from pandas import DataFrame, Series, date_range -from pandas.tests.plotting.common import ( - TestPlotBase, _check_plot_works, _ok_for_gaussian_kde, - _skip_if_no_scipy_gaussian_kde) +from pandas.tests.plotting.common import TestPlotBase, _check_plot_works import pandas.util.testing as tm import pandas.plotting as plotting @@ -61,8 +59,6 @@ def test_plot(self): _check_plot_works(self.iseries.plot) for kind in ['line', 'bar', 'barh', 'kde', 'hist', 'box']: - if not _ok_for_gaussian_kde(kind): - continue _check_plot_works(self.series[:5].plot, kind=kind) _check_plot_works(self.series[:10].plot.barh) @@ -602,7 +598,6 @@ def test_hist_kde(self): ylabels = ax.get_yticklabels() self._check_text_labels(ylabels, [''] * len(ylabels)) - _skip_if_no_scipy_gaussian_kde() _check_plot_works(self.ts.plot.kde) _check_plot_works(self.ts.plot.density) _, ax = self.plt.subplots() @@ -616,8 +611,6 @@ def test_hist_kde(self): @pytest.mark.slow @td.skip_if_no_scipy def test_kde_kwargs(self): - _skip_if_no_scipy_gaussian_kde() - sample_points = np.linspace(-100, 100, 20) _check_plot_works(self.ts.plot.kde, bw_method='scott', ind=20) _check_plot_works(self.ts.plot.kde, bw_method=None, ind=20) @@ -634,8 +627,6 @@ def test_kde_kwargs(self): @pytest.mark.slow @td.skip_if_no_scipy def test_kde_missing_vals(self): - _skip_if_no_scipy_gaussian_kde() - s = Series(np.random.uniform(size=50)) s[0] = np.nan axes = _check_plot_works(s.plot.kde) @@ -669,7 +660,6 @@ def test_hist_kde_color(self): assert len(ax.patches) == 10 self._check_colors(ax.patches, facecolors=['b'] * 10) - _skip_if_no_scipy_gaussian_kde() _, ax = self.plt.subplots() ax = self.ts.plot.kde(logy=True, color='r', ax=ax) self._check_ax_scales(ax, yaxis='log') @@ -694,8 +684,7 @@ def test_kind_both_ways(self): plotting._core._series_kinds) _, ax = self.plt.subplots() for kind in kinds: - if not _ok_for_gaussian_kde(kind): - continue + s.plot(kind=kind, ax=ax) getattr(s.plot, kind)() @@ -704,8 +693,6 @@ def test_invalid_plot_data(self): s = Series(list('abcd')) _, ax = self.plt.subplots() for kind in plotting._core._common_kinds: - if not _ok_for_gaussian_kde(kind): - continue msg = "no numeric data to plot" with pytest.raises(TypeError, match=msg): @@ -715,16 +702,12 @@ def test_invalid_plot_data(self): def test_valid_object_plot(self): s = Series(lrange(10), dtype=object) for kind in plotting._core._common_kinds: - if not _ok_for_gaussian_kde(kind): - continue _check_plot_works(s.plot, kind=kind) def test_partially_invalid_plot_data(self): s = Series(['a', 'b', 1.0, 2]) _, ax = self.plt.subplots() for kind in plotting._core._common_kinds: - if not _ok_for_gaussian_kde(kind): - continue msg = "no numeric data to plot" with pytest.raises(TypeError, match=msg): diff --git a/pandas/tests/series/test_analytics.py b/pandas/tests/series/test_analytics.py index 919f942bfa437..9e44cc32f8f45 100644 --- a/pandas/tests/series/test_analytics.py +++ b/pandas/tests/series/test_analytics.py @@ -1,7 +1,6 @@ # coding=utf-8 # pylint: disable-msg=E1101,W0612 -from distutils.version import LooseVersion from itertools import product import operator @@ -343,7 +342,6 @@ def test_corr(self, datetime_series): @td.skip_if_no_scipy def test_corr_rank(self): - import scipy import scipy.stats as stats # kendall and spearman @@ -358,11 +356,6 @@ def test_corr_rank(self): expected = stats.spearmanr(A, B)[0] tm.assert_almost_equal(result, expected) - # these methods got rewritten in 0.8 - if LooseVersion(scipy.__version__) < LooseVersion('0.9'): - pytest.skip("skipping corr rank because of scipy version " - "{0}".format(scipy.__version__)) - # results from R A = Series( [-0.89926396, 0.94209606, -1.03289164, -0.95445587, 0.76910310, - diff --git a/pandas/tests/series/test_missing.py b/pandas/tests/series/test_missing.py index 403fdb383d81a..7b1df6917e77c 100644 --- a/pandas/tests/series/test_missing.py +++ b/pandas/tests/series/test_missing.py @@ -2,7 +2,6 @@ # pylint: disable-msg=E1101,W0612 from datetime import datetime, timedelta -from distutils.version import LooseVersion import numpy as np from numpy import nan @@ -21,13 +20,6 @@ import pandas.util.testing as tm from pandas.util.testing import assert_frame_equal, assert_series_equal -try: - import scipy - _is_scipy_ge_0190 = (LooseVersion(scipy.__version__) >= - LooseVersion('0.19.0')) -except ImportError: - _is_scipy_ge_0190 = False - def _skip_if_no_pchip(): try: @@ -1069,12 +1061,7 @@ def test_interp_scipy_basic(self): assert_series_equal(result, expected) # quadratic # GH #15662. - # new cubic and quadratic interpolation algorithms from scipy 0.19.0. - # previously `splmake` was used. See scipy/scipy#6710 - if _is_scipy_ge_0190: - expected = Series([1, 3., 6.823529, 12., 18.058824, 25.]) - else: - expected = Series([1, 3., 6.769231, 12., 18.230769, 25.]) + expected = Series([1, 3., 6.823529, 12., 18.058824, 25.]) result = s.interpolate(method='quadratic') assert_series_equal(result, expected) @@ -1342,7 +1329,7 @@ def test_spline(self): expected = Series([1., 2., 3., 4., 5., 6., 7.]) assert_series_equal(result, expected) - @td.skip_if_no('scipy', min_version='0.15') + @td.skip_if_no_scipy def test_spline_extrapolate(self): s = Series([1, 2, 3, 4, np.nan, 6, np.nan]) result3 = s.interpolate(method='spline', order=1, ext=3) diff --git a/pandas/tests/series/test_rank.py b/pandas/tests/series/test_rank.py index c6a149bc0c296..31885077f53c1 100644 --- a/pandas/tests/series/test_rank.py +++ b/pandas/tests/series/test_rank.py @@ -1,5 +1,4 @@ # -*- coding: utf-8 -*- -from distutils.version import LooseVersion from itertools import chain import numpy as np @@ -321,7 +320,6 @@ def test_rank_desc_mix_nans_infs(self): def test_rank_methods_series(self): pytest.importorskip('scipy.stats.special') rankdata = pytest.importorskip('scipy.stats.rankdata') - import scipy xs = np.random.randn(9) xs = np.concatenate([xs[i:] for i in range(0, 9, 2)]) # add duplicates @@ -335,10 +333,7 @@ def test_rank_methods_series(self): for m in ['average', 'min', 'max', 'first', 'dense']: result = ts.rank(method=m) sprank = rankdata(vals, m if m != 'first' else 'ordinal') - expected = Series(sprank, index=index) - - if LooseVersion(scipy.__version__) >= LooseVersion('0.17.0'): - expected = expected.astype('float64') + expected = Series(sprank, index=index).astype('float64') tm.assert_series_equal(result, expected) def test_rank_dense_method(self): diff --git a/pandas/tests/sparse/frame/test_to_from_scipy.py b/pandas/tests/sparse/frame/test_to_from_scipy.py index bdb2cd022b451..a80a51a66017e 100644 --- a/pandas/tests/sparse/frame/test_to_from_scipy.py +++ b/pandas/tests/sparse/frame/test_to_from_scipy.py @@ -1,5 +1,3 @@ -from distutils.version import LooseVersion - import numpy as np import pytest @@ -77,9 +75,8 @@ def test_from_to_scipy_object(spmatrix, fill_value): columns = list('cd') index = list('ab') - if (spmatrix is scipy.sparse.dok_matrix and LooseVersion( - scipy.__version__) >= LooseVersion('0.19.0')): - pytest.skip("dok_matrix from object does not work in SciPy >= 0.19") + if spmatrix is scipy.sparse.dok_matrix: + pytest.skip("dok_matrix from object does not work in SciPy") # Make one ndarray and from it one sparse matrix, both to be used for # constructing frames and comparing results diff --git a/pandas/tests/test_nanops.py b/pandas/tests/test_nanops.py index 78b2e0b03952c..3d890d9fe4dc9 100644 --- a/pandas/tests/test_nanops.py +++ b/pandas/tests/test_nanops.py @@ -346,7 +346,7 @@ def test_nanstd(self, ddof): allow_str=False, allow_date=False, allow_tdelta=True, allow_obj='convert', ddof=ddof) - @td.skip_if_no('scipy', min_version='0.17.0') + @td.skip_if_no_scipy @pytest.mark.parametrize('ddof', range(3)) def test_nansem(self, ddof): from scipy.stats import sem @@ -415,7 +415,7 @@ def _skew_kurt_wrap(self, values, axis=None, func=None): return 0. return result - @td.skip_if_no('scipy', min_version='0.17.0') + @td.skip_if_no_scipy def test_nanskew(self): from scipy.stats import skew func = partial(self._skew_kurt_wrap, func=skew) @@ -424,7 +424,7 @@ def test_nanskew(self): allow_str=False, allow_date=False, allow_tdelta=False) - @td.skip_if_no('scipy', min_version='0.17.0') + @td.skip_if_no_scipy def test_nankurt(self): from scipy.stats import kurtosis func1 = partial(kurtosis, fisher=True) From a3e09c26dc004d409a0a2f53cc8403a21b2bd03f Mon Sep 17 00:00:00 2001 From: "H. Vetinari" Date: Tue, 26 Mar 2019 07:14:22 +0100 Subject: [PATCH 06/21] Reshuffle mpl pins --- ci/deps/azure-windows-36.yaml | 2 +- ci/deps/travis-36-locale.yaml | 6 ++++-- ci/deps/travis-36-slow.yaml | 2 +- 3 files changed, 6 insertions(+), 4 deletions(-) diff --git a/ci/deps/azure-windows-36.yaml b/ci/deps/azure-windows-36.yaml index 8661fc3ab65d2..7b3ae259fb8dd 100644 --- a/ci/deps/azure-windows-36.yaml +++ b/ci/deps/azure-windows-36.yaml @@ -7,7 +7,7 @@ dependencies: - bottleneck - boost-cpp<1.67 - fastparquet>=0.2.1 - - matplotlib + - matplotlib=3.0.2 - numexpr - numpy=1.15.* - openpyxl diff --git a/ci/deps/travis-36-locale.yaml b/ci/deps/travis-36-locale.yaml index ba57bfb9bfe6f..d4c1e19178bc4 100644 --- a/ci/deps/travis-36-locale.yaml +++ b/ci/deps/travis-36-locale.yaml @@ -9,7 +9,7 @@ dependencies: - ipython - jinja2 - lxml - - matplotlib=3.0.1 + - matplotlib=3.0.0 - nomkl - numexpr - numpy @@ -18,7 +18,9 @@ dependencies: - pymysql=0.7.9 - pytables - python-dateutil - - python=3.6.* + # cannot go past python=3.6.6 for matplotlib=3.0.0 due to + # https://github.com/matplotlib/matplotlib/issues/12626 + - python=3.6.6 - pytz - s3fs - scipy diff --git a/ci/deps/travis-36-slow.yaml b/ci/deps/travis-36-slow.yaml index e0a178c096b59..365c78c02f4d4 100644 --- a/ci/deps/travis-36-slow.yaml +++ b/ci/deps/travis-36-slow.yaml @@ -7,7 +7,7 @@ dependencies: - cython>=0.28.2 - html5lib - lxml - - matplotlib=3.0.0 + - matplotlib - numexpr - numpy - openpyxl From 27bf2064cf555654986defaf1396036ff53a253c Mon Sep 17 00:00:00 2001 From: "H. Vetinari" Date: Tue, 26 Mar 2019 07:15:32 +0100 Subject: [PATCH 07/21] More numpy cruft --- pandas/core/arrays/datetimes.py | 3 --- pandas/tests/arithmetic/test_numeric.py | 3 +-- 2 files changed, 1 insertion(+), 5 deletions(-) diff --git a/pandas/core/arrays/datetimes.py b/pandas/core/arrays/datetimes.py index 33e6674389e7c..8b14471521a69 100644 --- a/pandas/core/arrays/datetimes.py +++ b/pandas/core/arrays/datetimes.py @@ -197,9 +197,6 @@ def wrapper(self, other): result = com.values_from_object(result) - # Make sure to pass an array to result[...]; indexing with - # Series breaks with older version of numpy - o_mask = np.array(o_mask) if o_mask.any(): result[o_mask] = nat_result diff --git a/pandas/tests/arithmetic/test_numeric.py b/pandas/tests/arithmetic/test_numeric.py index d556101ac2ecb..0df6631a1e9d7 100644 --- a/pandas/tests/arithmetic/test_numeric.py +++ b/pandas/tests/arithmetic/test_numeric.py @@ -963,8 +963,7 @@ def test_binops(self): self.check_binop(ops, scalars, idxs) def test_binops_pow(self): - # later versions of numpy don't allow powers of negative integers - # so test separately + # numpy does not allow powers of negative integers so test separately # https://github.com/numpy/numpy/pull/8127 ops = [pow] scalars = [1, 2] From 64fc7019c9e2076883987f18959689b190811347 Mon Sep 17 00:00:00 2001 From: "H. Vetinari" Date: Tue, 26 Mar 2019 07:16:44 +0100 Subject: [PATCH 08/21] Fix order and pin in azure compat job --- ci/deps/azure-35-compat.yaml | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/ci/deps/azure-35-compat.yaml b/ci/deps/azure-35-compat.yaml index e96b1f49c3110..708c08239c7c0 100644 --- a/ci/deps/azure-35-compat.yaml +++ b/ci/deps/azure-35-compat.yaml @@ -3,10 +3,8 @@ channels: - defaults - conda-forge dependencies: - - beautifulsoup4==4.4.1 + - beautifulsoup4=4.4.1 - bottleneck=1.2.1 - - cython=0.28.2 - - hypothesis>=3.58.0 - jinja2=2.8 - numexpr=2.6.2 - numpy=1.13.3 @@ -20,6 +18,8 @@ dependencies: - xlsxwriter=0.7.7 - xlwt=1.0.0 # universal + - cython=0.28.2 + - hypothesis>=3.58.0 - pytest-xdist - pytest-mock - isort From 327ef302200d68129f7d067646766e220f7781d7 Mon Sep 17 00:00:00 2001 From: "H. Vetinari" Date: Tue, 26 Mar 2019 07:17:32 +0100 Subject: [PATCH 09/21] Reformulate version bump in whatsnew, add lowest version pins where missing --- ci/deps/travis-36-cov.yaml | 1 + ci/deps/travis-36-locale.yaml | 15 ++++-- doc/source/install.rst | 10 ++-- doc/source/whatsnew/v0.25.0.rst | 87 +++++++++++++++++++++------------ 4 files changed, 71 insertions(+), 42 deletions(-) diff --git a/ci/deps/travis-36-cov.yaml b/ci/deps/travis-36-cov.yaml index 766ab9380298d..95914568bea43 100644 --- a/ci/deps/travis-36-cov.yaml +++ b/ci/deps/travis-36-cov.yaml @@ -16,6 +16,7 @@ dependencies: - numexpr - numpy=1.15.* - openpyxl + - pandas-gbq - psycopg2 - pyarrow=0.9.0 - pymysql diff --git a/ci/deps/travis-36-locale.yaml b/ci/deps/travis-36-locale.yaml index d4c1e19178bc4..71022320da674 100644 --- a/ci/deps/travis-36-locale.yaml +++ b/ci/deps/travis-36-locale.yaml @@ -4,17 +4,22 @@ channels: - conda-forge dependencies: - beautifulsoup4 + - blosc=1.14.3 + - python-blosc - cython>=0.28.2 + - fastparquet=0.2.1 + - gcsfs=0.1.0 - html5lib - ipython - jinja2 - - lxml + - lxml=3.7.0 - matplotlib=3.0.0 - nomkl - numexpr - numpy - openpyxl - - psycopg2 + - pandas-gbq=0.8.0 + - psycopg2=2.6.2 - pymysql=0.7.9 - pytables - python-dateutil @@ -22,10 +27,10 @@ dependencies: # https://github.com/matplotlib/matplotlib/issues/12626 - python=3.6.6 - pytz - - s3fs + - s3fs=0.0.8 - scipy - - sqlalchemy - - xarray + - sqlalchemy=1.1.4 + - xarray=0.8.2 - xlrd - xlsxwriter - xlwt diff --git a/doc/source/install.rst b/doc/source/install.rst index a482fc6645439..b3b5945cc515e 100644 --- a/doc/source/install.rst +++ b/doc/source/install.rst @@ -255,10 +255,10 @@ Optional Dependencies * `Cython `__: Only necessary to build development version. Version 0.28.2 or higher. * `SciPy `__: miscellaneous statistical functions, Version 0.19.0 or higher -* `xarray `__: pandas like handling for > 2 dims. Version 0.7.0 or higher is recommended. +* `xarray `__: pandas like handling for > 2 dims. Version 0.8.2 or higher is recommended. * `PyTables `__: necessary for HDF5-based storage, Version 3.4.2 or higher * `pyarrow `__ (>= 0.9.0): necessary for feather-based storage. -* `Apache Parquet `__, either `pyarrow `__ (>= 0.7.0) or `fastparquet `__ (>= 0.2.1) for parquet-based storage. The `snappy `__ and `brotli `__ are available for compression support. +* `Apache Parquet `__, either `pyarrow `__ (>= 0.9.0) or `fastparquet `__ (>= 0.2.1) for parquet-based storage. The `snappy `__ and `brotli `__ are available for compression support. * `SQLAlchemy `__: for SQL database support. Version 1.1.4 or higher recommended. Besides SQLAlchemy, you also need a database specific driver. You can find an overview of supported drivers for each SQL dialect in the `SQLAlchemy docs `__. Some common drivers are: * `psycopg2 `__: for PostgreSQL @@ -270,11 +270,11 @@ Optional Dependencies * `xlrd/xlwt `__: Excel reading (xlrd), version 1.0.0 or higher required, and writing (xlwt) * `openpyxl `__: openpyxl version 2.4.0 - for writing .xlsx files (xlrd >= 0.9.0) + for writing .xlsx files (xlrd >= 1.0.0) * `XlsxWriter `__: Alternative Excel writer * `Jinja2 `__: Template engine for conditional HTML formatting. -* `s3fs `__: necessary for Amazon S3 access (s3fs >= 0.0.7). +* `s3fs `__: necessary for Amazon S3 access (s3fs >= 0.0.8). * `blosc `__: for msgpack compression using ``blosc`` * `gcsfs `__: necessary for Google Cloud Storage access (gcsfs >= 0.1.0). * One of @@ -289,8 +289,6 @@ Optional Dependencies `__: for Google BigQuery I/O. (pandas-gbq >= 0.8.0) - -* `Backports.lzma `__: Only for Python 2, for writing to and/or reading from an xz compressed DataFrame in CSV; Python 3 support is built into the standard library. * One of the following combinations of libraries is needed to use the top-level :func:`~pandas.read_html` function: diff --git a/doc/source/whatsnew/v0.25.0.rst b/doc/source/whatsnew/v0.25.0.rst index 5befea2fd43a9..97cc8e3dc8a7b 100644 --- a/doc/source/whatsnew/v0.25.0.rst +++ b/doc/source/whatsnew/v0.25.0.rst @@ -116,37 +116,62 @@ Increased minimum versions for dependencies Due to dropping support for Python 2.7, a number of optional dependencies have updated minimum versions. Independently, some minimum supported versions of dependencies were updated (:issue:`23519`, :issue:`24942`, :issue:`25554`, :issue:`25752`). -If installed, we now require: - -+-----------------+-----------------+----------+ -| Package | Minimum Version | Required | -+=================+=================+==========+ -| numpy | 1.13.3 | X | -+-----------------+-----------------+----------+ -| beautifulsoup4 | 4.4.1 | | -+-----------------+-----------------+----------+ -| bottleneck | 1.2.1 | | -+-----------------+-----------------+----------+ -| matplotlib | 2.2.2 | | -+-----------------+-----------------+----------+ -| numexpr | 2.6.2 | | -+-----------------+-----------------+----------+ -| openpyxl | 2.4.0 | | -+-----------------+-----------------+----------+ -| pymysql | 0.7.9 | | -+-----------------+-----------------+----------+ -| pytz | 2015.4 | | -+-----------------+-----------------+----------+ -| scipy | 0.19.0 | | -+-----------------+-----------------+----------+ -| sqlalchemy | 1.1.4 | | -+-----------------+-----------------+----------+ -| xlsxwriter | 0.7.7 | | -+-----------------+-----------------+----------+ -| xlwt | 1.0.0 | | -+-----------------+-----------------+----------+ -| pytest | 4.0.2 | (dev) | -+-----------------+-----------------+----------+ + +Below is an overview of the minimal versions, as required resp. recommended. Optional libraries below the lowest tested version may still work, but are not considered supported. + ++-----------------+-----------------+-----------------------+ +| Package | Minimum Version | Comment | ++=================+=================+=======================+ +| numpy | 1.13.3 | Required | ++-----------------+-----------------+-----------------------+ +| pytz | 2015.4 | Required | ++-----------------+-----------------+-----------------------+ +| bottleneck | 1.2.1 | Required if installed | ++-----------------+-----------------+-----------------------+ +| numexpr | 2.6.2 | Required if installed | ++-----------------+-----------------+-----------------------+ +| beautifulsoup4 | 4.4.1 | Lowest tested version | ++-----------------+-----------------+-----------------------+ +| blosc | 1.14.3 | Lowest tested version | ++-----------------+-----------------+-----------------------+ +| fastparquet | 0.2.1 | Lowest tested version | ++-----------------+-----------------+-----------------------+ +| gcsfs | 0.1.0 | Lowest tested version | ++-----------------+-----------------+-----------------------+ +| jinja2 | 2.8 | Lowest tested version | ++-----------------+-----------------+-----------------------+ +| lxml | 3.7.0 | Lowest tested version | ++-----------------+-----------------+-----------------------+ +| matplotlib | 2.2.2 | Lowest tested version | ++-----------------+-----------------+-----------------------+ +| openpyxl | 2.4.0 | Lowest tested version | ++-----------------+-----------------+-----------------------+ +| psycopg2 | 2.6.2 | Lowest tested version | ++-----------------+-----------------+-----------------------+ +| pyarrow | 0.9.0 | Lowest tested version | ++-----------------+-----------------+-----------------------+ +| pymysql | 0.7.9 | Lowest tested version | ++-----------------+-----------------+-----------------------+ +| pytables | 3.4.2 | Lowest tested version | ++-----------------+-----------------+-----------------------+ +| s3fs | 0.0.8 | Lowest tested version | ++-----------------+-----------------+-----------------------+ +| scipy | 0.19.0 | Lowest tested version | ++-----------------+-----------------+-----------------------+ +| sqlalchemy | 1.1.4 | Lowest tested version | ++-----------------+-----------------+-----------------------+ +| xarray | 0.8.2 | Lowest tested version | ++-----------------+-----------------+-----------------------+ +| xlrd | 1.0.0 | Lowest tested version | ++-----------------+-----------------+-----------------------+ +| xlsxwriter | 0.7.7 | Lowest tested version | ++-----------------+-----------------+-----------------------+ +| xlwt | 1.0.0 | Lowest tested version | ++-----------------+-----------------+-----------------------+ +| cython | 0.28.2 | Development-only req. | ++-----------------+-----------------+-----------------------+ +| pytest | 4.0.2 | Development-only req. | ++-----------------+-----------------+-----------------------+ .. _whatsnew_0250.api.other: From f3f7d2bc9825e84b6f744f3b18290acf0327dce9 Mon Sep 17 00:00:00 2001 From: "H. Vetinari" Date: Tue, 26 Mar 2019 07:18:34 +0100 Subject: [PATCH 10/21] clean some old sqlalchemy code --- pandas/io/sql.py | 14 -------------- 1 file changed, 14 deletions(-) diff --git a/pandas/io/sql.py b/pandas/io/sql.py index 3540daab13b54..6145bdb4a6ec5 100644 --- a/pandas/io/sql.py +++ b/pandas/io/sql.py @@ -47,24 +47,10 @@ def _is_sqlalchemy_connectable(con): try: import sqlalchemy _SQLALCHEMY_INSTALLED = True - - from distutils.version import LooseVersion - ver = sqlalchemy.__version__ - # For sqlalchemy versions < 0.8.2, the BIGINT type is recognized - # for a sqlite engine, which results in a warning when trying to - # read/write a DataFrame with int64 values. (GH7433) - if LooseVersion(ver) < LooseVersion('0.8.2'): - from sqlalchemy import BigInteger - from sqlalchemy.ext.compiler import compiles - - @compiles(BigInteger, 'sqlite') - def compile_big_int_sqlite(type_, compiler, **kw): - return 'INTEGER' except ImportError: _SQLALCHEMY_INSTALLED = False if _SQLALCHEMY_INSTALLED: - import sqlalchemy return isinstance(con, sqlalchemy.engine.Connectable) else: return False From e3d9f6e609ccb4de17de3f3c44fc0771c77a8132 Mon Sep 17 00:00:00 2001 From: "H. Vetinari" Date: Tue, 26 Mar 2019 07:48:27 +0100 Subject: [PATCH 11/21] Review (jreback) --- pandas/plotting/_compat.py | 2 +- pandas/tests/plotting/common.py | 2 +- pandas/tests/plotting/test_datetimelike.py | 16 ++++++++-------- 3 files changed, 10 insertions(+), 10 deletions(-) diff --git a/pandas/plotting/_compat.py b/pandas/plotting/_compat.py index 02dba9a6a99f1..793ab54926f96 100644 --- a/pandas/plotting/_compat.py +++ b/pandas/plotting/_compat.py @@ -18,5 +18,5 @@ def inner(): return inner -_mpl_eq_2_2_2 = _mpl_version('2.2.2', operator.eq) +_mpl_ge_2_2_3 = _mpl_version('2.2.3', operator.ge) _mpl_ge_3_0_0 = _mpl_version('3.0.0', operator.ge) diff --git a/pandas/tests/plotting/common.py b/pandas/tests/plotting/common.py index 8a1403615e7f1..1eef226749383 100644 --- a/pandas/tests/plotting/common.py +++ b/pandas/tests/plotting/common.py @@ -35,7 +35,7 @@ def setup_method(self, method): import matplotlib as mpl mpl.rcdefaults() - self.mpl_eq_2_2_2 = plotting._compat._mpl_eq_2_2_2() + self.mpl_ge_2_2_3 = plotting._compat._mpl_ge_2_2_3() self.mpl_ge_3_0_0 = plotting._compat._mpl_ge_3_0_0() self.bp_n_objects = 7 diff --git a/pandas/tests/plotting/test_datetimelike.py b/pandas/tests/plotting/test_datetimelike.py index fae00f2956fd6..42ffb3ff58179 100644 --- a/pandas/tests/plotting/test_datetimelike.py +++ b/pandas/tests/plotting/test_datetimelike.py @@ -405,7 +405,7 @@ def test_get_finder(self): def test_finder_daily(self): day_lst = [10, 40, 252, 400, 950, 2750, 10000] - if self.mpl_ge_3_0_0 or self.mpl_eq_2_2_2: + if self.mpl_ge_3_0_0 or not self.mpl_ge_2_2_3: xpl1 = xpl2 = [Period('1999-1-1', freq='B').ordinal] * len(day_lst) else: # 2.2.3, 2.2.4 xpl1 = [7565, 7564, 7553, 7546, 7518, 7428, 7066] @@ -433,7 +433,7 @@ def test_finder_daily(self): def test_finder_quarterly(self): yrs = [3.5, 11] - if self.mpl_ge_3_0_0 or self.mpl_eq_2_2_2: + if self.mpl_ge_3_0_0 or not self.mpl_ge_2_2_3: xpl1 = xpl2 = [Period('1988Q1').ordinal] * len(yrs) else: # 2.2.3, 2.2.4 xpl1 = [68, 68] @@ -461,7 +461,7 @@ def test_finder_quarterly(self): def test_finder_monthly(self): yrs = [1.15, 2.5, 4, 11] - if self.mpl_ge_3_0_0 or self.mpl_eq_2_2_2: + if self.mpl_ge_3_0_0 or not self.mpl_ge_2_2_3: xpl1 = xpl2 = [Period('Jan 1988').ordinal] * len(yrs) else: # 2.2.3, 2.2.4 xpl1 = [216, 216, 204, 204] @@ -497,7 +497,7 @@ def test_finder_monthly_long(self): @pytest.mark.slow def test_finder_annual(self): - if self.mpl_ge_3_0_0 or self.mpl_eq_2_2_2: + if self.mpl_ge_3_0_0 or not self.mpl_ge_2_2_3: xp = [1987, 1988, 1990, 1990, 1995, 2020, 2070, 2170] else: # 2.2.3, 2.2.4 xp = [1986, 1986, 1990, 1990, 1995, 2020, 1970, 1970] @@ -551,7 +551,7 @@ def test_gaps(self): line = lines[0] data = line.get_xydata() - if self.mpl_ge_3_0_0 or self.mpl_eq_2_2_2: + if self.mpl_ge_3_0_0 or not self.mpl_ge_2_2_3: data = np.ma.MaskedArray(data, mask=isna(data), fill_value=np.nan) assert isinstance(data, np.ma.core.MaskedArray) @@ -570,7 +570,7 @@ def test_gaps(self): line = lines[0] data = line.get_xydata() - if self.mpl_ge_3_0_0 or self.mpl_eq_2_2_2: + if self.mpl_ge_3_0_0 or not self.mpl_ge_2_2_3: data = np.ma.MaskedArray(data, mask=isna(data), fill_value=np.nan) assert isinstance(data, np.ma.core.MaskedArray) @@ -588,7 +588,7 @@ def test_gaps(self): assert len(lines) == 1 line = lines[0] data = line.get_xydata() - if self.mpl_ge_3_0_0 or self.mpl_eq_2_2_2: + if self.mpl_ge_3_0_0 or not self.mpl_ge_2_2_3: data = np.ma.MaskedArray(data, mask=isna(data), fill_value=np.nan) assert isinstance(data, np.ma.core.MaskedArray) @@ -611,7 +611,7 @@ def test_gap_upsample(self): line = lines[0] data = line.get_xydata() - if self.mpl_ge_3_0_0 or self.mpl_eq_2_2_2: + if self.mpl_ge_3_0_0 or not self.mpl_ge_2_2_3: data = np.ma.MaskedArray(data, mask=isna(data), fill_value=np.nan) assert isinstance(data, np.ma.core.MaskedArray) From 182d67ce0474a3ec7c35c1298bd449fb30783fc8 Mon Sep 17 00:00:00 2001 From: "H. Vetinari" Date: Tue, 26 Mar 2019 08:17:52 +0100 Subject: [PATCH 12/21] Fixes --- pandas/io/sql.py | 1 + pandas/tests/plotting/test_frame.py | 2 ++ 2 files changed, 3 insertions(+) diff --git a/pandas/io/sql.py b/pandas/io/sql.py index c28621b233011..a93fa8ce7c629 100644 --- a/pandas/io/sql.py +++ b/pandas/io/sql.py @@ -51,6 +51,7 @@ def _is_sqlalchemy_connectable(con): _SQLALCHEMY_INSTALLED = False if _SQLALCHEMY_INSTALLED: + import sqlalchemy return isinstance(con, sqlalchemy.engine.Connectable) else: return False diff --git a/pandas/tests/plotting/test_frame.py b/pandas/tests/plotting/test_frame.py index 2482e40502094..292c6ea910788 100644 --- a/pandas/tests/plotting/test_frame.py +++ b/pandas/tests/plotting/test_frame.py @@ -2194,6 +2194,7 @@ def test_unordered_ts(self): ydata = ax.lines[0].get_ydata() tm.assert_numpy_array_equal(ydata, np.array([1.0, 2.0, 3.0])) + @td.skip_if_no_scipy def test_kind_both_ways(self): df = DataFrame({'x': [1, 2, 3]}) for kind in plotting._core._common_kinds: @@ -2702,6 +2703,7 @@ def _check(axes): self._check_visible(ax.get_xticklabels(), visible=True) self._check_visible(ax.get_xticklabels(minor=True), visible=True) + @td.skip_if_no_scipy def test_memory_leak(self): """ Check that every plot type gets properly collected. """ import weakref From d0bb9303e3dd500bc72ffed97bc624af51522a6d Mon Sep 17 00:00:00 2001 From: "H. Vetinari" Date: Tue, 26 Mar 2019 08:48:56 +0100 Subject: [PATCH 13/21] Lint --- pandas/io/sql.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pandas/io/sql.py b/pandas/io/sql.py index a93fa8ce7c629..f2af71ee1948c 100644 --- a/pandas/io/sql.py +++ b/pandas/io/sql.py @@ -51,7 +51,7 @@ def _is_sqlalchemy_connectable(con): _SQLALCHEMY_INSTALLED = False if _SQLALCHEMY_INSTALLED: - import sqlalchemy + import sqlalchemy # noqa: F811 return isinstance(con, sqlalchemy.engine.Connectable) else: return False From 3ea9cd8295678d3abd99736b13f965354e71686d Mon Sep 17 00:00:00 2001 From: "H. Vetinari" Date: Tue, 26 Mar 2019 08:59:37 +0100 Subject: [PATCH 14/21] Update whatsnew issues references --- doc/source/whatsnew/v0.25.0.rst | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/doc/source/whatsnew/v0.25.0.rst b/doc/source/whatsnew/v0.25.0.rst index 49e6cba0bf098..9a0bfcd3a370e 100644 --- a/doc/source/whatsnew/v0.25.0.rst +++ b/doc/source/whatsnew/v0.25.0.rst @@ -158,8 +158,8 @@ cause a ``SparseSeries`` or ``SparseDataFrame`` to be returned, as before. Increased minimum versions for dependencies ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ -Due to dropping support for Python 2.7, a number of optional dependencies have updated minimum versions. -Independently, some minimum supported versions of dependencies were updated (:issue:`23519`, :issue:`24942`, :issue:`25554`, :issue:`25752`). +Due to dropping support for Python 2.7, a number of optional dependencies have updated minimum versions (issue:`25725`, :issue:`24942`, :issue:`25752`). +Independently, some minimum supported versions of dependencies were updated (:issue:`23519`, :issue:`25554`). Below is an overview of the minimal versions, as required resp. recommended. Optional libraries below the lowest tested version may still work, but are not considered supported. From ffd86ffec821b835ecbae6fcca355f3bf270096d Mon Sep 17 00:00:00 2001 From: "H. Vetinari" Date: Wed, 27 Mar 2019 07:53:46 +0100 Subject: [PATCH 15/21] split table in whatsnew (review jreback) --- doc/source/whatsnew/v0.25.0.rst | 31 +++++++++++-------------------- 1 file changed, 11 insertions(+), 20 deletions(-) diff --git a/doc/source/whatsnew/v0.25.0.rst b/doc/source/whatsnew/v0.25.0.rst index 9a0bfcd3a370e..315326750ec2e 100644 --- a/doc/source/whatsnew/v0.25.0.rst +++ b/doc/source/whatsnew/v0.25.0.rst @@ -160,8 +160,7 @@ Increased minimum versions for dependencies Due to dropping support for Python 2.7, a number of optional dependencies have updated minimum versions (issue:`25725`, :issue:`24942`, :issue:`25752`). Independently, some minimum supported versions of dependencies were updated (:issue:`23519`, :issue:`25554`). - -Below is an overview of the minimal versions, as required resp. recommended. Optional libraries below the lowest tested version may still work, but are not considered supported. +If installed, we now require: +-----------------+-----------------+-----------------------+ | Package | Minimum Version | Comment | @@ -174,32 +173,28 @@ Below is an overview of the minimal versions, as required resp. recommended. Opt +-----------------+-----------------+-----------------------+ | numexpr | 2.6.2 | Required if installed | +-----------------+-----------------+-----------------------+ -| beautifulsoup4 | 4.4.1 | Lowest tested version | -+-----------------+-----------------+-----------------------+ -| blosc | 1.14.3 | Lowest tested version | -+-----------------+-----------------+-----------------------+ -| fastparquet | 0.2.1 | Lowest tested version | +| cython | 0.28.2 | Development-only req. | +-----------------+-----------------+-----------------------+ -| gcsfs | 0.1.0 | Lowest tested version | +| pytest | 4.0.2 | Development-only req. | +-----------------+-----------------+-----------------------+ -| jinja2 | 2.8 | Lowest tested version | + +For `optional libraries `_ the general recommendation is to use the latest version. +The following table lists the lowest version per library that is being tested throughout the development of pandas. +Optional libraries below the lowest tested version may still work, but are not considered supported. + +-----------------+-----------------+-----------------------+ -| lxml | 3.7.0 | Lowest tested version | +| Package | Minimum Version | Comment | ++=================+=================+=======================+ +| fastparquet | 0.2.1 | Lowest tested version | +-----------------+-----------------+-----------------------+ | matplotlib | 2.2.2 | Lowest tested version | +-----------------+-----------------+-----------------------+ | openpyxl | 2.4.0 | Lowest tested version | +-----------------+-----------------+-----------------------+ -| psycopg2 | 2.6.2 | Lowest tested version | -+-----------------+-----------------+-----------------------+ | pyarrow | 0.9.0 | Lowest tested version | +-----------------+-----------------+-----------------------+ -| pymysql | 0.7.9 | Lowest tested version | -+-----------------+-----------------+-----------------------+ | pytables | 3.4.2 | Lowest tested version | +-----------------+-----------------+-----------------------+ -| s3fs | 0.0.8 | Lowest tested version | -+-----------------+-----------------+-----------------------+ | scipy | 0.19.0 | Lowest tested version | +-----------------+-----------------+-----------------------+ | sqlalchemy | 1.1.4 | Lowest tested version | @@ -212,10 +207,6 @@ Below is an overview of the minimal versions, as required resp. recommended. Opt +-----------------+-----------------+-----------------------+ | xlwt | 1.0.0 | Lowest tested version | +-----------------+-----------------+-----------------------+ -| cython | 0.28.2 | Development-only req. | -+-----------------+-----------------+-----------------------+ -| pytest | 4.0.2 | Development-only req. | -+-----------------+-----------------+-----------------------+ .. _whatsnew_0250.api.other: From a7d7190c35dc0c8ef7d0788ebab765af4d8eaf18 Mon Sep 17 00:00:00 2001 From: "H. Vetinari" Date: Wed, 27 Mar 2019 07:54:20 +0100 Subject: [PATCH 16/21] Remove left-over comment --- pandas/core/arrays/numpy_.py | 3 --- 1 file changed, 3 deletions(-) diff --git a/pandas/core/arrays/numpy_.py b/pandas/core/arrays/numpy_.py index b2c2e1f411e6f..0deefd2b10b6e 100644 --- a/pandas/core/arrays/numpy_.py +++ b/pandas/core/arrays/numpy_.py @@ -83,9 +83,6 @@ def itemsize(self): return self._dtype.itemsize -# We would normally write this as bases=(...), then "class Foo(*bases): -# but Python2 doesn't allow unpacking tuples in the class statement. -# So, we fall back to "object", to avoid writing a metaclass. class PandasArray(ExtensionArray, ExtensionOpsMixin, NDArrayOperatorsMixin): """ A pandas ExtensionArray for NumPy data. From aad68c658e1f3707cb7eecb286cb69d37756f0d3 Mon Sep 17 00:00:00 2001 From: "H. Vetinari" Date: Wed, 27 Mar 2019 08:01:49 +0100 Subject: [PATCH 17/21] Remove cython from deps in whatsnew --- doc/source/whatsnew/v0.25.0.rst | 2 -- 1 file changed, 2 deletions(-) diff --git a/doc/source/whatsnew/v0.25.0.rst b/doc/source/whatsnew/v0.25.0.rst index 339a3568f1a81..80c6cb95b8ab8 100644 --- a/doc/source/whatsnew/v0.25.0.rst +++ b/doc/source/whatsnew/v0.25.0.rst @@ -174,8 +174,6 @@ If installed, we now require: +-----------------+-----------------+-----------------------+ | numexpr | 2.6.2 | Required if installed | +-----------------+-----------------+-----------------------+ -| cython | 0.28.2 | Development-only req. | -+-----------------+-----------------+-----------------------+ | pytest | 4.0.2 | Development-only req. | +-----------------+-----------------+-----------------------+ From fa674e3d08c20046a746db04c0793f6cd15c5114 Mon Sep 17 00:00:00 2001 From: "H. Vetinari" Date: Wed, 27 Mar 2019 08:06:29 +0100 Subject: [PATCH 18/21] Fix wording --- doc/source/whatsnew/v0.25.0.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/doc/source/whatsnew/v0.25.0.rst b/doc/source/whatsnew/v0.25.0.rst index 80c6cb95b8ab8..3b12e714d478c 100644 --- a/doc/source/whatsnew/v0.25.0.rst +++ b/doc/source/whatsnew/v0.25.0.rst @@ -178,7 +178,7 @@ If installed, we now require: +-----------------+-----------------+-----------------------+ For `optional libraries `_ the general recommendation is to use the latest version. -The following table lists the lowest version per library that is being tested throughout the development of pandas. +The following table lists the lowest version per library that is currently being tested throughout the development of pandas. Optional libraries below the lowest tested version may still work, but are not considered supported. +-----------------+-----------------+-----------------------+ From 8005679407a9983d07f8a22bf90e33ab66b65889 Mon Sep 17 00:00:00 2001 From: "H. Vetinari" Date: Wed, 27 Mar 2019 09:05:40 +0100 Subject: [PATCH 19/21] Reinstate better regexes --- pandas/tests/test_algos.py | 8 +++++--- pandas/tests/test_sorting.py | 11 +++++++---- 2 files changed, 12 insertions(+), 7 deletions(-) diff --git a/pandas/tests/test_algos.py b/pandas/tests/test_algos.py index b8226bc2f8269..45b78c78f3797 100644 --- a/pandas/tests/test_algos.py +++ b/pandas/tests/test_algos.py @@ -228,9 +228,11 @@ def test_complex_sorting(self): # gh 12666 - check no segfault x17 = np.array([complex(i) for i in range(17)], dtype=object) - msg = (r"'(<|>)' not supported between instances of 'complex' and" - r" 'complex'|" - r"unorderable types: complex\(\) > complex\(\)") + msg = ("unorderable types: {0} [<>] {0}".format(r"complex\(\)") + + "|" + + "'[<>]' not supported between instances of {0} and {0}".format( + "'complex'") + ) with pytest.raises(TypeError, match=msg): algos.factorize(x17[::-1], sort=True) diff --git a/pandas/tests/test_sorting.py b/pandas/tests/test_sorting.py index c753b5531fde7..aa91a6b2a299a 100644 --- a/pandas/tests/test_sorting.py +++ b/pandas/tests/test_sorting.py @@ -413,10 +413,13 @@ def test_mixed_integer_from_list(self): def test_unsortable(self): # GH 13714 arr = np.array([1, 2, datetime.now(), 0, 3], dtype=object) - msg = (r"'(<|>)' not supported between instances of ('" - r"datetime\.datetime' and 'int'|'int' and 'datetime\.datetime" - r"')|" - r"unorderable types: int\(\) > datetime\.datetime\(\)") + msg = ("unorderable types: ({0} [<>] {1}|{1} [<>] {0})".format( + r"int\(\)", r"datetime\.datetime\(\)") # noqa: E126 + + "|" + + ("'[<>]' not supported between instances of " + "({0} and {1}|{1} and {0})").format( + "'int'", r"'datetime\.datetime'") + ) with pytest.raises(TypeError, match=msg): safe_sort(arr) From e0f8a6df068a11a4c6b2abf231b82ee8b4c4fb02 Mon Sep 17 00:00:00 2001 From: "H. Vetinari" Date: Wed, 27 Mar 2019 20:01:53 +0100 Subject: [PATCH 20/21] Review (jreback) --- doc/source/whatsnew/v0.25.0.rst | 76 ++++++++++++++++----------------- 1 file changed, 38 insertions(+), 38 deletions(-) diff --git a/doc/source/whatsnew/v0.25.0.rst b/doc/source/whatsnew/v0.25.0.rst index 3b12e714d478c..c7554a70bea91 100644 --- a/doc/source/whatsnew/v0.25.0.rst +++ b/doc/source/whatsnew/v0.25.0.rst @@ -163,49 +163,49 @@ Due to dropping support for Python 2.7, a number of optional dependencies have u Independently, some minimum supported versions of dependencies were updated (:issue:`23519`, :issue:`25554`). If installed, we now require: -+-----------------+-----------------+-----------------------+ -| Package | Minimum Version | Comment | -+=================+=================+=======================+ -| numpy | 1.13.3 | Required | -+-----------------+-----------------+-----------------------+ -| pytz | 2015.4 | Required | -+-----------------+-----------------+-----------------------+ -| bottleneck | 1.2.1 | Required if installed | -+-----------------+-----------------+-----------------------+ -| numexpr | 2.6.2 | Required if installed | -+-----------------+-----------------+-----------------------+ -| pytest | 4.0.2 | Development-only req. | -+-----------------+-----------------+-----------------------+ ++-----------------+-----------------+----------+ +| Package | Minimum Version | Required | ++=================+=================+==========+ +| numpy | 1.13.3 | X | ++-----------------+-----------------+----------+ +| pytz | 2015.4 | X | ++-----------------+-----------------+----------+ +| bottleneck | 1.2.1 | | ++-----------------+-----------------+----------+ +| numexpr | 2.6.2 | | ++-----------------+-----------------+----------+ +| pytest (dev) | 4.0.2 | | ++-----------------+-----------------+----------+ For `optional libraries `_ the general recommendation is to use the latest version. The following table lists the lowest version per library that is currently being tested throughout the development of pandas. Optional libraries below the lowest tested version may still work, but are not considered supported. -+-----------------+-----------------+-----------------------+ -| Package | Minimum Version | Comment | -+=================+=================+=======================+ -| fastparquet | 0.2.1 | Lowest tested version | -+-----------------+-----------------+-----------------------+ -| matplotlib | 2.2.2 | Lowest tested version | -+-----------------+-----------------+-----------------------+ -| openpyxl | 2.4.0 | Lowest tested version | -+-----------------+-----------------+-----------------------+ -| pyarrow | 0.9.0 | Lowest tested version | -+-----------------+-----------------+-----------------------+ -| pytables | 3.4.2 | Lowest tested version | -+-----------------+-----------------+-----------------------+ -| scipy | 0.19.0 | Lowest tested version | -+-----------------+-----------------+-----------------------+ -| sqlalchemy | 1.1.4 | Lowest tested version | -+-----------------+-----------------+-----------------------+ -| xarray | 0.8.2 | Lowest tested version | -+-----------------+-----------------+-----------------------+ -| xlrd | 1.0.0 | Lowest tested version | -+-----------------+-----------------+-----------------------+ -| xlsxwriter | 0.7.7 | Lowest tested version | -+-----------------+-----------------+-----------------------+ -| xlwt | 1.0.0 | Lowest tested version | -+-----------------+-----------------+-----------------------+ ++-----------------+-----------------+ +| Package | Minimum Version | ++=================+=================+ +| fastparquet | 0.2.1 | ++-----------------+-----------------+ +| matplotlib | 2.2.2 | ++-----------------+-----------------+ +| openpyxl | 2.4.0 | ++-----------------+-----------------+ +| pyarrow | 0.9.0 | ++-----------------+-----------------+ +| pytables | 3.4.2 | ++-----------------+-----------------+ +| scipy | 0.19.0 | ++-----------------+-----------------+ +| sqlalchemy | 1.1.4 | ++-----------------+-----------------+ +| xarray | 0.8.2 | ++-----------------+-----------------+ +| xlrd | 1.0.0 | ++-----------------+-----------------+ +| xlsxwriter | 0.7.7 | ++-----------------+-----------------+ +| xlwt | 1.0.0 | ++-----------------+-----------------+ .. _whatsnew_0250.api.other: From 445a9a2c3607330b1abe422213a6f9fc8c4dbb4f Mon Sep 17 00:00:00 2001 From: "H. Vetinari" Date: Thu, 28 Mar 2019 07:48:30 +0100 Subject: [PATCH 21/21] Simplify regex --- pandas/tests/test_algos.py | 8 +++----- pandas/tests/test_sorting.py | 10 +++------- 2 files changed, 6 insertions(+), 12 deletions(-) diff --git a/pandas/tests/test_algos.py b/pandas/tests/test_algos.py index 45b78c78f3797..b64786de264cd 100644 --- a/pandas/tests/test_algos.py +++ b/pandas/tests/test_algos.py @@ -228,11 +228,9 @@ def test_complex_sorting(self): # gh 12666 - check no segfault x17 = np.array([complex(i) for i in range(17)], dtype=object) - msg = ("unorderable types: {0} [<>] {0}".format(r"complex\(\)") - + "|" + - "'[<>]' not supported between instances of {0} and {0}".format( - "'complex'") - ) + msg = ("unorderable types: .* [<>] .*" + "|" # the above case happens for numpy < 1.14 + "'[<>]' not supported between instances of .*") with pytest.raises(TypeError, match=msg): algos.factorize(x17[::-1], sort=True) diff --git a/pandas/tests/test_sorting.py b/pandas/tests/test_sorting.py index aa91a6b2a299a..04a50cf6facd5 100644 --- a/pandas/tests/test_sorting.py +++ b/pandas/tests/test_sorting.py @@ -413,13 +413,9 @@ def test_mixed_integer_from_list(self): def test_unsortable(self): # GH 13714 arr = np.array([1, 2, datetime.now(), 0, 3], dtype=object) - msg = ("unorderable types: ({0} [<>] {1}|{1} [<>] {0})".format( - r"int\(\)", r"datetime\.datetime\(\)") # noqa: E126 - + "|" + - ("'[<>]' not supported between instances of " - "({0} and {1}|{1} and {0})").format( - "'int'", r"'datetime\.datetime'") - ) + msg = ("unorderable types: .* [<>] .*" + "|" # the above case happens for numpy < 1.14 + "'[<>]' not supported between instances of .*") with pytest.raises(TypeError, match=msg): safe_sort(arr)