Repository: enthought/chaco

Issue:
Warnings in Python 3.8 `test_image_plot`
**Problem Description**

A number of warnings are generated during test runs under Python 3.8.

A `list` being set on a `Tuple` trait:
```
test_horizontal_bottom_left (chaco.plots.tests.test_image_plot.TestResultImage) ... /home/runner/.edm/envs/chaco-test-3.8-pyside6/lib/python3.8/site-packages/traits/trait_types.py:4244: DeprecationWarning: In the future, lists will no longer be accepted by the Tuple trait type. Lists should be converted to tuples prior to validation.
  return trait_type_instance.validate(obj, name, value)
ok
```

A bad division somewhere:
```
test_resize_to_zero (chaco.plots.tests.test_image_plot.TestResultImage) ... /home/runner/.edm/envs/chaco-test-3.8-pyside6/lib/python3.8/site-packages/chaco/axis.py:710: RuntimeWarning: invalid value encountered in true_divide
  self._axis_pixel_vector = self._axis_vector / sqrt(
ok
```

A deprecated NumPy function:
```
/home/runner/.edm/envs/chaco-test-3.8-pyside6/lib/python3.8/site-packages/chaco/plots/tests/test_image_plot.py:40: DeprecationWarning: This function is deprecated. Please call randint(0, 255 + 1) instead
  IMAGE = np.random.random_integers(0, 255, size=([10](https://github.com/enthought/chaco/actions/runs/3994687826/jobs/6852683234#step:9:11)0, 200)).astype(np.uint8)
```

There is a similar warning in `test_data_label_tool`:

```
/home/runner/.edm/envs/chaco-test-3.8-pyside6/lib/python3.8/site-packages/chaco/tools/tests/test_data_label_tool.py:13: DeprecationWarning: This function is deprecated. Please call randint(0, 255 + 1) instead
  IMAGE = np.random.random_integers(0, 255, size=(100, 200)).astype(np.uint8)
```

It is possible that these warnings are more widespread but we are only seeing the first occurrence.

**Reproduction Steps:**

Run the tests using edmtool with Python 3.8

**Expected behavior:**

No Warnings.

**OS, Python version:** All, Python 3.8


Discussion:

Resolving patch:
diff --git a/chaco/plots/image_plot.py b/chaco/plots/image_plot.py
--- a/chaco/plots/image_plot.py
+++ b/chaco/plots/image_plot.py
@@ -22,13 +22,12 @@
 from traits.api import (
     Bool,
     Enum,
+    Float,
     Instance,
-    List,
     Range,
     Tuple,
     Property,
     cached_property,
-    Union,
 )
 from kiva.agg import GraphicsContextArray
 
@@ -84,7 +83,7 @@ class ImagePlot(Base2DPlot):
 
     # Tuple-defined rectangle (x, y, dx, dy) in screen space in which the
     # **_cached_image** is to be drawn.
-    _cached_dest_rect = Union(Tuple, List, transient=True)
+    _cached_dest_rect = Tuple(Float, Float, Float, Float, transient=True)
 
     # Bool indicating whether the origin is top-left or bottom-right.
     # The name "principal diagonal" is borrowed from linear algebra.
@@ -285,7 +284,7 @@ def _compute_cached_image(self, data=None, mapper=None):
 
         # Update cached image and rectangle.
         self._cached_image = self._kiva_array_from_numpy_array(data)
-        self._cached_dest_rect = screen_rect
+        self._cached_dest_rect = tuple(screen_rect)
         self._image_cache_valid = True
 
     def _kiva_array_from_numpy_array(self, data):
diff --git a/chaco/tools/pan_tool.py b/chaco/tools/pan_tool.py
--- a/chaco/tools/pan_tool.py
+++ b/chaco/tools/pan_tool.py
@@ -231,8 +231,10 @@ def panning_mouse_move(self, event):
                     newlow = mapper.map_data(screenlow + screen_delta)
 
                 # Use .set_bounds() so that we don't generate two range_changed
-                # events on the DataRange
-                mapper.range.set_bounds(newlow, newhigh)
+                # events on the DataRange.
+                # Do an explicit conversion to float because raw values may not
+                # be floating-point types, which makes NumPy unhappy (#854).
+                mapper.range.set_bounds(float(newlow), float(newhigh))
 
         event.handled = True
 


Test patch:
diff --git a/chaco/plots/tests/test_image_plot.py b/chaco/plots/tests/test_image_plot.py
--- a/chaco/plots/tests/test_image_plot.py
+++ b/chaco/plots/tests/test_image_plot.py
@@ -37,7 +37,7 @@
 # The Quartz backend rescales pixel values, so use a higher threshold.
 MAX_RMS_ERROR = 16 if ETSConfig.kiva_backend == "quartz" else 1
 
-IMAGE = np.random.random_integers(0, 255, size=(100, 200)).astype(np.uint8)
+IMAGE = np.random.randint(0, 256, size=(100, 200)).astype(np.uint8)
 RGB = np.dstack([IMAGE] * 3)
 # Rendering adds rows and columns for some reason.
 TRIM_RENDERED = (slice(1, -1), slice(1, -1), 0)
diff --git a/chaco/tools/tests/test_data_label_tool.py b/chaco/tools/tests/test_data_label_tool.py
--- a/chaco/tools/tests/test_data_label_tool.py
+++ b/chaco/tools/tests/test_data_label_tool.py
@@ -10,7 +10,7 @@
 from chaco.api import ArrayPlotData, DataLabel, Plot
 from chaco.tools.api import DataLabelTool
 
-IMAGE = np.random.random_integers(0, 255, size=(100, 200)).astype(np.uint8)
+IMAGE = np.random.randint(0, 256, size=(100, 200)).astype(np.uint8)
 RGB = np.dstack([IMAGE] * 3)