##// END OF EJS Templates
Fixed None transformers error.
Jonathan Frederic -
Show More
@@ -1,315 +1,317 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
24 24 # IPython imports
25 25 from IPython.config.configurable import Configurable
26 26 from IPython.nbformat import current as nbformat
27 27 from IPython.utils.traitlets import MetaHasTraits, Unicode, List, Bool
28 28 from IPython.utils.text import indent
29 29
30 30 # other libs/dependencies
31 31 from jinja2 import Environment, FileSystemLoader
32 32 from markdown import markdown
33 33
34 34 # local import
35 35 import nbconvert.filters.strings
36 36 import nbconvert.filters.markdown
37 37 import nbconvert.filters.latex
38 38 import nbconvert.filters.datatypefilter
39 39 import nbconvert.filters.highlight
40 40 import nbconvert.filters.ansi
41 41
42 42 import nbconvert.transformers.extractfigure
43 43 import nbconvert.transformers.coalescestreams
44 44
45 45 #-----------------------------------------------------------------------------
46 46 # Globals and constants
47 47 #-----------------------------------------------------------------------------
48 48
49 49 #Jinja2 extensions to load.
50 50 JINJA_EXTENSIONS = ['jinja2.ext.loopcontrols']
51 51
52 52 #-----------------------------------------------------------------------------
53 53 # Class
54 54 #-----------------------------------------------------------------------------
55 55
56 56 class Exporter(Configurable):
57 57 """
58 58 Exports notebooks into other file formats. Uses Jinja 2 templating engine
59 59 to output new formats. Inherit from this class if you are creating a new
60 60 template type along with new filters/transformers. If the filters/
61 61 transformers provided by default suffice, there is no need to inherit from
62 62 this class. Instead, override the template_file and file_extension
63 63 traits via a config file.
64 64 """
65 65
66 66 template_file = Unicode(
67 67 '', config=True,
68 68 help="Name of the template file to use")
69 69
70 70 file_extension = Unicode(
71 71 'txt', config=True,
72 72 help="Extension of the file that should be written to disk"
73 73 )
74 74
75 75 template_path = Unicode(
76 76 "/../templates/", config=True,
77 77 help="Path where the template files are located.")
78 78
79 79 template_skeleton_path = Unicode(
80 80 "/../templates/skeleton/", config=True,
81 81 help="Path where the template skeleton files are located.")
82 82
83 83 #Jinja block definitions
84 84 jinja_comment_block_start = Unicode("", config=True)
85 85 jinja_comment_block_end = Unicode("", config=True)
86 86 jinja_variable_block_start = Unicode("", config=True)
87 87 jinja_variable_block_end = Unicode("", config=True)
88 88 jinja_logic_block_start = Unicode("", config=True)
89 89 jinja_logic_block_end = Unicode("", config=True)
90 90
91 91 #Extension that the template files use.
92 92 template_extension = Unicode(".tpl", config=True)
93 93
94 94 #Processors that process the input data prior to the export, set in the
95 95 #constructor for this class.
96 96 transformers = []
97 97
98 98
99 99 def __init__(self, transformers=None, filters=None, config=None, **kw):
100 100 """
101 101 Public constructor
102 102
103 103 Parameters
104 104 ----------
105 105 transformers : list[of transformer]
106 106 Custom transformers to apply to the notebook prior to engaging
107 107 the Jinja template engine. Any transformers specified here
108 108 will override existing transformers if a naming conflict
109 109 occurs.
110 110 filters : list[of filter]
111 111 Custom filters to make accessible to the Jinja templates. Any
112 112 filters specified here will override existing filters if a
113 113 naming conflict occurs.
114 114 config : config
115 115 User configuration instance.
116 116 """
117 117
118 118 #Call the base class constructor
119 119 super(Exporter, self).__init__(config=config, **kw)
120 120
121 121 #Standard environment
122 122 self._init_environment()
123 123
124 124 #Add transformers
125 125 self._register_transformers()
126 126
127 127 #Add filters to the Jinja2 environment
128 128 self._register_filters()
129 129
130 130 #Load user transformers. Overwrite existing transformers if need be.
131 131 if not transformers is None:
132 132 for transformer in transformers:
133 133 self.register_transformer(transformer)
134 134
135 135 #Load user filters. Overwrite existing filters if need be.
136 136 if not filters is None:
137 137 for key, user_filter in filters.iteritems():
138 138 if issubclass(user_filter, MetaHasTraits):
139 139 self.environment.filters[key] = user_filter(config=config)
140 140 else:
141 141 self.environment.filters[key] = user_filter
142 142
143 143
144 144 def from_notebook_node(self, nb):
145 145 """
146 146 Convert a notebook from a notebook node instance.
147 147
148 148 Parameters
149 149 ----------
150 150 nb : Notebook node
151 151 """
152 152
153 153 nb, resources = self._preprocess(nb)
154 154
155 155 #Load the template file.
156 156 self.template = self.environment.get_template(self.template_file+self.template_extension)
157 157
158 158 return self.template.render(nb=nb, resources=resources), resources
159 159
160 160
161 161 def from_filename(self, filename):
162 162 """
163 163 Convert a notebook from a notebook file.
164 164
165 165 Parameters
166 166 ----------
167 167 filename : str
168 168 Full filename of the notebook file to open and convert.
169 169 """
170 170
171 171 with io.open(filename) as f:
172 172 return self.from_notebook_node(nbformat.read(f, 'json'))
173 173
174 174
175 175 def from_file(self, file_stream):
176 176 """
177 177 Convert a notebook from a notebook file.
178 178
179 179 Parameters
180 180 ----------
181 181 file_stream : file-like object
182 182 Notebook file-like object to convert.
183 183 """
184 184 return self.from_notebook_node(nbformat.read(file_stream, 'json'))
185 185
186 186
187 187 def register_transformer(self, transformer):
188 188 """
189 189 Register a transformer.
190 190 Transformers are classes that act upon the notebook before it is
191 191 passed into the Jinja templating engine. Transformers are also
192 192 capable of passing additional information to the Jinja
193 193 templating engine.
194 194
195 195 Parameters
196 196 ----------
197 197 transformer : transformer
198 198 """
199 if self.transformers is None:
200 self.transformers = []
199 201
200 202 if inspect.isfunction(transformer):
201 203 self.transformers.append(transformer)
202 204 return transformer
203 205 elif isinstance(transformer, MetaHasTraits):
204 206 transformer_instance = transformer(config=self.config)
205 207 self.transformers.append(transformer_instance)
206 208 return transformer_instance
207 209 else:
208 210 transformer_instance = transformer()
209 211 self.transformers.append(transformer_instance)
210 212 return transformer_instance
211 213
212 214
213 215 def register_filter(self, name, filter):
214 216 """
215 217 Register a filter.
216 218 A filter is a function that accepts and acts on one string.
217 219 The filters are accesible within the Jinja templating engine.
218 220
219 221 Parameters
220 222 ----------
221 223 name : str
222 224 name to give the filter in the Jinja engine
223 225 filter : filter
224 226 """
225 227 if inspect.isfunction(filter):
226 228 self.environment.filters[name] = filter
227 229 elif isinstance(filter, MetaHasTraits):
228 230 self.environment.filters[name] = filter(config=self.config)
229 231 else:
230 232 self.environment.filters[name] = filter()
231 233 return self.environment.filters[name]
232 234
233 235
234 236 def _register_transformers(self):
235 237 """
236 238 Register all of the transformers needed for this exporter.
237 239 """
238 240
239 241 self.register_transformer(nbconvert.transformers.coalescestreams.coalesce_streams)
240 242
241 243 #Remember the figure extraction transformer so it can be enabled and
242 244 #disabled easily later.
243 245 self.extract_figure_transformer = self.register_transformer(nbconvert.transformers.extractfigure.ExtractFigureTransformer)
244 246
245 247
246 248 def _register_filters(self):
247 249 """
248 250 Register all of the filters required for the exporter.
249 251 """
250 252
251 253 self.register_filter('indent', indent)
252 254 self.register_filter('markdown', markdown)
253 255 self.register_filter('ansi2html', nbconvert.filters.ansi.ansi2html)
254 256 self.register_filter('filter_data_type', nbconvert.filters.datatypefilter.DataTypeFilter)
255 257 self.register_filter('get_lines', nbconvert.filters.strings.get_lines)
256 258 self.register_filter('highlight', nbconvert.filters.highlight.highlight)
257 259 self.register_filter('highlight2html', nbconvert.filters.highlight.highlight)
258 260 self.register_filter('highlight2latex', nbconvert.filters.highlight.highlight2latex)
259 261 self.register_filter('markdown2latex', nbconvert.filters.markdown.markdown2latex)
260 262 self.register_filter('markdown2rst', nbconvert.filters.markdown.markdown2rst)
261 263 self.register_filter('pycomment', nbconvert.filters.strings.python_comment)
262 264 self.register_filter('rm_ansi', nbconvert.filters.ansi.remove_ansi)
263 265 self.register_filter('rm_dollars', nbconvert.filters.strings.strip_dollars)
264 266 self.register_filter('rm_fake', nbconvert.filters.strings.rm_fake)
265 267 self.register_filter('rm_math_space', nbconvert.filters.latex.rm_math_space)
266 268 self.register_filter('wrap', nbconvert.filters.strings.wrap)
267 269
268 270
269 271 def _init_environment(self):
270 272 """
271 273 Create the Jinja templating environment.
272 274 """
273 275
274 276 self.environment = Environment(
275 277 loader=FileSystemLoader([
276 278 os.path.dirname(os.path.realpath(__file__)) + self.template_path,
277 279 os.path.dirname(os.path.realpath(__file__)) + self.template_skeleton_path,
278 280 ]),
279 281 extensions=JINJA_EXTENSIONS
280 282 )
281 283
282 284 #Set special Jinja2 syntax that will not conflict with latex.
283 285 if self.jinja_logic_block_start:
284 286 self.environment.block_start_string = self.jinja_logic_block_start
285 287 if self.jinja_logic_block_end:
286 288 self.environment.block_end_string = self.jinja_logic_block_end
287 289 if self.jinja_variable_block_start:
288 290 self.environment.variable_start_string = self.jinja_variable_block_start
289 291 if self.jinja_variable_block_end:
290 292 self.environment.variable_end_string = self.jinja_variable_block_end
291 293 if self.jinja_comment_block_start:
292 294 self.environment.comment_start_string = self.jinja_comment_block_start
293 295 if self.jinja_comment_block_end:
294 296 self.environment.comment_end_string = self.jinja_comment_block_end
295 297
296 298
297 299 def _preprocess(self, nb):
298 300 """
299 301 Preprocess the notebook before passing it into the Jinja engine.
300 302 To preprocess the notebook is to apply all of the
301 303
302 304 Parameters
303 305 ----------
304 306 nb : notebook node
305 307 notebook that is being exported.
306 308 """
307 309
308 310 #Dict of 'resources' that can be filled by the transformers.
309 311 resources = {}
310 312
311 313 #Run each transformer on the notebook. Carry the output along
312 314 #to each transformer
313 315 for transformer in self.transformers:
314 316 nb, resources = transformer(nb, resources)
315 317 return nb, resources
General Comments 0
You need to be logged in to leave comments. Login now