Context
Pyramids ships a fat platform wheel that vendors GDAL/osgeo (so pip users get GDAL without installing it
separately) and lets conda-forge users get GDAL from the feedstock. That wheel already bundles GDAL driver
plugins (NetCDF / HDF4 / HDF5) into src/pyramids/_data/gdalplugins/.
This proposal surfaced from PR #455 (LabeledDataset). While fixing that PR's CI, the parquet pixi feature
(pyarrow) was temporarily added to the py311-py314 test-matrix envs. That un-skipped a pre-existing
core test, tests/feature/test_tile_strategy.py::TestRowGroupParquet::test_row_group_parquet, which then
failed on Linux/macOS with:
pyogrio.errors.DataSourceError: '.../points.parquet' not recognized as being in a supported file format.
It could have been recognized by driver Parquet, but plugin ogr_Parquet.so is not available in your
installation. You may install it with 'conda install -c conda-forge libgdal-arrow-parquet'.
It passed on Windows because the conda-forge Windows GDAL build bundles the Arrow/Parquet driver in-tree;
on Linux/macOS conda-forge splits it into a separate libgdal-arrow-parquet package that is not installed.
PR #455 resolved this by dropping parquet from those envs (keeping only lazy), restoring the prior skip.
This issue tracks doing it properly, decoupled from #455.
Problem / Current Behaviour
There are two distinct Parquet capabilities, and they are independent - having one does not give the
other:
- Python
pyarrow (the [parquet] extra) - used for writing Parquet from pandas/geopandas
(df.to_parquet, gdf.to_parquet) and LabeledDataset.to_parquet. Already available and pip-portable
(pyarrow is a normal PyPI dependency).
- GDAL OGR Parquet driver (
libgdal-arrow-parquet / ogr_Parquet.so) - used for reading a
.parquet as a vector layer through GDAL/pyogrio, e.g.
FeatureCollection.iter_features(p, bbox=..., tile_strategy="row_group") (streaming + bbox + row-group
pushdown). This is the piece missing on Linux/macOS conda envs without the driver and on all pip
installs (the standard gdal wheel does not bundle the Arrow/Parquet driver).
Installing libgdal-arrow-parquet does not provide Python pyarrow, and vice-versa; the row-group test
needs both. The result is a real conda-vs-pip (and Windows-vs-Linux/macOS) asymmetry in GDAL-side Parquet
vector reading.
Affected locations
| File |
Symbol |
Notes |
ci/install-and-vendor-osgeo.py |
plugin-copy step (~L365-375) |
Already copies lib/gdalplugins/ to _data/gdalplugins/; would pick up ogr_Parquet automatically |
pyproject.toml |
[tool.pixi.dependencies] (gdal, libgdal-netcdf, libgdal-hdf4) |
Where libgdal-arrow-parquet would be added for the wheel build |
.github/workflows/build-wheels.yml |
wheel repair step |
Must explicitly include the Arrow C++ libs (dlopen'd plugin) |
src/pyramids/feature* |
FeatureCollection.iter_features |
The consumer of the OGR Parquet read driver |
tests/feature/test_tile_strategy.py |
TestRowGroupParquet::test_row_group_parquet |
Skips today; would run skip-free with the driver present |
ci/check-wheel-size.sh |
WHEEL_SIZE_BUDGET_MB (120) |
Size gate the added libs eat into |
Motivation Example
from pyramids.featurecollection import FeatureCollection
# Today: works on conda-Windows; on Linux/macOS conda without libgdal-arrow-parquet, and on ALL pip
# installs, this raises DataSourceError ("plugin ogr_Parquet.so is not available").
feats = list(
FeatureCollection.iter_features("reaches.parquet", bbox=(0, 0, 10, 10), tile_strategy="row_group")
)
Proposed Solution
Vendor libgdal-arrow-parquet into the platform wheel using the existing osgeo-vendoring machinery:
- Add
libgdal-arrow-parquet to the wheel-build conda deps (next to libgdal-netcdf / libgdal-hdf4).
The vendor script's existing plugin-copy step then bundles ogr_Parquet.so (and the Arrow driver
.dll/.dylib) into _data/gdalplugins/ with no change to the copy logic.
- Catch - the plugin is
dlopen'd at runtime, so the wheel-repair tools
(auditwheel / delvewheel / delocate) will not auto-discover its Arrow C++ deps via the osgeo._gdal
extension's DT_NEEDED. The Arrow runtime libs (libarrow, libparquet, libarrow-dataset,
libarrow-acero, libarrow-compute) must be explicitly added to the vendor/repair step so they land
in pyramids_gis.libs/.
- ABI: conda-forge solves
libgdal-arrow-parquet against the pinned libgdal 3.12, so the binaries
match.
Size cost (measured)
The plugin itself is tiny (~0.8 MB); the weight is the Arrow C++ runtime it links. Measured uncompressed
on-disk:
| Library |
Uncompressed |
Needed by the OGR Parquet driver? |
libgdal-arrow-parquet (plugin) |
~0.8 MB |
yes (driver glue) |
arrow |
~13.2 MB |
yes |
arrow_compute |
~8.8 MB |
yes (dataset/acero depend on it) |
parquet |
~2.6 MB |
yes |
arrow_dataset |
~1.3 MB |
yes (row-group/dataset API) |
arrow_acero |
~1.2 MB |
yes (dataset engine) |
arrow_python* |
~1.4 MB |
no - pyarrow-only, not the GDAL driver |
- ~28 MB uncompressed total for the driver + its Arrow runtime.
- Compressed conda downloads:
libgdal-arrow-parquet 0.8 MB + libarrow 6.5 MB + libparquet 1.4 MB +
libarrow-acero 0.6 MB ~= 9.3 MB.
- Native libs compress ~2.5-3x in the
.whl, so this adds ~10-12 MB to every platform wheel's download
(Linux/macOS/Windows x py311-py314), paid by all users - including those who never read Parquet.
- Wheel budget is 120 MB per
.whl (WHEEL_SIZE_BUDGET_MB, rationale in
planning/bundle/wheel-size-analysis.md). ~10-12 MB fits within headroom but is a permanent, meaningful
chunk of it.
Pros
- pip/PyPI users gain GDAL-side Parquet vector reading - closes the conda-vs-pip asymmetry that exists
today.
FeatureCollection.iter_features row-group pushdown works uniformly across all install paths.
test_row_group_parquet (and LabeledDataset.to_parquet) can run skip-free on the Linux/macOS matrix when
the env has the driver.
- Reuses the existing vendoring design; minimal new infra (a conda dep + explicit repair-step inclusion).
Cons
- +~10-12 MB to every wheel for all users, eating wheel-size-budget headroom, for a feature many users
never use.
- More native libs to keep ABI-aligned with
libgdal across version bumps (another pin/maintenance
surface).
- Repair-step needs explicit handling because the driver is
dlopen'd (the repair tools won't auto-bundle
the Arrow deps).
- conda-forge already provides this via the feedstock; the only net-new beneficiaries are pip users and
Linux/macOS conda envs lacking the driver.
Alternative
Move FeatureCollection's Parquet reading off the GDAL OGR driver onto the pure-Python
geopandas/pyarrow path (gpd.read_parquet(bbox=...)). pyarrow is a normal pip dependency (not vendored), so
this adds ~0 to the wheel and is fully pip/conda portable - at the cost of a Parquet-specific code path
that diverges from the unified pyogrio/OGR reader and may have different row-group pushdown semantics. This is
the lighter-weight alternative to bundling ~28 MB.
Decision asked
Choose between:
- (A) Vendor
libgdal-arrow-parquet + Arrow runtime into the wheel - skip-free, uniform GDAL reader,
+~12 MB/wheel. Requires: add the conda dep, extend the repair/vendor step to include the Arrow libs, add
libgdal-arrow-parquet to the relevant test envs, and re-enable the row-group test on Linux/macOS.
- (B) Keep the GDAL driver conda-only and optionally add a geopandas/pyarrow read path for pip
portability - no wheel growth.
Out of Scope
Effort Estimate
Size: M
Rationale: small conda-dep + explicit repair-step change, but cross-platform wheel verification
(auditwheel/delvewheel/delocate must actually bundle and load the Arrow libs at runtime on
Linux/macOS/Windows) plus a size-budget re-check is the bulk of the work.
Definition of Done
Context
Pyramids ships a fat platform wheel that vendors GDAL/
osgeo(so pip users get GDAL without installing itseparately) and lets conda-forge users get GDAL from the feedstock. That wheel already bundles GDAL driver
plugins (NetCDF / HDF4 / HDF5) into
src/pyramids/_data/gdalplugins/.This proposal surfaced from PR #455 (
LabeledDataset). While fixing that PR's CI, theparquetpixi feature(pyarrow) was temporarily added to the
py311-py314test-matrix envs. That un-skipped a pre-existingcoretest,tests/feature/test_tile_strategy.py::TestRowGroupParquet::test_row_group_parquet, which thenfailed on Linux/macOS with:
It passed on Windows because the conda-forge Windows GDAL build bundles the Arrow/Parquet driver in-tree;
on Linux/macOS conda-forge splits it into a separate
libgdal-arrow-parquetpackage that is not installed.PR #455 resolved this by dropping
parquetfrom those envs (keeping onlylazy), restoring the prior skip.This issue tracks doing it properly, decoupled from #455.
Problem / Current Behaviour
There are two distinct Parquet capabilities, and they are independent - having one does not give the
other:
pyarrow(the[parquet]extra) - used for writing Parquet from pandas/geopandas(
df.to_parquet,gdf.to_parquet) andLabeledDataset.to_parquet. Already available and pip-portable(
pyarrowis a normal PyPI dependency).libgdal-arrow-parquet/ogr_Parquet.so) - used for reading a.parquetas a vector layer through GDAL/pyogrio, e.g.FeatureCollection.iter_features(p, bbox=..., tile_strategy="row_group")(streaming + bbox + row-grouppushdown). This is the piece missing on Linux/macOS conda envs without the driver and on all pip
installs (the standard
gdalwheel does not bundle the Arrow/Parquet driver).Installing
libgdal-arrow-parquetdoes not provide Pythonpyarrow, and vice-versa; the row-group testneeds both. The result is a real conda-vs-pip (and Windows-vs-Linux/macOS) asymmetry in GDAL-side Parquet
vector reading.
Affected locations
ci/install-and-vendor-osgeo.pylib/gdalplugins/to_data/gdalplugins/; would pick upogr_Parquetautomaticallypyproject.toml[tool.pixi.dependencies](gdal,libgdal-netcdf,libgdal-hdf4)libgdal-arrow-parquetwould be added for the wheel build.github/workflows/build-wheels.ymlsrc/pyramids/feature*FeatureCollection.iter_featurestests/feature/test_tile_strategy.pyTestRowGroupParquet::test_row_group_parquetci/check-wheel-size.shWHEEL_SIZE_BUDGET_MB(120)Motivation Example
Proposed Solution
Vendor
libgdal-arrow-parquetinto the platform wheel using the existing osgeo-vendoring machinery:libgdal-arrow-parquetto the wheel-build conda deps (next tolibgdal-netcdf/libgdal-hdf4).The vendor script's existing plugin-copy step then bundles
ogr_Parquet.so(and the Arrow driver.dll/.dylib) into_data/gdalplugins/with no change to the copy logic.dlopen'd at runtime, so the wheel-repair tools(auditwheel / delvewheel / delocate) will not auto-discover its Arrow C++ deps via the
osgeo._gdalextension's
DT_NEEDED. The Arrow runtime libs (libarrow,libparquet,libarrow-dataset,libarrow-acero,libarrow-compute) must be explicitly added to the vendor/repair step so they landin
pyramids_gis.libs/.libgdal-arrow-parquetagainst the pinnedlibgdal 3.12, so the binariesmatch.
Size cost (measured)
The plugin itself is tiny (~0.8 MB); the weight is the Arrow C++ runtime it links. Measured uncompressed
on-disk:
libgdal-arrow-parquet(plugin)arrowarrow_computeparquetarrow_datasetarrow_aceroarrow_python*libgdal-arrow-parquet0.8 MB +libarrow6.5 MB +libparquet1.4 MB +libarrow-acero0.6 MB ~= 9.3 MB..whl, so this adds ~10-12 MB to every platform wheel's download(Linux/macOS/Windows x py311-py314), paid by all users - including those who never read Parquet.
.whl(WHEEL_SIZE_BUDGET_MB, rationale inplanning/bundle/wheel-size-analysis.md). ~10-12 MB fits within headroom but is a permanent, meaningfulchunk of it.
Pros
today.
FeatureCollection.iter_featuresrow-group pushdown works uniformly across all install paths.test_row_group_parquet(andLabeledDataset.to_parquet) can run skip-free on the Linux/macOS matrix whenthe env has the driver.
Cons
never use.
libgdalacross version bumps (another pin/maintenancesurface).
dlopen'd (the repair tools won't auto-bundlethe Arrow deps).
Linux/macOS conda envs lacking the driver.
Alternative
Move
FeatureCollection's Parquet reading off the GDAL OGR driver onto the pure-Pythongeopandas/pyarrow path (
gpd.read_parquet(bbox=...)).pyarrowis a normal pip dependency (not vendored), sothis adds ~0 to the wheel and is fully pip/conda portable - at the cost of a Parquet-specific code path
that diverges from the unified pyogrio/OGR reader and may have different row-group pushdown semantics. This is
the lighter-weight alternative to bundling ~28 MB.
Decision asked
Choose between:
libgdal-arrow-parquet+ Arrow runtime into the wheel - skip-free, uniform GDAL reader,+~12 MB/wheel. Requires: add the conda dep, extend the repair/vendor step to include the Arrow libs, add
libgdal-arrow-parquetto the relevant test envs, and re-enable the row-group test on Linux/macOS.portability - no wheel growth.
Out of Scope
LabeledDatasetPR (feat(netcdf): label-indexed (non-gridded) NetCDF/Zarr reader — PY-G subset (P-A…P-F, P-B) #455) itself - that ships withparquetexcluded from the matrix and is unaffectedby this decision.
pyarrowwrite path (to_parquet), which already works pip-portably.Effort Estimate
Size:
MRationale: small conda-dep + explicit repair-step change, but cross-platform wheel verification
(auditwheel/delvewheel/delocate must actually bundle and load the Arrow libs at runtime on
Linux/macOS/Windows) plus a size-budget re-check is the bulk of the work.
Definition of Done
libgdal-arrow-parquetadded to the wheel-build conda deps; Arrow runtime libs explicitlyvendored into
pyramids_gis.libs/.dlopenthe OGR Parquet driver and read a.parquetviaFeatureCollection.iter_featuresat runtime (verified inwheel-test.yml).test_row_group_parquetruns (not skipped) on the Linux/macOS matrix and passes.WHEEL_SIZE_BUDGET_MBceiling.