Merge lp:~thisfred/autoqueue/lp-777355 into lp:autoqueue
- lp-777355
- Merge into trunk
Proposed by
Eric Casteleijn
Status: | Merged | ||||
---|---|---|---|---|---|
Approved by: | Eric Casteleijn | ||||
Approved revision: | not available | ||||
Merged at revision: | 320 | ||||
Proposed branch: | lp:~thisfred/autoqueue/lp-777355 | ||||
Merge into: | lp:autoqueue | ||||
Diff against target: |
953 lines (+206/-392) 5 files modified
autoqueue/__init__.py (+10/-10) autoqueue/similarity.py (+22/-25) autoqueue/tests/test_autoqueue.py (+86/-249) autoqueue/tests/test_similarity.py (+36/-0) mirage/tests/test_mirage.py (+52/-108) |
||||
To merge this branch: | bzr merge lp:~thisfred/autoqueue/lp-777355 | ||||
Related bugs: |
|
Reviewer | Review Type | Date Requested | Status |
---|---|---|---|
Eric Casteleijn | Pending | ||
Review via email: mp+60134@code.launchpad.net |
Commit message
Fixed tests and removed hopelessly broken ones.
Description of the change
Fixed tests and removed hopelessly broken ones.
To post a comment you must log in.
Preview Diff
[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
1 | === modified file 'autoqueue/__init__.py' |
2 | --- autoqueue/__init__.py 2011-05-03 16:30:52 +0000 |
3 | +++ autoqueue/__init__.py 2011-05-06 00:06:43 +0000 |
4 | @@ -333,7 +333,7 @@ |
5 | else: |
6 | try: |
7 | excluded_filenames.append(unicode(filename, 'utf-8')) |
8 | - except: |
9 | + except UnicodeDecodeError: |
10 | self.log('Could not decode filename: %r' % filename) |
11 | filename = song.get_filename() |
12 | try: |
13 | @@ -343,7 +343,7 @@ |
14 | self.similarity.analyze_track( |
15 | filename, True, excluded_filenames, 5, reply_handler=NO_OP, |
16 | error_handler=NO_OP, timeout=300) |
17 | - except: |
18 | + except UnicodeDecodeError: |
19 | self.log('Could not decode filename: %r' % filename) |
20 | if self.desired_queue_length == 0 or self.queue_needs_songs(): |
21 | self.fill_queue() |
22 | @@ -387,7 +387,7 @@ |
23 | if not isinstance(filename, unicode): |
24 | try: |
25 | filename = filename.decode('utf-8') |
26 | - except: |
27 | + except UnicodeDecodeError: |
28 | self.log('failed to decode filename %r' % filename) |
29 | self.similarity.remove_track_by_filename( |
30 | filename, reply_handler=NO_OP, |
31 | @@ -438,7 +438,7 @@ |
32 | else: |
33 | try: |
34 | excluded_filenames.append(unicode(filename, 'utf-8')) |
35 | - except: |
36 | + except UnicodeDecodeError: |
37 | self.log('Could not decode filename: %r' % filename) |
38 | filename = song.get_filename() |
39 | try: |
40 | @@ -449,7 +449,7 @@ |
41 | filename, True, excluded_filenames, 0, |
42 | reply_handler=self.analyzed, |
43 | error_handler=self.error_handler, timeout=300) |
44 | - except: |
45 | + except UnicodeDecodeError: |
46 | self.log('Could not decode filename: %r' % filename) |
47 | |
48 | def analyzed(self): |
49 | @@ -462,7 +462,7 @@ |
50 | filename, |
51 | reply_handler=self.mirage_reply_handler, |
52 | error_handler=self.error_handler, timeout=300) |
53 | - except: |
54 | + except UnicodeDecodeError: |
55 | self.log('Could not decode filename: %r' % filename) |
56 | |
57 | def done(self): |
58 | @@ -475,7 +475,7 @@ |
59 | else: |
60 | try: |
61 | excluded_filenames.append(unicode(filename, 'utf-8')) |
62 | - except: |
63 | + except UnicodeDecodeError: |
64 | self.log('Could not decode filename: %r' % filename) |
65 | filename = song.get_filename() |
66 | try: |
67 | @@ -486,7 +486,7 @@ |
68 | filename, True, excluded_filenames, 0, |
69 | reply_handler=NO_OP, |
70 | error_handler=NO_OP, timeout=300) |
71 | - except: |
72 | + except UnicodeDecodeError: |
73 | self.log('Could not decode filename: %r' % filename) |
74 | self.running = False |
75 | |
76 | @@ -575,7 +575,7 @@ |
77 | else: |
78 | try: |
79 | excluded_filenames.append(unicode(filename, 'utf-8')) |
80 | - except: |
81 | + except UnicodeDecodeError: |
82 | self.log('Could not decode filename: %r' % filename) |
83 | filename = song.get_filename() |
84 | try: |
85 | @@ -586,7 +586,7 @@ |
86 | filename, True, excluded_filenames, 0, |
87 | reply_handler=self.analyzed, |
88 | error_handler=self.error_handler, timeout=300) |
89 | - except: |
90 | + except UnicodeDecodeError: |
91 | self.log('Could not decode filename: %r' % filename) |
92 | |
93 | def process_results(self, results): |
94 | |
95 | === modified file 'autoqueue/similarity.py' |
96 | --- autoqueue/similarity.py 2011-05-03 16:30:52 +0000 |
97 | +++ autoqueue/similarity.py 2011-05-06 00:06:43 +0000 |
98 | @@ -1,5 +1,7 @@ |
99 | """Autoqueue similarity service.""" |
100 | |
101 | +# TODO: real logging |
102 | + |
103 | import dbus |
104 | import dbus.service |
105 | import gobject |
106 | @@ -32,7 +34,7 @@ |
107 | DBusGMainLoop(set_as_default=True) |
108 | |
109 | DBUS_BUSNAME = 'org.autoqueue' |
110 | -DBUS_IFACE = 'org.autoqueue.SimilarityInterface' |
111 | +IFACE = 'org.autoqueue.SimilarityInterface' |
112 | DBUS_PATH = '/org/autoqueue/Similarity' |
113 | |
114 | # If you change even a single character of code, I would ask that you |
115 | @@ -86,18 +88,18 @@ |
116 | |
117 | def set_path(self, path): |
118 | """Set the database path.""" |
119 | - self.path = path |
120 | + self.path = path # pylint: disable=W0201 |
121 | |
122 | def set_queue(self, queue): |
123 | """Set the queue to use.""" |
124 | - self.queue = queue |
125 | + self.queue = queue # pylint: disable=W0201 |
126 | |
127 | def run(self): |
128 | connection = sqlite3.connect( |
129 | self.path, timeout=5.0, isolation_level="immediate") |
130 | cursor = connection.cursor() |
131 | while True: |
132 | - priority, cmd = self.queue.get() |
133 | + _, cmd = self.queue.get() |
134 | sql = cmd.sql |
135 | if sql == ('STOP',): |
136 | cmd.result_queue.put(None) |
137 | @@ -108,8 +110,7 @@ |
138 | try: |
139 | cursor.execute(*sql) |
140 | except: |
141 | - for s in sql: |
142 | - print repr(s) |
143 | + print repr(sql) # pylint: disable=W0702 |
144 | if not sql[0].upper().startswith('SELECT'): |
145 | commit_needed = True |
146 | for row in cursor.fetchall(): |
147 | @@ -119,11 +120,10 @@ |
148 | cmd.result_queue.put(result) |
149 | |
150 | |
151 | -class Db(object): |
152 | +class Database(object): |
153 | """Database access class.""" |
154 | |
155 | def __init__(self): |
156 | - self._data_dir = None |
157 | self.db_path = os.path.join( |
158 | self.player_get_data_dir(), "similarity.db") |
159 | self.queue = PriorityQueue() |
160 | @@ -147,14 +147,11 @@ |
161 | Defaults to $XDG_DATA_HOME/autoqueue on Gnome. |
162 | |
163 | """ |
164 | - if self._data_dir: |
165 | - return self._data_dir |
166 | if not XDG: |
167 | return NotImplemented |
168 | data_dir = os.path.join(xdg.BaseDirectory.xdg_data_home, 'autoqueue') |
169 | if not os.path.exists(data_dir): |
170 | os.makedirs(data_dir) |
171 | - self._data_dir = data_dir |
172 | return data_dir |
173 | |
174 | def add_track(self, filename, scms, priority): |
175 | @@ -257,7 +254,7 @@ |
176 | if not exclude_filenames: |
177 | exclude_filenames = [] |
178 | to_add = neighbours * 2 |
179 | - _ = self.execute_sql( |
180 | + self.execute_sql( |
181 | ("DELETE FROM distance WHERE track_1 = ?;", (trackid,)), |
182 | priority=priority) |
183 | conf = ScmsConfiguration(20) |
184 | @@ -302,7 +299,7 @@ |
185 | "SELECT * FROM artists WHERE name = ?;", (artist_name,))) |
186 | for row in rows: |
187 | return row |
188 | - _ = self.execute_sql(( |
189 | + self.execute_sql(( |
190 | "INSERT INTO artists (name) VALUES (?);", (artist_name,))) |
191 | rows = self.execute_sql(( |
192 | "SELECT * FROM artists WHERE name = ?;", (artist_name,))) |
193 | @@ -318,7 +315,7 @@ |
194 | (artist_id, title)), priority=0) |
195 | for row in rows: |
196 | return row |
197 | - _ = self.execute_sql(( |
198 | + self.execute_sql(( |
199 | "INSERT INTO tracks (artist, title) VALUES (?, ?);", |
200 | (artist_id, title)), priority=0) |
201 | rows = self.execute_sql(( |
202 | @@ -488,7 +485,8 @@ |
203 | 'DELETE FROM artist_2_artist WHERE artist1 = ? OR artist2 = ' |
204 | '?;', (artist_id, artist_id)), priority=10) |
205 | self.execute_sql( |
206 | - ('DELETE FROM artists WHERE id = ?', (artist_id,)), priority=10) |
207 | + ('DELETE FROM artists WHERE id = ?', (artist_id,)), |
208 | + priority=10) |
209 | |
210 | |
211 | class SimilarityService(dbus.service.Object): |
212 | @@ -496,7 +494,7 @@ |
213 | |
214 | def __init__(self, bus_name, object_path): |
215 | import gst |
216 | - self.db = Db() |
217 | + self.db = Database() |
218 | self.lastfm = True |
219 | self.cache_time = 90 |
220 | super(SimilarityService, self).__init__( |
221 | @@ -592,22 +590,22 @@ |
222 | self.lastfm = False |
223 | return None |
224 | |
225 | - @method(dbus_interface=DBUS_IFACE, in_signature='s') |
226 | + @method(dbus_interface=IFACE, in_signature='s') |
227 | def remove_track_by_filename(self, filename): |
228 | """Remove tracks from database.""" |
229 | self.db.remove_track_by_filename(filename) |
230 | |
231 | - @method(dbus_interface=DBUS_IFACE, in_signature='ss') |
232 | + @method(dbus_interface=IFACE, in_signature='ss') |
233 | def remove_track(self, artist, title): |
234 | """Remove tracks from database.""" |
235 | self.db.remove_track(artist, title) |
236 | |
237 | - @method(dbus_interface=DBUS_IFACE, in_signature='s') |
238 | + @method(dbus_interface=IFACE, in_signature='s') |
239 | def remove_artist(self, artist): |
240 | """Remove tracks from database.""" |
241 | self.db.remove_artist(artist) |
242 | |
243 | - @method(dbus_interface=DBUS_IFACE, in_signature='sbasi') |
244 | + @method(dbus_interface=IFACE, in_signature='sbasi') |
245 | def analyze_track(self, filename, add_neighbours, exclude_filenames, |
246 | priority): |
247 | """Perform mirage analysis of a track.""" |
248 | @@ -635,14 +633,13 @@ |
249 | trackid, scms, exclude_filenames=exclude_filenames, |
250 | neighbours=NEIGHBOURS, priority=priority) |
251 | |
252 | - @method(dbus_interface=DBUS_IFACE, in_signature='s', out_signature='a(is)') |
253 | + @method(dbus_interface=IFACE, in_signature='s', out_signature='a(is)') |
254 | def get_ordered_mirage_tracks(self, filename): |
255 | """Get similar tracks by mirage acoustic analysis.""" |
256 | trackid = self.db.get_track_id(filename, priority=0) |
257 | return self.db.get_neighbours(trackid) |
258 | |
259 | - @method(dbus_interface=DBUS_IFACE, in_signature='ss', |
260 | - out_signature='a(iss)') |
261 | + @method(dbus_interface=IFACE, in_signature='ss', out_signature='a(iss)') |
262 | def get_ordered_similar_tracks(self, artist_name, title): |
263 | """Get similar tracks from last.fm/the database. |
264 | |
265 | @@ -663,8 +660,7 @@ |
266 | return self.get_similar_tracks_from_lastfm( |
267 | artist_name, title, track_id) |
268 | |
269 | - @method(dbus_interface=DBUS_IFACE, in_signature='as', |
270 | - out_signature='a(is)') |
271 | + @method(dbus_interface=IFACE, in_signature='as', out_signature='a(is)') |
272 | def get_ordered_similar_artists(self, artists): |
273 | """Get similar artists from the database. |
274 | |
275 | @@ -694,6 +690,7 @@ |
276 | return results |
277 | |
278 | def run(self): |
279 | + """Run loop.""" |
280 | self.loop.run() |
281 | |
282 | |
283 | |
284 | === modified file 'autoqueue/tests/test_autoqueue.py' |
285 | --- autoqueue/tests/test_autoqueue.py 2011-05-03 14:47:07 +0000 |
286 | +++ autoqueue/tests/test_autoqueue.py 2011-05-06 00:06:43 +0000 |
287 | @@ -1,15 +1,16 @@ |
288 | # -*- coding: utf-8 -*- |
289 | +"""Tests for autoqueue.""" |
290 | import gobject |
291 | -import sqlite3 |
292 | import unittest |
293 | -from datetime import datetime, timedelta |
294 | +from datetime import datetime |
295 | from xml.dom import minidom |
296 | -from autoqueue import SongBase, AutoQueueBase, Throttle |
297 | +from collections import deque |
298 | +from autoqueue import SongBase, AutoQueueBase |
299 | + |
300 | |
301 | # we have to do this or the tests break badly |
302 | gobject.threads_init() |
303 | |
304 | -WAIT_BETWEEN_REQUESTS = timedelta(0,0,10) |
305 | |
306 | FAKE_RESPONSES = { |
307 | 'http://ws.audioscrobbler.com/2.0/?method=track.getsimilar&artist=' |
308 | @@ -31,6 +32,7 @@ |
309 | |
310 | |
311 | class FakePlayer(object): |
312 | + """Fake music player object.""" |
313 | def __init__(self, plugin_on_song_started): |
314 | self.queue = [] |
315 | self.library = [ |
316 | @@ -56,7 +58,8 @@ |
317 | self.plugin_on_song_started = plugin_on_song_started |
318 | |
319 | def satisfies_criteria(self, song, criteria): |
320 | - positions = {'artist':0, 'title':1, 'tags':2} |
321 | + """Check that song satisfies search criteria.""" |
322 | + positions = {'artist': 0, 'title': 1, 'tags': 2} |
323 | for criterium in criteria: |
324 | if criterium.startswith('not_'): |
325 | ncriterium = criterium.split("_")[1] |
326 | @@ -67,7 +70,6 @@ |
327 | song[positions[ncriterium]]): |
328 | return False |
329 | else: |
330 | - #print song, criteria |
331 | if song[positions[ncriterium]] in criteria[criterium]: |
332 | return False |
333 | else: |
334 | @@ -83,12 +85,16 @@ |
335 | return True |
336 | |
337 | def play_song_from_queue(self): |
338 | + """Fake playing a song from the queue.""" |
339 | func = self.plugin_on_song_started |
340 | queue_song = self.queue.pop(0) |
341 | func(queue_song) |
342 | |
343 | |
344 | class FakeSong(SongBase): |
345 | + """Fake song object.""" |
346 | + |
347 | + # pylint: disable=W0231 |
348 | def __init__(self, artist, title, tags=None, performers=None, |
349 | filename=None): |
350 | self.filename = filename |
351 | @@ -96,6 +102,7 @@ |
352 | self.title = title |
353 | self.tags = tags |
354 | self.performers = performers or [] |
355 | + # pylint: enable=W0231 |
356 | |
357 | def get_artist(self): |
358 | return self.artist.lower() |
359 | @@ -127,11 +134,69 @@ |
360 | return .5 |
361 | |
362 | |
363 | +class FakeSimilarityService(object): |
364 | + """Fake similarity Service implementation.""" |
365 | + |
366 | + def analyze_track(self, filename, add_neighbours, exclude_filenames, |
367 | + priority, reply_handler=None, error_handler=None, |
368 | + timeout=0): |
369 | + """Fake analyze.""" |
370 | + reply_handler() |
371 | + |
372 | + def get_ordered_mirage_tracks(self, filename, reply_handler=None, |
373 | + error_handler=None, timeout=0): |
374 | + """Fake get_ordered_mirage_tracks.""" |
375 | + reply_handler([]) |
376 | + |
377 | + def get_ordered_similar_tracks(self, artist_name, title, |
378 | + reply_handler=None, error_handler=None, |
379 | + timeout=0): |
380 | + """Fake get similar tracks.""" |
381 | + reply_handler([(715, 'joanna newsom', 'peach, plum, pear')]) |
382 | + |
383 | + def last_fm_request(self, url): |
384 | + """Fake last.fm request.""" |
385 | + urlfile = FAKE_RESPONSES.get(url) |
386 | + if not urlfile: |
387 | + return None |
388 | + stream = open(urlfile, 'r') |
389 | + try: |
390 | + xmldoc = minidom.parse(stream).documentElement |
391 | + return xmldoc |
392 | + except: # pylint: disable=W0702 |
393 | + return None |
394 | + |
395 | + |
396 | class FakeAutoQueue(AutoQueueBase): |
397 | - def __init__(self): |
398 | + """Fake autoqueue plugin implementation.""" |
399 | + |
400 | + def __init__(self): # pylint: disable=W0231 |
401 | self.connection = None |
402 | self.player = FakePlayer(self.start) |
403 | - super(FakeAutoQueue, self).__init__() |
404 | + self.artist_block_time = 1 |
405 | + self._blocked_artists = deque([]) |
406 | + self._blocked_artists_times = deque([]) |
407 | + self._cache_dir = None |
408 | + self.desired_queue_length = 0 |
409 | + self.cached_misses = deque([]) |
410 | + self.by_mirage = False |
411 | + self.by_tracks = True |
412 | + self.by_artists = True |
413 | + self.by_tags = True |
414 | + self.running = False |
415 | + self.verbose = False |
416 | + self.weed = False |
417 | + self.song = None |
418 | + self.restrictions = None |
419 | + self.prune_artists = [] |
420 | + self.prune_titles = [] |
421 | + self.prune_filenames = [] |
422 | + self._rows = [] |
423 | + self._nrows = [] |
424 | + self.last_songs = [] |
425 | + self.last_song = None |
426 | + self.found = None |
427 | + self.similarity = FakeSimilarityService() |
428 | self.by_tags = True |
429 | self.verbose = True |
430 | |
431 | @@ -139,18 +204,14 @@ |
432 | """Simulate song start.""" |
433 | self.on_song_started(song) |
434 | |
435 | - def get_db_path(self): |
436 | - return ":memory:" |
437 | - |
438 | - def get_database_connection(self): |
439 | - if self.connection: |
440 | - return self.connection |
441 | - self.connection = sqlite3.connect(":memory:") |
442 | - return self.connection |
443 | - |
444 | - def close_database_connection(self, connection): |
445 | - """Close the database connection.""" |
446 | - pass |
447 | + def block_artist(self, artist_name): |
448 | + """Block songs by artist from being played for a while.""" |
449 | + now = datetime.now() |
450 | + self._blocked_artists.append(artist_name) |
451 | + self._blocked_artists_times.append(now) |
452 | + self.log("Blocked artist: %s (%s)" % ( |
453 | + artist_name, |
454 | + len(self._blocked_artists))) |
455 | |
456 | def player_construct_file_search(self, filename, restrictions=None): |
457 | """Construct a search that looks for songs with this artist |
458 | @@ -205,250 +266,26 @@ |
459 | """Return (wrapped) song objects for the songs in the queue.""" |
460 | return self.player.queue |
461 | |
462 | - def last_fm_request(self, url): |
463 | - urlfile = FAKE_RESPONSES.get(url) |
464 | - if not urlfile: |
465 | - return None |
466 | - stream = open(urlfile, 'r') |
467 | - try: |
468 | - xmldoc = minidom.parse(stream).documentElement |
469 | - return xmldoc |
470 | - except: |
471 | - return None |
472 | - |
473 | - def analyze_track(self, song, add_neighbours=False): |
474 | - yield |
475 | - |
476 | - |
477 | -@Throttle(WAIT_BETWEEN_REQUESTS) |
478 | -def throttled_method(): |
479 | - return |
480 | - |
481 | - |
482 | -@Throttle(timedelta(0)) |
483 | -def unthrottled_method(): |
484 | - return |
485 | - |
486 | |
487 | class TestAutoQueue(unittest.TestCase): |
488 | + """Test autoqueue functionality.""" |
489 | + |
490 | def setUp(self): |
491 | self.autoqueue = FakeAutoQueue() |
492 | |
493 | - def test_get_database_connection(self): |
494 | - connection = self.autoqueue.get_database_connection() |
495 | - cursor = connection.cursor() |
496 | - cursor.execute("SELECT * FROM tracks;") |
497 | - rows = cursor.fetchall() |
498 | - self.assertEqual([], rows) |
499 | - |
500 | - def test_get_artist(self): |
501 | - artist = 'joni mitchell' |
502 | - row = self.autoqueue.get_artist(artist) |
503 | - self.assertEqual((artist, None), row[1:]) |
504 | - |
505 | - def test_get_track(self): |
506 | - artist = "nina simone" |
507 | - title = "i think it's going to rain today" |
508 | - artist_id = self.autoqueue.get_artist(artist)[0] |
509 | - row = self.autoqueue.get_track(artist, title) |
510 | - self.assertEqual((artist_id, title, None), row[1:]) |
511 | - |
512 | - def test_get_similar_artists_from_lastfm(self): |
513 | - artist = 'joni mitchell' |
514 | - artist_id = self.autoqueue.get_artist(artist) |
515 | - similar_artists = self.autoqueue.get_similar_artists_from_lastfm( |
516 | - artist, artist_id) |
517 | - td = [ |
518 | - {'score': 10000, 'artist': u'rickie lee jones'}, |
519 | - {'score': 9271, 'artist': u'carole king'}, |
520 | - {'score': 8669, 'artist': u'ani difranco'}, |
521 | - {'score': 8127, 'artist': u'joan baez'}, |
522 | - {'score': 7473, 'artist': u'neil young'}, |
523 | - {'score': 7051, 'artist': u'martha wainwright'}, |
524 | - {'score': 7044, 'artist': u'indigo girls'}, |
525 | - {'score': 6880, 'artist': u'james taylor'}, |
526 | - {'score': 6705, 'artist': u'paul simon'}, |
527 | - {'score': 6677, 'artist': u'dar williams'}, |
528 | - {'score': 6404, 'artist': u'crosby, stills, nash & young'}, |
529 | - {'score': 6229, 'artist': u'k.d. lang'}, |
530 | - {'score': 6151, 'artist': u'simon & garfunkel'}, |
531 | - {'score': 6064, 'artist': u'joan armatrading'}, |
532 | - {'score': 5959, 'artist': u'patty griffin'}, |
533 | - {'score': 5883, 'artist': u'leonard cohen'}, |
534 | - {'score': 5840, 'artist': u'tim buckley'}, |
535 | - {'score': 5702, 'artist': u'suzanne vega'}, |
536 | - {'score': 5649, 'artist': u'janis ian'}, |
537 | - {'score': 5591, 'artist': u'kate bush'}, |
538 | - {'score': 5555, 'artist': u'cat stevens'}, |
539 | - {'score': 5477, 'artist': u'neil young & crazy horse'}] |
540 | - sim = [track for track in similar_artists][:22] |
541 | - self.assertEqual(td, sim) |
542 | - artist = u'habib koité & bamada' |
543 | - row = self.autoqueue.get_artist(artist) |
544 | - artist_id = row[0] |
545 | - similar_artists = self.autoqueue.get_similar_artists_from_lastfm( |
546 | - artist, artist_id) |
547 | - sim = [track for track in similar_artists][:22] |
548 | - td = [ |
549 | - {'score': 10000, 'artist': u'salif keita'}, |
550 | - {'score': 9536, 'artist': u'mamou sidib\xe9'}, |
551 | - {'score': 9330, 'artist': u'k\xe9l\xe9tigui diabat\xe9'}, |
552 | - {'score': 9058, 'artist': u'ali farka tour\xe9'}, |
553 | - {'score': 8917, 'artist': u'habib koit\xe9'}, |
554 | - {'score': 8569, 'artist': u'amadou & mariam'}, |
555 | - {'score': 5950, 'artist': u'tinariwen'}, |
556 | - {'score': 5826, 'artist': u'boubacar traor\xe9'}, |
557 | - {'score': 5371, 'artist': u'oliver mtukudzi'}, |
558 | - {'score': 381, 'artist': u'super rail band'}, |
559 | - {'score': 359, 'artist': u'lobi traor\xe9'}, |
560 | - {'score': 358, |
561 | - 'artist': u'ali farka tour\xe9 & toumani diabat\xe9'}, |
562 | - {'score': 358, 'artist': u'tartit'}, |
563 | - {'score': 355, 'artist': u'issa bagayogo'}, |
564 | - {'score': 349, 'artist': u'kasse mady diabate'}, |
565 | - {'score': 347, 'artist': u'rokia traor\xe9'}, |
566 | - {'score': 346, 'artist': u'daby tour\xe9'}, |
567 | - {'score': 346, 'artist': u'oumou sangar\xe9'}, |
568 | - {'score': 340, 'artist': u'luciana souza'}, |
569 | - {'score': 337, 'artist': u'kandia kouyate'}, |
570 | - {'score': 326, |
571 | - 'artist': u'ali farka tour\xe9 and ry cooder'}, |
572 | - {'score': 318, 'artist': u'sali sidibe'}] |
573 | - self.assertEqual(td, sim) |
574 | - |
575 | - def test_get_similar_tracks_from_lastfm(self): |
576 | - artist = 'nina simone' |
577 | - title = "i think it's going to rain today" |
578 | - track = self.autoqueue.get_track(artist, title) |
579 | - track_id = track[0] |
580 | - similar_tracks = self.autoqueue.get_similar_tracks_from_lastfm( |
581 | - artist, title, track_id) |
582 | - td = [{'title': u'how long has this been going o', |
583 | - 'score': 447, 'artist': u'ella fitzgerald'}, |
584 | - {'title': u'our love is here to stay', 'score': 446, |
585 | - 'artist': u'dinah washington'}, |
586 | - {'title': u'love for sale', 'score': 444, |
587 | - 'artist': u'dinah washington'}, |
588 | - {'title': u'will i find my love today?', 'score': 443, |
589 | - 'artist': u'marlena shaw'}, |
590 | - {'title': u'a couple of loosers', 'score': 443, |
591 | - 'artist': u'marlena shaw'}, |
592 | - {'title': u'reasons', 'score': 438, |
593 | - 'artist': u'minnie riperton'}, |
594 | - {'title': u'sorry (digitally remastered 02)', |
595 | - 'score': 438, |
596 | - 'artist': u'natalie cole'}, |
597 | - {'title': u'stand by (digitally remastered 02)', |
598 | - 'score': 438, 'artist': u'natalie cole'}, |
599 | - {'title': u'adventures in paradise', 'score': 436, |
600 | - 'artist': u'minnie riperton'}, |
601 | - {'title': u"i've got my love to keep me wa", 'score': 436, |
602 | - 'artist': u'ella fitzgerald'}, |
603 | - {'title': u'find him', 'score': 428, |
604 | - 'artist': u'cassandra wilson'}, |
605 | - {'title': u'almost like being in love (lp version)', |
606 | - 'score': 428, 'artist': u'della reese'}, |
607 | - {'title': u'jacaranda bougainvillea', 'score': 426, |
608 | - 'artist': u'al jarreau'}, |
609 | - {'title': u'mellow mood', 'score': 426, |
610 | - 'artist': u'jimmy smith and wes montgomery'}] |
611 | - sim = [track for track in similar_tracks][:14] |
612 | - self.assertEqual(td, sim) |
613 | - |
614 | - def test_get_ordered_similar_artists(self): |
615 | - song = FakeSong('nina simone', 'ne me quitte pas') |
616 | - artist = song.get_artist() |
617 | - similar_artists = self.autoqueue.get_ordered_similar_artists(song) |
618 | - td = [ |
619 | - {'score': 10000, 'artist': u'billie holiday'}, |
620 | - {'score': 7934, 'artist': u'ella fitzgerald'}, |
621 | - {'score': 7402, 'artist': u'sarah vaughan'}, |
622 | - {'score': 6731, 'artist': u'dinah washington'}, |
623 | - {'score': 6518, 'artist': u'madeleine peyroux'}, |
624 | - {'score': 6042, 'artist': u'etta james'}, |
625 | - {'score': 5065, 'artist': u'peggy lee'}, |
626 | - {'score': 4984, 'artist': u'julie london'}, |
627 | - {'score': 4905, |
628 | - 'artist': u'ella fitzgerald & louis armstrong'}, |
629 | - {'score': 4887, 'artist': u'blossom dearie'}] |
630 | - for i, item in enumerate(td): |
631 | - self.assertEqual(td[i], similar_artists.next()) |
632 | - row = self.autoqueue.get_artist(artist) |
633 | - self.assertEqual((artist, None), row[1:]) |
634 | - artist = 'dionne warwick' |
635 | - row = self.autoqueue.get_artist(artist) |
636 | - self.assertEqual((artist, None), row[1:]) |
637 | - |
638 | - def test_get_ordered_similar_tracks(self): |
639 | - song = FakeSong('joni mitchell', 'carey') |
640 | - artist = song.get_artist() |
641 | - title = song.get_title() |
642 | - similar_tracks = self.autoqueue.get_ordered_similar_tracks(song) |
643 | - td = [ |
644 | - {'title': u'things behind the sun', 'score': 838, |
645 | - 'artist': u'nick drake'}, |
646 | - {'title': u'horn', 'score': 807, 'artist': u'nick drake'}, |
647 | - {'title': u'peach, plum, pear', 'score': 715, |
648 | - 'artist': u'joanna newsom'}, |
649 | - {'title': u'suzanne', 'score': 700, |
650 | - 'artist': u'leonard cohen'}, |
651 | - {'title': u'sprout and the bean', 'score': 691, |
652 | - 'artist': u'joanna newsom'}, |
653 | - {'title': u"blowin' in the wind", 'score': 664, |
654 | - 'artist': u'bob dylan'}, |
655 | - {'title': u'famous blue raincoat', 'score': 635, |
656 | - 'artist': u'leonard cohen'}, |
657 | - {'title': u'song for the asking', 'score': 598, |
658 | - 'artist': u'simon & garfunkel'}, |
659 | - {'title': u"the times they are a-changin'", 'score': 593, |
660 | - 'artist': u'bob dylan'}, |
661 | - {'title': u'keep the customer satisfied', 'score': 535, |
662 | - 'artist': u'simon & garfunkel'}, |
663 | - {'title': u'peace train', 'score': 520, |
664 | - 'artist': u'cat stevens'}, |
665 | - {'title': u'fire and rain', 'score': 511, |
666 | - 'artist': u'james taylor'}, |
667 | - {'title': u'enough to be on your way', 'score': 451, |
668 | - 'artist': u'james taylor'}, |
669 | - {'title': u"that's the spirit", 'score': 449, |
670 | - 'artist': u'judee sill'}] |
671 | - sim = [track for track in similar_tracks][:14] |
672 | - self.assertEqual(td, sim) |
673 | - artist_id = self.autoqueue.get_artist(artist)[0] |
674 | - row = self.autoqueue.get_track(artist, title) |
675 | - self.assertEqual((artist_id, title, None), row[1:]) |
676 | - artist = 'leonard cohen' |
677 | - title = 'suzanne' |
678 | - artist_id = self.autoqueue.get_artist(artist)[0] |
679 | - row = self.autoqueue.get_track(artist, title) |
680 | - self.assertEqual((artist_id, title, None), row[1:]) |
681 | - |
682 | def test_queue_needs_songs(self): |
683 | + """Test the queue_needs_songs method.""" |
684 | self.autoqueue.desired_queue_length = 4 |
685 | self.assertEqual(True, self.autoqueue.queue_needs_songs()) |
686 | test_song = FakeSong('Joni Mitchell', 'Carey') |
687 | - for i in range(4): |
688 | + for _ in range(4): |
689 | self.autoqueue.player_enqueue(test_song) |
690 | self.assertEqual(False, self.autoqueue.queue_needs_songs()) |
691 | |
692 | def test_on_song_started(self): |
693 | + """Test the on_song_started handler.""" |
694 | test_song = FakeSong('Joni Mitchell', 'Carey') |
695 | self.autoqueue.start(test_song) |
696 | songs_in_queue = self.autoqueue.player_get_songs_in_queue() |
697 | self.assertEqual('joanna newsom', songs_in_queue[0].get_artist()) |
698 | self.assertEqual('peach, plum, pear', songs_in_queue[0].get_title()) |
699 | - |
700 | - |
701 | -class TestThrottle(unittest.TestCase): |
702 | - """Test the throttle decorator.""" |
703 | - |
704 | - def test_throttle(self): |
705 | - """Test throttling.""" |
706 | - now = datetime.now() |
707 | - times = 0 |
708 | - while True: |
709 | - throttled_method() |
710 | - times += 1 |
711 | - if datetime.now() > (now + timedelta(0, 0, 1000)): |
712 | - break |
713 | - self.assertEqual(True, times < 100) |
714 | |
715 | === added file 'autoqueue/tests/test_similarity.py' |
716 | --- autoqueue/tests/test_similarity.py 1970-01-01 00:00:00 +0000 |
717 | +++ autoqueue/tests/test_similarity.py 2011-05-06 00:06:43 +0000 |
718 | @@ -0,0 +1,36 @@ |
719 | +# -*- coding: utf-8 -*- |
720 | +"""Tests for autoqueue.similarity.""" |
721 | + |
722 | +import unittest |
723 | +from datetime import datetime, timedelta |
724 | +from autoqueue.similarity import Throttle, Database |
725 | + |
726 | +WAIT_BETWEEN_REQUESTS = timedelta(0, 0, 10) |
727 | + |
728 | + |
729 | +@Throttle(WAIT_BETWEEN_REQUESTS) |
730 | +def throttled_method(): |
731 | + """Dummy method.""" |
732 | + return |
733 | + |
734 | + |
735 | +@Throttle(timedelta(0)) |
736 | +def unthrottled_method(): |
737 | + """Dummy method.""" |
738 | + return |
739 | + |
740 | + |
741 | +class TestThrottle(unittest.TestCase): |
742 | + """Test the throttle decorator.""" |
743 | + |
744 | + def test_throttle(self): |
745 | + """Test throttling.""" |
746 | + now = datetime.now() |
747 | + times = 0 |
748 | + while True: |
749 | + throttled_method() |
750 | + times += 1 |
751 | + if datetime.now() > (now + timedelta(0, 0, 1000)): |
752 | + break |
753 | + self.assertEqual(True, times < 100) |
754 | + |
755 | |
756 | === modified file 'mirage/tests/test_mirage.py' |
757 | --- mirage/tests/test_mirage.py 2011-05-03 14:42:24 +0000 |
758 | +++ mirage/tests/test_mirage.py 2011-05-06 00:06:43 +0000 |
759 | @@ -1,53 +1,42 @@ |
760 | -import unittest, sqlite3 |
761 | -from mirage import Mir, Matrix, Db, ScmsConfiguration |
762 | +"""Tests for mirage.""" |
763 | +import unittest |
764 | +from mirage import Mir, Matrix, ScmsConfiguration |
765 | from mirage import distance |
766 | from decimal import Decimal, getcontext |
767 | |
768 | import gst |
769 | |
770 | -mir = Mir() |
771 | +MIR = Mir() |
772 | |
773 | -filenames = [ |
774 | +FILENAMES = [ |
775 | 'mirage/tests/testfiles/test.mp3', |
776 | 'mirage/tests/testfiles/test2.mp3', |
777 | 'mirage/tests/testfiles/test3.ogg', |
778 | 'mirage/tests/testfiles/test4.ogg', |
779 | 'mirage/tests/testfiles/test5.ogg'] |
780 | |
781 | -scmses = {} |
782 | - |
783 | -for filename in filenames: |
784 | - scmses[filename] = mir.analyze(filename) |
785 | - |
786 | -scms = scmses[filenames[0]] |
787 | -scms2 = scmses[filenames[1]] |
788 | -scms3 = scmses[filenames[2]] |
789 | -scms4 = scmses[filenames[3]] |
790 | -scms5 = scmses[filenames[4]] |
791 | +SCMSES = {} |
792 | + |
793 | +for filename in FILENAMES: |
794 | + SCMSES[filename] = MIR.analyze(filename) |
795 | + |
796 | +SCMS = SCMSES[FILENAMES[0]] |
797 | +SCMS2 = SCMSES[FILENAMES[1]] |
798 | +SCMS3 = SCMSES[FILENAMES[2]] |
799 | +SCMS4 = SCMSES[FILENAMES[3]] |
800 | +SCMS5 = SCMSES[FILENAMES[4]] |
801 | + |
802 | |
803 | def decimize(f): |
804 | + """Convert to decimal.""" |
805 | return Decimal(str(f)) |
806 | |
807 | |
808 | class TestMir(unittest.TestCase): |
809 | - def setUp(self): |
810 | - connection = sqlite3.connect(":memory:") |
811 | - self.db = Db(":memory:", connection=connection) |
812 | - connection.execute( |
813 | - 'CREATE TABLE IF NOT EXISTS mirage (trackid INTEGER PRIMARY KEY, ' |
814 | - 'filename VARCHAR(300), scms BLOB)') |
815 | - connection.execute( |
816 | - "CREATE TABLE IF NOT EXISTS distance (track_1 INTEGER, track_2 " |
817 | - "INTEGER, distance INTEGER)") |
818 | - connection.execute( |
819 | - "CREATE INDEX IF NOT EXISTS mfnx ON mirage (filename)") |
820 | - connection.execute( |
821 | - "CREATE INDEX IF NOT EXISTS dtrack1x ON distance (track_1)") |
822 | - connection.execute( |
823 | - "CREATE INDEX IF NOT EXISTS dtrack2x ON distance (track_2)") |
824 | - connection.commit() |
825 | + """Test mirage analysis and comparison.""" |
826 | |
827 | def test_matrix(self): |
828 | + """Test the matrix object.""" |
829 | getcontext().prec = 6 |
830 | mat = Matrix(8, 5) |
831 | for i in range(mat.rows): |
832 | @@ -65,6 +54,7 @@ |
833 | 0.875, 1.0, 1.125, 1.25, 1.375]]) |
834 | |
835 | def test_multiply(self): |
836 | + """Test matrix multiplication.""" |
837 | getcontext().prec = 6 |
838 | mat = Matrix(8, 5) |
839 | for i in range(mat.rows): |
840 | @@ -88,81 +78,35 @@ |
841 | 0.0, 2.3375, 4.675, 7.0125]]) |
842 | |
843 | def test_analysis(self): |
844 | - c = ScmsConfiguration(20) |
845 | - |
846 | - self.assertEqual(0, int(distance(scms, scms, c))) |
847 | - self.assertEqual(75, int(distance(scms, scms2, c))) |
848 | - self.assertEqual(52, int(distance(scms, scms3, c))) |
849 | - self.assertEqual(69, int(distance(scms, scms4, c))) |
850 | - self.assertEqual(240, int(distance(scms, scms5, c))) |
851 | - |
852 | - self.assertEqual(75, int(distance(scms2, scms, c))) |
853 | - self.assertEqual(0, int(distance(scms2, scms2, c))) |
854 | - self.assertEqual(16, int(distance(scms2, scms3, c))) |
855 | - self.assertEqual(59, int(distance(scms2, scms4, c))) |
856 | - self.assertEqual(124, int(distance(scms2, scms5, c))) |
857 | - |
858 | - self.assertEqual(52, int(distance(scms3, scms, c))) |
859 | - self.assertEqual(16, int(distance(scms3, scms2, c))) |
860 | - self.assertEqual(0, int(distance(scms3, scms3, c))) |
861 | - self.assertEqual(49, int(distance(scms3, scms4, c))) |
862 | - self.assertEqual(84, int(distance(scms3, scms5, c))) |
863 | - |
864 | - self.assertEqual(69, int(distance(scms4, scms, c))) |
865 | - self.assertEqual(59, int(distance(scms4, scms2, c))) |
866 | - self.assertEqual(49, int(distance(scms4, scms3, c))) |
867 | - self.assertEqual(0, int(distance(scms4, scms4, c))) |
868 | - self.assertEqual(124, int(distance(scms4, scms5, c))) |
869 | - |
870 | - self.assertEqual(240, int(distance(scms5, scms, c))) |
871 | - self.assertEqual(124, int(distance(scms5, scms2, c))) |
872 | - self.assertEqual(84, int(distance(scms5, scms3, c))) |
873 | - self.assertEqual(124, int(distance(scms5, scms4, c))) |
874 | - self.assertEqual(0, int(distance(scms5, scms5, c))) |
875 | - |
876 | - def test_add_track(self): |
877 | - for filename in filenames: |
878 | - self.db.add_track(filename, scmses[filename]) |
879 | - self.assertEqual( |
880 | - [1,2,3,4,5], |
881 | - sorted([id for (scms, id) in |
882 | - self.db.get_tracks()])) |
883 | - self.assertEqual( |
884 | - [1,2,5], |
885 | - sorted([id for (scms, id) in |
886 | - self.db.get_tracks(exclude_ids=['3','4'])])) |
887 | - |
888 | - def test_get_track(self): |
889 | - for filename in filenames: |
890 | - self.db.add_track(filename, scmses[filename]) |
891 | - scms3_db = self.db.get_track(filenames[2])[1] |
892 | - scms4_db = self.db.get_track(filenames[3])[1] |
893 | - c = ScmsConfiguration(20) |
894 | - self.assertEqual(49, int(distance(scms3_db, scms4_db, c))) |
895 | - |
896 | - def test_add_neighbours(self): |
897 | - for filename in filenames: |
898 | - testscms = scmses[filename] |
899 | - self.db.add_track(filename, testscms) |
900 | - track_id = self.db.get_track_id(filename) |
901 | - for dummy in self.db.add_neighbours(track_id, testscms): |
902 | - pass |
903 | - connection = self.db.get_database_connection() |
904 | - distances = [ |
905 | - row for row in connection.execute("SELECT * FROM distance")] |
906 | - self.assertEqual( |
907 | - [(2, 1, 75208), (3, 1, 52895), (3, 2, 16559), (4, 1, 69194), |
908 | - (4, 2, 59488), (4, 3, 49652), (5, 1, 240408), (5, 4, 124490), |
909 | - (5, 2, 124272), (5, 3, 84228)], |
910 | - distances) |
911 | - |
912 | - def test_get_neighbours(self): |
913 | - for filename in filenames: |
914 | - testscms = scmses[filename] |
915 | - self.db.add_track(filename, testscms) |
916 | - track_id = self.db.get_track_id(filename) |
917 | - for dummy in self.db.add_neighbours(track_id, testscms): |
918 | - pass |
919 | - self.assertEqual( |
920 | - [(84228, 3), (124272, 2), (124490, 4), (240408, 1)], |
921 | - [a for a in self.db.get_neighbours(5)]) |
922 | + """Test mirage analysis.""" |
923 | + conf = ScmsConfiguration(20) |
924 | + |
925 | + self.assertEqual(0, int(distance(SCMS, SCMS, conf))) |
926 | + self.assertEqual(75, int(distance(SCMS, SCMS2, conf))) |
927 | + self.assertEqual(52, int(distance(SCMS, SCMS3, conf))) |
928 | + self.assertEqual(69, int(distance(SCMS, SCMS4, conf))) |
929 | + self.assertEqual(240, int(distance(SCMS, SCMS5, conf))) |
930 | + |
931 | + self.assertEqual(75, int(distance(SCMS2, SCMS, conf))) |
932 | + self.assertEqual(0, int(distance(SCMS2, SCMS2, conf))) |
933 | + self.assertEqual(16, int(distance(SCMS2, SCMS3, conf))) |
934 | + self.assertEqual(59, int(distance(SCMS2, SCMS4, conf))) |
935 | + self.assertEqual(124, int(distance(SCMS2, SCMS5, conf))) |
936 | + |
937 | + self.assertEqual(52, int(distance(SCMS3, SCMS, conf))) |
938 | + self.assertEqual(16, int(distance(SCMS3, SCMS2, conf))) |
939 | + self.assertEqual(0, int(distance(SCMS3, SCMS3, conf))) |
940 | + self.assertEqual(49, int(distance(SCMS3, SCMS4, conf))) |
941 | + self.assertEqual(84, int(distance(SCMS3, SCMS5, conf))) |
942 | + |
943 | + self.assertEqual(69, int(distance(SCMS4, SCMS, conf))) |
944 | + self.assertEqual(59, int(distance(SCMS4, SCMS2, conf))) |
945 | + self.assertEqual(49, int(distance(SCMS4, SCMS3, conf))) |
946 | + self.assertEqual(0, int(distance(SCMS4, SCMS4, conf))) |
947 | + self.assertEqual(124, int(distance(SCMS4, SCMS5, conf))) |
948 | + |
949 | + self.assertEqual(240, int(distance(SCMS5, SCMS, conf))) |
950 | + self.assertEqual(124, int(distance(SCMS5, SCMS2, conf))) |
951 | + self.assertEqual(84, int(distance(SCMS5, SCMS3, conf))) |
952 | + self.assertEqual(124, int(distance(SCMS5, SCMS4, conf))) |
953 | + self.assertEqual(0, int(distance(SCMS5, SCMS5, conf))) |