summaryrefslogtreecommitdiffstats
path: root/equations/signals.py
blob: 0fecc34845fd82c9951340370d73df94dd2fb308 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
from django.conf import settings

def update_render(sender, instance, signal, *args, **kwargs):
    """Renders an object's .png representation using LaTeX and puts it 
       in the right directory. Requires latex, dvipng, etc"""
    import os, shutil, tempfile, subprocess
    def call_command_in_dir(app, args, targetdir):
        cwd = os.getcwd()
        try:
            os.chdir(targetdir)
            p = subprocess.Popen(app + ' ' + ' '.join(args), shell=True)
            sts = os.waitpid(p.pid, 0)
            # FIXME -- should we raise an exception of status is non-zero?
        finally:
            # Restore working directory
            os.chdir(cwd)

    rawlatex = instance.latex    
    dstdir = settings.MEDIA_ROOT + instance.renderdir
    dstfile = "%s.png" % instance.id
    dst = "%s" % instance.id

    prologue = ""
    latex_template = r'''
    \documentclass[12pt]{article}
    \pagestyle{empty}
    %(prologue)s
    \begin{document}
    $$%(raw)s$$
    \end{document}
    '''
    max_pages = 1
    MAX_RUN_TIME = 5 # seconds
    latex = "latex"
    dvipng = "dvipng"
    latex_args = ("--interaction=nonstopmode", "%s.tex")
    dvipng_args = ("-q", "-bgTransparent", "-Ttight", "--noghostscript", 
        "-l%s" % max_pages, "%s.dvi")
    tex = latex_template % { 'raw': rawlatex, 'prologue': prologue }

    tmpdir = tempfile.mkdtemp()
    try:
        data = open("%s/%s.tex" % (tmpdir, dst), "w")
        data.write(tex)
        data.close()
        args = list(latex_args)
        args[-1] = args[-1] % dst
        res = call_command_in_dir(latex, args, tmpdir)
        if not res is None:
            # FIXME need to return some sort of error
            return []
        args = list(dvipng_args)
        args[-1] = args[-1] % dst
        res = call_command_in_dir(dvipng, args, tmpdir)
        if not res is None:
            # FIXME need to return some sort of error
            return []

        if os.access("%s/%s1.png" % (tmpdir, dst), os.R_OK):
            shutil.copyfile("%s/%s1.png" % (tmpdir, dst),
                dstdir + dstfile)
    finally:
        # FIXME do some tidy up here
        instance.render = instance.renderdir + dstfile
    shutil.rmtree(tmpdir)