##// END OF EJS Templates
Merge pull request #3784 from jdfreder/export_flavors...
Jonathan Frederic -
r11769:a9c0f491 merge
parent child Browse files
Show More
@@ -0,0 +1,2 b''
1 from .base import PostProcessorBase
2 from .pdf import PDFPostProcessor
@@ -0,0 +1,51 b''
1 """
2 Contains writer for writing nbconvert output to PDF.
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 subprocess
17 import os
18
19 from IPython.utils.traitlets import Integer, Unicode, Bool
20
21 from .base import PostProcessorBase
22
23 #-----------------------------------------------------------------------------
24 # Classes
25 #-----------------------------------------------------------------------------
26 class PDFPostProcessor(PostProcessorBase):
27 """Writer designed to write to PDF files"""
28
29 iteration_count = Integer(3, config=True, help="""
30 How many times pdflatex will be called.
31 """)
32
33 compiler = Unicode(u'pdflatex {0}', config=True, help="""
34 Shell command used to compile PDF.""")
35
36 verbose = Bool(False, config=True, help="""
37 Whether or not to display the output of the compile call.
38 """)
39
40 def call(self, input):
41 """
42 Consume and write Jinja output a PDF.
43 See files.py for more...
44 """
45 command = self.compiler.format(input)
46 for index in range(self.iteration_count):
47 if self.verbose:
48 subprocess.Popen(command, shell=True)
49 else:
50 with open(os.devnull, 'wb') as null:
51 subprocess.Popen(command, shell=True, stdout=null)
@@ -1,6 +1,7 b''
1 1 """Utilities for converting notebooks to and from different formats."""
2 2
3 3 from .exporters import *
4 4 import filters
5 5 import transformers
6 import post_processors
6 7 import writers
@@ -1,11 +1,8 b''
1 from .basichtml import BasicHTMLExporter
2 1 from .export import *
2 from .html import HTMLExporter
3 from .slides import SlidesExporter
3 4 from .exporter import Exporter
4 from .fullhtml import FullHTMLExporter
5 from .reveal import RevealExporter
6 5 from .latex import LatexExporter
7 6 from .markdown import MarkdownExporter
8 7 from .python import PythonExporter
9 8 from .rst import RSTExporter
10 from .sphinx_howto import SphinxHowtoExporter
11 from .sphinx_manual import SphinxManualExporter
@@ -1,226 +1,211 b''
1 1 """
2 2 Module containing single call export functions.
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 from functools import wraps
17 17
18 18 from IPython.nbformat.v3.nbbase import NotebookNode
19 19 from IPython.config import Config
20 20
21 21 from .exporter import Exporter
22 from .basichtml import BasicHTMLExporter
23 from .fullhtml import FullHTMLExporter
22 from .html import HTMLExporter
23 from .slides import SlidesExporter
24 24 from .latex import LatexExporter
25 25 from .markdown import MarkdownExporter
26 26 from .python import PythonExporter
27 from .reveal import RevealExporter
28 27 from .rst import RSTExporter
29 from .sphinx_howto import SphinxHowtoExporter
30 from .sphinx_manual import SphinxManualExporter
31 28
32 29 #-----------------------------------------------------------------------------
33 30 # Classes
34 31 #-----------------------------------------------------------------------------
35 32
36 33 def DocDecorator(f):
37 34
38 35 #Set docstring of function
39 36 f.__doc__ = f.__doc__ + """
40 37 nb : Notebook node
41 38 config : config (optional, keyword arg)
42 39 User configuration instance.
43 40 resources : dict (optional, keyword arg)
44 41 Resources used in the conversion process.
45 42
46 43 Returns
47 44 ----------
48 45 tuple- output, resources, exporter_instance
49 46 output : str
50 47 Jinja 2 output. This is the resulting converted notebook.
51 48 resources : dictionary
52 49 Dictionary of resources used prior to and during the conversion
53 50 process.
54 51 exporter_instance : Exporter
55 52 Instance of the Exporter class used to export the document. Useful
56 53 to caller because it provides a 'file_extension' property which
57 specifies what extension the output should be saved as."""
54 specifies what extension the output should be saved as.
55
56 WARNING: API WILL CHANGE IN FUTURE RELEASES OF NBCONVERT
57 """
58 58
59 59 @wraps(f)
60 60 def decorator(*args, **kwargs):
61 61 return f(*args, **kwargs)
62 62
63 63 return decorator
64 64
65 65
66 66 #-----------------------------------------------------------------------------
67 67 # Functions
68 68 #-----------------------------------------------------------------------------
69 69
70 70 __all__ = [
71 71 'export',
72 'export_sphinx_manual',
73 'export_sphinx_howto',
74 'export_basic_html',
75 'export_full_html',
72 'export_html',
73 'export_custom',
74 'export_slides',
76 75 'export_latex',
77 76 'export_markdown',
78 77 'export_python',
79 'export_reveal',
80 78 'export_rst',
81 79 'export_by_name',
82 80 'get_export_names',
83 81 'ExporterNameError'
84 82 ]
85 83
86 84
87 85 class ExporterNameError(NameError):
88 86 pass
89 87
90 88
91 89 @DocDecorator
92 90 def export(exporter, nb, **kw):
93 91 """
94 92 Export a notebook object using specific exporter class.
95 93
96 94 exporter : Exporter class type or instance
97 95 Class type or instance of the exporter that should be used. If the
98 96 method initializes it's own instance of the class, it is ASSUMED that
99 97 the class type provided exposes a constructor (__init__) with the same
100 98 signature as the base Exporter class.
101 99 """
102 100
103 101 #Check arguments
104 102 if exporter is None:
105 103 raise TypeError("Exporter is None")
106 104 elif not isinstance(exporter, Exporter) and not issubclass(exporter, Exporter):
107 105 raise TypeError("exporter does not inherit from Exporter (base)")
108 106 if nb is None:
109 107 raise TypeError("nb is None")
110 108
111 109 #Create the exporter
112 110 resources = kw.pop('resources', None)
113 111 if isinstance(exporter, Exporter):
114 112 exporter_instance = exporter
115 113 else:
116 114 exporter_instance = exporter(**kw)
117 115
118 116 #Try to convert the notebook using the appropriate conversion function.
119 117 if isinstance(nb, NotebookNode):
120 118 output, resources = exporter_instance.from_notebook_node(nb, resources)
121 119 elif isinstance(nb, basestring):
122 120 output, resources = exporter_instance.from_filename(nb, resources)
123 121 else:
124 122 output, resources = exporter_instance.from_file(nb, resources)
125 123 return output, resources
126 124
127 125
128 126 @DocDecorator
129 def export_sphinx_manual(nb, **kw):
130 """
131 Export a notebook object to Sphinx Manual LaTeX
132 """
133 return export(SphinxManualExporter, nb, **kw)
134
135
136 @DocDecorator
137 def export_sphinx_howto(nb, **kw):
127 def export_custom(nb, **kw):
138 128 """
139 Export a notebook object to Sphinx HowTo LaTeX
129 Export a notebook object to a custom format
140 130 """
141 return export(SphinxHowtoExporter, nb, **kw)
131 return export(Exporter, nb, **kw)
142 132
143 133
144 134 @DocDecorator
145 def export_basic_html(nb, **kw):
135 def export_html(nb, **kw):
146 136 """
147 Export a notebook object to Basic HTML
137 Export a notebook object to HTML
148 138 """
149 return export(BasicHTMLExporter, nb, **kw)
139 return export(HTMLExporter, nb, **kw)
150 140
151 141
152 142 @DocDecorator
153 def export_full_html(nb, **kw):
143 def export_slides(nb, **kw):
154 144 """
155 Export a notebook object to Full HTML
145 Export a notebook object to Slides
156 146 """
157 return export(FullHTMLExporter, nb, **kw)
147 return export(SlidesExporter, nb, **kw)
158 148
159 149
160 150 @DocDecorator
161 151 def export_latex(nb, **kw):
162 152 """
163 153 Export a notebook object to LaTeX
164 154 """
165 155 return export(LatexExporter, nb, **kw)
166 156
167 157
168 158 @DocDecorator
169 159 def export_markdown(nb, **kw):
170 160 """
171 161 Export a notebook object to Markdown
172 162 """
173 163 return export(MarkdownExporter, nb, **kw)
174 164
175 165
176 166 @DocDecorator
177 167 def export_python(nb, **kw):
178 168 """
179 169 Export a notebook object to Python
180 170 """
181 171 return export(PythonExporter, nb, **kw)
182 172
183 173
184 174 @DocDecorator
185 def export_reveal(nb, **kw):
186 """
187 Export a notebook object to a Reveal.js presentation
188 """
189 return export(RevealExporter, nb, **kw)
190
191
192 @DocDecorator
193 175 def export_rst(nb, **kw):
194 176 """
195 177 Export a notebook object to reStructuredText
196 178 """
197 179 return export(RSTExporter, nb, **kw)
198 180
199 181
200 182 @DocDecorator
201 183 def export_by_name(format_name, nb, **kw):
202 184 """
203 185 Export a notebook object to a template type by its name. Reflection
204 186 (Inspect) is used to find the template's corresponding explicit export
205 187 method defined in this module. That method is then called directly.
206 188
207 189 format_name : str
208 190 Name of the template style to export to.
209 191 """
210 192
211 193 function_name = "export_" + format_name.lower()
212 194
213 195 if function_name in globals():
214 196 return globals()[function_name](nb, **kw)
215 197 else:
216 198 raise ExporterNameError("template for `%s` not found" % function_name)
217 199
218 200
219 201 def get_export_names():
220 "Return a list of the currently supported export targets"
202 """Return a list of the currently supported export targets
203
204 WARNING: API WILL CHANGE IN FUTURE RELEASES OF NBCONVERT"""
205
221 206 # grab everything after 'export_'
222 207 l = [x[len('export_'):] for x in __all__ if x.startswith('export_')]
223 208
224 209 # filter out the one method that is not a template
225 210 l = [x for x in l if 'by_name' not in x]
226 211 return sorted(l)
@@ -1,446 +1,482 b''
1 1 """This module defines Exporter, a highly configurable converter
2 2 that uses Jinja2 to export notebook files into different formats.
3 3 """
4 4
5 5 #-----------------------------------------------------------------------------
6 6 # Copyright (c) 2013, the IPython Development Team.
7 7 #
8 8 # Distributed under the terms of the Modified BSD License.
9 9 #
10 10 # The full license is in the file COPYING.txt, distributed with this software.
11 11 #-----------------------------------------------------------------------------
12 12
13 13 #-----------------------------------------------------------------------------
14 14 # Imports
15 15 #-----------------------------------------------------------------------------
16 16
17 17 from __future__ import print_function, absolute_import
18 18
19 19 # Stdlib imports
20 20 import io
21 21 import os
22 22 import inspect
23 23 import copy
24 24 import collections
25 25 import datetime
26 26
27 27 # other libs/dependencies
28 from jinja2 import Environment, FileSystemLoader, ChoiceLoader
28 from jinja2 import Environment, FileSystemLoader, ChoiceLoader, TemplateNotFound
29 29
30 30 # IPython imports
31 31 from IPython.config.configurable import Configurable
32 32 from IPython.config import Config
33 33 from IPython.nbformat import current as nbformat
34 34 from IPython.utils.traitlets import MetaHasTraits, DottedObjectName, Unicode, List, Dict
35 35 from IPython.utils.importstring import import_item
36 36 from IPython.utils.text import indent
37 37 from IPython.utils import py3compat
38 38
39 39 from IPython.nbconvert import transformers as nbtransformers
40 40 from IPython.nbconvert import filters
41 41
42 42 #-----------------------------------------------------------------------------
43 43 # Globals and constants
44 44 #-----------------------------------------------------------------------------
45 45
46 46 #Jinja2 extensions to load.
47 47 JINJA_EXTENSIONS = ['jinja2.ext.loopcontrols']
48 48
49 49 default_filters = {
50 50 'indent': indent,
51 51 'markdown2html': filters.markdown2html,
52 52 'ansi2html': filters.ansi2html,
53 53 'filter_data_type': filters.DataTypeFilter,
54 54 'get_lines': filters.get_lines,
55 55 'highlight2html': filters.highlight2html,
56 56 'highlight2latex': filters.highlight2latex,
57 57 'ipython2python': filters.ipython2python,
58 58 'markdown2latex': filters.markdown2latex,
59 59 'markdown2rst': filters.markdown2rst,
60 60 'comment_lines': filters.comment_lines,
61 61 'strip_ansi': filters.strip_ansi,
62 62 'strip_dollars': filters.strip_dollars,
63 63 'strip_files_prefix': filters.strip_files_prefix,
64 64 'html2text' : filters.html2text,
65 65 'add_anchor': filters.add_anchor,
66 66 'ansi2latex': filters.ansi2latex,
67 67 'strip_math_space': filters.strip_math_space,
68 68 'wrap_text': filters.wrap_text,
69 69 'escape_latex': filters.escape_latex
70 70 }
71 71
72 72 #-----------------------------------------------------------------------------
73 73 # Class
74 74 #-----------------------------------------------------------------------------
75 75
76 76 class ResourcesDict(collections.defaultdict):
77 77 def __missing__(self, key):
78 78 return ''
79 79
80 80
81 81 class Exporter(Configurable):
82 82 """
83 83 Exports notebooks into other file formats. Uses Jinja 2 templating engine
84 84 to output new formats. Inherit from this class if you are creating a new
85 85 template type along with new filters/transformers. If the filters/
86 86 transformers provided by default suffice, there is no need to inherit from
87 87 this class. Instead, override the template_file and file_extension
88 88 traits via a config file.
89
89
90 90 {filters}
91 91 """
92 92
93 93 # finish the docstring
94 94 __doc__ = __doc__.format(filters = '- '+'\n - '.join(default_filters.keys()))
95 95
96 96
97 template_file = Unicode(
98 '', config=True,
97 template_file = Unicode(u'default',
98 config=True,
99 99 help="Name of the template file to use")
100 def _template_file_changed(self, name, old, new):
101 if new=='default':
102 self.template_file = self.default_template
103 else:
104 self.template_file = new
105 default_template = Unicode(u'')
100 106
101 107 file_extension = Unicode(
102 108 'txt', config=True,
103 109 help="Extension of the file that should be written to disk"
104 110 )
105 111
106 112 template_path = List(['.'], config=True)
107 113
108 114 default_template_path = Unicode(
109 115 os.path.join("..", "templates"),
110 116 help="Path where the template files are located.")
111 117
112 118 template_skeleton_path = Unicode(
113 119 os.path.join("..", "templates", "skeleton"),
114 120 help="Path where the template skeleton files are located.")
115 121
116 122 #Jinja block definitions
117 123 jinja_comment_block_start = Unicode("", config=True)
118 124 jinja_comment_block_end = Unicode("", config=True)
119 125 jinja_variable_block_start = Unicode("", config=True)
120 126 jinja_variable_block_end = Unicode("", config=True)
121 127 jinja_logic_block_start = Unicode("", config=True)
122 128 jinja_logic_block_end = Unicode("", config=True)
123 129
124 130 #Extension that the template files use.
125 131 template_extension = Unicode(".tpl", config=True)
126 132
127 133 #Configurability, allows the user to easily add filters and transformers.
128 134 transformers = List(config=True,
129 135 help="""List of transformers, by name or namespace, to enable.""")
130 136
131 137 filters = Dict(config=True,
132 138 help="""Dictionary of filters, by name and namespace, to add to the Jinja
133 139 environment.""")
134 140
135 141 default_transformers = List([nbtransformers.coalesce_streams,
136 142 nbtransformers.SVG2PDFTransformer,
137 143 nbtransformers.ExtractOutputTransformer,
138 144 nbtransformers.CSSHTMLHeaderTransformer,
139 145 nbtransformers.RevealHelpTransformer,
140 146 nbtransformers.LatexTransformer,
141 147 nbtransformers.SphinxTransformer],
142 148 config=True,
143 149 help="""List of transformers available by default, by name, namespace,
144 150 instance, or type.""")
145 151
146 152
147 153 def __init__(self, config=None, extra_loaders=None, **kw):
148 154 """
149 155 Public constructor
150 156
151 157 Parameters
152 158 ----------
153 159 config : config
154 160 User configuration instance.
155 161 extra_loaders : list[of Jinja Loaders]
156 162 ordered list of Jinja loder to find templates. Will be tried in order
157 163 before the default FileSysteme ones.
164 template : str (optional, kw arg)
165 Template to use when exporting.
158 166 """
159 167
160 168 #Call the base class constructor
161 169 c = self.default_config
162 170 if config:
163 171 c.merge(config)
164 172
165 173 super(Exporter, self).__init__(config=c, **kw)
166 174
167 175 #Init
176 self._init_template(**kw)
168 177 self._init_environment(extra_loaders=extra_loaders)
169 178 self._init_transformers()
170 179 self._init_filters()
171 180
172 181
173 182 @property
174 183 def default_config(self):
175 184 return Config()
176 185
177 186
178 187 def from_notebook_node(self, nb, resources=None, **kw):
179 188 """
180 189 Convert a notebook from a notebook node instance.
181 190
182 191 Parameters
183 192 ----------
184 193 nb : Notebook node
185 194 resources : dict (**kw)
186 195 of additional resources that can be accessed read/write by
187 196 transformers and filters.
188 197 """
189 198 nb_copy = copy.deepcopy(nb)
190 199 resources = self._init_resources(resources)
191 200
192 #Preprocess
201 # Preprocess
193 202 nb_copy, resources = self._transform(nb_copy, resources)
194 203
195 #Convert
196 self.template = self.environment.get_template(self.template_file + self.template_extension)
197 output = self.template.render(nb=nb_copy, resources=resources)
204 # Try different template names during conversion. First try to load the
205 # template by name with extension added, then try loading the template
206 # as if the name is explicitly specified, then try the name as a
207 # 'flavor', and lastly just try to load the template by module name.
208 module_name = self.__module__.split('.')[-1]
209 try_names = [self.template_file + self.template_extension,
210 self.template_file,
211 module_name + '_' + self.template_file + self.template_extension,
212 module_name + self.template_extension]
213 for try_name in try_names:
214 try:
215 self.template = self.environment.get_template(try_name)
216 break
217 except TemplateNotFound:
218 pass
219
220 if hasattr(self, 'template'):
221 output = self.template.render(nb=nb_copy, resources=resources)
222 else:
223 raise IOError('template file "%s" could not be found' % self.template_file)
198 224 return output, resources
199 225
200 226
201 227 def from_filename(self, filename, resources=None, **kw):
202 228 """
203 229 Convert a notebook from a notebook file.
204 230
205 231 Parameters
206 232 ----------
207 233 filename : str
208 234 Full filename of the notebook file to open and convert.
209 235 """
210 236
211 237 #Pull the metadata from the filesystem.
212 238 if resources is None:
213 239 resources = ResourcesDict()
214 240 if not 'metadata' in resources or resources['metadata'] == '':
215 241 resources['metadata'] = ResourcesDict()
216 242 basename = os.path.basename(filename)
217 243 notebook_name = basename[:basename.rfind('.')]
218 244 resources['metadata']['name'] = notebook_name
219 245
220 246 modified_date = datetime.datetime.fromtimestamp(os.path.getmtime(filename))
221 247 resources['metadata']['modified_date'] = modified_date.strftime("%B %d, %Y")
222 248
223 249 with io.open(filename) as f:
224 250 return self.from_notebook_node(nbformat.read(f, 'json'), resources=resources,**kw)
225 251
226 252
227 253 def from_file(self, file_stream, resources=None, **kw):
228 254 """
229 255 Convert a notebook from a notebook file.
230 256
231 257 Parameters
232 258 ----------
233 259 file_stream : file-like object
234 260 Notebook file-like object to convert.
235 261 """
236 262 return self.from_notebook_node(nbformat.read(file_stream, 'json'), resources=resources, **kw)
237 263
238 264
239 265 def register_transformer(self, transformer, enabled=False):
240 266 """
241 267 Register a transformer.
242 268 Transformers are classes that act upon the notebook before it is
243 269 passed into the Jinja templating engine. Transformers are also
244 270 capable of passing additional information to the Jinja
245 271 templating engine.
246 272
247 273 Parameters
248 274 ----------
249 275 transformer : transformer
250 276 """
251 277 if transformer is None:
252 278 raise TypeError('transformer')
253 279 isclass = isinstance(transformer, type)
254 280 constructed = not isclass
255 281
256 282 #Handle transformer's registration based on it's type
257 283 if constructed and isinstance(transformer, py3compat.string_types):
258 284 #Transformer is a string, import the namespace and recursively call
259 285 #this register_transformer method
260 286 transformer_cls = import_item(transformer)
261 287 return self.register_transformer(transformer_cls, enabled)
262 288
263 289 if constructed and hasattr(transformer, '__call__'):
264 290 #Transformer is a function, no need to construct it.
265 291 #Register and return the transformer.
266 292 if enabled:
267 293 transformer.enabled = True
268 294 self._transformers.append(transformer)
269 295 return transformer
270 296
271 297 elif isclass and isinstance(transformer, MetaHasTraits):
272 298 #Transformer is configurable. Make sure to pass in new default for
273 299 #the enabled flag if one was specified.
274 300 self.register_transformer(transformer(parent=self), enabled)
275 301
276 302 elif isclass:
277 303 #Transformer is not configurable, construct it
278 304 self.register_transformer(transformer(), enabled)
279 305
280 306 else:
281 307 #Transformer is an instance of something without a __call__
282 308 #attribute.
283 309 raise TypeError('transformer')
284 310
285 311
286 312 def register_filter(self, name, jinja_filter):
287 313 """
288 314 Register a filter.
289 315 A filter is a function that accepts and acts on one string.
290 316 The filters are accesible within the Jinja templating engine.
291 317
292 318 Parameters
293 319 ----------
294 320 name : str
295 321 name to give the filter in the Jinja engine
296 322 filter : filter
297 323 """
298 324 if jinja_filter is None:
299 325 raise TypeError('filter')
300 326 isclass = isinstance(jinja_filter, type)
301 327 constructed = not isclass
302 328
303 329 #Handle filter's registration based on it's type
304 330 if constructed and isinstance(jinja_filter, py3compat.string_types):
305 331 #filter is a string, import the namespace and recursively call
306 332 #this register_filter method
307 333 filter_cls = import_item(jinja_filter)
308 334 return self.register_filter(name, filter_cls)
309 335
310 336 if constructed and hasattr(jinja_filter, '__call__'):
311 337 #filter is a function, no need to construct it.
312 338 self.environment.filters[name] = jinja_filter
313 339 return jinja_filter
314 340
315 341 elif isclass and isinstance(jinja_filter, MetaHasTraits):
316 342 #filter is configurable. Make sure to pass in new default for
317 343 #the enabled flag if one was specified.
318 344 filter_instance = jinja_filter(parent=self)
319 345 self.register_filter(name, filter_instance )
320 346
321 347 elif isclass:
322 348 #filter is not configurable, construct it
323 349 filter_instance = jinja_filter()
324 350 self.register_filter(name, filter_instance)
325 351
326 352 else:
327 353 #filter is an instance of something without a __call__
328 354 #attribute.
329 355 raise TypeError('filter')
330 356
331 357
358 def _init_template(self, **kw):
359 """
360 Make sure a template name is specified. If one isn't specified, try to
361 build one from the information we know.
362 """
363 self._template_file_changed('template_file', self.template_file, self.template_file)
364 if 'template' in kw:
365 self.template_file = kw['template']
366
367
332 368 def _init_environment(self, extra_loaders=None):
333 369 """
334 370 Create the Jinja templating environment.
335 371 """
336 372 here = os.path.dirname(os.path.realpath(__file__))
337 373 loaders = []
338 374 if extra_loaders:
339 375 loaders.extend(extra_loaders)
340 376
341 377 paths = self.template_path
342 378 paths.extend([os.path.join(here, self.default_template_path),
343 379 os.path.join(here, self.template_skeleton_path)])
344 380 loaders.append(FileSystemLoader(paths))
345 381
346 382 self.environment = Environment(
347 383 loader= ChoiceLoader(loaders),
348 384 extensions=JINJA_EXTENSIONS
349 385 )
350 386
351 387 #Set special Jinja2 syntax that will not conflict with latex.
352 388 if self.jinja_logic_block_start:
353 389 self.environment.block_start_string = self.jinja_logic_block_start
354 390 if self.jinja_logic_block_end:
355 391 self.environment.block_end_string = self.jinja_logic_block_end
356 392 if self.jinja_variable_block_start:
357 393 self.environment.variable_start_string = self.jinja_variable_block_start
358 394 if self.jinja_variable_block_end:
359 395 self.environment.variable_end_string = self.jinja_variable_block_end
360 396 if self.jinja_comment_block_start:
361 397 self.environment.comment_start_string = self.jinja_comment_block_start
362 398 if self.jinja_comment_block_end:
363 399 self.environment.comment_end_string = self.jinja_comment_block_end
364 400
365 401
366 402 def _init_transformers(self):
367 403 """
368 404 Register all of the transformers needed for this exporter, disabled
369 405 unless specified explicitly.
370 406 """
371 407 self._transformers = []
372 408
373 409 #Load default transformers (not necessarly enabled by default).
374 410 if self.default_transformers:
375 411 for transformer in self.default_transformers:
376 412 self.register_transformer(transformer)
377 413
378 414 #Load user transformers. Enable by default.
379 415 if self.transformers:
380 416 for transformer in self.transformers:
381 417 self.register_transformer(transformer, enabled=True)
382 418
383 419
384 420 def _init_filters(self):
385 421 """
386 422 Register all of the filters required for the exporter.
387 423 """
388 424
389 425 #Add default filters to the Jinja2 environment
390 426 for key, value in default_filters.items():
391 427 self.register_filter(key, value)
392 428
393 429 #Load user filters. Overwrite existing filters if need be.
394 430 if self.filters:
395 431 for key, user_filter in self.filters.items():
396 432 self.register_filter(key, user_filter)
397 433
398 434
399 435 def _init_resources(self, resources):
400 436
401 437 #Make sure the resources dict is of ResourcesDict type.
402 438 if resources is None:
403 439 resources = ResourcesDict()
404 440 if not isinstance(resources, ResourcesDict):
405 441 new_resources = ResourcesDict()
406 442 new_resources.update(resources)
407 443 resources = new_resources
408 444
409 445 #Make sure the metadata extension exists in resources
410 446 if 'metadata' in resources:
411 447 if not isinstance(resources['metadata'], ResourcesDict):
412 448 resources['metadata'] = ResourcesDict(resources['metadata'])
413 449 else:
414 450 resources['metadata'] = ResourcesDict()
415 451 if not resources['metadata']['name']:
416 452 resources['metadata']['name'] = 'Notebook'
417 453
418 454 #Set the output extension
419 455 resources['output_extension'] = self.file_extension
420 456 return resources
421 457
422 458
423 459 def _transform(self, nb, resources):
424 460 """
425 461 Preprocess the notebook before passing it into the Jinja engine.
426 462 To preprocess the notebook is to apply all of the
427 463
428 464 Parameters
429 465 ----------
430 466 nb : notebook node
431 467 notebook that is being exported.
432 468 resources : a dict of additional resources that
433 469 can be accessed read/write by transformers
434 470 and filters.
435 471 """
436 472
437 473 # Do a copy.deepcopy first,
438 474 # we are never safe enough with what the transformers could do.
439 475 nbc = copy.deepcopy(nb)
440 476 resc = copy.deepcopy(resources)
441 477
442 478 #Run each transformer on the notebook. Carry the output along
443 479 #to each transformer
444 480 for transformer in self._transformers:
445 481 nbc, resc = transformer(nbc, resc)
446 482 return nbc, resc
@@ -1,42 +1,52 b''
1 1 """
2 2 Exporter that exports Basic HTML.
3 3 """
4 4
5 5 #-----------------------------------------------------------------------------
6 6 # Copyright (c) 2013, the IPython Development Team.
7 7 #
8 8 # Distributed under the terms of the Modified BSD License.
9 9 #
10 10 # The full license is in the file COPYING.txt, distributed with this software.
11 11 #-----------------------------------------------------------------------------
12 12
13 13 #-----------------------------------------------------------------------------
14 14 # Imports
15 15 #-----------------------------------------------------------------------------
16 16
17 17 from IPython.utils.traitlets import Unicode, List
18 18
19 19 from IPython.nbconvert import transformers
20 from IPython.config import Config
20 21
21 22 from .exporter import Exporter
22 23
23 24 #-----------------------------------------------------------------------------
24 25 # Classes
25 26 #-----------------------------------------------------------------------------
26 27
27 class BasicHTMLExporter(Exporter):
28 class HTMLExporter(Exporter):
28 29 """
29 30 Exports a basic HTML document. This exporter assists with the export of
30 31 HTML. Inherit from it if you are writing your own HTML template and need
31 32 custom transformers/filters. If you don't need custom transformers/
32 33 filters, just change the 'template_file' config option.
33 34 """
34 35
35 36 file_extension = Unicode(
36 37 'html', config=True,
37 38 help="Extension of the file that should be written to disk"
38 39 )
39 40
40 template_file = Unicode(
41 'basichtml', config=True,
42 help="Name of the template file to use")
41 default_template = Unicode('full', config=True, help="""Flavor of the data
42 format to use. I.E. 'full' or 'basic'""")
43
44 @property
45 def default_config(self):
46 c = Config({
47 'CSSHTMLHeaderTransformer':{
48 'enabled':True
49 }
50 })
51 c.merge(super(HTMLExporter,self).default_config)
52 return c
@@ -1,88 +1,91 b''
1 1 """
2 2 Exporter that allows Latex Jinja templates to work. Contains logic to
3 3 appropriately prepare IPYNB files for export to LaTeX. Including but
4 4 not limited to escaping LaTeX, fixing math region tags, using special
5 5 tags to circumvent Jinja/Latex syntax conflicts.
6 6 """
7 7 #-----------------------------------------------------------------------------
8 8 # Copyright (c) 2013, the IPython Development Team.
9 9 #
10 10 # Distributed under the terms of the Modified BSD License.
11 11 #
12 12 # The full license is in the file COPYING.txt, distributed with this software.
13 13 #-----------------------------------------------------------------------------
14 14
15 15 #-----------------------------------------------------------------------------
16 16 # Imports
17 17 #-----------------------------------------------------------------------------
18 18
19 19 # Stdlib imports
20 20 import os
21 21
22 22 # IPython imports
23 23 from IPython.utils.traitlets import Unicode, List
24 24 from IPython.config import Config
25 25
26 26 from IPython.nbconvert import filters, transformers
27 27 from .exporter import Exporter
28 28
29 29 #-----------------------------------------------------------------------------
30 30 # Classes and functions
31 31 #-----------------------------------------------------------------------------
32 32
33 33 class LatexExporter(Exporter):
34 34 """
35 35 Exports to a Latex template. Inherit from this class if your template is
36 36 LaTeX based and you need custom tranformers/filters. Inherit from it if
37 37 you are writing your own HTML template and need custom tranformers/filters.
38 38 If you don't need custom tranformers/filters, just change the
39 39 'template_file' config option. Place your template in the special "/latex"
40 40 subfolder of the "../templates" folder.
41 41 """
42 42
43 43 file_extension = Unicode(
44 44 'tex', config=True,
45 45 help="Extension of the file that should be written to disk")
46 46
47 template_file = Unicode(
48 'base', config=True,
49 help="Name of the template file to use")
47 default_template = Unicode('article', config=True, help="""Template of the
48 data format to use. I.E. 'full' or 'basic'""")
50 49
51 50 #Latex constants
52 51 default_template_path = Unicode(
53 52 os.path.join("..", "templates", "latex"), config=True,
54 53 help="Path where the template files are located.")
55 54
56 55 template_skeleton_path = Unicode(
57 56 os.path.join("..", "templates", "latex", "skeleton"), config=True,
58 57 help="Path where the template skeleton files are located.")
59 58
60 59 #Special Jinja2 syntax that will not conflict when exporting latex.
61 60 jinja_comment_block_start = Unicode("((=", config=True)
62 61 jinja_comment_block_end = Unicode("=))", config=True)
63 62 jinja_variable_block_start = Unicode("(((", config=True)
64 63 jinja_variable_block_end = Unicode(")))", config=True)
65 64 jinja_logic_block_start = Unicode("((*", config=True)
66 65 jinja_logic_block_end = Unicode("*))", config=True)
67 66
68 67 #Extension that the template files use.
69 68 template_extension = Unicode(".tplx", config=True)
70 69
70
71 71 @property
72 72 def default_config(self):
73 73 c = Config({
74 74 'NbConvertBase': {
75 75 'display_data_priority' : ['latex', 'pdf', 'png', 'jpg', 'svg', 'jpeg', 'text']
76 76 },
77 77 'ExtractOutputTransformer': {
78 78 'enabled':True
79 79 },
80 80 'SVG2PDFTransformer': {
81 81 'enabled':True
82 82 },
83 83 'LatexTransformer': {
84 84 'enabled':True
85 },
86 'SphinxTransformer': {
87 'enabled':True
85 88 }
86 89 })
87 90 c.merge(super(LatexExporter,self).default_config)
88 91 return c
@@ -1,35 +1,31 b''
1 1 """
2 2 Exporter that will export your ipynb to Markdown.
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 from IPython.utils.traitlets import Unicode
17 17
18 18 from .exporter import Exporter
19 19
20 20 #-----------------------------------------------------------------------------
21 21 # Classes
22 22 #-----------------------------------------------------------------------------
23 23
24 24 class MarkdownExporter(Exporter):
25 25 """
26 26 Exports to a markdown document (.md)
27 27 """
28 28
29 29 file_extension = Unicode(
30 30 'md', config=True,
31 31 help="Extension of the file that should be written to disk")
32
33 template_file = Unicode(
34 'markdown', config=True,
35 help="Name of the template file to use")
@@ -1,35 +1,31 b''
1 1 """
2 2 Python exporter which exports Notebook code into a PY file.
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 from IPython.utils.traitlets import Unicode
17 17
18 18 from .exporter import Exporter
19 19
20 20 #-----------------------------------------------------------------------------
21 21 # Classes
22 22 #-----------------------------------------------------------------------------
23 23
24 24 class PythonExporter(Exporter):
25 25 """
26 26 Exports a Python code file.
27 27 """
28 28
29 29 file_extension = Unicode(
30 30 'py', config=True,
31 31 help="Extension of the file that should be written to disk")
32
33 template_file = Unicode(
34 'python', config=True,
35 help="Name of the template file to use")
@@ -1,42 +1,38 b''
1 1 """
2 2 Exporter for exporting notebooks to restructured text.
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 from IPython.utils.traitlets import Unicode
17 17 from IPython.config import Config
18 18
19 19 from .exporter import Exporter
20 20
21 21 #-----------------------------------------------------------------------------
22 22 # Classes
23 23 #-----------------------------------------------------------------------------
24 24
25 25 class RSTExporter(Exporter):
26 26 """
27 27 Exports restructured text documents.
28 28 """
29 29
30 30 file_extension = Unicode(
31 31 'rst', config=True,
32 32 help="Extension of the file that should be written to disk")
33 33
34 template_file = Unicode(
35 'rst', config=True,
36 help="Name of the template file to use")
37
38 34 @property
39 35 def default_config(self):
40 36 c = Config({'ExtractOutputTransformer':{'enabled':True}})
41 37 c.merge(super(RSTExporter,self).default_config)
42 38 return c
@@ -1,51 +1,52 b''
1 1 """
2 Reveal slide show exporter.
2 Contains slide show exporter
3 3 """
4
4 5 #-----------------------------------------------------------------------------
5 6 # Copyright (c) 2013, the IPython Development Team.
6 7 #
7 8 # Distributed under the terms of the Modified BSD License.
8 9 #
9 10 # The full license is in the file COPYING.txt, distributed with this software.
10 11 #-----------------------------------------------------------------------------
11 12
12 13 #-----------------------------------------------------------------------------
13 14 # Imports
14 15 #-----------------------------------------------------------------------------
15 16
16 from IPython.utils.traitlets import Unicode, List
17 from IPython.config import Config
17 from IPython.utils.traitlets import Unicode
18 18
19 from .basichtml import BasicHTMLExporter
20 19 from IPython.nbconvert import transformers
20 from IPython.config import Config
21
22 from .exporter import Exporter
21 23
22 24 #-----------------------------------------------------------------------------
23 25 # Classes
24 26 #-----------------------------------------------------------------------------
25 27
26 class RevealExporter(BasicHTMLExporter):
28 class SlidesExporter(Exporter):
27 29 """
28 Exports a Reveal slide show (.HTML) which may be rendered in a web browser.
30 Exports slides
29 31 """
30 32
31 33 file_extension = Unicode(
32 'reveal.html', config=True,
33 help="Extension of the file that should be written to disk")
34
35 template_file = Unicode(
36 'reveal', config=True,
37 help="Name of the template file to use")
34 'slides.html', config=True,
35 help="Extension of the file that should be written to disk"
36 )
38 37
38 default_template = Unicode('reveal', config=True, help="""Template of the
39 data format to use. I.E. 'reveal'""")
39 40
40 41 @property
41 42 def default_config(self):
42 43 c = Config({
43 44 'CSSHTMLHeaderTransformer':{
44 45 'enabled':True
45 46 },
46 47 'RevealHelpTransformer':{
47 48 'enabled':True,
48 49 },
49 50 })
50 c.merge(super(RevealExporter,self).default_config)
51 c.merge(super(SlidesExporter,self).default_config)
51 52 return c
@@ -1,40 +1,59 b''
1 1 """
2 Module with tests for fullhtml.py
2 Module with tests for html.py
3 3 """
4 4
5 5 #-----------------------------------------------------------------------------
6 6 # Copyright (c) 2013, the IPython Development Team.
7 7 #
8 8 # Distributed under the terms of the Modified BSD License.
9 9 #
10 10 # The full license is in the file COPYING.txt, distributed with this software.
11 11 #-----------------------------------------------------------------------------
12 12
13 13 #-----------------------------------------------------------------------------
14 14 # Imports
15 15 #-----------------------------------------------------------------------------
16 16
17 17 from .base import ExportersTestsBase
18 from ..fullhtml import FullHTMLExporter
18 from ..html import HTMLExporter
19 19 from IPython.testing.decorators import onlyif_cmds_exist
20 20
21 21 #-----------------------------------------------------------------------------
22 22 # Class
23 23 #-----------------------------------------------------------------------------
24 24
25 class TestFullHTMLExporter(ExportersTestsBase):
26 """Contains test functions for fullhtml.py"""
25 class TestHTMLExporter(ExportersTestsBase):
26 """Contains test functions for html.py"""
27 27
28 28 def test_constructor(self):
29 29 """
30 Can a FullHTMLExporter be constructed?
30 Can a HTMLExporter be constructed?
31 31 """
32 FullHTMLExporter()
32 HTMLExporter()
33
33 34
34 35 @onlyif_cmds_exist('pandoc')
35 36 def test_export(self):
36 37 """
37 Can a FullHTMLExporter export something?
38 Can a HTMLExporter export something?
39 """
40 (output, resources) = HTMLExporter().from_filename(self._get_notebook())
41 assert len(output) > 0
42
43
44 @onlyif_cmds_exist('pandoc')
45 def test_export_basic(self):
46 """
47 Can a HTMLExporter export using the 'basic' template?
48 """
49 (output, resources) = HTMLExporter(template='basic').from_filename(self._get_notebook())
50 assert len(output) > 0
51
52
53 @onlyif_cmds_exist('pandoc')
54 def test_export_full(self):
55 """
56 Can a HTMLExporter export using the 'full' template?
38 57 """
39 (output, resources) = FullHTMLExporter().from_filename(self._get_notebook())
58 (output, resources) = HTMLExporter(template='full').from_filename(self._get_notebook())
40 59 assert len(output) > 0
@@ -1,41 +1,68 b''
1 1 """
2 2 Module with tests for latex.py
3 3 """
4 4
5 5 #-----------------------------------------------------------------------------
6 6 # Copyright (c) 2013, the IPython Development Team.
7 7 #
8 8 # Distributed under the terms of the Modified BSD License.
9 9 #
10 10 # The full license is in the file COPYING.txt, distributed with this software.
11 11 #-----------------------------------------------------------------------------
12 12
13 13 #-----------------------------------------------------------------------------
14 14 # Imports
15 15 #-----------------------------------------------------------------------------
16 16
17 17 from .base import ExportersTestsBase
18 18 from ..latex import LatexExporter
19 19 from IPython.testing.decorators import onlyif_cmds_exist
20 20
21 21 #-----------------------------------------------------------------------------
22 22 # Class
23 23 #-----------------------------------------------------------------------------
24 24
25 25 class TestLatexExporter(ExportersTestsBase):
26 26 """Contains test functions for latex.py"""
27 27
28 28 def test_constructor(self):
29 29 """
30 30 Can a LatexExporter be constructed?
31 31 """
32 32 LatexExporter()
33 33
34 34
35 35 @onlyif_cmds_exist('pandoc')
36 36 def test_export(self):
37 37 """
38 38 Can a LatexExporter export something?
39 39 """
40 40 (output, resources) = LatexExporter().from_filename(self._get_notebook())
41 41 assert len(output) > 0
42
43
44 @onlyif_cmds_exist('pandoc')
45 def test_export_book(self):
46 """
47 Can a LatexExporter export using 'book' template?
48 """
49 (output, resources) = LatexExporter(template='book').from_filename(self._get_notebook())
50 assert len(output) > 0
51
52
53 @onlyif_cmds_exist('pandoc')
54 def test_export_basic(self):
55 """
56 Can a LatexExporter export using 'basic' template?
57 """
58 (output, resources) = LatexExporter(template='basic').from_filename(self._get_notebook())
59 assert len(output) > 0
60
61
62 @onlyif_cmds_exist('pandoc')
63 def test_export_article(self):
64 """
65 Can a LatexExporter export using 'article' template?
66 """
67 (output, resources) = LatexExporter(template='article').from_filename(self._get_notebook())
68 assert len(output) > 0 No newline at end of file
@@ -1,40 +1,47 b''
1 1 """
2 Module with tests for basichtml.py
2 Module with tests for slides.py
3 3 """
4 4
5 5 #-----------------------------------------------------------------------------
6 6 # Copyright (c) 2013, the IPython Development Team.
7 7 #
8 8 # Distributed under the terms of the Modified BSD License.
9 9 #
10 10 # The full license is in the file COPYING.txt, distributed with this software.
11 11 #-----------------------------------------------------------------------------
12 12
13 13 #-----------------------------------------------------------------------------
14 14 # Imports
15 15 #-----------------------------------------------------------------------------
16 16
17 17 from .base import ExportersTestsBase
18 from ..basichtml import BasicHTMLExporter
19 from IPython.testing.decorators import onlyif_cmds_exist
18 from ..slides import SlidesExporter
20 19
21 20 #-----------------------------------------------------------------------------
22 21 # Class
23 22 #-----------------------------------------------------------------------------
24 23
25 class TestBasicHTMLExporter(ExportersTestsBase):
26 """Contains test functions for basichtml.py"""
24 class TestSlidesExporter(ExportersTestsBase):
25 """Contains test functions for slides.py"""
27 26
28 27 def test_constructor(self):
29 28 """
30 Can a BasicHTMLExporter be constructed?
29 Can a SlidesExporter be constructed?
31 30 """
32 BasicHTMLExporter()
31 SlidesExporter()
32
33 33
34 @onlyif_cmds_exist('pandoc')
35 34 def test_export(self):
36 35 """
37 Can a BasicHTMLExporter export something?
36 Can a SlidesExporter export something?
37 """
38 (output, resources) = SlidesExporter().from_filename(self._get_notebook())
39 assert len(output) > 0
40
41
42 def test_export_reveal(self):
43 """
44 Can a SlidesExporter export using the 'reveal' template?
38 45 """
39 (output, resources) = BasicHTMLExporter().from_filename(self._get_notebook())
46 (output, resources) = SlidesExporter(template='reveal').from_filename(self._get_notebook())
40 47 assert len(output) > 0
@@ -1,241 +1,301 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 from IPython.nbconvert import exporters, transformers, writers
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 class DottedOrNone(DottedObjectName):
42 """
43 A string holding a valid dotted object name in Python, such as A.b3._c
44 Also allows for None type."""
45
46 default_value = u''
47
48 def validate(self, obj, value):
49 if value is not None and len(value) > 0:
50 return super(DottedOrNone, self).validate(obj, value)
51 else:
52 return value
53
41 54 nbconvert_aliases = {}
42 55 nbconvert_aliases.update(base_aliases)
43 56 nbconvert_aliases.update({
44 'format' : 'NbConvertApp.export_format',
57 'to' : 'NbConvertApp.export_format',
58 'template' : 'Exporter.template_file',
45 59 'notebooks' : 'NbConvertApp.notebooks',
46 60 'writer' : 'NbConvertApp.writer_class',
61 'post': 'NbConvertApp.post_processor_class'
47 62 })
48 63
49 64 nbconvert_flags = {}
50 65 nbconvert_flags.update(base_flags)
51 66 nbconvert_flags.update({
52 67 'stdout' : (
53 68 {'NbConvertApp' : {'writer_class' : "StdoutWriter"}},
54 69 "Write notebook output to stdout instead of files."
55 70 )
56 71 })
57 72
58 73
59 74 class NbConvertApp(BaseIPythonApplication):
60 75 """Application used to convert to and from notebook file type (*.ipynb)"""
61 76
62 77 name = 'ipython-nbconvert'
63 78 aliases = nbconvert_aliases
64 79 flags = nbconvert_flags
65 80
66 81 def _classes_default(self):
67 82 classes = [NbConvertBase]
68 83 for pkg in (exporters, transformers, writers):
69 84 for name in dir(pkg):
70 85 cls = getattr(pkg, name)
71 86 if isinstance(cls, type) and issubclass(cls, Configurable):
72 87 classes.append(cls)
73 88 return classes
74 89
75 90 description = Unicode(
76 91 u"""This application is used to convert notebook files (*.ipynb)
77 to various other formats.""")
92 to various other formats.
93
94 WARNING: THE COMMANDLINE INTERFACE MAY CHANGE IN FUTURE RELEASES.""")
78 95
79 96 examples = Unicode(u"""
80 97 The simplest way to use nbconvert is
81 98
82 99 > ipython nbconvert mynotebook.ipynb
83 100
84 101 which will convert mynotebook.ipynb to the default format (probably HTML).
85 102
86 You can specify the export format with `--format`.
103 You can specify the export format with `--to`.
87 104 Options include {0}
88 105
89 > ipython nbconvert --format latex mynotebook.ipnynb
106 > ipython nbconvert --to latex mynotebook.ipnynb
107
108 Both HTML and LaTeX support multiple output templates. LaTeX includes
109 'basic', 'book', and 'article'. HTML includes 'basic' and 'full'. You
110 can specify the flavor of the format used.
111
112 > ipython nbconvert --to html --template basic mynotebook.ipynb
90 113
91 114 You can also pipe the output to stdout, rather than a file
92 115
93 116 > ipython nbconvert mynotebook.ipynb --stdout
117
118 A post-processor can be used to compile a PDF
119
120 > ipython nbconvert mynotebook.ipynb --to latex --post PDF
94 121
95 122 Multiple notebooks can be given at the command line in a couple of
96 123 different ways:
97 124
98 125 > ipython nbconvert notebook*.ipynb
99 126 > ipython nbconvert notebook1.ipynb notebook2.ipynb
100 127
101 128 or you can specify the notebooks list in a config file, containing::
102 129
103 130 c.NbConvertApp.notebooks = ["my_notebook.ipynb"]
104 131
105 132 > ipython nbconvert --config mycfg.py
106 133 """.format(get_export_names()))
134
107 135 # Writer specific variables
108 136 writer = Instance('IPython.nbconvert.writers.base.WriterBase',
109 137 help="""Instance of the writer class used to write the
110 138 results of the conversion.""")
111 139 writer_class = DottedObjectName('FilesWriter', config=True,
112 140 help="""Writer class used to write the
113 141 results of the conversion""")
114 142 writer_aliases = {'FilesWriter': 'IPython.nbconvert.writers.files.FilesWriter',
115 143 'DebugWriter': 'IPython.nbconvert.writers.debug.DebugWriter',
116 144 'StdoutWriter': 'IPython.nbconvert.writers.stdout.StdoutWriter'}
117 145 writer_factory = Type()
118 146
119 147 def _writer_class_changed(self, name, old, new):
120 148 if new in self.writer_aliases:
121 149 new = self.writer_aliases[new]
122 150 self.writer_factory = import_item(new)
123 151
152 # Post-processor specific variables
153 post_processor = Instance('IPython.nbconvert.post_processors.base.PostProcessorBase',
154 help="""Instance of the PostProcessor class used to write the
155 results of the conversion.""")
156
157 post_processor_class = DottedOrNone(config=True,
158 help="""PostProcessor class used to write the
159 results of the conversion""")
160 post_processor_aliases = {'PDF': 'IPython.nbconvert.post_processors.pdf.PDFPostProcessor'}
161 post_processor_factory = Type()
162
163 def _post_processor_class_changed(self, name, old, new):
164 if new in self.post_processor_aliases:
165 new = self.post_processor_aliases[new]
166 if new:
167 self.post_processor_factory = import_item(new)
168
124 169
125 170 # Other configurable variables
126 171 export_format = CaselessStrEnum(get_export_names(),
127 default_value="full_html",
172 default_value="html",
128 173 config=True,
129 174 help="""The export format to be used."""
130 175 )
131 176
132 177 notebooks = List([], config=True, help="""List of notebooks to convert.
133 178 Wildcards are supported.
134 179 Filenames passed positionally will be added to the list.
135 180 """)
136 181
137 182 @catch_config_error
138 183 def initialize(self, argv=None):
139 184 super(NbConvertApp, self).initialize(argv)
140 185 self.init_syspath()
141 186 self.init_notebooks()
142 187 self.init_writer()
188 self.init_post_processor()
189
143 190
144 191
145 192 def init_syspath(self):
146 193 """
147 194 Add the cwd to the sys.path ($PYTHONPATH)
148 195 """
149 196 sys.path.insert(0, os.getcwd())
150 197
151 198
152 199 def init_notebooks(self):
153 200 """Construct the list of notebooks.
154 201 If notebooks are passed on the command-line,
155 202 they override notebooks specified in config files.
156 203 Glob each notebook to replace notebook patterns with filenames.
157 204 """
158 205
159 206 # Specifying notebooks on the command-line overrides (rather than adds)
160 207 # the notebook list
161 208 if self.extra_args:
162 209 patterns = self.extra_args
163 210 else:
164 211 patterns = self.notebooks
165 212
166 213 # Use glob to replace all the notebook patterns with filenames.
167 214 filenames = []
168 215 for pattern in patterns:
169 216
170 217 # Use glob to find matching filenames. Allow the user to convert
171 218 # notebooks without having to type the extension.
172 219 globbed_files = glob.glob(pattern)
173 220 globbed_files.extend(glob.glob(pattern + '.ipynb'))
174 221
175 222 for filename in globbed_files:
176 223 if not filename in filenames:
177 224 filenames.append(filename)
178 225 self.notebooks = filenames
179 226
180 227 def init_writer(self):
181 228 """
182 229 Initialize the writer (which is stateless)
183 230 """
184 231 self._writer_class_changed(None, self.writer_class, self.writer_class)
185 232 self.writer = self.writer_factory(parent=self)
186 233
234 def init_post_processor(self):
235 """
236 Initialize the post_processor (which is stateless)
237 """
238 self._post_processor_class_changed(None, self.post_processor_class,
239 self.post_processor_class)
240 if self.post_processor_factory:
241 self.post_processor = self.post_processor_factory(parent=self)
242
187 243 def start(self):
188 244 """
189 245 Ran after initialization completed
190 246 """
191 247 super(NbConvertApp, self).start()
192 248 self.convert_notebooks()
193 249
194 250 def convert_notebooks(self):
195 251 """
196 252 Convert the notebooks in the self.notebook traitlet
197 253 """
198 254 # Export each notebook
199 255 conversion_success = 0
200 256 for notebook_filename in self.notebooks:
201 257
202 258 # Get a unique key for the notebook and set it in the resources object.
203 259 basename = os.path.basename(notebook_filename)
204 260 notebook_name = basename[:basename.rfind('.')]
205 261 resources = {}
206 262 resources['unique_key'] = notebook_name
207 263 resources['output_files_dir'] = '%s_files' % notebook_name
208 264
209 265 # Try to export
210 266 try:
211 267 output, resources = export_by_name(self.export_format,
212 268 notebook_filename,
213 269 resources=resources,
214 270 config=self.config)
215 271 except ExporterNameError as e:
216 272 print("Error while converting '%s': '%s' exporter not found."
217 273 %(notebook_filename, self.export_format),
218 274 file=sys.stderr)
219 275 print("Known exporters are:",
220 276 "\n\t" + "\n\t".join(get_export_names()),
221 277 file=sys.stderr)
222 278 self.exit(1)
223 279 except ConversionException as e:
224 280 print("Error while converting '%s': %s" %(notebook_filename, e),
225 281 file=sys.stderr)
226 282 self.exit(1)
227 283 else:
228 self.writer.write(output, resources, notebook_name=notebook_name)
284 write_resultes = self.writer.write(output, resources, notebook_name=notebook_name)
285
286 #Post-process if post processor has been defined.
287 if hasattr(self, 'post_processor') and self.post_processor:
288 self.post_processor(write_resultes)
229 289 conversion_success += 1
230 290
231 291 # If nothing was converted successfully, help the user.
232 292 if conversion_success == 0:
233 293 self.print_help()
234 294 sys.exit(-1)
235 295
236 296
237 297 #-----------------------------------------------------------------------------
238 298 # Main entry point
239 299 #-----------------------------------------------------------------------------
240 300
241 301 launch_new_instance = NbConvertApp.launch_instance
@@ -1,34 +1,35 b''
1 1 """
2 Exporter for exporting notebooks to Sphinx 'Manual' style latex. Latex
3 formatted for use with PDFLatex.
2 Basic post processor
4 3 """
5 4 #-----------------------------------------------------------------------------
6 # Copyright (c) 2013, the IPython Development Team.
5 #Copyright (c) 2013, the IPython Development Team.
7 6 #
8 # Distributed under the terms of the Modified BSD License.
7 #Distributed under the terms of the Modified BSD License.
9 8 #
10 # The full license is in the file COPYING.txt, distributed with this software.
9 #The full license is in the file COPYING.txt, distributed with this software.
11 10 #-----------------------------------------------------------------------------
12 11
13 12 #-----------------------------------------------------------------------------
14 13 # Imports
15 14 #-----------------------------------------------------------------------------
16 15
17 from IPython.utils.traitlets import Unicode
16 from ..utils.base import NbConvertBase
18 17
19 from .sphinx_howto import SphinxHowtoExporter
20 18
21 19 #-----------------------------------------------------------------------------
22 20 # Classes
23 21 #-----------------------------------------------------------------------------
22 class PostProcessorBase(NbConvertBase):
24 23
25 class SphinxManualExporter(SphinxHowtoExporter):
26 """
27 Exports Sphinx "Manual" LaTeX documents. The Sphinx "Manual" exporter
28 produces book like latex output for use with PDFLatex.
29 """
30
31 template_file = Unicode(
32 'sphinx_manual', config=True,
33 help="Name of the template file to use")
34 No newline at end of file
24 def __call__(self, input):
25 """
26 See def call() ...
27 """
28 self.call(input)
29
30
31 def call(self, input):
32 """
33 Post-process output from a writer.
34 """
35 raise NotImplementedError('call')
1 NO CONTENT: file renamed from IPython/nbconvert/templates/basichtml.tpl to IPython/nbconvert/templates/html_basic.tpl
@@ -1,68 +1,68 b''
1 {%- extends 'basichtml.tpl' -%}
1 {%- extends 'html_basic.tpl' -%}
2 2
3 3 {%- block header -%}<!DOCTYPE html>
4 4 <html>
5 5 <head>
6 6 <meta charset="UTF-8">
7 7 <title>[{{nb.metadata.name}}]</title>
8 8 {% for css in resources.inlining.css -%}
9 9 <style type="text/css">
10 10 {{css}}
11 11 </style>
12 12 {% endfor %}
13 13
14 14 <style type="text/css">
15 15 /* Overrides of notebook CSS for static HTML export */
16 16 body {
17 17 overflow: visible;
18 18 padding: 8px;
19 19 }
20 20 .input_area {
21 21 padding: 0.2em;
22 22 }
23 23
24 24 pre {
25 25 padding: 0.2em;
26 26 border: none;
27 27 margin: 0px;
28 28 font-size: 13px;
29 29 }
30 30 </style>
31 31
32 32 <!-- Custom stylesheet, it must be in the same directory as the html file -->
33 33 <link rel="stylesheet" href="custom.css">
34 34
35 35 <script src="https://c328740.ssl.cf1.rackcdn.com/mathjax/latest/MathJax.js?config=TeX-AMS_HTML" type="text/javascript">
36 36
37 37 </script>
38 38 <script type="text/javascript">
39 39 init_mathjax = function() {
40 40 if (window.MathJax) {
41 41 // MathJax loaded
42 42 MathJax.Hub.Config({
43 43 tex2jax: {
44 44 inlineMath: [ ['$','$'], ["\\(","\\)"] ],
45 45 displayMath: [ ['$$','$$'], ["\\[","\\]"] ]
46 46 },
47 47 displayAlign: 'left', // Change this to 'center' to center equations.
48 48 "HTML-CSS": {
49 49 styles: {'.MathJax_Display': {"margin": 0}}
50 50 }
51 51 });
52 52 MathJax.Hub.Queue(["Typeset",MathJax.Hub]);
53 53 }
54 54 }
55 55 init_mathjax();
56 56 </script>
57 57 </head>
58 58 {%- endblock header -%}
59 59
60 60
61 61 {% block body %}
62 62 <body>{{ super() }}
63 63 </body>
64 64 {%- endblock body %}
65 65
66 66
67 67 {% block footer %}
68 68 </html>{% endblock footer %}
@@ -1,25 +1,25 b''
1 1 ((============================================================================
2 2 NBConvert Sphinx-Latex HowTo Template
3 3
4 4 Purpose: Allow export of PDF friendly Latex inspired by Sphinx HowTo
5 5 document style. Most of the is derived directly from Sphinx source.
6 6
7 Inheritance: null>display_priority>latex_base->latex_sphinx_base
7 Inheritance: null>display_priority>sphinx
8 8
9 9 ==========================================================================))
10 10
11 ((*- extends 'sphinx_base.tplx' -*))
11 ((*- extends 'sphinx.tplx' -*))
12 12
13 13 ((* set parentdocumentclass = 'article' *))
14 14 ((* set documentclass = 'howto' *))
15 15
16 16 ((* block h1 -*))part((* endblock h1 -*))
17 17 ((* block h2 -*))section((* endblock h2 -*))
18 18 ((* block h3 -*))subsection((* endblock h3 -*))
19 19 ((* block h4 -*))subsubsection((* endblock h4 -*))
20 20 ((* block h5 -*))paragraph((* endblock h5 -*))
21 21 ((* block h6 -*))subparagraph((* endblock h6 -*))
22 22
23 23 % Diasble table of contents for howto
24 24 ((* block toc *))
25 25 ((* endblock toc *))
@@ -1,258 +1,260 b''
1 1 ((*- extends 'display_priority.tplx' -*))
2 2
3 \nonstopmode
4
3 5 ((* block in_prompt *))((* endblock in_prompt *))
4 6
5 7 ((* block output_prompt *))((* endblock output_prompt *))
6 8
7 9 ((* block codecell *))\begin{codecell}((( super() )))
8 10 \end{codecell}
9 11 ((* endblock *))
10 12
11 13 ((* block input *))
12 14 \begin{codeinput}
13 15 \begin{lstlisting}
14 16 ((( cell.input )))
15 17 \end{lstlisting}
16 18 \end{codeinput}
17 19 ((* endblock input *))
18 20
19 21
20 22 ((= Those Two are for error displaying
21 23 even if the first one seem to do nothing,
22 24 it introduces a new line
23 25
24 26 =))
25 27 ((* block pyerr *))
26 28 \begin{traceback}
27 29 \begin{verbatim}((( super() )))
28 30 \end{verbatim}
29 31 \end{traceback}
30 32 ((* endblock pyerr *))
31 33
32 34 ((* block traceback_line *))
33 35 ((( line |indent| strip_ansi )))((* endblock traceback_line *))
34 36 ((= .... =))
35 37
36 38
37 39 ((*- block output_group -*))
38 40 \begin{codeoutput}
39 41 ((( super() )))
40 42 \end{codeoutput}((* endblock *))
41 43
42 44 ((*- block data_png -*))
43 45 \begin{center}
44 46 \includegraphics[max size={0.7\textwidth}{0.9\textheight}]{(((output.png_filename)))}
45 47 \par
46 48 \end{center}
47 49 ((*- endblock -*))
48 50
49 51 ((*- block data_jpg -*))
50 52 \begin{center}
51 53 \includegraphics[max size={0.7\textwidth}{0.9\textheight}]{(((output.jpeg_filename)))}
52 54 \par
53 55 \end{center}
54 56 ((*- endblock -*))
55 57
56 58 ((*- block data_svg -*))
57 59 \begin{center}
58 60 \includegraphics[width=0.7\textwidth]{(((output.svg_filename)))}
59 61 \par
60 62 \end{center}
61 63 ((*- endblock -*))
62 64
63 65 ((*- block data_pdf -*))
64 66 \begin{center}
65 67 \includegraphics[width=0.7\textwidth]{(((output.pdf_filename)))}
66 68 \par
67 69 \end{center}
68 70 ((*- endblock -*))
69 71
70 72 ((* block pyout *))
71 73 ((* block data_priority scoped *))((( super() )))((* endblock *))
72 74 ((* endblock pyout *))
73 75
74 76 ((* block data_text *))
75 77 \begin{verbatim}
76 78 ((( output.text )))
77 79 \end{verbatim}
78 80 ((* endblock *))
79 81
80 82 ((* block data_latex -*))
81 83 ((*- if output.latex.startswith('$'): -*)) \begin{equation*}
82 84 ((( output.latex | strip_dollars)))
83 85 \end{equation*}
84 86 ((*- else -*)) ((( output.latex ))) ((*- endif *))
85 87 ((* endblock *))
86 88
87 89 ((* block stream *))
88 90 \begin{Verbatim}[commandchars=\\\{\}]
89 91 ((( output.text | ansi2latex)))
90 92 \end{Verbatim}
91 93 ((* endblock stream *))
92 94
93 95 ((* block markdowncell scoped *))((( cell.source | markdown2latex )))
94 96 ((* endblock markdowncell *))
95 97
96 98 ((* block headingcell scoped -*))
97 99 ((( ('#' * cell.level + cell.source) | replace('\n', ' ') | markdown2latex )))
98 100 ((* endblock headingcell *))
99 101
100 102 ((* block rawcell scoped *))
101 103 ((( cell.source | comment_lines )))
102 104 ((* endblock rawcell *))
103 105
104 106 ((* block unknowncell scoped *))
105 107 unknown type (((cell.type)))
106 108 ((* endblock unknowncell *))
107 109
108 110
109 111
110 112 ((* block body *))
111 113
112 114 ((* block bodyBegin *))
113 115 \begin{document}
114 116 ((* endblock bodyBegin *))
115 117
116 118 ((( super() )))
117 119
118 120 ((* block bodyEnd *))
119 121 \end{document}
120 122 ((* endblock bodyEnd *))
121 123 ((* endblock body *))
122 124
123 125 ((* block header *))
124 126 %% This file was auto-generated by IPython.
125 127 %% Conversion from the original notebook file:
126 128 %%
127 129 \documentclass[11pt,english]{article}
128 130
129 131 %% This is the automatic preamble used by IPython. Note that it does *not*
130 132 %% include a documentclass declaration, that is added at runtime to the overall
131 133 %% document.
132 134
133 135 \usepackage{amsmath}
134 136 \usepackage{amssymb}
135 137 \usepackage{graphicx}
136 138 \usepackage{ucs}
137 139 \usepackage[utf8x]{inputenc}
138 140
139 141 % Scale down larger images
140 142 \usepackage[export]{adjustbox}
141 143
142 144 %fancy verbatim
143 145 \usepackage{fancyvrb}
144 146 % needed for markdown enumerations to work
145 147 \usepackage{enumerate}
146 148
147 149 % Slightly bigger margins than the latex defaults
148 150 \usepackage{geometry}
149 151 \geometry{verbose,tmargin=3cm,bmargin=3cm,lmargin=2.5cm,rmargin=2.5cm}
150 152
151 153 % Define a few colors for use in code, links and cell shading
152 154 \usepackage{color}
153 155 \definecolor{orange}{cmyk}{0,0.4,0.8,0.2}
154 156 \definecolor{darkorange}{rgb}{.71,0.21,0.01}
155 157 \definecolor{darkgreen}{rgb}{.12,.54,.11}
156 158 \definecolor{myteal}{rgb}{.26, .44, .56}
157 159 \definecolor{gray}{gray}{0.45}
158 160 \definecolor{lightgray}{gray}{.95}
159 161 \definecolor{mediumgray}{gray}{.8}
160 162 \definecolor{inputbackground}{rgb}{.95, .95, .85}
161 163 \definecolor{outputbackground}{rgb}{.95, .95, .95}
162 164 \definecolor{traceback}{rgb}{1, .95, .95}
163 165
164 166 % new ansi colors
165 167 \definecolor{brown}{rgb}{0.54,0.27,0.07}
166 168 \definecolor{purple}{rgb}{0.5,0.0,0.5}
167 169 \definecolor{darkgray}{gray}{0.25}
168 170 \definecolor{lightred}{rgb}{1.0,0.39,0.28}
169 171 \definecolor{lightgreen}{rgb}{0.48,0.99,0.0}
170 172 \definecolor{lightblue}{rgb}{0.53,0.81,0.92}
171 173 \definecolor{lightpurple}{rgb}{0.87,0.63,0.87}
172 174 \definecolor{lightcyan}{rgb}{0.5,1.0,0.83}
173 175
174 176 % Framed environments for code cells (inputs, outputs, errors, ...). The
175 177 % various uses of \unskip (or not) at the end were fine-tuned by hand, so don't
176 178 % randomly change them unless you're sure of the effect it will have.
177 179 \usepackage{framed}
178 180
179 181 % remove extraneous vertical space in boxes
180 182 \setlength\fboxsep{0pt}
181 183
182 184 % codecell is the whole input+output set of blocks that a Code cell can
183 185 % generate.
184 186
185 187 % TODO: unfortunately, it seems that using a framed codecell environment breaks
186 188 % the ability of the frames inside of it to be broken across pages. This
187 189 % causes at least the problem of having lots of empty space at the bottom of
188 190 % pages as new frames are moved to the next page, and if a single frame is too
189 191 % long to fit on a page, will completely stop latex from compiling the
190 192 % document. So unless we figure out a solution to this, we'll have to instead
191 193 % leave the codecell env. as empty. I'm keeping the original codecell
192 194 % definition here (a thin vertical bar) for reference, in case we find a
193 195 % solution to the page break issue.
194 196
195 197 %% \newenvironment{codecell}{%
196 198 %% \def\FrameCommand{\color{mediumgray} \vrule width 1pt \hspace{5pt}}%
197 199 %% \MakeFramed{\vspace{-0.5em}}}
198 200 %% {\unskip\endMakeFramed}
199 201
200 202 % For now, make this a no-op...
201 203 \newenvironment{codecell}{}
202 204
203 205 \newenvironment{codeinput}{%
204 206 \def\FrameCommand{\colorbox{inputbackground}}%
205 207 \MakeFramed{\advance\hsize-\width \FrameRestore}}
206 208 {\unskip\endMakeFramed}
207 209
208 210 \newenvironment{codeoutput}{%
209 211 \def\FrameCommand{\colorbox{outputbackground}}%
210 212 \vspace{-1.4em}
211 213 \MakeFramed{\advance\hsize-\width \FrameRestore}}
212 214 {\unskip\medskip\endMakeFramed}
213 215
214 216 \newenvironment{traceback}{%
215 217 \def\FrameCommand{\colorbox{traceback}}%
216 218 \MakeFramed{\advance\hsize-\width \FrameRestore}}
217 219 {\endMakeFramed}
218 220
219 221 % Use and configure listings package for nicely formatted code
220 222 \usepackage{listingsutf8}
221 223 \lstset{
222 224 language=python,
223 225 inputencoding=utf8x,
224 226 extendedchars=\true,
225 227 aboveskip=\smallskipamount,
226 228 belowskip=\smallskipamount,
227 229 xleftmargin=2mm,
228 230 breaklines=true,
229 231 basicstyle=\small \ttfamily,
230 232 showstringspaces=false,
231 233 keywordstyle=\color{blue}\bfseries,
232 234 commentstyle=\color{myteal},
233 235 stringstyle=\color{darkgreen},
234 236 identifierstyle=\color{darkorange},
235 237 columns=fullflexible, % tighter character kerning, like verb
236 238 }
237 239
238 240 % The hyperref package gives us a pdf with properly built
239 241 % internal navigation ('pdf bookmarks' for the table of contents,
240 242 % internal cross-reference links, web links for URLs, etc.)
241 243 \usepackage{hyperref}
242 244 \hypersetup{
243 245 breaklinks=true, % so long urls are correctly broken across lines
244 246 colorlinks=true,
245 247 urlcolor=blue,
246 248 linkcolor=darkorange,
247 249 citecolor=darkgreen,
248 250 }
249 251
250 252 % hardcode size of all verbatim environments to be a bit smaller
251 253 \makeatletter
252 254 \g@addto@macro\@verbatim\small\topsep=0.5em\partopsep=0pt
253 255 \makeatother
254 256
255 257 % Prevent overflowing lines due to urls and other hard-to-break entities.
256 258 \sloppy
257 259
258 260 ((* endblock *))
@@ -1,21 +1,21 b''
1 1 ((============================================================================
2 2 NBConvert Sphinx-Latex Manual Template
3 3
4 4 Purpose: Allow export of PDF friendly Latex inspired by Sphinx Manual
5 5 document style. Most of the is derived directly from Sphinx source.
6 6
7 Inheritance: null>display_priority>latex_base->latex_sphinx_base
7 Inheritance: null>display_priority>sphinx
8 8
9 9 ==========================================================================))
10 10
11 ((*- extends 'sphinx_base.tplx' -*))
11 ((*- extends 'sphinx.tplx' -*))
12 12
13 13 ((* set parentdocumentclass = 'report' *))
14 14 ((* set documentclass = 'manual' *))
15 15
16 16 ((* block h1 -*))part((* endblock h1 -*))
17 17 ((* block h2 -*))chapter((* endblock h2 -*))
18 18 ((* block h3 -*))section((* endblock h3 -*))
19 19 ((* block h4 -*))subsection((* endblock h4 -*))
20 20 ((* block h5 -*))subsubsection((* endblock h5 -*))
21 21 ((* block h6 -*))paragraph((* endblock h6 -*))
@@ -1,450 +1,452 b''
1 1 ((= NBConvert Sphinx-Latex Template
2 2
3 3 Purpose: Allow export of PDF friendly Latex inspired by Sphinx. Most of the
4 4 template is derived directly from Sphinx source.
5 5
6 6 Inheritance: null>display_priority
7 7
8 8 Note: For best display, use latex syntax highlighting. =))
9 9
10 10 ((*- extends 'display_priority.tplx' -*))
11 11
12 \nonstopmode
13
12 14 %==============================================================================
13 15 % Declarations
14 16 %==============================================================================
15 17
16 18 % In order to make sure that the input/output header follows the code it
17 19 % preceeds, the needspace package is used to request that a certain
18 20 % amount of lines (specified by this variable) are reserved. If those
19 21 % lines aren't available on the current page, the documenter will break
20 22 % to the next page and the header along with accomanying lines will be
21 23 % rendered together. This value specifies the number of lines that
22 24 % the header will be forced to group with without a page break.
23 25 ((*- set min_header_lines = 4 -*))
24 26
25 27 % This is the number of characters that are permitted per line. It's
26 28 % important that this limit is set so characters do not run off the
27 29 % edges of latex pages (since latex does not always seem smart enough
28 30 % to prevent this in some cases.) This is only applied to textual output
29 31 ((* if resources.sphinx.outputstyle == 'simple' *))
30 32 ((*- set wrap_size = 85 -*))
31 33 ((* elif resources.sphinx.outputstyle == 'notebook' *))
32 34 ((*- set wrap_size = 70 -*))
33 35 ((* endif *))
34 36
35 37 %==============================================================================
36 38 % Header
37 39 %==============================================================================
38 40 ((* block header *))
39 41
40 42 % Header, overrides base
41 43
42 44 % Make sure that the sphinx doc style knows who it inherits from.
43 45 \def\sphinxdocclass{(((parentdocumentclass)))}
44 46
45 47 % Declare the document class
46 48 \documentclass[letterpaper,10pt,english]{((( resources.sphinx.texinputs )))/sphinx(((documentclass)))}
47 49
48 50 % Imports
49 51 \usepackage[utf8]{inputenc}
50 52 \DeclareUnicodeCharacter{00A0}{\\nobreakspace}
51 53 \usepackage[T1]{fontenc}
52 54 \usepackage{babel}
53 55 \usepackage{times}
54 56 \usepackage{import}
55 57 \usepackage[((( resources.sphinx.chapterstyle )))]{((( resources.sphinx.texinputs )))/fncychap}
56 58 \usepackage{longtable}
57 59 \usepackage{((( resources.sphinx.texinputs )))/sphinx}
58 60 \usepackage{multirow}
59 61
60 62 \usepackage{amsmath}
61 63 \usepackage{amssymb}
62 64 \usepackage{ucs}
63 65 \usepackage{enumerate}
64 66
65 67 % Used to make the Input/Output rules follow around the contents.
66 68 \usepackage{needspace}
67 69
68 70 % Pygments requirements
69 71 \usepackage{fancyvrb}
70 72 \usepackage{color}
71 73 % ansi colors additions
72 74 \definecolor{darkgreen}{rgb}{.12,.54,.11}
73 75 \definecolor{lightgray}{gray}{.95}
74 76 \definecolor{brown}{rgb}{0.54,0.27,0.07}
75 77 \definecolor{purple}{rgb}{0.5,0.0,0.5}
76 78 \definecolor{darkgray}{gray}{0.25}
77 79 \definecolor{lightred}{rgb}{1.0,0.39,0.28}
78 80 \definecolor{lightgreen}{rgb}{0.48,0.99,0.0}
79 81 \definecolor{lightblue}{rgb}{0.53,0.81,0.92}
80 82 \definecolor{lightpurple}{rgb}{0.87,0.63,0.87}
81 83 \definecolor{lightcyan}{rgb}{0.5,1.0,0.83}
82 84
83 85 % Needed to box output/input
84 86 \usepackage{tikz}
85 87 \usetikzlibrary{calc,arrows,shadows}
86 88 \usepackage[framemethod=tikz]{mdframed}
87 89
88 90 \usepackage{alltt}
89 91
90 92 % Used to load and display graphics
91 93 \usepackage{graphicx}
92 94 \graphicspath{ {figs/} }
93 95 \usepackage[Export]{adjustbox} % To resize
94 96
95 97
96 98 % For formatting output while also word wrapping.
97 99 \usepackage{listings}
98 100 \lstset{breaklines=true}
99 101 \lstset{basicstyle=\small\ttfamily}
100 102 \def\smaller{\fontsize{9.5pt}{9.5pt}\selectfont}
101 103
102 104 %Pygments definitions
103 105 ((( resources.sphinx.pygment_definitions )))
104 106
105 107 %Set pygments styles if needed...
106 108 ((* if resources.sphinx.outputstyle == 'notebook' *))
107 109 \definecolor{nbframe-border}{rgb}{0.867,0.867,0.867}
108 110 \definecolor{nbframe-bg}{rgb}{0.969,0.969,0.969}
109 111 \definecolor{nbframe-in-prompt}{rgb}{0.0,0.0,0.502}
110 112 \definecolor{nbframe-out-prompt}{rgb}{0.545,0.0,0.0}
111 113
112 114 \newenvironment{ColorVerbatim}
113 115 {\begin{mdframed}[%
114 116 roundcorner=1.0pt, %
115 117 backgroundcolor=nbframe-bg, %
116 118 userdefinedwidth=1\linewidth, %
117 119 leftmargin=0.1\linewidth, %
118 120 innerleftmargin=0pt, %
119 121 innerrightmargin=0pt, %
120 122 linecolor=nbframe-border, %
121 123 linewidth=1pt, %
122 124 usetwoside=false, %
123 125 everyline=true, %
124 126 innerlinewidth=3pt, %
125 127 innerlinecolor=nbframe-bg, %
126 128 middlelinewidth=1pt, %
127 129 middlelinecolor=nbframe-bg, %
128 130 outerlinewidth=0.5pt, %
129 131 outerlinecolor=nbframe-border, %
130 132 needspace=0pt
131 133 ]}
132 134 {\end{mdframed}}
133 135
134 136 \newenvironment{InvisibleVerbatim}
135 137 {\begin{mdframed}[leftmargin=0.1\linewidth,innerleftmargin=3pt,innerrightmargin=3pt, userdefinedwidth=1\linewidth, linewidth=0pt, linecolor=white, usetwoside=false]}
136 138 {\end{mdframed}}
137 139
138 140 \renewenvironment{Verbatim}[1][\unskip]
139 141 {\begin{alltt}\smaller}
140 142 {\end{alltt}}
141 143 ((* endif *))
142 144
143 145 % Help prevent overflowing lines due to urls and other hard-to-break
144 146 % entities. This doesn't catch everything...
145 147 \sloppy
146 148
147 149 % Document level variables
148 150 \title{((( resources.metadata.name | escape_latex )))}
149 151 \date{((( resources.sphinx.date | escape_latex )))}
150 152 \release{((( resources.sphinx.version | escape_latex )))}
151 153 \author{((( resources.sphinx.author | escape_latex )))}
152 154 \renewcommand{\releasename}{((( resources.sphinx.release | escape_latex )))}
153 155
154 156 % TODO: Add option for the user to specify a logo for his/her export.
155 157 \newcommand{\sphinxlogo}{}
156 158
157 159 % Make the index page of the document.
158 160 \makeindex
159 161
160 162 % Import sphinx document type specifics.
161 163 ((* block sphinxheader *))((* endblock sphinxheader *))
162 164 ((* endblock header *))
163 165
164 166 %==============================================================================
165 167 % Body
166 168 %==============================================================================
167 169 ((* block body *))
168 170 ((* block bodyBegin *))
169 171 % Body
170 172
171 173 % Start of the document
172 174 \begin{document}
173 175
174 176 ((* if resources.sphinx.header *))
175 177 \maketitle
176 178 ((* endif *))
177 179
178 180 ((* block toc *))
179 181 \tableofcontents
180 182 ((* endblock toc *))
181 183
182 184 ((* endblock bodyBegin *))((( super() )))((* block bodyEnd *))
183 185
184 186 \renewcommand{\indexname}{Index}
185 187 \printindex
186 188
187 189 % End of document
188 190 \end{document}
189 191 ((* endblock bodyEnd *))
190 192 ((* endblock body *))
191 193
192 194 %==============================================================================
193 195 % Footer
194 196 %==============================================================================
195 197 ((* block footer *))
196 198 ((* endblock footer *))
197 199
198 200 %==============================================================================
199 201 % Headings
200 202 %
201 203 % Purpose: Format pynb headers as sphinx headers. Depending on the Sphinx
202 204 % style that is active, this will change. Thus sphinx styles will
203 205 % override the values here.
204 206 %==============================================================================
205 207 ((* block headingcell -*))
206 208 \
207 209 ((*- if cell.level == 1 -*))
208 210 ((* block h1 -*))part((* endblock h1 -*))
209 211 ((*- elif cell.level == 2 -*))
210 212 ((* block h2 -*))chapter((* endblock h2 -*))
211 213 ((*- elif cell.level == 3 -*))
212 214 ((* block h3 -*))section((* endblock h3 -*))
213 215 ((*- elif cell.level == 4 -*))
214 216 ((* block h4 -*))subsection((* endblock h4 -*))
215 217 ((*- elif cell.level == 5 -*))
216 218 ((* block h5 -*))subsubsection((* endblock h5 -*))
217 219 ((*- elif cell.level == 6 -*))
218 220 ((* block h6 -*))paragraph((* endblock h6 -*))
219 221
220 222 ((= It's important to make sure that underscores (which tend to be common
221 223 in IPYNB file titles) do not make their way into latex. Sometimes this
222 224 causes latex to barf. =))
223 225 ((*- endif -*)){((( cell.source | markdown2latex )))}
224 226 ((*- endblock headingcell *))
225 227
226 228 %==============================================================================
227 229 % Markdown
228 230 %
229 231 % Purpose: Convert markdown to latex. Here markdown2latex is explicitly
230 232 % called since we know we want latex output.
231 233 %==============================================================================
232 234 ((*- block markdowncell scoped-*))
233 235 ((( cell.source | markdown2latex )))
234 236 ((*- endblock markdowncell -*))
235 237
236 238 %==============================================================================
237 239 % Rawcell
238 240 %
239 241 % Purpose: Raw text cells allow the user to manually inject document code that
240 242 % will not get touched by the templating system.
241 243 %==============================================================================
242 244 ((*- block rawcell *))
243 245 ((( cell.source | wrap_text(wrap_size) )))
244 246 ((* endblock rawcell -*))
245 247
246 248 %==============================================================================
247 249 % Unknowncell
248 250 %
249 251 % Purpose: This is the catch anything unhandled. To display this data, we
250 252 % remove all possible latex conflicts and wrap the characters so they
251 253 % can't flow off of the page.
252 254 %==============================================================================
253 255 ((* block unknowncell scoped*))
254 256
255 257 % Unsupported cell type, no formatting
256 258 ((( cell.source | wrap_text | escape_latex )))
257 259 ((* endblock unknowncell *))
258 260
259 261 %==============================================================================
260 262 % Input
261 263 %==============================================================================
262 264 ((* block input *))
263 265
264 266 % Make sure that atleast 4 lines are below the HR
265 267 \needspace{((( min_header_lines )))\baselineskip}
266 268
267 269 ((* if resources.sphinx.outputstyle == 'simple' *))
268 270
269 271 % Add a horizantal break, along with break title.
270 272 \vspace{10pt}
271 273 {\scriptsize Input}\\*
272 274 \rule[10pt]{\linewidth}{0.5pt}
273 275 \vspace{-25pt}
274 276
275 277 % Add contents below.
276 278 ((( cell.input | highlight2latex )))
277 279
278 280 ((* elif resources.sphinx.outputstyle == 'notebook' *))
279 281 \vspace{6pt}
280 282 ((( write_prompt("In", cell.prompt_number, "nbframe-in-prompt") )))
281 283 \vspace{-2.65\baselineskip}
282 284 \begin{ColorVerbatim}
283 285 \vspace{-0.7\baselineskip}
284 286 ((( cell.input | highlight2latex )))
285 287 ((* if cell.input == None or cell.input == '' *))
286 288 \vspace{0.3\baselineskip}
287 289 ((* else *))
288 290 \vspace{-0.2\baselineskip}
289 291 ((* endif *))
290 292 \end{ColorVerbatim}
291 293 ((* endif *))
292 294 ((* endblock input *))
293 295
294 296 %==============================================================================
295 297 % Output_Group
296 298 %
297 299 % Purpose: Make sure that only one header bar only attaches to the output
298 300 % once. By keeping track of when an input group is started
299 301 %==============================================================================
300 302 ((* block output_group *))
301 303 ((* if cell.outputs.__len__() > 0 *))
302 304
303 305 % If the first block is an image, minipage the image. Else
304 306 % request a certain amount of space for the input text.
305 307 ((( iff_figure(cell.outputs[0], "\\begin{minipage}{1.0\\textwidth}", "\\needspace{" ~ min_header_lines ~ "\\baselineskip}") )))
306 308
307 309 ((* if resources.sphinx.outputstyle == 'simple' *))
308 310
309 311 % Add a horizantal break, along with break title.
310 312 \vspace{10pt}
311 313 {\scriptsize Output}\\*
312 314 \rule[10pt]{\linewidth}{0.5pt}
313 315 \vspace{-20pt}
314 316
315 317 % Add the contents of the first block.
316 318 ((( render_output(cell.outputs[0]) )))
317 319
318 320 % Close the minipage.
319 321 ((( iff_figure(cell.outputs[0], "\\end{minipage}", "") )))
320 322
321 323 % Add remainer of the document contents below.
322 324 ((* for output in cell.outputs[1:] *))
323 325 ((( render_output(output, cell.prompt_number) )))
324 326 ((* endfor *))
325 327 ((* elif resources.sphinx.outputstyle == 'notebook' *))
326 328
327 329 % Add document contents.
328 330 ((* for output in cell.outputs *))
329 331 ((( render_output(output, cell.prompt_number) )))
330 332 ((* endfor *))
331 333 ((* endif *))
332 334 ((* endif *))
333 335 ((* endblock *))
334 336
335 337 %==============================================================================
336 338 % Additional formating
337 339 %==============================================================================
338 340 ((* block data_text *))
339 341 ((( custom_verbatim(output.text) | ansi2latex)))
340 342 ((* endblock *))
341 343
342 344 ((* block traceback_line *))
343 345 ((( conditionally_center_output(line | indent| strip_ansi) )))
344 346 ((* endblock traceback_line *))
345 347
346 348 %==============================================================================
347 349 % Supported image formats
348 350 %==============================================================================
349 351 ((*- block data_png -*))
350 352 ((( conditionally_center_output(insert_graphics(output.png_filename)) )))
351 353 ((*- endblock -*))
352 354
353 355 ((*- block data_jpg -*))
354 356 ((( conditionally_center_output(insert_graphics(output.jpg_filename)) )))
355 357 ((*- endblock -*))
356 358
357 359 ((*- block data_svg -*))
358 360 ((( conditionally_center_output(insert_graphics(output.svg_filename)) )))
359 361 ((*- endblock -*))
360 362
361 363 ((*- block data_pdf -*))
362 364 ((( conditionally_center_output(insert_graphics(output.pdf_filename)) )))
363 365 ((*- endblock -*))
364 366
365 367 ((*- block data_latex *))
366 368 ((* if resources.sphinx.centeroutput *))\begin{center}((* endif -*))((( output.latex | strip_math_space )))((*- if resources.sphinx.centeroutput *))\end{center} ((* endif -*))
367 369 ((*- endblock -*))
368 370
369 371 %==============================================================================
370 372 % Support Macros
371 373 %==============================================================================
372 374
373 375 % Name: write_prompt
374 376 % Purpose: Renders an output/input prompt for notebook style pdfs
375 377 ((* macro write_prompt(prompt, number, color) -*))
376 378 \makebox[0.1\linewidth]{\smaller\hfill\tt\color{((( color )))}((( prompt )))\hspace{4pt}{[}((( number ))){]}:\hspace{4pt}}\\*
377 379 ((*- endmacro *))
378 380
379 381 % Name: render_output
380 382 % Purpose: Renders an output block appropriately.
381 383 ((* macro render_output(output, prompt_number) -*))
382 384 ((*- if output.output_type == 'pyerr' -*))
383 385 ((*- block pyerr scoped *))
384 386 ((( custom_verbatim(super()) )))
385 387 ((* endblock pyerr -*))
386 388 ((*- else -*))
387 389
388 390 ((* if resources.sphinx.outputstyle == 'notebook' *))
389 391 ((*- if output.output_type == 'pyout' -*))
390 392 ((( write_prompt("Out", prompt_number, "nbframe-out-prompt") )))
391 393 \vspace{-2.55\baselineskip}
392 394 ((*- endif -*))
393 395
394 396 \begin{InvisibleVerbatim}
395 397 \vspace{-0.5\baselineskip}
396 398 ((*- endif -*))
397 399
398 400 ((*- block display_data scoped -*))
399 401 ((( super() )))
400 402 ((*- endblock display_data -*))
401 403
402 404 ((* if resources.sphinx.outputstyle == 'notebook' *))
403 405 \end{InvisibleVerbatim}
404 406 ((*- endif -*))
405 407 ((*- endif -*))
406 408 ((*- endmacro *))
407 409
408 410 % Name: iff_figure
409 411 % Purpose: If the output block provided is a figure type, the 'true_content'
410 412 % parameter will be returned. Else, the 'false_content'.
411 413 ((* macro iff_figure(output, true_content, false_content) -*))
412 414 ((*- set is_figure = false -*))
413 415 ((*- for type in output | filter_data_type -*))
414 416 ((*- if type in ['pdf', 'svg', 'png', 'jpeg','html']*))
415 417 ((*- set is_figure = true -*))
416 418 ((*- endif -*))
417 419 ((*- endfor -*))
418 420
419 421 ((* if is_figure -*))
420 422 ((( true_content )))
421 423 ((*- else -*))
422 424 ((( false_content )))
423 425 ((*- endif *))
424 426 ((*- endmacro *))
425 427
426 428 % Name: custom_verbatim
427 429 % Purpose: This macro creates a verbatim style block that fits the existing
428 430 % sphinx style more readily than standard verbatim blocks.
429 431 ((* macro custom_verbatim(text) -*))
430 432 \begin{alltt}
431 433 ((*- if resources.sphinx.centeroutput *))\begin{center} ((* endif -*))
432 434 ((( text | wrap_text(wrap_size) )))
433 435 ((*- if resources.sphinx.centeroutput *))\end{center}((* endif -*))
434 436 \end{alltt}
435 437 ((*- endmacro *))
436 438
437 439 % Name: conditionally_center_output
438 440 % Purpose: This macro centers the output if the output centering is enabled.
439 441 ((* macro conditionally_center_output(text) -*))
440 442 ((* if resources.sphinx.centeroutput *)){\centering ((* endif *))((( text )))((* if resources.sphinx.centeroutput *))}((* endif *))
441 443 ((*- endmacro *))
442 444
443 445 % Name: insert_graphics
444 446 % Purpose: This macro will insert an image in the latex document given a path.
445 447 ((* macro insert_graphics(path) -*))
446 448 \begin{center}
447 449 \includegraphics[max size={\textwidth}{\textheight}]{(((path)))}
448 450 \par
449 451 \end{center}
450 452 ((*- endmacro *))
@@ -1,21 +1,21 b''
1 {%- extends 'basichtml.tpl' -%}
1 {%- extends 'html_basic.tpl' -%}
2 2
3 3
4 4
5 5 {%- block any_cell scoped -%}
6 6 {%- if cell.metadata.slide_type in ['-', 'slide', 'subslide'] -%}
7 7 {{ super() }}
8 8 {%- elif cell.metadata.slide_type in ['skip'] -%}
9 9 <div style=display:none>
10 10 {{ super() }}
11 11 </div>
12 12 {%- elif cell.metadata.slide_type in ['notes'] -%}
13 13 <aside class="notes">
14 14 {{ super() }}
15 15 </aside>
16 16 {%- elif cell.metadata.slide_type in ['fragment'] -%}
17 17 <div class="fragment">
18 18 {{ super() }}
19 19 </div>
20 20 {%- endif -%}
21 21 {%- endblock any_cell -%}
1 NO CONTENT: file renamed from IPython/nbconvert/templates/reveal.tpl to IPython/nbconvert/templates/slides_reveal.tpl
@@ -1,178 +1,177 b''
1 #!/usr/bin/env python
2 1 """
3 2 Contains base test class for nbconvert
4 3 """
5 4 #-----------------------------------------------------------------------------
6 5 #Copyright (c) 2013, the IPython Development Team.
7 6 #
8 7 #Distributed under the terms of the Modified BSD License.
9 8 #
10 9 #The full license is in the file COPYING.txt, distributed with this software.
11 10 #-----------------------------------------------------------------------------
12 11
13 12 #-----------------------------------------------------------------------------
14 13 # Imports
15 14 #-----------------------------------------------------------------------------
16 15
17 16 import subprocess
18 17 import os
19 18 import glob
20 19 import shutil
21 20 import sys
22 21
23 22 import IPython
24 23 from IPython.utils.tempdir import TemporaryDirectory
25 24 from IPython.utils import py3compat
26 25
27 26 #-----------------------------------------------------------------------------
28 27 # Classes and functions
29 28 #-----------------------------------------------------------------------------
30 29
31 30 class TemporaryWorkingDirectory(TemporaryDirectory):
32 31 """
33 32 Creates a temporary directory and sets the cwd to that directory.
34 33 Automatically reverts to previous cwd upon cleanup.
35 34 Usage example:
36 35
37 36 with TemporaryWorakingDirectory() as tmpdir:
38 37 ...
39 38 """
40 39
41 40 def __init__(self, **kw):
42 41 """
43 42 Constructor
44 43 """
45 44 super(TemporaryWorkingDirectory, self).__init__(**kw)
46 45
47 46 #Change cwd to new temp dir. Remember old cwd.
48 47 self.old_wd = os.getcwd()
49 48 os.chdir(self.name)
50 49
51 50
52 51 def cleanup(self):
53 52 """
54 53 Destructor
55 54 """
56 55
57 56 #Revert to old cwd.
58 57 os.chdir(self.old_wd)
59 58
60 59 #Cleanup
61 60 super(TemporaryWorkingDirectory, self).cleanup()
62 61
63 62
64 63 class TestsBase(object):
65 64 """Base tests class. Contains usefull fuzzy comparison and nbconvert
66 65 functions."""
67 66
68 67
69 68 def fuzzy_compare(self, a, b, newlines_are_spaces=True, tabs_are_spaces=True,
70 69 fuzzy_spacing=True, ignore_spaces=False,
71 70 ignore_newlines=False, case_sensitive=False):
72 71 """
73 72 Performs a fuzzy comparison of two strings. A fuzzy comparison is a
74 73 comparison that ignores insignificant differences in the two comparands.
75 74 The significance of certain differences can be specified via the keyword
76 75 parameters of this method.
77 76 """
78 77
79 78 if newlines_are_spaces:
80 79 a = a.replace('\n', ' ')
81 80 b = b.replace('\n', ' ')
82 81
83 82 if tabs_are_spaces:
84 83 a = a.replace('\t', ' ')
85 84 b = b.replace('\t', ' ')
86 85
87 86 if ignore_spaces:
88 87 a = a.replace(' ', '')
89 88 b = b.replace(' ', '')
90 89
91 90 if fuzzy_spacing:
92 91 a = self.recursive_replace(a, ' ', ' ')
93 92 b = self.recursive_replace(b, ' ', ' ')
94 93
95 94 if ignore_newlines:
96 95 a = a.replace('\n', '')
97 96 b = b.replace('\n', '')
98 97
99 98 if not case_sensitive:
100 99 a = a.lower()
101 100 b = b.lower()
102 101
103 102 return a == b
104 103
105 104
106 105 def recursive_replace(self, text, search, replacement):
107 106 """
108 107 Performs a recursive replacement operation. Replaces all instances
109 108 of a search string in a text string with a replacement string until
110 109 the search string no longer exists. Recursion is needed because the
111 110 replacement string may generate additional search strings.
112 111
113 112 For example:
114 113 Replace "ii" with "i" in the string "Hiiii" yields "Hii"
115 114 Another replacement yields "Hi" (the desired output)
116 115
117 116 Parameters:
118 117 -----------
119 118 text : string
120 119 Text to replace in.
121 120 search : string
122 121 String to search for within "text"
123 122 replacement : string
124 123 String to replace "search" with
125 124 """
126 125 while search in text:
127 126 text = text.replace(search, replacement)
128 127 return text
129 128
130 129
131 130 def create_temp_cwd(self, copy_filenames=None):
132 131 temp_dir = TemporaryWorkingDirectory()
133 132
134 133 #Copy the files if requested.
135 134 if not copy_filenames is None:
136 135 self.copy_files_to(copy_filenames)
137 136
138 137 #Return directory handler
139 138 return temp_dir
140 139
141 140
142 141 def copy_files_to(self, copy_filenames=None, destination=None):
143 142
144 143 #Copy test files into the destination directory.
145 144 if copy_filenames:
146 145 for pattern in copy_filenames:
147 146 for match in glob.glob(os.path.join(self._get_files_path(), pattern)):
148 147 if destination is None:
149 148 shutil.copyfile(match, os.path.basename(match))
150 149 else:
151 150 if not os.path.isdir(destination):
152 151 os.makedirs(destination)
153 152 shutil.copyfile(match, os.path.join(destination, os.path.basename(match)))
154 153
155 154
156 155 def _get_files_path(self):
157 156
158 157 #Get the relative path to this module in the IPython directory.
159 158 names = self.__module__.split('.')[1:-1]
160 159 names.append('files')
161 160
162 161 #Build a path using the IPython directory and the relative path we just
163 162 #found.
164 163 path = IPython.__path__[0]
165 164 for name in names:
166 165 path = os.path.join(path, name)
167 166 return path
168 167
169 168
170 169 def call(self, parameters):
171 170 output = subprocess.Popen(parameters, stdout=subprocess.PIPE).communicate()[0]
172 171
173 172 #Convert the output to a string if running Python3
174 173 if py3compat.PY3:
175 174 return output.decode('utf-8')
176 175 else:
177 176 return output
178 177 No newline at end of file
@@ -1,123 +1,149 b''
1 1 """
2 2 Contains tests for the nbconvertapp
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 os
17 17 from .base import TestsBase
18 18
19 19 from IPython.utils import py3compat
20 from IPython.testing import decorators as dec
20 21
21 22
22 23 #-----------------------------------------------------------------------------
23 24 # Constants
24 25 #-----------------------------------------------------------------------------
25 26
26 27 # Define ipython commandline name
27 28 if py3compat.PY3:
28 29 IPYTHON = 'ipython3'
29 30 else:
30 31 IPYTHON = 'ipython'
31 32
32 33
33 34 #-----------------------------------------------------------------------------
34 35 # Classes and functions
35 36 #-----------------------------------------------------------------------------
36 37
37 38 class TestNbConvertApp(TestsBase):
38 39 """Collection of NbConvertApp tests"""
39 40
40 41
41 42 def test_notebook_help(self):
42 43 """
43 44 Will help show if no notebooks are specified?
44 45 """
45 46 with self.create_temp_cwd():
46 47 assert "see '--help-all'" in self.call([IPYTHON, 'nbconvert'])
47 48
48 49
49 50 def test_glob(self):
50 51 """
51 52 Do search patterns work for notebook names?
52 53 """
53 54 with self.create_temp_cwd(['notebook*.ipynb']):
54 55 assert not 'error' in self.call([IPYTHON, 'nbconvert',
55 '--format="python"', '--notebooks=["*.ipynb"]']).lower()
56 '--to="python"', '--notebooks=["*.ipynb"]']).lower()
56 57 assert os.path.isfile('notebook1.py')
57 58 assert os.path.isfile('notebook2.py')
58 59
59 60
60 61 def test_glob_subdir(self):
61 62 """
62 63 Do search patterns work for subdirectory notebook names?
63 64 """
64 65 with self.create_temp_cwd() as cwd:
65 66 self.copy_files_to(['notebook*.ipynb'], 'subdir/')
66 assert not 'error' in self.call([IPYTHON, 'nbconvert', '--format="python"',
67 assert not 'error' in self.call([IPYTHON, 'nbconvert', '--to="python"',
67 68 '--notebooks=["%s"]' % os.path.join('subdir', '*.ipynb')]).lower()
68 69 assert os.path.isfile('notebook1.py')
69 70 assert os.path.isfile('notebook2.py')
70 71
71 72
72 73 def test_explicit(self):
73 74 """
74 75 Do explicit notebook names work?
75 76 """
76 77 with self.create_temp_cwd(['notebook*.ipynb']):
77 assert not 'error' in self.call([IPYTHON, 'nbconvert', '--format="python"',
78 assert not 'error' in self.call([IPYTHON, 'nbconvert', '--to="python"',
78 79 '--notebooks=["notebook2.ipynb"]']).lower()
79 80 assert not os.path.isfile('notebook1.py')
80 81 assert os.path.isfile('notebook2.py')
81 82
82 83
84 @dec.onlyif_cmds_exist('pdflatex')
85 def test_post_processor(self):
86 """
87 Do post processors work?
88 """
89 with self.create_temp_cwd(['notebook1.ipynb']):
90 assert not 'error' in self.call([IPYTHON, 'nbconvert', '--to="latex"',
91 'notebook1', '--post="PDF"', '--PDFPostProcessor.verbose=True']).lower()
92 assert os.path.isfile('notebook1.tex')
93 print("\n\n\t" + "\n\t".join([f for f in os.listdir('.') if os.path.isfile(f)]) + "\n\n")
94 assert os.path.isfile('notebook1.pdf')
95
96
97 def test_template(self):
98 """
99 Do export templates work?
100 """
101 with self.create_temp_cwd(['notebook2.ipynb']):
102 assert not 'error' in self.call([IPYTHON, 'nbconvert', '--to=slides',
103 '--notebooks=["notebook2.ipynb"]', '--template=reveal']).lower()
104 assert os.path.isfile('notebook2.slides.html')
105 with open('notebook2.slides.html') as f:
106 assert '/reveal.css' in f.read()
107
108
83 109 def test_glob_explicit(self):
84 110 """
85 111 Can a search pattern be used along with matching explicit notebook names?
86 112 """
87 113 with self.create_temp_cwd(['notebook*.ipynb']):
88 assert not 'error' in self.call([IPYTHON, 'nbconvert', '--format="python"',
114 assert not 'error' in self.call([IPYTHON, 'nbconvert', '--to="python"',
89 115 '--notebooks=["*.ipynb", "notebook1.ipynb", "notebook2.ipynb"]']).lower()
90 116 assert os.path.isfile('notebook1.py')
91 117 assert os.path.isfile('notebook2.py')
92 118
93 119
94 120 def test_explicit_glob(self):
95 121 """
96 122 Can explicit notebook names be used and then a matching search pattern?
97 123 """
98 124 with self.create_temp_cwd(['notebook*.ipynb']):
99 assert not 'error' in self.call([IPYTHON, 'nbconvert', '--format="python"',
125 assert not 'error' in self.call([IPYTHON, 'nbconvert', '--to="python"',
100 126 '--notebooks=["notebook1.ipynb", "notebook2.ipynb", "*.ipynb"]']).lower()
101 127 assert os.path.isfile('notebook1.py')
102 128 assert os.path.isfile('notebook2.py')
103 129
104 130
105 131 def test_default_config(self):
106 132 """
107 133 Does the default config work?
108 134 """
109 135 with self.create_temp_cwd(['notebook*.ipynb', 'ipython_nbconvert_config.py']):
110 136 assert not 'error' in self.call([IPYTHON, 'nbconvert']).lower()
111 137 assert os.path.isfile('notebook1.py')
112 138 assert not os.path.isfile('notebook2.py')
113 139
114 140
115 141 def test_override_config(self):
116 142 """
117 143 Can the default config be overriden?
118 144 """
119 145 with self.create_temp_cwd(['notebook*.ipynb', 'ipython_nbconvert_config.py',
120 146 'override.py']):
121 147 assert not 'error' in self.call([IPYTHON, 'nbconvert', '--config="override.py"']).lower()
122 148 assert not os.path.isfile('notebook1.py')
123 149 assert os.path.isfile('notebook2.py')
@@ -1,2 +1,3 b''
1 1 from .files import FilesWriter
2 2 from .stdout import StdoutWriter
3 from .base import WriterBase
@@ -1,57 +1,56 b''
1 #!/usr/bin/env python
2 1 """
3 2 Contains writer base class.
4 3 """
5 4 #-----------------------------------------------------------------------------
6 5 #Copyright (c) 2013, the IPython Development Team.
7 6 #
8 7 #Distributed under the terms of the Modified BSD License.
9 8 #
10 9 #The full license is in the file COPYING.txt, distributed with this software.
11 10 #-----------------------------------------------------------------------------
12 11
13 12 #-----------------------------------------------------------------------------
14 13 # Imports
15 14 #-----------------------------------------------------------------------------
16 15
17 16 from IPython.utils.traitlets import List
18 17
19 18 from ..utils.base import NbConvertBase
20 19
21 20 #-----------------------------------------------------------------------------
22 21 # Classes
23 22 #-----------------------------------------------------------------------------
24 23
25 24 class WriterBase(NbConvertBase):
26 25 """Consumes output from nbconvert export...() methods and writes to a
27 26 useful location. """
28 27
29 28
30 29 files = List([], config=True, help="""
31 30 List of the files that the notebook references. Files will be
32 31 included with written output.""")
33 32
34 33
35 34 def __init__(self, config=None, **kw):
36 35 """
37 36 Constructor
38 37 """
39 38 super(WriterBase, self).__init__(config=config, **kw)
40 39
41 40
42 41 def write(self, output, resources, **kw):
43 42 """
44 43 Consume and write Jinja output.
45 44
46 45 Parameters
47 46 ----------
48 47 output : string
49 48 Conversion results. This string contains the file contents of the
50 49 converted file.
51 50 resources : dict
52 51 Resources created and filled by the nbconvert conversion process.
53 52 Includes output from transformers, such as the extract figure
54 53 transformer.
55 54 """
56 55
57 56 raise NotImplementedError()
@@ -1,43 +1,42 b''
1 #!/usr/bin/env python
2 1 """
3 2 Contains debug writer.
4 3 """
5 4 #-----------------------------------------------------------------------------
6 5 #Copyright (c) 2013, the IPython Development Team.
7 6 #
8 7 #Distributed under the terms of the Modified BSD License.
9 8 #
10 9 #The full license is in the file COPYING.txt, distributed with this software.
11 10 #-----------------------------------------------------------------------------
12 11
13 12 #-----------------------------------------------------------------------------
14 13 # Imports
15 14 #-----------------------------------------------------------------------------
16 15
17 16 from .base import WriterBase
18 17 from pprint import pprint
19 18
20 19 #-----------------------------------------------------------------------------
21 20 # Classes
22 21 #-----------------------------------------------------------------------------
23 22
24 23 class DebugWriter(WriterBase):
25 24 """Consumes output from nbconvert export...() methods and writes usefull
26 25 debugging information to the stdout. The information includes a list of
27 26 resources that were extracted from the notebook(s) during export."""
28 27
29 28
30 29 def write(self, output, resources, notebook_name='notebook', **kw):
31 30 """
32 31 Consume and write Jinja output.
33 32
34 33 See base for more...
35 34 """
36 35
37 36 if 'outputs' in resources:
38 37 print("outputs extracted from %s" % notebook_name)
39 38 print('-' * 80)
40 39 pprint.pprint(resources['outputs'], indent=2, width=70)
41 40 else:
42 41 print("No outputs extracted from %s" % notebook_name)
43 42 print('=' * 80)
@@ -1,102 +1,102 b''
1 #!/usr/bin/env python
2 1 """
3 2 Contains writer for writing nbconvert output to filesystem.
4 3 """
5 4 #-----------------------------------------------------------------------------
6 5 #Copyright (c) 2013, the IPython Development Team.
7 6 #
8 7 #Distributed under the terms of the Modified BSD License.
9 8 #
10 9 #The full license is in the file COPYING.txt, distributed with this software.
11 10 #-----------------------------------------------------------------------------
12 11
13 12 #-----------------------------------------------------------------------------
14 13 # Imports
15 14 #-----------------------------------------------------------------------------
16 15
17 16 import io
18 17 import os
19 18 import glob
20 19
21 20 from IPython.utils.traitlets import Unicode
22 21 from IPython.utils.path import link_or_copy
23 22
24 23 from .base import WriterBase
25 24
26 25 #-----------------------------------------------------------------------------
27 26 # Classes
28 27 #-----------------------------------------------------------------------------
29 28
30 29 class FilesWriter(WriterBase):
31 30 """Consumes nbconvert output and produces files."""
32 31
33 32
34 33 build_directory = Unicode(".", config=True,
35 34 help="""Directory to write output to. Leave blank
36 35 to output to the current directory""")
37 36
38 37
39 38 # Make sure that the output directory exists.
40 39 def _build_directory_changed(self, name, old, new):
41 40 if new and not os.path.isdir(new):
42 41 os.makedirs(new)
43 42
44 43
45 44 def __init__(self, **kw):
46 45 super(FilesWriter, self).__init__(**kw)
47 46 self._build_directory_changed('build_directory', self.build_directory,
48 47 self.build_directory)
49 48
50 49
51 50 def write(self, output, resources, notebook_name=None, **kw):
52 51 """
53 52 Consume and write Jinja output to the file system. Output directory
54 53 is set via the 'build_directory' variable of this instance (a
55 54 configurable).
56 55
57 56 See base for more...
58 57 """
59 58
60 59 # Pull the extension and subdir from the resources dict.
61 60 output_extension = resources['output_extension']
62 61
63 62 # Write all of the extracted resources to the destination directory.
64 63 # NOTE: WE WRITE EVERYTHING AS-IF IT'S BINARY. THE EXTRACT FIG
65 64 # TRANSFORMER SHOULD HANDLE UNIX/WINDOWS LINE ENDINGS...
66 65 for filename, data in resources.get('outputs', {}).items():
67 66
68 67 # Determine where to write the file to
69 68 dest = os.path.join(self.build_directory, filename)
70 69 path = os.path.dirname(dest)
71 70 if not os.path.isdir(path):
72 71 os.makedirs(path)
73 72
74 73 # Write file
75 74 with io.open(dest, 'wb') as f:
76 75 f.write(data)
77 76
78 77 # Copy referenced files to output directory
79 78 if self.build_directory:
80 79 for filename in self.files:
81 80
82 81 # Copy files that match search pattern
83 82 for matching_filename in glob.glob(filename):
84 83
85 84 # Make sure folder exists.
86 85 dest = os.path.join(self.build_directory, filename)
87 86 path = os.path.dirname(dest)
88 87 if not os.path.isdir(path):
89 88 os.makedirs(path)
90 89
91 90 # Copy if destination is different.
92 91 if not os.path.normpath(dest) == os.path.normpath(matching_filename):
93 92 link_or_copy(matching_filename, dest)
94 93
95 94 # Determine where to write conversion results.
96 95 dest = notebook_name + '.' + output_extension
97 96 if self.build_directory:
98 97 dest = os.path.join(self.build_directory, dest)
99 98
100 99 # Write conversion results.
101 100 with io.open(dest, 'w') as f:
102 101 f.write(output)
102 return dest No newline at end of file
@@ -1,35 +1,34 b''
1 #!/usr/bin/env python
2 1 """
3 2 Contains Stdout writer
4 3 """
5 4 #-----------------------------------------------------------------------------
6 5 #Copyright (c) 2013, the IPython Development Team.
7 6 #
8 7 #Distributed under the terms of the Modified BSD License.
9 8 #
10 9 #The full license is in the file COPYING.txt, distributed with this software.
11 10 #-----------------------------------------------------------------------------
12 11
13 12 #-----------------------------------------------------------------------------
14 13 # Imports
15 14 #-----------------------------------------------------------------------------
16 15
17 16 from .base import WriterBase
18 17
19 18 #-----------------------------------------------------------------------------
20 19 # Classes
21 20 #-----------------------------------------------------------------------------
22 21
23 22 class StdoutWriter(WriterBase):
24 23 """Consumes output from nbconvert export...() methods and writes to the
25 24 stdout stream."""
26 25
27 26
28 27 def write(self, output, resources, **kw):
29 28 """
30 29 Consume and write Jinja output.
31 30
32 31 See base for more...
33 32 """
34 33
35 34 print(output)
1 NO CONTENT: file was removed
1 NO CONTENT: file was removed
1 NO CONTENT: file was removed
1 NO CONTENT: file was removed
1 NO CONTENT: file was removed
General Comments 0
You need to be logged in to leave comments. Login now