##// END OF EJS Templates
Adding better logic to the PDF postprocessor.
Brian E. Granger -
Show More
@@ -30,23 +30,46 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...
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).
44 66 """
45 command = [c.format(filename=input) for c in self.command]
46 self.log.info("Building PDF: %s", command)
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)
47 70 with open(os.devnull, 'rb') as null:
48 71 stdout = subprocess.PIPE if not self.verbose else None
49 for index in range(self.iteration_count):
72 for index in range(count):
50 73 p = subprocess.Popen(command, stdout=stdout, stdin=null)
51 74 out, err = p.communicate()
52 75 if p.returncode:
@@ -56,5 +79,52 b' class PDFPostProcessor(PostProcessorBase):'
56 79 out = u''
57 80 else:
58 81 out = out.decode('utf-8', 'replace')
59 self.log.critical(u"PDF conversion failed: %s\n%s", command, out)
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)
60 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
@@ -62,3 +62,7 b' class TestPDF(TestsBase):'
62 62
63 63 # Check that the PDF was created.
64 64 assert os.path.isfile('a.pdf')
65
66 # Make sure that temp files are cleaned up
67 for ext in processor.temp_file_exts:
68 assert not os.path.isfile('a'+ext)
General Comments 0
You need to be logged in to leave comments. Login now