##// END OF EJS Templates
warn on glob with no matches
MinRK -
Show More
@@ -1,328 +1,330
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 export_by_name, get_export_names, ExporterNameError
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 157 writer_aliases = {'FilesWriter': 'IPython.nbconvert.writers.files.FilesWriter',
158 158 'DebugWriter': 'IPython.nbconvert.writers.debug.DebugWriter',
159 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 163 if new in self.writer_aliases:
164 164 new = self.writer_aliases[new]
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 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 180 if new in self.post_processor_aliases:
181 181 new = self.post_processor_aliases[new]
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 if not globbed_files:
238 self.log.warn("pattern %r matched no files", pattern)
237 239
238 240 for filename in globbed_files:
239 241 if not filename in filenames:
240 242 filenames.append(filename)
241 243 self.notebooks = filenames
242 244
243 245 def init_writer(self):
244 246 """
245 247 Initialize the writer (which is stateless)
246 248 """
247 249 self._writer_class_changed(None, self.writer_class, self.writer_class)
248 250 self.writer = self.writer_factory(parent=self)
249 251
250 252 def init_post_processor(self):
251 253 """
252 254 Initialize the post_processor (which is stateless)
253 255 """
254 256 self._post_processor_class_changed(None, self.post_processor_class,
255 257 self.post_processor_class)
256 258 if self.post_processor_factory:
257 259 self.post_processor = self.post_processor_factory(parent=self)
258 260
259 261 def start(self):
260 262 """
261 263 Ran after initialization completed
262 264 """
263 265 super(NbConvertApp, self).start()
264 266 self.convert_notebooks()
265 267
266 268 def convert_notebooks(self):
267 269 """
268 270 Convert the notebooks in the self.notebook traitlet
269 271 """
270 272 # Export each notebook
271 273 conversion_success = 0
272 274
273 275 if self.output_base != '' and len(self.notebooks) > 1:
274 276 print(dedent(
275 277 """UsageError: --output flag or `NbConvertApp.output_base` config option
276 278 cannot be used when converting multiple notebooks.
277 279 """))
278 280 self.exit(1)
279 281
280 282 for notebook_filename in self.notebooks:
281 283 self.log.info("Converting notebook %s to %s", notebook_filename, self.export_format)
282 284
283 285 # Get a unique key for the notebook and set it in the resources object.
284 286 basename = os.path.basename(notebook_filename)
285 287 notebook_name = basename[:basename.rfind('.')]
286 288 if self.output_base:
287 289 notebook_name = self.output_base
288 290 resources = {}
289 291 resources['unique_key'] = notebook_name
290 292 resources['output_files_dir'] = '%s_files' % notebook_name
291 293 self.log.info("Support files will be in %s", os.path.join(resources['output_files_dir'], ''))
292 294
293 295 # Try to export
294 296 try:
295 297 output, resources = export_by_name(self.export_format,
296 298 notebook_filename,
297 299 resources=resources,
298 300 config=self.config)
299 301 except ExporterNameError as e:
300 302 print("Error while converting '%s': '%s' exporter not found."
301 303 %(notebook_filename, self.export_format),
302 304 file=sys.stderr)
303 305 print("Known exporters are:",
304 306 "\n\t" + "\n\t".join(get_export_names()),
305 307 file=sys.stderr)
306 308 self.exit(1)
307 309 except ConversionException as e:
308 310 print("Error while converting '%s': %s" %(notebook_filename, e),
309 311 file=sys.stderr)
310 312 self.exit(1)
311 313 else:
312 314 write_resultes = self.writer.write(output, resources, notebook_name=notebook_name)
313 315
314 316 #Post-process if post processor has been defined.
315 317 if hasattr(self, 'post_processor') and self.post_processor:
316 318 self.post_processor(write_resultes)
317 319 conversion_success += 1
318 320
319 321 # If nothing was converted successfully, help the user.
320 322 if conversion_success == 0:
321 323 self.print_help()
322 324 sys.exit(-1)
323 325
324 326 #-----------------------------------------------------------------------------
325 327 # Main entry point
326 328 #-----------------------------------------------------------------------------
327 329
328 330 launch_new_instance = NbConvertApp.launch_instance
General Comments 0
You need to be logged in to leave comments. Login now