Show More
@@ -0,0 +1,36 | |||||
|
1 | #!/usr/bin/env python | |||
|
2 | """ | |||
|
3 | Basic post processor | |||
|
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 ..utils.base import NbConvertBase | |||
|
18 | ||||
|
19 | ||||
|
20 | #----------------------------------------------------------------------------- | |||
|
21 | # Classes | |||
|
22 | #----------------------------------------------------------------------------- | |||
|
23 | class PostProcessorBase(NbConvertBase): | |||
|
24 | ||||
|
25 | def __call__(self, input): | |||
|
26 | """ | |||
|
27 | See def call() ... | |||
|
28 | """ | |||
|
29 | self.call(input) | |||
|
30 | ||||
|
31 | ||||
|
32 | def call(self, input): | |||
|
33 | """ | |||
|
34 | Post-process output from a writer. | |||
|
35 | """ | |||
|
36 | raise NotImplementedError('call') |
@@ -3,4 +3,5 | |||||
3 | from .exporters import * |
|
3 | from .exporters import * | |
4 | import filters |
|
4 | import filters | |
5 | import transformers |
|
5 | import transformers | |
|
6 | import post_processors | |||
6 | import writers |
|
7 | import writers |
@@ -30,7 +30,7 from IPython.utils.traitlets import ( | |||||
30 | from IPython.utils.importstring import import_item |
|
30 | from IPython.utils.importstring import import_item | |
31 |
|
31 | |||
32 | from .exporters.export import export_by_name, get_export_names, ExporterNameError |
|
32 | from .exporters.export import export_by_name, get_export_names, ExporterNameError | |
33 | from IPython.nbconvert import exporters, transformers, writers |
|
33 | from IPython.nbconvert import exporters, transformers, writers, post_processors | |
34 | from .utils.base import NbConvertBase |
|
34 | from .utils.base import NbConvertBase | |
35 | from .utils.exceptions import ConversionException |
|
35 | from .utils.exceptions import ConversionException | |
36 |
|
36 | |||
@@ -38,6 +38,19 from .utils.exceptions import ConversionException | |||||
38 | #Classes and functions |
|
38 | #Classes and functions | |
39 | #----------------------------------------------------------------------------- |
|
39 | #----------------------------------------------------------------------------- | |
40 |
|
40 | |||
|
41 | class DottedOrNone(DottedObjectName): | |||
|
42 | """ | |||
|
43 | A string holding a valid dotted object name in Python, such as A.b3._c | |||
|
44 | Also allows for None type.""" | |||
|
45 | ||||
|
46 | default_value = u'' | |||
|
47 | ||||
|
48 | def validate(self, obj, value): | |||
|
49 | if value is not None and len(value) > 0: | |||
|
50 | return super(DottedOrNone, self).validate(obj, value) | |||
|
51 | else: | |||
|
52 | return value | |||
|
53 | ||||
41 | nbconvert_aliases = {} |
|
54 | nbconvert_aliases = {} | |
42 | nbconvert_aliases.update(base_aliases) |
|
55 | nbconvert_aliases.update(base_aliases) | |
43 | nbconvert_aliases.update({ |
|
56 | nbconvert_aliases.update({ | |
@@ -45,6 +58,7 nbconvert_aliases.update({ | |||||
45 | 'template' : 'Exporter.template_file', |
|
58 | 'template' : 'Exporter.template_file', | |
46 | 'notebooks' : 'NbConvertApp.notebooks', |
|
59 | 'notebooks' : 'NbConvertApp.notebooks', | |
47 | 'writer' : 'NbConvertApp.writer_class', |
|
60 | 'writer' : 'NbConvertApp.writer_class', | |
|
61 | 'post': 'NbConvertApp.post_processor_class' | |||
48 | }) |
|
62 | }) | |
49 |
|
63 | |||
50 | nbconvert_flags = {} |
|
64 | nbconvert_flags = {} | |
@@ -53,11 +67,6 nbconvert_flags.update({ | |||||
53 | 'stdout' : ( |
|
67 | 'stdout' : ( | |
54 | {'NbConvertApp' : {'writer_class' : "StdoutWriter"}}, |
|
68 | {'NbConvertApp' : {'writer_class' : "StdoutWriter"}}, | |
55 | "Write notebook output to stdout instead of files." |
|
69 | "Write notebook output to stdout instead of files." | |
56 | ), |
|
|||
57 |
|
||||
58 | 'pdf' : ( |
|
|||
59 | {'NbConvertApp' : {'writer_class' : "PDFWriter"}}, |
|
|||
60 | "Compile notebook output to a PDF (requires `--to latex`)." |
|
|||
61 | ) |
|
70 | ) | |
62 | }) |
|
71 | }) | |
63 |
|
72 | |||
@@ -120,6 +129,7 class NbConvertApp(BaseIPythonApplication): | |||||
120 |
|
129 | |||
121 | > ipython nbconvert --config mycfg.py |
|
130 | > ipython nbconvert --config mycfg.py | |
122 | """.format(get_export_names())) |
|
131 | """.format(get_export_names())) | |
|
132 | ||||
123 | # Writer specific variables |
|
133 | # Writer specific variables | |
124 | writer = Instance('IPython.nbconvert.writers.base.WriterBase', |
|
134 | writer = Instance('IPython.nbconvert.writers.base.WriterBase', | |
125 | help="""Instance of the writer class used to write the |
|
135 | help="""Instance of the writer class used to write the | |
@@ -138,6 +148,23 class NbConvertApp(BaseIPythonApplication): | |||||
138 | new = self.writer_aliases[new] |
|
148 | new = self.writer_aliases[new] | |
139 | self.writer_factory = import_item(new) |
|
149 | self.writer_factory = import_item(new) | |
140 |
|
150 | |||
|
151 | # Post-processor specific variables | |||
|
152 | post_processor = Instance('IPython.nbconvert.post_processors.base.PostProcessorBase', | |||
|
153 | help="""Instance of the PostProcessor class used to write the | |||
|
154 | results of the conversion.""") | |||
|
155 | ||||
|
156 | post_processor_class = DottedOrNone(config=True, | |||
|
157 | help="""PostProcessor class used to write the | |||
|
158 | results of the conversion""") | |||
|
159 | post_processor_aliases = {'PDF': 'IPython.nbconvert.post_processors.pdf.PDFPostProcessor'} | |||
|
160 | post_processor_factory = Type() | |||
|
161 | ||||
|
162 | def _post_processor_class_changed(self, name, old, new): | |||
|
163 | if new in self.post_processor_aliases: | |||
|
164 | new = self.post_processor_aliases[new] | |||
|
165 | if new: | |||
|
166 | self.post_processor_factory = import_item(new) | |||
|
167 | ||||
141 |
|
168 | |||
142 | # Other configurable variables |
|
169 | # Other configurable variables | |
143 | export_format = CaselessStrEnum(get_export_names(), |
|
170 | export_format = CaselessStrEnum(get_export_names(), | |
@@ -157,6 +184,8 class NbConvertApp(BaseIPythonApplication): | |||||
157 | self.init_syspath() |
|
184 | self.init_syspath() | |
158 | self.init_notebooks() |
|
185 | self.init_notebooks() | |
159 | self.init_writer() |
|
186 | self.init_writer() | |
|
187 | self.init_post_processor() | |||
|
188 | ||||
160 |
|
189 | |||
161 |
|
190 | |||
162 | def init_syspath(self): |
|
191 | def init_syspath(self): | |
@@ -201,6 +230,15 class NbConvertApp(BaseIPythonApplication): | |||||
201 | self._writer_class_changed(None, self.writer_class, self.writer_class) |
|
230 | self._writer_class_changed(None, self.writer_class, self.writer_class) | |
202 | self.writer = self.writer_factory(parent=self) |
|
231 | self.writer = self.writer_factory(parent=self) | |
203 |
|
232 | |||
|
233 | def init_post_processor(self): | |||
|
234 | """ | |||
|
235 | Initialize the post_processor (which is stateless) | |||
|
236 | """ | |||
|
237 | self._post_processor_class_changed(None, self.post_processor_class, | |||
|
238 | self.post_processor_class) | |||
|
239 | if self.post_processor_factory: | |||
|
240 | self.post_processor = self.post_processor_factory(parent=self) | |||
|
241 | ||||
204 | def start(self): |
|
242 | def start(self): | |
205 | """ |
|
243 | """ | |
206 | Ran after initialization completed |
|
244 | Ran after initialization completed | |
@@ -242,7 +280,11 class NbConvertApp(BaseIPythonApplication): | |||||
242 | file=sys.stderr) |
|
280 | file=sys.stderr) | |
243 | self.exit(1) |
|
281 | self.exit(1) | |
244 | else: |
|
282 | else: | |
245 | self.writer.write(output, resources, notebook_name=notebook_name) |
|
283 | write_resultes = self.writer.write(output, resources, notebook_name=notebook_name) | |
|
284 | ||||
|
285 | #Post-process if post processor has been defined. | |||
|
286 | if hasattr(self, 'post_processor') and self.post_processor: | |||
|
287 | self.post_processor(write_resultes) | |||
246 | conversion_success += 1 |
|
288 | conversion_success += 1 | |
247 |
|
289 | |||
248 | # If nothing was converted successfully, help the user. |
|
290 | # If nothing was converted successfully, help the user. |
@@ -17,14 +17,14 Contains writer for writing nbconvert output to PDF. | |||||
17 | import subprocess |
|
17 | import subprocess | |
18 | import os |
|
18 | import os | |
19 |
|
19 | |||
20 | from IPython.utils.traitlets import Integer, Unicode |
|
20 | from IPython.utils.traitlets import Integer, Unicode, Bool | |
21 |
|
21 | |||
22 | from .files import FilesWriter |
|
22 | from .base import PostProcessorBase | |
23 |
|
23 | |||
24 | #----------------------------------------------------------------------------- |
|
24 | #----------------------------------------------------------------------------- | |
25 | # Classes |
|
25 | # Classes | |
26 | #----------------------------------------------------------------------------- |
|
26 | #----------------------------------------------------------------------------- | |
27 | class PDFWriter(FilesWriter): |
|
27 | class PDFPostProcessor(PostProcessorBase): | |
28 | """Writer designed to write to PDF files""" |
|
28 | """Writer designed to write to PDF files""" | |
29 |
|
29 | |||
30 | iteration_count = Integer(3, config=True, help=""" |
|
30 | iteration_count = Integer(3, config=True, help=""" | |
@@ -34,14 +34,19 class PDFWriter(FilesWriter): | |||||
34 | compiler = Unicode(u'pdflatex {0}', config=True, help=""" |
|
34 | compiler = Unicode(u'pdflatex {0}', config=True, help=""" | |
35 | Shell command used to compile PDF.""") |
|
35 | Shell command used to compile PDF.""") | |
36 |
|
36 | |||
37 | def write(self, output, resources, notebook_name=None, **kw): |
|
37 | verbose = Bool(False, config=True, help=""" | |
|
38 | Whether or not to display the output of the compile call. | |||
|
39 | """) | |||
|
40 | ||||
|
41 | def call(self, input): | |||
38 | """ |
|
42 | """ | |
39 | Consume and write Jinja output a PDF. |
|
43 | Consume and write Jinja output a PDF. | |
40 | See files.py for more... |
|
44 | See files.py for more... | |
41 | """ |
|
45 | """ | |
42 | dest = super(PDFWriter, self).write(output, resources, |
|
46 | command = self.compiler.format(input) | |
43 | notebook_name=notebook_name, **kw) |
|
|||
44 | command = self.compiler.format(dest) |
|
|||
45 |
|
||||
46 | for index in range(self.iteration_count): |
|
47 | for index in range(self.iteration_count): | |
47 | subprocess.Popen(command, shell=True, stdout=open(os.devnull, 'wb')) |
|
48 | if self.verbose: | |
|
49 | subprocess.Popen(command, shell=True) | |||
|
50 | else: | |||
|
51 | with open(os.devnull, 'wb') as null: | |||
|
52 | subprocess.Popen(command, shell=True, stdout=null) |
@@ -17,6 +17,7 import os | |||||
17 | from .base import TestsBase |
|
17 | from .base import TestsBase | |
18 |
|
18 | |||
19 | from IPython.utils import py3compat |
|
19 | from IPython.utils import py3compat | |
|
20 | from IPython.testing import decorators as dec | |||
20 |
|
21 | |||
21 |
|
22 | |||
22 | #----------------------------------------------------------------------------- |
|
23 | #----------------------------------------------------------------------------- | |
@@ -80,6 +81,19 class TestNbConvertApp(TestsBase): | |||||
80 | assert os.path.isfile('notebook2.py') |
|
81 | assert os.path.isfile('notebook2.py') | |
81 |
|
82 | |||
82 |
|
83 | |||
|
84 | #@dec.skip_known_failure | |||
|
85 | def test_post_processor(self): | |||
|
86 | """ | |||
|
87 | Do post processors work? | |||
|
88 | """ | |||
|
89 | with self.create_temp_cwd(['notebook1.ipynb']): | |||
|
90 | assert not 'error' in self.call([IPYTHON, 'nbconvert', '--to="latex"', | |||
|
91 | 'notebook1', '--post="PDF"', 'PDFPostProcessor.verbose=True']).lower() | |||
|
92 | assert os.path.isfile('notebook1.tex') | |||
|
93 | print("\n\n\t" + "\n\t".join([f for f in os.listdir('.') if os.path.isfile(f)]) + "\n\n") | |||
|
94 | assert os.path.isfile('notebook1.pdf') | |||
|
95 | ||||
|
96 | ||||
83 | def test_template(self): |
|
97 | def test_template(self): | |
84 | """ |
|
98 | """ | |
85 | Do export templates work? |
|
99 | Do export templates work? |
General Comments 0
You need to be logged in to leave comments.
Login now