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