@@ -429,14 +429,23 @@ def filenames(self):
429429 return [self .filename (fmt ) for fmt in self .formats ]
430430
431431
432- def out_of_date (original , derived ):
432+ def out_of_date (original , derived , includes = None ):
433433 """
434- Return whether *derived* is out-of-date relative to *original*, both of
435- which are full file paths.
434+ Return whether *derived* is out-of-date relative to *original* or any of
435+ the RST files included in it using the RST include directive (*includes*).
436+ *derived* and *original* are full paths, and *includes* is optionally a
437+ list of full paths which may have been included in the *original*.
436438 """
437- return (not os .path .exists (derived ) or
438- (os .path .exists (original ) and
439- os .stat (derived ).st_mtime < os .stat (original ).st_mtime ))
439+ if includes is None :
440+ includes = []
441+ files_to_check = [original , * includes ]
442+
443+ def out_of_date_one (original , derived ):
444+ return (not os .path .exists (derived ) or
445+ (os .path .exists (original ) and
446+ os .stat (derived ).st_mtime < os .stat (original ).st_mtime ))
447+
448+ return any (out_of_date_one (f , derived ) for f in files_to_check )
440449
441450
442451class PlotError (RuntimeError ):
@@ -532,7 +541,8 @@ def get_plot_formats(config):
532541
533542def render_figures (code , code_path , output_dir , output_base , context ,
534543 function_name , config , context_reset = False ,
535- close_figs = False ):
544+ close_figs = False ,
545+ code_includes = None ):
536546 """
537547 Run a pyplot script and save the images in *output_dir*.
538548
@@ -742,6 +752,25 @@ def run(arguments, content, options, state_machine, state, lineno):
742752 build_dir_link = build_dir
743753 source_link = dest_dir_link + '/' + output_base + source_ext
744754
755+ # get list of included rst files so that the output is updated when any
756+ # plots in the included files change. These attributes are modified by the
757+ # include directive (see the docutils.parsers.rst.directives.misc module).
758+ try :
759+ source_file_includes = [os .path .join (os .getcwd (), t [0 ])
760+ for t in state .document .include_log ]
761+ except AttributeError :
762+ # the document.include_log attribute only exists in docutils >=0.17,
763+ # before that we need to inspect the state machine
764+ possible_sources = [os .path .join (setup .confdir , t [0 ])
765+ for t in state_machine .input_lines .items ]
766+ source_file_includes = [f for f in set (possible_sources )
767+ if os .path .isfile (f )]
768+ # remove the source file itself from the includes
769+ try :
770+ source_file_includes .remove (source_file_name )
771+ except ValueError :
772+ pass
773+
745774 # make figures
746775 try :
747776 results = render_figures (code ,
@@ -752,7 +781,8 @@ def run(arguments, content, options, state_machine, state, lineno):
752781 function_name ,
753782 config ,
754783 context_reset = context_opt == 'reset' ,
755- close_figs = context_opt == 'close-figs' )
784+ close_figs = context_opt == 'close-figs' ,
785+ code_includes = source_file_includes )
756786 errors = []
757787 except PlotError as err :
758788 reporter = state .memo .reporter
0 commit comments