diff --git a/IPython/core/display.py b/IPython/core/display.py index d1c3130..4d43552 100644 --- a/IPython/core/display.py +++ b/IPython/core/display.py @@ -680,8 +680,76 @@ lib_t1 = """$.getScript("%s", function () { lib_t2 = """}); """ -class GeoJSON(JSON): +class GeoJSON(DisplayObject): + """GeoJSON expects JSON-able dict + not an already-serialized JSON string. + + Scalar types (None, number, string) are not allowed, only dict containers. + """ + # wrap data in a property, which warns about passing already-serialized JSON + _data = None + + def __init__(self, data=None, url_template=None, layer_options=None, url=None, filename=None, metadata=None): + """Create a GeoJSON display object given raw data. + + Parameters + ---------- + data : dict or list + VegaLite data. Not an already-serialized JSON string. + Scalar types (None, number, string) are not allowed, only dict + or list containers. + url_template : string + Leaflet TileLayer URL template: http://leafletjs.com/reference.html#url-template + layer_options : dict + Leaflet TileLayer options: http://leafletjs.com/reference.html#tilelayer-options + url : unicode + A URL to download the data from. + filename : unicode + Path to a local file to load the data from. + metadata: dict + Specify extra metadata to attach to the json display object. + + Examples + -------- + + The following will display an interactive map of Mars with a point of + interest on frontend that do support GeoJSON display. + + >>> from IPython.display import GeoJSON + + >>> GeoJSON(data={ + ... "type": "Feature", + ... "geometry": { + ... "type": "Point", + ... "coordinates": [-81.327, 296.038] + ... }, + ... "properties": { + ... "name": "Inca City" + ... } + ... }, + ... url_template="http://s3-eu-west-1.amazonaws.com/whereonmars.cartodb.net/{basemap_id}/{z}/{x}/{y}.png", + ... layer_options={ + ... "basemap_id": "celestia_mars-shaded-16k_global", + ... "attribution" : "Celestia/praesepe", + ... "minZoom" : 0, + ... "maxZoom" : 18, + ... }) + + + In the terminal IPython, you will only see the text representation of + the GeoJSON object. + + """ + self.url_template = url_template + self.layer_options = layer_options + self.metadata = metadata + super(GeoJSON, self).__init__(data=data, url=url, filename=filename) + + def _check_data(self): + if self.data is not None and not isinstance(self.data, dict): + raise TypeError("%s expects a JSONable dict, not %r" % (self.__class__.__name__, self.data)) + @property def data(self): return self._data @@ -693,11 +761,21 @@ class GeoJSON(JSON): self._data = data def _ipython_display_(self): + md = {} + if self.url_template: + md['tileUrlTemplate'] = self.url_template + if self.layer_options: + md['tileLayerOptions'] = self.layer_options + if self.metadata: + md.update(self.metadata) bundle = { 'application/geo+json': self.data, 'text/plain': '' } - display(bundle, raw=True) + metadata = { + 'application/geo+json': md + } + display(bundle, metadata=metadata, raw=True) class Javascript(TextDisplayObject): diff --git a/IPython/core/tests/test_display.py b/IPython/core/tests/test_display.py index f619d58..c639f92 100644 --- a/IPython/core/tests/test_display.py +++ b/IPython/core/tests/test_display.py @@ -28,6 +28,28 @@ def test_image_size(): img = display.Image(url=thisurl, unconfined=True) nt.assert_equal(u'' % (thisurl), img._repr_html_()) + +def test_geojson(): + + gj = display.GeoJSON(data={ + "type": "Feature", + "geometry": { + "type": "Point", + "coordinates": [-81.327, 296.038] + }, + "properties": { + "name": "Inca City" + } + }, + url_template="http://s3-eu-west-1.amazonaws.com/whereonmars.cartodb.net/{basemap_id}/{z}/{x}/{y}.png", + layer_options={ + "basemap_id": "celestia_mars-shaded-16k_global", + "attribution": "Celestia/praesepe", + "minZoom": 0, + "maxZoom": 18, + }) + nt.assert_equal(u'', str(gj)) + def test_retina_png(): here = os.path.dirname(__file__) img = display.Image(os.path.join(here, "2x2.png"), retina=True) diff --git a/docs/source/whatsnew/pr/display-geojson.rst b/docs/source/whatsnew/pr/display-geojson.rst new file mode 100644 index 0000000..5479873 --- /dev/null +++ b/docs/source/whatsnew/pr/display-geojson.rst @@ -0,0 +1,2 @@ +* IPython.display has gained a :any:`GeoJSON ` object. + :ghpull:`10288` and :ghpull:`10253`