Using _repr_html_ to output a pretty holoviews output to custom class

I’ve got a custom class, and I’d like to output a pretty html output with _repr_html (or whatever like _repr_pretty_), when using a notebook.

This is a working solution, but I think that using _repr_mimebundle_ is a bad idea:

class MyClass:
    def __init__(self, x, y):
        self.x = x
        self.y = y
    def _repr_html_(self):
        import holoviews as hv
        hv.extension('bokeh', logo=False)
        curve = hv.Curve([(0,0),(self.x,self.y)])
        return curve._repr_mimebundle_()[0]['text/html']  #  probably bad
        # return hv.render(curve, backend='bokeh')._repr_html_()  # only output str("Figure(	id = '1290', …)")

What is the correct solution to do so ?

I think that I have to use:

# hv.extension('bokeh', logo=False)  # removed
return hv.renderer('bokeh').html(curve)

This is still not the good solution.

If myclass is in a separate file, I have to import holoviews from it.
But then, it will be imported twice, and it will show a javascript error in the notebook (at the second execution of the notebook):

In [1]

import holoviews as hv
hv.extension('bokeh')

from myclass import MyClass
#file myclass.py
#import holoviews as hv  # this cause bokeh/javascript error ? 
#class MyClass:
#    def __init__(self, x, y):
#        self.x = x
#        self.y = y
#    def _repr_html_(self):
#        curve = hv.Curve([(0,0),(self.x,self.y)])
#        return hv.renderer('bokeh').html(curve)

Out [1]

Erreur JavaScript pendant l'écriture de la sortie !
Error: Mismatched anonymous define() module: function () { 'use strict'; var hookCallback;
 function hooks() { return hookCallback.apply(null, arguments); } 
// This is done to register the method called with moment() 
// without creating circular dependencies.
 function setHookCallback(callback) { hookCallback = callback; } function isArray(input) { return ( input instanceof Array || Object.prototype.toString.call(input) === '[object Array]' ); } function isObject(input) { // IE8 will treat undefined and null as object if it wasn't for // input != null return ( input != null && Object.prototype.toString.call(input) === '[object Object]' ); } function hasOwnProp(a, b) { return Object.prototype.hasOwnProperty.call(a, b); } function isObjectEmpty(obj) { if (Object.getOwnPropertyNames) { return Object.getOwnPropertyNames(obj).length === 0; }

In [2]

# normal holoviews Curve call
hv.Curve([(-1,-1),(1,1)])

Out[2]
(holoviews Curve ok)

In[3]

# MyClass has a _repr_html_ that output html from holoviews
MyClass(5,5)

Out[3]
(holoviews Curve ok)

So how to get rid of this javascript error ?

Importing something twice or many times should never be a problem; after the first one it should be quick and cause no new errors. So if there is an error here that only occurs on multiple imports of the same library, then please file a bug report on github for that library.

In fact, the problem is not importing twice holoviews, but calling twice hv.extension('bokeh') followed by display_html.

Here is a minimal example, that will produce the javascript error:

from IPython.display import display_html
import holoviews as hv

curve = hv.Curve([(-1,-1),(1,1)])

hv.extension('bokeh')
display_html(hv.renderer('bokeh').html(curve), raw=True)

hv.extension('bokeh')
display_html(hv.renderer('bokeh').html(curve), raw=True)

The same problem will occur if hv.extension and display_html are called only once, but the notebook cell is executed 2 times.

Finally (hopefully…), my first attempt to use _repr_mimebundle_ was probably good, but I was misusing it.

So for now ‘MyClass’ code looks like this:

import holoviews as hv

class MyClass:
    def __init__(self, x, y):
        self.x = x
        self.y = y

    def _repr_mimebundle_(self, include=None, exclude=None):
        curve = hv.Curve([(0, 0), (self.x, self.y)])
        return curve._repr_mimebundle_(include=include, exclude=exclude)

And my notebook cell look like this:
In [1]

import holoviews as hv
hv.extension('bokeh')

from myclass import MyClass
MyClass(5,5)

Out [1]
(correct bokeh plot)

And I can do other holoviews plots in other cells, and restart the notebook without javascript error.

Can somebody tell me if it’s the correct solution, so I can mark the question as answered ?

1 Like