diff --git a/folium/elements.py b/folium/elements.py index 753a55ad06..9faa2623d7 100644 --- a/folium/elements.py +++ b/folium/elements.py @@ -149,6 +149,18 @@ def __init__(self, element_name: str, element_parent_name: str): self.element_name = element_name self.element_parent_name = element_parent_name + def render(self, **kwargs): + figure = self.get_root() + assert isinstance( + figure, Figure + ), "You cannot render this Element if it is not in a Figure." + script = self._template.module.__dict__.get("script", None) + if script is not None: + figure.script.add_child( + Element(script(self, kwargs)), + name=f"{self.element_name}_add_to_{self.element_parent_name}", + ) + class IncludeStatement(MacroElement): """Generate an include statement on a class.""" diff --git a/folium/map.py b/folium/map.py index ce2e561a5b..8b99e1bbfa 100644 --- a/folium/map.py +++ b/folium/map.py @@ -517,6 +517,18 @@ def __init__( self.marker = marker self.icon = icon + def render(self, **kwargs): + figure = self.get_root() + assert isinstance( + figure, Figure + ), "You cannot render this Element if it is not in a Figure." + script = self._template.module.__dict__.get("script", None) + if script is not None: + figure.script.add_child( + Element(script(self, kwargs)), + name=f"{self.marker.get_name()}_set_icon", + ) + def __init__( self, location: Optional[Sequence[float]] = None, diff --git a/tests/test_map.py b/tests/test_map.py index cf6635a0b9..581e603ff7 100644 --- a/tests/test_map.py +++ b/tests/test_map.py @@ -290,3 +290,27 @@ def test_icon_invalid_marker_colors(): pytest.warns(UserWarning, Icon, color="lila") pytest.warns(UserWarning, Icon, color=42) pytest.warns(UserWarning, Icon, color=None) + + +def test_repeated_save_produces_identical_html(tmp_path): + """Regression test for https://github.com/python-visualization/folium/issues/2237""" + m = Map(location=[40.75, -73.98], zoom_start=13) + locations = [ + [40.7829, -73.9654], + [40.7484, -73.9857], + [40.7580, -73.9855], + ] + for lat, lon in locations: + Marker([lat, lon], icon=Icon(color="blue", icon="info-sign")).add_to(m) + + path1 = tmp_path / "1.html" + path2 = tmp_path / "2.html" + path3 = tmp_path / "3.html" + m.save(path1) + m.save(path2) + m.save(path3) + + html1 = path1.read_text() + html2 = path2.read_text() + html3 = path3.read_text() + assert html1 == html2 == html3