154 lines
		
	
	
		
			5.2 KiB
		
	
	
	
		
			Python
		
	
	
	
			
		
		
	
	
			154 lines
		
	
	
		
			5.2 KiB
		
	
	
	
		
			Python
		
	
	
	
import py
 | 
						|
 | 
						|
from py.__.process.cmdexec import ExecutionFailed
 | 
						|
 | 
						|
font_to_package = {"times": "times", "helvetica": "times",
 | 
						|
                   "new century schoolbock": "newcent", "avant garde": "newcent",
 | 
						|
                   "palatino": "palatino",
 | 
						|
                  }
 | 
						|
sans_serif_fonts = {"helvetica": True,
 | 
						|
                    "avant garde": True,
 | 
						|
                   }
 | 
						|
 | 
						|
 | 
						|
def merge_files(pathlist, pagebreak=False):
 | 
						|
    if len(pathlist) == 1:
 | 
						|
        return pathlist[0].read()
 | 
						|
    sectnum = False
 | 
						|
    toc = False
 | 
						|
    result = []
 | 
						|
    includes = {}
 | 
						|
    for path in pathlist:
 | 
						|
        lines = path.readlines()
 | 
						|
        for line in lines:
 | 
						|
            # prevent several table of contents
 | 
						|
            # and especially sectnum several times
 | 
						|
            if ".. contents::" in line:
 | 
						|
                if not toc:
 | 
						|
                    toc = True
 | 
						|
                    result.append(line)
 | 
						|
            elif ".. sectnum::" in line:
 | 
						|
                if not sectnum:
 | 
						|
                    sectnum = True
 | 
						|
                    result.append(line)
 | 
						|
            elif line.strip().startswith(".. include:: "):
 | 
						|
                #XXX slightly unsafe
 | 
						|
                inc = line.strip()[13:]
 | 
						|
                if inc not in includes:
 | 
						|
                    includes[inc] = True
 | 
						|
                    result.append(line)
 | 
						|
            else:
 | 
						|
                result.append(line)
 | 
						|
        if pagebreak:
 | 
						|
            result.append(".. raw:: latex \n\n \\newpage\n\n")
 | 
						|
    if pagebreak:
 | 
						|
        result.pop() #remove the last pagebreak again
 | 
						|
    return "".join(result)
 | 
						|
 | 
						|
def create_stylesheet(options, path):
 | 
						|
    fill_in = {}
 | 
						|
    if "logo" in options:
 | 
						|
        fill_in["have_logo"] = ""
 | 
						|
        fill_in["logo"] = options["logo"]
 | 
						|
    else:
 | 
						|
        fill_in["have_logo"] = "%"
 | 
						|
        fill_in["logo"] = ""
 | 
						|
    if "font" in options:
 | 
						|
        font = options["font"].lower()
 | 
						|
        fill_in["font_package"] = font_to_package[font]
 | 
						|
        fill_in["specified_font"] = ""
 | 
						|
        fill_in["sans_serif"] = font not in sans_serif_fonts and "%" or ""
 | 
						|
    else:
 | 
						|
        fill_in["specified_font"] = "%"
 | 
						|
        fill_in["sans_serif"] = "%"
 | 
						|
        fill_in["font_package"] = ""
 | 
						|
    if 'toc_depth' in options:
 | 
						|
        fill_in["have_tocdepth"] = ""
 | 
						|
        fill_in["toc_depth"] = options["toc_depth"]
 | 
						|
    else:
 | 
						|
        fill_in["have_tocdepth"] = "%"
 | 
						|
        fill_in["toc_depth"] = ""
 | 
						|
    fill_in["heading"] = options.get("heading", "")
 | 
						|
    template_file = path.join("rest.sty.template")
 | 
						|
    if not template_file.check():
 | 
						|
        template_file = py.magic.autopath().dirpath().join("rest.sty.template")
 | 
						|
    return template_file.read() % fill_in
 | 
						|
 | 
						|
def process_configfile(configfile, debug=False):
 | 
						|
    old = py.path.local()
 | 
						|
    py.path.local(configfile).dirpath().chdir()
 | 
						|
    configfile = py.path.local(configfile)
 | 
						|
    path = configfile.dirpath()
 | 
						|
    configfile_dic = {}
 | 
						|
    py.std.sys.path.insert(0, str(path))
 | 
						|
    execfile(str(configfile), configfile_dic)
 | 
						|
    pagebreak = configfile_dic.get("pagebreak", False)
 | 
						|
    rest_sources = [py.path.local(p)
 | 
						|
                    for p in configfile_dic['rest_sources']]
 | 
						|
    rest = configfile.new(ext='txt')
 | 
						|
    if len(rest_sources) > 1:
 | 
						|
        assert rest not in rest_sources
 | 
						|
    content = merge_files(rest_sources, pagebreak)
 | 
						|
    if len(rest_sources) > 1:
 | 
						|
        rest.write(content)
 | 
						|
    sty = configfile.new(ext='sty')
 | 
						|
    content = create_stylesheet(configfile_dic, path)
 | 
						|
    sty.write(content)
 | 
						|
    rest_options = None
 | 
						|
    if 'rest_options' in configfile_dic:
 | 
						|
        rest_options = configfile_dic['rest_options']
 | 
						|
    process_rest_file(rest, sty.basename, debug, rest_options)
 | 
						|
    #cleanup:
 | 
						|
    if not debug:
 | 
						|
        sty.remove()
 | 
						|
        if rest not in rest_sources:
 | 
						|
            rest.remove()
 | 
						|
    old.chdir()
 | 
						|
 | 
						|
def process_rest_file(restfile, stylesheet=None, debug=False, rest_options=None):
 | 
						|
    from docutils.core import publish_cmdline
 | 
						|
    if not py.path.local.sysfind("pdflatex"):
 | 
						|
        raise SystemExit("ERROR: pdflatex not found")
 | 
						|
    old = py.path.local()
 | 
						|
    f = py.path.local(restfile)
 | 
						|
    path = f.dirpath()
 | 
						|
    path.chdir()
 | 
						|
    pdf = f.new(ext="pdf")
 | 
						|
    if pdf.check():
 | 
						|
        pdf.remove()
 | 
						|
    tex = f.new(ext="tex").basename
 | 
						|
    options = [f, "--input-encoding=latin-1", "--graphicx-option=auto",
 | 
						|
               "--traceback"]
 | 
						|
    if stylesheet is not None:
 | 
						|
        sty = path.join(stylesheet)
 | 
						|
        if sty.check():
 | 
						|
            options.append('--stylesheet=%s' % (sty.relto(f.dirpath()), ))
 | 
						|
    options.append(f.new(basename=tex))
 | 
						|
    options = map(str, options)
 | 
						|
    if rest_options is not None:
 | 
						|
        options.extend(rest_options)
 | 
						|
    publish_cmdline(writer_name='latex', argv=options)
 | 
						|
    i = 0
 | 
						|
    while i < 10: # there should never be as many as five reruns, but to be sure
 | 
						|
        try:
 | 
						|
            latexoutput = py.process.cmdexec('pdflatex "%s"' % (tex, ))
 | 
						|
        except ExecutionFailed, e:
 | 
						|
            print "ERROR: pdflatex execution failed"
 | 
						|
            print "pdflatex stdout:"
 | 
						|
            print e.out
 | 
						|
            print "pdflatex stderr:"
 | 
						|
            print e.err
 | 
						|
            raise SystemExit
 | 
						|
        if debug:
 | 
						|
            print latexoutput
 | 
						|
        if py.std.re.search("LaTeX Warning:.*Rerun", latexoutput) is None:
 | 
						|
            break
 | 
						|
        i += 1
 | 
						|
            
 | 
						|
    old.chdir()
 | 
						|
    #cleanup:
 | 
						|
    if not debug:
 | 
						|
        for ext in "log aux tex out".split():
 | 
						|
            p = pdf.new(ext=ext)
 | 
						|
            p.remove()
 |