148148import traceback
149149import warnings
150150
151- from docutils .parsers .rst import directives
151+ from docutils import nodes
152+ from docutils .parsers .rst import directives , Directive
152153from docutils .parsers .rst .directives .images import Image
153154align = Image .align
154155import jinja2 # Sphinx dependency.
176177
177178def plot_directive (name , arguments , options , content , lineno ,
178179 content_offset , block_text , state , state_machine ):
179- """Implementation of the ``.. plot::`` directive.
180+ """Deprecated function-based implementation of the ``.. plot::`` directive.
180181
181- See the module docstring for details.
182+ Use PlotDirective instead.
183+ See the module docstring for details on configuration.
182184 """
183185 return run (arguments , content , options , state_machine , state , lineno )
184186
@@ -241,25 +243,45 @@ def mark_plot_labels(app, document):
241243 break
242244
243245
246+ class PlotDirective (Directive ):
247+ """Implementation of the ``.. plot::`` directive.
248+
249+ See the module docstring for details.
250+ """
251+
252+ has_content = True
253+ required_arguments = 0
254+ optional_arguments = 2
255+ final_argument_whitespace = False
256+ option_spec = {
257+ 'alt' : directives .unchanged ,
258+ 'height' : directives .length_or_unitless ,
259+ 'width' : directives .length_or_percentage_or_unitless ,
260+ 'scale' : directives .nonnegative_int ,
261+ 'align' : _option_align ,
262+ 'class' : directives .class_option ,
263+ 'include-source' : _option_boolean ,
264+ 'format' : _option_format ,
265+ 'context' : _option_context ,
266+ 'nofigs' : directives .flag ,
267+ 'encoding' : directives .encoding ,
268+ }
269+
270+ def run (self ):
271+ """Run the plot directive."""
272+ return run (self .arguments , self .content , self .options ,
273+ self .state_machine , self .state , self .lineno ,
274+ function = False )
275+
276+
244277def setup (app ):
245278 setup .app = app
246279 setup .config = app .config
247280 setup .confdir = app .confdir
248-
249- options = {'alt' : directives .unchanged ,
250- 'height' : directives .length_or_unitless ,
251- 'width' : directives .length_or_percentage_or_unitless ,
252- 'scale' : directives .nonnegative_int ,
253- 'align' : _option_align ,
254- 'class' : directives .class_option ,
255- 'include-source' : _option_boolean ,
256- 'format' : _option_format ,
257- 'context' : _option_context ,
258- 'nofigs' : directives .flag ,
259- 'encoding' : directives .encoding
260- }
261-
262- app .add_directive ('plot' , plot_directive , True , (0 , 2 , False ), ** options )
281+ # Old, function-based method was equivalent to:
282+ # app.add_directive('plot', plot_directive, True, (0, 2, False),
283+ # **PlotDirective.option_spec)
284+ app .add_directive ('plot' , PlotDirective )
263285 app .add_config_value ('plot_pre_code' , None , True )
264286 app .add_config_value ('plot_include_source' , False , True )
265287 app .add_config_value ('plot_html_show_source_link' , True , True )
@@ -273,7 +295,8 @@ def setup(app):
273295
274296 app .connect ('doctree-read' , mark_plot_labels )
275297
276- metadata = {'parallel_read_safe' : True , 'parallel_write_safe' : True }
298+ metadata = {'parallel_read_safe' : True , 'parallel_write_safe' : True ,
299+ 'version' : 0.2 }
277300 return metadata
278301
279302
@@ -630,7 +653,8 @@ def render_figures(code, code_path, output_dir, output_base, context,
630653 return results
631654
632655
633- def run (arguments , content , options , state_machine , state , lineno ):
656+ def run (arguments , content , options , state_machine , state , lineno ,
657+ function = True ):
634658 document = state_machine .document
635659 config = document .settings .env .config
636660 nofigs = 'nofigs' in options
@@ -800,9 +824,6 @@ def run(arguments, content, options, state_machine, state, lineno):
800824 total_lines .extend (result .split ("\n " ))
801825 total_lines .extend ("\n " )
802826
803- if total_lines :
804- state_machine .insert_input (total_lines , source = source_file_name )
805-
806827 # copy image files to builder's output directory, if necessary
807828 Path (dest_dir ).mkdir (parents = True , exist_ok = True )
808829
@@ -818,4 +839,14 @@ def run(arguments, content, options, state_machine, state, lineno):
818839 unescape_doctest (code ) if source_file_name == rst_file else code ,
819840 encoding = 'utf-8' )
820841
821- return errors
842+ if function :
843+ if total_lines :
844+ state_machine .insert_input (total_lines , source = source_file_name )
845+ out = errors
846+ else :
847+ if len (errors ):
848+ out = errors
849+ else :
850+ out = [nodes .raw ('\n ' .join (total_lines ))] if total_lines else []
851+
852+ return out
0 commit comments