##// 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 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(["pdflatex", "{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(["bibtex", "{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
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 times = 'time' if count == 1 else 'times'
79 times = 'time' if count == 1 else 'times'
73 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)
74 with open(os.devnull, 'rb') as null:
81 with open(os.devnull, 'rb') as null:
75 stdout = subprocess.PIPE if not self.verbose else None
82 stdout = subprocess.PIPE if not self.verbose else None
76 for index in range(count):
83 for index in range(count):
77 p = subprocess.Popen(command, stdout=stdout, stdin=null)
84 p = subprocess.Popen(command, stdout=stdout, stdin=null)
78 out, err = p.communicate()
85 out, err = p.communicate()
79 if p.returncode:
86 if p.returncode:
80 if self.verbose:
87 if self.verbose:
81 # verbose means I didn't capture stdout with PIPE,
88 # verbose means I didn't capture stdout with PIPE,
82 # so it's already been displayed and `out` is None.
89 # so it's already been displayed and `out` is None.
83 out = u''
90 out = u''
84 else:
91 else:
85 out = out.decode('utf-8', 'replace')
92 out = out.decode('utf-8', 'replace')
86 log_function(command, out)
93 log_function(command, out)
87 return False # failure
94 return False # failure
88 return True # success
95 return True # success
89
96
90 def run_latex(self, filename):
97 def run_latex(self, filename):
91 """Run pdflatex self.latex_count times."""
98 """Run pdflatex self.latex_count times."""
92
99
93 def log_error(command, out):
100 def log_error(command, out):
94 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)
95
102
96 return self.run_command(self.latex_command, filename,
103 return self.run_command(self.latex_command, filename,
97 self.latex_count, log_error)
104 self.latex_count, log_error)
98
105
99 def run_bib(self, filename):
106 def run_bib(self, filename):
100 """Run bibtex self.latex_count times."""
107 """Run bibtex self.latex_count times."""
101 filename = os.path.splitext(filename)[0]
108 filename = os.path.splitext(filename)[0]
102
109
103 def log_error(command, out):
110 def log_error(command, out):
104 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',
105 command[0])
112 command[0])
106 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)
107
114
108 return self.run_command(self.bib_command, filename, 1, log_error)
115 return self.run_command(self.bib_command, filename, 1, log_error)
109
116
110 def clean_temp_files(self, filename):
117 def clean_temp_files(self, filename):
111 """Remove temporary files created by pdflatex/bibtext."""
118 """Remove temporary files created by pdflatex/bibtext."""
112 self.log.info("Removing temporary LaTeX files")
119 self.log.info("Removing temporary LaTeX files")
113 filename = os.path.splitext(filename)[0]
120 filename = os.path.splitext(filename)[0]
114 for ext in self.temp_file_exts:
121 for ext in self.temp_file_exts:
115 try:
122 try:
116 os.remove(filename+ext)
123 os.remove(filename+ext)
117 except OSError:
124 except OSError:
118 pass
125 pass
119
126
120 def open_pdf(self, filename):
127 def open_pdf(self, filename):
121 """Open the pdf in the default viewer."""
128 """Open the pdf in the default viewer."""
122 if sys.platform.startswith('darwin'):
129 if sys.platform.startswith('darwin'):
123 subprocess.call(('open', filename))
130 subprocess.call(('open', filename))
124 elif os.name == 'nt':
131 elif os.name == 'nt':
125 os.startfile(filename)
132 os.startfile(filename)
126 elif os.name == 'posix':
133 elif os.name == 'posix':
127 subprocess.call(('xdg-open', filename))
134 subprocess.call(('xdg-open', filename))
128 return
135 return
129
136
130 def postprocess(self, filename):
137 def postprocess(self, filename):
131 """Build a PDF by running pdflatex and bibtex"""
138 """Build a PDF by running pdflatex and bibtex"""
132 self.log.info("Building PDF")
139 self.log.info("Building PDF")
133 cont = self.run_latex(filename)
140 cont = self.run_latex(filename)
134 if cont:
141 if cont:
135 cont = self.run_bib(filename)
142 cont = self.run_bib(filename)
136 else:
143 else:
137 self.clean_temp_files(filename)
144 self.clean_temp_files(filename)
138 return
145 return
139 if cont:
146 if cont:
140 cont = self.run_latex(filename)
147 cont = self.run_latex(filename)
141 self.clean_temp_files(filename)
148 self.clean_temp_files(filename)
142 filename = os.path.splitext(filename)[0]
149 filename = os.path.splitext(filename)[0]
143 if os.path.isfile(filename+'.pdf'):
150 if os.path.isfile(filename+'.pdf'):
144 self.log.info('PDF successfully created')
151 self.log.info('PDF successfully created')
145 if self.pdf_open:
152 if self.pdf_open:
146 self.log.info('Viewer called')
153 self.log.info('Viewer called')
147 self.open_pdf(filename+'.pdf')
154 self.open_pdf(filename+'.pdf')
148 return
155 return
149
156
@@ -1,185 +1,207 b''
1 # -*- coding: utf-8 -*-
1 """Test NbConvertApp"""
2 """Test NbConvertApp"""
2
3
3 #-----------------------------------------------------------------------------
4 #-----------------------------------------------------------------------------
4 # Copyright (C) 2013 The IPython Development Team
5 # Copyright (C) 2013 The IPython Development Team
5 #
6 #
6 # Distributed under the terms of the BSD License. The full license is in
7 # Distributed under the terms of the BSD License. The full license is in
7 # the file COPYING, distributed as part of this software.
8 # the file COPYING, distributed as part of this software.
8 #-----------------------------------------------------------------------------
9 #-----------------------------------------------------------------------------
9
10
10 #-----------------------------------------------------------------------------
11 #-----------------------------------------------------------------------------
11 # Imports
12 # Imports
12 #-----------------------------------------------------------------------------
13 #-----------------------------------------------------------------------------
13
14
14 import os
15 import os
15 import glob
16 import glob
16 import sys
17 import sys
17
18
18 from .base import TestsBase
19 from .base import TestsBase
19
20
20 import IPython.testing.tools as tt
21 import IPython.testing.tools as tt
21 from IPython.testing import decorators as dec
22 from IPython.testing import decorators as dec
22
23
23
24
24 #-----------------------------------------------------------------------------
25 #-----------------------------------------------------------------------------
25 # Constants
26 # Constants
26 #-----------------------------------------------------------------------------
27 #-----------------------------------------------------------------------------
27
28
28
29
29 #-----------------------------------------------------------------------------
30 #-----------------------------------------------------------------------------
30 # Classes and functions
31 # Classes and functions
31 #-----------------------------------------------------------------------------
32 #-----------------------------------------------------------------------------
32
33
33 class TestNbConvertApp(TestsBase):
34 class TestNbConvertApp(TestsBase):
34 """Collection of NbConvertApp tests"""
35 """Collection of NbConvertApp tests"""
35
36
36
37
37 def test_notebook_help(self):
38 def test_notebook_help(self):
38 """Will help show if no notebooks are specified?"""
39 """Will help show if no notebooks are specified?"""
39 with self.create_temp_cwd():
40 with self.create_temp_cwd():
40 out, err = self.call('nbconvert --log-level 0', ignore_return_code=True)
41 out, err = self.call('nbconvert --log-level 0', ignore_return_code=True)
41 self.assertIn("see '--help-all'", out)
42 self.assertIn("see '--help-all'", out)
42
43
43 def test_help_output(self):
44 def test_help_output(self):
44 """ipython nbconvert --help-all works"""
45 """ipython nbconvert --help-all works"""
45 tt.help_all_output_test('nbconvert')
46 tt.help_all_output_test('nbconvert')
46
47
47 def test_glob(self):
48 def test_glob(self):
48 """
49 """
49 Do search patterns work for notebook names?
50 Do search patterns work for notebook names?
50 """
51 """
51 with self.create_temp_cwd(['notebook*.ipynb']):
52 with self.create_temp_cwd(['notebook*.ipynb']):
52 self.call('nbconvert --to python *.ipynb --log-level 0')
53 self.call('nbconvert --to python *.ipynb --log-level 0')
53 assert os.path.isfile('notebook1.py')
54 assert os.path.isfile('notebook1.py')
54 assert os.path.isfile('notebook2.py')
55 assert os.path.isfile('notebook2.py')
55
56
56
57
57 def test_glob_subdir(self):
58 def test_glob_subdir(self):
58 """
59 """
59 Do search patterns work for subdirectory notebook names?
60 Do search patterns work for subdirectory notebook names?
60 """
61 """
61 with self.create_temp_cwd():
62 with self.create_temp_cwd():
62 self.copy_files_to(['notebook*.ipynb'], 'subdir/')
63 self.copy_files_to(['notebook*.ipynb'], 'subdir/')
63 self.call('nbconvert --to python --log-level 0 ' +
64 self.call('nbconvert --to python --log-level 0 ' +
64 os.path.join('subdir', '*.ipynb'))
65 os.path.join('subdir', '*.ipynb'))
65 assert os.path.isfile('notebook1.py')
66 assert os.path.isfile('notebook1.py')
66 assert os.path.isfile('notebook2.py')
67 assert os.path.isfile('notebook2.py')
67
68
68
69
69 def test_explicit(self):
70 def test_explicit(self):
70 """
71 """
71 Do explicit notebook names work?
72 Do explicit notebook names work?
72 """
73 """
73 with self.create_temp_cwd(['notebook*.ipynb']):
74 with self.create_temp_cwd(['notebook*.ipynb']):
74 self.call('nbconvert --log-level 0 --to python notebook2')
75 self.call('nbconvert --log-level 0 --to python notebook2')
75 assert not os.path.isfile('notebook1.py')
76 assert not os.path.isfile('notebook1.py')
76 assert os.path.isfile('notebook2.py')
77 assert os.path.isfile('notebook2.py')
77
78
78
79
79 @dec.onlyif_cmds_exist('pdflatex')
80 @dec.onlyif_cmds_exist('pdflatex')
80 @dec.onlyif_cmds_exist('pandoc')
81 @dec.onlyif_cmds_exist('pandoc')
81 def test_filename_spaces(self):
82 def test_filename_spaces(self):
82 """
83 """
83 Generate PDFs with graphics if notebooks have spaces in the name?
84 Generate PDFs with graphics if notebooks have spaces in the name?
84 """
85 """
85 with self.create_temp_cwd(['notebook2.ipynb']):
86 with self.create_temp_cwd(['notebook2.ipynb']):
86 os.rename('notebook2.ipynb', 'notebook with spaces.ipynb')
87 os.rename('notebook2.ipynb', 'notebook with spaces.ipynb')
87 o,e = self.call('nbconvert --log-level 0 --to latex '
88 o,e = self.call('nbconvert --log-level 0 --to latex '
88 '"notebook with spaces" --post PDF '
89 '"notebook with spaces" --post PDF '
89 '--PDFPostProcessor.verbose=True')
90 '--PDFPostProcessor.verbose=True')
90 assert os.path.isfile('notebook with spaces.tex')
91 assert os.path.isfile('notebook with spaces.tex')
91 assert os.path.isdir('notebook with spaces_files')
92 assert os.path.isdir('notebook with spaces_files')
92 assert os.path.isfile('notebook with spaces.pdf')
93 assert os.path.isfile('notebook with spaces.pdf')
93
94
94 @dec.onlyif_cmds_exist('pdflatex')
95 @dec.onlyif_cmds_exist('pdflatex')
95 @dec.onlyif_cmds_exist('pandoc')
96 @dec.onlyif_cmds_exist('pandoc')
96 def test_post_processor(self):
97 def test_post_processor(self):
97 """
98 """
98 Do post processors work?
99 Do post processors work?
99 """
100 """
100 with self.create_temp_cwd(['notebook1.ipynb']):
101 with self.create_temp_cwd(['notebook1.ipynb']):
101 self.call('nbconvert --log-level 0 --to latex notebook1 '
102 self.call('nbconvert --log-level 0 --to latex notebook1 '
102 '--post PDF --PDFPostProcessor.verbose=True')
103 '--post PDF --PDFPostProcessor.verbose=True')
103 assert os.path.isfile('notebook1.tex')
104 assert os.path.isfile('notebook1.tex')
104 assert os.path.isfile('notebook1.pdf')
105 assert os.path.isfile('notebook1.pdf')
105
106
106 @dec.onlyif_cmds_exist('pandoc')
107 @dec.onlyif_cmds_exist('pandoc')
107 def test_spurious_cr(self):
108 def test_spurious_cr(self):
108 """Check for extra CR characters"""
109 """Check for extra CR characters"""
109 with self.create_temp_cwd(['notebook2.ipynb']):
110 with self.create_temp_cwd(['notebook2.ipynb']):
110 self.call('nbconvert --log-level 0 --to latex notebook2')
111 self.call('nbconvert --log-level 0 --to latex notebook2')
111 assert os.path.isfile('notebook2.tex')
112 assert os.path.isfile('notebook2.tex')
112 with open('notebook2.tex') as f:
113 with open('notebook2.tex') as f:
113 tex = f.read()
114 tex = f.read()
114 self.call('nbconvert --log-level 0 --to html notebook2')
115 self.call('nbconvert --log-level 0 --to html notebook2')
115 assert os.path.isfile('notebook2.html')
116 assert os.path.isfile('notebook2.html')
116 with open('notebook2.html') as f:
117 with open('notebook2.html') as f:
117 html = f.read()
118 html = f.read()
118 self.assertEqual(tex.count('\r'), tex.count('\r\n'))
119 self.assertEqual(tex.count('\r'), tex.count('\r\n'))
119 self.assertEqual(html.count('\r'), html.count('\r\n'))
120 self.assertEqual(html.count('\r'), html.count('\r\n'))
120
121
121 @dec.onlyif_cmds_exist('pandoc')
122 @dec.onlyif_cmds_exist('pandoc')
122 def test_png_base64_html_ok(self):
123 def test_png_base64_html_ok(self):
123 """Is embedded png data well formed in HTML?"""
124 """Is embedded png data well formed in HTML?"""
124 with self.create_temp_cwd(['notebook2.ipynb']):
125 with self.create_temp_cwd(['notebook2.ipynb']):
125 self.call('nbconvert --log-level 0 --to HTML '
126 self.call('nbconvert --log-level 0 --to HTML '
126 'notebook2.ipynb --template full')
127 'notebook2.ipynb --template full')
127 assert os.path.isfile('notebook2.html')
128 assert os.path.isfile('notebook2.html')
128 with open('notebook2.html') as f:
129 with open('notebook2.html') as f:
129 assert "data:image/png;base64,b'" not in f.read()
130 assert "data:image/png;base64,b'" not in f.read()
130
131
131 @dec.onlyif_cmds_exist('pandoc')
132 @dec.onlyif_cmds_exist('pandoc')
132 def test_template(self):
133 def test_template(self):
133 """
134 """
134 Do export templates work?
135 Do export templates work?
135 """
136 """
136 with self.create_temp_cwd(['notebook2.ipynb']):
137 with self.create_temp_cwd(['notebook2.ipynb']):
137 self.call('nbconvert --log-level 0 --to slides '
138 self.call('nbconvert --log-level 0 --to slides '
138 'notebook2.ipynb')
139 'notebook2.ipynb')
139 assert os.path.isfile('notebook2.slides.html')
140 assert os.path.isfile('notebook2.slides.html')
140 with open('notebook2.slides.html') as f:
141 with open('notebook2.slides.html') as f:
141 assert '/reveal.css' in f.read()
142 assert '/reveal.css' in f.read()
142
143
143
144
144 def test_glob_explicit(self):
145 def test_glob_explicit(self):
145 """
146 """
146 Can a search pattern be used along with matching explicit notebook names?
147 Can a search pattern be used along with matching explicit notebook names?
147 """
148 """
148 with self.create_temp_cwd(['notebook*.ipynb']):
149 with self.create_temp_cwd(['notebook*.ipynb']):
149 self.call('nbconvert --log-level 0 --to python '
150 self.call('nbconvert --log-level 0 --to python '
150 '*.ipynb notebook1.ipynb notebook2.ipynb')
151 '*.ipynb notebook1.ipynb notebook2.ipynb')
151 assert os.path.isfile('notebook1.py')
152 assert os.path.isfile('notebook1.py')
152 assert os.path.isfile('notebook2.py')
153 assert os.path.isfile('notebook2.py')
153
154
154
155
155 def test_explicit_glob(self):
156 def test_explicit_glob(self):
156 """
157 """
157 Can explicit notebook names be used and then a matching search pattern?
158 Can explicit notebook names be used and then a matching search pattern?
158 """
159 """
159 with self.create_temp_cwd(['notebook*.ipynb']):
160 with self.create_temp_cwd(['notebook*.ipynb']):
160 self.call('nbconvert --log-level 0 --to=python '
161 self.call('nbconvert --log-level 0 --to=python '
161 'notebook1.ipynb notebook2.ipynb *.ipynb')
162 'notebook1.ipynb notebook2.ipynb *.ipynb')
162 assert os.path.isfile('notebook1.py')
163 assert os.path.isfile('notebook1.py')
163 assert os.path.isfile('notebook2.py')
164 assert os.path.isfile('notebook2.py')
164
165
165
166
166 def test_default_config(self):
167 def test_default_config(self):
167 """
168 """
168 Does the default config work?
169 Does the default config work?
169 """
170 """
170 with self.create_temp_cwd(['notebook*.ipynb', 'ipython_nbconvert_config.py']):
171 with self.create_temp_cwd(['notebook*.ipynb', 'ipython_nbconvert_config.py']):
171 self.call('nbconvert --log-level 0')
172 self.call('nbconvert --log-level 0')
172 assert os.path.isfile('notebook1.py')
173 assert os.path.isfile('notebook1.py')
173 assert not os.path.isfile('notebook2.py')
174 assert not os.path.isfile('notebook2.py')
174
175
175
176
176 def test_override_config(self):
177 def test_override_config(self):
177 """
178 """
178 Can the default config be overriden?
179 Can the default config be overriden?
179 """
180 """
180 with self.create_temp_cwd(['notebook*.ipynb',
181 with self.create_temp_cwd(['notebook*.ipynb',
181 'ipython_nbconvert_config.py',
182 'ipython_nbconvert_config.py',
182 'override.py']):
183 'override.py']):
183 self.call('nbconvert --log-level 0 --config="override.py"')
184 self.call('nbconvert --log-level 0 --config="override.py"')
184 assert not os.path.isfile('notebook1.py')
185 assert not os.path.isfile('notebook1.py')
185 assert os.path.isfile('notebook2.py')
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