##// END OF EJS Templates
Break up convert_notebooks so that it is easier to subclass
Jessica B. Hamrick -
Show More
@@ -1,340 +1,407 b''
1 #!/usr/bin/env python
1 #!/usr/bin/env python
2 """NbConvert is a utility for conversion of .ipynb files.
2 """NbConvert is a utility for conversion of .ipynb files.
3
3
4 Command-line interface for the NbConvert conversion utility.
4 Command-line interface for the NbConvert conversion utility.
5 """
5 """
6
6
7 # Copyright (c) IPython Development Team.
7 # Copyright (c) IPython Development Team.
8 # Distributed under the terms of the Modified BSD License.
8 # Distributed under the terms of the Modified BSD License.
9
9
10 from __future__ import print_function
10 from __future__ import print_function
11
11
12 import logging
12 import logging
13 import sys
13 import sys
14 import os
14 import os
15 import glob
15 import glob
16
16
17 from IPython.core.application import BaseIPythonApplication, base_aliases, base_flags
17 from IPython.core.application import BaseIPythonApplication, base_aliases, base_flags
18 from IPython.core.profiledir import ProfileDir
18 from IPython.core.profiledir import ProfileDir
19 from IPython.config import catch_config_error, Configurable
19 from IPython.config import catch_config_error, Configurable
20 from IPython.utils.traitlets import (
20 from IPython.utils.traitlets import (
21 Unicode, List, Instance, DottedObjectName, Type, CaselessStrEnum, Bool,
21 Unicode, List, Instance, DottedObjectName, Type, CaselessStrEnum, Bool,
22 )
22 )
23 from IPython.utils.importstring import import_item
23 from IPython.utils.importstring import import_item
24
24
25 from .exporters.export import get_export_names, exporter_map
25 from .exporters.export import get_export_names, exporter_map
26 from IPython.nbconvert import exporters, preprocessors, writers, postprocessors
26 from IPython.nbconvert import exporters, preprocessors, writers, postprocessors
27 from .utils.base import NbConvertBase
27 from .utils.base import NbConvertBase
28 from .utils.exceptions import ConversionException
28 from .utils.exceptions import ConversionException
29
29
30 #-----------------------------------------------------------------------------
30 #-----------------------------------------------------------------------------
31 #Classes and functions
31 #Classes and functions
32 #-----------------------------------------------------------------------------
32 #-----------------------------------------------------------------------------
33
33
34 class DottedOrNone(DottedObjectName):
34 class DottedOrNone(DottedObjectName):
35 """
35 """
36 A string holding a valid dotted object name in Python, such as A.b3._c
36 A string holding a valid dotted object name in Python, such as A.b3._c
37 Also allows for None type."""
37 Also allows for None type."""
38
38
39 default_value = u''
39 default_value = u''
40
40
41 def validate(self, obj, value):
41 def validate(self, obj, value):
42 if value is not None and len(value) > 0:
42 if value is not None and len(value) > 0:
43 return super(DottedOrNone, self).validate(obj, value)
43 return super(DottedOrNone, self).validate(obj, value)
44 else:
44 else:
45 return value
45 return value
46
46
47 nbconvert_aliases = {}
47 nbconvert_aliases = {}
48 nbconvert_aliases.update(base_aliases)
48 nbconvert_aliases.update(base_aliases)
49 nbconvert_aliases.update({
49 nbconvert_aliases.update({
50 'to' : 'NbConvertApp.export_format',
50 'to' : 'NbConvertApp.export_format',
51 'template' : 'TemplateExporter.template_file',
51 'template' : 'TemplateExporter.template_file',
52 'writer' : 'NbConvertApp.writer_class',
52 'writer' : 'NbConvertApp.writer_class',
53 'post': 'NbConvertApp.postprocessor_class',
53 'post': 'NbConvertApp.postprocessor_class',
54 'output': 'NbConvertApp.output_base',
54 'output': 'NbConvertApp.output_base',
55 'reveal-prefix': 'RevealHelpPreprocessor.url_prefix',
55 'reveal-prefix': 'RevealHelpPreprocessor.url_prefix',
56 'nbformat': 'NotebookExporter.nbformat_version',
56 'nbformat': 'NotebookExporter.nbformat_version',
57 })
57 })
58
58
59 nbconvert_flags = {}
59 nbconvert_flags = {}
60 nbconvert_flags.update(base_flags)
60 nbconvert_flags.update(base_flags)
61 nbconvert_flags.update({
61 nbconvert_flags.update({
62 'execute' : (
62 'execute' : (
63 {'ExecutePreprocessor' : {'enabled' : True}},
63 {'ExecutePreprocessor' : {'enabled' : True}},
64 "Execute the notebook prior to export."
64 "Execute the notebook prior to export."
65 ),
65 ),
66 'stdout' : (
66 'stdout' : (
67 {'NbConvertApp' : {'writer_class' : "StdoutWriter"}},
67 {'NbConvertApp' : {'writer_class' : "StdoutWriter"}},
68 "Write notebook output to stdout instead of files."
68 "Write notebook output to stdout instead of files."
69 ),
69 ),
70 'inplace' : (
70 'inplace' : (
71 {
71 {
72 'NbConvertApp' : {'use_output_suffix' : False},
72 'NbConvertApp' : {'use_output_suffix' : False},
73 'FilesWriter': {'build_directory': ''}
73 'FilesWriter': {'build_directory': ''}
74 },
74 },
75 """Run nbconvert in place, overwriting the existing notebook (only
75 """Run nbconvert in place, overwriting the existing notebook (only
76 relevant when converting to notebook format)"""
76 relevant when converting to notebook format)"""
77 )
77 )
78 })
78 })
79
79
80
80
81 class NbConvertApp(BaseIPythonApplication):
81 class NbConvertApp(BaseIPythonApplication):
82 """Application used to convert from notebook file type (``*.ipynb``)"""
82 """Application used to convert from notebook file type (``*.ipynb``)"""
83
83
84 name = 'ipython-nbconvert'
84 name = 'ipython-nbconvert'
85 aliases = nbconvert_aliases
85 aliases = nbconvert_aliases
86 flags = nbconvert_flags
86 flags = nbconvert_flags
87
87
88 def _log_level_default(self):
88 def _log_level_default(self):
89 return logging.INFO
89 return logging.INFO
90
90
91 def _classes_default(self):
91 def _classes_default(self):
92 classes = [NbConvertBase, ProfileDir]
92 classes = [NbConvertBase, ProfileDir]
93 for pkg in (exporters, preprocessors, writers, postprocessors):
93 for pkg in (exporters, preprocessors, writers, postprocessors):
94 for name in dir(pkg):
94 for name in dir(pkg):
95 cls = getattr(pkg, name)
95 cls = getattr(pkg, name)
96 if isinstance(cls, type) and issubclass(cls, Configurable):
96 if isinstance(cls, type) and issubclass(cls, Configurable):
97 classes.append(cls)
97 classes.append(cls)
98
98
99 return classes
99 return classes
100
100
101 description = Unicode(
101 description = Unicode(
102 u"""This application is used to convert notebook files (*.ipynb)
102 u"""This application is used to convert notebook files (*.ipynb)
103 to various other formats.
103 to various other formats.
104
104
105 WARNING: THE COMMANDLINE INTERFACE MAY CHANGE IN FUTURE RELEASES.""")
105 WARNING: THE COMMANDLINE INTERFACE MAY CHANGE IN FUTURE RELEASES.""")
106
106
107 output_base = Unicode('', config=True, help='''overwrite base name use for output files.
107 output_base = Unicode('', config=True, help='''overwrite base name use for output files.
108 can only be used when converting one notebook at a time.
108 can only be used when converting one notebook at a time.
109 ''')
109 ''')
110
110
111 use_output_suffix = Bool(
111 use_output_suffix = Bool(
112 True,
112 True,
113 config=True,
113 config=True,
114 help="""Whether to apply a suffix prior to the extension (only relevant
114 help="""Whether to apply a suffix prior to the extension (only relevant
115 when converting to notebook format). The suffix is determined by
115 when converting to notebook format). The suffix is determined by
116 the exporter, and is usually '.nbconvert'.""")
116 the exporter, and is usually '.nbconvert'.""")
117
117
118 examples = Unicode(u"""
118 examples = Unicode(u"""
119 The simplest way to use nbconvert is
119 The simplest way to use nbconvert is
120
120
121 > ipython nbconvert mynotebook.ipynb
121 > ipython nbconvert mynotebook.ipynb
122
122
123 which will convert mynotebook.ipynb to the default format (probably HTML).
123 which will convert mynotebook.ipynb to the default format (probably HTML).
124
124
125 You can specify the export format with `--to`.
125 You can specify the export format with `--to`.
126 Options include {0}
126 Options include {0}
127
127
128 > ipython nbconvert --to latex mynotebook.ipynb
128 > ipython nbconvert --to latex mynotebook.ipynb
129
129
130 Both HTML and LaTeX support multiple output templates. LaTeX includes
130 Both HTML and LaTeX support multiple output templates. LaTeX includes
131 'base', 'article' and 'report'. HTML includes 'basic' and 'full'. You
131 'base', 'article' and 'report'. HTML includes 'basic' and 'full'. You
132 can specify the flavor of the format used.
132 can specify the flavor of the format used.
133
133
134 > ipython nbconvert --to html --template basic mynotebook.ipynb
134 > ipython nbconvert --to html --template basic mynotebook.ipynb
135
135
136 You can also pipe the output to stdout, rather than a file
136 You can also pipe the output to stdout, rather than a file
137
137
138 > ipython nbconvert mynotebook.ipynb --stdout
138 > ipython nbconvert mynotebook.ipynb --stdout
139
139
140 PDF is generated via latex
140 PDF is generated via latex
141
141
142 > ipython nbconvert mynotebook.ipynb --to pdf
142 > ipython nbconvert mynotebook.ipynb --to pdf
143
143
144 You can get (and serve) a Reveal.js-powered slideshow
144 You can get (and serve) a Reveal.js-powered slideshow
145
145
146 > ipython nbconvert myslides.ipynb --to slides --post serve
146 > ipython nbconvert myslides.ipynb --to slides --post serve
147
147
148 Multiple notebooks can be given at the command line in a couple of
148 Multiple notebooks can be given at the command line in a couple of
149 different ways:
149 different ways:
150
150
151 > ipython nbconvert notebook*.ipynb
151 > ipython nbconvert notebook*.ipynb
152 > ipython nbconvert notebook1.ipynb notebook2.ipynb
152 > ipython nbconvert notebook1.ipynb notebook2.ipynb
153
153
154 or you can specify the notebooks list in a config file, containing::
154 or you can specify the notebooks list in a config file, containing::
155
155
156 c.NbConvertApp.notebooks = ["my_notebook.ipynb"]
156 c.NbConvertApp.notebooks = ["my_notebook.ipynb"]
157
157
158 > ipython nbconvert --config mycfg.py
158 > ipython nbconvert --config mycfg.py
159 """.format(get_export_names()))
159 """.format(get_export_names()))
160
160
161 # Writer specific variables
161 # Writer specific variables
162 writer = Instance('IPython.nbconvert.writers.base.WriterBase',
162 writer = Instance('IPython.nbconvert.writers.base.WriterBase',
163 help="""Instance of the writer class used to write the
163 help="""Instance of the writer class used to write the
164 results of the conversion.""")
164 results of the conversion.""")
165 writer_class = DottedObjectName('FilesWriter', config=True,
165 writer_class = DottedObjectName('FilesWriter', config=True,
166 help="""Writer class used to write the
166 help="""Writer class used to write the
167 results of the conversion""")
167 results of the conversion""")
168 writer_aliases = {'fileswriter': 'IPython.nbconvert.writers.files.FilesWriter',
168 writer_aliases = {'fileswriter': 'IPython.nbconvert.writers.files.FilesWriter',
169 'debugwriter': 'IPython.nbconvert.writers.debug.DebugWriter',
169 'debugwriter': 'IPython.nbconvert.writers.debug.DebugWriter',
170 'stdoutwriter': 'IPython.nbconvert.writers.stdout.StdoutWriter'}
170 'stdoutwriter': 'IPython.nbconvert.writers.stdout.StdoutWriter'}
171 writer_factory = Type()
171 writer_factory = Type()
172
172
173 def _writer_class_changed(self, name, old, new):
173 def _writer_class_changed(self, name, old, new):
174 if new.lower() in self.writer_aliases:
174 if new.lower() in self.writer_aliases:
175 new = self.writer_aliases[new.lower()]
175 new = self.writer_aliases[new.lower()]
176 self.writer_factory = import_item(new)
176 self.writer_factory = import_item(new)
177
177
178 # Post-processor specific variables
178 # Post-processor specific variables
179 postprocessor = Instance('IPython.nbconvert.postprocessors.base.PostProcessorBase',
179 postprocessor = Instance('IPython.nbconvert.postprocessors.base.PostProcessorBase',
180 help="""Instance of the PostProcessor class used to write the
180 help="""Instance of the PostProcessor class used to write the
181 results of the conversion.""")
181 results of the conversion.""")
182
182
183 postprocessor_class = DottedOrNone(config=True,
183 postprocessor_class = DottedOrNone(config=True,
184 help="""PostProcessor class used to write the
184 help="""PostProcessor class used to write the
185 results of the conversion""")
185 results of the conversion""")
186 postprocessor_aliases = {'serve': 'IPython.nbconvert.postprocessors.serve.ServePostProcessor'}
186 postprocessor_aliases = {'serve': 'IPython.nbconvert.postprocessors.serve.ServePostProcessor'}
187 postprocessor_factory = Type()
187 postprocessor_factory = Type()
188
188
189 def _postprocessor_class_changed(self, name, old, new):
189 def _postprocessor_class_changed(self, name, old, new):
190 if new.lower() in self.postprocessor_aliases:
190 if new.lower() in self.postprocessor_aliases:
191 new = self.postprocessor_aliases[new.lower()]
191 new = self.postprocessor_aliases[new.lower()]
192 if new:
192 if new:
193 self.postprocessor_factory = import_item(new)
193 self.postprocessor_factory = import_item(new)
194
194
195
195
196 # Other configurable variables
196 # Other configurable variables
197 export_format = CaselessStrEnum(get_export_names(),
197 export_format = CaselessStrEnum(get_export_names(),
198 default_value="html",
198 default_value="html",
199 config=True,
199 config=True,
200 help="""The export format to be used."""
200 help="""The export format to be used."""
201 )
201 )
202
202
203 notebooks = List([], config=True, help="""List of notebooks to convert.
203 notebooks = List([], config=True, help="""List of notebooks to convert.
204 Wildcards are supported.
204 Wildcards are supported.
205 Filenames passed positionally will be added to the list.
205 Filenames passed positionally will be added to the list.
206 """)
206 """)
207
207
208 @catch_config_error
208 @catch_config_error
209 def initialize(self, argv=None):
209 def initialize(self, argv=None):
210 self.init_syspath()
210 self.init_syspath()
211 super(NbConvertApp, self).initialize(argv)
211 super(NbConvertApp, self).initialize(argv)
212 self.init_notebooks()
212 self.init_notebooks()
213 self.init_writer()
213 self.init_writer()
214 self.init_postprocessor()
214 self.init_postprocessor()
215
215
216
216
217
217
218 def init_syspath(self):
218 def init_syspath(self):
219 """
219 """
220 Add the cwd to the sys.path ($PYTHONPATH)
220 Add the cwd to the sys.path ($PYTHONPATH)
221 """
221 """
222 sys.path.insert(0, os.getcwd())
222 sys.path.insert(0, os.getcwd())
223
223
224
224
225 def init_notebooks(self):
225 def init_notebooks(self):
226 """Construct the list of notebooks.
226 """Construct the list of notebooks.
227 If notebooks are passed on the command-line,
227 If notebooks are passed on the command-line,
228 they override notebooks specified in config files.
228 they override notebooks specified in config files.
229 Glob each notebook to replace notebook patterns with filenames.
229 Glob each notebook to replace notebook patterns with filenames.
230 """
230 """
231
231
232 # Specifying notebooks on the command-line overrides (rather than adds)
232 # Specifying notebooks on the command-line overrides (rather than adds)
233 # the notebook list
233 # the notebook list
234 if self.extra_args:
234 if self.extra_args:
235 patterns = self.extra_args
235 patterns = self.extra_args
236 else:
236 else:
237 patterns = self.notebooks
237 patterns = self.notebooks
238
238
239 # Use glob to replace all the notebook patterns with filenames.
239 # Use glob to replace all the notebook patterns with filenames.
240 filenames = []
240 filenames = []
241 for pattern in patterns:
241 for pattern in patterns:
242
242
243 # Use glob to find matching filenames. Allow the user to convert
243 # Use glob to find matching filenames. Allow the user to convert
244 # notebooks without having to type the extension.
244 # notebooks without having to type the extension.
245 globbed_files = glob.glob(pattern)
245 globbed_files = glob.glob(pattern)
246 globbed_files.extend(glob.glob(pattern + '.ipynb'))
246 globbed_files.extend(glob.glob(pattern + '.ipynb'))
247 if not globbed_files:
247 if not globbed_files:
248 self.log.warn("pattern %r matched no files", pattern)
248 self.log.warn("pattern %r matched no files", pattern)
249
249
250 for filename in globbed_files:
250 for filename in globbed_files:
251 if not filename in filenames:
251 if not filename in filenames:
252 filenames.append(filename)
252 filenames.append(filename)
253 self.notebooks = filenames
253 self.notebooks = filenames
254
254
255 def init_writer(self):
255 def init_writer(self):
256 """
256 """
257 Initialize the writer (which is stateless)
257 Initialize the writer (which is stateless)
258 """
258 """
259 self._writer_class_changed(None, self.writer_class, self.writer_class)
259 self._writer_class_changed(None, self.writer_class, self.writer_class)
260 self.writer = self.writer_factory(parent=self)
260 self.writer = self.writer_factory(parent=self)
261 if hasattr(self.writer, 'build_directory') and self.writer.build_directory != '':
261 if hasattr(self.writer, 'build_directory') and self.writer.build_directory != '':
262 self.use_output_suffix = False
262 self.use_output_suffix = False
263
263
264 def init_postprocessor(self):
264 def init_postprocessor(self):
265 """
265 """
266 Initialize the postprocessor (which is stateless)
266 Initialize the postprocessor (which is stateless)
267 """
267 """
268 self._postprocessor_class_changed(None, self.postprocessor_class,
268 self._postprocessor_class_changed(None, self.postprocessor_class,
269 self.postprocessor_class)
269 self.postprocessor_class)
270 if self.postprocessor_factory:
270 if self.postprocessor_factory:
271 self.postprocessor = self.postprocessor_factory(parent=self)
271 self.postprocessor = self.postprocessor_factory(parent=self)
272
272
273 def start(self):
273 def start(self):
274 """
274 """
275 Ran after initialization completed
275 Ran after initialization completed
276 """
276 """
277 super(NbConvertApp, self).start()
277 super(NbConvertApp, self).start()
278 self.convert_notebooks()
278 self.convert_notebooks()
279
279
280 def init_single_notebook_resources(self, notebook_filename):
281 """Step 1: Initialize resources
282
283 This intializes the resources dictionary for a single notebook. This
284 method should return the resources dictionary, and MUST include the
285 following keys:
286
287 - profile_dir: the location of the profile directory
288 - unique_key: the notebook name
289 - output_files_dir: a directory where output files (not including
290 the notebook itself) should be saved
291
292 """
293
294 # Get a unique key for the notebook and set it in the resources object.
295 basename = os.path.basename(notebook_filename)
296 notebook_name = basename[:basename.rfind('.')]
297 if self.output_base:
298 # strip duplicate extension from output_base, to avoid Basname.ext.ext
299 if getattr(self.exporter, 'file_extension', False):
300 base, ext = os.path.splitext(self.output_base)
301 if ext == self.exporter.file_extension:
302 self.output_base = base
303 notebook_name = self.output_base
304
305 self.log.debug("Notebook name is '%s'", notebook_name)
306
307 # first initialize the resources we want to use
308 resources = {}
309 resources['profile_dir'] = self.profile_dir.location
310 resources['unique_key'] = notebook_name
311 resources['output_files_dir'] = '%s_files' % notebook_name
312
313 return resources
314
315 def export_single_notebook(self, notebook_filename, resources):
316 """Step 2: Export the notebook
317
318 Exports the notebook to a particular format according to the specified
319 exporter. This function returns the output and (possibly modified)
320 resources from the exporter.
321
322 """
323 try:
324 output, resources = self.exporter.from_filename(notebook_filename, resources=resources)
325 except ConversionException:
326 self.log.error("Error while converting '%s'", notebook_filename, exc_info=True)
327 self.exit(1)
328
329 return output, resources
330
331 def write_single_notebook(self, output, resources):
332 """Step 3: Write the notebook to file
333
334 This writes output from the exporter to file using the specified writer.
335 It returns the results from the writer.
336
337 """
338 if 'unique_key' not in resources:
339 raise KeyError("unique_key MUST be specified in the resources, but it is not")
340
341 notebook_name = resources['unique_key']
342 if self.use_output_suffix and not self.output_base:
343 notebook_name += resources.get('output_suffix', '')
344
345 write_results = self.writer.write(
346 output, resources, notebook_name=notebook_name)
347 return write_results
348
349 def postprocess_single_notebook(self, write_results):
350 """Step 4: Postprocess the notebook
351
352 This postprocesses the notebook after it has been written, taking as an
353 argument the results of writing the notebook to file. This only actually
354 does anything if a postprocessor has actually been specified.
355
356 """
357 # Post-process if post processor has been defined.
358 if hasattr(self, 'postprocessor') and self.postprocessor:
359 self.postprocessor(write_results)
360
361 def convert_single_notebook(self, notebook_filename):
362 """Convert a single notebook. Performs the following steps:
363
364 1. Initialize notebook resources
365 2. Export the notebook to a particular format
366 3. Write the exported notebook to file
367 4. (Maybe) postprocess the written file
368
369 """
370 self.log.info("Converting notebook %s to %s", notebook_filename, self.export_format)
371 resources = self.init_single_notebook_resources(notebook_filename)
372 output, resources = self.export_single_notebook(notebook_filename, resources)
373 write_results = self.write_single_notebook(output, resources)
374 self.postprocess_single_notebook(write_results)
375
280 def convert_notebooks(self):
376 def convert_notebooks(self):
281 """
377 """
282 Convert the notebooks in the self.notebook traitlet
378 Convert the notebooks in the self.notebook traitlet
283 """
379 """
284 # Export each notebook
380 # check that the output base isn't specified if there is more than
285 conversion_success = 0
381 # one notebook to convert
286
287 if self.output_base != '' and len(self.notebooks) > 1:
382 if self.output_base != '' and len(self.notebooks) > 1:
288 self.log.error(
383 self.log.error(
289 """UsageError: --output flag or `NbConvertApp.output_base` config option
384 """
290 cannot be used when converting multiple notebooks.
385 UsageError: --output flag or `NbConvertApp.output_base` config option
291 """)
386 cannot be used when converting multiple notebooks.
387 """
388 )
292 self.exit(1)
389 self.exit(1)
293
390
294 exporter = exporter_map[self.export_format](config=self.config)
391 # initialize the exporter
392 self.exporter = exporter_map[self.export_format](config=self.config)
295
393
296 for notebook_filename in self.notebooks:
394 # no notebooks to convert!
297 self.log.info("Converting notebook %s to %s", notebook_filename, self.export_format)
395 if len(self.notebooks) == 0:
298
299 # Get a unique key for the notebook and set it in the resources object.
300 basename = os.path.basename(notebook_filename)
301 notebook_name = basename[:basename.rfind('.')]
302 if self.output_base:
303 # strip duplicate extension from output_base, to avoid Basname.ext.ext
304 if getattr(exporter, 'file_extension', False):
305 base, ext = os.path.splitext(self.output_base)
306 if ext == exporter.file_extension:
307 self.output_base = base
308 notebook_name = self.output_base
309 resources = {}
310 resources['profile_dir'] = self.profile_dir.location
311 resources['unique_key'] = notebook_name
312 resources['output_files_dir'] = '%s_files' % notebook_name
313
314 # Try to export
315 try:
316 output, resources = exporter.from_filename(notebook_filename, resources=resources)
317 except ConversionException as e:
318 self.log.error("Error while converting '%s'", notebook_filename,
319 exc_info=True)
320 self.exit(1)
321 else:
322 if self.use_output_suffix and 'output_suffix' in resources and not self.output_base:
323 notebook_name += resources['output_suffix']
324 write_results = self.writer.write(output, resources, notebook_name=notebook_name)
325
326 #Post-process if post processor has been defined.
327 if hasattr(self, 'postprocessor') and self.postprocessor:
328 self.postprocessor(write_results)
329 conversion_success += 1
330
331 # If nothing was converted successfully, help the user.
332 if conversion_success == 0:
333 self.print_help()
396 self.print_help()
334 sys.exit(-1)
397 sys.exit(-1)
398
399 # convert each notebook
400 for notebook_filename in self.notebooks:
401 self.convert_single_notebook(notebook_filename)
335
402
336 #-----------------------------------------------------------------------------
403 #-----------------------------------------------------------------------------
337 # Main entry point
404 # Main entry point
338 #-----------------------------------------------------------------------------
405 #-----------------------------------------------------------------------------
339
406
340 launch_new_instance = NbConvertApp.launch_instance
407 launch_new_instance = NbConvertApp.launch_instance
General Comments 0
You need to be logged in to leave comments. Login now