diff --git a/NEWS.rst b/NEWS.rst index 69b60da..69057dd 100644 --- a/NEWS.rst +++ b/NEWS.rst @@ -7,6 +7,35 @@ Version History =============== +v0.19 (2026/02/15) +------------------ + +* Fixed backslash escapes in docstrings and regexes for syntax compatibility + with Python 3.11+. + +* ``js`` now works as a command family for JavaScript (#197). + +* Python console commands and environments are now compatible with Python + 3.14 (#229). + +* Fixed a bug that could cause non-Windows operating systems to attempt to + invoke a nonexistent batch file when the executable associated with a + language is not found (#225). + +* Replaced doctype ``tex`` with ``texminted`` for ``Weave.jl`` (#219). + +* Fixed a bug that resulted in uncaught exceptions when ``\inputpygments`` + was used with files that do not exist (#64). + +* Fixed a bug in tracking the number of Pygments errors (#206). + +* Improved error messages (#207, #209). Improved documentation for + ``--error-exit-code`` (#208). + +* Several minor improvements to documentation. + + + v0.18 (2021/06/06) ------------------ diff --git a/README.rst b/README.rst index 7be4cea..2854032 100644 --- a/README.rst +++ b/README.rst @@ -94,6 +94,24 @@ in any resulting publications. The best and most recent paper is in `2013 SciPy proceedings `_. +Development status +================== + +Since 2020, I am increasingly creating new teaching materials with Markdown +and HTML instead of PythonTeX and LaTeX. I have limited time for developing +open-source software that I do not use frequently myself. There should be +occasional releases to keep PythonTeX running, but no major changes or +significant new features are anticipated. + +I have been developing `Codebraid `_ since 2019, +partially to have a PythonTeX equivalent for Markdown but also in the hope +that it could eventually be integrated with LaTeX as a PythonTeX replacement. +As part of `minted `_ version 3, I created +new software for passing data between LaTeX and Python. I cannot make any +guarantees, but I hope that this will eventually make it possible to create a +new LaTeX package based on Codebraid, with significant PythonTeX compatibility. + + License ======= diff --git a/pythontex/README b/pythontex/README index 8928d3d..14c2e82 100644 --- a/pythontex/README +++ b/pythontex/README @@ -3,7 +3,7 @@ =================================================================== :Author: Geoffrey Poore -:Version: 0.18 (2021/06/06) +:Version: 0.19 (2026/02/15) :License: LPPL v1.3 or later (LaTeX code) and BSD 3-Clause (Python code) :Development: https://github.com/gpoore/pythontex :Requirements: Python 2.7 or 3.2+; Pygments diff --git a/pythontex/depythontex.py b/pythontex/depythontex.py index 3d48e3b..f015c15 100644 --- a/pythontex/depythontex.py +++ b/pythontex/depythontex.py @@ -9,7 +9,7 @@ launch depythontex2.py or depythontex3.py directly. The version of Python does not matter for depythontex, since no code is executed. -Copyright (c) 2013-2017, Geoffrey M. Poore +Copyright (c) 2013-2026, Geoffrey M. Poore All rights reserved. Licensed under the BSD 3-Clause License: http://www.opensource.org/licenses/BSD-3-Clause diff --git a/pythontex/depythontex2.py b/pythontex/depythontex2.py index 997a30d..6e5a7f8 100644 --- a/pythontex/depythontex2.py +++ b/pythontex/depythontex2.py @@ -47,7 +47,7 @@ typeset with a different package. -Copyright (c) 2013-2021, Geoffrey M. Poore +Copyright (c) 2013-2026, Geoffrey M. Poore All rights reserved. Licensed under the BSD 3-Clause License: http://www.opensource.org/licenses/BSD-3-Clause @@ -86,7 +86,7 @@ # Script parameters # Version -__version__ = '0.18' +__version__ = '0.19' # Functions and parameters for customizing the script output @@ -760,7 +760,7 @@ def replace_print_env(name, arglist, linenum, if not os.path.isfile(depytxfile_name): print('* DePythonTeX error:') print(' Could not find DePythonTeX auxiliary file "' + depytxfile_name + '"') - print(' Use package option depythontex to creat it') + print(' Use package option depythontex to create it') sys.exit(1) diff --git a/pythontex/depythontex3.py b/pythontex/depythontex3.py index e27abea..e19f102 100644 --- a/pythontex/depythontex3.py +++ b/pythontex/depythontex3.py @@ -29,7 +29,7 @@ facilitate customization. Most of the key substitutions are performed by a few functions defined near the beginning of the script, so if you need custom substitutions, you should begin there. By default, all typeset code is -wrapped in `\verb` commands and verbatim environments, since these have the +wrapped in `\\verb` commands and verbatim environments, since these have the greatest generality. However, the command-line option --listing allows code to be typeset with the fancyvrb, listings, minted, or PythonTeX packages instead. @@ -47,7 +47,7 @@ typeset with a different package. -Copyright (c) 2013-2021, Geoffrey M. Poore +Copyright (c) 2013-2026, Geoffrey M. Poore All rights reserved. Licensed under the BSD 3-Clause License: http://www.opensource.org/licenses/BSD-3-Clause @@ -86,7 +86,7 @@ # Script parameters # Version -__version__ = '0.18' +__version__ = '0.19' # Functions and parameters for customizing the script output @@ -121,7 +121,7 @@ def replace_code_cmd(name, arglist, linenum, code_replacement, Usually, code from a command is also typeset with a command. This function primarily deals with that case. In cases where code from a - command is typeset with an environment (for example, `\inputpygments`), + command is typeset with an environment (for example, `\\inputpygments`), this function performs some preprocessing and then uses replace_code_env() to do the real work. This approach prevents the two functions from unnecessarily duplicating each other, while still giving @@ -161,7 +161,7 @@ def replace_code_cmd(name, arglist, linenum, code_replacement, # Make sure the introduction of an environment where a command was # previously won't produce errors with following content; make sure # that any following content is on a separate line - if bool(match('[ \t]*\S', after)): + if bool(match(r'[ \t]*\S', after)): after = '\n' + after # Rather than duplicating much of replace_code_env(), just use it return replace_code_env(name, arglist, linenum, code_replacement, @@ -333,7 +333,7 @@ def replace_print_cmd(name, arglist, linenum, break print_replacement = r'\verb' + delim + print_replacement + delim elif print_replacement_mode == 'verbatim': - if bool(match('\s*?\n', after)): + if bool(match(r'\s*?\n', after)): # Usually, we would end the verbatim environment with a newline. # This is fine if there is content in `after` before the next # newline---in fact, it's desirable, because the verbatim package @@ -405,11 +405,11 @@ def replace_print_cmd(name, arglist, linenum, # the `\input` content. print_replacement = print_replacement.rstrip(' \t\n') after = sub(r'^\\unskip\s+', '', after) - elif bool(match('\S', after)): + elif bool(match(r'\S', after)): # If the next character is not whitespace, we can just leave # the `\n`, and it will yield a space. pass - elif bool(match('\s*$', after)): + elif bool(match(r'\s*$', after)): # If the rest of the current line, and the next line, are # whitespace, we will get the correct spacing without needing # `\space{}`. We could leave `\n`, but it would be @@ -421,14 +421,14 @@ def replace_print_cmd(name, arglist, linenum, # it's at the end of an environment, and thus is needed to # protect the following content print_replacement += '\\space{}' - after = sub('^\s+', '', after) + after = sub(r'^\s+', '', after) forced_double_space_list.append((name, linenum)) else: - if bool(match('\s+\S', after)): + if bool(match(r'\s+\S', after)): # If the following line starts with whitespace, replace it # with a newline, to protect in the event that the printed # content ended with an end-of-environment command - after = sub('^\s+', '\n', after) + after = sub(r'^\s+', '\n', after) # Issue warnings, if warranted # Warn about `\endinput` if (r'\endinput' in print_replacement and @@ -505,7 +505,7 @@ def replace_print_env(name, arglist, linenum, #### The inlineverb and verb modes should work, but haven't been tested since there are currently no environments that use them; they are only - used by `\printpythontex`, which is a command. + used by `\\printpythontex`, which is a command. ''' if print_replacement_mode == 'verb': if print_replacement.count('\n') > 1: @@ -519,17 +519,17 @@ def replace_print_env(name, arglist, linenum, if delim not in print_replacement: break print_replacement = r'\verb' + delim + print_replacement + delim - if not bool(match('[ \t]+\S', after)): + if not bool(match(r'[ \t]+\S', after)): # If there is text on the same line as the end of the # environment, we're fine (this is unusual). Otherwise, # we need to toss the newline at the end of the environment # and gobble leading spaces. Leading spaces need to be # gobbled because previously they were at the beginning of a # line, where they would have been discarded. - if not bool(match('\s*$', after)): - after = sub('^\s*?\n\s*', '', after) + if not bool(match(r'\s*$', after)): + after = sub(r'^\s*?\n\s*', '', after) elif print_replacement_mode == 'verbatim': - if bool(match('\s*?\n', after)): + if bool(match(r'\s*?\n', after)): # Usually, we would end the verbatim environment with a newline. # This is fine if there is content in `after` before the next # newline---in fact, it's desirable, because the verbatim package @@ -570,15 +570,15 @@ def replace_print_env(name, arglist, linenum, # printed content. Later, we issue a warning in case it appears # anywhere else. print_replacement = print_replacement.rsplit(r'\endinput', 1)[0] - if not bool(match('[ \t]+\S', after)): + if not bool(match(r'[ \t]+\S', after)): # If there is text on the same line as the end of the # environment, we're fine (this is unusual). Otherwise, # we need to toss the newline at the end of the environment # and gobble leading spaces. Leading spaces need to be # gobbled because previously they were at the beginning of a # line, where they would have been discarded. - if not bool(match('\s*$', after)): - after = sub('^\s*?\n\s*', '', after) + if not bool(match(r'\s*$', after)): + after = sub(r'^\s*?\n\s*', '', after) elif (print_replacement.endswith('%\n') and not print_replacement.endswith('\\%\n') and not print_replacement.endswith('\\string%\n')): @@ -590,15 +590,15 @@ def replace_print_env(name, arglist, linenum, # warning if there is reason to think that a percent character # was active in the last line. print_replacement = print_replacement.rsplit(r'%', 1)[0] - if not bool(match('[ \t]+\S', after)): + if not bool(match(r'[ \t]+\S', after)): # If there is text on the same line as the end of the # environment, we're fine (this is unusual). Otherwise, # we need to toss the newline at the end of the environment # and gobble leading spaces. Leading spaces need to be # gobbled because previously they were at the beginning of a # line, where they would have been discarded. - if not bool(match('\s*$', after)): - after = sub('^\s*?\n\s*', '', after) + if not bool(match(r'\s*$', after)): + after = sub(r'^\s*?\n\s*', '', after) else: # By default, LaTeX strips newlines and adds a space at the end # of each line of content that is brought in by `\input`. This @@ -611,13 +611,13 @@ def replace_print_env(name, arglist, linenum, # `\unskip` print_replacement = print_replacement.rstrip(' \t\n') after = sub(r'^\s*\\unskip\s+', '', after) - elif bool(match('[ \t]+\S', after)): + elif bool(match(r'[ \t]+\S', after)): # If the next character after the end of the environment is # not whitespace (usually not allowed), we can just leave # the `\n` in printed content, and it will yield a space. # So we need do nothing. But if there is text on that line # we need `\space{}`. - after = sub('^\s+', '\\space', after) + after = sub(r'^\s+', '\\space', after) forced_double_space_list.append((name, linenum)) else: # If the line at the end of the environment is blank, @@ -760,7 +760,7 @@ def replace_print_env(name, arglist, linenum, if not os.path.isfile(depytxfile_name): print('* DePythonTeX error:') print(' Could not find DePythonTeX auxiliary file "' + depytxfile_name + '"') - print(' Use package option depythontex to creat it') + print(' Use package option depythontex to create it') sys.exit(1) @@ -1080,7 +1080,7 @@ def replace_print_env(name, arglist, linenum, else: if obeylines: # Take into account possible whitespace before arg - if bool(match('[ \t]*\[', after)): + if bool(match(r'[ \t]*\[', after)): after = after.split('[', 1)[1] while ']' not in after: texlinenum += 1 @@ -1094,11 +1094,11 @@ def replace_print_env(name, arglist, linenum, after = sub('^[ \t]*', '', after) else: # Allow peeking ahead a line for the argument - if bool(match('\s*$', after)) and after.count('\n') < 2: + if bool(match(r'\s*$', after)) and after.count('\n') < 2: texlinenum += 1 after += tex[texlinenum] # Take into account possible whitespace before arg - if bool(match('\s*\[', after)): + if bool(match(r'\s*\[', after)): after = after.split('[', 1)[1] while ']' not in after: texlinenum += 1 @@ -1108,11 +1108,11 @@ def replace_print_env(name, arglist, linenum, optarg = None # Account for eating whitespace afterward, if arg not found if argindex == len(depy_args) - 1: - if bool(match('\s*$', after)) and after.count('\n') < 2: + if bool(match(r'\s*$', after)) and after.count('\n') < 2: texlinenum += 1 after += tex[texlinenum] - if not bool(match('\s*$', after)): - after = sub('^\s*', '', after) + if not bool(match(r'\s*$', after)): + after = sub(r'^\s*', '', after) arglist.append(optarg) elif arg == 'm': # Account for possible line breaks or spaces before arg @@ -1121,7 +1121,7 @@ def replace_print_env(name, arglist, linenum, else: if obeylines: # Account for possible leading whitespace - if bool(match('[ \t\f\v]*\{', after)): + if bool(match(r'[ \t\f\v]*\{', after)): after = after.split('{', 1)[1] else: print('* DePythonTeX error:') @@ -1129,10 +1129,10 @@ def replace_print_env(name, arglist, linenum, sys.exit(1) else: # Peek ahead a line if needed - if bool(match('\s*$', after)) and after.count('\n') < 2: + if bool(match(r'\s*$', after)) and after.count('\n') < 2: texlinenum += 1 after += tex[texlinenum] - if bool(match('\s*\{', after)): + if bool(match(r'\s*\{', after)): after = after.split('{', 1)[1] else: print('* DePythonTeX error:') @@ -1338,7 +1338,7 @@ def replace_print_env(name, arglist, linenum, after = tex[texlinenum] break after = after.split(end_environment, 1)[1] - if bool(match('\s*\n', after)): + if bool(match(r'\s*\n', after)): # If the line following `after` is whitespace, it should # be stripped, since most environments throw away # anything after the end of the environment @@ -1389,7 +1389,7 @@ def replace_print_env(name, arglist, linenum, # Take care of graphicspath if args.graphicspath and settings['graphicx']: for n, line in enumerate(texout): - if '\\graphicspath' in line and not bool(match('\s*%', line)): + if '\\graphicspath' in line and not bool(match(r'\s*%', line)): texout[n] = line.replace('\\graphicspath{', '\\graphicspath{{' + settings['outputdir'] +'/}') break elif line.startswith(r'\begin{document}'): diff --git a/pythontex/pythontex.dtx b/pythontex/pythontex.dtx index 38d44ff..be9c287 100644 --- a/pythontex/pythontex.dtx +++ b/pythontex/pythontex.dtx @@ -1,6 +1,6 @@ % \iffalse meta-comment % -% Copyright (C) 2012-2021 by Geoffrey M. Poore +% Copyright (C) 2012-2026 by Geoffrey M. Poore % --------------------------------------------------------------------------- % This work may be distributed and/or modified under the % conditions of the LaTeX Project Public License, either version 1.3 @@ -26,7 +26,7 @@ %\NeedsTeXFormat{LaTeX2e}[1999/12/01] %\ProvidesPackage{pythontex} %<*package> - [2021/06/06 v0.18 execute and typeset Python code and other languages] + [2026/02/15 v0.19 execute and typeset Python code and other languages] % % %<*driver> @@ -35,6 +35,8 @@ \usepackage[T1]{fontenc} \usepackage[utf8]{inputenc} \usepackage{lmodern} +\usepackage{microtype} + \usepackage{textcomp} \usepackage[svgnames]{xcolor} \usepackage{environ} @@ -108,6 +110,11 @@ \AtBeginDocument{\let|\pipe@active@verbatim} \endgroup +\renewenvironment{verbatim}% + {\VerbatimEnvironment\begin{Verbatim}[gobble=1]}% + {\end{Verbatim}} + + \def\MacroFont{% \fontencoding\encodingdefault% \fontfamily\ttdefault% @@ -117,13 +124,56 @@ \def\PrintMacroName#1{{\strut\MacroFont\color{DarkGreen}\footnotesize\string #1\ }} -\def\PrintDescribeMacro#1{\strut\MacroFont\textcolor{DarkGreen}{\string #1\ }} +\def\PrintDescribeMacro#1{\parbox[t]{1in}{\strut\MacroFont\textcolor{DarkGreen}{\string #1\ }}} \let\PrintDescribeEnv\PrintDescribeMacro %\let\PrintMacroName\PrintDescribeMacro \let\PrintEnvName\PrintDescribeEnv \def\theCodelineNo{\textcolor{DarkGreen}{\sffamily\scriptsize{\arabic{CodelineNo}}}} + +\renewenvironment{macro}{\macro@custom@arg}{} +\def\macro@custom@arg{% + \begingroup\makeatletter\macro@custom@arg@i} +\def\macro@custom@arg@i#1{% + \makeatother + \par\noindent + \ifstrempty{#1}% + {~\par}% + {\ttfamily\color{DarkGreen}\hspace*{-0.5in}% + \macro@custom@arg@split#1,\FV@Sentinel\par}% + \endgroup} +\def\macro@custom@arg@spacegobble#1{#1} +\def\macro@custom@arg@split#1,#2\FV@Sentinel{% + \expandafter\string\macro@custom@arg@spacegobble#1% + \if\relax\detokenize{#2}\relax + \expandafter\@firstoftwo + \else + \expandafter\@secondoftwo + \fi + {}{\\\hspace*{-0.5in}\macro@custom@arg@split#2\FV@Sentinel}} + +\renewenvironment{environment}{\env@custom@arg}{} +\def\env@custom@arg{% + \begingroup\makeatletter\env@custom@arg@i} +\def\env@custom@arg@i#1{% + \makeatother + \ifstrempty{#1}% + {~\par}% + {\ttfamily\color{DarkGreen}\hspace*{-0.5in}% + \env@custom@arg@split#1,\FV@Sentinel\par}% + \endgroup} +\def\env@custom@arg@spacegobble#1{#1} +\def\env@custom@arg@split#1,#2\FV@Sentinel{% + \env@custom@arg@spacegobble#1{\textrm{ \textit{(env.)}}}% + \if\relax\detokenize{#2}\relax + \expandafter\@firstoftwo + \else + \expandafter\@secondoftwo + \fi + {}{\\\hspace*{-0.5in}\env@custom@arg@split#2\FV@Sentinel}} + + \let\orig@footnote\footnote \renewcommand{\footnote}{% \begingroup @@ -136,6 +186,7 @@ \endgroup \orig@footnote{\scantokens{#1}}} + %\EnableCrossrefs %\CodelineIndex %\RecordChanges @@ -168,6 +219,21 @@ % % % +% \begin{changelog}{v0.19}{2026/02/15} +% \begin{itemize} +% \item Fixed backslash escapes in docstrings and regexes for syntax compatibility with Python 3.11+. +% \item \texttt{js} now works as a command family for JavaScript (\#197). +% \item Python console commands and environments are now compatible with Python 3.14 (\#229). +% \item Fixed a bug that could cause non-Windows operating systems to attempt to invoke a nonexistent batch file when the executable associated with a language is not found (\#225). +% \item Replaced doctype \texttt{tex} with \texttt{texminted} for \texttt{Weave.jl} (\#219). +% \item Fixed a bug that resulted in uncaught exceptions when \Verb{\inputpygments} was used with files that do not exist (\#64). +% \item Fixed a bug in tracking the number of Pygments errors (\#206). +% \item Improved error messages (\#207, \#209). Improved documentation for \Verb{--error-exit-code} (\#208). +% \item Several minor improvements to documentation. +% \end{itemize} +% \end{changelog} +% +% % \begin{changelog}{v0.18}{2021/06/06} % \begin{itemize} % \item \texttt{\string\inputpygments} now checks inputted files for modification, so that typeset code will correctly update when the source is changed (\#162). @@ -350,7 +416,7 @@ % \begin{changelog}{v0.11}{2013/04/21} % \begin{itemize} % \item As the first non-beta release, this version adds several features and introduces several changes. You should read these release notes carefully, since some changes are not backwards-compatible. Changes are based on a thorough review of all current and planned features. PythonTeX's capabilities have already grown beyond what was originally intended, and a long list of features still remains to be implemented. As a result, some changes are needed to ensure consistent syntax and naming in the future. Insofar as possible, all command names and syntax will be frozen after this release. -% \item Added the \texttt{pythontex.py} and \texttt{depythontex.py} wrapper scripts. When run, these detect the current version of Python and import the correct PythonTeX code. It is still possible to run \texttt{pythontex*.py} and \texttt{depythontex*.py} directly, but the new wrapper scripts should be used instead for simplicity. There is now only a single \texttt{pythontex\_utils.py}, which works with both Python 2 and Python 3. +% \item Added the \texttt{pythontex.py} and \texttt{depythontex.py} wrapper scripts. When run, these detect the current version of Python and import the correct PythonTeX code. It is still possible to run \texttt{pythontex*.py} and \texttt{depythontex*.py} directly, but the new wrapper scripts should be used instead for simplicity. There is now only a single \texttt{pythontex\_utils.py}, which works with both Python 2 and Python 3. % \item Added the \texttt{beta} package option. This makes the current version behave like v0.11beta, for compatibility. This option is temporary and will probably only be retained for a few releases. % \item Backward-incompatible changes (require the \texttt{beta} option to restore old behavior) % \begin{itemize} @@ -474,6 +540,7 @@ % % \maketitle % +% % \begin{abstract} % \pytex\ provides access to Python from within \LaTeX\ documents. It allows Python code entered within a \LaTeX\ document to be executed, and the results to be included within the original document. Python code may be adjacent to the figure or calculation it produces. The package also makes possible macro definitions that mix Python and \LaTeX\ code. In addition, \pytex\ provides syntax highlighting for many programming languages via the Pygments syntax highlighter. % @@ -483,13 +550,23 @@ % % While Python is the focus of \pytex, adding basic support for an additional language is usually as simple as creating a new class instance and a few templates, usually totaling less than 100 lines of code. The following languages already have built-in support: Ruby, Julia, Octave, Bash, Rust, R, Perl, Perl 6, and JavaScript. % \end{abstract} -% % % -% \section*{\centering Warning} -% +% +% \begingroup +% \small +% +% \subsection*{\centering Development Status} +% Since 2020, I am increasingly creating new teaching materials with Markdown and HTML instead of \pytex\ and \LaTeX. I have limited time for developing open-source software that I do not use frequently myself. There should be occasional releases to keep \pytex\ running, but no major changes or significant new features are anticipated. +% +% +% +% \subsection*{\centering Warning} +% % \pytex\ makes possible some pretty amazing things. But that power brings with it a certain risk and responsibility. Compiling a document that uses \pytex\ involves executing Python code, and potentially other programs, on your computer. You should only compile \pytex\ documents from sources you trust. \pytex\ comes with NO WARRANTY.\footnote{All \LaTeX\ code is licensed under the \href{http://www.latex-project.org/lppl.txt}{\LaTeX\ Project Public License (LPPL)} and all Python code is licensed under the \href{http://www.opensource.org/licenses/BSD-3-Clause}{BSD 3-Clause License}.} The copyright holder and any additional authors will not be liable for any damages. % +% \endgroup +% % % \pagebreak % \tableofcontents @@ -515,7 +592,7 @@ % \item[Compiling without executing]\hfill\\ Even with all of these features to boost execution speed, there will be times when we have to run slow code. Thus, we need the execution of non-\LaTeX\ code to be separated from compiling the \LaTeX\ document. We need to be able to edit and compile a document containing unexecuted code. Unexecuted code should be invisible or be replaced by placeholders. Sage\TeX\ and Sympy\TeX\ have implemented such a separation of compiling and executing. In contrast, Lua\TeX\ and Perl\TeX\ execute all the code at each compilation---but that is appropriate given their goal of simplifying macro programming. % \item[Error messages]\hfill\\ Whenever code is saved from a \LaTeX\ document to an external file and then executed, the line numbers for any error messages will not correspond to the line numbering of the original \LaTeX\ document. At one extreme, |python.sty| doesn't attempt to deal with this issue, while at the other extreme, Sage\TeX\ uses an ingenous system of |Try|/|Except| statements on every chunk of code. We need a system that translates all error messages so that they correspond to the line numbering of the original \LaTeX\ document, with minimal overhead when there are no errors. % \item[Syntax highlighting]\hfill\\ Once we begin using non-\LaTeX\ code, sooner or later we will want to typeset some of it, which means we need syntax highlighting. A number of syntax highlighting packages currently exist for \LaTeX; perhaps the most popular are |listings| and |minted|. |listings| uses pure \LaTeX. It has not been updated since 2007, which makes it a less ideal solution in some circumstances. |minted| uses the Python-based syntax highlighter Pygments to perform highlighting. Pygments can provide superior syntax highlighting, but |minted| can be very slow because all code must be highlighted at each compilation and each instance of highlighting involves launching an external Python process. We need high-speed, user-friendly syntax highlighting via Pygments.\footnote{The author recently started maintaining the \texttt{minted} package. In the near future, \texttt{minted} will inherit \pytex's speed enhancements, and the two packages will become more compatible.} -% \item[Printing]\hfill\\ It would be nice for the |print| statement/function,\footnote{In Python, |print| was a statement until Python 3, when it became a function. The function form is available via import from |\textunderscore\textunderscore future\textunderscore\textunderscore| in Python 2.6 and later.} or its equivalent, to automatically return its output within the \LaTeX\ document. For example, using |python.sty| it is possible to generate some text while in Python, open a file, save the text to it, close the file, and then |\input| the file after returning to \LaTeX. But it is much simpler to generate the text and |print| it, since the printed content is automatically included in the \LaTeX\ document. This was one of the things that |python.sty| really got right. +% \item[Printing]\hfill\\ It would be nice for the |print| statement/function,\footnote{In Python, |print| was a statement until Python 3, when it became a function. The function form is available via import from |__future__| in Python 2.6 and later.} or its equivalent, to automatically return its output within the \LaTeX\ document. For example, using |python.sty| it is possible to generate some text while in Python, open a file, save the text to it, close the file, and then |\input| the file after returning to \LaTeX. But it is much simpler to generate the text and |print| it, since the printed content is automatically included in the \LaTeX\ document. This was one of the things that |python.sty| really got right. % \item[Pure code]\hfill\\ \LaTeX\ has a number of special characters (|#| \texttt{\$} |%| |&| |~| |_| |^| |\| |{| |}|), which complicates the entry of non-\LaTeX\ code since these same characters are common in many languages. Sage\TeX\ and Sympy\TeX\ delimit all inline code with curly braces (|{}|), but this approach fails in the (somewhat unlikely) event that code needs to contain an unmatched brace. More seriously, they do not allow the percent symbol |%| (modular arithmetic and string formatting in Sage and Python) to be used within inline code. Rather, a |\percent| macro must be used instead. This means that code must (sometimes) be entered as a hybrid between \LaTeX\ and the non-\LaTeX\ language. Lua\TeX\ is somewhat similar: ``The main thing about Lua code in a TeX document is this: the code is expanded by TeX before Lua gets to it. This means that all the Lua code, even the comments, must be valid TeX!''\footnote{\url{http://wiki.contextgarden.net/Programming_in_LuaTeX}} In the case of Lua\TeX, though, there is the \href{http://www.ctan.org/pkg/luacode}{\texttt{luacode}} package that allows for pure Lua. % % This language hybridization is not terribly difficult to work around in the Sage\TeX\ and Sympy\TeX\ cases, and is actually a Lua\TeX\ feature in many contexts. But if we are going to create a system for general-purpose access to a non-\LaTeX\ language, we need \textbf{all} valid code to work correctly in \textbf{all} contexts, with no hybridization of any sort required. We should be able to copy and paste valid code into a \LaTeX\ document, without having to worry about hybridizing it. Among other things, this means that inline code delimiters other than \LaTeX's default curly braces |{}| must be available. @@ -536,7 +613,7 @@ % % \section{Citing \pytex} % \label{sec:citing} -% +% % If you use \pytex\ in your writing and research, please consider citing it in any resulting publications. The best and most recent paper is in \textit{Computational Science \& Discovery}. % \begin{itemize} % \item ``PythonTeX: reproducible documents with LaTeX, Python, and more,'' Geoffrey M Poore. \textit{Computational Science \& Discovery} 8 (2015) 014010. Full text and Bib\TeX\ entry available at \url{http://stacks.iop.org/1749-4699/8/i=1/a=014010}. @@ -547,11 +624,11 @@ % \section{Installing and running} % \label{sec:installing-and-running} % -% \subsection{Installing \pytex} +% \subsection{Installing \pytex} % % \pytex\ requires a \TeX\ installation. It has been tested with \href{http://www.tug.org/texlive/}{\TeX\ Live} and \href{http://miktex.org/}{MiK\TeX}, but should work with other distributions. The following \LaTeX\ packages, with their dependencies, are required: |fancyvrb|, |fvextra|, |etoolbox|, |xstring|, |pgfopts|, |newfloat| (part of the |caption| bundle), |currfile|, and |color| or |xcolor|. A current \TeX\ installation is recommended, since some features require recent versions of the packages. If you are creating and including graphics, you will also need |graphicx|. The \href{http://www.ctan.org/pkg/mdframed}{\texttt{mdframed}} package is recommended for enclosing typeset code in boxes with fancy borders and/or background colors; \href{http://www.ctan.org/pkg/tcolorbox}{\texttt{tcolorbox}} and \href{http://www.ctan.org/pkg/framed}{\texttt{framed}} are alternatives. % -% \pytex\ also requires a \href{http://www.python.org/}{Python} installation. Python 2.7 is recommended for the greatest compatibility with scientific tools, although many scientific packages are now compatible with Python 3. \pytex\ is compatible with Python 2.7 and 3.2+. The Python package \href{http://pygments.org/}{Pygments} must be installed for syntax highlighting to function. \pytex\ has been tested with Pygments 1.4 and later, but the latest version is recommended. For scientific work, or to compile |pythontex_gallery.tex|, the following are also recommended: \href{http://numpy.scipy.org/}{NumPy}, \href{http://www.scipy.org/}{SciPy}, \href{http://matplotlib.sourceforge.net/}{matplotlib}, and \href{http://sympy.org}{SymPy}. When using \pytex\ with LyX, be aware that LyX may try to use its own version of Python; you may need to reconfigure LyX. +% \pytex\ also requires a \href{http://www.python.org/}{Python} installation. A recent Python 3 installation is recommended, but there is still support for Python 2.7. The Python package \href{http://pygments.org/}{Pygments} must be installed for syntax highlighting to function. \pytex\ has been tested with Pygments 1.4 and later, but the latest version is recommended. For scientific work, or to compile |pythontex_gallery.tex|, the following are also recommended: \href{http://numpy.scipy.org/}{NumPy}, \href{http://www.scipy.org/}{SciPy}, \href{http://matplotlib.sourceforge.net/}{matplotlib}, and \href{http://sympy.org}{SymPy}. When using \pytex\ with LyX, be aware that LyX may try to use its own version of Python; you may need to reconfigure LyX. % % \pytex\ also provides support for other languages such as Ruby, so you will need to install any additional languags you plan to use. Typically, the most recent major version of these languages is supported. % @@ -569,9 +646,9 @@ % \item |pythontex_quickstart.tex| and |pythontex_quickstart.pdf| % \item Optional installation script |pythontex_install.py| for \TeX\ Live and MiKTeX % \item Optional batch file |pythontex.bat| for use in launching |pythontex.py| under Windows -% \item Optional conversion script |pythontex_2to3.py| for converting \pytex\ code written for Python 2 into a form compatible with Python 3 +% \item |pythontex_2to3.py| was originally included with \pytex, but it is no longer needed. Originally, the core of \pytex\ was developed in |pythontex2.py| for Python 2.7, and then |pythontex_2to3.py| was used convert |pythontex2.py| into |pythontex3.py| for Python 3.2+. Currently, all development is in |pythontex3.py|. |pythontex2.py| is retained for backward compatibility, but in most cases it is no longer updated to maintain parity with |pythontex3.py|. Similarly, |depythontex3.py| is now developed directly, separately from |depythontex2.py|, and |depythontex2.py| typically doesn't receive updates. % \end{itemize} -% The style file |pythontex.sty| may be generated by running \LaTeX\ on |pythontex.ins|. The documentation you are reading may be generated by running \LaTeX\ on |pythontex.dtx|. Some code is provided in two forms, one for Python 2 and one for Python 3 (names ending in |2| and |3|). Whenever this is the case, a version-independent wrapper is supplied that automatically runs the correct code based on the Python version. For example, there are two main scripts, |pythontex2.py| and |pythontex3.py|, but you should actually run |pythontex.py|, which imports the correct code based on the Python version.\footnote{Unfortunately, it is not possible to provide full Unicode support for both Python 2 and 3 using a single script. Currently, all code is written for Python 2, and then the Python 3 version is automatically generated via the |pythontex\_2to3.py| script. This script comments out code that is only for Python 2, and un-comments code that is only for Python 3.} +% The style file |pythontex.sty| may be generated by running \LaTeX\ on |pythontex.ins|. The documentation you are reading may be generated by running \LaTeX\ on |pythontex.dtx|. Some code is provided in two forms, one for Python 2 and one for Python 3 (names ending in |2| and |3|). Whenever this is the case, a version-independent wrapper is supplied that automatically runs the correct code based on the Python version. For example, there are two main scripts, |pythontex2.py| and |pythontex3.py|, but you can typically run |pythontex.py|, which imports the correct code based on the Python version. % % If you want the absolute latest version of \pytex, you should install it manually from \href{https://github.com/gpoore/pythontex}{github.com/gpoore/pythontex}. A Python installation script is provided for use with \TeX\ Live and MiKTeX. It has been tested with Windows, Linux, and OS~X, but may need manual input or slight modifications depending on your system. The installation script performs the steps described below. % @@ -579,7 +656,7 @@ % % \textbf{Note that for a typical \TeX\ setup under Linux, you may need to run the script with elevated privileges, and may need to run it with the user's PATH.} This can be necessary when you are using a Linux distribution that includes an outdated version of \TeX\ Live, and have installed a new version manually. \textbf{If you are installing \pytex\ on a machine with multiple versions of \TeX, make sure you install \pytex\ for the correct version.} For example, under Ubuntu Linux, you will probably need the following command if you have installed the latest version of \TeX\ Live manually: % \begin{verbatim} -% sudo env PATH=$PATH python pythontex_install.py +%sudo env PATH=$PATH python pythontex_install.py % \end{verbatim} % % The installer creates the following files. It will offer to create the paths if they do not exist. If you are installing in TEXMFLOCAL, the paths will have an additional |local/| at the end. @@ -627,14 +704,14 @@ % \end{itemize} % For an example of a \pytex\ document that will correctly compile under all three engines, see the |pythontex_gallery.tex| source. % -% If you use XeLaTeX, and your non-\LaTeX\ code contains tabs, you \textbf{must} invoke XeLaTeX with the |-8bit| option so that tabs will be written to file as actual tab characters rather than as the character sequence |^^I|.\footnote{See \url{http://tex.stackexchange.com/questions/58732/how-to-output-a-tabulation-into-a-file} for more on tabs with XeTeX.} +% If you use XeLaTeX, and your non-\LaTeX\ code contains tabs, you \textbf{must} invoke XeLaTeX with the |-8bit| option so that tabs will be written to file as actual tab characters rather than as the character sequence |^^I|.\footnote{See \url{http://tex.stackexchange.com/questions/58732/how-to-output-a-tabulation-into-a-file} for more on tabs with XeTeX.} % % |pythontex.py| requires a single command-line argument: the name of the .tex file to process. The filename can be passed with or without an extension; the script really only needs the |\jobname|, so any extension is stripped off.\footnote{Thus, \pytex\ works happily with .tex, .ltx, .dtx, and any other extension.} The filename may include the path to the file; you do not have to be in the same directory as the file to run \pytex. If you are configuring your editor to run \pytex\ automatically via a shortcut, you may want to wrap the filename in double quotes |"| to allow for space characters.\footnote{Using spaces in the names of .tex files is apparently frowned upon. But if you configure things to handle spaces whenever it doesn't take much extra work, then that's one less thing that can go wrong.} For example, under Windows with \TeX\ Live and Python 2.7 we would create the wrapper |pythontex.exe|. Then we could run \pytex\ on a file \meta{file~name}.tex using the command |pythontex.exe "|\meta{file~name}|"|. % % |pythontex.py| accepts the following optional command-line arguments. Some of these options duplicate package-level options, so that settings may be configured either within the document or at the command line. In the event that the command-line and package options conflict, the package options always override the command-line options. For variations on these options that are acceptable, run |pythontex.py -h|. % \begin{itemize} % \item |--encoding=|\meta{encoding} This sets the file encoding. Any encoding supported by Python's \href{http://docs.python.org/library/codecs.html}{\texttt{codecs}} module may be used. The encoding should match that of the \LaTeX\ document. If an encoding is not specified, \pytex\ uses UTF-8. If support for characters beyond ASCII is required, then additional \LaTeX\ packages are required; see the discussion of \TeX\ engines above. -% \item |--error-exit-code={true,false}| By default, |pythontex.py| returns an exit code of 1 if there were any errors, and an exit code of 0 otherwise. This may be useful when \pytex\ is used in a scripting or command-line context, since the presence of errors may be easily detected. It is also useful with some \TeX\ editors. For example, \href{http://www.tug.org/texworks/}{TeXworks} automatically hides the output of external programs unless there are errors. +% \item |--error-exit-code={true,false}| By default, when |pythontex.py| finishes running, it returns an exit code of 1 if there were any errors (for example, in code execution), and an exit code of 0 otherwise. This may be useful when \pytex\ is used in a scripting or command-line context, since the presence of errors may be easily detected. It is also useful with some \TeX\ editors. For example, \href{http://www.tug.org/texworks/}{TeXworks} automatically hides the output of external programs unless there are errors. % % In some contexts, returning a nonzero exit code can be redundant. For example, with the \href{http://winshell.de/}{WinShell} editor under Windows with TeX Live, the complete output of \pytex\ is always available in the ``Output'' view, so it is clear if errors have occurred. Having a nonzero exit code causes |runscript.exe| to return an additional, redundant error message in the ``Output'' view. In such situations, it may be desirable to disable the nonzero exit code. % \item |--runall=[{true,false}]| This causes \textbf{all} code to be executed, regardless of modification or |rerun| settings. It is useful when code has not been modified, but a dependency such as a library or external data has changed. Note that the \pytex\ utilities class also provides a mechanism for automatically re-executing code that depends on external files when those external files are modified. @@ -711,7 +788,7 @@ % % \DescribeMacro{gobble=none/auto default:none} % -% This option is still under development and may change somewhat in future releases. If that occurs, equivalent functionality will be provided. +% This option is still under development and may change somewhat in future releases. If that occurs, equivalent functionality will be provided. % % This option determines how code indentation is handled. By default, indentation is left as-is; leading whitespace is significant. |auto| will dedent all code by gobbling the largest common leading whitespace, using Python's |textwrap.dedent()|.\footnote{It would be possible to do the dedent on the \LaTeX\ side, as is done manually in the \texttt{fancyvrb} and \texttt{listings} packages with the \texttt{gobble} option and is done automatically in the \texttt{lstautogobble} package. This is not done for stability and security reasons. \texttt{lstautogobble} determines the dedent by extracting the leading whitespace from the first line of code, and then applying this dedent to each subsequent line. This is adequate for \textbf{typesetting} code, since the worst-case scenario is that a subsequent line with less indentation will be typeset with the first few characters missing. Such an approach is not acceptable when the code will be \textbf{executed}, since a few missing characters could in principle cause serious damage. Doing the dedent on the Python side ensures that no characters are discarded, even if that results in an indentation error.} Keep in mind that Python's dedent will not work correctly with mixed tabs and spaces. % @@ -724,7 +801,7 @@ % % This option provides compatibility with the beta releases from before the full v0.11 release, which introduced some changes in syntax and command names. This option should \textbf{only} be used with old \pytex\ documents that require it. % -% You are encouraged to update old documents, since this compatility option will only be provided for a few releases. +% You are encouraged to update old documents, since this compatibility option will only be provided for a few releases. % % % \DescribeMacro{runall=\meta{none}/true/false default:false \meta{none}=true} @@ -733,7 +810,7 @@ % % A command-line equivalent |--runall| exists for |pythontex.py|. The package option |rerun=always| is essentially equivelent. % -% +% % \DescribeMacro{rerun=never/modified/errors/warnings/always default:errors} % % This option sets the threshold for re-executing code. By default, \pytex\ will rerun code that has been modified or that produced errors on the last run. Sometimes, we may wish to have a more lenient setting (only rerun if modified) or a more stringent setting (rerun even for warnings, or always rerun). |never| never executes code; a warning is issued if there is modified code. |modified| only executes code that has been modified. |errors| executes all modified code as well as all code that produced errors on the last run; this is the default. |warnings| executes all modified code, as well as all code that produced errors or warnings. |always| executes all code regardless of its condition. @@ -750,9 +827,13 @@ % % \DescribeMacro{autoprint=\meta{none}/true/false default:true \meta{none}=true} % +% ~ +% +% ~ +% % \DescribeMacro{autostdout=\meta{none}/true/false default:true \meta{none}=true} % -% Whenever a |print| command/statement is used, the printed content will automatically be included in the document, unless the code doing the printing is being typeset.\footnote{Note that |autoprint| only works within the body of the document. The |code| command and environment can be used in the preamble, but |autoprint| is disabled there. It is usually a not a good idea to print in the preamble, because nothing can be typeset; the only thing that could be validly printed is \LaTeX\ commands that do not typeset content, such as macro definitions. Thus, it is appropriate that printed content is only brought in while in the preamble if it is explicitly requested via |\string\printpythontex|. This approach is also helpful for writing packages using \pytex, since the author does not have to worry about any \LaTeX\ commands printed by the package either not being included (if |autoprint| is relied upon, but the user turns it off) or being included twice (if |\string\printpythontex| is used and |autoprint| is enabled). Printing should only be used in the preamble with great care.} In that case, the printed content must be included using the |\printpythontex| or |\stdoutpythontex| commands. +% Whenever a |print| command/statement is used, the printed content will automatically be included in the document, unless the code doing the printing is being typeset.\footnote{Note that |autoprint| only works within the body of the document. The |code| command and environment can be used in the preamble, but |autoprint| is disabled there. It is usually a not a good idea to print in the preamble, because nothing can be typeset; the only thing that could be validly printed is \LaTeX\ commands that do not typeset content, such as macro definitions. Thus, it is appropriate that printed content is only brought in while in the preamble if it is explicitly requested via |\printpythontex|. This approach is also helpful for writing packages using \pytex, since the author does not have to worry about any \LaTeX\ commands printed by the package either not being included (if |autoprint| is relied upon, but the user turns it off) or being included twice (if |\printpythontex| is used and |autoprint| is enabled). Printing should only be used in the preamble with great care.} In that case, the printed content must be included using the |\printpythontex| or |\stdoutpythontex| commands. % % Printed content is pulled in directly from the external file in which it is saved, and is interpreted by \LaTeX\ as \LaTeX\ code. If you wish to avoid this, you should print appropriate \LaTeX\ commands with your content to ensure that it is typeset as you desire. Alternatively, you may use |\printpythontex| or |\stdoutpythontex| to bring in printed content in verbatim form, using those commands' optional |verb| and |verbatim| options. % @@ -795,17 +876,17 @@ % % This option determines whether the |upquote| package is loaded. In general, the |upquote| package should be loaded, because it ensures that quotes within verbatim contexts are ``upquotes,'' that is, \expandafter|\textquotesingle| rather than |'|. % -% Using |upquote| is important beyond mere presentation. It allows code to be copied directly from the compiled PDF and executed without any errors due to quotes |'| being copied as acute accents \texttt{\'}. +% Using |upquote| is important beyond mere presentation. It allows code to be copied directly from the compiled PDF and executed without any errors due to quotes |'| being copied as acute accents \texttt{\'}. % % \DescribeMacro{fixlr=\meta{none}/true/false default:false \meta{none}=true} % % This option removes ``extra'' spacing around |\left| and |\right| in math mode. This spacing is sometimes undesirable, especially when typesetting functions such as the trig functions. See the implementation for details. Similar functionality is provided by the \href{http://www.ctan.org/pkg/mleftright}{\texttt{mleftright}} package % -% \DescribeMacro{keeptemps=\meta{none}/all/code/none default:none \meta{none}=all} +% \DescribeMacro{keeptemps=\meta{none}/all/code/none default:none \meta{none}=all} % % When \pytex\ runs, it creates a number of temporary files. By default, none of these are kept. The |none| option keeps no temp files, the |code| option keeps only code temp files (these can be useful for debugging), and the |all| option keeps all temp files (code, stdout and stderr for each code file, etc.). Note that this option does not apply to any user-generated content, since \pytex\ knows very little about that; it only applies to files that \pytex\ automatically creates by itself. % -% \DescribeMacro{prettyprinter=pygments/fancyvrb default:pygments} +% \DescribeMacro{prettyprinter=pygments/fancyvrb default:pygments} % % This allows the user to determine at the document level whether code is typeset using Pygments or |fancyvrb|. % @@ -817,31 +898,31 @@ % This determines whether inline content is pretty printed. If it is turned off, inline content is typeset with |fancyvrb|. % % -% \DescribeMacro{pygments=\meta{none}/true/false default:true \meta{none}=true} +% \DescribeMacro{pygments=\meta{none}/true/false default:true \meta{none}=true} % % This allows the user to determine at the document level whether code is typeset using Pygments rather than |fancyvrb|. It is an alias for |prettyprinter=pygments|. % % % \DescribeMacro{pyginline=\meta{none}/true/false default:true \meta{none}=true} -% +% % This option governs whether inline code, not just code in environments, is highlighted when Pygments highlighting is in use. When Pygments is in use, it will highlight everything by default. % % It is an alias for |prettyprintinline|. % % -% \DescribeMacro{pyglexer=\meta{pygments~lexer} default:\meta{none}} +% \DescribeMacro{pyglexer=\meta{pygments~lexer} default:\meta{none}} % % This allows a Pygments lexer to be set at the document level. In general, this option should \textbf{not} be used. It overrides the default lexer for all commands and environments, for both \pytex\ and Pygments content, and this is usually not desirable. It should be useful primarily when all content uses the same lexer, and multiple lexers are compatible with the content. % % -% \DescribeMacro{pygopt=\marg{pygments~options} default:\meta{none}} +% \DescribeMacro{pygopt=\marg{pygments~options} default:\meta{none}} % % This allows Pygments options to be set at the document level. The options must be enclosed in curly braces |{}|. Currently, three options may be passed in this manner: |style=|\meta{style~name}, which sets the formatting style; |texcomments|, which allows \LaTeX\ in code comments to be rendered; and |mathescape|, which allows \LaTeX\ math mode (|$...$|) in comments. The |texcomments| and |mathescape| options may be used with an argument (for example, |texcomments=true/false|); if an argument is not supplied, |true| is assumed. Example: |pygopt={style=colorful, texcomments=true, mathescape=false}|. % % Pygments options for individual command and environment families may be set with the |\setpythontexpygopt| macro; for Pygments content, there is |\setpygmentspygopt|. These individual settings are always overridden by the package option. % % -% \DescribeMacro{fvextfile=\meta{none}/\meta{integer} default:$\infty$ \meta{none}=25} +% \DescribeMacro{fvextfile=\meta{none}/\meta{integer} default:$\infty$ \meta{none}=25} % % This option speeds the typesetting of long blocks of code that are created on the Python side. This includes content highlighted using Pygments and the |console| environment. Typesetting speed is increased at the expense of creating additional external files (in the \pytex\ directory). The \meta{integer} determines the number of lines of code at which the system starts using multiple external files, rather than a single external file. See the implementation for the technical details; basically, an external file is used rather than |fancyvrb|'s |SaveVerbatim|, which becomes increasingly inefficient as the length of the saved verbatim content grows. In most situations, this option should not be needed, or should be fine with the default value or similar ``small'' integers. % @@ -855,11 +936,11 @@ % % This governs the form of the filename that appears in error messages in Python console environments. Python errors messages have a form such as the following: % \begin{verbatim} -% >>> z = 1 + 34 + -% File "", line 1 -% z = 1 + 34 + -% ^ -% SyntaxError: invalid syntax +%>>> z = 1 + 34 + +% File "", line 1 +% z = 1 + 34 + +% ^ +%SyntaxError: invalid syntax % \end{verbatim} % The |stdin| option replaces || with ||, as it appears in a standard Python interactive session. The |console| option uses || instead, which is the default setting for the Python |code| module used by \pytex\ to create Python console environments. % @@ -882,7 +963,7 @@ % \end{quote} % % -% \subsubsection{Inline commands} +% \subsubsection{Inline commands} % \pytxtodo{Fix spacing around |\DescribeMacro|!} % Inline commands are suitable for single lines of code that need to be executed within the body of a paragraph or within a larger body of text. The commands use arbitrary code delimiters (like |\verb| does), which allows the code to contain arbitrary characters. Note that this is only guaranteed to work properly when the inline commands are \textbf{not} inside other macros. If an inline command is used within another macro, the code will be read by the external macro before \pytex\ can read the special code characters (that is, \LaTeX\ will tokenize the code). The inline commands can work properly within other macros, but it is best to stick with curly braces for delimiters in this case and you may have trouble with the hash |#| and percent |%| characters. % @@ -890,11 +971,11 @@ % % This command is used for including variable values or other content that can be converted to a string. It is an alternative to including content via the |print| statement/function within other commands/environments. % -% The |\py| command sends \meta{code} to Python, and Python returns a string representation of \meta{code}.\pytxtodo{Link to details about Python built-ins} \meta{opening~delim} and \meta{closing~delim} must be either a pair of identical, non-space characters, or a pair of curly braces. If curly braces are used as delimiters, then curly braces may only be used within \meta{code} if they are paired. Thus, |\py{1+1}| sends the code |1+1| to Python, Python evaluates the string representation of this code, and the result is returned to \LaTeX\ and included as |2|. The commands |\py#1+1#| and |\py@1+1@| would have the same effect. The command can also be used to access variable values. For example, if the code |a=1| had been executed previously, then |\py{a}| simply brings the string represantation of |a| back into the document as |1|. +% The |\py| command sends \meta{code} to Python, and Python returns a string representation of \meta{code}.\pytxtodo{Link to details about Python built-ins} \meta{opening~delim} and \meta{closing~delim} must be either a pair of identical, non-space characters, or a pair of curly braces. If curly braces are used as delimiters, then curly braces may only be used within \meta{code} if they are paired. Thus, |\py{1+1}| sends the code |1+1| to Python, Python evaluates the string representation of this code, and the result is returned to \LaTeX\ and included as |2|. The commands |\py#1+1#| and |\py@1+1@| would have the same effect. The command can also be used to access variable values. For example, if the code |a=1| had been executed previously, then |\py{a}| simply brings the string represantation of |a| back into the document as |1|. % -% Assignment is \textbf{not} allowed using |\py|. For example, |\py{a=1}| is \textbf{not} valid. This is because assignment cannot be converted to a string.\footnote{It would be simple to allow any code within |\textbackslash py|, including assignment, by using a |try/except| statement. In this way, the functionality of |\textbackslash py| and |\textbackslash pyc| could be merged. While that would be simpler to use, it also has serious drawbacks. If |\textbackslash py| is not exclusively used to typeset string representations of \meta{code}, then it is no longer possible on the \LaTeX\ side to determine whether a command should return a string. Thus, it is harder to determine, from within a \TeX\ editor, whether |pythontex.py| needs to be run; warnings for missing Python content could not be issued, because the system wouldn't know (on the \LaTeX\ side) whether content was indeed missing.} +% Assignment is \textbf{not} allowed using |\py|. For example, |\py{a=1}| is \textbf{not} valid. This is because assignment cannot be converted to a string.\footnote{It would be simple to allow any code within |\py|, including assignment, by using a |try/except| statement. In this way, the functionality of |\py| and |\pyc| could be merged. While that would be simpler to use, it also has serious drawbacks. If |\py| is not exclusively used to typeset string representations of \meta{code}, then it is no longer possible on the \LaTeX\ side to determine whether a command should return a string. Thus, it is harder to determine, from within a \TeX\ editor, whether |pythontex.py| needs to be run; warnings for missing Python content could not be issued, because the system wouldn't know (on the \LaTeX\ side) whether content was indeed missing.} % -% The text returned by Python must be valid \LaTeX\ code. Verbatim and other special content is allowed. The primary reasons for using |\py| rather than |print| are (1) |\py| is more compact and (2) |print| requires an external file to be created for every command or environment in which it is used, while |\py| and equivalents for other families share a single external file. Thus, use of |\py| minimizes the creation of external files, which is a key design goal for \pytex.\footnote{For |\textbackslash py|, the text returned by Python is stored in macros and thus must be valid \LaTeX\ code, because \LaTeX\ interprets the returned content. The use of macros for storing returned content means that an external file need not be created for each use of |\textbackslash py|. Rather, all macros created by |\textbackslash py| and equivalent commands from other families are stored in a single file that is inputted. Note that even though the content is stored in macros, verbatim content is allowed, through the use of special macro definitions combined with \texttt{\string\scantokens}.} The main reason for using |print| rather than |\py| is if you need to include a very large amount of material; |print|'s use of external files won't use up \TeX's memory, and may give noticeably better performance once the material is sufficiently long. +% The text returned by Python must be valid \LaTeX\ code. Verbatim and other special content is allowed. The primary reasons for using |\py| rather than |print| are (1) |\py| is more compact and (2) |print| requires an external file to be created for every command or environment in which it is used, while |\py| and equivalents for other families share a single external file. Thus, use of |\py| minimizes the creation of external files, which is a key design goal for \pytex.\footnote{For |\py|, the text returned by Python is stored in macros and thus must be valid \LaTeX\ code, because \LaTeX\ interprets the returned content. The use of macros for storing returned content means that an external file need not be created for each use of |\py|. Rather, all macros created by |\py| and equivalent commands from other families are stored in a single file that is inputted. Note that even though the content is stored in macros, verbatim content is allowed, through the use of special macro definitions combined with \texttt{\string\scantokens}.} The main reason for using |print| rather than |\py| is if you need to include a very large amount of material; |print|'s use of external files won't use up \TeX's memory, and may give noticeably better performance once the material is sufficiently long. % % \DescribeMacro{\pyc\oarg{session}\meta{opening~delim}\meta{code}\meta{closing~delim}} % @@ -1060,7 +1141,7 @@ % The utilities class provides an interface for determining how Python objects are converted into strings in commands such as |\py|. The |pytex.set_formatter(|\meta{formatter}|)| method is used to set the conversion. Two formatters are provided: % \begin{itemize} % \item |'str'| converts Python objects to a string, using the |str()| function under Python 3 and the |unicode()| function under Python 2. (The use of |unicode()| under Python 2 should not cause problems, even if you have not imported |unicode_literals| and are not using unicode strings. All encoding issues should be taken care of automatically by the utilities class.) -% \item |'sympy_latex'| uses SymPy's |LatexPrinter| class to return context-sensitive \LaTeX\ representations of SymPy objects. Separate |LatexPrinter| settings may be created for the following contexts: |'display'| (displaystyle math), |'text'| (textstyle math), |'script'| (superscripts and subscripts), and |'scriptscript'| (superscripts and subscripts, of superscripts and subscripts). Settings are created via |pytex.set_sympy_latex(|\meta{context}|,|\meta{settings}|)|. For example, |pytex.set_sympy_latex('display', mul_symbol='times')| sets multiplication to use a multiplication symbol $\times$, but only when math is in displaystyle.\footnote{Internally, the |'sympy\_latex'| formatter uses the |\textbackslash mathchoice| macro to return multiple representations of a SymPy object, if needed by the current settings. Then |\textbackslash mathchoice| typesets the correct representation, based on context.} See the \href{http://docs.sympy.org/dev/modules/printing.html}{SymPy documentation} for a list of possible settings for the |LatexPrinter| class. +% \item |'sympy_latex'| uses SymPy's |LatexPrinter| class to return context-sensitive \LaTeX\ representations of SymPy objects. Separate |LatexPrinter| settings may be created for the following contexts: |'display'| (displaystyle math), |'text'| (textstyle math), |'script'| (superscripts and subscripts), and |'scriptscript'| (superscripts and subscripts, of superscripts and subscripts). Settings are created via |pytex.set_sympy_latex(|\meta{context}|,|\meta{settings}|)|. For example, |pytex.set_sympy_latex('display', mul_symbol='times')| sets multiplication to use a multiplication symbol $\times$, but only when math is in displaystyle.\footnote{Internally, the |'sympy_latex'| formatter uses the |\mathchoice| macro to return multiple representations of a SymPy object, if needed by the current settings. Then |\mathchoice| typesets the correct representation, based on context.} See the \href{http://docs.sympy.org/dev/modules/printing.html}{SymPy documentation} for a list of possible settings for the |LatexPrinter| class. % % By default, |'sympy_latex'| only treats matrices differently based on context. Matrices in displaystyle are typeset using |pmatrix|, while those in all other styles are typeset via |smallmatrix| with parentheses. % @@ -1072,7 +1153,7 @@ % The utilities class also provides methods for tracking dependencies and created files. % \begin{itemize} % \item |pytex.add_dependencies(|\meta{dependencies}|)| This adds \meta{dependencies} to a list. If any dependencies in the list change, code is re-executed, even if the code itself has not changed (unless |rerun=never|). Modified dependencies are determined via either modification time (default) or hash; see the package option |hashdependencies| for details. This method is useful for tracking changes in external data and similar files. -% +% % \meta{dependencies} should be one or more strings, separated by commas, that are the file names of dependencies. Dependencies should be given with relative paths from the current working directory, with absolute paths, or with paths based on the user's home directory (that is, starting with a tilde |~|). Paths can use a forward slash ``|/|'' even under Windows. Remember that by default, the working directory is the main document directory. This can be adjusted with |\setpythontexworkingdir|. % % It is possible that a dependency of one session might be modified by another session while \pytex\ runs. The first session might not be executed during the \pytex\ run because its dependency was unmodified at the beginning. A more serious case occurs when the first session does run, but we don't know whether it accessed the dependency before or after the dependency was updated (remember, sessions run in parallel). \pytex\ keeps track of the time at which it started. Any sessions with dependencies that were modified after that time are set to re-execute on the next run. A warning is also issued to indicate that this is the case. @@ -1199,7 +1280,7 @@ % % % \DescribeMacro{\saveprintpythontex\marg{name}} -% +% % \DescribeMacro{\savestdoutpythontex\marg{name}} % % \DescribeMacro{\useprintpythontex\oarg{verbatim~options}\oarg{fancyvrb~options}\marg{name}} @@ -1238,14 +1319,14 @@ % ~\par % % This allows autoprint behavior to be modified at various points within the document. The package-level |autoprint| option is also available for setting autoprint at the document level, but it is overridden by |\setpythontexautoprint|. \meta{boolean} should be |true| or |false|. -% +% % % \subsection{Pygments commands and environments} % % Although \pytex's goal is primarily the execution and typesetting of Python code from within \LaTeX, it also provides access to syntax highlighting for any language supported by Pygments. % % \DescribeMacro{\pygment\marg{lexer}\meta{opening~delim}\meta{code}\meta{closing~delim}} -% +% % This command typesets \meta{code} in a suitable form for inline use within a paragraph, using the specified Pygments \meta{lexer}. Internally, it uses the same macros as the \pytex\ inline commands. \meta{opening~delim} and \meta{closing~delim} may be a pair of any characters except for the space character, or a matched set of curly braces |{}|. % % As with the inline commands for code typesetting and execution, there is not an optional argument for |fancyvrb| settings, since almost all of them are not relevant for inline usage, and the few that might be should probably be used document-wide if at all. @@ -1255,10 +1336,10 @@ % % This environment typesets its contents using the specified Pygments \meta{lexer} and applying the \meta{fancyvrb~settings}. % -% +% % \DescribeMacro{\inputpygments\oarg{fancyvrb~settings}\marg{lexer}\marg{external~file}} % -% This command brings in the contents of \meta{external~file}, highlights it using \meta{lexer}, and typesets it using \meta{fancyvrb~settings}. +% This command brings in the contents of \meta{external~file}, highlights it using \meta{lexer}, and typesets it using \meta{fancyvrb~settings}. % % % \DescribeMacro{\setpygmentsfv\oarg{lexer}\marg{fancyvrb~settings}} @@ -1272,7 +1353,7 @@ % % If \meta{lexer} is not given, options are set for the entire document. % -% +% % \DescribeMacro{\setpygmentsprettyprinter\marg{printer}} % % This usually should not be needed. It allows the pretty printer for the document to be set; it is equivalent to using |\setpythontexprettyprinter| without an optional argument. Valid options for \meta{printer} are |fancyvrb| and |pygments|. @@ -1297,7 +1378,7 @@ % % \pytex\ uses |fancyvrb| internally to typeset all code. Even code that is highlighted with Pygments is typeset afterwards with |fancyvrb|. Using |fancyvrb|, it is possible to set background colors for individual lines of code, but not for entire blocks of code, using |\FancyVerbFormatLine| (you may also wish to consider the |formatcom| option). For example, the following command puts a green background behind all the characters in each line of code: % \begin{verbatim} -% \renewcommand{\FancyVerbFormatLine}[1]{\colorbox{green}{#1}} +%\renewcommand{\FancyVerbFormatLine}[1]{\colorbox{green}{#1}} % \end{verbatim} % % If you need a completely solid colored background for an environment, or a highly customizable background, you should consider the |mdframed| package. Wrapping \pytex\ environments with |mdframed| frames works quite well. You can even automatically add a particular style of frame to all instances of an environment using the command @@ -1347,7 +1428,7 @@ % % All contextual data is available as strings on the Python/other language side. For convenience, the utilities class provides unit conversion methods for converting from \TeX\ points to inches, centimeters, millimeters, and big (DTP or PostScript) points. These methods take integers, floats, or strings that consist of digits (optionally ending in ``pt''), and return floats. For example, |pytex.pt_to_in()|, |pytex.pt_to_cm()|, |pytex.pt_to_mm()|, |pytex.pt_to_bp()|. Keep in mind that the units of \TeX\ points are \href{http://tex.stackexchange.com/questions/41370/what-are-the-possible-dimensions-sizes-units-latex-understands}{$1/72.27$} of an inch, \emph{not} $1/72$ of an inch (which is a bp). % -% There is also a type system for Python that allows the types of \meta{values} to be specified. Any \meta{value} beginning with |!!int| will become an integer; with |!!float|, a float; with |!!str|, a string. This notation is borrowed from \href{http://yaml.org/}{YAML}. For example, +% There is also a type system for Python that allows the types of \meta{values} to be specified. Any \meta{value} beginning with |!!int| will become an integer; with |!!float|, a float; with |!!str|, a string. This notation is borrowed from \href{http://yaml.org/}{YAML}. For example, %\begin{verbatim} %\setpythontexcontext{a=!!int 42, b=!!float 42, c=!!str 42} %\end{verbatim} @@ -1371,7 +1452,7 @@ % % \DescribeMacro{\setpythontexoutputdir\marg{output~directory}} % -% By default, \pytex\ saves all temporary files and automatically generated content in a directory called |pythontex-files-|\meta{sanitized jobname}, where \meta{sanitized jobname} is just |\jobname| with any space characters or asterisks replaced with hyphens. This directory will be created by |pythontex.py|. If we wish to specify another directory (for example, if |\jobname| is long and complex, and there is no danger of two files trying to use the same directory), then we can use the |\setpythontexoutputdir| macro to redefine the output directory.\footnote{In the rare event that both |\string\setpythontexoutputdir| is used and |\string\printpythontex| is needed in the preamble, |\string\setpythontexoutputdir| must be used first, so that |\string\printpythontex| will know where to look for output.} +% By default, \pytex\ saves all temporary files and automatically generated content in a directory called |pythontex-files-|\meta{sanitized jobname}, where \meta{sanitized jobname} is just |\jobname| with any space characters or asterisks replaced with hyphens. This directory will be created by |pythontex.py|. If we wish to specify another directory (for example, if |\jobname| is long and complex, and there is no danger of two files trying to use the same directory), then we can use the |\setpythontexoutputdir| macro to redefine the output directory.\footnote{In the rare event that both |\setpythontexoutputdir| is used and |\printpythontex| is needed in the preamble, |\setpythontexoutputdir| must be used first, so that |\printpythontex| will know where to look for output.} % % Any slashes in \meta{output~directory} should be forward slashes ``|/|'' (even under Windows). Tildes |~| may be used to refer to the user's home directory, including under Windows. % @@ -1385,7 +1466,7 @@ % % Note that in many use cases, you may be able to use the output directory as the working directory. The |graphicx| package will automatically look for images and figures in the output directory when it is used as the working directory, so long as you do not use the |\graphicspath| command outside the preamble.\footnote{\texttt{graphicx} looks for graphics in the document root directory and in the most recent graphics path defined by \texttt{\string\graphicspath}. \texttt{\string\graphicspath} stores the graphics path in \texttt{\string\Ginput@path}, overwriting any previous value. At the end of the preamble, \pytex\ appends the output directory to \texttt{\string\Ginput@path} if the output directory is being used as the working directory. Thus, that directory will always be checked for graphics, so long as \texttt{\string\Ginput@path} is not overwritten by a subsequent use of \texttt{\string\graphicspath}. If you need to use \texttt{\string\graphicspath} within the document, you could consider creating a custom version that redefines \texttt{\string\Ginput@path} with the \pytex\ output directory automatically appended.} To use the output directory as the working directory, you may enter the full name of the output directory manually, or use the text ``||'' as a shortcut: %\begin{verbatim} -%\setpythontexworkingdir{} +%\setpythontexworkingdir{} %\end{verbatim} % % It is also possible to change the working directory from within Python code, via |os.chdir()|. @@ -1421,8 +1502,8 @@ % \label{sec:depythontex} % % \pytex\ can greatly simplify the creation of documents. At the same time, by introducing dependence on non-\LaTeX\ external tools, it can constrain how these documents are used. For example, many publishers will not accept \LaTeX\ documents that require special packages or need special macros. To address this issue, the package includes a feature called |depythontex| that can convert a \pytex\ document into a plain \LaTeX\ document. -% -% +% +% % \subsection{Preparing a document that will be converted} % % The conversion process should work flawlessly in most cases, with no special formatting required. @@ -1434,7 +1515,7 @@ % \item If you need to insert content from Python in inline contexts, it is best to use |\py| or an equivalent command. If you use |print|, either directly (for example, from within |\pyc|) or via |\printpythontex|, make sure that the spacing following the printed content is correct. You may need to print an |\endinput| or |%| at the end of your content to prevent an extra trailing space. |depythontex| will attempt to reproduce the spacing of the original document, even if it is not ideal. See Section~\ref{sec:depythontex:technical-details} for additional details. % \item Some \LaTeX\ environments, such as the |verbatim| environment from the |verbatim| package and the |Verbatim| environment from |fancyvrb|, do not allow text to follow the |\end{|\meta{environment}|}|. If you bring Python-generated content that ends with one of these environments into your document, using |print| or |\py|, make sure that the end-of-environment command is followed by a newline. For example, if you are assembling a |Verbatim| environment to bring in, the last line should be the string % \begin{verbatim} -% '\\end{Verbatim}\n' +%'\\end{Verbatim}\n' % \end{verbatim} % Even if you neglect a final newline, |depythontex| will still function correctly in most cases. Whenever Python-generated content does not end with a newline, |depythontex| usually inserts one and gobbles spaces that follow the environment. This preserves the correct spacing while avoiding any issues produced by an end-of-environment command. But in some cases, |depythontex| cannot do this. For example, if |\py| is used to bring in a |Verbatim| environment, and there is text immediately after the |\py|, without any intervening space, |depythontex| cannot substitute a newline for spaces, because there are none. Because of the way that |print| and |\py| content is brought in, everything may still work correctly in the original \pytex\ document. But it would fail in the |depythontex| output. % \item Do not create \pytex\ commands or environments on the Python side and |print| or otherwise bring them in. That is too many levels of complexity! @@ -1445,7 +1526,7 @@ % \end{itemize} % % \subsection{Removing \pytex\ dependence} -% +% % Converting a document requires three steps. % \begin{enumerate} % \item Turn on the package option |depythontex|. Then compile the document, run |pythontex.py|, and compile the document again. Depending on the document, additional compiles may be necessary (for example, to resolve references). Any syntax highlighting will be turned off automatically during this process, to remove dependence on Pygments. @@ -1461,13 +1542,13 @@ % When code is typeset with any option other than |verbatim|, listing line numbering from the original document will be preserved. When code is typeset with any option other than |verbatim| and |fancyvrb|, syntax highlighting will also be preserved. The only exception is when |listings| is used, and |listings|'s language name does not correspond to Pygments' lexer name. In this case, you should use the |--lexer-dict| option to specify how the Pygments lexer is to be translated into a |listings| language. % \item |--lexer-dict| This option is used to specify how Pygments lexers are converted to |listings| languages, when the two do not have the same name. It takes a comma-separated list of the form % \begin{verbatim} -% ":, ..., ... " +%":, ..., ... " % \end{verbatim} % A Python-style dict will also be accepted. % \item |--preamble| This option allows additional commands to be added to the output document's preamble. This is useful when you want the output document to load a package that was automatically loaded by \pytex, such as |upquote|. % \item |--graphicspath| This option adds the |outputdir| to any existing graphics path defined by |\graphicspath|, or adds a |\graphicspath| command if one does not already exist. This causes the |depythontex| document to automatically look in the |outputdir| for graphics. Only use this option if you want to continue using the |outputdir| with the |depythontex| document. Graphics are further discussed below. % \item |-o| |--output| The name of the output file. If no name is given, the converted file is written to |stdout|. -% \item |TEXNAME| The name of the \LaTeX\ file whose \pytex\ dependence is to be removed. +% \item |TEXNAME| The name of the \LaTeX\ file whose \pytex\ dependence is to be removed. % \end{itemize} % \item Compile the |depythontex| file, and compare it to the original. % @@ -1488,7 +1569,7 @@ % This spacing behavior is due to \LaTeX's |\input|. When the file of printed content is brought in via |\input|, \LaTeX\ removes any newline characters (|\n|, |\r|, or |\r\n|) at the end of each line, and adds a space at the end of each line (even if there wasn't a newline character). Thus, when the printed content is brought in, a space is added to its end. Since this space is within the |\input|'s curly braces |{}|, it is not combined with any following spaces in the \LaTeX\ document to make a single space. Rather, if the printed content is followed by one or more spaces, two spaces will result; and if it is followed immediately by text, there will be a single space before the text. % -% The space added by |\input| is often invisible, and even when it is not, it is sometimes desirable.\footnote{For example, |\string\printpythontex| behaves as a normal command, and gobbles following spaces, but the space from |\string\input| puts a space back. So you often get the space you want in inline contexts.} But this space can be an issue in some inline contexts. The simplest solution is to use a command like |\py| to bring in content inline. +% The space added by |\input| is often invisible, and even when it is not, it is sometimes desirable.\footnote{For example, |\printpythontex| behaves as a normal command, and gobbles following spaces, but the space from |\input| puts a space back. So you often get the space you want in inline contexts.} But this space can be an issue in some inline contexts. The simplest solution is to use a command like |\py| to bring in content inline. % % If a command like |\py| is not practical for some reason, there are at least three ways to deal with the space introduced by |\input|: by printing |\endinput| at the end of the printed content (ending the content before the final space), by printing |%| at the end of the printed content (commenting out the final space), or by using |\unskip| after the printed content (eating preceding spaces). |depythontex| will work with all three approaches, but only under a limited range of circumstances. In summary, |depythontex| works with |\endinput| and |%| only if they are the very last thing printed (before a final newline), and works with a following |\unskip|.\footnote{It would be possible to make \texttt{depythontex} work with \texttt{\string\endinput} and \texttt{\%} anywhere, not just at the very end of printed content. But doing so would require a lot of additional parsing, especially for \texttt{\string\endinput}, to be absolutely sure that we found an actual command rather than a string. Furthermore, there is no reason that there should be any content after an \texttt{\string\endinput} or \texttt{\%}, since such content would never be included in the document. Indeed, the current approach prevents any printed content from accidentally being eliminated in this manner.} % \begin{itemize} @@ -1522,16 +1603,16 @@ % This section will be expanded in the future. For now, it offers a brief summary. % % \subsection{Macro programming with \pytex} -% +% % In many situations, you can use \pytex\ commands inside macro definitions without any special consideration. For example, consider the following macro, for calculating powers. % \newcommand{\pow}[2]{\py{#1**#2}} % \begin{verbatim} -% \newcommand{\pow}[2]{\py{#1**#2}} +%\newcommand{\pow}[2]{\py{#1**#2}} % \end{verbatim} % Once this is defined, we can calculate |2**8| via |\pow{2}{8}|: \pow{2}{8}. Similarly, we can reverse a string. % \newcommand{\reverse}[1]{\py{"#1"[::-1]}} % \begin{verbatim} -% \newcommand{\reverse}[1]{\py{"#1"[::-1]}} +%\newcommand{\reverse}[1]{\py{"#1"[::-1]}} % \end{verbatim} % Now we can use |\reverse{``This is some text!''}|: \reverse{``This is some text!''}. % @@ -1539,16 +1620,16 @@ % % Of course, there are many cases where macros don't need arguments. Here is code for creating a macro that generates random polynomials. % \begin{verbatim} -% \begin{sympycode} -% from sympy.stats import DiscreteUniform, sample -% x = Symbol('x') -% a = DiscreteUniform('a', range(-10, 11)) -% b = DiscreteUniform('b', range(-10, 11)) -% c = DiscreteUniform('c', range(-10, 11)) -% def randquad(): -% return Eq(sample(a)*x**2 + sample(b)*x + sample(c)) -% \end{sympycode} -% \newcommand\randquad{\sympy{randquad()}} +%\begin{sympycode} +%from sympy.stats import DiscreteUniform, sample +%x = Symbol('x') +%a = DiscreteUniform('a', range(-10, 11)) +%b = DiscreteUniform('b', range(-10, 11)) +%c = DiscreteUniform('c', range(-10, 11)) +%def randquad(): +% return Eq(sample(a)*x**2 + sample(b)*x + sample(c), 0) +%\end{sympycode} +%\newcommand{\randquad}{\ensuremath{\sympy{randquad()}}} % \end{verbatim} % % If you are considering writing macros that involve \pytex, you should keep a few things in mind. @@ -1649,14 +1730,14 @@ % % % \subsection{Perl} -% +% % Support for Perl was added in v0.17. % % Loading \pytex\ with |usefamily=perl| enables the |perl| family of commands and environments. Alternatively, |usefamily=pl| may be used to enable the |pl| family. There is currently no utilities class or related features. % % % \subsection{Perl 6} -% +% % Support for Perl 6 was added in v0.17. % % Loading \pytex\ with |usefamily=perlsix| enables the |perlsix| family of commands and environments. Alternatively, |usefamily=psix| may be used to enable the |psix| family. There is currently no utilities class or related features. @@ -1687,7 +1768,7 @@ % \item Set the script encoding. The |{encoding}| field will be replaced with a user-specified encoding or the default |UTF-8|. If you are not using anything beyond ASCII, this is not strictly necessary. % \item Python templates should have a |{future}| field at the beginning, for compability with Python 2 and the package option |pyfuture|.\footnote{The beginning of user code is parsed for imports from \texttt{\_\_future\_\_}. Any imports are collected and inserted into the \texttt{\{\{future\}\}} field.} % \item Set the |stdout| and |stderr| encoding, again using |{encoding}|. As before, this is not strictly necessary when only ASCII support is needed. -% \item Create a language-specific equivalent of the \pytex\ utilities class.\footnote{Python templates can import the \pytex\ utilities class. In that case, \texttt{sys.path.append('\{\{utilspath\}\}')} is needed before the import, so that the location of the utilities class is known.} Create an instance of this class. It is recommended that the class be called \meta{language~name}|TeXUtils| and the instance \meta{language~extension}|tex|, by analogy with the Python case.\footnote{The class could be called \meta{language~name}\texttt{TeX}. In that case, the class and the instance would have the very same name (except for capitalization) in cases where the language name and extension are the same (for example, Lua). That is probably not desirable, and besides, \texttt{Utils} adds additional clarity. The instance name \meta{language~extension}\texttt{tex} is recommended because it will be short and easily remembered. Plain \texttt{tex} could be used instead, but that would be less descriptive (it lacks the interface connotations) and would not remind the user of the language currently in use (which could be beneficial in a document combining multiple languages, each with its own slightly different utilities class).} When the \meta{language~extension} is only a single character or is shared by multiple languages, it may be better to use the full \meta{language~name} or an abbreviation in the name of the class instance. +% \item Create a language-specific equivalent of the \pytex\ utilities class.\footnote{Python templates can import the \pytex\ utilities class. In that case, |sys.path.append('{{utilspath}}')| is needed before the import, so that the location of the utilities class is known.} Create an instance of this class. It is recommended that the class be called \meta{language~name}|TeXUtils| and the instance \meta{language~extension}|tex|, by analogy with the Python case.\footnote{The class could be called \meta{language~name}\texttt{TeX}. In that case, the class and the instance would have the very same name (except for capitalization) in cases where the language name and extension are the same (for example, Lua). That is probably not desirable, and besides, \texttt{Utils} adds additional clarity. The instance name \meta{language~extension}\texttt{tex} is recommended because it will be short and easily remembered. Plain \texttt{tex} could be used instead, but that would be less descriptive (it lacks the interface connotations) and would not remind the user of the language currently in use (which could be beneficial in a document combining multiple languages, each with its own slightly different utilities class).} When the \meta{language~extension} is only a single character or is shared by multiple languages, it may be better to use the full \meta{language~name} or an abbreviation in the name of the class instance. % % For full \pytex\ support, the utilities class should provide the following methods: % \begin{itemize} @@ -1773,7 +1854,7 @@ % % \item The |tabular| environment can conflict with \pytex\ under some circumstances, due to how |tabular| functions. Among other things, printing within a |tabular| environment can cause errors, because printing involves bringing in external content via |\InputIfFileExists|, but that macro is not expandable.\footnote{For more information, see \href{http://tex.stackexchange.com/questions/50820/expandable-version-of-inputiffileexists-or-iffileexists}{this}, \href{http://tex.stackexchange.com/questions/50828/execute-non-expandable-code-inside-a-tabular-environment}{this}, and \href{http://tex.stackexchange.com/questions/50694/cannot-use-toprule-when-doing-input-inside-tabular-why}{this}.} There are a few different ways to work around the limitations of |tabular|. % \begin{itemize} -%\item Put the printed content in a macro definition, and use the macro in |tabular|. You will have to create a dummy version of the macro, to avoid errors before the macro is defined by \pytex. An example is given below. The |\global\def| is needed so that the macro is defined outside of the |pycode| environment. +%\item Put the printed content in a macro definition, and use the macro in |tabular|. You will have to create a dummy version of the macro, to avoid errors before the macro is defined by \pytex. An example is given below. The |\global\def| is needed so that the macro is defined outside of the |pycode| environment. %\begin{verbatim} %\let\row\relax %\begin{pycode} @@ -1898,7 +1979,7 @@ % We store the name of the package in a macro for later use in warnings and error messages. % \begin{macrocode} \newcommand{\pytx@packagename}{PythonTeX} -\newcommand{\pytx@packageversion}{0.18} +\newcommand{\pytx@packageversion}{0.19} % \end{macrocode} % % \subsection{Required packages} @@ -2119,7 +2200,7 @@ % % \subsubsection{Upquote} % \begin{macro}{pytx@opt@upquote} -% The |upquote| option determines whether the |upquote| package is loaded. It makes quotes within verbatim contexts \expandafter|\textquotesingle| rather than |'|. This is important, because it means that code may be copied directly from the compiled PDF and executed without any errors due to quotes |'| being copied as acute accents \texttt{\'}. +% The |upquote| option determines whether the |upquote| package is loaded. It makes quotes within verbatim contexts \expandafter|\textquotesingle| rather than |'|. This is important, because it means that code may be copied directly from the compiled PDF and executed without any errors due to quotes |'| being copied as acute accents \texttt{\'}. % \begin{macrocode} \newbool{pytx@opt@upquote} \booltrue{pytx@opt@upquote} @@ -2160,7 +2241,7 @@ % By default, \pytex\ uses |fancyvrb| to typeset code. This provides nice formatting and font options, but no syntax highlighting. The |prettyprinter| options, and |pygments| alias, determine whether Pygments or |fancyvrb| is used to typeset code. Pygments is a generic syntax highlighter written in Python. Since \pytex\ sends code to Python anyway, having Pygments process the code is only a small additional step and in many cases takes little if any extra time to execute.\footnote{Pygments code highlighting is executed as a separate process by |pythontex.py|, so it runs in parallel on a multicore system. Pygments usage is optimized by saving highlighted code and only reprocessing it when changed.} % % Command and environment families obey the |prettyprinter| option by default, but they may be set to override it and always use Pygments or always use |fancyvrb|, via |\setpythontexprettyprinter| and |\setpygmentsprettyprinter|. -% \begin{macrocode} +% \begin{macrocode} \newbool{pytx@opt@pygments} \booltrue{pytx@opt@pygments} \pgfkeys{/PYTX/pkgopt/prettyprinter/.is choice} @@ -2205,7 +2286,7 @@ % % Currently, three options may be passed in this manner: |style=|\meta{style}, which sets the formatting style; |texcomments|, which allows \LaTeX\ in code comments to be rendered; and |mathescape|, which allows \LaTeX\ math mode (|$...$|) in comments. The |texcomments| and |mathescape| options may be used with a boolean argument; if an argument is not supplied, true is assumed. As an example of |pygopt| usage, consider the following: % \begin{verbatim} -% pygopt={style=colorful, texcomments=true, mathescape=false} +%pygopt={style=colorful, texcomments=true, mathescape=false} % \end{verbatim} % % While the package-level |pygments| option may be overridden by individual commands and environments (though it is not by default), the package-level Pygments options cannot be overridden by individual commands and environments. While we're defining storage for |pygopt|, go ahead and define parsing to extract |style| for later use under all cicumstances. This should be reorganized during the next refactoring. @@ -2238,7 +2319,7 @@ % A default value of 25 is set. There is nothing special about 25; it is just a relatively reasonably cutoff. If the option is unused, it has a value of $-1$, which is converted to the maximum integer on the Python side. % \begin{macrocode} \def\pytx@fvextfile{-1} -\pgfkeys{/PYTX/pkgopt/fvextfile/.default=25} +\pgfkeys{/PYTX/pkgopt/fvextfile/.default=25} \pgfkeys{/PYTX/pkgopt/fvextfile/.code=\IfInteger{#1}{% \ifnum#1>0\relax \def\pytx@fvextfile{#1}% @@ -2249,7 +2330,7 @@ } % \end{macrocode} % \end{macro} -% +% % \subsubsection{Python console environment} % \begin{macro}{\pytx@opt@pyconbanner} % This option governs the appearance (or disappearance) of a banner at the beginning of Python console environments. The options |none| (no banner), |standard| (standard Python banner), |default| (default banner for Python's |code| module, standard banner plus interactive console class name), and |pyversion| (banner in the form |Python x.y.z|) are accepted. @@ -2266,8 +2347,8 @@ % \begin{macro}{\pytx@opt@pyconfilename} % This option governs the file name that appears in error messages in the console. The file name may be either |stdin|, as it is in a standard interactive interpreter, or |console|, as it would typically be for the Python |code| module. % \begin{verbatim} -% Traceback (most recent call last): -% File "", line , in +%Traceback (most recent call last): +% File "", line , in % \end{verbatim} % \begin{macrocode} \def\pytx@opt@pyconfilename{stdin} @@ -2328,7 +2409,7 @@ % Once options are processed, we proceed to define a number of utility macros and setup the file input/output that is required by \pytex. We also create macros and perform setup needed by depythontex, since these are closely related to input/output. % % \subsubsection{Automatic counter creation} -% +% % \begin{macro}{\pytx@CheckCounter} % We will be using counters to give each command/environment a unique identifier, as well as to manage line numbering of code when desired. We don't know the names of the counters ahead of time (this is actually determined by the user's naming of code sessions), so we need a macro that checks whether a counter exists, and if not, creates it. % \begin{macrocode} @@ -2441,7 +2522,7 @@ \@onlypreamble\restartpythontexsession \restartpythontexsession{default} % \end{macrocode} -% +% % \subsubsection{File input and output} % % \begin{macro}{\pytx@jobname} @@ -2500,7 +2581,7 @@ % % \begin{macro}{pytx@usedpygments} % Once we have specified the output directory, we are free to pull in content from it. Most content from the output directory will be pulled in manually by the user (for example, via |\includegraphics|) or automatically by \pytex\ as it goes along. But content ``printed'' by code commands and environments (via macros) as well as code typeset by Pygments needs to be included conditionally, based on whether it exists and on user preferences. -% +% % This gets a little tricky. We only want to pull in the Pygments content if it is actually used, since Pygments content will typically use |fancyvrb|'s |SaveVerb| environment, and this can slow down compilation when very large chunks of code are saved. It doesn't matter if the code is actually used; saving it in a macro is what potentially slows things down. So we create a bool to keep track of whether Pygments is ever actually used, and only bring in Pygments content if it is.\footnote{The same effect could be achieved by having |pythontex.py| delete the Pygments content whenever it is run and Pygments is not used. But that approach is faulty in two regards. First, it requires that |pythontex.py| be run, which is not necessarily the case if the user simply sets the package option |pygments| to |false| and the recompiles. Second, even if it could be guaranteed that the content would be deleted, such an approach would not be optimal. It is quite possible that the user wishes to temporarily turn off Pygments usage to speed compilation while working on other parts of the document. In this case, deleting the Pygments content is simply deleting data that must be recreated when Pygments is turned back on.} This bool must be set to |true| whenever a command or environment is created that makes use of Pygments (in practice, we will simply set it to true when a family is created). Note that we cannot use the |pytx@opt@pygments| bool for this purpose, because it only tells us if the package option for Pygments usage is |true| or |false|. Typically, this will determine if any Pygments content is used. But it is possible for the user to create a command and environment family that overrides the package option (indeed, this may sometimes be desirable, for example, if the user wishes code in a particular language never to be highlighted). Thus, a new bool is needed to allow detection in such nonstandard cases. % \begin{macrocode} \newbool{pytx@usedpygments} @@ -2539,7 +2620,7 @@ } % \end{macrocode} % \end{macro}\end{macro} -% +% % % \begin{macro}{\pytx@codefile} % We create a new write, named |\pytx@codefile|, to which we will save code. All the code from the document will be written to this single file, interspersed with information specifying where in the document it came from. \pytex\ parses this file to separate the code into individual sessions and groups. These are then executed, and the identifying information is used to tie code output back to the original code in the document.\footnote{The choice to write all code to a single file is the result of two factors. First, \TeX\ has a limited number of output registers available (16), so having a separate output stream for each group or session is not possible. The |morewrites| package from Bruno Le Floch potentially removes this obstacle, but since this package is very recent (README from 2011/7/10), we will not consider using additional writes in the immediate future. Second, one of the design goals of \pytex\ is to minimize the number of persistent files created by a run. This keeps directories cleaner and makes file synchronization/transfer somewhat simpler. Using one write per session or group could result in numerous code files, and these could only be cleaned up by |pythontex.py| since \LaTeX\ cannot delete files itself (well, without unrestricted |write18|). Using a single output file for code does introduce a speed penalty since the code does not come pre-sorted by session or group, but in typical usage this should be minimal. Adding an option for single or multiple code files may be something to reconsider at a later date.} @@ -2548,7 +2629,7 @@ \immediate\openout\pytx@codefile=\jobname.pytxcode % \end{macrocode} % \end{macro} -% +% % In the code file, information from \pytex\ must be interspersed with the code. Some type of delimiting is needed for \pytex\ information. All \pytex\ content is written to the file in the form |=>PYTHONTEX#|\meta{content}|#|. When this content involves package options, the delimiter is modified to the form |=>PYTHONTEX:SETTINGS#|\meta{content}|#|. The |#| symbol is also used as a subdelimiter within \meta{content}. The |#| symbol is convenient as a delimiter since it has a special meaning in \TeX\ and is very unlikely to be accidentally entered by the user in unexpected locations without producing errors. Note that the usage of ``|=>PYTHONTEX#|'' as a beginning delimiter for \pytex\ data means that this string should \textbf{never} be written by the user at the beginning of a line, because |pythontex.py| will try to intepret it as data and will fail. % % \begin{macro}{\pytx@delimchar} @@ -2631,7 +2712,7 @@ % \begin{macro}{\pytx@fvsettings}\begin{macro}{\setpythontexfv} % The macro |\setpythontexfv|\oarg{family}\marg{settings} takes \meta{settings} and stores them in a macro that is run through |fancyvrb|'s |\fvset| at the beginning of \pytex\ code. If a \meta{family} is specified, the settings are stored in |\pytx@fvsettings@|\meta{family}, and the settings only apply to typeset code belonging to that family. If no optional argument is given, then the settings are stored in |\pytx@fvsettings|, and the settings apply to all typeset code. % -% In the current implementation, |\setpythontexfv| and |\fvset| differ because the former is not persistent in the same sense as the latter. If we use |\fvset| to set one property, and then use it later to set another property, the setting for the original property is persistent. It remains until another |\fvset| command is issued to change it. In contrast, every time |\setpythontexfv| is used, it clears all prior settings and only the current settings actually apply. This is because |\fvset| stores the state of each setting in its own macro, while |\setpythontexfv| simply stores a string of settings that is passed to |\fvset| at the appropriate times. For typical use scenarios, this distinction shouldn't be important---usually, we will want to set the behavior of |fancyvrb| for all \pytex\ content, or for a family of \pytex\ content, and leave those settings constant throughout the document. Furthermore, environments that typeset code take |fancyvrb| commands as their second optional argument, so there is already a mechanism in place for changing the settings for a single environment. However, if we ever want to change the typesetting of code for only a small portion of a document (larger than a single environment), this persistence distinction does become important.\footnote{An argument could be made for having |\textbackslash setpythontexfv| behave exactly like |\textbackslash fvset|. Properly implementing this behavior would be tricky, because of inheritance issues between \pytex-wide and family-specific settings (this is probably a job for |pgfkeys|). Full persistence would likely require a large number of macros and conditionals. At least from the perspective of keeping the code clean and concise, the current approach is superior, and probably introduces minor annoyances at worst.} +% In the current implementation, |\setpythontexfv| and |\fvset| differ because the former is not persistent in the same sense as the latter. If we use |\fvset| to set one property, and then use it later to set another property, the setting for the original property is persistent. It remains until another |\fvset| command is issued to change it. In contrast, every time |\setpythontexfv| is used, it clears all prior settings and only the current settings actually apply. This is because |\fvset| stores the state of each setting in its own macro, while |\setpythontexfv| simply stores a string of settings that is passed to |\fvset| at the appropriate times. For typical use scenarios, this distinction shouldn't be important---usually, we will want to set the behavior of |fancyvrb| for all \pytex\ content, or for a family of \pytex\ content, and leave those settings constant throughout the document. Furthermore, environments that typeset code take |fancyvrb| commands as their second optional argument, so there is already a mechanism in place for changing the settings for a single environment. However, if we ever want to change the typesetting of code for only a small portion of a document (larger than a single environment), this persistence distinction does become important.\footnote{An argument could be made for having |\setpythontexfv| behave exactly like |\fvset|. Properly implementing this behavior would be tricky, because of inheritance issues between \pytex-wide and family-specific settings (this is probably a job for |pgfkeys|). Full persistence would likely require a large number of macros and conditionals. At least from the perspective of keeping the code clean and concise, the current approach is superior, and probably introduces minor annoyances at worst.} % \begin{macrocode} \newcommand{\setpythontexfv}[2][]{% \Depythontex{cmd:setpythontexfv:om:n}% @@ -2640,7 +2721,7 @@ {\expandafter\gdef\csname pytx@fvsettings@#1\endcsname{#2}}% }% % \end{macrocode} -% +% % Now that we have a mechanism for applying global settings to typeset \pytex\ code, we go ahead and set a default tab size for all environments. If |\setpythontexfv| is ever invoked, this setting will be overwritten, so that must be kept in mind. % \begin{macrocode} \setpythontexfv{tabsize=4} @@ -2864,7 +2945,7 @@ % % A mechanism is provided for saving and later using stderr. This should be used with care, since stderr content may lose some of its meaning if isolated from the larger code context that produced it. % -% \begin{macro}{\savestderrpythontex} +% \begin{macro}{\savestderrpythontex} % \begin{macrocode} \def\savestderrpythontex#1{% \Depythontex{cmd:savestderrpythontex:m:n}% @@ -2921,7 +3002,7 @@ % \begin{macro}{\Depythontex} % Each command or environment that is to work with depythontex will write the following information to the auxiliary file: % \begin{verbatim} -% =>DEPYTHONTEX#:::::[]# +%=>DEPYTHONTEX#:::::[]# % \end{verbatim} % where || is |cmd| or |env|; || is the complete name of the command or environment; || is a string representing the arguments taken (|o|=optional, |m|=mandatory, |v|=mandatory~verbatim, |n|=none); || is a string representing what is typeset (|c|=code, |p|=printed, |n|=null), and || is |\the\inputlineno|. The last one can be determined automatically without user input, but the first four must be entered when a macro is created. Optionally, the Pygments lexer is written to file if it is available (if |\pytx@lexer| is not |\relax|). These pieces of information are needed for the following reasons. % \begin{itemize} @@ -3112,7 +3193,7 @@ % We save a retokenized version of the argument in |\pytx@argretok|. This is needed for typesetting with |fancyvrb|. The code must be retokenized so that space characters are active, since |fancyvrb| allows space characters to be visible or invisible by making them active. % % The \textbf{name} of the counter corresponding to this code is assembled. It is needed for keeping track of the instance, and is used for bringing in content created by the code and for bringing in highlighting created by Pygments. -% +% % Next we call a series of macros that determine whether the code is shown (typeset), whether it is saved to the code file, and whether content created by the code (``printed'') should be brought in. These macros are |\let| to appropriate values when an inline command is called; they are not defined independently. % % Finally, the counter for the code is incremented. @@ -3141,7 +3222,7 @@ % % % \begin{macro}{\pytx@InlineShowFV} -% Code may be typeset with |fancyvrb|. |fancyvrb| settings are invoked via |pytx@FVSet|, but this must be done within a group so that the settings remain local. Most of the remainder of the commands are from |fancyvrb|'s |\FV@FormattingPrep|, and take care of various formatting matters, including spacing, font, whether space characters are shown, and any user-defined formatting. Finally, we create an |\hbox| and invoke |\FancyVerbFormatLine| to maintain parallelism with |BVerbatim|, which is used for inline content highlighted with Pygments. |\FancyVerbFormatLine| may be redefined to alter the typeset code, for example, by putting it in a colorbox via the following command:\footnote{Currently, |\textbackslash FancyVerbFormatLine| is global, as in |fancyvrb|. Allowing a family-specific variant may be considered in the future. In most cases, the |fancyvrb| option |formatcom|, combined with external formatting from packages like |mdframed|, should provide all formatting desired. But something family-specific might occasionally prove useful.} +% Code may be typeset with |fancyvrb|. |fancyvrb| settings are invoked via |pytx@FVSet|, but this must be done within a group so that the settings remain local. Most of the remainder of the commands are from |fancyvrb|'s |\FV@FormattingPrep|, and take care of various formatting matters, including spacing, font, whether space characters are shown, and any user-defined formatting. Finally, we create an |\hbox| and invoke |\FancyVerbFormatLine| to maintain parallelism with |BVerbatim|, which is used for inline content highlighted with Pygments. |\FancyVerbFormatLine| may be redefined to alter the typeset code, for example, by putting it in a colorbox via the following command:\footnote{Currently, |\FancyVerbFormatLine| is global, as in |fancyvrb|. Allowing a family-specific variant may be considered in the future. In most cases, the |fancyvrb| option |formatcom|, combined with external formatting from packages like |mdframed|, should provide all formatting desired. But something family-specific might occasionally prove useful.} % \begin{quote} % |\renewcommand{\FancyVerbFormatLine}[1]{\colorbox{green}{#1}}| % \end{quote} @@ -3472,7 +3553,7 @@ % % % \subsection{Environments} -% +% % The inline commands were all created using a common core set of macros, combined with short, command-specific constructors. In the case of environments, we do not have a common core set of macros. Each environment is coded separately, though there are similarities among environments. In the future, it may be worthwhile to attempt to consolidate the environment code base. % % One of the differences between inline commands and environments is that environments may need to typeset code with line numbers. Each family of code needs to have its own line numbering (actually, its own numbering for code, verbatim, and console groups), and this line numbering should not overwrite any line numbering that may separately be in use by |fancyvrb|. To make this possible, we use a temporary counter extensively. When line numbers are used, |fancyvrb|'s line counter is copied into |pytx@FancyVerbLineTemp|, lines are numbered, and then |fancyvrb|'s line counter is restored from |pytx@FancyVerbLineTemp|. This keeps |fancyvrb| and \pytex's line numbering separate, even though \pytex\ is using |fancyvrb| and its macros internally. @@ -3488,7 +3569,7 @@ \gdef\pytx@FancyVerbGetLine#1^^M{% \@nil% \FV@CheckEnd{#1}% - \ifx\@tempa\FV@EnvironName% + \ifx\@tempa\FV@EnvironName% \ifx\@tempb\FV@@@CheckEnd\else\FV@BadEndError\fi% \let\next\FV@EndScanning% \else% @@ -3703,7 +3784,7 @@ % % % \subsubsection{Code environment constructor} -% The |code| environment merely saves code to the code file; nothing is typeset. To accomplish this, we use a slightly modified version of |fancyvrb|'s |VerbatimOut|. +% The |code| environment merely saves code to the code file; nothing is typeset. To accomplish this, we use a slightly modified version of |fancyvrb|'s |VerbatimOut|. % \begin{macro}{\pytx@WriteDetok} % We can use |fancyvrb| to capture the code, but we will need a way to write the code in detokenized form. This is necessary so that \TeX\ doesn't try to process the code as it is written, which would generally be disastrous. % \begin{macrocode} @@ -3897,11 +3978,11 @@ % \end{macrocode} % \end{macro} % -% +% % % % \subsubsection{Console environment constructor} -% +% % The |console| environment needs to write all code contained in the environment to the code file, and then bring in the console output. % % An environment suffix is not enforced for flexibility. For Python, the convention is that |console| type names will end with |con|, and then the environment will use the suffix |sole|. For example, the |pycon| type has the |pyconsole| environment. @@ -4484,7 +4565,7 @@ % Then we check to see if the file actually exists, and issue a warning if not. This saves the user from running |pythontex.py| to get the same error. We perform our typical |FancyVerbLine| trickery. Next we make use of the saved content in the same way as the |pygments| environment. Note that we do not create a counter for the line numbers. This is because under typical usage an external file should have its lines numbered beginning with 1. We also encourage this by setting |firstnumber=auto| before bringing in the content. % % The current naming of the macro in which the Pygments content is saved is probably excessive. In almost every situation, a unique name could be formed with less information. The current approach has been taken to maintain parallelism, thus simplifying |pythontex.py|, and to avoid any rare potential conflicts. -% +% % \begin{macrocode} \def\pytx@MakePygmentsInputFV{ \newcommand{\inputpygments}[3][]{% @@ -4531,9 +4612,9 @@ \pytx@FVSet \fvset{firstnumber=auto}% \pytx@ConfigPygments - \ifcsname FV@SV@pytx@\pytx@type @\pytx@session @\pytx@group + \ifcsname FV@SV@pytx@\pytx@type @\pytx@session @\pytx@group @\arabic{\pytx@counter}\endcsname - \UseVerbatim[##1]{pytx@\pytx@type @\pytx@session @\pytx@group + \UseVerbatim[##1]{pytx@\pytx@type @\pytx@session @\pytx@group @\arabic{\pytx@counter}}% \else \InputIfFileExists{\pytx@outputdir/\pytx@type_##3_\pytx@group @@ -4800,7 +4881,7 @@ }{} %End beta % \end{macrocode} -% +% % % % \iffalse diff --git a/pythontex/pythontex.ins b/pythontex/pythontex.ins index 83dd081..2d7f3c1 100644 --- a/pythontex/pythontex.ins +++ b/pythontex/pythontex.ins @@ -1,4 +1,4 @@ -%% Copyright (C) 2012-2019 by Geoffrey M. Poore +%% Copyright (C) 2012-2026 by Geoffrey M. Poore %% -------------------------------------------------------------------------- %% This work may be distributed and/or modified under the %% conditions of the LaTeX Project Public License, either version 1.3 @@ -25,7 +25,7 @@ This is a generated file. -Copyright (C) 2012-2021 by Geoffrey M. Poore +Copyright (C) 2012-2026 by Geoffrey M. Poore -------------------------------------------------------------------------- This work may be distributed and/or modified under the conditions of the LaTeX Project Public License, either version 1.3 diff --git a/pythontex/pythontex.pdf b/pythontex/pythontex.pdf index f6cd05d..635a412 100644 Binary files a/pythontex/pythontex.pdf and b/pythontex/pythontex.pdf differ diff --git a/pythontex/pythontex.py b/pythontex/pythontex.py index 2fe6de9..21c2966 100644 --- a/pythontex/pythontex.py +++ b/pythontex/pythontex.py @@ -16,7 +16,7 @@ Licensed under the BSD 3-Clause License: -Copyright (c) 2012-2017, Geoffrey M. Poore +Copyright (c) 2012-2026, Geoffrey M. Poore All rights reserved. diff --git a/pythontex/pythontex.sty b/pythontex/pythontex.sty index 5fa953f..d2640c7 100644 --- a/pythontex/pythontex.sty +++ b/pythontex/pythontex.sty @@ -8,7 +8,7 @@ %% %% This is a generated file. %% -%% Copyright (C) 2012-2021 by Geoffrey M. Poore +%% Copyright (C) 2012-2026 by Geoffrey M. Poore %% -------------------------------------------------------------------------- %% This work may be distributed and/or modified under the %% conditions of the LaTeX Project Public License, either version 1.3 @@ -20,10 +20,10 @@ %% \NeedsTeXFormat{LaTeX2e}[1999/12/01] \ProvidesPackage{pythontex} - [2021/06/06 v0.18 execute and typeset Python code and other languages] + [2026/02/15 v0.19 execute and typeset Python code and other languages] \newcommand{\pytx@packagename}{PythonTeX} -\newcommand{\pytx@packageversion}{0.18} +\newcommand{\pytx@packageversion}{0.19} \RequirePackage{fvextra} \RequirePackage{etoolbox} \RequirePackage{xstring} diff --git a/pythontex/pythontex2.py b/pythontex/pythontex2.py index 661ef37..c83a81f 100644 --- a/pythontex/pythontex2.py +++ b/pythontex/pythontex2.py @@ -13,7 +13,7 @@ Licensed under the BSD 3-Clause License: -Copyright (c) 2012-2021, Geoffrey M. Poore +Copyright (c) 2012-2026, Geoffrey M. Poore All rights reserved. @@ -78,7 +78,7 @@ # Script parameters # Version -__version__ = '0.18' +__version__ = '0.19' @@ -483,7 +483,7 @@ def set_kv_pygments(k, v): print(' Unknown option "' + key + '"') temp_data['warnings'] += 1 - # Check for compatility between the .pytxcode and the script + # Check for compatibility between the .pytxcode and the script if 'version' not in settings or settings['version'] != data['version']: print('* PythonTeX error') print(' The version of the PythonTeX scripts does not match the last code') @@ -592,7 +592,7 @@ def get_old_data(data, old_data, temp_data): f = open(pythontex_data_file, 'rb') old = pickle.load(f) f.close() - # Check for compabilility + # Check for compatibility if 'vitals' in old and data['vitals'] == old['vitals']: temp_data['loaded_old_data'] = True old_data.update(old) @@ -2343,7 +2343,7 @@ def run_code(encoding, outputdir, workingdir, errors += 1 command_message = ''' * PythonTeX error - An error occurred but no error messages were identified. + An error occurred, but no error messages were identified. This may indicate a bad command or missing program. The following command was executed: "{0}"''' diff --git a/pythontex/pythontex3.py b/pythontex/pythontex3.py index 488c234..21bda37 100644 --- a/pythontex/pythontex3.py +++ b/pythontex/pythontex3.py @@ -13,7 +13,7 @@ Licensed under the BSD 3-Clause License: -Copyright (c) 2012-2021, Geoffrey M. Poore +Copyright (c) 2012-2026, Geoffrey M. Poore All rights reserved. @@ -78,7 +78,7 @@ # Script parameters # Version -__version__ = '0.18' +__version__ = '0.19' @@ -215,7 +215,8 @@ def process_argv(data, temp_data): if k == 'python': set_python_interpreter = True except: - print('Invalid --interpreter argument') + print('* PythonTeX error') + print(' Invalid --interpreter argument') return sys.exit(2) # If the Python interpreter wasn't set, then try to set an appropriate # default value, based on how PythonTeX was launched (pythontex.py, @@ -365,8 +366,9 @@ def load_code_get_settings(data, temp_data): try: pytxcode, pytxsettings = pytxcode.rsplit('=>PYTHONTEX:SETTINGS#', 1) except: - print('The .pytxcode file appears to have an outdated format or be invalid') - print('Run LaTeX to make sure the file is current') + print('* PythonTeX error') + print(' The .pytxcode file appears to have an outdated format or be invalid') + print(' Run LaTeX to make sure the file is current') return sys.exit(1) @@ -483,7 +485,7 @@ def set_kv_pygments(k, v): print(' Unknown option "' + key + '"') temp_data['warnings'] += 1 - # Check for compatility between the .pytxcode and the script + # Check for compatibility between the .pytxcode and the script if 'version' not in settings or settings['version'] != data['version']: print('* PythonTeX error') print(' The version of the PythonTeX scripts does not match the last code') @@ -554,7 +556,7 @@ def do_upgrade_compatibility(data, old_data, temp_data): It will continue to use the output directory for now. To keep your current settings long-term and avoid seeing this message in the future, add the following command to the preamble of your document, right after - the "\\usepackage{pythontex}": "\setpythontexworkingdir{}". + the "\\usepackage{pythontex}": "\\setpythontexworkingdir{}". If you wish to continue with the new settings instead, simply delete the file with extension .pkl in the output directory, and run PythonTeX. **** End PythonTeX upgrade message **** @@ -592,7 +594,7 @@ def get_old_data(data, old_data, temp_data): f = open(pythontex_data_file, 'rb') old = pickle.load(f) f.close() - # Check for compabilility + # Check for compatibility if 'vitals' in old and data['vitals'] == old['vitals']: temp_data['loaded_old_data'] = True old_data.update(old) @@ -1570,7 +1572,7 @@ def run_code(encoding, outputdir, workingdir, else: proc = subprocess.Popen(exec_cmd, stdout=out_file, stderr=subprocess.STDOUT) except OSError as e: - if e.errno == 2: + if platform.system() == 'Windows' and e.errno == 2: # Batch files won't be found when called without extension. They # would be found if `shell=True`, but then getting the right # exit code is tricky. So we perform some `cmd` trickery that @@ -1807,7 +1809,7 @@ def run_code(encoding, outputdir, workingdir, # Get the gobbleation. This is used to determine if # other lines containing the basename are a continuation, # or separate messages. - errgobble = match('(\s*)', line).groups()[0] + errgobble = match(r'(\s*)', line).groups()[0] if start_errgobble is None: start_errgobble = errgobble # Only issue a message and track down the line numer if @@ -2072,7 +2074,7 @@ def run_code(encoding, outputdir, workingdir, # Get the gobbleation. This is used to determine if # other lines containing the basename are a continuation, # or separate messages. - errgobble = match('(\s*)', line).groups()[0] + errgobble = match(r'(\s*)', line).groups()[0] if start_errgobble is None: start_errgobble = errgobble # Only issue a message and track down the line numer if @@ -2343,7 +2345,7 @@ def run_code(encoding, outputdir, workingdir, errors += 1 command_message = ''' * PythonTeX error - An error occurred but no error messages were identified. + An error occurred, but no error messages were identified. This may indicate a bad command or missing program. The following command was executed: "{0}"''' @@ -2408,17 +2410,17 @@ def do_pygments(encoding, outputdir, fvextfile, pygments_list, if c.is_cons: content = typeset_cache[c.key_run][c.instance] elif c.is_extfile: - if os.path.isfile(c.extfile): - f = open(c.extfile, encoding=encoding) - content = f.read() - f.close() + try: + with open(c.extfile, encoding=encoding) as f: + content = f.read() if hashdependencies: hasher = sha1() hasher.update(content.encode(encoding)) dependencies[c.key_typeset] = {c.extfile: (os.path.getmtime(c.extfile), hasher.hexdigest())} else: dependencies[c.key_typeset] = {c.extfile: (os.path.getmtime(c.extfile), '')} - else: + except FileNotFoundError: + errors += 1 content = None messages.append('* PythonTeX error') messages.append(' Could not find external file ' + c.extfile) @@ -2426,7 +2428,9 @@ def do_pygments(encoding, outputdir, fvextfile, pygments_list, else: content = c.code processed = highlight(content, lexer[c.family], formatter[c.family]) - if c.is_inline or content.count('\n') < fvextfile: + if content is None: + pass + elif c.is_inline or content.count('\n') < fvextfile: # Highlighted code brought in via macros needs SaveVerbatim if c.args_prettyprint: processed = sub(r'\\begin{Verbatim}\[(.+)\]', @@ -2471,6 +2475,13 @@ def python_console(jobname, encoding, outputdir, workingdir, fvextfile, Use Python's ``code`` module to typeset emulated Python interactive sessions, optionally highlighting with Pygments. ''' + try: + ps1 = sys.ps1 + ps2 = sys.ps2 + except AttributeError: + ps1 = '>>> ' + ps2 = '... ' + # Create what's needed for storing results key_run = cons_list[0].key_run files = [] @@ -2578,7 +2589,7 @@ def raw_input(self, prompt): self.write(old_line) except IndexError: raise EOFError - if line or prompt == sys.ps2: + if line or prompt == ps2: self.write('{0}{1}\n'.format(prompt, line)) else: self.write('\n') @@ -2636,8 +2647,8 @@ def write(self, data): exception = False console_content_lines = console_content.splitlines() for line in console_content_lines: - if (not line.startswith(sys.ps1) and - not line.startswith(sys.ps2) and + if (not line.startswith(ps1) and + not line.startswith(ps2) and line and not line.isspace()): exception = True break @@ -2658,8 +2669,8 @@ def write(self, data): exception = False console_content_lines = console_content.splitlines() for line in console_content_lines: - if (line and not line.startswith(sys.ps1) and - not line.startswith(sys.ps2) and + if (line and not line.startswith(ps1) and + not line.startswith(ps2) and not line.isspace()): exception = True break diff --git a/pythontex/pythontex_engines.py b/pythontex/pythontex_engines.py index 6b00dbb..e0d912b 100644 --- a/pythontex/pythontex_engines.py +++ b/pythontex/pythontex_engines.py @@ -1114,7 +1114,7 @@ def cleanup SubCodeEngine('julia', 'jl') -CodeEngine('juliacon', 'julia', '.jl', '{julia} --project=@. -e "using Weave; weave(\\"{File}.jl\\", \\"tex\\")"', '{body}\n', +CodeEngine('juliacon', 'julia', '.jl', '{julia} --project=@. -e "using Weave; weave(\\"{File}.jl\\", \\"texminted\\")"', '{body}\n', '#+ term=true\n{code}\n', '', '', 'ERROR:', 'WARNING:', ':{number}', True, created='{File}.tex') @@ -1748,3 +1748,4 @@ def cleanup ['error', 'Error'], ['warning', 'Warning'], ':{number}') +SubCodeEngine('javascript', 'js') diff --git a/pythontex/pythontex_utils.py b/pythontex/pythontex_utils.py index 2731e7a..3e09901 100644 --- a/pythontex/pythontex_utils.py +++ b/pythontex/pythontex_utils.py @@ -2,11 +2,11 @@ ''' PythonTeX utilities class for Python scripts. -The utilities class provides variables and methods for the individual -Python scripts created and executed by PythonTeX. An instance of the class +The utilities class provides variables and methods for the individual +Python scripts created and executed by PythonTeX. An instance of the class named "pytex" is automatically created in each individual script. -Copyright (c) 2012-2014, Geoffrey M. Poore +Copyright (c) 2012-2026, Geoffrey M. Poore All rights reserved. Licensed under the BSD 3-Clause License: http://www.opensource.org/licenses/BSD-3-Clause @@ -20,27 +20,27 @@ if sys.version_info.major == 2: import io -# Most imports are only needed for SymPy; these are brought in via -# "lazy import." Importing unicode_literals here shouldn't ever be necessary -# under Python 2. If unicode_literals is imported in the main script, then -# all strings in this script will be treated as bytes, and the main script -# will try to decode the strings from this script as necessary. The decoding -# shouldn't cause any problems, since all strings in this file may be decoded -# as valid ASCII. (The actual file is encoded in utf-8, but only characters +# Most imports are only needed for SymPy; these are brought in via +# "lazy import." Importing unicode_literals here shouldn't ever be necessary +# under Python 2. If unicode_literals is imported in the main script, then +# all strings in this script will be treated as bytes, and the main script +# will try to decode the strings from this script as necessary. The decoding +# shouldn't cause any problems, since all strings in this file may be decoded +# as valid ASCII. (The actual file is encoded in utf-8, but only characters # within the ASCII subset are actually used). class PythonTeXUtils(object): ''' A class of PythonTeX utilities. - + Provides variables for keeping track of TeX-side information, and methods for formatting and saving data. - - The following variables and methods will be created within instances + + The following variables and methods will be created within instances of the class during execution. - - String variables for keeping track of TeX information. Most are + + String variables for keeping track of TeX information. Most are actually needed; the rest are included for completeness. * family * session @@ -50,21 +50,21 @@ class PythonTeXUtils(object): * args * instance * line - + Future file handle for output that is saved via macros * macrofile - + Future formatter function that is used to format output * formatter ''' - + def __init__(self, fmtr='str'): ''' Initialize ''' self.set_formatter(fmtr) - - # We need a function that will process the raw `context` into a + + # We need a function that will process the raw `context` into a # dictionary with attributes _context_raw = None class _DictWithAttr(dict): @@ -88,14 +88,14 @@ def set_context(self, expr): v = v[6:] self.context[k] = v setattr(self.context, k, v) - + # A primary use for contextual information is to pass dimensions from the # TeX side to the Python side. To make that as convenient as possible, # we need some length conversion functions. # Conversion reference: http://tex.stackexchange.com/questions/41370/what-are-the-possible-dimensions-sizes-units-latex-understands def pt_to_in(self, expr): ''' - Convert points to inches. Accepts numbers, strings of digits, and + Convert points to inches. Accepts numbers, strings of digits, and strings of digits that end with `pt`. ''' try: @@ -120,81 +120,81 @@ def pt_to_bp(self, expr): Convert points to big (DTP or PostScript) points. ''' return self.pt_to_in(expr)*72 - - - # We need a context-aware interface to SymPy's latex printer. The - # appearance of typeset math should depend on where it appears in a - # document. (We will refer to the latex printer, rather than the LaTeX - # printer, because the two are separate. Compare sympy.printing.latex - # and sympy.galgebra.latex_ex.) + + + # We need a context-aware interface to SymPy's latex printer. The + # appearance of typeset math should depend on where it appears in a + # document. (We will refer to the latex printer, rather than the LaTeX + # printer, because the two are separate. Compare sympy.printing.latex + # and sympy.galgebra.latex_ex.) # - # Creating this interface takes some work. We don't want to import - # anything from SymPy unless it is actually used, to keep things clean and + # Creating this interface takes some work. We don't want to import + # anything from SymPy unless it is actually used, to keep things clean and # fast. - - # First we create a tuple containing all LaTeX math styles. These are + + # First we create a tuple containing all LaTeX math styles. These are # the contexts that SymPy's latex printer must adapt to. # The style order doesn't matter, but it corresponds to that of \mathchoice _sympy_latex_styles = ('display', 'text', 'script', 'scriptscript') - - # Create the public functions for the user, and private functions that - # they call. Two layers are necessary, because we need to be able to - # redefine the functions that do the actual work, once things are - # initialized. But we don't want to redefine the public functions, since - # that could cause problems if the user defines a new function to be one + + # Create the public functions for the user, and private functions that + # they call. Two layers are necessary, because we need to be able to + # redefine the functions that do the actual work, once things are + # initialized. But we don't want to redefine the public functions, since + # that could cause problems if the user defines a new function to be one # of the public functions--the user's function would not change when # the method was redefined. def _sympy_latex(self, expr, **settings): self._init_sympy_latex() return self._sympy_latex(expr, **settings) - + def sympy_latex(self, expr, **settings): return self._sympy_latex(expr, **settings) - + def _set_sympy_latex(self, style, **kwargs): self._init_sympy_latex() self._set_sympy_latex(style, **kwargs) - + def set_sympy_latex(self, style, **kwargs): self._set_sympy_latex(style, **kwargs) # Temporary compatibility with deprecated methods def init_sympy_latex(self): warnings.warn('Method init_sympy_latex() is deprecated; init is now automatic.') self._init_sympy_latex() - - # Next we create a method that initializes the actual context-aware + + # Next we create a method that initializes the actual context-aware # interface to SymPy's latex printer. def _init_sympy_latex(self): ''' Initialize a context-aware interface to SymPy's latex printer. - - This consists of creating the dictionary of settings and creating the - sympy_latex method that serves as an interface to SymPy's - LatexPrinter. This last step is actually performed by calling + + This consists of creating the dictionary of settings and creating the + sympy_latex method that serves as an interface to SymPy's + LatexPrinter. This last step is actually performed by calling self._make_sympy_latex(). ''' # Create dictionaries of settings for different contexts. - # - # Currently, the main goal is to use pmatrix (or an equivalent) - # in \displaystyle contexts, and smallmatrix in \textstyle, + # + # Currently, the main goal is to use pmatrix (or an equivalent) + # in \displaystyle contexts, and smallmatrix in \textstyle, # \scriptstyle (superscript or subscript), and \scriptscriptstyle - # (superscript or subscript of a superscript or subscript) - # contexts. Basically, we want matrix size to automatically - # scale based on context. It is expected that additional - # customization may prove useful as SymPy's LatexPrinter is + # (superscript or subscript of a superscript or subscript) + # contexts. Basically, we want matrix size to automatically + # scale based on context. It is expected that additional + # customization may prove useful as SymPy's LatexPrinter is # further developed. # - # The 'fold_frac_powers' option is probably the main other - # setting that might sometimes be nice to invoke in a + # The 'fold_frac_powers' option is probably the main other + # setting that might sometimes be nice to invoke in a # context-dependent manner. # - # In the default settings below, all matrices are set to use - # parentheses rather than square brackets. This is largely a - # matter of personal preference. The use of parentheses is based - # on the rationale that parentheses are less easily confused with - # the determinant and are easier to write by hand than are square + # In the default settings below, all matrices are set to use + # parentheses rather than square brackets. This is largely a + # matter of personal preference. The use of parentheses is based + # on the rationale that parentheses are less easily confused with + # the determinant and are easier to write by hand than are square # brackets. The settings for 'script' and 'scriptscript' are set - # to those of 'text', since all of these should in general + # to those of 'text', since all of these should in general # require a more compact representation of things. self._sympy_latex_settings = {'display': {'mat_str': 'pmatrix', 'mat_delim': None}, 'text': {'mat_str': 'smallmatrix', 'mat_delim': '('}, @@ -202,13 +202,13 @@ def _init_sympy_latex(self): 'scriptscript': {'mat_str': 'smallmatrix', 'mat_delim': '('} } # Now we create a function for updating the settings. # - # Note that EVERY time the settings are changed, we must call - # self._make_sympy_latex(). This is because the _sympy_latex() - # method is defined based on the settings, and every time the - # settings change, it may need to be redefined. It would be - # possible to define _sympy_latex() so that its definition remained - # constant, simply drawing on the settings. But most common - # combinations of settings allow more efficient versions of + # Note that EVERY time the settings are changed, we must call + # self._make_sympy_latex(). This is because the _sympy_latex() + # method is defined based on the settings, and every time the + # settings change, it may need to be redefined. It would be + # possible to define _sympy_latex() so that its definition remained + # constant, simply drawing on the settings. But most common + # combinations of settings allow more efficient versions of # _sympy_latex() to be defined. def _set_sympy_latex(style, **kwargs): if style in self._sympy_latex_styles: @@ -220,79 +220,79 @@ def _set_sympy_latex(style, **kwargs): warnings.warn('Unknown LaTeX math style ' + str(style)) self._make_sympy_latex() self._set_sympy_latex = _set_sympy_latex - - # Now that the dictionaries of settings have been created, and - # the function for modifying the settings is in place, we are ready + + # Now that the dictionaries of settings have been created, and + # the function for modifying the settings is in place, we are ready # to create the actual interface. self._make_sympy_latex() - + # Finally, create the actual interface to SymPy's LatexPrinter def _make_sympy_latex(self): ''' Create a context-aware interface to SymPy's LatexPrinter class. - - This is an interface to the LatexPrinter class, rather than - to the latex function, because the function is simply a - wrapper for accessing the class and because settings may be + + This is an interface to the LatexPrinter class, rather than + to the latex function, because the function is simply a + wrapper for accessing the class and because settings may be passed to the class more easily. - - Context dependence is accomplished via LaTeX's \mathchoice macro. + + Context dependence is accomplished via LaTeX's \\mathchoice macro. This macros takes four arguments: - \mathchoice{}{}{