Repository: regionmask/regionmask

Issue:
test on python 3.12
All dependencies are ready and the tests pass. So it should just be a matter of updating everything that is needed.

Comments:

Patch:
diff --git a/.github/workflows/ci.yaml b/.github/workflows/ci.yaml
index ac4facf..b9765a1 100644
--- a/.github/workflows/ci.yaml
+++ b/.github/workflows/ci.yaml
@@ -23,7 +23,7 @@ jobs:
       matrix:
         os: ["ubuntu-latest"]
         # Bookend python versions
-        python-version: ["3.9", "3.11"]
+        python-version: ["3.9", "3.12"]
     steps:
       - uses: actions/checkout@v4
         with:
diff --git a/.github/workflows/linting.yaml b/.github/workflows/linting.yaml
index 6c2b3d6..e5a3b70 100644
--- a/.github/workflows/linting.yaml
+++ b/.github/workflows/linting.yaml
@@ -23,7 +23,7 @@ jobs:
       matrix:
         os: ["ubuntu-latest"]
         # Bookend python versions
-        python-version: ["3.11"]
+        python-version: ["3.12"]
     steps:
       - uses: actions/checkout@v4
         with:
diff --git a/.github/workflows/upstream-dev-ci.yaml b/.github/workflows/upstream-dev-ci.yaml
index 0841085..2f11651 100644
--- a/.github/workflows/upstream-dev-ci.yaml
+++ b/.github/workflows/upstream-dev-ci.yaml
@@ -33,7 +33,7 @@ jobs:
     strategy:
       fail-fast: false
       matrix:
-        python-version: ["3.11"]
+        python-version: ["3.12"]
     steps:
       - uses: actions/checkout@v4
         with:
diff --git a/CHANGELOG.rst b/CHANGELOG.rst
index 5bcd1f9..39baca4 100644
--- a/CHANGELOG.rst
+++ b/CHANGELOG.rst
@@ -26,12 +26,15 @@ Breaking Changes
 Enhancements
 ~~~~~~~~~~~~
 
+- Add python 3.12 to list of supported versions (:pull:`494`).
+
 New regions
 ~~~~~~~~~~~
 
 Bug Fixes
 ~~~~~~~~~
 
+- Ensure correct masks are created for `float32` coordinates (:issue:`489`, :pull:`493`).
 - Fixed the default value of ``overlap`` of :py:func:`from_geopandas` to ``None`` (:issue:`453`, :pull:`470`).
 
 Docs
diff --git a/ci/requirements/docs.yml b/ci/requirements/docs.yml
index af14e8e..40d3cea 100644
--- a/ci/requirements/docs.yml
+++ b/ci/requirements/docs.yml
@@ -5,7 +5,7 @@ channels:
   - nodefaults
 
 dependencies:
-  - python=3.11
+  - python=3.12
 # regionmask dependencies
   - cartopy
   - geopandas
diff --git a/regionmask/core/mask.py b/regionmask/core/mask.py
index cf1f85e..eba2571 100644
--- a/regionmask/core/mask.py
+++ b/regionmask/core/mask.py
@@ -204,8 +204,8 @@ def _mask(
                 "be converted to degree?"
             )
 
-    lon_arr = np.asarray(lon)
-    lat_arr = np.asarray(lat)
+    lon_arr = np.asarray(lon, dtype=float)
+    lat_arr = np.asarray(lat, dtype=float)
 
     # automatically detect whether wrapping is necessary
     if wrap_lon is None:
diff --git a/setup.cfg b/setup.cfg
index 32ae80f..acdf717 100644
--- a/setup.cfg
+++ b/setup.cfg
@@ -17,6 +17,7 @@ classifiers =
     Programming Language :: Python :: 3.9
     Programming Language :: Python :: 3.10
     Programming Language :: Python :: 3.11
+    Programming Language :: Python :: 3.12
     Topic :: Scientific/Engineering
     Topic :: Scientific/Engineering :: Atmospheric Science
     Topic :: Scientific/Engineering :: GIS


Test patch:
diff --git a/regionmask/tests/test_mask.py b/regionmask/tests/test_mask.py
index 8996f0e..b279a1c 100644
--- a/regionmask/tests/test_mask.py
+++ b/regionmask/tests/test_mask.py
@@ -964,12 +964,29 @@ def test_mask_whole_grid(method, regions, lon):
     mask = regions.mask(lon, lat, method=method)
 
     assert (mask == 0).all()
+    assert mask.lon.dtype == int
+    assert mask.lat.dtype == int
 
     # with wrap_lon=False the edges are not masked
     mask = regions.mask(lon, lat, method=method, wrap_lon=False)
     assert mask.sel(lat=-90).isnull().all()
 
 
+@pytest.mark.parametrize("method", MASK_METHODS)
+@pytest.mark.parametrize("regions", [r_GLOB_180, r_GLOB_360])
+@pytest.mark.parametrize("lon", [lon180, lon360])
+def test_mask_whole_grid_float32(method, regions, lon):
+
+    lat = np.arange(90, -91, -10, dtype=np.float32)
+    lon = lon.astype(np.float32)  # creates a copy
+    mask = regions.mask(lon, lat, method=method)
+
+    assert (mask == 0).all()
+
+    assert mask.lon.dtype == np.float32
+    assert mask.lat.dtype == np.float32
+
+
 @pytest.mark.parametrize("regions", [r_GLOB_180, r_GLOB_360])
 @pytest.mark.parametrize("lon", [lon180, lon360])
 def test_mask_whole_grid_nan_lon(regions, lon):