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