Handles retrying failed requests and error handling.

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')
        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:
                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)
        # 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