##// END OF EJS Templates
Rebase changes made by hand
Jonathan Frederic -
Show More
@@ -1,9 +1,9
1 1 from .export import *
2 2 from .html import HTMLExporter
3 3 from .slides import SlidesExporter
4 from .exporter import TemplateExporter
4 from .templateexporter import TemplateExporter
5 5 from .latex import LatexExporter
6 6 from .markdown import MarkdownExporter
7 7 from .python import PythonExporter
8 8 from .rst import RSTExporter
9 from .baseexporter import BaseExporter
9 from .exporter import Exporter
@@ -1,169 +1,169
1 1 """
2 2 Module containing single call export functions.
3 3 """
4 4 #-----------------------------------------------------------------------------
5 5 # Copyright (c) 2013, the IPython Development Team.
6 6 #
7 7 # Distributed under the terms of the Modified BSD License.
8 8 #
9 9 # The full license is in the file COPYING.txt, distributed with this software.
10 10 #-----------------------------------------------------------------------------
11 11
12 12 #-----------------------------------------------------------------------------
13 13 # Imports
14 14 #-----------------------------------------------------------------------------
15 15
16 16 from functools import wraps
17 17
18 18 from IPython.nbformat.v3.nbbase import NotebookNode
19 19 from IPython.config import Config
20 20
21 from .exporter import TemplateExporter
21 from .templateexporter import TemplateExporter
22 22 from .html import HTMLExporter
23 23 from .slides import SlidesExporter
24 24 from .latex import LatexExporter
25 25 from .markdown import MarkdownExporter
26 26 from .python import PythonExporter
27 27 from .rst import RSTExporter
28 28
29 29 #-----------------------------------------------------------------------------
30 30 # Classes
31 31 #-----------------------------------------------------------------------------
32 32
33 33 def DocDecorator(f):
34 34
35 35 #Set docstring of function
36 36 f.__doc__ = f.__doc__ + """
37 37 nb : Notebook node
38 38 config : config (optional, keyword arg)
39 39 User configuration instance.
40 40 resources : dict (optional, keyword arg)
41 41 Resources used in the conversion process.
42 42
43 43 Returns
44 44 ----------
45 45 tuple- output, resources, exporter_instance
46 46 output : str
47 47 Jinja 2 output. This is the resulting converted notebook.
48 48 resources : dictionary
49 49 Dictionary of resources used prior to and during the conversion
50 50 process.
51 51 exporter_instance : Exporter
52 52 Instance of the Exporter class used to export the document. Useful
53 53 to caller because it provides a 'file_extension' property which
54 54 specifies what extension the output should be saved as.
55 55
56 56 WARNING: API WILL CHANGE IN FUTURE RELEASES OF NBCONVERT
57 57 """
58 58
59 59 @wraps(f)
60 60 def decorator(*args, **kwargs):
61 61 return f(*args, **kwargs)
62 62
63 63 return decorator
64 64
65 65
66 66 #-----------------------------------------------------------------------------
67 67 # Functions
68 68 #-----------------------------------------------------------------------------
69 69
70 70 __all__ = [
71 71 'export',
72 72 'export_html',
73 73 'export_custom',
74 74 'export_slides',
75 75 'export_latex',
76 76 'export_markdown',
77 77 'export_python',
78 78 'export_rst',
79 79 'export_by_name',
80 80 'get_export_names',
81 81 'ExporterNameError'
82 82 ]
83 83
84 84
85 85 class ExporterNameError(NameError):
86 86 pass
87 87
88 88 @DocDecorator
89 89 def export(exporter, nb, **kw):
90 90 """
91 91 Export a notebook object using specific exporter class.
92 92
93 93 exporter : Exporter class type or instance
94 94 Class type or instance of the exporter that should be used. If the
95 95 method initializes it's own instance of the class, it is ASSUMED that
96 96 the class type provided exposes a constructor (__init__) with the same
97 97 signature as the base Exporter class.
98 98 """
99 99
100 100 #Check arguments
101 101 if exporter is None:
102 102 raise TypeError("Exporter is None")
103 103 elif not isinstance(exporter, TemplateExporter) and not issubclass(exporter, TemplateExporter):
104 104 raise TypeError("exporter does not inherit from Exporter (base)")
105 105 if nb is None:
106 106 raise TypeError("nb is None")
107 107
108 108 #Create the exporter
109 109 resources = kw.pop('resources', None)
110 110 if isinstance(exporter, TemplateExporter):
111 111 exporter_instance = exporter
112 112 else:
113 113 exporter_instance = exporter(**kw)
114 114
115 115 #Try to convert the notebook using the appropriate conversion function.
116 116 if isinstance(nb, NotebookNode):
117 117 output, resources = exporter_instance.from_notebook_node(nb, resources)
118 118 elif isinstance(nb, basestring):
119 119 output, resources = exporter_instance.from_filename(nb, resources)
120 120 else:
121 121 output, resources = exporter_instance.from_file(nb, resources)
122 122 return output, resources
123 123
124 124 exporter_map = dict(
125 125 custom=TemplateExporter,
126 126 html=HTMLExporter,
127 127 slides=SlidesExporter,
128 128 latex=LatexExporter,
129 129 markdown=MarkdownExporter,
130 130 python=PythonExporter,
131 131 rst=RSTExporter,
132 132 )
133 133
134 134 def _make_exporter(name, E):
135 135 """make an export_foo function from a short key and Exporter class E"""
136 136 def _export(nb, **kw):
137 137 return export(E, nb, **kw)
138 138 _export.__doc__ = """Export a notebook object to {0} format""".format(name)
139 139 return _export
140 140
141 141 g = globals()
142 142
143 143 for name, E in exporter_map.items():
144 144 g['export_%s' % name] = DocDecorator(_make_exporter(name, E))
145 145
146 146 @DocDecorator
147 147 def export_by_name(format_name, nb, **kw):
148 148 """
149 149 Export a notebook object to a template type by its name. Reflection
150 150 (Inspect) is used to find the template's corresponding explicit export
151 151 method defined in this module. That method is then called directly.
152 152
153 153 format_name : str
154 154 Name of the template style to export to.
155 155 """
156 156
157 157 function_name = "export_" + format_name.lower()
158 158
159 159 if function_name in globals():
160 160 return globals()[function_name](nb, **kw)
161 161 else:
162 162 raise ExporterNameError("template for `%s` not found" % function_name)
163 163
164 164
165 165 def get_export_names():
166 166 """Return a list of the currently supported export targets
167 167
168 168 WARNING: API WILL CHANGE IN FUTURE RELEASES OF NBCONVERT"""
169 169 return sorted(exporter_map.keys())
@@ -1,282 +1,281
1 """This module defines BaseExporter, a highly configurable converter
1 """This module defines Exporter, a highly configurable converter
2 2 that uses Jinja2 to export notebook files into different formats.
3 3 """
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 from __future__ import print_function, absolute_import
18 18
19 19 # Stdlib imports
20 20 import io
21 21 import os
22 22 import copy
23 23 import collections
24 24 import datetime
25 25
26 26
27 27 # IPython imports
28 28 from IPython.config.configurable import LoggingConfigurable
29 29 from IPython.config import Config
30 30 from IPython.nbformat import current as nbformat
31 31 from IPython.utils.traitlets import MetaHasTraits, Unicode, List
32 32 from IPython.utils.importstring import import_item
33 from IPython.utils import py3compat
33 from IPython.utils import text, py3compat
34 34
35 from IPython.nbconvert import transformers as nbtransformers
35 from IPython.nbconvert import preprocessors as nbpreprocessors
36 36
37 37
38 38 #-----------------------------------------------------------------------------
39 39 # Class
40 40 #-----------------------------------------------------------------------------
41 41
42 42 class ResourcesDict(collections.defaultdict):
43 43 def __missing__(self, key):
44 44 return ''
45 45
46 46
47 class BaseExporter(LoggingConfigurable):
47 class Exporter(LoggingConfigurable):
48 48 """
49 Base Exporter Class that only conver notebook to notebook
50 and apply the transformers and provide basic methods for
49 Exporter class that only converts from notebook to notebook
50 by applying the preprocessors and providing basic methods for
51 51 reading a notebook from different sources.
52
53 52 """
54 53
55 54 # finish the docstring
56 55
57 56 file_extension = Unicode(
58 57 'txt', config=True,
59 58 help="Extension of the file that should be written to disk"
60 59 )
61 60
62 #Configurability, allows the user to easily add transformers.
63 transformers = List(config=True,
64 help="""List of transformers, by name or namespace, to enable.""")
61 #Configurability, allows the user to easily add filters and preprocessors.
62 preprocessors = List(config=True,
63 help="""List of preprocessors, by name or namespace, to enable.""")
65 64
66 _transformers = None
65 _preprocessors = None
67 66
68 default_transformers = List([nbtransformers.coalesce_streams,
69 nbtransformers.SVG2PDFTransformer,
70 nbtransformers.ExtractOutputTransformer,
71 nbtransformers.CSSHTMLHeaderTransformer,
72 nbtransformers.RevealHelpTransformer,
73 nbtransformers.LatexTransformer,
74 nbtransformers.SphinxTransformer],
67 default_preprocessors = List([nbpreprocessors.coalesce_streams,
68 nbpreprocessors.SVG2PDFPreprocessor,
69 nbpreprocessors.ExtractOutputPreprocessor,
70 nbpreprocessors.CSSHTMLHeaderPreprocessor,
71 nbpreprocessors.RevealHelpPreprocessor,
72 nbpreprocessors.LatexPreprocessor,
73 nbpreprocessors.SphinxPreprocessor],
75 74 config=True,
76 help="""List of transformers available by default, by name, namespace,
75 help="""List of preprocessors available by default, by name, namespace,
77 76 instance, or type.""")
78 77
79 78
80 79 def __init__(self, config=None, **kw):
81 80 """
82 81 Public constructor
83 82
84 83 Parameters
85 84 ----------
86 85 config : config
87 86 User configuration instance.
88 87 """
89 88 if not config:
90 89 config = self.default_config
91 90
92 super(BaseExporter, self).__init__(config=config, **kw)
91 super(Exporter, self).__init__(config=config, **kw)
93 92
94 93 #Init
95 self._init_transformers()
94 self._init_preprocessors()
96 95
97 96
98 97 @property
99 98 def default_config(self):
100 99 return Config()
101 100
102 101 def _config_changed(self, name, old, new):
103 102 """When setting config, make sure to start with our default_config"""
104 103 c = self.default_config
105 104 if new:
106 105 c.merge(new)
107 106 if c != old:
108 107 self.config = c
109 super(BaseExporter, self)._config_changed(name, old, c)
108 super(Exporter, self)._config_changed(name, old, c)
110 109
111 110
112 111 def from_notebook_node(self, nb, resources=None):
113 112 """
114 113 Convert a notebook from a notebook node instance.
115 114
116 115 Parameters
117 116 ----------
118 117 nb : Notebook node
119 118 resources : dict (**kw)
120 119 of additional resources that can be accessed read/write by
121 transformers.
120 preprocessors.
122 121 """
123 122 nb_copy = copy.deepcopy(nb)
124 123 resources = self._init_resources(resources)
125 124
126 125 # Preprocess
127 126 nb_copy, resources = self._transform(nb_copy, resources)
128 127
129 128 return nb_copy, resources
130 129
131 130
132 131 def from_filename(self, filename, resources=None, **kw):
133 132 """
134 133 Convert a notebook from a notebook file.
135 134
136 135 Parameters
137 136 ----------
138 137 filename : str
139 138 Full filename of the notebook file to open and convert.
140 139 """
141 140
142 #Pull the metadata from the filesystem.
141 # Pull the metadata from the filesystem.
143 142 if resources is None:
144 143 resources = ResourcesDict()
145 144 if not 'metadata' in resources or resources['metadata'] == '':
146 145 resources['metadata'] = ResourcesDict()
147 146 basename = os.path.basename(filename)
148 147 notebook_name = basename[:basename.rfind('.')]
149 148 resources['metadata']['name'] = notebook_name
150 149
151 150 modified_date = datetime.datetime.fromtimestamp(os.path.getmtime(filename))
152 resources['metadata']['modified_date'] = modified_date.strftime("%B %d, %Y")
151 resources['metadata']['modified_date'] = modified_date.strftime(text.date_format)
153 152
154 153 with io.open(filename) as f:
155 154 return self.from_notebook_node(nbformat.read(f, 'json'), resources=resources, **kw)
156 155
157 156
158 157 def from_file(self, file_stream, resources=None, **kw):
159 158 """
160 159 Convert a notebook from a notebook file.
161 160
162 161 Parameters
163 162 ----------
164 163 file_stream : file-like object
165 164 Notebook file-like object to convert.
166 165 """
167 166 return self.from_notebook_node(nbformat.read(file_stream, 'json'), resources=resources, **kw)
168 167
169 168
170 def register_transformer(self, transformer, enabled=False):
169 def register_preprocessor(self, preprocessor, enabled=False):
171 170 """
172 Register a transformer.
173 Transformers are classes that act upon the notebook before it is
174 passed into the Jinja templating engine. Transformers are also
171 Register a preprocessor.
172 preprocessors are classes that act upon the notebook before it is
173 passed into the Jinja templating engine. preprocessors are also
175 174 capable of passing additional information to the Jinja
176 175 templating engine.
177 176
178 177 Parameters
179 178 ----------
180 transformer : transformer
179 preprocessor : preprocessor
181 180 """
182 if transformer is None:
183 raise TypeError('transformer')
184 isclass = isinstance(transformer, type)
181 if preprocessor is None:
182 raise TypeError('preprocessor')
183 isclass = isinstance(preprocessor, type)
185 184 constructed = not isclass
186 185
187 #Handle transformer's registration based on it's type
188 if constructed and isinstance(transformer, py3compat.string_types):
189 #Transformer is a string, import the namespace and recursively call
190 #this register_transformer method
191 transformer_cls = import_item(transformer)
192 return self.register_transformer(transformer_cls, enabled)
186 #Handle preprocessor's registration based on it's type
187 if constructed and isinstance(preprocessor, py3compat.string_types):
188 #preprocessor is a string, import the namespace and recursively call
189 #this register_preprocessor method
190 preprocessor_cls = import_item(preprocessor)
191 return self.register_preprocessor(preprocessor_cls, enabled)
193 192
194 if constructed and hasattr(transformer, '__call__'):
195 #Transformer is a function, no need to construct it.
196 #Register and return the transformer.
193 if constructed and hasattr(preprocessor, '__call__'):
194 #preprocessor is a function, no need to construct it.
195 #Register and return the preprocessor.
197 196 if enabled:
198 transformer.enabled = True
199 self._transformers.append(transformer)
200 return transformer
197 preprocessor.enabled = True
198 self._preprocessors.append(preprocessor)
199 return preprocessor
201 200
202 elif isclass and isinstance(transformer, MetaHasTraits):
203 #Transformer is configurable. Make sure to pass in new default for
201 elif isclass and isinstance(preprocessor, MetaHasTraits):
202 #preprocessor is configurable. Make sure to pass in new default for
204 203 #the enabled flag if one was specified.
205 self.register_transformer(transformer(parent=self), enabled)
204 self.register_preprocessor(preprocessor(parent=self), enabled)
206 205
207 206 elif isclass:
208 #Transformer is not configurable, construct it
209 self.register_transformer(transformer(), enabled)
207 #preprocessor is not configurable, construct it
208 self.register_preprocessor(preprocessor(), enabled)
210 209
211 210 else:
212 #Transformer is an instance of something without a __call__
211 #preprocessor is an instance of something without a __call__
213 212 #attribute.
214 raise TypeError('transformer')
213 raise TypeError('preprocessor')
215 214
216 215
217 def _init_transformers(self):
216 def _init_preprocessors(self):
218 217 """
219 Register all of the transformers needed for this exporter, disabled
218 Register all of the preprocessors needed for this exporter, disabled
220 219 unless specified explicitly.
221 220 """
222 if self._transformers is None:
223 self._transformers = []
221 if self._preprocessors is None:
222 self._preprocessors = []
224 223
225 #Load default transformers (not necessarly enabled by default).
226 if self.default_transformers:
227 for transformer in self.default_transformers:
228 self.register_transformer(transformer)
224 #Load default preprocessors (not necessarly enabled by default).
225 if self.default_preprocessors:
226 for preprocessor in self.default_preprocessors:
227 self.register_preprocessor(preprocessor)
229 228
230 #Load user transformers. Enable by default.
231 if self.transformers:
232 for transformer in self.transformers:
233 self.register_transformer(transformer, enabled=True)
229 #Load user preprocessors. Enable by default.
230 if self.preprocessors:
231 for preprocessor in self.preprocessors:
232 self.register_preprocessor(preprocessor, enabled=True)
234 233
235 234
236 235 def _init_resources(self, resources):
237 236
238 237 #Make sure the resources dict is of ResourcesDict type.
239 238 if resources is None:
240 239 resources = ResourcesDict()
241 240 if not isinstance(resources, ResourcesDict):
242 241 new_resources = ResourcesDict()
243 242 new_resources.update(resources)
244 243 resources = new_resources
245 244
246 245 #Make sure the metadata extension exists in resources
247 246 if 'metadata' in resources:
248 247 if not isinstance(resources['metadata'], ResourcesDict):
249 248 resources['metadata'] = ResourcesDict(resources['metadata'])
250 249 else:
251 250 resources['metadata'] = ResourcesDict()
252 251 if not resources['metadata']['name']:
253 252 resources['metadata']['name'] = 'Notebook'
254 253
255 254 #Set the output extension
256 255 resources['output_extension'] = self.file_extension
257 256 return resources
258 257
259 258
260 259 def _transform(self, nb, resources):
261 260 """
262 261 Preprocess the notebook before passing it into the Jinja engine.
263 262 To preprocess the notebook is to apply all of the
264 263
265 264 Parameters
266 265 ----------
267 266 nb : notebook node
268 267 notebook that is being exported.
269 268 resources : a dict of additional resources that
270 can be accessed read/write by transformers
269 can be accessed read/write by preprocessors
271 270 """
272 271
273 272 # Do a copy.deepcopy first,
274 # we are never safe enough with what the transformers could do.
273 # we are never safe enough with what the preprocessors could do.
275 274 nbc = copy.deepcopy(nb)
276 275 resc = copy.deepcopy(resources)
277 276
278 #Run each transformer on the notebook. Carry the output along
279 #to each transformer
280 for transformer in self._transformers:
281 nbc, resc = transformer(nbc, resc)
277 #Run each preprocessor on the notebook. Carry the output along
278 #to each preprocessor
279 for preprocessor in self._preprocessors:
280 nbc, resc = preprocessor(nbc, resc)
282 281 return nbc, resc
@@ -1,52 +1,52
1 1 """
2 2 Exporter that exports Basic HTML.
3 3 """
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 from IPython.utils.traitlets import Unicode, List
18 18
19 19 from IPython.nbconvert import preprocessors
20 20 from IPython.config import Config
21 21
22 from .exporter import TemplateExporter
22 from .templateexporter import TemplateExporter
23 23
24 24 #-----------------------------------------------------------------------------
25 25 # Classes
26 26 #-----------------------------------------------------------------------------
27 27
28 28 class HTMLExporter(TemplateExporter):
29 29 """
30 30 Exports a basic HTML document. This exporter assists with the export of
31 31 HTML. Inherit from it if you are writing your own HTML template and need
32 32 custom preprocessors/filters. If you don't need custom preprocessors/
33 33 filters, just change the 'template_file' config option.
34 34 """
35 35
36 36 file_extension = Unicode(
37 37 'html', config=True,
38 38 help="Extension of the file that should be written to disk"
39 39 )
40 40
41 41 default_template = Unicode('full', config=True, help="""Flavor of the data
42 42 format to use. I.E. 'full' or 'basic'""")
43 43
44 44 @property
45 45 def default_config(self):
46 46 c = Config({
47 47 'CSSHTMLHeaderPreprocessor':{
48 48 'enabled':True
49 49 }
50 50 })
51 51 c.merge(super(HTMLExporter,self).default_config)
52 52 return c
@@ -1,91 +1,91
1 1 """
2 2 Exporter that allows Latex Jinja templates to work. Contains logic to
3 3 appropriately prepare IPYNB files for export to LaTeX. Including but
4 4 not limited to escaping LaTeX, fixing math region tags, using special
5 5 tags to circumvent Jinja/Latex syntax conflicts.
6 6 """
7 7 #-----------------------------------------------------------------------------
8 8 # Copyright (c) 2013, the IPython Development Team.
9 9 #
10 10 # Distributed under the terms of the Modified BSD License.
11 11 #
12 12 # The full license is in the file COPYING.txt, distributed with this software.
13 13 #-----------------------------------------------------------------------------
14 14
15 15 #-----------------------------------------------------------------------------
16 16 # Imports
17 17 #-----------------------------------------------------------------------------
18 18
19 19 # Stdlib imports
20 20 import os
21 21
22 22 # IPython imports
23 23 from IPython.utils.traitlets import Unicode, List
24 24 from IPython.config import Config
25 25
26 26 from IPython.nbconvert import filters, preprocessors
27 from .exporter import Exporter
27 from .templateexporter import TemplateExporter
28 28
29 29 #-----------------------------------------------------------------------------
30 30 # Classes and functions
31 31 #-----------------------------------------------------------------------------
32 32
33 class LatexExporter(Exporter):
33 class LatexExporter(TemplateExporter):
34 34 """
35 35 Exports to a Latex template. Inherit from this class if your template is
36 36 LaTeX based and you need custom tranformers/filters. Inherit from it if
37 37 you are writing your own HTML template and need custom tranformers/filters.
38 38 If you don't need custom tranformers/filters, just change the
39 39 'template_file' config option. Place your template in the special "/latex"
40 40 subfolder of the "../templates" folder.
41 41 """
42 42
43 43 file_extension = Unicode(
44 44 'tex', config=True,
45 45 help="Extension of the file that should be written to disk")
46 46
47 47 default_template = Unicode('article', config=True, help="""Template of the
48 48 data format to use. I.E. 'full' or 'basic'""")
49 49
50 50 #Latex constants
51 51 default_template_path = Unicode(
52 52 os.path.join("..", "templates", "latex"), config=True,
53 53 help="Path where the template files are located.")
54 54
55 55 template_skeleton_path = Unicode(
56 56 os.path.join("..", "templates", "latex", "skeleton"), config=True,
57 57 help="Path where the template skeleton files are located.")
58 58
59 59 #Special Jinja2 syntax that will not conflict when exporting latex.
60 60 jinja_comment_block_start = Unicode("((=", config=True)
61 61 jinja_comment_block_end = Unicode("=))", config=True)
62 62 jinja_variable_block_start = Unicode("(((", config=True)
63 63 jinja_variable_block_end = Unicode(")))", config=True)
64 64 jinja_logic_block_start = Unicode("((*", config=True)
65 65 jinja_logic_block_end = Unicode("*))", config=True)
66 66
67 67 #Extension that the template files use.
68 68 template_extension = Unicode(".tplx", config=True)
69 69
70 70
71 71 @property
72 72 def default_config(self):
73 73 c = Config({
74 74 'NbConvertBase': {
75 75 'display_data_priority' : ['latex', 'pdf', 'png', 'jpg', 'svg', 'jpeg', 'text']
76 76 },
77 77 'ExtractOutputPreprocessor': {
78 78 'enabled':True
79 79 },
80 80 'SVG2PDFPreprocessor': {
81 81 'enabled':True
82 82 },
83 83 'LatexPreprocessor': {
84 84 'enabled':True
85 85 },
86 86 'SphinxPreprocessor': {
87 87 'enabled':True
88 88 }
89 89 })
90 90 c.merge(super(LatexExporter,self).default_config)
91 91 return c
@@ -1,38 +1,38
1 1 """
2 2 Exporter that will export your ipynb to Markdown.
3 3 """
4 4 #-----------------------------------------------------------------------------
5 5 # Copyright (c) 2013, the IPython Development Team.
6 6 #
7 7 # Distributed under the terms of the Modified BSD License.
8 8 #
9 9 # The full license is in the file COPYING.txt, distributed with this software.
10 10 #-----------------------------------------------------------------------------
11 11
12 12 #-----------------------------------------------------------------------------
13 13 # Imports
14 14 #-----------------------------------------------------------------------------
15 15
16 16 from IPython.config import Config
17 17 from IPython.utils.traitlets import Unicode
18 18
19 from .exporter import TemplateExporter
19 from .templateexporter import TemplateExporter
20 20
21 21 #-----------------------------------------------------------------------------
22 22 # Classes
23 23 #-----------------------------------------------------------------------------
24 24
25 25 class MarkdownExporter(TemplateExporter):
26 26 """
27 27 Exports to a markdown document (.md)
28 28 """
29 29
30 30 file_extension = Unicode(
31 31 'md', config=True,
32 32 help="Extension of the file that should be written to disk")
33 33
34 34 @property
35 35 def default_config(self):
36 36 c = Config({'ExtractOutputPreprocessor':{'enabled':True}})
37 37 c.merge(super(MarkdownExporter,self).default_config)
38 38 return c
@@ -1,31 +1,31
1 1 """
2 2 Python exporter which exports Notebook code into a PY file.
3 3 """
4 4 #-----------------------------------------------------------------------------
5 5 # Copyright (c) 2013, the IPython Development Team.
6 6 #
7 7 # Distributed under the terms of the Modified BSD License.
8 8 #
9 9 # The full license is in the file COPYING.txt, distributed with this software.
10 10 #-----------------------------------------------------------------------------
11 11
12 12 #-----------------------------------------------------------------------------
13 13 # Imports
14 14 #-----------------------------------------------------------------------------
15 15
16 16 from IPython.utils.traitlets import Unicode
17 17
18 from .exporter import TemplateExporter
18 from .templateexporter import TemplateExporter
19 19
20 20 #-----------------------------------------------------------------------------
21 21 # Classes
22 22 #-----------------------------------------------------------------------------
23 23
24 24 class PythonExporter(TemplateExporter):
25 25 """
26 26 Exports a Python code file.
27 27 """
28 28
29 29 file_extension = Unicode(
30 30 'py', config=True,
31 31 help="Extension of the file that should be written to disk")
@@ -1,38 +1,38
1 1 """
2 2 Exporter for exporting notebooks to restructured text.
3 3 """
4 4 #-----------------------------------------------------------------------------
5 5 # Copyright (c) 2013, the IPython Development Team.
6 6 #
7 7 # Distributed under the terms of the Modified BSD License.
8 8 #
9 9 # The full license is in the file COPYING.txt, distributed with this software.
10 10 #-----------------------------------------------------------------------------
11 11
12 12 #-----------------------------------------------------------------------------
13 13 # Imports
14 14 #-----------------------------------------------------------------------------
15 15
16 16 from IPython.utils.traitlets import Unicode
17 17 from IPython.config import Config
18 18
19 from .exporter import TemplateExporter
19 from .templateexporter import TemplateExporter
20 20
21 21 #-----------------------------------------------------------------------------
22 22 # Classes
23 23 #-----------------------------------------------------------------------------
24 24
25 25 class RSTExporter(TemplateExporter):
26 26 """
27 27 Exports restructured text documents.
28 28 """
29 29
30 30 file_extension = Unicode(
31 31 'rst', config=True,
32 32 help="Extension of the file that should be written to disk")
33 33
34 34 @property
35 35 def default_config(self):
36 36 c = Config({'ExtractOutputPreprocessor':{'enabled':True}})
37 37 c.merge(super(RSTExporter,self).default_config)
38 38 return c
@@ -1,52 +1,52
1 1 """
2 2 Contains slide show exporter
3 3 """
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 from IPython.utils.traitlets import Unicode
18 18
19 19 from IPython.nbconvert import preprocessors
20 20 from IPython.config import Config
21 21
22 from .exporter import TemplateExporter
22 from .templateexporter import TemplateExporter
23 23
24 24 #-----------------------------------------------------------------------------
25 25 # Classes
26 26 #-----------------------------------------------------------------------------
27 27
28 28 class SlidesExporter(TemplateExporter):
29 29 """
30 30 Exports slides
31 31 """
32 32
33 33 file_extension = Unicode(
34 34 'slides.html', config=True,
35 35 help="Extension of the file that should be written to disk"
36 36 )
37 37
38 38 default_template = Unicode('reveal', config=True, help="""Template of the
39 39 data format to use. I.E. 'reveal'""")
40 40
41 41 @property
42 42 def default_config(self):
43 43 c = Config({
44 44 'CSSHTMLHeaderPreprocessor':{
45 45 'enabled':True
46 46 },
47 47 'RevealHelpPreprocessor':{
48 48 'enabled':True,
49 49 },
50 50 })
51 51 c.merge(super(SlidesExporter,self).default_config)
52 52 return c
@@ -1,520 +1,315
1 1 """This module defines Exporter, a highly configurable converter
2 2 that uses Jinja2 to export notebook files into different formats.
3 3 """
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 from __future__ import print_function, absolute_import
18 18
19 19 # Stdlib imports
20 import io
21 20 import os
22 import inspect
23 import copy
24 import collections
25 import datetime
26 21
27 22 # other libs/dependencies
28 23 from jinja2 import Environment, FileSystemLoader, ChoiceLoader, TemplateNotFound
29 24
30 25 # IPython imports
31 from IPython.config.configurable import LoggingConfigurable
32 from IPython.config import Config
33 from IPython.nbformat import current as nbformat
34 from IPython.utils.traitlets import MetaHasTraits, DottedObjectName, Unicode, List, Dict, Any
26 from IPython.utils.traitlets import MetaHasTraits, Unicode, List, Dict, Any
35 27 from IPython.utils.importstring import import_item
36 from IPython.utils import text
37 from IPython.utils import py3compat
28 from IPython.utils import py3compat, text
38 29
39 from IPython.nbconvert import preprocessors as nbpreprocessors
40 30 from IPython.nbconvert import filters
31 from .exporter import Exporter
41 32
42 33 #-----------------------------------------------------------------------------
43 34 # Globals and constants
44 35 #-----------------------------------------------------------------------------
45 36
46 37 #Jinja2 extensions to load.
47 38 JINJA_EXTENSIONS = ['jinja2.ext.loopcontrols']
48 39
49 40 default_filters = {
50 41 'indent': text.indent,
51 42 'markdown2html': filters.markdown2html,
52 43 'ansi2html': filters.ansi2html,
53 44 'filter_data_type': filters.DataTypeFilter,
54 45 'get_lines': filters.get_lines,
55 46 'highlight2html': filters.highlight2html,
56 47 'highlight2latex': filters.highlight2latex,
57 48 'ipython2python': filters.ipython2python,
58 49 'posix_path': filters.posix_path,
59 50 'markdown2latex': filters.markdown2latex,
60 51 'markdown2rst': filters.markdown2rst,
61 52 'comment_lines': filters.comment_lines,
62 53 'strip_ansi': filters.strip_ansi,
63 54 'strip_dollars': filters.strip_dollars,
64 55 'strip_files_prefix': filters.strip_files_prefix,
65 56 'html2text' : filters.html2text,
66 57 'add_anchor': filters.add_anchor,
67 58 'ansi2latex': filters.ansi2latex,
68 59 'strip_math_space': filters.strip_math_space,
69 60 'wrap_text': filters.wrap_text,
70 61 'escape_latex': filters.escape_latex,
71 62 'citation2latex': filters.citation2latex,
72 63 'path2url': filters.path2url,
73 64 }
74 65
75 66 #-----------------------------------------------------------------------------
76 67 # Class
77 68 #-----------------------------------------------------------------------------
78 69
79 class ResourcesDict(collections.defaultdict):
80 def __missing__(self, key):
81 return ''
82
83
84 class Exporter(LoggingConfigurable):
70 class TemplateExporter(Exporter):
85 71 """
86 72 Exports notebooks into other file formats. Uses Jinja 2 templating engine
87 73 to output new formats. Inherit from this class if you are creating a new
88 74 template type along with new filters/preprocessors. If the filters/
89 75 preprocessors provided by default suffice, there is no need to inherit from
90 76 this class. Instead, override the template_file and file_extension
91 77 traits via a config file.
92 78
93 79 {filters}
94 80 """
95 81
96 82 # finish the docstring
97 83 __doc__ = __doc__.format(filters = '- '+'\n - '.join(default_filters.keys()))
98 84
99 85
100 86 template_file = Unicode(u'default',
101 87 config=True,
102 88 help="Name of the template file to use")
103 89 def _template_file_changed(self, name, old, new):
104 if new=='default':
90 if new == 'default':
105 91 self.template_file = self.default_template
106 92 else:
107 93 self.template_file = new
108 94 self.template = None
109 95 self._load_template()
110 96
111 97 default_template = Unicode(u'')
112 98 template = Any()
113 99 environment = Any()
114 100
115 file_extension = Unicode(
116 'txt', config=True,
117 help="Extension of the file that should be written to disk"
118 )
119
120 101 template_path = List(['.'], config=True)
121 102 def _template_path_changed(self, name, old, new):
122 103 self._load_template()
123 104
124 105 default_template_path = Unicode(
125 106 os.path.join("..", "templates"),
126 107 help="Path where the template files are located.")
127 108
128 109 template_skeleton_path = Unicode(
129 110 os.path.join("..", "templates", "skeleton"),
130 111 help="Path where the template skeleton files are located.")
131 112
132 113 #Jinja block definitions
133 114 jinja_comment_block_start = Unicode("", config=True)
134 115 jinja_comment_block_end = Unicode("", config=True)
135 116 jinja_variable_block_start = Unicode("", config=True)
136 117 jinja_variable_block_end = Unicode("", config=True)
137 118 jinja_logic_block_start = Unicode("", config=True)
138 119 jinja_logic_block_end = Unicode("", config=True)
139 120
140 121 #Extension that the template files use.
141 122 template_extension = Unicode(".tpl", config=True)
142 123
143 #Configurability, allows the user to easily add filters and preprocessors.
144 preprocessors = List(config=True,
145 help="""List of preprocessors, by name or namespace, to enable.""")
146
147 124 filters = Dict(config=True,
148 125 help="""Dictionary of filters, by name and namespace, to add to the Jinja
149 126 environment.""")
150 127
151 default_preprocessors = List([nbpreprocessors.coalesce_streams,
152 nbpreprocessors.SVG2PDFPreprocessor,
153 nbpreprocessors.ExtractOutputPreprocessor,
154 nbpreprocessors.CSSHTMLHeaderPreprocessor,
155 nbpreprocessors.RevealHelpPreprocessor,
156 nbpreprocessors.LatexPreprocessor,
157 nbpreprocessors.SphinxPreprocessor],
158 config=True,
159 help="""List of preprocessors available by default, by name, namespace,
160 instance, or type.""")
161
162 128
163 129 def __init__(self, config=None, extra_loaders=None, **kw):
164 130 """
165 131 Public constructor
166 132
167 133 Parameters
168 134 ----------
169 135 config : config
170 136 User configuration instance.
171 137 extra_loaders : list[of Jinja Loaders]
172 138 ordered list of Jinja loader to find templates. Will be tried in order
173 139 before the default FileSystem ones.
174 140 template : str (optional, kw arg)
175 141 Template to use when exporting.
176 142 """
177 143 if not config:
178 144 config = self.default_config
179 145
180 146 super(Exporter, self).__init__(config=config, **kw)
181 147
182 148 #Init
183 149 self._init_template()
184 150 self._init_environment(extra_loaders=extra_loaders)
185 151 self._init_preprocessors()
186 152 self._init_filters()
187 153
188 154
189 @property
190 def default_config(self):
191 return Config()
192
193 def _config_changed(self, name, old, new):
194 """When setting config, make sure to start with our default_config"""
195 c = self.default_config
196 if new:
197 c.merge(new)
198 if c != old:
199 self.config = c
200 super(Exporter, self)._config_changed(name, old, c)
201
202
203 155 def _load_template(self):
204 156 """Load the Jinja template object from the template file
205 157
206 158 This is a no-op if the template attribute is already defined,
207 159 or the Jinja environment is not setup yet.
208 160
209 161 This is triggered by various trait changes that would change the template.
210 162 """
211 163 if self.template is not None:
212 164 return
213 165 # called too early, do nothing
214 166 if self.environment is None:
215 167 return
216 168 # Try different template names during conversion. First try to load the
217 169 # template by name with extension added, then try loading the template
218 170 # as if the name is explicitly specified, then try the name as a
219 171 # 'flavor', and lastly just try to load the template by module name.
220 172 module_name = self.__module__.rsplit('.', 1)[-1]
221 173 try_names = []
222 174 if self.template_file:
223 175 try_names.extend([
224 176 self.template_file + self.template_extension,
225 177 self.template_file,
226 178 module_name + '_' + self.template_file + self.template_extension,
227 179 ])
228 180 try_names.append(module_name + self.template_extension)
229 181 for try_name in try_names:
230 182 self.log.debug("Attempting to load template %s", try_name)
231 183 try:
232 184 self.template = self.environment.get_template(try_name)
233 185 except (TemplateNotFound, IOError):
234 186 pass
235 187 except Exception as e:
236 188 self.log.warn("Unexpected exception loading template: %s", try_name, exc_info=True)
237 189 else:
238 190 self.log.info("Loaded template %s", try_name)
239 191 break
240 192
241 193 def from_notebook_node(self, nb, resources=None, **kw):
242 194 """
243 195 Convert a notebook from a notebook node instance.
244 196
245 197 Parameters
246 198 ----------
247 199 nb : Notebook node
248 200 resources : dict (**kw)
249 201 of additional resources that can be accessed read/write by
250 202 preprocessors and filters.
251 203 """
252 nb_copy = copy.deepcopy(nb)
253 resources = self._init_resources(resources)
254
255 # Preprocess
256 nb_copy, resources = self._preprocess(nb_copy, resources)
204 nb_copy, resources = super(TemplateExporter, self).from_notebook_node(nb, resources, **kw)
257 205
258 206 self._load_template()
259 207
260 208 if self.template is not None:
261 209 output = self.template.render(nb=nb_copy, resources=resources)
262 210 else:
263 211 raise IOError('template file "%s" could not be found' % self.template_file)
264 212 return output, resources
265 213
266 214
267 def from_filename(self, filename, resources=None, **kw):
268 """
269 Convert a notebook from a notebook file.
270
271 Parameters
272 ----------
273 filename : str
274 Full filename of the notebook file to open and convert.
275 """
276
277 #Pull the metadata from the filesystem.
278 if resources is None:
279 resources = ResourcesDict()
280 if not 'metadata' in resources or resources['metadata'] == '':
281 resources['metadata'] = ResourcesDict()
282 basename = os.path.basename(filename)
283 notebook_name = basename[:basename.rfind('.')]
284 resources['metadata']['name'] = notebook_name
285
286 modified_date = datetime.datetime.fromtimestamp(os.path.getmtime(filename))
287 resources['metadata']['modified_date'] = modified_date.strftime(text.date_format)
288
289 with io.open(filename) as f:
290 return self.from_notebook_node(nbformat.read(f, 'json'), resources=resources,**kw)
291
292
293 def from_file(self, file_stream, resources=None, **kw):
294 """
295 Convert a notebook from a notebook file.
296
297 Parameters
298 ----------
299 file_stream : file-like object
300 Notebook file-like object to convert.
301 """
302 return self.from_notebook_node(nbformat.read(file_stream, 'json'), resources=resources, **kw)
303
304
305 def register_preprocessor(self, preprocessor, enabled=False):
306 """
307 Register a preprocessor.
308 Preprocessors are classes that act upon the notebook before it is
309 passed into the Jinja templating engine. Preprocessors are also
310 capable of passing additional information to the Jinja
311 templating engine.
312
313 Parameters
314 ----------
315 preprocessor : preprocessor
316 """
317 if preprocessor is None:
318 raise TypeError('preprocessor')
319 isclass = isinstance(preprocessor, type)
320 constructed = not isclass
321
322 #Handle preprocessor's registration based on it's type
323 if constructed and isinstance(preprocessor, py3compat.string_types):
324 #Preprocessor is a string, import the namespace and recursively call
325 #this register_preprocessor method
326 preprocessor_cls = import_item(preprocessor)
327 return self.register_preprocessor(preprocessor_cls, enabled)
328
329 if constructed and hasattr(preprocessor, '__call__'):
330 #Preprocessor is a function, no need to construct it.
331 #Register and return the preprocessor.
332 if enabled:
333 preprocessor.enabled = True
334 self._preprocessors.append(preprocessor)
335 return preprocessor
336
337 elif isclass and isinstance(preprocessor, MetaHasTraits):
338 #Preprocessor is configurable. Make sure to pass in new default for
339 #the enabled flag if one was specified.
340 self.register_preprocessor(preprocessor(parent=self), enabled)
341
342 elif isclass:
343 #Preprocessor is not configurable, construct it
344 self.register_preprocessor(preprocessor(), enabled)
345
346 else:
347 #Preprocessor is an instance of something without a __call__
348 #attribute.
349 raise TypeError('preprocessor')
350
351
352 215 def register_filter(self, name, jinja_filter):
353 216 """
354 217 Register a filter.
355 218 A filter is a function that accepts and acts on one string.
356 219 The filters are accesible within the Jinja templating engine.
357 220
358 221 Parameters
359 222 ----------
360 223 name : str
361 224 name to give the filter in the Jinja engine
362 225 filter : filter
363 226 """
364 227 if jinja_filter is None:
365 228 raise TypeError('filter')
366 229 isclass = isinstance(jinja_filter, type)
367 230 constructed = not isclass
368 231
369 232 #Handle filter's registration based on it's type
370 233 if constructed and isinstance(jinja_filter, py3compat.string_types):
371 234 #filter is a string, import the namespace and recursively call
372 235 #this register_filter method
373 236 filter_cls = import_item(jinja_filter)
374 237 return self.register_filter(name, filter_cls)
375 238
376 239 if constructed and hasattr(jinja_filter, '__call__'):
377 240 #filter is a function, no need to construct it.
378 241 self.environment.filters[name] = jinja_filter
379 242 return jinja_filter
380 243
381 244 elif isclass and isinstance(jinja_filter, MetaHasTraits):
382 245 #filter is configurable. Make sure to pass in new default for
383 246 #the enabled flag if one was specified.
384 247 filter_instance = jinja_filter(parent=self)
385 248 self.register_filter(name, filter_instance )
386 249
387 250 elif isclass:
388 251 #filter is not configurable, construct it
389 252 filter_instance = jinja_filter()
390 253 self.register_filter(name, filter_instance)
391 254
392 255 else:
393 256 #filter is an instance of something without a __call__
394 257 #attribute.
395 258 raise TypeError('filter')
396 259
397 260
398 261 def _init_template(self):
399 262 """
400 263 Make sure a template name is specified. If one isn't specified, try to
401 264 build one from the information we know.
402 265 """
403 266 self._template_file_changed('template_file', self.template_file, self.template_file)
404 267
405 268
406 269 def _init_environment(self, extra_loaders=None):
407 270 """
408 271 Create the Jinja templating environment.
409 272 """
410 273 here = os.path.dirname(os.path.realpath(__file__))
411 274 loaders = []
412 275 if extra_loaders:
413 276 loaders.extend(extra_loaders)
414 277
415 278 paths = self.template_path
416 279 paths.extend([os.path.join(here, self.default_template_path),
417 280 os.path.join(here, self.template_skeleton_path)])
418 281 loaders.append(FileSystemLoader(paths))
419 282
420 283 self.environment = Environment(
421 284 loader= ChoiceLoader(loaders),
422 285 extensions=JINJA_EXTENSIONS
423 286 )
424 287
425 288 #Set special Jinja2 syntax that will not conflict with latex.
426 289 if self.jinja_logic_block_start:
427 290 self.environment.block_start_string = self.jinja_logic_block_start
428 291 if self.jinja_logic_block_end:
429 292 self.environment.block_end_string = self.jinja_logic_block_end
430 293 if self.jinja_variable_block_start:
431 294 self.environment.variable_start_string = self.jinja_variable_block_start
432 295 if self.jinja_variable_block_end:
433 296 self.environment.variable_end_string = self.jinja_variable_block_end
434 297 if self.jinja_comment_block_start:
435 298 self.environment.comment_start_string = self.jinja_comment_block_start
436 299 if self.jinja_comment_block_end:
437 300 self.environment.comment_end_string = self.jinja_comment_block_end
438 301
439 302
440 def _init_preprocessors(self):
441 """
442 Register all of the preprocessors needed for this exporter, disabled
443 unless specified explicitly.
444 """
445 self._preprocessors = []
446
447 #Load default preprocessors (not necessarly enabled by default).
448 if self.default_preprocessors:
449 for preprocessor in self.default_preprocessors:
450 self.register_preprocessor(preprocessor)
451
452 #Load user preprocessors. Enable by default.
453 if self.preprocessors:
454 for preprocessor in self.preprocessors:
455 self.register_preprocessor(preprocessor, enabled=True)
456
457
458 303 def _init_filters(self):
459 304 """
460 305 Register all of the filters required for the exporter.
461 306 """
462 307
463 308 #Add default filters to the Jinja2 environment
464 309 for key, value in default_filters.items():
465 310 self.register_filter(key, value)
466 311
467 312 #Load user filters. Overwrite existing filters if need be.
468 313 if self.filters:
469 314 for key, user_filter in self.filters.items():
470 315 self.register_filter(key, user_filter)
471
472
473 def _init_resources(self, resources):
474
475 #Make sure the resources dict is of ResourcesDict type.
476 if resources is None:
477 resources = ResourcesDict()
478 if not isinstance(resources, ResourcesDict):
479 new_resources = ResourcesDict()
480 new_resources.update(resources)
481 resources = new_resources
482
483 #Make sure the metadata extension exists in resources
484 if 'metadata' in resources:
485 if not isinstance(resources['metadata'], ResourcesDict):
486 resources['metadata'] = ResourcesDict(resources['metadata'])
487 else:
488 resources['metadata'] = ResourcesDict()
489 if not resources['metadata']['name']:
490 resources['metadata']['name'] = 'Notebook'
491
492 #Set the output extension
493 resources['output_extension'] = self.file_extension
494 return resources
495
496
497 def _preprocess(self, nb, resources):
498 """
499 Preprocess the notebook before passing it into the Jinja engine.
500 To preprocess the notebook is to apply all of the
501
502 Parameters
503 ----------
504 nb : notebook node
505 notebook that is being exported.
506 resources : a dict of additional resources that
507 can be accessed read/write by preprocessors
508 and filters.
509 """
510
511 # Do a copy.deepcopy first,
512 # we are never safe enough with what the preprocessors could do.
513 nbc = copy.deepcopy(nb)
514 resc = copy.deepcopy(resources)
515
516 #Run each preprocessor on the notebook. Carry the output along
517 #to each preprocessor
518 for preprocessor in self._preprocessors:
519 nbc, resc = preprocessor(nbc, resc)
520 return nbc, resc
@@ -1,108 +1,108
1 1 """
2 2 Module with tests for exporter.py
3 3 """
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 from IPython.config import Config
18 18
19 19 from .base import ExportersTestsBase
20 20 from .cheese import CheesePreprocessor
21 from ..exporter import Exporter
21 from ..templateexporter import TemplateExporter
22 22
23 23
24 24 #-----------------------------------------------------------------------------
25 25 # Class
26 26 #-----------------------------------------------------------------------------
27 27
28 28 class TestExporter(ExportersTestsBase):
29 29 """Contains test functions for exporter.py"""
30 30
31 31
32 32 def test_constructor(self):
33 33 """
34 Can an Exporter be constructed?
34 Can an TemplateExporter be constructed?
35 35 """
36 Exporter()
36 TemplateExporter()
37 37
38 38
39 39 def test_export(self):
40 40 """
41 41 Can an Exporter export something?
42 42 """
43 43 exporter = self._make_exporter()
44 44 (output, resources) = exporter.from_filename(self._get_notebook())
45 45 assert len(output) > 0
46 46
47 47
48 48 def test_extract_outputs(self):
49 49 """
50 50 If the ExtractOutputPreprocessor is enabled, are outputs extracted?
51 51 """
52 52 config = Config({'ExtractOutputPreprocessor': {'enabled': True}})
53 53 exporter = self._make_exporter(config=config)
54 54 (output, resources) = exporter.from_filename(self._get_notebook())
55 55 assert resources is not None
56 56 assert isinstance(resources['outputs'], dict)
57 57 assert len(resources['outputs']) > 0
58 58
59 59
60 60 def test_preprocessor_class(self):
61 61 """
62 62 Can a preprocessor be added to the preprocessors list by class type?
63 63 """
64 64 config = Config({'Exporter': {'preprocessors': [CheesePreprocessor]}})
65 65 exporter = self._make_exporter(config=config)
66 66 (output, resources) = exporter.from_filename(self._get_notebook())
67 67 assert resources is not None
68 68 assert resources['cheese'] == 'real'
69 69
70 70
71 71 def test_preprocessor_instance(self):
72 72 """
73 73 Can a preprocessor be added to the preprocessors list by instance?
74 74 """
75 75 config = Config({'Exporter': {'preprocessors': [CheesePreprocessor()]}})
76 76 exporter = self._make_exporter(config=config)
77 77 (output, resources) = exporter.from_filename(self._get_notebook())
78 78 assert resources is not None
79 79 assert resources['cheese'] == 'real'
80 80
81 81
82 82 def test_preprocessor_dottedobjectname(self):
83 83 """
84 84 Can a preprocessor be added to the preprocessors list by dotted object name?
85 85 """
86 86 config = Config({'Exporter': {'preprocessors': ['IPython.nbconvert.exporters.tests.cheese.CheesePreprocessor']}})
87 87 exporter = self._make_exporter(config=config)
88 88 (output, resources) = exporter.from_filename(self._get_notebook())
89 89 assert resources is not None
90 90 assert resources['cheese'] == 'real'
91 91
92 92
93 93 def test_preprocessor_via_method(self):
94 94 """
95 95 Can a preprocessor be added via the Exporter convenience method?
96 96 """
97 97 exporter = self._make_exporter()
98 98 exporter.register_preprocessor(CheesePreprocessor, enabled=True)
99 99 (output, resources) = exporter.from_filename(self._get_notebook())
100 100 assert resources is not None
101 101 assert resources['cheese'] == 'real'
102 102
103 103
104 104 def _make_exporter(self, config=None):
105 105 #Create the exporter instance, make sure to set a template name since
106 106 #the base Exporter doesn't have a template associated with it.
107 exporter = Exporter(config=config, template_file='python')
107 exporter = TemplateExporter(config=config, template_file='python')
108 108 return exporter
@@ -1,7 +1,7
1 1 from .ansi import *
2 from .citation import *
2 3 from .datatypefilter import *
3 4 from .highlight import *
4 5 from .latex import *
5 6 from .markdown import *
6 7 from .strings import *
7 from .citation import * No newline at end of file
@@ -1,53 +1,53
1 1 """
2 2 Module with utility functions for preprocessor tests
3 3 """
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 from IPython.nbformat import current as nbformat
18 18
19 19 from ...tests.base import TestsBase
20 from ...exporters.baseexporter import ResourcesDict
20 from ...exporters.exporter import ResourcesDict
21 21
22 22 #-----------------------------------------------------------------------------
23 23 # Class
24 24 #-----------------------------------------------------------------------------
25 25
26 26 class PreprocessorTestsBase(TestsBase):
27 27 """Contains test functions preprocessor tests"""
28 28
29 29
30 30 def build_notebook(self):
31 31 """Build a notebook in memory for use with preprocessor tests"""
32 32
33 33 outputs = [nbformat.new_output(output_type="stream", stream="stdout", output_text="a"),
34 34 nbformat.new_output(output_type="text", output_text="b"),
35 35 nbformat.new_output(output_type="stream", stream="stdout", output_text="c"),
36 36 nbformat.new_output(output_type="stream", stream="stdout", output_text="d"),
37 37 nbformat.new_output(output_type="stream", stream="stderr", output_text="e"),
38 38 nbformat.new_output(output_type="stream", stream="stderr", output_text="f"),
39 39 nbformat.new_output(output_type="png", output_png='Zw==')] #g
40 40
41 41 cells=[nbformat.new_code_cell(input="$ e $", prompt_number=1,outputs=outputs),
42 42 nbformat.new_text_cell('markdown', source="$ e $")]
43 43 worksheets = [nbformat.new_worksheet(name="worksheet1", cells=cells)]
44 44
45 45 return nbformat.new_notebook(name="notebook1", worksheets=worksheets)
46 46
47 47
48 48 def build_resources(self):
49 49 """Build an empty resources dictionary."""
50 50
51 51 res = ResourcesDict()
52 52 res['metadata'] = ResourcesDict()
53 53 return res
General Comments 0
You need to be logged in to leave comments. Login now