Skip to content

Commit 19d9340

Browse files
authored
Merge pull request #24215 from lpsinger/show-source-link-option
Add :shows-source-link: option to Sphinx plot directive
2 parents c1c4b5a + d58fc21 commit 19d9340

File tree

3 files changed

+76
-24
lines changed

3 files changed

+76
-24
lines changed
Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
Source links can be shown or hidden for each Sphinx plot directive
2+
------------------------------------------------------------------
3+
The :doc:`Sphinx plot directive </api/sphinxext_plot_directive_api>`
4+
(``.. plot::``) now supports a ``:show-source-link:`` option to show or hide
5+
the link to the source code for each plot. The default is set using the
6+
``plot_html_show_source_link`` variable in :file:`conf.py` (which
7+
defaults to True).

lib/matplotlib/sphinxext/plot_directive.py

Lines changed: 9 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -55,6 +55,11 @@
5555
the ``plot_include_source`` variable in :file:`conf.py` (which itself
5656
defaults to False).
5757
58+
``:show-source-link:`` : bool
59+
Whether to show a link to the source in HTML. The default can be
60+
changed using the ``plot_html_show_source_link`` variable in
61+
:file:`conf.py` (which itself defaults to True).
62+
5863
``:encoding:`` : str
5964
If this source file is in a non-UTF8 or non-ASCII encoding, the
6065
encoding must be specified using the ``:encoding:`` option. The
@@ -245,6 +250,7 @@ class PlotDirective(Directive):
245250
'align': Image.align,
246251
'class': directives.class_option,
247252
'include-source': _option_boolean,
253+
'show-source-link': _option_boolean,
248254
'format': _option_format,
249255
'context': _option_context,
250256
'nofigs': directives.flag,
@@ -666,6 +672,7 @@ def run(arguments, content, options, state_machine, state, lineno):
666672
default_fmt = formats[0][0]
667673

668674
options.setdefault('include-source', config.plot_include_source)
675+
options.setdefault('show-source-link', config.plot_html_show_source_link)
669676
if 'class' in options:
670677
# classes are parsed into a list of string, and output by simply
671678
# printing the list, abusing the fact that RST guarantees to strip
@@ -832,7 +839,7 @@ def run(arguments, content, options, state_machine, state, lineno):
832839

833840
# Not-None src_link signals the need for a source link in the generated
834841
# html
835-
if j == 0 and config.plot_html_show_source_link:
842+
if j == 0 and options['show-source-link']:
836843
src_link = source_link
837844
else:
838845
src_link = None
@@ -866,7 +873,7 @@ def run(arguments, content, options, state_machine, state, lineno):
866873
shutil.copyfile(fn, destimg)
867874

868875
# copy script (if necessary)
869-
if config.plot_html_show_source_link:
876+
if options['show-source-link']:
870877
Path(dest_dir, output_base + source_ext).write_text(
871878
doctest.script_from_examples(code)
872879
if source_file_name == rst_file and is_doctest

lib/matplotlib/tests/test_sphinxext.py

Lines changed: 60 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -14,11 +14,11 @@
1414
minversion=None if sys.version_info < (3, 10) else '4.1.3')
1515

1616

17-
def test_tinypages(tmpdir):
18-
source_dir = Path(tmpdir) / 'src'
19-
shutil.copytree(Path(__file__).parent / 'tinypages', source_dir)
20-
html_dir = source_dir / '_build' / 'html'
21-
doctree_dir = source_dir / 'doctrees'
17+
def test_tinypages(tmp_path):
18+
shutil.copytree(Path(__file__).parent / 'tinypages', tmp_path,
19+
dirs_exist_ok=True)
20+
html_dir = tmp_path / '_build' / 'html'
21+
doctree_dir = tmp_path / 'doctrees'
2222
# Build the pages with warnings turned into errors
2323
cmd = [sys.executable, '-msphinx', '-W', '-b', 'html',
2424
'-d', str(doctree_dir),
@@ -32,7 +32,7 @@ def test_tinypages(tmpdir):
3232
out, err = proc.communicate()
3333

3434
# Build the pages with warnings turned into errors
35-
build_sphinx_html(source_dir, doctree_dir, html_dir)
35+
build_sphinx_html(tmp_path, doctree_dir, html_dir)
3636

3737
def plot_file(num):
3838
return html_dir / f'some_plots-{num}.png'
@@ -75,13 +75,13 @@ def plot_directive_file(num):
7575
assert filecmp.cmp(range_6, plot_file(17))
7676

7777
# Modify the included plot
78-
contents = (source_dir / 'included_plot_21.rst').read_bytes()
78+
contents = (tmp_path / 'included_plot_21.rst').read_bytes()
7979
contents = contents.replace(b'plt.plot(range(6))', b'plt.plot(range(4))')
80-
(source_dir / 'included_plot_21.rst').write_bytes(contents)
80+
(tmp_path / 'included_plot_21.rst').write_bytes(contents)
8181
# Build the pages again and check that the modified file was updated
8282
modification_times = [plot_directive_file(i).stat().st_mtime
8383
for i in (1, 2, 3, 5)]
84-
build_sphinx_html(source_dir, doctree_dir, html_dir)
84+
build_sphinx_html(tmp_path, doctree_dir, html_dir)
8585
assert filecmp.cmp(range_4, plot_file(17))
8686
# Check that the plots in the plot_directive folder weren't changed.
8787
# (plot_directive_file(1) won't be modified, but it will be copied to html/
@@ -98,35 +98,73 @@ def plot_directive_file(num):
9898
assert filecmp.cmp(range_6, plot_file(5))
9999

100100

101-
def test_plot_html_show_source_link(tmpdir):
102-
source_dir = Path(tmpdir) / 'src'
103-
source_dir.mkdir()
101+
def test_plot_html_show_source_link(tmp_path):
104102
parent = Path(__file__).parent
105-
shutil.copyfile(parent / 'tinypages/conf.py', source_dir / 'conf.py')
106-
shutil.copytree(parent / 'tinypages/_static', source_dir / '_static')
107-
doctree_dir = source_dir / 'doctrees'
108-
(source_dir / 'index.rst').write_text("""
103+
shutil.copyfile(parent / 'tinypages/conf.py', tmp_path / 'conf.py')
104+
shutil.copytree(parent / 'tinypages/_static', tmp_path / '_static')
105+
doctree_dir = tmp_path / 'doctrees'
106+
(tmp_path / 'index.rst').write_text("""
109107
.. plot::
110108
111109
plt.plot(range(2))
112110
""")
113111
# Make sure source scripts are created by default
114-
html_dir1 = source_dir / '_build' / 'html1'
115-
build_sphinx_html(source_dir, doctree_dir, html_dir1)
112+
html_dir1 = tmp_path / '_build' / 'html1'
113+
build_sphinx_html(tmp_path, doctree_dir, html_dir1)
116114
assert "index-1.py" in [p.name for p in html_dir1.iterdir()]
117115
# Make sure source scripts are NOT created when
118116
# plot_html_show_source_link` is False
119-
html_dir2 = source_dir / '_build' / 'html2'
120-
build_sphinx_html(source_dir, doctree_dir, html_dir2,
117+
html_dir2 = tmp_path / '_build' / 'html2'
118+
build_sphinx_html(tmp_path, doctree_dir, html_dir2,
121119
extra_args=['-D', 'plot_html_show_source_link=0'])
122120
assert "index-1.py" not in [p.name for p in html_dir2.iterdir()]
123121

124122

125-
def build_sphinx_html(source_dir, doctree_dir, html_dir, extra_args=None):
123+
@pytest.mark.parametrize('plot_html_show_source_link', [0, 1])
124+
def test_show_source_link_true(tmp_path, plot_html_show_source_link):
125+
# Test that a source link is generated if :show-source-link: is true,
126+
# whether or not plot_html_show_source_link is true.
127+
parent = Path(__file__).parent
128+
shutil.copyfile(parent / 'tinypages/conf.py', tmp_path / 'conf.py')
129+
shutil.copytree(parent / 'tinypages/_static', tmp_path / '_static')
130+
doctree_dir = tmp_path / 'doctrees'
131+
(tmp_path / 'index.rst').write_text("""
132+
.. plot::
133+
:show-source-link: true
134+
135+
plt.plot(range(2))
136+
""")
137+
html_dir = tmp_path / '_build' / 'html'
138+
build_sphinx_html(tmp_path, doctree_dir, html_dir, extra_args=[
139+
'-D', f'plot_html_show_source_link={plot_html_show_source_link}'])
140+
assert "index-1.py" in [p.name for p in html_dir.iterdir()]
141+
142+
143+
@pytest.mark.parametrize('plot_html_show_source_link', [0, 1])
144+
def test_show_source_link_false(tmp_path, plot_html_show_source_link):
145+
# Test that a source link is NOT generated if :show-source-link: is false,
146+
# whether or not plot_html_show_source_link is true.
147+
parent = Path(__file__).parent
148+
shutil.copyfile(parent / 'tinypages/conf.py', tmp_path / 'conf.py')
149+
shutil.copytree(parent / 'tinypages/_static', tmp_path / '_static')
150+
doctree_dir = tmp_path / 'doctrees'
151+
(tmp_path / 'index.rst').write_text("""
152+
.. plot::
153+
:show-source-link: false
154+
155+
plt.plot(range(2))
156+
""")
157+
html_dir = tmp_path / '_build' / 'html'
158+
build_sphinx_html(tmp_path, doctree_dir, html_dir, extra_args=[
159+
'-D', f'plot_html_show_source_link={plot_html_show_source_link}'])
160+
assert "index-1.py" not in [p.name for p in html_dir.iterdir()]
161+
162+
163+
def build_sphinx_html(tmp_path, doctree_dir, html_dir, extra_args=None):
126164
# Build the pages with warnings turned into errors
127165
extra_args = [] if extra_args is None else extra_args
128166
cmd = [sys.executable, '-msphinx', '-W', '-b', 'html',
129-
'-d', str(doctree_dir), str(source_dir), str(html_dir), *extra_args]
167+
'-d', str(doctree_dir), str(tmp_path), str(html_dir), *extra_args]
130168
proc = Popen(cmd, stdout=PIPE, stderr=PIPE, universal_newlines=True,
131169
env={**os.environ, "MPLBACKEND": ""})
132170
out, err = proc.communicate()

0 commit comments

Comments
 (0)
pFad - Phonifier reborn

Pfad - The Proxy pFad of © 2024 Garber Painting. All rights reserved.

Note: This service is not intended for secure transactions such as banking, social media, email, or purchasing. Use at your own risk. We assume no liability whatsoever for broken pages.


Alternative Proxies:

Alternative Proxy

pFad Proxy

pFad v3 Proxy

pFad v4 Proxy