Show More
@@ -0,0 +1,79 b'' | |||||
|
1 | """Module containing a transformer that converts outputs in the notebook from | |||
|
2 | one format to another. | |||
|
3 | """ | |||
|
4 | #----------------------------------------------------------------------------- | |||
|
5 | # Copyright (c) 2013, the IPython Development Team. | |||
|
6 | # | |||
|
7 | # Distributed under the terms of the Modified BSD License. | |||
|
8 | # | |||
|
9 | # The full license is in the file COPYING.txt, distributed with this software. | |||
|
10 | #----------------------------------------------------------------------------- | |||
|
11 | ||||
|
12 | #----------------------------------------------------------------------------- | |||
|
13 | # Imports | |||
|
14 | #----------------------------------------------------------------------------- | |||
|
15 | ||||
|
16 | from .base import Transformer | |||
|
17 | from IPython.utils.traitlets import Unicode | |||
|
18 | ||||
|
19 | #----------------------------------------------------------------------------- | |||
|
20 | # Classes | |||
|
21 | #----------------------------------------------------------------------------- | |||
|
22 | ||||
|
23 | class ConvertFiguresTransformer(Transformer): | |||
|
24 | """ | |||
|
25 | Converts all of the outputs in a notebook from one format to another. | |||
|
26 | """ | |||
|
27 | ||||
|
28 | from_format = Unicode(config=True, help='Format the converter accepts') | |||
|
29 | to_format = Unicode(config=True, help='Format the converter writes') | |||
|
30 | ||||
|
31 | def __init__(self, **kw): | |||
|
32 | """ | |||
|
33 | Public constructor | |||
|
34 | """ | |||
|
35 | super(ConvertFiguresTransformer, self).__init__(**kw) | |||
|
36 | ||||
|
37 | ||||
|
38 | def convert_figure(self, data_format, data): | |||
|
39 | raise NotImplementedError() | |||
|
40 | ||||
|
41 | ||||
|
42 | def transform_cell(self, cell, resources, cell_index): | |||
|
43 | """ | |||
|
44 | Apply a transformation on each cell, | |||
|
45 | ||||
|
46 | See base.py | |||
|
47 | """ | |||
|
48 | ||||
|
49 | #Loop through all of the datatypes of the outputs in the cell. | |||
|
50 | for index, cell_out in enumerate(cell.get('outputs', [])): | |||
|
51 | for data_type, data in cell_out.items(): | |||
|
52 | ||||
|
53 | #Get the name of the file exported by the extract figure | |||
|
54 | #transformer. Do not try to convert the figure if the extract | |||
|
55 | #fig transformer hasn't touched it | |||
|
56 | filename = cell_out.get(data_type + '_filename', None) | |||
|
57 | if filename: | |||
|
58 | figure_name = filename[:filename.rfind('.')] | |||
|
59 | self._convert_figure(cell_out, figure_name, resources, data_type, data) | |||
|
60 | return cell, resources | |||
|
61 | ||||
|
62 | ||||
|
63 | def _convert_figure(self, cell_out, resources, figure_name, data_type, data): | |||
|
64 | """ | |||
|
65 | Convert a figure and output the results to the cell output | |||
|
66 | """ | |||
|
67 | ||||
|
68 | if not self.to_format in cell_out: | |||
|
69 | if data_type == self.from_format: | |||
|
70 | filename = figure_name + '.' + self.to_format | |||
|
71 | if filename not in resources['figures']: | |||
|
72 | ||||
|
73 | #On the cell, make the figure available via | |||
|
74 | # cell.outputs[i].pdf_filename ... etc (PDF in example) | |||
|
75 | cell_out[self.to_format + '_filename'] = filename | |||
|
76 | ||||
|
77 | #In the resources, make the figure available via | |||
|
78 | # resources['figures']['filename'] = data | |||
|
79 | resources['figures'][filename] = self.convert_figure(data_type, data) |
@@ -0,0 +1,77 b'' | |||||
|
1 | """Module containing a transformer that converts outputs in the notebook from | |||
|
2 | one format to another. | |||
|
3 | """ | |||
|
4 | #----------------------------------------------------------------------------- | |||
|
5 | # Copyright (c) 2013, the IPython Development Team. | |||
|
6 | # | |||
|
7 | # Distributed under the terms of the Modified BSD License. | |||
|
8 | # | |||
|
9 | # The full license is in the file COPYING.txt, distributed with this software. | |||
|
10 | #----------------------------------------------------------------------------- | |||
|
11 | ||||
|
12 | #----------------------------------------------------------------------------- | |||
|
13 | # Imports | |||
|
14 | #----------------------------------------------------------------------------- | |||
|
15 | ||||
|
16 | import os | |||
|
17 | import sys | |||
|
18 | import subprocess | |||
|
19 | ||||
|
20 | from IPython.utils.tempdir import TemporaryDirectory | |||
|
21 | from IPython.utils.traitlets import Unicode | |||
|
22 | ||||
|
23 | from .convertfigures import ConvertFiguresTransformer | |||
|
24 | ||||
|
25 | ||||
|
26 | #----------------------------------------------------------------------------- | |||
|
27 | # Constants | |||
|
28 | #----------------------------------------------------------------------------- | |||
|
29 | ||||
|
30 | INKSCAPE_COMMAND = 'inkscape --without-gui --export-pdf="{to_filename}" "{from_filename}"' | |||
|
31 | INKSCAPE_OSX_COMMAND = '/Applications/Inkscape.app/Contents/Resources/bin/inkscape --without-gui --export-pdf="{to_filename}" "{from_filename}"' | |||
|
32 | ||||
|
33 | ||||
|
34 | #----------------------------------------------------------------------------- | |||
|
35 | # Classes | |||
|
36 | #----------------------------------------------------------------------------- | |||
|
37 | ||||
|
38 | class SVG2PDFTransformer(ConvertFiguresTransformer): | |||
|
39 | """ | |||
|
40 | Converts all of the outputs in a notebook from one format to another. | |||
|
41 | """ | |||
|
42 | ||||
|
43 | from_format = Unicode('svg', config=True, help='Format the converter accepts') | |||
|
44 | to_format = Unicode('pdf', config=False, help='Format the converter writes') | |||
|
45 | ||||
|
46 | ||||
|
47 | def convert_figure(self, data_format, data): | |||
|
48 | """ | |||
|
49 | Convert a single Svg figure. Returns converted data. | |||
|
50 | """ | |||
|
51 | ||||
|
52 | #Work in a temporary directory | |||
|
53 | with TemporaryDirectory() as tmpdir: | |||
|
54 | ||||
|
55 | #Write fig to temp file | |||
|
56 | input_filename = os.path.join(tmpdir, 'figure.' + data_format) | |||
|
57 | with open(input_filename, 'w') as f: | |||
|
58 | f.write(data) | |||
|
59 | ||||
|
60 | #Determine command (different on Mac OSX) | |||
|
61 | command = INKSCAPE_COMMAND | |||
|
62 | if sys.platform == 'darwin': | |||
|
63 | command = INKSCAPE_OSX_COMMAND | |||
|
64 | ||||
|
65 | #Call conversion application | |||
|
66 | output_filename = os.path.join(tmpdir, 'figure.pdf') | |||
|
67 | shell = command.format(from_filename=input_filename, | |||
|
68 | to_filename=output_filename) | |||
|
69 | subprocess.call(shell, shell=True) #Shell=True okay since input is trusted. | |||
|
70 | ||||
|
71 | #Read output from drive | |||
|
72 | if os.path.isfile(output_filename): | |||
|
73 | with open(output_filename, 'rb') as f: | |||
|
74 | return f.read().encode("base64") #PDF is a nb supported binary | |||
|
75 | #data type, so base64 encode. | |||
|
76 | else: | |||
|
77 | return TypeError("Inkscape svg to png conversion failed") |
@@ -0,0 +1,57 b'' | |||||
|
1 | #!/usr/bin/env python | |||
|
2 | """ | |||
|
3 | Contains writer base class. | |||
|
4 | """ | |||
|
5 | #----------------------------------------------------------------------------- | |||
|
6 | #Copyright (c) 2013, the IPython Development Team. | |||
|
7 | # | |||
|
8 | #Distributed under the terms of the Modified BSD License. | |||
|
9 | # | |||
|
10 | #The full license is in the file COPYING.txt, distributed with this software. | |||
|
11 | #----------------------------------------------------------------------------- | |||
|
12 | ||||
|
13 | #----------------------------------------------------------------------------- | |||
|
14 | # Imports | |||
|
15 | #----------------------------------------------------------------------------- | |||
|
16 | ||||
|
17 | from IPython.utils.traitlets import List | |||
|
18 | ||||
|
19 | from ..utils.base import NbConvertBase | |||
|
20 | ||||
|
21 | #----------------------------------------------------------------------------- | |||
|
22 | # Classes | |||
|
23 | #----------------------------------------------------------------------------- | |||
|
24 | ||||
|
25 | class WriterBase(NbConvertBase): | |||
|
26 | """Consumes output from nbconvert export...() methods and writes to a | |||
|
27 | useful location. """ | |||
|
28 | ||||
|
29 | ||||
|
30 | files = List([], config=True, help=""" | |||
|
31 | List of the files that the notebook references. Files will be | |||
|
32 | included with written output.""") | |||
|
33 | ||||
|
34 | ||||
|
35 | def __init__(self, config=None, **kw): | |||
|
36 | """ | |||
|
37 | Constructor | |||
|
38 | """ | |||
|
39 | super(WriterBase, self).__init__(config=config, **kw) | |||
|
40 | ||||
|
41 | ||||
|
42 | def write(self, output, resources, **kw): | |||
|
43 | """ | |||
|
44 | Consume and write Jinja output. | |||
|
45 | ||||
|
46 | Parameters | |||
|
47 | ---------- | |||
|
48 | output : string | |||
|
49 | Conversion results. This string contains the file contents of the | |||
|
50 | converted file. | |||
|
51 | resources : dict | |||
|
52 | Resources created and filled by the nbconvert conversion process. | |||
|
53 | Includes output from transformers, such as the extract figure | |||
|
54 | transformer. | |||
|
55 | """ | |||
|
56 | ||||
|
57 | raise NotImplementedError() |
@@ -0,0 +1,43 b'' | |||||
|
1 | #!/usr/bin/env python | |||
|
2 | """ | |||
|
3 | Contains debug writer. | |||
|
4 | """ | |||
|
5 | #----------------------------------------------------------------------------- | |||
|
6 | #Copyright (c) 2013, the IPython Development Team. | |||
|
7 | # | |||
|
8 | #Distributed under the terms of the Modified BSD License. | |||
|
9 | # | |||
|
10 | #The full license is in the file COPYING.txt, distributed with this software. | |||
|
11 | #----------------------------------------------------------------------------- | |||
|
12 | ||||
|
13 | #----------------------------------------------------------------------------- | |||
|
14 | # Imports | |||
|
15 | #----------------------------------------------------------------------------- | |||
|
16 | ||||
|
17 | from .base import WriterBase | |||
|
18 | from pprint import pprint | |||
|
19 | ||||
|
20 | #----------------------------------------------------------------------------- | |||
|
21 | # Classes | |||
|
22 | #----------------------------------------------------------------------------- | |||
|
23 | ||||
|
24 | class DebugWriter(WriterBase): | |||
|
25 | """Consumes output from nbconvert export...() methods and writes usefull | |||
|
26 | debugging information to the stdout. The information includes a list of | |||
|
27 | resources that were extracted from the notebook(s) during export.""" | |||
|
28 | ||||
|
29 | ||||
|
30 | def write(self, output, resources, **kw): | |||
|
31 | """ | |||
|
32 | Consume and write Jinja output. | |||
|
33 | ||||
|
34 | See base for more... | |||
|
35 | """ | |||
|
36 | ||||
|
37 | if 'figures' in resources: | |||
|
38 | print("Figures extracted from %s" % notebook_name) | |||
|
39 | print('-' * 80) | |||
|
40 | pprint.pprint(resources['figures'], indent=2, width=70) | |||
|
41 | else: | |||
|
42 | print("No figures extracted from %s" % notebook_name) | |||
|
43 | print('=' * 80) |
@@ -0,0 +1,98 b'' | |||||
|
1 | #!/usr/bin/env python | |||
|
2 | """ | |||
|
3 | Contains writer for writing nbconvert output to filesystem. | |||
|
4 | """ | |||
|
5 | #----------------------------------------------------------------------------- | |||
|
6 | #Copyright (c) 2013, the IPython Development Team. | |||
|
7 | # | |||
|
8 | #Distributed under the terms of the Modified BSD License. | |||
|
9 | # | |||
|
10 | #The full license is in the file COPYING.txt, distributed with this software. | |||
|
11 | #----------------------------------------------------------------------------- | |||
|
12 | ||||
|
13 | #----------------------------------------------------------------------------- | |||
|
14 | # Imports | |||
|
15 | #----------------------------------------------------------------------------- | |||
|
16 | ||||
|
17 | import io | |||
|
18 | import os | |||
|
19 | import shutil | |||
|
20 | import glob | |||
|
21 | ||||
|
22 | from IPython.utils.traitlets import Unicode | |||
|
23 | ||||
|
24 | from .base import WriterBase | |||
|
25 | ||||
|
26 | #----------------------------------------------------------------------------- | |||
|
27 | # Classes | |||
|
28 | #----------------------------------------------------------------------------- | |||
|
29 | ||||
|
30 | class FilesWriter(WriterBase): | |||
|
31 | """Consumes nbconvert output and produces files.""" | |||
|
32 | ||||
|
33 | ||||
|
34 | build_directory = Unicode("nbconvert_build", config=True, | |||
|
35 | help="""Directory to write output to. Leave blank | |||
|
36 | to output to the current directory""") | |||
|
37 | ||||
|
38 | ||||
|
39 | #Make sure that the output directory exists. | |||
|
40 | def _build_directory_changed(self, name, old, new): | |||
|
41 | if new and not os.path.isdir(new): | |||
|
42 | os.makedirs(new) | |||
|
43 | ||||
|
44 | ||||
|
45 | def __init__(self, **kw): | |||
|
46 | super(FilesWriter, self).__init__(**kw) | |||
|
47 | self._build_directory_changed('build_directory', self.build_directory, | |||
|
48 | self.build_directory) | |||
|
49 | ||||
|
50 | ||||
|
51 | def write(self, output, resources, notebook_name=None, **kw): | |||
|
52 | """ | |||
|
53 | Consume and write Jinja output to the file system. Output directory | |||
|
54 | is set via the 'build_directory' variable of this instance (a | |||
|
55 | configurable). | |||
|
56 | ||||
|
57 | See base for more... | |||
|
58 | """ | |||
|
59 | ||||
|
60 | #Pull the extension from the resources dict. | |||
|
61 | output_extension = resources['output_extension'] | |||
|
62 | ||||
|
63 | #Write all of the extracted resources to the destination directory. | |||
|
64 | #NOTE: WE WRITE EVERYTHING AS-IF IT'S BINARY. THE EXTRACT FIG | |||
|
65 | #TRANSFORMER SHOULD HANDLE UNIX/WINDOWS LINE ENDINGS... | |||
|
66 | for filename, data in resources.get('figures', {}).items(): | |||
|
67 | ||||
|
68 | #Determine where to write the file to | |||
|
69 | dest = os.path.join(self.build_directory, filename) | |||
|
70 | ||||
|
71 | #Write file | |||
|
72 | with io.open(dest, 'wb') as f: | |||
|
73 | f.write(data) | |||
|
74 | ||||
|
75 | #Copy referenced files to output directory | |||
|
76 | if self.build_directory: | |||
|
77 | for filename in self.files: | |||
|
78 | ||||
|
79 | #Copy files that match search pattern | |||
|
80 | for matching_filename in glob.glob(filename): | |||
|
81 | ||||
|
82 | #Make sure folder exists. | |||
|
83 | dest = os.path.join(self.build_directory, filename) | |||
|
84 | path = os.path.dirname(dest) | |||
|
85 | if not os.path.isdir(path): | |||
|
86 | os.makedirs(path) | |||
|
87 | ||||
|
88 | #Copy | |||
|
89 | shutil.copyfile(matching_filename, dest) | |||
|
90 | ||||
|
91 | #Determine where to write conversion results. | |||
|
92 | dest = notebook_name + '.' + output_extension | |||
|
93 | if self.build_directory: | |||
|
94 | dest = os.path.join(self.build_directory, dest) | |||
|
95 | ||||
|
96 | #Write conversion results. | |||
|
97 | with io.open(dest, 'w') as f: | |||
|
98 | f.write(output) |
@@ -0,0 +1,37 b'' | |||||
|
1 | #!/usr/bin/env python | |||
|
2 | """ | |||
|
3 | Contains Stdout writer | |||
|
4 | """ | |||
|
5 | #----------------------------------------------------------------------------- | |||
|
6 | #Copyright (c) 2013, the IPython Development Team. | |||
|
7 | # | |||
|
8 | #Distributed under the terms of the Modified BSD License. | |||
|
9 | # | |||
|
10 | #The full license is in the file COPYING.txt, distributed with this software. | |||
|
11 | #----------------------------------------------------------------------------- | |||
|
12 | ||||
|
13 | #----------------------------------------------------------------------------- | |||
|
14 | # Imports | |||
|
15 | #----------------------------------------------------------------------------- | |||
|
16 | ||||
|
17 | from .base import WriterBase | |||
|
18 | ||||
|
19 | #----------------------------------------------------------------------------- | |||
|
20 | # Classes | |||
|
21 | #----------------------------------------------------------------------------- | |||
|
22 | ||||
|
23 | class StdoutWriter(WriterBase): | |||
|
24 | """Consumes output from nbconvert export...() methods and writes to the | |||
|
25 | stdout stream. Allows for quick debuging of nbconvert output. Using the | |||
|
26 | debug flag makes the writer pretty-print the figures contained within the | |||
|
27 | notebook.""" | |||
|
28 | ||||
|
29 | ||||
|
30 | def write(self, output, resources, **kw): | |||
|
31 | """ | |||
|
32 | Consume and write Jinja output. | |||
|
33 | ||||
|
34 | See base for more... | |||
|
35 | """ | |||
|
36 | ||||
|
37 | print(output) |
@@ -3,3 +3,4 b'' | |||||
3 | from .exporters import * |
|
3 | from .exporters import * | |
4 | import filters |
|
4 | import filters | |
5 | import transformers |
|
5 | import transformers | |
|
6 | import writers |
@@ -6,6 +6,6 b' from .reveal import RevealExporter' | |||||
6 | from .latex import LatexExporter |
|
6 | from .latex import LatexExporter | |
7 | from .markdown import MarkdownExporter |
|
7 | from .markdown import MarkdownExporter | |
8 | from .python import PythonExporter |
|
8 | from .python import PythonExporter | |
9 |
from .rst import R |
|
9 | from .rst import RSTExporter | |
10 | from .sphinx_howto import SphinxHowtoExporter |
|
10 | from .sphinx_howto import SphinxHowtoExporter | |
11 | from .sphinx_manual import SphinxManualExporter |
|
11 | from .sphinx_manual import SphinxManualExporter |
@@ -14,9 +14,9 b' Exporter that exports Basic HTML.' | |||||
14 | # Imports |
|
14 | # Imports | |
15 | #----------------------------------------------------------------------------- |
|
15 | #----------------------------------------------------------------------------- | |
16 |
|
16 | |||
17 | from IPython.utils.traitlets import Unicode |
|
17 | from IPython.utils.traitlets import Unicode, List | |
18 |
|
18 | |||
19 | from ..transformers.csshtmlheader import CSSHTMLHeaderTransformer |
|
19 | from IPython.nbconvert import transformers | |
20 |
|
20 | |||
21 | from .exporter import Exporter |
|
21 | from .exporter import Exporter | |
22 |
|
22 | |||
@@ -40,16 +40,3 b' class BasicHTMLExporter(Exporter):' | |||||
40 | template_file = Unicode( |
|
40 | template_file = Unicode( | |
41 | 'basichtml', config=True, |
|
41 | 'basichtml', config=True, | |
42 | help="Name of the template file to use") |
|
42 | help="Name of the template file to use") | |
43 |
|
||||
44 |
|
||||
45 | def _register_transformers(self): |
|
|||
46 | """ |
|
|||
47 | Register all of the transformers needed for this exporter. |
|
|||
48 | """ |
|
|||
49 |
|
||||
50 | #Register the transformers of the base class. |
|
|||
51 | super(BasicHTMLExporter, self)._register_transformers() |
|
|||
52 |
|
||||
53 | #Register CSSHTMLHeaderTransformer transformer |
|
|||
54 | self.register_transformer(CSSHTMLHeaderTransformer) |
|
|||
55 |
|
@@ -16,6 +16,7 b' Module containing single call export functions.' | |||||
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 |
|
20 | |||
20 | from .exporter import Exporter |
|
21 | from .exporter import Exporter | |
21 | from .basichtml import BasicHTMLExporter |
|
22 | from .basichtml import BasicHTMLExporter | |
@@ -24,7 +25,7 b' from .latex import LatexExporter' | |||||
24 | from .markdown import MarkdownExporter |
|
25 | from .markdown import MarkdownExporter | |
25 | from .python import PythonExporter |
|
26 | from .python import PythonExporter | |
26 | from .reveal import RevealExporter |
|
27 | from .reveal import RevealExporter | |
27 |
from .rst import R |
|
28 | from .rst import RSTExporter | |
28 | from .sphinx_howto import SphinxHowtoExporter |
|
29 | from .sphinx_howto import SphinxHowtoExporter | |
29 | from .sphinx_manual import SphinxManualExporter |
|
30 | from .sphinx_manual import SphinxManualExporter | |
30 |
|
31 | |||
@@ -32,22 +33,15 b' from .sphinx_manual import SphinxManualExporter' | |||||
32 | # Classes |
|
33 | # Classes | |
33 | #----------------------------------------------------------------------------- |
|
34 | #----------------------------------------------------------------------------- | |
34 |
|
35 | |||
35 |
def DocDecorator(f): |
|
36 | def DocDecorator(f): | |
36 |
|
37 | |||
37 | #Set docstring of function |
|
38 | #Set docstring of function | |
38 | f.__doc__ = f.__doc__ + """ |
|
39 | f.__doc__ = f.__doc__ + """ | |
39 | nb : Notebook node |
|
40 | nb : Notebook node | |
40 | config : config |
|
41 | config : config (optional, keyword arg) | |
41 | User configuration instance. |
|
42 | User configuration instance. | |
42 | transformers : list[of transformer] |
|
43 | resources : dict (optional, keyword arg) | |
43 | Custom transformers to apply to the notebook prior to engaging |
|
44 | Resources used in the conversion process. | |
44 | the Jinja template engine. Any transformers specified here |
|
|||
45 | will override existing transformers if a naming conflict |
|
|||
46 | occurs. |
|
|||
47 | filters : list[of filter] |
|
|||
48 | Custom filters to make accessible to the Jinja templates. Any |
|
|||
49 | filters specified here will override existing filters if a |
|
|||
50 | naming conflict occurs. |
|
|||
51 |
|
45 | |||
52 | Returns |
|
46 | Returns | |
53 | ---------- |
|
47 | ---------- | |
@@ -85,139 +79,148 b' __all__ = [' | |||||
85 | 'export_reveal', |
|
79 | 'export_reveal', | |
86 | 'export_rst', |
|
80 | 'export_rst', | |
87 | 'export_by_name', |
|
81 | 'export_by_name', | |
88 | 'get_export_names' |
|
82 | 'get_export_names', | |
|
83 | 'ExporterNameError' | |||
89 | ] |
|
84 | ] | |
90 |
|
85 | |||
|
86 | ||||
|
87 | class ExporterNameError(NameError): | |||
|
88 | pass | |||
|
89 | ||||
|
90 | ||||
91 | @DocDecorator |
|
91 | @DocDecorator | |
92 | def export(exporter_type, nb, config=None, transformers=None, filters=None): |
|
92 | def export(exporter, nb, **kw): | |
93 | """ |
|
93 | """ | |
94 | Export a notebook object using specific exporter class. |
|
94 | Export a notebook object using specific exporter class. | |
95 |
|
95 | |||
96 |
exporter |
|
96 | exporter : Exporter class type or instance | |
97 |
Class type of the exporter that should be used. |
|
97 | Class type or instance of the exporter that should be used. If the | |
98 |
|
|
98 | method initializes it's own instance of the class, it is ASSUMED that | |
99 |
|
|
99 | the class type provided exposes a constructor (__init__) with the same | |
100 | constructor (__init__) with the same signature as the |
|
100 | signature as the base Exporter class. | |
101 | base Exporter class.} |
|
|||
102 | """ |
|
101 | """ | |
103 |
|
102 | |||
104 | #Check arguments |
|
103 | #Check arguments | |
105 |
if exporter |
|
104 | if exporter is None: | |
106 | raise TypeError("Exporter is None") |
|
105 | raise TypeError("Exporter is None") | |
107 |
elif not issubclass(exporter |
|
106 | elif not isinstance(exporter, Exporter) and not issubclass(exporter, Exporter): | |
108 |
raise TypeError(" |
|
107 | raise TypeError("exporter does not inherit from Exporter (base)") | |
109 |
|
||||
110 | if nb is None: |
|
108 | if nb is None: | |
111 | raise TypeError("nb is None") |
|
109 | raise TypeError("nb is None") | |
112 |
|
110 | |||
113 | #Create the exporter |
|
111 | #Create the exporter | |
114 | exporter_instance = exporter_type(preprocessors=transformers, |
|
112 | resources = kw.pop('resources', None) | |
115 | jinja_filters=filters, config=config) |
|
113 | if isinstance(exporter, Exporter): | |
|
114 | exporter_instance = exporter | |||
|
115 | else: | |||
|
116 | exporter_instance = exporter(**kw) | |||
116 |
|
117 | |||
117 | #Try to convert the notebook using the appropriate conversion function. |
|
118 | #Try to convert the notebook using the appropriate conversion function. | |
118 | if isinstance(nb, NotebookNode): |
|
119 | if isinstance(nb, NotebookNode): | |
119 | output, resources = exporter_instance.from_notebook_node(nb) |
|
120 | output, resources = exporter_instance.from_notebook_node(nb, resources) | |
120 | elif isinstance(nb, basestring): |
|
121 | elif isinstance(nb, basestring): | |
121 | output, resources = exporter_instance.from_filename(nb) |
|
122 | output, resources = exporter_instance.from_filename(nb, resources) | |
122 | else: |
|
123 | else: | |
123 | output, resources = exporter_instance.from_file(nb) |
|
124 | output, resources = exporter_instance.from_file(nb, resources) | |
124 |
return output, resources |
|
125 | return output, resources | |
125 |
|
126 | |||
126 |
|
127 | |||
127 | @DocDecorator |
|
128 | @DocDecorator | |
128 | def export_sphinx_manual(nb, config=None, transformers=None, filters=None): |
|
129 | def export_sphinx_manual(nb, **kw): | |
129 | """ |
|
130 | """ | |
130 | Export a notebook object to Sphinx Manual LaTeX |
|
131 | Export a notebook object to Sphinx Manual LaTeX | |
131 | """ |
|
132 | """ | |
132 |
return export(SphinxManualExporter, nb, |
|
133 | return export(SphinxManualExporter, nb, **kw) | |
133 |
|
134 | |||
134 |
|
135 | |||
135 | @DocDecorator |
|
136 | @DocDecorator | |
136 | def export_sphinx_howto(nb, config=None, transformers=None, filters=None): |
|
137 | def export_sphinx_howto(nb, **kw): | |
137 | """ |
|
138 | """ | |
138 | Export a notebook object to Sphinx HowTo LaTeX |
|
139 | Export a notebook object to Sphinx HowTo LaTeX | |
139 | """ |
|
140 | """ | |
140 |
return export(SphinxHowtoExporter, nb, |
|
141 | return export(SphinxHowtoExporter, nb, **kw) | |
141 |
|
142 | |||
142 |
|
143 | |||
143 | @DocDecorator |
|
144 | @DocDecorator | |
144 | def export_basic_html(nb, config=None, transformers=None, filters=None): |
|
145 | def export_basic_html(nb, **kw): | |
145 | """ |
|
146 | """ | |
146 | Export a notebook object to Basic HTML |
|
147 | Export a notebook object to Basic HTML | |
147 | """ |
|
148 | """ | |
148 |
return export(BasicHTMLExporter, nb, |
|
149 | return export(BasicHTMLExporter, nb, **kw) | |
149 |
|
150 | |||
150 |
|
151 | |||
151 | @DocDecorator |
|
152 | @DocDecorator | |
152 | def export_full_html(nb, config=None, transformers=None, filters=None): |
|
153 | def export_full_html(nb, **kw): | |
153 | """ |
|
154 | """ | |
154 | Export a notebook object to Full HTML |
|
155 | Export a notebook object to Full HTML | |
155 | """ |
|
156 | """ | |
156 |
return export(FullHTMLExporter, nb, |
|
157 | return export(FullHTMLExporter, nb, **kw) | |
157 |
|
158 | |||
158 |
|
159 | |||
159 | @DocDecorator |
|
160 | @DocDecorator | |
160 | def export_latex(nb, config=None, transformers=None, filters=None): |
|
161 | def export_latex(nb, **kw): | |
161 | """ |
|
162 | """ | |
162 | Export a notebook object to LaTeX |
|
163 | Export a notebook object to LaTeX | |
163 | """ |
|
164 | """ | |
164 |
return export(LatexExporter, nb, |
|
165 | return export(LatexExporter, nb, **kw) | |
165 |
|
166 | |||
166 |
|
167 | |||
167 | @DocDecorator |
|
168 | @DocDecorator | |
168 | def export_markdown(nb, config=None, transformers=None, filters=None): |
|
169 | def export_markdown(nb, **kw): | |
169 | """ |
|
170 | """ | |
170 | Export a notebook object to Markdown |
|
171 | Export a notebook object to Markdown | |
171 | """ |
|
172 | """ | |
172 |
return export(MarkdownExporter, nb, |
|
173 | return export(MarkdownExporter, nb, **kw) | |
173 |
|
174 | |||
174 |
|
175 | |||
175 | @DocDecorator |
|
176 | @DocDecorator | |
176 | def export_python(nb, config=None, transformers=None, filters=None): |
|
177 | def export_python(nb, **kw): | |
177 | """ |
|
178 | """ | |
178 | Export a notebook object to Python |
|
179 | Export a notebook object to Python | |
179 | """ |
|
180 | """ | |
180 |
return export(PythonExporter, nb, |
|
181 | return export(PythonExporter, nb, **kw) | |
181 |
|
182 | |||
182 |
|
183 | |||
183 | @DocDecorator |
|
184 | @DocDecorator | |
184 | def export_reveal(nb, config=None, transformers=None, filters=None): |
|
185 | def export_reveal(nb, **kw): | |
185 | """ |
|
186 | """ | |
186 | Export a notebook object to Reveal |
|
187 | Export a notebook object to a Reveal.js presentation | |
187 | """ |
|
188 | """ | |
188 |
return export(RevealExporter, nb, |
|
189 | return export(RevealExporter, nb, **kw) | |
189 |
|
190 | |||
190 |
|
191 | |||
191 | @DocDecorator |
|
192 | @DocDecorator | |
192 | def export_rst(nb, config=None, transformers=None, filters=None): |
|
193 | def export_rst(nb, **kw): | |
193 | """ |
|
194 | """ | |
194 |
Export a notebook object to |
|
195 | Export a notebook object to reStructuredText | |
195 | """ |
|
196 | """ | |
196 |
return export(R |
|
197 | return export(RSTExporter, nb, **kw) | |
197 |
|
198 | |||
198 |
|
199 | |||
199 | @DocDecorator |
|
200 | @DocDecorator | |
200 | def export_by_name(template_name, nb, config=None, transformers=None, filters=None): |
|
201 | def export_by_name(format_name, nb, **kw): | |
201 | """ |
|
202 | """ | |
202 | Export a notebook object to a template type by its name. Reflection |
|
203 | Export a notebook object to a template type by its name. Reflection | |
203 | (Inspect) is used to find the template's corresponding explicit export |
|
204 | (Inspect) is used to find the template's corresponding explicit export | |
204 | method defined in this module. That method is then called directly. |
|
205 | method defined in this module. That method is then called directly. | |
205 |
|
206 | |||
206 |
|
|
207 | format_name : str | |
207 | Name of the template style to export to. |
|
208 | Name of the template style to export to. | |
208 | """ |
|
209 | """ | |
209 |
|
210 | |||
210 |
function_name = "export_" + |
|
211 | function_name = "export_" + format_name.lower() | |
211 |
|
212 | |||
212 | if function_name in globals(): |
|
213 | if function_name in globals(): | |
213 |
return globals()[function_name](nb, |
|
214 | return globals()[function_name](nb, **kw) | |
214 | else: |
|
215 | else: | |
215 | raise NameError("template for `%s` not found" % function_name) |
|
216 | raise ExporterNameError("template for `%s` not found" % function_name) | |
|
217 | ||||
216 |
|
218 | |||
217 | def get_export_names(): |
|
219 | def get_export_names(): | |
218 | "Return a list of the currently supported export targets" |
|
220 | "Return a list of the currently supported export targets" | |
219 | # grab everything after 'export_' |
|
221 | # grab everything after 'export_' | |
220 | l = [x[len('export_'):] for x in __all__ if x.startswith('export_')] |
|
222 | l = [x[len('export_'):] for x in __all__ if x.startswith('export_')] | |
|
223 | ||||
221 | # filter out the one method that is not a template |
|
224 | # filter out the one method that is not a template | |
222 | l = [x for x in l if 'by_name' not in x] |
|
225 | l = [x for x in l if 'by_name' not in x] | |
223 | return sorted(l) |
|
226 | return sorted(l) |
@@ -20,7 +20,10 b' from __future__ import print_function, absolute_import' | |||||
20 | import io |
|
20 | import io | |
21 | import os |
|
21 | import os | |
22 | import inspect |
|
22 | import inspect | |
23 | from copy import deepcopy |
|
23 | import types | |
|
24 | import copy | |||
|
25 | import collections | |||
|
26 | import datetime | |||
24 |
|
27 | |||
25 | # other libs/dependencies |
|
28 | # other libs/dependencies | |
26 | from jinja2 import Environment, FileSystemLoader, ChoiceLoader |
|
29 | from jinja2 import Environment, FileSystemLoader, ChoiceLoader | |
@@ -29,11 +32,12 b' from jinja2 import Environment, FileSystemLoader, ChoiceLoader' | |||||
29 | from IPython.config.configurable import Configurable |
|
32 | from IPython.config.configurable import Configurable | |
30 | from IPython.config import Config |
|
33 | from IPython.config import Config | |
31 | from IPython.nbformat import current as nbformat |
|
34 | from IPython.nbformat import current as nbformat | |
32 | from IPython.utils.traitlets import MetaHasTraits, Unicode |
|
35 | from IPython.utils.traitlets import MetaHasTraits, DottedObjectName, Unicode, List, Dict | |
|
36 | from IPython.utils.importstring import import_item | |||
33 | from IPython.utils.text import indent |
|
37 | from IPython.utils.text import indent | |
34 |
|
38 | |||
|
39 | from IPython.nbconvert import transformers as nbtransformers | |||
35 | from IPython.nbconvert import filters |
|
40 | from IPython.nbconvert import filters | |
36 | from IPython.nbconvert import transformers |
|
|||
37 |
|
41 | |||
38 | #----------------------------------------------------------------------------- |
|
42 | #----------------------------------------------------------------------------- | |
39 | # Globals and constants |
|
43 | # Globals and constants | |
@@ -68,6 +72,11 b' default_filters = {' | |||||
68 | # Class |
|
72 | # Class | |
69 | #----------------------------------------------------------------------------- |
|
73 | #----------------------------------------------------------------------------- | |
70 |
|
74 | |||
|
75 | class ResourcesDict(collections.defaultdict): | |||
|
76 | def __missing__(self, key): | |||
|
77 | return '' | |||
|
78 | ||||
|
79 | ||||
71 | class Exporter(Configurable): |
|
80 | class Exporter(Configurable): | |
72 | """ |
|
81 | """ | |
73 | Exports notebooks into other file formats. Uses Jinja 2 templating engine |
|
82 | Exports notebooks into other file formats. Uses Jinja 2 templating engine | |
@@ -112,27 +121,32 b' class Exporter(Configurable):' | |||||
112 | #Extension that the template files use. |
|
121 | #Extension that the template files use. | |
113 | template_extension = Unicode(".tpl", config=True) |
|
122 | template_extension = Unicode(".tpl", config=True) | |
114 |
|
123 | |||
115 | #Processors that process the input data prior to the export, set in the |
|
124 | #Configurability, allows the user to easily add filters and transformers. | |
116 | #constructor for this class. |
|
125 | transformers = List(config=True, | |
117 | transformers = None |
|
126 | help="""List of transformers, by name or namespace, to enable.""") | |
118 |
|
127 | |||
119 |
|
128 | filters = Dict(config=True, | ||
120 | def __init__(self, transformers=None, filters=None, config=None, extra_loaders=None, **kw): |
|
129 | help="""Dictionary of filters, by name and namespace, to add to the Jinja | |
|
130 | environment.""") | |||
|
131 | ||||
|
132 | default_transformers = List([nbtransformers.coalesce_streams, | |||
|
133 | nbtransformers.SVG2PDFTransformer, | |||
|
134 | nbtransformers.ExtractFigureTransformer, | |||
|
135 | nbtransformers.CSSHTMLHeaderTransformer, | |||
|
136 | nbtransformers.RevealHelpTransformer, | |||
|
137 | nbtransformers.LatexTransformer, | |||
|
138 | nbtransformers.SphinxTransformer], | |||
|
139 | config=True, | |||
|
140 | help="""List of transformers available by default, by name, namespace, | |||
|
141 | instance, or type.""") | |||
|
142 | ||||
|
143 | ||||
|
144 | def __init__(self, config=None, extra_loaders=None, **kw): | |||
121 | """ |
|
145 | """ | |
122 | Public constructor |
|
146 | Public constructor | |
123 |
|
147 | |||
124 | Parameters |
|
148 | Parameters | |
125 | ---------- |
|
149 | ---------- | |
126 | transformers : list[of transformer] |
|
|||
127 | Custom transformers to apply to the notebook prior to engaging |
|
|||
128 | the Jinja template engine. Any transformers specified here |
|
|||
129 | will override existing transformers if a naming conflict |
|
|||
130 | occurs. |
|
|||
131 | filters : dict[of filter] |
|
|||
132 | filters specified here will override existing filters if a naming |
|
|||
133 | conflict occurs. Filters are availlable in jinja template through |
|
|||
134 | the name of the corresponding key. Cf class docstring for |
|
|||
135 | availlable default filters. |
|
|||
136 | config : config |
|
150 | config : config | |
137 | User configuration instance. |
|
151 | User configuration instance. | |
138 | extra_loaders : list[of Jinja Loaders] |
|
152 | extra_loaders : list[of Jinja Loaders] | |
@@ -147,53 +161,41 b' class Exporter(Configurable):' | |||||
147 |
|
161 | |||
148 | super(Exporter, self).__init__(config=c, **kw) |
|
162 | super(Exporter, self).__init__(config=c, **kw) | |
149 |
|
163 | |||
150 | #Standard environment |
|
164 | #Init | |
151 | self._init_environment(extra_loaders=extra_loaders) |
|
165 | self._init_environment(extra_loaders=extra_loaders) | |
|
166 | self._init_transformers() | |||
|
167 | self._init_filters() | |||
152 |
|
168 | |||
153 | #Add transformers |
|
|||
154 | self._register_transformers() |
|
|||
155 |
|
||||
156 | #Add filters to the Jinja2 environment |
|
|||
157 | self._register_filters() |
|
|||
158 |
|
||||
159 | #Load user transformers. Overwrite existing transformers if need be. |
|
|||
160 | if transformers : |
|
|||
161 | for transformer in transformers: |
|
|||
162 | self.register_transformer(transformer) |
|
|||
163 |
|
||||
164 | #Load user filters. Overwrite existing filters if need be. |
|
|||
165 | if not filters is None: |
|
|||
166 | for key, user_filter in filters.iteritems(): |
|
|||
167 | self.register_filter(key, user_filter) |
|
|||
168 |
|
169 | |||
169 | @property |
|
170 | @property | |
170 | def default_config(self): |
|
171 | def default_config(self): | |
171 | return Config() |
|
172 | return Config() | |
172 |
|
173 | |||
173 |
|
174 | |||
174 |
|
175 | def from_notebook_node(self, nb, resources=None, **kw): | ||
175 | def from_notebook_node(self, nb, resources=None): |
|
|||
176 | """ |
|
176 | """ | |
177 | Convert a notebook from a notebook node instance. |
|
177 | Convert a notebook from a notebook node instance. | |
178 |
|
178 | |||
179 | Parameters |
|
179 | Parameters | |
180 | ---------- |
|
180 | ---------- | |
181 | nb : Notebook node |
|
181 | nb : Notebook node | |
182 | resources : a dict of additional resources that |
|
182 | resources : dict (**kw) | |
183 |
can be accessed read/write by |
|
183 | of additional resources that can be accessed read/write by | |
184 |
|
|
184 | transformers and filters. | |
185 | """ |
|
185 | """ | |
186 | if resources is None: |
|
186 | nb_copy = copy.deepcopy(nb) | |
187 | resources = {} |
|
187 | resources = self._init_resources(resources) | |
188 | nb, resources = self._preprocess(nb, resources) |
|
188 | ||
189 |
|
189 | #Preprocess | ||
190 | #Load the template file. |
|
190 | nb_copy, resources = self._transform(nb_copy, resources) | |
191 | self.template = self.environment.get_template(self.template_file+self.template_extension) |
|
|||
192 |
|
||||
193 | return self.template.render(nb=nb, resources=resources), resources |
|
|||
194 |
|
191 | |||
|
192 | #Convert | |||
|
193 | self.template = self.environment.get_template(self.template_file + self.template_extension) | |||
|
194 | output = self.template.render(nb=nb_copy, resources=resources) | |||
|
195 | return output, resources | |||
195 |
|
196 | |||
196 | def from_filename(self, filename): |
|
197 | ||
|
198 | def from_filename(self, filename, resources=None, **kw): | |||
197 | """ |
|
199 | """ | |
198 | Convert a notebook from a notebook file. |
|
200 | Convert a notebook from a notebook file. | |
199 |
|
201 | |||
@@ -202,12 +204,24 b' class Exporter(Configurable):' | |||||
202 | filename : str |
|
204 | filename : str | |
203 | Full filename of the notebook file to open and convert. |
|
205 | Full filename of the notebook file to open and convert. | |
204 | """ |
|
206 | """ | |
|
207 | ||||
|
208 | #Pull the metadata from the filesystem. | |||
|
209 | if resources is None: | |||
|
210 | resources = ResourcesDict() | |||
|
211 | if not 'metadata' in resources or resources['metadata'] == '': | |||
|
212 | resources['metadata'] = ResourcesDict() | |||
|
213 | basename = os.path.basename(filename) | |||
|
214 | notebook_name = basename[:basename.rfind('.')] | |||
|
215 | resources['metadata']['name'] = notebook_name | |||
|
216 | ||||
|
217 | modified_date = datetime.datetime.fromtimestamp(os.path.getmtime(filename)) | |||
|
218 | resources['metadata']['modified_date'] = modified_date.strftime("%B %-d, %Y") | |||
205 |
|
219 | |||
206 | with io.open(filename) as f: |
|
220 | with io.open(filename) as f: | |
207 | return self.from_notebook_node(nbformat.read(f, 'json')) |
|
221 | return self.from_notebook_node(nbformat.read(f, 'json'), resources=resources,**kw) | |
208 |
|
222 | |||
209 |
|
223 | |||
210 | def from_file(self, file_stream): |
|
224 | def from_file(self, file_stream, resources=None, **kw): | |
211 | """ |
|
225 | """ | |
212 | Convert a notebook from a notebook file. |
|
226 | Convert a notebook from a notebook file. | |
213 |
|
227 | |||
@@ -216,10 +230,10 b' class Exporter(Configurable):' | |||||
216 | file_stream : file-like object |
|
230 | file_stream : file-like object | |
217 | Notebook file-like object to convert. |
|
231 | Notebook file-like object to convert. | |
218 | """ |
|
232 | """ | |
219 | return self.from_notebook_node(nbformat.read(file_stream, 'json')) |
|
233 | return self.from_notebook_node(nbformat.read(file_stream, 'json'), resources=resources, **kw) | |
220 |
|
234 | |||
221 |
|
235 | |||
222 | def register_transformer(self, transformer): |
|
236 | def register_transformer(self, transformer, enabled=False): | |
223 | """ |
|
237 | """ | |
224 | Register a transformer. |
|
238 | Register a transformer. | |
225 | Transformers are classes that act upon the notebook before it is |
|
239 | Transformers are classes that act upon the notebook before it is | |
@@ -231,20 +245,39 b' class Exporter(Configurable):' | |||||
231 | ---------- |
|
245 | ---------- | |
232 | transformer : transformer |
|
246 | transformer : transformer | |
233 | """ |
|
247 | """ | |
234 |
if |
|
248 | if transformer is None: | |
235 |
|
|
249 | raise TypeError('transformer') | |
|
250 | isclass = inspect.isclass(transformer) | |||
|
251 | constructed = not isclass | |||
|
252 | ||||
|
253 | #Handle transformer's registration based on it's type | |||
|
254 | if constructed and isinstance(transformer, types.StringTypes): | |||
|
255 | #Transformer is a string, import the namespace and recursively call | |||
|
256 | #this register_transformer method | |||
|
257 | transformer_cls = import_item(transformer) | |||
|
258 | return self.register_transformer(transformer_cls, enabled) | |||
236 |
|
259 | |||
237 |
if |
|
260 | if constructed and hasattr(transformer, '__call__'): | |
238 | self.transformers.append(transformer) |
|
261 | #Transformer is a function, no need to construct it. | |
|
262 | #Register and return the transformer. | |||
|
263 | if enabled: | |||
|
264 | transformer.enabled = True | |||
|
265 | self._transformers.append(transformer) | |||
239 | return transformer |
|
266 | return transformer | |
240 | elif isinstance(transformer, MetaHasTraits): |
|
267 | ||
241 | transformer_instance = transformer(config=self.config) |
|
268 | elif isclass and isinstance(transformer, MetaHasTraits): | |
242 | self.transformers.append(transformer_instance) |
|
269 | #Transformer is configurable. Make sure to pass in new default for | |
243 | return transformer_instance |
|
270 | #the enabled flag if one was specified. | |
|
271 | self.register_transformer(transformer(parent=self), enabled) | |||
|
272 | ||||
|
273 | elif isclass: | |||
|
274 | #Transformer is not configurable, construct it | |||
|
275 | self.register_transformer(transformer(), enabled) | |||
|
276 | ||||
244 | else: |
|
277 | else: | |
245 |
|
|
278 | #Transformer is an instance of something without a __call__ | |
246 | self.transformers.append(transformer_instance) |
|
279 | #attribute. | |
247 |
re |
|
280 | raise TypeError('transformer') | |
248 |
|
281 | |||
249 |
|
282 | |||
250 | def register_filter(self, name, filter): |
|
283 | def register_filter(self, name, filter): | |
@@ -259,34 +292,37 b' class Exporter(Configurable):' | |||||
259 | name to give the filter in the Jinja engine |
|
292 | name to give the filter in the Jinja engine | |
260 | filter : filter |
|
293 | filter : filter | |
261 | """ |
|
294 | """ | |
262 | if inspect.isfunction(filter): |
|
295 | if filter is None: | |
|
296 | raise TypeError('filter') | |||
|
297 | isclass = inspect.isclass(filter) | |||
|
298 | constructed = not isclass | |||
|
299 | ||||
|
300 | #Handle filter's registration based on it's type | |||
|
301 | if constructed and isinstance(filter, types.StringTypes): | |||
|
302 | #filter is a string, import the namespace and recursively call | |||
|
303 | #this register_filter method | |||
|
304 | filter_cls = import_item(filter) | |||
|
305 | return self.register_filter(name, filter_cls) | |||
|
306 | ||||
|
307 | if constructed and hasattr(filter, '__call__'): | |||
|
308 | #filter is a function, no need to construct it. | |||
263 | self.environment.filters[name] = filter |
|
309 | self.environment.filters[name] = filter | |
264 | elif isinstance(filter, MetaHasTraits): |
|
310 | return filter | |
265 | self.environment.filters[name] = filter(config=self.config) |
|
311 | ||
|
312 | elif isclass and isinstance(filter, MetaHasTraits): | |||
|
313 | #filter is configurable. Make sure to pass in new default for | |||
|
314 | #the enabled flag if one was specified. | |||
|
315 | self.register_filter(name, filter(parent=self)) | |||
|
316 | ||||
|
317 | elif isclass: | |||
|
318 | #filter is not configurable, construct it | |||
|
319 | self.register_filter(name, filter()) | |||
|
320 | ||||
266 | else: |
|
321 | else: | |
267 | self.environment.filters[name] = filter() |
|
322 | #filter is an instance of something without a __call__ | |
268 | return self.environment.filters[name] |
|
323 | #attribute. | |
|
324 | raise TypeError('filter') | |||
269 |
|
325 | |||
270 |
|
||||
271 | def _register_transformers(self): |
|
|||
272 | """ |
|
|||
273 | Register all of the transformers needed for this exporter. |
|
|||
274 | """ |
|
|||
275 |
|
||||
276 | self.register_transformer(transformers.coalesce_streams) |
|
|||
277 |
|
||||
278 | #Remember the figure extraction transformer so it can be enabled and |
|
|||
279 | #disabled easily later. |
|
|||
280 | self.extract_figure_transformer = self.register_transformer(transformers.ExtractFigureTransformer) |
|
|||
281 |
|
||||
282 |
|
||||
283 | def _register_filters(self): |
|
|||
284 | """ |
|
|||
285 | Register all of the filters required for the exporter. |
|
|||
286 | """ |
|
|||
287 | for k, v in default_filters.iteritems(): |
|
|||
288 | self.register_filter(k, v) |
|
|||
289 |
|
||||
290 |
|
326 | |||
291 | def _init_environment(self, extra_loaders=None): |
|
327 | def _init_environment(self, extra_loaders=None): | |
292 | """ |
|
328 | """ | |
@@ -321,8 +357,65 b' class Exporter(Configurable):' | |||||
321 | if self.jinja_comment_block_end: |
|
357 | if self.jinja_comment_block_end: | |
322 | self.environment.comment_end_string = self.jinja_comment_block_end |
|
358 | self.environment.comment_end_string = self.jinja_comment_block_end | |
323 |
|
359 | |||
|
360 | ||||
|
361 | def _init_transformers(self): | |||
|
362 | """ | |||
|
363 | Register all of the transformers needed for this exporter, disabled | |||
|
364 | unless specified explicitly. | |||
|
365 | """ | |||
|
366 | self._transformers = [] | |||
|
367 | ||||
|
368 | #Load default transformers (not necessarly enabled by default). | |||
|
369 | if self.default_transformers: | |||
|
370 | for transformer in self.default_transformers: | |||
|
371 | self.register_transformer(transformer) | |||
|
372 | ||||
|
373 | #Load user transformers. Enable by default. | |||
|
374 | if self.transformers: | |||
|
375 | for transformer in self.transformers: | |||
|
376 | self.register_transformer(transformer, enabled=True) | |||
|
377 | ||||
|
378 | ||||
|
379 | def _init_filters(self): | |||
|
380 | """ | |||
|
381 | Register all of the filters required for the exporter. | |||
|
382 | """ | |||
|
383 | ||||
|
384 | #Add default filters to the Jinja2 environment | |||
|
385 | for key, value in default_filters.iteritems(): | |||
|
386 | self.register_filter(key, value) | |||
|
387 | ||||
|
388 | #Load user filters. Overwrite existing filters if need be. | |||
|
389 | if self.filters: | |||
|
390 | for key, user_filter in self.filters.iteritems(): | |||
|
391 | self.register_filter(key, user_filter) | |||
|
392 | ||||
|
393 | ||||
|
394 | def _init_resources(self, resources): | |||
324 |
|
395 | |||
325 | def _preprocess(self, nb, resources): |
|
396 | #Make sure the resources dict is of ResourcesDict type. | |
|
397 | if resources is None: | |||
|
398 | resources = ResourcesDict() | |||
|
399 | if not isinstance(resources, ResourcesDict): | |||
|
400 | new_resources = ResourcesDict() | |||
|
401 | new_resources.update(resources) | |||
|
402 | resources = new_resources | |||
|
403 | ||||
|
404 | #Make sure the metadata extension exists in resources | |||
|
405 | if 'metadata' in resources: | |||
|
406 | if not isinstance(resources['metadata'], ResourcesDict): | |||
|
407 | resources['metadata'] = ResourcesDict(resources['metadata']) | |||
|
408 | else: | |||
|
409 | resources['metadata'] = ResourcesDict() | |||
|
410 | if not resources['metadata']['name']: | |||
|
411 | resources['metadata']['name'] = 'Notebook' | |||
|
412 | ||||
|
413 | #Set the output extension | |||
|
414 | resources['output_extension'] = self.file_extension | |||
|
415 | return resources | |||
|
416 | ||||
|
417 | ||||
|
418 | def _transform(self, nb, resources): | |||
326 | """ |
|
419 | """ | |
327 | Preprocess the notebook before passing it into the Jinja engine. |
|
420 | Preprocess the notebook before passing it into the Jinja engine. | |
328 | To preprocess the notebook is to apply all of the |
|
421 | To preprocess the notebook is to apply all of the | |
@@ -336,13 +429,13 b' class Exporter(Configurable):' | |||||
336 | and filters. |
|
429 | and filters. | |
337 | """ |
|
430 | """ | |
338 |
|
431 | |||
339 | # Do a deepcopy first, |
|
432 | # Do a copy.deepcopy first, | |
340 | # we are never safe enough with what the transformers could do. |
|
433 | # we are never safe enough with what the transformers could do. | |
341 | nbc = deepcopy(nb) |
|
434 | nbc = copy.deepcopy(nb) | |
342 | resc = deepcopy(resources) |
|
435 | resc = copy.deepcopy(resources) | |
|
436 | ||||
343 | #Run each transformer on the notebook. Carry the output along |
|
437 | #Run each transformer on the notebook. Carry the output along | |
344 | #to each transformer |
|
438 | #to each transformer | |
345 | for transformer in self.transformers: |
|
439 | for transformer in self._transformers: | |
346 |
nb, res |
|
440 | nbc, resc = transformer(nbc, resc) | |
347 |
return nb, res |
|
441 | return nbc, resc | |
348 |
|
@@ -20,7 +20,7 b' tags to circumvent Jinja/Latex syntax conflicts.' | |||||
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, List | |
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 | |
@@ -68,41 +68,35 b' class LatexExporter(Exporter):' | |||||
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 | ||
|
72 | def _init_filters(self): | |||
72 | """ |
|
73 | """ | |
73 | Register all of the filters required for the exporter. |
|
74 | Register all of the filters required for the exporter. | |
74 | """ |
|
75 | """ | |
75 |
|
76 | |||
76 | #Register the filters of the base class. |
|
77 | #Register the filters of the base class. | |
77 |
super(LatexExporter, self)._ |
|
78 | super(LatexExporter, self)._init_filters() | |
78 |
|
79 | |||
79 | #Add latex filters to the Jinja2 environment |
|
80 | #Add latex filters to the Jinja2 environment | |
80 | self.register_filter('escape_tex', filters.escape_latex) |
|
81 | self.register_filter('escape_tex', filters.escape_latex) | |
81 | self.register_filter('highlight', filters.highlight2latex) |
|
82 | self.register_filter('highlight', filters.highlight2latex) | |
82 |
|
83 | |||
83 |
|
||||
84 | def _register_transformers(self): |
|
|||
85 | """ |
|
|||
86 | Register all of the transformers needed for this exporter. |
|
|||
87 | """ |
|
|||
88 |
|
||||
89 | #Register the transformers of the base class. |
|
|||
90 | super(LatexExporter, self)._register_transformers() |
|
|||
91 |
|
||||
92 | #Register latex transformer |
|
|||
93 | self.register_transformer(transformers.LatexTransformer) |
|
|||
94 |
|
84 | |||
95 | @property |
|
85 | @property | |
96 | def default_config(self): |
|
86 | def default_config(self): | |
97 | c = Config({ |
|
87 | c = Config({ | |
98 |
' |
|
88 | 'NbConvertBase': { | |
99 |
'display_data_priority' : ['latex', ' |
|
89 | 'display_data_priority' : ['latex', 'png', 'jpg', 'svg', 'jpeg', 'text'] | |
100 | }, |
|
90 | }, | |
101 | 'ExtractFigureTransformer': { |
|
91 | 'ExtractFigureTransformer': { | |
102 |
'enabled':True |
|
92 | 'enabled':True | |
103 | 'extra_ext_map':{'svg':'pdf'}, |
|
93 | }, | |
|
94 | 'SVG2PDFTransformer': { | |||
|
95 | 'enabled':True | |||
|
96 | }, | |||
|
97 | 'LatexTransformer': { | |||
|
98 | 'enabled':True | |||
104 | } |
|
99 | } | |
105 | }) |
|
100 | }) | |
106 | c.merge(super(LatexExporter,self).default_config) |
|
101 | c.merge(super(LatexExporter,self).default_config) | |
107 | return c |
|
102 | return c | |
108 |
|
@@ -13,7 +13,7 b' Reveal slide show exporter.' | |||||
13 | # Imports |
|
13 | # Imports | |
14 | #----------------------------------------------------------------------------- |
|
14 | #----------------------------------------------------------------------------- | |
15 |
|
15 | |||
16 | from IPython.utils.traitlets import Unicode |
|
16 | from IPython.utils.traitlets import Unicode, List | |
17 | from IPython.config import Config |
|
17 | from IPython.config import Config | |
18 |
|
18 | |||
19 | from .basichtml import BasicHTMLExporter |
|
19 | from .basichtml import BasicHTMLExporter | |
@@ -35,17 +35,7 b' class RevealExporter(BasicHTMLExporter):' | |||||
35 | template_file = Unicode( |
|
35 | template_file = Unicode( | |
36 | 'reveal', config=True, |
|
36 | 'reveal', config=True, | |
37 | help="Name of the template file to use") |
|
37 | help="Name of the template file to use") | |
38 |
|
38 | |||
39 | def _register_transformers(self): |
|
|||
40 | """ |
|
|||
41 | Register all of the transformers needed for this exporter. |
|
|||
42 | """ |
|
|||
43 |
|
||||
44 | #Register the transformers of the base class. |
|
|||
45 | super(RevealExporter, self)._register_transformers() |
|
|||
46 |
|
||||
47 | #Register reveal help transformer |
|
|||
48 | self.register_transformer(transformers.RevealHelpTransformer) |
|
|||
49 |
|
39 | |||
50 | @property |
|
40 | @property | |
51 | def default_config(self): |
|
41 | def default_config(self): |
@@ -22,7 +22,7 b' from .exporter import Exporter' | |||||
22 | # Classes |
|
22 | # Classes | |
23 | #----------------------------------------------------------------------------- |
|
23 | #----------------------------------------------------------------------------- | |
24 |
|
24 | |||
25 |
class R |
|
25 | class RSTExporter(Exporter): | |
26 | """ |
|
26 | """ | |
27 | Exports restructured text documents. |
|
27 | Exports restructured text documents. | |
28 | """ |
|
28 | """ | |
@@ -38,5 +38,5 b' class RstExporter(Exporter):' | |||||
38 | @property |
|
38 | @property | |
39 | def default_config(self): |
|
39 | def default_config(self): | |
40 | c = Config({'ExtractFigureTransformer':{'enabled':True}}) |
|
40 | c = Config({'ExtractFigureTransformer':{'enabled':True}}) | |
41 |
c.merge(super(R |
|
41 | c.merge(super(RSTExporter,self).default_config) | |
42 | return c |
|
42 | return c |
@@ -14,7 +14,7 b' formatted for use with PDFLatex.' | |||||
14 | # Imports |
|
14 | # Imports | |
15 | #----------------------------------------------------------------------------- |
|
15 | #----------------------------------------------------------------------------- | |
16 |
|
16 | |||
17 | from IPython.utils.traitlets import Unicode |
|
17 | from IPython.utils.traitlets import Unicode, List | |
18 | from IPython.config import Config |
|
18 | from IPython.config import Config | |
19 |
|
19 | |||
20 | # local import |
|
20 | # local import | |
@@ -36,19 +36,9 b' class SphinxHowtoExporter(LatexExporter):' | |||||
36 | 'sphinx_howto', config=True, |
|
36 | 'sphinx_howto', config=True, | |
37 | help="Name of the template file to use") |
|
37 | help="Name of the template file to use") | |
38 |
|
38 | |||
39 | def _register_transformers(self): |
|
39 | ||
40 |
|
||||
41 | #Register the transformers of the base class. |
|
|||
42 | super(SphinxHowtoExporter, self)._register_transformers() |
|
|||
43 |
|
||||
44 | #Register sphinx latex transformer |
|
|||
45 | self.register_transformer(transformers.SphinxTransformer) |
|
|||
46 |
|
||||
47 | @property |
|
40 | @property | |
48 | def default_config(self): |
|
41 | def default_config(self): | |
49 | c = Config({ |
|
42 | c = Config({'SphinxTransformer': {'enabled':True}}) | |
50 | 'SphinxTransformer': {'enabled':True} |
|
|||
51 | }) |
|
|||
52 | c.merge(super(SphinxHowtoExporter,self).default_config) |
|
43 | c.merge(super(SphinxHowtoExporter,self).default_config) | |
53 | return c |
|
44 | return c | |
54 |
|
@@ -36,7 +36,7 b' def remove_ansi(source):' | |||||
36 | Source to remove the ansi from |
|
36 | Source to remove the ansi from | |
37 | """ |
|
37 | """ | |
38 |
|
38 | |||
39 |
return re.sub(r'\033\[( |
|
39 | return re.sub(r'\033\[(\d|;)+?m', '', source) | |
40 |
|
40 | |||
41 |
|
41 | |||
42 | def ansi2html(text): |
|
42 | def ansi2html(text): |
@@ -3,7 +3,7 b'' | |||||
3 | The filter contained in the file allows the converter templates to select |
|
3 | The filter contained in the file allows the converter templates to select | |
4 | the output format that is most valuable to the active export format. The |
|
4 | the output format that is most valuable to the active export format. The | |
5 | value of the different formats is set via |
|
5 | value of the different formats is set via | |
6 |
|
|
6 | NbConvertBase.display_data_priority | |
7 | """ |
|
7 | """ | |
8 | #----------------------------------------------------------------------------- |
|
8 | #----------------------------------------------------------------------------- | |
9 | # Copyright (c) 2013, the IPython Development Team. |
|
9 | # Copyright (c) 2013, the IPython Development Team. | |
@@ -17,11 +17,11 b' GlobalConfigurable.display_data_priority' | |||||
17 | # Classes and functions |
|
17 | # Classes and functions | |
18 | #----------------------------------------------------------------------------- |
|
18 | #----------------------------------------------------------------------------- | |
19 |
|
19 | |||
20 |
from ..utils. |
|
20 | from ..utils.base import NbConvertBase | |
21 |
|
21 | |||
22 | __all__ = ['DataTypeFilter'] |
|
22 | __all__ = ['DataTypeFilter'] | |
23 |
|
23 | |||
24 |
class DataTypeFilter( |
|
24 | class DataTypeFilter(NbConvertBase): | |
25 | """ Returns the preferred display format """ |
|
25 | """ Returns the preferred display format """ | |
26 |
|
26 | |||
27 | def __call__(self, output): |
|
27 | def __call__(self, output): |
@@ -1,8 +1,7 b'' | |||||
1 | #!/usr/bin/env python |
|
1 | #!/usr/bin/env python | |
2 |
"""NBConvert is a utility for conversion of |
|
2 | """NBConvert is a utility for conversion of .ipynb files. | |
3 |
|
3 | |||
4 |
Commandline interface for the N |
|
4 | Command-line interface for the NbConvert conversion utility. | |
5 | readme.rst for usage information |
|
|||
6 | """ |
|
5 | """ | |
7 | #----------------------------------------------------------------------------- |
|
6 | #----------------------------------------------------------------------------- | |
8 | #Copyright (c) 2013, the IPython Development Team. |
|
7 | #Copyright (c) 2013, the IPython Development Team. | |
@@ -19,211 +18,212 b' readme.rst for usage information' | |||||
19 | #Stdlib imports |
|
18 | #Stdlib imports | |
20 | from __future__ import print_function |
|
19 | from __future__ import print_function | |
21 | import sys |
|
20 | import sys | |
22 | import io |
|
|||
23 | import os |
|
21 | import os | |
|
22 | import glob | |||
24 |
|
23 | |||
25 | #From IPython |
|
24 | #From IPython | |
26 |
from IPython.co |
|
25 | from IPython.core.application import BaseIPythonApplication, base_aliases, base_flags | |
27 | from IPython.utils.traitlets import Bool, Unicode |
|
26 | from IPython.config import catch_config_error, Configurable | |
28 |
|
27 | from IPython.utils.traitlets import ( | ||
29 | from .exporters.export import export_by_name, get_export_names |
|
28 | Unicode, List, Instance, DottedObjectName, Type, CaselessStrEnum, | |
30 | from .exporters.exporter import Exporter |
|
29 | ) | |
31 | from .transformers import extractfigure |
|
30 | from IPython.utils.importstring import import_item | |
32 | from .utils.config import GlobalConfigurable |
|
|||
33 |
|
||||
34 | #----------------------------------------------------------------------------- |
|
|||
35 | #Globals and constants |
|
|||
36 | #----------------------------------------------------------------------------- |
|
|||
37 |
|
||||
38 | #'Keys in resources' user prompt. |
|
|||
39 | KEYS_PROMPT_HEAD = "====================== Keys in Resources ==================================" |
|
|||
40 | KEYS_PROMPT_BODY = """ |
|
|||
41 | =========================================================================== |
|
|||
42 | You are responsible for writing these files into the appropriate |
|
|||
43 | directory(ies) if need be. If you do not want to see this message, enable |
|
|||
44 | the 'write' (boolean) flag of the converter. |
|
|||
45 | =========================================================================== |
|
|||
46 | """ |
|
|||
47 |
|
||||
48 | _examples = """ |
|
|||
49 | ipython nbconvert rst Untitled0.ipynb # convert ipynb to ReStructured Text |
|
|||
50 | ipython nbconvert latex Untitled0.ipynb # convert ipynb to LaTeX |
|
|||
51 | ipython nbconvert reveal Untitled0.ipynb # convert to Reveal (HTML/JS) slideshow |
|
|||
52 | """ |
|
|||
53 |
|
31 | |||
|
32 | from .exporters.export import export_by_name, get_export_names, ExporterNameError | |||
|
33 | from IPython.nbconvert import exporters, transformers, writers | |||
|
34 | from .utils.base import NbConvertBase | |||
54 |
|
35 | |||
55 | #----------------------------------------------------------------------------- |
|
36 | #----------------------------------------------------------------------------- | |
56 | #Classes and functions |
|
37 | #Classes and functions | |
57 | #----------------------------------------------------------------------------- |
|
38 | #----------------------------------------------------------------------------- | |
58 |
|
39 | |||
59 | class NbConvertApp(Application): |
|
40 | nbconvert_aliases = {} | |
60 | __doc__ = """IPython notebook conversion utility |
|
41 | nbconvert_aliases.update(base_aliases) | |
61 |
|
42 | nbconvert_aliases.update({ | ||
62 | Convert to and from notebook file type (*.ipynb) |
|
43 | 'format' : 'NbConvertApp.export_format', | |
63 |
|
44 | 'notebooks' : 'NbConvertApp.notebooks', | ||
64 | ipython nbconvert TARGET FILENAME |
|
45 | 'writer' : 'NbConvertApp.writer_class', | |
65 |
|
46 | }) | ||
66 | Supported export TARGETs are: %s |
|
47 | ||
67 | """ % (" ".join(get_export_names())) |
|
48 | nbconvert_flags = {} | |
68 | description = Unicode(__doc__) |
|
49 | nbconvert_flags.update(base_flags) | |
69 |
|
50 | nbconvert_flags.update({ | ||
70 | examples = _examples |
|
51 | 'stdout' : ( | |
71 |
|
52 | {'NbConvertApp' : {'writer_class' : "StdoutWriter"}}, | ||
72 | stdout = Bool( |
|
53 | "Write notebook output to stdout instead of files." | |
73 | False, config=True, |
|
|||
74 | help="""Whether to print the converted IPYNB file to stdout |
|
|||
75 | use full do diff files without actually writing a new file""" |
|
|||
76 | ) |
|
|||
77 |
|
||||
78 | write = Bool( |
|
|||
79 | True, config=True, |
|
|||
80 | help="""Should the converted notebook file be written to disk |
|
|||
81 | along with potential extracted resources.""" |
|
|||
82 | ) |
|
54 | ) | |
|
55 | }) | |||
83 |
|
56 | |||
84 | aliases = { |
|
|||
85 | 'stdout':'NbConvertApp.stdout', |
|
|||
86 | 'write':'NbConvertApp.write', |
|
|||
87 | } |
|
|||
88 |
|
57 | |||
89 | flags = {} |
|
58 | class NbConvertApp(BaseIPythonApplication): | |
|
59 | """Application used to convert to and from notebook file type (*.ipynb)""" | |||
90 |
|
60 | |||
91 | flags['stdout'] = ( |
|
61 | name = 'ipython-nbconvert' | |
92 | {'NbConvertApp' : {'stdout' : True}}, |
|
62 | aliases = nbconvert_aliases | |
93 | """Print converted file to stdout, equivalent to --stdout=True |
|
63 | flags = nbconvert_flags | |
94 |
|
|
64 | ||
95 | ) |
|
65 | def _classes_default(self): | |
96 |
|
66 | classes = [NbConvertBase] | ||
97 | flags['no-write'] = ( |
|
67 | for pkg in (exporters, transformers, writers): | |
98 | {'NbConvertApp' : {'write' : True}}, |
|
68 | for name in dir(pkg): | |
99 | """Do not write to disk, equivalent to --write=False |
|
69 | cls = getattr(pkg, name) | |
100 | """ |
|
70 | if isinstance(cls, type) and issubclass(cls, Configurable): | |
|
71 | classes.append(cls) | |||
|
72 | return classes | |||
|
73 | ||||
|
74 | description = Unicode( | |||
|
75 | u"""This application is used to convert notebook files (*.ipynb) | |||
|
76 | to various other formats.""") | |||
|
77 | ||||
|
78 | examples = Unicode(u""" | |||
|
79 | The simplest way to use nbconvert is | |||
|
80 | ||||
|
81 | > ipython nbconvert mynotebook.ipynb | |||
|
82 | ||||
|
83 | which will convert mynotebook.ipynb to the default format (probably HTML). | |||
|
84 | ||||
|
85 | You can specify the export format with `--format`. | |||
|
86 | Options include {0} | |||
|
87 | ||||
|
88 | > ipython nbconvert --format latex mynotebook.ipnynb | |||
|
89 | ||||
|
90 | You can also pipe the output to stdout, rather than a file | |||
|
91 | ||||
|
92 | > ipython nbconvert mynotebook.ipynb --stdout | |||
|
93 | ||||
|
94 | Multiple notebooks can be given at the command line in a couple of | |||
|
95 | different ways: | |||
|
96 | ||||
|
97 | > ipython nbconvert notebook*.ipynb | |||
|
98 | > ipython nbconvert notebook1.ipynb notebook2.ipynb | |||
|
99 | ||||
|
100 | or you can specify the notebooks list in a config file, containing:: | |||
|
101 | ||||
|
102 | c.NbConvertApp.notebooks = ["my_notebook.ipynb"] | |||
|
103 | ||||
|
104 | > ipython nbconvert --config mycfg.py | |||
|
105 | """.format(get_export_names())) | |||
|
106 | #Writer specific variables | |||
|
107 | writer = Instance('IPython.nbconvert.writers.base.WriterBase', | |||
|
108 | help="""Instance of the writer class used to write the | |||
|
109 | results of the conversion.""") | |||
|
110 | writer_class = DottedObjectName('FilesWriter', config=True, | |||
|
111 | help="""Writer class used to write the | |||
|
112 | results of the conversion""") | |||
|
113 | writer_aliases = {'FilesWriter': 'IPython.nbconvert.writers.files.FilesWriter', | |||
|
114 | 'DebugWriter': 'IPython.nbconvert.writers.debug.DebugWriter', | |||
|
115 | 'StdoutWriter': 'IPython.nbconvert.writers.stdout.StdoutWriter'} | |||
|
116 | writer_factory = Type() | |||
|
117 | ||||
|
118 | def _writer_class_changed(self, name, old, new): | |||
|
119 | if new in self.writer_aliases: | |||
|
120 | new = self.writer_aliases[new] | |||
|
121 | self.writer_factory = import_item(new) | |||
|
122 | ||||
|
123 | ||||
|
124 | #Other configurable variables | |||
|
125 | export_format = CaselessStrEnum(get_export_names(), | |||
|
126 | default_value="full_html", | |||
|
127 | config=True, | |||
|
128 | help="""The export format to be used.""" | |||
101 | ) |
|
129 | ) | |
102 |
|
130 | |||
|
131 | notebooks = List([], config=True, help="""List of notebooks to convert. | |||
|
132 | Wildcards are supported. | |||
|
133 | Filenames passed positionally will be added to the list. | |||
|
134 | """) | |||
|
135 | ||||
|
136 | @catch_config_error | |||
|
137 | def initialize(self, argv=None): | |||
|
138 | super(NbConvertApp, self).initialize(argv) | |||
|
139 | self.init_notebooks() | |||
|
140 | self.init_writer() | |||
|
141 | ||||
|
142 | def init_notebooks(self): | |||
|
143 | """Construct the list of notebooks. | |||
|
144 | If notebooks are passed on the command-line, | |||
|
145 | they override notebooks specified in config files. | |||
|
146 | Glob each notebook to replace notebook patterns with filenames. | |||
|
147 | """ | |||
103 |
|
148 | |||
104 | def __init__(self, **kwargs): |
|
149 | # Specifying notebooks on the command-line overrides (rather than adds) | |
105 | """Public constructor""" |
|
150 | # the notebook list | |
106 |
|
151 | if self.extra_args: | ||
107 | #Call base class |
|
152 | patterns = self.extra_args | |
108 | super(NbConvertApp, self).__init__(**kwargs) |
|
153 | else: | |
109 |
|
154 | patterns = self.notebooks | ||
110 | #Register class here to have help with help all |
|
|||
111 | self.classes.insert(0, Exporter) |
|
|||
112 | self.classes.insert(0, GlobalConfigurable) |
|
|||
113 |
|
155 | |||
|
156 | #Use glob to replace all the notebook patterns with filenames. | |||
|
157 | filenames = [] | |||
|
158 | for pattern in patterns: | |||
|
159 | for filename in glob.glob(pattern): | |||
|
160 | if not filename in filenames: | |||
|
161 | filenames.append(filename) | |||
|
162 | self.notebooks = filenames | |||
114 |
|
163 | |||
115 |
def |
|
164 | def init_writer(self): | |
116 | """Entrypoint of NbConvert application. |
|
|||
117 |
|
||||
118 | Parameters |
|
|||
119 | ---------- |
|
|||
120 | argv : list |
|
|||
121 | Commandline arguments |
|
|||
122 |
|
|
165 | """ | |
123 |
|
166 | Initialize the writer (which is stateless) | ||
124 | #Parse the commandline options. |
|
167 | """ | |
125 | self.parse_command_line(argv) |
|
168 | self._writer_class_changed(None, self.writer_class, self.writer_class) | |
|
169 | self.writer = self.writer_factory(parent=self) | |||
126 |
|
170 | |||
127 | #Call base |
|
171 | def start(self): | |
|
172 | """ | |||
|
173 | Ran after initialization completed | |||
|
174 | """ | |||
128 | super(NbConvertApp, self).start() |
|
175 | super(NbConvertApp, self).start() | |
|
176 | self.convert_notebooks() | |||
129 |
|
177 | |||
130 | #The last arguments in list will be used by nbconvert |
|
178 | def convert_notebooks(self): | |
131 | if len(self.extra_args) is not 3: |
|
|||
132 | print( "Wrong number of arguments, use --help flag for usage", file=sys.stderr) |
|
|||
133 | sys.exit(-1) |
|
|||
134 | export_type = (self.extra_args)[1] |
|
|||
135 | ipynb_file = (self.extra_args)[2] |
|
|||
136 |
|
||||
137 | #Export |
|
|||
138 | try: |
|
|||
139 | return_value = export_by_name(export_type, ipynb_file) |
|
|||
140 | except NameError as e: |
|
|||
141 | print("Error: '%s' exporter not found." % export_type, |
|
|||
142 | file=sys.stderr) |
|
|||
143 | print("Known exporters are:", |
|
|||
144 | "\n\t" + "\n\t".join(get_export_names()), |
|
|||
145 | file=sys.stderr) |
|
|||
146 | sys.exit(-1) |
|
|||
147 | else: |
|
|||
148 | (output, resources, exporter) = return_value |
|
|||
149 |
|
||||
150 | #TODO: Allow user to set output directory and file. |
|
|||
151 | destination_filename = None |
|
|||
152 | destination_directory = None |
|
|||
153 | if self.write: |
|
|||
154 |
|
||||
155 | #Get the file name without the '.ipynb' (6 chars) extension and then |
|
|||
156 | #remove any addition periods and spaces. The resulting name will |
|
|||
157 | #be used to create the directory that the files will be exported |
|
|||
158 | #into. |
|
|||
159 | out_root = ipynb_file[:-6].replace('.', '_').replace(' ', '_') |
|
|||
160 | destination_filename = os.path.join(out_root+'.'+exporter.file_extension) |
|
|||
161 |
|
||||
162 | destination_directory = out_root+'_files' |
|
|||
163 | if not os.path.exists(destination_directory): |
|
|||
164 | os.mkdir(destination_directory) |
|
|||
165 |
|
||||
166 | #Write the results |
|
|||
167 | if self.stdout or not (destination_filename is None and destination_directory is None): |
|
|||
168 | self._write_results(output, resources, destination_filename, destination_directory) |
|
|||
169 |
|
||||
170 |
|
||||
171 | def _write_results(self, output, resources, destination_filename=None, destination_directory=None): |
|
|||
172 | """Output the conversion results to the console and/or filesystem |
|
|||
173 |
|
||||
174 | Parameters |
|
|||
175 | ---------- |
|
|||
176 | output : str |
|
|||
177 | Output of conversion |
|
|||
178 | resources : dictionary |
|
|||
179 | Additional input/output used by the transformers. For |
|
|||
180 | example, the ExtractFigure transformer outputs the |
|
|||
181 | figures it extracts into this dictionary. This method |
|
|||
182 | relies on the figures being in this dictionary when |
|
|||
183 | attempting to write the figures to the file system. |
|
|||
184 | destination_filename : str, Optional |
|
|||
185 | Filename to write output into. If None, output is not |
|
|||
186 | written to a file. |
|
|||
187 | destination_directory : str, Optional |
|
|||
188 | Directory to write notebook data (i.e. figures) to. If |
|
|||
189 | None, figures are not written to the file system. |
|
|||
190 |
|
|
179 | """ | |
191 |
|
180 | Convert the notebooks in the self.notebook traitlet | ||
192 | if self.stdout: |
|
181 | """ | |
193 | print(output.encode('utf-8')) |
|
182 | #Export each notebook | |
194 |
|
183 | conversion_success = 0 | ||
195 | #Write file output from conversion. |
|
184 | for notebook_filename in self.notebooks: | |
196 | if not destination_filename is None: |
|
185 | ||
197 | with io.open(destination_filename, 'w') as f: |
|
186 | #Get a unique key for the notebook and set it in the resources object. | |
198 | f.write(output) |
|
187 | basename = os.path.basename(notebook_filename) | |
199 |
|
188 | notebook_name = basename[:basename.rfind('.')] | ||
200 | #Get the key names used by the extract figure transformer |
|
189 | resources = {} | |
201 | figures_key = extractfigure.FIGURES_KEY |
|
190 | resources['unique_key'] = notebook_name | |
202 | binary_key = extractfigure.BINARY_KEY |
|
191 | ||
203 | text_key = extractfigure.TEXT_KEY |
|
192 | #Try to export | |
204 |
|
193 | try: | ||
205 | #Output any associate figures into the same "root" directory. |
|
194 | output, resources = export_by_name(self.export_format, | |
206 | binkeys = resources.get(figures_key, {}).get(binary_key,{}).keys() |
|
195 | notebook_filename, | |
207 | textkeys = resources.get(figures_key, {}).get(text_key,{}).keys() |
|
196 | resources=resources, | |
208 | if binkeys or textkeys : |
|
197 | config=self.config) | |
209 | if not destination_directory is None: |
|
198 | except ExporterNameError as e: | |
210 | for key in binkeys: |
|
199 | print("Error: '%s' exporter not found." % self.export_format, | |
211 | with io.open(os.path.join(destination_directory, key), 'wb') as f: |
|
200 | file=sys.stderr) | |
212 | f.write(resources[figures_key][binary_key][key]) |
|
201 | print("Known exporters are:", | |
213 | for key in textkeys: |
|
202 | "\n\t" + "\n\t".join(get_export_names()), | |
214 | with io.open(os.path.join(destination_directory, key), 'w') as f: |
|
203 | file=sys.stderr) | |
215 | f.write(resources[figures_key][text_key][key]) |
|
204 | sys.exit(-1) | |
216 |
|
205 | #except Exception as e: | ||
217 | #Figures that weren't exported which will need to be created by the |
|
206 | #print("Error: could not export '%s'" % notebook_filename, file=sys.stderr) | |
218 | #user. Tell the user what figures these are. |
|
207 | #print(e, file=sys.stderr) | |
219 |
|
|
208 | else: | |
220 | print(KEYS_PROMPT_HEAD, file=sys.stderr) |
|
209 | self.writer.write(output, resources, notebook_name=notebook_name) | |
221 | print(resources[figures_key].keys(), file=sys.stderr) |
|
210 | conversion_success += 1 | |
222 | print(KEYS_PROMPT_BODY , file=sys.stderr) |
|
211 | ||
|
212 | #If nothing was converted successfully, help the user. | |||
|
213 | if conversion_success == 0: | |||
|
214 | ||||
|
215 | #No notebooks were specified, show help. | |||
|
216 | if len(self.notebooks) == 0: | |||
|
217 | self.print_help() | |||
|
218 | ||||
|
219 | #Notebooks were specified, but not converted successfully. Show how | |||
|
220 | #to access help. | |||
|
221 | else: | |||
|
222 | print('For help, use "ipython nbconvert --help"') | |||
|
223 | ||||
223 |
|
224 | |||
224 | #----------------------------------------------------------------------------- |
|
225 | #----------------------------------------------------------------------------- | |
225 | # Main entry point |
|
226 | # Main entry point | |
226 | #----------------------------------------------------------------------------- |
|
227 | #----------------------------------------------------------------------------- | |
227 |
|
228 | |||
228 | launch_new_instance = NbConvertApp.launch_instance |
|
229 | launch_new_instance = NbConvertApp.launch_instance | |
229 |
|
@@ -41,21 +41,21 b' it introduces a new line' | |||||
41 |
|
41 | |||
42 | ((*- block data_png -*)) |
|
42 | ((*- block data_png -*)) | |
43 | \begin{center} |
|
43 | \begin{center} | |
44 |
\includegraphics[max size={0.7\textwidth}{0.9\textheight}]{(((output. |
|
44 | \includegraphics[max size={0.7\textwidth}{0.9\textheight}]{(((output.png_filename)))} | |
45 | \par |
|
45 | \par | |
46 | \end{center} |
|
46 | \end{center} | |
47 | ((*- endblock -*)) |
|
47 | ((*- endblock -*)) | |
48 |
|
48 | |||
49 | ((*- block data_jpg -*)) |
|
49 | ((*- block data_jpg -*)) | |
50 | \begin{center} |
|
50 | \begin{center} | |
51 |
\includegraphics[max size={0.7\textwidth}{0.9\textheight}]{(((output. |
|
51 | \includegraphics[max size={0.7\textwidth}{0.9\textheight}]{(((output.jpeg_filename)))} | |
52 | \par |
|
52 | \par | |
53 | \end{center} |
|
53 | \end{center} | |
54 | ((*- endblock -*)) |
|
54 | ((*- endblock -*)) | |
55 |
|
55 | |||
56 | ((*- block data_svg -*)) |
|
56 | ((*- block data_svg -*)) | |
57 | \begin{center} |
|
57 | \begin{center} | |
58 |
\includegraphics[width=0.7\textwidth]{(((output. |
|
58 | \includegraphics[width=0.7\textwidth]{(((output.svg_filename)))} | |
59 | \par |
|
59 | \par | |
60 | \end{center} |
|
60 | \end{center} | |
61 | ((*- endblock -*)) |
|
61 | ((*- endblock -*)) |
@@ -145,11 +145,11 b' Note: For best display, use latex syntax highlighting. =))' | |||||
145 | \sloppy |
|
145 | \sloppy | |
146 |
|
146 | |||
147 | % Document level variables |
|
147 | % Document level variables | |
148 |
\title{((( |
|
148 | \title{((( resources.metadata.name | escape_tex )))} | |
149 |
\date{((( |
|
149 | \date{((( resources.sphinx.date | escape_tex )))} | |
150 |
\release{((( |
|
150 | \release{((( resources.sphinx.version | escape_tex )))} | |
151 |
\author{((( |
|
151 | \author{((( resources.sphinx.author | escape_tex )))} | |
152 |
\renewcommand{\releasename}{((( |
|
152 | \renewcommand{\releasename}{((( resources.sphinx.release | escape_tex )))} | |
153 |
|
153 | |||
154 | % TODO: Add option for the user to specify a logo for his/her export. |
|
154 | % TODO: Add option for the user to specify a logo for his/her export. | |
155 | \newcommand{\sphinxlogo}{} |
|
155 | \newcommand{\sphinxlogo}{} | |
@@ -347,11 +347,15 b' Note: For best display, use latex syntax highlighting. =))' | |||||
347 | % Supported image formats |
|
347 | % Supported image formats | |
348 | %============================================================================== |
|
348 | %============================================================================== | |
349 | ((*- block data_png -*)) |
|
349 | ((*- block data_png -*)) | |
350 |
((( conditionally_center_output(insert_graphics(output. |
|
350 | ((( conditionally_center_output(insert_graphics(output.png_filename)) ))) | |
|
351 | ((*- endblock -*)) | |||
|
352 | ||||
|
353 | ((*- block data_jpg -*)) | |||
|
354 | ((( conditionally_center_output(insert_graphics(output.jpg_filename)) ))) | |||
351 | ((*- endblock -*)) |
|
355 | ((*- endblock -*)) | |
352 |
|
356 | |||
353 | ((*- block data_svg -*)) |
|
357 | ((*- block data_svg -*)) | |
354 |
((( conditionally_center_output(insert_graphics(output. |
|
358 | ((( conditionally_center_output(insert_graphics(output.svg_filename)) ))) | |
355 | ((*- endblock -*)) |
|
359 | ((*- endblock -*)) | |
356 |
|
360 | |||
357 | ((*- block data_latex *)) |
|
361 | ((*- block data_latex *)) |
@@ -30,15 +30,15 b" In[{{cell.prompt_number if cell.prompt_number else ' '}}]:{% endblock in_prompt " | |||||
30 |
|
30 | |||
31 |
|
31 | |||
32 | {% block data_svg %} |
|
32 | {% block data_svg %} | |
33 |
[!image]({{output. |
|
33 | [!image]({{output.svg_filename}}) | |
34 | {% endblock data_svg %} |
|
34 | {% endblock data_svg %} | |
35 |
|
35 | |||
36 | {% block data_png %} |
|
36 | {% block data_png %} | |
37 |
[!image]({{output. |
|
37 | [!image]({{output.png_filename}}) | |
38 | {% endblock data_png %} |
|
38 | {% endblock data_png %} | |
39 |
|
39 | |||
40 | {% block data_jpg %} |
|
40 | {% block data_jpg %} | |
41 |
[!image]({{output. |
|
41 | [!image]({{output.jpg_filename}}) | |
42 | {% endblock data_jpg %} |
|
42 | {% endblock data_jpg %} | |
43 |
|
43 | |||
44 |
|
44 |
@@ -33,15 +33,15 b' Out[{{cell.prompt_number}}]:{% endif %}{% endblock output_prompt %}' | |||||
33 |
|
33 | |||
34 |
|
34 | |||
35 |
|
35 | |||
36 |
{% block data_svg %}.. image:: {{output. |
|
36 | {% block data_svg %}.. image:: {{output.svg_filename}} | |
37 |
|
37 | |||
38 | {% endblock data_svg %} |
|
38 | {% endblock data_svg %} | |
39 |
|
39 | |||
40 |
{% block data_png %}.. image:: {{output. |
|
40 | {% block data_png %}.. image:: {{output.png_filename}} | |
41 |
|
41 | |||
42 | {% endblock data_png %} |
|
42 | {% endblock data_png %} | |
43 |
|
43 | |||
44 |
{% block data_jpg %}..jpg image:: {{output. |
|
44 | {% block data_jpg %}..jpg image:: {{output.jpg_filename}} | |
45 |
|
45 | |||
46 | {% endblock data_jpg %} |
|
46 | {% endblock data_jpg %} | |
47 |
|
47 |
@@ -1,10 +1,12 b'' | |||||
1 | # Class base Transformers |
|
1 | # Class base Transformers | |
2 |
from . |
|
2 | from .base import Transformer | |
3 |
from . |
|
3 | from .convertfigures import ConvertFiguresTransformer | |
|
4 | from .svg2pdf import SVG2PDFTransformer | |||
4 | from .extractfigure import ExtractFigureTransformer |
|
5 | from .extractfigure import ExtractFigureTransformer | |
5 | from .revealhelp import RevealHelpTransformer |
|
6 | from .revealhelp import RevealHelpTransformer | |
6 | from .latex import LatexTransformer |
|
7 | from .latex import LatexTransformer | |
7 | from .sphinx import SphinxTransformer |
|
8 | from .sphinx import SphinxTransformer | |
|
9 | from .csshtmlheader import CSSHTMLHeaderTransformer | |||
8 |
|
10 | |||
9 | # decorated function Transformers |
|
11 | # decorated function Transformers | |
10 | from .coalescestreams import coalesce_streams |
|
12 | from .coalescestreams import coalesce_streams |
@@ -16,13 +16,14 b' It exposes a convenient class to inherit from to access configurability.' | |||||
16 | # Imports |
|
16 | # Imports | |
17 | #----------------------------------------------------------------------------- |
|
17 | #----------------------------------------------------------------------------- | |
18 |
|
18 | |||
19 |
from ..utils. |
|
19 | from ..utils.base import NbConvertBase | |
|
20 | from IPython.utils.traitlets import Bool | |||
20 |
|
21 | |||
21 | #----------------------------------------------------------------------------- |
|
22 | #----------------------------------------------------------------------------- | |
22 | # Classes and Functions |
|
23 | # Classes and Functions | |
23 | #----------------------------------------------------------------------------- |
|
24 | #----------------------------------------------------------------------------- | |
24 |
|
25 | |||
25 |
class |
|
26 | class Transformer(NbConvertBase): | |
26 | """ A configurable transformer |
|
27 | """ A configurable transformer | |
27 |
|
28 | |||
28 | Inherit from this class if you wish to have configurability for your |
|
29 | Inherit from this class if you wish to have configurability for your | |
@@ -31,11 +32,16 b' class ConfigurableTransformer(GlobalConfigurable):' | |||||
31 | Any configurable traitlets this class exposed will be configurable in profiles |
|
32 | Any configurable traitlets this class exposed will be configurable in profiles | |
32 | using c.SubClassName.atribute=value |
|
33 | using c.SubClassName.atribute=value | |
33 |
|
34 | |||
34 |
you can overwrite |
|
35 | you can overwrite transform_cell to apply a transformation independently on each cell | |
35 | or __call__ if you prefer your own logic. See corresponding docstring for informations. |
|
36 | or __call__ if you prefer your own logic. See corresponding docstring for informations. | |
|
37 | ||||
|
38 | Disabled by default and can be enabled via the config by | |||
|
39 | 'c.YourTransformerName.enabled = True' | |||
36 | """ |
|
40 | """ | |
37 |
|
41 | |||
38 | def __init__(self, config=None, **kw): |
|
42 | enabled = Bool(False, config=True) | |
|
43 | ||||
|
44 | def __init__(self, **kw): | |||
39 | """ |
|
45 | """ | |
40 | Public constructor |
|
46 | Public constructor | |
41 |
|
47 | |||
@@ -47,11 +53,15 b' class ConfigurableTransformer(GlobalConfigurable):' | |||||
47 | Additional arguments |
|
53 | Additional arguments | |
48 | """ |
|
54 | """ | |
49 |
|
55 | |||
50 |
super( |
|
56 | super(Transformer, self).__init__(**kw) | |
51 |
|
57 | |||
52 |
|
58 | |||
53 | def __call__(self, nb, resources): |
|
59 | def __call__(self, nb, resources): | |
54 | return self.call(nb,resources) |
|
60 | if self.enabled: | |
|
61 | return self.call(nb,resources) | |||
|
62 | else: | |||
|
63 | return nb, resources | |||
|
64 | ||||
55 |
|
65 | |||
56 | def call(self, nb, resources): |
|
66 | def call(self, nb, resources): | |
57 | """ |
|
67 | """ | |
@@ -59,7 +69,7 b' class ConfigurableTransformer(GlobalConfigurable):' | |||||
59 |
|
69 | |||
60 | You should return modified nb, resources. |
|
70 | You should return modified nb, resources. | |
61 | If you wish to apply your transform on each cell, you might want to |
|
71 | If you wish to apply your transform on each cell, you might want to | |
62 |
overwrite |
|
72 | overwrite transform_cell method instead. | |
63 |
|
73 | |||
64 | Parameters |
|
74 | Parameters | |
65 | ---------- |
|
75 | ---------- | |
@@ -72,13 +82,13 b' class ConfigurableTransformer(GlobalConfigurable):' | |||||
72 | try : |
|
82 | try : | |
73 | for worksheet in nb.worksheets : |
|
83 | for worksheet in nb.worksheets : | |
74 | for index, cell in enumerate(worksheet.cells): |
|
84 | for index, cell in enumerate(worksheet.cells): | |
75 |
worksheet.cells[index], resources = self. |
|
85 | worksheet.cells[index], resources = self.transform_cell(cell, resources, index) | |
76 | return nb, resources |
|
86 | return nb, resources | |
77 | except NotImplementedError: |
|
87 | except NotImplementedError: | |
78 | raise NotImplementedError('should be implemented by subclass') |
|
88 | raise NotImplementedError('should be implemented by subclass') | |
79 |
|
89 | |||
80 |
|
90 | |||
81 |
def |
|
91 | def transform_cell(self, cell, resources, index): | |
82 | """ |
|
92 | """ | |
83 | Overwrite if you want to apply a transformation on each cell. You |
|
93 | Overwrite if you want to apply a transformation on each cell. You | |
84 | should return modified cell and resource dictionary. |
|
94 | should return modified cell and resource dictionary. |
@@ -72,4 +72,3 b' def coalesce_streams(cell, resources, index):' | |||||
72 |
|
72 | |||
73 | cell.outputs = new_outputs |
|
73 | cell.outputs = new_outputs | |
74 | return cell, resources |
|
74 | return cell, resources | |
75 |
|
@@ -16,18 +16,18 b' import os' | |||||
16 | import io |
|
16 | import io | |
17 |
|
17 | |||
18 | from pygments.formatters import HtmlFormatter |
|
18 | from pygments.formatters import HtmlFormatter | |
19 |
|
19 | |||
20 | from IPython.utils import path |
|
20 | from IPython.utils import path | |
21 |
|
21 | |||
22 |
from . |
|
22 | from .base import Transformer | |
23 |
|
23 | |||
24 | from IPython.utils.traitlets import Unicode |
|
24 | from IPython.utils.traitlets import Unicode | |
25 |
|
25 | |||
26 | #----------------------------------------------------------------------------- |
|
26 | #----------------------------------------------------------------------------- | |
27 | # Classes and functions |
|
27 | # Classes and functions | |
28 | #----------------------------------------------------------------------------- |
|
28 | #----------------------------------------------------------------------------- | |
29 |
|
29 | |||
30 |
class CSSHTMLHeaderTransformer( |
|
30 | class CSSHTMLHeaderTransformer(Transformer): | |
31 | """ |
|
31 | """ | |
32 | Transformer used to pre-process notebook for HTML output. Adds IPython notebook |
|
32 | Transformer used to pre-process notebook for HTML output. Adds IPython notebook | |
33 | front-end CSS and Pygments CSS to HTML output. |
|
33 | front-end CSS and Pygments CSS to HTML output. |
@@ -12,59 +12,26 b" notebook file. The extracted figures are returned in the 'resources' dictionary" | |||||
12 | #----------------------------------------------------------------------------- |
|
12 | #----------------------------------------------------------------------------- | |
13 | # Imports |
|
13 | # Imports | |
14 | #----------------------------------------------------------------------------- |
|
14 | #----------------------------------------------------------------------------- | |
15 | import itertools |
|
|||
16 |
|
15 | |||
17 | from IPython.utils.traitlets import Dict, Unicode |
|
16 | import sys | |
18 | from .activatable import ActivatableTransformer |
|
17 | from IPython.utils.traitlets import Unicode | |
19 |
|
18 | from .base import Transformer | ||
20 | #----------------------------------------------------------------------------- |
|
|||
21 | # Constants |
|
|||
22 | #----------------------------------------------------------------------------- |
|
|||
23 |
|
||||
24 | FIGURES_KEY = "figures" |
|
|||
25 | BINARY_KEY = "binary" |
|
|||
26 | TEXT_KEY = "text" |
|
|||
27 |
|
19 | |||
28 | #----------------------------------------------------------------------------- |
|
20 | #----------------------------------------------------------------------------- | |
29 | # Classes |
|
21 | # Classes | |
30 | #----------------------------------------------------------------------------- |
|
22 | #----------------------------------------------------------------------------- | |
31 |
|
23 | |||
32 |
class ExtractFigureTransformer( |
|
24 | class ExtractFigureTransformer(Transformer): | |
33 | """ |
|
25 | """ | |
34 | Extracts all of the figures from the notebook file. The extracted |
|
26 | Extracts all of the figures from the notebook file. The extracted | |
35 | figures are returned in the 'resources' dictionary. |
|
27 | figures are returned in the 'resources' dictionary. | |
36 | """ |
|
28 | """ | |
37 |
|
29 | |||
38 | extra_extension_map = Dict({}, |
|
30 | figure_filename_template = Unicode( | |
39 | config=True, |
|
31 | "{unique_key}_{cell_index}_{index}.{extension}", config=True) | |
40 | help="""Extra map to override extension based on type. |
|
|||
41 | Useful for latex where SVG will be converted to PDF before inclusion |
|
|||
42 | """) |
|
|||
43 |
|
||||
44 | key_format_map = Dict({}, config=True,) |
|
|||
45 | figure_name_format_map = Dict({}, config=True) |
|
|||
46 |
|
||||
47 | #TODO: Change this to .format {} syntax |
|
|||
48 | default_key_template = Unicode('_fig_{index:02d}.{ext}', config=True) |
|
|||
49 |
|
||||
50 | def __init__(self, config=None, **kw): |
|
|||
51 | """ |
|
|||
52 | Public constructor |
|
|||
53 |
|
||||
54 | Parameters |
|
|||
55 | ---------- |
|
|||
56 | config : Config |
|
|||
57 | Configuration file structure |
|
|||
58 | **kw : misc |
|
|||
59 | Additional arguments |
|
|||
60 | """ |
|
|||
61 |
|
||||
62 | super(ExtractFigureTransformer, self).__init__(config=config, **kw) |
|
|||
63 |
|
32 | |||
64 | # A unique index for association with extracted figures |
|
|||
65 | self.index_generator = itertools.count(1) |
|
|||
66 |
|
33 | |||
67 |
def |
|
34 | def transform_cell(self, cell, resources, cell_index): | |
68 | """ |
|
35 | """ | |
69 | Apply a transformation on each cell, |
|
36 | Apply a transformation on each cell, | |
70 |
|
37 | |||
@@ -75,69 +42,49 b' class ExtractFigureTransformer(ActivatableTransformer):' | |||||
75 | resources : dictionary |
|
42 | resources : dictionary | |
76 | Additional resources used in the conversion process. Allows |
|
43 | Additional resources used in the conversion process. Allows | |
77 | transformers to pass variables into the Jinja engine. |
|
44 | transformers to pass variables into the Jinja engine. | |
78 | index : int |
|
45 | cell_index : int | |
79 | Index of the cell being processed (see base.py) |
|
46 | Index of the cell being processed (see base.py) | |
80 | """ |
|
47 | """ | |
|
48 | ||||
|
49 | #Get the unique key from the resource dict if it exists. If it does not | |||
|
50 | #exist, use 'figure' as the default. | |||
|
51 | unique_key = resources.get('unique_key', 'figure') | |||
81 |
|
52 | |||
82 | if resources.get(FIGURES_KEY, None) is None : |
|
53 | #Make sure figures key exists | |
83 | resources[FIGURES_KEY] = {TEXT_KEY:{},BINARY_KEY:{}} |
|
54 | if not 'figures' in resources: | |
|
55 | resources['figures'] = {} | |||
84 |
|
56 | |||
85 | for out in cell.get('outputs', []): |
|
57 | #Loop through all of the outputs in the cell | |
|
58 | for index, out in enumerate(cell.get('outputs', [])): | |||
|
59 | ||||
|
60 | #Get the output in data formats that the template is interested in. | |||
86 | for out_type in self.display_data_priority: |
|
61 | for out_type in self.display_data_priority: | |
87 |
|
||||
88 | if out.hasattr(out_type): |
|
62 | if out.hasattr(out_type): | |
89 |
|
|
63 | data = out[out_type] | |
90 | out['key_'+out_type] = figname |
|
64 | ||
|
65 | #Binary files are base64-encoded, SVG is already XML | |||
|
66 | if out_type in ('png', 'jpg', 'jpeg', 'pdf'): | |||
|
67 | data = data.decode('base64') | |||
|
68 | elif sys.platform == 'win32': | |||
|
69 | data = data.replace('\n', '\r\n').encode("UTF-8") | |||
|
70 | else: | |||
|
71 | data = data.encode("UTF-8") | |||
91 |
|
72 | |||
92 |
|
|
73 | #Build a figure name | |
93 | resources[FIGURES_KEY][BINARY_KEY][key] = data |
|
74 | figure_name = self.figure_filename_template.format( | |
94 | else : |
|
75 | unique_key=unique_key, | |
95 | resources[FIGURES_KEY][TEXT_KEY][key] = data |
|
76 | cell_index=cell_index, | |
96 |
|
77 | index=index, | ||
97 | index += 1 |
|
78 | extension=out_type) | |
98 | return cell, resources |
|
79 | ||
99 |
|
80 | #On the cell, make the figure available via | ||
|
81 | # cell.outputs[i].svg_filename ... etc (svg in example) | |||
|
82 | # Where | |||
|
83 | # cell.outputs[i].svg contains the data | |||
|
84 | out[out_type + '_filename'] = figure_name | |||
|
85 | ||||
|
86 | #In the resources, make the figure available via | |||
|
87 | # resources['figures']['filename'] = data | |||
|
88 | resources['figures'][figure_name] = data | |||
100 |
|
89 | |||
101 | def _get_override_extension(self, extension): |
|
90 | return cell, resources | |
102 | """Gets the overriden extension if it exists, else returns extension. |
|
|||
103 |
|
||||
104 | Parameters |
|
|||
105 | ---------- |
|
|||
106 | extension : str |
|
|||
107 | File extension. |
|
|||
108 | """ |
|
|||
109 |
|
||||
110 | if extension in self.extra_extension_map : |
|
|||
111 | return self.extra_extension_map[extension] |
|
|||
112 |
|
||||
113 | return extension |
|
|||
114 |
|
||||
115 |
|
||||
116 | def _new_figure(self, data, format): |
|
|||
117 | """Create a new figure file in the given format. |
|
|||
118 |
|
||||
119 | Parameters |
|
|||
120 | ---------- |
|
|||
121 | data : str |
|
|||
122 | Cell data (from Notebook node cell) |
|
|||
123 | format : str |
|
|||
124 | Figure format |
|
|||
125 | index : int |
|
|||
126 | Index of the figure being extracted |
|
|||
127 | """ |
|
|||
128 |
|
||||
129 | figure_name_template = self.figure_name_format_map.get(format, self.default_key_template) |
|
|||
130 | key_template = self.key_format_map.get(format, self.default_key_template) |
|
|||
131 |
|
||||
132 | #TODO: option to pass the hash as data? |
|
|||
133 | index = next(self.index_generator) |
|
|||
134 | figure_name = figure_name_template.format(index=index, ext=self._get_override_extension(format)) |
|
|||
135 | key = key_template.format(index=index, ext=self._get_override_extension(format)) |
|
|||
136 |
|
||||
137 | #Binary files are base64-encoded, SVG is already XML |
|
|||
138 | binary = False |
|
|||
139 | if format in ('png', 'jpg', 'pdf'): |
|
|||
140 | data = data.decode('base64') |
|
|||
141 | binary = True |
|
|||
142 |
|
||||
143 | return figure_name, key, data, binary |
|
@@ -17,19 +17,19 b' from __future__ import print_function, absolute_import' | |||||
17 |
|
17 | |||
18 | # Our own imports |
|
18 | # Our own imports | |
19 | # Needed to override transformer |
|
19 | # Needed to override transformer | |
20 |
from . |
|
20 | from .base import (Transformer) | |
21 | from IPython.nbconvert import filters |
|
21 | from IPython.nbconvert import filters | |
22 |
|
22 | |||
23 | #----------------------------------------------------------------------------- |
|
23 | #----------------------------------------------------------------------------- | |
24 | # Classes |
|
24 | # Classes | |
25 | #----------------------------------------------------------------------------- |
|
25 | #----------------------------------------------------------------------------- | |
26 |
|
26 | |||
27 |
class LatexTransformer( |
|
27 | class LatexTransformer(Transformer): | |
28 | """ |
|
28 | """ | |
29 | Converter for latex destined documents. |
|
29 | Converter for latex destined documents. | |
30 | """ |
|
30 | """ | |
31 |
|
31 | |||
32 |
def |
|
32 | def transform_cell(self, cell, resources, index): | |
33 | """ |
|
33 | """ | |
34 | Apply a transformation on each cell, |
|
34 | Apply a transformation on each cell, | |
35 |
|
35 |
@@ -12,14 +12,14 b'' | |||||
12 | # Imports |
|
12 | # Imports | |
13 | #----------------------------------------------------------------------------- |
|
13 | #----------------------------------------------------------------------------- | |
14 |
|
14 | |||
15 |
from .base import |
|
15 | from .base import Transformer | |
16 | from IPython.utils.traitlets import Unicode |
|
16 | from IPython.utils.traitlets import Unicode | |
17 |
|
17 | |||
18 | #----------------------------------------------------------------------------- |
|
18 | #----------------------------------------------------------------------------- | |
19 | # Classes and functions |
|
19 | # Classes and functions | |
20 | #----------------------------------------------------------------------------- |
|
20 | #----------------------------------------------------------------------------- | |
21 |
|
21 | |||
22 |
class RevealHelpTransformer( |
|
22 | class RevealHelpTransformer(Transformer): | |
23 |
|
23 | |||
24 | url_prefix = Unicode('//cdn.jsdelivr.net/reveal.js/2.4.0', |
|
24 | url_prefix = Unicode('//cdn.jsdelivr.net/reveal.js/2.4.0', | |
25 | config=True, |
|
25 | config=True, | |
@@ -39,9 +39,8 b' class RevealHelpTransformer(ConfigurableTransformer):' | |||||
39 | transformers to pass variables into the Jinja engine. |
|
39 | transformers to pass variables into the Jinja engine. | |
40 | """ |
|
40 | """ | |
41 |
|
41 | |||
42 |
|
||||
43 | for worksheet in nb.worksheets : |
|
42 | for worksheet in nb.worksheets : | |
44 | for i, cell in enumerate(worksheet.cells): |
|
43 | for index, cell in enumerate(worksheet.cells): | |
45 |
|
44 | |||
46 | #Make sure the cell has slideshow metadata. |
|
45 | #Make sure the cell has slideshow metadata. | |
47 | cell.metadata.align_type = cell.get('metadata', {}).get('slideshow', {}).get('align_type', 'Left') |
|
46 | cell.metadata.align_type = cell.get('metadata', {}).get('slideshow', {}).get('align_type', 'Left') | |
@@ -50,9 +49,9 b' class RevealHelpTransformer(ConfigurableTransformer):' | |||||
50 | #Get the slide type. If type is start of subslide or slide, |
|
49 | #Get the slide type. If type is start of subslide or slide, | |
51 | #end the last subslide/slide. |
|
50 | #end the last subslide/slide. | |
52 | if cell.metadata.slide_type in ['slide']: |
|
51 | if cell.metadata.slide_type in ['slide']: | |
53 | worksheet.cells[i - 1].metadata.slide_helper = 'slide_end' |
|
52 | worksheet.cells[index - 1].metadata.slide_helper = 'slide_end' | |
54 | if cell.metadata.slide_type in ['subslide']: |
|
53 | if cell.metadata.slide_type in ['subslide']: | |
55 | worksheet.cells[i - 1].metadata.slide_helper = 'subslide_end' |
|
54 | worksheet.cells[index - 1].metadata.slide_helper = 'subslide_end' | |
56 |
|
55 | |||
57 |
|
56 | |||
58 | if 'reveal' not in resources: |
|
57 | if 'reveal' not in resources: |
@@ -33,7 +33,7 b' from pygments.formatters import LatexFormatter' | |||||
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 . |
|
36 | from .base import (Transformer) | |
37 |
|
37 | |||
38 | from IPython.nbconvert.utils import console |
|
38 | from IPython.nbconvert.utils import console | |
39 |
|
39 | |||
@@ -41,7 +41,7 b' from IPython.nbconvert.utils import console' | |||||
41 | # Classes and functions |
|
41 | # Classes and functions | |
42 | #----------------------------------------------------------------------------- |
|
42 | #----------------------------------------------------------------------------- | |
43 |
|
43 | |||
44 |
class SphinxTransformer( |
|
44 | class SphinxTransformer(Transformer): | |
45 | """ |
|
45 | """ | |
46 | Sphinx utility transformer. |
|
46 | Sphinx utility transformer. | |
47 |
|
47 | |||
@@ -127,9 +127,6 b' class SphinxTransformer(ActivatableTransformer):' | |||||
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: |
|
|||
131 | nb.metadata._draft = {} |
|
|||
132 |
|
||||
133 | if not "sphinx" in resources: |
|
130 | if not "sphinx" in resources: | |
134 | resources["sphinx"] = {} |
|
131 | resources["sphinx"] = {} | |
135 |
|
132 | |||
@@ -137,10 +134,10 b' class SphinxTransformer(ActivatableTransformer):' | |||||
137 |
|
134 | |||
138 | # Prompt the user for additional meta data that doesn't exist currently |
|
135 | # Prompt the user for additional meta data that doesn't exist currently | |
139 | # but would be usefull for Sphinx. |
|
136 | # but would be usefull for Sphinx. | |
140 |
|
|
137 | resources["sphinx"]["author"] = self._prompt_author() | |
141 |
|
|
138 | resources["sphinx"]["version"] = self._prompt_version() | |
142 |
|
|
139 | resources["sphinx"]["release"] = self._prompt_release() | |
143 |
|
|
140 | resources["sphinx"]["date"] = self._prompt_date() | |
144 |
|
141 | |||
145 | # Prompt the user for the document style. |
|
142 | # Prompt the user for the document style. | |
146 | resources["sphinx"]["chapterstyle"] = self._prompt_chapter_title_style() |
|
143 | resources["sphinx"]["chapterstyle"] = self._prompt_chapter_title_style() | |
@@ -152,15 +149,17 b' class SphinxTransformer(ActivatableTransformer):' | |||||
152 | else: |
|
149 | else: | |
153 |
|
150 | |||
154 | # Try to use the traitlets. |
|
151 | # Try to use the traitlets. | |
155 |
|
|
152 | resources["sphinx"]["author"] = self.author | |
156 |
|
|
153 | resources["sphinx"]["version"] = self.version | |
157 |
|
|
154 | resources["sphinx"]["release"] = self.release | |
158 |
|
155 | |||
159 | # Use todays date if none is provided. |
|
156 | # Use todays date if none is provided. | |
160 |
if |
|
157 | if self.publish_date: | |
161 | nb.metadata._draft["date"] = date.today().strftime("%B %d, %Y") |
|
158 | resources["sphinx"]["date"] = self.publish_date | |
|
159 | elif len(resources['metadata']['modified_date'].strip()) == 0: | |||
|
160 | resources["sphinx"]["date"] = date.today().strftime("%B %-d, %Y") | |||
162 | else: |
|
161 | else: | |
163 | nb.metadata._draft["date"] = self.publish_date |
|
162 | resources["sphinx"]["date"] = resources['metadata']['modified_date'] | |
164 |
|
163 | |||
165 | # Sphinx traitlets. |
|
164 | # Sphinx traitlets. | |
166 | resources["sphinx"]["chapterstyle"] = self.chapter_style |
|
165 | resources["sphinx"]["chapterstyle"] = self.chapter_style | |
@@ -175,7 +174,7 b' class SphinxTransformer(ActivatableTransformer):' | |||||
175 | resources["sphinx"]["pygment_definitions"] = self._generate_pygments_latex_def() |
|
174 | resources["sphinx"]["pygment_definitions"] = self._generate_pygments_latex_def() | |
176 |
|
175 | |||
177 | if not (self.overridetitle == None or len(self.overridetitle.strip()) == 0): |
|
176 | if not (self.overridetitle == None or len(self.overridetitle.strip()) == 0): | |
178 |
|
|
177 | resources['metadata']['name'] = self.overridetitle | |
179 |
|
178 | |||
180 | # End |
|
179 | # End | |
181 | return nb, resources |
|
180 | return nb, resources | |
@@ -212,12 +211,16 b' class SphinxTransformer(ActivatableTransformer):' | |||||
212 | return console.input("Release Name (ie ""Rough draft""): ") |
|
211 | return console.input("Release Name (ie ""Rough draft""): ") | |
213 |
|
212 | |||
214 |
|
213 | |||
215 | def _prompt_date(self): |
|
214 | def _prompt_date(self, resources): | |
216 | """ |
|
215 | """ | |
217 | Prompt the user to enter a date |
|
216 | Prompt the user to enter a date | |
218 | """ |
|
217 | """ | |
219 |
|
218 | |||
220 | default_date = date.today().strftime("%B %d, %Y") |
|
219 | if resources['metadata']['modified_date']: | |
|
220 | default_date = resources['metadata']['modified_date'] | |||
|
221 | else: | |||
|
222 | default_date = date.today().strftime("%B %-d, %Y") | |||
|
223 | ||||
221 | user_date = console.input("Date (deafults to \"" + default_date + "\"): ") |
|
224 | user_date = console.input("Date (deafults to \"" + default_date + "\"): ") | |
222 | if len(user_date.strip()) == 0: |
|
225 | if len(user_date.strip()) == 0: | |
223 | user_date = default_date |
|
226 | user_date = default_date |
@@ -18,7 +18,7 b' from IPython.config.configurable import Configurable' | |||||
18 | # Classes and functions |
|
18 | # Classes and functions | |
19 | #----------------------------------------------------------------------------- |
|
19 | #----------------------------------------------------------------------------- | |
20 |
|
20 | |||
21 |
class |
|
21 | class NbConvertBase(Configurable): | |
22 | """Global configurable class for shared config |
|
22 | """Global configurable class for shared config | |
23 |
|
23 | |||
24 | Usefull for display data priority that might be use by many trasnformers |
|
24 | Usefull for display data priority that might be use by many trasnformers | |
@@ -33,5 +33,5 b' class GlobalConfigurable(Configurable):' | |||||
33 | """ |
|
33 | """ | |
34 | ) |
|
34 | ) | |
35 |
|
35 | |||
36 |
def __init__(self, |
|
36 | def __init__(self, **kw): | |
37 |
super( |
|
37 | super(NbConvertBase, self).__init__(**kw) |
1 | NO CONTENT: file was removed |
|
NO CONTENT: file was removed |
General Comments 0
You need to be logged in to leave comments.
Login now