diff --git a/cf/data/data.py b/cf/data/data.py index e91d6df03b..35591315a1 100644 --- a/cf/data/data.py +++ b/cf/data/data.py @@ -3144,7 +3144,7 @@ def _combined_units(self, data1, method, inplace): return data0, data1, _units_1 else: # units1 is defined and is not dimensionless - if data0._size > 1: + if data0.size > 1: raise ValueError( "Can only raise units to the power of a single " "value at a time. Asking to raise to the power of " @@ -3220,7 +3220,7 @@ def _combined_units(self, data1, method, inplace): return data0, data1, _units_1 else: # units0 is defined and is not dimensionless - if data1._size > 1: + if data1.size > 1: raise ValueError( "Can only raise units to the power of a single " "value at a time. Asking to raise to the power of " @@ -3372,6 +3372,13 @@ def _binary_operation(self, other, method): elif inplace: # Find non-in-place equivalent operator (remove 'i') equiv_method = method[:2] + method[3:] + # Need to add check in here to ensure that the operation is not + # trying to cast in a way which is invalid. For example, doing + # [an int array] ** float value = [a float array] is fine, but + # doing this in-place would try to chance an int array into a + # float one, which isn't valid casting. Therefore we need to + # catch cases where __i__ isn't possible even if ____ + # is due to datatype consistency rules. result = getattr(dx0, equiv_method)(dx1) else: result = getattr(dx0, method)(dx1) @@ -8496,7 +8503,7 @@ def datum(self, *index): index = (slice(-1, None),) * self.ndim elif isinstance(index, int): if index < 0: - index += self._size + index += self.size index = np.unravel_index(index, self.shape) elif len(index) == self.ndim: diff --git a/cf/test/test_Data.py b/cf/test/test_Data.py index 196cf77865..9014449274 100644 --- a/cf/test/test_Data.py +++ b/cf/test/test_Data.py @@ -293,7 +293,7 @@ def test_Data_equals(self): self.assertTrue(sa2.equals(sa2.copy())) # Unlike for numeric types, for string-like data as long as the data # is the same consider the arrays equal, even if the dtype differs. - # TODO DASK: this behaviour will be added via cfdm, test fails for now + # TODODASK: this behaviour will be added via cfdm, test fails for now # ## self.assertTrue(sa1.equals(sa2)) sa3_data = sa2_data.astype("S5") sa3 = cf.Data(sa3_data, "m", chunks=mask_test_chunksize) @@ -2004,14 +2004,10 @@ def test_Data_BINARY_AND_UNARY_OPERATORS(self): self.assertTrue( (d // x).equals(cf.Data(a0 // x, "m"), verbose=1), message ) - # TODODASK SB: re-instate this once _combined_units is sorted, - # presently fails with error: - # AttributeError: 'Data' object has no attribute '_size' - # - # message = "Failed in {!r}**{}".format(d, x) - # self.assertTrue( - # (d ** x).equals(cf.Data(a0 ** x, "m2"), verbose=1), message - # ) + message = "Failed in {!r}**{}".format(d, x) + self.assertTrue( + (d**x).equals(cf.Data(a0**x, "m2"), verbose=1), message + ) message = "Failed in {!r}.__truediv__{}".format(d, x) self.assertTrue( d.__truediv__(x).equals( @@ -2124,9 +2120,10 @@ def test_Data_BINARY_AND_UNARY_OPERATORS(self): e.equals(cf.Data(a, "m"), verbose=1), message ) - # TODODASK SB: re-instate this once _combined_units is sorted, - # presently fails with error, as with __pow__: - # AttributeError: 'Data' object has no attribute '_size' + # TODO: this test fails due to casting issues. It is actually + # testing against expected behaviour with contradicts that of + # NumPy so we might want to change the logic: see Issue 435, + # github.com/NCAS-CMS/cf-python/issues/435. Skip for now. # a = a0.copy() # try: # a **= x