##// END OF EJS Templates
Backport PR #5535: fix n^2 performance issue in coalesce_streams preprocessor...
MinRK -
Show More
@@ -58,7 +58,7 b' class APITest(NotebookTestBase):'
58 nb.worksheets = [ws]
58 nb.worksheets = [ws]
59 ws.cells.append(new_heading_cell(u'Created by test ³'))
59 ws.cells.append(new_heading_cell(u'Created by test ³'))
60 cc1 = new_code_cell(input=u'print(2*6)')
60 cc1 = new_code_cell(input=u'print(2*6)')
61 cc1.outputs.append(new_output(output_text=u'12'))
61 cc1.outputs.append(new_output(output_text=u'12', output_type='stream'))
62 cc1.outputs.append(new_output(output_png=png_green_pixel, output_type='pyout'))
62 cc1.outputs.append(new_output(output_png=png_green_pixel, output_type='pyout'))
63 ws.cells.append(cc1)
63 ws.cells.append(cc1)
64
64
@@ -1,27 +1,11 b''
1 """
1 """Base class for preprocessors"""
2 Module that re-groups preprocessor that would be applied to ipynb files
3 before going through the templating machinery.
4
5 It exposes a convenient class to inherit from to access configurability.
6 """
7 #-----------------------------------------------------------------------------
8 # Copyright (c) 2013, the IPython Development Team.
9 #
10 # Distributed under the terms of the Modified BSD License.
11 #
12 # The full license is in the file COPYING.txt, distributed with this software.
13 #-----------------------------------------------------------------------------
14
2
15 #-----------------------------------------------------------------------------
3 # Copyright (c) IPython Development Team.
16 # Imports
4 # Distributed under the terms of the Modified BSD License.
17 #-----------------------------------------------------------------------------
18
5
19 from ..utils.base import NbConvertBase
6 from ..utils.base import NbConvertBase
20 from IPython.utils.traitlets import Bool
7 from IPython.utils.traitlets import Bool
21
8
22 #-----------------------------------------------------------------------------
23 # Classes and Functions
24 #-----------------------------------------------------------------------------
25
9
26 class Preprocessor(NbConvertBase):
10 class Preprocessor(NbConvertBase):
27 """ A configurable preprocessor
11 """ A configurable preprocessor
@@ -30,7 +14,7 b' class Preprocessor(NbConvertBase):'
30 preprocessor.
14 preprocessor.
31
15
32 Any configurable traitlets this class exposed will be configurable in
16 Any configurable traitlets this class exposed will be configurable in
33 profiles using c.SubClassName.atribute=value
17 profiles using c.SubClassName.attribute = value
34
18
35 you can overwrite :meth:`preprocess_cell` to apply a transformation
19 you can overwrite :meth:`preprocess_cell` to apply a transformation
36 independently on each cell or :meth:`preprocess` if you prefer your own
20 independently on each cell or :meth:`preprocess` if you prefer your own
@@ -59,6 +43,7 b' class Preprocessor(NbConvertBase):'
59
43
60 def __call__(self, nb, resources):
44 def __call__(self, nb, resources):
61 if self.enabled:
45 if self.enabled:
46 self.log.debug("Applying preprocessor: %s", self.__class__.__name__)
62 return self.preprocess(nb,resources)
47 return self.preprocess(nb,resources)
63 else:
48 else:
64 return nb, resources
49 return nb, resources
@@ -68,9 +53,10 b' class Preprocessor(NbConvertBase):'
68 """
53 """
69 Preprocessing to apply on each notebook.
54 Preprocessing to apply on each notebook.
70
55
71 You should return modified nb, resources.
56 Must return modified nb, resources.
57
72 If you wish to apply your preprocessing to each cell, you might want
58 If you wish to apply your preprocessing to each cell, you might want
73 to overwrite preprocess_cell method instead.
59 to override preprocess_cell method instead.
74
60
75 Parameters
61 Parameters
76 ----------
62 ----------
@@ -80,20 +66,16 b' class Preprocessor(NbConvertBase):'
80 Additional resources used in the conversion process. Allows
66 Additional resources used in the conversion process. Allows
81 preprocessors to pass variables into the Jinja engine.
67 preprocessors to pass variables into the Jinja engine.
82 """
68 """
83 self.log.debug("Applying preprocess: %s", self.__class__.__name__)
69 for worksheet in nb.worksheets:
84 try :
70 for index, cell in enumerate(worksheet.cells):
85 for worksheet in nb.worksheets:
71 worksheet.cells[index], resources = self.preprocess_cell(cell, resources, index)
86 for index, cell in enumerate(worksheet.cells):
72 return nb, resources
87 worksheet.cells[index], resources = self.preprocess_cell(cell, resources, index)
88 return nb, resources
89 except NotImplementedError:
90 raise NotImplementedError('should be implemented by subclass')
91
73
92
74
93 def preprocess_cell(self, cell, resources, index):
75 def preprocess_cell(self, cell, resources, index):
94 """
76 """
95 Overwrite if you want to apply some preprocessing to each cell. You
77 Override if you want to apply some preprocessing to each cell.
96 should return modified cell and resource dictionary.
78 Must return modified cell and resource dictionary.
97
79
98 Parameters
80 Parameters
99 ----------
81 ----------
@@ -1,23 +1,10 b''
1 """Module that allows latex output notebooks to be conditioned before
1 """Preprocessor for merging consecutive stream outputs for easier handling."""
2 they are converted. Exposes a decorator (@cell_preprocessor) in
2
3 addition to the coalesce_streams pre-proccessor.
3 # Copyright (c) IPython Development Team.
4 """
5 #-----------------------------------------------------------------------------
6 # Copyright (c) 2013, the IPython Development Team.
7 #
8 # Distributed under the terms of the Modified BSD License.
4 # 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
5
13 #-----------------------------------------------------------------------------
14 # Imports
15 #-----------------------------------------------------------------------------
16 import re
6 import re
17
7
18 #-----------------------------------------------------------------------------
19 # Functions
20 #-----------------------------------------------------------------------------
21 def cell_preprocessor(function):
8 def cell_preprocessor(function):
22 """
9 """
23 Wrap a function to be executed on all cells of a notebook
10 Wrap a function to be executed on all cells of a notebook
@@ -34,12 +21,18 b' def cell_preprocessor(function):'
34 """
21 """
35
22
36 def wrappedfunc(nb, resources):
23 def wrappedfunc(nb, resources):
37 for worksheet in nb.worksheets :
24 from IPython.config import Application
25 if Application.initialized():
26 Application.instance().log.debug(
27 "Applying preprocessor: %s", function.__name__
28 )
29 for worksheet in nb.worksheets:
38 for index, cell in enumerate(worksheet.cells):
30 for index, cell in enumerate(worksheet.cells):
39 worksheet.cells[index], resources = function(cell, resources, index)
31 worksheet.cells[index], resources = function(cell, resources, index)
40 return nb, resources
32 return nb, resources
41 return wrappedfunc
33 return wrappedfunc
42
34
35 cr_pat = re.compile(r'.*\r(?=[^\n])')
43
36
44 @cell_preprocessor
37 @cell_preprocessor
45 def coalesce_streams(cell, resources, index):
38 def coalesce_streams(cell, resources, index):
@@ -64,7 +57,6 b' def coalesce_streams(cell, resources, index):'
64
57
65 last = outputs[0]
58 last = outputs[0]
66 new_outputs = [last]
59 new_outputs = [last]
67
68 for output in outputs[1:]:
60 for output in outputs[1:]:
69 if (output.output_type == 'stream' and
61 if (output.output_type == 'stream' and
70 last.output_type == 'stream' and
62 last.output_type == 'stream' and
@@ -72,12 +64,14 b' def coalesce_streams(cell, resources, index):'
72 ):
64 ):
73 last.text += output.text
65 last.text += output.text
74
66
75 # Respect \r characters.
76 cr_pat = re.compile(r'.*\r(?=[^\n])')
77 last.text = cr_pat.sub('', last.text)
78 else:
67 else:
79 new_outputs.append(output)
68 new_outputs.append(output)
80 last = output
69 last = output
81
70
71 # process \r characters
72 for output in new_outputs:
73 if output.output_type == 'stream':
74 output.text = cr_pat.sub('', output.text)
75
82 cell.outputs = new_outputs
76 cell.outputs = new_outputs
83 return cell, resources
77 return cell, resources
@@ -4,22 +4,10 b' The Python representation of a notebook is a nested structure of'
4 dictionary subclasses that support attribute access
4 dictionary subclasses that support attribute access
5 (IPython.utils.ipstruct.Struct). The functions in this module are merely
5 (IPython.utils.ipstruct.Struct). The functions in this module are merely
6 helpers to build the structs in the right form.
6 helpers to build the structs in the right form.
7
8 Authors:
9
10 * Brian Granger
11 """
7 """
12
8
13 #-----------------------------------------------------------------------------
9 # Copyright (c) IPython Development Team.
14 # Copyright (C) 2008-2011 The IPython Development Team
10 # Distributed under the terms of the Modified BSD License.
15 #
16 # Distributed under the terms of the BSD License. The full license is in
17 # the file COPYING, distributed as part of this software.
18 #-----------------------------------------------------------------------------
19
20 #-----------------------------------------------------------------------------
21 # Imports
22 #-----------------------------------------------------------------------------
23
11
24 import pprint
12 import pprint
25 import uuid
13 import uuid
@@ -51,15 +39,14 b' def from_dict(d):'
51 return d
39 return d
52
40
53
41
54 def new_output(output_type=None, output_text=None, output_png=None,
42 def new_output(output_type, output_text=None, output_png=None,
55 output_html=None, output_svg=None, output_latex=None, output_json=None,
43 output_html=None, output_svg=None, output_latex=None, output_json=None,
56 output_javascript=None, output_jpeg=None, prompt_number=None,
44 output_javascript=None, output_jpeg=None, prompt_number=None,
57 ename=None, evalue=None, traceback=None, stream=None, metadata=None):
45 ename=None, evalue=None, traceback=None, stream=None, metadata=None):
58 """Create a new output, to go in the ``cell.outputs`` list of a code cell.
46 """Create a new output, to go in the ``cell.outputs`` list of a code cell.
59 """
47 """
60 output = NotebookNode()
48 output = NotebookNode()
61 if output_type is not None:
49 output.output_type = unicode_type(output_type)
62 output.output_type = unicode_type(output_type)
63
50
64 if metadata is None:
51 if metadata is None:
65 metadata = {}
52 metadata = {}
@@ -143,15 +143,15 b' class TestMetadata(TestCase):'
143
143
144 class TestOutputs(TestCase):
144 class TestOutputs(TestCase):
145 def test_binary_png(self):
145 def test_binary_png(self):
146 out = new_output(output_png=b'\x89PNG\r\n\x1a\n')
146 out = new_output(output_png=b'\x89PNG\r\n\x1a\n', output_type='display_data')
147
147
148 def test_b64b6tes_png(self):
148 def test_b64b6tes_png(self):
149 out = new_output(output_png=b'iVBORw0KG')
149 out = new_output(output_png=b'iVBORw0KG', output_type='display_data')
150
150
151 def test_binary_jpeg(self):
151 def test_binary_jpeg(self):
152 out = new_output(output_jpeg=b'\xff\xd8')
152 out = new_output(output_jpeg=b'\xff\xd8', output_type='display_data')
153
153
154 def test_b64b6tes_jpeg(self):
154 def test_b64b6tes_jpeg(self):
155 out = new_output(output_jpeg=b'/9')
155 out = new_output(output_jpeg=b'/9', output_type='display_data')
156
156
157
157
General Comments 0
You need to be logged in to leave comments. Login now