##// END OF EJS Templates
create configurable preprocessors
Matthias BUSSONNIER -
Show More
@@ -16,17 +16,18 b' a conversion of IPython notebooks to some other format should inherit.'
16 16 #-----------------------------------------------------------------------------
17 17
18 18 from __future__ import print_function, absolute_import
19 from .transformers import extract_figure_transformer
20 19 import converters.transformers as trans
21 20 from converters.jinja_filters import (python_comment, indent,
22 21 rm_fake, remove_ansi, markdown, highlight,
23 22 ansi2html, markdown2latex, escape_tex)
24 23
25 24
25
26 26 # Stdlib imports
27 27 import io
28 28 import os
29 29 from IPython.utils import path
30 from IPython.utils.traitlets import MetaHasTraits
30 31
31 32 from jinja2 import Environment, FileSystemLoader
32 33 env = Environment(
@@ -118,8 +119,8 b' class ConverterTemplate(Configurable):'
118 119 the others.
119 120 """
120 121 )
121
122 pre_transformer_order = List(['haspyout_transformer'],
122
123 pre_transformer_order = List(['haspyout_transformer', 'Foobar'],
123 124 config=True,
124 125 help= """
125 126 An ordered list of pre transformer to apply to the ipynb
@@ -169,10 +170,14 b' class ConverterTemplate(Configurable):'
169 170 self.ext = '.tplx' if self.tex_environement else '.tpl'
170 171 self.nb = None
171 172 self.preprocessors = preprocessors
173
172 174 for name in self.pre_transformer_order:
173 self.preprocessors.append(getattr(trans, name))
175 tr = getattr(trans, name)
176 if isinstance(tr, MetaHasTraits):
177 tr = tr(config=config)
178 self.preprocessors.append(tr)
174 179 if self.extract_figures:
175 self.preprocessors.append(extract_figure_transformer)
180 self.preprocessors.append(trans.ExtractFigureTransformer(config=config))
176 181
177 182 self.env.filters['filter_data_type'] = self.filter_data_type
178 183 self.env.filters['pycomment'] = python_comment
@@ -218,3 +223,5 b' class ConverterTemplate(Configurable):'
218 223 with io.open(filename) as f:
219 224 self.nb = nbformat.read(f, 'json')
220 225
226
227
@@ -2,6 +2,41 b''
2 2
3 3 """
4 4
5 from __future__ import print_function
6
7 from IPython.config.configurable import Configurable
8 from IPython.utils.traitlets import Unicode, Bool, Dict
9
10 class ConfigurableTransformers(Configurable):
11 """ A configurable transformer """
12
13 def __init__(self, config=None, **kw):
14 super(ConfigurableTransformers, self).__init__(config=config, **kw)
15
16 def __call__(self, nb, other):
17 try :
18 for worksheet in nb.worksheets :
19 for index, cell in enumerate(worksheet.cells):
20 worksheet.cells[index], other = self.cell_transform(cell, other, index)
21 return nb, other
22 except NotImplementedError as error :
23 raise NotImplementedError('should be implemented by subclass')
24
25 def cell_transform(self, cell, other, index):
26 """
27 Overwrite if you want to apply a transformation on each cell
28 """
29 raise NotImplementedError('should be implemented by subclass')
30
31
32 class Foobar(ConfigurableTransformers):
33 message = Unicode('-- nothing', config=True)
34
35
36 def cell_transform(self, cell, other, index):
37 return cell, other
38
39
5 40 def cell_preprocessor(function):
6 41 """ wrap a function to be executed on all cells of a notebook
7 42
@@ -22,7 +57,7 b' def cell_preprocessor(function):'
22 57 def haspyout_transformer(cell, other, count):
23 58 """
24 59 Add a haspyout flag to cell that have it
25
60
26 61 Easier for templating, where you can't know in advance
27 62 wether to write the out prompt
28 63
@@ -37,28 +72,54 b' def haspyout_transformer(cell, other, count):'
37 72
38 73
39 74 # todo, make the key part configurable.
40 def _new_figure(data, fmt, count):
41 """Create a new figure file in the given format.
42 75
43 Returns a path relative to the input file.
44 """
45 figname = '_fig_%02i.%s' % (count, fmt)
76 class ExtractFigureTransformer(ConfigurableTransformers):
77 enabled = Bool(False,
78 config=True,
79 help=""" If set to false, this transformer will be no-op """
80 )
46 81
47 # Binary files are base64-encoded, SVG is already XML
48 if fmt in ('png', 'jpg', 'pdf'):
49 data = data.decode('base64')
82 extra_ext_map = Dict({},
83 config=True,
84 help="""extra map to override extension based on type.
85 Usefull for latex where svg will be converted to pdf before inclusion
86 """
87 )
50 88
51 return figname, data
52 89
53 @cell_preprocessor
54 def extract_figure_transformer(cell, other, count):
55 for i, out in enumerate(cell.get('outputs', [])):
56 for type in ['html', 'pdf', 'svg', 'latex', 'png', 'jpg', 'jpeg']:
57 if out.hasattr(type):
58 figname, data = _new_figure(out[type], type, count)
59 cell.outputs[i][type] = figname
60 out['key_'+type] = figname
61 other[figname] = data
62 count = count+1
63 return cell, other
90 #to do change this to .format {} syntax
91 key_tpl = Unicode('_fig_%02i.%s', config=True)
92
93 def _get_ext(self, ext):
94 if ext in self.extra_ext_map :
95 return self.extra_ext_map[ext]
96 return ext
97
98 def _new_figure(self, data, fmt, count):
99 """Create a new figure file in the given format.
100
101 Returns a path relative to the input file.
102 """
103 figname = self.key_tpl % (count, self._get_ext(fmt))
104 key = self.key_tpl % (count, fmt)
105
106 # Binary files are base64-encoded, SVG is already XML
107 if fmt in ('png', 'jpg', 'pdf'):
108 data = data.decode('base64')
109
110 return figname, key, data
111
112
113 def cell_transform(self, cell, other, count):
114 if not self.enabled:
115 return cell, other
116 for i, out in enumerate(cell.get('outputs', [])):
117 for type in ['html', 'pdf', 'svg', 'latex', 'png', 'jpg', 'jpeg']:
118 if out.hasattr(type):
119 figname, key, data = self._new_figure(out[type], type, count)
120 cell.outputs[i][type] = figname
121 out['key_'+type] = figname
122 other[key] = data
123 count = count+1
124 return cell, other
64 125
@@ -1,5 +1,8 b''
1 1 c = get_config()
2 2
3
3 4 c.ConverterTemplate.extract_figures=False
4 5 c.ConverterTemplate.template_file='fullhtml'
5 6 c.ConverterTemplate.tex_environement=False
7
8 c.ExtractFigureTransformer.enabled = False
@@ -1,5 +1,7 b''
1 1 c = get_config()
2 2
3 c.ConverterTemplate.extract_figures=False
3 c.ConverterTemplate.extract_figures=True
4 4 c.ConverterTemplate.template_file='latex_base'
5 5 c.ConverterTemplate.tex_environement=True
6
7 c.ExtractFigureTransformer.extra_ext_map={'svg':'pdf'}
@@ -17,6 +17,8 b' from IPython.config.application import Application'
17 17 from IPython.config.loader import ConfigFileNotFound
18 18 from IPython.utils.traitlets import List, Unicode, Type, Bool, Dict, CaselessStrEnum
19 19
20 from converters.transformers import (ConfigurableTransformers,Foobar,ExtractFigureTransformer)
21
20 22
21 23 class NbconvertApp(Application):
22 24
@@ -24,6 +26,9 b' class NbconvertApp(Application):'
24 26 def __init__(self, **kwargs):
25 27 super(NbconvertApp, self).__init__(**kwargs)
26 28 self.classes.insert(0,ConverterTemplate)
29 # register class here to have help with help all
30 self.classes.insert(0,ExtractFigureTransformer)
31 self.classes.insert(0,Foobar)
27 32 # ensure those are registerd
28 33
29 34 def load_config_file(self, profile_name):
@@ -54,11 +59,6 b' class NbconvertApp(Application):'
54 59
55 60 template_file = sys.argv[1]
56 61
57 if template_file.startswith('latex'):
58 tex_environement=True
59 else:
60 tex_environement=False
61
62 62 C = ConverterTemplate(tplfile=sys.argv[1],
63 63 config=self.config)
64 64 C.read(ipynb_file)
@@ -37,7 +37,14 b' it introduces a new line'
37 37
38 38 ((*- block data_png -*))
39 39 \begin{center}
40 \includegraphics[width=0.7\textwidth]{(((output.png)))}
40 \includegraphics[width=0.7\textwidth]{(((output.key_png)))}
41 \par
42 \end{center}
43 ((*- endblock -*))
44
45 ((*- block data_svg -*))
46 \begin{center}
47 \includegraphics[width=0.7\textwidth]{(((output.key_svg)))}
41 48 \par
42 49 \end{center}
43 50 ((*- endblock -*))
General Comments 0
You need to be logged in to leave comments. Login now