def _request(self, method, endpoint, id=None, **kwargs): "Handles retrying failed requests and error handling." request = getattr(requests, method, None) if not callable(request): raise RequestError('Invalid method %s' % method) # Find files, separate them out to correct kwarg for requests. data = kwargs.get('data') mpe_data = None if data: files = {} for name, value in list(data.items()): # Value might be a file-like object (with a read method), or it # might be a (filename, file-like) tuple. if hasattr(value, 'read') or isinstance(value, tuple): files[name] = data.pop(name) if files: mpe_data = MultipartEncoder(fields=files) kwargs['data'] = mpe_data # kwargs.setdefault('files', {}).update(files) path = ['api', self.version, endpoint] # If we received an ID, append it to the path. if id: path.append(str(id)) # Join fragments into a URL path = '/'.join(path) if not path.endswith('/'): path += '/' while '//' in path: path = path.replace('//', '/') url = self.url + path # Add our user agent. kwargs.setdefault('headers', {}).setdefault('User-Agent', HTTP_USER_AGENT) if mpe_data: kwargs['headers']['content-type'] = mpe_data.content_type # Now try the request, if we get throttled, sleep and try again. trys, retrys = 0, 3 while True: if trys == retrys: raise RequestError('Could not complete request after %s trys.' % trys) trys += 1 try: return self._do_request(request, url, **kwargs) except ResponseError as e: if self.throttle_wait and e.status_code == 503: m = THROTTLE_PATTERN.match( e.response.headers.get('x-throttle', '')) if m: time.sleep(float(m.group(1))) continue # Failed for a reason other than throttling. raise
def _do_request(self, request, url, **kwargs): "Actually makes the HTTP request." try: response = request(url, stream=True, **kwargs) except RequestException as e: raise RequestError(e) else: if response.status_code >= 400: raise ResponseError(response) # Try to return the response in the most useful fashion given it's # type. if response.headers.get('content-type') == 'application/json': try: # Try to decode as JSON return response.json() except (TypeError, ValueError): # If that fails, return the text. return response.text else: # This might be a file, so return it. if kwargs.get('params', {}).get('raw', True): return response.raw else: return response
def _do_request(self, request, url, **kwargs): "Actually makes the HTTP request." try: response = request(url, stream=True, **kwargs) except RequestException, e: raise RequestError(e)