Tiles attribution not showing when using custom tiles server with gv.WMTS

Hi everyone,
I am using a custom tiles server with gv.WMTS. The attribution seems to show when using the WMTSTileSource object from Bokeh or the built-in OSM tiles with gv.tile_sources.OSM() but it does not show with the custom tile server.

Minimal code to reproduce :

from bokeh.plotting import figure, show
from bokeh.io import output_notebook
from bokeh.models import WMTSTileSource

output_notebook()

import cartopy.crs as ccrs
import numpy as np

x_bounds=(2.14572, 2.61568)
y_bounds=(48.68763, 49.01233)
google_mercator_bbox = ccrs.GOOGLE_MERCATOR.transform_points(
        ccrs.PlateCarree(), x=np.array(x_bounds), y=np.array(y_bounds)
    )[:, :-1].flatten()

PLANIGNV2_tile_provider = WMTSTileSource(url="https://data.geopf.fr/tms/1.0.0/GEOGRAPHICALGRIDSYSTEMS.PLANIGNV2/{Z}/{X}/{Y}.png",
                              name='PLAN IGN',
                              attribution="""
<a href="https://geoservices.ign.fr/services-web-decouverte" target="_blank">&copy; Institut national de l'information géographique et forestière
</a>""")
plan_ign_v2 = figure(x_range=(google_mercator_bbox[0], google_mercator_bbox[2]),
                     y_range=(google_mercator_bbox[1], google_mercator_bbox[3]),
                     min_width=800, min_height=400,
                     x_axis_type='mercator', y_axis_type='mercator',
                     active_drag='pan', active_scroll='wheel_zoom', match_aspect=True)
plan_ign_v2.add_tile(PLANIGNV2_tile_provider)
show(plan_ign_v2)

This shows the attribution at the bottom right corner of the map:

Then using it with Geoviews :

import geoviews as gv
gv.extension("bokeh")

gv.WMTS(PLANIGNV2_tile_provider).opts(active_tools=['wheel_zoom'], min_height=500, min_width=800, xlim=(google_mercator_bbox[0], google_mercator_bbox[2]), ylim=(google_mercator_bbox[1], google_mercator_bbox[3]))

The tiles are showing but not the attribution:

However, I checked with the built-in OSM tiles and the attributions are there:

gv.tile_sources.OSM().opts(active_tools=['wheel_zoom'], min_height=500, min_width=800,
                              xlim=(google_mercator_bbox[0], google_mercator_bbox[2]),
                     ylim=(google_mercator_bbox[1], google_mercator_bbox[3]))

Hmm. I see code in holoviews/plotting/bokeh/tiles.py to handle custom attributions, but it doesn’t make a lot of sense to me:

        if isinstance(element.data, dict):
            params = {
                'url': element.data.build_url(scale_factor="@2x"),
                'min_zoom': element.data.get("min_zoom", 0),
                'max_zoom': element.data.get("max_zoom", 20),
                'attribution': element.data.html_attribution}

I.e. if element.data is a dictionary, why are we accessing the “build_url” and “html_attribution” using dot notation rather than dictionary notation? Seems to me that we’ve got some code paths here that aren’t being exercised. Plus I agree it would make sense to respect the attribution field of the underlying Bokeh object if that’s what was provided. Unless I’m confused, please file a bug report about these issues!

I created an issue on GitHub
Tiles attribution not showing when using custom tile server · Issue #765 · holoviz/geoviews