nbsphinx icon indicating copy to clipboard operation
nbsphinx copied to clipboard

embed markdown tables automatically generated

Open gpagliuca opened this issue 7 years ago • 13 comments

I would like to embed tables and plots generated on the fly in markdown cells based on some (hidden) initialization cells.

This is possible in the jupyter notebook thanks to this extension python-markdown.

According to the extension documentation it is possible to have the same behavior exporting via nbconvert using a pre-processor (here the preprocessor source code) :

Exporting In order to have nbconvert show the computed Python output when exporting to another format, use the pre_pymarkdown.py preprocessor. If you used the python setup.py install command to install the IPython-contrib extension package, this will already be installed. For manual setup, you need to copy this file to a location within the Python path (or extend PYTHONPATH). Additionally, you need to add these two lines to your jupyter_nbconvert_config.py configuration file: c = get_config() c.Exporter.preprocessors = ['pre_pymarkdown.PyMarkdownPreprocessor']

This works when I manually convert a notebook to html using nbconvert, but not when I try to build the doc with sphinx.

Any suggestion? Is this the best approach? (related in end to issue #15)

Thanks ;-)

gpagliuca avatar Dec 13 '16 08:12 gpagliuca

For now, nbsphinx doesn't support adding custom preprocessors, but it shouldn't be too hard to implement this.

Would you like to make a PR for this?

mgeier avatar Dec 15 '16 10:12 mgeier

I am more a user... but I'll try.

Thanks for the answer.

gpagliuca avatar Dec 15 '16 13:12 gpagliuca

If you need help, don't hesitate to ask!

mgeier avatar Dec 16 '16 18:12 mgeier

Created a pull request with the hide_input option as cell metadata. It works but it is ugly.

I need your help for the pre-processor instead. The pre-processor I'd like to add extends the nbconvert Preprocessor class and it is automatically called when using nbconvert with the jupyter nbextensions installed.

Now, in nbsphinx, if I have well understood, the only preprocessor used is HighlightMagicsPreprocessor in the Exporter class but if I simply try to add there PyMarkdownPreprocessor I see no change or error.

gpagliuca avatar Dec 21 '16 08:12 gpagliuca

AFAIK, the thing with the HighlightMagicsPreprocessor only works because it is in the list of default preprocessors: https://github.com/jupyter/nbconvert/blob/d7c996c87db98c2bb80e72a0c22511a802064bc4/nbconvert/exporters/exporter.py#L70

A few lines above you can see the preprocessors attribute, maybe you can use this?

Is your PyMarkdownPreprocessor supposed to be run before or after the ExecutePreprocessor? I'm invoking the ExecutePreprocessor manually (and conditionally) in nbsphinx. If your preprocessor has to run after that, I think the preprocessors attribute won't work, because those will be involked before nbsphinx.Exporter.from_notebook_node()is even called.

mgeier avatar Dec 23 '16 15:12 mgeier

Has any one had success with this preprocessor yet? Tried it but without any success.

keluc avatar Oct 14 '17 14:10 keluc

It would be so awesome to be able to embed variables generated in the notebook within the Markdown cells for nbsphinx - this would help me a lot in documenting jupyterlab-lsp, and maybe it could be useful to jupyterlab in general in the future. I expect that the things changed in the last 4 years and maybe it would be worth to have a fresh look a this. Would you think that using a preprocessor is the best option, or would it be better to export the variables to the RST and display them using substitutions? Or would it be too difficult due to any potential escaping?

krassowski avatar Jul 18 '20 22:07 krassowski

So here is what I came up with: I write my markdown in a code cell but prepend it with %%markdown (which gives me linting of markdown as a bonus when using jupyterlab-lsp); however instead of using the default IPython markdown magic I redefine it as:

from IPython.display import Markdown
from IPython.core.magic import register_cell_magic


@register_cell_magic
def markdown(line, cell):
    return Markdown(cell.format(**globals()))

Then I hide the cell source in nbsphinx by setting {"hide_input": true} in cell metadata.

I find this solution very nice because I can provide installation instructions such as:

Screenshot from 2020-07-19 01-15-34

krassowski avatar Jul 19 '20 00:07 krassowski

Instead of going the Markdown detour, you can also simply use text output:

print(f"""\
pip install jupyter-lsp={JUPYTER_LSP_VERSION}
jupyter labextension install @krassowski/jupyterlab-lsp@{JUPYTERLAB_LSP_VERSION}
""")

Would you think that using a preprocessor is the best option,

I don't know whether it's the best option, but I still think it's worth trying.

or would it be better to export the variables to the RST and display them using substitutions?

I see two problems:

  • nbsphinx internally using a reST representation is just an implementation detail which will be changed in the future (#36).
  • the parsing of reST happens after the whole notebook is executed, so if a variable is overwritten during notebook execution, it will always be displayed with its final value, even if it is mentioned much earlier in the notebook.

mgeier avatar Jul 19 '20 09:07 mgeier

Did anything ever come of this? I would love to be able to do this and would be willing to help.

My main problem with any of the proposed alternatives is that--unless you can hide that specific code cell--you end up reading everything twice:

In [1]

answer = 42
print(f"This is the answer to life, universe, everything: {answer}")

Out[1] This is the answer to life, the universe, everything: 42

unless you can hide the input code (but only hide that input code and not the input code for anything else you produce). Additionally, the output is in a different font than the rest of the text, which can be a disconcerting context switch.

I looked through the documentation for pre-processing and didn't see anything so I assume this wasn't solved but I'm not sure.

actsasgeek avatar Nov 21 '20 18:11 actsasgeek

I think that hide_input in metadata for specific cell does exactly that (see my comment above) - unless I misunderstood.

krassowski avatar Nov 21 '20 18:11 krassowski

@krassowski Thank you for your quick response.

I still have the qualm that, at least in the notebook itself, you have to read "it" twice...the code to generate it and the generated output. I provide both the notebooks and the PDF to my students.

OTOH, I do like the idea of something that works with Jupyter Lab as well as Jupyter Notebook.

The main issue I'm having right now is that {"hide_input": true} doesn't do anything (although "nbsphinx": "hidden" does but that hides both). I can't find documentation for just "hide_input" and looking through the issues, it's not clear how the whole "hide input" thing was ever resolved. Additionally, this is for PDF not HTML. (nbsphinx 0.7.1)

actsasgeek avatar Nov 21 '20 19:11 actsasgeek

I can't find documentation for just "hide_input" and looking through the issues, it's not clear how the whole "hide input" thing was ever resolved.

It wasn't.

There are several issues where this has been discussed and there are multiple open pull requests: #436, #185, #86.

If you want this to progress, please chime in!

mgeier avatar Dec 04 '20 14:12 mgeier