Skip to content

Commit

Permalink
make sure geo_interface takes precedence over iterable, fixes #110
Browse files Browse the repository at this point in the history
  • Loading branch information
perrygeo committed Jan 16, 2016
1 parent 37766d3 commit c6c8568
Show file tree
Hide file tree
Showing 3 changed files with 55 additions and 5 deletions.
6 changes: 3 additions & 3 deletions src/rasterstats/io.py
Original file line number Diff line number Diff line change
Expand Up @@ -102,15 +102,15 @@ def fiona_generator(obj):
elif isinstance(obj, bytes):
# Single binary object, probably a wkb
features_iter = [parse_feature(obj)]
elif isinstance(obj, Iterable):
# Iterable of feature-like objects
features_iter = (parse_feature(x) for x in obj)
elif hasattr(obj, '__geo_interface__'):
mapping = obj.__geo_interface__
if mapping['type'] == 'FeatureCollection':
features_iter = mapping['features']
else:
features_iter = [parse_feature(mapping)]
elif isinstance(obj, Iterable):
# Iterable of feature-like objects
features_iter = (parse_feature(x) for x in obj)

if not features_iter:
raise ValueError("Object is not a recognized source of Features")
Expand Down
39 changes: 37 additions & 2 deletions tests/test_io.py
Original file line number Diff line number Diff line change
Expand Up @@ -283,13 +283,48 @@ def test_Raster_context():
assert r2.src.closed


def test_geointerface():
class MockGeo(object):
def __init__(self, features):
self.__geo_interface__ = {
'type': "FeatureCollection",
'features': features}

# Make it iterable just to ensure that geo interface
# takes precendence over iterability
def __iter__(self):
pass

def __next__(self):
pass

def next(self):
pass

features = [{
"type": "Feature",
"properties": {},
"geometry": {
"type": "Point",
"coordinates": [0, 0]}
}, {
"type": "Feature",
"properties": {},
"geometry": {
"type": "Polygon",
"coordinates": [[[-50, -10], [-40, 10], [-30, -10], [-50, -10]]]}}]

geothing = MockGeo(features)
assert list(read_features(geothing)) == features


# Optional tests
def test_geodataframe():
try:
import geopandas as gpd
df = gpd.GeoDataFrame.from_file(polygons)
df = gpd.read_file(polygons)
if not hasattr(df, '__geo_interface__'):
pytest.skip("This version of geopandas doesn't support df.__geo_interface__")
except ImportError:
pytest.skip("Can't import geopands")
assert read_features(df)
assert list(read_features(df))
15 changes: 15 additions & 0 deletions tests/test_zonal.py
Original file line number Diff line number Diff line change
Expand Up @@ -404,3 +404,18 @@ def test_geojson_out():
assert feature['type'] == 'Feature'
assert 'id' in feature['properties'] # from orig
assert 'count' in feature['properties'] # from zonal stats

# Optional tests
def test_geodataframe_zonal():
polygons = os.path.join(DATA, 'polygons.shp')

try:
import geopandas as gpd
df = gpd.read_file(polygons)
if not hasattr(df, '__geo_interface__'):
pytest.skip("This version of geopandas doesn't support df.__geo_interface__")
except ImportError:
pytest.skip("Can't import geopands")

expected = zonal_stats(polygons, raster)
assert zonal_stats(df, raster) == expected

0 comments on commit c6c8568

Please sign in to comment.