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