1 | """ |
---|
2 | Created by Massimo Di Pierro |
---|
3 | License BSD |
---|
4 | """ |
---|
5 | from __future__ import print_function |
---|
6 | |
---|
7 | import subprocess |
---|
8 | import os |
---|
9 | import os.path |
---|
10 | import re |
---|
11 | import sys |
---|
12 | from tempfile import mkstemp, mkdtemp, NamedTemporaryFile |
---|
13 | from gluon.contrib.markmin.markmin2latex import markmin2latex |
---|
14 | |
---|
15 | __all__ = ['markmin2pdf'] |
---|
16 | |
---|
17 | |
---|
18 | def removeall(path): |
---|
19 | ERROR_STR = """Error removing %(path)s, %(error)s """ |
---|
20 | |
---|
21 | def rmgeneric(path, __func__): |
---|
22 | try: |
---|
23 | __func__(path) |
---|
24 | except OSError as xxx_todo_changeme: |
---|
25 | (errno, strerror) = xxx_todo_changeme.args |
---|
26 | print(ERROR_STR % {'path': path, 'error': strerror}) |
---|
27 | |
---|
28 | files = [path] |
---|
29 | |
---|
30 | while files: |
---|
31 | file = files[0] |
---|
32 | if os.path.isfile(file): |
---|
33 | f = os.remove |
---|
34 | rmgeneric(file, os.remove) |
---|
35 | del files[0] |
---|
36 | elif os.path.isdir(file): |
---|
37 | nested = os.listdir(file) |
---|
38 | if not nested: |
---|
39 | rmgeneric(file, os.rmdir) |
---|
40 | del files[0] |
---|
41 | else: |
---|
42 | files = [os.path.join(file, x) for x in nested] + files |
---|
43 | |
---|
44 | |
---|
45 | def latex2pdf(latex, pdflatex='pdflatex', passes=3): |
---|
46 | """ |
---|
47 | calls pdflatex in a tempfolder |
---|
48 | |
---|
49 | Arguments: |
---|
50 | |
---|
51 | - pdflatex: path to the pdflatex command. Default is just 'pdflatex'. |
---|
52 | - passes: defines how often pdflates should be run in the texfile. |
---|
53 | """ |
---|
54 | |
---|
55 | pdflatex = pdflatex |
---|
56 | passes = passes |
---|
57 | warnings = [] |
---|
58 | |
---|
59 | # setup the envoriment |
---|
60 | tmpdir = mkdtemp() |
---|
61 | texfile = open(tmpdir + '/test.tex', 'wt',encoding="utf-8") |
---|
62 | texfile.write(latex) |
---|
63 | texfile.seek(0) |
---|
64 | texfile.close() |
---|
65 | texfile = os.path.abspath(texfile.name) |
---|
66 | |
---|
67 | # start doing some work |
---|
68 | for i in range(0, passes): |
---|
69 | logfd, logname = mkstemp() |
---|
70 | outfile = os.fdopen(logfd) |
---|
71 | try: |
---|
72 | ret = subprocess.call([pdflatex, |
---|
73 | '-interaction=nonstopmode', |
---|
74 | '-output-format', 'pdf', |
---|
75 | '-output-directory', tmpdir, |
---|
76 | texfile], |
---|
77 | cwd=os.path.dirname(texfile), stdout=outfile, |
---|
78 | stderr=subprocess.PIPE) |
---|
79 | finally: |
---|
80 | outfile.close() |
---|
81 | re_errors = re.compile('^\!(.*)$', re.M) |
---|
82 | re_warnings = re.compile('^LaTeX Warning\:(.*)$', re.M) |
---|
83 | flog = open(logname,encoding="utf-8") |
---|
84 | try: |
---|
85 | loglines = flog.read() |
---|
86 | finally: |
---|
87 | flog.close() |
---|
88 | errors = re_errors.findall(loglines) |
---|
89 | warnings = re_warnings.findall(loglines) |
---|
90 | os.unlink(logname) |
---|
91 | |
---|
92 | pdffile = texfile.rsplit('.', 1)[0] + '.pdf' |
---|
93 | data = None |
---|
94 | |
---|
95 | if os.path.isfile(pdffile): |
---|
96 | with open(pdffile,'rb') as fpdf : |
---|
97 | data = fpdf.read() |
---|
98 | |
---|
99 | removeall(tmpdir) |
---|
100 | |
---|
101 | return data, warnings, errors |
---|
102 | |
---|
103 | |
---|
104 | def markmin2pdf(text, image_mapper=lambda x: None, extra={}): |
---|
105 | return latex2pdf(markmin2latex(text, image_mapper=image_mapper, extra=extra)) |
---|
106 | |
---|
107 | |
---|
108 | if __name__ == '__main__': |
---|
109 | import sys |
---|
110 | import doctest |
---|
111 | import markmin2html |
---|
112 | |
---|
113 | if sys.argv[1:2] == ['-h']: |
---|
114 | data, warnings, errors = markmin2pdf(markmin2html.__doc__) |
---|
115 | if errors: |
---|
116 | print('ERRORS:' + '\n'.join(errors)) |
---|
117 | print('WARNGINS:' + '\n'.join(warnings)) |
---|
118 | else: |
---|
119 | print(data) |
---|
120 | elif len(sys.argv) > 1: |
---|
121 | fargv = open(sys.argv[1], 'rb') |
---|
122 | try: |
---|
123 | data, warnings, errors = markmin2pdf(fargv.read()) |
---|
124 | finally: |
---|
125 | fargv.close() |
---|
126 | if errors: |
---|
127 | print('ERRORS:' + '\n'.join(errors)) |
---|
128 | print('WARNGINS:' + '\n'.join(warnings)) |
---|
129 | else: |
---|
130 | print(data) |
---|
131 | else: |
---|
132 | doctest.testmod() |
---|