##// END OF EJS Templates
Merge pull request #7453 from takluyver/check-latex-commands...
Min RK -
r19925:dd150e70 merge
parent child Browse files
Show More
@@ -1,141 +1,147 b''
1 1 """Export to PDF via latex"""
2 2
3 3 # Copyright (c) IPython Development Team.
4 4 # Distributed under the terms of the Modified BSD License.
5 5
6 6 import subprocess
7 7 import os
8 8 import sys
9 9
10 from IPython.utils.process import find_cmd
10 11 from IPython.utils.traitlets import Integer, List, Bool, Instance
11 12 from IPython.utils.tempdir import TemporaryWorkingDirectory
12 13 from .latex import LatexExporter
13 14
14 15
15 16 class PDFExporter(LatexExporter):
16 17 """Writer designed to write to PDF files"""
17 18
18 19 latex_count = Integer(3, config=True,
19 20 help="How many times latex will be called."
20 21 )
21 22
22 23 latex_command = List([u"pdflatex", u"{filename}"], config=True,
23 24 help="Shell command used to compile latex."
24 25 )
25 26
26 27 bib_command = List([u"bibtex", u"{filename}"], config=True,
27 28 help="Shell command used to run bibtex."
28 29 )
29 30
30 31 verbose = Bool(False, config=True,
31 32 help="Whether to display the output of latex commands."
32 33 )
33 34
34 35 temp_file_exts = List(['.aux', '.bbl', '.blg', '.idx', '.log', '.out'], config=True,
35 36 help="File extensions of temp files to remove after running."
36 37 )
37 38
38 39 writer = Instance("IPython.nbconvert.writers.FilesWriter", args=())
39 40
40 41 def run_command(self, command_list, filename, count, log_function):
41 42 """Run command_list count times.
42 43
43 44 Parameters
44 45 ----------
45 46 command_list : list
46 47 A list of args to provide to Popen. Each element of this
47 48 list will be interpolated with the filename to convert.
48 49 filename : unicode
49 50 The name of the file to convert.
50 51 count : int
51 52 How many times to run the command.
52 53
53 54 Returns
54 55 -------
55 56 success : bool
56 57 A boolean indicating if the command was successful (True)
57 58 or failed (False).
58 59 """
59 60 command = [c.format(filename=filename) for c in command_list]
60 #In windows and python 2.x there is a bug in subprocess.Popen and
61
62 # On windows with python 2.x there is a bug in subprocess.Popen and
61 63 # unicode commands are not supported
62 64 if sys.platform == 'win32' and sys.version_info < (3,0):
63 65 #We must use cp1252 encoding for calling subprocess.Popen
64 66 #Note that sys.stdin.encoding and encoding.DEFAULT_ENCODING
65 67 # could be different (cp437 in case of dos console)
66 68 command = [c.encode('cp1252') for c in command]
69
70 # This will throw a clearer error if the command is not found
71 find_cmd(command_list[0])
72
67 73 times = 'time' if count == 1 else 'times'
68 74 self.log.info("Running %s %i %s: %s", command_list[0], count, times, command)
69 75 with open(os.devnull, 'rb') as null:
70 76 stdout = subprocess.PIPE if not self.verbose else None
71 77 for index in range(count):
72 78 p = subprocess.Popen(command, stdout=stdout, stdin=null)
73 79 out, err = p.communicate()
74 80 if p.returncode:
75 81 if self.verbose:
76 82 # verbose means I didn't capture stdout with PIPE,
77 83 # so it's already been displayed and `out` is None.
78 84 out = u''
79 85 else:
80 86 out = out.decode('utf-8', 'replace')
81 87 log_function(command, out)
82 88 return False # failure
83 89 return True # success
84 90
85 91 def run_latex(self, filename):
86 92 """Run pdflatex self.latex_count times."""
87 93
88 94 def log_error(command, out):
89 95 self.log.critical(u"%s failed: %s\n%s", command[0], command, out)
90 96
91 97 return self.run_command(self.latex_command, filename,
92 98 self.latex_count, log_error)
93 99
94 100 def run_bib(self, filename):
95 101 """Run bibtex self.latex_count times."""
96 102 filename = os.path.splitext(filename)[0]
97 103
98 104 def log_error(command, out):
99 105 self.log.warn('%s had problems, most likely because there were no citations',
100 106 command[0])
101 107 self.log.debug(u"%s output: %s\n%s", command[0], command, out)
102 108
103 109 return self.run_command(self.bib_command, filename, 1, log_error)
104 110
105 111 def clean_temp_files(self, filename):
106 112 """Remove temporary files created by pdflatex/bibtex."""
107 113 self.log.info("Removing temporary LaTeX files")
108 114 filename = os.path.splitext(filename)[0]
109 115 for ext in self.temp_file_exts:
110 116 try:
111 117 os.remove(filename+ext)
112 118 except OSError:
113 119 pass
114 120
115 121 def from_notebook_node(self, nb, resources=None, **kw):
116 122 latex, resources = super(PDFExporter, self).from_notebook_node(
117 123 nb, resources=resources, **kw
118 124 )
119 125 with TemporaryWorkingDirectory() as td:
120 126 notebook_name = "notebook"
121 127 tex_file = self.writer.write(latex, resources, notebook_name=notebook_name)
122 128 self.log.info("Building PDF")
123 129 rc = self.run_latex(tex_file)
124 130 if not rc:
125 131 rc = self.run_bib(tex_file)
126 132 if not rc:
127 133 rc = self.run_latex(tex_file)
128 134
129 135 pdf_file = notebook_name + '.pdf'
130 136 if not os.path.isfile(pdf_file):
131 137 raise RuntimeError("PDF creating failed")
132 138 self.log.info('PDF successfully created')
133 139 with open(pdf_file, 'rb') as f:
134 140 pdf_data = f.read()
135 141
136 142 # convert output extension to pdf
137 143 # the writer above required it to be tex
138 144 resources['output_extension'] = '.pdf'
139 145
140 146 return pdf_data, resources
141 147
General Comments 0
You need to be logged in to leave comments. Login now