From c153cfb350198574708a5fa18b8ae2891bbdc954 Mon Sep 17 00:00:00 2001 From: Eric Larson Date: Wed, 9 Jan 2019 14:00:45 -0500 Subject: [PATCH 1/4] API: Use class-based directive in sphinxext --- lib/matplotlib/sphinxext/plot_directive.py | 79 +++++++++++++++------- 1 file changed, 55 insertions(+), 24 deletions(-) diff --git a/lib/matplotlib/sphinxext/plot_directive.py b/lib/matplotlib/sphinxext/plot_directive.py index 2d1ad2a2b353..c885ae8061ae 100644 --- a/lib/matplotlib/sphinxext/plot_directive.py +++ b/lib/matplotlib/sphinxext/plot_directive.py @@ -148,7 +148,8 @@ import traceback import warnings -from docutils.parsers.rst import directives +from docutils import nodes +from docutils.parsers.rst import directives, Directive from docutils.parsers.rst.directives.images import Image align = Image.align import jinja2 # Sphinx dependency. @@ -176,9 +177,10 @@ def plot_directive(name, arguments, options, content, lineno, content_offset, block_text, state, state_machine): - """Implementation of the ``.. plot::`` directive. + """Deprecated function-based implementation of the ``.. plot::`` directive. - See the module docstring for details. + Use PlotDirective instead. + See the module docstring for details on configuration. """ return run(arguments, content, options, state_machine, state, lineno) @@ -241,25 +243,45 @@ def mark_plot_labels(app, document): break +class PlotDirective(Directive): + """Implementation of the ``.. plot::`` directive. + + See the module docstring for details. + """ + + has_content = True + required_arguments = 0 + optional_arguments = 2 + final_argument_whitespace = False + option_spec = { + 'alt': directives.unchanged, + 'height': directives.length_or_unitless, + 'width': directives.length_or_percentage_or_unitless, + 'scale': directives.nonnegative_int, + 'align': _option_align, + 'class': directives.class_option, + 'include-source': _option_boolean, + 'format': _option_format, + 'context': _option_context, + 'nofigs': directives.flag, + 'encoding': directives.encoding, + } + + def run(self): + """Run the plot directive.""" + return run(self.arguments, self.content, self.options, + self.state_machine, self.state, self.lineno, + function=False) + + def setup(app): setup.app = app setup.config = app.config setup.confdir = app.confdir - - options = {'alt': directives.unchanged, - 'height': directives.length_or_unitless, - 'width': directives.length_or_percentage_or_unitless, - 'scale': directives.nonnegative_int, - 'align': _option_align, - 'class': directives.class_option, - 'include-source': _option_boolean, - 'format': _option_format, - 'context': _option_context, - 'nofigs': directives.flag, - 'encoding': directives.encoding - } - - app.add_directive('plot', plot_directive, True, (0, 2, False), **options) + # Old, function-based method was equivalent to: + # app.add_directive('plot', plot_directive, True, (0, 2, False), + # **PlotDirective.option_spec) + app.add_directive('plot', PlotDirective) app.add_config_value('plot_pre_code', None, True) app.add_config_value('plot_include_source', False, True) app.add_config_value('plot_html_show_source_link', True, True) @@ -273,7 +295,8 @@ def setup(app): app.connect('doctree-read', mark_plot_labels) - metadata = {'parallel_read_safe': True, 'parallel_write_safe': True} + metadata = {'parallel_read_safe': True, 'parallel_write_safe': True, + 'version': 0.2} return metadata @@ -630,7 +653,8 @@ def render_figures(code, code_path, output_dir, output_base, context, return results -def run(arguments, content, options, state_machine, state, lineno): +def run(arguments, content, options, state_machine, state, lineno, + function=True): document = state_machine.document config = document.settings.env.config nofigs = 'nofigs' in options @@ -800,9 +824,6 @@ def run(arguments, content, options, state_machine, state, lineno): total_lines.extend(result.split("\n")) total_lines.extend("\n") - if total_lines: - state_machine.insert_input(total_lines, source=source_file_name) - # copy image files to builder's output directory, if necessary Path(dest_dir).mkdir(parents=True, exist_ok=True) @@ -818,4 +839,14 @@ def run(arguments, content, options, state_machine, state, lineno): unescape_doctest(code) if source_file_name == rst_file else code, encoding='utf-8') - return errors + if function: + if total_lines: + state_machine.insert_input(total_lines, source=source_file_name) + out = errors + else: + if len(errors): + out = errors + else: + out = [nodes.raw('\n'.join(total_lines))] if total_lines else [] + + return out From 8a103647937908ffe962e388dffa068934a0cbfc Mon Sep 17 00:00:00 2001 From: Eric Larson Date: Wed, 9 Jan 2019 14:11:21 -0500 Subject: [PATCH 2/4] DOC: Changes --- doc/api/next_api_changes/2019-01-09-deprecations.rst | 8 ++++++++ 1 file changed, 8 insertions(+) create mode 100644 doc/api/next_api_changes/2019-01-09-deprecations.rst diff --git a/doc/api/next_api_changes/2019-01-09-deprecations.rst b/doc/api/next_api_changes/2019-01-09-deprecations.rst new file mode 100644 index 000000000000..b179dcd9f5cb --- /dev/null +++ b/doc/api/next_api_changes/2019-01-09-deprecations.rst @@ -0,0 +1,8 @@ +Deprecations +```````````` + +The ``matplotlib.sphinxext.plot_directive`` interface has changed from +the (Sphinx-)deprecated function-based interface to a class-based interface. +This should not affect end users, but the +``matplotlib.sphinxext.plot_directive.plot_directive`` function is now +deprecated. From 66201355ea9ee6324676a5d8c0cb28d9463b5673 Mon Sep 17 00:00:00 2001 From: Eric Larson Date: Wed, 9 Jan 2019 19:19:31 -0500 Subject: [PATCH 3/4] FIX: Refactor --- lib/matplotlib/sphinxext/plot_directive.py | 36 ++++++++-------------- 1 file changed, 12 insertions(+), 24 deletions(-) diff --git a/lib/matplotlib/sphinxext/plot_directive.py b/lib/matplotlib/sphinxext/plot_directive.py index c885ae8061ae..1ab5aa5e17dd 100644 --- a/lib/matplotlib/sphinxext/plot_directive.py +++ b/lib/matplotlib/sphinxext/plot_directive.py @@ -148,10 +148,8 @@ import traceback import warnings -from docutils import nodes from docutils.parsers.rst import directives, Directive from docutils.parsers.rst.directives.images import Image -align = Image.align import jinja2 # Sphinx dependency. import matplotlib @@ -166,6 +164,7 @@ else: import matplotlib.pyplot as plt from matplotlib import _pylab_helpers, cbook +align = Image.align __version__ = 2 @@ -175,12 +174,12 @@ # ----------------------------------------------------------------------------- +@cbook.deprecated("3.1", alternative="PlotDirective") def plot_directive(name, arguments, options, content, lineno, content_offset, block_text, state, state_machine): - """Deprecated function-based implementation of the ``.. plot::`` directive. + """Implementation of the ``.. plot::`` directive. - Use PlotDirective instead. - See the module docstring for details on configuration. + See the module docstring for details. """ return run(arguments, content, options, state_machine, state, lineno) @@ -270,17 +269,14 @@ class PlotDirective(Directive): def run(self): """Run the plot directive.""" return run(self.arguments, self.content, self.options, - self.state_machine, self.state, self.lineno, - function=False) + self.state_machine, self.state, self.lineno) def setup(app): + import matplotlib setup.app = app setup.config = app.config setup.confdir = app.confdir - # Old, function-based method was equivalent to: - # app.add_directive('plot', plot_directive, True, (0, 2, False), - # **PlotDirective.option_spec) app.add_directive('plot', PlotDirective) app.add_config_value('plot_pre_code', None, True) app.add_config_value('plot_include_source', False, True) @@ -296,7 +292,7 @@ def setup(app): app.connect('doctree-read', mark_plot_labels) metadata = {'parallel_read_safe': True, 'parallel_write_safe': True, - 'version': 0.2} + 'version': matplotlib.__version__} return metadata @@ -653,8 +649,7 @@ def render_figures(code, code_path, output_dir, output_base, context, return results -def run(arguments, content, options, state_machine, state, lineno, - function=True): +def run(arguments, content, options, state_machine, state, lineno): document = state_machine.document config = document.settings.env.config nofigs = 'nofigs' in options @@ -824,6 +819,9 @@ def run(arguments, content, options, state_machine, state, lineno, total_lines.extend(result.split("\n")) total_lines.extend("\n") + if total_lines: + state_machine.insert_input(total_lines, source=source_file_name) + # copy image files to builder's output directory, if necessary Path(dest_dir).mkdir(parents=True, exist_ok=True) @@ -839,14 +837,4 @@ def run(arguments, content, options, state_machine, state, lineno, unescape_doctest(code) if source_file_name == rst_file else code, encoding='utf-8') - if function: - if total_lines: - state_machine.insert_input(total_lines, source=source_file_name) - out = errors - else: - if len(errors): - out = errors - else: - out = [nodes.raw('\n'.join(total_lines))] if total_lines else [] - - return out + return errors From 348531deada3e0e4748b9e219b862655d8fea42c Mon Sep 17 00:00:00 2001 From: Eric Larson Date: Wed, 9 Jan 2019 19:43:33 -0500 Subject: [PATCH 4/4] FIX: Remove ignore --- .flake8 | 1 - 1 file changed, 1 deletion(-) diff --git a/.flake8 b/.flake8 index a83dd15d4136..2754bc04e4c4 100644 --- a/.flake8 +++ b/.flake8 @@ -42,7 +42,6 @@ per-file-ignores = matplotlib/projections/geo.py: E203, E221, E502 matplotlib/pylab.py: E501 matplotlib/rcsetup.py: E501 - matplotlib/sphinxext/plot_directive.py: E402 matplotlib/tests/test_mathtext.py: E501 matplotlib/transforms.py: E201, E202, E203, E501 matplotlib/tri/triinterpolate.py: E201, E221