Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
13 changes: 0 additions & 13 deletions .github/workflows/docker-gdal.yml
Original file line number Diff line number Diff line change
Expand Up @@ -26,8 +26,6 @@ jobs:
- "ghcr.io/osgeo/gdal:ubuntu-small-3.8.5" # python 3.10.12
- "ghcr.io/osgeo/gdal:ubuntu-small-3.7.3" # python 3.10.12
- "ghcr.io/osgeo/gdal:ubuntu-small-3.6.4" # python 3.10.6
- "osgeo/gdal:ubuntu-small-3.5.3" # python 3.9.20 (installed manually)
- "osgeo/gdal:ubuntu-small-3.4.3" # python 3.9.20 (installed manually)

container:
image: ${{ matrix.container }}
Expand All @@ -37,15 +35,6 @@ jobs:
run: |
apt-get update && apt-get install -y build-essential git python3-dev

- name: Install Python
# the GDAL 3.4 and 3.5 images do have Python 3.8 installed, so have to
# install a more recent Python version manually
if: matrix.container == 'osgeo/gdal:ubuntu-small-3.5.3' || matrix.container == 'osgeo/gdal:ubuntu-small-3.4.3'
run: |
apt-get update && apt-get install -y software-properties-common
add-apt-repository -y ppa:deadsnakes/ppa
apt-get update && apt-get install -y python3.9-dev

- uses: actions/checkout@v5

- name: Install uv
Expand All @@ -65,8 +54,6 @@ jobs:
uv pip install -e .[dev,test,geopandas]

- name: Install pyarrow
# GDAL>=3.6 required to use Arrow API
if: matrix.container != 'osgeo/gdal:ubuntu-small-3.5.3' && matrix.container != 'osgeo/gdal:ubuntu-small-3.4.3'
run: |
uv pip install pyarrow

Expand Down
5 changes: 0 additions & 5 deletions .github/workflows/tests-conda.yml
Original file line number Diff line number Diff line change
Expand Up @@ -35,11 +35,6 @@ jobs:
- os: "ubuntu-latest"
python: "3.9"
env: "minimal"
# environment for older Windows libgdal to make sure gdal_i.lib is
# properly detected
- os: "windows-2022"
python: "3.10"
env: "libgdal3.5.1"
# environment with nightly wheels
- os: "ubuntu-latest"
python: "3.11"
Expand Down
1 change: 1 addition & 0 deletions CHANGES.md
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@

- Return JSON fields (as identified by GDAL) as dicts/lists in `read_dataframe`;
these were previously returned as strings (#556).
- Drop support for GDAL 3.4 and 3.5 (#584).

### Improvements

Expand Down
2 changes: 1 addition & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,7 @@ Read the documentation for more information:

## Requirements

Supports Python 3.9 - 3.13 and GDAL 3.4.x - 3.9.x.
Supports Python 3.9 - 3.13 and GDAL 3.6.x - 3.9.x.

Reading to GeoDataFrames requires `geopandas>=0.12` with `shapely>=2`.

Expand Down
7 changes: 0 additions & 7 deletions ci/envs/libgdal3.5.1.yml

This file was deleted.

8 changes: 4 additions & 4 deletions docs/source/install.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@

## Requirements

Supports Python 3.9 - 3.13 and GDAL 3.4.x - 3.9.x
Supports Python 3.9 - 3.13 and GDAL 3.6.x - 3.9.x

Reading to GeoDataFrames requires `geopandas>=0.12` with `shapely>=2`.

Expand Down Expand Up @@ -132,20 +132,20 @@ To build on Windows, you need to provide additional environment variables or
command-line parameters because the location of the GDAL binaries and headers
cannot be automatically determined.

Assuming GDAL 3.4.1 is installed to `c:\GDAL`, you can set the `GDAL_INCLUDE_PATH`,
Assuming GDAL 3.8.3 is installed to `c:\GDAL`, you can set the `GDAL_INCLUDE_PATH`,
`GDAL_LIBRARY_PATH` and `GDAL_VERSION` environment variables and build as follows:

```bash
set GDAL_INCLUDE_PATH=C:\GDAL\include
set GDAL_LIBRARY_PATH=C:\GDAL\lib
set GDAL_VERSION=3.4.1
set GDAL_VERSION=3.8.3
python -m pip install --no-deps --force-reinstall --no-use-pep517 -e . -v
```

Alternatively, you can pass those options also as command-line parameters:

```bash
python -m pip install --install-option=build_ext --install-option="-IC:\GDAL\include" --install-option="-lgdal_i" --install-option="-LC:\GDAL\lib" --install-option="--gdalversion=3.4.1" --no-deps --force-reinstall --no-use-pep517 -e . -v
python -m pip install --install-option=build_ext --install-option="-IC:\GDAL\include" --install-option="-lgdal_i" --install-option="-LC:\GDAL\lib" --install-option="--gdalversion=3.8.3" --no-deps --force-reinstall --no-use-pep517 -e . -v
```

The location of the GDAL DLLs must be on your system `PATH`.
Expand Down
3 changes: 0 additions & 3 deletions pyogrio/_compat.py
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,6 @@
pandas = None


HAS_ARROW_API = __gdal_version__ >= (3, 6, 0)
HAS_ARROW_WRITE_API = __gdal_version__ >= (3, 8, 0)
HAS_PYARROW = pyarrow is not None
HAS_PYPROJ = pyproj is not None
Expand All @@ -44,8 +43,6 @@
PANDAS_GE_22 = pandas is not None and Version(pandas.__version__) >= Version("2.2.0")
PANDAS_GE_30 = pandas is not None and Version(pandas.__version__) >= Version("3.0.0dev")

GDAL_GE_350 = __gdal_version__ >= (3, 5, 0)
GDAL_GE_352 = __gdal_version__ >= (3, 5, 2)
GDAL_GE_37 = __gdal_version__ >= (3, 7, 0)
GDAL_GE_38 = __gdal_version__ >= (3, 8, 0)
GDAL_GE_311 = __gdal_version__ >= (3, 11, 0)
Expand Down
3 changes: 0 additions & 3 deletions pyogrio/_io.pyx
Original file line number Diff line number Diff line change
Expand Up @@ -1620,9 +1620,6 @@ def ogr_open_arrow(
cdef ArrowArrayStream* stream
cdef ArrowSchema schema

IF CTE_GDAL_VERSION < (3, 6, 0):
raise RuntimeError("Need GDAL>=3.6 for Arrow support")

if force_2d:
raise ValueError("forcing 2D is not supported for Arrow")

Expand Down
12 changes: 4 additions & 8 deletions pyogrio/_ogr.pxd
Original file line number Diff line number Diff line change
Expand Up @@ -418,14 +418,10 @@ cdef extern from "ogr_api.h":
const char* OLCFastGetExtent
const char* OLCTransactions


IF CTE_GDAL_VERSION >= (3, 6, 0):

cdef extern from "ogr_api.h":
bint OGR_L_GetArrowStream(
OGRLayerH hLayer, ArrowArrayStream *out_stream, char** papszOptions
)

cdef extern from "ogr_api.h":
bint OGR_L_GetArrowStream(
OGRLayerH hLayer, ArrowArrayStream *out_stream, char** papszOptions
)

IF CTE_GDAL_VERSION >= (3, 8, 0):

Expand Down
16 changes: 5 additions & 11 deletions pyogrio/_ogr.pyx
Original file line number Diff line number Diff line change
@@ -1,6 +1,5 @@
import os
import sys
from uuid import uuid4
import warnings

from pyogrio._err cimport check_pointer
Expand Down Expand Up @@ -44,21 +43,16 @@ def get_gdal_version_string():
return get_string(version)


IF CTE_GDAL_VERSION >= (3, 4, 0):

cdef extern from "ogr_api.h":
bint OGRGetGEOSVersion(int *pnMajor, int *pnMinor, int *pnPatch)
cdef extern from "ogr_api.h":
bint OGRGetGEOSVersion(int *pnMajor, int *pnMinor, int *pnPatch)


def get_gdal_geos_version():
cdef int major, minor, revision

IF CTE_GDAL_VERSION >= (3, 4, 0):
if not OGRGetGEOSVersion(&major, &minor, &revision):
return None
return (major, minor, revision)
ELSE:
if not OGRGetGEOSVersion(&major, &minor, &revision):
return None
return (major, minor, revision)


def set_gdal_config_options(dict options):
Expand Down Expand Up @@ -167,7 +161,7 @@ def get_gdal_data_path():
"""
cdef const char *path_c = CPLFindFile("gdal", "header.dxf")
if path_c != NULL:
return get_string(path_c).rstrip("header.dxf")
return get_string(path_c).replace("header.dxf", "")
return None


Expand Down
11 changes: 1 addition & 10 deletions pyogrio/raw.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@
from io import BytesIO
from pathlib import Path

from pyogrio._compat import HAS_ARROW_API, HAS_ARROW_WRITE_API, HAS_PYARROW
from pyogrio._compat import HAS_ARROW_WRITE_API, HAS_PYARROW
from pyogrio._env import GDALEnv
from pyogrio.core import detect_write_driver
from pyogrio.errors import DataSourceError
Expand Down Expand Up @@ -435,9 +435,6 @@ def open_arrow(
}

"""
if not HAS_ARROW_API:
raise RuntimeError("GDAL>= 3.6 required to read using arrow")

dataset_kwargs = _preprocess_options_key_value(kwargs) if kwargs else {}

return ogr_open_arrow(
Expand Down Expand Up @@ -581,12 +578,6 @@ def _get_write_path_driver(path, driver, append=False):
f"{get_gdal_version_string()}"
)

# prevent segfault from: https://github.com/OSGeo/gdal/issues/5739
if append and driver == "FlatGeobuf" and get_gdal_version() <= (3, 5, 0):
raise RuntimeError(
"append to FlatGeobuf is not supported for GDAL <= 3.5.0 due to segfault"
)

return path, driver


Expand Down
6 changes: 1 addition & 5 deletions pyogrio/tests/conftest.py
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,6 @@
)
from pyogrio._compat import (
GDAL_GE_37,
HAS_ARROW_API,
HAS_ARROW_WRITE_API,
HAS_GDAL_GEOS,
HAS_PYARROW,
Expand Down Expand Up @@ -66,10 +65,7 @@ def pytest_report_header(config):


# marks to skip tests if optional dependecies are not present
requires_arrow_api = pytest.mark.skipif(not HAS_ARROW_API, reason="GDAL>=3.6 required")
requires_pyarrow_api = pytest.mark.skipif(
not HAS_ARROW_API or not HAS_PYARROW, reason="GDAL>=3.6 and pyarrow required"
)
requires_pyarrow_api = pytest.mark.skipif(not HAS_PYARROW, reason="pyarrow required")

requires_pyproj = pytest.mark.skipif(not HAS_PYPROJ, reason="pyproj required")

Expand Down
9 changes: 1 addition & 8 deletions pyogrio/tests/test_arrow.py
Original file line number Diff line number Diff line change
Expand Up @@ -476,10 +476,6 @@ def test_write_geojson(tmp_path, naturalearth_lowres):


@requires_arrow_write_api
@pytest.mark.skipif(
__gdal_version__ < (3, 6, 0),
reason="OpenFileGDB write support only available for GDAL >= 3.6.0",
)
@pytest.mark.parametrize(
"write_int64",
[
Expand Down Expand Up @@ -643,7 +639,7 @@ def test_write_append(request, tmp_path, naturalearth_lowres, ext):
assert read_info(filename)["features"] == 354


@pytest.mark.parametrize("driver,ext", [("GML", ".gml"), ("GeoJSONSeq", ".geojsons")])
@pytest.mark.parametrize("driver,ext", [("GML", ".gml")])
@requires_arrow_write_api
def test_write_append_unsupported(tmp_path, naturalearth_lowres, driver, ext):
meta, table = read_arrow(naturalearth_lowres)
Expand Down Expand Up @@ -961,9 +957,6 @@ def test_write_memory_driver_required(naturalearth_lowres):
@requires_arrow_write_api
@pytest.mark.parametrize("driver", ["ESRI Shapefile", "OpenFileGDB"])
def test_write_memory_unsupported_driver(naturalearth_lowres, driver):
if driver == "OpenFileGDB" and __gdal_version__ < (3, 6, 0):
pytest.skip("OpenFileGDB write support only available for GDAL >= 3.6.0")

meta, table = read_arrow(naturalearth_lowres, max_features=1)

buffer = BytesIO()
Expand Down
16 changes: 2 additions & 14 deletions pyogrio/tests/test_core.py
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@
vsi_rmtree,
vsi_unlink,
)
from pyogrio._compat import GDAL_GE_38, GDAL_GE_350
from pyogrio._compat import GDAL_GE_38
from pyogrio._env import GDALEnv
from pyogrio.errors import DataLayerError, DataSourceError
from pyogrio.raw import read, write
Expand Down Expand Up @@ -140,11 +140,7 @@ def test_list_drivers():
# verify that the core drivers are present
for name in ("ESRI Shapefile", "GeoJSON", "GeoJSONSeq", "GPKG", "OpenFileGDB"):
assert name in all_drivers

expected_capability = "rw"
if name == "OpenFileGDB" and __gdal_version__ < (3, 6, 0):
expected_capability = "r"

assert all_drivers[name] == expected_capability

drivers = list_drivers(read=True)
Expand Down Expand Up @@ -396,10 +392,6 @@ def test_read_bounds_mask(naturalearth_lowres_all_ext, mask, expected):
assert array_equal(fids, fids_expected)


@pytest.mark.skipif(
__gdal_version__ < (3, 4, 0),
reason="Cannot determine if GEOS is present or absent for GDAL < 3.4",
)
def test_read_bounds_bbox_intersects_vs_envelope_overlaps(naturalearth_lowres_all_ext):
# If GEOS is present and used by GDAL, bbox filter will be based on intersection
# of bbox and actual geometries; if GEOS is absent or not used by GDAL, it
Expand Down Expand Up @@ -587,11 +579,7 @@ def test_read_info_jsonfield(nested_geojson_file):
"""Test if JSON fields types are returned correctly."""
meta = read_info(nested_geojson_file)
assert meta["ogr_types"] == ["OFTString", "OFTString"]
if GDAL_GE_350:
# OFSTJSON is only supported for GDAL >= 3.5
assert meta["ogr_subtypes"] == ["OFSTNone", "OFSTJSON"]
else:
assert meta["ogr_subtypes"] == ["OFSTNone", "OFSTNone"]
assert meta["ogr_subtypes"] == ["OFSTNone", "OFSTJSON"]


def test_read_info_unspecified_layer_warning(data_dir):
Expand Down
22 changes: 0 additions & 22 deletions pyogrio/tests/test_geopandas_io.py
Original file line number Diff line number Diff line change
Expand Up @@ -20,8 +20,6 @@
from pyogrio._compat import (
GDAL_GE_37,
GDAL_GE_311,
GDAL_GE_350,
GDAL_GE_352,
HAS_ARROW_WRITE_API,
HAS_PYPROJ,
PANDAS_GE_15,
Expand Down Expand Up @@ -272,10 +270,6 @@ def test_read_force_2d(tmp_path, use_arrow):
assert not df.iloc[0].geometry.has_z


@pytest.mark.skipif(
not GDAL_GE_352,
reason="gdal >= 3.5.2 needed to use OGR_GEOJSON_MAX_OBJ_SIZE with a float value",
)
def test_read_geojson_error(naturalearth_lowres_geojson, use_arrow):
try:
set_gdal_config_options({"OGR_GEOJSON_MAX_OBJ_SIZE": 0.01})
Expand Down Expand Up @@ -387,10 +381,6 @@ def test_read_datetime_tz(datetime_tz_file, tmp_path, use_arrow):
assert_series_equal(df_read.datetime_col, expected)


@pytest.mark.skipif(
not GDAL_GE_350,
reason="OFSTJSON subtype + some list type situations need GDAL >= 3.5",
)
def test_read_list_types(list_field_values_file, use_arrow):
"""Test reading a geojson file containing fields with lists."""
info = read_info(list_field_values_file)
Expand Down Expand Up @@ -1439,12 +1429,6 @@ def test_write_dataframe_gpkg_multiple_layers(tmp_path, naturalearth_lowres, use
@pytest.mark.parametrize("ext", ALL_EXTS)
@pytest.mark.requires_arrow_write_api
def test_write_dataframe_append(request, tmp_path, naturalearth_lowres, ext, use_arrow):
if ext == ".fgb" and __gdal_version__ <= (3, 5, 0):
pytest.skip("Append to FlatGeobuf fails for GDAL <= 3.5.0")

if ext in (".geojsonl", ".geojsons") and __gdal_version__ <= (3, 6, 0):
pytest.skip("Append to GeoJSONSeq only available for GDAL >= 3.6.0")

if use_arrow and ext.startswith(".geojson"):
# Bug in GDAL when appending int64 to GeoJSON
# (https://github.com/OSGeo/gdal/issues/9792)
Expand Down Expand Up @@ -2088,9 +2072,6 @@ def test_read_multisurface(multisurface_file, use_arrow):
assert df.geometry.type.tolist() == ["MultiPolygon"]


@pytest.mark.skipif(
not GDAL_GE_350, reason="OFSTJSON subtype only supported for GDAL >= 3.5"
)
def test_read_dataset_kwargs(nested_geojson_file, use_arrow):
# by default, nested data are not flattened
df = read_dataframe(nested_geojson_file, use_arrow=use_arrow)
Expand Down Expand Up @@ -2358,9 +2339,6 @@ def test_write_memory_driver_required(naturalearth_lowres):

@pytest.mark.parametrize("driver", ["ESRI Shapefile", "OpenFileGDB"])
def test_write_memory_unsupported_driver(naturalearth_lowres, driver):
if driver == "OpenFileGDB" and __gdal_version__ < (3, 6, 0):
pytest.skip("OpenFileGDB write support only available for GDAL >= 3.6.0")

df = read_dataframe(naturalearth_lowres)

buffer = BytesIO()
Expand Down
Loading
Loading