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