From c50ca82b60aa9fc8e5fc6388f1c8b01670cfbebc Mon Sep 17 00:00:00 2001 From: Frank <33519926+Conengmo@users.noreply.github.com> Date: Sun, 29 Dec 2024 12:00:02 +0100 Subject: [PATCH 01/13] remove render() return types --- folium/elements.py | 2 +- folium/features.py | 12 ++++++------ folium/folium.py | 2 +- folium/map.py | 6 +++--- folium/raster_layers.py | 2 +- 5 files changed, 12 insertions(+), 12 deletions(-) diff --git a/folium/elements.py b/folium/elements.py index aa1dbd8846..3dbbc82ff1 100644 --- a/folium/elements.py +++ b/folium/elements.py @@ -12,7 +12,7 @@ class JSCSSMixin(Element): default_js: List[Tuple[str, str]] = [] default_css: List[Tuple[str, str]] = [] - def render(self, **kwargs) -> None: + def render(self, **kwargs): figure = self.get_root() assert isinstance( figure, Figure diff --git a/folium/features.py b/folium/features.py index cba87e8eff..84c8748744 100644 --- a/folium/features.py +++ b/folium/features.py @@ -165,7 +165,7 @@ def __init__( self.top = _parse_size(top) self.position = position - def render(self, **kwargs) -> None: + def render(self, **kwargs): """Renders the HTML representation of the element.""" super().render(**kwargs) @@ -284,7 +284,7 @@ def __init__( self.top = _parse_size(top) self.position = position - def render(self, **kwargs) -> None: + def render(self, **kwargs): """Renders the HTML representation of the element.""" self._parent.html.add_child( Element( @@ -820,7 +820,7 @@ def _get_self_bounds(self) -> List[List[Optional[float]]]: """ return get_bounds(self.data, lonlat=True) - def render(self, **kwargs) -> None: + def render(self, **kwargs): self.parent_map = get_obj_in_upper_tree(self, Map) # Need at least one feature, otherwise style mapping fails if (self.style or self.highlight) and self.data["features"]: @@ -1041,7 +1041,7 @@ def recursive_get(data, keys): self.style_function(feature) ) # noqa - def render(self, **kwargs) -> None: + def render(self, **kwargs): """Renders the HTML representation of the element.""" self.style_data() super().render(**kwargs) @@ -1160,7 +1160,7 @@ def warn_for_geometry_collections(self) -> None: UserWarning, ) - def render(self, **kwargs) -> None: + def render(self, **kwargs): """Renders the HTML representation of the element.""" figure = self.get_root() if isinstance(self._parent, GeoJson): @@ -1657,7 +1657,7 @@ def _get_by_key(cls, obj: Union[dict, list], key: str) -> Union[float, str, None else: return value - def render(self, **kwargs) -> None: + def render(self, **kwargs): """Render the GeoJson/TopoJson and color scale objects.""" if self.color_scale: # ColorMap needs Map as its parent diff --git a/folium/folium.py b/folium/folium.py index e48049371d..12510ecb43 100644 --- a/folium/folium.py +++ b/folium/folium.py @@ -377,7 +377,7 @@ def _repr_png_(self) -> Optional[bytes]: return None return self._to_png() - def render(self, **kwargs) -> None: + def render(self, **kwargs): """Renders the HTML representation of the element.""" figure = self.get_root() assert isinstance( diff --git a/folium/map.py b/folium/map.py index 758e64153a..634603e0c4 100644 --- a/folium/map.py +++ b/folium/map.py @@ -221,7 +221,7 @@ def reset(self) -> None: self.base_layers = OrderedDict() self.overlays = OrderedDict() - def render(self, **kwargs) -> None: + def render(self, **kwargs): """Renders the HTML representation of the element.""" self.reset() for item in self._parent._children.values(): @@ -404,7 +404,7 @@ def _get_self_bounds(self) -> List[List[float]]: assert self.location is not None return [self.location, self.location] - def render(self) -> None: + def render(self): if self.location is None: raise ValueError( f"{self._name} location must be assigned when added directly to map." @@ -492,7 +492,7 @@ def __init__( **kwargs, ) - def render(self, **kwargs) -> None: + def render(self, **kwargs): """Renders the HTML representation of the element.""" for name, child in self._children.items(): child.render(**kwargs) diff --git a/folium/raster_layers.py b/folium/raster_layers.py index bbb2f0b9f5..7b0ca2b916 100644 --- a/folium/raster_layers.py +++ b/folium/raster_layers.py @@ -319,7 +319,7 @@ def __init__( self.url = image_to_url(image, origin=origin, colormap=colormap) - def render(self, **kwargs) -> None: + def render(self, **kwargs): super().render() figure = self.get_root() From 188bd8502331e851209ec96b3dc0bafac0fe30cb Mon Sep 17 00:00:00 2001 From: Frank <33519926+Conengmo@users.noreply.github.com> Date: Sun, 29 Dec 2024 12:10:13 +0100 Subject: [PATCH 02/13] fix TypeBounds --- folium/map.py | 2 +- folium/utilities.py | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/folium/map.py b/folium/map.py index 634603e0c4..4db0e4cce2 100644 --- a/folium/map.py +++ b/folium/map.py @@ -396,7 +396,7 @@ def __init__( tooltip if isinstance(tooltip, Tooltip) else Tooltip(str(tooltip)) ) - def _get_self_bounds(self) -> List[List[float]]: + def _get_self_bounds(self) -> TypeBounds: """Computes the bounds of the object itself. Because a marker has only single coordinates, we repeat them. diff --git a/folium/utilities.py b/folium/utilities.py index a730417c38..4225d1cc0c 100644 --- a/folium/utilities.py +++ b/folium/utilities.py @@ -49,7 +49,7 @@ TypePathOptions = Union[bool, str, float, None] -TypeBounds = Sequence[Sequence[float]] +TypeBounds = List[List[Optional[float]]] _VALID_URLS = set(uses_relative + uses_netloc + uses_params) From 583da1c72ccf172ce5f2c1150adc791b7c65e260 Mon Sep 17 00:00:00 2001 From: Frank <33519926+Conengmo@users.noreply.github.com> Date: Sun, 29 Dec 2024 12:10:57 +0100 Subject: [PATCH 03/13] missing return statement --- folium/plugins/overlapping_marker_spiderfier.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/folium/plugins/overlapping_marker_spiderfier.py b/folium/plugins/overlapping_marker_spiderfier.py index 70fcea4129..e6335aaf40 100644 --- a/folium/plugins/overlapping_marker_spiderfier.py +++ b/folium/plugins/overlapping_marker_spiderfier.py @@ -92,7 +92,7 @@ def add_to( ) -> Element: self._parent = parent self.markers = self._get_all_markers(parent) - super().add_to(parent, name=name, index=index) + return super().add_to(parent, name=name, index=index) def _get_all_markers(self, element: Element) -> list: markers = [] From 0764be3a2a59af2ce72ca15b0167359a90516d0e Mon Sep 17 00:00:00 2001 From: Frank <33519926+Conengmo@users.noreply.github.com> Date: Sun, 29 Dec 2024 12:24:50 +0100 Subject: [PATCH 04/13] split TypeBounds in input and return types --- folium/features.py | 4 ++-- folium/map.py | 4 ++-- folium/raster_layers.py | 6 +++--- folium/utilities.py | 3 ++- 4 files changed, 9 insertions(+), 8 deletions(-) diff --git a/folium/features.py b/folium/features.py index 84c8748744..2f06195f12 100644 --- a/folium/features.py +++ b/folium/features.py @@ -32,7 +32,7 @@ none_max, none_min, remove_empty, - validate_locations, + validate_locations, TypeBoundsReturn, ) from folium.vector_layers import Circle, CircleMarker, PolyLine, path_options @@ -1046,7 +1046,7 @@ def render(self, **kwargs): self.style_data() super().render(**kwargs) - def get_bounds(self) -> List[List[float]]: + def get_bounds(self) -> TypeBoundsReturn: """ Computes the bounds of the object itself (not including it's children) in the form [[lat_min, lon_min], [lat_max, lon_max]] diff --git a/folium/map.py b/folium/map.py index 4db0e4cce2..7ba477784f 100644 --- a/folium/map.py +++ b/folium/map.py @@ -18,7 +18,7 @@ escape_backticks, parse_options, remove_empty, - validate_location, + validate_location, TypeBoundsReturn, ) if TYPE_CHECKING: @@ -396,7 +396,7 @@ def __init__( tooltip if isinstance(tooltip, Tooltip) else Tooltip(str(tooltip)) ) - def _get_self_bounds(self) -> TypeBounds: + def _get_self_bounds(self) -> TypeBoundsReturn: """Computes the bounds of the object itself. Because a marker has only single coordinates, we repeat them. diff --git a/folium/raster_layers.py b/folium/raster_layers.py index 7b0ca2b916..83bac7dfab 100644 --- a/folium/raster_layers.py +++ b/folium/raster_layers.py @@ -16,7 +16,7 @@ image_to_url, mercator_transform, parse_options, - remove_empty, + remove_empty, TypeBoundsReturn, ) @@ -344,7 +344,7 @@ def render(self, **kwargs): Element(pixelated), name="leaflet-image-layer" ) # noqa - def _get_self_bounds(self) -> TypeBounds: + def _get_self_bounds(self) -> TypeBoundsReturn: """ Computes the bounds of the object itself (not including it's children) in the form [[lat_min, lon_min], [lat_max, lon_max]]. @@ -411,7 +411,7 @@ def __init__( self.bounds = bounds self.options = remove_empty(autoplay=autoplay, loop=loop, **kwargs) - def _get_self_bounds(self) -> TypeBounds: + def _get_self_bounds(self) -> TypeBoundsReturn: """ Computes the bounds of the object itself (not including it's children) in the form [[lat_min, lon_min], [lat_max, lon_max]] diff --git a/folium/utilities.py b/folium/utilities.py index 4225d1cc0c..ef87eee292 100644 --- a/folium/utilities.py +++ b/folium/utilities.py @@ -49,7 +49,8 @@ TypePathOptions = Union[bool, str, float, None] -TypeBounds = List[List[Optional[float]]] +TypeBounds = Sequence[Sequence[float]] +TypeBoundsReturn = List[List[Optional[float]]] _VALID_URLS = set(uses_relative + uses_netloc + uses_params) From 33dcd98154d821014aec331e55bb1c73f84d090d Mon Sep 17 00:00:00 2001 From: Frank <33519926+Conengmo@users.noreply.github.com> Date: Sun, 29 Dec 2024 12:37:30 +0100 Subject: [PATCH 05/13] deal with bounds from args to return --- folium/map.py | 4 ++-- folium/raster_layers.py | 12 ++++++------ folium/utilities.py | 4 ++++ tests/test_utilities.py | 16 +++++++++++++++- 4 files changed, 27 insertions(+), 9 deletions(-) diff --git a/folium/map.py b/folium/map.py index 7ba477784f..41b76f7b38 100644 --- a/folium/map.py +++ b/folium/map.py @@ -5,7 +5,7 @@ import warnings from collections import OrderedDict -from typing import TYPE_CHECKING, List, Optional, Sequence, Union +from typing import TYPE_CHECKING, List, Optional, Sequence, Union, cast from branca.element import Element, Figure, Html, MacroElement @@ -402,7 +402,7 @@ def _get_self_bounds(self) -> TypeBoundsReturn: Because a marker has only single coordinates, we repeat them. """ assert self.location is not None - return [self.location, self.location] + return cast(TypeBoundsReturn, [self.location, self.location]) def render(self): if self.location is None: diff --git a/folium/raster_layers.py b/folium/raster_layers.py index 83bac7dfab..787ca7f973 100644 --- a/folium/raster_layers.py +++ b/folium/raster_layers.py @@ -3,7 +3,7 @@ """ -from typing import Any, Callable, Optional, Union +from typing import Any, Callable, Optional, Union, cast import xyzservices from branca.element import Element, Figure @@ -16,7 +16,7 @@ image_to_url, mercator_transform, parse_options, - remove_empty, TypeBoundsReturn, + remove_empty, TypeBoundsReturn, normalize_bounds_type, ) @@ -246,7 +246,7 @@ class ImageOverlay(Layer): * If string, it will be written directly in the output file. * If file, it's content will be converted as embedded in the output file. * If array-like, it will be converted to PNG base64 string and embedded in the output. - bounds: list + bounds: list/tuple of list/tuple of float Image bounds on the map in the form [[lat_min, lon_min], [lat_max, lon_max]] opacity: float, default Leaflet's default (1.0) @@ -350,7 +350,7 @@ def _get_self_bounds(self) -> TypeBoundsReturn: in the form [[lat_min, lon_min], [lat_max, lon_max]]. """ - return self.bounds + return normalize_bounds_type(self.bounds) class VideoOverlay(Layer): @@ -361,7 +361,7 @@ class VideoOverlay(Layer): ---------- video_url: str URL of the video - bounds: list + bounds: list/tuple of list/tuple of float Video bounds on the map in the form [[lat_min, lon_min], [lat_max, lon_max]] autoplay: bool, default True @@ -417,4 +417,4 @@ def _get_self_bounds(self) -> TypeBoundsReturn: in the form [[lat_min, lon_min], [lat_max, lon_max]] """ - return self.bounds + return normalize_bounds_type(self.bounds) diff --git a/folium/utilities.py b/folium/utilities.py index ef87eee292..b45b3c1235 100644 --- a/folium/utilities.py +++ b/folium/utilities.py @@ -326,6 +326,10 @@ def get_bounds( return bounds +def normalize_bounds_type(bounds: TypeBounds) -> TypeBoundsReturn: + return [[float(x) if x is not None else None for x in y] for y in bounds] + + def camelize(key: str) -> str: """Convert a python_style_variable_name to lowerCamelCase. diff --git a/tests/test_utilities.py b/tests/test_utilities.py index 2218bba733..1fe2682a49 100644 --- a/tests/test_utilities.py +++ b/tests/test_utilities.py @@ -16,7 +16,7 @@ parse_options, validate_location, validate_locations, - validate_multi_locations, + validate_multi_locations, normalize_bounds_type, ) @@ -133,6 +133,20 @@ def test_if_pandas_df_convert_to_numpy(): assert if_pandas_df_convert_to_numpy(expected) is expected +@pytest.mark.parametrize( + "bounds, expected", + [ + ([[1, 2], [3, 4]], [[1.0, 2.0], [3.0, 4.0]]), + ([[None, 2], [3, None]], [[None, 2.0], [3.0, None]]), + ([[1.1, 2.2], [3.3, 4.4]], [[1.1, 2.2], [3.3, 4.4]]), + ([[None, None], [None, None]], [[None, None], [None, None]]), + ([[0, -1], [-2, 3]], [[0.0, -1.0], [-2.0, 3.0]]), + ], +) +def test_normalize_bounds_type(bounds, expected): + assert normalize_bounds_type(bounds) == expected + + def test_camelize(): assert camelize("variable_name") == "variableName" assert camelize("variableName") == "variableName" From 93ef618522897067a5688529546c07aefbac035b Mon Sep 17 00:00:00 2001 From: Frank <33519926+Conengmo@users.noreply.github.com> Date: Sun, 29 Dec 2024 13:04:05 +0100 Subject: [PATCH 06/13] fix VegaLite typing --- folium/features.py | 42 +++++++++++++++++++++++------------------- folium/utilities.py | 6 +++++- 2 files changed, 28 insertions(+), 20 deletions(-) diff --git a/folium/features.py b/folium/features.py index 2f06195f12..0c2d860d81 100644 --- a/folium/features.py +++ b/folium/features.py @@ -12,7 +12,7 @@ import numpy as np import requests from branca.colormap import ColorMap, LinearColormap, StepColormap -from branca.element import Element, Figure, Html, IFrame, JavascriptLink, MacroElement +from branca.element import Element, Figure, Html, IFrame, JavascriptLink, MacroElement, Div from branca.utilities import color_brewer from folium.elements import JSCSSMixin @@ -32,7 +32,7 @@ none_max, none_min, remove_empty, - validate_locations, TypeBoundsReturn, + validate_locations, TypeBoundsReturn, TypeContainer, ) from folium.vector_layers import Circle, CircleMarker, PolyLine, path_options @@ -286,7 +286,11 @@ def __init__( def render(self, **kwargs): """Renders the HTML representation of the element.""" - self._parent.html.add_child( + parent = self._parent + if not isinstance(parent, (Figure, Div, Popup)): + raise TypeError("VegaLite elements can only be added to a Figure, Div, or Popup") + + parent.html.add_child( Element( Template( """ @@ -331,7 +335,7 @@ def render(self, **kwargs): embed_vegalite = embed_mapping.get( self.vegalite_major_version, self._embed_vegalite_v2 ) - embed_vegalite(figure) + embed_vegalite(figure=figure, parent=parent) @property def vegalite_major_version(self) -> Optional[int]: @@ -342,8 +346,8 @@ def vegalite_major_version(self) -> Optional[int]: return int(schema.split("/")[-1].split(".")[0].lstrip("v")) - def _embed_vegalite_v5(self, figure: Figure) -> None: - self._vega_embed() + def _embed_vegalite_v5(self, figure: Figure, parent: TypeContainer) -> None: + self._vega_embed(parent=parent) figure.header.add_child( JavascriptLink("https://cdn.jsdelivr.net/npm//vega@5"), name="vega" @@ -356,8 +360,8 @@ def _embed_vegalite_v5(self, figure: Figure) -> None: name="vega-embed", ) - def _embed_vegalite_v4(self, figure: Figure) -> None: - self._vega_embed() + def _embed_vegalite_v4(self, figure: Figure, parent: TypeContainer) -> None: + self._vega_embed(parent=parent) figure.header.add_child( JavascriptLink("https://cdn.jsdelivr.net/npm//vega@5"), name="vega" @@ -370,8 +374,8 @@ def _embed_vegalite_v4(self, figure: Figure) -> None: name="vega-embed", ) - def _embed_vegalite_v3(self, figure: Figure) -> None: - self._vega_embed() + def _embed_vegalite_v3(self, figure: Figure, parent: TypeContainer) -> None: + self._vega_embed(parent=parent) figure.header.add_child( JavascriptLink("https://cdn.jsdelivr.net/npm/vega@4"), name="vega" @@ -384,8 +388,8 @@ def _embed_vegalite_v3(self, figure: Figure) -> None: name="vega-embed", ) - def _embed_vegalite_v2(self, figure: Figure) -> None: - self._vega_embed() + def _embed_vegalite_v2(self, figure: Figure, parent: TypeContainer) -> None: + self._vega_embed(parent=parent) figure.header.add_child( JavascriptLink("https://cdn.jsdelivr.net/npm/vega@3"), name="vega" @@ -398,8 +402,8 @@ def _embed_vegalite_v2(self, figure: Figure) -> None: name="vega-embed", ) - def _vega_embed(self) -> None: - self._parent.script.add_child( + def _vega_embed(self, parent: TypeContainer) -> None: + parent.script.add_child( Element( Template( """ @@ -412,8 +416,8 @@ def _vega_embed(self) -> None: name=self.get_name(), ) - def _embed_vegalite_v1(self, figure: Figure) -> None: - self._parent.script.add_child( + def _embed_vegalite_v1(self, figure: Figure, parent: TypeContainer) -> None: + parent.script.add_child( Element( Template( """ @@ -436,19 +440,19 @@ def _embed_vegalite_v1(self, figure: Figure) -> None: figure.header.add_child( JavascriptLink("https://cdnjs.cloudflare.com/ajax/libs/vega/2.6.5/vega.js"), name="vega", - ) # noqa + ) figure.header.add_child( JavascriptLink( "https://cdnjs.cloudflare.com/ajax/libs/vega-lite/1.3.1/vega-lite.js" ), name="vega-lite", - ) # noqa + ) figure.header.add_child( JavascriptLink( "https://cdnjs.cloudflare.com/ajax/libs/vega-embed/2.2.0/vega-embed.js" ), name="vega-embed", - ) # noqa + ) class GeoJson(Layer): diff --git a/folium/utilities.py b/folium/utilities.py index b45b3c1235..cbe2e2879d 100644 --- a/folium/utilities.py +++ b/folium/utilities.py @@ -24,7 +24,9 @@ from urllib.parse import urlparse, uses_netloc, uses_params, uses_relative import numpy as np -from branca.element import Element, Figure +from folium import Popup + +from branca.element import Element, Figure, Div # import here for backwards compatibility from branca.utilities import ( # noqa F401 @@ -52,6 +54,8 @@ TypeBounds = Sequence[Sequence[float]] TypeBoundsReturn = List[List[Optional[float]]] +TypeContainer = Union[Figure, Div, Popup] + _VALID_URLS = set(uses_relative + uses_netloc + uses_params) _VALID_URLS.discard("") From add7847d202630deb69bd59a59516866622cb70c Mon Sep 17 00:00:00 2001 From: Frank <33519926+Conengmo@users.noreply.github.com> Date: Sun, 29 Dec 2024 13:05:49 +0100 Subject: [PATCH 07/13] geojsondetail assert parent is geojson --- folium/features.py | 1 + 1 file changed, 1 insertion(+) diff --git a/folium/features.py b/folium/features.py index 0c2d860d81..3469a11b70 100644 --- a/folium/features.py +++ b/folium/features.py @@ -1150,6 +1150,7 @@ def __init__( def warn_for_geometry_collections(self) -> None: """Checks for GeoJson GeometryCollection features to warn user about incompatibility.""" + assert isinstance(self._parent, GeoJson) geom_collections = [ feature.get("properties") if feature.get("properties") is not None else key for key, feature in enumerate(self._parent.data["features"]) From f21926d85b8ea3003ef3797ad1ba99808b251bd1 Mon Sep 17 00:00:00 2001 From: Frank <33519926+Conengmo@users.noreply.github.com> Date: Sun, 29 Dec 2024 13:08:41 +0100 Subject: [PATCH 08/13] bin_edges in choropleth --- folium/features.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/folium/features.py b/folium/features.py index 3469a11b70..790a5907e7 100644 --- a/folium/features.py +++ b/folium/features.py @@ -1570,7 +1570,7 @@ def __init__( color_range = color_brewer(fill_color, n=nb_bins) self.color_scale = StepColormap( color_range, - index=bin_edges, + index=list(bin_edges), vmin=bins_min, vmax=bins_max, caption=legend_name, From 3a681da1cc8cff9333b465ab30bc5bb5d85fbee5 Mon Sep 17 00:00:00 2001 From: Frank <33519926+Conengmo@users.noreply.github.com> Date: Sun, 29 Dec 2024 13:09:31 +0100 Subject: [PATCH 09/13] geojson/topojson in choropleth --- folium/features.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/folium/features.py b/folium/features.py index 790a5907e7..aec10a92fe 100644 --- a/folium/features.py +++ b/folium/features.py @@ -1630,7 +1630,7 @@ def highlight_function(x): return {"weight": line_weight + 2, "fillOpacity": fill_opacity + 0.2} if topojson: - self.geojson = TopoJson( + self.geojson: Union[TopoJson, GeoJson] = TopoJson( geo_data, topojson, style_function=style_function, From f006bfad668658709467d5c032e2c2a4f619608e Mon Sep 17 00:00:00 2001 From: Frank <33519926+Conengmo@users.noreply.github.com> Date: Sun, 29 Dec 2024 13:12:21 +0100 Subject: [PATCH 10/13] colormap type in ColorLine --- folium/features.py | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/folium/features.py b/folium/features.py index aec10a92fe..0220c1ac2c 100644 --- a/folium/features.py +++ b/folium/features.py @@ -1968,8 +1968,11 @@ def __init__( vmin=min(colors), vmax=max(colors), ).to_step(nb_steps) - else: + elif isinstance(colormap, StepColormap): cm = colormap + else: + raise TypeError(f"Unexpected type for argument `colormap`: {type(colormap)}") + out: Dict[str, List[List[List[float]]]] = {} for (lat1, lng1), (lat2, lng2), color in zip(coords[:-1], coords[1:], colors): out.setdefault(cm(color), []).append([[lat1, lng1], [lat2, lng2]]) From f329d81f518f09d471e692edd7c5a8f601ee14a1 Mon Sep 17 00:00:00 2001 From: Frank <33519926+Conengmo@users.noreply.github.com> Date: Sun, 29 Dec 2024 13:12:42 +0100 Subject: [PATCH 11/13] ruff check --- folium/features.py | 6 ++++-- folium/map.py | 5 +++-- folium/raster_layers.py | 6 ++++-- folium/utilities.py | 6 +++--- tests/test_utilities.py | 3 ++- 5 files changed, 16 insertions(+), 10 deletions(-) diff --git a/folium/features.py b/folium/features.py index 0220c1ac2c..468bf8292b 100644 --- a/folium/features.py +++ b/folium/features.py @@ -12,7 +12,7 @@ import numpy as np import requests from branca.colormap import ColorMap, LinearColormap, StepColormap -from branca.element import Element, Figure, Html, IFrame, JavascriptLink, MacroElement, Div +from branca.element import Div, Element, Figure, Html, IFrame, JavascriptLink, MacroElement from branca.utilities import color_brewer from folium.elements import JSCSSMixin @@ -20,6 +20,8 @@ from folium.map import FeatureGroup, Icon, Layer, Marker, Popup, Tooltip from folium.template import Template from folium.utilities import ( + TypeBoundsReturn, + TypeContainer, TypeJsonValue, TypeLine, TypePathOptions, @@ -32,7 +34,7 @@ none_max, none_min, remove_empty, - validate_locations, TypeBoundsReturn, TypeContainer, + validate_locations, ) from folium.vector_layers import Circle, CircleMarker, PolyLine, path_options diff --git a/folium/map.py b/folium/map.py index 41b76f7b38..36c4655945 100644 --- a/folium/map.py +++ b/folium/map.py @@ -5,7 +5,7 @@ import warnings from collections import OrderedDict -from typing import TYPE_CHECKING, List, Optional, Sequence, Union, cast +from typing import TYPE_CHECKING, Optional, Sequence, Union, cast from branca.element import Element, Figure, Html, MacroElement @@ -14,11 +14,12 @@ from folium.utilities import ( JsCode, TypeBounds, + TypeBoundsReturn, TypeJsonValue, escape_backticks, parse_options, remove_empty, - validate_location, TypeBoundsReturn, + validate_location, ) if TYPE_CHECKING: diff --git a/folium/raster_layers.py b/folium/raster_layers.py index 787ca7f973..0ff6ef9948 100644 --- a/folium/raster_layers.py +++ b/folium/raster_layers.py @@ -3,7 +3,7 @@ """ -from typing import Any, Callable, Optional, Union, cast +from typing import Any, Callable, Optional, Union import xyzservices from branca.element import Element, Figure @@ -12,11 +12,13 @@ from folium.template import Template from folium.utilities import ( TypeBounds, + TypeBoundsReturn, TypeJsonValue, image_to_url, mercator_transform, + normalize_bounds_type, parse_options, - remove_empty, TypeBoundsReturn, normalize_bounds_type, + remove_empty, ) diff --git a/folium/utilities.py b/folium/utilities.py index cbe2e2879d..468af1d554 100644 --- a/folium/utilities.py +++ b/folium/utilities.py @@ -24,9 +24,7 @@ from urllib.parse import urlparse, uses_netloc, uses_params, uses_relative import numpy as np -from folium import Popup - -from branca.element import Element, Figure, Div +from branca.element import Div, Element, Figure # import here for backwards compatibility from branca.utilities import ( # noqa F401 @@ -37,6 +35,8 @@ write_png, ) +from folium import Popup + try: import pandas as pd except ImportError: diff --git a/tests/test_utilities.py b/tests/test_utilities.py index 1fe2682a49..a1f10be361 100644 --- a/tests/test_utilities.py +++ b/tests/test_utilities.py @@ -12,11 +12,12 @@ get_obj_in_upper_tree, if_pandas_df_convert_to_numpy, javascript_identifier_path_to_array_notation, + normalize_bounds_type, parse_font_size, parse_options, validate_location, validate_locations, - validate_multi_locations, normalize_bounds_type, + validate_multi_locations, ) From bab25863082a326a7a36e37ae77d105dd03490fa Mon Sep 17 00:00:00 2001 From: Frank <33519926+Conengmo@users.noreply.github.com> Date: Sun, 29 Dec 2024 13:13:49 +0100 Subject: [PATCH 12/13] black --- folium/features.py | 18 +++++++++++++++--- 1 file changed, 15 insertions(+), 3 deletions(-) diff --git a/folium/features.py b/folium/features.py index 468bf8292b..83a7b7fa47 100644 --- a/folium/features.py +++ b/folium/features.py @@ -12,7 +12,15 @@ import numpy as np import requests from branca.colormap import ColorMap, LinearColormap, StepColormap -from branca.element import Div, Element, Figure, Html, IFrame, JavascriptLink, MacroElement +from branca.element import ( + Div, + Element, + Figure, + Html, + IFrame, + JavascriptLink, + MacroElement, +) from branca.utilities import color_brewer from folium.elements import JSCSSMixin @@ -290,7 +298,9 @@ def render(self, **kwargs): """Renders the HTML representation of the element.""" parent = self._parent if not isinstance(parent, (Figure, Div, Popup)): - raise TypeError("VegaLite elements can only be added to a Figure, Div, or Popup") + raise TypeError( + "VegaLite elements can only be added to a Figure, Div, or Popup" + ) parent.html.add_child( Element( @@ -1973,7 +1983,9 @@ def __init__( elif isinstance(colormap, StepColormap): cm = colormap else: - raise TypeError(f"Unexpected type for argument `colormap`: {type(colormap)}") + raise TypeError( + f"Unexpected type for argument `colormap`: {type(colormap)}" + ) out: Dict[str, List[List[List[float]]]] = {} for (lat1, lng1), (lat2, lng2), color in zip(coords[:-1], coords[1:], colors): From 004ebca253414378b2bf277ddbd4af3762090083 Mon Sep 17 00:00:00 2001 From: Frank <33519926+Conengmo@users.noreply.github.com> Date: Sun, 29 Dec 2024 13:28:02 +0100 Subject: [PATCH 13/13] fix circular import --- folium/utilities.py | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/folium/utilities.py b/folium/utilities.py index 468af1d554..9210bf59e6 100644 --- a/folium/utilities.py +++ b/folium/utilities.py @@ -9,6 +9,7 @@ import uuid from contextlib import contextmanager from typing import ( + TYPE_CHECKING, Any, Callable, Dict, @@ -35,13 +36,14 @@ write_png, ) -from folium import Popup - try: import pandas as pd except ImportError: pd = None +if TYPE_CHECKING: + from .features import Popup + TypeLine = Iterable[Sequence[float]] TypeMultiLine = Union[TypeLine, Iterable[TypeLine]] @@ -54,7 +56,7 @@ TypeBounds = Sequence[Sequence[float]] TypeBoundsReturn = List[List[Optional[float]]] -TypeContainer = Union[Figure, Div, Popup] +TypeContainer = Union[Figure, Div, "Popup"] _VALID_URLS = set(uses_relative + uses_netloc + uses_params)