Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

adds voyager basemaps as default basemap #241

Merged
merged 2 commits into from
Oct 11, 2017
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
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