Skip to content

Explicit coordinate validation #1090

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

Merged
merged 2 commits into from
Mar 19, 2019
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
14 changes: 7 additions & 7 deletions examples/Plugins.ipynb

Large diffs are not rendered by default.

1 change: 0 additions & 1 deletion folium/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,6 @@
from __future__ import (absolute_import, division, print_function)

import sys
import warnings

import branca
from branca.colormap import (ColorMap, LinearColormap, StepColormap)
Expand Down
7 changes: 4 additions & 3 deletions folium/features.py
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@
from folium.folium import Map
from folium.map import (FeatureGroup, Icon, Layer, Marker, Tooltip)
from folium.utilities import (
_iter_tolist,
validate_locations,
_parse_size,
get_bounds,
image_to_url,
Expand All @@ -45,7 +45,7 @@ class RegularPolygonMarker(Marker):

Parameters
----------
location: tuple or list, default None
location: tuple or list
Latitude and Longitude of Marker (Northing, Easting)
number_of_sides: int, default 4
Number of polygon sides
Expand Down Expand Up @@ -75,7 +75,7 @@ class RegularPolygonMarker(Marker):
def __init__(self, location, number_of_sides=4, rotation=0, radius=15,
popup=None, tooltip=None, **kwargs):
super(RegularPolygonMarker, self).__init__(
_iter_tolist(location),
location,
popup=popup, tooltip=tooltip
)
self._name = 'RegularPolygonMarker'
Expand Down Expand Up @@ -1357,6 +1357,7 @@ def __init__(self, positions, colors, colormap=None, nb_steps=12,
weight=None, opacity=None, **kwargs):
super(ColorLine, self).__init__(**kwargs)
self._name = 'ColorLine'
positions = validate_locations(positions)

if colormap is None:
cm = LinearColormap(['green', 'yellow', 'red'],
Expand Down
4 changes: 2 additions & 2 deletions folium/folium.py
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@

from folium.map import FitBounds
from folium.raster_layers import TileLayer
from folium.utilities import _parse_size, _tmp_html, _validate_location
from folium.utilities import _parse_size, _tmp_html, validate_location

from jinja2 import Environment, PackageLoader, Template

Expand Down Expand Up @@ -243,7 +243,7 @@ def __init__(self, location=None, width='100%', height='100%',
self.location = [0, 0]
self.zoom_start = 1
else:
self.location = _validate_location(location)
self.location = validate_location(location)
self.zoom_start = zoom_start

Figure().add_child(self)
Expand Down
34 changes: 13 additions & 21 deletions folium/map.py
Original file line number Diff line number Diff line change
Expand Up @@ -11,14 +11,9 @@

import warnings

from branca.element import CssLink, Element, Figure, Html, JavascriptLink, MacroElement # noqa
from branca.element import Element, Figure, Html, MacroElement

from folium.utilities import (
_validate_coordinates,
camelize,
get_bounds,
parse_options,
)
from folium.utilities import validate_location, camelize, parse_options

from jinja2 import Template

Expand Down Expand Up @@ -241,7 +236,7 @@ class Marker(MacroElement):

Parameters
----------
location: tuple or list, default None
location: tuple or list
Latitude and Longitude of Marker (Northing, Easting)
popup: string or folium.Popup, default None
Label for the Marker; either an escaped HTML string to initialize
Expand Down Expand Up @@ -278,30 +273,27 @@ def __init__(self, location, popup=None, tooltip=None, icon=None,
draggable=False, **kwargs):
super(Marker, self).__init__()
self._name = 'Marker'
self.location = _validate_coordinates(location)
self.location = validate_location(location)
self.options = parse_options(
draggable=draggable or None,
autoPan=draggable or None,
**kwargs
)
if icon is not None:
self.add_child(icon)
if isinstance(popup, text_type) or isinstance(popup, binary_type):
self.add_child(Popup(popup))
elif popup is not None:
self.add_child(popup)
if isinstance(tooltip, Tooltip):
self.add_child(tooltip)
elif tooltip is not None:
self.add_child(Tooltip(tooltip.__str__()))
if popup is not None:
self.add_child(popup if isinstance(popup, Popup)
else Popup(str(popup)))
if tooltip is not None:
self.add_child(tooltip if isinstance(tooltip, Tooltip)
else Tooltip(str(tooltip)))

def _get_self_bounds(self):
"""
Computes the bounds of the object itself (not including it's children)
in the form [[lat_min, lon_min], [lat_max, lon_max]].
"""Computes the bounds of the object itself.

Because a marker has only single coordinates, we repeat them.
"""
return get_bounds(self.location)
return [self.location, self.location]


class Popup(Element):
Expand Down
9 changes: 4 additions & 5 deletions folium/plugins/antpath.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,13 +4,12 @@

from branca.element import Figure, JavascriptLink

from folium import Marker
from folium.vector_layers import path_options
from folium.vector_layers import path_options, BaseMultiLocation

from jinja2 import Template


class AntPath(Marker):
class AntPath(BaseMultiLocation):
"""
Class for drawing AntPath polyline overlays on a map.

Expand All @@ -34,15 +33,15 @@ class AntPath(Marker):
_template = Template(u"""
{% macro script(this, kwargs) %}
{{ this.get_name() }} = L.polyline.antPath(
{{ this.location|tojson }},
{{ this.locations|tojson }},
{{ this.options|tojson }}
).addTo({{this._parent.get_name()}});
{% endmacro %}
""")

def __init__(self, locations, popup=None, tooltip=None, **kwargs):
super(AntPath, self).__init__(
location=locations,
locations,
popup=popup,
tooltip=tooltip,
)
Expand Down
4 changes: 2 additions & 2 deletions folium/plugins/boat_marker.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@
from branca.element import Figure, JavascriptLink

from folium.map import Marker
from folium.utilities import _validate_location, parse_options
from folium.utilities import parse_options

from jinja2 import Template

Expand Down Expand Up @@ -50,7 +50,7 @@ class BoatMarker(Marker):
def __init__(self, location, popup=None, icon=None,
heading=0, wind_heading=None, wind_speed=0, **kwargs):
super(BoatMarker, self).__init__(
_validate_location(location),
location,
popup=popup,
icon=icon
)
Expand Down
31 changes: 17 additions & 14 deletions folium/plugins/fast_marker_cluster.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
from __future__ import (absolute_import, division, print_function)

from folium.plugins.marker_cluster import MarkerCluster
from folium.utilities import _validate_coordinates
from folium.utilities import validate_location, if_pandas_df_convert_to_numpy

from jinja2 import Template

Expand All @@ -22,14 +22,15 @@ class FastMarkerCluster(MarkerCluster):

Parameters
----------
data: list
List of list of shape [[], []]. Data points should be of
the form [[lat, lng]].
callback: string, default None
data: list of list with values
List of list of shape [[lat, lon], [lat, lon], etc.]
When you use a custom callback you could add more values after the
lat and lon. E.g. [[lat, lon, 'red'], [lat, lon, 'blue']]
callback: string, optional
A string representation of a valid Javascript function
that will be passed a lat, lon coordinate pair. See the
that will be passed each row in data. See the
FasterMarkerCluster for an example of a custom callback.
name : string, default None
name : string, optional
The name of the Layer, as it will appear in LayerControls.
overlay : bool, default True
Adds the layer as an optional overlay (True) or the base layer (False).
Expand All @@ -38,16 +39,16 @@ class FastMarkerCluster(MarkerCluster):
show: bool, default True
Whether the layer will be shown on opening (only for overlays).
**kwargs
Additional arguments are passed to Leaflet.markercluster. See
https://github.com/Leaflet/Leaflet.markercluster for options.
Additional arguments are passed to Leaflet.markercluster options. See
https://github.com/Leaflet/Leaflet.markercluster

"""
_template = Template(u"""
{% macro script(this, kwargs) %}
var {{ this.get_name() }} = (function(){
{{ this._callback }}
{{ this.callback }}

var data = {{ this._data|tojson }};
var data = {{ this.data|tojson }};
var cluster = L.markerClusterGroup({{ this.options|tojson }});

for (var i = 0; i < data.length; i++) {
Expand All @@ -69,15 +70,17 @@ def __init__(self, data, callback=None, options=None,
control=control, show=show,
**kwargs)
self._name = 'FastMarkerCluster'
self._data = _validate_coordinates(data)
data = if_pandas_df_convert_to_numpy(data)
self.data = [[*validate_location(row[:2]), *row[2:]] # noqa: E999
for row in data]

if callback is None:
self._callback = """
self.callback = """
var callback = function (row) {
var icon = L.AwesomeMarkers.icon();
var marker = L.marker(new L.LatLng(row[0], row[1]));
marker.setIcon(icon);
return marker;
};"""
else:
self._callback = 'var callback = {};'.format(callback)
self.callback = 'var callback = {};'.format(callback)
16 changes: 9 additions & 7 deletions folium/plugins/heat_map.py
Original file line number Diff line number Diff line change
Expand Up @@ -6,15 +6,17 @@

from folium.map import Layer
from folium.utilities import (
_isnan,
_iter_tolist,
none_max,
none_min,
parse_options,
if_pandas_df_convert_to_numpy,
validate_location,
)

from jinja2 import Template

import numpy as np


class HeatMap(Layer):
"""
Expand Down Expand Up @@ -61,12 +63,12 @@ def __init__(self, data, name=None, min_opacity=0.5, max_zoom=18,
overlay=True, control=True, show=True, **kwargs):
super(HeatMap, self).__init__(name=name, overlay=overlay,
control=control, show=show)
data = _iter_tolist(data)
if _isnan(data):
raise ValueError('data cannot contain NaNs, '
'got:\n{!r}'.format(data))
self._name = 'HeatMap'
self.data = [[x for x in line] for line in data]
data = if_pandas_df_convert_to_numpy(data)
self.data = [[*validate_location(line[:2]), *line[2:]] # noqa: E999
for line in data]
if np.any(np.isnan(self.data)):
raise ValueError('data may not contain NaNs.')
self.options = parse_options(
min_opacity=min_opacity,
max_zoom=max_zoom,
Expand Down
22 changes: 7 additions & 15 deletions folium/plugins/marker_cluster.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,8 +4,8 @@

from branca.element import CssLink, Figure, JavascriptLink

from folium.map import Icon, Layer, Marker, Popup
from folium.utilities import parse_options
from folium.map import Layer, Marker
from folium.utilities import validate_locations, parse_options

from jinja2 import Template

Expand Down Expand Up @@ -71,25 +71,17 @@ def __init__(self, locations=None, popups=None, icons=None, name=None,
self._name = 'MarkerCluster'

if locations is not None:
if popups is None:
popups = [None] * len(locations)
if icons is None:
icons = [None] * len(locations)
for location, popup, icon in zip(locations, popups, icons):
p = popup if self._validate(popup, Popup) else Popup(popup)
i = icon if self._validate(icon, Icon) else Icon(icon)
self.add_child(Marker(location, popup=p, icon=i))
locations = validate_locations(locations)
for i, location in enumerate(locations):
self.add_child(Marker(location,
popup=popups and popups[i],
icon=icons and icons[i]))

self.options = parse_options(**kwargs)
if icon_create_function is not None:
assert isinstance(icon_create_function, str)
self.icon_create_function = icon_create_function

@staticmethod
def _validate(obj, cls):
"""Check whether the given object is from the given class or is None."""
return True if obj is None or isinstance(obj, cls) else False

def render(self, **kwargs):
super(MarkerCluster, self).render(**kwargs)

Expand Down
Loading