aboutsummaryrefslogtreecommitdiff
path: root/tests/test_pandora
diff options
context:
space:
mode:
Diffstat (limited to 'tests/test_pandora')
-rw-r--r--tests/test_pandora/test_client.py237
-rw-r--r--tests/test_pandora/test_clientbuilder.py112
-rw-r--r--tests/test_pandora/test_errors.py1
-rw-r--r--tests/test_pandora/test_models.py303
-rw-r--r--tests/test_pandora/test_transport.py60
5 files changed, 397 insertions, 316 deletions
diff --git a/tests/test_pandora/test_client.py b/tests/test_pandora/test_client.py
index 8144f42..1c5a229 100644
--- a/tests/test_pandora/test_client.py
+++ b/tests/test_pandora/test_client.py
@@ -13,7 +13,6 @@ from tests.test_pandora.test_models import TestAdItem
13 13
14 14
15class TestAPIClientLogin(TestCase): 15class TestAPIClientLogin(TestCase):
16
17 class StubTransport: 16 class StubTransport:
18 17
19 API_VERSION = None 18 API_VERSION = None
@@ -56,7 +55,6 @@ class TestAPIClientLogin(TestCase):
56 55
57 56
58class TestCallingAPIClient(TestCase): 57class TestCallingAPIClient(TestCase):
59
60 def test_call_should_retry_on_token_error(self): 58 def test_call_should_retry_on_token_error(self):
61 transport = Mock(side_effect=[errors.InvalidAuthToken(), None]) 59 transport = Mock(side_effect=[errors.InvalidAuthToken(), None])
62 60
@@ -70,37 +68,44 @@ class TestCallingAPIClient(TestCase):
70 transport.assert_has_calls([call("method"), call("method")]) 68 transport.assert_has_calls([call("method"), call("method")])
71 69
72 def test_playlist_fetches_ads(self): 70 def test_playlist_fetches_ads(self):
73 fake_playlist = {"items": [ 71 fake_playlist = {
74 {"songName": "test"}, 72 "items": [
75 {"adToken": "foo"}, 73 {"songName": "test"},
76 {"songName": "test"}, 74 {"adToken": "foo"},
77 ]} 75 {"songName": "test"},
78 with patch.object(APIClient, '__call__', return_value=fake_playlist): 76 ]
77 }
78 with patch.object(APIClient, "__call__", return_value=fake_playlist):
79 client = APIClient(Mock(), None, None, None, None) 79 client = APIClient(Mock(), None, None, None, None)
80 client._authenticate = Mock() 80 client._authenticate = Mock()
81 81
82 items = client.get_playlist('token_mock') 82 items = client.get_playlist("token_mock")
83 self.assertIsInstance(items[1], AdItem) 83 self.assertIsInstance(items[1], AdItem)
84 84
85 def test_ad_support_enabled_parameters(self): 85 def test_ad_support_enabled_parameters(self):
86 with patch.object(APIClient, '__call__') as playlist_mock: 86 with patch.object(APIClient, "__call__") as playlist_mock:
87 transport = Mock(side_effect=[errors.InvalidAuthToken(), None]) 87 transport = Mock(side_effect=[errors.InvalidAuthToken(), None])
88 88
89 client = APIClient(transport, None, None, None, None) 89 client = APIClient(transport, None, None, None, None)
90 client._authenticate = Mock() 90 client._authenticate = Mock()
91 91
92 client.get_playlist('token_mock') 92 client.get_playlist("token_mock")
93 93
94 playlist_mock.assert_has_calls([call("station.getPlaylist", 94 playlist_mock.assert_has_calls(
95 additionalAudioUrl='', 95 [
96 audioAdPodCapable=True, 96 call(
97 includeTrackLength=True, 97 "station.getPlaylist",
98 stationToken='token_mock', 98 additionalAudioUrl="",
99 xplatformAdCapable=True)]) 99 audioAdPodCapable=True,
100 includeTrackLength=True,
101 stationToken="token_mock",
102 xplatformAdCapable=True,
103 )
104 ]
105 )
100 106
101 107
102class TestGettingQualities(TestCase): 108class TestGettingQualities(TestCase):
103
104 def test_with_invalid_quality_returning_all(self): 109 def test_with_invalid_quality_returning_all(self):
105 result = BaseAPIClient.get_qualities("foo", True) 110 result = BaseAPIClient.get_qualities("foo", True)
106 self.assertEqual(BaseAPIClient.ALL_QUALITIES, result) 111 self.assertEqual(BaseAPIClient.ALL_QUALITIES, result)
@@ -111,20 +116,22 @@ class TestGettingQualities(TestCase):
111 116
112 def test_with_valid_quality(self): 117 def test_with_valid_quality(self):
113 result = BaseAPIClient.get_qualities( 118 result = BaseAPIClient.get_qualities(
114 BaseAPIClient.MED_AUDIO_QUALITY, False) 119 BaseAPIClient.MED_AUDIO_QUALITY, False
120 )
115 121
116 expected = [ 122 expected = [
117 BaseAPIClient.LOW_AUDIO_QUALITY, 123 BaseAPIClient.LOW_AUDIO_QUALITY,
118 BaseAPIClient.MED_AUDIO_QUALITY] 124 BaseAPIClient.MED_AUDIO_QUALITY,
125 ]
119 126
120 self.assertEqual(expected, result) 127 self.assertEqual(expected, result)
121 128
122 129
123class TestGettingAds(TestCase): 130class TestGettingAds(TestCase):
124
125 def test_get_ad_item_(self): 131 def test_get_ad_item_(self):
126 metamock = patch.object( 132 metamock = patch.object(
127 APIClient, '__call__', return_value=TestAdItem.JSON_DATA) 133 APIClient, "__call__", return_value=TestAdItem.JSON_DATA
134 )
128 135
129 with metamock as ad_metadata_mock: 136 with metamock as ad_metadata_mock:
130 transport = Mock(side_effect=[errors.InvalidAuthToken(), None]) 137 transport = Mock(side_effect=[errors.InvalidAuthToken(), None])
@@ -132,13 +139,20 @@ class TestGettingAds(TestCase):
132 client = APIClient(transport, None, None, None, None) 139 client = APIClient(transport, None, None, None, None)
133 client._authenticate = Mock() 140 client._authenticate = Mock()
134 141
135 ad_item = client.get_ad_item('id_mock', 'token_mock') 142 ad_item = client.get_ad_item("id_mock", "token_mock")
136 assert ad_item.station_id == 'id_mock' 143 assert ad_item.station_id == "id_mock"
137 assert ad_item.ad_token == 'token_mock' 144 assert ad_item.ad_token == "token_mock"
138 145
139 ad_metadata_mock.assert_has_calls([ 146 ad_metadata_mock.assert_has_calls(
140 call("ad.getAdMetadata", adToken='token_mock', 147 [
141 returnAdTrackingTokens=True, supportAudioAds=True)]) 148 call(
149 "ad.getAdMetadata",
150 adToken="token_mock",
151 returnAdTrackingTokens=True,
152 supportAudioAds=True,
153 )
154 ]
155 )
142 156
143 def test_get_ad_item_with_no_station_id_specified_raises_exception(self): 157 def test_get_ad_item_with_no_station_id_specified_raises_exception(self):
144 transport = Mock(side_effect=[errors.InvalidAuthToken(), None]) 158 transport = Mock(side_effect=[errors.InvalidAuthToken(), None])
@@ -147,28 +161,31 @@ class TestGettingAds(TestCase):
147 client.get_ad_metadata = Mock() 161 client.get_ad_metadata = Mock()
148 162
149 self.assertRaises( 163 self.assertRaises(
150 errors.ParameterMissing, client.get_ad_item, '', 'token_mock') 164 errors.ParameterMissing, client.get_ad_item, "", "token_mock"
165 )
151 166
152 167
153class TestCreatingStation(TestCase): 168class TestCreatingStation(TestCase):
154
155 def test_using_search_token(self): 169 def test_using_search_token(self):
156 client = APIClient(Mock(return_value={}), None, None, None, None) 170 client = APIClient(Mock(return_value={}), None, None, None, None)
157 client.create_station(search_token="foo") 171 client.create_station(search_token="foo")
158 client.transport.assert_called_with( 172 client.transport.assert_called_with(
159 "station.createStation", musicToken="foo") 173 "station.createStation", musicToken="foo"
174 )
160 175
161 def test_using_artist_token(self): 176 def test_using_artist_token(self):
162 client = APIClient(Mock(return_value={}), None, None, None, None) 177 client = APIClient(Mock(return_value={}), None, None, None, None)
163 client.create_station(artist_token="foo") 178 client.create_station(artist_token="foo")
164 client.transport.assert_called_with( 179 client.transport.assert_called_with(
165 "station.createStation", trackToken="foo", musicType="artist") 180 "station.createStation", trackToken="foo", musicType="artist"
181 )
166 182
167 def test_using_track_token(self): 183 def test_using_track_token(self):
168 client = APIClient(Mock(return_value={}), None, None, None, None) 184 client = APIClient(Mock(return_value={}), None, None, None, None)
169 client.create_station(track_token="foo") 185 client.create_station(track_token="foo")
170 client.transport.assert_called_with( 186 client.transport.assert_called_with(
171 "station.createStation", trackToken="foo", musicType="song") 187 "station.createStation", trackToken="foo", musicType="song"
188 )
172 189
173 def test_with_no_token(self): 190 def test_with_no_token(self):
174 with self.assertRaises(KeyError): 191 with self.assertRaises(KeyError):
@@ -177,25 +194,20 @@ class TestCreatingStation(TestCase):
177 194
178 195
179class TestCreatingGenreStation(TestCase): 196class TestCreatingGenreStation(TestCase):
180
181 def test_has_initial_checksum(self): 197 def test_has_initial_checksum(self):
182 fake_data = { 198 fake_data = {
183 "categories": [ 199 "categories": [{"categoryName": "foo", "stations": []},],
184 {"categoryName": "foo", "stations": []},
185 ],
186
187 # Not actually part of the genre station response but is needed to 200 # Not actually part of the genre station response but is needed to
188 # fake out the mock for get_genre_stations_checksum 201 # fake out the mock for get_genre_stations_checksum
189 "checksum": "foo" 202 "checksum": "foo",
190 } 203 }
191 with patch.object(APIClient, '__call__', return_value=fake_data): 204 with patch.object(APIClient, "__call__", return_value=fake_data):
192 client = APIClient(Mock(), None, None, None, None) 205 client = APIClient(Mock(), None, None, None, None)
193 station = client.get_genre_stations() 206 station = client.get_genre_stations()
194 self.assertEqual(station.checksum, "foo") 207 self.assertEqual(station.checksum, "foo")
195 208
196 209
197class TestAdditionalUrls(TestCase): 210class TestAdditionalUrls(TestCase):
198
199 def test_non_iterable_string(self): 211 def test_non_iterable_string(self):
200 with self.assertRaises(TypeError): 212 with self.assertRaises(TypeError):
201 transport = Mock(side_effect=[errors.InvalidAuthToken(), None]) 213 transport = Mock(side_effect=[errors.InvalidAuthToken(), None])
@@ -203,7 +215,7 @@ class TestAdditionalUrls(TestCase):
203 client = APIClient(transport, None, None, None, None) 215 client = APIClient(transport, None, None, None, None)
204 client._authenticate = Mock() 216 client._authenticate = Mock()
205 217
206 client.get_playlist('token_mock', additional_urls='') 218 client.get_playlist("token_mock", additional_urls="")
207 219
208 def test_non_iterable_other(self): 220 def test_non_iterable_other(self):
209 with self.assertRaises(TypeError): 221 with self.assertRaises(TypeError):
@@ -212,50 +224,64 @@ class TestAdditionalUrls(TestCase):
212 client = APIClient(transport, None, None, None, None) 224 client = APIClient(transport, None, None, None, None)
213 client._authenticate = Mock() 225 client._authenticate = Mock()
214 226
215 client.get_playlist('token_mock', 227 client.get_playlist(
216 additional_urls=AdditionalAudioUrl.HTTP_32_WMA) 228 "token_mock", additional_urls=AdditionalAudioUrl.HTTP_32_WMA
229 )
217 230
218 def test_without_enum(self): 231 def test_without_enum(self):
219 with patch.object(APIClient, '__call__') as playlist_mock: 232 with patch.object(APIClient, "__call__") as playlist_mock:
220 transport = Mock(side_effect=[errors.InvalidAuthToken(), None]) 233 transport = Mock(side_effect=[errors.InvalidAuthToken(), None])
221 234
222 client = APIClient(transport, None, None, None, None) 235 client = APIClient(transport, None, None, None, None)
223 client._authenticate = Mock() 236 client._authenticate = Mock()
224 237
225 urls = ['HTTP_128_MP3', 238 urls = ["HTTP_128_MP3", "HTTP_24_AACPLUS_ADTS"]
226 'HTTP_24_AACPLUS_ADTS']
227 239
228 desired = 'HTTP_128_MP3,HTTP_24_AACPLUS_ADTS' 240 desired = "HTTP_128_MP3,HTTP_24_AACPLUS_ADTS"
229 241
230 client.get_playlist('token_mock', additional_urls=urls) 242 client.get_playlist("token_mock", additional_urls=urls)
231 243
232 playlist_mock.assert_has_calls([call("station.getPlaylist", 244 playlist_mock.assert_has_calls(
233 additionalAudioUrl=desired, 245 [
234 audioAdPodCapable=True, 246 call(
235 includeTrackLength=True, 247 "station.getPlaylist",
236 stationToken='token_mock', 248 additionalAudioUrl=desired,
237 xplatformAdCapable=True)]) 249 audioAdPodCapable=True,
250 includeTrackLength=True,
251 stationToken="token_mock",
252 xplatformAdCapable=True,
253 )
254 ]
255 )
238 256
239 def test_with_enum(self): 257 def test_with_enum(self):
240 with patch.object(APIClient, '__call__') as playlist_mock: 258 with patch.object(APIClient, "__call__") as playlist_mock:
241 transport = Mock(side_effect=[errors.InvalidAuthToken(), None]) 259 transport = Mock(side_effect=[errors.InvalidAuthToken(), None])
242 260
243 client = APIClient(transport, None, None, None, None) 261 client = APIClient(transport, None, None, None, None)
244 client._authenticate = Mock() 262 client._authenticate = Mock()
245 263
246 urls = [AdditionalAudioUrl.HTTP_128_MP3, 264 urls = [
247 AdditionalAudioUrl.HTTP_24_AACPLUS_ADTS] 265 AdditionalAudioUrl.HTTP_128_MP3,
266 AdditionalAudioUrl.HTTP_24_AACPLUS_ADTS,
267 ]
248 268
249 desired = 'HTTP_128_MP3,HTTP_24_AACPLUS_ADTS' 269 desired = "HTTP_128_MP3,HTTP_24_AACPLUS_ADTS"
250 270
251 client.get_playlist('token_mock', additional_urls=urls) 271 client.get_playlist("token_mock", additional_urls=urls)
252 272
253 playlist_mock.assert_has_calls([call("station.getPlaylist", 273 playlist_mock.assert_has_calls(
254 additionalAudioUrl=desired, 274 [
255 audioAdPodCapable=True, 275 call(
256 includeTrackLength=True, 276 "station.getPlaylist",
257 stationToken='token_mock', 277 additionalAudioUrl=desired,
258 xplatformAdCapable=True)]) 278 audioAdPodCapable=True,
279 includeTrackLength=True,
280 stationToken="token_mock",
281 xplatformAdCapable=True,
282 )
283 ]
284 )
259 285
260 286
261# On the surface this test class seems dumb because it's mostly just exercising 287# On the surface this test class seems dumb because it's mostly just exercising
@@ -263,7 +289,6 @@ class TestAdditionalUrls(TestCase):
263# introduced to API client methods that will only be spotted at runtime (import 289# introduced to API client methods that will only be spotted at runtime (import
264# errors, etc...) 290# errors, etc...)
265class TestAPIClientExhaustive(TestCase): 291class TestAPIClientExhaustive(TestCase):
266
267 def setUp(self): 292 def setUp(self):
268 self.transport = Mock() 293 self.transport = Mock()
269 self.api = APIClient(self.transport, "puser", "ppass", "device") 294 self.api = APIClient(self.transport, "puser", "ppass", "device")
@@ -271,23 +296,29 @@ class TestAPIClientExhaustive(TestCase):
271 def test_register_ad(self): 296 def test_register_ad(self):
272 self.api.register_ad("sid", "tokens") 297 self.api.register_ad("sid", "tokens")
273 self.transport.assert_called_with( 298 self.transport.assert_called_with(
274 "ad.registerAd", stationId="sid", adTrackingTokens="tokens") 299 "ad.registerAd", stationId="sid", adTrackingTokens="tokens"
300 )
275 301
276 def test_share_music(self): 302 def test_share_music(self):
277 self.api.share_music("token", "foo@example.com") 303 self.api.share_music("token", "foo@example.com")
278 self.transport.assert_called_with( 304 self.transport.assert_called_with(
279 "music.shareMusic", musicToken="token", email="foo@example.com") 305 "music.shareMusic", musicToken="token", email="foo@example.com"
306 )
280 307
281 def test_transform_shared_station(self): 308 def test_transform_shared_station(self):
282 self.api.transform_shared_station("token") 309 self.api.transform_shared_station("token")
283 self.transport.assert_called_with( 310 self.transport.assert_called_with(
284 "station.transformSharedStation", stationToken="token") 311 "station.transformSharedStation", stationToken="token"
312 )
285 313
286 def test_share_station(self): 314 def test_share_station(self):
287 self.api.share_station("sid", "token", "foo@example.com") 315 self.api.share_station("sid", "token", "foo@example.com")
288 self.transport.assert_called_with( 316 self.transport.assert_called_with(
289 "station.shareStation", stationId="sid", stationToken="token", 317 "station.shareStation",
290 emails=("foo@example.com",)) 318 stationId="sid",
319 stationToken="token",
320 emails=("foo@example.com",),
321 )
291 322
292 def test_sleep_song(self): 323 def test_sleep_song(self):
293 self.api.sleep_song("token") 324 self.api.sleep_song("token")
@@ -296,22 +327,26 @@ class TestAPIClientExhaustive(TestCase):
296 def test_set_quick_mix(self): 327 def test_set_quick_mix(self):
297 self.api.set_quick_mix("id") 328 self.api.set_quick_mix("id")
298 self.transport.assert_called_with( 329 self.transport.assert_called_with(
299 "user.setQuickMix", quickMixStationIds=("id",)) 330 "user.setQuickMix", quickMixStationIds=("id",)
331 )
300 332
301 def test_explain_track(self): 333 def test_explain_track(self):
302 self.api.explain_track("token") 334 self.api.explain_track("token")
303 self.transport.assert_called_with( 335 self.transport.assert_called_with(
304 "track.explainTrack", trackToken="token") 336 "track.explainTrack", trackToken="token"
337 )
305 338
306 def test_rename_station(self): 339 def test_rename_station(self):
307 self.api.rename_station("token", "name") 340 self.api.rename_station("token", "name")
308 self.transport.assert_called_with( 341 self.transport.assert_called_with(
309 "station.renameStation", stationToken="token", stationName="name") 342 "station.renameStation", stationToken="token", stationName="name"
343 )
310 344
311 def test_delete_station(self): 345 def test_delete_station(self):
312 self.api.delete_station("token") 346 self.api.delete_station("token")
313 self.transport.assert_called_with( 347 self.transport.assert_called_with(
314 "station.deleteStation", stationToken="token") 348 "station.deleteStation", stationToken="token"
349 )
315 350
316 def test_delete_music(self): 351 def test_delete_music(self):
317 self.api.delete_music("seed") 352 self.api.delete_music("seed")
@@ -320,37 +355,44 @@ class TestAPIClientExhaustive(TestCase):
320 def test_delete_feedback(self): 355 def test_delete_feedback(self):
321 self.api.delete_feedback("id") 356 self.api.delete_feedback("id")
322 self.transport.assert_called_with( 357 self.transport.assert_called_with(
323 "station.deleteFeedback", feedbackId="id") 358 "station.deleteFeedback", feedbackId="id"
359 )
324 360
325 def test_add_music(self): 361 def test_add_music(self):
326 self.api.add_music("mt", "st") 362 self.api.add_music("mt", "st")
327 self.transport.assert_called_with( 363 self.transport.assert_called_with(
328 "station.addMusic", musicToken="mt", stationToken="st") 364 "station.addMusic", musicToken="mt", stationToken="st"
365 )
329 366
330 def test_add_feedback(self): 367 def test_add_feedback(self):
331 self.api.add_feedback("token", False) 368 self.api.add_feedback("token", False)
332 self.transport.assert_called_with( 369 self.transport.assert_called_with(
333 "station.addFeedback", trackToken="token", isPositive=False) 370 "station.addFeedback", trackToken="token", isPositive=False
371 )
334 372
335 def test_add_artist_bookmark(self): 373 def test_add_artist_bookmark(self):
336 self.api.add_artist_bookmark("tt") 374 self.api.add_artist_bookmark("tt")
337 self.transport.assert_called_with( 375 self.transport.assert_called_with(
338 "bookmark.addArtistBookmark", trackToken="tt") 376 "bookmark.addArtistBookmark", trackToken="tt"
377 )
339 378
340 def test_add_song_bookmark(self): 379 def test_add_song_bookmark(self):
341 self.api.add_song_bookmark("tt") 380 self.api.add_song_bookmark("tt")
342 self.transport.assert_called_with( 381 self.transport.assert_called_with(
343 "bookmark.addSongBookmark", trackToken="tt") 382 "bookmark.addSongBookmark", trackToken="tt"
383 )
344 384
345 def test_delete_song_bookmark(self): 385 def test_delete_song_bookmark(self):
346 self.api.delete_song_bookmark("bt") 386 self.api.delete_song_bookmark("bt")
347 self.transport.assert_called_with( 387 self.transport.assert_called_with(
348 "bookmark.deleteSongBookmark", bookmarkToken="bt") 388 "bookmark.deleteSongBookmark", bookmarkToken="bt"
389 )
349 390
350 def test_delete_artist_bookmark(self): 391 def test_delete_artist_bookmark(self):
351 self.api.delete_artist_bookmark("bt") 392 self.api.delete_artist_bookmark("bt")
352 self.transport.assert_called_with( 393 self.transport.assert_called_with(
353 "bookmark.deleteArtistBookmark", bookmarkToken="bt") 394 "bookmark.deleteArtistBookmark", bookmarkToken="bt"
395 )
354 396
355 def test_get_station_list_checksum(self): 397 def test_get_station_list_checksum(self):
356 self.transport.return_value = {"checksum": "foo"} 398 self.transport.return_value = {"checksum": "foo"}
@@ -364,7 +406,8 @@ class TestAPIClientExhaustive(TestCase):
364 self.transport.return_value = {"stations": []} 406 self.transport.return_value = {"stations": []}
365 self.assertIsInstance(self.api.get_station_list(), StationList) 407 self.assertIsInstance(self.api.get_station_list(), StationList)
366 self.transport.assert_called_with( 408 self.transport.assert_called_with(
367 "user.getStationList", includeStationArtUrl=True) 409 "user.getStationList", includeStationArtUrl=True
410 )
368 411
369 def test_get_bookmarks(self): 412 def test_get_bookmarks(self):
370 self.transport.return_value = {} 413 self.transport.return_value = {}
@@ -375,14 +418,22 @@ class TestAPIClientExhaustive(TestCase):
375 self.transport.return_value = {} 418 self.transport.return_value = {}
376 self.assertIsInstance(self.api.get_station("st"), Station) 419 self.assertIsInstance(self.api.get_station("st"), Station)
377 self.transport.assert_called_with( 420 self.transport.assert_called_with(
378 "station.getStation", stationToken="st", 421 "station.getStation",
379 includeExtendedAttributes=True) 422 stationToken="st",
423 includeExtendedAttributes=True,
424 )
380 425
381 def test_search(self): 426 def test_search(self):
382 self.transport.return_value = {} 427 self.transport.return_value = {}
383 self.assertIsInstance(self.api.search( 428 self.assertIsInstance(
384 "text", include_near_matches=True, include_genre_stations=True), 429 self.api.search(
385 SearchResult) 430 "text", include_near_matches=True, include_genre_stations=True
431 ),
432 SearchResult,
433 )
386 self.transport.assert_called_with( 434 self.transport.assert_called_with(
387 "music.search", searchText="text", includeNearMatches=True, 435 "music.search",
388 includeGenreStations=True) 436 searchText="text",
437 includeNearMatches=True,
438 includeGenreStations=True,
439 )
diff --git a/tests/test_pandora/test_clientbuilder.py b/tests/test_pandora/test_clientbuilder.py
index af0e219..17a4036 100644
--- a/tests/test_pandora/test_clientbuilder.py
+++ b/tests/test_pandora/test_clientbuilder.py
@@ -8,7 +8,6 @@ from pandora.transport import DEFAULT_API_HOST
8 8
9 9
10class TestTranslatingDict(TestCase): 10class TestTranslatingDict(TestCase):
11
12 class TestDict(cb.TranslatingDict): 11 class TestDict(cb.TranslatingDict):
13 12
14 KEY_TRANSLATIONS = {"FOO": "BAR"} 13 KEY_TRANSLATIONS = {"FOO": "BAR"}
@@ -62,29 +61,32 @@ class TestTranslatingDict(TestCase):
62 61
63 62
64class TestSettingsDictBuilder(TestCase): 63class TestSettingsDictBuilder(TestCase):
65
66 @classmethod 64 @classmethod
67 def _build_minimal(self): 65 def _build_minimal(self):
68 return cb.SettingsDictBuilder({ 66 return cb.SettingsDictBuilder(
69 "DECRYPTION_KEY": "blowfishkey", 67 {
70 "ENCRYPTION_KEY": "blowfishkey", 68 "DECRYPTION_KEY": "blowfishkey",
71 "PARTNER_USER": "user", 69 "ENCRYPTION_KEY": "blowfishkey",
72 "PARTNER_PASSWORD": "pass", 70 "PARTNER_USER": "user",
73 "DEVICE": "dev", 71 "PARTNER_PASSWORD": "pass",
74 }).build() 72 "DEVICE": "dev",
73 }
74 ).build()
75 75
76 @classmethod 76 @classmethod
77 def _build_maximal(self): 77 def _build_maximal(self):
78 return cb.SettingsDictBuilder({ 78 return cb.SettingsDictBuilder(
79 "DECRYPTION_KEY": "blowfishkey", 79 {
80 "ENCRYPTION_KEY": "blowfishkey", 80 "DECRYPTION_KEY": "blowfishkey",
81 "PARTNER_USER": "user", 81 "ENCRYPTION_KEY": "blowfishkey",
82 "PARTNER_PASSWORD": "pass", 82 "PARTNER_USER": "user",
83 "DEVICE": "dev", 83 "PARTNER_PASSWORD": "pass",
84 "PROXY": "proxy.example.com", 84 "DEVICE": "dev",
85 "AUDIO_QUALITY": "high", 85 "PROXY": "proxy.example.com",
86 "API_HOST": "example.com", 86 "AUDIO_QUALITY": "high",
87 }).build() 87 "API_HOST": "example.com",
88 }
89 ).build()
88 90
89 def test_building(self): 91 def test_building(self):
90 client = TestSettingsDictBuilder._build_minimal() 92 client = TestSettingsDictBuilder._build_minimal()
@@ -97,14 +99,15 @@ class TestSettingsDictBuilder(TestCase):
97 self.assertEqual({}, client.transport._http.proxies) 99 self.assertEqual({}, client.transport._http.proxies)
98 self.assertEqual(DEFAULT_API_HOST, client.transport.api_host) 100 self.assertEqual(DEFAULT_API_HOST, client.transport.api_host)
99 self.assertEqual( 101 self.assertEqual(
100 APIClient.MED_AUDIO_QUALITY, client.default_audio_quality) 102 APIClient.MED_AUDIO_QUALITY, client.default_audio_quality
103 )
101 104
102 def test_validate_client(self): 105 def test_validate_client(self):
103 client = TestSettingsDictBuilder._build_maximal() 106 client = TestSettingsDictBuilder._build_maximal()
104 expected_proxies = { 107 expected_proxies = {
105 "http": "proxy.example.com", 108 "http": "proxy.example.com",
106 "https": "proxy.example.com" 109 "https": "proxy.example.com",
107 } 110 }
108 111
109 self.assertIsNotNone(client.transport.cryptor.bf_in) 112 self.assertIsNotNone(client.transport.cryptor.bf_in)
110 self.assertIsNotNone(client.transport.cryptor.bf_out) 113 self.assertIsNotNone(client.transport.cryptor.bf_out)
@@ -119,7 +122,6 @@ class TestSettingsDictBuilder(TestCase):
119 122
120 123
121class TestFileBasedBuilder(TestCase): 124class TestFileBasedBuilder(TestCase):
122
123 class StubBuilder(cb.FileBasedClientBuilder): 125 class StubBuilder(cb.FileBasedClientBuilder):
124 126
125 DEFAULT_CONFIG_FILE = "foo" 127 DEFAULT_CONFIG_FILE = "foo"
@@ -170,7 +172,6 @@ class TestFileBasedBuilder(TestCase):
170 172
171 173
172class TestPydoraConfigFileBuilder(TestCase): 174class TestPydoraConfigFileBuilder(TestCase):
173
174 def test_cfg_to_dict(self): 175 def test_cfg_to_dict(self):
175 cfg = Mock() 176 cfg = Mock()
176 cfg.items = Mock(return_value=[("a", "b"), ("c", "d")]) 177 cfg.items = Mock(return_value=[("a", "b"), ("c", "d")])
@@ -184,38 +185,43 @@ class TestPydoraConfigFileBuilder(TestCase):
184 path = os.path.join(os.path.dirname(__file__), "pydora.cfg") 185 path = os.path.join(os.path.dirname(__file__), "pydora.cfg")
185 cfg = cb.PydoraConfigFileBuilder(path).parse_config() 186 cfg = cb.PydoraConfigFileBuilder(path).parse_config()
186 187
187 self.assertDictEqual(cfg, { 188 self.assertDictEqual(
188 "AUDIO_QUALITY": "test_quality", 189 cfg,
189 "DECRYPTION_KEY": "test_decryption_key", 190 {
190 "DEVICE": "test_device", 191 "AUDIO_QUALITY": "test_quality",
191 "ENCRYPTION_KEY": "test_encryption_key", 192 "DECRYPTION_KEY": "test_decryption_key",
192 "PARTNER_PASSWORD": "test_partner_password", 193 "DEVICE": "test_device",
193 "PARTNER_USER": "test_partner_username", 194 "ENCRYPTION_KEY": "test_encryption_key",
194 "API_HOST": "test_host", 195 "PARTNER_PASSWORD": "test_partner_password",
195 "USER": { 196 "PARTNER_USER": "test_partner_username",
196 "USERNAME": "test_username", 197 "API_HOST": "test_host",
197 "PASSWORD": "test_password", 198 "USER": {
198 } 199 "USERNAME": "test_username",
199 }) 200 "PASSWORD": "test_password",
201 },
202 },
203 )
200 204
201 205
202class TestPianobarConfigFileBuilder(TestCase): 206class TestPianobarConfigFileBuilder(TestCase):
203
204 def test_integration(self): 207 def test_integration(self):
205 path = os.path.join(os.path.dirname(__file__), "pianobar.cfg") 208 path = os.path.join(os.path.dirname(__file__), "pianobar.cfg")
206 cfg = cb.PianobarConfigFileBuilder(path).parse_config() 209 cfg = cb.PianobarConfigFileBuilder(path).parse_config()
207 210
208 self.assertDictEqual(cfg, { 211 self.assertDictEqual(
209 "AUDIO_QUALITY": "test_qualityQuality", 212 cfg,
210 "DECRYPTION_KEY": "test_decryption_key", 213 {
211 "DEVICE": "test_device", 214 "AUDIO_QUALITY": "test_qualityQuality",
212 "ENCRYPTION_KEY": "test_encryption_key", 215 "DECRYPTION_KEY": "test_decryption_key",
213 "PARTNER_PASSWORD": "test_partner_password", 216 "DEVICE": "test_device",
214 "PARTNER_USER": "test_partner_username", 217 "ENCRYPTION_KEY": "test_encryption_key",
215 "API_HOST": "test_host/services/json/", 218 "PARTNER_PASSWORD": "test_partner_password",
216 "PROXY": "test_proxy", 219 "PARTNER_USER": "test_partner_username",
217 "USER": { 220 "API_HOST": "test_host/services/json/",
218 "USERNAME": "test_username", 221 "PROXY": "test_proxy",
219 "PASSWORD": "test_password", 222 "USER": {
220 } 223 "USERNAME": "test_username",
221 }) 224 "PASSWORD": "test_password",
225 },
226 },
227 )
diff --git a/tests/test_pandora/test_errors.py b/tests/test_pandora/test_errors.py
index 778771a..d9df41f 100644
--- a/tests/test_pandora/test_errors.py
+++ b/tests/test_pandora/test_errors.py
@@ -4,7 +4,6 @@ from pandora.errors import InternalServerError, PandoraException
4 4
5 5
6class TestPandoraExceptionConstructionFromErrorCode(TestCase): 6class TestPandoraExceptionConstructionFromErrorCode(TestCase):
7
8 def test_it_returns_specific_error_class_if_possible(self): 7 def test_it_returns_specific_error_class_if_possible(self):
9 error = PandoraException.from_code(0, "Test Message") 8 error = PandoraException.from_code(0, "Test Message")
10 self.assertIsInstance(error, InternalServerError) 9 self.assertIsInstance(error, InternalServerError)
diff --git a/tests/test_pandora/test_models.py b/tests/test_pandora/test_models.py
index cb650df..16307b4 100644
--- a/tests/test_pandora/test_models.py
+++ b/tests/test_pandora/test_models.py
@@ -14,7 +14,6 @@ import pandora.models.playlist as plm
14 14
15 15
16class TestField(TestCase): 16class TestField(TestCase):
17
18 def test_defaults(self): 17 def test_defaults(self):
19 field = m.Field("name") 18 field = m.Field("name")
20 19
@@ -24,7 +23,6 @@ class TestField(TestCase):
24 23
25 24
26class TestModelMetaClass(TestCase): 25class TestModelMetaClass(TestCase):
27
28 class TestModel(metaclass=m.ModelMetaClass): 26 class TestModel(metaclass=m.ModelMetaClass):
29 27
30 foo = "bar" 28 foo = "bar"
@@ -40,7 +38,6 @@ class TestModelMetaClass(TestCase):
40 38
41 39
42class TestDateField(TestCase): 40class TestDateField(TestCase):
43
44 class SampleModel(m.PandoraModel): 41 class SampleModel(m.PandoraModel):
45 42
46 date_field = m.DateField("foo") 43 date_field = m.DateField("foo")
@@ -57,34 +54,26 @@ class TestDateField(TestCase):
57 54
58 55
59class TestAdditionalUrlField(TestCase): 56class TestAdditionalUrlField(TestCase):
60
61 def test_single_url(self): 57 def test_single_url(self):
62 dummy_data = { 58 dummy_data = {"_paramAdditionalUrls": ["foo"]}
63 '_paramAdditionalUrls': ['foo']
64 }
65 59
66 field = plm.AdditionalUrlField("additionalAudioUrl") 60 field = plm.AdditionalUrlField("additionalAudioUrl")
67 61
68 ret = field.formatter(None, dummy_data, 'test') 62 ret = field.formatter(None, dummy_data, "test")
69 63
70 self.assertEqual(ret, {'foo': 'test'}) 64 self.assertEqual(ret, {"foo": "test"})
71 65
72 def test_multiple_urls(self): 66 def test_multiple_urls(self):
73 dummy_data = { 67 dummy_data = {"_paramAdditionalUrls": ["abc", "def",]}
74 '_paramAdditionalUrls': [
75 'abc',
76 'def',
77 ]
78 }
79 68
80 field = plm.AdditionalUrlField("additionalAudioUrl") 69 field = plm.AdditionalUrlField("additionalAudioUrl")
81 70
82 ret = field.formatter(None, dummy_data, ['foo', 'bar']) 71 ret = field.formatter(None, dummy_data, ["foo", "bar"])
83 72
84 expected = { 73 expected = {
85 'abc': 'foo', 74 "abc": "foo",
86 'def': 'bar', 75 "def": "bar",
87 } 76 }
88 77
89 self.assertEqual(ret, expected) 78 self.assertEqual(ret, expected)
90 79
@@ -99,7 +88,6 @@ class TestPandoraModel(TestCase):
99 } 88 }
100 89
101 class TestModel(m.PandoraModel): 90 class TestModel(m.PandoraModel):
102
103 class SubModel(m.PandoraModel): 91 class SubModel(m.PandoraModel):
104 92
105 field1 = m.Field("field1") 93 field1 = m.Field("field1")
@@ -116,7 +104,6 @@ class TestPandoraModel(TestCase):
116 pass 104 pass
117 105
118 class ExtraReprModel(m.PandoraModel): 106 class ExtraReprModel(m.PandoraModel):
119
120 def __repr__(self): 107 def __repr__(self):
121 return self._base_repr("Foo") 108 return self._base_repr("Foo")
122 109
@@ -153,9 +140,11 @@ class TestPandoraModel(TestCase):
153 self.assertEqual("a string", result[1].field1) 140 self.assertEqual("a string", result[1].field1)
154 141
155 def test_repr(self): 142 def test_repr(self):
156 expected = ("TestModel(field1='a string', field2=['test2'], field3=42," 143 expected = (
157 " field4=SubModel(field1='foo'), " 144 "TestModel(field1='a string', field2=['test2'], field3=42,"
158 "field5=[SubModel(field1='foo'), SubModel(field1='bar')])") 145 " field4=SubModel(field1='foo'), "
146 "field5=[SubModel(field1='foo'), SubModel(field1='bar')])"
147 )
159 result = self.TestModel.from_json(None, self.JSON_DATA) 148 result = self.TestModel.from_json(None, self.JSON_DATA)
160 self.assertEqual(expected, repr(result)) 149 self.assertEqual(expected, repr(result))
161 150
@@ -179,12 +168,12 @@ class TestSubModel(m.PandoraModel):
179class TestPandoraListModel(TestCase): 168class TestPandoraListModel(TestCase):
180 169
181 JSON_DATA = { 170 JSON_DATA = {
182 "field1": 42, 171 "field1": 42,
183 "field2": [ 172 "field2": [
184 {"idx": "foo", "fieldS1": "Foo"}, 173 {"idx": "foo", "fieldS1": "Foo"},
185 {"idx": "bar", "fieldS1": "Bar"}, 174 {"idx": "bar", "fieldS1": "Bar"},
186 ] 175 ],
187 } 176 }
188 177
189 class TestModel(m.PandoraListModel): 178 class TestModel(m.PandoraListModel):
190 179
@@ -204,8 +193,10 @@ class TestPandoraListModel(TestCase):
204 self.assertEqual("Bar", self.result[1].fieldS1) 193 self.assertEqual("Bar", self.result[1].fieldS1)
205 194
206 def test_repr(self): 195 def test_repr(self):
207 expected = ("TestModel(field1=42, [TestSubModel(fieldS1='Foo', " 196 expected = (
208 "idx='foo'), TestSubModel(fieldS1='Bar', idx='bar')])") 197 "TestModel(field1=42, [TestSubModel(fieldS1='Foo', "
198 "idx='foo'), TestSubModel(fieldS1='Bar', idx='bar')])"
199 )
209 self.assertEqual(expected, repr(self.result)) 200 self.assertEqual(expected, repr(self.result))
210 201
211 def test_indexed_model(self): 202 def test_indexed_model(self):
@@ -232,17 +223,17 @@ class TestPandoraListModel(TestCase):
232class TestPandoraDictListModel(TestCase): 223class TestPandoraDictListModel(TestCase):
233 224
234 JSON_DATA = { 225 JSON_DATA = {
235 "field1": 42, 226 "field1": 42,
236 "fieldD1": [ 227 "fieldD1": [
237 { 228 {
238 "dictKey": "Foobear", 229 "dictKey": "Foobear",
239 "listKey": [ 230 "listKey": [
240 {"idx": "foo", "fieldS1": "Foo"}, 231 {"idx": "foo", "fieldS1": "Foo"},
241 {"idx": "bar", "fieldS1": "Bar"}, 232 {"idx": "bar", "fieldS1": "Bar"},
242 ] 233 ],
243 } 234 }
244 ] 235 ],
245 } 236 }
246 237
247 class TestModel(m.PandoraDictListModel): 238 class TestModel(m.PandoraDictListModel):
248 239
@@ -266,9 +257,11 @@ class TestPandoraDictListModel(TestCase):
266 self.assertEqual("bar", self.result["Foobear"][1].idx) 257 self.assertEqual("bar", self.result["Foobear"][1].idx)
267 258
268 def test_repr(self): 259 def test_repr(self):
269 expected = ("TestModel(field1=42, {'Foobear': " 260 expected = (
270 "[TestSubModel(fieldS1='Foo', idx='foo'), " 261 "TestModel(field1=42, {'Foobear': "
271 "TestSubModel(fieldS1='Bar', idx='bar')]})") 262 "[TestSubModel(fieldS1='Foo', idx='foo'), "
263 "TestSubModel(fieldS1='Bar', idx='bar')]})"
264 )
272 self.assertEqual(expected, repr(self.result)) 265 self.assertEqual(expected, repr(self.result))
273 266
274 267
@@ -320,7 +313,6 @@ class TestPlaylistItemModel(TestCase):
320 313
321 314
322class TestPlaylistModel(TestCase): 315class TestPlaylistModel(TestCase):
323
324 def setUp(self): 316 def setUp(self):
325 self.client = Mock() 317 self.client = Mock()
326 self.playlist = plm.PlaylistModel(self.client) 318 self.playlist = plm.PlaylistModel(self.client)
@@ -354,47 +346,47 @@ class TestPlaylistModel(TestCase):
354class TestAdItem(TestCase): 346class TestAdItem(TestCase):
355 347
356 JSON_DATA = { 348 JSON_DATA = {
357 'audioUrlMap': { 349 "audioUrlMap": {
358 'mediumQuality': { 350 "mediumQuality": {
359 'audioUrl': 'med_url_mock', 351 "audioUrl": "med_url_mock",
360 'bitrate': '64', 352 "bitrate": "64",
361 'protocol': 'http', 353 "protocol": "http",
362 'encoding': 'aacplus' 354 "encoding": "aacplus",
363 }, 355 },
364 'highQuality': { 356 "highQuality": {
365 'audioUrl': 'high_url_mock', 357 "audioUrl": "high_url_mock",
366 'bitrate': '64', 358 "bitrate": "64",
367 'protocol': 'http', 359 "protocol": "http",
368 'encoding': 'aacplus' 360 "encoding": "aacplus",
361 },
362 "lowQuality": {
363 "audioUrl": "low_url_mock",
364 "bitrate": "32",
365 "protocol": "http",
366 "encoding": "aacplus",
369 }, 367 },
370 'lowQuality': {
371 'audioUrl': 'low_url_mock',
372 'bitrate': '32',
373 'protocol': 'http',
374 'encoding': 'aacplus'
375 }
376 }, 368 },
377 'clickThroughUrl': 'click_url_mock', 369 "clickThroughUrl": "click_url_mock",
378 'imageUrl': 'img_url_mock', 370 "imageUrl": "img_url_mock",
379 'companyName': '', 371 "companyName": "",
380 'title': '', 372 "title": "",
381 'trackGain': '0.0', 373 "trackGain": "0.0",
382 'adTrackingTokens': ['token_1_mock', 'token_2_mock'] 374 "adTrackingTokens": ["token_1_mock", "token_2_mock"],
383 } 375 }
384 376
385 def setUp(self): 377 def setUp(self):
386 api_client_mock = Mock(spec=APIClient) 378 api_client_mock = Mock(spec=APIClient)
387 api_client_mock.default_audio_quality = APIClient.HIGH_AUDIO_QUALITY 379 api_client_mock.default_audio_quality = APIClient.HIGH_AUDIO_QUALITY
388 self.result = am.AdItem.from_json(api_client_mock, self.JSON_DATA) 380 self.result = am.AdItem.from_json(api_client_mock, self.JSON_DATA)
389 self.result.station_id = 'station_id_mock' 381 self.result.station_id = "station_id_mock"
390 self.result.ad_token = 'token_mock' 382 self.result.ad_token = "token_mock"
391 383
392 def test_is_ad_is_true(self): 384 def test_is_ad_is_true(self):
393 assert self.result.is_ad is True 385 assert self.result.is_ad is True
394 386
395 def test_register_ad(self): 387 def test_register_ad(self):
396 self.result._api_client.register_ad = Mock() 388 self.result._api_client.register_ad = Mock()
397 self.result.register_ad('id_mock') 389 self.result.register_ad("id_mock")
398 390
399 assert self.result._api_client.register_ad.called 391 assert self.result._api_client.register_ad.called
400 392
@@ -403,12 +395,12 @@ class TestAdItem(TestCase):
403 self.result.tracking_tokens = [] 395 self.result.tracking_tokens = []
404 self.result._api_client.register_ad = Mock(spec=am.AdItem) 396 self.result._api_client.register_ad = Mock(spec=am.AdItem)
405 397
406 self.result.register_ad('id_mock') 398 self.result.register_ad("id_mock")
407 399
408 assert self.result._api_client.register_ad.called 400 assert self.result._api_client.register_ad.called
409 401
410 def test_prepare_playback(self): 402 def test_prepare_playback(self):
411 with patch.object(plm.PlaylistModel, 'prepare_playback') as super_mock: 403 with patch.object(plm.PlaylistModel, "prepare_playback") as super_mock:
412 404
413 self.result.register_ad = Mock() 405 self.result.register_ad = Mock()
414 self.result.prepare_playback() 406 self.result.prepare_playback()
@@ -416,21 +408,26 @@ class TestAdItem(TestCase):
416 assert super_mock.called 408 assert super_mock.called
417 409
418 def test_prepare_playback_raises_paramater_missing(self): 410 def test_prepare_playback_raises_paramater_missing(self):
419 with patch.object(plm.PlaylistModel, 'prepare_playback') as super_mock: 411 with patch.object(plm.PlaylistModel, "prepare_playback") as super_mock:
420 412
421 self.result.register_ad = Mock(side_effect=ParameterMissing( 413 self.result.register_ad = Mock(
422 'No ad tracking tokens provided for registration.') 414 side_effect=ParameterMissing(
423 ) 415 "No ad tracking tokens provided for registration."
416 )
417 )
424 self.assertRaises(ParameterMissing, self.result.prepare_playback) 418 self.assertRaises(ParameterMissing, self.result.prepare_playback)
425 assert self.result.register_ad.called 419 assert self.result.register_ad.called
426 assert not super_mock.called 420 assert not super_mock.called
427 421
428 def test_prepare_playback_handles_paramater_missing_if_no_tokens(self): 422 def test_prepare_playback_handles_paramater_missing_if_no_tokens(self):
429 with patch.object(plm.PlaylistModel, 'prepare_playback') as super_mock: 423 with patch.object(plm.PlaylistModel, "prepare_playback") as super_mock:
430 424
431 self.result.tracking_tokens = [] 425 self.result.tracking_tokens = []
432 self.result.register_ad = Mock(side_effect=ParameterMissing( 426 self.result.register_ad = Mock(
433 'No ad tracking tokens provided for registration.')) 427 side_effect=ParameterMissing(
428 "No ad tracking tokens provided for registration."
429 )
430 )
434 self.result.prepare_playback() 431 self.result.prepare_playback()
435 assert self.result.register_ad.called 432 assert self.result.register_ad.called
436 assert super_mock.called 433 assert super_mock.called
@@ -449,43 +446,45 @@ class TestSearchResultItem(TestCase):
449 "artistName": "artist_name_mock", 446 "artistName": "artist_name_mock",
450 "musicToken": "S0000000", 447 "musicToken": "S0000000",
451 "songName": "song_name_mock", 448 "songName": "song_name_mock",
452 "score": 100 449 "score": 100,
453 } 450 }
454 451
455 ARTIST_JSON_DATA = { 452 ARTIST_JSON_DATA = {
456 "artistName": "artist_name_mock", 453 "artistName": "artist_name_mock",
457 "musicToken": "R0000000", 454 "musicToken": "R0000000",
458 "likelyMatch": False, 455 "likelyMatch": False,
459 "score": 100 456 "score": 100,
460 } 457 }
461 458
462 COMPOSER_JSON_DATA = { 459 COMPOSER_JSON_DATA = {
463 "artistName": "composer_name_mock", 460 "artistName": "composer_name_mock",
464 "musicToken": "C0000000", 461 "musicToken": "C0000000",
465 "likelyMatch": False, 462 "likelyMatch": False,
466 "score": 100 463 "score": 100,
467 } 464 }
468 465
469 GENRE_JSON_DATA = { 466 GENRE_JSON_DATA = {
470 "stationName": "station_name_mock", 467 "stationName": "station_name_mock",
471 "musicToken": "G0000000", 468 "musicToken": "G0000000",
472 "score": 100 469 "score": 100,
473 } 470 }
474 471
475 UNKNOWN_JSON_DATA = { 472 UNKNOWN_JSON_DATA = {
476 "stationName": "unknown_name_mock", 473 "stationName": "unknown_name_mock",
477 "musicToken": "U0000000", 474 "musicToken": "U0000000",
478 "score": 100 475 "score": 100,
479 } 476 }
480 477
481 def setUp(self): 478 def setUp(self):
482 self.api_client_mock = Mock(spec=APIClient) 479 self.api_client_mock = Mock(spec=APIClient)
483 self.api_client_mock.default_audio_quality = \ 480 self.api_client_mock.default_audio_quality = (
484 APIClient.HIGH_AUDIO_QUALITY 481 APIClient.HIGH_AUDIO_QUALITY
482 )
485 483
486 def test_is_song(self): 484 def test_is_song(self):
487 result = sm.SearchResultItem.from_json( 485 result = sm.SearchResultItem.from_json(
488 self.api_client_mock, self.SONG_JSON_DATA) 486 self.api_client_mock, self.SONG_JSON_DATA
487 )
489 assert result.is_song 488 assert result.is_song
490 assert not result.is_artist 489 assert not result.is_artist
491 assert not result.is_composer 490 assert not result.is_composer
@@ -493,7 +492,8 @@ class TestSearchResultItem(TestCase):
493 492
494 def test_is_artist(self): 493 def test_is_artist(self):
495 result = sm.SearchResultItem.from_json( 494 result = sm.SearchResultItem.from_json(
496 self.api_client_mock, self.ARTIST_JSON_DATA) 495 self.api_client_mock, self.ARTIST_JSON_DATA
496 )
497 assert not result.is_song 497 assert not result.is_song
498 assert result.is_artist 498 assert result.is_artist
499 assert not result.is_composer 499 assert not result.is_composer
@@ -501,7 +501,8 @@ class TestSearchResultItem(TestCase):
501 501
502 def test_is_composer(self): 502 def test_is_composer(self):
503 result = sm.SearchResultItem.from_json( 503 result = sm.SearchResultItem.from_json(
504 self.api_client_mock, self.COMPOSER_JSON_DATA) 504 self.api_client_mock, self.COMPOSER_JSON_DATA
505 )
505 assert not result.is_song 506 assert not result.is_song
506 assert not result.is_artist 507 assert not result.is_artist
507 assert result.is_composer 508 assert result.is_composer
@@ -509,7 +510,8 @@ class TestSearchResultItem(TestCase):
509 510
510 def test_is_genre_station(self): 511 def test_is_genre_station(self):
511 result = sm.SearchResultItem.from_json( 512 result = sm.SearchResultItem.from_json(
512 self.api_client_mock, self.GENRE_JSON_DATA) 513 self.api_client_mock, self.GENRE_JSON_DATA
514 )
513 assert not result.is_song 515 assert not result.is_song
514 assert not result.is_artist 516 assert not result.is_artist
515 assert not result.is_composer 517 assert not result.is_composer
@@ -518,7 +520,8 @@ class TestSearchResultItem(TestCase):
518 def test_fails_if_unknown(self): 520 def test_fails_if_unknown(self):
519 with self.assertRaises(NotImplementedError): 521 with self.assertRaises(NotImplementedError):
520 sm.SearchResultItem.from_json( 522 sm.SearchResultItem.from_json(
521 self.api_client_mock, self.UNKNOWN_JSON_DATA) 523 self.api_client_mock, self.UNKNOWN_JSON_DATA
524 )
522 525
523 def test_interface(self): 526 def test_interface(self):
524 result = sm.SearchResultItem(self.api_client_mock) 527 result = sm.SearchResultItem(self.api_client_mock)
@@ -533,44 +536,51 @@ class TestArtistSearchResultItem(TestCase):
533 "artistName": "artist_name_mock", 536 "artistName": "artist_name_mock",
534 "musicToken": "R0000000", 537 "musicToken": "R0000000",
535 "likelyMatch": False, 538 "likelyMatch": False,
536 "score": 100 539 "score": 100,
537 } 540 }
538 541
539 COMPOSER_JSON_DATA = { 542 COMPOSER_JSON_DATA = {
540 "artistName": "composer_name_mock", 543 "artistName": "composer_name_mock",
541 "musicToken": "C0000000", 544 "musicToken": "C0000000",
542 "likelyMatch": False, 545 "likelyMatch": False,
543 "score": 100 546 "score": 100,
544 } 547 }
545 548
546 def setUp(self): 549 def setUp(self):
547 self.api_client_mock = Mock(spec=APIClient) 550 self.api_client_mock = Mock(spec=APIClient)
548 self.api_client_mock.default_audio_quality = \ 551 self.api_client_mock.default_audio_quality = (
549 APIClient.HIGH_AUDIO_QUALITY 552 APIClient.HIGH_AUDIO_QUALITY
553 )
550 554
551 def test_repr(self): 555 def test_repr(self):
552 result = sm.SearchResultItem.from_json( 556 result = sm.SearchResultItem.from_json(
553 self.api_client_mock, self.ARTIST_JSON_DATA) 557 self.api_client_mock, self.ARTIST_JSON_DATA
558 )
554 expected = ( 559 expected = (
555 "ArtistSearchResultItem(artist='artist_name_mock', " 560 "ArtistSearchResultItem(artist='artist_name_mock', "
556 "likely_match=False, score=100, token='R0000000')") 561 "likely_match=False, score=100, token='R0000000')"
562 )
557 self.assertEqual(expected, repr(result)) 563 self.assertEqual(expected, repr(result))
558 564
559 result = sm.SearchResultItem.from_json( 565 result = sm.SearchResultItem.from_json(
560 self.api_client_mock, self.COMPOSER_JSON_DATA) 566 self.api_client_mock, self.COMPOSER_JSON_DATA
567 )
561 expected = ( 568 expected = (
562 "ArtistSearchResultItem(artist='composer_name_mock', " 569 "ArtistSearchResultItem(artist='composer_name_mock', "
563 "likely_match=False, score=100, token='C0000000')") 570 "likely_match=False, score=100, token='C0000000')"
571 )
564 self.assertEqual(expected, repr(result)) 572 self.assertEqual(expected, repr(result))
565 573
566 def test_create_station(self): 574 def test_create_station(self):
567 result = sm.SearchResultItem.from_json( 575 result = sm.SearchResultItem.from_json(
568 self.api_client_mock, self.ARTIST_JSON_DATA) 576 self.api_client_mock, self.ARTIST_JSON_DATA
577 )
569 result._api_client.create_station = Mock() 578 result._api_client.create_station = Mock()
570 579
571 result.create_station() 580 result.create_station()
572 result._api_client.create_station.assert_called_with( 581 result._api_client.create_station.assert_called_with(
573 artist_token=result.token) 582 artist_token=result.token
583 )
574 584
575 585
576class TestSongSearchResultItem(TestCase): 586class TestSongSearchResultItem(TestCase):
@@ -579,30 +589,35 @@ class TestSongSearchResultItem(TestCase):
579 "artistName": "artist_name_mock", 589 "artistName": "artist_name_mock",
580 "musicToken": "S0000000", 590 "musicToken": "S0000000",
581 "songName": "song_name_mock", 591 "songName": "song_name_mock",
582 "score": 100 592 "score": 100,
583 } 593 }
584 594
585 def setUp(self): 595 def setUp(self):
586 self.api_client_mock = Mock(spec=APIClient) 596 self.api_client_mock = Mock(spec=APIClient)
587 self.api_client_mock.default_audio_quality = \ 597 self.api_client_mock.default_audio_quality = (
588 APIClient.HIGH_AUDIO_QUALITY 598 APIClient.HIGH_AUDIO_QUALITY
599 )
589 600
590 def test_repr(self): 601 def test_repr(self):
591 result = sm.SearchResultItem.from_json( 602 result = sm.SearchResultItem.from_json(
592 self.api_client_mock, self.SONG_JSON_DATA) 603 self.api_client_mock, self.SONG_JSON_DATA
604 )
593 expected = ( 605 expected = (
594 "SongSearchResultItem(artist='artist_name_mock', score=100, " 606 "SongSearchResultItem(artist='artist_name_mock', score=100, "
595 "song_name='song_name_mock', token='S0000000')") 607 "song_name='song_name_mock', token='S0000000')"
608 )
596 self.assertEqual(expected, repr(result)) 609 self.assertEqual(expected, repr(result))
597 610
598 def test_create_station(self): 611 def test_create_station(self):
599 result = sm.SearchResultItem.from_json( 612 result = sm.SearchResultItem.from_json(
600 self.api_client_mock, self.SONG_JSON_DATA) 613 self.api_client_mock, self.SONG_JSON_DATA
614 )
601 result._api_client.create_station = Mock() 615 result._api_client.create_station = Mock()
602 616
603 result.create_station() 617 result.create_station()
604 result._api_client.create_station.assert_called_with( 618 result._api_client.create_station.assert_called_with(
605 track_token=result.token) 619 track_token=result.token
620 )
606 621
607 622
608class TestGenreStationSearchResultItem(TestCase): 623class TestGenreStationSearchResultItem(TestCase):
@@ -610,61 +625,69 @@ class TestGenreStationSearchResultItem(TestCase):
610 GENRE_JSON_DATA = { 625 GENRE_JSON_DATA = {
611 "stationName": "station_name_mock", 626 "stationName": "station_name_mock",
612 "musicToken": "G0000000", 627 "musicToken": "G0000000",
613 "score": 100 628 "score": 100,
614 } 629 }
615 630
616 def setUp(self): 631 def setUp(self):
617 self.api_client_mock = Mock(spec=APIClient) 632 self.api_client_mock = Mock(spec=APIClient)
618 self.api_client_mock.default_audio_quality = \ 633 self.api_client_mock.default_audio_quality = (
619 APIClient.HIGH_AUDIO_QUALITY 634 APIClient.HIGH_AUDIO_QUALITY
635 )
620 636
621 def test_repr(self): 637 def test_repr(self):
622 result = sm.SearchResultItem.from_json( 638 result = sm.SearchResultItem.from_json(
623 self.api_client_mock, self.GENRE_JSON_DATA) 639 self.api_client_mock, self.GENRE_JSON_DATA
640 )
624 expected = ( 641 expected = (
625 "GenreStationSearchResultItem(score=100, " 642 "GenreStationSearchResultItem(score=100, "
626 "station_name='station_name_mock', token='G0000000')") 643 "station_name='station_name_mock', token='G0000000')"
644 )
627 self.assertEqual(expected, repr(result)) 645 self.assertEqual(expected, repr(result))
628 646
629 def test_create_station(self): 647 def test_create_station(self):
630 result = sm.SearchResultItem.from_json( 648 result = sm.SearchResultItem.from_json(
631 self.api_client_mock, self.GENRE_JSON_DATA) 649 self.api_client_mock, self.GENRE_JSON_DATA
650 )
632 result._api_client.create_station = Mock() 651 result._api_client.create_station = Mock()
633 652
634 result.create_station() 653 result.create_station()
635 result._api_client.create_station.assert_called_with( 654 result._api_client.create_station.assert_called_with(
636 search_token=result.token) 655 search_token=result.token
656 )
637 657
638 658
639class TestSearchResult(TestCase): 659class TestSearchResult(TestCase):
640 660
641 JSON_DATA = { 661 JSON_DATA = {
642 'nearMatchesAvailable': True, 662 "nearMatchesAvailable": True,
643 'explanation': '', 663 "explanation": "",
644 'songs': [{ 664 "songs": [
645 'artistName': 'song_artist_mock', 665 {
646 'musicToken': 'S0000000', 666 "artistName": "song_artist_mock",
647 'songName': 'song_name_mock', 667 "musicToken": "S0000000",
648 'score': 100 668 "songName": "song_name_mock",
649 }], 669 "score": 100,
650 'artists': [{ 670 }
651 'artistName': 'artist_mock', 671 ],
652 'musicToken': 'R000000', 672 "artists": [
653 'likelyMatch': False, 673 {
654 'score': 80 674 "artistName": "artist_mock",
655 }], 675 "musicToken": "R000000",
656 'genreStations': [{ 676 "likelyMatch": False,
657 'musicToken': 'G0000', 677 "score": 80,
658 'stationName': 'station_mock', 678 }
659 'score': 50 679 ],
660 }] 680 "genreStations": [
681 {"musicToken": "G0000", "stationName": "station_mock", "score": 50}
682 ],
661 } 683 }
662 684
663 def setUp(self): 685 def setUp(self):
664 api_client_mock = Mock(spec=APIClient) 686 api_client_mock = Mock(spec=APIClient)
665 api_client_mock.default_audio_quality = APIClient.HIGH_AUDIO_QUALITY 687 api_client_mock.default_audio_quality = APIClient.HIGH_AUDIO_QUALITY
666 self.result = sm.SearchResult.from_json( 688 self.result = sm.SearchResult.from_json(
667 api_client_mock, self.JSON_DATA) 689 api_client_mock, self.JSON_DATA
690 )
668 691
669 def test_repr(self): 692 def test_repr(self):
670 expected = ( 693 expected = (
@@ -676,7 +699,8 @@ class TestSearchResult(TestCase):
676 "nearest_matches_available=True, " 699 "nearest_matches_available=True, "
677 "songs=[SongSearchResultItem(artist='song_artist_mock', " 700 "songs=[SongSearchResultItem(artist='song_artist_mock', "
678 "score=100, song_name='song_name_mock', " 701 "score=100, song_name='song_name_mock', "
679 "token='S0000000')])") 702 "token='S0000000')])"
703 )
680 self.assertEqual(expected, repr(self.result)) 704 self.assertEqual(expected, repr(self.result))
681 705
682 706
@@ -684,9 +708,7 @@ class TestGenreStationList(TestCase):
684 708
685 TEST_DATA = { 709 TEST_DATA = {
686 "checksum": "bar", 710 "checksum": "bar",
687 "categories": [ 711 "categories": [{"categoryName": "foo", "stations": []},],
688 {"categoryName": "foo", "stations": []},
689 ]
690 } 712 }
691 713
692 def test_has_changed(self): 714 def test_has_changed(self):
@@ -706,7 +728,8 @@ class TestGenreStation(TestCase):
706 genre_station = stm.GenreStation.from_json(api_client, self.TEST_DATA) 728 genre_station = stm.GenreStation.from_json(api_client, self.TEST_DATA)
707 729
708 with self.assertRaisesRegex( 730 with self.assertRaisesRegex(
709 NotImplementedError, "Genre stations do not have playlists.*"): 731 NotImplementedError, "Genre stations do not have playlists.*"
732 ):
710 genre_station.get_playlist() 733 genre_station.get_playlist()
711 734
712 735
@@ -750,7 +773,6 @@ class TestBookmark(TestCase):
750 773
751 774
752class TestPandoraType(TestCase): 775class TestPandoraType(TestCase):
753
754 def test_it_can_be_built_from_a_model(self): 776 def test_it_can_be_built_from_a_model(self):
755 pt = plm.PandoraType.from_model(None, "TR") 777 pt = plm.PandoraType.from_model(None, "TR")
756 self.assertIs(plm.PandoraType.TRACK, pt) 778 self.assertIs(plm.PandoraType.TRACK, pt)
@@ -765,7 +787,6 @@ class TestPandoraType(TestCase):
765 787
766 788
767class TestSyntheticField(TestCase): 789class TestSyntheticField(TestCase):
768
769 def test_interface(self): 790 def test_interface(self):
770 sf = m.SyntheticField(field="foo") 791 sf = m.SyntheticField(field="foo")
771 792
diff --git a/tests/test_pandora/test_transport.py b/tests/test_pandora/test_transport.py
index 851fa06..28ca6b2 100644
--- a/tests/test_pandora/test_transport.py
+++ b/tests/test_pandora/test_transport.py
@@ -16,12 +16,12 @@ class SysCallError(Exception):
16 16
17 17
18class TestTransport(TestCase): 18class TestTransport(TestCase):
19
20 def test_test_url_should_return_true_if_request_okay(self): 19 def test_test_url_should_return_true_if_request_okay(self):
21 transport = t.APITransport(Mock()) 20 transport = t.APITransport(Mock())
22 transport._http = Mock() 21 transport._http = Mock()
23 transport._http.head.return_value = Mock( 22 transport._http.head.return_value = Mock(
24 status_code=requests.codes.not_found) 23 status_code=requests.codes.not_found
24 )
25 25
26 self.assertFalse(transport.test_url("foo")) 26 self.assertFalse(transport.test_url("foo"))
27 27
@@ -34,7 +34,8 @@ class TestTransport(TestCase):
34 34
35 time.sleep = Mock() 35 time.sleep = Mock()
36 client.transport._make_http_request = Mock( 36 client.transport._make_http_request = Mock(
37 side_effect=SysCallError("error_mock")) 37 side_effect=SysCallError("error_mock")
38 )
38 client.transport._start_request = Mock() 39 client.transport._start_request = Mock()
39 40
40 client("method") 41 client("method")
@@ -48,7 +49,8 @@ class TestTransport(TestCase):
48 49
49 time.sleep = Mock() 50 time.sleep = Mock()
50 client.transport._make_http_request = Mock( 51 client.transport._make_http_request = Mock(
51 side_effect=PandoraException("error_mock")) 52 side_effect=PandoraException("error_mock")
53 )
52 client.transport._start_request = Mock() 54 client.transport._start_request = Mock()
53 55
54 client("method") 56 client("method")
@@ -62,7 +64,8 @@ class TestTransport(TestCase):
62 64
63 time.sleep = Mock() 65 time.sleep = Mock()
64 client.transport._make_http_request = Mock( 66 client.transport._make_http_request = Mock(
65 side_effect=InvalidAuthToken("error_mock")) 67 side_effect=InvalidAuthToken("error_mock")
68 )
66 client.transport._start_request = Mock() 69 client.transport._start_request = Mock()
67 70
68 client._authenticate = Mock() 71 client._authenticate = Mock()
@@ -82,11 +85,11 @@ class TestTransport(TestCase):
82 transport._http.post.return_value = http_result 85 transport._http.post.return_value = http_result
83 86
84 self.assertEqual( 87 self.assertEqual(
85 "bar", transport(t.APITransport.NO_ENCRYPT[0], foo="bar")) 88 "bar", transport(t.APITransport.NO_ENCRYPT[0], foo="bar")
89 )
86 90
87 91
88class TestTransportSetters(TestCase): 92class TestTransportSetters(TestCase):
89
90 def setUp(self): 93 def setUp(self):
91 self.cryptor = Mock() 94 self.cryptor = Mock()
92 self.transport = t.APITransport(self.cryptor) 95 self.transport = t.APITransport(self.cryptor)
@@ -94,27 +97,29 @@ class TestTransportSetters(TestCase):
94 def test_set_partner(self): 97 def test_set_partner(self):
95 self.cryptor.decrypt_sync_time.return_value = 456 98 self.cryptor.decrypt_sync_time.return_value = 456
96 99
97 self.transport.set_partner({ 100 self.transport.set_partner(
98 "syncTime": "123", 101 {
99 "partnerAuthToken": "partner_auth_token", 102 "syncTime": "123",
100 "partnerId": "partner_id", 103 "partnerAuthToken": "partner_auth_token",
101 }) 104 "partnerId": "partner_id",
105 }
106 )
102 107
103 self.cryptor.decrypt_sync_time.assert_called_with("123") 108 self.cryptor.decrypt_sync_time.assert_called_with("123")
104 self.assertEqual("partner_auth_token", self.transport.auth_token) 109 self.assertEqual("partner_auth_token", self.transport.auth_token)
105 self.assertEqual("partner_id", self.transport.partner_id) 110 self.assertEqual("partner_id", self.transport.partner_id)
106 self.assertEqual( 111 self.assertEqual(
107 "partner_auth_token", self.transport.partner_auth_token) 112 "partner_auth_token", self.transport.partner_auth_token
113 )
108 114
109 self.transport.start_time = 10 115 self.transport.start_time = 10
110 with patch.object(time, "time", return_value=30): 116 with patch.object(time, "time", return_value=30):
111 self.assertEqual(476, self.transport.sync_time) 117 self.assertEqual(476, self.transport.sync_time)
112 118
113 def test_set_user(self): 119 def test_set_user(self):
114 self.transport.set_user({ 120 self.transport.set_user(
115 "userId": "user", 121 {"userId": "user", "userAuthToken": "auth",}
116 "userAuthToken": "auth", 122 )
117 })
118 123
119 self.assertEqual("user", self.transport.user_id) 124 self.assertEqual("user", self.transport.user_id)
120 self.assertEqual("auth", self.transport.user_auth_token) 125 self.assertEqual("auth", self.transport.user_auth_token)
@@ -126,7 +131,6 @@ class TestTransportSetters(TestCase):
126 131
127 132
128class TestDelayExponential(TestCase): 133class TestDelayExponential(TestCase):
129
130 def test_fixed_delay(self): 134 def test_fixed_delay(self):
131 self.assertEqual(8, t.delay_exponential(2, 2, 3)) 135 self.assertEqual(8, t.delay_exponential(2, 2, 3))
132 136
@@ -143,7 +147,6 @@ class TestDelayExponential(TestCase):
143 147
144 148
145class TestRetries(TestCase): 149class TestRetries(TestCase):
146
147 def test_no_retries_returns_none(self): 150 def test_no_retries_returns_none(self):
148 @t.retries(0) 151 @t.retries(0)
149 def foo(): 152 def foo():
@@ -178,7 +181,6 @@ class TestParseResponse(TestCase):
178 181
179 182
180class TestTransportRequestPrep(TestCase): 183class TestTransportRequestPrep(TestCase):
181
182 def setUp(self): 184 def setUp(self):
183 self.cryptor = Mock() 185 self.cryptor = Mock()
184 self.transport = t.APITransport(self.cryptor) 186 self.transport = t.APITransport(self.cryptor)
@@ -207,7 +209,8 @@ class TestTransportRequestPrep(TestCase):
207 209
208 self.transport._http = http 210 self.transport._http = http
209 res = self.transport._make_http_request( 211 res = self.transport._make_http_request(
210 "/url", b"data", {"a": None, "b": "c"}) 212 "/url", b"data", {"a": None, "b": "c"}
213 )
211 214
212 http.post.assert_called_with("/url", data=b"data", params={"b": "c"}) 215 http.post.assert_called_with("/url", data=b"data", params={"b": "c"})
213 retval.raise_for_status.assert_called_with() 216 retval.raise_for_status.assert_called_with()
@@ -237,7 +240,8 @@ class TestTransportRequestPrep(TestCase):
237 240
238 with patch.object(time, "time", return_value=20): 241 with patch.object(time, "time", return_value=20):
239 val = self.transport._build_data( 242 val = self.transport._build_data(
240 t.APITransport.NO_ENCRYPT[0], {"a": "b", "c": None}) 243 t.APITransport.NO_ENCRYPT[0], {"a": "b", "c": None}
244 )
241 245
242 val = json.loads(val) 246 val = json.loads(val)
243 self.assertEqual("b", val["a"]) 247 self.assertEqual("b", val["a"])
@@ -247,7 +251,6 @@ class TestTransportRequestPrep(TestCase):
247 251
248# All Cryptor implementations must pass these test cases unmodified 252# All Cryptor implementations must pass these test cases unmodified
249class CommonCryptorTestCases: 253class CommonCryptorTestCases:
250
251 def test_decrypt_invalid_padding(self): 254 def test_decrypt_invalid_padding(self):
252 with self.assertRaises(ValueError): 255 with self.assertRaises(ValueError):
253 data = b"12345678\x00" 256 data = b"12345678\x00"
@@ -267,7 +270,6 @@ class CommonCryptorTestCases:
267 270
268 271
269class TestPurePythonBlowfishCryptor(TestCase, CommonCryptorTestCases): 272class TestPurePythonBlowfishCryptor(TestCase, CommonCryptorTestCases):
270
271 def setUp(self): 273 def setUp(self):
272 # Ugh... blowfish can't even be *imported* in python2 274 # Ugh... blowfish can't even be *imported* in python2
273 if not t.blowfish: 275 if not t.blowfish:
@@ -288,7 +290,6 @@ class TestEncryptor(TestCase):
288 ENCODED_TIME = "31353037343131313539" 290 ENCODED_TIME = "31353037343131313539"
289 291
290 class NoopCrypto: 292 class NoopCrypto:
291
292 def __init__(self, key): 293 def __init__(self, key):
293 pass 294 pass
294 295
@@ -303,14 +304,17 @@ class TestEncryptor(TestCase):
303 304
304 def test_decrypt(self): 305 def test_decrypt(self):
305 self.assertEqual( 306 self.assertEqual(
306 {"foo": "bar"}, self.cryptor.decrypt(self.ENCODED_JSON)) 307 {"foo": "bar"}, self.cryptor.decrypt(self.ENCODED_JSON)
308 )
307 309
308 def test_encrypt(self): 310 def test_encrypt(self):
309 self.assertEqual( 311 self.assertEqual(
310 self.ENCODED_JSON.encode("ascii"), 312 self.ENCODED_JSON.encode("ascii"),
311 self.cryptor.encrypt(self.UNENCODED_JSON)) 313 self.cryptor.encrypt(self.UNENCODED_JSON),
314 )
312 315
313 def test_decrypt_sync_time(self): 316 def test_decrypt_sync_time(self):
314 self.assertEqual( 317 self.assertEqual(
315 self.EXPECTED_TIME, 318 self.EXPECTED_TIME,
316 self.cryptor.decrypt_sync_time(self.ENCODED_TIME)) 319 self.cryptor.decrypt_sync_time(self.ENCODED_TIME),
320 )