Skip to content

Commit

Permalink
unpin numpy (pydata#8061)
Browse files Browse the repository at this point in the history
* unpin `numpy`

* dispatch to `np.empty_like` if there's no missing value

* make sure there's no code path without `create_template`

* declare `create_template` as callable

* ignore the intentionally wrong typing

* mark the ignore as intentional, even if it might not be used

this important because the fix in `numpy` that now means we *don't*
need it anymore has been around for less than 3 months (requires a
sufficiently new version of `mypy`).

* also directly check that `Variable.unstack` does not raise warnings

* fix the unstack test
  • Loading branch information
keewis authored Aug 17, 2023
1 parent 06a756c commit ab096b0
Show file tree
Hide file tree
Showing 9 changed files with 35 additions and 12 deletions.
2 changes: 1 addition & 1 deletion ci/requirements/all-but-dask.yml
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@ dependencies:
- netcdf4
- numba
- numbagg
- numpy<1.24
- numpy
- packaging
- pandas
- pint<0.21
Expand Down
2 changes: 1 addition & 1 deletion ci/requirements/doc.yml
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@ dependencies:
- nbsphinx
- netcdf4>=1.5
- numba
- numpy>=1.21,<1.24
- numpy>=1.21
- packaging>=21.3
- pandas>=1.4
- pooch
Expand Down
2 changes: 1 addition & 1 deletion ci/requirements/environment-windows.yml
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@ dependencies:
- netcdf4
- numba
- numbagg
- numpy<1.24
- numpy
- packaging
- pandas
- pint<0.21
Expand Down
2 changes: 1 addition & 1 deletion ci/requirements/environment.yml
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,7 @@ dependencies:
- numba
- numbagg
- numexpr
- numpy<1.24
- numpy
- packaging
- pandas
- pint<0.21
Expand Down
13 changes: 7 additions & 6 deletions xarray/core/variable.py
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@
import warnings
from collections.abc import Hashable, Iterable, Mapping, Sequence
from datetime import timedelta
from functools import partial
from typing import TYPE_CHECKING, Any, Callable, Literal, NoReturn

import numpy as np
Expand Down Expand Up @@ -1836,15 +1837,20 @@ def _unstack_once(
new_shape = tuple(list(reordered.shape[: len(other_dims)]) + new_dim_sizes)
new_dims = reordered.dims[: len(other_dims)] + new_dim_names

create_template: Callable
if fill_value is dtypes.NA:
is_missing_values = math.prod(new_shape) > math.prod(self.shape)
if is_missing_values:
dtype, fill_value = dtypes.maybe_promote(self.dtype)

create_template = partial(np.full_like, fill_value=fill_value)
else:
dtype = self.dtype
fill_value = dtypes.get_fill_value(dtype)
create_template = np.empty_like
else:
dtype = self.dtype
create_template = partial(np.full_like, fill_value=fill_value)

if sparse:
# unstacking a dense multitindexed array to a sparse array
Expand All @@ -1867,12 +1873,7 @@ def _unstack_once(
)

else:
data = np.full_like(
self.data,
fill_value=fill_value,
shape=new_shape,
dtype=dtype,
)
data = create_template(self.data, shape=new_shape, dtype=dtype)

# Indexer is a list of lists of locations. Each list is the locations
# on the new dimension. This is robust to the data being sparse; in that
Expand Down
2 changes: 1 addition & 1 deletion xarray/tests/test_coding_strings.py
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,7 @@ def test_vlen_dtype() -> None:
assert strings.check_vlen_dtype(dtype) is bytes

# check h5py variant ("vlen")
dtype = np.dtype("O", metadata={"vlen": str}) # type: ignore[call-overload]
dtype = np.dtype("O", metadata={"vlen": str}) # type: ignore[call-overload,unused-ignore]
assert strings.check_vlen_dtype(dtype) is str

assert strings.check_vlen_dtype(np.dtype(object)) is None
Expand Down
13 changes: 13 additions & 0 deletions xarray/tests/test_dataarray.py
Original file line number Diff line number Diff line change
Expand Up @@ -2490,6 +2490,19 @@ def test_unstack_pandas_consistency(self) -> None:
actual = DataArray(s, dims="z").unstack("z")
assert_identical(expected, actual)

@pytest.mark.filterwarnings("error")
def test_unstack_roundtrip_integer_array(self) -> None:
arr = xr.DataArray(
np.arange(6).reshape(2, 3),
coords={"x": ["a", "b"], "y": [0, 1, 2]},
dims=["x", "y"],
)

stacked = arr.stack(z=["x", "y"])
roundtripped = stacked.unstack()

assert_identical(arr, roundtripped)

def test_stack_nonunique_consistency(self, da) -> None:
da = da.isel(time=0, drop=True) # 2D
actual = da.stack(z=["a", "x"])
Expand Down
2 changes: 1 addition & 1 deletion xarray/tests/test_groupby.py
Original file line number Diff line number Diff line change
Expand Up @@ -728,7 +728,7 @@ def test_groupby_dataset_iter() -> None:
def test_groupby_dataset_errors() -> None:
data = create_test_data()
with pytest.raises(TypeError, match=r"`group` must be"):
data.groupby(np.arange(10))
data.groupby(np.arange(10)) # type: ignore
with pytest.raises(ValueError, match=r"length does not match"):
data.groupby(data["dim1"][:3])
with pytest.raises(TypeError, match=r"`group` must be"):
Expand Down
9 changes: 9 additions & 0 deletions xarray/tests/test_variable.py
Original file line number Diff line number Diff line change
Expand Up @@ -1707,6 +1707,15 @@ def test_stack_unstack_consistency(self):
actual = v.stack(z=("x", "y")).unstack(z={"x": 2, "y": 2})
assert_identical(actual, v)

@pytest.mark.filterwarnings("error::RuntimeWarning")
def test_unstack_without_missing(self):
v = Variable(["z"], [0, 1, 2, 3])
expected = Variable(["x", "y"], [[0, 1], [2, 3]])

actual = v.unstack(z={"x": 2, "y": 2})

assert_identical(actual, expected)

def test_broadcasting_math(self):
x = np.random.randn(2, 3)
v = Variable(["a", "b"], x)
Expand Down

0 comments on commit ab096b0

Please sign in to comment.