Repository: Toblerity/Shapely
Pull request #1176 (2021-07-28 16:15:21)

Added /opt/homebrew/lib for GEOS shared library
I added the directory /opt/homebrew/lib to the list of directories to be searched for the GEOS
  shared library. Homebrew installs into /opt/homebrew rather than /usr/local on systems with the new Apple Silicon (M1) chip.

## Expected behavior and actual behavior.

Actual behaviour of
`python -c "from shapely.geos import lgeos"`

is

```
Traceback (most recent call last):
  File "<string>", line 1, in <module>
  File "/Users/cuntz/.pyenv/versions/3.9.6/envs/test-cartopy/lib/python3.9/site-packages/shapely/geos.py", line 136, in <module>
    _lgeos = load_dll('geos_c', fallbacks=alt_paths)
  File "/Users/cuntz/.pyenv/versions/3.9.6/envs/test-cartopy/lib/python3.9/site-packages/shapely/geos.py", line 60, in load_dll
    raise OSError(
OSError: Could not find lib geos_c or load any of its variants ['/Library/Frameworks/GEOS.framework/Versions/Current/GEOS', '/opt/local/lib/libgeos_c.dylib', '/usr/local/lib/libgeos_c.dylib'].
```

## Operating system

macOS Big Sur (Version 11.5.1) on Mac mini (M1, 2020).
Python 3.9.6

## Shapely version and provenance

Current master on Github.


mayteio: +1!

Patch:
diff --git a/CHANGES.txt b/CHANGES.txt
index 8b12c78..fac3a81 100644
--- a/CHANGES.txt
+++ b/CHANGES.txt
@@ -1,8 +1,24 @@
 Changes
 =======
 
-1.8a2 (TBD)
------------
+1.8a3 (2021-08-24)
+------------------
+
+Deprecations:
+
+The STRtree class deprecation warnings have been removed. The class in 2.0.0
+will be backwards compatible with the class in 1.8.0.
+
+Bug fixes:
+
+- The __array_interface__ raises only AttributeError, all other exceptions are
+  deprecated starting with Numpy 1.21 (#1173).
+- The STRtree class now uses a pair of item, geom sequences internally instead
+  of a dict (#1177).
+
+
+1.8a2 (2021-07-15)
+------------------
 
 Python version support:
 
@@ -31,6 +47,9 @@ Bug fixes:
   geometry are avoided by never passing an empty geometry (#1134).
 - Python's builtin super() is now used only as described in PEP 3135 (#1109).
 - Only load conda GEOS dll if it exists (on Windows) (#1108).
+- Add /opt/homebrew/lib to the list of directories to be searched for the GEOS
+  shared library.
+- Added new library search path to assist app creation with cx_Freeze.
 
 1.8a1 (2021-03-03)
 ------------------
diff --git a/shapely/__init__.py b/shapely/__init__.py
index 4110415..d4b1f6d 100644
--- a/shapely/__init__.py
+++ b/shapely/__init__.py
@@ -1,1 +1,1 @@
-__version__ = "1.8a2"
+__version__ = "1.8a3"
diff --git a/shapely/_buildcfg.py b/shapely/_buildcfg.py
index 086539b..789b0cc 100644
--- a/shapely/_buildcfg.py
+++ b/shapely/_buildcfg.py
@@ -181,8 +181,10 @@ elif sys.platform == 'darwin':
                 "/Library/Frameworks/GEOS.framework/Versions/Current/GEOS",
                 # macports
                 '/opt/local/lib/libgeos_c.dylib',
-                # homebrew
+                # homebrew Intel
                 '/usr/local/lib/libgeos_c.dylib',
+                # homebrew Apple Silicon
+                '/opt/homebrew/lib/libgeos_c.dylib',
             ]
         lgeos = load_dll('geos_c', fallbacks=alt_paths)
 
diff --git a/shapely/coords.py b/shapely/coords.py
index df673b0..ce526ef 100644
--- a/shapely/coords.py
+++ b/shapely/coords.py
@@ -116,7 +116,10 @@ class CoordinateSequence:
     def _ctypes(self):
         self._update()
         has_z = self._ndim == 3
-        n = self._ndim
+        n = self._ndim or 0
+        if n == 0:
+            # ignore with NumPy 1.21 __array_interface__
+            raise AttributeError("empty geometry sequence")
         m = self.__len__()
         array_type = c_double * (m * n)
         data = array_type()
diff --git a/shapely/geometry/base.py b/shapely/geometry/base.py
index 1ad0d07..be5ff0c 100644
--- a/shapely/geometry/base.py
+++ b/shapely/geometry/base.py
@@ -309,7 +309,7 @@ class BaseGeometry:
     @property
     def __array_interface__(self):
         """Provide the Numpy array protocol."""
-        raise NotImplementedError
+        raise AttributeError("Not implemented")
 
     # Coordinate access
     # -----------------
@@ -849,8 +849,8 @@ class BaseMultipartGeometry(BaseGeometry):
     @property
     def __array_interface__(self):
         """Provide the Numpy array protocol."""
-        raise NotImplementedError("Multi-part geometries do not themselves "
-                                  "provide the array interface")
+        raise AttributeError("Multi-part geometries do not themselves "
+                             "provide the array interface")
 
     def _get_coords(self):
         raise NotImplementedError("Sub-geometries may have coordinate "
diff --git a/shapely/geometry/polygon.py b/shapely/geometry/polygon.py
index 4386eb4..fabb6f2 100644
--- a/shapely/geometry/polygon.py
+++ b/shapely/geometry/polygon.py
@@ -317,7 +317,7 @@ class Polygon(BaseGeometry):
 
     @property
     def __array_interface__(self):
-        raise NotImplementedError(
+        raise AttributeError(
         "A polygon does not itself provide the array interface. Its rings do.")
 
     def _get_coords(self):
diff --git a/shapely/geos.py b/shapely/geos.py
index fe73419..799412d 100644
--- a/shapely/geos.py
+++ b/shapely/geos.py
@@ -131,9 +131,11 @@ elif sys.platform == 'darwin':
                     os.environ['RESOURCEPATH'], '..', 'Frameworks',
                     'libgeos_c.dylib')]
             except KeyError:
-                # binary from pyinstaller
                 alt_paths = [
-                    os.path.join(sys.executable, 'libgeos_c.dylib')]
+                    # binary from pyinstaller
+                    os.path.join(sys.executable, 'libgeos_c.dylib'),
+                    # .app from cx_Freeze
+                    os.path.join(os.path.dirname(sys.executable), 'libgeos_c.1.dylib')]
                 if hasattr(sys, '_MEIPASS'):
                     alt_paths.append(
                         os.path.join(sys._MEIPASS, 'libgeos_c.1.dylib'))
@@ -143,8 +145,10 @@ elif sys.platform == 'darwin':
                 "/Library/Frameworks/GEOS.framework/Versions/Current/GEOS",
                 # macports
                 '/opt/local/lib/libgeos_c.dylib',
-                # homebrew
+                # homebrew Intel
                 '/usr/local/lib/libgeos_c.dylib',
+                # homebrew Apple Silicon
+                '/opt/homebrew/lib/libgeos_c.dylib',
             ]
         _lgeos = load_dll('geos_c', fallbacks=alt_paths)
 
diff --git a/shapely/speedups/_speedups.pyx b/shapely/speedups/_speedups.pyx
index f5b6dc2..0b49959 100644
--- a/shapely/speedups/_speedups.pyx
+++ b/shapely/speedups/_speedups.pyx
@@ -421,7 +421,10 @@ def coordseq_ctypes(self):
     cdef GEOSCoordSequence *cs
     cdef double *data_p
     self._update()
-    n = self._ndim
+    n = self._ndim or 0
+    if n == 0:
+        # ignore with NumPy 1.21 __array_interface__
+        raise AttributeError("empty geometry sequence")
     m = self.__len__()
     array_type = ctypes.c_double * (m * n)
     data = array_type()
diff --git a/shapely/strtree.py b/shapely/strtree.py
index 30c79a5..aba92c3 100644
--- a/shapely/strtree.py
+++ b/shapely/strtree.py
@@ -22,9 +22,7 @@ import ctypes
 import logging
 from typing import Any, ItemsView, Iterable, Iterator, Optional, Sequence, Tuple, Union
 import sys
-from warnings import warn
 
-from shapely.errors import ShapelyDeprecationWarning
 from shapely.geometry.base import BaseGeometry
 from shapely.geos import lgeos
 
@@ -99,49 +97,34 @@ class STRtree:
         items: Iterable[Any] = None,
         node_capacity: int = 10,
     ):
-        warn(
-            "STRtree will be changed in 2.0.0. The exact API is not yet decided, but will be documented before 1.8.0",
-            ShapelyDeprecationWarning,
-            stacklevel=2,
-        )
-        self._tree = None
         self.node_capacity = node_capacity
-        self._rev = {
-            item: geom
-            for geom, item in self._iterinitdata(geoms, items)
-            if not geom.is_empty
-        }
-        if self._rev:
-            self._init_tree(self._rev.items())
-
-    def _iterinitdata(
-        self,
-        geoms: Iterable[BaseGeometry], items: Optional[Iterable[BaseGeometry]],
-    ) -> Iterator[Tuple[BaseGeometry, Any]]:
-        if items is not None:
-            for geom, item in zip(geoms, items):
-                if isinstance(geom, BaseGeometry):
-                    yield (geom, item)
+
+        # Keep references to geoms
+        self._geoms = list(geoms)
+        # Default enumeration index to store in the tree
+        self._idxs = list(range(len(self._geoms)))
+
+        # handle items
+        self._has_custom_items = items is not None
+        if not self._has_custom_items:
+            items = self._idxs
+        self._items = items
+
+        # initialize GEOS STRtree
+        self._tree = lgeos.GEOSSTRtree_create(self.node_capacity)
+        i = 0
+        for idx, geom in zip(self._idxs, self._geoms):
+            # filter empty geometries out of the input
+            if geom is not None and not geom.is_empty:
+                lgeos.GEOSSTRtree_insert(self._tree, geom._geom, ctypes.py_object(idx))
+                i += 1
+        self._n_geoms = i
+
+    def __reduce__(self):
+        if self._has_custom_items:
+            return STRtree, (self._geoms, self._items)
         else:
-            for enum_idx, geom in enumerate(geoms):
-                if isinstance(geom, BaseGeometry):
-                    yield (geom, enum_idx)
-
-    def _init_tree(self, rev_initdata: ItemsView[Any, BaseGeometry]):
-        if rev_initdata:
-            self._tree = lgeos.GEOSSTRtree_create(self.node_capacity)
-            for item, geom in rev_initdata:
-                lgeos.GEOSSTRtree_insert(self._tree, geom._geom, ctypes.py_object(item))
-
-    def __getstate__(self):
-        state = self.__dict__.copy()
-        del state["_tree"]
-        return state
-
-    def __setstate__(self, state):
-        self.__dict__.update(state)
-        if self._rev:
-            self._init_tree(self._rev.items())
+            return STRtree, (self._geoms, )
 
     def __del__(self):
         if self._tree is not None:
@@ -152,6 +135,19 @@ class STRtree:
 
             self._tree = None
 
+    def _query(self, geom):
+        if self._n_geoms == 0:
+            return []
+
+        result = []
+
+        def callback(item, userdata):
+            idx = ctypes.cast(item, ctypes.py_object).value
+            result.append(idx)
+
+        lgeos.GEOSSTRtree_query(self._tree, geom._geom, lgeos.GEOSQueryCallback(callback), None)
+        return result
+
     def query_items(self, geom: BaseGeometry) -> Sequence[Any]:
         """Query for nodes which intersect the geom's envelope to get
         stored items.
@@ -197,19 +193,11 @@ class STRtree:
         ['POINT (2 2)']
 
         """
-        if self._tree is None or not self._rev:
-            return []
-
-        result = []
-
-        def callback(item, userdata):
-            idx = ctypes.cast(item, ctypes.py_object).value
-            result.append(idx)
-
-        lgeos.GEOSSTRtree_query(
-            self._tree, geom._geom, lgeos.GEOSQueryCallback(callback), None
-        )
-        return result
+        result = self._query(geom)
+        if self._has_custom_items:
+            return [self._items[i] for i in result]
+        else:
+            return result
 
     def query_geoms(self, geom: BaseGeometry) -> Sequence[BaseGeometry]:
         """Query for nodes which intersect the geom's envelope to get
@@ -225,8 +213,8 @@ class STRtree:
         An array or list of geometry objects.
 
         """
-        items = self.query_items(geom)
-        return [self._rev[idx] for idx in items]
+        result = self._query(geom)
+        return [self._geoms[i] for i in result]
 
     def query(self, geom: BaseGeometry) -> Sequence[BaseGeometry]:
         """Query for nodes which intersect the geom's envelope to get
@@ -247,6 +235,34 @@ class STRtree:
         """
         return self.query_geoms(geom)
 
+    def _nearest(self, geom, exclusive):
+        envelope = geom.envelope
+
+        def callback(item1, item2, distance, userdata):
+            try:
+                callback_userdata = ctypes.cast(userdata, ctypes.py_object).value
+                idx = ctypes.cast(item1, ctypes.py_object).value
+                geom2 = ctypes.cast(item2, ctypes.py_object).value
+                dist = ctypes.cast(distance, ctypes.POINTER(ctypes.c_double))
+                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)
+                
+                return 1
+            except Exception:
+                log.exception("Caught exception")
+                return 0
+
+        item = lgeos.GEOSSTRtree_nearest_generic(
+            self._tree,
+            ctypes.py_object(geom),
+            envelope._geom,
+            lgeos.GEOSDistanceCallback(callback),
+            ctypes.py_object({"exclusive": exclusive}),
+        )
+        return ctypes.cast(item, ctypes.py_object).value
+
     def nearest_item(
         self, geom: BaseGeometry, exclusive: bool = False
     ) -> Union[Any, None]:
@@ -285,35 +301,14 @@ class STRtree:
         'POINT (0 0)'
 
         """
-        if self._tree is None or not self._rev:
+        if self._n_geoms == 0:
             return None
 
-        envelope = geom.envelope
-
-        def callback(item1, item2, distance, userdata):
-            try:
-                callback_userdata = ctypes.cast(userdata, ctypes.py_object).value
-                idx = ctypes.cast(item1, ctypes.py_object).value
-                geom2 = ctypes.cast(item2, ctypes.py_object).value
-                dist = ctypes.cast(distance, ctypes.POINTER(ctypes.c_double))
-                if callback_userdata["exclusive"] and self._rev[idx].equals(geom2):
-                    dist[0] = sys.float_info.max
-                else:
-                    lgeos.GEOSDistance(self._rev[idx]._geom, geom2._geom, dist)
-                return 1
-            except Exception:
-                log.exception("Caught exception")
-                return 0
-
-        item = lgeos.GEOSSTRtree_nearest_generic(
-            self._tree,
-            ctypes.py_object(geom),
-            envelope._geom,
-            lgeos.GEOSDistanceCallback(callback),
-            ctypes.py_object({"exclusive": exclusive}),
-        )
-        result = ctypes.cast(item, ctypes.py_object).value
-        return result
+        result = self._nearest(geom, exclusive)
+        if self._has_custom_items:
+            return self._items[result]
+        else:
+            return result
 
     def nearest_geom(
         self, geom: BaseGeometry, exclusive: bool = False
@@ -337,11 +332,8 @@ class STRtree:
         version 2.0.
 
         """
-        item = self.nearest_item(geom, exclusive=exclusive)
-        if item is None:
-            return None
-        else:
-            return self._rev[item]
+        result = self._nearest(geom, exclusive)
+        return self._geoms[result]
 
     def nearest(
         self, geom: BaseGeometry, exclusive: bool = False


Test patch:
diff --git a/tests/test_collection.py b/tests/test_collection.py
index 09b5c11..5ba176b 100644
--- a/tests/test_collection.py
+++ b/tests/test_collection.py
@@ -114,3 +114,14 @@ def test_len_deprecated(geometrycollection_geojson):
     geom = shape(geometrycollection_geojson)
     with pytest.warns(ShapelyDeprecationWarning, match="__len__"):
         assert len(geom) == 2
+
+
+@shapely20_deprecated
+@pytest.mark.filterwarnings("error:An exception was ignored")  # NumPy 1.21
+def test_numpy_object_array():
+    np = pytest.importorskip("numpy")
+
+    geom = GeometryCollection([LineString([(0, 0), (1, 1)])])
+    ar = np.empty(1, object)
+    ar[:] = [geom]
+    assert ar[0] == geom
diff --git a/tests/test_dlls.py b/tests/test_dlls.py
index ca6fb07..c71da8e 100644
--- a/tests/test_dlls.py
+++ b/tests/test_dlls.py
@@ -13,8 +13,9 @@ class LoadingTestCase(unittest.TestCase):
     def test_fallbacks(self):
         load_dll('geos_c', fallbacks=[
             os.path.join(sys.prefix, "lib", "libgeos_c.dylib"), # anaconda (Mac OS X)
-            '/opt/local/lib/libgeos_c.dylib',  # MacPorts
-            '/usr/local/lib/libgeos_c.dylib',  # homebrew (Mac OS X)
+            '/opt/local/lib/libgeos_c.dylib',     # MacPorts
+            '/usr/local/lib/libgeos_c.dylib',     # homebrew (Mac OS X)
+            '/opt/homebrew/lib/libgeos_c.dylib',  # homebrew (macOS)
             os.path.join(sys.prefix, "lib", "libgeos_c.so"), # anaconda (Linux)
             'libgeos_c.so.1',
             'libgeos_c.so'])
diff --git a/tests/test_emptiness.py b/tests/test_emptiness.py
index 348266d..33e654f 100644
--- a/tests/test_emptiness.py
+++ b/tests/test_emptiness.py
@@ -69,6 +69,16 @@ class EmptinessTestCase(unittest.TestCase):
         self.assertTrue(LinearRing(empty_generator()).is_empty)
 
 
+@shapely20_deprecated
+@pytest.mark.filterwarnings("error:An exception was ignored")  # NumPy 1.21
+def test_numpy_object_array():
+    np = pytest.importorskip("numpy")
+
+    geoms = [BaseGeometry(), EmptyGeometry()]
+    arr = np.empty(2, object)
+    arr[:] = geoms
+
+
 def test_shape_empty():
     empty_mp = MultiPolygon()
     empty_json = mapping(empty_mp)
diff --git a/tests/test_linestring.py b/tests/test_linestring.py
index 2b6e7f9..a452ff7 100644
--- a/tests/test_linestring.py
+++ b/tests/test_linestring.py
@@ -87,6 +87,7 @@ def test_from_numpy():
     assert line.coords[:] == [(1.0, 2.0), (3.0, 4.0)]
 
 
+@pytest.mark.filterwarnings("error:An exception was ignored")  # NumPy 1.21
 def test_numpy_empty_linestring_coords():
     np = pytest.importorskip("numpy")
 
@@ -97,6 +98,17 @@ def test_numpy_empty_linestring_coords():
     assert la.shape == (0,)
 
 
+@shapely20_deprecated
+@pytest.mark.filterwarnings("error:An exception was ignored")  # NumPy 1.21
+def test_numpy_object_array():
+    np = pytest.importorskip("numpy")
+
+    geom = LineString([(0.0, 0.0), (0.0, 1.0)])
+    ar = np.empty(1, object)
+    ar[:] = [geom]
+    assert ar[0] == geom
+
+
 def test_from_invalid_dim():
     with pytest.raises(ValueError, match="at least 2 coordinate tuples"):
         LineString([(1, 2)])
diff --git a/tests/test_multilinestring.py b/tests/test_multilinestring.py
index bf79ddf..c6475dc 100644
--- a/tests/test_multilinestring.py
+++ b/tests/test_multilinestring.py
@@ -117,3 +117,14 @@ def test_getitem_deprecated():
     geom = MultiLineString([[[5.0, 6.0], [7.0, 8.0]]])
     with pytest.warns(ShapelyDeprecationWarning, match="__getitem__"):
         part = geom[0]
+
+
+@shapely20_deprecated
+@pytest.mark.filterwarnings("error:An exception was ignored")  # NumPy 1.21
+def test_numpy_object_array():
+    np = pytest.importorskip("numpy")
+
+    geom = MultiLineString([[[5.0, 6.0], [7.0, 8.0]]])
+    ar = np.empty(1, object)
+    ar[:] = [geom]
+    assert ar[0] == geom
diff --git a/tests/test_multipoint.py b/tests/test_multipoint.py
index afbffaf..a3e2914 100644
--- a/tests/test_multipoint.py
+++ b/tests/test_multipoint.py
@@ -129,6 +129,17 @@ def test_multipoint_array_interface_numpy_deprecated():
         np.array(geom)
 
 
+@shapely20_deprecated
+@pytest.mark.filterwarnings("error:An exception was ignored")  # NumPy 1.21
+def test_numpy_object_array():
+    np = pytest.importorskip("numpy")
+
+    geom = MultiPoint(((1.0, 2.0), (3.0, 4.0)))
+    ar = np.empty(1, object)
+    ar[:] = [geom]
+    assert ar[0] == geom
+
+
 def test_iteration_deprecated():
     geom = MultiPoint([[5.0, 6.0], [7.0, 8.0]])
     with pytest.warns(ShapelyDeprecationWarning, match="Iteration"):
diff --git a/tests/test_multipolygon.py b/tests/test_multipolygon.py
index c3982a8..878211a 100644
--- a/tests/test_multipolygon.py
+++ b/tests/test_multipolygon.py
@@ -110,3 +110,16 @@ def test_getitem_deprecated():
           [((0.25, 0.25), (0.25, 0.5), (0.5, 0.5), (0.5, 0.25))])])
     with pytest.warns(ShapelyDeprecationWarning, match="__getitem__"):
         part = geom[0]
+
+
+@shapely20_deprecated
+@pytest.mark.filterwarnings("error:An exception was ignored")  # NumPy 1.21
+def test_numpy_object_array():
+    np = pytest.importorskip("numpy")
+
+    geom = MultiPolygon(
+        [(((0.0, 0.0), (0.0, 1.0), (1.0, 1.0), (1.0, 0.0)),
+          [((0.25, 0.25), (0.25, 0.5), (0.5, 0.5), (0.5, 0.25))])])
+    ar = np.empty(1, object)
+    ar[:] = [geom]
+    assert ar[0] == geom
diff --git a/tests/test_point.py b/tests/test_point.py
index 264118c..4a80564 100644
--- a/tests/test_point.py
+++ b/tests/test_point.py
@@ -262,6 +262,7 @@ def test_point_array_interface_numpy_deprecated():
         np.array(p)
 
 
+@pytest.mark.filterwarnings("error:An exception was ignored")  # NumPy 1.21
 def test_numpy_empty_point_coords():
     np = pytest.importorskip("numpy")
 
@@ -270,3 +271,14 @@ def test_numpy_empty_point_coords():
     # Access the coords
     a = np.asarray(pe.coords)
     assert a.shape == (0,)
+
+
+@shapely20_deprecated
+@pytest.mark.filterwarnings("error:An exception was ignored")  # NumPy 1.21
+def test_numpy_object_array():
+    np = pytest.importorskip("numpy")
+
+    geom = Point(3.0, 4.0)
+    ar = np.empty(1, object)
+    ar[:] = [geom]
+    assert ar[0] == geom
diff --git a/tests/test_polygon.py b/tests/test_polygon.py
index 863b623..62b2f96 100644
--- a/tests/test_polygon.py
+++ b/tests/test_polygon.py
@@ -109,6 +109,7 @@ def test_numpy_linearring_coords():
     assert_array_equal(ra, expected)
 
 
+@pytest.mark.filterwarnings("error:An exception was ignored")  # NumPy 1.21
 def test_numpy_empty_linearring_coords():
     np = pytest.importorskip("numpy")
 
@@ -116,6 +117,16 @@ def test_numpy_empty_linearring_coords():
     assert np.asarray(ring.coords).shape == (0,)
 
 
+@pytest.mark.filterwarnings("error:An exception was ignored")  # NumPy 1.21
+def test_numpy_object_array():
+    np = pytest.importorskip("numpy")
+
+    geom = Polygon([(0.0, 0.0), (0.0, 1.0), (1.0, 1.0)])
+    ar = np.empty(1, object)
+    ar[:] = [geom]
+    assert ar[0] == geom
+
+
 def test_polygon_from_coordinate_sequence():
     coords = [(0.0, 0.0), (0.0, 1.0), (1.0, 1.0), (0.0, 0.0)]
 
diff --git a/tests/test_strtree.py b/tests/test_strtree.py
index e1402cc..4ecda52 100644
--- a/tests/test_strtree.py
+++ b/tests/test_strtree.py
@@ -6,7 +6,6 @@ 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
@@ -27,8 +26,7 @@ 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):
-    with pytest.warns(ShapelyDeprecationWarning):
-        tree = STRtree(geoms)
+    tree = STRtree(geoms)
     results = tree.query(query_geom)
     assert len(results) == num_results
 
@@ -41,8 +39,7 @@ def test_query(geoms, query_geom, num_results):
 )
 def test_query_enumeration_idx(geoms, query_geom, expected):
     """Store enumeration idx"""
-    with pytest.warns(ShapelyDeprecationWarning):
-        tree = STRtree(geoms, range(len(geoms)))
+    tree = STRtree(geoms, range(len(geoms)))
     results = tree.query_items(query_geom)
     assert sorted(results) == sorted(expected)
 
@@ -56,8 +53,7 @@ def test_query_enumeration_idx(geoms, query_geom, expected):
 )
 def test_query_items(geoms, items, query_geom, expected):
     """Store enumeration idx"""
-    with pytest.warns(ShapelyDeprecationWarning):
-        tree = STRtree(geoms, items)
+    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)
@@ -74,8 +70,7 @@ def test_query_items(geoms, items, query_geom, expected):
     ],
 )
 def test_query_items_with_empty(tree_geometry, geometry, expected):
-    with pytest.warns(ShapelyDeprecationWarning):
-        tree = STRtree(tree_geometry)
+    tree = STRtree(tree_geometry)
     assert tree.query_items(geometry) == expected
 
 
@@ -87,8 +82,7 @@ def test_insert_empty_geometry():
     """
     empty = Polygon()
     geoms = [empty]
-    with pytest.warns(ShapelyDeprecationWarning):
-        tree = STRtree(geoms)
+    tree = STRtree(geoms)
     query = Polygon([(0, 0), (1, 1), (2, 0), (0, 0)])
     results = tree.query(query)
     assert len(results) == 0
@@ -103,8 +97,7 @@ def test_query_empty_geometry():
     empty = Polygon()
     point = Point(1, 0.5)
     geoms = [empty, point]
-    with pytest.warns(ShapelyDeprecationWarning):
-        tree = STRtree(geoms)
+    tree = STRtree(geoms)
     query = Polygon([(0, 0), (1, 1), (2, 0), (0, 0)])
     results = tree.query(query)
     assert len(results) == 1
@@ -117,8 +110,7 @@ def test_references():
     empty = Polygon()
     point = Point(1, 0.5)
     geoms = [empty, point]
-    with pytest.warns(ShapelyDeprecationWarning):
-        tree = STRtree(geoms)
+    tree = STRtree(geoms)
 
     empty = None
     point = None
@@ -132,8 +124,7 @@ def test_references():
 
 @requires_geos_342
 def test_safe_delete():
-    with pytest.warns(ShapelyDeprecationWarning):
-        tree = STRtree([])
+    tree = STRtree([])
 
     _lgeos = strtree.lgeos
     strtree.lgeos = None
@@ -148,8 +139,7 @@ def test_pickle_persistence():
     """
     Don't crash trying to use unpickled GEOS handle.
     """
-    with pytest.warns(ShapelyDeprecationWarning):
-        tree = STRtree([Point(i, i).buffer(0.1) for i in range(3)], range(3))
+    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")
@@ -175,8 +165,7 @@ def test_pickle_persistence():
 )
 @pytest.mark.parametrize("query_geom", [Point(0, 0.4)])
 def test_nearest_geom(geoms, query_geom):
-    with pytest.warns(ShapelyDeprecationWarning):
-        tree = STRtree(geoms)
+    tree = STRtree(geoms)
     result = tree.nearest(query_geom)
     assert result.geom_type == "Point"
     assert result.x == 0.0
@@ -197,22 +186,19 @@ 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):
-    with pytest.warns(ShapelyDeprecationWarning):
-        tree = STRtree(geoms, items)
+    tree = STRtree(geoms, items)
     assert tree.nearest_item(query_geom) == items[0]
 
 
 @pytest.mark.parametrize(["geoms", "items"], [([], None), ([], [])])
 def test_nearest_empty(geoms, items):
-    with pytest.warns(ShapelyDeprecationWarning):
-        tree = STRtree(geoms, items)
+    tree = STRtree(geoms, items)
     assert tree.nearest_item(None) is None
 
 
 @pytest.mark.parametrize(["geoms", "items"], [([], None), ([], [])])
 def test_nearest_items(geoms, items):
-    with pytest.warns(ShapelyDeprecationWarning):
-        tree = STRtree(geoms, items)
+    tree = STRtree(geoms, items)
     assert tree.nearest_item(None) is None
 
 
@@ -230,6 +216,5 @@ 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):
-    with pytest.warns(ShapelyDeprecationWarning):
-        tree = STRtree(geoms, items)
+    tree = STRtree(geoms, items)
     assert tree.nearest_item(query_geom, exclusive=True) != items[0]