Differences between Lab and Notebook for handling display_data messages with text/html data

221 views
Skip to first unread message

Nils Bruin

unread,
Apr 20, 2019, 12:00:59 AM4/20/19
to Project Jupyter
First of all many thanks for developing and maintaining the excellent Jupyter software.

For the IPython kernel https://github.com/nbruin/magma_kernel I am noticing a difference in behaviour between Jupyter Lab and Notebook for the handling of a display_data message with text/html data.

The kernel handles certain responses with with following code, which is supposed to display an HTML link (to online help):

    def do_help(self, keyword):
        URL="http://system/online_help.html?query="+keyword
        content = {
            'source': 'stdout',
            'data': {
                'text/html':'<a href="{}" target="magma_help">Magma help on {}</a>'.format(URL,keyword)
            }
        }
        self.send_response(self.iopub_socket, 'display_data', content)

In Jupyter Notebook this works as expected. In Lab it doesn't display anything at all. Any suggestions on how I should change this code so that it works on Lab as well?

Kind regards,

Nils Bruin

Matthew Seal

unread,
Apr 22, 2019, 4:28:18 PM4/22/19
to jup...@googlegroups.com
Hi Nils,

Likely you have something missing in the header or parent header that's expected. I would look at the difference in payload between the ipython kernel and the magma kernel. In particular:

from IPython.display import HTML
HTML('<a href="{https://localhost:8080/foo}" target="magma_help">Magma help on FOO</a>')

produces on an ipython notebook client:
  1. buffers[]
  2. channel"iopub"
  3. content{data: {text/plain: "<IPython.core.display.HTML object>",…}, metadata: {}, execution_count: 2}
    1. data{text/plain: "<IPython.core.display.HTML object>",…}
      1. text/html"<a href="{https://localhost:8080/foo}" target="magma_help">Magma help on FOO</a>"
      2. text/plain"<IPython.core.display.HTML object>"
    2. execution_count2
    3. metadata{}
  4. header{version: "5.3", date: "2019-04-22T20:08:39.525031Z", session: "dda6906b-07b8f6043ea3f36416561134",…}
    1. date"2019-04-22T20:08:39.525031Z"
    2. msg_id"22771259-692e45452b81ef4b1ebb33e0"
    3. msg_type"execute_result"
    4. session"dda6906b-07b8f6043ea3f36416561134"
    5. username"mseal"
    6. version"5.3"
  5. metadata{}
  6. msg_id"22771259-692e45452b81ef4b1ebb33e0"
  7. msg_type"execute_result"
  8. parent_header{msg_id: "f7426ab80bd1418680290b7cad9578cc", username: "username",…}
    1. date"2019-04-22T20:08:39.507312Z"
    2. msg_id"f7426ab80bd1418680290b7cad9578cc"
    3. msg_type"execute_request"
    4. session"cb6c03c40bf34b2d94f4468d5202cfb2"
    5. username"username"
    6. version"5.2"
You likely need to check if the client is receiving a similar message. You can actually test the exact message and test how it would be interpreted by the protocol you can monkey patch https://github.com/jupyter/nbconvert/blob/master/nbconvert/preprocessors/execute.py#L531 and run `nbconvert --execute my_magma_nb.ipynb` to see what message is received and how it gets processed. See if this can reveal how the kernel is acting differently. I can help advise how to make your payload be accepted as expected in nbconvert if there's differences that aren't clear or confusing. Comparing payload between ipython kernel and new kernel work is a good starting point.

Best,
Matt

--
You received this message because you are subscribed to the Google Groups "Project Jupyter" group.
To unsubscribe from this group and stop receiving emails from it, send an email to jupyter+u...@googlegroups.com.
To post to this group, send email to jup...@googlegroups.com.
To view this discussion on the web visit https://groups.google.com/d/msgid/jupyter/10396a1e-2cb7-4365-ae03-60c87953b830%40googlegroups.com.
For more options, visit https://groups.google.com/d/optout.

Nils Bruin

unread,
Apr 22, 2019, 6:30:03 PM4/22/19
to Project Jupyter
Dear Matt,

Thank you very much! That worked quite well. I'm recording some details below for future reference.

In fact, nbconvert raised an error complaining that "metadata" was missing (from the content), so adding a "metadata: {}" to the content dict of the display_data message seems to resolve the issue.

It looks like JupyterLab just swallows that error (it should probably log it). Somehow, JupyNotebook doesn't seem bothered so it probably uses a different message parser.

By adding a `print(msg)` line to line 359 of nbconvert/preprocesors/execute.py it was easy to confirm what the message content was that caused the problem.

Further differences: the IPython.display.HTML(...) results in a "execute_result" message; not a "display_data" message. I'd be happy returning one of those instead, but when I read the jupyter kernel protocol docs, I did find display_data and not execute_result. It may be a later addition?

Jason Grout

unread,
Apr 22, 2019, 7:35:06 PM4/22/19
to Project Jupyter
1. Jupyter notebook and JupyterLab do indeed use completely different message processors.
2. The execute_result vs display_data difference you see is from how you evaluated things. execute_result basically returns the result of displaying the last line of execution. display_data messages come from explicitly displaying something. To see the display_data message, do something like `display(HTML(...))`.

Thanks,

Jason


--
You received this message because you are subscribed to the Google Groups "Project Jupyter" group.
To unsubscribe from this group and stop receiving emails from it, send an email to jupyter+u...@googlegroups.com.
To post to this group, send email to jup...@googlegroups.com.

Nils Bruin

unread,
Apr 22, 2019, 8:32:11 PM4/22/19
to Project Jupyter
On Monday, April 22, 2019 at 4:35:06 PM UTC-7, Jason Grout wrote:
2. The execute_result vs display_data difference you see is from how you evaluated things. execute_result basically returns the result of displaying the last line of execution. display_data messages come from explicitly displaying something. To see the display_data message, do something like `display(HTML(...))`.

OK. So suppose we have the following scenario

[Input:] ?SomeCommand

Desired output:


Presently, this is generated by a do_execute amounting to:

self.send_response(self.iopub_socket, 'display_data', content)
return {'status': 'ok', 'execution_count': self.execution_count, 'payload': [], 'user_expressions': {}}

where "content" is a dictionary that successfully encodes the information for displaying the desired "<a href...".

Would it be more appropriate to send an  'execute_result' response instead? Does it matter? Would it just be a matter of replacing 'display_data' with 'execute_result'?

Matthew Seal

unread,
Apr 25, 2019, 8:35:18 PM4/25/19
to jup...@googlegroups.com
I think your thinking is correct that if the result is just a display that execute_result would be more concise. Testing your messaging pattern through nbconvert is a great way to evaluate how it will be interpreted with a debugger. So I'd recommend testing your patterns there as proof of standard following.

--
You received this message because you are subscribed to the Google Groups "Project Jupyter" group.
To unsubscribe from this group and stop receiving emails from it, send an email to jupyter+u...@googlegroups.com.
To post to this group, send email to jup...@googlegroups.com.
Reply all
Reply to author
Forward
0 new messages