def runLatex(code, res, charheightpx, latexTemplate): def ensureWorkingDirectory(path): """Ensure this directory exists and is writable.""" if not os.access(path,os.F_OK): os.mkdir(path) if not os.access(path,os.W_OK): os.system('chmod u+rwx %s' % path) texfileName = fileNameFor(code, charheightpx, '.tex') dvifileName = fileNameFor(code, charheightpx, '.dvi') psfileName = fileNameFor(code, charheightpx, '.ps') cmdLine = '%s %s' %(latexpath, texfileName) ensureWorkingDirectory(workingDir) file = open(os.path.join(workingDir, texfileName), 'w') file.write(latexTemplate %(code,)) file.close() err, stdout, stderr = runCommand(cmdLine) if err: out = stderr + '\n' + stdout err = re.search('!.*\?', out, re.MULTILINE+re.DOTALL) if err: out = err.group(0) # FIXME translate latex line numbers to source line numbers raise LatexSyntaxError(out)
def renderReduce(reduceCodeList): def securityCheck(code): # newCode = re.compile(r'^[ \t]*\)sys([^\n]*)',reConsts).sub(r'-- not allowed: )sys\1\n)sys',code) newCode = code return newCode n = 0 unifiedCode = '' for reduceCode in reduceCodeList: newReduceCode = securityCheck(reduceCode) n = n + 1 if re.match(r'^\s*\)abbrev',newReduceCode): # Starts like a package so compile as library code reduceFileName = os.path.join(workingDir,fileNameFor(newReduceCode, 25, '.%3.3d.red'%n)) unifiedCode = unifiedCode + 'compile "%s";\n'%reduceFileName else: # otherwise it is just an input file reduceFileName = os.path.join(workingDir,fileNameFor(newReduceCode, 25, '.%3.3d.rin'%n)) unifiedCode = unifiedCode + 'in "%s";\n'%reduceFileName reduceFile = open(reduceFileName, 'w') reduceFile.write(newReduceCode) reduceFile.close() if unifiedCode: try: latexCode=runReduce(unifiedCode,reduceTemplate) latexCodeList = re.compile(outputPattern, reConsts).findall(latexCode) return (latexCodeList,'') except ReduceSyntaxError, data: errors = str(data) log(errors, 'ReduceSyntaxError') return ([],escape(errors))
def runLatex(code, charheightpx, latexTemplate): texfileName = fileNameFor(code, charheightpx, '.tex') dvifileName = fileNameFor(code, charheightpx, '.dvi') psfileName = fileNameFor(code, charheightpx, '.ps') #cmdLine = 'pdflatex --interaction errorstopmode %s' %(texfileName) cmdLine = '/usr/bin/latex %s' %(texfileName) file = open(os.path.join(workingDir, texfileName), 'w') file.write(latexTemplate %(code,)) file.close() err, stdout, stderr = runCommand(cmdLine) # Process Graphviz .dot files again = 0 for f in os.listdir(workingDir): if re.search(r'\.dot$',f): dotfileName = os.path.join(workingDir,f) err, stdout, stderr = runCommand( 'dot -Tps -o %s %s'%(re.sub(r'dot$','ps',dotfileName), dotfileName)) os.remove(dotfileName) again = 1 # repeat LaTeX command if necessary if again==1: err, stdout, stderr = runCommand(cmdLine) if err: out = stderr + '\n' + stdout err = re.search('!.*\?', out, re.MULTILINE+re.DOTALL) if err: out = err.group(0) raise LatexSyntaxError(out) else: err, stdout, stderr = runCommand('/usr/local/teTeX/bin/i686-pc-linux-gnu/dvips -o %s %s'%(psfileName, dvifileName))
def runMaxima(maximaCode, maximaTemplate): maximaFileName = os.path.join(workingDir,fileNameFor(maximaCode, 25, '.mbat')) cmdLine = '/usr/bin/maxima -p /zope1/Products/ZWiki/plugins/mathaction/mathaction-maxima-5.9.3.lisp < %s' %(maximaFileName) file = open(maximaFileName, 'w') file.write(maximaTemplate%maximaCode) file.close() err, stdout, stderr = runCommand(cmdLine) if err: out = 'Error: ' + cmdLine + '\n' + stderr + '\n' + stdout raise MaximaSyntaxError(out) else: # don't want the final prompt return re.sub(r'<prompt>.*</prompt></maxima>$',r'',stdout)
def getImageFor(latexCode, charheightpx): preamble, postamble = '', '' width, height = '', '' imageFile = fileNameFor(latexCode, charheightpx, '.png') imageUrl = imagesPath + imageFile width, height = getPngSize(os.path.join(workingDir, imageFile)) #src = html_quote(re.match(latexRemoveDelim, latexCode, re.MULTILINE|re.DOTALL). group(2)) src = 'LatexWiki Image' return '%s<img alt="%s" class="equation" src="%s" width="%s" height="%s"/>%s' %(preamble, src, imageUrl, width, height, postamble)
def runReduce(reduceCode, reduceTemplate): reduceFileName = os.path.join(workingDir,fileNameFor(reduceCode, 25, '.run')) cmdLine = 'export PATH=/usr/local/bin:$PATH;reduce < %s' %(reduceFileName) file = open(reduceFileName, 'w') file.write(reduceTemplate%reduceCode) file.close() err, stdout, stderr = runCommand(cmdLine) if err: out = 'Error: ' + cmdLine + '\n' + stderr + '\n' + stdout raise ReduceSyntaxError(out) else: # Clean up the startup prompts newcode = re.compile(r'^(?:.*?1: ){3}', reConsts).sub('',stdout) return newcode
def getImageFor(latexCode, charheightpx): preamble, postamble = '', '' width, height = '', '' imageFile = fileNameFor(latexCode, charheightpx, '.png') imageUrl = imagesPath + imageFile width, height = getPngSize(os.path.join(workingDir, imageFile)) src = html_quote(re.match(latexRemoveDelim, latexCode, re.MULTILINE|re.DOTALL).group(2)) src = re.sub(r'\n\n+', '\n', src) # FIXME collapse blank lines or they will # be interpreted as stx paragraphs -- this is an stx bug since they are # inside a tag. return '%s<img alt="%s" class="equation" src="%s" width="%s" height="%s"/>%s' %(preamble, src, imageUrl, width, height, postamble)
def runAxiom(axiomCode, axiomTemplate): axiomFileName = os.path.join(workingDir,fileNameFor(axiomCode, 25, '.axm')) # problem: http://wiki.axiom-developer.org/145PipingCommandsToSmanDoesNotWork #cmdLine = '/usr/bin/axiom < %s' %(axiomFileName) #cmdLine = 'export AXIOM=/usr/local/axiom/mnt/linux; export PATH=$AXIOM/bin:$PATH; export ALDORROOT=/usr/local/aldor/linux/1.0.2; export PATH=$ALDORROOT/bin:$PATH; export HOME=/var/lib/plone2/main; AXIOMsys < %s' %(axiomFileName) # enough for now on debian cmdLine = 'export AXIOM=/usr/lib/axiom-20050901; $AXIOM/bin/AXIOMsys < %s' %(axiomFileName) file = open(axiomFileName, 'w') file.write(axiomTemplate%axiomCode) file.close() err, stdout, stderr = runCommand(cmdLine) if err: out = 'Error: ' + cmdLine + '\n' + stderr + '\n' + stdout raise AxiomSyntaxError(out) else: # Clean up the startup prompts newcode = re.compile(r'^.*?(?:\(1\) -> ){5}', reConsts).sub('',stdout) # Temporary fix for Axiom bug \spadcommand{radix(10**90,32)} newcode = re.compile(r'#\\', reConsts).sub('',newcode) return newcode
def renderMaxima(maximaCodeList): def securityCheck(code): return code n = 0 unifiedCode = '' for maximaCode in maximaCodeList: newMaximaCode = securityCheck(maximaCode) n = n + 1 maximaFileName = os.path.join(workingDir,fileNameFor(newMaximaCode, 25, '.%3.3d.max'%n)) unifiedCode = unifiedCode + 'batch("%s");\n'%maximaFileName maximaFile = open(maximaFileName, 'w') maximaFile.write(newMaximaCode) maximaFile.close() if unifiedCode: try: latexCode=runMaxima(unifiedCode,maximaTemplate) latexCodeList = re.split(outputSplit,latexCode)[1:] return (latexCodeList,'') except MaximaSyntaxError, data: errors = str(data) log(errors, 'MaximaSyntaxError') return ([],escape(errors))
def renderAxiom(axiomCodeList): def securityCheck(code): newCode = re.compile(r'^[ \t]*\)sys([^\n]*)',reConsts).sub(r'-- not allowed: )sys\1\n)sys',code) # newCode = re.compile(r'^[ \t]*\)lisp([^\n]*)',reConsts).sub(r'-- not allowed: )lisp\1\n)sys',newCode) newCode = re.compile(r'^[ \t]*\)fin([^\n]*)',reConsts).sub(r'-- not allowed: )fin\1\n)sys',newCode) newCode = re.compile(r'^[ \t]*\)spool([^\n]*)',reConsts).sub(r'-- not allowed: )spool\1\n)sys',newCode) return newCode n = 0 unifiedCode = '' for axiomCode in axiomCodeList: newAxiomCode = securityCheck(axiomCode) n = n + 1 if re.match(r'^\s*\)abb',newAxiomCode): # Starts like spad so compile as library code axiomFileName = os.path.join(workingDir,fileNameFor(newAxiomCode, 25, '.%3.3d.spad'%n)) unifiedCode = unifiedCode + ')set message prompt none\n' unifiedCode = unifiedCode + ')sys cat %s\n'%axiomFileName unifiedCode = unifiedCode + ')compile %s\n'%axiomFileName unifiedCode = unifiedCode + ')set message prompt step\n' elif re.match(r'^\\begin *{spad}\s*.*?\s*\\end *{spad}',newAxiomCode, reConsts): # spad so compile as library code m = re.match(r'^\\begin *{spad}\s*(.*?)\s*\\end *{spad}', newAxiomCode,reConsts) newAxiomCode = m.group(1) # just the spad code axiomFileName = os.path.join(workingDir,fileNameFor(newAxiomCode, 25, '%3.3d.spad'%n)) unifiedCode = unifiedCode + ')set message prompt none\n' unifiedCode = unifiedCode + ')sys echo "<spad>";cat %s;echo "</spad>"\n'%axiomFileName unifiedCode = unifiedCode + ')compile %s\n'%axiomFileName unifiedCode = unifiedCode + ')set message prompt step\n' elif re.match(r'^\\begin *{aldor}\s*.*?\s*\\end *{aldor}',newAxiomCode, reConsts): # aldor so compile as library code m = re.match(r'^\\begin *{aldor} *(?:\[(.*?)\])?\s*(.*?)\s*\\end *{aldor}', newAxiomCode,reConsts) if m.group(1): # optional file name axiomFileName = os.path.join(workingDir,m.group(1)+'.as') else : axiomFileName = os.path.join(workingDir,fileNameFor(newAxiomCode, 25, '%3.3d.as'%n)) newAxiomCode = m.group(2) # just the aldor code unifiedCode = unifiedCode + ')set message prompt none\n' unifiedCode = unifiedCode + ')sys echo "<aldor>";cat %s;echo "</aldor>"\n'%axiomFileName unifiedCode = unifiedCode + ')compile %s\n'%axiomFileName unifiedCode = unifiedCode + ')set message prompt step\n' elif re.match(r'^\\begin *{boot}\s*.*?\s*\\end *{boot}',newAxiomCode, reConsts): m = re.match(r'^\\begin *{boot}\s*(.*?)\s*\\end *{boot}', newAxiomCode,reConsts) newAxiomCode = m.group(1) # just the boot code fileName = fileNameFor(newAxiomCode, 25, '%3.3d'%n) axiomFileName = os.path.join(workingDir,fileName+'.boot') axiomFileName2 = fileName+'.clisp' unifiedCode = unifiedCode + ')set message prompt none\n' unifiedCode = unifiedCode + ')sys echo "<boot>";cat %s;echo "</boot>"\n'%axiomFileName unifiedCode = unifiedCode + ')lisp (boottran::boottocl "%s")\n'%axiomFileName unifiedCode = unifiedCode + ')lisp (load (compile-file (truename (concat (si:getenv "AXIOM") "/../../int/interp/%s"))))\n'%axiomFileName2 unifiedCode = unifiedCode + ')set message prompt step\n' elif re.match(r'^\\begin *{lisp}\s*.*?\s*\\end *{lisp}',newAxiomCode, reConsts): m = re.match(r'^\\begin *{lisp}\s*(.*?)\s*\\end *{lisp}', newAxiomCode,reConsts) newAxiomCode = m.group(1) # just the lisp code axiomFileName = os.path.join(workingDir,fileNameFor(newAxiomCode, 25, '%3.3d.lisp'%n)) unifiedCode = unifiedCode + ')set message prompt none\n' unifiedCode = unifiedCode + ')sys echo "<lisp>";cat %s;echo "</lisp>"\n'%axiomFileName unifiedCode = unifiedCode + ')lisp (load (compile-file "%s"))\n'%axiomFileName unifiedCode = unifiedCode + ')set message prompt step\n' else: # otherwise it is just an input file axiomFileName = os.path.join(workingDir,fileNameFor(newAxiomCode, 25, '.%3.3d.input'%n)) unifiedCode = unifiedCode + ')read %s\n'%axiomFileName axiomFile = open(axiomFileName, 'w') axiomFile.write(newAxiomCode) axiomFile.close() if unifiedCode: try: latexCode=runAxiom(unifiedCode,axiomTemplate) latexCodeList = re.compile(outputPattern, reConsts).findall(latexCode) return (latexCodeList,'') except AxiomSyntaxError, data: errors = str(data) log(errors, 'AxiomSyntaxError') return ([],escape(errors))
def imageDoesNotExist(code, charheightpx): return not os.path.exists(os.path.join(workingDir, fileNameFor(code, charheightpx, imageExtension)))
res = charheightpx*ptperinch/charsizept*resfudge errors = "" codeToRender = filter(lambda x: imageDoesNotExist(x, charheightpx), unique(latexCodeList)) if (not codeToRender): return unifiedCode = re.sub(r'^(\$|\\\()', r'\1|~ ', codeToRender[0]) for code in codeToRender[1:len(codeToRender)]: unifiedCode = unifiedCode + '\n\\newpage\n' + re.sub(r'^(\$|\\\()', r'\1|~ ', code) try: runLatex(unifiedCode, res, charheightpx, latexTemplate) except LatexSyntaxError, data: errors = str(data) log(errors, 'LatexSyntaxError') # FIXME translate latex line number to source line number return escape(errors) fName = fileNameFor(unifiedCode, charheightpx) dviPng(fName, res) for code, i in map(None, codeToRender, range(0, len(codeToRender))): newFileName = fileNameFor(code, charheightpx, imageExtension) imname = '%s-%03d.png'%(fName,i+1) if re.match(r'^(?:\$|\\\()', code): # FIXME make dvipng do the alpha properly im = Image.open(os.path.join(workingDir, imname)) try: im = align(im, charheightpx, alignfudge) # returns an RGBA image except (AlignError, ValueError), data: raise LatexRenderError(str(data) + '\nThe code was:\n' + \ code+ '\nin the file %s'%(os.path.join(workingDir, imname))) if im.mode != 'RGBA': alpha = ImageChops.invert(im.convert('L')) im = im.putalpha(alpha) im.save(os.path.join(workingDir, newFileName), "PNG")