leo-colisson / robust-externalize

A LaTeX library to cache pictures (including tikz, python code, and more) in a robust, customizable, and pure way.
7 stars 2 forks source link

[Feature Request] Python. Stop compilation if plt.savefig not present. #45

Closed dflvunoooooo closed 1 month ago

dflvunoooooo commented 1 month ago

Is it possible to stop the compilation process and throw a warning if the plt.savefig command is not present or commented out? I just copied a 600 line program and missed to copy the plt.savefig command and the compiler didn't ever stop. There was no error or anything, the compilation just never finished.

tobiasBora commented 1 month ago

You should be able to add (not tested) in your preset:

if matches={plt.savefig}{/utils/exec={\PackageError{dflvunoooooo}{I found no plt.savefig line in your code}{Maybe try to add one}}}

but I don't want to make this default since users might generate content in a different way. What is more surprising is that the compilation does not stop (unless if python does not stop itself). If you can provide a mwe with the exact command that you run, it might help.

dflvunoooooo commented 1 month ago

It makes sense not to set it as default, you are right.

Your code works in a way. I now get an error for every occurance of plt.savefig :) Is it possible to inverse the match? I didn't find anything about that in the manual.

tobiasBora commented 1 month ago

Ahahah of course, stupid me. Maybe try this:

/utils/exec={\def\PltSavefigNotFound{}},
if matches={plt.savefig}{/utils/exec={\let\PltSavefigNotFound\undefined}},
execute after each externalization={\ifdefined\PltSavefigNotFound\PackageError{dflvunoooooo}{I found no plt.savefig line in your code}{Maybe try to add one}\fi},

I should maybe provide a simpler if matches else={…}{…}{…} construction.

dflvunoooooo commented 1 month ago

Hm, this dos compile if plt.savefig is present, but it still compiles forever if not present. Here is a mwe:

\documentclass{scrreport}

\usepackage{robust-externalize}

\robExtConfigure{
    new preset={python matplotlib pgf mit template}{
        python,
        custom include command={\evalPlaceholder{\cacheMe[tikz]{\input{__ROBEXT_OUTPUT_PREFIX__.pgf}}}}
        if matches={plt.savefig}{/utils/exec={\let\PltSavefigNotFound\undefined}},
        execute after each externalization={\ifdefined\PltSavefigNotFound\PackageError{robust-externalize}{I found no plt.savefig line in your code}{Maybe try to add one}\fi},
    },
}

\begin{document}
\begin{figure}
    \centering
    \begin{CacheMeCode}{python matplotlib pgf mit template,     % itarnetrin uaertniaetrniae             
        set placeholder eval={__BREITE__}{\lenToCmNoUnit[in]{\textwidth}},  
        set placeholder eval={__HOEHE__}{\lenToCmNoUnit[in]{.71\textwidth}}, 
    }
        # Python-Code beginnt.
        import matplotlib.pyplot as plt
        import matplotlib
        matplotlib.use("pgf")

        year = [2014, 2015, 2016, 2017, 2018, 2019]
        tutorial_count = [39, 117, 111, 110, 67, 29]
        plt.plot(year, tutorial_count, color="#6c3376", linewidth=3)
        plt.xlabel('Year')
        plt.ylabel('Number of futurestud.io Tutorials')
        #plt.savefig(get_filename_from_extension(".pgf"), bbox_inches="tight")
    \end{CacheMeCode}
    \caption{blabla.}%
    \label{py:22Na-64-Winkelkorrelation}
\end{figure}
\end{document}
tobiasBora commented 1 month ago

Ok so:

  1. Infinite compilation is fixed now (bug on my side forgetting -interaction=nonstopmode (warning: this will invalidate previous latex cache, just copy an older .sty or see doc to avoid this)
  2. Make sure to add coma between configuration lines
  3. I introduced if matches else to create a clearer error message

Reopen if you still experience issues.

\documentclass{scrreport}

\usepackage{robust-externalize}

\robExtConfigure{
    new preset={python matplotlib pgf mit template}{
        python,
        custom include command={\evalPlaceholder{\cacheMe[tikz]{\input{__ROBEXT_OUTPUT_PREFIX__.pgf}}}},
        if matches else={plt.savefig}{}{/utils/exec={\PackageError{robust-externalize}{I found no plt.savefig line in your code}{Maybe try to add one}}},
        % if matches={plt.savefig}{/utils/exec={\let\PltSavefigNotFound\undefined}},
        % execute after each externalization={\ifdefined\PltSavefigNotFound\PackageError{robust-externalize}{I found no plt.savefig line in your code}{Maybe try to add one}\fi},
    },
}

\begin{document}
\begin{figure}
    \centering
    \begin{CacheMeCode}{python matplotlib pgf mit template,     % itarnetrin uaertniaetrniae             
        set placeholder eval={__BREITE__}{\lenToCmNoUnit[in]{\textwidth}},  
        set placeholder eval={__HOEHE__}{\lenToCmNoUnit[in]{.71\textwidth}}, 
    }
        # Python-Code beginnt.
        import matplotlib.pyplot as plt
        import matplotlib
        matplotlib.use("pgf")

        year = [2014, 2015, 2016, 2017, 2018, 2019]
        tutorial_count = [39, 117, 111, 110, 67, 29]
        plt.plot(year, tutorial_count, color="#6c3376", linewidth=3)
        plt.xlabel('Year')
        plt.ylabel('Number of futurestud.io Tutorials')
    \end{CacheMeCode}
    \caption{blabla.}%
    \label{py:22Na-64-Winkelkorrelation}
\end{figure}
\end{document}
dflvunoooooo commented 1 month ago

Great work, thank you for fixing the issue that fast! I can confirm, that the fix stops the compilation.

Only the line if matches else={plt.savefig}{}{/utils/exec={\PackageError{robust-externalize}{I found no plt.savefig line in your code}{Maybe try to add one}}}, does not seem to make any difference.

tobiasBora commented 1 month ago

Only the line … does not seem to make any difference.

You made sure to include a comma to separate it from the previous entry? Can you post your example?

dflvunoooooo commented 1 month ago

Yes. It stops if no plt.savefig is present, but not with the customized error message.

\documentclass{scrreport}

\usepackage{robust-externalize}

\robExtConfigure{
    new preset={python matplotlib pgf mit template}{
        python,
        custom include command={\evalPlaceholder{\cacheMe[tikz]{\input{__ROBEXT_OUTPUT_PREFIX__.pgf}}}},
        if matches else={plt.savefig}{}{/utils/exec={\PackageError{robust-externalize}{I found no plt.savefig line in your code}{Maybe try to add one}}},
    },
}

\begin{document}
\begin{figure}
    \centering
    \begin{CacheMeCode}{python matplotlib pgf mit template,     % itarnetrin uaertniaetrniae             
        set placeholder eval={__BREITE__}{\lenToCmNoUnit[in]{\textwidth}},  
        set placeholder eval={__HOEHE__}{\lenToCmNoUnit[in]{.71\textwidth}}, 
    }
        # Python-Code beginnt.
        import matplotlib.pyplot as plt
        import matplotlib
        matplotlib.use("pgf")

        year = [2014, 2015, 2016, 2017, 2018, 2019]
        tutorial_count = [39, 117, 111, 110, 67, 29]
        plt.plot(year, tutorial_count, color="#6c3376", linewidth=3)
        plt.xlabel('Year')
        plt.ylabel('Number of futurestud.io Tutorials')
        #plt.savefig(get_filename_from_extension(".pgf"), bbox_inches="tight")
    \end{CacheMeCode}
    \caption{blabla.}%
    \label{py:22Na-64-Winkelkorrelation}
\end{figure}
\end{document}
tobiasBora commented 1 month ago

Ahah, of course, it's because your code HAS savefig inside, robust-externalize is too dump to realize that it is commented ^^ Just remove the

        #plt.savefig(get_filename_from_extension(".pgf"), bbox_inches="tight")

line and it should work just as intended.

dflvunoooooo commented 1 month ago

Oh, that makes sense, my bad. Thank you very much!

dflvunoooooo commented 1 month ago

Hm, no, it still doesn't raise the customized error. The compilation fails with:

Enter file name:
! Emergency stop.
<read *>

l.15 ...bExt-B1E6942D6D91D26F082942694E833DED.pgf}
                                                  %^^M
!  ==> Fatal error occurred, no output PDF file produced!
Transcript written on robExt-F1110278CE3F2DEE316914AFBF946226.log.
-------- End of the full log --------

~/Daten/Latex/_Problem/robust-externalize plt.savefig/test_python.tex:30: Package robExt Error: The compilation of the code block at line 30 failed:
(robExt)                the following file is indeed missing:
(robExt)               
robustExternalize/robExt-F1110278CE3F2DEE316914AFBF946226.pdf.