Show More
@@ -0,0 +1,14 b'' | |||||
|
1 | """Generic script exporter class for any kernel language""" | |||
|
2 | ||||
|
3 | from .templateexporter import TemplateExporter | |||
|
4 | ||||
|
5 | class ScriptExporter(TemplateExporter): | |||
|
6 | def _template_file_default(self): | |||
|
7 | return 'script' | |||
|
8 | ||||
|
9 | def from_notebook_node(self, nb, resources=None, **kw): | |||
|
10 | langinfo = nb.metadata.get('language_info', {}) | |||
|
11 | self.file_extension = langinfo.get('file_extension', '.txt') | |||
|
12 | self.output_mimetype = langinfo.get('mimetype', 'text/plain') | |||
|
13 | ||||
|
14 | return super(ScriptExporter, self).from_notebook_node(nb, resources, **kw) |
@@ -0,0 +1,5 b'' | |||||
|
1 | {%- extends 'null.tpl' -%} | |||
|
2 | ||||
|
3 | {% block input %} | |||
|
4 | {{ cell.source }} | |||
|
5 | {% endblock input %} |
@@ -43,7 +43,7 b' def respond_zip(handler, name, output, resources):' | |||||
43 | # Prepare the zip file |
|
43 | # Prepare the zip file | |
44 | buffer = io.BytesIO() |
|
44 | buffer = io.BytesIO() | |
45 | zipf = zipfile.ZipFile(buffer, mode='w', compression=zipfile.ZIP_DEFLATED) |
|
45 | zipf = zipfile.ZipFile(buffer, mode='w', compression=zipfile.ZIP_DEFLATED) | |
46 |
output_filename = os.path.splitext(name)[0] + |
|
46 | output_filename = os.path.splitext(name)[0] + resources['output_extension'] | |
47 | zipf.writestr(output_filename, cast_bytes(output, 'utf-8')) |
|
47 | zipf.writestr(output_filename, cast_bytes(output, 'utf-8')) | |
48 | for filename, data in output_files.items(): |
|
48 | for filename, data in output_files.items(): | |
49 | zipf.writestr(os.path.basename(filename), data) |
|
49 | zipf.writestr(os.path.basename(filename), data) | |
@@ -96,7 +96,7 b' class NbconvertFileHandler(IPythonHandler):' | |||||
96 |
|
96 | |||
97 | # Force download if requested |
|
97 | # Force download if requested | |
98 | if self.get_argument('download', 'false').lower() == 'true': |
|
98 | if self.get_argument('download', 'false').lower() == 'true': | |
99 |
filename = os.path.splitext(name)[0] + |
|
99 | filename = os.path.splitext(name)[0] + resources['output_extension'] | |
100 | self.set_header('Content-Disposition', |
|
100 | self.set_header('Content-Disposition', | |
101 | 'attachment; filename="%s"' % filename) |
|
101 | 'attachment; filename="%s"' % filename) | |
102 |
|
102 |
@@ -69,9 +69,6 b' define([' | |||||
69 | MenuBar.prototype._nbconvert = function (format, download) { |
|
69 | MenuBar.prototype._nbconvert = function (format, download) { | |
70 | download = download || false; |
|
70 | download = download || false; | |
71 | var notebook_path = this.notebook.notebook_path; |
|
71 | var notebook_path = this.notebook.notebook_path; | |
72 | if (this.notebook.dirty) { |
|
|||
73 | this.notebook.save_notebook({async : false}); |
|
|||
74 | } |
|
|||
75 | var url = utils.url_join_encode( |
|
72 | var url = utils.url_join_encode( | |
76 | this.base_url, |
|
73 | this.base_url, | |
77 | 'nbconvert', |
|
74 | 'nbconvert', | |
@@ -79,7 +76,14 b' define([' | |||||
79 | notebook_path |
|
76 | notebook_path | |
80 | ) + "?download=" + download.toString(); |
|
77 | ) + "?download=" + download.toString(); | |
81 |
|
78 | |||
82 |
window.open( |
|
79 | var w = window.open() | |
|
80 | if (this.notebook.dirty) { | |||
|
81 | this.notebook.save_notebook().then(function() { | |||
|
82 | w.location = url; | |||
|
83 | }); | |||
|
84 | } else { | |||
|
85 | w.location = url; | |||
|
86 | } | |||
83 | }; |
|
87 | }; | |
84 |
|
88 | |||
85 | MenuBar.prototype.bind_events = function () { |
|
89 | MenuBar.prototype.bind_events = function () { | |
@@ -129,10 +133,6 b' define([' | |||||
129 | that._nbconvert('html', false); |
|
133 | that._nbconvert('html', false); | |
130 | }); |
|
134 | }); | |
131 |
|
135 | |||
132 | this.element.find('#download_py').click(function () { |
|
|||
133 | that._nbconvert('python', true); |
|
|||
134 | }); |
|
|||
135 |
|
||||
136 | this.element.find('#download_html').click(function () { |
|
136 | this.element.find('#download_html').click(function () { | |
137 | that._nbconvert('html', true); |
|
137 | that._nbconvert('html', true); | |
138 | }); |
|
138 | }); | |
@@ -308,6 +308,16 b' define([' | |||||
308 | this.events.on('checkpoint_created.Notebook', function (event, data) { |
|
308 | this.events.on('checkpoint_created.Notebook', function (event, data) { | |
309 | that.update_restore_checkpoint(that.notebook.checkpoints); |
|
309 | that.update_restore_checkpoint(that.notebook.checkpoints); | |
310 | }); |
|
310 | }); | |
|
311 | ||||
|
312 | this.events.on('notebook_loaded.Notebook', function() { | |||
|
313 | var langinfo = that.notebook.metadata.language_info || {}; | |||
|
314 | that.update_nbconvert_script(langinfo); | |||
|
315 | }); | |||
|
316 | ||||
|
317 | this.events.on('kernel_ready.Kernel', function(event, data) { | |||
|
318 | var langinfo = data.kernel.info_reply.language_info || {}; | |||
|
319 | that.update_nbconvert_script(langinfo); | |||
|
320 | }); | |||
311 | }; |
|
321 | }; | |
312 |
|
322 | |||
313 | MenuBar.prototype.update_restore_checkpoint = function(checkpoints) { |
|
323 | MenuBar.prototype.update_restore_checkpoint = function(checkpoints) { | |
@@ -341,6 +351,31 b' define([' | |||||
341 | }); |
|
351 | }); | |
342 | }; |
|
352 | }; | |
343 |
|
353 | |||
|
354 | MenuBar.prototype.update_nbconvert_script = function(langinfo) { | |||
|
355 | // Set the 'Download as foo' menu option for the relevant language. | |||
|
356 | var el = this.element.find('#download_script'); | |||
|
357 | var that = this; | |||
|
358 | ||||
|
359 | // Set menu entry text to e.g. "Python (.py)" | |||
|
360 | var langname = (langinfo.name || 'Script') | |||
|
361 | langname = langname.charAt(0).toUpperCase()+langname.substr(1) // Capitalise | |||
|
362 | el.find('a').text(langname + ' ('+(langinfo.file_extension || 'txt')+')'); | |||
|
363 | ||||
|
364 | // Unregister any previously registered handlers | |||
|
365 | el.off('click'); | |||
|
366 | if (langinfo.nbconvert_exporter) { | |||
|
367 | // Metadata specifies a specific exporter, e.g. 'python' | |||
|
368 | el.click(function() { | |||
|
369 | that._nbconvert(langinfo.nbconvert_exporter, true); | |||
|
370 | }); | |||
|
371 | } else { | |||
|
372 | // Use generic 'script' exporter | |||
|
373 | el.click(function() { | |||
|
374 | that._nbconvert('script', true); | |||
|
375 | }); | |||
|
376 | } | |||
|
377 | }; | |||
|
378 | ||||
344 | // Backwards compatability. |
|
379 | // Backwards compatability. | |
345 | IPython.MenuBar = MenuBar; |
|
380 | IPython.MenuBar = MenuBar; | |
346 |
|
381 |
@@ -1944,7 +1944,7 b' define([' | |||||
1944 | var start = new Date().getTime(); |
|
1944 | var start = new Date().getTime(); | |
1945 |
|
1945 | |||
1946 | var that = this; |
|
1946 | var that = this; | |
1947 | this.contents.save(this.notebook_path, model).then( |
|
1947 | return this.contents.save(this.notebook_path, model).then( | |
1948 | $.proxy(this.save_notebook_success, this, start), |
|
1948 | $.proxy(this.save_notebook_success, this, start), | |
1949 | function (error) { |
|
1949 | function (error) { | |
1950 | that.events.trigger('notebook_save_failed.Notebook', error); |
|
1950 | that.events.trigger('notebook_save_failed.Notebook', error); |
@@ -105,7 +105,7 b' class="notebook_app"' | |||||
105 | <li class="dropdown-submenu"><a href="#">Download as</a> |
|
105 | <li class="dropdown-submenu"><a href="#">Download as</a> | |
106 | <ul class="dropdown-menu"> |
|
106 | <ul class="dropdown-menu"> | |
107 | <li id="download_ipynb"><a href="#">IPython Notebook (.ipynb)</a></li> |
|
107 | <li id="download_ipynb"><a href="#">IPython Notebook (.ipynb)</a></li> | |
108 |
<li id="download_ |
|
108 | <li id="download_script"><a href="#">Script</a></li> | |
109 | <li id="download_html"><a href="#">HTML (.html)</a></li> |
|
109 | <li id="download_html"><a href="#">HTML (.html)</a></li> | |
110 | <li id="download_rst"><a href="#">reST (.rst)</a></li> |
|
110 | <li id="download_rst"><a href="#">reST (.rst)</a></li> | |
111 | <li id="download_pdf"><a href="#">PDF (.pdf)</a></li> |
|
111 | <li id="download_pdf"><a href="#">PDF (.pdf)</a></li> |
@@ -75,6 +75,8 b' class IPythonKernel(KernelBase):' | |||||
75 | 'codemirror_mode': {'name': 'ipython', |
|
75 | 'codemirror_mode': {'name': 'ipython', | |
76 | 'version': sys.version_info[0]}, |
|
76 | 'version': sys.version_info[0]}, | |
77 | 'pygments_lexer': 'ipython%d' % (3 if PY3 else 2), |
|
77 | 'pygments_lexer': 'ipython%d' % (3 if PY3 else 2), | |
|
78 | 'nbconvert_exporter': 'python', | |||
|
79 | 'file_extension': '.py' | |||
78 | } |
|
80 | } | |
79 | @property |
|
81 | @property | |
80 | def banner(self): |
|
82 | def banner(self): |
@@ -19,6 +19,7 b' from .markdown import MarkdownExporter' | |||||
19 | from .python import PythonExporter |
|
19 | from .python import PythonExporter | |
20 | from .rst import RSTExporter |
|
20 | from .rst import RSTExporter | |
21 | from .notebook import NotebookExporter |
|
21 | from .notebook import NotebookExporter | |
|
22 | from .script import ScriptExporter | |||
22 |
|
23 | |||
23 | #----------------------------------------------------------------------------- |
|
24 | #----------------------------------------------------------------------------- | |
24 | # Classes |
|
25 | # Classes | |
@@ -74,6 +75,7 b' __all__ = [' | |||||
74 | 'export_pdf', |
|
75 | 'export_pdf', | |
75 | 'export_markdown', |
|
76 | 'export_markdown', | |
76 | 'export_python', |
|
77 | 'export_python', | |
|
78 | 'export_script', | |||
77 | 'export_rst', |
|
79 | 'export_rst', | |
78 | 'export_by_name', |
|
80 | 'export_by_name', | |
79 | 'get_export_names', |
|
81 | 'get_export_names', | |
@@ -132,6 +134,7 b' exporter_map = dict(' | |||||
132 | python=PythonExporter, |
|
134 | python=PythonExporter, | |
133 | rst=RSTExporter, |
|
135 | rst=RSTExporter, | |
134 | notebook=NotebookExporter, |
|
136 | notebook=NotebookExporter, | |
|
137 | script=ScriptExporter, | |||
135 | ) |
|
138 | ) | |
136 |
|
139 | |||
137 | def _make_exporter(name, E): |
|
140 | def _make_exporter(name, E): |
@@ -32,7 +32,7 b' class Exporter(LoggingConfigurable):' | |||||
32 | """ |
|
32 | """ | |
33 |
|
33 | |||
34 | file_extension = Unicode( |
|
34 | file_extension = Unicode( | |
35 | 'txt', config=True, |
|
35 | '.txt', config=True, | |
36 | help="Extension of the file that should be written to disk" |
|
36 | help="Extension of the file that should be written to disk" | |
37 | ) |
|
37 | ) | |
38 |
|
38 |
@@ -32,7 +32,7 b' class HTMLExporter(TemplateExporter):' | |||||
32 | """ |
|
32 | """ | |
33 |
|
33 | |||
34 | def _file_extension_default(self): |
|
34 | def _file_extension_default(self): | |
35 | return 'html' |
|
35 | return '.html' | |
36 |
|
36 | |||
37 | def _default_template_path_default(self): |
|
37 | def _default_template_path_default(self): | |
38 | return os.path.join("..", "templates", "html") |
|
38 | return os.path.join("..", "templates", "html") |
@@ -37,7 +37,7 b' class LatexExporter(TemplateExporter):' | |||||
37 | """ |
|
37 | """ | |
38 |
|
38 | |||
39 | def _file_extension_default(self): |
|
39 | def _file_extension_default(self): | |
40 | return 'tex' |
|
40 | return '.tex' | |
41 |
|
41 | |||
42 | def _template_file_default(self): |
|
42 | def _template_file_default(self): | |
43 | return 'article' |
|
43 | return 'article' |
@@ -135,7 +135,7 b' class PDFExporter(LatexExporter):' | |||||
135 |
|
135 | |||
136 | # convert output extension to pdf |
|
136 | # convert output extension to pdf | |
137 | # the writer above required it to be tex |
|
137 | # the writer above required it to be tex | |
138 | resources['output_extension'] = 'pdf' |
|
138 | resources['output_extension'] = '.pdf' | |
139 |
|
139 | |||
140 | return pdf_data, resources |
|
140 | return pdf_data, resources | |
141 |
|
141 |
@@ -23,7 +23,7 b' class PythonExporter(TemplateExporter):' | |||||
23 | Exports a Python code file. |
|
23 | Exports a Python code file. | |
24 | """ |
|
24 | """ | |
25 | def _file_extension_default(self): |
|
25 | def _file_extension_default(self): | |
26 | return 'py' |
|
26 | return '.py' | |
27 |
|
27 | |||
28 | def _template_file_default(self): |
|
28 | def _template_file_default(self): | |
29 | return 'python' |
|
29 | return 'python' |
@@ -26,7 +26,7 b' class RSTExporter(TemplateExporter):' | |||||
26 | """ |
|
26 | """ | |
27 |
|
27 | |||
28 | def _file_extension_default(self): |
|
28 | def _file_extension_default(self): | |
29 | return 'rst' |
|
29 | return '.rst' | |
30 |
|
30 | |||
31 | def _template_file_default(self): |
|
31 | def _template_file_default(self): | |
32 | return 'rst' |
|
32 | return 'rst' |
@@ -25,7 +25,7 b' class SlidesExporter(HTMLExporter):' | |||||
25 | """Exports HTML slides with reveal.js""" |
|
25 | """Exports HTML slides with reveal.js""" | |
26 |
|
26 | |||
27 | def _file_extension_default(self): |
|
27 | def _file_extension_default(self): | |
28 | return 'slides.html' |
|
28 | return '.slides.html' | |
29 |
|
29 | |||
30 | def _template_file_default(self): |
|
30 | def _template_file_default(self): | |
31 | return 'slides_reveal' |
|
31 | return 'slides_reveal' |
@@ -286,7 +286,7 b' class NbConvertApp(BaseIPythonApplication):' | |||||
286 | # strip duplicate extension from output_base, to avoid Basname.ext.ext |
|
286 | # strip duplicate extension from output_base, to avoid Basname.ext.ext | |
287 | if getattr(exporter, 'file_extension', False): |
|
287 | if getattr(exporter, 'file_extension', False): | |
288 | base, ext = os.path.splitext(self.output_base) |
|
288 | base, ext = os.path.splitext(self.output_base) | |
289 |
if ext == |
|
289 | if ext == exporter.file_extension: | |
290 | self.output_base = base |
|
290 | self.output_base = base | |
291 | notebook_name = self.output_base |
|
291 | notebook_name = self.output_base | |
292 | resources = {} |
|
292 | resources = {} |
@@ -93,7 +93,7 b' class FilesWriter(WriterBase):' | |||||
93 |
|
93 | |||
94 | # Determine where to write conversion results. |
|
94 | # Determine where to write conversion results. | |
95 | if output_extension is not None: |
|
95 | if output_extension is not None: | |
96 |
dest = notebook_name + |
|
96 | dest = notebook_name + output_extension | |
97 | else: |
|
97 | else: | |
98 | dest = notebook_name |
|
98 | dest = notebook_name | |
99 | if self.build_directory: |
|
99 | if self.build_directory: |
@@ -59,7 +59,7 b' class Testfiles(TestsBase):' | |||||
59 | with self.create_temp_cwd(): |
|
59 | with self.create_temp_cwd(): | |
60 |
|
60 | |||
61 | # Create the resoruces dictionary |
|
61 | # Create the resoruces dictionary | |
62 | res = {'output_extension': 'txt'} |
|
62 | res = {'output_extension': '.txt'} | |
63 |
|
63 | |||
64 | # Create files writer, test output |
|
64 | # Create files writer, test output | |
65 | writer = FilesWriter() |
|
65 | writer = FilesWriter() |
@@ -735,6 +735,9 b' Message type: ``kernel_info_reply``::' | |||||
735 | 'language_info': { |
|
735 | 'language_info': { | |
736 | 'mimetype': str, |
|
736 | 'mimetype': str, | |
737 |
|
737 | |||
|
738 | # Extension without the dot, e.g. 'py' | |||
|
739 | 'file_extension': str, | |||
|
740 | ||||
738 | # Pygments lexer, for highlighting |
|
741 | # Pygments lexer, for highlighting | |
739 | # Only needed if it differs from the top level 'language' field. |
|
742 | # Only needed if it differs from the top level 'language' field. | |
740 | 'pygments_lexer': str, |
|
743 | 'pygments_lexer': str, | |
@@ -742,6 +745,11 b' Message type: ``kernel_info_reply``::' | |||||
742 | # Codemirror mode, for for highlighting in the notebook. |
|
745 | # Codemirror mode, for for highlighting in the notebook. | |
743 | # Only needed if it differs from the top level 'language' field. |
|
746 | # Only needed if it differs from the top level 'language' field. | |
744 | 'codemirror_mode': str or dict, |
|
747 | 'codemirror_mode': str or dict, | |
|
748 | ||||
|
749 | # Nbconvert exporter, if notebooks written with this kernel should | |||
|
750 | # be exported with something other than the general 'script' | |||
|
751 | # exporter. | |||
|
752 | 'nbconvert_exporter': str, | |||
745 | }, |
|
753 | }, | |
746 |
|
754 | |||
747 | # A banner of information about the kernel, |
|
755 | # A banner of information about the kernel, |
@@ -38,9 +38,10 b' following methods and attributes:' | |||||
38 |
|
38 | |||
39 | Language information for :ref:`msging_kernel_info` replies, in a dictionary. |
|
39 | Language information for :ref:`msging_kernel_info` replies, in a dictionary. | |
40 | This should contain the key ``mimetype`` with the mimetype of code in the |
|
40 | This should contain the key ``mimetype`` with the mimetype of code in the | |
41 |
target language (e.g. ``'text/x-python'``) |
|
41 | target language (e.g. ``'text/x-python'``), and ``file_extension`` (e.g. | |
42 | ``codemirror_mode`` and ``pygments_lexer`` if they need to differ from |
|
42 | ``'py'``). | |
43 | :attr:`language`. |
|
43 | It may also contain keys ``codemirror_mode`` and ``pygments_lexer`` if they | |
|
44 | need to differ from :attr:`language`. | |||
44 |
|
45 | |||
45 | Other keys may be added to this later. |
|
46 | Other keys may be added to this later. | |
46 |
|
47 |
General Comments 0
You need to be logged in to leave comments.
Login now