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