##// END OF EJS Templates
removed sehll=True
marcmolla -
Show More
@@ -1,156 +1,156 b''
1 """
1 """
2 Contains writer for writing nbconvert output to PDF.
2 Contains writer for writing nbconvert output to PDF.
3 """
3 """
4 #-----------------------------------------------------------------------------
4 #-----------------------------------------------------------------------------
5 #Copyright (c) 2013, the IPython Development Team.
5 #Copyright (c) 2013, the IPython Development Team.
6 #
6 #
7 #Distributed under the terms of the Modified BSD License.
7 #Distributed under the terms of the Modified BSD License.
8 #
8 #
9 #The full license is in the file COPYING.txt, distributed with this software.
9 #The full license is in the file COPYING.txt, distributed with this software.
10 #-----------------------------------------------------------------------------
10 #-----------------------------------------------------------------------------
11
11
12 #-----------------------------------------------------------------------------
12 #-----------------------------------------------------------------------------
13 # Imports
13 # Imports
14 #-----------------------------------------------------------------------------
14 #-----------------------------------------------------------------------------
15
15
16 import subprocess
16 import subprocess
17 import os
17 import os
18 import sys
18 import sys
19
19
20 from IPython.utils.traitlets import Integer, List, Bool
20 from IPython.utils.traitlets import Integer, List, Bool
21
21
22 from .base import PostProcessorBase
22 from .base import PostProcessorBase
23
23
24 #-----------------------------------------------------------------------------
24 #-----------------------------------------------------------------------------
25 # Classes
25 # Classes
26 #-----------------------------------------------------------------------------
26 #-----------------------------------------------------------------------------
27 class PDFPostProcessor(PostProcessorBase):
27 class PDFPostProcessor(PostProcessorBase):
28 """Writer designed to write to PDF files"""
28 """Writer designed to write to PDF files"""
29
29
30 latex_count = Integer(3, config=True, help="""
30 latex_count = Integer(3, config=True, help="""
31 How many times pdflatex will be called.
31 How many times pdflatex will be called.
32 """)
32 """)
33
33
34 latex_command = List([u"pdflatex", u"{filename}"], config=True, help="""
34 latex_command = List([u"pdflatex", u"{filename}"], config=True, help="""
35 Shell command used to compile PDF.""")
35 Shell command used to compile PDF.""")
36
36
37 bib_command = List([u"bibtex", u"{filename}"], config=True, help="""
37 bib_command = List([u"bibtex", u"{filename}"], config=True, help="""
38 Shell command used to run bibtex.""")
38 Shell command used to run bibtex.""")
39
39
40 verbose = Bool(False, config=True, help="""
40 verbose = Bool(False, config=True, help="""
41 Whether or not to display the output of the compile call.
41 Whether or not to display the output of the compile call.
42 """)
42 """)
43
43
44 temp_file_exts = List(['.aux', '.bbl', '.blg', '.idx', '.log', '.out'],
44 temp_file_exts = List(['.aux', '.bbl', '.blg', '.idx', '.log', '.out'],
45 config=True, help="""
45 config=True, help="""
46 Filename extensions of temp files to remove after running.
46 Filename extensions of temp files to remove after running.
47 """)
47 """)
48 pdf_open = Bool(False, config=True, help="""
48 pdf_open = Bool(False, config=True, help="""
49 Whether or not to open the pdf after the compile call.
49 Whether or not to open the pdf after the compile call.
50 """)
50 """)
51
51
52 def run_command(self, command_list, filename, count, log_function):
52 def run_command(self, command_list, filename, count, log_function):
53 """Run command_list count times.
53 """Run command_list count times.
54
54
55 Parameters
55 Parameters
56 ----------
56 ----------
57 command_list : list
57 command_list : list
58 A list of args to provide to Popen. Each element of this
58 A list of args to provide to Popen. Each element of this
59 list will be interpolated with the filename to convert.
59 list will be interpolated with the filename to convert.
60 filename : unicode
60 filename : unicode
61 The name of the file to convert.
61 The name of the file to convert.
62 count : int
62 count : int
63 How many times to run the command.
63 How many times to run the command.
64
64
65 Returns
65 Returns
66 -------
66 -------
67 continue : bool
67 continue : bool
68 A boolean indicating if the command was successful (True)
68 A boolean indicating if the command was successful (True)
69 or failed (False).
69 or failed (False).
70 """
70 """
71 command = [c.format(filename=filename) for c in command_list]
71 command = [c.format(filename=filename) for c in command_list]
72 #In windows and python 2.x there is a bug in subprocess.Popen and
72 #In windows and python 2.x there is a bug in subprocess.Popen and
73 # unicode commands are not supported
73 # unicode commands are not supported
74 if sys.platform == 'win32' and sys.version_info < (3,0):
74 if sys.platform == 'win32' and sys.version_info < (3,0):
75 #We must use cp1252 encoding for calling subprocess.Popen
75 #We must use cp1252 encoding for calling subprocess.Popen
76 #Note that sys.stdin.encoding and encoding.DEFAULT_ENCODING
76 #Note that sys.stdin.encoding and encoding.DEFAULT_ENCODING
77 # could be different (cp437 in case of dos console)
77 # could be different (cp437 in case of dos console)
78 command = [c.encode('cp1252') for c in command]
78 command = [c.encode('cp1252') for c in command]
79 times = 'time' if count == 1 else 'times'
79 times = 'time' if count == 1 else 'times'
80 self.log.info("Running %s %i %s: %s", command_list[0], count, times, command)
80 self.log.info("Running %s %i %s: %s", command_list[0], count, times, command)
81 with open(os.devnull, 'rb') as null:
81 with open(os.devnull, 'rb') as null:
82 stdout = subprocess.PIPE if not self.verbose else None
82 stdout = subprocess.PIPE if not self.verbose else None
83 for index in range(count):
83 for index in range(count):
84 p = subprocess.Popen(command, stdout=stdout, stdin=null, shell=True)
84 p = subprocess.Popen(command, stdout=stdout, stdin=null)
85 out, err = p.communicate()
85 out, err = p.communicate()
86 if p.returncode:
86 if p.returncode:
87 if self.verbose:
87 if self.verbose:
88 # verbose means I didn't capture stdout with PIPE,
88 # verbose means I didn't capture stdout with PIPE,
89 # so it's already been displayed and `out` is None.
89 # so it's already been displayed and `out` is None.
90 out = u''
90 out = u''
91 else:
91 else:
92 out = out.decode('utf-8', 'replace')
92 out = out.decode('utf-8', 'replace')
93 log_function(command, out)
93 log_function(command, out)
94 return False # failure
94 return False # failure
95 return True # success
95 return True # success
96
96
97 def run_latex(self, filename):
97 def run_latex(self, filename):
98 """Run pdflatex self.latex_count times."""
98 """Run pdflatex self.latex_count times."""
99
99
100 def log_error(command, out):
100 def log_error(command, out):
101 self.log.critical(u"%s failed: %s\n%s", command[0], command, out)
101 self.log.critical(u"%s failed: %s\n%s", command[0], command, out)
102
102
103 return self.run_command(self.latex_command, filename,
103 return self.run_command(self.latex_command, filename,
104 self.latex_count, log_error)
104 self.latex_count, log_error)
105
105
106 def run_bib(self, filename):
106 def run_bib(self, filename):
107 """Run bibtex self.latex_count times."""
107 """Run bibtex self.latex_count times."""
108 filename = os.path.splitext(filename)[0]
108 filename = os.path.splitext(filename)[0]
109
109
110 def log_error(command, out):
110 def log_error(command, out):
111 self.log.warn('%s had problems, most likely because there were no citations',
111 self.log.warn('%s had problems, most likely because there were no citations',
112 command[0])
112 command[0])
113 self.log.debug(u"%s output: %s\n%s", command[0], command, out)
113 self.log.debug(u"%s output: %s\n%s", command[0], command, out)
114
114
115 return self.run_command(self.bib_command, filename, 1, log_error)
115 return self.run_command(self.bib_command, filename, 1, log_error)
116
116
117 def clean_temp_files(self, filename):
117 def clean_temp_files(self, filename):
118 """Remove temporary files created by pdflatex/bibtext."""
118 """Remove temporary files created by pdflatex/bibtext."""
119 self.log.info("Removing temporary LaTeX files")
119 self.log.info("Removing temporary LaTeX files")
120 filename = os.path.splitext(filename)[0]
120 filename = os.path.splitext(filename)[0]
121 for ext in self.temp_file_exts:
121 for ext in self.temp_file_exts:
122 try:
122 try:
123 os.remove(filename+ext)
123 os.remove(filename+ext)
124 except OSError:
124 except OSError:
125 pass
125 pass
126
126
127 def open_pdf(self, filename):
127 def open_pdf(self, filename):
128 """Open the pdf in the default viewer."""
128 """Open the pdf in the default viewer."""
129 if sys.platform.startswith('darwin'):
129 if sys.platform.startswith('darwin'):
130 subprocess.call(('open', filename))
130 subprocess.call(('open', filename))
131 elif os.name == 'nt':
131 elif os.name == 'nt':
132 os.startfile(filename)
132 os.startfile(filename)
133 elif os.name == 'posix':
133 elif os.name == 'posix':
134 subprocess.call(('xdg-open', filename))
134 subprocess.call(('xdg-open', filename))
135 return
135 return
136
136
137 def postprocess(self, filename):
137 def postprocess(self, filename):
138 """Build a PDF by running pdflatex and bibtex"""
138 """Build a PDF by running pdflatex and bibtex"""
139 self.log.info("Building PDF")
139 self.log.info("Building PDF")
140 cont = self.run_latex(filename)
140 cont = self.run_latex(filename)
141 if cont:
141 if cont:
142 cont = self.run_bib(filename)
142 cont = self.run_bib(filename)
143 else:
143 else:
144 self.clean_temp_files(filename)
144 self.clean_temp_files(filename)
145 return
145 return
146 if cont:
146 if cont:
147 cont = self.run_latex(filename)
147 cont = self.run_latex(filename)
148 self.clean_temp_files(filename)
148 self.clean_temp_files(filename)
149 filename = os.path.splitext(filename)[0]
149 filename = os.path.splitext(filename)[0]
150 if os.path.isfile(filename+'.pdf'):
150 if os.path.isfile(filename+'.pdf'):
151 self.log.info('PDF successfully created')
151 self.log.info('PDF successfully created')
152 if self.pdf_open:
152 if self.pdf_open:
153 self.log.info('Viewer called')
153 self.log.info('Viewer called')
154 self.open_pdf(filename+'.pdf')
154 self.open_pdf(filename+'.pdf')
155 return
155 return
156
156
General Comments 0
You need to be logged in to leave comments. Login now