Skip to content

Commit

Permalink
Merge pull request #241 from CartoDB/add-voyager
Browse files Browse the repository at this point in the history
adds voyager basemaps as default basemap
  • Loading branch information
andy-esch committed Oct 11, 2017
2 parents a694cfa + 1737675 commit 9665543
Show file tree
Hide file tree
Showing 6 changed files with 54 additions and 21 deletions.
10 changes: 5 additions & 5 deletions cartoframes/context.py
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@
from carto.exceptions import CartoException

from .credentials import Credentials
from .utils import dict_items, normalize_colnames, norm_colname
from .utils import dict_items, normalize_colnames, norm_colname, join_url
from .layer import BaseMap
from .maps import non_basemap_layers, get_map_name, get_map_template

Expand Down Expand Up @@ -217,7 +217,7 @@ def write(self, df, table_name, temp_dir='/tmp', overwrite=False,
'minutes.\n'
'\033[1mNote:\033[0m `CartoContext.map` will not work on '
'this table until its geometries are created.'.format(
table_url='/'.join((self.creds.base_url(),
table_url=join_url((self.creds.base_url(),
'dataset',
final_table_name, )),
job_id=status.get('job_id'),
Expand All @@ -227,7 +227,7 @@ def write(self, df, table_name, temp_dir='/tmp', overwrite=False,
self.sql_client.send(query)

tqdm.write('Table successfully written to CARTO: {table_url}'.format(
table_url='/'.join((self.creds.base_url(),
table_url=join_url((self.creds.base_url(),
'dataset',
final_table_name, ))))

Expand Down Expand Up @@ -679,7 +679,7 @@ def map(self, layers=None, interactive=True,
elif not base_layers:
# default basemap is dark with labels in back
# labels will be changed if all geoms are non-point
layers.insert(0, BaseMap(source='dark', labels='back'))
layers.insert(0, BaseMap())
geoms = set()

# Setup layers
Expand Down Expand Up @@ -734,7 +734,7 @@ def map(self, layers=None, interactive=True,
options.update(self._get_bounds(nb_layers))

map_name = self._send_map_template(layers, has_zoom=has_zoom)
api_url = '/'.join((self.creds.base_url(), 'api/v1/map', ))
api_url = join_url((self.creds.base_url(), 'api/v1/map', ))

static_url = ('{api_url}/static/named/{map_name}'
'/{width}/{height}.png?{params}').format(
Expand Down
30 changes: 20 additions & 10 deletions cartoframes/layer.py
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@
import pandas as pd
import webcolors

from cartoframes.utils import cssify
from cartoframes.utils import cssify, join_url
from cartoframes.styling import BinMethod, mint, antique, get_scheme_cartocss

# colors map data layers without color specified
Expand Down Expand Up @@ -53,38 +53,48 @@ class BaseMap(AbstractLayer):
"""
is_basemap = True

def __init__(self, source='dark', labels='back', only_labels=False):
def __init__(self, source='voyager', labels='back', only_labels=False):
if labels not in ('front', 'back', None):
raise ValueError("labels must be None, 'front', or 'back'")

self.source = source
self.labels = labels
stem = 'https://cartodb-basemaps-{s}.global.ssl.fastly.net/'
if source == 'voyager':
stem += 'rastertiles'

if self.is_basic():
if only_labels:
style = source + '_only_labels'
else:
style = source + ('_all' if labels == 'back' else '_nolabels')

self.url = ('https://cartodb-basemaps-{{s}}.global.ssl.fastly.net/'
'{style}/{{z}}/{{x}}/{{y}}.png').format(style=style)
if source in ('dark', 'light', ):
label_type = '_all'
else:
label_type = '_labels_under'
style = source + (label_type if labels == 'back'
else '_nolabels')
self.url = join_url((stem,
'{style}/{{z}}/{{x}}/{{y}}.png'.format(
style=style)
))
elif self.source.startswith('http'):
# TODO: Remove this once baselayer urls can be passed in named
# map config
raise ValueError('BaseMap cannot contain a custom url at the '
'moment')
# self.url = source
else:
raise ValueError("`source` must be one of 'dark' or 'light'")
raise ValueError("`source` must be one of 'dark', 'light', or "
"'voyager'")

def is_basic(self):
"""Does BaseMap pull from CARTO default basemaps?
Returns:
bool: `True` if using a CARTO basemap (Dark Matter or Positron),
`False` otherwise.
bool: `True` if using a CARTO basemap (Dark Matter, Positron or
Voyager), `False` otherwise.
"""
return self.source in ('dark', 'light')
return self.source in ('dark', 'light', 'voyager', )


class QueryLayer(AbstractLayer):
Expand Down
3 changes: 2 additions & 1 deletion cartoframes/maps.py
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@ def get_map_name(layers, has_zoom):
num_layers = len(non_basemap_layers(layers))
has_labels = len(layers) > 1 and layers[-1].is_basemap
has_time = has_time_layer(layers)
basemap_id = dict(light=0, dark=1, voyager=2)[layers[0].source]

return ('cartoframes_ver{version}'
'_layers{layers}'
Expand All @@ -31,7 +32,7 @@ def get_map_name(layers, has_zoom):
has_time=('1' if has_time else '0'),
# TODO: Remove this once baselayer urls can be passed in named
# map config
baseid=('1' if layers[0].source == 'dark' else '0'),
baseid=basemap_id,
has_labels=('1' if has_labels else '0'),
has_zoom=('1' if has_zoom else '0')
)
Expand Down
5 changes: 5 additions & 0 deletions cartoframes/utils.py
Original file line number Diff line number Diff line change
Expand Up @@ -73,3 +73,8 @@ def norm_colname(colname):
if final_name[0].isdigit():
return '_' + final_name
return final_name


def join_url(parts):
"""join parts of URL into complete url"""
return '/'.join(s.strip('/') for s in parts)
11 changes: 6 additions & 5 deletions test/test_context.py
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@
import pandas as pd

WILL_SKIP = False
warnings.filterwarnings("ignore")


class TestCartoContext(unittest.TestCase):
Expand Down Expand Up @@ -533,21 +534,21 @@ def test_cartocontext_map_geom_type(self):
# baseid1 = dark, labels1 = labels on top in named map name
labels_polygon = cc.map(layers=Layer(self.test_read_table))
self.assertRegexpMatches(labels_polygon.__html__(),
'.*baseid1_labels1.*',
'.*baseid2_labels1.*',
msg='labels should be on top since only a '
'polygon layer is present')

# baseid1 = dark, labels0 = labels on bottom
# baseid2 = voyager, labels0 = labels on bottom
labels_point = cc.map(layers=Layer(self.test_point_table))
self.assertRegexpMatches(labels_point.__html__(),
'.*baseid1_labels0.*',
'.*baseid2_labels0.*',
msg='labels should be on bottom because a '
'point layer is present')

labels_multi = cc.map(layers=[Layer(self.test_point_table),
Layer(self.test_read_table)])
self.assertRegexpMatches(labels_multi.__html__(),
'.*baseid1_labels0.*',
'.*baseid2_labels0.*',
msg='labels should be on bottom because a '
'point layer is present')
# create a layer with points and polys, but with more polys
Expand All @@ -566,7 +567,7 @@ def test_cartocontext_map_geom_type(self):
points=self.test_point_table))
multi_geom = cc.map(layers=multi_geom_layer)
self.assertRegexpMatches(multi_geom.__html__(),
'.*baseid1_labels1.*',
'.*baseid2_labels1.*',
msg='layer has more polys than points, so it '
'should default to polys labels (on top)')

Expand Down
16 changes: 16 additions & 0 deletions test/test_layer.py
Original file line number Diff line number Diff line change
Expand Up @@ -15,18 +15,23 @@ def setUp(self):
# basemaps with baked-in labels
self.dark_map_all = BaseMap(source='dark')
self.light_map_all = BaseMap(source='light')
self.voyager_labels_under = BaseMap(source='voyager')

# basemaps with no labels
self.dark_map_no_labels = BaseMap(source='dark',
labels=None)
self.light_map_no_labels = BaseMap(source='light',
labels=None)
self.voyager_map_no_labels = BaseMap(source='voyager',
labels=None)

# labels with no basemaps
self.dark_only_labels = BaseMap(source='dark',
only_labels=True)
self.light_only_labels = BaseMap(source='light',
only_labels=True)
self.voyager_only_labels = BaseMap(source='voyager',
only_labels=True)

def test_basemap_invalid(self):
"""layer.Basemap exceptions on invalid source"""
Expand All @@ -53,23 +58,34 @@ def test_basemap_source(self):
self.assertEqual(self.light_map_all.url,
'https://cartodb-basemaps-{s}.global.ssl.fastly.net/'
'light_all/{z}/{x}/{y}.png')
self.assertEqual(self.voyager_labels_under.url,
'https://cartodb-basemaps-{s}.global.ssl.fastly.net/'
'rastertiles/voyager_labels_under/{z}/{x}/{y}.png')
self.assertEqual(self.dark_map_no_labels.url,
'https://cartodb-basemaps-{s}.global.ssl.fastly.net/'
'dark_nolabels/{z}/{x}/{y}.png')
self.assertEqual(self.light_map_no_labels.url,
'https://cartodb-basemaps-{s}.global.ssl.fastly.net/'
'light_nolabels/{z}/{x}/{y}.png')
self.assertEqual(self.voyager_map_no_labels.url,
'https://cartodb-basemaps-{s}.global.ssl.fastly.net/'
'rastertiles/voyager_nolabels/{z}/{x}/{y}.png')
self.assertEqual(self.light_only_labels.url,
'https://cartodb-basemaps-{s}.global.ssl.fastly.net/'
'light_only_labels/{z}/{x}/{y}.png')
self.assertEqual(self.dark_only_labels.url,
'https://cartodb-basemaps-{s}.global.ssl.fastly.net/'
'dark_only_labels/{z}/{x}/{y}.png')
self.assertEqual(self.voyager_only_labels.url,
'https://cartodb-basemaps-{s}.global.ssl.fastly.net/'
'rastertiles/voyager_only_labels/{z}/{x}/{y}.png')

# ensure self.is_basic() works as intended
self.assertTrue(self.light_map_all.is_basic(),
msg='is a basic carto basemap')
self.assertTrue(self.dark_map_all.is_basic())
self.assertTrue(self.voyager_labels_under.is_basic(),
msg='is a basic carto basemap')


class TestQueryLayer(unittest.TestCase):
Expand Down

0 comments on commit 9665543

Please sign in to comment.