<SYSTEM_TASK:>
Solve the following problem using Python, implementing the functions described below, one line at a time
<END_TASK>
<USER_TASK:>
Description:
 def request( self, method, endpoint=None, headers=None, use_auth=True, _url=None, _kwargs=None, **kwargs):
 """ Make a request to the Canvas API and return the response. :param method: The HTTP method for the request. :type method: str :param endpoint: The endpoint to call. :type endpoint: str :param headers: Optional HTTP headers to be sent with the request. :type headers: dict :param use_auth: Optional flag to remove the authentication header from the request. :type use_auth: bool :param _url: Optional argument to send a request to a URL outside of the Canvas API. If this is selected and an endpoint is provided, the endpoint will be ignored and only the _url argument will be used. :type _url: str :param _kwargs: A list of 2-tuples representing processed keyword arguments to be sent to Canvas as params or data. :type _kwargs: `list` :rtype: str """

        full_url = _url if _url else "{}{}".format(self.base_url, endpoint)

        if not headers:
            headers = {}

        if use_auth:
            auth_header = {'Authorization': 'Bearer {}'.format(self.access_token)}
            headers.update(auth_header)

        # Convert kwargs into list of 2-tuples and combine with _kwargs.
        _kwargs = _kwargs or []
        _kwargs.extend(kwargs.items())

        # Do any final argument processing before sending to request method.
        for i, kwarg in enumerate(_kwargs):
            kw, arg = kwarg

            # Convert boolean objects to a lowercase string.
            if isinstance(arg, bool):
                _kwargs[i] = (kw, str(arg).lower())

            # Convert any datetime objects into ISO 8601 formatted strings.
            elif isinstance(arg, datetime):
                _kwargs[i] = (kw, arg.isoformat())

        # Determine the appropriate request method.
        if method == 'GET':
            req_method = self._get_request
        elif method == 'POST':
            req_method = self._post_request
        elif method == 'DELETE':
            req_method = self._delete_request
        elif method == 'PUT':
            req_method = self._put_request

        # Call the request method
        response = req_method(full_url, headers, _kwargs)

        # Add response to internal cache
        if len(self._cache) > 4:
            self._cache.pop()

        self._cache.insert(0, response)

        # Raise for status codes
        if response.status_code == 400:
            raise BadRequest(response.text)
        elif response.status_code == 401:
            if 'WWW-Authenticate' in response.headers:
                raise InvalidAccessToken(response.json())
            else:
                raise Unauthorized(response.json())
        elif response.status_code == 403:
            raise Forbidden(response.text)
        elif response.status_code == 404:
            raise ResourceDoesNotExist('Not Found')
        elif response.status_code == 409:
            raise Conflict(response.text)
        elif response.status_code == 500:
            raise CanvasException("API encountered an error processing your request")

        return response