Skip to content

Commit 04737d3

Browse files
committed
imporve download role
1 parent 4a8e325 commit 04737d3

File tree

3 files changed

+46
-16
lines changed

3 files changed

+46
-16
lines changed

jupyter_sphinx/__init__.py

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,7 @@
1919
JupyterWidgetViewNode,
2020
JupyterWidgetStateNode,
2121
WIDGET_VIEW_MIMETYPE,
22-
jupyter_download_role,
22+
JupyterDownloadRole,
2323
CellOutputsToNodes,
2424
)
2525
from .execute import JupyterKernel, ExecuteJupyterCells
@@ -272,8 +272,9 @@ def setup(app):
272272
app.add_directive("jupyter-execute", JupyterCell)
273273
app.add_directive("jupyter-kernel", JupyterKernel)
274274
app.add_directive("thebe-button", ThebeButton)
275-
app.add_role("jupyter-download:notebook", jupyter_download_role)
276-
app.add_role("jupyter-download:script", jupyter_download_role)
275+
app.add_role("jupyter-download:notebook", JupyterDownloadRole())
276+
app.add_role("jupyter-download:nb", JupyterDownloadRole())
277+
app.add_role("jupyter-download:script", JupyterDownloadRole())
277278
app.add_transform(ExecuteJupyterCells)
278279
app.add_post_transform(CellOutputsToNodes)
279280

jupyter_sphinx/ast.py

Lines changed: 16 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -5,8 +5,9 @@
55

66
import docutils
77
from docutils.parsers.rst import Directive, directives
8-
from docutils.nodes import math_block, image
8+
from docutils.nodes import math_block, image, literal
99
from sphinx.util import parselinenos
10+
from sphinx.util.docutils import ReferenceRole
1011
from sphinx.addnodes import download_reference
1112
from sphinx.transforms import SphinxTransform
1213
from sphinx.environment.collectors.asset import ImageCollector
@@ -393,16 +394,20 @@ def attach_outputs(output_nodes, node, thebe_config, cm_language):
393394
node.children = node.children[::-1]
394395

395396

396-
def jupyter_download_role(name, rawtext, text, lineno, inliner):
397-
_, filetype = name.split(":")
398-
assert filetype in ("notebook", "script")
399-
ext = ".ipynb" if filetype == "notebook" else ".py"
400-
output_dir = sphinx_abs_dir(inliner.document.settings.env)
401-
download_file = text + ext
402-
node = download_reference(
403-
download_file, download_file, reftarget=os.path.join(output_dir, download_file)
404-
)
405-
return [node], []
397+
class JupyterDownloadRole(ReferenceRole):
398+
def run(self):
399+
_, filetype = self.name.split(":")
400+
401+
assert filetype in ("notebook", "nb", "script")
402+
ext = ".ipynb" if filetype in ("notebook", "nb") else ".py"
403+
output_dir = sphinx_abs_dir(self.env)
404+
download_file = self.target + ext
405+
reftarget=os.path.realpath(os.path.join(output_dir, download_file))
406+
node = download_reference(self.rawtext, reftarget=reftarget)
407+
self.set_source_info(node)
408+
title = self.title if self.has_explicit_title else download_file
409+
node += literal(self.rawtext, title, classes=["xref", "download"])
410+
return [node], []
406411

407412

408413
def get_widgets(notebook):

tests/test_execute.py

Lines changed: 26 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -3,10 +3,12 @@
33
import os
44
import sys
55
from io import StringIO
6+
from unittest.mock import Mock
67

7-
from sphinx.testing.util import SphinxTestApp, path
8+
from sphinx.addnodes import download_reference
9+
from sphinx.testing.util import assert_node, SphinxTestApp, path
810
from sphinx.errors import ExtensionError
9-
from docutils.nodes import raw
11+
from docutils.nodes import literal, raw
1012
from nbformat import from_dict
1113

1214
import pytest
@@ -18,6 +20,7 @@
1820
JupyterWidgetViewNode,
1921
JupyterWidgetStateNode,
2022
cell_output_to_nodes,
23+
JupyterDownloadRole,
2124
)
2225
from jupyter_sphinx.thebelab import ThebeSourceNode, ThebeOutputNode, ThebeButtonNode
2326

@@ -564,3 +567,24 @@ def test_image_mimetype_uri(doctree):
564567
cell = from_dict(cell)
565568
output_node = cell_output_to_nodes(cell["outputs"], priority, True, output_dir, None)
566569
assert output_node[0].attributes['uri'] == img_locs[index]
570+
571+
572+
@pytest.mark.parametrize('text,reftarget,caption', (
573+
('nb_name', '/jupyter_execute/path/to/nb_name.ipynb', 'nb_name.ipynb'),
574+
('../nb_name', '/jupyter_execute/path/nb_name.ipynb', '../nb_name.ipynb'),
575+
('text <nb_name>', '/jupyter_execute/path/to/nb_name.ipynb', 'text'),
576+
))
577+
def test_download_role(text, reftarget, caption):
578+
role = JupyterDownloadRole()
579+
mock_inliner = Mock()
580+
config = {
581+
'document.settings.env.app.outdir': 'outdir',
582+
'document.settings.env.docname': 'path/to/docname',
583+
'document.settings.env.app.srcdir': 'srcdir',
584+
'reporter.get_source_and_line': lambda l: ('source', l)
585+
}
586+
mock_inliner.configure_mock(**config)
587+
ret, msg = role('jupyter-download:notebook', text, text, 0, mock_inliner)
588+
assert_node(ret[0], [download_reference], reftarget=reftarget)
589+
assert_node(ret[0][0], [literal, caption])
590+
assert msg == []

0 commit comments

Comments
 (0)