[Git][debian-gis-team/python-geopandas][upstream] New upstream version 1.1.4

Bas Couwenberg (@sebastic) gitlab at salsa.debian.org
Sat Jun 27 07:19:00 BST 2026



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


Commits:
791026ab by Bas Couwenberg at 2026-06-27T07:40:15+02:00
New upstream version 1.1.4
- - - - -


14 changed files:

- CHANGELOG.md
- CODE_OF_CONDUCT.md
- + doc/source/community/code_of_conduct.md
- − doc/source/community/code_of_conduct.rst
- geopandas/_version.py
- geopandas/base.py
- geopandas/explore.py
- geopandas/io/sql.py
- geopandas/tests/test_explore.py
- geopandas/tests/test_geom_methods.py
- geopandas/tests/test_overlay.py
- geopandas/tools/_random.py
- geopandas/tools/overlay.py
- pyproject.toml


Changes:

=====================================
CHANGELOG.md
=====================================
@@ -1,8 +1,20 @@
 # Changelog
 
+## Version 1.1.4 (June 26, 2026)
+
+Bug fixes:
+
+- Further hardening of ``to_postgis`` against SQL injection (#3800).
+- Ensure that points generated by ``sample_points`` are not sorted along x-axis (#3773).
+- Fix ``GeoDataFrame.explore()`` ignoring custom ``legend_kwds={"labels": ...}``
+  for categorical and boolean columns (#3496).
+- More graceful handling of ``keep_geom_type`` in the ``overlay()`` function with
+  empty input (#3745).
+
 ## 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).


=====================================
CODE_OF_CONDUCT.md
=====================================
@@ -1,133 +1,27 @@
-# GeoPandas Project Code of Conduct
+# NumFOCUS Code of Conduct
 
-Behind the GeoPandas Project is an engaged and respectful community made up of people
-from all over the world and with a wide range of backgrounds.
-Naturally, this implies diversity of ideas and perspectives on often complex
-problems. Disagreement and healthy discussion of conflicting viewpoints is
-welcome: the best solutions to hard problems rarely come from a single angle.
-But disagreement is not an excuse for aggression: humans tend to take
-disagreement personally and easily drift into behavior that ultimately degrades
-a community. This is particularly acute with online communication across
-language and cultural gaps, where many cues of human behavior are unavailable.
-We are outlining here a set of principles and processes to support a
-healthy community in the face of these challenges.
+You can find the whole document here [https://numfocus.org/code-of-conduct](https://numfocus.org/code-of-conduct).
 
-Fundamentally, we are committed to fostering a productive, harassment-free
-environment for everyone. Rather than considering this code an exhaustive list
-of things that you can’t do, take it in the spirit it is intended - a guide to
-make it easier to enrich all of us and the communities in which we participate.
+## The short version
 
-Importantly: as a member of our community, *you are also a steward of these
-values*.  Not all problems need to be resolved via formal processes, and often
-a quick, friendly but clear word on an online forum or in person can help
-resolve a misunderstanding and de-escalate things.
+NumFOCUS is dedicated to providing a harassment-free community for everyone, regardless of gender, sexual orientation, gender identity and expression, disability, physical appearance, body size, race, or religion. We do not tolerate harassment of community members in any form.
 
-However, sometimes these informal processes may be inadequate: they fail to
-work, there is urgency or risk to someone, nobody is intervening publicly and
-you don't feel comfortable speaking in public, etc.  For these or other
-reasons, structured follow-up may be necessary and here we provide the means
-for that: we welcome reports by emailing
-[*geopandas-conduct at googlegroups.com*](mailto:geopandas-conduct at googlegroups.com)
-or by filling out
-[this form](https://docs.google.com/forms/d/e/1FAIpQLSd8Tbi2zNl1i2N9COX0yavHEqTGFIPQ1_cLcy1A3JgVc1OrAQ/viewform).
+Be kind to others. Do not insult or put down others. Behave professionally. Remember that harassment and sexist, racist, or exclusionary jokes are not appropriate for NumFOCUS.
 
-This code applies equally to founders, developers, mentors and new community
-members, in all spaces managed by the GeoPandas Project. This
-includes the mailing lists, our GitHub organization, our chat room, in-person
-events, and any other forums created by the project team. In addition,
-violations of this code outside these spaces may affect a person's ability to
-participate within them.
+All communication should be appropriate for a professional audience including people of many different backgrounds. Sexual language and imagery is not appropriate.
 
-By embracing the following principles, guidelines and actions to follow or
-avoid, you will help us make the GeoPandas Project a welcoming and productive community. Feel
-free to contact the Code of Conduct Committee at
-[*geopandas-conduct at googlegroups.com*](mailto:geopandas-conduct at googlegroups.com)  with any questions.
+Thank you for helping make this a welcoming, friendly community for all.
 
+## Long version
 
-1. **Be friendly and patient**.
+You can find the long version of the Code of Conduct on the NumFOCUS website [https://numfocus.org/code-of-conduct](https://numfocus.org/code-of-conduct)
 
-2. **Be welcoming**. We strive to be a community that welcomes and supports
-   people of all backgrounds and identities. This includes, but is not limited
-   to, members of any race, ethnicity, culture, national origin, color,
-   immigration status, social and economic class, educational level, sex, sexual
-   orientation, gender identity and expression, age, physical appearance, family
-   status, technological or professional choices, academic
-   discipline, religion, mental ability, and physical ability.
+## How to report
 
-3. **Be considerate**. Your work will be used by other people, and you in turn
-   will depend on the work of others. Any decision you take will affect users
-   and colleagues, and you should take those consequences into account when
-   making decisions. Remember that we're a world-wide community. You may be
-   communicating with someone with a different primary language or cultural
-   background.
+If you feel that the Code of Conduct has been violated, feel free to submit a report, by using the form: [NumFOCUS Code of Conduct Reporting Form](https://forms.monday.com/forms/f130e8cddb99568fa86cf077b8912a60?r=use1)  
 
-4. **Be respectful**. Not all of us will agree all the time, but disagreement is
-   no excuse for poor behavior or poor manners. We might all experience some
-   frustration now and then, but we cannot allow that frustration to turn into a
-   personal attack. It’s important to remember that a community where people
-   feel uncomfortable or threatened is not a productive one.
+## Who will receive your report
 
-5. **Be careful in the words that you choose**. Be kind to others. Do not insult
-   or put down other community members. Harassment and other exclusionary
-   behavior are not acceptable. This includes, but is not limited to:
-   * Violent threats or violent language directed against another person
-   * Discriminatory jokes and language
-   * Posting sexually explicit or violent material
-   * Posting (or threatening to post) other people's personally identifying
-     information ("doxing")
-   * Personal insults, especially those using racist, sexist, and xenophobic terms
-   * Unwelcome sexual attention
-   * Advocating for, or encouraging, any of the above behavior
-   * Repeated harassment of others. In general, if someone asks you to stop,
-     then stop
+Your report will be received and handled by NumFOCUS Code of Conduct Working Group; trained, and experienced contributors with diverse backgrounds. The group is making decisions independently from the project, PyData, NumFOCUS or any other organization.
 
-6. **Moderate your expectations**. Please respect that community members choose
-   how they spend their time in the project. A thoughtful question about your
-   expectations is preferable to demands for another person's time.
-
-7. **When we disagree, try to understand why**. Disagreements, both social and
-   technical, happen all the time and the GeoPandas Project is no exception.  Try to
-   understand where others are coming from, as seeing a question from their
-   viewpoint may help find a new path forward.  And don’t forget that it is
-   human to err: blaming each other doesn’t get us anywhere, while we can learn
-   from mistakes to find better solutions.
-
-8. **A simple apology can go a long way**. It can often de-escalate a situation,
-   and telling someone that you are sorry is an act of empathy that doesn’t
-   automatically imply an admission of guilt.
-
-
-## Reporting
-
-If you believe someone is violating the code of conduct, please report this in
-a timely manner. Code of conduct violations reduce the value of the community
-for everyone and we take them seriously.
-
-You can file a report by emailing
-[*geopandas-conduct at googlegroups.com*](mailto:geopandas-conduct at googlegroups.com) or by filing out
-[this form](https://docs.google.com/forms/d/e/1FAIpQLSd8Tbi2zNl1i2N9COX0yavHEqTGFIPQ1_cLcy1A3JgVc1OrAQ/viewform).
-
-The online form gives you the option to keep your report anonymous or request
-that we follow up with you directly. While we cannot follow up on an anonymous
-report, we will take appropriate action.
-
-Messages sent to the e-mail address or through the form will be sent
-only to the Code of Conduct Committee, which currently consists of:
-
-* Hannah Aizenman
-* Joris Van den Bossche
-* Martin Fleischmann
-
-
-## Enforcement
-
-Enforcement procedures within the GeoPandas Project follow Project Jupyter's
-[*Enforcement Manual*](https://github.com/jupyter/governance/blob/master/conduct/enforcement.md). For information on enforcement, please view the [original manual](https://github.com/jupyter/governance/blob/master/conduct/enforcement.md).
-
-Original text courtesy of the [*Speak
-Up!*](http://web.archive.org/web/20141109123859/http://speakup.io/coc.html),
-[*Django*](https://www.djangoproject.com/conduct) and [*Jupyter*](https://github.com/jupyter/governance/blob/master/conduct/code_of_conduct.md) Projects,
-modified by the GeoPandas Project. We are grateful to those projects for contributing these materials under open licensing terms for us to easily reuse.
-
-All content on this page is licensed under a [*Creative Commons
-Attribution*](http://creativecommons.org/licenses/by/3.0/) license.
+You can learn more about the current group members, as well as the reporting procedure **[HERE](https://numfocus.org/code-of-conduct)**


=====================================
doc/source/community/code_of_conduct.md
=====================================
@@ -0,0 +1,27 @@
+# NumFOCUS Code of Conduct
+
+You can find the whole document here [https://numfocus.org/code-of-conduct](https://numfocus.org/code-of-conduct).
+
+## The short version
+
+NumFOCUS is dedicated to providing a harassment-free community for everyone, regardless of gender, sexual orientation, gender identity and expression, disability, physical appearance, body size, race, or religion. We do not tolerate harassment of community members in any form.
+
+Be kind to others. Do not insult or put down others. Behave professionally. Remember that harassment and sexist, racist, or exclusionary jokes are not appropriate for NumFOCUS.
+
+All communication should be appropriate for a professional audience including people of many different backgrounds. Sexual language and imagery is not appropriate.
+
+Thank you for helping make this a welcoming, friendly community for all.
+
+## Long version
+
+You can find the long version of the Code of Conduct on the NumFOCUS website [https://numfocus.org/code-of-conduct](https://numfocus.org/code-of-conduct)
+
+## How to report
+
+If you feel that the Code of Conduct has been violated, feel free to submit a report, by using the form: [NumFOCUS Code of Conduct Reporting Form](https://forms.monday.com/forms/f130e8cddb99568fa86cf077b8912a60?r=use1)  
+
+## Who will receive your report
+
+Your report will be received and handled by NumFOCUS Code of Conduct Working Group; trained, and experienced contributors with diverse backgrounds. The group is making decisions independently from the project, PyData, NumFOCUS or any other organization.
+
+You can learn more about the current group members, as well as the reporting procedure **[HERE](https://numfocus.org/code-of-conduct)**


=====================================
doc/source/community/code_of_conduct.rst deleted
=====================================
@@ -1,135 +0,0 @@
-GeoPandas Project Code of Conduct
-=================================
-
-Behind the GeoPandas Project is an engaged and respectful community made up of
-people from all over the world and with a wide range of backgrounds.
-Naturally, this implies diversity of ideas and perspectives on often
-complex problems. Disagreement and healthy discussion of conflicting
-viewpoints is welcome: the best solutions to hard problems rarely come from a single
-angle. But disagreement is not an excuse for aggression: humans tend to take
-disagreement personally and easily drift into behavior that ultimately
-degrades a community. This is particularly acute with online communication
-across language and cultural gaps, where many cues of human behavior are
-unavailable. We are outlining here a set of principles and processes to support a
-healthy community in the face of these challenges.
-
-Fundamentally, we are committed to fostering a productive, harassment-free
-environment for everyone. Rather than considering this code an exhaustive list
-of things that you can’t do, take it in the spirit it is intended - a guide to
-make it easier to enrich all of us and the communities in which we participate.
-
-Importantly: as a member of our community, *you are also a steward of these
-values*. Not all problems need to be resolved via formal processes, and often
-a quick, friendly but clear word on an online forum or in person can help
-resolve a misunderstanding and de-escalate things.
-
-However, sometimes these informal processes may be inadequate: they fail to
-work, there is urgency or risk to someone, nobody is intervening publicly and
-you don't feel comfortable speaking in public, etc. For these or other
-reasons, structured follow-up may be necessary and here we provide the means
-for that: we welcome reports by emailing
-`geopandas-conduct at googlegroups.com <mailto:geopandas-conduct at googlegroups.com>`__ or by filling out `this
-form <https://docs.google.com/forms/d/e/1FAIpQLSd8Tbi2zNl1i2N9COX0yavHEqTGFIPQ1_cLcy1A3JgVc1OrAQ/viewform>`__.
-
-This code applies equally to founders, developers, mentors and new community
-members, in all spaces managed by the GeoPandas Project. This
-includes the mailing lists, our GitHub organization, our chat room, in-person
-events, and any other forums created by the project team. In addition,
-violations of this code outside these spaces may affect a person's ability to
-participate within them.
-
-By embracing the following principles, guidelines and actions to follow or
-avoid, you will help us make Jupyter a welcoming and productive community. Feel
-free to contact the Code of Conduct Committee at
-`geopandas-conduct at googlegroups.com <mailto:geopandas-conduct at googlegroups.com>`__ with any questions.
-
-1. **Be friendly and patient**.
-
-2. **Be welcoming**. We strive to be a community that welcomes and supports
-   people of all backgrounds and identities. This includes, but is not limited
-   to, members of any race, ethnicity, culture, national origin, color,
-   immigration status, social and economic class, educational level, sex, sexual
-   orientation, gender identity and expression, age, physical appearance, family
-   status, technological or professional choices, academic
-   discipline, religion, mental ability, and physical ability.
-
-3. **Be considerate**. Your work will be used by other people, and you in turn
-   will depend on the work of others. Any decision you take will affect users
-   and colleagues, and you should take those consequences into account when
-   making decisions. Remember that we're a world-wide community. You may be
-   communicating with someone with a different primary language or cultural
-   background.
-
-4. **Be respectful**. Not all of us will agree all the time, but disagreement is
-   no excuse for poor behavior or poor manners. We might all experience some
-   frustration now and then, but we cannot allow that frustration to turn into a
-   personal attack. It’s important to remember that a community where people
-   feel uncomfortable or threatened is not a productive one.
-
-5. **Be careful in the words that you choose**. Be kind to others. Do not insult
-   or put down other community members. Harassment and other exclusionary
-   behavior are not acceptable. This includes, but is not limited to:
-
-   -  Violent threats or violent language directed against another person
-   -  Discriminatory jokes and language
-   -  Posting sexually explicit or violent material
-   -  Posting (or threatening to post) other people's personally identifying information ("doxing")
-   -  Personal insults, especially those using racist, sexist, and xenophobic terms
-   -  Unwelcome sexual attention
-   -  Advocating for, or encouraging, any of the above behavior
-   -  Repeated harassment of others. In general, if someone asks you to stop, then stop
-
-6. **Moderate your expectations**. Please respect that community members choose
-   how they spend their time in the project. A thoughtful question about your
-   expectations is preferable to demands for another person's time.
-
-7. **When we disagree, try to understand why**. Disagreements, both social and
-   technical, happen all the time and the GeoPandas Project is no exception. Try to
-   understand where others are coming from, as seeing a question from their
-   viewpoint may help find a new path forward. And don’t forget that it is
-   human to err: blaming each other doesn’t get us anywhere, while we can learn
-   from mistakes to find better solutions.
-
-8. **A simple apology can go a long way**. It can often de-escalate a situation,
-   and telling someone that you are sorry is an act of empathy that doesn’t
-   automatically imply an admission of guilt.
-
-Reporting
----------
-
-If you believe someone is violating the code of conduct, please report this in
-a timely manner. Code of conduct violations reduce the value of the community
-for everyone and we take them seriously.
-
-You can file a report by emailing
-`geopandas-conduct at googlegroups.com <mailto:geopandas-conduct at googlegroups.com>`__ or by filing out
-`this form <https://docs.google.com/forms/d/e/1FAIpQLSd8Tbi2zNl1i2N9COX0yavHEqTGFIPQ1_cLcy1A3JgVc1OrAQ/viewform>`__.
-
-The online form gives you the option to keep your report anonymous or request
-that we follow up with you directly. While we cannot follow up on an anonymous
-report, we will take appropriate action.
-
-Messages sent to the e-mail address or through the form will be sent
-only to the Code of Conduct Committee, which currently consists of:
-
-- Hannah Aizenman
-- Joris Van den Bossche
-- Martin Fleischmann
-
-Enforcement
------------
-
-Enforcement procedures within the GeoPandas Project follow Project Jupyter's `Enforcement
-Manual <https://github.com/jupyter/governance/blob/master/conduct/enforcement.md>`__.
-For information on enforcement, please view the `original
-manual <https://github.com/jupyter/governance/blob/master/conduct/enforcement.md>`__.
-
-Original text courtesy of the `Speak
-Up! <http://web.archive.org/web/20141109123859/http://speakup.io/coc.html>`__,
-`Django <https://www.djangoproject.com/conduct>`__ and
-`Jupyter <https://github.com/jupyter/governance/blob/master/conduct/code_of_conduct.md>`__
-Projects, modified by the GeoPandas Project. We are grateful to those projects for
-contributing these materials under open licensing terms for us to easily reuse.
-
-All content on this page is licensed under a `Creative Commons
-Attribution <http://creativecommons.org/licenses/by/3.0/>`__ license.


=====================================
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.3, 1.1.x)"
-    git_full = "f5fe3ff5f0e473603cd0e81673d9f1f300f4975d"
-    git_date = "2026-03-10 08:34:35 +1100"
+    git_refnames = " (tag: v1.1.4, 1.1.x)"
+    git_full = "91ec4af3c502be268ee147a3a832387534c0be3d"
+    git_date = "2026-06-26 19:22:35 +0200"
     keywords = {"refnames": git_refnames, "full": git_full, "date": git_date}
     return keywords
 


=====================================
geopandas/base.py
=====================================
@@ -9,7 +9,7 @@ from shapely.geometry import MultiPoint, box
 from shapely.geometry.base import BaseGeometry
 
 from . import _compat as compat
-from .array import GeometryArray, GeometryDtype, points_from_xy
+from .array import GeometryArray, GeometryDtype
 
 
 def is_geometry_type(data):
@@ -6449,9 +6449,9 @@ GeometryCollection
             if pd.api.types.is_list_like(size):
                 result = [
                     (
-                        points_from_xy(
-                            *sample_function(x, size=s, rng=rng, **kwargs).T
-                        ).union_all()
+                        shapely.multipoints(
+                            sample_function(x, size=s, rng=rng, **kwargs)
+                        )
                         if not (x.is_empty or x is None or "Polygon" not in x.geom_type)
                         else MultiPoint()
                     )
@@ -6460,9 +6460,9 @@ GeometryCollection
             else:
                 result = self.geometry.apply(
                     lambda x: (
-                        points_from_xy(
-                            *sample_function(x, size=size, rng=rng, **kwargs).T
-                        ).union_all()
+                        shapely.multipoints(
+                            sample_function(x, size=size, rng=rng, **kwargs)
+                        )
                         if not (x.is_empty or x is None or "Polygon" not in x.geom_type)
                         else MultiPoint()
                     ),


=====================================
geopandas/explore.py
=====================================
@@ -223,6 +223,12 @@ def _explore(
 
         caption : string
             Custom caption of the legend. Defaults to the column name.
+        labels : list-like
+            A list of legend labels to override the auto-generated labels.
+            Needs to have the same number of elements as the number of unique
+            categories (for categorical or boolean columns) or the number of
+            classes ``k`` (for ``scheme``-based classification). For
+            ``scheme``-based classification it applies only if ``colorbar=False``.
 
         Additional accepted keywords when ``scheme`` is specified:
 
@@ -236,10 +242,6 @@ def _explore(
             A formatting specification for the bin edges of the classes in the
             legend. For example, to have no decimals: ``{"fmt": "{:.0f}"}``. Applies
             if ``colorbar=False``.
-        labels : list-like
-            A list of legend labels to override the auto-generated labels.
-            Needs to have the same number of elements as the number of
-            classes (`k`). Applies if ``colorbar=False``.
         interval : boolean (default False)
             An option to control brackets from mapclassify legend.
             If True, open/closed interval brackets are shown in the legend.
@@ -677,6 +679,15 @@ def _explore(
             categories = cat.categories.to_list()
             legend_colors = legend_colors.tolist()
 
+            labels = legend_kwds.pop("labels", None)
+            if labels is not None:
+                if len(labels) != len(categories):
+                    raise ValueError(
+                        f"The number of legend labels ({len(labels)}) does not "
+                        f"match the number of categories ({len(categories)})."
+                    )
+                categories = list(labels)
+
             if nan_idx.any() and nan_color:
                 categories.append(missing_kwds.pop("label", "NaN"))
                 legend_colors.append(nan_color)
@@ -709,7 +720,7 @@ def _explore(
                 else:
                     fmt = legend_kwds.pop("fmt", "{:.2f}")
                     if "labels" in legend_kwds:
-                        categories = legend_kwds["labels"]
+                        categories = legend_kwds.pop("labels")
                     else:
                         categories = binning.get_legend_classes(fmt)
                         show_interval = legend_kwds.pop("interval", False)


=====================================
geopandas/io/sql.py
=====================================
@@ -94,7 +94,7 @@ def _df_to_geodf(df, geom_col="geom", crs=None, con=None):
 
         df[geom_col] = geoms = geoms.apply(load_geom)
         if crs is None:
-            srid = shapely.get_srid(geoms.iat[0])
+            srid = int(shapely.get_srid(geoms.iat[0]))
             # if no defined SRID in geodatabase, returns SRID of 0
             if srid != 0:
                 try:
@@ -324,12 +324,15 @@ def _psql_insert_copy(tbl, conn, keys, data_iter):
     writer.writerows(data_iter)
     s_buf.seek(0)
 
-    columns = ", ".join(f'"{k}"' for k in keys)
+    preparer = conn.dialect.identifier_preparer
+    columns = ", ".join(preparer.quote(k) for k in keys)
+
+    table_name = preparer.quote(tbl.table.name)
+    if tbl.table.schema:
+        table_name = f"{preparer.quote_schema(tbl.table.schema)}.{table_name}"
 
     dbapi_conn = conn.connection
-    sql = (
-        f'COPY "{tbl.table.schema}"."{tbl.table.name}" ({columns}) FROM STDIN WITH CSV'
-    )
+    sql = f"COPY {table_name} ({columns}) FROM STDIN WITH CSV"
     with dbapi_conn.cursor() as cur:
         # Use psycopg method if it's available
         if hasattr(cur, "copy") and callable(cur.copy):
@@ -460,7 +463,7 @@ def _write_postgis(
 
 
 @lru_cache
-def _get_spatial_ref_sys_df(con, srid):
+def _get_spatial_ref_sys_df(con, srid: int):
     spatial_ref_sys_sql = (
         f"SELECT srid, auth_name FROM spatial_ref_sys WHERE srid = {srid}"
     )


=====================================
geopandas/tests/test_explore.py
=====================================
@@ -653,6 +653,55 @@ class TestExplore:
         out_str = self._fetch_map_string(m)
         assert "red'></span>NaN" in out_str
 
+    def test_categorical_legend_custom_labels(self):
+        # GH3496: custom legend labels must be honored for categorical and
+        # boolean columns
+        labels = [
+            "Cat0",
+            "Cat1",
+            "Cat2",
+            "Cat3",
+            "Cat4",
+            "Cat5",
+            "Cat6",
+            "Cat7",
+        ]
+        m = self.world.explore("continent", legend=True, legend_kwds={"labels": labels})
+        out_str = self._fetch_map_string(m)
+        for label in labels:
+            assert label in out_str
+        # original category names must no longer appear as legend rows
+        assert "'></span>Africa" not in out_str
+        assert "'></span>SouthAmerica" not in out_str
+
+        # a length mismatch must raise a clear error
+        with pytest.raises(ValueError, match="number of legend labels"):
+            self.world.explore(
+                "continent", legend=True, legend_kwds={"labels": ["only", "two"]}
+            )
+
+        # custom labels combined with a missing (NaN) row: the NaN entry must
+        # still render after the custom labels and not consume a custom label
+        m = self.missing.explore(
+            "continent",
+            legend=True,
+            legend_kwds={"labels": labels},
+            missing_kwds={"color": "red"},
+        )
+        out_str = self._fetch_map_string(m)
+        assert "Cat0" in out_str
+        assert "red'></span>NaN" in out_str
+
+        # GH3496: also works for boolean columns (the original reporter's case)
+        nybb_bool = self.nybb.copy()
+        nybb_bool["is_manhattan"] = nybb_bool["BoroName"] == "Manhattan"
+        m = nybb_bool.explore(
+            "is_manhattan", legend=True, legend_kwds={"labels": ["Outer", "Core"]}
+        )
+        out_str = self._fetch_map_string(m)
+        assert "Outer" in out_str
+        assert "Core" in out_str
+
     def test_colorbar(self):
         def quoted_in(find, s):
             return find in s or find.replace("'", '"') in s


=====================================
geopandas/tests/test_geom_methods.py
=====================================
@@ -1,3 +1,4 @@
+import re
 import string
 import warnings
 from packaging.version import Version
@@ -2127,17 +2128,17 @@ class TestGeomMethods:
             self.a1,
             self.na_none,
         ):
-            output = gs.sample_points(size)
+            output = gs.sample_points(size, rng=0)
             assert_index_equal(gs.index, output.index)
             assert (
                 len(output.explode(ignore_index=True))
                 == len(gs[~(gs.is_empty | gs.isna())]) * size
             )
-        with pytest.warns(FutureWarning, match="The 'seed' keyword is deprecated"):
-            _ = gs.sample_points(size, seed=1)
+            x = output.get_coordinates()["x"]
+            assert not x.equals(x.sort_values())
 
     def test_sample_points_array(self):
-        output = concat([self.g1, self.g1]).sample_points([10, 15, 20, 25])
+        output = concat([self.g1, self.g1]).sample_points([10, 15, 20, 25], rng=0)
         expected = Series(
             [10, 15, 20, 25], index=[0, 1, 0, 1], name="sampled_points", dtype="int32"
         )
@@ -2169,7 +2170,12 @@ class TestGeomMethods:
                     with pytest.raises(AssertionError, match="2 out of"):
                         assert_geoseries_equal(output1, output2)
 
-        with pytest.raises(AttributeError, match="pointpats.random module has no"):
+            x = output1.get_coordinates()["x"]
+            assert not x.equals(x.sort_values())
+
+        with pytest.raises(
+            AttributeError, match=re.escape("pointpats.random module has no")
+        ):
             gs.sample_points(10, method="nonexistent")
 
     @pytest.mark.parametrize("rng", [None, 1, np.random.default_rng(seed=2)])


=====================================
geopandas/tests/test_overlay.py
=====================================
@@ -846,13 +846,22 @@ def test_zero_len():
         crs=4326,
     )
     # overlay with empty geodataframe shouldn't throw
-    gdf2 = GeoDataFrame({"geometry": []}, crs=4326)
-    res = gdf1.overlay(gdf2, how="union")
+    empty = GeoDataFrame({"geometry": []}, crs=4326)
+    res = gdf1.overlay(empty, how="union")
     assert_geodataframe_equal(res, gdf1)
-
-    gdf2 = GeoDataFrame(geometry=[], crs=4326)
-    res = gdf1.overlay(gdf2, how="union")
+    res = gdf1.overlay(empty, how="union")
+    assert_geodataframe_equal(res, gdf1)
+    res = empty.overlay(gdf1, how="union", keep_geom_type=False)
     assert_geodataframe_equal(res, gdf1)
+    res = empty.overlay(gdf1, how="difference", keep_geom_type=False)
+    assert_geodataframe_equal(res, empty)
+
+    # keep_geom_type should warn gracefully with an empty input
+    # https://github.com/geopandas/geopandas/discussions/3738
+    with pytest.warns(
+        UserWarning, match="`keep_geom_type=True` is invalid when df1 is empty"
+    ):
+        empty.overlay(gdf1, how="union", keep_geom_type=True)
 
 
 class TestOverlayWikiExample:


=====================================
geopandas/tools/_random.py
=====================================
@@ -7,10 +7,8 @@ from shapely.geometry import MultiPoint
 from geopandas.array import (
     LINE_GEOM_TYPES,
     POLYGON_GEOM_TYPES,
-    from_shapely,
     points_from_xy,
 )
-from geopandas.geoseries import GeoSeries
 
 
 def uniform(geom, size, rng=None):
@@ -67,7 +65,7 @@ def uniform(geom, size, rng=None):
 def _uniform_line(geom, size, generator):
     """Sample points from an input shapely linestring."""
     fracs = generator.uniform(size=size)
-    return from_shapely(geom.interpolate(fracs, normalized=True)).union_all()
+    return MultiPoint(geom.interpolate(fracs, normalized=True))
 
 
 def _uniform_polygon(geom, size, generator):
@@ -82,4 +80,4 @@ def _uniform_polygon(geom, size, generator):
         valid_samples = batch[batch.sindex.query(geom, predicate="contains")]
         candidates.extend(valid_samples)
     generator.shuffle(candidates)  # avoid the artifacts of STRTree ordering
-    return GeoSeries(candidates[:size]).union_all()
+    return MultiPoint(candidates[:size])


=====================================
geopandas/tools/overlay.py
=====================================
@@ -1,5 +1,6 @@
 import warnings
 from functools import reduce
+from typing import Literal
 
 import numpy as np
 import pandas as pd
@@ -169,7 +170,15 @@ def _overlay_union(df1, df2):
     return dfunion.reindex(columns=columns)
 
 
-def overlay(df1, df2, how="intersection", keep_geom_type=None, make_valid=True):
+def overlay(
+    df1: GeoDataFrame,
+    df2: GeoDataFrame,
+    how: Literal[
+        "intersection", "union", "identity", "symmetric_difference", "difference"
+    ] = "intersection",
+    keep_geom_type: bool | None = None,
+    make_valid: bool = True,
+):
     """Perform spatial overlay between two GeoDataFrames.
 
     Currently only supports data GeoDataFrames with uniform geometry types,
@@ -333,7 +342,15 @@ def overlay(df1, df2, how="intersection", keep_geom_type=None, make_valid=True):
 
     # Determine the geometry type before make_valid, as make_valid may change it
     if keep_geom_type:
-        geom_type = df1.geom_type.iloc[0]
+        if len(df1) == 0:
+            msg = (
+                "`keep_geom_type=True` is invalid when df1 is empty as "
+                "there is no geometry type to keep. Setting `keep_geom_type=False`"
+            )
+            warnings.warn(msg, stacklevel=3)
+            keep_geom_type = False
+        else:
+            geom_type = df1.geom_type.iloc[0]
 
     df1 = _make_valid(df1)
     df2 = _make_valid(df2)


=====================================
pyproject.toml
=====================================
@@ -1,5 +1,5 @@
 [build-system]
-requires = ["setuptools>=61.0.0"]
+requires = ["setuptools>=77"]
 build-backend = "setuptools.build_meta"
 
 [project]



View it on GitLab: https://salsa.debian.org/debian-gis-team/python-geopandas/-/commit/791026abaa69e9d1b6438d86d697e8a461a3288c

-- 
View it on GitLab: https://salsa.debian.org/debian-gis-team/python-geopandas/-/commit/791026abaa69e9d1b6438d86d697e8a461a3288c
You're receiving this email because of your account on salsa.debian.org. Manage all notifications: https://salsa.debian.org/-/profile/notifications | Help: https://salsa.debian.org/help


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


More information about the Pkg-grass-devel mailing list