Repository: geopandas/geopandas
Pull request #3384 (2024-07-17 12:06:44)

BUG: Fix geodataframe constructor not supporting classes with name attributes besides (Geo)Series
Alternate to #3380, have opted for a test using regular enums and not str enums as they're only in the standard library from 3.11 onwards.



Patch:
diff --git a/CHANGELOG.md b/CHANGELOG.md
index 89da9029..0c806036 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -5,6 +5,8 @@
 Bug fixes:
 
 - Properly support named aggregations over a geometry column in `GroupBy.agg` (#3368).
+- Support GeoDataFrame constructor receiving arguments to `geometry` which are not
+  (Geo)Series, but instead should be interpreted as column names, like Enums (#3384).
 - Fix regression where constructing a GeoSeries from a pd.Series with GeometryDtype values 
   failed when `crs` was provided(#3383).
 
diff --git a/geopandas/geodataframe.py b/geopandas/geodataframe.py
index d2e889b4..a054b576 100644
--- a/geopandas/geodataframe.py
+++ b/geopandas/geodataframe.py
@@ -201,7 +201,10 @@ class GeoDataFrame(GeoPandasBase, DataFrame):
             ):
                 raise ValueError(crs_mismatch_error)
 
-            if hasattr(geometry, "name") and geometry.name not in ("geometry", None):
+            if isinstance(geometry, pd.Series) and geometry.name not in (
+                "geometry",
+                None,
+            ):
                 # __init__ always creates geometry col named "geometry"
                 # rename as `set_geometry` respects the given series name
                 geometry = geometry.rename("geometry")
@@ -1327,7 +1330,8 @@ properties': {'col1': 'name1'}, 'geometry': {'type': 'Point', 'coordinates': (1.
             If ``False``, the index(es) will not be written to the file.
             If ``None``, the index(ex) will be included as columns in the file
             output except `RangeIndex` which is stored as metadata only.
-        compression : {'snappy', 'gzip', 'brotli', None}, default 'snappy'
+        compression : {'snappy', 'gzip', 'brotli', 'lz4', 'zstd', None}, \
+default 'snappy'
             Name of the compression to use. Use ``None`` for no compression.
         geometry_encoding : {'WKB', 'geoarrow'}, default 'WKB'
             The encoding to use for the geometry columns. Defaults to "WKB"


Test patch:
diff --git a/.github/workflows/tests.yaml b/.github/workflows/tests.yaml
index 4e419a47..2cbc1083 100644
--- a/.github/workflows/tests.yaml
+++ b/.github/workflows/tests.yaml
@@ -88,7 +88,7 @@ jobs:
 
       - name: Test
         run: |
-          pytest -v -r fEs -n auto --color=yes --cov=geopandas --cov-append --cov-report term-missing --cov-report xml geopandas/
+          pytest -v -r a -n auto --color=yes --cov=geopandas --cov-append --cov-report term-missing --cov-report xml geopandas/
 
       - name: Test with PostGIS
         if: (contains(matrix.env, '310-pd20-conda-forge.yaml') || contains(matrix.env, '311-latest-conda-forge.yaml'))
@@ -102,7 +102,7 @@ jobs:
           conda install postgis -c conda-forge
           sh ci/scripts/setup_postgres.sh
           set -o pipefail
-          pytest -v -r fEs --color=yes --cov=geopandas --cov-append --cov-report term-missing --cov-report xml geopandas/io/tests/test_sql.py | tee /dev/stderr | if grep SKIPPED >/dev/null;then echo "TESTS SKIPPED, FAILING" && exit 1;fi
+          pytest -v -r a --color=yes --cov=geopandas --cov-append --cov-report term-missing --cov-report xml geopandas/io/tests/test_sql.py | tee /dev/stderr | if grep SKIPPED >/dev/null;then echo "TESTS SKIPPED, FAILING" && exit 1;fi
 
       - name: Test docstrings
         if: contains(matrix.env, '310-pd20-conda-forge.yaml') && contains(matrix.os, 'ubuntu')
diff --git a/geopandas/io/tests/test_arrow.py b/geopandas/io/tests/test_arrow.py
index 9078191d..c10220a1 100644
--- a/geopandas/io/tests/test_arrow.py
+++ b/geopandas/io/tests/test_arrow.py
@@ -466,7 +466,9 @@ def test_column_order(tmpdir, file_format, naturalearth_lowres):
     assert_geodataframe_equal(result, df[custom_column_order[1:]])
 
 
-@pytest.mark.parametrize("compression", ["snappy", "gzip", "brotli", None])
+@pytest.mark.parametrize(
+    "compression", ["snappy", "gzip", "brotli", "lz4", "zstd", None]
+)
 def test_parquet_compression(compression, tmpdir, naturalearth_lowres):
     """Using compression options should not raise errors, and should
     return identical GeoDataFrame.
@@ -1020,7 +1022,6 @@ def test_read_parquet_geoarrow(geometry_type):
     ["point", "linestring", "polygon", "multipoint", "multilinestring", "multipolygon"],
 )
 def test_geoarrow_roundtrip(tmp_path, geometry_type):
-
     df = geopandas.read_parquet(
         DATA_PATH
         / "arrow"
diff --git a/geopandas/tests/test_geodataframe.py b/geopandas/tests/test_geodataframe.py
index c9d74b1f..c710b262 100644
--- a/geopandas/tests/test_geodataframe.py
+++ b/geopandas/tests/test_geodataframe.py
@@ -2,6 +2,7 @@ import json
 import os
 import shutil
 import tempfile
+from enum import Enum
 
 import numpy as np
 import pandas as pd
@@ -1489,6 +1490,19 @@ class TestConstructor:
         df[other_df.columns] = other_df
         assert_geodataframe_equal(df, expected)
 
+    def test_geometry_colname_enum(self):
+        # ensure that other classes to geometry arg in GeoDataFrame
+        # with `name` attribute are not assumed to be (Geo)Series
+        class Fruit(Enum):
+            apple = 1
+            pear = 2
+
+        df = pd.DataFrame(
+            {Fruit.apple: [1, 2], Fruit.pear: GeoSeries.from_xy([1, 2], [3, 4])}
+        )
+        res = GeoDataFrame(df, geometry=Fruit.pear)
+        assert res.active_geometry_name == Fruit.pear
+
 
 @pytest.mark.skipif(not compat.HAS_PYPROJ, reason="pyproj not available")
 def test_geodataframe_crs():