aboutsummaryrefslogtreecommitdiff
path: root/pandora/client.py
diff options
context:
space:
mode:
Diffstat (limited to 'pandora/client.py')
-rw-r--r--pandora/client.py36
1 files changed, 36 insertions, 0 deletions
diff --git a/pandora/client.py b/pandora/client.py
index a98056c..ff27678 100644
--- a/pandora/client.py
+++ b/pandora/client.py
@@ -14,6 +14,7 @@ For simplicity use a client builder from pandora.clientbuilder to create an
14instance of a client. 14instance of a client.
15""" 15"""
16from . import errors 16from . import errors
17from .ratelimit import WarningTokenBucket
17 18
18 19
19class BaseAPIClient: 20class BaseAPIClient:
@@ -36,7 +37,27 @@ class BaseAPIClient:
36 partner_password, 37 partner_password,
37 device, 38 device,
38 default_audio_quality=MED_AUDIO_QUALITY, 39 default_audio_quality=MED_AUDIO_QUALITY,
40 rate_limiter=WarningTokenBucket,
39 ): 41 ):
42 """Initialize an API Client
43
44 transport
45 instance of a Pandora transport
46 partner_user
47 partner username
48 partner_password
49 partner password
50 device
51 device type identifier
52 default_audio_quality
53 audio quality level, one of the *_AUDIO_QUALITY constants in the
54 BaseAPIClient class
55 rate_limiter
56 class (not instance) implementing the pandora.ratelimit.TokenBucket
57 interface. Used by various client components to handle rate
58 limits with the Pandora API. The default rate limited warns when
59 the rate limit has been exceeded but does not enforce the limit.
60 """
40 self.transport = transport 61 self.transport = transport
41 self.partner_user = partner_user 62 self.partner_user = partner_user
42 self.partner_password = partner_password 63 self.partner_password = partner_password
@@ -45,6 +66,17 @@ class BaseAPIClient:
45 self.username = None 66 self.username = None
46 self.password = None 67 self.password = None
47 68
69 # Global rate limiter for all methods, allows a call rate of 2 calls
70 # per second. This limit is based on nothing but seems sane to prevent
71 # runaway code from hitting Pandora too hard.
72 self._api_limiter = rate_limiter(120, 1, 1)
73
74 # Rate limiter for the get_playlist API which has a much lower
75 # server-side limit than other APIs. This was determined
76 # experimentally. This is applied before and in addition to the global
77 # API rate limit.
78 self._playlist_limiter = rate_limiter(5, 1, 1)
79
48 def _partner_login(self): 80 def _partner_login(self):
49 partner = self.transport( 81 partner = self.transport(
50 "auth.partnerLogin", 82 "auth.partnerLogin",
@@ -98,6 +130,8 @@ class BaseAPIClient:
98 return [] 130 return []
99 131
100 def __call__(self, method, **kwargs): 132 def __call__(self, method, **kwargs):
133 self._api_limiter.consume(1)
134
101 try: 135 try:
102 return self.transport(method, **kwargs) 136 return self.transport(method, **kwargs)
103 except errors.InvalidAuthToken: 137 except errors.InvalidAuthToken:
@@ -125,6 +159,8 @@ class APIClient(BaseAPIClient):
125 def get_playlist(self, station_token, additional_urls=None): 159 def get_playlist(self, station_token, additional_urls=None):
126 from .models.playlist import Playlist 160 from .models.playlist import Playlist
127 161
162 self._playlist_limiter.consume(1)
163
128 if additional_urls is None: 164 if additional_urls is None:
129 additional_urls = [] 165 additional_urls = []
130 166