##// END OF EJS Templates
Change to encodestring to b64encode to avoid newlines in the data URI...
David Österberg -
Show More
@@ -1,487 +1,489 b''
1 """Various display related classes.
1 """Various display related classes.
2
2
3 Authors : MinRK, gregcaporaso, dannystaple
3 Authors : MinRK, gregcaporaso, dannystaple
4 """
4 """
5 from os.path import exists, isfile, splitext, abspath, join, isdir
5 from os.path import exists, isfile, splitext, abspath, join, isdir
6 from os import walk, sep
6 from os import walk, sep
7
7
8 from IPython.core.display import DisplayObject
8 from IPython.core.display import DisplayObject
9
9
10
10
11 class Audio(DisplayObject):
11 class Audio(DisplayObject):
12 """Create an audio object.
12 """Create an audio object.
13
13
14 When this object is returned by an input cell or passed to the
14 When this object is returned by an input cell or passed to the
15 display function, it will result in Audio controls being displayed
15 display function, it will result in Audio controls being displayed
16 in the frontend (only works in the notebook).
16 in the frontend (only works in the notebook).
17
17
18 Parameters
18 Parameters
19 ----------
19 ----------
20 data : numpy array, unicode, str or bytes
20 data : numpy array, unicode, str or bytes
21 Can be a
21 Can be a
22 * Numpy array containing the desired waveform,
22 * Numpy array containing the desired waveform,
23 * String containing the filename
23 * String containing the filename
24 * Bytestring containing raw PCM data or
24 * Bytestring containing raw PCM data or
25 * URL pointing to a file on the web.
25 * URL pointing to a file on the web.
26
26
27 If the array option is used the waveform will be normalized.
27 If the array option is used the waveform will be normalized.
28
28
29 If a filename or url is used the format support will be browser
29 If a filename or url is used the format support will be browser
30 dependent.
30 dependent.
31 url : unicode
31 url : unicode
32 A URL to download the data from.
32 A URL to download the data from.
33 filename : unicode
33 filename : unicode
34 Path to a local file to load the data from.
34 Path to a local file to load the data from.
35 embed : boolean
35 embed : boolean
36 Should the image data be embedded using a data URI (True) or should
36 Should the image data be embedded using a data URI (True) or should
37 the original source be referenced. Set this to True if you want the
37 the original source be referenced. Set this to True if you want the
38 audio to playable later with no internet connection in the notebook.
38 audio to playable later with no internet connection in the notebook.
39
39
40 Default is `True`, unless the keyword argument `url` is set, then
40 Default is `True`, unless the keyword argument `url` is set, then
41 default value is `False`.
41 default value is `False`.
42 rate : integer
42 rate : integer
43 The sampling rate of the raw data.
43 The sampling rate of the raw data.
44 Only required when data parameter is being used as an array
44 Only required when data parameter is being used as an array
45 autoplay : bool
45 autoplay : bool
46 Set to True if the audio should immediately start playing.
46 Set to True if the audio should immediately start playing.
47 Default is `False`.
47 Default is `False`.
48
48
49 Examples
49 Examples
50 --------
50 --------
51
51
52 # Generate a sound
52 # Generate a sound
53 import numpy as np
53 import numpy as np
54 framerate = 44100
54 framerate = 44100
55 t = np.linspace(0,5,framerate*5)
55 t = np.linspace(0,5,framerate*5)
56 data = np.sin(2*np.pi*440*np.sin(10*t**2))
56 data = np.sin(2*np.pi*440*np.sin(10*t**2))
57 Audio(data,rate=framerate)
57 Audio(data,rate=framerate)
58
58
59 Audio("http://www.nch.com.au/acm/8k16bitpcm.wav")
59 Audio("http://www.nch.com.au/acm/8k16bitpcm.wav")
60 Audio(url="http://media.bradsucks.net/albums/ooi-128/01_-_Brad_Sucks_-_Dropping_out_of_School.mp3")
60 Audio(url="http://media.bradsucks.net/albums/ooi-128/01_-_Brad_Sucks_-_Dropping_out_of_School.mp3")
61 Audio(url="http://www.w3schools.com/html/horse.ogg", embed=True)
61 Audio(url="http://www.w3schools.com/html/horse.ogg", embed=True)
62
62
63 Audio('/path/to/sound.wav')
63 Audio('/path/to/sound.wav')
64 Audio(filename='/path/to/sound.ogg')
64 Audio(filename='/path/to/sound.ogg')
65
65
66 Audio(b'RAW_WAV_DATA..)
66 Audio(b'RAW_WAV_DATA..)
67 Audio(data=b'RAW_WAV_DATA..)
67 Audio(data=b'RAW_WAV_DATA..)
68
68
69 """
69 """
70
70
71 def __init__(self, data=None, filename=None, url=None, embed=None, rate=None, autoplay=False):
71 def __init__(self, data=None, filename=None, url=None, embed=None, rate=None, autoplay=False):
72 if filename is None and url is None and data is None:
72 if filename is None and url is None and data is None:
73 raise ValueError("No image data found. Expecting filename, url, or data.")
73 raise ValueError("No image data found. Expecting filename, url, or data.")
74 if embed is False and url is None:
74 if embed is False and url is None:
75 raise ValueError("No url found. Expecting url when embed=False")
75 raise ValueError("No url found. Expecting url when embed=False")
76
76
77 if url is not None and embed is not True:
77 if url is not None and embed is not True:
78 self.embed = False
78 self.embed = False
79 else:
79 else:
80 self.embed = True
80 self.embed = True
81 self.autoplay = autoplay
81 self.autoplay = autoplay
82 super(Audio, self).__init__(data=data, url=url, filename=filename)
82 super(Audio, self).__init__(data=data, url=url, filename=filename)
83
83
84 if self.data is not None and not isinstance(self.data, bytes):
84 if self.data is not None and not isinstance(self.data, bytes):
85 self.data = self._make_wav(data,rate)
85 self.data = self._make_wav(data,rate)
86
86
87 def reload(self):
87 def reload(self):
88 """Reload the raw data from file or URL."""
88 """Reload the raw data from file or URL."""
89 import mimetypes
89 import mimetypes
90 if self.embed:
90 if self.embed:
91 super(Audio, self).reload()
91 super(Audio, self).reload()
92
92
93 if self.filename is not None:
93 if self.filename is not None:
94 self.mimetype = mimetypes.guess_type(self.filename)[0]
94 self.mimetype = mimetypes.guess_type(self.filename)[0]
95 elif self.url is not None:
95 elif self.url is not None:
96 self.mimetype = mimetypes.guess_type(self.url)[0]
96 self.mimetype = mimetypes.guess_type(self.url)[0]
97 else:
97 else:
98 self.mimetype = "audio/wav"
98 self.mimetype = "audio/wav"
99
99
100
100
101 def _make_wav(self,data,rate):
101 def _make_wav(self,data,rate):
102 """ Transform a numpy array to a PCM bytestring """
102 """ Transform a numpy array to a PCM bytestring """
103 import struct
103 import struct
104 from io import BytesIO
104 from io import BytesIO
105 import wave
105 import wave
106 maxabsvalue = max(map(abs,data))
106 maxabsvalue = max(map(abs,data))
107 scaled = map(lambda x: int(x/maxabsvalue*32767), data)
107 scaled = map(lambda x: int(x/maxabsvalue*32767), data)
108 fp = BytesIO()
108 fp = BytesIO()
109 waveobj = wave.open(fp,mode='wb')
109 waveobj = wave.open(fp,mode='wb')
110 waveobj.setnchannels(1)
110 waveobj.setnchannels(1)
111 waveobj.setframerate(rate)
111 waveobj.setframerate(rate)
112 waveobj.setsampwidth(2)
112 waveobj.setsampwidth(2)
113 waveobj.setcomptype('NONE','NONE')
113 waveobj.setcomptype('NONE','NONE')
114 waveobj.writeframes(b''.join([struct.pack('<h',x) for x in scaled]))
114 waveobj.writeframes(b''.join([struct.pack('<h',x) for x in scaled]))
115 val = fp.getvalue()
115 val = fp.getvalue()
116 waveobj.close()
116 waveobj.close()
117 return val
117 return val
118
118
119 def _data_and_metadata(self):
119 def _data_and_metadata(self):
120 """shortcut for returning metadata with url information, if defined"""
120 """shortcut for returning metadata with url information, if defined"""
121 md = {}
121 md = {}
122 if self.url:
122 if self.url:
123 md['url'] = self.url
123 md['url'] = self.url
124 if md:
124 if md:
125 return self.data, md
125 return self.data, md
126 else:
126 else:
127 return self.data
127 return self.data
128
128
129 def _repr_html_(self):
129 def _repr_html_(self):
130 src = """
130 src = """
131 <audio controls="controls" {autoplay}>
131 <audio controls="controls" {autoplay}>
132 <source src="{src}" type="{type}" />
132 <source src="{src}" type="{type}" />
133 Your browser does not support the audio element.
133 Your browser does not support the audio element.
134 </audio>
134 </audio>
135 """
135 """
136 return src.format(src=self.src_attr(),type=self.mimetype, autoplay=self.autoplay_attr())
136 return src.format(src=self.src_attr(),type=self.mimetype, autoplay=self.autoplay_attr())
137
137
138 def src_attr(self):
138 def src_attr(self):
139 import base64
139 import base64
140 if self.embed and (self.data is not None):
140 if self.embed and (self.data is not None):
141 return """data:{type};base64,{base64}""".format(type=self.mimetype, base64=base64.encodestring(self.data))
141 data = base64=base64.b64encode(self.data).decode('ascii'))
142 return """data:{type};base64,{base64}""".format(type=self.mimetype,
143 base64=data)
142 elif self.url is not None:
144 elif self.url is not None:
143 return self.url
145 return self.url
144 else:
146 else:
145 return ""
147 return ""
146
148
147 def autoplay_attr(self):
149 def autoplay_attr(self):
148 if(self.autoplay):
150 if(self.autoplay):
149 return 'autoplay="autoplay"'
151 return 'autoplay="autoplay"'
150 else:
152 else:
151 return ''
153 return ''
152
154
153 class IFrame(object):
155 class IFrame(object):
154 """
156 """
155 Generic class to embed an iframe in an IPython notebook
157 Generic class to embed an iframe in an IPython notebook
156 """
158 """
157
159
158 iframe = """
160 iframe = """
159 <iframe
161 <iframe
160 width="{width}"
162 width="{width}"
161 height={height}"
163 height={height}"
162 src="{src}{params}"
164 src="{src}{params}"
163 frameborder="0"
165 frameborder="0"
164 allowfullscreen
166 allowfullscreen
165 ></iframe>
167 ></iframe>
166 """
168 """
167
169
168 def __init__(self, src, width, height, **kwargs):
170 def __init__(self, src, width, height, **kwargs):
169 self.src = src
171 self.src = src
170 self.width = width
172 self.width = width
171 self.height = height
173 self.height = height
172 self.params = kwargs
174 self.params = kwargs
173
175
174 def _repr_html_(self):
176 def _repr_html_(self):
175 """return the embed iframe"""
177 """return the embed iframe"""
176 if self.params:
178 if self.params:
177 from urllib import urlencode
179 from urllib import urlencode
178 params = "?" + urlencode(self.params)
180 params = "?" + urlencode(self.params)
179 else:
181 else:
180 params = ""
182 params = ""
181 return self.iframe.format(src=self.src,
183 return self.iframe.format(src=self.src,
182 width=self.width,
184 width=self.width,
183 height=self.height,
185 height=self.height,
184 params=params)
186 params=params)
185
187
186 class YouTubeVideo(IFrame):
188 class YouTubeVideo(IFrame):
187 """Class for embedding a YouTube Video in an IPython session, based on its video id.
189 """Class for embedding a YouTube Video in an IPython session, based on its video id.
188
190
189 e.g. to embed the video on this page:
191 e.g. to embed the video on this page:
190
192
191 http://www.youtube.com/watch?v=foo
193 http://www.youtube.com/watch?v=foo
192
194
193 you would do:
195 you would do:
194
196
195 vid = YouTubeVideo("foo")
197 vid = YouTubeVideo("foo")
196 display(vid)
198 display(vid)
197
199
198 To start from 30 seconds:
200 To start from 30 seconds:
199
201
200 vid = YouTubeVideo("abc", start=30)
202 vid = YouTubeVideo("abc", start=30)
201 display(vid)
203 display(vid)
202
204
203 To calculate seconds from time as hours, minutes, seconds use:
205 To calculate seconds from time as hours, minutes, seconds use:
204 start=int(timedelta(hours=1, minutes=46, seconds=40).total_seconds())
206 start=int(timedelta(hours=1, minutes=46, seconds=40).total_seconds())
205
207
206 Other parameters can be provided as documented at
208 Other parameters can be provided as documented at
207 https://developers.google.com/youtube/player_parameters#parameter-subheader
209 https://developers.google.com/youtube/player_parameters#parameter-subheader
208 """
210 """
209
211
210 def __init__(self, id, width=400, height=300, **kwargs):
212 def __init__(self, id, width=400, height=300, **kwargs):
211 src = "http://www.youtube.com/embed/{0}".format(id)
213 src = "http://www.youtube.com/embed/{0}".format(id)
212 super(YouTubeVideo, self).__init__(src, width, height, **kwargs)
214 super(YouTubeVideo, self).__init__(src, width, height, **kwargs)
213
215
214 class VimeoVideo(IFrame):
216 class VimeoVideo(IFrame):
215 """
217 """
216 Class for embedding a Vimeo video in an IPython session, based on its video id.
218 Class for embedding a Vimeo video in an IPython session, based on its video id.
217 """
219 """
218
220
219 def __init__(self, id, width=400, height=300, **kwargs):
221 def __init__(self, id, width=400, height=300, **kwargs):
220 src="http://player.vimeo.com/video/{0}".format(id)
222 src="http://player.vimeo.com/video/{0}".format(id)
221 super(VimeoVideo, self).__init__(src, width, height, **kwargs)
223 super(VimeoVideo, self).__init__(src, width, height, **kwargs)
222
224
223 class ScribdDocument(IFrame):
225 class ScribdDocument(IFrame):
224 """
226 """
225 Class for embedding a Scribd document in an IPython session
227 Class for embedding a Scribd document in an IPython session
226
228
227 Use the start_page params to specify a starting point in the document
229 Use the start_page params to specify a starting point in the document
228 Use the view_mode params to specify display type one off scroll | slideshow | book
230 Use the view_mode params to specify display type one off scroll | slideshow | book
229
231
230 e.g to Display Wes' foundational paper about PANDAS in book mode from page 3
232 e.g to Display Wes' foundational paper about PANDAS in book mode from page 3
231
233
232 ScribdDocument(71048089, width=800, height=400, start_page=3, view_mode="book")
234 ScribdDocument(71048089, width=800, height=400, start_page=3, view_mode="book")
233 """
235 """
234
236
235 def __init__(self, id, width=400, height=300, **kwargs):
237 def __init__(self, id, width=400, height=300, **kwargs):
236 src="http://www.scribd.com/embeds/{0}/content".format(id)
238 src="http://www.scribd.com/embeds/{0}/content".format(id)
237 super(ScribdDocument, self).__init__(src, width, height, **kwargs)
239 super(ScribdDocument, self).__init__(src, width, height, **kwargs)
238
240
239 class FileLink(object):
241 class FileLink(object):
240 """Class for embedding a local file link in an IPython session, based on path
242 """Class for embedding a local file link in an IPython session, based on path
241
243
242 e.g. to embed a link that was generated in the IPython notebook as my/data.txt
244 e.g. to embed a link that was generated in the IPython notebook as my/data.txt
243
245
244 you would do::
246 you would do::
245
247
246 local_file = FileLink("my/data.txt")
248 local_file = FileLink("my/data.txt")
247 display(local_file)
249 display(local_file)
248
250
249 or in the HTML notebook, just::
251 or in the HTML notebook, just::
250
252
251 FileLink("my/data.txt")
253 FileLink("my/data.txt")
252 """
254 """
253
255
254 html_link_str = "<a href='%s' target='_blank'>%s</a>"
256 html_link_str = "<a href='%s' target='_blank'>%s</a>"
255
257
256 def __init__(self,
258 def __init__(self,
257 path,
259 path,
258 url_prefix='files/',
260 url_prefix='files/',
259 result_html_prefix='',
261 result_html_prefix='',
260 result_html_suffix='<br>'):
262 result_html_suffix='<br>'):
261 """
263 """
262 Parameters
264 Parameters
263 ----------
265 ----------
264 path : str
266 path : str
265 path to the file or directory that should be formatted
267 path to the file or directory that should be formatted
266 directory_prefix : str
268 directory_prefix : str
267 prefix to be prepended to all files to form a working link [default:
269 prefix to be prepended to all files to form a working link [default:
268 'files']
270 'files']
269 result_html_prefix : str
271 result_html_prefix : str
270 text to append to beginning to link [default: none]
272 text to append to beginning to link [default: none]
271 result_html_suffix : str
273 result_html_suffix : str
272 text to append at the end of link [default: '<br>']
274 text to append at the end of link [default: '<br>']
273 """
275 """
274 if isdir(path):
276 if isdir(path):
275 raise ValueError,\
277 raise ValueError,\
276 ("Cannot display a directory using FileLink. "
278 ("Cannot display a directory using FileLink. "
277 "Use FileLinks to display '%s'." % path)
279 "Use FileLinks to display '%s'." % path)
278 self.path = path
280 self.path = path
279 self.url_prefix = url_prefix
281 self.url_prefix = url_prefix
280 self.result_html_prefix = result_html_prefix
282 self.result_html_prefix = result_html_prefix
281 self.result_html_suffix = result_html_suffix
283 self.result_html_suffix = result_html_suffix
282
284
283 def _format_path(self):
285 def _format_path(self):
284 fp = ''.join([self.url_prefix,self.path])
286 fp = ''.join([self.url_prefix,self.path])
285 return ''.join([self.result_html_prefix,
287 return ''.join([self.result_html_prefix,
286 self.html_link_str % (fp, self.path),
288 self.html_link_str % (fp, self.path),
287 self.result_html_suffix])
289 self.result_html_suffix])
288
290
289 def _repr_html_(self):
291 def _repr_html_(self):
290 """return html link to file
292 """return html link to file
291 """
293 """
292 if not exists(self.path):
294 if not exists(self.path):
293 return ("Path (<tt>%s</tt>) doesn't exist. "
295 return ("Path (<tt>%s</tt>) doesn't exist. "
294 "It may still be in the process of "
296 "It may still be in the process of "
295 "being generated, or you may have the "
297 "being generated, or you may have the "
296 "incorrect path." % self.path)
298 "incorrect path." % self.path)
297
299
298 return self._format_path()
300 return self._format_path()
299
301
300 def __repr__(self):
302 def __repr__(self):
301 """return absolute path to file
303 """return absolute path to file
302 """
304 """
303 return abspath(self.path)
305 return abspath(self.path)
304
306
305 class FileLinks(FileLink):
307 class FileLinks(FileLink):
306 """Class for embedding local file links in an IPython session, based on path
308 """Class for embedding local file links in an IPython session, based on path
307
309
308 e.g. to embed links to files that were generated in the IPython notebook under my/data
310 e.g. to embed links to files that were generated in the IPython notebook under my/data
309
311
310 you would do:
312 you would do:
311
313
312 local_files = FileLinks("my/data")
314 local_files = FileLinks("my/data")
313 display(local_files)
315 display(local_files)
314
316
315 or in the HTML notebook, just
317 or in the HTML notebook, just
316
318
317 FileLinks("my/data")
319 FileLinks("my/data")
318
320
319 """
321 """
320 def __init__(self,
322 def __init__(self,
321 path,
323 path,
322 url_prefix='files/',
324 url_prefix='files/',
323 included_suffixes=None,
325 included_suffixes=None,
324 result_html_prefix='',
326 result_html_prefix='',
325 result_html_suffix='<br>',
327 result_html_suffix='<br>',
326 notebook_display_formatter=None,
328 notebook_display_formatter=None,
327 terminal_display_formatter=None):
329 terminal_display_formatter=None):
328 """
330 """
329 included_suffixes : list of filename suffixes to include when
331 included_suffixes : list of filename suffixes to include when
330 formatting output [default: include all files]
332 formatting output [default: include all files]
331
333
332 See the FileLink (baseclass of LocalDirectory) docstring for
334 See the FileLink (baseclass of LocalDirectory) docstring for
333 information on additional parameters.
335 information on additional parameters.
334
336
335 notebook_display_formatter : func used to format links for display
337 notebook_display_formatter : func used to format links for display
336 in the notebook. See discussion of formatter function below.
338 in the notebook. See discussion of formatter function below.
337
339
338 terminal_display_formatter : func used to format links for display
340 terminal_display_formatter : func used to format links for display
339 in the terminal. See discussion of formatter function below.
341 in the terminal. See discussion of formatter function below.
340
342
341
343
342 Passing custom formatter functions
344 Passing custom formatter functions
343 ----------------------------------
345 ----------------------------------
344 Formatter functions must be of the form:
346 Formatter functions must be of the form:
345 f(dirname, fnames, included_suffixes)
347 f(dirname, fnames, included_suffixes)
346 dirname : the name of a directory (a string),
348 dirname : the name of a directory (a string),
347 fnames : a list of the files in that directory
349 fnames : a list of the files in that directory
348 included_suffixes : a list of the file suffixes that should be
350 included_suffixes : a list of the file suffixes that should be
349 included in the output (passing None means
351 included in the output (passing None means
350 to include all suffixes in the output in
352 to include all suffixes in the output in
351 the built-in formatters)
353 the built-in formatters)
352
354
353 returns a list of lines that should will be print in the
355 returns a list of lines that should will be print in the
354 notebook (if passing notebook_display_formatter) or the terminal
356 notebook (if passing notebook_display_formatter) or the terminal
355 (if passing terminal_display_formatter). This function is iterated
357 (if passing terminal_display_formatter). This function is iterated
356 over for each directory in self.path. Default formatters are in
358 over for each directory in self.path. Default formatters are in
357 place, can be passed here to support alternative formatting.
359 place, can be passed here to support alternative formatting.
358
360
359 """
361 """
360 if isfile(path):
362 if isfile(path):
361 raise ValueError,\
363 raise ValueError,\
362 ("Cannot display a file using FileLinks. "
364 ("Cannot display a file using FileLinks. "
363 "Use FileLink to display '%s'." % path)
365 "Use FileLink to display '%s'." % path)
364 self.included_suffixes = included_suffixes
366 self.included_suffixes = included_suffixes
365 # remove trailing slashs for more consistent output formatting
367 # remove trailing slashs for more consistent output formatting
366 path = path.rstrip('/')
368 path = path.rstrip('/')
367
369
368 self.path = path
370 self.path = path
369 self.url_prefix = url_prefix
371 self.url_prefix = url_prefix
370 self.result_html_prefix = result_html_prefix
372 self.result_html_prefix = result_html_prefix
371 self.result_html_suffix = result_html_suffix
373 self.result_html_suffix = result_html_suffix
372
374
373 self.notebook_display_formatter = \
375 self.notebook_display_formatter = \
374 notebook_display_formatter or self._get_notebook_display_formatter()
376 notebook_display_formatter or self._get_notebook_display_formatter()
375 self.terminal_display_formatter = \
377 self.terminal_display_formatter = \
376 terminal_display_formatter or self._get_terminal_display_formatter()
378 terminal_display_formatter or self._get_terminal_display_formatter()
377
379
378 def _get_display_formatter(self,
380 def _get_display_formatter(self,
379 dirname_output_format,
381 dirname_output_format,
380 fname_output_format,
382 fname_output_format,
381 fp_format,
383 fp_format,
382 fp_cleaner=None):
384 fp_cleaner=None):
383 """ generate built-in formatter function
385 """ generate built-in formatter function
384
386
385 this is used to define both the notebook and terminal built-in
387 this is used to define both the notebook and terminal built-in
386 formatters as they only differ by some wrapper text for each entry
388 formatters as they only differ by some wrapper text for each entry
387
389
388 dirname_output_format: string to use for formatting directory
390 dirname_output_format: string to use for formatting directory
389 names, dirname will be substituted for a single "%s" which
391 names, dirname will be substituted for a single "%s" which
390 must appear in this string
392 must appear in this string
391 fname_output_format: string to use for formatting file names,
393 fname_output_format: string to use for formatting file names,
392 if a single "%s" appears in the string, fname will be substituted
394 if a single "%s" appears in the string, fname will be substituted
393 if two "%s" appear in the string, the path to fname will be
395 if two "%s" appear in the string, the path to fname will be
394 substituted for the first and fname will be substituted for the
396 substituted for the first and fname will be substituted for the
395 second
397 second
396 fp_format: string to use for formatting filepaths, must contain
398 fp_format: string to use for formatting filepaths, must contain
397 exactly two "%s" and the dirname will be subsituted for the first
399 exactly two "%s" and the dirname will be subsituted for the first
398 and fname will be substituted for the second
400 and fname will be substituted for the second
399 """
401 """
400 def f(dirname, fnames, included_suffixes=None):
402 def f(dirname, fnames, included_suffixes=None):
401 result = []
403 result = []
402 # begin by figuring out which filenames, if any,
404 # begin by figuring out which filenames, if any,
403 # are going to be displayed
405 # are going to be displayed
404 display_fnames = []
406 display_fnames = []
405 for fname in fnames:
407 for fname in fnames:
406 if (isfile(join(dirname,fname)) and
408 if (isfile(join(dirname,fname)) and
407 (included_suffixes == None or
409 (included_suffixes == None or
408 splitext(fname)[1] in included_suffixes)):
410 splitext(fname)[1] in included_suffixes)):
409 display_fnames.append(fname)
411 display_fnames.append(fname)
410
412
411 if len(display_fnames) == 0:
413 if len(display_fnames) == 0:
412 # if there are no filenames to display, don't print anything
414 # if there are no filenames to display, don't print anything
413 # (not even the directory name)
415 # (not even the directory name)
414 pass
416 pass
415 else:
417 else:
416 # otherwise print the formatted directory name followed by
418 # otherwise print the formatted directory name followed by
417 # the formatted filenames
419 # the formatted filenames
418 dirname_output_line = dirname_output_format % dirname
420 dirname_output_line = dirname_output_format % dirname
419 result.append(dirname_output_line)
421 result.append(dirname_output_line)
420 for fname in display_fnames:
422 for fname in display_fnames:
421 fp = fp_format % (dirname,fname)
423 fp = fp_format % (dirname,fname)
422 if fp_cleaner is not None:
424 if fp_cleaner is not None:
423 fp = fp_cleaner(fp)
425 fp = fp_cleaner(fp)
424 try:
426 try:
425 # output can include both a filepath and a filename...
427 # output can include both a filepath and a filename...
426 fname_output_line = fname_output_format % (fp, fname)
428 fname_output_line = fname_output_format % (fp, fname)
427 except TypeError:
429 except TypeError:
428 # ... or just a single filepath
430 # ... or just a single filepath
429 fname_output_line = fname_output_format % fname
431 fname_output_line = fname_output_format % fname
430 result.append(fname_output_line)
432 result.append(fname_output_line)
431 return result
433 return result
432 return f
434 return f
433
435
434 def _get_notebook_display_formatter(self,
436 def _get_notebook_display_formatter(self,
435 spacer="&nbsp;&nbsp;"):
437 spacer="&nbsp;&nbsp;"):
436 """ generate function to use for notebook formatting
438 """ generate function to use for notebook formatting
437 """
439 """
438 dirname_output_format = \
440 dirname_output_format = \
439 self.result_html_prefix + "%s/" + self.result_html_suffix
441 self.result_html_prefix + "%s/" + self.result_html_suffix
440 fname_output_format = \
442 fname_output_format = \
441 self.result_html_prefix + spacer + self.html_link_str + self.result_html_suffix
443 self.result_html_prefix + spacer + self.html_link_str + self.result_html_suffix
442 fp_format = self.url_prefix + '%s/%s'
444 fp_format = self.url_prefix + '%s/%s'
443 if sep == "\\":
445 if sep == "\\":
444 # Working on a platform where the path separator is "\", so
446 # Working on a platform where the path separator is "\", so
445 # must convert these to "/" for generating a URI
447 # must convert these to "/" for generating a URI
446 def fp_cleaner(fp):
448 def fp_cleaner(fp):
447 # Replace all occurences of backslash ("\") with a forward
449 # Replace all occurences of backslash ("\") with a forward
448 # slash ("/") - this is necessary on windows when a path is
450 # slash ("/") - this is necessary on windows when a path is
449 # provided as input, but we must link to a URI
451 # provided as input, but we must link to a URI
450 return fp.replace('\\','/')
452 return fp.replace('\\','/')
451 else:
453 else:
452 fp_cleaner = None
454 fp_cleaner = None
453
455
454 return self._get_display_formatter(dirname_output_format,
456 return self._get_display_formatter(dirname_output_format,
455 fname_output_format,
457 fname_output_format,
456 fp_format,
458 fp_format,
457 fp_cleaner)
459 fp_cleaner)
458
460
459 def _get_terminal_display_formatter(self,
461 def _get_terminal_display_formatter(self,
460 spacer=" "):
462 spacer=" "):
461 """ generate function to use for terminal formatting
463 """ generate function to use for terminal formatting
462 """
464 """
463 dirname_output_format = "%s/"
465 dirname_output_format = "%s/"
464 fname_output_format = spacer + "%s"
466 fname_output_format = spacer + "%s"
465 fp_format = '%s/%s'
467 fp_format = '%s/%s'
466
468
467 return self._get_display_formatter(dirname_output_format,
469 return self._get_display_formatter(dirname_output_format,
468 fname_output_format,
470 fname_output_format,
469 fp_format)
471 fp_format)
470
472
471 def _format_path(self):
473 def _format_path(self):
472 result_lines = []
474 result_lines = []
473 walked_dir = list(walk(self.path))
475 walked_dir = list(walk(self.path))
474 walked_dir.sort()
476 walked_dir.sort()
475 for dirname, subdirs, fnames in walked_dir:
477 for dirname, subdirs, fnames in walked_dir:
476 result_lines += self.notebook_display_formatter(dirname, fnames, self.included_suffixes)
478 result_lines += self.notebook_display_formatter(dirname, fnames, self.included_suffixes)
477 return '\n'.join(result_lines)
479 return '\n'.join(result_lines)
478
480
479 def __repr__(self):
481 def __repr__(self):
480 """return newline-separated absolute paths
482 """return newline-separated absolute paths
481 """
483 """
482 result_lines = []
484 result_lines = []
483 walked_dir = list(walk(self.path))
485 walked_dir = list(walk(self.path))
484 walked_dir.sort()
486 walked_dir.sort()
485 for dirname, subdirs, fnames in walked_dir:
487 for dirname, subdirs, fnames in walked_dir:
486 result_lines += self.terminal_display_formatter(dirname, fnames, self.included_suffixes)
488 result_lines += self.terminal_display_formatter(dirname, fnames, self.included_suffixes)
487 return '\n'.join(result_lines)
489 return '\n'.join(result_lines)
General Comments 0
You need to be logged in to leave comments. Login now