Skip to content

Commit 72cf0e7

Browse files
committed
Merge remote-tracking branch 'upstream/master' into load_nonindex_coords
2 parents 1c30474 + 5bd4015 commit 72cf0e7

15 files changed

+148
-164
lines changed

.travis.yml

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -39,6 +39,8 @@ matrix:
3939
env: CONDA_ENV=py36-bottleneck-dev
4040
- python: 3.6
4141
env: CONDA_ENV=py36-condaforge-rc
42+
- python: 3.6
43+
env: CONDA_ENV=py36-pynio-dev
4244
allow_failures:
4345
- python: 3.6
4446
env:
@@ -59,6 +61,8 @@ matrix:
5961
env: CONDA_ENV=py36-bottleneck-dev
6062
- python: 3.6
6163
env: CONDA_ENV=py36-condaforge-rc
64+
- python: 3.6
65+
env: CONDA_ENV=py36-pynio-dev
6266

6367
before_install:
6468
- if [[ "$TRAVIS_PYTHON_VERSION" == "2.7" ]]; then

ci/requirements-py36-pynio-dev.yml

Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,25 @@
1+
name: test_env
2+
channels:
3+
- conda-forge
4+
- ncar
5+
dependencies:
6+
- python=3.6
7+
- dask
8+
- distributed
9+
- h5py
10+
- h5netcdf
11+
- matplotlib
12+
- netcdf4
13+
- pynio=dev
14+
- pytest
15+
- numpy
16+
- pandas
17+
- scipy
18+
- seaborn
19+
- toolz
20+
- rasterio
21+
- bottleneck
22+
- pip:
23+
- coveralls
24+
- pytest-cov
25+
- pydap

doc/whats-new.rst

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -203,6 +203,7 @@ Bug fixes
203203
- ``:py:meth:`~xarray.Dataset.__init__` raises a ``MergeError`` if an
204204
coordinate shares a name with a dimension but is comprised of arbitrary
205205
dimensions(:issue:`1120`).
206+
206207
- :py:func:`~xarray.open_rasterio` method now skips rasterio.crs -attribute if
207208
it is none.
208209
By `Leevi Annala <https://github.com/leevei>`_.
@@ -215,6 +216,21 @@ Bug fixes
215216
when objects other than ``Dataset`` are provided (:issue:`1555`).
216217
By `Joe Hamman <https://github.com/jhamman>`_.
217218

219+
- :py:func:`xarray.concat` would eagerly load dask variables into memory if
220+
the first argument was a numpy variable (:issue:`1588`).
221+
By `Guido Imperiale <https://github.com/crusaderky>`_.
222+
223+
- Fix ``netCDF4`` backend to properly roundtrip the ``shuffle`` encoding option
224+
(:issue:`1606`).
225+
By `Joe Hamman <https://github.com/jhamman>`_.
226+
227+
- Fix bug when using ``pytest`` class decorators to skiping certain unittests.
228+
The previous behavior unintentionally causing additional tests to be skipped
229+
(:issue:`1531`). By `Joe Hamman <https://github.com/jhamman>`_.
230+
231+
- Fix pynio backend for upcoming release of pynio with python3 support
232+
(:issue:`1611`). By `Ben Hillman <https://github/brhillman>`_.
233+
218234
.. _whats-new.0.9.6:
219235

220236
v0.9.6 (8 June 2017)

xarray/backends/netCDF4_.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -153,7 +153,7 @@ def _extract_nc4_variable_encoding(variable, raise_on_invalid=False,
153153

154154
safe_to_drop = set(['source', 'original_shape'])
155155
valid_encodings = set(['zlib', 'complevel', 'fletcher32', 'contiguous',
156-
'chunksizes'])
156+
'chunksizes', 'shuffle'])
157157
if lsd_okay:
158158
valid_encodings.add('least_significant_digit')
159159

xarray/backends/pynio_.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -57,7 +57,7 @@ def open_store_variable(self, name, var):
5757
def get_variables(self):
5858
with self.ensure_open(autoclose=False):
5959
return FrozenOrderedDict((k, self.open_store_variable(k, v))
60-
for k, v in self.ds.variables.iteritems())
60+
for k, v in self.ds.variables.items())
6161

6262
def get_attrs(self):
6363
with self.ensure_open(autoclose=True):

xarray/conventions.py

Lines changed: 8 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -858,12 +858,14 @@ def decode_cf_variable(var, concat_characters=True, mask_and_scale=True,
858858
if ('_FillValue' in attributes and
859859
not utils.equivalent(attributes['_FillValue'],
860860
attributes['missing_value'])):
861-
raise ValueError("Discovered conflicting _FillValue "
862-
"and missing_value. Considering "
863-
"opening the offending dataset using "
864-
"decode_cf=False, corrected the attributes",
865-
"and decoding explicitly using "
866-
"xarray.conventions.decode_cf(ds)")
861+
raise ValueError("Conflicting _FillValue and missing_value "
862+
"attributes on a variable: {} vs. {}\n\n"
863+
"Consider opening the offending dataset "
864+
"using decode_cf=False, correcting the "
865+
"attributes and decoding explicitly using "
866+
"xarray.decode_cf()."
867+
.format(attributes['_FillValue'],
868+
attributes['missing_value']))
867869
attributes['_FillValue'] = attributes.pop('missing_value')
868870
fill_value = np.array(pop_to(attributes, encoding, '_FillValue'))
869871
if fill_value.size > 1:

xarray/core/duck_array_ops.py

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -40,9 +40,11 @@ def _dask_or_eager_func(name, eager_module=np, list_of_args=False,
4040
"""Create a function that dispatches to dask for dask array inputs."""
4141
if has_dask:
4242
def f(*args, **kwargs):
43-
dispatch_args = args[0] if list_of_args else args
44-
if any(isinstance(a, da.Array)
45-
for a in dispatch_args[:n_array_args]):
43+
if list_of_args:
44+
dispatch_args = args[0]
45+
else:
46+
dispatch_args = args[:n_array_args]
47+
if any(isinstance(a, da.Array) for a in dispatch_args):
4648
module = da
4749
else:
4850
module = eager_module

xarray/core/groupby.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -236,8 +236,8 @@ def __init__(self, obj, group, squeeze=False, grouper=None, bins=None,
236236
raise ValueError('index must be monotonic for resampling')
237237
s = pd.Series(np.arange(index.size), index)
238238
first_items = s.groupby(grouper).first()
239+
full_index = first_items.index
239240
if first_items.isnull().any():
240-
full_index = first_items.index
241241
first_items = first_items.dropna()
242242
sbins = first_items.values.astype(np.int64)
243243
group_indices = ([slice(i, j)

xarray/tests/__init__.py

Lines changed: 38 additions & 98 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@
55
from contextlib import contextmanager
66
from distutils.version import LooseVersion
77
import re
8+
import importlib
89

910
import numpy as np
1011
from numpy.testing import assert_array_equal
@@ -25,111 +26,50 @@
2526
except ImportError:
2627
import mock
2728

28-
try:
29-
import scipy
30-
has_scipy = True
31-
except ImportError:
32-
has_scipy = False
33-
34-
try:
35-
import pydap.client
36-
has_pydap = True
37-
except ImportError:
38-
has_pydap = False
39-
40-
try:
41-
import netCDF4
42-
has_netCDF4 = True
43-
except ImportError:
44-
has_netCDF4 = False
45-
46-
47-
try:
48-
import h5netcdf
49-
has_h5netcdf = True
50-
except ImportError:
51-
has_h5netcdf = False
52-
53-
54-
try:
55-
import Nio
56-
has_pynio = True
57-
except ImportError:
58-
has_pynio = False
59-
60-
61-
try:
62-
import dask.array
63-
import dask
64-
dask.set_options(get=dask.get)
65-
has_dask = True
66-
except ImportError:
67-
has_dask = False
68-
69-
70-
try:
71-
import matplotlib
72-
has_matplotlib = True
73-
except ImportError:
74-
has_matplotlib = False
75-
7629

77-
try:
78-
import bottleneck
79-
if LooseVersion(bottleneck.__version__) < LooseVersion('1.1'):
80-
raise ImportError('Fall back to numpy')
81-
has_bottleneck = True
82-
except ImportError:
83-
has_bottleneck = False
84-
85-
try:
86-
import rasterio
87-
has_rasterio = True
88-
except ImportError:
89-
has_rasterio = False
90-
91-
try:
92-
import pathlib
93-
has_pathlib = True
94-
except ImportError:
30+
def _importorskip(modname, minversion=None):
9531
try:
96-
import pathlib2
97-
has_pathlib = True
32+
mod = importlib.import_module(modname)
33+
has = True
34+
if minversion is not None:
35+
if LooseVersion(mod.__version__) < LooseVersion(minversion):
36+
raise ImportError('Minimum version not satisfied')
9837
except ImportError:
99-
has_pathlib = False
100-
101-
102-
# slighly simpler construction that the full functions.
103-
# Generally `pytest.importorskip('package')` inline is even easier
104-
requires_matplotlib = pytest.mark.skipif(
105-
not has_matplotlib, reason='requires matplotlib')
106-
requires_scipy = pytest.mark.skipif(
107-
not has_scipy, reason='requires scipy')
108-
requires_pydap = pytest.mark.skipif(
109-
not has_pydap, reason='requires pydap')
110-
requires_netCDF4 = pytest.mark.skipif(
111-
not has_netCDF4, reason='requires netCDF4')
112-
requires_h5netcdf = pytest.mark.skipif(
113-
not has_h5netcdf, reason='requires h5netcdf')
114-
requires_pynio = pytest.mark.skipif(
115-
not has_pynio, reason='requires pynio')
116-
requires_scipy_or_netCDF4 = pytest.mark.skipif(
117-
not has_scipy and not has_netCDF4, reason='requires scipy or netCDF4')
118-
requires_dask = pytest.mark.skipif(
119-
not has_dask, reason='requires dask')
120-
requires_bottleneck = pytest.mark.skipif(
121-
not has_bottleneck, reason='requires bottleneck')
122-
requires_rasterio = pytest.mark.skipif(
123-
not has_rasterio, reason='requires rasterio')
124-
requires_pathlib = pytest.mark.skipif(
125-
not has_pathlib, reason='requires pathlib / pathlib2'
126-
)
127-
38+
has = False
39+
# TODO: use pytest.skipif instead of unittest.skipUnless
40+
# Using `unittest.skipUnless` is a temporary workaround for pytest#568,
41+
# wherein class decorators stain inherited classes.
42+
# xref: xarray#1531, implemented in xarray #1557.
43+
func = unittest.skipUnless(has, reason='requires {}'.format(modname))
44+
return has, func
45+
46+
47+
has_matplotlib, requires_matplotlib = _importorskip('matplotlib')
48+
has_scipy, requires_scipy = _importorskip('scipy')
49+
has_pydap, requires_pydap = _importorskip('pydap.client')
50+
has_netCDF4, requires_netCDF4 = _importorskip('netCDF4')
51+
has_h5netcdf, requires_h5netcdf = _importorskip('h5netcdf')
52+
has_pynio, requires_pynio = _importorskip('Nio')
53+
has_dask, requires_dask = _importorskip('dask')
54+
has_bottleneck, requires_bottleneck = _importorskip('bottleneck')
55+
has_rasterio, requires_rasterio = _importorskip('rasterio')
56+
has_pathlib, requires_pathlib = _importorskip('pathlib')
57+
58+
# some special cases
59+
has_scipy_or_netCDF4 = has_scipy or has_netCDF4
60+
requires_scipy_or_netCDF4 = unittest.skipUnless(
61+
has_scipy_or_netCDF4, reason='requires scipy or netCDF4')
62+
if not has_pathlib:
63+
has_pathlib, requires_pathlib = _importorskip('pathlib2')
64+
65+
if has_dask:
66+
import dask
67+
dask.set_options(get=dask.get)
12868

12969
try:
13070
_SKIP_FLAKY = not pytest.config.getoption("--run-flaky")
13171
_SKIP_NETWORK_TESTS = not pytest.config.getoption("--run-network-tests")
132-
except ValueError:
72+
except (ValueError, AttributeError):
13373
# Can't get config from pytest, e.g., because xarray is installed instead
13474
# of being run from a development version (and hence conftests.py is not
13575
# available). Don't run flaky tests.

xarray/tests/test_backends.py

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -729,6 +729,7 @@ def test_compression_encoding(self):
729729
data['var2'].encoding.update({'zlib': True,
730730
'chunksizes': (5, 5),
731731
'fletcher32': True,
732+
'shuffle': True,
732733
'original_shape': data.var2.shape})
733734
with self.roundtrip(data) as actual:
734735
for k, v in iteritems(data['var2'].encoding):
@@ -1179,7 +1180,7 @@ def test_encoding_unlimited_dims(self):
11791180

11801181

11811182
# tests pending h5netcdf fix
1182-
@pytest.mark.xfail
1183+
@unittest.skip
11831184
class H5NetCDFDataTestAutocloseTrue(H5NetCDFDataTest):
11841185
autoclose = True
11851186

@@ -1846,6 +1847,11 @@ def test_extract_nc4_variable_encoding(self):
18461847
encoding = _extract_nc4_variable_encoding(var)
18471848
self.assertEqual({}, encoding)
18481849

1850+
# regression test
1851+
var = xr.Variable(('x',), [1, 2, 3], {}, {'shuffle': True})
1852+
encoding = _extract_nc4_variable_encoding(var, raise_on_invalid=True)
1853+
self.assertEqual({'shuffle': True}, encoding)
1854+
18491855
def test_extract_h5nc_encoding(self):
18501856
# not supported with h5netcdf (yet)
18511857
var = xr.Variable(('x',), [1, 2, 3], {},

xarray/tests/test_conventions.py

Lines changed: 2 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -451,11 +451,9 @@ def test_cf_timedelta(self):
451451
('1us', 'microseconds', np.int64(1)),
452452
(['NaT', '0s', '1s'], None, [np.nan, 0, 1]),
453453
(['30m', '60m'], 'hours', [0.5, 1.0]),
454+
(np.timedelta64('NaT', 'ns'), 'days', np.nan),
455+
(['NaT', 'NaT'], 'days', [np.nan, np.nan]),
454456
]
455-
if pd.__version__ >= '0.16':
456-
# not quite sure why, but these examples don't work on older pandas
457-
examples.extend([(np.timedelta64('NaT', 'ns'), 'days', np.nan),
458-
(['NaT', 'NaT'], 'days', [np.nan, np.nan])])
459457

460458
for timedeltas, units, numbers in examples:
461459
timedeltas = pd.to_timedelta(timedeltas, box=False)

0 commit comments

Comments
 (0)