Repository: SciTools/cartopy

Issue:
Bug with Natural Earth roads at 1:10m
The 1:10m Natural Earth road dataset triggers an error.

Running ...:

``` python
import matplotlib.pyplot as plt
import cartopy
ax = plt.axes(projection=cartopy.crs.PlateCarree())
ax.add_feature(cartopy.feature.NaturalEarthFeature('cultural', 'roads', '10m'))
plt.show()
```

... results in the following error:

```
  ...
  File ".../cartopy/feature.py", line 166, in geometries
    geometries = tuple(shapereader.Reader(path).geometries())
  File ".../cartopy/io/shapereader.py", line 180, in geometries
    yield _make_geometry(geometry_factory, shape)
  File ".../cartopy/io/shapereader.py", line 98, in _make_geometry
    geometry = geometry_factory(shape)
  File ".../cartopy/io/shapereader.py", line 62, in _create_polyline
    parts = list(shape.parts) + [None]
AttributeError: _Shape instance has no attribute 'parts'
```



Discussion:
Hmmm. Looking at the https://github.com/nvkelso/natural-earth-vector issues I'm not entirely sure there is anything related to this. We need to look into this to identify whether this is a problem with our shapereader or with the shapefile itself.

Reproducible without the feature functionality:

```
import cartopy.io.shapereader as shpreader

fname = shpreader.natural_earth(category='cultural', name='roads', resolution='10m')

reader = shpreader.Reader(fname)
for record in reader.records():
    print type(record.geometry)
```

Raises the same exception.

```
import shapefile

fname = shpreader.natural_earth(category='cultural', name='roads', resolution='10m')
r = shapefile.Reader(fname)
rec = r.shapeRecord(8126)
print rec.record
print rec.shape.points
```

The result:

```
[100, 'Road', '                                                  ', '   ', '                                                  ', "Mystry can't be deleted?", '                         ', '                         ', '                              ', '                                                  ', 0, 0, 0, 'ne_europe_basic', '                                                  ', '                                                  ', '                              ', '                              ', '                              ', 0, 0, 0, 0, 0, '     ', 0, 'Europe', 0, '                                                  ']
[]
```

Looks like the record has no points and is therefore blowing up when we try to create a geometry from it.

I've just opened an issue with the natural earth repo, we can fix this now by checking that the resulting shape's "points" are not empty before getting hold of the shape's "parts".


Resolving patch:
diff --git a/lib/cartopy/io/shapereader.py b/lib/cartopy/io/shapereader.py
--- a/lib/cartopy/io/shapereader.py
+++ b/lib/cartopy/io/shapereader.py
@@ -59,6 +59,9 @@ def _create_point(shape):
 
 
 def _create_polyline(shape):
+    if not shape.points:
+        return MultiLineString()
+
     parts = list(shape.parts) + [None]
     bounds = zip(parts[:-1], parts[1:])
     lines = [shape.points[slice(lower, upper)] for lower, upper in bounds]
@@ -66,6 +69,9 @@ def _create_polyline(shape):
 
 
 def _create_polygon(shape):
+    if not shape.points:
+        return MultiPolygon()
+
     # Partition the shapefile rings into outer rings/polygons (clockwise) and
     # inner rings/holes (anti-clockwise).
     parts = list(shape.parts) + [None]


Test patch: