Repository: shapely/shapely

Issue:
New STRtree deprecation warnings in 1.8.3
As mentioned in #1386, 2.0 will have a different STRTree API than the one in 1.8.0. This means we're going to walk back this stated decision (from 1.8a3 https://github.com/shapely/shapely/blob/maint-1.8/CHANGES.txt#L76-L79):

> 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.

And return to this (from 1.8a1 https://github.com/shapely/shapely/blob/maint-1.8/CHANGES.txt#L136-L150):

> Deprecations:
> 
> ...
> 
> The STRtree class will be entirely changed in 2.0.0. The exact future API is not yet decided, but will be decided before 1.8.0 is released.

With the difference that the 2.0 API has been decided (though small changes might be made before 2.0.0).

We will have a 1.8.3 release and it will warn, on import of shapely.strtree, that incompatible changes are coming back again in 2.0.0. The team discussed having a 1.9.0 release for the new deprecations, but decided against that. A 1.8.3 will accomplish the same thing and there is still plenty of time before 2.0.0 to adapt.



Discussion:

Patch:
diff --git a/CHANGES.txt b/CHANGES.txt
index 0525044..75d265e 100644
--- a/CHANGES.txt
+++ b/CHANGES.txt
@@ -1,6 +1,15 @@
 Changes
 =======
 
+1.8.3 (TBD)
+-----------
+
+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).
+
 1.8.2 (2022-05-03)
 ------------------
 
diff --git a/shapely/__init__.py b/shapely/__init__.py
index 320141d..0e7da05 100644
--- a/shapely/__init__.py
+++ b/shapely/__init__.py
@@ -1,1 +1,1 @@
-__version__ = "1.8.2"
+__version__ = "1.8.3dev"
diff --git a/shapely/strtree.py b/shapely/strtree.py
index aba92c3..7e9484c 100644
--- a/shapely/strtree.py
+++ b/shapely/strtree.py
@@ -22,7 +22,9 @@ 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
 
@@ -97,6 +99,11 @@ class STRtree:
         items: Iterable[Any] = None,
         node_capacity: int = 10,
     ):
+        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


Test patch:
diff --git a/tests/test_strtree.py b/tests/test_strtree.py
index 4ecda52..e1402cc 100644
--- a/tests/test_strtree.py
+++ b/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]