##// END OF EJS Templates
Changes after in person review with @ellisonbg including TODO tags
Jonathan Frederic -
Show More
@@ -1,220 +1,220
1 """
1 """
2 Module containing single call export functions.
2 Module containing single call export functions.
3 """
3 """
4 #-----------------------------------------------------------------------------
4 #-----------------------------------------------------------------------------
5 # Copyright (c) 2013, the IPython Development Team.
5 # Copyright (c) 2013, the IPython Development Team.
6 #
6 #
7 # Distributed under the terms of the Modified BSD License.
7 # Distributed under the terms of the Modified BSD License.
8 #
8 #
9 # The full license is in the file COPYING.txt, distributed with this software.
9 # The full license is in the file COPYING.txt, distributed with this software.
10 #-----------------------------------------------------------------------------
10 #-----------------------------------------------------------------------------
11
11
12 #-----------------------------------------------------------------------------
12 #-----------------------------------------------------------------------------
13 # Imports
13 # Imports
14 #-----------------------------------------------------------------------------
14 #-----------------------------------------------------------------------------
15
15
16 from functools import wraps
16 from functools import wraps
17
17
18 from IPython.nbformat.v3.nbbase import NotebookNode
18 from IPython.nbformat.v3.nbbase import NotebookNode
19 from IPython.config import Config
19 from IPython.config import Config
20
20
21 from .exporter import Exporter
21 from .exporter import Exporter
22 from .basichtml import BasicHTMLExporter
22 from .basichtml import BasicHTMLExporter
23 from .fullhtml import FullHTMLExporter
23 from .fullhtml import FullHTMLExporter
24 from .latex import LatexExporter
24 from .latex import LatexExporter
25 from .markdown import MarkdownExporter
25 from .markdown import MarkdownExporter
26 from .python import PythonExporter
26 from .python import PythonExporter
27 from .reveal import RevealExporter
27 from .reveal import RevealExporter
28 from .rst import RstExporter
28 from .rst import RstExporter
29 from .sphinx_howto import SphinxHowtoExporter
29 from .sphinx_howto import SphinxHowtoExporter
30 from .sphinx_manual import SphinxManualExporter
30 from .sphinx_manual import SphinxManualExporter
31
31
32 #-----------------------------------------------------------------------------
32 #-----------------------------------------------------------------------------
33 # Classes
33 # Classes
34 #-----------------------------------------------------------------------------
34 #-----------------------------------------------------------------------------
35
35
36 def DocDecorator(f):
36 def DocDecorator(f):
37
37
38 #Set docstring of function
38 #Set docstring of function
39 f.__doc__ = f.__doc__ + """
39 f.__doc__ = f.__doc__ + """
40 nb : Notebook node
40 nb : Notebook node
41 config : config (optional, keyword arg)
41 config : config (optional, keyword arg)
42 User configuration instance.
42 User configuration instance.
43 resources : dict (optional, keyword arg)
43 resources : dict (optional, keyword arg)
44 Resources used in the conversion process.
44 Resources used in the conversion process.
45
45
46 Returns
46 Returns
47 ----------
47 ----------
48 tuple- output, resources, exporter_instance
48 tuple- output, resources, exporter_instance
49 output : str
49 output : str
50 Jinja 2 output. This is the resulting converted notebook.
50 Jinja 2 output. This is the resulting converted notebook.
51 resources : dictionary
51 resources : dictionary
52 Dictionary of resources used prior to and during the conversion
52 Dictionary of resources used prior to and during the conversion
53 process.
53 process.
54 exporter_instance : Exporter
54 exporter_instance : Exporter
55 Instance of the Exporter class used to export the document. Useful
55 Instance of the Exporter class used to export the document. Useful
56 to caller because it provides a 'file_extension' property which
56 to caller because it provides a 'file_extension' property which
57 specifies what extension the output should be saved as."""
57 specifies what extension the output should be saved as."""
58
58
59 @wraps(f)
59 @wraps(f)
60 def decorator(*args, **kwargs):
60 def decorator(*args, **kwargs):
61 return f(*args, **kwargs)
61 return f(*args, **kwargs)
62
62
63 return decorator
63 return decorator
64
64
65
65
66 #-----------------------------------------------------------------------------
66 #-----------------------------------------------------------------------------
67 # Functions
67 # Functions
68 #-----------------------------------------------------------------------------
68 #-----------------------------------------------------------------------------
69
69
70 __all__ = [
70 __all__ = [
71 'export',
71 'export',
72 'export_sphinx_manual',
72 'export_sphinx_manual',
73 'export_sphinx_howto',
73 'export_sphinx_howto',
74 'export_basic_html',
74 'export_basic_html',
75 'export_full_html',
75 'export_full_html',
76 'export_latex',
76 'export_latex',
77 'export_markdown',
77 'export_markdown',
78 'export_python',
78 'export_python',
79 'export_reveal',
79 'export_reveal',
80 'export_rst',
80 'export_rst',
81 'export_by_name',
81 'export_by_name',
82 'get_export_names'
82 'get_export_names'
83 ]
83 ]
84
84
85 class ExporterNameError(NameError):
85 class ExporterNameError(NameError):
86 pass
86 pass
87
87
88 @DocDecorator
88 @DocDecorator
89 def export(exporter_type, nb, **kw):
89 def export(exporter_type, nb, **kw):
90 """
90 """
91 Export a notebook object using specific exporter class.
91 Export a notebook object using specific exporter class.
92
92
93 exporter_type : Exporter class type
93 exporter_type : Exporter class type
94 Class type of the exporter that should be used. This method
94 Class type of the exporter that should be used. This method
95 will initialize it's own instance of the class. It is
95 will initialize it's own instance of the class. It is
96 ASSUMED that the class type provided exposes a
96 ASSUMED that the class type provided exposes a
97 constructor (__init__) with the same signature as the
97 constructor (__init__) with the same signature as the
98 base Exporter class.}
98 base Exporter class.}
99 """
99 """
100
100
101 #Check arguments
101 #Check arguments
102 if exporter_type is None:
102 if exporter_type is None:
103 raise TypeError("Exporter is None")
103 raise TypeError("Exporter is None")
104 elif not issubclass(exporter_type, Exporter):
104 elif not issubclass(exporter_type, Exporter):
105 raise TypeError("Exporter type does not inherit from Exporter (base)")
105 raise TypeError("Exporter type does not inherit from Exporter (base)")
106 if nb is None:
106 if nb is None:
107 raise TypeError("nb is None")
107 raise TypeError("nb is None")
108
108
109 #Create the exporter
109 #Create the exporter
110 exporter_instance = exporter_type(config=kw.get('config', Config()))
110 resources = kw.pop('resources', None)
111 exporter_instance = exporter_type(**kw)
111
112
112 #Try to convert the notebook using the appropriate conversion function.
113 #Try to convert the notebook using the appropriate conversion function.
113 resources = kw.get('resources', {})
114 if isinstance(nb, NotebookNode):
114 if isinstance(nb, NotebookNode):
115 output, resources = exporter_instance.from_notebook_node(nb, resources)
115 output, resources = exporter_instance.from_notebook_node(nb, resources)
116 elif isinstance(nb, basestring):
116 elif isinstance(nb, basestring):
117 output, resources = exporter_instance.from_filename(nb, resources)
117 output, resources = exporter_instance.from_filename(nb, resources)
118 else:
118 else:
119 output, resources = exporter_instance.from_file(nb, resources)
119 output, resources = exporter_instance.from_file(nb, resources)
120 return output, resources
120 return output, resources
121
121
122
122
123 @DocDecorator
123 @DocDecorator
124 def export_sphinx_manual(nb, **kw):
124 def export_sphinx_manual(nb, **kw):
125 """
125 """
126 Export a notebook object to Sphinx Manual LaTeX
126 Export a notebook object to Sphinx Manual LaTeX
127 """
127 """
128 return export(SphinxManualExporter, nb, **kw)
128 return export(SphinxManualExporter, nb, **kw)
129
129
130
130
131 @DocDecorator
131 @DocDecorator
132 def export_sphinx_howto(nb, **kw):
132 def export_sphinx_howto(nb, **kw):
133 """
133 """
134 Export a notebook object to Sphinx HowTo LaTeX
134 Export a notebook object to Sphinx HowTo LaTeX
135 """
135 """
136 return export(SphinxHowtoExporter, nb, **kw)
136 return export(SphinxHowtoExporter, nb, **kw)
137
137
138
138
139 @DocDecorator
139 @DocDecorator
140 def export_basic_html(nb, **kw):
140 def export_basic_html(nb, **kw):
141 """
141 """
142 Export a notebook object to Basic HTML
142 Export a notebook object to Basic HTML
143 """
143 """
144 return export(BasicHTMLExporter, nb, **kw)
144 return export(BasicHTMLExporter, nb, **kw)
145
145
146
146
147 @DocDecorator
147 @DocDecorator
148 def export_full_html(nb, **kw):
148 def export_full_html(nb, **kw):
149 """
149 """
150 Export a notebook object to Full HTML
150 Export a notebook object to Full HTML
151 """
151 """
152 return export(FullHTMLExporter, nb, **kw)
152 return export(FullHTMLExporter, nb, **kw)
153
153
154
154
155 @DocDecorator
155 @DocDecorator
156 def export_latex(nb, **kw):
156 def export_latex(nb, **kw):
157 """
157 """
158 Export a notebook object to LaTeX
158 Export a notebook object to LaTeX
159 """
159 """
160 return export(LatexExporter, nb, **kw)
160 return export(LatexExporter, nb, **kw)
161
161
162
162
163 @DocDecorator
163 @DocDecorator
164 def export_markdown(nb, **kw):
164 def export_markdown(nb, **kw):
165 """
165 """
166 Export a notebook object to Markdown
166 Export a notebook object to Markdown
167 """
167 """
168 return export(MarkdownExporter, nb, **kw)
168 return export(MarkdownExporter, nb, **kw)
169
169
170
170
171 @DocDecorator
171 @DocDecorator
172 def export_python(nb, **kw):
172 def export_python(nb, **kw):
173 """
173 """
174 Export a notebook object to Python
174 Export a notebook object to Python
175 """
175 """
176 return export(PythonExporter, nb, **kw)
176 return export(PythonExporter, nb, **kw)
177
177
178
178
179 @DocDecorator
179 @DocDecorator
180 def export_reveal(nb, **kw):
180 def export_reveal(nb, **kw):
181 """
181 """
182 Export a notebook object to Reveal
182 Export a notebook object to Reveal
183 """
183 """
184 return export(RevealExporter, nb, **kw)
184 return export(RevealExporter, nb, **kw)
185
185
186
186
187 @DocDecorator
187 @DocDecorator
188 def export_rst(nb, **kw):
188 def export_rst(nb, **kw):
189 """
189 """
190 Export a notebook object to RST
190 Export a notebook object to RST
191 """
191 """
192 return export(RstExporter, nb, **kw)
192 return export(RstExporter, nb, **kw)
193
193
194
194
195 @DocDecorator
195 @DocDecorator
196 def export_by_name(format_name, nb, **kw):
196 def export_by_name(format_name, nb, **kw):
197 """
197 """
198 Export a notebook object to a template type by its name. Reflection
198 Export a notebook object to a template type by its name. Reflection
199 (Inspect) is used to find the template's corresponding explicit export
199 (Inspect) is used to find the template's corresponding explicit export
200 method defined in this module. That method is then called directly.
200 method defined in this module. That method is then called directly.
201
201
202 format_name : str
202 format_name : str
203 Name of the template style to export to.
203 Name of the template style to export to.
204 """
204 """
205
205
206 function_name = "export_" + format_name.lower()
206 function_name = "export_" + format_name.lower()
207
207
208 if function_name in globals():
208 if function_name in globals():
209 return globals()[function_name](nb, **kw)
209 return globals()[function_name](nb, **kw)
210 else:
210 else:
211 raise ExporterNameError("template for `%s` not found" % function_name)
211 raise ExporterNameError("template for `%s` not found" % function_name)
212
212
213 def get_export_names():
213 def get_export_names():
214 "Return a list of the currently supported export targets"
214 "Return a list of the currently supported export targets"
215 # grab everything after 'export_'
215 # grab everything after 'export_'
216 l = [x[len('export_'):] for x in __all__ if x.startswith('export_')]
216 l = [x[len('export_'):] for x in __all__ if x.startswith('export_')]
217
217
218 # filter out the one method that is not a template
218 # filter out the one method that is not a template
219 l = [x for x in l if 'by_name' not in x]
219 l = [x for x in l if 'by_name' not in x]
220 return sorted(l)
220 return sorted(l)
@@ -1,361 +1,360
1 """This module defines Exporter, a highly configurable converter
1 """This module defines Exporter, a highly configurable converter
2 that uses Jinja2 to export notebook files into different formats.
2 that uses Jinja2 to export notebook files into different formats.
3 """
3 """
4
4
5 #-----------------------------------------------------------------------------
5 #-----------------------------------------------------------------------------
6 # Copyright (c) 2013, the IPython Development Team.
6 # Copyright (c) 2013, the IPython Development Team.
7 #
7 #
8 # Distributed under the terms of the Modified BSD License.
8 # Distributed under the terms of the Modified BSD License.
9 #
9 #
10 # The full license is in the file COPYING.txt, distributed with this software.
10 # The full license is in the file COPYING.txt, distributed with this software.
11 #-----------------------------------------------------------------------------
11 #-----------------------------------------------------------------------------
12
12
13 #-----------------------------------------------------------------------------
13 #-----------------------------------------------------------------------------
14 # Imports
14 # Imports
15 #-----------------------------------------------------------------------------
15 #-----------------------------------------------------------------------------
16
16
17 from __future__ import print_function, absolute_import
17 from __future__ import print_function, absolute_import
18
18
19 # Stdlib imports
19 # Stdlib imports
20 import io
20 import io
21 import os
21 import os
22 import inspect
22 import inspect
23 import types
23 import types
24 from copy import deepcopy
24 from copy import deepcopy
25
25
26 # other libs/dependencies
26 # other libs/dependencies
27 from jinja2 import Environment, FileSystemLoader, ChoiceLoader
27 from jinja2 import Environment, FileSystemLoader, ChoiceLoader
28
28
29 # IPython imports
29 # IPython imports
30 from IPython.config.configurable import Configurable
30 from IPython.config.configurable import Configurable
31 from IPython.config import Config
31 from IPython.config import Config
32 from IPython.nbformat import current as nbformat
32 from IPython.nbformat import current as nbformat
33 from IPython.utils.traitlets import MetaHasTraits, DottedObjectName, Unicode, List, Dict
33 from IPython.utils.traitlets import MetaHasTraits, DottedObjectName, Unicode, List, Dict
34 from IPython.utils.importstring import import_item
34 from IPython.utils.importstring import import_item
35 from IPython.utils.text import indent
35 from IPython.utils.text import indent
36
36
37 from IPython.nbconvert import filters
37 from IPython.nbconvert import filters
38 from IPython.nbconvert import transformers
38 from IPython.nbconvert import transformers
39
39
40 #-----------------------------------------------------------------------------
40 #-----------------------------------------------------------------------------
41 # Globals and constants
41 # Globals and constants
42 #-----------------------------------------------------------------------------
42 #-----------------------------------------------------------------------------
43
43
44 #Jinja2 extensions to load.
44 #Jinja2 extensions to load.
45 JINJA_EXTENSIONS = ['jinja2.ext.loopcontrols']
45 JINJA_EXTENSIONS = ['jinja2.ext.loopcontrols']
46
46
47 default_filters = {
47 default_filters = {
48 'indent': indent,
48 'indent': indent,
49 'markdown': filters.markdown2html,
49 'markdown': filters.markdown2html,
50 'ansi2html': filters.ansi2html,
50 'ansi2html': filters.ansi2html,
51 'filter_data_type': filters.DataTypeFilter,
51 'filter_data_type': filters.DataTypeFilter,
52 'get_lines': filters.get_lines,
52 'get_lines': filters.get_lines,
53 'highlight': filters.highlight,
53 'highlight': filters.highlight,
54 'highlight2html': filters.highlight,
54 'highlight2html': filters.highlight,
55 'highlight2latex': filters.highlight2latex,
55 'highlight2latex': filters.highlight2latex,
56 'markdown2latex': filters.markdown2latex,
56 'markdown2latex': filters.markdown2latex,
57 'markdown2rst': filters.markdown2rst,
57 'markdown2rst': filters.markdown2rst,
58 'pycomment': filters.python_comment,
58 'pycomment': filters.python_comment,
59 'rm_ansi': filters.remove_ansi,
59 'rm_ansi': filters.remove_ansi,
60 'rm_dollars': filters.strip_dollars,
60 'rm_dollars': filters.strip_dollars,
61 'rm_fake': filters.rm_fake,
61 'rm_fake': filters.rm_fake,
62 'ansi2latex': filters.ansi2latex,
62 'ansi2latex': filters.ansi2latex,
63 'rm_math_space': filters.rm_math_space,
63 'rm_math_space': filters.rm_math_space,
64 'wrap': filters.wrap
64 'wrap': filters.wrap
65 }
65 }
66
66
67 #-----------------------------------------------------------------------------
67 #-----------------------------------------------------------------------------
68 # Class
68 # Class
69 #-----------------------------------------------------------------------------
69 #-----------------------------------------------------------------------------
70
70
71 class Exporter(Configurable):
71 class Exporter(Configurable):
72 """
72 """
73 Exports notebooks into other file formats. Uses Jinja 2 templating engine
73 Exports notebooks into other file formats. Uses Jinja 2 templating engine
74 to output new formats. Inherit from this class if you are creating a new
74 to output new formats. Inherit from this class if you are creating a new
75 template type along with new filters/transformers. If the filters/
75 template type along with new filters/transformers. If the filters/
76 transformers provided by default suffice, there is no need to inherit from
76 transformers provided by default suffice, there is no need to inherit from
77 this class. Instead, override the template_file and file_extension
77 this class. Instead, override the template_file and file_extension
78 traits via a config file.
78 traits via a config file.
79
79
80 {filters}
80 {filters}
81 """
81 """
82
82
83 # finish the docstring
83 # finish the docstring
84 __doc__ = __doc__.format(filters = '- '+'\n - '.join(default_filters.keys()))
84 __doc__ = __doc__.format(filters = '- '+'\n - '.join(default_filters.keys()))
85
85
86
86
87 template_file = Unicode(
87 template_file = Unicode(
88 '', config=True,
88 '', config=True,
89 help="Name of the template file to use")
89 help="Name of the template file to use")
90
90
91 file_extension = Unicode(
91 file_extension = Unicode(
92 'txt', config=True,
92 'txt', config=True,
93 help="Extension of the file that should be written to disk"
93 help="Extension of the file that should be written to disk"
94 )
94 )
95
95
96 template_path = Unicode(
96 template_path = Unicode(
97 os.path.join("..", "templates"), config=True,
97 os.path.join("..", "templates"), config=True,
98 help="Path where the template files are located.")
98 help="Path where the template files are located.")
99
99
100 template_skeleton_path = Unicode(
100 template_skeleton_path = Unicode(
101 os.path.join("..", "templates", "skeleton"), config=True,
101 os.path.join("..", "templates", "skeleton"), config=True,
102 help="Path where the template skeleton files are located.")
102 help="Path where the template skeleton files are located.")
103
103
104 #Jinja block definitions
104 #Jinja block definitions
105 jinja_comment_block_start = Unicode("", config=True)
105 jinja_comment_block_start = Unicode("", config=True)
106 jinja_comment_block_end = Unicode("", config=True)
106 jinja_comment_block_end = Unicode("", config=True)
107 jinja_variable_block_start = Unicode("", config=True)
107 jinja_variable_block_start = Unicode("", config=True)
108 jinja_variable_block_end = Unicode("", config=True)
108 jinja_variable_block_end = Unicode("", config=True)
109 jinja_logic_block_start = Unicode("", config=True)
109 jinja_logic_block_start = Unicode("", config=True)
110 jinja_logic_block_end = Unicode("", config=True)
110 jinja_logic_block_end = Unicode("", config=True)
111
111
112 #Extension that the template files use.
112 #Extension that the template files use.
113 template_extension = Unicode(".tpl", config=True)
113 template_extension = Unicode(".tpl", config=True)
114
114
115 #Configurability, allows the user to easily add filters and transformers.
115 #Configurability, allows the user to easily add filters and transformers.
116 transformers = List(config=True,
116 transformers = List(config=True,
117 help="""List of transformers, by name or namespace, to enable.""")
117 help="""List of transformers, by name or namespace, to enable.""")
118 filters = Dict(config=True,
118 filters = Dict(config=True,
119 help="""Dictionary of filters, by name and namespace, to add to the Jinja
119 help="""Dictionary of filters, by name and namespace, to add to the Jinja
120 environment.""")
120 environment.""")
121
121
122 def __init__(self, config=None, extra_loaders=None, **kw):
122 def __init__(self, config=None, extra_loaders=None, **kw):
123 """
123 """
124 Public constructor
124 Public constructor
125
125
126 Parameters
126 Parameters
127 ----------
127 ----------
128 config : config
128 config : config
129 User configuration instance.
129 User configuration instance.
130 extra_loaders : list[of Jinja Loaders]
130 extra_loaders : list[of Jinja Loaders]
131 ordered list of Jinja loder to find templates. Will be tried in order
131 ordered list of Jinja loder to find templates. Will be tried in order
132 before the default FileSysteme ones.
132 before the default FileSysteme ones.
133 """
133 """
134
134
135 #Call the base class constructor
135 #Call the base class constructor
136 c = self.default_config
136 c = self.default_config
137 if config:
137 if config:
138 c.merge(config)
138 c.merge(config)
139
139
140 super(Exporter, self).__init__(config=c, **kw)
140 super(Exporter, self).__init__(config=c, **kw)
141
141
142 #Standard environment
142 #Standard environment
143 self._init_environment(extra_loaders=extra_loaders)
143 self._init_environment(extra_loaders=extra_loaders)
144
144
145 #Add transformers
145 #Add transformers
146 self._transformers = []
146 self._transformers = []
147 self._register_transformers()
147 self._register_transformers()
148
148
149 #Add filters to the Jinja2 environment
149 #Add filters to the Jinja2 environment
150 self._register_filters()
150 self._register_filters()
151
151
152 #Load user transformers. Enabled by default.
152 #Load user transformers. Enabled by default.
153 if self.transformers:
153 if self.transformers:
154 for transformer in self.transformers:
154 for transformer in self.transformers:
155 self.register_transformer(transformer, True)
155 self.register_transformer(transformer, enabled=True)
156
156
157 #Load user filters. Overwrite existing filters if need be.
157 #Load user filters. Overwrite existing filters if need be.
158 if self.filters:
158 if self.filters:
159 for key, user_filter in self.filters.iteritems():
159 for key, user_filter in self.filters.iteritems():
160 self.register_filter(key, user_filter)
160 self.register_filter(key, user_filter)
161
161
162
162
163 @property
163 @property
164 def default_config(self):
164 def default_config(self):
165 return Config()
165 return Config()
166
166
167
167
168 def from_notebook_node(self, nb, resources=None, **kw):
168 def from_notebook_node(self, nb, resources=None, **kw):
169 """
169 """
170 Convert a notebook from a notebook node instance.
170 Convert a notebook from a notebook node instance.
171
171
172 Parameters
172 Parameters
173 ----------
173 ----------
174 nb : Notebook node
174 nb : Notebook node
175 resources : dict (**kw)
175 resources : dict (**kw)
176 of additional resources that can be accessed read/write by
176 of additional resources that can be accessed read/write by
177 transformers and filters.
177 transformers and filters.
178 """
178 """
179 nb_copy = deepcopy(nb)
179 nb_copy = deepcopy(nb)
180
180
181 #Set output extension in resources dict
182 #TODO: init_resources
183 resources['output_extension'] = self.file_extension
184
181 #Preprocess
185 #Preprocess
182 nb_copy, resources = self._preprocess(nb_copy, resources)
186 nb_copy, resources = self._transform(nb_copy, resources)
183
187
184 #Convert
188 #Convert
185 self.template = self.environment.get_template(self.template_file + self.template_extension)
189 self.template = self.environment.get_template(self.template_file + self.template_extension)
186 output = self.template.render(nb=nb_copy, resources=resources)
190 output = self.template.render(nb=nb_copy, resources=resources)
187
188 #Set output extension in resources dict
189 resources['output_extension'] = self.file_extension
190 return output, resources
191 return output, resources
191
192
192
193
193 def from_filename(self, filename, resources=None **kw):
194 def from_filename(self, filename, resources=None, **kw):
194 """
195 """
195 Convert a notebook from a notebook file.
196 Convert a notebook from a notebook file.
196
197
197 Parameters
198 Parameters
198 ----------
199 ----------
199 filename : str
200 filename : str
200 Full filename of the notebook file to open and convert.
201 Full filename of the notebook file to open and convert.
201 """
202 """
202
203
203 with io.open(filename) as f:
204 with io.open(filename) as f:
204 return self.from_notebook_node(nbformat.read(f, 'json'), resources=resources,**kw)
205 return self.from_notebook_node(nbformat.read(f, 'json'), resources=resources,**kw)
205
206
206
207
207 def from_file(self, file_stream, resources=None, **kw):
208 def from_file(self, file_stream, resources=None, **kw):
208 """
209 """
209 Convert a notebook from a notebook file.
210 Convert a notebook from a notebook file.
210
211
211 Parameters
212 Parameters
212 ----------
213 ----------
213 file_stream : file-like object
214 file_stream : file-like object
214 Notebook file-like object to convert.
215 Notebook file-like object to convert.
215 """
216 """
216 return self.from_notebook_node(nbformat.read(file_stream, 'json'), resources=resources, **kw)
217 return self.from_notebook_node(nbformat.read(file_stream, 'json'), resources=resources, **kw)
217
218
218
219
219 def register_transformer(self, transformer, enabled=None):
220 def register_transformer(self, transformer, enabled=None):
220 """
221 """
221 Register a transformer.
222 Register a transformer.
222 Transformers are classes that act upon the notebook before it is
223 Transformers are classes that act upon the notebook before it is
223 passed into the Jinja templating engine. Transformers are also
224 passed into the Jinja templating engine. Transformers are also
224 capable of passing additional information to the Jinja
225 capable of passing additional information to the Jinja
225 templating engine.
226 templating engine.
226
227
227 Parameters
228 Parameters
228 ----------
229 ----------
229 transformer : transformer
230 transformer : transformer
230 """
231 """
231
232
232 #Handle transformer's registration based on it's type
233 #Handle transformer's registration based on it's type
233 if inspect.isfunction(transformer):
234 if inspect.isfunction(transformer):
234 #Transformer is a function, no need to construct it.
235 #Transformer is a function, no need to construct it.
235 self._transformers.append(transformer)
236 self._transformers.append(transformer)
236 return transformer
237 return transformer
237
238
238 elif isinstance(transformer, types.StringTypes):
239 elif isinstance(transformer, types.StringTypes):
239 #Transformer is a string, import the namespace and recursively call
240 #Transformer is a string, import the namespace and recursively call
240 #this register_transformer method
241 #this register_transformer method
241 transformer_cls = import_item(DottedObjectName(transformer))
242 transformer_cls = import_item(DottedObjectName(transformer))
242 return self.register_transformer(transformer_cls, enabled=None)
243 return self.register_transformer(transformer_cls, enabled=None)
243
244
244 elif isinstance(transformer, MetaHasTraits):
245 elif isinstance(transformer, MetaHasTraits):
245 #Transformer is configurable. Make sure to pass in new default for
246 #Transformer is configurable. Make sure to pass in new default for
246 #the enabled flag if one was specified.
247 #the enabled flag if one was specified.
247 c = Config()
248 transformer_instance = transformer(parent=self)
248 if not enabled is None:
249 if enabled is not None:
249 c = Config({transformer.__name__: {'enabled': enabled}})
250 transformer_instance.enabled = True
250 c.merge(self.config)
251 transformer_instance = transformer(config=c)
252
251
253 else:
252 else:
254 #Transformer is not configurable, construct it
253 #Transformer is not configurable, construct it
255 transformer_instance = transformer()
254 transformer_instance = transformer()
256
255
257 #Register and return the transformer.
256 #Register and return the transformer.
258 self._transformers.append(transformer_instance)
257 self._transformers.append(transformer_instance)
259 return transformer_instance
258 return transformer_instance
260
259
261
260
262 def register_filter(self, name, filter):
261 def register_filter(self, name, filter):
263 """
262 """
264 Register a filter.
263 Register a filter.
265 A filter is a function that accepts and acts on one string.
264 A filter is a function that accepts and acts on one string.
266 The filters are accesible within the Jinja templating engine.
265 The filters are accesible within the Jinja templating engine.
267
266
268 Parameters
267 Parameters
269 ----------
268 ----------
270 name : str
269 name : str
271 name to give the filter in the Jinja engine
270 name to give the filter in the Jinja engine
272 filter : filter
271 filter : filter
273 """
272 """
274 if inspect.isfunction(filter):
273 if inspect.isfunction(filter):
275 self.environment.filters[name] = filter
274 self.environment.filters[name] = filter
276 elif isinstance(filter, types.StringTypes):
275 elif isinstance(filter, types.StringTypes):
277 filter_cls = import_item(DottedObjectName(filter))
276 filter_cls = import_item(DottedObjectName(filter))
278 self.register_filter(name, filter_cls)
277 self.register_filter(name, filter_cls)
279 elif isinstance(filter, MetaHasTraits):
278 elif isinstance(filter, MetaHasTraits):
280 self.environment.filters[name] = filter(config=self.config)
279 self.environment.filters[name] = filter(config=self.config)
281 else:
280 else:
282 self.environment.filters[name] = filter()
281 self.environment.filters[name] = filter()
283 return self.environment.filters[name]
282 return self.environment.filters[name]
284
283
285
284
286 def _register_transformers(self):
285 def _register_transformers(self):
287 """
286 """
288 Register all of the transformers needed for this exporter, disabled
287 Register all of the transformers needed for this exporter, disabled
289 unless specified explicitly.
288 unless specified explicitly.
290 """
289 """
291
290
292 self.register_transformer(transformers.coalesce_streams)
291 self.register_transformer(transformers.coalesce_streams)
293 self.register_transformer(transformers.ExtractFigureTransformer)
292 self.register_transformer(transformers.ExtractFigureTransformer)
294
293
295
294
296 def _register_filters(self):
295 def _register_filters(self):
297 """
296 """
298 Register all of the filters required for the exporter.
297 Register all of the filters required for the exporter.
299 """
298 """
300 for key, value in default_filters.iteritems():
299 for key, value in default_filters.iteritems():
301 self.register_filter(key, value)
300 self.register_filter(key, value)
302
301
303
302
304 def _init_environment(self, extra_loaders=None):
303 def _init_environment(self, extra_loaders=None):
305 """
304 """
306 Create the Jinja templating environment.
305 Create the Jinja templating environment.
307 """
306 """
308 here = os.path.dirname(os.path.realpath(__file__))
307 here = os.path.dirname(os.path.realpath(__file__))
309 loaders = []
308 loaders = []
310 if extra_loaders:
309 if extra_loaders:
311 loaders.extend(extra_loaders)
310 loaders.extend(extra_loaders)
312
311
313 loaders.append(FileSystemLoader([
312 loaders.append(FileSystemLoader([
314 os.path.join(here, self.template_path),
313 os.path.join(here, self.template_path),
315 os.path.join(here, self.template_skeleton_path),
314 os.path.join(here, self.template_skeleton_path),
316 ]))
315 ]))
317
316
318 self.environment = Environment(
317 self.environment = Environment(
319 loader= ChoiceLoader(loaders),
318 loader= ChoiceLoader(loaders),
320 extensions=JINJA_EXTENSIONS
319 extensions=JINJA_EXTENSIONS
321 )
320 )
322
321
323 #Set special Jinja2 syntax that will not conflict with latex.
322 #Set special Jinja2 syntax that will not conflict with latex.
324 if self.jinja_logic_block_start:
323 if self.jinja_logic_block_start:
325 self.environment.block_start_string = self.jinja_logic_block_start
324 self.environment.block_start_string = self.jinja_logic_block_start
326 if self.jinja_logic_block_end:
325 if self.jinja_logic_block_end:
327 self.environment.block_end_string = self.jinja_logic_block_end
326 self.environment.block_end_string = self.jinja_logic_block_end
328 if self.jinja_variable_block_start:
327 if self.jinja_variable_block_start:
329 self.environment.variable_start_string = self.jinja_variable_block_start
328 self.environment.variable_start_string = self.jinja_variable_block_start
330 if self.jinja_variable_block_end:
329 if self.jinja_variable_block_end:
331 self.environment.variable_end_string = self.jinja_variable_block_end
330 self.environment.variable_end_string = self.jinja_variable_block_end
332 if self.jinja_comment_block_start:
331 if self.jinja_comment_block_start:
333 self.environment.comment_start_string = self.jinja_comment_block_start
332 self.environment.comment_start_string = self.jinja_comment_block_start
334 if self.jinja_comment_block_end:
333 if self.jinja_comment_block_end:
335 self.environment.comment_end_string = self.jinja_comment_block_end
334 self.environment.comment_end_string = self.jinja_comment_block_end
336
335
337
336
338 def _preprocess(self, nb, resources):
337 def _transform(self, nb, resources):
339 """
338 """
340 Preprocess the notebook before passing it into the Jinja engine.
339 Preprocess the notebook before passing it into the Jinja engine.
341 To preprocess the notebook is to apply all of the
340 To preprocess the notebook is to apply all of the
342
341
343 Parameters
342 Parameters
344 ----------
343 ----------
345 nb : notebook node
344 nb : notebook node
346 notebook that is being exported.
345 notebook that is being exported.
347 resources : a dict of additional resources that
346 resources : a dict of additional resources that
348 can be accessed read/write by transformers
347 can be accessed read/write by transformers
349 and filters.
348 and filters.
350 """
349 """
351
350
352 # Do a deepcopy first,
351 # Do a deepcopy first,
353 # we are never safe enough with what the transformers could do.
352 # we are never safe enough with what the transformers could do.
354 nbc = deepcopy(nb)
353 nbc = deepcopy(nb)
355 resc = deepcopy(resources)
354 resc = deepcopy(resources)
356
355
357 #Run each transformer on the notebook. Carry the output along
356 #Run each transformer on the notebook. Carry the output along
358 #to each transformer
357 #to each transformer
359 for transformer in self._transformers:
358 for transformer in self._transformers:
360 nbc, resc = transformer(nbc, resc)
359 nbc, resc = transformer(nbc, resc)
361 return nbc, resc
360 return nbc, resc
@@ -1,111 +1,111
1 """
1 """
2 Exporter that allows Latex Jinja templates to work. Contains logic to
2 Exporter that allows Latex Jinja templates to work. Contains logic to
3 appropriately prepare IPYNB files for export to LaTeX. Including but
3 appropriately prepare IPYNB files for export to LaTeX. Including but
4 not limited to escaping LaTeX, fixing math region tags, using special
4 not limited to escaping LaTeX, fixing math region tags, using special
5 tags to circumvent Jinja/Latex syntax conflicts.
5 tags to circumvent Jinja/Latex syntax conflicts.
6 """
6 """
7 #-----------------------------------------------------------------------------
7 #-----------------------------------------------------------------------------
8 # Copyright (c) 2013, the IPython Development Team.
8 # Copyright (c) 2013, the IPython Development Team.
9 #
9 #
10 # Distributed under the terms of the Modified BSD License.
10 # Distributed under the terms of the Modified BSD License.
11 #
11 #
12 # The full license is in the file COPYING.txt, distributed with this software.
12 # The full license is in the file COPYING.txt, distributed with this software.
13 #-----------------------------------------------------------------------------
13 #-----------------------------------------------------------------------------
14
14
15 #-----------------------------------------------------------------------------
15 #-----------------------------------------------------------------------------
16 # Imports
16 # Imports
17 #-----------------------------------------------------------------------------
17 #-----------------------------------------------------------------------------
18
18
19 # Stdlib imports
19 # Stdlib imports
20 import os
20 import os
21
21
22 # IPython imports
22 # IPython imports
23 from IPython.utils.traitlets import Unicode
23 from IPython.utils.traitlets import Unicode
24 from IPython.config import Config
24 from IPython.config import Config
25
25
26 from IPython.nbconvert import filters, transformers
26 from IPython.nbconvert import filters, transformers
27 from .exporter import Exporter
27 from .exporter import Exporter
28
28
29 #-----------------------------------------------------------------------------
29 #-----------------------------------------------------------------------------
30 # Classes and functions
30 # Classes and functions
31 #-----------------------------------------------------------------------------
31 #-----------------------------------------------------------------------------
32
32
33 class LatexExporter(Exporter):
33 class LatexExporter(Exporter):
34 """
34 """
35 Exports to a Latex template. Inherit from this class if your template is
35 Exports to a Latex template. Inherit from this class if your template is
36 LaTeX based and you need custom tranformers/filters. Inherit from it if
36 LaTeX based and you need custom tranformers/filters. Inherit from it if
37 you are writing your own HTML template and need custom tranformers/filters.
37 you are writing your own HTML template and need custom tranformers/filters.
38 If you don't need custom tranformers/filters, just change the
38 If you don't need custom tranformers/filters, just change the
39 'template_file' config option. Place your template in the special "/latex"
39 'template_file' config option. Place your template in the special "/latex"
40 subfolder of the "../templates" folder.
40 subfolder of the "../templates" folder.
41 """
41 """
42
42
43 file_extension = Unicode(
43 file_extension = Unicode(
44 'tex', config=True,
44 'tex', config=True,
45 help="Extension of the file that should be written to disk")
45 help="Extension of the file that should be written to disk")
46
46
47 template_file = Unicode(
47 template_file = Unicode(
48 'base', config=True,
48 'base', config=True,
49 help="Name of the template file to use")
49 help="Name of the template file to use")
50
50
51 #Latex constants
51 #Latex constants
52 template_path = Unicode(
52 template_path = Unicode(
53 os.path.join("..", "templates", "latex"), config=True,
53 os.path.join("..", "templates", "latex"), config=True,
54 help="Path where the template files are located.")
54 help="Path where the template files are located.")
55
55
56 template_skeleton_path = Unicode(
56 template_skeleton_path = Unicode(
57 os.path.join("..", "templates", "latex", "skeleton"), config=True,
57 os.path.join("..", "templates", "latex", "skeleton"), config=True,
58 help="Path where the template skeleton files are located.")
58 help="Path where the template skeleton files are located.")
59
59
60 #Special Jinja2 syntax that will not conflict when exporting latex.
60 #Special Jinja2 syntax that will not conflict when exporting latex.
61 jinja_comment_block_start = Unicode("((=", config=True)
61 jinja_comment_block_start = Unicode("((=", config=True)
62 jinja_comment_block_end = Unicode("=))", config=True)
62 jinja_comment_block_end = Unicode("=))", config=True)
63 jinja_variable_block_start = Unicode("(((", config=True)
63 jinja_variable_block_start = Unicode("(((", config=True)
64 jinja_variable_block_end = Unicode(")))", config=True)
64 jinja_variable_block_end = Unicode(")))", config=True)
65 jinja_logic_block_start = Unicode("((*", config=True)
65 jinja_logic_block_start = Unicode("((*", config=True)
66 jinja_logic_block_end = Unicode("*))", config=True)
66 jinja_logic_block_end = Unicode("*))", config=True)
67
67
68 #Extension that the template files use.
68 #Extension that the template files use.
69 template_extension = Unicode(".tplx", config=True)
69 template_extension = Unicode(".tplx", config=True)
70
70
71 def _register_filters(self):
71 def _register_filters(self):
72 """
72 """
73 Register all of the filters required for the exporter.
73 Register all of the filters required for the exporter.
74 """
74 """
75
75
76 #Register the filters of the base class.
76 #Register the filters of the base class.
77 super(LatexExporter, self)._register_filters()
77 super(LatexExporter, self)._register_filters()
78
78
79 #Add latex filters to the Jinja2 environment
79 #Add latex filters to the Jinja2 environment
80 self.register_filter('escape_tex', filters.escape_latex)
80 self.register_filter('escape_tex', filters.escape_latex)
81 self.register_filter('highlight', filters.highlight2latex)
81 self.register_filter('highlight', filters.highlight2latex)
82
82
83
83
84 def _register_transformers(self):
84 def _register_transformers(self):
85 """
85 """
86 Register all of the transformers needed for this exporter.
86 Register all of the transformers needed for this exporter.
87 """
87 """
88
88
89 #Register ConvertSvgTransformer before any other transformers!
89 #Register ConvertSvgTransformer before any other transformers!
90 #Important because it allows the conversion of svg->png BEFORE the
90 #Important because it allows the conversion of svg->png BEFORE the
91 #extract figure transformer acts on the data.
91 #extract figure transformer acts on the data.
92 self.register_transformer(transformers.ConvertSvgTransformer, True)
92 self.register_transformer(transformers.ConvertSvgTransformer, True)
93
93
94 #Register transformers
94 #Register transformers
95 super(LatexExporter, self)._register_transformers()
95 super(LatexExporter, self)._register_transformers()
96 self.register_transformer(transformers.LatexTransformer, True)
96 self.register_transformer(transformers.LatexTransformer, True)
97
97
98 @property
98 @property
99 def default_config(self):
99 def default_config(self):
100 c = Config({
100 c = Config({
101 'GlobalConfigurable': {
101 'GlobalConfigurable': {
102 'display_data_priority' : ['latex', 'png', 'jpg', 'jpeg', 'text']
102 'display_data_priority' : ['latex', 'png', 'jpg', 'pdf', 'jpeg', 'text']
103 },
103 },
104 'ExtractFigureTransformer': {
104 'ExtractFigureTransformer': {
105 'enabled':True
105 'enabled':True
106 }
106 }
107
107
108 })
108 })
109 c.merge(super(LatexExporter,self).default_config)
109 c.merge(super(LatexExporter,self).default_config)
110 return c
110 return c
111
111
@@ -1,179 +1,180
1 #!/usr/bin/env python
1 #!/usr/bin/env python
2 """NBConvert is a utility for conversion of IPYNB files.
2 """NBConvert is a utility for conversion of IPYNB files.
3
3
4 Commandline interface for the NBConvert conversion utility. Read the
4 Commandline interface for the NBConvert conversion utility. Read the
5 readme.rst for usage information
5 readme.rst for usage information
6 """
6 """
7 #-----------------------------------------------------------------------------
7 #-----------------------------------------------------------------------------
8 #Copyright (c) 2013, the IPython Development Team.
8 #Copyright (c) 2013, the IPython Development Team.
9 #
9 #
10 #Distributed under the terms of the Modified BSD License.
10 #Distributed under the terms of the Modified BSD License.
11 #
11 #
12 #The full license is in the file COPYING.txt, distributed with this software.
12 #The full license is in the file COPYING.txt, distributed with this software.
13 #-----------------------------------------------------------------------------
13 #-----------------------------------------------------------------------------
14
14
15 #-----------------------------------------------------------------------------
15 #-----------------------------------------------------------------------------
16 #Imports
16 #Imports
17 #-----------------------------------------------------------------------------
17 #-----------------------------------------------------------------------------
18
18
19 #Stdlib imports
19 #Stdlib imports
20 from __future__ import print_function
20 from __future__ import print_function
21 import sys
21 import sys
22 import os
22 import os
23 import glob
23 import glob
24
24
25 #From IPython
25 #From IPython
26 from IPython.core.application import BaseIPythonApplication
26 from IPython.core.application import BaseIPythonApplication
27 from IPython.config.application import catch_config_error
27 from IPython.config.application import catch_config_error
28 from IPython.utils.traitlets import Unicode, List, Instance, DottedObjectName, Type
28 from IPython.utils.traitlets import Unicode, List, Instance, DottedObjectName, Type
29 from IPython.utils.importstring import import_item
29 from IPython.utils.importstring import import_item
30
30
31 from .exporters.export import export_by_name, get_export_names, ExporterNameError
31 from .exporters.export import export_by_name, get_export_names, ExporterNameError
32 from .exporters.exporter import Exporter
32 from .exporters.exporter import Exporter
33 from .writers.base import WriterBase
33 from .writers.base import WriterBase
34 from .utils.config import GlobalConfigurable
34 from .utils.config import GlobalConfigurable
35
35
36 #-----------------------------------------------------------------------------
36 #-----------------------------------------------------------------------------
37 #Classes and functions
37 #Classes and functions
38 #-----------------------------------------------------------------------------
38 #-----------------------------------------------------------------------------
39
39
40 class NbConvertApp(BaseIPythonApplication):
40 class NbConvertApp(BaseIPythonApplication):
41 """Application used to convert to and from notebook file type (*.ipynb)"""
41 """Application used to convert to and from notebook file type (*.ipynb)"""
42
42
43
43
44 description = Unicode(
44 description = Unicode(
45 u"""This application is used to convert notebook files (*.ipynb).
45 u"""This application is used to convert notebook files (*.ipynb).
46 An ipython config file can be used to batch convert notebooks in the
46 An ipython config file can be used to batch convert notebooks in the
47 current directory.""")
47 current directory.""")
48
48
49 examples = Unicode(u"""
49 examples = Unicode(u"""
50 Running `ipython nbconvert` will read the directory config file and then
50 Running `ipython nbconvert` will read the directory config file and then
51 apply it to one or more notebooks.
51 apply it to one or more notebooks.
52
52
53 Multiple notebooks can be given at the command line in a couple of
53 Multiple notebooks can be given at the command line in a couple of
54 different ways:
54 different ways:
55
55
56 > ipython nbconvert notebook*.ipynb
56 > ipython nbconvert notebook*.ipynb
57 > ipython nbconvert notebook1.ipynb notebook2.ipynb
57 > ipython nbconvert notebook1.ipynb notebook2.ipynb
58 > ipython nbconvert # this will use the config file to fill in the notebooks
58 > ipython nbconvert # this will use the config file to fill in the notebooks
59 """)
59 """)
60
60
61 config_file_name = Unicode(u'ipython_nbconvert_config.py')
61 config_file_name = Unicode(u'ipython_nbconvert_config.py')
62
62
63 #Writer specific variables
63 #Writer specific variables
64 writer = Instance('IPython.nbconvert.writers.base.WriterBase',
64 writer = Instance('IPython.nbconvert.writers.base.WriterBase',
65 help="""Instance of the writer class used to write the
65 help="""Instance of the writer class used to write the
66 results of the conversion.""")
66 results of the conversion.""")
67 writer_class = DottedObjectName('FilesWriter', config=True,
67 writer_class = DottedObjectName('FilesWriter', config=True,
68 help="""Writer class used to write the
68 help="""Writer class used to write the
69 results of the conversion""")
69 results of the conversion""")
70 writer_aliases = {'FilesWriter': 'IPython.nbconvert.writers.files.FilesWriter',
70 writer_aliases = {'FilesWriter': 'IPython.nbconvert.writers.files.FilesWriter',
71 'DebugWriter': 'IPython.nbconvert.writers.debug.DebugWriter',
71 'DebugWriter': 'IPython.nbconvert.writers.debug.DebugWriter',
72 'StdoutWriter': 'IPython.nbconvert.writers.stdout.StdoutWriter'}
72 'StdoutWriter': 'IPython.nbconvert.writers.stdout.StdoutWriter'}
73 writer_factory = Type()
73 writer_factory = Type()
74
74
75 def _writer_class_changed(self, name, old, new):
75 def _writer_class_changed(self, name, old, new):
76 if new in self.writer_aliases:
76 if new in self.writer_aliases:
77 new = self.writer_aliases[new]
77 new = self.writer_aliases[new]
78 self.writer_factory = import_item(new)
78 self.writer_factory = import_item(new)
79
79
80
80
81 #Other configurable variables
81 #Other configurable variables
82 export_format = Unicode(
82 export_format = Unicode(
83 "", config=True,
83 "", config=True,
84 help="""If specified, nbconvert will convert the document(s) specified
84 help="""If specified, nbconvert will convert the document(s) specified
85 using this format.""")
85 using this format.""")
86
86
87 notebooks = List([], config=True, help="""List of notebooks to convert.
87 notebooks = List([], config=True, help="""List of notebooks to convert.
88 Search patterns are supported.""")
88 Search patterns are supported.""")
89
89
90 aliases = {'format':'NbConvertApp.export_format',
90 aliases = {'format':'NbConvertApp.export_format',
91 'notebooks':'NbConvertApp.notebooks',
91 'notebooks':'NbConvertApp.notebooks',
92 'writer':'NbConvertApp.writer_class'}
92 'writer':'NbConvertApp.writer_class'}
93
93
94
94
95 @catch_config_error
95 @catch_config_error
96 def initialize(self, argv=None):
96 def initialize(self, argv=None):
97 super(NbConvertApp, self).initialize(argv)
97 super(NbConvertApp, self).initialize(argv)
98
98
99 #Register class here to have help with help all
99 #Register class here to have help with help all
100 self.classes.insert(0, Exporter)
100 self.classes.insert(0, Exporter)
101 self.classes.insert(0, WriterBase)
101 self.classes.insert(0, WriterBase)
102 self.classes.insert(0, GlobalConfigurable)
102 self.classes.insert(0, GlobalConfigurable)
103
103
104 #Init
104 #Init
105 self.init_config(self.extra_args)
105 self.init_config(self.extra_args)
106 self.init_writer()
106 self.init_writer()
107
107
108
108
109 def init_config(self, extra_args):
109 def init_config(self, extra_args):
110 """
110 """
111 Add notebooks to the config if needed. Glob each notebook to replace
111 Add notebooks to the config if needed. Glob each notebook to replace
112 notebook patterns with filenames.
112 notebook patterns with filenames.
113 """
113 """
114
114
115 #Get any additional notebook patterns from the commandline
115 #Get any additional notebook patterns from the commandline
116 if len(extra_args) > 0:
116 if len(extra_args) > 0:
117 for pattern in extra_args:
117 for pattern in extra_args:
118 self.notebooks.append(pattern)
118 self.notebooks.append(pattern)
119
119
120 #Use glob to replace all the notebook patterns with filenames.
120 #Use glob to replace all the notebook patterns with filenames.
121 filenames = []
121 filenames = []
122 for pattern in self.notebooks:
122 for pattern in self.notebooks:
123 for filename in glob.glob(pattern):
123 for filename in glob.glob(pattern):
124 if not filename in filenames:
124 if not filename in filenames:
125 filenames.append(filename)
125 filenames.append(filename)
126 self.notebooks = filenames
126 self.notebooks = filenames
127
127
128
128
129 def init_writer(self):
129 def init_writer(self):
130 """
130 """
131 Initialize the writer (which is stateless)
131 Initialize the writer (which is stateless)
132 """
132 """
133 self._writer_class_changed(None, self.writer_class, self.writer_class)
133 self._writer_class_changed(None, self.writer_class, self.writer_class)
134 self.writer = self.writer_factory(parent=self)
134 self.writer = self.writer_factory(parent=self)
135
135
136
136
137 def start(self, argv=None):
137 def start(self, argv=None):
138 """
138 """
139 Entrypoint of NbConvert application.
139 Entrypoint of NbConvert application.
140 """
140 """
141
141
142 #Call base
142 #Call base
143 super(NbConvertApp, self).start()
143 super(NbConvertApp, self).start()
144
144
145 #Export each notebook
145 #Export each notebook
146 #TODO: Empty check
146 for notebook_filename in self.notebooks:
147 for notebook_filename in self.notebooks:
147
148
148 #Get a unique key for the notebook and set it in the resources object.
149 #Get a unique key for the notebook and set it in the resources object.
149 basename = os.path.basename(notebook_filename)
150 basename = os.path.basename(notebook_filename)
150 notebook_name = basename[:basename.rfind('.')]
151 notebook_name = basename[:basename.rfind('.')]
151 resources = {}
152 resources = {}
152 resources['unique_key'] = notebook_name
153 resources['unique_key'] = notebook_name
153
154
154 #Try to export
155 #Try to export
155 try:
156 try:
156 return_value = export_by_name(self.export_format,
157 output, resources = export_by_name(self.export_format,
157 notebook_filename,
158 notebook_filename,
158 resources=resources,
159 resources=resources,
159 config=self.config)
160 config=self.config)
160 except ExporterNameError as e:
161 except ExporterNameError as e:
161 print("Error: '%s' exporter not found." % self.export_format,
162 print("Error: '%s' exporter not found." % self.export_format,
162 file=sys.stderr)
163 file=sys.stderr)
163 print("Known exporters are:",
164 print("Known exporters are:",
164 "\n\t" + "\n\t".join(get_export_names()),
165 "\n\t" + "\n\t".join(get_export_names()),
165 file=sys.stderr)
166 file=sys.stderr)
166 sys.exit(-1)
167 sys.exit(-1)
167 else:
168 except Exception as e:
168 output, resources = return_value
169 print("Error: could no export '%s'" % notebook_filename, file=sys.stderr)
170 print(e, file=sys.stderr)
169
171
170 #Write
172 #Write
171 self.writer.write(output, resources, notebook_name=notebook_name)
173 self.writer.write(output, resources, notebook_name=notebook_name)
172
174
173
175
174 #-----------------------------------------------------------------------------
176 #-----------------------------------------------------------------------------
175 # Main entry point
177 # Main entry point
176 #-----------------------------------------------------------------------------
178 #-----------------------------------------------------------------------------
177
179
178 launch_new_instance = NbConvertApp.launch_instance
180 launch_new_instance = NbConvertApp.launch_instance
179
@@ -1,74 +1,77
1 """Module containing a transformer that converts outputs in the notebook from
1 """Module containing a transformer that converts outputs in the notebook from
2 one format to another.
2 one format to another.
3 """
3 """
4 #-----------------------------------------------------------------------------
4 #-----------------------------------------------------------------------------
5 # Copyright (c) 2013, the IPython Development Team.
5 # Copyright (c) 2013, the IPython Development Team.
6 #
6 #
7 # Distributed under the terms of the Modified BSD License.
7 # Distributed under the terms of the Modified BSD License.
8 #
8 #
9 # The full license is in the file COPYING.txt, distributed with this software.
9 # The full license is in the file COPYING.txt, distributed with this software.
10 #-----------------------------------------------------------------------------
10 #-----------------------------------------------------------------------------
11
11
12 #TODO: Come after extract
13
12 #-----------------------------------------------------------------------------
14 #-----------------------------------------------------------------------------
13 # Imports
15 # Imports
14 #-----------------------------------------------------------------------------
16 #-----------------------------------------------------------------------------
15
17
16 from .activatable import ActivatableTransformer
18 from .activatable import ActivatableTransformer
17
19
18 #-----------------------------------------------------------------------------
20 #-----------------------------------------------------------------------------
19 # Classes
21 # Classes
20 #-----------------------------------------------------------------------------
22 #-----------------------------------------------------------------------------
21
23
22 class ConvertFiguresTransformer(ActivatableTransformer):
24 class ConvertFiguresTransformer(ActivatableTransformer):
23 """
25 """
24 Converts all of the outputs in a notebook from one format to another.
26 Converts all of the outputs in a notebook from one format to another.
25 """
27 """
26
28
27
29
28 def __init__(self, from_formats, to_format, **kw):
30 def __init__(self, from_formats, to_format, **kw):
29 """
31 """
30 Public constructor
32 Public constructor
31
33
32 Parameters
34 Parameters
33 ----------
35 ----------
34 from_formats : list [of string]
36 from_formats : list [of string]
35 Formats that the converter can convert from
37 Formats that the converter can convert from
36 to_format : string
38 to_format : string
37 Format that the converter converts to
39 Format that the converter converts to
38 config : Config
40 config : Config
39 Configuration file structure
41 Configuration file structure
40 **kw : misc
42 **kw : misc
41 Additional arguments
43 Additional arguments
42 """
44 """
43 super(ConvertFiguresTransformer, self).__init__(**kw)
45 super(ConvertFiguresTransformer, self).__init__(**kw)
44
46
47 #TODO: Configurable, singular
45 self._from_formats = from_formats
48 self._from_formats = from_formats
46 self._to_format = to_format
49 self._to_format = to_format
47
50
48
51
49 def convert_figure(self, data_format, data):
52 def convert_figure(self, data_format, data):
50 raise NotImplementedError()
53 raise NotImplementedError()
51
54
52
55
53 def transform_cell(self, cell, resources, cell_index):
56 def transform_cell(self, cell, resources, cell_index):
54 """
57 """
55 Apply a transformation on each cell,
58 Apply a transformation on each cell,
56
59
57 See base.py
60 See base.py
58 """
61 """
59
62
60 #Loop through all of the datatypes of the outputs in the cell.
63 #Loop through all of the datatypes of the outputs in the cell.
61 for index, cell_out in enumerate(cell.get('outputs', [])):
64 for index, cell_out in enumerate(cell.get('outputs', [])):
62 for data_type, data in cell_out.items():
65 for data_type, data in cell_out.items():
63 self._convert_figure(cell_out, data_type, data)
66 self._convert_figure(cell_out, data_type, data)
64 return cell, resources
67 return cell, resources
65
68
66
69
67 def _convert_figure(self, cell_out, data_type, data):
70 def _convert_figure(self, cell_out, data_type, data):
68 """
71 """
69 Convert a figure and output the results to the cell output
72 Convert a figure and output the results to the cell output
70 """
73 """
71
74
72 if not self._to_format in cell_out:
75 if not self._to_format in cell_out:
73 if data_type in self._from_formats:
76 if data_type in self._from_formats:
74 cell_out[self._to_format] = self.convert_figure(data_type, data)
77 cell_out[self._to_format] = self.convert_figure(data_type, data)
@@ -1,71 +1,72
1 """Module containing a transformer that converts outputs in the notebook from
1 """Module containing a transformer that converts outputs in the notebook from
2 one format to another.
2 one format to another.
3 """
3 """
4 #-----------------------------------------------------------------------------
4 #-----------------------------------------------------------------------------
5 # Copyright (c) 2013, the IPython Development Team.
5 # Copyright (c) 2013, the IPython Development Team.
6 #
6 #
7 # Distributed under the terms of the Modified BSD License.
7 # Distributed under the terms of the Modified BSD License.
8 #
8 #
9 # The full license is in the file COPYING.txt, distributed with this software.
9 # The full license is in the file COPYING.txt, distributed with this software.
10 #-----------------------------------------------------------------------------
10 #-----------------------------------------------------------------------------
11
11
12 #-----------------------------------------------------------------------------
12 #-----------------------------------------------------------------------------
13 # Imports
13 # Imports
14 #-----------------------------------------------------------------------------
14 #-----------------------------------------------------------------------------
15
15
16 import os
16 import os
17 from IPython.utils.tempdir import TemporaryDirectory
17 from IPython.utils.tempdir import TemporaryDirectory
18
18
19 from .convertfigures import ConvertFiguresTransformer
19 from .convertfigures import ConvertFiguresTransformer
20
20
21
21
22 #-----------------------------------------------------------------------------
22 #-----------------------------------------------------------------------------
23 # Constants
23 # Constants
24 #-----------------------------------------------------------------------------
24 #-----------------------------------------------------------------------------
25
25
26 INKSCAPE_COMMAND = "inkscape --without-gui --export-pdf=\"{to_filename}\" \"{from_filename}\""
26 INKSCAPE_COMMAND = "inkscape --without-gui --export-pdf=\"{to_filename}\" \"{from_filename}\""
27
27
28
28
29 #-----------------------------------------------------------------------------
29 #-----------------------------------------------------------------------------
30 # Classes
30 # Classes
31 #-----------------------------------------------------------------------------
31 #-----------------------------------------------------------------------------
32
32
33 class ConvertSvgTransformer(ConvertFiguresTransformer):
33 class ConvertSvgTransformer(ConvertFiguresTransformer):
34 """
34 """
35 Converts all of the outputs in a notebook from one format to another.
35 Converts all of the outputs in a notebook from one format to another.
36 """
36 """
37
37
38
38
39 def __init__(self, **kw):
39 def __init__(self, **kw):
40 """
40 """
41 Constructor
41 Constructor
42 """
42 """
43 super(ConvertSvgTransformer, self).__init__(['svg'], 'pdf', **kw)
43 super(ConvertSvgTransformer, self).__init__(['svg'], 'pdf', **kw)
44
44
45
45
46 def convert_figure(self, data_format, data):
46 def convert_figure(self, data_format, data):
47 """
47 """
48 Convert a single Svg figure. Returns converted data.
48 Convert a single Svg figure. Returns converted data.
49 """
49 """
50
50
51 #Work in a temporary directory
51 #Work in a temporary directory
52 with TemporaryDirectory() as tmpdir:
52 with TemporaryDirectory() as tmpdir:
53
53
54 #Write fig to temp file
54 #Write fig to temp file
55 input_filename = os.path.join(tmpdir, 'figure.' + data_format)
55 input_filename = os.path.join(tmpdir, 'figure.' + data_format)
56 with open(input_filename, 'w') as f:
56 with open(input_filename, 'w') as f:
57 f.write(data)
57 f.write(data)
58
58
59 #Call conversion application
59 #Call conversion application
60 output_filename = os.path.join(tmpdir, 'figure.pdf')
60 output_filename = os.path.join(tmpdir, 'figure.pdf')
61 shell = INKSCAPE_COMMAND.format(from_filename=input_filename,
61 shell = INKSCAPE_COMMAND.format(from_filename=input_filename,
62 to_filename=output_filename)
62 to_filename=output_filename)
63 subprocess.call(shell, shell=True) #Shell=True okay since input is trusted.
63 subprocess.call(shell, shell=True) #Shell=True okay since input is trusted.
64
64
65 #Read output from drive
65 #Read output from drive
66 if os.path.isfile(output_filename):
66 if os.path.isfile(output_filename):
67 with open(output_filename, 'rb') as f:
67 with open(output_filename, 'rb') as f:
68 return f.read().encode("base64") #PDF is a nb supported binary
68 return f.read().encode("base64") #PDF is a nb supported binary
69 #data type, so base64 encode.
69 #data type, so base64 encode.
70 else:
70 else:
71 return TypeError("Inkscape svg to png conversion failed")
71 return TypeError("Inkscape svg to png conversion failed")
72 #TODO: ERROR: which notebook crashed exporter
@@ -1,100 +1,91
1 """Module containing a transformer that extracts all of the figures from the
1 """Module containing a transformer that extracts all of the figures from the
2 notebook file. The extracted figures are returned in the 'resources' dictionary.
2 notebook file. The extracted figures are returned in the 'resources' dictionary.
3 """
3 """
4 #-----------------------------------------------------------------------------
4 #-----------------------------------------------------------------------------
5 # Copyright (c) 2013, the IPython Development Team.
5 # Copyright (c) 2013, the IPython Development Team.
6 #
6 #
7 # Distributed under the terms of the Modified BSD License.
7 # Distributed under the terms of the Modified BSD License.
8 #
8 #
9 # The full license is in the file COPYING.txt, distributed with this software.
9 # The full license is in the file COPYING.txt, distributed with this software.
10 #-----------------------------------------------------------------------------
10 #-----------------------------------------------------------------------------
11
11
12 #-----------------------------------------------------------------------------
12 #-----------------------------------------------------------------------------
13 # Imports
13 # Imports
14 #-----------------------------------------------------------------------------
14 #-----------------------------------------------------------------------------
15
15
16 import sys
16 import sys
17 from IPython.utils.traitlets import Dict, Unicode
17 from IPython.utils.traitlets import Dict, Unicode
18 from .activatable import ActivatableTransformer
18 from .activatable import ActivatableTransformer
19
19
20 #-----------------------------------------------------------------------------
20 #-----------------------------------------------------------------------------
21 # Constants
22 #-----------------------------------------------------------------------------
23
24 # win64 is win32 for backwards compatability, for now. See
25 # http://mail.python.org/pipermail/patches/2000-May/000648.html
26 # for the original patch that this decision was made.
27 WINDOWS_PLATFORMS = ['win32']
28
29 #-----------------------------------------------------------------------------
30 # Classes
21 # Classes
31 #-----------------------------------------------------------------------------
22 #-----------------------------------------------------------------------------
32
23
33 class ExtractFigureTransformer(ActivatableTransformer):
24 class ExtractFigureTransformer(ActivatableTransformer):
34 """
25 """
35 Extracts all of the figures from the notebook file. The extracted
26 Extracts all of the figures from the notebook file. The extracted
36 figures are returned in the 'resources' dictionary.
27 figures are returned in the 'resources' dictionary.
37 """
28 """
38
29
39
30
40 figure_filename_template = Unicode(
31 figure_filename_template = Unicode(
41 "{unique_key}_{cell_index}_{index}.{extension}", config=True)
32 "{unique_key}_{cell_index}_{index}.{extension}", config=True)
42
33
43
34
44 def transform_cell(self, cell, resources, cell_index):
35 def transform_cell(self, cell, resources, cell_index):
45 """
36 """
46 Apply a transformation on each cell,
37 Apply a transformation on each cell,
47
38
48 Parameters
39 Parameters
49 ----------
40 ----------
50 cell : NotebookNode cell
41 cell : NotebookNode cell
51 Notebook cell being processed
42 Notebook cell being processed
52 resources : dictionary
43 resources : dictionary
53 Additional resources used in the conversion process. Allows
44 Additional resources used in the conversion process. Allows
54 transformers to pass variables into the Jinja engine.
45 transformers to pass variables into the Jinja engine.
55 cell_index : int
46 cell_index : int
56 Index of the cell being processed (see base.py)
47 Index of the cell being processed (see base.py)
57 """
48 """
58
49
59 #Get the unique key from the resource dict if it exists. If it does not
50 #Get the unique key from the resource dict if it exists. If it does not
60 #exist, use 'figure' as the default.
51 #exist, use 'figure' as the default.
61 unique_key = resources.get('unique_key', 'figure')
52 unique_key = resources.get('unique_key', 'figure')
62
53
63 #Make sure figures key exists
54 #Make sure figures key exists
64 if not 'figures' in resources:
55 if not 'figures' in resources:
65 resources['figures'] = {}
56 resources['figures'] = {}
66
57
67 #Loop through all of the outputs in the cell
58 #Loop through all of the outputs in the cell
68 for index, out in enumerate(cell.get('outputs', [])):
59 for index, out in enumerate(cell.get('outputs', [])):
69
60
70 #Get the output in data formats that the template is interested in.
61 #Get the output in data formats that the template is interested in.
71 for out_type in self.display_data_priority:
62 for out_type in self.display_data_priority:
72 if out.hasattr(out_type):
63 if out.hasattr(out_type):
73 data = out[out_type]
64 data = out[out_type]
74
65
75 #Binary files are base64-encoded, SVG is already XML
66 #Binary files are base64-encoded, SVG is already XML
76 if out_type in ('png', 'jpg', 'pdf'):
67 if out_type in ('png', 'jpg', 'pdf'):
77 data = data.decode('base64')
68 data = data.decode('base64')
78 elif sys.platform in WINDOWS_PLATFORMS:
69 elif sys.platform == 'win32':
79 data = data.replace('\n', '\r\n').encode("UTF-8")
70 data = data.replace('\n', '\r\n').encode("UTF-8")
80 else:
71 else:
81 data = data.encode("UTF-8")
72 data = data.encode("UTF-8")
82
73
83 #Build a figure name
74 #Build a figure name
84 figure_name = self.figure_filename_template.format(
75 figure_name = self.figure_filename_template.format(
85 unique_key=unique_key,
76 unique_key=unique_key,
86 cell_index=cell_index,
77 cell_index=cell_index,
87 index=index,
78 index=index,
88 extension=out_type)
79 extension=out_type)
89
80
90 #On the cell, make the figure available via
81 #On the cell, make the figure available via
91 # cell.outputs[i].svg_filename ... etc (svg in example)
82 # cell.outputs[i].svg_filename ... etc (svg in example)
92 # Where
83 # Where
93 # cell.outputs[i].svg contains the data
84 # cell.outputs[i].svg contains the data
94 out[out_type + '_filename'] = figure_name
85 out[out_type + '_filename'] = figure_name
95
86
96 #In the resources, make the figure available via
87 #In the resources, make the figure available via
97 # resources['figures']['filename'] = data
88 # resources['figures']['filename'] = data
98 resources['figures'][figure_name] = data
89 resources['figures'][figure_name] = data
99
90
100 return cell, resources
91 return cell, resources
@@ -1,261 +1,261
1 """Module that allows custom Sphinx parameters to be set on the notebook and
1 """Module that allows custom Sphinx parameters to be set on the notebook and
2 on the 'other' object passed into Jinja. Called prior to Jinja conversion
2 on the 'other' object passed into Jinja. Called prior to Jinja conversion
3 process.
3 process.
4 """
4 """
5 #-----------------------------------------------------------------------------
5 #-----------------------------------------------------------------------------
6 # Copyright (c) 2013, the IPython Development Team.
6 # Copyright (c) 2013, the IPython Development Team.
7 #
7 #
8 # Distributed under the terms of the Modified BSD License.
8 # Distributed under the terms of the Modified BSD License.
9 #
9 #
10 # The full license is in the file COPYING.txt, distributed with this software.
10 # The full license is in the file COPYING.txt, distributed with this software.
11 #-----------------------------------------------------------------------------
11 #-----------------------------------------------------------------------------
12
12
13 #-----------------------------------------------------------------------------
13 #-----------------------------------------------------------------------------
14 # Imports
14 # Imports
15 #-----------------------------------------------------------------------------
15 #-----------------------------------------------------------------------------
16
16
17 from __future__ import print_function, absolute_import
17 from __future__ import print_function, absolute_import
18
18
19 # Stdlib imports
19 # Stdlib imports
20 # Used to find Sphinx package location
20 # Used to find Sphinx package location
21 import sphinx
21 import sphinx
22 import os.path
22 import os.path
23
23
24 # Used to set the default date to today's date
24 # Used to set the default date to today's date
25 from datetime import date
25 from datetime import date
26
26
27 # Third-party imports
27 # Third-party imports
28 # Needed for Pygments latex definitions.
28 # Needed for Pygments latex definitions.
29 from pygments.formatters import LatexFormatter
29 from pygments.formatters import LatexFormatter
30
30
31 # Our own imports
31 # Our own imports
32 # Configurable traitlets
32 # Configurable traitlets
33 from IPython.utils.traitlets import Unicode, Bool
33 from IPython.utils.traitlets import Unicode, Bool
34
34
35 # Needed to override transformer
35 # Needed to override transformer
36 from .activatable import (ActivatableTransformer) #TODO
36 from .activatable import (ActivatableTransformer) #TODO
37
37
38 from IPython.nbconvert.utils import console
38 from IPython.nbconvert.utils import console
39
39
40 #-----------------------------------------------------------------------------
40 #-----------------------------------------------------------------------------
41 # Classes and functions
41 # Classes and functions
42 #-----------------------------------------------------------------------------
42 #-----------------------------------------------------------------------------
43
43
44 class SphinxTransformer(ActivatableTransformer):
44 class SphinxTransformer(ActivatableTransformer):
45 """
45 """
46 Sphinx utility transformer.
46 Sphinx utility transformer.
47
47
48 This transformer is used to set variables needed by the latex to build
48 This transformer is used to set variables needed by the latex to build
49 Sphinx stylized templates.
49 Sphinx stylized templates.
50 """
50 """
51
51
52 interactive = Bool(False, config=True, help="""
52 interactive = Bool(False, config=True, help="""
53 Allows you to define whether or not the Sphinx exporter will prompt
53 Allows you to define whether or not the Sphinx exporter will prompt
54 you for input during the conversion process. If this is set to false,
54 you for input during the conversion process. If this is set to false,
55 the author, version, release, date, and chapter_style traits should
55 the author, version, release, date, and chapter_style traits should
56 be set.
56 be set.
57 """)
57 """)
58
58
59 author = Unicode("Unknown Author", config=True, help="Author name")
59 author = Unicode("Unknown Author", config=True, help="Author name")
60
60
61 version = Unicode("", config=True, help="""
61 version = Unicode("", config=True, help="""
62 Version number
62 Version number
63 You can leave this blank if you do not want to render a version number.
63 You can leave this blank if you do not want to render a version number.
64 Example: "1.0.0"
64 Example: "1.0.0"
65 """)
65 """)
66
66
67 release = Unicode("", config=True, help="""
67 release = Unicode("", config=True, help="""
68 Release name
68 Release name
69 You can leave this blank if you do not want to render a release name.
69 You can leave this blank if you do not want to render a release name.
70 Example: "Rough Draft"
70 Example: "Rough Draft"
71 """)
71 """)
72
72
73 publish_date = Unicode("", config=True, help="""
73 publish_date = Unicode("", config=True, help="""
74 Publish date
74 Publish date
75 This is the date to render on the document as the publish date.
75 This is the date to render on the document as the publish date.
76 Leave this blank to default to todays date.
76 Leave this blank to default to todays date.
77 Example: "June 12, 1990"
77 Example: "June 12, 1990"
78 """)
78 """)
79
79
80 chapter_style = Unicode("Bjarne", config=True, help="""
80 chapter_style = Unicode("Bjarne", config=True, help="""
81 Sphinx chapter style
81 Sphinx chapter style
82 This is the style to use for the chapter headers in the document.
82 This is the style to use for the chapter headers in the document.
83 You may choose one of the following:
83 You may choose one of the following:
84 "Bjarne" (default)
84 "Bjarne" (default)
85 "Lenny"
85 "Lenny"
86 "Glenn"
86 "Glenn"
87 "Conny"
87 "Conny"
88 "Rejne"
88 "Rejne"
89 "Sonny" (used for international documents)
89 "Sonny" (used for international documents)
90 """)
90 """)
91
91
92 output_style = Unicode("notebook", config=True, help="""
92 output_style = Unicode("notebook", config=True, help="""
93 Nbconvert Ipython
93 Nbconvert Ipython
94 notebook input/output formatting style.
94 notebook input/output formatting style.
95 You may choose one of the following:
95 You may choose one of the following:
96 "simple (recommended for long code segments)"
96 "simple (recommended for long code segments)"
97 "notebook" (default)
97 "notebook" (default)
98 """)
98 """)
99
99
100 center_output = Bool(False, config=True, help="""
100 center_output = Bool(False, config=True, help="""
101 Optional attempt to center all output. If this is false, no additional
101 Optional attempt to center all output. If this is false, no additional
102 formatting is applied.
102 formatting is applied.
103 """)
103 """)
104
104
105 use_headers = Bool(True, config=True, help="""
105 use_headers = Bool(True, config=True, help="""
106 Whether not a header should be added to the document.
106 Whether not a header should be added to the document.
107 """)
107 """)
108
108
109 #Allow the user to override the title of the notebook (useful for
109 #Allow the user to override the title of the notebook (useful for
110 #fancy document titles that the file system doesn't support.)
110 #fancy document titles that the file system doesn't support.)
111 overridetitle = Unicode("", config=True, help="")
111 overridetitle = Unicode("", config=True, help="")
112
112
113
113
114 def call(self, nb, resources):
114 def call(self, nb, resources):
115 """
115 """
116 Sphinx transformation to apply on each notebook.
116 Sphinx transformation to apply on each notebook.
117
117
118 Parameters
118 Parameters
119 ----------
119 ----------
120 nb : NotebookNode
120 nb : NotebookNode
121 Notebook being converted
121 Notebook being converted
122 resources : dictionary
122 resources : dictionary
123 Additional resources used in the conversion process. Allows
123 Additional resources used in the conversion process. Allows
124 transformers to pass variables into the Jinja engine.
124 transformers to pass variables into the Jinja engine.
125 """
125 """
126
126
127 # TODO: Add versatile method of additional notebook metadata. Include
127 # TODO: Add versatile method of additional notebook metadata. Include
128 # handling of multiple files. For now use a temporay namespace,
128 # handling of multiple files. For now use a temporay namespace,
129 # '_draft' to signify that this needs to change.
129 # '_draft' to signify that this needs to change.
130 if not "_draft" in nb.metadata:
130 if not "_draft" in nb.metadata:
131 nb.metadata._draft = {}
131 nb.metadata._draft = {}
132
132 #TODO: Remove draft, and nb
133 if not "sphinx" in resources:
133 if not "sphinx" in resources:
134 resources["sphinx"] = {}
134 resources["sphinx"] = {}
135
135
136 if self.interactive:
136 if self.interactive:
137
137
138 # Prompt the user for additional meta data that doesn't exist currently
138 # Prompt the user for additional meta data that doesn't exist currently
139 # but would be usefull for Sphinx.
139 # but would be usefull for Sphinx.
140 nb.metadata._draft["author"] = self._prompt_author()
140 nb.metadata._draft["author"] = self._prompt_author()
141 nb.metadata._draft["version"] = self._prompt_version()
141 nb.metadata._draft["version"] = self._prompt_version()
142 nb.metadata._draft["release"] = self._prompt_release()
142 nb.metadata._draft["release"] = self._prompt_release()
143 nb.metadata._draft["date"] = self._prompt_date()
143 nb.metadata._draft["date"] = self._prompt_date()
144
144
145 # Prompt the user for the document style.
145 # Prompt the user for the document style.
146 resources["sphinx"]["chapterstyle"] = self._prompt_chapter_title_style()
146 resources["sphinx"]["chapterstyle"] = self._prompt_chapter_title_style()
147 resources["sphinx"]["outputstyle"] = self._prompt_output_style()
147 resources["sphinx"]["outputstyle"] = self._prompt_output_style()
148
148
149 # Small options
149 # Small options
150 resources["sphinx"]["centeroutput"] = console.prompt_boolean("Do you want to center the output? (false)", False)
150 resources["sphinx"]["centeroutput"] = console.prompt_boolean("Do you want to center the output? (false)", False)
151 resources["sphinx"]["header"] = console.prompt_boolean("Should a Sphinx document header be used? (true)", True)
151 resources["sphinx"]["header"] = console.prompt_boolean("Should a Sphinx document header be used? (true)", True)
152 else:
152 else:
153
153
154 # Try to use the traitlets.
154 # Try to use the traitlets.
155 nb.metadata._draft["author"] = self.author
155 nb.metadata._draft["author"] = self.author
156 nb.metadata._draft["version"] = self.version
156 nb.metadata._draft["version"] = self.version
157 nb.metadata._draft["release"] = self.release
157 nb.metadata._draft["release"] = self.release
158
158
159 # Use todays date if none is provided.
159 # Use todays date if none is provided.
160 if len(self.publish_date.strip()) == 0:
160 if len(self.publish_date.strip()) == 0:
161 nb.metadata._draft["date"] = date.today().strftime("%B %d, %Y")
161 nb.metadata._draft["date"] = date.today().strftime("%B %d, %Y")
162 else:
162 else:
163 nb.metadata._draft["date"] = self.publish_date
163 nb.metadata._draft["date"] = self.publish_date
164
164
165 # Sphinx traitlets.
165 # Sphinx traitlets.
166 resources["sphinx"]["chapterstyle"] = self.chapter_style
166 resources["sphinx"]["chapterstyle"] = self.chapter_style
167 resources["sphinx"]["outputstyle"] = self.output_style
167 resources["sphinx"]["outputstyle"] = self.output_style
168 resources["sphinx"]["centeroutput"] = self.center_output
168 resources["sphinx"]["centeroutput"] = self.center_output
169 resources["sphinx"]["header"] = self.use_headers
169 resources["sphinx"]["header"] = self.use_headers
170
170
171 # Find and pass in the path to the Sphinx dependencies.
171 # Find and pass in the path to the Sphinx dependencies.
172 resources["sphinx"]["texinputs"] = os.path.realpath(os.path.join(sphinx.__file__, "..", "texinputs"))
172 resources["sphinx"]["texinputs"] = os.path.realpath(os.path.join(sphinx.__file__, "..", "texinputs"))
173
173
174 # Generate Pygments definitions for Latex
174 # Generate Pygments definitions for Latex
175 resources["sphinx"]["pygment_definitions"] = self._generate_pygments_latex_def()
175 resources["sphinx"]["pygment_definitions"] = self._generate_pygments_latex_def()
176
176
177 if not (self.overridetitle == None or len(self.overridetitle.strip()) == 0):
177 if not (self.overridetitle == None or len(self.overridetitle.strip()) == 0):
178 nb.metadata.name = self.overridetitle
178 nb.metadata.name = self.overridetitle
179
179
180 # End
180 # End
181 return nb, resources
181 return nb, resources
182
182
183
183
184 def _generate_pygments_latex_def(self):
184 def _generate_pygments_latex_def(self):
185 """
185 """
186 Generate the pygments latex definitions that allows pygments
186 Generate the pygments latex definitions that allows pygments
187 to work in latex.
187 to work in latex.
188 """
188 """
189
189
190 return LatexFormatter().get_style_defs()
190 return LatexFormatter().get_style_defs()
191
191
192
192
193 def _prompt_author(self):
193 def _prompt_author(self):
194 """
194 """
195 Prompt the user to input an Author name
195 Prompt the user to input an Author name
196 """
196 """
197 return console.input("Author name: ")
197 return console.input("Author name: ")
198
198
199
199
200 def _prompt_version(self):
200 def _prompt_version(self):
201 """
201 """
202 prompt the user to enter a version number
202 prompt the user to enter a version number
203 """
203 """
204 return console.input("Version (ie ""1.0.0""): ")
204 return console.input("Version (ie ""1.0.0""): ")
205
205
206
206
207 def _prompt_release(self):
207 def _prompt_release(self):
208 """
208 """
209 Prompt the user to input a release name
209 Prompt the user to input a release name
210 """
210 """
211
211
212 return console.input("Release Name (ie ""Rough draft""): ")
212 return console.input("Release Name (ie ""Rough draft""): ")
213
213
214
214
215 def _prompt_date(self):
215 def _prompt_date(self):
216 """
216 """
217 Prompt the user to enter a date
217 Prompt the user to enter a date
218 """
218 """
219
219
220 default_date = date.today().strftime("%B %d, %Y")
220 default_date = date.today().strftime("%B %d, %Y")
221 user_date = console.input("Date (deafults to \"" + default_date + "\"): ")
221 user_date = console.input("Date (deafults to \"" + default_date + "\"): ")
222 if len(user_date.strip()) == 0:
222 if len(user_date.strip()) == 0:
223 user_date = default_date
223 user_date = default_date
224 return user_date
224 return user_date
225
225
226
226
227 def _prompt_output_style(self):
227 def _prompt_output_style(self):
228 """
228 """
229 Prompts the user to pick an IPython output style.
229 Prompts the user to pick an IPython output style.
230 """
230 """
231
231
232 # Dictionary of available output styles
232 # Dictionary of available output styles
233 styles = {1: "simple",
233 styles = {1: "simple",
234 2: "notebook"}
234 2: "notebook"}
235
235
236 #Append comments to the menu when displaying it to the user.
236 #Append comments to the menu when displaying it to the user.
237 comments = {1: "(recommended for long code segments)",
237 comments = {1: "(recommended for long code segments)",
238 2: "(default)"}
238 2: "(default)"}
239
239
240 return console.prompt_dictionary(styles, default_style=2, menu_comments=comments)
240 return console.prompt_dictionary(styles, default_style=2, menu_comments=comments)
241
241
242
242
243 def _prompt_chapter_title_style(self):
243 def _prompt_chapter_title_style(self):
244 """
244 """
245 Prompts the user to pick a Sphinx chapter style
245 Prompts the user to pick a Sphinx chapter style
246 """
246 """
247
247
248 # Dictionary of available Sphinx styles
248 # Dictionary of available Sphinx styles
249 styles = {1: "Bjarne",
249 styles = {1: "Bjarne",
250 2: "Lenny",
250 2: "Lenny",
251 3: "Glenn",
251 3: "Glenn",
252 4: "Conny",
252 4: "Conny",
253 5: "Rejne",
253 5: "Rejne",
254 6: "Sonny"}
254 6: "Sonny"}
255
255
256 #Append comments to the menu when displaying it to the user.
256 #Append comments to the menu when displaying it to the user.
257 comments = {1: "(default)",
257 comments = {1: "(default)",
258 6: "(for international documents)"}
258 6: "(for international documents)"}
259
259
260 return console.prompt_dictionary(styles, menu_comments=comments)
260 return console.prompt_dictionary(styles, menu_comments=comments)
261
261
General Comments 0
You need to be logged in to leave comments. Login now