##// END OF EJS Templates
Speed up normalization if numpy is avaliable
David Österberg -
Show More
@@ -1,489 +1,494 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 try:
107 import numpy as np
108 data = np.array(data,dtype=float)
109 scaled = list(np.int16(data/np.max(np.abs(data))*32767))
110 except ImportError:
106 maxabsvalue = float(max(map(abs,data)))
111 maxabsvalue = float(max(map(abs,data)))
107 scaled = map(lambda x: int(x/maxabsvalue*32767), data)
112 scaled = map(lambda x: int(x/maxabsvalue*32767), data)
108 fp = BytesIO()
113 fp = BytesIO()
109 waveobj = wave.open(fp,mode='wb')
114 waveobj = wave.open(fp,mode='wb')
110 waveobj.setnchannels(1)
115 waveobj.setnchannels(1)
111 waveobj.setframerate(rate)
116 waveobj.setframerate(rate)
112 waveobj.setsampwidth(2)
117 waveobj.setsampwidth(2)
113 waveobj.setcomptype('NONE','NONE')
118 waveobj.setcomptype('NONE','NONE')
114 waveobj.writeframes(b''.join([struct.pack('<h',x) for x in scaled]))
119 waveobj.writeframes(b''.join([struct.pack('<h',x) for x in scaled]))
115 val = fp.getvalue()
120 val = fp.getvalue()
116 waveobj.close()
121 waveobj.close()
117 return val
122 return val
118
123
119 def _data_and_metadata(self):
124 def _data_and_metadata(self):
120 """shortcut for returning metadata with url information, if defined"""
125 """shortcut for returning metadata with url information, if defined"""
121 md = {}
126 md = {}
122 if self.url:
127 if self.url:
123 md['url'] = self.url
128 md['url'] = self.url
124 if md:
129 if md:
125 return self.data, md
130 return self.data, md
126 else:
131 else:
127 return self.data
132 return self.data
128
133
129 def _repr_html_(self):
134 def _repr_html_(self):
130 src = """
135 src = """
131 <audio controls="controls" {autoplay}>
136 <audio controls="controls" {autoplay}>
132 <source src="{src}" type="{type}" />
137 <source src="{src}" type="{type}" />
133 Your browser does not support the audio element.
138 Your browser does not support the audio element.
134 </audio>
139 </audio>
135 """
140 """
136 return src.format(src=self.src_attr(),type=self.mimetype, autoplay=self.autoplay_attr())
141 return src.format(src=self.src_attr(),type=self.mimetype, autoplay=self.autoplay_attr())
137
142
138 def src_attr(self):
143 def src_attr(self):
139 import base64
144 import base64
140 if self.embed and (self.data is not None):
145 if self.embed and (self.data is not None):
141 data = base64=base64.b64encode(self.data).decode('ascii')
146 data = base64=base64.b64encode(self.data).decode('ascii')
142 return """data:{type};base64,{base64}""".format(type=self.mimetype,
147 return """data:{type};base64,{base64}""".format(type=self.mimetype,
143 base64=data)
148 base64=data)
144 elif self.url is not None:
149 elif self.url is not None:
145 return self.url
150 return self.url
146 else:
151 else:
147 return ""
152 return ""
148
153
149 def autoplay_attr(self):
154 def autoplay_attr(self):
150 if(self.autoplay):
155 if(self.autoplay):
151 return 'autoplay="autoplay"'
156 return 'autoplay="autoplay"'
152 else:
157 else:
153 return ''
158 return ''
154
159
155 class IFrame(object):
160 class IFrame(object):
156 """
161 """
157 Generic class to embed an iframe in an IPython notebook
162 Generic class to embed an iframe in an IPython notebook
158 """
163 """
159
164
160 iframe = """
165 iframe = """
161 <iframe
166 <iframe
162 width="{width}"
167 width="{width}"
163 height={height}"
168 height={height}"
164 src="{src}{params}"
169 src="{src}{params}"
165 frameborder="0"
170 frameborder="0"
166 allowfullscreen
171 allowfullscreen
167 ></iframe>
172 ></iframe>
168 """
173 """
169
174
170 def __init__(self, src, width, height, **kwargs):
175 def __init__(self, src, width, height, **kwargs):
171 self.src = src
176 self.src = src
172 self.width = width
177 self.width = width
173 self.height = height
178 self.height = height
174 self.params = kwargs
179 self.params = kwargs
175
180
176 def _repr_html_(self):
181 def _repr_html_(self):
177 """return the embed iframe"""
182 """return the embed iframe"""
178 if self.params:
183 if self.params:
179 from urllib import urlencode
184 from urllib import urlencode
180 params = "?" + urlencode(self.params)
185 params = "?" + urlencode(self.params)
181 else:
186 else:
182 params = ""
187 params = ""
183 return self.iframe.format(src=self.src,
188 return self.iframe.format(src=self.src,
184 width=self.width,
189 width=self.width,
185 height=self.height,
190 height=self.height,
186 params=params)
191 params=params)
187
192
188 class YouTubeVideo(IFrame):
193 class YouTubeVideo(IFrame):
189 """Class for embedding a YouTube Video in an IPython session, based on its video id.
194 """Class for embedding a YouTube Video in an IPython session, based on its video id.
190
195
191 e.g. to embed the video on this page:
196 e.g. to embed the video on this page:
192
197
193 http://www.youtube.com/watch?v=foo
198 http://www.youtube.com/watch?v=foo
194
199
195 you would do:
200 you would do:
196
201
197 vid = YouTubeVideo("foo")
202 vid = YouTubeVideo("foo")
198 display(vid)
203 display(vid)
199
204
200 To start from 30 seconds:
205 To start from 30 seconds:
201
206
202 vid = YouTubeVideo("abc", start=30)
207 vid = YouTubeVideo("abc", start=30)
203 display(vid)
208 display(vid)
204
209
205 To calculate seconds from time as hours, minutes, seconds use:
210 To calculate seconds from time as hours, minutes, seconds use:
206 start=int(timedelta(hours=1, minutes=46, seconds=40).total_seconds())
211 start=int(timedelta(hours=1, minutes=46, seconds=40).total_seconds())
207
212
208 Other parameters can be provided as documented at
213 Other parameters can be provided as documented at
209 https://developers.google.com/youtube/player_parameters#parameter-subheader
214 https://developers.google.com/youtube/player_parameters#parameter-subheader
210 """
215 """
211
216
212 def __init__(self, id, width=400, height=300, **kwargs):
217 def __init__(self, id, width=400, height=300, **kwargs):
213 src = "http://www.youtube.com/embed/{0}".format(id)
218 src = "http://www.youtube.com/embed/{0}".format(id)
214 super(YouTubeVideo, self).__init__(src, width, height, **kwargs)
219 super(YouTubeVideo, self).__init__(src, width, height, **kwargs)
215
220
216 class VimeoVideo(IFrame):
221 class VimeoVideo(IFrame):
217 """
222 """
218 Class for embedding a Vimeo video in an IPython session, based on its video id.
223 Class for embedding a Vimeo video in an IPython session, based on its video id.
219 """
224 """
220
225
221 def __init__(self, id, width=400, height=300, **kwargs):
226 def __init__(self, id, width=400, height=300, **kwargs):
222 src="http://player.vimeo.com/video/{0}".format(id)
227 src="http://player.vimeo.com/video/{0}".format(id)
223 super(VimeoVideo, self).__init__(src, width, height, **kwargs)
228 super(VimeoVideo, self).__init__(src, width, height, **kwargs)
224
229
225 class ScribdDocument(IFrame):
230 class ScribdDocument(IFrame):
226 """
231 """
227 Class for embedding a Scribd document in an IPython session
232 Class for embedding a Scribd document in an IPython session
228
233
229 Use the start_page params to specify a starting point in the document
234 Use the start_page params to specify a starting point in the document
230 Use the view_mode params to specify display type one off scroll | slideshow | book
235 Use the view_mode params to specify display type one off scroll | slideshow | book
231
236
232 e.g to Display Wes' foundational paper about PANDAS in book mode from page 3
237 e.g to Display Wes' foundational paper about PANDAS in book mode from page 3
233
238
234 ScribdDocument(71048089, width=800, height=400, start_page=3, view_mode="book")
239 ScribdDocument(71048089, width=800, height=400, start_page=3, view_mode="book")
235 """
240 """
236
241
237 def __init__(self, id, width=400, height=300, **kwargs):
242 def __init__(self, id, width=400, height=300, **kwargs):
238 src="http://www.scribd.com/embeds/{0}/content".format(id)
243 src="http://www.scribd.com/embeds/{0}/content".format(id)
239 super(ScribdDocument, self).__init__(src, width, height, **kwargs)
244 super(ScribdDocument, self).__init__(src, width, height, **kwargs)
240
245
241 class FileLink(object):
246 class FileLink(object):
242 """Class for embedding a local file link in an IPython session, based on path
247 """Class for embedding a local file link in an IPython session, based on path
243
248
244 e.g. to embed a link that was generated in the IPython notebook as my/data.txt
249 e.g. to embed a link that was generated in the IPython notebook as my/data.txt
245
250
246 you would do::
251 you would do::
247
252
248 local_file = FileLink("my/data.txt")
253 local_file = FileLink("my/data.txt")
249 display(local_file)
254 display(local_file)
250
255
251 or in the HTML notebook, just::
256 or in the HTML notebook, just::
252
257
253 FileLink("my/data.txt")
258 FileLink("my/data.txt")
254 """
259 """
255
260
256 html_link_str = "<a href='%s' target='_blank'>%s</a>"
261 html_link_str = "<a href='%s' target='_blank'>%s</a>"
257
262
258 def __init__(self,
263 def __init__(self,
259 path,
264 path,
260 url_prefix='files/',
265 url_prefix='files/',
261 result_html_prefix='',
266 result_html_prefix='',
262 result_html_suffix='<br>'):
267 result_html_suffix='<br>'):
263 """
268 """
264 Parameters
269 Parameters
265 ----------
270 ----------
266 path : str
271 path : str
267 path to the file or directory that should be formatted
272 path to the file or directory that should be formatted
268 directory_prefix : str
273 directory_prefix : str
269 prefix to be prepended to all files to form a working link [default:
274 prefix to be prepended to all files to form a working link [default:
270 'files']
275 'files']
271 result_html_prefix : str
276 result_html_prefix : str
272 text to append to beginning to link [default: none]
277 text to append to beginning to link [default: none]
273 result_html_suffix : str
278 result_html_suffix : str
274 text to append at the end of link [default: '<br>']
279 text to append at the end of link [default: '<br>']
275 """
280 """
276 if isdir(path):
281 if isdir(path):
277 raise ValueError,\
282 raise ValueError,\
278 ("Cannot display a directory using FileLink. "
283 ("Cannot display a directory using FileLink. "
279 "Use FileLinks to display '%s'." % path)
284 "Use FileLinks to display '%s'." % path)
280 self.path = path
285 self.path = path
281 self.url_prefix = url_prefix
286 self.url_prefix = url_prefix
282 self.result_html_prefix = result_html_prefix
287 self.result_html_prefix = result_html_prefix
283 self.result_html_suffix = result_html_suffix
288 self.result_html_suffix = result_html_suffix
284
289
285 def _format_path(self):
290 def _format_path(self):
286 fp = ''.join([self.url_prefix,self.path])
291 fp = ''.join([self.url_prefix,self.path])
287 return ''.join([self.result_html_prefix,
292 return ''.join([self.result_html_prefix,
288 self.html_link_str % (fp, self.path),
293 self.html_link_str % (fp, self.path),
289 self.result_html_suffix])
294 self.result_html_suffix])
290
295
291 def _repr_html_(self):
296 def _repr_html_(self):
292 """return html link to file
297 """return html link to file
293 """
298 """
294 if not exists(self.path):
299 if not exists(self.path):
295 return ("Path (<tt>%s</tt>) doesn't exist. "
300 return ("Path (<tt>%s</tt>) doesn't exist. "
296 "It may still be in the process of "
301 "It may still be in the process of "
297 "being generated, or you may have the "
302 "being generated, or you may have the "
298 "incorrect path." % self.path)
303 "incorrect path." % self.path)
299
304
300 return self._format_path()
305 return self._format_path()
301
306
302 def __repr__(self):
307 def __repr__(self):
303 """return absolute path to file
308 """return absolute path to file
304 """
309 """
305 return abspath(self.path)
310 return abspath(self.path)
306
311
307 class FileLinks(FileLink):
312 class FileLinks(FileLink):
308 """Class for embedding local file links in an IPython session, based on path
313 """Class for embedding local file links in an IPython session, based on path
309
314
310 e.g. to embed links to files that were generated in the IPython notebook under my/data
315 e.g. to embed links to files that were generated in the IPython notebook under my/data
311
316
312 you would do:
317 you would do:
313
318
314 local_files = FileLinks("my/data")
319 local_files = FileLinks("my/data")
315 display(local_files)
320 display(local_files)
316
321
317 or in the HTML notebook, just
322 or in the HTML notebook, just
318
323
319 FileLinks("my/data")
324 FileLinks("my/data")
320
325
321 """
326 """
322 def __init__(self,
327 def __init__(self,
323 path,
328 path,
324 url_prefix='files/',
329 url_prefix='files/',
325 included_suffixes=None,
330 included_suffixes=None,
326 result_html_prefix='',
331 result_html_prefix='',
327 result_html_suffix='<br>',
332 result_html_suffix='<br>',
328 notebook_display_formatter=None,
333 notebook_display_formatter=None,
329 terminal_display_formatter=None):
334 terminal_display_formatter=None):
330 """
335 """
331 included_suffixes : list of filename suffixes to include when
336 included_suffixes : list of filename suffixes to include when
332 formatting output [default: include all files]
337 formatting output [default: include all files]
333
338
334 See the FileLink (baseclass of LocalDirectory) docstring for
339 See the FileLink (baseclass of LocalDirectory) docstring for
335 information on additional parameters.
340 information on additional parameters.
336
341
337 notebook_display_formatter : func used to format links for display
342 notebook_display_formatter : func used to format links for display
338 in the notebook. See discussion of formatter function below.
343 in the notebook. See discussion of formatter function below.
339
344
340 terminal_display_formatter : func used to format links for display
345 terminal_display_formatter : func used to format links for display
341 in the terminal. See discussion of formatter function below.
346 in the terminal. See discussion of formatter function below.
342
347
343
348
344 Passing custom formatter functions
349 Passing custom formatter functions
345 ----------------------------------
350 ----------------------------------
346 Formatter functions must be of the form:
351 Formatter functions must be of the form:
347 f(dirname, fnames, included_suffixes)
352 f(dirname, fnames, included_suffixes)
348 dirname : the name of a directory (a string),
353 dirname : the name of a directory (a string),
349 fnames : a list of the files in that directory
354 fnames : a list of the files in that directory
350 included_suffixes : a list of the file suffixes that should be
355 included_suffixes : a list of the file suffixes that should be
351 included in the output (passing None means
356 included in the output (passing None means
352 to include all suffixes in the output in
357 to include all suffixes in the output in
353 the built-in formatters)
358 the built-in formatters)
354
359
355 returns a list of lines that should will be print in the
360 returns a list of lines that should will be print in the
356 notebook (if passing notebook_display_formatter) or the terminal
361 notebook (if passing notebook_display_formatter) or the terminal
357 (if passing terminal_display_formatter). This function is iterated
362 (if passing terminal_display_formatter). This function is iterated
358 over for each directory in self.path. Default formatters are in
363 over for each directory in self.path. Default formatters are in
359 place, can be passed here to support alternative formatting.
364 place, can be passed here to support alternative formatting.
360
365
361 """
366 """
362 if isfile(path):
367 if isfile(path):
363 raise ValueError,\
368 raise ValueError,\
364 ("Cannot display a file using FileLinks. "
369 ("Cannot display a file using FileLinks. "
365 "Use FileLink to display '%s'." % path)
370 "Use FileLink to display '%s'." % path)
366 self.included_suffixes = included_suffixes
371 self.included_suffixes = included_suffixes
367 # remove trailing slashs for more consistent output formatting
372 # remove trailing slashs for more consistent output formatting
368 path = path.rstrip('/')
373 path = path.rstrip('/')
369
374
370 self.path = path
375 self.path = path
371 self.url_prefix = url_prefix
376 self.url_prefix = url_prefix
372 self.result_html_prefix = result_html_prefix
377 self.result_html_prefix = result_html_prefix
373 self.result_html_suffix = result_html_suffix
378 self.result_html_suffix = result_html_suffix
374
379
375 self.notebook_display_formatter = \
380 self.notebook_display_formatter = \
376 notebook_display_formatter or self._get_notebook_display_formatter()
381 notebook_display_formatter or self._get_notebook_display_formatter()
377 self.terminal_display_formatter = \
382 self.terminal_display_formatter = \
378 terminal_display_formatter or self._get_terminal_display_formatter()
383 terminal_display_formatter or self._get_terminal_display_formatter()
379
384
380 def _get_display_formatter(self,
385 def _get_display_formatter(self,
381 dirname_output_format,
386 dirname_output_format,
382 fname_output_format,
387 fname_output_format,
383 fp_format,
388 fp_format,
384 fp_cleaner=None):
389 fp_cleaner=None):
385 """ generate built-in formatter function
390 """ generate built-in formatter function
386
391
387 this is used to define both the notebook and terminal built-in
392 this is used to define both the notebook and terminal built-in
388 formatters as they only differ by some wrapper text for each entry
393 formatters as they only differ by some wrapper text for each entry
389
394
390 dirname_output_format: string to use for formatting directory
395 dirname_output_format: string to use for formatting directory
391 names, dirname will be substituted for a single "%s" which
396 names, dirname will be substituted for a single "%s" which
392 must appear in this string
397 must appear in this string
393 fname_output_format: string to use for formatting file names,
398 fname_output_format: string to use for formatting file names,
394 if a single "%s" appears in the string, fname will be substituted
399 if a single "%s" appears in the string, fname will be substituted
395 if two "%s" appear in the string, the path to fname will be
400 if two "%s" appear in the string, the path to fname will be
396 substituted for the first and fname will be substituted for the
401 substituted for the first and fname will be substituted for the
397 second
402 second
398 fp_format: string to use for formatting filepaths, must contain
403 fp_format: string to use for formatting filepaths, must contain
399 exactly two "%s" and the dirname will be subsituted for the first
404 exactly two "%s" and the dirname will be subsituted for the first
400 and fname will be substituted for the second
405 and fname will be substituted for the second
401 """
406 """
402 def f(dirname, fnames, included_suffixes=None):
407 def f(dirname, fnames, included_suffixes=None):
403 result = []
408 result = []
404 # begin by figuring out which filenames, if any,
409 # begin by figuring out which filenames, if any,
405 # are going to be displayed
410 # are going to be displayed
406 display_fnames = []
411 display_fnames = []
407 for fname in fnames:
412 for fname in fnames:
408 if (isfile(join(dirname,fname)) and
413 if (isfile(join(dirname,fname)) and
409 (included_suffixes == None or
414 (included_suffixes == None or
410 splitext(fname)[1] in included_suffixes)):
415 splitext(fname)[1] in included_suffixes)):
411 display_fnames.append(fname)
416 display_fnames.append(fname)
412
417
413 if len(display_fnames) == 0:
418 if len(display_fnames) == 0:
414 # if there are no filenames to display, don't print anything
419 # if there are no filenames to display, don't print anything
415 # (not even the directory name)
420 # (not even the directory name)
416 pass
421 pass
417 else:
422 else:
418 # otherwise print the formatted directory name followed by
423 # otherwise print the formatted directory name followed by
419 # the formatted filenames
424 # the formatted filenames
420 dirname_output_line = dirname_output_format % dirname
425 dirname_output_line = dirname_output_format % dirname
421 result.append(dirname_output_line)
426 result.append(dirname_output_line)
422 for fname in display_fnames:
427 for fname in display_fnames:
423 fp = fp_format % (dirname,fname)
428 fp = fp_format % (dirname,fname)
424 if fp_cleaner is not None:
429 if fp_cleaner is not None:
425 fp = fp_cleaner(fp)
430 fp = fp_cleaner(fp)
426 try:
431 try:
427 # output can include both a filepath and a filename...
432 # output can include both a filepath and a filename...
428 fname_output_line = fname_output_format % (fp, fname)
433 fname_output_line = fname_output_format % (fp, fname)
429 except TypeError:
434 except TypeError:
430 # ... or just a single filepath
435 # ... or just a single filepath
431 fname_output_line = fname_output_format % fname
436 fname_output_line = fname_output_format % fname
432 result.append(fname_output_line)
437 result.append(fname_output_line)
433 return result
438 return result
434 return f
439 return f
435
440
436 def _get_notebook_display_formatter(self,
441 def _get_notebook_display_formatter(self,
437 spacer="&nbsp;&nbsp;"):
442 spacer="&nbsp;&nbsp;"):
438 """ generate function to use for notebook formatting
443 """ generate function to use for notebook formatting
439 """
444 """
440 dirname_output_format = \
445 dirname_output_format = \
441 self.result_html_prefix + "%s/" + self.result_html_suffix
446 self.result_html_prefix + "%s/" + self.result_html_suffix
442 fname_output_format = \
447 fname_output_format = \
443 self.result_html_prefix + spacer + self.html_link_str + self.result_html_suffix
448 self.result_html_prefix + spacer + self.html_link_str + self.result_html_suffix
444 fp_format = self.url_prefix + '%s/%s'
449 fp_format = self.url_prefix + '%s/%s'
445 if sep == "\\":
450 if sep == "\\":
446 # Working on a platform where the path separator is "\", so
451 # Working on a platform where the path separator is "\", so
447 # must convert these to "/" for generating a URI
452 # must convert these to "/" for generating a URI
448 def fp_cleaner(fp):
453 def fp_cleaner(fp):
449 # Replace all occurences of backslash ("\") with a forward
454 # Replace all occurences of backslash ("\") with a forward
450 # slash ("/") - this is necessary on windows when a path is
455 # slash ("/") - this is necessary on windows when a path is
451 # provided as input, but we must link to a URI
456 # provided as input, but we must link to a URI
452 return fp.replace('\\','/')
457 return fp.replace('\\','/')
453 else:
458 else:
454 fp_cleaner = None
459 fp_cleaner = None
455
460
456 return self._get_display_formatter(dirname_output_format,
461 return self._get_display_formatter(dirname_output_format,
457 fname_output_format,
462 fname_output_format,
458 fp_format,
463 fp_format,
459 fp_cleaner)
464 fp_cleaner)
460
465
461 def _get_terminal_display_formatter(self,
466 def _get_terminal_display_formatter(self,
462 spacer=" "):
467 spacer=" "):
463 """ generate function to use for terminal formatting
468 """ generate function to use for terminal formatting
464 """
469 """
465 dirname_output_format = "%s/"
470 dirname_output_format = "%s/"
466 fname_output_format = spacer + "%s"
471 fname_output_format = spacer + "%s"
467 fp_format = '%s/%s'
472 fp_format = '%s/%s'
468
473
469 return self._get_display_formatter(dirname_output_format,
474 return self._get_display_formatter(dirname_output_format,
470 fname_output_format,
475 fname_output_format,
471 fp_format)
476 fp_format)
472
477
473 def _format_path(self):
478 def _format_path(self):
474 result_lines = []
479 result_lines = []
475 walked_dir = list(walk(self.path))
480 walked_dir = list(walk(self.path))
476 walked_dir.sort()
481 walked_dir.sort()
477 for dirname, subdirs, fnames in walked_dir:
482 for dirname, subdirs, fnames in walked_dir:
478 result_lines += self.notebook_display_formatter(dirname, fnames, self.included_suffixes)
483 result_lines += self.notebook_display_formatter(dirname, fnames, self.included_suffixes)
479 return '\n'.join(result_lines)
484 return '\n'.join(result_lines)
480
485
481 def __repr__(self):
486 def __repr__(self):
482 """return newline-separated absolute paths
487 """return newline-separated absolute paths
483 """
488 """
484 result_lines = []
489 result_lines = []
485 walked_dir = list(walk(self.path))
490 walked_dir = list(walk(self.path))
486 walked_dir.sort()
491 walked_dir.sort()
487 for dirname, subdirs, fnames in walked_dir:
492 for dirname, subdirs, fnames in walked_dir:
488 result_lines += self.terminal_display_formatter(dirname, fnames, self.included_suffixes)
493 result_lines += self.terminal_display_formatter(dirname, fnames, self.included_suffixes)
489 return '\n'.join(result_lines)
494 return '\n'.join(result_lines)
General Comments 0
You need to be logged in to leave comments. Login now