def request(
        self,
        url,
        params=None,
        data=None,
        headers=None,
        timeout=None,
        auth=None,
        cookiejar=None,
        retry_times=None,
        retry_wait=None,
    ):
        """
        Make a request to a url and retrieve the results.

        If the headers parameter does not provide an 'User-Agent' key, one will
        be added automatically following the convention:

            py3status/<version> <per session random uuid>

        :param url: url to request eg `http://example.com`
        :param params: extra query string parameters as a dict
        :param data: POST data as a dict.  If this is not supplied the GET method will be used
        :param headers: http headers to be added to the request as a dict
        :param timeout: timeout for the request in seconds
        :param auth: authentication info as tuple `(username, password)`
        :param cookiejar: an object of a CookieJar subclass
        :param retry_times: how many times to retry the request
        :param retry_wait: how long to wait between retries in seconds

        :returns: HttpResponse
        """

        # The aim of this function is to be a limited lightweight replacement
        # for the requests library but using only pythons standard libs.

        # IMPORTANT NOTICE
        # This function is excluded from private variable hiding as it is
        # likely to need api keys etc which people may have obfuscated.
        # Therefore it is important that no logging is done in this function
        # that might reveal this information.

        if headers is None:
            headers = {}

        if timeout is None:
            timeout = getattr(self._py3status_module, "request_timeout", 10)

        if retry_times is None:
            retry_times = getattr(self._py3status_module, "request_retry_times", 3)

        if retry_wait is None:
            retry_wait = getattr(self._py3status_module, "request_retry_wait", 2)

        if "User-Agent" not in headers:
            headers["User-Agent"] = f"py3status/{version} {self._uid}"

        def get_http_response():
            return HttpResponse(
                url,
                params=params,
                data=data,
                headers=headers,
                timeout=timeout,
                auth=auth,
                cookiejar=cookiejar,
            )

        for n in range(1, retry_times):
            try:
                return get_http_response()
            except (self.RequestTimeout, self.RequestURLError):
                self.log(f"HTTP request retry {n}/{retry_times}")
                sleep(retry_wait)
        self.log(f"HTTP request retry {retry_times}/{retry_times}")
        sleep(retry_wait)
        return get_http_response()

        Make a request to a url and retrieve the results.

        If the headers parameter does not provide an 'User-Agent' key, one will
        be added automatically following the convention:

            py3status/<version> <per session random uuid>

        :param url: url to request eg `http://example.com`
        :param params: extra query string parameters as a dict
        :param data: POST data as a dict.  If this is not supplied the GET method will be used
        :param headers: http headers to be added to the request as a dict
        :param timeout: timeout for the request in seconds
        :param auth: authentication info as tuple `(username, password)`
        :param cookiejar: an object of a CookieJar subclass
        :param retry_times: how many times to retry the request
        :param retry_wait: how long to wait between retries in seconds

        :returns: HttpResponse
        
py3status/py3.py