diff --git a/.github/workflows/docker-gdal.yml b/.github/workflows/docker-gdal.yml index de600454..864457b7 100644 --- a/.github/workflows/docker-gdal.yml +++ b/.github/workflows/docker-gdal.yml @@ -26,8 +26,8 @@ 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) + - "osgeo/gdal:ubuntu-small-3.5.3" # python 3.10 (installed manually) + - "osgeo/gdal:ubuntu-small-3.4.3" # python 3.10 (installed manually) container: image: ${{ matrix.container }} @@ -44,7 +44,7 @@ jobs: 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 + apt-get update && apt-get install -y python3.10-dev - uses: actions/checkout@v5 diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index 978fd653..b662cf0d 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -257,7 +257,7 @@ jobs: "macos-13", "macos-latest", ] - python-version: ["3.9", "3.10", "3.11", "3.12", "3.13"] + python-version: ["3.10", "3.11", "3.12", "3.13"] include: - os: "ubuntu-latest" artifact: pyogrio-wheel-linux-manylinux2014_x86_64 diff --git a/.github/workflows/tests-conda.yml b/.github/workflows/tests-conda.yml index d74a2c5d..259dc620 100644 --- a/.github/workflows/tests-conda.yml +++ b/.github/workflows/tests-conda.yml @@ -33,7 +33,7 @@ jobs: geopandas=0.12 # minimal environment without optional dependencies - os: "ubuntu-latest" - python: "3.9" + python: "3.10" env: "minimal" # environment for older Windows libgdal to make sure gdal_i.lib is # properly detected diff --git a/CHANGES.md b/CHANGES.md index 9e786442..c34f6734 100644 --- a/CHANGES.md +++ b/CHANGES.md @@ -1,10 +1,14 @@ # CHANGELOG -## 0.12.0 (yyyy-mm-dd) +## 0.12.0 (xxxx-xx-xx) + +### Packaging + +- pyogrio now requires a minimum version of Python >= 3.10 (#557). ### Bug fixes -- Fix wrong layername when creating .gpkg.zip file (#570) +- Fix wrong layername when creating .gpkg.zip file (#570). ## 0.11.1 (2025-08-02) diff --git a/README.md b/README.md index 9e5e9708..75de1530 100644 --- a/README.md +++ b/README.md @@ -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.10 - 3.13 and GDAL 3.4.x - 3.9.x. Reading to GeoDataFrames requires `geopandas>=0.12` with `shapely>=2`. diff --git a/docs/environment.yml b/docs/environment.yml index af811239..0c3679c7 100644 --- a/docs/environment.yml +++ b/docs/environment.yml @@ -2,9 +2,9 @@ name: pyogrio channels: - conda-forge dependencies: - - python==3.9.* + - python==3.10.* - gdal - - numpy==1.19.* + - numpy==1.24.* - numpydoc==1.1.* - Cython==0.29.* - docutils==0.16.* diff --git a/docs/source/install.md b/docs/source/install.md index 94513d11..61a4fdb9 100644 --- a/docs/source/install.md +++ b/docs/source/install.md @@ -2,7 +2,7 @@ ## Requirements -Supports Python 3.9 - 3.13 and GDAL 3.4.x - 3.9.x +Supports Python 3.10 - 3.13 and GDAL 3.4.x - 3.9.x Reading to GeoDataFrames requires `geopandas>=0.12` with `shapely>=2`. diff --git a/pyogrio/core.py b/pyogrio/core.py index 1fa18fa4..e06418c0 100644 --- a/pyogrio/core.py +++ b/pyogrio/core.py @@ -1,7 +1,6 @@ """Core functions to interact with OGR data sources.""" from pathlib import Path -from typing import Optional, Union from pyogrio._env import GDALEnv from pyogrio.util import ( @@ -336,7 +335,7 @@ def get_gdal_data_path(): return _get_gdal_data_path() -def vsi_listtree(path: Union[str, Path], pattern: Optional[str] = None): +def vsi_listtree(path: str | Path, pattern: str | None = None): """Recursively list the contents of a VSI directory. An fnmatch pattern can be specified to filter the directories/files @@ -356,7 +355,7 @@ def vsi_listtree(path: Union[str, Path], pattern: Optional[str] = None): return ogr_vsi_listtree(path, pattern=pattern) -def vsi_rmtree(path: Union[str, Path]): +def vsi_rmtree(path: str | Path): """Recursively remove VSI directory. Parameters @@ -371,7 +370,7 @@ def vsi_rmtree(path: Union[str, Path]): ogr_vsi_rmtree(path) -def vsi_unlink(path: Union[str, Path]): +def vsi_unlink(path: str | Path): """Remove a VSI file. Parameters diff --git a/pyogrio/geopandas.py b/pyogrio/geopandas.py index ce57575b..810f6e7a 100644 --- a/pyogrio/geopandas.py +++ b/pyogrio/geopandas.py @@ -697,7 +697,7 @@ def write_dataframe( if isinstance(values, pd.api.extensions.ExtensionArray): from pandas.arrays import BooleanArray, FloatingArray, IntegerArray - if isinstance(values, (IntegerArray, FloatingArray, BooleanArray)): + if isinstance(values, IntegerArray | FloatingArray | BooleanArray): field_data.append(values._data) field_mask.append(values._mask) else: diff --git a/pyogrio/util.py b/pyogrio/util.py index 0c8e4399..0479df89 100644 --- a/pyogrio/util.py +++ b/pyogrio/util.py @@ -4,7 +4,6 @@ import sys from packaging.version import Version from pathlib import Path -from typing import Union from urllib.parse import urlparse from pyogrio._ogr import MULTI_EXTENSIONS @@ -53,7 +52,7 @@ def get_vsi_path_or_buffer(path_or_buffer): return vsi_path(str(path_or_buffer)) -def vsi_path(path: Union[str, Path]) -> str: +def vsi_path(path: str | Path) -> str: """Ensure path is a local path or a GDAL-compatible VSI path.""" # Convert Path objects to string, but for VSI paths, keep posix style path. if isinstance(path, Path): @@ -236,7 +235,7 @@ def _mask_to_wkb(mask): return shapely.to_wkb(mask) -def vsimem_rmtree_toplevel(path: Union[str, Path]): +def vsimem_rmtree_toplevel(path: str | Path): """Remove the parent directory of the file path recursively. This is used for final cleanup of an in-memory dataset, which may have been diff --git a/pyproject.toml b/pyproject.toml index d4d1640b..a86f467f 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -27,7 +27,7 @@ classifiers = [ "Programming Language :: Python :: 3", "Topic :: Scientific/Engineering :: GIS", ] -requires-python = ">=3.9" +requires-python = ">=3.10" dependencies = ["certifi", "numpy", "packaging"] [project.optional-dependencies] diff --git a/setup.py b/setup.py index 10c4a03d..6a3ffd74 100644 --- a/setup.py +++ b/setup.py @@ -20,12 +20,12 @@ logger = logging.getLogger(__name__) -MIN_PYTHON_VERSION = (3, 9, 0) +MIN_PYTHON_VERSION = (3, 10, 0) MIN_GDAL_VERSION = (2, 4, 0) if sys.version_info < MIN_PYTHON_VERSION: - raise RuntimeError("Python >= 3.9 is required") + raise RuntimeError("Python >= 3.10 is required") def copy_data_tree(datadir, destdir):