Skip to content

Commit

Permalink
[New @deck.gl/json syntax support - Part 2] pydeck: Use @@type in ren…
Browse files Browse the repository at this point in the history
…dered JSON (#3959)
  • Loading branch information
ajduberstein authored and Andrew Duberstein committed Dec 7, 2019
1 parent f90b742 commit b0f014c
Show file tree
Hide file tree
Showing 35 changed files with 668 additions and 211 deletions.
11 changes: 11 additions & 0 deletions bindings/python/pydeck/pydeck/bindings/layer.py
Expand Up @@ -4,6 +4,9 @@
from .json_tools import JSONMixin


TYPE_IDENTIFIER = '@@type'


class Layer(JSONMixin):
def __init__(
self,
Expand Down Expand Up @@ -88,3 +91,11 @@ def data(self, data_set):
self._data = data_set.to_dict(orient='records')
else:
self._data = data_set

@property
def type(self):
return getattr(self, TYPE_IDENTIFIER)

@type.setter
def type(self, type_name):
self.__setattr__(TYPE_IDENTIFIER, type_name)
10 changes: 10 additions & 0 deletions bindings/python/pydeck/pydeck/bindings/view.py
@@ -1,5 +1,7 @@
from .json_tools import JSONMixin

TYPE_IDENTIFIER = '@@type'

class View(JSONMixin):
"""
Represents a "hard configuration" of a camera location
Expand All @@ -18,3 +20,11 @@ def __init__(
):
self.type = type
self.controller = controller

@property
def type(self):
return getattr(self, TYPE_IDENTIFIER)

@type.setter
def type(self, type_name):
self.__setattr__(TYPE_IDENTIFIER, type_name)
133 changes: 87 additions & 46 deletions bindings/python/pydeck/tests/bindings/test_deck.py
Expand Up @@ -3,73 +3,114 @@
import json
import os

from pydeck import (
Layer,
LightSettings,
ViewState,
View,
Deck
)
from ..const import FIXTURE_STRING
from pydeck import Layer, LightSettings, ViewState, View, Deck
from ..fixtures import fixtures

"""Create a series of test objects"""
lights = LightSettings(
lights_position=[
-0.144528,
49.739968,
8000,
-3.807751,
54.104682,
8000],
ambient_ratio=0.4,
diffuse_ratio=0.6)
layer = Layer(
'HexagonLayer',
'https://raw.githubusercontent.com/uber-common/deck.gl-data/master/examples/3d-heatmap/heatmap-data.csv',
id='heatmap',
elevation_scale=50,
elevation_range=[0, 3000],
extruded=True,
coverage=1,
light_settings=lights)
view_state = ViewState(
longitude=-1.4157267858730052,
latitude=52.232395363869415,
zoom=6.6,
min_zoom=5,
max_zoom=15,
pitch=40.5,
bearing=-27.396674584323023)
view = View(type='MapView', controller=True)
deck = Deck(layers=[layer], initial_view_state=view_state, views=[view])

def create_minimal_test_object():
lights = LightSettings(
lights_position=[-0.144528, 49.739968, 8000, -3.807751, 54.104682, 8000],
ambient_ratio=0.4,
diffuse_ratio=0.6,
)
layer = Layer(
"HexagonLayer",
"https://raw.githubusercontent.com/uber-common/deck.gl-data/master/examples/3d-heatmap/heatmap-data.csv",
id="heatmap",
elevation_scale=50,
elevation_range=[0, 3000],
extruded=True,
coverage=1,
light_settings=lights,
)
view_state = ViewState(
longitude=-1.4157267858730052,
latitude=52.232395363869415,
zoom=6.6,
min_zoom=5,
max_zoom=15,
pitch=40.5,
bearing=-27.396674584323023,
)
view = View(type="MapView", controller=True)
return Deck(layers=[layer], initial_view_state=view_state, views=[view])


def create_multi_layer_test_object():
view_state = ViewState(latitude=-122.45, longitude=37.8, zoom=12)
scatterplot = Layer(
"ScatterplotLayer",
id='scatterplot',
data=[{"position": [-122.45, 37.8]}],
get_position='position',
get_fill_color=[255, 0, 0, 255],
get_radius=1000,
)
text_layer = Layer(
"TextLayer",
id='textlayer',
data=[{"position": [-122.45, 37.8], "text": "Hello World"}],
get_text_anchor="end",
)
geojson_layer = Layer(
"GeoJsonLayer",
id='geojsonlayer',
data={
"type": "FeatureCollection",
"features": [
{
"type": "Feature",
"properties": {},
"geometry": {
"type": "Point",
"coordinates": [-122.42923736572264, 37.80544394934271],
},
}
],
},
stroked=True,
filled=True,
get_position='features.geometry.coordinates',
line_width_min_pixels=2,
opacity=0.4,
get_line_color=[255, 100, 100],
get_fill_color=[200, 160, 0, 180],
)
return Deck(layers=[scatterplot, text_layer, geojson_layer], initial_view_state=view_state)


def test_warning():
"""Verify that a warning is emitted when no Mapbox API key is set"""
_environ = dict(os.environ)
try:
if os.environ.get('MAPBOX_API_KEY'):
del os.environ['MAPBOX_API_KEY']
if os.environ.get("MAPBOX_API_KEY"):
del os.environ["MAPBOX_API_KEY"]
with pytest.warns(UserWarning) as record:
d = Deck()
os.environ['MAPBOX_API_KEY'] = 'pk.xx'
os.environ["MAPBOX_API_KEY"] = "pk.xx"
d = Deck()
# Assert that only one warning has been raised
assert len(record) == 1
finally:
os.environ.clear()
os.environ.update(_environ)


def test_json_output():
"""Verify that the JSON rendering produces an @deck.gl/json library-compliant JSON object"""
assert str(deck) == json.dumps(json.loads(FIXTURE_STRING), sort_keys=True)
deck = create_minimal_test_object()
assert str(deck) == json.dumps(json.loads(fixtures["minimal"]), sort_keys=True)
deck = create_multi_layer_test_object()
assert str(deck) == json.dumps(json.loads(fixtures["multilayers"]), sort_keys=True)


def test_update():
"""Verify that calling `update` changes the Deck object"""
view_state.latitude, view_state.longitude = 0, 0
deck = create_minimal_test_object()
deck.initial_view_state.latitude, deck.initial_view_state.longitude = 0, 0
deck.update()
# Create relevant results string
expected_results = json.loads(FIXTURE_STRING)
expected_results['initialViewState']['latitude'] = 0
expected_results['initialViewState']['longitude'] = 0
expected_results = json.loads(fixtures["minimal"])
expected_results["initialViewState"]["latitude"] = 0
expected_results["initialViewState"]["longitude"] = 0
assert str(deck) == json.dumps(expected_results, sort_keys=True)
2 changes: 1 addition & 1 deletion bindings/python/pydeck/tests/browser/test_html_renderer.py
Expand Up @@ -2,7 +2,7 @@
import os
from pydeck import Deck, Layer, ViewState

from ..const import FIXTURE_STRING
from ..fixtures import fixtures

text_data = [{'text': 'Test', 'position': [0.0, 0.0]}]
scatterplot_data = [
Expand Down
4 changes: 0 additions & 4 deletions bindings/python/pydeck/tests/const.py

This file was deleted.

16 changes: 16 additions & 0 deletions bindings/python/pydeck/tests/fixtures.py
@@ -0,0 +1,16 @@
import glob
import json
import os
import logging


here = os.path.dirname(os.path.abspath(__file__))
fixture_path = os.path.join(here, './fixtures/')
json_glob = os.path.join(fixture_path, '*.json')

fixtures = {}

for fname in glob.glob(json_glob):
fixture_text = open(fname).read()
fixture_name = os.path.basename(fname).replace('.json', '')
fixtures[fixture_name] = fixture_text
46 changes: 46 additions & 0 deletions bindings/python/pydeck/tests/fixtures/minimal.json
@@ -0,0 +1,46 @@
{
"initialViewState": {
"bearing": -27.396674584323023,
"latitude": 52.232395363869415,
"longitude": -1.4157267858730052,
"maxZoom": 15,
"minZoom": 5,
"pitch": 40.5,
"zoom": 6.6
},
"layers": [
{
"@@type": "HexagonLayer",
"coverage": 1,
"data": "https://raw.githubusercontent.com/uber-common/deck.gl-data/master/examples/3d-heatmap/heatmap-data.csv",
"elevationRange": [
0,
3000
],
"elevationScale": 50,
"extruded": true,
"getPosition": "[lng, lat]",
"id": "heatmap",
"lightSettings": {
"ambientRatio": 0.4,
"diffuseRatio": 0.6,
"lightsPosition": [
-0.144528,
49.739968,
8000,
-3.807751,
54.104682,
8000
],
"numberOfLights": 2
}
}
],
"mapStyle": "mapbox://styles/mapbox/dark-v9",
"views": [
{
"@@type": "MapView",
"controller": true
}
]
}
91 changes: 91 additions & 0 deletions bindings/python/pydeck/tests/fixtures/multilayers.json
@@ -0,0 +1,91 @@
{
"initialViewState": {
"bearing": 0,
"latitude": -122.45,
"longitude": 37.8,
"maxZoom": 20,
"minZoom": 0,
"pitch": 0,
"zoom": 12
},
"layers": [
{
"@@type": "ScatterplotLayer",
"data": [
{
"position": [
-122.45,
37.8
]
}
],
"getFillColor": [
255,
0,
0,
255
],
"getPosition": "position",
"getRadius": 1000,
"id": "scatterplot"
},
{
"@@type": "TextLayer",
"data": [
{
"position": [
-122.45,
37.8
],
"text": "Hello World"
}
],
"getPosition": "[lng, lat]",
"getTextAnchor": "end",
"id": "textlayer"
},
{
"@@type": "GeoJsonLayer",
"data": {
"features": [
{
"geometry": {
"coordinates": [
-122.42923736572264,
37.80544394934271
],
"type": "Point"
},
"properties": {},
"type": "Feature"
}
],
"type": "FeatureCollection"
},
"filled": true,
"getFillColor": [
200,
160,
0,
180
],
"getLineColor": [
255,
100,
100
],
"getPosition": "features.geometry.coordinates",
"id": "geojsonlayer",
"lineWidthMinPixels": 2,
"opacity": 0.4,
"stroked": true
}
],
"mapStyle": "mapbox://styles/mapbox/dark-v9",
"views": [
{
"@@type": "MapView",
"controller": true
}
]
}
6 changes: 3 additions & 3 deletions bindings/python/pydeck/tests/io/test_html.py
Expand Up @@ -17,12 +17,12 @@
open_named_or_temporary_file
)

from ..const import FIXTURE_STRING
from ..fixtures import fixtures


def test_rendering_is_not_broken():
rendered = render_json_to_html(FIXTURE_STRING, 'fake_key')
assert FIXTURE_STRING in rendered
rendered = render_json_to_html(fixtures['minimal'], 'fake_key')
assert fixtures['minimal'] in rendered
assert 'fake_key' in rendered


Expand Down

0 comments on commit b0f014c

Please sign in to comment.