Skip to content
This repository has been archived by the owner on Aug 2, 2022. It is now read-only.

Commit

Permalink
Merge pull request #76 from mapbox/staticmaps
Browse files Browse the repository at this point in the history
Staticmaps API
  • Loading branch information
sgillies committed Dec 2, 2015
2 parents 71ceb61 + eebb63b commit a04cb61
Show file tree
Hide file tree
Showing 5 changed files with 178 additions and 0 deletions.
1 change: 1 addition & 0 deletions .travis.yml
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@ env:
install:
- pip install -U pip --cache-dir $HOME/.pip-cache
- pip install -e .[test] --cache-dir $HOME/.pip-cache
- if [[ $TRAVIS_PYTHON_VERSION == 2.6 ]]; then pip install ordereddict; fi
script:
- py.test --cov mapbox --cov-report term-missing
- py.test --doctest-glob='*.md' docs/*.md
Expand Down
19 changes: 19 additions & 0 deletions README.rst
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,11 @@ Services
- Forward (place names ⇢ longitude, latitude)
- Reverse (longitude, latitude ⇢ place names)

- `Static Maps <https://www.mapbox.com/developers/api/static/>`__

- Generate standalone images from existing Mapbox mapids
- Render with GeoJSON overlays

- `Surface <https://www.mapbox.com/developers/api/surface/>`__

- Interpolates values along lines. Useful for elevation traces.
Expand Down Expand Up @@ -138,6 +143,20 @@ which returns::
See ``import mapbox; help(mapbox.Distance)`` for more detailed usage.

Static Maps
-----------
Static maps are standalone images that can be displayed on web and mobile devices without the aid of a mapping library or API. Static maps can display GeoJSON overlays and the `simplestyle-spec <https://github.com/mapbox/simplestyle-spec>`_ styles will be respected and rendered.

.. code:: python
from mapbox import Static
res = Static().image('mapbox.satellite',
lon=-61.7, lat=12.1, z=12,
features=list_of_points)
with open('map.png', 'wb') as output:
output.write(res.content)
Surface
-------
Expand Down
1 change: 1 addition & 0 deletions mapbox/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -7,3 +7,4 @@
from .services.geocoding import Geocoder, InvalidPlaceTypeError
from .services.surface import Surface
from .services.uploads import Uploader
from .services.static import Static
58 changes: 58 additions & 0 deletions mapbox/services/static.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,58 @@
import json

from uritemplate import URITemplate

from mapbox.services.base import Service


class Static(Service):

def __init__(self, access_token=None):
self.baseuri = 'https://api.mapbox.com/v4'
self.session = self.get_session(access_token)

def image(self, mapid, lon=None, lat=None, z=None, features=None,
width=600, height=600, image_format='png256'):

if lon and lat and z:
auto = False
else:
auto = True

values = dict(
mapid=mapid,
lon=str(lon),
lat=str(lat),
z=str(z),
width=str(width),
height=str(height),
format=image_format)

if features:
values['overlay'] = json.dumps({'type': 'FeatureCollection',
'features': features})

if len(values['overlay']) > 4087: # limit is 4096 minus the 'geojson()'
raise ValueError("geojson is too large for the static maps API, "
"must be less than 4096 characters")

if auto:
uri = URITemplate(
'%s/{mapid}/geojson({overlay})/auto/{width}x{height}.{format}' %
self.baseuri).expand(**values)
else:
uri = URITemplate(
'%s/{mapid}/geojson({overlay})/{lon},{lat},{z}/{width}x{height}.{format}' %
self.baseuri).expand(**values)
else:
if auto:
raise ValueError("Must provide features if lat, lon, z are None")

# No overlay
uri = URITemplate(
'%s/{mapid}/{lon},{lat},{z}/{width}x{height}.{format}' %
self.baseuri).expand(**values)

res = self.session.get(uri)
self.handle_http_error(res)
return res
99 changes: 99 additions & 0 deletions tests/test_staticmaps.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,99 @@
import json

try:
from urllib import quote
except ImportError:
# python 3
from urllib.parse import quote

try:
from collections import OrderedDict
except ImportError:
# python 2.6
from ordereddict import OrderedDict

import pytest
import responses

import mapbox


@pytest.fixture
def points():
points = [
OrderedDict(
type="Feature",
properties=OrderedDict(title="point1"),
geometry=OrderedDict(
type="Point",
coordinates=[-61.7, 12.1])),
OrderedDict(
type="Feature",
properties=OrderedDict(title="point2"),
geometry=OrderedDict(
type="Point",
coordinates=[-61.6, 12.0]))]

return points


@responses.activate
def test_staticmap_lonlatz_only():

responses.add(
responses.GET,
'https://api.mapbox.com/v4/mapbox.satellite/-61.7,12.1,12/600x600.png256?access_token=pk.test',
match_querystring=True,
body='png123',
status=200,
content_type='image/png')

res = mapbox.Static(access_token='pk.test').image('mapbox.satellite', -61.7, 12.1, 12)
assert res.status_code == 200


@responses.activate
def test_staticmap_lonlatz_features(points):

overlay = json.dumps({'type': 'FeatureCollection',
'features': points})
overlay = quote(overlay)
url = ('https://api.mapbox.com/v4/mapbox.satellite/geojson({0})/'
'-61.7,12.1,12/600x600.png256?access_token=pk.test'.format(overlay))

responses.add(
responses.GET, url,
match_querystring=True,
body='png123',
status=200,
content_type='image/png')

res = mapbox.Static(access_token='pk.test').image('mapbox.satellite',
-61.7, 12.1, 12,
points)
assert res.status_code == 200

@responses.activate
def test_staticmap_auto_features(points):

overlay = json.dumps({'type': 'FeatureCollection',
'features': points})
overlay = quote(overlay)
url = ('https://api.mapbox.com/v4/mapbox.satellite/geojson({0})/'
'auto/600x600.png256?access_token=pk.test'.format(overlay))

responses.add(
responses.GET, url,
match_querystring=True,
body='png123',
status=200,
content_type='image/png')

res = mapbox.Static(access_token='pk.test').image('mapbox.satellite',
features=points)
assert res.status_code == 200


def test_staticmap_auto_nofeatures(points):
with pytest.raises(ValueError):
mapbox.Static(access_token='pk.test').image('mapbox.satellite')

0 comments on commit a04cb61

Please sign in to comment.