##// END OF EJS Templates
Rename ExtractFigureTransformer to ExtractOutputTransformer
Jonathan Frederic -
Show More
@@ -1,443 +1,443
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
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 'markdown': filters.markdown2html,
52 52 'ansi2html': filters.ansi2html,
53 53 'filter_data_type': filters.DataTypeFilter,
54 54 'get_lines': filters.get_lines,
55 55 'highlight': filters.highlight,
56 56 'highlight2html': filters.highlight,
57 57 'highlight2latex': filters.highlight2latex,
58 58 'markdown2latex': filters.markdown2latex,
59 59 'markdown2rst': filters.markdown2rst,
60 60 'pycomment': filters.python_comment,
61 61 'rm_ansi': filters.remove_ansi,
62 62 'rm_dollars': filters.strip_dollars,
63 63 'rm_fake': filters.rm_fake,
64 64 'html_text' : filters.html_text,
65 65 'add_anchor': filters.add_anchor,
66 66 'ansi2latex': filters.ansi2latex,
67 67 'rm_math_space': filters.rm_math_space,
68 68 'wrap': filters.wrap
69 69 }
70 70
71 71 #-----------------------------------------------------------------------------
72 72 # Class
73 73 #-----------------------------------------------------------------------------
74 74
75 75 class ResourcesDict(collections.defaultdict):
76 76 def __missing__(self, key):
77 77 return ''
78 78
79 79
80 80 class Exporter(Configurable):
81 81 """
82 82 Exports notebooks into other file formats. Uses Jinja 2 templating engine
83 83 to output new formats. Inherit from this class if you are creating a new
84 84 template type along with new filters/transformers. If the filters/
85 85 transformers provided by default suffice, there is no need to inherit from
86 86 this class. Instead, override the template_file and file_extension
87 87 traits via a config file.
88 88
89 89 {filters}
90 90 """
91 91
92 92 # finish the docstring
93 93 __doc__ = __doc__.format(filters = '- '+'\n - '.join(default_filters.keys()))
94 94
95 95
96 96 template_file = Unicode(
97 97 '', config=True,
98 98 help="Name of the template file to use")
99 99
100 100 file_extension = Unicode(
101 101 'txt', config=True,
102 102 help="Extension of the file that should be written to disk"
103 103 )
104 104
105 105 template_path = Unicode(
106 106 os.path.join("..", "templates"), config=True,
107 107 help="Path where the template files are located.")
108 108
109 109 template_skeleton_path = Unicode(
110 110 os.path.join("..", "templates", "skeleton"), config=True,
111 111 help="Path where the template skeleton files are located.")
112 112
113 113 #Jinja block definitions
114 114 jinja_comment_block_start = Unicode("", config=True)
115 115 jinja_comment_block_end = Unicode("", config=True)
116 116 jinja_variable_block_start = Unicode("", config=True)
117 117 jinja_variable_block_end = Unicode("", config=True)
118 118 jinja_logic_block_start = Unicode("", config=True)
119 119 jinja_logic_block_end = Unicode("", config=True)
120 120
121 121 #Extension that the template files use.
122 122 template_extension = Unicode(".tpl", config=True)
123 123
124 124 #Configurability, allows the user to easily add filters and transformers.
125 125 transformers = List(config=True,
126 126 help="""List of transformers, by name or namespace, to enable.""")
127 127
128 128 filters = Dict(config=True,
129 129 help="""Dictionary of filters, by name and namespace, to add to the Jinja
130 130 environment.""")
131 131
132 132 default_transformers = List([nbtransformers.coalesce_streams,
133 133 nbtransformers.SVG2PDFTransformer,
134 nbtransformers.ExtractFigureTransformer,
134 nbtransformers.ExtractOutputTransformer,
135 135 nbtransformers.CSSHTMLHeaderTransformer,
136 136 nbtransformers.RevealHelpTransformer,
137 137 nbtransformers.LatexTransformer,
138 138 nbtransformers.SphinxTransformer],
139 139 config=True,
140 140 help="""List of transformers available by default, by name, namespace,
141 141 instance, or type.""")
142 142
143 143
144 144 def __init__(self, config=None, extra_loaders=None, **kw):
145 145 """
146 146 Public constructor
147 147
148 148 Parameters
149 149 ----------
150 150 config : config
151 151 User configuration instance.
152 152 extra_loaders : list[of Jinja Loaders]
153 153 ordered list of Jinja loder to find templates. Will be tried in order
154 154 before the default FileSysteme ones.
155 155 """
156 156
157 157 #Call the base class constructor
158 158 c = self.default_config
159 159 if config:
160 160 c.merge(config)
161 161
162 162 super(Exporter, self).__init__(config=c, **kw)
163 163
164 164 #Init
165 165 self._init_environment(extra_loaders=extra_loaders)
166 166 self._init_transformers()
167 167 self._init_filters()
168 168
169 169
170 170 @property
171 171 def default_config(self):
172 172 return Config()
173 173
174 174
175 175 def from_notebook_node(self, nb, resources=None, **kw):
176 176 """
177 177 Convert a notebook from a notebook node instance.
178 178
179 179 Parameters
180 180 ----------
181 181 nb : Notebook node
182 182 resources : dict (**kw)
183 183 of additional resources that can be accessed read/write by
184 184 transformers and filters.
185 185 """
186 186 nb_copy = copy.deepcopy(nb)
187 187 resources = self._init_resources(resources)
188 188
189 189 #Preprocess
190 190 nb_copy, resources = self._transform(nb_copy, resources)
191 191
192 192 #Convert
193 193 self.template = self.environment.get_template(self.template_file + self.template_extension)
194 194 output = self.template.render(nb=nb_copy, resources=resources)
195 195 return output, resources
196 196
197 197
198 198 def from_filename(self, filename, resources=None, **kw):
199 199 """
200 200 Convert a notebook from a notebook file.
201 201
202 202 Parameters
203 203 ----------
204 204 filename : str
205 205 Full filename of the notebook file to open and convert.
206 206 """
207 207
208 208 #Pull the metadata from the filesystem.
209 209 if resources is None:
210 210 resources = ResourcesDict()
211 211 if not 'metadata' in resources or resources['metadata'] == '':
212 212 resources['metadata'] = ResourcesDict()
213 213 basename = os.path.basename(filename)
214 214 notebook_name = basename[:basename.rfind('.')]
215 215 resources['metadata']['name'] = notebook_name
216 216
217 217 modified_date = datetime.datetime.fromtimestamp(os.path.getmtime(filename))
218 218 resources['metadata']['modified_date'] = modified_date.strftime("%B %-d, %Y")
219 219
220 220 with io.open(filename) as f:
221 221 return self.from_notebook_node(nbformat.read(f, 'json'), resources=resources,**kw)
222 222
223 223
224 224 def from_file(self, file_stream, resources=None, **kw):
225 225 """
226 226 Convert a notebook from a notebook file.
227 227
228 228 Parameters
229 229 ----------
230 230 file_stream : file-like object
231 231 Notebook file-like object to convert.
232 232 """
233 233 return self.from_notebook_node(nbformat.read(file_stream, 'json'), resources=resources, **kw)
234 234
235 235
236 236 def register_transformer(self, transformer, enabled=False):
237 237 """
238 238 Register a transformer.
239 239 Transformers are classes that act upon the notebook before it is
240 240 passed into the Jinja templating engine. Transformers are also
241 241 capable of passing additional information to the Jinja
242 242 templating engine.
243 243
244 244 Parameters
245 245 ----------
246 246 transformer : transformer
247 247 """
248 248 if transformer is None:
249 249 raise TypeError('transformer')
250 250 isclass = isinstance(transformer, type)
251 251 constructed = not isclass
252 252
253 253 #Handle transformer's registration based on it's type
254 254 if constructed and isinstance(transformer, py3compat.string_types):
255 255 #Transformer is a string, import the namespace and recursively call
256 256 #this register_transformer method
257 257 transformer_cls = import_item(transformer)
258 258 return self.register_transformer(transformer_cls, enabled)
259 259
260 260 if constructed and hasattr(transformer, '__call__'):
261 261 #Transformer is a function, no need to construct it.
262 262 #Register and return the transformer.
263 263 if enabled:
264 264 transformer.enabled = True
265 265 self._transformers.append(transformer)
266 266 return transformer
267 267
268 268 elif isclass and isinstance(transformer, MetaHasTraits):
269 269 #Transformer is configurable. Make sure to pass in new default for
270 270 #the enabled flag if one was specified.
271 271 self.register_transformer(transformer(parent=self), enabled)
272 272
273 273 elif isclass:
274 274 #Transformer is not configurable, construct it
275 275 self.register_transformer(transformer(), enabled)
276 276
277 277 else:
278 278 #Transformer is an instance of something without a __call__
279 279 #attribute.
280 280 raise TypeError('transformer')
281 281
282 282
283 283 def register_filter(self, name, jinja_filter):
284 284 """
285 285 Register a filter.
286 286 A filter is a function that accepts and acts on one string.
287 287 The filters are accesible within the Jinja templating engine.
288 288
289 289 Parameters
290 290 ----------
291 291 name : str
292 292 name to give the filter in the Jinja engine
293 293 filter : filter
294 294 """
295 295 if jinja_filter is None:
296 296 raise TypeError('filter')
297 297 isclass = isinstance(jinja_filter, type)
298 298 constructed = not isclass
299 299
300 300 #Handle filter's registration based on it's type
301 301 if constructed and isinstance(jinja_filter, py3compat.string_types):
302 302 #filter is a string, import the namespace and recursively call
303 303 #this register_filter method
304 304 filter_cls = import_item(jinja_filter)
305 305 return self.register_filter(name, filter_cls)
306 306
307 307 if constructed and hasattr(jinja_filter, '__call__'):
308 308 #filter is a function, no need to construct it.
309 309 self.environment.filters[name] = jinja_filter
310 310 return jinja_filter
311 311
312 312 elif isclass and isinstance(jinja_filter, MetaHasTraits):
313 313 #filter is configurable. Make sure to pass in new default for
314 314 #the enabled flag if one was specified.
315 315 filter_instance = jinja_filter(parent=self)
316 316 self.register_filter(name, filter_instance )
317 317
318 318 elif isclass:
319 319 #filter is not configurable, construct it
320 320 filter_instance = jinja_filter()
321 321 self.register_filter(name, filter_instance)
322 322
323 323 else:
324 324 #filter is an instance of something without a __call__
325 325 #attribute.
326 326 raise TypeError('filter')
327 327
328 328
329 329 def _init_environment(self, extra_loaders=None):
330 330 """
331 331 Create the Jinja templating environment.
332 332 """
333 333 here = os.path.dirname(os.path.realpath(__file__))
334 334 loaders = []
335 335 if extra_loaders:
336 336 loaders.extend(extra_loaders)
337 337
338 338 loaders.append(FileSystemLoader([
339 339 os.path.join(here, self.template_path),
340 340 os.path.join(here, self.template_skeleton_path),
341 341 ]))
342 342
343 343 self.environment = Environment(
344 344 loader= ChoiceLoader(loaders),
345 345 extensions=JINJA_EXTENSIONS
346 346 )
347 347
348 348 #Set special Jinja2 syntax that will not conflict with latex.
349 349 if self.jinja_logic_block_start:
350 350 self.environment.block_start_string = self.jinja_logic_block_start
351 351 if self.jinja_logic_block_end:
352 352 self.environment.block_end_string = self.jinja_logic_block_end
353 353 if self.jinja_variable_block_start:
354 354 self.environment.variable_start_string = self.jinja_variable_block_start
355 355 if self.jinja_variable_block_end:
356 356 self.environment.variable_end_string = self.jinja_variable_block_end
357 357 if self.jinja_comment_block_start:
358 358 self.environment.comment_start_string = self.jinja_comment_block_start
359 359 if self.jinja_comment_block_end:
360 360 self.environment.comment_end_string = self.jinja_comment_block_end
361 361
362 362
363 363 def _init_transformers(self):
364 364 """
365 365 Register all of the transformers needed for this exporter, disabled
366 366 unless specified explicitly.
367 367 """
368 368 self._transformers = []
369 369
370 370 #Load default transformers (not necessarly enabled by default).
371 371 if self.default_transformers:
372 372 for transformer in self.default_transformers:
373 373 self.register_transformer(transformer)
374 374
375 375 #Load user transformers. Enable by default.
376 376 if self.transformers:
377 377 for transformer in self.transformers:
378 378 self.register_transformer(transformer, enabled=True)
379 379
380 380
381 381 def _init_filters(self):
382 382 """
383 383 Register all of the filters required for the exporter.
384 384 """
385 385
386 386 #Add default filters to the Jinja2 environment
387 387 for key, value in default_filters.items():
388 388 self.register_filter(key, value)
389 389
390 390 #Load user filters. Overwrite existing filters if need be.
391 391 if self.filters:
392 392 for key, user_filter in self.filters.items():
393 393 self.register_filter(key, user_filter)
394 394
395 395
396 396 def _init_resources(self, resources):
397 397
398 398 #Make sure the resources dict is of ResourcesDict type.
399 399 if resources is None:
400 400 resources = ResourcesDict()
401 401 if not isinstance(resources, ResourcesDict):
402 402 new_resources = ResourcesDict()
403 403 new_resources.update(resources)
404 404 resources = new_resources
405 405
406 406 #Make sure the metadata extension exists in resources
407 407 if 'metadata' in resources:
408 408 if not isinstance(resources['metadata'], ResourcesDict):
409 409 resources['metadata'] = ResourcesDict(resources['metadata'])
410 410 else:
411 411 resources['metadata'] = ResourcesDict()
412 412 if not resources['metadata']['name']:
413 413 resources['metadata']['name'] = 'Notebook'
414 414
415 415 #Set the output extension
416 416 resources['output_extension'] = self.file_extension
417 417 return resources
418 418
419 419
420 420 def _transform(self, nb, resources):
421 421 """
422 422 Preprocess the notebook before passing it into the Jinja engine.
423 423 To preprocess the notebook is to apply all of the
424 424
425 425 Parameters
426 426 ----------
427 427 nb : notebook node
428 428 notebook that is being exported.
429 429 resources : a dict of additional resources that
430 430 can be accessed read/write by transformers
431 431 and filters.
432 432 """
433 433
434 434 # Do a copy.deepcopy first,
435 435 # we are never safe enough with what the transformers could do.
436 436 nbc = copy.deepcopy(nb)
437 437 resc = copy.deepcopy(resources)
438 438
439 439 #Run each transformer on the notebook. Carry the output along
440 440 #to each transformer
441 441 for transformer in self._transformers:
442 442 nbc, resc = transformer(nbc, resc)
443 443 return nbc, resc
@@ -1,102 +1,102
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 47 template_file = Unicode(
48 48 'base', config=True,
49 49 help="Name of the template file to use")
50 50
51 51 #Latex constants
52 52 template_path = Unicode(
53 53 os.path.join("..", "templates", "latex"), config=True,
54 54 help="Path where the template files are located.")
55 55
56 56 template_skeleton_path = Unicode(
57 57 os.path.join("..", "templates", "latex", "skeleton"), config=True,
58 58 help="Path where the template skeleton files are located.")
59 59
60 60 #Special Jinja2 syntax that will not conflict when exporting latex.
61 61 jinja_comment_block_start = Unicode("((=", config=True)
62 62 jinja_comment_block_end = Unicode("=))", config=True)
63 63 jinja_variable_block_start = Unicode("(((", config=True)
64 64 jinja_variable_block_end = Unicode(")))", config=True)
65 65 jinja_logic_block_start = Unicode("((*", config=True)
66 66 jinja_logic_block_end = Unicode("*))", config=True)
67 67
68 68 #Extension that the template files use.
69 69 template_extension = Unicode(".tplx", config=True)
70 70
71 71
72 72 def _init_filters(self):
73 73 """
74 74 Register all of the filters required for the exporter.
75 75 """
76 76
77 77 #Register the filters of the base class.
78 78 super(LatexExporter, self)._init_filters()
79 79
80 80 #Add latex filters to the Jinja2 environment
81 81 self.register_filter('escape_tex', filters.escape_latex)
82 82 self.register_filter('highlight', filters.highlight2latex)
83 83
84 84
85 85 @property
86 86 def default_config(self):
87 87 c = Config({
88 88 'NbConvertBase': {
89 89 'display_data_priority' : ['latex', 'pdf', 'png', 'jpg', 'svg', 'jpeg', 'text']
90 90 },
91 'ExtractFigureTransformer': {
91 'ExtractOutputTransformer': {
92 92 'enabled':True
93 93 },
94 94 'SVG2PDFTransformer': {
95 95 'enabled':True
96 96 },
97 97 'LatexTransformer': {
98 98 'enabled':True
99 99 }
100 100 })
101 101 c.merge(super(LatexExporter,self).default_config)
102 102 return c
@@ -1,42 +1,42
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 34 template_file = Unicode(
35 35 'rst', config=True,
36 36 help="Name of the template file to use")
37 37
38 38 @property
39 39 def default_config(self):
40 c = Config({'ExtractFigureTransformer':{'enabled':True}})
40 c = Config({'ExtractOutputTransformer':{'enabled':True}})
41 41 c.merge(super(RSTExporter,self).default_config)
42 42 return c
@@ -1,113 +1,113
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_figures(self):
49 49 """
50 If the ExtractFigureTransformer is enabled, are figures extracted?
50 If the ExtractOutputTransformer is enabled, are figures extracted?
51 51 """
52 config = Config({'ExtractFigureTransformer': {'enabled': True}})
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 'figures' in resources
57 57 assert len(resources['figures']) > 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 98 Can a transformer be added via the Exporter convinience 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 111 exporter = Exporter(config=config)
112 112 exporter.template_file = 'python'
113 113 return exporter No newline at end of file
@@ -1,12 +1,12
1 1 # Class base Transformers
2 2 from .base import Transformer
3 3 from .convertfigures import ConvertFiguresTransformer
4 4 from .svg2pdf import SVG2PDFTransformer
5 from .extractfigure import ExtractFigureTransformer
5 from .extractoutput import ExtractOutputTransformer
6 6 from .revealhelp import RevealHelpTransformer
7 7 from .latex import LatexTransformer
8 8 from .sphinx import SphinxTransformer
9 9 from .csshtmlheader import CSSHTMLHeaderTransformer
10 10
11 11 # decorated function Transformers
12 12 from .coalescestreams import coalesce_streams
@@ -1,101 +1,101
1 """Module containing a transformer that extracts all of the figures from the
2 notebook file. The extracted figures are returned in the 'resources' dictionary.
1 """Module containing a transformer that extracts all of the outputs from the
2 notebook file. The extracted outputs are returned in the 'resources' dictionary.
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 base64
17 17 import sys
18 18 import os
19 19
20 20 from IPython.utils.traitlets import Unicode
21 21 from .base import Transformer
22 22 from IPython.utils import py3compat
23 23
24 24 #-----------------------------------------------------------------------------
25 25 # Classes
26 26 #-----------------------------------------------------------------------------
27 27
28 class ExtractFigureTransformer(Transformer):
28 class ExtractOutputTransformer(Transformer):
29 29 """
30 Extracts all of the figures from the notebook file. The extracted
31 figures are returned in the 'resources' dictionary.
30 Extracts all of the outputs from the notebook file. The extracted
31 outputs are returned in the 'resources' dictionary.
32 32 """
33 33
34 34 figure_filename_template = Unicode(
35 35 "{unique_key}_{cell_index}_{index}.{extension}", config=True)
36 36
37 37
38 38 def transform_cell(self, cell, resources, cell_index):
39 39 """
40 40 Apply a transformation on each cell,
41 41
42 42 Parameters
43 43 ----------
44 44 cell : NotebookNode cell
45 45 Notebook cell being processed
46 46 resources : dictionary
47 47 Additional resources used in the conversion process. Allows
48 48 transformers to pass variables into the Jinja engine.
49 49 cell_index : int
50 50 Index of the cell being processed (see base.py)
51 51 """
52 52
53 53 #Get the unique key from the resource dict if it exists. If it does not
54 54 #exist, use 'figure' as the default. Also, get files directory if it
55 55 #has been specified
56 56 unique_key = resources.get('unique_key', 'figure')
57 57 output_files_dir = resources.get('output_files_dir', None)
58 58
59 #Make sure figures key exists
60 if not 'figures' in resources:
61 resources['figures'] = {}
59 #Make sure outputs key exists
60 if not 'outputs' in resources:
61 resources['outputs'] = {}
62 62
63 63 #Loop through all of the outputs in the cell
64 64 for index, out in enumerate(cell.get('outputs', [])):
65 65
66 66 #Get the output in data formats that the template is interested in.
67 67 for out_type in self.display_data_priority:
68 68 if out.hasattr(out_type):
69 69 data = out[out_type]
70 70
71 71 #Binary files are base64-encoded, SVG is already XML
72 72 if out_type in ('png', 'jpg', 'jpeg', 'pdf'):
73 73 # data is b64-encoded as text (str, unicode)
74 74 # decodestring only accepts bytes
75 75 data = py3compat.cast_bytes(data)
76 76 data = base64.decodestring(data)
77 77 elif sys.platform == 'win32':
78 78 data = data.replace('\n', '\r\n').encode("UTF-8")
79 79 else:
80 80 data = data.encode("UTF-8")
81 81
82 82 #Build a figure name
83 83 filename = self.figure_filename_template.format(
84 84 unique_key=unique_key,
85 85 cell_index=cell_index,
86 86 index=index,
87 87 extension=out_type)
88 88
89 89 #On the cell, make the figure available via
90 90 # cell.outputs[i].svg_filename ... etc (svg in example)
91 91 # Where
92 92 # cell.outputs[i].svg contains the data
93 93 if output_files_dir is not None:
94 94 filename = os.path.join(output_files_dir, filename)
95 95 out[out_type + '_filename'] = filename
96 96
97 97 #In the resources, make the figure available via
98 # resources['figures']['filename'] = data
99 resources['figures'][filename] = data
98 # resources['outputs']['filename'] = data
99 resources['outputs'][filename] = data
100 100
101 101 return cell, resources
General Comments 0
You need to be logged in to leave comments. Login now