def request(self, method, url, path=(), extension=None, suffix=None,<EOL>params=None, headers=None, data=None, debug=None,<EOL>cache_lifetime=None, silent=None, ignore_cache=False,<EOL>format='<STR_LIT>', delay=<NUM_LIT:0.0>, formatter=None, **kwargs):
if debug is None:<EOL><INDENT>debug = self.debug<EOL><DEDENT>request_headers = dict(self.headers.__dict__)<EOL>if headers is not None:<EOL><INDENT>request_headers.update(headers)<EOL><DEDENT>if type(format) in (list, tuple) and len(format) == <NUM_LIT:2>:<EOL><INDENT>request_format, response_format = format<EOL><DEDENT>else:<EOL><INDENT>request_format = response_format = format<EOL><DEDENT>if request_format and (data is not None):<EOL><INDENT>request_headers.setdefault(<EOL>'<STR_LIT:Content-Type>', formats.meta(request_format).get('<STR_LIT>'))<EOL>data = formats.compose(request_format, data)<EOL><DEDENT>if not hasattr(path, "<STR_LIT>"):<EOL><INDENT>path = '<STR_LIT:/>'.join(path)<EOL><DEDENT>if extension is None:<EOL><INDENT>extension = '<STR_LIT>'<EOL><DEDENT>elif not extension.startswith('<STR_LIT:.>'):<EOL><INDENT>extension = '<STR_LIT:.>' + extension<EOL><DEDENT>if suffix is None:<EOL><INDENT>suffix = '<STR_LIT>'<EOL><DEDENT>url = '<STR_LIT>' % (url, path, extension, suffix)<EOL>self._log(debug_messages['<STR_LIT>'], debug, method=method.upper(),<EOL>url=url, headers=request_headers, params=params, data=data)<EOL>cache_key = (url, str(params), str(headers))<EOL>if self.cache.has(cache_key) and not ignore_cache:<EOL><INDENT>item = self.cache.get(cache_key)<EOL>self._log(debug_messages['<STR_LIT>'], debug, text=item)<EOL>return bunchify(item)<EOL><DEDENT>if delay > <NUM_LIT:0>:<EOL><INDENT>t = time.time()<EOL>if self._last_request_time is None:<EOL><INDENT>self._last_request_time = t<EOL><DEDENT>elapsed = t - self._last_request_time<EOL>if elapsed < delay:<EOL><INDENT>time.sleep(delay - elapsed)<EOL><DEDENT><DEDENT>for name, value in self.defaults.items():<EOL><INDENT>kwargs.setdefault(name, value)<EOL><DEDENT>r = self.send_request(method, url, params=params,<EOL>headers=request_headers, data=data, **kwargs)<EOL>self._last_request_time = time.time()<EOL>if not silent:<EOL><INDENT>r.raise_for_status()<EOL><DEDENT>try:<EOL><INDENT>has_body = len(r.text) > <NUM_LIT:0><EOL>if not has_body:<EOL><INDENT>parsed_response = '<STR_LIT>'<EOL><DEDENT>else:<EOL><INDENT>parsed_response = formats.parse(response_format, r.text)<EOL><DEDENT><DEDENT>except ValueError as e:<EOL><INDENT>if len(r.text) > DEBUG_MAX_TEXT_LENGTH:<EOL><INDENT>text = r.text[:DEBUG_MAX_TEXT_LENGTH] + '<STR_LIT>'<EOL><DEDENT>else:<EOL><INDENT>text = r.text<EOL><DEDENT>self._log(debug_messages['<STR_LIT>'], debug,<EOL>format=response_format, status_code=r.status_code,<EOL>reason=r.reason, text=text)<EOL>if silent:<EOL><INDENT>return None<EOL><DEDENT>raise e<EOL><DEDENT>if cache_lifetime and cache_lifetime > <NUM_LIT:0> and method.lower() == '<STR_LIT>':<EOL><INDENT>self.cache.set(cache_key, parsed_response, cache_lifetime)<EOL><DEDENT>debug_message = '<STR_LIT>' if r.status_code == <NUM_LIT:200> else'<STR_LIT>'<EOL>self._log(debug_messages[debug_message], debug,<EOL>status_code=r.status_code, reason=r.reason,<EOL>text=parsed_response)<EOL>if has_body:<EOL><INDENT>return bunchify(parsed_response)<EOL><DEDENT>return None<EOL>
Requests a URL and returns a *Bunched* response.

        This method basically wraps the request method of the requests
        module and adds a `path` and `debug` option.

        A `ValueError` will be thrown if the response is not JSON encoded.

        :param method: The request method, e.g. 'get', 'post', etc.
        :param url: The URL to request
        :param path: (optional) Appended to the request URL. This can be
            either a string or a list which will be joined
            by forward slashes.
        :param extension: (optional) The extension to append to the URL.
        :param suffix: (optional) Append stuff like trailing slashes the URL.
        :param params: (optional) The URL query parameters
        :param headers: (optional) Extra headers to sent with the request.
            Existing header keys can be overwritten.
        :param data: (optional) Dictionary
        :param debug: (optional) Overwrite of `Client.debug`
        :param cache_lifetime: (optional) The amount of seconds that the
            response has to be cached for.
        :param silent: (optional) When ``True`, any exception resulted
            from HTTP status codes or parsing will be ignored.
        :param ignore_cache: (optional) When ``True``, a previously
            cached response of the same request will be ignored.
        :param format: (optional) The type of request data to parse.
            May take the following values:
              - 'json', 'xml', ... both request data load and response are
                converted to the specified format
              - (None, 'json') a tuple, with the request data format in pos 0
                and the response format in pos 1
            defaults to 'json'
        :param delay: (option) Ensures a minimum delay of seconds between
            requests.
        :param kwargs: (optional) Arguments that will be passed to
            the `requests.request` method
        :return: :class:`Bunch` object from JSON-parsed response