From 797230da94f97c0fae34867deb4272560d6c6e84 Mon Sep 17 00:00:00 2001 From: abdoulaye Date: Tue, 21 Aug 2018 11:56:09 +0200 Subject: [PATCH 1/9] feat: add notmuch count module Displays the result of a notmuch count query default : unread emails wich path do not contained "Trash" (notmuch count "tag:unread AND NOT path:/.*Trash.*/") Parameters: notmuch_count.query: notmuch count query to show result Errors: if the notmuch query failed, the shown value is -1 Dependencies: notmuch (https://notmuchmail.org/) --- bumblebee/modules/notmuch_count.py | 51 ++++++++++++++++++++++++++++++ themes/icons/awesome-fonts.json | 3 ++ 2 files changed, 54 insertions(+) create mode 100644 bumblebee/modules/notmuch_count.py diff --git a/bumblebee/modules/notmuch_count.py b/bumblebee/modules/notmuch_count.py new file mode 100644 index 0000000..88e6869 --- /dev/null +++ b/bumblebee/modules/notmuch_count.py @@ -0,0 +1,51 @@ +# pylint: disable=C0111,R0903 + +"""Displays the result of a notmuch count query + default : unread emails wich path do not contained "Trash" (notmuch count "tag:unread AND NOT path:/.*Trash.*/") + +Parameters: + * notmuch_count.query: notmuch count query to show result + +Errors: + if the notmuch query failed, the shown value is -1 + +Dependencies: + notmuch (https://notmuchmail.org/) +""" + +import bumblebee.input +import bumblebee.output +import bumblebee.engine +import os + +class Module(bumblebee.engine.Module): + + + def __init__(self, engine, config): + super(Module, self).__init__(engine, config, + bumblebee.output.Widget(full_text=self.output) + ) + self._notmuch_count_query = self.parameter("query", "tag:unread AND NOT path:/.*Trash.*/") + self._notmuch_count = self.count_notmuch() + + + def output(self, widget): + self._notmuch_count = self.count_notmuch() + return str(self._notmuch_count) + + + def state(self, widgets): + if self._notmuch_count == 0: + return "empty" + return "items" + + + def count_notmuch(self): + try: + notmuch_count_cmd = "notmuch count " + self._notmuch_count_query + notmuch_count = int(bumblebee.util.execute(notmuch_count_cmd)) + return notmuch_count + except Exception: + return -1 + +# vim: tabstop=8 expandtab shiftwidth=4 softtabstop=4 diff --git a/themes/icons/awesome-fonts.json b/themes/icons/awesome-fonts.json index b9491da..4d43115 100644 --- a/themes/icons/awesome-fonts.json +++ b/themes/icons/awesome-fonts.json @@ -15,6 +15,9 @@ "load": { "prefix": "" }, "layout": { "prefix": "" }, "layout-xkb": { "prefix": "" }, + "notmuch_count": { "empty": {"prefix": "\uf0e0" }, + "items": {"prefix": "\uf0e0" } + }, "todo": { "empty": {"prefix": "" }, "items": {"prefix": "" }, "uptime": {"prefix": "" } From 3270e3edd8df7e3fdc6c410789d8076667e5f29f Mon Sep 17 00:00:00 2001 From: Tobias Witek Date: Tue, 21 Aug 2018 13:27:31 +0200 Subject: [PATCH 2/9] [doc] Update module count in readme --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index e87ebd0..3232b17 100644 --- a/README.md +++ b/README.md @@ -5,7 +5,7 @@ [![Test Coverage](https://codeclimate.com/github/tobi-wan-kenobi/bumblebee-status/badges/coverage.svg)](https://codeclimate.com/github/tobi-wan-kenobi/bumblebee-status/coverage) [![Issue Count](https://codeclimate.com/github/tobi-wan-kenobi/bumblebee-status/badges/issue_count.svg)](https://codeclimate.com/github/tobi-wan-kenobi/bumblebee-status) -**Many, many thanks to all contributors! As of now, 27 of the modules are from various contributors (!), and only 16 from myself.** +**Many, many thanks to all contributors! As of now, 28 of the modules are from various contributors (!), and only 16 from myself.** ![Solarized Powerline](https://github.com/tobi-wan-kenobi/bumblebee-status/blob/master/screenshots/themes/powerline-solarized.png) From 2461621b564bc89fa928d394d03a20bd8fb115d3 Mon Sep 17 00:00:00 2001 From: abdoulaye Date: Tue, 21 Aug 2018 14:21:40 +0200 Subject: [PATCH 3/9] docs: fix notmuch_count module doc english errors --- bumblebee/modules/notmuch_count.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/bumblebee/modules/notmuch_count.py b/bumblebee/modules/notmuch_count.py index 88e6869..821118a 100644 --- a/bumblebee/modules/notmuch_count.py +++ b/bumblebee/modules/notmuch_count.py @@ -1,7 +1,7 @@ # pylint: disable=C0111,R0903 """Displays the result of a notmuch count query - default : unread emails wich path do not contained "Trash" (notmuch count "tag:unread AND NOT path:/.*Trash.*/") + default : unread emails which path do not contained "Trash" (notmuch count "tag:unread AND NOT path:/.*Trash.*/") Parameters: * notmuch_count.query: notmuch count query to show result From 8c12daa4079f8caa830bf5d465e9ae2065d568f5 Mon Sep 17 00:00:00 2001 From: Frank Scherrer Date: Fri, 24 Aug 2018 10:22:28 +0200 Subject: [PATCH 4/9] add 'which' function to utils and use for 'iwgetid' --- bumblebee/modules/nic.py | 4 +++- bumblebee/util.py | 17 +++++++++++++++++ 2 files changed, 20 insertions(+), 1 deletion(-) diff --git a/bumblebee/modules/nic.py b/bumblebee/modules/nic.py index ca47409..c1c60f8 100644 --- a/bumblebee/modules/nic.py +++ b/bumblebee/modules/nic.py @@ -35,6 +35,8 @@ class Module(bumblebee.engine.Module): self._states["include"].append(state) self._format = self.parameter("format","{intf} {state} {ip} {ssid}"); self._update_widgets(widgets) + self.iwgetid = bumblebee.util.which("iwgetid") + def update(self, widgets): self._update_widgets(widgets) @@ -106,7 +108,7 @@ class Module(bumblebee.engine.Module): def get_ssid(self, intf): if self._iswlan(intf): try: - return subprocess.check_output(["iwgetid","-r",intf]).strip().decode('utf-8') + return subprocess.check_output([self.iwgetid,"-r",intf]).strip().decode('utf-8') except: return "" return "" diff --git a/bumblebee/util.py b/bumblebee/util.py index 8032032..f5bb4ea 100644 --- a/bumblebee/util.py +++ b/bumblebee/util.py @@ -60,4 +60,21 @@ def durationfmt(duration, shorten=False, suffix=False): return "{}{}".format(res, suf if suffix else "") +def which(program): + import os + def is_exe(fpath): + return os.path.isfile(fpath) and os.access(fpath, os.X_OK) + + fpath, fname = os.path.split(program) + if fpath: + if is_exe(program): + return program + else: + for path in os.environ["PATH"].split(os.pathsep) + ["/sbin", "/usr/sbin/", "/usr/local/sbin"]: + exe_file = os.path.join(path, program) + if is_exe(exe_file): + return exe_file + + return None + # vim: tabstop=8 expandtab shiftwidth=4 softtabstop=4 From 62150b3030d4de4446d9de74861b83282cf1b5f6 Mon Sep 17 00:00:00 2001 From: Frank Scherrer Date: Fri, 24 Aug 2018 10:44:42 +0200 Subject: [PATCH 5/9] trying to remove codeclimate complain * Sorry, I don't have codeclimate * did little refactoring, hope it helps. --- bumblebee/util.py | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/bumblebee/util.py b/bumblebee/util.py index f5bb4ea..f3545ac 100644 --- a/bumblebee/util.py +++ b/bumblebee/util.py @@ -70,7 +70,9 @@ def which(program): if is_exe(program): return program else: - for path in os.environ["PATH"].split(os.pathsep) + ["/sbin", "/usr/sbin/", "/usr/local/sbin"]: + localPATH = os.environ["PATH"].split(os.pathsep) + localPATH += ["/sbin", "/usr/sbin/", "/usr/local/sbin"] + for path in localPATH: exe_file = os.path.join(path, program) if is_exe(exe_file): return exe_file From 872c2047e5eddb1ffe684807f78a5ef5d4b63cc8 Mon Sep 17 00:00:00 2001 From: Frank Scherrer Date: Tue, 28 Aug 2018 14:52:17 +0200 Subject: [PATCH 6/9] add test for util.which * and make runtests.sh dash-compatible for debian-like OS --- runtests.sh | 2 +- tests/test_util.py | 9 +++++++++ 2 files changed, 10 insertions(+), 1 deletion(-) diff --git a/runtests.sh b/runtests.sh index 3ae7ddb..549eb4a 100755 --- a/runtests.sh +++ b/runtests.sh @@ -3,7 +3,7 @@ echo "testing with $(python2 -V 2>&1)" python2 $(which nosetests) -v --with-coverage --cover-erase tests/ -if [ $? == 0 ]; then +if test $? -eq 0 ; then echo echo "testing with $(python3 -V 2>&1)" diff --git a/tests/test_util.py b/tests/test_util.py index 1988756..64c320f 100644 --- a/tests/test_util.py +++ b/tests/test_util.py @@ -2,6 +2,7 @@ import mock import unittest +import re import tests.mocks as mocks @@ -53,4 +54,12 @@ class TestUtil(unittest.TestCase): with self.assertRaises(RuntimeError): execute(self.some_command_with_args) + def test_which(self): + program = "iwgetid" + self.assertTrue( + which(program) is None or + re.search('/(' + program + ')$', which(program)) + ) + + # vim: tabstop=8 expandtab shiftwidth=4 softtabstop=4 From a969fc0b7596b8b44ed0963f03b1ed4899fd161f Mon Sep 17 00:00:00 2001 From: WORD559 Date: Sat, 1 Sep 2018 14:40:18 +0100 Subject: [PATCH 7/9] Added parameter to pulseaudio module that allows users to specify the percentage change of the volume when scrolling on the module. --- bumblebee/modules/pulseaudio.py | 12 ++++++++++-- 1 file changed, 10 insertions(+), 2 deletions(-) diff --git a/bumblebee/modules/pulseaudio.py b/bumblebee/modules/pulseaudio.py index 2b4fd05..f6b33cf 100644 --- a/bumblebee/modules/pulseaudio.py +++ b/bumblebee/modules/pulseaudio.py @@ -6,6 +6,7 @@ Aliases: pasink (use this to control output instead of input), pasource Parameters: * pulseaudio.autostart: If set to "true" (default is "false"), automatically starts the pulseaudio daemon if it is not running + * pulseaudio.percent_change: How much to change volume by when scrolling on the module (default is 2%) Requires the following executable: * pulseaudio @@ -33,6 +34,13 @@ class Module(bumblebee.engine.Module): bumblebee.util.execute("pulseaudio --start") except Exception: pass + try: + percent_change = int(self.parameter("percent_change","2%").strip("%")) + except: + percent_change = 2 + if percent_change < 0 or percent_change > 100: + percent_change = 2 + self._left = 0 self._right = 0 @@ -51,8 +59,8 @@ class Module(bumblebee.engine.Module): events = [ {"type": "mute", "action": "toggle", "button": bumblebee.input.LEFT_MOUSE}, - {"type": "volume", "action": "+2%", "button": bumblebee.input.WHEEL_UP}, - {"type": "volume", "action": "-2%", "button": bumblebee.input.WHEEL_DOWN}, + {"type": "volume", "action": "+{percent}%".format(percent=percent_change), "button": bumblebee.input.WHEEL_UP}, + {"type": "volume", "action": "-{percent}%".format(percent=percent_change), "button": bumblebee.input.WHEEL_DOWN}, ] for event in events: From a52c3e8e12ef6bc0fc7066a852e60857bb7da8ca Mon Sep 17 00:00:00 2001 From: Frank Scherrer Date: Tue, 4 Sep 2018 09:24:12 +0200 Subject: [PATCH 8/9] add further tests for which * test which for always present binary "ls" * test which for garbage input --- tests/test_util.py | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/tests/test_util.py b/tests/test_util.py index 64c320f..1aaeaef 100644 --- a/tests/test_util.py +++ b/tests/test_util.py @@ -55,11 +55,19 @@ class TestUtil(unittest.TestCase): execute(self.some_command_with_args) def test_which(self): + # test for a binary that has to be somewhere + print(which("ls")) + self.assertTrue(re.search('/(ls)$', which("ls"))) + + # test for a binary that is not necessarily there program = "iwgetid" self.assertTrue( which(program) is None or re.search('/(' + program + ')$', which(program)) ) + # test if which also works with garbage input + self.assertTrue(which("qwertygarbage") is None) + # vim: tabstop=8 expandtab shiftwidth=4 softtabstop=4 From a6eb5a43a588df6d4429ea21ef6ca77c472a6bfd Mon Sep 17 00:00:00 2001 From: Frank Scherrer Date: Tue, 4 Sep 2018 09:57:29 +0200 Subject: [PATCH 9/9] fix code for flake8 linter --- tests/test_util.py | 44 ++++++++++++++++++++++---------------------- 1 file changed, 22 insertions(+), 22 deletions(-) diff --git a/tests/test_util.py b/tests/test_util.py index 1aaeaef..07d6d3a 100644 --- a/tests/test_util.py +++ b/tests/test_util.py @@ -1,12 +1,12 @@ # pylint: disable=C0103,C0111 -import mock import unittest import re import tests.mocks as mocks -from bumblebee.util import * +import bumblebee.util as bu + class TestUtil(unittest.TestCase): def setUp(self): @@ -18,56 +18,56 @@ class TestUtil(unittest.TestCase): self.popen.cleanup() def test_bytefmt(self): - self.assertEquals(bytefmt(10), "10.00B") - self.assertEquals(bytefmt(15*1024), "15.00KiB") - self.assertEquals(bytefmt(20*1024*1024), "20.00MiB") - self.assertEquals(bytefmt(22*1024*1024*1024), "22.00GiB") - self.assertEquals(bytefmt(35*1024*1024*1024*1024), "35840.00GiB") + self.assertEquals(bu.bytefmt(10), "10.00B") + self.assertEquals(bu.bytefmt(15 * 1024), "15.00KiB") + self.assertEquals(bu.bytefmt(20 * 1024 * 1024), "20.00MiB") + self.assertEquals(bu.bytefmt(22 * 1024 * 1024 * 1024), "22.00GiB") + self.assertEquals(bu.bytefmt(35 * 1024 * 1024 * 1024 * 1024), "35840.00GiB") def test_durationfmt(self): - self.assertEquals(durationfmt(00), "00:00") - self.assertEquals(durationfmt(25), "00:25") - self.assertEquals(durationfmt(60), "01:00") - self.assertEquals(durationfmt(119), "01:59") - self.assertEquals(durationfmt(3600), "01:00:00") - self.assertEquals(durationfmt(7265), "02:01:05") + self.assertEquals(bu.durationfmt(00), "00:00") + self.assertEquals(bu.durationfmt(25), "00:25") + self.assertEquals(bu.durationfmt(60), "01:00") + self.assertEquals(bu.durationfmt(119), "01:59") + self.assertEquals(bu.durationfmt(3600), "01:00:00") + self.assertEquals(bu.durationfmt(7265), "02:01:05") def test_execute(self): - execute(self.some_command_with_args) + bu.execute(self.some_command_with_args) self.assertTrue(self.popen.mock.popen.called) self.popen.mock.popen.assert_call(self.some_command_with_args) self.assertTrue(self.popen.mock.communicate.called) def test_execute_nowait(self): - execute(self.some_command_with_args, False) + bu.execute(self.some_command_with_args, False) self.assertTrue(self.popen.mock.popen.called) self.popen.mock.popen.assert_call(self.some_command_with_args) self.assertFalse(self.popen.mock.communicate.called) def test_execute_utf8(self): - self.popen.mock.communicate.return_value = [ self.some_utf8, None ] + self.popen.mock.communicate.return_value = [self.some_utf8, None] self.test_execute() def test_execute_error(self): self.popen.mock.returncode = 1 with self.assertRaises(RuntimeError): - execute(self.some_command_with_args) + bu.execute(self.some_command_with_args) def test_which(self): # test for a binary that has to be somewhere - print(which("ls")) - self.assertTrue(re.search('/(ls)$', which("ls"))) + print(bu.which("ls")) + self.assertTrue(re.search('/(ls)$', bu.which("ls"))) # test for a binary that is not necessarily there program = "iwgetid" self.assertTrue( - which(program) is None or - re.search('/(' + program + ')$', which(program)) + bu.which(program) is None or + re.search('/(' + program + ')$', bu.which(program)) ) # test if which also works with garbage input - self.assertTrue(which("qwertygarbage") is None) + self.assertTrue(bu.which("qwertygarbage") is None) # vim: tabstop=8 expandtab shiftwidth=4 softtabstop=4