Repository: geopandas/geopandas

Issue:
DOC: geoparquet docs page out of sync
https://geopandas.org/en/latest/docs/user_guide/io.html#apache-parquet-and-feather-file-formats page refers to the  0.1.0 geo-arrow-spec and not the newer geoparquet repo. I believe we also removed the corresponding warning text from the parquet io methods.


Discussion:

Resolving patch:
diff --git a/geopandas/io/arrow.py b/geopandas/io/arrow.py
--- a/geopandas/io/arrow.py
+++ b/geopandas/io/arrow.py
@@ -11,8 +11,8 @@
 import geopandas
 from .file import _expand_user
 
-METADATA_VERSION = "0.4.0"
-SUPPORTED_VERSIONS = ["0.1.0", "0.4.0"]
+METADATA_VERSION = "1.0.0-beta.1"
+SUPPORTED_VERSIONS = ["0.1.0", "0.4.0", "1.0.0-beta.1"]
 # reference: https://github.com/opengeospatial/geoparquet
 
 # Metadata structure:
@@ -21,7 +21,7 @@
 #         "columns": {
 #             "<name>": {
 #                 "encoding": "WKB"
-#                 "geometry_type": <str or list of str: REQUIRED>
+#                 "geometry_types": <list of str: REQUIRED>
 #                 "crs": "<PROJJSON or None: OPTIONAL>",
 #                 "orientation": "<'counterclockwise' or None: OPTIONAL>"
 #                 "edges": "planar"
@@ -73,7 +73,7 @@ def _create_metadata(df, schema_version=None):
     Parameters
     ----------
     df : GeoDataFrame
-    schema_version : {'0.1.0', '0.4.0', None}
+    schema_version : {'0.1.0', '0.4.0', '1.0.0-beta.1', None}
         GeoParquet specification version; if not provided will default to
         latest supported version.
 
@@ -94,6 +94,12 @@ def _create_metadata(df, schema_version=None):
     for col in df.columns[df.dtypes == "geometry"]:
         series = df[col]
         geometry_types = sorted(Series(series.geom_type.unique()).dropna())
+        if schema_version[0] == "0":
+            geometry_types_name = "geometry_type"
+            if len(geometry_types) == 1:
+                geometry_types = geometry_types[0]
+        else:
+            geometry_types_name = "geometry_types"
 
         crs = None
         if series.crs:
@@ -106,9 +112,7 @@ def _create_metadata(df, schema_version=None):
         column_metadata[col] = {
             "encoding": "WKB",
             "crs": crs,
-            "geometry_type": geometry_types[0]
-            if len(geometry_types) == 1
-            else geometry_types,
+            geometry_types_name: geometry_types,
         }
 
         bbox = series.total_bounds.tolist()
@@ -264,8 +268,9 @@ def _to_parquet(
 
     Requires 'pyarrow'.
 
-    This is tracking version 0.4.0 of the GeoParquet specification at:
-    https://github.com/opengeospatial/geoparquet
+    This is tracking version 1.0.0-beta.1 of the GeoParquet specification at:
+    https://github.com/opengeospatial/geoparquet. Writing older versions is
+    supported using the `schema_version` keyword.
 
     .. versionadded:: 0.8
 
@@ -280,10 +285,10 @@ def _to_parquet(
         output except `RangeIndex` which is stored as metadata only.
     compression : {'snappy', 'gzip', 'brotli', None}, default 'snappy'
         Name of the compression to use. Use ``None`` for no compression.
-    schema_version : {'0.1.0', '0.4.0', None}
+    schema_version : {'0.1.0', '0.4.0', '1.0.0-beta.1', None}
         GeoParquet specification version; if not provided will default to
         latest supported version.
-    kwargs
+    **kwargs
         Additional keyword arguments passed to pyarrow.parquet.write_table().
     """
     parquet = import_optional_dependency(
@@ -314,8 +319,9 @@ def _to_feather(df, path, index=None, compression=None, schema_version=None, **k
 
     Requires 'pyarrow' >= 0.17.
 
-    This is tracking version 0.4.0 of the GeoParquet specification at:
-    https://github.com/opengeospatial/geoparquet
+    This is tracking version 1.0.0-beta.1 of the GeoParquet specification for
+    the metadata at: https://github.com/opengeospatial/geoparquet. Writing
+    older versions is supported using the `schema_version` keyword.
 
     .. versionadded:: 0.8
 
@@ -331,9 +337,9 @@ def _to_feather(df, path, index=None, compression=None, schema_version=None, **k
     compression : {'zstd', 'lz4', 'uncompressed'}, optional
         Name of the compression to use. Use ``"uncompressed"`` for no
         compression. By default uses LZ4 if available, otherwise uncompressed.
-    schema_version : {'0.1.0', '0.4.0', None}
-        GeoParquet specification version; if not provided will default to
-        latest supported version.
+    schema_version : {'0.1.0', '0.4.0', '1.0.0-beta.1', None}
+        GeoParquet specification version for the metadata; if not provided
+        will default to latest supported version.
     kwargs
         Additional keyword arguments passed to pyarrow.feather.write_feather().
     """
@@ -501,8 +507,8 @@ def _read_parquet(path, columns=None, storage_options=None, **kwargs):
       columns, the first available geometry column will be set as the geometry
       column of the returned GeoDataFrame.
 
-    Supports versions 0.1.0, 0.4.0 of the GeoParquet specification at:
-    https://github.com/opengeospatial/geoparquet
+    Supports versions 0.1.0, 0.4.0 and 1.0.0-beta.1 of the GeoParquet
+    specification at: https://github.com/opengeospatial/geoparquet
 
     If 'crs' key is not present in the GeoParquet metadata associated with the
     Parquet object, it will default to "OGC:CRS84" according to the specification.
@@ -598,8 +604,8 @@ def _read_feather(path, columns=None, **kwargs):
       columns, the first available geometry column will be set as the geometry
       column of the returned GeoDataFrame.
 
-    Supports versions 0.1.0, 0.4.0 of the GeoParquet specification at:
-    https://github.com/opengeospatial/geoparquet
+    Supports versions 0.1.0, 0.4.0 and 1.0.0-beta.1 of the GeoParquet
+    specification at: https://github.com/opengeospatial/geoparquet
 
     If 'crs' key is not present in the Feather metadata associated with the
     Parquet object, it will default to "OGC:CRS84" according to the specification.


Test patch:
diff --git a/geopandas/io/tests/data/arrow/test_data_v1.0.0-beta.1.feather b/geopandas/io/tests/data/arrow/test_data_v1.0.0-beta.1.feather
new file mode 100644
Binary files /dev/null and b/geopandas/io/tests/data/arrow/test_data_v1.0.0-beta.1.feather differ
diff --git a/geopandas/io/tests/data/arrow/test_data_v1.0.0-beta.1.parquet b/geopandas/io/tests/data/arrow/test_data_v1.0.0-beta.1.parquet
new file mode 100644
Binary files /dev/null and b/geopandas/io/tests/data/arrow/test_data_v1.0.0-beta.1.parquet differ
diff --git a/geopandas/io/tests/test_arrow.py b/geopandas/io/tests/test_arrow.py
--- a/geopandas/io/tests/test_arrow.py
+++ b/geopandas/io/tests/test_arrow.py
@@ -73,7 +73,7 @@ def test_create_metadata():
     _remove_id_from_member_of_ensembles(crs_expected)
     assert metadata["columns"]["geometry"]["crs"] == crs_expected
     assert metadata["columns"]["geometry"]["encoding"] == "WKB"
-    assert metadata["columns"]["geometry"]["geometry_type"] == [
+    assert metadata["columns"]["geometry"]["geometry_types"] == [
         "MultiPolygon",
         "Polygon",
     ]
@@ -713,9 +713,11 @@ def test_write_spec_version(tmpdir, format, schema_version):
     df = read(filename)
     assert_geodataframe_equal(df, gdf)
 
+    # verify the correct version is written in the metadata
+    schema_version = schema_version or METADATA_VERSION
     table = read_table(filename)
     metadata = json.loads(table.schema.metadata[b"geo"])
-    assert metadata["version"] == schema_version or METADATA_VERSION
+    assert metadata["version"] == schema_version
 
     # verify that CRS is correctly handled between versions
     if schema_version == "0.1.0":
@@ -726,6 +728,14 @@ def test_write_spec_version(tmpdir, format, schema_version):
         _remove_id_from_member_of_ensembles(crs_expected)
         assert metadata["columns"]["geometry"]["crs"] == crs_expected
 
+    # verify that geometry_type(s) is correctly handled between versions
+    if Version(schema_version) <= Version("0.4.0"):
+        assert "geometry_type" in metadata["columns"]["geometry"]
+        assert metadata["columns"]["geometry"]["geometry_type"] == "Polygon"
+    else:
+        assert "geometry_types" in metadata["columns"]["geometry"]
+        assert metadata["columns"]["geometry"]["geometry_types"] == ["Polygon"]
+
 
 @pytest.mark.parametrize(
     "format,version", product(["feather", "parquet"], [None] + SUPPORTED_VERSIONS)
@@ -767,7 +777,7 @@ def test_write_deprecated_version_parameter(tmpdir, format, version):
         assert metadata["version"] == METADATA_VERSION
 
 
-@pytest.mark.parametrize("version", ["0.1.0", "0.4.0"])
+@pytest.mark.parametrize("version", ["0.1.0", "0.4.0", "1.0.0-beta.1"])
 def test_read_versioned_file(version):
     """
     Verify that files for different metadata spec versions can be read