Skip to content

fixes for warnings related to unit tests and nan comparisons #1657

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 12 commits into from
Oct 29, 2017
5 changes: 5 additions & 0 deletions doc/whats-new.rst
Original file line number Diff line number Diff line change
@@ -85,6 +85,11 @@ Breaking changes
disk when calling ``repr`` (:issue:`1522`).
By `Guido Imperiale <https://github.com/crusaderky>`_.

- Suppress ``RuntimeWarning`` issued by ``numpy`` for "invalid value comparisons"
(e.g. NaNs). Xarray now behaves similarly to Pandas in its treatment of
binary and unary operations on objects with ``NaN``s (:issue:`1657`).
By `Joe Hamman <https://github.com/jhamman>`_.
- Several existing features have been deprecated and will change to new
behavior in xarray v0.11. If you use any of them with xarray v0.10, you
should see a ``FutureWarning`` that describes how to update your code:
4 changes: 3 additions & 1 deletion xarray/core/dataarray.py
Original file line number Diff line number Diff line change
@@ -1575,7 +1575,9 @@ def __array_wrap__(self, obj, context=None):
def _unary_op(f):
@functools.wraps(f)
def func(self, *args, **kwargs):
return self.__array_wrap__(f(self.variable.data, *args, **kwargs))
with np.errstate(all='ignore'):
return self.__array_wrap__(f(self.variable.data, *args,
**kwargs))

return func

3 changes: 2 additions & 1 deletion xarray/core/pycompat.py
Original file line number Diff line number Diff line change
@@ -25,6 +25,7 @@ def itervalues(d):
from functools import reduce
import builtins
from urllib.request import urlretrieve
from inspect import getfullargspec as getargspec
else: # pragma: no cover
# Python 2
basestring = basestring # noqa
@@ -43,7 +44,7 @@ def itervalues(d):
reduce = reduce
import __builtin__ as builtins
from urllib import urlretrieve

from inspect import getargspec
try:
from cyordereddict import OrderedDict
except ImportError: # pragma: no cover
13 changes: 8 additions & 5 deletions xarray/core/variable.py
Original file line number Diff line number Diff line change
@@ -1354,7 +1354,8 @@ def __array_wrap__(self, obj, context=None):
def _unary_op(f):
@functools.wraps(f)
def func(self, *args, **kwargs):
return self.__array_wrap__(f(self.data, *args, **kwargs))
with np.errstate(all='ignore'):
return self.__array_wrap__(f(self.data, *args, **kwargs))
return func

@staticmethod
@@ -1364,9 +1365,10 @@ def func(self, other):
if isinstance(other, (xr.DataArray, xr.Dataset)):
return NotImplemented
self_data, other_data, dims = _broadcast_compat_data(self, other)
new_data = (f(self_data, other_data)
if not reflexive
else f(other_data, self_data))
with np.errstate(all='ignore'):
new_data = (f(self_data, other_data)
if not reflexive
else f(other_data, self_data))
result = Variable(dims, new_data)
return result
return func
@@ -1381,7 +1383,8 @@ def func(self, other):
if dims != self.dims:
raise ValueError('dimensions cannot change for in-place '
'operations')
self.values = f(self_data, other_data)
with np.errstate(all='ignore'):
self.values = f(self_data, other_data)
return self
return func

4 changes: 2 additions & 2 deletions xarray/plot/facetgrid.py
Original file line number Diff line number Diff line change
@@ -2,13 +2,13 @@
from __future__ import division
from __future__ import print_function

import inspect
import warnings
import itertools
import functools

import numpy as np

from ..core.pycompat import getargspec
from ..core.formatting import format_item
from .utils import (_determine_cmap_params, _infer_xy_labels,
import_matplotlib_pyplot)
@@ -228,7 +228,7 @@ def map_dataarray(self, func, x, y, **kwargs):
'filled': func.__name__ != 'contour',
}

cmap_args = inspect.getargspec(_determine_cmap_params).args
cmap_args = getargspec(_determine_cmap_params).args
cmap_kwargs.update((a, kwargs[a]) for a in cmap_args if a in kwargs)

cmap_params = _determine_cmap_params(**cmap_kwargs)
6 changes: 3 additions & 3 deletions xarray/tests/test_accessors.py
Original file line number Diff line number Diff line change
@@ -6,7 +6,7 @@
import numpy as np
import pandas as pd

from . import TestCase, requires_dask
from . import TestCase, requires_dask, raises_regex


class TestDatetimeAccessor(TestCase):
@@ -45,7 +45,7 @@ def test_not_datetime_type(self):
nontime_data = self.data.copy()
int_data = np.arange(len(self.data.time)).astype('int8')
nontime_data['time'].values = int_data
with self.assertRaisesRegexp(TypeError, 'dt'):
with raises_regex(TypeError, 'dt'):
nontime_data.time.dt

@requires_dask
@@ -93,4 +93,4 @@ def test_seasons(self):
"SON", "SON", "SON", "DJF"]
seasons = xr.DataArray(seasons)

self.assertArrayEqual(seasons.values, dates.dt.season.values)
self.assertArrayEqual(seasons.values, dates.dt.season.values)
73 changes: 36 additions & 37 deletions xarray/tests/test_backends.py
Original file line number Diff line number Diff line change
@@ -28,7 +28,7 @@
requires_scipy_or_netCDF4, requires_dask, requires_h5netcdf,
requires_pynio, requires_pathlib, has_netCDF4, has_scipy,
assert_allclose, flaky, network, requires_rasterio,
assert_identical)
assert_identical, raises_regex)
from .test_dataset import create_test_data

from xarray.tests import mock
@@ -113,7 +113,7 @@ def __getitem__(self, key):
return self.array[key]

array = UnreliableArray([0])
with self.assertRaises(UnreliableArrayFailure):
with pytest.raises(UnreliableArrayFailure):
array[0]
self.assertEqual(array[0], 0)

@@ -218,7 +218,7 @@ def assert_loads(vars=None):
self.assertTrue(v._in_memory)
self.assertDatasetIdentical(expected, actual)

with self.assertRaises(AssertionError):
with pytest.raises(AssertionError):
# make sure the contextmanager works!
with assert_loads() as ds:
pass
@@ -345,8 +345,7 @@ def test_roundtrip_datetime_data(self):
kwds = {'encoding': {'t0': {'units': 'days since 1950-01-01'}}}
with self.roundtrip(expected, save_kwargs=kwds) as actual:
self.assertDatasetIdentical(expected, actual)
self.assertEquals(actual.t0.encoding['units'],
'days since 1950-01-01')
assert actual.t0.encoding['units'] == 'days since 1950-01-01'

def test_roundtrip_timedelta_data(self):
time_deltas = pd.to_timedelta(['1h', '2h', 'NaT'])
@@ -528,7 +527,7 @@ def test_roundtrip_endian(self):

if type(self) is NetCDF4DataTest:
ds['z'].encoding['endian'] = 'big'
with self.assertRaises(NotImplementedError):
with pytest.raises(NotImplementedError):
with self.roundtrip(ds) as actual:
pass

@@ -539,7 +538,7 @@ def test_invalid_dataarray_names_raise(self):
da = xr.DataArray(data)
for name, e in zip([0, (4, 5), True, ''], [te, te, te, ve]):
ds = Dataset({name: da})
with self.assertRaisesRegexp(*e):
with raises_regex(*e):
with self.roundtrip(ds) as actual:
pass

@@ -551,17 +550,17 @@ def test_encoding_kwarg(self):
self.assertEqual(ds.x.encoding, {})

kwargs = dict(encoding={'x': {'foo': 'bar'}})
with self.assertRaisesRegexp(ValueError, 'unexpected encoding'):
with raises_regex(ValueError, 'unexpected encoding'):
with self.roundtrip(ds, save_kwargs=kwargs) as actual:
pass

kwargs = dict(encoding={'x': 'foo'})
with self.assertRaisesRegexp(ValueError, 'must be castable'):
with raises_regex(ValueError, 'must be castable'):
with self.roundtrip(ds, save_kwargs=kwargs) as actual:
pass

kwargs = dict(encoding={'invalid': {}})
with self.assertRaises(KeyError):
with pytest.raises(KeyError):
with self.roundtrip(ds, save_kwargs=kwargs) as actual:
pass

@@ -676,9 +675,9 @@ def test_open_group(self):
self.assertVariableEqual(actual['x'], expected['x'])

# check that missing group raises appropriate exception
with self.assertRaises(IOError):
with pytest.raises(IOError):
open_dataset(tmp_file, group='bar')
with self.assertRaisesRegexp(ValueError, 'must be a string'):
with raises_regex(ValueError, 'must be a string'):
open_dataset(tmp_file, group=(1, 2, 3))

def test_open_subgroup(self):
@@ -1019,7 +1018,7 @@ def create_store(self):

def test_array_attrs(self):
ds = Dataset(attrs={'foo': [[1, 2], [3, 4]]})
with self.assertRaisesRegexp(ValueError, 'must be 1-dimensional'):
with raises_regex(ValueError, 'must be 1-dimensional'):
with self.roundtrip(ds) as roundtripped:
pass

@@ -1036,11 +1035,11 @@ def test_netcdf3_endianness(self):

@requires_netCDF4
def test_nc4_scipy(self):
with create_tmp_file() as tmp_file:
with create_tmp_file(allow_cleanup_failure=True) as tmp_file:
with nc4.Dataset(tmp_file, 'w', format='NETCDF4') as rootgrp:
rootgrp.createGroup('foo')

with self.assertRaisesRegexp(TypeError, 'pip install netcdf4'):
with raises_regex(TypeError, 'pip install netcdf4'):
open_dataset(tmp_file, engine='scipy')
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Well, we aren't closing this file properly, so I'm not too surprised that Windows is complaining. I don't know why it's only showing up now, though.

For now, just add allow_cleanup_failure=True to the create_tmp_file() call. We'll tackle this later in #1668.



@@ -1096,18 +1095,18 @@ def test_write_store(self):

def test_engine(self):
data = create_test_data()
with self.assertRaisesRegexp(ValueError, 'unrecognized engine'):
with raises_regex(ValueError, 'unrecognized engine'):
data.to_netcdf('foo.nc', engine='foobar')
with self.assertRaisesRegexp(ValueError, 'invalid engine'):
with raises_regex(ValueError, 'invalid engine'):
data.to_netcdf(engine='netcdf4')

with create_tmp_file() as tmp_file:
data.to_netcdf(tmp_file)
with self.assertRaisesRegexp(ValueError, 'unrecognized engine'):
with raises_regex(ValueError, 'unrecognized engine'):
open_dataset(tmp_file, engine='foobar')

netcdf_bytes = data.to_netcdf()
with self.assertRaisesRegexp(ValueError, 'can only read'):
with raises_regex(ValueError, 'can only read'):
open_dataset(BytesIO(netcdf_bytes), engine='foobar')

def test_cross_engine_read_write_netcdf3(self):
@@ -1389,12 +1388,12 @@ def test_common_coord_when_datavars_minimal(self):
def test_invalid_data_vars_value_should_fail(self):

with self.setup_files_and_datasets() as (files, _):
with self.assertRaises(ValueError):
with pytest.raises(ValueError):
with open_mfdataset(files, data_vars='minimum'):
pass

# test invalid coord parameter
with self.assertRaises(ValueError):
with pytest.raises(ValueError):
with open_mfdataset(files, coords='minimum'):
pass

@@ -1452,7 +1451,7 @@ def test_open_mfdataset(self):
self.assertEqual(actual.foo.variable.data.chunks,
((3, 2, 3, 2),))

with self.assertRaisesRegexp(IOError, 'no files to open'):
with raises_regex(IOError, 'no files to open'):
open_mfdataset('foo-bar-baz-*.nc', autoclose=self.autoclose)

@requires_pathlib
@@ -1483,7 +1482,7 @@ def test_attrs_mfdataset(self):
# first dataset loaded
self.assertEqual(actual.test1, ds1.test1)
# attributes from ds2 are not retained, e.g.,
with self.assertRaisesRegexp(AttributeError,
with raises_regex(AttributeError,
'no attribute'):
actual.test2

@@ -1513,15 +1512,15 @@ def test_save_mfdataset_roundtrip(self):

def test_save_mfdataset_invalid(self):
ds = Dataset()
with self.assertRaisesRegexp(ValueError, 'cannot use mode'):
with raises_regex(ValueError, 'cannot use mode'):
save_mfdataset([ds, ds], ['same', 'same'])
with self.assertRaisesRegexp(ValueError, 'same length'):
with raises_regex(ValueError, 'same length'):
save_mfdataset([ds, ds], ['only one path'])

def test_save_mfdataset_invalid_dataarray(self):
# regression test for GH1555
da = DataArray([1, 2])
with self.assertRaisesRegexp(TypeError, 'supports writing Dataset'):
with raises_regex(TypeError, 'supports writing Dataset'):
save_mfdataset([da], ['dataarray'])


@@ -1846,11 +1845,11 @@ def test_indexing(self):
# but on x and y only windowed operations are allowed, more
# exotic slicing should raise an error
err_msg = 'not valid on rasterio'
with self.assertRaisesRegexp(IndexError, err_msg):
with raises_regex(IndexError, err_msg):
actual.isel(x=[2, 4], y=[1, 3]).values
with self.assertRaisesRegexp(IndexError, err_msg):
with raises_regex(IndexError, err_msg):
actual.isel(x=[4, 2]).values
with self.assertRaisesRegexp(IndexError, err_msg):
with raises_regex(IndexError, err_msg):
actual.isel(x=slice(5, 2, -1)).values

# Integer indexing
@@ -1916,7 +1915,7 @@ def test_caching(self):

# Without cache an error is raised
err_msg = 'not valid on rasterio'
with self.assertRaisesRegexp(IndexError, err_msg):
with raises_regex(IndexError, err_msg):
actual.isel(x=[2, 4]).values

# This should cache everything
@@ -1976,7 +1975,7 @@ class TestEncodingInvalid(TestCase):

def test_extract_nc4_variable_encoding(self):
var = xr.Variable(('x',), [1, 2, 3], {}, {'foo': 'bar'})
with self.assertRaisesRegexp(ValueError, 'unexpected encoding'):
with raises_regex(ValueError, 'unexpected encoding'):
_extract_nc4_variable_encoding(var, raise_on_invalid=True)

var = xr.Variable(('x',), [1, 2, 3], {}, {'chunking': (2, 1)})
@@ -1992,7 +1991,7 @@ def test_extract_h5nc_encoding(self):
# not supported with h5netcdf (yet)
var = xr.Variable(('x',), [1, 2, 3], {},
{'least_sigificant_digit': 2})
with self.assertRaisesRegexp(ValueError, 'unexpected encoding'):
with raises_regex(ValueError, 'unexpected encoding'):
_extract_nc4_variable_encoding(var, raise_on_invalid=True)


@@ -2025,17 +2024,17 @@ def new_dataset_and_coord_attrs():
ds, attrs = new_dataset_and_attrs()

attrs[123] = 'test'
with self.assertRaisesRegexp(TypeError, 'Invalid name for attr'):
with raises_regex(TypeError, 'Invalid name for attr'):
ds.to_netcdf('test.nc')

ds, attrs = new_dataset_and_attrs()
attrs[MiscObject()] = 'test'
with self.assertRaisesRegexp(TypeError, 'Invalid name for attr'):
with raises_regex(TypeError, 'Invalid name for attr'):
ds.to_netcdf('test.nc')

ds, attrs = new_dataset_and_attrs()
attrs[''] = 'test'
with self.assertRaisesRegexp(ValueError, 'Invalid name for attr'):
with raises_regex(ValueError, 'Invalid name for attr'):
ds.to_netcdf('test.nc')

# This one should work
@@ -2046,12 +2045,12 @@ def new_dataset_and_coord_attrs():

ds, attrs = new_dataset_and_attrs()
attrs['test'] = {'a': 5}
with self.assertRaisesRegexp(TypeError, 'Invalid value for attr'):
with raises_regex(TypeError, 'Invalid value for attr'):
ds.to_netcdf('test.nc')

ds, attrs = new_dataset_and_attrs()
attrs['test'] = MiscObject()
with self.assertRaisesRegexp(TypeError, 'Invalid value for attr'):
with raises_regex(TypeError, 'Invalid value for attr'):
ds.to_netcdf('test.nc')

ds, attrs = new_dataset_and_attrs()
Loading