Skip to content

Commit ba773a0

Browse files
committed
Release v2.0.1
2 parents 6a63f60 + fcc3aa3 commit ba773a0

File tree

5 files changed

+113
-15
lines changed

5 files changed

+113
-15
lines changed

README.rst

+8
Original file line numberDiff line numberDiff line change
@@ -139,6 +139,14 @@ Project resources
139139
Changelog
140140
=========
141141

142+
v2.0.1 (2015-08-23)
143+
-------------------
144+
145+
Bug fix release.
146+
147+
- Filter out ``None`` from ``library.get_distinct()`` return values. (Fixes:
148+
#63)
149+
142150
v2.0.0 (2015-08-11)
143151
-------------------
144152

mopidy_spotify/__init__.py

+1-1
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@
55
from mopidy import config, ext
66

77

8-
__version__ = '2.0.0'
8+
__version__ = '2.0.1'
99

1010

1111
class Extension(ext.Extension):

mopidy_spotify/distinct.py

+17-10
Original file line numberDiff line numberDiff line change
@@ -18,15 +18,17 @@ def get_distinct(config, session, field, query=None):
1818
sp_query = translator.sp_search_query(query) if query else None
1919

2020
if field == 'artist':
21-
return _get_distinct_artists(config, session, sp_query)
21+
result = _get_distinct_artists(config, session, sp_query)
2222
elif field == 'albumartist':
23-
return _get_distinct_albumartists(config, session, sp_query)
23+
result = _get_distinct_albumartists(config, session, sp_query)
2424
elif field == 'album':
25-
return _get_distinct_albums(config, session, sp_query)
25+
result = _get_distinct_albums(config, session, sp_query)
2626
elif field == 'date':
27-
return _get_distinct_dates(config, session, sp_query)
27+
result = _get_distinct_dates(config, session, sp_query)
2828
else:
29-
return set()
29+
result = set()
30+
31+
return result - {None}
3032

3133

3234
def _get_distinct_artists(config, session, sp_query):
@@ -50,11 +52,15 @@ def _get_distinct_albumartists(config, session, sp_query):
5052
sp_search = _get_sp_search(config, session, sp_query, album=True)
5153
if sp_search is None:
5254
return set()
53-
return {album.artist.name for album in sp_search.albums}
55+
return {
56+
album.artist.name
57+
for album in sp_search.albums
58+
if album.artist}
5459
else:
5560
return {
5661
track.album.artist.name
57-
for track in _get_playlist_tracks(config, session)}
62+
for track in _get_playlist_tracks(config, session)
63+
if track.album and track.album.artist}
5864

5965

6066
def _get_distinct_albums(config, session, sp_query):
@@ -67,7 +73,8 @@ def _get_distinct_albums(config, session, sp_query):
6773
else:
6874
return {
6975
track.album.name
70-
for track in _get_playlist_tracks(config, session)}
76+
for track in _get_playlist_tracks(config, session)
77+
if track.album}
7178

7279

7380
def _get_distinct_dates(config, session, sp_query):
@@ -79,12 +86,12 @@ def _get_distinct_dates(config, session, sp_query):
7986
return {
8087
'%s' % album.year
8188
for album in sp_search.albums
82-
if album.year != 0}
89+
if album.year not in (None, 0)}
8390
else:
8491
return {
8592
'%s' % track.album.year
8693
for track in _get_playlist_tracks(config, session)
87-
if track.album.year != 0}
94+
if track.album and track.album.year not in (None, 0)}
8895

8996

9097
def _get_sp_search(

tests/conftest.py

+76
Original file line numberDiff line numberDiff line change
@@ -66,6 +66,21 @@ def sp_artist_mock():
6666
return sp_artist
6767

6868

69+
@pytest.fixture
70+
def sp_unloaded_artist_mock():
71+
sp_artist = mock.Mock(spec=spotify.Artist)
72+
sp_artist.is_loaded = False
73+
sp_artist.name = None
74+
75+
sp_link = mock.Mock(spec=spotify.Link)
76+
sp_link.uri = 'spotify:artist:abba'
77+
sp_link.type = spotify.LinkType.ARTIST
78+
sp_link.as_artist.return_value = sp_artist
79+
sp_artist.link = sp_link
80+
81+
return sp_artist
82+
83+
6984
@pytest.fixture
7085
def sp_artist_browser_mock(sp_artist_mock, sp_album_mock):
7186
sp_artist_browser = mock.Mock(spec=spotify.ArtistBrowser)
@@ -94,6 +109,25 @@ def sp_album_mock(sp_artist_mock):
94109
return sp_album
95110

96111

112+
@pytest.fixture
113+
def sp_unloaded_album_mock(sp_unloaded_artist_mock):
114+
sp_album = mock.Mock(spec=spotify.Album)
115+
sp_album.is_loaded = True
116+
sp_album.is_loaded = False
117+
sp_album.name = None
118+
# Optimally, we should test with both None and sp_unloaded_artist_mock
119+
sp_album.artist = sp_unloaded_artist_mock
120+
sp_album.year = None
121+
122+
sp_link = mock.Mock(spec=spotify.Link)
123+
sp_link.uri = 'spotify:album:def'
124+
sp_link.type = spotify.LinkType.ALBUM
125+
sp_link.as_album.return_value = sp_album
126+
sp_album.link = sp_link
127+
128+
return sp_album
129+
130+
97131
@pytest.fixture
98132
def sp_album_browser_mock(sp_album_mock, sp_track_mock):
99133
sp_album_browser = mock.Mock(spec=spotify.AlbumBrowser)
@@ -128,6 +162,30 @@ def sp_track_mock(sp_artist_mock, sp_album_mock):
128162
return sp_track
129163

130164

165+
@pytest.fixture
166+
def sp_unloaded_track_mock(sp_unloaded_artist_mock, sp_unloaded_album_mock):
167+
sp_track = mock.Mock(spec=spotify.Track)
168+
sp_track.is_loaded = False
169+
sp_track.error = spotify.ErrorType.OK
170+
sp_track.availability = None
171+
sp_track.name = None
172+
# Optimally, we should test with both None and [sp_unloaded_artist_mock]
173+
sp_track.artists = [sp_unloaded_artist_mock]
174+
# Optimally, we should test with both None and sp_unloaded_album_mock
175+
sp_track.album = sp_unloaded_album_mock
176+
sp_track.duration = None
177+
sp_track.disc = None
178+
sp_track.index = None
179+
180+
sp_link = mock.Mock(spec=spotify.Link)
181+
sp_link.uri = 'spotify:track:abc'
182+
sp_link.type = spotify.LinkType.TRACK
183+
sp_link.as_track.return_value = sp_track
184+
sp_track.link = sp_link
185+
186+
return sp_track
187+
188+
131189
@pytest.fixture
132190
def sp_starred_mock(sp_user_mock, sp_artist_mock, sp_album_mock):
133191
sp_track1 = sp_track_mock(sp_artist_mock, sp_album_mock)
@@ -170,6 +228,24 @@ def sp_playlist_mock(sp_user_mock, sp_track_mock):
170228
return sp_playlist
171229

172230

231+
@pytest.fixture
232+
def sp_unloaded_playlist_mock(sp_unloaded_track_mock):
233+
sp_playlist = mock.Mock(spec=spotify.Playlist)
234+
sp_playlist.is_loaded = False
235+
sp_playlist.owner = None
236+
sp_playlist.name = None
237+
# Optimally, we should test with both None and [sp_unloaded_track_mock]
238+
sp_playlist.tracks = [sp_unloaded_track_mock]
239+
240+
sp_link = mock.Mock(spec=spotify.Link)
241+
sp_link.uri = 'spotify:user:alice:playlist:foo'
242+
sp_link.type = spotify.LinkType.PLAYLIST
243+
sp_link.as_playlist.return_value = sp_playlist
244+
sp_playlist.link = sp_link
245+
246+
return sp_playlist
247+
248+
173249
@pytest.fixture
174250
def sp_playlist_folder_start_mock():
175251
sp_playlist_folder_start = mock.Mock(spec=spotify.PlaylistFolder)

tests/test_distinct.py

+11-4
Original file line numberDiff line numberDiff line change
@@ -7,22 +7,29 @@
77

88
@pytest.fixture
99
def session_mock_with_playlists(
10-
session_mock, sp_playlist_mock,
10+
session_mock, sp_playlist_mock, sp_unloaded_playlist_mock,
1111
sp_playlist_folder_start_mock, sp_playlist_folder_end_mock):
1212

1313
session_mock.playlist_container = [
1414
sp_playlist_folder_start_mock,
1515
sp_playlist_mock,
16+
sp_unloaded_playlist_mock,
1617
sp_playlist_folder_end_mock,
1718
]
1819
return session_mock
1920

2021

2122
@pytest.fixture
22-
def session_mock_with_search(session_mock, sp_album_mock, sp_artist_mock):
23+
def session_mock_with_search(
24+
session_mock,
25+
sp_album_mock, sp_unloaded_album_mock,
26+
sp_artist_mock, sp_unloaded_artist_mock):
27+
2328
session_mock.connection.state = spotify.ConnectionState.LOGGED_IN
24-
session_mock.search.return_value.albums = [sp_album_mock]
25-
session_mock.search.return_value.artists = [sp_artist_mock]
29+
session_mock.search.return_value.albums = [
30+
sp_album_mock, sp_unloaded_album_mock]
31+
session_mock.search.return_value.artists = [
32+
sp_artist_mock, sp_unloaded_artist_mock]
2633
return session_mock
2734

2835

0 commit comments

Comments
 (0)