##// END OF EJS Templates
Moved more code to Strings utilities file
Jonathan Frederic -
Show More
@@ -1,312 +1,306 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 befor conversion and jinja filter that would then be availlable 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 26 import re
27 27
28 28 # IPython imports
29 29 from IPython.config.configurable import Configurable
30 30 from IPython.nbformat import current as nbformat
31 31 from IPython.utils.traitlets import MetaHasTraits, Unicode, List, Bool
32 32 from IPython.utils.text import indent
33 33
34 34 # other libs/dependencies
35 35 from jinja2 import Environment, FileSystemLoader
36 36 from markdown import markdown
37 37
38 38 # local import (pre-transformers)
39 39 from exceptions import ConversionException
40 40 from . import transformers as trans #TODO
41 41 from .latex_transformer import (LatexTransformer) #TODO
42 42 from .utils import markdown2rst #TODO
43 43 from .utils import markdown2latex #TODO
44 44 from .utils import highlight2latex #TODO
45 45 from .utils import get_lines #TODO
46 46 from .utils import remove_ansi #TODO
47 47 from .utils import highlight, ansi2html #TODO
48 48 from .latex_transformer import rm_math_space #TODO
49 from .utils.strings import wrap as _wrap
49 import .utils.strings as strings
50 50
51 51 #Jinja2 filters
52 52 from .jinja_filters import (python_comment,
53 53 rm_fake,
54 54 escape_tex, FilterDataType,
55 55 rm_dollars
56 56 )
57 57
58 58 #Try to import the Sphinx exporter. If the user doesn't have Sphinx isntalled
59 59 #on his/her machine, fail silently.
60 60 try:
61 61 from .sphinx_transformer import (SphinxTransformer) #TODO
62 62 except ImportError:
63 63 SphinxTransformer = None
64 64
65 65 #-----------------------------------------------------------------------------
66 66 # Globals and constants
67 67 #-----------------------------------------------------------------------------
68 68
69 69 #Standard Jinja2 environment constants
70 70 TEMPLATE_PATH = "/../templates/"
71 71 TEMPLATE_SKELETON_PATH = "/../templates/skeleton/"
72 72 TEMPLATE_EXTENSION = ".tpl"
73 73
74 74 #Latex Jinja2 constants
75 75 LATEX_TEMPLATE_PATH = "/../templates/tex/"
76 76 LATEX_TEMPLATE_SKELETON_PATH = "/../templates/tex/skeleton/"
77 77 LATEX_TEMPLATE_EXTENSION = ".tplx"
78 78
79 79 #Special Jinja2 syntax that will not conflict when exporting latex.
80 80 LATEX_JINJA_COMMENT_BLOCK = ["((=", "=))"]
81 81 LATEX_JINJA_VARIABLE_BLOCK = ["(((", ")))"]
82 82 LATEX_JINJA_LOGIC_BLOCK = ["((*", "*))"]
83 83
84 84 #Jinja2 extensions to load.
85 85 JINJA_EXTENSIONS = ['jinja2.ext.loopcontrols']
86 86
87 87 #Latex substitutions for escaping latex.
88 88 LATEX_SUBS = (
89 89 (re.compile(r'\\'), r'\\textbackslash'),
90 90 (re.compile(r'([{}_#%&$])'), r'\\\1'),
91 91 (re.compile(r'~'), r'\~{}'),
92 92 (re.compile(r'\^'), r'\^{}'),
93 93 (re.compile(r'"'), r"''"),
94 94 (re.compile(r'\.\.\.+'), r'\\ldots'),
95 95 )
96 96
97 97 #-----------------------------------------------------------------------------
98 98 # Classes and functions
99 99 #-----------------------------------------------------------------------------
100 100 class Exporter(Configurable):
101 101 """ A Jinja2 base converter templates
102 102
103 103 Preprocess the ipynb files, feed it throug jinja templates,
104 104 and spit an converted files and a data object with other data
105 105 should be mostly configurable
106 106 """
107 107
108 108 pre_transformer_order = List(['haspyout_transformer'],
109 109 config=True,
110 110 help= """
111 111 An ordered list of pre transformer to apply to the ipynb
112 112 file before running through templates
113 113 """
114 114 )
115 115
116 116 tex_environement = Bool(
117 117 False,
118 118 config=True,
119 119 help=" Whether or not the user is exporting to latex.")
120 120
121 121 template_file = Unicode(
122 122 '', config=True,
123 123 help="Name of the template file to use")
124 124
125 125 #Processors that process the input data prior to the export, set in the
126 126 #constructor for this class.
127 127 preprocessors = []
128 128
129 129 def __init__(self, preprocessors={}, jinja_filters={}, config=None, **kw):
130 130 """ Init a new converter.
131 131
132 132 config: the Configurable config object to pass around.
133 133
134 134 preprocessors: dict of **availlable** key/value function to run on
135 135 ipynb json data before conversion to extract/inline file.
136 136 See `transformer.py` and `ConfigurableTransformers`
137 137
138 138 set the order in which the transformers should apply
139 139 with the `pre_transformer_order` trait of this class
140 140
141 141 transformers registerd by this key will take precedence on
142 142 default one.
143 143
144 144 jinja_filters: dict of supplementary jinja filter that should be made
145 145 availlable in template. If those are of Configurable Class type,
146 146 they will be instanciated with the config object as argument.
147 147
148 148 user defined filter will overwrite the one availlable by default.
149 149 """
150 150 super(ConverterTemplate, self).__init__(config=config, **kw)
151 151
152 152 #Create a Latex environment if the user is exporting latex.
153 153 if self.tex_environement:
154 154 self.ext = LATEX_TEMPLATE_EXTENSION
155 155 self.env = Environment(
156 156 loader=FileSystemLoader([
157 157 os.path.dirname(os.path.realpath(__file__)) + LATEX_TEMPLATE_PATH,
158 158 os.path.dirname(os.path.realpath(__file__)) + LATEX_TEMPLATE_SKELETON_PATH,
159 159 ]),
160 160 extensions=JINJA_EXTENSIONS
161 161 )
162 162
163 163 #Set special Jinja2 syntax that will not conflict with latex.
164 164 self.env.block_start_string = LATEX_JINJA_LOGIC_BLOCK[0]
165 165 self.env.block_end_string = LATEX_JINJA_LOGIC_BLOCK[1]
166 166 self.env.variable_start_string = LATEX_JINJA_VARIABLE_BLOCK[0]
167 167 self.env.variable_end_string = LATEX_JINJA_VARIABLE_BLOCK[1]
168 168 self.env.comment_start_string = LATEX_JINJA_COMMENT_BLOCK[0]
169 169 self.env.comment_end_string = LATEX_JINJA_COMMENT_BLOCK[1]
170 170
171 171 else: #Standard environment
172 172 self.ext = TEMPLATE_EXTENSION
173 173 self.env = Environment(
174 174 loader=FileSystemLoader([
175 175 os.path.dirname(os.path.realpath(__file__)) + TEMPLATE_PATH,
176 176 os.path.dirname(os.path.realpath(__file__)) + TEMPLATE_SKELETON_PATH,
177 177 ]),
178 178 extensions=JINJA_EXTENSIONS
179 179 )
180 180
181 181 for name in self.pre_transformer_order:
182 182 # get the user-defined transformer first
183 183 transformer = preprocessors.get(name, getattr(trans, name, None))
184 184 if isinstance(transformer, MetaHasTraits):
185 185 transformer = transformer(config=config)
186 186 self.preprocessors.append(transformer)
187 187
188 188 #For compatibility, TODO: remove later.
189 189 self.preprocessors.append(trans.coalesce_streams)
190 190 self.preprocessors.append(trans.ExtractFigureTransformer(config=config))
191 191 self.preprocessors.append(trans.RevealHelpTransformer(config=config))
192 192 self.preprocessors.append(trans.CSSHtmlHeaderTransformer(config=config))
193 193 self.preprocessors.append(LatexTransformer(config=config))
194 194
195 195 #Only load the sphinx transformer if the file reference worked
196 196 #(Sphinx dependencies exist on the user's machine.)
197 197 if SphinxTransformer:
198 198 self.preprocessors.append(SphinxTransformer(config=config))
199 199
200 200 #Add filters to the Jinja2 environment
201 201 self.env.filters['filter_data_type'] = FilterDataType(config=config)
202 202 self.env.filters['pycomment'] = _python_comment
203 203 self.env.filters['indent'] = indent
204 204 self.env.filters['rm_fake'] = _rm_fake
205 205 self.env.filters['rm_ansi'] = remove_ansi
206 206 self.env.filters['markdown'] = markdown
207 207 self.env.filters['ansi2html'] = ansi2html
208 208 self.env.filters['markdown2latex'] = markdown2latex
209 209 self.env.filters['markdown2rst'] = markdown2rst
210 210 self.env.filters['get_lines'] = get_lines
211 self.env.filters['wrap'] = _wrap
212 self.env.filters['rm_dollars'] = _rm_dollars
211 self.env.filters['wrap'] = strings.wrap
212 self.env.filters['rm_dollars'] = strings.strip_dollars
213 213 self.env.filters['rm_math_space'] = rm_math_space
214 214 self.env.filters['highlight2html'] = highlight
215 215 self.env.filters['highlight2latex'] = highlight2latex
216 216
217 217 #Latex specific filters
218 218 if self.tex_environement:
219 219 self.env.filters['escape_tex'] = _escape_tex
220 220 self.env.filters['highlight'] = highlight2latex
221 221 else:
222 222 self.env.filters['highlight'] = highlight
223 223
224 224 #Load user filters. Overwrite existing filters if need be.
225 225 for key, user_filter in jinja_filters.iteritems():
226 226 if isinstance(user_filter, MetaHasTraits):
227 227 self.env.filters[key] = user_filter(config=config)
228 228 else:
229 229 self.env.filters[key] = user_filter
230 230
231 231 #Load the template file.
232 232 self.template = self.env.get_template(self.template_file+self.ext)
233 233
234 234
235 235 def export(self, nb):
236 236 """Export notebook object
237 237
238 238 nb: Notebook object to export.
239 239
240 240 Returns both the converted ipynb file and a dict containing the
241 241 resources created along the way via the transformers and Jinja2
242 242 processing.
243 243 """
244 244
245 245 nb, resources = self._preprocess(nb)
246 246 return self.template.render(nb=nb, resources=resources), resources
247 247
248 248
249 249 def from_filename(self, filename):
250 250 """Read and export a notebook from a filename
251 251
252 252 filename: Filename of the notebook file to export.
253 253
254 254 Returns both the converted ipynb file and a dict containing the
255 255 resources created along the way via the transformers and Jinja2
256 256 processing.
257 257 """
258 258 with io.open(filename) as f:
259 259 return self.export(nbformat.read(f, 'json'))
260 260
261 261
262 262 def from_file(self, file_stream):
263 263 """Read and export a notebook from a filename
264 264
265 265 file_stream: File handle of file that contains notebook data.
266 266
267 267 Returns both the converted ipynb file and a dict containing the
268 268 resources created along the way via the transformers and Jinja2
269 269 processing.
270 270 """
271 271
272 272 return self.export(nbformat.read(file_stream, 'json'))
273 273
274 274
275 275 def _preprocess(self, nb):
276 276 """ Preprocess the notebook using the transformers specific
277 277 for the current export format.
278 278
279 279 nb: Notebook to preprocess
280 280 """
281 281
282 282 #Dict of 'resources' that can be filled by the preprocessors.
283 283 resources = {}
284 284
285 285 #Run each transformer on the notebook. Carry the output along
286 286 #to each transformer
287 287 for transformer in self.preprocessors:
288 288 nb, resources = transformer(nb, resources)
289 289 return nb, resources
290 290
291 291
292 292 #TODO: Comment me.
293 293 def _rm_fake(strng):
294 294 return strng.replace('/files/', '')
295 295
296
297 #TODO: Comment me.
298 def _rm_dollars(strng):
299 return strng.strip('$')
300
301
302 296 #TODO: Comment me.
303 297 def _python_comment(string):
304 298 return '# '+'\n# '.join(string.split('\n'))
305 299
306 300
307 301 #TODO: Comment me.
308 302 def _escape_tex(value):
309 303 newval = value
310 304 for pattern, replacement in LATEX_SUBS:
311 305 newval = pattern.sub(replacement, newval)
312 306 return newval No newline at end of file
@@ -1,29 +1,35 b''
1 1 """String utilities.
2 2
3 3 Contains a collection of usefull string manipulations functions.
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 # Our own imports
18 18 import textwrap #TODO
19 19
20 20 #-----------------------------------------------------------------------------
21 21 # Functions
22 22 #-----------------------------------------------------------------------------
23 23 def wrap(text, width=100):
24 """ Try to detect and wrap paragraph"""
24 """ Intelligently wrap text"""
25 25
26 26 splitt = text.split('\n')
27 27 wrp = map(lambda x:textwrap.wrap(x,width),splitt)
28 28 wrpd = map('\n'.join, wrp)
29 return '\n'.join(wrpd) No newline at end of file
29 return '\n'.join(wrpd)
30
31
32 def strip_dollars(text):
33 """Remove all dollar symbols from text"""
34
35 return text.strip('$') No newline at end of file
General Comments 0
You need to be logged in to leave comments. Login now