Skip to content

Commit

Permalink
Allow including text/x-rst outputs in rst conversion, transition aw…
Browse files Browse the repository at this point in the history
…ay from `text/restructuredtext` (#2167)

Co-authored-by: pre-commit-ci[bot] <66853113+pre-commit-ci[bot]@users.noreply.github.com>
  • Loading branch information
takluyver and pre-commit-ci[bot] authored Aug 28, 2024
1 parent 55ff3e9 commit e159962
Show file tree
Hide file tree
Showing 7 changed files with 112 additions and 2 deletions.
18 changes: 17 additions & 1 deletion nbconvert/exporters/rst.py
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@
from traitlets import default
from traitlets.config import Config

from ..filters import DataTypeFilter
from .templateexporter import TemplateExporter


Expand All @@ -22,9 +23,24 @@ def _file_extension_default(self):
def _template_name_default(self):
return "rst"

output_mimetype = "text/restructuredtext"
@default("raw_mimetypes")
def _raw_mimetypes_default(self):
# Up to summer 2024, nbconvert had a mistaken output_mimetype.
# Listing that as an extra option here maintains compatibility for
# notebooks with raw cells marked as that mimetype.
return [self.output_mimetype, "text/restructuredtext", ""]

output_mimetype = "text/x-rst"
export_from_notebook = "reST"

def default_filters(self):
"""Override filter_data_type to use native rst outputs"""
dtf = DataTypeFilter()
dtf.display_data_priority = [self.output_mimetype, *dtf.display_data_priority]
filters = dict(super().default_filters())
filters["filter_data_type"] = dtf
return filters.items()

@property
def default_config(self):
c = Config(
Expand Down
1 change: 1 addition & 0 deletions nbconvert/exporters/templateexporter.py
Original file line number Diff line number Diff line change
Expand Up @@ -407,6 +407,7 @@ def from_notebook_node( # type:ignore[explicit-override, override]
"""
nb_copy, resources = super().from_notebook_node(nb, resources, **kw)
resources.setdefault("raw_mimetypes", self.raw_mimetypes)
resources.setdefault("output_mimetype", self.output_mimetype)
resources["global_content_filter"] = {
"include_code": not self.exclude_code_cell,
"include_markdown": not self.exclude_markdown,
Expand Down
3 changes: 3 additions & 0 deletions share/templates/base/display_priority.j2
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,9 @@
{%- elif type == 'application/vnd.jupyter.widget-view+json' -%}
{%- block data_widget_view -%}
{%- endblock -%}
{%- elif type == resources.output_mimetype -%}
{%- block data_native -%}
{%- endblock -%}
{%- else -%}
{%- block data_other -%}
{%- endblock -%}
Expand Down
2 changes: 1 addition & 1 deletion share/templates/rst/conf.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"base_template": "base",
"mimetypes": {
"text/restructuredtext": true
"text/x-rst": true
}
}
4 changes: 4 additions & 0 deletions share/templates/rst/index.rst.j2
Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,10 @@
{{ output.text | indent }}
{% endblock stream %}

{% block data_native %}
{{ output.data['text/x-rst'] }}
{% endblock data_native %}

{% block data_svg %}
.. image:: {{ output.metadata.filenames['image/svg+xml'] | urlencode }}
{% endblock data_svg %}
Expand Down
75 changes: 75 additions & 0 deletions tests/exporters/files/rst_output.ipynb
Original file line number Diff line number Diff line change
@@ -0,0 +1,75 @@
{
"cells": [
{
"cell_type": "code",
"execution_count": 1,
"id": "d5202f0f-21b8-4509-a9e2-45caf1c7db7a",
"metadata": {},
"outputs": [],
"source": [
"from textwrap import indent\n",
"\n",
"\n",
"class Note:\n",
" def __init__(self, text):\n",
" self.text = text\n",
"\n",
" def _repr_html_(self):\n",
" return f'<div style=\"font-weight: bold; font-size: 16pt;\">{self.text}</div>'\n",
"\n",
" def _repr_mimebundle_(self, include=None, exclude=None):\n",
" return {\"text/x-rst\": \".. note::\\n\\n\" + indent(self.text, \" \")}"
]
},
{
"cell_type": "code",
"execution_count": 2,
"id": "5145b05f-3a07-4cff-8738-516a9c27cb58",
"metadata": {},
"outputs": [
{
"data": {
"text/html": [
"<div style=\"font-weight: bold; font-size: 16pt;\">Testing testing</div>"
],
"text/plain": [
"<__main__.Note at 0x7f457c0250d0>"
],
"text/x-rst": [
".. note::\n",
"\n",
" Testing testing"
]
},
"execution_count": 2,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"Note(\"Testing testing\")"
]
}
],
"metadata": {
"kernelspec": {
"display_name": "Python 3 (ipykernel)",
"language": "python",
"name": "python3"
},
"language_info": {
"codemirror_mode": {
"name": "ipython",
"version": 3
},
"file_extension": ".py",
"mimetype": "text/x-python",
"name": "python",
"nbconvert_exporter": "python",
"pygments_lexer": "ipython3",
"version": "3.12.4"
}
},
"nbformat": 4,
"nbformat_minor": 5
}
11 changes: 11 additions & 0 deletions tests/exporters/test_rst.py
Original file line number Diff line number Diff line change
Expand Up @@ -68,3 +68,14 @@ def test_png_metadata(self):
assert ":width:" in attr_string
assert ":height:" in attr_string
assert "px" in attr_string

def test_rst_output(self):
"""
Is native text/x-rst output included when converting
"""
(output, resources) = RSTExporter().from_filename(
self._get_notebook(nb_name="rst_output.ipynb")
)
assert len(output) > 0
assert "\n.. note::" in output
assert ".. raw:: html" not in output # rst should shadow html output

0 comments on commit e159962

Please sign in to comment.