##// END OF EJS Templates
Merge pull request #4732 from marcmolla/master...
Min RK -
r14782:3e415e78 merge
parent child Browse files
Show More
@@ -0,0 +1,22 b''
1 {
2 "metadata": {
3 "name": ""
4 },
5 "nbformat": 3,
6 "nbformat_minor": 0,
7 "worksheets": [
8 {
9 "cells": [
10 {
11 "cell_type": "code",
12 "collapsed": false,
13 "input": [],
14 "language": "python",
15 "metadata": {},
16 "outputs": []
17 }
18 ],
19 "metadata": {}
20 }
21 ]
22 } No newline at end of file
@@ -1,149 +1,156 b''
1 1 """
2 2 Contains writer for writing nbconvert output to PDF.
3 3 """
4 4 #-----------------------------------------------------------------------------
5 5 #Copyright (c) 2013, the IPython Development Team.
6 6 #
7 7 #Distributed under the terms of the Modified BSD License.
8 8 #
9 9 #The full license is in the file COPYING.txt, distributed with this software.
10 10 #-----------------------------------------------------------------------------
11 11
12 12 #-----------------------------------------------------------------------------
13 13 # Imports
14 14 #-----------------------------------------------------------------------------
15 15
16 16 import subprocess
17 17 import os
18 18 import sys
19 19
20 20 from IPython.utils.traitlets import Integer, List, Bool
21 21
22 22 from .base import PostProcessorBase
23 23
24 24 #-----------------------------------------------------------------------------
25 25 # Classes
26 26 #-----------------------------------------------------------------------------
27 27 class PDFPostProcessor(PostProcessorBase):
28 28 """Writer designed to write to PDF files"""
29 29
30 30 latex_count = Integer(3, config=True, help="""
31 31 How many times pdflatex will be called.
32 32 """)
33 33
34 latex_command = List(["pdflatex", "{filename}"], config=True, help="""
34 latex_command = List([u"pdflatex", u"{filename}"], config=True, help="""
35 35 Shell command used to compile PDF.""")
36 36
37 bib_command = List(["bibtex", "{filename}"], config=True, help="""
37 bib_command = List([u"bibtex", u"{filename}"], config=True, help="""
38 38 Shell command used to run bibtex.""")
39 39
40 40 verbose = Bool(False, config=True, help="""
41 41 Whether or not to display the output of the compile call.
42 42 """)
43 43
44 44 temp_file_exts = List(['.aux', '.bbl', '.blg', '.idx', '.log', '.out'],
45 45 config=True, help="""
46 46 Filename extensions of temp files to remove after running.
47 47 """)
48 48 pdf_open = Bool(False, config=True, help="""
49 49 Whether or not to open the pdf after the compile call.
50 50 """)
51 51
52 52 def run_command(self, command_list, filename, count, log_function):
53 53 """Run command_list count times.
54 54
55 55 Parameters
56 56 ----------
57 57 command_list : list
58 58 A list of args to provide to Popen. Each element of this
59 59 list will be interpolated with the filename to convert.
60 60 filename : unicode
61 61 The name of the file to convert.
62 62 count : int
63 63 How many times to run the command.
64 64
65 65 Returns
66 66 -------
67 67 continue : bool
68 68 A boolean indicating if the command was successful (True)
69 69 or failed (False).
70 70 """
71 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
73 # unicode commands are not supported
74 if sys.platform == 'win32' and sys.version_info < (3,0):
75 #We must use cp1252 encoding for calling subprocess.Popen
76 #Note that sys.stdin.encoding and encoding.DEFAULT_ENCODING
77 # could be different (cp437 in case of dos console)
78 command = [c.encode('cp1252') for c in command]
72 79 times = 'time' if count == 1 else 'times'
73 80 self.log.info("Running %s %i %s: %s", command_list[0], count, times, command)
74 81 with open(os.devnull, 'rb') as null:
75 82 stdout = subprocess.PIPE if not self.verbose else None
76 83 for index in range(count):
77 84 p = subprocess.Popen(command, stdout=stdout, stdin=null)
78 85 out, err = p.communicate()
79 86 if p.returncode:
80 87 if self.verbose:
81 88 # verbose means I didn't capture stdout with PIPE,
82 89 # so it's already been displayed and `out` is None.
83 90 out = u''
84 91 else:
85 92 out = out.decode('utf-8', 'replace')
86 93 log_function(command, out)
87 94 return False # failure
88 95 return True # success
89 96
90 97 def run_latex(self, filename):
91 98 """Run pdflatex self.latex_count times."""
92 99
93 100 def log_error(command, out):
94 101 self.log.critical(u"%s failed: %s\n%s", command[0], command, out)
95 102
96 103 return self.run_command(self.latex_command, filename,
97 104 self.latex_count, log_error)
98 105
99 106 def run_bib(self, filename):
100 107 """Run bibtex self.latex_count times."""
101 108 filename = os.path.splitext(filename)[0]
102 109
103 110 def log_error(command, out):
104 111 self.log.warn('%s had problems, most likely because there were no citations',
105 112 command[0])
106 113 self.log.debug(u"%s output: %s\n%s", command[0], command, out)
107 114
108 115 return self.run_command(self.bib_command, filename, 1, log_error)
109 116
110 117 def clean_temp_files(self, filename):
111 118 """Remove temporary files created by pdflatex/bibtext."""
112 119 self.log.info("Removing temporary LaTeX files")
113 120 filename = os.path.splitext(filename)[0]
114 121 for ext in self.temp_file_exts:
115 122 try:
116 123 os.remove(filename+ext)
117 124 except OSError:
118 125 pass
119 126
120 127 def open_pdf(self, filename):
121 128 """Open the pdf in the default viewer."""
122 129 if sys.platform.startswith('darwin'):
123 130 subprocess.call(('open', filename))
124 131 elif os.name == 'nt':
125 132 os.startfile(filename)
126 133 elif os.name == 'posix':
127 134 subprocess.call(('xdg-open', filename))
128 135 return
129 136
130 137 def postprocess(self, filename):
131 138 """Build a PDF by running pdflatex and bibtex"""
132 139 self.log.info("Building PDF")
133 140 cont = self.run_latex(filename)
134 141 if cont:
135 142 cont = self.run_bib(filename)
136 143 else:
137 144 self.clean_temp_files(filename)
138 145 return
139 146 if cont:
140 147 cont = self.run_latex(filename)
141 148 self.clean_temp_files(filename)
142 149 filename = os.path.splitext(filename)[0]
143 150 if os.path.isfile(filename+'.pdf'):
144 151 self.log.info('PDF successfully created')
145 152 if self.pdf_open:
146 153 self.log.info('Viewer called')
147 154 self.open_pdf(filename+'.pdf')
148 155 return
149 156
@@ -1,185 +1,207 b''
1 # -*- coding: utf-8 -*-
1 2 """Test NbConvertApp"""
2 3
3 4 #-----------------------------------------------------------------------------
4 5 # Copyright (C) 2013 The IPython Development Team
5 6 #
6 7 # Distributed under the terms of the BSD License. The full license is in
7 8 # the file COPYING, distributed as part of this software.
8 9 #-----------------------------------------------------------------------------
9 10
10 11 #-----------------------------------------------------------------------------
11 12 # Imports
12 13 #-----------------------------------------------------------------------------
13 14
14 15 import os
15 16 import glob
16 17 import sys
17 18
18 19 from .base import TestsBase
19 20
20 21 import IPython.testing.tools as tt
21 22 from IPython.testing import decorators as dec
22 23
23 24
24 25 #-----------------------------------------------------------------------------
25 26 # Constants
26 27 #-----------------------------------------------------------------------------
27 28
28 29
29 30 #-----------------------------------------------------------------------------
30 31 # Classes and functions
31 32 #-----------------------------------------------------------------------------
32 33
33 34 class TestNbConvertApp(TestsBase):
34 35 """Collection of NbConvertApp tests"""
35 36
36 37
37 38 def test_notebook_help(self):
38 39 """Will help show if no notebooks are specified?"""
39 40 with self.create_temp_cwd():
40 41 out, err = self.call('nbconvert --log-level 0', ignore_return_code=True)
41 42 self.assertIn("see '--help-all'", out)
42 43
43 44 def test_help_output(self):
44 45 """ipython nbconvert --help-all works"""
45 46 tt.help_all_output_test('nbconvert')
46 47
47 48 def test_glob(self):
48 49 """
49 50 Do search patterns work for notebook names?
50 51 """
51 52 with self.create_temp_cwd(['notebook*.ipynb']):
52 53 self.call('nbconvert --to python *.ipynb --log-level 0')
53 54 assert os.path.isfile('notebook1.py')
54 55 assert os.path.isfile('notebook2.py')
55 56
56 57
57 58 def test_glob_subdir(self):
58 59 """
59 60 Do search patterns work for subdirectory notebook names?
60 61 """
61 62 with self.create_temp_cwd():
62 63 self.copy_files_to(['notebook*.ipynb'], 'subdir/')
63 64 self.call('nbconvert --to python --log-level 0 ' +
64 65 os.path.join('subdir', '*.ipynb'))
65 66 assert os.path.isfile('notebook1.py')
66 67 assert os.path.isfile('notebook2.py')
67 68
68 69
69 70 def test_explicit(self):
70 71 """
71 72 Do explicit notebook names work?
72 73 """
73 74 with self.create_temp_cwd(['notebook*.ipynb']):
74 75 self.call('nbconvert --log-level 0 --to python notebook2')
75 76 assert not os.path.isfile('notebook1.py')
76 77 assert os.path.isfile('notebook2.py')
77 78
78 79
79 80 @dec.onlyif_cmds_exist('pdflatex')
80 81 @dec.onlyif_cmds_exist('pandoc')
81 82 def test_filename_spaces(self):
82 83 """
83 84 Generate PDFs with graphics if notebooks have spaces in the name?
84 85 """
85 86 with self.create_temp_cwd(['notebook2.ipynb']):
86 87 os.rename('notebook2.ipynb', 'notebook with spaces.ipynb')
87 88 o,e = self.call('nbconvert --log-level 0 --to latex '
88 89 '"notebook with spaces" --post PDF '
89 90 '--PDFPostProcessor.verbose=True')
90 91 assert os.path.isfile('notebook with spaces.tex')
91 92 assert os.path.isdir('notebook with spaces_files')
92 93 assert os.path.isfile('notebook with spaces.pdf')
93 94
94 95 @dec.onlyif_cmds_exist('pdflatex')
95 96 @dec.onlyif_cmds_exist('pandoc')
96 97 def test_post_processor(self):
97 98 """
98 99 Do post processors work?
99 100 """
100 101 with self.create_temp_cwd(['notebook1.ipynb']):
101 102 self.call('nbconvert --log-level 0 --to latex notebook1 '
102 103 '--post PDF --PDFPostProcessor.verbose=True')
103 104 assert os.path.isfile('notebook1.tex')
104 105 assert os.path.isfile('notebook1.pdf')
105 106
106 107 @dec.onlyif_cmds_exist('pandoc')
107 108 def test_spurious_cr(self):
108 109 """Check for extra CR characters"""
109 110 with self.create_temp_cwd(['notebook2.ipynb']):
110 111 self.call('nbconvert --log-level 0 --to latex notebook2')
111 112 assert os.path.isfile('notebook2.tex')
112 113 with open('notebook2.tex') as f:
113 114 tex = f.read()
114 115 self.call('nbconvert --log-level 0 --to html notebook2')
115 116 assert os.path.isfile('notebook2.html')
116 117 with open('notebook2.html') as f:
117 118 html = f.read()
118 119 self.assertEqual(tex.count('\r'), tex.count('\r\n'))
119 120 self.assertEqual(html.count('\r'), html.count('\r\n'))
120 121
121 122 @dec.onlyif_cmds_exist('pandoc')
122 123 def test_png_base64_html_ok(self):
123 124 """Is embedded png data well formed in HTML?"""
124 125 with self.create_temp_cwd(['notebook2.ipynb']):
125 126 self.call('nbconvert --log-level 0 --to HTML '
126 127 'notebook2.ipynb --template full')
127 128 assert os.path.isfile('notebook2.html')
128 129 with open('notebook2.html') as f:
129 130 assert "data:image/png;base64,b'" not in f.read()
130 131
131 132 @dec.onlyif_cmds_exist('pandoc')
132 133 def test_template(self):
133 134 """
134 135 Do export templates work?
135 136 """
136 137 with self.create_temp_cwd(['notebook2.ipynb']):
137 138 self.call('nbconvert --log-level 0 --to slides '
138 139 'notebook2.ipynb')
139 140 assert os.path.isfile('notebook2.slides.html')
140 141 with open('notebook2.slides.html') as f:
141 142 assert '/reveal.css' in f.read()
142 143
143 144
144 145 def test_glob_explicit(self):
145 146 """
146 147 Can a search pattern be used along with matching explicit notebook names?
147 148 """
148 149 with self.create_temp_cwd(['notebook*.ipynb']):
149 150 self.call('nbconvert --log-level 0 --to python '
150 151 '*.ipynb notebook1.ipynb notebook2.ipynb')
151 152 assert os.path.isfile('notebook1.py')
152 153 assert os.path.isfile('notebook2.py')
153 154
154 155
155 156 def test_explicit_glob(self):
156 157 """
157 158 Can explicit notebook names be used and then a matching search pattern?
158 159 """
159 160 with self.create_temp_cwd(['notebook*.ipynb']):
160 161 self.call('nbconvert --log-level 0 --to=python '
161 162 'notebook1.ipynb notebook2.ipynb *.ipynb')
162 163 assert os.path.isfile('notebook1.py')
163 164 assert os.path.isfile('notebook2.py')
164 165
165 166
166 167 def test_default_config(self):
167 168 """
168 169 Does the default config work?
169 170 """
170 171 with self.create_temp_cwd(['notebook*.ipynb', 'ipython_nbconvert_config.py']):
171 172 self.call('nbconvert --log-level 0')
172 173 assert os.path.isfile('notebook1.py')
173 174 assert not os.path.isfile('notebook2.py')
174 175
175 176
176 177 def test_override_config(self):
177 178 """
178 179 Can the default config be overriden?
179 180 """
180 181 with self.create_temp_cwd(['notebook*.ipynb',
181 182 'ipython_nbconvert_config.py',
182 183 'override.py']):
183 184 self.call('nbconvert --log-level 0 --config="override.py"')
184 185 assert not os.path.isfile('notebook1.py')
185 186 assert os.path.isfile('notebook2.py')
187
188 def test_accents_in_filename(self):
189 """
190 Can notebook names include accents?
191 """
192 with self.create_temp_cwd(['nb*.ipynb']):
193 self.call('nbconvert --log-level 0 --to python nb1_*')
194 assert os.path.isfile(u'nb1_análisis.py')
195
196 @dec.onlyif_cmds_exist('pdflatex')
197 @dec.onlyif_cmds_exist('pandoc')
198 def test_filename_spaces(self):
199 """
200 Generate PDFs if notebooks have an accent in their name?
201 """
202 with self.create_temp_cwd(['nb*.ipynb']):
203 o,e = self.call('nbconvert --log-level 0 --to latex '
204 '"nb1_*" --post PDF '
205 '--PDFPostProcessor.verbose=True')
206 assert os.path.isfile(u'nb1_análisis.tex')
207 assert os.path.isfile(u'nb1_análisis.pdf')
General Comments 0
You need to be logged in to leave comments. Login now