##// END OF EJS Templates
added tests to confirm that error is raise when FileLink is passed a directory. Also specifically disallowed passing a file to FileLinks for consistency.
Greg Caporaso -
Show More
@@ -1,283 +1,287 b''
1 1 """Various display related classes.
2 2
3 3 Authors : MinRK, gregcaporaso, dannystaple
4 4 """
5 5 import urllib
6 6
7 7 from os.path import exists, isfile, splitext, abspath, join, isdir
8 8 from os import walk
9 9
10 10
11 11 class YouTubeVideo(object):
12 12 """Class for embedding a YouTube Video in an IPython session, based on its video id.
13 13
14 14 e.g. to embed the video on this page:
15 15
16 16 http://www.youtube.com/watch?v=foo
17 17
18 18 you would do:
19 19
20 20 vid = YouTubeVideo("foo")
21 21 display(vid)
22 22
23 23 To start from 30 seconds:
24 24
25 25 vid = YouTubeVideo("abc", start=30)
26 26 display(vid)
27 27
28 28 To calculate seconds from time as hours, minutes, seconds use:
29 29 start=int(timedelta(hours=1, minutes=46, seconds=40).total_seconds())
30 30
31 31 Other parameters can be provided as documented at
32 32 https://developers.google.com/youtube/player_parameters#parameter-subheader
33 33 """
34 34
35 35 def __init__(self, id, width=400, height=300, **kwargs):
36 36 self.id = id
37 37 self.width = width
38 38 self.height = height
39 39 self.params = kwargs
40 40
41 41 def _repr_html_(self):
42 42 """return YouTube embed iframe for this video id"""
43 43 if self.params:
44 44 params = "?" + urllib.urlencode(self.params)
45 45 else:
46 46 params = ""
47 47 return """
48 48 <iframe
49 49 width="%i"
50 50 height="%i"
51 51 src="http://www.youtube.com/embed/%s%s"
52 52 frameborder="0"
53 53 allowfullscreen
54 54 ></iframe>
55 55 """ % (self.width, self.height, self.id, params)
56 56
57 57 class FileLink(object):
58 58 """Class for embedding a local file link in an IPython session, based on path
59 59
60 60 e.g. to embed a link that was generated in the IPython notebook as my/data.txt
61 61
62 62 you would do:
63 63
64 64 local_file = FileLink("my/data.txt")
65 65 display(local_file)
66 66
67 67 or in the HTML notebook, just
68 68
69 69 FileLink("my/data.txt")
70 70 """
71 71
72 72 html_link_str = "<a href='%s' target='_blank'>%s</a>"
73 73
74 74 def __init__(self,
75 75 path,
76 76 url_prefix='files/',
77 77 result_html_prefix='',
78 78 result_html_suffix='<br>'):
79 79 """
80 80 path : path to the file or directory that should be formatted
81 81 directory_prefix : prefix to be prepended to all files to form a
82 82 working link [default: 'files']
83 83 result_html_prefix : text to append to beginning to link
84 84 [default: none]
85 85 result_html_suffix : text to append at the end of link
86 86 [default: '<br>']
87 87 """
88 88 if isdir(path):
89 89 raise ValueError,\
90 ("Cannot display a directory as a FileLink object. "
90 ("Cannot display a directory using FileLink. "
91 91 "Use FileLinks to display '%s'." % path)
92 92 self.path = path
93 93 self.url_prefix = url_prefix
94 94 self.result_html_prefix = result_html_prefix
95 95 self.result_html_suffix = result_html_suffix
96 96
97 97 def _format_path(self):
98 98 fp = ''.join([self.url_prefix,self.path])
99 99 return ''.join([self.result_html_prefix,
100 100 self.html_link_str % (fp, self.path),
101 101 self.result_html_suffix])
102 102
103 103 def _repr_html_(self):
104 104 """return html link to file
105 105 """
106 106 if not exists(self.path):
107 107 return ("Path (<tt>%s</tt>) doesn't exist. "
108 108 "It may still be in the process of "
109 109 "being generated, or you may have the "
110 110 "incorrect path." % self.path)
111 111
112 112 return self._format_path()
113 113
114 114 def __repr__(self):
115 115 """return absolute path to file
116 116 """
117 117 return abspath(self.path)
118 118
119 119 class FileLinks(FileLink):
120 120 """Class for embedding local file links in an IPython session, based on path
121 121
122 122 e.g. to embed links to files that were generated in the IPython notebook under my/data
123 123
124 124 you would do:
125 125
126 126 local_files = FileLinks("my/data")
127 127 display(local_files)
128 128
129 129 or in the HTML notebook, just
130 130
131 131 FileLinks("my/data")
132 132
133 133 """
134 134 def __init__(self,
135 135 path,
136 136 url_prefix='files/',
137 137 included_suffixes=None,
138 138 result_html_prefix='',
139 139 result_html_suffix='<br>',
140 140 notebook_display_formatter=None,
141 141 terminal_display_formatter=None):
142 142 """
143 143 included_suffixes : list of filename suffixes to include when
144 144 formatting output [default: include all files]
145 145
146 146 See the FileLink (baseclass of LocalDirectory) docstring for
147 147 information on additional parameters.
148 148
149 149 notebook_display_formatter : func used to format links for display
150 150 in the notebook. See discussion of formatter function below.
151 151
152 152 terminal_display_formatter : func used to format links for display
153 153 in the terminal. See discussion of formatter function below.
154 154
155 155
156 156 Passing custom formatter functions
157 157 ----------------------------------
158 158 Formatter functions must be of the form:
159 159 f(dirname, fnames, included_suffixes)
160 160 dirname : the name of a directory (a string),
161 161 fnames : a list of the files in that directory
162 162 included_suffixes : a list of the file suffixes that should be
163 163 included in the output (passing None means
164 164 to include all suffixes in the output in
165 165 the built-in formatters)
166 166
167 167 returns a list of lines that should will be print in the
168 168 notebook (if passing notebook_display_formatter) or the terminal
169 169 (if passing terminal_display_formatter). This function is iterated
170 170 over for each directory in self.path. Default formatters are in
171 171 place, can be passed here to support alternative formatting.
172 172
173 173 """
174 if isfile(path):
175 raise ValueError,\
176 ("Cannot display a file using FileLinks. "
177 "Use FileLink to display '%s'." % path)
174 178 self.included_suffixes = included_suffixes
175 179 # remove trailing slashs for more consistent output formatting
176 180 path = path.rstrip('/')
177 181
178 182 self.path = path
179 183 self.url_prefix = url_prefix
180 184 self.result_html_prefix = result_html_prefix
181 185 self.result_html_suffix = result_html_suffix
182 186
183 187 self.notebook_display_formatter = \
184 188 notebook_display_formatter or self._get_notebook_display_formatter()
185 189 self.terminal_display_formatter = \
186 190 terminal_display_formatter or self._get_terminal_display_formatter()
187 191
188 192 def _get_display_formatter(self,
189 193 dirname_output_format,
190 194 fname_output_format,
191 195 fp_format):
192 196 """ generate built-in formatter function
193 197
194 198 this is used to define both the notebook and terminal built-in
195 199 formatters as they only differ by some wrapper text for each entry
196 200
197 201 dirname_output_format: string to use for formatting directory
198 202 names, dirname will be substituted for a single "%s" which
199 203 must appear in this string
200 204 fname_output_format: string to use for formatting file names,
201 205 if a single "%s" appears in the string, fname will be substituted
202 206 if two "%s" appear in the string, the path to fname will be
203 207 substituted for the first and fname will be substituted for the
204 208 second
205 209 fp_format: string to use for formatting filepaths, must contain
206 210 exactly two "%s" and the dirname will be subsituted for the first
207 211 and fname will be substituted for the second
208 212 """
209 213 def f(dirname, fnames, included_suffixes=None):
210 214 result = []
211 215 # begin by figuring out which filenames, if any,
212 216 # are going to be displayed
213 217 display_fnames = []
214 218 for fname in fnames:
215 219 if (isfile(join(dirname,fname)) and
216 220 (included_suffixes == None or
217 221 splitext(fname)[1] in included_suffixes)):
218 222 display_fnames.append(fname)
219 223
220 224 if len(display_fnames) == 0:
221 225 # if there are no filenames to display, don't print anything
222 226 # (not even the directory name)
223 227 pass
224 228 else:
225 229 # otherwise print the formatted directory name followed by
226 230 # the formatted filenames
227 231 dirname_output_line = dirname_output_format % dirname
228 232 result.append(dirname_output_line)
229 233 for fname in display_fnames:
230 234 fp = fp_format % (dirname,fname)
231 235 try:
232 236 # output can include both a filepath and a filename...
233 237 fname_output_line = fname_output_format % (fp, fname)
234 238 except TypeError:
235 239 # ... or just a single filepath
236 240 fname_output_line = fname_output_format % fname
237 241 result.append(fname_output_line)
238 242 return result
239 243 return f
240 244
241 245 def _get_notebook_display_formatter(self,
242 246 spacer="&nbsp;&nbsp;"):
243 247 """ generate function to use for notebook formatting
244 248 """
245 249 dirname_output_format = \
246 250 self.result_html_prefix + "%s/" + self.result_html_suffix
247 251 fname_output_format = \
248 252 self.result_html_prefix + spacer + self.html_link_str + self.result_html_suffix
249 253 fp_format = self.url_prefix + '%s/%s'
250 254
251 255 return self._get_display_formatter(dirname_output_format,
252 256 fname_output_format,
253 257 fp_format)
254 258
255 259 def _get_terminal_display_formatter(self,
256 260 spacer=" "):
257 261 """ generate function to use for terminal formatting
258 262 """
259 263 dirname_output_format = "%s/"
260 264 fname_output_format = spacer + "%s"
261 265 fp_format = '%s/%s'
262 266
263 267 return self._get_display_formatter(dirname_output_format,
264 268 fname_output_format,
265 269 fp_format)
266 270
267 271 def _format_path(self):
268 272 result_lines = []
269 273 walked_dir = list(walk(self.path))
270 274 walked_dir.sort()
271 275 for dirname, subdirs, fnames in walked_dir:
272 276 result_lines += self.notebook_display_formatter(dirname, fnames, self.included_suffixes)
273 277 return '\n'.join(result_lines)
274 278
275 279 def __repr__(self):
276 280 """return newline-separated absolute paths
277 281 """
278 282 result_lines = []
279 283 walked_dir = list(walk(self.path))
280 284 walked_dir.sort()
281 285 for dirname, subdirs, fnames in walked_dir:
282 286 result_lines += self.terminal_display_formatter(dirname, fnames, self.included_suffixes)
283 287 return '\n'.join(result_lines)
@@ -1,140 +1,153 b''
1 1 """Tests for IPython.lib.display.
2 2
3 3 """
4 4 #-----------------------------------------------------------------------------
5 5 # Copyright (c) 2012, the IPython Development Team.
6 6 #
7 7 # Distributed under the terms of the Modified BSD License.
8 8 #
9 9 # The full license is in the file COPYING.txt, distributed with this software.
10 10 #-----------------------------------------------------------------------------
11 11
12 12 #-----------------------------------------------------------------------------
13 13 # Imports
14 14 #-----------------------------------------------------------------------------
15 15 from __future__ import print_function
16 16 from tempfile import NamedTemporaryFile, mkdtemp
17 17 from os.path import split
18 18
19 19 # Third-party imports
20 20 import nose.tools as nt
21 21
22 22 # Our own imports
23 23 from IPython.lib import display
24 24
25 25 #-----------------------------------------------------------------------------
26 26 # Classes and functions
27 27 #-----------------------------------------------------------------------------
28 28
29 29 #--------------------------
30 30 # FileLink tests
31 31 #--------------------------
32 32
33 33 def test_instantiation_FileLink():
34 34 """FileLink: Test class can be instantiated"""
35 35 fl = display.FileLink('example.txt')
36 36
37 37 def test_warning_on_non_existant_path_FileLink():
38 38 """FileLink: Calling _repr_html_ on non-existant files returns a warning
39 39 """
40 40 fl = display.FileLink('example.txt')
41 41 nt.assert_true(fl._repr_html_().startswith('Path (<tt>example.txt</tt>)'))
42 42
43 43 def test_existing_path_FileLink():
44 44 """FileLink: Calling _repr_html_ functions as expected on existing filepath
45 45 """
46 46 tf = NamedTemporaryFile()
47 47 fl = display.FileLink(tf.name)
48 48 actual = fl._repr_html_()
49 49 expected = "<a href='files/%s' target='_blank'>%s</a><br>" % (tf.name,tf.name)
50 50 nt.assert_equal(actual,expected)
51 51
52 52 def test_existing_path_FileLink_repr():
53 53 """FileLink: Calling repr() functions as expected on existing filepath
54 54 """
55 55 tf = NamedTemporaryFile()
56 56 fl = display.FileLink(tf.name)
57 57 actual = repr(fl)
58 58 expected = tf.name
59 59 nt.assert_equal(actual,expected)
60 60
61 def test_error_on_directory_to_FileLink():
62 """FileLink: Raises error when passed directory
63 """
64 td = mkdtemp()
65 nt.assert_raises(ValueError,display.FileLink,td)
66
61 67 #--------------------------
62 68 # FileLinks tests
63 69 #--------------------------
64 70
65 71 def test_instantiation_FileLinks():
66 72 """FileLinks: Test class can be instantiated
67 73 """
68 74 fls = display.FileLinks('example')
69 75
70 76 def test_warning_on_non_existant_path_FileLinks():
71 77 """FileLinks: Calling _repr_html_ on non-existant files returns a warning
72 78 """
73 79 fls = display.FileLinks('example')
74 80 nt.assert_true(fls._repr_html_().startswith('Path (<tt>example</tt>)'))
75 81
76 82 def test_existing_path_FileLinks():
77 83 """FileLinks: Calling _repr_html_ functions as expected on existing dir
78 84 """
79 85 td = mkdtemp()
80 86 tf1 = NamedTemporaryFile(dir=td)
81 87 tf2 = NamedTemporaryFile(dir=td)
82 88 fl = display.FileLinks(td)
83 89 actual = fl._repr_html_()
84 90 actual = actual.split('\n')
85 91 actual.sort()
86 92 expected = ["%s/<br>" % td,
87 93 "&nbsp;&nbsp;<a href='files/%s' target='_blank'>%s</a><br>" % (tf2.name,split(tf2.name)[1]),
88 94 "&nbsp;&nbsp;<a href='files/%s' target='_blank'>%s</a><br>" % (tf1.name,split(tf1.name)[1])]
89 95 expected.sort()
90 96 # We compare the sorted list of links here as that's more reliable
91 97 nt.assert_equal(actual,expected)
92 98
93 99 def test_existing_path_FileLinks_alt_formatter():
94 100 """FileLinks: Calling _repr_html_ functions as expected w/ an alt formatter
95 101 """
96 102 td = mkdtemp()
97 103 tf1 = NamedTemporaryFile(dir=td)
98 104 tf2 = NamedTemporaryFile(dir=td)
99 105 def fake_formatter(dirname,fnames,included_suffixes):
100 106 return ["hello","world"]
101 107 fl = display.FileLinks(td,notebook_display_formatter=fake_formatter)
102 108 actual = fl._repr_html_()
103 109 actual = actual.split('\n')
104 110 actual.sort()
105 111 expected = ["hello","world"]
106 112 expected.sort()
107 113 # We compare the sorted list of links here as that's more reliable
108 114 nt.assert_equal(actual,expected)
109 115
110 116 def test_existing_path_FileLinks_repr():
111 117 """FileLinks: Calling repr() functions as expected on existing directory """
112 118 td = mkdtemp()
113 119 tf1 = NamedTemporaryFile(dir=td)
114 120 tf2 = NamedTemporaryFile(dir=td)
115 121 fl = display.FileLinks(td)
116 122 actual = repr(fl)
117 123 actual = actual.split('\n')
118 124 actual.sort()
119 125 expected = ['%s/' % td, ' %s' % split(tf1.name)[1],' %s' % split(tf2.name)[1]]
120 126 expected.sort()
121 127 # We compare the sorted list of links here as that's more reliable
122 128 nt.assert_equal(actual,expected)
123 129
124 130 def test_existing_path_FileLinks_repr_alt_formatter():
125 131 """FileLinks: Calling repr() functions as expected w/ alt formatter
126 132 """
127 133 td = mkdtemp()
128 134 tf1 = NamedTemporaryFile(dir=td)
129 135 tf2 = NamedTemporaryFile(dir=td)
130 136 def fake_formatter(dirname,fnames,included_suffixes):
131 137 return ["hello","world"]
132 138 fl = display.FileLinks(td,terminal_display_formatter=fake_formatter)
133 139 actual = repr(fl)
134 140 actual = actual.split('\n')
135 141 actual.sort()
136 142 expected = ["hello","world"]
137 143 expected.sort()
138 144 # We compare the sorted list of links here as that's more reliable
139 145 nt.assert_equal(actual,expected)
146
147 def test_error_on_file_to_FileLinks():
148 """FileLinks: Raises error when passed file
149 """
150 td = mkdtemp()
151 tf1 = NamedTemporaryFile(dir=td)
152 nt.assert_raises(ValueError,display.FileLinks,tf1.name)
140 153
General Comments 0
You need to be logged in to leave comments. Login now