From aed3f6cd299d382a63bbf679f75b2005466a6af1 Mon Sep 17 00:00:00 2001
From: "Sadie L. Bartholomew" <sadie.bartholomew@ncas.ac.uk>
Date: Thu, 11 Aug 2022 12:08:31 +0100
Subject: [PATCH 1/5] test_Data: convert lone bad form of 'TODODASK' dev
 markers

---
 cf/test/test_Data.py | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/cf/test/test_Data.py b/cf/test/test_Data.py
index 196cf77865..bc2e9908b6 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)

From ace47a537f4d5a114b01c3df55aa48cc021f36be Mon Sep 17 00:00:00 2001
From: "Sadie L. Bartholomew" <sadie.bartholomew@ncas.ac.uk>
Date: Thu, 11 Aug 2022 12:17:50 +0100
Subject: [PATCH 2/5] Reinstate test_Data_BINARY_AND_UNARY_OPERATORS __pow__
 test cases

---
 cf/test/test_Data.py | 39 ++++++++++++++++-----------------------
 1 file changed, 16 insertions(+), 23 deletions(-)

diff --git a/cf/test/test_Data.py b/cf/test/test_Data.py
index bc2e9908b6..8bfa2b9694 100644
--- a/cf/test/test_Data.py
+++ b/cf/test/test_Data.py
@@ -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,21 +2120,18 @@ 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'
-                # a = a0.copy()
-                # try:
-                #     a **= x
-                # except TypeError:
-                #     pass
-                # else:
-                #     e = d.copy()
-                #     e **= x
-                #     message = "Failed in {!r}**={}".format(d, x)
-                #     self.assertTrue(
-                #         e.equals(cf.Data(a, "m2"), verbose=1), message
-                #     )
+                a = a0.copy()
+                try:
+                    a **= x
+                except TypeError:
+                    pass
+                else:
+                    e = d.copy()
+                    e **= x
+                    message = "Failed in {!r}**={}".format(d, x)
+                    self.assertTrue(
+                        e.equals(cf.Data(a, "m2"), verbose=1), message
+                    )
 
                 a = a0.copy()
                 try:

From a6eb3e0ef828d09cf15671e1221e7ce0c46a4098 Mon Sep 17 00:00:00 2001
From: "Sadie L. Bartholomew" <sadie.bartholomew@ncas.ac.uk>
Date: Thu, 11 Aug 2022 14:07:35 +0100
Subject: [PATCH 3/5] Data module: Data._size -> Data.size property conversion

---
 cf/data/data.py | 6 +++---
 1 file changed, 3 insertions(+), 3 deletions(-)

diff --git a/cf/data/data.py b/cf/data/data.py
index e91d6df03b..f768d4704d 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 "
@@ -8496,7 +8496,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:

From 27c15b28025189f7e2df6aaaad0f6bfa72bb1e74 Mon Sep 17 00:00:00 2001
From: "Sadie L. Bartholomew" <sadie.bartholomew@ncas.ac.uk>
Date: Fri, 12 Aug 2022 17:11:14 +0100
Subject: [PATCH 4/5] Data._binary_operation: summarise issue raised by
 __ipow__ test

---
 cf/data/data.py | 7 +++++++
 1 file changed, 7 insertions(+)

diff --git a/cf/data/data.py b/cf/data/data.py
index f768d4704d..35591315a1 100644
--- a/cf/data/data.py
+++ b/cf/data/data.py
@@ -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<op>__ isn't possible even if __<op>__
+            # is due to datatype consistency rules.
             result = getattr(dx0, equiv_method)(dx1)
         else:
             result = getattr(dx0, method)(dx1)

From 61a779b4efdc591aec572dc55d15126e8e64ee00 Mon Sep 17 00:00:00 2001
From: "Sadie L. Bartholomew" <sadie.bartholomew@ncas.ac.uk>
Date: Fri, 12 Aug 2022 19:17:49 +0100
Subject: [PATCH 5/5] test_Data: comment out a problematic test case for now

---
 cf/test/test_Data.py | 28 ++++++++++++++++------------
 1 file changed, 16 insertions(+), 12 deletions(-)

diff --git a/cf/test/test_Data.py b/cf/test/test_Data.py
index 8bfa2b9694..9014449274 100644
--- a/cf/test/test_Data.py
+++ b/cf/test/test_Data.py
@@ -2120,18 +2120,22 @@ def test_Data_BINARY_AND_UNARY_OPERATORS(self):
                         e.equals(cf.Data(a, "m"), verbose=1), message
                     )
 
-                a = a0.copy()
-                try:
-                    a **= x
-                except TypeError:
-                    pass
-                else:
-                    e = d.copy()
-                    e **= x
-                    message = "Failed in {!r}**={}".format(d, x)
-                    self.assertTrue(
-                        e.equals(cf.Data(a, "m2"), verbose=1), message
-                    )
+                # 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
+                # except TypeError:
+                #     pass
+                # else:
+                #     e = d.copy()
+                #     e **= x
+                #     message = "Failed in {!r}**={}".format(d, x)
+                #     self.assertTrue(
+                #         e.equals(cf.Data(a, "m2"), verbose=1), message
+                #     )
 
                 a = a0.copy()
                 try:
