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