1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207
|
import json
from math import ceil
from twilio.base import values
from twilio.base.exceptions import TwilioRestException
class Version(object):
"""
Represents an API version.
"""
def __init__(self, domain):
"""
:param Domain domain:
:return:
"""
self.domain = domain
self.version = None
def absolute_url(self, uri):
"""
Turns a relative uri into an absolute url.
"""
return self.domain.absolute_url(self.relative_uri(uri))
def relative_uri(self, uri):
"""
Turns a relative uri into a versioned relative uri.
"""
return '{}/{}'.format(self.version.strip('/'), uri.strip('/'))
def request(self, method, uri, params=None, data=None, headers=None,
auth=None, timeout=None, allow_redirects=False):
"""
Make an HTTP request.
"""
url = self.relative_uri(uri)
return self.domain.request(
method,
url,
params=params,
data=data,
headers=headers,
auth=auth,
timeout=timeout,
allow_redirects=allow_redirects
)
@classmethod
def exception(cls, method, uri, response, message):
"""
Wraps an exceptional response in a `TwilioRestException`.
"""
# noinspection PyBroadException
try:
error_payload = json.loads(response.text)
if 'message' in error_payload:
message = '{}: {}'.format(message, error_payload['message'])
details = error_payload.get('details')
code = error_payload.get('code', response.status_code)
return TwilioRestException(response.status_code, uri, message, code, method, details)
except Exception:
return TwilioRestException(response.status_code, uri, message, response.status_code,
method)
def fetch(self, method, uri, params=None, data=None, headers=None, auth=None, timeout=None,
allow_redirects=False):
"""
Fetch a resource instance.
"""
response = self.request(
method,
uri,
params=params,
data=data,
headers=headers,
auth=auth,
timeout=timeout,
allow_redirects=allow_redirects,
)
# Note that 3XX response codes are allowed for fetches.
if response.status_code < 200 or response.status_code >= 400:
raise self.exception(method, uri, response, 'Unable to fetch record')
return json.loads(response.text)
def update(self, method, uri, params=None, data=None, headers=None, auth=None, timeout=None,
allow_redirects=False):
"""
Update a resource instance.
"""
response = self.request(
method,
uri,
params=params,
data=data,
headers=headers,
auth=auth,
timeout=timeout,
allow_redirects=allow_redirects,
)
if response.status_code < 200 or response.status_code >= 300:
raise self.exception(method, uri, response, 'Unable to update record')
return json.loads(response.text)
def delete(self, method, uri, params=None, data=None, headers=None, auth=None, timeout=None,
allow_redirects=False):
"""
Delete a resource.
"""
response = self.request(
method,
uri,
params=params,
data=data,
headers=headers,
auth=auth,
timeout=timeout,
allow_redirects=allow_redirects,
)
if response.status_code < 200 or response.status_code >= 300:
raise self.exception(method, uri, response, 'Unable to delete record')
return response.status_code == 204
def read_limits(self, limit=None, page_size=None):
"""
Takes a limit on the max number of records to read and a max page_size
and calculates the max number of pages to read.
:param int limit: Max number of records to read.
:param int page_size: Max page size.
:return dict: A dictionary of paging limits.
"""
if limit is not None and page_size is None:
page_size = limit
return {
'limit': limit or values.unset,
'page_size': page_size or values.unset,
}
def page(self, method, uri, params=None, data=None, headers=None, auth=None, timeout=None,
allow_redirects=False):
"""
Makes an HTTP request.
"""
return self.request(
method,
uri,
params=params,
data=data,
headers=headers,
auth=auth,
timeout=timeout,
allow_redirects=allow_redirects,
)
def stream(self, page, limit=None, page_limit=None):
"""
Generates records one a time from a page, stopping at prescribed limits.
:param Page page: The page to stream.
:param int limit: The max number of records to read.
:param int page_limit: The max number of pages to read.
"""
current_record = 1
current_page = 1
while page is not None:
for record in page:
yield record
current_record += 1
if limit and limit is not values.unset and limit < current_record:
return
current_page += 1
if page_limit and page_limit is not values.unset and page_limit < current_page:
return
page = page.next_page()
def create(self, method, uri, params=None, data=None, headers=None, auth=None, timeout=None,
allow_redirects=False):
"""
Create a resource instance.
"""
response = self.request(
method,
uri,
params=params,
data=data,
headers=headers,
auth=auth,
timeout=timeout,
allow_redirects=allow_redirects,
)
if response.status_code < 200 or response.status_code >= 300:
raise self.exception(method, uri, response, 'Unable to create record')
return json.loads(response.text)
|