prompt: We are currently solving the following issue within our repository. Here is the issue text:
  --- BEGIN ISSUE ---
  SlippyImageArtist cannot be composited
  For example, take the WMTS example and add a second layer. Then attempt to save as a PDF.
  
  ``` python
  import cartopy.crs as ccrs
  import matplotlib.pyplot as plt
  
  url = 'http://map1c.vis.earthdata.nasa.gov/wmts-geo/wmts.cgi'
  layer1 = 'VIIRS_CityLights_2012'
  layer2 = 'ASTER_GDEM_Color_Index'
  
  ax = plt.axes(projection=ccrs.PlateCarree())
  ax.add_wmts(url, layer1)
  ax.add_wmts(url, layer2)
  ax.set_extent((-15, 25, 35, 60))
  
  plt.title('Suomi NPP Earth at night April/October 2012')
  plt.savefig('test.pdf')
  plt.show()
  ```
  
  which results in:
  
  ``` python
  Traceback (most recent call last):
    File "wmts.py", line 33, in main
      plt.savefig('test.pdf')
    File "/usr/lib64/python2.7/site-packages/matplotlib/pyplot.py", line 577, in savefig
      res = fig.savefig(*args, **kwargs)
    File "/usr/lib64/python2.7/site-packages/matplotlib/figure.py", line 1476, in savefig
      self.canvas.print_figure(*args, **kwargs)
    File "/usr/lib64/python2.7/site-packages/matplotlib/backends/backend_qt5agg.py", line 161, in print_figure
      FigureCanvasAgg.print_figure(self, *args, **kwargs)
    File "/usr/lib64/python2.7/site-packages/matplotlib/backend_bases.py", line 2211, in print_figure
      **kwargs)
    File "/usr/lib64/python2.7/site-packages/matplotlib/backends/backend_pdf.py", line 2485, in print_pdf
      self.figure.draw(renderer)
    File "/usr/lib64/python2.7/site-packages/matplotlib/artist.py", line 59, in draw_wrapper
      draw(artist, renderer, *args, **kwargs)
    File "/usr/lib64/python2.7/site-packages/matplotlib/figure.py", line 1085, in draw
      func(*args)
    File "/usr/lib64/python2.7/site-packages/matplotlib/artist.py", line 59, in draw_wrapper
      draw(artist, renderer, *args, **kwargs)
    File "/usr/lib64/python2.7/site-packages/cartopy/mpl/geoaxes.py", line 359, in draw
      inframe=inframe)
    File "/usr/lib64/python2.7/site-packages/matplotlib/artist.py", line 59, in draw_wrapper
      draw(artist, renderer, *args, **kwargs)
    File "/usr/lib64/python2.7/site-packages/matplotlib/axes/_base.py", line 2081, in draw
      for z, im in zorder_images]
    File "/usr/lib64/python2.7/site-packages/matplotlib/image.py", line 580, in make_image
      raise RuntimeError('You must first set the image'
  RuntimeError: You must first set the image array or the image attribute
  ```
  
  I think maybe `SlippyImageArtist` should be overriding `make_image`, too.
  
  
  --- END ISSUE ---
  
  Below are some code segments, each from a relevant file. One or more of these files may contain bugs.
  --- BEGIN FILES ---
  Path: `lib/cartopy/mpl/slippy_image_artist.py`
  Content:
  ```
  1 # (C) British Crown Copyright 2014 - 2018, Met Office
  2 #
  3 # This file is part of cartopy.
  4 #
  5 # cartopy is free software: you can redistribute it and/or modify it under
  6 # the terms of the GNU Lesser General Public License as published by the
  7 # Free Software Foundation, either version 3 of the License, or
  8 # (at your option) any later version.
  9 #
  10 # cartopy is distributed in the hope that it will be useful,
  11 # but WITHOUT ANY WARRANTY; without even the implied warranty of
  12 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  13 # GNU Lesser General Public License for more details.
  14 #
  15 # You should have received a copy of the GNU Lesser General Public License
  16 # along with cartopy.  If not, see <https://www.gnu.org/licenses/>.
  17 """
  18 Define the SlippyImageArtist class, which interfaces with
  19 :class:`cartopy.io.RasterSource` instances at draw time, for interactive
  20 dragging and zooming of raster data.
  21 
  22 """
  23 
  24 from __future__ import (absolute_import, division, print_function)
  25 
  26 from matplotlib.image import AxesImage
  27 import matplotlib.artist
  28 
  29 
  30 class SlippyImageArtist(AxesImage):
  31 
  32     """
  33     A subclass of :class:`~matplotlib.image.AxesImage` which provides an
  34     interface for getting a raster from the given object with interactive
  35     slippy map type functionality.
  36 
  37     Kwargs are passed to the AxesImage constructor.
  38 
  39     """
  40     def __init__(self, ax, raster_source, **kwargs):
  41         self.raster_source = raster_source
  42         super(SlippyImageArtist, self).__init__(ax, **kwargs)
  43         self.set_clip_path(ax.background_patch)
  44         self.cache = []
  45 
  46         ax.figure.canvas.mpl_connect('button_press_event', self.on_press)
  47         ax.figure.canvas.mpl_connect('button_release_event', self.on_release)
  48 
  49         self.on_release()
  50 
  51     def on_press(self, event=None):
  52         self.user_is_interacting = True
  53 
  54     def on_release(self, event=None):
  55         self.user_is_interacting = False
  56         self.stale = True
  57 
  58     @matplotlib.artist.allow_rasterization
  59     def draw(self, renderer, *args, **kwargs):
  60         if not self.get_visible():
  61             return
  62 
  63         ax = self.axes
  64         window_extent = ax.get_window_extent()
  65         [x1, y1], [x2, y2] = ax.viewLim.get_points()
  66         if not self.user_is_interacting:
  67             located_images = self.raster_source.fetch_raster(
  68                 ax.projection, extent=[x1, x2, y1, y2],
  69                 target_resolution=(window_extent.width, window_extent.height))
  70             self.cache = located_images
  71 
  72         for img, extent in self.cache:
  73             self.set_array(img)
  74             with ax.hold_limits():
  75                 self.set_extent(extent)
  76             super(SlippyImageArtist, self).draw(renderer, *args, **kwargs)
  77
  ```
  --- END FILES ---
  
  Please first localize the bug based on the issue statement, and then generate a patch according to the `git diff` format fenced by three backticks.
  
  Here is an example:
  
  ```diff
  diff --git a/examples/server_async.py b/examples/server_async.py
  --- a/examples/server_async.py
  +++ b/examples/server_async.py
  @@ -313,4 +313,4 @@
   
   
   if __name__ == "__main__":
  -    asyncio.run(run_async_server("."), debug=True)
  +    asyncio.run(run_async_server(), debug=True)
  diff --git a/examples/server_sync.py b/examples/server_sync.py
  --- a/examples/server_sync.py
  +++ b/examples/server_sync.py
  @@ -313,5 +313,5 @@
   
   
   if __name__ == "__main__":
  -    server = run_sync_server(".")
  +    server = run_sync_server()
       server.shutdown()
  
  ```
  
golden_diff: diff --git a/lib/cartopy/mpl/slippy_image_artist.py b/lib/cartopy/mpl/slippy_image_artist.py
  --- a/lib/cartopy/mpl/slippy_image_artist.py
  +++ b/lib/cartopy/mpl/slippy_image_artist.py
  @@ -74,3 +74,8 @@
               with ax.hold_limits():
                   self.set_extent(extent)
               super(SlippyImageArtist, self).draw(renderer, *args, **kwargs)
  +
  +    def can_composite(self):
  +        # As per https://github.com/SciTools/cartopy/issues/689, disable
  +        # compositing multiple raster sources.
  +        return False
  
verification_info: {"golden_diff": "diff --git a/lib/cartopy/mpl/slippy_image_artist.py b/lib/cartopy/mpl/slippy_image_artist.py\n--- a/lib/cartopy/mpl/slippy_image_artist.py\n+++ b/lib/cartopy/mpl/slippy_image_artist.py\n@@ -74,3 +74,8 @@\n             with ax.hold_limits():\n                 self.set_extent(extent)\n             super(SlippyImageArtist, self).draw(renderer, *args, **kwargs)\n+\n+    def can_composite(self):\n+        # As per https://github.com/SciTools/cartopy/issues/689, disable\n+        # compositing multiple raster sources.\n+        return False\n", "issue": "SlippyImageArtist cannot be composited\nFor example, take the WMTS example and add a second layer. Then attempt to save as a PDF.\n\n``` python\nimport cartopy.crs as ccrs\nimport matplotlib.pyplot as plt\n\nurl = 'http://map1c.vis.earthdata.nasa.gov/wmts-geo/wmts.cgi'\nlayer1 = 'VIIRS_CityLights_2012'\nlayer2 = 'ASTER_GDEM_Color_Index'\n\nax = plt.axes(projection=ccrs.PlateCarree())\nax.add_wmts(url, layer1)\nax.add_wmts(url, layer2)\nax.set_extent((-15, 25, 35, 60))\n\nplt.title('Suomi NPP Earth at night April/October 2012')\nplt.savefig('test.pdf')\nplt.show()\n```\n\nwhich results in:\n\n``` python\nTraceback (most recent call last):\n  File \"wmts.py\", line 33, in main\n    plt.savefig('test.pdf')\n  File \"/usr/lib64/python2.7/site-packages/matplotlib/pyplot.py\", line 577, in savefig\n    res = fig.savefig(*args, **kwargs)\n  File \"/usr/lib64/python2.7/site-packages/matplotlib/figure.py\", line 1476, in savefig\n    self.canvas.print_figure(*args, **kwargs)\n  File \"/usr/lib64/python2.7/site-packages/matplotlib/backends/backend_qt5agg.py\", line 161, in print_figure\n    FigureCanvasAgg.print_figure(self, *args, **kwargs)\n  File \"/usr/lib64/python2.7/site-packages/matplotlib/backend_bases.py\", line 2211, in print_figure\n    **kwargs)\n  File \"/usr/lib64/python2.7/site-packages/matplotlib/backends/backend_pdf.py\", line 2485, in print_pdf\n    self.figure.draw(renderer)\n  File \"/usr/lib64/python2.7/site-packages/matplotlib/artist.py\", line 59, in draw_wrapper\n    draw(artist, renderer, *args, **kwargs)\n  File \"/usr/lib64/python2.7/site-packages/matplotlib/figure.py\", line 1085, in draw\n    func(*args)\n  File \"/usr/lib64/python2.7/site-packages/matplotlib/artist.py\", line 59, in draw_wrapper\n    draw(artist, renderer, *args, **kwargs)\n  File \"/usr/lib64/python2.7/site-packages/cartopy/mpl/geoaxes.py\", line 359, in draw\n    inframe=inframe)\n  File \"/usr/lib64/python2.7/site-packages/matplotlib/artist.py\", line 59, in draw_wrapper\n    draw(artist, renderer, *args, **kwargs)\n  File \"/usr/lib64/python2.7/site-packages/matplotlib/axes/_base.py\", line 2081, in draw\n    for z, im in zorder_images]\n  File \"/usr/lib64/python2.7/site-packages/matplotlib/image.py\", line 580, in make_image\n    raise RuntimeError('You must first set the image'\nRuntimeError: You must first set the image array or the image attribute\n```\n\nI think maybe `SlippyImageArtist` should be overriding `make_image`, too.\n\n", "before_files": [{"content": "# (C) British Crown Copyright 2014 - 2018, Met Office\n#\n# This file is part of cartopy.\n#\n# cartopy is free software: you can redistribute it and/or modify it under\n# the terms of the GNU Lesser General Public License as published by the\n# Free Software Foundation, either version 3 of the License, or\n# (at your option) any later version.\n#\n# cartopy is distributed in the hope that it will be useful,\n# but WITHOUT ANY WARRANTY; without even the implied warranty of\n# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n# GNU Lesser General Public License for more details.\n#\n# You should have received a copy of the GNU Lesser General Public License\n# along with cartopy.  If not, see <https://www.gnu.org/licenses/>.\n\"\"\"\nDefine the SlippyImageArtist class, which interfaces with\n:class:`cartopy.io.RasterSource` instances at draw time, for interactive\ndragging and zooming of raster data.\n\n\"\"\"\n\nfrom __future__ import (absolute_import, division, print_function)\n\nfrom matplotlib.image import AxesImage\nimport matplotlib.artist\n\n\nclass SlippyImageArtist(AxesImage):\n\n    \"\"\"\n    A subclass of :class:`~matplotlib.image.AxesImage` which provides an\n    interface for getting a raster from the given object with interactive\n    slippy map type functionality.\n\n    Kwargs are passed to the AxesImage constructor.\n\n    \"\"\"\n    def __init__(self, ax, raster_source, **kwargs):\n        self.raster_source = raster_source\n        super(SlippyImageArtist, self).__init__(ax, **kwargs)\n        self.set_clip_path(ax.background_patch)\n        self.cache = []\n\n        ax.figure.canvas.mpl_connect('button_press_event', self.on_press)\n        ax.figure.canvas.mpl_connect('button_release_event', self.on_release)\n\n        self.on_release()\n\n    def on_press(self, event=None):\n        self.user_is_interacting = True\n\n    def on_release(self, event=None):\n        self.user_is_interacting = False\n        self.stale = True\n\n    @matplotlib.artist.allow_rasterization\n    def draw(self, renderer, *args, **kwargs):\n        if not self.get_visible():\n            return\n\n        ax = self.axes\n        window_extent = ax.get_window_extent()\n        [x1, y1], [x2, y2] = ax.viewLim.get_points()\n        if not self.user_is_interacting:\n            located_images = self.raster_source.fetch_raster(\n                ax.projection, extent=[x1, x2, y1, y2],\n                target_resolution=(window_extent.width, window_extent.height))\n            self.cache = located_images\n\n        for img, extent in self.cache:\n            self.set_array(img)\n            with ax.hold_limits():\n                self.set_extent(extent)\n            super(SlippyImageArtist, self).draw(renderer, *args, **kwargs)\n", "path": "lib/cartopy/mpl/slippy_image_artist.py"}], "after_files": [{"content": "# (C) British Crown Copyright 2014 - 2018, Met Office\n#\n# This file is part of cartopy.\n#\n# cartopy is free software: you can redistribute it and/or modify it under\n# the terms of the GNU Lesser General Public License as published by the\n# Free Software Foundation, either version 3 of the License, or\n# (at your option) any later version.\n#\n# cartopy is distributed in the hope that it will be useful,\n# but WITHOUT ANY WARRANTY; without even the implied warranty of\n# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n# GNU Lesser General Public License for more details.\n#\n# You should have received a copy of the GNU Lesser General Public License\n# along with cartopy.  If not, see <https://www.gnu.org/licenses/>.\n\"\"\"\nDefine the SlippyImageArtist class, which interfaces with\n:class:`cartopy.io.RasterSource` instances at draw time, for interactive\ndragging and zooming of raster data.\n\n\"\"\"\n\nfrom __future__ import (absolute_import, division, print_function)\n\nfrom matplotlib.image import AxesImage\nimport matplotlib.artist\n\n\nclass SlippyImageArtist(AxesImage):\n\n    \"\"\"\n    A subclass of :class:`~matplotlib.image.AxesImage` which provides an\n    interface for getting a raster from the given object with interactive\n    slippy map type functionality.\n\n    Kwargs are passed to the AxesImage constructor.\n\n    \"\"\"\n    def __init__(self, ax, raster_source, **kwargs):\n        self.raster_source = raster_source\n        super(SlippyImageArtist, self).__init__(ax, **kwargs)\n        self.set_clip_path(ax.background_patch)\n        self.cache = []\n\n        ax.figure.canvas.mpl_connect('button_press_event', self.on_press)\n        ax.figure.canvas.mpl_connect('button_release_event', self.on_release)\n\n        self.on_release()\n\n    def on_press(self, event=None):\n        self.user_is_interacting = True\n\n    def on_release(self, event=None):\n        self.user_is_interacting = False\n        self.stale = True\n\n    @matplotlib.artist.allow_rasterization\n    def draw(self, renderer, *args, **kwargs):\n        if not self.get_visible():\n            return\n\n        ax = self.axes\n        window_extent = ax.get_window_extent()\n        [x1, y1], [x2, y2] = ax.viewLim.get_points()\n        if not self.user_is_interacting:\n            located_images = self.raster_source.fetch_raster(\n                ax.projection, extent=[x1, x2, y1, y2],\n                target_resolution=(window_extent.width, window_extent.height))\n            self.cache = located_images\n\n        for img, extent in self.cache:\n            self.set_array(img)\n            with ax.hold_limits():\n                self.set_extent(extent)\n            super(SlippyImageArtist, self).draw(renderer, *args, **kwargs)\n\n    def can_composite(self):\n        # As per https://github.com/SciTools/cartopy/issues/689, disable\n        # compositing multiple raster sources.\n        return False\n", "path": "lib/cartopy/mpl/slippy_image_artist.py"}]}