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