Repository: mapbox/mapbox-sdk-py
Pull request #135 (2016-10-14 13:39:52)

limit reverse geocoding results
Ready for 👀  @KaiBot3000 @sgillies 


Patch:
diff --git a/docs/geocoding.md b/docs/geocoding.md
index 7cc5957..4c49b1a 100644
--- a/docs/geocoding.md
+++ b/docs/geocoding.md
@@ -180,6 +180,23 @@ United States: country...
 
 ```
 
+## Reverse geocoding with limited results by location type
+
+The number of results may be limited by a single type
+
+```python
+
+>>> response = geocoder.reverse(lon=-73.989, lat=40.733, limit=1, types=['country'])
+>>> response.status_code
+200
+>>> features = response.geojson()['features']
+>>> len(features)
+1
+>>> print('{place_name}: {id}'.format(**features[0]))
+United States: country...
+
+```
+
 ## Filtering by country code
 
 `forward()` can be restricted to a list of country codes. No results in Canada
diff --git a/mapbox/services/geocoding.py b/mapbox/services/geocoding.py
index 20d1d3e..8989bbc 100644
--- a/mapbox/services/geocoding.py
+++ b/mapbox/services/geocoding.py
@@ -36,7 +36,8 @@ class Geocoder(Service):
                 raise InvalidPlaceTypeError(pt)
         return {'types': ",".join(types)}
 
-    def forward(self, address, types=None, lon=None, lat=None, country=None, bbox=None, limit=None):
+    def forward(self, address, types=None, lon=None, lat=None,
+                country=None, bbox=None, limit=None):
         """Returns a Requests response object that contains a GeoJSON
         collection of places matching the given address.
 
@@ -72,7 +73,7 @@ class Geocoder(Service):
 
         return resp
 
-    def reverse(self, lon=None, lat=None, types=None):
+    def reverse(self, lon, lat, types=None, limit=None):
         """Returns a Requests response object that contains a GeoJSON
         collection of places near the given longitude and latitude.
 
@@ -85,8 +86,17 @@ class Geocoder(Service):
             lon=str(round(float(lon), self.precision.get('reverse', 5))),
             lat=str(round(float(lat), self.precision.get('reverse', 5))))
         params = {}
+
         if types:
+            types = list(types)
             params.update(self._validate_place_types(types))
+
+        if limit is not None:
+            if not types or len(types) != 1:
+                raise InvalidPlaceTypeError(
+                    'Specify a single type when using limit with reverse geocoding')
+            params.update(limit='{0}'.format(limit))
+
         resp = self.session.get(uri, params=params)
         self.handle_http_error(resp)
 


Test patch:
diff --git a/tests/test_geocoder.py b/tests/test_geocoder.py
index 7b921c9..5ecc3da 100644
--- a/tests/test_geocoder.py
+++ b/tests/test_geocoder.py
@@ -3,6 +3,7 @@
 import json
 import re
 import responses
+import pytest
 
 import mapbox
 
@@ -246,6 +247,43 @@ def test_geocoder_forward_limit():
     assert response.status_code == 200
     assert len(response.json()['features']) == 3
 
+
+@responses.activate
+def test_geocoder_reverse_limit():
+    """Limit parameter works"""
+
+    lon, lat = -77.4371, 37.5227
+    body = json.dumps({"query": [lon, lat],
+                       "features": [{'name': 'place'}]})
+
+    responses.add(
+        responses.GET,
+        'https://api.mapbox.com/geocoding/v5/mapbox.places/{0},{1}.json?access_token=pk.test&limit=1&types=place'.format(lon, lat),
+        match_querystring=True,
+        body=body,
+        status=200,
+        content_type='application/json')
+
+    service = mapbox.Geocoder(access_token='pk.test')
+    response = service.reverse(lon=lon, lat=lat, limit=1, types=['place'])
+    assert response.status_code == 200
+    assert len(response.json()['features']) == 1
+
+
+@responses.activate
+def test_geocoder_reverse_limit_requires_onetype():
+    """Limit requires a single type"""
+
+    lon, lat = -77.123456789, 37.987654321
+    service = mapbox.Geocoder(access_token='pk.test')
+
+    with pytest.raises(mapbox.InvalidPlaceTypeError):
+        service.reverse(lon=lon, lat=lat, limit=1)
+
+    with pytest.raises(mapbox.InvalidPlaceTypeError):
+        service.reverse(lon=lon, lat=lat, limit=1, types=['places', 'country'])
+
+
 @responses.activate
 def test_geocoder_reverse_rounding():
     """Reverse geocoding parameters are rounded to 5 decimal places"""
@@ -293,3 +331,19 @@ def test_geocoder_unicode():
 
     response = mapbox.Geocoder(access_token='pk.test').forward(query)
     assert response.status_code == 200
+
+
+@responses.activate
+def test_geocoder_forward_country():
+    """Country parameter of forward geocoding works"""
+
+    responses.add(
+        responses.GET,
+        'https://api.mapbox.com/geocoding/v5/mapbox.places/1600%20pennsylvania%20ave%20nw.json?country=us&access_token=pk.test',
+        match_querystring=True,
+        body='{"query": ["1600", "pennsylvania", "ave", "nw"]}', status=200,
+        content_type='application/json')
+
+    response = mapbox.Geocoder(
+        access_token='pk.test').forward('1600 pennsylvania ave nw', country=['us'])
+    assert response.status_code == 200