Repository: SciTools/cartopy

Issue:
AttributeError: 'GeoAxesSubplot' object has no attribute '_hold'
### Description
<!-- Please provide a general introduction to the issue/proposal. -->
Hello, when running Travis on our package https://travis-ci.org/ARM-DOE/pyart/jobs/432631010#L1645-L1675. I encountered the error in the traceback below.

Looking into it more, it seems that in matplotlib 3.0.0, axes attribute hold was removed. 
https://matplotlib.org/api/api_changes.html#removals

In geoaxes.py, hold is used. Matplotlib 3.0.0.
https://github.com/SciTools/cartopy/blob/master/lib/cartopy/mpl/geoaxes.py#L1450-L1465
#### Code
https://github.com/SciTools/cartopy/blob/master/lib/cartopy/mpl/geoaxes.py#L1450-L1465

#### Traceback 
```
./../../miniconda3/envs/testenv/lib/python3.6/site-packages/cartopy/mpl/geoaxes.py:1451: in pcolormesh
    result = self._pcolormesh_patched(*args, **kwargs)

def _pcolormesh_patched(self, *args, **kwargs):
        """
            A temporary, modified duplicate of
            :func:`~matplotlib.pyplot.pcolormesh'.
    
            This function contains a workaround for a Matplotlib issue
            and will be removed once the issue has been resolved.
            https://github.com/matplotlib/matplotlib/pull/1314
    
            """
        import warnings
        import matplotlib.colors as mcolors
        import matplotlib.collections as mcoll
    
>       if not self._hold:
E       AttributeError: 'GeoAxesSubplot' object has no attribute '_hold'
```

<details>
 <summary>Full environment definition</summary>

<!-- fill in the following information as appropriate -->

### Operating system
Ubuntu 14.04.5 LTS

### Cartopy version
```
cartopy=0.16.0
```
### conda list

```
python=3.6.6
matplotlib=3.0.0
numpy=1.15.1
```

</details>

Remove pcolormesh patched?
This is what the docstring for `cartopy.mpl.geoaxes.GeoAxes._pcolormesh_patched` says:

```
A temporary, modified duplicate of
:func:`~matplotlib.pyplot.pcolormesh'.

This function contains a workaround for a Matplotlib issue
and will be removed once the issue has been resolved.
https://github.com/matplotlib/matplotlib/pull/1314
```

That link says that the PR was merged 5 years ago.  Surely we can take this out now?


Discussion:
So, I see the function says:

> This function contains a workaround for a Matplotlib issue
            and will be removed once the issue has been resolved.
            https://github.com/matplotlib/matplotlib/pull/1314

This issue was apparently fixed in matplotlib 1.2.x...so considering we only support matplotlib >=1.5, should we just nuke this function and be done?

It would seem this should probably push us to get 0.17 out the door ASAP with whatever we have done.

@zssherman Can you try monkey patching for me and see if it fixes PyART?
```python
from matplotlib.axes import Axes
from cartopy.mpl.geoaxes import GeoAxes
GeoAxes._pcolormesh_patched = Axes.pcolormesh
```

To be clear, I don't recommend this as anything you guys ship, but want to see if that's enough to fix it.
@dopplershift Sounds good! I will do the change and see if it fixes it. Thanks for the suggestion! And yeah I'll take your recommendation and not ship that.
I also think matplotlib will put `_hold` back for us (as a do-nothing bit of code) in 3.0.1.
@dopplershift Ah gotcha. And the monkey patch seems to work for radarmapdisplay_cartopy. I will submit a pull request to pyart for the mean time as a temporary fix.
That docstring is outdated; other things are done in `pcolormesh` that are not workarounds.
Unfortunately it has moved on since then. I don't think we will ever be able to reconcile the two...

See also: https://github.com/SciTools/cartopy/blob/master/lib/cartopy/mpl/geoaxes.py#L1462-L1480

Perhaps we should just remove the comment.

Resolving patch:
diff --git a/lib/cartopy/mpl/geoaxes.py b/lib/cartopy/mpl/geoaxes.py
--- a/lib/cartopy/mpl/geoaxes.py
+++ b/lib/cartopy/mpl/geoaxes.py
@@ -1448,19 +1448,19 @@ def pcolormesh(self, *args, **kwargs):
 
     def _pcolormesh_patched(self, *args, **kwargs):
         """
-        A temporary, modified duplicate of
-        :func:`~matplotlib.pyplot.pcolormesh'.
+        A modified duplicate of :func:`~matplotlib.pyplot.pcolormesh'.
 
-        This function contains a workaround for a Matplotlib issue
-        and will be removed once the issue has been resolved.
-        https://github.com/matplotlib/matplotlib/pull/1314
+        This function contains patches for Cartopy-specific behaviour, such as
+        using the transform for limit checks, applying longitude wrapping, etc.
+        See PATCH comments below.
 
         """
         import warnings
         import matplotlib.colors as mcolors
         import matplotlib.collections as mcoll
 
-        if not self._hold:
+        # Remove this check when only MPL >= 3.0 is supported.
+        if not getattr(self, '_hold', True):
             self.cla()
 
         alpha = kwargs.pop('alpha', None)


Test patch:
diff --git a/lib/cartopy/tests/mpl/baseline_images/mpl/test_mpl_integration/global_contour_wrap.png b/lib/cartopy/tests/mpl/baseline_images/mpl/test_mpl_integration/global_contour_wrap.png
Binary files a/lib/cartopy/tests/mpl/baseline_images/mpl/test_mpl_integration/global_contour_wrap.png and b/lib/cartopy/tests/mpl/baseline_images/mpl/test_mpl_integration/global_contour_wrap.png differ
diff --git a/lib/cartopy/tests/mpl/baseline_images/mpl/test_mpl_integration/global_contour_wrap_mpl_pre_3.0.0.png b/lib/cartopy/tests/mpl/baseline_images/mpl/test_mpl_integration/global_contour_wrap_mpl_pre_3.0.0.png
new file mode 100644
Binary files /dev/null and b/lib/cartopy/tests/mpl/baseline_images/mpl/test_mpl_integration/global_contour_wrap_mpl_pre_3.0.0.png differ
diff --git a/lib/cartopy/tests/mpl/baseline_images/mpl/test_mpl_integration/streamplot_mpl_2.png b/lib/cartopy/tests/mpl/baseline_images/mpl/test_mpl_integration/streamplot_mpl_2.0.0.png
similarity index 100%
rename from lib/cartopy/tests/mpl/baseline_images/mpl/test_mpl_integration/streamplot_mpl_2.png
rename to lib/cartopy/tests/mpl/baseline_images/mpl/test_mpl_integration/streamplot_mpl_2.0.0.png
diff --git a/lib/cartopy/tests/mpl/baseline_images/mpl/test_mpl_integration/streamplot.png b/lib/cartopy/tests/mpl/baseline_images/mpl/test_mpl_integration/streamplot_mpl_2.1.0.png
similarity index 100%
rename from lib/cartopy/tests/mpl/baseline_images/mpl/test_mpl_integration/streamplot.png
rename to lib/cartopy/tests/mpl/baseline_images/mpl/test_mpl_integration/streamplot_mpl_2.1.0.png
diff --git a/lib/cartopy/tests/mpl/baseline_images/mpl/test_mpl_integration/streamplot_mpl_3.0.0.png b/lib/cartopy/tests/mpl/baseline_images/mpl/test_mpl_integration/streamplot_mpl_3.0.0.png
new file mode 100644
Binary files /dev/null and b/lib/cartopy/tests/mpl/baseline_images/mpl/test_mpl_integration/streamplot_mpl_3.0.0.png differ
diff --git a/lib/cartopy/tests/mpl/test_mpl_integration.py b/lib/cartopy/tests/mpl/test_mpl_integration.py
--- a/lib/cartopy/tests/mpl/test_mpl_integration.py
+++ b/lib/cartopy/tests/mpl/test_mpl_integration.py
@@ -32,16 +32,26 @@
 
 
 _ROB_TOL = 0.5 if ccrs.PROJ4_VERSION < (4, 9) else 0.111
-if MPL_VERSION >= '2.1.0':
-    _STREAMPLOT_IMAGE = 'streamplot'
-elif MPL_VERSION >= '2':
-    _STREAMPLOT_IMAGE = 'streamplot_mpl_2'
+_CONTOUR_STYLE = _STREAMPLOT_STYLE = 'classic'
+if MPL_VERSION >= '3.0.0':
+    _CONTOUR_IMAGE = 'global_contour_wrap'
+    _CONTOUR_STYLE = 'mpl20'
+    _STREAMPLOT_IMAGE = 'streamplot_mpl_3.0.0'
+    # Should have been the case for anything but _1.4.3, but we don't want to
+    # regenerate those images again.
+    _STREAMPLOT_STYLE = 'mpl20'
 else:
-    _STREAMPLOT_IMAGE = 'streamplot_mpl_1.4.3'
+    _CONTOUR_IMAGE = 'global_contour_wrap_mpl_pre_3.0.0'
+    if MPL_VERSION >= '2.1.0':
+        _STREAMPLOT_IMAGE = 'streamplot_mpl_2.1.0'
+    elif MPL_VERSION >= '2':
+        _STREAMPLOT_IMAGE = 'streamplot_mpl_2.0.0'
+    else:
+        _STREAMPLOT_IMAGE = 'streamplot_mpl_1.4.3'
 
 
 @pytest.mark.natural_earth
-@ImageTesting(['global_contour_wrap'])
+@ImageTesting([_CONTOUR_IMAGE], style=_CONTOUR_STYLE)
 def test_global_contour_wrap_new_transform():
     ax = plt.axes(projection=ccrs.PlateCarree())
     ax.coastlines()
@@ -51,7 +61,7 @@ def test_global_contour_wrap_new_transform():
 
 
 @pytest.mark.natural_earth
-@ImageTesting(['global_contour_wrap'])
+@ImageTesting([_CONTOUR_IMAGE], style=_CONTOUR_STYLE)
 def test_global_contour_wrap_no_transform():
     ax = plt.axes(projection=ccrs.PlateCarree())
     ax.coastlines()
@@ -601,7 +611,7 @@ def test_barbs_1d_transformed():
 
 
 @pytest.mark.natural_earth
-@ImageTesting([_STREAMPLOT_IMAGE])
+@ImageTesting([_STREAMPLOT_IMAGE], style=_STREAMPLOT_STYLE)
 def test_streamplot():
     x = np.arange(-60, 42.5, 2.5)
     y = np.arange(30, 72.5, 2.5)