Skip to content
forked from pydata/xarray

Commit

Permalink
Merge branch 'master' into concat-join
Browse files Browse the repository at this point in the history
* master:
  enable sphinx.ext.napoleon (pydata#3180)
  remove type annotations from autodoc method signatures (pydata#3179)
  Fix regression: IndexVariable.copy(deep=True) casts dtype=U to object (pydata#3095)
  Fix distributed.Client.compute applied to DataArray (pydata#3173)
  • Loading branch information
dcherian committed Aug 6, 2019
2 parents 23875bb + 01a9baa commit 2899067
Show file tree
Hide file tree
Showing 8 changed files with 77 additions and 25 deletions.
5 changes: 5 additions & 0 deletions doc/conf.py
Original file line number Diff line number Diff line change
Expand Up @@ -66,6 +66,7 @@
'sphinx.ext.intersphinx',
'sphinx.ext.extlinks',
'sphinx.ext.mathjax',
'sphinx.ext.napoleon',
'numpydoc',
'IPython.sphinxext.ipython_directive',
'IPython.sphinxext.ipython_console_highlighting',
Expand All @@ -83,6 +84,10 @@
}

autosummary_generate = True
autodoc_typehints = 'none'

napoleon_use_param = True
napoleon_use_rtype = True

numpydoc_class_members_toctree = True
numpydoc_show_class_members = False
Expand Down
11 changes: 8 additions & 3 deletions doc/whats-new.rst
Original file line number Diff line number Diff line change
Expand Up @@ -48,17 +48,22 @@ Enhancements

Bug fixes
~~~~~~~~~

- Improved error handling and documentation for `.expand_dims()`
- Fix regression introduced in v0.12.2 where ``copy(deep=True)`` would convert
unicode indices to dtype=object (:issue:`3094`).
By `Guido Imperiale <https://github.com/crusaderky>`_.
- Improved error handling and documentation for `.expand_dims()`
read-only view.
- Fix tests for big-endian systems (:issue:`3125`).
By `Graham Inggs <https://github.com/ginggs>`_.
- XFAIL several tests which are expected to fail on ARM systems
due to a ``datetime`` issue in NumPy (:issue:`2334`).
By `Graham Inggs <https://github.com/ginggs>`_.
- Fixed bug in ``combine_by_coords()`` causing a `ValueError` if the input had
an unused dimension with coordinates which were not monotonic (:issue`3150`).
an unused dimension with coordinates which were not monotonic (:issue:`3150`).
By `Tom Nicholas <http://github.com/TomNicholas>`_.
- Fixed crash when applying ``distributed.Client.compute()`` to a DataArray
(:issue:`3171`). By `Guido Imperiale <https://github.com/crusaderky>`_.


.. _whats-new.0.12.3:

Expand Down
6 changes: 3 additions & 3 deletions xarray/core/dataarray.py
Original file line number Diff line number Diff line change
Expand Up @@ -300,7 +300,7 @@ def _replace(
self,
variable: Variable = None,
coords=None,
name: Union[Hashable, None, ReprObject] = __default,
name: Optional[Hashable] = __default,
) -> 'DataArray':
if variable is None:
variable = self.variable
Expand All @@ -313,7 +313,7 @@ def _replace(
def _replace_maybe_drop_dims(
self,
variable: Variable,
name: Union[str, None, utils.ReprObject] = __default
name: Optional[Hashable] = __default
) -> 'DataArray':
if variable.dims == self.dims and variable.shape == self.shape:
coords = self._coords.copy()
Expand Down Expand Up @@ -356,7 +356,7 @@ def _to_temp_dataset(self) -> Dataset:
def _from_temp_dataset(
self,
dataset: Dataset,
name: Union[Hashable, ReprObject] = __default
name: Hashable = __default
) -> 'DataArray':
variable = dataset._variables.pop(_THIS_ARRAY)
coords = dataset._variables
Expand Down
40 changes: 31 additions & 9 deletions xarray/core/indexing.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,12 +3,13 @@
from collections import defaultdict
from contextlib import suppress
from datetime import timedelta
from typing import Sequence
from typing import Any, Tuple, Sequence, Union

import numpy as np
import pandas as pd

from . import duck_array_ops, nputils, utils
from .npcompat import DTypeLike
from .pycompat import dask_array_type, integer_types
from .utils import is_dict_like

Expand Down Expand Up @@ -1227,9 +1228,10 @@ def transpose(self, order):


class PandasIndexAdapter(ExplicitlyIndexedNDArrayMixin):
"""Wrap a pandas.Index to preserve dtypes and handle explicit indexing."""
"""Wrap a pandas.Index to preserve dtypes and handle explicit indexing.
"""

def __init__(self, array, dtype=None):
def __init__(self, array: Any, dtype: DTypeLike = None):
self.array = utils.safe_cast_to_index(array)
if dtype is None:
if isinstance(array, pd.PeriodIndex):
Expand All @@ -1241,13 +1243,15 @@ def __init__(self, array, dtype=None):
dtype = np.dtype('O')
else:
dtype = array.dtype
else:
dtype = np.dtype(dtype)
self._dtype = dtype

@property
def dtype(self):
def dtype(self) -> np.dtype:
return self._dtype

def __array__(self, dtype=None):
def __array__(self, dtype: DTypeLike = None) -> np.ndarray:
if dtype is None:
dtype = self.dtype
array = self.array
Expand All @@ -1258,11 +1262,18 @@ def __array__(self, dtype=None):
return np.asarray(array.values, dtype=dtype)

@property
def shape(self):
def shape(self) -> Tuple[int]:
# .shape is broken on pandas prior to v0.15.2
return (len(self.array),)

def __getitem__(self, indexer):
def __getitem__(
self, indexer
) -> Union[
NumpyIndexingAdapter,
np.ndarray,
np.datetime64,
np.timedelta64,
]:
key = indexer.tuple
if isinstance(key, tuple) and len(key) == 1:
# unpack key so it can index a pandas.Index object (pandas.Index
Expand Down Expand Up @@ -1299,9 +1310,20 @@ def __getitem__(self, indexer):

return result

def transpose(self, order):
def transpose(self, order) -> pd.Index:
return self.array # self.array should be always one-dimensional

def __repr__(self):
def __repr__(self) -> str:
return ('%s(array=%r, dtype=%r)'
% (type(self).__name__, self.array, self.dtype))

def copy(self, deep: bool = True) -> 'PandasIndexAdapter':
# Not the same as just writing `self.array.copy(deep=deep)`, as
# shallow copies of the underlying numpy.ndarrays become deep ones
# upon pickling
# >>> len(pickle.dumps((self.array, self.array)))
# 4000281
# >>> len(pickle.dumps((self.array, self.array.copy(deep=False))))
# 8000341
array = self.array.copy(deep=True) if deep else self.array
return PandasIndexAdapter(array, self._dtype)
10 changes: 10 additions & 0 deletions xarray/core/utils.py
Original file line number Diff line number Diff line change
Expand Up @@ -462,12 +462,22 @@ def __repr__(self: Any) -> str:
class ReprObject:
"""Object that prints as the given value, for use with sentinel values.
"""
__slots__ = ('_value', )

def __init__(self, value: str):
self._value = value

def __repr__(self) -> str:
return self._value

def __eq__(self, other) -> bool:
if isinstance(other, ReprObject):
return self._value == other._value
return False

def __hash__(self) -> int:
return hash((ReprObject, self._value))


@contextlib.contextmanager
def close_on_error(f):
Expand Down
9 changes: 1 addition & 8 deletions xarray/core/variable.py
Original file line number Diff line number Diff line change
Expand Up @@ -1942,14 +1942,7 @@ def copy(self, deep=True, data=None):
data copied from original.
"""
if data is None:
if deep:
# self._data should be a `PandasIndexAdapter` instance at this
# point, which doesn't have a copy method, so make a deep copy
# of the underlying `pandas.MultiIndex` and create a new
# `PandasIndexAdapter` instance with it.
data = PandasIndexAdapter(self._data.array.copy(deep=True))
else:
data = self._data
data = self._data.copy(deep=deep)
else:
data = as_compatible_data(data)
if self.shape != data.shape:
Expand Down
16 changes: 16 additions & 0 deletions xarray/tests/test_utils.py
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
from collections import OrderedDict
from datetime import datetime
from typing import Hashable

import numpy as np
import pandas as pd
Expand Down Expand Up @@ -179,6 +180,21 @@ def test_sorted_keys_dict(self):
def test_repr_object():
obj = utils.ReprObject('foo')
assert repr(obj) == 'foo'
assert isinstance(obj, Hashable)
assert not isinstance(obj, str)


def test_repr_object_magic_methods():
o1 = utils.ReprObject('foo')
o2 = utils.ReprObject('foo')
o3 = utils.ReprObject('bar')
o4 = 'foo'
assert o1 == o2
assert o1 != o3
assert o1 != o4
assert hash(o1) == hash(o2)
assert hash(o1) != hash(o3)
assert hash(o1) != hash(o4)


def test_is_remote_uri():
Expand Down
5 changes: 3 additions & 2 deletions xarray/tests/test_variable.py
Original file line number Diff line number Diff line change
Expand Up @@ -477,8 +477,9 @@ def test_concat_mixed_dtypes(self):
assert actual.dtype == object

@pytest.mark.parametrize('deep', [True, False])
def test_copy(self, deep):
v = self.cls('x', 0.5 * np.arange(10), {'foo': 'bar'})
@pytest.mark.parametrize('astype', [float, int, str])
def test_copy(self, deep, astype):
v = self.cls('x', (0.5 * np.arange(10)).astype(astype), {'foo': 'bar'})
w = v.copy(deep=deep)
assert type(v) is type(w)
assert_identical(v, w)
Expand Down

0 comments on commit 2899067

Please sign in to comment.