From 30c1f712a6d58f2de5be78ddb20f895e657a4730 Mon Sep 17 00:00:00 2001 From: tobi-wan-kenobi Date: Sun, 3 May 2020 11:15:52 +0200 Subject: [PATCH] [formatting] reformat using "black -t py34" getting rid of thinking about consistent formatting... --- bumblebee-ctl | 46 +- bumblebee-status | 48 +- core/config.py | 179 ++-- core/decorators.py | 44 +- core/event.py | 8 +- core/input.py | 44 +- core/module.py | 62 +- core/output.py | 172 ++-- core/theme.py | 77 +- core/widget.py | 20 +- modules/contrib/amixer.py | 28 +- modules/contrib/apt.py | 49 +- modules/contrib/arch-update.py | 8 +- modules/contrib/bluetooth.py | 76 +- modules/contrib/bluetooth2.py | 68 +- modules/contrib/caffeine.py | 38 +- modules/contrib/cpu2.py | 113 ++- modules/contrib/currency.py | 1254 ++++++--------------------- modules/contrib/datetimetz.py | 53 +- modules/contrib/datetz.py | 4 +- modules/contrib/deadbeef.py | 90 +- modules/contrib/deezer.py | 72 +- modules/contrib/dnf.py | 50 +- modules/contrib/docker_ps.py | 22 +- modules/contrib/dunst.py | 25 +- modules/contrib/getcrypto.py | 63 +- modules/contrib/github.py | 35 +- modules/contrib/gpmdp.py | 41 +- modules/contrib/hddtemp.py | 21 +- modules/contrib/hostname.py | 6 +- modules/contrib/http_status.py | 20 +- modules/contrib/indicator.py | 37 +- modules/contrib/layout-xkbswitch.py | 15 +- modules/contrib/layout.py | 43 +- modules/contrib/libvirtvms.py | 9 +- modules/contrib/mocp.py | 10 +- modules/contrib/mpd.py | 169 ++-- modules/contrib/network_traffic.py | 45 +- modules/contrib/notmuch_count.py | 18 +- modules/contrib/nvidiagpu.py | 76 +- modules/contrib/octoprint.py | 120 ++- modules/contrib/pacman.py | 33 +- modules/contrib/pihole.py | 48 +- modules/contrib/pomodoro.py | 87 +- modules/contrib/prime.py | 31 +- modules/contrib/progress.py | 74 +- modules/contrib/publicip.py | 7 +- modules/contrib/rotation.py | 32 +- modules/contrib/rss.py | 185 ++-- modules/contrib/sensors.py | 90 +- modules/contrib/shell.py | 18 +- modules/contrib/shortcut.py | 20 +- modules/contrib/smartstatus.py | 98 ++- modules/contrib/spaceapi.py | 39 +- modules/contrib/spotify.py | 76 +- modules/contrib/stock.py | 31 +- modules/contrib/sun.py | 29 +- modules/contrib/system.py | 71 +- modules/contrib/taskwarrior.py | 12 +- modules/contrib/timetz.py | 6 +- modules/contrib/title.py | 31 +- modules/contrib/todo.py | 18 +- modules/contrib/traffic.py | 122 ++- modules/contrib/twmn.py | 18 +- modules/contrib/uptime.py | 10 +- modules/contrib/vpn.py | 47 +- modules/contrib/watson.py | 20 +- modules/contrib/weather.py | 99 ++- modules/contrib/xkcd.py | 12 +- modules/contrib/yubikey.py | 10 +- modules/contrib/zpool.py | 171 ++-- modules/core/__pulseaudio.py | 133 +-- modules/core/battery-upower.py | 211 +++-- modules/core/battery.py | 152 ++-- modules/core/brightness.py | 37 +- modules/core/cmus.py | 105 ++- modules/core/cpu.py | 15 +- modules/core/date.py | 4 +- modules/core/datetime.py | 22 +- modules/core/debug.py | 6 +- modules/core/disk.py | 33 +- modules/core/error.py | 13 +- modules/core/git.py | 48 +- modules/core/kernel.py | 2 + modules/core/layout-xkb.py | 32 +- modules/core/load.py | 15 +- modules/core/memory.py | 60 +- modules/core/nic.py | 98 ++- modules/core/pasink.py | 4 +- modules/core/pasource.py | 4 +- modules/core/ping.py | 73 +- modules/core/redshift.py | 81 +- modules/core/sensors2.py | 169 ++-- modules/core/spacer.py | 2 + modules/core/test.py | 4 +- modules/core/time.py | 6 +- modules/core/vault.py | 47 +- modules/core/xrandr.py | 83 +- tests/core/test_config.py | 57 +- tests/core/test_decorators.py | 59 +- tests/core/test_event.py | 30 +- tests/core/test_input.py | 70 +- tests/core/test_module.py | 92 +- tests/core/test_output.py | 139 +-- tests/core/test_theme.py | 123 ++- tests/core/test_widget.py | 52 +- tests/modules/test_kernel.py | 10 +- tests/util/test_algorithm.py | 10 +- tests/util/test_cli.py | 22 +- tests/util/test_format.py | 92 +- tests/util/test_location.py | 40 +- tests/util/test_store.py | 28 +- util/algorithm.py | 1 + util/cli.py | 17 +- util/format.py | 55 +- util/graph.py | 102 ++- util/location.py | 56 +- util/popup.py | 8 +- util/store.py | 11 +- 119 files changed, 3961 insertions(+), 3495 deletions(-) diff --git a/bumblebee-ctl b/bumblebee-ctl index c470d0e..b1c0f37 100755 --- a/bumblebee-ctl +++ b/bumblebee-ctl @@ -7,34 +7,48 @@ import glob import socket button = { - 'left-mouse': 1, - 'middle-mouse': 2, - 'right-mouse': 3, - 'wheel-up': 4, - 'wheel-down': 5, + "left-mouse": 1, + "middle-mouse": 2, + "right-mouse": 3, + "wheel-up": 4, + "wheel-down": 5, } + def main(): - parser = argparse.ArgumentParser(description='send commands to bumblebee-status') - parser.add_argument('-b', '--button', choices=['left-mouse', 'right-mouse', 'middle-mouse', 'wheel-up', 'wheel-down'], help='button to emulate', default='left-mouse') - parser.add_argument('-i', '--id', help='ID of widget to trigger') - parser.add_argument('-m', '--module', help='name of the module to trigger', required=True) + parser = argparse.ArgumentParser(description="send commands to bumblebee-status") + parser.add_argument( + "-b", + "--button", + choices=["left-mouse", "right-mouse", "middle-mouse", "wheel-up", "wheel-down"], + help="button to emulate", + default="left-mouse", + ) + parser.add_argument("-i", "--id", help="ID of widget to trigger") + parser.add_argument( + "-m", "--module", help="name of the module to trigger", required=True + ) args = parser.parse_args() - for f in glob.glob('/tmp/.bumblebee-status.*'): + for f in glob.glob("/tmp/.bumblebee-status.*"): s = socket.socket(socket.AF_UNIX, socket.SOCK_STREAM) try: s.connect(f) - s.sendall(json.dumps({ - 'name': args.module, - 'instance': args.id, - 'button': button[args.button], - }).encode('ascii')) + s.sendall( + json.dumps( + { + "name": args.module, + "instance": args.id, + "button": button[args.button], + } + ).encode("ascii") + ) except Exception as e: os.remove(f) -if __name__ == '__main__': + +if __name__ == "__main__": main() # vim: tabstop=8 expandtab shiftwidth=4 softtabstop=4 diff --git a/bumblebee-status b/bumblebee-status index a621165..920dff1 100755 --- a/bumblebee-status +++ b/bumblebee-status @@ -14,9 +14,10 @@ import core.module import core.input import core.event + class CommandSocket(object): def __init__(self): - self.__name = '/tmp/.bumblebee-status.{}'.format(os.getpid()) + self.__name = "/tmp/.bumblebee-status.{}".format(os.getpid()) self.__socket = None def __enter__(self): @@ -29,6 +30,7 @@ class CommandSocket(object): self.__socket.close() os.unlink(self.__name) + def handle_input(output): with CommandSocket() as cmdsocket: poll = select.poll() @@ -44,24 +46,25 @@ def handle_input(output): tmp, _ = cmdsocket.accept() line = tmp.recv(4096).decode() tmp.close() - logging.debug('socket event {}'.format(line)) + logging.debug("socket event {}".format(line)) else: - line = '[' - while line.startswith('['): - line = sys.stdin.readline().strip(',').strip() - logging.info('input event: {}'.format(line)) + line = "[" + while line.startswith("["): + line = sys.stdin.readline().strip(",").strip() + logging.info("input event: {}".format(line)) try: event = json.loads(line) core.input.trigger(event) - if 'name' in event: - modules[event['name']] = True + if "name" in event: + modules[event["name"]] = True except ValueError: pass - core.event.trigger('update', modules.keys()) - core.event.trigger('draw') + core.event.trigger("update", modules.keys()) + core.event.trigger("draw") poll.unregister(sys.stdin.fileno()) + def main(): config = core.config.Config(sys.argv[1:]) @@ -70,28 +73,28 @@ def main(): logging.basicConfig( level=level, format="[%(asctime)s] %(module)-16s %(levelname)-8s %(message)s", - filename=os.path.abspath(os.path.expanduser(config.logfile())) + filename=os.path.abspath(os.path.expanduser(config.logfile())), ) else: logging.basicConfig( level=level, format="[%(asctime)s] %(module)-16s %(levelname)-8s %(message)s", - stream=sys.stderr + stream=sys.stderr, ) theme = core.theme.Theme(config.theme(), config.iconset()) output = core.output.i3(theme, config) modules = [] - core.input.register(None, core.input.WHEEL_UP, 'i3-msg workspace prev_on_output') - core.input.register(None, core.input.WHEEL_DOWN, 'i3-msg workspace next_on_output') + core.input.register(None, core.input.WHEEL_UP, "i3-msg workspace prev_on_output") + core.input.register(None, core.input.WHEEL_DOWN, "i3-msg workspace next_on_output") input_thread = threading.Thread(target=handle_input, args=(output,)) input_thread.daemon = True input_thread.start() if config.debug(): - modules.append(core.module.load('debug', config, theme)) + modules.append(core.module.load("debug", config, theme)) for module in config.modules(): modules.append(core.module.load(module, config, theme)) @@ -100,12 +103,13 @@ def main(): modules.reverse() output.modules(modules) - core.event.trigger('start') + core.event.trigger("start") while True: - core.event.trigger('update') - core.event.trigger('draw') + core.event.trigger("update") + core.event.trigger("draw") output.wait(config.interval()) - core.event.trigger('stop') + core.event.trigger("stop") + if __name__ == "__main__": main() @@ -113,9 +117,9 @@ if __name__ == "__main__": main() except Exception as e: output = core.output.i3() - output.modules(core.module.Error(module='main', error=e)) - output.draw('start') + output.modules(core.module.Error(module="main", error=e)) + output.draw("start") output.update() - output.draw('statusline') + output.draw("statusline") # vim: tabstop=8 expandtab shiftwidth=4 softtabstop=4 diff --git a/core/config.py b/core/config.py index 19989cf..3aad18e 100644 --- a/core/config.py +++ b/core/config.py @@ -19,58 +19,66 @@ import modules.contrib log = logging.getLogger(__name__) -MODULE_HELP = 'Specify a space-separated list of modules to load. The order of the list determines their order in the i3bar (from left to right). Use : to provide an alias in case you want to load the same module multiple times, but specify different parameters.' -PARAMETER_HELP = 'Provide configuration parameters in the form of .=' -THEME_HELP = 'Specify the theme to use for drawing modules' +MODULE_HELP = "Specify a space-separated list of modules to load. The order of the list determines their order in the i3bar (from left to right). Use : to provide an alias in case you want to load the same module multiple times, but specify different parameters." +PARAMETER_HELP = ( + "Provide configuration parameters in the form of .=" +) +THEME_HELP = "Specify the theme to use for drawing modules" + def all_modules(): """Return a list of available modules""" result = {} - for path in [ modules.core.__file__, modules.contrib.__file__ ]: + for path in [modules.core.__file__, modules.contrib.__file__]: path = os.path.dirname(path) - for mod in glob.iglob('{}/*.py'.format(path)): - result[os.path.basename(mod).replace('.py', '')] = 1 - + for mod in glob.iglob("{}/*.py".format(path)): + result[os.path.basename(mod).replace(".py", "")] = 1 + res = list(result.keys()) res.sort() return res + class print_usage(argparse.Action): def __init__(self, option_strings, dest, nargs=None, **kwargs): argparse.Action.__init__(self, option_strings, dest, nargs, **kwargs) - self._indent = ' '*2 + self._indent = " " * 2 def __call__(self, parser, namespace, value, option_string=None): - if value == 'modules': + if value == "modules": self._args = namespace - self._format = 'plain' + self._format = "plain" self.print_modules() - elif value == 'modules-markdown': + elif value == "modules-markdown": self._args = namespace - self._format = 'markdown' + self._format = "markdown" self.print_modules() - elif value == 'themes': + elif value == "themes": self.print_themes() sys.exit(0) def print_themes(self): - print(', '.join(core.theme.themes())) + print(", ".join(core.theme.themes())) def print_modules(self): - if self._format == 'markdown': - print('# Table of modules') - print('|Name |Description |') - print('|-----|------------|') + if self._format == "markdown": + print("# Table of modules") + print("|Name |Description |") + print("|-----|------------|") for m in all_modules(): try: - basepath = os.path.abspath(os.path.join(os.path.dirname(os.path.realpath(__file__)), '..')) - filename = os.path.join(basepath, 'modules', 'core', '{}.py'.format(m)) + basepath = os.path.abspath( + os.path.join(os.path.dirname(os.path.realpath(__file__)), "..") + ) + filename = os.path.join(basepath, "modules", "core", "{}.py".format(m)) if not os.path.exists(filename): - filename = os.path.join(basepath, 'modules', 'contrib', '{}.py'.format(m)) + filename = os.path.join( + basepath, "modules", "contrib", "{}.py".format(m) + ) if not os.path.exists(filename): - log.warning('module {} not found'.format(m)) + log.warning("module {} not found".format(m)) continue doc = None @@ -79,72 +87,126 @@ class print_usage(argparse.Action): doc = ast.get_docstring(tree) if not doc: - log.warning('failed to find docstring for {}'.format(m)) + log.warning("failed to find docstring for {}".format(m)) continue - if self._format == 'markdown': - doc = doc.replace('<', '\<') - doc = doc.replace('>', '\>') - doc = doc.replace('\n', '
') - print('|{} |{} |'.format(m, doc)) + if self._format == "markdown": + doc = doc.replace("<", "\<") + doc = doc.replace(">", "\>") + doc = doc.replace("\n", "
") + print("|{} |{} |".format(m, doc)) else: - print(textwrap.fill('{}:'.format(m), 80, - initial_indent=self._indent*2, subsequent_indent=self._indent*2)) - for line in doc.split('\n'): - print(textwrap.fill(line, 80, - initial_indent=self._indent*3, subsequent_indent=self._indent*6)) + print( + textwrap.fill( + "{}:".format(m), + 80, + initial_indent=self._indent * 2, + subsequent_indent=self._indent * 2, + ) + ) + for line in doc.split("\n"): + print( + textwrap.fill( + line, + 80, + initial_indent=self._indent * 3, + subsequent_indent=self._indent * 6, + ) + ) except Exception as e: log.warning(e) + class Config(util.store.Store): def __init__(self, args): super(Config, self).__init__() - parser = argparse.ArgumentParser(description='bumblebee-status is a modular, theme-able status line generator for the i3 window manager. https://github.com/tobi-wan-kenobi/bumblebee-status/wiki') - parser.add_argument('-m', '--modules', nargs='+', action='append', default=[], - help=MODULE_HELP) - parser.add_argument('-p', '--parameters', nargs='+', action='append', default=[], - help=PARAMETER_HELP) - parser.add_argument('-t', '--theme', default='default', help=THEME_HELP) - parser.add_argument('-i', '--iconset', default='auto', - help='Specify the name of an iconset to use (overrides theme default)') - parser.add_argument('-a', '--autohide', nargs='+', default=[], - help='Specify a list of modules to hide when not in warning/error state') - parser.add_argument('-d', '--debug', action='store_true', - help='Add debug fields to i3 output') - parser.add_argument('-f', '--logfile', help='destination for the debug log file, if -d|--debug is specified; defaults to stderr') - parser.add_argument('-r', '--right-to-left', action='store_true', help='Draw widgets from right to left, rather than left to right (which is the default)') - parser.add_argument('-l', '--list', choices=['modules', 'themes', 'modules-markdown'], help='Display a list of available themes or available modules, along with their parameters', - action=print_usage) + parser = argparse.ArgumentParser( + description="bumblebee-status is a modular, theme-able status line generator for the i3 window manager. https://github.com/tobi-wan-kenobi/bumblebee-status/wiki" + ) + parser.add_argument( + "-m", "--modules", nargs="+", action="append", default=[], help=MODULE_HELP + ) + parser.add_argument( + "-p", + "--parameters", + nargs="+", + action="append", + default=[], + help=PARAMETER_HELP, + ) + parser.add_argument("-t", "--theme", default="default", help=THEME_HELP) + parser.add_argument( + "-i", + "--iconset", + default="auto", + help="Specify the name of an iconset to use (overrides theme default)", + ) + parser.add_argument( + "-a", + "--autohide", + nargs="+", + default=[], + help="Specify a list of modules to hide when not in warning/error state", + ) + parser.add_argument( + "-d", "--debug", action="store_true", help="Add debug fields to i3 output" + ) + parser.add_argument( + "-f", + "--logfile", + help="destination for the debug log file, if -d|--debug is specified; defaults to stderr", + ) + parser.add_argument( + "-r", + "--right-to-left", + action="store_true", + help="Draw widgets from right to left, rather than left to right (which is the default)", + ) + parser.add_argument( + "-l", + "--list", + choices=["modules", "themes", "modules-markdown"], + help="Display a list of available themes or available modules, along with their parameters", + action=print_usage, + ) self.__args = parser.parse_args(args) - for cfg in [ '~/.bumblebee-status.conf', '~/.config/bumblebee-status.conf', '~/.config/bumblebee-status/config' ]: + for cfg in [ + "~/.bumblebee-status.conf", + "~/.config/bumblebee-status.conf", + "~/.config/bumblebee-status/config", + ]: cfg = os.path.expanduser(cfg) self.load_config(cfg) - parameters = [ item for sub in self.__args.parameters for item in sub ] + parameters = [item for sub in self.__args.parameters for item in sub] for param in parameters: - if not '=' in param: - log.error('missing value for parameter "{}" - ignoring this parameter'.format(param)) + if not "=" in param: + log.error( + 'missing value for parameter "{}" - ignoring this parameter'.format( + param + ) + ) continue - key, value = param.split('=', 1) + key, value = param.split("=", 1) self.set(key, value) def load_config(self, filename): if os.path.exists(filename): - log.info('loading {}'.format(filename)) + log.info("loading {}".format(filename)) tmp = RawConfigParser() tmp.read(filename) - if tmp.has_section('module-parameters'): - for key, value in tmp.items('module-parameters'): + if tmp.has_section("module-parameters"): + for key, value in tmp.items("module-parameters"): self.set(key, value) def modules(self): return [item for sub in self.__args.modules for item in sub] def interval(self, default=1): - return util.format.seconds(self.get('interval', default)) + return util.format.seconds(self.get("interval", default)) def debug(self): return self.__args.debug @@ -164,4 +226,5 @@ class Config(util.store.Store): def autohide(self, name): return name in self.__args.autohide + # vim: tabstop=8 expandtab shiftwidth=4 softtabstop=4 diff --git a/core/decorators.py b/core/decorators.py index 9c9e37c..56b2ead 100644 --- a/core/decorators.py +++ b/core/decorators.py @@ -1,41 +1,49 @@ import util.format + def never(init): def call_init(obj, *args, **kwargs): init(obj, *args, **kwargs) - if obj.parameter('interval') is None: - obj.set('interval', 'never') + if obj.parameter("interval") is None: + obj.set("interval", "never") + return call_init + def every(hours=0, minutes=0, seconds=0): def decorator_init(init): def call_init(obj, *args, **kwargs): init(obj, *args, **kwargs) - if obj.parameter('interval') is None: - obj.set('interval', hours*3600 + minutes*60 + seconds) + if obj.parameter("interval") is None: + obj.set("interval", hours * 3600 + minutes * 60 + seconds) + return call_init + return decorator_init + def scrollable(func): def wrapper(module, widget): text = func(module, widget) if not text: return text - width = widget.get('theme.width', util.format.asint(module.parameter('width', 30))) - if util.format.asbool(module.parameter('scrolling.makewide', True)): - widget.set('theme.minwidth', 'A'*width) + width = widget.get( + "theme.width", util.format.asint(module.parameter("width", 30)) + ) + if util.format.asbool(module.parameter("scrolling.makewide", True)): + widget.set("theme.minwidth", "A" * width) if width < 0 or len(text) <= width: return text - start = widget.get('scrolling.start', 0) - bounce = util.format.asbool(module.parameter('scrolling.bounce', True)) - scroll_speed = util.format.asint(module.parameter('scrolling.speed', 1)) - direction = widget.get('scrolling.direction', 'right') + start = widget.get("scrolling.start", 0) + bounce = util.format.asbool(module.parameter("scrolling.bounce", True)) + scroll_speed = util.format.asint(module.parameter("scrolling.speed", 1)) + direction = widget.get("scrolling.direction", "right") - if direction == 'left': + if direction == "left": scroll_speed = -scroll_speed - if start + scroll_speed <= 0: # bounce back - widget.set('scrolling.direction', 'right') + if start + scroll_speed <= 0: # bounce back + widget.set("scrolling.direction", "right") next_start = start + scroll_speed if next_start + width > len(text): @@ -43,11 +51,13 @@ def scrollable(func): next_start = 0 else: next_start = start - scroll_speed - widget.set('scrolling.direction', 'left') + widget.set("scrolling.direction", "left") - widget.set('scrolling.start', next_start) + widget.set("scrolling.start", next_start) + + return text[start : start + width] - return text[start:start+width] return wrapper + # vim: tabstop=8 expandtab shiftwidth=4 softtabstop=4 diff --git a/core/event.py b/core/event.py index a9a364c..3cd7931 100644 --- a/core/event.py +++ b/core/event.py @@ -1,6 +1,6 @@ - __callbacks = {} + def register(event, callback, *args, **kwargs): cb = callback if len(args) + len(kwargs) > 0: @@ -8,12 +8,15 @@ def register(event, callback, *args, **kwargs): __callbacks.setdefault(event, []).append(cb) + def clear(): __callbacks.clear() + def trigger(event, *args, **kwargs): cb = __callbacks.get(event, []) - if len(cb) == 0: return False + if len(cb) == 0: + return False for callback in cb: if len(args) + len(kwargs) == 0: @@ -22,4 +25,5 @@ def trigger(event, *args, **kwargs): callback(*args, **kwargs) return True + # vim: tabstop=8 expandtab shiftwidth=4 softtabstop=4 diff --git a/core/input.py b/core/input.py index 308f7f7..66519d5 100644 --- a/core/input.py +++ b/core/input.py @@ -11,45 +11,59 @@ RIGHT_MOUSE = 3 WHEEL_UP = 4 WHEEL_DOWN = 5 + def button_name(button): - if button == LEFT_MOUSE: return 'left-mouse' - if button == RIGHT_MOUSE: return 'right-mouse' - if button == MIDDLE_MOUSE: return 'middle-mouse' - if button == WHEEL_UP: return 'wheel-up' - if button == WHEEL_DOWN: return 'wheel-down' - return 'n/a' + if button == LEFT_MOUSE: + return "left-mouse" + if button == RIGHT_MOUSE: + return "right-mouse" + if button == MIDDLE_MOUSE: + return "middle-mouse" + if button == WHEEL_UP: + return "wheel-up" + if button == WHEEL_DOWN: + return "wheel-down" + return "n/a" + class Object(object): def __init__(self): super(Object, self).__init__() self.id = str(uuid.uuid4()) + def __event_id(obj_id, button): - return '{}::{}'.format(obj_id, button_name(button)) + return "{}::{}".format(obj_id, button_name(button)) + def __execute(cmd): try: util.cli.execute(cmd, wait=False) except Exception as e: - logging.error('failed to invoke callback: {}'.format(e)) + logging.error("failed to invoke callback: {}".format(e)) + def register(obj, button=None, cmd=None): - event_id = __event_id(obj.id if obj is not None else '', button) - logging.debug('registering callback {}'.format(event_id)) + event_id = __event_id(obj.id if obj is not None else "", button) + logging.debug("registering callback {}".format(event_id)) if callable(cmd): core.event.register(event_id, cmd) else: core.event.register(event_id, lambda _: __execute(cmd)) + def trigger(event): - if not 'button' in event: return + if not "button" in event: + return triggered = False - for field in ['instance', 'name']: - if not field in event: continue - if core.event.trigger(__event_id(event[field], event['button']), event): + for field in ["instance", "name"]: + if not field in event: + continue + if core.event.trigger(__event_id(event[field], event["button"]), event): triggered = True if not triggered: - core.event.trigger(__event_id('', event['button']), event) + core.event.trigger(__event_id("", event["button"]), event) + # vim: tabstop=8 expandtab shiftwidth=4 softtabstop=4 diff --git a/core/module.py b/core/module.py index 2ccce29..07403ab 100644 --- a/core/module.py +++ b/core/module.py @@ -7,35 +7,41 @@ import core.widget import core.decorators try: - error = ModuleNotFoundError('') + error = ModuleNotFoundError("") except Exception as e: ModuleNotFoundError = Exception log = logging.getLogger(__name__) + def load(module_name, config=core.config.Config([]), theme=None): error = None - module_short, alias = (module_name.split(':') + [module_name])[0:2] - config.set('__alias__', alias) - for namespace in [ 'core', 'contrib' ]: + module_short, alias = (module_name.split(":") + [module_name])[0:2] + config.set("__alias__", alias) + for namespace in ["core", "contrib"]: try: - mod = importlib.import_module('modules.{}.{}'.format(namespace, module_short)) - log.debug('importing {} from {}.{}'.format(module_short, namespace, module_short)) - return getattr(mod, 'Module')(config, theme) + mod = importlib.import_module( + "modules.{}.{}".format(namespace, module_short) + ) + log.debug( + "importing {} from {}.{}".format(module_short, namespace, module_short) + ) + return getattr(mod, "Module")(config, theme) except ImportError as e: - error = e - log.fatal('failed to import {}: {}'.format(module_name, error)) + error = e + log.fatal("failed to import {}: {}".format(module_name, error)) return Error(config=config, module=module_name, error=error) + class Module(core.input.Object): def __init__(self, config=core.config.Config([]), theme=None, widgets=[]): super().__init__() self.__config = config - self.__widgets = widgets if isinstance(widgets, list) else [ widgets ] + self.__widgets = widgets if isinstance(widgets, list) else [widgets] - self.module_name = self.__module__.split('.')[-1] + self.module_name = self.__module__.split(".")[-1] self.name = self.module_name - self.alias = self.__config.get('__alias__', None) + self.alias = self.__config.get("__alias__", None) self.id = self.alias if self.alias else self.name self.next_update = None @@ -50,13 +56,13 @@ class Module(core.input.Object): def parameter(self, key, default=None): value = default - for prefix in [ self.name, self.module_name, self.alias ]: - value = self.__config.get('{}.{}'.format(prefix, key), value) + for prefix in [self.name, self.module_name, self.alias]: + value = self.__config.get("{}.{}".format(prefix, key), value) # TODO retrieve from config file return value def set(self, key, value): - self.__config.set('{}.{}'.format(self.name, key), value) + self.__config.set("{}.{}".format(self.name, key), value) def update(self): pass @@ -65,8 +71,8 @@ class Module(core.input.Object): try: self.update() except Exception as e: - self.set('interval', 1) - module = Error(config=self.__config, module='error', error=str(e)) + self.set("interval", 1) + module = Error(config=self.__config, module="error", error=str(e)) self.__widgets = [module.widget()] self.update = module.update @@ -75,28 +81,31 @@ class Module(core.input.Object): self.__widgets = widgets return self.__widgets - def add_widget(self, full_text='', name=None): + def add_widget(self, full_text="", name=None): widget = core.widget.Widget(full_text=full_text, name=name, module=self) self.widgets().append(widget) return widget def widget(self, name=None): - if not name: return self.widgets()[0] + if not name: + return self.widgets()[0] for w in self.widgets(): - if w.name == name: return w + if w.name == name: + return w return None def state(self, widget): return [] def threshold_state(self, value, warn, crit): - if value > float(self.parameter('critical', crit)): - return 'critical' - if value > float(self.parameter('warning', warn)): - return 'warning' + if value > float(self.parameter("critical", crit)): + return "critical" + if value > float(self.parameter("warning", warn)): + return "warning" return None + class Error(Module): def __init__(self, module, error, config=core.config.Config([]), theme=None): super().__init__(config, theme, core.widget.Widget(self.full_text)) @@ -104,9 +113,10 @@ class Error(Module): self.__error = error def full_text(self, widget): - return '{}: {}'.format(self.__module, self.__error) + return "{}: {}".format(self.__module, self.__error) def state(self, widget): - return ['critical'] + return ["critical"] + # vim: tabstop=8 expandtab shiftwidth=4 softtabstop=4 diff --git a/core/output.py b/core/output.py index af1a5b8..da22697 100644 --- a/core/output.py +++ b/core/output.py @@ -7,15 +7,17 @@ import core.event import util.format + def dump_json(obj): return obj.dict() + def assign(src, dst, key, src_key=None, default=None): if not src_key: - if key.startswith('_'): + if key.startswith("_"): src_key = key else: - src_key = key.replace('_', '-') # automagically replace _ with - + src_key = key.replace("_", "-") # automagically replace _ with - for k in src_key if isinstance(src_key, list) else [src_key]: if k in src: @@ -24,12 +26,23 @@ def assign(src, dst, key, src_key=None, default=None): if default is not None: dst[key] = default + class block(object): __COMMON_THEME_FIELDS = [ - 'separator', 'separator-block-width', 'default-separators', - 'border-top', 'border-left', 'border-right', 'border-bottom', - 'fg', 'bg', 'padding', 'prefix', 'suffix' + "separator", + "separator-block-width", + "default-separators", + "border-top", + "border-left", + "border-right", + "border-bottom", + "fg", + "bg", + "padding", + "prefix", + "suffix", ] + def __init__(self, theme, module, widget): self.__attributes = {} for key in self.__COMMON_THEME_FIELDS: @@ -37,72 +50,85 @@ class block(object): if tmp is not None: self.__attributes[key] = tmp - self.__attributes['name'] = module.id - self.__attributes['instance'] = widget.id - self.__attributes['prev-bg'] = theme.get('bg', 'previous') + self.__attributes["name"] = module.id + self.__attributes["instance"] = widget.id + self.__attributes["prev-bg"] = theme.get("bg", "previous") def set(self, key, value): self.__attributes[key] = value def is_pango(self, attr): - if isinstance(attr, dict) and 'pango' in attr: + if isinstance(attr, dict) and "pango" in attr: return True return False def pangoize(self, text): if not self.is_pango(text): return text - self.__attributes['markup'] = 'pango' - attr = dict(text['pango']) - text = attr.get('full_text', '') - if 'full_text' in attr: - del attr['full_text'] - result = ' self.index(): self.id = custom_ids[self.index()] def index(self): - if not self.module: return 0 + if not self.module: + return 0 idx = 0 for w in self.module.widgets(): if w.id == self.id: return idx idx = idx + 1 - return -1 # not found + return -1 # not found def theme(self, attribute): - attr = 'theme.{}'.format(attribute) + attr = "theme.{}".format(attribute) if self.module: param = util.format.aslist(self.module.parameter(attr)) if param and len(param) > self.index(): @@ -54,12 +57,13 @@ class Widget(util.store.Store, core.input.Object): def state(self): rv = [] - if self.get('state', None): - tmp = self.get('state') + if self.get("state", None): + tmp = self.get("state") rv = tmp[:] if isinstance(tmp, list) else [tmp] if self.module: tmp = self.module.state(self) rv.extend(tmp if isinstance(tmp, list) else [tmp]) return rv + # vim: tabstop=8 expandtab shiftwidth=4 softtabstop=4 diff --git a/modules/contrib/amixer.py b/modules/contrib/amixer.py index 6c94e72..cdce9ca 100644 --- a/modules/contrib/amixer.py +++ b/modules/contrib/amixer.py @@ -10,36 +10,40 @@ import core.widget import util.cli + class Module(core.module.Module): def __init__(self, config, theme): super().__init__(config, theme, core.widget.Widget(self.volume)) - self.__level = 'n/a' + self.__level = "n/a" self.__muted = True - device = self.parameter('device', 'Master,0') - self._cmdString = 'amixer get {}'.format(device) + device = self.parameter("device", "Master,0") + self._cmdString = "amixer get {}".format(device) def volume(self, widget): - if self.__level == 'n/a': + if self.__level == "n/a": return self.__level - m = re.search(r'([\d]+)\%', self.__level) + m = re.search(r"([\d]+)\%", self.__level) self.__muted = True if m: - if m.group(1) != '0' and '[on]' in self.__level: + if m.group(1) != "0" and "[on]" in self.__level: self.__muted = False - return '{}%'.format(m.group(1)) + return "{}%".format(m.group(1)) else: - return '0%' + return "0%" def update(self): try: - self.__level = util.cli.execute('amixer get {}'.format(self.parameter('device', 'Master,0'))) + self.__level = util.cli.execute( + "amixer get {}".format(self.parameter("device", "Master,0")) + ) except Exception as e: - self.__level = 'n/a' + self.__level = "n/a" def state(self, widget): if self.__muted: - return ['warning', 'muted'] - return ['unmuted'] + return ["warning", "muted"] + return ["unmuted"] + # vim: tabstop=8 expandtab shiftwidth=4 softtabstop=4 diff --git a/modules/contrib/apt.py b/modules/contrib/apt.py index 4673606..093ab3c 100644 --- a/modules/contrib/apt.py +++ b/modules/contrib/apt.py @@ -15,34 +15,39 @@ import core.decorators import util.cli -PATTERN = '{} packages upgraded, {} newly installed, {} to remove and {} not upgraded.' +PATTERN = "{} packages upgraded, {} newly installed, {} to remove and {} not upgraded." + def parse_result(to_parse): # We want to line with the iforamtion about package upgrade - line_to_parse = to_parse.split('\n')[-4] - result = re.search('(.+) packages upgraded, (.+) newly installed, (.+) to remove', line_to_parse) + line_to_parse = to_parse.split("\n")[-4] + result = re.search( + "(.+) packages upgraded, (.+) newly installed, (.+) to remove", line_to_parse + ) return int(result.group(1)), int(result.group(3)) + def get_apt_check_info(module): widget = module.widget() try: - res = util.cli.execute('aptitude full-upgrade --simulate --assume-yes') - widget.set('error', None) + res = util.cli.execute("aptitude full-upgrade --simulate --assume-yes") + widget.set("error", None) except (RuntimeError, FileNotFoundError) as e: - widget.set('error', 'unable to query APT: {}'.format(e)) + widget.set("error", "unable to query APT: {}".format(e)) return to_upgrade = 0 to_remove = 0 try: to_upgrade, to_remove = parse_result(res) - widget.set('to_upgrade', to_upgrade) - widget.set('to_remove', to_remove) + widget.set("to_upgrade", to_upgrade) + widget.set("to_remove", to_remove) except Exception as e: - widget.set('error', 'parse error: {}'.format(e)) + widget.set("error", "parse error: {}".format(e)) + + core.event.trigger("update", [module.id], redraw_only=True) - core.event.trigger('update', [ module.id ], redraw_only=True) class Module(core.module.Module): @core.decorators.every(minutes=30) @@ -51,30 +56,32 @@ class Module(core.module.Module): self.__thread = None def updates(self, widget): - if widget.get('error'): - return widget.get('error') - return '{} to upgrade, {} to remove'.format( - widget.get('to_upgrade', 0), widget.get('to_remove', 0) + if widget.get("error"): + return widget.get("error") + return "{} to upgrade, {} to remove".format( + widget.get("to_upgrade", 0), widget.get("to_remove", 0) ) def update(self): - if self.__thread and self.__thread.isAlive(): return + if self.__thread and self.__thread.isAlive(): + return self.__thread = threading.Thread(target=get_apt_check_info, args=(self,)) self.__thread.start() def state(self, widget): cnt = 0 - ret = 'good' - for t in ['to_upgrade', 'to_remove']: + ret = "good" + for t in ["to_upgrade", "to_remove"]: cnt += widget.get(t, 0) if cnt > 50: - ret = 'critical' + ret = "critical" elif cnt > 0: - ret = 'warning' - if widget.get('error'): - ret = 'critical' + ret = "warning" + if widget.get("error"): + ret = "critical" return ret + # vim: tabstop=8 expandtab shiftwidth=4 softtabstop=4 diff --git a/modules/contrib/arch-update.py b/modules/contrib/arch-update.py index f833af6..493fa3d 100644 --- a/modules/contrib/arch-update.py +++ b/modules/contrib/arch-update.py @@ -10,6 +10,7 @@ import core.decorators import util.cli + class Module(core.module.Module): @core.decorators.every(minutes=60) def __init__(self, config, theme): @@ -18,7 +19,7 @@ class Module(core.module.Module): @property def __format(self): - return self.parameter('format', 'Update Arch: {}') + return self.parameter("format", "Update Arch: {}") def utilization(self, widget): return self.__format.format(self.__packages) @@ -27,10 +28,11 @@ class Module(core.module.Module): return self.__packages == 0 def update(self): - result = util.cli.execute('checkupdates') - self.__packages = len(result.split('\n')) - 1 + result = util.cli.execute("checkupdates") + self.__packages = len(result.split("\n")) - 1 def state(self, widget): return self.threshold_state(self.__packages, 1, 100) + # vim: tabstop=8 expandtab shiftwidth=4 softtabstop=4 diff --git a/modules/contrib/bluetooth.py b/modules/contrib/bluetooth.py index cbca01e..7d5b078 100644 --- a/modules/contrib/bluetooth.py +++ b/modules/contrib/bluetooth.py @@ -23,30 +23,27 @@ import util.cli import util.format import util.popup + class Module(core.module.Module): def __init__(self, config, theme): super().__init__(config, theme, core.widget.Widget(self.status)) - device = self.parameter('device', 'hci0') - self.manager = self.parameter('manager', 'blueman-manager') - self._path = '/sys/class/bluetooth/{}'.format(device) - self._status = 'Off' + device = self.parameter("device", "hci0") + self.manager = self.parameter("manager", "blueman-manager") + self._path = "/sys/class/bluetooth/{}".format(device) + self._status = "Off" - core.input.register(self, button=core.input.LEFT_MOUSE, - cmd=self.manager) + core.input.register(self, button=core.input.LEFT_MOUSE, cmd=self.manager) # determine whether to use pop-up menu or simply toggle the device on/off right_click_popup = util.format.asbool( - self.parameter('right_click_popup', True)) + self.parameter("right_click_popup", True) + ) if right_click_popup: - core.input.register(self, - button=core.input.RIGHT_MOUSE, - cmd=self.popup) + core.input.register(self, button=core.input.RIGHT_MOUSE, cmd=self.popup) else: - core.input.register(self, - button=core.input.RIGHT_MOUSE, - cmd=self._toggle) + core.input.register(self, button=core.input.RIGHT_MOUSE, cmd=self._toggle) def status(self, widget): """Get status.""" @@ -55,35 +52,33 @@ class Module(core.module.Module): def update(self): """Update current state.""" if not os.path.exists(self._path): - self._status = '?' + self._status = "?" return # search for whichever rfkill directory available try: dirnames = next(os.walk(self._path))[1] for dirname in dirnames: - m = re.match(r'rfkill[0-9]+', dirname) + m = re.match(r"rfkill[0-9]+", dirname) if m is not None: - with open(os.path.join(self._path, - dirname, - 'state'), 'r') as f: + with open(os.path.join(self._path, dirname, "state"), "r") as f: state = int(f.read()) if state == 1: - self._status = 'On' + self._status = "On" else: - self._status = 'Off' + self._status = "Off" return except IOError: - self._status = '?' + self._status = "?" def popup(self, widget): """Show a popup menu.""" menu = util.popup.PopupMenu() - if self._status == 'On': - menu.add_menuitem('Disable Bluetooth') - elif self._status == 'Off': - menu.add_menuitem('Enable Bluetooth') + if self._status == "On": + menu.add_menuitem("Disable Bluetooth") + elif self._status == "Off": + menu.add_menuitem("Enable Bluetooth") else: return @@ -95,32 +90,35 @@ class Module(core.module.Module): def _toggle(self, widget=None): """Toggle bluetooth state.""" - if self._status == 'On': - state = 'false' + if self._status == "On": + state = "false" else: - state = 'true' + state = "true" - dst = self.parameter('dbus_destination', 'org.blueman.Mechanism') - dst_path = self.parameter('dbus_destination_path', '/') + dst = self.parameter("dbus_destination", "org.blueman.Mechanism") + dst_path = self.parameter("dbus_destination_path", "/") - cmd = 'dbus-send --system --print-reply --dest={}'\ - ' {} org.blueman.Mechanism.SetRfkillState'\ - ' boolean:{}'.format(dst, dst_path, state) + cmd = ( + "dbus-send --system --print-reply --dest={}" + " {} org.blueman.Mechanism.SetRfkillState" + " boolean:{}".format(dst, dst_path, state) + ) - logging.debug('bt: toggling bluetooth') + logging.debug("bt: toggling bluetooth") util.cli.execute(cmd) def state(self, widget): """Get current state.""" state = [] - if self._status == '?': - state = ['unknown'] - elif self._status == 'On': - state = ['ON'] + if self._status == "?": + state = ["unknown"] + elif self._status == "On": + state = ["ON"] else: - state = ['OFF'] + state = ["OFF"] return state + # vim: tabstop=8 expandtab shiftwidth=4 softtabstop=4 diff --git a/modules/contrib/bluetooth2.py b/modules/contrib/bluetooth2.py index 48e391b..796da91 100644 --- a/modules/contrib/bluetooth2.py +++ b/modules/contrib/bluetooth2.py @@ -20,19 +20,18 @@ import core.input import util.cli + class Module(core.module.Module): def __init__(self, config, theme): super().__init__(config, theme, core.widget.Widget(self.status)) - self.manager = self.parameter('manager', 'blueman-manager') - self._status = 'Off' + self.manager = self.parameter("manager", "blueman-manager") + self._status = "Off" dbus.mainloop.glib.DBusGMainLoop(set_as_default=True) self._bus = dbus.SystemBus() - core.input.register(self, button=core.input.LEFT_MOUSE, - cmd=self.manager) - core.input.register(self, button=core.input.RIGHT_MOUSE, - cmd=self._toggle) + core.input.register(self, button=core.input.LEFT_MOUSE, cmd=self.manager) + core.input.register(self, button=core.input.RIGHT_MOUSE, cmd=self._toggle) def status(self, widget): """Get status.""" @@ -40,58 +39,63 @@ class Module(core.module.Module): def update(self): """Update current state.""" - state = len(subprocess.run(['bluetoothctl', 'list'], stdout=subprocess.PIPE).stdout) + state = len( + subprocess.run(["bluetoothctl", "list"], stdout=subprocess.PIPE).stdout + ) if state > 0: connected_devices = self.get_connected_devices() - self._status = 'On - {}'.format(connected_devices) + self._status = "On - {}".format(connected_devices) else: - self._status = 'Off' - adapters_cmd = 'rfkill list | grep Bluetooth' - if not len(subprocess.run(adapters_cmd, shell=True, stdout=subprocess.PIPE).stdout): - self._status = 'No Adapter Found' + self._status = "Off" + adapters_cmd = "rfkill list | grep Bluetooth" + if not len( + subprocess.run(adapters_cmd, shell=True, stdout=subprocess.PIPE).stdout + ): + self._status = "No Adapter Found" return def _toggle(self, widget=None): """Toggle bluetooth state.""" - if 'On' in self._status: - state = 'false' + if "On" in self._status: + state = "false" else: - state = 'true' + state = "true" - cmd = 'dbus-send --system --print-reply --dest=org.blueman.Mechanism /org/blueman/mechanism org.blueman.Mechanism.SetRfkillState boolean:%s' % state + cmd = ( + "dbus-send --system --print-reply --dest=org.blueman.Mechanism /org/blueman/mechanism org.blueman.Mechanism.SetRfkillState boolean:%s" + % state + ) - logging.debug('bt: toggling bluetooth') + logging.debug("bt: toggling bluetooth") core.util.execute(cmd) def state(self, widget): """Get current state.""" state = [] - if self._status == 'No Adapter Found': - state.append('critical') - elif self._status == 'On - 0': - state.append('warning') - elif 'On' in self._status and not(self._status == 'On - 0'): - state.append('ON') + if self._status == "No Adapter Found": + state.append("critical") + elif self._status == "On - 0": + state.append("warning") + elif "On" in self._status and not (self._status == "On - 0"): + state.append("ON") else: - state.append('critical') + state.append("critical") return state def get_connected_devices(self): devices = 0 objects = dbus.Interface( - self._bus.get_object('org.bluez', '/'), - 'org.freedesktop.DBus.ObjectManager' + self._bus.get_object("org.bluez", "/"), "org.freedesktop.DBus.ObjectManager" ).GetManagedObjects() for path, interfaces in objects.items(): - if 'org.bluez.Device1' in interfaces: + if "org.bluez.Device1" in interfaces: if dbus.Interface( - self._bus.get_object('org.bluez', path), - 'org.freedesktop.DBus.Properties' - ).Get( - 'org.bluez.Device1', 'Connected' - ): + self._bus.get_object("org.bluez", path), + "org.freedesktop.DBus.Properties", + ).Get("org.bluez.Device1", "Connected"): devices += 1 return devices + # vim: tabstop=8 expandtab shiftwidth=4 softtabstop=4 diff --git a/modules/contrib/caffeine.py b/modules/contrib/caffeine.py index 45b1b1d..dfbfe2f 100644 --- a/modules/contrib/caffeine.py +++ b/modules/contrib/caffeine.py @@ -1,4 +1,4 @@ -#pylint: disable=C0111,R0903,W0212 +# pylint: disable=C0111,R0903,W0212 """Enable/disable automatic screen locking. @@ -21,10 +21,11 @@ import core.decorators import util.cli + class Module(core.module.Module): @core.decorators.every(minutes=10) def __init__(self, config, theme): - super().__init__(config, theme, core.widget.Widget('')) + super().__init__(config, theme, core.widget.Widget("")) self.__active = False self.__xid = None @@ -32,7 +33,7 @@ class Module(core.module.Module): core.input.register(self, button=core.input.LEFT_MOUSE, cmd=self.__toggle) def __check_requirements(self): - requirements = ['xdotool', 'xprop', 'xdg-screensaver'] + requirements = ["xdotool", "xprop", "xdg-screensaver"] missing = [] for tool in requirements: if not shutil.which(tool): @@ -40,20 +41,24 @@ class Module(core.module.Module): return missing def __get_i3bar_xid(self): - xid = util.cli.execute('xdotool search --class \'i3bar\'').partition('\n')[0].strip() + xid = ( + util.cli.execute("xdotool search --class 'i3bar'") + .partition("\n")[0] + .strip() + ) if xid.isdigit(): return xid - logging.warning('Module caffeine: xdotool couldn\'t get X window ID of \'i3bar\'.') + logging.warning("Module caffeine: xdotool couldn't get X window ID of 'i3bar'.") return None def __notify(self): - if not shutil.which('notify-send'): + if not shutil.which("notify-send"): return if self.__active: - util.cli.execute('notify-send \'Consuming caffeine\'') + util.cli.execute("notify-send 'Consuming caffeine'") else: - util.cli.execute('notify-send \'Out of coffee\'') + util.cli.execute("notify-send 'Out of coffee'") def _suspend_screensaver(self): self.__xid = self.__get_i3bar_xid() @@ -63,7 +68,7 @@ class Module(core.module.Module): pid = os.fork() if pid == 0: os.setsid() - util.cli.execute('xdg-screensaver suspend {}'.format(self.__xid)) + util.cli.execute("xdg-screensaver suspend {}".format(self.__xid)) os._exit(0) else: os.waitpid(pid, 0) @@ -71,8 +76,12 @@ class Module(core.module.Module): def __resume_screensaver(self): success = True - xprop_path = shutil.which('xprop') - pids = [ p.pid for p in psutil.process_iter() if p.cmdline() == [xprop_path, '-id', str(self.__xid), '-spy'] ] + xprop_path = shutil.which("xprop") + pids = [ + p.pid + for p in psutil.process_iter() + if p.cmdline() == [xprop_path, "-id", str(self.__xid), "-spy"] + ] for pid in pids: try: os.kill(pid, 9) @@ -82,13 +91,13 @@ class Module(core.module.Module): def state(self, _): if self.__active: - return 'activated' - return 'deactivated' + return "activated" + return "deactivated" def __toggle(self, _): missing = self.__check_requirements() if missing: - logging.warning('Could not run caffeine - missing %s!', ', '.join(missing)) + logging.warning("Could not run caffeine - missing %s!", ", ".join(missing)) return self.__active = not self.__active @@ -102,4 +111,5 @@ class Module(core.module.Module): else: self.__active = not self.__active + # vim: tabstop=8 expandtab shiftwidth=4 softtabstop=4 diff --git a/modules/contrib/cpu2.py b/modules/contrib/cpu2.py index 4c3af00..68db8c8 100644 --- a/modules/contrib/cpu2.py +++ b/modules/contrib/cpu2.py @@ -42,90 +42,88 @@ import util.cli import util.graph import util.format + class Module(core.module.Module): def __init__(self, config, theme): super().__init__(config, theme, []) - self.__layout = self.parameter('layout', 'cpu2.maxfreq cpu2.cpuload cpu2.coresload cpu2.temp cpu2.fanspeed') + self.__layout = self.parameter( + "layout", "cpu2.maxfreq cpu2.cpuload cpu2.coresload cpu2.temp cpu2.fanspeed" + ) self.__widget_names = self.__layout.split() - self.__colored = util.format.asbool(self.parameter('colored', False)) + self.__colored = util.format.asbool(self.parameter("colored", False)) widget_list = [] for widget_name in self.__widget_names: - if widget_name == 'cpu2.maxfreq': - widget = core.widget.Widget( - name=widget_name, full_text=self.maxfreq) - widget.set('type', 'freq') - elif widget_name == 'cpu2.cpuload': - widget = core.widget.Widget( - name=widget_name, full_text=self.cpuload) - widget.set('type', 'load') - elif widget_name == 'cpu2.coresload': - widget = core.widget.Widget( - name=widget_name, full_text=self.coresload) - widget.set('type', 'loads') - elif widget_name == 'cpu2.temp': - widget = core.widget.Widget( - name=widget_name, full_text=self.temp) - widget.set('type', 'temp') - elif widget_name == 'cpu2.fanspeed': - widget = core.widget.Widget( - name=widget_name, full_text=self.fanspeed) - widget.set('type', 'fan') + if widget_name == "cpu2.maxfreq": + widget = core.widget.Widget(name=widget_name, full_text=self.maxfreq) + widget.set("type", "freq") + elif widget_name == "cpu2.cpuload": + widget = core.widget.Widget(name=widget_name, full_text=self.cpuload) + widget.set("type", "load") + elif widget_name == "cpu2.coresload": + widget = core.widget.Widget(name=widget_name, full_text=self.coresload) + widget.set("type", "loads") + elif widget_name == "cpu2.temp": + widget = core.widget.Widget(name=widget_name, full_text=self.temp) + widget.set("type", "temp") + elif widget_name == "cpu2.fanspeed": + widget = core.widget.Widget(name=widget_name, full_text=self.fanspeed) + widget.set("type", "fan") if self.__colored: - widget.set('pango', True) + widget.set("pango", True) widget_list.append(widget) self.widgets(widget_list) - self.__temp_pattern = self.parameter('temp_pattern') + self.__temp_pattern = self.parameter("temp_pattern") if self.__temp_pattern is None: - self.__temp = 'n/a' - self.__fan_pattern = self.parameter('fan_pattern') + self.__temp = "n/a" + self.__fan_pattern = self.parameter("fan_pattern") if self.__fan_pattern is None: - self.__fan = 'n/a' + self.__fan = "n/a" # maxfreq is loaded only once at startup - if 'cpu2.maxfreq' in self.__widget_names: + if "cpu2.maxfreq" in self.__widget_names: self.__maxfreq = psutil.cpu_freq().max / 1000 def maxfreq(self, _): - return '{:.2f}GHz'.format(self.__maxfreq) + return "{:.2f}GHz".format(self.__maxfreq) def cpuload(self, _): - return '{:>3}%'.format(self.__cpuload) + return "{:>3}%".format(self.__cpuload) def add_color(self, bar): """add color as pango markup to a bar""" - if bar in ['▁', '▂']: - color = self.theme.color('green', 'green') - elif bar in ['▃', '▄']: - color = self.theme.color('yellow', 'yellow') - elif bar in ['▅', '▆']: - color = self.theme.color('orange', 'orange') - elif bar in ['▇', '█']: - color = self.theme.color('red', 'red') + if bar in ["▁", "▂"]: + color = self.theme.color("green", "green") + elif bar in ["▃", "▄"]: + color = self.theme.color("yellow", "yellow") + elif bar in ["▅", "▆"]: + color = self.theme.color("orange", "orange") + elif bar in ["▇", "█"]: + color = self.theme.color("red", "red") colored_bar = '{}'.format(color, bar) return colored_bar def coresload(self, _): mono_bars = [util.graph.hbar(x) for x in self.__coresload] if not self.__colored: - return ''.join(mono_bars) + return "".join(mono_bars) colored_bars = [self.add_color(x) for x in mono_bars] - return ''.join(colored_bars) + return "".join(colored_bars) def temp(self, _): - if self.__temp == 'n/a' or self.__temp == 0: - return 'n/a' - return '{}°C'.format(self.__temp) + if self.__temp == "n/a" or self.__temp == 0: + return "n/a" + return "{}°C".format(self.__temp) def fanspeed(self, _): - if self.__fanspeed == 'n/a': - return 'n/a' - return '{}RPM'.format(self.__fanspeed) + if self.__fanspeed == "n/a": + return "n/a" + return "{}RPM".format(self.__fanspeed) def _parse_sensors_output(self): - output = util.cli.execute('sensors -u') - lines = output.split('\n') - temp = 'n/a' - fan = 'n/a' + output = util.cli.execute("sensors -u") + lines = output.split("\n") + temp = "n/a" + fan = "n/a" temp_line = None fan_line = None for line in lines: @@ -136,23 +134,24 @@ class Module(core.module.Module): if temp_line is not None and fan_line is not None: break if temp_line is not None: - temp = round(float(temp_line.split(':')[1].strip())) + temp = round(float(temp_line.split(":")[1].strip())) if fan_line is not None: - fan = int(fan_line.split(':')[1].strip()[:-4]) + fan = int(fan_line.split(":")[1].strip()[:-4]) return temp, fan def update(self): - if 'cpu2.maxfreq' in self.__widget_names: + if "cpu2.maxfreq" in self.__widget_names: self.__maxfreq = psutil.cpu_freq().max / 1000 - if 'cpu2.cpuload' in self.__widget_names: + if "cpu2.cpuload" in self.__widget_names: self.__cpuload = round(psutil.cpu_percent(percpu=False)) - if 'cpu2.coresload' in self.__widget_names: + if "cpu2.coresload" in self.__widget_names: self.__coresload = psutil.cpu_percent(percpu=True) - if 'cpu2.temp' in self.__widget_names or 'cpu2.fanspeed' in self.__widget_names: + if "cpu2.temp" in self.__widget_names or "cpu2.fanspeed" in self.__widget_names: self.__temp, self.__fanspeed = self._parse_sensors_output() def state(self, widget): """for having per-widget icons""" - return [widget.get('type', '')] + return [widget.get("type", "")] + # vim: tabstop=8 expandtab shiftwidth=4 softtabstop=4 diff --git a/modules/contrib/currency.py b/modules/contrib/currency.py index 3aa1634..96efd28 100644 --- a/modules/contrib/currency.py +++ b/modules/contrib/currency.py @@ -18,6 +18,7 @@ Note: source and destination names right now must correspond to the names used b """ import requests + try: from babel.numbers import format_currency except ImportError: @@ -32,990 +33,264 @@ import core.decorators import util.format import util.location -SYMBOL = { - 'GBP': u'£', 'EUR': u'€', 'USD': u'$', 'JPY': u'¥', 'KRW': u'₩' -} -DEFAULT_DEST = 'USD,EUR,auto' -DEFAULT_SRC = 'GBP' +SYMBOL = {"GBP": "£", "EUR": "€", "USD": "$", "JPY": "¥", "KRW": "₩"} +DEFAULT_DEST = "USD,EUR,auto" +DEFAULT_SRC = "GBP" + +API_URL = "https://markets.ft.com/data/currencies/ajax/conversion?baseCurrency={}&comparison={}" -API_URL = 'https://markets.ft.com/data/currencies/ajax/conversion?baseCurrency={}&comparison={}' def load_country_to_currency(): return [ - { - "country": "Afghanistan", - "currency_code": "AFN" - }, - { - "country": "Albania", - "currency_code": "ALL" - }, - { - "country": "Algeria", - "currency_code": "DZD" - }, - { - "country": "American Samoa", - "currency_code": "USD" - }, - { - "country": "Andorra", - "currency_code": "EUR" - }, - { - "country": "Angola", - "currency_code": "AOA" - }, - { - "country": "Anguilla", - "currency_code": "XCD" - }, - { - "country": "Antarctica", - "currency_code": "XCD" - }, - { - "country": "Antigua and Barbuda", - "currency_code": "XCD" - }, - { - "country": "Argentina", - "currency_code": "ARS" - }, - { - "country": "Armenia", - "currency_code": "AMD" - }, - { - "country": "Aruba", - "currency_code": "AWG" - }, - { - "country": "Australia", - "currency_code": "AUD" - }, - { - "country": "Austria", - "currency_code": "EUR" - }, - { - "country": "Azerbaijan", - "currency_code": "AZN" - }, - { - "country": "Bahamas", - "currency_code": "BSD" - }, - { - "country": "Bahrain", - "currency_code": "BHD" - }, - { - "country": "Bangladesh", - "currency_code": "BDT" - }, - { - "country": "Barbados", - "currency_code": "BBD" - }, - { - "country": "Belarus", - "currency_code": "BYR" - }, - { - "country": "Belgium", - "currency_code": "EUR" - }, - { - "country": "Belize", - "currency_code": "BZD" - }, - { - "country": "Benin", - "currency_code": "XOF" - }, - { - "country": "Bermuda", - "currency_code": "BMD" - }, - { - "country": "Bhutan", - "currency_code": "BTN" - }, - { - "country": "Bolivia", - "currency_code": "BOB" - }, - { - "country": "Bosnia and Herzegovina", - "currency_code": "BAM" - }, - { - "country": "Botswana", - "currency_code": "BWP" - }, - { - "country": "Bouvet Island", - "currency_code": "NOK" - }, - { - "country": "Brazil", - "currency_code": "BRL" - }, - { - "country": "British Indian Ocean Territory", - "currency_code": "USD" - }, - { - "country": "Brunei", - "currency_code": "BND" - }, - { - "country": "Bulgaria", - "currency_code": "BGN" - }, - { - "country": "Burkina Faso", - "currency_code": "XOF" - }, - { - "country": "Burundi", - "currency_code": "BIF" - }, - { - "country": "Cambodia", - "currency_code": "KHR" - }, - { - "country": "Cameroon", - "currency_code": "XAF" - }, - { - "country": "Canada", - "currency_code": "CAD" - }, - { - "country": "Cape Verde", - "currency_code": "CVE" - }, - { - "country": "Cayman Islands", - "currency_code": "KYD" - }, - { - "country": "Central African Republic", - "currency_code": "XAF" - }, - { - "country": "Chad", - "currency_code": "XAF" - }, - { - "country": "Chile", - "currency_code": "CLP" - }, - { - "country": "China", - "currency_code": "CNY" - }, - { - "country": "Christmas Island", - "currency_code": "AUD" - }, - { - "country": "Cocos (Keeling) Islands", - "currency_code": "AUD" - }, - { - "country": "Colombia", - "currency_code": "COP" - }, - { - "country": "Comoros", - "currency_code": "KMF" - }, - { - "country": "Congo", - "currency_code": "XAF" - }, - { - "country": "Cook Islands", - "currency_code": "NZD" - }, - { - "country": "Costa Rica", - "currency_code": "CRC" - }, - { - "country": "Croatia", - "currency_code": "HRK" - }, - { - "country": "Cuba", - "currency_code": "CUP" - }, - { - "country": "Cyprus", - "currency_code": "EUR" - }, - { - "country": "Czech Republic", - "currency_code": "CZK" - }, - { - "country": "Denmark", - "currency_code": "DKK" - }, - { - "country": "Djibouti", - "currency_code": "DJF" - }, - { - "country": "Dominica", - "currency_code": "XCD" - }, - { - "country": "Dominican Republic", - "currency_code": "DOP" - }, - { - "country": "East Timor", - "currency_code": "USD" - }, - { - "country": "Ecuador", - "currency_code": "ECS" - }, - { - "country": "Egypt", - "currency_code": "EGP" - }, - { - "country": "El Salvador", - "currency_code": "SVC" - }, - { - "country": "England", - "currency_code": "GBP" - }, - { - "country": "Equatorial Guinea", - "currency_code": "XAF" - }, - { - "country": "Eritrea", - "currency_code": "ERN" - }, - { - "country": "Estonia", - "currency_code": "EUR" - }, - { - "country": "Ethiopia", - "currency_code": "ETB" - }, - { - "country": "Falkland Islands", - "currency_code": "FKP" - }, - { - "country": "Faroe Islands", - "currency_code": "DKK" - }, - { - "country": "Fiji Islands", - "currency_code": "FJD" - }, - { - "country": "Finland", - "currency_code": "EUR" - }, - { - "country": "France", - "currency_code": "EUR" - }, - { - "country": "French Guiana", - "currency_code": "EUR" - }, - { - "country": "French Polynesia", - "currency_code": "XPF" - }, - { - "country": "French Southern territories", - "currency_code": "EUR" - }, - { - "country": "Gabon", - "currency_code": "XAF" - }, - { - "country": "Gambia", - "currency_code": "GMD" - }, - { - "country": "Georgia", - "currency_code": "GEL" - }, - { - "country": "Germany", - "currency_code": "EUR" - }, - { - "country": "Ghana", - "currency_code": "GHS" - }, - { - "country": "Gibraltar", - "currency_code": "GIP" - }, - { - "country": "Greece", - "currency_code": "EUR" - }, - { - "country": "Greenland", - "currency_code": "DKK" - }, - { - "country": "Grenada", - "currency_code": "XCD" - }, - { - "country": "Guadeloupe", - "currency_code": "EUR" - }, - { - "country": "Guam", - "currency_code": "USD" - }, - { - "country": "Guatemala", - "currency_code": "QTQ" - }, - { - "country": "Guinea", - "currency_code": "GNF" - }, - { - "country": "Guinea-Bissau", - "currency_code": "CFA" - }, - { - "country": "Guyana", - "currency_code": "GYD" - }, - { - "country": "Haiti", - "currency_code": "HTG" - }, - { - "country": "Heard Island and McDonald Islands", - "currency_code": "AUD" - }, - { - "country": "Holy See (Vatican City State)", - "currency_code": "EUR" - }, - { - "country": "Honduras", - "currency_code": "HNL" - }, - { - "country": "Hong Kong", - "currency_code": "HKD" - }, - { - "country": "Hungary", - "currency_code": "HUF" - }, - { - "country": "Iceland", - "currency_code": "ISK" - }, - { - "country": "India", - "currency_code": "INR" - }, - { - "country": "Indonesia", - "currency_code": "IDR" - }, - { - "country": "Iran", - "currency_code": "IRR" - }, - { - "country": "Iraq", - "currency_code": "IQD" - }, - { - "country": "Ireland", - "currency_code": "EUR" - }, - { - "country": "Israel", - "currency_code": "ILS" - }, - { - "country": "Italy", - "currency_code": "EUR" - }, - { - "country": "Ivory Coast", - "currency_code": "XOF" - }, - { - "country": "Jamaica", - "currency_code": "JMD" - }, - { - "country": "Japan", - "currency_code": "JPY" - }, - { - "country": "Jordan", - "currency_code": "JOD" - }, - { - "country": "Kazakhstan", - "currency_code": "KZT" - }, - { - "country": "Kenya", - "currency_code": "KES" - }, - { - "country": "Kiribati", - "currency_code": "AUD" - }, - { - "country": "Kuwait", - "currency_code": "KWD" - }, - { - "country": "Kyrgyzstan", - "currency_code": "KGS" - }, - { - "country": "Laos", - "currency_code": "LAK" - }, - { - "country": "Latvia", - "currency_code": "LVL" - }, - { - "country": "Lebanon", - "currency_code": "LBP" - }, - { - "country": "Lesotho", - "currency_code": "LSL" - }, - { - "country": "Liberia", - "currency_code": "LRD" - }, - { - "country": "Libyan Arab Jamahiriya", - "currency_code": "LYD" - }, - { - "country": "Liechtenstein", - "currency_code": "CHF" - }, - { - "country": "Lithuania", - "currency_code": "LTL" - }, - { - "country": "Luxembourg", - "currency_code": "EUR" - }, - { - "country": "Macao", - "currency_code": "MOP" - }, - { - "country": "North Macedonia", - "currency_code": "MKD" - }, - { - "country": "Madagascar", - "currency_code": "MGF" - }, - { - "country": "Malawi", - "currency_code": "MWK" - }, - { - "country": "Malaysia", - "currency_code": "MYR" - }, - { - "country": "Maldives", - "currency_code": "MVR" - }, - { - "country": "Mali", - "currency_code": "XOF" - }, - { - "country": "Malta", - "currency_code": "EUR" - }, - { - "country": "Marshall Islands", - "currency_code": "USD" - }, - { - "country": "Martinique", - "currency_code": "EUR" - }, - { - "country": "Mauritania", - "currency_code": "MRO" - }, - { - "country": "Mauritius", - "currency_code": "MUR" - }, - { - "country": "Mayotte", - "currency_code": "EUR" - }, - { - "country": "Mexico", - "currency_code": "MXN" - }, - { - "country": "Micronesia, Federated States of", - "currency_code": "USD" - }, - { - "country": "Moldova", - "currency_code": "MDL" - }, - { - "country": "Monaco", - "currency_code": "EUR" - }, - { - "country": "Mongolia", - "currency_code": "MNT" - }, - { - "country": "Montserrat", - "currency_code": "XCD" - }, - { - "country": "Morocco", - "currency_code": "MAD" - }, - { - "country": "Mozambique", - "currency_code": "MZN" - }, - { - "country": "Myanmar", - "currency_code": "MMR" - }, - { - "country": "Namibia", - "currency_code": "NAD" - }, - { - "country": "Nauru", - "currency_code": "AUD" - }, - { - "country": "Nepal", - "currency_code": "NPR" - }, - { - "country": "Netherlands", - "currency_code": "EUR" - }, - { - "country": "Netherlands Antilles", - "currency_code": "ANG" - }, - { - "country": "New Caledonia", - "currency_code": "XPF" - }, - { - "country": "New Zealand", - "currency_code": "NZD" - }, - { - "country": "Nicaragua", - "currency_code": "NIO" - }, - { - "country": "Niger", - "currency_code": "XOF" - }, - { - "country": "Nigeria", - "currency_code": "NGN" - }, - { - "country": "Niue", - "currency_code": "NZD" - }, - { - "country": "Norfolk Island", - "currency_code": "AUD" - }, - { - "country": "North Korea", - "currency_code": "KPW" - }, - { - "country": "Northern Ireland", - "currency_code": "GBP" - }, - { - "country": "Northern Mariana Islands", - "currency_code": "USD" - }, - { - "country": "Norway", - "currency_code": "NOK" - }, - { - "country": "Oman", - "currency_code": "OMR" - }, - { - "country": "Pakistan", - "currency_code": "PKR" - }, - { - "country": "Palau", - "currency_code": "USD" - }, - { - "country": "Palestine", - "currency_code": null - }, - { - "country": "Panama", - "currency_code": "PAB" - }, - { - "country": "Papua New Guinea", - "currency_code": "PGK" - }, - { - "country": "Paraguay", - "currency_code": "PYG" - }, - { - "country": "Peru", - "currency_code": "PEN" - }, - { - "country": "Philippines", - "currency_code": "PHP" - }, - { - "country": "Pitcairn", - "currency_code": "NZD" - }, - { - "country": "Poland", - "currency_code": "PLN" - }, - { - "country": "Portugal", - "currency_code": "EUR" - }, - { - "country": "Puerto Rico", - "currency_code": "USD" - }, - { - "country": "Qatar", - "currency_code": "QAR" - }, - { - "country": "Reunion", - "currency_code": "EUR" - }, - { - "country": "Romania", - "currency_code": "RON" - }, - { - "country": "Russian Federation", - "currency_code": "RUB" - }, - { - "country": "Rwanda", - "currency_code": "RWF" - }, - { - "country": "Saint Helena", - "currency_code": "SHP" - }, - { - "country": "Saint Kitts and Nevis", - "currency_code": "XCD" - }, - { - "country": "Saint Lucia", - "currency_code": "XCD" - }, - { - "country": "Saint Pierre and Miquelon", - "currency_code": "EUR" - }, - { - "country": "Saint Vincent and the Grenadines", - "currency_code": "XCD" - }, - { - "country": "Samoa", - "currency_code": "WST" - }, - { - "country": "San Marino", - "currency_code": "EUR" - }, - { - "country": "Sao Tome and Principe", - "currency_code": "STD" - }, - { - "country": "Saudi Arabia", - "currency_code": "SAR" - }, - { - "country": "Scotland", - "currency_code": "GBP" - }, - { - "country": "Senegal", - "currency_code": "XOF" - }, - { - "country": "Seychelles", - "currency_code": "SCR" - }, - { - "country": "Sierra Leone", - "currency_code": "SLL" - }, - { - "country": "Singapore", - "currency_code": "SGD" - }, - { - "country": "Slovakia", - "currency_code": "EUR" - }, - { - "country": "Slovenia", - "currency_code": "EUR" - }, - { - "country": "Solomon Islands", - "currency_code": "SBD" - }, - { - "country": "Somalia", - "currency_code": "SOS" - }, - { - "country": "South Africa", - "currency_code": "ZAR" - }, + {"country": "Afghanistan", "currency_code": "AFN"}, + {"country": "Albania", "currency_code": "ALL"}, + {"country": "Algeria", "currency_code": "DZD"}, + {"country": "American Samoa", "currency_code": "USD"}, + {"country": "Andorra", "currency_code": "EUR"}, + {"country": "Angola", "currency_code": "AOA"}, + {"country": "Anguilla", "currency_code": "XCD"}, + {"country": "Antarctica", "currency_code": "XCD"}, + {"country": "Antigua and Barbuda", "currency_code": "XCD"}, + {"country": "Argentina", "currency_code": "ARS"}, + {"country": "Armenia", "currency_code": "AMD"}, + {"country": "Aruba", "currency_code": "AWG"}, + {"country": "Australia", "currency_code": "AUD"}, + {"country": "Austria", "currency_code": "EUR"}, + {"country": "Azerbaijan", "currency_code": "AZN"}, + {"country": "Bahamas", "currency_code": "BSD"}, + {"country": "Bahrain", "currency_code": "BHD"}, + {"country": "Bangladesh", "currency_code": "BDT"}, + {"country": "Barbados", "currency_code": "BBD"}, + {"country": "Belarus", "currency_code": "BYR"}, + {"country": "Belgium", "currency_code": "EUR"}, + {"country": "Belize", "currency_code": "BZD"}, + {"country": "Benin", "currency_code": "XOF"}, + {"country": "Bermuda", "currency_code": "BMD"}, + {"country": "Bhutan", "currency_code": "BTN"}, + {"country": "Bolivia", "currency_code": "BOB"}, + {"country": "Bosnia and Herzegovina", "currency_code": "BAM"}, + {"country": "Botswana", "currency_code": "BWP"}, + {"country": "Bouvet Island", "currency_code": "NOK"}, + {"country": "Brazil", "currency_code": "BRL"}, + {"country": "British Indian Ocean Territory", "currency_code": "USD"}, + {"country": "Brunei", "currency_code": "BND"}, + {"country": "Bulgaria", "currency_code": "BGN"}, + {"country": "Burkina Faso", "currency_code": "XOF"}, + {"country": "Burundi", "currency_code": "BIF"}, + {"country": "Cambodia", "currency_code": "KHR"}, + {"country": "Cameroon", "currency_code": "XAF"}, + {"country": "Canada", "currency_code": "CAD"}, + {"country": "Cape Verde", "currency_code": "CVE"}, + {"country": "Cayman Islands", "currency_code": "KYD"}, + {"country": "Central African Republic", "currency_code": "XAF"}, + {"country": "Chad", "currency_code": "XAF"}, + {"country": "Chile", "currency_code": "CLP"}, + {"country": "China", "currency_code": "CNY"}, + {"country": "Christmas Island", "currency_code": "AUD"}, + {"country": "Cocos (Keeling) Islands", "currency_code": "AUD"}, + {"country": "Colombia", "currency_code": "COP"}, + {"country": "Comoros", "currency_code": "KMF"}, + {"country": "Congo", "currency_code": "XAF"}, + {"country": "Cook Islands", "currency_code": "NZD"}, + {"country": "Costa Rica", "currency_code": "CRC"}, + {"country": "Croatia", "currency_code": "HRK"}, + {"country": "Cuba", "currency_code": "CUP"}, + {"country": "Cyprus", "currency_code": "EUR"}, + {"country": "Czech Republic", "currency_code": "CZK"}, + {"country": "Denmark", "currency_code": "DKK"}, + {"country": "Djibouti", "currency_code": "DJF"}, + {"country": "Dominica", "currency_code": "XCD"}, + {"country": "Dominican Republic", "currency_code": "DOP"}, + {"country": "East Timor", "currency_code": "USD"}, + {"country": "Ecuador", "currency_code": "ECS"}, + {"country": "Egypt", "currency_code": "EGP"}, + {"country": "El Salvador", "currency_code": "SVC"}, + {"country": "England", "currency_code": "GBP"}, + {"country": "Equatorial Guinea", "currency_code": "XAF"}, + {"country": "Eritrea", "currency_code": "ERN"}, + {"country": "Estonia", "currency_code": "EUR"}, + {"country": "Ethiopia", "currency_code": "ETB"}, + {"country": "Falkland Islands", "currency_code": "FKP"}, + {"country": "Faroe Islands", "currency_code": "DKK"}, + {"country": "Fiji Islands", "currency_code": "FJD"}, + {"country": "Finland", "currency_code": "EUR"}, + {"country": "France", "currency_code": "EUR"}, + {"country": "French Guiana", "currency_code": "EUR"}, + {"country": "French Polynesia", "currency_code": "XPF"}, + {"country": "French Southern territories", "currency_code": "EUR"}, + {"country": "Gabon", "currency_code": "XAF"}, + {"country": "Gambia", "currency_code": "GMD"}, + {"country": "Georgia", "currency_code": "GEL"}, + {"country": "Germany", "currency_code": "EUR"}, + {"country": "Ghana", "currency_code": "GHS"}, + {"country": "Gibraltar", "currency_code": "GIP"}, + {"country": "Greece", "currency_code": "EUR"}, + {"country": "Greenland", "currency_code": "DKK"}, + {"country": "Grenada", "currency_code": "XCD"}, + {"country": "Guadeloupe", "currency_code": "EUR"}, + {"country": "Guam", "currency_code": "USD"}, + {"country": "Guatemala", "currency_code": "QTQ"}, + {"country": "Guinea", "currency_code": "GNF"}, + {"country": "Guinea-Bissau", "currency_code": "CFA"}, + {"country": "Guyana", "currency_code": "GYD"}, + {"country": "Haiti", "currency_code": "HTG"}, + {"country": "Heard Island and McDonald Islands", "currency_code": "AUD"}, + {"country": "Holy See (Vatican City State)", "currency_code": "EUR"}, + {"country": "Honduras", "currency_code": "HNL"}, + {"country": "Hong Kong", "currency_code": "HKD"}, + {"country": "Hungary", "currency_code": "HUF"}, + {"country": "Iceland", "currency_code": "ISK"}, + {"country": "India", "currency_code": "INR"}, + {"country": "Indonesia", "currency_code": "IDR"}, + {"country": "Iran", "currency_code": "IRR"}, + {"country": "Iraq", "currency_code": "IQD"}, + {"country": "Ireland", "currency_code": "EUR"}, + {"country": "Israel", "currency_code": "ILS"}, + {"country": "Italy", "currency_code": "EUR"}, + {"country": "Ivory Coast", "currency_code": "XOF"}, + {"country": "Jamaica", "currency_code": "JMD"}, + {"country": "Japan", "currency_code": "JPY"}, + {"country": "Jordan", "currency_code": "JOD"}, + {"country": "Kazakhstan", "currency_code": "KZT"}, + {"country": "Kenya", "currency_code": "KES"}, + {"country": "Kiribati", "currency_code": "AUD"}, + {"country": "Kuwait", "currency_code": "KWD"}, + {"country": "Kyrgyzstan", "currency_code": "KGS"}, + {"country": "Laos", "currency_code": "LAK"}, + {"country": "Latvia", "currency_code": "LVL"}, + {"country": "Lebanon", "currency_code": "LBP"}, + {"country": "Lesotho", "currency_code": "LSL"}, + {"country": "Liberia", "currency_code": "LRD"}, + {"country": "Libyan Arab Jamahiriya", "currency_code": "LYD"}, + {"country": "Liechtenstein", "currency_code": "CHF"}, + {"country": "Lithuania", "currency_code": "LTL"}, + {"country": "Luxembourg", "currency_code": "EUR"}, + {"country": "Macao", "currency_code": "MOP"}, + {"country": "North Macedonia", "currency_code": "MKD"}, + {"country": "Madagascar", "currency_code": "MGF"}, + {"country": "Malawi", "currency_code": "MWK"}, + {"country": "Malaysia", "currency_code": "MYR"}, + {"country": "Maldives", "currency_code": "MVR"}, + {"country": "Mali", "currency_code": "XOF"}, + {"country": "Malta", "currency_code": "EUR"}, + {"country": "Marshall Islands", "currency_code": "USD"}, + {"country": "Martinique", "currency_code": "EUR"}, + {"country": "Mauritania", "currency_code": "MRO"}, + {"country": "Mauritius", "currency_code": "MUR"}, + {"country": "Mayotte", "currency_code": "EUR"}, + {"country": "Mexico", "currency_code": "MXN"}, + {"country": "Micronesia, Federated States of", "currency_code": "USD"}, + {"country": "Moldova", "currency_code": "MDL"}, + {"country": "Monaco", "currency_code": "EUR"}, + {"country": "Mongolia", "currency_code": "MNT"}, + {"country": "Montserrat", "currency_code": "XCD"}, + {"country": "Morocco", "currency_code": "MAD"}, + {"country": "Mozambique", "currency_code": "MZN"}, + {"country": "Myanmar", "currency_code": "MMR"}, + {"country": "Namibia", "currency_code": "NAD"}, + {"country": "Nauru", "currency_code": "AUD"}, + {"country": "Nepal", "currency_code": "NPR"}, + {"country": "Netherlands", "currency_code": "EUR"}, + {"country": "Netherlands Antilles", "currency_code": "ANG"}, + {"country": "New Caledonia", "currency_code": "XPF"}, + {"country": "New Zealand", "currency_code": "NZD"}, + {"country": "Nicaragua", "currency_code": "NIO"}, + {"country": "Niger", "currency_code": "XOF"}, + {"country": "Nigeria", "currency_code": "NGN"}, + {"country": "Niue", "currency_code": "NZD"}, + {"country": "Norfolk Island", "currency_code": "AUD"}, + {"country": "North Korea", "currency_code": "KPW"}, + {"country": "Northern Ireland", "currency_code": "GBP"}, + {"country": "Northern Mariana Islands", "currency_code": "USD"}, + {"country": "Norway", "currency_code": "NOK"}, + {"country": "Oman", "currency_code": "OMR"}, + {"country": "Pakistan", "currency_code": "PKR"}, + {"country": "Palau", "currency_code": "USD"}, + {"country": "Palestine", "currency_code": null}, + {"country": "Panama", "currency_code": "PAB"}, + {"country": "Papua New Guinea", "currency_code": "PGK"}, + {"country": "Paraguay", "currency_code": "PYG"}, + {"country": "Peru", "currency_code": "PEN"}, + {"country": "Philippines", "currency_code": "PHP"}, + {"country": "Pitcairn", "currency_code": "NZD"}, + {"country": "Poland", "currency_code": "PLN"}, + {"country": "Portugal", "currency_code": "EUR"}, + {"country": "Puerto Rico", "currency_code": "USD"}, + {"country": "Qatar", "currency_code": "QAR"}, + {"country": "Reunion", "currency_code": "EUR"}, + {"country": "Romania", "currency_code": "RON"}, + {"country": "Russian Federation", "currency_code": "RUB"}, + {"country": "Rwanda", "currency_code": "RWF"}, + {"country": "Saint Helena", "currency_code": "SHP"}, + {"country": "Saint Kitts and Nevis", "currency_code": "XCD"}, + {"country": "Saint Lucia", "currency_code": "XCD"}, + {"country": "Saint Pierre and Miquelon", "currency_code": "EUR"}, + {"country": "Saint Vincent and the Grenadines", "currency_code": "XCD"}, + {"country": "Samoa", "currency_code": "WST"}, + {"country": "San Marino", "currency_code": "EUR"}, + {"country": "Sao Tome and Principe", "currency_code": "STD"}, + {"country": "Saudi Arabia", "currency_code": "SAR"}, + {"country": "Scotland", "currency_code": "GBP"}, + {"country": "Senegal", "currency_code": "XOF"}, + {"country": "Seychelles", "currency_code": "SCR"}, + {"country": "Sierra Leone", "currency_code": "SLL"}, + {"country": "Singapore", "currency_code": "SGD"}, + {"country": "Slovakia", "currency_code": "EUR"}, + {"country": "Slovenia", "currency_code": "EUR"}, + {"country": "Solomon Islands", "currency_code": "SBD"}, + {"country": "Somalia", "currency_code": "SOS"}, + {"country": "South Africa", "currency_code": "ZAR"}, { "country": "South Georgia and the South Sandwich Islands", - "currency_code": "GBP" + "currency_code": "GBP", }, - { - "country": "South Korea", - "currency_code": "KRW" - }, - { - "country": "South Sudan", - "currency_code": "SSP" - }, - { - "country": "Spain", - "currency_code": "EUR" - }, - { - "country": "SriLanka", - "currency_code": "LKR" - }, - { - "country": "Sudan", - "currency_code": "SDG" - }, - { - "country": "Suriname", - "currency_code": "SRD" - }, - { - "country": "Svalbard and Jan Mayen", - "currency_code": "NOK" - }, - { - "country": "Swaziland", - "currency_code": "SZL" - }, - { - "country": "Sweden", - "currency_code": "SEK" - }, - { - "country": "Switzerland", - "currency_code": "CHF" - }, - { - "country": "Syria", - "currency_code": "SYP" - }, - { - "country": "Tajikistan", - "currency_code": "TJS" - }, - { - "country": "Tanzania", - "currency_code": "TZS" - }, - { - "country": "Thailand", - "currency_code": "THB" - }, - { - "country": "The Democratic Republic of Congo", - "currency_code": "CDF" - }, - { - "country": "Togo", - "currency_code": "XOF" - }, - { - "country": "Tokelau", - "currency_code": "NZD" - }, - { - "country": "Tonga", - "currency_code": "TOP" - }, - { - "country": "Trinidad and Tobago", - "currency_code": "TTD" - }, - { - "country": "Tunisia", - "currency_code": "TND" - }, - { - "country": "Turkey", - "currency_code": "TRY" - }, - { - "country": "Turkmenistan", - "currency_code": "TMT" - }, - { - "country": "Turks and Caicos Islands", - "currency_code": "USD" - }, - { - "country": "Tuvalu", - "currency_code": "AUD" - }, - { - "country": "Uganda", - "currency_code": "UGX" - }, - { - "country": "Ukraine", - "currency_code": "UAH" - }, - { - "country": "United Arab Emirates", - "currency_code": "AED" - }, - { - "country": "United Kingdom", - "currency_code": "GBP" - }, - { - "country": "United States", - "currency_code": "USD" - }, - { - "country": "United States Minor Outlying Islands", - "currency_code": "USD" - }, - { - "country": "Uruguay", - "currency_code": "UYU" - }, - { - "country": "Uzbekistan", - "currency_code": "UZS" - }, - { - "country": "Vanuatu", - "currency_code": "VUV" - }, - { - "country": "Venezuela", - "currency_code": "VEF" - }, - { - "country": "Vietnam", - "currency_code": "VND" - }, - { - "country": "Virgin Islands, British", - "currency_code": "USD" - }, - { - "country": "Virgin Islands, U.S.", - "currency_code": "USD" - }, - { - "country": "Wales", - "currency_code": "GBP" - }, - { - "country": "Wallis and Futuna", - "currency_code": "XPF" - }, - { - "country": "Western Sahara", - "currency_code": "MAD" - }, - { - "country": "Yemen", - "currency_code": "YER" - }, - { - "country": "Yugoslavia", - "currency_code": null - }, - { - "country": "Zambia", - "currency_code": "ZMW" - }, - { - "country": "Zimbabwe", - "currency_code": "ZWD" - } + {"country": "South Korea", "currency_code": "KRW"}, + {"country": "South Sudan", "currency_code": "SSP"}, + {"country": "Spain", "currency_code": "EUR"}, + {"country": "SriLanka", "currency_code": "LKR"}, + {"country": "Sudan", "currency_code": "SDG"}, + {"country": "Suriname", "currency_code": "SRD"}, + {"country": "Svalbard and Jan Mayen", "currency_code": "NOK"}, + {"country": "Swaziland", "currency_code": "SZL"}, + {"country": "Sweden", "currency_code": "SEK"}, + {"country": "Switzerland", "currency_code": "CHF"}, + {"country": "Syria", "currency_code": "SYP"}, + {"country": "Tajikistan", "currency_code": "TJS"}, + {"country": "Tanzania", "currency_code": "TZS"}, + {"country": "Thailand", "currency_code": "THB"}, + {"country": "The Democratic Republic of Congo", "currency_code": "CDF"}, + {"country": "Togo", "currency_code": "XOF"}, + {"country": "Tokelau", "currency_code": "NZD"}, + {"country": "Tonga", "currency_code": "TOP"}, + {"country": "Trinidad and Tobago", "currency_code": "TTD"}, + {"country": "Tunisia", "currency_code": "TND"}, + {"country": "Turkey", "currency_code": "TRY"}, + {"country": "Turkmenistan", "currency_code": "TMT"}, + {"country": "Turks and Caicos Islands", "currency_code": "USD"}, + {"country": "Tuvalu", "currency_code": "AUD"}, + {"country": "Uganda", "currency_code": "UGX"}, + {"country": "Ukraine", "currency_code": "UAH"}, + {"country": "United Arab Emirates", "currency_code": "AED"}, + {"country": "United Kingdom", "currency_code": "GBP"}, + {"country": "United States", "currency_code": "USD"}, + {"country": "United States Minor Outlying Islands", "currency_code": "USD"}, + {"country": "Uruguay", "currency_code": "UYU"}, + {"country": "Uzbekistan", "currency_code": "UZS"}, + {"country": "Vanuatu", "currency_code": "VUV"}, + {"country": "Venezuela", "currency_code": "VEF"}, + {"country": "Vietnam", "currency_code": "VND"}, + {"country": "Virgin Islands, British", "currency_code": "USD"}, + {"country": "Virgin Islands, U.S.", "currency_code": "USD"}, + {"country": "Wales", "currency_code": "GBP"}, + {"country": "Wallis and Futuna", "currency_code": "XPF"}, + {"country": "Western Sahara", "currency_code": "MAD"}, + {"country": "Yemen", "currency_code": "YER"}, + {"country": "Yugoslavia", "currency_code": null}, + {"country": "Zambia", "currency_code": "ZMW"}, + {"country": "Zimbabwe", "currency_code": "ZWD"}, ] + class Module(core.module.Module): @core.decorators.every(minutes=5) def __init__(self, config, theme): @@ -1023,15 +298,15 @@ class Module(core.module.Module): self.__data = [] - src = self.parameter('source', DEFAULT_SRC) - if src == 'auto': + src = self.parameter("source", DEFAULT_SRC) + if src == "auto": self.__base = self.find_local_currency() else: self.__base = src self.__symbols = [] - for d in util.format.aslist(self.parameter('destination', DEFAULT_DEST)): - if d == 'auto': + for d in util.format.aslist(self.parameter("destination", DEFAULT_DEST)): + if d == "auto": new = self.find_local_currency() else: new = d @@ -1040,24 +315,26 @@ class Module(core.module.Module): def price(self, widget): if len(self.__data) == 0: - return '?' + return "?" rates = [] for sym, rate in self.__data: - rate_float = float(rate.replace(',','')) + rate_float = float(rate.replace(",", "")) if format_currency: rates.append(format_currency(rate_float, sym)) else: rate = self.fmt_rate(rate) - rates.append(u'{}{}'.format(rate, SYMBOL[sym] if sym in SYMBOL else sym)) + rates.append("{}{}".format(rate, SYMBOL[sym] if sym in SYMBOL else sym)) - basefmt = u'{}'.format(self.parameter('sourceformat', '{}={}')) - ratefmt = u'{}'.format(self.parameter('destinationdelimiter', '=')) + basefmt = "{}".format(self.parameter("sourceformat", "{}={}")) + ratefmt = "{}".format(self.parameter("destinationdelimiter", "=")) if format_currency: base_val = format_currency(1, self.__base) else: - base_val = '1{}'.format(SYMBOL[self.__base] if self.__base in SYMBOL else self.__base) + base_val = "1{}".format( + SYMBOL[self.__base] if self.__base in SYMBOL else self.__base + ) return basefmt.format(base_val, ratefmt.join(rates)) @@ -1067,7 +344,7 @@ class Module(core.module.Module): url = API_URL.format(self.__base, symbol) try: response = requests.get(url).json() - self.__data.append((symbol, response['data']['exchangeRate'])) + self.__data.append((symbol, response["data"]["exchangeRate"])) except Exception: pass @@ -1081,12 +358,13 @@ class Module(core.module.Module): return DEFAULT_SRC def fmt_rate(self, rate): - float_rate = float(rate.replace(',', '')) + float_rate = float(rate.replace(",", "")) if not 0.01 < float_rate < 100: ret = rate else: - ret = '%.3g' % float_rate + ret = "%.3g" % float_rate return ret + # vim: tabstop=8 expandtab shiftwidth=4 softtabstop=4 diff --git a/modules/contrib/datetimetz.py b/modules/contrib/datetimetz.py index 3efb7b0..fc58b24 100644 --- a/modules/contrib/datetimetz.py +++ b/modules/contrib/datetimetz.py @@ -27,71 +27,82 @@ import core.input import util.format + def default_format(module): - default = '%x %X %Z' - if module == 'datetz': - default = '%x %Z' - if module == 'timetz': - default = '%X %Z' + default = "%x %X %Z" + if module == "datetz": + default = "%x %Z" + if module == "timetz": + default = "%X %Z" return default + class Module(core.module.Module): def __init__(self, config, theme): super().__init__(config, theme, core.widget.Widget(self.get_time)) core.input.register(self, button=core.input.LEFT_MOUSE, cmd=self.next_tz) core.input.register(self, button=core.input.RIGHT_MOUSE, cmd=self.prev_tz) - self.__fmt = self.parameter('format', self.default_format()) + self.__fmt = self.parameter("format", self.default_format()) - default_timezone = '' + default_timezone = "" try: default_timezone = tzlocal.get_localzone().zone except Exception as e: - logging.error('unable to get default timezone: {}'.format(str(e))) + logging.error("unable to get default timezone: {}".format(str(e))) try: - self._timezones = util.format.aslist(self.parameter('timezone', default_timezone)) + self._timezones = util.format.aslist( + self.parameter("timezone", default_timezone) + ) except: self._timezones = [default_timezone] self._current_tz = 0 l = locale.getdefaultlocale() if not l or l == (None, None): - l = ('en_US', 'UTF-8') - lcl = self.parameter('locale', '.'.join(l)) + l = ("en_US", "UTF-8") + lcl = self.parameter("locale", ".".join(l)) try: - locale.setlocale(locale.LC_TIME, lcl.split('.')) + locale.setlocale(locale.LC_TIME, lcl.split(".")) except Exception: - locale.setlocale(locale.LC_TIME, ('en_US', 'UTF-8')) + locale.setlocale(locale.LC_TIME, ("en_US", "UTF-8")) def default_format(self): - return '%x %X %Z' + return "%x %X %Z" def get_time(self, widget): try: try: tz = pytz.timezone(self._timezones[self._current_tz].strip()) - retval = datetime.datetime.now(tz=tzlocal.get_localzone()).astimezone(tz).strftime(self.__fmt) + retval = ( + datetime.datetime.now(tz=tzlocal.get_localzone()) + .astimezone(tz) + .strftime(self.__fmt) + ) except pytz.exceptions.UnknownTimeZoneError: - retval = '[Unknown timezone: {}]'.format(self._timezones[self._current_tz].strip()) + retval = "[Unknown timezone: {}]".format( + self._timezones[self._current_tz].strip() + ) except Exception as e: - logging.error('unable to get time: {}'.format(str(e))) - retval = '[n/a]' + logging.error("unable to get time: {}".format(str(e))) + retval = "[n/a]" enc = locale.getpreferredencoding() - if hasattr(retval, 'decode'): + if hasattr(retval, "decode"): return retval.decode(enc) return retval def next_tz(self, event): next_timezone = self._current_tz + 1 if next_timezone >= len(self._timezones): - next_timezone = 0 # wraparound + next_timezone = 0 # wraparound self._current_tz = next_timezone def prev_tz(self, event): previous_timezone = self._current_tz - 1 if previous_timezone < 0: - previous_timezone = 0 # wraparound + previous_timezone = 0 # wraparound self._current_tz = previous_timezone + # vim: tabstop=8 expandtab shiftwidth=4 softtabstop=4 diff --git a/modules/contrib/datetz.py b/modules/contrib/datetz.py index e2b727f..71f8193 100644 --- a/modules/contrib/datetz.py +++ b/modules/contrib/datetz.py @@ -10,12 +10,14 @@ Parameters: import core.decorators from .datetimetz import Module + class Module(Module): @core.decorators.every(hours=1) def __init__(self, config, theme): super().__init__(config, theme) def default_format(self): - return '%x %Z' + return "%x %Z" + # vim: tabstop=8 expandtab shiftwidth=4 softtabstop=4 diff --git a/modules/contrib/deadbeef.py b/modules/contrib/deadbeef.py index 7c79297..e2261fb 100644 --- a/modules/contrib/deadbeef.py +++ b/modules/contrib/deadbeef.py @@ -45,66 +45,71 @@ import core.decorators import util.cli import util.format + class Module(core.module.Module): def __init__(self, config, theme): super().__init__(config, theme, core.widget.Widget(self.deadbeef)) - buttons = {'LEFT_CLICK': core.input.LEFT_MOUSE, - 'RIGHT_CLICK': core.input.RIGHT_MOUSE, - 'MIDDLE_CLICK': core.input.MIDDLE_MOUSE, - 'SCROLL_UP': core.input.WHEEL_UP, - 'SCROLL_DOWN': core.input.WHEEL_DOWN, - } - - self._song = '' - self._format = self.parameter('format', '{artist} - {title}') - self._tf_format = self.parameter('tf_format', '') - self._show_tf_when_stopped = util.format.asbool(self.parameter('tf_format_if_stopped', False)) - prev_button = self.parameter('previous', 'LEFT_CLICK') - next_button = self.parameter('next', 'RIGHT_CLICK') - pause_button = self.parameter('pause', 'MIDDLE_CLICK') + buttons = { + "LEFT_CLICK": core.input.LEFT_MOUSE, + "RIGHT_CLICK": core.input.RIGHT_MOUSE, + "MIDDLE_CLICK": core.input.MIDDLE_MOUSE, + "SCROLL_UP": core.input.WHEEL_UP, + "SCROLL_DOWN": core.input.WHEEL_DOWN, + } - self.now_playing = 'deadbeef --nowplaying %a;%t;%b;%l;%n;%y;%c;%r;%e' - self.now_playing_tf = 'deadbeef --nowplaying-tf ' - cmd = 'deadbeef ' + self._song = "" + self._format = self.parameter("format", "{artist} - {title}") + self._tf_format = self.parameter("tf_format", "") + self._show_tf_when_stopped = util.format.asbool( + self.parameter("tf_format_if_stopped", False) + ) + prev_button = self.parameter("previous", "LEFT_CLICK") + next_button = self.parameter("next", "RIGHT_CLICK") + pause_button = self.parameter("pause", "MIDDLE_CLICK") - core.input.register(self, button=buttons[prev_button], - cmd=cmd + '--prev') - core.input.register(self, button=buttons[next_button], - cmd=cmd + '--next') - core.input.register(self, button=buttons[pause_button], - cmd=cmd + '--play-pause') + self.now_playing = "deadbeef --nowplaying %a;%t;%b;%l;%n;%y;%c;%r;%e" + self.now_playing_tf = "deadbeef --nowplaying-tf " + cmd = "deadbeef " + + core.input.register(self, button=buttons[prev_button], cmd=cmd + "--prev") + core.input.register(self, button=buttons[next_button], cmd=cmd + "--next") + core.input.register( + self, button=buttons[pause_button], cmd=cmd + "--play-pause" + ) # modify the tf_format if we don't want it to show on stop # this adds conditions to the query itself, rather than # polling to see if deadbeef is running # doing this reduces the number of calls we have to make if self._tf_format and not self._show_tf_when_stopped: - self._tf_format = '$if($or(%isplaying%,%ispaused%),{query})'.format(query=self._tf_format) + self._tf_format = "$if($or(%isplaying%,%ispaused%),{query})".format( + query=self._tf_format + ) @core.decorators.scrollable def deadbeef(self, widget): return self.string_song def hidden(self): - return self.string_song == '' + return self.string_song == "" def update(self): widgets = self.widgets() try: - if self._tf_format == '': # no tf format set, use the old style + if self._tf_format == "": # no tf format set, use the old style return self.update_standard(widgets) return self.update_tf(widgets) except Exception as e: logging.exception(e) - self._song = 'error' + self._song = "error" def update_tf(self, widgets): ## ensure that deadbeef is actually running ## easiest way to do this is to check --nowplaying for ## the string 'nothing' - if util.cli.execute(self.now_playing) == 'nothing': - self._song = '' + if util.cli.execute(self.now_playing) == "nothing": + self._song = "" return ## perform the actual query -- these can be much more sophisticated data = util.cli.execute(self.now_playing_tf + self._tf_format) @@ -112,19 +117,21 @@ class Module(core.module.Module): def update_standard(self, widgets): data = util.cli.execute(self.now_playing) - if data == 'nothing': - self._song = '' + if data == "nothing": + self._song = "" else: - data = data.split(';') - self._song = self._format.format(artist=data[0], - title=data[1], - album=data[2], - length=data[3], - trackno=data[4], - year=data[5], - comment=data[6], - copyright=data[7], - time=data[8]) + data = data.split(";") + self._song = self._format.format( + artist=data[0], + title=data[1], + album=data[2], + length=data[3], + trackno=data[4], + year=data[5], + comment=data[6], + copyright=data[7], + time=data[8], + ) @property def string_song(self): @@ -136,4 +143,5 @@ Returns the current song as a string, either as a unicode() (Python < return unicode(self._song) return str(self._song) + # vim: tabstop=8 expandtab shiftwidth=4 softtabstop=4 diff --git a/modules/contrib/deezer.py b/modules/contrib/deezer.py index 3843e70..779d492 100644 --- a/modules/contrib/deezer.py +++ b/modules/contrib/deezer.py @@ -19,51 +19,61 @@ import core.module import core.widget import core.input + class Module(core.module.Module): def __init__(self, config, theme): super().__init__(config, theme, core.widget.Widget(self.deezer)) - buttons = {'LEFT_CLICK':core.input.LEFT_MOUSE, - 'RIGHT_CLICK':core.input.RIGHT_MOUSE, - 'MIDDLE_CLICK':core.input.MIDDLE_MOUSE, - 'SCROLL_UP':core.input.WHEEL_UP, - 'SCROLL_DOWN':core.input.WHEEL_DOWN, - } - - self._song = '' - self._format = self.parameter('format', '{artist} - {title}') - prev_button = self.parameter('previous', 'LEFT_CLICK') - next_button = self.parameter('next', 'RIGHT_CLICK') - pause_button = self.parameter('pause', 'MIDDLE_CLICK') + buttons = { + "LEFT_CLICK": core.input.LEFT_MOUSE, + "RIGHT_CLICK": core.input.RIGHT_MOUSE, + "MIDDLE_CLICK": core.input.MIDDLE_MOUSE, + "SCROLL_UP": core.input.WHEEL_UP, + "SCROLL_DOWN": core.input.WHEEL_DOWN, + } - cmd = 'dbus-send --session --type=method_call --dest=org.mpris.MediaPlayer2.deezer \ - /org/mpris/MediaPlayer2 org.mpris.MediaPlayer2.Player.' - core.input.register(self, button=buttons[prev_button], - cmd=cmd + 'Previous') - core.input.register(self, button=buttons[next_button], - cmd=cmd + 'Next') - core.input.register(self, button=buttons[pause_button], - cmd=cmd + 'PlayPause') + self._song = "" + self._format = self.parameter("format", "{artist} - {title}") + prev_button = self.parameter("previous", "LEFT_CLICK") + next_button = self.parameter("next", "RIGHT_CLICK") + pause_button = self.parameter("pause", "MIDDLE_CLICK") + + cmd = "dbus-send --session --type=method_call --dest=org.mpris.MediaPlayer2.deezer \ + /org/mpris/MediaPlayer2 org.mpris.MediaPlayer2.Player." + core.input.register(self, button=buttons[prev_button], cmd=cmd + "Previous") + core.input.register(self, button=buttons[next_button], cmd=cmd + "Next") + core.input.register(self, button=buttons[pause_button], cmd=cmd + "PlayPause") def deezer(self, widget): return str(self._song) def hidden(self): - return str(self._song) == '' + return str(self._song) == "" def update(self): try: bus = dbus.SessionBus() - deezer = bus.get_object('org.mpris.MediaPlayer2.deezer', '/org/mpris/MediaPlayer2') - deezer_iface = dbus.Interface(deezer, 'org.freedesktop.DBus.Properties') - props = deezer_iface.Get('org.mpris.MediaPlayer2.Player', 'Metadata') - playback_status = str(deezer_iface.Get('org.mpris.MediaPlayer2.Player', 'PlaybackStatus')) - self._song = self._format.format(album=str(props.get('xesam:album')), - title=str(props.get('xesam:title')), - artist=','.join(props.get('xesam:artist')), - trackNumber=str(props.get('xesam:trackNumber')), - playbackStatus=u'\u25B6' if playback_status=='Playing' else u'\u258D\u258D' if playback_status=='Paused' else '',) + deezer = bus.get_object( + "org.mpris.MediaPlayer2.deezer", "/org/mpris/MediaPlayer2" + ) + deezer_iface = dbus.Interface(deezer, "org.freedesktop.DBus.Properties") + props = deezer_iface.Get("org.mpris.MediaPlayer2.Player", "Metadata") + playback_status = str( + deezer_iface.Get("org.mpris.MediaPlayer2.Player", "PlaybackStatus") + ) + self._song = self._format.format( + album=str(props.get("xesam:album")), + title=str(props.get("xesam:title")), + artist=",".join(props.get("xesam:artist")), + trackNumber=str(props.get("xesam:trackNumber")), + playbackStatus="\u25B6" + if playback_status == "Playing" + else "\u258D\u258D" + if playback_status == "Paused" + else "", + ) except Exception: - self._song = '' + self._song = "" + # vim: tabstop=8 expandtab shiftwidth=4 softtabstop=4 diff --git a/modules/contrib/dnf.py b/modules/contrib/dnf.py index 83e52cf..3f5e484 100644 --- a/modules/contrib/dnf.py +++ b/modules/contrib/dnf.py @@ -19,34 +19,41 @@ import core.decorators import util.cli + def get_dnf_info(widget): - res = util.cli.execute('dnf updateinfo', ignore_errors=True) + res = util.cli.execute("dnf updateinfo", ignore_errors=True) security = 0 bugfixes = 0 enhancements = 0 other = 0 - for line in res.split('\n'): - if not line.startswith(' '): continue - elif 'ecurity' in line: + for line in res.split("\n"): + if not line.startswith(" "): + continue + elif "ecurity" in line: for s in line.split(): - if s.isdigit(): security += int(s) - elif 'ugfix' in line: + if s.isdigit(): + security += int(s) + elif "ugfix" in line: for s in line.split(): - if s.isdigit(): bugfixes += int(s) - elif 'hancement' in line: + if s.isdigit(): + bugfixes += int(s) + elif "hancement" in line: for s in line.split(): - if s.isdigit(): enhancements += int(s) + if s.isdigit(): + enhancements += int(s) else: for s in line.split(): - if s.isdigit(): other += int(s) + if s.isdigit(): + other += int(s) - widget.set('security', security) - widget.set('bugfixes', bugfixes) - widget.set('enhancements', enhancements) - widget.set('other', other) + widget.set("security", security) + widget.set("bugfixes", bugfixes) + widget.set("enhancements", enhancements) + widget.set("other", other) + + core.event.trigger("update", [widget.module.id], redraw_only=True) - core.event.trigger('update', [ widget.module.id ], redraw_only=True) class Module(core.module.Module): @core.decorators.every(minutes=30) @@ -55,9 +62,9 @@ class Module(core.module.Module): def updates(self, widget): result = [] - for t in ['security', 'bugfixes', 'enhancements', 'other']: + for t in ["security", "bugfixes", "enhancements", "other"]: result.append(str(widget.get(t, 0))) - return '/'.join(result) + return "/".join(result) def update(self): thread = threading.Thread(target=get_dnf_info, args=(self.widget(),)) @@ -65,11 +72,12 @@ class Module(core.module.Module): def state(self, widget): cnt = 0 - for t in ['security', 'bugfixes', 'enhancements', 'other']: + for t in ["security", "bugfixes", "enhancements", "other"]: cnt += widget.get(t, 0) if cnt == 0: - return 'good' - if cnt > 50 or widget.get('security', 0) > 0: - return 'critical' + return "good" + if cnt > 50 or widget.get("security", 0) > 0: + return "critical" + # vim: tabstop=8 expandtab shiftwidth=4 softtabstop=4 diff --git a/modules/contrib/docker_ps.py b/modules/contrib/docker_ps.py index 13b9f7f..7ece29c 100644 --- a/modules/contrib/docker_ps.py +++ b/modules/contrib/docker_ps.py @@ -15,29 +15,33 @@ import core.module import core.widget import core.decorators + class Module(core.module.Module): @core.decorators.every(seconds=5) def __init__(self, config, theme): super().__init__(config, theme, core.widget.Widget(self.docker_info)) - self.__info = '' + self.__info = "" def state(self, widget): state = [] - if self.__info == 'OK - 0': - state.append('warning') - elif self.__info in ['n/a', 'daemon off']: - state.append('critical') + if self.__info == "OK - 0": + state.append("warning") + elif self.__info in ["n/a", "daemon off"]: + state.append("critical") return state def docker_info(self, widget): try: - cli = docker.DockerClient(base_url='unix://var/run/docker.sock') + cli = docker.DockerClient(base_url="unix://var/run/docker.sock") cli.ping() - self.__info = 'OK - {}'.format(len(cli.containers.list(filters={'status': 'running'}))) + self.__info = "OK - {}".format( + len(cli.containers.list(filters={"status": "running"})) + ) except ConnectionError: - self.__info = 'daemon off' + self.__info = "daemon off" except Exception: - self.__info = 'n/a' + self.__info = "n/a" return self.__info + # vim: tabstop=8 expandtab shiftwidth=4 softtabstop=4 diff --git a/modules/contrib/dunst.py b/modules/contrib/dunst.py index 399d997..bf9d72b 100644 --- a/modules/contrib/dunst.py +++ b/modules/contrib/dunst.py @@ -1,6 +1,6 @@ -#pylint: disable=C0111,R0903 +# pylint: disable=C0111,R0903 -'''Toggle dunst notifications.''' +"""Toggle dunst notifications.""" import core.module import core.widget @@ -8,28 +8,27 @@ import core.input import util.cli + class Module(core.module.Module): def __init__(self, config, theme): - super().__init__(config, theme, core.widget.Widget('')) + super().__init__(config, theme, core.widget.Widget("")) self._paused = False # Make sure that dunst is currently not paused - util.cli.execute('killall -s SIGUSR2 dunst', ignore_errors=True) - core.input.register(self, button=core.input.LEFT_MOUSE, - cmd=self.toggle_status - ) + util.cli.execute("killall -s SIGUSR2 dunst", ignore_errors=True) + core.input.register(self, button=core.input.LEFT_MOUSE, cmd=self.toggle_status) def toggle_status(self, event): self._paused = not self._paused - + try: if self._paused: - util.cli.execute('killall -s SIGUSR1 dunst') + util.cli.execute("killall -s SIGUSR1 dunst") else: - util.cli.execute('killall -s SIGUSR2 dunst') + util.cli.execute("killall -s SIGUSR2 dunst") except: - self._paused = not self._paused # toggling failed + self._paused = not self._paused # toggling failed def state(self, widget): if self._paused: - return ['muted', 'warning'] - return ['unmuted'] + return ["muted", "warning"] + return ["unmuted"] diff --git a/modules/contrib/getcrypto.py b/modules/contrib/getcrypto.py index 2381609..785dbd0 100644 --- a/modules/contrib/getcrypto.py +++ b/modules/contrib/getcrypto.py @@ -24,51 +24,64 @@ import core.decorators import util.format + def getfromkrak(coin, currency): abbrev = { - 'Btc': ['xbt', 'XXBTZ'], - 'Eth': ['eth', 'XETHZ'], - 'Ltc': ['ltc', 'XLTCZ'], + "Btc": ["xbt", "XXBTZ"], + "Eth": ["eth", "XETHZ"], + "Ltc": ["ltc", "XLTCZ"], } data = abbrev.get(coin, None) - if not data: return - epair = '{}{}'.format(data[0], currency) - tickname = '{}{}'.format(data[1], currency.upper()) + if not data: + return + epair = "{}{}".format(data[0], currency) + tickname = "{}{}".format(data[1], currency.upper()) try: - krakenget = requests.get('https://api.kraken.com/0/public/Ticker?pair='+epair).json() + krakenget = requests.get( + "https://api.kraken.com/0/public/Ticker?pair=" + epair + ).json() except (RequestException, Exception): - return 'No connection' - if not 'result' in krakenget: - return 'No data' - kethusdask = float(krakenget['result'][tickname]['a'][0]) - kethusdbid = float(krakenget['result'][tickname]['b'][0]) - return coin+': '+str((kethusdask+kethusdbid)/2)[0:6] + return "No connection" + if not "result" in krakenget: + return "No data" + kethusdask = float(krakenget["result"][tickname]["a"][0]) + kethusdbid = float(krakenget["result"][tickname]["b"][0]) + return coin + ": " + str((kethusdask + kethusdbid) / 2)[0:6] + class Module(core.module.Module): @core.decorators.every(minutes=30) def __init__(self, config, theme): super().__init__(config, theme, core.widget.Widget(self.curprice)) - self.__curprice = '' - self.__getbtc = util.format.asbool(self.parameter('getbtc', True)) - self.__geteth = util.format.asbool(self.parameter('geteth', True)) - self.__getltc = util.format.asbool(self.parameter('getltc', True)) - self.__getcur = self.parameter('getcur', 'usd') - core.input.register(self, button=core.input.LEFT_MOUSE, - cmd='xdg-open https://cryptowat.ch/') + self.__curprice = "" + self.__getbtc = util.format.asbool(self.parameter("getbtc", True)) + self.__geteth = util.format.asbool(self.parameter("geteth", True)) + self.__getltc = util.format.asbool(self.parameter("getltc", True)) + self.__getcur = self.parameter("getcur", "usd") + core.input.register( + self, button=core.input.LEFT_MOUSE, cmd="xdg-open https://cryptowat.ch/" + ) def curprice(self, widget): return self.__curprice def update(self): currency = self.__getcur - btcprice, ethprice, ltcprice = '', '', '' + btcprice, ethprice, ltcprice = "", "", "" if self.__getbtc: - btcprice = getfromkrak('Btc', currency) + btcprice = getfromkrak("Btc", currency) if self.__geteth: - ethprice = getfromkrak('Eth', currency) + ethprice = getfromkrak("Eth", currency) if self.__getltc: - ltcprice = getfromkrak('Ltc', currency) - self.__curprice = btcprice+' '*(self.__getbtc*self.__geteth)+ethprice+' '*(self.__getltc*max(self.__getbtc, self.__geteth))+ltcprice + ltcprice = getfromkrak("Ltc", currency) + self.__curprice = ( + btcprice + + " " * (self.__getbtc * self.__geteth) + + ethprice + + " " * (self.__getltc * max(self.__getbtc, self.__geteth)) + + ltcprice + ) + # vim: tabstop=8 expandtab shiftwidth=4 softtabstop=4 diff --git a/modules/contrib/github.py b/modules/contrib/github.py index b22fed1..f312f43 100644 --- a/modules/contrib/github.py +++ b/modules/contrib/github.py @@ -18,6 +18,7 @@ import core.widget import core.decorators import core.input + class Module(core.module.Module): @core.decorators.every(minutes=5) def __init__(self, config, theme): @@ -25,15 +26,19 @@ class Module(core.module.Module): self.__count = 0 self.__requests = requests.Session() - self.__requests.headers.update({'Authorization':'token {}'.format(self.parameter('token', ''))}) + self.__requests.headers.update( + {"Authorization": "token {}".format(self.parameter("token", ""))} + ) - cmd = 'xdg-open' + cmd = "xdg-open" if not shutil.which(cmd): - cmd = 'x-www-browser' + cmd = "x-www-browser" - - core.input.register(self, button=core.input.LEFT_MOUSE, - cmd='{} https://github.com/notifications'.format(cmd)) + core.input.register( + self, + button=core.input.LEFT_MOUSE, + cmd="{} https://github.com/notifications".format(cmd), + ) core.input.register(self, button=core.input.RIGHT_MOUSE, cmd=self.update) def github(self, _): @@ -42,17 +47,25 @@ class Module(core.module.Module): def update(self): try: self.__count = 0 - url = 'https://api.github.com/notifications' + url = "https://api.github.com/notifications" while True: notifications = self.__requests.get(url) - self.__count += len(list(filter(lambda notification: notification['unread'], notifications.json()))) - next_link = notifications.links.get('next') + self.__count += len( + list( + filter( + lambda notification: notification["unread"], + notifications.json(), + ) + ) + ) + next_link = notifications.links.get("next") if next_link is not None: - url = next_link.get('url') + url = next_link.get("url") else: break except Exception: - self.__count = 'n/a' + self.__count = "n/a" + # vim: tabstop=8 expandtab shiftwidth=4 softtabstop=4 diff --git a/modules/contrib/gpmdp.py b/modules/contrib/gpmdp.py index e40f3d1..5d5110b 100644 --- a/modules/contrib/gpmdp.py +++ b/modules/contrib/gpmdp.py @@ -12,42 +12,47 @@ import core.input import util.cli + class Module(core.module.Module): def __init__(self, config, theme): widgets = [ - core.widget.Widget(name='gpmdp.prev'), - core.widget.Widget(name='gpmdp.main', full_text=self.description), - core.widget.Widget(name='gpmdp.next'), + core.widget.Widget(name="gpmdp.prev"), + core.widget.Widget(name="gpmdp.main", full_text=self.description), + core.widget.Widget(name="gpmdp.next"), ] super().__init__(config, theme, widgets) - core.input.register(widgets[0], button=core.input.LEFT_MOUSE, - cmd='playerctl previous') - core.input.register(widgets[1], button=core.input.LEFT_MOUSE, - cmd='playerctl play-pause') - core.input.register(widgets[2], button=core.input.LEFT_MOUSE, - cmd='playerctl next') + core.input.register( + widgets[0], button=core.input.LEFT_MOUSE, cmd="playerctl previous" + ) + core.input.register( + widgets[1], button=core.input.LEFT_MOUSE, cmd="playerctl play-pause" + ) + core.input.register( + widgets[2], button=core.input.LEFT_MOUSE, cmd="playerctl next" + ) self.__status = None self.__tags = None def description(self, widget): - return self.__tags if self.__tags else 'n/a' + return self.__tags if self.__tags else "n/a" def update(self): self.__load_song() def state(self, widget): - if widget.name == 'gpmdp.prev': - return 'prev' - if widget.name == 'gpmdp.next': - return 'next' + if widget.name == "gpmdp.prev": + return "prev" + if widget.name == "gpmdp.next": + return "next" return self.__status def __load_song(self): - info = util.cli.execute('gpmdp-remote current', ignore_errors=True) - status = util.cli.execute('gpmdp-remote status', ignore_errors=True) - self.__status = status.split('\n')[0].lower() - self.__tags = info.split('\n')[0] + info = util.cli.execute("gpmdp-remote current", ignore_errors=True) + status = util.cli.execute("gpmdp-remote status", ignore_errors=True) + self.__status = status.split("\n")[0].lower() + self.__tags = info.split("\n")[0] + # vim: tabstop=8 expandtab shiftwidth=4 softtabstop=4 diff --git a/modules/contrib/hddtemp.py b/modules/contrib/hddtemp.py index 84b43d3..44b16b5 100644 --- a/modules/contrib/hddtemp.py +++ b/modules/contrib/hddtemp.py @@ -9,12 +9,13 @@ import socket import core.module import core.widget -HOST = 'localhost' +HOST = "localhost" PORT = 7634 CHUNK_SIZE = 1024 RECORD_SIZE = 5 -SEPARATOR = '|' +SEPARATOR = "|" + class Module(core.module.Module): def __init__(self, config, theme): @@ -29,7 +30,7 @@ class Module(core.module.Module): try: with socket.socket(socket.AF_INET, socket.SOCK_STREAM) as sock: sock.connect((HOST, PORT)) - data = '' + data = "" while True: chunk = sock.recv(CHUNK_SIZE) if chunk: @@ -46,7 +47,7 @@ class Module(core.module.Module): split data using | separator and remove first item (because the first item is empty) """ - parts = data.split('|')[1:] + parts = data.split("|")[1:] return parts @staticmethod @@ -54,8 +55,9 @@ class Module(core.module.Module): """ partition parts: one device record is five (5) items """ - per_disk = [parts[i:i+RECORD_SIZE] - for i in range(len(parts))[::RECORD_SIZE]] + per_disk = [ + parts[i : i + RECORD_SIZE] for i in range(len(parts))[::RECORD_SIZE] + ] return per_disk @staticmethod @@ -64,20 +66,20 @@ class Module(core.module.Module): get device name (without /dev part, to save space on bar) and temperature (in °C) as tuple """ - device_name = device_record[0].split('/')[-1] + device_name = device_record[0].split("/")[-1] device_temp = device_record[2] return (device_name, device_temp) @staticmethod def __get_hddtemp(device_record): name, temp = device_record - hddtemp = '{}+{}°C'.format(name, temp) + hddtemp = "{}+{}°C".format(name, temp) return hddtemp def __get_hddtemps(self): data = self.__fetch_data() if data is None: - return 'n/a' + return "n/a" parts = self.__get_parts(data) per_disk = self.__partition_parts(parts) names_and_temps = [self.__get_name_and_temp(x) for x in per_disk] @@ -87,4 +89,5 @@ class Module(core.module.Module): def update(self): self.__hddtemps = self.__get_hddtemps() + # vim: tabstop=8 expandtab shiftwidth=4 softtabstop=4 diff --git a/modules/contrib/hostname.py b/modules/contrib/hostname.py index 43a9521..e4f72d2 100644 --- a/modules/contrib/hostname.py +++ b/modules/contrib/hostname.py @@ -8,16 +8,18 @@ import core.module import core.widget import core.decorators + class Module(core.module.Module): @core.decorators.every(minutes=60) def __init__(self, config, theme): super().__init__(config, theme, core.widget.Widget(self.output)) - self.__hname = '' + self.__hname = "" def output(self, _): - return self.__hname + ' ' + u'\uf233' + return self.__hname + " " + "\uf233" def update(self): self.__hname = platform.node() + # vim: tabstop=8 expandtab shiftwidth=4 softtabstop=4 diff --git a/modules/contrib/http_status.py b/modules/contrib/http_status.py index 49f6f7b..5bc7b69 100644 --- a/modules/contrib/http_status.py +++ b/modules/contrib/http_status.py @@ -16,21 +16,22 @@ import core.module import core.widget import core.decorators + class Module(core.module.Module): - UNK = 'UNK' + UNK = "UNK" @core.decorators.every(seconds=30) def __init__(self, config, theme): super().__init__(config, theme, core.widget.Widget(self.output)) - self.__label = self.parameter('label') - self.__target = self.parameter('target') - self.__expect = self.parameter('expect', '200') + self.__label = self.parameter("label") + self.__target = self.parameter("target") + self.__expect = self.parameter("expect", "200") def labelize(self, s): if self.__label is None: return s - return '{}: {}'.format(self.__label, s) + return "{}: {}".format(self.__label, s) def getStatus(self): try: @@ -46,8 +47,8 @@ class Module(core.module.Module): if self.__status == self.__expect: return self.labelize(self.__status) else: - reason = ' != {}'.format(self.__expect) - return self.labelize('{}{}'.format(self.__status, reason)) + reason = " != {}".format(self.__expect) + return self.labelize("{}{}".format(self.__status, reason)) def output(self, widget): return self.__output @@ -58,9 +59,10 @@ class Module(core.module.Module): def state(self, widget): if self.__status == self.UNK: - return 'warning' + return "warning" if self.__status != self.__expect: - return 'critical' + return "critical" return self.__output + # vim: tabstop=8 expandtab shiftwidth=4 softtabstop=4 diff --git a/modules/contrib/indicator.py b/modules/contrib/indicator.py index b761b3e..c6778cb 100644 --- a/modules/contrib/indicator.py +++ b/modules/contrib/indicator.py @@ -1,4 +1,4 @@ -#pylint: disable=C0111,R0903 +# pylint: disable=C0111,R0903 """Displays the indicator status, for numlock, scrolllock and capslock @@ -13,18 +13,29 @@ import core.widget import util.cli import util.format + class Module(core.module.Module): def __init__(self, config, theme): super().__init__(config, theme, []) - self.__include = tuple(filter(len, util.format.aslist(self.parameter('include', 'NumLock,CapsLock')))) - self.__signalType = self.parameter('signaltype') if not self.parameter('signaltype') is None else 'warning' + self.__include = tuple( + filter( + len, util.format.aslist(self.parameter("include", "NumLock,CapsLock")) + ) + ) + self.__signalType = ( + self.parameter("signaltype") + if not self.parameter("signaltype") is None + else "warning" + ) def update(self): - status_line = '' - for line in util.cli.execute('xset q', ignore_errors=True).replace(' ', '').split('\n'): - if 'capslock' in line.lower(): - status_line = line + status_line = "" + for line in ( + util.cli.execute("xset q", ignore_errors=True).replace(" ", "").split("\n") + ): + if "capslock" in line.lower(): + status_line = line break for indicator in self.__include: widget = self.widget(indicator) @@ -32,15 +43,21 @@ class Module(core.module.Module): widget = core.widget.Widget(name=indicator, module=self) self.widgets().append(widget) - widget.set('status', True if '{}:on'.format(indicator.lower()) in status_line.lower() else False) + widget.set( + "status", + True + if "{}:on".format(indicator.lower()) in status_line.lower() + else False, + ) widget.full_text(indicator) def state(self, widget): states = [] - if widget.get('status', False): + if widget.get("status", False): states.append(self.__signalType) else: - states.append('normal') + states.append("normal") return states + # vim: tabstop=8 expandtab shiftwidth=4 softtabstop=4 diff --git a/modules/contrib/layout-xkbswitch.py b/modules/contrib/layout-xkbswitch.py index cf18be6..58c15b9 100644 --- a/modules/contrib/layout-xkbswitch.py +++ b/modules/contrib/layout-xkbswitch.py @@ -11,31 +11,30 @@ import core.input import util.cli + class Module(core.module.Module): @core.decorators.every(seconds=60) def __init__(self, config, theme): super().__init__(config, theme, core.widget.Widget(self.current_layout)) - core.input.register( - self, - button=core.input.LEFT_MOUSE, - cmd=self.__next_keymap) + core.input.register(self, button=core.input.LEFT_MOUSE, cmd=self.__next_keymap) self.__current_layout = self.__get_current_layout() def current_layout(self, _): return self.__current_layout def __next_keymap(self, event): - util.cli.execute('xkb-switch -n', ignore_errors=True) + util.cli.execute("xkb-switch -n", ignore_errors=True) def __get_current_layout(self): try: - res = util.cli.execute('xkb-switch') - return res.split('\n')[0] + res = util.cli.execute("xkb-switch") + return res.split("\n")[0] except RuntimeError: - return ['n/a'] + return ["n/a"] def update(self): self.__current_layout = self.__get_current_layout() + # vim: tabstop=8 expandtab shiftwidth=4 softtabstop=4 diff --git a/modules/contrib/layout.py b/modules/contrib/layout.py index 5004bdb..9acd8ed 100644 --- a/modules/contrib/layout.py +++ b/modules/contrib/layout.py @@ -12,14 +12,13 @@ import core.input import util.cli + class Module(core.module.Module): def __init__(self, config, theme): super().__init__(config, theme, core.widget.Widget(self.current_layout)) - core.input.register(self, button=core.input.LEFT_MOUSE, - cmd=self.__next_keymap) - core.input.register(self, button=core.input.RIGHT_MOUSE, - cmd=self.__prev_keymap) + core.input.register(self, button=core.input.LEFT_MOUSE, cmd=self.__next_keymap) + core.input.register(self, button=core.input.RIGHT_MOUSE, cmd=self.__prev_keymap) def __next_keymap(self, event): self._set_keymap(1) @@ -29,41 +28,49 @@ class Module(core.module.Module): def _set_keymap(self, rotation): layouts = self.get_layouts() - if len(layouts) == 1: return # nothing to do + if len(layouts) == 1: + return # nothing to do layouts = layouts[rotation:] + layouts[:rotation] layout_list = [] variant_list = [] for l in layouts: - tmp = l.split(':') + tmp = l.split(":") layout_list.append(tmp[0]) - variant_list.append(tmp[1] if len(tmp) > 1 else '') + variant_list.append(tmp[1] if len(tmp) > 1 else "") - util.cli.execute('setxkbmap -layout {} -variant {}'.format(','.join(layout_list), ','.join(variant_list)), ignore_errors=True) + util.cli.execute( + "setxkbmap -layout {} -variant {}".format( + ",".join(layout_list), ",".join(variant_list) + ), + ignore_errors=True, + ) def get_layouts(self): try: - res = util.cli.execute('setxkbmap -query') + res = util.cli.execute("setxkbmap -query") except RuntimeError: - return ['n/a'] + return ["n/a"] layouts = [] variants = [] - for line in res.split('\n'): - if not line: continue - if 'layout' in line: - layouts = line.split(':')[1].strip().split(',') - if 'variant' in line: - variants = line.split(':')[1].strip().split(',') + for line in res.split("\n"): + if not line: + continue + if "layout" in line: + layouts = line.split(":")[1].strip().split(",") + if "variant" in line: + variants = line.split(":")[1].strip().split(",") result = [] for idx, layout in enumerate(layouts): if len(variants) > idx and variants[idx]: - layout = '{}:{}'.format(layout, variants[idx]) + layout = "{}:{}".format(layout, variants[idx]) result.append(layout) - return result if len(result) > 0 else ['n/a'] + return result if len(result) > 0 else ["n/a"] def current_layout(self, widget): layouts = self.get_layouts() return layouts[0] + # vim: tabstop=8 expandtab shiftwidth=4 softtabstop=4 diff --git a/modules/contrib/libvirtvms.py b/modules/contrib/libvirtvms.py index 8f39814..edb17dd 100644 --- a/modules/contrib/libvirtvms.py +++ b/modules/contrib/libvirtvms.py @@ -11,18 +11,19 @@ import core.widget import core.input import core.decorators + class Module(core.module.Module): @core.decorators.every(seconds=10) def __init__(self, config, theme): super().__init__(config, theme, core.widget.Widget(self.status)) - core.input.register(self, button=core.input.LEFT_MOUSE, - cmd='virt-manager') + core.input.register(self, button=core.input.LEFT_MOUSE, cmd="virt-manager") def status(self, _): conn = libvirt.openReadOnly(None) if conn == None: - return 'Failed to open connection to the hypervisor' - return 'VMs %s' % (conn.numOfDomains()) + return "Failed to open connection to the hypervisor" + return "VMs %s" % (conn.numOfDomains()) + # vim: tabstop=8 expandtab shiftwidth=4 softtabstop=4 diff --git a/modules/contrib/mocp.py b/modules/contrib/mocp.py index db83800..31ac067 100644 --- a/modules/contrib/mocp.py +++ b/modules/contrib/mocp.py @@ -29,17 +29,18 @@ import core.input import util.cli + class Module(core.module.Module): def __init__(self, config, theme): super().__init__(config, theme, core.widget.Widget(self.description)) - core.input.register(self, button=core.input.LEFT_MOUSE, cmd='mocp -G') - core.input.register(self, button=core.input.RIGHT_MOUSE, cmd='mocp -t shuffle') - self.__format = self.parameter('format', '%state %artist - %song | %ct/%tt') + core.input.register(self, button=core.input.LEFT_MOUSE, cmd="mocp -G") + core.input.register(self, button=core.input.RIGHT_MOUSE, cmd="mocp -t shuffle") + self.__format = self.parameter("format", "%state %artist - %song | %ct/%tt") self.__running = False def description(self, widget): - return self.__info if self.__running == True else 'Music On Console Player' + return self.__info if self.__running == True else "Music On Console Player" def update(self): self.__load_song() @@ -51,4 +52,5 @@ class Module(core.module.Module): except RuntimeError: self.__running = False + # vim: tabstop=8 expandtab shiftwidth=4 softtabstop=4 diff --git a/modules/contrib/mpd.py b/modules/contrib/mpd.py index 85e8ea6..6622143 100644 --- a/modules/contrib/mpd.py +++ b/modules/contrib/mpd.py @@ -52,22 +52,25 @@ import core.decorators import util.cli + class Module(core.module.Module): def __init__(self, config, theme): super().__init__(config, theme, []) - self._layout = self.parameter('layout', 'mpd.prev mpd.main mpd.next mpd.shuffle mpd.repeat') + self._layout = self.parameter( + "layout", "mpd.prev mpd.main mpd.next mpd.shuffle mpd.repeat" + ) - self._fmt = self.parameter('format', '{artist} - {title} {position}/{duration}') + self._fmt = self.parameter("format", "{artist} - {title} {position}/{duration}") self._status = None self._shuffle = False self._repeat = False - self._tags = defaultdict(lambda: '') + self._tags = defaultdict(lambda: "") - if not self.parameter('host'): - self._hostcmd = '' + if not self.parameter("host"): + self._hostcmd = "" else: - self._hostcmd = ' -h ' + self.parameter('host') + self._hostcmd = " -h " + self.parameter("host") # Create widgets widget_list = [] @@ -76,19 +79,38 @@ class Module(core.module.Module): widget = core.widget.Widget(name=widget_name, module=self) widget_list.append(widget) - if widget_name == 'mpd.prev': - widget_map[widget] = {'button': core.input.LEFT_MOUSE, 'cmd': 'mpc prev' + self._hostcmd} - elif widget_name == 'mpd.main': - widget_map[widget] = {'button': core.input.LEFT_MOUSE, 'cmd': 'mpc toggle' + self._hostcmd} + if widget_name == "mpd.prev": + widget_map[widget] = { + "button": core.input.LEFT_MOUSE, + "cmd": "mpc prev" + self._hostcmd, + } + elif widget_name == "mpd.main": + widget_map[widget] = { + "button": core.input.LEFT_MOUSE, + "cmd": "mpc toggle" + self._hostcmd, + } widget.full_text(self.description) - elif widget_name == 'mpd.next': - widget_map[widget] = {'button': core.input.LEFT_MOUSE, 'cmd': 'mpc next' + self._hostcmd} - elif widget_name == 'mpd.shuffle': - widget_map[widget] = {'button': core.input.LEFT_MOUSE, 'cmd': 'mpc random' + self._hostcmd} - elif widget_name == 'mpd.repeat': - widget_map[widget] = {'button': core.input.LEFT_MOUSE, 'cmd': 'mpc repeat' + self._hostcmd} + elif widget_name == "mpd.next": + widget_map[widget] = { + "button": core.input.LEFT_MOUSE, + "cmd": "mpc next" + self._hostcmd, + } + elif widget_name == "mpd.shuffle": + widget_map[widget] = { + "button": core.input.LEFT_MOUSE, + "cmd": "mpc random" + self._hostcmd, + } + elif widget_name == "mpd.repeat": + widget_map[widget] = { + "button": core.input.LEFT_MOUSE, + "cmd": "mpc repeat" + self._hostcmd, + } else: - raise KeyError('The mpd module does not support a {widget_name!r} widget'.format(widget_name=widget_name)) + raise KeyError( + "The mpd module does not support a {widget_name!r} widget".format( + widget_name=widget_name + ) + ) self.widgets(widget_list) # Register input callbacks @@ -106,74 +128,79 @@ class Module(core.module.Module): self._load_song() def state(self, widget): - if widget.name == 'mpd.shuffle': - return 'shuffle-on' if self._shuffle else 'shuffle-off' - if widget.name == 'mpd.repeat': - return 'repeat-on' if self._repeat else 'repeat-off' - if widget.name == 'mpd.prev': - return 'prev' - if widget.name == 'mpd.next': - return 'next' + if widget.name == "mpd.shuffle": + return "shuffle-on" if self._shuffle else "shuffle-off" + if widget.name == "mpd.repeat": + return "repeat-on" if self._repeat else "repeat-off" + if widget.name == "mpd.prev": + return "prev" + if widget.name == "mpd.next": + return "next" return self._status def _load_song(self): - info = '' - tags = ['name', - 'artist', - 'album', - 'albumartist', - 'comment', - 'composer', - 'date', - 'originaldate', - 'disc', - 'genre', - 'performer', - 'title', - 'track', - 'time', - 'file', - 'id', - 'prio', - 'mtime', - 'mdate'] - joinedtags = '\n'.join(['tag {0} %{0}%'.format(tag) for tag in tags]) - info = util.cli.execute('mpc -f "{}"{}'.format(joinedtags, self._hostcmd), ignore_errors=True) + info = "" + tags = [ + "name", + "artist", + "album", + "albumartist", + "comment", + "composer", + "date", + "originaldate", + "disc", + "genre", + "performer", + "title", + "track", + "time", + "file", + "id", + "prio", + "mtime", + "mdate", + ] + joinedtags = "\n".join(["tag {0} %{0}%".format(tag) for tag in tags]) + info = util.cli.execute( + 'mpc -f "{}"{}'.format(joinedtags, self._hostcmd), ignore_errors=True + ) - self._tags = defaultdict(lambda: '') + self._tags = defaultdict(lambda: "") self._status = None - for line in info.split('\n'): - if line.startswith('[playing]'): - self._status = 'playing' - elif line.startswith('[paused]'): - self._status = 'paused' + for line in info.split("\n"): + if line.startswith("[playing]"): + self._status = "playing" + elif line.startswith("[paused]"): + self._status = "paused" - if line.startswith('['): + if line.startswith("["): timer = line.split()[2] - position = timer.split('/')[0] - dur = timer.split('/')[1] - duration = dur.split(' ')[0] - self._tags.update({'position': position}) - self._tags.update({'duration': duration}) + position = timer.split("/")[0] + dur = timer.split("/")[1] + duration = dur.split(" ")[0] + self._tags.update({"position": position}) + self._tags.update({"duration": duration}) - if line.startswith('volume'): - value = line.split(' ', 2)[1:] + if line.startswith("volume"): + value = line.split(" ", 2)[1:] for option in value: - if option.startswith('repeat: on'): + if option.startswith("repeat: on"): self._repeat = True - elif option.startswith('repeat: off'): + elif option.startswith("repeat: off"): self._repeat = False - elif option.startswith('random: on'): + elif option.startswith("random: on"): self._shuffle = True - elif option.startswith('random: off'): + elif option.startswith("random: off"): self._shuffle = False - if line.startswith('tag'): - key, value = line.split(' ', 2)[1:] + if line.startswith("tag"): + key, value = line.split(" ", 2)[1:] self._tags.update({key: value}) - if key == 'file': - self._tags.update({'file1': os.path.basename(value)}) + if key == "file": + self._tags.update({"file1": os.path.basename(value)}) self._tags.update( - {'file2': - os.path.splitext(os.path.basename(value))[0]}) + {"file2": os.path.splitext(os.path.basename(value))[0]} + ) + # vim: tabstop=8 expandtab shiftwidth=4 softtabstop=4 diff --git a/modules/contrib/network_traffic.py b/modules/contrib/network_traffic.py index 97616b6..36e1124 100644 --- a/modules/contrib/network_traffic.py +++ b/modules/contrib/network_traffic.py @@ -13,24 +13,33 @@ import core.widget import util.format -WIDGET_NAME = 'network_traffic' +WIDGET_NAME = "network_traffic" + class Module(core.module.Module): def __init__(self, config, theme): widgets = [ - core.widget.Widget(module=self, name='{0}.rx'.format(WIDGET_NAME), full_text=self.download_rate), - core.widget.Widget(module=self, name='{0}.tx'.format(WIDGET_NAME), full_text=self.upload_rate) + core.widget.Widget( + module=self, + name="{0}.rx".format(WIDGET_NAME), + full_text=self.download_rate, + ), + core.widget.Widget( + module=self, + name="{0}.tx".format(WIDGET_NAME), + full_text=self.upload_rate, + ), ] super().__init__(config, theme, widgets) - self.widgets()[0].set('theme.minwidth', '0000000KiB/s') - self.widgets()[1].set('theme.minwidth', '0000000KiB/s') + self.widgets()[0].set("theme.minwidth", "0000000KiB/s") + self.widgets()[1].set("theme.minwidth", "0000000KiB/s") try: self._bandwidth = BandwidthInfo() - self._rate_recv = '?' - self._rate_sent = '?' + self._rate_recv = "?" + self._rate_sent = "?" self._bytes_recv = self._bandwidth.bytes_recv() self._bytes_sent = self._bandwidth.bytes_sent() except Exception: @@ -40,10 +49,10 @@ class Module(core.module.Module): def state(self, widget): """Return the widget state""" - if widget.name == '{}.rx'.format(WIDGET_NAME): - return 'rx' - elif widget.name == '{}.tx'.format(WIDGET_NAME): - return 'tx' + if widget.name == "{}.rx".format(WIDGET_NAME): + return "rx" + elif widget.name == "{}.tx".format(WIDGET_NAME): + return "tx" return None @@ -52,8 +61,8 @@ class Module(core.module.Module): bytes_recv = self._bandwidth.bytes_recv() bytes_sent = self._bandwidth.bytes_sent() - self._rate_recv = (bytes_recv - self._bytes_recv) - self._rate_sent = (bytes_sent - self._bytes_sent) + self._rate_recv = bytes_recv - self._bytes_recv + self._rate_sent = bytes_sent - self._bytes_sent self._bytes_recv, self._bytes_sent = bytes_recv, bytes_sent except Exception: @@ -61,10 +70,11 @@ class Module(core.module.Module): pass def download_rate(self, _): - return '{}/s'.format(util.format.byte(self._rate_recv)) + return "{}/s".format(util.format.byte(self._rate_recv)) def upload_rate(self, _): - return '{}/s'.format(util.format.byte(self._rate_sent)) + return "{}/s".format(util.format.byte(self._rate_sent)) + class BandwidthInfo(object): """Get received/sent bytes from network adapter""" @@ -85,10 +95,10 @@ class BandwidthInfo(object): @classmethod def default_network_adapter(cls): """Return default active network adapter""" - gateway = netifaces.gateways()['default'] + gateway = netifaces.gateways()["default"] if not gateway: - raise 'No default gateway found' + raise "No default gateway found" return gateway[netifaces.AF_INET][1] @@ -97,4 +107,5 @@ class BandwidthInfo(object): """Return IO counters""" return psutil.net_io_counters(pernic=True) + # vim: tabstop=8 expandtab shiftwidth=4 softtabstop=4 diff --git a/modules/contrib/notmuch_count.py b/modules/contrib/notmuch_count.py index e1ac040..3b84ff2 100644 --- a/modules/contrib/notmuch_count.py +++ b/modules/contrib/notmuch_count.py @@ -20,24 +20,30 @@ import core.widget import util.cli + class Module(core.module.Module): def __init__(self, config, theme): super().__init__(config, theme, core.widget.Widget(self.output)) - self.__notmuch_count_query = self.parameter('query', 'tag:unread AND NOT path:/.*Trash.*/') + self.__notmuch_count_query = self.parameter( + "query", "tag:unread AND NOT path:/.*Trash.*/" + ) def output(self, widget): - return self.__notmuch_count + return self.__notmuch_count def state(self, widgets): if self.__notmuch_count == 0: - return 'empty' - return 'items' + return "empty" + return "items" def update(self): try: - self.__notmuch_count = util.cli.execute('notmuch count {}'.format(self.__notmuch_count_query)).strip() + self.__notmuch_count = util.cli.execute( + "notmuch count {}".format(self.__notmuch_count_query) + ).strip() except Exception: - self.__notmuch_count = 'n/a' + self.__notmuch_count = "n/a" + # vim: tabstop=8 expandtab shiftwidth=4 softtabstop=4 diff --git a/modules/contrib/nvidiagpu.py b/modules/contrib/nvidiagpu.py index 9d58d17..c4eb593 100644 --- a/modules/contrib/nvidiagpu.py +++ b/modules/contrib/nvidiagpu.py @@ -15,11 +15,12 @@ import core.widget import util.cli import util.format + class Module(core.module.Module): def __init__(self, config, theme): super().__init__(config, theme, core.widget.Widget(self.utilization)) - self.__utilization = 'Not found: 0 0/0' + self.__utilization = "Not found: 0 0/0" def utilization(self, widget): return self.__utilization @@ -28,49 +29,52 @@ class Module(core.module.Module): return "not found" in self.__utilization def update(self): - sp = util.cli.execute('nvidia-smi -q', ignore_errors=True) + sp = util.cli.execute("nvidia-smi -q", ignore_errors=True) - title = '' - usedMem = '' - totalMem = '' - temp = '' - name = 'not found' - clockMem = '' - clockGpu = '' - fanspeed = '' - for item in sp.split('\n'): + title = "" + usedMem = "" + totalMem = "" + temp = "" + name = "not found" + clockMem = "" + clockGpu = "" + fanspeed = "" + for item in sp.split("\n"): try: - key, val = item.split(':') + key, val = item.split(":") key, val = key.strip(), val.strip() - if title == 'Clocks': - if key == 'Graphics': - clockGpu = val.split(' ')[0] - elif key == 'Memory': - clockMem = val.split(' ')[0] - if title == 'FB Memory Usage': - if key == 'Total': - totalMem = val.split(' ')[0] - elif key == 'Used': - usedMem = val.split(' ')[0] - elif key == 'GPU Current Temp': - temp = val.split(' ')[0] - elif key == 'Product Name': + if title == "Clocks": + if key == "Graphics": + clockGpu = val.split(" ")[0] + elif key == "Memory": + clockMem = val.split(" ")[0] + if title == "FB Memory Usage": + if key == "Total": + totalMem = val.split(" ")[0] + elif key == "Used": + usedMem = val.split(" ")[0] + elif key == "GPU Current Temp": + temp = val.split(" ")[0] + elif key == "Product Name": name = val - elif key == 'Fan Speed': - fanspeed = val.split(' ')[0] + elif key == "Fan Speed": + fanspeed = val.split(" ")[0] except: title = item.strip() - str_format = self.parameter('format', '{name}: {temp}°C {mem_used}/{mem_total} MiB') + str_format = self.parameter( + "format", "{name}: {temp}°C {mem_used}/{mem_total} MiB" + ) self.__utilization = str_format.format( - name = name, - temp = temp, - mem_used = usedMem, - mem_total = totalMem, - clock_gpu = clockGpu, - clock_mem = clockMem, - fanspeed = fanspeed, - ) + name=name, + temp=temp, + mem_used=usedMem, + mem_total=totalMem, + clock_gpu=clockGpu, + clock_mem=clockMem, + fanspeed=fanspeed, + ) + # vim: tabstop=8 expandtab shiftwidth=4 softtabstop=4 diff --git a/modules/contrib/octoprint.py b/modules/contrib/octoprint.py index 5e9a5da..6cd110b 100644 --- a/modules/contrib/octoprint.py +++ b/modules/contrib/octoprint.py @@ -27,27 +27,30 @@ import core.module import core.widget import core.input + def get_frame(url): - img_bytes = b"" - stream = urllib.request.urlopen(url) + img_bytes = b"" + stream = urllib.request.urlopen(url) while True: img_bytes += stream.read(1024) - a = img_bytes.find(b'\xff\xd8') - b = img_bytes.find(b'\xff\xd9') + a = img_bytes.find(b"\xff\xd8") + b = img_bytes.find(b"\xff\xd9") if a != -1 and b != -1: - jpg = img_bytes[a:b+2] - img_bytes = img_bytes[b+2:] + jpg = img_bytes[a : b + 2] + img_bytes = img_bytes[b + 2 :] img = Image.open(BytesIO(jpg)) return img return None + class WebcamImagesWorker(threading.Thread): def __init__(self, url, queue): threading.Thread.__init__(self) - + self.__url = url self.__queue = queue self.__running = True + def run(self): while self.__running: img = get_frame(self.__url) @@ -56,6 +59,7 @@ class WebcamImagesWorker(threading.Thread): def stop(self): self.__running = False + class Module(core.module.Module): @core.decorators.every(seconds=5) def __init__(self, config, theme): @@ -69,34 +73,44 @@ class Module(core.module.Module): self.__webcam_images_worker = None self.__webcam_image_url = self.__octoprint_address + "/webcam/?action=stream" self.__webcam_images_queue = None - + self.__printer_bed_temperature = "-" self.__tool1_temperature = "-" - + self.update_status() - core.input.register(self, button=core.input.LEFT_MOUSE, - cmd=self.__show_popup) + core.input.register(self, button=core.input.LEFT_MOUSE, cmd=self.__show_popup) def octoprint_status(self, widget): if self.__octoprint_state == "Offline" or self.__octoprint_state == "Unknown": return self.__octoprint_state - return self.__octoprint_state + " | B: " + str(self.__printer_bed_temperature) + "°C" + " | T1: " + str(self.__tool1_temperature) + "°C" + return ( + self.__octoprint_state + + " | B: " + + str(self.__printer_bed_temperature) + + "°C" + + " | T1: " + + str(self.__tool1_temperature) + + "°C" + ) def __get(self, endpoint): url = self.__octoprint_address + "/api/" + endpoint headers = {"X-Api-Key": self.__octoprint_api_token} resp = requests.get(url, headers=headers) - + try: return resp.json(), resp.status_code except simplejson.errors.JSONDecodeError: return None, resp.status_code - + def __get_printer_bed_temperature(self): printer_info, status_code = self.__get("printer") if status_code == 200: - return printer_info["temperature"]["bed"]["actual"], printer_info["temperature"]["bed"]["target"] + return ( + printer_info["temperature"]["bed"]["actual"], + printer_info["temperature"]["bed"]["target"], + ) return None, None def __get_octoprint_state(self): @@ -109,7 +123,7 @@ class Module(core.module.Module): printer_info, status_code = self.__get("printer") if status_code == 200: temperatures = printer_info["temperature"] - + tool_id = 0 while True: try: @@ -122,9 +136,9 @@ class Module(core.module.Module): def update_status(self): try: - self.__octoprint_state = self.__get_octoprint_state() + self.__octoprint_state = self.__get_octoprint_state() - actual_temp, _ = self.__get_printer_bed_temperature() + actual_temp, _ = self.__get_printer_bed_temperature() if actual_temp is None: actual_temp = "-" self.__printer_bed_temperature = str(actual_temp) @@ -149,17 +163,18 @@ class Module(core.module.Module): root.after(5, self.__refresh_image, root, webcam_image, webcam_image_container) - def __refresh_temperatures(self, root, printer_bed_temperature_label, tools_temperature_label): + def __refresh_temperatures( + self, root, printer_bed_temperature_label, tools_temperature_label + ): actual_bed_temp, target_bed_temp = self.__get_printer_bed_temperature() if actual_bed_temp is None: actual_bed_temp = "-" if target_bed_temp is None: target_bed_temp = "-" - bed_temp = "Bed: " + str(actual_bed_temp) + "/" + str(target_bed_temp) + " °C" + bed_temp = "Bed: " + str(actual_bed_temp) + "/" + str(target_bed_temp) + " °C" printer_bed_temperature_label.config(text=bed_temp) - tool_temperatures = self.__get_tool_temperatures() tools_temp = "Tools: " @@ -167,48 +182,68 @@ class Module(core.module.Module): tools_temp += "-/- °C" else: for i, tool_temperature in enumerate(tool_temperatures): - tools_temp += str(tool_temperature[0]) + "/" + str(tool_temperature[1]) + "°C" - if i != len(tool_temperatures)-1: + tools_temp += ( + str(tool_temperature[0]) + "/" + str(tool_temperature[1]) + "°C" + ) + if i != len(tool_temperatures) - 1: tools_temp += "\t" tools_temperature_label.config(text=tools_temp) - - root.after(500, self.__refresh_temperatures, root, printer_bed_temperature_label, tools_temperature_label) + + root.after( + 500, + self.__refresh_temperatures, + root, + printer_bed_temperature_label, + tools_temperature_label, + ) def __show_popup(self, widget): root = tk.Tk() - root.attributes('-type', 'dialog') + root.attributes("-type", "dialog") root.title("Octoprint") - frame = tk.Frame(root) + frame = tk.Frame(root) if self.__octoprint_webcam: - #load first image synchronous before popup is shown, otherwise tkinter isn't able to layout popup properly + # load first image synchronous before popup is shown, otherwise tkinter isn't able to layout popup properly img = get_frame(self.__webcam_image_url) webcam_image = ImageTk.PhotoImage(img) - webcam_image_container = tk.Button(frame, image=webcam_image) + webcam_image_container = tk.Button(frame, image=webcam_image) webcam_image_container.pack() self.__webcam_images_queue = queue.Queue() - self.__webcam_images_worker = WebcamImagesWorker(self.__webcam_image_url, self.__webcam_images_queue) + self.__webcam_images_worker = WebcamImagesWorker( + self.__webcam_image_url, self.__webcam_images_queue + ) self.__webcam_images_worker.start() else: - logging.debug("Not using webcam, as webcam is disabled. Enable with --webcam.") + logging.debug( + "Not using webcam, as webcam is disabled. Enable with --webcam." + ) frame.pack() - temperatures_label = tk.Label(frame, text="Temperatures", font=('', 25)) + temperatures_label = tk.Label(frame, text="Temperatures", font=("", 25)) temperatures_label.pack() - printer_bed_temperature_label = tk.Label(frame, text="Bed: -/- °C", font=('', 15)) - printer_bed_temperature_label.pack() - - tools_temperature_label = tk.Label(frame, text="Tools: -/- °C", font=('', 15)) - tools_temperature_label.pack() - + printer_bed_temperature_label = tk.Label( + frame, text="Bed: -/- °C", font=("", 15) + ) + printer_bed_temperature_label.pack() + + tools_temperature_label = tk.Label(frame, text="Tools: -/- °C", font=("", 15)) + tools_temperature_label.pack() + root.after(10, self.__refresh_image, root, webcam_image, webcam_image_container) - root.after(500, self.__refresh_temperatures, root, printer_bed_temperature_label, tools_temperature_label) + root.after( + 500, + self.__refresh_temperatures, + root, + printer_bed_temperature_label, + tools_temperature_label, + ) root.bind("", self.__on_close_popup) - - root.eval('tk::PlaceWindow . center') + + root.eval("tk::PlaceWindow . center") root.mainloop() def __on_close_popup(self, event): @@ -219,6 +254,7 @@ class Module(core.module.Module): self.update_status() def state(self, widget): - return [] + return [] + # vim: tabstop=8 expandtab shiftwidth=4 softtabstop=4 diff --git a/modules/contrib/pacman.py b/modules/contrib/pacman.py index 2d8245a..781af0b 100644 --- a/modules/contrib/pacman.py +++ b/modules/contrib/pacman.py @@ -20,22 +20,23 @@ import core.decorators import util.cli import util.format -#list of repositories. -#the last one should always be other -repos = ['core', 'extra', 'community', 'multilib', 'testing', 'other'] +# list of repositories. +# the last one should always be other +repos = ["core", "extra", "community", "multilib", "testing", "other"] + def get_pacman_info(widget, path): - cmd = '{}/../../bin/pacman-updates'.format(path) + cmd = "{}/../../bin/pacman-updates".format(path) if not os.path.exists(cmd): - cmd = '/usr/share/bumblebee-status/bin/pacman-update' + cmd = "/usr/share/bumblebee-status/bin/pacman-update" result = util.cli.execute(cmd, ignore_errors=True) - count = len(repos)*[0] + count = len(repos) * [0] for line in result.splitlines(): - if line.startswith(('http', 'rsync')): - for i in range(len(repos)-1): - if '/' + repos[i] + '/' in line: + if line.startswith(("http", "rsync")): + for i in range(len(repos) - 1): + if "/" + repos[i] + "/" in line: count[i] += 1 break else: @@ -43,7 +44,8 @@ def get_pacman_info(widget, path): for i in range(len(repos)): widget.set(repos[i], count[i]) - core.event.trigger('update', [ widget.module.id ], redraw_only=True) + core.event.trigger("update", [widget.module.id], redraw_only=True) + class Module(core.module.Module): @core.decorators.every(minutes=30) @@ -51,9 +53,9 @@ class Module(core.module.Module): super().__init__(config, theme, core.widget.Widget(self.updates)) def updates(self, widget): - if util.format.asbool(self.parameter('sum')): + if util.format.asbool(self.parameter("sum")): return str(sum(map(lambda x: widget.get(x, 0), repos))) - return '/'.join(map(lambda x: str(widget.get(x, 0)), repos)) + return "/".join(map(lambda x: str(widget.get(x, 0)), repos)) def update(self): path = os.path.dirname(os.path.abspath(__file__)) @@ -61,11 +63,14 @@ class Module(core.module.Module): thread.start() def state(self, widget): - weightedCount = sum(map(lambda x: (len(repos)-x[0]) * widget.get(x[1], 0), enumerate(repos))) + weightedCount = sum( + map(lambda x: (len(repos) - x[0]) * widget.get(x[1], 0), enumerate(repos)) + ) if weightedCount < 10: - return 'good' + return "good" return self.threshold_state(weightedCount, 100, 150) + # vim: tabstop=8 expandtab shiftwidth=4 softtabstop=4 diff --git a/modules/contrib/pihole.py b/modules/contrib/pihole.py index 8ae228f..311736e 100644 --- a/modules/contrib/pihole.py +++ b/modules/contrib/pihole.py @@ -12,30 +12,36 @@ import core.module import core.widget import core.input + class Module(core.module.Module): @core.decorators.every(minutes=1) def __init__(self, config, theme): super().__init__(config, theme, core.widget.Widget(self.pihole_status)) - self._pihole_address = self.parameter('address', '') - self._pihole_pw_hash = self.parameter('pwhash', '') + self._pihole_address = self.parameter("address", "") + self._pihole_pw_hash = self.parameter("pwhash", "") self._pihole_status = None - self._ads_blocked_today = '-' + self._ads_blocked_today = "-" self.update_pihole_status() - core.input.register(self, button=core.input.LEFT_MOUSE, - cmd=self.toggle_pihole_status) + core.input.register( + self, button=core.input.LEFT_MOUSE, cmd=self.toggle_pihole_status + ) def pihole_status(self, widget): if self._pihole_status is None: - return 'pi-hole unknown' - return 'pi-hole {}'.format('up {} blocked'.format(self._ads_blocked_today) if self._pihole_status else 'down') + return "pi-hole unknown" + return "pi-hole {}".format( + "up {} blocked".format(self._ads_blocked_today) + if self._pihole_status + else "down" + ) def update_pihole_status(self): try: - data = requests.get(self._pihole_address + '/admin/api.php?summary').json() - self._pihole_status = True if data['status'] == 'enabled' else False - self._ads_blocked_today = data['ads_blocked_today'] + data = requests.get(self._pihole_address + "/admin/api.php?summary").json() + self._pihole_status = True if data["status"] == "enabled" else False + self._ads_blocked_today = data["ads_blocked_today"] except Exception as e: self._pihole_status = None @@ -44,17 +50,24 @@ class Module(core.module.Module): try: req = None if self._pihole_status: - req = requests.get(self._pihole_address + '/admin/api.php?disable&auth=' + self._pihole_pw_hash) + req = requests.get( + self._pihole_address + + "/admin/api.php?disable&auth=" + + self._pihole_pw_hash + ) else: - req = requests.get(self._pihole_address + '/admin/api.php?enable&auth=' + self._pihole_pw_hash) + req = requests.get( + self._pihole_address + + "/admin/api.php?enable&auth=" + + self._pihole_pw_hash + ) if req is not None: if req.status_code == 200: - status = req.json()['status'] - self._pihole_status = False if status == 'disabled' else True + status = req.json()["status"] + self._pihole_status = False if status == "disabled" else True except: pass - def update(self): self.update_pihole_status() @@ -62,7 +75,8 @@ class Module(core.module.Module): if self._pihole_status is None: return [] elif self._pihole_status: - return ['enabled'] - return ['disabled', 'warning'] + return ["enabled"] + return ["disabled", "warning"] + # vim: tabstop=8 expandtab shiftwidth=4 softtabstop=4 diff --git a/modules/contrib/pomodoro.py b/modules/contrib/pomodoro.py index 2c1b175..c7c4666 100644 --- a/modules/contrib/pomodoro.py +++ b/modules/contrib/pomodoro.py @@ -26,97 +26,102 @@ import core.input import util.cli + class Module(core.module.Module): def __init__(self, config, theme): super().__init__(config, theme, core.widget.Widget(self.text)) # Parameters - self.__work_period = int(self.parameter('work', 25)) - self.__break_period = int(self.parameter('break', 5)) - self.__time_format = self.parameter('format', '%m:%s') - self.__notify_cmd = self.parameter('notify', '') + self.__work_period = int(self.parameter("work", 25)) + self.__break_period = int(self.parameter("break", 5)) + self.__time_format = self.parameter("format", "%m:%s") + self.__notify_cmd = self.parameter("notify", "") # TODO: Handle time formats more gracefully. This is kludge. self.display_seconds_p = False self.display_minutes_p = False - if '%s' in self.__time_format: + if "%s" in self.__time_format: self.display_seconds_p = True - if '%m' in self.__time_format: + if "%m" in self.__time_format: self.display_minutes_p = True self.remaining_time = datetime.timedelta(minutes=self.__work_period) self.time = None - self.pomodoro = { 'state':'OFF', 'type': ''} - self.__text = self.remaining_time_str() + self.pomodoro['type'] + self.pomodoro = {"state": "OFF", "type": ""} + self.__text = self.remaining_time_str() + self.pomodoro["type"] + + core.input.register( + self, button=core.input.LEFT_MOUSE, cmd=self.timer_play_pause + ) + core.input.register(self, button=core.input.RIGHT_MOUSE, cmd=self.timer_reset) - core.input.register(self, button=core.input.LEFT_MOUSE, - cmd=self.timer_play_pause) - core.input.register(self, button=core.input.RIGHT_MOUSE, - cmd=self.timer_reset) - def remaining_time_str(self): if self.display_seconds_p and self.display_minutes_p: minutes, seconds = divmod(self.remaining_time.seconds, 60) if not self.display_seconds_p: minutes = ceil(self.remaining_time.seconds / 60) - seconds = 0 + seconds = 0 if not self.display_minutes_p: minutes = 0 seconds = self.remaining_time.seconds - minutes = '{:2d}'.format(minutes) - seconds = '{:02d}'.format(seconds) - return self.__time_format.replace('%m',minutes).replace('%s',seconds)+' ' + minutes = "{:2d}".format(minutes) + seconds = "{:02d}".format(seconds) + return self.__time_format.replace("%m", minutes).replace("%s", seconds) + " " def text(self, widget): - return '{}'.format(self.__text) - + return "{}".format(self.__text) + def update(self): - if self.pomodoro['state'] == 'ON': - timediff = (datetime.datetime.now() - self.time) + if self.pomodoro["state"] == "ON": + timediff = datetime.datetime.now() - self.time if timediff.seconds >= 0: self.remaining_time -= timediff self.time = datetime.datetime.now() if self.remaining_time.total_seconds() <= 0: self.notify() - if self.pomodoro['type'] == 'Work': - self.pomodoro['type'] = 'Break' - self.remaining_time = datetime.timedelta(minutes=self.__break_period) - elif self.pomodoro['type'] == 'Break': - self.pomodoro['type'] = 'Work' + if self.pomodoro["type"] == "Work": + self.pomodoro["type"] = "Break" + self.remaining_time = datetime.timedelta( + minutes=self.__break_period + ) + elif self.pomodoro["type"] == "Break": + self.pomodoro["type"] = "Work" self.remaining_time = datetime.timedelta(minutes=self.__work_period) - self.__text = self.remaining_time_str() + self.pomodoro['type'] - + self.__text = self.remaining_time_str() + self.pomodoro["type"] + def notify(self): if self.__notify_cmd: util.cli.execute(self.__notify_cmd) def timer_play_pause(self, widget): - if self.pomodoro['state'] == 'OFF': - self.pomodoro = {'state': 'ON', 'type': 'Work'} + if self.pomodoro["state"] == "OFF": + self.pomodoro = {"state": "ON", "type": "Work"} self.remaining_time = datetime.timedelta(minutes=self.__work_period) self.time = datetime.datetime.now() - elif self.pomodoro['state'] == 'ON': - self.pomodoro['state'] = 'PAUSED' - self.remaining_time -= (datetime.datetime.now() - self.time) + elif self.pomodoro["state"] == "ON": + self.pomodoro["state"] = "PAUSED" + self.remaining_time -= datetime.datetime.now() - self.time self.time = datetime.datetime.now() - elif self.pomodoro['state'] == 'PAUSED': - self.pomodoro['state'] = 'ON' + elif self.pomodoro["state"] == "PAUSED": + self.pomodoro["state"] = "ON" self.time = datetime.datetime.now() def timer_reset(self, widget): - if self.pomodoro['state'] == 'ON' or self.pomodoro['state'] == 'PAUSED': - self.pomodoro = {'state':'OFF', 'type': '' } + if self.pomodoro["state"] == "ON" or self.pomodoro["state"] == "PAUSED": + self.pomodoro = {"state": "OFF", "type": ""} self.remaining_time = datetime.timedelta(minutes=self.__work_period) def state(self, widget): - state = []; - state.append(self.pomodoro['state'].lower()) - if self.pomodoro['state'] == 'ON' or self.pomodoro['state'] == 'OFF': - state.append(self.pomodoro['type'].lower()) + state = [] + state.append(self.pomodoro["state"].lower()) + if self.pomodoro["state"] == "ON" or self.pomodoro["state"] == "OFF": + state.append(self.pomodoro["type"].lower()) return state + + # vim: tabstop=8 expandtab shiftwidth=4 softtabstop=4 diff --git a/modules/contrib/prime.py b/modules/contrib/prime.py index 2b140e8..abca96d 100644 --- a/modules/contrib/prime.py +++ b/modules/contrib/prime.py @@ -31,36 +31,37 @@ import core.input import util.cli + class Module(core.module.Module): def __init__(self, config, theme): super().__init__(config, theme, core.widget.Widget(self.query)) - core.input.register(self, button=core.input.LEFT_MOUSE, - cmd=self.__chooseNvidia) - core.input.register(self, button=core.input.RIGHT_MOUSE, - cmd=self.__chooseIntel) + core.input.register(self, button=core.input.LEFT_MOUSE, cmd=self.__chooseNvidia) + core.input.register(self, button=core.input.RIGHT_MOUSE, cmd=self.__chooseIntel) - self.nvidiastring = self.parameter('nvidiastring', 'nv') - self.intelstring = self.parameter('intelstring', 'it') + self.nvidiastring = self.parameter("nvidiastring", "nv") + self.intelstring = self.parameter("intelstring", "it") def __chooseNvidia(self, event): - util.cli.execute('sudo prime-select nvidia') + util.cli.execute("sudo prime-select nvidia") def __chooseIntel(self, event): - util.cli.execute('sudo prime-select intel') + util.cli.execute("sudo prime-select intel") def query(self, widget): try: - res = util.cli.execute('prime-select query') + res = util.cli.execute("prime-select query") except RuntimeError: - return 'n/a' + return "n/a" - for line in res.split('\n'): - if not line: continue - if 'nvidia' in line: + for line in res.split("\n"): + if not line: + continue + if "nvidia" in line: return self.nvidiastring - if 'intel' in line: + if "intel" in line: return self.intelstring - return 'n/a' + return "n/a" + # vim: tabstop=8 expandtab shiftwidth=4 softtabstop=4 diff --git a/modules/contrib/progress.py b/modules/contrib/progress.py index 35f210a..c45ec54 100644 --- a/modules/contrib/progress.py +++ b/modules/contrib/progress.py @@ -21,6 +21,7 @@ import util.format import re + class Module(core.module.Module): def __init__(self, config, theme): super().__init__(config, theme, core.widget.Widget(self.get_progress_text)) @@ -28,33 +29,31 @@ class Module(core.module.Module): def get_progress_text(self, widget): if self.update_progress_info(widget): - width = util.format.asint(self.parameter('barwidth', 8)) - count = round((width * widget.get('per')) / 100) - filledchar = self.parameter('barfilledchar', '#') - emptychar = self.parameter('baremptychar', '-') + width = util.format.asint(self.parameter("barwidth", 8)) + count = round((width * widget.get("per")) / 100) + filledchar = self.parameter("barfilledchar", "#") + emptychar = self.parameter("baremptychar", "-") - bar = '[{}{}]'.format( - filledchar * count, - emptychar * (width - count) - ) + bar = "[{}{}]".format(filledchar * count, emptychar * (width - count)) - str_format = self.parameter('format', '{bar} {cmd} {arg}') + str_format = self.parameter("format", "{bar} {cmd} {arg}") return str_format.format( - bar = bar, - pid = widget.get('pid'), - cmd = widget.get('cmd'), - arg = widget.get('arg'), - percentage = widget.get('per'), - quantity = widget.get('qty'), - speed = widget.get('spd'), - time = widget.get('tim') + bar=bar, + pid=widget.get("pid"), + cmd=widget.get("cmd"), + arg=widget.get("arg"), + percentage=widget.get("per"), + quantity=widget.get("qty"), + speed=widget.get("spd"), + time=widget.get("tim"), ) else: - return self.parameter('placeholder', 'n/a') + return self.parameter("placeholder", "n/a") def update_progress_info(self, widget): """Update widget's informations about the copy""" - if not self.__active: return + if not self.__active: + return # These regex extracts following groups: # 1. pid @@ -64,39 +63,44 @@ class Module(core.module.Module): # 5. quantity (.. unit / .. unit formated) # 6. speed # 7. time remaining - extract_nospeed = re.compile('\[ *(\d*)\] ([a-zA-Z]*) (.*)\n\t(\d*\.*\d*)% \((.*)\)\n.*') - extract_wtspeed = re.compile('\[ *(\d*)\] ([a-zA-Z]*) (.*)\n\t(\d*\.*\d*)% \((.*)\) (\d*\.\d .*) remaining (\d*:\d*:\d*)\n.*') + extract_nospeed = re.compile( + "\[ *(\d*)\] ([a-zA-Z]*) (.*)\n\t(\d*\.*\d*)% \((.*)\)\n.*" + ) + extract_wtspeed = re.compile( + "\[ *(\d*)\] ([a-zA-Z]*) (.*)\n\t(\d*\.*\d*)% \((.*)\) (\d*\.\d .*) remaining (\d*:\d*:\d*)\n.*" + ) try: - raw = util.cli.execute('progress -qW 0.1') + raw = util.cli.execute("progress -qW 0.1") result = extract_wtspeed.match(raw) if not result: # Abord speed measures - raw = util.cli.execute('progress -q') + raw = util.cli.execute("progress -q") result = extract_nospeed.match(raw) - widget.set('spd', '???.? B/s') - widget.set('tim', '??:??:??') + widget.set("spd", "???.? B/s") + widget.set("tim", "??:??:??") else: - widget.set('spd', result.group(6)) - widget.set('tim', result.group(7)) + widget.set("spd", result.group(6)) + widget.set("tim", result.group(7)) - widget.set('pid', int(result.group(1))) - widget.set('cmd', result.group(2)) - widget.set('arg', result.group(3)) - widget.set('per', float(result.group(4))) - widget.set('qty', result.group(5)) + widget.set("pid", int(result.group(1))) + widget.set("cmd", result.group(2)) + widget.set("arg", result.group(3)) + widget.set("per", float(result.group(4))) + widget.set("qty", result.group(5)) return True except Exception: return False def update(self): - self.__active = bool(util.cli.execute('progress -q')) + self.__active = bool(util.cli.execute("progress -q")) def state(self, widget): if self.__active: - return 'copying' - return 'pending' + return "copying" + return "pending" + # vim: tabstop=8 expandtab shiftwidth=4 softtabstop=4 diff --git a/modules/contrib/publicip.py b/modules/contrib/publicip.py index 0fd5ac2..17a23e3 100644 --- a/modules/contrib/publicip.py +++ b/modules/contrib/publicip.py @@ -7,13 +7,13 @@ import core.decorators import util.location + class Module(core.module.Module): @core.decorators.every(minutes=60) def __init__(self, config, theme): super().__init__(config, theme, core.widget.Widget(self.public_ip)) - self.__ip = '' - + self.__ip = "" def public_ip(self, widget): return self.__ip @@ -22,6 +22,7 @@ class Module(core.module.Module): try: self.__ip = util.location.public_ip() except Exception: - self.__ip = 'n/a' + self.__ip = "n/a" + # vim: tabstop=8 expandtab shiftwidth=4 softtabstop=4 diff --git a/modules/contrib/rotation.py b/modules/contrib/rotation.py index baf7a4d..dc7f317 100644 --- a/modules/contrib/rotation.py +++ b/modules/contrib/rotation.py @@ -12,7 +12,8 @@ import core.input import util.cli -possible_orientations = ['normal', 'left', 'inverted', 'right'] +possible_orientations = ["normal", "left", "inverted", "right"] + class Module(core.module.Module): def __init__(self, config, theme): @@ -20,37 +21,42 @@ class Module(core.module.Module): def update(self): widgets = self.widgets() - for line in util.cli.execute('xrandr -q').split('\n'): - if not ' connected' in line: + for line in util.cli.execute("xrandr -q").split("\n"): + if not " connected" in line: continue - display = line.split(' ', 2)[0] + display = line.split(" ", 2)[0] - orientation = 'normal' + orientation = "normal" for curr_orient in possible_orientations: - if((line.split(' ')).count(curr_orient) > 1): + if (line.split(" ")).count(curr_orient) > 1: orientation = curr_orient break widget = self.widget(display) if not widget: widget = core.widget.Widget(full_text=display, name=display) - core.input.register(widget, button=core.input.LEFT_MOUSE, cmd=self.__toggle) - widget.set('orientation', orientation) + core.input.register( + widget, button=core.input.LEFT_MOUSE, cmd=self.__toggle + ) + widget.set("orientation", orientation) widgets.append(widget) def state(self, widget): - return widget.get('orientation', 'normal') + return widget.get("orientation", "normal") def __toggle(self, event): - widget = self.widget_by_id(event['instance']) + widget = self.widget_by_id(event["instance"]) # compute new orientation based on current orientation - idx = possible_orientations.index(widget.get('orientation')) + idx = possible_orientations.index(widget.get("orientation")) idx = (idx + 1) % len(possible_orientations) new_orientation = possible_orientations[idx] - widget.set('orientation', new_orientation) + widget.set("orientation", new_orientation) + + util.cli.execute( + "xrandr --output {} --rotation {}".format(widget.name, new_orientation) + ) - util.cli.execute('xrandr --output {} --rotation {}'.format(widget.name, new_orientation)) # vim: tabstop=8 expandtab shiftwidth=4 softtabstop=4 diff --git a/modules/contrib/rss.py b/modules/contrib/rss.py index beaa4ff..d85f7a8 100644 --- a/modules/contrib/rss.py +++ b/modules/contrib/rss.py @@ -30,17 +30,19 @@ import core.input class Module(core.module.Module): REFRESH_DELAY = 600 SCROLL_SPEED = 3 - LAYOUT_STYLES_ITEMS = [[1,1,1],[3,3,2],[2,3,3],[3,2,3]] - HISTORY_FILENAME = '.config/i3/rss.hist' + LAYOUT_STYLES_ITEMS = [[1, 1, 1], [3, 3, 2], [2, 3, 3], [3, 2, 3]] + HISTORY_FILENAME = ".config/i3/rss.hist" def __init__(self, config, theme): super().__init__(config, theme, core.widget.Widget(self.ticker_update)) - self._feeds = self.parameter('feeds', 'https://www.espn.com/espn/rss/news').split(' ') + self._feeds = self.parameter( + "feeds", "https://www.espn.com/espn/rss/news" + ).split(" ") self._feeds_to_update = [] - self._response = '' + self._response = "" - self._max_title_length = int(self.parameter('length', 60)) + self._max_title_length = int(self.parameter("length", 60)) self._items = [] self._current_item = None @@ -51,76 +53,103 @@ class Module(core.module.Module): self._state = [] - self._newspaper_filename = tempfile.mktemp('.html') + self._newspaper_filename = tempfile.mktemp(".html") self._last_refresh = 0 self._last_update = 0 core.input.register(self, button=core.input.LEFT_MOUSE, cmd=self._open) - core.input.register(self, button=core.input.RIGHT_MOUSE, cmd=self._create_newspaper) + core.input.register( + self, button=core.input.RIGHT_MOUSE, cmd=self._create_newspaper + ) - self._history = {'ticker': {}, 'newspaper': {}} + self._history = {"ticker": {}, "newspaper": {}} self._load_history() def _load_history(self): if os.path.isfile(self.HISTORY_FILENAME): - self._history = json.loads(open(self.HISTORY_FILENAME, 'r').read()) + self._history = json.loads(open(self.HISTORY_FILENAME, "r").read()) def _update_history(self, group): - sources = set([i['source'] for i in self._items]) - self._history[group] = dict([[s, [i['title'] for i in self._items if i['source'] == s]] for s in sources]) + sources = set([i["source"] for i in self._items]) + self._history[group] = dict( + [ + [s, [i["title"] for i in self._items if i["source"] == s]] + for s in sources + ] + ) def _save_history(self): if not os.path.exists(os.path.dirname(self.HISTORY_FILENAME)): os.makedirs(os.path.dirname(self.HISTORY_FILENAME)) - open(self.HISTORY_FILENAME, 'w').write(json.dumps(self._history)) + open(self.HISTORY_FILENAME, "w").write(json.dumps(self._history)) def _check_history(self, items, group): for i in items: - i['new'] = not (i['source'] in self._history[group] and i['title'] in self._history[group][i['source']]) + i["new"] = not ( + i["source"] in self._history[group] + and i["title"] in self._history[group][i["source"]] + ) def _open(self, _): if self._current_item: - webbrowser.open(self._current_item['link']) + webbrowser.open(self._current_item["link"]) def _check_for_image(self, entry): - image = next(iter([l['href'] for l in entry['links'] if l['rel'] == 'enclosure']), None) - if not image and 'media_content' in entry: + image = next( + iter([l["href"] for l in entry["links"] if l["rel"] == "enclosure"]), None + ) + if not image and "media_content" in entry: try: - media = sorted(entry['media_content'], key=lambda i: i['height'] if 'height' in i else 0, reverse=True) - image = next(iter([i['url'] for i in media if i['medium'] == 'image']), None) + media = sorted( + entry["media_content"], + key=lambda i: i["height"] if "height" in i else 0, + reverse=True, + ) + image = next( + iter([i["url"] for i in media if i["medium"] == "image"]), None + ) except Exception: pass if not image: - match = re.search(r"]*src\s*=['\']*([^\s^>^'^\']*)['\']*", entry['summary']) + match = re.search( + r"]*src\s*=['\']*([^\s^>^'^\']*)['\']*", entry["summary"] + ) if match: image = match.group(1) - return image if image else '' + return image if image else "" def _remove_tags(self, txt): - return re.sub('<[^>]*>', '', txt) + return re.sub("<[^>]*>", "", txt) def _create_item(self, entry, url, feed): - return {'title': self._remove_tags(entry['title'].replace('\n', ' ')), - 'link': entry['link'], - 'new': True, - 'source': url, - 'summary': self._remove_tags(entry['summary']), - 'feed': feed, - 'image': self._check_for_image(entry), - 'published': time.mktime(entry.published_parsed) if hasattr(entry, 'published_parsed') else 0} + return { + "title": self._remove_tags(entry["title"].replace("\n", " ")), + "link": entry["link"], + "new": True, + "source": url, + "summary": self._remove_tags(entry["summary"]), + "feed": feed, + "image": self._check_for_image(entry), + "published": time.mktime(entry.published_parsed) + if hasattr(entry, "published_parsed") + else 0, + } def _update_items_from_feed(self, url): parser = feedparser.parse(url) - new_items = [self._create_item(entry, url, parser['feed']['title']) for entry in parser['entries']] + new_items = [ + self._create_item(entry, url, parser["feed"]["title"]) + for entry in parser["entries"] + ] # Check history - self._check_history(new_items, 'ticker') + self._check_history(new_items, "ticker") # Remove the previous items - self._items = [i for i in self._items if i['source'] != url] + self._items = [i for i in self._items if i["source"] != url] # Add the new items self._items.extend(new_items) # Sort the items on publish date - self._items.sort(key=lambda i: i['published'], reverse=True) + self._items.sort(key=lambda i: i["published"], reverse=True) def _check_for_refresh(self): if self._feeds_to_update: @@ -129,12 +158,12 @@ class Module(core.module.Module): self._update_items_from_feed(url) if not self._feeds_to_update: - self._update_history('ticker') + self._update_history("ticker") self._save_history() if not self._current_item: self._next_item() - elif time.time()-self._last_refresh >= self.REFRESH_DELAY: + elif time.time() - self._last_refresh >= self.REFRESH_DELAY: # Populate the list with feeds to update self._feeds_to_update = self._feeds[:] # Update the refresh time @@ -149,19 +178,27 @@ class Module(core.module.Module): return # Index of the current element - idx = self._items.index(self._current_item) if self._current_item in self._items else - 1 + idx = ( + self._items.index(self._current_item) + if self._current_item in self._items + else -1 + ) # First show new items, else show next - new_items = [i for i in self._items if i['new']] - self._current_item = next(iter(new_items), self._items[(idx+1) % len(self._items)]) + new_items = [i for i in self._items if i["new"]] + self._current_item = next( + iter(new_items), self._items[(idx + 1) % len(self._items)] + ) def _check_scroll_done(self): # Check if the complete title has been shown - if self._ticker_offset + self._max_title_length > len(self._current_item['title']): + if self._ticker_offset + self._max_title_length > len( + self._current_item["title"] + ): # Do not immediately show next item after scroll self._post_delay -= 1 if self._post_delay == 0: - self._current_item['new'] = False + self._current_item["new"] = False # Mark the previous item as 'old' self._next_item() else: @@ -171,7 +208,7 @@ class Module(core.module.Module): def ticker_update(self, _): # Only update the ticker once a second now = time.time() - if now-self._last_update < 1: + if now - self._last_update < 1: return self._response self._last_update = now @@ -180,18 +217,20 @@ class Module(core.module.Module): # If no items were retrieved, return an empty string if not self._current_item: - return ' '*self._max_title_length + return " " * self._max_title_length # Prepare a substring of the item title - self._response = self._current_item['title'][self._ticker_offset:self._ticker_offset+self._max_title_length] + self._response = self._current_item["title"][ + self._ticker_offset : self._ticker_offset + self._max_title_length + ] # Add spaces if too short self._response = self._response.ljust(self._max_title_length) # Do not immediately scroll if self._pre_delay > 0: # Change state during pre_delay for new items - if self._current_item['new']: - self._state = ['warning'] + if self._current_item["new"]: + self._state = ["warning"] self._pre_delay -= 1 return self._response @@ -205,48 +244,76 @@ class Module(core.module.Module): def _create_news_element(self, item, overlay_title): try: - timestr = '' if item['published'] == 0 else str(time.ctime(item['published'])) + timestr = ( + "" if item["published"] == 0 else str(time.ctime(item["published"])) + ) except Exception as exc: logging.error(str(exc)) raise e - element = "
" + element = "
" element += "
" - element += " " - element += "
"+("" if item['new'] else "")+item['title']+"
" + element += ( + " " + ) + element += ( + "
" + + ("" if item["new"] else "") + + item["title"] + + "
" + ) element += "
" - element += "
"+item['summary']+"
" - element += "
"+item['feed']+""+timestr+"
" + element += "
" + item["summary"] + "
" + element += ( + "
" + + item["feed"] + + "" + + timestr + + "
" + ) element += "
" return element def _create_news_section(self, newspaper_items): style = random.randint(0, 3) - section = "" + section = "
" for i in range(0, 3): section += "" section += "
" for _ in range(0, self.LAYOUT_STYLES_ITEMS[style][i]): if newspaper_items: - section += self._create_news_element(newspaper_items[0], self.LAYOUT_STYLES_ITEMS[style][i] != 3) + section += self._create_news_element( + newspaper_items[0], self.LAYOUT_STYLES_ITEMS[style][i] != 3 + ) del newspaper_items[0] section += "
" return section def _create_newspaper(self, _): - content = '' + content = "" newspaper_items = self._items[:] - self._check_history(newspaper_items, 'newspaper') + self._check_history(newspaper_items, "newspaper") # Make sure new items are always listed first, independent of publish date - newspaper_items.sort(key=lambda i: i['published']+(10000000 if i['new'] else 0), reverse=True) + newspaper_items.sort( + key=lambda i: i["published"] + (10000000 if i["new"] else 0), reverse=True + ) while newspaper_items: content += self._create_news_section(newspaper_items) - open(self._newspaper_filename, 'w').write(HTML_TEMPLATE.replace('[[CONTENT]]', content)) - webbrowser.open('file://'+self._newspaper_filename) - self._update_history('newspaper') + open(self._newspaper_filename, "w").write( + HTML_TEMPLATE.replace("[[CONTENT]]", content) + ) + webbrowser.open("file://" + self._newspaper_filename) + self._update_history("newspaper") self._save_history() + HTML_TEMPLATE = """ diff --git a/modules/contrib/sensors.py b/modules/contrib/sensors.py index 078d7f9..1d490ac 100644 --- a/modules/contrib/sensors.py +++ b/modules/contrib/sensors.py @@ -27,105 +27,119 @@ import core.input import util.cli import util.format + class Module(core.module.Module): def __init__(self, config, theme): super().__init__(config, theme, core.widget.Widget(self.temperature)) - self._temperature = 'unknown' - self._mhz = 'n/a' - self._match_number = int(self.parameter('match_number', '-1')) - self._match_pattern = self.parameter('match_pattern', None) - self._pattern = re.compile(r'^\s*{}:\s*([\d.]+)$'.format(self.parameter('match', 'temp1_input')), re.MULTILINE) - self._json = util.format.asbool(self.parameter('json', False)) - self._freq = util.format.asbool(self.parameter('show_freq', True)) - core.input.register(self, button=core.input.LEFT_MOUSE, cmd='xsensors') + self._temperature = "unknown" + self._mhz = "n/a" + self._match_number = int(self.parameter("match_number", "-1")) + self._match_pattern = self.parameter("match_pattern", None) + self._pattern = re.compile( + r"^\s*{}:\s*([\d.]+)$".format(self.parameter("match", "temp1_input")), + re.MULTILINE, + ) + self._json = util.format.asbool(self.parameter("json", False)) + self._freq = util.format.asbool(self.parameter("show_freq", True)) + core.input.register(self, button=core.input.LEFT_MOUSE, cmd="xsensors") self.determine_method() def determine_method(self): - if self.parameter('path') != None and self._json == False: - self.use_sensors = False # use thermal zone + if self.parameter("path") != None and self._json == False: + self.use_sensors = False # use thermal zone else: # try to use output of sensors -u try: - output = util.cli.execute('sensors -u') + output = util.cli.execute("sensors -u") self.use_sensors = True - log.debug('Sensors command available') + log.debug("Sensors command available") except FileNotFoundError as e: - log.info('Sensors command not available, using /sys/class/thermal/thermal_zone*/') + log.info( + "Sensors command not available, using /sys/class/thermal/thermal_zone*/" + ) self.use_sensors = False def _get_temp_from_sensors(self): if self._json == True: try: - output = json.loads(util.cli.execute('sensors -j')) - for key in self.parameter('path').split('/'): + output = json.loads(util.cli.execute("sensors -j")) + for key in self.parameter("path").split("/"): output = output[key] return int(float(output)) except Exception as e: - logging.error('unable to read sensors: {}'.format(str(e))) - return 'unknown' + logging.error("unable to read sensors: {}".format(str(e))) + return "unknown" else: - output = util.cli.execute('sensors -u') + output = util.cli.execute("sensors -u") if self._match_pattern: - temp_pattern = self.parameter('match', 'temp1_input') - match = re.search(r'{}.+{}:\s*([\d.]+)$'.format(self._match_pattern, temp_pattern), output.replace('\n', '')) + temp_pattern = self.parameter("match", "temp1_input") + match = re.search( + r"{}.+{}:\s*([\d.]+)$".format(self._match_pattern, temp_pattern), + output.replace("\n", ""), + ) if match: return int(float(match.group(1))) else: - return 'unknown' + return "unknown" match = self._pattern.findall(output) if match: return int(float(match[self._match_number])) - return 'unknown' + return "unknown" def get_temp(self): if self.use_sensors: temperature = self._get_temp_from_sensors() - log.debug('Retrieve temperature from sensors -u') + log.debug("Retrieve temperature from sensors -u") else: try: - temperature = open(self.parameter('path', '/sys/class/thermal/thermal_zone0/temp')).read()[:2] - log.debug('retrieved temperature from /sys/class/') + temperature = open( + self.parameter("path", "/sys/class/thermal/thermal_zone0/temp") + ).read()[:2] + log.debug("retrieved temperature from /sys/class/") # TODO: Iterate through all thermal zones to determine the correct one and use its value # https://unix.stackexchange.com/questions/304845/discrepancy-between-number-of-cores-and-thermal-zones-in-sys-class-thermal except IOError: - temperature = 'unknown' - log.info('Can not determine temperature, please install lm-sensors') + temperature = "unknown" + log.info("Can not determine temperature, please install lm-sensors") return temperature def get_mhz(self): mhz = None try: - output = open('/sys/devices/system/cpu/cpufreq/policy0/scaling_cur_freq').read() - mhz = int(float(output)/1000.0) + output = open( + "/sys/devices/system/cpu/cpufreq/policy0/scaling_cur_freq" + ).read() + mhz = int(float(output) / 1000.0) except: - output = open('/proc/cpuinfo').read() - m = re.search(r'cpu MHz\s+:\s+(\d+)', output) + output = open("/proc/cpuinfo").read() + m = re.search(r"cpu MHz\s+:\s+(\d+)", output) if m: mhz = int(m.group(1)) else: - m = re.search(r'BogoMIPS\s+:\s+(\d+)', output) + m = re.search(r"BogoMIPS\s+:\s+(\d+)", output) if m: - return '{} BogoMIPS'.format(int(m.group(1))) + return "{} BogoMIPS".format(int(m.group(1))) if not mhz: - return 'n/a' + return "n/a" if mhz < 1000: - return '{} MHz'.format(mhz) + return "{} MHz".format(mhz) else: - return '{:0.01f} GHz'.format(float(mhz)/1000.0) + return "{:0.01f} GHz".format(float(mhz) / 1000.0) def temperature(self, _): if self._freq: - return u'{}°c @ {}'.format(self._temperature, self._mhz) + return "{}°c @ {}".format(self._temperature, self._mhz) else: - return u'{}°c'.format(self._temperature) + return "{}°c".format(self._temperature) def update(self): self._temperature = self.get_temp() if self._freq: self._mhz = self.get_mhz() + # vim: tabstop=8 expandtab shiftwidth=4 softtabstop=4 diff --git a/modules/contrib/shell.py b/modules/contrib/shell.py index 41e56e1..ad46630 100644 --- a/modules/contrib/shell.py +++ b/modules/contrib/shell.py @@ -33,15 +33,16 @@ import core.input import util.format import util.cli + class Module(core.module.Module): def __init__(self, config, theme): super().__init__(config, theme, core.widget.Widget(self.get_output)) - self.__command = self.parameter('command', 'echo "no command configured"') - self.__async = util.format.asbool(self.parameter('async')) + self.__command = self.parameter("command", 'echo "no command configured"') + self.__async = util.format.asbool(self.parameter("async")) if self.__async: - self.__output = 'please wait...' + self.__output = "please wait..." self.__current_thread = threading.Thread() # LMB and RMB will update output regardless of timer @@ -66,13 +67,16 @@ class Module(core.module.Module): # spawn new thread to execute command and pass callback method to get output from it self.__current_thread = threading.Thread( - target=lambda obj, cmd: obj.set_output(util.cli.execute(cmd, ignore_errors=True)), - args=(self, self.__command) + target=lambda obj, cmd: obj.set_output( + util.cli.execute(cmd, ignore_errors=True) + ), + args=(self, self.__command), ) self.__current_thread.start() def state(self, _): - if self.__output == 'no command configured': - return 'warning' + if self.__output == "no command configured": + return "warning" + # vim: tabstop=4 expandtab shiftwidth=4 softtabstop=4 diff --git a/modules/contrib/shortcut.py b/modules/contrib/shortcut.py index b31a808..ffbebfb 100644 --- a/modules/contrib/shortcut.py +++ b/modules/contrib/shortcut.py @@ -19,22 +19,23 @@ Parameters: import logging -LINK = 'https://github.com/tobi-wan-kenobi/bumblebee-status/wiki' -LABEL = 'Click me' +LINK = "https://github.com/tobi-wan-kenobi/bumblebee-status/wiki" +LABEL = "Click me" import core.module import core.widget import core.input import core.decorators + class Module(core.module.Module): @core.decorators.every(minutes=60) def __init__(self, config, theme): super().__init__(config, theme, []) - self.__labels = self.parameter('labels', '{}'.format(LABEL)) - self.__cmds = self.parameter('cmds', 'firefox {}'.format(LINK)) - self.__delim = self.parameter('delim', ';') + self.__labels = self.parameter("labels", "{}".format(LABEL)) + self.__cmds = self.parameter("cmds", "firefox {}".format(LINK)) + self.__delim = self.parameter("delim", ";") self.update_widgets() @@ -51,9 +52,11 @@ class Module(core.module.Module): # report possible problem as a warning if len(cmds) is not len(labels): - logging.warning('shortcut: the number of commands does not match '\ - 'the number of provided labels.') - logging.warning('cmds : %s, labels : %s', cmds, labels) + logging.warning( + "shortcut: the number of commands does not match " + "the number of provided labels." + ) + logging.warning("cmds : %s, labels : %s", cmds, labels) for idx in range(0, num_shortcuts): cmd = cmds[idx] @@ -64,4 +67,5 @@ class Module(core.module.Module): widgets.append(widget) + # vim: tabstop=8 expandtab shiftwidth=4 softtabstop=4 diff --git a/modules/contrib/smartstatus.py b/modules/contrib/smartstatus.py index 2008165..a403eeb 100644 --- a/modules/contrib/smartstatus.py +++ b/modules/contrib/smartstatus.py @@ -20,99 +20,107 @@ import core.decorators import util.cli + class Module(core.module.Module): @core.decorators.every(minutes=5) def __init__(self, config, theme): super().__init__(config, theme, []) self.devices = self.list_devices() - self.display = self.parameter('display', 'combined') - self.drives = self.parameter('drives', 'sda') + self.display = self.parameter("display", "combined") + self.drives = self.parameter("drives", "sda") self.widgets(self.create_widgets()) def create_widgets(self): widgets = [] - if self.display == 'combined': + if self.display == "combined": widget = core.widget.Widget(module=self) - widget.set('device', 'combined') - widget.set('assessment', self.combined()) + widget.set("device", "combined") + widget.set("assessment", self.combined()) self.output(widget) widgets.append(widget) else: for device in self.devices: - if self.display == 'singles' and device not in self.drives: + if self.display == "singles" and device not in self.drives: continue widget = core.widget.Widget(module=self) - widget.set('device', device) - widget.set('assessment', self.smart(device)) + widget.set("device", device) + widget.set("assessment", self.smart(device)) self.output(widget) widgets.append(widget) return widgets def update(self): for widget in self.widgets(): - device = widget.get('device') - if device == 'combined': - widget.set('assessment', self.combined()) + device = widget.get("device") + if device == "combined": + widget.set("assessment", self.combined()) self.output(widget) else: - widget.set('assessment', self.smart(device)) + widget.set("assessment", self.smart(device)) self.output(widget) def output(self, widget): - device = widget.get('device') - assessment = widget.get('assessment') - widget.full_text('{}: {}'.format(device, assessment)) + device = widget.get("device") + assessment = widget.get("assessment") + widget.full_text("{}: {}".format(device, assessment)) def state(self, widget): states = [] - assessment = widget.get('assessment') - if assessment == 'Pre-fail': - states.append('warning') - if assessment == 'Fail': - states.append('critical') + assessment = widget.get("assessment") + if assessment == "Pre-fail": + states.append("warning") + if assessment == "Fail": + states.append("critical") return states def combined(self): for device in self.devices: result = self.smart(device) - if result == 'Fail': - return 'Fail' - if result == 'Pre-fail': - return 'Pre-fail' - return 'OK' + if result == "Fail": + return "Fail" + if result == "Pre-fail": + return "Pre-fail" + return "OK" def list_devices(self): - for (root, folders, files) in os.walk('/dev'): - if root == '/dev': - devices = {''.join(filter(lambda i: i.isdigit() == False, file)) for file in files if 'sd' in file} - nvme = {file for file in files if('nvme0n' in file and 'p' not in file)} + for (root, folders, files) in os.walk("/dev"): + if root == "/dev": + devices = { + "".join(filter(lambda i: i.isdigit() == False, file)) + for file in files + if "sd" in file + } + nvme = { + file for file in files if ("nvme0n" in file and "p" not in file) + } devices.update(nvme) return devices def smart(self, disk_name): - smartctl = shutil.which('smartctl') + smartctl = shutil.which("smartctl") assessment = None - output = util.cli.execute('sudo {} --health {}'.format( - smartctl, os.path.join('/dev/', disk_name) - )) - output = output.split('\n') + output = util.cli.execute( + "sudo {} --health {}".format(smartctl, os.path.join("/dev/", disk_name)) + ) + output = output.split("\n") line = output[4] - if 'SMART' in line: - if any([i in line for i in ['PASSED', 'OK']]): - assessment = 'OK' + if "SMART" in line: + if any([i in line for i in ["PASSED", "OK"]]): + assessment = "OK" else: - assessment = 'Fail' + assessment = "Fail" - if assessment == 'OK': - output = util.cli.execute('sudo {} -A {}'.format( - smartctl, os.path.join('/dev/', disk_name) - )) - output = output.split('\n') + if assessment == "OK": + output = util.cli.execute( + "sudo {} -A {}".format(smartctl, os.path.join("/dev/", disk_name)) + ) + output = output.split("\n") for line in output: - if 'Pre-fail' in line: - assessment = 'Pre-fail' + if "Pre-fail" in line: + assessment = "Pre-fail" return assessment + # vim: tabstop=8 expandtab shiftwidth=4 softtabstop=4 diff --git a/modules/contrib/spaceapi.py b/modules/contrib/spaceapi.py index 567a605..49ddfd7 100644 --- a/modules/contrib/spaceapi.py +++ b/modules/contrib/spaceapi.py @@ -36,6 +36,7 @@ import core.widget import core.input import core.decorators + def formatStringBuilder(s, json): """ Parses Format Strings @@ -43,14 +44,14 @@ def formatStringBuilder(s, json): s -> format string json -> the spaceapi response object """ - identifiers = re.findall('%%.*?%%', s) + identifiers = re.findall("%%.*?%%", s) for i in identifiers: ic = i[2:-2] # Discard %% - j = ic.split('%') + j = ic.split("%") # Only neither of, or both true AND false may be overwritten if len(j) != 3 and len(j) != 1: - return 'INVALID FORMAT STRING' + return "INVALID FORMAT STRING" if len(j) == 1: # no overwrite s = s.replace(i, json[j[0]]) @@ -66,30 +67,28 @@ class Module(core.module.Module): def __init__(self, config, theme): super().__init__(config, theme, core.widget.Widget(self.getState)) - core.input.register( - self, button=core.input.LEFT_MOUSE, cmd=self.__forceReload - ) + core.input.register(self, button=core.input.LEFT_MOUSE, cmd=self.__forceReload) self.__data = {} self.__error = None self.__thread = None # The URL representing the api endpoint - self.__url = self.parameter('url', default='http://club.entropia.de/spaceapi') + self.__url = self.parameter("url", default="http://club.entropia.de/spaceapi") self._format = self.parameter( - 'format', default=u' %%space%%: %%state.open%Open%Closed%%' + "format", default=" %%space%%: %%state.open%Open%Closed%%" ) def state(self, widget): try: if self.__error is not None: - return ['critical'] - elif self.__data['state.open']: - return ['warning'] + return ["critical"] + elif self.__data["state.open"]: + return ["warning"] else: return [] except KeyError: - return ['critical'] + return ["critical"] def update(self): if not self.__thread or self.__thread.is_alive() == False: @@ -104,7 +103,7 @@ class Module(core.module.Module): try: text = formatStringBuilder(self._format, self.__data) except KeyError: - text = 'KeyError' + text = "KeyError" return text def get_api_async(self): @@ -115,19 +114,19 @@ class Module(core.module.Module): self.__data = self.__flatten(json.loads(request.text)) self.__error = None except requests.exceptions.Timeout: - self.__error = 'Timeout' + self.__error = "Timeout" except requests.exceptions.HTTPError: - self.__error = 'HTTP Error' + self.__error = "HTTP Error" except ValueError: - self.__error = 'Not a JSON response' - core.event.trigger('update', [ self.id ], redraw_only=True) + self.__error = "Not a JSON response" + core.event.trigger("update", [self.id], redraw_only=True) # left_mouse_button handler def __forceReload(self, event): if self.__thread: self.__thread.raise_exception() - self.__error = 'RELOADING' - core.event.trigger('update', [ self.id ], redraw_only=True) + self.__error = "RELOADING" + core.event.trigger("update", [self.id], redraw_only=True) # Flattens the JSON structure recursively, e.g. ['space']['open'] # becomes ['space.open'] @@ -138,7 +137,7 @@ class Module(core.module.Module): if type(value) is dict: flattened_key = self.__flatten(value) for fk in flattened_key: - out[key + '.' + fk] = flattened_key[fk] + out[key + "." + fk] = flattened_key[fk] else: out[key] = value return out diff --git a/modules/contrib/spotify.py b/modules/contrib/spotify.py index 3982ee7..7c02129 100644 --- a/modules/contrib/spotify.py +++ b/modules/contrib/spotify.py @@ -21,59 +21,69 @@ import core.widget import core.input import core.decorators + class Module(core.module.Module): def __init__(self, config, theme): super().__init__(config, theme, core.widget.Widget(self.spotify)) - buttons = {'LEFT_CLICK':core.input.LEFT_MOUSE, - 'RIGHT_CLICK':core.input.RIGHT_MOUSE, - 'MIDDLE_CLICK':core.input.MIDDLE_MOUSE, - 'SCROLL_UP':core.input.WHEEL_UP, - 'SCROLL_DOWN':core.input.WHEEL_DOWN, - } - - self.__song = '' - self.__format = self.parameter('format', '{artist} - {title}') - prev_button = self.parameter('previous', 'LEFT_CLICK') - next_button = self.parameter('next', 'RIGHT_CLICK') - pause_button = self.parameter('pause', 'MIDDLE_CLICK') + buttons = { + "LEFT_CLICK": core.input.LEFT_MOUSE, + "RIGHT_CLICK": core.input.RIGHT_MOUSE, + "MIDDLE_CLICK": core.input.MIDDLE_MOUSE, + "SCROLL_UP": core.input.WHEEL_UP, + "SCROLL_DOWN": core.input.WHEEL_DOWN, + } - cmd = 'dbus-send --session --type=method_call --dest=org.mpris.MediaPlayer2.spotify \ - /org/mpris/MediaPlayer2 org.mpris.MediaPlayer2.Player.' - core.input.register(self, button=buttons[prev_button], - cmd=cmd + 'Previous') - core.input.register(self, button=buttons[next_button], - cmd=cmd + 'Next') - core.input.register(self, button=buttons[pause_button], - cmd=cmd + 'PlayPause') + self.__song = "" + self.__format = self.parameter("format", "{artist} - {title}") + prev_button = self.parameter("previous", "LEFT_CLICK") + next_button = self.parameter("next", "RIGHT_CLICK") + pause_button = self.parameter("pause", "MIDDLE_CLICK") + + cmd = "dbus-send --session --type=method_call --dest=org.mpris.MediaPlayer2.spotify \ + /org/mpris/MediaPlayer2 org.mpris.MediaPlayer2.Player." + core.input.register(self, button=buttons[prev_button], cmd=cmd + "Previous") + core.input.register(self, button=buttons[next_button], cmd=cmd + "Next") + core.input.register(self, button=buttons[pause_button], cmd=cmd + "PlayPause") @core.decorators.scrollable def spotify(self, widget): return self.string_song def hidden(self): - return self.string_song == '' + return self.string_song == "" def update(self): try: bus = dbus.SessionBus() - spotify = bus.get_object('org.mpris.MediaPlayer2.spotify', '/org/mpris/MediaPlayer2') - spotify_iface = dbus.Interface(spotify, 'org.freedesktop.DBus.Properties') - props = spotify_iface.Get('org.mpris.MediaPlayer2.Player', 'Metadata') - playback_status = str(spotify_iface.Get('org.mpris.MediaPlayer2.Player', 'PlaybackStatus')) - self.__song = self.__format.format(album=str(props.get('xesam:album')), - title=str(props.get('xesam:title')), - artist=','.join(props.get('xesam:artist')), - trackNumber=str(props.get('xesam:trackNumber')), - playbackStatus=u'\u25B6' if playback_status=='Playing' else u'\u258D\u258D' if playback_status=='Paused' else '',) - + spotify = bus.get_object( + "org.mpris.MediaPlayer2.spotify", "/org/mpris/MediaPlayer2" + ) + spotify_iface = dbus.Interface(spotify, "org.freedesktop.DBus.Properties") + props = spotify_iface.Get("org.mpris.MediaPlayer2.Player", "Metadata") + playback_status = str( + spotify_iface.Get("org.mpris.MediaPlayer2.Player", "PlaybackStatus") + ) + self.__song = self.__format.format( + album=str(props.get("xesam:album")), + title=str(props.get("xesam:title")), + artist=",".join(props.get("xesam:artist")), + trackNumber=str(props.get("xesam:trackNumber")), + playbackStatus="\u25B6" + if playback_status == "Playing" + else "\u258D\u258D" + if playback_status == "Paused" + else "", + ) + except Exception: - self.__song = '' + self.__song = "" @property def string_song(self): if sys.version_info.major < 3: return unicode(self.__song) return str(self.__song) - + + # vim: tabstop=8 expandtab shiftwidth=4 softtabstop=4 diff --git a/modules/contrib/stock.py b/modules/contrib/stock.py index 7f62c18..d225968 100644 --- a/modules/contrib/stock.py +++ b/modules/contrib/stock.py @@ -22,39 +22,44 @@ import core.decorators import util.format + class Module(core.module.Module): @core.decorators.every(hours=1) def __init__(self, config, theme): super().__init__(config, theme, core.widget.Widget(self.value)) - self.__symbols = self.parameter('symbols', '') - self.__change = util.format.asbool(self.parameter('change', True)) + self.__symbols = self.parameter("symbols", "") + self.__change = util.format.asbool(self.parameter("change", True)) self.__value = None def value(self, widget): results = [] if not self.__value: - return 'n/a' + return "n/a" data = json.loads(self.__value) - for symbol in data['quoteResponse']['result']: - valkey = 'regularMarketChange' if self.__change else 'regularMarketPrice' - sym = symbol.get('symbol', 'n/a') - currency = symbol.get('currency', 'USD') - val = 'n/a' if not valkey in symbol else '{:.2f}'.format(symbol[valkey]) - results.append('{} {} {}'.format(sym, val, currency)) - return u' '.join(results) + for symbol in data["quoteResponse"]["result"]: + valkey = "regularMarketChange" if self.__change else "regularMarketPrice" + sym = symbol.get("symbol", "n/a") + currency = symbol.get("currency", "USD") + val = "n/a" if not valkey in symbol else "{:.2f}".format(symbol[valkey]) + results.append("{} {} {}".format(sym, val, currency)) + return " ".join(results) def fetch(self): if self.__symbols: - url = 'https://query1.finance.yahoo.com/v7/finance/quote?symbols=' - url += self.__symbols + '&fields=regularMarketPrice,currency,regularMarketChange' + url = "https://query1.finance.yahoo.com/v7/finance/quote?symbols=" + url += ( + self.__symbols + + "&fields=regularMarketPrice,currency,regularMarketChange" + ) return urllib.request.urlopen(url).read().strip() else: - logging.error('unable to retrieve stock exchange rate') + logging.error("unable to retrieve stock exchange rate") return None def update(self): self.__value = self.fetch() + # vim: tabstop=8 expandtab shiftwidth=4 softtabstop=4 diff --git a/modules/contrib/sun.py b/modules/contrib/sun.py index 75ee7a6..4276df2 100644 --- a/modules/contrib/sun.py +++ b/modules/contrib/sun.py @@ -23,13 +23,14 @@ import core.decorators import util.location + class Module(core.module.Module): @core.decorators.every(hours=1) def __init__(self, config, theme): super().__init__(config, theme, core.widget.Widget(self.suntimes)) - lat = self.parameter('lat', None) - lon = self.parameter('lon', None) + lat = self.parameter("lat", None) + lon = self.parameter("lon", None) self.__sun = None if not lat or not lon: @@ -40,12 +41,13 @@ class Module(core.module.Module): def suntimes(self, _): if self.__sunset and self.__sunrise: if self.__isup: - return u'\u21A7{} \u21A5{}'.format( - self.__sunset.strftime('%H:%M'), - self.__sunrise.strftime('%H:%M')) - return u'\u21A5{} \u21A7{}'.format(self.__sunrise.strftime('%H:%M'), - self.__sunset.strftime('%H:%M')) - return 'n/a' + return "\u21A7{} \u21A5{}".format( + self.__sunset.strftime("%H:%M"), self.__sunrise.strftime("%H:%M") + ) + return "\u21A5{} \u21A7{}".format( + self.__sunrise.strftime("%H:%M"), self.__sunset.strftime("%H:%M") + ) + return "n/a" def __calculate_times(self): self.__isup = False @@ -55,13 +57,13 @@ class Module(core.module.Module): try: self.__sunrise = self.__sun.get_local_sunrise_time() except SunTimeException: - self.__sunrise = 'no sunrise' + self.__sunrise = "no sunrise" order_matters = False try: self.__sunset = self.__sun.get_local_sunset_time() except SunTimeException: - self.__sunset = 'no sunset' + self.__sunset = "no sunset" order_matters = False if not order_matters: @@ -74,19 +76,20 @@ class Module(core.module.Module): self.__sunrise = self.__sun.get_local_sunrise_time(tomorrow) self.__sunset = self.__sun.get_local_sunset_time(tomorrow) except SunTimeException: - self.__sunrise = 'no sunrise' - self.__sunset = 'no sunset' + self.__sunrise = "no sunrise" + self.__sunset = "no sunset" elif now > self.__sunrise: tomorrow = (now + datetime.timedelta(days=1)).date() try: self.__sunrise = self.__sun.get_local_sunrise_time(tomorrow) except SunTimeException: - self.__sunrise = 'no sunrise' + self.__sunrise = "no sunrise" return self.__isup = True def update(self): self.__calculate_times() + # vim: tabstop=8 expandtab shiftwidth=4 softtabstop=4 diff --git a/modules/contrib/system.py b/modules/contrib/system.py index 1ffd750..3b942c2 100644 --- a/modules/contrib/system.py +++ b/modules/contrib/system.py @@ -1,4 +1,4 @@ -# -*- coding: utf-8 -*- +# -*- coding: utf-8 -*- # pylint: disable=C0111,R0903 """ system module @@ -28,7 +28,7 @@ try: import tkinter as tk from tkinter import messagebox as tkmessagebox except ImportError: - logging.warning('failed to import tkinter - bumblebee popups won\'t work!') + logging.warning("failed to import tkinter - bumblebee popups won't work!") import core.module import core.widget @@ -39,18 +39,18 @@ import util.cli import util.popup import util.format + class Module(core.module.Module): @core.decorators.every(minutes=60) def __init__(self, config, theme): super().__init__(config, theme, core.widget.Widget(self.text)) - self.__confirm = util.format.asbool(self.parameter('confirm', True)) + self.__confirm = util.format.asbool(self.parameter("confirm", True)) - core.input.register(self, button=core.input.LEFT_MOUSE, - cmd=self.popup) + core.input.register(self, button=core.input.LEFT_MOUSE, cmd=self.popup) def text(self, widget): - return '' + return "" def __on_command(self, header, text, command): do_it = True @@ -58,33 +58,56 @@ class Module(core.module.Module): root = tk.Tk() root.withdraw() root.focus_set() - + do_it = tkmessagebox.askyesno(header, text) root.destroy() - - if do_it: - util.cli.execute(command) + if do_it: + util.cli.execute(command) def popup(self, widget): menu = util.popup.menu() - reboot_cmd = self.parameter('reboot', 'reboot') - shutdown_cmd = self.parameter('shutdown', 'shutdown -h now') - logout_cmd = self.parameter('logout', 'i3exit logout') - switch_user_cmd = self.parameter('switch_user', 'i3exit switch_user') - lock_cmd = self.parameter('lock', 'i3exit lock') - suspend_cmd = self.parameter('suspend', 'i3exit suspend') - hibernate_cmd = self.parameter('hibernate', 'i3exit hibernate') + reboot_cmd = self.parameter("reboot", "reboot") + shutdown_cmd = self.parameter("shutdown", "shutdown -h now") + logout_cmd = self.parameter("logout", "i3exit logout") + switch_user_cmd = self.parameter("switch_user", "i3exit switch_user") + lock_cmd = self.parameter("lock", "i3exit lock") + suspend_cmd = self.parameter("suspend", "i3exit suspend") + hibernate_cmd = self.parameter("hibernate", "i3exit hibernate") - menu.add_menuitem('shutdown', callback=functools.partial(self.__on_command, 'Shutdown', 'Shutdown?', shutdown_cmd)) - menu.add_menuitem('reboot', callback=functools.partial(self.__on_command, 'Reboot', 'Reboot?', reboot_cmd)) - menu.add_menuitem('log out', callback=functools.partial(self.__on_command, 'Log out', 'Log out?', 'i3exit logout')) + menu.add_menuitem( + "shutdown", + callback=functools.partial( + self.__on_command, "Shutdown", "Shutdown?", shutdown_cmd + ), + ) + menu.add_menuitem( + "reboot", + callback=functools.partial( + self.__on_command, "Reboot", "Reboot?", reboot_cmd + ), + ) + menu.add_menuitem( + "log out", + callback=functools.partial( + self.__on_command, "Log out", "Log out?", "i3exit logout" + ), + ) # don't ask for these - menu.add_menuitem('switch user', callback=functools.partial(util.cli.execute, switch_user_cmd)) - menu.add_menuitem('lock', callback=functools.partial(util.cli.execute, lock_cmd)) - menu.add_menuitem('suspend', callback=functools.partial(util.cli.execute, suspend_cmd)) - menu.add_menuitem('hibernate', callback=functools.partial(util.cli.execute, hibernate_cmd)) + menu.add_menuitem( + "switch user", callback=functools.partial(util.cli.execute, switch_user_cmd) + ) + menu.add_menuitem( + "lock", callback=functools.partial(util.cli.execute, lock_cmd) + ) + menu.add_menuitem( + "suspend", callback=functools.partial(util.cli.execute, suspend_cmd) + ) + menu.add_menuitem( + "hibernate", callback=functools.partial(util.cli.execute, hibernate_cmd) + ) menu.show(widget, 0, 0) + # vim: tabstop=8 expandtab shiftwidth=4 softtabstop=4 diff --git a/modules/contrib/taskwarrior.py b/modules/contrib/taskwarrior.py index 958463f..b2c058c 100644 --- a/modules/contrib/taskwarrior.py +++ b/modules/contrib/taskwarrior.py @@ -13,24 +13,26 @@ import core.module import core.widget import core.decorators + class Module(core.module.Module): def __init__(self, config, theme): super().__init__(config, theme, core.widget.Widget(self.output)) - self.__pending_tasks = '0' + self.__pending_tasks = "0" def update(self): """Return a string with the number of pending tasks from TaskWarrior.""" try: - taskrc = self.parameter('taskrc', '~/.taskrc') + taskrc = self.parameter("taskrc", "~/.taskrc") w = TaskWarrior(config_filename=taskrc) - pending_tasks = w.filter_tasks({'status': 'pending'}) + pending_tasks = w.filter_tasks({"status": "pending"}) self.__pending_tasks = str(len(pending_tasks)) except: - self.__pending_tasks = 'n/a' + self.__pending_tasks = "n/a" def output(self, _): """Format the task counter to output in bumblebee.""" - return '{}'.format(self.__pending_tasks) + return "{}".format(self.__pending_tasks) + # vim: tabstop=8 expandtab shiftwidth=4 softtabstop=4 diff --git a/modules/contrib/timetz.py b/modules/contrib/timetz.py index ea96fe1..d1da5cb 100644 --- a/modules/contrib/timetz.py +++ b/modules/contrib/timetz.py @@ -10,12 +10,14 @@ Parameters: import core.decorators from .datetimetz import Module + class Module(Module): - @core.decorators.every(seconds=59) # ensures one update per minute + @core.decorators.every(seconds=59) # ensures one update per minute def __init__(self, config, theme): super().__init__(config, theme) def default_format(self): - return '%X %Z' + return "%X %Z" + # vim: tabstop=8 expandtab shiftwidth=4 softtabstop=4 diff --git a/modules/contrib/title.py b/modules/contrib/title.py index 25c674c..74338c2 100644 --- a/modules/contrib/title.py +++ b/modules/contrib/title.py @@ -18,7 +18,7 @@ try: except ImportError: pass -no_title = 'n/a' +no_title = "n/a" import core.module import core.widget @@ -26,24 +26,32 @@ import core.decorators import util.format + class Module(core.module.Module): def __init__(self, config, theme): super().__init__(config, theme, []) # parsing of parameters - self.__scroll = util.format.asbool(self.parameter('scroll', False)) - self.__max = int(self.parameter('max', 64)) - self.__placeholder = self.parameter('placeholder', '...') - self.__title = '' + self.__scroll = util.format.asbool(self.parameter("scroll", False)) + self.__max = int(self.parameter("max", 64)) + self.__placeholder = self.parameter("placeholder", "...") + self.__title = "" # set output of the module - self.widgets([core.widget.Widget(full_text= - self.__scrolling_focused_title if self.__scroll else self.__focused_title)]) + self.widgets( + [ + core.widget.Widget( + full_text=self.__scrolling_focused_title + if self.__scroll + else self.__focused_title + ) + ] + ) # create a connection with i3ipc self.__i3 = i3ipc.Connection() # event is called both on focus change and title change - self.__i3.on('window', lambda __p_i3, __p_e: self.__pollTitle()) + self.__i3.on("window", lambda __p_i3, __p_e: self.__pollTitle()) # begin listening for events threading.Thread(target=self.__i3.main).start() @@ -69,9 +77,12 @@ class Module(core.module.Module): if not self.__scroll: # cut the text if it is too long if len(self.__full_title) > self.__max: - self.__title = self.__full_title[0:self.__max - len(self.__placeholder)] - self.__title = '{}{}'.format(self.__title, self.__placeholder) + self.__title = self.__full_title[ + 0 : self.__max - len(self.__placeholder) + ] + self.__title = "{}{}".format(self.__title, self.__placeholder) else: self.__title = self.__full_title + # vim: tabstop=8 expandtab shiftwidth=4 softtabstop=4 diff --git a/modules/contrib/todo.py b/modules/contrib/todo.py index 3be3b82..15120ed 100644 --- a/modules/contrib/todo.py +++ b/modules/contrib/todo.py @@ -12,24 +12,27 @@ import core.module import core.widget import core.input + class Module(core.module.Module): def __init__(self, config, theme): super().__init__(config, theme, core.widget.Widget(self.output)) - self.__doc = os.path.expanduser(self.parameter('file', '~/Documents/todo.txt')) + self.__doc = os.path.expanduser(self.parameter("file", "~/Documents/todo.txt")) self.__todos = self.count_items() - core.input.register(self, button=core.input.LEFT_MOUSE, cmd='xdg-open {}'.format(self.__doc)) + core.input.register( + self, button=core.input.LEFT_MOUSE, cmd="xdg-open {}".format(self.__doc) + ) def output(self, widget): - return str(self.__todos) + return str(self.__todos) def update(self): - self.__todos = self.count_items() + self.__todos = self.count_items() def state(self, widgets): if self.__todos == 0: - return 'empty' - return 'items' + return "empty" + return "items" def count_items(self): try: @@ -37,8 +40,9 @@ class Module(core.module.Module): with open(self.__doc) as f: for i, l in enumerate(f): pass - return i+1 + return i + 1 except Exception: return 0 + # vim: tabstop=8 expandtab shiftwidth=4 softtabstop=4 diff --git a/modules/contrib/traffic.py b/modules/contrib/traffic.py index a4a66e2..f1dfbcc 100644 --- a/modules/contrib/traffic.py +++ b/modules/contrib/traffic.py @@ -24,37 +24,47 @@ import core.widget import util.format import util.graph + class Module(core.module.Module): def __init__(self, config, theme): widgets = [] super().__init__(config, theme, widgets) - self._exclude = tuple(filter(len, util.format.aslist(self.parameter('exclude', 'lo,virbr,docker,vboxnet,veth')))) - self._status = '' + self._exclude = tuple( + filter( + len, + util.format.aslist( + self.parameter("exclude", "lo,virbr,docker,vboxnet,veth") + ), + ) + ) + self._status = "" - self._showname = util.format.asbool(self.parameter('showname', True)) - self._format = self.parameter('format', '{:.2f}') + self._showname = util.format.asbool(self.parameter("showname", True)) + self._format = self.parameter("format", "{:.2f}") self._prev = {} self._states = {} self._lastcheck = 0 - self._states['include'] = [] - self._states['exclude'] = [] - for state in tuple(filter(len, util.format.aslist(self.parameter('states', '')))): - if state[0] == '^': - self._states['exclude'].append(state[1:]) + self._states["include"] = [] + self._states["exclude"] = [] + for state in tuple( + filter(len, util.format.aslist(self.parameter("states", ""))) + ): + if state[0] == "^": + self._states["exclude"].append(state[1:]) else: - self._states['include'].append(state) - self._graphlen = int(self.parameter('graphlen', 0)) + self._states["include"].append(state) + self._graphlen = int(self.parameter("graphlen", 0)) if self._graphlen > 0: self._graphdata = {} self._first_run = True self._update_widgets(widgets) def state(self, widget): - if 'traffic.rx' in widget.name: - return 'rx' - if 'traffic.tx' in widget.name: - return 'tx' + if "traffic.rx" in widget.name: + return "rx" + if "traffic.tx" in widget.name: + return "tx" return self._status def update(self): @@ -74,8 +84,8 @@ class Module(core.module.Module): retval = [] try: for ip in netifaces.ifaddresses(intf).get(netifaces.AF_INET, []): - if ip.get('addr', '') != '': - retval.append(ip.get('addr')) + if ip.get("addr", "") != "": + retval.append(ip.get("addr")) except Exception: return [] return retval @@ -85,66 +95,80 @@ class Module(core.module.Module): computes theme.minwidth string based on traffic.format and traffic.graphlen parameters """ - minwidth_str = '' + minwidth_str = "" if self._graphlen > 0: graph_len = int(self._graphlen / 2) - graph_prefix = '0' * graph_len + graph_prefix = "0" * graph_len minwidth_str += graph_prefix - minwidth_str += '1000' + minwidth_str += "1000" try: - length = int(re.match('{:\.(\d+)f}', self._format).group(1)) + length = int(re.match("{:\.(\d+)f}", self._format).group(1)) if length > 0: - minwidth_str += '.' + '0' * length + minwidth_str += "." + "0" * length except AttributeError: # return default value - return '1000.00KiB/s' + return "1000.00KiB/s" finally: - minwidth_str += 'KiB/s' + minwidth_str += "KiB/s" return minwidth_str def _update_widgets(self, widgets): - interfaces = [i for i in netifaces.interfaces() if not i.startswith(self._exclude)] + interfaces = [ + i for i in netifaces.interfaces() if not i.startswith(self._exclude) + ] del widgets[:] counters = psutil.net_io_counters(pernic=True) now = time.time() timediff = now - (self._lastcheck if self._lastcheck else now) - if timediff <= 0: timediff = 1 + if timediff <= 0: + timediff = 1 self._lastcheck = now for interface in interfaces: if self._graphlen > 0: if interface not in self._graphdata: self._graphdata[interface] = { - 'rx': [0] * self._graphlen, - 'tx': [0] * self._graphlen} - if not interface: interface = 'lo' - state = 'down' + "rx": [0] * self._graphlen, + "tx": [0] * self._graphlen, + } + if not interface: + interface = "lo" + state = "down" if len(self.get_addresses(interface)) > 0: - state = 'up' - elif util.format.asbool(self.parameter('hide_down', True)): + state = "up" + elif util.format.asbool(self.parameter("hide_down", True)): continue - if len(self._states['exclude']) > 0 and state in self._states['exclude']: continue - if len(self._states['include']) > 0 and state not in self._states['include']: continue + if len(self._states["exclude"]) > 0 and state in self._states["exclude"]: + continue + if ( + len(self._states["include"]) > 0 + and state not in self._states["include"] + ): + continue data = { - 'rx': counters[interface].bytes_recv, - 'tx': counters[interface].bytes_sent, + "rx": counters[interface].bytes_recv, + "tx": counters[interface].bytes_sent, } - name = 'traffic-{}'.format(interface) + name = "traffic-{}".format(interface) if self._showname: - self.create_widget(widgets, name, interface) + self.create_widget(widgets, name, interface) - for direction in ['rx', 'tx']: - name = 'traffic.{}-{}'.format(direction, interface) - widget = self.create_widget(widgets, name, attributes={'theme.minwidth': self.get_minwidth_str()}) + for direction in ["rx", "tx"]: + name = "traffic.{}-{}".format(direction, interface) + widget = self.create_widget( + widgets, + name, + attributes={"theme.minwidth": self.get_minwidth_str()}, + ) prev = self._prev.get(name, 0) - bspeed = (int(data[direction]) - int(prev))/timediff + bspeed = (int(data[direction]) - int(prev)) / timediff speed = util.format.byte(bspeed, self._format) - txtspeed = '{0}/s'.format(speed) + txtspeed = "{0}/s".format(speed) if self._graphlen > 0: # skip first value returned by psutil, because it is # giant and ruins the grapth ratio until it gets pushed @@ -152,10 +176,16 @@ class Module(core.module.Module): if self._first_run is True: self._first_run = False else: - self._graphdata[interface][direction] = self._graphdata[interface][direction][1:] + self._graphdata[interface][direction] = self._graphdata[ + interface + ][direction][1:] self._graphdata[interface][direction].append(bspeed) - txtspeed = '{}{}'.format(util.graph.braille(self._graphdata[interface][direction]), txtspeed) - widget.full_text(txtspeed) + txtspeed = "{}{}".format( + util.graph.braille(self._graphdata[interface][direction]), + txtspeed, + ) + widget.full_text(txtspeed) self._prev[name] = data[direction] + # vim: tabstop=8 expandtab shiftwidth=4 softtabstop=4 diff --git a/modules/contrib/twmn.py b/modules/contrib/twmn.py index bda1c96..1a2d5a9 100644 --- a/modules/contrib/twmn.py +++ b/modules/contrib/twmn.py @@ -1,4 +1,4 @@ -#pylint: disable=C0111,R0903 +# pylint: disable=C0111,R0903 """Toggle twmn notifications.""" @@ -9,14 +9,15 @@ import core.decorators import util.cli + class Module(core.module.Module): @core.decorators.every(minutes=60) def __init__(self, config, theme): - super().__init__(config, theme, core.widget.Widget('')) + super().__init__(config, theme, core.widget.Widget("")) self.__paused = False # Make sure that twmn is currently not paused - util.cli.execute('killall -SIGUSR2 twmnd', ignore_errors=True) + util.cli.execute("killall -SIGUSR2 twmnd", ignore_errors=True) core.input.register(self, button=core.input.LEFT_MOUSE, cmd=self.toggle_status) def toggle_status(self, event): @@ -24,15 +25,16 @@ class Module(core.module.Module): try: if self.__paused: - util.cli.execute('systemctl --user start twmnd') + util.cli.execute("systemctl --user start twmnd") else: - util.cli.execute('systemctl --user stop twmnd') + util.cli.execute("systemctl --user stop twmnd") except: - self.__paused = not self.__paused # toggling failed + self.__paused = not self.__paused # toggling failed def state(self, widget): if self.__paused: - return ['muted'] - return ['unmuted'] + return ["muted"] + return ["unmuted"] + # vim: tabstop=8 expandtab shiftwidth=4 softtabstop=4 diff --git a/modules/contrib/uptime.py b/modules/contrib/uptime.py index dd39da3..4a9d21f 100644 --- a/modules/contrib/uptime.py +++ b/modules/contrib/uptime.py @@ -7,17 +7,19 @@ from datetime import timedelta import core.module import core.widget + class Module(core.module.Module): def __init__(self, config, theme): super().__init__(config, theme, core.widget.Widget(self.output)) - self.__uptime = '' + self.__uptime = "" def output(self, _): - return '{}'.format(self.__uptime) + return "{}".format(self.__uptime) def update(self): - with open('/proc/uptime', 'r') as f: + with open("/proc/uptime", "r") as f: uptime_seconds = int(float(f.readline().split()[0])) - self.__uptime = timedelta(seconds = uptime_seconds) + self.__uptime = timedelta(seconds=uptime_seconds) + # vim: tabstop=8 expandtab shiftwidth=4 softtabstop=4 diff --git a/modules/contrib/vpn.py b/modules/contrib/vpn.py index c403487..e5d102b 100644 --- a/modules/contrib/vpn.py +++ b/modules/contrib/vpn.py @@ -25,6 +25,7 @@ import core.input import util.cli import util.popup + class Module(core.module.Module): def __init__(self, config, theme): super().__init__(config, theme, core.widget.Widget(self.vpn_status)) @@ -32,74 +33,82 @@ class Module(core.module.Module): self.__connected_vpn_profile = None self.__selected_vpn_profile = None - res = util.cli.execute('nmcli -g NAME,TYPE c') + res = util.cli.execute("nmcli -g NAME,TYPE c") lines = res.splitlines() self.__vpn_profiles = [] for line in lines: - info = line.split(':') + info = line.split(":") try: if self.__isvpn(info[1]): self.__vpn_profiles.append(info[0]) except: pass - core.input.register(self, button=core.input.LEFT_MOUSE, - cmd=self.popup) + core.input.register(self, button=core.input.LEFT_MOUSE, cmd=self.popup) def __isvpn(self, connection_type): - return connection_type in ['vpn', 'wireguard'] + return connection_type in ["vpn", "wireguard"] def update(self): try: - res = util.cli.execute('nmcli -g NAME,TYPE,DEVICE con') + res = util.cli.execute("nmcli -g NAME,TYPE,DEVICE con") lines = res.splitlines() self.__connected_vpn_profile = None for line in lines: - info = line.split(':') - if self.__isvpn(info[1]) and info[2] != '': + info = line.split(":") + if self.__isvpn(info[1]) and info[2] != "": self.__connected_vpn_profile = info[0] except Exception as e: - logging.exception('Could not get VPN status') + logging.exception("Could not get VPN status") self.__connected_vpn_profile = None def vpn_status(self, widget): if self.__connected_vpn_profile is None: - return 'off' + return "off" return self.__connected_vpn_profile def __on_vpndisconnect(self): try: - util.cli.execute('nmcli c down \'{vpn}\'' - .format(vpn=self.__connected_vpn_profile)) + util.cli.execute( + "nmcli c down '{vpn}'".format(vpn=self.__connected_vpn_profile) + ) self.__connected_vpn_profile = None except Exception as e: - logging.exception('Could not disconnect VPN connection') + logging.exception("Could not disconnect VPN connection") def __on_vpnconnect(self, name): self.__selected_vpn_profile = name try: - util.cli.execute('nmcli c up \'{vpn}\'' - .format(vpn=self.__selected_vpn_profile)) + util.cli.execute( + "nmcli c up '{vpn}'".format(vpn=self.__selected_vpn_profile) + ) self.__connected_vpn_profile = name except Exception as e: - logging.exception('Could not establish VPN connection') + logging.exception("Could not establish VPN connection") self.__connected_vpn_profile = None def popup(self, widget): menu = util.popup.menu() if self.__connected_vpn_profile is not None: - menu.add_menuitem('Disconnect', callback=self.__on_vpndisconnect) + menu.add_menuitem("Disconnect", callback=self.__on_vpndisconnect) for vpn_profile in self.__vpn_profiles: - if self.__connected_vpn_profile is not None and self.__connected_vpn_profile == vpn_profile: + if ( + self.__connected_vpn_profile is not None + and self.__connected_vpn_profile == vpn_profile + ): continue - menu.add_menuitem(vpn_profile, callback=functools.partial(self.__on_vpnconnect, vpn_profile)) + menu.add_menuitem( + vpn_profile, + callback=functools.partial(self.__on_vpnconnect, vpn_profile), + ) menu.show(widget) def state(self, widget): return [] + # vim: tabstop=8 expandtab shiftwidth=4 softtabstop=4 diff --git a/modules/contrib/watson.py b/modules/contrib/watson.py index f8f7076..ac56c8f 100644 --- a/modules/contrib/watson.py +++ b/modules/contrib/watson.py @@ -17,40 +17,42 @@ import core.decorators import util.cli + class Module(core.module.Module): @core.decorators.every(minutes=60) def __init__(self, config, theme): super().__init__(config, theme, core.widget.Widget(self.text)) self.__tracking = False - self.__project = '' + self.__project = "" core.input.register(self, button=core.input.LEFT_MOUSE, cmd=self.toggle) def toggle(self, widget): - self.__project = 'hit' + self.__project = "hit" if self.__tracking: - util.cli.execute('watson stop') + util.cli.execute("watson stop") else: - util.cli.execute('watson restart') + util.cli.execute("watson restart") self.__tracking = not self.__tracking def text(self, widget): if self.__tracking: return self.__project else: - return 'Paused' + return "Paused" def update(self): - output = util.cli.execute('watson status') - if re.match('No project started', output): + output = util.cli.execute("watson status") + if re.match("No project started", output): self.__tracking = False return self.__tracking = True - m = re.search(r'Project (.+) started', output) + m = re.search(r"Project (.+) started", output) self.__project = m.group(1) def state(self, widget): - return 'on' if self.__tracking else 'off' + return "on" if self.__tracking else "off" + # vim: tabstop=8 expandtab shiftwidth=4 softtabstop=4 diff --git a/modules/contrib/weather.py b/modules/contrib/weather.py index 21927d7..e73f52f 100644 --- a/modules/contrib/weather.py +++ b/modules/contrib/weather.py @@ -28,30 +28,37 @@ import re import requests from requests.exceptions import RequestException + class Module(core.module.Module): @core.decorators.every(minutes=15) def __init__(self, config, theme): super().__init__(config, theme, core.widget.Widget(self.output)) self.__temperature = 0 - self.__apikey = self.parameter('apikey', 'af7bfe22287c652d032a3064ffa44088') - self.__location = util.format.aslist(self.parameter('location', 'auto')) + self.__apikey = self.parameter("apikey", "af7bfe22287c652d032a3064ffa44088") + self.__location = util.format.aslist(self.parameter("location", "auto")) self.__index = 0 - self.__showcity = util.format.asbool(self.parameter('showcity', True)) - self.__showminmax = util.format.asbool(self.parameter('showminmax', False)) - self.__unit = self.parameter('unit', 'metric') + self.__showcity = util.format.asbool(self.parameter("showcity", True)) + self.__showminmax = util.format.asbool(self.parameter("showminmax", False)) + self.__unit = self.parameter("unit", "metric") self.__valid = False - core.input.register(self, button=core.input.LEFT_MOUSE, cmd=self.__next_location) - core.input.register(self, button=core.input.RIGHT_MOUSE, cmd=self.__prev_location) + core.input.register( + self, button=core.input.LEFT_MOUSE, cmd=self.__next_location + ) + core.input.register( + self, button=core.input.RIGHT_MOUSE, cmd=self.__prev_location + ) def __next_location(self, event): self.__index = (self.__index + 1) % len(self.__location) self.update() def __prev_location(self, event): - self.__index = len(self.__location) - 1 if self.__index <= 0 else self.__index - 1 + self.__index = ( + len(self.__location) - 1 if self.__index <= 0 else self.__index - 1 + ) self.update() def temperature(self): @@ -64,15 +71,22 @@ class Module(core.module.Module): return util.format.astemperature(self.__tempmax, self.__unit) def city(self): - city = re.sub('[_-]', ' ', self.__city) - return u'{} '.format(city) + city = re.sub("[_-]", " ", self.__city) + return "{} ".format(city) def output(self, widget): if not self.__valid: - return u'?' + return "?" if self.__showminmax: - self.__showcity=False - return self.city() + self.temperature() + ' Hi:' + self.tempmax() + ' Lo:' + self.tempmin() + self.__showcity = False + return ( + self.city() + + self.temperature() + + " Hi:" + + self.tempmax() + + " Lo:" + + self.tempmin() + ) elif self.__showcity: return self.city() + self.temperature() else: @@ -80,42 +94,51 @@ class Module(core.module.Module): def state(self, widget): if self.__valid: - if 'thunderstorm' in self.__weather: - return ['thunder'] - elif 'drizzle' in self.__weather: - return ['rain'] - elif 'rain' in self.__weather: - return ['rain'] - elif 'snow' in self.__weather: - return ['snow'] - elif 'sleet' in self.__weather: - return ['sleet'] - elif 'clear' in self.__weather: - return ['clear'] - elif 'cloud' in self.__weather: - return ['clouds'] + if "thunderstorm" in self.__weather: + return ["thunder"] + elif "drizzle" in self.__weather: + return ["rain"] + elif "rain" in self.__weather: + return ["rain"] + elif "snow" in self.__weather: + return ["snow"] + elif "sleet" in self.__weather: + return ["sleet"] + elif "clear" in self.__weather: + return ["clear"] + elif "cloud" in self.__weather: + return ["clouds"] return [] def update(self): try: - weather_url = 'http://api.openweathermap.org/data/2.5/weather?appid={}'.format(self.__apikey) - weather_url = '{}&units={}'.format(weather_url, self.__unit) - if self.__location[self.__index] == 'auto': + weather_url = "http://api.openweathermap.org/data/2.5/weather?appid={}".format( + self.__apikey + ) + weather_url = "{}&units={}".format(weather_url, self.__unit) + if self.__location[self.__index] == "auto": coord = util.location.coordinates() - weather_url = '{url}&lat={lat}&lon={lon}'.format(url=weather_url, lat=coord[0], lon=coord[1]) + weather_url = "{url}&lat={lat}&lon={lon}".format( + url=weather_url, lat=coord[0], lon=coord[1] + ) elif self.__location[self.__index].isdigit(): - weather_url = '{url}&id={id}'.format(url=weather_url, id=self.__location[self.__index]) + weather_url = "{url}&id={id}".format( + url=weather_url, id=self.__location[self.__index] + ) else: - weather_url = '{url}&q={city}'.format(url=weather_url, city=self.__location[self.__index]) + weather_url = "{url}&q={city}".format( + url=weather_url, city=self.__location[self.__index] + ) weather = requests.get(weather_url).json() - self.__city = weather['name'] - self.__temperature = int(weather['main']['temp']) - self.__tempmin = int(weather['main']['temp_min']) - self.__tempmax = int(weather['main']['temp_max']) - self.__weather = weather['weather'][0]['main'].lower() + self.__city = weather["name"] + self.__temperature = int(weather["main"]["temp"]) + self.__tempmin = int(weather["main"]["temp_min"]) + self.__tempmax = int(weather["main"]["temp_max"]) + self.__weather = weather["weather"][0]["main"].lower() self.__valid = True except Exception: self.__valid = False + # vim: tabstop=8 expandtab shiftwidth=4 softtabstop=4 diff --git a/modules/contrib/xkcd.py b/modules/contrib/xkcd.py index 4e91959..aa84756 100644 --- a/modules/contrib/xkcd.py +++ b/modules/contrib/xkcd.py @@ -1,4 +1,4 @@ -#pylint: disable=C0111,R0903 +# pylint: disable=C0111,R0903 """Opens a random xkcd comic in the browser.""" @@ -7,12 +7,16 @@ import core.widget import core.input import core.decorators + class Module(core.module.Module): @core.decorators.never def __init__(self, config, theme): - super().__init__(config, theme, core.widget.Widget('xkcd')) - core.input.register(self, button=core.input.LEFT_MOUSE, - cmd="xdg-open https://c.xkcd.com/random/comic/" + super().__init__(config, theme, core.widget.Widget("xkcd")) + core.input.register( + self, + button=core.input.LEFT_MOUSE, + cmd="xdg-open https://c.xkcd.com/random/comic/", ) + # vim: tabstop=8 expandtab shiftwidth=4 softtabstop=4 diff --git a/modules/contrib/yubikey.py b/modules/contrib/yubikey.py index 2cfe80f..dce01be 100644 --- a/modules/contrib/yubikey.py +++ b/modules/contrib/yubikey.py @@ -15,21 +15,25 @@ import core.module import core.widget import core.decorators + class Module(core.module.Module): @core.decorators.every(seconds=5) def __init__(self, config, theme): super().__init__(config, theme, core.widget.Widget(self.keystate)) - self.__keystate = 'No YubiKey' + self.__keystate = "No YubiKey" def keystate(self, widget): return self.__keystate def update(self): try: - self.__keystate = "YubiKey: " + str(yubico.find_yubikey(debug=False).serial()) + self.__keystate = "YubiKey: " + str( + yubico.find_yubikey(debug=False).serial() + ) except yubico.yubico_exception.YubicoError: self.__keystate = "No YubiKey" except Exception: - self.__keystate = 'n/a' + self.__keystate = "n/a" + # vim: tabstop=8 expandtab shiftwidth=4 softtabstop=4 diff --git a/modules/contrib/zpool.py b/modules/contrib/zpool.py index 8218793..cb5ef06 100644 --- a/modules/contrib/zpool.py +++ b/modules/contrib/zpool.py @@ -36,46 +36,81 @@ import core.widget import util.cli import util.format + class Module(core.module.Module): def __init__(self, config, theme): super().__init__(config, theme, []) - self._includelist = set(filter(lambda x: len(x) > 0, - util.format.aslist(self.parameter('list', default='')))) - self._format = self.parameter('format', default='{name} {shortstatus} {used}/{size} ' + - '({percentfree}%)') - self._usesudo = util.format.asbool(self.parameter('sudo', default=False)) - self._showio = util.format.asbool(self.parameter('showio', default=True)) - self._ioformat = self.parameter('ioformat', default='{band}') - self._warnfree = int(self.parameter('warnfree', default=10)) + self._includelist = set( + filter( + lambda x: len(x) > 0, + util.format.aslist(self.parameter("list", default="")), + ) + ) + self._format = self.parameter( + "format", default="{name} {shortstatus} {used}/{size} " + "({percentfree}%)" + ) + self._usesudo = util.format.asbool(self.parameter("sudo", default=False)) + self._showio = util.format.asbool(self.parameter("showio", default=True)) + self._ioformat = self.parameter("ioformat", default="{band}") + self._warnfree = int(self.parameter("warnfree", default=10)) def update(self): widgets = self.widgets() - zfs_version_path = '/sys/module/zfs/version' + zfs_version_path = "/sys/module/zfs/version" # zpool list -H: List all zpools, use script mode (no headers and tabs as separators). try: - with open(zfs_version_path, 'r') as zfs_mod_version: - zfs_version = zfs_mod_version.readline().rstrip().split('-')[0] + with open(zfs_version_path, "r") as zfs_mod_version: + zfs_version = zfs_mod_version.readline().rstrip().split("-")[0] except IOError: # ZFS isn't installed or the module isn't loaded, stub the version - zfs_version = '0.0.0' - logging.error('ZFS version information not found at {}, check the module is loaded.'.format(zfs_version_path)) + zfs_version = "0.0.0" + logging.error( + "ZFS version information not found at {}, check the module is loaded.".format( + zfs_version_path + ) + ) - raw_zpools = util.cli.execute(('sudo ' if self._usesudo else '') + 'zpool list -H').split('\n') + raw_zpools = util.cli.execute( + ("sudo " if self._usesudo else "") + "zpool list -H" + ).split("\n") for widget in widgets: - widget.set('visited', False) + widget.set("visited", False) for raw_zpool in raw_zpools: try: # Ignored fields (assigned to _) are 'expandsz' and 'altroot', also 'ckpoint' in ZFS 0.8.0+ - if parse_version(zfs_version) < parse_version('0.8.0'): - name, size, alloc, free, _, frag, cap, dedup, health, _ = raw_zpool.split('\t') + if parse_version(zfs_version) < parse_version("0.8.0"): + ( + name, + size, + alloc, + free, + _, + frag, + cap, + dedup, + health, + _, + ) = raw_zpool.split("\t") else: - name, size, alloc, free, _, _, frag, cap, dedup, health, _ = raw_zpool.split('\t') - cap = cap.rstrip('%') - percentuse=int(cap) - percentfree=100-percentuse + ( + name, + size, + alloc, + free, + _, + _, + frag, + cap, + dedup, + health, + _, + ) = raw_zpool.split("\t") + cap = cap.rstrip("%") + percentuse = int(cap) + percentfree = 100 - percentuse # There is a command, zpool iostat, which is however blocking and was therefore # causing issues. # Instead, we read file `/proc/spl/kstat/zfs//io` which contains @@ -83,7 +118,7 @@ class Module(core.module.Module): # (and timestamp) during each widget update, and during the next widget update we # use them to compute delta of transferred bytes, and using the last and current # timestamp the rate at which they have been transferred. - with open('/proc/spl/kstat/zfs/{}/io'.format(name), 'r') as f: + with open("/proc/spl/kstat/zfs/{}/io".format(name), "r") as f: # Third row provides data we need, we are interested in the first 4 values. # More info about this file can be found here: # https://github.com/zfsonlinux/zfs/blob/master/lib/libspl/include/sys/kstat.h#L580 @@ -100,12 +135,12 @@ class Module(core.module.Module): widget = self.widget(name) if not widget: widget = core.widget.Widget(name=name) - widget.set('last_iostat', [0, 0, 0, 0]) - widget.set('last_timestamp', 0) + widget.set("last_iostat", [0, 0, 0, 0]) + widget.set("last_timestamp", 0) widgets.append(widget) - delta_iostat = [b - a for a, b in zip(iostat, widget.get('last_iostat'))] - widget.set('last_iostat', iostat) + delta_iostat = [b - a for a, b in zip(iostat, widget.get("last_iostat"))] + widget.set("last_iostat", iostat) # From docs: # > Note that even though the time is always returned as a floating point number, not @@ -114,8 +149,8 @@ class Module(core.module.Module): # Also, during one update cycle the reported I/O may be garbage if the system time # was changed. timestamp = time.time() - delta_timestamp = widget.get('last_timestamp') - timestamp - widget.set('last_timestamp', time.time()) + delta_timestamp = widget.get("last_timestamp") - timestamp + widget.set("last_timestamp", time.time()) # abs is there because sometimes the result is -0 rate_iostat = [abs(x / delta_timestamp) for x in delta_iostat] @@ -123,17 +158,26 @@ class Module(core.module.Module): # theme.minwidth is not set since these values are not expected to change # rapidly - widget.full_text(self._format.format(name=name, used=alloc, left=free, size=size, - percentfree=percentfree, percentuse=percentuse, - status=health, - shortstatus=self._shortstatus(health), - fragpercent=frag, deduppercent=dedup)) - widget.set('state', health) - widget.set('percentfree', percentfree) - widget.set('visited', True) + widget.full_text( + self._format.format( + name=name, + used=alloc, + left=free, + size=size, + percentfree=percentfree, + percentuse=percentuse, + status=health, + shortstatus=self._shortstatus(health), + fragpercent=frag, + deduppercent=dedup, + ) + ) + widget.set("state", health) + widget.set("percentfree", percentfree) + widget.set("visited", True) if self._showio: - wname, rname = [name + x for x in ['__write', '__read']] + wname, rname = [name + x for x in ["__write", "__read"]] widget_w = self.widget(wname) widget_r = self.widget(rname) if not widget_w or not widget_r: @@ -141,30 +185,40 @@ class Module(core.module.Module): widget_w = core.widget.Widget(name=wname) widgets.extend([widget_r, widget_w]) for w in [widget_r, widget_w]: - w.set('theme.minwidth', self._ioformat.format(ops=9999, - band=util.format.bytefmt(999.99*(1024**2)))) - w.set('visited', True) - widget_w.full_text(self._ioformat.format(ops=round(writes), - band=util.format.bytefmt(nwritten))) - widget_r.full_text(self._ioformat.format(ops=round(reads), - band=util.format.bytefmt(nread))) + w.set( + "theme.minwidth", + self._ioformat.format( + ops=9999, band=util.format.bytefmt(999.99 * (1024 ** 2)) + ), + ) + w.set("visited", True) + widget_w.full_text( + self._ioformat.format( + ops=round(writes), band=util.format.bytefmt(nwritten) + ) + ) + widget_r.full_text( + self._ioformat.format( + ops=round(reads), band=util.format.bytefmt(nread) + ) + ) for widget in widgets: - if widget.get('visited') is False: + if widget.get("visited") is False: widgets.remove(widget) self.widgets(widgets) def state(self, widget): - if widget.name.endswith('__read'): - return 'poolread' - elif widget.name.endswith('__write'): - return 'poolwrite' + if widget.name.endswith("__read"): + return "poolread" + elif widget.name.endswith("__write"): + return "poolwrite" - state = widget.get('state') - if state == 'FAULTED': - return [state, 'critical'] - elif state == 'DEGRADED' or widget.get('percentfree') < self._warnfree: - return [state, 'warning'] + state = widget.get("state") + if state == "FAULTED": + return [state, "critical"] + elif state == "DEGRADED" or widget.get("percentfree") < self._warnfree: + return [state, "warning"] return state @@ -177,13 +231,14 @@ class Module(core.module.Module): # configuration. A faulted pool has corrupted metadata, or one or more faulted devices, and # insufficient replicas to continue functioning. shortstate = { - 'DEGRADED': 'DEG', - 'FAULTED': 'FLT', - 'ONLINE': 'ONL', + "DEGRADED": "DEG", + "FAULTED": "FLT", + "ONLINE": "ONL", } try: return shortstate[status] except KeyError: - return '' + return "" + # vim: tabstop=8 expandtab shiftwidth=4 softtabstop=4 diff --git a/modules/core/__pulseaudio.py b/modules/core/__pulseaudio.py index 22136a8..b12b397 100644 --- a/modules/core/__pulseaudio.py +++ b/modules/core/__pulseaudio.py @@ -1,6 +1,6 @@ # pylint: disable=C0111,R0903 -'''Displays volume and mute status and controls for PulseAudio devices. Use wheel up and down to change volume, left click mutes, right click opens pavucontrol. +"""Displays volume and mute status and controls for PulseAudio devices. Use wheel up and down to change volume, left click mutes, right click opens pavucontrol. Aliases: pasink (use this to control output instead of input), pasource @@ -16,7 +16,7 @@ Requires the following executable: * pulseaudio * pactl * pavucontrol -''' +""" import re import logging @@ -29,15 +29,18 @@ import util.cli import util.graph import util.format + class Module(core.module.Module): def __init__(self, config, theme, channel): super().__init__(config, theme, core.widget.Widget(self.volume)) - if util.format.asbool(self.parameter('autostart', False)): - util.cli.execute('pulseaudio --start', ignore_errors=True) + if util.format.asbool(self.parameter("autostart", False)): + util.cli.execute("pulseaudio --start", ignore_errors=True) - self._change = util.format.asint(self.parameter('percent_change', '2%').strip('%'), 0, 100) - self._limit = util.format.asint(self.parameter('limit', '0%').strip('%'), 0) + self._change = util.format.asint( + self.parameter("percent_change", "2%").strip("%"), 0, 100 + ) + self._limit = util.format.asint(self.parameter("limit", "0%").strip("%"), 0) self._left = 0 self._right = 0 @@ -45,131 +48,153 @@ class Module(core.module.Module): self._mute = False self._failed = False self._channel = channel - self._showbars = util.format.asbool(self.parameter('showbars', 0)) + self._showbars = util.format.asbool(self.parameter("showbars", 0)) self._patterns = [ - {'expr': 'Name:', 'callback': (lambda line: False)}, - {'expr': 'Mute:', 'callback': (lambda line: self.mute(False if ' no' in line.lower() else True))}, - {'expr': 'Volume:', 'callback': self.getvolume}, + {"expr": "Name:", "callback": (lambda line: False)}, + { + "expr": "Mute:", + "callback": ( + lambda line: self.mute(False if " no" in line.lower() else True) + ), + }, + {"expr": "Volume:", "callback": self.getvolume}, ] - core.input.register(self, button=core.input.RIGHT_MOUSE, cmd='pavucontrol') + core.input.register(self, button=core.input.RIGHT_MOUSE, cmd="pavucontrol") events = [ - {'type': 'mute', 'action': self.toggle, 'button': core.input.LEFT_MOUSE}, - {'type': 'volume', 'action': self.increase_volume, 'button': core.input.WHEEL_UP}, - {'type': 'volume', 'action': self.decrease_volume, 'button': core.input.WHEEL_DOWN}, + {"type": "mute", "action": self.toggle, "button": core.input.LEFT_MOUSE}, + { + "type": "volume", + "action": self.increase_volume, + "button": core.input.WHEEL_UP, + }, + { + "type": "volume", + "action": self.decrease_volume, + "button": core.input.WHEEL_DOWN, + }, ] for event in events: - core.input.register(self, button=event['button'], cmd=event['action']) + core.input.register(self, button=event["button"], cmd=event["action"]) def set_volume(self, amount): - util.cli.execute('pactl set-{}-{} @DEFAULT_{}@ {}'.format( - self._channel, 'volume', self._channel.upper(), amount)) + util.cli.execute( + "pactl set-{}-{} @DEFAULT_{}@ {}".format( + self._channel, "volume", self._channel.upper(), amount + ) + ) def increase_volume(self, event): - if self._limit > 0: # we need to check the limit + if self._limit > 0: # we need to check the limit left = int(self._left) right = int(self._right) - if left + self._change >= self._limit or right + self._change >= self._limit: + if ( + left + self._change >= self._limit + or right + self._change >= self._limit + ): if left == right: # easy case, just set to limit - self.set_volume('{}%'.format(self._limit)) + self.set_volume("{}%".format(self._limit)) return else: # don't adjust anymore, since i don't know how to update only one channel return - self.set_volume('+{}%'.format(self._change)) + self.set_volume("+{}%".format(self._change)) def decrease_volume(self, event): - self.set_volume('-{}%'.format(self._change)) + self.set_volume("-{}%".format(self._change)) def toggle(self, event): - util.cli.execute('pactl set-{}-mute @DEFAULT_{}@ toggle'.format( - self._channel, self._channel.upper())) + util.cli.execute( + "pactl set-{}-mute @DEFAULT_{}@ toggle".format( + self._channel, self._channel.upper() + ) + ) def mute(self, value): self._mute = value def getvolume(self, line): - if 'mono' in line: - m = re.search(r'mono:.*\s*\/\s*(\d+)%', line) + if "mono" in line: + m = re.search(r"mono:.*\s*\/\s*(\d+)%", line) if m: self._mono = m.group(1) else: - m = re.search(r'left:.*\s*\/\s*(\d+)%.*right:.*\s*\/\s*(\d+)%', line) + m = re.search(r"left:.*\s*\/\s*(\d+)%.*right:.*\s*\/\s*(\d+)%", line) if m: self._left = m.group(1) self._right = m.group(2) def _default_device(self): - output = util.cli.execute('pactl info') - pattern = 'Default {}: '.format('Sink' if self._channel == 'sink' else 'Source') - for line in output.split('\n'): + output = util.cli.execute("pactl info") + pattern = "Default {}: ".format("Sink" if self._channel == "sink" else "Source") + for line in output.split("\n"): if line.startswith(pattern): - return line.replace(pattern, '') - logging.error('no pulseaudio device found') - return 'n/a' + return line.replace(pattern, "") + logging.error("no pulseaudio device found") + return "n/a" def volume(self, widget): if self._failed == True: - return 'n/a' + return "n/a" if int(self._mono) > 0: - vol = '{}%'.format(self._mono) + vol = "{}%".format(self._mono) if self._showbars: - vol = '{} {}'.format( - vol, util.graph.hbar(float(self._mono))) + vol = "{} {}".format(vol, util.graph.hbar(float(self._mono))) return vol elif self._left == self._right: - vol = '{}%'.format(self._left) + vol = "{}%".format(self._left) if self._showbars: - vol = '{} {}'.format( - vol, util.graph.hbar(float(self._left))) + vol = "{} {}".format(vol, util.graph.hbar(float(self._left))) return vol else: - vol = '{}%/{}%'.format(self._left, self._right) + vol = "{}%/{}%".format(self._left, self._right) if self._showbars: - vol = '{} {}{}'.format( + vol = "{} {}{}".format( vol, util.graph.hbar(float(self._left)), - util.graph.hbar(float(self._right))) + util.graph.hbar(float(self._right)), + ) return vol def update(self): try: self._failed = False - channel = 'sinks' if self._channel == 'sink' else 'sources' + channel = "sinks" if self._channel == "sink" else "sources" device = self._default_device() - result = util.cli.execute('pactl list {}'.format(channel)) + result = util.cli.execute("pactl list {}".format(channel)) found = False - for line in result.split('\n'): - if 'Name: {}'.format(device) in line: + for line in result.split("\n"): + if "Name: {}".format(device) in line: found = True continue if found is False: continue for pattern in self._patterns: - if not pattern['expr'] in line: + if not pattern["expr"] in line: continue - if pattern['callback'](line) is False and found == True: + if pattern["callback"](line) is False and found == True: return except Exception as e: self._failed = True logging.exception(e) - if util.format.asbool(self.parameter('autostart', False)): - util.cli.execute('pulseaudio --start', ignore_errors=True) + if util.format.asbool(self.parameter("autostart", False)): + util.cli.execute("pulseaudio --start", ignore_errors=True) else: raise e def state(self, widget): if self._mute: - return ['warning', 'muted'] + return ["warning", "muted"] if int(self._left) > int(100): - return ['critical', 'unmuted'] - return ['unmuted'] + return ["critical", "unmuted"] + return ["unmuted"] + # vim: tabstop=8 expandtab shiftwidth=4 softtabstop=4 diff --git a/modules/core/battery-upower.py b/modules/core/battery-upower.py index ca1d7b7..cc8d3ca 100644 --- a/modules/core/battery-upower.py +++ b/modules/core/battery-upower.py @@ -17,7 +17,8 @@ import core.input import util.format -class UPowerManager(): + +class UPowerManager: def __init__(self): self.UPOWER_NAME = "org.freedesktop.UPower" self.UPOWER_PATH = "/org/freedesktop/UPower" @@ -56,64 +57,100 @@ class UPowerManager(): battery_proxy = self.bus.get_object(self.UPOWER_NAME, battery) battery_proxy_interface = dbus.Interface(battery_proxy, self.DBUS_PROPERTIES) - hasHistory = battery_proxy_interface.Get(self.UPOWER_NAME + ".Device", "HasHistory") - hasStatistics = battery_proxy_interface.Get(self.UPOWER_NAME + ".Device", "HasStatistics") - isPresent = battery_proxy_interface.Get(self.UPOWER_NAME + ".Device", "IsPresent") - isRechargable = battery_proxy_interface.Get(self.UPOWER_NAME + ".Device", "IsRechargeable") + hasHistory = battery_proxy_interface.Get( + self.UPOWER_NAME + ".Device", "HasHistory" + ) + hasStatistics = battery_proxy_interface.Get( + self.UPOWER_NAME + ".Device", "HasStatistics" + ) + isPresent = battery_proxy_interface.Get( + self.UPOWER_NAME + ".Device", "IsPresent" + ) + isRechargable = battery_proxy_interface.Get( + self.UPOWER_NAME + ".Device", "IsRechargeable" + ) online = battery_proxy_interface.Get(self.UPOWER_NAME + ".Device", "Online") - powersupply = battery_proxy_interface.Get(self.UPOWER_NAME + ".Device", "PowerSupply") + powersupply = battery_proxy_interface.Get( + self.UPOWER_NAME + ".Device", "PowerSupply" + ) capacity = battery_proxy_interface.Get(self.UPOWER_NAME + ".Device", "Capacity") energy = battery_proxy_interface.Get(self.UPOWER_NAME + ".Device", "Energy") - energyempty = battery_proxy_interface.Get(self.UPOWER_NAME + ".Device", "EnergyEmpty") - energyfull = battery_proxy_interface.Get(self.UPOWER_NAME + ".Device", "EnergyFull") - energyfulldesign = battery_proxy_interface.Get(self.UPOWER_NAME + ".Device", "EnergyFullDesign") - energyrate = battery_proxy_interface.Get(self.UPOWER_NAME + ".Device", "EnergyRate") - luminosity = battery_proxy_interface.Get(self.UPOWER_NAME + ".Device", "Luminosity") - percentage = battery_proxy_interface.Get(self.UPOWER_NAME + ".Device", "Percentage") - temperature = battery_proxy_interface.Get(self.UPOWER_NAME + ".Device", "Temperature") + energyempty = battery_proxy_interface.Get( + self.UPOWER_NAME + ".Device", "EnergyEmpty" + ) + energyfull = battery_proxy_interface.Get( + self.UPOWER_NAME + ".Device", "EnergyFull" + ) + energyfulldesign = battery_proxy_interface.Get( + self.UPOWER_NAME + ".Device", "EnergyFullDesign" + ) + energyrate = battery_proxy_interface.Get( + self.UPOWER_NAME + ".Device", "EnergyRate" + ) + luminosity = battery_proxy_interface.Get( + self.UPOWER_NAME + ".Device", "Luminosity" + ) + percentage = battery_proxy_interface.Get( + self.UPOWER_NAME + ".Device", "Percentage" + ) + temperature = battery_proxy_interface.Get( + self.UPOWER_NAME + ".Device", "Temperature" + ) voltage = battery_proxy_interface.Get(self.UPOWER_NAME + ".Device", "Voltage") - timetoempty = battery_proxy_interface.Get(self.UPOWER_NAME + ".Device", "TimeToEmpty") - timetofull = battery_proxy_interface.Get(self.UPOWER_NAME + ".Device", "TimeToFull") + timetoempty = battery_proxy_interface.Get( + self.UPOWER_NAME + ".Device", "TimeToEmpty" + ) + timetofull = battery_proxy_interface.Get( + self.UPOWER_NAME + ".Device", "TimeToFull" + ) iconname = battery_proxy_interface.Get(self.UPOWER_NAME + ".Device", "IconName") model = battery_proxy_interface.Get(self.UPOWER_NAME + ".Device", "Model") - nativepath = battery_proxy_interface.Get(self.UPOWER_NAME + ".Device", "NativePath") + nativepath = battery_proxy_interface.Get( + self.UPOWER_NAME + ".Device", "NativePath" + ) serial = battery_proxy_interface.Get(self.UPOWER_NAME + ".Device", "Serial") vendor = battery_proxy_interface.Get(self.UPOWER_NAME + ".Device", "Vendor") state = battery_proxy_interface.Get(self.UPOWER_NAME + ".Device", "State") - technology = battery_proxy_interface.Get(self.UPOWER_NAME + ".Device", "Technology") + technology = battery_proxy_interface.Get( + self.UPOWER_NAME + ".Device", "Technology" + ) battype = battery_proxy_interface.Get(self.UPOWER_NAME + ".Device", "Type") - warninglevel = battery_proxy_interface.Get(self.UPOWER_NAME + ".Device", "WarningLevel") - updatetime = battery_proxy_interface.Get(self.UPOWER_NAME + ".Device", "UpdateTime") + warninglevel = battery_proxy_interface.Get( + self.UPOWER_NAME + ".Device", "WarningLevel" + ) + updatetime = battery_proxy_interface.Get( + self.UPOWER_NAME + ".Device", "UpdateTime" + ) information_table = { - 'HasHistory': hasHistory, - 'HasStatistics': hasStatistics, - 'IsPresent': isPresent, - 'IsRechargeable': isRechargable, - 'Online': online, - 'PowerSupply': powersupply, - 'Capacity': capacity, - 'Energy': energy, - 'EnergyEmpty': energyempty, - 'EnergyFull': energyfull, - 'EnergyFullDesign': energyfulldesign, - 'EnergyRate': energyrate, - 'Luminosity': luminosity, - 'Percentage': percentage, - 'Temperature': temperature, - 'Voltage': voltage, - 'TimeToEmpty': timetoempty, - 'TimeToFull': timetofull, - 'IconName': iconname, - 'Model': model, - 'NativePath': nativepath, - 'Serial': serial, - 'Vendor': vendor, - 'State': state, - 'Technology': technology, - 'Type': battype, - 'WarningLevel': warninglevel, - 'UpdateTime': updatetime + "HasHistory": hasHistory, + "HasStatistics": hasStatistics, + "IsPresent": isPresent, + "IsRechargeable": isRechargable, + "Online": online, + "PowerSupply": powersupply, + "Capacity": capacity, + "Energy": energy, + "EnergyEmpty": energyempty, + "EnergyFull": energyfull, + "EnergyFullDesign": energyfulldesign, + "EnergyRate": energyrate, + "Luminosity": luminosity, + "Percentage": percentage, + "Temperature": temperature, + "Voltage": voltage, + "TimeToEmpty": timetoempty, + "TimeToFull": timetofull, + "IconName": iconname, + "Model": model, + "NativePath": nativepath, + "Serial": serial, + "Vendor": vendor, + "State": state, + "Technology": technology, + "Type": battype, + "WarningLevel": warninglevel, + "UpdateTime": updatetime, } return information_table @@ -122,40 +159,48 @@ class UPowerManager(): upower_proxy = self.bus.get_object(self.UPOWER_NAME, self.UPOWER_PATH) upower_interface = dbus.Interface(upower_proxy, self.DBUS_PROPERTIES) - is_lid_present = bool(upower_interface.Get(self.UPOWER_NAME, 'LidIsPresent')) + is_lid_present = bool(upower_interface.Get(self.UPOWER_NAME, "LidIsPresent")) return is_lid_present def is_lid_closed(self): upower_proxy = self.bus.get_object(self.UPOWER_NAME, self.UPOWER_PATH) upower_interface = dbus.Interface(upower_proxy, self.DBUS_PROPERTIES) - is_lid_closed = bool(upower_interface.Get(self.UPOWER_NAME, 'LidIsClosed')) + is_lid_closed = bool(upower_interface.Get(self.UPOWER_NAME, "LidIsClosed")) return is_lid_closed def on_battery(self): upower_proxy = self.bus.get_object(self.UPOWER_NAME, self.UPOWER_PATH) upower_interface = dbus.Interface(upower_proxy, self.DBUS_PROPERTIES) - on_battery = bool(upower_interface.Get(self.UPOWER_NAME, 'OnBattery')) + on_battery = bool(upower_interface.Get(self.UPOWER_NAME, "OnBattery")) return on_battery def has_wakeup_capabilities(self): - upower_proxy = self.bus.get_object(self.UPOWER_NAME, self.UPOWER_PATH + "/Wakeups") + upower_proxy = self.bus.get_object( + self.UPOWER_NAME, self.UPOWER_PATH + "/Wakeups" + ) upower_interface = dbus.Interface(upower_proxy, self.DBUS_PROPERTIES) - has_wakeup_capabilities = bool(upower_interface.Get(self.UPOWER_NAME + '.Wakeups', 'HasCapability')) + has_wakeup_capabilities = bool( + upower_interface.Get(self.UPOWER_NAME + ".Wakeups", "HasCapability") + ) return has_wakeup_capabilities def get_wakeups_data(self): - upower_proxy = self.bus.get_object(self.UPOWER_NAME, self.UPOWER_PATH + "/Wakeups") - upower_interface = dbus.Interface(upower_proxy, self.UPOWER_NAME + '.Wakeups') + upower_proxy = self.bus.get_object( + self.UPOWER_NAME, self.UPOWER_PATH + "/Wakeups" + ) + upower_interface = dbus.Interface(upower_proxy, self.UPOWER_NAME + ".Wakeups") data = upower_interface.GetData() return data def get_wakeups_total(self): - upower_proxy = self.bus.get_object(self.UPOWER_NAME, self.UPOWER_PATH + "/Wakeups") - upower_interface = dbus.Interface(upower_proxy, self.UPOWER_NAME + '.Wakeups') + upower_proxy = self.bus.get_object( + self.UPOWER_NAME, self.UPOWER_PATH + "/Wakeups" + ) + upower_interface = dbus.Interface(upower_proxy, self.UPOWER_NAME + ".Wakeups") data = upower_interface.GetTotal() return data @@ -166,7 +211,7 @@ class UPowerManager(): state = int(battery_proxy_interface.Get(self.UPOWER_NAME + ".Device", "State")) - if (state == 1): + if state == 1: return True else: return False @@ -177,21 +222,22 @@ class UPowerManager(): state = int(battery_proxy_interface.Get(self.UPOWER_NAME + ".Device", "State")) - if (state == 0): + if state == 0: return "Unknown" - elif (state == 1): + elif state == 1: return "Loading" - elif (state == 2): + elif state == 2: return "Discharging" - elif (state == 3): + elif state == 3: return "Empty" - elif (state == 4): + elif state == 4: return "Fully charged" - elif (state == 5): + elif state == 5: return "Pending charge" - elif (state == 6): + elif state == 6: return "Pending discharge" + class Module(core.module.Module): def __init__(self, config, theme): super().__init__(config, theme, core.widget.Widget(self.capacity)) @@ -201,11 +247,11 @@ class Module(core.module.Module): self.device = self.power.get_display_device() except Exception as e: logging.exception("unable to get battery display device: {}".format(str(e))) - core.input.register(self, button=core.input.LEFT_MOUSE, - cmd="gnome-power-statistics") + core.input.register( + self, button=core.input.LEFT_MOUSE, cmd="gnome-power-statistics" + ) - self._showremaining = util.format.asbool( - self.parameter("showremaining", True)) + self._showremaining = util.format.asbool(self.parameter("showremaining", True)) def capacity(self, widget): widget.set("capacity", -1) @@ -222,19 +268,25 @@ class Module(core.module.Module): if self._showremaining: try: - p = self.power # an alias to make each line of code shorter + p = self.power # an alias to make each line of code shorter proxy = p.bus.get_object(p.UPOWER_NAME, self.device) interface = dbus.Interface(proxy, p.DBUS_PROPERTIES) - state = int(interface.Get(p.UPOWER_NAME+".Device", "State")) + state = int(interface.Get(p.UPOWER_NAME + ".Device", "State")) # state: 1 => charging, 2 => discharging, other => don't care - remain = int(interface.Get( - p.UPOWER_NAME+".Device", ["TimeToFull", "TimeToEmpty"][state-1])) + remain = int( + interface.Get( + p.UPOWER_NAME + ".Device", + ["TimeToFull", "TimeToEmpty"][state - 1], + ) + ) remain = util.format.duration(remain, compact=True, unit=True) output = "{} {}".format(output, remain) except IndexError: pass except Exception as e: - logging.exception("unable to get battery remaining time: {}".format(str(e))) + logging.exception( + "unable to get battery remaining time: {}".format(str(e)) + ) return output @@ -258,9 +310,17 @@ class Module(core.module.Module): except Exception as e: logging.exception("unable to get charge value: {}".format(str(e))) if charge == "Discharging": - state.append("discharging-{}".format(min([10, 25, 50, 80, 100], key=lambda i: abs(i - capacity)))) + state.append( + "discharging-{}".format( + min([10, 25, 50, 80, 100], key=lambda i: abs(i - capacity)) + ) + ) elif charge == "Unknown": - state.append("unknown-{}".format(min([10, 25, 50, 80, 100], key=lambda i: abs(i - capacity)))) + state.append( + "unknown-{}".format( + min([10, 25, 50, 80, 100], key=lambda i: abs(i - capacity)) + ) + ) else: if capacity > 95: state.append("charged") @@ -268,4 +328,5 @@ class Module(core.module.Module): state.append("charging") return state + # vim: tabstop=8 expandtab shiftwidth=4 softtabstop=4 diff --git a/modules/core/battery.py b/modules/core/battery.py index 283b54c..d5f5cbe 100644 --- a/modules/core/battery.py +++ b/modules/core/battery.py @@ -15,6 +15,7 @@ Parameters: import os import glob import logging + log = logging.getLogger(__name__) try: @@ -28,6 +29,7 @@ import core.input import util.format + class BatteryManager(object): def remaining(self): try: @@ -35,26 +37,25 @@ class BatteryManager(object): # do not show remaining if on AC if estimate == power.common.TIME_REMAINING_UNLIMITED: return None - return estimate*60 # return value in seconds + return estimate * 60 # return value in seconds except Exception as e: return -1 return -1 def read(self, battery, component, default=None): - path = '/sys/class/power_supply/{}'.format(battery) + path = "/sys/class/power_supply/{}".format(battery) if not os.path.exists(path): return default try: - with open('{}/{}'.format(path, component)) as f: + with open("{}/{}".format(path, component)) as f: return f.read().strip() except IOError: - return 'n/a' + return "n/a" return default - def capacity(self, battery): - capacity = self.read(battery, 'capacity', 100) - if capacity != 'n/a': + capacity = self.read(battery, "capacity", 100) + if capacity != "n/a": capacity = int(capacity) return capacity if capacity < 100 else 100 @@ -64,37 +65,41 @@ class BatteryManager(object): full = 0 for battery in batteries: try: - with open('/sys/class/power_supply/{}/energy_full'.format(battery)) as f: + with open( + "/sys/class/power_supply/{}/energy_full".format(battery) + ) as f: full += int(f.read()) - with open('/sys/class/power_supply/{}/energy_now'.format(battery)) as f: + with open("/sys/class/power_supply/{}/energy_now".format(battery)) as f: now += int(f.read()) except IOError: - return 'n/a' - return int(float(now)/float(full)*100.0) + return "n/a" + return int(float(now) / float(full) * 100.0) def isac(self, battery): - path = '/sys/class/power_supply/{}'.format(battery) + path = "/sys/class/power_supply/{}".format(battery) return not os.path.exists(path) def isac_any(self, batteries): for battery in batteries: - if self.isac(battery): return True + if self.isac(battery): + return True return False def consumption(self, battery): - consumption = self.read(battery, 'power_now', 'n/a') - if consumption == 'n/a': - return 'n/a' - return '{}W'.format(int(consumption)/1000000) + consumption = self.read(battery, "power_now", "n/a") + if consumption == "n/a": + return "n/a" + return "{}W".format(int(consumption) / 1000000) def charge(self, battery): - return self.read(battery, 'status', 'n/a') + return self.read(battery, "status", "n/a") def charge_any(self, batteries): for battery in batteries: - if self.charge(battery) == 'Discharging': - return 'Discharging' - return 'Charged' + if self.charge(battery) == "Discharging": + return "Discharging" + return "Charged" + class Module(core.module.Module): def __init__(self, config, theme): @@ -103,81 +108,104 @@ class Module(core.module.Module): self.__manager = BatteryManager() - self._batteries = util.format.aslist(self.parameter('device', 'auto')) - if self._batteries[0] == 'auto': - self._batteries = [ os.path.basename(battery) for battery in glob.glob('/sys/class/power_supply/BAT*') ] + self._batteries = util.format.aslist(self.parameter("device", "auto")) + if self._batteries[0] == "auto": + self._batteries = [ + os.path.basename(battery) + for battery in glob.glob("/sys/class/power_supply/BAT*") + ] if len(self._batteries) == 0: - raise Exceptions('no batteries configured/found') - core.input.register(self, button=core.input.LEFT_MOUSE, - cmd='gnome-power-statistics') + raise Exceptions("no batteries configured/found") + core.input.register( + self, button=core.input.LEFT_MOUSE, cmd="gnome-power-statistics" + ) - if util.format.asbool(self.parameter('compact-devices', False)): - widget = core.widget.Widget(full_text=self.capacity, name='all-batteries', module=self) + if util.format.asbool(self.parameter("compact-devices", False)): + widget = core.widget.Widget( + full_text=self.capacity, name="all-batteries", module=self + ) widgets.append(widget) else: for battery in self._batteries: - log.debug('adding new widget for {}'.format(battery)) - widget = core.widget.Widget(full_text=self.capacity, name=battery, module=self) + log.debug("adding new widget for {}".format(battery)) + widget = core.widget.Widget( + full_text=self.capacity, name=battery, module=self + ) widgets.append(widget) for w in self.widgets(): - if util.format.asbool(self.parameter('decorate', True)) == False: - widget.set('theme.exclude', 'suffix') + if util.format.asbool(self.parameter("decorate", True)) == False: + widget.set("theme.exclude", "suffix") def capacity(self, widget): - if widget.name == 'all-batteries': + if widget.name == "all-batteries": capacity = self.__manager.capacity_all(self._batteries) else: capacity = self.__manager.capacity(widget.name) - widget.set('capacity', capacity) - widget.set('ac', self.__manager.isac_any(self._batteries)) - widget.set('theme.minwidth', '100%') + widget.set("capacity", capacity) + widget.set("ac", self.__manager.isac_any(self._batteries)) + widget.set("theme.minwidth", "100%") # Read power conumption - if util.format.asbool(self.parameter('showpowerconsumption', False)): - output = '{}% ({})'.format(capacity, self.__manager.consumption(widget.name)) + if util.format.asbool(self.parameter("showpowerconsumption", False)): + output = "{}% ({})".format( + capacity, self.__manager.consumption(widget.name) + ) else: - output = '{}%'.format(capacity) + output = "{}%".format(capacity) - if util.format.asbool(self.parameter('showremaining', True))\ - and self.__manager.charge(widget.name) == 'Discharging': + if ( + util.format.asbool(self.parameter("showremaining", True)) + and self.__manager.charge(widget.name) == "Discharging" + ): remaining = self.__manager.remaining() if remaining >= 0: - output = '{} {}'.format(output, util.format.duration(remaining, compact=True, unit=True)) + output = "{} {}".format( + output, util.format.duration(remaining, compact=True, unit=True) + ) - if util.format.asbool(self.parameter('showdevice', False)): - output = '{} ({})'.format(output, widget.name) + if util.format.asbool(self.parameter("showdevice", False)): + output = "{} ({})".format(output, widget.name) return output - + def state(self, widget): state = [] - capacity = widget.get('capacity') + capacity = widget.get("capacity") if capacity < 0: - log.debug('battery state: {}'.format(state)) - return ['critical', 'unknown'] + log.debug("battery state: {}".format(state)) + return ["critical", "unknown"] - if capacity < int(self.parameter('critical', 10)): - state.append('critical') - elif capacity < int(self.parameter('warning', 20)): - state.append('warning') + if capacity < int(self.parameter("critical", 10)): + state.append("critical") + elif capacity < int(self.parameter("warning", 20)): + state.append("warning") - if widget.get('ac'): - state.append('AC') + if widget.get("ac"): + state.append("AC") else: - if widget.name == 'all-batteries': + if widget.name == "all-batteries": charge = self.__manager.charge_any(self._batteries) else: charge = self.__manager.charge(widget.name) - if charge == 'Discharging': - state.append('discharging-{}'.format(min([10, 25, 50, 80, 100], key=lambda i: abs(i-capacity)))) - elif charge == 'Unknown': - state.append('unknown-{}'.format(min([10, 25, 50, 80, 100], key=lambda i: abs(i-capacity)))) + if charge == "Discharging": + state.append( + "discharging-{}".format( + min([10, 25, 50, 80, 100], key=lambda i: abs(i - capacity)) + ) + ) + elif charge == "Unknown": + state.append( + "unknown-{}".format( + min([10, 25, 50, 80, 100], key=lambda i: abs(i - capacity)) + ) + ) else: if capacity > 95: - state.append('charged') + state.append("charged") else: - state.append('charging') + state.append("charging") return state + # vim: tabstop=8 expandtab shiftwidth=4 softtabstop=4 diff --git a/modules/core/brightness.py b/modules/core/brightness.py index 6cc1610..e911db8 100644 --- a/modules/core/brightness.py +++ b/modules/core/brightness.py @@ -17,27 +17,29 @@ import core.decorators import util.cli + class Module(core.module.Module): @core.decorators.every(seconds=30) def __init__(self, config, theme): super().__init__(config, theme, core.widget.Widget(self.brightness)) - self.__brightness = 'n/a' + self.__brightness = "n/a" self.__readcmd = None - step = self.parameter('step', 2) + step = self.parameter("step", 2) - if shutil.which('light'): + if shutil.which("light"): self.__readcmd = self.__light - self.register_cmd('light -A {}%'.format(step), - 'light -U {}%'.format(step)) - elif shutil.which('brightnessctl'): + self.register_cmd("light -A {}%".format(step), "light -U {}%".format(step)) + elif shutil.which("brightnessctl"): self.__readcmd = self.__brightnessctl - self.register_cmd('brightnessctl s {}%+'.format(step), - 'brightnessctl s {}%-'.format(step)) + self.register_cmd( + "brightnessctl s {}%+".format(step), "brightnessctl s {}%-".format(step) + ) else: self.__readcmd = self.__xbacklight - self.register_cmd('xbacklight +{}%'.format(step), - 'xbacklight -{}%'.format(step)) + self.register_cmd( + "xbacklight +{}%".format(step), "xbacklight -{}%".format(step) + ) def register_cmd(self, up_cmd, down_cmd): core.input.register(self, button=core.input.WHEEL_UP, cmd=up_cmd) @@ -47,20 +49,21 @@ class Module(core.module.Module): return self.__brightness def __light(self): - return util.cli.execute('light').strip() + return util.cli.execute("light").strip() def __brightnessctl(self): - m = util.cli.execute('brightnessctl m').strip() - g = util.cli.execute('brightnessctl g').strip() - return float(g)/float(m)*100.0 + m = util.cli.execute("brightnessctl m").strip() + g = util.cli.execute("brightnessctl g").strip() + return float(g) / float(m) * 100.0 def __xbacklight(self): - return util.cli.execute('xbacklight -get').strip() + return util.cli.execute("xbacklight -get").strip() def update(self): try: - self.__brightness = '{:3.0f}%'.format(float(self.__readcmd())) + self.__brightness = "{:3.0f}%".format(float(self.__readcmd())) except: - self.__brightness = 'n/a' + self.__brightness = "n/a" + # vim: tabstop=8 expandtab shiftwidth=4 softtabstop=4 diff --git a/modules/core/cmus.py b/modules/core/cmus.py index 2d66646..9cecf71 100644 --- a/modules/core/cmus.py +++ b/modules/core/cmus.py @@ -32,18 +32,21 @@ import core.decorators import util.cli import util.format + class Module(core.module.Module): def __init__(self, config, theme): super().__init__(config, theme, []) - self._layout = self.parameter('layout', 'cmus.prev cmus.main cmus.next cmus.shuffle cmus.repeat') - self._fmt = self.parameter('format', '{artist} - {title} {position}/{duration}') - self._server = self.parameter('server', None) - self._passwd = self.parameter('passwd', None) + self._layout = self.parameter( + "layout", "cmus.prev cmus.main cmus.next cmus.shuffle cmus.repeat" + ) + self._fmt = self.parameter("format", "{artist} - {title} {position}/{duration}") + self._server = self.parameter("server", None) + self._passwd = self.parameter("passwd", None) self._status = None self._shuffle = False self._repeat = False - self._tags = defaultdict(lambda: '') + self._tags = defaultdict(lambda: "") # Create widgets widget_list = [] @@ -51,25 +54,48 @@ class Module(core.module.Module): for widget_name in self._layout.split(): widget = core.widget.Widget(name=widget_name, module=self) widget_list.append(widget) - self._cmd = 'cmus-remote' + self._cmd = "cmus-remote" if self._server is not None: - self._cmd = '{cmd} --server {server}'.format(cmd=self._cmd, server=self._server) + self._cmd = "{cmd} --server {server}".format( + cmd=self._cmd, server=self._server + ) if self._passwd is not None: - self._cmd = '{cmd} --passwd {passwd}'.format(cmd=self._cmd, passwd=self._passwd) + self._cmd = "{cmd} --passwd {passwd}".format( + cmd=self._cmd, passwd=self._passwd + ) - if widget_name == 'cmus.prev': - widget_map[widget] = {'button': core.input.LEFT_MOUSE, 'cmd': '{cmd} -r'.format(cmd=self._cmd)} - elif widget_name == 'cmus.main': - widget_map[widget] = {'button': core.input.LEFT_MOUSE, 'cmd': '{cmd} -u'.format(cmd=self._cmd)} + if widget_name == "cmus.prev": + widget_map[widget] = { + "button": core.input.LEFT_MOUSE, + "cmd": "{cmd} -r".format(cmd=self._cmd), + } + elif widget_name == "cmus.main": + widget_map[widget] = { + "button": core.input.LEFT_MOUSE, + "cmd": "{cmd} -u".format(cmd=self._cmd), + } widget.full_text(self.description) - elif widget_name == 'cmus.next': - widget_map[widget] = {'button': core.input.LEFT_MOUSE, 'cmd': '{cmd} -n'.format(cmd=self._cmd)} - elif widget_name == 'cmus.shuffle': - widget_map[widget] = {'button': core.input.LEFT_MOUSE, 'cmd': '{cmd} -S'.format(cmd=self._cmd)} - elif widget_name == 'cmus.repeat': - widget_map[widget] = {'button': core.input.LEFT_MOUSE, 'cmd': '{cmd} -R'.format(cmd=self._cmd)} + elif widget_name == "cmus.next": + widget_map[widget] = { + "button": core.input.LEFT_MOUSE, + "cmd": "{cmd} -n".format(cmd=self._cmd), + } + elif widget_name == "cmus.shuffle": + widget_map[widget] = { + "button": core.input.LEFT_MOUSE, + "cmd": "{cmd} -S".format(cmd=self._cmd), + } + elif widget_name == "cmus.repeat": + widget_map[widget] = { + "button": core.input.LEFT_MOUSE, + "cmd": "{cmd} -R".format(cmd=self._cmd), + } else: - raise KeyError('The cmus module does not support a {widget_name!r} widget'.format(widget_name=widget_name)) + raise KeyError( + "The cmus module does not support a {widget_name!r} widget".format( + widget_name=widget_name + ) + ) self.widgets(widget_list) # Register input callbacks @@ -88,44 +114,45 @@ class Module(core.module.Module): def state(self, widget): returns = { - 'cmus.shuffle': 'shuffle-on' if self._shuffle else 'shuffle-off', - 'cmus.repeat': 'repeat-on' if self._repeat else 'repeat-off', - 'cmus.prev': 'prev', - 'cmus.next': 'next', + "cmus.shuffle": "shuffle-on" if self._shuffle else "shuffle-off", + "cmus.repeat": "repeat-on" if self._repeat else "repeat-off", + "cmus.prev": "prev", + "cmus.next": "next", } return returns.get(widget.name, self._status) def _eval_line(self, line): - if line.startswith('file '): + if line.startswith("file "): full_file = line[5:] file1 = os.path.basename(full_file) file2 = os.path.splitext(file1)[0] - self._tags.update({'file': full_file}) - self._tags.update({'file1': file1}) - self._tags.update({'file2': file2}) + self._tags.update({"file": full_file}) + self._tags.update({"file1": file1}) + self._tags.update({"file2": file2}) return - name, key, value = (line.split(' ', 2) + [None, None])[:3] + name, key, value = (line.split(" ", 2) + [None, None])[:3] - if name == 'status': + if name == "status": self._status = key - if name == 'tag': + if name == "tag": self._tags.update({key: value}) - if name in ['duration', 'position']: + if name in ["duration", "position"]: self._tags.update({name: util.format.duration(int(key))}) - if name == 'set' and key == 'repeat': - self._repeat = value == 'true' - if name == 'set' and key == 'shuffle': - self._shuffle = value == 'true' + if name == "set" and key == "repeat": + self._repeat = value == "true" + if name == "set" and key == "shuffle": + self._shuffle = value == "true" def _load_song(self): - info = '' + info = "" try: - info = util.cli.execute('{cmd} -Q'.format(cmd=self._cmd)) + info = util.cli.execute("{cmd} -Q".format(cmd=self._cmd)) except RuntimeError: self._status = None - self._tags = defaultdict(lambda: '') - for line in info.split('\n'): + self._tags = defaultdict(lambda: "") + for line in info.split("\n"): self._eval_line(line) + # vim: tabstop=8 expandtab shiftwidth=4 softtabstop=4 diff --git a/modules/core/cpu.py b/modules/core/cpu.py index 65d30a7..5d43de7 100644 --- a/modules/core/cpu.py +++ b/modules/core/cpu.py @@ -1,12 +1,12 @@ # pylint: disable=C0111,R0903 -'''Displays CPU utilization across all CPUs. +"""Displays CPU utilization across all CPUs. Parameters: * cpu.warning : Warning threshold in % of CPU usage (defaults to 70%) * cpu.critical: Critical threshold in % of CPU usage (defaults to 80%) * cpu.format : Format string (defaults to '{:.01f}%') -''' +""" import psutil @@ -14,17 +14,19 @@ import core.module import core.widget import core.input + class Module(core.module.Module): def __init__(self, config, theme): super().__init__(config, theme, core.widget.Widget(self.utilization)) - self.widget().set('theme.minwidth', self._format.format(100.0-10e-20)) + self.widget().set("theme.minwidth", self._format.format(100.0 - 10e-20)) self._utilization = psutil.cpu_percent(percpu=False) - core.input.register(self, button=core.input.LEFT_MOUSE, - cmd='gnome-system-monitor') + core.input.register( + self, button=core.input.LEFT_MOUSE, cmd="gnome-system-monitor" + ) @property def _format(self): - return self.parameter('format', '{:.01f}%') + return self.parameter("format", "{:.01f}%") def utilization(self, _): return self._format.format(self._utilization) @@ -35,4 +37,5 @@ class Module(core.module.Module): def state(self, _): return self.threshold_state(self._utilization, 70, 80) + # vim: tabstop=8 expandtab shiftwidth=4 softtabstop=4 diff --git a/modules/core/date.py b/modules/core/date.py index bb4ff0d..4c7fc31 100644 --- a/modules/core/date.py +++ b/modules/core/date.py @@ -10,12 +10,14 @@ Parameters: import core.decorators from .datetime import Module + class Module(Module): @core.decorators.every(hours=1) def __init__(self, config, theme): super().__init__(config, theme) def default_format(self): - return '%x' + return "%x" + # vim: tabstop=8 expandtab shiftwidth=4 softtabstop=4 diff --git a/modules/core/datetime.py b/modules/core/datetime.py index ada5fdd..f421e15 100644 --- a/modules/core/datetime.py +++ b/modules/core/datetime.py @@ -1,11 +1,11 @@ # pylint: disable=C0111,R0903 -'''Displays the current date and time. +"""Displays the current date and time. Parameters: * datetime.format: strftime()-compatible formatting string * datetime.locale: locale to use rather than the system default -''' +""" from __future__ import absolute_import import datetime @@ -15,29 +15,31 @@ import core.module import core.widget import core.input + class Module(core.module.Module): def __init__(self, config, theme): super().__init__(config, theme, core.widget.Widget(self.full_text)) - core.input.register(self, button=core.input.LEFT_MOUSE, cmd='calendar') - self._fmt = self.parameter('format', self.default_format()) + core.input.register(self, button=core.input.LEFT_MOUSE, cmd="calendar") + self._fmt = self.parameter("format", self.default_format()) l = locale.getdefaultlocale() if not l or l == (None, None): - l = ('en_US', 'UTF-8') - lcl = self.parameter('locale', '.'.join(l)) + l = ("en_US", "UTF-8") + lcl = self.parameter("locale", ".".join(l)) try: - locale.setlocale(locale.LC_TIME, lcl.split('.')) + locale.setlocale(locale.LC_TIME, lcl.split(".")) except Exception as e: - locale.setlocale(locale.LC_TIME, ('en_US', 'UTF-8')) + locale.setlocale(locale.LC_TIME, ("en_US", "UTF-8")) def default_format(self): - return '%x %X' + return "%x %X" def full_text(self, widget): enc = locale.getpreferredencoding() retval = datetime.datetime.now().strftime(self._fmt) - if hasattr(retval, 'decode'): + if hasattr(retval, "decode"): return retval.decode(enc) return retval + # vim: tabstop=8 expandtab shiftwidth=4 softtabstop=4 diff --git a/modules/core/debug.py b/modules/core/debug.py index 9df26bb..35d9f6d 100644 --- a/modules/core/debug.py +++ b/modules/core/debug.py @@ -8,15 +8,17 @@ import core.module import core.widget import core.decorators + class Module(core.module.Module): @core.decorators.every(minutes=60) def __init__(self, config, theme): super().__init__(config, theme, core.widget.Widget(self.full_text)) def full_text(self, widgets): - return 'debug' + return "debug" def state(self, widget): - return 'warning' + return "warning" + # vim: tabstop=8 expandtab shiftwidth=4 softtabstop=4 diff --git a/modules/core/disk.py b/modules/core/disk.py index bcd9328..12c7a16 100644 --- a/modules/core/disk.py +++ b/modules/core/disk.py @@ -1,6 +1,6 @@ # pylint: disable=C0111,R0903 -'''Shows free diskspace, total diskspace and the percentage of free disk space. +"""Shows free diskspace, total diskspace and the percentage of free disk space. Parameters: * disk.warning: Warning threshold in % of disk space (defaults to 80%) @@ -8,7 +8,7 @@ Parameters: * disk.path: Path to calculate disk usage from (defaults to /) * disk.open: Which application / file manager to launch (default xdg-open) * disk.format: Format string, tags {path}, {used}, {left}, {size} and {percent} (defaults to '{path} {used}/{size} ({percent:05.02f}%)') -''' +""" import os @@ -18,20 +18,24 @@ import core.input import util.format + class Module(core.module.Module): def __init__(self, config, theme): super().__init__(config, theme, core.widget.Widget(self.diskspace)) - self._path = self.parameter('path', '/') - self._format = self.parameter('format', '{used}/{size} ({percent:05.02f}%)') + self._path = self.parameter("path", "/") + self._format = self.parameter("format", "{used}/{size} ({percent:05.02f}%)") self._used = 0 self._left = 0 self._size = 0 self._percent = 0 - core.input.register(self, button=core.input.LEFT_MOUSE, - cmd='{} {}'.format(self.parameter('open', 'xdg-open'), self._path)) + core.input.register( + self, + button=core.input.LEFT_MOUSE, + cmd="{} {}".format(self.parameter("open", "xdg-open"), self._path), + ) def diskspace(self, widget): used_str = util.format.byte(self._used) @@ -39,20 +43,23 @@ class Module(core.module.Module): left_str = util.format.byte(self._left) percent_str = self._percent - return self._format.format(path=self._path, - used=used_str, - left=left_str, - size=size_str, - percent=percent_str) + return self._format.format( + path=self._path, + used=used_str, + left=left_str, + size=size_str, + percent=percent_str, + ) def update(self): st = os.statvfs(self._path) self._size = st.f_blocks * st.f_frsize self._used = (st.f_blocks - st.f_bfree) * st.f_frsize - self._left = self._size - self._used; - self._percent = 100.0 * self._used/self._size + self._left = self._size - self._used + self._percent = 100.0 * self._used / self._size def state(self, widget): return self.threshold_state(self._percent, 80, 90) + # vim: tabstop=8 expandtab shiftwidth=4 softtabstop=4 diff --git a/modules/core/error.py b/modules/core/error.py index 959a52f..968d4bb 100644 --- a/modules/core/error.py +++ b/modules/core/error.py @@ -8,23 +8,26 @@ import core.module import core.widget import core.event + class Module(core.module.Module): def __init__(self, config, theme): super().__init__(config, theme, core.widget.Widget(self.full_text)) - self.__error = '' - self.__state = 'critical' + self.__error = "" + self.__state = "critical" - core.event.register('error', self.__set_error) + core.event.register("error", self.__set_error) def full_text(self, widgets): return self.__error - def __set_error(self, error='n/a', state='critical'): + def __set_error(self, error="n/a", state="critical"): self.__error = error self.__state = state def state(self, widget): - if self.__error: return [self.__state] + if self.__error: + return [self.__state] return [] + # vim: tabstop=8 expandtab shiftwidth=4 softtabstop=4 diff --git a/modules/core/git.py b/modules/core/git.py index f9b4b87..e9966f6 100644 --- a/modules/core/git.py +++ b/modules/core/git.py @@ -16,6 +16,7 @@ import core.widget import util.cli + class Module(core.module.Module): def __init__(self, config, theme): super().__init__(config, theme, []) @@ -33,40 +34,49 @@ class Module(core.module.Module): directory = self.__get_git_root(directory) repo = pygit2.Repository(directory) - new_widgets.append(core.widget.Widget(name='git.main', full_text=repo.head.shorthand)) + new_widgets.append( + core.widget.Widget(name="git.main", full_text=repo.head.shorthand) + ) for filepath, flags in repo.status().items(): - if flags == pygit2.GIT_STATUS_WT_NEW or \ - flags == pygit2.GIT_STATUS_INDEX_NEW: - state['new'] = True - if flags == pygit2.GIT_STATUS_WT_DELETED or \ - flags == pygit2.GIT_STATUS_INDEX_DELETED: - state['deleted'] = True - if flags == pygit2.GIT_STATUS_WT_MODIFIED or \ - flags == pygit2.GIT_STATUS_INDEX_MODIFIED: - state['modified'] = True + if ( + flags == pygit2.GIT_STATUS_WT_NEW + or flags == pygit2.GIT_STATUS_INDEX_NEW + ): + state["new"] = True + if ( + flags == pygit2.GIT_STATUS_WT_DELETED + or flags == pygit2.GIT_STATUS_INDEX_DELETED + ): + state["deleted"] = True + if ( + flags == pygit2.GIT_STATUS_WT_MODIFIED + or flags == pygit2.GIT_STATUS_INDEX_MODIFIED + ): + state["modified"] = True self.__error = False - if 'new' in state: - new_widgets.append(core.widget.Widget(name='git.new')) - if 'modified' in state: - new_widgets.append(core.widget.Widget(name='git.modified')) - if 'deleted' in state: - new_widgets.append(core.widget.Widget(name='git.deleted')) + if "new" in state: + new_widgets.append(core.widget.Widget(name="git.new")) + if "modified" in state: + new_widgets.append(core.widget.Widget(name="git.modified")) + if "deleted" in state: + new_widgets.append(core.widget.Widget(name="git.deleted")) self.widgets().clear() self.widget(new_widgets) - + except Exception as e: self.__error = True def state(self, widget): - return widget.name.split('.')[1] + return widget.name.split(".")[1] def __get_git_root(self, directory): while len(directory) > 1: if os.path.exists(os.path.join(directory, ".git")): return directory directory = "/".join(directory.split("/")[0:-1]) - return "/" + return "/" + # vim: tabstop=8 expandtab shiftwidth=4 softtabstop=4 diff --git a/modules/core/kernel.py b/modules/core/kernel.py index 1432a05..32b6542 100644 --- a/modules/core/kernel.py +++ b/modules/core/kernel.py @@ -8,6 +8,7 @@ import core.module import core.widget import core.decorators + class Module(core.module.Module): @core.decorators.every(minutes=60) def __init__(self, config, theme): @@ -16,4 +17,5 @@ class Module(core.module.Module): def full_text(self, widgets): return platform.release() + # vim: tabstop=8 expandtab shiftwidth=4 softtabstop=4 diff --git a/modules/core/layout-xkb.py b/modules/core/layout-xkb.py index 1b02900..4d1dc7a 100644 --- a/modules/core/layout-xkb.py +++ b/modules/core/layout-xkb.py @@ -15,6 +15,7 @@ Parameters: from xkbgroup import * import logging + log = logging.getLogger(__name__) import core.module @@ -23,15 +24,14 @@ import core.input import util.format + class Module(core.module.Module): def __init__(self, config, theme): super().__init__(config, theme, core.widget.Widget(self.current_layout)) - core.input.register(self, button=core.input.LEFT_MOUSE, - cmd=self.__next_keymap) - core.input.register(self, button=core.input.RIGHT_MOUSE, - cmd=self.__prev_keymap) - self.__show_variant = util.format.asbool(self.parameter('show_variant', True)) + core.input.register(self, button=core.input.LEFT_MOUSE, cmd=self.__next_keymap) + core.input.register(self, button=core.input.RIGHT_MOUSE, cmd=self.__prev_keymap) + self.__show_variant = util.format.asbool(self.parameter("show_variant", True)) def __next_keymap(self, event): self.__set_keymap(1) @@ -41,7 +41,8 @@ class Module(core.module.Module): def __set_keymap(self, rotation): xkb = XKeyboard() - if xkb.groups_count < 2: return # nothing to do + if xkb.groups_count < 2: + return # nothing to do layouts = xkb.groups_symbols idx = layouts.index(xkb.group_symbol) xkb.group_symbol = str(layouts[(idx + rotation) % len(layouts)]) @@ -49,13 +50,22 @@ class Module(core.module.Module): def current_layout(self, widget): try: xkb = XKeyboard() - log.debug('group num: {}'.format(xkb.group_num)) - name = xkb.group_name if util.format.asbool(self.parameter('showname'), False) else xkb.group_symbol + log.debug("group num: {}".format(xkb.group_num)) + name = ( + xkb.group_name + if util.format.asbool(self.parameter("showname"), False) + else xkb.group_symbol + ) if self.__show_variant: - return '{} ({})'.format(name, xkb.group_variant) if xkb.group_variant else name + return ( + "{} ({})".format(name, xkb.group_variant) + if xkb.group_variant + else name + ) return name except Exception as e: - print('got exception: {}'.format(e)) - return 'n/a' + print("got exception: {}".format(e)) + return "n/a" + # vim: tabstop=8 expandtab shiftwidth=4 softtabstop=4 diff --git a/modules/core/load.py b/modules/core/load.py index 646a876..7ca839b 100644 --- a/modules/core/load.py +++ b/modules/core/load.py @@ -1,11 +1,11 @@ # pylint: disable=C0111,R0903 -'''Displays system load. +"""Displays system load. Parameters: * load.warning : Warning threshold for the one-minute load average (defaults to 70% of the number of CPUs) * load.critical: Critical threshold for the one-minute load average (defaults to 80% of the number of CPUs) -''' +""" import os import multiprocessing @@ -13,6 +13,7 @@ import multiprocessing import core.module import core.input + class Module(core.module.Module): def __init__(self, config, theme): super().__init__(config, theme, core.widget.Widget(self.load)) @@ -21,11 +22,12 @@ class Module(core.module.Module): self._cpus = multiprocessing.cpu_count() except NotImplementedError as e: self._cpus = 1 - core.input.register(self, button=core.input.LEFT_MOUSE, - cmd='gnome-system-monitor') + core.input.register( + self, button=core.input.LEFT_MOUSE, cmd="gnome-system-monitor" + ) def load(self, widget): - return '{:.02f}/{:.02f}/{:.02f}'.format( + return "{:.02f}/{:.02f}/{:.02f}".format( self._load[0], self._load[1], self._load[2] ) @@ -33,6 +35,7 @@ class Module(core.module.Module): self._load = os.getloadavg() def state(self, widget): - return self.threshold_state(self._load[0], self._cpus*0.7, self._cpus*0.8) + return self.threshold_state(self._load[0], self._cpus * 0.7, self._cpus * 0.8) + # vim: tabstop=8 expandtab shiftwidth=4 softtabstop=4 diff --git a/modules/core/memory.py b/modules/core/memory.py index 544cd12..7ce7545 100644 --- a/modules/core/memory.py +++ b/modules/core/memory.py @@ -1,13 +1,13 @@ # pylint: disable=C0111,R0903 -'''Displays available RAM, total amount of RAM and percentage available. +"""Displays available RAM, total amount of RAM and percentage available. Parameters: * memory.warning : Warning threshold in % of memory used (defaults to 80%) * memory.critical: Critical threshold in % of memory used (defaults to 90%) * memory.format: Format string (defaults to '{used}/{total} ({percent:05.02f}%)') * memory.usedonly: Only show the amount of RAM in use (defaults to False). Same as memory.format='{used}' -''' +""" import re @@ -17,49 +17,61 @@ import core.input import util.format + class Module(core.module.Module): def __init__(self, config, theme): super().__init__(config, theme, core.widget.Widget(self.memory_usage)) - core.input.register(self, button=core.input.LEFT_MOUSE, - cmd='gnome-system-monitor') + core.input.register( + self, button=core.input.LEFT_MOUSE, cmd="gnome-system-monitor" + ) @property def _format(self): - if util.format.asbool(self.parameter('usedonly', False)): - return '{used}' + if util.format.asbool(self.parameter("usedonly", False)): + return "{used}" else: - return self.parameter('format', '{used}/{total} ({percent:05.02f}%)') + return self.parameter("format", "{used}/{total} ({percent:05.02f}%)") def memory_usage(self, widget): return self._format.format(**self._mem) def update(self): data = {} - with open('/proc/meminfo', 'r') as f: + with open("/proc/meminfo", "r") as f: for line in f: - tmp = re.split(r'[:\s]+', line) + tmp = re.split(r"[:\s]+", line) value = int(tmp[1]) - if tmp[2] == 'kB': value = value*1024 - if tmp[2] == 'mB': value = value*1024*1024 - if tmp[2] == 'gB': value = value*1024*1024*1024 + if tmp[2] == "kB": + value = value * 1024 + if tmp[2] == "mB": + value = value * 1024 * 1024 + if tmp[2] == "gB": + value = value * 1024 * 1024 * 1024 data[tmp[0]] = value - if 'MemAvailable' in data: - used = data['MemTotal'] - data['MemAvailable'] + if "MemAvailable" in data: + used = data["MemTotal"] - data["MemAvailable"] else: - used = data['MemTotal'] - data['MemFree'] - data['Buffers'] - data['Cached'] - data['Slab'] + used = ( + data["MemTotal"] + - data["MemFree"] + - data["Buffers"] + - data["Cached"] + - data["Slab"] + ) self._mem = { - 'total': util.format.byte(data['MemTotal']), - 'available': util.format.byte(data['MemAvailable']), - 'free': util.format.byte(data['MemFree']), - 'used': util.format.byte(used), - 'percent': float(used)/float(data['MemTotal'])*100.0 + "total": util.format.byte(data["MemTotal"]), + "available": util.format.byte(data["MemAvailable"]), + "free": util.format.byte(data["MemFree"]), + "used": util.format.byte(used), + "percent": float(used) / float(data["MemTotal"]) * 100.0, } def state(self, widget): - if self._mem['percent'] > float(self.parameter('critical', 90)): - return 'critical' - if self._mem['percent'] > float(self.parameter('warning', 80)): - return 'warning' + if self._mem["percent"] > float(self.parameter("critical", 90)): + return "critical" + if self._mem["percent"] > float(self.parameter("warning", 80)): + return "warning" return None + # vim: tabstop=8 expandtab shiftwidth=4 softtabstop=4 diff --git a/modules/core/nic.py b/modules/core/nic.py index b2ec324..c92b7d3 100644 --- a/modules/core/nic.py +++ b/modules/core/nic.py @@ -1,4 +1,4 @@ -#pylint: disable=C0111,R0903 +# pylint: disable=C0111,R0903 """Displays the name, IP address(es) and status of each available network interface. @@ -22,22 +22,30 @@ import core.decorators import util.cli import util.format + class Module(core.module.Module): @core.decorators.every(seconds=10) def __init__(self, config, theme): widgets = [] super().__init__(config, theme, widgets) - self._exclude = tuple(filter(len, self.parameter('exclude', 'lo,virbr,docker,vboxnet,veth,br').split(','))) - self._include = self.parameter('include', '').split(',') + self._exclude = tuple( + filter( + len, + self.parameter("exclude", "lo,virbr,docker,vboxnet,veth,br").split(","), + ) + ) + self._include = self.parameter("include", "").split(",") - self._states = { 'include': [], 'exclude': [] } - for state in tuple(filter(len, util.format.aslist(self.parameter('states', '')))): - if state[0] == '^': - self._states['exclude'].append(state[1:]) + self._states = {"include": [], "exclude": []} + for state in tuple( + filter(len, util.format.aslist(self.parameter("states", ""))) + ): + if state[0] == "^": + self._states["exclude"].append(state[1:]) else: - self._states['include'].append(state) - self._format = self.parameter('format','{intf} {state} {ip} {ssid}'); - self.iwgetid = shutil.which('iwgetid') + self._states["include"].append(state) + self._format = self.parameter("format", "{intf} {state} {ip} {ssid}") + self.iwgetid = shutil.which("iwgetid") self._update_widgets(widgets) def update(self): @@ -46,71 +54,91 @@ class Module(core.module.Module): def state(self, widget): states = [] - if widget.get('state') == 'down': - states.append('critical') - elif widget.get('state') != 'up': - states.append('warning') + if widget.get("state") == "down": + states.append("critical") + elif widget.get("state") != "up": + states.append("warning") - intf = widget.get('intf') - iftype = 'wireless' if self._iswlan(intf) else 'wired' - iftype = 'tunnel' if self._istunnel(intf) else iftype + intf = widget.get("intf") + iftype = "wireless" if self._iswlan(intf) else "wired" + iftype = "tunnel" if self._istunnel(intf) else iftype - states.append('{}-{}'.format(iftype, widget.get('state'))) + states.append("{}-{}".format(iftype, widget.get("state"))) return states def _iswlan(self, intf): # wifi, wlan, wlp, seems to work for me - if intf.startswith('w'): return True + if intf.startswith("w"): + return True return False def _istunnel(self, intf): - return intf.startswith('tun') or intf.startswith('wg') + return intf.startswith("tun") or intf.startswith("wg") def get_addresses(self, intf): retval = [] try: for ip in netifaces.ifaddresses(intf).get(netifaces.AF_INET, []): - if ip.get('addr', '') != '': - retval.append(ip.get('addr')) + if ip.get("addr", "") != "": + retval.append(ip.get("addr")) except Exception: return [] return retval def _update_widgets(self, widgets): - interfaces = [i for i in netifaces.interfaces() if not i.startswith(self._exclude)] + interfaces = [ + i for i in netifaces.interfaces() if not i.startswith(self._exclude) + ] interfaces.extend([i for i in netifaces.interfaces() if i in self._include]) for widget in widgets: - widget.set('visited', False) + widget.set("visited", False) for intf in interfaces: addr = [] - state = 'down' + state = "down" for ip in self.get_addresses(intf): addr.append(ip) - state = 'up' + state = "up" - if len(self._states['exclude']) > 0 and state in self._states['exclude']: continue - if len(self._states['include']) > 0 and state not in self._states['include']: continue + if len(self._states["exclude"]) > 0 and state in self._states["exclude"]: + continue + if ( + len(self._states["include"]) > 0 + and state not in self._states["include"] + ): + continue widget = self.widget(intf) if not widget: widget = core.widget.Widget(name=intf, module=self) widgets.append(widget) # join/split is used to get rid of multiple whitespaces (in case SSID is not available, for instance - widget.full_text(' '.join(self._format.format(ip=', '.join(addr),intf=intf,state=state,ssid=self.get_ssid(intf)).split())) - widget.set('intf', intf) - widget.set('state', state) - widget.set('visited', True) + widget.full_text( + " ".join( + self._format.format( + ip=", ".join(addr), + intf=intf, + state=state, + ssid=self.get_ssid(intf), + ).split() + ) + ) + widget.set("intf", intf) + widget.set("state", state) + widget.set("visited", True) for widget in widgets: - if widget.get('visited') is False: + if widget.get("visited") is False: widgets.remove(widget) def get_ssid(self, intf): if self._iswlan(intf) and self.iwgetid: - return util.cli.execute('{} -r {}'.format(self.iwgetid, intf), ignore_errors=True) - return '' + return util.cli.execute( + "{} -r {}".format(self.iwgetid, intf), ignore_errors=True + ) + return "" + # vim: tabstop=8 expandtab shiftwidth=4 softtabstop=4 diff --git a/modules/core/pasink.py b/modules/core/pasink.py index ba30597..85dadd2 100644 --- a/modules/core/pasink.py +++ b/modules/core/pasink.py @@ -1,7 +1,9 @@ from .__pulseaudio import Module + class Module(Module): def __init__(self, config, theme): - super().__init__(config, theme, 'sink') + super().__init__(config, theme, "sink") + # vim: tabstop=8 expandtab shiftwidth=4 softtabstop=4 diff --git a/modules/core/pasource.py b/modules/core/pasource.py index 7640d82..103cf15 100644 --- a/modules/core/pasource.py +++ b/modules/core/pasource.py @@ -1,7 +1,9 @@ from .__pulseaudio import Module + class Module(Module): def __init__(self, config, theme): - super().__init__(config, theme, 'source') + super().__init__(config, theme, "source") + # vim: tabstop=8 expandtab shiftwidth=4 softtabstop=4 diff --git a/modules/core/ping.py b/modules/core/ping.py index a5ae490..bd740d7 100644 --- a/modules/core/ping.py +++ b/modules/core/ping.py @@ -24,30 +24,39 @@ import core.decorators import util.cli + def get_rtt(module, widget): try: - widget.set('rtt-unreachable', False) - res = util.cli.execute('ping -n -q -c {} -W {} {}'.format( - widget.get('rtt-probes'), widget.get('rtt-timeout'), widget.get('address') - )) + widget.set("rtt-unreachable", False) + res = util.cli.execute( + "ping -n -q -c {} -W {} {}".format( + widget.get("rtt-probes"), + widget.get("rtt-timeout"), + widget.get("address"), + ) + ) - for line in res.split('\n'): - if line.startswith('{} packets transmitted'.format(widget.get('rtt-probes'))): - m = re.search(r'(\d+)% packet loss', line) + for line in res.split("\n"): + if line.startswith( + "{} packets transmitted".format(widget.get("rtt-probes")) + ): + m = re.search(r"(\d+)% packet loss", line) - widget.set('packet-loss', m.group(1)) + widget.set("packet-loss", m.group(1)) - if not line.startswith('rtt'): continue - m = re.search(r'([0-9\.]+)/([0-9\.]+)/([0-9\.]+)/([0-9\.]+)\s+(\S+)', line) + if not line.startswith("rtt"): + continue + m = re.search(r"([0-9\.]+)/([0-9\.]+)/([0-9\.]+)/([0-9\.]+)\s+(\S+)", line) - widget.set('rtt-min', float(m.group(1))) - widget.set('rtt-avg', float(m.group(2))) - widget.set('rtt-max', float(m.group(3))) - widget.set('rtt-unit', m.group(5)) + widget.set("rtt-min", float(m.group(1))) + widget.set("rtt-avg", float(m.group(2))) + widget.set("rtt-max", float(m.group(3))) + widget.set("rtt-unit", m.group(5)) except Exception as e: - widget.set('rtt-unreachable', True) + widget.set("rtt-unreachable", True) + + core.event.trigger("update", [module.id], redraw_only=True) - core.event.trigger('update', [ module.id ], redraw_only=True) class Module(core.module.Module): @core.decorators.every(seconds=60) @@ -56,29 +65,31 @@ class Module(core.module.Module): widget = self.widget() - widget.set('address', self.parameter('address', '8.8.8.8')) - widget.set('rtt-probes', self.parameter('probes', 5)) - widget.set('rtt-timeout', self.parameter('timeout', 5.0)) - widget.set('rtt-avg', 0.0) - widget.set('rtt-unit', '') - widget.set('packet-loss', 0) + widget.set("address", self.parameter("address", "8.8.8.8")) + widget.set("rtt-probes", self.parameter("probes", 5)) + widget.set("rtt-timeout", self.parameter("timeout", 5.0)) + widget.set("rtt-avg", 0.0) + widget.set("rtt-unit", "") + widget.set("packet-loss", 0) def rtt(self, widget): - if widget.get('rtt-unreachable'): - return '{}: unreachable'.format(widget.get('address')) - return '{}: {:.1f}{} ({}%)'.format( - widget.get('address'), - widget.get('rtt-avg'), - widget.get('rtt-unit'), - widget.get('packet-loss') + if widget.get("rtt-unreachable"): + return "{}: unreachable".format(widget.get("address")) + return "{}: {:.1f}{} ({}%)".format( + widget.get("address"), + widget.get("rtt-avg"), + widget.get("rtt-unit"), + widget.get("packet-loss"), ) def state(self, widget): - if widget.get('rtt-unreachable'): return ['critical'] - return self.threshold_state(widget.get('rtt-avg'), 1000.0, 2000.0) + if widget.get("rtt-unreachable"): + return ["critical"] + return self.threshold_state(widget.get("rtt-avg"), 1000.0, 2000.0) def update(self): thread = threading.Thread(target=get_rtt, args=(self, self.widget(),)) thread.start() + # vim: tabstop=8 expandtab shiftwidth=4 softtabstop=4 diff --git a/modules/core/redshift.py b/modules/core/redshift.py index 1ad29d0..9eba599 100644 --- a/modules/core/redshift.py +++ b/modules/core/redshift.py @@ -24,45 +24,49 @@ import core.decorators import util.cli import util.location + def get_redshift_value(module): widget = module.widget() - location = module.parameter('location', 'auto') - lat = module.parameter('lat', None) - lon = module.parameter('lon', None) + location = module.parameter("location", "auto") + lat = module.parameter("lat", None) + lon = module.parameter("lon", None) # Even if location method is set to manual, if we have no lat or lon, # fall back to the geoclue2 method. - if location == 'manual' and (lat is None or lon is None): - location = 'geoclue2' + if location == "manual" and (lat is None or lon is None): + location = "geoclue2" - command = ['redshift', '-p'] - if location == 'manual': - command.extend(['-l', '{}:{}'.format(lat, lon)]) - if location == 'geoclue2': - command.extend(['-l', 'geoclue2']) + command = ["redshift", "-p"] + if location == "manual": + command.extend(["-l", "{}:{}".format(lat, lon)]) + if location == "geoclue2": + command.extend(["-l", "geoclue2"]) try: - res = util.cli.execute(' '.join(command)) + res = util.cli.execute(" ".join(command)) except Exception: - res = '' - widget.set('temp', 'n/a') - widget.set('transition', '') - widget.set('state', 'day') - for line in res.split('\n'): + res = "" + widget.set("temp", "n/a") + widget.set("transition", "") + widget.set("state", "day") + for line in res.split("\n"): line = line.lower() - if 'temperature' in line: - widget.set('temp', line.split(' ')[2]) - if 'period' in line: - state = line.split(' ')[1] - if 'day' in state: - widget.set('state', 'day') - elif 'night' in state: - widget.set('state', 'night') + if "temperature" in line: + widget.set("temp", line.split(" ")[2]) + if "period" in line: + state = line.split(" ")[1] + if "day" in state: + widget.set("state", "day") + elif "night" in state: + widget.set("state", "night") else: - widget.set('state', 'transition') - match = re.search(r'(\d+)\.\d+% ([a-z]+)', line) - widget.set('transition', '({}% {})'.format(match.group(1), match.group(2))) - core.event.trigger('update', [ widget.module.id ], redraw_only=True) + widget.set("state", "transition") + match = re.search(r"(\d+)\.\d+% ([a-z]+)", line) + widget.set( + "transition", "({}% {})".format(match.group(1), match.group(2)) + ) + core.event.trigger("update", [widget.module.id], redraw_only=True) + class Module(core.module.Module): @core.decorators.every(seconds=10) @@ -71,24 +75,24 @@ class Module(core.module.Module): self.__thread = None - if self.parameter('location', '') == 'ipinfo': + if self.parameter("location", "") == "ipinfo": # override lon/lat with ipinfo try: location = util.location.coordinates() - self.set('lat', location[0]) - self.set('lon', location[1]) - self.set('location', 'manual') + self.set("lat", location[0]) + self.set("lon", location[1]) + self.set("location", "manual") except Exception: # Fall back to geoclue2. - self.set('location', 'geoclue2') + self.set("location", "geoclue2") - self._text = '' + self._text = "" def text(self, widget): - val = widget.get('temp', 'n/a') - transition = widget.get('transition', '') + val = widget.get("temp", "n/a") + transition = widget.get("transition", "") if transition: - val = '{} {}'.format(val, transition) + val = "{} {}".format(val, transition) return val def update(self): @@ -98,6 +102,7 @@ class Module(core.module.Module): self.__thread.start() def state(self, widget): - return widget.get('state', None) + return widget.get("state", None) + # vim: tabstop=8 expandtab shiftwidth=4 softtabstop=4 diff --git a/modules/core/sensors2.py b/modules/core/sensors2.py index 64d553e..5f101fa 100644 --- a/modules/core/sensors2.py +++ b/modules/core/sensors2.py @@ -26,11 +26,12 @@ import core.widget import util.cli import util.format + class Module(core.module.Module): def __init__(self, config, theme): super().__init__(config, theme, []) - self.__chip = self.parameter('chip', '') + self.__chip = self.parameter("chip", "") self.__data = {} self.__update() @@ -42,31 +43,45 @@ class Module(core.module.Module): self.__update_widget(widget) def state(self, widget): - widget_type = widget.get('type', '') + widget_type = widget.get("type", "") try: - data = self.__data[widget.get('adapter')][widget.get('package')][widget.get('field')] - if 'crit' in data and float(data['input']) > float(data['crit']): - return ['critical', widget_type] - if 'max' in data and float(data['input']) > float(data['max']): - return ['warning', widget_type] + data = self.__data[widget.get("adapter")][widget.get("package")][ + widget.get("field") + ] + if "crit" in data and float(data["input"]) > float(data["crit"]): + return ["critical", widget_type] + if "max" in data and float(data["input"]) > float(data["max"]): + return ["warning", widget_type] except: pass return [widget_type] def __create_widgets(self): - show_temp = util.format.asbool(self.parameter('showtemp', True)) - show_fan = util.format.asbool(self.parameter('showfan', True)) - show_other = util.format.asbool(self.parameter('showother', False)) - include_chip = tuple(filter(len, util.format.aslist(self.parameter('chip_include', '')))) - exclude_chip = tuple(filter(len, util.format.aslist(self.parameter('chip_exclude', '')))) - include_field = tuple(filter(len, util.format.aslist(self.parameter('field_include', '')))) - exclude_field = tuple(filter(len, util.format.aslist(self.parameter('field_exclude', '')))) - include_chip_field = tuple(filter(len, util.format.aslist(self.parameter('chip_field_include', '')))) - exclude_chip_field = tuple(filter(len, util.format.aslist(self.parameter('chip_field_exclude', '')))) + show_temp = util.format.asbool(self.parameter("showtemp", True)) + show_fan = util.format.asbool(self.parameter("showfan", True)) + show_other = util.format.asbool(self.parameter("showother", False)) + include_chip = tuple( + filter(len, util.format.aslist(self.parameter("chip_include", ""))) + ) + exclude_chip = tuple( + filter(len, util.format.aslist(self.parameter("chip_exclude", ""))) + ) + include_field = tuple( + filter(len, util.format.aslist(self.parameter("field_include", ""))) + ) + exclude_field = tuple( + filter(len, util.format.aslist(self.parameter("field_exclude", ""))) + ) + include_chip_field = tuple( + filter(len, util.format.aslist(self.parameter("chip_field_include", ""))) + ) + exclude_chip_field = tuple( + filter(len, util.format.aslist(self.parameter("chip_field_exclude", ""))) + ) - if util.format.asbool(self.parameter('showcpu', True)): + if util.format.asbool(self.parameter("showcpu", True)): widget = self.add_widget(full_text=self.__cpu) - widget.set('type', 'cpu') + widget.set("type", "cpu") for adapter in self.__data: if include_chip or exclude_chip: @@ -79,23 +94,27 @@ class Module(core.module.Module): if include_chip_field: try: - if all([i.split('.')[0] not in adapter for i in include_chip_field]): + if all( + [i.split(".")[0] not in adapter for i in include_chip_field] + ): continue except: pass for package in self.__data[adapter]: - if util.format.asbool(self.parameter('showname', False)): + if util.format.asbool(self.parameter("showname", False)): widget = self.add_widget(full_text=package) - widget.set('data', self.__data[adapter][package]) - widget.set('package', package) - widget.set('field', '') - widget.set('adapter', adapter) + widget.set("data", self.__data[adapter][package]) + widget.set("package", package) + widget.set("field", "") + widget.set("adapter", adapter) for field in self.__data[adapter][package]: if include_field or exclude_field: if include_field: - if all([included not in field for included in include_field]): + if all( + [included not in field for included in include_field] + ): continue else: if any([excluded in field for excluded in exclude_field]): @@ -104,62 +123,79 @@ class Module(core.module.Module): try: if include_chip_field or exclude_chip_field: if include_chip_field: - if all([i.split('.')[1] not in field for i in include_chip_field if i.split('.')[0] in adapter]): + if all( + [ + i.split(".")[1] not in field + for i in include_chip_field + if i.split(".")[0] in adapter + ] + ): continue else: - if any([i.split('.')[1] in field for i in exclude_chip_field if i.split('.')[0] in adapter]): + if any( + [ + i.split(".")[1] in field + for i in exclude_chip_field + if i.split(".")[0] in adapter + ] + ): continue except: pass widget = None - if 'temp' in field and show_temp: + if "temp" in field and show_temp: # seems to be a temperature widget = self.add_widget() - widget.set('type', 'temp') - if 'fan' in field and show_fan: + widget.set("type", "temp") + if "fan" in field and show_fan: # seems to be a fan widget = self.add_widget() - widget.set('type', 'fan') + widget.set("type", "fan") elif show_other: # everything else widget = self.add_widget() - widget.set('type', 'other') + widget.set("type", "other") if widget: - widget.set('package', package) - widget.set('field', field) - widget.set('adapter', adapter) + widget.set("package", package) + widget.set("field", field) + widget.set("adapter", adapter) def __update_widget(self, widget): - if widget.get('field', '') == '': - return # nothing to do - data = self.__data[widget.get('adapter')][widget.get('package')][widget.get('field')] - if 'temp' in widget.get('field'): - widget.full_text(u'{:0.01f}°C'.format(data['input'])) - elif 'fan' in widget.get('field'): - widget.full_text(u'{:0.0f}RPM'.format(data['input'])) + if widget.get("field", "") == "": + return # nothing to do + data = self.__data[widget.get("adapter")][widget.get("package")][ + widget.get("field") + ] + if "temp" in widget.get("field"): + widget.full_text("{:0.01f}°C".format(data["input"])) + elif "fan" in widget.get("field"): + widget.full_text("{:0.0f}RPM".format(data["input"])) else: - widget.full_text(u'{:0.0f}'.format(data['input'])) + widget.full_text("{:0.0f}".format(data["input"])) def __update(self): - output = util.cli.execute('sensors -u {}'.format(self.__chip), ignore_errors=True) + output = util.cli.execute( + "sensors -u {}".format(self.__chip), ignore_errors=True + ) self.__data = self.__parse(output) def __parse(self, data): output = {} - package = '' + package = "" adapter = None chip = None - for line in data.split('\n'): - if 'Adapter' in line: + for line in data.split("\n"): + if "Adapter" in line: # new adapter - line = line.replace('Adapter: ', '') - output[chip + ' ' + line] = {} - adapter = chip + ' ' + line - chip = line #default - line before adapter is always the chip - if not adapter: continue - key, value = (line.split(':') + ['', ''])[:2] - if not line.startswith(' '): + line = line.replace("Adapter: ", "") + output[chip + " " + line] = {} + adapter = chip + " " + line + chip = line # default - line before adapter is always the chip + if not adapter: + continue + key, value = (line.split(":") + ["", ""])[:2] + if not line.startswith(" "): # assume this starts a new package if package in output[adapter] and output[adapter][package] == {}: del output[adapter][package] @@ -168,9 +204,9 @@ class Module(core.module.Module): else: # feature for this chip try: - name, variant = (key.strip().split('_', 1) + ['',''])[:2] + name, variant = (key.strip().split("_", 1) + ["", ""])[:2] if not name in output[adapter][package]: - output[adapter][package][name] = { } + output[adapter][package][name] = {} if variant: output[adapter][package][name][variant] = {} output[adapter][package][name][variant] = float(value) @@ -181,23 +217,26 @@ class Module(core.module.Module): def __cpu(self, _): mhz = None try: - output = open('/sys/devices/system/cpu/cpufreq/policy0/scaling_cur_freq').read() - mhz = int(float(output)/1000.0) + output = open( + "/sys/devices/system/cpu/cpufreq/policy0/scaling_cur_freq" + ).read() + mhz = int(float(output) / 1000.0) except: - output = open('/proc/cpuinfo').read() - m = re.search(r'cpu MHz\s+:\s+(\d+)', output) + output = open("/proc/cpuinfo").read() + m = re.search(r"cpu MHz\s+:\s+(\d+)", output) if m: mhz = int(m.group(1)) else: - m = re.search(r'BogoMIPS\s+:\s+(\d+)', output) + m = re.search(r"BogoMIPS\s+:\s+(\d+)", output) if m: - return '{} BogoMIPS'.format(int(m.group(1))) + return "{} BogoMIPS".format(int(m.group(1))) if not mhz: - return 'n/a' + return "n/a" if mhz < 1000: - return '{} MHz'.format(mhz) + return "{} MHz".format(mhz) else: - return '{:0.01f} GHz'.format(float(mhz)/1000.0) + return "{:0.01f} GHz".format(float(mhz) / 1000.0) + # vim: tabstop=8 expandtab shiftwidth=4 softtabstop=4 diff --git a/modules/core/spacer.py b/modules/core/spacer.py index 4ff8f3c..7e4453a 100644 --- a/modules/core/spacer.py +++ b/modules/core/spacer.py @@ -10,6 +10,7 @@ import core.module import core.widget import core.decorators + class Module(core.module.Module): @core.decorators.every(minutes=60) def __init__(self, config, theme): @@ -19,4 +20,5 @@ class Module(core.module.Module): def text(self, _): return self.__text + # vim: tabstop=8 expandtab shiftwidth=4 softtabstop=4 diff --git a/modules/core/test.py b/modules/core/test.py index 31c3a1c..030e581 100644 --- a/modules/core/test.py +++ b/modules/core/test.py @@ -6,8 +6,10 @@ import core.widget import core.module + class Module(core.module.Module): def __init__(self, config, theme): - super().__init__(config=config, theme=theme, widgets=core.widget.Widget('test')) + super().__init__(config=config, theme=theme, widgets=core.widget.Widget("test")) + # vim: tabstop=8 expandtab shiftwidth=4 softtabstop=4 diff --git a/modules/core/time.py b/modules/core/time.py index f92ff8f..1c2c4b1 100644 --- a/modules/core/time.py +++ b/modules/core/time.py @@ -10,12 +10,14 @@ Parameters: import core.decorators from .datetime import Module + class Module(Module): - @core.decorators.every(seconds=59) # ensures one update per minute + @core.decorators.every(seconds=59) # ensures one update per minute def __init__(self, config, theme): super().__init__(config, theme) def default_format(self): - return '%X' + return "%X" + # vim: tabstop=8 expandtab shiftwidth=4 softtabstop=4 diff --git a/modules/core/vault.py b/modules/core/vault.py index 8447b2d..cd627dc 100644 --- a/modules/core/vault.py +++ b/modules/core/vault.py @@ -12,7 +12,7 @@ Parameters: """ -# TODO: +# TODO: # - support multiple backends by abstracting the menu structure into a tree # - build the menu and the actions based on that abstracted tree # @@ -29,30 +29,39 @@ import core.event import util.cli import util.popup + def build_menu(parent, current_directory, callback): with os.scandir(current_directory) as it: for entry in it: - if entry.name.startswith('.'): continue + if entry.name.startswith("."): + continue if entry.is_file(): - name = entry.name[:entry.name.rfind('.')] - parent.add_menuitem(name, callback=lambda : callback(os.path.join(current_directory, name))) + name = entry.name[: entry.name.rfind(".")] + parent.add_menuitem( + name, + callback=lambda: callback(os.path.join(current_directory, name)), + ) else: submenu = util.popup.menu(parent, leave=False) - build_menu(submenu, os.path.join(current_directory, entry.name), callback) + build_menu( + submenu, os.path.join(current_directory, entry.name), callback + ) parent.add_cascade(entry.name, submenu) + class Module(core.module.Module): def __init__(self, config, theme): super().__init__(config, theme, core.widget.Widget(self.text)) - self.__duration = int(self.parameter('duration', 30)) - self.__offx = int(self.parameter('offx', 0)) - self.__offy = int(self.parameter('offy', 0)) - self.__path = os.path.expanduser(self.parameter('location', '~/.password-store/')) + self.__duration = int(self.parameter("duration", 30)) + self.__offx = int(self.parameter("offx", 0)) + self.__offy = int(self.parameter("offy", 0)) + self.__path = os.path.expanduser( + self.parameter("location", "~/.password-store/") + ) self.__reset() - core.input.register(self, button=core.input.LEFT_MOUSE, - cmd=self.popup) + core.input.register(self, button=core.input.LEFT_MOUSE, cmd=self.popup) def popup(self, widget): menu = util.popup.menu(leave=False) @@ -62,14 +71,17 @@ class Module(core.module.Module): def __reset(self): self.__timer = None - self.__text = str(self.parameter('text', '')) + self.__text = str(self.parameter("text", "")) def __callback(self, secret_name): - secret_name = secret_name.replace(self.__path, '') # remove common path + secret_name = secret_name.replace(self.__path, "") # remove common path if self.__timer: self.__timer.cancel() - res = util.cli.execute('pass -c {}'.format(secret_name), wait=False, - env={ 'PASSWORD_STORE_CLIP_TIME': self.__duration }) + res = util.cli.execute( + "pass -c {}".format(secret_name), + wait=False, + env={"PASSWORD_STORE_CLIP_TIME": self.__duration}, + ) self.__timer = threading.Timer(self.__duration, self.__reset) self.__timer.start() self.__start = int(time.time()) @@ -77,7 +89,10 @@ class Module(core.module.Module): def text(self, widget): if self.__timer: - return '{} ({}s)'.format(self.__text, self.__duration - (int(time.time()) - self.__start)) + return "{} ({}s)".format( + self.__text, self.__duration - (int(time.time()) - self.__start) + ) return self.__text + # vim: tabstop=8 expandtab shiftwidth=4 softtabstop=4 diff --git a/modules/core/xrandr.py b/modules/core/xrandr.py index 77cda49..47ca7a7 100644 --- a/modules/core/xrandr.py +++ b/modules/core/xrandr.py @@ -1,6 +1,6 @@ # pylint: disable=C0111,R0903 -'''Shows a widget for each connected screen and allows the user to enable/disable screens. +"""Shows a widget for each connected screen and allows the user to enable/disable screens. Parameters: * xrandr.overwrite_i3config: If set to 'true', this module assembles a new i3 config @@ -14,7 +14,7 @@ Requires the following python module: Requires the following executable: * xrandr -''' +""" import os import re @@ -33,17 +33,18 @@ try: except: pass + class Module(core.module.Module): - @core.decorators.every(seconds=5) # takes up to 5s to detect a new screen + @core.decorators.every(seconds=5) # takes up to 5s to detect a new screen def __init__(self, config, theme): widgets = [] super().__init__(config, theme, widgets) - self._autoupdate = util.format.asbool(self.parameter('autoupdate', True)) + self._autoupdate = util.format.asbool(self.parameter("autoupdate", True)) self._needs_update = True try: - i3.Subscription(self._output_update, 'output') + i3.Subscription(self._output_update, "output") except: pass @@ -58,31 +59,33 @@ class Module(core.module.Module): self._needs_update = False - for line in util.cli.execute('xrandr -q').split('\n'): - if not ' connected' in line: + for line in util.cli.execute("xrandr -q").split("\n"): + if not " connected" in line: continue - display = line.split(' ', 2)[0] - m = re.search(r'\d+x\d+\+(\d+)\+\d+', line) + display = line.split(" ", 2)[0] + m = re.search(r"\d+x\d+\+(\d+)\+\d+", line) widget = self.widget(display) if not widget: - widget = core.widget.Widget(full_text=display, name=display, module=self) + widget = core.widget.Widget( + full_text=display, name=display, module=self + ) core.input.register(widget, button=1, cmd=self._toggle) core.input.register(widget, button=3, cmd=self._toggle) new_widgets.append(widget) - widget.set('state', 'on' if m else 'off') - widget.set('pos', int(m.group(1)) if m else sys.maxsize) + widget.set("state", "on" if m else "off") + widget.set("pos", int(m.group(1)) if m else sys.maxsize) self.widgets(new_widgets) if self._autoupdate == False: - widget = core.widget.Widget(full_text='', module=self) - widget.set('state', 'refresh') + widget = core.widget.Widget(full_text="", module=self) + widget.set("state", "refresh") core.input.register(widget, button=1, cmd=self._refresh) self.widgets().append(widget) def state(self, widget): - return widget.get('state', 'off') + return widget.get("state", "off") def _refresh(self, event): self._needs_update = True @@ -91,26 +94,50 @@ class Module(core.module.Module): self._refresh(self, event) path = os.path.dirname(os.path.abspath(__file__)) - if util.format.asbool(self.parameter('overwrite_i3config', False)) == True: - toggle_cmd = '{}/../../bin/toggle-display.sh'.format(path) + if util.format.asbool(self.parameter("overwrite_i3config", False)) == True: + toggle_cmd = "{}/../../bin/toggle-display.sh".format(path) else: - toggle_cmd = 'xrandr' + toggle_cmd = "xrandr" - widget = self.widget_by_id(event['instance']) + widget = self.widget_by_id(event["instance"]) - if widget.get('state') == 'on': - util.cli.execute('{} --output {} --off'.format(toggle_cmd, widget.name)) + if widget.get("state") == "on": + util.cli.execute("{} --output {} --off".format(toggle_cmd, widget.name)) else: - first_neighbor = next((widget for widget in self.widgets() if widget.get('state') == 'on'), None) - last_neighbor = next((widget for widget in reversed(self.widgets()) if widget.get('state') == 'on'), None) + first_neighbor = next( + (widget for widget in self.widgets() if widget.get("state") == "on"), + None, + ) + last_neighbor = next( + ( + widget + for widget in reversed(self.widgets()) + if widget.get("state") == "on" + ), + None, + ) - neighbor = first_neighbor if event['button'] == core.input.LEFT_MOUSE else last_neighbor + neighbor = ( + first_neighbor + if event["button"] == core.input.LEFT_MOUSE + else last_neighbor + ) if neighbor is None: - util.cli.execute('{} --output {} --auto'.format(toggle_cmd, widget.name)) + util.cli.execute( + "{} --output {} --auto".format(toggle_cmd, widget.name) + ) else: - util.cli.execute('{} --output {} --auto --{}-of {}'.format(toggle_cmd, widget.name, - 'left' if event.get('button') == core.input.LEFT_MOUSE else 'right', - neighbor.name)) + util.cli.execute( + "{} --output {} --auto --{}-of {}".format( + toggle_cmd, + widget.name, + "left" + if event.get("button") == core.input.LEFT_MOUSE + else "right", + neighbor.name, + ) + ) + # vim: tabstop=8 expandtab shiftwidth=4 softtabstop=4 diff --git a/tests/core/test_config.py b/tests/core/test_config.py index 161796f..a3b8ea9 100644 --- a/tests/core/test_config.py +++ b/tests/core/test_config.py @@ -3,74 +3,83 @@ import unittest import core.config + class config(unittest.TestCase): def setUp(self): - self.someModules = [ 'b', 'x', 'a' ] - self.moreModules = [ 'this', 'module', 'here' ] - self.someTheme = 'some-theme' - self.someIconset = 'some-iconset' + self.someModules = ["b", "x", "a"] + self.moreModules = ["this", "module", "here"] + self.someTheme = "some-theme" + self.someIconset = "some-iconset" self.defaultConfig = core.config.Config([]) def test_module(self): - cfg = core.config.Config([ '-m' ] + self.someModules) + cfg = core.config.Config(["-m"] + self.someModules) self.assertEqual(self.someModules, cfg.modules()) def test_module_ordering_maintained(self): - cfg = core.config.Config([ '-m' ] + self.someModules + [ '-m' ] + self.moreModules) + cfg = core.config.Config(["-m"] + self.someModules + ["-m"] + self.moreModules) self.assertEqual(self.someModules + self.moreModules, cfg.modules()) def test_default_interval(self): self.assertEqual(1, self.defaultConfig.interval()) def test_interval(self): - cfg = core.config.Config([ '-p', 'interval=4']) + cfg = core.config.Config(["-p", "interval=4"]) self.assertEqual(4, cfg.interval()) def test_float_interval(self): - cfg = core.config.Config([ '-p', 'interval=0.5']) + cfg = core.config.Config(["-p", "interval=0.5"]) self.assertEqual(0.5, cfg.interval()) def test_default_theme(self): - self.assertEqual('default', self.defaultConfig.theme()) + self.assertEqual("default", self.defaultConfig.theme()) def test_theme(self): - cfg = core.config.Config(['-t', self.someTheme]) + cfg = core.config.Config(["-t", self.someTheme]) self.assertEqual(self.someTheme, cfg.theme()) def test_default_iconset(self): - self.assertEqual('auto', self.defaultConfig.iconset()) + self.assertEqual("auto", self.defaultConfig.iconset()) def test_iconset(self): - cfg = core.config.Config(['-i', self.someIconset]) + cfg = core.config.Config(["-i", self.someIconset]) self.assertEqual(self.someIconset, cfg.iconset()) def test_right_to_left(self): - cfg = core.config.Config(['-r']) + cfg = core.config.Config(["-r"]) self.assertTrue(cfg.reverse()) self.assertFalse(self.defaultConfig.reverse()) def test_logfile(self): - cfg = core.config.Config(['-f', 'my-custom-logfile']) + cfg = core.config.Config(["-f", "my-custom-logfile"]) self.assertEquals(None, self.defaultConfig.logfile()) - self.assertEquals('my-custom-logfile', cfg.logfile()) + self.assertEquals("my-custom-logfile", cfg.logfile()) def test_all_modules(self): modules = core.config.all_modules() self.assertGreater(len(modules), 0) for module in modules: - pyname = '{}.py'.format(module) - base = os.path.abspath(os.path.join(os.path.dirname(os.path.realpath(__file__)), '..', '..', 'modules')) - self.assertTrue(os.path.exists(os.path.join(base, 'contrib', pyname)) or os.path.exists(os.path.join(base, 'core', pyname))) + pyname = "{}.py".format(module) + base = os.path.abspath( + os.path.join( + os.path.dirname(os.path.realpath(__file__)), "..", "..", "modules" + ) + ) + self.assertTrue( + os.path.exists(os.path.join(base, "contrib", pyname)) + or os.path.exists(os.path.join(base, "core", pyname)) + ) def test_list_output(self): - with unittest.mock.patch('core.config.sys') as sys: - cfg = core.config.Config([ '-l', 'themes' ]) - cfg = core.config.Config([ '-l', 'modules' ]) - cfg = core.config.Config([ '-l', 'modules-markdown' ]) + with unittest.mock.patch("core.config.sys") as sys: + cfg = core.config.Config(["-l", "themes"]) + cfg = core.config.Config(["-l", "modules"]) + cfg = core.config.Config(["-l", "modules-markdown"]) # TODO: think of some plausibility testing here def test_missing_parameter(self): - cfg = core.config.Config([ '-p', 'test.key' ]) - self.assertEqual('no-value-set', cfg.get('test.key', 'no-value-set')) + cfg = core.config.Config(["-p", "test.key"]) + self.assertEqual("no-value-set", cfg.get("test.key", "no-value-set")) + # vim: tabstop=8 expandtab shiftwidth=4 softtabstop=4 diff --git a/tests/core/test_decorators.py b/tests/core/test_decorators.py index fb3c37e..bbf7691 100644 --- a/tests/core/test_decorators.py +++ b/tests/core/test_decorators.py @@ -5,59 +5,62 @@ import core.widget import core.module import core.config + class TestModule(core.module.Module): def __init__(self, config=None, theme=None): config = core.config.Config([]) super().__init__(config, theme, core.widget.Widget(self.get)) - self.text = '' + self.text = "" @core.decorators.scrollable def get(self, widget): return self.text + class config(unittest.TestCase): def setUp(self): self.module = TestModule() self.widget = self.module.widget() self.width = 10 - self.module.set('width', self.width) + self.module.set("width", self.width) def test_no_text(self): - self.assertEqual('', self.module.text) - self.assertEqual('', self.module.get(self.widget)) + self.assertEqual("", self.module.text) + self.assertEqual("", self.module.get(self.widget)) def test_smaller(self): - self.module.text = 'test' + self.module.text = "test" self.assertLess(len(self.module.text), self.width) - self.assertEqual('test', self.module.get(self.widget)) + self.assertEqual("test", self.module.get(self.widget)) def test_bigger(self): - self.module.text = 'abcdefghijklmnopqrst' + self.module.text = "abcdefghijklmnopqrst" self.assertGreater(len(self.module.text), self.width) - self.assertEqual(self.module.text[:self.width], self.module.get(self.widget)) + self.assertEqual(self.module.text[: self.width], self.module.get(self.widget)) def test_bounce(self): - self.module.text = 'abcd' - self.module.set('width', 2) - self.assertEqual('ab', self.module.get(self.widget)) - self.assertEqual('bc', self.module.get(self.widget)) - self.assertEqual('cd', self.module.get(self.widget)) - self.assertEqual('bc', self.module.get(self.widget)) - self.assertEqual('ab', self.module.get(self.widget)) - self.assertEqual('bc', self.module.get(self.widget)) - self.assertEqual('cd', self.module.get(self.widget)) - self.assertEqual('bc', self.module.get(self.widget)) - self.assertEqual('ab', self.module.get(self.widget)) + self.module.text = "abcd" + self.module.set("width", 2) + self.assertEqual("ab", self.module.get(self.widget)) + self.assertEqual("bc", self.module.get(self.widget)) + self.assertEqual("cd", self.module.get(self.widget)) + self.assertEqual("bc", self.module.get(self.widget)) + self.assertEqual("ab", self.module.get(self.widget)) + self.assertEqual("bc", self.module.get(self.widget)) + self.assertEqual("cd", self.module.get(self.widget)) + self.assertEqual("bc", self.module.get(self.widget)) + self.assertEqual("ab", self.module.get(self.widget)) def test_nobounce(self): - self.module.set('scrolling.bounce', False) - self.module.text = 'abcd' - self.module.set('width', 2) - self.assertEqual('ab', self.module.get(self.widget)) - self.assertEqual('bc', self.module.get(self.widget)) - self.assertEqual('cd', self.module.get(self.widget)) - self.assertEqual('ab', self.module.get(self.widget)) - self.assertEqual('bc', self.module.get(self.widget)) - self.assertEqual('cd', self.module.get(self.widget)) + self.module.set("scrolling.bounce", False) + self.module.text = "abcd" + self.module.set("width", 2) + self.assertEqual("ab", self.module.get(self.widget)) + self.assertEqual("bc", self.module.get(self.widget)) + self.assertEqual("cd", self.module.get(self.widget)) + self.assertEqual("ab", self.module.get(self.widget)) + self.assertEqual("bc", self.module.get(self.widget)) + self.assertEqual("cd", self.module.get(self.widget)) + # vim: tabstop=8 expandtab shiftwidth=4 softtabstop=4 diff --git a/tests/core/test_event.py b/tests/core/test_event.py index 9f5866c..e256bc4 100644 --- a/tests/core/test_event.py +++ b/tests/core/test_event.py @@ -2,25 +2,26 @@ import unittest import core.event + class event(unittest.TestCase): def setUp(self): - self.someEvent = 'event' + self.someEvent = "event" self.called = {} self.params = [] core.event.clear() def callback1(self): - self.called['callback1'] = True + self.called["callback1"] = True def callback2(self): - self.called['callback2'] = True + self.called["callback2"] = True def callback_args(self, val1, val2): - self.called['callback_args'] = True + self.called["callback_args"] = True self.params = [val1, val2] def callback_kwargs(self, val1, val2, key1=None, key2=None): - self.called['callback_kwargs'] = True + self.called["callback_kwargs"] = True self.params = [val1, val2, key1, key2] def test_simple_callback(self): @@ -32,27 +33,30 @@ class event(unittest.TestCase): self.assertEqual(2, len(self.called.keys())) def test_arg_callback(self): - core.event.register(self.someEvent, self.callback_args, 'a', 'b') + core.event.register(self.someEvent, self.callback_args, "a", "b") core.event.trigger(self.someEvent) self.assertEqual(1, len(self.called.keys())) - self.assertEqual(['a', 'b'], self.params) + self.assertEqual(["a", "b"], self.params) def test_kwargs_callback(self): - core.event.register(self.someEvent, self.callback_kwargs, 'a', 'b', key1='test', key2='x') + core.event.register( + self.someEvent, self.callback_kwargs, "a", "b", key1="test", key2="x" + ) core.event.trigger(self.someEvent) self.assertEqual(1, len(self.called.keys())) - self.assertEqual(['a', 'b', 'test', 'x'], self.params) + self.assertEqual(["a", "b", "test", "x"], self.params) def test_arg_trigger(self): core.event.register(self.someEvent, self.callback_args) - core.event.trigger(self.someEvent, 'a', 'b') + core.event.trigger(self.someEvent, "a", "b") self.assertEqual(1, len(self.called.keys())) - self.assertEqual(['a', 'b'], self.params) + self.assertEqual(["a", "b"], self.params) def test_kwargs_trigger(self): core.event.register(self.someEvent, self.callback_kwargs) - core.event.trigger(self.someEvent, 'a', 'b', key1='test', key2='x') + core.event.trigger(self.someEvent, "a", "b", key1="test", key2="x") self.assertEqual(1, len(self.called.keys())) - self.assertEqual(['a', 'b', 'test', 'x'], self.params) + self.assertEqual(["a", "b", "test", "x"], self.params) + # vim: tabstop=8 expandtab shiftwidth=4 softtabstop=4 diff --git a/tests/core/test_input.py b/tests/core/test_input.py index 9d7885e..667184a 100644 --- a/tests/core/test_input.py +++ b/tests/core/test_input.py @@ -2,31 +2,44 @@ import unittest import core.input + class config(unittest.TestCase): def setUp(self): self.inputObject = core.input.Object() self.anotherObject = core.input.Object() - self.someEvent = { 'button': core.input.LEFT_MOUSE, 'instance': self.inputObject.id } - self.anotherEvent = { 'button': core.input.RIGHT_MOUSE, 'instance': self.inputObject.id} + self.someEvent = { + "button": core.input.LEFT_MOUSE, + "instance": self.inputObject.id, + } + self.anotherEvent = { + "button": core.input.RIGHT_MOUSE, + "instance": self.inputObject.id, + } self.callback = unittest.mock.MagicMock() self.callback2 = unittest.mock.MagicMock() - self.someCommand = 'some sample command' + self.someCommand = "some sample command" def test_callable_gets_called(self): - core.input.register(self.inputObject, self.someEvent['button'], self.callback) + core.input.register(self.inputObject, self.someEvent["button"], self.callback) core.input.trigger(self.someEvent) self.callback.assert_called_once_with(self.someEvent) def test_nonexistent_callback(self): - core.input.register(self.inputObject, self.someEvent['button'], self.callback) + core.input.register(self.inputObject, self.someEvent["button"], self.callback) core.input.trigger(self.anotherEvent) self.callback.assert_not_called() def test_different_events(self): - core.input.register(self.inputObject, self.someEvent['button'], self.callback) - core.input.register(self.inputObject, self.anotherEvent['button'], self.callback) - core.input.register(self.anotherObject, self.someEvent['button'], self.callback2) - core.input.register(self.anotherObject, self.anotherEvent['button'], self.callback2) + core.input.register(self.inputObject, self.someEvent["button"], self.callback) + core.input.register( + self.inputObject, self.anotherEvent["button"], self.callback + ) + core.input.register( + self.anotherObject, self.someEvent["button"], self.callback2 + ) + core.input.register( + self.anotherObject, self.anotherEvent["button"], self.callback2 + ) core.input.trigger(self.someEvent) core.input.trigger(self.anotherEvent) self.callback.assert_any_call(self.someEvent) @@ -34,35 +47,42 @@ class config(unittest.TestCase): self.callback2.assert_not_called() def test_multiple_registrations(self): - core.input.register(self.inputObject, self.someEvent['button'], self.callback) - core.input.register(self.inputObject, self.someEvent['button'], self.callback2) + core.input.register(self.inputObject, self.someEvent["button"], self.callback) + core.input.register(self.inputObject, self.someEvent["button"], self.callback2) core.input.trigger(self.someEvent) self.callback.assert_called_once_with(self.someEvent) self.callback2.assert_called_once_with(self.someEvent) def test_event_names(self): - self.assertEqual(core.input.button_name(core.input.LEFT_MOUSE), 'left-mouse') - self.assertEqual(core.input.button_name(core.input.RIGHT_MOUSE), 'right-mouse') - self.assertEqual(core.input.button_name(core.input.MIDDLE_MOUSE), 'middle-mouse') - self.assertEqual(core.input.button_name(core.input.WHEEL_UP), 'wheel-up') - self.assertEqual(core.input.button_name(core.input.WHEEL_DOWN), 'wheel-down') - self.assertEqual(core.input.button_name(12345), 'n/a') + self.assertEqual(core.input.button_name(core.input.LEFT_MOUSE), "left-mouse") + self.assertEqual(core.input.button_name(core.input.RIGHT_MOUSE), "right-mouse") + self.assertEqual( + core.input.button_name(core.input.MIDDLE_MOUSE), "middle-mouse" + ) + self.assertEqual(core.input.button_name(core.input.WHEEL_UP), "wheel-up") + self.assertEqual(core.input.button_name(core.input.WHEEL_DOWN), "wheel-down") + self.assertEqual(core.input.button_name(12345), "n/a") def test_non_callable_callback(self): - with unittest.mock.patch('core.input.util.cli') as cli: - cli.execute.return_value = '' - core.input.register(self.inputObject, self.someEvent['button'], self.someCommand) + with unittest.mock.patch("core.input.util.cli") as cli: + cli.execute.return_value = "" + core.input.register( + self.inputObject, self.someEvent["button"], self.someCommand + ) core.input.trigger(self.someEvent) cli.execute.assert_called_once_with(self.someCommand, wait=False) def test_non_existent_callback(self): - with unittest.mock.patch('core.input.util.cli') as cli: - cli.execute.return_value = '' - cli.execute.side_effect = RuntimeError('some-error') - core.input.register(self.inputObject, self.someEvent['button'], self.someCommand) + with unittest.mock.patch("core.input.util.cli") as cli: + cli.execute.return_value = "" + cli.execute.side_effect = RuntimeError("some-error") + core.input.register( + self.inputObject, self.someEvent["button"], self.someCommand + ) try: core.input.trigger(self.someEvent) except Exception: - self.fail('input module propagated exception') + self.fail("input module propagated exception") + # vim: tabstop=8 expandtab shiftwidth=4 softtabstop=4 diff --git a/tests/core/test_module.py b/tests/core/test_module.py index 1d82a7e..71f59ad 100644 --- a/tests/core/test_module.py +++ b/tests/core/test_module.py @@ -7,91 +7,116 @@ import core.module import core.widget import core.config + class TestModule(core.module.Module): def update(self): if self.fail: raise Exception(self.error) pass + class module(unittest.TestCase): def setUp(self): - self.invalidModuleName = 'invalid-module-name' - self.validModuleName = 'test' - self.someWidget = core.widget.Widget('randomeWidgetContent', name='A') - self.anotherWidget = core.widget.Widget('more Widget content', name='B') - self.unusedWidgetName = 'C' + self.invalidModuleName = "invalid-module-name" + self.validModuleName = "test" + self.someWidget = core.widget.Widget("randomeWidgetContent", name="A") + self.anotherWidget = core.widget.Widget("more Widget content", name="B") + self.unusedWidgetName = "C" def test_loadinvalid_module(self): config = unittest.mock.MagicMock() module = core.module.load(module_name=self.invalidModuleName, config=config) - self.assertEqual('core.module', module.__class__.__module__, 'module must be a module object') - self.assertEqual('Error', module.__class__.__name__, 'an invalid module must be a core.module.Error') + self.assertEqual( + "core.module", module.__class__.__module__, "module must be a module object" + ) + self.assertEqual( + "Error", + module.__class__.__name__, + "an invalid module must be a core.module.Error", + ) - @unittest.skipIf(sys.version_info.major == 3 and sys.version_info.minor in [ 4, 5 ], 'importlib error reporting in Python 3.{4,5} different') + @unittest.skipIf( + sys.version_info.major == 3 and sys.version_info.minor in [4, 5], + "importlib error reporting in Python 3.{4,5} different", + ) def test_importerror(self): - with unittest.mock.patch('core.module.importlib') as importlib: - importlib.import_module.side_effect = ImportError('some-error') + with unittest.mock.patch("core.module.importlib") as importlib: + importlib.import_module.side_effect = ImportError("some-error") config = unittest.mock.MagicMock() module = core.module.load(module_name=self.validModuleName, config=config) module.widget().full_text() - self.assertEqual('Error', module.__class__.__name__, 'an invalid module must be a core.module.Error') - self.assertEqual(module.widget().full_text(), 'test: some-error') + self.assertEqual( + "Error", + module.__class__.__name__, + "an invalid module must be a core.module.Error", + ) + self.assertEqual(module.widget().full_text(), "test: some-error") def test_loadvalid_module(self): module = core.module.load(module_name=self.validModuleName) - self.assertEqual('modules.core.{}'.format(self.validModuleName), module.__class__.__module__, 'module must be a modules.core. object') - self.assertEqual('Module', module.__class__.__name__, 'a valid module must have a Module class') - self.assertEqual([], module.state(None), 'default state of module is empty') + self.assertEqual( + "modules.core.{}".format(self.validModuleName), + module.__class__.__module__, + "module must be a modules.core. object", + ) + self.assertEqual( + "Module", + module.__class__.__name__, + "a valid module must have a Module class", + ) + self.assertEqual([], module.state(None), "default state of module is empty") def test_empty_widgets(self): module = core.module.Module(widgets=[]) self.assertEqual([], module.widgets()) def test_error_widget(self): - cfg = core.config.Config(shlex.split('-p test_module.foo=5')) - module = core.module.Error(cfg, 'test-mod', 'xyz') - self.assertEqual(['critical'], module.state(None), 'error module must have critical state') + cfg = core.config.Config(shlex.split("-p test_module.foo=5")) + module = core.module.Error(cfg, "test-mod", "xyz") + self.assertEqual( + ["critical"], module.state(None), "error module must have critical state" + ) full_text = module.full_text(module.widget()) - self.assertTrue('test-mod' in full_text) - self.assertTrue('xyz' in full_text) + self.assertTrue("test-mod" in full_text) + self.assertTrue("xyz" in full_text) def test_single_widget(self): module = core.module.Module(widgets=self.someWidget) self.assertEqual([self.someWidget], module.widgets()) def test_widget_list(self): - module = core.module.Module(widgets=[ self.someWidget, self.anotherWidget ]) - self.assertEqual([ self.someWidget, self.anotherWidget ], module.widgets()) + module = core.module.Module(widgets=[self.someWidget, self.anotherWidget]) + self.assertEqual([self.someWidget, self.anotherWidget], module.widgets()) def test_module_Name(self): module = TestModule() - self.assertEqual('test_module', module.name, 'module has wrong name') - self.assertEqual('test_module', module.module_name, 'module has wrong name') + self.assertEqual("test_module", module.name, "module has wrong name") + self.assertEqual("test_module", module.module_name, "module has wrong name") def testvalid_parameter(self): - cfg = core.config.Config(shlex.split('-p test_module.foo=5')) + cfg = core.config.Config(shlex.split("-p test_module.foo=5")) module = TestModule(config=cfg) - self.assertEqual(5, int(module.parameter('foo'))) + self.assertEqual(5, int(module.parameter("foo"))) def test_default_parameter(self): cfg = core.config.Config([]) module = TestModule(config=cfg) - self.assertEqual('default', module.parameter('foo', 'default')) + self.assertEqual("default", module.parameter("foo", "default")) def test_default_is_none(self): cfg = core.config.Config([]) module = TestModule(config=cfg) - self.assertEqual(None, module.parameter('foo')) + self.assertEqual(None, module.parameter("foo")) def test_error_widget(self): cfg = core.config.Config([]) module = TestModule(config=cfg) module.fail = True - module.error = '!!' + module.error = "!!" module.update_wrapper() self.assertEqual(1, len(module.widgets())) - self.assertEqual('error: !!', module.widget().full_text()) + self.assertEqual("error: !!", module.widget().full_text()) def test_get_widget_by_name(self): cfg = core.config.Config([]) @@ -106,10 +131,11 @@ class module(unittest.TestCase): cfg = core.config.Config([]) module = TestModule(config=cfg, widgets=[self.someWidget, self.anotherWidget]) - self.assertEqual('critical', module.threshold_state(100, 80, 99)) - self.assertEqual('warning', module.threshold_state(100, 80, 100)) - self.assertEqual('warning', module.threshold_state(81, 80, 100)) + self.assertEqual("critical", module.threshold_state(100, 80, 99)) + self.assertEqual("warning", module.threshold_state(100, 80, 100)) + self.assertEqual("warning", module.threshold_state(81, 80, 100)) self.assertEqual(None, module.threshold_state(80, 80, 100)) self.assertEqual(None, module.threshold_state(10, 80, 100)) + # vim: tabstop=8 expandtab shiftwidth=4 softtabstop=4 diff --git a/tests/core/test_output.py b/tests/core/test_output.py index 87c1017..b5dc2c2 100644 --- a/tests/core/test_output.py +++ b/tests/core/test_output.py @@ -5,76 +5,93 @@ import core.config import core.output import core.module + class TestModule(core.module.Module): pass + class i3(unittest.TestCase): def setUp(self): self.i3 = core.output.i3() widget = unittest.mock.MagicMock() widget.full_text.return_value = "test" - self.someModule = TestModule(config=core.config.Config([]), - widgets=[widget, widget, widget]) - self.paddedTheme = core.theme.Theme(raw_data = { - 'defaults': { 'padding': ' ' } - }) - self.separator = '***'; - self.separatorTheme = core.theme.Theme(raw_data = { - 'defaults': { 'separator': self.separator, 'fg': 'red', 'bg': 'blue' } - }) + self.someModule = TestModule( + config=core.config.Config([]), widgets=[widget, widget, widget] + ) + self.paddedTheme = core.theme.Theme(raw_data={"defaults": {"padding": " "}}) + self.separator = "***" + self.separatorTheme = core.theme.Theme( + raw_data={ + "defaults": {"separator": self.separator, "fg": "red", "bg": "blue"} + } + ) self.someBlock = core.output.block( theme=self.separatorTheme, - module=self.someModule, - widget=self.someModule.widget() + module=self.someModule, + widget=self.someModule.widget(), ) def test_start(self): core.event.clear() all_data = self.i3.start() - data = all_data['blocks'] - self.assertEqual(1, data['version'], 'i3bar protocol version 1 expected') - self.assertTrue(data['click_events'], 'click events should be enabled') - self.assertEqual('\n[', all_data['suffix']) + data = all_data["blocks"] + self.assertEqual(1, data["version"], "i3bar protocol version 1 expected") + self.assertTrue(data["click_events"], "click events should be enabled") + self.assertEqual("\n[", all_data["suffix"]) def test_stop(self): - self.assertEqual('\n]', self.i3.stop()['suffix'], 'wrong i3bar protocol during stop') + self.assertEqual( + "\n]", self.i3.stop()["suffix"], "wrong i3bar protocol during stop" + ) def test_no_modules_by_default(self): - self.assertEqual(0, len(self.i3.modules()), 'module list should be empty by default') + self.assertEqual( + 0, len(self.i3.modules()), "module list should be empty by default" + ) def test_register_single_module(self): self.i3.modules(self.someModule) - self.assertEqual(1, len(self.i3.modules()), 'setting single module does not work') + self.assertEqual( + 1, len(self.i3.modules()), "setting single module does not work" + ) def test_register_multiple_modules(self): - self.i3.modules([ self.someModule, self.someModule, self.someModule ]) - self.assertEqual(3, len(self.i3.modules()), 'setting module list does not work') + self.i3.modules([self.someModule, self.someModule, self.someModule]) + self.assertEqual(3, len(self.i3.modules()), "setting module list does not work") def test_draw_existing_module(self): - self.i3.test_draw = unittest.mock.MagicMock(return_value={ - 'blocks': { 'test': True }, 'suffix': 'end' - }) - self.i3.draw('test_draw') + self.i3.test_draw = unittest.mock.MagicMock( + return_value={"blocks": {"test": True}, "suffix": "end"} + ) + self.i3.draw("test_draw") self.i3.test_draw.assert_called_once_with() def test_empty_status_line(self): data = self.i3.statusline() - self.assertEqual([], data['blocks'], 'expected empty list of status line entries') - self.assertEqual(',', data['suffix'], 'expected "," as suffix') + self.assertEqual( + [], data["blocks"], "expected empty list of status line entries" + ) + self.assertEqual(",", data["suffix"], 'expected "," as suffix') def test_statusline(self): - self.i3.modules([ self.someModule, self.someModule, self.someModule ]) + self.i3.modules([self.someModule, self.someModule, self.someModule]) self.i3.update() data = self.i3.statusline() - self.assertEqual(len(self.someModule.widgets())*3, len(data['blocks']), 'wrong number of widgets') + self.assertEqual( + len(self.someModule.widgets()) * 3, + len(data["blocks"]), + "wrong number of widgets", + ) def test_padding(self): self.i3.theme(self.paddedTheme) - blk = core.output.block(self.i3.theme(), self.someModule, self.someModule.widget()) - blk.set('full_text', 'abc') - result = blk.dict()['full_text'] - self.assertEqual(' abc ', result) + blk = core.output.block( + self.i3.theme(), self.someModule, self.someModule.widget() + ) + blk.set("full_text", "abc") + result = blk.dict()["full_text"] + self.assertEqual(" abc ", result) def test_no_separator(self): result = self.i3.__separator_block(self.someModule, self.someModule.widget()) @@ -84,9 +101,12 @@ class i3(unittest.TestCase): self.i3.theme(self.separatorTheme) result = self.i3.__separator_block(self.someModule, self.someModule.widget()) self.assertEqual(1, len(result)) - self.assertEqual('***', result[0].dict()['full_text']) - self.assertTrue(result[0].dict().get('_decorator', False)) - self.assertEqual(self.separatorTheme.get('bg', self.someModule.widget()), result[0].dict()['color']) + self.assertEqual("***", result[0].dict()["full_text"]) + self.assertTrue(result[0].dict().get("_decorator", False)) + self.assertEqual( + self.separatorTheme.get("bg", self.someModule.widget()), + result[0].dict()["color"], + ) def test_dump_json(self): obj = unittest.mock.MagicMock() @@ -95,47 +115,48 @@ class i3(unittest.TestCase): obj.dict_assert_called_once_with() def test_assign(self): - src = { - 'a': 'x', 'b': 'y', 'c': 'z' - } + src = {"a": "x", "b": "y", "c": "z"} dst = {} - core.output.assign(src, dst, 'a') - self.assertEqual(dst['a'], src['a']) + core.output.assign(src, dst, "a") + self.assertEqual(dst["a"], src["a"]) - core.output.assign(src, dst, '123', 'b') - self.assertEqual(dst['123'], src['b']) + core.output.assign(src, dst, "123", "b") + self.assertEqual(dst["123"], src["b"]) - core.output.assign(src, dst, 'blub', default='def') - self.assertEqual('def', dst['blub']) + core.output.assign(src, dst, "blub", default="def") + self.assertEqual("def", dst["blub"]) def test_pango_detection(self): self.assertFalse(self.someBlock.is_pango({})) - self.assertTrue(self.someBlock.is_pango({ 'pango': {} })) + self.assertTrue(self.someBlock.is_pango({"pango": {}})) def test_pangoize(self): - self.assertEqual('test', self.someBlock.pangoize('test')) - self.assertFalse('markup' in self.someBlock.dict()) + self.assertEqual("test", self.someBlock.pangoize("test")) + self.assertFalse("markup" in self.someBlock.dict()) - pango = self.someBlock.pangoize({ 'pango': { 'attr': 'blub', 'x': 'y', 'full_text': 'test' } }) + pango = self.someBlock.pangoize( + {"pango": {"attr": "blub", "x": "y", "full_text": "test"}} + ) self.assertTrue('attr="blub"' in pango) self.assertTrue('x="y"' in pango) - self.assertTrue('test' in pango) - self.assertEqual('pango', self.someBlock.dict()['markup']) + self.assertTrue("test" in pango) + self.assertEqual("pango", self.someBlock.dict()["markup"]) def test_padding(self): - self.someBlock.set('padding', '***') - self.someBlock.set('full_text', 'test') + self.someBlock.set("padding", "***") + self.someBlock.set("full_text", "test") - self.assertEqual('***test***', self.someBlock.dict()['full_text']) + self.assertEqual("***test***", self.someBlock.dict()["full_text"]) def test_pre_suffix(self): - self.someBlock.set('padding', '*') - self.someBlock.set('prefix', 'pre') - self.someBlock.set('suffix', 'suf') - self.someBlock.set('full_text', 'test') + self.someBlock.set("padding", "*") + self.someBlock.set("prefix", "pre") + self.someBlock.set("suffix", "suf") + self.someBlock.set("full_text", "test") + + self.assertEqual("*pre*test*suf*", self.someBlock.dict()["full_text"]) - self.assertEqual('*pre*test*suf*', self.someBlock.dict()['full_text']) # vim: tabstop=8 expandtab shiftwidth=4 softtabstop=4 diff --git a/tests/core/test_theme.py b/tests/core/test_theme.py index 1865992..027a9b3 100644 --- a/tests/core/test_theme.py +++ b/tests/core/test_theme.py @@ -5,40 +5,24 @@ import core.theme import core.event import core.widget + class theme(unittest.TestCase): def setUp(self): core.event.clear() - self.invalidThemeName = 'this-theme-does-not-exist' - self.validThemeName = 'default' - self.defaultsTheme = { - 'defaults': { - 'fg': 'red', 'bg': 'black' - } - } + self.invalidThemeName = "this-theme-does-not-exist" + self.validThemeName = "default" + self.defaultsTheme = {"defaults": {"fg": "red", "bg": "black"}} self.cycleTheme = { - 'cycle': [ - { 'fg': 'red', 'bg': 'black' }, - { 'fg': 'black', 'bg': 'red' }, - { 'fg': 'white', 'bg': 'blue' } + "cycle": [ + {"fg": "red", "bg": "black"}, + {"fg": "black", "bg": "red"}, + {"fg": "white", "bg": "blue"}, ] } - self.colorTheme = { - 'colors': [{ - 'red': '#ff0000', 'blue': '#0000ff' - }] - } - self.walTheme = { - 'colors': ['wal'] - } - self.cycleValueTheme = { - 'defaults': { - 'fg': [ 'red', 'green', 'blue' ] - } - } - self.stateTheme = { - 'warning': { 'fg': 'yellow' }, - 'critical': { 'fg': 'red' } - } + self.colorTheme = {"colors": [{"red": "#ff0000", "blue": "#0000ff"}]} + self.walTheme = {"colors": ["wal"]} + self.cycleValueTheme = {"defaults": {"fg": ["red", "green", "blue"]}} + self.stateTheme = {"warning": {"fg": "yellow"}, "critical": {"fg": "red"}} def test_invalid_theme(self): with self.assertRaises(RuntimeError): @@ -50,82 +34,85 @@ class theme(unittest.TestCase): def test_defaults(self): theme = core.theme.Theme(raw_data=self.defaultsTheme) - self.assertEqual(self.defaultsTheme['defaults']['fg'], theme.get('fg')) - self.assertEqual(self.defaultsTheme['defaults']['bg'], theme.get('bg')) + self.assertEqual(self.defaultsTheme["defaults"]["fg"], theme.get("fg")) + self.assertEqual(self.defaultsTheme["defaults"]["bg"], theme.get("bg")) def test_cycle(self): theme = core.theme.Theme(raw_data=self.cycleTheme) - self.assertEqual(None, theme.get('prev-bg')) - self.assertEqual(self.cycleTheme['cycle'][0]['fg'], theme.get('fg')) - self.assertEqual(self.cycleTheme['cycle'][0]['bg'], theme.get('bg')) - core.event.trigger('next-widget') - self.assertEqual(self.cycleTheme['cycle'][0]['bg'], theme.get('bg', 'previous')) - core.event.trigger('next-widget') - self.assertEqual(self.cycleTheme['cycle'][2]['fg'], theme.get('fg')) - self.assertEqual(self.cycleTheme['cycle'][2]['bg'], theme.get('bg')) + self.assertEqual(None, theme.get("prev-bg")) + self.assertEqual(self.cycleTheme["cycle"][0]["fg"], theme.get("fg")) + self.assertEqual(self.cycleTheme["cycle"][0]["bg"], theme.get("bg")) + core.event.trigger("next-widget") + self.assertEqual(self.cycleTheme["cycle"][0]["bg"], theme.get("bg", "previous")) + core.event.trigger("next-widget") + self.assertEqual(self.cycleTheme["cycle"][2]["fg"], theme.get("fg")) + self.assertEqual(self.cycleTheme["cycle"][2]["bg"], theme.get("bg")) - with unittest.mock.patch('core.output.sys.stdout'): - core.event.trigger('draw') - self.assertEqual(self.cycleTheme['cycle'][0]['fg'], theme.get('fg')) - self.assertEqual(self.cycleTheme['cycle'][0]['bg'], theme.get('bg')) + with unittest.mock.patch("core.output.sys.stdout"): + core.event.trigger("draw") + self.assertEqual(self.cycleTheme["cycle"][0]["fg"], theme.get("fg")) + self.assertEqual(self.cycleTheme["cycle"][0]["bg"], theme.get("bg")) def test_custom_iconset(self): theme = core.theme.Theme(raw_data=self.defaultsTheme) - self.assertNotEqual('aaa', theme.get('padding')) - theme = core.theme.Theme(raw_data=self.defaultsTheme, iconset={ - 'defaults': { 'padding': 'aaa' } - }) - self.assertEqual('aaa', theme.get('padding')) + self.assertNotEqual("aaa", theme.get("padding")) + theme = core.theme.Theme( + raw_data=self.defaultsTheme, iconset={"defaults": {"padding": "aaa"}} + ) + self.assertEqual("aaa", theme.get("padding")) def test_colors(self): theme = core.theme.Theme(raw_data=self.defaultsTheme) self.assertEqual({}, theme.keywords()) theme = core.theme.Theme(raw_data=self.colorTheme) - self.assertEqual(self.colorTheme['colors'][0], theme.keywords()) + self.assertEqual(self.colorTheme["colors"][0], theme.keywords()) def test_wal_colors(self): - with unittest.mock.patch('core.theme.io') as io: - with unittest.mock.patch('core.theme.os') as os: + with unittest.mock.patch("core.theme.io") as io: + with unittest.mock.patch("core.theme.os") as os: os.path.isfile.return_value = True io.open.return_value = unittest.mock.MagicMock() - io.open.return_value.__enter__.return_value.read.return_value=''' + io.open.return_value.__enter__.return_value.read.return_value = """ { "colors": { "red": "#ff0000" } } - ''' + """ theme = core.theme.Theme(raw_data=self.walTheme) - self.assertEqual({'red': '#ff0000'}, theme.keywords()) + self.assertEqual({"red": "#ff0000"}, theme.keywords()) def test_wal_special(self): - with unittest.mock.patch('core.theme.io') as io: - with unittest.mock.patch('core.theme.os') as os: + with unittest.mock.patch("core.theme.io") as io: + with unittest.mock.patch("core.theme.os") as os: os.path.isfile.return_value = True - io.open.return_value.__enter__.return_value.read.return_value=''' + io.open.return_value.__enter__.return_value.read.return_value = """ { "special": { "background": "#ff0000" } } - ''' + """ theme = core.theme.Theme(raw_data=self.walTheme) - self.assertEqual({'background': '#ff0000'}, theme.keywords()) + self.assertEqual({"background": "#ff0000"}, theme.keywords()) def test_cycle_value(self): widget = core.widget.Widget() - expected = self.cycleValueTheme['defaults']['fg'] + expected = self.cycleValueTheme["defaults"]["fg"] theme = core.theme.Theme(raw_data=self.cycleValueTheme) - for i in range(0, len(expected)*3): - self.assertEqual(expected[i%len(expected)], theme.get('fg', widget)) - self.assertEqual(expected[i%len(expected)], theme.get('fg', widget)) # ensure multiple invocations are OK - core.event.trigger('draw') + for i in range(0, len(expected) * 3): + self.assertEqual(expected[i % len(expected)], theme.get("fg", widget)) + self.assertEqual( + expected[i % len(expected)], theme.get("fg", widget) + ) # ensure multiple invocations are OK + core.event.trigger("draw") def test_state(self): widget = core.widget.Widget() theme = core.theme.Theme(raw_data=self.stateTheme) - self.assertEqual(None, theme.get('fg', widget)) + self.assertEqual(None, theme.get("fg", widget)) - widget.state = types.MethodType(lambda self: ['warning'], widget) - self.assertEqual(self.stateTheme['warning']['fg'], theme.get('fg', widget)) + widget.state = types.MethodType(lambda self: ["warning"], widget) + self.assertEqual(self.stateTheme["warning"]["fg"], theme.get("fg", widget)) + + widget.state = types.MethodType(lambda self: ["critical"], widget) + self.assertEqual(self.stateTheme["critical"]["fg"], theme.get("fg", widget)) - widget.state = types.MethodType(lambda self: ['critical'], widget) - self.assertEqual(self.stateTheme['critical']['fg'], theme.get('fg', widget)) # vim: tabstop=8 expandtab shiftwidth=4 softtabstop=4 diff --git a/tests/core/test_widget.py b/tests/core/test_widget.py index e71cba2..1f5e471 100644 --- a/tests/core/test_widget.py +++ b/tests/core/test_widget.py @@ -5,6 +5,7 @@ import core.widget import core.module import core.config + class TestModule(core.module.Module): def __init__(self, widgets, config=core.config.Config([]), theme=None): super().__init__(config, theme, widgets) @@ -18,13 +19,16 @@ class TestModule(core.module.Module): def state(self, widget): return self.states + class widget(unittest.TestCase): def setUp(self): - self.someValue = 'some random value' - self.someOtherValue = 'some different value' - self.callbackReturnValue = 'callback return value' + self.someValue = "some random value" + self.someOtherValue = "some different value" + self.callbackReturnValue = "callback return value" self.someWidget = core.widget.Widget(full_text=self.someValue) - self.someCallback = unittest.mock.MagicMock(return_value=self.callbackReturnValue) + self.someCallback = unittest.mock.MagicMock( + return_value=self.callbackReturnValue + ) self.assertNotEqual(self.someValue, self.someOtherValue) @@ -54,38 +58,38 @@ class widget(unittest.TestCase): self.assertEqual([], self.someWidget.state()) def test_single_widget_state(self): - self.someWidget.set('state', 'state1') - self.assertEqual(['state1'], self.someWidget.state()) + self.someWidget.set("state", "state1") + self.assertEqual(["state1"], self.someWidget.state()) def test_multiple_widget_states(self): - self.someWidget.set('state', ['state1', 'state2']) - self.assertEqual(['state1', 'state2'], self.someWidget.state()) + self.someWidget.set("state", ["state1", "state2"]) + self.assertEqual(["state1", "state2"], self.someWidget.state()) def test_widget_module_state(self): module = TestModule(widgets=self.someWidget) - self.someWidget.set('state', ['state1', 'state2']) + self.someWidget.set("state", ["state1", "state2"]) - module.states = 'x' - self.assertEqual(['state1', 'state2', 'x'], self.someWidget.state()) - module.states = ['a', 'b'] - self.assertEqual(['state1', 'state2', 'a', 'b'], self.someWidget.state()) + module.states = "x" + self.assertEqual(["state1", "state2", "x"], self.someWidget.state()) + module.states = ["a", "b"] + self.assertEqual(["state1", "state2", "a", "b"], self.someWidget.state()) def test_multiple_widget_themes(self): - widget1 = core.widget.Widget(full_text='a') - widget2 = core.widget.Widget(full_text='b') - widget3 = core.widget.Widget(full_text='c') + widget1 = core.widget.Widget(full_text="a") + widget2 = core.widget.Widget(full_text="b") + widget3 = core.widget.Widget(full_text="c") module = TestModule(widgets=[widget1, widget2, widget3]) - module.set('theme.test', '1,2,3') - module.set('theme.test2', 'x') + module.set("theme.test", "1,2,3") + module.set("theme.test2", "x") - self.assertEqual('1', widget1.theme('test')) - self.assertEqual('2', widget2.theme('test')) - self.assertEqual('3', widget3.theme('test')) + self.assertEqual("1", widget1.theme("test")) + self.assertEqual("2", widget2.theme("test")) + self.assertEqual("3", widget3.theme("test")) - self.assertEqual('x', widget1.theme('test2')) - self.assertEqual(None, widget2.theme('test2')) - self.assertEqual(None, widget3.theme('test2')) + self.assertEqual("x", widget1.theme("test2")) + self.assertEqual(None, widget2.theme("test2")) + self.assertEqual(None, widget3.theme("test2")) # vim: tabstop=8 expandtab shiftwidth=4 softtabstop=4 diff --git a/tests/modules/test_kernel.py b/tests/modules/test_kernel.py index 8d5034e..4c50483 100644 --- a/tests/modules/test_kernel.py +++ b/tests/modules/test_kernel.py @@ -3,15 +3,19 @@ import unittest import core.config import modules.core.kernel + class kernel(unittest.TestCase): def setUp(self): - self.someKernel = 'this-is-my-kernel' - self.module = modules.core.kernel.Module(config=core.config.Config([]), theme=None) + self.someKernel = "this-is-my-kernel" + self.module = modules.core.kernel.Module( + config=core.config.Config([]), theme=None + ) def test_full_text(self): - with unittest.mock.patch('modules.core.kernel.platform') as platform: + with unittest.mock.patch("modules.core.kernel.platform") as platform: platform.release.return_value = self.someKernel self.assertEqual(1, len(self.module.widgets())) self.assertEqual(self.someKernel, self.module.widget().full_text()) + # vim: tabstop=8 expandtab shiftwidth=4 softtabstop=4 diff --git a/tests/util/test_algorithm.py b/tests/util/test_algorithm.py index 5dee8fc..8fcc419 100644 --- a/tests/util/test_algorithm.py +++ b/tests/util/test_algorithm.py @@ -2,12 +2,13 @@ import unittest from util.algorithm import * + class algorithm(unittest.TestCase): def setUp(self): - self.someData = {'a': 100, 'b': 200, 'c': [1,2,3]} - self.differentData = {'x': 20, 'y': 'bla', 'z': ['a','b']} - self.moreData = {'n': 100} - self.overlapData = {'a': 200, 'c': [1,2,4]} + self.someData = {"a": 100, "b": 200, "c": [1, 2, 3]} + self.differentData = {"x": 20, "y": "bla", "z": ["a", "b"]} + self.moreData = {"n": 100} + self.overlapData = {"a": 200, "c": [1, 2, 4]} def test_merge_with_empty(self): self.assertEqual(self.someData, merge(self.someData, {})) @@ -37,4 +38,5 @@ class algorithm(unittest.TestCase): for k in self.overlapData: self.assertEqual(result[k], self.overlapData[k]) + # vim: tabstop=8 expandtab shiftwidth=4 softtabstop=4 diff --git a/tests/util/test_cli.py b/tests/util/test_cli.py index 5e2de98..0e4bd5c 100644 --- a/tests/util/test_cli.py +++ b/tests/util/test_cli.py @@ -2,13 +2,14 @@ import unittest import util.cli + class cli(unittest.TestCase): def setUp(self): - self.nonExistentCommand = 'i-do-not-exist' - self.validCommand = 'echo test' - self.validCommandOutput = 'test\n' - self.utfCommand = 'echo ÖPmŧß' - self.utfCommandOutput = 'ÖPmŧß\n' + self.nonExistentCommand = "i-do-not-exist" + self.validCommand = "echo test" + self.validCommandOutput = "test\n" + self.utfCommand = "echo ÖPmŧß" + self.utfCommandOutput = "ÖPmŧß\n" def test_valid_command(self): rv = util.cli.execute(self.validCommand) @@ -24,16 +25,19 @@ class cli(unittest.TestCase): def test_command_exit_code(self): with self.assertRaises(RuntimeError): - util.cli.execute('cat {}'.format(self.nonExistentCommand)) + util.cli.execute("cat {}".format(self.nonExistentCommand)) def test_command_exit_code_no_error(self): try: - util.cli.execute('cat {}'.format(self.nonExistentCommand), ignore_errors=True) + util.cli.execute( + "cat {}".format(self.nonExistentCommand), ignore_errors=True + ) except Exception: - self.fail('exception was thrown') + self.fail("exception was thrown") def test_async(self): rv = util.cli.execute(self.validCommand, wait=False) - self.assertEqual('', rv) + self.assertEqual("", rv) + # vim: tabstop=8 expandtab shiftwidth=4 softtabstop=4 diff --git a/tests/util/test_format.py b/tests/util/test_format.py index d170ae6..e50cf00 100644 --- a/tests/util/test_format.py +++ b/tests/util/test_format.py @@ -2,11 +2,12 @@ import unittest from util.format import * + class format(unittest.TestCase): def test_int_from_string(self): - self.assertEqual(100, asint('100')) - self.assertEqual(-100, asint('-100')) - self.assertEqual(0, asint('0')) + self.assertEqual(100, asint("100")) + self.assertEqual(-100, asint("-100")) + self.assertEqual(0, asint("0")) def test_int_from_none(self): self.assertEqual(0, asint(None)) @@ -27,73 +28,76 @@ class format(unittest.TestCase): self.assertEqual(100, asint(200, maximum=100)) def test_true_from_str(self): - self.assertTrue(asbool('true')) + self.assertTrue(asbool("true")) self.assertTrue(asbool(True)) - self.assertTrue(asbool('t')) - self.assertTrue(asbool('1')) - self.assertTrue(asbool('yes')) - self.assertTrue(asbool('y')) - self.assertTrue(asbool('on')) + self.assertTrue(asbool("t")) + self.assertTrue(asbool("1")) + self.assertTrue(asbool("yes")) + self.assertTrue(asbool("y")) + self.assertTrue(asbool("on")) def test_false_from_str(self): - self.assertFalse(asbool('false')) + self.assertFalse(asbool("false")) self.assertFalse(asbool(False)) - self.assertFalse(asbool('f')) - self.assertFalse(asbool('0')) - self.assertFalse(asbool('no')) - self.assertFalse(asbool('n')) - self.assertFalse(asbool('off')) + self.assertFalse(asbool("f")) + self.assertFalse(asbool("0")) + self.assertFalse(asbool("no")) + self.assertFalse(asbool("n")) + self.assertFalse(asbool("off")) self.assertFalse(asbool(None)) def test_list_from_None(self): self.assertEqual([], aslist(None)) def test_list_from_list(self): - self.assertEqual([1,2,3], aslist([1,2,3])) + self.assertEqual([1, 2, 3], aslist([1, 2, 3])) def test_list_from_str(self): - self.assertEqual(['12', '13', '14'], aslist('12,13,14')) + self.assertEqual(["12", "13", "14"], aslist("12,13,14")) def test_byteformat(self): - self.assertEqual('500.00B', byte(500)) - self.assertEqual('1.00KiB', byte(1024)) - self.assertEqual('1KiB', byte(1024, '{:.0f}')) - self.assertEqual('1.50KiB', byte(1024+512)) - self.assertEqual('2.50MiB', byte(1024*1024*2 + 1024*512)) - self.assertEqual('4.50GiB', byte(1024*1024*1024*4 + 1024*1024*512)) - self.assertEqual('2048.00GiB', byte(1024*1024*1024*1024*2)) + self.assertEqual("500.00B", byte(500)) + self.assertEqual("1.00KiB", byte(1024)) + self.assertEqual("1KiB", byte(1024, "{:.0f}")) + self.assertEqual("1.50KiB", byte(1024 + 512)) + self.assertEqual("2.50MiB", byte(1024 * 1024 * 2 + 1024 * 512)) + self.assertEqual("4.50GiB", byte(1024 * 1024 * 1024 * 4 + 1024 * 1024 * 512)) + self.assertEqual("2048.00GiB", byte(1024 * 1024 * 1024 * 1024 * 2)) def test_duration(self): - self.assertEqual('04:20:00', duration(4*60*60+20*60)) - self.assertEqual('04:20:00h', duration(4*60*60+20*60, unit=True)) - self.assertEqual('04:20h', duration(4*60*60+20*60, compact=True, unit=True)) + self.assertEqual("04:20:00", duration(4 * 60 * 60 + 20 * 60)) + self.assertEqual("04:20:00h", duration(4 * 60 * 60 + 20 * 60, unit=True)) + self.assertEqual( + "04:20h", duration(4 * 60 * 60 + 20 * 60, compact=True, unit=True) + ) - self.assertEqual('20:00', duration(20*60)) - self.assertEqual('20:00m', duration(20*60, unit=True)) - self.assertEqual('20:00m', duration(20*60, compact=True, unit=True)) + self.assertEqual("20:00", duration(20 * 60)) + self.assertEqual("20:00m", duration(20 * 60, unit=True)) + self.assertEqual("20:00m", duration(20 * 60, compact=True, unit=True)) - self.assertEqual('00:20', duration(20)) - self.assertEqual('00:20m', duration(20, unit=True)) - self.assertEqual('00:20m', duration(20, compact=True, unit=True)) + self.assertEqual("00:20", duration(20)) + self.assertEqual("00:20m", duration(20, unit=True)) + self.assertEqual("00:20m", duration(20, compact=True, unit=True)) - self.assertEqual('n/a', duration(-1)) + self.assertEqual("n/a", duration(-1)) def test_seconds(self): self.assertEqual(10, seconds(10)) - self.assertEqual(10, seconds('10')) + self.assertEqual(10, seconds("10")) - self.assertEqual(300, seconds('5m')) - self.assertEqual(320, seconds('5m20s')) + self.assertEqual(300, seconds("5m")) + self.assertEqual(320, seconds("5m20s")) - self.assertEqual(4*3600, seconds('4h')) - self.assertEqual(4*3600 + 5*60 + 22, seconds('4h5m22s')) + self.assertEqual(4 * 3600, seconds("4h")) + self.assertEqual(4 * 3600 + 5 * 60 + 22, seconds("4h5m22s")) - self.assertEqual(4*3600 + 5*60, seconds('4h5m')) + self.assertEqual(4 * 3600 + 5 * 60, seconds("4h5m")) def test_temperature(self): - self.assertEqual('10°C', astemperature(10)) - self.assertEqual('10°C', astemperature(10, 'metric')) - self.assertEqual('-100°F', astemperature(-100, 'imperial')) - self.assertEqual('-100°K', astemperature('-100', 'kelvin')) + self.assertEqual("10°C", astemperature(10)) + self.assertEqual("10°C", astemperature(10, "metric")) + self.assertEqual("-100°F", astemperature(-100, "imperial")) + self.assertEqual("-100°K", astemperature("-100", "kelvin")) + # vim: tabstop=8 expandtab shiftwidth=4 softtabstop=4 diff --git a/tests/util/test_location.py b/tests/util/test_location.py index 7e54ee5..5792f95 100644 --- a/tests/util/test_location.py +++ b/tests/util/test_location.py @@ -4,40 +4,48 @@ import urllib.request import util.location + class location(unittest.TestCase): def setUp(self): - patcher = unittest.mock.patch('util.location.urllib.request') + patcher = unittest.mock.patch("util.location.urllib.request") self.addCleanup(patcher.stop) self.request = patcher.start() util.location.reset() self.primary = { - 'country': 'Middle Earth', - 'longitude': '10.0', - 'latitude': '20.5', - 'ip': '127.0.0.1', + "country": "Middle Earth", + "longitude": "10.0", + "latitude": "20.5", + "ip": "127.0.0.1", } self.secondary = { - 'country_name': 'Rivia', - 'longitude': '-10.0', - 'latitude': '-23', - 'ip': '127.0.0.6', + "country_name": "Rivia", + "longitude": "-10.0", + "latitude": "-23", + "ip": "127.0.0.6", } def test_primary_provider(self): self.request.urlopen.return_value.read.return_value = json.dumps(self.primary) util.location.country() - self.assertEqual(self.primary['country'], util.location.country()) - self.assertEqual((self.primary['latitude'], self.primary['longitude']), util.location.coordinates()) - self.assertEqual(self.primary['ip'], util.location.public_ip()) + self.assertEqual(self.primary["country"], util.location.country()) + self.assertEqual( + (self.primary["latitude"], self.primary["longitude"]), + util.location.coordinates(), + ) + self.assertEqual(self.primary["ip"], util.location.public_ip()) def test_secondary_provider(self): urlopen = unittest.mock.MagicMock() urlopen.read.return_value = json.dumps(self.secondary) - self.request.urlopen.side_effect = [ RuntimeError(), urlopen ] + self.request.urlopen.side_effect = [RuntimeError(), urlopen] + + self.assertEqual(self.secondary["country_name"], util.location.country()) + self.assertEqual( + (self.secondary["latitude"], self.secondary["longitude"]), + util.location.coordinates(), + ) + self.assertEqual(self.secondary["ip"], util.location.public_ip()) - self.assertEqual(self.secondary['country_name'], util.location.country()) - self.assertEqual((self.secondary['latitude'], self.secondary['longitude']), util.location.coordinates()) - self.assertEqual(self.secondary['ip'], util.location.public_ip()) # vim: tabstop=8 expandtab shiftwidth=4 softtabstop=4 diff --git a/tests/util/test_store.py b/tests/util/test_store.py index 71cbffa..97b1a13 100644 --- a/tests/util/test_store.py +++ b/tests/util/test_store.py @@ -2,6 +2,7 @@ import unittest import util.store + class store(unittest.TestCase): def setUp(self): self.store = util.store.Store() @@ -13,14 +14,24 @@ class store(unittest.TestCase): self.someOtherValue = "anotherRandomValue" def test_get_of_unset_key(self): - self.assertEqual(None, self.store.get(self.unusedKey), 'default value expected to be None') - self.assertEqual(self.someValue, self.store.get(self.unusedKey, self.someValue), 'wrong user-provided default value returned') + self.assertEqual( + None, self.store.get(self.unusedKey), "default value expected to be None" + ) + self.assertEqual( + self.someValue, + self.store.get(self.unusedKey, self.someValue), + "wrong user-provided default value returned", + ) def test_get_of_set_key(self): self.assertNotEqual(self.someValue, None) self.store.set(self.someKey, self.someValue) - self.assertEqual(self.someValue, self.store.get(self.someKey), 'unexpected value for existing key') + self.assertEqual( + self.someValue, + self.store.get(self.someKey), + "unexpected value for existing key", + ) def test_overwrite_set(self): self.assertNotEqual(self.someValue, None) @@ -28,7 +39,11 @@ class store(unittest.TestCase): self.store.set(self.someKey, self.someValue) self.store.set(self.someKey, self.someOtherValue) - self.assertEqual(self.someOtherValue, self.store.get(self.someKey), 'unexpected value for existing key') + self.assertEqual( + self.someOtherValue, + self.store.get(self.someKey), + "unexpected value for existing key", + ) def test_unused_keys(self): self.assertNotEqual(self.someKey, self.someOtherKey) @@ -36,9 +51,12 @@ class store(unittest.TestCase): self.store.set(self.someKey, self.someValue) self.store.set(self.someOtherKey, self.someOtherValue) - self.assertEqual(sorted(self.store.unused_keys()), sorted([self.someKey, self.someOtherKey])) + self.assertEqual( + sorted(self.store.unused_keys()), sorted([self.someKey, self.someOtherKey]) + ) self.store.get(self.someKey) self.assertEqual(self.store.unused_keys(), [self.someOtherKey]) + # vim: tabstop=8 expandtab shiftwidth=4 softtabstop=4 diff --git a/util/algorithm.py b/util/algorithm.py index 67cf9d9..faa40d9 100644 --- a/util/algorithm.py +++ b/util/algorithm.py @@ -20,4 +20,5 @@ def merge(target, *args): target[key] = copy.deepcopy(value) return target + # vim: tabstop=8 expandtab shiftwidth=4 softtabstop=4 diff --git a/util/cli.py b/util/cli.py index dae8e56..5ea29f4 100644 --- a/util/cli.py +++ b/util/cli.py @@ -3,22 +3,29 @@ import shlex import subprocess import logging + def execute(cmd, wait=True, ignore_errors=False, include_stderr=False, env=None): args = shlex.split(cmd) logging.debug(cmd) try: - proc = subprocess.Popen(args, stdout=subprocess.PIPE, stderr=subprocess.STDOUT if include_stderr else subprocess.PIPE, env=env) + proc = subprocess.Popen( + args, + stdout=subprocess.PIPE, + stderr=subprocess.STDOUT if include_stderr else subprocess.PIPE, + env=env, + ) except FileNotFoundError as e: - raise RuntimeError('{} not found'.format(cmd)) + raise RuntimeError("{} not found".format(cmd)) if wait: out, _ = proc.communicate() if proc.returncode != 0: - err = '{} exited with code {}'.format(cmd, proc.returncode) + err = "{} exited with code {}".format(cmd, proc.returncode) if ignore_errors: return err raise RuntimeError(err) - return out.decode('utf-8') - return '' + return out.decode("utf-8") + return "" + # vim: tabstop=8 expandtab shiftwidth=4 softtabstop=4 diff --git a/util/format.py b/util/format.py index cd1bf27..d5dc15a 100644 --- a/util/format.py +++ b/util/format.py @@ -1,12 +1,14 @@ import re + def asbool(val): if val is None: return False if isinstance(val, bool): return val val = str(val).strip().lower() - return val in ('t', 'true', 'y', 'yes', 'on', '1') + return val in ("t", "true", "y", "yes", "on", "1") + def asint(val, minimum=None, maximum=None): if val is None: @@ -16,28 +18,33 @@ def asint(val, minimum=None, maximum=None): val = max(val, minimum if minimum else val) return val + def aslist(val): if val is None: return [] if isinstance(val, list): return val - return str(val).replace(' ', '').split(',') + return str(val).replace(" ", "").split(",") -__UNITS = { - 'metric': 'C', 'kelvin': 'K', 'imperial': 'F', - 'default': 'C' -} -def astemperature(value, unit='metric'): - return u'{}°{}'.format(int(value), __UNITS.get(unit, __UNITS['default'])) -def byte(val, fmt='{:.2f}'): - for unit in ['', 'Ki', 'Mi', 'Gi']: +__UNITS = {"metric": "C", "kelvin": "K", "imperial": "F", "default": "C"} + + +def astemperature(value, unit="metric"): + return "{}°{}".format(int(value), __UNITS.get(unit, __UNITS["default"])) + + +def byte(val, fmt="{:.2f}"): + for unit in ["", "Ki", "Mi", "Gi"]: if val < 1024.0: - return '{}{}B'.format(fmt, unit).format(val) + return "{}{}B".format(fmt, unit).format(val) val /= 1024.0 - return '{}GiB'.format(fmt).format(val*1024.0) + return "{}GiB".format(fmt).format(val * 1024.0) + + +__seconds_pattern = re.compile("(([\d\.?]+)h)?(([\d\.]+)m)?([\d\.]+)?s?") + -__seconds_pattern = re.compile('(([\d\.?]+)h)?(([\d\.]+)m)?([\d\.]+)?s?') def seconds(duration): if isinstance(duration, int) or isinstance(duration, float): return float(duration) @@ -45,29 +52,31 @@ def seconds(duration): matches = __seconds_pattern.match(duration) result = 0.0 if matches.group(2): - result += float(matches.group(2))*3600 # hours + result += float(matches.group(2)) * 3600 # hours if matches.group(4): - result += float(matches.group(4))*60 # minutes + result += float(matches.group(4)) * 60 # minutes if matches.group(5): - result += float(matches.group(5)) # seconds + result += float(matches.group(5)) # seconds return result + def duration(duration, compact=False, unit=False): duration = int(duration) if duration < 0: - return 'n/a' + return "n/a" minutes, seconds = divmod(duration, 60) hours, minutes = divmod(minutes, 60) - suf = 'm' - res = '{:02d}:{:02d}'.format(minutes, seconds) + suf = "m" + res = "{:02d}:{:02d}".format(minutes, seconds) if hours > 0: if compact: - res = '{:02d}:{:02d}'.format(hours, minutes) + res = "{:02d}:{:02d}".format(hours, minutes) else: - res = '{:02d}:{}'.format(hours, res) - suf = 'h' + res = "{:02d}:{}".format(hours, res) + suf = "h" + + return "{}{}".format(res, suf if unit else "") - return '{}{}'.format(res, suf if unit else '') # vim: tabstop=8 expandtab shiftwidth=4 softtabstop=4 diff --git a/util/graph.py b/util/graph.py index ddfd62e..b305477 100644 --- a/util/graph.py +++ b/util/graph.py @@ -1,7 +1,9 @@ -MAX_PERCENTS = 100. +MAX_PERCENTS = 100.0 + class Bar(object): """superclass""" + bars = None def __init__(self, value): @@ -12,17 +14,19 @@ class Bar(object): """ self.value = value + class HBar(Bar): """horizontal bar (1 char)""" + bars = [ - u"\u2581", - u"\u2582", - u"\u2583", - u"\u2584", - u"\u2585", - u"\u2586", - u"\u2587", - u"\u2588" + "\u2581", + "\u2582", + "\u2583", + "\u2584", + "\u2585", + "\u2586", + "\u2587", + "\u2588", ] def __init__(self, value): @@ -47,6 +51,7 @@ class HBar(Bar): return self.bars[i] return self.bars[-1] + def hbar(value): """wrapper function""" return HBar(value).get_char() @@ -54,15 +59,16 @@ def hbar(value): class VBar(Bar): """vertical bar (can be more than 1 char)""" + bars = [ - u"\u258f", - u"\u258e", - u"\u258d", - u"\u258c", - u"\u258b", - u"\u258a", - u"\u2589", - u"\u2588" + "\u258f", + "\u258e", + "\u258d", + "\u258c", + "\u258b", + "\u258a", + "\u2589", + "\u2588", ] def __init__(self, value, width=1): @@ -108,38 +114,41 @@ def vbar(value, width): """wrapper function""" return VBar(value, width).get_chars() + class BrailleGraph(object): """ graph using Braille chars scaled to passed values """ + chars = { - (0, 0): u" ", - (1, 0): u"\u2840", - (2, 0): u"\u2844", - (3, 0): u"\u2846", - (4, 0): u"\u2847", - (0, 1): u"\u2880", - (0, 2): u"\u28a0", - (0, 3): u"\u28b0", - (0, 4): u"\u28b8", - (1, 1): u"\u28c0", - (2, 1): u"\u28c4", - (3, 1): u"\u28c6", - (4, 1): u"\u28c7", - (1, 2): u"\u28e0", - (2, 2): u"\u28e4", - (3, 2): u"\u28e6", - (4, 2): u"\u28e7", - (1, 3): u"\u28f0", - (2, 3): u"\u28f4", - (3, 3): u"\u28f6", - (4, 3): u"\u28f7", - (1, 4): u"\u28f8", - (2, 4): u"\u28fc", - (3, 4): u"\u28fe", - (4, 4): u"\u28ff" + (0, 0): " ", + (1, 0): "\u2840", + (2, 0): "\u2844", + (3, 0): "\u2846", + (4, 0): "\u2847", + (0, 1): "\u2880", + (0, 2): "\u28a0", + (0, 3): "\u28b0", + (0, 4): "\u28b8", + (1, 1): "\u28c0", + (2, 1): "\u28c4", + (3, 1): "\u28c6", + (4, 1): "\u28c7", + (1, 2): "\u28e0", + (2, 2): "\u28e4", + (3, 2): "\u28e6", + (4, 2): "\u28e7", + (1, 3): "\u28f0", + (2, 3): "\u28f4", + (3, 3): "\u28f6", + (4, 3): "\u28f7", + (1, 4): "\u28f8", + (2, 4): "\u28fc", + (3, 4): "\u28fe", + (4, 4): "\u28ff", } + def __init__(self, values): """ Args: @@ -152,8 +161,7 @@ class BrailleGraph(object): if len(self.values) % 2 == 1: self.values.append(0) self.steps = self.get_steps() - self.parts = [tuple(self.steps[i:i+2]) - for i in range(len(self.steps))[::2]] + self.parts = [tuple(self.steps[i : i + 2]) for i in range(len(self.steps))[::2]] @staticmethod def get_height(value, unit): @@ -166,7 +174,7 @@ class BrailleGraph(object): unit (number): unit """ - if value < unit / 10.: + if value < unit / 10.0: return 0 elif value <= unit: return 1 @@ -184,7 +192,7 @@ class BrailleGraph(object): Return: list """ maxval = max(self.values) - unit = maxval / 4. + unit = maxval / 4.0 if unit == 0: return [0] * len(self.values) stepslist = [] @@ -203,8 +211,10 @@ class BrailleGraph(object): chars.append(BrailleGraph.chars[part]) return "".join(chars) + def braille(values): """wrapper function""" return BrailleGraph(values).get_chars() + # vim: tabstop=8 expandtab shiftwidth=4 softtabstop=4 diff --git a/util/location.py b/util/location.py index 632532a..caaee40 100644 --- a/util/location.py +++ b/util/location.py @@ -7,30 +7,32 @@ __data = {} __next = 0 __sources = [ - { - 'url': 'http://free.ipwhois.io/json/', - 'mapping': { - 'latitude': 'latitude', - 'longitude': 'longitude', - 'country': 'country', - 'ip': 'public_ip', - } + { + "url": "http://free.ipwhois.io/json/", + "mapping": { + "latitude": "latitude", + "longitude": "longitude", + "country": "country", + "ip": "public_ip", }, - { - 'url': 'http://ipapi.co/json', - 'mapping': { - 'latitude': 'latitude', - 'longitude': 'longitude', - 'country_name': 'country', - 'ip': 'public_ip', - } - } + }, + { + "url": "http://ipapi.co/json", + "mapping": { + "latitude": "latitude", + "longitude": "longitude", + "country_name": "country", + "ip": "public_ip", + }, + }, ] + def __expired(): global __next return __next <= time.time() + def __load(): global __data global __next @@ -38,14 +40,15 @@ def __load(): __data = {} for src in __sources: try: - tmp = json.loads(urllib.request.urlopen(src['url']).read()) - for k, v in src['mapping'].items(): + tmp = json.loads(urllib.request.urlopen(src["url"]).read()) + for k, v in src["mapping"].items(): __data[v] = tmp.get(k, None) - __next = time.time() + 60*60*12 # update once every 12h + __next = time.time() + 60 * 60 * 12 # update once every 12h return except Exception as e: pass - __next = time.time() + 60*30 # error - try again every 30m + __next = time.time() + 60 * 30 # error - try again every 30m + def __get(name, default=None): global __data @@ -53,17 +56,22 @@ def __get(name, default=None): __load() return __data.get(name, default) + def reset(): global __next __next = 0 + def coordinates(): - return __get('latitude'), __get('longitude') + return __get("latitude"), __get("longitude") + def country(): - return __get('country') + return __get("country") + def public_ip(): - return __get('public_ip') + return __get("public_ip") + # vim: tabstop=8 expandtab shiftwidth=4 softtabstop=4 diff --git a/util/popup.py b/util/popup.py index d526440..23f3587 100644 --- a/util/popup.py +++ b/util/popup.py @@ -10,6 +10,7 @@ except ImportError: import functools + class menu(object): def __init__(self, parent=None, leave=True): if not parent: @@ -42,13 +43,16 @@ class menu(object): self._menu.add_cascade(label=menuitem, menu=submenu.menu()) def add_menuitem(self, menuitem, callback): - self._menu.add_command(label=menuitem, command=functools.partial(self._on_click, callback)) + self._menu.add_command( + label=menuitem, command=functools.partial(self._on_click, callback) + ) def show(self, event, offset_x=0, offset_y=0): try: - self._menu.tk_popup(event['x'] + offset_x, event['y'] + offset_y) + self._menu.tk_popup(event["x"] + offset_x, event["y"] + offset_y) finally: self._menu.grab_release() self._root.mainloop() + # vim: tabstop=8 expandtab shiftwidth=4 softtabstop=4 diff --git a/util/store.py b/util/store.py index 79057af..2ae95b0 100644 --- a/util/store.py +++ b/util/store.py @@ -5,23 +5,26 @@ store interface by deriving from the Store class in this module """ + class Store(object): """Interface for storing and retrieving simple values""" + def __init__(self): super(Store, self).__init__() self._data = {} def set(self, key, value): """Set 'key' to 'value', overwriting 'key' if it exists already""" - self._data[key] = { 'value': value, 'used': False } + self._data[key] = {"value": value, "used": False} def unused_keys(self): - return [ key for key, value in self._data.items() if value['used'] == False ] + return [key for key, value in self._data.items() if value["used"] == False] def get(self, key, default=None): """Return the current value of 'key', or 'default' if 'key' is not set""" if key in self._data: - self._data[key]['used'] = True - return self._data.get(key, { 'value': default })['value'] + self._data[key]["used"] = True + return self._data.get(key, {"value": default})["value"] + # vim: tabstop=8 expandtab shiftwidth=4 softtabstop=4