##// END OF EJS Templates
added listing of known exporters on error
Paul Ivanov -
Show More
@@ -1,225 +1,233 b''
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
20 20 from .exporter import Exporter
21 21 from .basichtml import BasicHTMLExporter
22 22 from .fullhtml import FullHTMLExporter
23 23 from .latex import LatexExporter
24 24 from .markdown import MarkdownExporter
25 25 from .python import PythonExporter
26 26 from .python_armor import PythonArmorExporter
27 27 from .reveal import RevealExporter
28 28 from .rst import RstExporter
29 29 from .sphinx_howto import SphinxHowtoExporter
30 30 from .sphinx_manual import SphinxManualExporter
31 31
32 32 #-----------------------------------------------------------------------------
33 33 # Classes
34 34 #-----------------------------------------------------------------------------
35 35
36 36 def DocDecorator(f):
37 37
38 38 #Set docstring of function
39 39 f.__doc__ = f.__doc__ + """
40 40 nb : Notebook node
41 41 config : config
42 42 User configuration instance.
43 43 transformers : list[of transformer]
44 44 Custom transformers to apply to the notebook prior to engaging
45 45 the Jinja template engine. Any transformers specified here
46 46 will override existing transformers if a naming conflict
47 47 occurs.
48 48 filters : list[of filter]
49 49 Custom filters to make accessible to the Jinja templates. Any
50 50 filters specified here will override existing filters if a
51 51 naming conflict occurs.
52 52
53 53 Returns
54 54 ----------
55 55 tuple- output, resources, exporter_instance
56 56 output : str
57 57 Jinja 2 output. This is the resulting converted notebook.
58 58 resources : dictionary
59 59 Dictionary of resources used prior to and during the conversion
60 60 process.
61 61 exporter_instance : Exporter
62 62 Instance of the Exporter class used to export the document. Useful
63 63 to caller because it provides a 'file_extension' property which
64 64 specifies what extension the output should be saved as."""
65 65
66 66 @wraps(f)
67 67 def decorator(*args, **kwargs):
68 68 return f(*args, **kwargs)
69 69
70 70 return decorator
71 71
72 72
73 73 #-----------------------------------------------------------------------------
74 74 # Functions
75 75 #-----------------------------------------------------------------------------
76 76
77 77 __all__ = [
78 78 'export',
79 79 'export_sphinx_manual',
80 80 'export_sphinx_howto',
81 81 'export_basic_html',
82 82 'export_full_html',
83 83 'export_latex',
84 84 'export_markdown',
85 85 'export_python',
86 86 'export_python_armor',
87 87 'export_reveal',
88 88 'export_rst',
89 'export_by_name'
89 'export_by_name',
90 'get_export_names'
90 91 ]
91 92
92 93 @DocDecorator
93 94 def export(exporter_type, nb, config=None, transformers=None, filters=None):
94 95 """
95 96 Export a notebook object using specific exporter class.
96 97
97 98 exporter_type : Exporter class type
98 99 Class type of the exporter that should be used. This method
99 100 will initialize it's own instance of the class. It is
100 101 ASSUMED that the class type provided exposes a
101 102 constructor (__init__) with the same signature as the
102 103 base Exporter class.}
103 104 """
104 105
105 106 #Check arguments
106 107 if exporter_type is None:
107 108 raise TypeError("Exporter is None")
108 109 elif not issubclass(exporter_type, Exporter):
109 110 raise TypeError("Exporter type does not inherit from Exporter (base)")
110 111
111 112 if nb is None:
112 113 raise TypeError("nb is None")
113 114
114 115 #Create the exporter
115 116 exporter_instance = exporter_type(preprocessors=transformers,
116 117 jinja_filters=filters, config=config)
117 118
118 119 #Try to convert the notebook using the appropriate conversion function.
119 120 if isinstance(nb, NotebookNode):
120 121 output, resources = exporter_instance.from_notebook_node(nb)
121 122 elif isinstance(nb, basestring):
122 123 output, resources = exporter_instance.from_filename(nb)
123 124 else:
124 125 output, resources = exporter_instance.from_file(nb)
125 126 return output, resources, exporter_instance
126 127
127 128
128 129 @DocDecorator
129 130 def export_sphinx_manual(nb, config=None, transformers=None, filters=None):
130 131 """
131 132 Export a notebook object to Sphinx Manual LaTeX
132 133 """
133 134 return export(SphinxManualExporter, nb, config, transformers, filters)
134 135
135 136
136 137 @DocDecorator
137 138 def export_sphinx_howto(nb, config=None, transformers=None, filters=None):
138 139 """
139 140 Export a notebook object to Sphinx HowTo LaTeX
140 141 """
141 142 return export(SphinxHowtoExporter, nb, config, transformers, filters)
142 143
143 144
144 145 @DocDecorator
145 146 def export_basic_html(nb, config=None, transformers=None, filters=None):
146 147 """
147 148 Export a notebook object to Basic HTML
148 149 """
149 150 return export(BasicHTMLExporter, nb, config, transformers, filters)
150 151
151 152
152 153 @DocDecorator
153 154 def export_full_html(nb, config=None, transformers=None, filters=None):
154 155 """
155 156 Export a notebook object to Full HTML
156 157 """
157 158 return export(FullHTMLExporter, nb, config, transformers, filters)
158 159
159 160
160 161 @DocDecorator
161 162 def export_latex(nb, config=None, transformers=None, filters=None):
162 163 """
163 164 Export a notebook object to LaTeX
164 165 """
165 166 return export(LatexExporter, nb, config, transformers, filters)
166 167
167 168
168 169 @DocDecorator
169 170 def export_markdown(nb, config=None, transformers=None, filters=None):
170 171 """
171 172 Export a notebook object to Markdown
172 173 """
173 174 return export(MarkdownExporter, nb, config, transformers, filters)
174 175
175 176
176 177 @DocDecorator
177 178 def export_python(nb, config=None, transformers=None, filters=None):
178 179 """
179 180 Export a notebook object to Python
180 181 """
181 182 return export(PythonExporter, nb, config, transformers, filters)
182 183
183 184
184 185 @DocDecorator
185 186 def export_python_armor(nb, config=None, transformers=None, filters=None):
186 187 """
187 188 Export a notebook object to Python (Armor)
188 189 """
189 190 return export(PythonArmorExporter, nb, config, transformers, filters)
190 191
191 192
192 193 @DocDecorator
193 194 def export_reveal(nb, config=None, transformers=None, filters=None):
194 195 """
195 196 Export a notebook object to Reveal
196 197 """
197 198 return export(RevealExporter, nb, config, transformers, filters)
198 199
199 200
200 201 @DocDecorator
201 202 def export_rst(nb, config=None, transformers=None, filters=None):
202 203 """
203 204 Export a notebook object to RST
204 205 """
205 206 return export(RstExporter, nb, config, transformers, filters)
206 207
207 208
208 209 @DocDecorator
209 210 def export_by_name(template_name, nb, config=None, transformers=None, filters=None):
210 211 """
211 212 Export a notebook object to a template type by its name. Reflection
212 213 (Inspect) is used to find the template's corresponding explicit export
213 214 method defined in this module. That method is then called directly.
214 215
215 216 template_name : str
216 217 Name of the template style to export to.
217 218 """
218 219
219 220 function_name = "export_" + template_name.lower()
220 221
221 222 if function_name in globals():
222 223 return globals()[function_name](nb, config, transformers, filters)
223 224 else:
224 225 raise NameError("template for `%s` not found" % function_name)
225 226
227 def get_export_names():
228 "Return a list of the currently supported export targets"
229 # grab everything after 'export_'
230 l = [x[len('export_'):] for x in __all__ if x.startswith('export_')]
231 # filter out the one method that is not a template
232 l = [x for x in l if 'by_name' not in x]
233 return sorted(l)
@@ -1,221 +1,226 b''
1 1 #!/usr/bin/env python
2 2 """NBConvert is a utility for conversion of IPYNB files.
3 3
4 4 Commandline interface for the NBConvert conversion utility. Read the
5 5 readme.rst for usage information
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 from __future__ import print_function
21 21 import sys
22 22 import io
23 23 import os
24 24
25 25 #From IPython
26 26 from IPython.config.application import Application
27 27 from IPython.utils.traitlets import Bool, Unicode
28 28
29 from .exporters.export import export_by_name
29 from .exporters.export import export_by_name, get_export_names
30 30 from .exporters.exporter import Exporter
31 31 from .transformers import extractfigure
32 32 from .utils.config import GlobalConfigurable
33 33
34 34 #-----------------------------------------------------------------------------
35 35 #Globals and constants
36 36 #-----------------------------------------------------------------------------
37 37
38 38 #'Keys in resources' user prompt.
39 39 KEYS_PROMPT_HEAD = "====================== Keys in Resources =================================="
40 40 KEYS_PROMPT_BODY = """
41 41 ===========================================================================
42 42 You are responsible for writing these files into the appropriate
43 43 directory(ies) if need be. If you do not want to see this message, enable
44 44 the 'write' (boolean) flag of the converter.
45 45 ===========================================================================
46 46 """
47 47
48 48 _examples = """
49 49 ipython nbconvert rst Untitled0.ipynb # convert ipynb to ReStructured Text
50 50 ipython nbconvert latex Untitled0.ipynb # convert ipynb to LaTeX
51 51 ipython nbconvert reveal Untitled0.ipynb # convert to Reveal (HTML/JS) slideshow
52 52 """
53 53
54 54 #-----------------------------------------------------------------------------
55 55 #Classes and functions
56 56 #-----------------------------------------------------------------------------
57 57
58 58 class NbConvertApp(Application):
59 59 """Application used to convert to and from notebook file type (*.ipynb)"""
60 60 description = Unicode(__doc__)
61 61
62 62 examples = _examples
63 63
64 64 stdout = Bool(
65 65 False, config=True,
66 66 help="""Whether to print the converted IPYNB file to stdout
67 67 use full do diff files without actually writing a new file"""
68 68 )
69 69
70 70 write = Bool(
71 71 True, config=True,
72 72 help="""Should the converted notebook file be written to disk
73 73 along with potential extracted resources."""
74 74 )
75 75
76 76 aliases = {
77 77 'stdout':'NbConvertApp.stdout',
78 78 'write':'NbConvertApp.write',
79 79 }
80 80
81 81 flags = {}
82 82
83 83 flags['stdout'] = (
84 84 {'NbConvertApp' : {'stdout' : True}},
85 85 """Print converted file to stdout, equivalent to --stdout=True
86 86 """
87 87 )
88 88
89 89 flags['no-write'] = (
90 90 {'NbConvertApp' : {'write' : True}},
91 91 """Do not write to disk, equivalent to --write=False
92 92 """
93 93 )
94 94
95 95
96 96 def __init__(self, **kwargs):
97 97 """Public constructor"""
98 98
99 99 #Call base class
100 100 super(NbConvertApp, self).__init__(**kwargs)
101 101
102 102 #Register class here to have help with help all
103 103 self.classes.insert(0, Exporter)
104 104 self.classes.insert(0, GlobalConfigurable)
105 105
106 106
107 107 def start(self, argv=None):
108 108 """Entrypoint of NbConvert application.
109 109
110 110 Parameters
111 111 ----------
112 112 argv : list
113 113 Commandline arguments
114 114 """
115 115
116 116 #Parse the commandline options.
117 117 self.parse_command_line(argv)
118 118
119 119 #Call base
120 120 super(NbConvertApp, self).start()
121 121
122 122 #The last arguments in list will be used by nbconvert
123 123 if len(self.extra_args) is not 3:
124 124 print( "Wrong number of arguments, use --help flag for usage", file=sys.stderr)
125 125 sys.exit(-1)
126 126 export_type = (self.extra_args)[1]
127 127 ipynb_file = (self.extra_args)[2]
128 128
129 129 #Export
130 return_value = export_by_name(export_type, ipynb_file)
131 if return_value is None:
132 print("Error: '%s' template not found." % export_type)
133 return
130 try:
131 return_value = export_by_name(export_type, ipynb_file)
132 except NameError as e:
133 print("Error: '%s' exporter not found." % export_type,
134 file=sys.stderr)
135 print("Known exporters are:",
136 "\n\t" + "\n\t".join(get_export_names()),
137 file=sys.stderr)
138 sys.exit(-1)
134 139 else:
135 140 (output, resources, exporter) = return_value
136 141
137 142 #TODO: Allow user to set output directory and file.
138 143 destination_filename = None
139 144 destination_directory = None
140 145 if self.write:
141 146
142 147 #Get the file name without the '.ipynb' (6 chars) extension and then
143 148 #remove any addition periods and spaces. The resulting name will
144 149 #be used to create the directory that the files will be exported
145 150 #into.
146 151 out_root = ipynb_file[:-6].replace('.', '_').replace(' ', '_')
147 152 destination_filename = os.path.join(out_root+'.'+exporter.file_extension)
148 153
149 154 destination_directory = out_root+'_files'
150 155 if not os.path.exists(destination_directory):
151 156 os.mkdir(destination_directory)
152 157
153 158 #Write the results
154 159 if self.stdout or not (destination_filename is None and destination_directory is None):
155 160 self._write_results(output, resources, destination_filename, destination_directory)
156 161
157 162
158 163 def _write_results(self, output, resources, destination_filename=None, destination_directory=None):
159 164 """Output the conversion results to the console and/or filesystem
160 165
161 166 Parameters
162 167 ----------
163 168 output : str
164 169 Output of conversion
165 170 resources : dictionary
166 171 Additional input/output used by the transformers. For
167 172 example, the ExtractFigure transformer outputs the
168 173 figures it extracts into this dictionary. This method
169 174 relies on the figures being in this dictionary when
170 175 attempting to write the figures to the file system.
171 176 destination_filename : str, Optional
172 177 Filename to write output into. If None, output is not
173 178 written to a file.
174 179 destination_directory : str, Optional
175 180 Directory to write notebook data (i.e. figures) to. If
176 181 None, figures are not written to the file system.
177 182 """
178 183
179 184 if self.stdout:
180 185 print(output.encode('utf-8'))
181 186
182 187 #Write file output from conversion.
183 188 if not destination_filename is None:
184 189 with io.open(destination_filename, 'w') as f:
185 190 f.write(output)
186 191
187 192 #Get the key names used by the extract figure transformer
188 193 figures_key = extractfigure.FIGURES_KEY
189 194 binary_key = extractfigure.BINARY_KEY
190 195 text_key = extractfigure.TEXT_KEY
191 196
192 197 #Output any associate figures into the same "root" directory.
193 198 binkeys = resources.get(figures_key, {}).get(binary_key,{}).keys()
194 199 textkeys = resources.get(figures_key, {}).get(text_key,{}).keys()
195 200 if binkeys or textkeys :
196 201 if not destination_directory is None:
197 202 for key in binkeys:
198 203 with io.open(os.path.join(destination_directory, key), 'wb') as f:
199 204 f.write(resources[figures_key][binary_key][key])
200 205 for key in textkeys:
201 206 with io.open(os.path.join(destination_directory, key), 'w') as f:
202 207 f.write(resources[figures_key][text_key][key])
203 208
204 209 #Figures that weren't exported which will need to be created by the
205 210 #user. Tell the user what figures these are.
206 211 if self.stdout:
207 212 print(KEYS_PROMPT_HEAD, file=sys.stderr)
208 213 print(resources[figures_key].keys(), file=sys.stderr)
209 214 print(KEYS_PROMPT_BODY , file=sys.stderr)
210 215
211 216 #-----------------------------------------------------------------------------
212 217 # Main entry point
213 218 #-----------------------------------------------------------------------------
214 219
215 220 def launch_new_instance():
216 221 """Application entry point"""
217 222
218 223 app = NbConvertApp.instance()
219 224 app.description = __doc__
220 225 app.start(argv=sys.argv)
221 226
General Comments 0
You need to be logged in to leave comments. Login now