summaryrefslogtreecommitdiff
path: root/Master/texmf-dist/doc/latex/sagetex
diff options
context:
space:
mode:
authorKarl Berry <karl@freefriends.org>2009-06-21 00:23:51 +0000
committerKarl Berry <karl@freefriends.org>2009-06-21 00:23:51 +0000
commitd5c69362ef92a985a1cecefe6bbbca5eb51e822a (patch)
treeb6af1179a24bd3d2401d9540741fc4c161d7664b /Master/texmf-dist/doc/latex/sagetex
parentf7498423bd232008266cf75bb0c1faa1465fbb1e (diff)
sage 2.2.1 (20jun09), omitting python scripts in bin
git-svn-id: svn://tug.org/texlive/trunk@13843 c570f23f-e606-0410-a88d-b1316a301751
Diffstat (limited to 'Master/texmf-dist/doc/latex/sagetex')
-rw-r--r--Master/texmf-dist/doc/latex/sagetex/README23
-rw-r--r--Master/texmf-dist/doc/latex/sagetex/example.pdfbin254523 -> 199517 bytes
-rw-r--r--Master/texmf-dist/doc/latex/sagetex/example.tex125
-rw-r--r--Master/texmf-dist/doc/latex/sagetex/extractsagecode.py84
-rw-r--r--Master/texmf-dist/doc/latex/sagetex/makestatic.py84
-rw-r--r--Master/texmf-dist/doc/latex/sagetex/remote-sagetex.py344
-rw-r--r--Master/texmf-dist/doc/latex/sagetex/sagetex.py222
-rw-r--r--Master/texmf-dist/doc/latex/sagetex/sagetexpackage.pdfbin241432 -> 356078 bytes
-rw-r--r--Master/texmf-dist/doc/latex/sagetex/sagetexparse.py151
9 files changed, 893 insertions, 140 deletions
diff --git a/Master/texmf-dist/doc/latex/sagetex/README b/Master/texmf-dist/doc/latex/sagetex/README
index 2e9d512d0eb..d677252b478 100644
--- a/Master/texmf-dist/doc/latex/sagetex/README
+++ b/Master/texmf-dist/doc/latex/sagetex/README
@@ -3,13 +3,21 @@ computations, and plots from the Sage mathematics software suite
(http://sagemath.org) into LaTeX documents.
====================================================================
-To use SageTeX, you need the files sagetex.sty and sagetex.py. If those
-haven't been extracted from the .dtx file, you'll need to do:
+The recommended way to acquire and install SageTeX is by installing the
+Sage spkg; visit http://sagemath.org/packages/optional/, find the
+current version number, and run "sage -i sagetex-[version]" in a
+terminal. Then you'll need to make the file sagetex.sty known to TeX;
+that file will be in SAGE_ROOT/local/share/texmf/tex/generic/sagetex,
+along with documentation and examples.
+
+If you can't or don't want to install SageTeX by using Sage, you can use
+this CTAN package. If sagetex.py and sagetex.sty haven't been extracted
+from the .dtx file, you'll need to do:
0. Run `latex sagetexpackage.ins'
If a PDF file of the documentation wasn't included with this
-distribution of SageTex, you will need to build the documentation
+distribution of SageTeX, you will need to build the documentation
yourself. To do that:
1. Run `latex sagetexpackage.dtx'
@@ -30,7 +38,12 @@ the documentation.)
To use the SageTeX package with your own documents, see the
"Installation" section of the documentation.
-This works builds on a lot of work by others; see the "Credits" section
+SageTeX now includes `remote-sagetex.py', a plain Python script that
+allows you to use a remote Sage server instead of a local Sage
+installation, so now you can use SageTeX on any computer with TeX and
+Python 2.6 installed.
+
+This work builds on a lot of work by others; see the "Credits" section
of the documentation for credits. The source code may be modified and
distributed under the terms of the GPL, v2 or later; the documentation
may be modified and distributed under a Creative Commons Attribution -
@@ -40,4 +53,4 @@ section of the documentation.
Please let me know if you find any bugs or have any ideas for
improvement!
-- Dan Drake <ddrake@member.ams.org>
+- Dan Drake <http://mathsci.kaist.ac.kr/~drake/>
diff --git a/Master/texmf-dist/doc/latex/sagetex/example.pdf b/Master/texmf-dist/doc/latex/sagetex/example.pdf
index 52b3ba0e34a..270018177db 100644
--- a/Master/texmf-dist/doc/latex/sagetex/example.pdf
+++ b/Master/texmf-dist/doc/latex/sagetex/example.pdf
Binary files differ
diff --git a/Master/texmf-dist/doc/latex/sagetex/example.tex b/Master/texmf-dist/doc/latex/sagetex/example.tex
index 0f84e3152e6..d9c67589fbc 100644
--- a/Master/texmf-dist/doc/latex/sagetex/example.tex
+++ b/Master/texmf-dist/doc/latex/sagetex/example.tex
@@ -1,32 +1,39 @@
% General example LaTeX file for including Sage calculations and plots
-% Build with: (pdf)latex example.tex; sage example.sage; pdflatex
-% example.tex Please read README and the documentation of the SageTeX
-% package for more information!
+% Build with:
+%
+% (pdf)latex example.tex; sage example.sage; pdflatex example.tex
+%
+% Please read README and the documentation of the SageTeX package for
+% more information!
\documentclass{article}
-\title{Examples of embedding Sage in \LaTeX}
-\author{}
-
+\title{Examples of embedding Sage in \LaTeX{} with \textsf{Sage\TeX}}
+\author{Dan Drake and others}
+\usepackage{amsmath}
\usepackage{sagetex}
-%
-% If you want sagetex to use Imagemagick's convert utility to make eps
-% files from png files when generating a dvi file, add the
-% "imagemagick" option above:
+%
+% If you want SageTeX to use Imagemagick's `convert' utility to make eps
+% files from png files when generating a dvi file, add the "imagemagick"
+% option above:
%
% \usepackage[imagemagick]{sagetex}
+\setlength{\sagetexindent}{10ex}
+
\begin{document}
\maketitle
\section{Inline Sage, code blocks}
This is an example $2+2=\sage{2+2}$. If you raise the current year mod
-$100$ ($\sage{mod(\the\year, 100)}$) to the power of the current day
-($\the\day$), you get $\sage{Integer(mod(\the\year, 100))^\the\day}$.
-Also, $\the\year$ modulo $42$ is $\sage{\the\year \percent 42}$.
+$100$ (which equals $\sage{mod(\the\year, 100)}$) to the power of the
+current day ($\the\day$), you get $\sage{Integer(mod(\the\year,
+100))^\the\day}$. Also, $\the\year$ modulo $42$ is $\sage{\the\year
+\percent 42}$.
Code block which uses a variable \texttt{s} to store the solutions:
\begin{sageblock}
+ 1+1
var('a,b,c')
eqn = [a+b*c==1, b-a*c==0, a+b==5]
s = solve(eqn, a,b,c)
@@ -46,8 +53,8 @@ E = EllipticCurve("37a")
\end{sageblock}
You can't do assignment inside \verb|\sage| macros, since Sage doesn't
know how to typeset the output of such a thing. So you have to use a
-code block. The elliptic curve $E$ given by $\sage{E}$
-has discriminant $\sage{E.discriminant()}$.
+code block. The elliptic curve $E$ given by $\sage{E}$ has discriminant
+$\sage{E.discriminant()}$.
You can do anything in a code block that you can do in Sage and/or
Python. Here we save an elliptic curve into a file.
@@ -60,8 +67,8 @@ except IOError:
E.save('E2')
\end{sageblock}
-The 9999th Fourier coefficient of $\sage{E}$ is
-$\sage{E.anlist(100000)[9999]}$.
+The 9999th Fourier coefficient of $\sage{E}$ is
+$\sage{E.anlist(100000)[9999]}$.
The following code block doesn't appear in the typeset file\dots
\begin{sagesilent}
@@ -72,9 +79,9 @@ but we can refer to whatever we did in that code block: $e=\sage{e}$.
\begin{sageblock}
var('x')
- f = log(sin(x)/x)
+ f(x) = log(sin(x)/x)
\end{sageblock}
-The Taylor Series of $f$ is: $\sage{ f.taylor(x, 0, 10) }$.
+The Taylor Series of $f$ begins: $\sage{ f.taylor(x, 0, 10) }$.
\section{Plotting}
@@ -83,8 +90,10 @@ Here's a plot of the elliptic curve $E$.
\sageplot{E.plot(-3,3)}
\begin{sagesilent}
+ # the var line is unecessary unless you've defined x to be something
+ # other than a symbolic variable
var('x')
- f=-x^3+3*x^2+7*x-4
+ f(x) = -x^3+3*x^2+7*x-4
\end{sagesilent}
You can use variables to hold plot objects and do stuff with them.
@@ -94,7 +103,7 @@ You can use variables to hold plot objects and do stuff with them.
Here's a small plot of $f$ from $-5$ to $5$, which I've centered:
-\centerline{\sageplot[scale=.2]{p}}
+\begin{center} \sageplot[scale=.2]{p} \end{center}
On second thought, use the default size of $3/4$ the \verb|\textwidth|
and don't use axes:
@@ -120,7 +129,7 @@ almost all situations. (Although see the section on 3D plotting.)
\sageplot[angle=45, width=.5\textwidth][png]{plot1}
If you use regular \verb|latex| to make a DVI file, you'll see a box,
-beause DVI files can't include PNG files. If you use \verb|pdflatex|
+because DVI files can't include PNG files. If you use \verb|pdflatex|
that will work. See the documentation for details.
When using \verb|\sageplot|, you can pass in just about anything that
@@ -160,12 +169,15 @@ And here's the picture:
\sageplot{matrixprogram}
+Reset \texttt{x} in Sage so that it's not a generator for the polynomial
+ring: \sage{var('x')}
+
\subsection{3D plotting}
3D plotting right now is problematic because there's no convenient way
to produce vector graphics. We can make PNGs, though, and since the
\verb|sageplot| command defaults to EPS and PDF, \emph{you must specify
-a valid format for 3D plotting}. Sage right now (version 2.10.3) can't
+a valid format for 3D plotting}. Sage right now (version 3.4.2) can't
produce EPS or PDF files from plot3d objects, so if you don't specify a
valid format, things will go badly. You can specify the
``\texttt{imagemagick}'' option, which will use the Imagemagick
@@ -182,4 +194,71 @@ Here's the famous Sage cube graph:
% passing an option to includegraphics
\sageplot[][png]{G.plot3d(engine='tachyon')}
+\section{Pausing Sage\TeX}
+\label{sec:pausing-sagetex}
+
+Sometimes you want to ``pause'' for a bit while writing your document if
+you have embedded a long calculation or just want to concentrate on the
+\LaTeX{} and ignore any Sage stuff. You can use the \verb|\sagetexpause|
+and \verb|\sagetexunpause| macros to do that.
+
+\sagetexpause
+
+A calculation: $\sage{factor(2^325 + 1)}$ and a code environment that
+simulates a time-consuming calculation. While paused, this will get
+skipped over.
+\begin{sageblock}
+ import time
+ time.sleep(15)
+\end{sageblock}
+
+Graphics are also skipped: \sageplot{plot(2*sin(x^2) + x^2, (x, 0, 5))}
+
+\sagetexunpause
+
+\section{Make Sage write your \LaTeX{} for you}
+
+With \textsf{Sage\TeX}, you can not only have Sage do your math for you,
+it can write parts of your \LaTeX{} document for you! For example, I
+hate writing \texttt{tabular} environments; there's too many fiddly
+little bits of punctuation and whatnot\ldots and what if you want to add
+a column? It's a pain---or rather, it \emph{was} a pain. Here's how to
+make Pascal's triangle. It requires the \texttt{amsmath} package because
+of what Sage does when producing a \LaTeX{} representation of a string.
+(It puts it inside a \verb|\text| macro.)
+
+\begin{sageblock}
+def pascals_triangle(n):
+ # start of the table
+ s = r"\begin{tabular}{cc|" + "r" * (n+1) + "}"
+ s += r" & & $k$: & \\"
+ # second row, with k values:
+ s += r" & "
+ for k in [0..n]:
+ s += "& %d " % k
+ s += r"\\"
+ # the n = 0 row:
+ s += r"\hline" + "\n" + r"$n$: & 0 & 1 & \\"
+ # now the rest of the rows
+ for r in [1..n]:
+ s += " & %d " % r
+ for k in [0..r]:
+ s += "& %d " % binomial(r, k)
+ s += r"\\"
+ # add the last line and return
+ s += r"\end{tabular}"
+ return s
+
+# how big should the table be?
+n = 8
+\end{sageblock}
+
+Okay, now here's the table. To change the size, edit \texttt{n} above.
+If you have several tables, you can use this to get them all the same
+size, while changing only one thing.
+
+\begin{center}
+ \sage{pascals_triangle(n)}
+\end{center}
+
\end{document}
diff --git a/Master/texmf-dist/doc/latex/sagetex/extractsagecode.py b/Master/texmf-dist/doc/latex/sagetex/extractsagecode.py
new file mode 100644
index 00000000000..62200d42d68
--- /dev/null
+++ b/Master/texmf-dist/doc/latex/sagetex/extractsagecode.py
@@ -0,0 +1,84 @@
+#!/usr/bin/env python
+##
+## This is file `extractsagecode.py',
+## generated with the docstrip utility.
+##
+## The original source files were:
+##
+## scripts.dtx (with options: `extractscript')
+##
+## This is a generated file. It is part of the SageTeX package.
+##
+## Copyright (C) 2009 by Dan Drake <ddrake@member.ams.org>
+##
+## This program is free software: you can redistribute it and/or modify it
+## under the terms of the GNU General Public License as published by the
+## Free Software Foundation, either version 2 of the License, or (at your
+## option) any later version.
+##
+## This program is distributed in the hope that it will be useful, but
+## WITHOUT ANY WARRANTY; without even the implied warranty of
+## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General
+## Public License for more details.
+##
+## You should have received a copy of the GNU General Public License along
+## with this program. If not, see <http://www.gnu.org/licenses/>.
+##
+import sys
+import time
+import getopt
+import os.path
+from sagetexparse import SageCodeExtractor
+
+def usage():
+ print("""Usage: %s [-h|--help] [-o|--overwrite] inputfile [outputfile]
+
+Extracts Sage code from `inputfile'.
+
+`inputfile' can include the .tex extension or not. If you provide
+`outputfile', the results will be written to a file of that name,
+otherwise the result will be printed to stdout.
+
+Specify `-o' or `--overwrite' to overwrite the file if it exists.
+
+See the SageTeX documentation for more details.""" % sys.argv[0])
+
+try:
+ opts, args = getopt.getopt(sys.argv[1:], 'ho', ['help', 'overwrite'])
+except getopt.GetoptError, err:
+ print str(err)
+ usage()
+ sys.exit(2)
+
+overwrite = False
+for o, a in opts:
+ if o in ('-h', '--help'):
+ usage()
+ sys.exit()
+ elif o in ('-o', '--overwrite'):
+ overwrite = True
+
+if len(args) == 0 or len(args) > 2:
+ print('Error: wrong number of arguments. Make sure to specify options first.\n')
+ usage()
+ sys.exit(2)
+
+if len(args) == 2 and (os.path.exists(args[1]) and not overwrite):
+ print('Error: %s exists and overwrite option not specified.' % args[1])
+ sys.exit(1)
+
+src, ext = os.path.splitext(args[0])
+sagecode = SageCodeExtractor(src)
+header = """\
+# This file contains Sage code extracted from %s%s.
+# Processed %s.
+
+""" % (src, ext, time.strftime('%a %d %b %Y %H:%M:%S', time.localtime()))
+
+if len(args) == 2:
+ dest = open(args[1], 'w')
+else:
+ dest = sys.stdout
+
+dest.write(header)
+dest.write(sagecode.result)
diff --git a/Master/texmf-dist/doc/latex/sagetex/makestatic.py b/Master/texmf-dist/doc/latex/sagetex/makestatic.py
new file mode 100644
index 00000000000..2121d9b78c5
--- /dev/null
+++ b/Master/texmf-dist/doc/latex/sagetex/makestatic.py
@@ -0,0 +1,84 @@
+#!/usr/bin/env python
+##
+## This is file `makestatic.py',
+## generated with the docstrip utility.
+##
+## The original source files were:
+##
+## scripts.dtx (with options: `staticscript')
+##
+## This is a generated file. It is part of the SageTeX package.
+##
+## Copyright (C) 2009 by Dan Drake <ddrake@member.ams.org>
+##
+## This program is free software: you can redistribute it and/or modify it
+## under the terms of the GNU General Public License as published by the
+## Free Software Foundation, either version 2 of the License, or (at your
+## option) any later version.
+##
+## This program is distributed in the hope that it will be useful, but
+## WITHOUT ANY WARRANTY; without even the implied warranty of
+## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General
+## Public License for more details.
+##
+## You should have received a copy of the GNU General Public License along
+## with this program. If not, see <http://www.gnu.org/licenses/>.
+##
+import sys
+import time
+import getopt
+import os.path
+from sagetexparse import DeSageTex
+
+def usage():
+ print("""Usage: %s [-h|--help] [-o|--overwrite] inputfile [outputfile]
+
+Removes SageTeX macros from `inputfile' and replaces them with the
+Sage-computed results to make a "static" file. You'll need to have run
+Sage on `inputfile' already.
+
+`inputfile' can include the .tex extension or not. If you provide
+`outputfile', the results will be written to a file of that name.
+Specify `-o' or `--overwrite' to overwrite the file if it exists.
+
+See the SageTeX documentation for more details.""" % sys.argv[0])
+
+try:
+ opts, args = getopt.getopt(sys.argv[1:], 'ho', ['help', 'overwrite'])
+except getopt.GetoptError, err:
+ print str(err)
+ usage()
+ sys.exit(2)
+
+overwrite = False
+for o, a in opts:
+ if o in ('-h', '--help'):
+ usage()
+ sys.exit()
+ elif o in ('-o', '--overwrite'):
+ overwrite = True
+
+if len(args) == 0 or len(args) > 2:
+ print('Error: wrong number of arguments. Make sure to specify options first.\n')
+ usage()
+ sys.exit(2)
+
+if len(args) == 2 and (os.path.exists(args[1]) and not overwrite):
+ print('Error: %s exists and overwrite option not specified.' % args[1])
+ sys.exit(1)
+
+src, ext = os.path.splitext(args[0])
+desagetexed = DeSageTex(src)
+header = """\
+## SageTeX commands have been automatically removed from this file and
+## replaced with plain LaTeX. Processed %s.
+
+""" % time.strftime('%a %d %b %Y %H:%M:%S', time.localtime())
+
+if len(args) == 2:
+ dest = open(args[1], 'w')
+else:
+ dest = sys.stdout
+
+dest.write(header)
+dest.write(desagetexed.result)
diff --git a/Master/texmf-dist/doc/latex/sagetex/remote-sagetex.py b/Master/texmf-dist/doc/latex/sagetex/remote-sagetex.py
new file mode 100644
index 00000000000..e8946bd1814
--- /dev/null
+++ b/Master/texmf-dist/doc/latex/sagetex/remote-sagetex.py
@@ -0,0 +1,344 @@
+#!/usr/bin/env python
+##
+## This is file `remote-sagetex.py',
+## generated with the docstrip utility.
+##
+## The original source files were:
+##
+## remote-sagetex.dtx (with options: `remotesagetex')
+##
+## This is a generated file. It is part of the SageTeX package.
+##
+## Copyright (C) 2009 by Dan Drake <ddrake@member.ams.org>
+##
+## This program is free software: you can redistribute it and/or modify it
+## under the terms of the GNU General Public License as published by the
+## Free Software Foundation, either version 2 of the License, or (at your
+## option) any later version.
+##
+## This program is distributed in the hope that it will be useful, but
+## WITHOUT ANY WARRANTY; without even the implied warranty of
+## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General
+## Public License for more details.
+##
+## You should have received a copy of the GNU General Public License along
+## with this program. If not, see <http://www.gnu.org/licenses/>.
+##
+from __future__ import print_function
+import json
+import sys
+import time
+import re
+import urllib
+import hashlib
+import os
+import os.path
+import shutil
+import getopt
+from contextlib import closing
+
+#########################################################################
+# You can provide a filename here and the script will read your login #
+# information from that file. The format must be: #
+# #
+# server = 'http://foo.com:8000' #
+# username = 'my_name' #
+# password = 's33krit' #
+# #
+# You can omit one or more of those lines, use " quotes, and put hash #
+# marks at the beginning of a line for comments. Command-line args #
+# take precedence over information from the file. #
+#########################################################################
+login_info_file = None # e.g. '/home/foo/Private/sagetex-login.txt'
+
+usage = """Process a SageTeX-generated .sage file using a remote Sage server.
+
+Usage: {0} [options] inputfile.sage
+
+Options:
+
+ -h, --help: print this message
+ -s, --server: the Sage server to contact
+ -u, --username: username on the server
+ -p, --password: your password
+ -f, --file: get login information from a file
+
+If the server does not begin with the four characters `http', then
+`https://' will be prepended to the server name.
+
+You can hard-code the filename from which to read login information into
+the remote-sagetex script. Command-line arguments take precedence over
+the contents of that file. See the SageTeX documentation for formatting
+details.
+
+If any of the server, username, and password are omitted, you will be
+asked to provide them.
+
+See the SageTeX documentation for more details on usage and limitations
+of remote-sagetex.""".format(sys.argv[0])
+
+server, username, password = (None,) * 3
+
+try:
+ opts, args = getopt.getopt(sys.argv[1:], 'hs:u:p:f:',
+ ['help', 'server=', 'user=', 'password=', 'file='])
+except getopt.GetoptError as err:
+ print(str(err), usage, sep='\n\n')
+ sys.exit(2)
+
+for o, a in opts:
+ if o in ('-h', '--help'):
+ print(usage)
+ sys.exit()
+ elif o in ('-s', '--server'):
+ server = a
+ elif o in ('-u', '--user'):
+ username = a
+ elif o in ('-p', '--password'):
+ password = a
+ elif o in ('-f', '--file'):
+ login_info_file = a
+
+if len(args) != 1:
+ print('Error: must specify exactly one file. Please specify options first.',
+ usage, sep='\n\n')
+ sys.exit(2)
+
+jobname = os.path.splitext(args[0])[0]
+traceback_str = 'Exception in SageTeX session {0}:'.format(time.time())
+def parsedotsage(fn):
+ with open(fn, 'r') as f:
+ inline = re.compile(r" _st_.inline\((?P<num>\d+), (?P<code>.*)\)")
+ plot = re.compile(r" _st_.plot\((?P<num>\d+), (?P<code>.*)\)")
+ goboom = re.compile(r" _st_.goboom\((?P<num>\d+)\)")
+ pausemsg = re.compile(r"print.'(?P<msg>SageTeX (un)?paused.*)'")
+ blockbegin = re.compile(r"_st_.blockbegin\(\)")
+ ignore = re.compile(r"(try:)|(except):")
+ in_comment = False
+ in_block = False
+ cmds = []
+ for line in f.readlines():
+ if line.startswith('"""'):
+ in_comment = not in_comment
+ elif not in_comment:
+ m = pausemsg.match(line)
+ if m:
+ cmds.append({'type': 'pause',
+ 'msg': m.group('msg')})
+ m = inline.match(line)
+ if m:
+ cmds.append({'type': 'inline',
+ 'num': m.group('num'),
+ 'code': m.group('code')})
+ m = plot.match(line)
+ if m:
+ cmds.append({'type': 'plot',
+ 'num': m.group('num'),
+ 'code': m.group('code')})
+ m = goboom.match(line)
+ if m:
+ cmds[-1]['goboom'] = m.group('num')
+ if in_block:
+ in_block = False
+ if in_block and not ignore.match(line):
+ cmds[-1]['code'] += line
+ if blockbegin.match(line):
+ cmds.append({'type': 'block',
+ 'code': ''})
+ in_block = True
+ return cmds
+debug = False
+class RemoteSage:
+ def __init__(self, server, user, password):
+ self._srv = server.rstrip('/')
+ sep = '___S_A_G_E___'
+ self._response = re.compile('(?P<header>.*)' + sep +
+ '\n*(?P<output>.*)', re.DOTALL)
+ self._404 = re.compile('404 Not Found')
+ self._session = self._get_url('login',
+ urllib.urlencode({'username': user,
+ 'password':
+ password}))['session']
+ self._codewrap = """try:
+{{0}}
+except:
+ print('{0}')
+ traceback.print_exc()""".format(traceback_str)
+ self.do_block("""
+ import traceback
+ def __st_plot__(counter, _p_, format='notprovided', **kwargs):
+ if format == 'notprovided':
+ formats = ['eps', 'pdf']
+ else:
+ formats = [format]
+ for fmt in formats:
+ plotfilename = 'plot-%s.%s' % (counter, fmt)
+ _p_.save(filename=plotfilename, **kwargs)""")
+
+ def _encode(self, d):
+ return 'session={0}&'.format(self._session) + urllib.urlencode(d)
+
+ def _get_url(self, action, u):
+ with closing(urllib.urlopen(self._srv + '/simple/' + action +
+ '?' + u)) as h:
+ data = self._response.match(h.read())
+ result = json.loads(data.group('header'))
+ result['output'] = data.group('output').rstrip()
+ return result
+
+ def _get_file(self, fn, cell, ofn=None):
+ with closing(urllib.urlopen(self._srv + '/simple/' + 'file' + '?' +
+ self._encode({'cell': cell, 'file': fn}))) as h:
+ myfn = ofn if ofn else fn
+ data = h.read()
+ if not self._404.search(data):
+ with open(myfn, 'w') as f:
+ f.write(data)
+ else:
+ print('Remote server reported {0} could not be found:'.format(
+ fn))
+ print(data)
+ def _do_cell(self, code):
+ realcode = self._codewrap.format(code)
+ result = self._get_url('compute', self._encode({'code': realcode}))
+ if result['status'] == 'computing':
+ cell = result['cell_id']
+ while result['status'] == 'computing':
+ sys.stdout.write('working...')
+ sys.stdout.flush()
+ time.sleep(10)
+ result = self._get_url('status', self._encode({'cell': cell}))
+ if debug:
+ print('cell: <<<', realcode, '>>>', 'result: <<<',
+ result['output'], '>>>', sep='\n')
+ return result
+
+ def do_inline(self, code):
+ return self._do_cell(' print(latex({0}))'.format(code))
+
+ def do_block(self, code):
+ result = self._do_cell(code)
+ for fn in result['files']:
+ self._get_file(fn, result['cell_id'])
+ return result
+
+ def do_plot(self, num, code, plotdir):
+ result = self._do_cell(' __st_plot__({0}, {1})'.format(num, code))
+ for fn in result['files']:
+ self._get_file(fn, result['cell_id'], os.path.join(plotdir, fn))
+ return result
+ def close(self):
+ sys.stdout.write('Logging out of {0}...'.format(server))
+ sys.stdout.flush()
+ self._get_url('logout', self._encode({}))
+ print('done')
+def do_plot_setup(plotdir):
+ printc('initializing plots directory...')
+ if os.path.isdir(plotdir):
+ shutil.rmtree(plotdir)
+ os.mkdir(plotdir)
+ return True
+
+did_plot_setup = False
+plotdir = 'sage-plots-for-' + jobname + '.tex'
+
+def labelline(n, s):
+ return r'\newlabel{@sageinline' + str(n) + '}{{' + s + '}{}{}{}{}}\n'
+
+def printc(s):
+ print(s, end='')
+ sys.stdout.flush()
+
+error = re.compile("(^" + traceback_str + ")|(^Syntax Error:)", re.MULTILINE)
+
+def check_for_error(string, line):
+ if error.search(string):
+ print("""
+**** Error in Sage code on line {0} of {1}.tex!
+{2}
+**** Running Sage on {1}.sage failed! Fix {1}.tex and try again.""".format(
+ line, jobname, string))
+ sys.exit(1)
+print('Processing Sage code for {0}.tex using remote Sage server.'.format(
+ jobname))
+
+if login_info_file:
+ with open(login_info_file, 'r') as f:
+ print('Reading login information from {0}.'.format(login_info_file))
+ get_val = lambda x: x.split('=')[1].strip().strip('\'"')
+ for line in f:
+ print(line)
+ if not line.startswith('#'):
+ if line.startswith('server') and not server:
+ server = get_val(line)
+ if line.startswith('username') and not username:
+ username = get_val(line)
+ if line.startswith('password') and not password:
+ password = get_val(line)
+
+if not server:
+ server = raw_input('Enter server: ')
+
+if not server.startswith('http'):
+ server = 'https://' + server
+
+if not username:
+ username = raw_input('Enter username: ')
+
+if not password:
+ from getpass import getpass
+ password = getpass('Please enter password for user {0} on {1}: '.format(
+ username, server))
+
+printc('Parsing {0}.sage...'.format(jobname))
+cmds = parsedotsage(jobname + '.sage')
+print('done.')
+
+sout = '% This file was *autogenerated* from the file {0}.sage.\n'.format(
+ os.path.splitext(jobname)[0])
+
+printc('Logging into {0} and starting session...'.format(server))
+with closing(RemoteSage(server, username, password)) as sage:
+ print('done.')
+ for cmd in cmds:
+ if cmd['type'] == 'inline':
+ printc('Inline formula {0}...'.format(cmd['num']))
+ result = sage.do_inline(cmd['code'])
+ check_for_error(result['output'], cmd['goboom'])
+ sout += labelline(cmd['num'], result['output'])
+ print('done.')
+ if cmd['type'] == 'block':
+ printc('Code block begin...')
+ result = sage.do_block(cmd['code'])
+ check_for_error(result['output'], cmd['goboom'])
+ print('end.')
+ if cmd['type'] == 'plot':
+ printc('Plot {0}...'.format(cmd['num']))
+ if not did_plot_setup:
+ did_plot_setup = do_plot_setup(plotdir)
+ result = sage.do_plot(cmd['num'], cmd['code'], plotdir)
+ check_for_error(result['output'], cmd['goboom'])
+ print('done.')
+ if cmd['type'] == 'pause':
+ print(cmd['msg'])
+ if int(time.time()) % 2280 == 0:
+ printc('Unscheduled offworld activation; closing iris...')
+ time.sleep(1)
+ print('end.')
+
+with open(jobname + '.sage', 'r') as sagef:
+ h = hashlib.md5()
+ for line in sagef:
+ if (not line.startswith(' _st_.goboom') and
+ not line.startswith("print 'SageT")):
+ h.update(line)
+ sout += """%{0}% md5sum of corresponding .sage file
+{1} (minus "goboom" and pause/unpause lines)
+""".format(h.hexdigest(), '%')
+
+printc('Writing .sout file...')
+with open(jobname + '.sout', 'w') as soutf:
+ soutf.write(sout)
+ print('done.')
+print('Sage processing complete. Run LaTeX on {0}.tex again.'.format(jobname))
+
diff --git a/Master/texmf-dist/doc/latex/sagetex/sagetex.py b/Master/texmf-dist/doc/latex/sagetex/sagetex.py
index 2686b4348f5..576847894f7 100644
--- a/Master/texmf-dist/doc/latex/sagetex/sagetex.py
+++ b/Master/texmf-dist/doc/latex/sagetex/sagetex.py
@@ -1,38 +1,39 @@
-"""
-%%
-%% This is file `sagetex.py',
-%% generated with the docstrip utility.
-%%
-%% The original source files were:
-%%
-%% sagetexpackage.dtx (with options: `python')
-%%
-%% This is a generated file.
-%%
-%% Copyright (C) 2008 by Dan Drake <ddrake@member.ams.org>
-%%
-%% This program is free software: you can redistribute it and/or modify it
-%% under the terms of the GNU General Public License as published by the
-%% Free Software Foundation, either version 2 of the License, or (at your
-%% option) any later version.
-%%
-%% This program is distributed in the hope that it will be useful, but
-%% WITHOUT ANY WARRANTY; without even the implied warranty of
-%% MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
-%% General Public License for more details.
-%%
-%% You should have received a copy of the GNU General Public License along
-%% with this program. If not, see <http://www.gnu.org/licenses/>
-%%
+##
+## This is file `sagetex.py',
+## generated with the docstrip utility.
+##
+## The original source files were:
+##
+## sagetexpackage.dtx (with options: `python')
+## py-and-sty.dtx (with options: `python')
+##
+## This is a generated file. It is part of the SageTeX package.
+##
+## Copyright (C) 2009 by Dan Drake <ddrake@member.ams.org>
+##
+## This program is free software: you can redistribute it and/or modify it
+## under the terms of the GNU General Public License as published by the
+## Free Software Foundation, either version 2 of the License, or (at your
+## option) any later version.
+##
+## This program is distributed in the hope that it will be useful, but
+## WITHOUT ANY WARRANTY; without even the implied warranty of
+## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General
+## Public License for more details.
+##
+## You should have received a copy of the GNU General Public License along
+## with this program. If not, see <http://www.gnu.org/licenses/>.
+##
+__version__ = """
+ [2009/06/17 v2.2.1 embedding Sage into LaTeX documents]
"""
import sys
if __name__ == "__main__":
print("""This file is part of the SageTeX package.
It is not meant to be called directly.
-This file will be used by Sage scripts generated from a LaTeX document
-using the sagetex package. Keep it somewhere where Sage and Python can
-find it and it will automatically be imported.""")
+This file will be automatically used by Sage scripts generated from a
+LaTeX document using the SageTeX package.""")
sys.exit()
from sage.misc.latex import latex
import os
@@ -41,86 +42,83 @@ import hashlib
import traceback
import subprocess
import shutil
-initplot_done = False
-dirname = None
-filename = ""
-def progress(t,linebreak=True):
- if linebreak:
- print(t)
- else:
- sys.stdout.write(t)
-def openout(f):
- global filename
- filename = f
- global _file_
- _file_ = open(f + '.sout.tmp', 'w')
- s = '% This file was *autogenerated* from the file ' + \
- os.path.splitext(filename)[0] + '.sage.\n'
- _file_.write(s)
- progress('Processing Sage code for %s.tex...' % filename)
-def initplot(f):
- global initplot_done
- if not initplot_done:
- progress('Initializing plots directory')
- global dirname
- dirname = 'sage-plots-for-' + f + '.tex'
- if os.path.isdir(dirname):
- shutil.rmtree(dirname)
- os.mkdir(dirname)
- initplot_done = True
-def inline(counter, s):
- progress('Inline formula %s' % counter)
- _file_.write('\\newlabel{@sagelabel' + str(counter) + '}{{' + \
- latex(s) + '}{}{}{}{}}\n')
-def blockbegin():
- progress('Code block begin...', False)
-def blockend():
- progress('end')
-def plot(counter, p, format='notprovided', epsmagick=False, **kwargs):
- global dirname
- progress('Plot %s' % counter)
- if format == 'notprovided':
- formats = ['eps', 'pdf']
- else:
- formats = [format]
- for fmt in formats:
- plotfilename = os.path.join(dirname, 'plot-%s.%s' % (counter, fmt))
- #print(' plotting %s with args %s' % (plotfilename, kwargs))
- p.save(filename=plotfilename, **kwargs)
- if format != 'notprovided' and epsmagick is True:
- print('Calling Imagemagick to convert plot-%s.%s to EPS' % \
- (counter, format))
- toeps(counter, format)
-def toeps(counter, ext):
- global dirname
- subprocess.check_call(['convert',\
- '%s/plot-%s.%s' % (dirname, counter, ext), \
- '%s/plot-%s.eps' % (dirname, counter)])
-def goboom(line):
- global filename
- print('\n**** Error in Sage code on line %s of %s.tex! Traceback\
- follows.' % (line, filename))
- traceback.print_exc()
- print('\n**** Running Sage on %s.sage failed! Fix %s.tex and try\
- again.' % (filename, filename))
- os.remove(filename + '.sout.tmp')
- sys.exit(1)
-def endofdoc():
- global filename
- sagef = open(filename + '.sage', 'r')
- m = hashlib.md5()
- for line in sagef:
- if line[0:15] != ' sagetex.goboom':
- m.update(line)
- s = '%' + m.hexdigest() + '% md5sum of .sage file (minus "goboom" \
-lines) that produced this\n'
- _file_.write(s)
- _file_.close()
- os.rename(filename + '.sout.tmp', filename + '.sout')
- progress('Sage processing complete. Run LaTeX on %s.tex again.' %\
- filename)
-"""
-\endinput
-%%
-%% End of file `sagetex.py'.
-"""
+class SageTeXProcessor():
+ def __init__(self, jobname):
+ self.progress('Processing Sage code for %s.tex...' % jobname)
+ self.didinitplot = False
+ self.useimagemagick = False
+ self.useepstopdf = False
+ self.plotdir = 'sage-plots-for-' + jobname + '.tex'
+ self.filename = jobname
+ self.souttmp = open(self.filename + '.sout.tmp', 'w')
+ s = '% This file was *autogenerated* from the file ' + \
+ os.path.splitext(jobname)[0] + '.sage.\n'
+ self.souttmp.write(s)
+ def progress(self, t,linebreak=True):
+ if linebreak:
+ print(t)
+ else:
+ sys.stdout.write(t)
+ sys.stdout.flush()
+ def initplot(self):
+ self.progress('Initializing plots directory')
+ if os.path.isdir(self.plotdir):
+ shutil.rmtree(self.plotdir)
+ os.mkdir(self.plotdir)
+ self.didinitplot = True
+ def inline(self, counter, s):
+ self.progress('Inline formula %s' % counter)
+ self.souttmp.write('\\newlabel{@sageinline' + str(counter) + '}{{' + \
+ latex(s).rstrip() + '}{}{}{}{}}\n')
+ def blockbegin(self):
+ self.progress('Code block begin...', False)
+ def blockend(self):
+ self.progress('end')
+ def plot(self, counter, _p_, format='notprovided', **kwargs):
+ if not self.didinitplot:
+ self.initplot()
+ self.progress('Plot %s' % counter)
+ if format == 'notprovided':
+ formats = ['eps', 'pdf']
+ else:
+ formats = [format]
+ for fmt in formats:
+ if fmt == 'pdf' and self.useepstopdf:
+ epsfile = os.path.join(self.plotdir, 'plot-%s.eps' % counter)
+ self.progress('Calling epstopdf to convert plot-%s.eps to PDF' % \
+ counter)
+ subprocess.check_call(['epstopdf', epsfile])
+ continue
+ plotfilename = os.path.join(self.plotdir, 'plot-%s.%s' % (counter, fmt))
+ _p_.save(filename=plotfilename, **kwargs)
+ if format != 'notprovided' and self.useimagemagick:
+ self.progress('Calling Imagemagick to convert plot-%s.%s to EPS' % \
+ (counter, format))
+ self.toeps(counter, format)
+ def toeps(self, counter, ext):
+ subprocess.check_call(['convert',\
+ '%s/plot-%s.%s' % (self.plotdir, counter, ext), \
+ '%s/plot-%s.eps' % (self.plotdir, counter)])
+ def goboom(self, line):
+ print('\n**** Error in Sage code on line %s of %s.tex! Traceback\
+ follows.' % (line, self.filename))
+ traceback.print_exc()
+ print('\n**** Running Sage on %s.sage failed! Fix %s.tex and try\
+ again.' % ((self.filename,) * 2))
+ self.souttmp.close()
+ os.remove(self.filename + '.sout.tmp')
+ sys.exit(int(1))
+ def endofdoc(self):
+ sagef = open(self.filename + '.sage', 'r')
+ m = hashlib.md5()
+ for line in sagef:
+ if line[0:12] != " _st_.goboom" and line[0:12] != "print 'SageT":
+ m.update(line)
+ s = '%' + m.hexdigest() + '% md5sum of corresponding .sage file\
+ (minus "goboom" and pause/unpause lines)\n'
+ self.souttmp.write(s)
+ self.souttmp.close()
+ os.rename(self.filename + '.sout.tmp', self.filename + '.sout')
+ self.progress('Sage processing complete. Run LaTeX on %s.tex again.' %\
+ self.filename)
+
diff --git a/Master/texmf-dist/doc/latex/sagetex/sagetexpackage.pdf b/Master/texmf-dist/doc/latex/sagetex/sagetexpackage.pdf
index 43a32df1580..2f9fc546ecd 100644
--- a/Master/texmf-dist/doc/latex/sagetex/sagetexpackage.pdf
+++ b/Master/texmf-dist/doc/latex/sagetex/sagetexpackage.pdf
Binary files differ
diff --git a/Master/texmf-dist/doc/latex/sagetex/sagetexparse.py b/Master/texmf-dist/doc/latex/sagetex/sagetexparse.py
new file mode 100644
index 00000000000..c1927348032
--- /dev/null
+++ b/Master/texmf-dist/doc/latex/sagetex/sagetexparse.py
@@ -0,0 +1,151 @@
+##
+## This is file `sagetexparse.py',
+## generated with the docstrip utility.
+##
+## The original source files were:
+##
+## scripts.dtx (with options: `parsermod')
+##
+## This is a generated file. It is part of the SageTeX package.
+##
+## Copyright (C) 2009 by Dan Drake <ddrake@member.ams.org>
+##
+## This program is free software: you can redistribute it and/or modify it
+## under the terms of the GNU General Public License as published by the
+## Free Software Foundation, either version 2 of the License, or (at your
+## option) any later version.
+##
+## This program is distributed in the hope that it will be useful, but
+## WITHOUT ANY WARRANTY; without even the implied warranty of
+## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General
+## Public License for more details.
+##
+## You should have received a copy of the GNU General Public License along
+## with this program. If not, see <http://www.gnu.org/licenses/>.
+##
+import sys
+from pyparsing import *
+def skipToMatching(opener, closer):
+ nest = nestedExpr(opener, closer)
+ nest.setParseAction(lambda l, s, t: l[s:getTokensEndLoc()])
+ return nest
+
+curlybrackets = skipToMatching('{', '}')
+squarebrackets = skipToMatching('[', ']')
+sagemacroparser = r'\sage' + curlybrackets('code')
+sageplotparser = (r'\sageplot'
+ + Optional(squarebrackets)('opts')
+ + Optional(squarebrackets)('format')
+ + curlybrackets('code'))
+sagetexpause = Literal(r'\sagetexpause')
+sagetexunpause = Literal(r'\sagetexunpause')
+class SoutParser():
+ def __init__(self, fn):
+ self.label = []
+ parselabel = (r'\newlabel{@sageinline'
+ + Word(nums)('num')
+ + '}{'
+ + curlybrackets('result')
+ + '{}{}{}{}}')
+ parselabel.ignore('%' + restOfLine)
+ parselabel.setParseAction(self.newlabel)
+ try:
+ OneOrMore(parselabel).parseFile(fn)
+ except IOError:
+ print 'Error accessing %s; exiting. Does your .sout file exist?' % fn
+ sys.exit(1)
+ def newlabel(self, s, l, t):
+ self.label.append(t.result[1:-1])
+class DeSageTex():
+ def __init__(self, fn):
+ self.sagen = 0
+ self.plotn = 0
+ self.fn = fn
+ self.sout = SoutParser(fn + '.sout')
+ smacro = sagemacroparser
+ smacro.setParseAction(self.sage)
+ usepackage = (r'\usepackage'
+ + Optional(squarebrackets)
+ + '{sagetex}')
+ usepackage.setParseAction(replaceWith(r"""% "\usepackage{sagetex}" line was here:
+\RequirePackage{verbatim}
+\RequirePackage{graphicx}
+\newcommand{\sagetexpause}{\relax}
+\newcommand{\sagetexunpause}{\relax}"""))
+ splot = sageplotparser
+ splot.setParseAction(self.plot)
+ beginorend = oneOf('begin end')
+ blockorverb = 'sage' + oneOf('block verbatim')
+ blockorverb.setParseAction(replaceWith('verbatim'))
+ senv = '\\' + beginorend + '{' + blockorverb + '}'
+ silent = Literal('sagesilent')
+ silent.setParseAction(replaceWith('comment'))
+ ssilent = '\\' + beginorend + '{' + silent + '}'
+ stexindent = Suppress(r'\setlength{\sagetexindent}' + curlybrackets)
+ doit = smacro | senv | ssilent | usepackage | splot | stexindent
+ doit.ignore('%' + restOfLine)
+ doit.ignore(r'\begin{verbatim}' + SkipTo(r'\end{verbatim}'))
+ doit.ignore(r'\begin{comment}' + SkipTo(r'\end{comment}'))
+ doit.ignore(r'\sagetexpause' + SkipTo(r'\sagetexunpause'))
+ str = ''.join(open(fn + '.tex', 'r').readlines())
+ self.result = doit.transformString(str)
+ def sage(self, s, l, t):
+ self.sagen += 1
+ return self.sout.label[self.sagen - 1]
+ def plot(self, s, l, t):
+ self.plotn += 1
+ if len(t.opts) == 0:
+ opts = r'[width=.75\textwidth]'
+ else:
+ opts = t.opts[0]
+ return (r'\includegraphics%s{sage-plots-for-%s.tex/plot-%s}' %
+ (opts, self.fn, self.plotn - 1))
+class SageCodeExtractor():
+ def __init__(self, fn):
+ smacro = sagemacroparser
+ smacro.setParseAction(self.macroout)
+
+ splot = sageplotparser
+ splot.setParseAction(self.plotout)
+ env_names = oneOf('sageblock sageverbatim sagesilent')
+ senv = r'\begin{' + env_names('env') + '}' + SkipTo(
+ r'\end{' + matchPreviousExpr(env_names) + '}')('code')
+ senv.leaveWhitespace()
+ senv.setParseAction(self.envout)
+
+ spause = sagetexpause
+ spause.setParseAction(self.pause)
+
+ sunpause = sagetexunpause
+ sunpause.setParseAction(self.unpause)
+
+ doit = smacro | splot | senv | spause | sunpause
+
+ str = ''.join(open(fn + '.tex', 'r').readlines())
+ self.result = ''
+
+ doit.transformString(str)
+
+ def macroout(self, s, l, t):
+ self.result += '# \\sage{} from line %s\n' % lineno(l, s)
+ self.result += t.code[1:-1] + '\n\n'
+
+ def plotout(self, s, l, t):
+ self.result += '# \\sageplot{} from line %s:\n' % lineno(l, s)
+ if t.format is not '':
+ self.result += '# format: %s' % t.format[0][1:-1] + '\n'
+ self.result += t.code[1:-1] + '\n\n'
+
+ def envout(self, s, l, t):
+ self.result += '# %s environment from line %s:' % (t.env,
+ lineno(l, s))
+ self.result += t.code[0] + '\n'
+
+ def pause(self, s, l, t):
+ self.result += ('# SageTeX (probably) paused on input line %s.\n\n' %
+ (lineno(l, s)))
+
+ def unpause(self, s, l, t):
+ self.result += ('# SageTeX (probably) unpaused on input line %s.\n\n' %
+ (lineno(l, s)))
+