diff --git a/.local/bin/speedtest-cli b/.local/bin/speedtest-cli
index a33296d..18d1673 100755
--- a/.local/bin/speedtest-cli
+++ b/.local/bin/speedtest-cli
@@ -1,4 +1,4 @@
-#!/usr/bin/env python
+#!/usr/bin/env python3
 # -*- coding: utf-8 -*-
 # Copyright 2012 Matt Martz
 # All Rights Reserved.
@@ -31,12 +31,13 @@ import xml.parsers.expat
 
 try:
     import gzip
+
     GZIP_BASE = gzip.GzipFile
 except ImportError:
     gzip = None
     GZIP_BASE = object
 
-__version__ = '2.1.3'
+__version__ = "2.1.3"
 
 
 class FakeShutdownEvent(object):
@@ -46,7 +47,7 @@ class FakeShutdownEvent(object):
 
     @staticmethod
     def isSet():
-        "Dummy method to always return false"""
+        "Dummy method to always return false" ""
         return False
 
 
@@ -68,6 +69,7 @@ except ImportError:
 
 try:
     import xml.etree.ElementTree as ET
+
     try:
         from xml.etree.ElementTree import _Element as ET_Element
     except ImportError:
@@ -75,18 +77,35 @@ try:
 except ImportError:
     from xml.dom import minidom as DOM
     from xml.parsers.expat import ExpatError
+
     ET = None
 
 try:
-    from urllib2 import (urlopen, Request, HTTPError, URLError,
-                         AbstractHTTPHandler, ProxyHandler,
-                         HTTPDefaultErrorHandler, HTTPRedirectHandler,
-                         HTTPErrorProcessor, OpenerDirector)
+    from urllib2 import (
+        urlopen,
+        Request,
+        HTTPError,
+        URLError,
+        AbstractHTTPHandler,
+        ProxyHandler,
+        HTTPDefaultErrorHandler,
+        HTTPRedirectHandler,
+        HTTPErrorProcessor,
+        OpenerDirector,
+    )
 except ImportError:
-    from urllib.request import (urlopen, Request, HTTPError, URLError,
-                                AbstractHTTPHandler, ProxyHandler,
-                                HTTPDefaultErrorHandler, HTTPRedirectHandler,
-                                HTTPErrorProcessor, OpenerDirector)
+    from urllib.request import (
+        urlopen,
+        Request,
+        HTTPError,
+        URLError,
+        AbstractHTTPHandler,
+        ProxyHandler,
+        HTTPDefaultErrorHandler,
+        HTTPRedirectHandler,
+        HTTPErrorProcessor,
+        OpenerDirector,
+    )
 
 try:
     from httplib import HTTPConnection, BadStatusLine
@@ -132,22 +151,26 @@ except ImportError:
 try:
     from argparse import ArgumentParser as ArgParser
     from argparse import SUPPRESS as ARG_SUPPRESS
+
     PARSER_TYPE_INT = int
     PARSER_TYPE_STR = str
     PARSER_TYPE_FLOAT = float
 except ImportError:
     from optparse import OptionParser as ArgParser
     from optparse import SUPPRESS_HELP as ARG_SUPPRESS
-    PARSER_TYPE_INT = 'int'
-    PARSER_TYPE_STR = 'string'
-    PARSER_TYPE_FLOAT = 'float'
+
+    PARSER_TYPE_INT = "int"
+    PARSER_TYPE_STR = "string"
+    PARSER_TYPE_FLOAT = "float"
 
 try:
     from cStringIO import StringIO
+
     BytesIO = None
 except ImportError:
     try:
         from StringIO import StringIO
+
         BytesIO = None
     except ImportError:
         from io import StringIO, BytesIO
@@ -162,19 +185,18 @@ except ImportError:
         """UTF-8 encoded wrapper around stdout for py3, to override
         ASCII stdout
         """
+
         def __init__(self, f, **kwargs):
-            buf = FileIO(f.fileno(), 'w')
+            buf = FileIO(f.fileno(), "w")
             super(_Py3Utf8Output, self).__init__(
-                buf,
-                encoding='utf8',
-                errors='strict'
+                buf, encoding="utf8", errors="strict"
             )
 
         def write(self, s):
             super(_Py3Utf8Output, self).write(s)
             self.flush()
 
-    _py3_print = getattr(builtins, 'print')
+    _py3_print = getattr(builtins, "print")
     try:
         _py3_utf8_stdout = _Py3Utf8Output(sys.stdout)
         _py3_utf8_stderr = _Py3Utf8Output(sys.stderr)
@@ -190,18 +212,19 @@ except ImportError:
 
     def print_(*args, **kwargs):
         """Wrapper function for py3 to print, with a utf-8 encoded stdout"""
-        if kwargs.get('file') == sys.stderr:
-            kwargs['file'] = _py3_utf8_stderr
+        if kwargs.get("file") == sys.stderr:
+            kwargs["file"] = _py3_utf8_stderr
         else:
-            kwargs['file'] = kwargs.get('file', _py3_utf8_stdout)
+            kwargs["file"] = kwargs.get("file", _py3_utf8_stdout)
         _py3_print(*args, **kwargs)
+
 else:
     del __builtin__
 
     def to_utf8(v):
         """Encode value to utf-8 if possible for py2"""
         try:
-            return v.encode('utf8', 'strict')
+            return v.encode("utf8", "strict")
         except AttributeError:
             return v
 
@@ -220,16 +243,19 @@ else:
             if not isinstance(data, basestring):
                 data = str(data)
             # If the file has an encoding, encode unicode with it.
-            encoding = 'utf8'  # Always trust UTF-8 for output
-            if (isinstance(fp, file) and
-                    isinstance(data, unicode) and
-                    encoding is not None):
+            encoding = "utf8"  # Always trust UTF-8 for output
+            if (
+                isinstance(fp, file)
+                and isinstance(data, unicode)
+                and encoding is not None
+            ):
                 errors = getattr(fp, "errors", None)
                 if errors is None:
                     errors = "strict"
                 data = data.encode(encoding, errors)
             fp.write(data)
             fp.flush()
+
         want_unicode = False
         sep = kwargs.pop("sep", None)
         if sep is not None:
@@ -266,6 +292,7 @@ else:
             write(arg)
         write(end)
 
+
 if PY32PLUS:
     etree_iter = ET.Element.iter
 elif PY25PLUS:
@@ -280,15 +307,19 @@ else:
 # Exception "constants" to support Python 2 through Python 3
 try:
     import ssl
+
     try:
         CERT_ERROR = (ssl.CertificateError,)
     except AttributeError:
         CERT_ERROR = tuple()
 
     HTTP_ERRORS = (
-        (HTTPError, URLError, socket.error, ssl.SSLError, BadStatusLine) +
-        CERT_ERROR
-    )
+        HTTPError,
+        URLError,
+        socket.error,
+        ssl.SSLError,
+        BadStatusLine,
+    ) + CERT_ERROR
 except ImportError:
     ssl = None
     HTTP_ERRORS = (HTTPError, URLError, socket.error, BadStatusLine)
@@ -364,8 +395,9 @@ class SpeedtestMissingBestServer(SpeedtestException):
     """get_best_server not called or not able to determine best server"""
 
 
-def create_connection(address, timeout=_GLOBAL_DEFAULT_TIMEOUT,
-                      source_address=None):
+def create_connection(
+    address, timeout=_GLOBAL_DEFAULT_TIMEOUT, source_address=None
+):
     """Connect to *address* and return the socket object.
 
     Convenience function.  Connect to *address* (a 2-tuple ``(host,
@@ -409,9 +441,10 @@ class SpeedtestHTTPConnection(HTTPConnection):
     """Custom HTTPConnection to support source_address across
     Python 2.4 - Python 3
     """
+
     def __init__(self, *args, **kwargs):
-        source_address = kwargs.pop('source_address', None)
-        timeout = kwargs.pop('timeout', 10)
+        source_address = kwargs.pop("source_address", None)
+        timeout = kwargs.pop("timeout", 10)
 
         self._tunnel_host = None
 
@@ -424,15 +457,11 @@ class SpeedtestHTTPConnection(HTTPConnection):
         """Connect to the host and port specified in __init__."""
         try:
             self.sock = socket.create_connection(
-                (self.host, self.port),
-                self.timeout,
-                self.source_address
+                (self.host, self.port), self.timeout, self.source_address
             )
         except (AttributeError, TypeError):
             self.sock = create_connection(
-                (self.host, self.port),
-                self.timeout,
-                self.source_address
+                (self.host, self.port), self.timeout, self.source_address
             )
 
         if self._tunnel_host:
@@ -440,15 +469,17 @@ class SpeedtestHTTPConnection(HTTPConnection):
 
 
 if HTTPSConnection:
+
     class SpeedtestHTTPSConnection(HTTPSConnection):
         """Custom HTTPSConnection to support source_address across
         Python 2.4 - Python 3
         """
+
         default_port = 443
 
         def __init__(self, *args, **kwargs):
-            source_address = kwargs.pop('source_address', None)
-            timeout = kwargs.pop('timeout', 10)
+            source_address = kwargs.pop("source_address", None)
+            timeout = kwargs.pop("timeout", 10)
 
             self._tunnel_host = None
 
@@ -461,15 +492,11 @@ if HTTPSConnection:
             "Connect to a host on a given (SSL) port."
             try:
                 self.sock = socket.create_connection(
-                    (self.host, self.port),
-                    self.timeout,
-                    self.source_address
+                    (self.host, self.port), self.timeout, self.source_address
                 )
             except (AttributeError, TypeError):
                 self.sock = create_connection(
-                    (self.host, self.port),
-                    self.timeout,
-                    self.source_address
+                    (self.host, self.port), self.timeout, self.source_address
                 )
 
             if self._tunnel_host:
@@ -478,11 +505,11 @@ if HTTPSConnection:
             if ssl:
                 try:
                     kwargs = {}
-                    if hasattr(ssl, 'SSLContext'):
+                    if hasattr(ssl, "SSLContext"):
                         if self._tunnel_host:
-                            kwargs['server_hostname'] = self._tunnel_host
+                            kwargs["server_hostname"] = self._tunnel_host
                         else:
-                            kwargs['server_hostname'] = self.host
+                            kwargs["server_hostname"] = self.host
                     self.sock = self._context.wrap_socket(self.sock, **kwargs)
                 except AttributeError:
                     self.sock = ssl.wrap_socket(self.sock)
@@ -496,13 +523,13 @@ if HTTPSConnection:
                     self.sock = FakeSocket(self.sock, socket.ssl(self.sock))
                 except AttributeError:
                     raise SpeedtestException(
-                        'This version of Python does not support HTTPS/SSL '
-                        'functionality'
+                        "This version of Python does not support HTTPS/SSL "
+                        "functionality"
                     )
             else:
                 raise SpeedtestException(
-                    'This version of Python does not support HTTPS/SSL '
-                    'functionality'
+                    "This version of Python does not support HTTPS/SSL "
+                    "functionality"
                 )
 
 
@@ -513,14 +540,13 @@ def _build_connection(connection, source_address, timeout, context=None):
     Called from ``http(s)_open`` methods of ``SpeedtestHTTPHandler`` or
     ``SpeedtestHTTPSHandler``
     """
+
     def inner(host, **kwargs):
-        kwargs.update({
-            'source_address': source_address,
-            'timeout': timeout
-        })
+        kwargs.update({"source_address": source_address, "timeout": timeout})
         if context:
-            kwargs['context'] = context
+            kwargs["context"] = context
         return connection(host, **kwargs)
+
     return inner
 
 
@@ -528,6 +554,7 @@ class SpeedtestHTTPHandler(AbstractHTTPHandler):
     """Custom ``HTTPHandler`` that can build a ``HTTPConnection`` with the
     args we need for ``source_address`` and ``timeout``
     """
+
     def __init__(self, debuglevel=0, source_address=None, timeout=10):
         AbstractHTTPHandler.__init__(self, debuglevel)
         self.source_address = source_address
@@ -536,11 +563,9 @@ class SpeedtestHTTPHandler(AbstractHTTPHandler):
     def http_open(self, req):
         return self.do_open(
             _build_connection(
-                SpeedtestHTTPConnection,
-                self.source_address,
-                self.timeout
+                SpeedtestHTTPConnection, self.source_address, self.timeout
             ),
-            req
+            req,
         )
 
     http_request = AbstractHTTPHandler.do_request_
@@ -550,8 +575,10 @@ class SpeedtestHTTPSHandler(AbstractHTTPHandler):
     """Custom ``HTTPSHandler`` that can build a ``HTTPSConnection`` with the
     args we need for ``source_address`` and ``timeout``
     """
-    def __init__(self, debuglevel=0, context=None, source_address=None,
-                 timeout=10):
+
+    def __init__(
+        self, debuglevel=0, context=None, source_address=None, timeout=10
+    ):
         AbstractHTTPHandler.__init__(self, debuglevel)
         self._context = context
         self.source_address = source_address
@@ -565,7 +592,7 @@ class SpeedtestHTTPSHandler(AbstractHTTPHandler):
                 self.timeout,
                 context=self._context,
             ),
-            req
+            req,
         )
 
     https_request = AbstractHTTPHandler.do_request_
@@ -578,28 +605,32 @@ def build_opener(source_address=None, timeout=10):
     `User-Agent`
     """
 
-    printer('Timeout set to %d' % timeout, debug=True)
+    printer("Timeout set to %d" % timeout, debug=True)
 
     if source_address:
         source_address_tuple = (source_address, 0)
-        printer('Binding to source address: %r' % (source_address_tuple,),
-                debug=True)
+        printer(
+            "Binding to source address: %r" % (source_address_tuple,),
+            debug=True,
+        )
     else:
         source_address_tuple = None
 
     handlers = [
         ProxyHandler(),
-        SpeedtestHTTPHandler(source_address=source_address_tuple,
-                             timeout=timeout),
-        SpeedtestHTTPSHandler(source_address=source_address_tuple,
-                              timeout=timeout),
+        SpeedtestHTTPHandler(
+            source_address=source_address_tuple, timeout=timeout
+        ),
+        SpeedtestHTTPSHandler(
+            source_address=source_address_tuple, timeout=timeout
+        ),
         HTTPDefaultErrorHandler(),
         HTTPRedirectHandler(),
-        HTTPErrorProcessor()
+        HTTPErrorProcessor(),
     ]
 
     opener = OpenerDirector()
-    opener.addheaders = [('User-agent', build_user_agent())]
+    opener.addheaders = [("User-agent", build_user_agent())]
 
     for handler in handlers:
         opener.add_handler(handler)
@@ -614,12 +645,15 @@ class GzipDecodedResponse(GZIP_BASE):
     Largely copied from ``xmlrpclib``/``xmlrpc.client`` and modified
     to work for py2.4-py3
     """
+
     def __init__(self, response):
         # response doesn't support tell() and read(), required by
         # GzipFile
         if not gzip:
-            raise SpeedtestHTTPError('HTTP response body is gzip encoded, '
-                                     'but gzip support is not available')
+            raise SpeedtestHTTPError(
+                "HTTP response body is gzip encoded, "
+                "but gzip support is not available"
+            )
         IO = BytesIO or StringIO
         self.io = IO()
         while 1:
@@ -628,7 +662,7 @@ class GzipDecodedResponse(GZIP_BASE):
                 break
             self.io.write(chunk)
         self.io.seek(0)
-        gzip.GzipFile.__init__(self, mode='rb', fileobj=self.io)
+        gzip.GzipFile.__init__(self, mode="rb", fileobj=self.io)
 
     def close(self):
         try:
@@ -653,10 +687,9 @@ def distance(origin, destination):
 
     dlat = math.radians(lat2 - lat1)
     dlon = math.radians(lon2 - lon1)
-    a = (math.sin(dlat / 2) * math.sin(dlat / 2) +
-         math.cos(math.radians(lat1)) *
-         math.cos(math.radians(lat2)) * math.sin(dlon / 2) *
-         math.sin(dlon / 2))
+    a = math.sin(dlat / 2) * math.sin(dlat / 2) + math.cos(
+        math.radians(lat1)
+    ) * math.cos(math.radians(lat2)) * math.sin(dlon / 2) * math.sin(dlon / 2)
     c = 2 * math.atan2(math.sqrt(a), math.sqrt(1 - a))
     d = radius * c
 
@@ -667,19 +700,19 @@ def build_user_agent():
     """Build a Mozilla/5.0 compatible User-Agent string"""
 
     ua_tuple = (
-        'Mozilla/5.0',
-        '(%s; U; %s; en-us)' % (platform.platform(),
-                                platform.architecture()[0]),
-        'Python/%s' % platform.python_version(),
-        '(KHTML, like Gecko)',
-        'speedtest-cli/%s' % __version__
+        "Mozilla/5.0",
+        "(%s; U; %s; en-us)"
+        % (platform.platform(), platform.architecture()[0]),
+        "Python/%s" % platform.python_version(),
+        "(KHTML, like Gecko)",
+        "speedtest-cli/%s" % __version__,
     )
-    user_agent = ' '.join(ua_tuple)
-    printer('User-Agent: %s' % user_agent, debug=True)
+    user_agent = " ".join(ua_tuple)
+    printer("User-Agent: %s" % user_agent, debug=True)
     return user_agent
 
 
-def build_request(url, data=None, headers=None, bump='0', secure=False):
+def build_request(url, data=None, headers=None, bump="0", secure=False):
     """Build a urllib2 request object
 
     This function automatically adds a User-Agent header to all requests
@@ -689,28 +722,32 @@ def build_request(url, data=None, headers=None, bump='0', secure=False):
     if not headers:
         headers = {}
 
-    if url[0] == ':':
-        scheme = ('http', 'https')[bool(secure)]
-        schemed_url = '%s%s' % (scheme, url)
+    if url[0] == ":":
+        scheme = ("http", "https")[bool(secure)]
+        schemed_url = "%s%s" % (scheme, url)
     else:
         schemed_url = url
 
-    if '?' in url:
-        delim = '&'
+    if "?" in url:
+        delim = "&"
     else:
-        delim = '?'
+        delim = "?"
 
     # WHO YOU GONNA CALL? CACHE BUSTERS!
-    final_url = '%s%sx=%s.%s' % (schemed_url, delim,
-                                 int(timeit.time.time() * 1000),
-                                 bump)
+    final_url = "%s%sx=%s.%s" % (
+        schemed_url,
+        delim,
+        int(timeit.time.time() * 1000),
+        bump,
+    )
 
-    headers.update({
-        'Cache-Control': 'no-cache',
-    })
+    headers.update(
+        {
+            "Cache-Control": "no-cache",
+        }
+    )
 
-    printer('%s %s' % (('GET', 'POST')[bool(data)], final_url),
-            debug=True)
+    printer("%s %s" % (("GET", "POST")[bool(data)], final_url), debug=True)
 
     return Request(final_url, data=data, headers=headers)
 
@@ -729,7 +766,7 @@ def catch_request(request, opener=None):
     try:
         uh = _open(request)
         if request.get_full_url() != uh.geturl():
-            printer('Redirected to %s' % uh.geturl(), debug=True)
+            printer("Redirected to %s" % uh.geturl(), debug=True)
         return uh, False
     except HTTP_ERRORS:
         e = get_exception()
@@ -747,7 +784,7 @@ def get_response_stream(response):
     except AttributeError:
         getheader = response.getheader
 
-    if getheader('content-encoding') == 'gzip':
+    if getheader("content-encoding") == "gzip":
         return GzipDecodedResponse(response)
 
     return response
@@ -768,14 +805,16 @@ def print_dots(shutdown_event):
     """Built in callback function used by Thread classes for printing
     status
     """
+
     def inner(current, total, start=False, end=False):
         if shutdown_event.isSet():
             return
 
-        sys.stdout.write('.')
+        sys.stdout.write(".")
         if current + 1 == total and end is True:
-            sys.stdout.write('\n')
+            sys.stdout.write("\n")
         sys.stdout.flush()
+
     return inner
 
 
@@ -786,8 +825,9 @@ def do_nothing(*args, **kwargs):
 class HTTPDownloader(threading.Thread):
     """Thread class for retrieving a URL"""
 
-    def __init__(self, i, request, start, timeout, opener=None,
-                 shutdown_event=None):
+    def __init__(
+        self, i, request, start, timeout, opener=None, shutdown_event=None
+    ):
         threading.Thread.__init__(self)
         self.request = request
         self.result = [0]
@@ -808,9 +848,11 @@ class HTTPDownloader(threading.Thread):
         try:
             if (timeit.default_timer() - self.starttime) <= self.timeout:
                 f = self._opener(self.request)
-                while (not self._shutdown_event.isSet() and
-                        (timeit.default_timer() - self.starttime) <=
-                        self.timeout):
+                while (
+                    not self._shutdown_event.isSet()
+                    and (timeit.default_timer() - self.starttime)
+                    <= self.timeout
+                ):
                     self.result.append(len(f.read(10240)))
                     if self.result[-1] == 0:
                         break
@@ -841,19 +883,20 @@ class HTTPUploaderData(object):
         self.total = [0]
 
     def pre_allocate(self):
-        chars = '0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ'
+        chars = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ"
         multiplier = int(round(int(self.length) / 36.0))
         IO = BytesIO or StringIO
         try:
             self._data = IO(
-                ('content1=%s' %
-                 (chars * multiplier)[0:int(self.length) - 9]
-                 ).encode()
+                (
+                    "content1=%s"
+                    % (chars * multiplier)[0 : int(self.length) - 9]
+                ).encode()
             )
         except MemoryError:
             raise SpeedtestCLIError(
-                'Insufficient memory to pre-allocate upload data. Please '
-                'use --no-pre-allocate'
+                "Insufficient memory to pre-allocate upload data. Please "
+                "use --no-pre-allocate"
             )
 
     @property
@@ -863,8 +906,9 @@ class HTTPUploaderData(object):
         return self._data
 
     def read(self, n=10240):
-        if ((timeit.default_timer() - self.start) <= self.timeout and
-                not self._shutdown_event.isSet()):
+        if (
+            timeit.default_timer() - self.start
+        ) <= self.timeout and not self._shutdown_event.isSet():
             chunk = self.data.read(n)
             self.total.append(len(chunk))
             return chunk
@@ -878,8 +922,9 @@ class HTTPUploaderData(object):
 class HTTPUploader(threading.Thread):
     """Thread class for putting a URL"""
 
-    def __init__(self, i, request, start, size, timeout, opener=None,
-                 shutdown_event=None):
+    def __init__(
+        self, i, request, start, size, timeout, opener=None, shutdown_event=None
+    ):
         threading.Thread.__init__(self)
         self.request = request
         self.request.data.start = self.starttime = start
@@ -901,16 +946,19 @@ class HTTPUploader(threading.Thread):
     def run(self):
         request = self.request
         try:
-            if ((timeit.default_timer() - self.starttime) <= self.timeout and
-                    not self._shutdown_event.isSet()):
+            if (
+                timeit.default_timer() - self.starttime
+            ) <= self.timeout and not self._shutdown_event.isSet():
                 try:
                     f = self._opener(request)
                 except TypeError:
                     # PY24 expects a string or buffer
                     # This also causes issues with Ctrl-C, but we will concede
                     # for the moment that Ctrl-C on PY24 isn't immediate
-                    request = build_request(self.request.get_full_url(),
-                                            data=request.data.read(self.size))
+                    request = build_request(
+                        self.request.get_full_url(),
+                        data=request.data.read(self.size),
+                    )
                     f = self._opener(request)
                 f.read(11)
                 f.close()
@@ -936,8 +984,16 @@ class SpeedtestResults(object):
     to get a share results image link.
     """
 
-    def __init__(self, download=0, upload=0, ping=0, server=None, client=None,
-                 opener=None, secure=False):
+    def __init__(
+        self,
+        download=0,
+        upload=0,
+        ping=0,
+        server=None,
+        client=None,
+        opener=None,
+        secure=False,
+    ):
         self.download = download
         self.upload = upload
         self.ping = ping
@@ -948,7 +1004,7 @@ class SpeedtestResults(object):
         self.client = client or {}
 
         self._share = None
-        self.timestamp = '%sZ' % datetime.datetime.utcnow().isoformat()
+        self.timestamp = "%sZ" % datetime.datetime.utcnow().isoformat()
         self.bytes_received = 0
         self.bytes_sent = 0
 
@@ -978,29 +1034,33 @@ class SpeedtestResults(object):
         # We use a list instead of a dict because the API expects parameters
         # in a certain order
         api_data = [
-            'recommendedserverid=%s' % self.server['id'],
-            'ping=%s' % ping,
-            'screenresolution=',
-            'promo=',
-            'download=%s' % download,
-            'screendpi=',
-            'upload=%s' % upload,
-            'testmethod=http',
-            'hash=%s' % md5(('%s-%s-%s-%s' %
-                             (ping, upload, download, '297aae72'))
-                            .encode()).hexdigest(),
-            'touchscreen=none',
-            'startmode=pingselect',
-            'accuracy=1',
-            'bytesreceived=%s' % self.bytes_received,
-            'bytessent=%s' % self.bytes_sent,
-            'serverid=%s' % self.server['id'],
+            "recommendedserverid=%s" % self.server["id"],
+            "ping=%s" % ping,
+            "screenresolution=",
+            "promo=",
+            "download=%s" % download,
+            "screendpi=",
+            "upload=%s" % upload,
+            "testmethod=http",
+            "hash=%s"
+            % md5(
+                ("%s-%s-%s-%s" % (ping, upload, download, "297aae72")).encode()
+            ).hexdigest(),
+            "touchscreen=none",
+            "startmode=pingselect",
+            "accuracy=1",
+            "bytesreceived=%s" % self.bytes_received,
+            "bytessent=%s" % self.bytes_sent,
+            "serverid=%s" % self.server["id"],
         ]
 
-        headers = {'Referer': 'http://c.speedtest.net/flash/speedtest.swf'}
-        request = build_request('://www.speedtest.net/api/api.php',
-                                data='&'.join(api_data).encode(),
-                                headers=headers, secure=self._secure)
+        headers = {"Referer": "http://c.speedtest.net/flash/speedtest.swf"}
+        request = build_request(
+            "://www.speedtest.net/api/api.php",
+            data="&".join(api_data).encode(),
+            headers=headers,
+            secure=self._secure,
+        )
         f, e = catch_request(request, opener=self._opener)
         if e:
             raise ShareResultsConnectFailure(e)
@@ -1010,16 +1070,18 @@ class SpeedtestResults(object):
         f.close()
 
         if int(code) != 200:
-            raise ShareResultsSubmitFailure('Could not submit results to '
-                                            'speedtest.net')
+            raise ShareResultsSubmitFailure(
+                "Could not submit results to " "speedtest.net"
+            )
 
         qsargs = parse_qs(response.decode())
-        resultid = qsargs.get('resultid')
+        resultid = qsargs.get("resultid")
         if not resultid or len(resultid) != 1:
-            raise ShareResultsSubmitFailure('Could not submit results to '
-                                            'speedtest.net')
+            raise ShareResultsSubmitFailure(
+                "Could not submit results to " "speedtest.net"
+            )
 
-        self._share = 'http://www.speedtest.net/result/%s.png' % resultid[0]
+        self._share = "http://www.speedtest.net/result/%s.png" % resultid[0]
 
         return self._share
 
@@ -1027,38 +1089,56 @@ class SpeedtestResults(object):
         """Return dictionary of result data"""
 
         return {
-            'download': self.download,
-            'upload': self.upload,
-            'ping': self.ping,
-            'server': self.server,
-            'timestamp': self.timestamp,
-            'bytes_sent': self.bytes_sent,
-            'bytes_received': self.bytes_received,
-            'share': self._share,
-            'client': self.client,
+            "download": self.download,
+            "upload": self.upload,
+            "ping": self.ping,
+            "server": self.server,
+            "timestamp": self.timestamp,
+            "bytes_sent": self.bytes_sent,
+            "bytes_received": self.bytes_received,
+            "share": self._share,
+            "client": self.client,
         }
 
     @staticmethod
-    def csv_header(delimiter=','):
+    def csv_header(delimiter=","):
         """Return CSV Headers"""
 
-        row = ['Server ID', 'Sponsor', 'Server Name', 'Timestamp', 'Distance',
-               'Ping', 'Download', 'Upload', 'Share', 'IP Address']
+        row = [
+            "Server ID",
+            "Sponsor",
+            "Server Name",
+            "Timestamp",
+            "Distance",
+            "Ping",
+            "Download",
+            "Upload",
+            "Share",
+            "IP Address",
+        ]
         out = StringIO()
-        writer = csv.writer(out, delimiter=delimiter, lineterminator='')
+        writer = csv.writer(out, delimiter=delimiter, lineterminator="")
         writer.writerow([to_utf8(v) for v in row])
         return out.getvalue()
 
-    def csv(self, delimiter=','):
+    def csv(self, delimiter=","):
         """Return data in CSV format"""
 
         data = self.dict()
         out = StringIO()
-        writer = csv.writer(out, delimiter=delimiter, lineterminator='')
-        row = [data['server']['id'], data['server']['sponsor'],
-               data['server']['name'], data['timestamp'],
-               data['server']['d'], data['ping'], data['download'],
-               data['upload'], self._share or '', self.client['ip']]
+        writer = csv.writer(out, delimiter=delimiter, lineterminator="")
+        row = [
+            data["server"]["id"],
+            data["server"]["sponsor"],
+            data["server"]["name"],
+            data["timestamp"],
+            data["server"]["d"],
+            data["ping"],
+            data["download"],
+            data["upload"],
+            self._share or "",
+            self.client["ip"],
+        ]
         writer.writerow([to_utf8(v) for v in row])
         return out.getvalue()
 
@@ -1067,18 +1147,21 @@ class SpeedtestResults(object):
 
         kwargs = {}
         if pretty:
-            kwargs.update({
-                'indent': 4,
-                'sort_keys': True
-            })
+            kwargs.update({"indent": 4, "sort_keys": True})
         return json.dumps(self.dict(), **kwargs)
 
 
 class Speedtest(object):
     """Class for performing standard speedtest.net testing operations"""
 
-    def __init__(self, config=None, source_address=None, timeout=10,
-                 secure=False, shutdown_event=None):
+    def __init__(
+        self,
+        config=None,
+        source_address=None,
+        timeout=10,
+        secure=False,
+        shutdown_event=None,
+    ):
         self.config = {}
 
         self._source_address = source_address
@@ -1101,7 +1184,7 @@ class Speedtest(object):
         self._best = {}
 
         self.results = SpeedtestResults(
-            client=self.config['client'],
+            client=self.config["client"],
             opener=self._opener,
             secure=secure,
         )
@@ -1119,9 +1202,12 @@ class Speedtest(object):
 
         headers = {}
         if gzip:
-            headers['Accept-Encoding'] = 'gzip'
-        request = build_request('://www.speedtest.net/speedtest-config.php',
-                                headers=headers, secure=self._secure)
+            headers["Accept-Encoding"] = "gzip"
+        request = build_request(
+            "://www.speedtest.net/speedtest-config.php",
+            headers=headers,
+            secure=self._secure,
+        )
         uh, e = catch_request(request, opener=self._opener)
         if e:
             raise ConfigRetrievalError(e)
@@ -1142,9 +1228,9 @@ class Speedtest(object):
         if int(uh.code) != 200:
             return None
 
-        configxml = ''.encode().join(configxml_list)
+        configxml = "".encode().join(configxml_list)
 
-        printer('Config XML:\n%s' % configxml, debug=True)
+        printer("Config XML:\n%s" % configxml, debug=True)
 
         try:
             try:
@@ -1152,13 +1238,13 @@ class Speedtest(object):
             except ET.ParseError:
                 e = get_exception()
                 raise SpeedtestConfigError(
-                    'Malformed speedtest.net configuration: %s' % e
+                    "Malformed speedtest.net configuration: %s" % e
                 )
-            server_config = root.find('server-config').attrib
-            download = root.find('download').attrib
-            upload = root.find('upload').attrib
+            server_config = root.find("server-config").attrib
+            download = root.find("download").attrib
+            upload = root.find("upload").attrib
             # times = root.find('times').attrib
-            client = root.find('client').attrib
+            client = root.find("client").attrib
 
         except AttributeError:
             try:
@@ -1166,65 +1252,77 @@ class Speedtest(object):
             except ExpatError:
                 e = get_exception()
                 raise SpeedtestConfigError(
-                    'Malformed speedtest.net configuration: %s' % e
+                    "Malformed speedtest.net configuration: %s" % e
                 )
-            server_config = get_attributes_by_tag_name(root, 'server-config')
-            download = get_attributes_by_tag_name(root, 'download')
-            upload = get_attributes_by_tag_name(root, 'upload')
+            server_config = get_attributes_by_tag_name(root, "server-config")
+            download = get_attributes_by_tag_name(root, "download")
+            upload = get_attributes_by_tag_name(root, "upload")
             # times = get_attributes_by_tag_name(root, 'times')
-            client = get_attributes_by_tag_name(root, 'client')
+            client = get_attributes_by_tag_name(root, "client")
 
         ignore_servers = [
-            int(i) for i in server_config['ignoreids'].split(',') if i
+            int(i) for i in server_config["ignoreids"].split(",") if i
         ]
 
-        ratio = int(upload['ratio'])
-        upload_max = int(upload['maxchunkcount'])
+        ratio = int(upload["ratio"])
+        upload_max = int(upload["maxchunkcount"])
         up_sizes = [32768, 65536, 131072, 262144, 524288, 1048576, 7340032]
         sizes = {
-            'upload': up_sizes[ratio - 1:],
-            'download': [350, 500, 750, 1000, 1500, 2000, 2500,
-                         3000, 3500, 4000]
+            "upload": up_sizes[ratio - 1 :],
+            "download": [
+                350,
+                500,
+                750,
+                1000,
+                1500,
+                2000,
+                2500,
+                3000,
+                3500,
+                4000,
+            ],
         }
 
-        size_count = len(sizes['upload'])
+        size_count = len(sizes["upload"])
 
         upload_count = int(math.ceil(upload_max / size_count))
 
         counts = {
-            'upload': upload_count,
-            'download': int(download['threadsperurl'])
+            "upload": upload_count,
+            "download": int(download["threadsperurl"]),
         }
 
         threads = {
-            'upload': int(upload['threads']),
-            'download': int(server_config['threadcount']) * 2
+            "upload": int(upload["threads"]),
+            "download": int(server_config["threadcount"]) * 2,
         }
 
         length = {
-            'upload': int(upload['testlength']),
-            'download': int(download['testlength'])
+            "upload": int(upload["testlength"]),
+            "download": int(download["testlength"]),
         }
 
-        self.config.update({
-            'client': client,
-            'ignore_servers': ignore_servers,
-            'sizes': sizes,
-            'counts': counts,
-            'threads': threads,
-            'length': length,
-            'upload_max': upload_count * size_count
-        })
+        self.config.update(
+            {
+                "client": client,
+                "ignore_servers": ignore_servers,
+                "sizes": sizes,
+                "counts": counts,
+                "threads": threads,
+                "length": length,
+                "upload_max": upload_count * size_count,
+            }
+        )
 
         try:
-            self.lat_lon = (float(client['lat']), float(client['lon']))
+            self.lat_lon = (float(client["lat"]), float(client["lon"]))
         except ValueError:
             raise SpeedtestConfigError(
-                'Unknown location: lat=%r lon=%r' %
-                (client.get('lat'), client.get('lon'))
+                "Unknown location: lat=%r lon=%r"
+                % (client.get("lat"), client.get("lon"))
             )
 
-        printer('Config:\n%r' % self.config, debug=True)
+        printer("Config:\n%r" % self.config, debug=True)
 
         return self.config
 
@@ -1246,32 +1344,31 @@ class Speedtest(object):
                     server_list[i] = int(s)
                 except ValueError:
                     raise InvalidServerIDType(
-                        '%s is an invalid server type, must be int' % s
+                        "%s is an invalid server type, must be int" % s
                     )
 
         urls = [
-            '://www.speedtest.net/speedtest-servers-static.php',
-            'http://c.speedtest.net/speedtest-servers-static.php',
-            '://www.speedtest.net/speedtest-servers.php',
-            'http://c.speedtest.net/speedtest-servers.php',
+            "://www.speedtest.net/speedtest-servers-static.php",
+            "http://c.speedtest.net/speedtest-servers-static.php",
+            "://www.speedtest.net/speedtest-servers.php",
+            "http://c.speedtest.net/speedtest-servers.php",
         ]
 
         headers = {}
         if gzip:
-            headers['Accept-Encoding'] = 'gzip'
+            headers["Accept-Encoding"] = "gzip"
 
         errors = []
         for url in urls:
             try:
                 request = build_request(
-                    '%s?threads=%s' % (url,
-                                       self.config['threads']['download']),
+                    "%s?threads=%s" % (url, self.config["threads"]["download"]),
                     headers=headers,
-                    secure=self._secure
+                    secure=self._secure,
                 )
                 uh, e = catch_request(request, opener=self._opener)
                 if e:
-                    errors.append('%s' % e)
+                    errors.append("%s" % e)
                     raise ServersRetrievalError()
 
                 stream = get_response_stream(uh)
@@ -1291,9 +1388,9 @@ class Speedtest(object):
                 if int(uh.code) != 200:
                     raise ServersRetrievalError()
 
-                serversxml = ''.encode().join(serversxml_list)
+                serversxml = "".encode().join(serversxml_list)
 
-                printer('Servers XML:\n%s' % serversxml, debug=True)
+                printer("Servers XML:\n%s" % serversxml, debug=True)
 
                 try:
                     try:
@@ -1302,18 +1399,18 @@ class Speedtest(object):
                         except ET.ParseError:
                             e = get_exception()
                             raise SpeedtestServersError(
-                                'Malformed speedtest.net server list: %s' % e
+                                "Malformed speedtest.net server list: %s" % e
                             )
-                        elements = etree_iter(root, 'server')
+                        elements = etree_iter(root, "server")
                     except AttributeError:
                         try:
                             root = DOM.parseString(serversxml)
                         except ExpatError:
                             e = get_exception()
                             raise SpeedtestServersError(
-                                'Malformed speedtest.net server list: %s' % e
+                                "Malformed speedtest.net server list: %s" % e
                             )
-                        elements = root.getElementsByTagName('server')
+                        elements = root.getElementsByTagName("server")
                 except (SyntaxError, xml.parsers.expat.ExpatError):
                     raise ServersRetrievalError()
 
@@ -1323,21 +1420,27 @@ class Speedtest(object):
                     except AttributeError:
                         attrib = dict(list(server.attributes.items()))
 
-                    if servers and int(attrib.get('id')) not in servers:
+                    if servers and int(attrib.get("id")) not in servers:
                         continue
 
-                    if (int(attrib.get('id')) in self.config['ignore_servers']
-                            or int(attrib.get('id')) in exclude):
+                    if (
+                        int(attrib.get("id")) in self.config["ignore_servers"]
+                        or int(attrib.get("id")) in exclude
+                    ):
                         continue
 
                     try:
-                        d = distance(self.lat_lon,
-                                     (float(attrib.get('lat')),
-                                      float(attrib.get('lon'))))
+                        d = distance(
+                            self.lat_lon,
+                            (
+                                float(attrib.get("lat")),
+                                float(attrib.get("lon")),
+                            ),
+                        )
                     except Exception:
                         continue
 
-                    attrib['d'] = d
+                    attrib["d"] = d
 
                     try:
                         self.servers[d].append(attrib)
@@ -1370,41 +1473,45 @@ class Speedtest(object):
         request = build_request(url)
         uh, e = catch_request(request, opener=self._opener)
         if e:
-            raise SpeedtestMiniConnectFailure('Failed to connect to %s' %
-                                              server)
+            raise SpeedtestMiniConnectFailure(
+                "Failed to connect to %s" % server
+            )
         else:
             text = uh.read()
             uh.close()
 
-        extension = re.findall('upload_?[Ee]xtension: "([^"]+)"',
-                               text.decode())
+        extension = re.findall('upload_?[Ee]xtension: "([^"]+)"', text.decode())
         if not extension:
-            for ext in ['php', 'asp', 'aspx', 'jsp']:
+            for ext in ["php", "asp", "aspx", "jsp"]:
                 try:
-                    f = self._opener.open(
-                        '%s/speedtest/upload.%s' % (url, ext)
-                    )
+                    f = self._opener.open("%s/speedtest/upload.%s" % (url, ext))
                 except Exception:
                     pass
                 else:
                     data = f.read().strip().decode()
-                    if (f.code == 200 and
-                            len(data.splitlines()) == 1 and
-                            re.match('size=[0-9]', data)):
+                    if (
+                        f.code == 200
+                        and len(data.splitlines()) == 1
+                        and re.match("size=[0-9]", data)
+                    ):
                         extension = [ext]
                         break
         if not urlparts or not extension:
-            raise InvalidSpeedtestMiniServer('Invalid Speedtest Mini Server: '
-                                             '%s' % server)
+            raise InvalidSpeedtestMiniServer(
+                "Invalid Speedtest Mini Server: " "%s" % server
+            )
 
-        self.servers = [{
-            'sponsor': 'Speedtest Mini',
-            'name': urlparts[1],
-            'd': 0,
-            'url': '%s/speedtest/upload.%s' % (url.rstrip('/'), extension[0]),
-            'latency': 0,
-            'id': 0
-        }]
+        self.servers = [
+            {
+                "sponsor": "Speedtest Mini",
+                "name": urlparts[1],
+                "d": 0,
+                "url": "%s/speedtest/upload.%s"
+                % (url.rstrip("/"), extension[0]),
+                "latency": 0,
+                "id": 0,
+            }
+        ]
 
         return self.servers
 
@@ -1425,7 +1532,7 @@ class Speedtest(object):
                 continue
             break
 
-        printer('Closest Servers:\n%r' % self.closest, debug=True)
+        printer("Closest Servers:\n%r" % self.closest, debug=True)
         return self.closest
 
     def get_best_server(self, servers=None):
@@ -1448,39 +1555,36 @@ class Speedtest(object):
         results = {}
         for server in servers:
             cum = []
-            url = os.path.dirname(server['url'])
+            url = os.path.dirname(server["url"])
             stamp = int(timeit.time.time() * 1000)
-            latency_url = '%s/latency.txt?x=%s' % (url, stamp)
+            latency_url = "%s/latency.txt?x=%s" % (url, stamp)
             for i in range(0, 3):
-                this_latency_url = '%s.%s' % (latency_url, i)
-                printer('%s %s' % ('GET', this_latency_url),
-                        debug=True)
+                this_latency_url = "%s.%s" % (latency_url, i)
+                printer("%s %s" % ("GET", this_latency_url), debug=True)
                 urlparts = urlparse(latency_url)
                 try:
-                    if urlparts[0] == 'https':
+                    if urlparts[0] == "https":
                         h = SpeedtestHTTPSConnection(
-                            urlparts[1],
-                            source_address=source_address_tuple
+                            urlparts[1], source_address=source_address_tuple
                         )
                     else:
                         h = SpeedtestHTTPConnection(
-                            urlparts[1],
-                            source_address=source_address_tuple
+                            urlparts[1], source_address=source_address_tuple
                         )
-                    headers = {'User-Agent': user_agent}
-                    path = '%s?%s' % (urlparts[2], urlparts[4])
+                    headers = {"User-Agent": user_agent}
+                    path = "%s?%s" % (urlparts[2], urlparts[4])
                     start = timeit.default_timer()
                     h.request("GET", path, headers=headers)
                     r = h.getresponse()
-                    total = (timeit.default_timer() - start)
+                    total = timeit.default_timer() - start
                 except HTTP_ERRORS:
                     e = get_exception()
-                    printer('ERROR: %r' % e, debug=True)
+                    printer("ERROR: %r" % e, debug=True)
                     cum.append(3600)
                     continue
 
                 text = r.read(9)
-                if int(r.status) == 200 and text == 'test=test'.encode():
+                if int(r.status) == 200 and text == "test=test".encode():
                     cum.append(total)
                 else:
                     cum.append(3600)
@@ -1492,16 +1596,17 @@ class Speedtest(object):
         try:
             fastest = sorted(results.keys())[0]
         except IndexError:
-            raise SpeedtestBestServerFailure('Unable to connect to servers to '
-                                             'test latency.')
+            raise SpeedtestBestServerFailure(
+                "Unable to connect to servers to " "test latency."
+            )
         best = results[fastest]
-        best['latency'] = fastest
+        best["latency"] = fastest
 
         self.results.ping = fastest
         self.results.server = best
 
         self._best.update(best)
-        printer('Best Server:\n%r' % best, debug=True)
+        printer("Best Server:\n%r" % best, debug=True)
         return best
 
     def download(self, callback=do_nothing, threads=None):
@@ -1512,20 +1617,20 @@ class Speedtest(object):
         """
 
         urls = []
-        for size in self.config['sizes']['download']:
-            for _ in range(0, self.config['counts']['download']):
-                urls.append('%s/random%sx%s.jpg' %
-                            (os.path.dirname(self.best['url']), size, size))
+        for size in self.config["sizes"]["download"]:
+            for _ in range(0, self.config["counts"]["download"]):
+                urls.append(
+                    "%s/random%sx%s.jpg"
+                    % (os.path.dirname(self.best["url"]), size, size)
+                )
 
         request_count = len(urls)
         requests = []
         for i, url in enumerate(urls):
-            requests.append(
-                build_request(url, bump=i, secure=self._secure)
-            )
+            requests.append(build_request(url, bump=i, secure=self._secure))
 
-        max_threads = threads or self.config['threads']['download']
-        in_flight = {'threads': 0}
+        max_threads = threads or self.config["threads"]["download"]
+        in_flight = {"threads": 0}
 
         def producer(q, requests, request_count):
             for i, request in enumerate(requests):
@@ -1533,15 +1638,15 @@ class Speedtest(object):
                     i,
                     request,
                     start,
-                    self.config['length']['download'],
+                    self.config["length"]["download"],
                     opener=self._opener,
-                    shutdown_event=self._shutdown_event
+                    shutdown_event=self._shutdown_event,
                 )
-                while in_flight['threads'] >= max_threads:
+                while in_flight["threads"] >= max_threads:
                     timeit.time.sleep(0.001)
                 thread.start()
                 q.put(thread, True)
-                in_flight['threads'] += 1
+                in_flight["threads"] += 1
                 callback(i, request_count, start=True)
 
         finished = []
@@ -1552,15 +1657,15 @@ class Speedtest(object):
                 thread = q.get(True)
                 while _is_alive(thread):
                     thread.join(timeout=0.001)
-                in_flight['threads'] -= 1
+                in_flight["threads"] -= 1
                 finished.append(sum(thread.result))
                 callback(thread.i, request_count, end=True)
 
         q = Queue(max_threads)
-        prod_thread = threading.Thread(target=producer,
-                                       args=(q, requests, request_count))
-        cons_thread = threading.Thread(target=consumer,
-                                       args=(q, request_count))
+        prod_thread = threading.Thread(
+            target=producer, args=(q, requests, request_count)
+        )
+        cons_thread = threading.Thread(target=consumer, args=(q, request_count))
         start = timeit.default_timer()
         prod_thread.start()
         cons_thread.start()
@@ -1573,10 +1678,10 @@ class Speedtest(object):
         stop = timeit.default_timer()
         self.results.bytes_received = sum(finished)
         self.results.download = (
-            (self.results.bytes_received / (stop - start)) * 8.0
-        )
+            self.results.bytes_received / (stop - start)
+        ) * 8.0
         if self.results.download > 100000:
-            self.config['threads']['upload'] = 8
+            self.config["threads"]["upload"] = 8
         return self.results.download
 
     def upload(self, callback=do_nothing, pre_allocate=True, threads=None):
@@ -1588,12 +1693,12 @@ class Speedtest(object):
 
         sizes = []
 
-        for size in self.config['sizes']['upload']:
-            for _ in range(0, self.config['counts']['upload']):
+        for size in self.config["sizes"]["upload"]:
+            for _ in range(0, self.config["counts"]["upload"]):
                 sizes.append(size)
 
         # request_count = len(sizes)
-        request_count = self.config['upload_max']
+        request_count = self.config["upload_max"]
 
         requests = []
         for i, size in enumerate(sizes):
@@ -1602,23 +1707,27 @@ class Speedtest(object):
             data = HTTPUploaderData(
                 size,
                 0,
-                self.config['length']['upload'],
-                shutdown_event=self._shutdown_event
+                self.config["length"]["upload"],
+                shutdown_event=self._shutdown_event,
             )
             if pre_allocate:
                 data.pre_allocate()
 
-            headers = {'Content-length': size}
+            headers = {"Content-length": size}
             requests.append(
                 (
-                    build_request(self.best['url'], data, secure=self._secure,
-                                  headers=headers),
-                    size
+                    build_request(
+                        self.best["url"],
+                        data,
+                        secure=self._secure,
+                        headers=headers,
+                    ),
+                    size,
                 )
             )
 
-        max_threads = threads or self.config['threads']['upload']
-        in_flight = {'threads': 0}
+        max_threads = threads or self.config["threads"]["upload"]
+        in_flight = {"threads": 0}
 
         def producer(q, requests, request_count):
             for i, request in enumerate(requests[:request_count]):
@@ -1627,15 +1736,15 @@ class Speedtest(object):
                     request[0],
                     start,
                     request[1],
-                    self.config['length']['upload'],
+                    self.config["length"]["upload"],
                     opener=self._opener,
-                    shutdown_event=self._shutdown_event
+                    shutdown_event=self._shutdown_event,
                 )
-                while in_flight['threads'] >= max_threads:
+                while in_flight["threads"] >= max_threads:
                     timeit.time.sleep(0.001)
                 thread.start()
                 q.put(thread, True)
-                in_flight['threads'] += 1
+                in_flight["threads"] += 1
                 callback(i, request_count, start=True)
 
         finished = []
@@ -1646,15 +1755,15 @@ class Speedtest(object):
                 thread = q.get(True)
                 while _is_alive(thread):
                     thread.join(timeout=0.001)
-                in_flight['threads'] -= 1
+                in_flight["threads"] -= 1
                 finished.append(thread.result)
                 callback(thread.i, request_count, end=True)
 
-        q = Queue(threads or self.config['threads']['upload'])
-        prod_thread = threading.Thread(target=producer,
-                                       args=(q, requests, request_count))
-        cons_thread = threading.Thread(target=consumer,
-                                       args=(q, request_count))
+        q = Queue(threads or self.config["threads"]["upload"])
+        prod_thread = threading.Thread(
+            target=producer, args=(q, requests, request_count)
+        )
+        cons_thread = threading.Thread(target=consumer, args=(q, request_count))
         start = timeit.default_timer()
         prod_thread.start()
         cons_thread.start()
@@ -1666,9 +1775,7 @@ class Speedtest(object):
 
         stop = timeit.default_timer()
         self.results.bytes_sent = sum(finished)
-        self.results.upload = (
-            (self.results.bytes_sent / (stop - start)) * 8.0
-        )
+        self.results.upload = (self.results.bytes_sent / (stop - start)) * 8.0
         return self.results.upload
 
 
@@ -1676,22 +1783,24 @@ def ctrl_c(shutdown_event):
     """Catch Ctrl-C key sequence and set a SHUTDOWN_EVENT for our threaded
     operations
     """
+
     def inner(signum, frame):
         shutdown_event.set()
-        printer('\nCancelling...', error=True)
+        printer("\nCancelling...", error=True)
         sys.exit(0)
+
     return inner
 
 
 def version():
     """Print the version"""
 
-    printer('speedtest-cli %s' % __version__)
-    printer('Python %s' % sys.version.replace('\n', ''))
+    printer("speedtest-cli %s" % __version__)
+    printer("Python %s" % sys.version.replace("\n", ""))
     sys.exit(0)
 
 
-def csv_header(delimiter=','):
+def csv_header(delimiter=","):
     """Print the CSV Headers"""
 
     printer(SpeedtestResults.csv_header(delimiter=delimiter))
@@ -1701,11 +1810,12 @@ def csv_header(delimiter=','):
 def parse_args():
     """Function to handle building and parsing of command line arguments"""
     description = (
-        'Command line interface for testing internet bandwidth using '
-        'speedtest.net.\n'
-        '------------------------------------------------------------'
-        '--------------\n'
-        'https://github.com/sivel/speedtest-cli')
+        "Command line interface for testing internet bandwidth using "
+        "speedtest.net.\n"
+        "------------------------------------------------------------"
+        "--------------\n"
+        "https://github.com/sivel/speedtest-cli"
+    )
 
     parser = ArgParser(description=description)
     # Give optparse.OptionParser an `add_argument` method for
@@ -1714,67 +1824,133 @@ def parse_args():
         parser.add_argument = parser.add_option
     except AttributeError:
         pass
-    parser.add_argument('--no-download', dest='download', default=True,
-                        action='store_const', const=False,
-                        help='Do not perform download test')
-    parser.add_argument('--no-upload', dest='upload', default=True,
-                        action='store_const', const=False,
-                        help='Do not perform upload test')
-    parser.add_argument('--single', default=False, action='store_true',
-                        help='Only use a single connection instead of '
-                             'multiple. This simulates a typical file '
-                             'transfer.')
-    parser.add_argument('--bytes', dest='units', action='store_const',
-                        const=('byte', 8), default=('bit', 1),
-                        help='Display values in bytes instead of bits. Does '
-                             'not affect the image generated by --share, nor '
-                             'output from --json or --csv')
-    parser.add_argument('--share', action='store_true',
-                        help='Generate and provide a URL to the speedtest.net '
-                             'share results image, not displayed with --csv')
-    parser.add_argument('--simple', action='store_true', default=False,
-                        help='Suppress verbose output, only show basic '
-                             'information')
-    parser.add_argument('--csv', action='store_true', default=False,
-                        help='Suppress verbose output, only show basic '
-                             'information in CSV format. Speeds listed in '
-                             'bit/s and not affected by --bytes')
-    parser.add_argument('--csv-delimiter', default=',', type=PARSER_TYPE_STR,
-                        help='Single character delimiter to use in CSV '
-                             'output. Default ","')
-    parser.add_argument('--csv-header', action='store_true', default=False,
-                        help='Print CSV headers')
-    parser.add_argument('--json', action='store_true', default=False,
-                        help='Suppress verbose output, only show basic '
-                             'information in JSON format. Speeds listed in '
-                             'bit/s and not affected by --bytes')
-    parser.add_argument('--list', action='store_true',
-                        help='Display a list of speedtest.net servers '
-                             'sorted by distance')
-    parser.add_argument('--server', type=PARSER_TYPE_INT, action='append',
-                        help='Specify a server ID to test against. Can be '
-                             'supplied multiple times')
-    parser.add_argument('--exclude', type=PARSER_TYPE_INT, action='append',
-                        help='Exclude a server from selection. Can be '
-                             'supplied multiple times')
-    parser.add_argument('--mini', help='URL of the Speedtest Mini server')
-    parser.add_argument('--source', help='Source IP address to bind to')
-    parser.add_argument('--timeout', default=10, type=PARSER_TYPE_FLOAT,
-                        help='HTTP timeout in seconds. Default 10')
-    parser.add_argument('--secure', action='store_true',
-                        help='Use HTTPS instead of HTTP when communicating '
-                             'with speedtest.net operated servers')
-    parser.add_argument('--no-pre-allocate', dest='pre_allocate',
-                        action='store_const', default=True, const=False,
-                        help='Do not pre allocate upload data. Pre allocation '
-                             'is enabled by default to improve upload '
-                             'performance. To support systems with '
-                             'insufficient memory, use this option to avoid a '
-                             'MemoryError')
-    parser.add_argument('--version', action='store_true',
-                        help='Show the version number and exit')
-    parser.add_argument('--debug', action='store_true',
-                        help=ARG_SUPPRESS, default=ARG_SUPPRESS)
+    parser.add_argument(
+        "--no-download",
+        dest="download",
+        default=True,
+        action="store_const",
+        const=False,
+        help="Do not perform download test",
+    )
+    parser.add_argument(
+        "--no-upload",
+        dest="upload",
+        default=True,
+        action="store_const",
+        const=False,
+        help="Do not perform upload test",
+    )
+    parser.add_argument(
+        "--single",
+        default=False,
+        action="store_true",
+        help="Only use a single connection instead of "
+        "multiple. This simulates a typical file "
+        "transfer.",
+    )
+    parser.add_argument(
+        "--bytes",
+        dest="units",
+        action="store_const",
+        const=("byte", 8),
+        default=("bit", 1),
+        help="Display values in bytes instead of bits. Does "
+        "not affect the image generated by --share, nor "
+        "output from --json or --csv",
+    )
+    parser.add_argument(
+        "--share",
+        action="store_true",
+        help="Generate and provide a URL to the speedtest.net "
+        "share results image, not displayed with --csv",
+    )
+    parser.add_argument(
+        "--simple",
+        action="store_true",
+        default=False,
+        help="Suppress verbose output, only show basic " "information",
+    )
+    parser.add_argument(
+        "--csv",
+        action="store_true",
+        default=False,
+        help="Suppress verbose output, only show basic "
+        "information in CSV format. Speeds listed in "
+        "bit/s and not affected by --bytes",
+    )
+    parser.add_argument(
+        "--csv-delimiter",
+        default=",",
+        type=PARSER_TYPE_STR,
+        help="Single character delimiter to use in CSV " 'output. Default ","',
+    )
+    parser.add_argument(
+        "--csv-header",
+        action="store_true",
+        default=False,
+        help="Print CSV headers",
+    )
+    parser.add_argument(
+        "--json",
+        action="store_true",
+        default=False,
+        help="Suppress verbose output, only show basic "
+        "information in JSON format. Speeds listed in "
+        "bit/s and not affected by --bytes",
+    )
+    parser.add_argument(
+        "--list",
+        action="store_true",
+        help="Display a list of speedtest.net servers " "sorted by distance",
+    )
+    parser.add_argument(
+        "--server",
+        type=PARSER_TYPE_INT,
+        action="append",
+        help="Specify a server ID to test against. Can be "
+        "supplied multiple times",
+    )
+    parser.add_argument(
+        "--exclude",
+        type=PARSER_TYPE_INT,
+        action="append",
+        help="Exclude a server from selection. Can be "
+        "supplied multiple times",
+    )
+    parser.add_argument("--mini", help="URL of the Speedtest Mini server")
+    parser.add_argument("--source", help="Source IP address to bind to")
+    parser.add_argument(
+        "--timeout",
+        default=10,
+        type=PARSER_TYPE_FLOAT,
+        help="HTTP timeout in seconds. Default 10",
+    )
+    parser.add_argument(
+        "--secure",
+        action="store_true",
+        help="Use HTTPS instead of HTTP when communicating "
+        "with speedtest.net operated servers",
+    )
+    parser.add_argument(
+        "--no-pre-allocate",
+        dest="pre_allocate",
+        action="store_const",
+        default=True,
+        const=False,
+        help="Do not pre allocate upload data. Pre allocation "
+        "is enabled by default to improve upload "
+        "performance. To support systems with "
+        "insufficient memory, use this option to avoid a "
+        "MemoryError",
+    )
+    parser.add_argument(
+        "--version",
+        action="store_true",
+        help="Show the version number and exit",
+    )
+    parser.add_argument(
+        "--debug", action="store_true", help=ARG_SUPPRESS, default=ARG_SUPPRESS
+    )
 
     options = parser.parse_args()
     if isinstance(options, tuple):
@@ -1792,14 +1968,15 @@ def validate_optional_args(args):
     with an error stating which module is missing.
     """
     optional_args = {
-        'json': ('json/simplejson python module', json),
-        'secure': ('SSL support', HTTPSConnection),
+        "json": ("json/simplejson python module", json),
+        "secure": ("SSL support", HTTPSConnection),
     }
 
     for arg, info in optional_args.items():
         if getattr(args, arg, False) and info[1] is None:
-            raise SystemExit('%s is not installed. --%s is '
-                             'unavailable' % (info[0], arg))
+            raise SystemExit(
+                "%s is not installed. --%s is " "unavailable" % (info[0], arg)
+            )
 
 
 def printer(string, quiet=False, debug=False, error=False, **kwargs):
@@ -1810,14 +1987,14 @@ def printer(string, quiet=False, debug=False, error=False, **kwargs):
 
     if debug:
         if sys.stdout.isatty():
-            out = '\033[1;30mDEBUG: %s\033[0m' % string
+            out = "\033[1;30mDEBUG: %s\033[0m" % string
         else:
-            out = 'DEBUG: %s' % string
+            out = "DEBUG: %s" % string
     else:
         out = string
 
     if error:
-        kwargs['file'] = sys.stderr
+        kwargs["file"] = sys.stderr
 
     if not quiet:
         print_(out, **kwargs)
@@ -1838,19 +2015,20 @@ def shell():
         version()
 
     if not args.download and not args.upload:
-        raise SpeedtestCLIError('Cannot supply both --no-download and '
-                                '--no-upload')
+        raise SpeedtestCLIError(
+            "Cannot supply both --no-download and " "--no-upload"
+        )
 
     if len(args.csv_delimiter) != 1:
-        raise SpeedtestCLIError('--csv-delimiter must be a single character')
+        raise SpeedtestCLIError("--csv-delimiter must be a single character")
 
     if args.csv_header:
         csv_header(args.csv_delimiter)
 
     validate_optional_args(args)
 
-    debug = getattr(args, 'debug', False)
-    if debug == 'SUPPRESSHELP':
+    debug = getattr(args, "debug", False)
+    if debug == "SUPPRESSHELP":
         debug = False
     if debug:
         DEBUG = True
@@ -1871,28 +2049,28 @@ def shell():
     else:
         callback = print_dots(shutdown_event)
 
-    printer('Retrieving speedtest.net configuration...', quiet)
+    printer("Retrieving speedtest.net configuration...", quiet)
     try:
         speedtest = Speedtest(
-            source_address=args.source,
-            timeout=args.timeout,
-            secure=args.secure
+            source_address=args.source, timeout=args.timeout, secure=args.secure
         )
     except (ConfigRetrievalError,) + HTTP_ERRORS:
-        printer('Cannot retrieve speedtest configuration', error=True)
+        printer("Cannot retrieve speedtest configuration", error=True)
         raise SpeedtestCLIError(get_exception())
 
     if args.list:
         try:
             speedtest.get_servers()
         except (ServersRetrievalError,) + HTTP_ERRORS:
-            printer('Cannot retrieve speedtest server list', error=True)
+            printer("Cannot retrieve speedtest server list", error=True)
             raise SpeedtestCLIError(get_exception())
 
         for _, servers in sorted(speedtest.servers.items()):
             for server in servers:
-                line = ('%(id)5s) %(sponsor)s (%(name)s, %(country)s) '
-                        '[%(d)0.2f km]' % server)
+                line = (
+                    "%(id)5s) %(sponsor)s (%(name)s, %(country)s) "
+                    "[%(d)0.2f km]" % server
+                )
                 try:
                     printer(line)
                 except IOError:
@@ -1901,104 +2079,115 @@ def shell():
                         raise
         sys.exit(0)
 
-    printer('Testing from %(isp)s (%(ip)s)...' % speedtest.config['client'],
-            quiet)
+    printer(
+        "Testing from %(isp)s (%(ip)s)..." % speedtest.config["client"], quiet
+    )
 
     if not args.mini:
-        printer('Retrieving speedtest.net server list...', quiet)
+        printer("Retrieving speedtest.net server list...", quiet)
         try:
             speedtest.get_servers(servers=args.server, exclude=args.exclude)
         except NoMatchedServers:
             raise SpeedtestCLIError(
-                'No matched servers: %s' %
-                ', '.join('%s' % s for s in args.server)
+                "No matched servers: %s"
+                % ", ".join("%s" % s for s in args.server)
             )
         except (ServersRetrievalError,) + HTTP_ERRORS:
-            printer('Cannot retrieve speedtest server list', error=True)
+            printer("Cannot retrieve speedtest server list", error=True)
             raise SpeedtestCLIError(get_exception())
         except InvalidServerIDType:
             raise SpeedtestCLIError(
-                '%s is an invalid server type, must '
-                'be an int' % ', '.join('%s' % s for s in args.server)
+                "%s is an invalid server type, must "
+                "be an int" % ", ".join("%s" % s for s in args.server)
             )
 
         if args.server and len(args.server) == 1:
-            printer('Retrieving information for the selected server...', quiet)
+            printer("Retrieving information for the selected server...", quiet)
         else:
-            printer('Selecting best server based on ping...', quiet)
+            printer("Selecting best server based on ping...", quiet)
         speedtest.get_best_server()
     elif args.mini:
         speedtest.get_best_server(speedtest.set_mini_server(args.mini))
 
     results = speedtest.results
 
-    printer('Hosted by %(sponsor)s (%(name)s) [%(d)0.2f km]: '
-            '%(latency)s ms' % results.server, quiet)
+    printer(
+        "Hosted by %(sponsor)s (%(name)s) [%(d)0.2f km]: "
+        "%(latency)s ms" % results.server,
+        quiet,
+    )
 
     if args.download:
-        printer('Testing download speed', quiet,
-                end=('', '\n')[bool(debug)])
-        speedtest.download(
-            callback=callback,
-            threads=(None, 1)[args.single]
+        printer("Testing download speed", quiet, end=("", "\n")[bool(debug)])
+        speedtest.download(callback=callback, threads=(None, 1)[args.single])
+        printer(
+            "Download: %0.2f M%s/s"
+            % (
+                (results.download / 1000.0 / 1000.0) / args.units[1],
+                args.units[0],
+            ),
+            quiet,
         )
-        printer('Download: %0.2f M%s/s' %
-                ((results.download / 1000.0 / 1000.0) / args.units[1],
-                 args.units[0]),
-                quiet)
     else:
-        printer('Skipping download test', quiet)
+        printer("Skipping download test", quiet)
 
     if args.upload:
-        printer('Testing upload speed', quiet,
-                end=('', '\n')[bool(debug)])
+        printer("Testing upload speed", quiet, end=("", "\n")[bool(debug)])
         speedtest.upload(
             callback=callback,
             pre_allocate=args.pre_allocate,
-            threads=(None, 1)[args.single]
+            threads=(None, 1)[args.single],
+        )
+        printer(
+            "Upload: %0.2f M%s/s"
+            % (
+                (results.upload / 1000.0 / 1000.0) / args.units[1],
+                args.units[0],
+            ),
+            quiet,
         )
-        printer('Upload: %0.2f M%s/s' %
-                ((results.upload / 1000.0 / 1000.0) / args.units[1],
-                 args.units[0]),
-                quiet)
     else:
-        printer('Skipping upload test', quiet)
+        printer("Skipping upload test", quiet)
 
-    printer('Results:\n%r' % results.dict(), debug=True)
+    printer("Results:\n%r" % results.dict(), debug=True)
 
     if not args.simple and args.share:
         results.share()
 
     if args.simple:
-        printer('Ping: %s ms\nDownload: %0.2f M%s/s\nUpload: %0.2f M%s/s' %
-                (results.ping,
-                 (results.download / 1000.0 / 1000.0) / args.units[1],
-                 args.units[0],
-                 (results.upload / 1000.0 / 1000.0) / args.units[1],
-                 args.units[0]))
+        printer(
+            "Ping: %s ms\nDownload: %0.2f M%s/s\nUpload: %0.2f M%s/s"
+            % (
+                results.ping,
+                (results.download / 1000.0 / 1000.0) / args.units[1],
+                args.units[0],
+                (results.upload / 1000.0 / 1000.0) / args.units[1],
+                args.units[0],
+            )
+        )
     elif args.csv:
         printer(results.csv(delimiter=args.csv_delimiter))
     elif args.json:
         printer(results.json())
 
     if args.share and not machine_format:
-        printer('Share results: %s' % results.share())
+        printer("Share results: %s" % results.share())
 
 
 def main():
     try:
         shell()
     except KeyboardInterrupt:
-        printer('\nCancelling...', error=True)
+        printer("\nCancelling...", error=True)
     except (SpeedtestException, SystemExit):
         e = get_exception()
         # Ignore a successful exit, or argparse exit
-        if getattr(e, 'code', 1) not in (0, 2):
-            msg = '%s' % e
+        if getattr(e, "code", 1) not in (0, 2):
+            msg = "%s" % e
             if not msg:
-                msg = '%r' % e
-            raise SystemExit('ERROR: %s' % msg)
+                msg = "%r" % e
+            raise SystemExit("ERROR: %s" % msg)
 
 
-if __name__ == '__main__':
+if __name__ == "__main__":
     main()