##// END OF EJS Templates
create an activatable transformer classes...
Matthias BUSSONNIER -
Show More
@@ -1,236 +1,239 b''
1 1 """
2 2
3 3 """
4 4
5 5 from __future__ import print_function
6 6
7 7 from IPython.config.configurable import Configurable
8 8 from IPython.utils.traitlets import Unicode, Bool, Dict, List
9 9
10 10 class ConfigurableTransformers(Configurable):
11 11 """ A configurable transformer """
12 12
13 13 def __init__(self, config=None, **kw):
14 14 super(ConfigurableTransformers, self).__init__(config=config, **kw)
15 15
16 16 def __call__(self, nb, other):
17 17 try :
18 18 for worksheet in nb.worksheets :
19 19 for index, cell in enumerate(worksheet.cells):
20 20 worksheet.cells[index], other = self.cell_transform(cell, other, index)
21 21 return nb, other
22 22 except NotImplementedError as error :
23 23 raise NotImplementedError('should be implemented by subclass')
24 24
25 25 def cell_transform(self, cell, other, index):
26 26 """
27 27 Overwrite if you want to apply a transformation on each cell
28 28 """
29 29 raise NotImplementedError('should be implemented by subclass')
30 30
31 31
32 class Foobar(ConfigurableTransformers):
33 message = Unicode('-- nothing', config=True)
32 class ActivatableTransformer(ConfigurableTransformers):
34 33
34 active = Bool(False, config=True)
35 35
36 def cell_transform(self, cell, other, index):
37 return cell, other
36 def __call__(self, nb, other):
37 if not self.active :
38 return nb,other
39 else :
40 return super(ActivatableTransformer,self).__call__(nb, other)
38 41
39 42
40 43 def cell_preprocessor(function):
41 44 """ wrap a function to be executed on all cells of a notebook
42 45
43 46 wrapped function parameters :
44 47 cell : the cell
45 48 other : external resources
46 49 index : index of the cell
47 50 """
48 51 def wrappedfunc(nb, other):
49 52 for worksheet in nb.worksheets :
50 53 for index, cell in enumerate(worksheet.cells):
51 54 worksheet.cells[index], other = function(cell, other, index)
52 55 return nb, other
53 56 return wrappedfunc
54 57
55 58
56 59 @cell_preprocessor
57 60 def haspyout_transformer(cell, other, count):
58 61 """
59 62 Add a haspyout flag to cell that have it
60 63
61 64 Easier for templating, where you can't know in advance
62 65 wether to write the out prompt
63 66
64 67 """
65 68 cell.type = cell.cell_type
66 69 cell.haspyout = False
67 70 for out in cell.get('outputs', []):
68 71 if out.output_type == 'pyout':
69 72 cell.haspyout = True
70 73 break
71 74 return cell, other
72 75
73 76
74 77 # todo, make the key part configurable.
75 78
76 class ExtractFigureTransformer(ConfigurableTransformers):
79 class ExtractFigureTransformer(ActivatableTransformer):
77 80 enabled = Bool(False,
78 81 config=True,
79 82 help=""" If set to false, this transformer will be no-op """
80 83 )
81 84
82 85 extra_ext_map = Dict({},
83 86 config=True,
84 87 help="""extra map to override extension based on type.
85 88 Usefull for latex where svg will be converted to pdf before inclusion
86 89 """
87 90 )
88 91 display_data_priority = List(['html', 'pdf', 'svg', 'latex', 'png', 'jpg', 'jpeg' , 'text'],
89 92 config=True,
90 93 help= """
91 94 An ordered list of prefered output type, the first
92 95 encounterd will usually be used when converting discarding
93 96 the others.
94 97 """
95 98 )
96 99
97 100
98 101 #to do change this to .format {} syntax
99 102 key_tpl = Unicode('_fig_%02i.%s', config=True)
100 103
101 104 def _get_ext(self, ext):
102 105 if ext in self.extra_ext_map :
103 106 return self.extra_ext_map[ext]
104 107 return ext
105 108
106 109 def _new_figure(self, data, fmt, count):
107 110 """Create a new figure file in the given format.
108 111
109 112 Returns a path relative to the input file.
110 113 """
111 114 figname = self.key_tpl % (count, self._get_ext(fmt))
112 115 key = self.key_tpl % (count, fmt)
113 116
114 117 # Binary files are base64-encoded, SVG is already XML
115 118 if fmt in ('png', 'jpg', 'pdf'):
116 119 data = data.decode('base64')
117 120
118 121 return figname, key, data
119 122
120 123
121 124 def cell_transform(self, cell, other, count):
122 125 if not self.enabled:
123 126 return cell, other
124 127 if other.get('figures',None) is None :
125 128 other['figures']={}
126 129 for i, out in enumerate(cell.get('outputs', [])):
127 130 for type in self.display_data_priority:
128 131 if out.hasattr(type):
129 132 figname, key, data = self._new_figure(out[type], type, count)
130 133 out['key_'+type] = figname
131 134 other['figures'][key] = data
132 135 count = count+1
133 136 return cell, other
134 137
135 138 class RevealHelpTransformer(ConfigurableTransformers):
136 139
137 140 section_open = False
138 141 subsection_open = False
139 142 fragment_open = False
140 143
141 144 def open_subsection(self):
142 145 self.subsection_open = True
143 146 return True
144 147
145 148 def open_section(self):
146 149 self.section_open = True
147 150 return True
148 151
149 152 def open_fragment(self):
150 153 self.fragment_open = True
151 154 return True
152 155
153 156 # could probaly write those maybe_close/open
154 157 # with a function functor
155 158 def maybe_close_section(self):
156 159 """return True is already open, false otherwise
157 160 and change state to close
158 161 """
159 162 if self.section_open :
160 163 self.section_open = False
161 164 return True
162 165 else :
163 166 return False
164 167
165 168 def maybe_open_section(self):
166 169 """return True is already open, false otherwise
167 170 and change state to close
168 171 """
169 172 if not self.section_open :
170 173 self.section_open = True
171 174 return True
172 175 else :
173 176 return False
174 177
175 178 def maybe_open_subsection(self):
176 179 """return True is already open, false otherwise
177 180 and change state to close
178 181 """
179 182 if not self.subsection_open :
180 183 self.subsection_open = True
181 184 return True
182 185 else :
183 186 return False
184 187
185 188 def maybe_close_subsection(self):
186 189 """return True is already open, false otherwise
187 190 and change state to close
188 191 """
189 192 if self.subsection_open :
190 193 self.subsection_open = False
191 194 return True
192 195 else :
193 196 return False
194 197
195 198 def maybe_close_fragment(self):
196 199 """return True is already open, false otherwise
197 200 and change state to close
198 201 """
199 202 if self.fragment_open :
200 203 self.fragment_open = False
201 204 return True
202 205 else :
203 206 return False
204 207
205 208 def cell_transform(self, cell, other,count):
206 209 ctype = cell.metadata.get('slideshow',{}).get('slide_type',None)
207 210 if ctype in [None, '-'] :
208 211 cell.metadata.slideshow = {}
209 212 cell.metadata.slideshow['slide_type'] = None
210 213 elif ctype == 'fragment':
211 214 cell.metadata.slideshow.close_fragment = self.maybe_close_fragment()
212 215 cell.metadata.slideshow.close_subsection = False
213 216 cell.metadata.slideshow.close_section = False
214 217
215 218 cell.metadata.slideshow.open_section = self.maybe_open_section()
216 219 cell.metadata.slideshow.open_subsection = self.maybe_open_subsection()
217 220 cell.metadata.slideshow.open_fragment = self.open_fragment()
218 221
219 222 elif ctype == 'subslide':
220 223 cell.metadata.slideshow.close_fragment = self.maybe_close_fragment()
221 224 cell.metadata.slideshow.close_subsection = self.maybe_close_subsection()
222 225 cell.metadata.slideshow.close_section = False
223 226
224 227 cell.metadata.slideshow.open_section = self.maybe_open_section()
225 228 cell.metadata.slideshow.open_subsection = self.open_subsection()
226 229 cell.metadata.slideshow.open_fragment = False
227 230 elif ctype == 'slide':
228 231 cell.metadata.slideshow.close_fragment = self.maybe_close_fragment()
229 232 cell.metadata.slideshow.close_subsection = self.maybe_close_subsection()
230 233 cell.metadata.slideshow.close_section = self.maybe_close_section()
231 234
232 235 cell.metadata.slideshow.open_section = self.open_section()
233 236 cell.metadata.slideshow.open_subsection = self.open_subsection()
234 237 cell.metadata.slideshow.open_fragment = False
235 238 return cell,other
236 239
@@ -1,136 +1,135 b''
1 1 #!/usr/bin/env python
2 2 """
3 3 ================================================================================
4 4
5 5 |,---. | | , .| |
6 6 ||---', .|--- |---.,---.,---. |\ ||---.,---.,---.,---.. ,,---.,---.|---
7 7 || | || | || || | | \ || || | || | \ / |---'| |
8 8 `` `---|`---'` '`---'` ' ` `'`---'`---'`---'` ' `' `---'` `---'
9 9 `---'
10 10 ================================================================================
11 11
12 12 Highly experimental for now
13 13
14 14 """
15 15 #-----------------------------------------------------------------------------
16 16 # Imports
17 17 #-----------------------------------------------------------------------------
18 18 from __future__ import print_function
19 19 import sys
20 20 import io
21 21 import os
22 22
23 23 from converters.template import *
24 24 from converters.template import ConverterTemplate
25 25 from converters.html import ConverterHTML
26 26 # From IPython
27 27
28 28 # All the stuff needed for the configurable things
29 29 from IPython.config.application import Application
30 30 from IPython.config.loader import ConfigFileNotFound
31 31 from IPython.utils.traitlets import List, Unicode, Type, Bool, Dict, CaselessStrEnum
32 32
33 from converters.transformers import (ConfigurableTransformers,Foobar,ExtractFigureTransformer)
33 from converters.transformers import (ConfigurableTransformers,ExtractFigureTransformer)
34 34
35 35
36 36 class NbconvertApp(Application):
37 37
38 38 stdout = Bool(True, config=True)
39 39 write = Bool(False, config=True)
40 40
41 41 fileext = Unicode('txt', config=True)
42 42
43 43 aliases = {
44 44 'stdout':'NbconvertApp.stdout',
45 45 'write':'NbconvertApp.write',
46 46 }
47 47
48 48 flags= {}
49 49 flags['no-stdout'] = (
50 50 {'NbconvertApp' : {'stdout' : False}},
51 51 """the doc for this flag
52 52
53 53 """
54 54 )
55 55
56 56 def __init__(self, **kwargs):
57 57 super(NbconvertApp, self).__init__(**kwargs)
58 58 self.classes.insert(0,ConverterTemplate)
59 59 # register class here to have help with help all
60 60 self.classes.insert(0,ExtractFigureTransformer)
61 self.classes.insert(0,Foobar)
62 61 # ensure those are registerd
63 62
64 63 def load_config_file(self, profile_name):
65 64 try:
66 65 Application.load_config_file(
67 66 self,
68 67 profile_name+'.nbcv',
69 68 path=[os.path.join(os.getcwdu(),'profile')]
70 69 )
71 70 except ConfigFileNotFound:
72 71 self.log.warn("Config file for profile '%s' not found, giving up ",profile_name)
73 72 exit(1)
74 73
75 74
76 75 def initialize(self, argv=None):
77 76 self.parse_command_line(argv)
78 77 cl_config = self.config
79 78 profile_file = sys.argv[1]
80 79 self.load_config_file(profile_file)
81 80 self.update_config(cl_config)
82 81
83 82
84 83
85 84 def run(self):
86 85 """Convert a notebook to html in one step"""
87 86 template_file = (self.extra_args or [None])[0]
88 87 ipynb_file = (self.extra_args or [None])[1]
89 88
90 89 template_file = sys.argv[1]
91 90
92 91 C = ConverterTemplate(config=self.config)
93 92
94 93 output,resources = C.from_filename(ipynb_file)
95 94 if self.stdout :
96 95 print(output.encode('utf-8'))
97 96
98 97 out_root = ipynb_file[:-6].replace('.','_').replace(' ','_')
99 98
100 99 keys = resources.get('figures',{}).keys()
101 100 if self.write :
102 101 with io.open(os.path.join(out_root+'.'+self.fileext),'w') as f:
103 102 f.write(output)
104 103 if keys :
105 104 if self.write and not os.path.exists(out_root+'_files'):
106 105 os.mkdir(out_root+'_files')
107 106 for key in keys:
108 107 if self.write:
109 108 with io.open(os.path.join(out_root+'_files',key),'wb') as f:
110 109 print(' writing to ',os.path.join(out_root,key))
111 110 f.write(resources['figures'][key])
112 111 if self.stdout:
113 112 print('''
114 113 ====================== Keys in Resources ==================================
115 114 ''')
116 115 print(resources['figures'].keys())
117 116 print("""
118 117 ===========================================================================
119 118 you are responsible from writing those data do a file in the right place if
120 119 they need to be.
121 120 ===========================================================================
122 121 """)
123 122
124 123 def main():
125 124 """Convert a notebook to html in one step"""
126 125 app = NbconvertApp.instance()
127 126 app.description = __doc__
128 127 app.initialize()
129 128 app.start()
130 129 app.run()
131 130 #-----------------------------------------------------------------------------
132 131 # Script main
133 132 #-----------------------------------------------------------------------------
134 133
135 134 if __name__ == '__main__':
136 135 main()
General Comments 0
You need to be logged in to leave comments. Login now