##// END OF EJS Templates
Cleanup and refactor, transformers
Jonathan Frederic -
Show More
@@ -1,19 +1,53 b''
1 """
2 Contains base transformer with an enable/disable flag.
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
1 from .base import ConfigurableTransformer
16 from .base import ConfigurableTransformer
2 from IPython.utils.traitlets import (Bool)
17 from IPython.utils.traitlets import (Bool)
3
18
4 class ActivatableTransformer(ConfigurableTransformer):
19 #-----------------------------------------------------------------------------
5 """A simple ConfigurableTransformers that have an enabled flag
20 # Classes and Functions
21 #-----------------------------------------------------------------------------
6
22
7 Inherit from that if you just want to have a transformer which is
23 class ActivatableTransformer(ConfigurableTransformer):
8 no-op by default but can be activated in profiles with
24 """ConfigurableTransformer that has an enabled flag
9
25
10 c.YourTransformerName.enabled = True
26 Inherit from this if you just want to have a transformer which is
27 enabled by default and can be disabled via the config by
28 'c.YourTransformerName.enabled = True'
11 """
29 """
12
30
13 enabled = Bool(True, config=True)
31 enabled = Bool(True, config=True)
14
32
15 def __call__(self, nb, other):
33 def __call__(self, nb, resources):
34 """
35 Transformation to apply on each notebook.
36
37 You should return modified nb, resources.
38 If you wish to apply your transform on each cell, you might want to
39 overwrite cell_transform method instead.
40
41 Parameters
42 ----------
43 nb : NotebookNode
44 Notebook being converted
45 resources : dictionary
46 Additional resources used in the conversion process. Allows
47 transformers to pass variables into the Jinja engine.
48 """
49
16 if not self.enabled :
50 if not self.enabled :
17 return nb, other
51 return nb, resources
18 else :
52 else :
19 return super(ActivatableTransformer, self).__call__(nb, other)
53 return super(ActivatableTransformer, self).__call__(nb, resources)
@@ -1,59 +1,99 b''
1 """
1 """
2 Module that regroups transformer that woudl be applied to ipynb files
2 Module that re-groups transformer that would be applied to iPyNB files
3 before going through the templating machinery.
3 before going through the templating machinery.
4
4
5 It exposes convenient classes to inherit from to access configurability
5 It exposes a convenient class to inherit from to access configurability.
6 as well as decorator to simplify tasks.
7 """
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
15 #-----------------------------------------------------------------------------
16 # Imports
17 #-----------------------------------------------------------------------------
8
18
9 from __future__ import print_function, absolute_import
19 from __future__ import print_function, absolute_import
10
20
11 from IPython.config.configurable import Configurable
21 from IPython.config.configurable import Configurable
12
22
23 #-----------------------------------------------------------------------------
24 # Classes and Functions
25 #-----------------------------------------------------------------------------
26
13 class ConfigurableTransformer(Configurable):
27 class ConfigurableTransformer(Configurable):
14 """ A configurable transformer
28 """ A configurable transformer
15
29
16 Inherit from this class if you wish to have configurability for your
30 Inherit from this class if you wish to have configurability for your
17 transformer.
31 transformer.
18
32
19 Any configurable traitlets this class exposed will be configurable in profiles
33 Any configurable traitlets this class exposed will be configurable in profiles
20 using c.SubClassName.atribute=value
34 using c.SubClassName.atribute=value
21
35
22 you can overwrite cell_transform to apply a transformation independently on each cell
36 you can overwrite cell_transform to apply a transformation independently on each cell
23 or __call__ if you prefer your own logic. See orresponding docstring for informations.
37 or __call__ if you prefer your own logic. See orresponding docstring for informations.
24
25
26 """
38 """
27
39
28 def __init__(self, config=None, **kw):
40 def __init__(self, config=None, **kw):
29 super(ConfigurableTransformer, self).__init__(config=config, **kw)
41 """
30
42 Public constructor
31 def __call__(self, nb, other):
43
32 """transformation to apply on each notebook.
44 Parameters
45 ----------
46 config : Config
47 Configuration file structure
48 **kw : misc
49 Additional arguments
50 """
33
51
34 received a handle to the current notebook as well as a dict of resources
52 super(ConfigurableTransformer, self).__init__(config=config, **kw)
35 which structure depends on the transformer.
36
53
37 You should return modified nb, other.
38
54
39 If you wish to apply on each cell, you might want to overwrite cell_transform method.
55 def __call__(self, nb, resources):
56 """
57 Transformation to apply on each notebook.
58
59 You should return modified nb, resources.
60 If you wish to apply your transform on each cell, you might want to
61 overwrite cell_transform method instead.
62
63 Parameters
64 ----------
65 nb : NotebookNode
66 Notebook being converted
67 resources : dictionary
68 Additional resources used in the conversion process. Allows
69 transformers to pass variables into the Jinja engine.
40 """
70 """
41 try :
71 try :
42 for worksheet in nb.worksheets :
72 for worksheet in nb.worksheets :
43 for index, cell in enumerate(worksheet.cells):
73 for index, cell in enumerate(worksheet.cells):
44 worksheet.cells[index], other = self.cell_transform(cell, other, 100*index)
74
45 return nb, other
75 #TODO: Why are we multiplying the index by 100 here???
76 worksheet.cells[index], resources = self.cell_transform(cell, resources, 100*index)
77 return nb, resources
46 except NotImplementedError:
78 except NotImplementedError:
47 raise NotImplementedError('should be implemented by subclass')
79 raise NotImplementedError('should be implemented by subclass')
48
80
49 def cell_transform(self, cell, other, index):
50 """
51 Overwrite if you want to apply a transformation on each cell,
52
53 receive the current cell, the resource dict and the index of current cell as parameter.
54
81
55 You should return modified cell and resource dict.
82 def cell_transform(self, cell, resources, index):
83 """
84 Overwrite if you want to apply a transformation on each cell. You
85 should return modified cell and resource dictionary.
86
87 Parameters
88 ----------
89 cell : NotebookNode cell
90 Notebook cell being processed
91 resources : dictionary
92 Additional resources used in the conversion process. Allows
93 transformers to pass variables into the Jinja engine.
94 index : int
95 Index of the cell being processed
56 """
96 """
57
97
58 raise NotImplementedError('should be implemented by subclass')
98 raise NotImplementedError('should be implemented by subclass')
59 return cell, other
99 return cell, resources
@@ -1,42 +1,75 b''
1 """Module that allows latex output notebooks to be conditioned before
2 they are converted. Exposes a decorator (@cell_preprocessor) in
3 addition to the coalesce_streams pre-proccessor.
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 # Functions
15 #-----------------------------------------------------------------------------
1
16
2 def cell_preprocessor(function):
17 def cell_preprocessor(function):
3 """ wrap a function to be executed on all cells of a notebook
18 """
19 Wrap a function to be executed on all cells of a notebook
4
20
5 wrapped function parameters :
21 Wrapped Parameters
6 cell : the cell
22 ----------
7 other : external resources
23 cell : NotebookNode cell
8 index : index of the cell
24 Notebook cell being processed
25 resources : dictionary
26 Additional resources used in the conversion process. Allows
27 transformers to pass variables into the Jinja engine.
28 index : int
29 Index of the cell being processed
9 """
30 """
10 def wrappedfunc(nb, other):
31
32 def wrappedfunc(nb, resources):
11 for worksheet in nb.worksheets :
33 for worksheet in nb.worksheets :
12 for index, cell in enumerate(worksheet.cells):
34 for index, cell in enumerate(worksheet.cells):
13 worksheet.cells[index], other = function(cell, other, index)
35 worksheet.cells[index], resources = function(cell, resources, index)
14 return nb, other
36 return nb, resources
15 return wrappedfunc
37 return wrappedfunc
16
38
17
39
18 @cell_preprocessor
40 @cell_preprocessor
19 def coalesce_streams(cell, other, count):
41 def coalesce_streams(cell, resources, index):
20 """merge consecutive sequences of stream output into single stream
42 """
21
43 Merge consecutive sequences of stream output into single stream
22 to prevent extra newlines inserted at flush calls
44 to prevent extra newlines inserted at flush calls
23
45
24 TODO: handle \r deletion
46 Parameters
47 ----------
48 cell : NotebookNode cell
49 Notebook cell being processed
50 resources : dictionary
51 Additional resources used in the conversion process. Allows
52 transformers to pass variables into the Jinja engine.
53 index : int
54 Index of the cell being processed
25 """
55 """
56
26 outputs = cell.get('outputs', [])
57 outputs = cell.get('outputs', [])
27 if not outputs:
58 if not outputs:
28 return cell, other
59 return cell, resources
60
29 last = outputs[0]
61 last = outputs[0]
30 new_outputs = [last]
62 new_outputs = [last]
63
31 for output in outputs[1:]:
64 for output in outputs[1:]:
32 if (output.output_type == 'stream' and
65 if (output.output_type == 'stream' and
33 last.output_type == 'stream' and
66 last.output_type == 'stream' and
34 last.stream == output.stream
67 last.stream == output.stream
35 ):
68 ):
36 last.text += output.text
69 last.text += output.text
37 else:
70 else:
38 new_outputs.append(output)
71 new_outputs.append(output)
39
72
40 cell.outputs = new_outputs
73 cell.outputs = new_outputs
41 return cell, other
74 return cell, resources
42
75
@@ -1,57 +1,119 b''
1 """Module that pre-processes the notebook for export to HTML.
2 """
3 #-----------------------------------------------------------------------------
4 # Copyright (c) 2013, the IPython Development Team.
5 #
6 # Distributed under the terms of the Modified BSD License.
7 #
8 # The full license is in the file COPYING.txt, distributed with this software.
9 #-----------------------------------------------------------------------------
10
11 #-----------------------------------------------------------------------------
12 # Imports
13 #-----------------------------------------------------------------------------
14
15 import os
16 import io
17
18 from pygments.formatters import HtmlFormatter
19
20 from IPython.utils import path
21
1 from .activatable import ActivatableTransformer
22 from .activatable import ActivatableTransformer
2
23
24 #-----------------------------------------------------------------------------
25 # Classes and functions
26 #-----------------------------------------------------------------------------
27
3 class CSSHtmlHeaderTransformer(ActivatableTransformer):
28 class CSSHtmlHeaderTransformer(ActivatableTransformer):
29 """
30 Transformer used to pre-process notebook for HTML output. Adds IPython notebook
31 front-end CSS and Pygments CSS to HTML output.
32 """
33
34 header = []
35
36 def __init__(self, config=None, **kw):
37 """
38 Public constructor
39
40 Parameters
41 ----------
42 config : Config
43 Configuration file structure
44 **kw : misc
45 Additional arguments
46 """
47
48 super(CSSHtmlHeaderTransformer, self).__init__(config=config, **kw)
49
50 if self.enabled :
51 self._regen_header()
52
4
53
5 def __call__(self, nb, resources):
54 def __call__(self, nb, resources):
6 """Fetch and add css to the resource dict
55 """Fetch and add CSS to the resource dictionary
7
56
8 Fetch css from IPython adn Pygment to add at the beginning
57 Fetch CSS from IPython and Pygments to add at the beginning
9 of the html files.
58 of the html files. Add this css in resources in the
59 "inlining.css" key
10
60
11 Add this css in resources in the "inlining.css" key
61 Parameters
62 ----------
63 nb : NotebookNode
64 Notebook being converted
65 resources : dictionary
66 Additional resources used in the conversion process. Allows
67 transformers to pass variables into the Jinja engine.
12 """
68 """
69
13 resources['inlining'] = {}
70 resources['inlining'] = {}
14 resources['inlining']['css'] = self.header
71 resources['inlining']['css'] = self.header
72
15 return nb, resources
73 return nb, resources
16
74
17 header = []
18
75
19 def __init__(self, config=None, **kw):
76 def _regen_header(self):
20 super(CSSHtmlHeaderTransformer, self).__init__(config=config, **kw)
77 """
21 if self.enabled :
78 Fills self.header with lines of CSS extracted from iPython
22 self.regen_header()
79 and Pygments.
80 """
23
81
24 def regen_header(self):
82 #Clear existing header.
25 ## lazy load asa this might not be use in many transformers
26 import os
27 from IPython.utils import path
28 import io
29 from pygments.formatters import HtmlFormatter
30 header = []
83 header = []
31 static = os.path.join(path.get_ipython_package_dir(),
84
32 'frontend', 'html', 'notebook', 'static',
85 #Construct path to iPy CSS
33 )
86 static = os.path.join(path.get_ipython_package_dir(), 'frontend',
87 'html', 'notebook', 'static')
34 css = os.path.join(static, 'css')
88 css = os.path.join(static, 'css')
89
90 #Load each known CSS file.
35 for sheet in [
91 for sheet in [
36 # do we need jquery and prettify?
92 # TODO: do we need jquery and prettify?
37 # os.path.join(static, 'jquery', 'css', 'themes', 'base',
93 # os.path.join(static, 'jquery', 'css', 'themes', 'base',
38 # 'jquery-ui.min.css'),
94 # 'jquery-ui.min.css'),
39 # os.path.join(static, 'prettify', 'prettify.css'),
95 # os.path.join(static, 'prettify', 'prettify.css'),
96
40 os.path.join(css, 'boilerplate.css'),
97 os.path.join(css, 'boilerplate.css'),
41 os.path.join(css, 'fbm.css'),
98 os.path.join(css, 'fbm.css'),
42 os.path.join(css, 'notebook.css'),
99 os.path.join(css, 'notebook.css'),
43 os.path.join(css, 'renderedhtml.css'),
100 os.path.join(css, 'renderedhtml.css'),
44 os.path.join(css, 'style.min.css'),
101 os.path.join(css, 'style.min.css'),
45 ]:
102 ]:
103
46 try:
104 try:
47 with io.open(sheet, encoding='utf-8') as f:
105 with io.open(sheet, encoding='utf-8') as file:
48 s = f.read()
106 file_text = file.read()
49 header.append(s)
107 header.append(file_text)
50 except IOError:
108 except IOError:
51 # new version of ipython with style.min.css, pass
109
110 # New version of iPython with style.min.css, pass
52 pass
111 pass
53
112
113 #Add pygments CSS
54 pygments_css = HtmlFormatter().get_style_defs('.highlight')
114 pygments_css = HtmlFormatter().get_style_defs('.highlight')
55 header.append(pygments_css)
115 header.append(pygments_css)
116
117 #Set header
56 self.header = header
118 self.header = header
57
119
@@ -1,66 +1,127 b''
1 """Module containing a transformer that extracts all of the figures from the
2 notebook file. The extracted figures are returned in the 'resources' dictionary.
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
1 from IPython.utils.traitlets import (Dict, List, Unicode)
16 from IPython.utils.traitlets import (Dict, List, Unicode)
2 from .activatable import ActivatableTransformer
17 from .activatable import ActivatableTransformer
3
18
4 class ExtractFigureTransformer(ActivatableTransformer):
19 #-----------------------------------------------------------------------------
20 # Constants
21 #-----------------------------------------------------------------------------
5
22
23 FIGURES_KEY = "figures"
24 BINARY_KEY = "binary"
25 TEXT_KEY = "text"
6
26
7 extra_ext_map = Dict({},
27 #-----------------------------------------------------------------------------
8 config=True,
28 # Classes
9 help="""extra map to override extension based on type.
29 #-----------------------------------------------------------------------------
10 Usefull for latex where svg will be converted to pdf before inclusion
30
31 class ExtractFigureTransformer(ActivatableTransformer):
32 """
33 Extracts all of the figures from the notebook file. The extracted
34 figures are returned in the 'resources' dictionary.
11 """
35 """
12 )
13
36
14 key_format_map = Dict({},
37 extra_extension_map = Dict({},
15 config=True,
38 config=True,
16 )
39 help="""Extra map to override extension based on type.
40 Useful for latex where SVG will be converted to PDF before inclusion
41 """)
17
42
18 figname_format_map = Dict({},
43 key_format_map = Dict({}, config=True,)
19 config=True,
44 figure_name_format_map = Dict({}, config=True)
20 )
21
45
22 display_data_priority = List(['svg', 'png', 'latex', 'jpg', 'jpeg','text'])
46 display_data_priority = List(['svg', 'png', 'latex', 'jpg', 'jpeg','text'])
23
47
24 #to do change this to .format {} syntax
48 #TODO: Change this to .format {} syntax
25 default_key_tpl = Unicode('_fig_{count:02d}.{ext}', config=True)
49 default_key_template = Unicode('_fig_{count:02d}.{ext}', config=True)
50
51 def cell_transform(self, cell, resources, index):
52 """
53 Apply a transformation on each cell,
54
55 Parameters
56 ----------
57 cell : NotebookNode cell
58 Notebook cell being processed
59 resources : dictionary
60 Additional resources used in the conversion process. Allows
61 transformers to pass variables into the Jinja engine.
62 index : int
63 Modified index of the cell being processed (see base.py)
64 """
65
66 if resources.get(FIGURES_KEY, None) is None :
67 resources[FIGURES_KEY] = {TEXT_KEY:{},BINARY_KEY:{}}
68
69 for out in cell.get('outputs', []):
70 for out_type in self.display_data_priority:
71
72 if out.hasattr(out_type):
73 figname, key, data, binary = self._new_figure(out[out_type], out_type, index)
74 out['key_'+out_type] = figname
75
76 if binary :
77 resources[FIGURES_KEY][BINARY_KEY][key] = data
78 else :
79 resources[FIGURES_KEY][TEXT_KEY][key] = data
80
81 index += 1
82 return cell, resources
83
84
85 def _get_override_extension(self, extension):
86 """Gets the overriden extension if it exists, else returns extension.
26
87
27 def _get_ext(self, ext):
88 Parameters
28 if ext in self.extra_ext_map :
89 ----------
29 return self.extra_ext_map[ext]
90 extension : str
30 return ext
91 File extension.
92 """
93
94 if extension in self.extra_extension_map :
95 return self.extra_extension_map[extension]
96
97 return extension
31
98
32 def _new_figure(self, data, fmt, count):
99
100 def _new_figure(self, data, format, index):
33 """Create a new figure file in the given format.
101 """Create a new figure file in the given format.
34
102
103 Parameters
104 ----------
105 data : str
106 Cell data (from Notebook node cell)
107 resources : dictionary
108 Additional resources used in the conversion process. Allows
109 transformers to pass variables into the Jinja engine.
110 index : int
111 Modified index of the cell being processed (see base.py)
35 """
112 """
36 tplf = self.figname_format_map.get(fmt, self.default_key_tpl)
37 tplk = self.key_format_map.get(fmt, self.default_key_tpl)
38
113
39 # option to pass the hash as data ?
114 figure_name_template = self.figure_name_format_map.get(format, self.default_key_template)
40 figname = tplf.format(count=count, ext=self._get_ext(fmt))
115 key_template = self.key_format_map.get(format, self.default_key_template)
41 key = tplk.format(count=count, ext=self._get_ext(fmt))
116
117 #TODO: option to pass the hash as data?
118 figure_name = figure_name_template.format(index=index, ext=self._get_override_extension(format))
119 key = key_template.format(index=index, ext=self._get_override_extension(format))
42
120
43 # Binary files are base64-encoded, SVG is already XML
121 #Binary files are base64-encoded, SVG is already XML
44 binary = False
122 binary = False
45 if fmt in ('png', 'jpg', 'pdf'):
123 if format in ('png', 'jpg', 'pdf'):
46 data = data.decode('base64')
124 data = data.decode('base64')
47 binary = True
125 binary = True
48
126
49 return figname, key, data, binary
127 return figure_name, key, data, binary
50
51
52 def cell_transform(self, cell, other, count):
53 if other.get('figures', None) is None :
54 other['figures'] = {'text':{},'binary':{}}
55 for out in cell.get('outputs', []):
56 for out_type in self.display_data_priority:
57 if out.hasattr(out_type):
58 figname, key, data, binary = self._new_figure(out[out_type], out_type, count)
59 out['key_'+out_type] = figname
60 if binary :
61 other['figures']['binary'][key] = data
62 else :
63 other['figures']['text'][key] = data
64 count = count+1
65 return cell, other
66
@@ -1,43 +1,53 b''
1 """Latex transformer.
1 """Module that allows latex output notebooks to be conditioned before
2
3 Module that allows latex output notebooks to be conditioned before
4 they are converted.
2 they are converted.
5 """
3 """
6 #-----------------------------------------------------------------------------
4 #-----------------------------------------------------------------------------
7 # Copyright (c) 2013, the IPython Development Team.
5 # Copyright (c) 2013, the IPython Development Team.
8 #
6 #
9 # Distributed under the terms of the Modified BSD License.
7 # Distributed under the terms of the Modified BSD License.
10 #
8 #
11 # The full license is in the file COPYING.txt, distributed with this software.
9 # The full license is in the file COPYING.txt, distributed with this software.
12 #-----------------------------------------------------------------------------
10 #-----------------------------------------------------------------------------
13
11
14 #-----------------------------------------------------------------------------
12 #-----------------------------------------------------------------------------
15 # Imports
13 # Imports
16 #-----------------------------------------------------------------------------
14 #-----------------------------------------------------------------------------
15
17 from __future__ import print_function, absolute_import
16 from __future__ import print_function, absolute_import
18
17
19 # Our own imports
18 # Our own imports
20 # Needed to override transformer
19 # Needed to override transformer
21 from .activatable import (ActivatableTransformer)
20 from .activatable import (ActivatableTransformer)
22 from nbconvert.filters import latex
21 from nbconvert.filters import latex
23
22
24 #-----------------------------------------------------------------------------
23 #-----------------------------------------------------------------------------
25 # Classes
24 # Classes
26 #-----------------------------------------------------------------------------
25 #-----------------------------------------------------------------------------
26
27 class LatexTransformer(ActivatableTransformer):
27 class LatexTransformer(ActivatableTransformer):
28 """
28 """
29 Converter for latex destined documents.
29 Converter for latex destined documents.
30 """
30 """
31
31
32 def cell_transform(self, cell, other, index):
32 def cell_transform(self, cell, resources, index):
33 """
33 """
34 Apply a transformation on each cell,
34 Apply a transformation on each cell,
35
35
36 receive the current cell, the resource dict and the index of current cell as parameter.
36 Parameters
37
37 ----------
38 Returns modified cell and resource dict.
38 cell : NotebookNode cell
39 Notebook cell being processed
40 resources : dictionary
41 Additional resources used in the conversion process. Allows
42 transformers to pass variables into the Jinja engine.
43 index : int
44 Modified index of the cell being processed (see base.py)
39 """
45 """
40
46
47 #If the cell is a markdown cell, preprocess the ampersands used to
48 #remove the space between them and their contents. Latex will complain
49 #if spaces exist between the ampersands and the math content.
50 #See filters.latex.rm_math_space for more information.
41 if hasattr(cell, "source") and cell.cell_type == "markdown":
51 if hasattr(cell, "source") and cell.cell_type == "markdown":
42 cell.source = latex.rm_math_space(cell.source)
52 cell.source = latex.rm_math_space(cell.source)
43 return cell, other
53 return cell, resources
@@ -1,17 +1,55 b''
1 """Module that pre-processes the notebook for export via Reveal.
2 """
3 #-----------------------------------------------------------------------------
4 # Copyright (c) 2013, the IPython Development Team.
5 #
6 # Distributed under the terms of the Modified BSD License.
7 #
8 # The full license is in the file COPYING.txt, distributed with this software.
9 #-----------------------------------------------------------------------------
10
11 #-----------------------------------------------------------------------------
12 # Imports
13 #-----------------------------------------------------------------------------
14
1 from .base import ConfigurableTransformer
15 from .base import ConfigurableTransformer
2
16
17 #-----------------------------------------------------------------------------
18 # Classes and functions
19 #-----------------------------------------------------------------------------
20
3 class RevealHelpTransformer(ConfigurableTransformer):
21 class RevealHelpTransformer(ConfigurableTransformer):
4
22
5 def __call__(self, nb, other):
23 def __call__(self, nb, resources):
24 """
25 Called once to 'transform' contents of the notebook.
26
27 Parameters
28 ----------
29 nb : NotebookNode
30 Notebook being converted
31 resources : dictionary
32 Additional resources used in the conversion process. Allows
33 transformers to pass variables into the Jinja engine.
34 """
35
36
6 for worksheet in nb.worksheets :
37 for worksheet in nb.worksheets :
7 for i, cell in enumerate(worksheet.cells):
38 for i, cell in enumerate(worksheet.cells):
39
40 #Make sure the cell has metadata.
8 if not cell.get('metadata', None):
41 if not cell.get('metadata', None):
9 break
42 break
43
44 #Get the slide type. If type is start of subslide or slide,
45 #end the last subslide/slide.
10 cell.metadata.slide_type = cell.metadata.get('slideshow', {}).get('slide_type', None)
46 cell.metadata.slide_type = cell.metadata.get('slideshow', {}).get('slide_type', None)
11 if cell.metadata.slide_type is None:
47 if cell.metadata.slide_type is None:
12 cell.metadata.slide_type = '-'
48 cell.metadata.slide_type = '-'
13 if cell.metadata.slide_type in ['slide']:
49 if cell.metadata.slide_type in ['slide']:
14 worksheet.cells[i - 1].metadata.slide_helper = 'slide_end'
50 worksheet.cells[i - 1].metadata.slide_helper = 'slide_end'
15 if cell.metadata.slide_type in ['subslide']:
51 if cell.metadata.slide_type in ['subslide']:
16 worksheet.cells[i - 1].metadata.slide_helper = 'subslide_end'
52 worksheet.cells[i - 1].metadata.slide_helper = 'subslide_end'
17 return nb, other No newline at end of file
53
54 return nb, resources
55 No newline at end of file
@@ -1,287 +1,282 b''
1 """Module that allows custom Sphinx parameters to be set on the notebook and
1 """Module that allows custom Sphinx parameters to be set on the notebook and
2 on the 'other' object passed into Jinja.
2 on the 'other' object passed into Jinja. Called prior to Jinja conversion
3 process.
3 """
4 """
4 #-----------------------------------------------------------------------------
5 #-----------------------------------------------------------------------------
5 # Copyright (c) 2013, the IPython Development Team.
6 # Copyright (c) 2013, the IPython Development Team.
6 #
7 #
7 # Distributed under the terms of the Modified BSD License.
8 # Distributed under the terms of the Modified BSD License.
8 #
9 #
9 # The full license is in the file COPYING.txt, distributed with this software.
10 # The full license is in the file COPYING.txt, distributed with this software.
10 #-----------------------------------------------------------------------------
11 #-----------------------------------------------------------------------------
11
12
12 #-----------------------------------------------------------------------------
13 #-----------------------------------------------------------------------------
13 # Imports
14 # Imports
14 #-----------------------------------------------------------------------------
15 #-----------------------------------------------------------------------------
16
15 from __future__ import print_function, absolute_import
17 from __future__ import print_function, absolute_import
16
18
17 # Stdlib imports
19 # Stdlib imports
18 # Used to find Sphinx package location
20 # Used to find Sphinx package location
19 import sphinx
21 import sphinx
20 import os.path
22 import os.path
21
23
22 # Used to determine python version
23 import sys
24
25 # Used to set the default date to today's date
24 # Used to set the default date to today's date
26 from datetime import date
25 from datetime import date
27
26
28 # Third-party imports
27 # Third-party imports
29 # Needed for Pygments latex definitions.
28 # Needed for Pygments latex definitions.
30 from pygments.formatters import LatexFormatter
29 from pygments.formatters import LatexFormatter
31
30
32 # Our own imports
31 # Our own imports
33 # Configurable traitlets
32 # Configurable traitlets
34 from IPython.utils.traitlets import Unicode, Bool
33 from IPython.utils.traitlets import Unicode, Bool
35
34
36 # Needed to override transformer
35 # Needed to override transformer
37 from .activatable import (ActivatableTransformer) #TODO
36 from .activatable import (ActivatableTransformer) #TODO
38
37
38 import nbconvert.utils.console
39
39 #-----------------------------------------------------------------------------
40 #-----------------------------------------------------------------------------
40 # Classes and functions
41 # Classes and functions
41 #-----------------------------------------------------------------------------
42 #-----------------------------------------------------------------------------
43
42 class SphinxTransformer(ActivatableTransformer):
44 class SphinxTransformer(ActivatableTransformer):
43 """
45 """
44 Sphinx utility transformer.
46 Sphinx utility transformer.
45
47
46 This transformer is used to set variables needed by the latex to build
48 This transformer is used to set variables needed by the latex to build
47 Sphinx stylized templates.
49 Sphinx stylized templates.
48 """
50 """
49
51
50 interactive = Bool(True, config=True, help="""
52 interactive = Bool(True, config=True, help="""
51 Allows you to define whether or not the Sphinx exporter will prompt
53 Allows you to define whether or not the Sphinx exporter will prompt
52 you for input during the conversion process. If this is set to false,
54 you for input during the conversion process. If this is set to false,
53 the author, version, release, date, and chapter_style traits should
55 the author, version, release, date, and chapter_style traits should
54 be set.
56 be set.
55 """)
57 """)
56
58
57 author = Unicode("Unknown Author", config=True, help="Author name")
59 author = Unicode("Unknown Author", config=True, help="Author name")
58
60
59 version = Unicode("", config=True, help="""Version number
61 version = Unicode("", config=True, help="""
62 Version number
60 You can leave this blank if you do not want to render a version number.
63 You can leave this blank if you do not want to render a version number.
61 Example: "1.0.0"
64 Example: "1.0.0"
62 """)
65 """)
63
66
64 release = Unicode("", config=True, help="""Release name
67 release = Unicode("", config=True, help="""
68 Release name
65 You can leave this blank if you do not want to render a release name.
69 You can leave this blank if you do not want to render a release name.
66 Example: "Rough Draft"
70 Example: "Rough Draft"
67 """)
71 """)
68
72
69 publish_date = Unicode("", config=True, help="""Publish date
73 publish_date = Unicode("", config=True, help="""
74 Publish date
70 This is the date to render on the document as the publish date.
75 This is the date to render on the document as the publish date.
71 Leave this blank to default to todays date.
76 Leave this blank to default to todays date.
72 Example: "June 12, 1990"
77 Example: "June 12, 1990"
73 """)
78 """)
74
79
75 chapter_style = Unicode("Bjarne", config=True, help="""Sphinx chapter style
80 chapter_style = Unicode("Bjarne", config=True, help="""
81 Sphinx chapter style
76 This is the style to use for the chapter headers in the document.
82 This is the style to use for the chapter headers in the document.
77 You may choose one of the following:
83 You may choose one of the following:
78 "Bjarne" (default)
84 "Bjarne" (default)
79 "Lenny"
85 "Lenny"
80 "Glenn"
86 "Glenn"
81 "Conny"
87 "Conny"
82 "Rejne"
88 "Rejne"
83 "Sonny" (used for international documents)
89 "Sonny" (used for international documents)
84 """)
90 """)
85
91
86 output_style = Unicode("notebook", config=True, help="""Nbconvert Ipython
92 output_style = Unicode("notebook", config=True, help="""
93 Nbconvert Ipython
87 notebook input/output formatting style.
94 notebook input/output formatting style.
88 You may choose one of the following:
95 You may choose one of the following:
89 "simple (recommended for long code segments)"
96 "simple (recommended for long code segments)"
90 "notebook" (default)
97 "notebook" (default)
91 """)
98 """)
92
99
93 center_output = Bool(False, config=True, help="""
100 center_output = Bool(False, config=True, help="""
94 Optional attempt to center all output. If this is false, no additional
101 Optional attempt to center all output. If this is false, no additional
95 formatting is applied.
102 formatting is applied.
96 """)
103 """)
97
104
98 use_headers = Bool(True, config=True, help="""
105 use_headers = Bool(True, config=True, help="""
99 Whether not a header should be added to the document.
106 Whether not a header should be added to the document.
100 """)
107 """)
101
108
109 #Allow the user to override the title of the notebook (useful for
110 #fancy document titles that the file system doesn't support.)
102 overridetitle = Unicode("", config=True, help="")
111 overridetitle = Unicode("", config=True, help="")
103
112
104 def __call__(self, nb, other):
113
114 def __call__(self, nb, resources):
105 """
115 """
106 Entry
116 Entrypoint
107 Since we are not interested in any additional manipulation on a cell
117 Since we are not interested in any additional manipulation on a cell
108 by cell basis, we do not call the base implementation.
118 by cell basis, we do not call the base implementation.
119
120 Parameters
121 ----------
122 nb : NotebookNode
123 Notebook being converted
124 resources : dictionary
125 Additional resources used in the conversion process. Allows
126 transformers to pass variables into the Jinja engine.
109 """
127 """
128
110 if self.enabled:
129 if self.enabled:
111 return self.transform(nb, other)
130 return self.transform(nb, resources)
112 else:
131 else:
113 return nb,other
132 return nb,resources
133
114
134
115 def transform(self, nb, other):
135 def transform(self, nb, resources):
116 """
136 """
117 Sphinx transformation to apply on each notebook.
137 Sphinx transformation to apply on each notebook.
138
139 Parameters
140 ----------
141 nb : NotebookNode
142 Notebook being converted
143 resources : dictionary
144 Additional resources used in the conversion process. Allows
145 transformers to pass variables into the Jinja engine.
118 """
146 """
119
147
120 # TODO: Add versatile method of additional notebook metadata. Include
148 # TODO: Add versatile method of additional notebook metadata. Include
121 # handling of multiple files. For now use a temporay namespace,
149 # handling of multiple files. For now use a temporay namespace,
122 # '_draft' to signify that this needs to change.
150 # '_draft' to signify that this needs to change.
123 if not "_draft" in nb.metadata:
151 if not "_draft" in nb.metadata:
124 nb.metadata._draft = {}
152 nb.metadata._draft = {}
125
153
126 if not "sphinx" in other:
154 if not "sphinx" in resources:
127 other["sphinx"] = {}
155 resources["sphinx"] = {}
128
156
129 if self.interactive:
157 if self.interactive:
130
158
131 # Prompt the user for additional meta data that doesn't exist currently
159 # Prompt the user for additional meta data that doesn't exist currently
132 # but would be usefull for Sphinx.
160 # but would be usefull for Sphinx.
133 nb.metadata._draft["author"] = self._prompt_author()
161 nb.metadata._draft["author"] = self._prompt_author()
134 nb.metadata._draft["version"] = self._prompt_version()
162 nb.metadata._draft["version"] = self._prompt_version()
135 nb.metadata._draft["release"] = self._prompt_release()
163 nb.metadata._draft["release"] = self._prompt_release()
136 nb.metadata._draft["date"] = self._prompt_date()
164 nb.metadata._draft["date"] = self._prompt_date()
137
165
138 # Prompt the user for the document style.
166 # Prompt the user for the document style.
139 other["sphinx"]["chapterstyle"] = self._prompt_chapter_title_style()
167 resources["sphinx"]["chapterstyle"] = self._prompt_chapter_title_style()
140 other["sphinx"]["outputstyle"] = self._prompt_output_style()
168 resources["sphinx"]["outputstyle"] = self._prompt_output_style()
141
169
142 # Small options
170 # Small options
143 other["sphinx"]["centeroutput"] = self._prompt_boolean("Do you want to center the output? (false)", False)
171 resources["sphinx"]["centeroutput"] = nbconvert.utils.console.prompt_boolean("Do you want to center the output? (false)", False)
144 other["sphinx"]["header"] = self._prompt_boolean("Should a Sphinx document header be used? (true)", True)
172 resources["sphinx"]["header"] = nbconvert.utils.console.prompt_boolean("Should a Sphinx document header be used? (true)", True)
145 else:
173 else:
146
174
147 # Try to use the traitlets.
175 # Try to use the traitlets.
148 nb.metadata._draft["author"] = self.author
176 nb.metadata._draft["author"] = self.author
149 nb.metadata._draft["version"] = self.version
177 nb.metadata._draft["version"] = self.version
150 nb.metadata._draft["release"] = self.release
178 nb.metadata._draft["release"] = self.release
151
179
152 # Use todays date if none is provided.
180 # Use todays date if none is provided.
153 if len(self.publish_date.strip()) == 0:
181 if len(self.publish_date.strip()) == 0:
154 nb.metadata._draft["date"] = date.today().strftime("%B %-d, %Y")
182 nb.metadata._draft["date"] = date.today().strftime("%B %-d, %Y")
155 else:
183 else:
156 nb.metadata._draft["date"] = self.publish_date
184 nb.metadata._draft["date"] = self.publish_date
157
185
158 # Sphinx traitlets.
186 # Sphinx traitlets.
159 other["sphinx"]["chapterstyle"] = self.chapter_style
187 resources["sphinx"]["chapterstyle"] = self.chapter_style
160 other["sphinx"]["outputstyle"] = self.output_style
188 resources["sphinx"]["outputstyle"] = self.output_style
161 other["sphinx"]["centeroutput"] = self.center_output
189 resources["sphinx"]["centeroutput"] = self.center_output
162 other["sphinx"]["header"] = self.use_headers
190 resources["sphinx"]["header"] = self.use_headers
163
191
164 # Find and pass in the path to the Sphinx dependencies.
192 # Find and pass in the path to the Sphinx dependencies.
165 other["sphinx"]["texinputs"] = os.path.abspath(sphinx.__file__ + "/../texinputs")
193 resources["sphinx"]["texinputs"] = os.path.abspath(sphinx.__file__ + "/../texinputs")
166
194
167 # Generate Pygments definitions for Latex
195 # Generate Pygments definitions for Latex
168 other["sphinx"]["pygment_definitions"] = self._generate_pygments_latex_def()
196 resources["sphinx"]["pygment_definitions"] = self._generate_pygments_latex_def()
169
197
170 if not (self.overridetitle == None or len(self.overridetitle.strip()) == 0):
198 if not (self.overridetitle == None or len(self.overridetitle.strip()) == 0):
171 nb.metadata.name = self.overridetitle
199 nb.metadata.name = self.overridetitle
172
200
173 # End
201 # End
174 return nb, other
202 return nb, resources
203
175
204
176 def _generate_pygments_latex_def(self):
205 def _generate_pygments_latex_def(self):
206 """
207 Generate the pygments latex definitions that allows pygments
208 to work in latex.
209 """
210
177 return LatexFormatter().get_style_defs()
211 return LatexFormatter().get_style_defs()
178
212
213
179 def _prompt_author(self):
214 def _prompt_author(self):
180 return self._input("Author name: ")
215 """
216 Prompt the user to input an Author name
217 """
218 return nbconvert.utils.console.input("Author name: ")
219
181
220
182 def _prompt_version(self):
221 def _prompt_version(self):
183 return self._input("Version (ie ""1.0.0""): ")
222 """
223 prompt the user to enter a version number
224 """
225 return nbconvert.utils.console.input("Version (ie ""1.0.0""): ")
226
184
227
185 def _prompt_release(self):
228 def _prompt_release(self):
186 return self._input("Release Name (ie ""Rough draft""): ")
229 """
230 Prompt the user to input a release name
231 """
232
233 return nbconvert.utils.console.input("Release Name (ie ""Rough draft""): ")
234
187
235
188 def _prompt_date(self):
236 def _prompt_date(self):
237 """
238 Prompt the user to enter a date
239 """
240
189 default_date = date.today().strftime("%B %-d, %Y")
241 default_date = date.today().strftime("%B %-d, %Y")
190 user_date = self._input("Date (deafults to \"" + default_date + "\"): ")
242 user_date = nbconvert.utils.console.input("Date (deafults to \"" + default_date + "\"): ")
191 if len(user_date.strip()) == 0:
243 if len(user_date.strip()) == 0:
192 user_date = default_date
244 user_date = default_date
193 return user_date
245 return user_date
194
246
195 def _prompt_boolean(self, prompt, default=False):
196 response = self._input(prompt)
197 response = response.strip().lower()
198
199 #Catch 1, true, yes as True
200 if len(response) > 0 and (response == "1" or response[0] == "t" or response[0] == "y"):
201 return True
202
203 #Catch 0, false, no as False
204 elif len(response) > 0 and (response == "0" or response[0] == "f" or response[0] == "n"):
205 return False
206
207 else:
208 return default
209
247
210 def _prompt_output_style(self):
248 def _prompt_output_style(self):
249 """
250 Prompts the user to pick an iPython output style.
251 """
211
252
212 # Dictionary of available output styles
253 # Dictionary of available output styles
213 styles = {1: "simple",
254 styles = {1: "simple",
214 2: "notebook"}
255 2: "notebook"}
215
256
216 #Append comments to the menu when displaying it to the user.
257 #Append comments to the menu when displaying it to the user.
217 comments = {1: "(recommended for long code segments)",
258 comments = {1: "(recommended for long code segments)",
218 2: "(default)"}
259 2: "(default)"}
219
260
220 return self._prompt_dictionary(styles, default_style=2, menu_comments=comments)
261 return nbconvert.utils.console.prompt_dictionary(styles, default_style=2, menu_comments=comments)
262
221
263
222 def _prompt_chapter_title_style(self):
264 def _prompt_chapter_title_style(self):
265 """
266 Prompts the user to pick a Sphinx chapter style
267 """
223
268
224 # Dictionary of available Sphinx styles
269 # Dictionary of available Sphinx styles
225 styles = {1: "Bjarne",
270 styles = {1: "Bjarne",
226 2: "Lenny",
271 2: "Lenny",
227 3: "Glenn",
272 3: "Glenn",
228 4: "Conny",
273 4: "Conny",
229 5: "Rejne",
274 5: "Rejne",
230 6: "Sonny"}
275 6: "Sonny"}
231
276
232 #Append comments to the menu when displaying it to the user.
277 #Append comments to the menu when displaying it to the user.
233 comments = {1: "(default)",
278 comments = {1: "(default)",
234 6: "(for international documents)"}
279 6: "(for international documents)"}
235
280
236 return self._prompt_dictionary(styles, menu_comments=comments)
281 return nbconvert.utils.console.prompt_dictionary(styles, menu_comments=comments)
237
238 def _prompt_dictionary(self, choices, default_style=1, menu_comments={}):
239
240 # Build the menu that will be displayed to the user with
241 # all of the options available.
242 prompt = ""
243 for key, value in choices.iteritems():
244 prompt += "%d %s " % (key, value)
245 if key in menu_comments:
246 prompt += menu_comments[key]
247 prompt += "\n"
248
249 # Continue to ask the user for a style until an appropriate
250 # one is specified.
251 response = -1
252 while (not response in choices):
253 try:
254 text_response = self._input(prompt)
255
256 # Use default option if no input.
257 if len(text_response.strip()) == 0:
258 response = default_style
259 else:
260 response = int(text_response)
261 except:
262 print("Error: Value is not an available option. 0 selects the default.\n")
263 return choices[response]
264
265 def _input(self, prompt_text):
266 """
267 Prompt the user for input.
268
282
No newline at end of file
269 The input command will change depending on the version of python
270 installed. To maintain support for 2 and earlier, we must use
271 raw_input in that case. Else use input.
272 """
273
274 # Try to get the python version. This command is only available in
275 # python 2 and later, so it's important that we catch the exception
276 # if the command isn't found.
277 try:
278 majorversion = sys.version_info[0]
279 except:
280 majorversion = 1
281
282 # Use the correct function to prompt the user for input depending on
283 # what python version the code is running in.
284 if majorversion >= 3:
285 return input(prompt_text)
286 else:
287 return raw_input(prompt_text)
General Comments 0
You need to be logged in to leave comments. Login now