diff options
author | Karl Berry <karl@freefriends.org> | 2009-06-21 00:23:51 +0000 |
---|---|---|
committer | Karl Berry <karl@freefriends.org> | 2009-06-21 00:23:51 +0000 |
commit | d5c69362ef92a985a1cecefe6bbbca5eb51e822a (patch) | |
tree | b6af1179a24bd3d2401d9540741fc4c161d7664b /Master/texmf-dist/doc | |
parent | f7498423bd232008266cf75bb0c1faa1465fbb1e (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')
-rw-r--r-- | Master/texmf-dist/doc/latex/sagetex/README | 23 | ||||
-rw-r--r-- | Master/texmf-dist/doc/latex/sagetex/example.pdf | bin | 254523 -> 199517 bytes | |||
-rw-r--r-- | Master/texmf-dist/doc/latex/sagetex/example.tex | 125 | ||||
-rw-r--r-- | Master/texmf-dist/doc/latex/sagetex/extractsagecode.py | 84 | ||||
-rw-r--r-- | Master/texmf-dist/doc/latex/sagetex/makestatic.py | 84 | ||||
-rw-r--r-- | Master/texmf-dist/doc/latex/sagetex/remote-sagetex.py | 344 | ||||
-rw-r--r-- | Master/texmf-dist/doc/latex/sagetex/sagetex.py | 222 | ||||
-rw-r--r-- | Master/texmf-dist/doc/latex/sagetex/sagetexpackage.pdf | bin | 241432 -> 356078 bytes | |||
-rw-r--r-- | Master/texmf-dist/doc/latex/sagetex/sagetexparse.py | 151 |
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 Binary files differindex 52b3ba0e34a..270018177db 100644 --- a/Master/texmf-dist/doc/latex/sagetex/example.pdf +++ b/Master/texmf-dist/doc/latex/sagetex/example.pdf 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 Binary files differindex 43a32df1580..2f9fc546ecd 100644 --- a/Master/texmf-dist/doc/latex/sagetex/sagetexpackage.pdf +++ b/Master/texmf-dist/doc/latex/sagetex/sagetexpackage.pdf 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))) + |