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