From d58fc21b8bd2617f15aff00207d2c116622b899f Mon Sep 17 00:00:00 2001 From: Leo Singer Date: Tue, 18 Oct 2022 12:41:07 -0400 Subject: [PATCH] Add :shows-source-link: option to Sphinx plot directive The Sphinx plot directive (`.. plot::`) now supports a `:show-source-link` option to show or hide the link to the source for each plot. The default is set using the `plot_html_show_source_link` variable in `conf.py` (which itself defaults to True). --- .../show_source_links_directive_option.rst | 7 ++ lib/matplotlib/sphinxext/plot_directive.py | 11 ++- lib/matplotlib/tests/test_sphinxext.py | 82 ++++++++++++++----- 3 files changed, 76 insertions(+), 24 deletions(-) create mode 100644 doc/users/next_whats_new/show_source_links_directive_option.rst diff --git a/doc/users/next_whats_new/show_source_links_directive_option.rst b/doc/users/next_whats_new/show_source_links_directive_option.rst new file mode 100644 index 000000000000..8beb233f32e8 --- /dev/null +++ b/doc/users/next_whats_new/show_source_links_directive_option.rst @@ -0,0 +1,7 @@ +Source links can be shown or hidden for each Sphinx plot directive +------------------------------------------------------------------ +The :doc:`Sphinx plot directive ` +(``.. plot::``) now supports a ``:show-source-link:`` option to show or hide +the link to the source code for each plot. The default is set using the +``plot_html_show_source_link`` variable in :file:`conf.py` (which +defaults to True). diff --git a/lib/matplotlib/sphinxext/plot_directive.py b/lib/matplotlib/sphinxext/plot_directive.py index 743344086211..f483d17ce1f3 100644 --- a/lib/matplotlib/sphinxext/plot_directive.py +++ b/lib/matplotlib/sphinxext/plot_directive.py @@ -55,6 +55,11 @@ the ``plot_include_source`` variable in :file:`conf.py` (which itself defaults to False). + ``:show-source-link:`` : bool + Whether to show a link to the source in HTML. The default can be + changed using the ``plot_html_show_source_link`` variable in + :file:`conf.py` (which itself defaults to True). + ``:encoding:`` : str If this source file is in a non-UTF8 or non-ASCII encoding, the encoding must be specified using the ``:encoding:`` option. The @@ -245,6 +250,7 @@ class PlotDirective(Directive): 'align': Image.align, 'class': directives.class_option, 'include-source': _option_boolean, + 'show-source-link': _option_boolean, 'format': _option_format, 'context': _option_context, 'nofigs': directives.flag, @@ -666,6 +672,7 @@ def run(arguments, content, options, state_machine, state, lineno): default_fmt = formats[0][0] options.setdefault('include-source', config.plot_include_source) + options.setdefault('show-source-link', config.plot_html_show_source_link) if 'class' in options: # classes are parsed into a list of string, and output by simply # printing the list, abusing the fact that RST guarantees to strip @@ -832,7 +839,7 @@ def run(arguments, content, options, state_machine, state, lineno): # Not-None src_link signals the need for a source link in the generated # html - if j == 0 and config.plot_html_show_source_link: + if j == 0 and options['show-source-link']: src_link = source_link else: src_link = None @@ -866,7 +873,7 @@ def run(arguments, content, options, state_machine, state, lineno): shutil.copyfile(fn, destimg) # copy script (if necessary) - if config.plot_html_show_source_link: + if options['show-source-link']: Path(dest_dir, output_base + source_ext).write_text( doctest.script_from_examples(code) if source_file_name == rst_file and is_doctest diff --git a/lib/matplotlib/tests/test_sphinxext.py b/lib/matplotlib/tests/test_sphinxext.py index d4fb94ade5d1..de3146070918 100644 --- a/lib/matplotlib/tests/test_sphinxext.py +++ b/lib/matplotlib/tests/test_sphinxext.py @@ -14,11 +14,11 @@ minversion=None if sys.version_info < (3, 10) else '4.1.3') -def test_tinypages(tmpdir): - source_dir = Path(tmpdir) / 'src' - shutil.copytree(Path(__file__).parent / 'tinypages', source_dir) - html_dir = source_dir / '_build' / 'html' - doctree_dir = source_dir / 'doctrees' +def test_tinypages(tmp_path): + shutil.copytree(Path(__file__).parent / 'tinypages', tmp_path, + dirs_exist_ok=True) + html_dir = tmp_path / '_build' / 'html' + doctree_dir = tmp_path / 'doctrees' # Build the pages with warnings turned into errors cmd = [sys.executable, '-msphinx', '-W', '-b', 'html', '-d', str(doctree_dir), @@ -32,7 +32,7 @@ def test_tinypages(tmpdir): out, err = proc.communicate() # Build the pages with warnings turned into errors - build_sphinx_html(source_dir, doctree_dir, html_dir) + build_sphinx_html(tmp_path, doctree_dir, html_dir) def plot_file(num): return html_dir / f'some_plots-{num}.png' @@ -75,13 +75,13 @@ def plot_directive_file(num): assert filecmp.cmp(range_6, plot_file(17)) # Modify the included plot - contents = (source_dir / 'included_plot_21.rst').read_bytes() + contents = (tmp_path / 'included_plot_21.rst').read_bytes() contents = contents.replace(b'plt.plot(range(6))', b'plt.plot(range(4))') - (source_dir / 'included_plot_21.rst').write_bytes(contents) + (tmp_path / 'included_plot_21.rst').write_bytes(contents) # Build the pages again and check that the modified file was updated modification_times = [plot_directive_file(i).stat().st_mtime for i in (1, 2, 3, 5)] - build_sphinx_html(source_dir, doctree_dir, html_dir) + build_sphinx_html(tmp_path, doctree_dir, html_dir) assert filecmp.cmp(range_4, plot_file(17)) # Check that the plots in the plot_directive folder weren't changed. # (plot_directive_file(1) won't be modified, but it will be copied to html/ @@ -98,35 +98,73 @@ def plot_directive_file(num): assert filecmp.cmp(range_6, plot_file(5)) -def test_plot_html_show_source_link(tmpdir): - source_dir = Path(tmpdir) / 'src' - source_dir.mkdir() +def test_plot_html_show_source_link(tmp_path): parent = Path(__file__).parent - shutil.copyfile(parent / 'tinypages/conf.py', source_dir / 'conf.py') - shutil.copytree(parent / 'tinypages/_static', source_dir / '_static') - doctree_dir = source_dir / 'doctrees' - (source_dir / 'index.rst').write_text(""" + shutil.copyfile(parent / 'tinypages/conf.py', tmp_path / 'conf.py') + shutil.copytree(parent / 'tinypages/_static', tmp_path / '_static') + doctree_dir = tmp_path / 'doctrees' + (tmp_path / 'index.rst').write_text(""" .. plot:: plt.plot(range(2)) """) # Make sure source scripts are created by default - html_dir1 = source_dir / '_build' / 'html1' - build_sphinx_html(source_dir, doctree_dir, html_dir1) + html_dir1 = tmp_path / '_build' / 'html1' + build_sphinx_html(tmp_path, doctree_dir, html_dir1) assert "index-1.py" in [p.name for p in html_dir1.iterdir()] # Make sure source scripts are NOT created when # plot_html_show_source_link` is False - html_dir2 = source_dir / '_build' / 'html2' - build_sphinx_html(source_dir, doctree_dir, html_dir2, + html_dir2 = tmp_path / '_build' / 'html2' + build_sphinx_html(tmp_path, doctree_dir, html_dir2, extra_args=['-D', 'plot_html_show_source_link=0']) assert "index-1.py" not in [p.name for p in html_dir2.iterdir()] -def build_sphinx_html(source_dir, doctree_dir, html_dir, extra_args=None): +@pytest.mark.parametrize('plot_html_show_source_link', [0, 1]) +def test_show_source_link_true(tmp_path, plot_html_show_source_link): + # Test that a source link is generated if :show-source-link: is true, + # whether or not plot_html_show_source_link is true. + parent = Path(__file__).parent + shutil.copyfile(parent / 'tinypages/conf.py', tmp_path / 'conf.py') + shutil.copytree(parent / 'tinypages/_static', tmp_path / '_static') + doctree_dir = tmp_path / 'doctrees' + (tmp_path / 'index.rst').write_text(""" +.. plot:: + :show-source-link: true + + plt.plot(range(2)) +""") + html_dir = tmp_path / '_build' / 'html' + build_sphinx_html(tmp_path, doctree_dir, html_dir, extra_args=[ + '-D', f'plot_html_show_source_link={plot_html_show_source_link}']) + assert "index-1.py" in [p.name for p in html_dir.iterdir()] + + +@pytest.mark.parametrize('plot_html_show_source_link', [0, 1]) +def test_show_source_link_false(tmp_path, plot_html_show_source_link): + # Test that a source link is NOT generated if :show-source-link: is false, + # whether or not plot_html_show_source_link is true. + parent = Path(__file__).parent + shutil.copyfile(parent / 'tinypages/conf.py', tmp_path / 'conf.py') + shutil.copytree(parent / 'tinypages/_static', tmp_path / '_static') + doctree_dir = tmp_path / 'doctrees' + (tmp_path / 'index.rst').write_text(""" +.. plot:: + :show-source-link: false + + plt.plot(range(2)) +""") + html_dir = tmp_path / '_build' / 'html' + build_sphinx_html(tmp_path, doctree_dir, html_dir, extra_args=[ + '-D', f'plot_html_show_source_link={plot_html_show_source_link}']) + assert "index-1.py" not in [p.name for p in html_dir.iterdir()] + + +def build_sphinx_html(tmp_path, doctree_dir, html_dir, extra_args=None): # Build the pages with warnings turned into errors extra_args = [] if extra_args is None else extra_args cmd = [sys.executable, '-msphinx', '-W', '-b', 'html', - '-d', str(doctree_dir), str(source_dir), str(html_dir), *extra_args] + '-d', str(doctree_dir), str(tmp_path), str(html_dir), *extra_args] proc = Popen(cmd, stdout=PIPE, stderr=PIPE, universal_newlines=True, env={**os.environ, "MPLBACKEND": ""}) out, err = proc.communicate() 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