From 3b633d038fa3cdb2f2d8aab14872465c06081ee6 Mon Sep 17 00:00:00 2001 From: Romain Hugonnet Date: Wed, 16 Aug 2023 00:21:03 -0700 Subject: [PATCH] Backward-compatiblity with Shapely < 2.0 (#392) * Use BaseGeometry to be backward-compatible * Linting --- geoutils/vector.py | 11 ++++++----- tests/test_vector.py | 6 +++--- 2 files changed, 9 insertions(+), 8 deletions(-) diff --git a/geoutils/vector.py b/geoutils/vector.py index 010923ef..a824c98b 100644 --- a/geoutils/vector.py +++ b/geoutils/vector.py @@ -35,6 +35,7 @@ from rasterio import features, warp from rasterio.crs import CRS from scipy.spatial import Voronoi +from shapely.geometry.base import BaseGeometry from shapely.geometry.polygon import Polygon import geoutils as gu @@ -67,7 +68,7 @@ class Vector: See the API for more details. """ - def __init__(self, filename_or_dataset: str | pathlib.Path | gpd.GeoDataFrame | gpd.GeoSeries | shapely.Geometry): + def __init__(self, filename_or_dataset: str | pathlib.Path | gpd.GeoDataFrame | gpd.GeoSeries | BaseGeometry): """ Instantiate a vector from either a filename, a GeoPandas dataframe or series, or a Shapely geometry. @@ -83,7 +84,7 @@ def __init__(self, filename_or_dataset: str | pathlib.Path | gpd.GeoDataFrame | self._ds = ds self._name: str | gpd.GeoDataFrame | None = filename_or_dataset # If GeoPandas or Shapely object is passed - elif isinstance(filename_or_dataset, (gpd.GeoDataFrame, gpd.GeoSeries, shapely.Geometry)): + elif isinstance(filename_or_dataset, (gpd.GeoDataFrame, gpd.GeoSeries, BaseGeometry)): self._name = None if isinstance(filename_or_dataset, gpd.GeoDataFrame): self._ds = filename_or_dataset @@ -300,12 +301,12 @@ def save( ############################################################################ def _override_gdf_output( - self, other: gpd.GeoDataFrame | gpd.GeoSeries | shapely.Geometry | pd.Series | Any + self, other: gpd.GeoDataFrame | gpd.GeoSeries | BaseGeometry | pd.Series | Any ) -> Vector | pd.Series: """Parse outputs of GeoPandas functions to facilitate object manipulation.""" # Raise error if output is not treated separately, should appear in tests - if not isinstance(other, (gpd.GeoDataFrame, gpd.GeoDataFrame, pd.Series, shapely.Geometry)): + if not isinstance(other, (gpd.GeoDataFrame, gpd.GeoDataFrame, pd.Series, BaseGeometry)): raise ValueError("Not implemented. This error should only be raised in tests.") # If a GeoDataFrame is the output, return it @@ -315,7 +316,7 @@ def _override_gdf_output( elif isinstance(other, gpd.GeoSeries): return Vector(gpd.GeoDataFrame(geometry=other)) # If a Shapely Geometry is the output, re-encapsulate in a GeoDataFrame and return it - elif isinstance(other, shapely.Geometry): + elif isinstance(other, BaseGeometry): return Vector(gpd.GeoDataFrame({"geometry": [other]}, crs=self.crs)) # If a Pandas Series is the output, append it to that of the GeoDataFrame else: diff --git a/tests/test_vector.py b/tests/test_vector.py index 4ca06489..5a99c525 100644 --- a/tests/test_vector.py +++ b/tests/test_vector.py @@ -13,10 +13,10 @@ import numpy as np import pyproj import pytest -import shapely from geopandas.testing import assert_geodataframe_equal, assert_geoseries_equal from pandas.testing import assert_series_equal from scipy.ndimage import binary_erosion +from shapely.geometry.base import BaseGeometry from shapely.geometry.linestring import LineString from shapely.geometry.multilinestring import MultiLineString from shapely.geometry.multipolygon import MultiPolygon @@ -787,13 +787,13 @@ def test_geo_properties(self, vector: gu.Vector, method: str) -> None: # Assert output types assert isinstance(output_geoutils, gu.Vector) - assert isinstance(output_geopandas, (gpd.GeoSeries, gpd.GeoDataFrame, shapely.Geometry)) + assert isinstance(output_geopandas, (gpd.GeoSeries, gpd.GeoDataFrame, BaseGeometry)) # Separate cases depending on GeoPandas' output if isinstance(output_geopandas, gpd.GeoSeries): # Assert geoseries equality assert_geoseries_equal(output_geoutils.ds.geometry, output_geopandas) - elif isinstance(output_geopandas, shapely.Geometry): + elif isinstance(output_geopandas, BaseGeometry): assert_geodataframe_equal( output_geoutils.ds, gpd.GeoDataFrame({"geometry": [output_geopandas]}, crs=vector.crs) )