##// END OF EJS Templates
Fixed problem with data type filter construction.
Jonathan Frederic -
Show More
@@ -1,219 +1,226 b''
1 """Exporter for the notebook conversion pipeline.
1 """Exporter for the notebook conversion pipeline.
2
2
3 This module defines Exporter, a highly configurable converter
3 This module defines Exporter, a highly configurable converter
4 that uses Jinja2 to export notebook files into different format.
4 that uses Jinja2 to export notebook files into different format.
5
5
6 You can register both pre-transformers that will act on the notebook format
6 You can register both pre-transformers that will act on the notebook format
7 before conversion and jinja filter that would then be available in the templates
7 before conversion and jinja filter that would then be available in the templates
8 """
8 """
9
9
10 #-----------------------------------------------------------------------------
10 #-----------------------------------------------------------------------------
11 # Copyright (c) 2013, the IPython Development Team.
11 # Copyright (c) 2013, the IPython Development Team.
12 #
12 #
13 # Distributed under the terms of the Modified BSD License.
13 # Distributed under the terms of the Modified BSD License.
14 #
14 #
15 # The full license is in the file COPYING.txt, distributed with this software.
15 # The full license is in the file COPYING.txt, distributed with this software.
16 #-----------------------------------------------------------------------------
16 #-----------------------------------------------------------------------------
17
17
18 #-----------------------------------------------------------------------------
18 #-----------------------------------------------------------------------------
19 # Imports
19 # Imports
20 #-----------------------------------------------------------------------------
20 #-----------------------------------------------------------------------------
21 from __future__ import print_function, absolute_import
21 from __future__ import print_function, absolute_import
22
22
23 # Stdlib imports
23 # Stdlib imports
24 import io
24 import io
25 import os
25 import os
26 import inspect
26
27
27 # IPython imports
28 # IPython imports
28 from IPython.config.configurable import Configurable
29 from IPython.config.configurable import Configurable
29 from IPython.nbformat import current as nbformat
30 from IPython.nbformat import current as nbformat
30 from IPython.utils.traitlets import MetaHasTraits, Unicode, List, Bool
31 from IPython.utils.traitlets import MetaHasTraits, Unicode, List, Bool
31 from IPython.utils.text import indent
32 from IPython.utils.text import indent
32
33
33 # other libs/dependencies
34 # other libs/dependencies
34 from jinja2 import Environment, FileSystemLoader
35 from jinja2 import Environment, FileSystemLoader
35 from markdown import markdown
36 from markdown import markdown
36
37
37 # local import
38 # local import
38 import nbconvert.filters.strings
39 import nbconvert.filters.strings
39 import nbconvert.filters.markdown
40 import nbconvert.filters.markdown
40 import nbconvert.filters.latex
41 import nbconvert.filters.latex
41 import nbconvert.filters.datatypefilter
42 import nbconvert.filters.datatypefilter
42 import nbconvert.filters.highlight
43 import nbconvert.filters.highlight
43 import nbconvert.filters.ansi
44 import nbconvert.filters.ansi
44
45
45 import nbconvert.transformers.extractfigure
46 import nbconvert.transformers.extractfigure
46 import nbconvert.transformers.coalescestreams
47 import nbconvert.transformers.coalescestreams
47
48
48
49
49 #-----------------------------------------------------------------------------
50 #-----------------------------------------------------------------------------
50 # Globals and constants
51 # Globals and constants
51 #-----------------------------------------------------------------------------
52 #-----------------------------------------------------------------------------
52
53
53 #Standard Jinja2 environment constants
54 #Standard Jinja2 environment constants
54 TEMPLATE_PATH = "/../templates/"
55 TEMPLATE_PATH = "/../templates/"
55 TEMPLATE_SKELETON_PATH = "/../templates/skeleton/"
56 TEMPLATE_SKELETON_PATH = "/../templates/skeleton/"
56
57
57 #Jinja2 extensions to load.
58 #Jinja2 extensions to load.
58 JINJA_EXTENSIONS = ['jinja2.ext.loopcontrols']
59 JINJA_EXTENSIONS = ['jinja2.ext.loopcontrols']
59
60
60 #-----------------------------------------------------------------------------
61 #-----------------------------------------------------------------------------
61 # Classes and functions
62 # Classes and functions
62 #-----------------------------------------------------------------------------
63 #-----------------------------------------------------------------------------
63 class Exporter(Configurable):
64 class Exporter(Configurable):
64 pre_transformer_order = List(['haspyout_transformer'],
65 pre_transformer_order = List(['haspyout_transformer'],
65 config=True,
66 config=True,
66 help= """
67 help= """
67 An ordered list of pre-transformer to apply to the IPYNB
68 An ordered list of pre-transformer to apply to the IPYNB
68 file before running through templates
69 file before running through templates
69 """
70 """
70 )
71 )
71
72
72 template_file = Unicode(
73 template_file = Unicode(
73 '', config=True,
74 '', config=True,
74 help="Name of the template file to use")
75 help="Name of the template file to use")
75
76
76 file_extension = Unicode(
77 file_extension = Unicode(
77 'txt', config=True,
78 'txt', config=True,
78 help="Extension of the file that should be written to disk"
79 help="Extension of the file that should be written to disk"
79 )
80 )
80
81
81 stdout = Bool(
82 stdout = Bool(
82 True, config=True,
83 True, config=True,
83 help="""Whether to print the converted IPYNB file to stdout
84 help="""Whether to print the converted IPYNB file to stdout
84 use full do diff files without actually writing a new file"""
85 use full do diff files without actually writing a new file"""
85 )
86 )
86
87
87 write = Bool(
88 write = Bool(
88 False, config=True,
89 False, config=True,
89 help="""Should the converted notebook file be written to disk
90 help="""Should the converted notebook file be written to disk
90 along with potential extracted resources."""
91 along with potential extracted resources."""
91 )
92 )
92
93
93 #Extension that the template files use.
94 #Extension that the template files use.
94 template_extension = ".tpl"
95 template_extension = ".tpl"
95
96
96 #Processors that process the input data prior to the export, set in the
97 #Processors that process the input data prior to the export, set in the
97 #constructor for this class.
98 #constructor for this class.
98 preprocessors = []
99 preprocessors = []
99
100
100 # Public Constructor #####################################################
101 # Public Constructor #####################################################
101
102
102 def __init__(self, preprocessors=None, jinja_filters=None, config=None, **kw):
103 def __init__(self, preprocessors=None, jinja_filters=None, config=None, **kw):
103
104
104 #Call the base class constructor
105 #Call the base class constructor
105 super(Exporter, self).__init__(config=config, **kw)
106 super(Exporter, self).__init__(config=config, **kw)
106
107
107 #Standard environment
108 #Standard environment
108 self._init_environment()
109 self._init_environment()
109
110
110 #TODO: Implement reflection style methods to get user transformers.
111 #TODO: Implement reflection style methods to get user transformers.
111 #if not preprocessors is None:
112 #if not preprocessors is None:
112 # for name in self.pre_transformer_order:
113 # for name in self.pre_transformer_order:
113 # # get the user-defined transformer first
114 # # get the user-defined transformer first
114 # transformer = preprocessors.get(name, getattr(trans, name, None))
115 # transformer = preprocessors.get(name, getattr(trans, name, None))
115 # if isinstance(transformer, MetaHasTraits):
116 # if isinstance(transformer, MetaHasTraits):
116 # transformer = transformer(config=config)
117 # transformer = transformer(config=config)
117 # self.preprocessors.append(transformer)
118 # self.preprocessors.append(transformer)
118
119
119 #Add transformers
120 #Add transformers
120 self._register_transformers()
121 self._register_transformers()
121
122
122 #Add filters to the Jinja2 environment
123 #Add filters to the Jinja2 environment
123 self._register_filters()
124 self._register_filters()
124
125
125 #Load user filters. Overwrite existing filters if need be.
126 #Load user filters. Overwrite existing filters if need be.
126 if not jinja_filters is None:
127 if not jinja_filters is None:
127 for key, user_filter in jinja_filters.iteritems():
128 for key, user_filter in jinja_filters.iteritems():
128 if issubclass(user_filter, MetaHasTraits):
129 if issubclass(user_filter, MetaHasTraits):
129 self.environment.filters[key] = user_filter(config=config)
130 self.environment.filters[key] = user_filter(config=config)
130 else:
131 else:
131 self.environment.filters[key] = user_filter
132 self.environment.filters[key] = user_filter
132
133
133 # Public methods #########################################
134 # Public methods #########################################
134
135
135 def from_notebook_node(self, nb):
136 def from_notebook_node(self, nb):
136 nb, resources = self._preprocess(nb)
137 nb, resources = self._preprocess(nb)
137
138
138 #Load the template file.
139 #Load the template file.
139 self.template = self.environment.get_template(self.template_file+self.template_extension)
140 self.template = self.environment.get_template(self.template_file+self.template_extension)
140
141
141 return self.template.render(nb=nb, resources=resources), resources
142 return self.template.render(nb=nb, resources=resources), resources
142
143
143
144
144 def from_filename(self, filename):
145 def from_filename(self, filename):
145 with io.open(filename) as f:
146 with io.open(filename) as f:
146 return self.from_notebook_node(nbformat.read(f, 'json'))
147 return self.from_notebook_node(nbformat.read(f, 'json'))
147
148
148
149
149 def from_file(self, file_stream):
150 def from_file(self, file_stream):
150 return self.from_notebook_node(nbformat.read(file_stream, 'json'))
151 return self.from_notebook_node(nbformat.read(file_stream, 'json'))
151
152
152
153
153 def register_transformer(self, transformer):
154 def register_transformer(self, transformer):
154 if isinstance(transformer, MetaHasTraits):
155 if inspect.isfunction(transformer):
156 self.preprocessors.append(transformer)
157 return transformer
158 elif isinstance(transformer, MetaHasTraits):
155 transformer_instance = transformer(config=self.config)
159 transformer_instance = transformer(config=self.config)
156 self.preprocessors.append(transformer_instance)
160 self.preprocessors.append(transformer_instance)
157 return transformer_instance
161 return transformer_instance
158 else:
162 else:
159 self.preprocessors.append(transformer)
163 transformer_instance = transformer()
160 return transformer
164 self.preprocessors.append(transformer_instance)
165 return transformer_instance
161
166
162
167
163 def register_filter(self, name, filter):
168 def register_filter(self, name, filter):
164 if isinstance(filter, MetaHasTraits):
169 if inspect.isfunction(filter):
170 self.environment.filters[name] = filter
171 elif isinstance(filter, MetaHasTraits):
165 self.environment.filters[name] = filter(config=self.config)
172 self.environment.filters[name] = filter(config=self.config)
166 else:
173 else:
167 self.environment.filters[name] = filter
174 self.environment.filters[name] = filter()
168 return self.environment.filters[name]
175 return self.environment.filters[name]
169
176
170
177
171 # Protected and Private methods #########################################
178 # Protected and Private methods #########################################
172
179
173 def _register_transformers(self):
180 def _register_transformers(self):
174 self.register_transformer(nbconvert.transformers.coalescestreams.coalesce_streams)
181 self.register_transformer(nbconvert.transformers.coalescestreams.coalesce_streams)
175
182
176 #Remember the figure extraction transformer so it can be enabled and
183 #Remember the figure extraction transformer so it can be enabled and
177 #disabled easily later.
184 #disabled easily later.
178 self.extract_figure_transformer = self.register_transformer(nbconvert.transformers.extractfigure.ExtractFigureTransformer)
185 self.extract_figure_transformer = self.register_transformer(nbconvert.transformers.extractfigure.ExtractFigureTransformer)
179
186
180
187
181 def _register_filters(self):
188 def _register_filters(self):
182 self.register_filter('indent', indent)
189 self.register_filter('indent', indent)
183 self.register_filter('markdown', markdown)
190 self.register_filter('markdown', markdown)
184 self.register_filter('ansi2html', nbconvert.filters.ansi.ansi2html)
191 self.register_filter('ansi2html', nbconvert.filters.ansi.ansi2html)
185 self.register_filter('filter_data_type', nbconvert.filters.datatypefilter.DataTypeFilter)
192 self.register_filter('filter_data_type', nbconvert.filters.datatypefilter.DataTypeFilter)
186 self.register_filter('get_lines', nbconvert.filters.strings.get_lines)
193 self.register_filter('get_lines', nbconvert.filters.strings.get_lines)
187 self.register_filter('highlight', nbconvert.filters.highlight.highlight)
194 self.register_filter('highlight', nbconvert.filters.highlight.highlight)
188 self.register_filter('highlight2html', nbconvert.filters.highlight.highlight)
195 self.register_filter('highlight2html', nbconvert.filters.highlight.highlight)
189 self.register_filter('highlight2latex', nbconvert.filters.highlight.highlight2latex)
196 self.register_filter('highlight2latex', nbconvert.filters.highlight.highlight2latex)
190 self.register_filter('markdown2latex', nbconvert.filters.markdown.markdown2latex)
197 self.register_filter('markdown2latex', nbconvert.filters.markdown.markdown2latex)
191 self.register_filter('markdown2rst', nbconvert.filters.markdown.markdown2rst)
198 self.register_filter('markdown2rst', nbconvert.filters.markdown.markdown2rst)
192 self.register_filter('pycomment', nbconvert.filters.strings.python_comment)
199 self.register_filter('pycomment', nbconvert.filters.strings.python_comment)
193 self.register_filter('rm_ansi', nbconvert.filters.ansi.remove_ansi)
200 self.register_filter('rm_ansi', nbconvert.filters.ansi.remove_ansi)
194 self.register_filter('rm_dollars', nbconvert.filters.strings.strip_dollars)
201 self.register_filter('rm_dollars', nbconvert.filters.strings.strip_dollars)
195 self.register_filter('rm_fake', nbconvert.filters.strings.rm_fake)
202 self.register_filter('rm_fake', nbconvert.filters.strings.rm_fake)
196 self.register_filter('rm_math_space', nbconvert.filters.latex.rm_math_space)
203 self.register_filter('rm_math_space', nbconvert.filters.latex.rm_math_space)
197 self.register_filter('wrap', nbconvert.filters.strings.wrap)
204 self.register_filter('wrap', nbconvert.filters.strings.wrap)
198
205
199
206
200 def _init_environment(self):
207 def _init_environment(self):
201 self.environment = Environment(
208 self.environment = Environment(
202 loader=FileSystemLoader([
209 loader=FileSystemLoader([
203 os.path.dirname(os.path.realpath(__file__)) + TEMPLATE_PATH,
210 os.path.dirname(os.path.realpath(__file__)) + TEMPLATE_PATH,
204 os.path.dirname(os.path.realpath(__file__)) + TEMPLATE_SKELETON_PATH,
211 os.path.dirname(os.path.realpath(__file__)) + TEMPLATE_SKELETON_PATH,
205 ]),
212 ]),
206 extensions=JINJA_EXTENSIONS
213 extensions=JINJA_EXTENSIONS
207 )
214 )
208
215
209
216
210 def _preprocess(self, nb):
217 def _preprocess(self, nb):
211
218
212 #Dict of 'resources' that can be filled by the preprocessors.
219 #Dict of 'resources' that can be filled by the preprocessors.
213 resources = {}
220 resources = {}
214
221
215 #Run each transformer on the notebook. Carry the output along
222 #Run each transformer on the notebook. Carry the output along
216 #to each transformer
223 #to each transformer
217 for transformer in self.preprocessors:
224 for transformer in self.preprocessors:
218 nb, resources = transformer(nb, resources)
225 nb, resources = transformer(nb, resources)
219 return nb, resources
226 return nb, resources
@@ -1,39 +1,30 b''
1 """Filter used to select the first preferred output format available.
1 """Filter used to select the first preferred output format available.
2
2
3 The filter contained in the file allows the converter templates to select
3 The filter contained in the file allows the converter templates to select
4 the output format that is most valuable to the active export format. The
4 the output format that is most valuable to the active export format. The
5 value of the different formats is set via
5 value of the different formats is set via
6 GlobalConfigurable.display_data_priority
6 GlobalConfigurable.display_data_priority
7 """
7 """
8 #-----------------------------------------------------------------------------
8 #-----------------------------------------------------------------------------
9 # Copyright (c) 2013, the IPython Development Team.
9 # Copyright (c) 2013, the IPython Development Team.
10 #
10 #
11 # Distributed under the terms of the Modified BSD License.
11 # Distributed under the terms of the Modified BSD License.
12 #
12 #
13 # The full license is in the file COPYING.txt, distributed with this software.
13 # The full license is in the file COPYING.txt, distributed with this software.
14 #-----------------------------------------------------------------------------
14 #-----------------------------------------------------------------------------
15
15
16 #-----------------------------------------------------------------------------
16 #-----------------------------------------------------------------------------
17 # Classes and functions
17 # Classes and functions
18 #-----------------------------------------------------------------------------
18 #-----------------------------------------------------------------------------
19 class DataTypeFilter(object):
19 class DataTypeFilter(object):
20 """ Returns the preferred display format """
20 """ Returns the preferred display format """
21
21
22 display_data_priority = None
22 display_data_priority = ['html', 'pdf', 'svg', 'latex', 'png', 'jpg', 'jpeg' , 'text']
23
24 def __init__(self, display_data_priority):
25
26 #Make sure that the display data priority variably is not None.
27 if display_data_priority is None:
28 raise TypeError
29 else:
30 self.display_data_priority = display_data_priority
31
32
23
33 def __call__(self, output):
24 def __call__(self, output):
34 """ Return the first available format in the priority """
25 """ Return the first available format in the priority """
35
26
36 for fmt in self.display_data_priority:
27 for fmt in self.display_data_priority:
37 if fmt in output:
28 if fmt in output:
38 return [fmt]
29 return [fmt]
39 return [] No newline at end of file
30 return []
General Comments 0
You need to be logged in to leave comments. Login now