[Git][debian-gis-team/python-geopandas][master] 6 commits: New upstream version 1.1.3

Bas Couwenberg (@sebastic) gitlab at salsa.debian.org
Tue Mar 10 04:49:23 GMT 2026



Bas Couwenberg pushed to branch master at Debian GIS Project / python-geopandas


Commits:
5a5c4284 by Bas Couwenberg at 2026-03-10T05:28:55+01:00
New upstream version 1.1.3
- - - - -
b06069b4 by Bas Couwenberg at 2026-03-10T05:29:18+01:00
Update upstream source from tag 'upstream/1.1.3'

Update to upstream version '1.1.3'
with Debian dir 9e7f6a079d6427865647d36d5f7cf96bcc2e1f20
- - - - -
57577700 by Bas Couwenberg at 2026-03-10T05:34:36+01:00
New upstream release.

- - - - -
e5c2185a by Bas Couwenberg at 2026-03-10T05:38:58+01:00
Add python3-pointpats to build dependencies.

- - - - -
28bb716c by Bas Couwenberg at 2026-03-10T05:40:47+01:00
Refresh patches.

- - - - -
2eeecb63 by Bas Couwenberg at 2026-03-10T05:40:57+01:00
Set distribution to unstable.

- - - - -


22 changed files:

- .github/workflows/release_to_pypi.yml → .github/workflows/release.yml
- .github/workflows/tests.yaml
- CHANGELOG.md
- debian/changelog
- debian/control
- debian/patches/pandas2_compat.patch
- geopandas/_compat.py
- geopandas/_version.py
- geopandas/array.py
- geopandas/base.py
- geopandas/geodataframe.py
- geopandas/geoseries.py
- geopandas/io/sql.py
- geopandas/io/tests/test_sql.py
- geopandas/tests/test_crs.py
- geopandas/tests/test_geodataframe.py
- geopandas/tests/test_geom_methods.py
- geopandas/tests/test_geoseries.py
- geopandas/tests/test_op_output_types.py
- geopandas/tests/test_sindex.py
- geopandas/tools/clip.py
- pyproject.toml


Changes:

=====================================
.github/workflows/release_to_pypi.yml → .github/workflows/release.yml
=====================================
@@ -9,6 +9,11 @@ jobs:
   build-n-publish:
     name: Build and publish geopandas to PyPI
     runs-on: ubuntu-latest
+    environment:
+      name: pypi
+      url: https://pypi.org/p/geopandas
+    permissions:
+      id-token: write  # IMPORTANT: this permission is mandatory for trusted publishing
 
     steps:
       - name: Checkout source
@@ -27,9 +32,6 @@ jobs:
 
       - name: Publish distribution to PyPI
         uses: pypa/gh-action-pypi-publish at release/v1
-        with:
-          user: __token__
-          password: ${{ secrets.PYPI_API_TOKEN }}
 
       - name: Create GitHub Release
         id: create_release


=====================================
.github/workflows/tests.yaml
=====================================
@@ -58,7 +58,6 @@ jobs:
           - env: ci/envs/312-dev.yaml
             os: ubuntu-latest
             dev: true
-            pandas_future_infer_string: "1"
 
     steps:
       - uses: actions/checkout at v4
@@ -76,8 +75,6 @@ jobs:
           micromamba list
 
       - name: Test
-        env:
-          PANDAS_FUTURE_INFER_STRING: ${{ matrix.pandas_future_infer_string || '0' }}
         run: |
           pytest -v -r a -n auto --color=yes --cov=geopandas --cov-append --cov-report term-missing --cov-report xml geopandas/
 


=====================================
CHANGELOG.md
=====================================
@@ -1,5 +1,17 @@
 # Changelog
 
+## Version 1.1.3 (March 10, 2026)
+
+Bug fixes:
+- Improved compatibility with pandas 3.0 Copy-on-Write feature, making use of deferred copies where possible (#3298, #3711).
+- Fix `GeoSeries.sample_points` not accepting list-like `size` when generating points using
+  `pointpaterns` (#3710).
+- Fix `from_wkt/wkb` to correctly handle missing values with pandas 3 (where the new `str` dtype is used) (#3714).
+- Fix `to_postgis` to correctly handle missing values with pandas 3 (where the new `str` dtype is used) (#3722).
+- Using `loc` to assign column values to a new row index now correctly preserves the column CRS and geometry dtype
+  on pandas 3.1, due to an upstream bug fix (#3741, Pandas #62523)
+- Random states in ``pointpats`` methods of ``sample_points`` can now be fixed with ``rng`` (#3737).
+
 ## Version 1.1.2 (December 22, 2025)
 
 Bug fixes:
@@ -1057,7 +1069,7 @@ New features and improvements:
 - Addition of a ``GeoDataFrame.rename_geometry`` method to easily rename the active geometry column (#1053).
 - Addition of ``geopandas.show_versions()`` function, which can be used to give an overview of the installed libraries in bug reports (#899).
 - The ``legend_kwds`` keyword of the ``plot()`` method can now also be used to specify keywords for the color bar (#1102).
-- Performance improvement in the ``sjoin()`` operation by re-using existing spatial index of the input dataframes, if available (#789).
+- Performance improvement in the ``sjoin()`` operation by reusing existing spatial index of the input dataframes, if available (#789).
 - Updated documentation to work with latest version of geoplot and contextily (#1044, #1088).
 - A new ``geopandas.options`` configuration, with currently a single option to control the display precision of the coordinates (``options.display_precision``). The default is now to show less coordinates (3 for projected and 5 for geographic coordinates), but the default can be overridden with the option.
 


=====================================
debian/changelog
=====================================
@@ -1,3 +1,12 @@
+python-geopandas (1.1.3-1) unstable; urgency=medium
+
+  * Team upload.
+  * New upstream release.
+  * Add python3-pointpats to build dependencies.
+  * Refresh patches.
+
+ -- Bas Couwenberg <sebastic at debian.org>  Tue, 10 Mar 2026 05:40:50 +0100
+
 python-geopandas (1.1.2-2) unstable; urgency=medium
 
   [ Bas Couwenberg ]


=====================================
debian/control
=====================================
@@ -20,6 +20,7 @@ Build-Depends: debhelper-compat (= 13),
                python3-numpy,
                python3-numpydoc,
                python3-pandas,
+               python3-pointpats,
                python3-psycopg2,
                python3-pyogrio,
                python3-pyproj,


=====================================
debian/patches/pandas2_compat.patch
=====================================
@@ -7,7 +7,7 @@ Applied-Upstream: https://github.com/geopandas/geopandas/commit/45fbc51ea309a9c9
 
 --- a/geopandas/tests/test_geom_methods.py
 +++ b/geopandas/tests/test_geom_methods.py
-@@ -1675,7 +1675,7 @@ class TestGeomMethods:
+@@ -1683,7 +1683,7 @@ class TestGeomMethods:
              names=[index_name, None],
          )
          expected_df = expected_df.set_index(expected_index)
@@ -16,7 +16,7 @@ Applied-Upstream: https://github.com/geopandas/geopandas/commit/45fbc51ea309a9c9
  
      @pytest.mark.parametrize("index_name", [None, "test"])
      def test_explode_geodataframe_level_1(self, index_name):
-@@ -1694,7 +1694,7 @@ class TestGeomMethods:
+@@ -1702,7 +1702,7 @@ class TestGeomMethods:
              names=[index_name, None],
          )
          expected_df = expected_df.set_index(expected_index)
@@ -25,7 +25,7 @@ Applied-Upstream: https://github.com/geopandas/geopandas/commit/45fbc51ea309a9c9
  
      @pytest.mark.parametrize("index_name", [None, "test"])
      def test_explode_geodataframe_no_multiindex(self, index_name):
-@@ -1800,7 +1800,7 @@ class TestGeomMethods:
+@@ -1808,7 +1808,7 @@ class TestGeomMethods:
              names=["first", "second", None],
          )
          expected_df = expected_df.set_index(expected_index)
@@ -34,7 +34,7 @@ Applied-Upstream: https://github.com/geopandas/geopandas/commit/45fbc51ea309a9c9
  
      @pytest.mark.parametrize("outer_index", [1, (1, 2), "1"])
      def test_explode_pandas_multi_index_false(self, outer_index):
-@@ -1901,7 +1901,7 @@ class TestGeomMethods:
+@@ -1909,7 +1909,7 @@ class TestGeomMethods:
              geometry=expected_geometry,
              index=expected_index,
          )
@@ -43,7 +43,7 @@ Applied-Upstream: https://github.com/geopandas/geopandas/commit/45fbc51ea309a9c9
  
      def test_explode_order_no_multi(self):
          df = GeoDataFrame(
-@@ -1919,7 +1919,7 @@ class TestGeomMethods:
+@@ -1927,7 +1927,7 @@ class TestGeomMethods:
              geometry=[Point(0, x) for x in range(3)],
              index=expected_index,
          )
@@ -52,7 +52,7 @@ Applied-Upstream: https://github.com/geopandas/geopandas/commit/45fbc51ea309a9c9
  
      def test_explode_order_mixed(self):
          df = GeoDataFrame(
-@@ -1947,7 +1947,7 @@ class TestGeomMethods:
+@@ -1955,7 +1955,7 @@ class TestGeomMethods:
              geometry=expected_geometry,
              index=expected_index,
          )
@@ -61,7 +61,7 @@ Applied-Upstream: https://github.com/geopandas/geopandas/commit/45fbc51ea309a9c9
  
      def test_explode_duplicated_index(self):
          df = GeoDataFrame(
-@@ -1975,7 +1975,7 @@ class TestGeomMethods:
+@@ -1983,7 +1983,7 @@ class TestGeomMethods:
              geometry=expected_geometry,
              index=expected_index,
          )
@@ -70,7 +70,7 @@ Applied-Upstream: https://github.com/geopandas/geopandas/commit/45fbc51ea309a9c9
  
      @pytest.mark.parametrize("geom_col", ["geom", "geometry"])
      def test_explode_geometry_name(self, geom_col):
-@@ -2070,7 +2070,7 @@ class TestGeomMethods:
+@@ -2078,7 +2078,7 @@ class TestGeomMethods:
                  ]
              ),
          )


=====================================
geopandas/_compat.py
=====================================
@@ -13,7 +13,8 @@ PANDAS_GE_202 = Version(pd.__version__) >= Version("2.0.2")
 PANDAS_GE_21 = Version(pd.__version__) >= Version("2.1.0")
 PANDAS_GE_22 = Version(pd.__version__) >= Version("2.2.0")
 PANDAS_GE_23 = Version(pd.__version__) >= Version("2.3.0")
-PANDAS_GE_30 = Version(pd.__version__) >= Version("3.0.0.dev0")
+PANDAS_GE_30 = Version(pd.__version__) >= Version("3.0.0")
+PANDAS_GE_31 = Version(pd.__version__) >= Version("3.1.0.dev0")
 PANDAS_INFER_STR = PANDAS_GE_23 and pd.options.future.infer_string
 
 


=====================================
geopandas/_version.py
=====================================
@@ -25,9 +25,9 @@ def get_keywords() -> Dict[str, str]:
     # setup.py/versioneer.py will grep for the variable names, so they must
     # each be defined on a line of their own. _version.py will just call
     # get_keywords().
-    git_refnames = " (tag: v1.1.2, 1.1.x)"
-    git_full = "81214bf9f3eaba9f5fdcfd141ae8d16fa17fd860"
-    git_date = "2025-12-22 22:04:52 +0100"
+    git_refnames = " (tag: v1.1.3, 1.1.x)"
+    git_full = "f5fe3ff5f0e473603cd0e81673d9f1f300f4975d"
+    git_date = "2026-03-10 08:34:35 +1100"
     keywords = {"refnames": git_refnames, "full": git_full, "date": git_date}
     return keywords
 


=====================================
geopandas/array.py
=====================================
@@ -219,6 +219,8 @@ def from_wkb(data, crs=None, on_invalid="raise"):
           without a warning. Requires GEOS >= 3.11 and shapely >= 2.1.
 
     """
+    if isinstance(data, ExtensionArray):
+        data = data.to_numpy(na_value=None)
     return GeometryArray(shapely.from_wkb(data, on_invalid=on_invalid), crs=crs)
 
 
@@ -251,6 +253,8 @@ def from_wkt(data, crs=None, on_invalid="raise"):
           without a warning. Requires GEOS >= 3.11 and shapely >= 2.1.
 
     """
+    if isinstance(data, ExtensionArray):
+        data = data.to_numpy(na_value=None)
     return GeometryArray(shapely.from_wkt(data, on_invalid=on_invalid), crs=crs)
 
 
@@ -423,6 +427,18 @@ class GeometryArray(ExtensionArray):
     def __getitem__(self, idx):
         if isinstance(idx, numbers.Integral):
             return self._data[idx]
+        elif (
+            isinstance(idx, slice)
+            and idx.start is None
+            and idx.stop is None
+            and idx.step is None
+        ):
+            # special case of a full slice -> preserve the sindex
+            # (to ensure view() preserves it as well)
+            result = GeometryArray(self._data[idx], crs=self.crs)
+            result._sindex = self._sindex
+            return result
+
         # array-like, slice
         # validate and convert IntegerArray/BooleanArray
         # to numpy array, pass-through non-array-like indexers


=====================================
geopandas/base.py
=====================================
@@ -6446,15 +6446,27 @@ GeometryCollection
                     f" available random sampling methods."
                 )
             sample_function = getattr(pointpats.random, method)
-            result = self.geometry.apply(
-                lambda x: (
-                    points_from_xy(
-                        *sample_function(x, size=size, **kwargs).T
-                    ).union_all()
-                    if not (x.is_empty or x is None or "Polygon" not in x.geom_type)
-                    else MultiPoint()
-                ),
-            )
+            if pd.api.types.is_list_like(size):
+                result = [
+                    (
+                        points_from_xy(
+                            *sample_function(x, size=s, rng=rng, **kwargs).T
+                        ).union_all()
+                        if not (x.is_empty or x is None or "Polygon" not in x.geom_type)
+                        else MultiPoint()
+                    )
+                    for x, s in zip(self.geometry, size)
+                ]
+            else:
+                result = self.geometry.apply(
+                    lambda x: (
+                        points_from_xy(
+                            *sample_function(x, size=size, rng=rng, **kwargs).T
+                        ).union_all()
+                        if not (x.is_empty or x is None or "Polygon" not in x.geom_type)
+                        else MultiPoint()
+                    ),
+                )
 
         return GeoSeries(result, name="sampled_points", crs=self.crs, index=self.index)
 


=====================================
geopandas/geodataframe.py
=====================================
@@ -1264,7 +1264,7 @@ properties': {'col1': 'name1'}, 'geometry': {'type': 'Point', 'coordinates': (1.
         DataFrame
             geometry columns are encoded to WKB
         """
-        df = DataFrame(self.copy())
+        df = DataFrame(self.copy(deep=not PANDAS_GE_30))
 
         # Encode all geometry columns to WKB
         for col in df.columns[df.dtypes == "geometry"]:
@@ -1286,7 +1286,7 @@ properties': {'col1': 'name1'}, 'geometry': {'type': 'Point', 'coordinates': (1.
         DataFrame
             geometry columns are encoded to WKT
         """
-        df = DataFrame(self.copy())
+        df = DataFrame(self.copy(deep=not PANDAS_GE_30))
 
         # Encode all geometry columns to WKT
         for col in df.columns[df.dtypes == "geometry"]:
@@ -1730,7 +1730,7 @@ default 'snappy'
 
         """
         if not inplace:
-            df = self.copy()
+            df = self.copy(deep=not PANDAS_GE_30)
         else:
             df = self
         df.geometry = df.geometry.set_crs(
@@ -1838,7 +1838,7 @@ default 'snappy'
         if inplace:
             df = self
         else:
-            df = self.copy()
+            df = self.copy(deep=not PANDAS_GE_30)
         geom = df.geometry.to_crs(crs=crs, epsg=epsg)
         df.geometry = geom
         if not inplace:


=====================================
geopandas/geoseries.py
=====================================
@@ -603,7 +603,7 @@ class GeoSeries(GeoPandasBase, Series):
                 data = data.reindex(index)
             else:
                 index = data.index
-            data = data.values
+            data = data.to_numpy(na_value=None)
         return cls(
             from_wkb_or_wkt_function(data, crs=crs, on_invalid=on_invalid),
             index=index,
@@ -1165,7 +1165,7 @@ class GeoSeries(GeoPandasBase, Series):
                 "transform the geometries, use 'GeoSeries.to_crs' instead."
             )
         if not inplace:
-            result = self.copy()
+            result = self.copy(deep=not compat.PANDAS_GE_30)
         else:
             result = self
         result.array.crs = crs


=====================================
geopandas/io/sql.py
=====================================
@@ -233,7 +233,7 @@ def _get_geometry_type(gdf):
     has_curve = False
 
     for gt in geom_types:
-        if gt is None:
+        if pd.isna(gt):
             continue
         elif "LinearRing" in gt:
             has_curve = True
@@ -242,7 +242,7 @@ def _get_geometry_type(gdf):
         if has_curve:
             target_geom_type = "LINESTRING"
         else:
-            if geom_types[0] is None:
+            if pd.isna(geom_types[0]):
                 raise ValueError("No valid geometries in the data.")
             else:
                 target_geom_type = geom_types[0].upper()


=====================================
geopandas/io/tests/test_sql.py
=====================================
@@ -179,6 +179,23 @@ def df_mixed_single_and_multi():
     return df
 
 
+ at pytest.fixture
+def df_mixed_none_geometry():
+    from shapely.geometry import MultiPolygon
+
+    df = geopandas.GeoDataFrame(
+        {
+            "geometry": [
+                None,
+                MultiPolygon([[[[0, 0], [0, 1], [1, 1], [1, 0]]]]),
+            ],
+            "id": [0, 1],
+        },
+        crs="epsg:4326",
+    )
+    return df
+
+
 @pytest.fixture
 def df_geom_collection():
     from shapely.geometry import GeometryCollection, LineString, Point, Polygon
@@ -550,6 +567,28 @@ class TestIO:
         assert geom_type.upper() == "GEOMETRYCOLLECTION"
         assert df.geom_type.unique()[0] == "GeometryCollection"
 
+    @pytest.mark.parametrize("engine_postgis", POSTGIS_DRIVERS, indirect=True)
+    def test_write_postgis_none_geometry_types(
+        self, engine_postgis, df_mixed_none_geometry
+    ):
+        """
+        Tests that writing a mix of None and MulitPolygons is possible.
+        """
+        engine = engine_postgis
+
+        table = "geomtype_tests"
+
+        write_postgis(
+            df_mixed_none_geometry, con=engine, name=table, if_exists="replace"
+        )
+
+        # Validate geometry type
+        sql = text(f"SELECT DISTINCT GeometryType(geometry) FROM {table} ORDER BY 1;")
+        with engine.connect() as conn:
+            res = conn.execute(sql).fetchall()
+        assert res[0][0].upper() == "MULTIPOLYGON"
+        assert pd.isna(res[1][0])
+
     @pytest.mark.parametrize("engine_postgis", POSTGIS_DRIVERS, indirect=True)
     def test_write_postgis_mixed_geometry_types(
         self, engine_postgis, df_mixed_single_and_multi


=====================================
geopandas/tests/test_crs.py
=====================================
@@ -717,7 +717,7 @@ class TestSetCRS:
         naive = constructor([Point(0, 0), Point(1, 1)], crs=None)
         assert naive.crs is None
 
-        # by default returns a copy
+        # by default returns a (shallow) copy
         result = naive.set_crs(crs="EPSG:4326")
         assert result.crs == "EPSG:4326"
         assert naive.crs is None


=====================================
geopandas/tests/test_geodataframe.py
=====================================
@@ -152,17 +152,19 @@ class TestDataFrame:
         df = GeoDataFrame(data)
         s = GeoSeries([Point(x, y + 1) for x, y in zip(range(5), range(5))])
 
+        expected = s.copy()
+
         # setting geometry column
         for vals in [s, s.values]:
             df["geometry"] = vals
-            assert_geoseries_equal(df["geometry"], s)
-            assert_geoseries_equal(df.geometry, s)
+            assert_geoseries_equal(df["geometry"], expected)
+            assert_geoseries_equal(df.geometry, expected)
 
         # non-aligned values
         s2 = GeoSeries([Point(x, y + 1) for x, y in zip(range(6), range(6))])
         df["geometry"] = s2
-        assert_geoseries_equal(df["geometry"], s)
-        assert_geoseries_equal(df.geometry, s)
+        assert_geoseries_equal(df["geometry"], expected)
+        assert_geoseries_equal(df.geometry, expected)
 
         # setting other column with geometry values -> preserve geometry type
         for vals in [s, s.values]:
@@ -254,10 +256,12 @@ class TestDataFrame:
     def test_set_geometry(self):
         geom = GeoSeries([Point(x, y) for x, y in zip(range(5), range(5))])
         original_geom = self.df.geometry
+        expected = geom.copy()
+        expected.crs = self.df.crs
 
         df2 = self.df.set_geometry(geom)
-        assert self.df is not df2
-        assert_geoseries_equal(df2.geometry, geom, check_crs=False)
+        assert df2 is not self.df
+        assert_geoseries_equal(df2.geometry, expected)
         assert_geoseries_equal(self.df.geometry, original_geom)
         assert_geoseries_equal(self.df["geometry"], self.df.geometry)
         # unknown column
@@ -290,7 +294,7 @@ class TestDataFrame:
     def test_set_geometry_col(self):
         g = self.df.geometry
         g_simplified = g.simplify(100)
-        self.df["simplified_geometry"] = g_simplified
+        self.df["simplified_geometry"] = g_simplified.copy()
         df2 = self.df.set_geometry("simplified_geometry")
 
         # Drop is false by default


=====================================
geopandas/tests/test_geom_methods.py
=====================================
@@ -1,5 +1,6 @@
 import string
 import warnings
+from packaging.version import Version
 
 import numpy as np
 from pandas import DataFrame, Index, MultiIndex, Series, concat
@@ -29,6 +30,13 @@ from geopandas.tests.util import assert_geoseries_equal, geom_almost_equals, geo
 from numpy.testing import assert_array_equal
 from pandas.testing import assert_frame_equal, assert_index_equal, assert_series_equal
 
+try:
+    import pointpats
+
+    POINTPATS_GE_253 = Version(pointpats.__version__) >= Version("2.5.3")
+except ImportError:
+    POINTPATS_GE_253 = False
+
 
 def assert_array_dtype_equal(a, b, *args, **kwargs):
     a = np.asanyarray(a)
@@ -2135,23 +2143,49 @@ class TestGeomMethods:
         )
         assert_series_equal(shapely.get_num_geometries(output), expected)
 
+    @pytest.mark.parametrize("rng", [None, 1, np.random.default_rng(seed=2)])
     @pytest.mark.parametrize("size", [10, 20, 50])
-    def test_sample_points_pointpats(self, size):
-        pytest.importorskip("pointpats")
+    @pytest.mark.parametrize("method", ["cluster_poisson", "cluster_normal"])
+    @pytest.mark.skipif(
+        not POINTPATS_GE_253, reason="Requires pointpats>=2.5.3 for rng kwarg"
+    )
+    def test_sample_points_pointpats(self, method, size, rng):
         for gs in (
             self.g1,
             self.na,
             self.a1,
         ):
-            output = gs.sample_points(size, method="cluster_poisson")
-            assert_index_equal(gs.index, output.index)
+            output1 = gs.sample_points(size, method=method, rng=rng)
+            assert_index_equal(gs.index, output1.index)
             assert (
-                len(output.explode(ignore_index=True)) == len(gs[~gs.is_empty]) * size
+                len(output1.explode(ignore_index=True)) == len(gs[~gs.is_empty]) * size
             )
 
+            if rng is not None:
+                output2 = gs.sample_points(size, method=method, rng=rng)
+                if rng == 1:
+                    assert_geoseries_equal(output1, output2)
+                else:
+                    with pytest.raises(AssertionError, match="2 out of"):
+                        assert_geoseries_equal(output1, output2)
+
         with pytest.raises(AttributeError, match="pointpats.random module has no"):
             gs.sample_points(10, method="nonexistent")
 
+    @pytest.mark.parametrize("rng", [None, 1, np.random.default_rng(seed=2)])
+    @pytest.mark.parametrize("method", ["cluster_poisson", "cluster_normal"])
+    @pytest.mark.skipif(
+        not POINTPATS_GE_253, reason="Requires pointpats>=2.5.3 for rng kwarg"
+    )
+    def test_sample_points_pointpats_array(self, method, rng):
+        output = concat([self.g1, self.g1]).sample_points(
+            [10, 15, 20, 25], method=method, rng=rng
+        )
+        expected = Series(
+            [10, 15, 20, 25], index=[0, 1, 0, 1], name="sampled_points", dtype="int32"
+        )
+        assert_series_equal(shapely.get_num_geometries(output), expected)
+
     def test_offset_curve(self):
         oc = GeoSeries([self.l1]).offset_curve(1, join_style="mitre")
         expected = GeoSeries([LineString([[-1, 0], [-1, 2], [1, 2]])])


=====================================
geopandas/tests/test_geoseries.py
=====================================
@@ -372,6 +372,12 @@ class TestSeries:
         expected = self.g1.reindex(index)
         assert_geoseries_equal(expected, GeoSeries.from_wkb(s, index=index))
 
+    def test_from_wkb_with_missing(self):
+        s = pd.Series([self.t1.wkb, None, self.sq.wkb])
+        result = GeoSeries.from_wkb(s)
+        expected = GeoSeries([self.t1, None, self.sq])
+        assert_geoseries_equal(result, expected)
+
     def test_from_wkt(self):
         assert_geoseries_equal(self.g1, GeoSeries.from_wkt([self.t1.wkt, self.sq.wkt]))
 
@@ -404,6 +410,19 @@ class TestSeries:
         expected = self.g1.reindex(index)
         assert_geoseries_equal(expected, GeoSeries.from_wkt(s, index=index))
 
+    def test_from_wkt_with_missing(self):
+        s = pd.Series([self.t1.wkt, None, self.sq.wkt])
+        result = GeoSeries.from_wkt(s)
+        expected = GeoSeries([self.t1, None, self.sq])
+        assert_geoseries_equal(result, expected)
+
+    @pytest.mark.parametrize("missing_value", [None, np.nan, pd.NA])
+    def test_from_wkt_with_missing_object(self, missing_value):
+        s = pd.Series([self.t1.wkt, missing_value, self.sq.wkt], dtype="object")
+        result = GeoSeries.from_wkt(s)
+        expected = GeoSeries([self.t1, None, self.sq])
+        assert_geoseries_equal(result, expected)
+
     def test_to_wkb(self):
         assert_series_equal(pd.Series([self.t1.wkb, self.sq.wkb]), self.g1.to_wkb())
         assert_series_equal(


=====================================
geopandas/tests/test_op_output_types.py
=====================================
@@ -1,3 +1,5 @@
+import contextlib
+
 import numpy as np
 import pandas as pd
 
@@ -5,6 +7,7 @@ from shapely.geometry import Point
 
 import geopandas
 from geopandas import GeoDataFrame, GeoSeries
+from geopandas._compat import PANDAS_GE_31
 
 import pytest
 from geopandas.testing import assert_geodataframe_equal
@@ -147,30 +150,27 @@ def test_loc(df):
     assert_object(df.loc[:, "value1"], pd.Series)
 
 
- at pytest.mark.parametrize(
-    "geom_name",
-    [
-        "geometry",
-        pytest.param(
-            "geom",
-            marks=pytest.mark.xfail(
-                reason="pre-regression behaviour only works for geometry col geometry"
-            ),
-        ),
-    ],
-)
+ at pytest.mark.parametrize("geom_name", ["geometry", "geom"])
 def test_loc_add_row(geom_name, nybb_filename):
     # https://github.com/geopandas/geopandas/issues/3119
 
     nybb = geopandas.read_file(nybb_filename)[["BoroCode", "geometry"]]
     if geom_name != "geometry":
         nybb = nybb.rename_geometry(geom_name)
-    # crs_orig = nybb.crs
-
     # add a new row
-    nybb.loc[5] = [6, nybb.geometry.iloc[0]]
-    assert nybb.geometry.dtype == "geometry"
-    assert nybb.crs is None  # TODO this should be crs_orig, regressed in #2373
+    if PANDAS_GE_31:
+        ctx = pytest.warns(UserWarning, match="CRS not set for some.*")
+        expected_crs = nybb.crs
+    else:
+        ctx = contextlib.nullcontext()
+        expected_crs = None  # this should be nybb.crs, regressed in #2373
+    with ctx:
+        nybb.loc[5] = [6, nybb.geometry.iloc[0]]
+    if PANDAS_GE_31 or geom_name == "geometry":
+        assert nybb.geometry.dtype == "geometry"
+        assert nybb.crs is expected_crs
+    else:
+        assert nybb.geometry.dtype == "object"
 
 
 def test_iloc(df):


=====================================
geopandas/tests/test_sindex.py
=====================================
@@ -99,6 +99,7 @@ class TestSeriesSindex:
         assert sliced.sindex is not original_index
         # Select all rows
         sliced = s.iloc[:]
+        assert sliced.has_sindex
         assert sliced.sindex is original_index
         # Select all rows and flip
         sliced = s.iloc[::-1]


=====================================
geopandas/tools/clip.py
=====================================
@@ -8,6 +8,7 @@ import pandas.api.types
 from shapely.geometry import MultiPolygon, Polygon, box
 
 from geopandas import GeoDataFrame, GeoSeries
+from geopandas._compat import PANDAS_GE_30
 from geopandas.array import (
     LINE_GEOM_TYPES,
     POINT_GEOM_TYPES,
@@ -82,7 +83,7 @@ def _clip_gdf_with_mask(gdf, mask, sort=False):
 
     # Clip the data with the polygon
     if isinstance(gdf_sub, GeoDataFrame):
-        clipped = gdf_sub.copy()
+        clipped = gdf_sub.copy(deep=not PANDAS_GE_30)
         if clipping_by_rectangle:
             clipped.loc[non_point_mask, clipped._geometry_column_name] = (
                 gdf_sub.geometry.values[non_point_mask].clip_by_rect(*mask)
@@ -93,7 +94,7 @@ def _clip_gdf_with_mask(gdf, mask, sort=False):
             )
     else:
         # GeoSeries
-        clipped = gdf_sub.copy()
+        clipped = gdf_sub.copy(deep=not PANDAS_GE_30)
         if clipping_by_rectangle:
             clipped[non_point_mask] = gdf_sub.values[non_point_mask].clip_by_rect(*mask)
         else:


=====================================
pyproject.toml
=====================================
@@ -7,13 +7,12 @@ name = "geopandas"
 dynamic = ["version"]
 authors = [{ name = "Kelsey Jordahl", email = "kjordahl at alum.mit.edu" }]
 maintainers = [{ name = "GeoPandas contributors" }]
-license = { text = "BSD 3-Clause" }
+license = "BSD-3-Clause"
 description = "Geographic pandas extensions"
 keywords = ["GIS", "cartography", "pandas", "shapely"]
 classifiers = [
     "Development Status :: 5 - Production/Stable",
     "Intended Audience :: Science/Research",
-    "License :: OSI Approved :: BSD License",
     "Operating System :: OS Independent",
     "Programming Language :: Python :: 3",
     "Programming Language :: Python :: 3 :: Only",
@@ -41,6 +40,7 @@ all = [
     "GeoAlchemy2",
     "pyarrow>=10.0.0",
     "scipy",
+    "pointpats>=2.5.3",
 ]
 
 # Minimum supported additional deps, not installed as part of `all` extra



View it on GitLab: https://salsa.debian.org/debian-gis-team/python-geopandas/-/compare/58c8bb2391b8f6dbd1dcd12c9fc7ab67fe380de2...2eeecb636d9429d054ac4a9fb256bbf2623d1070

-- 
View it on GitLab: https://salsa.debian.org/debian-gis-team/python-geopandas/-/compare/58c8bb2391b8f6dbd1dcd12c9fc7ab67fe380de2...2eeecb636d9429d054ac4a9fb256bbf2623d1070
You're receiving this email because of your account on salsa.debian.org.


-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://alioth-lists.debian.net/pipermail/pkg-grass-devel/attachments/20260310/6eaf6ee4/attachment-0001.htm>


More information about the Pkg-grass-devel mailing list