From 338ad21ccba244900d4ba408cd3c0801096fdfd1 Mon Sep 17 00:00:00 2001 From: Gareth Dunstone Date: Wed, 14 Sep 2016 10:24:17 +1000 Subject: [PATCH 1/5] fixed net_speed to properly use speedtest-cli/modularize-2 added some nice unicode formatting down and up symbols for download and upload speed. --- i3pystatus/net_speed.py | 150 +++++++++++++++++++++------------------- 1 file changed, 77 insertions(+), 73 deletions(-) diff --git a/i3pystatus/net_speed.py b/i3pystatus/net_speed.py index fce158de..a159896c 100644 --- a/i3pystatus/net_speed.py +++ b/i3pystatus/net_speed.py @@ -1,5 +1,5 @@ from i3pystatus import IntervalModule -import speedtest_cli +import speedtest import requests import time import os @@ -12,23 +12,56 @@ class NetSpeed(IntervalModule): """ Attempts to provide an estimation of internet speeds. - Requires: speedtest_cli + Requires: speedtest-cli/modularize-2 """ settings = ( - ("url", "Target URL to download a file from. Uses speedtest_cli to " - "find the 'best' server if none is supplied."), ("units", "Valid values are B, b, bytes, or bits"), "format" ) color = "#FFFFFF" interval = 300 - url = None units = 'bits' - format = "{speed} ({hosting_provider})" + format = "↓{speed_down:.2f}{down_units} ↑{speed_up:.2f}{up_units} ({hosting_provider})" + + def form_b(self, n: float)->tuple: + """ + formates a bps as bps/kbps/mbps/gbps etc + handles whether its meant to be in bytes + :param n: input float + :rtype tuple: + :return: tuple of float-number of mbps etc, str-units + """ + unit = 'bps' + kilo = 1000 + mega = 1000000 + giga = 1000000000 + bps = 0 + + if self.units == 'bytes' or self.units == 'B': + unit = 'Bps' + kilo = 8000 + mega = 8000000 + giga = 8000000000 + + if n < kilo: + bps = float(n) + + if n >= kilo and n < mega: + unit = "K" + unit + bps = float(n / 1024.0) + + if n >= mega and n < giga: + unit = "M" + unit + bps = float(n / (1024.0 * 1024.0)) + + if n >= giga: + unit = "G" + unit + bps = float(n / (1024.0 * 1024.0 * 1024.0)) + + return bps, unit def run(self): - # since speedtest_cli likes to print crap, we need to squelch it @contextlib.contextmanager def nostdout(): @@ -37,73 +70,44 @@ def nostdout(): yield sys.stdout = save_stdout - if not self.url: - with nostdout(): + cdict = { + "speed_up": 0.0, + "speed_down": 0.0, + "down_units": "", + "up_units": "", + "hosting_provider": 'null' + } + st = None + with nostdout(): + try: + # this is now the canonical way to use speedtest_cli as a module. + st = speedtest.Speedtest() + except speedtest.ConfigRetrievalError: + # log('Cannot retrieve speedtest configuration') + self.output = {} + if st: try: - config = speedtest_cli.getConfig() - servers = speedtest_cli.closestServers(config['client']) - best = speedtest_cli.getBestServer(servers) - # 1500x1500 is about 4.3MB, which seems like a reasonable place to - # start, i guess... - url = '%s/random1500x1500.jpg' % os.path.dirname(best['url']) - except KeyError: - url = None - - if not url: - cdict = { - "speed": 0, - "hosting_provider": 'null', - } - else: - with open('/dev/null', 'wb') as devnull: - start = time.time() - req = requests.get(url, stream=True) - devnull.write(req.content) - end = time.time() - total_length = int(req.headers.get('content-length')) - devnull.close() - - # chop off the float after the 4th decimal point - # note: not rounding, simply cutting - # note: dl_time is in seconds - dl_time = float(end - start) - - if self.units == 'bits' or self.units == 'b': - unit = 'bps' - kilo = 1000 - mega = 1000000 - giga = 1000000000 - factor = 8 - elif self.units == 'bytes' or self.units == 'B': - unit = 'Bps' - kilo = 8000 - mega = 8000000 - giga = 8000000000 - factor = 1 - - if total_length < kilo: - bps = float(total_length / dl_time) - - if total_length >= kilo and total_length < mega: - unit = "K" + unit - bps = float((total_length / 1024.0) / dl_time) - - if total_length >= mega and total_length < giga: - unit = "M" + unit - bps = float((total_length / (1024.0 * 1024.0)) / dl_time) - - if total_length >= giga: - unit = "G" + unit - bps = float((total_length / (1024.0 * 1024.0 * 1024.0)) / dl_time) - - bps = "%.2f" % (bps * factor) - speed = "%s %s" % (bps, unit) - hosting_provider = '.'.join(urlparse(url).hostname.split('.')[-2:]) - - cdict = { - "speed": speed, - "hosting_provider": hosting_provider, - } + # get the servers + st.get_servers() + st.get_best_server() + + except speedtest.ServersRetrievalError: + # log this somehow + # log('Cannot retrieve speedtest server list') + pass + results = st.results + + down, up = st.download(), st.upload() + speed_down, down_units = self.form_b(down) + speed_up, up_units = self.form_b(up) + + cdict = { + "speed_down": speed_down, + "speed_up": speed_up, + "up_units": up_units, + "down_units": down_units, + "hosting_provider": results.server.get("sponsor", "Unknown Provider") + } self.output = { "full_text": self.format.format(**cdict), From 439e725107ed71aff87a6e68731c19b8efcc8e5b Mon Sep 17 00:00:00 2001 From: Gareth Dunstone Date: Wed, 14 Sep 2016 10:33:10 +1000 Subject: [PATCH 2/5] 2fp is too precise I think --- i3pystatus/net_speed.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/i3pystatus/net_speed.py b/i3pystatus/net_speed.py index a159896c..1f70c212 100644 --- a/i3pystatus/net_speed.py +++ b/i3pystatus/net_speed.py @@ -22,7 +22,7 @@ class NetSpeed(IntervalModule): color = "#FFFFFF" interval = 300 units = 'bits' - format = "↓{speed_down:.2f}{down_units} ↑{speed_up:.2f}{up_units} ({hosting_provider})" + format = "↓{speed_down:.1f}{down_units} ↑{speed_up:.1f}{up_units} ({hosting_provider})" def form_b(self, n: float)->tuple: """ From ca3a9b60b34f1e1f24535e9dcc182410d128e60e Mon Sep 17 00:00:00 2001 From: Gareth Dunstone Date: Thu, 15 Sep 2016 12:18:51 +1000 Subject: [PATCH 3/5] change to conf as per https://github.com/enkore/i3pystatus/pull/449#issuecomment-247045192 --- docs/conf.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/conf.py b/docs/conf.py index bc11038d..e24cd8d3 100644 --- a/docs/conf.py +++ b/docs/conf.py @@ -32,7 +32,7 @@ "bs4", "dota2py", "novaclient", - "speedtest_cli", + "speedtest", "pyzabbix", "vk", "google-api-python-client", From 207aa220357f380d841413cac98053ae3a3a94ed Mon Sep 17 00:00:00 2001 From: Gareth Dunstone Date: Wed, 28 Sep 2016 14:15:35 +1000 Subject: [PATCH 4/5] change to conf as per https://github.com/enkore/i3pystatus/pull/449#issuecomment-247045192 --- i3pystatus/net_speed.py | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/i3pystatus/net_speed.py b/i3pystatus/net_speed.py index 1f70c212..8981d66a 100644 --- a/i3pystatus/net_speed.py +++ b/i3pystatus/net_speed.py @@ -13,6 +13,8 @@ class NetSpeed(IntervalModule): """ Attempts to provide an estimation of internet speeds. Requires: speedtest-cli/modularize-2 + speedtest-cli/modularize-2 can be installed using pip: + `pip install https://github.com/sivel/speedtest-cli/archive/modularize-2.zip` """ settings = ( @@ -26,7 +28,7 @@ class NetSpeed(IntervalModule): def form_b(self, n: float)->tuple: """ - formates a bps as bps/kbps/mbps/gbps etc + formats a bps as bps/kbps/mbps/gbps etc handles whether its meant to be in bytes :param n: input float :rtype tuple: From c462ecf9556724901a385329267899d09a0cc3d0 Mon Sep 17 00:00:00 2001 From: Gareth Dunstone Date: Wed, 28 Sep 2016 14:20:06 +1000 Subject: [PATCH 5/5] Added to docstring pip installation command for speedtest-cli/modularize-2 --- i3pystatus/net_speed.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/i3pystatus/net_speed.py b/i3pystatus/net_speed.py index 8981d66a..22357ca1 100644 --- a/i3pystatus/net_speed.py +++ b/i3pystatus/net_speed.py @@ -14,7 +14,7 @@ class NetSpeed(IntervalModule): Attempts to provide an estimation of internet speeds. Requires: speedtest-cli/modularize-2 speedtest-cli/modularize-2 can be installed using pip: - `pip install https://github.com/sivel/speedtest-cli/archive/modularize-2.zip` + `pip install git+https://github.com/sivel/speedtest-cli.git@modularize-2` """ settings = (