##// END OF EJS Templates
Adding better logic to the PDF postprocessor.
Brian E. Granger -
Show More
@@ -30,31 +30,101 b' class PDFPostProcessor(PostProcessorBase):'
30 How many times pdflatex will be called.
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 Shell command used to compile PDF.""")
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 verbose = Bool(False, config=True, help="""
39 verbose = Bool(False, config=True, help="""
37 Whether or not to display the output of the compile call.
40 Whether or not to display the output of the compile call.
38 """)
41 """)
39
42
40 def postprocess(self, input):
43 temp_file_exts = List(['.aux', '.bbl', '.blg', '.idx', '.log', '.out'],
41 """
44 config=True, help="""
42 Consume and write Jinja output a PDF.
45 Filename extensions of temp files to remove after running
43 See files.py for more...
46 """)
44 """
47
45 command = [c.format(filename=input) for c in self.command]
48 def run_command(self, command_list, filename, count, log_function):
46 self.log.info("Building PDF: %s", command)
49 """Run pdflatex or bibtext count times.
47 with open(os.devnull, 'rb') as null:
50
48 stdout = subprocess.PIPE if not self.verbose else None
51 Parameters
49 for index in range(self.iteration_count):
52 ----------
50 p = subprocess.Popen(command, stdout=stdout, stdin=null)
53 command_list : list
51 out, err = p.communicate()
54 A list of args to provide to Popen. Each element of this
52 if p.returncode:
55 list will be interpolated with the filename to convert.
53 if self.verbose:
56 filename : unicode
54 # verbose means I didn't capture stdout with PIPE,
57 The name of the file to convert.
55 # so it's already been displayed and `out` is None.
58 count : int
56 out = u''
59 How many times to run the command.
57 else:
60
58 out = out.decode('utf-8', 'replace')
61 Returns
59 self.log.critical(u"PDF conversion failed: %s\n%s", command, out)
62 -------
60 return
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
@@ -62,3 +62,7 b' class TestPDF(TestsBase):'
62
62
63 # Check that the PDF was created.
63 # Check that the PDF was created.
64 assert os.path.isfile('a.pdf')
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