spotifywebapiPython 1.0.27__py3-none-any.whl → 1.0.28__py3-none-any.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.

Potentially problematic release.


This version of spotifywebapiPython might be problematic. Click here for more details.

Files changed (24) hide show
  1. {spotifywebapiPython-1.0.27.dist-info → spotifywebapiPython-1.0.28.dist-info}/METADATA +1 -1
  2. {spotifywebapiPython-1.0.27.dist-info → spotifywebapiPython-1.0.28.dist-info}/RECORD +24 -24
  3. spotifywebapipython/const.py +26 -2
  4. spotifywebapipython/docs/__init__.html +20 -2
  5. spotifywebapipython/docs/index.html +2 -2
  6. spotifywebapipython/docs/search.js +1 -1
  7. spotifywebapipython/docs/spotifywebapiPython/const.html +75 -3
  8. spotifywebapipython/docs/spotifywebapiPython/saappmessages.html +4 -4
  9. spotifywebapipython/docs/spotifywebapiPython/sautils.html +2 -2
  10. spotifywebapipython/docs/spotifywebapiPython/spotifyapierror.html +2 -2
  11. spotifywebapipython/docs/spotifywebapiPython/spotifyapimessage.html +2 -2
  12. spotifywebapipython/docs/spotifywebapiPython/spotifyauthtoken.html +2 -2
  13. spotifywebapipython/docs/spotifywebapiPython/spotifyclient.html +2105 -326
  14. spotifywebapipython/docs/spotifywebapiPython/spotifydiscovery.html +2 -2
  15. spotifywebapipython/docs/spotifywebapiPython/spotifywebapiauthenticationerror.html +2 -2
  16. spotifywebapipython/docs/spotifywebapiPython/spotifywebapierror.html +2 -2
  17. spotifywebapipython/models/category.py +11 -0
  18. spotifywebapipython/models/pageobject.py +77 -4
  19. spotifywebapipython/models/searchresponse.py +86 -50
  20. spotifywebapipython/saappmessages.py +3 -3
  21. spotifywebapipython/spotifyclient.py +2918 -335
  22. {spotifywebapiPython-1.0.27.dist-info → spotifywebapiPython-1.0.28.dist-info}/LICENSE +0 -0
  23. {spotifywebapiPython-1.0.27.dist-info → spotifywebapiPython-1.0.28.dist-info}/WHEEL +0 -0
  24. {spotifywebapiPython-1.0.27.dist-info → spotifywebapiPython-1.0.28.dist-info}/top_level.txt +0 -0
@@ -3,7 +3,6 @@ import base64
3
3
  import json
4
4
  from io import BytesIO
5
5
  from oauthlib.oauth2 import BackendApplicationClient, WebApplicationClient
6
- #from requests import Response
7
6
  from typing import Tuple, Callable
8
7
  from urllib3 import PoolManager, Timeout, HTTPResponse
9
8
  from urllib.parse import urlencode
@@ -22,12 +21,16 @@ from .spotifywebapierror import SpotifyWebApiError
22
21
  from .const import (
23
22
  SPOTIFY_API_AUTHORIZE_URL,
24
23
  SPOTIFY_API_TOKEN_URL,
24
+ SPOTIFY_DEFAULT_MARKET,
25
25
  SPOTIFY_WEBAPI_URL_BASE,
26
26
  TRACE_METHOD_RESULT,
27
27
  TRACE_METHOD_RESULT_TYPE,
28
28
  TRACE_METHOD_RESULT_TYPE_CACHED,
29
+ TRACE_METHOD_RESULT_TYPE_PAGE,
29
30
  TRACE_MSG_AUTHTOKEN_CREATE,
31
+ TRACE_MSG_AUTOPAGING_NEXT,
30
32
  TRACE_MSG_USERPROFILE,
33
+ TRACE_WARN_SPOTIFY_SEARCH_NO_MARKET,
31
34
  )
32
35
 
33
36
  CACHE_SOURCE_CACHED:str = "cached"
@@ -231,6 +234,51 @@ class SpotifyClient:
231
234
  return self._UserProfile
232
235
 
233
236
 
237
+ def _CheckForNextPage(self,
238
+ pageObj:PageObject,
239
+ resultItemsCount,
240
+ limit:int,
241
+ limitTotal:int,
242
+ urlParms:dict,
243
+ ) -> bool:
244
+ """
245
+ Modifies paging object and urlParms to point to the next page of data, if one
246
+ can be accessed.
247
+
248
+ Returns:
249
+ False if there are no more pages to process;
250
+ otherwise, True to safely process the next page of results.
251
+ """
252
+ # anymore page results?
253
+ if (pageObj.Next is None) or (resultItemsCount >= limitTotal) or (pageObj.Offset >= limitTotal):
254
+ # no - all pages were processed, or limit total reached.
255
+ return False
256
+ else:
257
+ # yes - prepare to retrieve the next page of results.
258
+ # if next page potential item count exceeds limit total, then limit to the difference.
259
+ pageObj.Offset = pageObj.Offset + pageObj.Limit
260
+ if (pageObj.Offset + pageObj.Limit) > limitTotal:
261
+ pageObj.Limit = limitTotal - pageObj.Offset
262
+
263
+ # the following can occur if the Spotify Web API does not return any items but has
264
+ # the 'next' value set to point to the next page of data. I noticed this happens
265
+ # when the API cannot resolve a market (or country code) value (e.g. the UserProfile
266
+ # Country property is not set and no market argument was supplied). Regardless, we
267
+ # will check for it here in case.
268
+ if pageObj.Limit <= 0:
269
+ pageObj.Limit = limit
270
+
271
+ # modify paging-related request parameters for next page of items.
272
+ urlParms['limit'] = pageObj.Limit
273
+ urlParms['offset'] = pageObj.Offset
274
+
275
+ # trace.
276
+ _logsi.LogVerbose(TRACE_MSG_AUTOPAGING_NEXT % pageObj.PagingInfo)
277
+
278
+ # indicate next page can be processed.
279
+ return True
280
+
281
+
234
282
  def _CheckResponseForErrors(self, msg:SpotifyApiMessage, response:HTTPResponse) -> None:
235
283
  """
236
284
  Checks the Spotify Web API response for errors.
@@ -397,6 +445,35 @@ class SpotifyClient:
397
445
  msg.ResponseData = responseData
398
446
 
399
447
 
448
+ def _ValidateMarket(self,
449
+ market:str,
450
+ ) -> str:
451
+ """
452
+ Validates that a market (aka country code) value has either been supplied, or exists
453
+ in the UserProfile.Country value and returns a value of 'US' if not supplied; otherwise,
454
+ the market aregument value is returned.
455
+
456
+ If a market argument was not specified and the user profile does not have a country code
457
+ set, then it causes the Spotify Web API search to return odd results. For example, the
458
+ items collection will return no items, but the `total` and `next` values are populated
459
+ like there are more results. It's almost like it found the results, but it won't return
460
+ the actual items due to market / country restrictions or something.
461
+ """
462
+ # if user profile contains a country value then spotify web api will use it if no
463
+ # market argument was supplied.
464
+ if (self.UserProfile.Country is not None):
465
+ return market
466
+
467
+ # if a non-null and non-empty string was supplied then assume it's a valid market.
468
+ # we will let the Spotify Web API tell us if it's not a valid code.
469
+ if (market is not None and len(market.strip()) > 0):
470
+ return market
471
+
472
+ # otherwise, defult the value.
473
+ _logsi.LogVerbose("A market value was not supplied for the request, and the user profile did not contain a country code value (e.g. public access token is in effect). Defaulting value to '%s'." % SPOTIFY_DEFAULT_MARKET)
474
+ return SPOTIFY_DEFAULT_MARKET
475
+
476
+
400
477
  def MakeRequest(self, method:str, msg:SpotifyApiMessage) -> int:
401
478
  """
402
479
  Performs a generic Spotify Web API request.
@@ -2117,6 +2194,9 @@ class SpotifyClient:
2117
2194
  apiMethodParms.AppendKeyValue("market", market)
2118
2195
  _logsi.LogMethodParmList(SILevel.Verbose, "Get Spotify catalog information for a single album", apiMethodParms)
2119
2196
 
2197
+ # ensure market was either supplied or implied; default if neither.
2198
+ market = self._ValidateMarket(market)
2199
+
2120
2200
  # build spotify web api request parameters.
2121
2201
  urlParms:dict = {}
2122
2202
  if market is not None:
@@ -2152,6 +2232,7 @@ class SpotifyClient:
2152
2232
  limit:int=20,
2153
2233
  offset:int=0,
2154
2234
  market:str=None,
2235
+ limitTotal:int=None
2155
2236
  ) -> AlbumPageSaved:
2156
2237
  """
2157
2238
  Get a list of the albums saved in the current Spotify user's 'Your Library'.
@@ -2160,10 +2241,10 @@ class SpotifyClient:
2160
2241
 
2161
2242
  Args:
2162
2243
  limit (int):
2163
- The maximum number of items to return.
2244
+ The maximum number of items to return in a page of items.
2164
2245
  Default: 20, Range: 1 to 50.
2165
2246
  offset (int):
2166
- The index of the first item to return.
2247
+ The page index offset of the first item to return.
2167
2248
  Use with limit to get the next set of items.
2168
2249
  Default: 0 (the first item).
2169
2250
  market (str):
@@ -2174,6 +2255,12 @@ class SpotifyClient:
2174
2255
  Note: If neither market or user country are provided, the content is considered unavailable for the client.
2175
2256
  Users can view the country that is associated with their account in the account settings.
2176
2257
  Example: `ES`
2258
+ limitTotal (int):
2259
+ The maximum number of items to return for the request.
2260
+ If specified, this argument overrides the limit and offset argument values
2261
+ and paging is automatically used to retrieve all available items up to the
2262
+ maximum number specified.
2263
+ Default: None (disabled)
2177
2264
 
2178
2265
  Returns:
2179
2266
  An `AlbumPageSaved` object that contains saved album information.
@@ -2186,11 +2273,17 @@ class SpotifyClient:
2186
2273
  If the method fails for any other reason.
2187
2274
 
2188
2275
  <details>
2189
- <summary>Sample Code</summary>
2276
+ <summary>Sample Code - Manual Paging</summary>
2190
2277
  ```python
2191
2278
  .. include:: ../docs/include/samplecode/SpotifyClient/GetAlbumFavorites.py
2192
2279
  ```
2193
2280
  </details>
2281
+ <details>
2282
+ <summary>Sample Code - Auto Paging</summary>
2283
+ ```python
2284
+ .. include:: ../docs/include/samplecode/SpotifyClient/GetAlbumFavorites_AutoPaging.py
2285
+ ```
2286
+ </details>
2194
2287
  """
2195
2288
  apiMethodName:str = 'GetAlbumFavorites'
2196
2289
  apiMethodParms:SIMethodParmListContext = None
@@ -2202,6 +2295,8 @@ class SpotifyClient:
2202
2295
  apiMethodParms = _logsi.EnterMethodParmList(SILevel.Debug, apiMethodName)
2203
2296
  apiMethodParms.AppendKeyValue("limit", limit)
2204
2297
  apiMethodParms.AppendKeyValue("offset", offset)
2298
+ apiMethodParms.AppendKeyValue("market", market)
2299
+ apiMethodParms.AppendKeyValue("limitTotal", limitTotal)
2205
2300
  _logsi.LogMethodParmList(SILevel.Verbose, "Get a list of the user's album favorites", apiMethodParms)
2206
2301
 
2207
2302
  # validations.
@@ -2209,6 +2304,19 @@ class SpotifyClient:
2209
2304
  limit = 20
2210
2305
  if offset is None:
2211
2306
  offset = 0
2307
+ if not isinstance(limitTotal, int):
2308
+ limitTotal = 0
2309
+
2310
+ # are we auto-paging? if so, then use max limit.
2311
+ if limitTotal > 0:
2312
+ limit = 50
2313
+ #limit = 2 # TEST TODO
2314
+ if limit > limitTotal:
2315
+ limit = limitTotal
2316
+ result = AlbumPageSaved()
2317
+
2318
+ # ensure market was either supplied or implied; default if neither.
2319
+ market = self._ValidateMarket(market)
2212
2320
 
2213
2321
  # build spotify web api request parameters.
2214
2322
  urlParms:dict = \
@@ -2219,15 +2327,49 @@ class SpotifyClient:
2219
2327
  if market is not None:
2220
2328
  urlParms['market'] = market
2221
2329
 
2222
- # execute spotify web api request.
2223
- msg:SpotifyApiMessage = SpotifyApiMessage(apiMethodName, '/me/albums')
2224
- msg.RequestHeaders[self.AuthToken.HeaderKey] = self.AuthToken.HeaderValue
2225
- msg.UrlParameters = urlParms
2226
- self.MakeRequest('GET', msg)
2330
+ # handle pagination, as spotify limits us to a set # of items returned per response.
2331
+ while True:
2227
2332
 
2228
- # process results.
2229
- result = AlbumPageSaved(root=msg.ResponseData)
2333
+ # execute spotify web api request.
2334
+ msg:SpotifyApiMessage = SpotifyApiMessage(apiMethodName, '/me/albums')
2335
+ msg.RequestHeaders[self.AuthToken.HeaderKey] = self.AuthToken.HeaderValue
2336
+ msg.UrlParameters = urlParms
2337
+ self.MakeRequest('GET', msg)
2338
+
2339
+ # process results.
2340
+ pageObj = AlbumPageSaved(root=msg.ResponseData)
2230
2341
 
2342
+ # trace.
2343
+ _logsi.LogObject(SILevel.Verbose, (TRACE_METHOD_RESULT_TYPE_PAGE + pageObj.PagingInfo) % (apiMethodName, type(pageObj).__name__), pageObj, excludeNonPublic=True)
2344
+
2345
+ # was limit total argument specified?
2346
+ if (limitTotal <= 0):
2347
+
2348
+ # no - just return the initial page of results.
2349
+ result = pageObj
2350
+ break
2351
+
2352
+ else:
2353
+
2354
+ # append page of items to final results.
2355
+ item:AlbumSaved
2356
+ for item in pageObj.Items:
2357
+ result.Items.append(item)
2358
+ result.Limit = result.ItemsCount
2359
+ if result.ItemsCount >= limitTotal:
2360
+ break
2361
+
2362
+ # anymore pages to process? if not, then exit the loop.
2363
+ if not self._CheckForNextPage(pageObj, result.ItemsCount, limit, limitTotal, urlParms):
2364
+ break
2365
+
2366
+ # update result object with final paging details.
2367
+ result.Total = pageObj.Total
2368
+
2369
+ # sort items on Name property, ascending order.
2370
+ if len(result.Items) > 0:
2371
+ result.Items.sort(key=lambda x: (x.Album.Name or "").lower(), reverse=False)
2372
+
2231
2373
  # trace.
2232
2374
  _logsi.LogObject(SILevel.Verbose, (TRACE_METHOD_RESULT_TYPE + result.PagingInfo) % (apiMethodName, type(result).__name__), result, excludeNonPublic=True)
2233
2375
  return result
@@ -2249,6 +2391,7 @@ class SpotifyClient:
2249
2391
  limit:int=20,
2250
2392
  offset:int=0,
2251
2393
  country:str=None,
2394
+ limitTotal:int=None
2252
2395
  ) -> AlbumPageSimplified:
2253
2396
  """
2254
2397
  Get a list of new album releases featured in Spotify (shown, for example, on a
@@ -2256,10 +2399,10 @@ class SpotifyClient:
2256
2399
 
2257
2400
  Args:
2258
2401
  limit (int):
2259
- The maximum number of items to return.
2402
+ The maximum number of items to return in a page of items.
2260
2403
  Default: 20, Range: 1 to 50.
2261
2404
  offset (int):
2262
- The index of the first item to return.
2405
+ The page index offset of the first item to return.
2263
2406
  Use with limit to get the next set of items.
2264
2407
  Default: 0 (the first item).
2265
2408
  country (str):
@@ -2267,6 +2410,12 @@ class SpotifyClient:
2267
2410
  Provide this parameter if you want the list of returned items to be relevant to a
2268
2411
  particular country. If omitted, the returned items will be relevant to all countries.
2269
2412
  Example: `SE`
2413
+ limitTotal (int):
2414
+ The maximum number of items to return for the request.
2415
+ If specified, this argument overrides the limit and offset argument values
2416
+ and paging is automatically used to retrieve all available items up to the
2417
+ maximum number specified.
2418
+ Default: None (disabled)
2270
2419
 
2271
2420
  Returns:
2272
2421
  An `AlbumPageSimplified` object that contains simplified album information.
@@ -2279,11 +2428,17 @@ class SpotifyClient:
2279
2428
  If the method fails for any other reason.
2280
2429
 
2281
2430
  <details>
2282
- <summary>Sample Code</summary>
2431
+ <summary>Sample Code - Manual Paging</summary>
2283
2432
  ```python
2284
2433
  .. include:: ../docs/include/samplecode/SpotifyClient/GetAlbumNewReleases.py
2285
2434
  ```
2286
2435
  </details>
2436
+ <details>
2437
+ <summary>Sample Code - Auto Paging</summary>
2438
+ ```python
2439
+ .. include:: ../docs/include/samplecode/SpotifyClient/GetAlbumNewReleases_AutoPaging.py
2440
+ ```
2441
+ </details>
2287
2442
  """
2288
2443
  apiMethodName:str = 'GetAlbumNewReleases'
2289
2444
  apiMethodParms:SIMethodParmListContext = None
@@ -2296,6 +2451,7 @@ class SpotifyClient:
2296
2451
  apiMethodParms.AppendKeyValue("limit", limit)
2297
2452
  apiMethodParms.AppendKeyValue("offset", offset)
2298
2453
  apiMethodParms.AppendKeyValue("country", country)
2454
+ apiMethodParms.AppendKeyValue("limitTotal", limitTotal)
2299
2455
  _logsi.LogMethodParmList(SILevel.Verbose, "Get a list of new album releases", apiMethodParms)
2300
2456
 
2301
2457
  # validations.
@@ -2303,6 +2459,16 @@ class SpotifyClient:
2303
2459
  limit = 20
2304
2460
  if offset is None:
2305
2461
  offset = 0
2462
+ if not isinstance(limitTotal, int):
2463
+ limitTotal = 0
2464
+
2465
+ # are we auto-paging? if so, then use max limit.
2466
+ if limitTotal > 0:
2467
+ limit = 50
2468
+ #limit = 2 # TEST TODO
2469
+ if limit > limitTotal:
2470
+ limit = limitTotal
2471
+ result = AlbumPageSimplified()
2306
2472
 
2307
2473
  # build spotify web api request parameters.
2308
2474
  urlParms:dict = \
@@ -2313,16 +2479,50 @@ class SpotifyClient:
2313
2479
  if country is not None:
2314
2480
  urlParms['country'] = country
2315
2481
 
2316
- # execute spotify web api request.
2317
- msg:SpotifyApiMessage = SpotifyApiMessage(apiMethodName, '/browse/new-releases')
2318
- msg.RequestHeaders[self.AuthToken.HeaderKey] = self.AuthToken.HeaderValue
2319
- msg.UrlParameters = urlParms
2320
- self.MakeRequest('GET', msg)
2482
+ # handle pagination, as spotify limits us to a set # of items returned per response.
2483
+ while True:
2321
2484
 
2322
- # process results.
2323
- item:dict = msg.ResponseData.get('albums', None)
2324
- if item is not None:
2325
- result = AlbumPageSimplified(root=item)
2485
+ # execute spotify web api request.
2486
+ msg:SpotifyApiMessage = SpotifyApiMessage(apiMethodName, '/browse/new-releases')
2487
+ msg.RequestHeaders[self.AuthToken.HeaderKey] = self.AuthToken.HeaderValue
2488
+ msg.UrlParameters = urlParms
2489
+ self.MakeRequest('GET', msg)
2490
+
2491
+ # process results.
2492
+ item:dict = msg.ResponseData.get('albums', None)
2493
+ if item is not None:
2494
+ pageObj = AlbumPageSimplified(root=item)
2495
+
2496
+ # trace.
2497
+ _logsi.LogObject(SILevel.Verbose, (TRACE_METHOD_RESULT_TYPE_PAGE + pageObj.PagingInfo) % (apiMethodName, type(pageObj).__name__), pageObj, excludeNonPublic=True)
2498
+
2499
+ # was limit total argument specified?
2500
+ if (limitTotal <= 0):
2501
+
2502
+ # no - just return the initial page of results.
2503
+ result = pageObj
2504
+ break
2505
+
2506
+ else:
2507
+
2508
+ # append page of items to final results.
2509
+ item:AlbumSimplified
2510
+ for item in pageObj.Items:
2511
+ result.Items.append(item)
2512
+ result.Limit = result.ItemsCount
2513
+ if result.ItemsCount >= limitTotal:
2514
+ break
2515
+
2516
+ # anymore pages to process? if not, then exit the loop.
2517
+ if not self._CheckForNextPage(pageObj, result.ItemsCount, limit, limitTotal, urlParms):
2518
+ break
2519
+
2520
+ # update result object with final paging details.
2521
+ result.Total = pageObj.Total
2522
+
2523
+ # sort items on Name property, ascending order.
2524
+ if len(result.Items) > 0:
2525
+ result.Items.sort(key=lambda x: (x.Name or "").lower(), reverse=False)
2326
2526
 
2327
2527
  # trace.
2328
2528
  _logsi.LogObject(SILevel.Verbose, (TRACE_METHOD_RESULT_TYPE + result.PagingInfo) % (apiMethodName, type(result).__name__), result, excludeNonPublic=True)
@@ -2391,6 +2591,9 @@ class SpotifyClient:
2391
2591
  apiMethodParms.AppendKeyValue("market", market)
2392
2592
  _logsi.LogMethodParmList(SILevel.Verbose, "Get Spotify catalog information for multiple albums", apiMethodParms)
2393
2593
 
2594
+ # ensure market was either supplied or implied; default if neither.
2595
+ market = self._ValidateMarket(market)
2596
+
2394
2597
  # build spotify web api request parameters.
2395
2598
  urlParms:dict = \
2396
2599
  {
@@ -2432,6 +2635,7 @@ class SpotifyClient:
2432
2635
  limit:int=20,
2433
2636
  offset:int=0,
2434
2637
  market:str=None,
2638
+ limitTotal:int=None
2435
2639
  ) -> TrackPageSimplified:
2436
2640
  """
2437
2641
  Get Spotify catalog information about an album's tracks.
@@ -2443,7 +2647,7 @@ class SpotifyClient:
2443
2647
  The Spotify ID of the album.
2444
2648
  Example: `6vc9OTcyd3hyzabCmsdnwE`
2445
2649
  limit (int):
2446
- The maximum number of items to return.
2650
+ The maximum number of items to return in a page of items.
2447
2651
  Default: 20, Range: 1 to 50.
2448
2652
  offset (int):
2449
2653
  The index of the first item to return; use with limit to get the next set of items.
@@ -2456,6 +2660,12 @@ class SpotifyClient:
2456
2660
  Note: If neither market or user country are provided, the content is considered unavailable for the client.
2457
2661
  Users can view the country that is associated with their account in the account settings.
2458
2662
  Example: `ES`
2663
+ limitTotal (int):
2664
+ The maximum number of items to return for the request.
2665
+ If specified, this argument overrides the limit and offset argument values
2666
+ and paging is automatically used to retrieve all available items up to the
2667
+ maximum number specified.
2668
+ Default: None (disabled)
2459
2669
 
2460
2670
  Returns:
2461
2671
  A `TrackPageSimplified` object that contains simplified track information for the albumId.
@@ -2468,11 +2678,17 @@ class SpotifyClient:
2468
2678
  If the method fails for any other reason.
2469
2679
 
2470
2680
  <details>
2471
- <summary>Sample Code</summary>
2681
+ <summary>Sample Code - Manual Paging</summary>
2472
2682
  ```python
2473
2683
  .. include:: ../docs/include/samplecode/SpotifyClient/GetAlbumTracks.py
2474
2684
  ```
2475
2685
  </details>
2686
+ <details>
2687
+ <summary>Sample Code - Auto Paging</summary>
2688
+ ```python
2689
+ .. include:: ../docs/include/samplecode/SpotifyClient/GetAlbumTracks_AutoPaging.py
2690
+ ```
2691
+ </details>
2476
2692
  """
2477
2693
  apiMethodName:str = 'GetAlbumTracks'
2478
2694
  apiMethodParms:SIMethodParmListContext = None
@@ -2486,6 +2702,7 @@ class SpotifyClient:
2486
2702
  apiMethodParms.AppendKeyValue("limit", limit)
2487
2703
  apiMethodParms.AppendKeyValue("offset", offset)
2488
2704
  apiMethodParms.AppendKeyValue("market", market)
2705
+ apiMethodParms.AppendKeyValue("limitTotal", limitTotal)
2489
2706
  _logsi.LogMethodParmList(SILevel.Verbose, "Get Spotify catalog information about an album's tracks", apiMethodParms)
2490
2707
 
2491
2708
  # validations.
@@ -2493,6 +2710,19 @@ class SpotifyClient:
2493
2710
  limit = 20
2494
2711
  if offset is None:
2495
2712
  offset = 0
2713
+ if not isinstance(limitTotal, int):
2714
+ limitTotal = 0
2715
+
2716
+ # are we auto-paging? if so, then use max limit.
2717
+ if limitTotal > 0:
2718
+ limit = 50
2719
+ #limit = 2 # TEST TODO
2720
+ if limit > limitTotal:
2721
+ limit = limitTotal
2722
+ result = TrackPageSimplified()
2723
+
2724
+ # ensure market was either supplied or implied; default if neither.
2725
+ market = self._ValidateMarket(market)
2496
2726
 
2497
2727
  # build spotify web api request parameters.
2498
2728
  urlParms:dict = \
@@ -2503,14 +2733,46 @@ class SpotifyClient:
2503
2733
  if market is not None:
2504
2734
  urlParms['market'] = market
2505
2735
 
2506
- # execute spotify web api request.
2507
- msg:SpotifyApiMessage = SpotifyApiMessage(apiMethodName, '/albums/{id}/tracks'.format(id=albumId))
2508
- msg.RequestHeaders[self.AuthToken.HeaderKey] = self.AuthToken.HeaderValue
2509
- msg.UrlParameters = urlParms
2510
- self.MakeRequest('GET', msg)
2736
+ # handle pagination, as spotify limits us to a set # of items returned per response.
2737
+ while True:
2511
2738
 
2512
- # process results.
2513
- result = TrackPageSimplified(root=msg.ResponseData)
2739
+ # execute spotify web api request.
2740
+ msg:SpotifyApiMessage = SpotifyApiMessage(apiMethodName, '/albums/{id}/tracks'.format(id=albumId))
2741
+ msg.RequestHeaders[self.AuthToken.HeaderKey] = self.AuthToken.HeaderValue
2742
+ msg.UrlParameters = urlParms
2743
+ self.MakeRequest('GET', msg)
2744
+
2745
+ # process results.
2746
+ pageObj = TrackPageSimplified(root=msg.ResponseData)
2747
+
2748
+ # trace.
2749
+ _logsi.LogObject(SILevel.Verbose, (TRACE_METHOD_RESULT_TYPE_PAGE + pageObj.PagingInfo) % (apiMethodName, type(pageObj).__name__), pageObj, excludeNonPublic=True)
2750
+
2751
+ # was limit total argument specified?
2752
+ if (limitTotal <= 0):
2753
+
2754
+ # no - just return the initial page of results.
2755
+ result = pageObj
2756
+ break
2757
+
2758
+ else:
2759
+
2760
+ # append page of items to final results.
2761
+ item:TrackSimplified
2762
+ for item in pageObj.Items:
2763
+ result.Items.append(item)
2764
+ result.Limit = result.ItemsCount
2765
+ if result.ItemsCount >= limitTotal:
2766
+ break
2767
+
2768
+ # anymore pages to process? if not, then exit the loop.
2769
+ if not self._CheckForNextPage(pageObj, result.ItemsCount, limit, limitTotal, urlParms):
2770
+ break
2771
+
2772
+ # update result object with final paging details.
2773
+ result.Total = pageObj.Total
2774
+
2775
+ # do not sort items, as they are in playable order.
2514
2776
 
2515
2777
  # trace.
2516
2778
  _logsi.LogObject(SILevel.Verbose, (TRACE_METHOD_RESULT_TYPE + result.PagingInfo) % (apiMethodName, type(result).__name__), result, excludeNonPublic=True)
@@ -2598,7 +2860,8 @@ class SpotifyClient:
2598
2860
  include_groups:str='album',
2599
2861
  limit:int=20,
2600
2862
  offset:int=0,
2601
- market:str=None
2863
+ market:str=None,
2864
+ limitTotal:int=None
2602
2865
  ) -> AlbumPageSimplified:
2603
2866
  """
2604
2867
  Get Spotify catalog information about an artist's albums.
@@ -2613,7 +2876,7 @@ class SpotifyClient:
2613
2876
  Valid values are: `album`, `single`, `appears_on`, `compilation`
2614
2877
  Example: `single,appears_on`
2615
2878
  limit (int):
2616
- The maximum number of items to return.
2879
+ The maximum number of items to return in a page of items.
2617
2880
  Default: 20, Range: 1 to 50.
2618
2881
  offset (int):
2619
2882
  The index of the first item to return; use with limit to get the next set of items.
@@ -2626,6 +2889,12 @@ class SpotifyClient:
2626
2889
  Note: If neither market or user country are provided, the content is considered unavailable for the client.
2627
2890
  Users can view the country that is associated with their account in the account settings.
2628
2891
  Example: `ES`
2892
+ limitTotal (int):
2893
+ The maximum number of items to return for the request.
2894
+ If specified, this argument overrides the limit and offset argument values
2895
+ and paging is automatically used to retrieve all available items up to the
2896
+ maximum number specified.
2897
+ Default: None (disabled)
2629
2898
 
2630
2899
  Returns:
2631
2900
  An `AlbumPageSimplified` object of matching results.
@@ -2638,11 +2907,17 @@ class SpotifyClient:
2638
2907
  If the method fails for any other reason.
2639
2908
 
2640
2909
  <details>
2641
- <summary>Sample Code</summary>
2910
+ <summary>Sample Code - Manual Paging</summary>
2642
2911
  ```python
2643
2912
  .. include:: ../docs/include/samplecode/SpotifyClient/GetArtistAlbums.py
2644
2913
  ```
2645
2914
  </details>
2915
+ <details>
2916
+ <summary>Sample Code - auto Paging</summary>
2917
+ ```python
2918
+ .. include:: ../docs/include/samplecode/SpotifyClient/GetArtistAlbums_AutoPaging.py
2919
+ ```
2920
+ </details>
2646
2921
  """
2647
2922
  apiMethodName:str = 'GetArtistAlbums'
2648
2923
  apiMethodParms:SIMethodParmListContext = None
@@ -2657,6 +2932,7 @@ class SpotifyClient:
2657
2932
  apiMethodParms.AppendKeyValue("limit", limit)
2658
2933
  apiMethodParms.AppendKeyValue("offset", offset)
2659
2934
  apiMethodParms.AppendKeyValue("market", market)
2935
+ apiMethodParms.AppendKeyValue("limitTotal", limitTotal)
2660
2936
  _logsi.LogMethodParmList(SILevel.Verbose, "Get Spotify catalog information about an artist's albums", apiMethodParms)
2661
2937
 
2662
2938
  # validations.
@@ -2664,6 +2940,19 @@ class SpotifyClient:
2664
2940
  limit = 20
2665
2941
  if offset is None:
2666
2942
  offset = 0
2943
+ if not isinstance(limitTotal, int):
2944
+ limitTotal = 0
2945
+
2946
+ # are we auto-paging? if so, then use max limit.
2947
+ if limitTotal > 0:
2948
+ limit = 50
2949
+ #limit = 5 # TEST TODO
2950
+ if limit > limitTotal:
2951
+ limit = limitTotal
2952
+ result = AlbumPageSimplified()
2953
+
2954
+ # ensure market was either supplied or implied; default if neither.
2955
+ market = self._ValidateMarket(market)
2667
2956
 
2668
2957
  # build spotify web api request parameters.
2669
2958
  urlParms:dict = \
@@ -2675,14 +2964,48 @@ class SpotifyClient:
2675
2964
  if market is not None:
2676
2965
  urlParms['market'] = market
2677
2966
 
2678
- # execute spotify web api request.
2679
- msg:SpotifyApiMessage = SpotifyApiMessage(apiMethodName, '/artists/{id}/albums'.format(id=artistId))
2680
- msg.RequestHeaders[self.AuthToken.HeaderKey] = self.AuthToken.HeaderValue
2681
- msg.UrlParameters = urlParms
2682
- self.MakeRequest('GET', msg)
2967
+ # handle pagination, as spotify limits us to a set # of items returned per response.
2968
+ while True:
2683
2969
 
2684
- # process results.
2685
- result = AlbumPageSimplified(root=msg.ResponseData)
2970
+ # execute spotify web api request.
2971
+ msg:SpotifyApiMessage = SpotifyApiMessage(apiMethodName, '/artists/{id}/albums'.format(id=artistId))
2972
+ msg.RequestHeaders[self.AuthToken.HeaderKey] = self.AuthToken.HeaderValue
2973
+ msg.UrlParameters = urlParms
2974
+ self.MakeRequest('GET', msg)
2975
+
2976
+ # process results.
2977
+ pageObj = AlbumPageSimplified(root=msg.ResponseData)
2978
+
2979
+ # trace.
2980
+ _logsi.LogObject(SILevel.Verbose, (TRACE_METHOD_RESULT_TYPE_PAGE + pageObj.PagingInfo) % (apiMethodName, type(pageObj).__name__), pageObj, excludeNonPublic=True)
2981
+
2982
+ # was limit total argument specified?
2983
+ if (limitTotal <= 0):
2984
+
2985
+ # no - just return the initial page of results.
2986
+ result = pageObj
2987
+ break
2988
+
2989
+ else:
2990
+
2991
+ # append page of items to final results.
2992
+ item:AlbumSimplified
2993
+ for item in pageObj.Items:
2994
+ result.Items.append(item)
2995
+ result.Limit = result.ItemsCount
2996
+ if result.ItemsCount >= limitTotal:
2997
+ break
2998
+
2999
+ # anymore pages to process? if not, then exit the loop.
3000
+ if not self._CheckForNextPage(pageObj, result.ItemsCount, limit, limitTotal, urlParms):
3001
+ break
3002
+
3003
+ # update result object with final paging details.
3004
+ result.Total = pageObj.Total
3005
+
3006
+ # sort items on Name property, ascending order.
3007
+ if len(result.Items) > 0:
3008
+ result.Items.sort(key=lambda x: (x.Name or "").lower(), reverse=False)
2686
3009
 
2687
3010
  # trace.
2688
3011
  _logsi.LogObject(SILevel.Verbose, (TRACE_METHOD_RESULT_TYPE + result.PagingInfo) % (apiMethodName, type(result).__name__), result, excludeNonPublic=True)
@@ -2845,6 +3168,7 @@ class SpotifyClient:
2845
3168
  def GetArtistsFollowed(self,
2846
3169
  after:str=None,
2847
3170
  limit:int=20,
3171
+ limitTotal:int=None
2848
3172
  ) -> ArtistPage:
2849
3173
  """
2850
3174
  Get the current user's followed artists.
@@ -2855,8 +3179,14 @@ class SpotifyClient:
2855
3179
  the first request.
2856
3180
  Example: `6APm8EjxOHSYM5B4i3vT3q`
2857
3181
  limit (int):
2858
- The maximum number of items to return.
3182
+ The maximum number of items to return in a page of items.
2859
3183
  Default: 20, Range: 1 to 50.
3184
+ limitTotal (int):
3185
+ The maximum number of items to return for the request.
3186
+ If specified, this argument overrides the limit and offset argument values
3187
+ and paging is automatically used to retrieve all available items up to the
3188
+ maximum number specified.
3189
+ Default: None (disabled)
2860
3190
 
2861
3191
  Returns:
2862
3192
  An `ArtistPage` object of matching results.
@@ -2869,11 +3199,17 @@ class SpotifyClient:
2869
3199
  If the method fails for any other reason.
2870
3200
 
2871
3201
  <details>
2872
- <summary>Sample Code</summary>
3202
+ <summary>Sample Code - Manual Paging</summary>
2873
3203
  ```python
2874
3204
  .. include:: ../docs/include/samplecode/SpotifyClient/GetArtistsFollowed.py
2875
3205
  ```
2876
3206
  </details>
3207
+ <details>
3208
+ <summary>Sample Code - Auto Paging</summary>
3209
+ ```python
3210
+ .. include:: ../docs/include/samplecode/SpotifyClient/GetArtistsFollowed_AutoPaging.py
3211
+ ```
3212
+ </details>
2877
3213
  """
2878
3214
  apiMethodName:str = 'GetArtistsFollowed'
2879
3215
  apiMethodParms:SIMethodParmListContext = None
@@ -2885,8 +3221,23 @@ class SpotifyClient:
2885
3221
  apiMethodParms = _logsi.EnterMethodParmList(SILevel.Debug, apiMethodName)
2886
3222
  apiMethodParms.AppendKeyValue("after", after)
2887
3223
  apiMethodParms.AppendKeyValue("limit", limit)
3224
+ apiMethodParms.AppendKeyValue("limitTotal", limitTotal)
2888
3225
  _logsi.LogMethodParmList(SILevel.Verbose, "Get the current user's followed artists", apiMethodParms)
2889
3226
 
3227
+ # validations.
3228
+ if limit is None:
3229
+ limit = 20
3230
+ if not isinstance(limitTotal, int):
3231
+ limitTotal = 0
3232
+
3233
+ # are we auto-paging? if so, then use max limit.
3234
+ if limitTotal > 0:
3235
+ limit = 50
3236
+ #limit = 5 # TEST TODO
3237
+ if limit > limitTotal:
3238
+ limit = limitTotal
3239
+ result = ArtistPage()
3240
+
2890
3241
  # build spotify web api request parameters.
2891
3242
  urlParms:dict = \
2892
3243
  {
@@ -2896,16 +3247,62 @@ class SpotifyClient:
2896
3247
  if after is not None:
2897
3248
  urlParms['after'] = after
2898
3249
 
2899
- # execute spotify web api request.
2900
- msg:SpotifyApiMessage = SpotifyApiMessage(apiMethodName, '/me/following')
2901
- msg.RequestHeaders[self.AuthToken.HeaderKey] = self.AuthToken.HeaderValue
2902
- msg.UrlParameters = urlParms
2903
- self.MakeRequest('GET', msg)
3250
+ # handle pagination, as spotify limits us to a set # of items returned per response.
3251
+ while True:
2904
3252
 
2905
- # process results.
2906
- item:dict = msg.ResponseData.get('artists',{})
2907
- if item is not None:
2908
- result = ArtistPage(root=item)
3253
+ # execute spotify web api request.
3254
+ msg:SpotifyApiMessage = SpotifyApiMessage(apiMethodName, '/me/following')
3255
+ msg.RequestHeaders[self.AuthToken.HeaderKey] = self.AuthToken.HeaderValue
3256
+ msg.UrlParameters = urlParms
3257
+ self.MakeRequest('GET', msg)
3258
+
3259
+ # process results.
3260
+ item:dict = msg.ResponseData.get('artists',{})
3261
+ if item is not None:
3262
+ pageObj = ArtistPage(root=item)
3263
+
3264
+ # trace.
3265
+ _logsi.LogObject(SILevel.Verbose, (TRACE_METHOD_RESULT_TYPE_PAGE + pageObj.PagingInfo) % (apiMethodName, type(pageObj).__name__), pageObj, excludeNonPublic=True)
3266
+
3267
+ # was limit total argument specified?
3268
+ if (limitTotal <= 0):
3269
+
3270
+ # no - just return the initial page of results.
3271
+ result = pageObj
3272
+ break
3273
+
3274
+ else:
3275
+
3276
+ # append page of items to final results.
3277
+ item:Artist
3278
+ for item in pageObj.Items:
3279
+ result.Items.append(item)
3280
+ result.Limit = result.ItemsCount
3281
+ if result.ItemsCount >= limitTotal:
3282
+ break
3283
+
3284
+ # anymore page results?
3285
+ if (pageObj.Next is None) or (result.ItemsCount >= limitTotal):
3286
+ # no - all pages were processed, or limit total reached.
3287
+ break
3288
+ else:
3289
+ # yes - retrieve the next page of results.
3290
+ pageObj.CursorAfter = item.Id
3291
+
3292
+ # modify paging-related request parameters for next page of items.
3293
+ urlParms['limit'] = pageObj.Limit
3294
+ urlParms['after'] = pageObj.CursorAfter
3295
+
3296
+ # trace.
3297
+ _logsi.LogVerbose(TRACE_MSG_AUTOPAGING_NEXT % pageObj.PagingInfo)
3298
+
3299
+ # update result object with final paging details.
3300
+ result.Total = pageObj.Total
3301
+ result.CursorAfter = pageObj.CursorAfter
3302
+
3303
+ # sort items on Name property, ascending order.
3304
+ if len(result.Items) > 0:
3305
+ result.Items.sort(key=lambda x: (x.Name or "").lower(), reverse=False)
2909
3306
 
2910
3307
  # trace.
2911
3308
  _logsi.LogObject(SILevel.Verbose, TRACE_METHOD_RESULT_TYPE % (apiMethodName, type(result).__name__), result, excludeNonPublic=True)
@@ -2973,6 +3370,9 @@ class SpotifyClient:
2973
3370
  apiMethodParms.AppendKeyValue("market", market)
2974
3371
  _logsi.LogMethodParmList(SILevel.Verbose, "Get Spotify catalog information about an artist's top tracks", apiMethodParms)
2975
3372
 
3373
+ # ensure market was either supplied or implied; default if neither.
3374
+ market = self._ValidateMarket(market)
3375
+
2976
3376
  # build spotify web api request parameters.
2977
3377
  urlParms:dict = {}
2978
3378
  if market is not None:
@@ -3062,6 +3462,9 @@ class SpotifyClient:
3062
3462
  apiMethodParms.AppendKeyValue("market", market)
3063
3463
  _logsi.LogMethodParmList(SILevel.Verbose, "Get Spotify catalog information for a single audiobook", apiMethodParms)
3064
3464
 
3465
+ # ensure market was either supplied or implied; default if neither.
3466
+ market = self._ValidateMarket(market)
3467
+
3065
3468
  # build spotify web api request parameters.
3066
3469
  urlParms:dict = {}
3067
3470
  if market is not None:
@@ -3097,7 +3500,8 @@ class SpotifyClient:
3097
3500
  audiobookId:str,
3098
3501
  limit:int=20,
3099
3502
  offset:int=0,
3100
- market:str=None
3503
+ market:str=None,
3504
+ limitTotal:int=None
3101
3505
  ) -> ChapterPageSimplified:
3102
3506
  """
3103
3507
  Get Spotify catalog information about an audiobook's chapters.
@@ -3109,7 +3513,7 @@ class SpotifyClient:
3109
3513
  The Spotify ID for the audiobook.
3110
3514
  Example: `74aydHJKgYz3AIq3jjBSv1`
3111
3515
  limit (int):
3112
- The maximum number of items to return.
3516
+ The maximum number of items to return in a page of items.
3113
3517
  Default: 20, Range: 1 to 50.
3114
3518
  offset (int):
3115
3519
  The index of the first item to return; use with limit to get the next set of items.
@@ -3122,6 +3526,12 @@ class SpotifyClient:
3122
3526
  Note: If neither market or user country are provided, the content is considered unavailable for the client.
3123
3527
  Users can view the country that is associated with their account in the account settings.
3124
3528
  Example: `ES`
3529
+ limitTotal (int):
3530
+ The maximum number of items to return for the request.
3531
+ If specified, this argument overrides the limit and offset argument values
3532
+ and paging is automatically used to retrieve all available items up to the
3533
+ maximum number specified.
3534
+ Default: None (disabled)
3125
3535
 
3126
3536
  Returns:
3127
3537
  A `ChapterPageSimplified` object that contains simplified track information for the audiobookId.
@@ -3134,11 +3544,17 @@ class SpotifyClient:
3134
3544
  If the method fails for any other reason.
3135
3545
 
3136
3546
  <details>
3137
- <summary>Sample Code</summary>
3547
+ <summary>Sample Code - Manual Paging</summary>
3138
3548
  ```python
3139
3549
  .. include:: ../docs/include/samplecode/SpotifyClient/GetAudiobookChapters.py
3140
3550
  ```
3141
3551
  </details>
3552
+ <details>
3553
+ <summary>Sample Code - Auto Paging</summary>
3554
+ ```python
3555
+ .. include:: ../docs/include/samplecode/SpotifyClient/GetAudiobookChapters_AutoPaging.py
3556
+ ```
3557
+ </details>
3142
3558
  """
3143
3559
  apiMethodName:str = 'GetAudiobookChapters'
3144
3560
  apiMethodParms:SIMethodParmListContext = None
@@ -3152,6 +3568,7 @@ class SpotifyClient:
3152
3568
  apiMethodParms.AppendKeyValue("limit", limit)
3153
3569
  apiMethodParms.AppendKeyValue("offset", offset)
3154
3570
  apiMethodParms.AppendKeyValue("market", market)
3571
+ apiMethodParms.AppendKeyValue("limitTotal", limitTotal)
3155
3572
  _logsi.LogMethodParmList(SILevel.Verbose, "Get Spotify catalog information about an audiobook's chapters", apiMethodParms)
3156
3573
 
3157
3574
  # validations.
@@ -3159,6 +3576,19 @@ class SpotifyClient:
3159
3576
  limit = 20
3160
3577
  if offset is None:
3161
3578
  offset = 0
3579
+ if not isinstance(limitTotal, int):
3580
+ limitTotal = 0
3581
+
3582
+ # are we auto-paging? if so, then use max limit.
3583
+ if limitTotal > 0:
3584
+ limit = 50
3585
+ #limit = 2 # TEST TODO
3586
+ if limit > limitTotal:
3587
+ limit = limitTotal
3588
+ result = ChapterPageSimplified()
3589
+
3590
+ # ensure market was either supplied or implied; default if neither.
3591
+ market = self._ValidateMarket(market)
3162
3592
 
3163
3593
  # build spotify web api request parameters.
3164
3594
  urlParms:dict = \
@@ -3169,14 +3599,46 @@ class SpotifyClient:
3169
3599
  if market is not None:
3170
3600
  urlParms['market'] = market
3171
3601
 
3172
- # execute spotify web api request.
3173
- msg:SpotifyApiMessage = SpotifyApiMessage(apiMethodName, '/audiobooks/{id}/chapters'.format(id=audiobookId))
3174
- msg.RequestHeaders[self.AuthToken.HeaderKey] = self.AuthToken.HeaderValue
3175
- msg.UrlParameters = urlParms
3176
- self.MakeRequest('GET', msg)
3602
+ # handle pagination, as spotify limits us to a set # of items returned per response.
3603
+ while True:
3177
3604
 
3178
- # process results.
3179
- result = ChapterPageSimplified(root=msg.ResponseData)
3605
+ # execute spotify web api request.
3606
+ msg:SpotifyApiMessage = SpotifyApiMessage(apiMethodName, '/audiobooks/{id}/chapters'.format(id=audiobookId))
3607
+ msg.RequestHeaders[self.AuthToken.HeaderKey] = self.AuthToken.HeaderValue
3608
+ msg.UrlParameters = urlParms
3609
+ self.MakeRequest('GET', msg)
3610
+
3611
+ # process results.
3612
+ pageObj = ChapterPageSimplified(root=msg.ResponseData)
3613
+
3614
+ # trace.
3615
+ _logsi.LogObject(SILevel.Verbose, (TRACE_METHOD_RESULT_TYPE_PAGE + pageObj.PagingInfo) % (apiMethodName, type(pageObj).__name__), pageObj, excludeNonPublic=True)
3616
+
3617
+ # was limit total argument specified?
3618
+ if (limitTotal <= 0):
3619
+
3620
+ # no - just return the initial page of results.
3621
+ result = pageObj
3622
+ break
3623
+
3624
+ else:
3625
+
3626
+ # append page of items to final results.
3627
+ item:ChapterSimplified
3628
+ for item in pageObj.Items:
3629
+ result.Items.append(item)
3630
+ result.Limit = result.ItemsCount
3631
+ if result.ItemsCount >= limitTotal:
3632
+ break
3633
+
3634
+ # anymore pages to process? if not, then exit the loop.
3635
+ if not self._CheckForNextPage(pageObj, result.ItemsCount, limit, limitTotal, urlParms):
3636
+ break
3637
+
3638
+ # update result object with final paging details.
3639
+ result.Total = pageObj.Total
3640
+
3641
+ # no sorting, as chapters are in playable order.
3180
3642
 
3181
3643
  # trace.
3182
3644
  _logsi.LogObject(SILevel.Verbose, (TRACE_METHOD_RESULT_TYPE + result.PagingInfo) % (apiMethodName, type(result).__name__), result, excludeNonPublic=True)
@@ -3198,6 +3660,7 @@ class SpotifyClient:
3198
3660
  def GetAudiobookFavorites(self,
3199
3661
  limit:int=20,
3200
3662
  offset:int=0,
3663
+ limitTotal:int=None
3201
3664
  ) -> AudiobookPageSimplified:
3202
3665
  """
3203
3666
  Get a list of the audiobooks saved in the current Spotify user's 'Your Library'.
@@ -3206,12 +3669,18 @@ class SpotifyClient:
3206
3669
 
3207
3670
  Args:
3208
3671
  limit (int):
3209
- The maximum number of items to return.
3672
+ The maximum number of items to return in a page of items.
3210
3673
  Default: 20, Range: 1 to 50.
3211
3674
  offset (int):
3212
- The index of the first item to return.
3675
+ The page index offset of the first item to return.
3213
3676
  Use with limit to get the next set of items.
3214
3677
  Default: 0 (the first item).
3678
+ limitTotal (int):
3679
+ The maximum number of items to return for the request.
3680
+ If specified, this argument overrides the limit and offset argument values
3681
+ and paging is automatically used to retrieve all available items up to the
3682
+ maximum number specified.
3683
+ Default: None (disabled)
3215
3684
 
3216
3685
  Returns:
3217
3686
  An `AudiobookPageSimplified` object that contains saved audiobook information.
@@ -3224,11 +3693,17 @@ class SpotifyClient:
3224
3693
  If the method fails for any other reason.
3225
3694
 
3226
3695
  <details>
3227
- <summary>Sample Code</summary>
3696
+ <summary>Sample Code - Manual Paging</summary>
3228
3697
  ```python
3229
3698
  .. include:: ../docs/include/samplecode/SpotifyClient/GetAudiobookFavorites.py
3230
3699
  ```
3231
3700
  </details>
3701
+ <details>
3702
+ <summary>Sample Code - Auto Paging</summary>
3703
+ ```python
3704
+ .. include:: ../docs/include/samplecode/SpotifyClient/GetAudiobookFavorites_AutoPaging.py
3705
+ ```
3706
+ </details>
3232
3707
  """
3233
3708
  apiMethodName:str = 'GetAudiobookFavorites'
3234
3709
  apiMethodParms:SIMethodParmListContext = None
@@ -3240,6 +3715,7 @@ class SpotifyClient:
3240
3715
  apiMethodParms = _logsi.EnterMethodParmList(SILevel.Debug, apiMethodName)
3241
3716
  apiMethodParms.AppendKeyValue("limit", limit)
3242
3717
  apiMethodParms.AppendKeyValue("offset", offset)
3718
+ apiMethodParms.AppendKeyValue("limitTotal", limitTotal)
3243
3719
  _logsi.LogMethodParmList(SILevel.Verbose, "Get a list of the users audiobook favorites", apiMethodParms)
3244
3720
 
3245
3721
  # validations.
@@ -3247,6 +3723,16 @@ class SpotifyClient:
3247
3723
  limit = 20
3248
3724
  if offset is None:
3249
3725
  offset = 0
3726
+ if not isinstance(limitTotal, int):
3727
+ limitTotal = 0
3728
+
3729
+ # are we auto-paging? if so, then use max limit.
3730
+ if limitTotal > 0:
3731
+ limit = 50
3732
+ #limit = 2 # TEST TODO
3733
+ if limit > limitTotal:
3734
+ limit = limitTotal
3735
+ result = AudiobookPageSimplified()
3250
3736
 
3251
3737
  # build spotify web api request parameters.
3252
3738
  urlParms:dict = \
@@ -3255,15 +3741,49 @@ class SpotifyClient:
3255
3741
  'offset': offset,
3256
3742
  }
3257
3743
 
3258
- # execute spotify web api request.
3259
- msg:SpotifyApiMessage = SpotifyApiMessage(apiMethodName, '/me/audiobooks')
3260
- msg.RequestHeaders[self.AuthToken.HeaderKey] = self.AuthToken.HeaderValue
3261
- msg.UrlParameters = urlParms
3262
- self.MakeRequest('GET', msg)
3744
+ # handle pagination, as spotify limits us to a set # of items returned per response.
3745
+ while True:
3263
3746
 
3264
- # process results.
3265
- result = AudiobookPageSimplified(root=msg.ResponseData)
3747
+ # execute spotify web api request.
3748
+ msg:SpotifyApiMessage = SpotifyApiMessage(apiMethodName, '/me/audiobooks')
3749
+ msg.RequestHeaders[self.AuthToken.HeaderKey] = self.AuthToken.HeaderValue
3750
+ msg.UrlParameters = urlParms
3751
+ self.MakeRequest('GET', msg)
3752
+
3753
+ # process results.
3754
+ pageObj = AudiobookPageSimplified(root=msg.ResponseData)
3266
3755
 
3756
+ # trace.
3757
+ _logsi.LogObject(SILevel.Verbose, (TRACE_METHOD_RESULT_TYPE_PAGE + pageObj.PagingInfo) % (apiMethodName, type(pageObj).__name__), pageObj, excludeNonPublic=True)
3758
+
3759
+ # was limit total argument specified?
3760
+ if (limitTotal <= 0):
3761
+
3762
+ # no - just return the initial page of results.
3763
+ result = pageObj
3764
+ break
3765
+
3766
+ else:
3767
+
3768
+ # append page of items to final results.
3769
+ item:AudiobookSimplified
3770
+ for item in pageObj.Items:
3771
+ result.Items.append(item)
3772
+ result.Limit = result.ItemsCount
3773
+ if result.ItemsCount >= limitTotal:
3774
+ break
3775
+
3776
+ # anymore pages to process? if not, then exit the loop.
3777
+ if not self._CheckForNextPage(pageObj, result.ItemsCount, limit, limitTotal, urlParms):
3778
+ break
3779
+
3780
+ # update result object with final paging details.
3781
+ result.Total = pageObj.Total
3782
+
3783
+ # sort items on Name property, ascending order.
3784
+ if len(result.Items) > 0:
3785
+ result.Items.sort(key=lambda x: (x.Name or "").lower(), reverse=False)
3786
+
3267
3787
  # trace.
3268
3788
  _logsi.LogObject(SILevel.Verbose, (TRACE_METHOD_RESULT_TYPE + result.PagingInfo) % (apiMethodName, type(result).__name__), result, excludeNonPublic=True)
3269
3789
  return result
@@ -3336,6 +3856,9 @@ class SpotifyClient:
3336
3856
  apiMethodParms.AppendKeyValue("market", market)
3337
3857
  _logsi.LogMethodParmList(SILevel.Verbose, "Get Spotify catalog information for multiple audiobooks", apiMethodParms)
3338
3858
 
3859
+ # ensure market was either supplied or implied; default if neither.
3860
+ market = self._ValidateMarket(market)
3861
+
3339
3862
  # build spotify web api request parameters.
3340
3863
  urlParms:dict = \
3341
3864
  {
@@ -3490,21 +4013,22 @@ class SpotifyClient:
3490
4013
  _logsi.LeaveMethod(SILevel.Debug, apiMethodName)
3491
4014
 
3492
4015
 
3493
- def GetBrowseCategorysPage(self,
3494
- limit:int=50,
3495
- offset:int=0,
3496
- country:str=None,
3497
- locale:str=None,
3498
- ) -> CategoryPage:
4016
+ def GetBrowseCategorys(self,
4017
+ limit:int=20,
4018
+ offset:int=0,
4019
+ country:str=None,
4020
+ locale:str=None,
4021
+ limitTotal:int=None
4022
+ ) -> CategoryPage:
3499
4023
  """
3500
4024
  Get a page of categories used to tag items in Spotify.
3501
4025
 
3502
4026
  Args:
3503
4027
  limit (int):
3504
- The maximum number of items to return.
3505
- Default: 50, Range: 1 to 50.
4028
+ The maximum number of items to return in a page of items.
4029
+ Default: 20, Range: 1 to 50.
3506
4030
  offset (int):
3507
- The index of the first item to return.
4031
+ The page index offset of the first item to return.
3508
4032
  Use with limit to get the next set of items.
3509
4033
  Default: 0 (the first item).
3510
4034
  country (str):
@@ -3522,6 +4046,12 @@ class SpotifyClient:
3522
4046
  the country parameter, may give odd results if not carefully matched. For example country=`SE` and
3523
4047
  locale=`de_DE` will return a list of categories relevant to Sweden but as German language strings.
3524
4048
  Example: `sv_SE`
4049
+ limitTotal (int):
4050
+ The maximum number of items to return for the request.
4051
+ If specified, this argument overrides the limit and offset argument values
4052
+ and paging is automatically used to retrieve all available items up to the
4053
+ maximum number specified.
4054
+ Default: None (disabled)
3525
4055
 
3526
4056
  Returns:
3527
4057
  A `CategoryPage` object that contains a page of category details.
@@ -3534,13 +4064,19 @@ class SpotifyClient:
3534
4064
  If the method fails for any other reason.
3535
4065
 
3536
4066
  <details>
3537
- <summary>Sample Code</summary>
4067
+ <summary>Sample Code - Manual Paging</summary>
4068
+ ```python
4069
+ .. include:: ../docs/include/samplecode/SpotifyClient/GetBrowseCategorys.py
4070
+ ```
4071
+ </details>
4072
+ <details>
4073
+ <summary>Sample Code - Auto Paging</summary>
3538
4074
  ```python
3539
- .. include:: ../docs/include/samplecode/SpotifyClient/GetBrowseCategorysPage.py
4075
+ .. include:: ../docs/include/samplecode/SpotifyClient/GetBrowseCategorys_AutoPaging.py
3540
4076
  ```
3541
4077
  </details>
3542
4078
  """
3543
- apiMethodName:str = 'GetBrowseCategorysPage'
4079
+ apiMethodName:str = 'GetBrowseCategorys'
3544
4080
  apiMethodParms:SIMethodParmListContext = None
3545
4081
  result:CategoryPage = None
3546
4082
 
@@ -3552,13 +4088,24 @@ class SpotifyClient:
3552
4088
  apiMethodParms.AppendKeyValue("offset", offset)
3553
4089
  apiMethodParms.AppendKeyValue("country", country)
3554
4090
  apiMethodParms.AppendKeyValue("locale", locale)
4091
+ apiMethodParms.AppendKeyValue("limitTotal", limitTotal)
3555
4092
  _logsi.LogMethodParmList(SILevel.Verbose, "Get a page of categories used to tag items in Spotify", apiMethodParms)
3556
4093
 
3557
4094
  # validations.
3558
4095
  if limit is None:
3559
- limit = 50
4096
+ limit = 20
3560
4097
  if offset is None:
3561
4098
  offset = 0
4099
+ if not isinstance(limitTotal, int):
4100
+ limitTotal = 0
4101
+
4102
+ # are we auto-paging? if so, then use max limit.
4103
+ if limitTotal > 0:
4104
+ limit = 50
4105
+ #limit = 2 # TEST TODO
4106
+ if limit > limitTotal:
4107
+ limit = limitTotal
4108
+ result = CategoryPage()
3562
4109
 
3563
4110
  # build spotify web api request parameters.
3564
4111
  urlParms:dict = \
@@ -3571,16 +4118,50 @@ class SpotifyClient:
3571
4118
  if locale is not None:
3572
4119
  urlParms['locale'] = str(locale)
3573
4120
 
3574
- # execute spotify web api request.
3575
- msg:SpotifyApiMessage = SpotifyApiMessage(apiMethodName, '/browse/categories')
3576
- msg.RequestHeaders[self.AuthToken.HeaderKey] = self.AuthToken.HeaderValue
3577
- msg.UrlParameters = urlParms
3578
- self.MakeRequest('GET', msg)
4121
+ # handle pagination, as spotify limits us to a set # of items returned per response.
4122
+ while True:
3579
4123
 
3580
- # process results.
3581
- item:dict = msg.ResponseData.get('categories',None)
3582
- if item is not None:
3583
- result = CategoryPage(root=item)
4124
+ # execute spotify web api request.
4125
+ msg:SpotifyApiMessage = SpotifyApiMessage(apiMethodName, '/browse/categories')
4126
+ msg.RequestHeaders[self.AuthToken.HeaderKey] = self.AuthToken.HeaderValue
4127
+ msg.UrlParameters = urlParms
4128
+ self.MakeRequest('GET', msg)
4129
+
4130
+ # process results.
4131
+ item:dict = msg.ResponseData.get('categories',None)
4132
+ if item is not None:
4133
+ pageObj = CategoryPage(root=item)
4134
+
4135
+ # trace.
4136
+ _logsi.LogObject(SILevel.Verbose, (TRACE_METHOD_RESULT_TYPE_PAGE + pageObj.PagingInfo) % (apiMethodName, type(pageObj).__name__), pageObj, excludeNonPublic=True)
4137
+
4138
+ # was limit total argument specified?
4139
+ if (limitTotal <= 0):
4140
+
4141
+ # no - just return the initial page of results.
4142
+ result = pageObj
4143
+ break
4144
+
4145
+ else:
4146
+
4147
+ # append page of items to final results.
4148
+ item:Category
4149
+ for item in pageObj.Items:
4150
+ result.Items.append(item)
4151
+ result.Limit = result.ItemsCount
4152
+ if result.ItemsCount >= limitTotal:
4153
+ break
4154
+
4155
+ # anymore pages to process? if not, then exit the loop.
4156
+ if not self._CheckForNextPage(pageObj, result.ItemsCount, limit, limitTotal, urlParms):
4157
+ break
4158
+
4159
+ # update result object with final paging details.
4160
+ result.Total = pageObj.Total
4161
+
4162
+ # sort items on Name property, ascending order.
4163
+ if len(result.Items) > 0:
4164
+ result.Items.sort(key=lambda x: (x.Name or "").lower(), reverse=False)
3584
4165
 
3585
4166
  # trace.
3586
4167
  _logsi.LogObject(SILevel.Verbose, TRACE_METHOD_RESULT_TYPE % (apiMethodName, type(result).__name__), result, excludeNonPublic=True)
@@ -3599,11 +4180,11 @@ class SpotifyClient:
3599
4180
  _logsi.LeaveMethod(SILevel.Debug, apiMethodName)
3600
4181
 
3601
4182
 
3602
- def GetBrowseCategorys(self,
3603
- country:str=None,
3604
- locale:str=None,
3605
- refresh:bool=True,
3606
- ) -> list[Category]:
4183
+ def GetBrowseCategorysList(self,
4184
+ country:str=None,
4185
+ locale:str=None,
4186
+ refresh:bool=True,
4187
+ ) -> list[Category]:
3607
4188
  """
3608
4189
  Get a sorted list of ALL categories used to tag items in Spotify.
3609
4190
 
@@ -3644,11 +4225,11 @@ class SpotifyClient:
3644
4225
  <details>
3645
4226
  <summary>Sample Code</summary>
3646
4227
  ```python
3647
- .. include:: ../docs/include/samplecode/SpotifyClient/GetBrowseCategorys.py
4228
+ .. include:: ../docs/include/samplecode/SpotifyClient/GetBrowseCategorysList.py
3648
4229
  ```
3649
4230
  </details>
3650
4231
  """
3651
- apiMethodName:str = 'GetBrowseCategorys'
4232
+ apiMethodName:str = 'GetBrowseCategorysList'
3652
4233
  apiMethodParms:SIMethodParmListContext = None
3653
4234
  result:list[Category] = []
3654
4235
  cacheDesc:str = CACHE_SOURCE_CURRENT
@@ -3659,6 +4240,7 @@ class SpotifyClient:
3659
4240
  apiMethodParms = _logsi.EnterMethodParmList(SILevel.Debug, apiMethodName)
3660
4241
  apiMethodParms.AppendKeyValue("country", country)
3661
4242
  apiMethodParms.AppendKeyValue("locale", locale)
4243
+ apiMethodParms.AppendKeyValue("refresh", refresh)
3662
4244
  _logsi.LogMethodParmList(SILevel.Verbose, "Get a sorted list of ALL browse categories", apiMethodParms)
3663
4245
 
3664
4246
  # can we use the cached value?
@@ -3669,29 +4251,14 @@ class SpotifyClient:
3669
4251
 
3670
4252
  else:
3671
4253
 
3672
- # get a page of categories used to tag items in Spotify
3673
- pageObj:CategoryPage = self.GetBrowseCategorysPage(country=country, locale=locale, limit=50)
3674
-
3675
- # handle pagination, as spotify limits us to a set # of items returned per response.
3676
- while True:
3677
-
3678
- # add category details to return list.
3679
- category:Category
3680
- for category in pageObj.Items:
3681
- result.append(category)
3682
-
3683
- # anymore page results?
3684
- if pageObj.Next is None:
3685
- # no - all pages were processed.
3686
- break
3687
- else:
3688
- # yes - retrieve the next page of results.
3689
- pageObj = self.GetBrowseCategorysPage(country=country, locale=locale, offset=pageObj.Offset + pageObj.Limit, limit=pageObj.Limit)
4254
+ # get all categories (return list is already sorted).
4255
+ pageObj:CategoryPage = self.GetBrowseCategorys(country=country, locale=locale, limitTotal=1000)
3690
4256
 
3691
- # sort items on Name property, ascending order.
3692
- if len(result) > 0:
3693
- result.sort(key=lambda x: (x.Name or "").lower(), reverse=False)
3694
-
4257
+ # add category details to return list.
4258
+ category:Category
4259
+ for category in pageObj.Items:
4260
+ result.append(category)
4261
+
3695
4262
  # update cache.
3696
4263
  self._ConfigurationCache[apiMethodName] = result
3697
4264
 
@@ -3717,6 +4284,7 @@ class SpotifyClient:
3717
4284
  limit:int=20,
3718
4285
  offset:int=0,
3719
4286
  country:str=None,
4287
+ limitTotal:int=None
3720
4288
  ) -> Tuple[PlaylistPageSimplified, str]:
3721
4289
  """
3722
4290
  Get a list of Spotify playlists tagged with a particular category.
@@ -3726,10 +4294,10 @@ class SpotifyClient:
3726
4294
  The Spotify category ID for the category.
3727
4295
  Example: `dinner`
3728
4296
  limit (int):
3729
- The maximum number of items to return.
4297
+ The maximum number of items to return in a page of items.
3730
4298
  Default: 20, Range: 1 to 50.
3731
4299
  offset (int):
3732
- The index of the first item to return.
4300
+ The page index offset of the first item to return.
3733
4301
  Use with limit to get the next set of items.
3734
4302
  Default: 0 (the first item).
3735
4303
  country (str):
@@ -3737,6 +4305,12 @@ class SpotifyClient:
3737
4305
  Provide this parameter if you want the list of returned items to be relevant to a
3738
4306
  particular country. If omitted, the returned items will be relevant to all countries.
3739
4307
  Example: `SE`
4308
+ limitTotal (int):
4309
+ The maximum number of items to return for the request.
4310
+ If specified, this argument overrides the limit and offset argument values
4311
+ and paging is automatically used to retrieve all available items up to the
4312
+ maximum number specified.
4313
+ Default: None (disabled)
3740
4314
 
3741
4315
  Returns:
3742
4316
  A tuple of 2 objects:
@@ -3751,11 +4325,17 @@ class SpotifyClient:
3751
4325
  If the method fails for any other reason.
3752
4326
 
3753
4327
  <details>
3754
- <summary>Sample Code</summary>
4328
+ <summary>Sample Code - Manual Paging</summary>
3755
4329
  ```python
3756
4330
  .. include:: ../docs/include/samplecode/SpotifyClient/GetCategoryPlaylists.py
3757
4331
  ```
3758
4332
  </details>
4333
+ <details>
4334
+ <summary>Sample Code - Auto Paging</summary>
4335
+ ```python
4336
+ .. include:: ../docs/include/samplecode/SpotifyClient/GetCategoryPlaylists_AutoPaging.py
4337
+ ```
4338
+ </details>
3759
4339
  """
3760
4340
  apiMethodName:str = 'GetCategoryPlaylists'
3761
4341
  apiMethodParms:SIMethodParmListContext = None
@@ -3770,6 +4350,7 @@ class SpotifyClient:
3770
4350
  apiMethodParms.AppendKeyValue("limit", limit)
3771
4351
  apiMethodParms.AppendKeyValue("offset", offset)
3772
4352
  apiMethodParms.AppendKeyValue("country", country)
4353
+ apiMethodParms.AppendKeyValue("limitTotal", limitTotal)
3773
4354
  _logsi.LogMethodParmList(SILevel.Verbose, "Get a list of Spotify playlists tagged with a particular category", apiMethodParms)
3774
4355
 
3775
4356
  # validations.
@@ -3777,6 +4358,16 @@ class SpotifyClient:
3777
4358
  limit = 20
3778
4359
  if offset is None:
3779
4360
  offset = 0
4361
+ if not isinstance(limitTotal, int):
4362
+ limitTotal = 0
4363
+
4364
+ # are we auto-paging? if so, then use max limit.
4365
+ if limitTotal > 0:
4366
+ limit = 50
4367
+ #limit = 2 # TEST TODO
4368
+ if limit > limitTotal:
4369
+ limit = limitTotal
4370
+ result = PlaylistPageSimplified()
3780
4371
 
3781
4372
  # build spotify web api request parameters.
3782
4373
  urlParms:dict = \
@@ -3788,18 +4379,52 @@ class SpotifyClient:
3788
4379
  if country is not None:
3789
4380
  urlParms['country'] = str(country)
3790
4381
 
3791
- # execute spotify web api request.
3792
- msg:SpotifyApiMessage = SpotifyApiMessage(apiMethodName, '/browse/categories/{category_id}/playlists'.format(category_id=categoryId))
3793
- msg.RequestHeaders[self.AuthToken.HeaderKey] = self.AuthToken.HeaderValue
3794
- msg.UrlParameters = urlParms
3795
- self.MakeRequest('GET', msg)
4382
+ # handle pagination, as spotify limits us to a set # of items returned per response.
4383
+ while True:
3796
4384
 
3797
- # process results.
3798
- resultMessage = msg.ResponseData.get('message','unknown')
3799
- item = msg.ResponseData.get('playlists',None)
3800
- if item is not None:
3801
- result = PlaylistPageSimplified(root=item)
4385
+ # execute spotify web api request.
4386
+ msg:SpotifyApiMessage = SpotifyApiMessage(apiMethodName, '/browse/categories/{category_id}/playlists'.format(category_id=categoryId))
4387
+ msg.RequestHeaders[self.AuthToken.HeaderKey] = self.AuthToken.HeaderValue
4388
+ msg.UrlParameters = urlParms
4389
+ self.MakeRequest('GET', msg)
4390
+
4391
+ # process results.
4392
+ resultMessage = msg.ResponseData.get('message','unknown')
4393
+ item = msg.ResponseData.get('playlists',None)
4394
+ if item is not None:
4395
+ pageObj = PlaylistPageSimplified(root=item)
3802
4396
 
4397
+ # trace.
4398
+ _logsi.LogObject(SILevel.Verbose, (TRACE_METHOD_RESULT_TYPE_PAGE + pageObj.PagingInfo) % (apiMethodName, type(pageObj).__name__), pageObj, excludeNonPublic=True)
4399
+
4400
+ # was limit total argument specified?
4401
+ if (limitTotal <= 0):
4402
+
4403
+ # no - just return the initial page of results.
4404
+ result = pageObj
4405
+ break
4406
+
4407
+ else:
4408
+
4409
+ # append page of items to final results.
4410
+ item:PlaylistSimplified
4411
+ for item in pageObj.Items:
4412
+ result.Items.append(item)
4413
+ result.Limit = result.ItemsCount
4414
+ if result.ItemsCount >= limitTotal:
4415
+ break
4416
+
4417
+ # anymore pages to process? if not, then exit the loop.
4418
+ if not self._CheckForNextPage(pageObj, result.ItemsCount, limit, limitTotal, urlParms):
4419
+ break
4420
+
4421
+ # update result object with final paging details.
4422
+ result.Total = pageObj.Total
4423
+
4424
+ # sort items on Name property, ascending order.
4425
+ if len(result.Items) > 0:
4426
+ result.Items.sort(key=lambda x: (x.Name or "").lower(), reverse=False)
4427
+
3803
4428
  # trace.
3804
4429
  _logsi.LogObject(SILevel.Verbose, (TRACE_METHOD_RESULT_TYPE + result.PagingInfo) % (apiMethodName, type(result).__name__), result, excludeNonPublic=True)
3805
4430
  return result, resultMessage
@@ -3873,6 +4498,9 @@ class SpotifyClient:
3873
4498
  apiMethodParms.AppendKeyValue("market", market)
3874
4499
  _logsi.LogMethodParmList(SILevel.Verbose, "Get Spotify catalog information for a single audiobook chapter", apiMethodParms)
3875
4500
 
4501
+ # ensure market was either supplied or implied; default if neither.
4502
+ market = self._ValidateMarket(market)
4503
+
3876
4504
  # build spotify web api request parameters.
3877
4505
  urlParms:dict = {}
3878
4506
  if market is not None:
@@ -3959,6 +4587,9 @@ class SpotifyClient:
3959
4587
  apiMethodParms.AppendKeyValue("market", market)
3960
4588
  _logsi.LogMethodParmList(SILevel.Verbose, "Get Spotify catalog information for multiple chapters", apiMethodParms)
3961
4589
 
4590
+ # ensure market was either supplied or implied; default if neither.
4591
+ market = self._ValidateMarket(market)
4592
+
3962
4593
  # build spotify web api request parameters.
3963
4594
  urlParms:dict = \
3964
4595
  {
@@ -4051,6 +4682,9 @@ class SpotifyClient:
4051
4682
  apiMethodParms.AppendKeyValue("market", market)
4052
4683
  _logsi.LogMethodParmList(SILevel.Verbose, "Get Spotify catalog information for a single episode", apiMethodParms)
4053
4684
 
4685
+ # ensure market was either supplied or implied; default if neither.
4686
+ market = self._ValidateMarket(market)
4687
+
4054
4688
  # build spotify web api request parameters.
4055
4689
  urlParms:dict = {}
4056
4690
  if market is not None:
@@ -4085,6 +4719,7 @@ class SpotifyClient:
4085
4719
  def GetEpisodeFavorites(self,
4086
4720
  limit:int=20,
4087
4721
  offset:int=0,
4722
+ limitTotal:int=None
4088
4723
  ) -> EpisodePageSaved:
4089
4724
  """
4090
4725
  Get a list of the episodes saved in the current Spotify user's 'Your Library'.
@@ -4093,12 +4728,18 @@ class SpotifyClient:
4093
4728
 
4094
4729
  Args:
4095
4730
  limit (int):
4096
- The maximum number of items to return.
4731
+ The maximum number of items to return in a page of items.
4097
4732
  Default: 20, Range: 1 to 50.
4098
4733
  offset (int):
4099
- The index of the first item to return.
4734
+ The page index offset of the first item to return.
4100
4735
  Use with limit to get the next set of items.
4101
4736
  Default: 0 (the first item).
4737
+ limitTotal (int):
4738
+ The maximum number of items to return for the request.
4739
+ If specified, this argument overrides the limit and offset argument values
4740
+ and paging is automatically used to retrieve all available items up to the
4741
+ maximum number specified.
4742
+ Default: None (disabled)
4102
4743
 
4103
4744
  Returns:
4104
4745
  An `EpisodePageSaved` object that contains saved episode information.
@@ -4111,11 +4752,17 @@ class SpotifyClient:
4111
4752
  If the method fails for any other reason.
4112
4753
 
4113
4754
  <details>
4114
- <summary>Sample Code</summary>
4755
+ <summary>Sample Code - Manual Paging</summary>
4115
4756
  ```python
4116
4757
  .. include:: ../docs/include/samplecode/SpotifyClient/GetEpisodeFavorites.py
4117
4758
  ```
4118
4759
  </details>
4760
+ <details>
4761
+ <summary>Sample Code - Auto Paging</summary>
4762
+ ```python
4763
+ .. include:: ../docs/include/samplecode/SpotifyClient/GetEpisodeFavorites_AutoPaging.py
4764
+ ```
4765
+ </details>
4119
4766
  """
4120
4767
  apiMethodName:str = 'GetEpisodeFavorites'
4121
4768
  apiMethodParms:SIMethodParmListContext = None
@@ -4127,6 +4774,7 @@ class SpotifyClient:
4127
4774
  apiMethodParms = _logsi.EnterMethodParmList(SILevel.Debug, apiMethodName)
4128
4775
  apiMethodParms.AppendKeyValue("limit", limit)
4129
4776
  apiMethodParms.AppendKeyValue("offset", offset)
4777
+ apiMethodParms.AppendKeyValue("limitTotal", limitTotal)
4130
4778
  _logsi.LogMethodParmList(SILevel.Verbose, "Get a list of the users episode favorites", apiMethodParms)
4131
4779
 
4132
4780
  # validations.
@@ -4134,6 +4782,16 @@ class SpotifyClient:
4134
4782
  limit = 20
4135
4783
  if offset is None:
4136
4784
  offset = 0
4785
+ if not isinstance(limitTotal, int):
4786
+ limitTotal = 0
4787
+
4788
+ # are we auto-paging? if so, then use max limit.
4789
+ if limitTotal > 0:
4790
+ limit = 50
4791
+ #limit = 1 # TEST TODO
4792
+ if limit > limitTotal:
4793
+ limit = limitTotal
4794
+ result = EpisodePageSaved()
4137
4795
 
4138
4796
  # build spotify web api request parameters.
4139
4797
  urlParms:dict = \
@@ -4142,14 +4800,48 @@ class SpotifyClient:
4142
4800
  'offset': offset,
4143
4801
  }
4144
4802
 
4145
- # execute spotify web api request.
4146
- msg:SpotifyApiMessage = SpotifyApiMessage(apiMethodName, '/me/episodes')
4147
- msg.RequestHeaders[self.AuthToken.HeaderKey] = self.AuthToken.HeaderValue
4148
- msg.UrlParameters = urlParms
4149
- self.MakeRequest('GET', msg)
4803
+ # handle pagination, as spotify limits us to a set # of items returned per response.
4804
+ while True:
4150
4805
 
4151
- # process results.
4152
- result = EpisodePageSaved(root=msg.ResponseData)
4806
+ # execute spotify web api request.
4807
+ msg:SpotifyApiMessage = SpotifyApiMessage(apiMethodName, '/me/episodes')
4808
+ msg.RequestHeaders[self.AuthToken.HeaderKey] = self.AuthToken.HeaderValue
4809
+ msg.UrlParameters = urlParms
4810
+ self.MakeRequest('GET', msg)
4811
+
4812
+ # process results.
4813
+ pageObj = EpisodePageSaved(root=msg.ResponseData)
4814
+
4815
+ # trace.
4816
+ _logsi.LogObject(SILevel.Verbose, (TRACE_METHOD_RESULT_TYPE_PAGE + pageObj.PagingInfo) % (apiMethodName, type(pageObj).__name__), pageObj, excludeNonPublic=True)
4817
+
4818
+ # was limit total argument specified?
4819
+ if (limitTotal <= 0):
4820
+
4821
+ # no - just return the initial page of results.
4822
+ result = pageObj
4823
+ break
4824
+
4825
+ else:
4826
+
4827
+ # append page of items to final results.
4828
+ item:EpisodeSaved
4829
+ for item in pageObj.Items:
4830
+ result.Items.append(item)
4831
+ result.Limit = result.ItemsCount
4832
+ if result.ItemsCount >= limitTotal:
4833
+ break
4834
+
4835
+ # anymore pages to process? if not, then exit the loop.
4836
+ if not self._CheckForNextPage(pageObj, result.ItemsCount, limit, limitTotal, urlParms):
4837
+ break
4838
+
4839
+ # update result object with final paging details.
4840
+ result.Total = pageObj.Total
4841
+
4842
+ # sort items on Name property, ascending order.
4843
+ if len(result.Items) > 0:
4844
+ result.Items.sort(key=lambda x: (x.Episode.Name or "").lower(), reverse=False)
4153
4845
 
4154
4846
  # trace.
4155
4847
  _logsi.LogObject(SILevel.Verbose, (TRACE_METHOD_RESULT_TYPE + result.PagingInfo) % (apiMethodName, type(result).__name__), result, excludeNonPublic=True)
@@ -4223,6 +4915,9 @@ class SpotifyClient:
4223
4915
  apiMethodParms.AppendKeyValue("market", market)
4224
4916
  _logsi.LogMethodParmList(SILevel.Verbose, "Get Spotify catalog information for multiple episodes", apiMethodParms)
4225
4917
 
4918
+ # ensure market was either supplied or implied; default if neither.
4919
+ market = self._ValidateMarket(market)
4920
+
4226
4921
  # build spotify web api request parameters.
4227
4922
  urlParms:dict = \
4228
4923
  {
@@ -4264,17 +4959,18 @@ class SpotifyClient:
4264
4959
  offset:int=0,
4265
4960
  country:str=None,
4266
4961
  locale:str=None,
4267
- timestamp:str=None
4962
+ timestamp:str=None,
4963
+ limitTotal:int=None
4268
4964
  ) -> Tuple[PlaylistPageSimplified, str]:
4269
4965
  """
4270
4966
  Get a list of Spotify featured playlists (shown, for example, on a Spotify player's 'Browse' tab).
4271
4967
 
4272
4968
  Args:
4273
4969
  limit (int):
4274
- The maximum number of items to return.
4970
+ The maximum number of items to return in a page of items.
4275
4971
  Default: 20, Range: 1 to 50.
4276
4972
  offset (int):
4277
- The index of the first item to return.
4973
+ The page index offset of the first item to return.
4278
4974
  Use with limit to get the next set of items.
4279
4975
  Default: 0 (the first item).
4280
4976
  country (str):
@@ -4300,6 +4996,12 @@ class SpotifyClient:
4300
4996
  If there were no featured playlists (or there is no data) at the specified time, the response will
4301
4997
  revert to the current UTC time.
4302
4998
  Example: `2023-10-23T09:00:00`
4999
+ limitTotal (int):
5000
+ The maximum number of items to return for the request.
5001
+ If specified, this argument overrides the limit and offset argument values
5002
+ and paging is automatically used to retrieve all available items up to the
5003
+ maximum number specified.
5004
+ Default: None (disabled)
4303
5005
 
4304
5006
  Returns:
4305
5007
  A tuple of 2 objects:
@@ -4314,11 +5016,17 @@ class SpotifyClient:
4314
5016
  If the method fails for any other reason.
4315
5017
 
4316
5018
  <details>
4317
- <summary>Sample Code</summary>
5019
+ <summary>Sample Code - Manual Paging</summary>
4318
5020
  ```python
4319
5021
  .. include:: ../docs/include/samplecode/SpotifyClient/GetFeaturedPlaylists.py
4320
5022
  ```
4321
5023
  </details>
5024
+ <details>
5025
+ <summary>Sample Code - Auto Paging</summary>
5026
+ ```python
5027
+ .. include:: ../docs/include/samplecode/SpotifyClient/GetFeaturedPlaylists_AutoPaging.py
5028
+ ```
5029
+ </details>
4322
5030
  """
4323
5031
  apiMethodName:str = 'GetFeaturedPlaylists'
4324
5032
  apiMethodParms:SIMethodParmListContext = None
@@ -4334,6 +5042,7 @@ class SpotifyClient:
4334
5042
  apiMethodParms.AppendKeyValue("country", country)
4335
5043
  apiMethodParms.AppendKeyValue("locale", locale)
4336
5044
  apiMethodParms.AppendKeyValue("timestamp", timestamp)
5045
+ apiMethodParms.AppendKeyValue("limitTotal", limitTotal)
4337
5046
  _logsi.LogMethodParmList(SILevel.Verbose, "Get a list of Spotify featured playlists", apiMethodParms)
4338
5047
 
4339
5048
  # validations.
@@ -4341,6 +5050,16 @@ class SpotifyClient:
4341
5050
  limit = 20
4342
5051
  if offset is None:
4343
5052
  offset = 0
5053
+ if not isinstance(limitTotal, int):
5054
+ limitTotal = 0
5055
+
5056
+ # are we auto-paging? if so, then use max limit.
5057
+ if limitTotal > 0:
5058
+ limit = 50
5059
+ #limit = 2 # TEST TODO
5060
+ if limit > limitTotal:
5061
+ limit = limitTotal
5062
+ result = PlaylistPageSimplified()
4344
5063
 
4345
5064
  # build spotify web api request parameters.
4346
5065
  urlParms:dict = \
@@ -4355,18 +5074,52 @@ class SpotifyClient:
4355
5074
  if timestamp is not None:
4356
5075
  urlParms['timestamp'] = timestamp
4357
5076
 
4358
- # execute spotify web api request.
4359
- msg:SpotifyApiMessage = SpotifyApiMessage(apiMethodName, '/browse/featured-playlists')
4360
- msg.RequestHeaders[self.AuthToken.HeaderKey] = self.AuthToken.HeaderValue
4361
- msg.UrlParameters = urlParms
4362
- self.MakeRequest('GET', msg)
5077
+ # handle pagination, as spotify limits us to a set # of items returned per response.
5078
+ while True:
4363
5079
 
4364
- # process results.
4365
- resultMessage = msg.ResponseData.get('message','unknown')
4366
- item = msg.ResponseData.get('playlists',None)
4367
- if item is not None:
4368
- result = PlaylistPageSimplified(root=item)
5080
+ # execute spotify web api request.
5081
+ msg:SpotifyApiMessage = SpotifyApiMessage(apiMethodName, '/browse/featured-playlists')
5082
+ msg.RequestHeaders[self.AuthToken.HeaderKey] = self.AuthToken.HeaderValue
5083
+ msg.UrlParameters = urlParms
5084
+ self.MakeRequest('GET', msg)
5085
+
5086
+ # process results.
5087
+ resultMessage = msg.ResponseData.get('message','unknown')
5088
+ item = msg.ResponseData.get('playlists',None)
5089
+ if item is not None:
5090
+ pageObj = PlaylistPageSimplified(root=item)
4369
5091
 
5092
+ # trace.
5093
+ _logsi.LogObject(SILevel.Verbose, (TRACE_METHOD_RESULT_TYPE_PAGE + pageObj.PagingInfo) % (apiMethodName, type(pageObj).__name__), pageObj, excludeNonPublic=True)
5094
+
5095
+ # was limit total argument specified?
5096
+ if (limitTotal <= 0):
5097
+
5098
+ # no - just return the initial page of results.
5099
+ result = pageObj
5100
+ break
5101
+
5102
+ else:
5103
+
5104
+ # append page of items to final results.
5105
+ item:PlaylistSimplified
5106
+ for item in pageObj.Items:
5107
+ result.Items.append(item)
5108
+ result.Limit = result.ItemsCount
5109
+ if result.ItemsCount >= limitTotal:
5110
+ break
5111
+
5112
+ # anymore pages to process? if not, then exit the loop.
5113
+ if not self._CheckForNextPage(pageObj, result.ItemsCount, limit, limitTotal, urlParms):
5114
+ break
5115
+
5116
+ # update result object with final paging details.
5117
+ result.Total = pageObj.Total
5118
+
5119
+ # sort items on Name property, ascending order.
5120
+ if len(result.Items) > 0:
5121
+ result.Items.sort(key=lambda x: (x.Name or "").lower(), reverse=False)
5122
+
4370
5123
  # trace.
4371
5124
  _logsi.LogObject(SILevel.Verbose, (TRACE_METHOD_RESULT_TYPE + result.PagingInfo) % (apiMethodName, type(result).__name__), result, excludeNonPublic=True)
4372
5125
  return result, resultMessage
@@ -4813,6 +5566,9 @@ class SpotifyClient:
4813
5566
  apiMethodParms.AppendKeyValue("market", market)
4814
5567
  _logsi.LogMethodParmList(SILevel.Verbose, "Get the object currently being played on the user's Spotify account", apiMethodParms)
4815
5568
 
5569
+ # ensure market was either supplied or implied; default if neither.
5570
+ market = self._ValidateMarket(market)
5571
+
4816
5572
  # build spotify web api request parameters.
4817
5573
  urlParms:dict = {}
4818
5574
  if market is not None:
@@ -4901,6 +5657,9 @@ class SpotifyClient:
4901
5657
  apiMethodParms.AppendKeyValue("market", market)
4902
5658
  _logsi.LogMethodParmList(SILevel.Verbose, "Get the user's current playback state", apiMethodParms)
4903
5659
 
5660
+ # ensure market was either supplied or implied; default if neither.
5661
+ market = self._ValidateMarket(market)
5662
+
4904
5663
  # build spotify web api request parameters.
4905
5664
  urlParms:dict = {}
4906
5665
  if market is not None:
@@ -5004,7 +5763,7 @@ class SpotifyClient:
5004
5763
 
5005
5764
  Args:
5006
5765
  limit (int):
5007
- The maximum number of items to return.
5766
+ The maximum number of items to return in a page of items.
5008
5767
  Default: `20`, Range: `1` to `50`.
5009
5768
  after (int):
5010
5769
  Returns all items after (but not including) this cursor position, which is
@@ -5187,6 +5946,9 @@ class SpotifyClient:
5187
5946
  apiMethodParms.AppendKeyValue("additionalTypes", additionalTypes)
5188
5947
  _logsi.LogMethodParmList(SILevel.Verbose, "Get a playlist owned by a Spotify user", apiMethodParms)
5189
5948
 
5949
+ # ensure market was either supplied or implied; default if neither.
5950
+ market = self._ValidateMarket(market)
5951
+
5190
5952
  # build spotify web api request parameters.
5191
5953
  urlParms:dict = {}
5192
5954
  if market is not None:
@@ -5296,7 +6058,8 @@ class SpotifyClient:
5296
6058
  offset:int=0,
5297
6059
  market:str=None,
5298
6060
  fields:str=None,
5299
- additionalTypes:str=None
6061
+ additionalTypes:str=None,
6062
+ limitTotal:int=None
5300
6063
  ) -> PlaylistPage:
5301
6064
  """
5302
6065
  Get full details of the items of a playlist owned by a Spotify user.
@@ -5308,10 +6071,10 @@ class SpotifyClient:
5308
6071
  The Spotify ID of the playlist.
5309
6072
  Example: `5v5ETK9WFXAnGQ3MRubKuE`
5310
6073
  limit (int):
5311
- The maximum number of items to return.
6074
+ The maximum number of items to return in a page of items.
5312
6075
  Default: 50, Range: 1 to 50.
5313
6076
  offset (int):
5314
- The index of the first item to return.
6077
+ The page index offset of the first item to return.
5315
6078
  Use with limit to get the next set of items.
5316
6079
  Default: 0 (the first item).
5317
6080
  market (str):
@@ -5342,6 +6105,12 @@ class SpotifyClient:
5342
6105
  Note: This parameter was introduced to allow existing clients to maintain their current behaviour
5343
6106
  and might be deprecated in the future. In addition to providing this parameter, make sure that your
5344
6107
  client properly handles cases of new types in the future by checking against the type field of each object.
6108
+ limitTotal (int):
6109
+ The maximum number of items to return for the request.
6110
+ If specified, this argument overrides the limit and offset argument values
6111
+ and paging is automatically used to retrieve all available items up to the
6112
+ maximum number specified.
6113
+ Default: None (disabled)
5345
6114
 
5346
6115
  Returns:
5347
6116
  A `Playlist` object that contains the playlist details.
@@ -5354,11 +6123,17 @@ class SpotifyClient:
5354
6123
  If the method fails for any other reason.
5355
6124
 
5356
6125
  <details>
5357
- <summary>Sample Code</summary>
6126
+ <summary>Sample Code - Manual Paging</summary>
5358
6127
  ```python
5359
6128
  .. include:: ../docs/include/samplecode/SpotifyClient/GetPlaylistItems.py
5360
6129
  ```
5361
6130
  </details>
6131
+ <details>
6132
+ <summary>Sample Code - Auto Paging</summary>
6133
+ ```python
6134
+ .. include:: ../docs/include/samplecode/SpotifyClient/GetPlaylistItems_AutoPaging.py
6135
+ ```
6136
+ </details>
5362
6137
  """
5363
6138
  apiMethodName:str = 'GetPlaylistItems'
5364
6139
  apiMethodParms:SIMethodParmListContext = None
@@ -5374,6 +6149,7 @@ class SpotifyClient:
5374
6149
  apiMethodParms.AppendKeyValue("market", market)
5375
6150
  apiMethodParms.AppendKeyValue("fields", fields)
5376
6151
  apiMethodParms.AppendKeyValue("additionalTypes", additionalTypes)
6152
+ apiMethodParms.AppendKeyValue("limitTotal", limitTotal)
5377
6153
  _logsi.LogMethodParmList(SILevel.Verbose, "Get full details of the items of a playlist owned by a Spotify user", apiMethodParms)
5378
6154
 
5379
6155
  # validations.
@@ -5381,6 +6157,19 @@ class SpotifyClient:
5381
6157
  limit = 20
5382
6158
  if offset is None:
5383
6159
  offset = 0
6160
+ if not isinstance(limitTotal, int):
6161
+ limitTotal = 0
6162
+
6163
+ # are we auto-paging? if so, then use max limit.
6164
+ if limitTotal > 0:
6165
+ limit = 50
6166
+ #limit = 2 # TEST TODO
6167
+ if limit > limitTotal:
6168
+ limit = limitTotal
6169
+ result = PlaylistPage()
6170
+
6171
+ # ensure market was either supplied or implied; default if neither.
6172
+ market = self._ValidateMarket(market)
5384
6173
 
5385
6174
  # build spotify web api request parameters.
5386
6175
  urlParms:dict = \
@@ -5395,17 +6184,49 @@ class SpotifyClient:
5395
6184
  if additionalTypes is not None:
5396
6185
  urlParms['additional_types'] = additionalTypes
5397
6186
 
5398
- # execute spotify web api request.
5399
- msg:SpotifyApiMessage = SpotifyApiMessage(apiMethodName, '/playlists/{id}/tracks'.format(id=playlistId))
5400
- msg.RequestHeaders[self.AuthToken.HeaderKey] = self.AuthToken.HeaderValue
5401
- msg.UrlParameters = urlParms
5402
- self.MakeRequest('GET', msg)
6187
+ # handle pagination, as spotify limits us to a set # of items returned per response.
6188
+ while True:
5403
6189
 
5404
- # process results.
5405
- result = PlaylistPage(root=msg.ResponseData)
5406
-
6190
+ # execute spotify web api request.
6191
+ msg:SpotifyApiMessage = SpotifyApiMessage(apiMethodName, '/playlists/{id}/tracks'.format(id=playlistId))
6192
+ msg.RequestHeaders[self.AuthToken.HeaderKey] = self.AuthToken.HeaderValue
6193
+ msg.UrlParameters = urlParms
6194
+ self.MakeRequest('GET', msg)
6195
+
6196
+ # process results.
6197
+ pageObj = PlaylistPage(root=msg.ResponseData)
6198
+
6199
+ # trace.
6200
+ _logsi.LogObject(SILevel.Verbose, (TRACE_METHOD_RESULT_TYPE_PAGE + pageObj.PagingInfo) % (apiMethodName, type(pageObj).__name__), pageObj, excludeNonPublic=True)
6201
+
6202
+ # was limit total argument specified?
6203
+ if (limitTotal <= 0):
6204
+
6205
+ # no - just return the initial page of results.
6206
+ result = pageObj
6207
+ break
6208
+
6209
+ else:
6210
+
6211
+ # append page of items to final results.
6212
+ item:PlaylistTrack
6213
+ for item in pageObj.Items:
6214
+ result.Items.append(item)
6215
+ result.Limit = result.ItemsCount
6216
+ if result.ItemsCount >= limitTotal:
6217
+ break
6218
+
6219
+ # anymore pages to process? if not, then exit the loop.
6220
+ if not self._CheckForNextPage(pageObj, result.ItemsCount, limit, limitTotal, urlParms):
6221
+ break
6222
+
6223
+ # update result object with final paging details.
6224
+ result.Total = pageObj.Total
6225
+
6226
+ # do not sort this list, as it is in play order.
6227
+
5407
6228
  # trace.
5408
- _logsi.LogObject(SILevel.Verbose, TRACE_METHOD_RESULT_TYPE % (apiMethodName, type(result).__name__), result, excludeNonPublic=True)
6229
+ _logsi.LogObject(SILevel.Verbose, (TRACE_METHOD_RESULT_TYPE + result.PagingInfo) % (apiMethodName, type(result).__name__), result, excludeNonPublic=True)
5409
6230
  return result
5410
6231
 
5411
6232
  except SpotifyWebApiError: raise # pass handled exceptions on thru
@@ -5424,6 +6245,7 @@ class SpotifyClient:
5424
6245
  def GetPlaylistFavorites(self,
5425
6246
  limit:int=20,
5426
6247
  offset:int=0,
6248
+ limitTotal:int=None
5427
6249
  ) -> PlaylistPageSimplified:
5428
6250
  """
5429
6251
  Get a list of the playlists owned or followed by the current Spotify user.
@@ -5432,12 +6254,18 @@ class SpotifyClient:
5432
6254
 
5433
6255
  Args:
5434
6256
  limit (int):
5435
- The maximum number of items to return.
6257
+ The maximum number of items to return in a page of items.
5436
6258
  Default: 20, Range: 1 to 50.
5437
6259
  offset (int):
5438
- The index of the first item to return.
6260
+ The page index offset of the first item to return.
5439
6261
  Use with limit to get the next set of items.
5440
6262
  Default: 0 (the first item).
6263
+ limitTotal (int):
6264
+ The maximum number of items to return for the request.
6265
+ If specified, this argument overrides the limit and offset argument values
6266
+ and paging is automatically used to retrieve all available items up to the
6267
+ maximum number specified.
6268
+ Default: None (disabled)
5441
6269
 
5442
6270
  Returns:
5443
6271
  An `PlaylistPageSimplified` object that contains playlist information.
@@ -5450,11 +6278,17 @@ class SpotifyClient:
5450
6278
  If the method fails for any other reason.
5451
6279
 
5452
6280
  <details>
5453
- <summary>Sample Code</summary>
6281
+ <summary>Sample Code - Manual Paging</summary>
5454
6282
  ```python
5455
6283
  .. include:: ../docs/include/samplecode/SpotifyClient/GetPlaylistFavorites.py
5456
6284
  ```
5457
6285
  </details>
6286
+ <details>
6287
+ <summary>Sample Code - Auto Paging</summary>
6288
+ ```python
6289
+ .. include:: ../docs/include/samplecode/SpotifyClient/GetPlaylistFavorites_AutoPaging.py
6290
+ ```
6291
+ </details>
5458
6292
  """
5459
6293
  apiMethodName:str = 'GetPlaylistFavorites'
5460
6294
  apiMethodParms:SIMethodParmListContext = None
@@ -5466,6 +6300,7 @@ class SpotifyClient:
5466
6300
  apiMethodParms = _logsi.EnterMethodParmList(SILevel.Debug, apiMethodName)
5467
6301
  apiMethodParms.AppendKeyValue("limit", limit)
5468
6302
  apiMethodParms.AppendKeyValue("offset", offset)
6303
+ apiMethodParms.AppendKeyValue("limitTotal", limitTotal)
5469
6304
  _logsi.LogMethodParmList(SILevel.Verbose, "Get a list of the users playlist favorites", apiMethodParms)
5470
6305
 
5471
6306
  # validations.
@@ -5473,6 +6308,16 @@ class SpotifyClient:
5473
6308
  limit = 20
5474
6309
  if offset is None:
5475
6310
  offset = 0
6311
+ if not isinstance(limitTotal, int):
6312
+ limitTotal = 0
6313
+
6314
+ # are we auto-paging? if so, then use max limit.
6315
+ if limitTotal > 0:
6316
+ limit = 50
6317
+ #limit = 2 # TEST TODO
6318
+ if limit > limitTotal:
6319
+ limit = limitTotal
6320
+ result = PlaylistPageSimplified()
5476
6321
 
5477
6322
  # build spotify web api request parameters.
5478
6323
  urlParms:dict = \
@@ -5481,14 +6326,48 @@ class SpotifyClient:
5481
6326
  'offset': offset,
5482
6327
  }
5483
6328
 
5484
- # execute spotify web api request.
5485
- msg:SpotifyApiMessage = SpotifyApiMessage(apiMethodName, '/me/playlists')
5486
- msg.RequestHeaders[self.AuthToken.HeaderKey] = self.AuthToken.HeaderValue
5487
- msg.UrlParameters = urlParms
5488
- self.MakeRequest('GET', msg)
6329
+ # handle pagination, as spotify limits us to a set # of items returned per response.
6330
+ while True:
5489
6331
 
5490
- # process results.
5491
- result = PlaylistPageSimplified(root=msg.ResponseData)
6332
+ # execute spotify web api request.
6333
+ msg:SpotifyApiMessage = SpotifyApiMessage(apiMethodName, '/me/playlists')
6334
+ msg.RequestHeaders[self.AuthToken.HeaderKey] = self.AuthToken.HeaderValue
6335
+ msg.UrlParameters = urlParms
6336
+ self.MakeRequest('GET', msg)
6337
+
6338
+ # process results.
6339
+ pageObj = PlaylistPageSimplified(root=msg.ResponseData)
6340
+
6341
+ # trace.
6342
+ _logsi.LogObject(SILevel.Verbose, (TRACE_METHOD_RESULT_TYPE_PAGE + pageObj.PagingInfo) % (apiMethodName, type(pageObj).__name__), pageObj, excludeNonPublic=True)
6343
+
6344
+ # was limit total argument specified?
6345
+ if (limitTotal <= 0):
6346
+
6347
+ # no - just return the initial page of results.
6348
+ result = pageObj
6349
+ break
6350
+
6351
+ else:
6352
+
6353
+ # append page of items to final results.
6354
+ item:PlaylistSimplified
6355
+ for item in pageObj.Items:
6356
+ result.Items.append(item)
6357
+ result.Limit = result.ItemsCount
6358
+ if result.ItemsCount >= limitTotal:
6359
+ break
6360
+
6361
+ # anymore pages to process? if not, then exit the loop.
6362
+ if not self._CheckForNextPage(pageObj, result.ItemsCount, limit, limitTotal, urlParms):
6363
+ break
6364
+
6365
+ # update result object with final paging details.
6366
+ result.Total = pageObj.Total
6367
+
6368
+ # sort items on Name property, ascending order.
6369
+ if len(result.Items) > 0:
6370
+ result.Items.sort(key=lambda x: (x.Name or "").lower(), reverse=False)
5492
6371
 
5493
6372
  # trace.
5494
6373
  _logsi.LogObject(SILevel.Verbose, (TRACE_METHOD_RESULT_TYPE + result.PagingInfo) % (apiMethodName, type(result).__name__), result, excludeNonPublic=True)
@@ -5511,6 +6390,7 @@ class SpotifyClient:
5511
6390
  userId:str,
5512
6391
  limit:int=20,
5513
6392
  offset:int=0,
6393
+ limitTotal:int=None
5514
6394
  ) -> PlaylistPageSimplified:
5515
6395
  """
5516
6396
  Get a list of the playlists owned or followed by a Spotify user.
@@ -5522,12 +6402,18 @@ class SpotifyClient:
5522
6402
  The user's Spotify user ID.
5523
6403
  Example: `smedjan`
5524
6404
  limit (int):
5525
- The maximum number of items to return.
6405
+ The maximum number of items to return in a page of items.
5526
6406
  Default: 20, Range: 1 to 50.
5527
6407
  offset (int):
5528
- The index of the first item to return.
6408
+ The page index offset of the first item to return.
5529
6409
  Use with limit to get the next set of items.
5530
6410
  Default: 0 (the first item).
6411
+ limitTotal (int):
6412
+ The maximum number of items to return for the request.
6413
+ If specified, this argument overrides the limit and offset argument values
6414
+ and paging is automatically used to retrieve all available items up to the
6415
+ maximum number specified.
6416
+ Default: None (disabled)
5531
6417
 
5532
6418
  Returns:
5533
6419
  An `PlaylistPageSimplified` object that contains playlist information.
@@ -5540,11 +6426,17 @@ class SpotifyClient:
5540
6426
  If the method fails for any other reason.
5541
6427
 
5542
6428
  <details>
5543
- <summary>Sample Code</summary>
6429
+ <summary>Sample Code - Manual Paging</summary>
5544
6430
  ```python
5545
6431
  .. include:: ../docs/include/samplecode/SpotifyClient/GetPlaylistsForUser.py
5546
6432
  ```
5547
6433
  </details>
6434
+ <details>
6435
+ <summary>Sample Code - Auto Paging</summary>
6436
+ ```python
6437
+ .. include:: ../docs/include/samplecode/SpotifyClient/GetPlaylistsForUser_AutoPaging.py
6438
+ ```
6439
+ </details>
5548
6440
  """
5549
6441
  apiMethodName:str = 'GetPlaylistsForUser'
5550
6442
  apiMethodParms:SIMethodParmListContext = None
@@ -5557,6 +6449,7 @@ class SpotifyClient:
5557
6449
  apiMethodParms.AppendKeyValue("userId", userId)
5558
6450
  apiMethodParms.AppendKeyValue("limit", limit)
5559
6451
  apiMethodParms.AppendKeyValue("offset", offset)
6452
+ apiMethodParms.AppendKeyValue("limitTotal", limitTotal)
5560
6453
  _logsi.LogMethodParmList(SILevel.Verbose, "Get a list of the playlists owned or followed by a Spotify user", apiMethodParms)
5561
6454
 
5562
6455
  # validations.
@@ -5564,6 +6457,16 @@ class SpotifyClient:
5564
6457
  limit = 20
5565
6458
  if offset is None:
5566
6459
  offset = 0
6460
+ if not isinstance(limitTotal, int):
6461
+ limitTotal = 0
6462
+
6463
+ # are we auto-paging? if so, then use max limit.
6464
+ if limitTotal > 0:
6465
+ limit = 50
6466
+ #limit = 2 # TEST TODO
6467
+ if limit > limitTotal:
6468
+ limit = limitTotal
6469
+ result = PlaylistPageSimplified()
5567
6470
 
5568
6471
  # build spotify web api request parameters.
5569
6472
  urlParms:dict = \
@@ -5573,14 +6476,48 @@ class SpotifyClient:
5573
6476
  'offset': offset,
5574
6477
  }
5575
6478
 
5576
- # execute spotify web api request.
5577
- msg:SpotifyApiMessage = SpotifyApiMessage(apiMethodName, '/users/{user_id}/playlists'.format(user_id=userId))
5578
- msg.RequestHeaders[self.AuthToken.HeaderKey] = self.AuthToken.HeaderValue
5579
- msg.UrlParameters = urlParms
5580
- self.MakeRequest('GET', msg)
6479
+ # handle pagination, as spotify limits us to a set # of items returned per response.
6480
+ while True:
5581
6481
 
5582
- # process results.
5583
- result = PlaylistPageSimplified(root=msg.ResponseData)
6482
+ # execute spotify web api request.
6483
+ msg:SpotifyApiMessage = SpotifyApiMessage(apiMethodName, '/users/{user_id}/playlists'.format(user_id=userId))
6484
+ msg.RequestHeaders[self.AuthToken.HeaderKey] = self.AuthToken.HeaderValue
6485
+ msg.UrlParameters = urlParms
6486
+ self.MakeRequest('GET', msg)
6487
+
6488
+ # process results.
6489
+ pageObj = PlaylistPageSimplified(root=msg.ResponseData)
6490
+
6491
+ # trace.
6492
+ _logsi.LogObject(SILevel.Verbose, (TRACE_METHOD_RESULT_TYPE_PAGE + pageObj.PagingInfo) % (apiMethodName, type(pageObj).__name__), pageObj, excludeNonPublic=True)
6493
+
6494
+ # was limit total argument specified?
6495
+ if (limitTotal <= 0):
6496
+
6497
+ # no - just return the initial page of results.
6498
+ result = pageObj
6499
+ break
6500
+
6501
+ else:
6502
+
6503
+ # append page of items to final results.
6504
+ item:PlaylistSimplified
6505
+ for item in pageObj.Items:
6506
+ result.Items.append(item)
6507
+ result.Limit = result.ItemsCount
6508
+ if result.ItemsCount >= limitTotal:
6509
+ break
6510
+
6511
+ # anymore pages to process? if not, then exit the loop.
6512
+ if not self._CheckForNextPage(pageObj, result.ItemsCount, limit, limitTotal, urlParms):
6513
+ break
6514
+
6515
+ # update result object with final paging details.
6516
+ result.Total = pageObj.Total
6517
+
6518
+ # sort items on Name property, ascending order.
6519
+ if len(result.Items) > 0:
6520
+ result.Items.sort(key=lambda x: (x.Name or "").lower(), reverse=False)
5584
6521
 
5585
6522
  # trace.
5586
6523
  _logsi.LogObject(SILevel.Verbose, (TRACE_METHOD_RESULT_TYPE + result.PagingInfo) % (apiMethodName, type(result).__name__), result, excludeNonPublic=True)
@@ -5653,6 +6590,9 @@ class SpotifyClient:
5653
6590
  apiMethodParms.AppendKeyValue("market", market)
5654
6591
  _logsi.LogMethodParmList(SILevel.Verbose, "Get Spotify catalog information for a single show", apiMethodParms)
5655
6592
 
6593
+ # ensure market was either supplied or implied; default if neither.
6594
+ market = self._ValidateMarket(market)
6595
+
5656
6596
  # build spotify web api request parameters.
5657
6597
  urlParms:dict = {}
5658
6598
  if market is not None:
@@ -5688,7 +6628,8 @@ class SpotifyClient:
5688
6628
  showId:str,
5689
6629
  limit:int=20,
5690
6630
  offset:int=0,
5691
- market:str=None
6631
+ market:str=None,
6632
+ limitTotal:int=None
5692
6633
  ) -> EpisodePageSimplified:
5693
6634
  """
5694
6635
  Get Spotify catalog information about a show's episodes.
@@ -5700,7 +6641,7 @@ class SpotifyClient:
5700
6641
  The Spotify ID for the show.
5701
6642
  Example: `38bS44xjbVVZ3No3ByF1dJ`
5702
6643
  limit (int):
5703
- The maximum number of items to return.
6644
+ The maximum number of items to return in a page of items.
5704
6645
  Default: 20, Range: 1 to 50.
5705
6646
  offset (int):
5706
6647
  The index of the first item to return; use with limit to get the next set of items.
@@ -5713,6 +6654,12 @@ class SpotifyClient:
5713
6654
  Note: If neither market or user country are provided, the content is considered unavailable for the client.
5714
6655
  Users can view the country that is associated with their account in the account settings.
5715
6656
  Example: `ES`
6657
+ limitTotal (int):
6658
+ The maximum number of items to return for the request.
6659
+ If specified, this argument overrides the limit and offset argument values
6660
+ and paging is automatically used to retrieve all available items up to the
6661
+ maximum number specified.
6662
+ Default: None (disabled)
5716
6663
 
5717
6664
  Returns:
5718
6665
  A `EpisodePageSimplified` object that contains simplified track information for the showId.
@@ -5725,11 +6672,17 @@ class SpotifyClient:
5725
6672
  If the method fails for any other reason.
5726
6673
 
5727
6674
  <details>
5728
- <summary>Sample Code</summary>
6675
+ <summary>Sample Code - Manual Paging</summary>
5729
6676
  ```python
5730
6677
  .. include:: ../docs/include/samplecode/SpotifyClient/GetShowEpisodes.py
5731
6678
  ```
5732
6679
  </details>
6680
+ <details>
6681
+ <summary>Sample Code - Auto Paging</summary>
6682
+ ```python
6683
+ .. include:: ../docs/include/samplecode/SpotifyClient/GetShowEpisodes_AutoPaging.py
6684
+ ```
6685
+ </details>
5733
6686
  """
5734
6687
  apiMethodName:str = 'GetShowEpisodes'
5735
6688
  apiMethodParms:SIMethodParmListContext = None
@@ -5743,6 +6696,7 @@ class SpotifyClient:
5743
6696
  apiMethodParms.AppendKeyValue("limit", limit)
5744
6697
  apiMethodParms.AppendKeyValue("offset", offset)
5745
6698
  apiMethodParms.AppendKeyValue("market", market)
6699
+ apiMethodParms.AppendKeyValue("limitTotal", limitTotal)
5746
6700
  _logsi.LogMethodParmList(SILevel.Verbose, "Get Spotify catalog information about a show's episodes", apiMethodParms)
5747
6701
 
5748
6702
  # validations.
@@ -5750,6 +6704,19 @@ class SpotifyClient:
5750
6704
  limit = 20
5751
6705
  if offset is None:
5752
6706
  offset = 0
6707
+ if not isinstance(limitTotal, int):
6708
+ limitTotal = 0
6709
+
6710
+ # are we auto-paging? if so, then use max limit.
6711
+ if limitTotal > 0:
6712
+ limit = 50
6713
+ #limit = 2 # TEST TODO
6714
+ if limit > limitTotal:
6715
+ limit = limitTotal
6716
+ result = EpisodePageSimplified()
6717
+
6718
+ # ensure market was either supplied or implied; default if neither.
6719
+ market = self._ValidateMarket(market)
5753
6720
 
5754
6721
  # build spotify web api request parameters.
5755
6722
  urlParms:dict = \
@@ -5760,25 +6727,57 @@ class SpotifyClient:
5760
6727
  if market is not None:
5761
6728
  urlParms['market'] = market
5762
6729
 
5763
- # execute spotify web api request.
5764
- msg:SpotifyApiMessage = SpotifyApiMessage(apiMethodName, '/shows/{id}/episodes'.format(id=showId))
5765
- msg.RequestHeaders[self.AuthToken.HeaderKey] = self.AuthToken.HeaderValue
5766
- msg.UrlParameters = urlParms
5767
- self.MakeRequest('GET', msg)
6730
+ # handle pagination, as spotify limits us to a set # of items returned per response.
6731
+ while True:
5768
6732
 
5769
- # process results.
5770
- result = EpisodePageSimplified(root=msg.ResponseData)
6733
+ # execute spotify web api request.
6734
+ msg:SpotifyApiMessage = SpotifyApiMessage(apiMethodName, '/shows/{id}/episodes'.format(id=showId))
6735
+ msg.RequestHeaders[self.AuthToken.HeaderKey] = self.AuthToken.HeaderValue
6736
+ msg.UrlParameters = urlParms
6737
+ self.MakeRequest('GET', msg)
5771
6738
 
5772
- # trace.
5773
- _logsi.LogObject(SILevel.Verbose, (TRACE_METHOD_RESULT_TYPE + result.PagingInfo) % (apiMethodName, type(result).__name__), result, excludeNonPublic=True)
5774
- return result
6739
+ # process results.
6740
+ pageObj = EpisodePageSimplified(root=msg.ResponseData)
5775
6741
 
5776
- except SpotifyWebApiError: raise # pass handled exceptions on thru
5777
- except SpotifyWebApiAuthenticationError: raise # pass handled exceptions on thru
5778
- except Exception as ex:
5779
-
5780
- # format unhandled exception.
5781
- raise SpotifyApiError(SAAppMessages.UNHANDLED_EXCEPTION.format(apiMethodName, str(ex)), ex, logsi=_logsi)
6742
+ # trace.
6743
+ _logsi.LogObject(SILevel.Verbose, (TRACE_METHOD_RESULT_TYPE_PAGE + pageObj.PagingInfo) % (apiMethodName, type(pageObj).__name__), pageObj, excludeNonPublic=True)
6744
+
6745
+ # was limit total argument specified?
6746
+ if (limitTotal <= 0):
6747
+
6748
+ # no - just return the initial page of results.
6749
+ result = pageObj
6750
+ break
6751
+
6752
+ else:
6753
+
6754
+ # append page of items to final results.
6755
+ item:EpisodeSimplified
6756
+ for item in pageObj.Items:
6757
+ result.Items.append(item)
6758
+ result.Limit = result.ItemsCount
6759
+ if result.ItemsCount >= limitTotal:
6760
+ break
6761
+
6762
+ # anymore pages to process? if not, then exit the loop.
6763
+ if not self._CheckForNextPage(pageObj, result.ItemsCount, limit, limitTotal, urlParms):
6764
+ break
6765
+
6766
+ # update result object with final paging details.
6767
+ result.Total = pageObj.Total
6768
+
6769
+ # no sort, as items are in playable order.
6770
+
6771
+ # trace.
6772
+ _logsi.LogObject(SILevel.Verbose, (TRACE_METHOD_RESULT_TYPE + result.PagingInfo) % (apiMethodName, type(result).__name__), result, excludeNonPublic=True)
6773
+ return result
6774
+
6775
+ except SpotifyWebApiError: raise # pass handled exceptions on thru
6776
+ except SpotifyWebApiAuthenticationError: raise # pass handled exceptions on thru
6777
+ except Exception as ex:
6778
+
6779
+ # format unhandled exception.
6780
+ raise SpotifyApiError(SAAppMessages.UNHANDLED_EXCEPTION.format(apiMethodName, str(ex)), ex, logsi=_logsi)
5782
6781
 
5783
6782
  finally:
5784
6783
 
@@ -5789,6 +6788,7 @@ class SpotifyClient:
5789
6788
  def GetShowFavorites(self,
5790
6789
  limit:int=20,
5791
6790
  offset:int=0,
6791
+ limitTotal:int=None
5792
6792
  ) -> ShowPageSaved:
5793
6793
  """
5794
6794
  Get a list of the shows saved in the current Spotify user's 'Your Library'.
@@ -5797,12 +6797,18 @@ class SpotifyClient:
5797
6797
 
5798
6798
  Args:
5799
6799
  limit (int):
5800
- The maximum number of items to return.
6800
+ The maximum number of items to return in a page of items.
5801
6801
  Default: 20, Range: 1 to 50.
5802
6802
  offset (int):
5803
- The index of the first item to return.
6803
+ The page index offset of the first item to return.
5804
6804
  Use with limit to get the next set of items.
5805
6805
  Default: 0 (the first item).
6806
+ limitTotal (int):
6807
+ The maximum number of items to return for the request.
6808
+ If specified, this argument overrides the limit and offset argument values
6809
+ and paging is automatically used to retrieve all available items up to the
6810
+ maximum number specified.
6811
+ Default: None (disabled)
5806
6812
 
5807
6813
  Returns:
5808
6814
  An `ShowPageSaved` object that contains saved show information.
@@ -5815,11 +6821,17 @@ class SpotifyClient:
5815
6821
  If the method fails for any other reason.
5816
6822
 
5817
6823
  <details>
5818
- <summary>Sample Code</summary>
6824
+ <summary>Sample Code - Manual Paging</summary>
5819
6825
  ```python
5820
6826
  .. include:: ../docs/include/samplecode/SpotifyClient/GetShowFavorites.py
5821
6827
  ```
5822
6828
  </details>
6829
+ <details>
6830
+ <summary>Sample Code - Auto Paging</summary>
6831
+ ```python
6832
+ .. include:: ../docs/include/samplecode/SpotifyClient/GetShowFavorites_AutoPaging.py
6833
+ ```
6834
+ </details>
5823
6835
  """
5824
6836
  apiMethodName:str = 'GetShowFavorites'
5825
6837
  apiMethodParms:SIMethodParmListContext = None
@@ -5831,6 +6843,7 @@ class SpotifyClient:
5831
6843
  apiMethodParms = _logsi.EnterMethodParmList(SILevel.Debug, apiMethodName)
5832
6844
  apiMethodParms.AppendKeyValue("limit", limit)
5833
6845
  apiMethodParms.AppendKeyValue("offset", offset)
6846
+ apiMethodParms.AppendKeyValue("limitTotal", limitTotal)
5834
6847
  _logsi.LogMethodParmList(SILevel.Verbose, "Get a list of the users show favorites", apiMethodParms)
5835
6848
 
5836
6849
  # validations.
@@ -5838,6 +6851,16 @@ class SpotifyClient:
5838
6851
  limit = 20
5839
6852
  if offset is None:
5840
6853
  offset = 0
6854
+ if not isinstance(limitTotal, int):
6855
+ limitTotal = 0
6856
+
6857
+ # are we auto-paging? if so, then use max limit.
6858
+ if limitTotal > 0:
6859
+ limit = 50
6860
+ #limit = 2 # TEST TODO
6861
+ if limit > limitTotal:
6862
+ limit = limitTotal
6863
+ result = ShowPageSaved()
5841
6864
 
5842
6865
  # build spotify web api request parameters.
5843
6866
  urlParms:dict = \
@@ -5846,14 +6869,48 @@ class SpotifyClient:
5846
6869
  'offset': offset,
5847
6870
  }
5848
6871
 
5849
- # execute spotify web api request.
5850
- msg:SpotifyApiMessage = SpotifyApiMessage(apiMethodName, '/me/shows')
5851
- msg.RequestHeaders[self.AuthToken.HeaderKey] = self.AuthToken.HeaderValue
5852
- msg.UrlParameters = urlParms
5853
- self.MakeRequest('GET', msg)
6872
+ # handle pagination, as spotify limits us to a set # of items returned per response.
6873
+ while True:
5854
6874
 
5855
- # process results.
5856
- result = ShowPageSaved(root=msg.ResponseData)
6875
+ # execute spotify web api request.
6876
+ msg:SpotifyApiMessage = SpotifyApiMessage(apiMethodName, '/me/shows')
6877
+ msg.RequestHeaders[self.AuthToken.HeaderKey] = self.AuthToken.HeaderValue
6878
+ msg.UrlParameters = urlParms
6879
+ self.MakeRequest('GET', msg)
6880
+
6881
+ # process results.
6882
+ pageObj = ShowPageSaved(root=msg.ResponseData)
6883
+
6884
+ # trace.
6885
+ _logsi.LogObject(SILevel.Verbose, (TRACE_METHOD_RESULT_TYPE_PAGE + pageObj.PagingInfo) % (apiMethodName, type(pageObj).__name__), pageObj, excludeNonPublic=True)
6886
+
6887
+ # was limit total argument specified?
6888
+ if (limitTotal <= 0):
6889
+
6890
+ # no - just return the initial page of results.
6891
+ result = pageObj
6892
+ break
6893
+
6894
+ else:
6895
+
6896
+ # append page of items to final results.
6897
+ item:AlbumSaved
6898
+ for item in pageObj.Items:
6899
+ result.Items.append(item)
6900
+ result.Limit = result.ItemsCount
6901
+ if result.ItemsCount >= limitTotal:
6902
+ break
6903
+
6904
+ # anymore pages to process? if not, then exit the loop.
6905
+ if not self._CheckForNextPage(pageObj, result.ItemsCount, limit, limitTotal, urlParms):
6906
+ break
6907
+
6908
+ # update result object with final paging details.
6909
+ result.Total = pageObj.Total
6910
+
6911
+ # sort items on Name property, ascending order.
6912
+ if len(result.Items) > 0:
6913
+ result.Items.sort(key=lambda x: (x.Show.Name or "").lower(), reverse=False)
5857
6914
 
5858
6915
  # trace.
5859
6916
  _logsi.LogObject(SILevel.Verbose, (TRACE_METHOD_RESULT_TYPE + result.PagingInfo) % (apiMethodName, type(result).__name__), result, excludeNonPublic=True)
@@ -5927,6 +6984,9 @@ class SpotifyClient:
5927
6984
  apiMethodParms.AppendKeyValue("market", market)
5928
6985
  _logsi.LogMethodParmList(SILevel.Verbose, "Get Spotify catalog information for multiple shows", apiMethodParms)
5929
6986
 
6987
+ # ensure market was either supplied or implied; default if neither.
6988
+ market = self._ValidateMarket(market)
6989
+
5930
6990
  # build spotify web api request parameters.
5931
6991
  urlParms:dict = \
5932
6992
  {
@@ -6095,6 +7155,7 @@ class SpotifyClient:
6095
7155
  limit:int=20,
6096
7156
  offset:int=0,
6097
7157
  market:str=None,
7158
+ limitTotal:int=None
6098
7159
  ) -> TrackPageSaved:
6099
7160
  """
6100
7161
  Get a list of the tracks saved in the current Spotify user's 'Your Library'.
@@ -6103,10 +7164,10 @@ class SpotifyClient:
6103
7164
 
6104
7165
  Args:
6105
7166
  limit (int):
6106
- The maximum number of items to return.
7167
+ The maximum number of items to return in a page of items.
6107
7168
  Default: 20, Range: 1 to 50.
6108
7169
  offset (int):
6109
- The index of the first item to return.
7170
+ The page index offset of the first item to return.
6110
7171
  Use with limit to get the next set of items.
6111
7172
  Default: 0 (the first item).
6112
7173
  market (str):
@@ -6117,6 +7178,12 @@ class SpotifyClient:
6117
7178
  Note: If neither market or user country are provided, the content is considered unavailable for the client.
6118
7179
  Users can view the country that is associated with their account in the account settings.
6119
7180
  Example: `ES`
7181
+ limitTotal (int):
7182
+ The maximum number of items to return for the request.
7183
+ If specified, this argument overrides the limit and offset argument values
7184
+ and paging is automatically used to retrieve all available items up to the
7185
+ maximum number specified.
7186
+ Default: None (disabled)
6120
7187
 
6121
7188
  Returns:
6122
7189
  An `TrackPageSaved` object that contains saved track information.
@@ -6129,11 +7196,17 @@ class SpotifyClient:
6129
7196
  If the method fails for any other reason.
6130
7197
 
6131
7198
  <details>
6132
- <summary>Sample Code</summary>
7199
+ <summary>Sample Code - Manual Paging</summary>
6133
7200
  ```python
6134
7201
  .. include:: ../docs/include/samplecode/SpotifyClient/GetTrackFavorites.py
6135
7202
  ```
6136
7203
  </details>
7204
+ <details>
7205
+ <summary>Sample Code - Auto Paging</summary>
7206
+ ```python
7207
+ .. include:: ../docs/include/samplecode/SpotifyClient/GetTrackFavorites_AutoPaging.py
7208
+ ```
7209
+ </details>
6137
7210
  """
6138
7211
  apiMethodName:str = 'GetTrackFavorites'
6139
7212
  apiMethodParms:SIMethodParmListContext = None
@@ -6146,6 +7219,7 @@ class SpotifyClient:
6146
7219
  apiMethodParms.AppendKeyValue("limit", limit)
6147
7220
  apiMethodParms.AppendKeyValue("offset", offset)
6148
7221
  apiMethodParms.AppendKeyValue("market", market)
7222
+ apiMethodParms.AppendKeyValue("limitTotal", limitTotal)
6149
7223
  _logsi.LogMethodParmList(SILevel.Verbose, "Get a list of the users track favorites", apiMethodParms)
6150
7224
 
6151
7225
  # validations.
@@ -6153,6 +7227,19 @@ class SpotifyClient:
6153
7227
  limit = 20
6154
7228
  if offset is None:
6155
7229
  offset = 0
7230
+ if not isinstance(limitTotal, int):
7231
+ limitTotal = 0
7232
+
7233
+ # are we auto-paging? if so, then use max limit.
7234
+ if limitTotal > 0:
7235
+ limit = 50
7236
+ #limit = 2 # TEST TODO
7237
+ if limit > limitTotal:
7238
+ limit = limitTotal
7239
+ result = TrackPageSaved()
7240
+
7241
+ # ensure market was either supplied or implied; default if neither.
7242
+ market = self._ValidateMarket(market)
6156
7243
 
6157
7244
  # build spotify web api request parameters.
6158
7245
  urlParms:dict = \
@@ -6163,15 +7250,49 @@ class SpotifyClient:
6163
7250
  if market is not None:
6164
7251
  urlParms['market'] = market
6165
7252
 
6166
- # execute spotify web api request.
6167
- msg:SpotifyApiMessage = SpotifyApiMessage(apiMethodName, '/me/tracks')
6168
- msg.RequestHeaders[self.AuthToken.HeaderKey] = self.AuthToken.HeaderValue
6169
- msg.UrlParameters = urlParms
6170
- self.MakeRequest('GET', msg)
7253
+ # handle pagination, as spotify limits us to a set # of items returned per response.
7254
+ while True:
6171
7255
 
6172
- # process results.
6173
- result = TrackPageSaved(root=msg.ResponseData)
7256
+ # execute spotify web api request.
7257
+ msg:SpotifyApiMessage = SpotifyApiMessage(apiMethodName, '/me/tracks')
7258
+ msg.RequestHeaders[self.AuthToken.HeaderKey] = self.AuthToken.HeaderValue
7259
+ msg.UrlParameters = urlParms
7260
+ self.MakeRequest('GET', msg)
7261
+
7262
+ # process results.
7263
+ pageObj = TrackPageSaved(root=msg.ResponseData)
6174
7264
 
7265
+ # trace.
7266
+ _logsi.LogObject(SILevel.Verbose, (TRACE_METHOD_RESULT_TYPE_PAGE + pageObj.PagingInfo) % (apiMethodName, type(pageObj).__name__), pageObj, excludeNonPublic=True)
7267
+
7268
+ # was limit total argument specified?
7269
+ if (limitTotal <= 0):
7270
+
7271
+ # no - just return the initial page of results.
7272
+ result = pageObj
7273
+ break
7274
+
7275
+ else:
7276
+
7277
+ # append page of items to final results.
7278
+ item:TrackSaved
7279
+ for item in pageObj.Items:
7280
+ result.Items.append(item)
7281
+ result.Limit = result.ItemsCount
7282
+ if result.ItemsCount >= limitTotal:
7283
+ break
7284
+
7285
+ # anymore pages to process? if not, then exit the loop.
7286
+ if not self._CheckForNextPage(pageObj, result.ItemsCount, limit, limitTotal, urlParms):
7287
+ break
7288
+
7289
+ # update result object with final paging details.
7290
+ result.Total = pageObj.Total
7291
+
7292
+ # sort items on Name property, ascending order.
7293
+ if len(result.Items) > 0:
7294
+ result.Items.sort(key=lambda x: (x.Track.Name or "").lower(), reverse=False)
7295
+
6175
7296
  # trace.
6176
7297
  _logsi.LogObject(SILevel.Verbose, (TRACE_METHOD_RESULT_TYPE + result.PagingInfo) % (apiMethodName, type(result).__name__), result, excludeNonPublic=True)
6177
7298
  return result
@@ -6239,6 +7360,9 @@ class SpotifyClient:
6239
7360
  apiMethodParms.AppendKeyValue("market", market)
6240
7361
  _logsi.LogMethodParmList(SILevel.Verbose, "Get Spotify catalog information for multiple tracks", apiMethodParms)
6241
7362
 
7363
+ # ensure market was either supplied or implied; default if neither.
7364
+ market = self._ValidateMarket(market)
7365
+
6242
7366
  # build spotify web api request parameters.
6243
7367
  urlParms:dict = \
6244
7368
  {
@@ -6378,7 +7502,7 @@ class SpotifyClient:
6378
7502
 
6379
7503
  Args:
6380
7504
  limit (int):
6381
- The maximum number of items to return.
7505
+ The maximum number of items to return in a page of items.
6382
7506
  Default: 20, Range: 1 to 50.
6383
7507
  market (str):
6384
7508
  An ISO 3166-1 alpha-2 country code. If a country code is specified, only content that
@@ -6609,6 +7733,9 @@ class SpotifyClient:
6609
7733
  apiMethodParms.AppendKeyValue("targetValence", targetValence)
6610
7734
  _logsi.LogMethodParmList(SILevel.Verbose, "Get track recommendations for specified criteria", apiMethodParms)
6611
7735
 
7736
+ # ensure market was either supplied or implied; default if neither.
7737
+ market = self._ValidateMarket(market)
7738
+
6612
7739
  # build spotify web api request parameters.
6613
7740
  urlParms:dict = \
6614
7741
  {
@@ -6939,7 +8066,8 @@ class SpotifyClient:
6939
8066
  def GetUsersTopArtists(self,
6940
8067
  timeRange:str='medium_term',
6941
8068
  limit:int=20,
6942
- offset:int=0
8069
+ offset:int=0,
8070
+ limitTotal:int=None
6943
8071
  ) -> ArtistPage:
6944
8072
  """
6945
8073
  Get the current user's top artists based on calculated affinity.
@@ -6954,12 +8082,18 @@ class SpotifyClient:
6954
8082
  Default: `medium_term`
6955
8083
  Example: `long_term`
6956
8084
  limit (int):
6957
- The maximum number of items to return.
8085
+ The maximum number of items to return in a page of items.
6958
8086
  Default: 20, Range: 1 to 50.
6959
8087
  offset (int):
6960
- The index of the first item to return.
8088
+ The page index offset of the first item to return.
6961
8089
  Use with limit to get the next set of items.
6962
8090
  Default: 0 (the first item), Range: 0 to 1000
8091
+ limitTotal (int):
8092
+ The maximum number of items to return for the request.
8093
+ If specified, this argument overrides the limit and offset argument values
8094
+ and paging is automatically used to retrieve all available items up to the
8095
+ maximum number specified.
8096
+ Default: None (disabled)
6963
8097
 
6964
8098
  Returns:
6965
8099
  An `ArtistPage` object of matching results.
@@ -6972,11 +8106,17 @@ class SpotifyClient:
6972
8106
  If the method fails for any other reason.
6973
8107
 
6974
8108
  <details>
6975
- <summary>Sample Code</summary>
8109
+ <summary>Sample Code - Manual Paging</summary>
6976
8110
  ```python
6977
8111
  .. include:: ../docs/include/samplecode/SpotifyClient/GetUsersTopArtists.py
6978
8112
  ```
6979
8113
  </details>
8114
+ <details>
8115
+ <summary>Sample Code - Auto Paging</summary>
8116
+ ```python
8117
+ .. include:: ../docs/include/samplecode/SpotifyClient/GetUsersTopArtists_AutoPaging.py
8118
+ ```
8119
+ </details>
6980
8120
  """
6981
8121
  apiMethodName:str = 'GetUsersTopArtists'
6982
8122
  apiMethodParms:SIMethodParmListContext = None
@@ -6989,6 +8129,7 @@ class SpotifyClient:
6989
8129
  apiMethodParms.AppendKeyValue("timeRange", timeRange)
6990
8130
  apiMethodParms.AppendKeyValue("limit", limit)
6991
8131
  apiMethodParms.AppendKeyValue("offset", offset)
8132
+ apiMethodParms.AppendKeyValue("limitTotal", limitTotal)
6992
8133
  _logsi.LogMethodParmList(SILevel.Verbose, "Get the current user's top artists", apiMethodParms)
6993
8134
 
6994
8135
  # validations.
@@ -6998,6 +8139,16 @@ class SpotifyClient:
6998
8139
  limit = 20
6999
8140
  if offset is None:
7000
8141
  offset = 0
8142
+ if not isinstance(limitTotal, int):
8143
+ limitTotal = 0
8144
+
8145
+ # are we auto-paging? if so, then use max limit.
8146
+ if limitTotal > 0:
8147
+ limit = 50
8148
+ #limit = 20 # TEST TODO
8149
+ if limit > limitTotal:
8150
+ limit = limitTotal
8151
+ result = ArtistPage()
7001
8152
 
7002
8153
  # build spotify web api request parameters.
7003
8154
  urlParms:dict = \
@@ -7007,17 +8158,51 @@ class SpotifyClient:
7007
8158
  'offset': offset,
7008
8159
  }
7009
8160
 
7010
- # execute spotify web api request.
7011
- msg:SpotifyApiMessage = SpotifyApiMessage(apiMethodName, '/me/top/artists')
7012
- msg.RequestHeaders[self.AuthToken.HeaderKey] = self.AuthToken.HeaderValue
7013
- msg.UrlParameters = urlParms
7014
- self.MakeRequest('GET', msg)
8161
+ # handle pagination, as spotify limits us to a set # of items returned per response.
8162
+ while True:
7015
8163
 
7016
- # process results.
7017
- result = ArtistPage(root=msg.ResponseData)
8164
+ # execute spotify web api request.
8165
+ msg:SpotifyApiMessage = SpotifyApiMessage(apiMethodName, '/me/top/artists')
8166
+ msg.RequestHeaders[self.AuthToken.HeaderKey] = self.AuthToken.HeaderValue
8167
+ msg.UrlParameters = urlParms
8168
+ self.MakeRequest('GET', msg)
8169
+
8170
+ # process results.
8171
+ pageObj = ArtistPage(root=msg.ResponseData)
8172
+
8173
+ # trace.
8174
+ _logsi.LogObject(SILevel.Verbose, (TRACE_METHOD_RESULT_TYPE_PAGE + pageObj.PagingInfo) % (apiMethodName, type(pageObj).__name__), pageObj, excludeNonPublic=True)
8175
+
8176
+ # was limit total argument specified?
8177
+ if (limitTotal <= 0):
8178
+
8179
+ # no - just return the initial page of results.
8180
+ result = pageObj
8181
+ break
8182
+
8183
+ else:
8184
+
8185
+ # append page of items to final results.
8186
+ item:Artist
8187
+ for item in pageObj.Items:
8188
+ result.Items.append(item)
8189
+ result.Limit = result.ItemsCount
8190
+ if result.ItemsCount >= limitTotal:
8191
+ break
8192
+
8193
+ # anymore pages to process? if not, then exit the loop.
8194
+ if not self._CheckForNextPage(pageObj, result.ItemsCount, limit, limitTotal, urlParms):
8195
+ break
8196
+
8197
+ # update result object with final paging details.
8198
+ result.Total = pageObj.Total
8199
+
8200
+ # sort items on Name property, ascending order.
8201
+ if len(result.Items) > 0:
8202
+ result.Items.sort(key=lambda x: (x.Name or "").lower(), reverse=False)
7018
8203
 
7019
8204
  # trace.
7020
- _logsi.LogObject(SILevel.Verbose, TRACE_METHOD_RESULT_TYPE % (apiMethodName, type(result).__name__), result, excludeNonPublic=True)
8205
+ _logsi.LogObject(SILevel.Verbose, (TRACE_METHOD_RESULT_TYPE + result.PagingInfo) % (apiMethodName, type(result).__name__), result, excludeNonPublic=True)
7021
8206
  return result
7022
8207
 
7023
8208
  except SpotifyWebApiError: raise # pass handled exceptions on thru
@@ -7036,7 +8221,8 @@ class SpotifyClient:
7036
8221
  def GetUsersTopTracks(self,
7037
8222
  timeRange:str='medium_term',
7038
8223
  limit:int=20,
7039
- offset:int=0
8224
+ offset:int=0,
8225
+ limitTotal:int=None
7040
8226
  ) -> TrackPage:
7041
8227
  """
7042
8228
  Get the current user's top tracks based on calculated affinity.
@@ -7051,12 +8237,18 @@ class SpotifyClient:
7051
8237
  Default: `medium_term`
7052
8238
  Example: `long_term`
7053
8239
  limit (int):
7054
- The maximum number of items to return.
8240
+ The maximum number of items to return in a page of items.
7055
8241
  Default: 20, Range: 1 to 50.
7056
8242
  offset (int):
7057
- The index of the first item to return.
8243
+ The page index offset of the first item to return.
7058
8244
  Use with limit to get the next set of items.
7059
- Default: 0 (the first item), Range: 0 to 1000
8245
+ Default: 0 (the first item).
8246
+ limitTotal (int):
8247
+ The maximum number of items to return for the request.
8248
+ If specified, this argument overrides the limit and offset argument values
8249
+ and paging is automatically used to retrieve all available items up to the
8250
+ maximum number specified.
8251
+ Default: None (disabled)
7060
8252
 
7061
8253
  Returns:
7062
8254
  An `TrackPage` object of matching results.
@@ -7069,11 +8261,17 @@ class SpotifyClient:
7069
8261
  If the method fails for any other reason.
7070
8262
 
7071
8263
  <details>
7072
- <summary>Sample Code</summary>
8264
+ <summary>Sample Code - Manual Paging</summary>
7073
8265
  ```python
7074
8266
  .. include:: ../docs/include/samplecode/SpotifyClient/GetUsersTopTracks.py
7075
8267
  ```
7076
8268
  </details>
8269
+ <details>
8270
+ <summary>Sample Code - Auto Paging</summary>
8271
+ ```python
8272
+ .. include:: ../docs/include/samplecode/SpotifyClient/GetUsersTopTracks_AutoPaging.py
8273
+ ```
8274
+ </details>
7077
8275
  """
7078
8276
  apiMethodName:str = 'GetUsersTopTracks'
7079
8277
  apiMethodParms:SIMethodParmListContext = None
@@ -7086,6 +8284,7 @@ class SpotifyClient:
7086
8284
  apiMethodParms.AppendKeyValue("timeRange", timeRange)
7087
8285
  apiMethodParms.AppendKeyValue("limit", limit)
7088
8286
  apiMethodParms.AppendKeyValue("offset", offset)
8287
+ apiMethodParms.AppendKeyValue("limitTotal", limitTotal)
7089
8288
  _logsi.LogMethodParmList(SILevel.Verbose, "Get the current user's top tracks", apiMethodParms)
7090
8289
 
7091
8290
  # validations.
@@ -7095,6 +8294,16 @@ class SpotifyClient:
7095
8294
  limit = 20
7096
8295
  if offset is None:
7097
8296
  offset = 0
8297
+ if not isinstance(limitTotal, int):
8298
+ limitTotal = 0
8299
+
8300
+ # are we auto-paging? if so, then use max limit.
8301
+ if limitTotal > 0:
8302
+ limit = 50
8303
+ #limit = 10 # TEST TODO
8304
+ if limit > limitTotal:
8305
+ limit = limitTotal
8306
+ result = TrackPage()
7098
8307
 
7099
8308
  # build spotify web api request parameters.
7100
8309
  urlParms:dict = \
@@ -7104,17 +8313,51 @@ class SpotifyClient:
7104
8313
  'offset': offset,
7105
8314
  }
7106
8315
 
7107
- # execute spotify web api request.
7108
- msg:SpotifyApiMessage = SpotifyApiMessage(apiMethodName, '/me/top/tracks')
7109
- msg.RequestHeaders[self.AuthToken.HeaderKey] = self.AuthToken.HeaderValue
7110
- msg.UrlParameters = urlParms
7111
- self.MakeRequest('GET', msg)
8316
+ # handle pagination, as spotify limits us to a set # of items returned per response.
8317
+ while True:
7112
8318
 
7113
- # process results.
7114
- result = TrackPage(root=msg.ResponseData)
8319
+ # execute spotify web api request.
8320
+ msg:SpotifyApiMessage = SpotifyApiMessage(apiMethodName, '/me/top/tracks')
8321
+ msg.RequestHeaders[self.AuthToken.HeaderKey] = self.AuthToken.HeaderValue
8322
+ msg.UrlParameters = urlParms
8323
+ self.MakeRequest('GET', msg)
8324
+
8325
+ # process results.
8326
+ pageObj = TrackPage(root=msg.ResponseData)
8327
+
8328
+ # trace.
8329
+ _logsi.LogObject(SILevel.Verbose, (TRACE_METHOD_RESULT_TYPE_PAGE + pageObj.PagingInfo) % (apiMethodName, type(pageObj).__name__), pageObj, excludeNonPublic=True)
8330
+
8331
+ # was limit total argument specified?
8332
+ if (limitTotal <= 0):
8333
+
8334
+ # no - just return the initial page of results.
8335
+ result = pageObj
8336
+ break
8337
+
8338
+ else:
8339
+
8340
+ # append page of items to final results.
8341
+ item:Track
8342
+ for item in pageObj.Items:
8343
+ result.Items.append(item)
8344
+ result.Limit = result.ItemsCount
8345
+ if result.ItemsCount >= limitTotal:
8346
+ break
8347
+
8348
+ # anymore pages to process? if not, then exit the loop.
8349
+ if not self._CheckForNextPage(pageObj, result.ItemsCount, limit, limitTotal, urlParms):
8350
+ break
8351
+
8352
+ # update result object with final paging details.
8353
+ result.Total = pageObj.Total
8354
+
8355
+ # sort items on Name property, ascending order.
8356
+ if len(result.Items) > 0:
8357
+ result.Items.sort(key=lambda x: (x.Name or "").lower(), reverse=False)
7115
8358
 
7116
8359
  # trace.
7117
- _logsi.LogObject(SILevel.Verbose, TRACE_METHOD_RESULT_TYPE % (apiMethodName, type(result).__name__), result, excludeNonPublic=True)
8360
+ _logsi.LogObject(SILevel.Verbose, (TRACE_METHOD_RESULT_TYPE + result.PagingInfo) % (apiMethodName, type(result).__name__), result, excludeNonPublic=True)
7118
8361
  return result
7119
8362
 
7120
8363
  except SpotifyWebApiError: raise # pass handled exceptions on thru
@@ -9214,18 +10457,192 @@ class SpotifyClient:
9214
10457
  _logsi.LeaveMethod(SILevel.Debug, apiMethodName)
9215
10458
 
9216
10459
 
9217
- def Search(self,
9218
- criteria:str,
9219
- criteriaType:str,
9220
- limit:int=20,
9221
- offset:int=0,
9222
- market:str=None,
9223
- includeExternal:str=None
9224
- ) -> SearchResponse:
9225
- """
9226
- Get Spotify catalog information about albums, artists, playlists, tracks, shows, episodes
9227
- or audiobooks that match a keyword string. Audiobooks are only available within the US, UK,
9228
- Canada, Ireland, New Zealand and Australia markets.
10460
+ # def Search(self,
10461
+ # criteria:str,
10462
+ # criteriaType:str,
10463
+ # limit:int=20,
10464
+ # offset:int=0,
10465
+ # market:str=None,
10466
+ # includeExternal:str=None,
10467
+ # ) -> SearchResponse:
10468
+ # """
10469
+ # Get Spotify catalog information about albums, artists, playlists, tracks, shows, episodes
10470
+ # or audiobooks that match a keyword string. Audiobooks are only available within the US, UK,
10471
+ # Canada, Ireland, New Zealand and Australia markets.
10472
+
10473
+ # Args:
10474
+ # criteria (str):
10475
+ # Your search query.
10476
+ # You can narrow down your search using field filters.
10477
+ # The available filters are album, artist, track, year, upc, tag:hipster, tag:new,
10478
+ # isrc, and genre. Each field filter only applies to certain result types.
10479
+ # The artist and year filters can be used while searching albums, artists and tracks.
10480
+ # You can filter on a single year or a range (e.g. 1955-1960).
10481
+ # The album filter can be used while searching albums and tracks.
10482
+ # The genre filter can be used while searching artists and tracks.
10483
+ # The isrc and track filters can be used while searching tracks.
10484
+ # The upc, tag:new and tag:hipster filters can only be used while searching albums.
10485
+ # The tag:new filter will return albums released in the past two weeks and tag:hipster
10486
+ # can be used to return only albums with the lowest 10% popularity.
10487
+ # criteriaType (str):
10488
+ # A comma-separated list of item types to search across.
10489
+ # Search results include hits from all the specified item types.
10490
+ # For example: "album,track" returns both albums and tracks matching criteria argument.
10491
+ # Allowed values: "album", "artist", "playlist", "track", "show", "episode", "audiobook".
10492
+ # limit (int):
10493
+ # The maximum number of items to return in a page of items.
10494
+ # Default: 20, Range: 1 to 50.
10495
+ # offset (int):
10496
+ # The page index offset of the first item to return.
10497
+ # Use with limit to get the next set of items.
10498
+ # Default: 0 (the first item). Range: 0 to 1000.
10499
+ # market (str):
10500
+ # An ISO 3166-1 alpha-2 country code. If a country code is specified, only content that
10501
+ # is available in that market will be returned. If a valid user access token is specified
10502
+ # in the request header, the country associated with the user account will take priority over
10503
+ # this parameter.
10504
+ # Note: If neither market or user country are provided, the content is considered unavailable for the client.
10505
+ # Users can view the country that is associated with their account in the account settings.
10506
+ # Example: `ES`
10507
+ # includeExternal (str):
10508
+ # If "audio" is specified it signals that the client can play externally hosted audio content, and
10509
+ # marks the content as playable in the response. By default externally hosted audio content is marked
10510
+ # as unplayable in the response.
10511
+ # Allowed values: "audio"
10512
+
10513
+ # Returns:
10514
+ # A `SearchResponse` object that contains the search results.
10515
+
10516
+ # Raises:
10517
+ # SpotifyWebApiError:
10518
+ # If the Spotify Web API request was for a non-authorization service
10519
+ # and the response contains error information.
10520
+ # SpotifApiError:
10521
+ # If the method fails for any other reason.
10522
+
10523
+ # Note the offset limitation of 1000 entries; this effectively limits you to 1,050 maximum
10524
+ # entries that you can return with a search.
10525
+
10526
+ # <details>
10527
+ # <summary>Sample Code - Search Albums</summary>
10528
+ # ```python
10529
+ # .. include:: ../docs/include/samplecode/SpotifyClient/SearchAlbums.py
10530
+ # ```
10531
+ # </details>
10532
+
10533
+ # <details>
10534
+ # <summary>Sample Code - Search Artists</summary>
10535
+ # ```python
10536
+ # .. include:: ../docs/include/samplecode/SpotifyClient/SearchArtists.py
10537
+ # ```
10538
+ # </details>
10539
+
10540
+ # <details>
10541
+ # <summary>Sample Code - Search Audiobooks</summary>
10542
+ # ```python
10543
+ # .. include:: ../docs/include/samplecode/SpotifyClient/SearchAudiobooks.py
10544
+ # ```
10545
+ # </details>
10546
+
10547
+ # <details>
10548
+ # <summary>Sample Code - Search Episodes</summary>
10549
+ # ```python
10550
+ # .. include:: ../docs/include/samplecode/SpotifyClient/SearchEpisodes.py
10551
+ # ```
10552
+ # </details>
10553
+
10554
+ # <details>
10555
+ # <summary>Sample Code - Search Playlists</summary>
10556
+ # ```python
10557
+ # .. include:: ../docs/include/samplecode/SpotifyClient/SearchPlaylists.py
10558
+ # ```
10559
+ # </details>
10560
+
10561
+ # <details>
10562
+ # <summary>Sample Code - Search Shows</summary>
10563
+ # ```python
10564
+ # .. include:: ../docs/include/samplecode/SpotifyClient/SearchShows.py
10565
+ # ```
10566
+ # </details>
10567
+
10568
+ # <details>
10569
+ # <summary>Sample Code - Search Tracks</summary>
10570
+ # ```python
10571
+ # .. include:: ../docs/include/samplecode/SpotifyClient/SearchTracks.py
10572
+ # ```
10573
+ # </details>
10574
+ # """
10575
+ # apiMethodName:str = 'Search'
10576
+ # apiMethodParms:SIMethodParmListContext = None
10577
+ # result:SearchResponse = None
10578
+
10579
+ # try:
10580
+
10581
+ # # trace.
10582
+ # apiMethodParms = _logsi.EnterMethodParmList(SILevel.Debug, apiMethodName)
10583
+ # apiMethodParms.AppendKeyValue("criteria", criteria)
10584
+ # apiMethodParms.AppendKeyValue("criteriaType", criteriaType)
10585
+ # apiMethodParms.AppendKeyValue("limit", limit)
10586
+ # apiMethodParms.AppendKeyValue("offset", offset)
10587
+ # apiMethodParms.AppendKeyValue("market", market)
10588
+ # apiMethodParms.AppendKeyValue("includeExternal", includeExternal)
10589
+ # _logsi.LogMethodParmList(SILevel.Verbose, "Searching Spotify catalog for information.", apiMethodParms)
10590
+
10591
+ # # validations.
10592
+ # if limit is None:
10593
+ # limit = 20
10594
+ # if offset is None:
10595
+ # offset = 0
10596
+
10597
+ # # build spotify web api request parameters.
10598
+ # urlParms:dict = \
10599
+ # {
10600
+ # 'q': criteria,
10601
+ # 'type': criteriaType,
10602
+ # 'limit': limit,
10603
+ # 'offset': offset,
10604
+ # }
10605
+ # if market is not None:
10606
+ # urlParms['market'] = market
10607
+ # if includeExternal is not None:
10608
+ # urlParms['include_external'] = includeExternal
10609
+
10610
+ # # execute spotify web api request.
10611
+ # msg:SpotifyApiMessage = SpotifyApiMessage(apiMethodName, '/search')
10612
+ # msg.RequestHeaders[self.AuthToken.HeaderKey] = self.AuthToken.HeaderValue
10613
+ # msg.UrlParameters = urlParms
10614
+ # self.MakeRequest('GET', msg)
10615
+
10616
+ # # process results.
10617
+ # result = SearchResponse(criteria, criteriaType, root=msg.ResponseData)
10618
+
10619
+ # # trace.
10620
+ # _logsi.LogObject(SILevel.Verbose, TRACE_METHOD_RESULT_TYPE % (apiMethodName, type(result).__name__), result, excludeNonPublic=True)
10621
+ # return result
10622
+
10623
+ # except SpotifyWebApiError: raise # pass handled exceptions on thru
10624
+ # except SpotifyWebApiAuthenticationError: raise # pass handled exceptions on thru
10625
+ # except Exception as ex:
10626
+
10627
+ # # format unhandled exception.
10628
+ # raise SpotifyApiError(SAAppMessages.UNHANDLED_EXCEPTION.format(apiMethodName, str(ex)), ex, logsi=_logsi)
10629
+
10630
+ # finally:
10631
+
10632
+ # # trace.
10633
+ # _logsi.LeaveMethod(SILevel.Debug, apiMethodName)
10634
+
10635
+
10636
+ def SearchAlbums(self,
10637
+ criteria:str,
10638
+ limit:int=20,
10639
+ offset:int=0,
10640
+ market:str=None,
10641
+ includeExternal:str=None,
10642
+ limitTotal:int=None
10643
+ ) -> SearchResponse:
10644
+ """
10645
+ Get Spotify catalog information about Albums that match a keyword string.
9229
10646
 
9230
10647
  Args:
9231
10648
  criteria (str):
@@ -9241,18 +10658,13 @@ class SpotifyClient:
9241
10658
  The upc, tag:new and tag:hipster filters can only be used while searching albums.
9242
10659
  The tag:new filter will return albums released in the past two weeks and tag:hipster
9243
10660
  can be used to return only albums with the lowest 10% popularity.
9244
- criteriaType (str):
9245
- A comma-separated list of item types to search across.
9246
- Search results include hits from all the specified item types.
9247
- For example: "album,track" returns both albums and tracks matching criteria argument.
9248
- Allowed values: "album", "artist", "playlist", "track", "show", "episode", "audiobook".
9249
10661
  limit (int):
9250
- The maximum number of items to return.
10662
+ The maximum number of items to return in a page of items.
9251
10663
  Default: 20, Range: 1 to 50.
9252
10664
  offset (int):
9253
- The index of the first item to return.
10665
+ The page index offset of the first item to return.
9254
10666
  Use with limit to get the next set of items.
9255
- Default: 0 (the first item), Range: 0 to 1000
10667
+ Default: 0 (the first item). Range: 0 to 1000.
9256
10668
  market (str):
9257
10669
  An ISO 3166-1 alpha-2 country code. If a country code is specified, only content that
9258
10670
  is available in that market will be returned. If a valid user access token is specified
@@ -9266,6 +10678,12 @@ class SpotifyClient:
9266
10678
  marks the content as playable in the response. By default externally hosted audio content is marked
9267
10679
  as unplayable in the response.
9268
10680
  Allowed values: "audio"
10681
+ limitTotal (int):
10682
+ The maximum number of items to return for the request.
10683
+ If specified, this argument overrides the limit and offset argument values
10684
+ and paging is automatically used to retrieve all available items up to the
10685
+ maximum number specified.
10686
+ Default: None (disabled)
9269
10687
 
9270
10688
  Returns:
9271
10689
  A `SearchResponse` object that contains the search results.
@@ -9277,61 +10695,26 @@ class SpotifyClient:
9277
10695
  SpotifApiError:
9278
10696
  If the method fails for any other reason.
9279
10697
 
9280
- Note the offset limitation of 1000 entries; this effectively limits you to 1,050 maximum
9281
- entries that you can return with a search.
10698
+ Note that Spotify Web API automatically limits you to 1,000 max entries per type that can
10699
+ be returned with a search.
9282
10700
 
9283
10701
  <details>
9284
- <summary>Sample Code - Search Albums</summary>
10702
+ <summary>Sample Code - Manual Paging</summary>
9285
10703
  ```python
9286
10704
  .. include:: ../docs/include/samplecode/SpotifyClient/SearchAlbums.py
9287
10705
  ```
9288
10706
  </details>
9289
-
9290
- <details>
9291
- <summary>Sample Code - Search Artists</summary>
9292
- ```python
9293
- .. include:: ../docs/include/samplecode/SpotifyClient/SearchArtists.py
9294
- ```
9295
- </details>
9296
-
9297
- <details>
9298
- <summary>Sample Code - Search Audiobooks</summary>
9299
- ```python
9300
- .. include:: ../docs/include/samplecode/SpotifyClient/SearchAudiobooks.py
9301
- ```
9302
- </details>
9303
-
9304
- <details>
9305
- <summary>Sample Code - Search Episodes</summary>
9306
- ```python
9307
- .. include:: ../docs/include/samplecode/SpotifyClient/SearchEpisodes.py
9308
- ```
9309
- </details>
9310
-
9311
- <details>
9312
- <summary>Sample Code - Search Playlists</summary>
9313
- ```python
9314
- .. include:: ../docs/include/samplecode/SpotifyClient/SearchPlaylists.py
9315
- ```
9316
- </details>
9317
-
9318
- <details>
9319
- <summary>Sample Code - Search Shows</summary>
9320
- ```python
9321
- .. include:: ../docs/include/samplecode/SpotifyClient/SearchShows.py
9322
- ```
9323
- </details>
9324
-
9325
10707
  <details>
9326
- <summary>Sample Code - Search Tracks</summary>
10708
+ <summary>Sample Code - Auto Paging</summary>
9327
10709
  ```python
9328
- .. include:: ../docs/include/samplecode/SpotifyClient/SearchTracks.py
10710
+ .. include:: ../docs/include/samplecode/SpotifyClient/SearchAlbums_AutoPaging.py
9329
10711
  ```
9330
10712
  </details>
9331
10713
  """
9332
- apiMethodName:str = 'Search'
10714
+ apiMethodName:str = 'SearchAlbums'
9333
10715
  apiMethodParms:SIMethodParmListContext = None
9334
- result:SearchResponse = None
10716
+ criteriaType:str = 'album'
10717
+ result:AlbumPageSimplified = None
9335
10718
 
9336
10719
  try:
9337
10720
 
@@ -9343,13 +10726,26 @@ class SpotifyClient:
9343
10726
  apiMethodParms.AppendKeyValue("offset", offset)
9344
10727
  apiMethodParms.AppendKeyValue("market", market)
9345
10728
  apiMethodParms.AppendKeyValue("includeExternal", includeExternal)
9346
- _logsi.LogMethodParmList(SILevel.Verbose, "Searching Spotify catalog for information.", apiMethodParms)
10729
+ apiMethodParms.AppendKeyValue("limitTotal", limitTotal)
10730
+ _logsi.LogMethodParmList(SILevel.Verbose, "Searching Spotify catalog for %s information" % criteriaType, apiMethodParms)
9347
10731
 
9348
10732
  # validations.
9349
10733
  if limit is None:
9350
10734
  limit = 20
9351
10735
  if offset is None:
9352
10736
  offset = 0
10737
+ if not isinstance(limitTotal, int):
10738
+ limitTotal = 0
10739
+
10740
+ # are we auto-paging? if so, then use max limit.
10741
+ if limitTotal > 0:
10742
+ limit = 50
10743
+ if limit > limitTotal:
10744
+ limit = limitTotal
10745
+ result = AlbumPageSimplified()
10746
+
10747
+ # ensure market was either supplied or implied; default if neither.
10748
+ market = self._ValidateMarket(market)
9353
10749
 
9354
10750
  # build spotify web api request parameters.
9355
10751
  urlParms:dict = \
@@ -9364,18 +10760,1203 @@ class SpotifyClient:
9364
10760
  if includeExternal is not None:
9365
10761
  urlParms['include_external'] = includeExternal
9366
10762
 
9367
- # execute spotify web api request.
9368
- msg:SpotifyApiMessage = SpotifyApiMessage(apiMethodName, '/search')
9369
- msg.RequestHeaders[self.AuthToken.HeaderKey] = self.AuthToken.HeaderValue
9370
- msg.UrlParameters = urlParms
9371
- self.MakeRequest('GET', msg)
10763
+ # handle pagination, as spotify limits us to a set # of items returned per response.
10764
+ while True:
9372
10765
 
9373
- # process results.
9374
- result = SearchResponse(criteria, criteriaType, root=msg.ResponseData)
10766
+ # execute spotify web api request.
10767
+ msg:SpotifyApiMessage = SpotifyApiMessage(apiMethodName, '/search')
10768
+ msg.RequestHeaders[self.AuthToken.HeaderKey] = self.AuthToken.HeaderValue
10769
+ msg.UrlParameters = urlParms
10770
+ self.MakeRequest('GET', msg)
10771
+
10772
+ # process results.
10773
+ searchResponse:SearchResponse = SearchResponse(criteria, criteriaType, root=msg.ResponseData)
10774
+ pageObj = searchResponse.Albums
10775
+
10776
+ # trace.
10777
+ _logsi.LogObject(SILevel.Verbose, (TRACE_METHOD_RESULT_TYPE_PAGE + pageObj.PagingInfo) % (apiMethodName, type(pageObj).__name__), pageObj, excludeNonPublic=True)
10778
+
10779
+ # was limit total argument specified?
10780
+ if (limitTotal <= 0):
10781
+
10782
+ # no - just return the initial page of results.
10783
+ result = pageObj
10784
+ break
10785
+
10786
+ else:
10787
+
10788
+ # append page of items to final results.
10789
+ item:AlbumSimplified
10790
+ for item in pageObj.Items:
10791
+ result.Items.append(item)
10792
+ result.Limit = result.ItemsCount
10793
+ if result.ItemsCount >= limitTotal:
10794
+ break
10795
+
10796
+ # anymore pages to process? if not, then exit the loop.
10797
+ if not self._CheckForNextPage(pageObj, result.ItemsCount, limit, limitTotal, urlParms):
10798
+ break
10799
+
10800
+ # update result object with final paging details.
10801
+ result.Total = pageObj.Total
10802
+
10803
+ # do not sort, as spotify uses intelligent AI to return results in its order.
9375
10804
 
9376
10805
  # trace.
9377
- _logsi.LogObject(SILevel.Verbose, TRACE_METHOD_RESULT_TYPE % (apiMethodName, type(result).__name__), result, excludeNonPublic=True)
9378
- return result
10806
+ _logsi.LogObject(SILevel.Verbose, (TRACE_METHOD_RESULT_TYPE + result.PagingInfo) % (apiMethodName, type(result).__name__), result, excludeNonPublic=True)
10807
+
10808
+ # return a search response object.
10809
+ response:SearchResponse = SearchResponse(criteria, criteriaType)
10810
+ response.Albums = result
10811
+ return response
10812
+
10813
+ except SpotifyWebApiError: raise # pass handled exceptions on thru
10814
+ except SpotifyWebApiAuthenticationError: raise # pass handled exceptions on thru
10815
+ except Exception as ex:
10816
+
10817
+ # format unhandled exception.
10818
+ raise SpotifyApiError(SAAppMessages.UNHANDLED_EXCEPTION.format(apiMethodName, str(ex)), ex, logsi=_logsi)
10819
+
10820
+ finally:
10821
+
10822
+ # trace.
10823
+ _logsi.LeaveMethod(SILevel.Debug, apiMethodName)
10824
+
10825
+
10826
+ def SearchArtists(self,
10827
+ criteria:str,
10828
+ limit:int=20,
10829
+ offset:int=0,
10830
+ market:str=None,
10831
+ includeExternal:str=None,
10832
+ limitTotal:int=None
10833
+ ) -> SearchResponse:
10834
+ """
10835
+ Get Spotify catalog information about Artists that match a keyword string.
10836
+
10837
+ Args:
10838
+ criteria (str):
10839
+ Your search query.
10840
+ You can narrow down your search using field filters.
10841
+ The available filters are album, artist, track, year, upc, tag:hipster, tag:new,
10842
+ isrc, and genre. Each field filter only applies to certain result types.
10843
+ The artist and year filters can be used while searching albums, artists and tracks.
10844
+ You can filter on a single year or a range (e.g. 1955-1960).
10845
+ The album filter can be used while searching albums and tracks.
10846
+ The genre filter can be used while searching artists and tracks.
10847
+ The isrc and track filters can be used while searching tracks.
10848
+ The upc, tag:new and tag:hipster filters can only be used while searching albums.
10849
+ The tag:new filter will return albums released in the past two weeks and tag:hipster
10850
+ can be used to return only albums with the lowest 10% popularity.
10851
+ limit (int):
10852
+ The maximum number of items to return in a page of items.
10853
+ Default: 20, Range: 1 to 50.
10854
+ offset (int):
10855
+ The page index offset of the first item to return.
10856
+ Use with limit to get the next set of items.
10857
+ Default: 0 (the first item). Range: 0 to 1000.
10858
+ market (str):
10859
+ An ISO 3166-1 alpha-2 country code. If a country code is specified, only content that
10860
+ is available in that market will be returned. If a valid user access token is specified
10861
+ in the request header, the country associated with the user account will take priority over
10862
+ this parameter.
10863
+ Note: If neither market or user country are provided, the content is considered unavailable for the client.
10864
+ Users can view the country that is associated with their account in the account settings.
10865
+ Example: `ES`
10866
+ includeExternal (str):
10867
+ If "audio" is specified it signals that the client can play externally hosted audio content, and
10868
+ marks the content as playable in the response. By default externally hosted audio content is marked
10869
+ as unplayable in the response.
10870
+ Allowed values: "audio"
10871
+ limitTotal (int):
10872
+ The maximum number of items to return for the request.
10873
+ If specified, this argument overrides the limit and offset argument values
10874
+ and paging is automatically used to retrieve all available items up to the
10875
+ maximum number specified.
10876
+ Default: None (disabled)
10877
+
10878
+ Returns:
10879
+ A `SearchResponse` object that contains the search results.
10880
+
10881
+ Raises:
10882
+ SpotifyWebApiError:
10883
+ If the Spotify Web API request was for a non-authorization service
10884
+ and the response contains error information.
10885
+ SpotifApiError:
10886
+ If the method fails for any other reason.
10887
+
10888
+ Note that Spotify Web API automatically limits you to 1,000 max entries per type that can
10889
+ be returned with a search.
10890
+
10891
+ <details>
10892
+ <summary>Sample Code - Manual Paging</summary>
10893
+ ```python
10894
+ .. include:: ../docs/include/samplecode/SpotifyClient/SearchArtists.py
10895
+ ```
10896
+ </details>
10897
+ <details>
10898
+ <summary>Sample Code - Auto Paging</summary>
10899
+ ```python
10900
+ .. include:: ../docs/include/samplecode/SpotifyClient/SearchArtists_AutoPaging.py
10901
+ ```
10902
+ </details>
10903
+ """
10904
+ apiMethodName:str = 'SearchArtists'
10905
+ apiMethodParms:SIMethodParmListContext = None
10906
+ criteriaType:str = 'artist'
10907
+ result:ArtistPage = None
10908
+
10909
+ try:
10910
+
10911
+ # trace.
10912
+ apiMethodParms = _logsi.EnterMethodParmList(SILevel.Debug, apiMethodName)
10913
+ apiMethodParms.AppendKeyValue("criteria", criteria)
10914
+ apiMethodParms.AppendKeyValue("criteriaType", criteriaType)
10915
+ apiMethodParms.AppendKeyValue("limit", limit)
10916
+ apiMethodParms.AppendKeyValue("offset", offset)
10917
+ apiMethodParms.AppendKeyValue("market", market)
10918
+ apiMethodParms.AppendKeyValue("includeExternal", includeExternal)
10919
+ apiMethodParms.AppendKeyValue("limitTotal", limitTotal)
10920
+ _logsi.LogMethodParmList(SILevel.Verbose, "Searching Spotify catalog for %s information" % criteriaType, apiMethodParms)
10921
+
10922
+ # validations.
10923
+ if limit is None:
10924
+ limit = 20
10925
+ if offset is None:
10926
+ offset = 0
10927
+ if not isinstance(limitTotal, int):
10928
+ limitTotal = 0
10929
+
10930
+ # are we auto-paging? if so, then use max limit.
10931
+ if limitTotal > 0:
10932
+ limit = 50
10933
+ if limit > limitTotal:
10934
+ limit = limitTotal
10935
+ result = ArtistPage()
10936
+
10937
+ # ensure market was either supplied or implied; default if neither.
10938
+ market = self._ValidateMarket(market)
10939
+
10940
+ # build spotify web api request parameters.
10941
+ urlParms:dict = \
10942
+ {
10943
+ 'q': criteria,
10944
+ 'type': criteriaType,
10945
+ 'limit': limit,
10946
+ 'offset': offset,
10947
+ }
10948
+ if market is not None:
10949
+ urlParms['market'] = market
10950
+ if includeExternal is not None:
10951
+ urlParms['include_external'] = includeExternal
10952
+
10953
+ # handle pagination, as spotify limits us to a set # of items returned per response.
10954
+ while True:
10955
+
10956
+ # execute spotify web api request.
10957
+ msg:SpotifyApiMessage = SpotifyApiMessage(apiMethodName, '/search')
10958
+ msg.RequestHeaders[self.AuthToken.HeaderKey] = self.AuthToken.HeaderValue
10959
+ msg.UrlParameters = urlParms
10960
+ self.MakeRequest('GET', msg)
10961
+
10962
+ # process results.
10963
+ searchResponse:SearchResponse = SearchResponse(criteria, criteriaType, root=msg.ResponseData)
10964
+ pageObj = searchResponse.Artists
10965
+
10966
+ # trace.
10967
+ _logsi.LogObject(SILevel.Verbose, (TRACE_METHOD_RESULT_TYPE_PAGE + pageObj.PagingInfo) % (apiMethodName, type(pageObj).__name__), pageObj, excludeNonPublic=True)
10968
+
10969
+ # was limit total argument specified?
10970
+ if (limitTotal <= 0):
10971
+
10972
+ # no - just return the initial page of results.
10973
+ result = pageObj
10974
+ break
10975
+
10976
+ else:
10977
+
10978
+ # append page of items to final results.
10979
+ item:Artist
10980
+ for item in pageObj.Items:
10981
+ result.Items.append(item)
10982
+ result.Limit = result.ItemsCount
10983
+ if result.ItemsCount >= limitTotal:
10984
+ break
10985
+
10986
+ # anymore pages to process? if not, then exit the loop.
10987
+ if not self._CheckForNextPage(pageObj, result.ItemsCount, limit, limitTotal, urlParms):
10988
+ break
10989
+
10990
+ # update result object with final paging details.
10991
+ result.Total = pageObj.Total
10992
+
10993
+ # do not sort, as spotify uses intelligent AI to return results in its order.
10994
+
10995
+ # trace.
10996
+ _logsi.LogObject(SILevel.Verbose, (TRACE_METHOD_RESULT_TYPE + result.PagingInfo) % (apiMethodName, type(result).__name__), result, excludeNonPublic=True)
10997
+
10998
+ # return a search response object.
10999
+ response:SearchResponse = SearchResponse(criteria, criteriaType)
11000
+ response.Artists = result
11001
+ return response
11002
+
11003
+ except SpotifyWebApiError: raise # pass handled exceptions on thru
11004
+ except SpotifyWebApiAuthenticationError: raise # pass handled exceptions on thru
11005
+ except Exception as ex:
11006
+
11007
+ # format unhandled exception.
11008
+ raise SpotifyApiError(SAAppMessages.UNHANDLED_EXCEPTION.format(apiMethodName, str(ex)), ex, logsi=_logsi)
11009
+
11010
+ finally:
11011
+
11012
+ # trace.
11013
+ _logsi.LeaveMethod(SILevel.Debug, apiMethodName)
11014
+
11015
+
11016
+ def SearchAudiobooks(self,
11017
+ criteria:str,
11018
+ limit:int=20,
11019
+ offset:int=0,
11020
+ market:str=None,
11021
+ includeExternal:str=None,
11022
+ limitTotal:int=None
11023
+ ) -> SearchResponse:
11024
+ """
11025
+ Get Spotify catalog information about Audiobooks that match a keyword string.
11026
+
11027
+ Args:
11028
+ criteria (str):
11029
+ Your search query.
11030
+ You can narrow down your search using field filters.
11031
+ The available filters are album, artist, track, year, upc, tag:hipster, tag:new,
11032
+ isrc, and genre. Each field filter only applies to certain result types.
11033
+ The artist and year filters can be used while searching albums, artists and tracks.
11034
+ You can filter on a single year or a range (e.g. 1955-1960).
11035
+ The album filter can be used while searching albums and tracks.
11036
+ The genre filter can be used while searching artists and tracks.
11037
+ The isrc and track filters can be used while searching tracks.
11038
+ The upc, tag:new and tag:hipster filters can only be used while searching albums.
11039
+ The tag:new filter will return albums released in the past two weeks and tag:hipster
11040
+ can be used to return only albums with the lowest 10% popularity.
11041
+ limit (int):
11042
+ The maximum number of items to return in a page of items.
11043
+ Default: 20, Range: 1 to 50.
11044
+ offset (int):
11045
+ The page index offset of the first item to return.
11046
+ Use with limit to get the next set of items.
11047
+ Default: 0 (the first item). Range: 0 to 1000.
11048
+ market (str):
11049
+ An ISO 3166-1 alpha-2 country code. If a country code is specified, only content that
11050
+ is available in that market will be returned. If a valid user access token is specified
11051
+ in the request header, the country associated with the user account will take priority over
11052
+ this parameter.
11053
+ Note: If neither market or user country are provided, the content is considered unavailable for the client.
11054
+ Users can view the country that is associated with their account in the account settings.
11055
+ Example: `ES`
11056
+ includeExternal (str):
11057
+ If "audio" is specified it signals that the client can play externally hosted audio content, and
11058
+ marks the content as playable in the response. By default externally hosted audio content is marked
11059
+ as unplayable in the response.
11060
+ Allowed values: "audio"
11061
+ limitTotal (int):
11062
+ The maximum number of items to return for the request.
11063
+ If specified, this argument overrides the limit and offset argument values
11064
+ and paging is automatically used to retrieve all available items up to the
11065
+ maximum number specified.
11066
+ Default: None (disabled)
11067
+
11068
+ Returns:
11069
+ A `SearchResponse` object that contains the search results.
11070
+
11071
+ Raises:
11072
+ SpotifyWebApiError:
11073
+ If the Spotify Web API request was for a non-authorization service
11074
+ and the response contains error information.
11075
+ SpotifApiError:
11076
+ If the method fails for any other reason.
11077
+
11078
+ Audiobooks are only available within the US, UK, Canada, Ireland, New Zealand and Australia markets.
11079
+
11080
+ Note that Spotify Web API automatically limits you to 1,000 max entries per type that can
11081
+ be returned with a search.
11082
+
11083
+ <details>
11084
+ <summary>Sample Code - Manual Paging</summary>
11085
+ ```python
11086
+ .. include:: ../docs/include/samplecode/SpotifyClient/SearchAudiobooks.py
11087
+ ```
11088
+ </details>
11089
+ <details>
11090
+ <summary>Sample Code - Auto Paging</summary>
11091
+ ```python
11092
+ .. include:: ../docs/include/samplecode/SpotifyClient/SearchAudiobooks_AutoPaging.py
11093
+ ```
11094
+ </details>
11095
+ """
11096
+ apiMethodName:str = 'SearchAudiobooks'
11097
+ apiMethodParms:SIMethodParmListContext = None
11098
+ criteriaType:str = 'audiobook'
11099
+ result:AudiobookPageSimplified = None
11100
+
11101
+ try:
11102
+
11103
+ # trace.
11104
+ apiMethodParms = _logsi.EnterMethodParmList(SILevel.Debug, apiMethodName)
11105
+ apiMethodParms.AppendKeyValue("criteria", criteria)
11106
+ apiMethodParms.AppendKeyValue("criteriaType", criteriaType)
11107
+ apiMethodParms.AppendKeyValue("limit", limit)
11108
+ apiMethodParms.AppendKeyValue("offset", offset)
11109
+ apiMethodParms.AppendKeyValue("market", market)
11110
+ apiMethodParms.AppendKeyValue("includeExternal", includeExternal)
11111
+ apiMethodParms.AppendKeyValue("limitTotal", limitTotal)
11112
+ _logsi.LogMethodParmList(SILevel.Verbose, "Searching Spotify catalog for %s information" % criteriaType, apiMethodParms)
11113
+
11114
+ # validations.
11115
+ if limit is None:
11116
+ limit = 20
11117
+ if offset is None:
11118
+ offset = 0
11119
+ if not isinstance(limitTotal, int):
11120
+ limitTotal = 0
11121
+
11122
+ # are we auto-paging? if so, then use max limit.
11123
+ if limitTotal > 0:
11124
+ limit = 50
11125
+ if limit > limitTotal:
11126
+ limit = limitTotal
11127
+ result = AudiobookPageSimplified()
11128
+
11129
+ # ensure market was either supplied or implied; default if neither.
11130
+ market = self._ValidateMarket(market)
11131
+
11132
+ # build spotify web api request parameters.
11133
+ urlParms:dict = \
11134
+ {
11135
+ 'q': criteria,
11136
+ 'type': criteriaType,
11137
+ 'limit': limit,
11138
+ 'offset': offset,
11139
+ }
11140
+ if market is not None:
11141
+ urlParms['market'] = market
11142
+ if includeExternal is not None:
11143
+ urlParms['include_external'] = includeExternal
11144
+
11145
+ # handle pagination, as spotify limits us to a set # of items returned per response.
11146
+ while True:
11147
+
11148
+ # execute spotify web api request.
11149
+ msg:SpotifyApiMessage = SpotifyApiMessage(apiMethodName, '/search')
11150
+ msg.RequestHeaders[self.AuthToken.HeaderKey] = self.AuthToken.HeaderValue
11151
+ msg.UrlParameters = urlParms
11152
+ self.MakeRequest('GET', msg)
11153
+
11154
+ # process results.
11155
+ searchResponse:SearchResponse = SearchResponse(criteria, criteriaType, root=msg.ResponseData)
11156
+ pageObj = searchResponse.Audiobooks
11157
+
11158
+ # trace.
11159
+ _logsi.LogObject(SILevel.Verbose, (TRACE_METHOD_RESULT_TYPE_PAGE + pageObj.PagingInfo) % (apiMethodName, type(pageObj).__name__), pageObj, excludeNonPublic=True)
11160
+
11161
+ # was limit total argument specified?
11162
+ if (limitTotal <= 0):
11163
+
11164
+ # no - just return the initial page of results.
11165
+ result = pageObj
11166
+ break
11167
+
11168
+ else:
11169
+
11170
+ # append page of items to final results.
11171
+ item:AudiobookSimplified
11172
+ for item in pageObj.Items:
11173
+ result.Items.append(item)
11174
+ result.Limit = result.ItemsCount
11175
+ if result.ItemsCount >= limitTotal:
11176
+ break
11177
+
11178
+ # anymore pages to process? if not, then exit the loop.
11179
+ if not self._CheckForNextPage(pageObj, result.ItemsCount, limit, limitTotal, urlParms):
11180
+ break
11181
+
11182
+ # update result object with final paging details.
11183
+ result.Total = pageObj.Total
11184
+
11185
+ # do not sort, as spotify uses intelligent AI to return results in its order.
11186
+
11187
+ # trace.
11188
+ _logsi.LogObject(SILevel.Verbose, (TRACE_METHOD_RESULT_TYPE + result.PagingInfo) % (apiMethodName, type(result).__name__), result, excludeNonPublic=True)
11189
+
11190
+ # return a search response object.
11191
+ response:SearchResponse = SearchResponse(criteria, criteriaType)
11192
+ response.Audiobooks = result
11193
+ return response
11194
+
11195
+ except SpotifyWebApiError: raise # pass handled exceptions on thru
11196
+ except SpotifyWebApiAuthenticationError: raise # pass handled exceptions on thru
11197
+ except Exception as ex:
11198
+
11199
+ # format unhandled exception.
11200
+ raise SpotifyApiError(SAAppMessages.UNHANDLED_EXCEPTION.format(apiMethodName, str(ex)), ex, logsi=_logsi)
11201
+
11202
+ finally:
11203
+
11204
+ # trace.
11205
+ _logsi.LeaveMethod(SILevel.Debug, apiMethodName)
11206
+
11207
+
11208
+ def SearchEpisodes(self,
11209
+ criteria:str,
11210
+ limit:int=20,
11211
+ offset:int=0,
11212
+ market:str=None,
11213
+ includeExternal:str=None,
11214
+ limitTotal:int=None
11215
+ ) -> SearchResponse:
11216
+ """
11217
+ Get Spotify catalog information about Episodes that match a keyword string.
11218
+
11219
+ Args:
11220
+ criteria (str):
11221
+ Your search query.
11222
+ You can narrow down your search using field filters.
11223
+ The available filters are album, artist, track, year, upc, tag:hipster, tag:new,
11224
+ isrc, and genre. Each field filter only applies to certain result types.
11225
+ The artist and year filters can be used while searching albums, artists and tracks.
11226
+ You can filter on a single year or a range (e.g. 1955-1960).
11227
+ The album filter can be used while searching albums and tracks.
11228
+ The genre filter can be used while searching artists and tracks.
11229
+ The isrc and track filters can be used while searching tracks.
11230
+ The upc, tag:new and tag:hipster filters can only be used while searching albums.
11231
+ The tag:new filter will return albums released in the past two weeks and tag:hipster
11232
+ can be used to return only albums with the lowest 10% popularity.
11233
+ limit (int):
11234
+ The maximum number of items to return in a page of items.
11235
+ Default: 20, Range: 1 to 50.
11236
+ offset (int):
11237
+ The page index offset of the first item to return.
11238
+ Use with limit to get the next set of items.
11239
+ Default: 0 (the first item). Range: 0 to 1000.
11240
+ market (str):
11241
+ An ISO 3166-1 alpha-2 country code. If a country code is specified, only content that
11242
+ is available in that market will be returned. If a valid user access token is specified
11243
+ in the request header, the country associated with the user account will take priority over
11244
+ this parameter.
11245
+ Note: If neither market or user country are provided, the content is considered unavailable for the client.
11246
+ Users can view the country that is associated with their account in the account settings.
11247
+ Example: `ES`
11248
+ includeExternal (str):
11249
+ If "audio" is specified it signals that the client can play externally hosted audio content, and
11250
+ marks the content as playable in the response. By default externally hosted audio content is marked
11251
+ as unplayable in the response.
11252
+ Allowed values: "audio"
11253
+ limitTotal (int):
11254
+ The maximum number of items to return for the request.
11255
+ If specified, this argument overrides the limit and offset argument values
11256
+ and paging is automatically used to retrieve all available items up to the
11257
+ maximum number specified.
11258
+ Default: None (disabled)
11259
+
11260
+ Returns:
11261
+ A `SearchResponse` object that contains the search results.
11262
+
11263
+ Raises:
11264
+ SpotifyWebApiError:
11265
+ If the Spotify Web API request was for a non-authorization service
11266
+ and the response contains error information.
11267
+ SpotifApiError:
11268
+ If the method fails for any other reason.
11269
+
11270
+ Note that Spotify Web API automatically limits you to 1,000 max entries per type that can
11271
+ be returned with a search.
11272
+
11273
+ <details>
11274
+ <summary>Sample Code - Manual Paging</summary>
11275
+ ```python
11276
+ .. include:: ../docs/include/samplecode/SpotifyClient/SearchEpisodes.py
11277
+ ```
11278
+ </details>
11279
+ <details>
11280
+ <summary>Sample Code - Auto Paging</summary>
11281
+ ```python
11282
+ .. include:: ../docs/include/samplecode/SpotifyClient/SearchEpisodes_AutoPaging.py
11283
+ ```
11284
+ </details>
11285
+ """
11286
+ apiMethodName:str = 'SearchEpisodes'
11287
+ apiMethodParms:SIMethodParmListContext = None
11288
+ criteriaType:str = 'episode'
11289
+ result:EpisodePageSimplified = None
11290
+
11291
+ try:
11292
+
11293
+ # trace.
11294
+ apiMethodParms = _logsi.EnterMethodParmList(SILevel.Debug, apiMethodName)
11295
+ apiMethodParms.AppendKeyValue("criteria", criteria)
11296
+ apiMethodParms.AppendKeyValue("criteriaType", criteriaType)
11297
+ apiMethodParms.AppendKeyValue("limit", limit)
11298
+ apiMethodParms.AppendKeyValue("offset", offset)
11299
+ apiMethodParms.AppendKeyValue("market", market)
11300
+ apiMethodParms.AppendKeyValue("includeExternal", includeExternal)
11301
+ apiMethodParms.AppendKeyValue("limitTotal", limitTotal)
11302
+ _logsi.LogMethodParmList(SILevel.Verbose, "Searching Spotify catalog for %s information" % criteriaType, apiMethodParms)
11303
+
11304
+ # validations.
11305
+ if limit is None:
11306
+ limit = 20
11307
+ if offset is None:
11308
+ offset = 0
11309
+ if not isinstance(limitTotal, int):
11310
+ limitTotal = 0
11311
+
11312
+ # are we auto-paging? if so, then use max limit.
11313
+ if limitTotal > 0:
11314
+ limit = 50
11315
+ if limit > limitTotal:
11316
+ limit = limitTotal
11317
+ result = EpisodePageSimplified()
11318
+
11319
+ # ensure market was either supplied or implied; default if neither.
11320
+ market = self._ValidateMarket(market)
11321
+
11322
+ # build spotify web api request parameters.
11323
+ urlParms:dict = \
11324
+ {
11325
+ 'q': criteria,
11326
+ 'type': criteriaType,
11327
+ 'limit': limit,
11328
+ 'offset': offset,
11329
+ }
11330
+ if market is not None:
11331
+ urlParms['market'] = market
11332
+ if includeExternal is not None:
11333
+ urlParms['include_external'] = includeExternal
11334
+
11335
+ # handle pagination, as spotify limits us to a set # of items returned per response.
11336
+ while True:
11337
+
11338
+ # execute spotify web api request.
11339
+ msg:SpotifyApiMessage = SpotifyApiMessage(apiMethodName, '/search')
11340
+ msg.RequestHeaders[self.AuthToken.HeaderKey] = self.AuthToken.HeaderValue
11341
+ msg.UrlParameters = urlParms
11342
+ self.MakeRequest('GET', msg)
11343
+
11344
+ # process results.
11345
+ searchResponse:SearchResponse = SearchResponse(criteria, criteriaType, root=msg.ResponseData)
11346
+ pageObj = searchResponse.Episodes
11347
+
11348
+ # trace.
11349
+ _logsi.LogObject(SILevel.Verbose, (TRACE_METHOD_RESULT_TYPE_PAGE + pageObj.PagingInfo) % (apiMethodName, type(pageObj).__name__), pageObj, excludeNonPublic=True)
11350
+
11351
+ # was limit total argument specified?
11352
+ if (limitTotal <= 0):
11353
+
11354
+ # no - just return the initial page of results.
11355
+ result = pageObj
11356
+ break
11357
+
11358
+ else:
11359
+
11360
+ # append page of items to final results.
11361
+ item:EpisodeSimplified
11362
+ for item in pageObj.Items:
11363
+ result.Items.append(item)
11364
+ result.Limit = result.ItemsCount
11365
+ if result.ItemsCount >= limitTotal:
11366
+ break
11367
+
11368
+ # anymore pages to process? if not, then exit the loop.
11369
+ if not self._CheckForNextPage(pageObj, result.ItemsCount, limit, limitTotal, urlParms):
11370
+ break
11371
+
11372
+ # update result object with final paging details.
11373
+ result.Total = pageObj.Total
11374
+
11375
+ # do not sort, as spotify uses intelligent AI to return results in its order.
11376
+
11377
+ # trace.
11378
+ _logsi.LogObject(SILevel.Verbose, (TRACE_METHOD_RESULT_TYPE + result.PagingInfo) % (apiMethodName, type(result).__name__), result, excludeNonPublic=True)
11379
+
11380
+ # return a search response object.
11381
+ response:SearchResponse = SearchResponse(criteria, criteriaType)
11382
+ response.Episodes = result
11383
+ return response
11384
+
11385
+ except SpotifyWebApiError: raise # pass handled exceptions on thru
11386
+ except SpotifyWebApiAuthenticationError: raise # pass handled exceptions on thru
11387
+ except Exception as ex:
11388
+
11389
+ # format unhandled exception.
11390
+ raise SpotifyApiError(SAAppMessages.UNHANDLED_EXCEPTION.format(apiMethodName, str(ex)), ex, logsi=_logsi)
11391
+
11392
+ finally:
11393
+
11394
+ # trace.
11395
+ _logsi.LeaveMethod(SILevel.Debug, apiMethodName)
11396
+
11397
+
11398
+ def SearchPlaylists(self,
11399
+ criteria:str,
11400
+ limit:int=20,
11401
+ offset:int=0,
11402
+ market:str=None,
11403
+ includeExternal:str=None,
11404
+ limitTotal:int=None
11405
+ ) -> SearchResponse:
11406
+ """
11407
+ Get Spotify catalog information about Playlists that match a keyword string.
11408
+
11409
+ Args:
11410
+ criteria (str):
11411
+ Your search query.
11412
+ You can narrow down your search using field filters.
11413
+ The available filters are album, artist, track, year, upc, tag:hipster, tag:new,
11414
+ isrc, and genre. Each field filter only applies to certain result types.
11415
+ The artist and year filters can be used while searching albums, artists and tracks.
11416
+ You can filter on a single year or a range (e.g. 1955-1960).
11417
+ The album filter can be used while searching albums and tracks.
11418
+ The genre filter can be used while searching artists and tracks.
11419
+ The isrc and track filters can be used while searching tracks.
11420
+ The upc, tag:new and tag:hipster filters can only be used while searching albums.
11421
+ The tag:new filter will return albums released in the past two weeks and tag:hipster
11422
+ can be used to return only albums with the lowest 10% popularity.
11423
+ limit (int):
11424
+ The maximum number of items to return in a page of items.
11425
+ Default: 20, Range: 1 to 50.
11426
+ offset (int):
11427
+ The page index offset of the first item to return.
11428
+ Use with limit to get the next set of items.
11429
+ Default: 0 (the first item). Range: 0 to 1000.
11430
+ market (str):
11431
+ An ISO 3166-1 alpha-2 country code. If a country code is specified, only content that
11432
+ is available in that market will be returned. If a valid user access token is specified
11433
+ in the request header, the country associated with the user account will take priority over
11434
+ this parameter.
11435
+ Note: If neither market or user country are provided, the content is considered unavailable for the client.
11436
+ Users can view the country that is associated with their account in the account settings.
11437
+ Example: `ES`
11438
+ includeExternal (str):
11439
+ If "audio" is specified it signals that the client can play externally hosted audio content, and
11440
+ marks the content as playable in the response. By default externally hosted audio content is marked
11441
+ as unplayable in the response.
11442
+ Allowed values: "audio"
11443
+ limitTotal (int):
11444
+ The maximum number of items to return for the request.
11445
+ If specified, this argument overrides the limit and offset argument values
11446
+ and paging is automatically used to retrieve all available items up to the
11447
+ maximum number specified.
11448
+ Default: None (disabled)
11449
+
11450
+ Returns:
11451
+ A `SearchResponse` object that contains the search results.
11452
+
11453
+ Raises:
11454
+ SpotifyWebApiError:
11455
+ If the Spotify Web API request was for a non-authorization service
11456
+ and the response contains error information.
11457
+ SpotifApiError:
11458
+ If the method fails for any other reason.
11459
+
11460
+ Note that Spotify Web API automatically limits you to 1,000 max entries per type that can
11461
+ be returned with a search.
11462
+
11463
+ <details>
11464
+ <summary>Sample Code - Manual Paging</summary>
11465
+ ```python
11466
+ .. include:: ../docs/include/samplecode/SpotifyClient/SearchPlaylists.py
11467
+ ```
11468
+ </details>
11469
+ <details>
11470
+ <summary>Sample Code - Auto Paging</summary>
11471
+ ```python
11472
+ .. include:: ../docs/include/samplecode/SpotifyClient/SearchPlaylists_AutoPaging.py
11473
+ ```
11474
+ </details>
11475
+ <details>
11476
+ <summary>Sample Code - Spotify Generated, Daily Mix</summary>
11477
+ ```python
11478
+ .. include:: ../docs/include/samplecode/SpotifyClient/SearchPlaylists_Spotify_DailyMix.py
11479
+ ```
11480
+ </details>
11481
+ """
11482
+ apiMethodName:str = 'SearchPlaylists'
11483
+ apiMethodParms:SIMethodParmListContext = None
11484
+ criteriaType:str = 'playlist'
11485
+ result:PlaylistPageSimplified = None
11486
+
11487
+ try:
11488
+
11489
+ # trace.
11490
+ apiMethodParms = _logsi.EnterMethodParmList(SILevel.Debug, apiMethodName)
11491
+ apiMethodParms.AppendKeyValue("criteria", criteria)
11492
+ apiMethodParms.AppendKeyValue("criteriaType", criteriaType)
11493
+ apiMethodParms.AppendKeyValue("limit", limit)
11494
+ apiMethodParms.AppendKeyValue("offset", offset)
11495
+ apiMethodParms.AppendKeyValue("market", market)
11496
+ apiMethodParms.AppendKeyValue("includeExternal", includeExternal)
11497
+ apiMethodParms.AppendKeyValue("limitTotal", limitTotal)
11498
+ _logsi.LogMethodParmList(SILevel.Verbose, "Searching Spotify catalog for %s information" % criteriaType, apiMethodParms)
11499
+
11500
+ # validations.
11501
+ if limit is None:
11502
+ limit = 20
11503
+ if offset is None:
11504
+ offset = 0
11505
+ if not isinstance(limitTotal, int):
11506
+ limitTotal = 0
11507
+
11508
+ # are we auto-paging? if so, then use max limit.
11509
+ if limitTotal > 0:
11510
+ limit = 50
11511
+ if limit > limitTotal:
11512
+ limit = limitTotal
11513
+ result = PlaylistPageSimplified()
11514
+
11515
+ # ensure market was either supplied or implied; default if neither.
11516
+ market = self._ValidateMarket(market)
11517
+
11518
+ # build spotify web api request parameters.
11519
+ urlParms:dict = \
11520
+ {
11521
+ 'q': criteria,
11522
+ 'type': criteriaType,
11523
+ 'limit': limit,
11524
+ 'offset': offset,
11525
+ }
11526
+ if market is not None:
11527
+ urlParms['market'] = market
11528
+ if includeExternal is not None:
11529
+ urlParms['include_external'] = includeExternal
11530
+
11531
+ # handle pagination, as spotify limits us to a set # of items returned per response.
11532
+ while True:
11533
+
11534
+ # execute spotify web api request.
11535
+ msg:SpotifyApiMessage = SpotifyApiMessage(apiMethodName, '/search')
11536
+ msg.RequestHeaders[self.AuthToken.HeaderKey] = self.AuthToken.HeaderValue
11537
+ msg.UrlParameters = urlParms
11538
+ self.MakeRequest('GET', msg)
11539
+
11540
+ # process results.
11541
+ searchResponse:SearchResponse = SearchResponse(criteria, criteriaType, root=msg.ResponseData)
11542
+ pageObj = searchResponse.Playlists
11543
+
11544
+ # trace.
11545
+ _logsi.LogObject(SILevel.Verbose, (TRACE_METHOD_RESULT_TYPE_PAGE + pageObj.PagingInfo) % (apiMethodName, type(pageObj).__name__), pageObj, excludeNonPublic=True)
11546
+
11547
+ # was limit total argument specified?
11548
+ if (limitTotal <= 0):
11549
+
11550
+ # no - just return the initial page of results.
11551
+ result = pageObj
11552
+ break
11553
+
11554
+ else:
11555
+
11556
+ # append page of items to final results.
11557
+ item:PlaylistSimplified
11558
+ for item in pageObj.Items:
11559
+ result.Items.append(item)
11560
+ result.Limit = result.ItemsCount
11561
+ if result.ItemsCount >= limitTotal:
11562
+ break
11563
+
11564
+ # anymore pages to process? if not, then exit the loop.
11565
+ if not self._CheckForNextPage(pageObj, result.ItemsCount, limit, limitTotal, urlParms):
11566
+ break
11567
+
11568
+ # update result object with final paging details.
11569
+ result.Total = pageObj.Total
11570
+
11571
+ # do not sort, as spotify uses intelligent AI to return results in its order.
11572
+
11573
+ # trace.
11574
+ _logsi.LogObject(SILevel.Verbose, (TRACE_METHOD_RESULT_TYPE + result.PagingInfo) % (apiMethodName, type(result).__name__), result, excludeNonPublic=True)
11575
+
11576
+ # return a search response object.
11577
+ response:SearchResponse = SearchResponse(criteria, criteriaType)
11578
+ response.Playlists = result
11579
+ return response
11580
+
11581
+ except SpotifyWebApiError: raise # pass handled exceptions on thru
11582
+ except SpotifyWebApiAuthenticationError: raise # pass handled exceptions on thru
11583
+ except Exception as ex:
11584
+
11585
+ # format unhandled exception.
11586
+ raise SpotifyApiError(SAAppMessages.UNHANDLED_EXCEPTION.format(apiMethodName, str(ex)), ex, logsi=_logsi)
11587
+
11588
+ finally:
11589
+
11590
+ # trace.
11591
+ _logsi.LeaveMethod(SILevel.Debug, apiMethodName)
11592
+
11593
+
11594
+ def SearchShows(self,
11595
+ criteria:str,
11596
+ limit:int=20,
11597
+ offset:int=0,
11598
+ market:str=None,
11599
+ includeExternal:str=None,
11600
+ limitTotal:int=None
11601
+ ) -> SearchResponse:
11602
+ """
11603
+ Get Spotify catalog information about Shows that match a keyword string.
11604
+
11605
+ Args:
11606
+ criteria (str):
11607
+ Your search query.
11608
+ You can narrow down your search using field filters.
11609
+ The available filters are album, artist, track, year, upc, tag:hipster, tag:new,
11610
+ isrc, and genre. Each field filter only applies to certain result types.
11611
+ The artist and year filters can be used while searching albums, artists and tracks.
11612
+ You can filter on a single year or a range (e.g. 1955-1960).
11613
+ The album filter can be used while searching albums and tracks.
11614
+ The genre filter can be used while searching artists and tracks.
11615
+ The isrc and track filters can be used while searching tracks.
11616
+ The upc, tag:new and tag:hipster filters can only be used while searching albums.
11617
+ The tag:new filter will return albums released in the past two weeks and tag:hipster
11618
+ can be used to return only albums with the lowest 10% popularity.
11619
+ limit (int):
11620
+ The maximum number of items to return in a page of items.
11621
+ Default: 20, Range: 1 to 50.
11622
+ offset (int):
11623
+ The page index offset of the first item to return.
11624
+ Use with limit to get the next set of items.
11625
+ Default: 0 (the first item). Range: 0 to 1000.
11626
+ market (str):
11627
+ An ISO 3166-1 alpha-2 country code. If a country code is specified, only content that
11628
+ is available in that market will be returned. If a valid user access token is specified
11629
+ in the request header, the country associated with the user account will take priority over
11630
+ this parameter.
11631
+ Note: If neither market or user country are provided, the content is considered unavailable for the client.
11632
+ Users can view the country that is associated with their account in the account settings.
11633
+ Example: `ES`
11634
+ includeExternal (str):
11635
+ If "audio" is specified it signals that the client can play externally hosted audio content, and
11636
+ marks the content as playable in the response. By default externally hosted audio content is marked
11637
+ as unplayable in the response.
11638
+ Allowed values: "audio"
11639
+ limitTotal (int):
11640
+ The maximum number of items to return for the request.
11641
+ If specified, this argument overrides the limit and offset argument values
11642
+ and paging is automatically used to retrieve all available items up to the
11643
+ maximum number specified.
11644
+ Default: None (disabled)
11645
+
11646
+ Returns:
11647
+ A `SearchResponse` object that contains the search results.
11648
+
11649
+ Raises:
11650
+ SpotifyWebApiError:
11651
+ If the Spotify Web API request was for a non-authorization service
11652
+ and the response contains error information.
11653
+ SpotifApiError:
11654
+ If the method fails for any other reason.
11655
+
11656
+ Note that Spotify Web API automatically limits you to 1,000 max entries per type that can
11657
+ be returned with a search.
11658
+
11659
+ <details>
11660
+ <summary>Sample Code - Manual Paging</summary>
11661
+ ```python
11662
+ .. include:: ../docs/include/samplecode/SpotifyClient/SearchShows.py
11663
+ ```
11664
+ </details>
11665
+ <details>
11666
+ <summary>Sample Code - Auto Paging</summary>
11667
+ ```python
11668
+ .. include:: ../docs/include/samplecode/SpotifyClient/SearchShows_AutoPaging.py
11669
+ ```
11670
+ </details>
11671
+ """
11672
+ apiMethodName:str = 'SearchShows'
11673
+ apiMethodParms:SIMethodParmListContext = None
11674
+ criteriaType:str = 'show'
11675
+ result:ShowPageSimplified = None
11676
+
11677
+ try:
11678
+
11679
+ # trace.
11680
+ apiMethodParms = _logsi.EnterMethodParmList(SILevel.Debug, apiMethodName)
11681
+ apiMethodParms.AppendKeyValue("criteria", criteria)
11682
+ apiMethodParms.AppendKeyValue("criteriaType", criteriaType)
11683
+ apiMethodParms.AppendKeyValue("limit", limit)
11684
+ apiMethodParms.AppendKeyValue("offset", offset)
11685
+ apiMethodParms.AppendKeyValue("market", market)
11686
+ apiMethodParms.AppendKeyValue("includeExternal", includeExternal)
11687
+ apiMethodParms.AppendKeyValue("limitTotal", limitTotal)
11688
+ _logsi.LogMethodParmList(SILevel.Verbose, "Searching Spotify catalog for %s information" % criteriaType, apiMethodParms)
11689
+
11690
+ # validations.
11691
+ if limit is None:
11692
+ limit = 20
11693
+ if offset is None:
11694
+ offset = 0
11695
+ if not isinstance(limitTotal, int):
11696
+ limitTotal = 0
11697
+
11698
+ # are we auto-paging? if so, then use max limit.
11699
+ if limitTotal > 0:
11700
+ limit = 50
11701
+ if limit > limitTotal:
11702
+ limit = limitTotal
11703
+ result = ShowPageSimplified()
11704
+
11705
+ # ensure market was either supplied or implied; default if neither.
11706
+ market = self._ValidateMarket(market)
11707
+
11708
+ # build spotify web api request parameters.
11709
+ urlParms:dict = \
11710
+ {
11711
+ 'q': criteria,
11712
+ 'type': criteriaType,
11713
+ 'limit': limit,
11714
+ 'offset': offset,
11715
+ }
11716
+ if market is not None:
11717
+ urlParms['market'] = market
11718
+ if includeExternal is not None:
11719
+ urlParms['include_external'] = includeExternal
11720
+
11721
+ # handle pagination, as spotify limits us to a set # of items returned per response.
11722
+ while True:
11723
+
11724
+ # execute spotify web api request.
11725
+ msg:SpotifyApiMessage = SpotifyApiMessage(apiMethodName, '/search')
11726
+ msg.RequestHeaders[self.AuthToken.HeaderKey] = self.AuthToken.HeaderValue
11727
+ msg.UrlParameters = urlParms
11728
+ self.MakeRequest('GET', msg)
11729
+
11730
+ # process results.
11731
+ searchResponse:SearchResponse = SearchResponse(criteria, criteriaType, root=msg.ResponseData)
11732
+ pageObj = searchResponse.Shows
11733
+
11734
+ # trace.
11735
+ _logsi.LogObject(SILevel.Verbose, (TRACE_METHOD_RESULT_TYPE_PAGE + pageObj.PagingInfo) % (apiMethodName, type(pageObj).__name__), pageObj, excludeNonPublic=True)
11736
+
11737
+ # was limit total argument specified?
11738
+ if (limitTotal <= 0):
11739
+
11740
+ # no - just return the initial page of results.
11741
+ result = pageObj
11742
+ break
11743
+
11744
+ else:
11745
+
11746
+ # append page of items to final results.
11747
+ item:ShowSimplified
11748
+ for item in pageObj.Items:
11749
+ result.Items.append(item)
11750
+ result.Limit = result.ItemsCount
11751
+ if result.ItemsCount >= limitTotal:
11752
+ break
11753
+
11754
+ # anymore pages to process? if not, then exit the loop.
11755
+ if not self._CheckForNextPage(pageObj, result.ItemsCount, limit, limitTotal, urlParms):
11756
+ break
11757
+
11758
+ # update result object with final paging details.
11759
+ result.Total = pageObj.Total
11760
+
11761
+ # do not sort, as spotify uses intelligent AI to return results in its order.
11762
+
11763
+ # trace.
11764
+ _logsi.LogObject(SILevel.Verbose, (TRACE_METHOD_RESULT_TYPE + result.PagingInfo) % (apiMethodName, type(result).__name__), result, excludeNonPublic=True)
11765
+
11766
+ # return a search response object.
11767
+ response:SearchResponse = SearchResponse(criteria, criteriaType)
11768
+ response.Shows = result
11769
+ return response
11770
+
11771
+ except SpotifyWebApiError: raise # pass handled exceptions on thru
11772
+ except SpotifyWebApiAuthenticationError: raise # pass handled exceptions on thru
11773
+ except Exception as ex:
11774
+
11775
+ # format unhandled exception.
11776
+ raise SpotifyApiError(SAAppMessages.UNHANDLED_EXCEPTION.format(apiMethodName, str(ex)), ex, logsi=_logsi)
11777
+
11778
+ finally:
11779
+
11780
+ # trace.
11781
+ _logsi.LeaveMethod(SILevel.Debug, apiMethodName)
11782
+
11783
+
11784
+ def SearchTracks(self,
11785
+ criteria:str,
11786
+ limit:int=20,
11787
+ offset:int=0,
11788
+ market:str=None,
11789
+ includeExternal:str=None,
11790
+ limitTotal:int=None
11791
+ ) -> SearchResponse:
11792
+ """
11793
+ Get Spotify catalog information about Tracks that match a keyword string.
11794
+
11795
+ Args:
11796
+ criteria (str):
11797
+ Your search query.
11798
+ You can narrow down your search using field filters.
11799
+ The available filters are album, artist, track, year, upc, tag:hipster, tag:new,
11800
+ isrc, and genre. Each field filter only applies to certain result types.
11801
+ The artist and year filters can be used while searching albums, artists and tracks.
11802
+ You can filter on a single year or a range (e.g. 1955-1960).
11803
+ The album filter can be used while searching albums and tracks.
11804
+ The genre filter can be used while searching artists and tracks.
11805
+ The isrc and track filters can be used while searching tracks.
11806
+ The upc, tag:new and tag:hipster filters can only be used while searching albums.
11807
+ The tag:new filter will return albums released in the past two weeks and tag:hipster
11808
+ can be used to return only albums with the lowest 10% popularity.
11809
+ limit (int):
11810
+ The maximum number of items to return in a page of items.
11811
+ Default: 20, Range: 1 to 50.
11812
+ offset (int):
11813
+ The page index offset of the first item to return.
11814
+ Use with limit to get the next set of items.
11815
+ Default: 0 (the first item). Range: 0 to 1000.
11816
+ market (str):
11817
+ An ISO 3166-1 alpha-2 country code. If a country code is specified, only content that
11818
+ is available in that market will be returned. If a valid user access token is specified
11819
+ in the request header, the country associated with the user account will take priority over
11820
+ this parameter.
11821
+ Note: If neither market or user country are provided, the content is considered unavailable for the client.
11822
+ Users can view the country that is associated with their account in the account settings.
11823
+ Example: `ES`
11824
+ includeExternal (str):
11825
+ If "audio" is specified it signals that the client can play externally hosted audio content, and
11826
+ marks the content as playable in the response. By default externally hosted audio content is marked
11827
+ as unplayable in the response.
11828
+ Allowed values: "audio"
11829
+ limitTotal (int):
11830
+ The maximum number of items to return for the request.
11831
+ If specified, this argument overrides the limit and offset argument values
11832
+ and paging is automatically used to retrieve all available items up to the
11833
+ maximum number specified.
11834
+ Default: None (disabled)
11835
+
11836
+ Returns:
11837
+ A `SearchResponse` object that contains the search results.
11838
+
11839
+ Raises:
11840
+ SpotifyWebApiError:
11841
+ If the Spotify Web API request was for a non-authorization service
11842
+ and the response contains error information.
11843
+ SpotifApiError:
11844
+ If the method fails for any other reason.
11845
+
11846
+ Note that Spotify Web API automatically limits you to 1,000 max entries per type that can
11847
+ be returned with a search.
11848
+
11849
+ <details>
11850
+ <summary>Sample Code - Manual Paging</summary>
11851
+ ```python
11852
+ .. include:: ../docs/include/samplecode/SpotifyClient/SearchTracks.py
11853
+ ```
11854
+ </details>
11855
+ <details>
11856
+ <summary>Sample Code - Auto Paging</summary>
11857
+ ```python
11858
+ .. include:: ../docs/include/samplecode/SpotifyClient/SearchTracks_AutoPaging.py
11859
+ ```
11860
+ </details>
11861
+ """
11862
+ apiMethodName:str = 'SearchTracks'
11863
+ apiMethodParms:SIMethodParmListContext = None
11864
+ criteriaType:str = 'track'
11865
+ result:TrackPage = None
11866
+
11867
+ try:
11868
+
11869
+ # trace.
11870
+ apiMethodParms = _logsi.EnterMethodParmList(SILevel.Debug, apiMethodName)
11871
+ apiMethodParms.AppendKeyValue("criteria", criteria)
11872
+ apiMethodParms.AppendKeyValue("criteriaType", criteriaType)
11873
+ apiMethodParms.AppendKeyValue("limit", limit)
11874
+ apiMethodParms.AppendKeyValue("offset", offset)
11875
+ apiMethodParms.AppendKeyValue("market", market)
11876
+ apiMethodParms.AppendKeyValue("includeExternal", includeExternal)
11877
+ apiMethodParms.AppendKeyValue("limitTotal", limitTotal)
11878
+ _logsi.LogMethodParmList(SILevel.Verbose, "Searching Spotify catalog for %s information" % criteriaType, apiMethodParms)
11879
+
11880
+ # validations.
11881
+ if limit is None:
11882
+ limit = 20
11883
+ if offset is None:
11884
+ offset = 0
11885
+ if not isinstance(limitTotal, int):
11886
+ limitTotal = 0
11887
+
11888
+ # are we auto-paging? if so, then use max limit.
11889
+ if limitTotal > 0:
11890
+ limit = 50
11891
+ if limit > limitTotal:
11892
+ limit = limitTotal
11893
+ result = TrackPage()
11894
+
11895
+ # ensure market was either supplied or implied; default if neither.
11896
+ market = self._ValidateMarket(market)
11897
+
11898
+ # build spotify web api request parameters.
11899
+ urlParms:dict = \
11900
+ {
11901
+ 'q': criteria,
11902
+ 'type': criteriaType,
11903
+ 'limit': limit,
11904
+ 'offset': offset,
11905
+ }
11906
+ if market is not None:
11907
+ urlParms['market'] = market
11908
+ if includeExternal is not None:
11909
+ urlParms['include_external'] = includeExternal
11910
+
11911
+ # handle pagination, as spotify limits us to a set # of items returned per response.
11912
+ while True:
11913
+
11914
+ # execute spotify web api request.
11915
+ msg:SpotifyApiMessage = SpotifyApiMessage(apiMethodName, '/search')
11916
+ msg.RequestHeaders[self.AuthToken.HeaderKey] = self.AuthToken.HeaderValue
11917
+ msg.UrlParameters = urlParms
11918
+ self.MakeRequest('GET', msg)
11919
+
11920
+ # process results.
11921
+ searchResponse:SearchResponse = SearchResponse(criteria, criteriaType, root=msg.ResponseData)
11922
+ pageObj = searchResponse.Tracks
11923
+
11924
+ # trace.
11925
+ _logsi.LogObject(SILevel.Verbose, (TRACE_METHOD_RESULT_TYPE_PAGE + pageObj.PagingInfo) % (apiMethodName, type(pageObj).__name__), pageObj, excludeNonPublic=True)
11926
+
11927
+ # was limit total argument specified?
11928
+ if (limitTotal <= 0):
11929
+
11930
+ # no - just return the initial page of results.
11931
+ result = pageObj
11932
+ break
11933
+
11934
+ else:
11935
+
11936
+ # append page of items to final results.
11937
+ item:Track
11938
+ for item in pageObj.Items:
11939
+ result.Items.append(item)
11940
+ result.Limit = result.ItemsCount
11941
+ if result.ItemsCount >= limitTotal:
11942
+ break
11943
+
11944
+ # anymore pages to process? if not, then exit the loop.
11945
+ if not self._CheckForNextPage(pageObj, result.ItemsCount, limit, limitTotal, urlParms):
11946
+ break
11947
+
11948
+ # update result object with final paging details.
11949
+ result.Total = pageObj.Total
11950
+
11951
+ # do not sort, as spotify uses intelligent AI to return results in its order.
11952
+
11953
+ # trace.
11954
+ _logsi.LogObject(SILevel.Verbose, (TRACE_METHOD_RESULT_TYPE + result.PagingInfo) % (apiMethodName, type(result).__name__), result, excludeNonPublic=True)
11955
+
11956
+ # return a search response object.
11957
+ response:SearchResponse = SearchResponse(criteria, criteriaType)
11958
+ response.Tracks = result
11959
+ return response
9379
11960
 
9380
11961
  except SpotifyWebApiError: raise # pass handled exceptions on thru
9381
11962
  except SpotifyWebApiAuthenticationError: raise # pass handled exceptions on thru
@@ -9808,14 +12389,16 @@ class SpotifyClient:
9808
12389
 
9809
12390
  # note that we cannot retrieve spotify user basic details, as the client credentials
9810
12391
  # authentication type does not utilize an authorization token. in this case, we will
9811
- # build a "public access" user profile, just so we have something there.
12392
+ # build a "public access" user profile, just so we have something there.
12393
+ #
12394
+ # also note that we do not set a value for Country, as some endpoints require a country
12395
+ # (or market) code in order to work properly (e.g. any of the Search... methods).
9812
12396
  userProfile:UserProfile = UserProfile()
9813
12397
  userProfile._DisplayName = 'Public Access'
9814
12398
  userProfile._Followers = Followers()
9815
12399
  userProfile._Followers._Total = 0
9816
12400
  userProfile._Id = 'unknown'
9817
12401
  userProfile._Uri = 'spotify.user.' + userProfile._Id
9818
- userProfile._Country = 'unknown'
9819
12402
  self._UserProfile = userProfile
9820
12403
 
9821
12404
  # trace.