Repository: SciTools/cartopy

Issue:
Colouring countries
### Description
Cartopy stop working when you try to color some countries, like Austria (AUT), Albania among others in Europe as far as I could see. My maps heve been working fine until couple last update on april.



#### Code to reproduce
```python
import matplotlib.pyplot as plt
import cartopy
import cartopy.io.shapereader as shpreader
import cartopy.crs as ccrs
import matplotlib.pyplot as plt
import cartopy.crs as ccrs
import cartopy.feature as cfeature


def area(ax, iso, clr) :
  
    shp = shpreader.natural_earth(resolution='10m',category='cultural',name='admin_0_countries')
    reader = shpreader.Reader(shp)
    countries = reader.records()
  
    for n in countries :
        if n.attributes['ADM0_A3'] == iso: 
            ax.add_geometries(n.geometry, ccrs.PlateCarree(),
                              facecolor=clr, alpha = 1.00, linewidth =0.15, edgecolor = "black",
                              label=n.attributes['ADM0_A3']) 
          
    return ax

iso3 = ['USA','CAN','RUS','GBR','ISL','FRA','ITA','AUT'] # works fine with this codes
#iso3 = ['USA','CAN','RUS','GBR','ISL','FRA','ITA','CHN','AUT'] # error message - due to  "AUT" - Austria 

def main():
    ax = plt.axes(projection=ccrs.Miller())
    
    states_provinces = cfeature.NaturalEarthFeature(
        category='cultural',
        name='admin_1_states_provinces_lines',
        scale='50m',
        facecolor='none')

    ax.add_feature(cfeature.LAND)
    ax.add_feature(cfeature.COASTLINE)
    ax.add_feature(states_provinces, edgecolor='gray')

    for n in iso3 :
        area(ax,n,"red")         
             
    plt.show()


if __name__ == '__main__':
    main()
```

#### Traceback

```python-traceback

File "C:\ProgramData\Anaconda3\lib\site-packages\cartopy\mpl\geoaxes.py", line 588, in add_geometries
  feature = cartopy.feature.ShapelyFeature(geoms, crs, **kwargs)

File "C:\ProgramData\Anaconda3\lib\site-packages\cartopy\feature\__init__.py", line 231, in __init__
  self._geoms = tuple(geometries)

TypeError: 'Polygon' object is not iterable
```

<details>
 <summary>Full environment definition</summary>

<!-- fill in the following information as appropriate -->

### Operating system
Windows 10

### Cartopy version
0.17.0

### conda list
4.64.14

### pip list
19.1

</details>



Discussion:
I'm not sure if this is helpful, but I just updated cartopy and I wasn't able to replicate the issue on my computer (Mac, cartopy v0.17.0, matplotlib v3.0.2). So it might be an issue that's more specific to your system (Windows OS or your environment).

```python
import matplotlib.pyplot as plt
import cartopy.io.shapereader as shpreader
import cartopy.crs as ccrs
import cartopy.feature as cfeature
%matplotlib inline

def area(ax, iso, clr) :
    shp = shpreader.natural_earth(resolution='10m',category='cultural',
                                  name='admin_0_countries')
    reader = shpreader.Reader(shp)
    for n in reader.records() :
        if n.attributes['ADM0_A3'] == iso: 
            ax.add_geometries(n.geometry, ccrs.PlateCarree(), facecolor=clr, 
                              alpha = 1.00, linewidth =0.15, edgecolor = "black",
                              label=n.attributes['ADM0_A3']) 
    return ax

iso3 = ['USA','CAN','RUS','GBR','ISL','FRA','ITA','CHN','AUT']

ax = plt.axes(projection=ccrs.Miller())
ax.add_feature(cfeature.COASTLINE)

for n in iso3 :
    area(ax, n, "red")
    
plt.show()
```

![Unknown](https://user-images.githubusercontent.com/6994487/57255835-f5a8ae80-7009-11e9-8fa0-08964d1f281b.png)

Dear Eleanor,

I tried to reset Spyder but the problem persists. On the other hand when I run Python via Canopy and It works fine. Something might no be right with my Anaconda/pyder installation.

Anyway, thank you very much Eleanor.

Roberval

![_EuropeTelephoneLines](https://user-images.githubusercontent.com/32061960/57292319-d5bfcc00-7097-11e9-9373-5093904aeb0c.gif)


I get the same `TypeError: 'Polygon' object is not iterable` error using:
```
cartopy                   0.17.0          py36h929c6f0_1004    conda-forge
```
```
matplotlib                3.0.3                    py36_0    conda-forge
```

and also with an update to:

```
cartopy                   0.17.0          py36h929c6f0_1004    conda-forge
```
```
matplotlib                3.1.0                    py36_1    conda-forge
```
I downgraded to cartopy 0.16 (which also downgraded associated packages as follows) and in doing so am able to iterate through the shpreader records

Here are the relevant package versions associated with the downgrade:
```
pyproj-1.9.5.1       | 54 KB     | ##################################### | 100% 
json-c-0.12.1        | 47 KB     | ##################################### | 100% 
geotiff-1.4.2        | 1.1 MB    | ##################################### | 100% 
shapely-1.6.4        | 302 KB    | ##################################### | 100% 
libgdal-2.2.2        | 15.2 MB   | ##################################### | 100% 
gdal-2.2.2           | 824 KB    | ##################################### | 100% 
blas-2.10            | 7 KB      | ##################################### | 100% 
netcdf4-1.3.1        | 749 KB    | ##################################### | 100% 
proj4-4.9.3          | 3.1 MB    | ##################################### | 100% 
libspatialite-4.3.0a | 3.0 MB    | ##################################### | 100% 
geos-3.6.2           | 1.4 MB    | ##################################### | 100% 
cartopy-0.16.0       | 1.7 MB    | ##################################### | 100% 
basemap-1.2.0        | 15.1 MB   | ##################################### | 100% 
fiona-1.7.13         | 756 KB    | ##################################### | 100%
```
I had the same issue with cartopy 0.17 and matplotlib 3.0.2 .  I ended up downgrading to 0.16 (and upgrading matplotlib to 3.1.0).  This fixed the error. I'm running the code in Atom with Hydrogen on a Mac.
I think the real problem here is that you're passing in a single geometry to the plot, which can't be iterated upon.

If you change your code to put the single geometry in a list `[n.geometry]` here:
```
            ax.add_geometries([n.geometry], ccrs.PlateCarree(),
                              facecolor=clr, alpha = 1.00, linewidth =0.15, edgecolor = "black",
                              label=n.attributes['ADM0_A3'])
```
it works for me without errors. An unfortunate pluralization of geometries() requiring an iterable I suppose.
Thank you so much @greglucas! That solves the problem I was having with the code.
This thread is probably not the most descriptively names to deal with this issue, but it does seem that allowing add_geometeries() to plot non-iterable (single) objects makes sense.
Glad that helped! I agree with you that it would be nice to not force plural here. My guess is something like:
```python
if isinstance(geometries, sgeom.base.BaseGeometry, sgeom.base.BaseMultipartGeometry)):
    geometries = [geometries]
```
near here:
https://github.com/SciTools/cartopy/blob/de1cd82d33517161339ebf69b6f3982b6d79b992/lib/cartopy/feature/__init__.py#L221

would do the trick. But that is untested. Feel free to open a PR if you'd like!

Resolving patch:
diff --git a/lib/cartopy/feature/__init__.py b/lib/cartopy/feature/__init__.py
--- a/lib/cartopy/feature/__init__.py
+++ b/lib/cartopy/feature/__init__.py
@@ -214,6 +214,8 @@ def __init__(self, geometries, crs, **kwargs):
 
         """
         super().__init__(crs, **kwargs)
+        if isinstance(geometries, sgeom.base.BaseGeometry):
+            geometries = [geometries]
         self._geoms = tuple(geometries)
 
     def geometries(self):


Test patch:
diff --git a/lib/cartopy/tests/mpl/test_axes.py b/lib/cartopy/tests/mpl/test_axes.py
--- a/lib/cartopy/tests/mpl/test_axes.py
+++ b/lib/cartopy/tests/mpl/test_axes.py
@@ -13,6 +13,7 @@
 import pytest
 
 import cartopy.crs as ccrs
+import cartopy.feature as cfeature
 from cartopy.mpl.geoaxes import InterProjectionTransform, GeoAxes
 
 
@@ -108,6 +109,14 @@ def test_styler_kwarg(self, ShapelyFeature, add_feature_method):
         add_feature_method.assert_called_once_with(
             ShapelyFeature(), styler=mock.sentinel.styler)
 
+    @pytest.mark.natural_earth
+    def test_single_geometry(self):
+        # A single geometry is acceptable
+        proj = ccrs.PlateCarree()
+        ax = GeoAxes(plt.figure(), [0, 0, 1, 1],
+                     map_projection=proj)
+        ax.add_geometries(next(cfeature.COASTLINE.geometries()), crs=proj)
+
 
 @cleanup
 def test_geoaxes_subplot():