##// END OF EJS Templates
Backport PR #5704: Update nbconvertapp.py...
Thomas Kluyver -
Show More
@@ -1,323 +1,323 b''
1 1 #!/usr/bin/env python
2 2 """NBConvert is a utility for conversion of .ipynb files.
3 3
4 4 Command-line interface for the NbConvert conversion utility.
5 5 """
6 6 #-----------------------------------------------------------------------------
7 7 #Copyright (c) 2013, the IPython Development Team.
8 8 #
9 9 #Distributed under the terms of the Modified BSD License.
10 10 #
11 11 #The full license is in the file COPYING.txt, distributed with this software.
12 12 #-----------------------------------------------------------------------------
13 13
14 14 #-----------------------------------------------------------------------------
15 15 #Imports
16 16 #-----------------------------------------------------------------------------
17 17
18 18 # Stdlib imports
19 19 from __future__ import print_function
20 20
21 21 import logging
22 22 import sys
23 23 import os
24 24 import glob
25 25
26 26 # From IPython
27 27 from IPython.core.application import BaseIPythonApplication, base_aliases, base_flags
28 28 from IPython.core.profiledir import ProfileDir
29 29 from IPython.config import catch_config_error, Configurable
30 30 from IPython.utils.traitlets import (
31 31 Unicode, List, Instance, DottedObjectName, Type, CaselessStrEnum,
32 32 )
33 33 from IPython.utils.importstring import import_item
34 34 from IPython.utils.text import dedent
35 35
36 36 from .exporters.export import get_export_names, exporter_map
37 37 from IPython.nbconvert import exporters, preprocessors, writers, postprocessors
38 38 from .utils.base import NbConvertBase
39 39 from .utils.exceptions import ConversionException
40 40
41 41 #-----------------------------------------------------------------------------
42 42 #Classes and functions
43 43 #-----------------------------------------------------------------------------
44 44
45 45 class DottedOrNone(DottedObjectName):
46 46 """
47 47 A string holding a valid dotted object name in Python, such as A.b3._c
48 48 Also allows for None type."""
49 49
50 50 default_value = u''
51 51
52 52 def validate(self, obj, value):
53 53 if value is not None and len(value) > 0:
54 54 return super(DottedOrNone, self).validate(obj, value)
55 55 else:
56 56 return value
57 57
58 58 nbconvert_aliases = {}
59 59 nbconvert_aliases.update(base_aliases)
60 60 nbconvert_aliases.update({
61 61 'to' : 'NbConvertApp.export_format',
62 62 'template' : 'TemplateExporter.template_file',
63 63 'writer' : 'NbConvertApp.writer_class',
64 64 'post': 'NbConvertApp.postprocessor_class',
65 65 'output': 'NbConvertApp.output_base',
66 66 'reveal-prefix': 'RevealHelpPreprocessor.url_prefix',
67 67 })
68 68
69 69 nbconvert_flags = {}
70 70 nbconvert_flags.update(base_flags)
71 71 nbconvert_flags.update({
72 72 'stdout' : (
73 73 {'NbConvertApp' : {'writer_class' : "StdoutWriter"}},
74 74 "Write notebook output to stdout instead of files."
75 75 )
76 76 })
77 77
78 78
79 79 class NbConvertApp(BaseIPythonApplication):
80 80 """Application used to convert from notebook file type (``*.ipynb``)"""
81 81
82 82 name = 'ipython-nbconvert'
83 83 aliases = nbconvert_aliases
84 84 flags = nbconvert_flags
85 85
86 86 def _log_level_default(self):
87 87 return logging.INFO
88 88
89 89 def _classes_default(self):
90 90 classes = [NbConvertBase, ProfileDir]
91 91 for pkg in (exporters, preprocessors, writers, postprocessors):
92 92 for name in dir(pkg):
93 93 cls = getattr(pkg, name)
94 94 if isinstance(cls, type) and issubclass(cls, Configurable):
95 95 classes.append(cls)
96 96
97 97 return classes
98 98
99 99 description = Unicode(
100 100 u"""This application is used to convert notebook files (*.ipynb)
101 101 to various other formats.
102 102
103 103 WARNING: THE COMMANDLINE INTERFACE MAY CHANGE IN FUTURE RELEASES.""")
104 104
105 105 output_base = Unicode('', config=True, help='''overwrite base name use for output files.
106 106 can only be use when converting one notebook at a time.
107 107 ''')
108 108
109 109 examples = Unicode(u"""
110 110 The simplest way to use nbconvert is
111 111
112 112 > ipython nbconvert mynotebook.ipynb
113 113
114 114 which will convert mynotebook.ipynb to the default format (probably HTML).
115 115
116 116 You can specify the export format with `--to`.
117 117 Options include {0}
118 118
119 > ipython nbconvert --to latex mynotebook.ipnynb
119 > ipython nbconvert --to latex mynotebook.ipynb
120 120
121 121 Both HTML and LaTeX support multiple output templates. LaTeX includes
122 122 'basic', 'book', and 'article'. HTML includes 'basic' and 'full'. You
123 123 can specify the flavor of the format used.
124 124
125 125 > ipython nbconvert --to html --template basic mynotebook.ipynb
126 126
127 127 You can also pipe the output to stdout, rather than a file
128 128
129 129 > ipython nbconvert mynotebook.ipynb --stdout
130 130
131 131 A post-processor can be used to compile a PDF
132 132
133 133 > ipython nbconvert mynotebook.ipynb --to latex --post PDF
134 134
135 135 You can get (and serve) a Reveal.js-powered slideshow
136 136
137 137 > ipython nbconvert myslides.ipynb --to slides --post serve
138 138
139 139 Multiple notebooks can be given at the command line in a couple of
140 140 different ways:
141 141
142 142 > ipython nbconvert notebook*.ipynb
143 143 > ipython nbconvert notebook1.ipynb notebook2.ipynb
144 144
145 145 or you can specify the notebooks list in a config file, containing::
146 146
147 147 c.NbConvertApp.notebooks = ["my_notebook.ipynb"]
148 148
149 149 > ipython nbconvert --config mycfg.py
150 150 """.format(get_export_names()))
151 151
152 152 # Writer specific variables
153 153 writer = Instance('IPython.nbconvert.writers.base.WriterBase',
154 154 help="""Instance of the writer class used to write the
155 155 results of the conversion.""")
156 156 writer_class = DottedObjectName('FilesWriter', config=True,
157 157 help="""Writer class used to write the
158 158 results of the conversion""")
159 159 writer_aliases = {'fileswriter': 'IPython.nbconvert.writers.files.FilesWriter',
160 160 'debugwriter': 'IPython.nbconvert.writers.debug.DebugWriter',
161 161 'stdoutwriter': 'IPython.nbconvert.writers.stdout.StdoutWriter'}
162 162 writer_factory = Type()
163 163
164 164 def _writer_class_changed(self, name, old, new):
165 165 if new.lower() in self.writer_aliases:
166 166 new = self.writer_aliases[new.lower()]
167 167 self.writer_factory = import_item(new)
168 168
169 169 # Post-processor specific variables
170 170 postprocessor = Instance('IPython.nbconvert.postprocessors.base.PostProcessorBase',
171 171 help="""Instance of the PostProcessor class used to write the
172 172 results of the conversion.""")
173 173
174 174 postprocessor_class = DottedOrNone(config=True,
175 175 help="""PostProcessor class used to write the
176 176 results of the conversion""")
177 177 postprocessor_aliases = {'pdf': 'IPython.nbconvert.postprocessors.pdf.PDFPostProcessor',
178 178 'serve': 'IPython.nbconvert.postprocessors.serve.ServePostProcessor'}
179 179 postprocessor_factory = Type()
180 180
181 181 def _postprocessor_class_changed(self, name, old, new):
182 182 if new.lower() in self.postprocessor_aliases:
183 183 new = self.postprocessor_aliases[new.lower()]
184 184 if new:
185 185 self.postprocessor_factory = import_item(new)
186 186
187 187
188 188 # Other configurable variables
189 189 export_format = CaselessStrEnum(get_export_names(),
190 190 default_value="html",
191 191 config=True,
192 192 help="""The export format to be used."""
193 193 )
194 194
195 195 notebooks = List([], config=True, help="""List of notebooks to convert.
196 196 Wildcards are supported.
197 197 Filenames passed positionally will be added to the list.
198 198 """)
199 199
200 200 @catch_config_error
201 201 def initialize(self, argv=None):
202 202 self.init_syspath()
203 203 super(NbConvertApp, self).initialize(argv)
204 204 self.init_notebooks()
205 205 self.init_writer()
206 206 self.init_postprocessor()
207 207
208 208
209 209
210 210 def init_syspath(self):
211 211 """
212 212 Add the cwd to the sys.path ($PYTHONPATH)
213 213 """
214 214 sys.path.insert(0, os.getcwd())
215 215
216 216
217 217 def init_notebooks(self):
218 218 """Construct the list of notebooks.
219 219 If notebooks are passed on the command-line,
220 220 they override notebooks specified in config files.
221 221 Glob each notebook to replace notebook patterns with filenames.
222 222 """
223 223
224 224 # Specifying notebooks on the command-line overrides (rather than adds)
225 225 # the notebook list
226 226 if self.extra_args:
227 227 patterns = self.extra_args
228 228 else:
229 229 patterns = self.notebooks
230 230
231 231 # Use glob to replace all the notebook patterns with filenames.
232 232 filenames = []
233 233 for pattern in patterns:
234 234
235 235 # Use glob to find matching filenames. Allow the user to convert
236 236 # notebooks without having to type the extension.
237 237 globbed_files = glob.glob(pattern)
238 238 globbed_files.extend(glob.glob(pattern + '.ipynb'))
239 239 if not globbed_files:
240 240 self.log.warn("pattern %r matched no files", pattern)
241 241
242 242 for filename in globbed_files:
243 243 if not filename in filenames:
244 244 filenames.append(filename)
245 245 self.notebooks = filenames
246 246
247 247 def init_writer(self):
248 248 """
249 249 Initialize the writer (which is stateless)
250 250 """
251 251 self._writer_class_changed(None, self.writer_class, self.writer_class)
252 252 self.writer = self.writer_factory(parent=self)
253 253
254 254 def init_postprocessor(self):
255 255 """
256 256 Initialize the postprocessor (which is stateless)
257 257 """
258 258 self._postprocessor_class_changed(None, self.postprocessor_class,
259 259 self.postprocessor_class)
260 260 if self.postprocessor_factory:
261 261 self.postprocessor = self.postprocessor_factory(parent=self)
262 262
263 263 def start(self):
264 264 """
265 265 Ran after initialization completed
266 266 """
267 267 super(NbConvertApp, self).start()
268 268 self.convert_notebooks()
269 269
270 270 def convert_notebooks(self):
271 271 """
272 272 Convert the notebooks in the self.notebook traitlet
273 273 """
274 274 # Export each notebook
275 275 conversion_success = 0
276 276
277 277 if self.output_base != '' and len(self.notebooks) > 1:
278 278 self.log.error(
279 279 """UsageError: --output flag or `NbConvertApp.output_base` config option
280 280 cannot be used when converting multiple notebooks.
281 281 """)
282 282 self.exit(1)
283 283
284 284 exporter = exporter_map[self.export_format](config=self.config)
285 285
286 286 for notebook_filename in self.notebooks:
287 287 self.log.info("Converting notebook %s to %s", notebook_filename, self.export_format)
288 288
289 289 # Get a unique key for the notebook and set it in the resources object.
290 290 basename = os.path.basename(notebook_filename)
291 291 notebook_name = basename[:basename.rfind('.')]
292 292 if self.output_base:
293 293 notebook_name = self.output_base
294 294 resources = {}
295 295 resources['unique_key'] = notebook_name
296 296 resources['output_files_dir'] = '%s_files' % notebook_name
297 297 self.log.info("Support files will be in %s", os.path.join(resources['output_files_dir'], ''))
298 298
299 299 # Try to export
300 300 try:
301 301 output, resources = exporter.from_filename(notebook_filename, resources=resources)
302 302 except ConversionException as e:
303 303 self.log.error("Error while converting '%s'", notebook_filename,
304 304 exc_info=True)
305 305 self.exit(1)
306 306 else:
307 307 write_resultes = self.writer.write(output, resources, notebook_name=notebook_name)
308 308
309 309 #Post-process if post processor has been defined.
310 310 if hasattr(self, 'postprocessor') and self.postprocessor:
311 311 self.postprocessor(write_resultes)
312 312 conversion_success += 1
313 313
314 314 # If nothing was converted successfully, help the user.
315 315 if conversion_success == 0:
316 316 self.print_help()
317 317 sys.exit(-1)
318 318
319 319 #-----------------------------------------------------------------------------
320 320 # Main entry point
321 321 #-----------------------------------------------------------------------------
322 322
323 323 launch_new_instance = NbConvertApp.launch_instance
General Comments 0
You need to be logged in to leave comments. Login now