Repository: python-visualization/folium

Issue:
Map attribution not showing up for built in tiles
In case the default tile is chosen (OpenStreetMap) during the creation of the map (or other built-in tiles, the ones present in the template/tiles folder), no attribution is showing up on the bottom left of maps.

```python

import folium
m = folium.Map(location=[45.5236, -122.6750])
```

Looking into the code, it seems that the file `attr.txt` for each built-in tile is well read, but nothing is done with it, the template does't refer to attr and the options is not updated:

Here is the template:
```python
_template = Template(u"""
        {% macro script(this, kwargs) %}
            var {{ this.get_name() }} = L.tileLayer(
                {{ this.tiles|tojson }},
                {{ this.options|tojson }}
            ).addTo({{ this._parent.get_name() }});
        {% endmacro %}
        """)
```
and an extract of the code (`raster_layers.py`) that is supposed to set the `self.attr` attribute:

 ```python
attr_template = 'tiles/' + tiles_flat + '/attr.txt'
if tile_template in templates and attr_template in templates:
        self.tiles = self._env.get_template(tile_template).render(API_key=API_key)  # noqa
        self.attr = self._env.get_template(attr_template).render()
    else:
        self.tiles = tiles
        if not attr:
            raise ValueError('Custom tiles must have an attribution.')
self.attr = attr
```

Am I missing something ?


Discussion:
FabeG: It seems the previous commit failed, but not sure it comes from the modifcations I made.

Patch:
diff --git a/folium/raster_layers.py b/folium/raster_layers.py
index be8d7296..a7a40f3d 100644
--- a/folium/raster_layers.py
+++ b/folium/raster_layers.py
@@ -90,18 +90,6 @@ class TileLayer(Layer):
         self._name = 'TileLayer'
         self._env = ENV
 
-        self.options = parse_options(
-            min_zoom=min_zoom,
-            max_zoom=max_zoom,
-            max_native_zoom=max_native_zoom or max_zoom,
-            no_wrap=no_wrap,
-            attribution=attr,
-            subdomains=subdomains,
-            detect_retina=detect_retina,
-            tms=tms,
-            opacity=opacity,
-            **kwargs
-        )
         tiles_flat = ''.join(tiles.lower().strip().split())
         if tiles_flat in ('cloudmade', 'mapbox') and not API_key:
             raise ValueError('You must pass an API key if using Cloudmade'
@@ -113,12 +101,24 @@ class TileLayer(Layer):
 
         if tile_template in templates and attr_template in templates:
             self.tiles = self._env.get_template(tile_template).render(API_key=API_key)  # noqa
-            self.attr = self._env.get_template(attr_template).render()
+            attr = self._env.get_template(attr_template).render()
         else:
             self.tiles = tiles
             if not attr:
                 raise ValueError('Custom tiles must have an attribution.')
-            self.attr = attr
+
+        self.options = parse_options(
+            min_zoom=min_zoom,
+            max_zoom=max_zoom,
+            max_native_zoom=max_native_zoom or max_zoom,
+            no_wrap=no_wrap,
+            attribution=attr,
+            subdomains=subdomains,
+            detect_retina=detect_retina,
+            tms=tms,
+            opacity=opacity,
+            **kwargs
+        )
 
 
 class WmsTileLayer(Layer):
diff --git a/folium/templates/tiles/cartodbdark_matter/attr.txt b/folium/templates/tiles/cartodbdark_matter/attr.txt
index 9dd4389e..5e119c76 100644
--- a/folium/templates/tiles/cartodbdark_matter/attr.txt
+++ b/folium/templates/tiles/cartodbdark_matter/attr.txt
@@ -1,1 +1,1 @@
-(c) <a href="http://www.openstreetmap.org/copyright">OpenStreetMap</a> contributors (c) <a href="http://cartodb.com/attributions">CartoDB</a>, CartoDB <a href ="http://cartodb.com/attributions">attributions</a>
+&copy; <a href="http://www.openstreetmap.org/copyright">OpenStreetMap</a> contributors &copy; <a href="http://cartodb.com/attributions">CartoDB</a>, CartoDB <a href ="http://cartodb.com/attributions">attributions</a>
diff --git a/folium/templates/tiles/cartodbpositron/attr.txt b/folium/templates/tiles/cartodbpositron/attr.txt
index 9dd4389e..5e119c76 100644
--- a/folium/templates/tiles/cartodbpositron/attr.txt
+++ b/folium/templates/tiles/cartodbpositron/attr.txt
@@ -1,1 +1,1 @@
-(c) <a href="http://www.openstreetmap.org/copyright">OpenStreetMap</a> contributors (c) <a href="http://cartodb.com/attributions">CartoDB</a>, CartoDB <a href ="http://cartodb.com/attributions">attributions</a>
+&copy; <a href="http://www.openstreetmap.org/copyright">OpenStreetMap</a> contributors &copy; <a href="http://cartodb.com/attributions">CartoDB</a>, CartoDB <a href ="http://cartodb.com/attributions">attributions</a>
diff --git a/folium/templates/tiles/cloudmade/attr.txt b/folium/templates/tiles/cloudmade/attr.txt
index 57ba3605..88a97e93 100644
--- a/folium/templates/tiles/cloudmade/attr.txt
+++ b/folium/templates/tiles/cloudmade/attr.txt
@@ -1,1 +1,1 @@
-Map data (c) <a href="http://openstreetmap.org">OpenStreetMap</a> contributors, <a href="http://creativecommons.org/licenses/by-sa/2.0/">CC-BY-SA</a>, Imagery (c) <a href="http://cloudmade.com">CloudMade</a>
\ No newline at end of file
+Map data &copy; <a href="http://openstreetmap.org">OpenStreetMap</a> contributors, <a href="http://creativecommons.org/licenses/by-sa/2.0/">CC-BY-SA</a>, Imagery &copy; <a href="http://cloudmade.com">CloudMade</a>
diff --git a/folium/templates/tiles/mapbox/attr.txt b/folium/templates/tiles/mapbox/attr.txt
index e85d4b9c..c5f59e3a 100644
--- a/folium/templates/tiles/mapbox/attr.txt
+++ b/folium/templates/tiles/mapbox/attr.txt
@@ -1,1 +1,1 @@
-Map tiles by <a href="http://www.mapbox.com/m">Mapbox</a> Data by <a href="http://openstreetmap.org">OpenStreetMap</a>, under <a href="http://creativecommons.org/licenses/by-sa/3.0">CC BY SA</a>.
\ No newline at end of file
+Map tiles by &copy; <a href="http://www.mapbox.com/about/maps">Mapbox</a> Data by &copy; <a href="http://openstreetmap.org">OpenStreetMap</a>, under <a href="http://creativecommons.org/licenses/by-sa/3.0">CC BY SA</a>.
diff --git a/folium/templates/tiles/mapboxbright/attr.txt b/folium/templates/tiles/mapboxbright/attr.txt
index e85d4b9c..c5f59e3a 100644
--- a/folium/templates/tiles/mapboxbright/attr.txt
+++ b/folium/templates/tiles/mapboxbright/attr.txt
@@ -1,1 +1,1 @@
-Map tiles by <a href="http://www.mapbox.com/m">Mapbox</a> Data by <a href="http://openstreetmap.org">OpenStreetMap</a>, under <a href="http://creativecommons.org/licenses/by-sa/3.0">CC BY SA</a>.
\ No newline at end of file
+Map tiles by &copy; <a href="http://www.mapbox.com/about/maps">Mapbox</a> Data by &copy; <a href="http://openstreetmap.org">OpenStreetMap</a>, under <a href="http://creativecommons.org/licenses/by-sa/3.0">CC BY SA</a>.
diff --git a/folium/templates/tiles/mapboxcontrolroom/attr.txt b/folium/templates/tiles/mapboxcontrolroom/attr.txt
index e85d4b9c..c5f59e3a 100644
--- a/folium/templates/tiles/mapboxcontrolroom/attr.txt
+++ b/folium/templates/tiles/mapboxcontrolroom/attr.txt
@@ -1,1 +1,1 @@
-Map tiles by <a href="http://www.mapbox.com/m">Mapbox</a> Data by <a href="http://openstreetmap.org">OpenStreetMap</a>, under <a href="http://creativecommons.org/licenses/by-sa/3.0">CC BY SA</a>.
\ No newline at end of file
+Map tiles by &copy; <a href="http://www.mapbox.com/about/maps">Mapbox</a> Data by &copy; <a href="http://openstreetmap.org">OpenStreetMap</a>, under <a href="http://creativecommons.org/licenses/by-sa/3.0">CC BY SA</a>.
diff --git a/folium/templates/tiles/openstreetmap/attr.txt b/folium/templates/tiles/openstreetmap/attr.txt
index 8797521d..30f379c8 100644
--- a/folium/templates/tiles/openstreetmap/attr.txt
+++ b/folium/templates/tiles/openstreetmap/attr.txt
@@ -1,1 +1,1 @@
-Data by <a href="http://openstreetmap.org">OpenStreetMap</a>, under <a href="http://www.openstreetmap.org/copyright">ODbL</a>.
+Data by &copy; <a href="http://openstreetmap.org">OpenStreetMap</a>, under <a href="http://www.openstreetmap.org/copyright">ODbL</a>.
diff --git a/folium/templates/tiles/stamenterrain/attr.txt b/folium/templates/tiles/stamenterrain/attr.txt
index 9af39ff0..f3b5044d 100644
--- a/folium/templates/tiles/stamenterrain/attr.txt
+++ b/folium/templates/tiles/stamenterrain/attr.txt
@@ -1,1 +1,1 @@
-Map tiles by <a href="http://stamen.com">Stamen Design</a>, under <a href="http://creativecommons.org/licenses/by/3.0">CC BY 3.0</a>. Data by <a href="http://openstreetmap.org">OpenStreetMap</a>, under <a href="http://creativecommons.org/licenses/by-sa/3.0">CC BY SA</a>.
\ No newline at end of file
+Map tiles by <a href="http://stamen.com">Stamen Design</a>, under <a href="http://creativecommons.org/licenses/by/3.0">CC BY 3.0</a>. Data by &copy; <a href="http://openstreetmap.org">OpenStreetMap</a>, under <a href="http://creativecommons.org/licenses/by-sa/3.0">CC BY SA</a>.
diff --git a/folium/templates/tiles/stamentoner/attr.txt b/folium/templates/tiles/stamentoner/attr.txt
index 3e60102a..442321f1 100644
--- a/folium/templates/tiles/stamentoner/attr.txt
+++ b/folium/templates/tiles/stamentoner/attr.txt
@@ -1,1 +1,1 @@
-Map tiles by <a href="http://stamen.com">Stamen Design</a>, under <a href="http://creativecommons.org/licenses/by/3.0">CC BY 3.0</a>. Data by <a href="http://openstreetmap.org">OpenStreetMap</a>, under <a href="http://www.openstreetmap.org/copyright">ODbL</a>.
\ No newline at end of file
+Map tiles by <a href="http://stamen.com">Stamen Design</a>, under <a href="http://creativecommons.org/licenses/by/3.0">CC BY 3.0</a>. Data by &copy; <a href="http://openstreetmap.org">OpenStreetMap</a>, under <a href="http://www.openstreetmap.org/copyright">ODbL</a>.
diff --git a/folium/templates/tiles/stamenwatercolor/attr.txt b/folium/templates/tiles/stamenwatercolor/attr.txt
index 9af39ff0..f3b5044d 100644
--- a/folium/templates/tiles/stamenwatercolor/attr.txt
+++ b/folium/templates/tiles/stamenwatercolor/attr.txt
@@ -1,1 +1,1 @@
-Map tiles by <a href="http://stamen.com">Stamen Design</a>, under <a href="http://creativecommons.org/licenses/by/3.0">CC BY 3.0</a>. Data by <a href="http://openstreetmap.org">OpenStreetMap</a>, under <a href="http://creativecommons.org/licenses/by-sa/3.0">CC BY SA</a>.
\ No newline at end of file
+Map tiles by <a href="http://stamen.com">Stamen Design</a>, under <a href="http://creativecommons.org/licenses/by/3.0">CC BY 3.0</a>. Data by &copy; <a href="http://openstreetmap.org">OpenStreetMap</a>, under <a href="http://creativecommons.org/licenses/by-sa/3.0">CC BY SA</a>.


Test patch:
diff --git a/tests/test_folium.py b/tests/test_folium.py
index d962f33f..d2e302fe 100644
--- a/tests/test_folium.py
+++ b/tests/test_folium.py
@@ -13,10 +13,10 @@ import branca.element
 
 import folium
 from folium.features import GeoJson, Choropleth
-from folium.utilities import normalize
 
 import jinja2
 from jinja2 import Environment, PackageLoader
+from jinja2.utils import htmlsafe_json_dumps
 
 import numpy as np
 import pandas as pd
@@ -114,24 +114,32 @@ class TestFolium(object):
                     'name': 'TileLayer',
                     'id': '00000000000000000000000000000000',
                     'children': {}
-                    }
                 }
             }
+        }
 
     def test_builtin_tile(self):
         """Test custom maptiles."""
 
-        default_tiles = ['OpenStreetMap', 'Stamen Terrain', 'Stamen Toner']
+        default_tiles = [
+            "OpenStreetMap",
+            "Stamen Terrain",
+            "Stamen Toner",
+            "Mapbox Bright",
+            "Mapbox Control Room",
+            "CartoDB positron",
+            "CartoDB dark_matter",
+        ]
         for tiles in default_tiles:
             m = folium.Map(location=[45.5236, -122.6750], tiles=tiles)
-            tiles = ''.join(tiles.lower().strip().split())
-            url = 'tiles/{}/tiles.txt'.format
-            attr = 'tiles/{}/attr.txt'.format
+            tiles = "".join(tiles.lower().strip().split())
+            url = "tiles/{}/tiles.txt".format
+            attr = "tiles/{}/attr.txt".format
             url = m._env.get_template(url(tiles)).render()
             attr = m._env.get_template(attr(tiles)).render()
 
             assert m._children[tiles].tiles == url
-            assert m._children[tiles].attr == attr
+            assert htmlsafe_json_dumps(attr) in m._parent.render()
 
         bounds = m.get_bounds()
         assert bounds == [[None, None], [None, None]], bounds
@@ -139,15 +147,15 @@ class TestFolium(object):
     def test_custom_tile(self):
         """Test custom tile URLs."""
 
-        url = 'http://{s}.custom_tiles.org/{z}/{x}/{y}.png'
-        attr = 'Attribution for custom tiles'
+        url = "http://{s}.custom_tiles.org/{z}/{x}/{y}.png"
+        attr = "Attribution for custom tiles"
 
         with pytest.raises(ValueError):
             folium.Map(location=[45.5236, -122.6750], tiles=url)
 
         m = folium.Map(location=[45.52, -122.67], tiles=url, attr=attr)
         assert m._children[url].tiles == url
-        assert m._children[url].attr == attr
+        assert attr in m._parent.render()
 
         bounds = m.get_bounds()
         assert bounds == [[None, None], [None, None]], bounds