Repository: geopandas/geopandas
Pull request #3427 (2024-09-24 21:53:10)

CI: add 3.13 to test matrix

martinfleis: Do you think it is worth it? If I remember correctly we always tested new versions only once the migration of conda-forge was sufficiently far. 
m-richards: > Do you think it is worth it? If I remember correctly we always tested new versions only once the migration of conda-forge was sufficiently far.

I'm inclined to just wait now - I thought I'd see if it was easy to do- and by the looks it's not super simple. We don't have any compiled code so at worst I think some deprecation warnings would surface, which we can fix after 3.13 is out.
m-richards: looks like we're waiting on pyarrow 18 to come out (we could temporarily drop pyarrow stuff from the build, but it's probably easier to just wait)
jorisvandenbossche: PyArrow 18is in the RC phase, so hopefully available something like next week. But temporarily commenting it out from the env file or installing from nightly sounds fine as well.
martinfleis: I would prefer not to use nightly wheels here. It may stuck there for a while. But I am fine testing without pyarrow.
m-richards: I think I'll just leave this until pyarrow is out then - the main thing is that 3.13 is not breaking and we can see that from the last commit

Patch:
diff --git a/CHANGELOG.md b/CHANGELOG.md
index 66d9621b..582e6554 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -6,10 +6,14 @@ Notes on dependencies:
 - GeoPandas 1.1 now requires Python 3.10 or greater and pandas 2.0, numpy 1.24, pyproj 3.5,
   are now the minimum required version for these dependencies.
   Furthermore, the minimum tested version for optional dependencies has been updated to
-  fiona 1.8.21, scipy 1.9, matplotlib 3.7, mapclassify 2.5, folium 0.12 and 
+  fiona 1.8.21, scipy 1.9, matplotlib 3.7, mapclassify 2.5, folium 0.12 and
   SQLAlchemy 2.0. Older versions of these libraries may continue to work, but are no longer
   considered supported (#3371).
 
+Bug fixes:
+
+- Fix an issue that showed numpy dtypes in bbox in `to_geo_dict` and `__geo_interface__`. (#3436)
+
 ## Version 1.0.2 (???)
 
 Bug fixes:
diff --git a/ci/envs/310-minimal.yaml b/ci/envs/310-minimal.yaml
index b04427e1..7768abeb 100644
--- a/ci/envs/310-minimal.yaml
+++ b/ci/envs/310-minimal.yaml
@@ -5,7 +5,7 @@ dependencies:
   - python=3.10
   # required
   - numpy=1.24
-  - pandas=1.5
+  - pandas=2.0
   - shapely=2.0.0
   # - pyogrio=0.7.2
   - packaging
diff --git a/ci/envs/312-dev.yaml b/ci/envs/312-dev.yaml
index 278a3076..840c14f8 100644
--- a/ci/envs/312-dev.yaml
+++ b/ci/envs/312-dev.yaml
@@ -14,7 +14,7 @@ dependencies:
   - pytest-cov
   - pytest-xdist
   - fsspec
-  - pytz
+
   # optional
   #- geopy
   - SQLalchemy<2.1 # test oldest support sqlalchemy version
diff --git a/geopandas/geodataframe.py b/geopandas/geodataframe.py
index d9125b1d..4c5d76c4 100644
--- a/geopandas/geodataframe.py
+++ b/geopandas/geodataframe.py
@@ -1160,7 +1160,7 @@ properties': {'col1': 'name1'}, 'geometry': {'type': 'Point', 'coordinates': (1.
         }
 
         if show_bbox:
-            geo["bbox"] = tuple(self.total_bounds)
+            geo["bbox"] = tuple(self.total_bounds.tolist())  # tolist to avoid np dtypes
 
         return geo
 


Test patch:
diff --git a/.github/workflows/tests.yaml b/.github/workflows/tests.yaml
index 28fd5f3b..d167d253 100644
--- a/.github/workflows/tests.yaml
+++ b/.github/workflows/tests.yaml
@@ -36,6 +36,7 @@ jobs:
           - ci/envs/311-latest.yaml
           - ci/envs/312-latest.yaml
           - ci/envs/312-latest-no-pyproj.yaml
+          - ci/envs/313-latest.yaml
         include:
           - env: ci/envs/310-latest-no-pyogrio.yaml
             os: macos-latest
diff --git a/ci/envs/313-latest.yaml b/ci/envs/313-latest.yaml
new file mode 100644
index 00000000..6f6b0ddf
--- /dev/null
+++ b/ci/envs/313-latest.yaml
@@ -0,0 +1,38 @@
+name: test
+channels:
+  - conda-forge
+dependencies:
+  - python=3.13
+  # required
+  - pandas
+  - shapely
+  - pyogrio
+  - pyproj
+  - packaging
+  # testing
+  - pytest
+  - pytest-cov
+  - pytest-xdist
+  - fsspec
+  - pytz
+  # optional
+  - fiona
+  - matplotlib
+  - mapclassify
+  - folium
+  - xyzservices
+  - scipy
+  - geopy
+  - pointpats
+  - geodatasets
+  # installed in tests.yaml, because not available on windows
+  # - postgis
+  - SQLalchemy
+  - psycopg
+  - psycopg2
+  - libspatialite
+  - geoalchemy2
+  - pyarrow
+  - geoarrow-pyarrow
+  # doctest testing
+  - pytest-doctestplus
diff --git a/geopandas/io/tests/test_file.py b/geopandas/io/tests/test_file.py
index d87935a6..74857fef 100644
--- a/geopandas/io/tests/test_file.py
+++ b/geopandas/io/tests/test_file.py
@@ -6,6 +6,7 @@ import pathlib
 import shutil
 import tempfile
 import warnings
+import zoneinfo
 from collections import OrderedDict
 from packaging.version import Version
 
@@ -46,7 +47,6 @@ except ImportError:
     fiona = False
     FIONA_GE_19 = False
 
-pytz = pytest.importorskip("pytz")
 
 PYOGRIO_MARK = pytest.mark.skipif(not pyogrio, reason="pyogrio not installed")
 FIONA_MARK = pytest.mark.skipif(not fiona, reason="fiona not installed")
@@ -196,9 +196,11 @@ def test_to_file_bool(tmpdir, driver, ext, engine):
 
 
 TEST_DATE = datetime.datetime(2021, 11, 21, 1, 7, 43, 17500)
-eastern = pytz.timezone("America/New_York")
-
-datetime_type_tests = (TEST_DATE, eastern.localize(TEST_DATE))
+# from pandas 2.0, utc equality checks less stringent, forward compat with zoneinfo
+utc = datetime.timezone.utc
+eastern = zoneinfo.ZoneInfo("America/New_York")
+test_date_eastern = TEST_DATE.replace(tzinfo=eastern)
+datetime_type_tests = (TEST_DATE, test_date_eastern)
 
 
 @pytest.mark.filterwarnings(
@@ -231,11 +233,11 @@ def test_to_file_datetime(tmpdir, driver, ext, time, engine):
         expected = df["b"].dt.as_unit("ms")
     actual = df_read["b"]
     if df["b"].dt.tz is not None:
-        # US/Eastern becomes pytz.FixedOffset(-300) when read from file
+        # US/Eastern becomes a UTC-5 fixed offset when read from file
         # as GDAL only models offsets, not timezones.
         # Compare fair result in terms of UTC instead
-        expected = expected.dt.tz_convert(pytz.utc)
-        actual = actual.dt.tz_convert(pytz.utc)
+        expected = expected.dt.tz_convert(utc)
+        actual = actual.dt.tz_convert(utc)
 
     assert_series_equal(expected, actual)
 
@@ -311,10 +313,6 @@ def test_read_file_datetime_mixed_offsets(tmpdir):
     res = read_file(tempfilename)
     # Convert mixed timezones to UTC equivalent
     assert is_datetime64_any_dtype(res["date"])
-    if not PANDAS_GE_20:
-        utc = pytz.utc
-    else:
-        utc = datetime.timezone.utc
     assert res["date"].dt.tz == utc
 
 
diff --git a/geopandas/tests/test_geodataframe.py b/geopandas/tests/test_geodataframe.py
index a123f66d..c34ef948 100644
--- a/geopandas/tests/test_geodataframe.py
+++ b/geopandas/tests/test_geodataframe.py
@@ -951,6 +951,8 @@ class TestDataFrame:
         assert "bbox" in geo.keys()
         assert len(geo["bbox"]) == 4
         assert isinstance(geo["bbox"], tuple)
+        for bound in geo["bbox"]:
+            assert not isinstance(bound, np.float64)
         for feature in geo["features"]:
             assert "bbox" in feature.keys()