[Git][debian-gis-team/python-shapely][upstream] New upstream version 1.8.3

Bas Couwenberg (@sebastic) gitlab at salsa.debian.org
Wed Aug 17 04:37:25 BST 2022



Bas Couwenberg pushed to branch upstream at Debian GIS Project / python-shapely


Commits:
41878988 by Bas Couwenberg at 2022-08-17T05:18:48+02:00
New upstream version 1.8.3
- - - - -


23 changed files:

- .github/workflows/release.yml
- .github/workflows/tests.yml
- CHANGES.txt
- pyproject.toml
- shapely/__init__.py
- shapely/ctypes_declarations.py
- shapely/geometry/base.py
- shapely/geometry/collection.py
- shapely/geometry/multilinestring.py
- shapely/geometry/multipoint.py
- shapely/geometry/multipolygon.py
- shapely/geometry/polygon.py
- shapely/geometry/proxy.py
- shapely/ops.py
- shapely/strtree.py
- shapely/topology.py
- tests/test_geos_err_handler.py
- tests/test_linear_referencing.py
- tests/test_parallel_offset.py
- tests/test_shared_paths.py
- tests/test_split.py
- tests/test_strtree.py
- tests/test_substring.py


Changes:

=====================================
.github/workflows/release.yml
=====================================
@@ -30,7 +30,7 @@ jobs:
 
       - name: Build a source tarball
         env:
-          GEOS_VERSION: "3.10.2"
+          GEOS_VERSION: "3.10.3"
           GEOS_INSTALL: ${{ runner.temp }}/geos-$GEOS_VERSION
           GEOS_CONFIG: ${{ runner.temp }}/geos-$GEOS_VERSION/bin/geos-config
           LD_LIBRARY_PATH: $LD_LIBRARY_PATH:${{ runner.temp }}/geos-$GEOS_VERSION/lib
@@ -49,7 +49,7 @@ jobs:
     name: Build ${{ matrix.arch }} wheels on ${{ matrix.os }}
     runs-on: ${{ matrix.os }}
     env:
-      GEOS_VERSION: "3.10.2"
+      GEOS_VERSION: "3.10.3"
       CIBW_BUILD_VERBOSITY: 2
     strategy:
       fail-fast: false
@@ -65,13 +65,13 @@ jobs:
         - os: windows-2019
           arch: AMD64
           msvc_arch: x64
-        - os: macos-10.15
+        - os: macos-11
           arch: x86_64
           cmake_osx_architectures: x86_64
-        - os: macos-10.15
+        - os: macos-11
           arch: arm64
           cmake_osx_architectures: arm64
-        - os: macos-10.15
+        - os: macos-11
           arch: universal2
           cmake_osx_architectures: "x86_64;arm64"
 


=====================================
.github/workflows/tests.yml
=====================================
@@ -14,7 +14,7 @@ jobs:
       matrix:
         os: [ubuntu-latest, macos-latest, windows-2019]
         architecture: [x64]
-        geos: [3.6.5, 3.7.3, 3.8.1, 3.9.2, 3.10.2]
+        geos: [3.6.5, 3.7.5, 3.8.3, 3.9.3, 3.10.3, 3.11.0]
         include:
           # 2017
           - python: 3.6
@@ -30,51 +30,63 @@ jobs:
             speeedups: 0
           # 2018
           - python: 3.7
-            geos: 3.7.3
+            geos: 3.7.5
             numpy: 1.15.4
             speedups: 1
           - python: 3.7
-            geos: 3.7.3
+            geos: 3.7.5
             numpy: 1.15.4
             speedups: 0
           - python: 3.7
-            geos: 3.7.3
+            geos: 3.7.5
             speedups: 0
           # 2019
           - python: 3.8
-            geos: 3.8.1
+            geos: 3.8.3
             numpy: 1.17.5
             speedups: 1
           - python: 3.8
-            geos: 3.8.1
+            geos: 3.8.3
             numpy: 1.17.5
             speedups: 0
           - python: 3.8
-            geos: 3.8.1
+            geos: 3.8.3
             speedups: 0
           # 2020
           - python: 3.9
-            geos: 3.9.2
+            geos: 3.9.3
             numpy: 1.19.5
             speedups: 1
           - python: 3.9
-            geos: 3.9.2
+            geos: 3.9.3
             numpy: 1.19.5
             speedups: 0
           - python: 3.9
-            geos: 3.9.2
+            geos: 3.9.3
             speedups: 0
           # 2021
           - python: "3.10"
-            geos: 3.10.2
+            geos: 3.10.3
             numpy: 1.21.3
             speedups: 1
           - python: "3.10"
-            geos: 3.10.2
+            geos: 3.10.3
             numpy: 1.21.3
             speedups: 0
           - python: "3.10"
-            geos: 3.10.2
+            geos: 3.10.3
+            speedups: 0
+          # 2022
+          - python: "3.10"  # switch to "3.11" when released (PEP 664)
+            geos: 3.11.0
+            numpy: 1.23.0
+            speedups: 1
+          - python: "3.10"
+            geos: 3.11.0
+            numpy: 1.23.0
+            speedups: 0
+          - python: "3.10"
+            geos: 3.11.0
             speedups: 0
           # enable two 32-bit windows builds
           - os: windows-2019
@@ -86,7 +98,7 @@ jobs:
           - os: windows-2019
             architecture: x86
             python: 3.9
-            geos: 3.10.2
+            geos: 3.10.3
             numpy: 1.19.5
             speeedups: 1
 
@@ -132,7 +144,7 @@ jobs:
 
       - name: Install python dependencies
         run: |
-          pip install --disable-pip-version-check --user --upgrade pip
+          python -m pip install --disable-pip-version-check --user --upgrade pip
           pip install --upgrade wheel setuptools
           if [ "$SPEEDUPS" == "1" ]; then
             pip install --install-option="--no-cython-compile" cython;


=====================================
CHANGES.txt
=====================================
@@ -1,6 +1,31 @@
 Changes
 =======
 
+1.8.3 (2022-08-16)
+------------------
+
+Deprecations:
+
+The STRtree class will be changed in 2.0.0 and will not be compatible with the
+class in versions 1.8.x. This change obsoletes the deprecation announcement in
+1.8a3 (below).
+
+Packaging:
+
+Wheels for 1.8.3 published on PyPI include GEOS 3.10.3.
+
+Bug fixes:
+
+- The signature for GEOSMinimumClearance has been corrected, fixing an issue
+  affecting aarch64-darwin (#1480)
+- Return and arg types have been corrected and made more strict for area,
+  length, and distance properties.
+- A new c_geom_p type has been created to replace c_void_p when calling GEOS
+  functions (#1479).
+- An incorrect polygon-line intersection (#1427) has been fixed in GEOS 3.10.3,
+  which will be included in wheels published to PyPI.
+- GEOS buffer parameters are now destroyed, fixing a memory leak (#1440)..
+
 1.8.2 (2022-05-03)
 ------------------
 
@@ -23,7 +48,7 @@ install from source.
 Packaging:
 
 Wheels for 1.8.1 published on PyPI include GEOS 3.10.2. This version is the
-best version of GDAL yet. Discrepancies in behavior compared to previous
+best version of GEOS yet. Discrepancies in behavior compared to previous
 versions are considered to be improvements.
 
 For the first time, we will publish wheels for macos_arm64 (see PR #1310).


=====================================
pyproject.toml
=====================================
@@ -1,2 +1,6 @@
 [build-system]
-requires = ["setuptools", "wheel", "cython>=0.29.24", "oldest-supported-numpy"]
+requires = [
+    "Cython>=0.29.24,<3",
+    "oldest-supported-numpy",
+    "setuptools<64",
+]


=====================================
shapely/__init__.py
=====================================
@@ -1 +1 @@
-__version__ = "1.8.2"
+__version__ = "1.8.3"


=====================================
shapely/ctypes_declarations.py
=====================================
@@ -3,8 +3,19 @@
 See header file: geos-x.y.z/capi/geos_c.h
 '''
 
-from ctypes import CFUNCTYPE, POINTER, c_void_p, c_char_p, \
-    c_size_t, c_byte, c_uint, c_int, c_double, py_object
+from ctypes import (
+    CFUNCTYPE,
+    POINTER,
+    Structure,
+    c_void_p,
+    c_char_p,
+    c_size_t,
+    c_byte,
+    c_uint,
+    c_int,
+    c_double,
+    py_object,
+)
 
 from .errors import UnsupportedGEOSVersionError
 
@@ -20,6 +31,13 @@ class allocated_c_char_p(c_char_p):
     pass
 
 
+class GEOSGeom_t(Structure):
+    pass
+
+
+c_geom_p = POINTER(GEOSGeom_t)
+
+
 def prototype(lgeos, geos_version):
     """Protype functions in geos_c.h for different version of GEOS
 
@@ -132,6 +150,9 @@ def prototype(lgeos, geos_version):
     lgeos.GEOSBufferParams_create.restype = c_void_p
     lgeos.GEOSBufferParams_create.argtypes = None
 
+    lgeos.GEOSBufferParams_destroy.restype = None
+    lgeos.GEOSBufferParams_destroy.argtypes = [c_void_p]
+
     lgeos.GEOSBufferParams_setEndCapStyle.restype = c_int
     lgeos.GEOSBufferParams_setEndCapStyle.argtypes = [c_void_p, c_int]
 
@@ -152,25 +173,25 @@ def prototype(lgeos, geos_version):
 
     # Geometry constructors
 
-    lgeos.GEOSGeom_createPoint.restype = c_void_p
+    lgeos.GEOSGeom_createPoint.restype = c_geom_p
     lgeos.GEOSGeom_createPoint.argtypes = [c_void_p]
 
-    lgeos.GEOSGeom_createLinearRing.restype = c_void_p
+    lgeos.GEOSGeom_createLinearRing.restype = c_geom_p
     lgeos.GEOSGeom_createLinearRing.argtypes = [c_void_p]
 
-    lgeos.GEOSGeom_createLineString.restype = c_void_p
+    lgeos.GEOSGeom_createLineString.restype = c_geom_p
     lgeos.GEOSGeom_createLineString.argtypes = [c_void_p]
 
-    lgeos.GEOSGeom_createPolygon.restype = c_void_p
-    lgeos.GEOSGeom_createPolygon.argtypes = [c_void_p, c_void_p, c_uint]
+    lgeos.GEOSGeom_createPolygon.restype = c_geom_p
+    lgeos.GEOSGeom_createPolygon.argtypes = [c_geom_p, POINTER(c_geom_p), c_uint]
 
-    lgeos.GEOSGeom_createCollection.restype = c_void_p
-    lgeos.GEOSGeom_createCollection.argtypes = [c_int, c_void_p, c_uint]
+    lgeos.GEOSGeom_createCollection.restype = c_geom_p
+    lgeos.GEOSGeom_createCollection.argtypes = [c_int, POINTER(c_geom_p), c_uint]
 
-    lgeos.GEOSGeom_createEmptyCollection.restype = c_void_p
+    lgeos.GEOSGeom_createEmptyCollection.restype = c_geom_p
     lgeos.GEOSGeom_createEmptyCollection.argtypes = [c_int]
 
-    lgeos.GEOSGeom_clone.restype = c_void_p
+    lgeos.GEOSGeom_clone.restype = c_geom_p
     lgeos.GEOSGeom_clone.argtypes = [c_void_p]
 
     # Memory management
@@ -222,9 +243,13 @@ def prototype(lgeos, geos_version):
     lgeos.GEOSPolygonize.restype = c_void_p
     lgeos.GEOSPolygonize.argtypes = [c_void_p, c_uint]
 
-    lgeos.GEOSPolygonize_full.restype = c_void_p
+    lgeos.GEOSPolygonize_full.restype = c_geom_p
     lgeos.GEOSPolygonize_full.argtypes = [
-        c_void_p, c_void_p, c_void_p, c_void_p]
+        c_geom_p,
+        POINTER(c_geom_p),
+        POINTER(c_geom_p),
+        POINTER(c_geom_p),
+    ]
 
     if geos_version >= (3, 4, 0):
         lgeos.GEOSDelaunayTriangulation.restype = c_void_p
@@ -393,17 +418,17 @@ def prototype(lgeos, geos_version):
 
     # Misc functions
 
-    lgeos.GEOSArea.restype = c_double
-    lgeos.GEOSArea.argtypes = [c_void_p, c_void_p]
+    lgeos.GEOSArea.restype = c_int
+    lgeos.GEOSArea.argtypes = [c_geom_p, POINTER(c_double)]
 
     lgeos.GEOSLength.restype = c_int
-    lgeos.GEOSLength.argtypes = [c_void_p, c_void_p]
+    lgeos.GEOSLength.argtypes = [c_geom_p, POINTER(c_double)]
 
     lgeos.GEOSDistance.restype = c_int
-    lgeos.GEOSDistance.argtypes = [c_void_p, c_void_p, c_void_p]
+    lgeos.GEOSDistance.argtypes = [c_geom_p, c_geom_p, POINTER(c_double)]
 
     lgeos.GEOSHausdorffDistance.restype = c_int
-    lgeos.GEOSHausdorffDistance.argtypes = [c_void_p, c_void_p, c_void_p]
+    lgeos.GEOSHausdorffDistance.argtypes = [c_geom_p, c_geom_p, POINTER(c_double)]
 
     # Reader and Writer APIs
 
@@ -521,8 +546,8 @@ def prototype(lgeos, geos_version):
             c_void_p, py_object, c_void_p, lgeos.GEOSDistanceCallback, py_object]
         lgeos.GEOSSTRtree_nearest_generic.restype = c_void_p
 
-        lgeos.GEOSMinimumClearance.argtypes = [c_void_p]
-        lgeos.GEOSMinimumClearance.restype = c_double
+        lgeos.GEOSMinimumClearance.argtypes = [c_geom_p, POINTER(c_double)]
+        lgeos.GEOSMinimumClearance.restype = c_int
 
     if geos_version >= (3, 8, 0):
         lgeos.GEOSMakeValid.restype = c_void_p


=====================================
shapely/geometry/base.py
=====================================
@@ -7,7 +7,7 @@ different z values may intersect or be equal.
 """
 
 from binascii import a2b_hex
-from ctypes import pointer, c_size_t, c_char_p, c_void_p
+from ctypes import cast, pointer, c_size_t, c_char_p, c_void_p
 from itertools import islice
 import logging
 import math
@@ -18,6 +18,7 @@ import warnings
 
 from shapely.affinity import affine_transform
 from shapely.coords import CoordinateSequence
+from shapely.ctypes_declarations import c_geom_p
 from shapely.errors import GeometryTypeError, WKBReadingError, WKTReadingError
 from shapely.errors import ShapelyDeprecationWarning
 from shapely.geos import WKBWriter, WKTWriter
@@ -107,10 +108,11 @@ def geos_geom_from_py(ob, create_func=None):
     This behaviour is useful for converting between LineString and LinearRing
     objects.
     """
+    geom_ptr = cast(ob._geom, c_geom_p)
     if create_func is None:
-        geom = lgeos.GEOSGeom_clone(ob._geom)
+        geom = lgeos.GEOSGeom_clone(geom_ptr)
     else:
-        cs = lgeos.GEOSGeom_getCoordSeq(ob._geom)
+        cs = lgeos.GEOSGeom_getCoordSeq(geom_ptr)
         cs = lgeos.GEOSCoordSeq_clone(cs)
         geom = create_func(cs)
 
@@ -625,12 +627,16 @@ class BaseGeometry:
 
         if 'buffer_with_params' in self.impl:
             params = self._lgeos.GEOSBufferParams_create()
-            self._lgeos.GEOSBufferParams_setEndCapStyle(params, cap_style)
-            self._lgeos.GEOSBufferParams_setJoinStyle(params, join_style)
-            self._lgeos.GEOSBufferParams_setMitreLimit(params, mitre_limit)
-            self._lgeos.GEOSBufferParams_setQuadrantSegments(params, res)
-            self._lgeos.GEOSBufferParams_setSingleSided(params, single_sided)
-            return geom_factory(self.impl['buffer_with_params'](self, params, distance))
+            try:
+                self._lgeos.GEOSBufferParams_setEndCapStyle(params, cap_style)
+                self._lgeos.GEOSBufferParams_setJoinStyle(params, join_style)
+                self._lgeos.GEOSBufferParams_setMitreLimit(params, mitre_limit)
+                self._lgeos.GEOSBufferParams_setQuadrantSegments(params, res)
+                self._lgeos.GEOSBufferParams_setSingleSided(params, single_sided)
+                return geom_factory(self.impl['buffer_with_params'](self, params, distance))
+            finally:
+                if params:
+                    self._lgeos.GEOSBufferParams_destroy(params)
 
         if cap_style == CAP_STYLE.round and join_style == JOIN_STYLE.round:
             return geom_factory(self.impl['buffer'](self, distance, res))


=====================================
shapely/geometry/collection.py
=====================================
@@ -3,6 +3,7 @@
 
 from ctypes import c_void_p
 
+from shapely.ctypes_declarations import c_geom_p
 from shapely.geos import lgeos
 from shapely.geometry.base import BaseGeometry
 from shapely.geometry.base import BaseMultipartGeometry
@@ -63,7 +64,7 @@ def geos_geometrycollection_from_py(ob):
          ob = ob.geoms
     L = len(ob)
     N = 2
-    subs = (c_void_p * L)()
+    subs = (c_geom_p * L)()
     for l in range(L):
         assert(isinstance(ob[l], BaseGeometry))
         if ob[l].has_z:


=====================================
shapely/geometry/multilinestring.py
=====================================
@@ -4,6 +4,7 @@
 from ctypes import c_void_p, cast
 import warnings
 
+from shapely.ctypes_declarations import c_geom_p
 from shapely.errors import EmptyPartError, ShapelyDeprecationWarning
 from shapely.geos import lgeos
 from shapely.geometry.base import BaseMultipartGeometry, geos_geom_from_py
@@ -116,9 +117,9 @@ def asMultiLineString(context):
 
 
 def geos_multilinestring_from_py(ob):
-    # ob must be either a MultiLineString, a sequence, or 
+    # ob must be either a MultiLineString, a sequence, or
     # array of sequences or arrays
-    
+
     if isinstance(ob, MultiLineString):
          return geos_geom_from_py(ob)
 
@@ -134,8 +135,8 @@ def geos_multilinestring_from_py(ob):
         raise ValueError("Invalid coordinate dimensionality")
 
     # Array of pointers to point geometries
-    subs = (c_void_p * L)()
-    
+    subs = (c_geom_p * L)()
+
     # add to coordinate sequence
     for l in range(L):
         geom, ndims = linestring.geos_linestring_from_py(obs[l])
@@ -143,6 +144,6 @@ def geos_multilinestring_from_py(ob):
         if lgeos.GEOSisEmpty(geom):
             raise EmptyPartError("Can't create MultiLineString with empty component")
 
-        subs[l] = cast(geom, c_void_p)
-            
+        subs[l] = cast(geom, c_geom_p)
+
     return (lgeos.GEOSGeom_createCollection(5, subs, L), N)


=====================================
shapely/geometry/multipoint.py
=====================================
@@ -4,6 +4,7 @@
 from ctypes import byref, c_double, c_void_p, cast
 import warnings
 
+from shapely.ctypes_declarations import c_geom_p
 from shapely.errors import EmptyPartError, ShapelyDeprecationWarning
 from shapely.geos import lgeos
 from shapely.geometry.base import (
@@ -194,7 +195,7 @@ def geos_multipoint_from_py(ob):
     assert n == 2 or n == 3
 
     # Array of pointers to point geometries
-    subs = (c_void_p * m)()
+    subs = (c_geom_p * m)()
 
     # add to coordinate sequence
     for i in range(m):
@@ -204,6 +205,6 @@ def geos_multipoint_from_py(ob):
         if lgeos.GEOSisEmpty(geom):
             raise EmptyPartError("Can't create MultiPoint with empty component")
 
-        subs[i] = cast(geom, c_void_p)
+        subs[i] = cast(geom, c_geom_p)
 
     return lgeos.GEOSGeom_createCollection(4, subs, m), n


=====================================
shapely/geometry/multipolygon.py
=====================================
@@ -4,6 +4,7 @@
 from ctypes import c_void_p, cast
 import warnings
 
+from shapely.ctypes_declarations import c_geom_p
 from shapely.errors import ShapelyDeprecationWarning
 from shapely.geos import lgeos
 from shapely.geometry.base import BaseMultipartGeometry, geos_geom_from_py
@@ -146,10 +147,10 @@ def geos_multipolygon_from_py(ob):
     N = len(ob[0][0][0])
     assert N == 2 or N == 3
 
-    subs = (c_void_p * L)()
+    subs = (c_geom_p * L)()
     for l in range(L):
         geom, ndims = polygon.geos_polygon_from_py(ob[l][0], ob[l][1:])
-        subs[l] = cast(geom, c_void_p)
+        subs[l] = cast(geom, c_geom_p)
 
     return (lgeos.GEOSGeom_createCollection(6, subs, L), N)
 
@@ -192,7 +193,7 @@ def geos_multipolygon_from_polygons(arg):
 
     assert N == 2 or N == 3
 
-    subs = (c_void_p * L)()
+    subs = (c_geom_p * L)()
 
     for i, ob in enumerate(obs):
         if isinstance(ob, polygon.Polygon):
@@ -203,6 +204,6 @@ def geos_multipolygon_from_polygons(arg):
             holes = ob[1]
 
         geom, ndims = polygon.geos_polygon_from_py(shell, holes)
-        subs[i] = cast(geom, c_void_p)
+        subs[i] = cast(geom, c_geom_p)
 
     return (lgeos.GEOSGeom_createCollection(6, subs, L), N)


=====================================
shapely/geometry/polygon.py
=====================================
@@ -9,6 +9,7 @@ import weakref
 
 from shapely.algorithms.cga import signed_area
 from shapely.coords import CoordinateSequence
+from shapely.ctypes_declarations import c_geom_p
 from shapely.geos import lgeos
 from shapely.geometry.base import BaseGeometry, geos_geom_from_py
 from shapely.geometry.linestring import LineString, LineStringAdapter
@@ -555,16 +556,17 @@ def geos_polygon_from_py(shell, holes=None):
                 raise ValueError("insufficiant coordinate dimension")
 
             # Array of pointers to ring geometries
-            geos_holes = (c_void_p * L)()
+            geos_holes = (c_geom_p * L)()
 
             # add to coordinate sequence
             for l in range(L):
                 geom, ndim = geos_linearring_from_py(ob[l])
-                geos_holes[l] = cast(geom, c_void_p)
+                geos_holes[l] = cast(geom, c_geom_p)
         else:
-            geos_holes = POINTER(c_void_p)()
+            geos_holes = POINTER(c_geom_p)()
             L = 0
 
         return (
-            lgeos.GEOSGeom_createPolygon(
-                c_void_p(geos_shell), geos_holes, L), ndim)
+            lgeos.GEOSGeom_createPolygon(cast(geos_shell, c_geom_p), geos_holes, L),
+            ndim,
+        )


=====================================
shapely/geometry/proxy.py
=====================================
@@ -34,14 +34,17 @@ class CachingGeometryProxy:
                 self.__geom__, n = self.factory(self.context)
         self._gtag = gtag
         return self.__geom__
-        
+
     def gtag(self):
         return hash(repr(self.context))
 
     def __setattr__(self, name, value):
         # to override the custom one in BaseGeometry, so we don't warn
         # for the proxy classes, which are already deprecated itself
-        object.__setattr__(self, name, value)
+        try:
+            object.__setattr__(self, name, value)
+        except AttributeError:
+            pass
 
 
 class PolygonProxy(CachingGeometryProxy):


=====================================
shapely/ops.py
=====================================
@@ -1,9 +1,10 @@
 """Support for various GEOS geometry operations
 """
 
-from ctypes import byref, c_void_p, c_double
+from ctypes import byref, cast, c_void_p, c_double
 from warnings import warn
 
+from shapely.ctypes_declarations import c_geom_p
 from shapely.errors import GeometryTypeError, ShapelyDeprecationWarning
 from shapely.prepared import prep
 from shapely.geos import lgeos
@@ -44,12 +45,16 @@ class CollectionOperator:
             source = [source]
         finally:
             obs = [self.shapeup(l) for l in source]
-        geom_array_type = c_void_p * len(obs)
+
+        geom_array_type = c_geom_p * len(obs)
         geom_array = geom_array_type()
+
         for i, line in enumerate(obs):
-            geom_array[i] = line._geom
+            geom_array[i] = cast(line._geom, c_geom_p)
+
         product = lgeos.GEOSPolygonize(byref(geom_array), len(obs))
         collection = geom_factory(product)
+
         for g in collection.geoms:
             clone = lgeos.GEOSGeom_clone(g._geom)
             g = geom_factory(clone)
@@ -78,16 +83,21 @@ class CollectionOperator:
             source = [source]
         finally:
             obs = [self.shapeup(l) for l in source]
+
         L = len(obs)
-        subs = (c_void_p * L)()
+        subs = (c_geom_p * L)()
+
         for i, g in enumerate(obs):
-            subs[i] = g._geom
+            subs[i] = cast(g._geom, c_geom_p)
+
         collection = lgeos.GEOSGeom_createCollection(5, subs, L)
-        dangles = c_void_p()
-        cuts = c_void_p()
-        invalids = c_void_p()
+        dangles = c_geom_p()
+        cuts = c_geom_p()
+        invalids = c_geom_p()
         product = lgeos.GEOSPolygonize_full(
-            collection, byref(dangles), byref(cuts), byref(invalids))
+            collection, byref(dangles), byref(cuts), byref(invalids)
+        )
+
         return (
             geom_factory(product),
             geom_factory(dangles),
@@ -135,9 +145,12 @@ class CollectionOperator:
         except TypeError:
             geoms = [geoms]
             L = 1
-        subs = (c_void_p * L)()
+
+        subs = (c_geom_p * L)()
+
         for i, g in enumerate(geoms):
-            subs[i] = g._geom
+            subs[i] = cast(g._geom, c_geom_p)
+
         collection = lgeos.GEOSGeom_createCollection(6, subs, L)
         return geom_factory(lgeos.methods['cascaded_union'](collection))
 
@@ -154,9 +167,12 @@ class CollectionOperator:
         except TypeError:
             geoms = [geoms]
             L = 1
-        subs = (c_void_p * L)()
+
+        subs = (c_geom_p * L)()
+
         for i, g in enumerate(geoms):
-            subs[i] = g._geom
+            subs[i] = cast(g._geom, c_geom_p)
+
         collection = lgeos.GEOSGeom_createCollection(6, subs, L)
         return geom_factory(lgeos.methods['unary_union'](collection))
 


=====================================
shapely/strtree.py
=====================================
@@ -22,7 +22,10 @@ import ctypes
 import logging
 from typing import Any, ItemsView, Iterable, Iterator, Optional, Sequence, Tuple, Union
 import sys
+from warnings import warn
 
+from shapely.ctypes_declarations import c_geom_p
+from shapely.errors import ShapelyDeprecationWarning
 from shapely.geometry.base import BaseGeometry
 from shapely.geos import lgeos
 
@@ -97,6 +100,19 @@ class STRtree:
         items: Iterable[Any] = None,
         node_capacity: int = 10,
     ):
+        if items is not None:
+            warn(
+                "STRtree will be changed in 2.0.0 and will not be compatible with versions < 2. "
+                "Specifically: the items keyword argument will be removed.",
+                ShapelyDeprecationWarning,
+                stacklevel=2,
+            )
+        else:
+            warn(
+                "STRtree will be changed in 2.0.0 and will not be compatible with versions < 2.",
+                ShapelyDeprecationWarning,
+                stacklevel=2,
+            )
         self.node_capacity = node_capacity
 
         # Keep references to geoms
@@ -247,8 +263,11 @@ class STRtree:
                 if callback_userdata["exclusive"] and self._geoms[idx].equals(geom2):
                     dist[0] = sys.float_info.max
                 else:
-                    lgeos.GEOSDistance(self._geoms[idx]._geom, geom2._geom, dist)
-                
+                    lgeos.GEOSDistance(
+                        ctypes.cast(self._geoms[idx]._geom, c_geom_p),
+                        ctypes.cast(geom2._geom, c_geom_p),
+                        dist,
+                    )
                 return 1
             except Exception:
                 log.exception("Caught exception")


=====================================
shapely/topology.py
=====================================
@@ -7,7 +7,9 @@ to GEOS functions via ctypes.
 These methods return ctypes objects that should be recast by the caller.
 """
 
-from ctypes import byref, c_double
+from ctypes import byref, cast, c_double
+
+from shapely.ctypes_declarations import c_geom_p
 from shapely.geos import TopologicalError, lgeos
 from shapely.errors import InvalidGeometryError
 
@@ -47,7 +49,9 @@ class BinaryRealProperty(Delegating):
         self._validate(this)
         self._validate(other, stop_prepared=True)
         d = c_double()
-        retval = self.fn(this._geom, other._geom, byref(d))
+        retval = self.fn(
+            cast(this._geom, c_geom_p), cast(other._geom, c_geom_p), byref(d)
+        )
         return d.value
 
 
@@ -56,7 +60,7 @@ class UnaryRealProperty(Delegating):
     def __call__(self, this):
         self._validate(this)
         d = c_double()
-        retval = self.fn(this._geom, byref(d))
+        retval = self.fn(cast(this._geom, c_geom_p), byref(d))
         return d.value
 
 


=====================================
tests/test_geos_err_handler.py
=====================================
@@ -19,7 +19,8 @@ def test_error_handler_exception(tmpdir):
     with pytest.raises(ReadingError):
         loads('POINT (LOLWUT)')
 
-    log = open(logfile).read()
+    with open(logfile) as fobj:
+        log = fobj.read()
     assert "Expected number but encountered word: 'LOLWUT'" in log
 
 
@@ -33,7 +34,8 @@ def test_error_handler(tmpdir):
     # has *no* conversion specifiers.
     LineString([(0, 0), (2, 2)]).project(LineString([(1, 1), (1.5, 1.5)]))
 
-    log = open(logfile).read()
+    with open(logfile) as fobj:
+        log = fobj.read()
     assert "third argument of GEOSProject_r must be Point" in log
 
 
@@ -57,7 +59,8 @@ def test_info_handler(tmpdir):
     g = loads('MULTIPOLYGON (((10 20, 10 120, 60 70, 30 70, 30 40, 60 40, 60 70, 90 20, 10 20)))')
     assert not g.is_valid
 
-    log = open(logfile).read()
+    with open(logfile) as fobj:
+        log = fobj.read()
     assert "Ring Self-intersection at or near point 60 70" in log
 
 
@@ -71,5 +74,6 @@ def test_info_handler_quiet(tmpdir):
     g = loads('MULTIPOLYGON (((10 20, 10 120, 60 70, 30 70, 30 40, 60 40, 60 70, 90 20, 10 20)))')
     assert not g.is_valid
 
-    log = open(logfile).read()
+    with open(logfile) as fobj:
+        log = fobj.read()
     assert "Ring Self-intersection at or near point 60 70" not in log


=====================================
tests/test_linear_referencing.py
=====================================
@@ -1,5 +1,7 @@
+import pytest
+
 from . import unittest
-from shapely.errors import GeometryTypeError
+from shapely.errors import GeometryTypeError, ShapelyDeprecationWarning
 from shapely.geometry import Point, LineString, MultiLineString
 
 
@@ -28,8 +30,9 @@ class LinearReferencingTestCase(unittest.TestCase):
             self.multiline.project(self.point, normalized=True), 0.125)
 
     def test_not_supported_project(self):
-        with self.assertRaises(GeometryTypeError):
-            self.point.buffer(1.0).project(self.point)
+        with pytest.warns(ShapelyDeprecationWarning):
+            with self.assertRaises(GeometryTypeError):
+                self.point.buffer(1.0).project(self.point)
 
     def test_not_on_line_project(self):
         # Points that aren't on the line project to 0.


=====================================
tests/test_parallel_offset.py
=====================================
@@ -9,9 +9,11 @@ class OperationsTestCase(unittest.TestCase):
         left = line1.parallel_offset(5, 'left')
         self.assertEqual(left, LineString([(0, 5), (10, 5)]))
         right = line1.parallel_offset(5, 'right')
-        self.assertEqual(right, LineString([(10, -5), (0, -5)]))
+        # using spatial equality because the order of coordinates is not guaranteed
+        # (GEOS 3.11 changed this, see https://github.com/shapely/shapely/issues/1436)
+        assert right.equals(LineString([(10, -5), (0, -5)]))
         right = line1.parallel_offset(-5, 'left')
-        self.assertEqual(right, LineString([(10, -5), (0, -5)]))
+        assert right.equals(LineString([(10, -5), (0, -5)]))
         left = line1.parallel_offset(-5, 'right')
         self.assertEqual(left, LineString([(0, 5), (10, 5)]))
 


=====================================
tests/test_shared_paths.py
=====================================
@@ -1,16 +1,19 @@
+import pytest
+
 from . import unittest
 
-from shapely.errors import GeometryTypeError
+from shapely.errors import GeometryTypeError, ShapelyDeprecationWarning
 from shapely.geometry import Point, LineString, Polygon, MultiLineString, \
                              GeometryCollection
 from shapely.ops import shared_paths
 
+
 class SharedPaths(unittest.TestCase):
     def test_shared_paths_forward(self):
         g1 = LineString([(0, 0), (10, 0), (10, 5), (20, 5)])
         g2 = LineString([(5, 0), (15, 0)])
         result = shared_paths(g1, g2)
-        
+
         self.assertTrue(isinstance(result, GeometryCollection))
         self.assertTrue(len(result.geoms) == 2)
         a, b = result.geoms
@@ -23,7 +26,7 @@ class SharedPaths(unittest.TestCase):
         g1 = LineString([(0, 0), (10, 0), (10, 5), (20, 5)])
         g2 = LineString([(15, 0), (5, 0)])
         result = shared_paths(g1, g2)
-        
+
         self.assertTrue(isinstance(result, GeometryCollection))
         self.assertTrue(len(result.geoms) == 2)
         a, b = result.geoms
@@ -31,13 +34,15 @@ class SharedPaths(unittest.TestCase):
         self.assertTrue(len(b.geoms) == 1)
         self.assertEqual(b.geoms[0].coords[:], [(5, 0), (10, 0)])
         self.assertTrue(a.is_empty)
-    
+
     def test_wrong_type(self):
         g1 = Point(0, 0)
         g2 = LineString([(5, 0), (15, 0)])
-        
-        with self.assertRaises(GeometryTypeError):
-            result = shared_paths(g1, g2)
-            
-        with self.assertRaises(GeometryTypeError):
-            result = shared_paths(g2, g1)
+
+        with pytest.warns(ShapelyDeprecationWarning):
+            with self.assertRaises(GeometryTypeError):
+                result = shared_paths(g1, g2)
+
+        with pytest.warns(ShapelyDeprecationWarning):
+            with self.assertRaises(GeometryTypeError):
+                result = shared_paths(g2, g1)


=====================================
tests/test_split.py
=====================================
@@ -1,230 +1,247 @@
-from shapely.ops import split
+import pytest
 
 from . import unittest
 
-from shapely.errors import GeometryTypeError
+from shapely.errors import GeometryTypeError, ShapelyDeprecationWarning
 from shapely.geometry import Point, MultiPoint, LineString, MultiLineString, Polygon, MultiPolygon, GeometryCollection
-from shapely.ops import linemerge, unary_union
+from shapely.ops import linemerge, split, unary_union
 
 class TestSplitGeometry(unittest.TestCase):
-	# helper class for testing below
-	def helper(self, geom, splitter, expected_chunks):
-		s = split(geom, splitter)
-		self.assertEqual(s.type, "GeometryCollection")
-		self.assertEqual(len(s.geoms), expected_chunks)
-		if expected_chunks > 1:
-			# split --> expected collection that when merged is again equal to original geometry
-			if s.geoms[0].type == 'LineString':
-				self.assertTrue(linemerge(s).simplify(0.000001).equals(geom))
-			elif s.geoms[0].type == 'Polygon':
-				union = unary_union(s).simplify(0.000001)
-				self.assertTrue(union.equals(geom))
-				self.assertEqual(union.area, geom.area)
-			else:
-				raise ValueError
-		elif expected_chunks == 1:
-			# not split --> expected equal to line
-			self.assertTrue(s.geoms[0].equals(geom))
-
-	def test_split_closed_line_with_point(self):
-		# point at start/end of closed ring -> return equal
-		# see GH #524
-		ls = LineString([(0,0), (0, 1), (1, 1), (1, 0), (0, 0)])
-		splitter = Point(0, 0)
-		self.helper(ls, splitter, 1)
+    # helper class for testing below
+    def helper(self, geom, splitter, expected_chunks):
+        s = split(geom, splitter)
+        self.assertEqual(s.type, "GeometryCollection")
+        self.assertEqual(len(s.geoms), expected_chunks)
+        if expected_chunks > 1:
+            # split --> expected collection that when merged is again equal to original geometry
+            if s.geoms[0].type == "LineString":
+                self.assertTrue(linemerge(s).simplify(0.000001).equals(geom))
+            elif s.geoms[0].type == "Polygon":
+                union = unary_union(s).simplify(0.000001)
+                self.assertTrue(union.equals(geom))
+                self.assertEqual(union.area, geom.area)
+            else:
+                raise ValueError
+        elif expected_chunks == 1:
+            # not split --> expected equal to line
+            self.assertTrue(s.geoms[0].equals(geom))
+
+    def test_split_closed_line_with_point(self):
+        # point at start/end of closed ring -> return equal
+        # see GH #524
+        ls = LineString([(0, 0), (0, 1), (1, 1), (1, 0), (0, 0)])
+        splitter = Point(0, 0)
+        self.helper(ls, splitter, 1)
 
 
 class TestSplitPolygon(TestSplitGeometry):
-	poly_simple = Polygon([(0, 0), (2, 0), (2, 2), (0, 2), (0, 0)])
-	poly_hole = Polygon([(0, 0), (2, 0), (2, 2), (0, 2), (0, 0)], [[(0.5, 0.5), (0.5, 1.5), (1.5, 1.5), (1.5, 0.5), (0.5, 0.5)]])
-
-	def test_split_poly_with_line(self):
-		# crossing at 2 points --> return 2 segments
-		splitter = LineString([(1, 3), (1, -3)])
-		self.helper(self.poly_simple, splitter, 2)
-		self.helper(self.poly_hole, splitter, 2)
-
-		# touching the boundary--> return equal
-		splitter = LineString([(0, 2), (5, 2)])
-		self.helper(self.poly_simple, splitter, 1)
-		self.helper(self.poly_hole, splitter, 1)
-
-		# inside the polygon --> return equal
-		splitter = LineString([(0.2, 0.2), (1.7, 1.7), (3, 2)])
-		self.helper(self.poly_simple, splitter, 1)
-		self.helper(self.poly_hole, splitter, 1)
-
-		# outside the polygon --> return equal
-		splitter = LineString([(0, 3), (3, 3) , (3, 0)])
-		self.helper(self.poly_simple, splitter, 1)
-		self.helper(self.poly_hole, splitter, 1)
-
-	def test_split_poly_with_other(self):
-		with self.assertRaises(GeometryTypeError):
-			split(self.poly_simple, Point(1, 1))
-		with self.assertRaises(GeometryTypeError):
-			split(self.poly_simple, MultiPoint([(1, 1), (3, 4)]))
-		with self.assertRaises(GeometryTypeError):
-			split(self.poly_simple, self.poly_hole)
+    poly_simple = Polygon([(0, 0), (2, 0), (2, 2), (0, 2), (0, 0)])
+    poly_hole = Polygon(
+        [(0, 0), (2, 0), (2, 2), (0, 2), (0, 0)],
+        [[(0.5, 0.5), (0.5, 1.5), (1.5, 1.5), (1.5, 0.5), (0.5, 0.5)]],
+    )
+
+    def test_split_poly_with_line(self):
+        # crossing at 2 points --> return 2 segments
+        splitter = LineString([(1, 3), (1, -3)])
+        self.helper(self.poly_simple, splitter, 2)
+        self.helper(self.poly_hole, splitter, 2)
+
+        # touching the boundary--> return equal
+        splitter = LineString([(0, 2), (5, 2)])
+        self.helper(self.poly_simple, splitter, 1)
+        self.helper(self.poly_hole, splitter, 1)
+
+        # inside the polygon --> return equal
+        splitter = LineString([(0.2, 0.2), (1.7, 1.7), (3, 2)])
+        self.helper(self.poly_simple, splitter, 1)
+        self.helper(self.poly_hole, splitter, 1)
+
+        # outside the polygon --> return equal
+        splitter = LineString([(0, 3), (3, 3), (3, 0)])
+        self.helper(self.poly_simple, splitter, 1)
+        self.helper(self.poly_hole, splitter, 1)
+
+    def test_split_poly_with_point(self):
+        with pytest.warns(ShapelyDeprecationWarning):
+            with self.assertRaises(GeometryTypeError):
+                split(self.poly_simple, Point(1, 1))
+
+    def test_split_poly_with_multipoint(self):
+        with pytest.warns(ShapelyDeprecationWarning):
+            with self.assertRaises(GeometryTypeError):
+                split(self.poly_simple, MultiPoint([(1, 1), (3, 4)]))
+
+    def test_split_poly_with_poly(self):
+        with pytest.warns(ShapelyDeprecationWarning):
+            with self.assertRaises(GeometryTypeError):
+                split(self.poly_simple, self.poly_hole)
 
 class TestSplitLine(TestSplitGeometry):
-	ls = LineString([(0, 0), (1.5, 1.5), (3.0, 4.0)])
-
-	def test_split_line_with_point(self):
-		# point on line interior --> return 2 segments
-		splitter = Point(1, 1)
-		self.helper(self.ls, splitter, 2)
-
-		# point on line point --> return 2 segments
-		splitter = Point(1.5, 1.5)
-		self.helper(self.ls, splitter, 2)
-
-		# point on boundary --> return equal
-		splitter = Point(3, 4)
-		self.helper(self.ls, splitter, 1)
-
-		# point on exterior of line --> return equal
-		splitter = Point(2, 2)
-		self.helper(self.ls, splitter, 1)
-
-	def test_split_line_with_multipoint(self):
-		# points on line interior --> return 4 segments
-		splitter = MultiPoint([(1,1), (1.5, 1.5), (0.5, 0.5)])
-		self.helper(self.ls, splitter, 4)
-
-		# points on line interior and boundary -> return 2 segments
-		splitter = MultiPoint([(1, 1), (3, 4)])
-		self.helper(self.ls, splitter, 2)
-
-		# point on linear interior but twice --> return 2 segments
-		splitter = MultiPoint([(1, 1), (1.5, 1.5), (1, 1)])
-		self.helper(self.ls, splitter, 3)
-
-	def test_split_line_with_line(self):
-		# crosses at one point --> return 2 segments
-		splitter = LineString([(0, 1), (1, 0)])
-		self.helper(self.ls, splitter, 2)
-
-		# crosses at two points --> return 3 segments
-		splitter = LineString([(0, 1), (1, 0), (1, 2)])
-		self.helper(self.ls, splitter, 3)
-
-		# overlaps --> raise
-		splitter = LineString([(0, 0), (15, 15)])
-		with self.assertRaises(ValueError):
-			self.helper(self.ls, splitter, 1)
-
-		# does not cross --> return equal
-		splitter = LineString([(0, 1), (0, 2)])
-		self.helper(self.ls, splitter, 1)
-
-		# is touching the boundary --> return equal
-		splitter = LineString([(-1, 1), (1, -1)])
-		self.assertTrue(splitter.touches(self.ls))
-		self.helper(self.ls, splitter, 1)
-
-		# splitter boundary touches interior of line --> return 2 segments
-		splitter = LineString([(0, 1), (1, 1)])  # touches at (1, 1)
-		self.assertTrue(splitter.touches(self.ls))
-		self.helper(self.ls, splitter, 2)
-
-	def test_split_line_with_multiline(self):
-		# crosses at one point --> return 2 segments
-		splitter = MultiLineString([[(0, 1), (1, 0)], [(0, 0), (2, -2)]])
-		self.helper(self.ls, splitter, 2)
-
-		# crosses at two points --> return 3 segments
-		splitter = MultiLineString([[(0, 1), (1, 0)], [(0, 2), (2, 0)]])
-		self.helper(self.ls, splitter, 3)
-
-		# crosses at three points --> return 4 segments
-		splitter = MultiLineString([[(0, 1), (1, 0)], [(0, 2), (2, 0), (2.2, 3.2)]])
-		self.helper(self.ls, splitter, 4)
-
-		# overlaps --> raise
-		splitter = MultiLineString([[(0, 0), (1.5, 1.5)], [(1.5, 1.5), (3, 4)]])
-		with self.assertRaises(ValueError):
-			self.helper(self.ls, splitter, 1)
-
-		# does not cross --> return equal
-		splitter = MultiLineString([[(0, 1), (0, 2)], [(1, 0), (2, 0)]])
-		self.helper(self.ls, splitter, 1)
-
-	def test_split_line_with_polygon(self):
-		# crosses at two points --> return 3 segments
-		splitter = Polygon([(1, 0), (1, 2), (2, 2), (2, 0), (1, 0)])
-		self.helper(self.ls, splitter, 3)
-
-		# crosses at one point and touches boundary --> return 2 segments
-		splitter = Polygon([(0, 0), (1, 2), (2, 2), (1, 0), (0, 0)])
-		self.helper(self.ls, splitter, 2)
-
-		# exterior crosses at one point and touches at (0, 0)
-		# interior crosses at two points
-		splitter = Polygon([(0, 0), (2, 0), (2, 2), (0, 2), (0, 0)], [[(0.5, 0.5), (0.5, 1.5), (1.5, 1.5), (1.5, 0.5), (0.5, 0.5)]])
-		self.helper(self.ls, splitter, 4)
-
-	def test_split_line_with_multipolygon(self):
-		poly1 = Polygon([(0, 0), (2, 0), (2, 2), (0, 2), (0, 0)]) # crosses at one point and touches at (0, 0)
-		poly2 = Polygon([(0.5, 0.5), (0.5, 1.5), (1.5, 1.5), (1.5, 0.5), (0.5, 0.5)]) # crosses at two points
-		poly3 = Polygon([(0, 0), (0, -2), (-2, -2), (-2, 0), (0, 0)]) # not crossing
-		splitter = MultiPolygon([poly1, poly2, poly3])
-		self.helper(self.ls, splitter, 4)
+    ls = LineString([(0, 0), (1.5, 1.5), (3.0, 4.0)])
+
+    def test_split_line_with_point(self):
+        # point on line interior --> return 2 segments
+        splitter = Point(1, 1)
+        self.helper(self.ls, splitter, 2)
+
+        # point on line point --> return 2 segments
+        splitter = Point(1.5, 1.5)
+        self.helper(self.ls, splitter, 2)
+
+        # point on boundary --> return equal
+        splitter = Point(3, 4)
+        self.helper(self.ls, splitter, 1)
+
+        # point on exterior of line --> return equal
+        splitter = Point(2, 2)
+        self.helper(self.ls, splitter, 1)
+
+    def test_split_line_with_multipoint(self):
+        # points on line interior --> return 4 segments
+        splitter = MultiPoint([(1, 1), (1.5, 1.5), (0.5, 0.5)])
+        self.helper(self.ls, splitter, 4)
+
+        # points on line interior and boundary -> return 2 segments
+        splitter = MultiPoint([(1, 1), (3, 4)])
+        self.helper(self.ls, splitter, 2)
+
+        # point on linear interior but twice --> return 2 segments
+        splitter = MultiPoint([(1, 1), (1.5, 1.5), (1, 1)])
+        self.helper(self.ls, splitter, 3)
+
+    def test_split_line_with_line(self):
+        # crosses at one point --> return 2 segments
+        splitter = LineString([(0, 1), (1, 0)])
+        self.helper(self.ls, splitter, 2)
+
+        # crosses at two points --> return 3 segments
+        splitter = LineString([(0, 1), (1, 0), (1, 2)])
+        self.helper(self.ls, splitter, 3)
+
+        # overlaps --> raise
+        splitter = LineString([(0, 0), (15, 15)])
+        with self.assertRaises(ValueError):
+            self.helper(self.ls, splitter, 1)
+
+        # does not cross --> return equal
+        splitter = LineString([(0, 1), (0, 2)])
+        self.helper(self.ls, splitter, 1)
+
+        # is touching the boundary --> return equal
+        splitter = LineString([(-1, 1), (1, -1)])
+        self.assertTrue(splitter.touches(self.ls))
+        self.helper(self.ls, splitter, 1)
+
+        # splitter boundary touches interior of line --> return 2 segments
+        splitter = LineString([(0, 1), (1, 1)])  # touches at (1, 1)
+        self.assertTrue(splitter.touches(self.ls))
+        self.helper(self.ls, splitter, 2)
+
+    def test_split_line_with_multiline(self):
+        # crosses at one point --> return 2 segments
+        splitter = MultiLineString([[(0, 1), (1, 0)], [(0, 0), (2, -2)]])
+        self.helper(self.ls, splitter, 2)
+
+        # crosses at two points --> return 3 segments
+        splitter = MultiLineString([[(0, 1), (1, 0)], [(0, 2), (2, 0)]])
+        self.helper(self.ls, splitter, 3)
+
+        # crosses at three points --> return 4 segments
+        splitter = MultiLineString([[(0, 1), (1, 0)], [(0, 2), (2, 0), (2.2, 3.2)]])
+        self.helper(self.ls, splitter, 4)
+
+        # overlaps --> raise
+        splitter = MultiLineString([[(0, 0), (1.5, 1.5)], [(1.5, 1.5), (3, 4)]])
+        with self.assertRaises(ValueError):
+            self.helper(self.ls, splitter, 1)
+
+        # does not cross --> return equal
+        splitter = MultiLineString([[(0, 1), (0, 2)], [(1, 0), (2, 0)]])
+        self.helper(self.ls, splitter, 1)
+
+    def test_split_line_with_polygon(self):
+        # crosses at two points --> return 3 segments
+        splitter = Polygon([(1, 0), (1, 2), (2, 2), (2, 0), (1, 0)])
+        self.helper(self.ls, splitter, 3)
+
+        # crosses at one point and touches boundary --> return 2 segments
+        splitter = Polygon([(0, 0), (1, 2), (2, 2), (1, 0), (0, 0)])
+        self.helper(self.ls, splitter, 2)
+
+        # exterior crosses at one point and touches at (0, 0)
+        # interior crosses at two points
+        splitter = Polygon(
+            [(0, 0), (2, 0), (2, 2), (0, 2), (0, 0)],
+            [[(0.5, 0.5), (0.5, 1.5), (1.5, 1.5), (1.5, 0.5), (0.5, 0.5)]],
+        )
+        self.helper(self.ls, splitter, 4)
+
+    def test_split_line_with_multipolygon(self):
+        poly1 = Polygon(
+            [(0, 0), (2, 0), (2, 2), (0, 2), (0, 0)]
+        )  # crosses at one point and touches at (0, 0)
+        poly2 = Polygon(
+            [(0.5, 0.5), (0.5, 1.5), (1.5, 1.5), (1.5, 0.5), (0.5, 0.5)]
+        )  # crosses at two points
+        poly3 = Polygon([(0, 0), (0, -2), (-2, -2), (-2, 0), (0, 0)])  # not crossing
+        splitter = MultiPolygon([poly1, poly2, poly3])
+        self.helper(self.ls, splitter, 4)
 
 class TestSplitClosedRing(TestSplitGeometry):
-	ls = LineString([[0, 0], [0, 1], [1, 1], [1, 0], [0, 0]])
+    ls = LineString([[0, 0], [0, 1], [1, 1], [1, 0], [0, 0]])
 
-	def test_split_closed_ring_with_point(self):
-		splitter = Point([0.0, 0.0])
-		self.helper(self.ls, splitter, 1)
+    def test_split_closed_ring_with_point(self):
+        splitter = Point([0.0, 0.0])
+        self.helper(self.ls, splitter, 1)
 
-		splitter = Point([0.0, 0.5])
-		self.helper(self.ls, splitter, 2)
-		result = split(self.ls, splitter)
-		assert result.geoms[0].coords[:] == [(0, 0), (0.0, 0.5)]
-		assert result.geoms[1].coords[:] == [(0.0, 0.5), (0, 1), (1, 1), (1, 0), (0, 0)]
+        splitter = Point([0.0, 0.5])
+        self.helper(self.ls, splitter, 2)
+        result = split(self.ls, splitter)
+        assert result.geoms[0].coords[:] == [(0, 0), (0.0, 0.5)]
+        assert result.geoms[1].coords[:] == [(0.0, 0.5), (0, 1), (1, 1), (1, 0), (0, 0)]
 
-		# previously failed, see GH#585
-		splitter = Point([0.5, 0.0])
-		self.helper(self.ls, splitter, 2)
-		result = split(self.ls, splitter)
-		assert result.geoms[0].coords[:] == [(0, 0), (0, 1), (1, 1), (1, 0), (0.5, 0)]
-		assert result.geoms[1].coords[:] == [(0.5, 0), (0, 0)]
+        # previously failed, see GH#585
+        splitter = Point([0.5, 0.0])
+        self.helper(self.ls, splitter, 2)
+        result = split(self.ls, splitter)
+        assert result.geoms[0].coords[:] == [(0, 0), (0, 1), (1, 1), (1, 0), (0.5, 0)]
+        assert result.geoms[1].coords[:] == [(0.5, 0), (0, 0)]
 
-		splitter = Point([2.0, 2.0])
-		self.helper(self.ls, splitter, 1)
+        splitter = Point([2.0, 2.0])
+        self.helper(self.ls, splitter, 1)
 
 
 class TestSplitMulti(TestSplitGeometry):
 
-	def test_split_multiline_with_point(self):
-		# a cross-like multilinestring with a point in the middle --> return 4 line segments
-		l1 = LineString([(0, 1), (2, 1)])
-		l2 = LineString([(1, 0), (1, 2)])
-		ml = MultiLineString([l1, l2])
-		splitter = Point((1, 1))
-		self.helper(ml, splitter, 4)
-
-	def test_split_multiline_with_multipoint(self):
-		# a cross-like multilinestring with a point in middle, a point on one of the lines and a point in the exterior
-		# --> return 4+1 line segments
-		l1 = LineString([(0, 1), (3, 1)])
-		l2 = LineString([(1, 0), (1, 2)])
-		ml = MultiLineString([l1, l2])
-		splitter = MultiPoint([(1, 1), (2, 1), (4, 2)])
-		self.helper(ml, splitter, 5)
-
-	def test_split_multipolygon_with_line(self):
-		# two polygons with a crossing line --> return 4 triangles
-		poly1 = Polygon([(0, 0), (1, 0), (1, 1), (0, 1), (0, 0)])
-		poly2 = Polygon([(1, 1), (1, 2), (2, 2), (2, 1), (1, 1)])
-		mpoly = MultiPolygon([poly1, poly2])
-		ls = LineString([(-1, -1), (3, 3)])
-		self.helper(mpoly, ls, 4)
-
-		# two polygons away from the crossing line --> return identity
-		poly1 = Polygon([(10, 10), (10, 11), (11, 11), (11, 10), (10, 10)])
-		poly2 = Polygon([(-10, -10), (-10, -11), (-11, -11), (-11, -10), (-10, -10)])
-		mpoly = MultiPolygon([poly1, poly2])
-		ls = LineString([(-1, -1), (3, 3)])
-		self.helper(mpoly, ls, 2)
+    def test_split_multiline_with_point(self):
+        # a cross-like multilinestring with a point in the middle --> return 4 line segments
+        l1 = LineString([(0, 1), (2, 1)])
+        l2 = LineString([(1, 0), (1, 2)])
+        ml = MultiLineString([l1, l2])
+        splitter = Point((1, 1))
+        self.helper(ml, splitter, 4)
+
+    def test_split_multiline_with_multipoint(self):
+        # a cross-like multilinestring with a point in middle, a point on one of the lines and a point in the exterior
+        # --> return 4+1 line segments
+        l1 = LineString([(0, 1), (3, 1)])
+        l2 = LineString([(1, 0), (1, 2)])
+        ml = MultiLineString([l1, l2])
+        splitter = MultiPoint([(1, 1), (2, 1), (4, 2)])
+        self.helper(ml, splitter, 5)
+
+    def test_split_multipolygon_with_line(self):
+        # two polygons with a crossing line --> return 4 triangles
+        poly1 = Polygon([(0, 0), (1, 0), (1, 1), (0, 1), (0, 0)])
+        poly2 = Polygon([(1, 1), (1, 2), (2, 2), (2, 1), (1, 1)])
+        mpoly = MultiPolygon([poly1, poly2])
+        ls = LineString([(-1, -1), (3, 3)])
+        self.helper(mpoly, ls, 4)
+
+        # two polygons away from the crossing line --> return identity
+        poly1 = Polygon([(10, 10), (10, 11), (11, 11), (11, 10), (10, 10)])
+        poly2 = Polygon([(-10, -10), (-10, -11), (-11, -11), (-11, -10), (-10, -10)])
+        mpoly = MultiPolygon([poly1, poly2])
+        ls = LineString([(-1, -1), (3, 3)])
+        self.helper(mpoly, ls, 2)


=====================================
tests/test_strtree.py
=====================================
@@ -6,6 +6,7 @@ import sys
 
 import pytest
 
+from shapely.errors import ShapelyDeprecationWarning
 from shapely.geometry import Point, Polygon, box
 from shapely.geos import geos_version
 from shapely import strtree
@@ -26,7 +27,8 @@ empty = wkt.loads("GEOMETRYCOLLECTION EMPTY")
     [(Point(2, 2).buffer(0.99), 1), (Point(2, 2).buffer(1.0), 3)],
 )
 def test_query(geoms, query_geom, num_results):
-    tree = STRtree(geoms)
+    with pytest.warns(ShapelyDeprecationWarning):
+        tree = STRtree(geoms)
     results = tree.query(query_geom)
     assert len(results) == num_results
 
@@ -39,7 +41,8 @@ def test_query(geoms, query_geom, num_results):
 )
 def test_query_enumeration_idx(geoms, query_geom, expected):
     """Store enumeration idx"""
-    tree = STRtree(geoms, range(len(geoms)))
+    with pytest.warns(ShapelyDeprecationWarning):
+        tree = STRtree(geoms, range(len(geoms)))
     results = tree.query_items(query_geom)
     assert sorted(results) == sorted(expected)
 
@@ -53,7 +56,8 @@ def test_query_enumeration_idx(geoms, query_geom, expected):
 )
 def test_query_items(geoms, items, query_geom, expected):
     """Store enumeration idx"""
-    tree = STRtree(geoms, items)
+    with pytest.warns(ShapelyDeprecationWarning):
+        tree = STRtree(geoms, items)
     results = tree.query_items(query_geom)
     expected = [items[idx] for idx in expected] if items is not None else expected
     assert sorted(results) == sorted(expected)
@@ -70,7 +74,8 @@ def test_query_items(geoms, items, query_geom, expected):
     ],
 )
 def test_query_items_with_empty(tree_geometry, geometry, expected):
-    tree = STRtree(tree_geometry)
+    with pytest.warns(ShapelyDeprecationWarning):
+        tree = STRtree(tree_geometry)
     assert tree.query_items(geometry) == expected
 
 
@@ -82,7 +87,8 @@ def test_insert_empty_geometry():
     """
     empty = Polygon()
     geoms = [empty]
-    tree = STRtree(geoms)
+    with pytest.warns(ShapelyDeprecationWarning):
+        tree = STRtree(geoms)
     query = Polygon([(0, 0), (1, 1), (2, 0), (0, 0)])
     results = tree.query(query)
     assert len(results) == 0
@@ -97,7 +103,8 @@ def test_query_empty_geometry():
     empty = Polygon()
     point = Point(1, 0.5)
     geoms = [empty, point]
-    tree = STRtree(geoms)
+    with pytest.warns(ShapelyDeprecationWarning):
+        tree = STRtree(geoms)
     query = Polygon([(0, 0), (1, 1), (2, 0), (0, 0)])
     results = tree.query(query)
     assert len(results) == 1
@@ -110,7 +117,8 @@ def test_references():
     empty = Polygon()
     point = Point(1, 0.5)
     geoms = [empty, point]
-    tree = STRtree(geoms)
+    with pytest.warns(ShapelyDeprecationWarning):
+        tree = STRtree(geoms)
 
     empty = None
     point = None
@@ -124,7 +132,8 @@ def test_references():
 
 @requires_geos_342
 def test_safe_delete():
-    tree = STRtree([])
+    with pytest.warns(ShapelyDeprecationWarning):
+        tree = STRtree([])
 
     _lgeos = strtree.lgeos
     strtree.lgeos = None
@@ -139,7 +148,8 @@ def test_pickle_persistence():
     """
     Don't crash trying to use unpickled GEOS handle.
     """
-    tree = STRtree([Point(i, i).buffer(0.1) for i in range(3)], range(3))
+    with pytest.warns(ShapelyDeprecationWarning):
+        tree = STRtree([Point(i, i).buffer(0.1) for i in range(3)], range(3))
 
     pickled_strtree = pickle.dumps(tree)
     unpickle_script_file_path = os.path.join(os.path.dirname(os.path.abspath(__file__)), "unpickle-strtree.py")
@@ -165,7 +175,8 @@ def test_pickle_persistence():
 )
 @pytest.mark.parametrize("query_geom", [Point(0, 0.4)])
 def test_nearest_geom(geoms, query_geom):
-    tree = STRtree(geoms)
+    with pytest.warns(ShapelyDeprecationWarning):
+        tree = STRtree(geoms)
     result = tree.nearest(query_geom)
     assert result.geom_type == "Point"
     assert result.x == 0.0
@@ -186,19 +197,22 @@ def test_nearest_geom(geoms, query_geom):
 @pytest.mark.parametrize("items", [list(range(1, 4)), list("abc")])
 @pytest.mark.parametrize("query_geom", [Point(0, 0.4)])
 def test_nearest_item(geoms, items, query_geom):
-    tree = STRtree(geoms, items)
+    with pytest.warns(ShapelyDeprecationWarning):
+        tree = STRtree(geoms, items)
     assert tree.nearest_item(query_geom) == items[0]
 
 
 @pytest.mark.parametrize(["geoms", "items"], [([], None), ([], [])])
 def test_nearest_empty(geoms, items):
-    tree = STRtree(geoms, items)
+    with pytest.warns(ShapelyDeprecationWarning):
+        tree = STRtree(geoms, items)
     assert tree.nearest_item(None) is None
 
 
 @pytest.mark.parametrize(["geoms", "items"], [([], None), ([], [])])
 def test_nearest_items(geoms, items):
-    tree = STRtree(geoms, items)
+    with pytest.warns(ShapelyDeprecationWarning):
+        tree = STRtree(geoms, items)
     assert tree.nearest_item(None) is None
 
 
@@ -216,5 +230,6 @@ def test_nearest_items(geoms, items):
 @pytest.mark.parametrize("items", [list(range(1, 4)), list("abc")])
 @pytest.mark.parametrize("query_geom", [Point(0, 0.5)])
 def test_nearest_item_exclusive(geoms, items, query_geom):
-    tree = STRtree(geoms, items)
+    with pytest.warns(ShapelyDeprecationWarning):
+        tree = STRtree(geoms, items)
     assert tree.nearest_item(query_geom, exclusive=True) != items[0]


=====================================
tests/test_substring.py
=====================================
@@ -1,7 +1,9 @@
 import json
 
+import pytest
+
 from . import unittest
-from shapely.errors import GeometryTypeError
+from shapely.errors import GeometryTypeError, ShapelyDeprecationWarning
 from shapely.ops import substring
 from shapely.geometry import Point, LineString, shape
 
@@ -106,7 +108,8 @@ class SubstringTestCase(unittest.TestCase):
         assert len(cut_line.coords) == 53
 
     def test_raise_type_error(self):
-        self.assertRaises(GeometryTypeError, substring, Point(0, 0), 0, 0)
+        with pytest.warns(ShapelyDeprecationWarning):
+            self.assertRaises(GeometryTypeError, substring, Point(0, 0), 0, 0)
 
 
 data_issue_848 = '{"type": "LineString", "coordinates": [[-87.71314, 41.96793], [-87.71312, 41.96667], [-87.71311, 41.96643], [-87.7131, 41.96635], [-87.71309, 41.9663], [-87.71303, 41.96621], [-87.71298, 41.96615], [-87.71292, 41.96611], [-87.7128, 41.96607], [-87.71268, 41.96605], [-87.71255, 41.96605], [-87.7124, 41.96605], [-87.71219, 41.96605], [-87.71173, 41.96606], [-87.71108, 41.96607], [-87.71027, 41.96607], [-87.70884, 41.96609], [-87.70763, 41.96611], [-87.70645, 41.96612], [-87.70399, 41.96613], [-87.70267, 41.96614], [-87.70166, 41.96615], [-87.70075, 41.96615], [-87.69954, 41.96615], [-87.69873, 41.96616], [-87.69789, 41.96618], [-87.69675, 41.9662], [-87.69502, 41.96621], [-87.69411, 41.96621], [-87.69145, 41.96623], [-87.69026, 41.96624], [-87.68946, 41.96625], [-87.6885, 41.96625], [-87.68718, 41.96628], [-87.68545, 41.96631], [-87.68399, 41.96632], [-87.68271, 41.96635], [-87.68159, 41.96636], [-87.68034, 41.96638], [-87.67863, 41.96641], [-87.67766, 41.96642], [-87.67741, 41.96641], [-87.67722, 41.9664], [-87.67695, 41.96638], [-87.67665, 41.96632], [-87.67638, 41.96623], [-87.67613, 41.96612], [-87.67589, 41.96596], [-87.6757, 41.96579], [-87.67557, 41.96565], [-87.67544, 41.96547], [-87.67539, 41.96536], [-87.6753, 41.96519], [-87.67524, 41.96503], [-87.67523, 41.96491], [-87.67522, 41.96477], [-87.67521, 41.96457], [-87.6752, 41.96434], [-87.67519, 41.96371], [-87.67517, 41.96175], [-87.67513, 41.96077], [-87.67505, 41.95798], [-87.67501, 41.95666], [-87.67497, 41.95513], [-87.67496, 41.95452], [-87.67491, 41.95392], [-87.67487, 41.95302], [-87.67485, 41.95202], [-87.67484, 41.95101], [-87.67479, 41.94959], [-87.67476, 41.94859], [-87.67474, 41.94703], [-87.67468, 41.94596], [-87.67466, 41.94513], [-87.67463, 41.94494], [-87.67457, 41.94474], [-87.6745, 41.94455], [-87.67442, 41.94438], [-87.6743, 41.94424], [-87.67419, 41.94414], [-87.67405, 41.94404], [-87.67386, 41.94393], [-87.67367, 41.94386], [-87.67348, 41.9438], [-87.67334, 41.94376], [-87.67311, 41.94373], [-87.67289, 41.9437], [-87.67263, 41.94369], [-87.67234, 41.94369], [-87.6715, 41.9437], [-87.67088, 41.94371], [-87.66938, 41.94373], [-87.66749, 41.94377], [-87.66585, 41.94378], [-87.66508, 41.94379], [-87.66361, 41.94381], [-87.6591, 41.94391], [-87.65767, 41.94391], [-87.65608, 41.94393], [-87.6555, 41.94394], [-87.65521, 41.94394], [-87.65503, 41.94393], [-87.65488, 41.9439], [-87.6547, 41.94386], [-87.65454, 41.9438], [-87.65441, 41.94375], [-87.65425, 41.94364], [-87.6541, 41.94351], [-87.654, 41.94342], [-87.65392, 41.94331], [-87.65382, 41.94319], [-87.65375, 41.94306], [-87.65367, 41.94292], [-87.65361, 41.9428], [-87.65355, 41.94269], [-87.65351, 41.94257], [-87.65347, 41.94238], [-87.65345, 41.94218], [-87.65338, 41.93975], [-87.65337, 41.93939], [-87.65337, 41.93893], [-87.65336, 41.93865], [-87.65333, 41.93763], [-87.65331, 41.93717], [-87.65328, 41.93627], [-87.65327, 41.93603], [-87.65323, 41.93532], [-87.65322, 41.93491], [-87.6532, 41.93445], [-87.65314, 41.93312], [-87.65313, 41.93273], [-87.6531, 41.93218], [-87.65307, 41.93151], [-87.65305, 41.9309], [-87.65302, 41.9303], [-87.65299, 41.92951], [-87.65296, 41.9287], [-87.65295, 41.92842], [-87.65294, 41.92768], [-87.65292, 41.92715], [-87.65289, 41.92599], [-87.65288, 41.92537], [-87.65287, 41.92505], [-87.65282, 41.92352], [-87.65276, 41.92172], [-87.65274, 41.92113], [-87.65264, 41.91822], [-87.65264, 41.91808], [-87.65262, 41.91763], [-87.65261, 41.91718], [-87.65255, 41.91563], [-87.6525, 41.91406], [-87.65242, 41.91377], [-87.65234, 41.91362], [-87.65223, 41.91351], [-87.65208, 41.91339], [-87.65183, 41.91322], [-87.65093, 41.9126], [-87.65017, 41.91203], [-87.64985, 41.9118], [-87.64971, 41.91171], [-87.64957, 41.91164], [-87.64948, 41.9116], [-87.64939, 41.91158], [-87.6492, 41.91153], [-87.649, 41.9115], [-87.64883, 41.9115], [-87.64863, 41.9115], [-87.64792, 41.91151], [-87.64781, 41.9115], [-87.64768, 41.91146], [-87.64756, 41.91139], [-87.64745, 41.91122], [-87.6474, 41.91112], [-87.64739, 41.91101], [-87.64738, 41.91086], [-87.64736, 41.91071], [-87.64734, 41.91061], [-87.64728, 41.91051], [-87.64718, 41.91044], [-87.64709, 41.9104], [-87.64697, 41.91036], [-87.64682, 41.91034], [-87.64664, 41.91033], [-87.64646, 41.91033], [-87.6458, 41.91034], [-87.64523, 41.91034], [-87.64348, 41.91036], [-87.64255, 41.91039], [-87.641, 41.9104], [-87.64038, 41.9104], [-87.63975, 41.9104], [-87.6393, 41.91041], [-87.63814, 41.91042], [-87.63798, 41.91041], [-87.63787, 41.91039], [-87.63771, 41.91034], [-87.63757, 41.91027], [-87.63746, 41.91021], [-87.63736, 41.91011], [-87.6373, 41.90999], [-87.63727, 41.90986], [-87.63726, 41.90973], [-87.63725, 41.90951], [-87.63723, 41.90874], [-87.63718, 41.90758], [-87.63713, 41.90607], [-87.63711, 41.90543], [-87.63702, 41.90381], [-87.63702, 41.90368], [-87.63701, 41.90334], [-87.63699, 41.90322], [-87.63694, 41.90312], [-87.63688, 41.90299], [-87.63682, 41.90292], [-87.63671, 41.90279], [-87.63659, 41.90265], [-87.63653, 41.90255], [-87.63649, 41.90245], [-87.63646, 41.90235], [-87.63647, 41.90221], [-87.63647, 41.90211], [-87.6365, 41.90202], [-87.63653, 41.9019], [-87.63659, 41.90177], [-87.63666, 41.90156], [-87.63669, 41.90143], [-87.6367, 41.90131], [-87.6367, 41.90119], [-87.63664, 41.90029], [-87.63664, 41.90008], [-87.63662, 41.89975], [-87.63658, 41.89892], [-87.63657, 41.89867], [-87.63654, 41.89761], [-87.63654, 41.89738], [-87.63649, 41.89726], [-87.63641, 41.89715], [-87.63634, 41.89708], [-87.63623, 41.89699], [-87.63595, 41.89677], [-87.63583, 41.89667], [-87.63574, 41.89654], [-87.63569, 41.89645], [-87.63568, 41.89633], [-87.63565, 41.89542], [-87.63563, 41.89434], [-87.6356, 41.89327], [-87.63558, 41.89261], [-87.63554, 41.89147], [-87.63553, 41.89051], [-87.63548, 41.8903], [-87.6354, 41.89021], [-87.63533, 41.89012], [-87.63524, 41.89007], [-87.63508, 41.89001], [-87.63493, 41.88997], [-87.63475, 41.88994], [-87.63462, 41.88991], [-87.63447, 41.88989], [-87.63436, 41.88984], [-87.63425, 41.88979], [-87.63414, 41.8897], [-87.63407, 41.88962], [-87.63402, 41.88952], [-87.63399, 41.88943], [-87.63397, 41.88897], [-87.63396, 41.88707], [-87.63391, 41.88572], [-87.63389, 41.88441], [-87.63385, 41.8827], [-87.63384, 41.88144], [-87.63378, 41.88014], [-87.63374, 41.87872], [-87.63369, 41.87726], [-87.63369, 41.87706], [-87.63365, 41.87695], [-87.63359, 41.87691], [-87.63353, 41.87688], [-87.63345, 41.87686], [-87.63338, 41.87685], [-87.63263, 41.87685], [-87.63173, 41.87686], [-87.62925, 41.87689], [-87.62821, 41.87691], [-87.62757, 41.87693], [-87.6265, 41.87696], [-87.62635, 41.87696], [-87.62603, 41.87697], [-87.62605, 41.87831], [-87.6261, 41.87951], [-87.62616, 41.88203], [-87.62619, 41.88322], [-87.62622, 41.88443], [-87.62626, 41.88534], [-87.62625, 41.88552], [-87.62625, 41.88557], [-87.62627, 41.88562], [-87.6263, 41.88566], [-87.62635, 41.88569], [-87.62642, 41.88572], [-87.6265, 41.88573], [-87.62655, 41.88574], [-87.62661, 41.88574], [-87.62683, 41.88574], [-87.62784, 41.88574], [-87.62887, 41.88574], [-87.62948, 41.88574], [-87.62982, 41.88574], [-87.62992, 41.88574], [-87.63011, 41.88574], [-87.6302, 41.88574], [-87.63089, 41.88574], [-87.63204, 41.88574], [-87.63285, 41.88573], [-87.63391, 41.88572], [-87.63396, 41.88707], [-87.63397, 41.88897], [-87.63399, 41.88943], [-87.63402, 41.88952], [-87.63407, 41.88962], [-87.63414, 41.8897], [-87.63425, 41.88979], [-87.63436, 41.88984], [-87.63447, 41.88989], [-87.63462, 41.88991], [-87.63475, 41.88994], [-87.63493, 41.88997], [-87.63508, 41.89001], [-87.63524, 41.89007], [-87.63533, 41.89012], [-87.6354, 41.89021], [-87.63548, 41.8903], [-87.63553, 41.89051], [-87.63554, 41.89147], [-87.63558, 41.89261], [-87.6356, 41.89327], [-87.63563, 41.89434], [-87.63565, 41.89542], [-87.63568, 41.89633], [-87.63569, 41.89645], [-87.63574, 41.89654], [-87.63583, 41.89667], [-87.63595, 41.89677], [-87.63623, 41.89699], [-87.63634, 41.89708], [-87.63641, 41.89715], [-87.63649, 41.89726], [-87.63654, 41.89738], [-87.63654, 41.89761], [-87.63657, 41.89867], [-87.63658, 41.89892], [-87.63662, 41.89975], [-87.63664, 41.90008], [-87.63664, 41.90029], [-87.6367, 41.90119], [-87.6367, 41.90131], [-87.63669, 41.90143], [-87.63666, 41.90156], [-87.63659, 41.90177], [-87.63653, 41.9019], [-87.6365, 41.90202], [-87.63647, 41.90211], [-87.63647, 41.90221], [-87.63646, 41.90235], [-87.63649, 41.90245], [-87.63653, 41.90255], [-87.63659, 41.90265], [-87.63671, 41.90279], [-87.63682, 41.90292], [-87.63688, 41.90299], [-87.63694, 41.90312], [-87.63699, 41.90322], [-87.63701, 41.90334], [-87.63702, 41.90368], [-87.63702, 41.90381], [-87.63711, 41.90543], [-87.63713, 41.90607], [-87.63718, 41.90758], [-87.63723, 41.90874], [-87.63725, 41.90951], [-87.63726, 41.90973], [-87.63727, 41.90986], [-87.6373, 41.90999], [-87.63736, 41.91011], [-87.63746, 41.91021], [-87.63757, 41.91027], [-87.63771, 41.91034], [-87.63787, 41.91039], [-87.63798, 41.91041], [-87.63814, 41.91042], [-87.6393, 41.91041], [-87.63975, 41.9104], [-87.64038, 41.9104], [-87.641, 41.9104], [-87.64255, 41.91039], [-87.64348, 41.91036], [-87.64523, 41.91034], [-87.6458, 41.91034], [-87.64646, 41.91033], [-87.64664, 41.91033], [-87.64682, 41.91034], [-87.64697, 41.91036], [-87.64709, 41.9104], [-87.64718, 41.91044], [-87.64728, 41.91051], [-87.64734, 41.91061], [-87.64736, 41.91071], [-87.64738, 41.91086], [-87.64739, 41.91101], [-87.6474, 41.91112], [-87.64745, 41.91122], [-87.64756, 41.91139], [-87.64768, 41.91146], [-87.64781, 41.9115], [-87.64792, 41.91151], [-87.64863, 41.9115], [-87.64883, 41.9115], [-87.649, 41.9115], [-87.6492, 41.91153], [-87.64939, 41.91158], [-87.64948, 41.9116], [-87.64957, 41.91164], [-87.64971, 41.91171], [-87.64985, 41.9118], [-87.65017, 41.91203], [-87.65093, 41.9126], [-87.65183, 41.91322], [-87.65208, 41.91339], [-87.65223, 41.91351], [-87.65234, 41.91362], [-87.65242, 41.91377], [-87.6525, 41.91406], [-87.65255, 41.91563], [-87.65261, 41.91718], [-87.65262, 41.91763], [-87.65264, 41.91808], [-87.65264, 41.91822], [-87.65274, 41.92113], [-87.65276, 41.92172], [-87.65282, 41.92352], [-87.65287, 41.92505], [-87.65288, 41.92537], [-87.65289, 41.92599], [-87.65292, 41.92715], [-87.65294, 41.92768], [-87.65295, 41.92842], [-87.65296, 41.9287], [-87.65299, 41.92951], [-87.65302, 41.9303], [-87.65305, 41.9309], [-87.65307, 41.93151], [-87.6531, 41.93218], [-87.65313, 41.93273], [-87.65314, 41.93312], [-87.6532, 41.93445], [-87.65322, 41.93491], [-87.65323, 41.93532], [-87.65327, 41.93603], [-87.65328, 41.93627], [-87.65331, 41.93717], [-87.65333, 41.93763], [-87.65336, 41.93865], [-87.65337, 41.93893], [-87.65337, 41.93939], [-87.65338, 41.93975], [-87.65345, 41.94218], [-87.65347, 41.94238], [-87.65351, 41.94257], [-87.65355, 41.94269], [-87.65361, 41.9428], [-87.65367, 41.94292], [-87.65375, 41.94306], [-87.65382, 41.94319], [-87.65392, 41.94331], [-87.654, 41.94342], [-87.6541, 41.94351], [-87.65425, 41.94364], [-87.65441, 41.94375], [-87.65454, 41.9438], [-87.6547, 41.94386], [-87.65488, 41.9439], [-87.65503, 41.94393], [-87.65521, 41.94394], [-87.6555, 41.94394], [-87.65608, 41.94393], [-87.65767, 41.94391], [-87.6591, 41.94391], [-87.66361, 41.94381], [-87.66508, 41.94379], [-87.66585, 41.94378], [-87.66749, 41.94377], [-87.66938, 41.94373], [-87.67088, 41.94371], [-87.6715, 41.9437], [-87.67234, 41.94369], [-87.67263, 41.94369], [-87.67289, 41.9437], [-87.67311, 41.94373], [-87.67334, 41.94376], [-87.67348, 41.9438], [-87.67367, 41.94386], [-87.67386, 41.94393], [-87.67405, 41.94404], [-87.67419, 41.94414], [-87.6743, 41.94424], [-87.67442, 41.94438], [-87.6745, 41.94455], [-87.67457, 41.94474], [-87.67463, 41.94494], [-87.67466, 41.94513], [-87.67468, 41.94596], [-87.67474, 41.94703], [-87.67476, 41.94859], [-87.67479, 41.94959], [-87.67484, 41.95101], [-87.67485, 41.95202], [-87.67487, 41.95302], [-87.67491, 41.95392], [-87.67496, 41.95452], [-87.67497, 41.95513], [-87.67501, 41.95666], [-87.67505, 41.95798], [-87.67513, 41.96077], [-87.67517, 41.96175], [-87.67519, 41.96371], [-87.6752, 41.96434], [-87.67521, 41.96457], [-87.67522, 41.96477], [-87.67523, 41.96491], [-87.67524, 41.96503], [-87.6753, 41.96519], [-87.67539, 41.96536], [-87.67544, 41.96547], [-87.67557, 41.96565], [-87.6757, 41.96579], [-87.67589, 41.96596], [-87.67613, 41.96612], [-87.67638, 41.96623], [-87.67665, 41.96632], [-87.67695, 41.96638], [-87.67722, 41.9664], [-87.67741, 41.96641], [-87.67766, 41.96642], [-87.67863, 41.96641], [-87.68034, 41.96638], [-87.68159, 41.96636], [-87.68271, 41.96635], [-87.68399, 41.96632], [-87.68545, 41.96631], [-87.68718, 41.96628], [-87.6885, 41.96625], [-87.68946, 41.96625], [-87.69026, 41.96624], [-87.69145, 41.96623], [-87.69411, 41.96621], [-87.69502, 41.96621], [-87.69675, 41.9662], [-87.69789, 41.96618], [-87.69873, 41.96616], [-87.69954, 41.96615], [-87.70075, 41.96615], [-87.70166, 41.96615], [-87.70267, 41.96614], [-87.70399, 41.96613], [-87.70645, 41.96612], [-87.70763, 41.96611], [-87.70884, 41.96609], [-87.71027, 41.96607], [-87.71108, 41.96607], [-87.71173, 41.96606], [-87.71219, 41.96605], [-87.7124, 41.96605], [-87.71255, 41.96605], [-87.71268, 41.96605], [-87.7128, 41.96607], [-87.71292, 41.96611], [-87.71298, 41.96615], [-87.71303, 41.96621], [-87.71309, 41.9663], [-87.7131, 41.96635], [-87.71311, 41.96643], [-87.71312, 41.96667], [-87.71314, 41.96793]]}'



View it on GitLab: https://salsa.debian.org/debian-gis-team/python-shapely/-/commit/418789883d799f8e56fa45e345569495c51bc80d

-- 
View it on GitLab: https://salsa.debian.org/debian-gis-team/python-shapely/-/commit/418789883d799f8e56fa45e345569495c51bc80d
You're receiving this email because of your account on salsa.debian.org.


-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://alioth-lists.debian.net/pipermail/pkg-grass-devel/attachments/20220817/71e5aa3b/attachment-0001.htm>


More information about the Pkg-grass-devel mailing list