Skip to content

Commit

Permalink
Pandas 0.24 compatibility and CI fixes (#3433)
Browse files Browse the repository at this point in the history
  • Loading branch information
philippjfr committed Jan 27, 2019
1 parent f51c33e commit 9b23328
Show file tree
Hide file tree
Showing 14 changed files with 172 additions and 116 deletions.
34 changes: 34 additions & 0 deletions .appveyor.yml
@@ -0,0 +1,34 @@
environment:
matrix:
- PY: "2.7"
CONDA: "C:\\Miniconda-x64"
- PY: "3.6"
CONDA: "C:\\Miniconda36-x64"

matrix:
allow_failures:
- PY: "2.7"
- PY: "3.6"

init:
- cmd: set PATH=%CONDA%;%CONDA%\Scripts;%CONDA%\Library\bin;%PATH%
- cmd: echo %path%

install:
- "conda config --set always_yes yes"
- "conda update -q conda"
- "conda info -a"
- "conda create -n holoviews python=%PY%"
- "conda env update -n holoviews -f environment.yml"
- "activate holoviews"
- "python setup.py develop"

build: false

before_test:
- cmd: for /f %%i in ('python -c "import matplotlib; print(matplotlib.matplotlib_fname())"') do set matplotlibrc=%%i
- cmd: 'echo backend : Agg > %matplotlibrc%'

test_script:
- "flake8 --ignore=E,W,F999,F405 holoviews"
- "nosetests --with-doctest --with-coverage --cover-package=holoviews"
13 changes: 4 additions & 9 deletions .travis.yml
Expand Up @@ -9,9 +9,6 @@ python:
notifications:
email:
on_failure: change # [always|never|change] default: always
flowdock:
secure: d32tzqLnUIJge2QyAMtseJWf0yRb3LenW77xzEGVUD+abzlTtoCBbQBIRaWjJn3V78wd3ogLinplnMnu46tsQi7Q2XWiKaxrWq2ZPVfVCbV88whFiYMmmwnj6DNJjl3CxfGQXgui/VyPg9fyaDp5TyZfNZa/gEdedkn1J5kIF3g=


install:
- SITE_PACKAGES=`pip --version | cut -d ' ' -f 4`
Expand All @@ -25,13 +22,13 @@ install:
- hash -r
- conda config --set always_yes yes --set changeps1 no
- conda update -q conda

# Useful for debugging any issues with conda
- conda info -a
- conda create -q -n holoviews python=$TRAVIS_PYTHON_VERSION
- conda create -n holoviews -q python=$TRAVIS_PYTHON_VERSION
- travis_wait conda env update -n holoviews -q -f environment.yml
- source activate holoviews
- python setup.py develop
- conda env export
- conda info -a; conda list; conda env export
- if [ "$TRAVIS_PULL_REQUEST" == 'false' ]; then
echo "Attempting to find any associated pull request";
CURRENT_BUILD=$(curl -s -X GET "https://api.travis-ci.org/repos/ioam/holoviews/builds?number=$TRAVIS_BUILD_NUMBER");
Expand All @@ -55,10 +52,8 @@ install:
fi
- cd ../..

before-script:
- "echo 'backend : Agg' > $HOME/.matplotlib/matplotlibrc"

script:
- export MPLBACKEND="Agg"
- export HOLOVIEWSRC=`pwd`'/holoviews.rc'
- echo 'import holoviews as hv;hv.config(style_17=True);hv.config.warn_options_call=True' > holoviews.rc
- flake8 --ignore=E,W,F999,F405 holoviews
Expand Down
38 changes: 21 additions & 17 deletions environment.yml
@@ -1,31 +1,35 @@
name: holoviews

channels:
- conda-forge

dependencies:
- numpy<1.16.0
- defaults::numpy
- defaults::scipy
- defaults::matplotlib
- notebook
- matplotlib=2.1.2
- pillow=5.2.0
- pandas=0.23.4
- scipy
- xarray=0.10.9
- networkx
- selenium
- cyordereddict
- phantomjs
- ffmpeg
- pillow=5.3.0
- pandas=0.24.0
- xarray=0.11.0
- ipython=5.4.1
- jsonschema=2.6.0
- cyordereddict
- nbconvert=5.3.1
- pyviz::param=1.8.0
- netcdf4=1.3.1
- flexx=0.4.1
- plotly=3.4
- bokeh=1.0.4
- pyviz::param=1.8.1
- pyviz::pyviz_comms=0.7.0
- pyviz::datashader
- conda-forge::netcdf4=1.3.1
- conda-forge::ffmpeg
- conda-forge::flexx=0.4.1
- conda-forge::plotly=3.4
- bokeh::bokeh=1.0.0
- bokeh::selenium
# Testing requirements
- flake8
- nose
- path.py
- conda-forge::deepdiff
- conda-forge::awscli
- conda-forge::coveralls
- deepdiff
- awscli
- coveralls
39 changes: 24 additions & 15 deletions holoviews/core/util.py
Expand Up @@ -74,24 +74,33 @@ def __cmp__(self, other):

try:
import pandas as pd
pandas_version = LooseVersion(pd.__version__)
if pandas_version > '0.20.0':
from pandas.core.dtypes.dtypes import DatetimeTZDtypeType
from pandas.core.dtypes.generic import ABCSeries, ABCIndexClass
else:
from pandas.types.dtypes import DatetimeTZDtypeType
from pandas.types.dtypes.generic import ABCSeries, ABCIndexClass
pandas_datetime_types = (pd.Timestamp, DatetimeTZDtypeType, pd.Period)
pandas_timedelta_types = (pd.Timedelta,)
datetime_types = datetime_types + pandas_datetime_types
timedelta_types = timedelta_types + pandas_timedelta_types
arraylike_types = arraylike_types + (ABCSeries, ABCIndexClass)
if pandas_version > '0.23.0':
from pandas.core.dtypes.generic import ABCExtensionArray
arraylike_types = arraylike_types + (ABCExtensionArray,)
except ImportError:
pd = None

if pd:
try:
pandas_version = LooseVersion(pd.__version__)
if pandas_version >= '0.24.0':
from pandas.core.dtypes.dtypes import DatetimeTZDtype as DatetimeTZDtypeType
from pandas.core.dtypes.generic import ABCSeries, ABCIndexClass
elif pandas_version > '0.20.0':
from pandas.core.dtypes.dtypes import DatetimeTZDtypeType
from pandas.core.dtypes.generic import ABCSeries, ABCIndexClass
else:
from pandas.types.dtypes import DatetimeTZDtypeType
from pandas.types.dtypes.generic import ABCSeries, ABCIndexClass
pandas_datetime_types = (pd.Timestamp, DatetimeTZDtypeType, pd.Period)
pandas_timedelta_types = (pd.Timedelta,)
datetime_types = datetime_types + pandas_datetime_types
timedelta_types = timedelta_types + pandas_timedelta_types
arraylike_types = arraylike_types + (ABCSeries, ABCIndexClass)
if pandas_version > '0.23.0':
from pandas.core.dtypes.generic import ABCExtensionArray
arraylike_types = arraylike_types + (ABCExtensionArray,)
except Exception as e:
param.main.warning('pandas could not register all extension types '
'imports failed with the following error: %s' % e)

try:
import cftime
cftime_types = (cftime.datetime,)
Expand Down
13 changes: 2 additions & 11 deletions holoviews/element/comparison.py
Expand Up @@ -109,8 +109,7 @@ def register(cls):
cls.equality_type_funcs[list] = cls.compare_lists
cls.equality_type_funcs[tuple] = cls.compare_tuples


#Dictionary comparisons
# Dictionary comparisons
cls.equality_type_funcs[dict] = cls.compare_dictionaries
cls.equality_type_funcs[OrderedDict] = cls.compare_dictionaries

Expand Down Expand Up @@ -262,11 +261,6 @@ def compare_arrays(cls, arr1, arr2, msg='Arrays'):
except AssertionError as e:
raise cls.failureException(msg + str(e)[11:])

@classmethod
def compare_dataframe(cls, df1, df2, msg='DataFrames'):
if not df1.equals(df2):
raise cls.failureException('%s are not equal' % msg)

@classmethod
def bounds_check(cls, el1, el2, msg=None):
lbrt1 = el1.bounds.lbrt()
Expand Down Expand Up @@ -672,12 +666,9 @@ def compare_tables(cls, el1, el2, msg='Table'):
#========#

@classmethod
def compare_dframe(cls, el1, el2, msg='DFrame'):
cls.compare_dimensioned(el1, el2)
def compare_dataframe(cls, df1, df2, msg='DFrame'):
from pandas.util.testing import assert_frame_equal
try:
df1 = el1.data.reset_index(drop=True)
df2 = el2.data.reset_index(drop=True)
assert_frame_equal(df1, df2)
except AssertionError as e:
raise cls.failureException(msg+': '+str(e))
Expand Down
99 changes: 53 additions & 46 deletions holoviews/plotting/mpl/element.py
Expand Up @@ -308,56 +308,63 @@ def _set_axis_limits(self, axis, view, subplots, ranges):
Compute extents for current view and apply as axis limits
"""
# Extents
scalex, scaley = True, True
extents = self.get_extents(view, ranges)
if extents and not self.overlaid:
coords = [coord if np.isreal(coord) or isinstance(coord, np.datetime64) else np.NaN for coord in extents]
coords = [date2num(util.dt64_to_dt(c)) if isinstance(c, np.datetime64) else c
for c in coords]
valid_lim = lambda c: util.isnumeric(c) and not np.isnan(c)
if self.projection == '3d' or len(extents) == 6:
l, b, zmin, r, t, zmax = coords
if self.invert_zaxis or any(p.invert_zaxis for p in subplots):
zmin, zmax = zmax, zmin
if zmin != zmax:
if valid_lim(zmin):
axis.set_zlim(bottom=zmin)
if valid_lim(zmax):
axis.set_zlim(top=zmax)
else:
l, b, r, t = coords

if self.invert_axes:
l, b, r, t = b, l, t, r

if self.invert_xaxis or any(p.invert_xaxis for p in subplots):
r, l = l, r

if isinstance(l, util.cftime_types) or l != r:
lims = {}
if valid_lim(l):
lims['left'] = l
scalex = False
if valid_lim(r):
lims['right'] = r
scalex = False
if lims:
axis.set_xlim(**lims)
if self.invert_yaxis or any(p.invert_yaxis for p in subplots):
t, b = b, t
if isinstance(b, util.cftime_types) or b != t:
lims = {}
if valid_lim(b):
lims['bottom'] = b
scaley = False
if valid_lim(t):
lims['top'] = t
scaley = False
if lims:
axis.set_ylim(**lims)
if not extents or self.overlaid:
axis.autoscale_view(scalex=True, scaley=True)
return

valid_lim = lambda c: util.isnumeric(c) and not np.isnan(c)
coords = [coord if np.isreal(coord) or isinstance(coord, np.datetime64) else np.NaN for coord in extents]
coords = [date2num(util.dt64_to_dt(c)) if isinstance(c, np.datetime64) else c
for c in coords]
if self.projection == '3d' or len(extents) == 6:
l, b, zmin, r, t, zmax = coords
if self.invert_zaxis or any(p.invert_zaxis for p in subplots):
zmin, zmax = zmax, zmin
if zmin != zmax:
if valid_lim(zmin):
axis.set_zlim(bottom=zmin)
if valid_lim(zmax):
axis.set_zlim(top=zmax)
else:
l, b, r, t = coords

if self.invert_axes:
l, b, r, t = b, l, t, r

invertx = self.invert_xaxis or any(p.invert_xaxis for p in subplots)
xlim, scalex = self._compute_limits(l, r, self.logx, invertx, 'left', 'right')
inverty = self.invert_yaxis or any(p.invert_yaxis for p in subplots)
ylim, scaley = self._compute_limits(b, t, self.logy, inverty, 'bottom', 'top')
if xlim:
axis.set_xlim(**xlim)
if ylim:
axis.set_ylim(**ylim)
axis.autoscale_view(scalex=scalex, scaley=scaley)


def _compute_limits(self, low, high, log, invert, low_key, high_key):
scale = True
lims = {}
valid_lim = lambda c: util.isnumeric(c) and not np.isnan(c)
if not isinstance(low, util.datetime_types) and log and (low is None or low <= 0):
low = 0.01 if high < 0.01 else 10**(np.log10(high)-2)
self.param.warning(
"Logarithmic axis range encountered value less "
"than or equal to zero, please supply explicit "
"lower-bound to override default of %.3f." % low)
if invert:
high, low = low, high
if isinstance(low, util.cftime_types) or low != high:
if valid_lim(low):
lims[low_key] = low
scale = False
if valid_lim(high):
lims[high_key] = high
scale = False
return lims, scale


def _set_axis_position(self, axes, axis, option):
"""
Set the position and visibility of the xaxis or yaxis by
Expand Down
5 changes: 3 additions & 2 deletions holoviews/tests/core/data/base.py
Expand Up @@ -386,11 +386,12 @@ def test_dataset_get_array_by_dimension(self):

def test_dataset_get_dframe(self):
df = self.dataset_hm.dframe()
self.assertEqual(df, pd.DataFrame({'x': self.xs, 'y': self.y_ints}))
self.assertEqual(df.x.values, self.xs)
self.assertEqual(df.y.values, self.y_ints)

def test_dataset_get_dframe_by_dimension(self):
df = self.dataset_hm.dframe(['x'])
self.assertEqual(df, pd.DataFrame({'x': self.xs}))
self.assertEqual(df, pd.DataFrame({'x': self.xs}, dtype=df.dtypes[0]))



Expand Down
5 changes: 5 additions & 0 deletions holoviews/tests/core/data/testgridinterface.py
Expand Up @@ -432,6 +432,11 @@ def test_dataset_groupby_drop_dims_dynamic_with_vdim(self):
partial = ds.to(Dataset, kdims=['Val'], vdims=['Val2'], groupby='y', dynamic=True)
self.assertEqual(partial[19]['Val'], array[:, -1, :].T.flatten().compute())

def test_dataset_get_dframe(self):
df = self.dataset_hm.dframe()
self.assertEqual(df.x.values, self.xs)
self.assertEqual(df.y.values, self.y_ints.compute())



class Image_GridInterfaceTests(Image_ImageInterfaceTests):
Expand Down
3 changes: 2 additions & 1 deletion holoviews/tests/core/data/testxarrayinterface.py
Expand Up @@ -188,7 +188,8 @@ def test_datetime_bins_range(self):
array = np.random.rand(10, 10)
ds = QuadMesh((xs, ys, array))
self.assertEqual(ds.interface.datatype, 'xarray')
expected = (dt.datetime(2017, 12, 31, 12, 0), dt.datetime(2018, 1, 10, 12, 0))
expected = (np.datetime64(dt.datetime(2017, 12, 31, 12, 0)),
np.datetime64(dt.datetime(2018, 1, 10, 12, 0)))
self.assertEqual(ds.range('x'), expected)

def test_datetime64_bins_range(self):
Expand Down
13 changes: 6 additions & 7 deletions holoviews/tests/core/testdynamic.py
Expand Up @@ -775,14 +775,13 @@ def callback(x): return Curve([1,2,3])
# Add stream subscriber mocking plot
xval.add_subscriber(lambda **kwargs: dmap[()])

dmap.periodic(0.0001, 1000, param_fn=lambda i: {'x':i}, block=False)
self.assertNotEqual(xval.x, 1000)
for i in range(1000):
time.sleep(0.01)
if dmap.periodic.instance.completed:
break
self.assertNotEqual(xval.x, 100)
dmap.periodic(0.0001, 100, param_fn=lambda i: {'x': i}, block=False)
time.sleep(2)
if not dmap.periodic.instance.completed:
raise RuntimeError('Periodic callback timed out.')
dmap.periodic.stop()
self.assertEqual(xval.x, 1000)
self.assertEqual(xval.x, 100)

def test_periodic_param_fn_blocking_period(self):
def callback(x):
Expand Down
6 changes: 3 additions & 3 deletions holoviews/tests/element/teststatselements.py
Expand Up @@ -86,12 +86,12 @@ def test_bivariate_array_range_vdims(self):

def test_distribution_array_kdim_type(self):
dist = Distribution(np.array([0, 1, 2]))
self.assertEqual(dist.get_dimension_type(0), np.int64)
self.assertTrue(np.issubdtype(dist.get_dimension_type(0), np.int_))

def test_bivariate_array_kdim_type(self):
dist = Bivariate(np.array([[0, 1], [1, 2], [2, 3]]))
self.assertEqual(dist.get_dimension_type(0), np.int64)
self.assertEqual(dist.get_dimension_type(1), np.int64)
self.assertTrue(np.issubdtype(dist.get_dimension_type(0), np.int_))
self.assertTrue(np.issubdtype(dist.get_dimension_type(1), np.int_))

def test_distribution_array_vdim_type(self):
dist = Distribution(np.array([0, 1, 2]))
Expand Down

0 comments on commit 9b23328

Please sign in to comment.