Repository: SciTools/cartopy

Issue:
Address Shapely 2.0 Deprecations
### Description

The Shapely 1.8 release is out now and is now emitting a bunch of `ShapelyDeprecationWarning` for things that will no longer work in Shapely 2.0.  Here's a sampling of a current CI run I made against 3.9

<details>

```
  <__array_function__ internals>:5: ShapelyDeprecationWarning: The array interface is deprecated and will no longer work in Shapely 2.0. Convert the '.coords' to a numpy array instead.
  /home/runner/work/cartopy/cartopy/lib/cartopy/crs.py:825: ShapelyDeprecationWarning: __len__ for multi-part geometries is deprecated and will be removed in Shapely 2.0. Check the length of the `geoms` property instead to get the  number of parts of a multi-part geometry.
  /home/runner/work/cartopy/cartopy/lib/cartopy/crs.py:836: ShapelyDeprecationWarning: Iteration over multi-part geometries is deprecated and will be removed in Shapely 2.0. Use the `geoms` property to access the constituent parts of a multi-part geometry.
  /home/runner/work/cartopy/cartopy/lib/cartopy/crs.py:836: ShapelyDeprecationWarning: __len__ for multi-part geometries is deprecated and will be removed in Shapely 2.0. Check the length of the `geoms` property instead to get the  number of parts of a multi-part geometry.
  /home/runner/work/cartopy/cartopy/lib/cartopy/crs.py:877: ShapelyDeprecationWarning: Iteration over multi-part geometries is deprecated and will be removed in Shapely 2.0. Use the `geoms` property to access the constituent parts of a multi-part geometry.
  /home/runner/work/cartopy/cartopy/lib/cartopy/crs.py:944: ShapelyDeprecationWarning: __len__ for multi-part geometries is deprecated and will be removed in Shapely 2.0. Check the length of the `geoms` property instead to get the  number of parts of a multi-part geometry.
  /home/runner/work/cartopy/cartopy/lib/cartopy/crs.py:982: ShapelyDeprecationWarning: Iteration over multi-part geometries is deprecated and will be removed in Shapely 2.0. Use the `geoms` property to access the constituent parts of a multi-part geometry.
  /home/runner/work/cartopy/cartopy/lib/cartopy/crs.py:982: ShapelyDeprecationWarning: __len__ for multi-part geometries is deprecated and will be removed in Shapely 2.0. Check the length of the `geoms` property instead to get the  number of parts of a multi-part geometry.
  /home/runner/work/cartopy/cartopy/lib/cartopy/io/ogc_clients.py:165: ShapelyDeprecationWarning: Iteration over multi-part geometries is deprecated and will be removed in Shapely 2.0. Use the `geoms` property to access the constituent parts of a multi-part geometry.
  /home/runner/work/cartopy/cartopy/lib/cartopy/mpl/gridliner.py:842: ShapelyDeprecationWarning: __len__ for multi-part geometries is deprecated and will be removed in Shapely 2.0. Check the length of the `geoms` property instead to get the  number of parts of a multi-part geometry.
  /home/runner/work/cartopy/cartopy/lib/cartopy/mpl/gridliner.py:848: ShapelyDeprecationWarning: __getitem__ for multi-part geometries is deprecated and will be removed in Shapely 2.0. Use the `geoms` property to access the constituent parts of a multi-part geometry.
  /home/runner/work/cartopy/cartopy/lib/cartopy/mpl/gridliner.py:853: ShapelyDeprecationWarning: Iteration over multi-part geometries is deprecated and will be removed in Shapely 2.0. Use the `geoms` property to access the constituent parts of a multi-part geometry.
  /home/runner/work/cartopy/cartopy/lib/cartopy/tests/test_crs.py:210: ShapelyDeprecationWarning: __len__ for multi-part geometries is deprecated and will be removed in Shapely 2.0. Check the length of the `geoms` property instead to get the  number of parts of a multi-part geometry.
  /home/runner/work/cartopy/cartopy/lib/cartopy/tests/test_crs.py:211: ShapelyDeprecationWarning: __getitem__ for multi-part geometries is deprecated and will be removed in Shapely 2.0. Use the `geoms` property to access the constituent parts of a multi-part geometry.
  /home/runner/work/cartopy/cartopy/lib/cartopy/tests/test_crs.py:212: ShapelyDeprecationWarning: __getitem__ for multi-part geometries is deprecated and will be removed in Shapely 2.0. Use the `geoms` property to access the constituent parts of a multi-part geometry.
  /home/runner/work/cartopy/cartopy/lib/cartopy/tests/test_linear_ring.py:138: ShapelyDeprecationWarning: __len__ for multi-part geometries is deprecated and will be removed in Shapely 2.0. Check the length of the `geoms` property instead to get the  number of parts of a multi-part geometry.
  /home/runner/work/cartopy/cartopy/lib/cartopy/tests/test_linear_ring.py:144: ShapelyDeprecationWarning: __len__ for multi-part geometries is deprecated and will be removed in Shapely 2.0. Check the length of the `geoms` property instead to get the  number of parts of a multi-part geometry.
  /home/runner/work/cartopy/cartopy/lib/cartopy/tests/test_linear_ring.py:173: ShapelyDeprecationWarning: __len__ for multi-part geometries is deprecated and will be removed in Shapely 2.0. Check the length of the `geoms` property instead to get the  number of parts of a multi-part geometry.
  /home/runner/work/cartopy/cartopy/lib/cartopy/tests/test_linear_ring.py:23: ShapelyDeprecationWarning: __len__ for multi-part geometries is deprecated and will be removed in Shapely 2.0. Check the length of the `geoms` property instead to get the  number of parts of a multi-part geometry.
  /home/runner/work/cartopy/cartopy/lib/cartopy/tests/test_linear_ring.py:40: ShapelyDeprecationWarning: Iteration over multi-part geometries is deprecated and will be removed in Shapely 2.0. Use the `geoms` property to access the constituent parts of a multi-part geometry.
  /home/runner/work/cartopy/cartopy/lib/cartopy/tests/test_linear_ring.py:71: ShapelyDeprecationWarning: __len__ for multi-part geometries is deprecated and will be removed in Shapely 2.0. Check the length of the `geoms` property instead to get the  number of parts of a multi-part geometry.
  /home/runner/work/cartopy/cartopy/lib/cartopy/tests/test_linear_ring.py:89: ShapelyDeprecationWarning: __len__ for multi-part geometries is deprecated and will be removed in Shapely 2.0. Check the length of the `geoms` property instead to get the  number of parts of a multi-part geometry.
  /home/runner/work/cartopy/cartopy/lib/cartopy/tests/test_line_string.py:106: ShapelyDeprecationWarning: __len__ for multi-part geometries is deprecated and will be removed in Shapely 2.0. Check the length of the `geoms` property instead to get the  number of parts of a multi-part geometry.
  /home/runner/work/cartopy/cartopy/lib/cartopy/tests/test_line_string.py:107: ShapelyDeprecationWarning: __getitem__ for multi-part geometries is deprecated and will be removed in Shapely 2.0. Use the `geoms` property to access the constituent parts of a multi-part geometry.
  /home/runner/work/cartopy/cartopy/lib/cartopy/tests/test_line_string.py:113: ShapelyDeprecationWarning: __len__ for multi-part geometries is deprecated and will be removed in Shapely 2.0. Check the length of the `geoms` property instead to get the  number of parts of a multi-part geometry.
  /home/runner/work/cartopy/cartopy/lib/cartopy/tests/test_line_string.py:114: ShapelyDeprecationWarning: __getitem__ for multi-part geometries is deprecated and will be removed in Shapely 2.0. Use the `geoms` property to access the constituent parts of a multi-part geometry.
  /home/runner/work/cartopy/cartopy/lib/cartopy/tests/test_line_string.py:120: ShapelyDeprecationWarning: __len__ for multi-part geometries is deprecated and will be removed in Shapely 2.0. Check the length of the `geoms` property instead to get the  number of parts of a multi-part geometry.
  /home/runner/work/cartopy/cartopy/lib/cartopy/tests/test_line_string.py:121: ShapelyDeprecationWarning: __getitem__ for multi-part geometries is deprecated and will be removed in Shapely 2.0. Use the `geoms` property to access the constituent parts of a multi-part geometry.
  /home/runner/work/cartopy/cartopy/lib/cartopy/tests/test_line_string.py:127: ShapelyDeprecationWarning: __len__ for multi-part geometries is deprecated and will be removed in Shapely 2.0. Check the length of the `geoms` property instead to get the  number of parts of a multi-part geometry.
  /home/runner/work/cartopy/cartopy/lib/cartopy/tests/test_line_string.py:128: ShapelyDeprecationWarning: __getitem__ for multi-part geometries is deprecated and will be removed in Shapely 2.0. Use the `geoms` property to access the constituent parts of a multi-part geometry.
  /home/runner/work/cartopy/cartopy/lib/cartopy/tests/test_line_string.py:134: ShapelyDeprecationWarning: __len__ for multi-part geometries is deprecated and will be removed in Shapely 2.0. Check the length of the `geoms` property instead to get the  number of parts of a multi-part geometry.
  /home/runner/work/cartopy/cartopy/lib/cartopy/tests/test_line_string.py:140: ShapelyDeprecationWarning: __len__ for multi-part geometries is deprecated and will be removed in Shapely 2.0. Check the length of the `geoms` property instead to get the  number of parts of a multi-part geometry.
  /home/runner/work/cartopy/cartopy/lib/cartopy/tests/test_line_string.py:141: ShapelyDeprecationWarning: __getitem__ for multi-part geometries is deprecated and will be removed in Shapely 2.0. Use the `geoms` property to access the constituent parts of a multi-part geometry.
  /home/runner/work/cartopy/cartopy/lib/cartopy/tests/test_line_string.py:147: ShapelyDeprecationWarning: __len__ for multi-part geometries is deprecated and will be removed in Shapely 2.0. Check the length of the `geoms` property instead to get the  number of parts of a multi-part geometry.
  /home/runner/work/cartopy/cartopy/lib/cartopy/tests/test_line_string.py:148: ShapelyDeprecationWarning: __getitem__ for multi-part geometries is deprecated and will be removed in Shapely 2.0. Use the `geoms` property to access the constituent parts of a multi-part geometry.
  /home/runner/work/cartopy/cartopy/lib/cartopy/tests/test_line_string.py:149: ShapelyDeprecationWarning: __getitem__ for multi-part geometries is deprecated and will be removed in Shapely 2.0. Use the `geoms` property to access the constituent parts of a multi-part geometry.
  /home/runner/work/cartopy/cartopy/lib/cartopy/tests/test_line_string.py:155: ShapelyDeprecationWarning: __len__ for multi-part geometries is deprecated and will be removed in Shapely 2.0. Check the length of the `geoms` property instead to get the  number of parts of a multi-part geometry.
  /home/runner/work/cartopy/cartopy/lib/cartopy/tests/test_line_string.py:156: ShapelyDeprecationWarning: __getitem__ for multi-part geometries is deprecated and will be removed in Shapely 2.0. Use the `geoms` property to access the constituent parts of a multi-part geometry.
  /home/runner/work/cartopy/cartopy/lib/cartopy/tests/test_line_string.py:162: ShapelyDeprecationWarning: __len__ for multi-part geometries is deprecated and will be removed in Shapely 2.0. Check the length of the `geoms` property instead to get the  number of parts of a multi-part geometry.
  /home/runner/work/cartopy/cartopy/lib/cartopy/tests/test_line_string.py:163: ShapelyDeprecationWarning: __getitem__ for multi-part geometries is deprecated and will be removed in Shapely 2.0. Use the `geoms` property to access the constituent parts of a multi-part geometry.
  /home/runner/work/cartopy/cartopy/lib/cartopy/tests/test_line_string.py:170: ShapelyDeprecationWarning: __len__ for multi-part geometries is deprecated and will be removed in Shapely 2.0. Check the length of the `geoms` property instead to get the  number of parts of a multi-part geometry.
  /home/runner/work/cartopy/cartopy/lib/cartopy/tests/test_line_string.py:171: ShapelyDeprecationWarning: __getitem__ for multi-part geometries is deprecated and will be removed in Shapely 2.0. Use the `geoms` property to access the constituent parts of a multi-part geometry.
  /home/runner/work/cartopy/cartopy/lib/cartopy/tests/test_line_string.py:178: ShapelyDeprecationWarning: __len__ for multi-part geometries is deprecated and will be removed in Shapely 2.0. Check the length of the `geoms` property instead to get the  number of parts of a multi-part geometry.
  /home/runner/work/cartopy/cartopy/lib/cartopy/tests/test_line_string.py:179: ShapelyDeprecationWarning: Iteration over multi-part geometries is deprecated and will be removed in Shapely 2.0. Use the `geoms` property to access the constituent parts of a multi-part geometry.
  /home/runner/work/cartopy/cartopy/lib/cartopy/tests/test_line_string.py:191: ShapelyDeprecationWarning: __len__ for multi-part geometries is deprecated and will be removed in Shapely 2.0. Check the length of the `geoms` property instead to get the  number of parts of a multi-part geometry.
  /home/runner/work/cartopy/cartopy/lib/cartopy/tests/test_line_string.py:192: ShapelyDeprecationWarning: Iteration over multi-part geometries is deprecated and will be removed in Shapely 2.0. Use the `geoms` property to access the constituent parts of a multi-part geometry.
  /home/runner/work/cartopy/cartopy/lib/cartopy/tests/test_line_string.py:206: ShapelyDeprecationWarning: Iteration over multi-part geometries is deprecated and will be removed in Shapely 2.0. Use the `geoms` property to access the constituent parts of a multi-part geometry.
  /home/runner/work/cartopy/cartopy/lib/cartopy/tests/test_line_string.py:216: ShapelyDeprecationWarning: __len__ for multi-part geometries is deprecated and will be removed in Shapely 2.0. Check the length of the `geoms` property instead to get the  number of parts of a multi-part geometry.
  /home/runner/work/cartopy/cartopy/lib/cartopy/tests/test_line_string.py:217: ShapelyDeprecationWarning: __getitem__ for multi-part geometries is deprecated and will be removed in Shapely 2.0. Use the `geoms` property to access the constituent parts of a multi-part geometry.
  /home/runner/work/cartopy/cartopy/lib/cartopy/tests/test_line_string.py:225: ShapelyDeprecationWarning: __len__ for multi-part geometries is deprecated and will be removed in Shapely 2.0. Check the length of the `geoms` property instead to get the  number of parts of a multi-part geometry.
  /home/runner/work/cartopy/cartopy/lib/cartopy/tests/test_line_string.py:229: ShapelyDeprecationWarning: __len__ for multi-part geometries is deprecated and will be removed in Shapely 2.0. Check the length of the `geoms` property instead to get the  number of parts of a multi-part geometry.
  /home/runner/work/cartopy/cartopy/lib/cartopy/tests/test_line_string.py:247: ShapelyDeprecationWarning: __len__ for multi-part geometries is deprecated and will be removed in Shapely 2.0. Check the length of the `geoms` property instead to get the  number of parts of a multi-part geometry.
  /home/runner/work/cartopy/cartopy/lib/cartopy/tests/test_line_string.py:248: ShapelyDeprecationWarning: __len__ for multi-part geometries is deprecated and will be removed in Shapely 2.0. Check the length of the `geoms` property instead to get the  number of parts of a multi-part geometry.
  /home/runner/work/cartopy/cartopy/lib/cartopy/tests/test_line_string.py:249: ShapelyDeprecationWarning: __getitem__ for multi-part geometries is deprecated and will be removed in Shapely 2.0. Use the `geoms` property to access the constituent parts of a multi-part geometry.
  /home/runner/work/cartopy/cartopy/lib/cartopy/tests/test_line_string.py:250: ShapelyDeprecationWarning: __getitem__ for multi-part geometries is deprecated and will be removed in Shapely 2.0. Use the `geoms` property to access the constituent parts of a multi-part geometry.
  /home/runner/work/cartopy/cartopy/lib/cartopy/tests/test_line_string.py:36: ShapelyDeprecationWarning: __len__ for multi-part geometries is deprecated and will be removed in Shapely 2.0. Check the length of the `geoms` property instead to get the  number of parts of a multi-part geometry.
  /home/runner/work/cartopy/cartopy/lib/cartopy/tests/test_line_string.py:54: ShapelyDeprecationWarning: __len__ for multi-part geometries is deprecated and will be removed in Shapely 2.0. Check the length of the `geoms` property instead to get the  number of parts of a multi-part geometry.
  /home/runner/work/cartopy/cartopy/lib/cartopy/tests/test_line_string.py:62: ShapelyDeprecationWarning: __len__ for multi-part geometries is deprecated and will be removed in Shapely 2.0. Check the length of the `geoms` property instead to get the  number of parts of a multi-part geometry.
  /home/runner/work/cartopy/cartopy/lib/cartopy/tests/test_polygon.py:177: ShapelyDeprecationWarning: __len__ for multi-part geometries is deprecated and will be removed in Shapely 2.0. Check the length of the `geoms` property instead to get the  number of parts of a multi-part geometry.
  /home/runner/work/cartopy/cartopy/lib/cartopy/tests/test_polygon.py:178: ShapelyDeprecationWarning: __getitem__ for multi-part geometries is deprecated and will be removed in Shapely 2.0. Use the `geoms` property to access the constituent parts of a multi-part geometry.
  /home/runner/work/cartopy/cartopy/lib/cartopy/tests/test_polygon.py:24: ShapelyDeprecationWarning: Iteration over multi-part geometries is deprecated and will be removed in Shapely 2.0. Use the `geoms` property to access the constituent parts of a multi-part geometry.
  /home/runner/work/cartopy/cartopy/lib/cartopy/tests/test_polygon.py:301: ShapelyDeprecationWarning: __len__ for multi-part geometries is deprecated and will be removed in Shapely 2.0. Check the length of the `geoms` property instead to get the  number of parts of a multi-part geometry.
  /home/runner/work/cartopy/cartopy/lib/cartopy/tests/test_polygon.py:308: ShapelyDeprecationWarning: __getitem__ for multi-part geometries is deprecated and will be removed in Shapely 2.0. Use the `geoms` property to access the constituent parts of a multi-part geometry.
  /home/runner/work/cartopy/cartopy/lib/cartopy/tests/test_polygon.py:318: ShapelyDeprecationWarning: __getitem__ for multi-part geometries is deprecated and will be removed in Shapely 2.0. Use the `geoms` property to access the constituent parts of a multi-part geometry.
  /home/runner/work/cartopy/cartopy/lib/cartopy/tests/test_polygon.py:350: ShapelyDeprecationWarning: __len__ for multi-part geometries is deprecated and will be removed in Shapely 2.0. Check the length of the `geoms` property instead to get the  number of parts of a multi-part geometry.
  /home/runner/work/cartopy/cartopy/lib/cartopy/tests/test_polygon.py:352: ShapelyDeprecationWarning: __getitem__ for multi-part geometries is deprecated and will be removed in Shapely 2.0. Use the `geoms` property to access the constituent parts of a multi-part geometry.
  /home/runner/work/cartopy/cartopy/lib/cartopy/tests/test_polygon.py:360: ShapelyDeprecationWarning: __len__ for multi-part geometries is deprecated and will be removed in Shapely 2.0. Check the length of the `geoms` property instead to get the  number of parts of a multi-part geometry.
  /home/runner/work/cartopy/cartopy/lib/cartopy/tests/test_polygon.py:362: ShapelyDeprecationWarning: Iteration over multi-part geometries is deprecated and will be removed in Shapely 2.0. Use the `geoms` property to access the constituent parts of a multi-part geometry.
  /home/runner/work/cartopy/cartopy/lib/cartopy/tests/test_polygon.py:375: ShapelyDeprecationWarning: __len__ for multi-part geometries is deprecated and will be removed in Shapely 2.0. Check the length of the `geoms` property instead to get the  number of parts of a multi-part geometry.
  /home/runner/work/cartopy/cartopy/lib/cartopy/tests/test_polygon.py:377: ShapelyDeprecationWarning: __getitem__ for multi-part geometries is deprecated and will be removed in Shapely 2.0. Use the `geoms` property to access the constituent parts of a multi-part geometry.
  /home/runner/work/cartopy/cartopy/lib/cartopy/tests/test_polygon.py:393: ShapelyDeprecationWarning: __len__ for multi-part geometries is deprecated and will be removed in Shapely 2.0. Check the length of the `geoms` property instead to get the  number of parts of a multi-part geometry.
  /home/runner/work/cartopy/cartopy/lib/cartopy/tests/test_polygon.py:394: ShapelyDeprecationWarning: __getitem__ for multi-part geometries is deprecated and will be removed in Shapely 2.0. Use the `geoms` property to access the constituent parts of a multi-part geometry.
  /home/runner/work/cartopy/cartopy/lib/cartopy/tests/test_polygon.py:396: ShapelyDeprecationWarning: __getitem__ for multi-part geometries is deprecated and will be removed in Shapely 2.0. Use the `geoms` property to access the constituent parts of a multi-part geometry.
  /home/runner/work/cartopy/cartopy/lib/cartopy/tests/test_polygon.py:406: ShapelyDeprecationWarning: __len__ for multi-part geometries is deprecated and will be removed in Shapely 2.0. Check the length of the `geoms` property instead to get the  number of parts of a multi-part geometry.
  /home/runner/work/cartopy/cartopy/lib/cartopy/tests/test_polygon.py:408: ShapelyDeprecationWarning: Iteration over multi-part geometries is deprecated and will be removed in Shapely 2.0. Use the `geoms` property to access the constituent parts of a multi-part geometry.
  /home/runner/work/cartopy/cartopy/lib/cartopy/tests/test_polygon.py:427: ShapelyDeprecationWarning: __len__ for multi-part geometries is deprecated and will be removed in Shapely 2.0. Check the length of the `geoms` property instead to get the  number of parts of a multi-part geometry.
  /home/runner/work/cartopy/cartopy/lib/cartopy/tests/test_polygon.py:428: ShapelyDeprecationWarning: __getitem__ for multi-part geometries is deprecated and will be removed in Shapely 2.0. Use the `geoms` property to access the constituent parts of a multi-part geometry.
  /home/runner/work/cartopy/cartopy/lib/cartopy/tests/test_polygon.py:429: ShapelyDeprecationWarning: __getitem__ for multi-part geometries is deprecated and will be removed in Shapely 2.0. Use the `geoms` property to access the constituent parts of a multi-part geometry.
  /home/runner/work/cartopy/cartopy/lib/cartopy/tests/test_polygon.py:431: ShapelyDeprecationWarning: __getitem__ for multi-part geometries is deprecated and will be removed in Shapely 2.0. Use the `geoms` property to access the constituent parts of a multi-part geometry.
  /home/runner/work/cartopy/cartopy/lib/cartopy/tests/test_polygon.py:433: ShapelyDeprecationWarning: __getitem__ for multi-part geometries is deprecated and will be removed in Shapely 2.0. Use the `geoms` property to access the constituent parts of a multi-part geometry.
  /home/runner/work/cartopy/cartopy/lib/cartopy/tests/test_polygon.py:442: ShapelyDeprecationWarning: __len__ for multi-part geometries is deprecated and will be removed in Shapely 2.0. Check the length of the `geoms` property instead to get the  number of parts of a multi-part geometry.
  /home/runner/work/cartopy/cartopy/lib/cartopy/tests/test_polygon.py:443: ShapelyDeprecationWarning: __getitem__ for multi-part geometries is deprecated and will be removed in Shapely 2.0. Use the `geoms` property to access the constituent parts of a multi-part geometry.
  /home/runner/work/cartopy/cartopy/lib/cartopy/tests/test_polygon.py:445: ShapelyDeprecationWarning: __getitem__ for multi-part geometries is deprecated and will be removed in Shapely 2.0. Use the `geoms` property to access the constituent parts of a multi-part geometry.
  /home/runner/work/cartopy/cartopy/lib/cartopy/tests/test_polygon.py:457: ShapelyDeprecationWarning: __len__ for multi-part geometries is deprecated and will be removed in Shapely 2.0. Check the length of the `geoms` property instead to get the  number of parts of a multi-part geometry.
  /home/runner/work/cartopy/cartopy/lib/cartopy/tests/test_polygon.py:458: ShapelyDeprecationWarning: __getitem__ for multi-part geometries is deprecated and will be removed in Shapely 2.0. Use the `geoms` property to access the constituent parts of a multi-part geometry.
  /home/runner/work/cartopy/cartopy/lib/cartopy/tests/test_polygon.py:460: ShapelyDeprecationWarning: __getitem__ for multi-part geometries is deprecated and will be removed in Shapely 2.0. Use the `geoms` property to access the constituent parts of a multi-part geometry.
  /home/runner/work/cartopy/cartopy/lib/cartopy/tests/test_polygon.py:473: ShapelyDeprecationWarning: __len__ for multi-part geometries is deprecated and will be removed in Shapely 2.0. Check the length of the `geoms` property instead to get the  number of parts of a multi-part geometry.
  /home/runner/work/cartopy/cartopy/lib/cartopy/tests/test_polygon.py:474: ShapelyDeprecationWarning: __getitem__ for multi-part geometries is deprecated and will be removed in Shapely 2.0. Use the `geoms` property to access the constituent parts of a multi-part geometry.
  /home/runner/work/cartopy/cartopy/lib/cartopy/tests/test_polygon.py:476: ShapelyDeprecationWarning: __getitem__ for multi-part geometries is deprecated and will be removed in Shapely 2.0. Use the `geoms` property to access the constituent parts of a multi-part geometry.
  /home/runner/work/cartopy/cartopy/lib/cartopy/tests/test_polygon.py:491: ShapelyDeprecationWarning: Iteration over multi-part geometries is deprecated and will be removed in Shapely 2.0. Use the `geoms` property to access the constituent parts of a multi-part geometry.
  /home/runner/work/cartopy/cartopy/lib/cartopy/tests/test_polygon.py:491: ShapelyDeprecationWarning: __len__ for multi-part geometries is deprecated and will be removed in Shapely 2.0. Check the length of the `geoms` property instead to get the  number of parts of a multi-part geometry.
  /home/runner/work/cartopy/cartopy/lib/cartopy/tests/test_polygon.py:57: ShapelyDeprecationWarning: __len__ for multi-part geometries is deprecated and will be removed in Shapely 2.0. Check the length of the `geoms` property instead to get the  number of parts of a multi-part geometry.
  /home/runner/work/cartopy/cartopy/lib/cartopy/tests/test_polygon.py:75: ShapelyDeprecationWarning: __len__ for multi-part geometries is deprecated and will be removed in Shapely 2.0. Check the length of the `geoms` property instead to get the  number of parts of a multi-part geometry.
  /home/runner/work/cartopy/cartopy/lib/cartopy/tests/test_polygon.py:76: ShapelyDeprecationWarning: __getitem__ for multi-part geometries is deprecated and will be removed in Shapely 2.0. Use the `geoms` property to access the constituent parts of a multi-part geometry.
  /usr/share/miniconda/envs/test-environment/lib/python3.9/site-packages/numpy/lib/function_base.py:4817: ShapelyDeprecationWarning: The array interface is deprecated and will no longer work in Shapely 2.0. Convert the '.coords' to a numpy array instead.
  /usr/share/miniconda/envs/test-environment/lib/python3.9/site-packages/numpy/testing/_private/utils.py:1046: ShapelyDeprecationWarning: The array interface is deprecated and will no longer work in Shapely 2.0. Convert the '.coords' to a numpy array instead.
```
</details>


Discussion:

Resolving patch:
diff --git a/lib/cartopy/crs.py b/lib/cartopy/crs.py
--- a/lib/cartopy/crs.py
+++ b/lib/cartopy/crs.py
@@ -822,7 +822,7 @@ def _project_linear_ring(self, linear_ring, src_crs):
         threshold = max(np.abs(self.x_limits + self.y_limits)) * 1e-5
 
         # 2) Simplify the segments where appropriate.
-        if len(multi_line_string) > 1:
+        if len(multi_line_string.geoms) > 1:
             # Stitch together segments which are close to continuous.
             # This is important when:
             # 1) The first source point projects into the map and the
@@ -833,7 +833,7 @@ def _project_linear_ring(self, linear_ring, src_crs):
             # 2) The cut ends of segments are too close to reliably
             # place into an order along the boundary.
 
-            line_strings = list(multi_line_string)
+            line_strings = list(multi_line_string.geoms)
             any_modified = False
             i = 0
             if debug:
@@ -874,7 +874,7 @@ def _project_linear_ring(self, linear_ring, src_crs):
         # 3) Check for rings that have been created by the projection stage.
         rings = []
         line_strings = []
-        for line in multi_line_string:
+        for line in multi_line_string.geoms:
             if len(line.coords) > 3 and np.allclose(line.coords[0],
                                                     line.coords[-1],
                                                     atol=threshold):
@@ -941,7 +941,7 @@ def _project_polygon(self, polygon, src_crs):
             p_rings, p_mline = self._project_linear_ring(src_ring, src_crs)
             if p_rings:
                 rings.extend(p_rings)
-            if len(p_mline) > 0:
+            if len(p_mline.geoms) > 0:
                 multi_lines.append(p_mline)
 
         # Convert any lines to rings by attaching them to the boundary.
@@ -979,7 +979,7 @@ def boundary_distance(xy):
         # Squash all the LineStrings into a single list.
         line_strings = []
         for multi_line_string in multi_line_strings:
-            line_strings.extend(multi_line_string)
+            line_strings.extend(multi_line_string.geoms)
 
         # Record the positions of all the segment ends
         for i, line_string in enumerate(line_strings):
diff --git a/lib/cartopy/io/ogc_clients.py b/lib/cartopy/io/ogc_clients.py
--- a/lib/cartopy/io/ogc_clients.py
+++ b/lib/cartopy/io/ogc_clients.py
@@ -162,7 +162,7 @@ def _target_extents(extent, requested_projection, available_projection):
 
     # Return the polygons' rectangular bounds as extent tuples.
     target_extents = []
-    for poly in polys:
+    for poly in polys.geoms:
         min_x, min_y, max_x, max_y = poly.bounds
         if fudge_mode:
             # If we shrunk the request area before, then here we
diff --git a/lib/cartopy/mpl/gridliner.py b/lib/cartopy/mpl/gridliner.py
--- a/lib/cartopy/mpl/gridliner.py
+++ b/lib/cartopy/mpl/gridliner.py
@@ -839,15 +839,20 @@ def update_artist(artist, renderer):
                                                sgeom.MultiLineString)):
                     if isinstance(intersection, sgeom.LineString):
                         intersection = [intersection]
-                    elif len(intersection) > 4:
+                    elif len(intersection.geoms) > 4:
                         # Gridline and map boundary are parallel and they
                         # intersect themselves too much it results in a
                         # multiline string that must be converted to a single
                         # linestring. This is an empirical workaround for a
                         # problem that can probably be solved in a cleaner way.
-                        xy = np.append(intersection[0], intersection[-1],
-                                       axis=0)
+                        xy = np.append(
+                            intersection.geoms[0].coords,
+                            intersection.geoms[-1].coords,
+                            axis=0,
+                        )
                         intersection = [sgeom.LineString(xy)]
+                    else:
+                        intersection = intersection.geoms
                     tails = []
                     heads = []
                     for inter in intersection:


Test patch:
diff --git a/lib/cartopy/tests/crs/test_albers_equal_area.py b/lib/cartopy/tests/crs/test_albers_equal_area.py
--- a/lib/cartopy/tests/crs/test_albers_equal_area.py
+++ b/lib/cartopy/tests/crs/test_albers_equal_area.py
@@ -61,8 +61,11 @@ def test_central_longitude(self, lon):
                       'x_0=0.0', 'y_0=0.0', 'lat_1=20.0', 'lat_2=50.0'}
         check_proj_params('aea', aea_offset, other_args)
 
-        assert_array_almost_equal(aea_offset.boundary, aea.boundary,
-                                  decimal=0)
+        assert_array_almost_equal(
+            aea_offset.boundary.coords,
+            aea.boundary.coords,
+            decimal=0,
+        )
 
     def test_standard_parallels(self):
         aea = ccrs.AlbersEqualArea(standard_parallels=(13, 37))
diff --git a/lib/cartopy/tests/crs/test_equidistant_conic.py b/lib/cartopy/tests/crs/test_equidistant_conic.py
--- a/lib/cartopy/tests/crs/test_equidistant_conic.py
+++ b/lib/cartopy/tests/crs/test_equidistant_conic.py
@@ -61,8 +61,11 @@ def test_central_longitude(self, lon):
                       'x_0=0.0', 'y_0=0.0', 'lat_1=20.0', 'lat_2=50.0'}
         check_proj_params('eqdc', eqdc_offset, other_args)
 
-        assert_array_almost_equal(eqdc_offset.boundary, eqdc.boundary,
-                                  decimal=0)
+        assert_array_almost_equal(
+            eqdc_offset.boundary.coords,
+            eqdc.boundary.coords,
+            decimal=0,
+        )
 
     def test_standard_parallels(self):
         eqdc = ccrs.EquidistantConic(standard_parallels=(13, 37))
diff --git a/lib/cartopy/tests/test_crs.py b/lib/cartopy/tests/test_crs.py
--- a/lib/cartopy/tests/test_crs.py
+++ b/lib/cartopy/tests/test_crs.py
@@ -207,9 +207,9 @@ def test_project_point(self):
 
         result = pc_rotated.project_geometry(multi_point, pc)
         assert isinstance(result, sgeom.MultiPoint)
-        assert len(result) == 2
-        assert_arr_almost_eq(result[0].xy, [[-180.], [45.]])
-        assert_arr_almost_eq(result[1].xy, [[0], [45.]])
+        assert len(result.geoms) == 2
+        assert_arr_almost_eq(result.geoms[0].xy, [[-180.], [45.]])
+        assert_arr_almost_eq(result.geoms[1].xy, [[0], [45.]])
 
     def test_utm(self):
         utm30n = ccrs.UTM(30)
diff --git a/lib/cartopy/tests/test_line_string.py b/lib/cartopy/tests/test_line_string.py
--- a/lib/cartopy/tests/test_line_string.py
+++ b/lib/cartopy/tests/test_line_string.py
@@ -33,7 +33,7 @@ def test_out_of_bounds(self):
                 expected = 0
             else:
                 expected = 1
-            assert len(multi_line_string) == expected, \
+            assert len(multi_line_string.geoms) == expected, \
                 f'Unexpected line when working from {start} to {end}'
 
     def test_simple_fragment_count(self):
@@ -51,7 +51,7 @@ def test_simple_fragment_count(self):
             multi_line_string = projection.project_geometry(line_string)
             # from cartopy.tests.mpl import show
             # show(projection, multi_line_string)
-            assert len(multi_line_string) == pieces
+            assert len(multi_line_string.geoms) == pieces
 
     def test_split(self):
         projection = ccrs.Robinson(170.5)
@@ -59,7 +59,7 @@ def test_split(self):
         multi_line_string = projection.project_geometry(line_string)
         # from cartopy.tests.mpl import show
         # show(projection, multi_line_string)
-        assert len(multi_line_string) == 2
+        assert len(multi_line_string.geoms) == 2
 
     def test_out_of_domain_efficiency(self):
         # Check we're efficiently dealing with lines that project
@@ -103,80 +103,80 @@ def test_repeated_point(self):
         projection = FakeProjection()
         line_string = sgeom.LineString([(10, 0), (10, 0)])
         multi_line_string = projection.project_geometry(line_string)
-        assert len(multi_line_string) == 1
-        assert len(multi_line_string[0].coords) == 2
+        assert len(multi_line_string.geoms) == 1
+        assert len(multi_line_string.geoms[0].coords) == 2
 
     def test_interior_repeated_point(self):
         projection = FakeProjection()
         line_string = sgeom.LineString([(0, 0), (10, 0), (10, 0), (20, 0)])
         multi_line_string = projection.project_geometry(line_string)
-        assert len(multi_line_string) == 1
-        assert len(multi_line_string[0].coords) == 4
+        assert len(multi_line_string.geoms) == 1
+        assert len(multi_line_string.geoms[0].coords) == 4
 
     def test_circular_repeated_point(self):
         projection = FakeProjection()
         line_string = sgeom.LineString([(0, 0), (360, 0)])
         multi_line_string = projection.project_geometry(line_string)
-        assert len(multi_line_string) == 1
-        assert len(multi_line_string[0].coords) == 2
+        assert len(multi_line_string.geoms) == 1
+        assert len(multi_line_string.geoms[0].coords) == 2
 
     def test_short(self):
         projection = FakeProjection()
         line_string = sgeom.LineString([(0, 0), (1e-12, 0)])
         multi_line_string = projection.project_geometry(line_string)
-        assert len(multi_line_string) == 1
-        assert len(multi_line_string[0].coords) == 2
+        assert len(multi_line_string.geoms) == 1
+        assert len(multi_line_string.geoms[0].coords) == 2
 
     def test_empty(self):
         projection = FakeProjection(right_offset=10)
         line_string = sgeom.LineString([(175, 0), (175, 10)])
         multi_line_string = projection.project_geometry(line_string)
-        assert len(multi_line_string) == 0
+        assert len(multi_line_string.geoms) == 0
 
     def test_simple_run_in(self):
         projection = FakeProjection(right_offset=10)
         line_string = sgeom.LineString([(160, 0), (175, 0)])
         multi_line_string = projection.project_geometry(line_string)
-        assert len(multi_line_string) == 1
-        assert len(multi_line_string[0].coords) == 2
+        assert len(multi_line_string.geoms) == 1
+        assert len(multi_line_string.geoms[0].coords) == 2
 
     def test_simple_wrap(self):
         projection = FakeProjection()
         line_string = sgeom.LineString([(160, 0), (-160, 0)])
         multi_line_string = projection.project_geometry(line_string)
-        assert len(multi_line_string) == 2
-        assert len(multi_line_string[0].coords) == 2
-        assert len(multi_line_string[1].coords) == 2
+        assert len(multi_line_string.geoms) == 2
+        assert len(multi_line_string.geoms[0].coords) == 2
+        assert len(multi_line_string.geoms[1].coords) == 2
 
     def test_simple_run_out(self):
         projection = FakeProjection(left_offset=10)
         line_string = sgeom.LineString([(-175, 0), (-160, 0)])
         multi_line_string = projection.project_geometry(line_string)
-        assert len(multi_line_string) == 1
-        assert len(multi_line_string[0].coords) == 2
+        assert len(multi_line_string.geoms) == 1
+        assert len(multi_line_string.geoms[0].coords) == 2
 
     def test_point_on_boundary(self):
         projection = FakeProjection()
         line_string = sgeom.LineString([(180, 0), (-160, 0)])
         multi_line_string = projection.project_geometry(line_string)
-        assert len(multi_line_string) == 1
-        assert len(multi_line_string[0].coords) == 2
+        assert len(multi_line_string.geoms) == 1
+        assert len(multi_line_string.geoms[0].coords) == 2
 
         # Add a small offset to the left-hand boundary to make things
         # even more pathological.
         projection = FakeProjection(left_offset=5)
         line_string = sgeom.LineString([(180, 0), (-160, 0)])
         multi_line_string = projection.project_geometry(line_string)
-        assert len(multi_line_string) == 1
-        assert len(multi_line_string[0].coords) == 2
+        assert len(multi_line_string.geoms) == 1
+        assert len(multi_line_string.geoms[0].coords) == 2
 
     def test_nan_start(self):
         projection = ccrs.TransverseMercator(central_longitude=-90,
                                              approx=False)
         line_string = sgeom.LineString([(10, 50), (-10, 30)])
         multi_line_string = projection.project_geometry(line_string)
-        assert len(multi_line_string) == 1
-        for line_string in multi_line_string:
+        assert len(multi_line_string.geoms) == 1
+        for line_string in multi_line_string.geoms:
             for coord in line_string.coords:
                 assert not any(np.isnan(coord)), \
                     'Unexpected NaN in projected coords.'
@@ -188,8 +188,8 @@ def test_nan_end(self):
         multi_line_string = projection.project_geometry(line_string)
         # from cartopy.tests.mpl import show
         # show(projection, multi_line_string)
-        assert len(multi_line_string) == 1
-        for line_string in multi_line_string:
+        assert len(multi_line_string.geoms) == 1
+        for line_string in multi_line_string.geoms:
             for coord in line_string.coords:
                 assert not any(np.isnan(coord)), \
                     'Unexpected NaN in projected coords.'
@@ -203,7 +203,7 @@ def test_misc(self):
         multi_line_string = projection.project_geometry(line_string)
         # from cartopy.tests.mpl import show
         # show(projection, multi_line_string)
-        for line_string in multi_line_string:
+        for line_string in multi_line_string.geoms:
             for coord in line_string.coords:
                 assert not any(np.isnan(coord)), \
                     'Unexpected NaN in projected coords.'
@@ -213,8 +213,8 @@ def test_something(self):
                                       pole_latitude=37.5)
         line_string = sgeom.LineString([(0, 0), (1e-14, 0)])
         multi_line_string = projection.project_geometry(line_string)
-        assert len(multi_line_string) == 1
-        assert len(multi_line_string[0].coords) == 2
+        assert len(multi_line_string.geoms) == 1
+        assert len(multi_line_string.geoms[0].coords) == 2
 
     def test_global_boundary(self):
         linear_ring = sgeom.LineString([(-180, -180), (-180, 180),
@@ -222,11 +222,11 @@ def test_global_boundary(self):
         pc = ccrs.PlateCarree()
         merc = ccrs.Mercator()
         multi_line_string = pc.project_geometry(linear_ring, merc)
-        assert len(multi_line_string) > 0
+        assert len(multi_line_string.geoms) > 0
 
         # check the identity transform
         multi_line_string = merc.project_geometry(linear_ring, merc)
-        assert len(multi_line_string) > 0
+        assert len(multi_line_string.geoms) > 0
 
 
 class TestSymmetry:
@@ -244,9 +244,9 @@ def test_curve(self):
 
         # Make sure that they generated the same points.
         # (Although obviously they will be in the opposite order!)
-        assert len(multi_line_string) == 1
-        assert len(multi_line_string2) == 1
-        coords = multi_line_string[0].coords
-        coords2 = multi_line_string2[0].coords
+        assert len(multi_line_string.geoms) == 1
+        assert len(multi_line_string2.geoms) == 1
+        coords = multi_line_string.geoms[0].coords
+        coords2 = multi_line_string2.geoms[0].coords
         np.testing.assert_allclose(coords, coords2[::-1],
                                    err_msg='Asymmetric curve generation')
diff --git a/lib/cartopy/tests/test_linear_ring.py b/lib/cartopy/tests/test_linear_ring.py
--- a/lib/cartopy/tests/test_linear_ring.py
+++ b/lib/cartopy/tests/test_linear_ring.py
@@ -20,7 +20,7 @@ def test_cuts(self):
         rings, multi_line_string = projection.project_geometry(linear_ring)
 
         # The original ring should have been split into multiple pieces.
-        assert len(multi_line_string) > 1
+        assert len(multi_line_string.geoms) > 1
         assert not rings
 
         def assert_intersection_with_boundary(segment_coords):
@@ -37,7 +37,7 @@ def assert_intersection_with_boundary(segment_coords):
         # segment that crosses the boundary when extended to double length.
         # (This is important when considering polygon rings which need to be
         # attached to the boundary.)
-        for line_string in multi_line_string:
+        for line_string in multi_line_string.geoms:
             coords = list(line_string.coords)
             assert len(coords) >= 2
             assert_intersection_with_boundary(coords[1::-1])
@@ -68,7 +68,7 @@ def test_out_of_bounds(self):
                 assert rings
                 assert not mlinestr
             else:
-                assert len(mlinestr) == expected_n_lines
+                assert len(mlinestr.geoms) == expected_n_lines
                 if expected_n_lines == 0:
                     assert mlinestr.is_empty
 
@@ -86,7 +86,7 @@ def test_small(self):
         rings, multi_line_string = projection.project_geometry(linear_ring)
         # There should be one, and only one, returned ring.
         assert isinstance(multi_line_string, sgeom.MultiLineString)
-        assert len(multi_line_string) == 0
+        assert len(multi_line_string.geoms) == 0
         assert len(rings) == 1
 
         # from cartopy.tests.mpl import show
@@ -135,13 +135,13 @@ def test_stitch(self):
 
         linear_ring = sgeom.LinearRing(coords)
         rings, mlinestr = target_proj.project_geometry(linear_ring, src_proj)
-        assert len(mlinestr) == 1
+        assert len(mlinestr.geoms) == 1
         assert len(rings) == 0
 
         # Check the stitch works in either direction.
         linear_ring = sgeom.LinearRing(coords[::-1])
         rings, mlinestr = target_proj.project_geometry(linear_ring, src_proj)
-        assert len(mlinestr) == 1
+        assert len(mlinestr.geoms) == 1
         assert len(rings) == 0
 
     def test_at_boundary(self):
@@ -170,7 +170,7 @@ def test_at_boundary(self):
         rings, mlinestr = tcrs._project_linear_ring(tring, scrs)
 
         # Number of linearstrings
-        assert len(mlinestr) == 4
+        assert len(mlinestr.geoms) == 4
         assert not rings
 
         # Test area of smallest Polygon that contains all the points in the
diff --git a/lib/cartopy/tests/test_polygon.py b/lib/cartopy/tests/test_polygon.py
--- a/lib/cartopy/tests/test_polygon.py
+++ b/lib/cartopy/tests/test_polygon.py
@@ -21,7 +21,7 @@ def test_no_polygon_boundary_reversal(self):
         polygon = sgeom.Polygon([(-10, 30), (10, 60), (10, 50)])
         projection = ccrs.Robinson(170.5)
         multi_polygon = projection.project_geometry(polygon)
-        for polygon in multi_polygon:
+        for polygon in multi_polygon.geoms:
             assert polygon.is_valid
 
     def test_polygon_boundary_attachment(self):
@@ -54,7 +54,7 @@ def test_out_of_bounds(self):
         for coords, expected_polys in polys:
             polygon = sgeom.Polygon(coords)
             multi_polygon = projection.project_geometry(polygon)
-            assert len(multi_polygon) == expected_polys
+            assert len(multi_polygon.geoms) == expected_polys
 
 
 class TestMisc:
@@ -72,8 +72,8 @@ def test_small(self):
             (-179.9173693847652942, -16.5017831356493616),
         ])
         multi_polygon = projection.project_geometry(polygon)
-        assert len(multi_polygon) == 1
-        assert len(multi_polygon[0].exterior.coords) == 4
+        assert len(multi_polygon.geoms) == 1
+        assert len(multi_polygon.geoms[0].exterior.coords) == 4
 
     def test_former_infloop_case(self):
         # test a polygon which used to get stuck in an infinite loop
@@ -174,8 +174,8 @@ def test_3pt_poly(self):
                                  (200000, -1000)])
         multi_polygon = projection.project_geometry(polygon,
                                                     ccrs.OSGB(approx=True))
-        assert len(multi_polygon) == 1
-        assert len(multi_polygon[0].exterior.coords) == 4
+        assert len(multi_polygon.geoms) == 1
+        assert len(multi_polygon.geoms[0].exterior.coords) == 4
 
     def test_self_intersecting_1(self):
         # Geometry comes from a matplotlib contourf (see #537)
@@ -298,14 +298,14 @@ def setup_class(self):
 
     def test_split(self):
         # Start simple ... there should be two projected polygons.
-        assert len(self.multi_polygon) == 2
+        assert len(self.multi_polygon.geoms) == 2
 
     def test_repeats(self):
         # Make sure we don't have repeated points at the boundary, because
         # they mess up the linear extrapolation to the boundary.
 
         # Make sure there aren't any repeated points.
-        xy = np.array(self.multi_polygon[0].exterior.coords)
+        xy = np.array(self.multi_polygon.geoms[0].exterior.coords)
         same = (xy[1:] == xy[:-1]).all(axis=1)
         assert not any(same), 'Repeated points in projected geometry.'
 
@@ -315,7 +315,7 @@ def test_symmetry(self):
         # from the boundary.
 
         # Identify all the contiguous sets of non-boundary points.
-        xy = np.array(self.multi_polygon[0].exterior.coords)
+        xy = np.array(self.multi_polygon.geoms[0].exterior.coords)
         boundary = np.logical_or(xy[:, 1] == 90, xy[:, 1] == -90)
         regions = (boundary[1:] != boundary[:-1]).cumsum()
         regions = np.insert(regions, 0, 0)
@@ -347,9 +347,9 @@ def test_plate_carree_no_wrap(self):
         poly = sgeom.box(0, 0, 10, 10)
         multi_polygon = proj.project_geometry(poly, proj)
         # Check the structure
-        assert len(multi_polygon) == 1
+        assert len(multi_polygon.geoms) == 1
         # Check the rough shape
-        polygon = multi_polygon[0]
+        polygon = multi_polygon.geoms[0]
         self._assert_bounds(polygon.bounds, 0, 0, 10, 10)
 
     def test_plate_carree_partial_wrap(self):
@@ -357,9 +357,9 @@ def test_plate_carree_partial_wrap(self):
         poly = sgeom.box(170, 0, 190, 10)
         multi_polygon = proj.project_geometry(poly, proj)
         # Check the structure
-        assert len(multi_polygon) == 2
+        assert len(multi_polygon.geoms) == 2
         # Check the rough shape
-        poly1, poly2 = multi_polygon
+        poly1, poly2 = multi_polygon.geoms
         # The order of these polygons is not guaranteed, so figure out
         # which is appropriate
         if 170.0 not in poly1.bounds:
@@ -372,9 +372,9 @@ def test_plate_carree_wrap(self):
         poly = sgeom.box(200, 0, 220, 10)
         multi_polygon = proj.project_geometry(poly, proj)
         # Check the structure
-        assert len(multi_polygon) == 1
+        assert len(multi_polygon.geoms) == 1
         # Check the rough shape
-        polygon = multi_polygon[0]
+        polygon = multi_polygon.geoms[0]
         self._assert_bounds(polygon.bounds, -160, 0, -140, 10)
 
 
@@ -390,10 +390,10 @@ def test_simple(self):
                              [ring(-20, -20, 20, 20, False)])
         multi_polygon = proj.project_geometry(poly)
         # Check the structure
-        assert len(multi_polygon) == 1
-        assert len(multi_polygon[0].interiors) == 1
+        assert len(multi_polygon.geoms) == 1
+        assert len(multi_polygon.geoms[0].interiors) == 1
         # Check the rough shape
-        polygon = multi_polygon[0]
+        polygon = multi_polygon.geoms[0]
         self._assert_bounds(polygon.bounds, -40, -47, 40, 47)
         self._assert_bounds(polygon.interiors[0].bounds, -20, -21, 20, 21)
 
@@ -403,9 +403,9 @@ def test_wrapped_poly_simple_hole(self):
                              [ring(-20, -20, 20, 20, False)])
         multi_polygon = proj.project_geometry(poly)
         # Check the structure
-        assert len(multi_polygon) == 2
+        assert len(multi_polygon.geoms) == 2
 
-        poly1, poly2 = multi_polygon
+        poly1, poly2 = multi_polygon.geoms
         # The order of these polygons is not guaranteed, so figure out
         # which is appropriate
         if not len(poly1.interiors) == 1:
@@ -424,13 +424,13 @@ def test_wrapped_poly_wrapped_hole(self):
                              [ring(-20, -20, 20, 20, False)])
         multi_polygon = proj.project_geometry(poly)
         # Check the structure
-        assert len(multi_polygon) == 2
-        assert len(multi_polygon[0].interiors) == 0
-        assert len(multi_polygon[1].interiors) == 0
+        assert len(multi_polygon.geoms) == 2
+        assert len(multi_polygon.geoms[0].interiors) == 0
+        assert len(multi_polygon.geoms[1].interiors) == 0
         # Check the rough shape
-        polygon = multi_polygon[0]
+        polygon = multi_polygon.geoms[0]
         self._assert_bounds(polygon.bounds, 140, -47, 180, 47)
-        polygon = multi_polygon[1]
+        polygon = multi_polygon.geoms[1]
         self._assert_bounds(polygon.bounds, -180, -47, -140, 47)
 
     def test_inverted_poly_simple_hole(self):
@@ -439,10 +439,10 @@ def test_inverted_poly_simple_hole(self):
                              [[(0, -30), (90, -30), (180, -30), (270, -30)]])
         multi_polygon = proj.project_geometry(poly)
         # Check the structure
-        assert len(multi_polygon) == 1
-        assert len(multi_polygon[0].interiors) == 1
+        assert len(multi_polygon.geoms) == 1
+        assert len(multi_polygon.geoms[0].interiors) == 1
         # Check the rough shape
-        polygon = multi_polygon[0]
+        polygon = multi_polygon.geoms[0]
         self._assert_bounds(polygon.bounds, -2.4e7, -2.4e7, 2.4e7, 2.4e7, 1e6)
         self._assert_bounds(polygon.interiors[0].bounds,
                             - 1.2e7, -1.2e7, 1.2e7, 1.2e7, 1e6)
@@ -454,10 +454,10 @@ def test_inverted_poly_clipped_hole(self):
                                (45, -60), (135, -60)]])
         multi_polygon = proj.project_geometry(poly)
         # Check the structure
-        assert len(multi_polygon) == 1
-        assert len(multi_polygon[0].interiors) == 1
+        assert len(multi_polygon.geoms) == 1
+        assert len(multi_polygon.geoms[0].interiors) == 1
         # Check the rough shape
-        polygon = multi_polygon[0]
+        polygon = multi_polygon.geoms[0]
         self._assert_bounds(polygon.bounds, -5.0e7, -5.0e7, 5.0e7, 5.0e7, 1e6)
         self._assert_bounds(polygon.interiors[0].bounds,
                             - 1.2e7, -1.2e7, 1.2e7, 1.2e7, 1e6)
@@ -470,10 +470,10 @@ def test_inverted_poly_removed_hole(self):
                                (45, -75), (135, -75)]])
         multi_polygon = proj.project_geometry(poly)
         # Check the structure
-        assert len(multi_polygon) == 1
-        assert len(multi_polygon[0].interiors) == 1
+        assert len(multi_polygon.geoms) == 1
+        assert len(multi_polygon.geoms[0].interiors) == 1
         # Check the rough shape
-        polygon = multi_polygon[0]
+        polygon = multi_polygon.geoms[0]
         self._assert_bounds(polygon.bounds, -5.0e7, -5.0e7, 5.0e7, 5.0e7, 1e6)
         self._assert_bounds(polygon.interiors[0].bounds,
                             - 1.2e7, -1.2e7, 1.2e7, 1.2e7, 1e6)
@@ -488,4 +488,4 @@ def test_multiple_interiors(self):
         target = ccrs.PlateCarree()
         source = ccrs.Geodetic()
 
-        assert len(list(target.project_geometry(poly, source))) == 1
+        assert len(list(target.project_geometry(poly, source).geoms)) == 1