From 168eca707832bb26b351d23898e6e8d76a7b0ac8 Mon Sep 17 00:00:00 2001 From: Keewis Date: Wed, 4 Dec 2019 18:29:14 +0100 Subject: [PATCH 01/32] don't use the index to construct the condition array --- xarray/tests/test_units.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/xarray/tests/test_units.py b/xarray/tests/test_units.py index 0be6f8af464..2d640f1ade7 100644 --- a/xarray/tests/test_units.py +++ b/xarray/tests/test_units.py @@ -1171,7 +1171,7 @@ def test_where_dataset(fill_value, unit, error, dtype): x = np.arange(10) * unit_registry.s ds = xr.Dataset(data_vars={"a": ("x", array1), "b": ("x", array2)}, coords={"x": x}) - cond = ds.x < 5 * unit_registry.s + cond = x < 5 * unit_registry.s # FIXME: this should work without wrapping in array() fill_value = np.array(fill_value) * unit From b280a68a7c7789a08c3f6a5e63dc9d8156092585 Mon Sep 17 00:00:00 2001 From: Keewis Date: Wed, 4 Dec 2019 18:37:19 +0100 Subject: [PATCH 02/32] use drop_vars to drop variables and coordinates --- xarray/tests/test_units.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/xarray/tests/test_units.py b/xarray/tests/test_units.py index 2d640f1ade7..ab06bb46c65 100644 --- a/xarray/tests/test_units.py +++ b/xarray/tests/test_units.py @@ -1969,7 +1969,7 @@ def test_broadcast_equals(self, unit, dtype): dim={"z": np.linspace(10, 20, 12) * unit_registry.s}, axis=1, ), - method("drop_sel", labels="x"), + method("drop_vars", "x"), method("reset_coords", names="x2"), method("copy"), pytest.param( @@ -4220,7 +4220,7 @@ def test_grouped_operations(self, func, dtype): method("rename_dims", x="offset_x"), method("swap_dims", {"x": "x2"}), method("expand_dims", v=np.linspace(10, 20, 12) * unit_registry.s, axis=1), - method("drop_sel", labels="x"), + method("drop_vars", "x"), method("drop_dims", "z"), method("set_coords", names="c"), method("reset_coords", names="x2"), From dece3830f8ebb58584f02a445b72dde3ece4d1a7 Mon Sep 17 00:00:00 2001 From: Keewis Date: Wed, 4 Dec 2019 20:05:13 +0100 Subject: [PATCH 03/32] update the xfail reason for astype and item --- xarray/tests/test_units.py | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/xarray/tests/test_units.py b/xarray/tests/test_units.py index ab06bb46c65..796d71fe235 100644 --- a/xarray/tests/test_units.py +++ b/xarray/tests/test_units.py @@ -1974,10 +1974,11 @@ def test_broadcast_equals(self, unit, dtype): method("copy"), pytest.param( method("astype", np.float32), - marks=pytest.mark.xfail(reason="units get stripped"), + marks=pytest.mark.xfail(reason="not provided by `pint` yet"), ), pytest.param( - method("item", 1), marks=pytest.mark.xfail(reason="units get stripped") + method("item", 1), + marks=pytest.mark.xfail(reason="not provided by `pint` yet"), ), ), ids=repr, From cd42e699287a6492dba5a6f4020a1c6ffe612ee1 Mon Sep 17 00:00:00 2001 From: Keewis Date: Wed, 4 Dec 2019 20:25:23 +0100 Subject: [PATCH 04/32] remove the xfails due to np.result_type not being implemented --- xarray/tests/test_units.py | 41 +++++--------------------------------- 1 file changed, 5 insertions(+), 36 deletions(-) diff --git a/xarray/tests/test_units.py b/xarray/tests/test_units.py index 796d71fe235..b3aa2a023d1 100644 --- a/xarray/tests/test_units.py +++ b/xarray/tests/test_units.py @@ -349,9 +349,7 @@ def test_apply_ufunc_dataarray(dtype): assert_equal_with_units(expected, result) -@pytest.mark.xfail( - reason="pint does not implement `np.result_type` and align strips units" -) +@pytest.mark.xfail(reason="align strips units") @pytest.mark.parametrize( "unit,error", ( @@ -433,9 +431,7 @@ def test_align_dataarray(fill_value, variant, unit, error, dtype): assert_equal_with_units(expected_b, result_b) -@pytest.mark.xfail( - reason="pint does not implement `np.result_type` and align strips units" -) +@pytest.mark.xfail(reason="align strips units") @pytest.mark.parametrize( "unit,error", ( @@ -2307,9 +2303,6 @@ def test_interp_like(self, unit, error): assert_equal_with_units(result_array, result_data_array) - @pytest.mark.xfail( - reason="pint does not implement np.result_type in __array_function__ yet" - ) @pytest.mark.parametrize( "unit,error", ( @@ -2346,9 +2339,6 @@ def test_reindex(self, unit, error): assert_equal_with_units(result_array, result_data_array) - @pytest.mark.xfail( - reason="pint does not implement np.result_type in __array_function__ yet" - ) @pytest.mark.parametrize( "unit,error", ( @@ -2750,12 +2740,7 @@ def test_repr(self, func, variant, dtype): reason="np.median does not work with dataset yet" ), ), - pytest.param( - function("sum"), - marks=pytest.mark.xfail( - reason="np.result_type not implemented by pint" - ), - ), + function("sum"), pytest.param( function("prod"), marks=pytest.mark.xfail(reason="not implemented by pint"), @@ -2781,12 +2766,7 @@ def test_repr(self, func, variant, dtype): method("min"), method("mean"), method("median"), - pytest.param( - method("sum"), - marks=pytest.mark.xfail( - reason="np.result_type not implemented by pint" - ), - ), + method("sum"), pytest.param( method("prod"), marks=pytest.mark.xfail(reason="not implemented by pint"), @@ -3162,12 +3142,7 @@ def test_isin(self, unit, dtype): @pytest.mark.parametrize( "variant", ( - pytest.param( - "masking", - marks=pytest.mark.xfail( - reason="np.result_type not implemented by quantity" - ), - ), + "masking", pytest.param( "replacing_scalar", marks=pytest.mark.xfail( @@ -3919,9 +3894,6 @@ def test_interp_like(self, unit, error, dtype): assert_equal_with_units(result, expected) - @pytest.mark.xfail( - reason="pint does not implement np.result_type in __array_function__ yet" - ) @pytest.mark.parametrize( "unit,error", ( @@ -3967,9 +3939,6 @@ def test_reindex(self, unit, error): assert_equal_with_units(result, expected) - @pytest.mark.xfail( - reason="pint does not implement np.result_type in __array_function__ yet" - ) @pytest.mark.parametrize( "unit,error", ( From c8d4a9b64cae10cb2ce830a0cca37874069b6ba0 Mon Sep 17 00:00:00 2001 From: Keewis Date: Wed, 4 Dec 2019 20:26:46 +0100 Subject: [PATCH 05/32] make array_extract_units a bit more robust --- xarray/tests/test_units.py | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/xarray/tests/test_units.py b/xarray/tests/test_units.py index b3aa2a023d1..8744d15f410 100644 --- a/xarray/tests/test_units.py +++ b/xarray/tests/test_units.py @@ -29,9 +29,11 @@ def array_extract_units(obj): - raw = obj.data if hasattr(obj, "data") else obj + if isinstance(obj, (xr.Variable, xr.DataArray, xr.Dataset)): + obj = obj.data + try: - return raw.units + return obj.units except AttributeError: return None From fa67d6717c3ca053b0c779a9220b449aefe87205 Mon Sep 17 00:00:00 2001 From: Keewis Date: Wed, 4 Dec 2019 20:27:32 +0100 Subject: [PATCH 06/32] add the missing dataset apply_ufunc test --- xarray/tests/test_units.py | 22 ++++++++++++++++++++++ 1 file changed, 22 insertions(+) diff --git a/xarray/tests/test_units.py b/xarray/tests/test_units.py index 8744d15f410..7838db89d4e 100644 --- a/xarray/tests/test_units.py +++ b/xarray/tests/test_units.py @@ -351,6 +351,28 @@ def test_apply_ufunc_dataarray(dtype): assert_equal_with_units(expected, result) +def test_apply_ufunc_dataset(dtype): + func = function( + xr.apply_ufunc, np.mean, input_core_dims=[["x"]], kwargs={"axis": -1} + ) + + array1 = np.linspace(0, 10, 5 * 10).reshape(5, 10).astype(dtype) * unit_registry.m + array2 = np.linspace(0, 10, 5).astype(dtype) * unit_registry.m + + x = np.arange(5) * unit_registry.s + y = np.arange(10) * unit_registry.m + + ds = xr.Dataset( + data_vars={"a": (("x", "y"), array1), "b": ("x", array2)}, + coords={"x": x, "y": y}, + ) + + expected = attach_units(func(strip_units(ds)), extract_units(ds)) + result = func(ds) + + assert_equal_with_units(expected, result) + + @pytest.mark.xfail(reason="align strips units") @pytest.mark.parametrize( "unit,error", From cd155fe3204c0ce1719821dfad8014d3c18754bd Mon Sep 17 00:00:00 2001 From: Keewis Date: Wed, 4 Dec 2019 20:28:21 +0100 Subject: [PATCH 07/32] use None as the dict key for quantities --- xarray/tests/test_units.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/xarray/tests/test_units.py b/xarray/tests/test_units.py index 7838db89d4e..65a3420c050 100644 --- a/xarray/tests/test_units.py +++ b/xarray/tests/test_units.py @@ -114,7 +114,7 @@ def extract_units(obj): units = {**vars_units, **coords_units} elif isinstance(obj, Quantity): - vars_units = {"": array_extract_units(obj)} + vars_units = {None: array_extract_units(obj)} units = {**vars_units} else: From 2a1df4721270ca9a583da42da3b2d96e993cedd6 Mon Sep 17 00:00:00 2001 From: Keewis Date: Wed, 4 Dec 2019 21:38:28 +0100 Subject: [PATCH 08/32] convert to variable to avoid the merge / assign_coords issue relevant issue: #3483 --- xarray/tests/test_units.py | 10 +++++++--- 1 file changed, 7 insertions(+), 3 deletions(-) diff --git a/xarray/tests/test_units.py b/xarray/tests/test_units.py index 65a3420c050..db6c700edf9 100644 --- a/xarray/tests/test_units.py +++ b/xarray/tests/test_units.py @@ -205,9 +205,13 @@ def attach_units(obj, units): def convert_units(obj, to): if isinstance(obj, xr.Dataset): data_vars = { - name: convert_units(array, to) for name, array in obj.data_vars.items() + name: convert_units(array, to).variable + for name, array in obj.data_vars.items() + } + coords = { + name: convert_units(array, to).variable + for name, array in obj.coords.items() } - coords = {name: convert_units(array, to) for name, array in obj.coords.items()} new_obj = xr.Dataset(data_vars=data_vars, coords=coords, attrs=obj.attrs) elif isinstance(obj, xr.DataArray): @@ -219,7 +223,7 @@ def convert_units(obj, to): data = convert_units(obj.data, {None: new_units}) coords = { - name: (array.dims, convert_units(array.data, to)) + name: (array.dims, convert_units(array.data, to).variable) for name, array in obj.coords.items() if name != obj.name } From cd6f6e726fd5c1f3d12866b69c5e37b11887472e Mon Sep 17 00:00:00 2001 From: Keewis Date: Wed, 4 Dec 2019 21:41:11 +0100 Subject: [PATCH 09/32] update the align tests --- xarray/tests/test_units.py | 34 ++++++++++++++-------------------- 1 file changed, 14 insertions(+), 20 deletions(-) diff --git a/xarray/tests/test_units.py b/xarray/tests/test_units.py index db6c700edf9..4537a54c453 100644 --- a/xarray/tests/test_units.py +++ b/xarray/tests/test_units.py @@ -435,24 +435,18 @@ def test_align_dataarray(fill_value, variant, unit, error, dtype): return stripped_kwargs = { - key: strip_units( - convert_units(value, {None: original_unit}) - if isinstance(value, unit_registry.Quantity) - else value - ) + key: strip_units(convert_units(value, {None: original_unit})) for key, value in func.kwargs.items() } units = extract_units(data_array1) - # FIXME: should the expected_b have the same units as data_array1 - # or data_array2? - expected_a, expected_b = tuple( - attach_units(elem, units) - for elem in func( - strip_units(data_array1), - strip_units(convert_units(data_array2, units)), - **stripped_kwargs, - ) + expected_a, expected_b = func( + strip_units(data_array1), strip_units(data_array2), **stripped_kwargs ) + expected_a = attach_units(expected_a, units) + # FIXME: should expected_b have the same units as data_array1 + # or data_array2? + expected_b = attach_units(expected_b, units) + result_a, result_b = func(data_array1, data_array2) assert_equal_with_units(expected_a, result_a) @@ -528,13 +522,13 @@ def test_align_dataset(fill_value, unit, variant, error, dtype): for key, value in func.kwargs.items() } units = extract_units(ds1) - # FIXME: should the expected_b have the same units as ds1 or ds2? - expected_a, expected_b = tuple( - attach_units(elem, units) - for elem in func( - strip_units(ds1), strip_units(convert_units(ds2, units)), **stripped_kwargs - ) + expected_a, expected_b = func( + strip_units(ds1), strip_units(convert_units(ds2, units)), **stripped_kwargs ) + expected_a = attach_units(expected_a, units) + # FIXME: should expected_b have the same units as ds1 or ds2? + expected_b = attach_units(expected_b, units) + result_a, result_b = func(ds1, ds2) assert_equal_with_units(expected_a, result_a) From 54dc98d04fd60aae017d50205151caa442ee25c9 Mon Sep 17 00:00:00 2001 From: Keewis Date: Wed, 4 Dec 2019 22:12:25 +0100 Subject: [PATCH 10/32] fix the bugs introduced by converting to variables --- xarray/tests/test_units.py | 11 +++++++---- 1 file changed, 7 insertions(+), 4 deletions(-) diff --git a/xarray/tests/test_units.py b/xarray/tests/test_units.py index 4537a54c453..2e112b8d19d 100644 --- a/xarray/tests/test_units.py +++ b/xarray/tests/test_units.py @@ -205,11 +205,11 @@ def attach_units(obj, units): def convert_units(obj, to): if isinstance(obj, xr.Dataset): data_vars = { - name: convert_units(array, to).variable + name: convert_units(array.variable, {None: to.get(name)}) for name, array in obj.data_vars.items() } coords = { - name: convert_units(array, to).variable + name: convert_units(array.variable, {None: to.get(name)}) for name, array in obj.coords.items() } @@ -220,10 +220,10 @@ def convert_units(obj, to): new_units = ( to.get(name, None) or to.get("data", None) or to.get(None, None) or 1 ) - data = convert_units(obj.data, {None: new_units}) + data = convert_units(obj.variable, {None: new_units}) coords = { - name: (array.dims, convert_units(array.data, to).variable) + name: (array.dims, convert_units(array.variable, {None: to.get(name)})) for name, array in obj.coords.items() if name != obj.name } @@ -231,6 +231,9 @@ def convert_units(obj, to): new_obj = xr.DataArray( name=name, data=data, coords=coords, attrs=obj.attrs, dims=obj.dims ) + elif isinstance(obj, xr.Variable): + new_data = convert_units(obj.data, to) + new_obj = obj.copy(data=new_data) elif isinstance(obj, unit_registry.Quantity): units = to.get(None) new_obj = obj.to(units) if units is not None else obj From d220eb025d8525598826bfb53d11568c249c8692 Mon Sep 17 00:00:00 2001 From: Keewis Date: Wed, 4 Dec 2019 23:56:46 +0100 Subject: [PATCH 11/32] update a few more tests --- xarray/tests/test_units.py | 38 ++++++++++++++++++-------------------- 1 file changed, 18 insertions(+), 20 deletions(-) diff --git a/xarray/tests/test_units.py b/xarray/tests/test_units.py index 2e112b8d19d..e00da60ff42 100644 --- a/xarray/tests/test_units.py +++ b/xarray/tests/test_units.py @@ -1128,7 +1128,6 @@ def test_replication_full_like_dataset(unit, error, dtype): assert_equal_with_units(expected, result) -@pytest.mark.xfail(reason="`where` strips units") @pytest.mark.parametrize( "unit,error", ( @@ -1157,21 +1156,19 @@ def test_where_dataarray(fill_value, unit, error, dtype): return - fill_value_ = ( - fill_value.to(unit_registry.m) - if isinstance(fill_value, unit_registry.Quantity) - and fill_value.check(unit_registry.m) - else fill_value - ) expected = attach_units( - xr.where(cond, strip_units(x), strip_units(fill_value_)), extract_units(x) + xr.where( + cond, + strip_units(x), + strip_units(convert_units(fill_value, {None: unit_registry.m})), + ), + extract_units(x), ) result = xr.where(cond, x, fill_value) assert_equal_with_units(expected, result) -@pytest.mark.xfail(reason="`where` strips units") @pytest.mark.parametrize( "unit,error", ( @@ -1202,14 +1199,13 @@ def test_where_dataset(fill_value, unit, error, dtype): return - fill_value_ = ( - fill_value.to(unit_registry.m) - if isinstance(fill_value, unit_registry.Quantity) - and fill_value.check(unit_registry.m) - else fill_value - ) expected = attach_units( - xr.where(cond, strip_units(ds), strip_units(fill_value_)), extract_units(ds) + xr.where( + cond, + strip_units(ds), + strip_units(convert_units(fill_value, {None: unit_registry.m})), + ), + extract_units(ds), ) result = xr.where(cond, ds, fill_value) @@ -1227,11 +1223,13 @@ def test_dot_dataarray(dtype): np.linspace(10, 20, 10 * 20).reshape(10, 20).astype(dtype) * unit_registry.s ) - arr1 = xr.DataArray(data=array1, dims=("x", "y")) - arr2 = xr.DataArray(data=array2, dims=("y", "z")) + data_array = xr.DataArray(data=array1, dims=("x", "y")) + other = xr.DataArray(data=array2, dims=("y", "z")) - expected = array1.dot(array2) - result = xr.dot(arr1, arr2) + expected = attach_units( + xr.dot(strip_units(data_array), strip_units(other)), {None: unit_registry.m} + ) + result = xr.dot(data_array, other) assert_equal_with_units(expected, result) From c95effb406dfc5b97ab9fc8c4ea975bfad5ac19f Mon Sep 17 00:00:00 2001 From: Keewis Date: Thu, 5 Dec 2019 00:13:36 +0100 Subject: [PATCH 12/32] update the aggregation tests --- xarray/tests/test_units.py | 40 +++++++++----------------------------- 1 file changed, 9 insertions(+), 31 deletions(-) diff --git a/xarray/tests/test_units.py b/xarray/tests/test_units.py index e00da60ff42..b7652a3f3d1 100644 --- a/xarray/tests/test_units.py +++ b/xarray/tests/test_units.py @@ -1314,26 +1314,11 @@ def test_repr(self, func, variant, dtype): function("any"), marks=pytest.mark.xfail(reason="not implemented by pint yet"), ), - pytest.param( - function("argmax"), - marks=pytest.mark.xfail( - reason="comparison of quantity with ndarrays in nanops not implemented" - ), - ), - pytest.param( - function("argmin"), - marks=pytest.mark.xfail( - reason="comparison of quantity with ndarrays in nanops not implemented" - ), - ), + function("argmax"), + function("argmin"), function("max"), function("mean"), - pytest.param( - function("median"), - marks=pytest.mark.xfail( - reason="np.median on DataArray strips the units" - ), - ), + function("median"), function("min"), pytest.param( function("prod"), @@ -1360,18 +1345,8 @@ def test_repr(self, func, variant, dtype): method("any"), marks=pytest.mark.xfail(reason="not implemented by pint yet"), ), - pytest.param( - method("argmax"), - marks=pytest.mark.xfail( - reason="comparison of quantities with ndarrays in nanops not implemented" - ), - ), - pytest.param( - method("argmin"), - marks=pytest.mark.xfail( - reason="comparison of quantities with ndarrays in nanops not implemented" - ), - ), + method("argmax"), + method("argmin"), method("max"), method("mean"), method("median"), @@ -1402,7 +1377,10 @@ def test_aggregation(self, func, dtype): array = np.arange(10).astype(dtype) * unit_registry.m data_array = xr.DataArray(data=array) - expected = xr.DataArray(data=func(array)) + # units differ based on the applied function, so we need to + # first compute the units + units = extract_units(func(array)) + expected = attach_units(func(strip_units(data_array)), units) result = func(data_array) assert_equal_with_units(expected, result) From 21410e5f0bcfa3c68c08b593b8837e74da9887e9 Mon Sep 17 00:00:00 2001 From: Keewis Date: Thu, 5 Dec 2019 22:29:00 +0100 Subject: [PATCH 13/32] update a few more tests --- xarray/tests/test_units.py | 236 ++++++++++++++++++++++--------------- 1 file changed, 144 insertions(+), 92 deletions(-) diff --git a/xarray/tests/test_units.py b/xarray/tests/test_units.py index b7652a3f3d1..5d0a43e9a9d 100644 --- a/xarray/tests/test_units.py +++ b/xarray/tests/test_units.py @@ -517,20 +517,17 @@ def test_align_dataset(fill_value, unit, variant, error, dtype): return stripped_kwargs = { - key: strip_units( - convert_units(value, {None: original_unit}) - if isinstance(value, unit_registry.Quantity) - else value - ) + key: strip_units(convert_units(value, {None: original_unit})) for key, value in func.kwargs.items() } - units = extract_units(ds1) + units_a = extract_units(ds1) + units_b = extract_units(ds2) expected_a, expected_b = func( - strip_units(ds1), strip_units(convert_units(ds2, units)), **stripped_kwargs + strip_units(ds1), strip_units(convert_units(ds2, units_a)), **stripped_kwargs ) - expected_a = attach_units(expected_a, units) + expected_a = attach_units(expected_a, units_a) # FIXME: should expected_b have the same units as ds1 or ds2? - expected_b = attach_units(expected_b, units) + expected_b = convert_units(attach_units(expected_b, units_a), units_b) result_a, result_b = func(ds1, ds2) @@ -1390,18 +1387,15 @@ def test_aggregation(self, func, dtype): ( pytest.param(operator.neg, id="negate"), pytest.param(abs, id="absolute"), - pytest.param( - np.round, - id="round", - marks=pytest.mark.xfail(reason="pint does not implement round"), - ), + pytest.param(np.round, id="round"), ), ) def test_unary_operations(self, func, dtype): array = np.arange(10).astype(dtype) * unit_registry.m data_array = xr.DataArray(data=array) - expected = xr.DataArray(data=func(array)) + units = extract_units(func(array)) + expected = attach_units(func(strip_units(data_array)), units) result = func(data_array) assert_equal_with_units(expected, result) @@ -1425,7 +1419,8 @@ def test_binary_operations(self, func, dtype): array = np.arange(10).astype(dtype) * unit_registry.m data_array = xr.DataArray(data=array) - expected = xr.DataArray(data=func(array)) + units = extract_units(func(array)) + expected = attach_units(func(strip_units(data_array)), units) result = func(data_array) assert_equal_with_units(expected, result) @@ -1445,8 +1440,9 @@ def test_binary_operations(self, func, dtype): pytest.param( unit_registry.dimensionless, DimensionalityError, id="dimensionless" ), - pytest.param(unit_registry.s, DimensionalityError, id="incorrect_unit"), - pytest.param(unit_registry.m, None, id="correct_unit"), + pytest.param(unit_registry.s, DimensionalityError, id="incompatible_unit"), + pytest.param(unit_registry.mm, None, id="compatible_unit"), + pytest.param(unit_registry.m, None, id="identical_unit"), ), ) def test_comparison_operations(self, comparison, unit, error, dtype): @@ -1466,48 +1462,85 @@ def test_comparison_operations(self, comparison, unit, error, dtype): with pytest.raises(error): comparison(data_array, to_compare_with) - else: - result = comparison(data_array, to_compare_with) - # pint compares incompatible arrays to False, so we need to extend - # the multiplication works for both scalar and array results - expected = xr.DataArray( - data=comparison(array, to_compare_with) - * np.ones_like(array, dtype=bool) - ) - assert_equal_with_units(expected, result) + return + + result = comparison(data_array, to_compare_with) + + expected_units = {None: unit_registry.m if array.check(unit) else None} + expected = array.check(unit) & comparison( + strip_units(data_array), + strip_units(convert_units(to_compare_with, expected_units)), + ) + + assert_equal_with_units(expected, result) @pytest.mark.parametrize( "units,error", ( pytest.param(unit_registry.dimensionless, None, id="dimensionless"), - pytest.param(unit_registry.m, DimensionalityError, id="incorrect unit"), - pytest.param(unit_registry.degree, None, id="correct unit"), + pytest.param(unit_registry.m, DimensionalityError, id="incompatible_unit"), + pytest.param(unit_registry.degree, None, id="compatible_unit"), ), ) def test_univariate_ufunc(self, units, error, dtype): array = np.arange(10).astype(dtype) * units data_array = xr.DataArray(data=array) + func = function("sin") + if error is not None: with pytest.raises(error): np.sin(data_array) - else: - expected = xr.DataArray(data=np.sin(array)) - result = np.sin(data_array) - assert_equal_with_units(expected, result) + return - @pytest.mark.xfail(reason="pint's implementation of `np.maximum` strips units") - def test_bivariate_ufunc(self, dtype): - unit = unit_registry.m - array = np.arange(10).astype(dtype) * unit + expected = attach_units( + func(strip_units(convert_units(data_array, {None: unit_registry.radians}))), + {None: unit_registry.dimensionless}, + ) + result = func(data_array) + + assert_equal_with_units(expected, result) + + @pytest.mark.xfail(reason="xarray's `np.maximum` strips units") + @pytest.mark.parametrize( + "unit,error", + ( + pytest.param(1, DimensionalityError, id="without_unit"), + pytest.param( + unit_registry.dimensionless, DimensionalityError, id="dimensionless" + ), + pytest.param(unit_registry.s, DimensionalityError, id="incompatible_unit"), + pytest.param(unit_registry.mm, None, id="compatible_unit"), + pytest.param(unit_registry.m, None, id="identical_unit"), + ), + ) + def test_bivariate_ufunc(self, unit, error, dtype): + original_unit = unit_registry.m + array = np.arange(10).astype(dtype) * original_unit data_array = xr.DataArray(data=array) - expected = xr.DataArray(np.maximum(array, 0 * unit)) + if error is not None: + with pytest.raises(error): + np.maximum(data_array, 0 * unit) + + return - assert_equal_with_units(expected, np.maximum(data_array, 0 * unit)) - assert_equal_with_units(expected, np.maximum(0 * unit, data_array)) + expected_units = {None: original_unit} + expected = attach_units( + np.maximum( + strip_units(data_array), + strip_units(convert_units(0 * unit, expected_units)), + ), + expected_units, + ) + + result = np.maximum(data_array, 0 * unit) + assert_equal_with_units(expected, result) + + result = np.maximum(0 * unit, data_array) + assert_equal_with_units(expected, result) @pytest.mark.parametrize("property", ("T", "imag", "real")) def test_numpy_properties(self, property, dtype): @@ -1515,11 +1548,11 @@ def test_numpy_properties(self, property, dtype): np.arange(5 * 10).astype(dtype) + 1j * np.linspace(-1, 0, 5 * 10).astype(dtype) ).reshape(5, 10) * unit_registry.s + data_array = xr.DataArray(data=array, dims=("x", "y")) - expected = xr.DataArray( - data=getattr(array, property), - dims=("x", "y")[:: 1 if property != "T" else -1], + expected = attach_units( + getattr(strip_units(data_array), property), extract_units(data_array) ) result = getattr(data_array, property) @@ -1543,13 +1576,24 @@ def test_numpy_methods(self, func, dtype): array = np.arange(10).astype(dtype) * unit_registry.m data_array = xr.DataArray(data=array, dims="x") - expected = xr.DataArray(func(array), dims="x") + units = extract_units(func(array)) + expected = attach_units(strip_units(data_array), units) result = func(data_array) assert_equal_with_units(expected, result) @pytest.mark.parametrize( - "func", (method("clip", min=3, max=8), method("searchsorted", v=5)), ids=repr + "func", + ( + method("clip", min=3, max=8), + pytest.param( + method("searchsorted", v=5), + marks=pytest.mark.xfail( + reason="searchsorted somehow requires a undocumented `keys` argument" + ), + ), + ), + ids=repr, ) @pytest.mark.parametrize( "unit,error", @@ -1572,20 +1616,24 @@ def test_numpy_methods_with_args(self, func, unit, error, dtype): key: (value * unit if isinstance(value, scalar_types) else value) for key, value in func.kwargs.items() } - if error is not None: with pytest.raises(error): func(data_array, **kwargs) - else: - expected = func(array, **kwargs) - if func.name not in ["searchsorted"]: - expected = xr.DataArray(data=expected) - result = func(data_array, **kwargs) - if func.name in ["searchsorted"]: - assert np.allclose(expected, result) - else: - assert_equal_with_units(expected, result) + return + + units = extract_units(data_array) + expected_units = extract_units(func(array, **kwargs)) + stripped_kwargs = { + key: strip_units(convert_units(value, units)) + for key, value in kwargs.items() + } + expected = attach_units( + func(strip_units(data_array), **stripped_kwargs), expected_units + ) + result = func(data_array, **kwargs) + + assert_equal_with_units(expected, result) @pytest.mark.parametrize( "func", (method("isnull"), method("notnull"), method("count")), ids=repr @@ -1686,7 +1734,7 @@ def test_dropna(self, dtype): pytest.param(unit_registry.dimensionless, id="dimensionless"), pytest.param(unit_registry.s, id="incompatible_unit"), pytest.param(unit_registry.cm, id="compatible_unit"), - pytest.param(unit_registry.m, id="same_unit"), + pytest.param(unit_registry.m, id="identical_unit"), ), ) def test_isin(self, unit, dtype): @@ -1699,12 +1747,13 @@ def test_isin(self, unit, dtype): raw_values = np.array([1.4, np.nan, 2.3]).astype(dtype) values = raw_values * unit - result_without_units = strip_units(data_array).isin(raw_values) - if unit != unit_registry.m: - result_without_units[:] = False - result_with_units = data_array.isin(values) + units = {None: unit_registry.m if array.check(unit) else None} + expected = strip_units(data_array).isin( + strip_units(convert_units(values, units)) + ) & array.check(unit) + result = data_array.isin(values) - assert_equal_with_units(result_without_units, result_with_units) + assert_equal_with_units(expected, result) @pytest.mark.parametrize( "variant", @@ -1738,13 +1787,10 @@ def test_isin(self, unit, dtype): ), pytest.param(unit_registry.s, DimensionalityError, id="incompatible_unit"), pytest.param(unit_registry.cm, None, id="compatible_unit"), - pytest.param(unit_registry.m, None, id="same_unit"), + pytest.param(unit_registry.m, None, id="identical_unit"), ), ) def test_where(self, variant, unit, error, dtype): - def _strip_units(mapping): - return {key: array_strip_units(value) for key, value in mapping.items()} - original_unit = unit_registry.m array = np.linspace(0, 1, 10).astype(dtype) * original_unit @@ -1759,19 +1805,29 @@ def _strip_units(mapping): "dropping": {"cond": condition, "drop": True}, } kwargs = variant_kwargs.get(variant) - kwargs_without_units = _strip_units(kwargs) + kwargs_without_units = { + key: strip_units( + convert_units( + value, {None: original_unit if array.check(unit) else None} + ) + ) + for key, value in kwargs.items() + } if variant not in ("masking", "dropping") and error is not None: with pytest.raises(error): data_array.where(**kwargs) - else: - expected = attach_units( - strip_units(array).where(**kwargs_without_units), - {"data": original_unit}, - ) - result = data_array.where(**kwargs) - assert_equal_with_units(expected, result) + return + + expected = attach_units( + strip_units(data_array).where(**kwargs_without_units), + extract_units(data_array), + ) + print("expected:", expected, sep="\n") + result = data_array.where(**kwargs) + + assert_equal_with_units(expected, result) @pytest.mark.xfail(reason="interpolate strips units") def test_interpolate_na(self, dtype): @@ -2307,9 +2363,11 @@ def test_interp_like(self, unit, error): @pytest.mark.parametrize( "unit,error", ( - pytest.param(1, None, id="no_unit"), - pytest.param(unit_registry.dimensionless, None, id="dimensionless"), - pytest.param(unit_registry.s, None, id="incompatible_unit"), + pytest.param(1, DimensionalityError, id="no_unit"), + pytest.param( + unit_registry.dimensionless, DimensionalityError, id="dimensionless" + ), + pytest.param(unit_registry.s, DimensionalityError, id="incompatible_unit"), pytest.param(unit_registry.cm, None, id="compatible_unit"), pytest.param(unit_registry.m, None, id="identical_unit"), ), @@ -2323,22 +2381,19 @@ def test_reindex(self, unit, error): } data_array = xr.DataArray(array, coords=coords, dims=("x", "y")) + func = method("reindex") if error is not None: with pytest.raises(error): - data_array.interp(x=new_coords) - else: - result_array = strip_units(data_array).reindex( - x=( - new_coords.magnitude - if hasattr(new_coords, "magnitude") - else new_coords - ) - * unit_registry.degK - ) - result_data_array = data_array.reindex(x=new_coords) + func(data_array, x=new_coords) - assert_equal_with_units(result_array, result_data_array) + expected = attach_units( + func(strip_units(data_array), x=strip_units(new_coords)), + {None: unit_registry.degK}, + ) + actual = func(data_array, x=new_coords) + + assert_equal_with_units(expected, actual) @pytest.mark.parametrize( "unit,error", @@ -2612,10 +2667,7 @@ class TestDataset: "shared", ( "nothing", - pytest.param( - "dims", - marks=pytest.mark.xfail(reason="reindex does not work with pint yet"), - ), + pytest.param("dims", marks=pytest.mark.xfail(reason="indexes strip units")), pytest.param( "coords", marks=pytest.mark.xfail(reason="reindex does not work with pint yet"), From 19b05265e92a08385a47e122246e4edfc57a4f28 Mon Sep 17 00:00:00 2001 From: Keewis Date: Thu, 5 Dec 2019 22:30:14 +0100 Subject: [PATCH 14/32] don't test rank which was deprecated in numpy 1.9 --- xarray/tests/test_units.py | 15 +-------------- 1 file changed, 1 insertion(+), 14 deletions(-) diff --git a/xarray/tests/test_units.py b/xarray/tests/test_units.py index 5d0a43e9a9d..52a62bbfcd7 100644 --- a/xarray/tests/test_units.py +++ b/xarray/tests/test_units.py @@ -1560,16 +1560,7 @@ def test_numpy_properties(self, property, dtype): @pytest.mark.parametrize( "func", - ( - method("conj"), - method("argsort"), - method("conjugate"), - method("round"), - pytest.param( - method("rank", dim="x"), - marks=pytest.mark.xfail(reason="pint does not implement rank yet"), - ), - ), + (method("conj"), method("argsort"), method("conjugate"), method("round")), ids=repr, ) def test_numpy_methods(self, func, dtype): @@ -2887,10 +2878,6 @@ def test_numpy_properties(self, property, dtype): method("argsort"), method("conjugate"), method("round"), - pytest.param( - method("rank", dim="x"), - marks=pytest.mark.xfail(reason="pint does not implement rank yet"), - ), ), ids=repr, ) From ea1cd2354c95f9aad6b6074cd13dfb5be7ab6a07 Mon Sep 17 00:00:00 2001 From: Keewis Date: Thu, 5 Dec 2019 22:46:52 +0100 Subject: [PATCH 15/32] update the DataArray.fillna tests --- xarray/tests/test_units.py | 54 ++++++++++++++++++++++++++++---------- 1 file changed, 40 insertions(+), 14 deletions(-) diff --git a/xarray/tests/test_units.py b/xarray/tests/test_units.py index 52a62bbfcd7..c0e12fe7576 100644 --- a/xarray/tests/test_units.py +++ b/xarray/tests/test_units.py @@ -1675,30 +1675,56 @@ def test_missing_value_filling(self, func, dtype): assert_equal_with_units(expected, result) - @pytest.mark.xfail(reason="fillna drops the unit") @pytest.mark.parametrize( - "fill_value", + "unit,error", ( + pytest.param(1, DimensionalityError, id="no_unit"), pytest.param( - -1, - id="python scalar", - marks=pytest.mark.xfail( - reason="python scalar cannot be converted using astype()" - ), + unit_registry.dimensionless, DimensionalityError, id="dimensionless" ), - pytest.param(np.array(-1), id="numpy scalar"), - pytest.param(np.array([-1]), id="numpy array"), + pytest.param(unit_registry.s, DimensionalityError, id="incompatible_unit"), + pytest.param( + unit_registry.cm, + None, + id="compatible_unit", + marks=pytest.mark.xfail(reason="fillna converts to value's unit"), + ), + pytest.param(unit_registry.m, None, id="identical_unit"), ), ) - def test_fillna(self, fill_value, dtype): - unit = unit_registry.m - array = np.array([1.4, np.nan, 2.3, np.nan, np.nan, 9.1]).astype(dtype) * unit + @pytest.mark.parametrize( + "fill_value", + ( + pytest.param(-1, id="python_scalar"), + pytest.param(np.array(-1), id="numpy_scalar"), + pytest.param(np.array([-1]), id="numpy_array"), + ), + ) + def test_fillna(self, fill_value, unit, error, dtype): + original_unit = unit_registry.m + array = ( + np.array([1.4, np.nan, 2.3, np.nan, np.nan, 9.1]).astype(dtype) + * original_unit + ) data_array = xr.DataArray(data=array) + func = method("fillna") + + value = fill_value * unit + if error is not None: + with pytest.raises(error): + func(data_array, value=value) + + return + + units = extract_units(data_array) expected = attach_units( - strip_units(data_array).fillna(value=fill_value), {"data": unit} + func( + strip_units(data_array), value=strip_units(convert_units(value, units)) + ), + units, ) - result = data_array.fillna(value=fill_value * unit) + result = func(data_array, value=value) assert_equal_with_units(expected, result) From 7bd4dcb6272f8b55b6ea38d89e0d77a500207eae Mon Sep 17 00:00:00 2001 From: Keewis Date: Fri, 6 Dec 2019 02:22:54 +0100 Subject: [PATCH 16/32] update most of the remaining DataArray tests --- xarray/tests/test_units.py | 424 +++++++++++++++++++------------------ 1 file changed, 213 insertions(+), 211 deletions(-) diff --git a/xarray/tests/test_units.py b/xarray/tests/test_units.py index c0e12fe7576..c30f5333e74 100644 --- a/xarray/tests/test_units.py +++ b/xarray/tests/test_units.py @@ -1069,11 +1069,16 @@ def test_replication_full_like_dataarray(unit, error, dtype): if error is not None: with pytest.raises(error): xr.full_like(data_array, fill_value=fill_value) - else: - result = xr.full_like(data_array, fill_value=fill_value) - expected = np.full_like(array, fill_value=fill_value) - assert_equal_with_units(expected, result) + return + + units = {**extract_units(data_array), **{None: unit if unit != 1 else None}} + expected = attach_units( + xr.full_like(strip_units(data_array), fill_value=strip_units(fill_value)), units + ) + result = xr.full_like(data_array, fill_value=fill_value) + + assert_equal_with_units(expected, result) @pytest.mark.xfail( @@ -1114,11 +1119,12 @@ def test_replication_full_like_dataset(unit, error, dtype): return - expected = ds.copy( - data={ - name: np.full_like(array, fill_value=fill_value) - for name, array in ds.data_vars.items() - } + units = { + **extract_units(ds), + **{name: unit if unit != 1 else None for name in ds.data_vars}, + } + expected = attach_units( + xr.full_like(strip_units(ds), fill_value=strip_units(fill_value)), units ) result = xr.full_like(ds, fill_value=fill_value) @@ -1144,8 +1150,7 @@ def test_where_dataarray(fill_value, unit, error, dtype): x = xr.DataArray(data=array, dims="x") cond = x < 5 * unit_registry.m - # FIXME: this should work without wrapping in array() - fill_value = np.array(fill_value) * unit + fill_value = fill_value * unit if error is not None: with pytest.raises(error): @@ -1187,8 +1192,7 @@ def test_where_dataset(fill_value, unit, error, dtype): ds = xr.Dataset(data_vars={"a": ("x", array1), "b": ("x", array2)}, coords={"x": x}) cond = x < 5 * unit_registry.s - # FIXME: this should work without wrapping in array() - fill_value = np.array(fill_value) * unit + fill_value = fill_value * unit if error is not None: with pytest.raises(error): @@ -1410,7 +1414,7 @@ def test_unary_operations(self, func, dtype): lambda x: x.T @ x, id="matrix multiply", marks=pytest.mark.xfail( - reason="pint does not support matrix multiplication yet" + reason="pint does not implement `np.einsum` yet" ), ), ), @@ -1736,14 +1740,12 @@ def test_dropna(self, dtype): x = np.arange(len(array)) data_array = xr.DataArray(data=array, coords={"x": x}, dims=["x"]) - expected = attach_units( - strip_units(data_array).dropna(dim="x"), {"data": unit_registry.m} - ) + units = extract_units(data_array) + expected = attach_units(strip_units(data_array).dropna(dim="x"), units) result = data_array.dropna(dim="x") assert_equal_with_units(expected, result) - @pytest.mark.xfail(reason="pint does not implement `numpy.isin`") @pytest.mark.parametrize( "unit", ( @@ -1779,16 +1781,8 @@ def test_isin(self, unit, dtype): "masking", marks=pytest.mark.xfail(reason="nan not compatible with quantity"), ), - pytest.param( - "replacing_scalar", - marks=pytest.mark.xfail(reason="scalar not convertible using astype"), - ), - pytest.param( - "replacing_array", - marks=pytest.mark.xfail( - reason="replacing using an array drops the units" - ), - ), + pytest.param("replacing_scalar"), + pytest.param("replacing_array"), pytest.param( "dropping", marks=pytest.mark.xfail(reason="nan not compatible with quantity"), @@ -1841,7 +1835,6 @@ def test_where(self, variant, unit, error, dtype): strip_units(data_array).where(**kwargs_without_units), extract_units(data_array), ) - print("expected:", expected, sep="\n") result = data_array.where(**kwargs) assert_equal_with_units(expected, result) @@ -1855,14 +1848,12 @@ def test_interpolate_na(self, dtype): x = np.arange(len(array)) data_array = xr.DataArray(data=array, coords={"x": x}, dims="x").astype(dtype) - expected = attach_units( - strip_units(data_array).interpolate_na(dim="x"), {"data": unit_registry.m} - ) + units = extract_units(data_array) + expected = attach_units(strip_units(data_array).interpolate_na(dim="x"), units) result = data_array.interpolate_na(dim="x") assert_equal_with_units(expected, result) - @pytest.mark.xfail(reason="uses DataArray.where, which currently fails") @pytest.mark.parametrize( "unit,error", ( @@ -1871,8 +1862,18 @@ def test_interpolate_na(self, dtype): unit_registry.dimensionless, DimensionalityError, id="dimensionless" ), pytest.param(unit_registry.s, DimensionalityError, id="incompatible_unit"), - pytest.param(unit_registry.cm, None, id="compatible_unit"), - pytest.param(unit_registry.m, None, id="identical_unit"), + pytest.param( + unit_registry.cm, + None, + id="compatible_unit", + marks=pytest.mark.xfail(reason="depends on reindex"), + ), + pytest.param( + unit_registry.m, + None, + id="identical_unit", + marks=pytest.mark.xfail(reason="depends on reindex"), + ), ), ) def test_combine_first(self, unit, error, dtype): @@ -1889,14 +1890,19 @@ def test_combine_first(self, unit, error, dtype): if error is not None: with pytest.raises(error): data_array.combine_first(other) - else: - expected = attach_units( - strip_units(data_array).combine_first(strip_units(other)), - {"data": unit_registry.m}, - ) - result = data_array.combine_first(other) - assert_equal_with_units(expected, result) + return + + units = extract_units(data_array) + expected = attach_units( + strip_units(data_array).combine_first( + strip_units(convert_units(other, units)) + ), + units, + ) + result = data_array.combine_first(other) + + assert_equal_with_units(expected, result) @pytest.mark.parametrize( "unit", @@ -1904,11 +1910,7 @@ def test_combine_first(self, unit, error, dtype): pytest.param(1, id="no_unit"), pytest.param(unit_registry.dimensionless, id="dimensionless"), pytest.param(unit_registry.s, id="incompatible_unit"), - pytest.param( - unit_registry.cm, - id="compatible_unit", - marks=pytest.mark.xfail(reason="identical does not check units yet"), - ), + pytest.param(unit_registry.cm, id="compatible_unit"), pytest.param(unit_registry.m, id="identical_unit"), ), ) @@ -1924,48 +1926,47 @@ def test_combine_first(self, unit, error, dtype): ) @pytest.mark.parametrize("func", (method("equals"), method("identical")), ids=repr) def test_comparisons(self, func, variation, unit, dtype): + def is_compatible(a, b): + a = a if a is not None else 1 + b = b if b is not None else 1 + quantity = np.arange(5) * a + + return a == b or quantity.check(b) + data = np.linspace(0, 5, 10).astype(dtype) coord = np.arange(len(data)).astype(dtype) base_unit = unit_registry.m - quantity = data * base_unit - x = coord * base_unit - y = coord * base_unit - - units = { - "data": (unit, base_unit, base_unit), - "dims": (base_unit, unit, base_unit), - "coords": (base_unit, base_unit, unit), + array = data * (base_unit if variation == "data" else 1) + x = coord * (base_unit if variation == "dims" else 1) + y = coord * (base_unit if variation == "coords" else 1) + + variations = { + "data": (unit, 1, 1), + "dims": (1, unit, 1), + "coords": (1, 1, unit), } - data_unit, dim_unit, coord_unit = units.get(variation) + data_unit, dim_unit, coord_unit = variations.get(variation) - data_array = xr.DataArray( - data=quantity, coords={"x": x, "y": ("x", y)}, dims="x" - ) + data_array = xr.DataArray(data=array, coords={"x": x, "y": ("x", y)}, dims="x") other = attach_units( - strip_units(data_array), - { - None: (data_unit, base_unit if quantity.check(data_unit) else None), - "x": (dim_unit, base_unit if x.check(dim_unit) else None), - "y": (coord_unit, base_unit if y.check(coord_unit) else None), - }, + strip_units(data_array), {None: data_unit, "x": dim_unit, "y": coord_unit} ) - # TODO: test dim coord once indexes leave units intact - # also, express this in terms of calls on the raw data array - # and then check the units - equal_arrays = ( - np.all(quantity == other.data) - and (np.all(x == other.x.data) or True) # dims can't be checked yet - and np.all(y == other.y.data) - ) - equal_units = ( - data_unit == unit_registry.m - and coord_unit == unit_registry.m - and dim_unit == unit_registry.m + units = extract_units(data_array) + other_units = extract_units(other) + + equal_arrays = all( + is_compatible(units[name], other_units[name]) for name in units.keys() + ) and ( + strip_units(data_array).equals( + strip_units(convert_units(other, extract_units(data_array))) + ) ) + equal_units = units == other_units expected = equal_arrays and (func.name != "identical" or equal_units) + result = func(data_array, other) assert expected == result @@ -2042,14 +2043,8 @@ def test_broadcast_equals(self, unit, dtype): method("drop_vars", "x"), method("reset_coords", names="x2"), method("copy"), - pytest.param( - method("astype", np.float32), - marks=pytest.mark.xfail(reason="not provided by `pint` yet"), - ), - pytest.param( - method("item", 1), - marks=pytest.mark.xfail(reason="not provided by `pint` yet"), - ), + method("astype", np.float32), + method("item", 1), ), ids=repr, ) @@ -2072,16 +2067,9 @@ def test_content_manipulation(self, func, dtype): stripped_kwargs = { key: array_strip_units(value) for key, value in func.kwargs.items() } - expected = attach_units( - func(strip_units(data_array), **stripped_kwargs), - { - "data": quantity.units, - "x": x.units, - "x_mm": x2.units, - "x2": x2.units, - "y": y.units, - }, - ) + units = {**{"x_mm": x2.units, "x2": x2.units}, **extract_units(data_array)} + + expected = attach_units(func(strip_units(data_array), **stripped_kwargs), units) result = func(data_array) assert_equal_with_units(expected, result) @@ -2148,8 +2136,7 @@ def test_isel(self, indices, dtype): data_array = xr.DataArray(data=array, coords={"x": x}, dims=["x"]) expected = attach_units( - strip_units(data_array).isel(x=indices), - {"data": unit_registry.s, "x": unit_registry.m}, + strip_units(data_array).isel(x=indices), extract_units(data_array) ) result = data_array.isel(x=indices) @@ -2161,34 +2148,43 @@ def test_isel(self, indices, dtype): @pytest.mark.parametrize( "values", ( - pytest.param(12, id="single value"), - pytest.param([10, 5, 13], id="list of multiple values"), - pytest.param(np.array([9, 3, 7, 12]), id="array of multiple values"), + pytest.param(12, id="single_value"), + pytest.param([10, 5, 13], id="list_of_values"), + pytest.param(np.array([9, 3, 7, 12]), id="array_of_values"), ), ) @pytest.mark.parametrize( - "units,error", + "unit,error", ( - pytest.param(1, KeyError, id="no units"), + pytest.param(1, KeyError, id="no_units"), pytest.param(unit_registry.dimensionless, KeyError, id="dimensionless"), - pytest.param(unit_registry.degree, KeyError, id="incorrect unit"), - pytest.param(unit_registry.s, None, id="correct unit"), + pytest.param(unit_registry.degree, KeyError, id="incompatible_unit"), + pytest.param(unit_registry.dm, None, id="compatible_unit"), + pytest.param(unit_registry.m, None, id="identical_unit"), ), ) - def test_sel(self, values, units, error, dtype): + def test_sel(self, values, unit, error, dtype): array = np.linspace(5, 10, 20).astype(dtype) * unit_registry.m - x = np.arange(len(array)) * unit_registry.s + x = np.arange(len(array)) * unit_registry.m data_array = xr.DataArray(data=array, coords={"x": x}, dims=["x"]) - values_with_units = values * units + values_with_units = values * unit if error is not None: with pytest.raises(error): data_array.sel(x=values_with_units) - else: - result_array = array[values] - result_data_array = data_array.sel(x=values_with_units) - assert_equal_with_units(result_array, result_data_array) + + return + + units = extract_units(data_array) + expected = attach_units( + strip_units(data_array).sel( + x=strip_units(convert_units(values_with_units, units)) + ), + units, + ) + result = data_array.sel(x=values_with_units) + assert_equal_with_units(expected, result) @pytest.mark.xfail( reason="xarray does not support duck arrays in dimension coordinates" @@ -2202,7 +2198,7 @@ def test_sel(self, values, units, error, dtype): ), ) @pytest.mark.parametrize( - "units,error", + "unit,error", ( pytest.param(1, KeyError, id="no units"), pytest.param(unit_registry.dimensionless, KeyError, id="dimensionless"), @@ -2210,20 +2206,28 @@ def test_sel(self, values, units, error, dtype): pytest.param(unit_registry.s, None, id="correct unit"), ), ) - def test_loc(self, values, units, error, dtype): + def test_loc(self, values, unit, error, dtype): array = np.linspace(5, 10, 20).astype(dtype) * unit_registry.m x = np.arange(len(array)) * unit_registry.s data_array = xr.DataArray(data=array, coords={"x": x}, dims=["x"]) - values_with_units = values * units + values_with_units = values * unit if error is not None: with pytest.raises(error): data_array.loc[values_with_units] - else: - result_array = array[values] - result_data_array = data_array.loc[values_with_units] - assert_equal_with_units(result_array, result_data_array) + + return + + units = extract_units(data_array) + expected = attach_units( + strip_units(data_array).sel( + x=strip_units(convert_units(values_with_units, units)) + ), + units, + ) + result = data_array.sel(x=values_with_units) + assert_equal_with_units(expected, result) @pytest.mark.xfail(reason="tries to coerce using asarray") @pytest.mark.parametrize( @@ -2302,12 +2306,15 @@ def test_head_tail_thin(self, func, unit, error, dtype): assert_equal_with_units(expected, result) + @pytest.mark.xfail(reason="indexes don't support units") @pytest.mark.parametrize( "unit,error", ( - pytest.param(1, None, id="no_unit"), - pytest.param(unit_registry.dimensionless, None, id="dimensionless"), - pytest.param(unit_registry.s, None, id="incompatible_unit"), + pytest.param(1, DimensionalityError, id="no_unit"), + pytest.param( + unit_registry.dimensionless, DimensionalityError, id="dimensionless" + ), + pytest.param(unit_registry.s, DimensionalityError, id="incompatible_unit"), pytest.param(unit_registry.cm, None, id="compatible_unit"), pytest.param(unit_registry.m, None, id="identical_unit"), ), @@ -2325,24 +2332,29 @@ def test_interp(self, unit, error): if error is not None: with pytest.raises(error): data_array.interp(x=new_coords) - else: - new_coords_ = ( - new_coords.magnitude if hasattr(new_coords, "magnitude") else new_coords - ) - result_array = strip_units(data_array).interp( - x=new_coords_ * unit_registry.degK - ) - result_data_array = data_array.interp(x=new_coords) - assert_equal_with_units(result_array, result_data_array) + return - @pytest.mark.xfail(reason="tries to coerce using asarray") + units = extract_units(data_array) + expected = attach_units( + strip_units(data_array).interp( + x=strip_units(convert_units(new_coords, {None: unit_registry.m})) + ), + units, + ) + result = data_array.interp(x=new_coords) + + assert_equal_with_units(expected, result) + + @pytest.mark.xfail(reason="indexes strip units") @pytest.mark.parametrize( "unit,error", ( - pytest.param(1, None, id="no_unit"), - pytest.param(unit_registry.dimensionless, None, id="dimensionless"), - pytest.param(unit_registry.s, None, id="incompatible_unit"), + pytest.param(1, DimensionalityError, id="no_unit"), + pytest.param( + unit_registry.dimensionless, DimensionalityError, id="dimensionless" + ), + pytest.param(unit_registry.s, DimensionalityError, id="incompatible_unit"), pytest.param(unit_registry.cm, None, id="compatible_unit"), pytest.param(unit_registry.m, None, id="identical_unit"), ), @@ -2355,28 +2367,30 @@ def test_interp_like(self, unit, error): } data_array = xr.DataArray(array, coords=coords, dims=("x", "y")) - new_data_array = xr.DataArray( - data=np.empty((20, 10)), + other = xr.DataArray( + data=np.empty((20, 10)) * unit_registry.degK, coords={"x": np.arange(20) * unit, "y": np.arange(10) * unit}, dims=("x", "y"), ) if error is not None: with pytest.raises(error): - data_array.interp_like(new_data_array) - else: - result_array = ( - xr.DataArray( - data=array.magnitude, - coords={name: value.magnitude for name, value in coords.items()}, - dims=("x", "y"), - ).interp_like(strip_units(new_data_array)) - * unit_registry.degK - ) - result_data_array = data_array.interp_like(new_data_array) + data_array.interp_like(other) - assert_equal_with_units(result_array, result_data_array) + return + units = extract_units(data_array) + expected = attach_units( + strip_units(data_array).interp_like( + strip_units(convert_units(other, units)) + ), + units, + ) + result = data_array.interp_like(other) + + assert_equal_with_units(expected, result) + + @pytest.mark.xfail(reason="indexes don't support units") @pytest.mark.parametrize( "unit,error", ( @@ -2389,8 +2403,10 @@ def test_interp_like(self, unit, error): pytest.param(unit_registry.m, None, id="identical_unit"), ), ) - def test_reindex(self, unit, error): - array = np.linspace(1, 2, 10 * 5).reshape(10, 5) * unit_registry.degK + def test_reindex(self, unit, error, dtype): + array = ( + np.linspace(1, 2, 10 * 5).reshape(10, 5).astype(dtype) * unit_registry.degK + ) new_coords = (np.arange(10) + 0.5) * unit coords = { "x": np.arange(10) * unit_registry.m, @@ -2404,53 +2420,64 @@ def test_reindex(self, unit, error): with pytest.raises(error): func(data_array, x=new_coords) + return + expected = attach_units( - func(strip_units(data_array), x=strip_units(new_coords)), + func( + strip_units(data_array), + x=strip_units(convert_units(new_coords, {None: unit_registry.m})), + ), {None: unit_registry.degK}, ) actual = func(data_array, x=new_coords) assert_equal_with_units(expected, actual) + @pytest.mark.xfail(reason="indexes don't support units") @pytest.mark.parametrize( "unit,error", ( - pytest.param(1, None, id="no_unit"), - pytest.param(unit_registry.dimensionless, None, id="dimensionless"), - pytest.param(unit_registry.s, None, id="incompatible_unit"), + pytest.param(1, DimensionalityError, id="no_unit"), + pytest.param( + unit_registry.dimensionless, DimensionalityError, id="dimensionless" + ), + pytest.param(unit_registry.s, DimensionalityError, id="incompatible_unit"), pytest.param(unit_registry.cm, None, id="compatible_unit"), pytest.param(unit_registry.m, None, id="identical_unit"), ), ) - def test_reindex_like(self, unit, error): - array = np.linspace(1, 2, 10 * 5).reshape(10, 5) * unit_registry.degK + def test_reindex_like(self, unit, error, dtype): + array = ( + np.linspace(1, 2, 10 * 5).reshape(10, 5).astype(dtype) * unit_registry.degK + ) coords = { "x": (np.arange(10) + 0.3) * unit_registry.m, "y": (np.arange(5) + 0.3) * unit_registry.m, } data_array = xr.DataArray(array, coords=coords, dims=("x", "y")) - new_data_array = xr.DataArray( - data=np.empty((20, 10)), + other = xr.DataArray( + data=np.empty((20, 10)) * unit_registry.degK, coords={"x": np.arange(20) * unit, "y": np.arange(10) * unit}, dims=("x", "y"), ) if error is not None: with pytest.raises(error): - data_array.reindex_like(new_data_array) - else: - expected = attach_units( - strip_units(data_array).reindex_like(strip_units(new_data_array)), - { - "data": unit_registry.degK, - "x": unit_registry.m, - "y": unit_registry.m, - }, - ) - result = data_array.reindex_like(new_data_array) + data_array.reindex_like(other) - assert_equal_with_units(expected, result) + return + + units = extract_units(data_array) + expected = attach_units( + strip_units(data_array).reindex_like( + strip_units(convert_units(other, units)) + ), + units, + ) + result = data_array.reindex_like(other) + + assert_equal_with_units(expected, result) @pytest.mark.parametrize( "func", @@ -2474,7 +2501,7 @@ def test_stacking_stacked(self, func, dtype): assert_equal_with_units(expected, result) - @pytest.mark.xfail(reason="indexes strip the label units") + @pytest.mark.xfail(reason="indexes don't support units") def test_to_unstacked_dataset(self, dtype): array = ( np.linspace(0, 10, 5 * 10).reshape(5, 10).astype(dtype) @@ -2495,8 +2522,6 @@ def test_to_unstacked_dataset(self, dtype): ).rename({elem.magnitude: elem for elem in x}) result = func(data_array) - print(data_array, expected, result, sep="\n") - assert_equal_with_units(expected, result) assert False @@ -2510,10 +2535,7 @@ def test_to_unstacked_dataset(self, dtype): pytest.param( method("shift", x=2), marks=pytest.mark.xfail(reason="strips units") ), - pytest.param( - method("roll", x=2, roll_coords=False), - marks=pytest.mark.xfail(reason="strips units"), - ), + method("roll", x=2, roll_coords=False), method("sortby", "x2"), ), ids=repr, @@ -2535,9 +2557,7 @@ def test_stacking_reordering(self, func, dtype): dims=("x", "y", "z"), ) - expected = attach_units( - func(strip_units(data_array)), {"data": unit_registry.m} - ) + expected = attach_units(func(strip_units(data_array)), {None: unit_registry.m}) result = func(data_array) assert_equal_with_units(expected, result) @@ -2548,16 +2568,8 @@ def test_stacking_reordering(self, func, dtype): method("diff", dim="x"), method("differentiate", coord="x"), method("integrate", dim="x"), - pytest.param( - method("quantile", q=[0.25, 0.75]), - marks=pytest.mark.xfail( - reason="pint does not implement nanpercentile yet" - ), - ), - pytest.param( - method("reduce", func=np.sum, dim="x"), - marks=pytest.mark.xfail(reason="strips units"), - ), + method("quantile", q=[0.25, 0.75]), + method("reduce", func=np.sum, dim="x"), pytest.param( lambda x: x.dot(x), id="method_dot", @@ -2585,20 +2597,16 @@ def test_computation(self, func, dtype): @pytest.mark.parametrize( "func", ( - pytest.param( - method("groupby", "y"), marks=pytest.mark.xfail(reason="strips units") - ), - pytest.param( - method("groupby_bins", "y", bins=4), - marks=pytest.mark.xfail(reason="strips units"), - ), + method("groupby", "x"), + method("groupby_bins", "y", bins=4), method("coarsen", y=2), pytest.param( - method("rolling", y=3), marks=pytest.mark.xfail(reason="strips units") + method("rolling", y=3), + marks=pytest.mark.xfail(reason="rolling strips units"), ), pytest.param( method("rolling_exp", y=3), - marks=pytest.mark.xfail(reason="strips units"), + marks=pytest.mark.xfail(reason="units not supported by numbagg"), ), ), ids=repr, @@ -2608,7 +2616,7 @@ def test_computation_objects(self, func, dtype): np.linspace(0, 10, 5 * 10).reshape(5, 10).astype(dtype) * unit_registry.m ) - x = np.arange(array.shape[0]) * unit_registry.m + x = np.array([0, 0, 1, 2, 2]) * unit_registry.m y = np.arange(array.shape[1]) * 3 * unit_registry.s data_array = xr.DataArray(data=array, coords={"x": x, "y": y}, dims=("x", "y")) @@ -2619,7 +2627,7 @@ def test_computation_objects(self, func, dtype): assert_equal_with_units(expected, result) - @pytest.mark.xfail(reason="strips units") + @pytest.mark.xfail(reason="resample strips units") def test_resample(self, dtype): array = np.linspace(0, 5, 10).astype(dtype) * unit_registry.m @@ -2637,16 +2645,10 @@ def test_resample(self, dtype): @pytest.mark.parametrize( "func", ( - pytest.param( - method("assign_coords", {"z": (["x"], np.arange(5) * unit_registry.s)}), - marks=pytest.mark.xfail(reason="strips units"), - ), - pytest.param(method("first")), - pytest.param(method("last")), - pytest.param( - method("quantile", q=[0.25, 0.5, 0.75], dim="x"), - marks=pytest.mark.xfail(reason="strips units"), - ), + method("assign_coords", {"z": (["x"], np.arange(5) * unit_registry.s)}), + method("first"), + method("last"), + method("quantile", q=[0.25, 0.5, 0.75], dim="x"), ), ids=repr, ) From 916abce80ca6f577d1f0f7c9cb9142c7e37872ec Mon Sep 17 00:00:00 2001 From: Keewis Date: Sat, 7 Dec 2019 02:14:50 +0100 Subject: [PATCH 17/32] remove a debug assert --- xarray/tests/test_units.py | 2 -- 1 file changed, 2 deletions(-) diff --git a/xarray/tests/test_units.py b/xarray/tests/test_units.py index c30f5333e74..98d21e9fab3 100644 --- a/xarray/tests/test_units.py +++ b/xarray/tests/test_units.py @@ -2524,8 +2524,6 @@ def test_to_unstacked_dataset(self, dtype): assert_equal_with_units(expected, result) - assert False - @pytest.mark.parametrize( "func", ( From 3a34d57b8b65de567785148d76b58ce0a6a90a1c Mon Sep 17 00:00:00 2001 From: Keewis Date: Sat, 7 Dec 2019 14:19:57 +0100 Subject: [PATCH 18/32] fix the broadcast_equals tests --- xarray/tests/test_units.py | 44 ++++++++++++++++++-------------------- 1 file changed, 21 insertions(+), 23 deletions(-) diff --git a/xarray/tests/test_units.py b/xarray/tests/test_units.py index 98d21e9fab3..3dea74ec607 100644 --- a/xarray/tests/test_units.py +++ b/xarray/tests/test_units.py @@ -218,7 +218,7 @@ def convert_units(obj, to): name = obj.name new_units = ( - to.get(name, None) or to.get("data", None) or to.get(None, None) or 1 + to.get(name, None) or to.get("data", None) or to.get(None, None) or None ) data = convert_units(obj.variable, {None: new_units}) @@ -2013,16 +2013,18 @@ def test_broadcast_like(self, unit, dtype): ) def test_broadcast_equals(self, unit, dtype): left_array = np.ones(shape=(2, 2), dtype=dtype) * unit_registry.m - right_array = array_attach_units( - np.ones(shape=(2,), dtype=dtype), - unit, - convert_from=unit_registry.m if left_array.check(unit) else None, - ) + right_array = np.ones(shape=(2,), dtype=dtype) * unit left = xr.DataArray(data=left_array, dims=("x", "y")) right = xr.DataArray(data=right_array, dims="x") - expected = np.all(left_array == right_array[:, None]) + units = { + **extract_units(left), + **({} if left_array.check(unit) else {None: None}), + } + expected = strip_units(left).broadcast_equals( + strip_units(convert_units(right, units)) + ) & left_array.check(unit) result = left.broadcast_equals(right) assert expected == result @@ -3488,35 +3490,31 @@ def test_broadcast_like(self, unit, dtype): ) def test_broadcast_equals(self, unit, dtype): left_array1 = np.ones(shape=(2, 3), dtype=dtype) * unit_registry.m - left_array2 = np.zeros(shape=(2, 6), dtype=dtype) * unit_registry.m + left_array2 = np.zeros(shape=(3, 6), dtype=dtype) * unit_registry.m - right_array1 = array_attach_units( - np.ones(shape=(2,), dtype=dtype), - unit, - convert_from=unit_registry.m if left_array1.check(unit) else None, - ) - right_array2 = array_attach_units( - np.ones(shape=(2,), dtype=dtype), - unit, - convert_from=unit_registry.m if left_array2.check(unit) else None, - ) + right_array1 = np.ones(shape=(2,)) * unit + right_array2 = np.ones(shape=(3,)) * unit left = xr.Dataset( data_vars={ "a": xr.DataArray(data=left_array1, dims=("x", "y")), - "b": xr.DataArray(data=left_array2, dims=("x", "z")), + "b": xr.DataArray(data=left_array2, dims=("y", "z")), } ) right = xr.Dataset( data_vars={ "a": xr.DataArray(data=right_array1, dims="x"), - "b": xr.DataArray(data=right_array2, dims="x"), + "b": xr.DataArray(data=right_array2, dims="y"), } ) - expected = np.all(left_array1 == right_array1[:, None]) and np.all( - left_array2 == right_array2[:, None] - ) + units = { + **extract_units(left), + **({} if left_array1.check(unit) else {"a": None, "b": None}), + } + expected = strip_units(left).broadcast_equals( + strip_units(convert_units(right, units)) + ) & left_array1.check(unit) result = left.broadcast_equals(right) assert expected == result From f64ce941776fdee21b3376cad8846391862423f9 Mon Sep 17 00:00:00 2001 From: Keewis Date: Sat, 7 Dec 2019 23:13:55 +0100 Subject: [PATCH 19/32] update the indexing tests --- xarray/tests/test_units.py | 73 +++++++++++++++++++------------------- 1 file changed, 36 insertions(+), 37 deletions(-) diff --git a/xarray/tests/test_units.py b/xarray/tests/test_units.py index 3dea74ec607..3530d99a592 100644 --- a/xarray/tests/test_units.py +++ b/xarray/tests/test_units.py @@ -2135,7 +2135,7 @@ def test_isel(self, indices, dtype): array = np.arange(10).astype(dtype) * unit_registry.s x = np.arange(len(array)) * unit_registry.m - data_array = xr.DataArray(data=array, coords={"x": x}, dims=["x"]) + data_array = xr.DataArray(data=array, coords={"x": x}, dims="x") expected = attach_units( strip_units(data_array).isel(x=indices), extract_units(data_array) @@ -2144,13 +2144,11 @@ def test_isel(self, indices, dtype): assert_equal_with_units(expected, result) - @pytest.mark.xfail( - reason="xarray does not support duck arrays in dimension coordinates" - ) + @pytest.mark.xfail(reason="indexes don't support units") @pytest.mark.parametrize( - "values", + "raw_values", ( - pytest.param(12, id="single_value"), + pytest.param(10, id="single_value"), pytest.param([10, 5, 13], id="list_of_values"), pytest.param(np.array([9, 3, 7, 12]), id="array_of_values"), ), @@ -2161,74 +2159,75 @@ def test_isel(self, indices, dtype): pytest.param(1, KeyError, id="no_units"), pytest.param(unit_registry.dimensionless, KeyError, id="dimensionless"), pytest.param(unit_registry.degree, KeyError, id="incompatible_unit"), - pytest.param(unit_registry.dm, None, id="compatible_unit"), + pytest.param(unit_registry.dm, KeyError, id="compatible_unit"), pytest.param(unit_registry.m, None, id="identical_unit"), ), ) - def test_sel(self, values, unit, error, dtype): + def test_sel(self, raw_values, unit, error, dtype): array = np.linspace(5, 10, 20).astype(dtype) * unit_registry.m x = np.arange(len(array)) * unit_registry.m - data_array = xr.DataArray(data=array, coords={"x": x}, dims=["x"]) + data_array = xr.DataArray(data=array, coords={"x": x}, dims="x") - values_with_units = values * unit + values = raw_values * unit - if error is not None: + if error is not None and not ( + isinstance(raw_values, (int, float)) and array.check(unit) + ): with pytest.raises(error): - data_array.sel(x=values_with_units) + data_array.sel(x=values) return - units = extract_units(data_array) expected = attach_units( strip_units(data_array).sel( - x=strip_units(convert_units(values_with_units, units)) + x=strip_units(convert_units(values, {None: array.units})) ), - units, + extract_units(data_array), ) - result = data_array.sel(x=values_with_units) + result = data_array.sel(x=values) assert_equal_with_units(expected, result) - @pytest.mark.xfail( - reason="xarray does not support duck arrays in dimension coordinates" - ) + @pytest.mark.xfail(reason="indexes don't support units") @pytest.mark.parametrize( - "values", + "raw_values", ( - pytest.param(12, id="single value"), - pytest.param([10, 5, 13], id="list of multiple values"), - pytest.param(np.array([9, 3, 7, 12]), id="array of multiple values"), + pytest.param(10, id="single_value"), + pytest.param([10, 5, 13], id="list_of_values"), + pytest.param(np.array([9, 3, 7, 12]), id="array_of_values"), ), ) @pytest.mark.parametrize( "unit,error", ( - pytest.param(1, KeyError, id="no units"), + pytest.param(1, KeyError, id="no_units"), pytest.param(unit_registry.dimensionless, KeyError, id="dimensionless"), - pytest.param(unit_registry.degree, KeyError, id="incorrect unit"), - pytest.param(unit_registry.s, None, id="correct unit"), + pytest.param(unit_registry.degree, KeyError, id="incompatible_unit"), + pytest.param(unit_registry.dm, KeyError, id="compatible_unit"), + pytest.param(unit_registry.m, None, id="identical_unit"), ), ) - def test_loc(self, values, unit, error, dtype): + def test_loc(self, raw_values, unit, error, dtype): array = np.linspace(5, 10, 20).astype(dtype) * unit_registry.m x = np.arange(len(array)) * unit_registry.s - data_array = xr.DataArray(data=array, coords={"x": x}, dims=["x"]) + data_array = xr.DataArray(data=array, coords={"x": x}, dims="x") - values_with_units = values * unit + values = raw_values * unit - if error is not None: + if error is not None and not ( + isinstance(raw_values, (int, float)) and array.check(unit) + ): with pytest.raises(error): - data_array.loc[values_with_units] + data_array.loc[values] return - units = extract_units(data_array) expected = attach_units( - strip_units(data_array).sel( - x=strip_units(convert_units(values_with_units, units)) - ), - units, + strip_units(data_array).loc[ + strip_units(convert_units(values, {None: array.units})) + ], + extract_units(data_array), ) - result = data_array.sel(x=values_with_units) + result = data_array.loc[values] assert_equal_with_units(expected, result) @pytest.mark.xfail(reason="tries to coerce using asarray") From 19fe5402abae5dda273e1dce1a506da7bf2b4c01 Mon Sep 17 00:00:00 2001 From: Keewis Date: Sat, 7 Dec 2019 23:30:41 +0100 Subject: [PATCH 20/32] update the tests depending on einsum --- xarray/tests/test_units.py | 16 ++-------------- 1 file changed, 2 insertions(+), 14 deletions(-) diff --git a/xarray/tests/test_units.py b/xarray/tests/test_units.py index 3530d99a592..cad2ef9671b 100644 --- a/xarray/tests/test_units.py +++ b/xarray/tests/test_units.py @@ -1213,7 +1213,6 @@ def test_where_dataset(fill_value, unit, error, dtype): assert_equal_with_units(expected, result) -@pytest.mark.xfail(reason="pint does not implement `np.einsum`") def test_dot_dataarray(dtype): array1 = ( np.linspace(0, 10, 5 * 10).reshape(5, 10).astype(dtype) @@ -1410,13 +1409,7 @@ def test_unary_operations(self, func, dtype): pytest.param(lambda x: 2 * x, id="multiply"), pytest.param(lambda x: x + x, id="add"), pytest.param(lambda x: x[0] + x, id="add scalar"), - pytest.param( - lambda x: x.T @ x, - id="matrix multiply", - marks=pytest.mark.xfail( - reason="pint does not implement `np.einsum` yet" - ), - ), + pytest.param(lambda x: x.T @ x, id="matrix multiply"), ), ) def test_binary_operations(self, func, dtype): @@ -2569,11 +2562,7 @@ def test_stacking_reordering(self, func, dtype): method("integrate", dim="x"), method("quantile", q=[0.25, 0.75]), method("reduce", func=np.sum, dim="x"), - pytest.param( - lambda x: x.dot(x), - id="method_dot", - marks=pytest.mark.xfail(reason="pint does not implement einsum"), - ), + pytest.param(lambda x: x.dot(x), id="method_dot"), ), ids=repr, ) @@ -3157,7 +3146,6 @@ def test_dropna(self, dtype): assert_equal_with_units(expected, result) - @pytest.mark.xfail(reason="pint does not implement `numpy.isin`") @pytest.mark.parametrize( "unit", ( From 7b1908931eefd0674fe72f2528d16176d7150198 Mon Sep 17 00:00:00 2001 From: Keewis Date: Sat, 7 Dec 2019 23:34:30 +0100 Subject: [PATCH 21/32] update the squeeze tests --- xarray/tests/test_units.py | 25 ++++++++++++++----------- 1 file changed, 14 insertions(+), 11 deletions(-) diff --git a/xarray/tests/test_units.py b/xarray/tests/test_units.py index cad2ef9671b..beb0c2f791b 100644 --- a/xarray/tests/test_units.py +++ b/xarray/tests/test_units.py @@ -2223,15 +2223,14 @@ def test_loc(self, raw_values, unit, error, dtype): result = data_array.loc[values] assert_equal_with_units(expected, result) - @pytest.mark.xfail(reason="tries to coerce using asarray") @pytest.mark.parametrize( "shape", ( - pytest.param((10, 20), id="nothing squeezable"), - pytest.param((10, 20, 1), id="last dimension squeezable"), - pytest.param((10, 1, 20), id="middle dimension squeezable"), - pytest.param((1, 10, 20), id="first dimension squeezable"), - pytest.param((1, 10, 1, 20), id="first and last dimension squeezable"), + pytest.param((10, 20), id="nothing_squeezable"), + pytest.param((10, 20, 1), id="last_dimension_squeezable"), + pytest.param((10, 1, 20), id="middle_dimension_squeezable"), + pytest.param((1, 10, 20), id="first_dimension_squeezable"), + pytest.param((1, 10, 1, 20), id="first_and_last_dimension_squeezable"), ), ) def test_squeeze(self, shape, dtype): @@ -2246,16 +2245,20 @@ def test_squeeze(self, shape, dtype): data=array, coords=coords, dims=tuple(names[: len(shape)]) ) - result_array = array.squeeze() - result_data_array = data_array.squeeze() - assert_equal_with_units(result_array, result_data_array) + expected = attach_units( + strip_units(data_array).squeeze(), extract_units(data_array) + ) + result = data_array.squeeze() + assert_equal_with_units(expected, result) # try squeezing the dimensions separately names = tuple(dim for dim, coord in coords.items() if len(coord) == 1) for index, name in enumerate(names): - assert_equal_with_units( - np.squeeze(array, axis=index), data_array.squeeze(dim=name) + expected = attach_units( + strip_units(data_array).squeeze(dim=name), extract_units(data_array) ) + result = data_array.squeeze(dim=name) + assert_equal_with_units(expected, result) @pytest.mark.xfail( reason="indexes strip units and head / tail / thin only support integers" From 25038258cd8c43177d0538f1ed03c82fa002f384 Mon Sep 17 00:00:00 2001 From: Keewis Date: Sat, 7 Dec 2019 23:41:38 +0100 Subject: [PATCH 22/32] fix a bug in the head / tail / thin test design --- xarray/tests/test_units.py | 60 +++++--------------------------------- 1 file changed, 8 insertions(+), 52 deletions(-) diff --git a/xarray/tests/test_units.py b/xarray/tests/test_units.py index beb0c2f791b..127c4dcd408 100644 --- a/xarray/tests/test_units.py +++ b/xarray/tests/test_units.py @@ -2260,27 +2260,12 @@ def test_squeeze(self, shape, dtype): result = data_array.squeeze(dim=name) assert_equal_with_units(expected, result) - @pytest.mark.xfail( - reason="indexes strip units and head / tail / thin only support integers" - ) - @pytest.mark.parametrize( - "unit,error", - ( - pytest.param(1, DimensionalityError, id="no_unit"), - pytest.param( - unit_registry.dimensionless, DimensionalityError, id="dimensionless" - ), - pytest.param(unit_registry.s, DimensionalityError, id="incompatible_unit"), - pytest.param(unit_registry.cm, None, id="compatible_unit"), - pytest.param(unit_registry.m, None, id="identical_unit"), - ), - ) @pytest.mark.parametrize( "func", (method("head", x=7, y=3), method("tail", x=7, y=3), method("thin", x=7, y=3)), ids=repr, ) - def test_head_tail_thin(self, func, unit, error, dtype): + def test_head_tail_thin(self, func, dtype): array = np.linspace(1, 2, 10 * 5).reshape(10, 5) * unit_registry.degK coords = { @@ -2288,18 +2273,12 @@ def test_head_tail_thin(self, func, unit, error, dtype): "y": np.arange(5) * unit_registry.m, } - arr = xr.DataArray(data=array, coords=coords, dims=("x", "y")) - - kwargs = {name: value * unit for name, value in func.kwargs.items()} - - if error is not None: - with pytest.raises(error): - func(arr, **kwargs) + data_array = xr.DataArray(data=array, coords=coords, dims=("x", "y")) - return - - expected = attach_units(func(strip_units(arr)), extract_units(arr)) - result = func(arr, **kwargs) + expected = attach_units( + func(strip_units(data_array)), extract_units(data_array) + ) + result = func(data_array) assert_equal_with_units(expected, result) @@ -3742,21 +3721,6 @@ def test_loc(self, values, units, error, dtype): result = ds.loc[{"x": values_with_units}] assert_equal_with_units(expected, result) - @pytest.mark.xfail( - reason="indexes strip units and head / tail / thin only support integers" - ) - @pytest.mark.parametrize( - "unit,error", - ( - pytest.param(1, DimensionalityError, id="no_unit"), - pytest.param( - unit_registry.dimensionless, DimensionalityError, id="dimensionless" - ), - pytest.param(unit_registry.s, DimensionalityError, id="incompatible_unit"), - pytest.param(unit_registry.cm, None, id="compatible_unit"), - pytest.param(unit_registry.m, None, id="identical_unit"), - ), - ) @pytest.mark.parametrize( "func", ( @@ -3766,7 +3730,7 @@ def test_loc(self, values, units, error, dtype): ), ids=repr, ) - def test_head_tail_thin(self, func, unit, error, dtype): + def test_head_tail_thin(self, func, dtype): array1 = np.linspace(1, 2, 10 * 5).reshape(10, 5) * unit_registry.degK array2 = np.linspace(1, 2, 10 * 8).reshape(10, 8) * unit_registry.Pa @@ -3784,16 +3748,8 @@ def test_head_tail_thin(self, func, unit, error, dtype): coords=coords, ) - kwargs = {name: value * unit for name, value in func.kwargs.items()} - - if error is not None: - with pytest.raises(error): - func(ds, **kwargs) - - return - expected = attach_units(func(strip_units(ds)), extract_units(ds)) - result = func(ds, **kwargs) + result = func(ds) assert_equal_with_units(expected, result) From ac5797e1c17934b2adef09fb710c8e47d6c1270c Mon Sep 17 00:00:00 2001 From: Keewis Date: Sat, 7 Dec 2019 23:43:54 +0100 Subject: [PATCH 23/32] use dictionaries to index in the loc tests --- xarray/tests/test_units.py | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/xarray/tests/test_units.py b/xarray/tests/test_units.py index 127c4dcd408..781141363bb 100644 --- a/xarray/tests/test_units.py +++ b/xarray/tests/test_units.py @@ -2210,17 +2210,17 @@ def test_loc(self, raw_values, unit, error, dtype): isinstance(raw_values, (int, float)) and array.check(unit) ): with pytest.raises(error): - data_array.loc[values] + data_array.loc[{"x": values}] return expected = attach_units( strip_units(data_array).loc[ - strip_units(convert_units(values, {None: array.units})) + {"x": strip_units(convert_units(values, {None: array.units}))} ], extract_units(data_array), ) - result = data_array.loc[values] + result = data_array.loc[{"x": values}] assert_equal_with_units(expected, result) @pytest.mark.parametrize( From ad76104c7b48265bdb8e8c2947b5b1a6ad69f92c Mon Sep 17 00:00:00 2001 From: Keewis Date: Sun, 8 Dec 2019 00:02:07 +0100 Subject: [PATCH 24/32] update the expected unit of the computation tests --- xarray/tests/test_units.py | 19 +++++++++++++++++-- 1 file changed, 17 insertions(+), 2 deletions(-) diff --git a/xarray/tests/test_units.py b/xarray/tests/test_units.py index 781141363bb..b98c3a723b8 100644 --- a/xarray/tests/test_units.py +++ b/xarray/tests/test_units.py @@ -2544,7 +2544,13 @@ def test_stacking_reordering(self, func, dtype): method("integrate", dim="x"), method("quantile", q=[0.25, 0.75]), method("reduce", func=np.sum, dim="x"), - pytest.param(lambda x: x.dot(x), id="method_dot"), + pytest.param( + lambda x: x.dot(x), + id="method_dot", + marks=pytest.mark.xfail( + reason="pint does not implement the dot method" + ), + ), ), ids=repr, ) @@ -2557,7 +2563,16 @@ def test_computation(self, func, dtype): y = np.arange(array.shape[1]) * unit_registry.s data_array = xr.DataArray(data=array, coords={"x": x, "y": y}, dims=("x", "y")) - units = extract_units(data_array) + + # we want to make sure the output unit is correct + units = { + **extract_units(data_array), + **( + {} + if isinstance(func, (function, method)) + else extract_units(func(array.reshape(-1))) + ), + } expected = attach_units(func(strip_units(data_array)), units) result = func(data_array) From 179176c711bbd1ba322563f198467524971a7d4e Mon Sep 17 00:00:00 2001 From: Keewis Date: Sun, 8 Dec 2019 00:08:15 +0100 Subject: [PATCH 25/32] update the grouped operations tests --- xarray/tests/test_units.py | 20 +++++++++++++++----- 1 file changed, 15 insertions(+), 5 deletions(-) diff --git a/xarray/tests/test_units.py b/xarray/tests/test_units.py index b98c3a723b8..0c77206b4af 100644 --- a/xarray/tests/test_units.py +++ b/xarray/tests/test_units.py @@ -2612,7 +2612,7 @@ def test_computation_objects(self, func, dtype): assert_equal_with_units(expected, result) - @pytest.mark.xfail(reason="resample strips units") + @pytest.mark.xfail(reason="blocked by `reindex` / `where`") def test_resample(self, dtype): array = np.linspace(0, 5, 10).astype(dtype) * unit_registry.m @@ -2630,10 +2630,10 @@ def test_resample(self, dtype): @pytest.mark.parametrize( "func", ( - method("assign_coords", {"z": (["x"], np.arange(5) * unit_registry.s)}), + method("assign_coords", z=(["x"], np.arange(5) * unit_registry.s)), method("first"), method("last"), - method("quantile", q=[0.25, 0.5, 0.75], dim="x"), + method("quantile", q=np.array([0.25, 0.5, 0.75]), dim="x"), ), ids=repr, ) @@ -2646,9 +2646,19 @@ def test_grouped_operations(self, func, dtype): y = np.arange(array.shape[1]) * 3 * unit_registry.s data_array = xr.DataArray(data=array, coords={"x": x, "y": y}, dims=("x", "y")) - units = extract_units(data_array) + units = {**extract_units(data_array), **{"z": unit_registry.s, "q": None}} - expected = attach_units(func(strip_units(data_array).groupby("y")), units) + stripped_kwargs = { + key: ( + strip_units(value) + if not isinstance(value, tuple) + else tuple(strip_units(elem) for elem in value) + ) + for key, value in func.kwargs.items() + } + expected = attach_units( + func(strip_units(data_array).groupby("y"), **stripped_kwargs), units + ) result = func(data_array.groupby("y")) assert_equal_with_units(expected, result) From 400df4ef0ce38cecfe38bb94f67db3b521e4d176 Mon Sep 17 00:00:00 2001 From: Keewis Date: Sun, 8 Dec 2019 00:50:58 +0100 Subject: [PATCH 26/32] update the where tests --- xarray/tests/test_units.py | 103 +++++++++++-------------------------- 1 file changed, 30 insertions(+), 73 deletions(-) diff --git a/xarray/tests/test_units.py b/xarray/tests/test_units.py index 0c77206b4af..22d896c00cc 100644 --- a/xarray/tests/test_units.py +++ b/xarray/tests/test_units.py @@ -1768,19 +1768,7 @@ def test_isin(self, unit, dtype): assert_equal_with_units(expected, result) @pytest.mark.parametrize( - "variant", - ( - pytest.param( - "masking", - marks=pytest.mark.xfail(reason="nan not compatible with quantity"), - ), - pytest.param("replacing_scalar"), - pytest.param("replacing_array"), - pytest.param( - "dropping", - marks=pytest.mark.xfail(reason="nan not compatible with quantity"), - ), - ), + "variant", ("masking", "replacing_scalar", "replacing_array", "dropping") ) @pytest.mark.parametrize( "unit,error", @@ -2958,33 +2946,22 @@ def test_numpy_methods_with_args(self, func, unit, error, dtype): ) units = extract_units(ds) - def strip(value): - return ( - value.magnitude if isinstance(value, unit_registry.Quantity) else value - ) - - def convert(value, to): - if isinstance(value, unit_registry.Quantity) and value.check(to): - return value.to(to) - - return value - - scalar_types = (int, float) kwargs = { - key: (value * unit if isinstance(value, scalar_types) else value) + key: (value * unit if isinstance(value, (int, float)) else value) for key, value in func.kwargs.items() } - stripped_kwargs = { - key: strip(convert(value, data_unit)) for key, value in kwargs.items() - } - if error is not None: with pytest.raises(error): func(ds, **kwargs) return + stripped_kwargs = { + key: strip_units(convert_units(value, {None: data_unit})) + for key, value in kwargs.items() + } + result = func(ds, **kwargs) expected = attach_units(func(strip_units(ds), **stripped_kwargs), units) @@ -3065,36 +3042,31 @@ def test_missing_value_filling(self, func, dtype): assert_equal_with_units(expected, result) - @pytest.mark.xfail(reason="fillna drops the unit") @pytest.mark.parametrize( "unit,error", ( - pytest.param( - 1, - DimensionalityError, - id="no_unit", - marks=pytest.mark.xfail(reason="blocked by the failing `where`"), - ), + pytest.param(1, DimensionalityError, id="no_unit"), pytest.param( unit_registry.dimensionless, DimensionalityError, id="dimensionless" ), pytest.param(unit_registry.s, DimensionalityError, id="incompatible_unit"), - pytest.param(unit_registry.cm, None, id="compatible_unit"), + pytest.param( + unit_registry.cm, + None, + id="compatible_unit", + marks=pytest.mark.xfail( + reason="where converts the array, not the fill value" + ), + ), pytest.param(unit_registry.m, None, id="identical_unit"), ), ) @pytest.mark.parametrize( "fill_value", ( - pytest.param( - -1, - id="python scalar", - marks=pytest.mark.xfail( - reason="python scalar cannot be converted using astype()" - ), - ), - pytest.param(np.array(-1), id="numpy scalar"), - pytest.param(np.array([-1]), id="numpy array"), + pytest.param(-1, id="python_scalar"), + pytest.param(np.array(-1), id="numpy_scalar"), + pytest.param(np.array([-1]), id="numpy_array"), ), ) def test_fillna(self, fill_value, unit, error, dtype): @@ -3121,7 +3093,11 @@ def test_fillna(self, fill_value, unit, error, dtype): result = ds.fillna(value=fill_value * unit) expected = attach_units( - strip_units(ds).fillna(value=fill_value), + strip_units(ds).fillna( + value=strip_units( + convert_units(fill_value * unit, {None: unit_registry.m}) + ) + ), {"a": unit_registry.m, "b": unit_registry.m}, ) @@ -3202,26 +3178,7 @@ def test_isin(self, unit, dtype): assert_equal_with_units(result, expected) @pytest.mark.parametrize( - "variant", - ( - "masking", - pytest.param( - "replacing_scalar", - marks=pytest.mark.xfail( - reason="python scalar not convertible using astype" - ), - ), - pytest.param( - "replacing_array", - marks=pytest.mark.xfail( - reason="replacing using an array drops the units" - ), - ), - pytest.param( - "dropping", - marks=pytest.mark.xfail(reason="nan not compatible with quantity"), - ), - ), + "variant", ("masking", "replacing_scalar", "replacing_array", "dropping") ) @pytest.mark.parametrize( "unit,error", @@ -3236,9 +3193,6 @@ def test_isin(self, unit, dtype): ), ) def test_where(self, variant, unit, error, dtype): - def _strip_units(mapping): - return {key: array_strip_units(value) for key, value in mapping.items()} - original_unit = unit_registry.m array1 = np.linspace(0, 1, 10).astype(dtype) * original_unit array2 = np.linspace(-1, 0, 10).astype(dtype) * original_unit @@ -3260,14 +3214,17 @@ def _strip_units(mapping): "dropping": {"cond": condition, "drop": True}, } kwargs = variant_kwargs.get(variant) - kwargs_without_units = _strip_units(kwargs) - if variant not in ("masking", "dropping") and error is not None: with pytest.raises(error): ds.where(**kwargs) return + kwargs_without_units = { + key: strip_units(convert_units(value, {None: original_unit})) + for key, value in kwargs.items() + } + expected = attach_units( strip_units(ds).where(**kwargs_without_units), {"a": original_unit, "b": original_unit}, From 4702ac77f627847e6c88508a40d3e9ed016c4eed Mon Sep 17 00:00:00 2001 From: Keewis Date: Sun, 8 Dec 2019 01:25:05 +0100 Subject: [PATCH 27/32] update most of the remaining dataset tests --- xarray/tests/test_units.py | 172 +++++++++++++++++-------------------- 1 file changed, 78 insertions(+), 94 deletions(-) diff --git a/xarray/tests/test_units.py b/xarray/tests/test_units.py index 22d896c00cc..3993d1ec672 100644 --- a/xarray/tests/test_units.py +++ b/xarray/tests/test_units.py @@ -2152,7 +2152,7 @@ def test_sel(self, raw_values, unit, error, dtype): values = raw_values * unit if error is not None and not ( - isinstance(raw_values, (int, float)) and array.check(unit) + isinstance(raw_values, (int, float)) and x.check(unit) ): with pytest.raises(error): data_array.sel(x=values) @@ -3260,7 +3260,7 @@ def test_interpolate_na(self, dtype): assert_equal_with_units(expected, result) - @pytest.mark.xfail(reason="uses Dataset.where, which currently fails") + @pytest.mark.xfail(reason="wrong argument order for `where`") @pytest.mark.parametrize( "unit,error", ( @@ -3276,11 +3276,11 @@ def test_interpolate_na(self, dtype): def test_combine_first(self, unit, error, dtype): array1 = ( np.array([1.4, np.nan, 2.3, np.nan, np.nan, 9.1]).astype(dtype) - * unit_registry.degK + * unit_registry.m ) array2 = ( np.array([4.3, 9.8, 7.5, np.nan, 8.2, np.nan]).astype(dtype) - * unit_registry.Pa + * unit_registry.m ) x = np.arange(len(array1)) ds = xr.Dataset( @@ -3307,7 +3307,11 @@ def test_combine_first(self, unit, error, dtype): return expected = attach_units( - strip_units(ds).combine_first(strip_units(other)), + strip_units(ds).combine_first( + strip_units( + convert_units(other, {"a": unit_registry.m, "b": unit_registry.m}) + ) + ), {"a": unit_registry.m, "b": unit_registry.m}, ) result = ds.combine_first(other) @@ -3505,7 +3509,6 @@ def test_stacking_stacked(self, func, dtype): assert_equal_with_units(expected, result) - @pytest.mark.xfail(reason="tries to subscript scalar quantities") def test_to_stacked_array(self, dtype): labels = np.arange(5).astype(dtype) * unit_registry.s arrays = {name: np.linspace(0, 1, 10) * unit_registry.m for name in labels} @@ -3534,12 +3537,10 @@ def test_to_stacked_array(self, dtype): method("stack", a=("x", "y")), method("set_index", x="x2"), pytest.param( - method("shift", x=2), marks=pytest.mark.xfail(reason="sets all to nan") - ), - pytest.param( - method("roll", x=2, roll_coords=False), - marks=pytest.mark.xfail(reason="strips units"), + method("shift", x=2), + marks=pytest.mark.xfail(reason="tries to concatenate nan arrays"), ), + method("roll", x=2, roll_coords=False), method("sortby", "x2"), ), ids=repr, @@ -3605,31 +3606,29 @@ def test_isel(self, indices, dtype): assert_equal_with_units(expected, result) - @pytest.mark.xfail( - reason="xarray does not support duck arrays in dimension coordinates" - ) + @pytest.mark.xfail(reason="indexes don't support units") @pytest.mark.parametrize( - "values", + "raw_values", ( - pytest.param(12, id="single_value"), + pytest.param(10, id="single_value"), pytest.param([10, 5, 13], id="list_of_values"), pytest.param(np.array([9, 3, 7, 12]), id="array_of_values"), ), ) @pytest.mark.parametrize( - "units,error", + "unit,error", ( pytest.param(1, KeyError, id="no_units"), pytest.param(unit_registry.dimensionless, KeyError, id="dimensionless"), pytest.param(unit_registry.degree, KeyError, id="incompatible_unit"), - pytest.param(unit_registry.ms, KeyError, id="compatible_unit"), - pytest.param(unit_registry.s, None, id="same_unit"), + pytest.param(unit_registry.dm, KeyError, id="compatible_unit"), + pytest.param(unit_registry.m, None, id="identical_unit"), ), ) - def test_sel(self, values, units, error, dtype): + def test_sel(self, raw_values, unit, error, dtype): array1 = np.linspace(5, 10, 20).astype(dtype) * unit_registry.degK array2 = np.linspace(0, 5, 20).astype(dtype) * unit_registry.Pa - x = np.arange(len(array1)) * unit_registry.s + x = np.arange(len(array1)) * unit_registry.m ds = xr.Dataset( data_vars={ @@ -3639,46 +3638,46 @@ def test_sel(self, values, units, error, dtype): coords={"x": x}, ) - values_with_units = values * units + values = raw_values * unit - if error is not None: + if error is not None and not ( + isinstance(raw_values, (int, float)) and x.check(unit) + ): with pytest.raises(error): - ds.sel(x=values_with_units) + ds.sel(x=values) return expected = attach_units( - strip_units(ds).sel(x=values), - {"a": unit_registry.degK, "b": unit_registry.Pa, "x": unit_registry.s}, + strip_units(ds).sel(x=strip_units(convert_units(values, {None: x.units}))), + {"a": array1.units, "b": array2.units, "x": x.units}, ) - result = ds.sel(x=values_with_units) + result = ds.sel(x=values) assert_equal_with_units(expected, result) - @pytest.mark.xfail( - reason="xarray does not support duck arrays in dimension coordinates" - ) + @pytest.mark.xfail(reason="indexes don't support units") @pytest.mark.parametrize( - "values", + "raw_values", ( - pytest.param(12, id="single value"), - pytest.param([10, 5, 13], id="list of multiple values"), - pytest.param(np.array([9, 3, 7, 12]), id="array of multiple values"), + pytest.param(10, id="single_value"), + pytest.param([10, 5, 13], id="list_of_values"), + pytest.param(np.array([9, 3, 7, 12]), id="array_of_values"), ), ) @pytest.mark.parametrize( - "units,error", + "unit,error", ( pytest.param(1, KeyError, id="no_units"), pytest.param(unit_registry.dimensionless, KeyError, id="dimensionless"), pytest.param(unit_registry.degree, KeyError, id="incompatible_unit"), - pytest.param(unit_registry.ms, KeyError, id="compatible_unit"), - pytest.param(unit_registry.s, None, id="same_unit"), + pytest.param(unit_registry.dm, KeyError, id="compatible_unit"), + pytest.param(unit_registry.m, None, id="identical_unit"), ), ) - def test_loc(self, values, units, error, dtype): + def test_loc(self, raw_values, unit, error, dtype): array1 = np.linspace(5, 10, 20).astype(dtype) * unit_registry.degK array2 = np.linspace(0, 5, 20).astype(dtype) * unit_registry.Pa - x = np.arange(len(array1)) * unit_registry.s + x = np.arange(len(array1)) * unit_registry.m ds = xr.Dataset( data_vars={ @@ -3688,19 +3687,23 @@ def test_loc(self, values, units, error, dtype): coords={"x": x}, ) - values_with_units = values * units + values = raw_values * unit - if error is not None: + if error is not None and not ( + isinstance(raw_values, (int, float)) and x.check(unit) + ): with pytest.raises(error): - ds.loc[{"x": values_with_units}] + ds.loc[{"x": values}] return expected = attach_units( - strip_units(ds).loc[{"x": values}], - {"a": unit_registry.degK, "b": unit_registry.Pa, "x": unit_registry.s}, + strip_units(ds).loc[ + {"x": strip_units(convert_units(values, {None: x.units}))} + ], + {"a": array1.units, "b": array2.units, "x": x.units}, ) - result = ds.loc[{"x": values_with_units}] + result = ds.loc[{"x": values}] assert_equal_with_units(expected, result) @pytest.mark.parametrize( @@ -3819,8 +3822,10 @@ def test_interp(self, unit, error): return + units = extract_units(ds) expected = attach_units( - strip_units(ds).interp(x=strip_units(new_coords)), extract_units(ds) + strip_units(ds).interp(x=strip_units(convert_units(new_coords, units))), + units, ) result = ds.interp(x=new_coords) @@ -3879,8 +3884,9 @@ def test_interp_like(self, unit, error, dtype): return + units = extract_units(ds) expected = attach_units( - strip_units(ds).interp_like(strip_units(other)), extract_units(ds) + strip_units(ds).interp_like(strip_units(convert_units(other, units))), units ) result = ds.interp_like(other) @@ -3924,8 +3930,10 @@ def test_reindex(self, unit, error): return + units = extract_units(ds) expected = attach_units( - strip_units(ds).reindex(x=strip_units(new_coords)), extract_units(ds) + strip_units(ds).reindex(x=strip_units(convert_units(new_coords, units))), + units, ) result = ds.reindex(x=new_coords) @@ -3983,8 +3991,10 @@ def test_reindex_like(self, unit, error, dtype): return + units = extract_units(ds) expected = attach_units( - strip_units(ds).reindex_like(strip_units(other)), extract_units(ds) + strip_units(ds).reindex_like(strip_units(convert_units(other, units))), + units, ) result = ds.reindex_like(other) @@ -3996,20 +4006,9 @@ def test_reindex_like(self, unit, error, dtype): method("diff", dim="x"), method("differentiate", coord="x"), method("integrate", coord="x"), - pytest.param( - method("quantile", q=[0.25, 0.75]), - marks=pytest.mark.xfail( - reason="pint does not implement nanpercentile yet" - ), - ), - pytest.param( - method("reduce", func=np.sum, dim="x"), - marks=pytest.mark.xfail(reason="strips units"), - ), - pytest.param( - method("map", np.fabs), - marks=pytest.mark.xfail(reason="fabs strips units"), - ), + method("quantile", q=[0.25, 0.75]), + method("reduce", func=np.sum, dim="x"), + method("map", np.fabs), ), ids=repr, ) @@ -4042,20 +4041,16 @@ def test_computation(self, func, dtype): @pytest.mark.parametrize( "func", ( - pytest.param( - method("groupby", "x"), marks=pytest.mark.xfail(reason="strips units") - ), - pytest.param( - method("groupby_bins", "x", bins=4), - marks=pytest.mark.xfail(reason="strips units"), - ), + method("groupby", "x"), + method("groupby_bins", "x", bins=4), method("coarsen", x=2), pytest.param( - method("rolling", x=3), marks=pytest.mark.xfail(reason="strips units") + method("rolling", x=3), + marks=pytest.mark.xfail(False, reason="strips units"), ), pytest.param( method("rolling_exp", x=3), - marks=pytest.mark.xfail(reason="strips units"), + marks=pytest.mark.xfail(reason="uses numbagg which strips units"), ), ), ids=repr, @@ -4088,7 +4083,7 @@ def test_computation_objects(self, func, dtype): assert_equal_with_units(expected, result) - @pytest.mark.xfail(reason="strips units") + @pytest.mark.xfail(reason="blocked by `reindex` / `where`") def test_resample(self, dtype): array1 = ( np.linspace(-5, 5, 10 * 5).reshape(10, 5).astype(dtype) * unit_registry.degK @@ -4119,22 +4114,11 @@ def test_resample(self, dtype): @pytest.mark.parametrize( "func", ( - pytest.param( - method("assign", c=lambda ds: 10 * ds.b), - marks=pytest.mark.xfail(reason="strips units"), - ), - pytest.param( - method("assign_coords", v=("x", np.arange(10) * unit_registry.s)), - marks=pytest.mark.xfail(reason="strips units"), - ), - pytest.param(method("first")), - pytest.param(method("last")), - pytest.param( - method("quantile", q=[0.25, 0.5, 0.75], dim="x"), - marks=pytest.mark.xfail( - reason="dataset groupby does not implement quantile" - ), - ), + method("assign", c=lambda ds: 10 * ds.b), + method("assign_coords", v=("x", np.arange(10) * unit_registry.s)), + method("first"), + method("last"), + method("quantile", q=[0.25, 0.5, 0.75], dim="x"), ), ids=repr, ) @@ -4214,16 +4198,16 @@ def test_content_manipulation(self, func, dtype): }, coords={"x": x, "y": y, "z": z, "x2": ("x", x2)}, ) - units = extract_units(ds) - units.update( - { + units = { + **extract_units(ds), + **{ "y2": unit_registry.mm, "x_mm": unit_registry.mm, "offset_x": unit_registry.m, "d": unit_registry.Pa, "temperature": unit_registry.degK, - } - ) + }, + } stripped_kwargs = { key: strip_units(value) for key, value in func.kwargs.items() From 6bbd1cf3dd2a38adda024b3953a9134864e68b32 Mon Sep 17 00:00:00 2001 From: Keewis Date: Sun, 8 Dec 2019 01:45:26 +0100 Subject: [PATCH 28/32] create new tests for drop_sel --- xarray/tests/test_units.py | 144 +++++++++++++++++++++++++++---------- 1 file changed, 108 insertions(+), 36 deletions(-) diff --git a/xarray/tests/test_units.py b/xarray/tests/test_units.py index 3993d1ec672..614c992252a 100644 --- a/xarray/tests/test_units.py +++ b/xarray/tests/test_units.py @@ -2058,52 +2058,30 @@ def test_content_manipulation(self, func, dtype): assert_equal_with_units(expected, result) @pytest.mark.parametrize( - "func", - ( - pytest.param( - method("drop_sel", labels=dict(x=np.array([1, 5]))), - marks=pytest.mark.xfail( - reason="selecting using incompatible units does not raise" - ), - ), - pytest.param(method("copy", data=np.arange(20))), - ), - ids=repr, + "func", (pytest.param(method("copy", data=np.arange(20))),), ids=repr ) @pytest.mark.parametrize( - "unit,error", + "unit", ( - pytest.param(1, DimensionalityError, id="no_unit"), - pytest.param( - unit_registry.dimensionless, DimensionalityError, id="dimensionless" - ), - pytest.param(unit_registry.s, DimensionalityError, id="incompatible_unit"), - pytest.param(unit_registry.cm, KeyError, id="compatible_unit"), - pytest.param(unit_registry.m, None, id="identical_unit"), + pytest.param(1, id="no_unit"), + pytest.param(unit_registry.dimensionless, id="dimensionless"), + pytest.param(unit_registry.degK, id="with_unit"), ), ) - def test_content_manipulation_with_units(self, func, unit, error, dtype): + def test_content_manipulation_with_units(self, func, unit, dtype): quantity = np.linspace(0, 10, 20, dtype=dtype) * unit_registry.pascal x = np.arange(len(quantity)) * unit_registry.m - data_array = xr.DataArray(name="data", data=quantity, coords={"x": x}, dims="x") + data_array = xr.DataArray(data=quantity, coords={"x": x}, dims="x") - kwargs = { - key: (value * unit if isinstance(value, np.ndarray) else value) - for key, value in func.kwargs.items() - } - stripped_kwargs = func.kwargs + kwargs = {key: value * unit for key, value in func.kwargs.items()} expected = attach_units( - func(strip_units(data_array), **stripped_kwargs), - {"data": quantity.units if func.name == "drop_sel" else unit, "x": x.units}, + func(strip_units(data_array)), {None: unit, "x": x.units} ) - if error is not None and func.name == "drop_sel": - with pytest.raises(error): - func(data_array, **kwargs) - else: - result = func(data_array, **kwargs) - assert_equal_with_units(expected, result) + + result = func(data_array, **kwargs) + assert_equal_with_units(expected, result) @pytest.mark.parametrize( "indices", @@ -2189,13 +2167,13 @@ def test_sel(self, raw_values, unit, error, dtype): ) def test_loc(self, raw_values, unit, error, dtype): array = np.linspace(5, 10, 20).astype(dtype) * unit_registry.m - x = np.arange(len(array)) * unit_registry.s + x = np.arange(len(array)) * unit_registry.m data_array = xr.DataArray(data=array, coords={"x": x}, dims="x") values = raw_values * unit if error is not None and not ( - isinstance(raw_values, (int, float)) and array.check(unit) + isinstance(raw_values, (int, float)) and x.check(unit) ): with pytest.raises(error): data_array.loc[{"x": values}] @@ -2211,6 +2189,49 @@ def test_loc(self, raw_values, unit, error, dtype): result = data_array.loc[{"x": values}] assert_equal_with_units(expected, result) + @pytest.mark.xfail(reason="indexes don't support units") + @pytest.mark.parametrize( + "raw_values", + ( + pytest.param(10, id="single_value"), + pytest.param([10, 5, 13], id="list_of_values"), + pytest.param(np.array([9, 3, 7, 12]), id="array_of_values"), + ), + ) + @pytest.mark.parametrize( + "unit,error", + ( + pytest.param(1, KeyError, id="no_units"), + pytest.param(unit_registry.dimensionless, KeyError, id="dimensionless"), + pytest.param(unit_registry.degree, KeyError, id="incompatible_unit"), + pytest.param(unit_registry.dm, KeyError, id="compatible_unit"), + pytest.param(unit_registry.m, None, id="identical_unit"), + ), + ) + def test_drop_sel(self, raw_values, unit, error, dtype): + array = np.linspace(5, 10, 20).astype(dtype) * unit_registry.m + x = np.arange(len(array)) * unit_registry.m + data_array = xr.DataArray(data=array, coords={"x": x}, dims="x") + + values = raw_values * unit + + if error is not None and not ( + isinstance(raw_values, (int, float)) and x.check(unit) + ): + with pytest.raises(error): + data_array.drop_sel(x=values) + + return + + expected = attach_units( + strip_units(data_array).drop_sel( + x=strip_units(convert_units(values, {None: x.units})) + ), + extract_units(data_array), + ) + result = data_array.drop_sel(x=values) + assert_equal_with_units(expected, result) + @pytest.mark.parametrize( "shape", ( @@ -3655,6 +3676,57 @@ def test_sel(self, raw_values, unit, error, dtype): result = ds.sel(x=values) assert_equal_with_units(expected, result) + @pytest.mark.xfail(False, reason="indexes don't support units") + @pytest.mark.parametrize( + "raw_values", + ( + pytest.param(10, id="single_value"), + pytest.param([10, 5, 13], id="list_of_values"), + pytest.param(np.array([9, 3, 7, 12]), id="array_of_values"), + ), + ) + @pytest.mark.parametrize( + "unit,error", + ( + pytest.param(1, KeyError, id="no_units"), + pytest.param(unit_registry.dimensionless, KeyError, id="dimensionless"), + pytest.param(unit_registry.degree, KeyError, id="incompatible_unit"), + pytest.param(unit_registry.dm, KeyError, id="compatible_unit"), + pytest.param(unit_registry.m, None, id="identical_unit"), + ), + ) + def test_drop_sel(self, raw_values, unit, error, dtype): + array1 = np.linspace(5, 10, 20).astype(dtype) * unit_registry.degK + array2 = np.linspace(0, 5, 20).astype(dtype) * unit_registry.Pa + x = np.arange(len(array1)) * unit_registry.m + + ds = xr.Dataset( + data_vars={ + "a": xr.DataArray(data=array1, dims="x"), + "b": xr.DataArray(data=array2, dims="x"), + }, + coords={"x": x}, + ) + + values = raw_values * unit + + if error is not None and not ( + isinstance(raw_values, (int, float)) and x.check(unit) + ): + with pytest.raises(error): + ds.drop_sel(x=values) + + return + + expected = attach_units( + strip_units(ds).drop_sel( + x=strip_units(convert_units(values, {None: x.units})) + ), + extract_units(ds), + ) + result = ds.drop_sel(x=values) + assert_equal_with_units(expected, result) + @pytest.mark.xfail(reason="indexes don't support units") @pytest.mark.parametrize( "raw_values", From 1a2de05e24378ba40af89dc5e66bfe4ac13de4b9 Mon Sep 17 00:00:00 2001 From: Keewis Date: Sun, 8 Dec 2019 01:52:15 +0100 Subject: [PATCH 29/32] final batch of updated tests --- xarray/tests/test_units.py | 218 +++++++++++++++++++++---------------- 1 file changed, 126 insertions(+), 92 deletions(-) diff --git a/xarray/tests/test_units.py b/xarray/tests/test_units.py index 614c992252a..ace76085569 100644 --- a/xarray/tests/test_units.py +++ b/xarray/tests/test_units.py @@ -380,7 +380,7 @@ def test_apply_ufunc_dataset(dtype): assert_equal_with_units(expected, result) -@pytest.mark.xfail(reason="align strips units") +@pytest.mark.xfail(reason="blocked by `reindex` / `where`") @pytest.mark.parametrize( "unit,error", ( @@ -406,11 +406,7 @@ def test_apply_ufunc_dataset(dtype): def test_align_dataarray(fill_value, variant, unit, error, dtype): original_unit = unit_registry.m - variants = { - "data": (unit, original_unit, original_unit), - "dims": (original_unit, unit, original_unit), - "coords": (original_unit, original_unit, unit), - } + variants = {"data": (unit, 1, 1), "dims": (1, unit, 1), "coords": (1, 1, unit)} data_unit, dim_unit, coord_unit = variants.get(variant) array1 = np.linspace(0, 10, 2 * 5).reshape(2, 5).astype(dtype) * original_unit @@ -438,17 +434,20 @@ def test_align_dataarray(fill_value, variant, unit, error, dtype): return stripped_kwargs = { - key: strip_units(convert_units(value, {None: original_unit})) + key: strip_units( + convert_units(value, {None: original_unit if data_unit != 1 else None}) + ) for key, value in func.kwargs.items() } - units = extract_units(data_array1) + units_a = extract_units(data_array1) + units_b = extract_units(data_array2) expected_a, expected_b = func( - strip_units(data_array1), strip_units(data_array2), **stripped_kwargs + strip_units(data_array1), + strip_units(convert_units(data_array2, units_a)), + **stripped_kwargs, ) - expected_a = attach_units(expected_a, units) - # FIXME: should expected_b have the same units as data_array1 - # or data_array2? - expected_b = attach_units(expected_b, units) + expected_a = attach_units(expected_a, units_a) + expected_b = convert_units(attach_units(expected_b, units_a), units_b) result_a, result_b = func(data_array1, data_array2) @@ -456,7 +455,7 @@ def test_align_dataarray(fill_value, variant, unit, error, dtype): assert_equal_with_units(expected_b, result_b) -@pytest.mark.xfail(reason="align strips units") +@pytest.mark.xfail(reason="blocked by `reindex` / `where`") @pytest.mark.parametrize( "unit,error", ( @@ -482,11 +481,7 @@ def test_align_dataarray(fill_value, variant, unit, error, dtype): def test_align_dataset(fill_value, unit, variant, error, dtype): original_unit = unit_registry.m - variants = { - "data": (unit, original_unit, original_unit), - "dims": (original_unit, unit, original_unit), - "coords": (original_unit, original_unit, unit), - } + variants = {"data": (unit, 1, 1), "dims": (1, unit, 1), "coords": (1, 1, unit)} data_unit, dim_unit, coord_unit = variants.get(variant) array1 = np.linspace(0, 10, 2 * 5).reshape(2, 5).astype(dtype) * original_unit @@ -517,7 +512,9 @@ def test_align_dataset(fill_value, unit, variant, error, dtype): return stripped_kwargs = { - key: strip_units(convert_units(value, {None: original_unit})) + key: strip_units( + convert_units(value, {None: original_unit if data_unit != 1 else None}) + ) for key, value in func.kwargs.items() } units_a = extract_units(ds1) @@ -526,7 +523,6 @@ def test_align_dataset(fill_value, unit, variant, error, dtype): strip_units(ds1), strip_units(convert_units(ds2, units_a)), **stripped_kwargs ) expected_a = attach_units(expected_a, units_a) - # FIXME: should expected_b have the same units as ds1 or ds2? expected_b = convert_units(attach_units(expected_b, units_a), units_b) result_a, result_b = func(ds1, ds2) @@ -737,7 +733,6 @@ def test_combine_nested(variant, unit, error, dtype): assert_equal_with_units(expected, result) -@pytest.mark.xfail(reason="`concat` strips units") @pytest.mark.parametrize( "unit,error", ( @@ -778,15 +773,18 @@ def test_concat_dataarray(variant, unit, error, dtype): return + units = extract_units(arr1) expected = attach_units( - xr.concat([strip_units(arr1), strip_units(arr2)], dim="x"), extract_units(arr1) + xr.concat( + [strip_units(arr1), strip_units(convert_units(arr2, units))], dim="x" + ), + units, ) result = xr.concat([arr1, arr2], dim="x") assert_equal_with_units(expected, result) -@pytest.mark.xfail(reason="`concat` strips units") @pytest.mark.parametrize( "unit,error", ( @@ -827,15 +825,17 @@ def test_concat_dataset(variant, unit, error, dtype): return + units = extract_units(ds1) expected = attach_units( - xr.concat([strip_units(ds1), strip_units(ds2)], dim="x"), extract_units(ds1) + xr.concat([strip_units(ds1), strip_units(convert_units(ds2, units))], dim="x"), + units, ) result = xr.concat([ds1, ds2], dim="x") assert_equal_with_units(expected, result) -@pytest.mark.xfail(reason="blocked by `where`") +@pytest.mark.xfail(reason="blocked by `reindex` / `where`") @pytest.mark.parametrize( "unit,error", ( @@ -925,7 +925,7 @@ def test_merge_dataarray(variant, unit, error, dtype): assert_equal_with_units(expected, result) -@pytest.mark.xfail(reason="blocked by `where`") +@pytest.mark.xfail(reason="blocked by `reindex` / `where`") @pytest.mark.parametrize( "unit,error", ( @@ -1656,17 +1656,10 @@ def test_missing_value_filling(self, func, dtype): * unit_registry.degK ) x = np.arange(len(array)) - data_array = xr.DataArray(data=array, coords={"x": x}, dims=["x"]) - - result_without_units = func(strip_units(data_array), dim="x") - result = xr.DataArray( - data=result_without_units.data * unit_registry.degK, - coords={"x": x}, - dims=["x"], - ) + data_array = xr.DataArray(data=array, coords={"x": x}, dims="x") expected = attach_units( - func(strip_units(data_array), dim="x"), {"data": unit_registry.degK} + func(strip_units(data_array), dim="x"), extract_units(data_array) ) result = func(data_array, dim="x") @@ -1742,7 +1735,13 @@ def test_dropna(self, dtype): @pytest.mark.parametrize( "unit", ( - pytest.param(1, id="no_unit"), + pytest.param( + 1, + id="no_unit", + marks=pytest.mark.xfail( + reason="pint's isin implementation does not work well with mixed args" + ), + ), pytest.param(unit_registry.dimensionless, id="dimensionless"), pytest.param(unit_registry.s, id="incompatible_unit"), pytest.param(unit_registry.cm, id="compatible_unit"), @@ -1768,7 +1767,19 @@ def test_isin(self, unit, dtype): assert_equal_with_units(expected, result) @pytest.mark.parametrize( - "variant", ("masking", "replacing_scalar", "replacing_array", "dropping") + "variant", + ( + pytest.param( + "masking", + marks=pytest.mark.xfail(reason="array(nan) is not a quantity"), + ), + "replacing_scalar", + "replacing_array", + pytest.param( + "dropping", + marks=pytest.mark.xfail(reason="array(nan) is not a quantity"), + ), + ), ) @pytest.mark.parametrize( "unit,error", @@ -2816,7 +2827,9 @@ def test_repr(self, func, variant, dtype): reason="np.median does not work with dataset yet" ), ), - function("sum"), + pytest.param( + function("sum"), marks=pytest.mark.xfail(reason="blocked by `where`") + ), pytest.param( function("prod"), marks=pytest.mark.xfail(reason="not implemented by pint"), @@ -2826,9 +2839,7 @@ def test_repr(self, func, variant, dtype): function("cumsum"), pytest.param( function("cumprod"), - marks=pytest.mark.xfail( - reason="pint does not support cumprod on non-dimensionless yet" - ), + marks=pytest.mark.xfail(reason="fails within xarray"), ), pytest.param( method("all"), marks=pytest.mark.xfail(reason="not implemented by pint") @@ -2842,7 +2853,9 @@ def test_repr(self, func, variant, dtype): method("min"), method("mean"), method("median"), - method("sum"), + pytest.param( + method("sum"), marks=pytest.mark.xfail(reason="blocked by `where`") + ), pytest.param( method("prod"), marks=pytest.mark.xfail(reason="not implemented by pint"), @@ -2851,17 +2864,21 @@ def test_repr(self, func, variant, dtype): method("var"), method("cumsum"), pytest.param( - method("cumprod"), - marks=pytest.mark.xfail( - reason="pint does not support cumprod on non-dimensionless yet" - ), + method("cumprod"), marks=pytest.mark.xfail(reason="fails within xarray") ), ), ids=repr, ) def test_aggregation(self, func, dtype): - unit_a = unit_registry.Pa - unit_b = unit_registry.kg / unit_registry.m ** 3 + unit_a = ( + unit_registry.Pa if func.name != "cumprod" else unit_registry.dimensionless + ) + unit_b = ( + unit_registry.kg / unit_registry.m ** 3 + if func.name != "cumprod" + else unit_registry.dimensionless + ) + print(unit_a, unit_b) a = xr.DataArray(data=np.linspace(0, 1, 10).astype(dtype) * unit_a, dims="x") b = xr.DataArray(data=np.linspace(-1, 0, 10).astype(dtype) * unit_b, dims="x") x = xr.DataArray(data=np.arange(10).astype(dtype) * unit_registry.m, dims="x") @@ -2874,7 +2891,10 @@ def test_aggregation(self, func, dtype): result = func(ds) expected = attach_units( func(strip_units(ds)), - {"a": array_extract_units(func(a)), "b": array_extract_units(func(b))}, + { + "a": extract_units(func(a)).get(None), + "b": extract_units(func(b)).get(None), + }, ) assert_equal_with_units(result, expected) @@ -3153,7 +3173,13 @@ def test_dropna(self, dtype): @pytest.mark.parametrize( "unit", ( - pytest.param(1, id="no_unit"), + pytest.param( + 1, + id="no_unit", + marks=pytest.mark.xfail( + reason="pint's isin implementation does not work well with mixed args" + ), + ), pytest.param(unit_registry.dimensionless, id="dimensionless"), pytest.param(unit_registry.s, id="incompatible_unit"), pytest.param(unit_registry.cm, id="compatible_unit"), @@ -3199,7 +3225,19 @@ def test_isin(self, unit, dtype): assert_equal_with_units(result, expected) @pytest.mark.parametrize( - "variant", ("masking", "replacing_scalar", "replacing_array", "dropping") + "variant", + ( + pytest.param( + "masking", + marks=pytest.mark.xfail(reason="array(nan) is not a quantity"), + ), + "replacing_scalar", + "replacing_array", + pytest.param( + "dropping", + marks=pytest.mark.xfail(reason="array(nan) is not a quantity"), + ), + ), ) @pytest.mark.parametrize( "unit,error", @@ -3345,11 +3383,7 @@ def test_combine_first(self, unit, error, dtype): pytest.param(1, id="no_unit"), pytest.param(unit_registry.dimensionless, id="dimensionless"), pytest.param(unit_registry.s, id="incompatible_unit"), - pytest.param( - unit_registry.cm, - id="compatible_unit", - marks=pytest.mark.xfail(reason="identical does not check units yet"), - ), + pytest.param(unit_registry.cm, id="compatible_unit"), pytest.param(unit_registry.m, id="identical_unit"), ), ) @@ -3365,6 +3399,13 @@ def test_combine_first(self, unit, error, dtype): ) @pytest.mark.parametrize("func", (method("equals"), method("identical")), ids=repr) def test_comparisons(self, func, variation, unit, dtype): + def is_compatible(a, b): + a = a if a is not None else 1 + b = b if b is not None else 1 + quantity = np.arange(5) * a + + return a == b or quantity.check(b) + array1 = np.linspace(0, 5, 10).astype(dtype) array2 = np.linspace(-5, 0, 10).astype(dtype) @@ -3376,11 +3417,7 @@ def test_comparisons(self, func, variation, unit, dtype): x = coord * original_unit y = coord * original_unit - units = { - "data": (unit, original_unit, original_unit), - "dims": (original_unit, unit, original_unit), - "coords": (original_unit, original_unit, unit), - } + units = {"data": (unit, 1, 1), "dims": (1, unit, 1), "coords": (1, 1, unit)} data_unit, dim_unit, coord_unit = units.get(variation) ds = xr.Dataset( @@ -3391,31 +3428,23 @@ def test_comparisons(self, func, variation, unit, dtype): coords={"x": x, "y": ("x", y)}, ) - other = attach_units( - strip_units(ds), - { - "a": (data_unit, original_unit if quantity1.check(data_unit) else None), - "b": (data_unit, original_unit if quantity2.check(data_unit) else None), - "x": (dim_unit, original_unit if x.check(dim_unit) else None), - "y": (coord_unit, original_unit if y.check(coord_unit) else None), - }, - ) + other_units = { + "a": data_unit if quantity1.check(data_unit) else None, + "b": data_unit if quantity2.check(data_unit) else None, + "x": dim_unit if x.check(dim_unit) else None, + "y": coord_unit if y.check(coord_unit) else None, + } + other = attach_units(strip_units(convert_units(ds, other_units)), other_units) + + units = extract_units(ds) + other_units = extract_units(other) + + equal_ds = all( + is_compatible(units[name], other_units[name]) for name in units.keys() + ) and (strip_units(ds).equals(strip_units(convert_units(other, units)))) + equal_units = units == other_units + expected = equal_ds and (func.name != "identical" or equal_units) - # TODO: test dim coord once indexes leave units intact - # also, express this in terms of calls on the raw data array - # and then check the units - equal_arrays = ( - np.all(ds.a.data == other.a.data) - and np.all(ds.b.data == other.b.data) - and (np.all(x == other.x.data) or True) # dims can't be checked yet - and np.all(y == other.y.data) - ) - equal_units = ( - data_unit == original_unit - and coord_unit == original_unit - and dim_unit == original_unit - ) - expected = equal_arrays and (func.name != "identical" or equal_units) result = func(ds, other) assert expected == result @@ -3676,7 +3705,7 @@ def test_sel(self, raw_values, unit, error, dtype): result = ds.sel(x=values) assert_equal_with_units(expected, result) - @pytest.mark.xfail(False, reason="indexes don't support units") + @pytest.mark.xfail(reason="indexes don't support units") @pytest.mark.parametrize( "raw_values", ( @@ -3964,6 +3993,7 @@ def test_interp_like(self, unit, error, dtype): assert_equal_with_units(result, expected) + @pytest.mark.xfail(reason="blocked by `where`") @pytest.mark.parametrize( "unit,error", ( @@ -3976,9 +4006,13 @@ def test_interp_like(self, unit, error, dtype): pytest.param(unit_registry.m, None, id="identical_unit"), ), ) - def test_reindex(self, unit, error): - array1 = np.linspace(1, 2, 10 * 5).reshape(10, 5) * unit_registry.degK - array2 = np.linspace(1, 2, 10 * 8).reshape(10, 8) * unit_registry.Pa + def test_reindex(self, unit, error, dtype): + array1 = ( + np.linspace(1, 2, 10 * 5).reshape(10, 5).astype(dtype) * unit_registry.degK + ) + array2 = ( + np.linspace(1, 2, 10 * 8).reshape(10, 8).astype(dtype) * unit_registry.Pa + ) coords = { "x": np.arange(10) * unit_registry.m, @@ -4011,6 +4045,7 @@ def test_reindex(self, unit, error): assert_equal_with_units(result, expected) + @pytest.mark.xfail(reason="blocked by `where`") @pytest.mark.parametrize( "unit,error", ( @@ -4117,8 +4152,7 @@ def test_computation(self, func, dtype): method("groupby_bins", "x", bins=4), method("coarsen", x=2), pytest.param( - method("rolling", x=3), - marks=pytest.mark.xfail(False, reason="strips units"), + method("rolling", x=3), marks=pytest.mark.xfail(reason="strips units") ), pytest.param( method("rolling_exp", x=3), From 1e192c3de059f2963ead2e58122c031d96e2f5e4 Mon Sep 17 00:00:00 2001 From: Keewis Date: Sun, 8 Dec 2019 02:56:45 +0100 Subject: [PATCH 30/32] rename result to actual to match the other test files --- xarray/tests/test_units.py | 386 ++++++++++++++++++------------------- 1 file changed, 193 insertions(+), 193 deletions(-) diff --git a/xarray/tests/test_units.py b/xarray/tests/test_units.py index ace76085569..8356da941e6 100644 --- a/xarray/tests/test_units.py +++ b/xarray/tests/test_units.py @@ -353,9 +353,9 @@ def test_apply_ufunc_dataarray(dtype): data_array = xr.DataArray(data=array, dims="x", coords={"x": x}) expected = attach_units(func(strip_units(data_array)), extract_units(data_array)) - result = func(data_array) + actual = func(data_array) - assert_equal_with_units(expected, result) + assert_equal_with_units(expected, actual) def test_apply_ufunc_dataset(dtype): @@ -375,9 +375,9 @@ def test_apply_ufunc_dataset(dtype): ) expected = attach_units(func(strip_units(ds)), extract_units(ds)) - result = func(ds) + actual = func(ds) - assert_equal_with_units(expected, result) + assert_equal_with_units(expected, actual) @pytest.mark.xfail(reason="blocked by `reindex` / `where`") @@ -449,10 +449,10 @@ def test_align_dataarray(fill_value, variant, unit, error, dtype): expected_a = attach_units(expected_a, units_a) expected_b = convert_units(attach_units(expected_b, units_a), units_b) - result_a, result_b = func(data_array1, data_array2) + actual_a, actual_b = func(data_array1, data_array2) - assert_equal_with_units(expected_a, result_a) - assert_equal_with_units(expected_b, result_b) + assert_equal_with_units(expected_a, actual_a) + assert_equal_with_units(expected_b, actual_b) @pytest.mark.xfail(reason="blocked by `reindex` / `where`") @@ -525,10 +525,10 @@ def test_align_dataset(fill_value, unit, variant, error, dtype): expected_a = attach_units(expected_a, units_a) expected_b = convert_units(attach_units(expected_b, units_a), units_b) - result_a, result_b = func(ds1, ds2) + actual_a, actual_b = func(ds1, ds2) - assert_equal_with_units(expected_a, result_a) - assert_equal_with_units(expected_b, result_b) + assert_equal_with_units(expected_a, actual_a) + assert_equal_with_units(expected_b, actual_b) def test_broadcast_dataarray(dtype): @@ -542,10 +542,10 @@ def test_broadcast_dataarray(dtype): attach_units(elem, extract_units(a)) for elem in xr.broadcast(strip_units(a), strip_units(b)) ) - result_a, result_b = xr.broadcast(a, b) + actual_a, actual_b = xr.broadcast(a, b) - assert_equal_with_units(expected_a, result_a) - assert_equal_with_units(expected_b, result_b) + assert_equal_with_units(expected_a, actual_a) + assert_equal_with_units(expected_b, actual_b) def test_broadcast_dataset(dtype): @@ -557,9 +557,9 @@ def test_broadcast_dataset(dtype): (expected,) = tuple( attach_units(elem, extract_units(ds)) for elem in xr.broadcast(strip_units(ds)) ) - (result,) = xr.broadcast(ds) + (actual,) = xr.broadcast(ds) - assert_equal_with_units(expected, result) + assert_equal_with_units(expected, actual) @pytest.mark.xfail(reason="`combine_by_coords` strips units") @@ -628,9 +628,9 @@ def test_combine_by_coords(variant, unit, error, dtype): ), units, ) - result = xr.combine_by_coords([ds, other]) + actual = xr.combine_by_coords([ds, other]) - assert_equal_with_units(expected, result) + assert_equal_with_units(expected, actual) @pytest.mark.xfail(reason="blocked by `where`") @@ -728,9 +728,9 @@ def test_combine_nested(variant, unit, error, dtype): ), units, ) - result = func([[ds1, ds2], [ds3, ds4]]) + actual = func([[ds1, ds2], [ds3, ds4]]) - assert_equal_with_units(expected, result) + assert_equal_with_units(expected, actual) @pytest.mark.parametrize( @@ -780,9 +780,9 @@ def test_concat_dataarray(variant, unit, error, dtype): ), units, ) - result = xr.concat([arr1, arr2], dim="x") + actual = xr.concat([arr1, arr2], dim="x") - assert_equal_with_units(expected, result) + assert_equal_with_units(expected, actual) @pytest.mark.parametrize( @@ -830,9 +830,9 @@ def test_concat_dataset(variant, unit, error, dtype): xr.concat([strip_units(ds1), strip_units(convert_units(ds2, units))], dim="x"), units, ) - result = xr.concat([ds1, ds2], dim="x") + actual = xr.concat([ds1, ds2], dim="x") - assert_equal_with_units(expected, result) + assert_equal_with_units(expected, actual) @pytest.mark.xfail(reason="blocked by `reindex` / `where`") @@ -920,9 +920,9 @@ def test_merge_dataarray(variant, unit, error, dtype): func([strip_units(arr1), convert_and_strip(arr2), convert_and_strip(arr3)]), units, ) - result = func([arr1, arr2, arr3]) + actual = func([arr1, arr2, arr3]) - assert_equal_with_units(expected, result) + assert_equal_with_units(expected, actual) @pytest.mark.xfail(reason="blocked by `reindex` / `where`") @@ -1003,9 +1003,9 @@ def test_merge_dataset(variant, unit, error, dtype): expected = attach_units( func([strip_units(ds1), convert_and_strip(ds2), convert_and_strip(ds3)]), units ) - result = func([ds1, ds2, ds3]) + actual = func([ds1, ds2, ds3]) - assert_equal_with_units(expected, result) + assert_equal_with_units(expected, actual) @pytest.mark.parametrize("func", (xr.zeros_like, xr.ones_like)) @@ -1015,9 +1015,9 @@ def test_replication_dataarray(func, dtype): numpy_func = getattr(np, func.__name__) expected = xr.DataArray(data=numpy_func(array), dims="x") - result = func(data_array) + actual = func(data_array) - assert_equal_with_units(expected, result) + assert_equal_with_units(expected, actual) @pytest.mark.parametrize("func", (xr.zeros_like, xr.ones_like)) @@ -1037,9 +1037,9 @@ def test_replication_dataset(func, dtype): expected = ds.copy( data={name: numpy_func(array.data) for name, array in ds.data_vars.items()} ) - result = func(ds) + actual = func(ds) - assert_equal_with_units(expected, result) + assert_equal_with_units(expected, actual) @pytest.mark.xfail( @@ -1076,9 +1076,9 @@ def test_replication_full_like_dataarray(unit, error, dtype): expected = attach_units( xr.full_like(strip_units(data_array), fill_value=strip_units(fill_value)), units ) - result = xr.full_like(data_array, fill_value=fill_value) + actual = xr.full_like(data_array, fill_value=fill_value) - assert_equal_with_units(expected, result) + assert_equal_with_units(expected, actual) @pytest.mark.xfail( @@ -1126,9 +1126,9 @@ def test_replication_full_like_dataset(unit, error, dtype): expected = attach_units( xr.full_like(strip_units(ds), fill_value=strip_units(fill_value)), units ) - result = xr.full_like(ds, fill_value=fill_value) + actual = xr.full_like(ds, fill_value=fill_value) - assert_equal_with_units(expected, result) + assert_equal_with_units(expected, actual) @pytest.mark.parametrize( @@ -1166,9 +1166,9 @@ def test_where_dataarray(fill_value, unit, error, dtype): ), extract_units(x), ) - result = xr.where(cond, x, fill_value) + actual = xr.where(cond, x, fill_value) - assert_equal_with_units(expected, result) + assert_equal_with_units(expected, actual) @pytest.mark.parametrize( @@ -1208,9 +1208,9 @@ def test_where_dataset(fill_value, unit, error, dtype): ), extract_units(ds), ) - result = xr.where(cond, ds, fill_value) + actual = xr.where(cond, ds, fill_value) - assert_equal_with_units(expected, result) + assert_equal_with_units(expected, actual) def test_dot_dataarray(dtype): @@ -1229,9 +1229,9 @@ def test_dot_dataarray(dtype): expected = attach_units( xr.dot(strip_units(data_array), strip_units(other)), {None: unit_registry.m} ) - result = xr.dot(data_array, other) + actual = xr.dot(data_array, other) - assert_equal_with_units(expected, result) + assert_equal_with_units(expected, actual) class TestDataArray: @@ -1381,9 +1381,9 @@ def test_aggregation(self, func, dtype): # first compute the units units = extract_units(func(array)) expected = attach_units(func(strip_units(data_array)), units) - result = func(data_array) + actual = func(data_array) - assert_equal_with_units(expected, result) + assert_equal_with_units(expected, actual) @pytest.mark.parametrize( "func", @@ -1399,9 +1399,9 @@ def test_unary_operations(self, func, dtype): units = extract_units(func(array)) expected = attach_units(func(strip_units(data_array)), units) - result = func(data_array) + actual = func(data_array) - assert_equal_with_units(expected, result) + assert_equal_with_units(expected, actual) @pytest.mark.parametrize( "func", @@ -1418,9 +1418,9 @@ def test_binary_operations(self, func, dtype): units = extract_units(func(array)) expected = attach_units(func(strip_units(data_array)), units) - result = func(data_array) + actual = func(data_array) - assert_equal_with_units(expected, result) + assert_equal_with_units(expected, actual) @pytest.mark.parametrize( "comparison", @@ -1462,7 +1462,7 @@ def test_comparison_operations(self, comparison, unit, error, dtype): return - result = comparison(data_array, to_compare_with) + actual = comparison(data_array, to_compare_with) expected_units = {None: unit_registry.m if array.check(unit) else None} expected = array.check(unit) & comparison( @@ -1470,7 +1470,7 @@ def test_comparison_operations(self, comparison, unit, error, dtype): strip_units(convert_units(to_compare_with, expected_units)), ) - assert_equal_with_units(expected, result) + assert_equal_with_units(expected, actual) @pytest.mark.parametrize( "units,error", @@ -1496,9 +1496,9 @@ def test_univariate_ufunc(self, units, error, dtype): func(strip_units(convert_units(data_array, {None: unit_registry.radians}))), {None: unit_registry.dimensionless}, ) - result = func(data_array) + actual = func(data_array) - assert_equal_with_units(expected, result) + assert_equal_with_units(expected, actual) @pytest.mark.xfail(reason="xarray's `np.maximum` strips units") @pytest.mark.parametrize( @@ -1533,11 +1533,11 @@ def test_bivariate_ufunc(self, unit, error, dtype): expected_units, ) - result = np.maximum(data_array, 0 * unit) - assert_equal_with_units(expected, result) + actual = np.maximum(data_array, 0 * unit) + assert_equal_with_units(expected, actual) - result = np.maximum(0 * unit, data_array) - assert_equal_with_units(expected, result) + actual = np.maximum(0 * unit, data_array) + assert_equal_with_units(expected, actual) @pytest.mark.parametrize("property", ("T", "imag", "real")) def test_numpy_properties(self, property, dtype): @@ -1551,9 +1551,9 @@ def test_numpy_properties(self, property, dtype): expected = attach_units( getattr(strip_units(data_array), property), extract_units(data_array) ) - result = getattr(data_array, property) + actual = getattr(data_array, property) - assert_equal_with_units(expected, result) + assert_equal_with_units(expected, actual) @pytest.mark.parametrize( "func", @@ -1566,9 +1566,9 @@ def test_numpy_methods(self, func, dtype): units = extract_units(func(array)) expected = attach_units(strip_units(data_array), units) - result = func(data_array) + actual = func(data_array) - assert_equal_with_units(expected, result) + assert_equal_with_units(expected, actual) @pytest.mark.parametrize( "func", @@ -1619,9 +1619,9 @@ def test_numpy_methods_with_args(self, func, unit, error, dtype): expected = attach_units( func(strip_units(data_array), **stripped_kwargs), expected_units ) - result = func(data_array, **kwargs) + actual = func(data_array, **kwargs) - assert_equal_with_units(expected, result) + assert_equal_with_units(expected, actual) @pytest.mark.parametrize( "func", (method("isnull"), method("notnull"), method("count")), ids=repr @@ -1644,9 +1644,9 @@ def test_missing_value_detection(self, func, dtype): data_array = xr.DataArray(data=array, coords={"x": x, "y": y}, dims=("x", "y")) expected = func(strip_units(data_array)) - result = func(data_array) + actual = func(data_array) - assert_equal_with_units(expected, result) + assert_equal_with_units(expected, actual) @pytest.mark.xfail(reason="ffill and bfill lose units in data") @pytest.mark.parametrize("func", (method("ffill"), method("bfill")), ids=repr) @@ -1661,9 +1661,9 @@ def test_missing_value_filling(self, func, dtype): expected = attach_units( func(strip_units(data_array), dim="x"), extract_units(data_array) ) - result = func(data_array, dim="x") + actual = func(data_array, dim="x") - assert_equal_with_units(expected, result) + assert_equal_with_units(expected, actual) @pytest.mark.parametrize( "unit,error", @@ -1714,9 +1714,9 @@ def test_fillna(self, fill_value, unit, error, dtype): ), units, ) - result = func(data_array, value=value) + actual = func(data_array, value=value) - assert_equal_with_units(expected, result) + assert_equal_with_units(expected, actual) def test_dropna(self, dtype): array = ( @@ -1728,9 +1728,9 @@ def test_dropna(self, dtype): units = extract_units(data_array) expected = attach_units(strip_units(data_array).dropna(dim="x"), units) - result = data_array.dropna(dim="x") + actual = data_array.dropna(dim="x") - assert_equal_with_units(expected, result) + assert_equal_with_units(expected, actual) @pytest.mark.parametrize( "unit", @@ -1762,9 +1762,9 @@ def test_isin(self, unit, dtype): expected = strip_units(data_array).isin( strip_units(convert_units(values, units)) ) & array.check(unit) - result = data_array.isin(values) + actual = data_array.isin(values) - assert_equal_with_units(expected, result) + assert_equal_with_units(expected, actual) @pytest.mark.parametrize( "variant", @@ -1827,9 +1827,9 @@ def test_where(self, variant, unit, error, dtype): strip_units(data_array).where(**kwargs_without_units), extract_units(data_array), ) - result = data_array.where(**kwargs) + actual = data_array.where(**kwargs) - assert_equal_with_units(expected, result) + assert_equal_with_units(expected, actual) @pytest.mark.xfail(reason="interpolate strips units") def test_interpolate_na(self, dtype): @@ -1842,9 +1842,9 @@ def test_interpolate_na(self, dtype): units = extract_units(data_array) expected = attach_units(strip_units(data_array).interpolate_na(dim="x"), units) - result = data_array.interpolate_na(dim="x") + actual = data_array.interpolate_na(dim="x") - assert_equal_with_units(expected, result) + assert_equal_with_units(expected, actual) @pytest.mark.parametrize( "unit,error", @@ -1892,9 +1892,9 @@ def test_combine_first(self, unit, error, dtype): ), units, ) - result = data_array.combine_first(other) + actual = data_array.combine_first(other) - assert_equal_with_units(expected, result) + assert_equal_with_units(expected, actual) @pytest.mark.parametrize( "unit", @@ -1959,9 +1959,9 @@ def is_compatible(a, b): equal_units = units == other_units expected = equal_arrays and (func.name != "identical" or equal_units) - result = func(data_array, other) + actual = func(data_array, other) - assert expected == result + assert expected == actual @pytest.mark.xfail(reason="blocked by `where`") @pytest.mark.parametrize( @@ -1989,9 +1989,9 @@ def test_broadcast_like(self, unit, dtype): expected = attach_units( strip_units(arr1).broadcast_like(strip_units(arr2)), extract_units(arr1) ) - result = arr1.broadcast_like(arr2) + actual = arr1.broadcast_like(arr2) - assert_equal_with_units(expected, result) + assert_equal_with_units(expected, actual) @pytest.mark.parametrize( "unit", @@ -2017,9 +2017,9 @@ def test_broadcast_equals(self, unit, dtype): expected = strip_units(left).broadcast_equals( strip_units(convert_units(right, units)) ) & left_array.check(unit) - result = left.broadcast_equals(right) + actual = left.broadcast_equals(right) - assert expected == result + assert expected == actual @pytest.mark.parametrize( "func", @@ -2064,9 +2064,9 @@ def test_content_manipulation(self, func, dtype): units = {**{"x_mm": x2.units, "x2": x2.units}, **extract_units(data_array)} expected = attach_units(func(strip_units(data_array), **stripped_kwargs), units) - result = func(data_array) + actual = func(data_array) - assert_equal_with_units(expected, result) + assert_equal_with_units(expected, actual) @pytest.mark.parametrize( "func", (pytest.param(method("copy", data=np.arange(20))),), ids=repr @@ -2091,8 +2091,8 @@ def test_content_manipulation_with_units(self, func, unit, dtype): func(strip_units(data_array)), {None: unit, "x": x.units} ) - result = func(data_array, **kwargs) - assert_equal_with_units(expected, result) + actual = func(data_array, **kwargs) + assert_equal_with_units(expected, actual) @pytest.mark.parametrize( "indices", @@ -2110,9 +2110,9 @@ def test_isel(self, indices, dtype): expected = attach_units( strip_units(data_array).isel(x=indices), extract_units(data_array) ) - result = data_array.isel(x=indices) + actual = data_array.isel(x=indices) - assert_equal_with_units(expected, result) + assert_equal_with_units(expected, actual) @pytest.mark.xfail(reason="indexes don't support units") @pytest.mark.parametrize( @@ -2154,8 +2154,8 @@ def test_sel(self, raw_values, unit, error, dtype): ), extract_units(data_array), ) - result = data_array.sel(x=values) - assert_equal_with_units(expected, result) + actual = data_array.sel(x=values) + assert_equal_with_units(expected, actual) @pytest.mark.xfail(reason="indexes don't support units") @pytest.mark.parametrize( @@ -2197,8 +2197,8 @@ def test_loc(self, raw_values, unit, error, dtype): ], extract_units(data_array), ) - result = data_array.loc[{"x": values}] - assert_equal_with_units(expected, result) + actual = data_array.loc[{"x": values}] + assert_equal_with_units(expected, actual) @pytest.mark.xfail(reason="indexes don't support units") @pytest.mark.parametrize( @@ -2240,8 +2240,8 @@ def test_drop_sel(self, raw_values, unit, error, dtype): ), extract_units(data_array), ) - result = data_array.drop_sel(x=values) - assert_equal_with_units(expected, result) + actual = data_array.drop_sel(x=values) + assert_equal_with_units(expected, actual) @pytest.mark.parametrize( "shape", @@ -2268,8 +2268,8 @@ def test_squeeze(self, shape, dtype): expected = attach_units( strip_units(data_array).squeeze(), extract_units(data_array) ) - result = data_array.squeeze() - assert_equal_with_units(expected, result) + actual = data_array.squeeze() + assert_equal_with_units(expected, actual) # try squeezing the dimensions separately names = tuple(dim for dim, coord in coords.items() if len(coord) == 1) @@ -2277,8 +2277,8 @@ def test_squeeze(self, shape, dtype): expected = attach_units( strip_units(data_array).squeeze(dim=name), extract_units(data_array) ) - result = data_array.squeeze(dim=name) - assert_equal_with_units(expected, result) + actual = data_array.squeeze(dim=name) + assert_equal_with_units(expected, actual) @pytest.mark.parametrize( "func", @@ -2298,9 +2298,9 @@ def test_head_tail_thin(self, func, dtype): expected = attach_units( func(strip_units(data_array)), extract_units(data_array) ) - result = func(data_array) + actual = func(data_array) - assert_equal_with_units(expected, result) + assert_equal_with_units(expected, actual) @pytest.mark.xfail(reason="indexes don't support units") @pytest.mark.parametrize( @@ -2338,9 +2338,9 @@ def test_interp(self, unit, error): ), units, ) - result = data_array.interp(x=new_coords) + actual = data_array.interp(x=new_coords) - assert_equal_with_units(expected, result) + assert_equal_with_units(expected, actual) @pytest.mark.xfail(reason="indexes strip units") @pytest.mark.parametrize( @@ -2382,9 +2382,9 @@ def test_interp_like(self, unit, error): ), units, ) - result = data_array.interp_like(other) + actual = data_array.interp_like(other) - assert_equal_with_units(expected, result) + assert_equal_with_units(expected, actual) @pytest.mark.xfail(reason="indexes don't support units") @pytest.mark.parametrize( @@ -2471,9 +2471,9 @@ def test_reindex_like(self, unit, error, dtype): ), units, ) - result = data_array.reindex_like(other) + actual = data_array.reindex_like(other) - assert_equal_with_units(expected, result) + assert_equal_with_units(expected, actual) @pytest.mark.parametrize( "func", @@ -2493,9 +2493,9 @@ def test_stacking_stacked(self, func, dtype): stacked = data_array.stack(z=("x", "y")) expected = attach_units(func(strip_units(stacked)), {"data": unit_registry.m}) - result = func(stacked) + actual = func(stacked) - assert_equal_with_units(expected, result) + assert_equal_with_units(expected, actual) @pytest.mark.xfail(reason="indexes don't support units") def test_to_unstacked_dataset(self, dtype): @@ -2516,9 +2516,9 @@ def test_to_unstacked_dataset(self, dtype): func(strip_units(data_array)), {"y": y.units, **dict(zip(x.magnitude, [array.units] * len(y)))}, ).rename({elem.magnitude: elem for elem in x}) - result = func(data_array) + actual = func(data_array) - assert_equal_with_units(expected, result) + assert_equal_with_units(expected, actual) @pytest.mark.parametrize( "func", @@ -2552,9 +2552,9 @@ def test_stacking_reordering(self, func, dtype): ) expected = attach_units(func(strip_units(data_array)), {None: unit_registry.m}) - result = func(data_array) + actual = func(data_array) - assert_equal_with_units(expected, result) + assert_equal_with_units(expected, actual) @pytest.mark.parametrize( "func", @@ -2595,9 +2595,9 @@ def test_computation(self, func, dtype): } expected = attach_units(func(strip_units(data_array)), units) - result = func(data_array) + actual = func(data_array) - assert_equal_with_units(expected, result) + assert_equal_with_units(expected, actual) @pytest.mark.parametrize( "func", @@ -2628,9 +2628,9 @@ def test_computation_objects(self, func, dtype): units = extract_units(data_array) expected = attach_units(func(strip_units(data_array)).mean(), units) - result = func(data_array).mean() + actual = func(data_array).mean() - assert_equal_with_units(expected, result) + assert_equal_with_units(expected, actual) @pytest.mark.xfail(reason="blocked by `reindex` / `where`") def test_resample(self, dtype): @@ -2643,9 +2643,9 @@ def test_resample(self, dtype): func = method("resample", time="6m") expected = attach_units(func(strip_units(data_array)).mean(), units) - result = func(data_array).mean() + actual = func(data_array).mean() - assert_equal_with_units(expected, result) + assert_equal_with_units(expected, actual) @pytest.mark.parametrize( "func", @@ -2679,9 +2679,9 @@ def test_grouped_operations(self, func, dtype): expected = attach_units( func(strip_units(data_array).groupby("y"), **stripped_kwargs), units ) - result = func(data_array.groupby("y")) + actual = func(data_array.groupby("y")) - assert_equal_with_units(expected, result) + assert_equal_with_units(expected, actual) class TestDataset: @@ -2752,7 +2752,7 @@ def test_init(self, shared, unit, error, dtype): return - result = xr.Dataset(data_vars={"a": arr1, "b": arr2}) + actual = xr.Dataset(data_vars={"a": arr1, "b": arr2}) expected_units = { "a": a.units, @@ -2766,7 +2766,7 @@ def test_init(self, shared, unit, error, dtype): xr.Dataset(data_vars={"a": strip_units(arr1), "b": strip_units(arr2)}), expected_units, ) - assert_equal_with_units(result, expected) + assert_equal_with_units(actual, expected) @pytest.mark.parametrize( "func", (pytest.param(str, id="str"), pytest.param(repr, id="repr")) @@ -2888,7 +2888,7 @@ def test_aggregation(self, func, dtype): ds = xr.Dataset(data_vars={"a": a, "b": b}, coords={"x": x, "y": y}) - result = func(ds) + actual = func(ds) expected = attach_units( func(strip_units(ds)), { @@ -2897,7 +2897,7 @@ def test_aggregation(self, func, dtype): }, ) - assert_equal_with_units(result, expected) + assert_equal_with_units(actual, expected) @pytest.mark.parametrize("property", ("imag", "real")) def test_numpy_properties(self, property, dtype): @@ -2917,10 +2917,10 @@ def test_numpy_properties(self, property, dtype): ) units = extract_units(ds) - result = getattr(ds, property) + actual = getattr(ds, property) expected = attach_units(getattr(strip_units(ds), property), units) - assert_equal_with_units(result, expected) + assert_equal_with_units(actual, expected) @pytest.mark.parametrize( "func", @@ -2955,10 +2955,10 @@ def test_numpy_methods(self, func, dtype): "y": unit_registry.s, } - result = func(ds) + actual = func(ds) expected = attach_units(func(strip_units(ds)), units) - assert_equal_with_units(result, expected) + assert_equal_with_units(actual, expected) @pytest.mark.parametrize("func", (method("clip", min=3, max=8),), ids=repr) @pytest.mark.parametrize( @@ -3003,10 +3003,10 @@ def test_numpy_methods_with_args(self, func, unit, error, dtype): for key, value in kwargs.items() } - result = func(ds, **kwargs) + actual = func(ds, **kwargs) expected = attach_units(func(strip_units(ds), **stripped_kwargs), units) - assert_equal_with_units(result, expected) + assert_equal_with_units(actual, expected) @pytest.mark.parametrize( "func", (method("isnull"), method("notnull"), method("count")), ids=repr @@ -3049,9 +3049,9 @@ def test_missing_value_detection(self, func, dtype): ) expected = func(strip_units(ds)) - result = func(ds) + actual = func(ds) - assert_equal_with_units(expected, result) + assert_equal_with_units(expected, actual) @pytest.mark.xfail(reason="ffill and bfill lose the unit") @pytest.mark.parametrize("func", (method("ffill"), method("bfill")), ids=repr) @@ -3079,9 +3079,9 @@ def test_missing_value_filling(self, func, dtype): func(strip_units(ds), dim="x"), {"a": unit_registry.degK, "b": unit_registry.Pa}, ) - result = func(ds, dim="x") + actual = func(ds, dim="x") - assert_equal_with_units(expected, result) + assert_equal_with_units(expected, actual) @pytest.mark.parametrize( "unit,error", @@ -3132,7 +3132,7 @@ def test_fillna(self, fill_value, unit, error, dtype): return - result = ds.fillna(value=fill_value * unit) + actual = ds.fillna(value=fill_value * unit) expected = attach_units( strip_units(ds).fillna( value=strip_units( @@ -3142,7 +3142,7 @@ def test_fillna(self, fill_value, unit, error, dtype): {"a": unit_registry.m, "b": unit_registry.m}, ) - assert_equal_with_units(expected, result) + assert_equal_with_units(expected, actual) def test_dropna(self, dtype): array1 = ( @@ -3166,9 +3166,9 @@ def test_dropna(self, dtype): strip_units(ds).dropna(dim="x"), {"a": unit_registry.degK, "b": unit_registry.Pa}, ) - result = ds.dropna(dim="x") + actual = ds.dropna(dim="x") - assert_equal_with_units(expected, result) + assert_equal_with_units(expected, actual) @pytest.mark.parametrize( "unit", @@ -3220,9 +3220,9 @@ def test_isin(self, unit, dtype): ): expected.a[:] = False expected.b[:] = False - result = ds.isin(values) + actual = ds.isin(values) - assert_equal_with_units(result, expected) + assert_equal_with_units(actual, expected) @pytest.mark.parametrize( "variant", @@ -3288,9 +3288,9 @@ def test_where(self, variant, unit, error, dtype): strip_units(ds).where(**kwargs_without_units), {"a": original_unit, "b": original_unit}, ) - result = ds.where(**kwargs) + actual = ds.where(**kwargs) - assert_equal_with_units(expected, result) + assert_equal_with_units(expected, actual) @pytest.mark.xfail(reason="interpolate strips units") def test_interpolate_na(self, dtype): @@ -3315,9 +3315,9 @@ def test_interpolate_na(self, dtype): strip_units(ds).interpolate_na(dim="x"), {"a": unit_registry.degK, "b": unit_registry.Pa}, ) - result = ds.interpolate_na(dim="x") + actual = ds.interpolate_na(dim="x") - assert_equal_with_units(expected, result) + assert_equal_with_units(expected, actual) @pytest.mark.xfail(reason="wrong argument order for `where`") @pytest.mark.parametrize( @@ -3373,9 +3373,9 @@ def test_combine_first(self, unit, error, dtype): ), {"a": unit_registry.m, "b": unit_registry.m}, ) - result = ds.combine_first(other) + actual = ds.combine_first(other) - assert_equal_with_units(expected, result) + assert_equal_with_units(expected, actual) @pytest.mark.parametrize( "unit", @@ -3445,9 +3445,9 @@ def is_compatible(a, b): equal_units = units == other_units expected = equal_ds and (func.name != "identical" or equal_units) - result = func(ds, other) + actual = func(ds, other) - assert expected == result + assert expected == actual @pytest.mark.xfail(reason="blocked by `where`") @pytest.mark.parametrize( @@ -3479,9 +3479,9 @@ def test_broadcast_like(self, unit, dtype): expected = attach_units( strip_units(ds1).broadcast_like(strip_units(ds2)), extract_units(ds1) ) - result = ds1.broadcast_like(ds2) + actual = ds1.broadcast_like(ds2) - assert_equal_with_units(expected, result) + assert_equal_with_units(expected, actual) @pytest.mark.parametrize( "unit", @@ -3520,9 +3520,9 @@ def test_broadcast_equals(self, unit, dtype): expected = strip_units(left).broadcast_equals( strip_units(convert_units(right, units)) ) & left_array1.check(unit) - result = left.broadcast_equals(right) + actual = left.broadcast_equals(right) - assert expected == result + assert expected == actual @pytest.mark.parametrize( "func", @@ -3555,9 +3555,9 @@ def test_stacking_stacked(self, func, dtype): expected = attach_units( func(strip_units(stacked)), {"a": unit_registry.m, "b": unit_registry.m} ) - result = func(stacked) + actual = func(stacked) - assert_equal_with_units(expected, result) + assert_equal_with_units(expected, actual) def test_to_stacked_array(self, dtype): labels = np.arange(5).astype(dtype) * unit_registry.s @@ -3572,13 +3572,13 @@ def test_to_stacked_array(self, dtype): func = method("to_stacked_array", "z", variable_dim="y", sample_dims=["x"]) - result = func(ds).rename(None) + actual = func(ds).rename(None) expected = attach_units( func(strip_units(ds)).rename(None), {None: unit_registry.m, "y": unit_registry.s}, ) - assert_equal_with_units(expected, result) + assert_equal_with_units(expected, actual) @pytest.mark.parametrize( "func", @@ -3623,9 +3623,9 @@ def test_stacking_reordering(self, func, dtype): expected = attach_units( func(strip_units(ds)), {"a": unit_registry.Pa, "b": unit_registry.degK} ) - result = func(ds) + actual = func(ds) - assert_equal_with_units(expected, result) + assert_equal_with_units(expected, actual) @pytest.mark.xfail(reason="indexes strip units") @pytest.mark.parametrize( @@ -3652,9 +3652,9 @@ def test_isel(self, indices, dtype): strip_units(ds).isel(x=indices), {"a": unit_registry.s, "b": unit_registry.Pa, "x": unit_registry.m}, ) - result = ds.isel(x=indices) + actual = ds.isel(x=indices) - assert_equal_with_units(expected, result) + assert_equal_with_units(expected, actual) @pytest.mark.xfail(reason="indexes don't support units") @pytest.mark.parametrize( @@ -3702,8 +3702,8 @@ def test_sel(self, raw_values, unit, error, dtype): strip_units(ds).sel(x=strip_units(convert_units(values, {None: x.units}))), {"a": array1.units, "b": array2.units, "x": x.units}, ) - result = ds.sel(x=values) - assert_equal_with_units(expected, result) + actual = ds.sel(x=values) + assert_equal_with_units(expected, actual) @pytest.mark.xfail(reason="indexes don't support units") @pytest.mark.parametrize( @@ -3753,8 +3753,8 @@ def test_drop_sel(self, raw_values, unit, error, dtype): ), extract_units(ds), ) - result = ds.drop_sel(x=values) - assert_equal_with_units(expected, result) + actual = ds.drop_sel(x=values) + assert_equal_with_units(expected, actual) @pytest.mark.xfail(reason="indexes don't support units") @pytest.mark.parametrize( @@ -3804,8 +3804,8 @@ def test_loc(self, raw_values, unit, error, dtype): ], {"a": array1.units, "b": array2.units, "x": x.units}, ) - result = ds.loc[{"x": values}] - assert_equal_with_units(expected, result) + actual = ds.loc[{"x": values}] + assert_equal_with_units(expected, actual) @pytest.mark.parametrize( "func", @@ -3835,9 +3835,9 @@ def test_head_tail_thin(self, func, dtype): ) expected = attach_units(func(strip_units(ds)), extract_units(ds)) - result = func(ds) + actual = func(ds) - assert_equal_with_units(expected, result) + assert_equal_with_units(expected, actual) @pytest.mark.parametrize( "shape", @@ -3874,15 +3874,15 @@ def test_squeeze(self, shape, dtype): expected = attach_units(strip_units(ds).squeeze(), units) - result = ds.squeeze() - assert_equal_with_units(result, expected) + actual = ds.squeeze() + assert_equal_with_units(actual, expected) # try squeezing the dimensions separately names = tuple(dim for dim, coord in coords.items() if len(coord) == 1) for name in names: expected = attach_units(strip_units(ds).squeeze(dim=name), units) - result = ds.squeeze(dim=name) - assert_equal_with_units(result, expected) + actual = ds.squeeze(dim=name) + assert_equal_with_units(actual, expected) @pytest.mark.xfail(reason="ignores units") @pytest.mark.parametrize( @@ -3928,9 +3928,9 @@ def test_interp(self, unit, error): strip_units(ds).interp(x=strip_units(convert_units(new_coords, units))), units, ) - result = ds.interp(x=new_coords) + actual = ds.interp(x=new_coords) - assert_equal_with_units(result, expected) + assert_equal_with_units(actual, expected) @pytest.mark.xfail(reason="ignores units") @pytest.mark.parametrize( @@ -3989,9 +3989,9 @@ def test_interp_like(self, unit, error, dtype): expected = attach_units( strip_units(ds).interp_like(strip_units(convert_units(other, units))), units ) - result = ds.interp_like(other) + actual = ds.interp_like(other) - assert_equal_with_units(result, expected) + assert_equal_with_units(actual, expected) @pytest.mark.xfail(reason="blocked by `where`") @pytest.mark.parametrize( @@ -4041,9 +4041,9 @@ def test_reindex(self, unit, error, dtype): strip_units(ds).reindex(x=strip_units(convert_units(new_coords, units))), units, ) - result = ds.reindex(x=new_coords) + actual = ds.reindex(x=new_coords) - assert_equal_with_units(result, expected) + assert_equal_with_units(actual, expected) @pytest.mark.xfail(reason="blocked by `where`") @pytest.mark.parametrize( @@ -4103,9 +4103,9 @@ def test_reindex_like(self, unit, error, dtype): strip_units(ds).reindex_like(strip_units(convert_units(other, units))), units, ) - result = ds.reindex_like(other) + actual = ds.reindex_like(other) - assert_equal_with_units(result, expected) + assert_equal_with_units(expected, actual) @pytest.mark.parametrize( "func", @@ -4141,9 +4141,9 @@ def test_computation(self, func, dtype): units = extract_units(ds) expected = attach_units(func(strip_units(ds)), units) - result = func(ds) + actual = func(ds) - assert_equal_with_units(expected, result) + assert_equal_with_units(expected, actual) @pytest.mark.parametrize( "func", @@ -4185,9 +4185,9 @@ def test_computation_objects(self, func, dtype): args = [] if func.name != "groupby" else ["y"] reduce_func = method("mean", *args) expected = attach_units(reduce_func(func(strip_units(ds))), units) - result = reduce_func(func(ds)) + actual = reduce_func(func(ds)) - assert_equal_with_units(expected, result) + assert_equal_with_units(expected, actual) @pytest.mark.xfail(reason="blocked by `reindex` / `where`") def test_resample(self, dtype): @@ -4213,9 +4213,9 @@ def test_resample(self, dtype): func = method("resample", time="6m") expected = attach_units(func(strip_units(ds)).mean(), units) - result = func(ds).mean() + actual = func(ds).mean() - assert_equal_with_units(expected, result) + assert_equal_with_units(expected, actual) @pytest.mark.parametrize( "func", @@ -4256,9 +4256,9 @@ def test_grouped_operations(self, func, dtype): expected = attach_units( func(strip_units(ds).groupby("y"), **stripped_kwargs), units ) - result = func(ds.groupby("y")) + actual = func(ds.groupby("y")) - assert_equal_with_units(expected, result) + assert_equal_with_units(expected, actual) @pytest.mark.parametrize( "func", @@ -4319,9 +4319,9 @@ def test_content_manipulation(self, func, dtype): key: strip_units(value) for key, value in func.kwargs.items() } expected = attach_units(func(strip_units(ds), **stripped_kwargs), units) - result = func(ds) + actual = func(ds) - assert_equal_with_units(expected, result) + assert_equal_with_units(expected, actual) @pytest.mark.xfail(reason="blocked by reindex") @pytest.mark.parametrize( @@ -4377,6 +4377,6 @@ def test_merge(self, variant, unit, error, dtype): converted = convert_units(right, units) expected = attach_units(strip_units(left).merge(strip_units(converted)), units) - result = left.merge(right) + actual = left.merge(right) - assert_equal_with_units(expected, result) + assert_equal_with_units(expected, actual) From 54451303af30fc92f95c4f485e27a5179d8860f5 Mon Sep 17 00:00:00 2001 From: Keewis Date: Sun, 8 Dec 2019 15:59:06 +0100 Subject: [PATCH 31/32] fix some more test bugs --- xarray/tests/test_units.py | 30 ++++++++++++++++++++---------- 1 file changed, 20 insertions(+), 10 deletions(-) diff --git a/xarray/tests/test_units.py b/xarray/tests/test_units.py index 8356da941e6..16656e538b3 100644 --- a/xarray/tests/test_units.py +++ b/xarray/tests/test_units.py @@ -406,7 +406,11 @@ def test_apply_ufunc_dataset(dtype): def test_align_dataarray(fill_value, variant, unit, error, dtype): original_unit = unit_registry.m - variants = {"data": (unit, 1, 1), "dims": (1, unit, 1), "coords": (1, 1, unit)} + variants = { + "data": (unit, 1, 1), + "dims": (original_unit, unit, 1), + "coords": (original_unit, 1, unit), + } data_unit, dim_unit, coord_unit = variants.get(variant) array1 = np.linspace(0, 10, 2 * 5).reshape(2, 5).astype(dtype) * original_unit @@ -1152,7 +1156,9 @@ def test_where_dataarray(fill_value, unit, error, dtype): cond = x < 5 * unit_registry.m fill_value = fill_value * unit - if error is not None: + if error is not None and not ( + np.isnan(fill_value) and not isinstance(fill_value, Quantity) + ): with pytest.raises(error): xr.where(cond, x, fill_value) @@ -1194,7 +1200,9 @@ def test_where_dataset(fill_value, unit, error, dtype): cond = x < 5 * unit_registry.s fill_value = fill_value * unit - if error is not None: + if error is not None and not ( + np.isnan(fill_value) and not isinstance(fill_value, Quantity) + ): with pytest.raises(error): xr.where(cond, ds, fill_value) @@ -1374,8 +1382,10 @@ def test_repr(self, func, variant, dtype): ids=repr, ) def test_aggregation(self, func, dtype): - array = np.arange(10).astype(dtype) * unit_registry.m - data_array = xr.DataArray(data=array) + array = np.arange(10).astype(dtype) * ( + unit_registry.m if func.name != "cumprod" else unit_registry.dimensionless + ) + data_array = xr.DataArray(data=array, dims="x") # units differ based on the applied function, so we need to # first compute the units @@ -2878,7 +2888,6 @@ def test_aggregation(self, func, dtype): if func.name != "cumprod" else unit_registry.dimensionless ) - print(unit_a, unit_b) a = xr.DataArray(data=np.linspace(0, 1, 10).astype(dtype) * unit_a, dims="x") b = xr.DataArray(data=np.linspace(-1, 0, 10).astype(dtype) * unit_b, dims="x") x = xr.DataArray(data=np.arange(10).astype(dtype) * unit_registry.m, dims="x") @@ -4032,14 +4041,15 @@ def test_reindex(self, unit, error, dtype): if error is not None: with pytest.raises(error): - ds.interp(x=new_coords) + ds.reindex(x=new_coords) return - units = extract_units(ds) expected = attach_units( - strip_units(ds).reindex(x=strip_units(convert_units(new_coords, units))), - units, + strip_units(ds).reindex( + x=strip_units(convert_units(new_coords, {None: coords["x"].units})) + ), + extract_units(ds), ) actual = ds.reindex(x=new_coords) From c926d582ab3e6949400b3d7d4694cdc74f8e52e2 Mon Sep 17 00:00:00 2001 From: Keewis Date: Sun, 8 Dec 2019 16:00:13 +0100 Subject: [PATCH 32/32] update the xfail marks --- xarray/tests/test_units.py | 78 ++++++++++++++------------------------ 1 file changed, 28 insertions(+), 50 deletions(-) diff --git a/xarray/tests/test_units.py b/xarray/tests/test_units.py index 16656e538b3..f8a8a259c1f 100644 --- a/xarray/tests/test_units.py +++ b/xarray/tests/test_units.py @@ -566,7 +566,6 @@ def test_broadcast_dataset(dtype): assert_equal_with_units(expected, actual) -@pytest.mark.xfail(reason="`combine_by_coords` strips units") @pytest.mark.parametrize( "unit,error", ( @@ -637,7 +636,6 @@ def test_combine_by_coords(variant, unit, error, dtype): assert_equal_with_units(expected, actual) -@pytest.mark.xfail(reason="blocked by `where`") @pytest.mark.parametrize( "unit,error", ( @@ -646,7 +644,12 @@ def test_combine_by_coords(variant, unit, error, dtype): unit_registry.dimensionless, DimensionalityError, id="dimensionless" ), pytest.param(unit_registry.s, DimensionalityError, id="incompatible_unit"), - pytest.param(unit_registry.mm, None, id="compatible_unit"), + pytest.param( + unit_registry.mm, + None, + id="compatible_unit", + marks=pytest.mark.xfail(reason="wrong order of arguments to `where`"), + ), pytest.param(unit_registry.m, None, id="identical_unit"), ), ids=repr, @@ -1326,18 +1329,16 @@ def test_repr(self, func, variant, dtype): function("argmin"), function("max"), function("mean"), - function("median"), + pytest.param( + function("median"), + marks=pytest.mark.xfail(reason="not implemented by xarray"), + ), function("min"), pytest.param( function("prod"), marks=pytest.mark.xfail(reason="not implemented by pint yet"), ), - pytest.param( - function("sum"), - marks=pytest.mark.xfail( - reason="comparison of quantity with ndarrays in nanops not implemented" - ), - ), + function("sum"), function("std"), function("var"), function("cumsum"), @@ -1365,12 +1366,7 @@ def test_repr(self, func, variant, dtype): reason="comparison of quantity with ndarrays in nanops not implemented" ), ), - pytest.param( - method("sum"), - marks=pytest.mark.xfail( - reason="comparison of quantity with ndarrays in nanops not implemented" - ), - ), + method("sum"), method("std"), method("var"), method("cumsum"), @@ -1973,7 +1969,6 @@ def is_compatible(a, b): assert expected == actual - @pytest.mark.xfail(reason="blocked by `where`") @pytest.mark.parametrize( "unit", ( @@ -2642,7 +2637,6 @@ def test_computation_objects(self, func, dtype): assert_equal_with_units(expected, actual) - @pytest.mark.xfail(reason="blocked by `reindex` / `where`") def test_resample(self, dtype): array = np.linspace(0, 5, 10).astype(dtype) * unit_registry.m @@ -2837,9 +2831,7 @@ def test_repr(self, func, variant, dtype): reason="np.median does not work with dataset yet" ), ), - pytest.param( - function("sum"), marks=pytest.mark.xfail(reason="blocked by `where`") - ), + function("sum"), pytest.param( function("prod"), marks=pytest.mark.xfail(reason="not implemented by pint"), @@ -2863,9 +2855,7 @@ def test_repr(self, func, variant, dtype): method("min"), method("mean"), method("median"), - pytest.param( - method("sum"), marks=pytest.mark.xfail(reason="blocked by `where`") - ), + method("sum"), pytest.param( method("prod"), marks=pytest.mark.xfail(reason="not implemented by pint"), @@ -3182,13 +3172,7 @@ def test_dropna(self, dtype): @pytest.mark.parametrize( "unit", ( - pytest.param( - 1, - id="no_unit", - marks=pytest.mark.xfail( - reason="pint's isin implementation does not work well with mixed args" - ), - ), + pytest.param(1, id="no_unit"), pytest.param(unit_registry.dimensionless, id="dimensionless"), pytest.param(unit_registry.s, id="incompatible_unit"), pytest.param(unit_registry.cm, id="compatible_unit"), @@ -3234,19 +3218,7 @@ def test_isin(self, unit, dtype): assert_equal_with_units(actual, expected) @pytest.mark.parametrize( - "variant", - ( - pytest.param( - "masking", - marks=pytest.mark.xfail(reason="array(nan) is not a quantity"), - ), - "replacing_scalar", - "replacing_array", - pytest.param( - "dropping", - marks=pytest.mark.xfail(reason="array(nan) is not a quantity"), - ), - ), + "variant", ("masking", "replacing_scalar", "replacing_array", "dropping") ) @pytest.mark.parametrize( "unit,error", @@ -3458,7 +3430,6 @@ def is_compatible(a, b): assert expected == actual - @pytest.mark.xfail(reason="blocked by `where`") @pytest.mark.parametrize( "unit", ( @@ -4002,7 +3973,7 @@ def test_interp_like(self, unit, error, dtype): assert_equal_with_units(actual, expected) - @pytest.mark.xfail(reason="blocked by `where`") + @pytest.mark.xfail(reason="indexes don't support units") @pytest.mark.parametrize( "unit,error", ( @@ -4055,7 +4026,7 @@ def test_reindex(self, unit, error, dtype): assert_equal_with_units(actual, expected) - @pytest.mark.xfail(reason="blocked by `where`") + @pytest.mark.xfail(reason="indexes don't support units") @pytest.mark.parametrize( "unit,error", ( @@ -4199,7 +4170,6 @@ def test_computation_objects(self, func, dtype): assert_equal_with_units(expected, actual) - @pytest.mark.xfail(reason="blocked by `reindex` / `where`") def test_resample(self, dtype): array1 = ( np.linspace(-5, 5, 10 * 5).reshape(10, 5).astype(dtype) * unit_registry.degK @@ -4333,7 +4303,6 @@ def test_content_manipulation(self, func, dtype): assert_equal_with_units(expected, actual) - @pytest.mark.xfail(reason="blocked by reindex") @pytest.mark.parametrize( "unit,error", ( @@ -4346,7 +4315,16 @@ def test_content_manipulation(self, func, dtype): pytest.param(unit_registry.m, None, id="identical_unit"), ), ) - @pytest.mark.parametrize("variant", ("data", "dims", "coords")) + @pytest.mark.parametrize( + "variant", + ( + "data", + pytest.param( + "dims", marks=pytest.mark.xfail(reason="indexes don't support units") + ), + "coords", + ), + ) def test_merge(self, variant, unit, error, dtype): original_data_unit = unit_registry.m original_dim_unit = unit_registry.m