Repository: shapely/shapely
Pull request #2237 (2025-02-24 22:38:05)

DEPR: deprecate positional args in some functions
This adds a few deprecation warnings to a few functions:

- `shapely.transform()` - warns about positional `include_z`, also described in docs
- `shapely.points()` - warns about positional `indices`
- `shapely.linestrings()` - warns about positional `indices`
- `shapely.linearrings()` - warns about positional `indices`

The last three creation functions don't note the deprecation warning, as I'm guessing it's not commonly used? 
The tests appeared to be missing use with indices, so these tests are added (both as positional and keyword).
 (Found the creation tests with "indices" in a separate test file.)

Xref to #2234 that introduced the decorator function and raised warnings for `shapely.get_coordinates`.

Are there any other public functions that have positional arguments that should probably be shifted towards keyword-only over time? If so, mention them here, so the deprecation warnings can be introduced for shapely 2.1.

coveralls: ## Pull Request Test Coverage Report for [Build 13509310562](https://coveralls.io/builds/72406418)


### Details

* **5** of **5**   **(100.0%)**  changed or added relevant lines in **2** files are covered.
* No unchanged relevant lines lost coverage.
* Overall coverage increased (+**0.3%**) to **87.86%**

---



|  Totals | [![Coverage Status](https://coveralls.io/builds/72406418/badge)](https://coveralls.io/builds/72406418) |
| :-- | --: |
| Change from base [Build 13506953774](https://coveralls.io/builds/72403754): |  0.3% |
| Covered Lines: | 2656 |
| Relevant Lines: | 3023 |

---
##### 💛  - [Coveralls](https://coveralls.io)


Patch:
diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md
new file mode 100644
index 0000000..6e1a1a7
--- /dev/null
+++ b/CONTRIBUTING.md
@@ -0,0 +1,17 @@
+Contributing to Shapely
+=======================
+
+All contributions are subject to the [Code of
+Conduct](https://github.com/shapely/shapely/blob/main/CODE_OF_CONDUCT.md).
+
+If you spot a bug or have an idea for a feature, please [create an
+issue](https://github.com/shapely/shapely/issues). For simple fixes or
+features, you can [create a pull
+request](https://github.com/shapely/shapely/pulls), but it is a good idea to
+have discussion on an issue before sinking a lot of time into a pull request.
+
+Shapely is a mature project and its primary needs are bug fixes and
+documentation. New features and major refactoring will be welcomed cautiously
+and slowly because the work of maintaining a new feature over the lifetime of
+the project can be several times larger than the work of the initial
+contribution. Please open a discussion about such work before starting.
diff --git a/shapely/_geometry.py b/shapely/_geometry.py
index 750f5a3..586db34 100644
--- a/shapely/_geometry.py
+++ b/shapely/_geometry.py
@@ -5,7 +5,11 @@ import numpy as np
 
 from shapely import _geometry_helpers, geos_version, lib
 from shapely._enum import ParamEnum
-from shapely.decorators import multithreading_enabled, requires_geos
+from shapely.decorators import (
+    deprecate_positional,
+    multithreading_enabled,
+    requires_geos,
+)
 
 __all__ = [
     "GeometryType",
@@ -629,6 +633,16 @@ def get_geometry(geometry, index, **kwargs):
     return lib.get_geometry(geometry, np.intc(index), **kwargs)
 
 
+# Note: future plan is to change this signature over a few releases:
+# shapely 2.0:
+#   get_parts(geometry, return_index=False)
+# shapely 2.1: shows deprecation warning about positional 'return_index'
+#   same signature as 2.0
+# shapely 2.2(?): enforce keyword-only arguments after 'geometry'
+#   get_parts(geometry, *, return_index=False)
+
+
+@deprecate_positional(["return_index"])
 def get_parts(geometry, return_index=False):
     """Get parts of each GeometryCollection or Multi* geometry object.
 
@@ -648,6 +662,14 @@ def get_parts(geometry, return_index=False):
         If True, will return a tuple of ndarrays of (parts, indexes), where
         indexes are the indexes of the original geometries in the source array.
 
+    Notes
+    -----
+
+    .. deprecated:: 2.1.0
+        A deprecation warning is shown if ``return_index`` is specified as
+        a positional argument. This will need to be specified as a keyword
+        argument in a future release.
+
     Returns
     -------
     ndarray of parts or tuple of (parts, indexes)
@@ -682,6 +704,16 @@ MultiPoint([(4, 5), (6, 7)])], return_index=True)
     return _geometry_helpers.get_parts(geometry)[0]
 
 
+# Note: future plan is to change this signature over a few releases:
+# shapely 2.0:
+#   get_rings(geometry, return_index=False)
+# shapely 2.1: shows deprecation warning about positional 'return_index'
+#   same signature as 2.0
+# shapely 2.2(?): enforce keyword-only arguments after 'geometry'
+#   get_rings(geometry, *, return_index=False)
+
+
+@deprecate_positional(["return_index"])
 def get_rings(geometry, return_index=False):
     """Get rings of Polygon geometry object.
 
@@ -699,6 +731,14 @@ def get_rings(geometry, return_index=False):
         If True, will return a tuple of ndarrays of (rings, indexes), where
         indexes are the indexes of the original geometries in the source array.
 
+    Notes
+    -----
+
+    .. deprecated:: 2.1.0
+        A deprecation warning is shown if ``return_index`` is specified as
+        a positional argument. This will need to be specified as a keyword
+        argument in a future release.
+
     Returns
     -------
     ndarray of rings or tuple of (rings, indexes)
diff --git a/shapely/constructive.py b/shapely/constructive.py
index aa73a12..2f4e93a 100644
--- a/shapely/constructive.py
+++ b/shapely/constructive.py
@@ -6,7 +6,11 @@ from shapely import Geometry, GeometryType, lib
 from shapely._enum import ParamEnum
 from shapely._geometry import get_parts
 from shapely.algorithms._oriented_envelope import _oriented_envelope_min_area_vectorized
-from shapely.decorators import multithreading_enabled, requires_geos
+from shapely.decorators import (
+    deprecate_positional,
+    multithreading_enabled,
+    requires_geos,
+)
 from shapely.errors import UnsupportedGEOSVersionError
 
 __all__ = [
@@ -120,6 +124,19 @@ MultiLineString, MultiPoint, Point, Polygon
     return lib.boundary(geometry, **kwargs)
 
 
+# Note: future plan is to change this signature over a few releases:
+# shapely 2.0:
+#   buffer(geometry, distance, quad_segs=8, ...)
+# shapely 2.1: shows deprecation warning about positional 'quad_segs', etc.
+#   same signature as 2.0
+# shapely 2.2(?): enforce keyword-only arguments after 'distance'
+#   buffer(geometry, distance, *, quad_segs=8, ...)
+
+
+@deprecate_positional(
+    ["quad_segs", "cap_style", "join_style", "mitre_limit", "single_sided"],
+    category=DeprecationWarning,
+)
 @multithreading_enabled
 def buffer(
     geometry,
@@ -168,6 +185,15 @@ def buffer(
     **kwargs
         See :ref:`NumPy ufunc docs <ufuncs.kwargs>` for other keyword arguments.
 
+    Notes
+    -----
+
+    .. deprecated:: 2.1.0
+        A deprecation warning is shown if ``quad_segs``,  ``cap_style``,
+        ``join_style``, ``mitre_limit`` or ``single_sided`` are
+        specified as positional arguments. In a future release, these will
+        need to be specified as keyword arguments.
+
     Examples
     --------
     >>> import shapely
@@ -229,6 +255,18 @@ def buffer(
     )
 
 
+# Note: future plan is to change this signature over a few releases:
+# shapely 2.0:
+#   offset_curve(geometry, distance, quad_segs=8, ...)
+# shapely 2.1: shows deprecation warning about positional 'quad_segs', etc.
+#   same signature as 2.0
+# shapely 2.2(?): enforce keyword-only arguments after 'distance'
+#   offset_curve(geometry, distance, *, quad_segs=8, ...)
+
+
+@deprecate_positional(
+    ["quad_segs", "join_style", "mitre_limit"], category=DeprecationWarning
+)
 @multithreading_enabled
 def offset_curve(
     geometry, distance, quad_segs=8, join_style="round", mitre_limit=5.0, **kwargs
@@ -267,6 +305,14 @@ def offset_curve(
     **kwargs
         See :ref:`NumPy ufunc docs <ufuncs.kwargs>` for other keyword arguments.
 
+    Notes
+    -----
+
+    .. deprecated:: 2.1.0
+        A deprecation warning is shown if ``quad_segs``, ``join_style`` or
+        ``mitre_limit`` are specified as positional arguments. In a future
+        release, these will need to be specified as keyword arguments.
+
     Examples
     --------
     >>> import shapely
@@ -575,7 +621,7 @@ def build_area(geometry, **kwargs):
 
 
 @multithreading_enabled
-def make_valid(geometry, method="linework", keep_collapsed=True, **kwargs):
+def make_valid(geometry, *, method="linework", keep_collapsed=True, **kwargs):
     """Repair invalid geometries.
 
     Two ``methods`` are available:
@@ -1014,6 +1060,16 @@ def segmentize(geometry, max_segment_length, **kwargs):
     return lib.segmentize(geometry, max_segment_length, **kwargs)
 
 
+# Note: future plan is to change this signature over a few releases:
+# shapely 2.0:
+#   simplify(geometry, tolerance, preserve_topology=True, **kwargs)
+# shapely 2.1: shows deprecation warning about positional 'preserve_topology'
+#   same signature as 2.0
+# shapely 2.2(?): enforce keyword-only arguments after 'tolerance'
+#   simplify(geometry, tolerance, *, preserve_topology=True, **kwargs)
+
+
+@deprecate_positional(["preserve_topology"], category=DeprecationWarning)
 @multithreading_enabled
 def simplify(geometry, tolerance, preserve_topology=True, **kwargs):
     """Return a simplified version of an input geometry.
@@ -1034,6 +1090,14 @@ def simplify(geometry, tolerance, preserve_topology=True, **kwargs):
     **kwargs
         See :ref:`NumPy ufunc docs <ufuncs.kwargs>` for other keyword arguments.
 
+    Notes
+    -----
+
+    .. deprecated:: 2.1.0
+        A deprecation warning is shown if ``preserve_topology`` is specified as
+        a positional argument. This will need to be specified as a keyword
+        argument in a future release.
+
     Examples
     --------
     >>> import shapely
@@ -1061,7 +1125,7 @@ def simplify(geometry, tolerance, preserve_topology=True, **kwargs):
 
 @requires_geos("3.12.0")
 @multithreading_enabled
-def coverage_simplify(geometry, tolerance, simplify_boundary=True):
+def coverage_simplify(geometry, tolerance, *, simplify_boundary=True):
     """Return a simplified version of an input geometry using coverage simplification.
 
     Assumes that the geometry forms a polygonal coverage. Under this assumption, the
@@ -1212,6 +1276,18 @@ def snap(geometry, reference, tolerance, **kwargs):
     return lib.snap(geometry, reference, tolerance, **kwargs)
 
 
+# Note: future plan is to change this signature over a few releases:
+# shapely 2.0:
+#   voronoi_polygons(geometry, tolerance=0.0, extend_to=None, ...)
+# shapely 2.1: shows deprecation warning about positional 'extend_to'
+#   same signature as 2.0
+# shapely 2.2(?): enforce keyword-only arguments after 'tolerance'
+#   voronoi_polygons(geometry, tolerance=0.0, extend_to=None, ...)
+
+
+@deprecate_positional(
+    ["extend_to", "only_edges", "ordered"], category=DeprecationWarning
+)
 @multithreading_enabled
 def voronoi_polygons(
     geometry, tolerance=0.0, extend_to=None, only_edges=False, ordered=False, **kwargs
@@ -1243,6 +1319,14 @@ def voronoi_polygons(
     **kwargs
         See :ref:`NumPy ufunc docs <ufuncs.kwargs>` for other keyword arguments.
 
+    Notes
+    -----
+
+    .. deprecated:: 2.1.0
+        A deprecation warning is shown if ``extend_to``, ``only_edges`` or
+        ``ordered`` are specified as positional arguments. In a future
+        release, these will need to be specified as keyword arguments.
+
     Examples
     --------
     >>> import shapely
diff --git a/shapely/coordinates.py b/shapely/coordinates.py
index efa2f71..b4b429d 100644
--- a/shapely/coordinates.py
+++ b/shapely/coordinates.py
@@ -9,10 +9,21 @@ from shapely.decorators import deprecate_positional
 __all__ = ["count_coordinates", "get_coordinates", "set_coordinates", "transform"]
 
 
+# Note: future plan is to change this signature over a few releases:
+# shapely 2.0: only supported XY and XYZ geometries
+#   transform(geometry, transformation, include_z=False)
+# shapely 2.1: shows deprecation warning about positional 'include_z' arg
+#   transform(geometry, transformation, include_z=False, *, interleaved=True)
+# shapely 2.2(?): enforce keyword-only arguments after 'transformation'
+#   transform(geometry, transformation, *, include_z=False, interleaved=True)
+
+
+@deprecate_positional(["include_z"], category=DeprecationWarning)
 def transform(
     geometry,
     transformation,
     include_z: bool | None = False,
+    *,
     interleaved: bool = True,
 ):
     """Apply a function to the coordinates of a geometry.
@@ -47,6 +58,14 @@ def transform(
 
         .. versionadded:: 2.1.0
 
+    Notes
+    -----
+
+    .. deprecated:: 2.1.0
+        A deprecation warning is shown if ``include_z`` is specified as a
+        positional argument. This will need to be specified as a keyword
+        argument in a future release.
+
     See Also
     --------
     has_z
@@ -100,10 +119,13 @@ interleaved=False, include_z=True)
         has_z = shapely.has_z(geometry_arr)
         result = np.empty_like(geometry_arr)
         result[has_z] = transform(
-            geometry_arr[has_z], transformation, True, interleaved
+            geometry_arr[has_z], transformation, include_z=True, interleaved=interleaved
         )
         result[~has_z] = transform(
-            geometry_arr[~has_z], transformation, False, interleaved
+            geometry_arr[~has_z],
+            transformation,
+            include_z=False,
+            interleaved=interleaved,
         )
     else:
         # TODO: expose include_m
@@ -166,9 +188,9 @@ def count_coordinates(geometry):
 # Note: future plan is to change this signature over a few releases:
 # shapely 2.0: only supported XY and XYZ geometries
 #   get_coordinates(geometry, include_z=False, return_index=False)
-# shapely 2.1: adds include_m at end, shows deprecation warning about position keywords
+# shapely 2.1: shows deprecation warning about positional 'include_z' and 'return_index'
 #   get_coordinates(geometry, include_z=False, return_index=False, *, include_m=False)
-# shapely 2.2(?): enforces keyword position arguments after geometry
+# shapely 2.2(?): enforce keyword-only arguments after 'geometry'
 #   get_coordinates(geometry, *, include_z=False, include_m=False, return_index=False)
 
 
diff --git a/shapely/coords.py b/shapely/coords.py
index daeb066..146c966 100644
--- a/shapely/coords.py
+++ b/shapely/coords.py
@@ -8,10 +8,13 @@ class CoordinateSequence:
 
     Examples
     --------
-      >>> from shapely.wkt import loads
-      >>> g = loads('POINT (0.0 0.0)')
-      >>> list(g.coords)
-      [(0.0, 0.0)]
+    >>> from shapely.wkt import loads
+    >>> g = loads('POINT (0.0 0.0)')
+    >>> list(g.coords)
+    [(0.0, 0.0)]
+    >>> g = loads('POINT M (1 2 4)')
+    >>> g.coords[:]
+    [(1.0, 2.0, 4.0)]
 
     """
 
diff --git a/shapely/creation.py b/shapely/creation.py
index 66a07b4..953eb4a 100644
--- a/shapely/creation.py
+++ b/shapely/creation.py
@@ -5,7 +5,7 @@ import numpy as np
 from shapely import Geometry, GeometryType, lib
 from shapely._enum import ParamEnum
 from shapely._geometry_helpers import collections_1d, simple_geometries_1d
-from shapely.decorators import multithreading_enabled
+from shapely.decorators import deprecate_positional, multithreading_enabled
 from shapely.io import from_wkt
 
 __all__ = [
@@ -40,9 +40,26 @@ def _xyz_to_coords(x, y, z):
     return np.stack(coords, axis=-1)
 
 
+# Note: future plan is to change this signature over a few releases:
+# shapely 2.0:
+#   points(coords, y=None, z=None, indices=None, out=None, **kwargs)
+# shapely 2.1: shows deprecation warning about positional 'indices' arg
+#   points(coords, y=None, z=None, indices=None, *, handle_nan=HandleNaN.allow, out=None, **kwargs)  # noqa: E501
+# shapely 2.2(?): enforce keyword-only arguments after 'z'
+#   points(coords, y=None, z=None, *, indices=None, handle_nan=HandleNaN.allow, out=None, **kwargs)  # noqa: E501
+
+
+@deprecate_positional(["indices"], category=DeprecationWarning)
 @multithreading_enabled
 def points(
-    coords, y=None, z=None, indices=None, handle_nan=HandleNaN.allow, out=None, **kwargs
+    coords,
+    y=None,
+    z=None,
+    indices=None,
+    *,
+    handle_nan=HandleNaN.allow,
+    out=None,
+    **kwargs,
 ):
     """Create an array of points.
 
@@ -111,9 +128,26 @@ def points(
         )
 
 
+# Note: future plan is to change this signature over a few releases:
+# shapely 2.0:
+#   linestrings(coords, y=None, z=None, indices=None, out=None, **kwargs)
+# shapely 2.1: shows deprecation warning about positional 'indices' arg
+#   linestrings(coords, y=None, z=None, indices=None, *, handle_nan=HandleNaN.allow, out=None, **kwargs)  # noqa: E501
+# shapely 2.2(?): enforce keyword-only arguments after 'z'
+#   linestrings(coords, y=None, z=None, *, indices=None, handle_nan=HandleNaN.allow, out=None, **kwargs)  # noqa: E501
+
+
+@deprecate_positional(["indices"], category=DeprecationWarning)
 @multithreading_enabled
 def linestrings(
-    coords, y=None, z=None, indices=None, handle_nan=HandleNaN.allow, out=None, **kwargs
+    coords,
+    y=None,
+    z=None,
+    indices=None,
+    *,
+    handle_nan=HandleNaN.allow,
+    out=None,
+    **kwargs,
 ):
     """Create an array of linestrings.
 
@@ -188,9 +222,26 @@ def linestrings(
         )
 
 
+# Note: future plan is to change this signature over a few releases:
+# shapely 2.0:
+#   linearrings(coords, y=None, z=None, indices=None, out=None, **kwargs)
+# shapely 2.1: shows deprecation warning about positional 'indices' arg
+#   linearrings(coords, y=None, z=None, indices=None, *, handle_nan=HandleNaN.allow, out=None, **kwargs)  # noqa: E501
+# shapely 2.2(?): enforce keyword-only arguments after 'z'
+#   linearrings(coords, y=None, z=None, *, indices=None, handle_nan=HandleNaN.allow, out=None, **kwargs)  # noqa: E501
+
+
+@deprecate_positional(["indices"], category=DeprecationWarning)
 @multithreading_enabled
 def linearrings(
-    coords, y=None, z=None, indices=None, handle_nan=HandleNaN.allow, out=None, **kwargs
+    coords,
+    y=None,
+    z=None,
+    indices=None,
+    *,
+    handle_nan=HandleNaN.allow,
+    out=None,
+    **kwargs,
 ):
     """Create an array of linearrings.
 
@@ -269,8 +320,18 @@ def linearrings(
         )
 
 
+# Note: future plan is to change this signature over a few releases:
+# shapely 2.0:
+#   polygons(geometries, holes=None, indices=None, out=None, **kwargs)
+# shapely 2.1: shows deprecation warning about positional 'indices' arg
+#   polygons(geometries, holes=None, indices=None, *, out=None, **kwargs)
+# shapely 2.2(?): enforce keyword-only arguments after 'holes'
+#   polygons(geometries, holes=None, *, indices=None, out=None, **kwargs)
+
+
+@deprecate_positional(["indices"], category=DeprecationWarning)
 @multithreading_enabled
-def polygons(geometries, holes=None, indices=None, out=None, **kwargs):
+def polygons(geometries, holes=None, indices=None, *, out=None, **kwargs):
     """Create an array of polygons.
 
     Parameters
@@ -298,6 +359,14 @@ def polygons(geometries, holes=None, indices=None, out=None, **kwargs):
         See :ref:`NumPy ufunc docs <ufuncs.kwargs>` for other keyword arguments.
         Ignored if ``indices`` is provided.
 
+    Notes
+    -----
+
+    .. deprecated:: 2.1.0
+        A deprecation warning is shown if ``indices`` is specified as a
+        positional argument. This will need to be specified as a keyword
+        argument in a future release.
+
     Examples
     --------
     >>> import shapely
@@ -365,6 +434,16 @@ def polygons(geometries, holes=None, indices=None, out=None, **kwargs):
     return lib.polygons(geometries, holes, out=out, **kwargs)
 
 
+# Note: future plan is to change this signature over a few releases:
+# shapely 2.0:
+#   box(xmin, ymin, xmax, ymax, ccw=True, **kwargs)
+# shapely 2.1: shows deprecation warning about positional 'ccw' arg
+#   same signature as 2.0
+# shapely 2.2(?): enforce keyword-only arguments after 'ymax'
+#   box(xmin, ymin, xmax, ymax, *, ccw=True, **kwargs)
+
+
+@deprecate_positional(["ccw"], category=DeprecationWarning)
 @multithreading_enabled
 def box(xmin, ymin, xmax, ymax, ccw=True, **kwargs):
     """Create box polygons.
@@ -387,6 +466,14 @@ def box(xmin, ymin, xmax, ymax, ccw=True, **kwargs):
     **kwargs
         See :ref:`NumPy ufunc docs <ufuncs.kwargs>` for other keyword arguments.
 
+    Notes
+    -----
+
+    .. deprecated:: 2.1.0
+        A deprecation warning is shown if ``ccw`` is specified as a
+        positional argument. This will need to be specified as a keyword
+        argument in a future release.
+
     Examples
     --------
     >>> import shapely
@@ -399,8 +486,18 @@ def box(xmin, ymin, xmax, ymax, ccw=True, **kwargs):
     return lib.box(xmin, ymin, xmax, ymax, ccw, **kwargs)
 
 
+# Note: future plan is to change this signature over a few releases:
+# shapely 2.0:
+#   multipoints(geometries, indices=None, out=None, **kwargs)
+# shapely 2.1: shows deprecation warning about positional 'indices' arg
+#   multipoints(geometries, indices=None, *, out=None, **kwargs)
+# shapely 2.2(?): enforce keyword-only arguments after 'indices'
+#   multipoints(geometries, *, indices=None, out=None, **kwargs)
+
+
+@deprecate_positional(["indices"], category=DeprecationWarning)
 @multithreading_enabled
-def multipoints(geometries, indices=None, out=None, **kwargs):
+def multipoints(geometries, indices=None, *, out=None, **kwargs):
     """Create multipoints from arrays of points.
 
     Parameters
@@ -419,6 +516,14 @@ def multipoints(geometries, indices=None, out=None, **kwargs):
         See :ref:`NumPy ufunc docs <ufuncs.kwargs>` for other keyword arguments.
         Ignored if ``indices`` is provided.
 
+    Notes
+    -----
+
+    .. deprecated:: 2.1.0
+        A deprecation warning is shown if ``indices`` is specified as a
+        positional argument. This will need to be specified as a keyword
+        argument in a future release.
+
     Examples
     --------
     >>> import shapely
@@ -466,8 +571,18 @@ def multipoints(geometries, indices=None, out=None, **kwargs):
         return collections_1d(geometries, indices, typ, out=out)
 
 
+# Note: future plan is to change this signature over a few releases:
+# shapely 2.0:
+#   multilinestrings(geometries, indices=None, out=None, **kwargs)
+# shapely 2.1: shows deprecation warning about positional 'indices' arg
+#   multilinestrings(geometries, indices=None, *, out=None, **kwargs)
+# shapely 2.2(?): enforce keyword-only arguments after 'indices'
+#   multilinestrings(geometries, *, indices=None, out=None, **kwargs)
+
+
+@deprecate_positional(["indices"], category=DeprecationWarning)
 @multithreading_enabled
-def multilinestrings(geometries, indices=None, out=None, **kwargs):
+def multilinestrings(geometries, indices=None, *, out=None, **kwargs):
     """Create multilinestrings from arrays of linestrings.
 
     Parameters
@@ -486,6 +601,14 @@ def multilinestrings(geometries, indices=None, out=None, **kwargs):
         See :ref:`NumPy ufunc docs <ufuncs.kwargs>` for other keyword arguments.
         Ignored if ``indices`` is provided.
 
+    Notes
+    -----
+
+    .. deprecated:: 2.1.0
+        A deprecation warning is shown if ``indices`` is specified as a
+        positional argument. This will need to be specified as a keyword
+        argument in a future release.
+
     See Also
     --------
     multipoints
@@ -504,8 +627,18 @@ def multilinestrings(geometries, indices=None, out=None, **kwargs):
         return collections_1d(geometries, indices, typ, out=out)
 
 
+# Note: future plan is to change this signature over a few releases:
+# shapely 2.0:
+#   multipolygons(geometries, indices=None, out=None, **kwargs)
+# shapely 2.1: shows deprecation warning about positional 'indices' arg
+#   multipolygons(geometries, indices=None, *, out=None, **kwargs)
+# shapely 2.2(?): enforce keyword-only arguments after 'indices'
+#   multipolygons(geometries, *, indices=None, out=None, **kwargs)
+
+
+@deprecate_positional(["indices"], category=DeprecationWarning)
 @multithreading_enabled
-def multipolygons(geometries, indices=None, out=None, **kwargs):
+def multipolygons(geometries, indices=None, *, out=None, **kwargs):
     """Create multipolygons from arrays of polygons.
 
     Parameters
@@ -524,6 +657,14 @@ def multipolygons(geometries, indices=None, out=None, **kwargs):
         See :ref:`NumPy ufunc docs <ufuncs.kwargs>` for other keyword arguments.
         Ignored if ``indices`` is provided.
 
+    Notes
+    -----
+
+    .. deprecated:: 2.1.0
+        A deprecation warning is shown if ``indices`` is specified as a
+        positional argument. This will need to be specified as a keyword
+        argument in a future release.
+
     See Also
     --------
     multipoints
@@ -541,6 +682,16 @@ def multipolygons(geometries, indices=None, out=None, **kwargs):
         return collections_1d(geometries, indices, typ, out=out)
 
 
+# Note: future plan is to change this signature over a few releases:
+# shapely 2.0:
+#   geometrycollections(geometries, indices=None, out=None, **kwargs)
+# shapely 2.1: shows deprecation warning about positional 'indices' arg
+#   geometrycollections(geometries, indices=None, *, out=None, **kwargs)
+# shapely 2.2(?): enforce keyword-only arguments after 'indices'
+#   geometrycollections(geometries, *, indices=None, out=None, **kwargs)
+
+
+@deprecate_positional(["indices"], category=DeprecationWarning)
 @multithreading_enabled
 def geometrycollections(geometries, indices=None, out=None, **kwargs):
     """Create geometrycollections from arrays of geometries.
@@ -561,6 +712,14 @@ def geometrycollections(geometries, indices=None, out=None, **kwargs):
         See :ref:`NumPy ufunc docs <ufuncs.kwargs>` for other keyword arguments.
         Ignored if ``indices`` is provided.
 
+    Notes
+    -----
+
+    .. deprecated:: 2.1.0
+        A deprecation warning is shown if ``indices`` is specified as a
+        positional argument. This will need to be specified as a keyword
+        argument in a future release.
+
     See Also
     --------
     multipoints
diff --git a/shapely/decorators.py b/shapely/decorators.py
index e011a0f..528e91b 100644
--- a/shapely/decorators.py
+++ b/shapely/decorators.py
@@ -103,7 +103,7 @@ def deprecate_positional(should_be_kwargs, category=DeprecationWarning):
 
             # check signature to see which positional args were used
             sig = inspect.signature(func)
-            args_bind = sig.bind(*args)
+            args_bind = sig.bind_partial(*args)
             warn_args = [
                 f"`{arg}`"
                 for arg in args_bind.arguments.keys()
@@ -122,7 +122,7 @@ def deprecate_positional(should_be_kwargs, category=DeprecationWarning):
                     else:
                         args = ", ".join(warn_args[:-1]) + ", and " + warn_args[-1]
                 msg = (
-                    f"positional argument{plr} {args} for `{func.__qualname__}` "
+                    f"positional argument{plr} {args} for `{func.__name__}` "
                     f"{isare} deprecated.  Please use keyword argument{plr} instead."
                 )
                 warnings.warn(msg, category=category, stacklevel=2)
diff --git a/shapely/geometry/base.py b/shapely/geometry/base.py
index 79b6bc2..31a053c 100644
--- a/shapely/geometry/base.py
+++ b/shapely/geometry/base.py
@@ -15,6 +15,7 @@ import shapely
 from shapely._geometry_helpers import _geom_factory
 from shapely.constructive import BufferCapStyle, BufferJoinStyle
 from shapely.coords import CoordinateSequence
+from shapely.decorators import deprecate_positional
 from shapely.errors import GeometryTypeError, GEOSException, ShapelyDeprecationWarning
 
 GEOMETRY_TYPES = [
@@ -28,6 +29,8 @@ GEOMETRY_TYPES = [
     "GeometryCollection",
 ]
 
+_geos_ge_312 = shapely.geos_version >= (3, 12, 0)
+
 
 def geom_factory(g, parent=None):
     """Create a Shapely geometry instance from a pointer to a GEOS geometry.
@@ -216,7 +219,9 @@ class BaseGeometry(shapely.Geometry):
     @property
     def coords(self):
         """Access to geometry's coordinates (CoordinateSequence)."""
-        coords_array = shapely.get_coordinates(self, include_z=self.has_z)
+        has_z = self.has_z
+        has_m = self.has_m if _geos_ge_312 else False
+        coords_array = shapely.get_coordinates(self, include_z=has_z, include_m=has_m)
         return CoordinateSequence(coords_array)
 
     @property
@@ -447,6 +452,17 @@ class BaseGeometry(shapely.Geometry):
         """
         return shapely.oriented_envelope(self)
 
+    # Note: future plan is to change this signature over a few releases:
+    # shapely 2.0:
+    #   buffer(self, geometry, distance, quad_segs=16, cap_style="round", ...)
+    # shapely 2.1: shows deprecation warning about positional 'cap_style', etc.
+    #   same signature as 2.0
+    # shapely 2.2(?): enforce keyword-only arguments after 'quad_segs'
+    #   buffer(self, geometry, distance, quad_segs=16, *, cap_style="round", ...)
+    @deprecate_positional(
+        ["cap_style", "join_style", "mitre_limit", "single_sided"],
+        category=DeprecationWarning,
+    )
     def buffer(
         self,
         distance,
@@ -521,6 +537,12 @@ class BaseGeometry(shapely.Geometry):
         The return value is a strictly two-dimensional geometry. All
         Z coordinates of the original geometry will be ignored.
 
+        .. deprecated:: 2.1.0
+            A deprecation warning is shown if ``quad_segs``,  ``cap_style``,
+            ``join_style``, ``mitre_limit`` or ``single_sided`` are
+            specified as positional arguments. In a future release, these will
+            need to be specified as keyword arguments.
+
         Examples
         --------
         >>> from shapely import BufferCapStyle
@@ -579,6 +601,15 @@ class BaseGeometry(shapely.Geometry):
             single_sided=single_sided,
         )
 
+    # Note: future plan is to change this signature over a few releases:
+    # shapely 2.0:
+    #   simplify(self, tolerance, preserve_topology=True)
+    # shapely 2.1: shows deprecation warning about positional 'preserve_topology'
+    #   same signature as 2.0
+    # shapely 2.2(?): enforce keyword-only arguments after 'tolerance'
+    #   simplify(self, tolerance, *, preserve_topology=True)
+
+    @deprecate_positional(["preserve_topology"], category=DeprecationWarning)
     def simplify(self, tolerance, preserve_topology=True):
         """Return a simplified geometry produced by the Douglas-Peucker algorithm.
 
@@ -609,6 +640,15 @@ class BaseGeometry(shapely.Geometry):
     # Overlay operations
     # ---------------------------
 
+    # Note: future plan is to change this signature over a few releases:
+    # shapely 2.0:
+    #   difference(self, other, grid_size=None)
+    # shapely 2.1: shows deprecation warning about positional 'grid_size' arg
+    #   same signature as 2.0
+    # shapely 2.2(?): enforce keyword-only arguments after 'other'
+    #   difference(self, other, *, grid_size=None)
+
+    @deprecate_positional(["grid_size"], category=DeprecationWarning)
     def difference(self, other, grid_size=None):
         """Return the difference of the geometries.
 
@@ -616,6 +656,15 @@ class BaseGeometry(shapely.Geometry):
         """
         return shapely.difference(self, other, grid_size=grid_size)
 
+    # Note: future plan is to change this signature over a few releases:
+    # shapely 2.0:
+    #   intersection(self, other, grid_size=None)
+    # shapely 2.1: shows deprecation warning about positional 'grid_size' arg
+    #   same signature as 2.0
+    # shapely 2.2(?): enforce keyword-only arguments after 'other'
+    #   intersection(self, other, *, grid_size=None)
+
+    @deprecate_positional(["grid_size"], category=DeprecationWarning)
     def intersection(self, other, grid_size=None):
         """Return the intersection of the geometries.
 
@@ -623,6 +672,15 @@ class BaseGeometry(shapely.Geometry):
         """
         return shapely.intersection(self, other, grid_size=grid_size)
 
+    # Note: future plan is to change this signature over a few releases:
+    # shapely 2.0:
+    #   symmetric_difference(self, other, grid_size=None)
+    # shapely 2.1: shows deprecation warning about positional 'grid_size' arg
+    #   same signature as 2.0
+    # shapely 2.2(?): enforce keyword-only arguments after 'other'
+    #   symmetric_difference(self, other, *, grid_size=None)
+
+    @deprecate_positional(["grid_size"], category=DeprecationWarning)
     def symmetric_difference(self, other, grid_size=None):
         """Return the symmetric difference of the geometries.
 
@@ -630,6 +688,15 @@ class BaseGeometry(shapely.Geometry):
         """
         return shapely.symmetric_difference(self, other, grid_size=grid_size)
 
+    # Note: future plan is to change this signature over a few releases:
+    # shapely 2.0:
+    #   union(self, other, grid_size=None)
+    # shapely 2.1: shows deprecation warning about positional 'grid_size' arg
+    #   same signature as 2.0
+    # shapely 2.2(?): enforce keyword-only arguments after 'other'
+    #   union(self, other, *, grid_size=None)
+
+    @deprecate_positional(["grid_size"], category=DeprecationWarning)
     def union(self, other, grid_size=None):
         """Return the union of the geometries.
 
@@ -769,7 +836,7 @@ class BaseGeometry(shapely.Geometry):
         """
         return _maybe_unpack(shapely.dwithin(self, other, distance))
 
-    def equals_exact(self, other, tolerance=0.0, normalize=False):
+    def equals_exact(self, other, tolerance=0.0, *, normalize=False):
         """Return True if the geometries are equivalent within the tolerance.
 
         Refer to :func:`~shapely.equals_exact` for full documentation.
@@ -802,7 +869,9 @@ class BaseGeometry(shapely.Geometry):
         bool
 
         """
-        return _maybe_unpack(shapely.equals_exact(self, other, tolerance, normalize))
+        return _maybe_unpack(
+            shapely.equals_exact(self, other, tolerance, normalize=normalize)
+        )
 
     def almost_equals(self, other, decimal=6):
         """Return True if all coordinates are equal to a specified decimal place.
@@ -851,6 +920,15 @@ class BaseGeometry(shapely.Geometry):
     # Linear referencing
     # ------------------
 
+    # Note: future plan is to change this signature over a few releases:
+    # shapely 2.0:
+    #   line_locate_point(self, other, normalized=False)
+    # shapely 2.1: shows deprecation warning about positional 'normalized'
+    #   same signature as 2.0
+    # shapely 2.2(?): enforce keyword-only arguments after 'other'
+    #   line_locate_point(self, other, *, normalized=False)
+
+    @deprecate_positional(["normalized"], category=DeprecationWarning)
     def line_locate_point(self, other, normalized=False):
         """Return the distance of this geometry to a point nearest the specified point.
 
@@ -863,6 +941,15 @@ class BaseGeometry(shapely.Geometry):
             shapely.line_locate_point(self, other, normalized=normalized)
         )
 
+    # Note: future plan is to change this signature over a few releases:
+    # shapely 2.0:
+    #   project(self, other, normalized=False)
+    # shapely 2.1: shows deprecation warning about positional 'normalized'
+    #   same signature as 2.0
+    # shapely 2.2(?): enforce keyword-only arguments after 'other'
+    #   project(self, other, *, normalized=False)
+
+    @deprecate_positional(["normalized"], category=DeprecationWarning)
     def project(self, other, normalized=False):
         """Return the distance of geometry to a point nearest the specified point.
 
@@ -875,6 +962,15 @@ class BaseGeometry(shapely.Geometry):
             shapely.line_locate_point(self, other, normalized=normalized)
         )
 
+    # Note: future plan is to change this signature over a few releases:
+    # shapely 2.0:
+    #   line_interpolate_point(self, distance, normalized=False)
+    # shapely 2.1: shows deprecation warning about positional 'normalized'
+    #   same signature as 2.0
+    # shapely 2.2(?): enforce keyword-only arguments after 'distance'
+    #   line_interpolate_point(self, distance, *, normalized=False)
+
+    @deprecate_positional(["normalized"], category=DeprecationWarning)
     def line_interpolate_point(self, distance, normalized=False):
         """Return a point at the specified distance along a linear geometry.
 
@@ -888,6 +984,15 @@ class BaseGeometry(shapely.Geometry):
         """
         return shapely.line_interpolate_point(self, distance, normalized=normalized)
 
+    # Note: future plan is to change this signature over a few releases:
+    # shapely 2.0:
+    #   interpolate(self, distance, normalized=False)
+    # shapely 2.1: shows deprecation warning about positional 'normalized'
+    #   same signature as 2.0
+    # shapely 2.2(?): enforce keyword-only arguments after 'distance'
+    #   interpolate(self, distance, *, normalized=False)
+
+    @deprecate_positional(["normalized"], category=DeprecationWarning)
     def interpolate(self, distance, normalized=False):
         """Return a point at the specified distance along a linear geometry.
 
diff --git a/shapely/geometry/linestring.py b/shapely/geometry/linestring.py
index dc553b0..7019be2 100644
--- a/shapely/geometry/linestring.py
+++ b/shapely/geometry/linestring.py
@@ -3,6 +3,7 @@
 import numpy as np
 
 import shapely
+from shapely.decorators import deprecate_positional
 from shapely.geometry.base import JOIN_STYLE, BaseGeometry
 from shapely.geometry.point import Point
 
@@ -125,6 +126,17 @@ class LineString(BaseGeometry):
         """
         return self.coords.xy
 
+    # Note: future plan is to change this signature over a few releases:
+    # shapely 2.0:
+    #   offset_curve(self, distance, quad_segs=16, ...)
+    # shapely 2.1: shows deprecation warning about positional 'quad_segs', etc.
+    #   same signature as 2.0
+    # shapely 2.2(?): enforce keyword-only arguments after 'distance'
+    #   offset_curve(self, distance, *, quad_segs=16, ...)
+
+    @deprecate_positional(
+        ["quad_segs", "join_style", "mitre_limit"], category=DeprecationWarning
+    )
     def offset_curve(
         self,
         distance,
@@ -162,7 +174,13 @@ class LineString(BaseGeometry):
             raise ValueError("Cannot compute offset from zero-length line segment")
         elif not np.isfinite(distance):
             raise ValueError("offset_curve distance must be finite")
-        return shapely.offset_curve(self, distance, quad_segs, join_style, mitre_limit)
+        return shapely.offset_curve(
+            self,
+            distance,
+            quad_segs=quad_segs,
+            join_style=join_style,
+            mitre_limit=mitre_limit,
+        )
 
     def parallel_offset(
         self,
diff --git a/shapely/linear.py b/shapely/linear.py
index d21db34..38c58c8 100644
--- a/shapely/linear.py
+++ b/shapely/linear.py
@@ -1,7 +1,7 @@
 """Linear geometry functions."""
 
 from shapely import lib
-from shapely.decorators import multithreading_enabled
+from shapely.decorators import deprecate_positional, multithreading_enabled
 from shapely.errors import UnsupportedGEOSVersionError
 
 __all__ = [
@@ -12,7 +12,16 @@ __all__ = [
     "shortest_line",
 ]
 
+# Note: future plan is to change this signature over a few releases:
+# shapely 2.0:
+#   line_interpolate_point(line, distance, normalized=False, **kwargs)
+# shapely 2.1: shows deprecation warning about positional 'normalized' arg
+#    same signature as 2.0
+# shapely 2.2(?): enforce keyword-only arguments after 'normalized'
+#   line_interpolate_point(line, distance, *, normalized=False, **kwargs)
 
+
+@deprecate_positional(["normalized"], category=DeprecationWarning)
 @multithreading_enabled
 def line_interpolate_point(line, distance, normalized=False, **kwargs):
     """Return a point interpolated at given distance on a line.
@@ -55,6 +64,16 @@ def line_interpolate_point(line, distance, normalized=False, **kwargs):
         return lib.line_interpolate_point(line, distance)
 
 
+# Note: future plan is to change this signature over a few releases:
+# shapely 2.0:
+#   line_locate_point(line, other, normalized=False, **kwargs)
+# shapely 2.1: shows deprecation warning about positional 'normalized' arg
+#    same signature as 2.0
+# shapely 2.2(?): enforce keyword-only arguments after 'normalized'
+#   line_locate_point(line, other, *, normalized=False, **kwargs)
+
+
+@deprecate_positional(["normalized"], category=DeprecationWarning)
 @multithreading_enabled
 def line_locate_point(line, other, normalized=False, **kwargs):
     """Return the distance to the line origin of given point.
diff --git a/shapely/ops.py b/shapely/ops.py
index 9939623..e540688 100644
--- a/shapely/ops.py
+++ b/shapely/ops.py
@@ -626,15 +626,15 @@ def substring(geom, start_dist, end_dist, normalized=False):
 
     # Filter out cases in which to return a point
     if start_dist == end_dist:
-        return geom.interpolate(start_dist, normalized)
+        return geom.interpolate(start_dist, normalized=normalized)
     elif not normalized and start_dist >= geom.length and end_dist >= geom.length:
-        return geom.interpolate(geom.length, normalized)
+        return geom.interpolate(geom.length, normalized=normalized)
     elif not normalized and -start_dist >= geom.length and -end_dist >= geom.length:
-        return geom.interpolate(0, normalized)
+        return geom.interpolate(0, normalized=normalized)
     elif normalized and start_dist >= 1 and end_dist >= 1:
-        return geom.interpolate(1, normalized)
+        return geom.interpolate(1, normalized=normalized)
     elif normalized and -start_dist >= 1 and -end_dist >= 1:
-        return geom.interpolate(0, normalized)
+        return geom.interpolate(0, normalized=normalized)
 
     if normalized:
         start_dist *= geom.length
diff --git a/shapely/predicates.py b/shapely/predicates.py
index fa93812..2fcc812 100644
--- a/shapely/predicates.py
+++ b/shapely/predicates.py
@@ -1035,7 +1035,7 @@ def within(a, b, **kwargs):
 
 
 @multithreading_enabled
-def equals_exact(a, b, tolerance=0.0, normalize=False, **kwargs):
+def equals_exact(a, b, tolerance=0.0, *, normalize=False, **kwargs):
     """Return True if the geometries are structurally equivalent within a given
     tolerance.
 
diff --git a/shapely/set_operations.py b/shapely/set_operations.py
index d91b68e..fe58a41 100644
--- a/shapely/set_operations.py
+++ b/shapely/set_operations.py
@@ -3,7 +3,11 @@
 import numpy as np
 
 from shapely import Geometry, GeometryType, lib
-from shapely.decorators import multithreading_enabled, requires_geos
+from shapely.decorators import (
+    deprecate_positional,
+    multithreading_enabled,
+    requires_geos,
+)
 
 __all__ = [
     "coverage_union",
@@ -21,6 +25,16 @@ __all__ = [
 ]
 
 
+# Note: future plan is to change this signature over a few releases:
+# shapely 2.0:
+#   difference(a, b, grid_size=None, **kwargs)
+# shapely 2.1: shows deprecation warning about positional 'grid_size' arg
+#   same signature as 2.0
+# shapely 2.2(?): enforce keyword-only arguments after 'b'
+#   difference(a, b, *, grid_size=None, **kwargs)
+
+
+@deprecate_positional(["grid_size"], category=DeprecationWarning)
 @multithreading_enabled
 def difference(a, b, grid_size=None, **kwargs):
     """Return the part of geometry A that does not intersect with geometry B.
@@ -43,6 +57,14 @@ def difference(a, b, grid_size=None, **kwargs):
     **kwargs
         See :ref:`NumPy ufunc docs <ufuncs.kwargs>` for other keyword arguments.
 
+    Notes
+    -----
+
+    .. deprecated:: 2.1.0
+        A deprecation warning is shown if ``grid_size`` is specified as a
+        positional argument. This will need to be specified as a keyword
+        argument in a future release.
+
     See Also
     --------
     set_precision
@@ -76,6 +98,16 @@ def difference(a, b, grid_size=None, **kwargs):
     return lib.difference(a, b, **kwargs)
 
 
+# Note: future plan is to change this signature over a few releases:
+# shapely 2.0:
+#   intersection(a, b, grid_size=None, **kwargs)
+# shapely 2.1: shows deprecation warning about positional 'grid_size' arg
+#   same signature as 2.0
+# shapely 2.2(?): enforce keyword-only arguments after 'b'
+#   intersection(a, b, *, grid_size=None, **kwargs)
+
+
+@deprecate_positional(["grid_size"], category=DeprecationWarning)
 @multithreading_enabled
 def intersection(a, b, grid_size=None, **kwargs):
     """Return the geometry that is shared between input geometries.
@@ -96,6 +128,14 @@ def intersection(a, b, grid_size=None, **kwargs):
     **kwargs
         See :ref:`NumPy ufunc docs <ufuncs.kwargs>` for other keyword arguments.
 
+    Notes
+    -----
+
+    .. deprecated:: 2.1.0
+        A deprecation warning is shown if ``grid_size`` is specified as a
+        positional argument. This will need to be specified as a keyword
+        argument in a future release.
+
     See Also
     --------
     intersection_all
@@ -126,6 +166,16 @@ def intersection(a, b, grid_size=None, **kwargs):
     return lib.intersection(a, b, **kwargs)
 
 
+# Note: future plan is to change this signature over a few releases:
+# shapely 2.0:
+#   intersection_all(geometries, axis=None, **kwargs)
+# shapely 2.1: shows deprecation warning about positional 'axis' arg
+#   same signature as 2.0
+# shapely 2.2(?): enforce keyword-only arguments after 'geometries'
+#   intersection_all(geometries, *, axis=None, **kwargs)
+
+
+@deprecate_positional(["axis"], category=DeprecationWarning)
 @multithreading_enabled
 def intersection_all(geometries, axis=None, **kwargs):
     """Return the intersection of multiple geometries.
@@ -146,6 +196,14 @@ def intersection_all(geometries, axis=None, **kwargs):
     **kwargs
         See :ref:`NumPy ufunc docs <ufuncs.kwargs>` for other keyword arguments.
 
+    Notes
+    -----
+
+    .. deprecated:: 2.1.0
+        A deprecation warning is shown if ``axis`` is specified as a
+        positional argument. This will need to be specified as a keyword
+        argument in a future release.
+
     See Also
     --------
     intersection
@@ -173,6 +231,16 @@ def intersection_all(geometries, axis=None, **kwargs):
     return lib.intersection_all(geometries, **kwargs)
 
 
+# Note: future plan is to change this signature over a few releases:
+# shapely 2.0:
+#   symmetric_difference(a, b, grid_size=None, **kwargs)
+# shapely 2.1: shows deprecation warning about positional 'grid_size' arg
+#   same signature as 2.0
+# shapely 2.2(?): enforce keyword-only arguments after 'b'
+#   symmetric_difference(a, b, *, grid_size=None, **kwargs)
+
+
+@deprecate_positional(["grid_size"], category=DeprecationWarning)
 @multithreading_enabled
 def symmetric_difference(a, b, grid_size=None, **kwargs):
     """Return the geometry with the portions of input geometries that do not intersect.
@@ -193,6 +261,14 @@ def symmetric_difference(a, b, grid_size=None, **kwargs):
     **kwargs
         See :ref:`NumPy ufunc docs <ufuncs.kwargs>` for other keyword arguments.
 
+    Notes
+    -----
+
+    .. deprecated:: 2.1.0
+        A deprecation warning is shown if ``grid_size`` is specified as a
+        positional argument. This will need to be specified as a keyword
+        argument in a future release.
+
     See Also
     --------
     symmetric_difference_all
@@ -223,6 +299,16 @@ def symmetric_difference(a, b, grid_size=None, **kwargs):
     return lib.symmetric_difference(a, b, **kwargs)
 
 
+# Note: future plan is to change this signature over a few releases:
+# shapely 2.0:
+#   symmetric_difference_all(geometries, axis=None, **kwargs)
+# shapely 2.1: shows deprecation warning about positional 'axis' arg
+#   same signature as 2.0
+# shapely 2.2(?): enforce keyword-only arguments after 'geometries'
+#   symmetric_difference_all(geometries, *, axis=None, **kwargs)
+
+
+@deprecate_positional(["axis"], category=DeprecationWarning)
 @multithreading_enabled
 def symmetric_difference_all(geometries, axis=None, **kwargs):
     """Return the symmetric difference of multiple geometries.
@@ -243,6 +329,14 @@ def symmetric_difference_all(geometries, axis=None, **kwargs):
     **kwargs
         See :ref:`NumPy ufunc docs <ufuncs.kwargs>` for other keyword arguments.
 
+    Notes
+    -----
+
+    .. deprecated:: 2.1.0
+        A deprecation warning is shown if ``axis`` is specified as a
+        positional argument. This will need to be specified as a keyword
+        argument in a future release.
+
     See Also
     --------
     symmetric_difference
@@ -272,6 +366,16 @@ def symmetric_difference_all(geometries, axis=None, **kwargs):
     return lib.symmetric_difference_all(geometries, **kwargs)
 
 
+# Note: future plan is to change this signature over a few releases:
+# shapely 2.0:
+#   union(a, b, grid_size=None, **kwargs)
+# shapely 2.1: shows deprecation warning about positional 'grid_size' arg
+#   same signature as 2.0
+# shapely 2.2(?): enforce keyword-only arguments after 'b'
+#   union(a, b, *, grid_size=None, **kwargs)
+
+
+@deprecate_positional(["grid_size"], category=DeprecationWarning)
 @multithreading_enabled
 def union(a, b, grid_size=None, **kwargs):
     """Merge geometries into one.
@@ -292,6 +396,14 @@ def union(a, b, grid_size=None, **kwargs):
     **kwargs
         See :ref:`NumPy ufunc docs <ufuncs.kwargs>` for other keyword arguments.
 
+    Notes
+    -----
+
+    .. deprecated:: 2.1.0
+        A deprecation warning is shown if ``grid_size`` is specified as a
+        positional argument. This will need to be specified as a keyword
+        argument in a future release.
+
     See Also
     --------
     union_all
@@ -324,6 +436,16 @@ def union(a, b, grid_size=None, **kwargs):
     return lib.union(a, b, **kwargs)
 
 
+# Note: future plan is to change this signature over a few releases:
+# shapely 2.0:
+#   union_all(geometries, grid_size=None, axis=None, **kwargs)
+# shapely 2.1: shows deprecation warning about positional 'grid_size' arg
+#   same signature as 2.0
+# shapely 2.2(?): enforce keyword-only arguments after 'geometries'
+#   union_all(geometries, *, grid_size=None, axis=None, **kwargs)
+
+
+@deprecate_positional(["grid_size", "axis"], category=DeprecationWarning)
 @multithreading_enabled
 def union_all(geometries, grid_size=None, axis=None, **kwargs):
     """Return the union of multiple geometries.
@@ -355,6 +477,14 @@ def union_all(geometries, grid_size=None, axis=None, **kwargs):
     **kwargs
         See :ref:`NumPy ufunc docs <ufuncs.kwargs>` for other keyword arguments.
 
+    Notes
+    -----
+
+    .. deprecated:: 2.1.0
+        A deprecation warning is shown if ``grid_size`` or ``axis`` are
+        specified as positional arguments. In a future release, these will
+        need to be specified as keyword arguments.
+
     See Also
     --------
     union
@@ -447,6 +577,16 @@ def coverage_union(a, b, **kwargs):
     return coverage_union_all([a, b], **kwargs)
 
 
+# Note: future plan is to change this signature over a few releases:
+# shapely 2.0:
+#   coverage_union_all(geometries, axis=None, **kwargs)
+# shapely 2.1: shows deprecation warning about positional 'axis' arg
+#   same signature as 2.0
+# shapely 2.2(?): enforce keyword-only arguments after 'geometries'
+#   coverage_union_all(geometries, *, axis=None, **kwargs)
+
+
+@deprecate_positional(["axis"], category=DeprecationWarning)
 @multithreading_enabled
 def coverage_union_all(geometries, axis=None, **kwargs):
     """Return the union of multiple polygons of a geometry collection.
@@ -470,6 +610,14 @@ def coverage_union_all(geometries, axis=None, **kwargs):
     **kwargs
         See :ref:`NumPy ufunc docs <ufuncs.kwargs>` for other keyword arguments.
 
+    Notes
+    -----
+
+    .. deprecated:: 2.1.0
+        A deprecation warning is shown if ``axis`` is specified as a
+        positional argument. This will need to be specified as a keyword
+        argument in a future release.
+
     See Also
     --------
     coverage_union
@@ -560,7 +708,7 @@ def disjoint_subset_union(a, b, **kwargs):
 
 @requires_geos("3.12.0")
 @multithreading_enabled
-def disjoint_subset_union_all(geometries, axis=None, **kwargs):
+def disjoint_subset_union_all(geometries, *, axis=None, **kwargs):
     """Return the union of multiple polygons.
 
     This is an optimized version of union which assumes inputs can be divided into


Test patch:
diff --git a/shapely/tests/geometry/test_coords.py b/shapely/tests/geometry/test_coords.py
index 1477c20..1132005 100644
--- a/shapely/tests/geometry/test_coords.py
+++ b/shapely/tests/geometry/test_coords.py
@@ -1,8 +1,17 @@
 import numpy as np
 import pytest
 
-from shapely import LineString
-from shapely.tests.common import line_string, line_string_z, point, point_z
+from shapely import LineString, geos_version
+from shapely.tests.common import (
+    line_string,
+    line_string_m,
+    line_string_z,
+    line_string_zm,
+    point,
+    point_m,
+    point_z,
+    point_zm,
+)
 
 
 class TestCoords:
@@ -100,3 +109,19 @@ def test_coords_array_copy(geom):
             np.array(coord_seq, copy=False)
     else:
         assert np.array(coord_seq, copy=False) is np.array(coord_seq, copy=False)
+
+
+@pytest.mark.skipif(geos_version < (3, 12, 0), reason="GEOS < 3.12")
+def test_coords_with_m():
+    assert point_m.coords[:] == [(2.0, 3.0, 5.0)]
+    assert point_zm.coords[:] == [(2.0, 3.0, 4.0, 5.0)]
+    assert line_string_m.coords[:] == [
+        (0.0, 0.0, 1.0),
+        (1.0, 0.0, 2.0),
+        (1.0, 1.0, 3.0),
+    ]
+    assert line_string_zm.coords[:] == [
+        (0.0, 0.0, 4.0, 1.0),
+        (1.0, 0.0, 4.0, 2.0),
+        (1.0, 1.0, 4.0, 3.0),
+    ]
diff --git a/shapely/tests/geometry/test_format.py b/shapely/tests/geometry/test_format.py
index 797b684..36c0fa3 100644
--- a/shapely/tests/geometry/test_format.py
+++ b/shapely/tests/geometry/test_format.py
@@ -79,7 +79,7 @@ def test_format_point(format_spec, coords, expt_wkt, same_python_float):
 
 def test_format_polygon():
     # check basic cases
-    poly = Point(0, 0).buffer(10, 2)
+    poly = Point(0, 0).buffer(10, quad_segs=2)
     assert f"{poly}" == poly.wkt
     assert format(poly, "") == poly.wkt
     assert format(poly, "x") == poly.wkb_hex.lower()
diff --git a/shapely/tests/geometry/test_geometry_base.py b/shapely/tests/geometry/test_geometry_base.py
index c1c665a..0314ccb 100644
--- a/shapely/tests/geometry/test_geometry_base.py
+++ b/shapely/tests/geometry/test_geometry_base.py
@@ -277,3 +277,93 @@ def test_array_argument_buffer():
     # check scalar
     result = point.buffer(distances[0])
     assert isinstance(result, Polygon)
+
+
+def test_buffer_deprecate_positional():
+    point = Point(1, 1)
+    with pytest.deprecated_call(
+        match="positional argument `cap_style` for `buffer` is deprecated"
+    ):
+        point.buffer(1.0, 8, "round")
+    with pytest.deprecated_call(
+        match="positional arguments `cap_style` and `join_style` "
+        "for `buffer` are deprecated"
+    ):
+        point.buffer(1.0, 8, "round", "round")
+    with pytest.deprecated_call():
+        point.buffer(1.0, 8, "round", "round", 5.0)
+    with pytest.deprecated_call():
+        point.buffer(1.0, 8, "round", "round", 5.0, False)
+
+
+def test_simplify_deprecate_positional():
+    linestring = LineString([(0, 0), (1, 1)])
+    with pytest.deprecated_call(
+        match="positional argument `preserve_topology` for `simplify` is deprecated"
+    ):
+        linestring.simplify(1.0, True)
+
+
+def test_difference_deprecate_positional():
+    point = Point(1, 1)
+    with pytest.deprecated_call(
+        match="positional argument `grid_size` for `difference` is deprecated"
+    ):
+        point.difference(point, None)
+
+
+def test_intersection_deprecate_positional():
+    point = Point(1, 1)
+    with pytest.deprecated_call(
+        match="positional argument `grid_size` for `intersection` is deprecated"
+    ):
+        point.intersection(point, None)
+
+
+def test_symmetric_difference_deprecate_positional():
+    point = Point(1, 1)
+    with pytest.deprecated_call(
+        match="positional argument `grid_size` for `symmetric_difference` is deprecated"
+    ):
+        point.symmetric_difference(point, None)
+
+
+def test_union_deprecate_positional():
+    point = Point(1, 1)
+    with pytest.deprecated_call(
+        match="positional argument `grid_size` for `union` is deprecated"
+    ):
+        point.union(point, None)
+
+
+def test_line_locate_point_deprecate_positional():
+    line_string = LineString([(1.0, 2.0), (3.0, 4.0)])
+    with pytest.deprecated_call(
+        match="positional argument `normalized` for `line_locate_point` is deprecated"
+    ):
+        line_string.line_locate_point(Point(1, 1), False)
+
+
+def test_project_deprecate_positional():
+    line_string = LineString([(1.0, 2.0), (3.0, 4.0)])
+    with pytest.deprecated_call(
+        match="positional argument `normalized` for `project` is deprecated"
+    ):
+        line_string.project(Point(1, 1), False)
+
+
+def test_line_interpolate_point_deprecate_positional():
+    line_string = LineString([(1.0, 2.0), (3.0, 4.0)])
+    with pytest.deprecated_call(
+        match="positional argument `normalized` for `line_interpolate_point` "
+        "is deprecated"
+    ):
+        line_string.line_interpolate_point(0, False)
+
+
+def test_interpolate_deprecate_positional():
+    line_string = LineString([(1.0, 2.0), (3.0, 4.0)])
+    with pytest.deprecated_call(
+        match="positional argument `normalized` for `interpolate` is deprecated"
+    ):
+        line_string.interpolate(0, False)
diff --git a/shapely/tests/geometry/test_linestring.py b/shapely/tests/geometry/test_linestring.py
index d078a6a..231c75a 100644
--- a/shapely/tests/geometry/test_linestring.py
+++ b/shapely/tests/geometry/test_linestring.py
@@ -212,3 +212,21 @@ def test_linestring_array_coercion():
     assert arr.size == 1
     assert arr.dtype == np.dtype("object")
     assert arr.item() == line
+
+
+def test_offset_curve_deprecate_positional():
+    line_string = LineString([(1.0, 2.0), (3.0, 4.0)])
+    with pytest.deprecated_call(
+        match="positional argument `quad_segs` for `offset_curve` is deprecated"
+    ):
+        line_string.offset_curve(1.0, 8)
+    with pytest.deprecated_call(
+        match="positional arguments `quad_segs` and `join_style` "
+        "for `offset_curve` are deprecated"
+    ):
+        line_string.offset_curve(1.0, 8, "round")
+    with pytest.deprecated_call(
+        match="positional arguments `quad_segs`, `join_style`, and `mitre_limit` "
+        "for `offset_curve` are deprecated"
+    ):
+        line_string.offset_curve(1.0, 8, "round", 5.0)
diff --git a/shapely/tests/geometry/test_polygon.py b/shapely/tests/geometry/test_polygon.py
index 7d18da9..21a67a4 100644
--- a/shapely/tests/geometry/test_polygon.py
+++ b/shapely/tests/geometry/test_polygon.py
@@ -352,7 +352,7 @@ class TestPolygon:
             (0.0, 0.0),
         ]
 
-        ec = list(Point(0.0, 0.0).buffer(1.0, 1).exterior.coords)
+        ec = list(Point(0.0, 0.0).buffer(1.0, quad_segs=1).exterior.coords)
         assert isinstance(ec, list)  # TODO: this is a poor test
 
         # Test chained access to interiors
diff --git a/shapely/tests/legacy/test_operations.py b/shapely/tests/legacy/test_operations.py
index 9c70e53..8b8b732 100644
--- a/shapely/tests/legacy/test_operations.py
+++ b/shapely/tests/legacy/test_operations.py
@@ -28,7 +28,7 @@ class OperationsTestCase(unittest.TestCase):
 
         # Buffer
         assert isinstance(point.buffer(10.0), Polygon)
-        assert isinstance(point.buffer(10.0, 32), Polygon)
+        assert isinstance(point.buffer(10.0, quad_segs=32), Polygon)
 
         # Simplify
         p = loads(
diff --git a/shapely/tests/test_constructive.py b/shapely/tests/test_constructive.py
index 89992d3..fffdca7 100644
--- a/shapely/tests/test_constructive.py
+++ b/shapely/tests/test_constructive.py
@@ -1301,3 +1301,65 @@ def test_orient_polygons_non_polygonal_input():
     arr = np.array([Point(0, 0), LineString([(0, 0), (1, 1)]), None])
     result = shapely.orient_polygons(arr)
     assert_geometries_equal(result, arr)
+
+
+def test_buffer_deprecate_positional():
+    with pytest.deprecated_call(
+        match="positional argument `quad_segs` for `buffer` is deprecated"
+    ):
+        shapely.buffer(point, 1.0, 8)
+    with pytest.deprecated_call(
+        match="positional arguments `quad_segs` and `cap_style` "
+        "for `buffer` are deprecated"
+    ):
+        shapely.buffer(point, 1.0, 8, "round")
+    with pytest.deprecated_call(
+        match="positional arguments `quad_segs`, `cap_style`, and `join_style` "
+        "for `buffer` are deprecated"
+    ):
+        shapely.buffer(point, 1.0, 8, "round", "round")
+    with pytest.deprecated_call():
+        shapely.buffer(point, 1.0, 8, "round", "round", 5.0)
+    with pytest.deprecated_call():
+        shapely.buffer(point, 1.0, 8, "round", "round", 5.0, False)
+
+
+def test_offset_curve_deprecate_positional():
+    with pytest.deprecated_call(
+        match="positional argument `quad_segs` for `offset_curve` is deprecated"
+    ):
+        shapely.offset_curve(line_string, 1.0, 8)
+    with pytest.deprecated_call(
+        match="positional arguments `quad_segs` and `join_style` "
+        "for `offset_curve` are deprecated"
+    ):
+        shapely.offset_curve(line_string, 1.0, 8, "round")
+    with pytest.deprecated_call(
+        match="positional arguments `quad_segs`, `join_style`, and `mitre_limit` "
+        "for `offset_curve` are deprecated"
+    ):
+        shapely.offset_curve(line_string, 1.0, 8, "round", 5.0)
+
+
+def test_simplify_deprecate_positional():
+    with pytest.deprecated_call(
+        match="positional argument `preserve_topology` for `simplify` is deprecated"
+    ):
+        shapely.simplify(line_string, 1.0, True)
+
+
+def test_voronoi_polygons_deprecate_positional():
+    with pytest.deprecated_call(
+        match="positional argument `extend_to` for `voronoi_polygons` is deprecated"
+    ):
+        shapely.voronoi_polygons(multi_point, 0.0, None)
+    with pytest.deprecated_call(
+        match="positional arguments `extend_to` and `only_edges` "
+        "for `voronoi_polygons` are deprecated"
+    ):
+        shapely.voronoi_polygons(multi_point, 0.0, None, False)
+    with pytest.deprecated_call(
+        match="positional arguments `extend_to`, `only_edges`, and `ordered` "
+        "for `voronoi_polygons` are deprecated"
+    ):
+        shapely.voronoi_polygons(multi_point, 0.0, None, False, False)
diff --git a/shapely/tests/test_coordinates.py b/shapely/tests/test_coordinates.py
index 706403c..a72d5a3 100644
--- a/shapely/tests/test_coordinates.py
+++ b/shapely/tests/test_coordinates.py
@@ -202,7 +202,7 @@ def test_get_coords_zm(geoms, x, y, z, m, include_z, include_m):
     assert_equal(actual, np.array(expected, np.float64).T)
 
 
-def test_get_coords_pos_args_deprecation_warning():
+def test_get_coords_deprecate_positional():
     with pytest.deprecated_call(
         match="positional argument `include_z` for `get_coordinates` is deprecated"
     ):
@@ -413,3 +413,10 @@ def test_transform_auto_coordinate_dimension_mixed_interleaved():
         shapely.get_coordinates(line_string_z, include_z=True) + [1, 2, 3],
         shapely.get_coordinates(new_geom[1], include_z=True),
     )
+
+
+def test_transform_deprecate_positional():
+    with pytest.deprecated_call(
+        match="positional argument `include_z` for `transform` is deprecated"
+    ):
+        transform(line_string_z, lambda x: x + 1, False)
diff --git a/shapely/tests/test_creation.py b/shapely/tests/test_creation.py
index 84564c8..5d98c34 100644
--- a/shapely/tests/test_creation.py
+++ b/shapely/tests/test_creation.py
@@ -1,3 +1,5 @@
+"""See test_creation_indices.py for tests with 'indices' parameter."""
+
 import numpy as np
 import pytest
 from numpy.testing import assert_array_equal
@@ -692,6 +694,13 @@ def test_box_nan(coords):
     assert shapely.box(*coords) is None
 
 
+def test_box_deprecate_positional():
+    with pytest.deprecated_call(
+        match="positional argument `ccw` for `box` is deprecated"
+    ):
+        shapely.box(0, 0, 1, 1, True)
+
+
 def test_prepare():
     arr = np.array([shapely.points(1, 1), None, shapely.box(0, 0, 1, 1)])
     assert arr[0]._geom_prepared == 0
diff --git a/shapely/tests/test_creation_indices.py b/shapely/tests/test_creation_indices.py
index 0849cab..c4533b1 100644
--- a/shapely/tests/test_creation_indices.py
+++ b/shapely/tests/test_creation_indices.py
@@ -527,3 +527,59 @@ def test_multipolygons():
 def test_incompatible_types(geometries, func):
     with pytest.raises(TypeError):
         func(geometries, indices=[0])
+
+
+def test_points_deprecate_positional():
+    with pytest.deprecated_call(
+        match="positional argument `indices` for `points` is deprecated"
+    ):
+        shapely.points([[0, 1], [2, 3]], None, None, [0, 1])
+
+
+def test_linestrings_deprecate_positional():
+    with pytest.deprecated_call(
+        match="positional argument `indices` for `linestrings` is deprecated"
+    ):
+        shapely.linestrings([[0, 1], [2, 3], [4, 5], [6, 7]], None, None, [0, 0, 1, 1])
+
+
+def test_linearrings_deprecate_positional():
+    with pytest.deprecated_call(
+        match="positional argument `indices` for `linearrings` is deprecated"
+    ):
+        shapely.linearrings([[0, 1], [1, 1], [1, 0]], None, None, [0, 0, 0])
+
+
+def test_polygons_deprecate_positional():
+    with pytest.deprecated_call(
+        match="positional argument `indices` for `polygons` is deprecated"
+    ):
+        shapely.polygons([linear_ring, linear_ring], None, [0, 1])
+
+
+def test_multipoints_deprecate_positional():
+    with pytest.deprecated_call(
+        match="positional argument `indices` for `multipoints` is deprecated"
+    ):
+        shapely.multipoints([point, point], [0, 1])
+
+
+def test_multilinestrings_deprecate_positional():
+    with pytest.deprecated_call(
+        match="positional argument `indices` for `multilinestrings` is deprecated"
+    ):
+        shapely.multilinestrings([line_string, line_string], [0, 1])
+
+
+def test_multipolygons_deprecate_positional():
+    with pytest.deprecated_call(
+        match="positional argument `indices` for `multipolygons` is deprecated"
+    ):
+        shapely.multipolygons([polygon, polygon], [0, 1])
+
+
+def test_geometrycollections_deprecate_positional():
+    with pytest.deprecated_call(
+        match="positional argument `indices` for `geometrycollections` is deprecated"
+    ):
+        shapely.geometrycollections([point, polygon], [0, 1])
diff --git a/shapely/tests/test_geometry.py b/shapely/tests/test_geometry.py
index f4de7f0..8a255be 100644
--- a/shapely/tests/test_geometry.py
+++ b/shapely/tests/test_geometry.py
@@ -369,6 +369,13 @@ def test_get_parts_invalid_geometry(geom):
         shapely.get_parts(geom)
 
 
+def test_get_parts_deprecate_positional():
+    with pytest.deprecated_call(
+        match="positional argument `return_index` for `get_parts` is deprecated"
+    ):
+        shapely.get_parts(multi_point, False)
+
+
 @pytest.mark.parametrize(
     "geom",
     [
@@ -431,6 +438,13 @@ def test_get_rings_invalid_dimensions(geom):
         shapely.get_parts(geom)
 
 
+def test_get_rings_deprecate_positional():
+    with pytest.deprecated_call(
+        match="positional argument `return_index` for `get_rings` is deprecated"
+    ):
+        shapely.get_rings(polygon, False)
+
+
 def test_get_precision():
     geometries = all_types + (point_z, empty_point, empty_line_string, empty_polygon)
     # default is 0
diff --git a/shapely/tests/test_linear.py b/shapely/tests/test_linear.py
index 3c37d0c..e1a5d13 100644
--- a/shapely/tests/test_linear.py
+++ b/shapely/tests/test_linear.py
@@ -90,6 +90,14 @@ def test_line_interpolate_point_nan():
     assert shapely.line_interpolate_point(line_string, np.nan) is None
 
 
+def test_line_interpolate_point_deprecate_positional():
+    with pytest.deprecated_call(
+        match="positional argument `normalized` for `line_interpolate_point` "
+        "is deprecated"
+    ):
+        shapely.line_interpolate_point(line_string, 0, False)
+
+
 def test_line_locate_point_geom_array():
     point = shapely.points(0, 1)
     actual = shapely.line_locate_point([line_string, linear_ring], point)
@@ -127,6 +135,13 @@ def test_line_locate_point_invalid_geometry(normalized):
         shapely.line_locate_point(polygon, point, normalized=normalized)
 
 
+def test_line_locate_point_deprecate_positional():
+    with pytest.deprecated_call(
+        match="positional argument `normalized` for `line_locate_point` is deprecated"
+    ):
+        shapely.line_locate_point(line_string, point, False)
+
+
 def test_line_merge_geom_array():
     actual = shapely.line_merge([line_string, multi_line_string])
     assert_geometries_equal(actual[0], line_string)
diff --git a/shapely/tests/test_set_operations.py b/shapely/tests/test_set_operations.py
index 4ce0f35..7ef5b81 100644
--- a/shapely/tests/test_set_operations.py
+++ b/shapely/tests/test_set_operations.py
@@ -409,3 +409,65 @@ def test_uary_union_alias():
     actual = shapely.unary_union(geoms, grid_size=1)
     expected = shapely.union_all(geoms, grid_size=1)
     assert shapely.equals(actual, expected)
+
+
+def test_difference_deprecate_positional():
+    with pytest.deprecated_call(
+        match="positional argument `grid_size` for `difference` is deprecated"
+    ):
+        shapely.difference(point, point, None)
+
+
+def test_intersection_deprecate_positional():
+    with pytest.deprecated_call(
+        match="positional argument `grid_size` for `intersection` is deprecated"
+    ):
+        shapely.intersection(point, point, None)
+
+
+def test_intersection_all_deprecate_positional():
+    with pytest.deprecated_call(
+        match="positional argument `axis` for `intersection_all` is deprecated"
+    ):
+        shapely.intersection_all([point, point], None)
+
+
+def test_symmetric_difference_deprecate_positional():
+    with pytest.deprecated_call(
+        match="positional argument `grid_size` for `symmetric_difference` is deprecated"
+    ):
+        shapely.symmetric_difference(point, point, None)
+
+
+def test_symmetric_difference_all_deprecate_positional():
+    with pytest.deprecated_call(
+        match="positional argument `axis` for `symmetric_difference_all` is deprecated"
+    ):
+        shapely.symmetric_difference_all([point, point], None)
+
+
+def test_union_deprecate_positional():
+    with pytest.deprecated_call(
+        match="positional argument `grid_size` for `union` is deprecated"
+    ):
+        shapely.union(point, point, None)
+
+
+def test_union_all_deprecate_positional():
+    with pytest.deprecated_call(
+        match="positional argument `grid_size` for `union_all` is deprecated"
+    ):
+        shapely.union_all([point, point], None)
+    with pytest.deprecated_call(
+        match="positional arguments `grid_size` and `axis` for `union_all` "
+        "are deprecated"
+    ):
+        shapely.union_all([point, point], None, None)
+
+
+def test_coverage_union_all_deprecate_positional():
+    data = [shapely.box(0, 0, 1, 1), shapely.box(1, 0, 2, 1)]
+    with pytest.deprecated_call(
+        match="positional argument `axis` for `coverage_union_all` is deprecated"
+    ):
+        shapely.coverage_union_all(data, None)