diff -r e86755df35da -r 87e77aa18610 project/kiwipycon/proceedings/booklet/mk_scipy_paper.py --- a/project/kiwipycon/proceedings/booklet/mk_scipy_paper.py Thu Apr 01 11:59:35 2010 +0530 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,463 +0,0 @@ -# encoding: utf-8 - -import os -import re -import sys -import shutil -import codecs -from glob import glob - -from docutils import core as docCore - -conf_name = 'SciPy2009' - -current_dir = '/media/python/workspace/kiwipycon/project/kiwipycon/proceedings/booklet' - -outdir = current_dir + os.sep + 'output' - -sourcedir = current_dir + os.sep + 'sources' -try: - os.mkdir(outdir) -except: - pass - -outfilename = outdir + os.sep + 'booklet.tex' - -############################################################################## -# Routines for supervised execution -############################################################################## - -from threading import Thread -import os -import signal -from subprocess import Popen -from time import sleep - -def delayed_kill(pid, delay=10): - sleep(delay) - try: - os.kill(pid, signal.SIGTERM) - except OSError: - pass - -def supervise_popen(command, timeout=10): - process = Popen(command) - Thread(target=delayed_kill, args=(process.pid,timeout),).start() - - process.wait() - - - -############################################################################## -# LaTeX generation functions. -############################################################################## - -def protect(string): - r''' Protects all the "\" in a string by adding a second one before - - >>> protect(r'\foo \*') - '\\\\foo \\\\*' - ''' - return re.sub(r"\\", r"\\\\", string) - - -def safe_unlink(filename): - """ Remove a file from the disk only if it exists, if not r=fails silently - """ - if os.path.exists(filename): - os.unlink(filename) - -rxcountpages = re.compile(r"$\s*/Type\s*/Page[/\s]", re.MULTILINE|re.DOTALL) - -def count_pages(filename): - data = file(filename,"rb").read() - return len(rxcountpages.findall(data)) - - -def tex2pdf(filename, remove_tex=True, timeout=10, runs=2): - """ Compiles a TeX file with pdfLaTeX (or LaTeX, if or dvi ps requested) - and cleans up the mess afterwards - """ - current_dir = os.getcwd() - os.chdir(os.path.dirname(filename)) - print >> sys.stderr, "Compiling document to pdf" - basename = os.path.splitext(os.path.basename(filename))[0] - if os.path.exists(basename + '.pdf'): - os.unlink(basename + '.pdf') - for _ in range(runs): - supervise_popen(("pdflatex", "--interaction", "scrollmode", - os.path.basename(filename)), timeout=timeout) - error_file = None - errors = file(os.path.abspath(basename + '.log')).readlines()[-1] - if not os.path.exists(basename + '.pdf') or \ - "Fatal error" in errors: - error_file = os.path.abspath(basename + '.log') - if remove_tex: - safe_unlink(filename+".tex") - safe_unlink(filename+".log") - safe_unlink(filename+".aux") - safe_unlink(filename+".out") - os.chdir(current_dir) - return error_file - - -def rst2latex(rst_string, no_preamble=True, allow_latex=True): - """ Calls docutils' engine to convert a rst string to a LaTeX file. - """ - overrides = {'output_encoding': 'utf-8', 'initial_header_level': 3, - 'no_doc_title': True, 'use_latex_citations': True, - 'use_latex_footnotes':True} - if allow_latex: - rst_string = u'''.. role:: math(raw) - :format: latex - \n\n''' + rst_string - tex_string = docCore.publish_string( - source=rst_string, - writer_name='latex2e', - settings_overrides=overrides) - if no_preamble: - extract_document = \ - re.compile(r'.*\\begin\{document\}(.*)\\end\{document\}', - re.DOTALL) - matches = extract_document.match(tex_string) - tex_string = matches.groups()[0] - return tex_string - - -def get_latex_preamble(): - """ Retrieve the required preamble from docutils. - """ - full_document = rst2latex('\n', no_preamble=False) - preamble = re.split(r'\\begin\{document\}', full_document)[0] - ## Remove the documentclass. - preamble = r""" - %s - \makeatletter - \newcommand{\class@name}{gael} - \makeatother - \usepackage{ltxgrid} - %s - """ % ( - preamble.split('\n')[0], - '\n'.join(preamble.split('\n')[1:]), - ) - return preamble - - -############################################################################## -# Functions to generate part of the booklet -############################################################################## -def addfile(outfile, texfilename): - """ Includes the content of a tex file in our outfile. - """ - include = codecs.open(texfilename, 'r') - data = include.readlines() - outfile.write(ur'\thispagestyle{empty}' + u'\n') - outfile.writelines(data) - - -def preamble(outfile): - outfile.write(r''' - %s - \usepackage{abstracts} - \usepackage{ltxgrid} - \usepackage{amssymb,latexsym,amsmath,amsthm} - \usepackage{longtable} - \geometry{left=.8cm, textwidth=17cm, bindingoffset=0.6cm, - textheight=25.3cm, twoside} - \usepackage{hyperref} - \hypersetup{pdftitle={Proceedings of the 8th Annual Python in Science Conference}} - \begin{document} - - '''.encode('utf-8') % get_latex_preamble()) - - # XXX SciPy08 should not be hard coded, but to run out of the webapp - -def hack_include_graphics(latex_text): - """ Replaces all the \includegraphics call with call that impose the - width to be 0.9\linewidth. - """ - latex_text = re.sub(r'\\setlength\{\\rightmargin\}\{\\leftmargin\}', - r'\\setlength{\\leftmargin}{4ex}\\setlength{\\rightmargin}{0ex}', - latex_text) - latex_text = re.sub(r'\\begin\{quote\}\n\\begin\{itemize\}', - r'\\begin{itemize}', - latex_text) - latex_text = re.sub(r'\\end\{itemize\}\n\\end\{quote\}', - r'\\end{itemize}', - latex_text) - latex_text = re.sub(r'\\includegraphics(\[.*\])?\{', - r'\includegraphics[width=\linewidth]{', - latex_text) - latex_text = re.sub(r'\\href\{([^}]+)\}\{http://(([^{}]|(\{[^}]*\}))+)\}', - r'''% -% Break penalties to have URL break easily: -\mathchardef\UrlBreakPenalty=0 -\mathchardef\UrlBigBreakPenalty=0 -%\hskip 0pt plus 2em -\href{\1}{\url{\1}}''', - latex_text) - latex_text = re.sub(r'\\href\{([^}]+)\}\{https://(([^{}]|(\{[^}]*\}))+)\}', - r'''% -% Break penalties to have URL break easily: -\mathchardef\UrlBreakPenalty=0 -\mathchardef\UrlBigBreakPenalty=0 -\linebreak -\href{\1}{\url{\1}}''', - latex_text) - - return latex_text - - -def render_abstract(outfile, abstract, start_page=None): - """ Writes the LaTeX string corresponding to one abstract. - """ - if start_page is not None: - outfile.write(r""" -\setcounter{page}{%i} -""" % start_page) - else: - if hasattr(abstract, 'start_page'): - start_page = abstract.start_page - else: - start_page = 1 - if not abstract.authors: - author_list = abstract.owners - else: - author_list = abstract.authors - authors = [] - print dir(author_list[0]) - for author in author_list: - # If the author has no surname, he is not an author - if author.surname: - if author.email_address: - email = r'(\email{%s})' % author.email_address - else: - email = '' - authors.append(ur'''\otherauthors{ - %s %s - %s -- - \address{%s, %s} - }''' % (author.first_names, author.surname, - email, - author.institution, - author.city)) - if authors: - authors = u'\n'.join(authors) - authors += r'\addauthorstoc{%s}' % ', '.join( - '%s. %s' % (author.first_names[0], author.surname) - for author in author_list - ) - author_cite_list = ['%s. %s' % (a.first_names[0], a.surname) - for a in author_list] - if len(author_cite_list) > 4: - author_cite_list = author_cite_list[:3] - author_cite_list.append('et al.') - citation = ', '.join(author_cite_list) + \ - 'in Proc. SciPy 2009, G. Varoquaux, S. van der Walt, J. Millman (Eds), ' - copyright = '\\copyright 2009, %s' % ( ', '.join(author_cite_list)) - else: - authors = '' - citation = 'Citation' - copyright = 'Copyright' - if hasattr(abstract, 'num_pages'): - citation += 'pp. %i--%i' % (start_page, start_page + - abstract.num_pages) - else: - citation += 'p. %i'% start_page - if hasattr(abstract, 'number'): - abstract.url = 'http://conference.scipy.org/proceedings/%s/paper_%i' \ - % (conf_name, abstract.number) - url = r'\url{%s}' % abstract.url - else: - url = '' - paper_text = abstract.paper_text - if paper_text == '': - paper_text = abstract.summary - # XXX: It doesn't seem to be right to be doing this, but I get a - # nasty UnicodeDecodeError on some rare abstracts, elsewhere. - paper_text = codecs.utf_8_decode(hack_include_graphics( - rst2latex(paper_text)))[0] - paper_abstract = abstract.paper_abstract - if paper_abstract is None: - paper_abstract = '' - if not paper_abstract=='': - paper_abstract = ur'\begin{abstract}%s\end{abstract}' % \ - paper_abstract#.encode('utf-8') - abstract_dict = { - 'text': paper_text.encode('utf-8'), - 'abstract': paper_abstract.encode('utf-8'), - 'authors': authors.encode('utf-8'), - 'title': abstract.title.encode('utf-8'), - 'citation': citation.encode('utf-8'), - 'copyright': copyright.encode('utf-8'), - 'url': url.encode('utf-8'), - } - outfile.write(codecs.utf_8_decode(ur''' -\phantomsection -\hypertarget{chapter}{} -\vspace*{-2em} - -\resetheadings{%(title)s}{%(citation)s}{%(url)s}{%(copyright)s} -\title{%(title)s} - -\begin{minipage}{\linewidth} -%(authors)s -\end{minipage} - -\noindent\rule{\linewidth}{0.2ex} -\vspace*{-0.5ex} -\twocolumngrid -%(abstract)s - -\sloppy - -%(text)s - -\fussy -\onecolumngrid -\smallskip -\vfill -\filbreak -\clearpage - -'''.encode('utf-8') % abstract_dict )[0]) - -def copy_files(dest=outfilename): - """ Copy the required file from the source dir to the output dir. - """ - dirname = os.path.dirname(dest) - if dirname == '': - dirname = '.' - for filename in glob(sourcedir+os.sep+'*'): - destfile = os.path.abspath(dirname + os.sep + - os.path.basename(filename)) - shutil.copy2(filename, destfile) - - -def mk_abstract_preview(abstract, outfilename, attach_dir, start_page=None): - """ Generate a preview for an given paper. - """ - copy_files() - outdir = os.path.dirname(os.path.abspath(outfilename)) - for f in glob(os.path.join(attach_dir, '*')): - if os.path.isdir(f) and not os.path.exists(f): - os.makedirs(f) - else: - if not outdir == os.path.dirname(os.path.abspath(f)): - shutil.copy2(f, outdir) - for f in glob(os.path.join(sourcedir, '*')): - if os.path.isdir(f): - os.makedirs(f) - else: - destfile = os.path.abspath(os.path.join(outdir, f)) - shutil.copy2(f, outdir) - - outbasename = os.path.splitext(outfilename)[0] - outfilename = outbasename + '.tex' - - outfile = codecs.open(outfilename, 'w', 'utf-8') - preamble(outfile) - render_abstract(outfile, abstract, start_page=start_page) - outfile.write(ur'\end{document}' + u'\n') - outfile.close() - - tex2pdf(outbasename, remove_tex=False) - abstract.num_pages = count_pages(outbasename + '.pdf') - - # Generate the tex file again, now that we know the length. - outfile = codecs.open(outfilename, 'w', 'utf-8') - preamble(outfile) - render_abstract(outfile, abstract, start_page=start_page) - outfile.write(ur'\end{document}' + u'\n') - outfile.close() - - return tex2pdf(os.path.splitext(outfilename)[0], remove_tex=False) - - -############################################################################## -# Code for using outside of the webapp. -############################################################################## - -def mk_zipfile(): - """ Generates a zipfile with the required files to build an - abstract. - """ - from zipfile import ZipFile - zipfilename = os.path.join(os.path.dirname(__file__), - 'mk_scipy_paper.zip') - z = ZipFile(zipfilename, 'w') - for filename in glob(os.path.join(sourcedir, '*')): - if not os.path.isdir(filename): - z.write(filename, arcname='source/' + os.path.basename(filename)) - z.write(__file__, arcname='mk_scipy_paper.py') - return zipfilename - -class Bunch(dict): - def __init__(self, **kwargs): - dict.__init__(self, **kwargs) - self.__dict__ = self - - def __reprt(self): - return repr(self.__dict__) - -author_like = Bunch( - first_names='XX', - surname='XXX', - email_address='xxx@XXX', - institution='XXX', - address='XXX', - country='XXX' -) - - -abstract_like = Bunch( - paper_abstract='An abstract', - authors=[author_like, ], - title='', - ) - -if __name__ == '__main__': - from optparse import OptionParser - parser = OptionParser() - parser.add_option("-o", "--output", dest="outfilename", - default="./paper.pdf", - help="output to FILE", metavar="FILE") - parser.usage = """%prog [options] rst_file [data_file] - Compiles a given rest file and information file to pdf for the SciPy - proceedings. - """ - - (options, args) = parser.parse_args() - if not len(args) in (1, 2): - print "One or two arguments required: the input rest file and " \ - "the input data file" - print '' - parser.print_help() - sys.exit(1) - infile = args[0] - if len(args)==1: - data_file = 'data.py' - if os.path.exists('data.py'): - print "Using data file 'data.py'" - else: - print "Generating the data file and storing it in data.py" - print "You will need to edit this file to add title, author " \ - "information, and abstract." - abstract = abstract_like - file('data.py', 'w').write(repr(abstract)) - elif len(args)==2: - data_file = args[1] - - abstract = Bunch( **eval(file(data_file).read())) - abstract.authors = [Bunch(**a) for a in abstract.authors] - - abstract['summary'] = u'' - abstract['paper_text'] = file(infile).read().decode('utf-8') - - outfilename = options.outfilename - - mk_abstract_preview(abstract, options.outfilename, - os.path.dirname(options.outfilename)) - # Ugly, but I don't want to wait on the thread. - sys.exit()