Show More
@@ -30,31 +30,101 b' class PDFPostProcessor(PostProcessorBase):' | |||
|
30 | 30 | How many times pdflatex will be called. |
|
31 | 31 | """) |
|
32 | 32 | |
|
33 | command = List(["pdflatex", "{filename}"], config=True, help=""" | |
|
33 | pdflatex_command = List(["pdflatex", "{filename}"], config=True, help=""" | |
|
34 | 34 | Shell command used to compile PDF.""") |
|
35 | 35 | |
|
36 | bibtex_command = List(["bibtex", "{filename}"], config=True, help=""" | |
|
37 | Shell command used to run bibtex.""") | |
|
38 | ||
|
36 | 39 | verbose = Bool(False, config=True, help=""" |
|
37 | 40 | Whether or not to display the output of the compile call. |
|
38 | 41 | """) |
|
39 | 42 | |
|
40 | def postprocess(self, input): | |
|
41 | """ | |
|
42 | Consume and write Jinja output a PDF. | |
|
43 | See files.py for more... | |
|
44 | """ | |
|
45 | command = [c.format(filename=input) for c in self.command] | |
|
46 | self.log.info("Building PDF: %s", command) | |
|
47 | with open(os.devnull, 'rb') as null: | |
|
48 | stdout = subprocess.PIPE if not self.verbose else None | |
|
49 | for index in range(self.iteration_count): | |
|
50 | p = subprocess.Popen(command, stdout=stdout, stdin=null) | |
|
51 | out, err = p.communicate() | |
|
52 | if p.returncode: | |
|
53 | if self.verbose: | |
|
54 | # verbose means I didn't capture stdout with PIPE, | |
|
55 | # so it's already been displayed and `out` is None. | |
|
56 | out = u'' | |
|
57 | else: | |
|
58 | out = out.decode('utf-8', 'replace') | |
|
59 | self.log.critical(u"PDF conversion failed: %s\n%s", command, out) | |
|
60 | return | |
|
43 | temp_file_exts = List(['.aux', '.bbl', '.blg', '.idx', '.log', '.out'], | |
|
44 | config=True, help=""" | |
|
45 | Filename extensions of temp files to remove after running | |
|
46 | """) | |
|
47 | ||
|
48 | def run_command(self, command_list, filename, count, log_function): | |
|
49 | """Run pdflatex or bibtext count times. | |
|
50 | ||
|
51 | Parameters | |
|
52 | ---------- | |
|
53 | command_list : list | |
|
54 | A list of args to provide to Popen. Each element of this | |
|
55 | list will be interpolated with the filename to convert. | |
|
56 | filename : unicode | |
|
57 | The name of the file to convert. | |
|
58 | count : int | |
|
59 | How many times to run the command. | |
|
60 | ||
|
61 | Returns | |
|
62 | ------- | |
|
63 | continue : bool | |
|
64 | A boolean indicating if the command was successful (True) | |
|
65 | or failed (False). | |
|
66 | """ | |
|
67 | command = [c.format(filename=filename) for c in command_list] | |
|
68 | times = 'time' if count == 1 else 'times' | |
|
69 | self.log.info("Running %s %i %s: %s", command_list[0], count, times, command) | |
|
70 | with open(os.devnull, 'rb') as null: | |
|
71 | stdout = subprocess.PIPE if not self.verbose else None | |
|
72 | for index in range(count): | |
|
73 | p = subprocess.Popen(command, stdout=stdout, stdin=null) | |
|
74 | out, err = p.communicate() | |
|
75 | if p.returncode: | |
|
76 | if self.verbose: | |
|
77 | # verbose means I didn't capture stdout with PIPE, | |
|
78 | # so it's already been displayed and `out` is None. | |
|
79 | out = u'' | |
|
80 | else: | |
|
81 | out = out.decode('utf-8', 'replace') | |
|
82 | log_function(command, out) | |
|
83 | return False # failure | |
|
84 | return True # success | |
|
85 | ||
|
86 | def run_pdflatex(self, filename): | |
|
87 | """Run pdflatex self.iteration_count times.""" | |
|
88 | ||
|
89 | def log_error(command, out): | |
|
90 | self.log.critical(u"pdflatex failed: %s\n%s", command, out) | |
|
91 | ||
|
92 | return self.run_command(self.pdflatex_command, filename, | |
|
93 | self.iteration_count, log_error) | |
|
94 | ||
|
95 | def run_bibtex(self, filename): | |
|
96 | """Run bibtex self.iteration_count times.""" | |
|
97 | filename = filename.rstrip('.tex') | |
|
98 | ||
|
99 | def log_error(command, out): | |
|
100 | self.log.warn('bibtex had problems, most likely because there were no citations') | |
|
101 | self.log.debug(u"bibtex output: %s\n%s", command, out) | |
|
102 | ||
|
103 | return self.run_command(self.bibtex_command, filename, 1, log_error) | |
|
104 | ||
|
105 | def clean_temp_files(self, filename): | |
|
106 | """Remove temporary files created by pdflatex/bibtext.""" | |
|
107 | self.log.info("Removing temporary LaTeX files") | |
|
108 | filename = filename.strip('.tex') | |
|
109 | for ext in self.temp_file_exts: | |
|
110 | try: | |
|
111 | os.remove(filename+ext) | |
|
112 | except OSError: | |
|
113 | pass | |
|
114 | ||
|
115 | def postprocess(self, filename): | |
|
116 | """Build a PDF by running pdflatex and bibtex""" | |
|
117 | self.log.info("Building PDF") | |
|
118 | cont = self.run_pdflatex(filename) | |
|
119 | if cont: | |
|
120 | cont = self.run_bibtex(filename) | |
|
121 | else: | |
|
122 | self.clean_temp_files(filename) | |
|
123 | return | |
|
124 | if cont: | |
|
125 | cont = self.run_pdflatex(filename) | |
|
126 | self.clean_temp_files(filename) | |
|
127 | if os.path.isfile(filename.rstrip('.tex')+'.pdf'): | |
|
128 | self.log.info('PDF successfully created') | |
|
129 | return | |
|
130 |
General Comments 0
You need to be logged in to leave comments.
Login now