Skip to content

Commit 409511b

Browse files
committed
Check modification times of included files in plot_directive
Fixes matplotlib#17860.
1 parent d385b2c commit 409511b

File tree

1 file changed

+38
-8
lines changed

1 file changed

+38
-8
lines changed

lib/matplotlib/sphinxext/plot_directive.py

Lines changed: 38 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -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

442451
class PlotError(RuntimeError):
@@ -532,7 +541,8 @@ def get_plot_formats(config):
532541

533542
def 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

Comments
 (0)