Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Require Python 3.9+ #1334

Merged
merged 15 commits into from
Mar 1, 2024
Merged
16 changes: 7 additions & 9 deletions .github/workflows/tests.yml
Original file line number Diff line number Diff line change
Expand Up @@ -39,18 +39,16 @@ jobs:
fail-fast: false
matrix:
include:
- python-version: '3.7'
gdal-version: '3.4.3'
- python-version: '3.8'
- python-version: '3.9'
gdal-version: '3.4.3'
- python-version: '3.9'
gdal-version: '3.5.3'
- python-version: '3.10'
gdal-version: '3.6.4'
- python-version: '3.11'
gdal-version: '3.7.1'
gdal-version: '3.7.3'
- python-version: '3.12'
gdal-version: '3.7.1'
gdal-version: '3.8.3'

steps:
- uses: actions/checkout@v4
Expand Down Expand Up @@ -94,9 +92,9 @@ jobs:
matrix:
include:
- os: macos-latest
python-version: '3.10'
python-version: '3.11'
- os: windows-latest
python-version: '3.10'
python-version: '3.11'
steps:
- uses: actions/checkout@v4

Expand All @@ -111,7 +109,7 @@ jobs:
run: |
conda config --prepend channels conda-forge
conda config --set channel_priority strict
conda create -n test python=${{ matrix.python-version }} libgdal geos=3.10.3 cython=3
conda create -n test python=${{ matrix.python-version }} libgdal geos=3.10.3 cython=3 "numpy>=1.25,<2"
source activate test
python -m pip install -e . || python -m pip install -e .
python -m pip install -r requirements-dev.txt
Expand All @@ -122,7 +120,7 @@ jobs:
run: |
conda config --prepend channels conda-forge
conda config --set channel_priority strict
conda create -n test python=${{ matrix.python-version }} libgdal geos=3.10.3 cython=3
conda create -n test python=${{ matrix.python-version }} libgdal geos=3.10.3 cython=3 "numpy>=1.25,<2"
source activate test
GDAL_VERSION="3.5" python setup.py build_ext -I"C:\\Miniconda\\envs\\test\\Library\\include" -lgdal_i -L"C:\\Miniconda\\envs\\test\\Library\\lib" install
python -m pip install -r requirements-dev.txt
Expand Down
8 changes: 8 additions & 0 deletions CHANGES.txt
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,14 @@ Changes

All issue numbers are relative to https://github.com/Toblerity/Fiona/issues.

Next
----

Python version:

Fiona 1.10 will be compatible with Numpy versions 1 and 2 and will require
Python version 3.9 or higher.

1.9.5 (2023-10-11)
------------------

Expand Down
2 changes: 1 addition & 1 deletion README.rst
Original file line number Diff line number Diff line change
Expand Up @@ -47,7 +47,7 @@ environment variable.
Many users find Anaconda and conda-forge a good way to install Fiona and get
access to more optional format drivers (like GML).

Fiona 2.0 requires Python 3.7 or higher and GDAL 3.2 or higher.
Fiona 1.10 requires Python 3.9 or higher and GDAL 3.4 or higher.

Python Usage
============
Expand Down
1 change: 1 addition & 0 deletions environment.yml
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ dependencies:
- python=3.9.*
- libgdal=3.4.*
- cython=3
- numpy>=1.25,<2
- sphinx-click
- sphinx-rtd-theme
- pip:
Expand Down
32 changes: 15 additions & 17 deletions fiona/_path.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@

"""

import os
import pathlib
import re
import sys
Expand Down Expand Up @@ -65,7 +66,14 @@ class _ParsedPath(_Path):
@classmethod
def from_uri(cls, uri):
parts = urlparse(uri)
path = pathlib.Path(parts.path).as_posix() if parts.path else parts.path
if sys.platform == "win32" and re.match(r"^[a-zA-Z]\:", parts.netloc):
parsed_path = f"{parts.netloc}{parts.path}"
parsed_netloc = None
else:
parsed_path = parts.path
parsed_netloc = parts.netloc

path = parsed_path
scheme = parts.scheme or None

if parts.query:
Expand All @@ -78,11 +86,11 @@ def from_uri(cls, uri):
else:
archive = None

if parts.scheme and parts.netloc:
if scheme and parsed_netloc:
if archive:
archive = parts.netloc + archive
archive = parsed_netloc + archive
else:
path = parts.netloc + path
path = parsed_netloc + path

return _ParsedPath(path, archive, scheme)

Expand Down Expand Up @@ -144,31 +152,21 @@ def _parse_path(path):
"""
if isinstance(path, _Path):
return path

elif pathlib and isinstance(path, pathlib.PurePath):
return _ParsedPath(path.as_posix(), None, None)

elif isinstance(path, pathlib.PurePath):
return _ParsedPath(os.fspath(path), None, None)
elif isinstance(path, str):

if sys.platform == "win32" and re.match(r"^[a-zA-Z]\:", path):
if pathlib:
return _ParsedPath(pathlib.Path(path).as_posix(), None, None)
else:
return _UnparsedPath(path)

return _ParsedPath(path, None, None)
elif path.startswith('/vsi'):
return _UnparsedPath(path)

else:
parts = urlparse(path)

else:
raise PathError("invalid path '{!r}'".format(path))

# if the scheme is not one of Rasterio's supported schemes, we
# return an UnparsedPath.
if parts.scheme:

if all(p in SCHEMES for p in parts.scheme.split('+')):
return _ParsedPath.from_uri(path)

Expand Down
13 changes: 0 additions & 13 deletions fiona/_vsiopener.pyx
Original file line number Diff line number Diff line change
@@ -1,12 +1,8 @@
# cython: language_level=3, boundscheck=False
# distutils: language = c++
"""Bridge between Python file openers and GDAL VSI.

Based on _filepath.pyx.
"""

# include "gdal.pxi"

import contextlib
from contextvars import ContextVar
import logging
Expand All @@ -25,15 +21,6 @@ from fiona.errors import OpenerRegistrationError

log = logging.getLogger(__name__)


# NOTE: This has to be defined outside of gdal.pxi or other C extensions will
# try to compile C++ only code included in this header.
cdef extern from "cpl_vsi_virtual.h":
cdef cppclass VSIFileManager:
@staticmethod
void* GetHandler(const char*)


# Prefix for all in-memory paths used by GDAL's VSI system
# Except for errors and log messages this shouldn't really be seen by the user
cdef str PREFIX = "/vsipyopener/"
Expand Down
5 changes: 2 additions & 3 deletions pyproject.toml
Original file line number Diff line number Diff line change
Expand Up @@ -20,14 +20,13 @@ classifiers = [
"Intended Audience :: Science/Research",
"License :: OSI Approved :: BSD License",
"Operating System :: OS Independent",
"Programming Language :: Python :: 3.7",
"Programming Language :: Python :: 3.8",
"Programming Language :: Python :: 3.9",
"Programming Language :: Python :: 3.10",
"Programming Language :: Python :: 3.11",
"Programming Language :: Python :: 3.12",
"Topic :: Scientific/Engineering :: GIS",
]
requires-python = ">=3.7"
requires-python = ">=3.9"
dependencies = [
"attrs>=19.2.0",
"certifi",
Expand Down
23 changes: 23 additions & 0 deletions tests/test__path.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
"""_path tests."""

import sys

from fiona._path import _parse_path, _vsi_path


def test_parse_zip_windows(monkeypatch):
"""Parse a zip+ Windows path."""
monkeypatch.setattr(sys, "platform", "win32")
path = _parse_path("zip://D:\\a\\Fiona\\Fiona\\tests\\data\\coutwildrnp.zip!coutwildrnp.shp")
vsi_path = _vsi_path(path)
assert vsi_path.startswith("/vsizip/D")
assert vsi_path.endswith("coutwildrnp.zip/coutwildrnp.shp")


def test_parse_zip_windows(monkeypatch):
"""Parse a tar+ Windows path."""
monkeypatch.setattr(sys, "platform", "win32")
path = _parse_path("tar://D:\\a\\Fiona\\Fiona\\tests\\data\\coutwildrnp.tar!testing/coutwildrnp.shp")
vsi_path = _vsi_path(path)
assert vsi_path.startswith("/vsitar/D")
assert vsi_path.endswith("coutwildrnp.tar/testing/coutwildrnp.shp")
2 changes: 2 additions & 0 deletions tests/test_layer.py
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
"""Layer tests."""

import pytest

import fiona
Expand Down
Loading