Cache the token request and use cached responses if available

def _cached_request(self, base_url, client_id, client_secret,
                        parameters, **kwargs):
        """Cache the token request and use cached responses if available"""
        key = (base_url, client_id, tuple(parameters.items()))
        cached = self._cache.get(key, {})

        if not cached.get('access_token') or self._expired(cached):
            cached = yield self._request(base_url, client_id, client_secret,
                                         parameters, **kwargs)
            self._cache[key] = cached
            # Purge cache when adding a new item so it doesn't grow too large
            # It's assumed the cache size is small enough that it's OK to loop
            # over the whole cache regularly. If not, could change this to
            # just pop off the oldest one
            self.purge_cache()

        logging.debug('Using a cached token: %s', cached.get('access_token'))
        raise Return(cached)