##// END OF EJS Templates
don't allow 'template' to specify 'template_file'...
MinRK -
Show More
@@ -1,509 +1,510 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 28 from jinja2 import Environment, FileSystemLoader, ChoiceLoader, TemplateNotFound
29 29
30 30 # IPython imports
31 31 from IPython.config.configurable import LoggingConfigurable
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, Any
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(LoggingConfigurable):
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 97 template_file = Unicode(u'default',
98 98 config=True,
99 99 help="Name of the template file to use")
100 100 def _template_file_changed(self, name, old, new):
101 101 if new=='default':
102 102 self.template_file = self.default_template
103 103 else:
104 104 self.template_file = new
105 105 self._load_template()
106 106
107 107 default_template = Unicode(u'')
108 108 template = Any()
109 109 environment = Any()
110 110
111 111 file_extension = Unicode(
112 112 'txt', config=True,
113 113 help="Extension of the file that should be written to disk"
114 114 )
115 115
116 116 template_path = List(['.'], config=True)
117 117 def _template_path_changed(self, name, old, new):
118 118 self._load_template()
119 119
120 120 default_template_path = Unicode(
121 121 os.path.join("..", "templates"),
122 122 help="Path where the template files are located.")
123 123
124 124 template_skeleton_path = Unicode(
125 125 os.path.join("..", "templates", "skeleton"),
126 126 help="Path where the template skeleton files are located.")
127 127
128 128 #Jinja block definitions
129 129 jinja_comment_block_start = Unicode("", config=True)
130 130 jinja_comment_block_end = Unicode("", config=True)
131 131 jinja_variable_block_start = Unicode("", config=True)
132 132 jinja_variable_block_end = Unicode("", config=True)
133 133 jinja_logic_block_start = Unicode("", config=True)
134 134 jinja_logic_block_end = Unicode("", config=True)
135 135
136 136 #Extension that the template files use.
137 137 template_extension = Unicode(".tpl", config=True)
138 138
139 139 #Configurability, allows the user to easily add filters and transformers.
140 140 transformers = List(config=True,
141 141 help="""List of transformers, by name or namespace, to enable.""")
142 142
143 143 filters = Dict(config=True,
144 144 help="""Dictionary of filters, by name and namespace, to add to the Jinja
145 145 environment.""")
146 146
147 147 default_transformers = List([nbtransformers.coalesce_streams,
148 148 nbtransformers.SVG2PDFTransformer,
149 149 nbtransformers.ExtractOutputTransformer,
150 150 nbtransformers.CSSHTMLHeaderTransformer,
151 151 nbtransformers.RevealHelpTransformer,
152 152 nbtransformers.LatexTransformer,
153 153 nbtransformers.SphinxTransformer],
154 154 config=True,
155 155 help="""List of transformers available by default, by name, namespace,
156 156 instance, or type.""")
157 157
158 158
159 159 def __init__(self, config=None, extra_loaders=None, **kw):
160 160 """
161 161 Public constructor
162 162
163 163 Parameters
164 164 ----------
165 165 config : config
166 166 User configuration instance.
167 167 extra_loaders : list[of Jinja Loaders]
168 168 ordered list of Jinja loader to find templates. Will be tried in order
169 169 before the default FileSystem ones.
170 170 template : str (optional, kw arg)
171 171 Template to use when exporting.
172 172 """
173 if not config:
174 config = self.default_config
173 175
174 176 super(Exporter, self).__init__(config=config, **kw)
175 177
176 178 #Init
177 self._init_template(**kw)
179 self._init_template()
178 180 self._init_environment(extra_loaders=extra_loaders)
179 181 self._init_transformers()
180 182 self._init_filters()
181 183
182 184
183 185 @property
184 186 def default_config(self):
185 187 return Config()
186 188
187 189 def _config_changed(self, name, old, new):
188 190 """When setting config, make sure to start with our default_config"""
189 191 c = self.default_config
190 192 if new:
191 193 c.merge(new)
192 if c != new:
194 if c != old:
193 195 self.config = c
196 super(Exporter, self)._config_changed(name, old, c)
194 197
195 198
196 199 def _load_template(self):
197 200 """Load the Jinja template object from the template file
198 201
199 202 This is a no-op if the template attribute is already defined,
200 203 or the Jinja environment is not setup yet.
201 204
202 205 This is triggered by various trait changes that would change the template.
203 206 """
204 207 if self.template is not None:
205 208 return
206 209 # called too early, do nothing
207 210 if self.environment is None:
208 211 return
209 212 # Try different template names during conversion. First try to load the
210 213 # template by name with extension added, then try loading the template
211 214 # as if the name is explicitly specified, then try the name as a
212 215 # 'flavor', and lastly just try to load the template by module name.
213 216 module_name = self.__module__.rsplit('.', 1)[-1]
214 217 try_names = [self.template_file + self.template_extension,
215 218 self.template_file,
216 219 module_name + '_' + self.template_file + self.template_extension,
217 220 module_name + self.template_extension]
218 221 for try_name in try_names:
219 222 self.log.debug("Attempting to load template %s", try_name)
220 223 try:
221 224 self.template = self.environment.get_template(try_name)
222 225 except TemplateNotFound:
223 226 pass
224 227 else:
225 228 self.log.info("Loaded template %s", try_name)
226 229 break
227 230
228 231 def from_notebook_node(self, nb, resources=None, **kw):
229 232 """
230 233 Convert a notebook from a notebook node instance.
231 234
232 235 Parameters
233 236 ----------
234 237 nb : Notebook node
235 238 resources : dict (**kw)
236 239 of additional resources that can be accessed read/write by
237 240 transformers and filters.
238 241 """
239 242 nb_copy = copy.deepcopy(nb)
240 243 resources = self._init_resources(resources)
241 244
242 245 # Preprocess
243 246 nb_copy, resources = self._transform(nb_copy, resources)
244 247
245 248 self._load_template()
246 249
247 250 if self.template is not None:
248 251 output = self.template.render(nb=nb_copy, resources=resources)
249 252 else:
250 253 raise IOError('template file "%s" could not be found' % self.template_file)
251 254 return output, resources
252 255
253 256
254 257 def from_filename(self, filename, resources=None, **kw):
255 258 """
256 259 Convert a notebook from a notebook file.
257 260
258 261 Parameters
259 262 ----------
260 263 filename : str
261 264 Full filename of the notebook file to open and convert.
262 265 """
263 266
264 267 #Pull the metadata from the filesystem.
265 268 if resources is None:
266 269 resources = ResourcesDict()
267 270 if not 'metadata' in resources or resources['metadata'] == '':
268 271 resources['metadata'] = ResourcesDict()
269 272 basename = os.path.basename(filename)
270 273 notebook_name = basename[:basename.rfind('.')]
271 274 resources['metadata']['name'] = notebook_name
272 275
273 276 modified_date = datetime.datetime.fromtimestamp(os.path.getmtime(filename))
274 277 resources['metadata']['modified_date'] = modified_date.strftime("%B %d, %Y")
275 278
276 279 with io.open(filename) as f:
277 280 return self.from_notebook_node(nbformat.read(f, 'json'), resources=resources,**kw)
278 281
279 282
280 283 def from_file(self, file_stream, resources=None, **kw):
281 284 """
282 285 Convert a notebook from a notebook file.
283 286
284 287 Parameters
285 288 ----------
286 289 file_stream : file-like object
287 290 Notebook file-like object to convert.
288 291 """
289 292 return self.from_notebook_node(nbformat.read(file_stream, 'json'), resources=resources, **kw)
290 293
291 294
292 295 def register_transformer(self, transformer, enabled=False):
293 296 """
294 297 Register a transformer.
295 298 Transformers are classes that act upon the notebook before it is
296 299 passed into the Jinja templating engine. Transformers are also
297 300 capable of passing additional information to the Jinja
298 301 templating engine.
299 302
300 303 Parameters
301 304 ----------
302 305 transformer : transformer
303 306 """
304 307 if transformer is None:
305 308 raise TypeError('transformer')
306 309 isclass = isinstance(transformer, type)
307 310 constructed = not isclass
308 311
309 312 #Handle transformer's registration based on it's type
310 313 if constructed and isinstance(transformer, py3compat.string_types):
311 314 #Transformer is a string, import the namespace and recursively call
312 315 #this register_transformer method
313 316 transformer_cls = import_item(transformer)
314 317 return self.register_transformer(transformer_cls, enabled)
315 318
316 319 if constructed and hasattr(transformer, '__call__'):
317 320 #Transformer is a function, no need to construct it.
318 321 #Register and return the transformer.
319 322 if enabled:
320 323 transformer.enabled = True
321 324 self._transformers.append(transformer)
322 325 return transformer
323 326
324 327 elif isclass and isinstance(transformer, MetaHasTraits):
325 328 #Transformer is configurable. Make sure to pass in new default for
326 329 #the enabled flag if one was specified.
327 330 self.register_transformer(transformer(parent=self), enabled)
328 331
329 332 elif isclass:
330 333 #Transformer is not configurable, construct it
331 334 self.register_transformer(transformer(), enabled)
332 335
333 336 else:
334 337 #Transformer is an instance of something without a __call__
335 338 #attribute.
336 339 raise TypeError('transformer')
337 340
338 341
339 342 def register_filter(self, name, jinja_filter):
340 343 """
341 344 Register a filter.
342 345 A filter is a function that accepts and acts on one string.
343 346 The filters are accesible within the Jinja templating engine.
344 347
345 348 Parameters
346 349 ----------
347 350 name : str
348 351 name to give the filter in the Jinja engine
349 352 filter : filter
350 353 """
351 354 if jinja_filter is None:
352 355 raise TypeError('filter')
353 356 isclass = isinstance(jinja_filter, type)
354 357 constructed = not isclass
355 358
356 359 #Handle filter's registration based on it's type
357 360 if constructed and isinstance(jinja_filter, py3compat.string_types):
358 361 #filter is a string, import the namespace and recursively call
359 362 #this register_filter method
360 363 filter_cls = import_item(jinja_filter)
361 364 return self.register_filter(name, filter_cls)
362 365
363 366 if constructed and hasattr(jinja_filter, '__call__'):
364 367 #filter is a function, no need to construct it.
365 368 self.environment.filters[name] = jinja_filter
366 369 return jinja_filter
367 370
368 371 elif isclass and isinstance(jinja_filter, MetaHasTraits):
369 372 #filter is configurable. Make sure to pass in new default for
370 373 #the enabled flag if one was specified.
371 374 filter_instance = jinja_filter(parent=self)
372 375 self.register_filter(name, filter_instance )
373 376
374 377 elif isclass:
375 378 #filter is not configurable, construct it
376 379 filter_instance = jinja_filter()
377 380 self.register_filter(name, filter_instance)
378 381
379 382 else:
380 383 #filter is an instance of something without a __call__
381 384 #attribute.
382 385 raise TypeError('filter')
383 386
384 387
385 def _init_template(self, **kw):
388 def _init_template(self):
386 389 """
387 390 Make sure a template name is specified. If one isn't specified, try to
388 391 build one from the information we know.
389 392 """
390 393 self._template_file_changed('template_file', self.template_file, self.template_file)
391 if 'template' in kw:
392 self.template_file = kw['template']
393 394
394 395
395 396 def _init_environment(self, extra_loaders=None):
396 397 """
397 398 Create the Jinja templating environment.
398 399 """
399 400 here = os.path.dirname(os.path.realpath(__file__))
400 401 loaders = []
401 402 if extra_loaders:
402 403 loaders.extend(extra_loaders)
403 404
404 405 paths = self.template_path
405 406 paths.extend([os.path.join(here, self.default_template_path),
406 407 os.path.join(here, self.template_skeleton_path)])
407 408 loaders.append(FileSystemLoader(paths))
408 409
409 410 self.environment = Environment(
410 411 loader= ChoiceLoader(loaders),
411 412 extensions=JINJA_EXTENSIONS
412 413 )
413 414
414 415 #Set special Jinja2 syntax that will not conflict with latex.
415 416 if self.jinja_logic_block_start:
416 417 self.environment.block_start_string = self.jinja_logic_block_start
417 418 if self.jinja_logic_block_end:
418 419 self.environment.block_end_string = self.jinja_logic_block_end
419 420 if self.jinja_variable_block_start:
420 421 self.environment.variable_start_string = self.jinja_variable_block_start
421 422 if self.jinja_variable_block_end:
422 423 self.environment.variable_end_string = self.jinja_variable_block_end
423 424 if self.jinja_comment_block_start:
424 425 self.environment.comment_start_string = self.jinja_comment_block_start
425 426 if self.jinja_comment_block_end:
426 427 self.environment.comment_end_string = self.jinja_comment_block_end
427 428
428 429
429 430 def _init_transformers(self):
430 431 """
431 432 Register all of the transformers needed for this exporter, disabled
432 433 unless specified explicitly.
433 434 """
434 435 self._transformers = []
435 436
436 437 #Load default transformers (not necessarly enabled by default).
437 438 if self.default_transformers:
438 439 for transformer in self.default_transformers:
439 440 self.register_transformer(transformer)
440 441
441 442 #Load user transformers. Enable by default.
442 443 if self.transformers:
443 444 for transformer in self.transformers:
444 445 self.register_transformer(transformer, enabled=True)
445 446
446 447
447 448 def _init_filters(self):
448 449 """
449 450 Register all of the filters required for the exporter.
450 451 """
451 452
452 453 #Add default filters to the Jinja2 environment
453 454 for key, value in default_filters.items():
454 455 self.register_filter(key, value)
455 456
456 457 #Load user filters. Overwrite existing filters if need be.
457 458 if self.filters:
458 459 for key, user_filter in self.filters.items():
459 460 self.register_filter(key, user_filter)
460 461
461 462
462 463 def _init_resources(self, resources):
463 464
464 465 #Make sure the resources dict is of ResourcesDict type.
465 466 if resources is None:
466 467 resources = ResourcesDict()
467 468 if not isinstance(resources, ResourcesDict):
468 469 new_resources = ResourcesDict()
469 470 new_resources.update(resources)
470 471 resources = new_resources
471 472
472 473 #Make sure the metadata extension exists in resources
473 474 if 'metadata' in resources:
474 475 if not isinstance(resources['metadata'], ResourcesDict):
475 476 resources['metadata'] = ResourcesDict(resources['metadata'])
476 477 else:
477 478 resources['metadata'] = ResourcesDict()
478 479 if not resources['metadata']['name']:
479 480 resources['metadata']['name'] = 'Notebook'
480 481
481 482 #Set the output extension
482 483 resources['output_extension'] = self.file_extension
483 484 return resources
484 485
485 486
486 487 def _transform(self, nb, resources):
487 488 """
488 489 Preprocess the notebook before passing it into the Jinja engine.
489 490 To preprocess the notebook is to apply all of the
490 491
491 492 Parameters
492 493 ----------
493 494 nb : notebook node
494 495 notebook that is being exported.
495 496 resources : a dict of additional resources that
496 497 can be accessed read/write by transformers
497 498 and filters.
498 499 """
499 500
500 501 # Do a copy.deepcopy first,
501 502 # we are never safe enough with what the transformers could do.
502 503 nbc = copy.deepcopy(nb)
503 504 resc = copy.deepcopy(resources)
504 505
505 506 #Run each transformer on the notebook. Carry the output along
506 507 #to each transformer
507 508 for transformer in self._transformers:
508 509 nbc, resc = transformer(nbc, resc)
509 510 return nbc, resc
@@ -1,113 +1,112 b''
1 1 """
2 2 Module with tests for exporter.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 IPython.config import Config
18 18
19 19 from .base import ExportersTestsBase
20 20 from .cheese import CheeseTransformer
21 21 from ..exporter import Exporter
22 22
23 23
24 24 #-----------------------------------------------------------------------------
25 25 # Class
26 26 #-----------------------------------------------------------------------------
27 27
28 28 class TestExporter(ExportersTestsBase):
29 29 """Contains test functions for exporter.py"""
30 30
31 31
32 32 def test_constructor(self):
33 33 """
34 34 Can an Exporter be constructed?
35 35 """
36 36 Exporter()
37 37
38 38
39 39 def test_export(self):
40 40 """
41 41 Can an Exporter export something?
42 42 """
43 43 exporter = self._make_exporter()
44 44 (output, resources) = exporter.from_filename(self._get_notebook())
45 45 assert len(output) > 0
46 46
47 47
48 48 def test_extract_outputs(self):
49 49 """
50 50 If the ExtractOutputTransformer is enabled, are outputs extracted?
51 51 """
52 52 config = Config({'ExtractOutputTransformer': {'enabled': True}})
53 53 exporter = self._make_exporter(config=config)
54 54 (output, resources) = exporter.from_filename(self._get_notebook())
55 55 assert resources is not None
56 56 assert 'outputs' in resources
57 57 assert len(resources['outputs']) > 0
58 58
59 59
60 60 def test_transformer_class(self):
61 61 """
62 62 Can a transformer be added to the transformers list by class type?
63 63 """
64 64 config = Config({'Exporter': {'transformers': [CheeseTransformer]}})
65 65 exporter = self._make_exporter(config=config)
66 66 (output, resources) = exporter.from_filename(self._get_notebook())
67 67 assert resources is not None
68 68 assert 'cheese' in resources
69 69 assert resources['cheese'] == 'real'
70 70
71 71
72 72 def test_transformer_instance(self):
73 73 """
74 74 Can a transformer be added to the transformers list by instance?
75 75 """
76 76 config = Config({'Exporter': {'transformers': [CheeseTransformer()]}})
77 77 exporter = self._make_exporter(config=config)
78 78 (output, resources) = exporter.from_filename(self._get_notebook())
79 79 assert resources is not None
80 80 assert 'cheese' in resources
81 81 assert resources['cheese'] == 'real'
82 82
83 83
84 84 def test_transformer_dottedobjectname(self):
85 85 """
86 86 Can a transformer be added to the transformers list by dotted object name?
87 87 """
88 88 config = Config({'Exporter': {'transformers': ['IPython.nbconvert.exporters.tests.cheese.CheeseTransformer']}})
89 89 exporter = self._make_exporter(config=config)
90 90 (output, resources) = exporter.from_filename(self._get_notebook())
91 91 assert resources is not None
92 92 assert 'cheese' in resources
93 93 assert resources['cheese'] == 'real'
94 94
95 95
96 96 def test_transformer_via_method(self):
97 97 """
98 Can a transformer be added via the Exporter convinience method?
98 Can a transformer be added via the Exporter convenience method?
99 99 """
100 100 exporter = self._make_exporter()
101 101 exporter.register_transformer(CheeseTransformer, enabled=True)
102 102 (output, resources) = exporter.from_filename(self._get_notebook())
103 103 assert resources is not None
104 104 assert 'cheese' in resources
105 105 assert resources['cheese'] == 'real'
106 106
107 107
108 108 def _make_exporter(self, config=None):
109 109 #Create the exporter instance, make sure to set a template name since
110 110 #the base Exporter doesn't have a template associated with it.
111 exporter = Exporter(config=config)
112 exporter.template_file = 'python'
111 exporter = Exporter(config=config, template_file='python')
113 112 return exporter No newline at end of file
@@ -1,59 +1,59 b''
1 1 """
2 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 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 25 class TestHTMLExporter(ExportersTestsBase):
26 26 """Contains test functions for html.py"""
27 27
28 28 def test_constructor(self):
29 29 """
30 30 Can a HTMLExporter be constructed?
31 31 """
32 32 HTMLExporter()
33 33
34 34
35 35 @onlyif_cmds_exist('pandoc')
36 36 def test_export(self):
37 37 """
38 38 Can a HTMLExporter export something?
39 39 """
40 40 (output, resources) = HTMLExporter().from_filename(self._get_notebook())
41 41 assert len(output) > 0
42 42
43 43
44 44 @onlyif_cmds_exist('pandoc')
45 45 def test_export_basic(self):
46 46 """
47 47 Can a HTMLExporter export using the 'basic' template?
48 48 """
49 (output, resources) = HTMLExporter(template='basic').from_filename(self._get_notebook())
49 (output, resources) = HTMLExporter(template_file='basic').from_filename(self._get_notebook())
50 50 assert len(output) > 0
51 51
52 52
53 53 @onlyif_cmds_exist('pandoc')
54 54 def test_export_full(self):
55 55 """
56 56 Can a HTMLExporter export using the 'full' template?
57 57 """
58 (output, resources) = HTMLExporter(template='full').from_filename(self._get_notebook())
58 (output, resources) = HTMLExporter(template_file='full').from_filename(self._get_notebook())
59 59 assert len(output) > 0
@@ -1,68 +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 42
43 43
44 44 @onlyif_cmds_exist('pandoc')
45 45 def test_export_book(self):
46 46 """
47 47 Can a LatexExporter export using 'book' template?
48 48 """
49 (output, resources) = LatexExporter(template='book').from_filename(self._get_notebook())
49 (output, resources) = LatexExporter(template_file='book').from_filename(self._get_notebook())
50 50 assert len(output) > 0
51 51
52 52
53 53 @onlyif_cmds_exist('pandoc')
54 54 def test_export_basic(self):
55 55 """
56 56 Can a LatexExporter export using 'basic' template?
57 57 """
58 (output, resources) = LatexExporter(template='basic').from_filename(self._get_notebook())
58 (output, resources) = LatexExporter(template_file='basic').from_filename(self._get_notebook())
59 59 assert len(output) > 0
60 60
61 61
62 62 @onlyif_cmds_exist('pandoc')
63 63 def test_export_article(self):
64 64 """
65 65 Can a LatexExporter export using 'article' template?
66 66 """
67 (output, resources) = LatexExporter(template='article').from_filename(self._get_notebook())
67 (output, resources) = LatexExporter(template_file='article').from_filename(self._get_notebook())
68 68 assert len(output) > 0 No newline at end of file
@@ -1,50 +1,50 b''
1 1 """
2 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 18 from ..slides import SlidesExporter
19 19 from IPython.testing.decorators import onlyif_cmds_exist
20 20
21 21 #-----------------------------------------------------------------------------
22 22 # Class
23 23 #-----------------------------------------------------------------------------
24 24
25 25 class TestSlidesExporter(ExportersTestsBase):
26 26 """Contains test functions for slides.py"""
27 27
28 28 def test_constructor(self):
29 29 """
30 30 Can a SlidesExporter be constructed?
31 31 """
32 32 SlidesExporter()
33 33
34 34
35 35 @onlyif_cmds_exist('pandoc')
36 36 def test_export(self):
37 37 """
38 38 Can a SlidesExporter export something?
39 39 """
40 40 (output, resources) = SlidesExporter().from_filename(self._get_notebook())
41 41 assert len(output) > 0
42 42
43 43
44 44 @onlyif_cmds_exist('pandoc')
45 45 def test_export_reveal(self):
46 46 """
47 47 Can a SlidesExporter export using the 'reveal' template?
48 48 """
49 (output, resources) = SlidesExporter(template='reveal').from_filename(self._get_notebook())
49 (output, resources) = SlidesExporter(template_file='reveal').from_filename(self._get_notebook())
50 50 assert len(output) > 0
General Comments 0
You need to be logged in to leave comments. Login now